Skip to content

Commit

Permalink
parser/pageparser: Fix handling of commented out front matter
Browse files Browse the repository at this point in the history
When the page parser was rewritten in 0.51, this was interpreted literally, but commented out front matter is used in the wild to "hide it from GitHub", e.g:

```
<!--
+++
title = "hello"
+++
-->
```

Fixes gohugoio#5478
  • Loading branch information
bep committed Nov 28, 2018
1 parent 7e75aec commit 7540a62
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 13 deletions.
1 change: 1 addition & 0 deletions go.sum
Expand Up @@ -68,6 +68,7 @@ github.com/magefile/mage v1.4.0 h1:RI7B1CgnPAuu2O9lWszwya61RLmfL0KCdo+QyyI/Bhk=
github.com/magefile/mage v1.4.0/go.mod h1:IUDi13rsHje59lecXokTfGX0QIzO45uVPlXnJYsXepA=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/markbates/inflect v0.0.0-20171215194931-a12c3aec81a6 h1:LZhVjIISSbj8qLf2qDPP0D8z0uvOWAW5C85ly5mJW6c=
github.com/markbates/inflect v0.0.0-20171215194931-a12c3aec81a6/go.mod h1:oTeZL2KHA7CUX6X+fovmK9OvIOFuqu0TwdQrZjLTh88=
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
Expand Down
2 changes: 0 additions & 2 deletions hugolib/page_content.go
Expand Up @@ -83,8 +83,6 @@ Loop:

switch {
case it.Type == pageparser.TypeIgnore:
case it.Type == pageparser.TypeHTMLComment:
// Ignore. This is only a leading Front matter comment.
case it.Type == pageparser.TypeHTMLStart:
// This is HTML without front matter. It can still have shortcodes.
p.renderable = false
Expand Down
27 changes: 27 additions & 0 deletions hugolib/page_test.go
Expand Up @@ -1586,6 +1586,33 @@ CONTENT:{{ .Content }}
)
}

// https://github.com/gohugoio/hugo/issues/5478
func TestPageWithCommentedOutFrontMatter(t *testing.T) {
b := newTestSitesBuilder(t)
b.WithSimpleConfigFile()

b.WithContent("page.md", `<!--
+++
title = "hello"
+++
-->
This is the content.
`)

b.WithTemplatesAdded("layouts/_default/single.html", `
Title: {{ .Title }}
Content:{{ .Content }}
`)

b.CreateSites().Build(BuildCfg{})

b.AssertFileContent("public/page/index.html",
"Title: hello",
"Content:<p>This is the content.</p>",
)

}

// TODO(bep) this may be useful for other tests.
func compareObjects(a interface{}, b interface{}) bool {
aStr := strings.Split(fmt.Sprintf("%v", a), "")
Expand Down
1 change: 0 additions & 1 deletion parser/pageparser/item.go
Expand Up @@ -108,7 +108,6 @@ const (

// page items
TypeHTMLStart // document starting with < as first non-whitespace
TypeHTMLComment // We ignore leading comments
TypeLeadSummaryDivider // <!--more-->, # more
TypeFrontMatterYAML
TypeFrontMatterTOML
Expand Down
43 changes: 35 additions & 8 deletions parser/pageparser/pagelexer.go
Expand Up @@ -53,6 +53,8 @@ type pageLexer struct {
summaryDivider []byte
// Set when we have parsed any summary divider
summaryDividerChecked bool
// Whether we're in a HTML comment.
isInHTMLComment bool

lexerShortcodeState

Expand Down Expand Up @@ -120,7 +122,7 @@ var (
delimYAML = []byte("---")
delimOrg = []byte("#+")
htmlCommentStart = []byte("<!--")
htmlCOmmentEnd = []byte("-->")
htmlCommentEnd = []byte("-->")
)

func (l *pageLexer) next() rune {
Expand Down Expand Up @@ -195,6 +197,15 @@ func (l *pageLexer) consumeCRLF() bool {
return consumed
}

func (l *pageLexer) consumeToNextLine() {
for {
r := l.next()
if r == eof || isEndOfLine(r) {
return
}
}
}

func (l *pageLexer) consumeSpace() {
for {
r := l.next()
Expand All @@ -206,6 +217,10 @@ func (l *pageLexer) consumeSpace() {
}

func lexMainSection(l *pageLexer) stateFunc {
if l.isInHTMLComment {
return lexEndFromtMatterHTMLComment
}

// Fast forward as far as possible.
var l1, l2 int

Expand Down Expand Up @@ -312,16 +327,15 @@ LOOP:
case r == byteOrderMark:
l.emit(TypeIgnore)
case !isSpace(r) && !isEndOfLine(r):
// No front matter.
if r == '<' {
l.backup()
if l.hasPrefix(htmlCommentStart) {
right := l.index(htmlCOmmentEnd)
if right == -1 {
return l.errorf("starting HTML comment with no end")
}
l.pos += right + len(htmlCOmmentEnd)
l.emit(TypeHTMLComment)
// This may be commented out front mattter, which should
// still be read.
l.consumeToNextLine()
l.isInHTMLComment = true
l.emit(TypeIgnore)
continue LOOP
} else {
if l.pos > l.start {
l.emit(tText)
Expand All @@ -341,6 +355,19 @@ LOOP:
return lexMainSection
}

func lexEndFromtMatterHTMLComment(l *pageLexer) stateFunc {
l.isInHTMLComment = false
right := l.index(htmlCommentEnd)
if right == -1 {
return l.errorf("starting HTML comment with no end")
}
l.pos += right + len(htmlCommentEnd)
l.emit(TypeIgnore)

// Now move on to the shortcodes.
return lexMainSection
}

func lexDone(l *pageLexer) stateFunc {

// Done!
Expand Down
4 changes: 2 additions & 2 deletions parser/pageparser/pageparser_intro_test.go
Expand Up @@ -60,7 +60,8 @@ var frontMatterTests = []lexerTest{
{"No front matter", "\nSome text.\n", []Item{tstSomeText, tstEOF}},
{"YAML front matter", "---\nfoo: \"bar\"\n---\n\nSome text.\n", []Item{tstFrontMatterYAML, tstSomeText, tstEOF}},
{"YAML empty front matter", "---\n---\n\nSome text.\n", []Item{nti(TypeFrontMatterYAML, ""), tstSomeText, tstEOF}},
{"YAML commented out front matter", "<!--\n---\nfoo: \"bar\"\n---\n-->\nSome text.\n", []Item{nti(TypeHTMLComment, "<!--\n---\nfoo: \"bar\"\n---\n-->"), tstSomeText, tstEOF}},
{"YAML commented out front matter", "<!--\n---\nfoo: \"bar\"\n---\n-->\nSome text.\n", []Item{nti(TypeIgnore, "<!--\n"), tstFrontMatterYAML, nti(TypeIgnore, "-->"), tstSomeText, tstEOF}},
{"YAML commented out front matter, no end", "<!--\n---\nfoo: \"bar\"\n---\nSome text.\n", []Item{nti(TypeIgnore, "<!--\n"), tstFrontMatterYAML, nti(tError, "starting HTML comment with no end")}},
// Note that we keep all bytes as they are, but we need to handle CRLF
{"YAML front matter CRLF", "---\r\nfoo: \"bar\"\r\n---\n\nSome text.\n", []Item{tstFrontMatterYAMLCRLF, tstSomeText, tstEOF}},
{"TOML front matter", "+++\nfoo = \"bar\"\n+++\n\nSome text.\n", []Item{tstFrontMatterTOML, tstSomeText, tstEOF}},
Expand All @@ -78,7 +79,6 @@ var frontMatterTests = []lexerTest{
func TestFrontMatter(t *testing.T) {
t.Parallel()
for i, test := range frontMatterTests {

items := collect([]byte(test.input), false, lexIntroSection)
if !equal(items, test.items) {
got := crLfReplacer.Replace(fmt.Sprint(items))
Expand Down

0 comments on commit 7540a62

Please sign in to comment.