Treat image labels as Markdown alternative text
This commit is contained in:
@@ -59,7 +59,9 @@ submodule contents remain out of scope under either setting.
|
|||||||
|
|
||||||
The parser recognizes inline links, images, reference links, and CommonMark
|
The parser recognizes inline links, images, reference links, and CommonMark
|
||||||
autolinks; link-like text in code is ignored, and raw HTML destinations are
|
autolinks; link-like text in code is ignored, and raw HTML destinations are
|
||||||
outside this check. Relative paths resolve from the source document in the
|
outside this check. For linked images, the image source and enclosing link
|
||||||
|
target are checked. Image labels supply alternative text.
|
||||||
|
Relative paths resolve from the source document in the
|
||||||
captured commit. Query components are ignored for file existence, and percent
|
captured commit. Query components are ignored for file existence, and percent
|
||||||
escapes in local paths and fragments are decoded once. Fragments are compared
|
escapes in local paths and fragments are decoded once. Fragments are compared
|
||||||
in lowercase with anchors derived from visible ATX or Setext heading text.
|
in lowercase with anchors derived from visible ATX or Setext heading text.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# ReleaseKit implementation remediation
|
# ReleaseKit implementation remediation
|
||||||
|
|
||||||
Status: Two open v0.2.0 findings (8–9). Findings 1–7 are addressed.
|
Status: One open v0.2.0 finding (9). Findings 1–8 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),
|
||||||
@@ -330,6 +330,13 @@ Keep external destination availability outside this offline capability.
|
|||||||
|
|
||||||
## 8. P2: Image alternative text creates additional release requirements
|
## 8. P2: Image alternative text creates additional release requirements
|
||||||
|
|
||||||
|
**Resolution:** Addressed. Destination extraction records an image source and
|
||||||
|
skips its alternative-text children. Regression coverage exercises nested
|
||||||
|
images/links, missing anchors, and outside-checkout label syntax under both
|
||||||
|
boundary settings. Real linked images still report missing sources and link
|
||||||
|
targets. The regression failed before the fix, and
|
||||||
|
`go test ./internal/validation` passed afterward.
|
||||||
|
|
||||||
**Owner:** [Markdown link extraction](../../internal/validation/markdown.go),
|
**Owner:** [Markdown link extraction](../../internal/validation/markdown.go),
|
||||||
`parseMarkdown`, especially the image branch and AST traversal at lines 65–110.
|
`parseMarkdown`, especially the image branch and AST traversal at lines 65–110.
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ func parseMarkdown(source []byte) *markdownDocument {
|
|||||||
Reference: node.Reference != nil,
|
Reference: node.Reference != nil,
|
||||||
Location: markdownLocationAt(lineStarts, node.Pos()),
|
Location: markdownLocationAt(lineStarts, node.Pos()),
|
||||||
})
|
})
|
||||||
|
// Image labels contribute alternative text, not navigable destinations.
|
||||||
|
return ast.WalkSkipChildren, nil
|
||||||
case *ast.AutoLink:
|
case *ast.AutoLink:
|
||||||
document.links = append(document.links, markdownLink{
|
document.links = append(document.links, markdownLink{
|
||||||
Destination: node.Destination.Value(source),
|
Destination: node.Destination.Value(source),
|
||||||
|
|||||||
@@ -46,6 +46,39 @@ func TestCheckMarkdownLinksResolvesCommittedDestinationsAndFragments(t *testing.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckMarkdownLinksTreatsImageLabelsAsAlternativeText(t *testing.T) {
|
||||||
|
_, tree := committedMarkdownTree(t, map[string][]byte{
|
||||||
|
"guide.md": []byte("" +
|
||||||
|
"](image.png)\n" +
|
||||||
|
"](image.png)\n" +
|
||||||
|
"](image.png)\n" +
|
||||||
|
"](image.png)\n" +
|
||||||
|
"[](target.md#present)\n" +
|
||||||
|
"[](absent.md)\n"),
|
||||||
|
"image.png": []byte("image"),
|
||||||
|
"target.md": []byte("# Present\n"),
|
||||||
|
})
|
||||||
|
for _, enforceBoundary := range []bool{false, true} {
|
||||||
|
t.Run(fmt.Sprintf("boundary=%t", enforceBoundary), func(t *testing.T) {
|
||||||
|
err := checkMarkdownLinks(context.Background(), tree, enforceBoundary, nil)
|
||||||
|
var failure *Failure
|
||||||
|
if !errors.As(err, &failure) || failure.Check != MarkdownLinks || len(failure.Findings) != 2 {
|
||||||
|
t.Fatalf("error = %v, want only the missing linked-image source and link target", err)
|
||||||
|
}
|
||||||
|
want := map[string]bool{"absent.png": true, "absent.md": true}
|
||||||
|
for _, finding := range failure.Findings {
|
||||||
|
if !want[finding.Target] {
|
||||||
|
t.Errorf("unexpected destination finding: %#v", finding)
|
||||||
|
}
|
||||||
|
delete(want, finding.Target)
|
||||||
|
}
|
||||||
|
if len(want) != 0 {
|
||||||
|
t.Errorf("missing findings for real destinations: %v", want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCheckMarkdownLinksReportsMissingPathsAnchorsAndCycles(t *testing.T) {
|
func TestCheckMarkdownLinksReportsMissingPathsAnchorsAndCycles(t *testing.T) {
|
||||||
_, tree := committedMarkdownTree(t, map[string][]byte{
|
_, tree := committedMarkdownTree(t, map[string][]byte{
|
||||||
"guide.md": []byte("" +
|
"guide.md": []byte("" +
|
||||||
|
|||||||
Reference in New Issue
Block a user