aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2024-11-14 09:43:37 +0100
committerBjørn Erik Pedersen <[email protected]>2024-11-14 14:25:07 +0100
commitce9cf882a54e9c55dcc7970398ae79c3b251f79e (patch)
treeeb40936552007028f8e8c7ffcb8d87f028a3c929
parent46e17053c85e61709e2436316b4fc9461e1fcb79 (diff)
downloadhugo-ce9cf882a54e9c55dcc7970398ae79c3b251f79e.tar.gz
hugo-ce9cf882a54e9c55dcc7970398ae79c3b251f79e.zip
server: Strip ANSI escape codes from browser error log
Fixes #13037
-rw-r--r--common/loggers/handlerterminal.go24
-rw-r--r--common/loggers/handlerterminal_test.go40
-rw-r--r--common/loggers/logger.go4
3 files changed, 59 insertions, 9 deletions
diff --git a/common/loggers/handlerterminal.go b/common/loggers/handlerterminal.go
index 53f6e41da..c5f8fcce8 100644
--- a/common/loggers/handlerterminal.go
+++ b/common/loggers/handlerterminal.go
@@ -18,18 +18,19 @@ package loggers
import (
"fmt"
"io"
+ "regexp"
"strings"
"sync"
"github.com/bep/logg"
)
-// newNoColoursHandler creates a new NoColoursHandler
-func newNoColoursHandler(outWriter, errWriter io.Writer, noLevelPrefix bool, predicate func(*logg.Entry) bool) *noColoursHandler {
+// newNoAnsiEscapeHandler creates a new noAnsiEscapeHandler
+func newNoAnsiEscapeHandler(outWriter, errWriter io.Writer, noLevelPrefix bool, predicate func(*logg.Entry) bool) *noAnsiEscapeHandler {
if predicate == nil {
predicate = func(e *logg.Entry) bool { return true }
}
- return &noColoursHandler{
+ return &noAnsiEscapeHandler{
noLevelPrefix: noLevelPrefix,
outWriter: outWriter,
errWriter: errWriter,
@@ -37,7 +38,7 @@ func newNoColoursHandler(outWriter, errWriter io.Writer, noLevelPrefix bool, pre
}
}
-type noColoursHandler struct {
+type noAnsiEscapeHandler struct {
mu sync.Mutex
outWriter io.Writer // Defaults to os.Stdout.
errWriter io.Writer // Defaults to os.Stderr.
@@ -45,7 +46,7 @@ type noColoursHandler struct {
noLevelPrefix bool
}
-func (h *noColoursHandler) HandleLog(e *logg.Entry) error {
+func (h *noAnsiEscapeHandler) HandleLog(e *logg.Entry) error {
if !h.predicate(e) {
return nil
}
@@ -71,10 +72,12 @@ func (h *noColoursHandler) HandleLog(e *logg.Entry) error {
prefix = prefix + ": "
}
+ msg := stripANSI(e.Message)
+
if h.noLevelPrefix {
- fmt.Fprintf(w, "%s%s", prefix, e.Message)
+ fmt.Fprintf(w, "%s%s", prefix, msg)
} else {
- fmt.Fprintf(w, "%s %s%s", levelString[e.Level], prefix, e.Message)
+ fmt.Fprintf(w, "%s %s%s", levelString[e.Level], prefix, msg)
}
for _, field := range e.Fields {
@@ -88,3 +91,10 @@ func (h *noColoursHandler) HandleLog(e *logg.Entry) error {
return nil
}
+
+var ansiRe = regexp.MustCompile(`\x1b\[[0-9;]*m`)
+
+// stripANSI removes ANSI escape codes from s.
+func stripANSI(s string) string {
+ return ansiRe.ReplaceAllString(s, "")
+}
diff --git a/common/loggers/handlerterminal_test.go b/common/loggers/handlerterminal_test.go
new file mode 100644
index 000000000..f45ce80df
--- /dev/null
+++ b/common/loggers/handlerterminal_test.go
@@ -0,0 +1,40 @@
+// Copyright 2024 The Hugo Authors. All rights reserved.
+// Some functions in this file (see comments) is based on the Go source code,
+// copyright The Go Authors and governed by a BSD-style license.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package loggers
+
+import (
+ "bytes"
+ "testing"
+
+ "github.com/bep/logg"
+ qt "github.com/frankban/quicktest"
+ "github.com/gohugoio/hugo/common/terminal"
+)
+
+func TestNoAnsiEscapeHandler(t *testing.T) {
+ c := qt.New(t)
+
+ test := func(s string) {
+ c.Assert(stripANSI(terminal.Notice(s)), qt.Equals, s)
+ }
+ test(`error in "file.md:1:2"`)
+
+ var buf bytes.Buffer
+ h := newNoAnsiEscapeHandler(&buf, &buf, false, nil)
+ h.HandleLog(&logg.Entry{Message: terminal.Notice(`error in "file.md:1:2"`), Level: logg.LevelInfo})
+
+ c.Assert(buf.String(), qt.Equals, "INFO error in \"file.md:1:2\"\n")
+}
diff --git a/common/loggers/logger.go b/common/loggers/logger.go
index 4e2f3ab21..75c8102c7 100644
--- a/common/loggers/logger.go
+++ b/common/loggers/logger.go
@@ -62,7 +62,7 @@ func New(opts Options) Logger {
if terminal.PrintANSIColors(os.Stdout) {
logHandler = newDefaultHandler(opts.Stdout, opts.Stderr)
} else {
- logHandler = newNoColoursHandler(opts.Stdout, opts.Stderr, false, nil)
+ logHandler = newNoAnsiEscapeHandler(opts.Stdout, opts.Stderr, false, nil)
}
errorsw := &strings.Builder{}
@@ -95,7 +95,7 @@ func New(opts Options) Logger {
}
if opts.StoreErrors {
- h := newNoColoursHandler(io.Discard, errorsw, true, func(e *logg.Entry) bool {
+ h := newNoAnsiEscapeHandler(io.Discard, errorsw, true, func(e *logg.Entry) bool {
return e.Level >= logg.LevelError
})