From 95599e96f6b9a732e1937d511cf87f9991c74f47 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Thu, 8 Oct 2026 01:31:18 +0000 Subject: [PATCH] Include autolink text in Markdown heading anchors --- docs/roadmap/remediation.md | 8 ++++++-- internal/validation/markdown.go | 3 +++ internal/validation/markdown_check_test.go | 3 +++ internal/validation/markdown_test.go | 12 +++++++++--- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index 2f465a0..ff869c8 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -1,7 +1,6 @@ # ReleaseKit implementation remediation -Status: Three open v0.2.0 findings (7–9). The six foundation findings (1–6) -are addressed. +Status: Two open v0.2.0 findings (8–9). Findings 1–7 are addressed. The v0.2.0 review covers committed state `edd670e` and the implementation commits after `89981ab`, against the [implementation plan](implementation.md), @@ -295,6 +294,11 @@ check, arbitrary inspection limit, or change to source-publication completion. ## 7. P2: Heading anchors omit autolink display text +**Resolution:** Addressed. Heading extraction includes autolink display labels. +Parser coverage includes URL/email headings and surrounding text; committed +fragment checks cover both forms. The new cases failed before the fix, and +`go test ./internal/validation` passed afterward. + **Owner:** [Markdown heading extraction](../../internal/validation/markdown.go), `markdownHeadingText`, lines 115–139. diff --git a/internal/validation/markdown.go b/internal/validation/markdown.go index ab62c9a..a32352a 100644 --- a/internal/validation/markdown.go +++ b/internal/validation/markdown.go @@ -128,6 +128,9 @@ func markdownHeadingText(heading *ast.Heading, source []byte) string { case *ast.CodeSpan: result.WriteString(node.Value.Value(source)) return + case *ast.AutoLink: + result.WriteString(node.Label.Value(source)) + return } for child := node.FirstChild(); child != nil; child = child.NextSibling() { appendNode(child) diff --git a/internal/validation/markdown_check_test.go b/internal/validation/markdown_check_test.go index 958b1d4..a9bb2d2 100644 --- a/internal/validation/markdown_check_test.go +++ b/internal/validation/markdown_check_test.go @@ -16,6 +16,8 @@ func TestCheckMarkdownLinksResolvesCommittedDestinationsAndFragments(t *testing. "# Start\n" + "[target](target.md?view=1#TARGET)\n" + "[same](#START)\n" + + "[url heading](autolinks.md#httpsexampleinvalid)\n" + + "[email heading](autolinks.md#maintainerexampleinvalid)\n" + "[top](#)\n" + "[directory](assets/?view=1)\n" + "[binary](image.bin#not-an-anchor)\n" + @@ -26,6 +28,7 @@ func TestCheckMarkdownLinksResolvesCommittedDestinationsAndFragments(t *testing. repository, tree := committedMarkdownTree(t, map[string][]byte{ "guide.md": guide, "target.md": []byte("# Target\n"), + "autolinks.md": []byte("# \n# \n"), "docs/a b.md": []byte("# Café\n"), "assets/file.md": []byte("# Asset\n"), "nested/guide.md": []byte("# Nested\n[same](#NESTED)\n[query](?view=1#nested)\n"), diff --git a/internal/validation/markdown_test.go b/internal/validation/markdown_test.go index f66abc3..171b938 100644 --- a/internal/validation/markdown_test.go +++ b/internal/validation/markdown_test.go @@ -61,7 +61,10 @@ func TestParseMarkdownHeadingAnchors(t *testing.T) { "# Foo\n" + "# Foo-1\n" + "# Foo\n" + - "# Foo-1\n") + "# Foo-1\n" + + "# \n" + + "# \n" + + "# Contact Today\n") document := parseMarkdown(source) for _, anchor := range []string{ "café--東京-code-here-bold", @@ -71,13 +74,16 @@ func TestParseMarkdownHeadingAnchors(t *testing.T) { "foo-1-1", "foo-2", "foo-1-2", + "httpsexampleinvalid", + "maintainerexampleinvalid", + "contact-maintainerexampleinvalid-today", } { if _, ok := document.anchors[anchor]; !ok { t.Errorf("missing anchor %q in %#v", anchor, document.anchors) } } - if len(document.anchors) != 7 { - t.Fatalf("found %d anchors, want 7: %#v", len(document.anchors), document.anchors) + if len(document.anchors) != 10 { + t.Fatalf("found %d anchors, want 10: %#v", len(document.anchors), document.anchors) } }