Resolve error handling/parser related TODOs
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 23 Oct 2018 12:37:09 +0000 (14:37 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 23 Oct 2018 17:41:22 +0000 (19:41 +0200)
See #5324

14 files changed:
hugofs/rootmapping_fs_test.go
hugolib/hugo_sites_build_errors_test.go
hugolib/hugo_sites_build_test.go
hugolib/page.go
hugolib/page_content.go
hugolib/page_test.go
hugolib/site_render.go
hugolib/site_test.go
parser/pageparser/item.go
parser/pageparser/pagelexer.go
parser/pageparser/pageparser.go
parser/pageparser/pageparser_intro_test.go
tpl/data/data.go
tpl/template.go

index d76e00d2e4dea8e48826d2126b16d79844ba3f4a..e6a0301c9411b1520150abd64ec12697a037b190 100644 (file)
@@ -50,7 +50,7 @@ func TestRootMappingFsDirnames(t *testing.T) {
        fif, err := rfs.Stat(filepath.Join("cf2", testfile))
        assert.NoError(err)
        assert.Equal("myfile.txt", fif.Name())
-       assert.Equal("f2t/myfile.txt", fif.(RealFilenameInfo).RealFilename())
+       assert.Equal(filepath.FromSlash("f2t/myfile.txt"), fif.(RealFilenameInfo).RealFilename())
 
        root, err := rfs.Open(filepathSeparator)
        assert.NoError(err)
index 1e53eb3c46bd12670276eb5c48d5330d8f88eb8a..8e913f061b2a68241a557f2737d9c67373dbd58a 100644 (file)
@@ -191,7 +191,7 @@ func TestSiteBuildErrors(t *testing.T) {
                        },
                        assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
                                assert.Error(err)
-                               assert.Contains(err.Error(), `"content/mytoml.md": render of "page" failed: execute of template failed: panic in Execute`)
+                               assert.Contains(err.Error(), `execute of template failed: panic in Execute`)
                        },
                },
        }
index 727cc6ed9246e7cc1ddb8a9e9cb7ea791e3744a2..f1e317f5967a2874f3d6f25faa4c2ae545eb6dd2 100644 (file)
@@ -631,12 +631,10 @@ func assertShouldNotBuild(t *testing.T, sites *HugoSites) {
        for _, p := range s.rawAllPages {
                // No HTML when not processed
                require.Equal(t, p.shouldBuild(), bytes.Contains(p.workContent, []byte("</")), p.BaseFileName()+": "+string(p.workContent))
-               // TODO(bep) 2errors
-               /*
-                       require.Equal(t, p.shouldBuild(), p.content() != "", fmt.Sprintf("%v:%v", p.content(), p.shouldBuild()))
 
-                       require.Equal(t, p.shouldBuild(), p.content() != "", p.BaseFileName())
-               */
+               require.Equal(t, p.shouldBuild(), p.content() != "", fmt.Sprintf("%v:%v", p.content(), p.shouldBuild()))
+
+               require.Equal(t, p.shouldBuild(), p.content() != "", p.BaseFileName())
 
        }
 }
index df6f88b01eae867159a415d5ade31d56b5abb0ad..f7149ad74410a6528f17f1a6319ea4ebbaa14abd 100644 (file)
@@ -1685,9 +1685,13 @@ func (p *Page) shouldRenderTo(f output.Format) bool {
        return found
 }
 
+// RawContent returns the un-rendered source content without
+// any leading front matter.
 func (p *Page) RawContent() string {
-       // TODO(bep) 2errors
-       return string(p.source.parsed.Input())
+       if p.source.posMainContent == -1 {
+               return ""
+       }
+       return string(p.source.parsed.Input()[p.source.posMainContent:])
 }
 
 func (p *Page) FullFilePath() string {
index be015253bd92db9fd47d500451adf5ab84ff48c0..dab46411e0eb70d439b86e39d9525d477bc72e58 100644 (file)
@@ -46,11 +46,11 @@ type rawPageContent struct {
        hasSummaryDivider bool
 
        // The AST of the parsed page. Contains information about:
-       // shortcBackup3odes, front matter, summary indicators.
-       // TODO(bep) 2errors add this to a new rawPagecContent struct
-       // with frontMatterItem (pos) etc.
-       // * RawContent, RawContentWithoutFrontMatter
+       // shortcodes, front matter, summary indicators.
        parsed pageparser.Result
+
+       // Returns the position in bytes after any front matter.
+       posMainContent int
 }
 
 // TODO(bep) lazy consolidate
@@ -58,6 +58,7 @@ func (p *Page) mapContent() error {
        p.shortcodeState = newShortcodeHandler(p)
        s := p.shortcodeState
        p.renderable = true
+       p.source.posMainContent = -1
 
        result := bp.GetBuffer()
        defer bp.PutBuffer(result)
@@ -81,8 +82,8 @@ Loop:
                case it.Type == pageparser.TypeIgnore:
                case it.Type == pageparser.TypeHTMLComment:
                        // Ignore. This is only a leading Front matter comment.
-               case it.Type == pageparser.TypeHTMLDocument:
-                       // This is HTML only. No shortcode, front matter etc.
+               case it.Type == pageparser.TypeHTMLStart:
+                       // This is HTML without front matter. It can still have shortcodes.
                        p.renderable = false
                        result.Write(it.Val)
                case it.IsFrontMatter():
@@ -99,12 +100,17 @@ Loop:
                                return err
                        }
 
+                       next := iter.Peek()
+                       if !next.IsDone() {
+                               p.source.posMainContent = next.Pos
+                       }
+
                        if !p.shouldBuild() {
                                // Nothing more to do.
                                return nil
                        }
 
-               case it.Type == pageparser.TypeLeadSummaryDivider, it.Type == pageparser.TypeSummaryDividerOrg:
+               case it.Type == pageparser.TypeLeadSummaryDivider:
                        result.Write(internalSummaryDivider)
                        p.source.hasSummaryDivider = true
                        // Need to determine if the page is truncated.
@@ -172,7 +178,6 @@ func (p *Page) parse(reader io.Reader) error {
                parsed: parseResult,
        }
 
-       // TODO(bep) 2errors
        p.lang = p.File.Lang()
 
        if p.s != nil && p.s.owner != nil {
index ced7e78d88296168bf58b0571a7523b5ad6fd3d1..4499a97e07732c9d2e1db3694ec5a929868ef558 100644 (file)
@@ -767,8 +767,7 @@ Simple Page With Some Date`
 }
 
 // Issue #2601
-// TODO(bep) 2errors
-func _TestPageRawContent(t *testing.T) {
+func TestPageRawContent(t *testing.T) {
        t.Parallel()
        cfg, fs := newTestCfg()
 
@@ -784,7 +783,7 @@ title: Raw
        require.Len(t, s.RegularPages, 1)
        p := s.RegularPages[0]
 
-       require.Contains(t, p.RawContent(), "**Raw**")
+       require.Equal(t, p.RawContent(), "**Raw**")
 
 }
 
@@ -1042,8 +1041,7 @@ func TestWordCountWithAllCJKRunesWithoutHasCJKLanguage(t *testing.T) {
        testAllMarkdownEnginesForPages(t, assertFunc, nil, simplePageWithAllCJKRunes)
 }
 
-// TODO(bep) 2errors
-func _TestWordCountWithAllCJKRunesHasCJKLanguage(t *testing.T) {
+func TestWordCountWithAllCJKRunesHasCJKLanguage(t *testing.T) {
        t.Parallel()
        settings := map[string]interface{}{"hasCJKLanguage": true}
 
@@ -1056,8 +1054,7 @@ func _TestWordCountWithAllCJKRunesHasCJKLanguage(t *testing.T) {
        testAllMarkdownEnginesForPages(t, assertFunc, settings, simplePageWithAllCJKRunes)
 }
 
-// TODO(bep) 2errors
-func _TestWordCountWithMainEnglishWithCJKRunes(t *testing.T) {
+func TestWordCountWithMainEnglishWithCJKRunes(t *testing.T) {
        t.Parallel()
        settings := map[string]interface{}{"hasCJKLanguage": true}
 
@@ -1164,7 +1161,6 @@ func TestShouldRenderContent(t *testing.T) {
                render bool
        }{
                {contentNoFrontmatter, true},
-               // TODO(bep) 2errors {invalidFrontmatterShortDelim, true},
                {renderNoFrontmatter, false},
                {contentWithCommentedFrontmatter, true},
                {contentWithCommentedTextFrontmatter, true},
index 6583acd06aa5639d544a6e47ffd41dce2375b01b..a8cdca255e85b8f82ce4cab5f5895fd233417ac2 100644 (file)
@@ -134,8 +134,7 @@ func pageRenderer(s *Site, pages <-chan *Page, results chan<- error, wg *sync.Wa
 
                        if shouldRender {
                                if err := pageOutput.renderResources(); err != nil {
-                                       // TODO(bep) 2errors
-                                       s.Log.ERROR.Printf("Failed to render resources for page %q: %s", page, err)
+                                       s.SendError(page.errorf(err, "failed to render page resources"))
                                        continue
                                }
                        }
@@ -147,7 +146,7 @@ func pageRenderer(s *Site, pages <-chan *Page, results chan<- error, wg *sync.Wa
                        } else {
                                layouts, err = s.layouts(pageOutput)
                                if err != nil {
-                                       s.Log.ERROR.Printf("Failed to resolve layout output %q for page %q: %s", outFormat.Name, page, err)
+                                       s.Log.ERROR.Printf("Failed to resolve layout for output %q for page %q: %s", outFormat.Name, page, err)
                                        continue
                                }
                        }
index 2142025cc6bed085c0060757a1c27eeedaefbdb7..0fd3a397a3ce640562d54b2141960fa2f5b1bc98 100644 (file)
@@ -451,8 +451,7 @@ func doTestSectionNaming(t *testing.T, canonify, uglify, pluralize bool) {
 
 }
 
-// TODO(bep) 2errors
-func _TestSkipRender(t *testing.T) {
+func TestSkipRender(t *testing.T) {
        t.Parallel()
        sources := [][2]string{
                {filepath.FromSlash("sect/doc1.html"), "---\nmarkup: markdown\n---\n# title\nsome *content*"},
index 049db584afa422e95f99669425f6e072ec036a75..0567bd8b9c29dd1fc05ef4ebef609b4860d7a10d 100644 (file)
@@ -103,10 +103,9 @@ const (
        tEOF
 
        // page items
-       TypeHTMLDocument       // document starting with < as first non-whitespace
+       TypeHTMLStart          // document starting with < as first non-whitespace
        TypeHTMLComment        // We ignore leading comments
-       TypeLeadSummaryDivider // <!--more-->
-       TypeSummaryDividerOrg  // # more
+       TypeLeadSummaryDivider // <!--more-->,  # more
        TypeFrontMatterYAML
        TypeFrontMatterTOML
        TypeFrontMatterJSON
index e02475d420eef292cd1fe3630cda68feb798fd59..ddf109b3de07570abf2f1759b47ab86a0fdf0eab 100644 (file)
@@ -48,6 +48,8 @@ type pageLexer struct {
        start      int // item start position
        width      int // width of last element
 
+       // The summary divider to look for.
+       summaryDivider []byte
        // Set when we have parsed any summary divider
        summaryDividerChecked bool
 
@@ -69,7 +71,6 @@ func (l *pageLexer) Input() []byte {
 
 // note: the input position here is normally 0 (start), but
 // can be set if position of first shortcode is known
-// TODO(bep) 2errors byte
 func newPageLexer(input []byte, inputPosition int, stateStart stateFunc) *pageLexer {
        lexer := &pageLexer{
                input:      input,
@@ -117,7 +118,7 @@ var (
        delimTOML         = []byte("+++")
        delimYAML         = []byte("---")
        delimOrg          = []byte("#+")
-       htmlCOmmentStart  = []byte("<!--")
+       htmlCommentStart  = []byte("<!--")
        htmlCOmmentEnd    = []byte("-->")
 )
 
@@ -195,17 +196,18 @@ func (l *pageLexer) consumeCRLF() bool {
 
 func lexMainSection(l *pageLexer) stateFunc {
        // Fast forward as far as possible.
-       var l1, l2, l3 int
-       if !l.summaryDividerChecked {
-               // TODO(bep) 2errors make the summary divider per type
-               l1 = l.index(summaryDivider)
-               l2 = l.index(summaryDividerOrg)
-               if l1 == -1 && l2 == -1 {
+       var l1, l2 int
+
+       if !l.summaryDividerChecked && l.summaryDivider != nil {
+               l1 = l.index(l.summaryDivider)
+               if l1 == -1 {
                        l.summaryDividerChecked = true
                }
        }
-       l3 = l.index(leftDelimSc)
-       skip := minPositiveIndex(l1, l2, l3)
+
+       l2 = l.index(leftDelimSc)
+       skip := minPositiveIndex(l1, l2)
+
        if skip > 0 {
                l.pos += skip
        }
@@ -225,23 +227,14 @@ func lexMainSection(l *pageLexer) stateFunc {
                        return lexShortcodeLeftDelim
                }
 
-               if !l.summaryDividerChecked {
-                       if l.hasPrefix(summaryDivider) {
+               if !l.summaryDividerChecked && l.summaryDivider != nil {
+                       if l.hasPrefix(l.summaryDivider) {
                                if l.pos > l.start {
                                        l.emit(tText)
                                }
                                l.summaryDividerChecked = true
-                               l.pos += len(summaryDivider)
-                               //l.consumeCRLF()
+                               l.pos += len(l.summaryDivider)
                                l.emit(TypeLeadSummaryDivider)
-                       } else if l.hasPrefix(summaryDividerOrg) {
-                               if l.pos > l.start {
-                                       l.emit(tText)
-                               }
-                               l.summaryDividerChecked = true
-                               l.pos += len(summaryDividerOrg)
-                               //l.consumeCRLF()
-                               l.emit(TypeSummaryDividerOrg)
                        }
                }
 
@@ -261,6 +254,8 @@ func (l *pageLexer) isShortCodeStart() bool {
 }
 
 func lexIntroSection(l *pageLexer) stateFunc {
+       l.summaryDivider = summaryDivider
+
 LOOP:
        for {
                r := l.next()
@@ -283,7 +278,7 @@ LOOP:
                        // No front matter.
                        if r == '<' {
                                l.backup()
-                               if l.hasPrefix(htmlCOmmentStart) {
+                               if l.hasPrefix(htmlCommentStart) {
                                        right := l.index(htmlCOmmentEnd)
                                        if right == -1 {
                                                return l.errorf("starting HTML comment with no end")
@@ -291,10 +286,14 @@ LOOP:
                                        l.pos += right + len(htmlCOmmentEnd)
                                        l.emit(TypeHTMLComment)
                                } else {
-                                       // Not need to look further. Hugo treats this as plain HTML,
-                                       // no front matter, no shortcodes, no nothing.
-                                       l.pos = len(l.input)
-                                       l.emit(TypeHTMLDocument)
+                                       if l.pos > l.start {
+                                               l.emit(tText)
+                                       }
+                                       l.next()
+                                       // This is the start of a plain HTML document with no
+                                       // front matter. I still can contain shortcodes, so we
+                                       // have to keep looking.
+                                       l.emit(TypeHTMLStart)
                                }
                        }
                        break LOOP
@@ -365,10 +364,11 @@ func lexFrontMatterOrgMode(l *pageLexer) stateFunc {
                #+DESCRIPTION: Just another golang parser for org content!
        */
 
+       l.summaryDivider = summaryDividerOrg
+
        l.backup()
 
        if !l.hasPrefix(delimOrg) {
-               // TODO(bep) consider error
                return lexMainSection
        }
 
index 6e75f195adeb55cd7e571e1c0f852c82fc18fdd8..75439712166d90723efab931a9fa241066b932e6 100644 (file)
@@ -48,7 +48,7 @@ func Parse(r io.Reader) (Result, error) {
 }
 
 func parseMainSection(input []byte, from int) Result {
-       lexer := newPageLexer(input, from, lexMainSection) // TODO(bep) 2errors
+       lexer := newPageLexer(input, from, lexMainSection)
        lexer.run()
        return lexer
 }
index 32de6dc444698864ab4b91c926c0bf0a40411640..ba4a2c84b761904ce16eff1d194a733f28eca335 100644 (file)
@@ -38,7 +38,7 @@ var (
        tstFrontMatterJSON     = nti(TypeFrontMatterJSON, tstJSON+"\r\n")
        tstSomeText            = nti(tText, "\nSome text.\n")
        tstSummaryDivider      = nti(TypeLeadSummaryDivider, "<!--more-->")
-       tstSummaryDividerOrg   = nti(TypeSummaryDividerOrg, "# more")
+       tstHtmlStart           = nti(TypeHTMLStart, "<")
 
        tstORG = `
 #+TITLE: T1
@@ -54,8 +54,8 @@ var crLfReplacer = strings.NewReplacer("\r", "#", "\n", "$")
 var frontMatterTests = []lexerTest{
        {"empty", "", []Item{tstEOF}},
        {"Byte order mark", "\ufeff\nSome text.\n", []Item{nti(TypeIgnore, "\ufeff"), tstSomeText, tstEOF}},
-       {"HTML Document", `  <html>  `, []Item{nti(TypeHTMLDocument, "  <html>  "), tstEOF}},
-       {"HTML Document 2", `<html><h1>Hugo Rocks</h1></html>`, []Item{nti(TypeHTMLDocument, "<html><h1>Hugo Rocks</h1></html>"), tstEOF}},
+       {"HTML Document", `  <html>  `, []Item{nti(tText, "  "), tstHtmlStart, nti(tText, "html>  "), tstEOF}},
+       {"HTML Document with shortcode", `<html>{{< sc1 >}}</html>`, []Item{tstHtmlStart, nti(tText, "html>"), tstLeftNoMD, tstSC1, tstRightNoMD, nti(tText, "</html>"), tstEOF}},
        {"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}},
@@ -65,7 +65,7 @@ var frontMatterTests = []lexerTest{
        {"TOML front matter", "+++\nfoo = \"bar\"\n+++\n\nSome text.\n", []Item{tstFrontMatterTOML, tstSomeText, tstEOF}},
        {"JSON front matter", tstJSON + "\r\n\nSome text.\n", []Item{tstFrontMatterJSON, tstSomeText, tstEOF}},
        {"ORG front matter", tstORG + "\nSome text.\n", []Item{tstFrontMatterORG, tstSomeText, tstEOF}},
-       {"Summary divider ORG", tstORG + "\nSome text.\n# more\nSome text.\n", []Item{tstFrontMatterORG, tstSomeText, tstSummaryDividerOrg, tstSomeText, tstEOF}},
+       {"Summary divider ORG", tstORG + "\nSome text.\n# more\nSome text.\n", []Item{tstFrontMatterORG, tstSomeText, nti(TypeLeadSummaryDivider, "# more"), tstSomeText, tstEOF}},
        {"Summary divider", "+++\nfoo = \"bar\"\n+++\n\nSome text.\n<!--more-->\nSome text.\n", []Item{tstFrontMatterTOML, tstSomeText, tstSummaryDivider, tstSomeText, tstEOF}},
 }
 
index 03fd27606011a6864fa2f2722eab4a8e62b83ed4..8b3eb8292efd979481ff2b1a74778a8504d0a3c4 100644 (file)
@@ -120,7 +120,6 @@ func (ns *Namespace) GetJSON(urlParts ...string) (v interface{}, err error) {
 
        if err != nil {
                return nil, _errors.Wrapf(err, "failed to get getJSON resource %q", url)
-               return nil, nil
        }
        return
 }
index 12a4607fbf793531f1be0bb17c71e59b101b01bb..9687054934abea9b2cda27e5508cfaaa57545989 100644 (file)
@@ -179,7 +179,7 @@ func (t *TemplateAdapter) addFileContext(name string, inerr error) error {
                }
                return false
        }
-       // TODO(bep) 2errors text vs HTML
+
        fe, ok := herrors.WithFileContext(ferr, realFilename, f, lineMatcher)
        if ok || !hasMaster {
                return fe