1414package output
1515
1616import (
17- "fmt"
1817 "strings"
1918 "sync"
2019
@@ -65,7 +64,6 @@ func NewLayoutHandler() *LayoutHandler {
6564// For returns a layout for the given LayoutDescriptor and options.
6665// Layouts are rendered and cached internally.
6766func (l * LayoutHandler ) For (d LayoutDescriptor , f Format ) ([]string , error ) {
68-
6967 // We will get lots of requests for the same layouts, so avoid recalculations.
7068 key := layoutCacheKey {d , f .Name }
7169 l .mu .RLock ()
@@ -131,7 +129,6 @@ func (l *layoutBuilder) addKind() {
131129const renderingHookRoot = "/_markup"
132130
133131func resolvePageTemplate (d LayoutDescriptor , f Format ) []string {
134-
135132 b := & layoutBuilder {d : d , f : f }
136133
137134 if ! d .RenderingHook && d .Layout != "" {
@@ -208,19 +205,17 @@ func resolvePageTemplate(d LayoutDescriptor, f Format) []string {
208205 }
209206
210207 return layouts
211-
212208}
213209
214210func (l * layoutBuilder ) resolveVariations () []string {
215-
216211 var layouts []string
217212
218213 var variations []string
219214 name := strings .ToLower (l .f .Name )
220215
221216 if l .d .Lang != "" {
222217 // We prefer the most specific type before language.
223- variations = append (variations , []string {fmt . Sprintf ( "%s.%s" , l .d .Lang , name ) , name , l .d .Lang }... )
218+ variations = append (variations , []string {l .d .Lang + "." + name , name , l .d .Lang }... )
224219 } else {
225220 variations = append (variations , name )
226221 }
@@ -233,55 +228,63 @@ func (l *layoutBuilder) resolveVariations() []string {
233228 if variation == "" && layoutVar == "" {
234229 continue
235230 }
236- template := layoutTemplate (typeVar , layoutVar )
237- layouts = append (layouts , replaceKeyValues (template ,
238- "TYPE" , typeVar ,
239- "LAYOUT" , layoutVar ,
240- "VARIATIONS" , variation ,
241- "EXTENSION" , l .f .MediaType .Suffix (),
242- ))
231+
232+ s := constructLayoutPath (typeVar , layoutVar , variation , l .f .MediaType .Suffix ())
233+ if s != "" {
234+ layouts = append (layouts , s )
235+ }
243236 }
244237 }
245-
246238 }
247239
248- return filterDotLess ( layouts )
240+ return layouts
249241}
250242
251- func layoutTemplate (typeVar , layoutVar string ) string {
243+ // constructLayoutPath constructs a layout path given a type, layout,
244+ // variations, and extension. The path constructed follows the pattern of
245+ // type/layout.variations.extension. If any value is empty, it will be left out
246+ // of the path construction.
247+ //
248+ // Path construction requires at least 2 of 3 out of layout, variations, and extension.
249+ // If more than one of those is empty, an empty string is returned.
250+ func constructLayoutPath (typ , layout , variations , extension string ) string {
251+ // we already know that layout and variations are not both empty because of
252+ // checks in resolveVariants().
253+ if extension == "" && (layout == "" || variations == "" ) {
254+ return ""
255+ }
256+
257+ // Commence valid path construction...
252258
253- var l string
259+ var (
260+ p strings.Builder
261+ needDot bool
262+ )
254263
255- if typeVar != "" {
256- l = "TYPE/"
264+ if typ != "" {
265+ p .WriteString (typ )
266+ p .WriteString ("/" )
257267 }
258268
259- if layoutVar != "" {
260- l += "LAYOUT.VARIATIONS.EXTENSION"
261- } else {
262- l += "VARIATIONS.EXTENSION"
269+ if layout != "" {
270+ p .WriteString (layout )
271+ needDot = true
263272 }
264273
265- return l
266- }
267-
268- func filterDotLess (layouts []string ) []string {
269- var filteredLayouts []string
270-
271- for _ , l := range layouts {
272- l = strings .Replace (l , ".." , "." , - 1 )
273- l = strings .Trim (l , "." )
274- // If media type has no suffix, we have "index" type of layouts in this list, which
275- // doesn't make much sense.
276- if strings .Contains (l , "." ) {
277- filteredLayouts = append (filteredLayouts , l )
274+ if variations != "" {
275+ if needDot {
276+ p .WriteString ("." )
278277 }
278+ p .WriteString (variations )
279+ needDot = true
279280 }
280281
281- return filteredLayouts
282- }
282+ if extension != "" {
283+ if needDot {
284+ p .WriteString ("." )
285+ }
286+ p .WriteString (extension )
287+ }
283288
284- func replaceKeyValues (s string , oldNew ... string ) string {
285- replacer := strings .NewReplacer (oldNew ... )
286- return replacer .Replace (s )
289+ return p .String ()
287290}
0 commit comments