mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-29 23:02:19 -05:00
160 lines
3.5 KiB
Go
160 lines
3.5 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 length.
|
|
// 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 resolveTemplateType(name string) templateType {
|
|
if isShortcode(name) {
|
|
return templateShortcode
|
|
}
|
|
|
|
if strings.Contains(name, "partials/") {
|
|
return templatePartial
|
|
}
|
|
|
|
return templateUndefined
|
|
}
|
|
|
|
func isShortcode(name string) bool {
|
|
return strings.Contains(name, shortcodesPathPrefix)
|
|
}
|
|
|
|
func isInternal(name string) bool {
|
|
return strings.HasPrefix(name, internalPathPrefix)
|
|
}
|