hide drafts and future-dated bundles; reveal them with -dev on
A draft is now not served at all, and neither is a bundle whose date has not arrived. The filter sits in `Site.Lookup` and `Site.Run`, which is every path to a bundle — so the files inside an unpublished bundle inherit its status for free, which is what ADR-0024 asks for and what the asset route was written to allow. A test asserts the 404 for the bundle *and* its picture, and that nothing leaks into a listing, a feed or a sitemap. The clock is read per request rather than at startup, so a scheduled post appears exactly when its date arrives with nothing to restart and nothing to invalidate. That first clock read created internal/content/clock.go, which is the only place `verify.sh` allows `time.Now` — a render that depends on the time is worth being able to find. `-dev on` reveals both and reparses the theme before each render. Deliberately not a bare boolean flag: turning unpublished work into public work should not be one fumbled argument away. A reload that fails to parse leaves the working template set in place, so a typo shows an error rather than replacing a good set with a broken one.
This commit is contained in:
@@ -49,6 +49,9 @@ type Bundle struct {
|
||||
// Route is the path this bundle is served at: its Key, unless a slug renamed the last segment. Set by
|
||||
// NewSite, which is the only place that can see whether every variant agrees.
|
||||
Route string
|
||||
// Draft is true when frontmatter says so. A draft is not served at all until `-dev` reveals it, and
|
||||
// neither are the files inside its bundle (ADR-0024).
|
||||
Draft bool
|
||||
// Order is this bundle's position in the series it is nested under, zero when frontmatter omits it.
|
||||
// The convention is sparse (10, 20, 30), so zero is not a position: an unordered member sorts by name
|
||||
// after every ordered one (ADR-0033).
|
||||
@@ -159,6 +162,8 @@ func Parse(name string, data []byte) (Bundle, error) {
|
||||
delete(b.Extra, "tags")
|
||||
b.Order = asInt(b.Extra["order"])
|
||||
delete(b.Extra, "order")
|
||||
b.Draft, _ = b.Extra["draft"].(bool)
|
||||
delete(b.Extra, "draft")
|
||||
if slug, isStr := b.Extra["slug"].(string); isStr {
|
||||
// One segment, normalised like every other identifier (ADR-0015). Slashes would let a slug move the
|
||||
// bundle to another section, which is a move, not a rename.
|
||||
@@ -169,6 +174,15 @@ func Parse(name string, data []byte) (Bundle, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Published reports whether a bundle is visible to a reader at the given moment.
|
||||
//
|
||||
// Two ways not to be: marked a draft, or dated in the future. The second is the same rule seen from the other
|
||||
// side — a bundle becomes public exactly when its own date arrives, with nothing to run and nothing to
|
||||
// invalidate (content-model.md).
|
||||
func (b Bundle) Published(at time.Time) bool {
|
||||
return !b.Draft && !b.Date.After(at)
|
||||
}
|
||||
|
||||
// Assets is the directory holding a bundle's own local files, and false for a bundle that has none.
|
||||
//
|
||||
// Only a directory bundle has one. A single-file bundle's neighbours belong to its section rather than to it,
|
||||
|
||||
Reference in New Issue
Block a user