@brandlab-digital/conformance 3.19.0 → 3.19.1
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/dist/current-release.js +5 -5
- package/dist/current-release.js.map +1 -1
- package/dist/site-system/journeys/page-helpers.d.ts +2 -0
- package/dist/site-system/journeys/page-helpers.d.ts.map +1 -1
- package/dist/site-system/journeys/page-helpers.js +19 -11
- package/dist/site-system/journeys/page-helpers.js.map +1 -1
- package/dist/site-system/rules/enquiry/k8-sections.d.ts.map +1 -1
- package/dist/site-system/rules/enquiry/k8-sections.js +5 -1
- package/dist/site-system/rules/enquiry/k8-sections.js.map +1 -1
- package/dist/site-system/rules/full/k12-slots.d.ts.map +1 -1
- package/dist/site-system/rules/full/k12-slots.js +3 -0
- package/dist/site-system/rules/full/k12-slots.js.map +1 -1
- package/dist/site-system/rules/sections/k11-density.d.ts.map +1 -1
- package/dist/site-system/rules/sections/k11-density.js +4 -2
- package/dist/site-system/rules/sections/k11-density.js.map +1 -1
- package/package.json +2 -2
package/dist/current-release.js
CHANGED
|
@@ -23,19 +23,19 @@ export const BRANDLAB_CURRENT_RUNTIME_RELEASE = Object.freeze({
|
|
|
23
23
|
"kind": "brandlab-runtime-release-contract",
|
|
24
24
|
"packages": {
|
|
25
25
|
"@brandlab-digital/conformance": {
|
|
26
|
-
"version": "3.19.
|
|
26
|
+
"version": "3.19.1"
|
|
27
27
|
},
|
|
28
28
|
"@brandlab-digital/eslint-plugin": {
|
|
29
|
-
"version": "3.19.
|
|
29
|
+
"version": "3.19.1"
|
|
30
30
|
},
|
|
31
31
|
"@brandlab-digital/site-core": {
|
|
32
|
-
"version": "3.19.
|
|
32
|
+
"version": "3.19.1"
|
|
33
33
|
},
|
|
34
34
|
"@brandlab-digital/site-next": {
|
|
35
|
-
"version": "3.19.
|
|
35
|
+
"version": "3.19.1"
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
|
-
"releaseVersion": "3.19.
|
|
38
|
+
"releaseVersion": "3.19.1",
|
|
39
39
|
"runtime": {
|
|
40
40
|
"bundler": "turbopack",
|
|
41
41
|
"cacheComponents": false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"current-release.js","sourceRoot":"","sources":["../src/current-release.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,wEAAwE;AACxE,OAAO,EAEL,sCAAsC,GACvC,MAAM,uBAAuB,CAAC;AAE/B,MAAM,CAAC,MAAM,gCAAgC,GAAG,MAAM,CAAC,MAAM,CAC7D;IACE,cAAc,EAAE;QACd,uCAAuC;QACvC,8BAA8B;QAC9B,yBAAyB;QACzB,6BAA6B;QAC7B,0BAA0B;QAC1B,4BAA4B;QAC5B,kCAAkC;QAClC,wCAAwC;QACxC,yBAAyB;KAC1B;IACD,WAAW,EAAE;QACX,WAAW,EAAE,cAAc;QAC3B,cAAc,EAAE,iBAAiB;QACjC,eAAe,EAAE,mBAAmB;QACpC,SAAS,EAAE,YAAY;QACvB,KAAK,EAAE,QAAQ;KAChB;IACD,MAAM,EAAE,mCAAmC;IAC3C,UAAU,EAAE;QACV,+BAA+B,EAAE;YAC/B,SAAS,EAAE,QAAQ;SACpB;QACD,iCAAiC,EAAE;YACjC,SAAS,EAAE,QAAQ;SACpB;QACD,6BAA6B,EAAE;YAC7B,SAAS,EAAE,QAAQ;SACpB;QACD,6BAA6B,EAAE;YAC7B,SAAS,EAAE,QAAQ;SACpB;KACF;IACD,gBAAgB,EAAE,QAAQ;IAC1B,SAAS,EAAE;QACT,SAAS,EAAE,WAAW;QACtB,iBAAiB,EAAE,KAAK;QACxB,MAAM,EAAE,QAAQ;QAChB,mBAAmB,EAAE,OAAO;QAC5B,MAAM,EAAE,MAAM;QACd,gBAAgB,EAAE,aAAa;QAC/B,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE,QAAQ;QACpB,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,QAAQ;QACjB,YAAY,EAAE,OAAO;KACtB;IACD,eAAe,EAAE,sCAAsC;CACxD,CAC6C,CAAC;AAE/C,sCAAsC,CAAC,gCAAgC,CAAC,CAAC","sourcesContent":["// Generated by standards/scripts/generate-conformance-current-release.mjs.\n// Each exact package release verifies its own current runtime contract.\nimport {\n type BrandlabRuntimeReleaseContract,\n validateBrandlabRuntimeReleaseContract,\n} from \"./release-manifest.js\";\n\nexport const BRANDLAB_CURRENT_RUNTIME_RELEASE = Object.freeze(\n{\n \"capabilities\": [\n \"typed-project-business-and-route-data\",\n \"essential-search-foundations\",\n \"shared-contact-delivery\",\n \"privacy-safe-lead-analytics\",\n \"security-patched-runtime\",\n \"live-google-review-summary\",\n \"high-signal-project-verification\",\n \"packed-positive-and-negative-consumers\",\n \"changesets-oidc-release\"\n ],\n \"contracts\": {\n \"analytics\": \"analytics-v4\",\n \"architecture\": \"architecture-v7\",\n \"configuration\": \"project-config-v7\",\n \"contact\": \"contact-v4\",\n \"seo\": \"seo-v4\"\n },\n \"kind\": \"brandlab-runtime-release-contract\",\n \"packages\": {\n \"@brandlab-digital/conformance\": {\n \"version\": \"3.19.
|
|
1
|
+
{"version":3,"file":"current-release.js","sourceRoot":"","sources":["../src/current-release.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,wEAAwE;AACxE,OAAO,EAEL,sCAAsC,GACvC,MAAM,uBAAuB,CAAC;AAE/B,MAAM,CAAC,MAAM,gCAAgC,GAAG,MAAM,CAAC,MAAM,CAC7D;IACE,cAAc,EAAE;QACd,uCAAuC;QACvC,8BAA8B;QAC9B,yBAAyB;QACzB,6BAA6B;QAC7B,0BAA0B;QAC1B,4BAA4B;QAC5B,kCAAkC;QAClC,wCAAwC;QACxC,yBAAyB;KAC1B;IACD,WAAW,EAAE;QACX,WAAW,EAAE,cAAc;QAC3B,cAAc,EAAE,iBAAiB;QACjC,eAAe,EAAE,mBAAmB;QACpC,SAAS,EAAE,YAAY;QACvB,KAAK,EAAE,QAAQ;KAChB;IACD,MAAM,EAAE,mCAAmC;IAC3C,UAAU,EAAE;QACV,+BAA+B,EAAE;YAC/B,SAAS,EAAE,QAAQ;SACpB;QACD,iCAAiC,EAAE;YACjC,SAAS,EAAE,QAAQ;SACpB;QACD,6BAA6B,EAAE;YAC7B,SAAS,EAAE,QAAQ;SACpB;QACD,6BAA6B,EAAE;YAC7B,SAAS,EAAE,QAAQ;SACpB;KACF;IACD,gBAAgB,EAAE,QAAQ;IAC1B,SAAS,EAAE;QACT,SAAS,EAAE,WAAW;QACtB,iBAAiB,EAAE,KAAK;QACxB,MAAM,EAAE,QAAQ;QAChB,mBAAmB,EAAE,OAAO;QAC5B,MAAM,EAAE,MAAM;QACd,gBAAgB,EAAE,aAAa;QAC/B,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE,QAAQ;QACpB,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,QAAQ;QACjB,YAAY,EAAE,OAAO;KACtB;IACD,eAAe,EAAE,sCAAsC;CACxD,CAC6C,CAAC;AAE/C,sCAAsC,CAAC,gCAAgC,CAAC,CAAC","sourcesContent":["// Generated by standards/scripts/generate-conformance-current-release.mjs.\n// Each exact package release verifies its own current runtime contract.\nimport {\n type BrandlabRuntimeReleaseContract,\n validateBrandlabRuntimeReleaseContract,\n} from \"./release-manifest.js\";\n\nexport const BRANDLAB_CURRENT_RUNTIME_RELEASE = Object.freeze(\n{\n \"capabilities\": [\n \"typed-project-business-and-route-data\",\n \"essential-search-foundations\",\n \"shared-contact-delivery\",\n \"privacy-safe-lead-analytics\",\n \"security-patched-runtime\",\n \"live-google-review-summary\",\n \"high-signal-project-verification\",\n \"packed-positive-and-negative-consumers\",\n \"changesets-oidc-release\"\n ],\n \"contracts\": {\n \"analytics\": \"analytics-v4\",\n \"architecture\": \"architecture-v7\",\n \"configuration\": \"project-config-v7\",\n \"contact\": \"contact-v4\",\n \"seo\": \"seo-v4\"\n },\n \"kind\": \"brandlab-runtime-release-contract\",\n \"packages\": {\n \"@brandlab-digital/conformance\": {\n \"version\": \"3.19.1\"\n },\n \"@brandlab-digital/eslint-plugin\": {\n \"version\": \"3.19.1\"\n },\n \"@brandlab-digital/site-core\": {\n \"version\": \"3.19.1\"\n },\n \"@brandlab-digital/site-next\": {\n \"version\": \"3.19.1\"\n }\n },\n \"releaseVersion\": \"3.19.1\",\n \"runtime\": {\n \"bundler\": \"turbopack\",\n \"cacheComponents\": false,\n \"next\": \"16.4.2\",\n \"nextVersionPolicy\": \"exact\",\n \"node\": \"24.x\",\n \"packageManager\": \"npm@11.14.1\",\n \"react\": \"19.2.8\",\n \"reactDom\": \"19.2.8\",\n \"router\": \"app\",\n \"sharp\": \"0.35.5\",\n \"typescript\": \"6.0.3\"\n },\n \"schemaVersion\": \"brandlab.runtime-release-contract.v1\"\n},\n) as unknown as BrandlabRuntimeReleaseContract;\n\nvalidateBrandlabRuntimeReleaseContract(BRANDLAB_CURRENT_RUNTIME_RELEASE);\n"]}
|
|
@@ -131,6 +131,8 @@ export declare function paintedGround(element: Element): string;
|
|
|
131
131
|
/**
|
|
132
132
|
* The page's top-level blocks in order (K14): each rendered child of `main` (through a lone wrapper), then what follows
|
|
133
133
|
* `main` up to and including the footer. A `[data-bl-inset]` block is part of the place before it, so it is left out.
|
|
134
|
+
* A `display: contents` wrapper has no box of its own (3.19.1): its rendered children stand in its place, named by
|
|
135
|
+
* the wrapper's section.
|
|
134
136
|
*/
|
|
135
137
|
export declare function groundBlocks(): PaintedGround[];
|
|
136
138
|
/** Neighbouring blocks that paint the same colour (K14): a photo or an unknown ground never matches. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-helpers.d.ts","sourceRoot":"","sources":["../../../src/site-system/journeys/page-helpers.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"page-helpers.d.ts","sourceRoot":"","sources":["../../../src/site-system/journeys/page-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -452,28 +452,36 @@ export function paintedGround(element) {
|
|
|
452
452
|
/**
|
|
453
453
|
* The page's top-level blocks in order (K14): each rendered child of `main` (through a lone wrapper), then what follows
|
|
454
454
|
* `main` up to and including the footer. A `[data-bl-inset]` block is part of the place before it, so it is left out.
|
|
455
|
+
* A `display: contents` wrapper has no box of its own (3.19.1): its rendered children stand in its place, named by
|
|
456
|
+
* the wrapper's section.
|
|
455
457
|
*/
|
|
456
458
|
export function groundBlocks() {
|
|
457
459
|
const main = document.querySelector('main');
|
|
458
460
|
if (!main)
|
|
459
461
|
return [];
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
462
|
+
const skipped = (element) => ['SCRIPT', 'STYLE', 'TEMPLATE', 'NOSCRIPT', 'LINK'].includes(element.tagName)
|
|
463
|
+
|| element.hasAttribute('data-bl-inset');
|
|
464
|
+
const named = (element, label) => label ?? element.getAttribute('data-bl-section') ?? (element.tagName === 'FOOTER' ? 'footer' : null);
|
|
465
|
+
const expand = (elements, label = null) => elements.flatMap((element) => {
|
|
466
|
+
if (skipped(element))
|
|
467
|
+
return [];
|
|
468
|
+
if (getComputedStyle(element).display === 'contents')
|
|
469
|
+
return expand(Array.from(element.children), named(element, label));
|
|
470
|
+
return isRendered(element) && element.getBoundingClientRect().height >= 8 ? [{ block: element, section: named(element, label) }] : [];
|
|
471
|
+
});
|
|
472
|
+
let blocks = expand(Array.from(main.children));
|
|
473
|
+
while (blocks.length === 1 && expand(Array.from(blocks[0].block.children)).length > 1 && paintedGround(blocks[0].block).startsWith('rgb') === false) {
|
|
474
|
+
blocks = expand(Array.from(blocks[0].block.children));
|
|
465
475
|
}
|
|
466
476
|
const footer = document.querySelector('footer[data-bl="footer"], body footer:not(main footer)');
|
|
467
477
|
for (let node = main.nextElementSibling; node; node = node.nextElementSibling) {
|
|
468
|
-
|
|
469
|
-
blocks.push(node);
|
|
478
|
+
blocks.push(...expand([node]));
|
|
470
479
|
if (node === footer || node.contains(footer))
|
|
471
480
|
break;
|
|
472
481
|
}
|
|
473
|
-
if (footer && !blocks.some((block) => block === footer || block.contains(footer)) && isRendered(footer))
|
|
474
|
-
blocks.push(footer);
|
|
475
|
-
return blocks.map((block) => {
|
|
476
|
-
const section = block.getAttribute('data-bl-section') ?? (block.tagName === 'FOOTER' ? 'footer' : null);
|
|
482
|
+
if (footer && !blocks.some(({ block }) => block === footer || block.contains(footer)) && isRendered(footer))
|
|
483
|
+
blocks.push({ block: footer, section: 'footer' });
|
|
484
|
+
return blocks.map(({ block, section }) => {
|
|
477
485
|
const description = section ? `"${section}"` : `${block.tagName.toLowerCase()}${block.id ? `#${block.id}` : ''}`;
|
|
478
486
|
return { description, ground: paintedGround(block) };
|
|
479
487
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-helpers.js","sourceRoot":"","sources":["../../../src/site-system/journeys/page-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Functions the site-system journeys run inside the page under test. Each one is self-contained: it uses DOM globals\n * and the other helpers in this file only, because `pageHelpersSource()` injects their source into every document\n * (as `window.__brandlabSiteSystem`, through Playwright's init script, which a Content Security Policy does not\n * block). The pure parts (colour, contrast, placement) are unit-tested in Node.\n */\n\n/**\n * The placements `phone_link_click` accepts: site-next's PHONE_CALL_PLACEMENTS (conformance cannot depend on\n * site-next; a test reads the site-next source and compares). Injected into the page with the helpers.\n */\nexport const SITE_SYSTEM_PHONE_PLACEMENTS: readonly string[] = Object.freeze(['header', 'footer', 'hero', 'cta', 'fab', 'contact', 'location', 'page', 'emergency']);\n\nexport type Rgba = [number, number, number, number];\n\n/** What `watchDisclosure` has seen, in `performance.now()` milliseconds. */\nexport interface DisclosureWatch {\n enter: number | null;\n leave: number | null;\n opened: number | null;\n closed: number | null;\n open: boolean;\n}\n\n/**\n * Whether an element is rendered: connected, with a box, not `visibility: hidden`, not fully transparent and not\n * inside a closed `<details>` (outside its summary). Chromium gives the content of a closed `<details>` a box, so\n * the box alone is not enough; `checkVisibility()` settles it where the browser has it.\n */\nexport function isRendered(element: Element | null | undefined): boolean {\n if (!element || !element.isConnected) return false;\n for (let details = element.closest('details:not([open])'); details; details = details.parentElement?.closest('details:not([open])') ?? null) {\n const summary = Array.from(details.children).find((child) => child.tagName === 'SUMMARY');\n if (!summary || !summary.contains(element)) return false;\n }\n if (typeof element.checkVisibility === 'function' && !element.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true })) return false;\n const rect = element.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return false;\n if (getComputedStyle(element).visibility !== 'visible') return false;\n for (let node: Element | null = element; node; node = node.parentElement) {\n if (getComputedStyle(node).opacity === '0') return false;\n }\n return true;\n}\n\n/** A short, readable name for an element in a failure message. */\nexport function describeElement(element: Element): string {\n const tag = element.tagName.toLowerCase();\n const label = element.getAttribute('aria-label') ?? (element as HTMLElement).innerText ?? element.textContent ?? '';\n const text = label.replace(/\\s+/g, ' ').trim().slice(0, 40);\n const href = element.getAttribute('href');\n return `${tag}${text ? ` \"${text}\"` : ''}${href ? ` (${href})` : ''}`;\n}\n\n/** The accessible name, approximately: aria-label, aria-labelledby, the rendered text, then the title. */\nexport function accessibleName(element: Element): string {\n const label = element.getAttribute('aria-label');\n if (label && label.trim()) return label.trim();\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const text = labelledBy.split(/\\s+/).map((id) => document.getElementById(id)?.textContent ?? '').join(' ').trim();\n if (text) return text.replace(/\\s+/g, ' ');\n }\n const text = ((element as HTMLElement).innerText ?? element.textContent ?? '').replace(/\\s+/g, ' ').trim();\n return text || (element.getAttribute('title') ?? '').trim();\n}\n\n/**\n * Where a telephone link reports its tap, exactly as site-next's shared listener resolves it: its own valid\n * `data-phone-location`, then a `<header>` or `<footer>` ancestor, then the nearest ancestor with a valid value,\n * otherwise `page`. `invalid` is the nearest declared value when it is not an allowed placement (the listener then\n * reports the link somewhere else, silently).\n */\nexport function phonePlacement(link: Element): { placement: string; invalid: string | null } {\n const valid = (node: Element): string | undefined => {\n const value = node.getAttribute('data-phone-location')?.trim().toLowerCase();\n return value && SITE_SYSTEM_PHONE_PLACEMENTS.includes(value) ? value : undefined;\n };\n const nearest = link.closest('[data-phone-location]');\n const invalid = nearest && !valid(nearest) ? nearest.getAttribute('data-phone-location') : null;\n const own = valid(link);\n if (own) return { placement: own, invalid };\n if (link.closest('header')) return { placement: 'header', invalid };\n if (link.closest('footer')) return { placement: 'footer', invalid };\n for (let node = link.parentElement?.closest('[data-phone-location]') ?? null; node; node = node.parentElement?.closest('[data-phone-location]') ?? null) {\n const value = valid(node);\n if (value) return { placement: value, invalid };\n }\n return { placement: 'page', invalid };\n}\n\n/** Parse a computed colour. `rgb()`/`rgba()` directly; any other syntax (oklch, lab, color()) through a canvas pixel. */\nexport function parseColour(value: string): Rgba | null {\n const text = value.trim().toLowerCase();\n if (text === 'transparent') return [0, 0, 0, 0];\n const match = /^rgba?\\(([^)]+)\\)$/.exec(text);\n if (match) {\n const parts = match[1]!.split(/[\\s,/]+/).filter(Boolean);\n if (parts.length < 3) return null;\n const channel = (part: string) => (part.endsWith('%') ? (Number.parseFloat(part) / 100) * 255 : Number.parseFloat(part));\n const alphaPart = parts[3];\n const alpha = alphaPart === undefined ? 1 : alphaPart.endsWith('%') ? Number.parseFloat(alphaPart) / 100 : Number.parseFloat(alphaPart);\n const rgba: Rgba = [channel(parts[0]!), channel(parts[1]!), channel(parts[2]!), alpha];\n return rgba.every((part) => Number.isFinite(part)) ? rgba : null;\n }\n if (typeof document === 'undefined') return null;\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const context = canvas.getContext('2d', { willReadFrequently: true });\n if (!context) return null;\n context.clearRect(0, 0, 1, 1);\n context.fillStyle = value;\n context.fillRect(0, 0, 1, 1);\n const [red = 0, green = 0, blue = 0, alpha = 0] = Array.from(context.getImageData(0, 0, 1, 1).data);\n return [red, green, blue, alpha / 255];\n}\n\n/** `top` painted over an opaque `bottom`. */\nexport function compositeColour(top: Rgba, bottom: Rgba): Rgba {\n const alpha = top[3];\n return [\n top[0] * alpha + bottom[0] * (1 - alpha),\n top[1] * alpha + bottom[1] * (1 - alpha),\n top[2] * alpha + bottom[2] * (1 - alpha),\n 1,\n ];\n}\n\n/** The WCAG contrast ratio of two opaque colours. */\nexport function contrastRatio(first: Rgba, second: Rgba): number {\n const luminance = (colour: Rgba) => {\n const [red, green, blue] = colour.slice(0, 3).map((channel) => {\n const value = channel / 255;\n return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;\n }) as [number, number, number];\n return 0.2126 * red + 0.7152 * green + 0.0722 * blue;\n };\n const [light, dark] = [luminance(first), luminance(second)].sort((left, right) => right - left) as [number, number];\n return (light + 0.05) / (dark + 0.05);\n}\n\n/**\n * The opaque colour behind an element, from its own and its ancestors' background colours over a white canvas.\n * `null` when a background image (a photo or gradient) is in the way: the contrast cannot be computed there.\n */\nexport function backgroundBehind(element: Element): Rgba | null {\n const layers: Rgba[] = [];\n for (let node: Element | null = element; node; node = node.parentElement) {\n const style = getComputedStyle(node);\n if (style.backgroundImage && style.backgroundImage !== 'none') return null;\n const colour = parseColour(style.backgroundColor);\n if (colour && colour[3] > 0) {\n layers.push(colour);\n if (colour[3] >= 1) break;\n }\n }\n return layers.reverse().reduce<Rgba>((bottom, top) => compositeColour(top, bottom), [255, 255, 255, 1]);\n}\n\n/**\n * Non-text contrast (WCAG 1.4.11) of icon-only controls inside `root`: a link or button with no visible text whose\n * icon is an SVG must reach 3:1 against what is behind it. Returns one line per failure; controls over a photo are\n * counted in `unmeasured`.\n */\nexport function iconContrastProblems(root: Element): { problems: string[]; checked: number; unmeasured: number } {\n const problems: string[] = [];\n let checked = 0;\n let unmeasured = 0;\n const paintOf = (svg: SVGElement): Rgba | null => {\n for (const shape of Array.from(svg.querySelectorAll('path, circle, rect, ellipse, line, polyline, polygon, text, use'))) {\n if (!isRendered(shape)) continue;\n const style = getComputedStyle(shape);\n for (const [paint, opacity] of [[style.fill, style.fillOpacity], [style.stroke, style.strokeOpacity]] as const) {\n if (!paint || paint === 'none' || paint.startsWith('url(')) continue;\n const colour = parseColour(paint);\n const alpha = colour ? colour[3] * Number(opacity || 1) * Number(style.opacity || 1) : 0;\n if (colour && alpha > 0) return [colour[0], colour[1], colour[2], alpha];\n }\n }\n return null;\n };\n for (const control of Array.from(root.querySelectorAll('a[href], button'))) {\n if (!isRendered(control)) continue;\n if (((control as HTMLElement).innerText ?? '').trim()) continue;\n const svg = control.querySelector('svg');\n if (!svg || !isRendered(svg)) continue;\n const paint = paintOf(svg);\n if (!paint) continue;\n const background = backgroundBehind(svg);\n if (!background) {\n unmeasured += 1;\n continue;\n }\n checked += 1;\n const ratio = contrastRatio(compositeColour(paint, background), background);\n if (ratio < 3) problems.push(`${describeElement(control)}: its icon is ${ratio.toFixed(2)}:1 against its background (needs 3:1)`);\n }\n return { problems, checked, unmeasured };\n}\n\n/**\n * The phone call bar: the shared `MobileCallBar`, or any fixed or sticky element along the bottom of the screen that\n * holds a visible telephone link (outside the header and dialogs). `null` when none is on screen.\n */\nexport function findCallBar(): Element | null {\n const tagged = Array.from(document.querySelectorAll('[data-bl=\"call-bar\"], [data-bl=\"callbar\"], [data-bl=\"mobile-call-bar\"]')).find(isRendered);\n if (tagged) return tagged;\n const height = window.innerHeight;\n for (const element of Array.from(document.body.querySelectorAll('*'))) {\n const position = getComputedStyle(element).position;\n if (position !== 'fixed' && position !== 'sticky') continue;\n if (element.closest('header, dialog, [role=\"dialog\"]')) continue;\n const rect = element.getBoundingClientRect();\n if (rect.height <= 0 || rect.bottom < height - 4 || rect.top < height / 2) continue;\n if (!isRendered(element)) continue;\n if (Array.from(element.querySelectorAll('a[href^=\"tel:\"]')).some(isRendered)) return element;\n }\n return null;\n}\n\n/** Visible quote actions in `root`: links or buttons named like the quote action, or the shared quote hooks. */\nexport function quoteActions(root: Element, name: { source: string; flags: string }): Element[] {\n const pattern = new RegExp(name.source, name.flags);\n return Array.from(root.querySelectorAll('a[href], button')).filter((element) => {\n if (!isRendered(element) || element.getAttribute('href')?.startsWith('tel:')) return false;\n if (element.matches('[data-bl=\"quote-button\"], [data-bl-cta^=\"quote\"], [data-lead-cta^=\"quote\"]')) return true;\n return pattern.test(accessibleName(element));\n });\n}\n\n/** The order of the first visible phone link and quote action in `root`. */\nexport function actionOrder(root: Element, name: { source: string; flags: string }): 'phone-first' | 'quote-first' | 'incomplete' {\n const phone = Array.from(root.querySelectorAll('a[href^=\"tel:\"]')).find(isRendered);\n const quote = quoteActions(root, name)[0];\n if (!phone || !quote) return 'incomplete';\n return phone.compareDocumentPosition(quote) & Node.DOCUMENT_POSITION_FOLLOWING ? 'phone-first' : 'quote-first';\n}\n\n/**\n * The hero: the shared hero section, else the smallest block around the page's visible H1 that holds a phone link\n * and a quote action, never above the H1's own section and never `<main>` (without a section, never a block holding\n * an H2). When none holds both, the H1's section (or its parent): its order then reads \"incomplete\".\n */\nexport function heroRegion(name: { source: string; flags: string }): Element | null {\n const heading = Array.from(document.querySelectorAll('h1')).find(isRendered);\n if (!heading) return null;\n const tagged = heading.closest('[data-bl-section=\"hero\"]');\n if (tagged) return tagged;\n const section = heading.closest('section');\n const fallback = section ?? heading.parentElement;\n for (let node = heading.parentElement; node && node !== document.body && node.tagName !== 'MAIN'; node = node.parentElement) {\n if (!section && node.querySelector('h2')) break;\n if (Array.from(node.querySelectorAll('a[href^=\"tel:\"]')).some(isRendered) && quoteActions(node, name).length > 0) return node;\n if (node === section) break;\n }\n return fallback && fallback.tagName !== 'MAIN' ? fallback : heading;\n}\n\n/** A point in the page that is not on an interactive element, a menu or anything in `avoid`. */\nexport function outsidePoint(avoid: Element[]): { x: number; y: number } | null {\n const interactive = 'a[href], button, input, select, textarea, label, summary, details, iframe, video, audio, [role=\"button\"], [role=\"link\"], [role=\"menuitem\"], [role=\"tab\"], [tabindex], [contenteditable=\"\"], [contenteditable=\"true\"]';\n for (let row = 9; row >= 3; row -= 1) {\n for (let column = 1; column <= 9; column += 1) {\n const x = Math.round((window.innerWidth * column) / 10);\n const y = Math.round((window.innerHeight * row) / 10);\n const element = document.elementFromPoint(x, y);\n if (!element || avoid.some((region) => region.contains(element))) continue;\n if (element.closest(interactive) || element.closest('header, nav, dialog, [role=\"dialog\"]')) continue;\n return { x, y };\n }\n }\n return null;\n}\n\n/** Tag an element so Playwright and axe can find it by `[data-brandlab-journey~=\"<name>\"]`. */\nexport function markElement(element: Element, name: string): void {\n const names = new Set((element.getAttribute('data-brandlab-journey') ?? '').split(/\\s+/).filter(Boolean));\n names.add(name);\n element.setAttribute('data-brandlab-journey', [...names].join(' '));\n}\n\n/**\n * Watch one disclosure: when the pointer enters and leaves its item (and panel), and when the panel it controls\n * becomes rendered or hidden, timed with `performance.now()`. Attribute and tree changes are sampled at once; style\n * changes without a DOM change (CSS `:hover`) every animation frame.\n */\nexport function watchDisclosure(trigger: Element, panelId: string): void {\n const item = trigger.closest('li') ?? trigger.parentElement ?? trigger;\n const panel = () => document.getElementById(panelId);\n const inside = (node: EventTarget | null) => node instanceof Node && (item.contains(node) || Boolean(panel()?.contains(node)));\n const state: DisclosureWatch = { enter: null, leave: null, opened: null, closed: null, open: isRendered(panel()) };\n const sample = () => {\n const open = isRendered(panel());\n if (open === state.open) return;\n state.open = open;\n if (open && state.opened === null) state.opened = performance.now();\n if (!open && state.closed === null) state.closed = performance.now();\n };\n const onOver = (event: Event) => {\n if (state.enter === null && inside(event.target)) state.enter = performance.now();\n };\n const onOut = (event: Event) => {\n if (state.leave === null && inside(event.target) && !inside((event as PointerEvent).relatedTarget)) state.leave = performance.now();\n };\n const observer = new MutationObserver(sample);\n observer.observe(document.documentElement, { attributes: true, childList: true, subtree: true });\n let frame = 0;\n const loop = () => {\n sample();\n frame = requestAnimationFrame(loop);\n };\n loop();\n document.addEventListener('pointerover', onOver, true);\n document.addEventListener('pointerout', onOut, true);\n const previous = (window as unknown as { __brandlabSiteSystemWatch?: { stop(): void } }).__brandlabSiteSystemWatch;\n previous?.stop();\n (window as unknown as { __brandlabSiteSystemWatch: unknown }).__brandlabSiteSystemWatch = {\n state,\n stop() {\n observer.disconnect();\n cancelAnimationFrame(frame);\n document.removeEventListener('pointerover', onOver, true);\n document.removeEventListener('pointerout', onOut, true);\n },\n };\n}\n\n/** The current state of `watchDisclosure`'s watch. */\nexport function watchState(): DisclosureWatch | null {\n const watch = (window as unknown as { __brandlabSiteSystemWatch?: { state: DisclosureWatch } }).__brandlabSiteSystemWatch;\n return watch ? { ...watch.state } : null;\n}\n\n/**\n * After a Tab press: is the focused element fully hidden under the sticky header or the call bar? Samples nine points\n * across the visible part of its box; it is hidden when the header or call bar is on top at every one. `repeat` is\n * true once focus comes back to an element it has already visited.\n */\nexport function focusStep(): { done: boolean; repeat: boolean; obscured: string | null; covered: 'header' | 'call bar' | null } {\n const element = document.activeElement;\n const store = window as unknown as { __brandlabSiteSystemFocus?: WeakSet<Element> };\n store.__brandlabSiteSystemFocus ??= new WeakSet<Element>();\n if (!element || element === document.body || element === document.documentElement) return { done: true, repeat: false, obscured: null, covered: null };\n const repeat = store.__brandlabSiteSystemFocus.has(element);\n store.__brandlabSiteSystemFocus.add(element);\n const header = document.querySelector('[data-brandlab-journey~=\"header\"]')\n ?? Array.from(document.querySelectorAll('[data-bl=\"header\"], header')).find((candidate) => isRendered(candidate) && !candidate.closest('main, article, section, aside, footer'))\n ?? null;\n const callBar = findCallBar();\n if (header?.contains(element) || callBar?.contains(element)) return { done: false, repeat, obscured: null, covered: null };\n const rect = element.getBoundingClientRect();\n const left = Math.max(rect.left, 0);\n const right = Math.min(rect.right, window.innerWidth);\n const top = Math.max(rect.top, 0);\n const bottom = Math.min(rect.bottom, window.innerHeight);\n if (right - left < 1 || bottom - top < 1) return { done: false, repeat, obscured: null, covered: null };\n let coveredBy: 'header' | 'call bar' | null = null;\n for (const fx of [0.15, 0.5, 0.85]) {\n for (const fy of [0.15, 0.5, 0.85]) {\n const hit = document.elementFromPoint(left + (right - left) * fx, top + (bottom - top) * fy);\n if (!hit || element.contains(hit)) return { done: false, repeat, obscured: null, covered: null };\n if (header?.contains(hit)) coveredBy ??= 'header';\n else if (callBar?.contains(hit)) coveredBy ??= 'call bar';\n else return { done: false, repeat, obscured: null, covered: null };\n }\n }\n return { done: false, repeat, obscured: describeElement(element), covered: coveredBy };\n}\n\n/**\n * `focusStep` one animation frame after the focus moved (capped at 50 ms, since a background page may not paint), so\n * a sticky bar that hides on its observer's next frame is measured after it moved, not mid-transition.\n */\nexport function focusStepAfterFrame(): Promise<ReturnType<typeof focusStep>> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n resolve(focusStep());\n };\n requestAnimationFrame(() => finish());\n setTimeout(finish, 50);\n });\n}\n\n/** Elements a Tab press can reach, roughly: enough to bound the K5 walk. */\nexport function tabbableCount(): number {\n const selector = 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), summary, iframe, [tabindex]:not([tabindex=\"-1\"])';\n return Array.from(document.querySelectorAll(selector)).filter(isRendered).length;\n}\n\n/** What a K14 block paints: an opaque colour, a photo or gradient (never equal to another block's), or unknown. */\nexport interface PaintedGround {\n description: string;\n /** `rgb(r, g, b)`, `image` or `unknown`. */\n ground: string;\n}\n\n/**\n * The ground a top-level block paints (K14, 3.19.0): its own background image (a photo band or gradient), a photo\n * covering most of it (a fill image), else its background colour composited over what shows through from its\n * ancestors. A transparent block whose one child covers it and paints a colour takes the child's.\n */\nexport function paintedGround(element: Element): string {\n const box = element.getBoundingClientRect();\n const area = box.width * box.height;\n if (area <= 0) return 'unknown';\n if (getComputedStyle(element).backgroundImage !== 'none') return 'image';\n for (const media of Array.from(element.querySelectorAll('img, picture, video'))) {\n const rect = media.getBoundingClientRect();\n if (rect.width * rect.height >= 0.8 * area && isRendered(media)) return 'image';\n }\n let painter: Element = element;\n const own = parseColour(getComputedStyle(element).backgroundColor);\n if (!own || own[3] === 0) {\n const cover = Array.from(element.children).find((child) => {\n const rect = child.getBoundingClientRect();\n const colour = parseColour(getComputedStyle(child).backgroundColor);\n return rect.width * rect.height >= 0.9 * area && colour !== null && colour[3] > 0;\n });\n if (cover) {\n if (getComputedStyle(cover).backgroundImage !== 'none') return 'image';\n painter = cover;\n }\n }\n const colour = backgroundBehind(painter);\n if (!colour) return 'image';\n return `rgb(${colour.slice(0, 3).map((channel) => Math.round(channel)).join(', ')})`;\n}\n\n/**\n * The page's top-level blocks in order (K14): each rendered child of `main` (through a lone wrapper), then what follows\n * `main` up to and including the footer. A `[data-bl-inset]` block is part of the place before it, so it is left out.\n */\nexport function groundBlocks(): PaintedGround[] {\n const main = document.querySelector('main');\n if (!main) return [];\n const usable = (element: Element) => !['SCRIPT', 'STYLE', 'TEMPLATE', 'NOSCRIPT', 'LINK'].includes(element.tagName)\n && !element.hasAttribute('data-bl-inset') && isRendered(element) && element.getBoundingClientRect().height >= 8;\n let blocks = Array.from(main.children).filter(usable);\n while (blocks.length === 1 && Array.from(blocks[0]!.children).filter(usable).length > 1 && paintedGround(blocks[0]!).startsWith('rgb') === false) {\n blocks = Array.from(blocks[0]!.children).filter(usable);\n }\n const footer = document.querySelector('footer[data-bl=\"footer\"], body footer:not(main footer)');\n for (let node = main.nextElementSibling; node; node = node.nextElementSibling) {\n if (usable(node)) blocks.push(node);\n if (node === footer || node.contains(footer)) break;\n }\n if (footer && !blocks.some((block) => block === footer || block.contains(footer)) && isRendered(footer)) blocks.push(footer);\n return blocks.map((block) => {\n const section = block.getAttribute('data-bl-section') ?? (block.tagName === 'FOOTER' ? 'footer' : null);\n const description = section ? `\"${section}\"` : `${block.tagName.toLowerCase()}${block.id ? `#${block.id}` : ''}`;\n return { description, ground: paintedGround(block) };\n });\n}\n\n/** Neighbouring blocks that paint the same colour (K14): a photo or an unknown ground never matches. */\nexport function groundProblems(path: string, blocks: readonly PaintedGround[]): string[] {\n const problems: string[] = [];\n const channels = (ground: string) => ground.slice(4, -1).split(',').map(Number);\n for (let index = 1; index < blocks.length; index += 1) {\n const [before, after] = [blocks[index - 1]!, blocks[index]!];\n if (!before.ground.startsWith('rgb') || !after.ground.startsWith('rgb')) continue;\n const [left, right] = [channels(before.ground), channels(after.ground)];\n if (left.every((channel, at) => Math.abs(channel - right[at]!) <= 2)) {\n problems.push(`${path}: ${before.description} and ${after.description} share the background ${after.ground}`);\n }\n }\n return problems;\n}\n\nconst PAGE_HELPERS = {\n isRendered, describeElement, accessibleName, phonePlacement, parseColour, compositeColour, contrastRatio, backgroundBehind,\n iconContrastProblems, findCallBar, quoteActions, actionOrder, heroRegion, outsidePoint, markElement, watchDisclosure,\n watchState, focusStep, focusStepAfterFrame, tabbableCount, paintedGround, groundBlocks, groundProblems,\n};\n\n/** `window.__brandlabSiteSystem` in a page the journeys opened. */\nexport type SiteSystemPageHelpers = typeof PAGE_HELPERS;\n\n/** The init script that defines `window.__brandlabSiteSystem` in every document of the page. */\nexport function pageHelpersSource(): string {\n const names = Object.keys(PAGE_HELPERS);\n return `(() => {\\nconst SITE_SYSTEM_PHONE_PLACEMENTS = ${JSON.stringify(SITE_SYSTEM_PHONE_PLACEMENTS)};\\n${Object.values(PAGE_HELPERS).map((helper) => helper.toString()).join('\\n')}\\nwindow.__brandlabSiteSystem = { ${names.join(', ')} };\\n})();`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"page-helpers.js","sourceRoot":"","sources":["../../../src/site-system/journeys/page-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Functions the site-system journeys run inside the page under test. Each one is self-contained: it uses DOM globals\n * and the other helpers in this file only, because `pageHelpersSource()` injects their source into every document\n * (as `window.__brandlabSiteSystem`, through Playwright's init script, which a Content Security Policy does not\n * block). The pure parts (colour, contrast, placement) are unit-tested in Node.\n */\n\n/**\n * The placements `phone_link_click` accepts: site-next's PHONE_CALL_PLACEMENTS (conformance cannot depend on\n * site-next; a test reads the site-next source and compares). Injected into the page with the helpers.\n */\nexport const SITE_SYSTEM_PHONE_PLACEMENTS: readonly string[] = Object.freeze(['header', 'footer', 'hero', 'cta', 'fab', 'contact', 'location', 'page', 'emergency']);\n\nexport type Rgba = [number, number, number, number];\n\n/** What `watchDisclosure` has seen, in `performance.now()` milliseconds. */\nexport interface DisclosureWatch {\n enter: number | null;\n leave: number | null;\n opened: number | null;\n closed: number | null;\n open: boolean;\n}\n\n/**\n * Whether an element is rendered: connected, with a box, not `visibility: hidden`, not fully transparent and not\n * inside a closed `<details>` (outside its summary). Chromium gives the content of a closed `<details>` a box, so\n * the box alone is not enough; `checkVisibility()` settles it where the browser has it.\n */\nexport function isRendered(element: Element | null | undefined): boolean {\n if (!element || !element.isConnected) return false;\n for (let details = element.closest('details:not([open])'); details; details = details.parentElement?.closest('details:not([open])') ?? null) {\n const summary = Array.from(details.children).find((child) => child.tagName === 'SUMMARY');\n if (!summary || !summary.contains(element)) return false;\n }\n if (typeof element.checkVisibility === 'function' && !element.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true })) return false;\n const rect = element.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return false;\n if (getComputedStyle(element).visibility !== 'visible') return false;\n for (let node: Element | null = element; node; node = node.parentElement) {\n if (getComputedStyle(node).opacity === '0') return false;\n }\n return true;\n}\n\n/** A short, readable name for an element in a failure message. */\nexport function describeElement(element: Element): string {\n const tag = element.tagName.toLowerCase();\n const label = element.getAttribute('aria-label') ?? (element as HTMLElement).innerText ?? element.textContent ?? '';\n const text = label.replace(/\\s+/g, ' ').trim().slice(0, 40);\n const href = element.getAttribute('href');\n return `${tag}${text ? ` \"${text}\"` : ''}${href ? ` (${href})` : ''}`;\n}\n\n/** The accessible name, approximately: aria-label, aria-labelledby, the rendered text, then the title. */\nexport function accessibleName(element: Element): string {\n const label = element.getAttribute('aria-label');\n if (label && label.trim()) return label.trim();\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const text = labelledBy.split(/\\s+/).map((id) => document.getElementById(id)?.textContent ?? '').join(' ').trim();\n if (text) return text.replace(/\\s+/g, ' ');\n }\n const text = ((element as HTMLElement).innerText ?? element.textContent ?? '').replace(/\\s+/g, ' ').trim();\n return text || (element.getAttribute('title') ?? '').trim();\n}\n\n/**\n * Where a telephone link reports its tap, exactly as site-next's shared listener resolves it: its own valid\n * `data-phone-location`, then a `<header>` or `<footer>` ancestor, then the nearest ancestor with a valid value,\n * otherwise `page`. `invalid` is the nearest declared value when it is not an allowed placement (the listener then\n * reports the link somewhere else, silently).\n */\nexport function phonePlacement(link: Element): { placement: string; invalid: string | null } {\n const valid = (node: Element): string | undefined => {\n const value = node.getAttribute('data-phone-location')?.trim().toLowerCase();\n return value && SITE_SYSTEM_PHONE_PLACEMENTS.includes(value) ? value : undefined;\n };\n const nearest = link.closest('[data-phone-location]');\n const invalid = nearest && !valid(nearest) ? nearest.getAttribute('data-phone-location') : null;\n const own = valid(link);\n if (own) return { placement: own, invalid };\n if (link.closest('header')) return { placement: 'header', invalid };\n if (link.closest('footer')) return { placement: 'footer', invalid };\n for (let node = link.parentElement?.closest('[data-phone-location]') ?? null; node; node = node.parentElement?.closest('[data-phone-location]') ?? null) {\n const value = valid(node);\n if (value) return { placement: value, invalid };\n }\n return { placement: 'page', invalid };\n}\n\n/** Parse a computed colour. `rgb()`/`rgba()` directly; any other syntax (oklch, lab, color()) through a canvas pixel. */\nexport function parseColour(value: string): Rgba | null {\n const text = value.trim().toLowerCase();\n if (text === 'transparent') return [0, 0, 0, 0];\n const match = /^rgba?\\(([^)]+)\\)$/.exec(text);\n if (match) {\n const parts = match[1]!.split(/[\\s,/]+/).filter(Boolean);\n if (parts.length < 3) return null;\n const channel = (part: string) => (part.endsWith('%') ? (Number.parseFloat(part) / 100) * 255 : Number.parseFloat(part));\n const alphaPart = parts[3];\n const alpha = alphaPart === undefined ? 1 : alphaPart.endsWith('%') ? Number.parseFloat(alphaPart) / 100 : Number.parseFloat(alphaPart);\n const rgba: Rgba = [channel(parts[0]!), channel(parts[1]!), channel(parts[2]!), alpha];\n return rgba.every((part) => Number.isFinite(part)) ? rgba : null;\n }\n if (typeof document === 'undefined') return null;\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const context = canvas.getContext('2d', { willReadFrequently: true });\n if (!context) return null;\n context.clearRect(0, 0, 1, 1);\n context.fillStyle = value;\n context.fillRect(0, 0, 1, 1);\n const [red = 0, green = 0, blue = 0, alpha = 0] = Array.from(context.getImageData(0, 0, 1, 1).data);\n return [red, green, blue, alpha / 255];\n}\n\n/** `top` painted over an opaque `bottom`. */\nexport function compositeColour(top: Rgba, bottom: Rgba): Rgba {\n const alpha = top[3];\n return [\n top[0] * alpha + bottom[0] * (1 - alpha),\n top[1] * alpha + bottom[1] * (1 - alpha),\n top[2] * alpha + bottom[2] * (1 - alpha),\n 1,\n ];\n}\n\n/** The WCAG contrast ratio of two opaque colours. */\nexport function contrastRatio(first: Rgba, second: Rgba): number {\n const luminance = (colour: Rgba) => {\n const [red, green, blue] = colour.slice(0, 3).map((channel) => {\n const value = channel / 255;\n return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;\n }) as [number, number, number];\n return 0.2126 * red + 0.7152 * green + 0.0722 * blue;\n };\n const [light, dark] = [luminance(first), luminance(second)].sort((left, right) => right - left) as [number, number];\n return (light + 0.05) / (dark + 0.05);\n}\n\n/**\n * The opaque colour behind an element, from its own and its ancestors' background colours over a white canvas.\n * `null` when a background image (a photo or gradient) is in the way: the contrast cannot be computed there.\n */\nexport function backgroundBehind(element: Element): Rgba | null {\n const layers: Rgba[] = [];\n for (let node: Element | null = element; node; node = node.parentElement) {\n const style = getComputedStyle(node);\n if (style.backgroundImage && style.backgroundImage !== 'none') return null;\n const colour = parseColour(style.backgroundColor);\n if (colour && colour[3] > 0) {\n layers.push(colour);\n if (colour[3] >= 1) break;\n }\n }\n return layers.reverse().reduce<Rgba>((bottom, top) => compositeColour(top, bottom), [255, 255, 255, 1]);\n}\n\n/**\n * Non-text contrast (WCAG 1.4.11) of icon-only controls inside `root`: a link or button with no visible text whose\n * icon is an SVG must reach 3:1 against what is behind it. Returns one line per failure; controls over a photo are\n * counted in `unmeasured`.\n */\nexport function iconContrastProblems(root: Element): { problems: string[]; checked: number; unmeasured: number } {\n const problems: string[] = [];\n let checked = 0;\n let unmeasured = 0;\n const paintOf = (svg: SVGElement): Rgba | null => {\n for (const shape of Array.from(svg.querySelectorAll('path, circle, rect, ellipse, line, polyline, polygon, text, use'))) {\n if (!isRendered(shape)) continue;\n const style = getComputedStyle(shape);\n for (const [paint, opacity] of [[style.fill, style.fillOpacity], [style.stroke, style.strokeOpacity]] as const) {\n if (!paint || paint === 'none' || paint.startsWith('url(')) continue;\n const colour = parseColour(paint);\n const alpha = colour ? colour[3] * Number(opacity || 1) * Number(style.opacity || 1) : 0;\n if (colour && alpha > 0) return [colour[0], colour[1], colour[2], alpha];\n }\n }\n return null;\n };\n for (const control of Array.from(root.querySelectorAll('a[href], button'))) {\n if (!isRendered(control)) continue;\n if (((control as HTMLElement).innerText ?? '').trim()) continue;\n const svg = control.querySelector('svg');\n if (!svg || !isRendered(svg)) continue;\n const paint = paintOf(svg);\n if (!paint) continue;\n const background = backgroundBehind(svg);\n if (!background) {\n unmeasured += 1;\n continue;\n }\n checked += 1;\n const ratio = contrastRatio(compositeColour(paint, background), background);\n if (ratio < 3) problems.push(`${describeElement(control)}: its icon is ${ratio.toFixed(2)}:1 against its background (needs 3:1)`);\n }\n return { problems, checked, unmeasured };\n}\n\n/**\n * The phone call bar: the shared `MobileCallBar`, or any fixed or sticky element along the bottom of the screen that\n * holds a visible telephone link (outside the header and dialogs). `null` when none is on screen.\n */\nexport function findCallBar(): Element | null {\n const tagged = Array.from(document.querySelectorAll('[data-bl=\"call-bar\"], [data-bl=\"callbar\"], [data-bl=\"mobile-call-bar\"]')).find(isRendered);\n if (tagged) return tagged;\n const height = window.innerHeight;\n for (const element of Array.from(document.body.querySelectorAll('*'))) {\n const position = getComputedStyle(element).position;\n if (position !== 'fixed' && position !== 'sticky') continue;\n if (element.closest('header, dialog, [role=\"dialog\"]')) continue;\n const rect = element.getBoundingClientRect();\n if (rect.height <= 0 || rect.bottom < height - 4 || rect.top < height / 2) continue;\n if (!isRendered(element)) continue;\n if (Array.from(element.querySelectorAll('a[href^=\"tel:\"]')).some(isRendered)) return element;\n }\n return null;\n}\n\n/** Visible quote actions in `root`: links or buttons named like the quote action, or the shared quote hooks. */\nexport function quoteActions(root: Element, name: { source: string; flags: string }): Element[] {\n const pattern = new RegExp(name.source, name.flags);\n return Array.from(root.querySelectorAll('a[href], button')).filter((element) => {\n if (!isRendered(element) || element.getAttribute('href')?.startsWith('tel:')) return false;\n if (element.matches('[data-bl=\"quote-button\"], [data-bl-cta^=\"quote\"], [data-lead-cta^=\"quote\"]')) return true;\n return pattern.test(accessibleName(element));\n });\n}\n\n/** The order of the first visible phone link and quote action in `root`. */\nexport function actionOrder(root: Element, name: { source: string; flags: string }): 'phone-first' | 'quote-first' | 'incomplete' {\n const phone = Array.from(root.querySelectorAll('a[href^=\"tel:\"]')).find(isRendered);\n const quote = quoteActions(root, name)[0];\n if (!phone || !quote) return 'incomplete';\n return phone.compareDocumentPosition(quote) & Node.DOCUMENT_POSITION_FOLLOWING ? 'phone-first' : 'quote-first';\n}\n\n/**\n * The hero: the shared hero section, else the smallest block around the page's visible H1 that holds a phone link\n * and a quote action, never above the H1's own section and never `<main>` (without a section, never a block holding\n * an H2). When none holds both, the H1's section (or its parent): its order then reads \"incomplete\".\n */\nexport function heroRegion(name: { source: string; flags: string }): Element | null {\n const heading = Array.from(document.querySelectorAll('h1')).find(isRendered);\n if (!heading) return null;\n const tagged = heading.closest('[data-bl-section=\"hero\"]');\n if (tagged) return tagged;\n const section = heading.closest('section');\n const fallback = section ?? heading.parentElement;\n for (let node = heading.parentElement; node && node !== document.body && node.tagName !== 'MAIN'; node = node.parentElement) {\n if (!section && node.querySelector('h2')) break;\n if (Array.from(node.querySelectorAll('a[href^=\"tel:\"]')).some(isRendered) && quoteActions(node, name).length > 0) return node;\n if (node === section) break;\n }\n return fallback && fallback.tagName !== 'MAIN' ? fallback : heading;\n}\n\n/** A point in the page that is not on an interactive element, a menu or anything in `avoid`. */\nexport function outsidePoint(avoid: Element[]): { x: number; y: number } | null {\n const interactive = 'a[href], button, input, select, textarea, label, summary, details, iframe, video, audio, [role=\"button\"], [role=\"link\"], [role=\"menuitem\"], [role=\"tab\"], [tabindex], [contenteditable=\"\"], [contenteditable=\"true\"]';\n for (let row = 9; row >= 3; row -= 1) {\n for (let column = 1; column <= 9; column += 1) {\n const x = Math.round((window.innerWidth * column) / 10);\n const y = Math.round((window.innerHeight * row) / 10);\n const element = document.elementFromPoint(x, y);\n if (!element || avoid.some((region) => region.contains(element))) continue;\n if (element.closest(interactive) || element.closest('header, nav, dialog, [role=\"dialog\"]')) continue;\n return { x, y };\n }\n }\n return null;\n}\n\n/** Tag an element so Playwright and axe can find it by `[data-brandlab-journey~=\"<name>\"]`. */\nexport function markElement(element: Element, name: string): void {\n const names = new Set((element.getAttribute('data-brandlab-journey') ?? '').split(/\\s+/).filter(Boolean));\n names.add(name);\n element.setAttribute('data-brandlab-journey', [...names].join(' '));\n}\n\n/**\n * Watch one disclosure: when the pointer enters and leaves its item (and panel), and when the panel it controls\n * becomes rendered or hidden, timed with `performance.now()`. Attribute and tree changes are sampled at once; style\n * changes without a DOM change (CSS `:hover`) every animation frame.\n */\nexport function watchDisclosure(trigger: Element, panelId: string): void {\n const item = trigger.closest('li') ?? trigger.parentElement ?? trigger;\n const panel = () => document.getElementById(panelId);\n const inside = (node: EventTarget | null) => node instanceof Node && (item.contains(node) || Boolean(panel()?.contains(node)));\n const state: DisclosureWatch = { enter: null, leave: null, opened: null, closed: null, open: isRendered(panel()) };\n const sample = () => {\n const open = isRendered(panel());\n if (open === state.open) return;\n state.open = open;\n if (open && state.opened === null) state.opened = performance.now();\n if (!open && state.closed === null) state.closed = performance.now();\n };\n const onOver = (event: Event) => {\n if (state.enter === null && inside(event.target)) state.enter = performance.now();\n };\n const onOut = (event: Event) => {\n if (state.leave === null && inside(event.target) && !inside((event as PointerEvent).relatedTarget)) state.leave = performance.now();\n };\n const observer = new MutationObserver(sample);\n observer.observe(document.documentElement, { attributes: true, childList: true, subtree: true });\n let frame = 0;\n const loop = () => {\n sample();\n frame = requestAnimationFrame(loop);\n };\n loop();\n document.addEventListener('pointerover', onOver, true);\n document.addEventListener('pointerout', onOut, true);\n const previous = (window as unknown as { __brandlabSiteSystemWatch?: { stop(): void } }).__brandlabSiteSystemWatch;\n previous?.stop();\n (window as unknown as { __brandlabSiteSystemWatch: unknown }).__brandlabSiteSystemWatch = {\n state,\n stop() {\n observer.disconnect();\n cancelAnimationFrame(frame);\n document.removeEventListener('pointerover', onOver, true);\n document.removeEventListener('pointerout', onOut, true);\n },\n };\n}\n\n/** The current state of `watchDisclosure`'s watch. */\nexport function watchState(): DisclosureWatch | null {\n const watch = (window as unknown as { __brandlabSiteSystemWatch?: { state: DisclosureWatch } }).__brandlabSiteSystemWatch;\n return watch ? { ...watch.state } : null;\n}\n\n/**\n * After a Tab press: is the focused element fully hidden under the sticky header or the call bar? Samples nine points\n * across the visible part of its box; it is hidden when the header or call bar is on top at every one. `repeat` is\n * true once focus comes back to an element it has already visited.\n */\nexport function focusStep(): { done: boolean; repeat: boolean; obscured: string | null; covered: 'header' | 'call bar' | null } {\n const element = document.activeElement;\n const store = window as unknown as { __brandlabSiteSystemFocus?: WeakSet<Element> };\n store.__brandlabSiteSystemFocus ??= new WeakSet<Element>();\n if (!element || element === document.body || element === document.documentElement) return { done: true, repeat: false, obscured: null, covered: null };\n const repeat = store.__brandlabSiteSystemFocus.has(element);\n store.__brandlabSiteSystemFocus.add(element);\n const header = document.querySelector('[data-brandlab-journey~=\"header\"]')\n ?? Array.from(document.querySelectorAll('[data-bl=\"header\"], header')).find((candidate) => isRendered(candidate) && !candidate.closest('main, article, section, aside, footer'))\n ?? null;\n const callBar = findCallBar();\n if (header?.contains(element) || callBar?.contains(element)) return { done: false, repeat, obscured: null, covered: null };\n const rect = element.getBoundingClientRect();\n const left = Math.max(rect.left, 0);\n const right = Math.min(rect.right, window.innerWidth);\n const top = Math.max(rect.top, 0);\n const bottom = Math.min(rect.bottom, window.innerHeight);\n if (right - left < 1 || bottom - top < 1) return { done: false, repeat, obscured: null, covered: null };\n let coveredBy: 'header' | 'call bar' | null = null;\n for (const fx of [0.15, 0.5, 0.85]) {\n for (const fy of [0.15, 0.5, 0.85]) {\n const hit = document.elementFromPoint(left + (right - left) * fx, top + (bottom - top) * fy);\n if (!hit || element.contains(hit)) return { done: false, repeat, obscured: null, covered: null };\n if (header?.contains(hit)) coveredBy ??= 'header';\n else if (callBar?.contains(hit)) coveredBy ??= 'call bar';\n else return { done: false, repeat, obscured: null, covered: null };\n }\n }\n return { done: false, repeat, obscured: describeElement(element), covered: coveredBy };\n}\n\n/**\n * `focusStep` one animation frame after the focus moved (capped at 50 ms, since a background page may not paint), so\n * a sticky bar that hides on its observer's next frame is measured after it moved, not mid-transition.\n */\nexport function focusStepAfterFrame(): Promise<ReturnType<typeof focusStep>> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n resolve(focusStep());\n };\n requestAnimationFrame(() => finish());\n setTimeout(finish, 50);\n });\n}\n\n/** Elements a Tab press can reach, roughly: enough to bound the K5 walk. */\nexport function tabbableCount(): number {\n const selector = 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), summary, iframe, [tabindex]:not([tabindex=\"-1\"])';\n return Array.from(document.querySelectorAll(selector)).filter(isRendered).length;\n}\n\n/** What a K14 block paints: an opaque colour, a photo or gradient (never equal to another block's), or unknown. */\nexport interface PaintedGround {\n description: string;\n /** `rgb(r, g, b)`, `image` or `unknown`. */\n ground: string;\n}\n\n/**\n * The ground a top-level block paints (K14, 3.19.0): its own background image (a photo band or gradient), a photo\n * covering most of it (a fill image), else its background colour composited over what shows through from its\n * ancestors. A transparent block whose one child covers it and paints a colour takes the child's.\n */\nexport function paintedGround(element: Element): string {\n const box = element.getBoundingClientRect();\n const area = box.width * box.height;\n if (area <= 0) return 'unknown';\n if (getComputedStyle(element).backgroundImage !== 'none') return 'image';\n for (const media of Array.from(element.querySelectorAll('img, picture, video'))) {\n const rect = media.getBoundingClientRect();\n if (rect.width * rect.height >= 0.8 * area && isRendered(media)) return 'image';\n }\n let painter: Element = element;\n const own = parseColour(getComputedStyle(element).backgroundColor);\n if (!own || own[3] === 0) {\n const cover = Array.from(element.children).find((child) => {\n const rect = child.getBoundingClientRect();\n const colour = parseColour(getComputedStyle(child).backgroundColor);\n return rect.width * rect.height >= 0.9 * area && colour !== null && colour[3] > 0;\n });\n if (cover) {\n if (getComputedStyle(cover).backgroundImage !== 'none') return 'image';\n painter = cover;\n }\n }\n const colour = backgroundBehind(painter);\n if (!colour) return 'image';\n return `rgb(${colour.slice(0, 3).map((channel) => Math.round(channel)).join(', ')})`;\n}\n\n/**\n * The page's top-level blocks in order (K14): each rendered child of `main` (through a lone wrapper), then what follows\n * `main` up to and including the footer. A `[data-bl-inset]` block is part of the place before it, so it is left out.\n * A `display: contents` wrapper has no box of its own (3.19.1): its rendered children stand in its place, named by\n * the wrapper's section.\n */\nexport function groundBlocks(): PaintedGround[] {\n const main = document.querySelector('main');\n if (!main) return [];\n const skipped = (element: Element) => ['SCRIPT', 'STYLE', 'TEMPLATE', 'NOSCRIPT', 'LINK'].includes(element.tagName)\n || element.hasAttribute('data-bl-inset');\n const named = (element: Element, label: string | null) => label ?? element.getAttribute('data-bl-section') ?? (element.tagName === 'FOOTER' ? 'footer' : null);\n const expand = (elements: readonly Element[], label: string | null = null): { block: Element; section: string | null }[] =>\n elements.flatMap((element) => {\n if (skipped(element)) return [];\n if (getComputedStyle(element).display === 'contents') return expand(Array.from(element.children), named(element, label));\n return isRendered(element) && element.getBoundingClientRect().height >= 8 ? [{ block: element, section: named(element, label) }] : [];\n });\n let blocks = expand(Array.from(main.children));\n while (blocks.length === 1 && expand(Array.from(blocks[0]!.block.children)).length > 1 && paintedGround(blocks[0]!.block).startsWith('rgb') === false) {\n blocks = expand(Array.from(blocks[0]!.block.children));\n }\n const footer = document.querySelector('footer[data-bl=\"footer\"], body footer:not(main footer)');\n for (let node = main.nextElementSibling; node; node = node.nextElementSibling) {\n blocks.push(...expand([node]));\n if (node === footer || node.contains(footer)) break;\n }\n if (footer && !blocks.some(({ block }) => block === footer || block.contains(footer)) && isRendered(footer)) blocks.push({ block: footer, section: 'footer' });\n return blocks.map(({ block, section }) => {\n const description = section ? `\"${section}\"` : `${block.tagName.toLowerCase()}${block.id ? `#${block.id}` : ''}`;\n return { description, ground: paintedGround(block) };\n });\n}\n\n/** Neighbouring blocks that paint the same colour (K14): a photo or an unknown ground never matches. */\nexport function groundProblems(path: string, blocks: readonly PaintedGround[]): string[] {\n const problems: string[] = [];\n const channels = (ground: string) => ground.slice(4, -1).split(',').map(Number);\n for (let index = 1; index < blocks.length; index += 1) {\n const [before, after] = [blocks[index - 1]!, blocks[index]!];\n if (!before.ground.startsWith('rgb') || !after.ground.startsWith('rgb')) continue;\n const [left, right] = [channels(before.ground), channels(after.ground)];\n if (left.every((channel, at) => Math.abs(channel - right[at]!) <= 2)) {\n problems.push(`${path}: ${before.description} and ${after.description} share the background ${after.ground}`);\n }\n }\n return problems;\n}\n\nconst PAGE_HELPERS = {\n isRendered, describeElement, accessibleName, phonePlacement, parseColour, compositeColour, contrastRatio, backgroundBehind,\n iconContrastProblems, findCallBar, quoteActions, actionOrder, heroRegion, outsidePoint, markElement, watchDisclosure,\n watchState, focusStep, focusStepAfterFrame, tabbableCount, paintedGround, groundBlocks, groundProblems,\n};\n\n/** `window.__brandlabSiteSystem` in a page the journeys opened. */\nexport type SiteSystemPageHelpers = typeof PAGE_HELPERS;\n\n/** The init script that defines `window.__brandlabSiteSystem` in every document of the page. */\nexport function pageHelpersSource(): string {\n const names = Object.keys(PAGE_HELPERS);\n return `(() => {\\nconst SITE_SYSTEM_PHONE_PLACEMENTS = ${JSON.stringify(SITE_SYSTEM_PHONE_PLACEMENTS)};\\n${Object.values(PAGE_HELPERS).map((helper) => helper.toString()).join('\\n')}\\nwindow.__brandlabSiteSystem = { ${names.join(', ')} };\\n})();`;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k8-sections.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/k8-sections.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAsE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAClH,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE/E,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,iDAAkD,CAAC;AAEjF,wEAAwE;AACxE,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,mGAAmG;AACnG,eAAO,MAAM,gBAAgB,qCAAsC,CAAC;AAsBpE,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAO5D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"k8-sections.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/k8-sections.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAsE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAClH,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE/E,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,iDAAkD,CAAC;AAEjF,wEAAwE;AACxE,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,mGAAmG;AACnG,eAAO,MAAM,gBAAgB,qCAAsC,CAAC;AAsBpE,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAO5D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,iBAAiB,EAAE,CAkDzE"}
|
|
@@ -42,7 +42,11 @@ export function checkK8(pages) {
|
|
|
42
42
|
sections.forEach((section, index) => {
|
|
43
43
|
const h2 = headings(section, "h2").length;
|
|
44
44
|
const holdsH1 = headings(section, "h1").length > 0;
|
|
45
|
-
|
|
45
|
+
// A guide's article text (3.19.1) is one long read: its H2s are the article's own, any number of them.
|
|
46
|
+
if (sectionId(section) === "article-body") {
|
|
47
|
+
// Only emptiness applies.
|
|
48
|
+
}
|
|
49
|
+
else if (h2 > 1) {
|
|
46
50
|
failures.push(fail("K8", page.path, `The section ${at(index)} on ${page.path} has ${h2} H2 headings; each section has one.`));
|
|
47
51
|
}
|
|
48
52
|
else if (h2 === 0 && !holdsH1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k8-sections.js","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/k8-sections.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"k8-sections.js","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/k8-sections.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * K8: the section contract, page by page (Site System v2 §13.2).\n *\n * Every `data-bl-section` has exactly one H2 (the section that holds the page's H1 may have none), is not empty, and\n * sits in a tone that differs from its neighbours'. A page has at most one `band` tone. A page that opens with a hero\n * (the money pages) shows proof within its first five sections. The emergency band and signature sections sit outside\n * the caps and don't take a place in that window either (3.17.0), so a signature placed early never pushes the proof out.\n */\nimport type { SiteSystemFinding } from \"../../checks.js\";\nimport { fail, notApplicable, plural, resultOf, sectionId, topLevelSections, type ParsedPage } from \"./common.js\";\nimport { attr, descendants, normaliseText, type HtmlElement } from \"./html.js\";\n\n/** The sections that count as proof for the first-five rule. */\nexport const K8_PROOF_SECTIONS = [\"reviews\", \"proof-strip\", \"projects\"] as const;\n\n/** The first sections of a money page are where proof has to appear. */\nexport const K8_PROOF_WITHIN = 5;\n\n/** Uncapped sections that aren't proof: they are skipped when counting the first five (3.17.0). */\nexport const K8_WINDOW_EXEMPT = [\"emergency\", \"signature\"] as const;\n\n/** Elements that are content on their own, without any text. */\nconst CONTENT_TAGS = new Set([\"img\", \"picture\", \"video\", \"audio\", \"iframe\", \"canvas\", \"input\", \"textarea\", \"select\", \"button\", \"table\"]);\n\nfunction headings(section: HtmlElement, tag: string): HtmlElement[] {\n return descendants(section).filter((element) => element.tag === tag);\n}\n\n/** The text of a section outside its headings. */\nfunction bodyText(element: HtmlElement): string {\n let text = \"\";\n for (const child of element.children) {\n if (child.type === \"text\") {\n text += child.text;\n } else if (!/^h[1-6]$/.test(child.tag) && ![\"script\", \"style\", \"template\"].includes(child.tag)) {\n text += ` ${bodyText(child)} `;\n }\n }\n return text;\n}\n\nexport function isEmptySection(section: HtmlElement): boolean {\n if (normaliseText(bodyText(section)) !== \"\") return false;\n return !descendants(section).some(\n (element) =>\n CONTENT_TAGS.has(element.tag) ||\n (element.tag === \"svg\" && (attr(element, \"role\") === \"img\" || attr(element, \"aria-label\") !== undefined)),\n );\n}\n\nexport function checkK8(pages: readonly ParsedPage[]): SiteSystemFinding[] {\n const failures: SiteSystemFinding[] = [];\n let checked = 0;\n for (const page of pages) {\n const sections = topLevelSections(page.root);\n if (sections.length === 0) continue;\n checked += 1;\n const at = (index: number) => `\"${sectionId(sections[index]!)}\" (section ${index + 1})`;\n\n sections.forEach((section, index) => {\n const h2 = headings(section, \"h2\").length;\n const holdsH1 = headings(section, \"h1\").length > 0;\n // A guide's article text (3.19.1) is one long read: its H2s are the article's own, any number of them.\n if (sectionId(section) === \"article-body\") {\n // Only emptiness applies.\n } else if (h2 > 1) {\n failures.push(fail(\"K8\", page.path, `The section ${at(index)} on ${page.path} has ${h2} H2 headings; each section has one.`));\n } else if (h2 === 0 && !holdsH1) {\n failures.push(fail(\"K8\", page.path, `The section ${at(index)} on ${page.path} has no H2 heading; each section has one.`));\n }\n if (isEmptySection(section)) {\n failures.push(fail(\"K8\", page.path, `The section ${at(index)} on ${page.path} is empty; a section with nothing to show is left out.`));\n }\n });\n\n const bands = sections.filter((section) => attr(section, \"data-tone\") === \"band\");\n if (bands.length > 1) {\n failures.push(fail(\"K8\", page.path, `${page.path} has ${bands.length} sections in the band tone; a page has at most one.`));\n }\n for (let index = 1; index < sections.length; index += 1) {\n const previous = attr(sections[index - 1]!, \"data-tone\");\n const tone = attr(sections[index]!, \"data-tone\");\n if (tone !== undefined && tone === previous) {\n failures.push(fail(\"K8\", page.path, `The sections ${at(index - 1)} and ${at(index)} on ${page.path} are both in the ${tone} tone; neighbours differ.`));\n }\n }\n\n const opensWithHero = sections.some((section) => sectionId(section) === \"hero\");\n if (opensWithHero) {\n const firstFive = sections\n .map(sectionId)\n .filter((id) => !(K8_WINDOW_EXEMPT as readonly (string | undefined)[]).includes(id))\n .slice(0, K8_PROOF_WITHIN);\n if (!firstFive.some((id) => (K8_PROOF_SECTIONS as readonly string[]).includes(id))) {\n failures.push(fail(\"K8\", page.path, `${page.path} shows no proof (${K8_PROOF_SECTIONS.join(\", \")}) in its first ${K8_PROOF_WITHIN} sections.`));\n }\n }\n }\n if (checked === 0) return [notApplicable(\"K8\", \"None of the sampled pages has a data-bl-section.\")];\n return resultOf(\"K8\", failures, `Checked ${plural(checked, \"page\")}: each follows the section contract.`);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k12-slots.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/full/k12-slots.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAiD,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAG9F,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"k12-slots.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/full/k12-slots.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAiD,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAG9F,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,iBAAiB,EAAE,CAgCvE"}
|
|
@@ -24,6 +24,9 @@ export function checkK12Slots(context) {
|
|
|
24
24
|
const found = page.slots?.get(section);
|
|
25
25
|
if (found?.present.includes(slot))
|
|
26
26
|
continue;
|
|
27
|
+
// The about page's credential lines may sit in its Licences ledger instead of the owner block (3.19.1).
|
|
28
|
+
if (section === "about-owner" && page.slots?.get("licences")?.present.includes(slot))
|
|
29
|
+
continue;
|
|
27
30
|
const skip = found?.skipped.find((entry) => entry.slot === slot);
|
|
28
31
|
if (skip && isDataBackedReason(skip.reason)) {
|
|
29
32
|
failures.push(warning("K12-slots", page.path, `${page.path} leaves the ${slot} line out of its "${section}" section (${skip.reason}); bring the record up to date so it shows again.`));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k12-slots.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/k12-slots.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,oBAAoB,EAA+C,MAAM,2CAA2C,CAAC;AAE9H,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAoB,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,aAAa,CAAC,OAAoB;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAkC,CAAC;IAClE,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,SAAS;QAC3B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAA4B,EAAE,KAAK,CAAC,CAAC;QAChF,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,QAAQ,EAAE,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YAC/C,OAAO,IAAI,CAAC,CAAC;YACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5C,MAAM,IAAI,GAAG,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YACjE,IAAI,IAAI,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,eAAe,IAAI,qBAAqB,OAAO,cAAc,IAAI,CAAC,MAAM,mDAAmD,CAAC,CAAC,CAAC;gBACxL,SAAS;YACX,CAAC;YACD,QAAQ,CAAC,IAAI,CACX,IAAI,CACF,WAAW,EACX,IAAI,CAAC,IAAI,EACT,GAAG,IAAI,CAAC,IAAI,aAAa,OAAO,iBAAiB,IAAI,aAAa,KAAK,sBAAsB,IAAI,CAAC,MAAM,4CAA4C,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CACpL,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,iEAAiE,CAAC,CAAC,CAAC,mFAAmF,CAAC,CAAC,CAAC;IACnN,CAAC;IACD,OAAO,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,qBAAqB,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC;AAC/H,CAAC","sourcesContent":["/**\n * K12-slots (3.14.0): the lines a trade requires inside a section (site-core `SECTION_TRADE_PROFILES`, matrix part\n * B), such as the tree trade's council permit note in `LocalFacts` on suburb and service-in-suburb pages. The trade is\n * the one `defineSectionOrder` names in strategy.ts. Wherever the section renders, it carries the slot\n * (`data-bl-slot=\"permit\"`), or lists it in `data-bl-slot-skip` with a reason drawn from its data\n * (`permit:no-current-council-record`), which passes with a warning so the record gets re-checked. A section that\n * does not render is K12's business.\n */\nimport { requiredSectionSlots, type BrandlabPageFamily, type BrandlabTrade } from \"@brandlab-digital/site-core/section-order\";\nimport type { SiteSystemFinding } from \"../../checks.js\";\nimport { fail, notApplicable, outcome, plural, warning, type FullContext } from \"./common.js\";\nimport { isDataBackedReason } from \"./k12-manifests.js\";\n\nexport function checkK12Slots(context: FullContext): SiteSystemFinding[] {\n const trade = context.strategy.trade as BrandlabTrade | undefined;\n const failures: SiteSystemFinding[] = [];\n let checked = 0;\n for (const page of context.estate.pages) {\n if (!page.family) continue;\n const required = requiredSectionSlots(page.family as BrandlabPageFamily, trade);\n for (const { section, slot } of required) {\n if (!page.sections.includes(section)) continue;\n checked += 1;\n const found = page.slots?.get(section);\n if (found?.present.includes(slot)) continue;\n const skip = found?.skipped.find((entry) => entry.slot === slot);\n if (skip && isDataBackedReason(skip.reason)) {\n failures.push(warning(\"K12-slots\", page.path, `${page.path} leaves the ${slot} line out of its \"${section}\" section (${skip.reason}); bring the record up to date so it shows again.`));\n continue;\n }\n failures.push(\n fail(\n \"K12-slots\",\n page.path,\n `${page.path} renders \"${section}\" without the ${slot} line the ${trade} trade requires on ${page.family} pages, and gives no data-backed reason (${skip ? skip.reason : \"none\"}).`,\n ),\n );\n }\n }\n if (checked === 0) {\n return [notApplicable(\"K12-slots\", trade ? `The ${trade} trade requires no line inside the sections these pages render.` : \"strategy.ts names no trade in defineSectionOrder, so no trade lines are required.\")];\n }\n return outcome(\"K12-slots\", failures, `${plural(checked, \"required trade line\")} ${checked === 1 ? \"is\" : \"are\"} in place.`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"k12-slots.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/k12-slots.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,oBAAoB,EAA+C,MAAM,2CAA2C,CAAC;AAE9H,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAoB,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,aAAa,CAAC,OAAoB;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAkC,CAAC;IAClE,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,SAAS;QAC3B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAA4B,EAAE,KAAK,CAAC,CAAC;QAChF,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,QAAQ,EAAE,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YAC/C,OAAO,IAAI,CAAC,CAAC;YACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5C,wGAAwG;YACxG,IAAI,OAAO,KAAK,aAAa,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC/F,MAAM,IAAI,GAAG,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YACjE,IAAI,IAAI,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,eAAe,IAAI,qBAAqB,OAAO,cAAc,IAAI,CAAC,MAAM,mDAAmD,CAAC,CAAC,CAAC;gBACxL,SAAS;YACX,CAAC;YACD,QAAQ,CAAC,IAAI,CACX,IAAI,CACF,WAAW,EACX,IAAI,CAAC,IAAI,EACT,GAAG,IAAI,CAAC,IAAI,aAAa,OAAO,iBAAiB,IAAI,aAAa,KAAK,sBAAsB,IAAI,CAAC,MAAM,4CAA4C,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CACpL,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,iEAAiE,CAAC,CAAC,CAAC,mFAAmF,CAAC,CAAC,CAAC;IACnN,CAAC;IACD,OAAO,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,qBAAqB,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC;AAC/H,CAAC","sourcesContent":["/**\n * K12-slots (3.14.0): the lines a trade requires inside a section (site-core `SECTION_TRADE_PROFILES`, matrix part\n * B), such as the tree trade's council permit note in `LocalFacts` on suburb and service-in-suburb pages. The trade is\n * the one `defineSectionOrder` names in strategy.ts. Wherever the section renders, it carries the slot\n * (`data-bl-slot=\"permit\"`), or lists it in `data-bl-slot-skip` with a reason drawn from its data\n * (`permit:no-current-council-record`), which passes with a warning so the record gets re-checked. A section that\n * does not render is K12's business.\n */\nimport { requiredSectionSlots, type BrandlabPageFamily, type BrandlabTrade } from \"@brandlab-digital/site-core/section-order\";\nimport type { SiteSystemFinding } from \"../../checks.js\";\nimport { fail, notApplicable, outcome, plural, warning, type FullContext } from \"./common.js\";\nimport { isDataBackedReason } from \"./k12-manifests.js\";\n\nexport function checkK12Slots(context: FullContext): SiteSystemFinding[] {\n const trade = context.strategy.trade as BrandlabTrade | undefined;\n const failures: SiteSystemFinding[] = [];\n let checked = 0;\n for (const page of context.estate.pages) {\n if (!page.family) continue;\n const required = requiredSectionSlots(page.family as BrandlabPageFamily, trade);\n for (const { section, slot } of required) {\n if (!page.sections.includes(section)) continue;\n checked += 1;\n const found = page.slots?.get(section);\n if (found?.present.includes(slot)) continue;\n // The about page's credential lines may sit in its Licences ledger instead of the owner block (3.19.1).\n if (section === \"about-owner\" && page.slots?.get(\"licences\")?.present.includes(slot)) continue;\n const skip = found?.skipped.find((entry) => entry.slot === slot);\n if (skip && isDataBackedReason(skip.reason)) {\n failures.push(warning(\"K12-slots\", page.path, `${page.path} leaves the ${slot} line out of its \"${section}\" section (${skip.reason}); bring the record up to date so it shows again.`));\n continue;\n }\n failures.push(\n fail(\n \"K12-slots\",\n page.path,\n `${page.path} renders \"${section}\" without the ${slot} line the ${trade} trade requires on ${page.family} pages, and gives no data-backed reason (${skip ? skip.reason : \"none\"}).`,\n ),\n );\n }\n }\n if (checked === 0) {\n return [notApplicable(\"K12-slots\", trade ? `The ${trade} trade requires no line inside the sections these pages render.` : \"strategy.ts names no trade in defineSectionOrder, so no trade lines are required.\")];\n }\n return outcome(\"K12-slots\", failures, `${plural(checked, \"required trade line\")} ${checked === 1 ? \"is\" : \"are\"} in place.`);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k11-density.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/sections/k11-density.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAA4D,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACjH,OAAO,EAA6B,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjF,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAmBzC,mFAAmF;AACnF,wBAAgB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,EAAE,CAW3D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,EAAE,CAgBnE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"k11-density.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/sections/k11-density.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAA4D,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACjH,OAAO,EAA6B,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjF,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAmBzC,mFAAmF;AACnF,wBAAgB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,EAAE,CAW3D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,EAAE,CAgBnE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,iBAAiB,EAAE,CAsB1E"}
|
|
@@ -68,10 +68,12 @@ export function checkK11(pages) {
|
|
|
68
68
|
measured += 1;
|
|
69
69
|
for (const section of sections) {
|
|
70
70
|
const id = sectionId(section);
|
|
71
|
+
// A guide's article text is one long read with its own H2s and lists (3.19.1); only its calls to action count.
|
|
72
|
+
const article = id === "article-body";
|
|
71
73
|
const h2 = descendants(section).filter((element) => element.tag === "h2").length;
|
|
72
|
-
if (h2 > 1)
|
|
74
|
+
if (h2 > 1 && !article)
|
|
73
75
|
problems.add(page.path, `The "${id}" section has ${h2} H2 headings; a section has one`);
|
|
74
|
-
const cards = cardsIn(section).length;
|
|
76
|
+
const cards = article ? 0 : cardsIn(section).length;
|
|
75
77
|
if (cards > K11_MAX_CARDS)
|
|
76
78
|
problems.add(page.path, `The "${id}" section shows ${cards} cards; a section shows at most ${K11_MAX_CARDS}`);
|
|
77
79
|
const calls = callsToActionIn(section).length;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k11-density.js","sourceRoot":"","sources":["../../../../src/site-system/rules/sections/k11-density.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"k11-density.js","sourceRoot":"","sources":["../../../../src/site-system/rules/sections/k11-density.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * K11: section density (Site System v2 §13.2). A section does one thing: one H2, at most 8 cards and at most 2 calls to\n * action. The rule measures what the server HTML shows. The spec also asks for body text no wider than about 75\n * characters a line and section padding of at least the token value; those are CSS, which the HTML cannot show, so\n * they stay with the contrast and spacing journeys and this rule says so rather than guessing.\n *\n * A card is one repeated unit with its own heading, image or quotation: an element with a card slot (`card`, `review`,\n * `project`, `service`, `tile`, `post`, `teaser`), an `<article>`, a card class, or a list item that holds a heading, an\n * image, a `<blockquote>` or a link with a sentence of its own. A call to action is a quote button, a call button, or the\n * submit button of a form; an inline text phone link is a contact detail, not a call to action. A hero that holds the\n * form also carries a quote button that scrolls to it (so the quote action is in the first screen on a phone); that\n * button and the form's submit button are one action.\n */\nimport type { SiteSystemFinding } from \"../../checks.js\";\nimport { notApplicable, pass, plural, sectionId, topLevelSections, type ParsedPage } from \"../enquiry/common.js\";\nimport { attr, descendants, textOf, type HtmlElement } from \"../enquiry/html.js\";\nimport { PageProblems } from \"../library/common.js\";\n\nexport const K11_MAX_CARDS = 8;\nexport const K11_MAX_CALLS_TO_ACTION = 2;\n\nconst CARD_SLOTS = new Set([\"card\", \"review\", \"project\", \"service\", \"tile\", \"post\", \"teaser\", \"testimonial\"]);\nconst SENTENCE_WORDS = 8;\n\nfunction words(element: HtmlElement): number {\n return textOf(element).split(/\\s+/).filter(Boolean).length;\n}\n\nfunction isCardLike(element: HtmlElement): boolean {\n if (element.tag === \"article\") return true;\n if (CARD_SLOTS.has(attr(element, \"data-slot\") ?? \"\")) return true;\n if (/(?:^|[\\s_-])card(?:[\\s_-]|$)/i.test(attr(element, \"class\") ?? \"\")) return true;\n if (element.tag !== \"li\") return false;\n const inside = descendants(element);\n if (inside.some((child) => /^h[2-6]$/.test(child.tag) || child.tag === \"img\" || child.tag === \"blockquote\" || attr(child, \"data-slot\") === \"quote\")) return true;\n return inside.some((child) => child.tag === \"a\") && words(element) >= SENTENCE_WORDS;\n}\n\n/** The cards in a section: the outermost card-like elements, each counted once. */\nexport function cardsIn(section: HtmlElement): HtmlElement[] {\n const cards: HtmlElement[] = [];\n const visit = (node: HtmlElement) => {\n for (const child of node.children) {\n if (child.type !== \"element\") continue;\n if (isCardLike(child)) cards.push(child);\n else visit(child);\n }\n };\n visit(section);\n return cards;\n}\n\nexport function callsToActionIn(section: HtmlElement): HtmlElement[] {\n const inside = descendants(section);\n const submits = inside.filter((element) => element.tag === \"button\" && (attr(element, \"type\") ?? \"submit\").toLowerCase() === \"submit\");\n const calls = new Set<HtmlElement>();\n for (const element of inside) {\n const hook = attr(element, \"data-bl\");\n const quote = hook === \"quote-button\" || attr(element, \"data-bl-cta\") !== undefined;\n // A quote button that jumps to the form beside it is the same action as the form's submit button, not a third.\n if (quote) {\n if (submits.length === 0 || !(attr(element, \"href\") ?? \"\").includes(\"#\")) calls.add(element);\n } else if (hook === \"phone-link\" && ![\"text\", \"inline\"].includes(attr(element, \"data-variant\") ?? \"\")) {\n calls.add(element);\n }\n }\n for (const submit of submits) calls.add(submit);\n return [...calls];\n}\n\nexport function checkK11(pages: readonly ParsedPage[]): SiteSystemFinding[] {\n const problems = new PageProblems();\n let measured = 0;\n for (const page of pages) {\n const sections = topLevelSections(page.root);\n if (sections.length === 0) continue;\n measured += 1;\n for (const section of sections) {\n const id = sectionId(section);\n // A guide's article text is one long read with its own H2s and lists (3.19.1); only its calls to action count.\n const article = id === \"article-body\";\n const h2 = descendants(section).filter((element) => element.tag === \"h2\").length;\n if (h2 > 1 && !article) problems.add(page.path, `The \"${id}\" section has ${h2} H2 headings; a section has one`);\n const cards = article ? 0 : cardsIn(section).length;\n if (cards > K11_MAX_CARDS) problems.add(page.path, `The \"${id}\" section shows ${cards} cards; a section shows at most ${K11_MAX_CARDS}`);\n const calls = callsToActionIn(section).length;\n if (calls > K11_MAX_CALLS_TO_ACTION) problems.add(page.path, `The \"${id}\" section has ${calls} calls to action; a section has at most ${K11_MAX_CALLS_TO_ACTION}`);\n }\n }\n if (measured === 0) return [notApplicable(\"K11\", \"None of the sampled pages has a data-bl-section.\")];\n if (problems.size > 0) return problems.findings(\"K11\");\n return [pass(\"K11\", `Checked the sections of ${plural(measured, \"page\")}: none has more than one H2, ${K11_MAX_CARDS} cards or ${K11_MAX_CALLS_TO_ACTION} calls to action (line length and section padding are CSS, checked in the browser).`)];\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brandlab-digital/conformance",
|
|
3
|
-
"version": "3.19.
|
|
3
|
+
"version": "3.19.1",
|
|
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.19.
|
|
32
|
+
"@brandlab-digital/site-core": "3.19.1",
|
|
33
33
|
"typescript": "6.0.3"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|