diff --git a/go.mod b/go.mod index a6e8b70741..0b59b36948 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.19 require ( github.com/BTBurke/k8sresource v1.2.0 - github.com/MakeNowJust/heredoc/v2 v2.0.1 github.com/Masterminds/semver v1.5.0 github.com/XSAM/otelsql v0.19.0 github.com/antihax/optional v1.0.0 @@ -62,7 +61,6 @@ require ( github.com/pkg/errors v0.9.1 github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285 github.com/rs/zerolog v1.29.0 - github.com/russross/blackfriday v1.6.0 github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.15.0 @@ -104,6 +102,7 @@ require ( github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect @@ -292,6 +291,7 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rs/cors v1.7.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.36.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.9.4 // indirect diff --git a/go.sum b/go.sum index 5465188188..a3205dbcab 100644 --- a/go.sum +++ b/go.sum @@ -98,8 +98,8 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A= -github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= @@ -2028,9 +2028,8 @@ github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThC github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= -github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= diff --git a/pkg/util/templates/markdown.go b/pkg/util/templates/markdown.go deleted file mode 100644 index bf4bb28687..0000000000 --- a/pkg/util/templates/markdown.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. -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 templates - -import ( - "bytes" - "fmt" - "strings" - - "github.com/russross/blackfriday" -) - -const linebreak = "\n" - -// ASCIIRenderer implements blackfriday.Renderer -var _ blackfriday.Renderer = &ASCIIRenderer{} - -// ASCIIRenderer is a blackfriday.Renderer intended for rendering markdown -// documents as plain text, well suited for human reading on terminals. -type ASCIIRenderer struct { - Indentation string - - listItemCount uint - listLevel uint -} - -// NormalText gets a text chunk *after* the markdown syntax was already -// processed and does a final cleanup on things we don't expect here, like -// removing linebreaks on things that are not a paragraph break (auto unwrap). -func (r *ASCIIRenderer) NormalText(out *bytes.Buffer, text []byte) { - raw := string(text) - lines := strings.Split(raw, linebreak) - for _, line := range lines { - trimmed := strings.Trim(line, " \n\t") - if len(trimmed) > 0 && trimmed[0] != '_' { - out.WriteString(" ") - } - out.WriteString(trimmed) - } -} - -// List renders the start and end of a list. -func (r *ASCIIRenderer) List(out *bytes.Buffer, text func() bool, flags int) { - r.listLevel++ - out.WriteString(linebreak) - text() - r.listLevel-- -} - -// ListItem renders list items and supports both ordered and unordered lists. -func (r *ASCIIRenderer) ListItem(out *bytes.Buffer, text []byte, flags int) { - if flags&blackfriday.LIST_ITEM_BEGINNING_OF_LIST != 0 { - r.listItemCount = 1 - } else { - r.listItemCount++ - } - indent := strings.Repeat(r.Indentation, int(r.listLevel)) - var bullet string - if flags&blackfriday.LIST_TYPE_ORDERED != 0 { - bullet += fmt.Sprintf("%d.", r.listItemCount) - } else { - bullet += "*" - } - out.WriteString(indent + bullet + " ") - r.fw(out, text) - out.WriteString(linebreak) -} - -// Paragraph renders the start and end of a paragraph. -func (r *ASCIIRenderer) Paragraph(out *bytes.Buffer, text func() bool) { - out.WriteString(linebreak) - text() - out.WriteString(linebreak) -} - -// BlockCode renders a chunk of text that represents source code. -func (r *ASCIIRenderer) BlockCode(out *bytes.Buffer, text []byte, lang string) { - out.WriteString(linebreak) - lines := []string{} - for _, line := range strings.Split(string(text), linebreak) { - indented := r.Indentation + line - lines = append(lines, indented) - } - out.WriteString(strings.Join(lines, linebreak)) -} - -func (r *ASCIIRenderer) GetFlags() int { return 0 } -func (r *ASCIIRenderer) HRule(out *bytes.Buffer) { - out.WriteString(linebreak + "----------" + linebreak) -} -func (r *ASCIIRenderer) LineBreak(out *bytes.Buffer) { out.WriteString(linebreak) } -func (r *ASCIIRenderer) TitleBlock(out *bytes.Buffer, text []byte) { r.fw(out, text) } -func (r *ASCIIRenderer) Header(out *bytes.Buffer, text func() bool, level int, id string) { text() } -func (r *ASCIIRenderer) BlockHtml(out *bytes.Buffer, text []byte) { r.fw(out, text) } //nolint:stylecheck,lll // inherited caps -func (r *ASCIIRenderer) BlockQuote(out *bytes.Buffer, text []byte) { r.fw(out, text) } -func (r *ASCIIRenderer) TableRow(out *bytes.Buffer, text []byte) { r.fw(out, text) } -func (r *ASCIIRenderer) TableHeaderCell(out *bytes.Buffer, text []byte, align int) { r.fw(out, text) } -func (r *ASCIIRenderer) TableCell(out *bytes.Buffer, text []byte, align int) { r.fw(out, text) } -func (r *ASCIIRenderer) Footnotes(out *bytes.Buffer, text func() bool) { text() } -func (r *ASCIIRenderer) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) { - r.fw(out, text) -} -func (r *ASCIIRenderer) AutoLink(out *bytes.Buffer, link []byte, kind int) { r.fw(out, link) } -func (r *ASCIIRenderer) CodeSpan(out *bytes.Buffer, text []byte) { r.fw(out, text) } -func (r *ASCIIRenderer) DoubleEmphasis(out *bytes.Buffer, text []byte) { r.fw(out, text) } -func (r *ASCIIRenderer) Emphasis(out *bytes.Buffer, text []byte) { r.fw(out, text) } -func (r *ASCIIRenderer) RawHtmlTag(out *bytes.Buffer, text []byte) { r.fw(out, text) } //nolint:stylecheck // inherited caps -func (r *ASCIIRenderer) TripleEmphasis(out *bytes.Buffer, text []byte) { r.fw(out, text) } -func (r *ASCIIRenderer) StrikeThrough(out *bytes.Buffer, text []byte) { r.fw(out, text) } -func (r *ASCIIRenderer) FootnoteRef(out *bytes.Buffer, ref []byte, id int) { r.fw(out, ref) } -func (r *ASCIIRenderer) Entity(out *bytes.Buffer, entity []byte) { r.fw(out, entity) } -func (r *ASCIIRenderer) Smartypants(out *bytes.Buffer, text []byte) { r.fw(out, text) } -func (r *ASCIIRenderer) DocumentHeader(out *bytes.Buffer) {} -func (r *ASCIIRenderer) DocumentFooter(out *bytes.Buffer) {} -func (r *ASCIIRenderer) TocHeaderWithAnchor(text []byte, level int, anchor string) {} -func (r *ASCIIRenderer) TocHeader(text []byte, level int) {} -func (r *ASCIIRenderer) TocFinalize() {} - -func (r *ASCIIRenderer) Table(out *bytes.Buffer, header, body []byte, columnData []int) { - r.fw(out, header, body) -} - -func (r *ASCIIRenderer) Link(out *bytes.Buffer, link, title, content []byte) { - out.WriteString(" ") - r.fw(out, link) -} - -func (r *ASCIIRenderer) Image(out *bytes.Buffer, link, title, alt []byte) { - r.fw(out, link) -} - -func (r *ASCIIRenderer) fw(out *bytes.Buffer, text ...[]byte) { - for _, t := range text { - out.Write(t) - } -} diff --git a/pkg/util/templates/normalizers.go b/pkg/util/templates/normalizers.go index d62653f99c..513a7d8fe3 100644 --- a/pkg/util/templates/normalizers.go +++ b/pkg/util/templates/normalizers.go @@ -1,71 +1,15 @@ -/* -Copyright 2016 The Kubernetes Authors. -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 templates import ( - "strings" - - "github.com/MakeNowJust/heredoc/v2" - "github.com/russross/blackfriday" + "k8s.io/kubectl/pkg/util/templates" ) -const Indentation = ` ` - // LongDesc normalizes a command's long description to follow the conventions. func LongDesc(s string) string { - if s == "" { - return s - } - return normalizer{s}.heredoc().markdown().trim().string + return templates.LongDesc(s) } // Examples normalizes a command's examples to follow the conventions. func Examples(s string) string { - if s == "" { - return s - } - return normalizer{s}.trim().indent().string -} - -type normalizer struct { - string -} - -func (s normalizer) markdown() normalizer { - bytes := []byte(s.string) - formatted := blackfriday.Markdown(bytes, &ASCIIRenderer{Indentation: Indentation}, blackfriday.EXTENSION_NO_INTRA_EMPHASIS) - s.string = string(formatted) - return s -} - -func (s normalizer) heredoc() normalizer { - s.string = heredoc.Doc(s.string) - return s -} - -func (s normalizer) trim() normalizer { - s.string = strings.TrimSpace(s.string) - return s -} - -func (s normalizer) indent() normalizer { - var indentedLines []string - for _, line := range strings.Split(s.string, "\n") { - trimmed := strings.TrimSpace(line) - indented := Indentation + trimmed - indentedLines = append(indentedLines, indented) - } - s.string = strings.Join(indentedLines, "\n") - return s + return templates.Examples(s) } diff --git a/pkg/util/templates/normalizers_test.go b/pkg/util/templates/normalizers_test.go new file mode 100644 index 0000000000..ae0e45cf4a --- /dev/null +++ b/pkg/util/templates/normalizers_test.go @@ -0,0 +1,41 @@ +package templates + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLongDesc(t *testing.T) { + actual := LongDesc(` + Create a job from a file or from stdin. + + JSON and YAML formats are accepted. + `) + + assert.Equal(t, `Create a job from a file or from stdin. + + JSON and YAML formats are accepted.`, actual) +} + +func TestExamples(t *testing.T) { + actual := Examples(` + # Describe a job with the full ID + bacalhau describe e3f8c209-d683-4a41-b840-f09b88d087b9 + + # Describe a job with the a shortened ID + bacalhau describe 47805f5c + + # Describe a job and include all server and local events + bacalhau describe --include-events b6ad164a +`) + + assert.Equal(t, ` # Describe a job with the full ID + bacalhau describe e3f8c209-d683-4a41-b840-f09b88d087b9 + + # Describe a job with the a shortened ID + bacalhau describe 47805f5c + + # Describe a job and include all server and local events + bacalhau describe --include-events b6ad164a`, actual) +}