summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-10-21 12:20:21 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-10-22 20:46:14 +0200
commitd1661b823af25c50d3bbe5366ea40a3cdd52e237 (patch)
treecd84d18229fb9c294ff1be56d7c0ce92a8f46761
parent7930d2132a3c36c1aaca20f16f56978c84656b0a (diff)
hugolib: Continue the file context/line number errors work
See #5324
-rw-r--r--commands/server_errors.go2
-rw-r--r--common/herrors/error_locator.go49
-rw-r--r--common/herrors/error_locator_test.go6
-rw-r--r--common/herrors/file_error.go41
-rw-r--r--common/herrors/file_error_test.go19
-rw-r--r--common/herrors/line_number_extractors.go27
-rw-r--r--deps/deps.go30
-rw-r--r--hugolib/hugo_sites.go36
-rw-r--r--hugolib/hugo_sites_build.go75
-rw-r--r--hugolib/hugo_sites_build_errors_test.go87
-rw-r--r--hugolib/page.go53
-rw-r--r--hugolib/page_content.go35
-rw-r--r--hugolib/page_errors.go47
-rw-r--r--hugolib/shortcode.go30
-rw-r--r--hugolib/site.go39
-rw-r--r--hugolib/testhelpers_test.go6
-rw-r--r--parser/pageparser/pagelexer.go17
-rw-r--r--parser/pageparser/pageparser.go5
-rw-r--r--parser/pageparser/pageparser_intro_test.go8
-rw-r--r--tpl/data/data.go24
-rw-r--r--tpl/data/data_test.go21
-rw-r--r--tpl/template.go19
-rw-r--r--tpl/tplimpl/template_errors.go4
23 files changed, 444 insertions, 236 deletions
diff --git a/commands/server_errors.go b/commands/server_errors.go
index 1a469dac8..8ee02e5f2 100644
--- a/commands/server_errors.go
+++ b/commands/server_errors.go
@@ -72,7 +72,7 @@ var buildErrorTemplate = `<!doctype html>
<main>
{{ highlight .Error "apl" "noclasses=true,style=monokai" }}
{{ with .File }}
- {{ $params := printf "noclasses=true,style=monokai,linenos=table,hl_lines=%d,linenostart=%d" (add .Pos 1) .LineNumber }}
+ {{ $params := printf "noclasses=true,style=monokai,linenos=table,hl_lines=%d,linenostart=%d" (add .Pos 1) (sub .LineNumber .Pos) }}
{{ $lexer := .ChromaLexer | default "go-html-template" }}
{{ highlight (delimit .Lines "\n") $lexer $params }}
{{ end }}
diff --git a/common/herrors/error_locator.go b/common/herrors/error_locator.go
index cc41e8868..306f8f46b 100644
--- a/common/herrors/error_locator.go
+++ b/common/herrors/error_locator.go
@@ -16,12 +16,17 @@ package herrors
import (
"bufio"
+ "fmt"
"io"
"strings"
+ "github.com/gohugoio/hugo/helpers"
+
"github.com/spf13/afero"
)
+var fileErrorFormat = "\"%s:%d:%d\": %s"
+
// LineMatcher is used to match a line with an error.
type LineMatcher func(le FileError, lineNumber int, line string) bool
@@ -34,6 +39,8 @@ var SimpleLineMatcher = func(le FileError, lineNumber int, line string) bool {
// ErrorContext contains contextual information about an error. This will
// typically be the lines surrounding some problem in a file.
type ErrorContext struct {
+ // The source filename.
+ Filename string
// If a match will contain the matched line and up to 2 lines before and after.
// Will be empty if no match.
@@ -45,6 +52,9 @@ type ErrorContext struct {
// The linenumber in the source file from where the Lines start. Starting at 1.
LineNumber int
+ // The column number in the source file. Starting at 1.
+ ColumnNumber int
+
// The lexer to use for syntax highlighting.
// https://gohugo.io/content-management/syntax-highlighting/#list-of-chroma-highlighting-languages
ChromaLexer string
@@ -60,7 +70,7 @@ type ErrorWithFileContext struct {
}
func (e *ErrorWithFileContext) Error() string {
- return e.cause.Error()
+ return fmt.Sprintf(fileErrorFormat, e.Filename, e.LineNumber, e.ColumnNumber, e.cause.Error())
}
func (e *ErrorWithFileContext) Cause() error {
@@ -69,39 +79,40 @@ func (e *ErrorWithFileContext) Cause() error {
// WithFileContextForFile will try to add a file context with lines matching the given matcher.
// If no match could be found, the original error is returned with false as the second return value.
-func WithFileContextForFile(e error, filename string, fs afero.Fs, chromaLexer string, matcher LineMatcher) (error, bool) {
+func WithFileContextForFile(e error, realFilename, filename string, fs afero.Fs, matcher LineMatcher) (error, bool) {
f, err := fs.Open(filename)
if err != nil {
return e, false
}
defer f.Close()
- return WithFileContext(e, f, chromaLexer, matcher)
+ return WithFileContext(e, realFilename, f, matcher)
}
// WithFileContextForFile will try to add a file context with lines matching the given matcher.
// If no match could be found, the original error is returned with false as the second return value.
-func WithFileContext(e error, r io.Reader, chromaLexer string, matcher LineMatcher) (error, bool) {
+func WithFileContext(e error, realFilename string, r io.Reader, matcher LineMatcher) (error, bool) {
if e == nil {
panic("error missing")
}
le := UnwrapFileError(e)
if le == nil {
var ok bool
- if le, ok = ToFileError("bash", e).(FileError); !ok {
+ if le, ok = ToFileError("", e).(FileError); !ok {
return e, false
}
}
errCtx := locateError(r, le, matcher)
+ errCtx.Filename = realFilename
if errCtx.LineNumber == -1 {
return e, false
}
- if chromaLexer != "" {
- errCtx.ChromaLexer = chromaLexer
- } else {
+ if le.Type() != "" {
errCtx.ChromaLexer = chromaLexerFromType(le.Type())
+ } else {
+ errCtx.ChromaLexer = chromaLexerFromFilename(realFilename)
}
return &ErrorWithFileContext{cause: e, ErrorContext: errCtx}, true
@@ -124,9 +135,22 @@ func UnwrapErrorWithFileContext(err error) *ErrorWithFileContext {
}
func chromaLexerFromType(fileType string) string {
+ switch fileType {
+ case "html", "htm":
+ return "go-html-template"
+ }
return fileType
}
+func chromaLexerFromFilename(filename string) string {
+ if strings.Contains(filename, "layouts") {
+ return "go-html-template"
+ }
+
+ ext := helpers.ExtNoDelimiter(filename)
+ return chromaLexerFromType(ext)
+}
+
func locateErrorInString(le FileError, src string, matcher LineMatcher) ErrorContext {
return locateError(strings.NewReader(src), nil, matcher)
}
@@ -135,6 +159,11 @@ func locateError(r io.Reader, le FileError, matches LineMatcher) ErrorContext {
var errCtx ErrorContext
s := bufio.NewScanner(r)
+ errCtx.ColumnNumber = 1
+ if le != nil {
+ errCtx.ColumnNumber = le.ColumnNumber()
+ }
+
lineNo := 0
var buff [6]string
@@ -152,7 +181,7 @@ func locateError(r io.Reader, le FileError, matches LineMatcher) ErrorContext {
if errCtx.Pos == -1 && matches(le, lineNo, txt) {
errCtx.Pos = i
- errCtx.LineNumber = lineNo - i
+ errCtx.LineNumber = lineNo
}
if errCtx.Pos == -1 && i == 2 {
@@ -171,7 +200,7 @@ func locateError(r io.Reader, le FileError, matches LineMatcher) ErrorContext {
if matches(le, lineNo, "") {
buff[i] = ""
errCtx.Pos = i
- errCtx.LineNumber = lineNo - 1
+ errCtx.LineNumber = lineNo
i++
}
diff --git a/common/herrors/error_locator_test.go b/common/herrors/error_locator_test.go
index 6c879727e..caa6e6385 100644
--- a/common/herrors/error_locator_test.go
+++ b/common/herrors/error_locator_test.go
@@ -41,7 +41,7 @@ LINE 8
location := locateErrorInString(nil, lines, lineMatcher)
assert.Equal([]string{"LINE 3", "LINE 4", "This is THEONE", "LINE 6", "LINE 7"}, location.Lines)
- assert.Equal(3, location.LineNumber)
+ assert.Equal(5, location.LineNumber)
assert.Equal(2, location.Pos)
assert.Equal([]string{"This is THEONE"}, locateErrorInString(nil, `This is THEONE`, lineMatcher).Lines)
@@ -92,7 +92,7 @@ I
J`, lineMatcher)
assert.Equal([]string{"D", "E", "F", "G", "H"}, location.Lines)
- assert.Equal(4, location.LineNumber)
+ assert.Equal(6, location.LineNumber)
assert.Equal(2, location.Pos)
// Test match EOF
@@ -106,7 +106,7 @@ C
`, lineMatcher)
assert.Equal([]string{"B", "C", ""}, location.Lines)
- assert.Equal(3, location.LineNumber)
+ assert.Equal(4, location.LineNumber)
assert.Equal(2, location.Pos)
}
diff --git a/common/herrors/file_error.go b/common/herrors/file_error.go
index f29f91fcc..86ccfcefb 100644
--- a/common/herrors/file_error.go
+++ b/common/herrors/file_error.go
@@ -13,10 +13,6 @@
package herrors
-import (
- "fmt"
-)
-
var _ causer = (*fileError)(nil)
// FileError represents an error when handling a file: Parsing a config file,
@@ -27,6 +23,8 @@ type FileError interface {
// LineNumber gets the error location, starting at line 1.
LineNumber() int
+ ColumnNumber() int
+
// A string identifying the type of file, e.g. JSON, TOML, markdown etc.
Type() string
}
@@ -34,9 +32,9 @@ type FileError interface {
var _ FileError = (*fileError)(nil)
type fileError struct {
- lineNumber int
- fileType string
- msg string
+ lineNumber int
+ columnNumber int
+ fileType string
cause error
}
@@ -45,32 +43,28 @@ func (e *fileError) LineNumber() int {
return e.lineNumber
}
+func (e *fileError) ColumnNumber() int {
+ return e.columnNumber
+}
+
func (e *fileError) Type() string {
return e.fileType
}
func (e *fileError) Error() string {
- return e.msg
+ if e.cause == nil {
+ return ""
+ }
+ return e.cause.Error()
}
func (f *fileError) Cause() error {
return f.cause
}
-func (e *fileError) Format(s fmt.State, verb rune) {
- switch verb {
- case 'v':
- fallthrough
- case 's':
- fmt.Fprintf(s, "%s:%d: %s:%s", e.fileType, e.lineNumber, e.msg, e.cause)
- case 'q':
- fmt.Fprintf(s, "%q:%d: %q:%q", e.fileType, e.lineNumber, e.msg, e.cause)
- }
-}
-
// NewFileError creates a new FileError.
-func NewFileError(fileType string, lineNumber int, msg string, err error) FileError {
- return &fileError{cause: err, fileType: fileType, lineNumber: lineNumber, msg: msg}
+func NewFileError(fileType string, lineNumber, columnNumber int, err error) FileError {
+ return &fileError{cause: err, fileType: fileType, lineNumber: lineNumber, columnNumber: columnNumber}
}
// UnwrapFileError tries to unwrap a FileError from err.
@@ -101,9 +95,10 @@ func ToFileError(fileType string, err error) error {
// If will fall back to returning the original error if a line number cannot be extracted.
func ToFileErrorWithOffset(fileType string, err error, offset int) error {
for _, handle := range lineNumberExtractors {
- lno, msg := handle(err, offset)
+
+ lno, col := handle(err)
if lno > 0 {
- return NewFileError(fileType, lno, msg, err)
+ return NewFileError(fileType, lno+offset, col, err)
}
}
// Fall back to the original.
diff --git a/common/herrors/file_error_test.go b/common/herrors/file_error_test.go
index e266ff1dc..0d4e82f66 100644
--- a/common/herrors/file_error_test.go
+++ b/common/herrors/file_error_test.go
@@ -28,16 +28,16 @@ func TestToLineNumberError(t *testing.T) {
assert := require.New(t)
for i, test := range []struct {
- in error
- offset int
- lineNumber int
+ in error
+ offset int
+ lineNumber int
+ columnNumber int
}{
- {errors.New("no line number for you"), 0, -1},
- {errors.New(`template: _default/single.html:2:15: executing "_default/single.html" at <.Titles>: can't evaluate field`), 0, 2},
- {errors.New("parse failed: template: _default/bundle-resource-meta.html:11: unexpected in operand"), 0, 11},
- {errors.New(`failed:: template: _default/bundle-resource-meta.html:2:7: executing "main" at <.Titles>`), 0, 2},
- {errors.New("error in front matter: Near line 32 (last key parsed 'title')"), 0, 32},
- {errors.New("error in front matter: Near line 32 (last key parsed 'title')"), 2, 34},
+ {errors.New("no line number for you"), 0, -1, 1},
+ {errors.New(`template: _default/single.html:4:15: executing "_default/single.html" at <.Titles>: can't evaluate field Titles in type *hugolib.PageOutput`), 0, 4, 15},
+ {errors.New("parse failed: template: _default/bundle-resource-meta.html:11: unexpected in operand"), 0, 11, 1},
+ {errors.New(`failed:: template: _default/bundle-resource-meta.html:2:7: executing "main" at <.Titles>`), 0, 2, 7},
+ {errors.New("error in front matter: Near line 32 (last key parsed 'title')"), 0, 32, 1},
} {
got := ToFileErrorWithOffset("template", test.in, test.offset)
@@ -48,6 +48,7 @@ func TestToLineNumberError(t *testing.T) {
if test.lineNumber > 0 {
assert.True(ok)
assert.Equal(test.lineNumber, le.LineNumber(), errMsg)
+ assert.Equal(test.columnNumber, le.ColumnNumber(), errMsg)
assert.Contains(got.Error(), strconv.Itoa(le.LineNumber()))
} else {
assert.False(ok)
diff --git a/common/herrors/line_number_extractors.go b/common/herrors/line_number_extractors.go
index 01a7450f9..8740afdf7 100644
--- a/common/herrors/line_number_extractors.go
+++ b/common/herrors/line_number_extractors.go
@@ -14,14 +14,13 @@
package herrors
import (
- "fmt"
"regexp"
"strconv"
)
var lineNumberExtractors = []lineNumberExtractor{
// Template/shortcode parse errors
- newLineNumberErrHandlerFromRegexp("(.*?:)(\\d+)(:.*)"),
+ newLineNumberErrHandlerFromRegexp("(.*?:)(\\d+)(:)(\\d+)?(.*)"),
// TOML parse errors
newLineNumberErrHandlerFromRegexp("(.*Near line )(\\d+)(\\s.*)"),
@@ -30,7 +29,7 @@ var lineNumberExtractors = []lineNumberExtractor{
newLineNumberErrHandlerFromRegexp("(line )(\\d+)(:)"),
}
-type lineNumberExtractor func(e error, offset int) (int, string)
+type lineNumberExtractor func(e error) (int, int)
func newLineNumberErrHandlerFromRegexp(expression string) lineNumberExtractor {
re := regexp.MustCompile(expression)
@@ -38,22 +37,26 @@ func newLineNumberErrHandlerFromRegexp(expression string) lineNumberExtractor {
}
func extractLineNo(re *regexp.Regexp) lineNumberExtractor {
- return func(e error, offset int) (int, string) {
+ return func(e error) (int, int) {
if e == nil {
panic("no error")
}
+ col := 1
s := e.Error()
m := re.FindStringSubmatch(s)
- if len(m) == 4 {
- i, _ := strconv.Atoi(m[2])
- msg := e.Error()
- if offset != 0 {
- i = i + offset
- msg = re.ReplaceAllString(s, fmt.Sprintf("${1}%d${3}", i))
+ if len(m) >= 4 {
+ lno, _ := strconv.Atoi(m[2])
+ if len(m) > 4 {
+ col, _ = strconv.Atoi(m[4])
}
- return i, msg
+
+ if col <= 0 {
+ col = 1
+ }
+
+ return lno, col
}
- return -1, ""
+ return -1, col
}
}
diff --git a/deps/deps.go b/deps/deps.go
index 1e2686421..db59ad212 100644
--- a/deps/deps.go
+++ b/deps/deps.go
@@ -5,7 +5,6 @@ import (
"time"
"github.com/gohugoio/hugo/common/loggers"
-
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugofs"
@@ -16,6 +15,7 @@ import (
"github.com/gohugoio/hugo/resource"
"github.com/gohugoio/hugo/source"
"github.com/gohugoio/hugo/tpl"
+ jww "github.com/spf13/jwalterweatherman"
)
// Deps holds dependencies used by many.
@@ -73,6 +73,33 @@ type Deps struct {
// BuildStartListeners will be notified before a build starts.
BuildStartListeners *Listeners
+
+ *globalErrHandler
+}
+
+type globalErrHandler struct {
+ // Channel for some "hard to get to" build errors
+ buildErrors chan error
+}
+
+// SendErr sends the error on a channel to be handled later.
+// This can be used in situations where returning and aborting the current
+// operation isn't practical.
+func (e *globalErrHandler) SendError(err error) {
+ if e.buildErrors != nil {
+ select {
+ case e.buildErrors <- err:
+ default:
+ }
+ return
+ }
+
+ jww.ERROR.Println(err)
+}
+
+func (e *globalErrHandler) StartErrorCollector() chan error {
+ e.buildErrors = make(chan error, 10)
+ return e.buildErrors
}
// Listeners represents an event listener.
@@ -194,6 +221,7 @@ func New(cfg DepsCfg) (*Deps, error) {
Language: cfg.Language,
BuildStartListeners: &Listeners{},
Timeout: time.Duration(timeoutms) * time.Millisecond,
+ globalErrHandler: &globalErrHandler{},
}
if cfg.Cfg.GetBool("templateMetrics") {
diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go
index 7f70967d6..a184e8877 100644
--- a/hugolib/hugo_sites.go
+++ b/hugolib/hugo_sites.go
@@ -21,6 +21,7 @@ import (
"strings"
"sync"
+ "github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers"
@@ -53,6 +54,40 @@ type HugoSites struct {
gitInfo *gitInfo
}
+func (h *HugoSites) pickOneAndLogTheRest(errors []error) error {
+ if len(errors) == 0 {
+ return nil
+ }
+
+ var i int
+
+ for j, err := range errors {
+ // If this is in server mode, we want to return an error to the client
+ // with a file context, if possible.
+ if herrors.UnwrapErrorWithFileContext(err) != nil {
+ i = j
+ break
+ }
+ }
+
+ // Log the rest, but add a threshold to avoid flooding the log.
+ const errLogThreshold = 5
+
+ for j, err := range errors {
+ if j == i || err == nil {
+ continue
+ }
+
+ if j >= errLogThreshold {
+ break
+ }
+
+ h.Log.ERROR.Println(err)
+ }
+
+ return errors[i]
+}
+
func (h *HugoSites) IsMultihost() bool {
return h != nil && h.multihost
}
@@ -636,6 +671,7 @@ func handleShortcodes(p *PageWithoutContent, rawContentCopy []byte) ([]byte, err
err := p.shortcodeState.executeShortcodesForDelta(p)
if err != nil {
+
return rawContentCopy, err
}
diff --git a/hugolib/hugo_sites_build.go b/hugolib/hugo_sites_build.go
index 13fbfd57e..4c275f55b 100644
--- a/hugolib/hugo_sites_build.go
+++ b/hugolib/hugo_sites_build.go
@@ -26,13 +26,29 @@ import (
// Build builds all sites. If filesystem events are provided,
// this is considered to be a potential partial rebuild.
func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
+ errCollector := h.StartErrorCollector()
+ errs := make(chan error)
+
+ go func(from, to chan error) {
+ var errors []error
+ i := 0
+ for e := range from {
+ i++
+ if i > 50 {
+ break
+ }
+ errors = append(errors, e)
+ }
+ to <- h.pickOneAndLogTheRest(errors)
+
+ close(to)
+
+ }(errCollector, errs)
if h.Metrics != nil {
h.Metrics.Reset()
}
- //t0 := time.Now()
-
// Need a pointer as this may be modified.
conf := &config
@@ -41,33 +57,46 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
conf.whatChanged = &whatChanged{source: true, other: true}
}
+ var prepareErr error
+
if !config.PartialReRender {
- for _, s := range h.Sites {
- s.Deps.BuildStartListeners.Notify()
- }
+ prepare := func() error {
+ for _, s := range h.Sites {
+ s.Deps.BuildStartListeners.Notify()
+ }
+
+ if len(events) > 0 {
+ // Rebuild
+ if err := h.initRebuild(conf); err != nil {
+ return err
+ }
+ } else {
+ if err := h.init(conf); err != nil {
+ return err
+ }
+ }
- if len(events) > 0 {
- // Rebuild
- if err := h.initRebuild(conf); err != nil {
+ if err := h.process(conf, events...); err != nil {
return err
}
- } else {
- if err := h.init(conf); err != nil {
+
+ if err := h.assemble(conf); err != nil {
return err
}
+ return nil
}
- if err := h.process(conf, events...); err != nil {
- return err
+ prepareErr = prepare()
+ if prepareErr != nil {
+ h.SendError(prepareErr)
}
- if err := h.assemble(conf); err != nil {
- return err
- }
}
- if err := h.render(conf); err != nil {
- return err
+ if prepareErr == nil {
+ if err := h.render(conf); err != nil {
+ h.SendError(err)
+ }
}
if h.Metrics != nil {
@@ -79,6 +108,18 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
h.Log.FEEDBACK.Println()
}
+ select {
+ // Make sure the channel always gets something.
+ case errCollector <- nil:
+ default:
+ }
+ close(errCollector)
+
+ err := <-errs
+ if err != nil {
+ return err
+ }
+
errorCount := h.Log.ErrorCounter.Count()
if errorCount > 0 {
return fmt.Errorf("logged %d error(s)", errorCount)
diff --git a/hugolib/hugo_sites_build_errors_test.go b/hugolib/hugo_sites_build_errors_test.go
index 6b44bea88..2e8eb99ea 100644
--- a/hugolib/hugo_sites_build_errors_test.go
+++ b/hugolib/hugo_sites_build_errors_test.go
@@ -2,6 +2,7 @@ package hugolib
import (
"fmt"
+ "path/filepath"
"strings"
"testing"
@@ -17,13 +18,20 @@ type testSiteBuildErrorAsserter struct {
func (t testSiteBuildErrorAsserter) getFileError(err error) *herrors.ErrorWithFileContext {
t.assert.NotNil(err, t.name)
ferr := herrors.UnwrapErrorWithFileContext(err)
- t.assert.NotNil(ferr, fmt.Sprintf("[%s] got %T: %+v", t.name, err, err))
+ t.assert.NotNil(ferr, fmt.Sprintf("[%s] got %T: %+v\n%s", t.name, err, err, trace()))
return ferr
}
func (t testSiteBuildErrorAsserter) assertLineNumber(lineNumber int, err error) {
fe := t.getFileError(err)
- t.assert.Equal(lineNumber, fe.LineNumber, fmt.Sprintf("[%s] got => %s", t.name, fe))
+ t.assert.Equal(lineNumber, fe.LineNumber, fmt.Sprintf("[%s] got => %s\n%s", t.name, fe, trace()))
+}
+
+func (t testSiteBuildErrorAsserter) assertErrorMessage(e1, e2 string) {
+ // The error message will contain filenames with OS slashes. Normalize before compare.
+ e1, e2 = filepath.ToSlash(e1), filepath.ToSlash(e2)
+ t.assert.Equal(e1, e2, trace())
+
}
func TestSiteBuildErrors(t *testing.T) {
@@ -32,6 +40,7 @@ func TestSiteBuildErrors(t *testing.T) {
const (
yamlcontent = "yamlcontent"
+ tomlcontent = "tomlcontent"
shortcode = "shortcode"
base = "base"
single = "single"
@@ -55,7 +64,7 @@ func TestSiteBuildErrors(t *testing.T) {
return strings.Replace(content, ".Title }}", ".Title }", 1)
},
assertCreateError: func(a testSiteBuildErrorAsserter, err error) {
- a.assertLineNumber(2, err)
+ a.assertLineNumber(4, err)
},
},
{
@@ -65,7 +74,7 @@ func TestSiteBuildErrors(t *testing.T) {
return strings.Replace(content, ".Title", ".Titles", 1)
},
assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
- a.assertLineNumber(2, err)
+ a.assertLineNumber(4, err)
},
},
{
@@ -75,7 +84,12 @@ func TestSiteBuildErrors(t *testing.T) {
return strings.Replace(content, ".Title }}", ".Title }", 1)
},
assertCreateError: func(a testSiteBuildErrorAsserter, err error) {
- a.assertLineNumber(3, err)
+ fe := a.getFileError(err)
+ assert.Equal(5, fe.LineNumber)
+ assert.Equal(1, fe.ColumnNumber)
+ assert.Equal("go-html-template", fe.ChromaLexer)
+ a.assertErrorMessage("\"layouts/_default/single.html:5:1\": parse failed: template: _default/single.html:5: unexpected \"}\" in operand", fe.Error())
+
},
},
{
@@ -85,7 +99,12 @@ func TestSiteBuildErrors(t *testing.T) {
return strings.Replace(content, ".Title", ".Titles", 1)
},
assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
- a.assertLineNumber(3, err)
+ fe := a.getFileError(err)
+ assert.Equal(5, fe.LineNumber)
+ assert.Equal(14, fe.ColumnNumber)
+ assert.Equal("md", fe.ChromaLexer)
+ a.assertErrorMessage("asdfadf", fe.Error())
+
},
},
{
@@ -95,7 +114,7 @@ func TestSiteBuildErrors(t *testing.T) {
return strings.Replace(content, ".Title }}", ".Title }", 1)
},
assertCreateError: func(a testSiteBuildErrorAsserter, err error) {
- a.assertLineNumber(2, err)
+ a.assertLineNumber(4, err)
},
},
{
@@ -105,10 +124,47 @@ func TestSiteBuildErrors(t *testing.T) {
return strings.Replace(content, ".Title", ".Titles", 1)
},
assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
- a.assertLineNumber(25, err)
+ a.assertLineNumber(4, err)
},
},
+ {
+ name: "Shortode does not exist",
+ fileType: yamlcontent,
+ fileFixer: func(content string) string {
+ return strings.Replace(content, "{{< sc >}}", "{{< nono >}}", 1)
+ },
+ assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
+ fe := a.getFileError(err)
+ assert.Equal(7, fe.LineNumber)