diff --git a/go.mod b/go.mod index 37ade64..d19539f 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-chi/chi/v5 v5.3.0 github.com/google/uuid v1.6.0 github.com/hashicorp/nomad/api v0.0.0-20260220212019-daca79db0bd6 - github.com/jedib0t/go-pretty/v6 v6.7.10 + github.com/jedib0t/go-pretty/v6 v6.8.1 github.com/rs/zerolog v1.35.1 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index d1d6b02..8d6cf61 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5O github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/nomad/api v0.0.0-20260220212019-daca79db0bd6 h1:QN/GwpGyiW8RdNcHGMA1xVnM8tJkAGNDR/BZ47XR+OU= github.com/hashicorp/nomad/api v0.0.0-20260220212019-daca79db0bd6/go.mod h1:KkLNLU0Nyfh5jWsFoF/PsmMbKpRIAoIV4lmQoJWgKCk= -github.com/jedib0t/go-pretty/v6 v6.7.10 h1:B/2qW2Bkv2L6n14PP8o1kx75kWzHOQ3YTluWzg9icac= -github.com/jedib0t/go-pretty/v6 v6.7.10/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.8.1 h1:0fkCNhjrX0zPpwkWaDYU5VMrygg41Tu197mWILIJoqQ= +github.com/jedib0t/go-pretty/v6 v6.8.1/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/filter.go b/vendor/github.com/jedib0t/go-pretty/v6/table/filter.go index 7462cfc..b4b6f19 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/filter.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/filter.go @@ -42,6 +42,11 @@ type FilterBy struct { // // Use this when the default filtering logic is not sufficient. CustomFilter func(cellValue string) bool + + // compiledRegex caches the compiled pattern for RegexMatch and + // RegexNotMatch; populated once by parseFilterBy instead of compiling + // the pattern again for every row + compiledRegex *regexp.Regexp } // FilterOperator defines how to filter. @@ -91,12 +96,13 @@ func (t *Table) parseFilterBy(filterBy []FilterBy) []FilterBy { } if colNum > 0 { resFilterBy = append(resFilterBy, FilterBy{ - Name: filter.Name, - Number: colNum, - Operator: filter.Operator, - Value: filter.Value, - IgnoreCase: filter.IgnoreCase, - CustomFilter: filter.CustomFilter, + Name: filter.Name, + Number: colNum, + Operator: filter.Operator, + Value: filter.Value, + IgnoreCase: filter.IgnoreCase, + CustomFilter: filter.CustomFilter, + compiledRegex: compileFilterRegex(filter), }) } } @@ -154,9 +160,9 @@ func (t *Table) matchesOperator(cellValue string, filter FilterBy) bool { case EndsWith: return t.compareEndsWith(cellValue, filter.Value, filter.IgnoreCase) case RegexMatch: - return t.compareRegexMatch(cellValue, filter.Value, filter.IgnoreCase) + return t.compareRegexMatch(cellValue, filter) case RegexNotMatch: - return !t.compareRegexMatch(cellValue, filter.Value, filter.IgnoreCase) + return !t.compareRegexMatch(cellValue, filter) default: return false } @@ -229,22 +235,33 @@ func (t *Table) compareEndsWith(cellValue string, filterValue interface{}, ignor return strings.HasSuffix(cellValue, filterStr) } -func (t *Table) compareRegexMatch(cellValue string, filterValue interface{}, ignoreCase bool) bool { - filterStr := fmt.Sprint(filterValue) - - // Compile the regex pattern - var pattern *regexp.Regexp - var err error - if ignoreCase { - pattern, err = regexp.Compile("(?i)" + filterStr) - } else { - pattern, err = regexp.Compile(filterStr) +func (t *Table) compareRegexMatch(cellValue string, filter FilterBy) bool { + pattern := filter.compiledRegex + if pattern == nil { + pattern = compileFilterRegex(filter) } - - if err != nil { + if pattern == nil { // If regex compilation fails, fall back to simple string matching - return t.compareEqual(cellValue, filterValue, ignoreCase) + return t.compareEqual(cellValue, filter.Value, filter.IgnoreCase) } return pattern.MatchString(cellValue) } + +// compileFilterRegex compiles the pattern for a RegexMatch/RegexNotMatch +// filter; returns nil for other operators or when the pattern is invalid. +func compileFilterRegex(filter FilterBy) *regexp.Regexp { + if filter.Operator != RegexMatch && filter.Operator != RegexNotMatch { + return nil + } + + filterStr := fmt.Sprint(filter.Value) + if filter.IgnoreCase { + filterStr = "(?i)" + filterStr + } + pattern, err := regexp.Compile(filterStr) + if err != nil { + return nil + } + return pattern +} diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/render.go b/vendor/github.com/jedib0t/go-pretty/v6/table/render.go index a1b6cfe..37c4b6b 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/render.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/render.go @@ -107,7 +107,9 @@ func (t *Table) renderColumn(out *strings.Builder, row rowStr, colIdx int, maxCo func (t *Table) renderColumnAutoIndex(out *strings.Builder, hint renderHint) { var outAutoIndex strings.Builder - outAutoIndex.Grow(t.maxColumnLengths[0]) + if len(t.maxColumnLengths) > 0 { + outAutoIndex.Grow(t.maxColumnLengths[0]) + } if hint.isSeparatorRow { numChars := t.autoIndexVIndexMaxLength + utf8.RuneCountInString(t.style.Box.PaddingLeft) + diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/render_csv.go b/vendor/github.com/jedib0t/go-pretty/v6/table/render_csv.go index 8974565..eac5824 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/render_csv.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/render_csv.go @@ -10,7 +10,7 @@ import ( // // #,First Name,Last Name,Salary, // 1,Arya,Stark,3000, -// 20,Jon,Snow,2000,"You know nothing\, Jon Snow!" +// 20,Jon,Snow,2000,"You know nothing, Jon Snow!" // 300,Tyrion,Lannister,5000, // ,,Total,10000, func (t *Table) RenderCSV() string { @@ -18,6 +18,7 @@ func (t *Table) RenderCSV() string { var out strings.Builder if t.numColumns > 0 { + out.Grow(t.estimatedRenderLength()) if t.title != "" { out.WriteString(t.title) } @@ -35,12 +36,21 @@ func (t *Table) RenderCSV() string { return t.render(&out) } -func (t *Table) csvFixCommas(str string) string { - return strings.ReplaceAll(str, ",", "\\,") +// csvEscapeDoubleQuotes escapes double-quotes inside a quoted field by +// doubling them, as mandated by RFC 4180. +func (t *Table) csvEscapeDoubleQuotes(str string) string { + return strings.ReplaceAll(str, "\"", "\"\"") } -func (t *Table) csvFixDoubleQuotes(str string) string { - return strings.ReplaceAll(str, "\"", "\\\"") +// csvProtectField neutralizes fields that spreadsheet applications would +// interpret as formulas (=, +, -, @, tab or CR prefix) by prefixing them with +// a single-quote. +func (t *Table) csvProtectField(str string) string { + switch str[0] { + case '=', '+', '-', '@', '\t', '\r': + return "'" + str + } + return str } func (t *Table) csvRenderRow(out *strings.Builder, row rowStr, hint renderHint) { @@ -61,9 +71,12 @@ func (t *Table) csvRenderRow(out *strings.Builder, row rowStr, hint renderHint) if colIdx > 0 { out.WriteRune(',') } + if t.style.CSV.FieldProtection && colStr != "" { + colStr = t.csvProtectField(colStr) + } if strings.ContainsAny(colStr, "\",\n") { out.WriteRune('"') - out.WriteString(t.csvFixCommas(t.csvFixDoubleQuotes(colStr))) + out.WriteString(t.csvEscapeDoubleQuotes(colStr)) out.WriteRune('"') } else if utf8.RuneCountInString(colStr) > 0 { out.WriteString(colStr) diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/render_html.go b/vendor/github.com/jedib0t/go-pretty/v6/table/render_html.go index 07b1850..e138faf 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/render_html.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/render_html.go @@ -64,11 +64,12 @@ func (t *Table) RenderHTML() string { var out strings.Builder if t.numColumns > 0 { + out.Grow(t.estimatedRenderLength()) out.WriteString("\n") t.htmlRenderTitle(&out) @@ -99,8 +100,12 @@ func (t *Table) htmlGetColStrAndTag(row rowStr, colIdx int, hint renderHint) (st func (t *Table) htmlRenderCaption(out *strings.Builder) { if t.caption != "" { + caption := t.caption + if t.style.HTML.EscapeText { + caption = html.EscapeString(caption) + } out.WriteString(" \n") } } @@ -263,6 +268,9 @@ func (t *Table) htmlRenderTitle(out *strings.Builder) { align := t.style.Title.Align.HTMLProperty() colors := t.style.Title.Colors.HTMLProperty() title := t.style.Title.Format.Apply(t.title) + if t.style.HTML.EscapeText { + title = html.EscapeString(title) + } out.WriteString("
") - out.WriteString(t.caption) + out.WriteString(caption) out.WriteString(" 0 { + out.Grow(t.estimatedRenderLength()) t.markdownRenderTitle(&out) t.markdownRenderRowsHeader(&out) t.markdownRenderRows(&out, t.rows, renderHint{}) diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/render_tsv.go b/vendor/github.com/jedib0t/go-pretty/v6/table/render_tsv.go index 9e0c4dd..81022d9 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/render_tsv.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/render_tsv.go @@ -11,6 +11,7 @@ func (t *Table) RenderTSV() string { var out strings.Builder if t.numColumns > 0 { + out.Grow(t.estimatedRenderLength()) if t.title != "" { out.WriteString(t.title) } diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/style.go b/vendor/github.com/jedib0t/go-pretty/v6/table/style.go index 0b2473d..0e2058a 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/style.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/style.go @@ -6,6 +6,7 @@ type Style struct { Name string // name of the Style Box BoxStyle // characters to use for the boxes Color ColorOptions // colors to use for the rows and columns + CSV CSVOptions // rendering options for CSV mode Format FormatOptions // formatting options for the rows and columns HTML HTMLOptions // rendering options for HTML mode Markdown MarkdownOptions // rendering options for Markdown mode diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/style_csv.go b/vendor/github.com/jedib0t/go-pretty/v6/table/style_csv.go new file mode 100644 index 0000000..dc24865 --- /dev/null +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/style_csv.go @@ -0,0 +1,19 @@ +package table + +// CSVOptions defines options to control CSV rendering. +type CSVOptions struct { + // FieldProtection neutralizes fields that spreadsheet applications could + // interpret as formulas (fields beginning with =, +, -, @, tab or CR) by + // prefixing them with a single-quote, preventing CSV formula injection + // when the rendered output is opened in such an application. + // + // Note that the single-quote becomes part of the field content for + // standards-compliant CSV readers; enable this only when the output is + // destined for a spreadsheet application. + FieldProtection bool +} + +var ( + // DefaultCSVOptions defines sensible CSV rendering defaults. + DefaultCSVOptions = CSVOptions{} +) diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/table.go b/vendor/github.com/jedib0t/go-pretty/v6/table/table.go index 02d4092..f654f36 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/table.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/table.go @@ -812,6 +812,13 @@ func (t *Table) isIndexColumn(colIdx int, hint renderHint) bool { return t.indexColumn == colIdx+1 || hint.isAutoIndexColumn } +// estimatedRenderLength approximates the rendered output size, to pre-size +// the output builder and avoid repeated re-allocations while rendering. +func (t *Table) estimatedRenderLength() int { + numRows := len(t.rows) + len(t.rowsHeader) + len(t.rowsFooter) + 1 + return numRows * (t.maxRowLength + 1) +} + func (t *Table) render(out *strings.Builder) string { outStr := out.String() if t.suppressTrailingSpaces { diff --git a/vendor/github.com/jedib0t/go-pretty/v6/text/align.go b/vendor/github.com/jedib0t/go-pretty/v6/text/align.go index 18cc59e..0169b91 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/text/align.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/text/align.go @@ -1,10 +1,8 @@ package text import ( - "fmt" "strconv" "strings" - "unicode/utf8" ) // Align denotes how text is to be aligned horizontally. @@ -39,24 +37,39 @@ func (a Align) Apply(text string, maxLength int) string { } text = aComputed.trimString(text) - sLen := utf8.RuneCountInString(text) sLenWoE := StringWidthWithoutEscSequences(text) - numEscChars := sLen - sLenWoE + padding := maxLength - sLenWoE - // now, align the text + // now, align the text by padding the missing display-width with spaces switch aComputed { case AlignDefault, AlignLeft: - return fmt.Sprintf("%-"+strconv.Itoa(maxLength+numEscChars)+"s", text) + return padText(text, 0, padding) case AlignCenter: - if sLenWoE < maxLength { - // left pad with half the number of spaces needed before using %text - return fmt.Sprintf("%"+strconv.Itoa(maxLength+numEscChars)+"s", - text+strings.Repeat(" ", (maxLength-sLenWoE)/2)) - } + // extra space on the left when the padding is odd + return padText(text, padding-padding/2, padding/2) case AlignJustify: return justifyText(text, sLenWoE, maxLength) } - return fmt.Sprintf("%"+strconv.Itoa(maxLength+numEscChars)+"s", text) + return padText(text, padding, 0) +} + +// padText returns the text with the given number of spaces on either side; +// non-positive counts add nothing. +func padText(text string, left int, right int) string { + if left <= 0 && right <= 0 { + return text + } + + var out strings.Builder + out.Grow(len(text) + left + right) + for idx := 0; idx < left; idx++ { + out.WriteByte(' ') + } + out.WriteString(text) + for idx := 0; idx < right; idx++ { + out.WriteByte(' ') + } + return out.String() } // HTMLProperty returns the equivalent HTML horizontal-align tag property. diff --git a/vendor/github.com/jedib0t/go-pretty/v6/text/escape_seq_parser.go b/vendor/github.com/jedib0t/go-pretty/v6/text/escape_seq_parser.go index 66edae6..2444498 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/text/escape_seq_parser.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/text/escape_seq_parser.go @@ -1,10 +1,12 @@ package text import ( + "bytes" "fmt" "sort" "strconv" "strings" + "unicode/utf8" ) // Constants @@ -64,6 +66,18 @@ const ( // conceal OSI sequences escapeStartConcealOSI = "\x1b]8;" escapeStopConcealOSI = "\x1b\\" + + // escSeqMaxLength bounds the accumulated escape sequence; real terminals + // cap sequences in the low KBs, and anything longer here is most likely + // malformed input that would otherwise grow the buffer without limit + escSeqMaxLength = 2048 +) + +// []byte forms of the conceal OSI markers for prefix/suffix checks on the +// escape sequence buffer without allocating per call +var ( + escapeStartConcealOSIBytes = []byte(escapeStartConcealOSI) + escapeStopConcealOSIBytes = []byte(escapeStopConcealOSI) ) // 256-color codes @@ -117,8 +131,9 @@ type EscSeqParser struct { inEscSeq bool // escSeqKind identifies the type of escape sequence being parsed (CSI or OSI). escSeqKind escSeqKind - // escapeSeq accumulates the current escape sequence being parsed. - escapeSeq string + // escapeSeq accumulates the current escape sequence being parsed; it is + // bounded by escSeqMaxLength and reused across sequences. + escapeSeq []byte } func (s *EscSeqParser) Codes() []int { @@ -136,7 +151,7 @@ func (s *EscSeqParser) Consume(char rune) { if !s.inEscSeq && char == EscapeStartRune { s.inEscSeq = true s.escSeqKind = escSeqKindUnknown - s.escapeSeq = "" + s.escapeSeq = s.escapeSeq[:0] } else if s.inEscSeq && s.escSeqKind == escSeqKindUnknown { switch char { case EscapeStartRuneCSI: @@ -147,20 +162,27 @@ func (s *EscSeqParser) Consume(char rune) { } if s.inEscSeq { - s.escapeSeq += string(char) + s.escapeSeq = utf8.AppendRune(s.escapeSeq, char) + + // abort on absurdly long (most likely malformed/unterminated) + // sequences instead of accumulating them without limit + if len(s.escapeSeq) > escSeqMaxLength { + s.Reset() + return + } // --- FIX for OSC 8 hyperlinks (e.g. \x1b]8;;url\x07label\x1b]8;;\x07) if s.escSeqKind == escSeqKindOSI && - strings.HasPrefix(s.escapeSeq, escapeStartConcealOSI) && + bytes.HasPrefix(s.escapeSeq, escapeStartConcealOSIBytes) && char == escRuneBEL { // BEL - s.ParseSeq(s.escapeSeq, s.escSeqKind) + s.ParseSeq(string(s.escapeSeq), s.escSeqKind) s.Reset() return } if s.isEscapeStopRune(char) { - s.ParseSeq(s.escapeSeq, s.escSeqKind) + s.ParseSeq(string(s.escapeSeq), s.escSeqKind) s.Reset() } } @@ -186,7 +208,7 @@ func (s *EscSeqParser) ParseSeq(seq string, seqKind escSeqKind) { } func (s *EscSeqParser) ParseString(str string) string { - s.escapeSeq, s.inEscSeq, s.escSeqKind = "", false, escSeqKindUnknown + s.escapeSeq, s.inEscSeq, s.escSeqKind = s.escapeSeq[:0], false, escSeqKindUnknown for _, char := range str { s.Consume(char) } @@ -196,7 +218,7 @@ func (s *EscSeqParser) ParseString(str string) string { func (s *EscSeqParser) Reset() { s.inEscSeq = false s.escSeqKind = escSeqKindUnknown - s.escapeSeq = "" + s.escapeSeq = s.escapeSeq[:0] } func (s *EscSeqParser) Sequence() string { @@ -275,8 +297,8 @@ func (s *EscSeqParser) clearColorRange(isForeground bool) { } func (s *EscSeqParser) isEscapeStopRune(char rune) bool { - if strings.HasPrefix(s.escapeSeq, escapeStartConcealOSI) { - if strings.HasSuffix(s.escapeSeq, escapeStopConcealOSI) { + if bytes.HasPrefix(s.escapeSeq, escapeStartConcealOSIBytes) { + if bytes.HasSuffix(s.escapeSeq, escapeStopConcealOSIBytes) { return true } } else if (s.escSeqKind == escSeqKindCSI && char == EscapeStopRuneCSI) || diff --git a/vendor/github.com/jedib0t/go-pretty/v6/text/hyperlink.go b/vendor/github.com/jedib0t/go-pretty/v6/text/hyperlink.go index 00a551a..48952c2 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/text/hyperlink.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/text/hyperlink.go @@ -1,8 +1,12 @@ package text -import "fmt" +import ( + "fmt" + "strings" +) func Hyperlink(url, text string) string { + url = sanitizeHyperlinkURL(url) if url == "" { return text } @@ -12,3 +16,15 @@ func Hyperlink(url, text string) string { // source https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda return fmt.Sprintf("\x1b]8;;%s\x1b\\%s\x1b]8;;\x1b\\", url, text) } + +// sanitizeHyperlinkURL strips ASCII control characters (including ESC and BEL) +// from the URL; left in place, they could terminate the OSC 8 sequence early +// and inject arbitrary escape sequences into the terminal output. +func sanitizeHyperlinkURL(url string) string { + return strings.Map(func(r rune) rune { + if r < 0x20 || r == 0x7f { + return -1 + } + return r + }, url) +} diff --git a/vendor/github.com/jedib0t/go-pretty/v6/text/string.go b/vendor/github.com/jedib0t/go-pretty/v6/text/string.go index fa3e4f1..d8b3084 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/text/string.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/text/string.go @@ -263,6 +263,15 @@ func StringWidth(str string) int { // StringWidthWithoutEscSequences("Ghost 生命"): 10 // StringWidthWithoutEscSequences("\x1b[33mGhost 生命\x1b[0m"): 10 func StringWidthWithoutEscSequences(str string) int { + // fast-path the common case of a string without escape sequences + if !strings.ContainsRune(str, EscapeStartRune) { + count := 0 + for _, c := range str { + count += RuneWidth(c) + } + return count + } + count, esp := 0, EscSeqParser{} for _, c := range str { if esp.InSequence() { diff --git a/vendor/github.com/jedib0t/go-pretty/v6/text/valign.go b/vendor/github.com/jedib0t/go-pretty/v6/text/valign.go index 8e086d9..9862590 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/text/valign.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/text/valign.go @@ -27,6 +27,10 @@ func (va VAlign) Apply(lines []string, maxLines int) []string { maxLines = len(lines) } + if maxLines < 1 { // no lines and a negative maxLines + return lines + } + var insertIdx int switch va { case VAlignMiddle: diff --git a/vendor/github.com/jedib0t/go-pretty/v6/text/wrap.go b/vendor/github.com/jedib0t/go-pretty/v6/text/wrap.go index fd657f7..962085c 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/text/wrap.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/text/wrap.go @@ -89,7 +89,7 @@ func WrapText(str string, wrapLen int) string { func appendChar(char rune, wrapLen int, lineLen *int, inEscSeq bool, lastSeenEscSeq string, out *strings.Builder) { // handle reaching the end of the line as dictated by wrapLen or by finding // a newline character - if (*lineLen == wrapLen && !inEscSeq && char != '\n') || (char == '\n') { + if (*lineLen >= wrapLen && !inEscSeq && char != '\n') || (char == '\n') { if lastSeenEscSeq != "" { // terminate escape sequence and the line; and restart the escape // sequence in the next line @@ -122,7 +122,7 @@ func appendWord(word string, lineIdx *int, lastSeenEscSeq string, wrapLen int, o inEscSeq = true lastSeenEscSeq = "" } - if inEscSeq { + if inEscSeq && len(lastSeenEscSeq) < escSeqMaxLength { lastSeenEscSeq += string(char) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 40d4225..028c12c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -57,7 +57,7 @@ github.com/hashicorp/go-rootcerts ## explicit; go 1.20 github.com/hashicorp/nomad/api github.com/hashicorp/nomad/api/contexts -# github.com/jedib0t/go-pretty/v6 v6.7.10 +# github.com/jedib0t/go-pretty/v6 v6.8.1 ## explicit; go 1.18 github.com/jedib0t/go-pretty/v6/table github.com/jedib0t/go-pretty/v6/text