mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
fix(scripts): preserve complete HTML src/href URLs in README link checks (#34817)
Only srcset is a comma-separated candidate list; src and href hold one URL. Splitting them invented missing targets for paths containing commas or spaces and could pass a missing target whose fragments were tracked. Fixes #34815
This commit is contained in:
@@ -7,7 +7,7 @@ import { pathToFileURL } from 'node:url'
|
||||
// Docs-only CI skips some media owners; check index paths because GitHub cannot render uncommitted docs-site/feature-wall assets.
|
||||
const TRANSLATED_README_DIR = path.join('docs', 'readme')
|
||||
const EXTERNAL_TARGET = /^(?:[a-z][a-z0-9+.-]*:|#|\/\/)/i
|
||||
const HTML_ATTRIBUTE = /\b(?:src|srcset|href)\s*=\s*(?:"([^"]*)"|'([^']*)')/g
|
||||
const HTML_ATTRIBUTE = /\b(src|srcset|href)\s*=\s*(?:"([^"]*)"|'([^']*)')/g
|
||||
const MARKDOWN_LINK = /!?\[[^\]]*\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g
|
||||
|
||||
function readmeFiles(root) {
|
||||
@@ -32,10 +32,14 @@ function trackedFiles(root, candidates) {
|
||||
}
|
||||
|
||||
function* localTargets(markdown) {
|
||||
for (const match of markdown.matchAll(HTML_ATTRIBUTE)) {
|
||||
// srcset lists candidates; each begins with its URL.
|
||||
for (const candidate of (match[1] ?? match[2]).split(',')) {
|
||||
const target = candidate.trim().split(/\s+/)[0]
|
||||
for (const [, attribute, doubleQuoted, singleQuoted] of markdown.matchAll(HTML_ATTRIBUTE)) {
|
||||
const value = doubleQuoted ?? singleQuoted
|
||||
// Only srcset lists candidates; each begins with its URL. src/href hold one whole URL.
|
||||
const targets =
|
||||
attribute === 'srcset'
|
||||
? value.split(',').map((candidate) => candidate.trim().split(/\s+/)[0])
|
||||
: [value.trim()]
|
||||
for (const target of targets) {
|
||||
if (target) {
|
||||
yield target
|
||||
}
|
||||
|
||||
@@ -44,7 +44,9 @@ const validReadmes = {
|
||||
"<img src='resources/build/icon.png' />",
|
||||
'<img src="https://img.shields.io/badge/x-y-z" />',
|
||||
'[Contributing](.github/CONTRIBUTING.md) [Docs](https://example.com/docs) [Top](#top)',
|
||||
''
|
||||
'',
|
||||
// src/href hold one URL; only srcset is a comma-separated list.
|
||||
'<img src="docs/assets/hero image,wide.jpg" /> <a href=\'https://example.com/docs?pages=one,two\'>Docs</a>'
|
||||
].join('\n'),
|
||||
'docs/readme/README.ja.md': [
|
||||
'<img src="../../resources/build/icon.png" />',
|
||||
@@ -56,6 +58,7 @@ const validReadmes = {
|
||||
'resources/onboarding/feature-wall/tile-01.poster.jpg': 'jpg',
|
||||
'docs/site/public/docs/tab-split.gif': 'gif',
|
||||
'docs/assets/hero image.jpg': 'jpg',
|
||||
'docs/assets/hero image,wide.jpg': 'jpg',
|
||||
'.github/CONTRIBUTING.md': 'contributing',
|
||||
LICENSE: 'mit'
|
||||
}
|
||||
@@ -77,6 +80,38 @@ describe('README local link check', () => {
|
||||
expect(findBrokenReadmeLinks(makeFixture(validReadmes))).toEqual([])
|
||||
})
|
||||
|
||||
it('rejects a missing full URL even when its split fragments are tracked', () => {
|
||||
const root = makeFixture({
|
||||
...validReadmes,
|
||||
'README.md': '<img src="docs/assets/missing image,wide.jpg" />',
|
||||
'docs/assets/missing': 'fragment',
|
||||
'wide.jpg': 'fragment'
|
||||
})
|
||||
|
||||
expect(findBrokenReadmeLinks(root)).toEqual([
|
||||
{
|
||||
readme: 'README.md',
|
||||
target: 'docs/assets/missing image,wide.jpg',
|
||||
resolved: 'docs/assets/missing image,wide.jpg'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('continues checking each srcset candidate without its descriptor', () => {
|
||||
const root = makeFixture({
|
||||
...validReadmes,
|
||||
'README.md': '<source srcset="resources/build/icon.png 1x, docs/assets/missing.png 2x">'
|
||||
})
|
||||
|
||||
expect(findBrokenReadmeLinks(root)).toEqual([
|
||||
{
|
||||
readme: 'README.md',
|
||||
target: 'docs/assets/missing.png',
|
||||
resolved: 'docs/assets/missing.png'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('checks tracked media outside the detector sparse checkout', () => {
|
||||
const root = makeFixture(validReadmes)
|
||||
const workflow = parse(readFileSync(path.join(projectDir, '.github/workflows/pr.yml'), 'utf8'))
|
||||
|
||||
Reference in New Issue
Block a user