From 6558245e12d19e84f645d5950f8edf17c9a19319 Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 21 Sep 2026 02:32:59 +0200 Subject: [PATCH] fix(agents): normalize internal HTML URL whitespace --- docs/development/agent-workflow.md | 3 ++- tools/skills/agent-guidance-markdown.mjs | 7 +++---- tools/skills/validate-agent-guidance.test.mjs | 11 +++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/development/agent-workflow.md b/docs/development/agent-workflow.md index 9ad64eb05..4cd10caad 100644 --- a/docs/development/agent-workflow.md +++ b/docs/development/agent-workflow.md @@ -57,7 +57,8 @@ Only headings present outside inert HTML containers contribute slugs or duplicat Explicit HTML anchors use `parse5`, excluding comments, scripts, styles and template contents. Rendered HTML anchor and image-map area hrefs and image sources use the same local-reference checks as Markdown links, including decoded attributes and fragment validation. -URL attributes discard surrounding ASCII control/space characters before resolution. +URL attributes remove ASCII tabs/newlines throughout and discard surrounding +ASCII control/space characters before resolution. Iframe/embed sources and object data attributes are document references and retain Markdown-target anchor checks. Image and media references must resolve to files, not directories. Image references check file existence without interpreting image fragments as diff --git a/tools/skills/agent-guidance-markdown.mjs b/tools/skills/agent-guidance-markdown.mjs index 166c608f5..9d7460273 100644 --- a/tools/skills/agent-guidance-markdown.mjs +++ b/tools/skills/agent-guidance-markdown.mjs @@ -85,10 +85,9 @@ function htmlNavigation(html, inspect = () => {}) { (node.tagName === 'object' && attribute.name === 'data') ) references.push({ - target: attribute.value.replace( - /^[\u0000-\u0020]+|[\u0000-\u0020]+$/gu, - '' - ), + target: attribute.value + .replace(/[\t\n\r]/gu, '') + .replace(/^[\u0000-\u0020]+|[\u0000-\u0020]+$/gu, ''), image: !['a', 'area', 'iframe', 'object', 'embed'].includes( node.tagName ), diff --git a/tools/skills/validate-agent-guidance.test.mjs b/tools/skills/validate-agent-guidance.test.mjs index 909594c2a..6aac2c98a 100644 --- a/tools/skills/validate-agent-guidance.test.mjs +++ b/tools/skills/validate-agent-guidance.test.mjs @@ -1370,3 +1370,14 @@ for (const tag of ['object', 'embed']) { ); }); } + +for (const entity of [' ', ' ', ' ']) { + test(`HTML URLs remove internal tab/newline: ${entity}`, async (t) => { + assert.deepEqual( + await diagnostics(t, { + 'AGENTS.md': `Guide`, + }), + [] + ); + }); +}