diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2019-01-02 12:33:26 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2019-03-23 18:51:22 +0100 |
commit | 597e418cb02883418f2cebb41400e8e61413f651 (patch) | |
tree | 177ad9c540b2583b6dab138c9f0490d28989c7f7 /tpl | |
parent | 44f5c1c14cb1f42cc5f01739c289e9cfc83602af (diff) |
Make Page an interface
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
Diffstat (limited to 'tpl')
-rw-r--r-- | tpl/collections/apply_test.go | 6 | ||||
-rw-r--r-- | tpl/collections/collections.go | 8 | ||||
-rw-r--r-- | tpl/collections/collections_test.go | 38 | ||||
-rw-r--r-- | tpl/template.go | 43 | ||||
-rw-r--r-- | tpl/template_info.go | 35 | ||||
-rw-r--r-- | tpl/tplimpl/ace.go | 15 | ||||
-rw-r--r-- | tpl/tplimpl/embedded/generate/generate.go | 4 | ||||
-rw-r--r-- | tpl/tplimpl/embedded/templates.autogen.go | 24 | ||||
-rw-r--r-- | tpl/tplimpl/embedded/templates/_default/rss.xml | 8 | ||||
-rw-r--r-- | tpl/tplimpl/embedded/templates/_default/sitemap.xml | 5 | ||||
-rw-r--r-- | tpl/tplimpl/embedded/templates/_default/sitemapindex.xml | 1 | ||||
-rw-r--r-- | tpl/tplimpl/embedded/templates/disqus.html | 2 | ||||
-rw-r--r-- | tpl/tplimpl/shortcodes.go | 148 | ||||
-rw-r--r-- | tpl/tplimpl/shortcodes_test.go | 94 | ||||
-rw-r--r-- | tpl/tplimpl/template.go | 201 | ||||
-rw-r--r-- | tpl/tplimpl/templateFuncster.go | 46 | ||||
-rw-r--r-- | tpl/tplimpl/template_ast_transformers.go | 132 | ||||
-rw-r--r-- | tpl/tplimpl/template_ast_transformers_test.go | 66 | ||||
-rw-r--r-- | tpl/tplimpl/template_funcs_test.go | 20 | ||||
-rw-r--r-- | tpl/tplimpl/template_info_test.go (renamed from tpl/tplimpl/template_test.go) | 48 |
20 files changed, 739 insertions, 205 deletions
diff --git a/tpl/collections/apply_test.go b/tpl/collections/apply_test.go index 0878844b2..edec3da18 100644 --- a/tpl/collections/apply_test.go +++ b/tpl/collections/apply_test.go @@ -1,4 +1,4 @@ -// Copyright 2017 The Hugo Authors. All rights reserved. +// 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. @@ -29,6 +29,10 @@ func (templateFinder) Lookup(name string) (tpl.Template, bool) { return nil, false } +func (templateFinder) LookupVariant(name string, variants tpl.TemplateVariants) (tpl.Template, bool, bool) { + return nil, false, false +} + func (templateFinder) GetFuncs() map[string]interface{} { return map[string]interface{}{ "print": fmt.Sprint, diff --git a/tpl/collections/collections.go b/tpl/collections/collections.go index bad65369f..92a61e575 100644 --- a/tpl/collections/collections.go +++ b/tpl/collections/collections.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Hugo Authors. All rights reserved. +// 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. @@ -329,13 +329,17 @@ func (ns *Namespace) Group(key interface{}, items interface{}) (interface{}, err return nil, errors.New("nil is not a valid key to group by") } + if g, ok := items.(collections.Grouper); ok { + return g.Group(key, items) + } + in := newSliceElement(items) if g, ok := in.(collections.Grouper); ok { return g.Group(key, items) } - return nil, fmt.Errorf("grouping not supported for type %T", items) + return nil, fmt.Errorf("grouping not supported for type %T %T", items, in) } // IsSet returns whether a given array, channel, slice, or map has a key diff --git a/tpl/collections/collections_test.go b/tpl/collections/collections_test.go index 0edb8299f..103aee59e 100644 --- a/tpl/collections/collections_test.go +++ b/tpl/collections/collections_test.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Hugo Authors. All rights reserved. +// 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. @@ -311,16 +311,16 @@ func TestIn(t *testing.T) { } } -type page struct { +type testPage struct { Title string } -func (p page) String() string { +func (p testPage) String() string { return "p-" + p.Title } -type pagesPtr []*page -type pagesVals []page +type pagesPtr []*testPage +type pagesVals []testPage func TestIntersect(t *testing.T) { t.Parallel() @@ -328,15 +328,15 @@ func TestIntersect(t *testing.T) { ns := New(&deps.Deps{}) var ( - p1 = &page{"A"} - p2 = &page{"B"} - p3 = &page{"C"} - p4 = &page{"D"} - - p1v = page{"A"} - p2v = page{"B"} - p3v = page{"C"} - p4v = page{"D"} + p1 = &testPage{"A"} + p2 = &testPage{"B"} + p3 = &testPage{"C"} + p4 = &testPage{"D"} + + p1v = testPage{"A"} + p2v = testPage{"B"} + p3v = testPage{"C"} + p4v = testPage{"D"} ) for i, test := range []struct { @@ -672,14 +672,14 @@ func TestUnion(t *testing.T) { ns := New(&deps.Deps{}) var ( - p1 = &page{"A"} - p2 = &page{"B"} + p1 = &testPage{"A"} + p2 = &testPage{"B"} // p3 = &page{"C"} - p4 = &page{"D"} + p4 = &testPage{"D"} - p1v = page{"A"} + p1v = testPage{"A"} //p2v = page{"B"} - p3v = page{"C"} + p3v = testPage{"C"} //p4v = page{"D"} ) diff --git a/tpl/template.go b/tpl/template.go index 3225814c0..07152166a 100644 --- a/tpl/template.go +++ b/tpl/template.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Hugo Authors. All rights reserved. +// 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. @@ -21,6 +21,8 @@ import ( "strings" "time" + "github.com/gohugoio/hugo/output" + "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/hugofs" @@ -37,7 +39,8 @@ import ( ) var ( - _ TemplateExecutor = (*TemplateAdapter)(nil) + _ TemplateExecutor = (*TemplateAdapter)(nil) + _ TemplateInfoProvider = (*TemplateAdapter)(nil) ) // TemplateHandler manages the collection of templates. @@ -53,17 +56,47 @@ type TemplateHandler interface { RebuildClone() } +// TemplateVariants describes the possible variants of a template. +// All of these may be empty. +type TemplateVariants struct { + Language string + OutputFormat output.Format +} + // TemplateFinder finds templates. type TemplateFinder interface { + TemplateLookup + TemplateLookupVariant +} + +type TemplateLookup interface { Lookup(name string) (Template, bool) } +type TemplateLookupVariant interface { + // TODO(bep) this currently only works for shortcodes. + // We may unify and expand this variant pattern to the + // other templates, but we need this now for the shortcodes to + // quickly determine if a shortcode has a template for a given + // output format. + // It returns the template, if it was found or not and if there are + // alternative representations (output format, language). + // We are currently only interested in output formats, so we should improve + // this for speed. + LookupVariant(name string, variants TemplateVariants) (Template, bool, bool) +} + // Template is the common interface between text/template and html/template. type Template interface { Execute(wr io.Writer, data interface{}) error Name() string } +// TemplateInfoProvider provides some contextual information about a template. +type TemplateInfoProvider interface { + TemplateInfo() Info +} + // TemplateParser is used to parse ad-hoc templates, e.g. in the Resource chain. type TemplateParser interface { Parse(name, tpl string) (Template, error) @@ -92,6 +125,8 @@ type TemplateAdapter struct { Template Metrics metrics.Provider + Info Info + // The filesystem where the templates are stored. Fs afero.Fs @@ -133,6 +168,10 @@ func (t *TemplateAdapter) Execute(w io.Writer, data interface{}) (execErr error) return } +func (t *TemplateAdapter) TemplateInfo() Info { + return t.Info +} + // The identifiers may be truncated in the log, e.g. // "executing "main" at <$scaled.SRelPermalin...>: can't evaluate field SRelPermalink in type *resource.Image" var identifiersRe = regexp.MustCompile("at \\<(.*?)(\\.{3})?\\>:") diff --git a/tpl/template_info.go b/tpl/template_info.go new file mode 100644 index 000000000..8568f46f0 --- /dev/null +++ b/tpl/template_info.go @@ -0,0 +1,35 @@ +// 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 tpl + +// Increments on breaking changes. +const TemplateVersion = 2 + +// Info holds some info extracted from a parsed template. +type Info struct { + + // Set for shortcode templates with any {{ .Inner }} + IsInner bool + + // Config extracted from template. + Config Config +} + +type Config struct { + Version int +} + +var DefaultConfig = Config{ + Version: TemplateVersion, +} diff --git a/tpl/tplimpl/ace.go b/tpl/tplimpl/ace.go index 6fb4ca439..7a1f849f4 100644 --- a/tpl/tplimpl/ace.go +++ b/tpl/tplimpl/ace.go @@ -1,4 +1,4 @@ -// Copyright 2017-present The Hugo Authors. All rights reserved. +// 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. @@ -14,7 +14,6 @@ package tplimpl import ( - "html/template" "path/filepath" "strings" @@ -52,15 +51,15 @@ func (t *templateHandler) addAceTemplate(name, basePath, innerPath string, baseC return err } - if err := applyTemplateTransformersToHMLTTemplate(templ); err != nil { + isShort := isShortcode(name) + + info, err := applyTemplateTransformersToHMLTTemplate(isShort, templ) + if err != nil { return err } - if strings.Contains(name, "shortcodes") { - // We need to keep track of one ot the output format's shortcode template - // without knowing the rendering context. - clone := template.Must(templ.Clone()) - t.html.t.AddParseTree(withoutExt, clone.Tree) + if isShort { + t.addShortcodeVariant(name, info, templ) } return nil diff --git a/tpl/tplimpl/embedded/generate/generate.go b/tpl/tplimpl/embedded/generate/generate.go index 76a167a99..a48e00756 100644 --- a/tpl/tplimpl/embedded/generate/generate.go +++ b/tpl/tplimpl/embedded/generate/generate.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Hugo Authors. All rights reserved. +// 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. @@ -63,7 +63,7 @@ func main() { log.Fatal(err) } - fmt.Fprint(file, `// Copyright 2018 The Hugo Authors. All rights reserved. + fmt.Fprint(file, `// 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. diff --git a/tpl/tplimpl/embedded/templates.autogen.go b/tpl/tplimpl/embedded/templates.autogen.go index ed9ba35ac..d55e5b307 100644 --- a/tpl/tplimpl/embedded/templates.autogen.go +++ b/tpl/tplimpl/embedded/templates.autogen.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Hugo Authors. All rights reserved. +// 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. @@ -19,7 +19,13 @@ package embedded // EmbeddedTemplates represents all embedded templates. var EmbeddedTemplates = [][2]string{ {`_default/robots.txt`, `User-agent: *`}, - {`_default/rss.xml`, `<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> + {`_default/rss.xml`, `{{- $pages := .Data.Pages -}} +{{- $limit := .Site.Config.Services.RSS.Limit -}} +{{- if ge $limit 1 -}} +{{- $pages = $pages | first $limit -}} +{{- end -}} +{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <channel> <title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title> <link>{{ .Permalink }}</link> @@ -33,7 +39,7 @@ var EmbeddedTemplates = [][2]string{ {{ with .OutputFormats.Get "RSS" }} {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }} {{ end }} - {{ range .Data.Pages }} + {{ range $pages }} <item> <title>{{ .Title }}</title> <link>{{ .Permalink }}</link> @@ -45,7 +51,8 @@ var EmbeddedTemplates = [][2]string{ {{ end }} </channel> </rss>`}, - {`_default/sitemap.xml`, `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" + {`_default/sitemap.xml`, `{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"> {{ range .Data.Pages }} <url> @@ -55,18 +62,19 @@ var EmbeddedTemplates = [][2]string{ <priority>{{ .Sitemap.Priority }}</priority>{{ end }}{{ if .IsTranslated }}{{ range .Translations }} <xhtml:link rel="alternate" - hreflang="{{ .Lang }}" + hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}" />{{ end }} <xhtml:link rel="alternate" - hreflang="{{ .Lang }}" + hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}" />{{ end }} </url> {{ end }} </urlset>`}, - {`_default/sitemapindex.xml`, `<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> + {`_default/sitemapindex.xml`, `{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} +<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> {{ range . }} <sitemap> <loc>{{ .SitemapAbsURL }}</loc> @@ -77,7 +85,7 @@ var EmbeddedTemplates = [][2]string{ {{ end }} </sitemapindex> `}, - {`disqus.html`, `{{- $pc := .Page.Site.Config.Privacy.Disqus -}} + {`disqus.html`, `{{- $pc := .Site.Config.Privacy.Disqus -}} {{- if not $pc.Disable -}} {{ if .Site.DisqusShortname }}<div id="disqus_thread"></div> <script type="application/javascript"> diff --git a/tpl/tplimpl/embedded/templates/_default/rss.xml b/tpl/tplimpl/embedded/templates/_default/rss.xml index abba0b28a..675ecd43c 100644 --- a/tpl/tplimpl/embedded/templates/_default/rss.xml +++ b/tpl/tplimpl/embedded/templates/_default/rss.xml @@ -1,3 +1,9 @@ +{{- $pages := .Data.Pages -}} +{{- $limit := .Site.Config.Services.RSS.Limit -}} +{{- if ge $limit 1 -}} +{{- $pages = $pages | first $limit -}} +{{- end -}} +{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <channel> <title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title> @@ -12,7 +18,7 @@ {{ with .OutputFormats.Get "RSS" }} {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }} {{ end }} - {{ range .Data.Pages }} + {{ range $pages }} <item> <title>{{ .Title }}</title> <link>{{ .Permalink }}</link> diff --git a/tpl/tplimpl/embedded/templates/_default/sitemap.xml b/tpl/tplimpl/embedded/templates/_default/sitemap.xml index e0a2b189d..f5b44c410 100644 --- a/tpl/tplimpl/embedded/templates/_default/sitemap.xml +++ b/tpl/tplimpl/embedded/templates/_default/sitemap.xml @@ -1,3 +1,4 @@ +{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"> {{ range .Data.Pages }} @@ -8,12 +9,12 @@ <priority>{{ .Sitemap.Priority }}</priority>{{ end }}{{ if .IsTranslated }}{{ range .Translations }} <xhtml:link rel="alternate" - hreflang="{{ .Lang }}" + hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}" />{{ end }} <xhtml:link rel="alternate" - hreflang="{{ .Lang }}" + hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}" />{{ end }} </url> diff --git a/tpl/tplimpl/embedded/templates/_default/sitemapindex.xml b/tpl/tplimpl/embedded/templates/_default/sitemapindex.xml index 4cd289fe9..60724c7b8 100644 --- a/tpl/tplimpl/embedded/templates/_default/sitemapindex.xml +++ b/tpl/tplimpl/embedded/templates/_default/sitemapindex.xml @@ -1,3 +1,4 @@ +{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> {{ range . }} <sitemap> diff --git a/tpl/tplimpl/embedded/templates/disqus.html b/tpl/tplimpl/embedded/templates/disqus.html index 178d84caf..ab51bb5c0 100644 --- a/tpl/tplimpl/embedded/templates/disqus.html +++ b/tpl/tplimpl/embedded/templates/disqus.html @@ -1,4 +1,4 @@ -{{- $pc := .Page.Site.Config.Privacy.Disqus -}} +{{- $pc := .Site.Config.Privacy.Disqus -}} {{- if not $pc.Disable -}} {{ if .Site.DisqusShortname }}<div id="disqus_thread"></div> <script type="application/javascript"> diff --git a/tpl/tplimpl/shortcodes.go b/tpl/tplimpl/shortcodes.go new file mode 100644 index 000000000..8577fbeed --- /dev/null +++ b/tpl/tplimpl/shortcodes.go @@ -0,0 +1,148 @@ +// 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/") +} diff --git a/tpl/tplimpl/shortcodes_test.go b/tpl/tplimpl/shortcodes_test.go new file mode 100644 index 000000000..6909feda7 --- /dev/null +++ b/tpl/tplimpl/shortcodes_test.go @@ -0,0 +1,94 @@ +// 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 ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestShortcodesTemplate(t *testing.T) { + + t.Run("isShortcode", func(t *testing.T) { + assert := require.New(t) + assert.True(isShortcode("shortcodes/figures.html")) + assert.True(isShortcode("_internal/shortcodes/figures.html")) + assert.False(isShortcode("shortcodes\\figures.html")) + assert.False(isShortcode("myshortcodes")) + + }) + + t.Run("variantsFromName", func(t *testing.T) { + assert := require.New(t) + assert.Equal([]string{"", "html", "html"}, templateVariants("figure.html")) + assert.Equal([]string{"no", "no", "html"}, templateVariants("figure.no.html")) + assert.Equal([]string{"no", "amp", "html"}, templateVariants("figure.no.amp.html")) + assert.Equal([]string{"amp", "amp", "html"}, templateVariants("figure.amp.html")) + + name, variants := templateNa |