Skip to content

Commit 077005e

Browse files
committed
output: Fix base theme vs project base template logic
Fixes #3323
1 parent efc0e05 commit 077005e

File tree

3 files changed

+63
-38
lines changed

3 files changed

+63
-38
lines changed

‎output/layout_base.go‎

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ type TemplateNames struct {
3838
}
3939

4040
type TemplateLookupDescriptor struct {
41-
// The full path to the site or theme root.
41+
// TemplateDir is the project or theme root of the current template.
42+
// This will be the same as WorkingDir for non-theme templates.
43+
TemplateDir string
44+
45+
// The full path to the site root.
4246
WorkingDir string
4347

4448
// Main project layout dir, defaults to "layouts"
@@ -51,8 +55,8 @@ type TemplateLookupDescriptor struct {
5155
// The template name prefix to look for, i.e. "theme".
5256
Prefix string
5357

54-
// The theme name if active.
55-
Theme string
58+
// The theme dir if theme active.
59+
ThemeDir string
5660

5761
// All the output formats in play. This is used to decide if text/template or
5862
// html/template.
@@ -64,16 +68,29 @@ type TemplateLookupDescriptor struct {
6468

6569
func CreateTemplateNames(d TemplateLookupDescriptor) (TemplateNames, error) {
6670

67-
var id TemplateNames
68-
6971
name := filepath.ToSlash(d.RelPath)
7072

7173
if d.Prefix != "" {
7274
name = strings.Trim(d.Prefix, "/") + "/" + name
7375
}
7476

75-
baseLayoutDir := filepath.Join(d.WorkingDir, d.LayoutDir)
76-
fullPath := filepath.Join(baseLayoutDir, d.RelPath)
77+
var (
78+
id TemplateNames
79+
80+
// This is the path to the actual template in process. This may
81+
// be in the theme's or the project's /layouts.
82+
baseLayoutDir = filepath.Join(d.TemplateDir, d.LayoutDir)
83+
fullPath = filepath.Join(baseLayoutDir, d.RelPath)
84+
85+
// This is always the project's layout dir.
86+
baseWorkLayoutDir = filepath.Join(d.WorkingDir, d.LayoutDir)
87+
88+
baseThemeLayoutDir string
89+
)
90+
91+
if d.ThemeDir != "" {
92+
baseThemeLayoutDir = filepath.Join(d.ThemeDir, "layouts")
93+
}
7794

7895
// The filename will have a suffix with an optional type indicator.
7996
// Examples:
@@ -140,8 +157,8 @@ func CreateTemplateNames(d TemplateLookupDescriptor) (TemplateNames, error) {
140157
currBaseFilename := fmt.Sprintf("%s-%s", filenameNoSuffix, baseFilename)
141158

142159
templateDir := filepath.Dir(fullPath)
143-
themeDir := filepath.Join(d.WorkingDir, d.Theme)
144160

161+
// Find the base, e.g. "_default".
145162
baseTemplatedDir := strings.TrimPrefix(templateDir, baseLayoutDir)
146163
baseTemplatedDir = strings.TrimPrefix(baseTemplatedDir, helpers.FilePathSeparator)
147164

@@ -162,7 +179,7 @@ func CreateTemplateNames(d TemplateLookupDescriptor) (TemplateNames, error) {
162179

163180
Loop:
164181
for _, pair := range pairsToCheck {
165-
pathsToCheck := basePathsToCheck(pair, baseLayoutDir, themeDir)
182+
pathsToCheck := basePathsToCheck(pair, baseLayoutDir, baseWorkLayoutDir, baseThemeLayoutDir)
166183

167184
for _, pathToCheck := range pathsToCheck {
168185
if ok, err := d.FileExists(pathToCheck); err == nil && ok {
@@ -177,13 +194,18 @@ func CreateTemplateNames(d TemplateLookupDescriptor) (TemplateNames, error) {
177194

178195
}
179196

180-
func basePathsToCheck(path []string, layoutDir, themeDir string) []string {
181-
// Always look in the project.
182-
pathsToCheck := []string{filepath.Join((append([]string{layoutDir}, path...))...)}
197+
func basePathsToCheck(path []string, layoutDir, workLayoutDir, themeLayoutDir string) []string {
198+
// workLayoutDir will always be the most specific, so start there.
199+
pathsToCheck := []string{filepath.Join((append([]string{workLayoutDir}, path...))...)}
200+
201+
if layoutDir != "" && layoutDir != workLayoutDir {
202+
pathsToCheck = append(pathsToCheck, filepath.Join((append([]string{layoutDir}, path...))...))
203+
}
183204

184205
// May have a theme
185-
if themeDir != "" {
186-
pathsToCheck = append(pathsToCheck, filepath.Join((append([]string{themeDir, "layouts"}, path...))...))
206+
if themeLayoutDir != "" && themeLayoutDir != layoutDir {
207+
pathsToCheck = append(pathsToCheck, filepath.Join((append([]string{themeLayoutDir}, path...))...))
208+
187209
}
188210

189211
return pathsToCheck

‎output/layout_base_test.go‎

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func TestLayoutBase(t *testing.T) {
2525

2626
var (
2727
workingDir = "/sites/mysite/"
28+
themeDir = "/themes/mytheme/"
2829
layoutBase1 = "layouts"
2930
layoutPath1 = "_default/single.html"
3031
layoutPathAmp = "_default/single.amp.html"
@@ -38,84 +39,84 @@ func TestLayoutBase(t *testing.T) {
3839
basePathMatchStrings string
3940
expect TemplateNames
4041
}{
41-
{"No base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1}, false, "",
42+
{"No base", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1}, false, "",
4243
TemplateNames{
4344
Name: "_default/single.html",
4445
OverlayFilename: "/sites/mysite/layouts/_default/single.html",
4546
}},
46-
{"Base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1}, true, "",
47+
{"Base", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1}, true, "",
4748
TemplateNames{
4849
Name: "_default/single.html",
4950
OverlayFilename: "/sites/mysite/layouts/_default/single.html",
5051
MasterFilename: "/sites/mysite/layouts/_default/single-baseof.html",
5152
}},
52-
{"Base in theme", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1, Theme: "mytheme"}, true,
53+
{"Base in theme", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1, ThemeDir: themeDir}, true,
5354
"mytheme/layouts/_default/baseof.html",
5455
TemplateNames{
5556
Name: "_default/single.html",
5657
OverlayFilename: "/sites/mysite/layouts/_default/single.html",
57-
MasterFilename: "/sites/mysite/mytheme/layouts/_default/baseof.html",
58+
MasterFilename: "/themes/mytheme/layouts/_default/baseof.html",
5859
}},
59-
{"Template in theme, base in theme", TemplateLookupDescriptor{WorkingDir: filepath.Join(workingDir, "mytheme"), LayoutDir: layoutBase1, RelPath: layoutPath1, Theme: "mytheme"}, true,
60+
{"Template in theme, base in theme", TemplateLookupDescriptor{TemplateDir: themeDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1, ThemeDir: themeDir}, true,
6061
"mytheme/layouts/_default/baseof.html",
6162
TemplateNames{
6263
Name: "_default/single.html",
63-
OverlayFilename: "/sites/mysite/mytheme/layouts/_default/single.html",
64-
MasterFilename: "/sites/mysite/mytheme/layouts/_default/baseof.html",
64+
OverlayFilename: "/themes/mytheme/layouts/_default/single.html",
65+
MasterFilename: "/themes/mytheme/layouts/_default/baseof.html",
6566
}},
66-
{"Template in theme, base in site", TemplateLookupDescriptor{WorkingDir: filepath.Join(workingDir, "mytheme"), LayoutDir: layoutBase1, RelPath: layoutPath1, Theme: "mytheme"}, true,
67-
"mytheme/layouts/_default/baseof.html",
67+
{"Template in theme, base in site", TemplateLookupDescriptor{TemplateDir: themeDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1, ThemeDir: themeDir}, true,
68+
"/sites/mysite/layouts/_default/baseof.html",
6869
TemplateNames{
6970
Name: "_default/single.html",
70-
OverlayFilename: "/sites/mysite/mytheme/layouts/_default/single.html",
71-
MasterFilename: "/sites/mysite/mytheme/layouts/_default/baseof.html",
71+
OverlayFilename: "/themes/mytheme/layouts/_default/single.html",
72+
MasterFilename: "/sites/mysite/layouts/_default/baseof.html",
7273
}},
73-
{"Template in site, base in theme", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1, Theme: "mytheme"}, true,
74-
"/sites/mysite/mytheme/layouts/_default/baseof.html",
74+
{"Template in site, base in theme", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1, ThemeDir: themeDir}, true,
75+
"/themes/mytheme",
7576
TemplateNames{
7677
Name: "_default/single.html",
7778
OverlayFilename: "/sites/mysite/layouts/_default/single.html",
78-
MasterFilename: "/sites/mysite/mytheme/layouts/_default/baseof.html",
79+
MasterFilename: "/themes/mytheme/layouts/_default/single-baseof.html",
7980
}},
80-
{"With prefix, base in theme", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1,
81-
Theme: "mytheme", Prefix: "someprefix"}, true,
81+
{"With prefix, base in theme", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1,
82+
ThemeDir: themeDir, Prefix: "someprefix"}, true,
8283
"mytheme/layouts/_default/baseof.html",
8384
TemplateNames{
8485
Name: "someprefix/_default/single.html",
8586
OverlayFilename: "/sites/mysite/layouts/_default/single.html",
86-
MasterFilename: "/sites/mysite/mytheme/layouts/_default/baseof.html",
87+
MasterFilename: "/themes/mytheme/layouts/_default/baseof.html",
8788
}},
88-
{"Partial", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: "partials/menu.html"}, true,
89+
{"Partial", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: "partials/menu.html"}, true,
8990
"mytheme/layouts/_default/baseof.html",
9091
TemplateNames{
9192
Name: "partials/menu.html",
9293
OverlayFilename: "/sites/mysite/layouts/partials/menu.html",
9394
}},
94-
{"AMP, no base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathAmp}, false, "",
95+
{"AMP, no base", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathAmp}, false, "",
9596
TemplateNames{
9697
Name: "_default/single.amp.html",
9798
OverlayFilename: "/sites/mysite/layouts/_default/single.amp.html",
9899
}},
99-
{"JSON, no base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathJSON}, false, "",
100+
{"JSON, no base", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathJSON}, false, "",
100101
TemplateNames{
101102
Name: "_default/single.json",
102103
OverlayFilename: "/sites/mysite/layouts/_default/single.json",
103104
}},
104-
{"AMP with base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathAmp}, true, "single-baseof.html|single-baseof.amp.html",
105+
{"AMP with base", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathAmp}, true, "single-baseof.html|single-baseof.amp.html",
105106
TemplateNames{
106107
Name: "_default/single.amp.html",
107108
OverlayFilename: "/sites/mysite/layouts/_default/single.amp.html",
108109
MasterFilename: "/sites/mysite/layouts/_default/single-baseof.amp.html",
109110
}},
110-
{"AMP with no match in base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathAmp}, true, "single-baseof.html",
111+
{"AMP with no match in base", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathAmp}, true, "single-baseof.html",
111112
TemplateNames{
112113
Name: "_default/single.amp.html",
113114
OverlayFilename: "/sites/mysite/layouts/_default/single.amp.html",
114115
// There is a single-baseof.html, but that makes no sense.
115116
MasterFilename: "",
116117
}},
117118

118-
{"JSON with base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathJSON}, true, "single-baseof.json",
119+
{"JSON with base", TemplateLookupDescriptor{TemplateDir: workingDir, WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathJSON}, true, "single-baseof.json",
119120
TemplateNames{
120121
Name: "_default/single.json",
121122
OverlayFilename: "/sites/mysite/layouts/_default/single.json",

‎tpl/tplimpl/template.go‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,13 +420,15 @@ func (t *templateHandler) loadTemplates(absPath string, prefix string) {
420420

421421
li := strings.LastIndex(path, layoutDir) + len(layoutDir) + 1
422422
relPath := path[li:]
423+
templateDir := path[:li-len(layoutDir)-1]
423424

424425
descriptor := output.TemplateLookupDescriptor{
426+
TemplateDir: templateDir,
425427
WorkingDir: workingDir,
426428
LayoutDir: layoutDir,
427429
RelPath: relPath,
428430
Prefix: prefix,
429-
Theme: t.PathSpec.Theme(),
431+
ThemeDir: themeDir,
430432
OutputFormats: t.OutputFormatsConfig,
431433
FileExists: func(filename string) (bool, error) {
432434
return helpers.Exists(filename, t.Fs.Source)

0 commit comments

Comments
 (0)