@brandlab-digital/conformance 3.13.0 → 3.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/analytics-e2e.d.ts +10 -16
- package/dist/analytics-e2e.d.ts.map +1 -1
- package/dist/analytics-e2e.js +61 -3
- package/dist/analytics-e2e.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -1
- package/dist/cli.js.map +1 -1
- package/dist/current-release.js +5 -5
- package/dist/current-release.js.map +1 -1
- package/dist/estate.d.ts +28 -0
- package/dist/estate.d.ts.map +1 -1
- package/dist/estate.js +35 -12
- package/dist/estate.js.map +1 -1
- package/dist/project.d.ts +20 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +92 -2
- package/dist/project.js.map +1 -1
- package/dist/ready-cli.d.ts.map +1 -1
- package/dist/ready-cli.js +8 -3
- package/dist/ready-cli.js.map +1 -1
- package/dist/rule-registry.d.ts +5 -0
- package/dist/rule-registry.d.ts.map +1 -1
- package/dist/rule-registry.js +1 -0
- package/dist/rule-registry.js.map +1 -1
- package/dist/site-system/checks.d.ts +26 -1
- package/dist/site-system/checks.d.ts.map +1 -1
- package/dist/site-system/checks.js +3 -0
- package/dist/site-system/checks.js.map +1 -1
- package/dist/site-system/report.d.ts.map +1 -1
- package/dist/site-system/report.js +19 -5
- package/dist/site-system/report.js.map +1 -1
- package/dist/site-system/rule-modules.d.ts.map +1 -1
- package/dist/site-system/rule-modules.js +5 -0
- package/dist/site-system/rule-modules.js.map +1 -1
- package/dist/site-system/rules/delivery/h13-inbox.d.ts +23 -0
- package/dist/site-system/rules/delivery/h13-inbox.d.ts.map +1 -0
- package/dist/site-system/rules/delivery/h13-inbox.js +208 -0
- package/dist/site-system/rules/delivery/h13-inbox.js.map +1 -0
- package/dist/site-system/rules/delivery/index.d.ts +12 -0
- package/dist/site-system/rules/delivery/index.d.ts.map +1 -0
- package/dist/site-system/rules/delivery/index.js +7 -0
- package/dist/site-system/rules/delivery/index.js.map +1 -0
- package/dist/site-system/rules/full/e1-pattern.d.ts +4 -0
- package/dist/site-system/rules/full/e1-pattern.d.ts.map +1 -0
- package/dist/site-system/rules/full/e1-pattern.js +47 -0
- package/dist/site-system/rules/full/e1-pattern.js.map +1 -0
- package/dist/site-system/rules/full/estate.d.ts +16 -1
- package/dist/site-system/rules/full/estate.d.ts.map +1 -1
- package/dist/site-system/rules/full/estate.js +23 -4
- package/dist/site-system/rules/full/estate.js.map +1 -1
- package/dist/site-system/rules/full/geography.d.ts +8 -2
- package/dist/site-system/rules/full/geography.d.ts.map +1 -1
- package/dist/site-system/rules/full/geography.js +6 -2
- package/dist/site-system/rules/full/geography.js.map +1 -1
- package/dist/site-system/rules/full/index.d.ts +2 -2
- package/dist/site-system/rules/full/index.d.ts.map +1 -1
- package/dist/site-system/rules/full/index.js +15 -4
- package/dist/site-system/rules/full/index.js.map +1 -1
- package/dist/site-system/rules/full/k12-slots.d.ts +4 -0
- package/dist/site-system/rules/full/k12-slots.d.ts.map +1 -0
- package/dist/site-system/rules/full/k12-slots.js +40 -0
- package/dist/site-system/rules/full/k12-slots.js.map +1 -0
- package/dist/site-system/rules/full/loc-index.d.ts +5 -0
- package/dist/site-system/rules/full/loc-index.d.ts.map +1 -1
- package/dist/site-system/rules/full/loc-index.js +43 -2
- package/dist/site-system/rules/full/loc-index.js.map +1 -1
- package/dist/site-system/rules/full/strategy.d.ts +4 -0
- package/dist/site-system/rules/full/strategy.d.ts.map +1 -1
- package/dist/site-system/rules/full/strategy.js +19 -3
- package/dist/site-system/rules/full/strategy.js.map +1 -1
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts +2 -2
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts.map +1 -1
- package/dist/site-system/rules/sections/k2-skin-coverage.js +6 -2
- package/dist/site-system/rules/sections/k2-skin-coverage.js.map +1 -1
- package/dist/site-system/runners.js +1 -1
- package/dist/site-system/runners.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k2-skin-coverage.js","sourceRoot":"","sources":["../../../../src/site-system/rules/sections/k2-skin-coverage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * K2: skin coverage (Site System v2 §13.2, §8.4). Every shared component a page renders has a skin entry, so a site\n * never ships an unstyled look-alike, and no reference-skin class (the test skins the library's own tests use) ships.\n *\n * What the HTML can show, defined exactly:\n * - A component is a rendered element with `data-bl=\"<name>\"` or `data-bl-section=\"<id>\"`, for the names the library\n * skins (SKINNED_HOOKS and SKINNED_SECTIONS below). Hooks without a skin entry (the skip link, the honeypot, a star\n * row) and the site's own compositions (the hero) are not components in this sense.\n * - The component is covered when, on at least one sampled page, its root element or one of its slot elements (an\n * element with `data-slot` inside it, outside any component nested in it) carries a class, because a skin gives a\n * component its look through `classes`; or when the project's own stylesheets under `src/` or `app/` select the\n * component by its hook (`[data-bl=\"footer\"]`, `[data-bl-section=\"faqs\"]`), which is how a site styles slots in plain CSS.\n * - A class token starting `ref-heavy-`, `ref-calm-` or `ref-pool-` on any element is a reference-skin class and fails.\n */\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { SiteSystemFinding } from \"../../checks.js\";\nimport { fail, notApplicable, pass, plural, type ParsedPage } from \"../enquiry/common.js\";\nimport { attr, descendants, type HtmlElement } from \"../enquiry/html.js\";\nimport { PageProblems } from \"../library/common.js\";\n\n/** `data-bl` names that have an entry in `BrandlabSkin` (ui-kit/brandlab-skin.ts). */\nexport const K2_SKINNED_HOOKS = [\n \"header\", \"drawer\", \"utility\", \"callbar\", \"back-to-top\", \"quote-button\", \"phone-link\", \"text-link\", \"button\", \"container\",\n \"quote-form\", \"photo-upload\", \"dialog\", \"field\", \"thank-you\", \"rating-chip\", \"footer\", \"accordion\", \"price-table\",\n] as const;\n\n/** `data-bl-section` ids of the sections the library renders and skins. */\nexport const K2_SKINNED_SECTIONS = [\"reviews\", \"cta\", \"faqs\", \"price-guide\", \"proof-strip\", \"page-header\", \"contact\"] as const;\n\nexport const K2_REFERENCE_CLASS = /^ref-(?:heavy|calm|pool)-/;\n\nfunction classesOf(element: HtmlElement): string[] {\n return (attr(element, \"class\") ?? \"\").split(/\\s+/).filter(Boolean);\n}\n\n/** The root and slot elements of one component, leaving out components nested inside it. */\nfunction skinSurface(root: HtmlElement): HtmlElement[] {\n const surface = [root];\n const visit = (node: HtmlElement) => {\n for (const child of node.children) {\n if (child.type !== \"element\") continue;\n if (attr(child, \"data-bl\") !== undefined || attr(child, \"data-bl-section\") !== undefined) continue;\n if (attr(child, \"data-slot\") !== undefined) surface.push(child);\n visit(child);\n }\n };\n visit(root);\n return surface;\n}\n\n/** Hook names the project's own stylesheets select: `[data-bl=\"x\"]` and `[data-bl-section=\"x\"]`. */\nexport function hooksStyledBySite(projectRoot: string): Set<string> {\n const styled = new Set<string>();\n const selector = /\\[\\s*data-bl(?:-section)?\\s*=\\s*[\"']?([a-z0-9-]+)[\"']?\\s*\\]/gi;\n const visit = (directory: string, depth: number) => {\n if (depth > 6) return;\n let entries;\n try {\n entries = readdirSync(directory, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n const path = join(directory, entry.name);\n if (entry.isDirectory()) visit(path, depth + 1);\n else if (entry.isFile() && /\\.(?:css|scss)$/i.test(entry.name)) {\n try {\n for (const match of readFileSync(path, \"utf8\").matchAll(selector)) styled.add(match[1]!.toLowerCase());\n } catch {\n // an unreadable stylesheet styles nothing we can see\n }\n }\n }\n };\n for (const folder of [\"src\", \"app\", \"sites\"]) if (existsSync(join(projectRoot, folder))) visit(join(projectRoot, folder), 0);\n return styled;\n}\n\nexport function checkK2(pages: readonly ParsedPage[], projectRoot: string): SiteSystemFinding[] {\n const hooks = new Set<string>(K2_SKINNED_HOOKS);\n const sections = new Set<string>(K2_SKINNED_SECTIONS);\n /** Component key (\"footer\", \"section:faqs\") to whether any instance carries a skin class, and the first page. */\n const components = new Map<string, { covered: boolean; page: string; label: string }>();\n const references = new PageProblems();\n\n for (const page of pages) {\n for (const element of descendants(page.root)) {\n const reference = classesOf(element).find((token) => K2_REFERENCE_CLASS.test(token));\n if (reference) references.add(page.path, `A reference-skin class (${reference}) ships; those belong to the library's own tests`);\n\n const hook = attr(element, \"data-bl\");\n const section = attr(element, \"data-bl-section\");\n const key = hook !== undefined && hooks.has(hook) ? `hook:${hook}` : section !== undefined && sections.has(section) ? `section:${section}` : null;\n if (!key) continue;\n const label = hook !== undefined ? `data-bl=\"${hook}\"` : `data-bl-section=\"${section}\"`;\n const carries = skinSurface(element).some((candidate) => classesOf(candidate).length > 0);\n const known = components.get(key);\n if (known) known.covered ||= carries;\n else components.set(key, { covered: carries, page: page.path, label });\n }\n }\n\n const failures = references.findings(\"K2\");\n if (components.size === 0 && failures.length === 0) return [notApplicable(\"K2\", \"None of the sampled pages renders a shared component.\")];\n const uncovered = [...components].filter(([, component]) => !component.covered);\n if (uncovered.length > 0) {\n const styled = hooksStyledBySite(projectRoot);\n for (const [key, component] of uncovered) {\n const name = key.slice(key.indexOf(\":\") + 1);\n if (styled.has(name)) continue;\n failures.push(fail(\"K2\", component.page, `${component.label} is rendered (first on ${component.page}) with no skin class on its root or slots and no selector for it in the site's stylesheets, so it has no skin entry.`));\n }\n }\n if (failures.length > 0) return failures;\n return [pass(\"K2\", `Checked ${plural(components.size, \"shared component\")} on ${plural(pages.length, \"page\")}: each carries a skin class or is styled by the site's own CSS, and no reference-skin class ships.`)];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"k2-skin-coverage.js","sourceRoot":"","sources":["../../../../src/site-system/rules/sections/k2-skin-coverage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * K2: skin coverage (Site System v2 §13.2, §8.4). Every shared component a page renders has a skin entry, so a site\n * never ships an unstyled look-alike, and no reference-skin class (the test skins the library's own tests use) ships.\n *\n * What the HTML can show, defined exactly:\n * - A component is a rendered element with `data-bl=\"<name>\"` or `data-bl-section=\"<id>\"`, for the names the library\n * skins (SKINNED_HOOKS and SKINNED_SECTIONS below). Hooks without a skin entry (the skip link, the honeypot, a star\n * row) and the site's own compositions are not components in this sense. From 3.14.0 the library's hero and the\n * primitives (button actions share `button`; cards, badges, chips and stats take no classes, so a site covers them\n * from its skin stylesheet) join the lists.\n * - The component is covered when, on at least one sampled page, its root element or one of its slot elements (an\n * element with `data-slot` inside it, outside any component nested in it) carries a class, because a skin gives a\n * component its look through `classes`; or when the project's own stylesheets under `src/` or `app/` select the\n * component by its hook (`[data-bl=\"footer\"]`, `[data-bl-section=\"faqs\"]`), which is how a site styles slots in plain CSS.\n * - A class token starting `ref-heavy-`, `ref-calm-` or `ref-pool-` on any element is a reference-skin class and fails.\n */\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { SiteSystemFinding } from \"../../checks.js\";\nimport { fail, notApplicable, pass, plural, type ParsedPage } from \"../enquiry/common.js\";\nimport { attr, descendants, type HtmlElement } from \"../enquiry/html.js\";\nimport { PageProblems } from \"../library/common.js\";\n\n/** `data-bl` names that have an entry in `BrandlabSkin` (ui-kit/brandlab-skin.ts). */\nexport const K2_SKINNED_HOOKS = [\n \"header\", \"drawer\", \"utility\", \"callbar\", \"back-to-top\", \"quote-button\", \"phone-link\", \"text-link\", \"button\", \"container\",\n \"quote-form\", \"photo-upload\", \"dialog\", \"field\", \"thank-you\", \"rating-chip\", \"footer\", \"accordion\", \"price-table\",\n // 3.14.0 primitives\n \"eyebrow\", \"card\", \"badge\", \"chip\", \"stat\", \"tick-list\", \"link-list\", \"media\", \"breadcrumbs\",\n] as const;\n\n/** `data-bl-section` ids of the sections the library renders and skins. */\nexport const K2_SKINNED_SECTIONS = [\"reviews\", \"cta\", \"faqs\", \"price-guide\", \"proof-strip\", \"page-header\", \"contact\", \"hero\", \"services\"] as const;\n\nexport const K2_REFERENCE_CLASS = /^ref-(?:heavy|calm|pool)-/;\n\nfunction classesOf(element: HtmlElement): string[] {\n return (attr(element, \"class\") ?? \"\").split(/\\s+/).filter(Boolean);\n}\n\n/** The root and slot elements of one component, leaving out components nested inside it. */\nfunction skinSurface(root: HtmlElement): HtmlElement[] {\n const surface = [root];\n const visit = (node: HtmlElement) => {\n for (const child of node.children) {\n if (child.type !== \"element\") continue;\n if (attr(child, \"data-bl\") !== undefined || attr(child, \"data-bl-section\") !== undefined) continue;\n if (attr(child, \"data-slot\") !== undefined) surface.push(child);\n visit(child);\n }\n };\n visit(root);\n return surface;\n}\n\n/** Hook names the project's own stylesheets select: `[data-bl=\"x\"]` and `[data-bl-section=\"x\"]`. */\nexport function hooksStyledBySite(projectRoot: string): Set<string> {\n const styled = new Set<string>();\n const selector = /\\[\\s*data-bl(?:-section)?\\s*=\\s*[\"']?([a-z0-9-]+)[\"']?\\s*\\]/gi;\n const visit = (directory: string, depth: number) => {\n if (depth > 6) return;\n let entries;\n try {\n entries = readdirSync(directory, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n const path = join(directory, entry.name);\n if (entry.isDirectory()) visit(path, depth + 1);\n else if (entry.isFile() && /\\.(?:css|scss)$/i.test(entry.name)) {\n try {\n for (const match of readFileSync(path, \"utf8\").matchAll(selector)) styled.add(match[1]!.toLowerCase());\n } catch {\n // an unreadable stylesheet styles nothing we can see\n }\n }\n }\n };\n for (const folder of [\"src\", \"app\", \"sites\"]) if (existsSync(join(projectRoot, folder))) visit(join(projectRoot, folder), 0);\n return styled;\n}\n\nexport function checkK2(pages: readonly ParsedPage[], projectRoot: string): SiteSystemFinding[] {\n const hooks = new Set<string>(K2_SKINNED_HOOKS);\n const sections = new Set<string>(K2_SKINNED_SECTIONS);\n /** Component key (\"footer\", \"section:faqs\") to whether any instance carries a skin class, and the first page. */\n const components = new Map<string, { covered: boolean; page: string; label: string }>();\n const references = new PageProblems();\n\n for (const page of pages) {\n for (const element of descendants(page.root)) {\n const reference = classesOf(element).find((token) => K2_REFERENCE_CLASS.test(token));\n if (reference) references.add(page.path, `A reference-skin class (${reference}) ships; those belong to the library's own tests`);\n\n const hook = attr(element, \"data-bl\");\n const section = attr(element, \"data-bl-section\");\n const key = hook !== undefined && hooks.has(hook) ? `hook:${hook}` : section !== undefined && sections.has(section) ? `section:${section}` : null;\n if (!key) continue;\n const label = hook !== undefined ? `data-bl=\"${hook}\"` : `data-bl-section=\"${section}\"`;\n const carries = skinSurface(element).some((candidate) => classesOf(candidate).length > 0);\n const known = components.get(key);\n if (known) known.covered ||= carries;\n else components.set(key, { covered: carries, page: page.path, label });\n }\n }\n\n const failures = references.findings(\"K2\");\n if (components.size === 0 && failures.length === 0) return [notApplicable(\"K2\", \"None of the sampled pages renders a shared component.\")];\n const uncovered = [...components].filter(([, component]) => !component.covered);\n if (uncovered.length > 0) {\n const styled = hooksStyledBySite(projectRoot);\n for (const [key, component] of uncovered) {\n const name = key.slice(key.indexOf(\":\") + 1);\n if (styled.has(name)) continue;\n failures.push(fail(\"K2\", component.page, `${component.label} is rendered (first on ${component.page}) with no skin class on its root or slots and no selector for it in the site's stylesheets, so it has no skin entry.`));\n }\n }\n if (failures.length > 0) return failures;\n return [pass(\"K2\", `Checked ${plural(components.size, \"shared component\")} on ${plural(pages.length, \"page\")}: each carries a skin class or is styled by the site's own CSS, and no reference-skin class ships.`)];\n}\n"]}
|
|
@@ -40,7 +40,7 @@ export function isSiteSystemFinding(value) {
|
|
|
40
40
|
const finding = value;
|
|
41
41
|
return (typeof finding.checkId === "string" &&
|
|
42
42
|
KNOWN_IDS.has(finding.checkId) &&
|
|
43
|
-
(finding.status === "pass" || finding.status === "fail" || finding.status === "not-applicable") &&
|
|
43
|
+
(finding.status === "pass" || finding.status === "fail" || finding.status === "not-run" || finding.status === "not-applicable") &&
|
|
44
44
|
typeof finding.message === "string" &&
|
|
45
45
|
(finding.target === undefined || typeof finding.target === "string") &&
|
|
46
46
|
(finding.severity === undefined || finding.severity === "warning"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runners.js","sourceRoot":"","sources":["../../src/site-system/runners.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAA0B,MAAM,aAAa,CAAC;AAwBzE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAS,kBAAkB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAE/E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,OAA4C,EAC5C,KAA8B;IAE9B,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,eAAe,CAAC;QAC5C,IAAI,OAAqC,CAAC;QAC1C,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,2BAA2B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACvI,SAAS;QACX,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;YAC9B,IAAI,mBAAmB,CAAC,OAAO,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;;gBACpD,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,uFAAuF,CAAC,CAAC;QACrH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9E,MAAM,OAAO,GAAG,KAAgC,CAAC;IACjD,OAAO,CACL,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;QACnC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;QAC9B,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,gBAAgB,CAAC;QAC/
|
|
1
|
+
{"version":3,"file":"runners.js","sourceRoot":"","sources":["../../src/site-system/runners.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAA0B,MAAM,aAAa,CAAC;AAwBzE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAS,kBAAkB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAE/E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,OAA4C,EAC5C,KAA8B;IAE9B,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,eAAe,CAAC;QAC5C,IAAI,OAAqC,CAAC;QAC1C,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,2BAA2B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACvI,SAAS;QACX,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;YAC9B,IAAI,mBAAmB,CAAC,OAAO,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;;gBACpD,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,uFAAuF,CAAC,CAAC;QACrH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9E,MAAM,OAAO,GAAG,KAAgC,CAAC;IACjD,OAAO,CACL,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;QACnC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;QAC9B,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,gBAAgB,CAAC;QAC/H,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;QACnC,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC;QACpE,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CACnE,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The rule-module interface of the ready gate. Each module under ./rules/ exports a runner, listed in\n * ./rule-modules.ts; `brandlab-ready` calls every runner with the sampled pages and merges what they find. Static\n * rules use the same shape and read the project through `projectRoot`. Every runner is called even when no page\n * could be read: static rules still run, and rendered rules return not-applicable for an empty page list (the gate\n * fails the run itself when home or the contact page is missing).\n */\nimport { SITE_SYSTEM_CHECKS, type SiteSystemFinding } from \"./checks.js\";\nimport type { SiteSystemSettings } from \"./config.js\";\nimport type { SiteSystemPage } from \"./samples.js\";\n\nexport interface SiteSystemRenderedInput {\n /** The running site's base URL with --base-url; empty when the pages were read from the build output. */\n readonly baseUrl: string;\n readonly pages: readonly SiteSystemPage[];\n /** Planned sample paths with no HTML, so rules can say what they could not check. */\n readonly missing: readonly string[];\n /** The project directory, for rules that read its data files. */\n readonly projectRoot: string;\n /**\n * The gate's parsed `siteSystem` settings from brandlab.config.ts (null when the site declares none). Rules use these\n * rather than reading the config themselves; a caller that leaves it out lets each rule read the config.\n */\n readonly siteSystem?: SiteSystemSettings | null;\n /** The production build directory (`.next` unless `--build-dir` says otherwise), for rules that read the whole build. */\n readonly buildDir?: string;\n}\n\n/** A rule module: one finding per check result (pass, fail or not-applicable), never a throw for a failing site. */\nexport type SiteSystemRenderedRunner = (input: SiteSystemRenderedInput) => Promise<readonly SiteSystemFinding[]>;\n\nconst KNOWN_IDS = new Set<string>(SITE_SYSTEM_CHECKS.map((check) => check.id));\n\n/**\n * Runs each runner in turn. A runner that throws, or returns a finding for an unknown check, is reported as a\n * problem; the checks it would have covered then show as not run, which fails them where they block.\n */\nexport async function runSiteSystemRenderedRunners(\n runners: readonly SiteSystemRenderedRunner[],\n input: SiteSystemRenderedInput,\n): Promise<{ findings: SiteSystemFinding[]; problems: string[] }> {\n const findings: SiteSystemFinding[] = [];\n const problems: string[] = [];\n for (const runner of runners) {\n const name = runner.name || \"A rule module\";\n let results: readonly SiteSystemFinding[];\n try {\n results = await runner(input);\n } catch (error) {\n problems.push(`${name} stopped with an error (${error instanceof Error ? error.message : String(error)}), so its checks did not run.`);\n continue;\n }\n for (const finding of results) {\n if (isSiteSystemFinding(finding)) findings.push(finding);\n else problems.push(`${name} returned a result for an unknown check or with an unknown status, so it was ignored.`);\n }\n }\n return { findings, problems };\n}\n\n/** A finding with a known check id, a known status and a message; anything else is ignored. */\nexport function isSiteSystemFinding(value: unknown): value is SiteSystemFinding {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const finding = value as Record<string, unknown>;\n return (\n typeof finding.checkId === \"string\" &&\n KNOWN_IDS.has(finding.checkId) &&\n (finding.status === \"pass\" || finding.status === \"fail\" || finding.status === \"not-run\" || finding.status === \"not-applicable\") &&\n typeof finding.message === \"string\" &&\n (finding.target === undefined || typeof finding.target === \"string\") &&\n (finding.severity === undefined || finding.severity === \"warning\")\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brandlab-digital/conformance",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.14.0",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@brandlab-digital/site-core": "3.
|
|
32
|
+
"@brandlab-digital/site-core": "3.14.0",
|
|
33
33
|
"typescript": "6.0.3"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|