fix(site): escape flags with backticks (#4479)

* fix(site): escape flags with backticks

In the generated markdown docs, flags like `--foo` inside
help texts currently get pretty-printed as `–foo` with an em-dash.

This change applies backticks via a regex replacement, so that
they appear as `--foo` in the docs but remain as --foo in the
CLI output.

---------

Co-authored-by: Julio Lopez <1953782+julio-lopez@users.noreply.github.com>
This commit is contained in:
blenderfreaky
2025-04-24 08:42:29 +02:00
committed by GitHub
parent f12fafb516
commit 6cd728394d
2 changed files with 96 additions and 4 deletions

View File

@@ -8,6 +8,7 @@
"log"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
@@ -31,6 +32,14 @@
dirMode = 0o750
)
// The group at the start is to avoid matching things like "in-place".
var escapeFlagsRe = regexp.MustCompile(`(^|\s)(--?\w+[-\w]*)`)
// escapeFlags escapes command-line flag references in help text by wrapping them in backticks.
func escapeFlags(text string) string {
return escapeFlagsRe.ReplaceAllString(text, "$1`$2`")
}
//nolint:gochecknoglobals
var overrideDefault = map[string]string{
"config-file": "repository.config",
@@ -75,9 +84,9 @@ func emitFlags(w io.Writer, flags []*kingpin.FlagModel) {
defaultValue = "`false`"
}
fmt.Fprintf(w, "| `--[no-]%v` | %v | %v | %v%v |\n", f.Name, shortFlag, defaultValue, maybeAdvanced, f.Help) //nolint:errcheck
fmt.Fprintf(w, "| `--[no-]%v` | %v | %v | %v%v |\n", f.Name, shortFlag, defaultValue, maybeAdvanced, escapeFlags(f.Help)) //nolint:errcheck
} else {
fmt.Fprintf(w, "| `--%v` | %v | %v | %v%v |\n", f.Name, shortFlag, defaultValue, maybeAdvanced, f.Help) //nolint:errcheck
fmt.Fprintf(w, "| `--%v` | %v | %v | %v%v |\n", f.Name, shortFlag, defaultValue, maybeAdvanced, escapeFlags(f.Help)) //nolint:errcheck
}
}
@@ -122,7 +131,7 @@ func emitArgs(w io.Writer, args []*kingpin.ArgModel) {
})
for _, f := range args2 {
fmt.Fprintf(w, "| `%v` | %v |\n", f.Name, f.Help) //nolint:errcheck
fmt.Fprintf(w, "| `%v` | %v |\n", f.Name, escapeFlags(f.Help)) //nolint:errcheck
}
fmt.Fprintf(w, "\n") //nolint:errcheck
@@ -297,7 +306,7 @@ func generateSubcommandPage(fname string, cmd *kingpin.CmdModel) {
}
fmt.Fprintf(f, "```shell\n$ kopia %v%v%v\n```\n\n", cmd.FullCommand, flagSummary, argSummary) //nolint:errcheck
fmt.Fprintf(f, "%v\n\n", cmd.Help) //nolint:errcheck
fmt.Fprintf(f, "%v\n\n", escapeFlags(cmd.Help)) //nolint:errcheck
emitFlags(f, cmd.Flags)
emitArgs(f, cmd.Args)

View File

@@ -0,0 +1,83 @@
package main
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestEscapeFlags(t *testing.T) {
cases := []struct {
name string
input string
expected string
}{
{
name: "empty string",
input: "",
expected: "",
},
{
name: "basic single flag",
input: "use -flag to enable",
expected: "use `-flag` to enable",
},
{
name: "double dash flag",
input: "use --long-flag-name to configure",
expected: "use `--long-flag-name` to configure",
},
{
name: "multiple flags",
input: "use -a or --bee flags",
expected: "use `-a` or `--bee` flags",
},
{
name: "should not match in-place",
input: "performs in-place modification",
expected: "performs in-place modification",
},
{
name: "flags with numbers and hyphens",
input: "use --http2-max-streams or -h2-timeout",
expected: "use `--http2-max-streams` or `-h2-timeout`",
},
{
name: "flag at start of string",
input: "-flag at start",
expected: "`-flag` at start",
},
{
name: "existing backticks",
input: "use `--existing` and -new flags",
expected: "use `--existing` and `-new` flags",
},
{
name: "multiple spaces before flag",
input: "test -flag with spaces",
expected: "test `-flag` with spaces",
},
{
name: "mixed valid and invalid patterns",
input: "test in-place and -valid --flags",
expected: "test in-place and `-valid` `--flags`",
},
{
name: "separator line",
input: "---------------",
expected: "---------------",
},
{
name: "too many dashes",
input: "none ---of these --- dashes ----should match",
expected: "none ---of these --- dashes ----should match",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := escapeFlags(tc.input)
require.Equal(t, tc.expected, got)
})
}
}