diff --git a/commands/hugo.go b/commands/hugo.go index 2204ae9f3..acc48539d 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -620,7 +620,9 @@ func (c *commandeer) buildSites() (err error) { func (c *commandeer) handleBuildErr(err error, msg string) { c.buildErr = err - c.logger.ERROR.Printf("%s: %s", msg, err) + + c.logger.ERROR.Print(msg + ":\n\n") + c.logger.ERROR.Println(helpers.FirstUpper(err.Error())) if !c.h.quiet && c.h.verbose { herrors.PrintStackTrace(err) } diff --git a/common/herrors/file_error_test.go b/common/herrors/file_error_test.go index 0d4e82f66..8b1674ba1 100644 --- a/common/herrors/file_error_test.go +++ b/common/herrors/file_error_test.go @@ -38,6 +38,7 @@ func TestToLineNumberError(t *testing.T) { {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}, + {errors.New(`failed to load translations: (6, 7): was expecting token =, but got "g" instead`), 0, 6, 7}, } { got := ToFileErrorWithOffset("template", test.in, test.offset) @@ -46,7 +47,7 @@ func TestToLineNumberError(t *testing.T) { le, ok := got.(FileError) if test.lineNumber > 0 { - assert.True(ok) + assert.True(ok, errMsg) assert.Equal(test.lineNumber, le.LineNumber(), errMsg) assert.Equal(test.columnNumber, le.ColumnNumber(), errMsg) assert.Contains(got.Error(), strconv.Itoa(le.LineNumber())) diff --git a/common/herrors/line_number_extractors.go b/common/herrors/line_number_extractors.go index 8740afdf7..93969b967 100644 --- a/common/herrors/line_number_extractors.go +++ b/common/herrors/line_number_extractors.go @@ -20,13 +20,17 @@ import ( var lineNumberExtractors = []lineNumberExtractor{ // Template/shortcode parse errors - newLineNumberErrHandlerFromRegexp("(.*?:)(\\d+)(:)(\\d+)?(.*)"), + newLineNumberErrHandlerFromRegexp(".*:(\\d+):(\\d*):"), + newLineNumberErrHandlerFromRegexp(".*:(\\d+):"), // TOML parse errors - newLineNumberErrHandlerFromRegexp("(.*Near line )(\\d+)(\\s.*)"), + newLineNumberErrHandlerFromRegexp(".*Near line (\\d+)(\\s.*)"), // YAML parse errors - newLineNumberErrHandlerFromRegexp("(line )(\\d+)(:)"), + newLineNumberErrHandlerFromRegexp("line (\\d+):"), + + // i18n bundle errors + newLineNumberErrHandlerFromRegexp("\\((\\d+),\\s(\\d*)"), } type lineNumberExtractor func(e error) (int, int) @@ -44,10 +48,10 @@ func extractLineNo(re *regexp.Regexp) lineNumberExtractor { col := 1 s := e.Error() m := re.FindStringSubmatch(s) - if len(m) >= 4 { - lno, _ := strconv.Atoi(m[2]) - if len(m) > 4 { - col, _ = strconv.Atoi(m[4]) + if len(m) >= 2 { + lno, _ := strconv.Atoi(m[1]) + if len(m) > 2 { + col, _ = strconv.Atoi(m[2]) } if col <= 0 { diff --git a/hugolib/site.go b/hugolib/site.go index e3f6d8f8c..127b143e5 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -861,6 +861,24 @@ func (s *Site) loadData(fs afero.Fs) (err error) { return } +func (s *Site) errWithFileContext(err error, f source.File) error { + rfi, ok := f.FileInfo().(hugofs.RealFilenameInfo) + if !ok { + return err + } + + realFilename := rfi.RealFilename() + + err, _ = herrors.WithFileContextForFile( + err, + realFilename, + realFilename, + s.SourceSpec.Fs.Source, + herrors.SimpleLineMatcher) + + return err +} + func (s *Site) handleDataFile(r source.ReadableFile) error { var current map[string]interface{} @@ -888,14 +906,7 @@ func (s *Site) handleDataFile(r source.ReadableFile) error { data, err := s.readData(r) if err != nil { - realFilename := r.FileInfo().(hugofs.RealFilenameInfo).RealFilename() - err, _ = herrors.WithFileContextForFile( - _errors.Wrapf(err, "failed to read data file"), - realFilename, - realFilename, - s.SourceSpec.Fs.Source, - herrors.SimpleLineMatcher) - return err + return s.errWithFileContext(err, r) } if data == nil { diff --git a/i18n/translationProvider.go b/i18n/translationProvider.go index 4e937c5a1..74e144007 100644 --- a/i18n/translationProvider.go +++ b/i18n/translationProvider.go @@ -16,8 +16,11 @@ package i18n import ( "errors" + "github.com/gohugoio/hugo/common/herrors" + "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/helpers" + "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/source" "github.com/nicksnyder/go-i18n/i18n/bundle" "github.com/nicksnyder/go-i18n/i18n/language" @@ -81,12 +84,12 @@ func (tp *TranslationProvider) Update(d *deps.Deps) error { func addTranslationFile(bundle *bundle.Bundle, r source.ReadableFile) error { f, err := r.Open() if err != nil { - return _errors.Wrapf(err, "Failed to open translations file %q:", r.LogicalName()) + return _errors.Wrapf(err, "failed to open translations file %q:", r.LogicalName()) } - defer f.Close() err = bundle.ParseTranslationFileBytes(r.LogicalName(), helpers.ReaderToBytes(f)) + f.Close() if err != nil { - return _errors.Wrapf(err, "Failed to load translations in file %q:", r.LogicalName()) + return errWithFileContext(_errors.Wrapf(err, "failed to load translations"), r) } return nil } @@ -97,3 +100,26 @@ func (tp *TranslationProvider) Clone(d *deps.Deps) error { return nil } + +func errWithFileContext(inerr error, r source.ReadableFile) error { + rfi, ok := r.FileInfo().(hugofs.RealFilenameInfo) + if !ok { + return inerr + } + + realFilename := rfi.RealFilename() + f, err := r.Open() + if err != nil { + return inerr + } + defer f.Close() + + err, _ = herrors.WithFileContext( + inerr, + realFilename, + f, + herrors.SimpleLineMatcher) + + return err + +}