Fix some inline shortcode issues

Fixes #5645
Fixes #5653
This commit is contained in:
Bjørn Erik Pedersen 2019-01-31 11:53:21 +01:00
parent 8ed2a1caa9
commit c52045bbb3
5 changed files with 66 additions and 23 deletions

View file

@ -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) {
m[key] = func() (string, error) { return renderShortcode(key, sc, nil, p)
return "", nil
}
} else {
m[key] = func() (string, error) {
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 {

View file

@ -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{})
shouldContain := []string{
"Seq: [1 2 3]",
"Param: first",
"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 { if enableInlineShortcodes {
b.AssertFileContent("public/page-md-shortcode/index.html", b.AssertFileContent("public/page-md-shortcode/index.html",
"Page: Hugo", shouldContain...,
"Seq: [1 2 3]", )
"Param: first", b.AssertFileContent("public/index.html",
"Param: second", 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:",
) )
} }
}) })
} }

View file

@ -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()

View file

@ -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 {
items := collect([]byte(test.input), true, lexMainSection) t.Run(test.name, func(t *testing.T) {
if !equal(items, test.items) { items := collect([]byte(test.input), true, lexMainSection)
t.Errorf("[%d] %s: got\n\t%v\nexpected\n\t%v", i, test.name, 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)
}
})
} }
} }

View file

@ -366,7 +366,8 @@ func (t *htmlTemplates) addLateTemplate(name, tpl string) error {
} }
type textTemplate struct { type textTemplate struct {
t *texttemplate.Template mu sync.RWMutex
t *texttemplate.Template
} }
func (t *textTemplate) Parse(name, tpl string) (tpl.Template, error) { func (t *textTemplate) Parse(name, tpl string) (tpl.Template, error) {
@ -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