Include autolink text in Markdown heading anchors
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
# ReleaseKit implementation remediation
|
# ReleaseKit implementation remediation
|
||||||
|
|
||||||
Status: Three open v0.2.0 findings (7–9). The six foundation findings (1–6)
|
Status: Two open v0.2.0 findings (8–9). Findings 1–7 are addressed.
|
||||||
are addressed.
|
|
||||||
|
|
||||||
The v0.2.0 review covers committed state `edd670e` and the implementation
|
The v0.2.0 review covers committed state `edd670e` and the implementation
|
||||||
commits after `89981ab`, against the [implementation plan](implementation.md),
|
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
|
## 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),
|
**Owner:** [Markdown heading extraction](../../internal/validation/markdown.go),
|
||||||
`markdownHeadingText`, lines 115–139.
|
`markdownHeadingText`, lines 115–139.
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,9 @@ func markdownHeadingText(heading *ast.Heading, source []byte) string {
|
|||||||
case *ast.CodeSpan:
|
case *ast.CodeSpan:
|
||||||
result.WriteString(node.Value.Value(source))
|
result.WriteString(node.Value.Value(source))
|
||||||
return
|
return
|
||||||
|
case *ast.AutoLink:
|
||||||
|
result.WriteString(node.Label.Value(source))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
for child := node.FirstChild(); child != nil; child = child.NextSibling() {
|
for child := node.FirstChild(); child != nil; child = child.NextSibling() {
|
||||||
appendNode(child)
|
appendNode(child)
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ func TestCheckMarkdownLinksResolvesCommittedDestinationsAndFragments(t *testing.
|
|||||||
"# Start\n" +
|
"# Start\n" +
|
||||||
"[target](target.md?view=1#TARGET)\n" +
|
"[target](target.md?view=1#TARGET)\n" +
|
||||||
"[same](#START)\n" +
|
"[same](#START)\n" +
|
||||||
|
"[url heading](autolinks.md#httpsexampleinvalid)\n" +
|
||||||
|
"[email heading](autolinks.md#maintainerexampleinvalid)\n" +
|
||||||
"[top](#)\n" +
|
"[top](#)\n" +
|
||||||
"[directory](assets/?view=1)\n" +
|
"[directory](assets/?view=1)\n" +
|
||||||
"[binary](image.bin#not-an-anchor)\n" +
|
"[binary](image.bin#not-an-anchor)\n" +
|
||||||
@@ -26,6 +28,7 @@ func TestCheckMarkdownLinksResolvesCommittedDestinationsAndFragments(t *testing.
|
|||||||
repository, tree := committedMarkdownTree(t, map[string][]byte{
|
repository, tree := committedMarkdownTree(t, map[string][]byte{
|
||||||
"guide.md": guide,
|
"guide.md": guide,
|
||||||
"target.md": []byte("# Target\n"),
|
"target.md": []byte("# Target\n"),
|
||||||
|
"autolinks.md": []byte("# <https://example.invalid>\n# <maintainer@example.invalid>\n"),
|
||||||
"docs/a b.md": []byte("# Café\n"),
|
"docs/a b.md": []byte("# Café\n"),
|
||||||
"assets/file.md": []byte("# Asset\n"),
|
"assets/file.md": []byte("# Asset\n"),
|
||||||
"nested/guide.md": []byte("# Nested\n[same](#NESTED)\n[query](?view=1#nested)\n"),
|
"nested/guide.md": []byte("# Nested\n[same](#NESTED)\n[query](?view=1#nested)\n"),
|
||||||
|
|||||||
@@ -61,7 +61,10 @@ func TestParseMarkdownHeadingAnchors(t *testing.T) {
|
|||||||
"# Foo\n" +
|
"# Foo\n" +
|
||||||
"# Foo-1\n" +
|
"# Foo-1\n" +
|
||||||
"# Foo\n" +
|
"# Foo\n" +
|
||||||
"# Foo-1\n")
|
"# Foo-1\n" +
|
||||||
|
"# <https://example.invalid>\n" +
|
||||||
|
"# <maintainer@example.invalid>\n" +
|
||||||
|
"# Contact <maintainer@example.invalid> Today\n")
|
||||||
document := parseMarkdown(source)
|
document := parseMarkdown(source)
|
||||||
for _, anchor := range []string{
|
for _, anchor := range []string{
|
||||||
"café--東京-code-here-bold",
|
"café--東京-code-here-bold",
|
||||||
@@ -71,13 +74,16 @@ func TestParseMarkdownHeadingAnchors(t *testing.T) {
|
|||||||
"foo-1-1",
|
"foo-1-1",
|
||||||
"foo-2",
|
"foo-2",
|
||||||
"foo-1-2",
|
"foo-1-2",
|
||||||
|
"httpsexampleinvalid",
|
||||||
|
"maintainerexampleinvalid",
|
||||||
|
"contact-maintainerexampleinvalid-today",
|
||||||
} {
|
} {
|
||||||
if _, ok := document.anchors[anchor]; !ok {
|
if _, ok := document.anchors[anchor]; !ok {
|
||||||
t.Errorf("missing anchor %q in %#v", anchor, document.anchors)
|
t.Errorf("missing anchor %q in %#v", anchor, document.anchors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(document.anchors) != 7 {
|
if len(document.anchors) != 10 {
|
||||||
t.Fatalf("found %d anchors, want 7: %#v", len(document.anchors), document.anchors)
|
t.Fatalf("found %d anchors, want 10: %#v", len(document.anchors), document.anchors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user