hugolib: Make RawContent raw again

This was a regression introduced in Hugo 0.17.

Fixes #2601
This commit is contained in:
Bjørn Erik Pedersen 2016-12-01 10:21:49 +01:00
parent 971d1baf13
commit 2f026ab3f3
5 changed files with 53 additions and 22 deletions

View file

@ -72,6 +72,9 @@ func (h htmlHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
panic(fmt.Sprintf("Page %q already rendered, does not need conversion", p.BaseFileName())) panic(fmt.Sprintf("Page %q already rendered, does not need conversion", p.BaseFileName()))
} }
// Work on a copy of the raw content from now on.
p.createWorkContentCopy()
p.ProcessShortcodes(t) p.ProcessShortcodes(t)
return HandledResult{err: nil} return HandledResult{err: nil}
@ -109,19 +112,22 @@ func commonConvert(p *Page, t tpl.Template) HandledResult {
panic(fmt.Sprintf("Page %q already rendered, does not need conversion", p.BaseFileName())) panic(fmt.Sprintf("Page %q already rendered, does not need conversion", p.BaseFileName()))
} }
// Work on a copy of the raw content from now on.
p.createWorkContentCopy()
p.ProcessShortcodes(t) p.ProcessShortcodes(t)
// TODO(bep) these page handlers need to be re-evaluated, as it is hard to // TODO(bep) these page handlers need to be re-evaluated, as it is hard to
// process a page in isolation. See the new preRender func. // process a page in isolation. See the new preRender func.
if viper.GetBool("enableEmoji") { if viper.GetBool("enableEmoji") {
p.rawContent = helpers.Emojify(p.rawContent) p.workContent = helpers.Emojify(p.workContent)
} }
// We have to replace the <!--more--> with something that survives all the // We have to replace the <!--more--> with something that survives all the
// rendering engines. // rendering engines.
// TODO(bep) inline replace // TODO(bep) inline replace
p.rawContent = bytes.Replace(p.rawContent, []byte(helpers.SummaryDivider), internalSummaryDivider, 1) p.workContent = bytes.Replace(p.workContent, []byte(helpers.SummaryDivider), internalSummaryDivider, 1)
p.rawContent = p.renderContent(p.rawContent) p.workContent = p.renderContent(p.workContent)
return HandledResult{err: nil} return HandledResult{err: nil}
} }

View file

@ -368,49 +368,49 @@ func (s *Site) preparePagesForRender(cfg *BuildCfg) {
// If in watch mode, we need to keep the original so we can // If in watch mode, we need to keep the original so we can
// repeat this process on rebuild. // repeat this process on rebuild.
var rawContentCopy []byte var workContentCopy []byte
if cfg.Watching { if cfg.Watching {
rawContentCopy = make([]byte, len(p.rawContent)) workContentCopy = make([]byte, len(p.workContent))
copy(rawContentCopy, p.rawContent) copy(workContentCopy, p.workContent)
} else { } else {
// Just reuse the same slice. // Just reuse the same slice.
rawContentCopy = p.rawContent workContentCopy = p.workContent
} }
if p.Markup == "markdown" { if p.Markup == "markdown" {
tmpContent, tmpTableOfContents := helpers.ExtractTOC(rawContentCopy) tmpContent, tmpTableOfContents := helpers.ExtractTOC(workContentCopy)
p.TableOfContents = helpers.BytesToHTML(tmpTableOfContents) p.TableOfContents = helpers.BytesToHTML(tmpTableOfContents)
rawContentCopy = tmpContent workContentCopy = tmpContent
} }
var err error var err error
if rawContentCopy, err = handleShortcodes(p, s.owner.tmpl, rawContentCopy); err != nil { if workContentCopy, err = handleShortcodes(p, s.owner.tmpl, workContentCopy); err != nil {
jww.ERROR.Printf("Failed to handle shortcodes for page %s: %s", p.BaseFileName(), err) jww.ERROR.Printf("Failed to handle shortcodes for page %s: %s", p.BaseFileName(), err)
} }
if p.Markup != "html" { if p.Markup != "html" {
// Now we know enough to create a summary of the page and count some words // Now we know enough to create a summary of the page and count some words
summaryContent, err := p.setUserDefinedSummaryIfProvided(rawContentCopy) summaryContent, err := p.setUserDefinedSummaryIfProvided(workContentCopy)
if err != nil { if err != nil {
jww.ERROR.Printf("Failed to set user defined summary for page %q: %s", p.Path(), err) jww.ERROR.Printf("Failed to set user defined summary for page %q: %s", p.Path(), err)
} else if summaryContent != nil { } else if summaryContent != nil {
rawContentCopy = summaryContent.content workContentCopy = summaryContent.content
} }
p.Content = helpers.BytesToHTML(rawContentCopy) p.Content = helpers.BytesToHTML(workContentCopy)
if summaryContent == nil { if summaryContent == nil {
p.setAutoSummary() p.setAutoSummary()
} }
} else { } else {
p.Content = helpers.BytesToHTML(rawContentCopy) p.Content = helpers.BytesToHTML(workContentCopy)
} }
// no need for this anymore // no need for this anymore
rawContentCopy = nil workContentCopy = nil
//analyze for raw stats //analyze for raw stats
p.analyzePage() p.analyzePage()

View file

@ -560,7 +560,7 @@ func assertShouldNotBuild(t *testing.T, sites *HugoSites) {
for _, p := range s.rawAllPages { for _, p := range s.rawAllPages {
// No HTML when not processed // No HTML when not processed
require.Equal(t, p.shouldBuild(), bytes.Contains(p.rawContent, []byte("</")), p.BaseFileName()+": "+string(p.rawContent)) require.Equal(t, p.shouldBuild(), bytes.Contains(p.workContent, []byte("</")), p.BaseFileName()+": "+string(p.workContent))
require.Equal(t, p.shouldBuild(), p.Content != "", p.BaseFileName()) require.Equal(t, p.shouldBuild(), p.Content != "", p.BaseFileName())
require.Equal(t, p.shouldBuild(), p.Content != "", p.BaseFileName()) require.Equal(t, p.shouldBuild(), p.Content != "", p.BaseFileName())

View file

@ -129,12 +129,12 @@ type Page struct {
frontmatter []byte frontmatter []byte
// rawContent isn't "raw" as in the same as in the content file. // rawContent is the raw content read from the content file.
// Hugo cares about memory consumption, so we make changes to it to do
// markdown rendering etc., but it is "raw enough" so we can do rebuilds
// when shortcode changes etc.
rawContent []byte rawContent []byte
// workContent is a copy of rawContent that may be mutated during site build.
workContent []byte
// state telling if this is a "new page" or if we have rendered it previously. // state telling if this is a "new page" or if we have rendered it previously.
rendered bool rendered bool
@ -292,6 +292,11 @@ func (ps Pages) FindPagePos(page *Page) int {
return -1 return -1
} }
func (p *Page) createWorkContentCopy() {
p.workContent = make([]byte, len(p.rawContent))
copy(p.workContent, p.rawContent)
}
func (p *Page) Plain() string { func (p *Page) Plain() string {
p.initPlain() p.initPlain()
return p.plain return p.plain
@ -1389,8 +1394,8 @@ func (p *Page) SaveSource() error {
} }
func (p *Page) ProcessShortcodes(t tpl.Template) { func (p *Page) ProcessShortcodes(t tpl.Template) {
tmpContent, tmpContentShortCodes, _ := extractAndRenderShortcodes(string(p.rawContent), p, t) tmpContent, tmpContentShortCodes, _ := extractAndRenderShortcodes(string(p.workContent), p, t)
p.rawContent = []byte(tmpContent) p.workContent = []byte(tmpContent)
p.contentShortCodes = tmpContentShortCodes p.contentShortCodes = tmpContentShortCodes
} }

View file

@ -753,6 +753,26 @@ func TestPageWithDelimiterForMarkdownThatCrossesBorder(t *testing.T) {
} }
} }
// Issue #2601
func TestPageRawContent(t *testing.T) {
s := newSiteFromSources("raw.md", `---
title: Raw
---
**Raw**`)
writeSource(t, filepath.Join("layouts", "_default", "single.html"), `{{ .RawContent }}`)
if err := buildSiteSkipRender(s); err != nil {
t.Fatalf("Failed to build site: %s", err)
}
require.Len(t, s.RegularPages, 1)
p := s.RegularPages[0]
require.Contains(t, p.RawContent(), "**Raw**")
}
func TestPageWithShortCodeInSummary(t *testing.T) { func TestPageWithShortCodeInSummary(t *testing.T) {
assertFunc := func(t *testing.T, ext string, pages Pages) { assertFunc := func(t *testing.T, ext string, pages Pages) {