Skip to content

Commit 20d0834

Browse files
deslop(#610): check-built-links member check — drop no-op BASE escaping, early-continue over one sitePath, collapse nested broken-set if
Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
1 parent e9e3e65 commit 20d0834

1 file changed

Lines changed: 9 additions & 7 deletions

File tree

‎website/scripts/check-built-links.mjs‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const ATTRIBUTE = /([a-zA-Z:-]+)\s*=\s*"([^"]*)"/g;
2929
const ID = /\s(?:id|name)="([^"]*)"/g;
3030
const SKIPPED_SCHEMES = /^(?:mailto:|javascript:|tel:|data:|https?:\/\/|\/\/)/i;
3131
const ANCHOR_ELEMENT = /<a\b([^>]*)>([\s\S]*?)<\/a>/gi;
32-
const API_MEMBER_LINK = new RegExp(`^${BASE.replace(/[/]/g, '\\/')}(?:zh\\/)?api\\/[^#?]+#(.+)$`);
32+
const API_MEMBER_LINK = new RegExp(`^${BASE}(?:zh/)?api/[^#?]+#(.+)$`);
3333
const IDENTIFIER = /^[A-Za-z_$][\w$]*$/;
3434
/** Visible text of an HTML fragment, as a reader compares it: tags (incl. `<wbr/>`) and entities gone, `()` dropped. */
3535
const visibleText = html => unescapeHtml(html.replace(/<[^>]*>/g, '')).replace(/\(\)$/, '').trim();
@@ -141,18 +141,20 @@ const main = () => {
141141
if (file.endsWith('.html') && !/^\/(?:zh\/)?api\//.test(pagePath)) {
142142
for (const [, rawAttributes, inner] of html.matchAll(ANCHOR_ELEMENT)) {
143143
const href = unescapeHtml(/\shref="([^"]*)"/.exec(rawAttributes)?.[1] ?? '');
144-
const member = API_MEMBER_LINK.exec(href.startsWith(ORIGIN) ? href.slice(ORIGIN.length) : href);
145-
const label = member ? visibleText(inner) : '';
146-
if (!member || !IDENTIFIER.test(label)) continue;
147-
const target = resolveTarget(href.replace(/#.*$/, '').replace(ORIGIN, ''));
144+
const sitePath = href.startsWith(ORIGIN) ? href.slice(ORIGIN.length) : href;
145+
const member = API_MEMBER_LINK.exec(sitePath);
146+
if (!member) continue;
147+
const label = visibleText(inner);
148+
if (!IDENTIFIER.test(label)) continue;
149+
const target = resolveTarget(sitePath.replace(/#.*$/, ''));
148150
if (target === null) continue;
149151
members += 1;
150152
const fragment = decode(member[1]);
151153
const heading = new RegExp(`<h[1-6]\\b[^>]*\\sid="${fragment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}"[^>]*>([\\s\\S]*?)</h[1-6]>`).exec(fs.readFileSync(target, 'utf8'));
152154
if (heading === null) continue;
153155
const headingLabel = visibleText(heading[1]).replace(/^#/, '').trim();
154-
if (headingLabel.toLowerCase() !== label.toLowerCase()) {
155-
if (!broken.has(href)) broken.set(href, `${href} — labelled "${label}" but #${fragment} is the heading "${headingLabel}" (e.g. in ${pagePath})`);
156+
if (headingLabel.toLowerCase() !== label.toLowerCase() && !broken.has(href)) {
157+
broken.set(href, `${href} — labelled "${label}" but #${fragment} is the heading "${headingLabel}" (e.g. in ${pagePath})`);
156158
}
157159
}
158160
}

0 commit comments

Comments
 (0)