Escape pipe char for Markdown table

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2021-09-03 00:59:15 +02:00
Родитель cf46896cec
Коммит be85b2165f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 3248E46B6BB8C7F7
7 изменённых файлов: 355 добавлений и 21 удалений

Просмотреть файл

@ -179,10 +179,14 @@ func mdCmdOutput(cmd *cobra.Command, old string) (string, error) {
}
name += "`"
name = mdMakeLink(name, f.Name, f, isLink)
fmt.Fprintf(b, "%s | %s |\n", name, f.Usage)
fmt.Fprintf(b, "%s | %s |\n", mdEscapePipe(name), mdEscapePipe(f.Usage))
})
fmt.Fprintln(b, "")
}
return b.String(), nil
}
func mdEscapePipe(s string) string {
return strings.ReplaceAll(s, `|`, `\|`)
}

Просмотреть файл

@ -21,24 +21,63 @@ import (
"testing"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
//nolint:errcheck
func TestGenMarkdownTree(t *testing.T) {
c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
s := &cobra.Command{Use: "sub [OPTIONS] arg1 arg2"}
flags := s.Flags()
_ = flags.Bool("push", false, "Shorthand for --output=type=registry")
_ = flags.Bool("load", false, "Shorthand for --output=type=docker")
_ = flags.StringArrayP("tag", "t", []string{}, "Name and optionally a tag in the 'name:tag' format")
flags.SetAnnotation("tag", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#tag-an-image--t"})
_ = flags.StringArray("build-arg", []string{}, "Set build-time variables")
flags.SetAnnotation("build-arg", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg"})
_ = flags.StringP("file", "f", "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")
flags.SetAnnotation("file", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f"})
_ = flags.StringArray("label", []string{}, "Set metadata for an image")
_ = flags.StringArray("cache-from", []string{}, "External cache sources (eg. user/app:cache, type=local,src=path/to/dir)")
_ = flags.StringArray("cache-to", []string{}, "Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir)")
_ = flags.String("target", "", "Set the target build stage to build.")
flags.SetAnnotation("target", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#specifying-target-build-stage---target"})
_ = flags.StringSlice("allow", []string{}, "Allow extra privileged entitlement, e.g. network.host, security.insecure")
_ = flags.StringArray("platform", []string{}, "Set target platform for build")
_ = flags.StringArray("secret", []string{}, "Secret file to expose to the build: id=mysecret,src=/local/secret")
_ = flags.StringArray("ssh", []string{}, "SSH agent socket or keys to expose to the build (format: `default|<id>[=<socket>|<key>[,<key>]]`)")
_ = flags.StringArrayP("output", "o", []string{}, "Output destination (format: type=local,dest=path)")
// not implemented
_ = flags.String("network", "default", "Set the networking mode for the RUN instructions during build")
_ = flags.StringSlice("add-host", []string{}, "Add a custom host-to-IP mapping (host:ip)")
_ = flags.SetAnnotation("add-host", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host"})
_ = flags.String("iidfile", "", "Write the image ID to the file")
// hidden flags
_ = flags.BoolP("quiet", "q", false, "Suppress the build output and print image ID on success")
flags.MarkHidden("quiet")
_ = flags.Bool("squash", false, "Squash newly built layers into a single new layer")
flags.MarkHidden("squash")
_ = flags.String("ulimit", "", "Ulimit options")
flags.MarkHidden("ulimit")
_ = flags.StringSlice("security-opt", []string{}, "Security options")
flags.MarkHidden("security-opt")
_ = flags.Bool("compress", false, "Compress the build context using gzip")
c.AddCommand(s)
tmpdir, err := ioutil.TempDir("", "test-gen-markdown-tree")
if err != nil {
t.Fatalf("Failed to create tmpdir: %s", err.Error())
}
require.NoError(t, err)
defer os.RemoveAll(tmpdir)
require.NoError(t, GenMarkdownTree(c, tmpdir))
if err := GenMarkdownTree(c, tmpdir); err != nil {
t.Fatalf("GenMarkdownTree failed: %s", err.Error())
}
if _, err := os.Stat(filepath.Join(tmpdir, "sub.md")); err != nil {
t.Fatalf("Expected file 'sub.md' to exist")
}
fres := filepath.Join(tmpdir, "sub.md")
require.FileExists(t, fres)
bres, err := ioutil.ReadFile(fres)
require.NoError(t, err)
bexc, err := ioutil.ReadFile("fixtures/sub.md")
require.NoError(t, err)
assert.Equal(t, string(bres), string(bexc))
}

Просмотреть файл

@ -21,24 +21,63 @@ import (
"testing"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
//nolint:errcheck
func TestGenYamlTree(t *testing.T) {
c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
s := &cobra.Command{Use: "sub [OPTIONS] arg1 arg2", Run: func(cmd *cobra.Command, args []string) {}}
flags := s.Flags()
_ = flags.Bool("push", false, "Shorthand for --output=type=registry")
_ = flags.Bool("load", false, "Shorthand for --output=type=docker")
_ = flags.StringArrayP("tag", "t", []string{}, "Name and optionally a tag in the 'name:tag' format")
flags.SetAnnotation("tag", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#tag-an-image--t"})
_ = flags.StringArray("build-arg", []string{}, "Set build-time variables")
flags.SetAnnotation("build-arg", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg"})
_ = flags.StringP("file", "f", "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")
flags.SetAnnotation("file", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f"})
_ = flags.StringArray("label", []string{}, "Set metadata for an image")
_ = flags.StringArray("cache-from", []string{}, "External cache sources (eg. user/app:cache, type=local,src=path/to/dir)")
_ = flags.StringArray("cache-to", []string{}, "Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir)")
_ = flags.String("target", "", "Set the target build stage to build.")
flags.SetAnnotation("target", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#specifying-target-build-stage---target"})
_ = flags.StringSlice("allow", []string{}, "Allow extra privileged entitlement, e.g. network.host, security.insecure")
_ = flags.StringArray("platform", []string{}, "Set target platform for build")
_ = flags.StringArray("secret", []string{}, "Secret file to expose to the build: id=mysecret,src=/local/secret")
_ = flags.StringArray("ssh", []string{}, "SSH agent socket or keys to expose to the build (format: `default|<id>[=<socket>|<key>[,<key>]]`)")
_ = flags.StringArrayP("output", "o", []string{}, "Output destination (format: type=local,dest=path)")
// not implemented
_ = flags.String("network", "default", "Set the networking mode for the RUN instructions during build")
_ = flags.StringSlice("add-host", []string{}, "Add a custom host-to-IP mapping (host:ip)")
_ = flags.SetAnnotation("add-host", "docs.external.url", []string{"https://docs.docker.com/engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host"})
_ = flags.String("iidfile", "", "Write the image ID to the file")
// hidden flags
_ = flags.BoolP("quiet", "q", false, "Suppress the build output and print image ID on success")
flags.MarkHidden("quiet")
_ = flags.Bool("squash", false, "Squash newly built layers into a single new layer")
flags.MarkHidden("squash")
_ = flags.String("ulimit", "", "Ulimit options")
flags.MarkHidden("ulimit")
_ = flags.StringSlice("security-opt", []string{}, "Security options")
flags.MarkHidden("security-opt")
_ = flags.Bool("compress", false, "Compress the build context using gzip")
c.AddCommand(s)
tmpdir, err := ioutil.TempDir("", "test-gen-yaml-tree")
if err != nil {
t.Fatalf("Failed to create tmpdir: %s", err.Error())
}
require.NoError(t, err)
defer os.RemoveAll(tmpdir)
require.NoError(t, GenYamlTree(c, tmpdir))
if err := GenYamlTree(c, tmpdir); err != nil {
t.Fatalf("GenYamlTree failed: %s", err.Error())
}
if _, err := os.Stat(filepath.Join(tmpdir, "do_sub.yaml")); err != nil {
t.Fatalf("Expected file 'do_sub.yaml' to exist")
}
fres := filepath.Join(tmpdir, "do_sub.yaml")
require.FileExists(t, fres)
bres, err := ioutil.ReadFile(fres)
require.NoError(t, err)
bexc, err := ioutil.ReadFile("fixtures/do_sub.yaml")
require.NoError(t, err)
assert.Equal(t, string(bres), string(bexc))
}

218
fixtures/do_sub.yaml Normal file
Просмотреть файл

@ -0,0 +1,218 @@
command: do sub
usage: do sub [OPTIONS] arg1 arg2 [flags]
pname: do
plink: do.yaml
options:
- option: add-host
value_type: stringSlice
default_value: '[]'
description: Add a custom host-to-IP mapping (host:ip)
details_url: /engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: allow
value_type: stringSlice
default_value: '[]'
description: |
Allow extra privileged entitlement, e.g. network.host, security.insecure
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: build-arg
value_type: stringArray
default_value: '[]'
description: Set build-time variables
details_url: /engine/reference/commandline/build/#set-build-time-variables---build-arg
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: cache-from
value_type: stringArray
default_value: '[]'
description: |
External cache sources (eg. user/app:cache, type=local,src=path/to/dir)
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: cache-to
value_type: stringArray
default_value: '[]'
description: |
Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir)
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: compress
value_type: bool
default_value: "false"
description: Compress the build context using gzip
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: file
shorthand: f
value_type: string
description: Name of the Dockerfile (Default is 'PATH/Dockerfile')
details_url: /engine/reference/commandline/build/#specify-a-dockerfile--f
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: iidfile
value_type: string
description: Write the image ID to the file
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: label
value_type: stringArray
default_value: '[]'
description: Set metadata for an image
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: load
value_type: bool
default_value: "false"
description: Shorthand for --output=type=docker
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: network
value_type: string
default_value: default
description: Set the networking mode for the RUN instructions during build
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: output
shorthand: o
value_type: stringArray
default_value: '[]'
description: 'Output destination (format: type=local,dest=path)'
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: platform
value_type: stringArray
default_value: '[]'
description: Set target platform for build
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: push
value_type: bool
default_value: "false"
description: Shorthand for --output=type=registry
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: quiet
shorthand: q
value_type: bool
default_value: "false"
description: Suppress the build output and print image ID on success
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: secret
value_type: stringArray
default_value: '[]'
description: 'Secret file to expose to the build: id=mysecret,src=/local/secret'
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: security-opt
value_type: stringSlice
default_value: '[]'
description: Security options
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: squash
value_type: bool
default_value: "false"
description: Squash newly built layers into a single new layer
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: ssh
value_type: stringArray
default_value: '[]'
description: |
SSH agent socket or keys to expose to the build (format: `default|<id>[=<socket>|<key>[,<key>]]`)
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: tag
shorthand: t
value_type: stringArray
default_value: '[]'
description: Name and optionally a tag in the 'name:tag' format
details_url: /engine/reference/commandline/build/#tag-an-image--t
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: target
value_type: string
description: Set the target build stage to build.
details_url: /engine/reference/commandline/build/#specifying-target-build-stage---target
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: ulimit
value_type: string
description: Ulimit options
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
deprecated: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false

29
fixtures/sub.md Normal file
Просмотреть файл

@ -0,0 +1,29 @@
# do sub
<!---MARKER_GEN_START-->
### Options
| Name | Description |
| --- | --- |
| [`--add-host stringSlice`](https://docs.docker.com/engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host) | Add a custom host-to-IP mapping (host:ip) |
| `--allow stringSlice` | Allow extra privileged entitlement, e.g. network.host, security.insecure |
| [`--build-arg stringArray`](https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg) | Set build-time variables |
| `--cache-from stringArray` | External cache sources (eg. user/app:cache, type=local,src=path/to/dir) |
| `--cache-to stringArray` | Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir) |
| `--compress` | Compress the build context using gzip |
| [`-f`](https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f), [`--file string`](https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f) | Name of the Dockerfile (Default is 'PATH/Dockerfile') |
| `--iidfile string` | Write the image ID to the file |
| `--label stringArray` | Set metadata for an image |
| `--load` | Shorthand for --output=type=docker |
| `--network string` | Set the networking mode for the RUN instructions during build |
| `-o`, `--output stringArray` | Output destination (format: type=local,dest=path) |
| `--platform stringArray` | Set target platform for build |
| `--push` | Shorthand for --output=type=registry |
| `--secret stringArray` | Secret file to expose to the build: id=mysecret,src=/local/secret |
| `--ssh stringArray` | SSH agent socket or keys to expose to the build (format: `default\|<id>[=<socket>\|<key>[,<key>]]`) |
| [`-t`](https://docs.docker.com/engine/reference/commandline/build/#tag-an-image--t), [`--tag stringArray`](https://docs.docker.com/engine/reference/commandline/build/#tag-an-image--t) | Name and optionally a tag in the 'name:tag' format |
| [`--target string`](https://docs.docker.com/engine/reference/commandline/build/#specifying-target-build-stage---target) | Set the target build stage to build. |
<!---MARKER_GEN_END-->

1
go.mod
Просмотреть файл

@ -6,5 +6,6 @@ require (
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
gopkg.in/yaml.v2 v2.4.0
)

4
go.sum
Просмотреть файл

@ -57,6 +57,7 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -193,6 +194,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -218,6 +220,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -559,6 +562,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=