Documentation
¶
Overview ¶
Package pages owns the public page tree. Every page is revisioned content with a parent and a translated slug; its public path follows from the published tree. A module page (for example "Blog") hands its whole subtree to a module instance.
Home (the root page) / ├── About /about │ └── Team /about/team └── Blog [module: blog] /blog, /blog/<anything below is the module's>
The published routes are read on every public request, so the Service keeps them in memory with the page revisions they point to (revisions never change). Publishing in this process replaces them at once; changes by other processes show up within the cache's time to live (see SetCacheTTL).
Index ¶
- Variables
- func Links(routes *router.Router, base string) router.PathFunc
- func NoLinks(string, ...any) (string, error)
- func Schema() fs.FS
- type Draft
- type Fields
- type Node
- type Page
- type Resolution
- type Revision
- type Route
- type Service
- func (s *Service) Alternates(ctx context.Context, pageID string) (map[string]string, error)
- func (s *Service) Content() *content.Revisions[Fields, Text]
- func (s *Service) Delete(ctx context.Context, id string) error
- func (s *Service) Generation() uint64
- func (s *Service) History(ctx context.Context, id string) ([]Revision, error)
- func (s *Service) Home(ctx context.Context) (string, error)
- func (s *Service) Init(ctx context.Context, titles map[string]string) error
- func (s *Service) Latest(ctx context.Context, id string) (Page, error)
- func (s *Service) ListLatest(ctx context.Context) ([]Page, error)
- func (s *Service) MountPath(ctx context.Context, module, locale string) (string, error)
- func (s *Service) MountURL(ctx context.Context, module, locale string) (string, error)
- func (s *Service) Move(ctx context.Context, id string, offset int) error
- func (s *Service) MoveTo(ctx context.Context, id, parentID string, index int, author string) (bool, error)
- func (s *Service) Planned(ctx context.Context) ([]Page, error)
- func (s *Service) Preview(ctx context.Context, locale, path, revisionID string) (Page, error)
- func (s *Service) PreviewPath(ctx context.Context, page Page, locale string) (string, error)
- func (s *Service) Publish(ctx context.Context, id, revisionID string) error
- func (s *Service) Published(ctx context.Context, route Route) (Page, error)
- func (s *Service) Purge(ctx context.Context, id string) error
- func (s *Service) Recent(ctx context.Context, limit int) ([]Page, error)
- func (s *Service) Resolve(ctx context.Context, locale, path string) (Resolution, error)
- func (s *Service) Restore(ctx context.Context, id, revisionID, author string) (Page, error)
- func (s *Service) Reviews() content.Reviewing[Fields, Text]
- func (s *Service) Revision(ctx context.Context, id, revisionID string) (Page, error)
- func (s *Service) Routes(ctx context.Context, locale string) ([]Route, error)
- func (s *Service) RunDue(ctx context.Context, now time.Time, required string) (int, error)
- func (s *Service) Save(ctx context.Context, draft Draft) (Page, error)
- func (s *Service) Schedule(ctx context.Context, id string, schedule content.Schedule) error
- func (s *Service) SetCacheTTL(ttl time.Duration)
- func (s *Service) Table(ctx context.Context) (*Table, error)
- func (s *Service) Trashed(ctx context.Context) ([]Page, error)
- func (s *Service) Tree(ctx context.Context, locale string) ([]Node, error)
- func (s *Service) Undelete(ctx context.Context, id string) error
- func (s *Service) Unpublish(ctx context.Context, id string) error
- func (s *Service) Unschedule(ctx context.Context, id string) error
- type Table
- type Text
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotFound is content.ErrNotFound: a page that does not exist, is // in the trash, or is not published where that is asked. ErrNotFound = content.ErrNotFound // ErrInvalid is a page the tree cannot take as it is; ErrSlug, // ErrParent and ErrHome say what is wrong. ErrInvalid = errors.New("invalid_page") // ErrCycle refuses to place a page below itself or below one of its own // subpages. ErrCycle = errors.New("page_cycle") // ErrHasChildren refuses to delete a page that still has subpages: they // would lose their place in the tree. ErrHasChildren = errors.New("page_has_children") // ErrModuleParent refuses subpages below a module page, whose module // owns every address below it. ErrModuleParent = errors.New("module_page_cannot_have_children") // ErrParentDeleted keeps a page in the trash while its parent page is // in the trash too, or gone. ErrParentDeleted = errors.New("page_parent_deleted") // ErrDuplicate is a published slug that a sibling page has in the same // language, or a top-level slug the site uses itself, such as the // admin's. ErrDuplicate = errors.New("duplicate_page_slug") // ErrMounted refuses to publish a module page for a module that another // published page shows already: each module instance has one place. ErrMounted = errors.New("module_already_mounted") // ErrUnknownMount is a module page for a module the site does not use. ErrUnknownMount = errors.New("unknown_module") // ErrSlug refuses a slug that is not lowercase letters, digits and // dashes, or a missing slug when none can be made from the title. ErrSlug = fmt.Errorf("%w: slug", ErrInvalid) // ErrParent refuses a page other than Home without a parent page. ErrParent = fmt.Errorf("%w: parent", ErrInvalid) // ErrHome refuses to take the home page off the site: it cannot be // unpublished, scheduled to be unpublished or deleted. ErrHome = fmt.Errorf("%w: home", ErrInvalid) )
Functions ¶
func Links ¶
Links gives the addresses of a module's routes on the page it is placed on, for links built outside its own handlers, such as in a block on another page or a search index. base is the page's MountURL: the paths are those of routes.At(base), and NoLinks while base is "".
base, err := s.pages.MountURL(ctx, s.key, locale)
...
paths := pages.Links(s.public, base)
url, _ := paths("post", "slug", "hello") // "/en/news/hello"
Types ¶
type Fields ¶
type Fields struct {
ParentID string `db:"parent_id,null"`
// Position orders the page among its siblings, lower first; siblings
// with equal positions are ordered by ID, which follows the order they
// were created in. It belongs to the page, not to a revision: Move
// changes it at once, also in the published menu. Save places a new
// page last among its siblings, and a page that changes parent last
// among its new siblings, unless Position is set to another value than
// the page has. A published page whose new parent is not published yet
// keeps its place in the published menu until it is; then it moves to
// its new place.
Position int `db:"-"`
// Module is the instance key of the mounted module, empty for content pages.
Module string `db:"module"`
}
Fields place a page in the tree.
type Node ¶
type Node struct {
Page Page
// Depth is 0 for Home, 1 for its children and so on.
Depth int
// Path is the page's path in the requested language from the latest
// slugs, such as "/about/team"; empty when the page or a page above it
// has no slug in that language.
Path string
// First and Last tell whether the page can move up or down among its
// siblings.
First bool
Last bool
}
Node is a page in the latest tree.
type Resolution ¶
type Resolution struct {
Page Page
Route Route
// Rest is the path below a module page, "/" for the page itself.
Rest string
}
Resolution is the published page behind a request path.
type Route ¶
type Route struct {
Locale string `db:"locale"`
Path string `db:"path"`
PageID string `db:"page_id"`
RevisionID string `db:"revision_id"`
ParentID string `db:"parent_id"`
Module string `db:"module"`
Position int `db:"position"`
Depth int `db:"depth"`
Title string `db:"title"`
}
Route is one published path. Module pages own every path below theirs.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service keeps the page tree: it saves, publishes and moves pages, and finds the published page behind a request path. It is safe for concurrent use.
func New ¶
func New(database *db.DB, provider locales.Provider, modules func() []string, reserved ...string) (*Service, error)
New creates the service. modules lists the instance keys that may be mounted; reserved lists top-level slugs the application uses itself.
func (*Service) Alternates ¶
Alternates maps each locale to the published path of the same page.
func (*Service) Content ¶
Content returns the revision store behind the pages, for code that needs its rules, such as which translations are complete (Spec). Changes to the tree go through the Service, which keeps the tree valid.
func (*Service) Delete ¶
Delete moves a page without children to the trash; it leaves the menu and its address at once. Home cannot be deleted.
func (*Service) Generation ¶
Generation counts the changes to the published routes in this process: publishing, unpublishing or moving a page. It only goes up, so a cache of what is made from published pages, such as the app's output cache, keeps it with what it made and makes it again once it moved on. Changes by other processes show when the cache's time to live (see SetCacheTTL) has passed, without changing it.
func (*Service) Init ¶
Init creates and publishes the Home page when it does not exist yet. titles gives the Home title per locale; "Home" is used otherwise.
func (*Service) Latest ¶
Latest returns the newest revision of a page, published or not, as the admin edits it. It returns ErrNotFound for a page that does not exist or is in the trash.
func (*Service) ListLatest ¶
ListLatest returns the latest revision of every page, newest page first; Tree returns them in tree order.
func (*Service) MountURL ¶
MountURL is the address of the page a module instance is placed on in locale, with the language prefix, such as "/en/news". Home never holds a module (Save clears it), so the address always has a path after the prefix. It is "" without an error while the instance is on no published page in locale, so modules can leave their links empty. A module gives the addresses of its routes below it with Links.
func (*Service) Move ¶
Move moves a page offset places among its siblings in the latest tree: -1 is one place up, 1 one place down; moves past the first or last place stop there. The order is not revisioned, so the published menu follows at once. Home has no siblings and does not move.
func (*Service) MoveTo ¶
func (s *Service) MoveTo(ctx context.Context, id, parentID string, index int, author string) (bool, error)
MoveTo places a page at index among the children of parentID in the latest tree, 0 being the first place; an index past the last place puts it last. author is the user who moves the page.
Below the page's current parent this is a reorder like Move: positions are not revisioned, so the published menu follows at once. Below another parent the page's address changes, so MoveTo saves a new draft revision with that parent, as choosing another parent in the editor does: the published menu keeps the page at its old place until the draft is published. MoveTo reports whether it saved a draft.
The same rules as for Save apply: a page cannot go below itself or the pages below it (ErrCycle), nor below a module page (ErrModuleParent); every page except Home needs a parent (ErrParent), and Home stays the root (ErrCycle, as every page is below it).
func (*Service) Planned ¶
Planned returns the latest revision of the pages with a planned publication change.
func (*Service) Preview ¶
Preview returns the page revision an editor previews at path in locale: a revision of the page published at path, or of a page whose revision would be at path (see PreviewPath), such as a page that was never published or whose slug changes. A revision of any other page is ErrNotFound, so a preview never shows one page's text at the address of another; so is a revision without text in locale.
func (*Service) PreviewPath ¶
PreviewPath is the path, without language prefix, at which a page revision shows in locale: below its parent's published path, with the revision's slug; "/" for the home page. ErrNotFound when the parent is not published in locale, or the revision has no text in it.
func (*Service) Publish ¶
Publish makes a revision public and rebuilds the published routes. It cancels the page's planned publication changes, like Unpublish.
func (*Service) Published ¶
Published returns the published revision a route points to, for example to search the text of published pages.
func (*Service) Recent ¶
Recent returns the latest revision of at most limit pages, the most recently changed first.
func (*Service) Resolve ¶
Resolve finds the published page for a path. Paths below a module page resolve to that page with the remainder in Rest.
func (*Service) Restore ¶
Restore copies an older revision of a page into a new latest revision by author, as if it had been saved again. It does not publish it. The page keeps its current place among its siblings, and the old revision's parent must still be a valid place.
func (*Service) Reviews ¶
Reviews is the review workflow of pages (see content.Reviewing). Publishing pages, by hand or scheduled, follows it through Publish.
func (*Service) Revision ¶
Revision returns one revision of a page, such as an older one shown in its history.
func (*Service) Routes ¶
Routes lists all published paths in a locale in tree order, for navigation: a copy, which the caller may change (see Table.Routes).
func (*Service) RunDue ¶
RunDue publishes and unpublishes the pages whose time has come, rebuilding the routes like Publish and Unpublish do; see content.Scheduler.
func (*Service) Save ¶
Save stores a new revision after checking its place in the tree. The root page stays the root; every other page needs a parent. A translation with a title and without a slug gets one made from the title, unique among the page's siblings in the latest tree.
func (*Service) Schedule ¶
Schedule plans the publication of a page revision and/or the page's unpublication (see content.Schedule).
func (*Service) SetCacheTTL ¶
SetCacheTTL sets how long the published routes are kept in memory (30 seconds by default). Publishing in this process applies at once. Zero or less disables the cache.
func (*Service) Table ¶
Table returns the published route table, the same one until the routes change (see Table), loading it when needed.
func (*Service) Trashed ¶
Trashed returns the latest revision of the pages in the trash, most recently deleted first.
func (*Service) Tree ¶
Tree returns the latest revision of every page in tree order: Home first, then each page followed by its children, siblings in menu order (by position, then by ID; see siblingOrder). Pages whose parent no longer exists follow at the end. locale chooses the slugs of Node.Path. The translations of Node.Page hold only slugs and titles; Latest loads a page in full.
func (*Service) Undelete ¶
Undelete brings a page back from the trash, at its place in the tree. Its parent must be there (ErrParentDeleted); a published page must not take a slug its siblings use now (ErrDuplicate) nor a module placed on another page meanwhile (ErrMounted).
type Table ¶
type Table struct {
// contains filtered or unexported fields
}
Table is one version of the published route table, indexed for each lookup. Publishing, unpublishing or moving a page, and the end of the cache's time to live (see SetCacheTTL), replace it with a new one, so what is made from the routes, such as a menu, can be kept alongside the Table it was made from and made again for another one. A Table never changes; nothing may change what its methods return either.
func (*Table) Alternates ¶
Alternates maps each locale to the published path of a page, as Service.Alternates does, without copying: the map is the Table's own, to read and never to change; nil for a page that is not published.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package pageadmin is the Pages section of the admin: the page tree, where editors add, move and publish pages and place modules on them, and the editor of each page, built with package editor.
|
Package pageadmin is the Pages section of the admin: the page tree, where editors add, move and publish pages and place modules on them, and the editor of each page, built with package editor. |