Skip to content

Commit a69afc8

Browse files
authored
Add opt-in documentation link formatting (#107)
Let consumers retain navigation targets while keeping the default link-stripping behavior. The variadic option changes the function type, so stored function values may need updating.
1 parent a950f4b commit a69afc8

3 files changed

Lines changed: 75 additions & 5 deletions

File tree

AGENTS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@
4646
- All internal doc links and remaining markdown links are stripped to plain text (URL removed).
4747
- Duplicate child names are deduplicated in search results.
4848

49+
### Shared transform API
50+
- `docs.Transform(content, version, opts ...TransformOption)` accepts optional link formatting; its default still strips links, and the CLI continues to use that default until it updates its docs dependency.
51+
- `docs.WithLinkSlugs()` formats current-version k6 links as text followed by an inline slug and preserves other markdown links; custom options set exported `TransformOptions.FormatLink`.
52+
- This is a runtime transform; bundle generation and `mcp-k6` behavior remain unchanged, and existing bundles need no regeneration.
53+
4954
### Documentation version handling
5055
- Auto-detects k6 version from Go build info.
5156
- Maps to wildcard: `v1.5.0``v1.5.x`, `v1.6.0-rc.1``v1.6.x`.

docs/transform.go

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package docs
22

33
import (
4+
"net/url"
45
"regexp"
56
"strings"
67
)
@@ -22,7 +23,7 @@ var (
2223
reImageLink = regexp.MustCompile(`!\[([^\]]*)\]\([^)]+\)`)
2324
// reMarkdownLink matches markdown links: [text](url)
2425
// The text portion allows one level of nested brackets for cases like [get(url, [params])](url).
25-
reMarkdownLink = regexp.MustCompile(`\[((?:[^\[\]]|\[[^\]]*\])*)\]\([^)]+\)`)
26+
reMarkdownLink = regexp.MustCompile(`\[((?:[^\[\]]|\[[^\]]*\])*)\]\(([^)]+)\)`)
2627
)
2728

2829
// PrepareTransform resolves docs/shared shortcodes using the shared content
@@ -46,10 +47,46 @@ func PrepareTransform(content string, sharedContent map[string]string) string {
4647
})
4748
}
4849

50+
// TransformOption configures optional markdown transformations.
51+
type TransformOption func(*TransformOptions)
52+
53+
// TransformOptions controls markdown link formatting.
54+
type TransformOptions struct {
55+
// FormatLink renders a link from its text, target URL, and documentation version.
56+
FormatLink func(text, target, version string) string
57+
}
58+
59+
// WithLinkSlugs shows current-version doc links as text followed by an inline
60+
// slug and preserves other markdown links, including web links.
61+
func WithLinkSlugs() TransformOption {
62+
return func(opts *TransformOptions) {
63+
opts.FormatLink = func(text, target, version string) string {
64+
link := "[" + text + "](" + target + ")"
65+
u, err := url.Parse(target)
66+
if err != nil || u.Host != "" && u.Host != "grafana.com" {
67+
return link
68+
}
69+
rest, ok := strings.CutPrefix(u.Path, "/docs/k6/")
70+
if !ok {
71+
return link
72+
}
73+
linkVersion, slug, ok := strings.Cut(rest, "/")
74+
if !ok || VersionWildcard(linkVersion) != VersionWildcard(version) {
75+
return link
76+
}
77+
slug = strings.Trim(slug, "/")
78+
if slug == "" {
79+
return link
80+
}
81+
return text + " (`" + slug + "`)"
82+
}
83+
}
84+
}
85+
4986
// Transform applies markdown cleanup to content. It handles all pure text
5087
// transforms (shortcode stripping, admonition conversion, link stripping,
5188
// frontmatter removal, whitespace normalization). The pipeline runs in a
52-
// fixed order:
89+
// fixed order (WithLinkSlugs opts into inline doc slugs and preserved web links):
5390
// 1. Strip code tags
5491
// 2. Convert admonitions to blockquotes
5592
// 3. Strip section tags
@@ -63,10 +100,16 @@ func PrepareTransform(content string, sharedContent map[string]string) string {
63100
// 7. Strip HTML comments
64101
// 8. Strip YAML frontmatter
65102
// 9. Normalize whitespace
66-
func Transform(content, version string) string {
103+
func Transform(content, version string, opts ...TransformOption) string {
67104
if content == "" {
68105
return ""
69106
}
107+
options := TransformOptions{
108+
FormatLink: func(text, _, _ string) string { return text },
109+
}
110+
for _, opt := range opts {
111+
opt(&options)
112+
}
70113

71114
s := content
72115

@@ -118,8 +161,11 @@ func Transform(content, version string) string {
118161
// 7. Strip markdown image links, keeping alt text.
119162
s = reImageLink.ReplaceAllString(s, "$1")
120163

121-
// 7a. Strip remaining markdown links, keeping link text.
122-
s = reMarkdownLink.ReplaceAllString(s, "$1")
164+
// 7a. Apply the selected link formatter.
165+
s = reMarkdownLink.ReplaceAllStringFunc(s, func(link string) string {
166+
m := reMarkdownLink.FindStringSubmatch(link)
167+
return options.FormatLink(m[1], m[2], version)
168+
})
123169

124170
// 8. Strip HTML comments.
125171
s = reHTMLComment.ReplaceAllString(s, "")

docs/transform_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package docs
2+
3+
import "testing"
4+
5+
func TestTransformWithLinkSlugs(t *testing.T) {
6+
t.Parallel()
7+
8+
const input = `Refer to [Running k6](https://grafana.com/docs/k6/<K6_VERSION>/get-started/running-k6/).
9+
See [results](/docs/k6/v1.6.1/get-started/running-k6/?view=all#results).
10+
Keep [older docs](https://grafana.com/docs/k6/v1.5.x/get-started/running-k6/) and [other resources](https://example.com/docs/k6/v1.6.x/get-started/running-k6/).`
11+
const want = "Refer to Running k6 (`get-started/running-k6`).\n" +
12+
"See results (`get-started/running-k6`).\n" +
13+
"Keep [older docs](https://grafana.com/docs/k6/v1.5.x/get-started/running-k6/) and " +
14+
"[other resources](https://example.com/docs/k6/v1.6.x/get-started/running-k6/)."
15+
16+
if got := Transform(input, "v1.6.x", WithLinkSlugs()); got != want {
17+
t.Errorf("Transform() = %q, want %q", got, want)
18+
}
19+
}

0 commit comments

Comments
 (0)