github.com/linchen2chris/hugo@v0.0.0-20230307053224-cec209389705/resources/page/page.go (about) 1 // Copyright 2019 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 // Package page contains the core interfaces and types for the Page resource, 15 // a core component in Hugo. 16 package page 17 18 import ( 19 "context" 20 "html/template" 21 22 "github.com/gohugoio/hugo/identity" 23 "github.com/gohugoio/hugo/markup/converter" 24 "github.com/gohugoio/hugo/markup/tableofcontents" 25 26 "github.com/gohugoio/hugo/config" 27 "github.com/gohugoio/hugo/tpl" 28 29 "github.com/gohugoio/hugo/common/maps" 30 "github.com/gohugoio/hugo/compare" 31 "github.com/gohugoio/hugo/hugofs/files" 32 33 "github.com/gohugoio/hugo/navigation" 34 "github.com/gohugoio/hugo/related" 35 "github.com/gohugoio/hugo/resources/resource" 36 "github.com/gohugoio/hugo/source" 37 ) 38 39 // Clear clears any global package state. 40 func Clear() error { 41 spc.clear() 42 return nil 43 } 44 45 // AlternativeOutputFormatsProvider provides alternative output formats for a 46 // Page. 47 type AlternativeOutputFormatsProvider interface { 48 // AlternativeOutputFormats gives the alternative output formats for the 49 // current output. 50 // Note that we use the term "alternative" and not "alternate" here, as it 51 // does not necessarily replace the other format, it is an alternative representation. 52 AlternativeOutputFormats() OutputFormats 53 } 54 55 // AuthorProvider provides author information. 56 type AuthorProvider interface { 57 // Deprecated. 58 Author() Author 59 // Deprecated. 60 Authors() AuthorList 61 } 62 63 // ChildCareProvider provides accessors to child resources. 64 type ChildCareProvider interface { 65 // Pages returns a list of pages of all kinds. 66 Pages() Pages 67 68 // RegularPages returns a list of pages of kind 'Page'. 69 RegularPages() Pages 70 71 // RegularPagesRecursive returns all regular pages below the current 72 // section. 73 RegularPagesRecursive() Pages 74 75 // Resources returns a list of all resources. 76 Resources() resource.Resources 77 } 78 79 // ContentProvider provides the content related values for a Page. 80 type ContentProvider interface { 81 Content(context.Context) (any, error) 82 83 // Plain returns the Page Content stripped of HTML markup. 84 Plain(context.Context) string 85 86 // PlainWords returns a string slice from splitting Plain using https://pkg.go.dev/strings#Fields. 87 PlainWords(context.Context) []string 88 89 // Summary returns a generated summary of the content. 90 // The breakpoint can be set manually by inserting a summary separator in the source file. 91 Summary(context.Context) template.HTML 92 93 // Truncated returns whether the Summary is truncated or not. 94 Truncated(context.Context) bool 95 96 // FuzzyWordCount returns the approximate number of words in the content. 97 FuzzyWordCount(context.Context) int 98 99 // WordCount returns the number of words in the content. 100 WordCount(context.Context) int 101 102 // ReadingTime returns the reading time based on the length of plain text. 103 ReadingTime(context.Context) int 104 105 // Len returns the length of the content. 106 // This is for internal use only. 107 Len(context.Context) int 108 } 109 110 // ContentRenderer provides the content rendering methods for some content. 111 type ContentRenderer interface { 112 // ParseAndRenderContent renders the given content. 113 // For internal use only. 114 ParseAndRenderContent(ctx context.Context, content []byte, enableTOC bool) (converter.ResultRender, error) 115 // For internal use only. 116 ParseContent(ctx context.Context, content []byte) (converter.ResultParse, bool, error) 117 // For internal use only. 118 RenderContent(ctx context.Context, content []byte, doc any) (converter.ResultRender, bool, error) 119 } 120 121 // FileProvider provides the source file. 122 type FileProvider interface { 123 // File returns the source file for this Page, 124 // or a zero File if this Page is not backed by a file. 125 File() source.File 126 } 127 128 // GetPageProvider provides the GetPage method. 129 type GetPageProvider interface { 130 // GetPage looks up a page for the given ref. 131 // {{ with .GetPage "blog" }}{{ .Title }}{{ end }} 132 // 133 // This will return nil when no page could be found, and will return 134 // an error if the ref is ambiguous. 135 GetPage(ref string) (Page, error) 136 137 // GetPageWithTemplateInfo is for internal use only. 138 GetPageWithTemplateInfo(info tpl.Info, ref string) (Page, error) 139 } 140 141 // GitInfoProvider provides Git info. 142 type GitInfoProvider interface { 143 // GitInfo returns the Git info for this object. 144 GitInfo() source.GitInfo 145 // CodeOwners returns the code owners for this object. 146 CodeOwners() []string 147 } 148 149 // InSectionPositioner provides section navigation. 150 type InSectionPositioner interface { 151 // NextInSection returns the next page in the same section. 152 NextInSection() Page 153 // PrevInSection returns the previous page in the same section. 154 PrevInSection() Page 155 } 156 157 // InternalDependencies is considered an internal interface. 158 type InternalDependencies interface { 159 // GetRelatedDocsHandler is for internal use only. 160 GetRelatedDocsHandler() *RelatedDocsHandler 161 } 162 163 // OutputFormatsProvider provides the OutputFormats of a Page. 164 type OutputFormatsProvider interface { 165 // OutputFormats returns the OutputFormats for this Page. 166 OutputFormats() OutputFormats 167 } 168 169 // Page is the core interface in Hugo. 170 type Page interface { 171 ContentProvider 172 TableOfContentsProvider 173 PageWithoutContent 174 } 175 176 type PageFragment interface { 177 resource.ResourceLinksProvider 178 resource.ResourceMetaProvider 179 } 180 181 // PageMetaProvider provides page metadata, typically provided via front matter. 182 type PageMetaProvider interface { 183 // The 4 page dates 184 resource.Dated 185 186 // Aliases forms the base for redirects generation. 187 Aliases() []string 188 189 // BundleType returns the bundle type: `leaf`, `branch` or an empty string. 190 BundleType() files.ContentClass 191 192 // A configured description. 193 Description() string 194 195 // Whether this is a draft. Will only be true if run with the --buildDrafts (-D) flag. 196 Draft() bool 197 198 // IsHome returns whether this is the home page. 199 IsHome() bool 200 201 // Configured keywords. 202 Keywords() []string 203 204 // The Page Kind. One of page, home, section, taxonomy, term. 205 Kind() string 206 207 // The configured layout to use to render this page. Typically set in front matter. 208 Layout() string 209 210 // The title used for links. 211 LinkTitle() string 212 213 // IsNode returns whether this is an item of one of the list types in Hugo, 214 // i.e. not a regular content 215 IsNode() bool 216 217 // IsPage returns whether this is a regular content 218 IsPage() bool 219 220 // Param looks for a param in Page and then in Site config. 221 Param(key any) (any, error) 222 223 // Path gets the relative path, including file name and extension if relevant, 224 // to the source of this Page. It will be relative to any content root. 225 Path() string 226 227 // This is just a temporary bridge method. Use Path in templates. 228 // Pathc is for internal usage only. 229 Pathc() string 230 231 // The slug, typically defined in front matter. 232 Slug() string 233 234 // This page's language code. Will be the same as the site's. 235 Lang() string 236 237 // IsSection returns whether this is a section 238 IsSection() bool 239 240 // Section returns the first path element below the content root. 241 Section() string 242 243 // Returns a slice of sections (directories if it's a file) to this 244 // Page. 245 SectionsEntries() []string 246 247 // SectionsPath is SectionsEntries joined with a /. 248 SectionsPath() string 249 250 // Sitemap returns the sitemap configuration for this page. 251 // This is for internal use only. 252 Sitemap() config.Sitemap 253 254 // Type is a discriminator used to select layouts etc. It is typically set 255 // in front matter, but will fall back to the root section. 256 Type() string 257 258 // The configured weight, used as the first sort value in the default 259 // page sort if non-zero. 260 Weight() int 261 } 262 263 // PageRenderProvider provides a way for a Page to render content. 264 type PageRenderProvider interface { 265 // Render renders the given layout with this Page as context. 266 Render(ctx context.Context, layout ...string) (template.HTML, error) 267 // RenderString renders the first value in args with tPaginatorhe content renderer defined 268 // for this Page. 269 // It takes an optional map as a second argument: 270 // 271 // display (“inline”): 272 // - inline or block. If inline (default), surrounding <p></p> on short snippets will be trimmed. 273 // markup (defaults to the Page’s markup) 274 RenderString(ctx context.Context, args ...any) (template.HTML, error) 275 } 276 277 // PageWithoutContent is the Page without any of the content methods. 278 type PageWithoutContent interface { 279 RawContentProvider 280 resource.Resource 281 PageMetaProvider 282 resource.LanguageProvider 283 284 // For pages backed by a file. 285 FileProvider 286 287 GitInfoProvider 288 289 // Output formats 290 OutputFormatsProvider 291 AlternativeOutputFormatsProvider 292 293 // Tree navigation 294 ChildCareProvider 295 TreeProvider 296 297 // Horizontal navigation 298 InSectionPositioner 299 PageRenderProvider 300 PaginatorProvider 301 Positioner 302 navigation.PageMenusProvider 303 304 // TODO(bep) 305 AuthorProvider 306 307 // Page lookups/refs 308 GetPageProvider 309 RefProvider 310 311 resource.TranslationKeyProvider 312 TranslationsProvider 313 314 SitesProvider 315 316 // Helper methods 317 ShortcodeInfoProvider 318 compare.Eqer 319 320 // Scratch returns a Scratch that can be used to store temporary state. 321 // Note that this Scratch gets reset on server rebuilds. See Store() for a variant that survives. 322 maps.Scratcher 323 324 // Store returns a Scratch that can be used to store temporary state. 325 // In contrast to Scratch(), this Scratch is not reset on server rebuilds. 326 Store() *maps.Scratch 327 328 RelatedKeywordsProvider 329 330 // GetTerms gets the terms of a given taxonomy, 331 // e.g. GetTerms("categories") 332 GetTerms(taxonomy string) Pages 333 334 // Used in change/dependency tracking. 335 identity.Provider 336 337 // Headings returns the headings for this page when a filter is set. 338 // This is currently only triggered with the Related content feature 339 // and the "fragments" type of index. 340 HeadingsFiltered(context.Context) tableofcontents.Headings 341 342 DeprecatedWarningPageMethods 343 } 344 345 // Positioner provides next/prev navigation. 346 type Positioner interface { 347 // Next points up to the next regular page (sorted by Hugo’s default sort). 348 Next() Page 349 // Prev points down to the previous regular page (sorted by Hugo’s default sort). 350 Prev() Page 351 352 // Deprecated: Use Prev. Will be removed in Hugo 0.57 353 PrevPage() Page 354 355 // Deprecated: Use Next. Will be removed in Hugo 0.57 356 NextPage() Page 357 } 358 359 // RawContentProvider provides the raw, unprocessed content of the page. 360 type RawContentProvider interface { 361 // RawContent returns the raw, unprocessed content of the page excluding any front matter. 362 RawContent() string 363 } 364 365 // RefProvider provides the methods needed to create reflinks to pages. 366 type RefProvider interface { 367 // Ref returns an absolute URl to a page. 368 Ref(argsm map[string]any) (string, error) 369 370 // RefFrom is for internal use only. 371 RefFrom(argsm map[string]any, source any) (string, error) 372 373 // RelRef returns a relative URL to a page. 374 RelRef(argsm map[string]any) (string, error) 375 376 // RefFrom is for internal use only. 377 RelRefFrom(argsm map[string]any, source any) (string, error) 378 } 379 380 // RelatedKeywordsProvider allows a Page to be indexed. 381 type RelatedKeywordsProvider interface { 382 // Make it indexable as a related.Document 383 // RelatedKeywords is meant for internal usage only. 384 RelatedKeywords(cfg related.IndexConfig) ([]related.Keyword, error) 385 } 386 387 // ShortcodeInfoProvider provides info about the shortcodes in a Page. 388 type ShortcodeInfoProvider interface { 389 // HasShortcode return whether the page has a shortcode with the given name. 390 // This method is mainly motivated with the Hugo Docs site's need for a list 391 // of pages with the `todo` shortcode in it. 392 HasShortcode(name string) bool 393 } 394 395 // SitesProvider provide accessors to get sites. 396 type SitesProvider interface { 397 // Site returns the current site. 398 Site() Site 399 // Sites returns all sites. 400 Sites() Sites 401 } 402 403 // TableOfContentsProvider provides the table of contents for a Page. 404 type TableOfContentsProvider interface { 405 // TableOfContents returns the table of contents for the page rendered as HTML. 406 TableOfContents(context.Context) template.HTML 407 408 // Fragments returns the fragments for this page. 409 Fragments(context.Context) *tableofcontents.Fragments 410 } 411 412 // TranslationsProvider provides access to any translations. 413 type TranslationsProvider interface { 414 415 // IsTranslated returns whether this content file is translated to 416 // other language(s). 417 IsTranslated() bool 418 419 // AllTranslations returns all translations, including the current Page. 420 AllTranslations() Pages 421 422 // Translations returns the translations excluding the current Page. 423 Translations() Pages 424 } 425 426 // TreeProvider provides section tree navigation. 427 type TreeProvider interface { 428 429 // IsAncestor returns whether the current page is an ancestor of other. 430 // Note that this method is not relevant for taxonomy lists and taxonomy terms pages. 431 IsAncestor(other any) (bool, error) 432 433 // CurrentSection returns the page's current section or the page itself if home or a section. 434 // Note that this will return nil for pages that is not regular, home or section pages. 435 CurrentSection() Page 436 437 // IsDescendant returns whether the current page is a descendant of other. 438 // Note that this method is not relevant for taxonomy lists and taxonomy terms pages. 439 IsDescendant(other any) (bool, error) 440 441 // FirstSection returns the section on level 1 below home, e.g. "/docs". 442 // For the home page, this will return itself. 443 FirstSection() Page 444 445 // InSection returns whether other is in the current section. 446 // Note that this will always return false for pages that are 447 // not either regular, home or section pages. 448 InSection(other any) (bool, error) 449 450 // Parent returns a section's parent section or a page's section. 451 // To get a section's subsections, see Page's Sections method. 452 Parent() Page 453 454 // Ancestors returns the ancestors of each page 455 Ancestors() Pages 456 457 // Sections returns this section's subsections, if any. 458 // Note that for non-sections, this method will always return an empty list. 459 Sections() Pages 460 461 // Page returns a reference to the Page itself, kept here mostly 462 // for legacy reasons. 463 Page() Page 464 } 465 466 // DeprecatedWarningPageMethods lists deprecated Page methods that will trigger 467 // a WARNING if invoked. 468 // This was added in Hugo 0.55. 469 type DeprecatedWarningPageMethods any // This was emptied in Hugo 0.93.0. 470 471 // Move here to trigger ERROR instead of WARNING. 472 // TODO(bep) create wrappers and put into the Page once it has some methods. 473 type DeprecatedErrorPageMethods any 474 475 // PageWithContext is a Page with a context.Context. 476 type PageWithContext struct { 477 Page 478 Ctx context.Context 479 } 480 481 func (p PageWithContext) Content() (any, error) { 482 return p.Page.Content(p.Ctx) 483 } 484 485 func (p PageWithContext) Plain() string { 486 return p.Page.Plain(p.Ctx) 487 } 488 489 func (p PageWithContext) PlainWords() []string { 490 return p.Page.PlainWords(p.Ctx) 491 } 492 493 func (p PageWithContext) Summary() template.HTML { 494 return p.Page.Summary(p.Ctx) 495 } 496 497 func (p PageWithContext) Truncated() bool { 498 return p.Page.Truncated(p.Ctx) 499 } 500 501 func (p PageWithContext) FuzzyWordCount() int { 502 return p.Page.FuzzyWordCount(p.Ctx) 503 } 504 505 func (p PageWithContext) WordCount() int { 506 return p.Page.WordCount(p.Ctx) 507 } 508 509 func (p PageWithContext) ReadingTime() int { 510 return p.Page.ReadingTime(p.Ctx) 511 } 512 513 func (p PageWithContext) Len() int { 514 return p.Page.Len(p.Ctx) 515 }