Files
wehub-resource-sync 36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:06 +08:00

58 lines
1.3 KiB
Go

package output
import (
"fmt"
"io"
)
type ansiString string
// Printer writes terminal-safe output to an io.Writer, sanitizing any
// string-like arguments (string, []byte, error, fmt.Stringer). Sanitization
// escapes embedded newlines/tabs so an untrusted value can't forge extra
// layout lines; the tool's own layout newlines must therefore go through
// Printf's format string (which is not sanitized), never a Print/Println arg.
type Printer struct {
w io.Writer
}
func NewPrinter(w io.Writer) Printer {
return Printer{w: w}
}
func (p Printer) Printf(format string, args ...any) {
fmt.Fprintf(p.w, format, sanitizePrintArgs(args)...)
}
func (p Printer) Print(args ...any) {
fmt.Fprint(p.w, sanitizePrintArgs(args)...)
}
func (p Printer) Println(args ...any) {
fmt.Fprintln(p.w, sanitizePrintArgs(args)...)
}
func sanitizePrintArgs(args []any) []any {
if len(args) == 0 {
return nil
}
out := make([]any, len(args))
for i, a := range args {
switch v := a.(type) {
case ansiString: // our own ansiString type is allowed to render as-is
out[i] = string(v)
case string:
out[i] = SanitizeTerminalLine(v)
case []byte:
out[i] = SanitizeTerminalLine(string(v))
case error:
out[i] = SanitizeTerminalLine(v.Error())
case fmt.Stringer:
out[i] = SanitizeTerminalLine(v.String())
default:
out[i] = a
}
}
return out
}