errors: Misc improvements

* Redo the server error template
* Always add the content file context if relevant
* Remove some now superflous error string matching
* Move the server error template to _server/error.html
* Add file context (with position) to codeblock render blocks
* Improve JS build errors

Fixes #9892
Fixes #9891
Fixes #9893
This commit is contained in:
Bjørn Erik Pedersen
2022-05-12 11:43:20 +02:00
parent 4a96df96d9
commit 5c96bda70a
27 changed files with 600 additions and 204 deletions

View File

@@ -34,11 +34,22 @@ type LineMatcher struct {
}
// LineMatcherFn is used to match a line with an error.
type LineMatcherFn func(m LineMatcher) bool
// It returns the column number or 0 if the line was found, but column could not be determinde. Returns -1 if no line match.
type LineMatcherFn func(m LineMatcher) int
// SimpleLineMatcher simply matches by line number.
var SimpleLineMatcher = func(m LineMatcher) bool {
return m.Position.LineNumber == m.LineNumber
var SimpleLineMatcher = func(m LineMatcher) int {
if m.Position.LineNumber == m.LineNumber {
// We found the line, but don't know the column.
return 0
}
return -1
}
// NopLineMatcher is a matcher that always returns 1.
// This will effectively give line 1, column 1.
var NopLineMatcher = func(m LineMatcher) int {
return 1
}
// ErrorContext contains contextual information about an error. This will
@@ -52,6 +63,10 @@ type ErrorContext struct {
// The position of the error in the Lines above. 0 based.
LinesPos int
// The position of the content in the file. Note that this may be different from the error's position set
// in FileError.
Position text.Position
// The lexer to use for syntax highlighting.
// https://gohugo.io/content-management/syntax-highlighting/#list-of-chroma-highlighting-languages
ChromaLexer string
@@ -78,31 +93,24 @@ func chromaLexerFromFilename(filename string) string {
return chromaLexerFromType(ext)
}
func locateErrorInString(src string, matcher LineMatcherFn) (*ErrorContext, text.Position) {
func locateErrorInString(src string, matcher LineMatcherFn) *ErrorContext {
return locateError(strings.NewReader(src), &fileError{}, matcher)
}
func locateError(r io.Reader, le FileError, matches LineMatcherFn) (*ErrorContext, text.Position) {
func locateError(r io.Reader, le FileError, matches LineMatcherFn) *ErrorContext {
if le == nil {
panic("must provide an error")
}
errCtx := &ErrorContext{LinesPos: -1}
pos := text.Position{LineNumber: -1, ColumnNumber: 1, Offset: -1}
ectx := &ErrorContext{LinesPos: -1, Position: text.Position{Offset: -1}}
b, err := ioutil.ReadAll(r)
if err != nil {
return errCtx, pos
return ectx
}
lepos := le.Position()
lines := strings.Split(string(b), "\n")
if lepos.ColumnNumber >= 0 {
pos.ColumnNumber = lepos.ColumnNumber
}
lineNo := 0
posBytes := 0
@@ -115,34 +123,36 @@ func locateError(r io.Reader, le FileError, matches LineMatcherFn) (*ErrorContex
Offset: posBytes,
Line: line,
}
if errCtx.LinesPos == -1 && matches(m) {
pos.LineNumber = lineNo
v := matches(m)
if ectx.LinesPos == -1 && v != -1 {
ectx.Position.LineNumber = lineNo
ectx.Position.ColumnNumber = v
break
}
posBytes += len(line)
}
if pos.LineNumber != -1 {
low := pos.LineNumber - 3
if ectx.Position.LineNumber > 0 {
low := ectx.Position.LineNumber - 3
if low < 0 {
low = 0
}
if pos.LineNumber > 2 {
errCtx.LinesPos = 2
if ectx.Position.LineNumber > 2 {
ectx.LinesPos = 2
} else {
errCtx.LinesPos = pos.LineNumber - 1
ectx.LinesPos = ectx.Position.LineNumber - 1
}
high := pos.LineNumber + 2
high := ectx.Position.LineNumber + 2
if high > len(lines) {
high = len(lines)
}
errCtx.Lines = lines[low:high]
ectx.Lines = lines[low:high]
}
return errCtx, pos
return ectx
}