mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
eada236f87
This commit introduces a new data structure to store pages and their resources. This data structure is backed by radix trees. This simplies tree operations, makes all pages a bundle, and paves the way for #6310. It also solves a set of annoying issues (see list below). Not a motivation behind this, but this commit also makes Hugo in general a little bit faster and more memory effective (see benchmarks). Especially for partial rebuilds on content edits, but also when taxonomies is in use. ``` name old time/op new time/op delta SiteNew/Bundle_with_image/Edit-16 1.32ms ± 8% 1.00ms ± 9% -24.42% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 1.28ms ± 0% 0.94ms ± 0% -26.26% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 33.9ms ± 2% 21.8ms ± 1% -35.67% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 40.6ms ± 1% 37.7ms ± 3% -7.20% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 56.7ms ± 0% 51.7ms ± 1% -8.82% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 19.9ms ± 2% 18.3ms ± 3% -7.64% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 37.9ms ± 4% 34.0ms ± 2% -10.28% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 10.7ms ± 0% 10.6ms ± 0% -1.15% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 10.8ms ± 0% 10.7ms ± 0% -1.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 43.2ms ± 1% 39.6ms ± 1% -8.35% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 47.6ms ± 1% 47.3ms ± 0% ~ (p=0.057 n=4+4) SiteNew/Deep_content_tree-16 73.0ms ± 1% 74.2ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Many_HTML_templates-16 37.9ms ± 0% 38.1ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Page_collections-16 53.6ms ± 1% 54.7ms ± 1% +2.09% (p=0.029 n=4+4) name old alloc/op new alloc/op delta SiteNew/Bundle_with_image/Edit-16 486kB ± 0% 430kB ± 0% -11.47% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 265kB ± 0% 209kB ± 0% -21.06% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 13.6MB ± 0% 8.8MB ± 0% -34.93% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 66.5MB ± 0% 63.9MB ± 0% -3.95% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 28.8MB ± 0% 25.8MB ± 0% -10.55% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 6.16MB ± 0% 5.56MB ± 0% -9.86% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 16.9MB ± 0% 16.0MB ± 0% -5.19% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 2.28MB ± 0% 2.29MB ± 0% +0.35% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 2.07MB ± 0% 2.07MB ± 0% ~ (p=0.114 n=4+4) SiteNew/Tags_and_categories-16 14.3MB ± 0% 13.2MB ± 0% -7.30% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 69.1MB ± 0% 69.0MB ± 0% ~ (p=0.343 n=4+4) SiteNew/Deep_content_tree-16 31.3MB ± 0% 31.8MB ± 0% +1.49% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 10.8MB ± 0% 10.9MB ± 0% +1.11% (p=0.029 n=4+4) SiteNew/Page_collections-16 21.4MB ± 0% 21.6MB ± 0% +1.15% (p=0.029 n=4+4) name old allocs/op new allocs/op delta SiteNew/Bundle_with_image/Edit-16 4.74k ± 0% 3.86k ± 0% -18.57% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 4.73k ± 0% 3.85k ± 0% -18.58% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 301k ± 0% 198k ± 0% -34.14% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 389k ± 0% 373k ± 0% -4.07% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 338k ± 0% 262k ± 0% -22.63% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 102k ± 0% 88k ± 0% -13.81% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 176k ± 0% 152k ± 0% -13.32% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 273k ± 0% 245k ± 0% -10.36% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 396k ± 0% 398k ± 0% +0.39% (p=0.029 n=4+4) SiteNew/Deep_content_tree-16 317k ± 0% 325k ± 0% +2.53% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 146k ± 0% 147k ± 0% +0.98% (p=0.029 n=4+4) SiteNew/Page_collections-16 210k ± 0% 215k ± 0% +2.44% (p=0.029 n=4+4) ``` Fixes #6312 Fixes #6087 Fixes #6738 Fixes #6412 Fixes #6743 Fixes #6875 Fixes #6034 Fixes #6902 Fixes #6173 Fixes #6590
379 lines
11 KiB
Go
379 lines
11 KiB
Go
// Copyright 2019 The Hugo Authors. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package page contains the core interfaces and types for the Page resource,
|
|
// a core component in Hugo.
|
|
package page
|
|
|
|
import (
|
|
"html/template"
|
|
|
|
"github.com/bep/gitmap"
|
|
"github.com/gohugoio/hugo/config"
|
|
|
|
"github.com/gohugoio/hugo/common/hugo"
|
|
"github.com/gohugoio/hugo/common/maps"
|
|
"github.com/gohugoio/hugo/compare"
|
|
"github.com/gohugoio/hugo/hugofs/files"
|
|
|
|
"github.com/gohugoio/hugo/navigation"
|
|
"github.com/gohugoio/hugo/related"
|
|
"github.com/gohugoio/hugo/resources/resource"
|
|
"github.com/gohugoio/hugo/source"
|
|
)
|
|
|
|
// Clear clears any global package state.
|
|
func Clear() error {
|
|
spc.clear()
|
|
return nil
|
|
}
|
|
|
|
// AlternativeOutputFormatsProvider provides alternative output formats for a
|
|
// Page.
|
|
type AlternativeOutputFormatsProvider interface {
|
|
// AlternativeOutputFormats gives the alternative output formats for the
|
|
// current output.
|
|
// Note that we use the term "alternative" and not "alternate" here, as it
|
|
// does not necessarily replace the other format, it is an alternative representation.
|
|
AlternativeOutputFormats() OutputFormats
|
|
}
|
|
|
|
// AuthorProvider provides author information.
|
|
type AuthorProvider interface {
|
|
Author() Author
|
|
Authors() AuthorList
|
|
}
|
|
|
|
// ChildCareProvider provides accessors to child resources.
|
|
type ChildCareProvider interface {
|
|
Pages() Pages
|
|
|
|
// RegularPages returns a list of pages of kind 'Page'.
|
|
// In Hugo 0.57 we changed the Pages method so it returns all page
|
|
// kinds, even sections. If you want the old behaviour, you can
|
|
// use RegularPages.
|
|
RegularPages() Pages
|
|
|
|
Resources() resource.Resources
|
|
}
|
|
|
|
// ContentProvider provides the content related values for a Page.
|
|
type ContentProvider interface {
|
|
Content() (interface{}, error)
|
|
Plain() string
|
|
PlainWords() []string
|
|
Summary() template.HTML
|
|
Truncated() bool
|
|
FuzzyWordCount() int
|
|
WordCount() int
|
|
ReadingTime() int
|
|
Len() int
|
|
}
|
|
|
|
// FileProvider provides the source file.
|
|
type FileProvider interface {
|
|
File() source.File
|
|
}
|
|
|
|
// GetPageProvider provides the GetPage method.
|
|
type GetPageProvider interface {
|
|
// GetPage looks up a page for the given ref.
|
|
// {{ with .GetPage "blog" }}{{ .Title }}{{ end }}
|
|
//
|
|
// This will return nil when no page could be found, and will return
|
|
// an error if the ref is ambiguous.
|
|
GetPage(ref string) (Page, error)
|
|
}
|
|
|
|
// GitInfoProvider provides Git info.
|
|
type GitInfoProvider interface {
|
|
GitInfo() *gitmap.GitInfo
|
|
}
|
|
|
|
// InSectionPositioner provides section navigation.
|
|
type InSectionPositioner interface {
|
|
NextInSection() Page
|
|
PrevInSection() Page
|
|
}
|
|
|
|
// InternalDependencies is considered an internal interface.
|
|
type InternalDependencies interface {
|
|
GetRelatedDocsHandler() *RelatedDocsHandler
|
|
}
|
|
|
|
// OutputFormatsProvider provides the OutputFormats of a Page.
|
|
type OutputFormatsProvider interface {
|
|
OutputFormats() OutputFormats
|
|
}
|
|
|
|
// Page is the core interface in Hugo.
|
|
type Page interface {
|
|
ContentProvider
|
|
TableOfContentsProvider
|
|
PageWithoutContent
|
|
}
|
|
|
|
// PageMetaProvider provides page metadata, typically provided via front matter.
|
|
type PageMetaProvider interface {
|
|
// The 4 page dates
|
|
resource.Dated
|
|
|
|
// Aliases forms the base for redirects generation.
|
|
Aliases() []string
|
|
|
|
// BundleType returns the bundle type: "leaf", "branch" or an empty string if it is none.
|
|
// See https://gohugo.io/content-management/page-bundles/
|
|
BundleType() files.ContentClass
|
|
|
|
// A configured description.
|
|
Description() string
|
|
|
|
// Whether this is a draft. Will only be true if run with the --buildDrafts (-D) flag.
|
|
Draft() bool
|
|
|
|
// IsHome returns whether this is the home page.
|
|
IsHome() bool
|
|
|
|
// Configured keywords.
|
|
Keywords() []string
|
|
|
|
// The Page Kind. One of page, home, section, taxonomy, taxonomyTerm.
|
|
Kind() string
|
|
|
|
// The configured layout to use to render this page. Typically set in front matter.
|
|
Layout() string
|
|
|
|
// The title used for links.
|
|
LinkTitle() string
|
|
|
|
// IsNode returns whether this is an item of one of the list types in Hugo,
|
|
// i.e. not a regular content
|
|
IsNode() bool
|
|
|
|
// IsPage returns whether this is a regular content
|
|
IsPage() bool
|
|
|
|
// Param looks for a param in Page and then in Site config.
|
|
Param(key interface{}) (interface{}, error)
|
|
|
|
// Path gets the relative path, including file name and extension if relevant,
|
|
// to the source of this Page. It will be relative to any content root.
|
|
Path() string
|
|
|
|
// The slug, typically defined in front matter.
|
|
Slug() string
|
|
|
|
// This page's language code. Will be the same as the site's.
|
|
Lang() string
|
|
|
|
// IsSection returns whether this is a section
|
|
IsSection() bool
|
|
|
|
// Section returns the first path element below the content root.
|
|
Section() string
|
|
|
|
// Returns a slice of sections (directories if it's a file) to this
|
|
// Page.
|
|
SectionsEntries() []string
|
|
|
|
// SectionsPath is SectionsEntries joined with a /.
|
|
SectionsPath() string
|
|
|
|
// Sitemap returns the sitemap configuration for this page.
|
|
Sitemap() config.Sitemap
|
|
|
|
// Type is a discriminator used to select layouts etc. It is typically set
|
|
// in front matter, but will fall back to the root section.
|
|
Type() string
|
|
|
|
// The configured weight, used as the first sort value in the default
|
|
// page sort if non-zero.
|
|
Weight() int
|
|
}
|
|
|
|
// PageRenderProvider provides a way for a Page to render content.
|
|
type PageRenderProvider interface {
|
|
Render(layout ...string) (template.HTML, error)
|
|
RenderString(args ...interface{}) (template.HTML, error)
|
|
}
|
|
|
|
// PageWithoutContent is the Page without any of the content methods.
|
|
type PageWithoutContent interface {
|
|
RawContentProvider
|
|
resource.Resource
|
|
PageMetaProvider
|
|
resource.LanguageProvider
|
|
|
|
// For pages backed by a file.
|
|
FileProvider
|
|
|
|
GitInfoProvider
|
|
|
|
// Output formats
|
|
OutputFormatsProvider
|
|
AlternativeOutputFormatsProvider
|
|
|
|
// Tree navigation
|
|
ChildCareProvider
|
|
TreeProvider
|
|
|
|
// Horizontal navigation
|
|
InSectionPositioner
|
|
PageRenderProvider
|
|
PaginatorProvider
|
|
Positioner
|
|
navigation.PageMenusProvider
|
|
|
|
// TODO(bep)
|
|
AuthorProvider
|
|
|
|
// Page lookups/refs
|
|
GetPageProvider
|
|
RefProvider
|
|
|
|
resource.TranslationKeyProvider
|
|
TranslationsProvider
|
|
|
|
SitesProvider
|
|
|
|
// Helper methods
|
|
ShortcodeInfoProvider
|
|
compare.Eqer
|
|
maps.Scratcher
|
|
RelatedKeywordsProvider
|
|
|
|
DeprecatedWarningPageMethods
|
|
}
|
|
|
|
// Positioner provides next/prev navigation.
|
|
type Positioner interface {
|
|
Next() Page
|
|
Prev() Page
|
|
|
|
// Deprecated: Use Prev. Will be removed in Hugo 0.57
|
|
PrevPage() Page
|
|
|
|
// Deprecated: Use Next. Will be removed in Hugo 0.57
|
|
NextPage() Page
|
|
}
|
|
|
|
// RawContentProvider provides the raw, unprocessed content of the page.
|
|
type RawContentProvider interface {
|
|
RawContent() string
|
|
}
|
|
|
|
// RefProvider provides the methods needed to create reflinks to pages.
|
|
type RefProvider interface {
|
|
Ref(argsm map[string]interface{}) (string, error)
|
|
RefFrom(argsm map[string]interface{}, source interface{}) (string, error)
|
|
RelRef(argsm map[string]interface{}) (string, error)
|
|
RelRefFrom(argsm map[string]interface{}, source interface{}) (string, error)
|
|
}
|
|
|
|
// RelatedKeywordsProvider allows a Page to be indexed.
|
|
type RelatedKeywordsProvider interface {
|
|
// Make it indexable as a related.Document
|
|
RelatedKeywords(cfg related.IndexConfig) ([]related.Keyword, error)
|
|
}
|
|
|
|
// ShortcodeInfoProvider provides info about the shortcodes in a Page.
|
|
type ShortcodeInfoProvider interface {
|
|
// HasShortcode return whether the page has a shortcode with the given name.
|
|
// This method is mainly motivated with the Hugo Docs site's need for a list
|
|
// of pages with the `todo` shortcode in it.
|
|
HasShortcode(name string) bool
|
|
}
|
|
|
|
// SitesProvider provide accessors to get sites.
|
|
type SitesProvider interface {
|
|
Site() Site
|
|
Sites() Sites
|
|
}
|
|
|
|
// TableOfContentsProvider provides the table of contents for a Page.
|
|
type TableOfContentsProvider interface {
|
|
TableOfContents() template.HTML
|
|
}
|
|
|
|
// TranslationsProvider provides access to any translations.
|
|
type TranslationsProvider interface {
|
|
|
|
// IsTranslated returns whether this content file is translated to
|
|
// other language(s).
|
|
IsTranslated() bool
|
|
|
|
// AllTranslations returns all translations, including the current Page.
|
|
AllTranslations() Pages
|
|
|
|
// Translations returns the translations excluding the current Page.
|
|
Translations() Pages
|
|
}
|
|
|
|
// TreeProvider provides section tree navigation.
|
|
type TreeProvider interface {
|
|
|
|
// IsAncestor returns whether the current page is an ancestor of the given
|
|
// Note that this method is not relevant for taxonomy lists and taxonomy terms pages.
|
|
IsAncestor(other interface{}) (bool, error)
|
|
|
|
// CurrentSection returns the page's current section or the page itself if home or a section.
|
|
// Note that this will return nil for pages that is not regular, home or section pages.
|
|
CurrentSection() Page
|
|
|
|
// IsDescendant returns whether the current page is a descendant of the given
|
|
// Note that this method is not relevant for taxonomy lists and taxonomy terms pages.
|
|
IsDescendant(other interface{}) (bool, error)
|
|
|
|
// FirstSection returns the section on level 1 below home, e.g. "/docs".
|
|
// For the home page, this will return itself.
|
|
FirstSection() Page
|
|
|
|
// InSection returns whether the given page is in the current section.
|
|
// Note that this will always return false for pages that are
|
|
// not either regular, home or section pages.
|
|
InSection(other interface{}) (bool, error)
|
|
|
|
// Parent returns a section's parent section or a page's section.
|
|
// To get a section's subsections, see Page's Sections method.
|
|
Parent() Page
|
|
|
|
// Sections returns this section's subsections, if any.
|
|
// Note that for non-sections, this method will always return an empty list.
|
|
Sections() Pages
|
|
|
|
// Page returns a reference to the Page itself, kept here mostly
|
|
// for legacy reasons.
|
|
Page() Page
|
|
}
|
|
|
|
// DeprecatedWarningPageMethods lists deprecated Page methods that will trigger
|
|
// a WARNING if invoked.
|
|
// This was added in Hugo 0.55.
|
|
type DeprecatedWarningPageMethods interface {
|
|
source.FileWithoutOverlap
|
|
DeprecatedWarningPageMethods1
|
|
}
|
|
|
|
type DeprecatedWarningPageMethods1 interface {
|
|
IsDraft() bool
|
|
Hugo() hugo.Info
|
|
LanguagePrefix() string
|
|
GetParam(key string) interface{}
|
|
RSSLink() template.URL
|
|
URL() string
|
|
}
|
|
|
|
// Move here to trigger ERROR instead of WARNING.
|
|
// TODO(bep) create wrappers and put into the Page once it has some methods.
|
|
type DeprecatedErrorPageMethods interface {
|
|
}
|