summaryrefslogtreecommitdiffstats
path: root/tpl/tplimpl/shortcodes.go
diff options
context:
space:
mode:
Diffstat (limited to 'tpl/tplimpl/shortcodes.go')
-rw-r--r--tpl/tplimpl/shortcodes.go148
1 files changed, 148 insertions, 0 deletions
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/")
+}