Fix: vendor static-HTML parsers so skill installs detect fully (#434)

Skill and plugin copies of the detector had no htmlparser2/css-select/css-tree/domutils, so HTML scans silently fell back to regex and exited 0. Bundle those parsers into the engine tree and exit 1 if the fallback still fires.

AI assistance: Cursor Grok 4.6 implemented this change.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Abdul Wahab
2026-09-01 15:03:10 +05:00
co-authored by Cursor
parent 94b7f34f6e
commit 6d973cdea6
10 changed files with 9781 additions and 24 deletions
+14 -19
View File
@@ -122,12 +122,8 @@ async function detectHtml(filePath, options = {}) {
ruleId: 'import-static-parser',
target: filePath,
}, async () => {
const [htmlparser2, cssSelect, csstree, domutils] = await Promise.all([
import('htmlparser2'),
import('css-select'),
import('css-tree'),
import('domutils'),
]);
const parsers = await import(new URL('../../vendor/static-html-parsers.mjs', import.meta.url).href);
const { htmlparser2, cssSelect, csstree, domutils } = parsers;
return {
parseDocument: htmlparser2.parseDocument,
selectAll: cssSelect.selectAll,
@@ -137,21 +133,20 @@ async function detectHtml(filePath, options = {}) {
domutils,
};
});
} catch (err) {
if (!globalThis.__impeccableStaticHtmlWarned) {
globalThis.__impeccableStaticHtmlWarned = true;
process.stderr.write(
'impeccable detect: DEGRADED - HTML parser modules unavailable ' +
'(htmlparser2, css-select, css-tree, domutils).\n' +
'Falling back to regex matching. Custom properties, selector matching and computed ' +
'contrast are NOT evaluated; findings are an undercount, not a clean bill of health.\n'
);
} catch {
if (!globalThis.__impeccableStaticHtmlWarned) {
globalThis.__impeccableStaticHtmlWarned = true;
process.stderr.write(
'impeccable detect: DEGRADED - HTML parser modules unavailable ' +
'(htmlparser2, css-select, css-tree, domutils).\n' +
'Falling back to regex matching. Custom properties, selector matching and computed ' +
'contrast are NOT evaluated; findings are an undercount, not a clean bill of health.\n',
);
}
globalThis.__impeccableStaticHtmlDegraded = true;
return detectText(html, filePath, options);
}
return detectText(html, filePath, options);
}
const resolvedPath = path.resolve(filePath);
const fileDir = path.dirname(resolvedPath);
const root = profileStep(profile, {