@brandlab-digital/conformance 3.7.0 → 3.9.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 +26 -0
- package/dist/current-release.js +5 -5
- package/dist/current-release.js.map +1 -1
- package/dist/engineering.js +4 -2
- package/dist/engineering.js.map +1 -1
- package/dist/public-copy.d.ts +7 -0
- package/dist/public-copy.d.ts.map +1 -1
- package/dist/public-copy.js +8 -3
- package/dist/public-copy.js.map +1 -1
- package/dist/ready-cli.d.ts +38 -0
- package/dist/ready-cli.d.ts.map +1 -0
- package/dist/ready-cli.js +327 -0
- package/dist/ready-cli.js.map +1 -0
- package/dist/site-system/checks.d.ts +389 -0
- package/dist/site-system/checks.d.ts.map +1 -0
- package/dist/site-system/checks.js +96 -0
- package/dist/site-system/checks.js.map +1 -0
- package/dist/site-system/config.d.ts +40 -0
- package/dist/site-system/config.d.ts.map +1 -0
- package/dist/site-system/config.js +214 -0
- package/dist/site-system/config.js.map +1 -0
- package/dist/site-system/index.d.ts +14 -0
- package/dist/site-system/index.d.ts.map +1 -0
- package/dist/site-system/index.js +14 -0
- package/dist/site-system/index.js.map +1 -0
- package/dist/site-system/journeys/access.d.ts +7 -0
- package/dist/site-system/journeys/access.d.ts.map +1 -0
- package/dist/site-system/journeys/access.js +263 -0
- package/dist/site-system/journeys/access.js.map +1 -0
- package/dist/site-system/journeys/browser.d.ts +79 -0
- package/dist/site-system/journeys/browser.d.ts.map +1 -0
- package/dist/site-system/journeys/browser.js +218 -0
- package/dist/site-system/journeys/browser.js.map +1 -0
- package/dist/site-system/journeys/conversion.d.ts +3 -0
- package/dist/site-system/journeys/conversion.d.ts.map +1 -0
- package/dist/site-system/journeys/conversion.js +152 -0
- package/dist/site-system/journeys/conversion.js.map +1 -0
- package/dist/site-system/journeys/menu.d.ts +11 -0
- package/dist/site-system/journeys/menu.d.ts.map +1 -0
- package/dist/site-system/journeys/menu.js +395 -0
- package/dist/site-system/journeys/menu.js.map +1 -0
- package/dist/site-system/journeys/page-helpers.d.ts +146 -0
- package/dist/site-system/journeys/page-helpers.d.ts.map +1 -0
- package/dist/site-system/journeys/page-helpers.js +426 -0
- package/dist/site-system/journeys/page-helpers.js.map +1 -0
- package/dist/site-system/journeys/plan.d.ts +82 -0
- package/dist/site-system/journeys/plan.d.ts.map +1 -0
- package/dist/site-system/journeys/plan.js +112 -0
- package/dist/site-system/journeys/plan.js.map +1 -0
- package/dist/site-system/journeys/shell.d.ts +24 -0
- package/dist/site-system/journeys/shell.d.ts.map +1 -0
- package/dist/site-system/journeys/shell.js +269 -0
- package/dist/site-system/journeys/shell.js.map +1 -0
- package/dist/site-system/playwright-report.d.ts +22 -0
- package/dist/site-system/playwright-report.d.ts.map +1 -0
- package/dist/site-system/playwright-report.js +131 -0
- package/dist/site-system/playwright-report.js.map +1 -0
- package/dist/site-system/records.d.ts +30 -0
- package/dist/site-system/records.d.ts.map +1 -0
- package/dist/site-system/records.js +98 -0
- package/dist/site-system/records.js.map +1 -0
- package/dist/site-system/report.d.ts +116 -0
- package/dist/site-system/report.d.ts.map +1 -0
- package/dist/site-system/report.js +366 -0
- package/dist/site-system/report.js.map +1 -0
- package/dist/site-system/rule-modules.d.ts +8 -0
- package/dist/site-system/rule-modules.d.ts.map +1 -0
- package/dist/site-system/rule-modules.js +33 -0
- package/dist/site-system/rule-modules.js.map +1 -0
- package/dist/site-system/rules/design/d4-distinctness.d.ts +36 -0
- package/dist/site-system/rules/design/d4-distinctness.d.ts.map +1 -0
- package/dist/site-system/rules/design/d4-distinctness.js +207 -0
- package/dist/site-system/rules/design/d4-distinctness.js.map +1 -0
- package/dist/site-system/rules/design/index.d.ts +17 -0
- package/dist/site-system/rules/design/index.d.ts.map +1 -0
- package/dist/site-system/rules/design/index.js +7 -0
- package/dist/site-system/rules/design/index.js.map +1 -0
- package/dist/site-system/rules/enquiry/c2-quote-form.d.ts +31 -0
- package/dist/site-system/rules/enquiry/c2-quote-form.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/c2-quote-form.js +211 -0
- package/dist/site-system/rules/enquiry/c2-quote-form.js.map +1 -0
- package/dist/site-system/rules/enquiry/common.d.ts +37 -0
- package/dist/site-system/rules/enquiry/common.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/common.js +59 -0
- package/dist/site-system/rules/enquiry/common.js.map +1 -0
- package/dist/site-system/rules/enquiry/e1-recorded-titles.d.ts +8 -0
- package/dist/site-system/rules/enquiry/e1-recorded-titles.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/e1-recorded-titles.js +59 -0
- package/dist/site-system/rules/enquiry/e1-recorded-titles.js.map +1 -0
- package/dist/site-system/rules/enquiry/e9-cost-guides.d.ts +22 -0
- package/dist/site-system/rules/enquiry/e9-cost-guides.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/e9-cost-guides.js +55 -0
- package/dist/site-system/rules/enquiry/e9-cost-guides.js.map +1 -0
- package/dist/site-system/rules/enquiry/html.d.ts +53 -0
- package/dist/site-system/rules/enquiry/html.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/html.js +294 -0
- package/dist/site-system/rules/enquiry/html.js.map +1 -0
- package/dist/site-system/rules/enquiry/index.d.ts +17 -0
- package/dist/site-system/rules/enquiry/index.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/index.js +26 -0
- package/dist/site-system/rules/enquiry/index.js.map +1 -0
- package/dist/site-system/rules/enquiry/k8-sections.d.ts +17 -0
- package/dist/site-system/rules/enquiry/k8-sections.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/k8-sections.js +76 -0
- package/dist/site-system/rules/enquiry/k8-sections.js.map +1 -0
- package/dist/site-system/rules/enquiry/literal.d.ts +29 -0
- package/dist/site-system/rules/enquiry/literal.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/literal.js +189 -0
- package/dist/site-system/rules/enquiry/literal.js.map +1 -0
- package/dist/site-system/rules/enquiry/t11-licence-classes.d.ts +73 -0
- package/dist/site-system/rules/enquiry/t11-licence-classes.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/t11-licence-classes.js +275 -0
- package/dist/site-system/rules/enquiry/t11-licence-classes.js.map +1 -0
- package/dist/site-system/rules/enquiry/t5-reviews.d.ts +23 -0
- package/dist/site-system/rules/enquiry/t5-reviews.d.ts.map +1 -0
- package/dist/site-system/rules/enquiry/t5-reviews.js +91 -0
- package/dist/site-system/rules/enquiry/t5-reviews.js.map +1 -0
- package/dist/site-system/rules/form/c11-contact-route.d.ts +5 -0
- package/dist/site-system/rules/form/c11-contact-route.d.ts.map +1 -0
- package/dist/site-system/rules/form/c11-contact-route.js +132 -0
- package/dist/site-system/rules/form/c11-contact-route.js.map +1 -0
- package/dist/site-system/rules/form/c7-thank-you.d.ts +20 -0
- package/dist/site-system/rules/form/c7-thank-you.d.ts.map +1 -0
- package/dist/site-system/rules/form/c7-thank-you.js +67 -0
- package/dist/site-system/rules/form/c7-thank-you.js.map +1 -0
- package/dist/site-system/rules/form/c8-forgiving-form.d.ts +19 -0
- package/dist/site-system/rules/form/c8-forgiving-form.d.ts.map +1 -0
- package/dist/site-system/rules/form/c8-forgiving-form.js +128 -0
- package/dist/site-system/rules/form/c8-forgiving-form.js.map +1 -0
- package/dist/site-system/rules/form/index.d.ts +14 -0
- package/dist/site-system/rules/form/index.d.ts.map +1 -0
- package/dist/site-system/rules/form/index.js +13 -0
- package/dist/site-system/rules/form/index.js.map +1 -0
- package/dist/site-system/rules/library/common.d.ts +36 -0
- package/dist/site-system/rules/library/common.d.ts.map +1 -0
- package/dist/site-system/rules/library/common.js +70 -0
- package/dist/site-system/rules/library/common.js.map +1 -0
- package/dist/site-system/rules/library/index.d.ts +16 -0
- package/dist/site-system/rules/library/index.d.ts.map +1 -0
- package/dist/site-system/rules/library/index.js +19 -0
- package/dist/site-system/rules/library/index.js.map +1 -0
- package/dist/site-system/rules/library/k1-shared-components.d.ts +29 -0
- package/dist/site-system/rules/library/k1-shared-components.d.ts.map +1 -0
- package/dist/site-system/rules/library/k1-shared-components.js +97 -0
- package/dist/site-system/rules/library/k1-shared-components.js.map +1 -0
- package/dist/site-system/rules/navigation/extract.d.ts +50 -0
- package/dist/site-system/rules/navigation/extract.d.ts.map +1 -0
- package/dist/site-system/rules/navigation/extract.js +220 -0
- package/dist/site-system/rules/navigation/extract.js.map +1 -0
- package/dist/site-system/rules/navigation/html.d.ts +23 -0
- package/dist/site-system/rules/navigation/html.d.ts.map +1 -0
- package/dist/site-system/rules/navigation/html.js +219 -0
- package/dist/site-system/rules/navigation/html.js.map +1 -0
- package/dist/site-system/rules/navigation/index.d.ts +37 -0
- package/dist/site-system/rules/navigation/index.d.ts.map +1 -0
- package/dist/site-system/rules/navigation/index.js +163 -0
- package/dist/site-system/rules/navigation/index.js.map +1 -0
- package/dist/site-system/rules/navigation/record.d.ts +8 -0
- package/dist/site-system/rules/navigation/record.d.ts.map +1 -0
- package/dist/site-system/rules/navigation/record.js +39 -0
- package/dist/site-system/rules/navigation/record.js.map +1 -0
- package/dist/site-system/rules/sections/exif.d.ts +22 -0
- package/dist/site-system/rules/sections/exif.d.ts.map +1 -0
- package/dist/site-system/rules/sections/exif.js +218 -0
- package/dist/site-system/rules/sections/exif.js.map +1 -0
- package/dist/site-system/rules/sections/images.d.ts +31 -0
- package/dist/site-system/rules/sections/images.d.ts.map +1 -0
- package/dist/site-system/rules/sections/images.js +96 -0
- package/dist/site-system/rules/sections/images.js.map +1 -0
- package/dist/site-system/rules/sections/index.d.ts +20 -0
- package/dist/site-system/rules/sections/index.d.ts.map +1 -0
- package/dist/site-system/rules/sections/index.js +34 -0
- package/dist/site-system/rules/sections/index.js.map +1 -0
- package/dist/site-system/rules/sections/k11-density.d.ts +23 -0
- package/dist/site-system/rules/sections/k11-density.d.ts.map +1 -0
- package/dist/site-system/rules/sections/k11-density.js +88 -0
- package/dist/site-system/rules/sections/k11-density.js.map +1 -0
- package/dist/site-system/rules/sections/k12-contact.d.ts +13 -0
- package/dist/site-system/rules/sections/k12-contact.d.ts.map +1 -0
- package/dist/site-system/rules/sections/k12-contact.js +70 -0
- package/dist/site-system/rules/sections/k12-contact.js.map +1 -0
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts +11 -0
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts.map +1 -0
- package/dist/site-system/rules/sections/k2-skin-coverage.js +126 -0
- package/dist/site-system/rules/sections/k2-skin-coverage.js.map +1 -0
- package/dist/site-system/rules/sections/n9-footer.d.ts +40 -0
- package/dist/site-system/rules/sections/n9-footer.d.ts.map +1 -0
- package/dist/site-system/rules/sections/n9-footer.js +186 -0
- package/dist/site-system/rules/sections/n9-footer.js.map +1 -0
- package/dist/site-system/rules/sections/t6-media-entries.d.ts +14 -0
- package/dist/site-system/rules/sections/t6-media-entries.d.ts.map +1 -0
- package/dist/site-system/rules/sections/t6-media-entries.js +96 -0
- package/dist/site-system/rules/sections/t6-media-entries.js.map +1 -0
- package/dist/site-system/rules/sections/t7-main-images.d.ts +13 -0
- package/dist/site-system/rules/sections/t7-main-images.d.ts.map +1 -0
- package/dist/site-system/rules/sections/t7-main-images.js +41 -0
- package/dist/site-system/rules/sections/t7-main-images.js.map +1 -0
- package/dist/site-system/rules/sections/t8-prices.d.ts +13 -0
- package/dist/site-system/rules/sections/t8-prices.d.ts.map +1 -0
- package/dist/site-system/rules/sections/t8-prices.js +92 -0
- package/dist/site-system/rules/sections/t8-prices.js.map +1 -0
- package/dist/site-system/rules/sections/t9-location-metadata.d.ts +3 -0
- package/dist/site-system/rules/sections/t9-location-metadata.d.ts.map +1 -0
- package/dist/site-system/rules/sections/t9-location-metadata.js +54 -0
- package/dist/site-system/rules/sections/t9-location-metadata.js.map +1 -0
- package/dist/site-system/rules/shell/banned-wording.d.ts +24 -0
- package/dist/site-system/rules/shell/banned-wording.d.ts.map +1 -0
- package/dist/site-system/rules/shell/banned-wording.js +212 -0
- package/dist/site-system/rules/shell/banned-wording.js.map +1 -0
- package/dist/site-system/rules/shell/budgets.d.ts +43 -0
- package/dist/site-system/rules/shell/budgets.d.ts.map +1 -0
- package/dist/site-system/rules/shell/budgets.js +297 -0
- package/dist/site-system/rules/shell/budgets.js.map +1 -0
- package/dist/site-system/rules/shell/cta-labels.d.ts +17 -0
- package/dist/site-system/rules/shell/cta-labels.d.ts.map +1 -0
- package/dist/site-system/rules/shell/cta-labels.js +86 -0
- package/dist/site-system/rules/shell/cta-labels.js.map +1 -0
- package/dist/site-system/rules/shell/facts.d.ts +33 -0
- package/dist/site-system/rules/shell/facts.d.ts.map +1 -0
- package/dist/site-system/rules/shell/facts.js +217 -0
- package/dist/site-system/rules/shell/facts.js.map +1 -0
- package/dist/site-system/rules/shell/headings.d.ts +5 -0
- package/dist/site-system/rules/shell/headings.d.ts.map +1 -0
- package/dist/site-system/rules/shell/headings.js +23 -0
- package/dist/site-system/rules/shell/headings.js.map +1 -0
- package/dist/site-system/rules/shell/hero-location.d.ts +4 -0
- package/dist/site-system/rules/shell/hero-location.d.ts.map +1 -0
- package/dist/site-system/rules/shell/hero-location.js +45 -0
- package/dist/site-system/rules/shell/hero-location.js.map +1 -0
- package/dist/site-system/rules/shell/html.d.ts +53 -0
- package/dist/site-system/rules/shell/html.d.ts.map +1 -0
- package/dist/site-system/rules/shell/html.js +341 -0
- package/dist/site-system/rules/shell/html.js.map +1 -0
- package/dist/site-system/rules/shell/index.d.ts +18 -0
- package/dist/site-system/rules/shell/index.d.ts.map +1 -0
- package/dist/site-system/rules/shell/index.js +65 -0
- package/dist/site-system/rules/shell/index.js.map +1 -0
- package/dist/site-system/rules/shell/licence.d.ts +4 -0
- package/dist/site-system/rules/shell/licence.d.ts.map +1 -0
- package/dist/site-system/rules/shell/licence.js +60 -0
- package/dist/site-system/rules/shell/licence.js.map +1 -0
- package/dist/site-system/rules/shell/location-wording.d.ts +13 -0
- package/dist/site-system/rules/shell/location-wording.d.ts.map +1 -0
- package/dist/site-system/rules/shell/location-wording.js +15 -0
- package/dist/site-system/rules/shell/location-wording.js.map +1 -0
- package/dist/site-system/rules/shell/navigation.d.ts +5 -0
- package/dist/site-system/rules/shell/navigation.d.ts.map +1 -0
- package/dist/site-system/rules/shell/navigation.js +272 -0
- package/dist/site-system/rules/shell/navigation.js.map +1 -0
- package/dist/site-system/rules/shell/overlays.d.ts +4 -0
- package/dist/site-system/rules/shell/overlays.d.ts.map +1 -0
- package/dist/site-system/rules/shell/overlays.js +93 -0
- package/dist/site-system/rules/shell/overlays.js.map +1 -0
- package/dist/site-system/rules/shell/page.d.ts +51 -0
- package/dist/site-system/rules/shell/page.d.ts.map +1 -0
- package/dist/site-system/rules/shell/page.js +256 -0
- package/dist/site-system/rules/shell/page.js.map +1 -0
- package/dist/site-system/rules/shell/phone.d.ts +13 -0
- package/dist/site-system/rules/shell/phone.d.ts.map +1 -0
- package/dist/site-system/rules/shell/phone.js +99 -0
- package/dist/site-system/rules/shell/phone.js.map +1 -0
- package/dist/site-system/rules/shell/proof-numbers.d.ts +7 -0
- package/dist/site-system/rules/shell/proof-numbers.d.ts.map +1 -0
- package/dist/site-system/rules/shell/proof-numbers.js +81 -0
- package/dist/site-system/rules/shell/proof-numbers.js.map +1 -0
- package/dist/site-system/rules/shell/types.d.ts +80 -0
- package/dist/site-system/rules/shell/types.d.ts.map +1 -0
- package/dist/site-system/rules/shell/types.js +17 -0
- package/dist/site-system/rules/shell/types.js.map +1 -0
- package/dist/site-system/runners.d.ts +37 -0
- package/dist/site-system/runners.d.ts.map +1 -0
- package/dist/site-system/runners.js +48 -0
- package/dist/site-system/runners.js.map +1 -0
- package/dist/site-system/samples.d.ts +43 -0
- package/dist/site-system/samples.d.ts.map +1 -0
- package/dist/site-system/samples.js +99 -0
- package/dist/site-system/samples.js.map +1 -0
- package/dist/site-system/steps.d.ts +66 -0
- package/dist/site-system/steps.d.ts.map +1 -0
- package/dist/site-system/steps.js +45 -0
- package/dist/site-system/steps.js.map +1 -0
- package/dist/site-system/streamed-html.d.ts +9 -0
- package/dist/site-system/streamed-html.d.ts.map +1 -0
- package/dist/site-system/streamed-html.js +43 -0
- package/dist/site-system/streamed-html.js.map +1 -0
- package/dist/site-system-e2e.d.ts +6 -0
- package/dist/site-system-e2e.d.ts.map +1 -0
- package/dist/site-system-e2e.js +54 -0
- package/dist/site-system-e2e.js.map +1 -0
- package/package.json +22 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/html.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A small tolerant HTML reader for the rendered rules. It reads the server HTML a crawler receives, builds the\n * element tree and answers the few questions the rules ask: attributes, descendants, text and the lines a person\n * reads. It is not a browser: it does not run scripts, apply CSS or repair every invalid document.\n */\n\nexport interface HtmlText {\n type: \"text\";\n text: string;\n parent: HtmlElement | null;\n}\n\nexport interface HtmlElement {\n type: \"element\";\n tag: string;\n attrs: Record<string, string>;\n children: HtmlNode[];\n parent: HtmlElement | null;\n}\n\nexport type HtmlNode = HtmlElement | HtmlText;\n\nconst VOID_TAGS = new Set([\n \"area\", \"base\", \"br\", \"col\", \"embed\", \"hr\", \"img\", \"input\", \"link\", \"meta\", \"param\", \"source\", \"track\", \"wbr\",\n]);\n\n/** Elements whose content is not markup: kept as text, never part of what a person reads. */\nconst RAW_TEXT_TAGS = new Set([\"script\", \"style\"]);\n/** Elements whose content is text with entities and no markup. */\nconst ESCAPABLE_RAW_TEXT_TAGS = new Set([\"textarea\", \"title\"]);\n\n/** Opening the key closes an open element of one of the listed tags when it is the innermost one. */\nconst IMPLIED_END: Record<string, readonly string[]> = {\n li: [\"li\"],\n dt: [\"dt\", \"dd\"],\n dd: [\"dt\", \"dd\"],\n tr: [\"tr\", \"td\", \"th\"],\n td: [\"td\", \"th\"],\n th: [\"td\", \"th\"],\n option: [\"option\"],\n optgroup: [\"option\", \"optgroup\"],\n p: [\"p\"],\n};\n\n/** Elements that read as part of the line they sit in. Every other element starts a new line. */\nconst INLINE_TAGS = new Set([\n \"a\", \"abbr\", \"b\", \"bdi\", \"bdo\", \"cite\", \"code\", \"data\", \"dfn\", \"em\", \"i\", \"kbd\", \"mark\", \"q\", \"s\", \"samp\", \"small\",\n \"span\", \"strong\", \"sub\", \"sup\", \"time\", \"u\", \"var\", \"wbr\",\n]);\n\n/** Elements whose text a person never reads as page copy. */\nconst NON_READABLE_TAGS = new Set([\"script\", \"style\", \"template\", \"noscript\", \"select\", \"option\", \"head\", \"svg\"]);\n\nconst NAMED_ENTITIES: Record<string, string> = {\n amp: \"&\", lt: \"<\", gt: \">\", quot: \"\\\"\", apos: \"'\", nbsp: \" \", dollar: \"$\", pound: \"£\", ndash: \"–\",\n mdash: \"—\", hellip: \"…\", rsquo: \"’\", lsquo: \"‘\", ldquo: \"“\", rdquo: \"”\", times: \"×\",\n copy: \"©\", bull: \"•\", middot: \"·\", check: \"✓\", star: \"☆\",\n};\n\nexport function decodeEntities(value: string): string {\n return value.replace(/&(#x[0-9a-f]+|#\\d+|[a-z][a-z0-9]*);/gi, (match, body: string) => {\n if (body[0] === \"#\") {\n const code = body[1] === \"x\" || body[1] === \"X\" ? Number.parseInt(body.slice(2), 16) : Number.parseInt(body.slice(1), 10);\n return Number.isFinite(code) && code > 0 && code <= 0x10ffff ? String.fromCodePoint(code) : match;\n }\n return NAMED_ENTITIES[body.toLowerCase()] ?? match;\n });\n}\n\n/** Collapses runs of whitespace, non-breaking spaces included, and trims. */\nexport function normaliseText(value: string): string {\n return value.replace(/[\\s ]+/g, \" \").trim();\n}\n\nconst ATTRIBUTE = /([^\\s\"'<>/=]+)(?:\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))?/g;\n\nfunction parseAttributes(source: string): Record<string, string> {\n const attrs: Record<string, string> = {};\n for (const match of source.matchAll(ATTRIBUTE)) {\n const name = match[1]!.toLowerCase();\n if (Object.hasOwn(attrs, name)) continue;\n attrs[name] = decodeEntities(match[2] ?? match[3] ?? match[4] ?? \"\");\n }\n return attrs;\n}\n\nfunction createElement(tag: string, attrs: Record<string, string>, parent: HtmlElement | null): HtmlElement {\n return { type: \"element\", tag, attrs, children: [], parent };\n}\n\n/** Parses server HTML into a tree under a synthetic `#root` element. Never throws. */\nexport function parseHtml(html: string): HtmlElement {\n const root = createElement(\"#root\", {}, null);\n const stack: HtmlElement[] = [root];\n const top = () => stack[stack.length - 1]!;\n const addText = (text: string) => {\n if (text) top().children.push({ type: \"text\", text, parent: top() });\n };\n\n let index = 0;\n while (index < html.length) {\n const open = html.indexOf(\"<\", index);\n if (open === -1) {\n addText(decodeEntities(html.slice(index)));\n break;\n }\n if (open > index) addText(decodeEntities(html.slice(index, open)));\n\n if (html.startsWith(\"<!--\", open)) {\n const close = html.indexOf(\"-->\", open + 4);\n index = close === -1 ? html.length : close + 3;\n continue;\n }\n if (html[open + 1] === \"!\" || html[open + 1] === \"?\") {\n const close = html.indexOf(\">\", open + 2);\n index = close === -1 ? html.length : close + 1;\n continue;\n }\n if (html[open + 1] === \"/\") {\n const close = html.indexOf(\">\", open + 2);\n const tag = html.slice(open + 2, close === -1 ? html.length : close).trim().toLowerCase();\n index = close === -1 ? html.length : close + 1;\n for (let depth = stack.length - 1; depth > 0; depth -= 1) {\n if (stack[depth]!.tag === tag) {\n stack.length = depth;\n break;\n }\n }\n continue;\n }\n const tagMatch = /^<([a-zA-Z][a-zA-Z0-9:-]*)/.exec(html.slice(open, open + 64));\n if (!tagMatch) {\n addText(\"<\");\n index = open + 1;\n continue;\n }\n // The tag ends at the first \">\" outside a quoted attribute value.\n let cursor = open + tagMatch[0].length;\n let quote = \"\";\n while (cursor < html.length) {\n const character = html[cursor]!;\n if (quote) {\n if (character === quote) quote = \"\";\n } else if (character === \"\\\"\" || character === \"'\") {\n quote = character;\n } else if (character === \">\") {\n break;\n }\n cursor += 1;\n }\n const tag = tagMatch[1]!.toLowerCase();\n const rawAttributes = html.slice(open + tagMatch[0].length, cursor);\n const selfClosing = rawAttributes.trimEnd().endsWith(\"/\");\n index = Math.min(cursor + 1, html.length);\n\n const implied = IMPLIED_END[tag];\n if (implied && stack.length > 1 && implied.includes(top().tag)) stack.pop();\n\n const element = createElement(tag, parseAttributes(selfClosing ? rawAttributes.trimEnd().slice(0, -1) : rawAttributes), top());\n top().children.push(element);\n if (VOID_TAGS.has(tag) || selfClosing) continue;\n\n if (RAW_TEXT_TAGS.has(tag) || ESCAPABLE_RAW_TEXT_TAGS.has(tag)) {\n const closing = new RegExp(`</${tag}\\\\s*>`, \"gi\");\n closing.lastIndex = index;\n const close = closing.exec(html);\n const end = close ? close.index : html.length;\n const content = html.slice(index, end);\n element.children.push({\n type: \"text\",\n text: ESCAPABLE_RAW_TEXT_TAGS.has(tag) ? decodeEntities(content) : content,\n parent: element,\n });\n index = close ? close.index + close[0].length : html.length;\n continue;\n }\n stack.push(element);\n }\n return root;\n}\n\n/** Every element below `node`, in document order. */\nexport function descendants(node: HtmlElement): HtmlElement[] {\n const found: HtmlElement[] = [];\n const visit = (current: HtmlElement) => {\n for (const child of current.children) {\n if (child.type !== \"element\") continue;\n found.push(child);\n visit(child);\n }\n };\n visit(node);\n return found;\n}\n\nexport function attr(element: HtmlElement, name: string): string | undefined {\n return Object.hasOwn(element.attrs, name) ? element.attrs[name] : undefined;\n}\n\nexport function ancestors(element: HtmlElement): HtmlElement[] {\n const found: HtmlElement[] = [];\n for (let current = element.parent; current && current.tag !== \"#root\"; current = current.parent) found.push(current);\n return found;\n}\n\nexport function closest(element: HtmlElement, test: (candidate: HtmlElement) => boolean): HtmlElement | null {\n for (let current: HtmlElement | null = element; current && current.tag !== \"#root\"; current = current.parent) {\n if (test(current)) return current;\n }\n return null;\n}\n\n/** Whether the element, or an ancestor, is hidden from people: `hidden` or `aria-hidden=\"true\"`. */\nexport function isHiddenFromPeople(element: HtmlElement): boolean {\n return closest(element, (candidate) => attr(candidate, \"hidden\") !== undefined || attr(candidate, \"aria-hidden\") === \"true\") !== null;\n}\n\n/**\n * The text a person reads inside an element, whitespace collapsed. Blocks are separated by a space. Inline parts join\n * with no space (\"$\" then \"450\" reads \"$450\") unless `spaced` is set, which puts a space at every element boundary\n * so that \"4.9\" in one span and \"132 reviews\" in the next do not run together.\n */\nexport function textOf(element: HtmlElement, spaced = false, skip?: (element: HtmlElement) => boolean): string {\n return normaliseText(collectText(element, spaced, skip));\n}\n\nfunction collectText(element: HtmlElement, spaced: boolean, skip?: (element: HtmlElement) => boolean): string {\n let text = \"\";\n for (const child of element.children) {\n if (child.type === \"text\") {\n text += child.text;\n continue;\n }\n if (NON_READABLE_TAGS.has(child.tag) || skip?.(child)) continue;\n const inline = !spaced && INLINE_TAGS.has(child.tag);\n text += (inline ? \"\" : \" \") + collectText(child, spaced, skip) + (inline ? \"\" : \" \");\n }\n return text;\n}\n\nexport interface ReadableLine {\n text: string;\n /** The `href` of every link in the line. */\n hrefs: string[];\n}\n\n/** Hidden from people by `hidden` or `aria-hidden=\"true\"` on the element itself. */\nfunction hiddenItself(element: HtmlElement): boolean {\n return attr(element, \"hidden\") !== undefined || attr(element, \"aria-hidden\") === \"true\";\n}\n\n/**\n * The lines of text a person reads in an element: inline parts join, every block starts a new line. Subtrees that are\n * hidden (`hidden`, `aria-hidden=\"true\"`) are left out, and each line keeps the links it contains.\n */\nexport function readableLines(element: HtmlElement): ReadableLine[] {\n const lines: ReadableLine[] = [];\n let current = \"\";\n let hrefs: string[] = [];\n const flush = () => {\n const text = normaliseText(current);\n if (text) lines.push({ text, hrefs });\n current = \"\";\n hrefs = [];\n };\n const visit = (node: HtmlElement) => {\n for (const child of node.children) {\n if (child.type === \"text\") {\n current += child.text;\n continue;\n }\n if (NON_READABLE_TAGS.has(child.tag) || hiddenItself(child)) continue;\n if (child.tag === \"br\") {\n flush();\n continue;\n }\n if (child.tag === \"a\") hrefs.push(attr(child, \"href\") ?? \"\");\n const inline = INLINE_TAGS.has(child.tag);\n if (!inline) flush();\n visit(child);\n if (!inline) flush();\n }\n };\n visit(element);\n flush();\n return lines;\n}\n\n/** The text of each line a person reads in an element. */\nexport function linesOf(element: HtmlElement): string[] {\n return readableLines(element).map((line) => line.text);\n}\n\n/** The page's `<title>` text, or null when it has none. */\nexport function documentTitle(root: HtmlElement): string | null {\n const title = descendants(root).find((element) => element.tag === \"title\");\n if (!title) return null;\n return normaliseText(title.children.map((child) => (child.type === \"text\" ? child.text : \"\")).join(\"\"));\n}\n\n/** The visible name of a form control: its label, `aria-label` or `aria-labelledby` text. Empty when it has none. */\nexport function accessibleLabel(control: HtmlElement, scope: HtmlElement): string {\n const ariaLabel = attr(control, \"aria-label\");\n if (ariaLabel) return normaliseText(ariaLabel);\n const labelledBy = attr(control, \"aria-labelledby\");\n const elements = descendants(scope);\n if (labelledBy) {\n const text = labelledBy\n .split(/\\s+/)\n .map((id) => elements.find((element) => attr(element, \"id\") === id))\n .filter((element): element is HtmlElement => element !== undefined)\n .map((element) => textOf(element))\n .join(\" \");\n if (text) return normaliseText(text);\n }\n const id = attr(control, \"id\");\n if (id) {\n const label = elements.find((element) => element.tag === \"label\" && attr(element, \"for\") === id);\n if (label) return textOf(label);\n }\n const wrapping = closest(control, (candidate) => candidate.tag === \"label\");\n return wrapping ? textOf(wrapping) : \"\";\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The enquiry-tier rendered rules and the data rules that ship with them (release 3.8.0): C2, E9, T5, K8, E1 and
|
|
3
|
+
* T11. They run over the sampled pages' server HTML and the project's recorded data, and return findings for the
|
|
4
|
+
* ready report. The runner has the signature the ready gate registers.
|
|
5
|
+
*/
|
|
6
|
+
import type { SiteSystemFinding } from "../../checks.js";
|
|
7
|
+
import { type EnquiryRuleInput, type EnquiryRuleOptions } from "./common.js";
|
|
8
|
+
export type { EnquiryRuleInput, EnquiryRuleOptions } from "./common.js";
|
|
9
|
+
export { C2_CONSENT_LINK, C2_FIELD_ORDER, C2_HELPER_LINE_EXAMPLES, C2_HELPER_LINE_PATTERNS, C2_MESSAGE_LABEL, C2_REQUIRED_MARKER_PATTERNS, checkC2, quoteFormProblems } from "./c2-quote-form.js";
|
|
10
|
+
export { E1_RECORD_PATH, checkE1, readRecordedTitles } from "./e1-recorded-titles.js";
|
|
11
|
+
export { E9_MIN_FIGURES, checkE9, isCostGuide, priceFigures } from "./e9-cost-guides.js";
|
|
12
|
+
export { K8_PROOF_SECTIONS, K8_PROOF_WITHIN, checkK8 } from "./k8-sections.js";
|
|
13
|
+
export { T11_HBC_CAP, T11_SERVICE_CLASS_MAP, checkT11, evaluateServiceClassGate, licenceConditionCap, readLicences, readServiceClassMap, } from "./t11-licence-classes.js";
|
|
14
|
+
export { checkT5, inspectReviewsSection } from "./t5-reviews.js";
|
|
15
|
+
/** Runs C2, E9, T5, K8, E1 and T11 over the sampled pages and the project at `projectRoot`. */
|
|
16
|
+
export declare function runEnquiryRenderedRules(input: EnquiryRuleInput, options?: EnquiryRuleOptions): Promise<readonly SiteSystemFinding[]>;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAc,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAOzF,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAClM,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,QAAQ,EACR,wBAAwB,EACxB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAEjE,+FAA+F;AAC/F,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAUvC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { checkC2 } from "./c2-quote-form.js";
|
|
2
|
+
import { parsePages } from "./common.js";
|
|
3
|
+
import { checkE1 } from "./e1-recorded-titles.js";
|
|
4
|
+
import { checkE9 } from "./e9-cost-guides.js";
|
|
5
|
+
import { checkK8 } from "./k8-sections.js";
|
|
6
|
+
import { checkT11 } from "./t11-licence-classes.js";
|
|
7
|
+
import { checkT5 } from "./t5-reviews.js";
|
|
8
|
+
export { C2_CONSENT_LINK, C2_FIELD_ORDER, C2_HELPER_LINE_EXAMPLES, C2_HELPER_LINE_PATTERNS, C2_MESSAGE_LABEL, C2_REQUIRED_MARKER_PATTERNS, checkC2, quoteFormProblems } from "./c2-quote-form.js";
|
|
9
|
+
export { E1_RECORD_PATH, checkE1, readRecordedTitles } from "./e1-recorded-titles.js";
|
|
10
|
+
export { E9_MIN_FIGURES, checkE9, isCostGuide, priceFigures } from "./e9-cost-guides.js";
|
|
11
|
+
export { K8_PROOF_SECTIONS, K8_PROOF_WITHIN, checkK8 } from "./k8-sections.js";
|
|
12
|
+
export { T11_HBC_CAP, T11_SERVICE_CLASS_MAP, checkT11, evaluateServiceClassGate, licenceConditionCap, readLicences, readServiceClassMap, } from "./t11-licence-classes.js";
|
|
13
|
+
export { checkT5, inspectReviewsSection } from "./t5-reviews.js";
|
|
14
|
+
/** Runs C2, E9, T5, K8, E1 and T11 over the sampled pages and the project at `projectRoot`. */
|
|
15
|
+
export async function runEnquiryRenderedRules(input, options = {}) {
|
|
16
|
+
const pages = parsePages(input.pages);
|
|
17
|
+
return [
|
|
18
|
+
...checkC2(pages, input.baseUrl),
|
|
19
|
+
...checkE9(pages),
|
|
20
|
+
...checkT5(pages),
|
|
21
|
+
...checkK8(pages),
|
|
22
|
+
...checkE1(pages, input.projectRoot),
|
|
23
|
+
...checkT11(pages, input.projectRoot, options.asOf ?? new Date()),
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAkD,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG1C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAClM,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,QAAQ,EACR,wBAAwB,EACxB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAEjE,+FAA+F;AAC/F,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAAuB,EACvB,UAA8B,EAAE;IAEhC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO;QACL,GAAG,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;QAChC,GAAG,OAAO,CAAC,KAAK,CAAC;QACjB,GAAG,OAAO,CAAC,KAAK,CAAC;QACjB,GAAG,OAAO,CAAC,KAAK,CAAC;QACjB,GAAG,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC;QACpC,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;KAClE,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The enquiry-tier rendered rules and the data rules that ship with them (release 3.8.0): C2, E9, T5, K8, E1 and\n * T11. They run over the sampled pages' server HTML and the project's recorded data, and return findings for the\n * ready report. The runner has the signature the ready gate registers.\n */\nimport type { SiteSystemFinding } from \"../../checks.js\";\nimport { checkC2 } from \"./c2-quote-form.js\";\nimport { parsePages, type EnquiryRuleInput, type EnquiryRuleOptions } from \"./common.js\";\nimport { checkE1 } from \"./e1-recorded-titles.js\";\nimport { checkE9 } from \"./e9-cost-guides.js\";\nimport { checkK8 } from \"./k8-sections.js\";\nimport { checkT11 } from \"./t11-licence-classes.js\";\nimport { checkT5 } from \"./t5-reviews.js\";\n\nexport type { EnquiryRuleInput, EnquiryRuleOptions } from \"./common.js\";\nexport { C2_CONSENT_LINK, C2_FIELD_ORDER, C2_HELPER_LINE_EXAMPLES, C2_HELPER_LINE_PATTERNS, C2_MESSAGE_LABEL, C2_REQUIRED_MARKER_PATTERNS, checkC2, quoteFormProblems } from \"./c2-quote-form.js\";\nexport { E1_RECORD_PATH, checkE1, readRecordedTitles } from \"./e1-recorded-titles.js\";\nexport { E9_MIN_FIGURES, checkE9, isCostGuide, priceFigures } from \"./e9-cost-guides.js\";\nexport { K8_PROOF_SECTIONS, K8_PROOF_WITHIN, checkK8 } from \"./k8-sections.js\";\nexport {\n T11_HBC_CAP,\n T11_SERVICE_CLASS_MAP,\n checkT11,\n evaluateServiceClassGate,\n licenceConditionCap,\n readLicences,\n readServiceClassMap,\n} from \"./t11-licence-classes.js\";\nexport { checkT5, inspectReviewsSection } from \"./t5-reviews.js\";\n\n/** Runs C2, E9, T5, K8, E1 and T11 over the sampled pages and the project at `projectRoot`. */\nexport async function runEnquiryRenderedRules(\n input: EnquiryRuleInput,\n options: EnquiryRuleOptions = {},\n): Promise<readonly SiteSystemFinding[]> {\n const pages = parsePages(input.pages);\n return [\n ...checkC2(pages, input.baseUrl),\n ...checkE9(pages),\n ...checkT5(pages),\n ...checkK8(pages),\n ...checkE1(pages, input.projectRoot),\n ...checkT11(pages, input.projectRoot, options.asOf ?? new Date()),\n ];\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* K8: the section contract, page by page (Site System v2 §13.2).
|
|
3
|
+
*
|
|
4
|
+
* Every `data-bl-section` has exactly one H2 (the section that holds the page's H1 may have none), is not empty, and
|
|
5
|
+
* sits in a tone that differs from its neighbours'. A page has at most one `band` tone. A page that opens with a hero
|
|
6
|
+
* (the money pages) shows proof within its first five sections.
|
|
7
|
+
*/
|
|
8
|
+
import type { SiteSystemFinding } from "../../checks.js";
|
|
9
|
+
import { type ParsedPage } from "./common.js";
|
|
10
|
+
import { type HtmlElement } from "./html.js";
|
|
11
|
+
/** The sections that count as proof for the first-five rule. */
|
|
12
|
+
export declare const K8_PROOF_SECTIONS: readonly ["reviews", "proof-strip", "projects"];
|
|
13
|
+
/** The first sections of a money page are where proof has to appear. */
|
|
14
|
+
export declare const K8_PROOF_WITHIN = 5;
|
|
15
|
+
export declare function isEmptySection(section: HtmlElement): boolean;
|
|
16
|
+
export declare function checkK8(pages: readonly ParsedPage[]): SiteSystemFinding[];
|
|
17
|
+
//# sourceMappingURL=k8-sections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"k8-sections.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/k8-sections.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;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;AAsBjC,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAO5D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,iBAAiB,EAAE,CA4CzE"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { fail, notApplicable, plural, resultOf, sectionId, topLevelSections } from "./common.js";
|
|
2
|
+
import { attr, descendants, normaliseText } from "./html.js";
|
|
3
|
+
/** The sections that count as proof for the first-five rule. */
|
|
4
|
+
export const K8_PROOF_SECTIONS = ["reviews", "proof-strip", "projects"];
|
|
5
|
+
/** The first sections of a money page are where proof has to appear. */
|
|
6
|
+
export const K8_PROOF_WITHIN = 5;
|
|
7
|
+
/** Elements that are content on their own, without any text. */
|
|
8
|
+
const CONTENT_TAGS = new Set(["img", "picture", "video", "audio", "iframe", "canvas", "input", "textarea", "select", "button", "table"]);
|
|
9
|
+
function headings(section, tag) {
|
|
10
|
+
return descendants(section).filter((element) => element.tag === tag);
|
|
11
|
+
}
|
|
12
|
+
/** The text of a section outside its headings. */
|
|
13
|
+
function bodyText(element) {
|
|
14
|
+
let text = "";
|
|
15
|
+
for (const child of element.children) {
|
|
16
|
+
if (child.type === "text") {
|
|
17
|
+
text += child.text;
|
|
18
|
+
}
|
|
19
|
+
else if (!/^h[1-6]$/.test(child.tag) && !["script", "style", "template"].includes(child.tag)) {
|
|
20
|
+
text += ` ${bodyText(child)} `;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return text;
|
|
24
|
+
}
|
|
25
|
+
export function isEmptySection(section) {
|
|
26
|
+
if (normaliseText(bodyText(section)) !== "")
|
|
27
|
+
return false;
|
|
28
|
+
return !descendants(section).some((element) => CONTENT_TAGS.has(element.tag) ||
|
|
29
|
+
(element.tag === "svg" && (attr(element, "role") === "img" || attr(element, "aria-label") !== undefined)));
|
|
30
|
+
}
|
|
31
|
+
export function checkK8(pages) {
|
|
32
|
+
const failures = [];
|
|
33
|
+
let checked = 0;
|
|
34
|
+
for (const page of pages) {
|
|
35
|
+
const sections = topLevelSections(page.root);
|
|
36
|
+
if (sections.length === 0)
|
|
37
|
+
continue;
|
|
38
|
+
checked += 1;
|
|
39
|
+
const at = (index) => `"${sectionId(sections[index])}" (section ${index + 1})`;
|
|
40
|
+
sections.forEach((section, index) => {
|
|
41
|
+
const h2 = headings(section, "h2").length;
|
|
42
|
+
const holdsH1 = headings(section, "h1").length > 0;
|
|
43
|
+
if (h2 > 1) {
|
|
44
|
+
failures.push(fail("K8", page.path, `The section ${at(index)} on ${page.path} has ${h2} H2 headings; each section has one.`));
|
|
45
|
+
}
|
|
46
|
+
else if (h2 === 0 && !holdsH1) {
|
|
47
|
+
failures.push(fail("K8", page.path, `The section ${at(index)} on ${page.path} has no H2 heading; each section has one.`));
|
|
48
|
+
}
|
|
49
|
+
if (isEmptySection(section)) {
|
|
50
|
+
failures.push(fail("K8", page.path, `The section ${at(index)} on ${page.path} is empty; a section with nothing to show is left out.`));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const bands = sections.filter((section) => attr(section, "data-tone") === "band");
|
|
54
|
+
if (bands.length > 1) {
|
|
55
|
+
failures.push(fail("K8", page.path, `${page.path} has ${bands.length} sections in the band tone; a page has at most one.`));
|
|
56
|
+
}
|
|
57
|
+
for (let index = 1; index < sections.length; index += 1) {
|
|
58
|
+
const previous = attr(sections[index - 1], "data-tone");
|
|
59
|
+
const tone = attr(sections[index], "data-tone");
|
|
60
|
+
if (tone !== undefined && tone === previous) {
|
|
61
|
+
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.`));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const opensWithHero = sections.some((section) => sectionId(section) === "hero");
|
|
65
|
+
if (opensWithHero) {
|
|
66
|
+
const firstFive = sections.slice(0, K8_PROOF_WITHIN).map(sectionId);
|
|
67
|
+
if (!firstFive.some((id) => K8_PROOF_SECTIONS.includes(id))) {
|
|
68
|
+
failures.push(fail("K8", page.path, `${page.path} shows no proof (${K8_PROOF_SECTIONS.join(", ")}) in its first ${K8_PROOF_WITHIN} sections.`));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (checked === 0)
|
|
73
|
+
return [notApplicable("K8", "None of the sampled pages has a data-bl-section.")];
|
|
74
|
+
return resultOf("K8", failures, `Checked ${plural(checked, "page")}: each follows the section contract.`);
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=k8-sections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"k8-sections.js","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/k8-sections.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAmB,MAAM,aAAa,CAAC;AAClH,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAoB,MAAM,WAAW,CAAC;AAE/E,gEAAgE;AAChE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,CAAU,CAAC;AAEjF,wEAAwE;AACxE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC,gEAAgE;AAChE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAEzI,SAAS,QAAQ,CAAC,OAAoB,EAAE,GAAW;IACjD,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AACvE,CAAC;AAED,kDAAkD;AAClD,SAAS,QAAQ,CAAC,OAAoB;IACpC,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;QACrB,CAAC;aAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/F,IAAI,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;QACjC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAoB;IACjD,IAAI,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAC1D,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAC/B,CAAC,OAAO,EAAE,EAAE,CACV,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;QAC7B,CAAC,OAAO,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,KAAK,SAAS,CAAC,CAAC,CAC5G,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAA4B;IAClD,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACpC,OAAO,IAAI,CAAC,CAAC;QACb,MAAM,EAAE,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAE,CAAC,cAAc,KAAK,GAAG,CAAC,GAAG,CAAC;QAExF,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;YAClC,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC;YAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YACnD,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;gBACX,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,IAAI,QAAQ,EAAE,qCAAqC,CAAC,CAAC,CAAC;YAChI,CAAC;iBAAM,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAChC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,IAAI,2CAA2C,CAAC,CAAC,CAAC;YAC5H,CAAC;YACD,IAAI,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,IAAI,wDAAwD,CAAC,CAAC,CAAC;YACzI,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,KAAK,MAAM,CAAC,CAAC;QAClF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,QAAQ,KAAK,CAAC,MAAM,qDAAqD,CAAC,CAAC,CAAC;QAC9H,CAAC;QACD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAE,EAAE,WAAW,CAAC,CAAC;YACzD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAE,EAAE,WAAW,CAAC,CAAC;YACjD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,gBAAgB,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,IAAI,oBAAoB,IAAI,2BAA2B,CAAC,CAAC,CAAC;YAC1J,CAAC;QACH,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC;QAChF,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACpE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAE,iBAAuC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBACnF,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,oBAAoB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,eAAe,YAAY,CAAC,CAAC,CAAC;YAClJ,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,OAAO,KAAK,CAAC;QAAE,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,kDAAkD,CAAC,CAAC,CAAC;IACpG,OAAO,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,sCAAsC,CAAC,CAAC;AAC5G,CAAC","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.\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/** 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 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.slice(0, K8_PROOF_WITHIN).map(sectionId);\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"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads plain data out of a project's TypeScript source without running it. The data files the rules read
|
|
3
|
+
* (`src/data/business.ts`, `src/data/businessEvidence.ts`, `src/data/strategy.ts`) are written as literals; this
|
|
4
|
+
* reads those literals, follows a same-file `const`, and unwraps the `verifiedFact(value, evidence)` family. Anything
|
|
5
|
+
* it cannot evaluate to plain data comes back as `UNRESOLVED`, so a rule can tell "not there" from "not readable".
|
|
6
|
+
*/
|
|
7
|
+
import ts from "typescript";
|
|
8
|
+
export declare const UNRESOLVED: unique symbol;
|
|
9
|
+
export type Literal = string | number | boolean | null | Literal[] | {
|
|
10
|
+
[key: string]: Literal;
|
|
11
|
+
} | typeof UNRESOLVED;
|
|
12
|
+
export declare function isLiteralObject(value: Literal | undefined): value is {
|
|
13
|
+
[key: string]: Literal;
|
|
14
|
+
};
|
|
15
|
+
/** True when nothing inside the value is unresolved. */
|
|
16
|
+
export declare function isFullyResolved(value: Literal | undefined): boolean;
|
|
17
|
+
export declare class LiteralReader {
|
|
18
|
+
readonly sourceFile: ts.SourceFile;
|
|
19
|
+
private readonly constants;
|
|
20
|
+
constructor(sourceText: string, fileName?: string);
|
|
21
|
+
/** The first argument of every call to `callee`, in source order. */
|
|
22
|
+
callArguments(callee: string): ts.Expression[];
|
|
23
|
+
/** The value of every property called `name`, wherever it sits in the file. */
|
|
24
|
+
propertyValues(name: string): ts.Expression[];
|
|
25
|
+
/** The initialiser of a top-level `const name = …`, or undefined. */
|
|
26
|
+
constant(name: string): ts.Expression | undefined;
|
|
27
|
+
evaluate(node: ts.Expression, depth?: number, seen?: ReadonlySet<string>): Literal;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=literal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"literal.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/literal.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,eAAO,MAAM,UAAU,EAAE,OAAO,MAA6B,CAAC;AAE9D,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,OAAO,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAAG,OAAO,UAAU,CAAC;AAEpH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,KAAK,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAE/F;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAKnE;AAID,qBAAa,aAAa;IACxB,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoC;gBAElD,UAAU,EAAE,MAAM,EAAE,QAAQ,SAAc;IAatD,qEAAqE;IACrE,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,UAAU,EAAE;IAY9C,+EAA+E;IAC/E,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,UAAU,EAAE;IAW7C,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,UAAU,GAAG,SAAS;IAIjD,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,EAAE,KAAK,SAAI,EAAE,IAAI,GAAE,WAAW,CAAC,MAAM,CAAa,GAAG,OAAO;CA6FzF"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads plain data out of a project's TypeScript source without running it. The data files the rules read
|
|
3
|
+
* (`src/data/business.ts`, `src/data/businessEvidence.ts`, `src/data/strategy.ts`) are written as literals; this
|
|
4
|
+
* reads those literals, follows a same-file `const`, and unwraps the `verifiedFact(value, evidence)` family. Anything
|
|
5
|
+
* it cannot evaluate to plain data comes back as `UNRESOLVED`, so a rule can tell "not there" from "not readable".
|
|
6
|
+
*/
|
|
7
|
+
import ts from "typescript";
|
|
8
|
+
export const UNRESOLVED = Symbol("unresolved");
|
|
9
|
+
export function isLiteralObject(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
/** True when nothing inside the value is unresolved. */
|
|
13
|
+
export function isFullyResolved(value) {
|
|
14
|
+
if (value === undefined || value === UNRESOLVED)
|
|
15
|
+
return false;
|
|
16
|
+
if (Array.isArray(value))
|
|
17
|
+
return value.every(isFullyResolved);
|
|
18
|
+
if (isLiteralObject(value))
|
|
19
|
+
return Object.values(value).every(isFullyResolved);
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
const MAX_DEPTH = 24;
|
|
23
|
+
export class LiteralReader {
|
|
24
|
+
sourceFile;
|
|
25
|
+
constants = new Map();
|
|
26
|
+
constructor(sourceText, fileName = "source.ts") {
|
|
27
|
+
this.sourceFile = ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
28
|
+
for (const statement of this.sourceFile.statements) {
|
|
29
|
+
if (!ts.isVariableStatement(statement))
|
|
30
|
+
continue;
|
|
31
|
+
if (!(statement.declarationList.flags & ts.NodeFlags.Const))
|
|
32
|
+
continue;
|
|
33
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
34
|
+
if (ts.isIdentifier(declaration.name) && declaration.initializer) {
|
|
35
|
+
this.constants.set(declaration.name.text, declaration.initializer);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** The first argument of every call to `callee`, in source order. */
|
|
41
|
+
callArguments(callee) {
|
|
42
|
+
const found = [];
|
|
43
|
+
const visit = (node) => {
|
|
44
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === callee && node.arguments[0]) {
|
|
45
|
+
found.push(node.arguments[0]);
|
|
46
|
+
}
|
|
47
|
+
ts.forEachChild(node, visit);
|
|
48
|
+
};
|
|
49
|
+
visit(this.sourceFile);
|
|
50
|
+
return found;
|
|
51
|
+
}
|
|
52
|
+
/** The value of every property called `name`, wherever it sits in the file. */
|
|
53
|
+
propertyValues(name) {
|
|
54
|
+
const found = [];
|
|
55
|
+
const visit = (node) => {
|
|
56
|
+
if (ts.isPropertyAssignment(node) && propertyName(node.name) === name)
|
|
57
|
+
found.push(node.initializer);
|
|
58
|
+
else if (ts.isShorthandPropertyAssignment(node) && node.name.text === name)
|
|
59
|
+
found.push(node.name);
|
|
60
|
+
ts.forEachChild(node, visit);
|
|
61
|
+
};
|
|
62
|
+
visit(this.sourceFile);
|
|
63
|
+
return found;
|
|
64
|
+
}
|
|
65
|
+
/** The initialiser of a top-level `const name = …`, or undefined. */
|
|
66
|
+
constant(name) {
|
|
67
|
+
return this.constants.get(name);
|
|
68
|
+
}
|
|
69
|
+
evaluate(node, depth = 0, seen = new Set()) {
|
|
70
|
+
if (depth > MAX_DEPTH)
|
|
71
|
+
return UNRESOLVED;
|
|
72
|
+
const next = (child) => this.evaluate(child, depth + 1, seen);
|
|
73
|
+
if (ts.isStringLiteralLike(node))
|
|
74
|
+
return node.text;
|
|
75
|
+
if (ts.isNumericLiteral(node))
|
|
76
|
+
return Number(node.text);
|
|
77
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword)
|
|
78
|
+
return true;
|
|
79
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword)
|
|
80
|
+
return false;
|
|
81
|
+
if (node.kind === ts.SyntaxKind.NullKeyword)
|
|
82
|
+
return null;
|
|
83
|
+
if (ts.isParenthesizedExpression(node) ||
|
|
84
|
+
ts.isAsExpression(node) ||
|
|
85
|
+
ts.isSatisfiesExpression(node) ||
|
|
86
|
+
ts.isTypeAssertionExpression(node) ||
|
|
87
|
+
ts.isNonNullExpression(node)) {
|
|
88
|
+
return next(node.expression);
|
|
89
|
+
}
|
|
90
|
+
if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.MinusToken) {
|
|
91
|
+
const value = next(node.operand);
|
|
92
|
+
return typeof value === "number" ? -value : UNRESOLVED;
|
|
93
|
+
}
|
|
94
|
+
if (ts.isTemplateExpression(node)) {
|
|
95
|
+
let text = node.head.text;
|
|
96
|
+
for (const span of node.templateSpans) {
|
|
97
|
+
const value = next(span.expression);
|
|
98
|
+
if (typeof value !== "string" && typeof value !== "number")
|
|
99
|
+
return UNRESOLVED;
|
|
100
|
+
text += String(value) + span.literal.text;
|
|
101
|
+
}
|
|
102
|
+
return text;
|
|
103
|
+
}
|
|
104
|
+
if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) {
|
|
105
|
+
const left = next(node.left);
|
|
106
|
+
const right = next(node.right);
|
|
107
|
+
if (typeof left === "string" && (typeof right === "string" || typeof right === "number"))
|
|
108
|
+
return left + String(right);
|
|
109
|
+
if (typeof left === "number" && typeof right === "number")
|
|
110
|
+
return left + right;
|
|
111
|
+
return UNRESOLVED;
|
|
112
|
+
}
|
|
113
|
+
if (ts.isArrayLiteralExpression(node)) {
|
|
114
|
+
const items = [];
|
|
115
|
+
for (const element of node.elements) {
|
|
116
|
+
if (ts.isSpreadElement(element)) {
|
|
117
|
+
const spread = next(element.expression);
|
|
118
|
+
if (Array.isArray(spread))
|
|
119
|
+
items.push(...spread);
|
|
120
|
+
else
|
|
121
|
+
items.push(UNRESOLVED);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
items.push(next(element));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return items;
|
|
128
|
+
}
|
|
129
|
+
if (ts.isObjectLiteralExpression(node)) {
|
|
130
|
+
const result = {};
|
|
131
|
+
for (const property of node.properties) {
|
|
132
|
+
if (ts.isPropertyAssignment(property)) {
|
|
133
|
+
const key = propertyName(property.name);
|
|
134
|
+
if (key !== undefined)
|
|
135
|
+
result[key] = next(property.initializer);
|
|
136
|
+
}
|
|
137
|
+
else if (ts.isShorthandPropertyAssignment(property)) {
|
|
138
|
+
result[property.name.text] = next(property.name);
|
|
139
|
+
}
|
|
140
|
+
else if (ts.isSpreadAssignment(property)) {
|
|
141
|
+
const spread = next(property.expression);
|
|
142
|
+
if (isLiteralObject(spread))
|
|
143
|
+
Object.assign(result, spread);
|
|
144
|
+
else
|
|
145
|
+
result["..."] = UNRESOLVED;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
result["..."] = UNRESOLVED;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
if (ts.isIdentifier(node)) {
|
|
154
|
+
if (node.text === "undefined")
|
|
155
|
+
return UNRESOLVED;
|
|
156
|
+
const initializer = this.constants.get(node.text);
|
|
157
|
+
if (!initializer || seen.has(node.text))
|
|
158
|
+
return UNRESOLVED;
|
|
159
|
+
return this.evaluate(initializer, depth + 1, new Set([...seen, node.text]));
|
|
160
|
+
}
|
|
161
|
+
if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {
|
|
162
|
+
const target = next(node.expression);
|
|
163
|
+
const key = ts.isPropertyAccessExpression(node)
|
|
164
|
+
? node.name.text
|
|
165
|
+
: ts.isStringLiteralLike(node.argumentExpression)
|
|
166
|
+
? node.argumentExpression.text
|
|
167
|
+
: undefined;
|
|
168
|
+
if (key === undefined || !isLiteralObject(target) || !Object.hasOwn(target, key))
|
|
169
|
+
return UNRESOLVED;
|
|
170
|
+
return target[key];
|
|
171
|
+
}
|
|
172
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
|
173
|
+
const callee = node.expression.text;
|
|
174
|
+
if (callee === "verifiedFact" && node.arguments[0])
|
|
175
|
+
return { status: "verified", value: next(node.arguments[0]) };
|
|
176
|
+
if (callee === "unknownFact")
|
|
177
|
+
return { status: "unknown" };
|
|
178
|
+
if (callee === "notApplicableFact")
|
|
179
|
+
return { status: "not-applicable" };
|
|
180
|
+
}
|
|
181
|
+
return UNRESOLVED;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function propertyName(name) {
|
|
185
|
+
if (ts.isIdentifier(name) || ts.isStringLiteralLike(name) || ts.isNumericLiteral(name))
|
|
186
|
+
return name.text;
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=literal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"literal.js","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/literal.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Reads plain data out of a project's TypeScript source without running it. The data files the rules read\n * (`src/data/business.ts`, `src/data/businessEvidence.ts`, `src/data/strategy.ts`) are written as literals; this\n * reads those literals, follows a same-file `const`, and unwraps the `verifiedFact(value, evidence)` family. Anything\n * it cannot evaluate to plain data comes back as `UNRESOLVED`, so a rule can tell \"not there\" from \"not readable\".\n */\nimport ts from \"typescript\";\n\nexport const UNRESOLVED: unique symbol = Symbol(\"unresolved\");\n\nexport type Literal = string | number | boolean | null | Literal[] | { [key: string]: Literal } | typeof UNRESOLVED;\n\nexport function isLiteralObject(value: Literal | undefined): value is { [key: string]: Literal } {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** True when nothing inside the value is unresolved. */\nexport function isFullyResolved(value: Literal | undefined): boolean {\n if (value === undefined || value === UNRESOLVED) return false;\n if (Array.isArray(value)) return value.every(isFullyResolved);\n if (isLiteralObject(value)) return Object.values(value).every(isFullyResolved);\n return true;\n}\n\nconst MAX_DEPTH = 24;\n\nexport class LiteralReader {\n readonly sourceFile: ts.SourceFile;\n private readonly constants = new Map<string, ts.Expression>();\n\n constructor(sourceText: string, fileName = \"source.ts\") {\n this.sourceFile = ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n for (const statement of this.sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue;\n if (!(statement.declarationList.flags & ts.NodeFlags.Const)) continue;\n for (const declaration of statement.declarationList.declarations) {\n if (ts.isIdentifier(declaration.name) && declaration.initializer) {\n this.constants.set(declaration.name.text, declaration.initializer);\n }\n }\n }\n }\n\n /** The first argument of every call to `callee`, in source order. */\n callArguments(callee: string): ts.Expression[] {\n const found: ts.Expression[] = [];\n const visit = (node: ts.Node) => {\n if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === callee && node.arguments[0]) {\n found.push(node.arguments[0]);\n }\n ts.forEachChild(node, visit);\n };\n visit(this.sourceFile);\n return found;\n }\n\n /** The value of every property called `name`, wherever it sits in the file. */\n propertyValues(name: string): ts.Expression[] {\n const found: ts.Expression[] = [];\n const visit = (node: ts.Node) => {\n if (ts.isPropertyAssignment(node) && propertyName(node.name) === name) found.push(node.initializer);\n else if (ts.isShorthandPropertyAssignment(node) && node.name.text === name) found.push(node.name);\n ts.forEachChild(node, visit);\n };\n visit(this.sourceFile);\n return found;\n }\n\n /** The initialiser of a top-level `const name = …`, or undefined. */\n constant(name: string): ts.Expression | undefined {\n return this.constants.get(name);\n }\n\n evaluate(node: ts.Expression, depth = 0, seen: ReadonlySet<string> = new Set()): Literal {\n if (depth > MAX_DEPTH) return UNRESOLVED;\n const next = (child: ts.Expression) => this.evaluate(child, depth + 1, seen);\n\n if (ts.isStringLiteralLike(node)) return node.text;\n if (ts.isNumericLiteral(node)) return Number(node.text);\n if (node.kind === ts.SyntaxKind.TrueKeyword) return true;\n if (node.kind === ts.SyntaxKind.FalseKeyword) return false;\n if (node.kind === ts.SyntaxKind.NullKeyword) return null;\n if (\n ts.isParenthesizedExpression(node) ||\n ts.isAsExpression(node) ||\n ts.isSatisfiesExpression(node) ||\n ts.isTypeAssertionExpression(node) ||\n ts.isNonNullExpression(node)\n ) {\n return next(node.expression);\n }\n if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.MinusToken) {\n const value = next(node.operand);\n return typeof value === \"number\" ? -value : UNRESOLVED;\n }\n if (ts.isTemplateExpression(node)) {\n let text = node.head.text;\n for (const span of node.templateSpans) {\n const value = next(span.expression);\n if (typeof value !== \"string\" && typeof value !== \"number\") return UNRESOLVED;\n text += String(value) + span.literal.text;\n }\n return text;\n }\n if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) {\n const left = next(node.left);\n const right = next(node.right);\n if (typeof left === \"string\" && (typeof right === \"string\" || typeof right === \"number\")) return left + String(right);\n if (typeof left === \"number\" && typeof right === \"number\") return left + right;\n return UNRESOLVED;\n }\n if (ts.isArrayLiteralExpression(node)) {\n const items: Literal[] = [];\n for (const element of node.elements) {\n if (ts.isSpreadElement(element)) {\n const spread = next(element.expression);\n if (Array.isArray(spread)) items.push(...spread);\n else items.push(UNRESOLVED);\n } else {\n items.push(next(element));\n }\n }\n return items;\n }\n if (ts.isObjectLiteralExpression(node)) {\n const result: { [key: string]: Literal } = {};\n for (const property of node.properties) {\n if (ts.isPropertyAssignment(property)) {\n const key = propertyName(property.name);\n if (key !== undefined) result[key] = next(property.initializer);\n } else if (ts.isShorthandPropertyAssignment(property)) {\n result[property.name.text] = next(property.name);\n } else if (ts.isSpreadAssignment(property)) {\n const spread = next(property.expression);\n if (isLiteralObject(spread)) Object.assign(result, spread);\n else result[\"...\"] = UNRESOLVED;\n } else {\n result[\"...\"] = UNRESOLVED;\n }\n }\n return result;\n }\n if (ts.isIdentifier(node)) {\n if (node.text === \"undefined\") return UNRESOLVED;\n const initializer = this.constants.get(node.text);\n if (!initializer || seen.has(node.text)) return UNRESOLVED;\n return this.evaluate(initializer, depth + 1, new Set([...seen, node.text]));\n }\n if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {\n const target = next(node.expression);\n const key = ts.isPropertyAccessExpression(node)\n ? node.name.text\n : ts.isStringLiteralLike(node.argumentExpression)\n ? node.argumentExpression.text\n : undefined;\n if (key === undefined || !isLiteralObject(target) || !Object.hasOwn(target, key)) return UNRESOLVED;\n return target[key]!;\n }\n if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {\n const callee = node.expression.text;\n if (callee === \"verifiedFact\" && node.arguments[0]) return { status: \"verified\", value: next(node.arguments[0]) };\n if (callee === \"unknownFact\") return { status: \"unknown\" };\n if (callee === \"notApplicableFact\") return { status: \"not-applicable\" };\n }\n return UNRESOLVED;\n }\n}\n\nfunction propertyName(name: ts.PropertyName): string | undefined {\n if (ts.isIdentifier(name) || ts.isStringLiteralLike(name) || ts.isNumericLiteral(name)) return name.text;\n return undefined;\n}\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { SiteSystemFinding } from "../../checks.js";
|
|
2
|
+
import { type ParsedPage } from "./common.js";
|
|
3
|
+
import { type HtmlElement } from "./html.js";
|
|
4
|
+
export declare const T11_SERVICE_CLASS_MAP = "docs/service-classes.json";
|
|
5
|
+
export declare const T11_LICENCE_FILES: readonly ["src/data/businessEvidence.ts", "src/data/business.ts"];
|
|
6
|
+
/** The Home Building Compensation threshold: a condition that names HBC without an amount caps the job at this. */
|
|
7
|
+
export declare const T11_HBC_CAP = 20000;
|
|
8
|
+
export interface HeldLicenceClass {
|
|
9
|
+
name: string;
|
|
10
|
+
conditions: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
export interface HeldLicence {
|
|
13
|
+
name: string;
|
|
14
|
+
identifier: string;
|
|
15
|
+
jurisdiction?: string;
|
|
16
|
+
/** The licensee (`licensee`, or a legacy `holder`), shown beside the number when it differs from the trading name. */
|
|
17
|
+
licensee?: string;
|
|
18
|
+
classes: readonly HeldLicenceClass[];
|
|
19
|
+
expiresOn?: string;
|
|
20
|
+
checkedOn?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ServiceClassEntry {
|
|
23
|
+
path: string;
|
|
24
|
+
name: string;
|
|
25
|
+
/** Licence classes that cover the service. Any one is enough. Empty when the work needs no licence. */
|
|
26
|
+
classes: readonly string[];
|
|
27
|
+
/** The job value above which the work needs a licence. 0 (the default) means any value. */
|
|
28
|
+
licenceAbove: number;
|
|
29
|
+
/** The largest job the page advertises, when the site records it. */
|
|
30
|
+
jobValueMax?: number;
|
|
31
|
+
}
|
|
32
|
+
export type LicenceRead = {
|
|
33
|
+
status: "found";
|
|
34
|
+
licences: HeldLicence[];
|
|
35
|
+
file: string;
|
|
36
|
+
} | {
|
|
37
|
+
status: "none";
|
|
38
|
+
file: string;
|
|
39
|
+
} | {
|
|
40
|
+
status: "unreadable";
|
|
41
|
+
reason: string;
|
|
42
|
+
};
|
|
43
|
+
/** Reads the licences from the evidence data files without running them. */
|
|
44
|
+
export declare function readLicences(projectRoot: string): LicenceRead;
|
|
45
|
+
/** Reads the service-to-class map. Returns null when it does not exist and a string when it cannot be read. */
|
|
46
|
+
export declare function readServiceClassMap(projectRoot: string): ServiceClassEntry[] | string | null;
|
|
47
|
+
/** Whether a licence has expired on `asOf` (today in Sydney is after its expiry date), by site-core's licenceRenderState. */
|
|
48
|
+
export declare function isExpired(licence: Pick<HeldLicence, "expiresOn">, asOf: Date): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* The job value a class's conditions cap the work at, or null when they set no cap. A condition that says "up to",
|
|
51
|
+
* "limited to", "not exceeding" and the like before a dollar amount sets that cap. One that names Home Building
|
|
52
|
+
* Compensation (HBC) without an amount sets the HBC threshold.
|
|
53
|
+
*/
|
|
54
|
+
export declare function licenceConditionCap(conditions: readonly string[]): number | null;
|
|
55
|
+
export declare function serviceNeedsLicence(service: ServiceClassEntry): boolean;
|
|
56
|
+
export interface ServiceGateResult {
|
|
57
|
+
service: ServiceClassEntry;
|
|
58
|
+
/** Set when the service is covered by a current licence class. */
|
|
59
|
+
coveredBy?: {
|
|
60
|
+
licence: HeldLicence;
|
|
61
|
+
className: string;
|
|
62
|
+
};
|
|
63
|
+
/** The dollar cap the covering class's conditions set, when they set one. */
|
|
64
|
+
cap: number | null;
|
|
65
|
+
/** Why the service is not covered, in plain words. */
|
|
66
|
+
problem?: string;
|
|
67
|
+
}
|
|
68
|
+
/** Judges each service that needs a licence against the licences held on `asOf`. Pure. */
|
|
69
|
+
export declare function evaluateServiceClassGate(services: readonly ServiceClassEntry[], licences: readonly HeldLicence[], asOf: Date): ServiceGateResult[];
|
|
70
|
+
/** `price`, `lowPrice` and `highPrice` values in a page's JSON-LD (the Offer data), as numbers. */
|
|
71
|
+
export declare function structuredDataPrices(root: HtmlElement): number[];
|
|
72
|
+
export declare function checkT11(pages: readonly ParsedPage[], projectRoot: string, asOf: Date): SiteSystemFinding[];
|
|
73
|
+
//# sourceMappingURL=t11-licence-classes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"t11-licence-classes.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/enquiry/t11-licence-classes.ts"],"names":[],"mappings":"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"}
|