mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
parent
8ed2a1caa9
commit
c52045bbb3
5 changed files with 66 additions and 23 deletions
|
@ -338,14 +338,9 @@ func (s *shortcodeHandler) prepareShortcodeForPage(placeholder string, sc *short
|
||||||
|
|
||||||
if sc.isInline {
|
if sc.isInline {
|
||||||
key := newScKeyFromLangAndOutputFormat(lang, p.outputFormats[0], placeholder)
|
key := newScKeyFromLangAndOutputFormat(lang, p.outputFormats[0], placeholder)
|
||||||
if !s.enableInlineShortcodes {
|
|
||||||
m[key] = func() (string, error) {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m[key] = func() (string, error) {
|
m[key] = func() (string, error) {
|
||||||
return renderShortcode(key, sc, nil, p)
|
return renderShortcode(key, sc, nil, p)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
@ -372,6 +367,9 @@ func renderShortcode(
|
||||||
var tmpl tpl.Template
|
var tmpl tpl.Template
|
||||||
|
|
||||||
if sc.isInline {
|
if sc.isInline {
|
||||||
|
if !p.s.enableInlineShortcodes {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
templName := path.Join("_inline_shortcode", p.Path(), sc.name)
|
templName := path.Join("_inline_shortcode", p.Path(), sc.name)
|
||||||
if sc.isClosing {
|
if sc.isClosing {
|
||||||
templStr := sc.innerString()
|
templStr := sc.innerString()
|
||||||
|
@ -542,6 +540,10 @@ func (s *shortcodeHandler) contentShortcodesForOutputFormat(f output.Format) *or
|
||||||
if !found && key.Suffix != "html" {
|
if !found && key.Suffix != "html" {
|
||||||
key.Suffix = "html"
|
key.Suffix = "html"
|
||||||
renderFn, found = s.contentShortcodes.Get(key)
|
renderFn, found = s.contentShortcodes.Get(key)
|
||||||
|
if !found {
|
||||||
|
key.OutputFormat = "HTML"
|
||||||
|
renderFn, found = s.contentShortcodes.Get(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
|
|
|
@ -1076,40 +1076,67 @@ enableInlineShortcodes = %t
|
||||||
|
|
||||||
b := newTestSitesBuilder(t)
|
b := newTestSitesBuilder(t)
|
||||||
b.WithConfigFile("toml", conf)
|
b.WithConfigFile("toml", conf)
|
||||||
b.WithContent("page-md-shortcode.md", `---
|
|
||||||
title: "Hugo"
|
|
||||||
---
|
|
||||||
|
|
||||||
FIRST:{{< myshort.inline "first" >}}
|
shortcodeContent := `FIRST:{{< myshort.inline "first" >}}
|
||||||
Page: {{ .Page.Title }}
|
Page: {{ .Page.Title }}
|
||||||
Seq: {{ seq 3 }}
|
Seq: {{ seq 3 }}
|
||||||
Param: {{ .Get 0 }}
|
Param: {{ .Get 0 }}
|
||||||
{{< /myshort.inline >}}:END:
|
{{< /myshort.inline >}}:END:
|
||||||
|
|
||||||
SECOND:{{< myshort.inline "second" />}}:END
|
SECOND:{{< myshort.inline "second" />}}:END
|
||||||
|
NEW INLINE: {{< n1.inline "5" >}}W1: {{ seq (.Get 0) }}{{< /n1.inline >}}:END:
|
||||||
|
INLINE IN INNER: {{< outer >}}{{< n2.inline >}}W2: {{ seq 4 }}{{< /n2.inline >}}{{< /outer >}}:END:
|
||||||
|
REUSED INLINE IN INNER: {{< outer >}}{{< n1.inline "3" />}}{{< /outer >}}:END:
|
||||||
|
`
|
||||||
|
|
||||||
`)
|
b.WithContent("page-md-shortcode.md", `---
|
||||||
|
title: "Hugo"
|
||||||
|
---
|
||||||
|
`+shortcodeContent)
|
||||||
|
|
||||||
|
b.WithContent("_index.md", `---
|
||||||
|
title: "Hugo Home"
|
||||||
|
---
|
||||||
|
|
||||||
|
`+shortcodeContent)
|
||||||
|
|
||||||
b.WithTemplatesAdded("layouts/_default/single.html", `
|
b.WithTemplatesAdded("layouts/_default/single.html", `
|
||||||
CONTENT:{{ .Content }}
|
CONTENT:{{ .Content }}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
b.WithTemplatesAdded("layouts/index.html", `
|
||||||
|
CONTENT:{{ .Content }}
|
||||||
|
`)
|
||||||
|
|
||||||
|
b.WithTemplatesAdded("layouts/shortcodes/outer.html", `Inner: {{ .Inner }}`)
|
||||||
|
|
||||||
b.CreateSites().Build(BuildCfg{})
|
b.CreateSites().Build(BuildCfg{})
|
||||||
|
|
||||||
if enableInlineShortcodes {
|
shouldContain := []string{
|
||||||
b.AssertFileContent("public/page-md-shortcode/index.html",
|
|
||||||
"Page: Hugo",
|
|
||||||
"Seq: [1 2 3]",
|
"Seq: [1 2 3]",
|
||||||
"Param: first",
|
"Param: first",
|
||||||
"Param: second",
|
"Param: second",
|
||||||
|
"NEW INLINE: W1: [1 2 3 4 5]",
|
||||||
|
"INLINE IN INNER: Inner: W2: [1 2 3 4]",
|
||||||
|
"REUSED INLINE IN INNER: Inner: W1: [1 2 3]",
|
||||||
|
}
|
||||||
|
|
||||||
|
if enableInlineShortcodes {
|
||||||
|
b.AssertFileContent("public/page-md-shortcode/index.html",
|
||||||
|
shouldContain...,
|
||||||
|
)
|
||||||
|
b.AssertFileContent("public/index.html",
|
||||||
|
shouldContain...,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
b.AssertFileContent("public/page-md-shortcode/index.html",
|
b.AssertFileContent("public/page-md-shortcode/index.html",
|
||||||
"FIRST::END",
|
"FIRST::END",
|
||||||
"SECOND::END",
|
"SECOND::END",
|
||||||
|
"NEW INLINE: :END",
|
||||||
|
"INLINE IN INNER: Inner: :END:",
|
||||||
|
"REUSED INLINE IN INNER: Inner: :END:",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,6 +280,7 @@ func lexInsideShortcode(l *pageLexer) stateFunc {
|
||||||
return l.errorf("got closing shortcode, but none is open")
|
return l.errorf("got closing shortcode, but none is open")
|
||||||
}
|
}
|
||||||
l.closingState++
|
l.closingState++
|
||||||
|
l.isInline = false
|
||||||
l.emit(tScClose)
|
l.emit(tScClose)
|
||||||
case r == '\\':
|
case r == '\\':
|
||||||
l.ignore()
|
l.ignore()
|
||||||
|
|
|
@ -24,6 +24,7 @@ var (
|
||||||
tstSCClose = nti(tScClose, "/")
|
tstSCClose = nti(tScClose, "/")
|
||||||
tstSC1 = nti(tScName, "sc1")
|
tstSC1 = nti(tScName, "sc1")
|
||||||
tstSC1Inline = nti(tScNameInline, "sc1.inline")
|
tstSC1Inline = nti(tScNameInline, "sc1.inline")
|
||||||
|
tstSC2Inline = nti(tScNameInline, "sc2.inline")
|
||||||
tstSC2 = nti(tScName, "sc2")
|
tstSC2 = nti(tScName, "sc2")
|
||||||
tstSC3 = nti(tScName, "sc3")
|
tstSC3 = nti(tScName, "sc3")
|
||||||
tstSCSlash = nti(tScName, "sc/sub")
|
tstSCSlash = nti(tScName, "sc/sub")
|
||||||
|
@ -152,6 +153,9 @@ var shortCodeLexerTests = []lexerTest{
|
||||||
{"basic inline", `{{< sc1.inline >}}Hello World{{< /sc1.inline >}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSCClose, tstSC1Inline, tstRightNoMD, tstEOF}},
|
{"basic inline", `{{< sc1.inline >}}Hello World{{< /sc1.inline >}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSCClose, tstSC1Inline, tstRightNoMD, tstEOF}},
|
||||||
{"basic inline with space", `{{< sc1.inline >}}Hello World{{< / sc1.inline >}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSCClose, tstSC1Inline, tstRightNoMD, tstEOF}},
|
{"basic inline with space", `{{< sc1.inline >}}Hello World{{< / sc1.inline >}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSCClose, tstSC1Inline, tstRightNoMD, tstEOF}},
|
||||||
{"inline self closing", `{{< sc1.inline >}}Hello World{{< /sc1.inline >}}Hello World{{< sc1.inline />}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSCClose, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSC1Inline, tstSCClose, tstRightNoMD, tstEOF}},
|
{"inline self closing", `{{< sc1.inline >}}Hello World{{< /sc1.inline >}}Hello World{{< sc1.inline />}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSCClose, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSC1Inline, tstSCClose, tstRightNoMD, tstEOF}},
|
||||||
|
{"inline self closing, then a new inline", `{{< sc1.inline >}}Hello World{{< /sc1.inline >}}Hello World{{< sc1.inline />}}{{< sc2.inline >}}Hello World{{< /sc2.inline >}}`, []Item{
|
||||||
|
tstLeftNoMD, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSCClose, tstSC1Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSC1Inline, tstSCClose, tstRightNoMD,
|
||||||
|
tstLeftNoMD, tstSC2Inline, tstRightNoMD, tstText, tstLeftNoMD, tstSCClose, tstSC2Inline, tstRightNoMD, tstEOF}},
|
||||||
{"inline with template syntax", `{{< sc1.inline >}}{{ .Get 0 }}{{ .Get 1 }}{{< /sc1.inline >}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, nti(tText, "{{ .Get 0 }}"), nti(tText, "{{ .Get 1 }}"), tstLeftNoMD, tstSCClose, tstSC1Inline, tstRightNoMD, tstEOF}},
|
{"inline with template syntax", `{{< sc1.inline >}}{{ .Get 0 }}{{ .Get 1 }}{{< /sc1.inline >}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, nti(tText, "{{ .Get 0 }}"), nti(tText, "{{ .Get 1 }}"), tstLeftNoMD, tstSCClose, tstSC1Inline, tstRightNoMD, tstEOF}},
|
||||||
{"inline with nested shortcode (not supported)", `{{< sc1.inline >}}Hello World{{< sc1 >}}{{< /sc1.inline >}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, tstText, nti(tError, "inline shortcodes do not support nesting")}},
|
{"inline with nested shortcode (not supported)", `{{< sc1.inline >}}Hello World{{< sc1 >}}{{< /sc1.inline >}}`, []Item{tstLeftNoMD, tstSC1Inline, tstRightNoMD, tstText, nti(tError, "inline shortcodes do not support nesting")}},
|
||||||
{"inline case mismatch", `{{< sc1.Inline >}}Hello World{{< /sc1.Inline >}}`, []Item{tstLeftNoMD, nti(tError, "period in shortcode name only allowed for inline identifiers")}},
|
{"inline case mismatch", `{{< sc1.Inline >}}Hello World{{< /sc1.Inline >}}`, []Item{tstLeftNoMD, nti(tError, "period in shortcode name only allowed for inline identifiers")}},
|
||||||
|
@ -160,10 +164,12 @@ var shortCodeLexerTests = []lexerTest{
|
||||||
func TestShortcodeLexer(t *testing.T) {
|
func TestShortcodeLexer(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
for i, test := range shortCodeLexerTests {
|
for i, test := range shortCodeLexerTests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
items := collect([]byte(test.input), true, lexMainSection)
|
items := collect([]byte(test.input), true, lexMainSection)
|
||||||
if !equal(items, test.items) {
|
if !equal(items, test.items) {
|
||||||
t.Errorf("[%d] %s: got\n\t%v\nexpected\n\t%v", i, test.name, items, test.items)
|
t.Errorf("[%d] %s: got\n\t%v\nexpected\n\t%v", i, test.name, items, test.items)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -366,6 +366,7 @@ func (t *htmlTemplates) addLateTemplate(name, tpl string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type textTemplate struct {
|
type textTemplate struct {
|
||||||
|
mu sync.RWMutex
|
||||||
t *texttemplate.Template
|
t *texttemplate.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,11 +375,17 @@ func (t *textTemplate) Parse(name, tpl string) (tpl.Template, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textTemplate) Lookup(name string) (tpl.Template, bool) {
|
func (t *textTemplate) Lookup(name string) (tpl.Template, bool) {
|
||||||
|
t.mu.RLock()
|
||||||
|
defer t.mu.RUnlock()
|
||||||
|
|
||||||
tpl := t.t.Lookup(name)
|
tpl := t.t.Lookup(name)
|
||||||
return tpl, tpl != nil
|
return tpl, tpl != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textTemplate) parSeIn(tt *texttemplate.Template, name, tpl string) (*texttemplate.Template, error) {
|
func (t *textTemplate) parSeIn(tt *texttemplate.Template, name, tpl string) (*texttemplate.Template, error) {
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
|
||||||
templ, err := tt.New(name).Parse(tpl)
|
templ, err := tt.New(name).Parse(tpl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
Loading…
Reference in a new issue