@@ -124,24 +124,25 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot i
124124 if p .posContainerHigh != - 1 {
125125 return
126126 }
127- mayHaveLang := pp .LanguageIndex != nil
127+ mayHaveLang := p . posIdentifierLanguage == - 1 && pp .LanguageIndex != nil
128128 mayHaveLang = mayHaveLang && (component == files .ComponentFolderContent || component == files .ComponentFolderLayouts )
129129 mayHaveOutputFormat := component == files .ComponentFolderLayouts
130- mayHaveKind := mayHaveOutputFormat
130+ mayHaveKind := p .posIdentifierKind == - 1 && mayHaveOutputFormat
131+ mayHaveLayout := component == files .ComponentFolderLayouts
131132
132133 var found bool
133134 var high int
134- if len (p .identifiers ) > 0 {
135+ if len (p .identifiersKnown ) > 0 {
135136 high = lastDot
136137 } else {
137138 high = len (p .s )
138139 }
139140 id := types.LowHigh [string ]{Low : i + 1 , High : high }
140141 sid := p .s [id .Low :id .High ]
141142
142- if len (p .identifiers ) == 0 {
143+ if len (p .identifiersKnown ) == 0 {
143144 // The first is always the extension.
144- p .identifiers = append (p .identifiers , id )
145+ p .identifiersKnown = append (p .identifiersKnown , id )
145146 found = true
146147
147148 // May also be the output format.
@@ -164,8 +165,8 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot i
164165 }
165166 found = langFound
166167 if langFound {
167- p .identifiers = append (p .identifiers , id )
168- p .posIdentifierLanguage = len (p .identifiers ) - 1
168+ p .identifiersKnown = append (p .identifiersKnown , id )
169+ p .posIdentifierLanguage = len (p .identifiersKnown ) - 1
169170
170171 }
171172 }
@@ -177,28 +178,33 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot i
177178 // false positives on the form css.html.
178179 if pp .IsOutputFormat (sid , p .Ext ()) {
179180 found = true
180- p .identifiers = append (p .identifiers , id )
181- p .posIdentifierOutputFormat = len (p .identifiers ) - 1
181+ p .identifiersKnown = append (p .identifiersKnown , id )
182+ p .posIdentifierOutputFormat = len (p .identifiersKnown ) - 1
182183 }
183184 }
184185
185186 if ! found && mayHaveKind {
186187 if kinds .GetKindMain (sid ) != "" {
187188 found = true
188- p .identifiers = append (p .identifiers , id )
189- p .posIdentifierKind = len (p .identifiers ) - 1
189+ p .identifiersKnown = append (p .identifiersKnown , id )
190+ p .posIdentifierKind = len (p .identifiersKnown ) - 1
190191 }
191192 }
192193
193194 if ! found && sid == identifierBaseof {
194195 found = true
195- p .identifiers = append (p .identifiers , id )
196- p .posIdentifierBaseof = len (p .identifiers ) - 1
196+ p .identifiersKnown = append (p .identifiersKnown , id )
197+ p .posIdentifierBaseof = len (p .identifiersKnown ) - 1
198+ }
199+
200+ if ! found && mayHaveLayout {
201+ p .identifiersKnown = append (p .identifiersKnown , id )
202+ p .posIdentifierLayout = len (p .identifiersKnown ) - 1
203+ found = true
197204 }
198205
199206 if ! found {
200- p .identifiers = append (p .identifiers , id )
201- p .identifiersUnknown = append (p .identifiersUnknown , len (p .identifiers )- 1 )
207+ p .identifiersUnknown = append (p .identifiersUnknown , id )
202208 }
203209
204210 }
@@ -252,13 +258,13 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
252258 }
253259 }
254260
255- if len (p .identifiers ) > 0 {
261+ if len (p .identifiersKnown ) > 0 {
256262 isContentComponent := p .component == files .ComponentFolderContent || p .component == files .ComponentFolderArchetypes
257263 isContent := isContentComponent && pp .IsContentExt (p .Ext ())
258- id := p .identifiers [len (p .identifiers )- 1 ]
264+ id := p .identifiersKnown [len (p .identifiersKnown )- 1 ]
259265
260- if id .High > p .posContainerHigh {
261- b := p .s [p .posContainerHigh : id .High ]
266+ if id .Low > p .posContainerHigh {
267+ b := p .s [p .posContainerHigh : id .Low - 1 ]
262268 if isContent {
263269 switch b {
264270 case "index" :
@@ -294,6 +300,16 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
294300 }
295301 }
296302
303+ if p .pathType == TypeShortcode && p .posIdentifierLayout != - 1 {
304+ // myshortcode or myshortcode.html, no layout.
305+ if len (p .identifiersKnown ) <= 2 {
306+ p .posIdentifierLayout = - 1
307+ } else {
308+ // First is always the name.
309+ p .posIdentifierLayout --
310+ }
311+ }
312+
297313 return p , nil
298314}
299315
@@ -350,13 +366,14 @@ type Path struct {
350366 component string
351367 pathType Type
352368
353- identifiers []types.LowHigh [string ]
369+ identifiersKnown []types.LowHigh [string ]
370+ identifiersUnknown []types.LowHigh [string ]
354371
355372 posIdentifierLanguage int
356373 posIdentifierOutputFormat int
357374 posIdentifierKind int
375+ posIdentifierLayout int
358376 posIdentifierBaseof int
359- identifiersUnknown []int
360377 disabled bool
361378
362379 trimLeadingSlash bool
@@ -388,10 +405,11 @@ func (p *Path) reset() {
388405 p .posSectionHigh = - 1
389406 p .component = ""
390407 p .pathType = 0
391- p .identifiers = p .identifiers [:0 ]
408+ p .identifiersKnown = p .identifiersKnown [:0 ]
392409 p .posIdentifierLanguage = - 1
393410 p .posIdentifierOutputFormat = - 1
394411 p .posIdentifierKind = - 1
412+ p .posIdentifierLayout = - 1
395413 p .posIdentifierBaseof = - 1
396414 p .disabled = false
397415 p .trimLeadingSlash = false
@@ -479,7 +497,7 @@ func (p *Path) Name() string {
479497// Name returns the last element of path without any extension.
480498func (p * Path ) NameNoExt () string {
481499 if i := p .identifierIndex (0 ); i != - 1 {
482- return p .s [p .posContainerHigh : p .identifiers [i ].Low - 1 ]
500+ return p .s [p .posContainerHigh : p .identifiersKnown [i ].Low - 1 ]
483501 }
484502 return p .s [p .posContainerHigh :]
485503}
@@ -491,7 +509,7 @@ func (p *Path) NameNoLang() string {
491509 return p .Name ()
492510 }
493511
494- return p .s [p .posContainerHigh :p .identifiers [i ].Low - 1 ] + p .s [p .identifiers [i ].High :]
512+ return p .s [p .posContainerHigh :p .identifiersKnown [i ].Low - 1 ] + p .s [p .identifiersKnown [i ].High :]
495513}
496514
497515// BaseNameNoIdentifier returns the logical base name for a resource without any identifier (e.g. no extension).
@@ -510,15 +528,15 @@ func (p *Path) NameNoIdentifier() string {
510528}
511529
512530func (p * Path ) nameLowHigh () types.LowHigh [string ] {
513- if len (p .identifiers ) > 0 {
514- lastID := p .identifiers [len (p .identifiers )- 1 ]
531+ if len (p .identifiersKnown ) > 0 {
532+ lastID := p .identifiersKnown [len (p .identifiersKnown )- 1 ]
515533 if p .posContainerHigh == lastID .Low {
516534 // The last identifier is the name.
517535 return lastID
518536 }
519537 return types.LowHigh [string ]{
520538 Low : p .posContainerHigh ,
521- High : p .identifiers [len (p .identifiers )- 1 ].Low - 1 ,
539+ High : p .identifiersKnown [len (p .identifiersKnown )- 1 ].Low - 1 ,
522540 }
523541 }
524542 return types.LowHigh [string ]{
@@ -566,7 +584,7 @@ func (p *Path) PathNoIdentifier() string {
566584
567585// PathBeforeLangAndOutputFormatAndExt returns the path up to the first identifier that is not a language or output format.
568586func (p * Path ) PathBeforeLangAndOutputFormatAndExt () string {
569- if len (p .identifiers ) == 0 {
587+ if len (p .identifiersKnown ) == 0 {
570588 return p .norm (p .s )
571589 }
572590 i := p .identifierIndex (0 )
@@ -582,7 +600,7 @@ func (p *Path) PathBeforeLangAndOutputFormatAndExt() string {
582600 return p .norm (p .s )
583601 }
584602
585- id := p .identifiers [i ]
603+ id := p .identifiersKnown [i ]
586604 return p .norm (p .s [:id .Low - 1 ])
587605}
588606
@@ -633,11 +651,11 @@ func (p *Path) BaseNoLeadingSlash() string {
633651}
634652
635653func (p * Path ) base (preserveExt , isBundle bool ) string {
636- if len (p .identifiers ) == 0 {
654+ if len (p .identifiersKnown ) == 0 {
637655 return p .norm (p .s )
638656 }
639657
640- if preserveExt && len (p .identifiers ) == 1 {
658+ if preserveExt && len (p .identifiersKnown ) == 1 {
641659 // Preserve extension.
642660 return p .norm (p .s )
643661 }
@@ -659,7 +677,7 @@ func (p *Path) base(preserveExt, isBundle bool) string {
659677 }
660678
661679 // For txt files etc. we want to preserve the extension.
662- id := p .identifiers [0 ]
680+ id := p .identifiersKnown [0 ]
663681
664682 return p .norm (p .s [:high ] + p .s [id .Low - 1 :id .High ])
665683}
@@ -676,6 +694,10 @@ func (p *Path) Kind() string {
676694 return p .identifierAsString (p .posIdentifierKind )
677695}
678696
697+ func (p * Path ) Layout () string {
698+ return p .identifierAsString (p .posIdentifierLayout )
699+ }
700+
679701func (p * Path ) Lang () string {
680702 return p .identifierAsString (p .posIdentifierLanguage )
681703}
@@ -689,8 +711,8 @@ func (p *Path) Disabled() bool {
689711}
690712
691713func (p * Path ) Identifiers () []string {
692- ids := make ([]string , len (p .identifiers ))
693- for i , id := range p .identifiers {
714+ ids := make ([]string , len (p .identifiersKnown ))
715+ for i , id := range p .identifiersKnown {
694716 ids [i ] = p .s [id .Low :id .High ]
695717 }
696718 return ids
@@ -699,7 +721,7 @@ func (p *Path) Identifiers() []string {
699721func (p * Path ) IdentifiersUnknown () []string {
700722 ids := make ([]string , len (p .identifiersUnknown ))
701723 for i , id := range p .identifiersUnknown {
702- ids [i ] = p .s [p . identifiers [ id ] .Low :p . identifiers [ id ] .High ]
724+ ids [i ] = p .s [id .Low :id .High ]
703725 }
704726 return ids
705727}
@@ -735,12 +757,12 @@ func (p *Path) identifierAsString(i int) string {
735757 return ""
736758 }
737759
738- id := p .identifiers [i ]
760+ id := p .identifiersKnown [i ]
739761 return p .s [id .Low :id .High ]
740762}
741763
742764func (p * Path ) identifierIndex (i int ) int {
743- if i < 0 || i >= len (p .identifiers ) {
765+ if i < 0 || i >= len (p .identifiersKnown ) {
744766 return - 1
745767 }
746768 return i
0 commit comments