summaryrefslogtreecommitdiffstats
path: root/output
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-01-04 18:24:36 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-05-16 18:01:29 +0200
commit241b21b0fd34d91fccb2ce69874110dceae6f926 (patch)
treed4e0118eac7e9c42f065815447a70805f8d6ad3e /output
parent6aededf6b42011c3039f5f66487a89a8dd65e0e7 (diff)
Create a struct with all of Hugo's config options
Primary motivation is documentation, but it will also hopefully simplify the code. Also, * Lower case the default output format names; this is in line with the custom ones (map keys) and how it's treated all the places. This avoids doing `stringds.EqualFold` everywhere. Closes #10896 Closes #10620
Diffstat (limited to 'output')
-rw-r--r--output/config.go147
-rw-r--r--output/config_test.go98
-rw-r--r--output/docshelper.go58
-rw-r--r--output/layouts/layout.go (renamed from output/layout.go)62
-rw-r--r--output/layouts/layout_test.go (renamed from output/layout_test.go)179
-rw-r--r--output/outputFormat.go157
-rw-r--r--output/outputFormat_test.go145
7 files changed, 436 insertions, 410 deletions
diff --git a/output/config.go b/output/config.go
new file mode 100644
index 000000000..7b83ef9de
--- /dev/null
+++ b/output/config.go
@@ -0,0 +1,147 @@
+// Copyright 2023 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 output
+
+import (
+ "fmt"
+ "reflect"
+ "sort"
+ "strings"
+
+ "github.com/gohugoio/hugo/common/maps"
+ "github.com/gohugoio/hugo/config"
+ "github.com/gohugoio/hugo/media"
+ "github.com/mitchellh/mapstructure"
+)
+
+// OutputFormatConfig configures a single output format.
+type OutputFormatConfig struct {
+ // The MediaType string. This must be a configured media type.
+ MediaType string
+ Format
+}
+
+func DecodeConfig(mediaTypes media.Types, in any) (*config.ConfigNamespace[map[string]OutputFormatConfig, Formats], error) {
+ buildConfig := func(in any) (Formats, any, error) {
+ f := make(Formats, len(DefaultFormats))
+ copy(f, DefaultFormats)
+ if in != nil {
+ m, err := maps.ToStringMapE(in)
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed convert config to map: %s", err)
+ }
+ m = maps.CleanConfigStringMap(m)
+
+ for k, v := range m {
+ found := false
+ for i, vv := range f {
+ // Both are lower case.
+ if k == vv.Name {
+ // Merge it with the existing
+ if err := decode(mediaTypes, v, &f[i]); err != nil {
+ return f, nil, err
+ }
+ found = true
+ }
+ }
+ if found {
+ continue
+ }
+
+ var newOutFormat Format
+ newOutFormat.Name = k
+ if err := decode(mediaTypes, v, &newOutFormat); err != nil {
+ return f, nil, err
+ }
+
+ // We need values for these
+ if newOutFormat.BaseName == "" {
+ newOutFormat.BaseName = "index"
+ }
+ if newOutFormat.Rel == "" {
+ newOutFormat.Rel = "alternate"
+ }
+
+ f = append(f, newOutFormat)
+
+ }
+ }
+
+ // Also format is a map for documentation purposes.
+ docm := make(map[string]OutputFormatConfig, len(f))
+ for _, ff := range f {
+ docm[ff.Name] = OutputFormatConfig{
+ MediaType: ff.MediaType.Type,
+ Format: ff,
+ }
+ }
+
+ sort.Sort(f)
+ return f, docm, nil
+ }
+
+ return config.DecodeNamespace[map[string]OutputFormatConfig](in, buildConfig)
+}
+
+func decode(mediaTypes media.Types, input any, output *Format) error {
+ config := &mapstructure.DecoderConfig{
+ Metadata: nil,
+ Result: output,
+ WeaklyTypedInput: true,
+ DecodeHook: func(a reflect.Type, b reflect.Type, c any) (any, error) {
+ if a.Kind() == reflect.Map {
+ dataVal := reflect.Indirect(reflect.ValueOf(c))
+ for _, key := range dataVal.MapKeys() {
+ keyStr, ok := key.Interface().(string)
+ if !ok {
+ // Not a string key
+ continue
+ }
+ if strings.EqualFold(keyStr, "mediaType") {
+ // If mediaType is a string, look it up and replace it
+ // in the map.
+ vv := dataVal.MapIndex(key)
+ vvi := vv.Interface()
+
+ switch vviv := vvi.(type) {
+ case media.Type:
+ // OK
+ case string:
+ mediaType, found := mediaTypes.GetByType(vviv)
+ if !found {
+ return c, fmt.Errorf("media type %q not found", vviv)
+ }
+ dataVal.SetMapIndex(key, reflect.ValueOf(mediaType))
+ default:
+ return nil, fmt.Errorf("invalid output format configuration; wrong type for media type, expected string (e.g. text/html), got %T", vvi)
+ }
+ }
+ }
+ }
+ return c, nil
+ },
+ }
+
+ decoder, err := mapstructure.NewDecoder(config)
+ if err != nil {
+ return err
+ }
+
+ if err = decoder.Decode(input); err != nil {
+ return fmt.Errorf("failed to decode output format configuration: %w", err)
+ }
+
+ return nil
+
+}
diff --git a/output/config_test.go b/output/config_test.go
new file mode 100644
index 000000000..52381c5d2
--- /dev/null
+++ b/output/config_test.go
@@ -0,0 +1,98 @@
+// Copyright 2023 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 output
+
+import (
+ "testing"
+
+ qt "github.com/frankban/quicktest"
+ "github.com/gohugoio/hugo/media"
+)
+
+func TestDecodeConfig(t *testing.T) {
+ c := qt.New(t)
+
+ mediaTypes := media.Types{media.Builtin.JSONType, media.Builtin.XMLType}
+
+ tests := []struct {
+ name string
+ m map[string]any
+ shouldError bool
+ assert func(t *testing.T, name string, f Formats)
+ }{
+ {
+ "Redefine JSON",
+ map[string]any{
+ "json": map[string]any{
+ "baseName": "myindex",
+ "isPlainText": "false",
+ },
+ },
+ false,
+ func(t *testing.T, name string, f Formats) {
+ msg := qt.Commentf(name)
+ c.Assert(len(f), qt.Equals, len(DefaultFormats), msg)
+ json, _ := f.GetByName("JSON")
+ c.Assert(json.BaseName, qt.Equals, "myindex")
+ c.Assert(json.MediaType, qt.Equals, media.Builtin.JSONType)
+ c.Assert(json.IsPlainText, qt.Equals, false)
+ },
+ },
+ {
+ "Add XML format with string as mediatype",
+ map[string]any{
+ "MYXMLFORMAT": map[string]any{
+ "baseName": "myxml",
+ "mediaType": "application/xml",
+ },
+ },
+ false,
+ func(t *testing.T, name string, f Formats) {
+ c.Assert(len(f), qt.Equals, len(DefaultFormats)+1)
+ xml, found := f.GetByName("MYXMLFORMAT")
+ c.Assert(found, qt.Equals, true)
+ c.Assert(xml.BaseName, qt.Equals, "myxml")
+ c.Assert(xml.MediaType, qt.Equals, media.Builtin.XMLType)
+
+ // Verify that we haven't changed the DefaultFormats slice.
+ json, _ := f.GetByName("JSON")
+ c.Assert(json.BaseName, qt.Equals, "index")
+ },
+ },
+ {
+ "Add format unknown mediatype",
+ map[string]any{
+ "MYINVALID": map[string]any{
+ "baseName": "mymy",
+ "mediaType": "application/hugo",
+ },
+ },
+ true,
+ func(t *testing.T, name string, f Formats) {
+ },
+ },
+ }
+
+ for _, test := range tests {
+ result, err := DecodeConfig(mediaTypes, test.m)
+ msg := qt.Commentf(test.name)
+
+ if test.shouldError {
+ c.Assert(err, qt.Not(qt.IsNil), msg)
+ } else {
+ c.Assert(err, qt.IsNil, msg)
+ test.assert(t, test.name, result.Config)
+ }
+ }
+}
diff --git a/output/docshelper.go b/output/docshelper.go
index abfedd148..fa8ed1342 100644
--- a/output/docshelper.go
+++ b/output/docshelper.go
@@ -6,6 +6,7 @@ import (
// "fmt"
"github.com/gohugoio/hugo/docshelper"
+ "github.com/gohugoio/hugo/output/layouts"
)
// This is is just some helpers used to create some JSON used in the Hugo docs.
@@ -39,44 +40,43 @@ func createLayoutExamples() any {
for _, example := range []struct {
name string
- d LayoutDescriptor
- f Format
+ d layouts.LayoutDescriptor
}{
- // Taxonomy output.LayoutDescriptor={categories category taxonomy en false Type Section
- {"Single page in \"posts\" section", LayoutDescriptor{Kind: "page", Type: "posts"}, HTMLFormat},
- {"Base template for single page in \"posts\" section", LayoutDescriptor{Baseof: true, Kind: "page", Type: "posts"}, HTMLFormat},
- {"Single page in \"posts\" section with layout set", LayoutDescriptor{Kind: "page", Type: "posts", Layout: demoLayout}, HTMLFormat},
- {"Base template for single page in \"posts\" section with layout set", LayoutDescriptor{Baseof: true, Kind: "page", Type: "posts", Layout: demoLayout}, HTMLFormat},
- {"AMP single page", LayoutDescriptor{Kind: "page", Type: "posts"}, AMPFormat},
- {"AMP single page, French language", LayoutDescriptor{Kind: "page", Type: "posts", Lang: "fr"}, AMPFormat},
+ // Taxonomy layouts.LayoutDescriptor={categories category taxonomy en false Type Section
+ {"Single page in \"posts\" section", layouts.LayoutDescriptor{Kind: "page", Type: "posts", OutputFormatName: "html", Suffix: "html"}},
+ {"Base template for single page in \"posts\" section", layouts.LayoutDescriptor{Baseof: true, Kind: "page", Type: "posts", OutputFormatName: "html", Suffix: "html"}},
+ {"Single page in \"posts\" section with layout set", layouts.LayoutDescriptor{Kind: "page", Type: "posts", Layout: demoLayout, OutputFormatName: "html", Suffix: "html"}},
+ {"Base template for single page in \"posts\" section with layout set", layouts.LayoutDescriptor{Baseof: true, Kind: "page", Type: "posts", Layout: demoLayout, OutputFormatName: "html", Suffix: "html"}},
+ {"AMP single page", layouts.LayoutDescriptor{Kind: "page", Type: "posts", OutputFormatName: "amp", Suffix: "html"}},
+ {"AMP single page, French language", layouts.LayoutDescriptor{Kind: "page", Type: "posts", Lang: "fr", OutputFormatName: "html", Suffix: "html"}},
// All section or typeless pages gets "page" as type
- {"Home page", LayoutDescriptor{Kind: "home", Type: "page"}, HTMLFormat},
- {"Base template for home page", LayoutDescriptor{Baseof: true, Kind: "home", Type: "page"}, HTMLFormat},
- {"Home page with type set", LayoutDescriptor{Kind: "home", Type: demoType}, HTMLFormat},
- {"Base template for home page with type set", LayoutDescriptor{Baseof: true, Kind: "home", Type: demoType}, HTMLFormat},
- {"Home page with layout set", LayoutDescriptor{Kind: "home", Type: "page", Layout: demoLayout}, HTMLFormat},
- {"AMP home, French language", LayoutDescriptor{Kind: "home", Type: "page", Lang: "fr"}, AMPFormat},
- {"JSON home", LayoutDescriptor{Kind: "home", Type: "page"}, JSONFormat},
- {"RSS home", LayoutDescriptor{Kind: "home", Type: "page"}, RSSFormat},
- {"RSS section posts", LayoutDescriptor{Kind: "section", Type: "posts"}, RSSFormat},
- {"Taxonomy in categories", LayoutDescriptor{Kind: "taxonomy", Type: "categories", Section: "category"}, RSSFormat},
- {"Term in categories", LayoutDescriptor{Kind: "term", Type: "categories", Section: "category"}, RSSFormat},
- {"Section list for \"posts\" section", LayoutDescriptor{Kind: "section", Type: "posts", Section: "posts"}, HTMLFormat},
- {"Section list for \"posts\" section with type set to \"blog\"", LayoutDescriptor{Kind: "section", Type: "blog", Section: "posts"}, HTMLFormat},
- {"Section list for \"posts\" section with layout set to \"demoLayout\"", LayoutDescriptor{Kind: "section", Layout: demoLayout, Section: "posts"}, HTMLFormat},
+ {"Home page", layouts.LayoutDescriptor{Kind: "home", Type: "page", OutputFormatName: "html", Suffix: "html"}},
+ {"Base template for home page", layouts.LayoutDescriptor{Baseof: true, Kind: "home", Type: "page", OutputFormatName: "html", Suffix: "html"}},
+ {"Home page with type set", layouts.LayoutDescriptor{Kind: "home", Type: demoType, OutputFormatName: "html", Suffix: "html"}},
+ {"Base template for home page with type set", layouts.LayoutDescriptor{Baseof: true, Kind: "home", Type: demoType, OutputFormatName: "html", Suffix: "html"}},
+ {"Home page with layout set", layouts.LayoutDescriptor{Kind: "home", Type: "page", Layout: demoLayout, OutputFormatName: "html", Suffix: "html"}},
+ {"AMP home, French language", layouts.LayoutDescriptor{Kind: "home", Type: "page", Lang: "fr", OutputFormatName: "amp", Suffix: "html"}},
+ {"JSON home", layouts.LayoutDescriptor{Kind: "home", Type: "page", OutputFormatName: "json", Suffix: "json"}},
+ {"RSS home", layouts.LayoutDescriptor{Kind: "home", Type: "page", OutputFormatName: "rss", Suffix: "rss"}},
+ {"RSS section posts", layouts.LayoutDescriptor{Kind: "section", Type: "posts", OutputFormatName: "rss", Suffix: "rss"}},
+ {"Taxonomy in categories", layouts.LayoutDescriptor{Kind: "taxonomy", Type: "categories", Section: "category", OutputFormatName: "rss", Suffix: "rss"}},
+ {"Term in categories", layouts.LayoutDescriptor{Kind: "term", Type: "categories", Section: "category", OutputFormatName: "rss", Suffix: "rss"}},
+ {"Section list for \"posts\" section", layouts.LayoutDescriptor{Kind: "section", Type: "posts", Section: "posts", OutputFormatName: "html", Suffix: "html"}},
+ {"Section list for \"posts\" section with type set to \"blog\"", layouts.LayoutDescriptor{Kind: "section", Type: "blog", Section: "posts", OutputFormatName: "html", Suffix: "html"}},
+ {"Section list for \"posts\" section with layout set to \"demoLayout\"", layouts.LayoutDescriptor{Kind: "section", Layout: demoLayout, Section: "posts", OutputFormatName: "html", Suffix: "html"}},
- {"Taxonomy list in categories", LayoutDescriptor{Kind: "taxonomy", Type: "categories", Section: "category"}, HTMLFormat},
- {"Taxonomy term in categories", LayoutDescriptor{Kind: "term", Type: "categories", Section: "category"}, HTMLFormat},
+ {"Taxonomy list in categories", layouts.LayoutDescriptor{Kind: "taxonomy", Type: "categories", Section: "category", OutputFormatName: "html", Suffix: "html"}},
+ {"Taxonomy term in categories", layouts.LayoutDescriptor{Kind: "term", Type: "categories", Section: "category", OutputFormatName: "html", Suffix: "html"}},
} {
- l := NewLayoutHandler()
- layouts, _ := l.For(example.d, example.f)
+ l := layouts.NewLayoutHandler()
+ layouts, _ := l.For(example.d)
basicExamples = append(basicExamples, Example{
Example: example.name,
Kind: example.d.Kind,
- OutputFormat: example.f.Name,
- Suffix: example.f.MediaType.FirstSuffix.Suffix,
+ OutputFormat: example.d.OutputFormatName,
+ Suffix: example.d.Suffix,
Layouts: makeLayoutsPresentable(layouts),
})
}
diff --git a/output/layout.go b/output/layouts/layout.go
index dcbdf461a..9c5ef17a1 100644
--- a/output/layout.go
+++ b/output/layouts/layout.go
@@ -1,4 +1,4 @@
-// Copyright 2017-present The Hugo Authors. All rights reserved.
+// Copyright 2023 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.
@@ -11,13 +11,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package output
+package layouts
import (
"strings"
"sync"
-
- "github.com/gohugoio/hugo/helpers"
)
// These may be used as content sections with potential conflicts. Avoid that.
@@ -43,6 +41,10 @@ type LayoutDescriptor struct {
// LayoutOverride indicates what we should only look for the above layout.
LayoutOverride bool
+ // From OutputFormat and MediaType.
+ OutputFormatName string
+ Suffix string
+
RenderingHook bool
Baseof bool
}
@@ -54,37 +56,31 @@ func (d LayoutDescriptor) isList() bool {
// LayoutHandler calculates the layout template to use to render a given output type.
type LayoutHandler struct {
mu sync.RWMutex
- cache map[layoutCacheKey][]string
-}
-
-type layoutCacheKey struct {
- d LayoutDescriptor
- f string
+ cache map[LayoutDescriptor][]string
}
// NewLayoutHandler creates a new LayoutHandler.
func NewLayoutHandler() *LayoutHandler {
- return &LayoutHandler{cache: make(map[layoutCacheKey][]string)}
+ return &LayoutHandler{cache: make(map[LayoutDescriptor][]string)}
}
// For returns a layout for the given LayoutDescriptor and options.
// Layouts are rendered and cached internally.
-func (l *LayoutHandler) For(d LayoutDescriptor, f Format) ([]string, error) {
+func (l *LayoutHandler) For(d LayoutDescriptor) ([]string, error) {
// We will get lots of requests for the same layouts, so avoid recalculations.
- key := layoutCacheKey{d, f.Name}
l.mu.RLock()
- if cacheVal, found := l.cache[key]; found {
+ if cacheVal, found := l.cache[d]; found {
l.mu.RUnlock()
return cacheVal, nil
}
l.mu.RUnlock()
- layouts := resolvePageTemplate(d, f)
+ layouts := resolvePageTemplate(d)
- layouts = helpers.UniqueStringsReuse(layouts)
+ layouts = uniqueStringsReuse(layouts)
l.mu.Lock()
- l.cache[key] = layouts
+ l.cache[d] = layouts
l.mu.Unlock()
return layouts, nil
@@ -94,7 +90,7 @@ type layoutBuilder struct {
layoutVariations []string
typeVariations []string
d LayoutDescriptor
- f Format
+ //f Format
}
func (l *layoutBuilder) addLayoutVariations(vars ...string) {
@@ -134,8 +130,8 @@ func (l *layoutBuilder) addKind() {
const renderingHookRoot = "/_markup"
-func resolvePageTemplate(d LayoutDescriptor, f Format) []string {
- b := &layoutBuilder{d: d, f: f}
+func resolvePageTemplate(d LayoutDescriptor) []string {
+ b := &layoutBuilder{d: d}
if !d.RenderingHook && d.Layout != "" {
b.addLayoutVariations(d.Layout)
@@ -190,7 +186,7 @@ func resolvePageTemplate(d LayoutDescriptor, f Format) []string {
b.addTypeVariations("")
}
- isRSS := f.Name == RSSFormat.Name
+ isRSS := strings.EqualFold(d.OutputFormatName, "rss")
if !d.RenderingHook && !d.Baseof && isRSS {
// The historic and common rss.xml case
b.addLayoutVariations("")
@@ -223,7 +219,7 @@ func (l *layoutBuilder) resolveVariations() []string {
var layouts []string
var variations []string
- name := strings.ToLower(l.f.Name)
+ name := strings.ToLower(l.d.OutputFormatName)
if l.d.Lang != "" {
// We prefer the most specific type before language.
@@ -241,7 +237,7 @@ func (l *layoutBuilder) resolveVariations() []string {
continue
}
- s := constructLayoutPath(typeVar, layoutVar, variation, l.f.MediaType.FirstSuffix.Suffix)
+ s := constructLayoutPath(typeVar, layoutVar, variation, l.d.Suffix)
if s != "" {
layouts = append(layouts, s)
}
@@ -300,3 +296,23 @@ func constructLayoutPath(typ, layout, variations, extension string) string {
return p.String()
}
+
+// Inline this here so we can use tinygo to compile a wasm binary of this package.
+func uniqueStringsReuse(s []string) []string {
+ result := s[:0]
+ for i, val := range s {
+ var seen bool
+
+ for j := 0; j < i; j++ {
+ if s[j] == val {
+ seen = true
+ break
+ }
+ }
+
+ if !seen {
+ result = append(result, val)
+ }
+ }
+ return result
+}
diff --git a/output/layout_test.go b/output/layouts/layout_test.go
index 8b7a2b541..2f340f238 100644
--- a/output/layout_test.go
+++ b/output/layouts/layout_test.go
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package output
+package layouts
import (
"fmt"
@@ -19,8 +19,6 @@ import (
"strings"
"testing"
- "github.com/gohugoio/hugo/media"
-
qt "github.com/frankban/quicktest"
"github.com/kylelemons/godebug/diff"
)
@@ -28,42 +26,16 @@ import (
func TestLayout(t *testing.T) {
c := qt.New(t)
- noExtNoDelimMediaType := media.WithDelimiterAndSuffixes(media.TextType, "", "")
- noExtMediaType := media.WithDelimiterAndSuffixes(media.TextType, ".", "")
-
- var (
- ampType = Format{
- Name: "AMP",
- MediaType: media.HTMLType,
- BaseName: "index",
- }
-
- htmlFormat = HTMLFormat
-
- noExtDelimFormat = Format{
- Name: "NEM",
- MediaType: noExtNoDelimMediaType,
- BaseName: "_redirects",
- }
-
- noExt = Format{
- Name: "NEX",
- MediaType: noExtMediaType,
- BaseName: "next",
- }
- )
-
for _, this := range []struct {
name string
layoutDescriptor LayoutDescriptor
layoutOverride string
- format Format
expect []string
}{
{
"Home",
- LayoutDescriptor{Kind: "home"},
- "", ampType,
+ LayoutDescriptor{Kind: "home", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"index.amp.html",
"home.amp.html",
@@ -81,8 +53,8 @@ func TestLayout(t *testing.T) {
},
{
"Home baseof",
- LayoutDescriptor{Kind: "home", Baseof: true},
- "", ampType,
+ LayoutDescriptor{Kind: "home", Baseof: true, OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"index-baseof.amp.html",
"home-baseof.amp.html",
@@ -104,8 +76,8 @@ func TestLayout(t *testing.T) {
},
{
"Home, HTML",
- LayoutDescriptor{Kind: "home"},
- "", htmlFormat,
+ LayoutDescriptor{Kind: "home", OutputFormatName: "html", Suffix: "html"},
+ "",
// We will eventually get to index.html. This looks stuttery, but makes the lookup logic easy to understand.
[]string{
"index.html.html",
@@ -124,8 +96,8 @@ func TestLayout(t *testing.T) {
},
{
"Home, HTML, baseof",
- LayoutDescriptor{Kind: "home", Baseof: true},
- "", htmlFormat,
+ LayoutDescriptor{Kind: "home", Baseof: true, OutputFormatName: "html", Suffix: "html"},
+ "",
[]string{
"index-baseof.html.html",
"home-baseof.html.html",
@@ -147,8 +119,8 @@ func TestLayout(t *testing.T) {
},
{
"Home, french language",
- LayoutDescriptor{Kind: "home", Lang: "fr"},
- "", ampType,
+ LayoutDescriptor{Kind: "home", Lang: "fr", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"index.fr.amp.html",
"home.fr.amp.html",
@@ -178,8 +150,8 @@ func TestLayout(t *testing.T) {
},
{
"Home, no ext or delim",
- LayoutDescriptor{Kind: "home"},
- "", noExtDelimFormat,
+ LayoutDescriptor{Kind: "home", OutputFormatName: "nem", Suffix: ""},
+ "",
[]string{
"index.nem",
"home.nem",
@@ -191,8 +163,8 @@ func TestLayout(t *testing.T) {
},
{
"Home, no ext",
- LayoutDescriptor{Kind: "home"},
- "", noExt,
+ LayoutDescriptor{Kind: "home", OutputFormatName: "nex", Suffix: ""},
+ "",
[]string{
"index.nex",
"home.nex",
@@ -204,14 +176,14 @@ func TestLayout(t *testing.T) {
},
{
"Page, no ext or delim",
- LayoutDescriptor{Kind: "page"},
- "", noExtDelimFormat,
+ LayoutDescriptor{Kind: "page", OutputFormatName: "nem", Suffix: ""},
+ "",
[]string{"_default/single.nem"},
},
{
"Section",
- LayoutDescriptor{Kind: "section", Section: "sect1"},
- "", ampType,
+ LayoutDescriptor{Kind: "section", Section: "sect1", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"sect1/sect1.amp.html",
"sect1/section.amp.html",
@@ -235,8 +207,8 @@ func TestLayout(t *testing.T) {
},
{
"Section, baseof",
- LayoutDescriptor{Kind: "section", Section: "sect1", Baseof: true},
- "", ampType,
+ LayoutDescriptor{Kind: "section", Section: "sect1", Baseof: true, OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"sect1/sect1-baseof.amp.html",
"sect1/section-baseof.amp.html",
@@ -266,8 +238,8 @@ func TestLayout(t *testing.T) {
},
{
"Section, baseof, French, AMP",
- LayoutDescriptor{Kind: "section", Section: "sect1", Lang: "fr", Baseof: true},
- "", ampType,
+ LayoutDescriptor{Kind: "section", Section: "sect1", Lang: "fr", Baseof: true, OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"sect1/sect1-baseof.fr.amp.html",
"sect1/section-baseof.fr.amp.html",
@@ -321,8 +293,8 @@ func TestLayout(t *testing.T) {
},
{
"Section with layout",
- LayoutDescriptor{Kind: "section", Section: "sect1", Layout: "mylayout"},
- "", ampType,
+ LayoutDescriptor{Kind: "section", Section: "sect1", Layout: "mylayout", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"sect1/mylayout.amp.html",
"sect1/sect1.amp.html",
@@ -352,8 +324,8 @@ func TestLayout(t *testing.T) {
},
{
"Term, French, AMP",
- LayoutDescriptor{Kind: "term", Section: "tags", Lang: "fr"},
- "", ampType,
+ LayoutDescriptor{Kind: "term", Section: "tags", Lang: "fr", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"term/term.fr.amp.html",
"term/tags.fr.amp.html",
@@ -423,8 +395,8 @@ func TestLayout(t *testing.T) {
},
{
"Term, baseof, French, AMP",
- LayoutDescriptor{Kind: "term", Section: "tags", Lang: "fr", Baseof: true},
- "", ampType,
+ LayoutDescriptor{Kind: "term", Section: "tags", Lang: "fr", Baseof: true, OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"term/term-baseof.fr.amp.html",
"term/tags-baseof.fr.amp.html",
@@ -510,8 +482,8 @@ func TestLayout(t *testing.T) {
},
{
"Term",
- LayoutDescriptor{Kind: "term", Section: "tags"},
- "", ampType,
+ LayoutDescriptor{Kind: "term", Section: "tags", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"term/term.amp.html",
"term/tags.amp.html",
@@ -549,8 +521,8 @@ func TestLayout(t *testing.T) {
},
{
"Taxonomy",
- LayoutDescriptor{Kind: "taxonomy", Section: "categories"},
- "", ampType,
+ LayoutDescriptor{Kind: "taxonomy", Section: "categories", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"categories/categories.terms.amp.html",
"categories/terms.amp.html",
@@ -580,8 +552,8 @@ func TestLayout(t *testing.T) {
},
{
"Page",
- LayoutDescriptor{Kind: "page"},
- "", ampType,
+ LayoutDescriptor{Kind: "page", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"_default/single.amp.html",
"_default/single.html",
@@ -589,8 +561,8 @@ func TestLayout(t *testing.T) {
},
{
"Page, baseof",
- LayoutDescriptor{Kind: "page", Baseof: true},
- "", ampType,
+ LayoutDescriptor{Kind: "page", Baseof: true, OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"_default/single-baseof.amp.html",
"_default/baseof.amp.html",
@@ -600,8 +572,8 @@ func TestLayout(t *testing.T) {
},
{
"Page with layout",
- LayoutDescriptor{Kind: "page", Layout: "mylayout"},
- "", ampType,
+ LayoutDescriptor{Kind: "page", Layout: "mylayout", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"_default/mylayout.amp.html",
"_default/single.amp.html",
@@ -611,8 +583,8 @@ func TestLayout(t *testing.T) {
},
{
"Page with layout, baseof",
- LayoutDescriptor{Kind: "page", Layout: "mylayout", Baseof: true},
- "", ampType,
+ LayoutDescriptor{Kind: "page", Layout: "mylayout", Baseof: true, OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"_default/mylayout-baseof.amp.html",
"_default/single-baseof.amp.html",
@@ -624,8 +596,8 @@ func TestLayout(t *testing.T) {
},
{
"Page with layout and type",
- LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype"},
- "", ampType,
+ LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"myttype/mylayout.amp.html",
"myttype/single.amp.html",
@@ -639,8 +611,8 @@ func TestLayout(t *testing.T) {
},
{
"Page baseof with layout and type",
- LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype", Baseof: true},
- "", ampType,
+ LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype", Baseof: true, OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"myttype/mylayout-baseof.amp.html",
"myttype/single-baseof.amp.html",
@@ -658,8 +630,8 @@ func TestLayout(t *testing.T) {
},
{
"Page baseof with layout and type in French",
- LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype", Lang: "fr", Baseof: true},
- "", ampType,
+ LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype", Lang: "fr", Baseof: true, OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"myttype/mylayout-baseof.fr.amp.html",
"myttype/single-baseof.fr.amp.html",
@@ -689,8 +661,8 @@ func TestLayout(t *testing.T) {
},
{
"Page with layout and type with subtype",
- LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype/mysubtype"},
- "", ampType,
+ LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype/mysubtype", OutputFormatName: "amp", Suffix: "html"},
+ "",
[]string{
"myttype/mysubtype/mylayout.amp.html",
"myttype/mysubtype/single.amp.html",
@@ -705,8 +677,8 @@ func TestLayout(t *testing.T) {
// RSS
{
"RSS Home",
- Layou