Skip to content

Commit 030cc31

Browse files
authored
fix: escape parsing of angle-brackets in Mintlify doc gen (#668)
1 parent 2d1b55b commit 030cc31

2 files changed

Lines changed: 49 additions & 4 deletions

File tree

internal/docgen/mintlify.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ func (MintlifyFormatter) Synopsis(meta CommandMeta) string {
5757

5858
func (MintlifyFormatter) FlagsSection(flags, inherited string) string {
5959
flags = linkifyKosliDocsURLs(flags)
60+
flags = escapeMintlifyProse(flags)
6061
inherited = linkifyKosliDocsURLs(inherited)
62+
inherited = escapeMintlifyProse(inherited)
6163
var b strings.Builder
6264
if flags != "" {
6365
b.WriteString("## Flags\n")
@@ -177,16 +179,39 @@ func linkifyKosliDocsURLs(s string) string {
177179
return kosliDocsURLPattern.ReplaceAllString(s, "[docs]($1)")
178180
}
179181

180-
var angleBracketPattern = regexp.MustCompile(`<([A-Z][A-Z0-9_-]*)>`)
182+
// angleBracketPattern matches placeholder patterns in angle brackets that MDX
183+
// would interpret as JSX tags. Matches:
184+
// - uppercase placeholders like <IMAGE-NAME>
185+
// - patterns with pipes like <hours|days|weeks|months> or <COMMIT_SHA1|FINGERPRINT>
186+
// - lowercase placeholders like <fingerprint>, <commit_sha>
187+
//
188+
// Standard HTML tags like <a>, <br/>, <pre>, <code> are filtered out in escapeProseFragment.
189+
var angleBracketPattern = regexp.MustCompile(`<([a-zA-Z][a-zA-Z0-9_|-]*)>`)
190+
191+
var htmlTags = map[string]bool{
192+
"a": true, "br": true, "pre": true, "code": true, "em": true,
193+
"strong": true, "p": true, "div": true, "span": true, "ul": true,
194+
"ol": true, "li": true, "img": true, "table": true, "tr": true,
195+
"td": true, "th": true, "thead": true, "tbody": true,
196+
"h1": true, "h2": true, "h3": true, "h4": true, "h5": true, "h6": true,
197+
}
181198

182199
func escapeProseFragment(s string) string {
183200
// Escape curly braces: {expr} -> \{expr\}
184201
s = strings.ReplaceAll(s, "{", "\\{")
185202
s = strings.ReplaceAll(s, "}", "\\}")
186203

187-
// Escape <UPPERCASE_WORD> patterns -> `UPPERCASE_WORD`
188-
// but leave HTML tags like <a>, <br/>, <pre> alone
189-
s = angleBracketPattern.ReplaceAllString(s, "`$1`")
204+
// Escape angle-bracket placeholders -> backtick-wrapped
205+
// but leave standard HTML tags alone
206+
s = angleBracketPattern.ReplaceAllStringFunc(s, func(match string) string {
207+
inner := match[1 : len(match)-1]
208+
// Check the base tag name (before any pipe) against HTML tags
209+
baseName := strings.SplitN(inner, "|", 2)[0]
210+
if htmlTags[strings.ToLower(baseName)] {
211+
return match
212+
}
213+
return "`" + inner + "`"
214+
})
190215

191216
return s
192217
}

internal/docgen/mintlify_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,26 @@ func TestEscapeMintlifyProse(t *testing.T) {
199199
input: "Use <a href=\"x\">link</a>",
200200
want: "Use <a href=\"x\">link</a>",
201201
},
202+
{
203+
name: "lowercase angle brackets with pipes converted",
204+
input: "Use <hours|days|weeks|months> for time",
205+
want: "Use `hours|days|weeks|months` for time",
206+
},
207+
{
208+
name: "uppercase angle brackets with pipes converted",
209+
input: "Format: <COMMIT_SHA1|ARTIFACT_FINGERPRINT>",
210+
want: "Format: `COMMIT_SHA1|ARTIFACT_FINGERPRINT`",
211+
},
212+
{
213+
name: "lowercase single-word placeholders converted",
214+
input: "flowName@<fingerprint> or flowName:<commit_sha>",
215+
want: "flowName@`fingerprint` or flowName:`commit_sha`",
216+
},
217+
{
218+
name: "double curly braces escaped",
219+
input: "--jira-secondary-source ${{ github.head_ref }}",
220+
want: "--jira-secondary-source $\\{\\{ github.head_ref \\}\\}",
221+
},
202222
{
203223
name: "code fence content not escaped",
204224
input: "text ```\n{code}\n<FOO>\n``` more {text}",

0 commit comments

Comments
 (0)