mirror of
https://github.com/gohugoio/hugo.git
synced 2024-12-26 15:23:04 +00:00
597e418cb0
The main motivation of this commit is to add a `page.Page` interface to replace the very file-oriented `hugolib.Page` struct. This is all a preparation step for issue #5074, "pages from other data sources". But this also fixes a set of annoying limitations, especially related to custom output formats, and shortcodes. Most notable changes: * The inner content of shortcodes using the `{{%` as the outer-most delimiter will now be sent to the content renderer, e.g. Blackfriday. This means that any markdown will partake in the global ToC and footnote context etc. * The Custom Output formats are now "fully virtualized". This removes many of the current limitations. * The taxonomy list type now has a reference to the `Page` object. This improves the taxonomy template `.Title` situation and make common template constructs much simpler. See #5074 Fixes #5763 Fixes #5758 Fixes #5090 Fixes #5204 Fixes #4695 Fixes #5607 Fixes #5707 Fixes #5719 Fixes #3113 Fixes #5706 Fixes #5767 Fixes #5723 Fixes #5769 Fixes #5770 Fixes #5771 Fixes #5759 Fixes #5776 Fixes #5777 Fixes #5778
148 lines
3.3 KiB
Go
148 lines
3.3 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 tplimpl
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/gohugoio/hugo/tpl"
|
|
)
|
|
|
|
// Currently lang, outFormat, suffix
|
|
const numTemplateVariants = 3
|
|
|
|
type shortcodeVariant struct {
|
|
|
|
// The possible variants: lang, outFormat, suffix
|
|
// gtag
|
|
// gtag.html
|
|
// gtag.no.html
|
|
// gtag.no.amp.html
|
|
// A slice of length numTemplateVariants.
|
|
variants []string
|
|
|
|
info tpl.Info
|
|
templ tpl.Template
|
|
}
|
|
|
|
type shortcodeTemplates struct {
|
|
variants []shortcodeVariant
|
|
}
|
|
|
|
func (s *shortcodeTemplates) indexOf(variants []string) int {
|
|
L:
|
|
for i, v1 := range s.variants {
|
|
for i, v2 := range v1.variants {
|
|
if v2 != variants[i] {
|
|
continue L
|
|
}
|
|
}
|
|
return i
|
|
}
|
|
return -1
|
|
}
|
|
|
|
func (s *shortcodeTemplates) fromVariants(variants tpl.TemplateVariants) (shortcodeVariant, bool) {
|
|
return s.fromVariantsSlice([]string{
|
|
variants.Language,
|
|
strings.ToLower(variants.OutputFormat.Name),
|
|
variants.OutputFormat.MediaType.Suffix(),
|
|
})
|
|
}
|
|
|
|
// Get the most specific template given a full name, e.g gtag.no.amp.html.
|
|
func (s *shortcodeTemplates) fromName(name string) (shortcodeVariant, bool) {
|
|
return s.fromVariantsSlice(templateVariants(name))
|
|
}
|
|
|
|
func (s *shortcodeTemplates) fromVariantsSlice(variants []string) (shortcodeVariant, bool) {
|
|
var (
|
|
bestMatch shortcodeVariant
|
|
bestMatchWeight int
|
|
)
|
|
|
|
for _, variant := range s.variants {
|
|
w := s.compareVariants(variants, variant.variants)
|
|
if bestMatchWeight == 0 || w > bestMatchWeight {
|
|
bestMatch = variant
|
|
bestMatchWeight = w
|
|
}
|
|
}
|
|
|
|
return bestMatch, true
|
|
}
|
|
|
|
// calculate a weight for two string slices of same lenght.
|
|
// higher value means "better match".
|
|
func (s *shortcodeTemplates) compareVariants(a, b []string) int {
|
|
|
|
weight := 0
|
|
for i, av := range a {
|
|
bv := b[i]
|
|
if av == bv {
|
|
weight++
|
|
} else {
|
|
weight--
|
|
}
|
|
}
|
|
return weight
|
|
}
|
|
|
|
func templateVariants(name string) []string {
|
|
_, variants := templateNameAndVariants(name)
|
|
return variants
|
|
}
|
|
|
|
func templateNameAndVariants(name string) (string, []string) {
|
|
|
|
variants := make([]string, numTemplateVariants)
|
|
|
|
parts := strings.Split(name, ".")
|
|
|
|
if len(parts) <= 1 {
|
|
// No variants.
|
|
return name, variants
|
|
}
|
|
|
|
name = parts[0]
|
|
parts = parts[1:]
|
|
lp := len(parts)
|
|
start := len(variants) - lp
|
|
|
|
for i, j := start, 0; i < len(variants); i, j = i+1, j+1 {
|
|
variants[i] = parts[j]
|
|
}
|
|
|
|
if lp > 1 && lp < len(variants) {
|
|
for i := lp - 1; i > 0; i-- {
|
|
variants[i-1] = variants[i]
|
|
}
|
|
}
|
|
|
|
if lp == 1 {
|
|
// Suffix only. Duplicate it into the output format field to
|
|
// make HTML win over AMP.
|
|
variants[len(variants)-2] = variants[len(variants)-1]
|
|
}
|
|
|
|
return name, variants
|
|
}
|
|
|
|
func isShortcode(name string) bool {
|
|
return strings.Contains(name, "shortcodes/")
|
|
}
|
|
|
|
func isInternal(name string) bool {
|
|
return strings.HasPrefix(name, "_internal/")
|
|
}
|