@brandlab-digital/conformance 3.15.0 → 3.16.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 +6 -1
- package/dist/current-release.js +5 -5
- package/dist/current-release.js.map +1 -1
- package/dist/site-system/checks.d.ts +6 -0
- package/dist/site-system/checks.d.ts.map +1 -1
- package/dist/site-system/checks.js +1 -0
- package/dist/site-system/checks.js.map +1 -1
- package/dist/site-system/rules/design/d4-distinctness.d.ts +2 -0
- package/dist/site-system/rules/design/d4-distinctness.d.ts.map +1 -1
- package/dist/site-system/rules/design/d4-distinctness.js +14 -2
- package/dist/site-system/rules/design/d4-distinctness.js.map +1 -1
- package/dist/site-system/rules/full/estate.d.ts +5 -0
- package/dist/site-system/rules/full/estate.d.ts.map +1 -1
- package/dist/site-system/rules/full/estate.js +5 -0
- package/dist/site-system/rules/full/estate.js.map +1 -1
- package/dist/site-system/rules/full/index.d.ts +2 -1
- package/dist/site-system/rules/full/index.d.ts.map +1 -1
- package/dist/site-system/rules/full/index.js +5 -2
- package/dist/site-system/rules/full/index.js.map +1 -1
- package/dist/site-system/rules/full/k12-manifests.d.ts +4 -0
- package/dist/site-system/rules/full/k12-manifests.d.ts.map +1 -1
- package/dist/site-system/rules/full/k12-manifests.js +11 -0
- package/dist/site-system/rules/full/k12-manifests.js.map +1 -1
- package/dist/site-system/rules/full/k13-signatures.d.ts +17 -0
- package/dist/site-system/rules/full/k13-signatures.d.ts.map +1 -0
- package/dist/site-system/rules/full/k13-signatures.js +74 -0
- package/dist/site-system/rules/full/k13-signatures.js.map +1 -0
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts +1 -1
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts.map +1 -1
- package/dist/site-system/rules/sections/k2-skin-coverage.js +2 -0
- package/dist/site-system/rules/sections/k2-skin-coverage.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"estate.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/estate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The estate the full tier reads: every page of the production build (the route catalogue as Next built it, from\n * `.next/prerender-manifest.json` and each page's prerendered HTML), the sitemap files in the build, and per page its\n * indexing, internal links, section manifest and the copy the location rules compare. Nothing is crawled: a site\n * checked with only a base URL and no build has just its sampled pages, and the estate-wide checks say so.\n *\n * A page's family is the one its section manifest names. A page without a manifest takes its family from the\n * sitemap file that lists it (`service-locations-*.xml`, `locations-*.xml`) or from the other pages of its stem (the\n * path with its place replaced: `/services/decking/{place}`), so a location page missing its manifest is still\n * found; a page built from the same dynamic route as a page with a manifest takes that page's family; the\n * representative service route is a service page; home is `/`. Other pages without a manifest have no known family.\n */\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { extractLinkGroups } from \"../../../page-standard.js\";\nimport type { SiteSystemPage } from \"../../samples.js\";\nimport { resolveStreamedHtml } from \"../../streamed-html.js\";\nimport { normalisePath, sectionId, topLevelSections } from \"../enquiry/common.js\";\nimport { attr, descendants, isHiddenFromPeople, normaliseText, parseHtml, readableLines, textOf, type HtmlElement, type HtmlNode } from \"../enquiry/html.js\";\nimport type { SiteEstatePaths } from \"@brandlab-digital/site-core/strategy\";\nimport { placeOfPath, type FullGeography, type PathAliases, type PathPlace } from \"./geography.js\";\n\n/** The section manifest as SectionSequence writes it (site-core `BrandlabSectionManifest`). */\nexport interface ManifestData {\n readonly version: number;\n readonly family: string;\n readonly page?: string;\n readonly cap: number;\n readonly order: \"default\" | \"recorded\";\n readonly planned: readonly { readonly id: string; readonly requirement: string }[];\n readonly rendered: readonly { readonly id: string; readonly section: string; readonly requirement: string; readonly tone?: string }[];\n readonly skipped: readonly { readonly id: string; readonly section: string; readonly requirement: string; readonly reason: string }[];\n readonly counted: number;\n readonly flags: readonly string[];\n}\n\nexport type ManifestState =\n | { readonly kind: \"none\" }\n | { readonly kind: \"invalid\"; readonly reason: string }\n | { readonly kind: \"many\"; readonly count: number }\n | { readonly kind: \"one\"; readonly manifest: ManifestData };\n\nexport const LOCATION_FAMILIES = [\"suburb\", \"service-in-suburb\", \"region\"] as const;\nexport type LocationFamily = (typeof LOCATION_FAMILIES)[number];\n\nexport function isLocationFamily(family: string | undefined): family is LocationFamily {\n return (LOCATION_FAMILIES as readonly string[]).includes(family ?? \"\");\n}\n\n/** The copy and parts of a location page the L4, L9 and L10 rules read. */\nexport interface LocationCopy {\n /** Readable lines of the page content, with the section they sit in (\"page\" outside any section). */\n readonly lines: readonly { readonly section: string; readonly text: string }[];\n readonly faqs: readonly { readonly question: string; readonly answer: string }[];\n /** The job cards of the nearby-jobs section; null when the page has none. */\n readonly jobs: readonly LocationJobCard[] | null;\n /** The price-guide section's text; null when the page has none. */\n readonly prices: string | null;\n readonly reviews: { readonly written: number; readonly googleLink: boolean; readonly rating: boolean } | null;\n readonly quoteForm: { readonly suburbField: boolean; readonly suburbValue: string } | null;\n readonly telLink: boolean;\n readonly callBar: boolean;\n}\n\n/** A nearby-job card: its text, and the job's suburb slug from the card's `data-suburb` (NearbyJobs) when it carries one. */\nexport interface LocationJobCard {\n readonly text: string;\n readonly place?: string;\n}\n\nexport interface EstatePage {\n readonly path: string;\n /** The app route Next built the page from (`/locations/[suburb]`), when known. */\n readonly srcRoute: string | undefined;\n /** The page's timed refresh in seconds as Next built it (`initialRevalidateSeconds`); false for never; absent when unknown. */\n readonly revalidate?: number | false;\n readonly indexable: boolean;\n readonly inSitemap: boolean;\n /** The sitemap file that lists the page, without its number and extension (`service-locations`). */\n readonly sitemapFile: string | undefined;\n /** Internal paths the page links to, once each. */\n readonly links: readonly string[];\n /** The main content's link groups (lists), as internal paths, for the neighbour order. */\n readonly linkGroups: readonly (readonly string[])[];\n readonly manifest: ManifestState;\n /** Top-level `data-bl-section` ids, in document order. */\n readonly sections: readonly string[];\n /**\n * Per top-level section (3.14.0): the `data-bl-slot` values inside it and the `slot:reason` pairs of its\n * `data-bl-slot-skip` attribute.\n */\n readonly slots?: ReadonlyMap<string, { readonly present: readonly string[]; readonly skipped: readonly { readonly slot: string; readonly reason: string }[] }>;\n readonly h1: string;\n /** The page's `<title>` text (3.14.0); absent when it has none. */\n readonly title?: string;\n readonly place: PathPlace | undefined;\n family: string | undefined;\n familySource: \"manifest\" | \"plan\" | \"sitemap\" | \"route\" | \"stem\" | \"path\" | undefined;\n copy: LocationCopy | undefined;\n}\n\nexport interface Estate {\n readonly pages: readonly EstatePage[];\n readonly byPath: ReadonlyMap<string, EstatePage>;\n /** True when the pages are the whole production build, not just a sample. */\n readonly complete: boolean;\n /** Paths listed in the build's sitemap files; null when the build holds no sitemap. */\n readonly sitemap: ReadonlySet<string> | null;\n /** Dynamic app routes in the build and how many pages each produced. */\n readonly dynamicRoutes: ReadonlyMap<string, number>;\n /** The timed refresh of pages a dynamic route renders on demand (`fallbackRevalidate`), for routes with a fallback. */\n readonly fallbackRevalidate: ReadonlyMap<string, number | false>;\n readonly buildDir: string;\n /** Routes the prerender manifest lists with no HTML in the build; `location` when the route is a location page's. */\n readonly missingHtml: readonly { readonly path: string; readonly location: boolean }[];\n}\n\nconst INTERNAL_ROUTES = new Set([\"/_not-found\", \"/_global-error\", \"/404\", \"/500\"]);\n\n/** Reads the estate: the whole build when `buildDir` holds one, otherwise the sampled pages. */\nexport function readEstate(input: {\n readonly pages: readonly SiteSystemPage[];\n readonly buildDir: string;\n readonly geography: FullGeography | null;\n /** Families known from elsewhere, by path (the representative service route). */\n readonly seeds?: Readonly<Record<string, string>>;\n /** The estate plan's public slugs (3.14.0). */\n readonly aliases?: PathAliases;\n /** The estate plan's family paths (3.14.0): they type region, suburb and service-in-suburb pages without a manifest. */\n readonly paths?: SiteEstatePaths;\n}): Estate {\n const missing: { path: string; srcRoute: string | undefined }[] = [];\n const manifest = readJson(join(input.buildDir, \"prerender-manifest.json\"));\n const sources = new Map<string, { html: string | (() => string); srcRoute?: string; headers?: Record<string, unknown>; revalidate?: number | false }>();\n const dynamicRoutes = new Map<string, number>();\n const fallbackRevalidate = new Map<string, number | false>();\n let complete = false;\n\n if (isRecord(manifest) && isRecord(manifest.routes)) {\n complete = true;\n const appDir = join(input.buildDir, \"server\", \"app\");\n for (const [route, entry] of isRecord(manifest.dynamicRoutes) ? Object.entries(manifest.dynamicRoutes) : []) {\n dynamicRoutes.set(route, 0);\n const fallback = isRecord(entry) ? entry.fallbackRevalidate : undefined;\n if (isRecord(entry) && entry.fallback !== false && (typeof fallback === \"number\" || fallback === false)) fallbackRevalidate.set(route, fallback);\n }\n for (const [rawPath, entry] of Object.entries(manifest.routes)) {\n if (!isRecord(entry) || !rawPath.startsWith(\"/\")) continue;\n const srcRoute = typeof entry.srcRoute === \"string\" ? entry.srcRoute : undefined;\n if (srcRoute && dynamicRoutes.has(srcRoute)) dynamicRoutes.set(srcRoute, (dynamicRoutes.get(srcRoute) ?? 0) + 1);\n if (entry.routeType !== undefined ? entry.routeType !== \"page\" : /\\.[a-z0-9]+$/i.test(rawPath)) continue;\n const path = normalisePath(rawPath);\n if (INTERNAL_ROUTES.has(path) || INTERNAL_ROUTES.has(srcRoute ?? \"\")) continue;\n const file = join(appDir, `${path === \"/\" ? \"/index\" : path}.html`);\n if (!existsSync(file)) {\n missing.push({ path, srcRoute });\n continue;\n }\n const meta = readJson(join(appDir, `${path === \"/\" ? \"/index\" : path}.meta`));\n const revalidate = entry.initialRevalidateSeconds;\n sources.set(path, {\n html: () => readFileSync(file, \"utf8\"),\n ...(srcRoute ? { srcRoute } : {}),\n ...(typeof revalidate === \"number\" || revalidate === false ? { revalidate } : {}),\n ...(isRecord(meta) && isRecord(meta.headers) ? { headers: meta.headers } : {}),\n });\n }\n }\n // Sampled pages fill in what the build does not have (a base-URL run without a build).\n for (const page of input.pages) {\n const path = normalisePath(page.path);\n if (!sources.has(path)) sources.set(path, { html: page.html });\n }\n\n const sitemapFiles = complete ? readSitemaps(join(input.buildDir, \"server\", \"app\")) : [];\n const sitemapOf = new Map<string, string>();\n for (const file of sitemapFiles) for (const path of file.paths) if (!sitemapOf.has(path)) sitemapOf.set(path, file.name);\n\n // First pass: one summary per page, links kept as written until every canonical host is known.\n const hosts = new Set<string>([\"localhost\"]);\n const read: { summary: EstatePage; hrefs: string[]; groups: string[][]; source: { html: string | (() => string) } }[] = [];\n for (const [path, source] of sources) {\n const html = resolveStreamedHtml(typeof source.html === \"string\" ? source.html : source.html());\n for (const match of html.matchAll(/<link\\b[^>]*\\brel=[\"']canonical[\"'][^>]*>/gi)) {\n const href = /\\bhref=[\"']([^\"']+)[\"']/i.exec(match[0])?.[1];\n try {\n if (href) {\n // A self-link may use the www or the bare host, whichever the canonical does not.\n const host = new URL(href).host;\n hosts.add(host);\n hosts.add(host.startsWith(\"www.\") ? host.slice(4) : `www.${host}`);\n }\n } catch {\n // A relative canonical names no host.\n }\n }\n const { summary, hrefs } = summarise(\n { path, html, ...(source.srcRoute ? { srcRoute: source.srcRoute } : {}), ...(source.headers ? { headers: source.headers } : {}), ...(source.revalidate !== undefined ? { revalidate: source.revalidate } : {}) },\n sitemapOf,\n input.geography,\n input.aliases,\n );\n read.push({ summary, hrefs, groups: extractLinkGroups(html), source });\n }\n const pages: EstatePage[] = [];\n for (const { summary, hrefs, groups } of read) {\n const links = new Set<string>();\n for (const href of hrefs) {\n const path = internalPath(href, summary.path, hosts);\n if (path && path !== summary.path) links.add(path);\n }\n pages.push({\n ...summary,\n links: [...links],\n linkGroups: groups.map((group) => group.flatMap((href) => internalPath(href, summary.path, hosts) ?? [])).filter((group) => group.length > 0),\n });\n }\n const byPath = new Map(pages.map((page) => [page.path, page]));\n inferFamilies(pages, input.seeds ?? {}, input.paths);\n // Second pass: the copy of location pages found without a manifest.\n for (const [index, page] of pages.entries()) {\n if (!isLocationFamily(page.family) || page.copy) continue;\n const source = read[index]!.source;\n page.copy = locationCopy(parseHtml(resolveStreamedHtml(typeof source.html === \"string\" ? source.html : source.html())));\n }\n const locationRoutes = new Set(pages.flatMap((page) => (isLocationFamily(page.family) && page.srcRoute && isGenerated(page.srcRoute) ? [page.srcRoute] : [])));\n const locationStems = new Set(pages.flatMap((page) => (isLocationFamily(page.family) && page.place ? [page.place.stem] : [])));\n const missingHtml = missing.map((item) => {\n const stem = input.geography ? placeOfPath(item.path, input.geography, input.aliases)?.stem : undefined;\n return { path: item.path, location: (item.srcRoute !== undefined && locationRoutes.has(item.srcRoute)) || (stem !== undefined && locationStems.has(stem)) };\n });\n return {\n pages,\n byPath,\n complete,\n sitemap: complete && sitemapFiles.length > 0 ? new Set(sitemapOf.keys()) : null,\n dynamicRoutes,\n fallbackRevalidate,\n buildDir: input.buildDir,\n missingHtml,\n };\n}\n\nfunction summarise(\n item: { path: string; html: string; srcRoute?: string; headers?: Record<string, unknown>; revalidate?: number | false },\n sitemapOf: ReadonlyMap<string, string>,\n geography: FullGeography | null,\n aliases?: PathAliases,\n): { summary: EstatePage; hrefs: string[] } {\n const root = parseHtml(item.html);\n const elements = descendants(root);\n const robots = elements\n .filter((element) => element.tag === \"meta\" && /^(robots|googlebot)$/i.test(attr(element, \"name\") ?? \"\"))\n .map((element) => attr(element, \"content\") ?? \"\")\n .join(\" \");\n const header = item.headers?.[\"x-robots-tag\"];\n const indexable = !/noindex/i.test(`${robots} ${typeof header === \"string\" ? header : \"\"}`);\n\n const hrefs = elements.filter((element) => element.tag === \"a\").map((element) => attr(element, \"href\") ?? \"\");\n const h1Element = elements.find((element) => element.tag === \"h1\");\n const place = geography ? placeOfPath(item.path, geography, aliases) : undefined;\n const page: EstatePage = {\n path: item.path,\n srcRoute: item.srcRoute,\n ...(item.revalidate !== undefined ? { revalidate: item.revalidate } : {}),\n indexable,\n inSitemap: sitemapOf.has(item.path),\n sitemapFile: sitemapOf.get(item.path),\n links: [],\n linkGroups: [],\n manifest: readManifest(elements),\n sections: topLevelSections(root).map(sectionId),\n slots: sectionSlots(root),\n h1: h1Element ? textOf(h1Element) : \"\",\n ...(titleOf(elements) !== undefined ? { title: titleOf(elements)! } : {}),\n place,\n family: undefined,\n familySource: undefined,\n copy: undefined,\n };\n if (page.manifest.kind === \"one\") {\n page.family = page.manifest.manifest.family;\n page.familySource = \"manifest\";\n if (isLocationFamily(page.family)) page.copy = locationCopy(root);\n }\n return { summary: page, hrefs };\n}\n\nfunction sectionSlots(root: HtmlElement): EstatePage[\"slots\"] {\n const slots = new Map<string, { present: string[]; skipped: { slot: string; reason: string }[] }>();\n for (const section of topLevelSections(root)) {\n const present = descendants(section).flatMap((element) => attr(element, \"data-bl-slot\") ?? []);\n const skipped = (attr(section, \"data-bl-slot-skip\") ?? \"\").split(/\\s+/).flatMap((pair) => {\n const [slot, reason] = pair.split(\":\");\n return slot && reason ? [{ slot, reason }] : [];\n });\n if (present.length > 0 || skipped.length > 0) slots.set(sectionId(section), { present, skipped });\n }\n return slots;\n}\n\nfunction titleOf(elements: readonly HtmlElement[]): string | undefined {\n const title = elements.find((element) => element.tag === \"title\");\n return title ? normaliseText(textOf(title)) : undefined;\n}\n\nfunction readManifest(elements: readonly HtmlElement[]): ManifestState {\n const scripts = elements.filter((element) => element.tag === \"script\" && attr(element, \"data-bl-manifest\") !== undefined);\n if (scripts.length === 0) return { kind: \"none\" };\n if (scripts.length > 1) return { kind: \"many\", count: scripts.length };\n const text = scripts[0]!.children.map((child) => (child.type === \"text\" ? child.text : \"\")).join(\"\");\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch {\n return { kind: \"invalid\", reason: \"is not valid JSON\" };\n }\n if (!isRecord(value) || typeof value.family !== \"string\" || !Array.isArray(value.planned) || !Array.isArray(value.rendered) || !Array.isArray(value.skipped)) {\n return { kind: \"invalid\", reason: \"lacks its family, planned, rendered or skipped lists\" };\n }\n const entries = (list: unknown[]) => list.every((entry) => isRecord(entry) && typeof entry.id === \"string\" && typeof entry.requirement === \"string\");\n if (!entries(value.planned) || !entries(value.rendered) || !entries(value.skipped)) {\n return { kind: \"invalid\", reason: \"has an entry without an id or requirement\" };\n }\n return {\n kind: \"one\",\n manifest: {\n version: typeof value.version === \"number\" ? value.version : 0,\n family: value.family,\n ...(typeof value.page === \"string\" ? { page: value.page } : {}),\n cap: typeof value.cap === \"number\" ? value.cap : Number.POSITIVE_INFINITY,\n order: value.order === \"recorded\" ? \"recorded\" : \"default\",\n planned: value.planned as ManifestData[\"planned\"],\n rendered: (value.rendered as Record<string, string>[]).map((entry) => ({\n id: entry.id!,\n section: typeof entry.section === \"string\" ? entry.section : entry.id!,\n requirement: entry.requirement!,\n })),\n skipped: (value.skipped as Record<string, string>[]).map((entry) => ({\n id: entry.id!,\n section: typeof entry.section === \"string\" ? entry.section : entry.id!,\n requirement: entry.requirement!,\n reason: typeof entry.reason === \"string\" ? entry.reason : \"\",\n })),\n counted: typeof value.counted === \"number\" ? value.counted : 0,\n flags: Array.isArray(value.flags) ? value.flags.filter((flag): flag is string => typeof flag === \"string\") : [],\n },\n };\n}\n\nconst SUBURB_STEM = /^\\/(?:locations?|areas?|suburbs?|service-areas?|areas-we-(?:service|serve)|regions?|where-we-work)\\/\\{place\\}$/;\n\n/** A dynamic route that builds one family (not a catch-all, which serves many). */\nfunction isGenerated(route: string): boolean {\n return route.includes(\"[\") && !route.includes(\"[...\") && !route.includes(\"[[...\");\n}\n\n/**\n * Families for pages without a manifest: the sitemap file, then the family of the other pages of their dynamic route,\n * the seeds (the representative service route), the family of their stem, then `/` as home.\n */\nfunction inferFamilies(pages: readonly EstatePage[], seeds: Readonly<Record<string, string>>, paths: SiteEstatePaths | undefined): void {\n // The estate plan's family paths come first: region and suburb pages can share a dynamic route with service pages\n // (AA's /tree-services/[slug]), so the route alone cannot type them.\n const parent = (template: string) => template.slice(0, template.lastIndexOf(\"/\"));\n const suburbParents = new Map<string, string>([\n ...(paths?.serviceInSuburb ?? []).map((template) => [parent(template), \"service-in-suburb\"] as const),\n ...(paths?.suburb !== undefined ? [[parent(paths.suburb), \"suburb\"] as const] : []),\n ]);\n const regionParents = new Set([paths?.region, ...(paths?.serviceInSuburb ?? [])].flatMap((template) => (template === undefined ? [] : [parent(template)])));\n for (const page of pages) {\n const at = parent(page.path);\n // The whole last segment is the place: \"/tree-services/tree-removal-sydney\" is a service page, not a suburb page.\n if (page.family !== undefined || !page.place || page.place.stem !== `${at}/{place}`) continue;\n const family = page.place.kind === \"region\" ? (regionParents.has(at) ? \"region\" : undefined) : suburbParents.get(at);\n if (family) {\n page.family = family;\n page.familySource = \"plan\";\n }\n }\n for (const page of pages) {\n if (page.family !== undefined || !page.sitemapFile) continue;\n const file = page.sitemapFile;\n if (/service-?locations?/.test(file)) page.family = page.place?.kind === \"region\" ? \"region\" : \"service-in-suburb\";\n else if (/locations?|areas?|suburbs?/.test(file)) page.family = page.place?.kind === \"region\" ? \"region\" : \"suburb\";\n if (page.family !== undefined) page.familySource = \"sitemap\";\n }\n // A dynamic route can build hubs and suburb pages alike, so pages match on the route and on the kind of place.\n const routeKey = (page: EstatePage) => `${page.srcRoute}|${page.place?.kind ?? \"\"}`;\n const counts = new Map<string, Map<string, number>>();\n for (const page of pages) {\n if (page.familySource !== \"manifest\" || !page.srcRoute || !isGenerated(page.srcRoute)) continue;\n const families = counts.get(routeKey(page)) ?? new Map<string, number>();\n families.set(page.family!, (families.get(page.family!) ?? 0) + 1);\n counts.set(routeKey(page), families);\n }\n const routeFamilies = new Map([...counts].map(([key, families]) => [key, [...families].sort((left, right) => right[1] - left[1])[0]![0]]));\n for (const page of pages) {\n if (page.family !== undefined) continue;\n const family = (page.srcRoute ? routeFamilies.get(routeKey(page)) : undefined) ?? seeds[page.path];\n if (family) {\n page.family = family;\n page.familySource = \"route\";\n }\n }\n // The other pages of a seeded page's dynamic route share its family.\n for (const page of pages) {\n if (page.family !== undefined || !page.srcRoute || !isGenerated(page.srcRoute)) continue;\n // Only pages naming the same kind of place: a route that builds service pages and suburb pages types them apart.\n const seeded = pages.find((other) => other.familySource === \"route\" && routeKey(other) === routeKey(page));\n if (seeded) {\n page.family = seeded.family;\n page.familySource = \"route\";\n }\n }\n const stems = new Map<string, string>();\n for (const page of pages) {\n if (!page.place || (page.family !== \"suburb\" && page.family !== \"service-in-suburb\")) continue;\n if (!stems.has(page.place.stem)) stems.set(page.place.stem, page.family);\n }\n // A stem that three or more suburbs share is a family of location pages even when nothing names it: suburb pages\n // under an areas folder (`/locations/{place}`), service-in-suburb pages otherwise.\n const unnamed = new Map<string, number>();\n for (const page of pages) {\n if (page.family === undefined && page.place?.kind === \"suburb\") unnamed.set(page.place.stem, (unnamed.get(page.place.stem) ?? 0) + 1);\n }\n for (const [stem, count] of unnamed) {\n if (count >= 3 && !stems.has(stem)) stems.set(stem, SUBURB_STEM.test(stem) ? \"suburb\" : \"service-in-suburb\");\n }\n for (const page of pages) {\n if (page.family !== undefined) continue;\n if (page.path === \"/\") {\n page.family = \"home\";\n page.familySource = \"path\";\n continue;\n }\n const family = page.place ? stems.get(page.place.stem) : undefined;\n if (!family || !page.place) continue;\n page.family = page.place.kind === \"region\" ? \"region\" : family;\n page.familySource = \"stem\";\n }\n}\n\n/** The page content a person reads, without the header, footer, navigation, call bar or drawer. */\nfunction contentRoot(root: HtmlElement): HtmlElement {\n return descendants(root).find((element) => element.tag === \"main\") ?? descendants(root).find((element) => element.tag === \"body\") ?? root;\n}\n\nconst CHROME = (element: HtmlElement) =>\n [\"header\", \"footer\", \"nav\"].includes(element.tag) || [\"header\", \"footer\", \"callbar\", \"drawer\", \"utility\"].includes(attr(element, \"data-bl\") ?? \"\");\n\nfunction linesOutsideChrome(element: HtmlElement): string[] {\n // readableLines has no skip, so chrome is cut from a shallow copy of the tree.\n const prune = (node: HtmlElement): HtmlElement => ({\n ...node,\n children: node.children.flatMap((child): HtmlNode[] => (child.type === \"element\" ? (CHROME(child) ? [] : [prune(child)]) : [child])),\n });\n return readableLines(prune(element)).map((line) => line.text);\n}\n\nfunction locationCopy(root: HtmlElement): LocationCopy {\n const elements = descendants(root);\n const sections = topLevelSections(root);\n const lines = sections.length > 0\n ? sections.flatMap((section) => readableLines(section).map((line) => ({ section: sectionId(section), text: line.text })))\n : linesOutsideChrome(contentRoot(root)).map((text) => ({ section: \"page\", text }));\n const sectionOf = (id: string) => elements.find((element) => attr(element, \"data-bl-section\") === id);\n\n // The FAQs section, or on a page without sections the disclosures that ask a question.\n const faqSection = sectionOf(\"faqs\");\n const faqScope = faqSection ?? contentRoot(root);\n const faqs: { question: string; answer: string }[] = [];\n for (const details of descendants(faqScope).filter((element) => element.tag === \"details\")) {\n const summary = details.children.find((child): child is HtmlElement => child.type === \"element\" && child.tag === \"summary\");\n if (!summary) continue;\n const question = textOf(summary);\n const answer = normaliseText(textOf(details, true, (element) => element === summary));\n if (question && (faqSection || question.endsWith(\"?\"))) faqs.push({ question, answer });\n }\n if (faqs.length === 0) {\n for (const term of descendants(faqScope).filter((element) => element.tag === \"dt\")) {\n const siblings = term.parent?.children.filter((child): child is HtmlElement => child.type === \"element\") ?? [];\n const definition = siblings[siblings.indexOf(term) + 1];\n const question = textOf(term);\n if (definition?.tag === \"dd\" && (faqSection || question.endsWith(\"?\"))) faqs.push({ question, answer: textOf(definition, true) });\n }\n }\n\n const jobsSection = sectionOf(\"nearby-jobs\");\n let jobs: LocationJobCard[] | null = null;\n if (jobsSection) {\n const cards = descendants(jobsSection).filter(\n (element) => (element.tag === \"li\" || element.tag === \"article\") && !descendants(element).some((inner) => inner.tag === \"li\" || inner.tag === \"article\"),\n );\n const headings = new Set(descendants(jobsSection).filter((element) => /^h[1-6]$/.test(element.tag)).map((element) => textOf(element)));\n // The job's place is structured data on the card (NearbyJobs renders `data-suburb`), so its outcome text is never\n // read for place names when the card says where the job was.\n const placeOf = (card: HtmlElement) => {\n const carrier = [card, ...descendants(card)].find((element) => attr(element, \"data-suburb\"));\n return carrier ? attr(carrier, \"data-suburb\")!.trim() : undefined;\n };\n jobs = cards.length > 0\n ? cards.flatMap((card) => {\n const text = textOf(card, true);\n const place = placeOf(card);\n return text ? [place ? { text, place } : { text }] : [];\n })\n : readableLines(jobsSection).map((line) => line.text).filter((text) => !headings.has(text)).map((text) => ({ text }));\n }\n\n const pricesSection = sectionOf(\"price-guide\");\n const reviewsSection = sectionOf(\"reviews\");\n const reviews = reviewsSection\n ? {\n written: descendants(reviewsSection).filter((element) => element.tag === \"blockquote\").length,\n googleLink: descendants(reviewsSection).some((element) => element.tag === \"a\" && /(?:^|\\.)google\\.|g\\.page|goo\\.gl/i.test(attr(element, \"href\") ?? \"\")),\n rating:\n descendants(reviewsSection).some((element) => attr(element, \"data-bl\") === \"rating-chip\") ||\n /\\b[1-5](?:\\.\\d)?\\s*(?:out of 5|stars?|★)|\\b[1-5]\\.\\d\\b/i.test(textOf(reviewsSection, true)),\n }\n : null;\n\n const forms = elements.filter((element) => element.tag === \"form\" && !isHiddenFromPeople(element));\n const form = forms.find((element) => attr(element, \"data-bl\") === \"quote-form\") ?? forms[0];\n let quoteForm: LocationCopy[\"quoteForm\"] = null;\n if (form) {\n const field = descendants(form).find(\n (element) =>\n element.tag === \"input\" &&\n (attr(element, \"autocomplete\") === \"address-level2\" || /suburb|location/i.test(`${attr(element, \"name\") ?? \"\"} ${attr(element, \"id\") ?? \"\"}`)),\n );\n quoteForm = { suburbField: field !== undefined, suburbValue: normaliseText(field ? (attr(field, \"value\") ?? \"\") : \"\") };\n }\n\n return {\n lines,\n faqs,\n jobs,\n prices: pricesSection ? textOf(pricesSection, true) : null,\n reviews,\n quoteForm,\n telLink: elements.some((element) => element.tag === \"a\" && /^tel:/i.test(attr(element, \"href\") ?? \"\")),\n callBar: elements.some((element) => attr(element, \"data-bl\") === \"callbar\"),\n };\n}\n\n/** An internal link's normalised path, or null for other sites, anchors on the same page, mail and phone links. */\nexport function internalPath(href: string, from: string, hosts: ReadonlySet<string>): string | null {\n const value = href.trim();\n if (!value || value.startsWith(\"#\") || /^(?:mailto|tel|sms|javascript|data):/i.test(value)) return null;\n let url: URL;\n try {\n url = new URL(value, `http://localhost${from}`);\n } catch {\n return null;\n }\n if (!/^https?:$/.test(url.protocol) || !hosts.has(url.host) && !hosts.has(url.hostname)) return null;\n let path: string;\n try {\n path = decodeURIComponent(url.pathname);\n } catch {\n path = url.pathname;\n }\n return normalisePath(path);\n}\n\ninterface SitemapFile {\n readonly name: string;\n readonly paths: readonly string[];\n}\n\n/** The URL sets in the build's prerendered sitemap files (`*.xml.body`); sitemap indexes are skipped. */\nfunction readSitemaps(appDir: string): SitemapFile[] {\n if (!existsSync(appDir)) return [];\n const files: SitemapFile[] = [];\n const visit = (directory: string) => {\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n const full = join(directory, entry.name);\n if (entry.isDirectory()) visit(full);\n else if (entry.name.endsWith(\".xml.body\")) {\n const xml = readFileSync(full, \"utf8\");\n if (!/<urlset\\b/i.test(xml)) continue;\n const paths: string[] = [];\n for (const match of xml.matchAll(/<loc>\\s*([^<\\s]+)\\s*<\\/loc>/gi)) {\n try {\n paths.push(normalisePath(new URL(match[1]!.replace(/&/g, \"&\")).pathname));\n } catch {\n // A loc that is not a URL lists no page.\n }\n }\n const name = relative(appDir, full).replace(/\\.xml\\.body$/, \"\").split(\"/\").pop()!.replace(/-\\d+$/, \"\");\n files.push({ name, paths });\n }\n }\n };\n visit(appDir);\n return files;\n}\n\nfunction readJson(file: string): unknown {\n if (!existsSync(file)) return undefined;\n try {\n return JSON.parse(readFileSync(file, \"utf8\"));\n } catch {\n return undefined;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"estate.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/estate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAmC,MAAM,oBAAoB,CAAC;AAE7J,OAAO,EAAE,WAAW,EAAwD,MAAM,gBAAgB,CAAC;AA8BnG,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,mBAAmB,EAAE,QAAQ,CAAU,CAAC;AAGpF,MAAM,UAAU,gBAAgB,CAAC,MAA0B;IACzD,OAAQ,iBAAuC,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;AACzE,CAAC;AAwED,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEnF,gGAAgG;AAChG,MAAM,UAAU,UAAU,CAAC,KAU1B;IACC,MAAM,OAAO,GAAqD,EAAE,CAAC;IACrE,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAgI,CAAC;IACxJ,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC7D,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACpD,QAAQ,GAAG,IAAI,CAAC;QAChB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QACrD,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC5G,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC5B,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC;YACxE,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK,IAAI,CAAC,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,KAAK,CAAC;gBAAE,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACnJ,CAAC;QACD,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC3D,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YACjF,IAAI,QAAQ,IAAI,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAAE,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACjH,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;gBAAE,SAAS;YACzG,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YACpC,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;gBAAE,SAAS;YAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC;YACpE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACjC,SAAS;YACX,CAAC;YACD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC;YAC9E,MAAM,UAAU,GAAG,KAAK,CAAC,wBAAwB,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE;gBAChB,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC;gBACtC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjC,GAAG,CAAC,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjF,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,uFAAuF;IACvF,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzF,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,YAAY;QAAE,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAEzH,+FAA+F;IAC/F,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7C,MAAM,IAAI,GAA8G,EAAE,CAAC;IAC3H,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAChG,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,6CAA6C,CAAC,EAAE,CAAC;YACjF,MAAM,IAAI,GAAG,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC5D,IAAI,CAAC;gBACH,IAAI,IAAI,EAAE,CAAC;oBACT,kFAAkF;oBAClF,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;oBAChC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBAChB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;gBACrE,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,sCAAsC;YACxC,CAAC;QACH,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,SAAS,CAClC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAChN,SAAS,EACT,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,OAAO,CACd,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACrD,IAAI,IAAI,IAAI,IAAI,KAAK,OAAO,CAAC,IAAI;gBAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QACD,KAAK,CAAC,IAAI,CAAC;YACT,GAAG,OAAO;YACV,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC;YACjB,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;SAC9I,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/D,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACrD,oEAAoE;IACpE,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI;YAAE,SAAS;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAE,CAAC,MAAM,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC,SAAS,CAAC,mBAAmB,CAAC,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1H,CAAC;IACD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/J,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/H,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACvC,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACxG,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IAC9J,CAAC,CAAC,CAAC;IACH,OAAO;QACL,KAAK;QACL,MAAM;QACN,QAAQ;QACR,OAAO,EAAE,QAAQ,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;QAC/E,aAAa;QACb,kBAAkB;QAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAChB,IAAuH,EACvH,SAAsC,EACtC,SAA+B,EAC/B,OAAqB;IAErB,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,QAAQ;SACpB,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,MAAM,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;SACxG,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;SAChD,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,cAAc,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAE5F,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9G,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,MAAM,IAAI,GAAe;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,GAAG,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,SAAS;QACT,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QACnC,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QACrC,KAAK,EAAE,EAAE;QACT,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC;QAChC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;QAC/C,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC;aAC/B,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,WAAW,CAAC;aACvD,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,IAAI,EAAE,CAAC;QAC7D,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC;QACzB,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;QACtC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,KAAK;QACL,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,SAAS;QACvB,IAAI,EAAE,SAAS;KAChB,CAAC;IACF,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC5C,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC;QAC/B,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,YAAY,CAAC,IAAiB;IACrC,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8E,CAAC;IACpG,KAAK,MAAM,OAAO,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/F,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACvF,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACvC,OAAO,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,CAAC,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,OAAO,CAAC,QAAgC;IAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC;IAClE,OAAO,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1D,CAAC;AAED,SAAS,YAAY,CAAC,QAAgC;IACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,KAAK,SAAS,CAAC,CAAC;IAC1H,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAClD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IACvE,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrG,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC1D,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7J,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,sDAAsD,EAAE,CAAC;IAC7F,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,IAAe,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC;IACrJ,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACnF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,2CAA2C,EAAE,CAAC;IAClF,CAAC;IACD,OAAO;QACL,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE;YACR,OAAO,EAAE,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC9D,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,GAAG,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,GAAG,EAAE,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB;YACzE,KAAK,EAAE,KAAK,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;YAC1D,OAAO,EAAE,KAAK,CAAC,OAAkC;YACjD,QAAQ,EAAG,KAAK,CAAC,QAAqC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACrE,EAAE,EAAE,KAAK,CAAC,EAAG;gBACb,OAAO,EAAE,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAG;gBACtE,WAAW,EAAE,KAAK,CAAC,WAAY;gBAC/B,GAAG,CAAC,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9E,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACnE,CAAC,CAAC;YACH,OAAO,EAAG,KAAK,CAAC,OAAoC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACnE,EAAE,EAAE,KAAK,CAAC,EAAG;gBACb,OAAO,EAAE,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAG;gBACtE,WAAW,EAAE,KAAK,CAAC,WAAY;gBAC/B,MAAM,EAAE,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;aAC7D,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC9D,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;SAChH;KACF,CAAC;AACJ,CAAC;AAED,MAAM,WAAW,GAAG,gHAAgH,CAAC;AAErI,mFAAmF;AACnF,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,KAA4B,EAAE,KAAuC,EAAE,KAAkC;IAC9H,kHAAkH;IAClH,qEAAqE;IACrE,MAAM,MAAM,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAClF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAiB;QAC5C,GAAG,CAAC,KAAK,EAAE,eAAe,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAU,CAAC;QACrG,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACpF,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,eAAe,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5J,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,kHAAkH;QAClH,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,EAAE,UAAU;YAAE,SAAS;QAC9F,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrH,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YACrB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,SAAS;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;QAC9B,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC;aAC9G,IAAI,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;QACpH,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;IAC/D,CAAC;IACD,+GAA+G;IAC/G,MAAM,QAAQ,GAAG,CAAC,IAAgB,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;IACpF,MAAM,MAAM,GAAG,IAAI,GAAG,EAA+B,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,YAAY,KAAK,UAAU,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,SAAS;QAChG,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,GAAG,EAAkB,CAAC;QACzE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAO,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3I,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,SAAS;QACxC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnG,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YACrB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,qEAAqE;IACrE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,SAAS;QACzF,iHAAiH;QACjH,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,KAAK,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3G,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC5B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,mBAAmB,CAAC;YAAE,SAAS;QAC/F,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3E,CAAC;IACD,iHAAiH;IACjH,mFAAmF;IACnF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxI,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QACpC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC/G,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,SAAS;QACxC,IAAI,IAAI,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YACrB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;YAC3B,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACnE,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,SAAS;QACrC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QAC/D,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,mGAAmG;AACnG,SAAS,WAAW,CAAC,IAAiB;IACpC,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC;AAC5I,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,OAAoB,EAAE,EAAE,CACtC,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;AAErJ,SAAS,kBAAkB,CAAC,OAAoB;IAC9C,+EAA+E;IAC/E,MAAM,KAAK,GAAG,CAAC,IAAiB,EAAe,EAAE,CAAC,CAAC;QACjD,GAAG,IAAI;QACP,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAc,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;KACrI,CAAC,CAAC;IACH,OAAO,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,YAAY,CAAC,IAAiB;IACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC;QAC/B,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACzH,CAAC,CAAC,kBAAkB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACrF,MAAM,SAAS,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,KAAK,EAAE,CAAC,CAAC;IAEtG,uFAAuF;IACvF,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,UAAU,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,IAAI,GAA2C,EAAE,CAAC;IACxD,KAAK,MAAM,OAAO,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,EAAE,CAAC;QAC3F,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAwB,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC;QAC5H,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC;QACtF,IAAI,QAAQ,IAAI,CAAC,UAAU,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,IAAI,CAAC,EAAE,CAAC;YACnF,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAwB,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YAC/G,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,UAAU,EAAE,GAAG,KAAK,IAAI,IAAI,CAAC,UAAU,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACpI,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;IAC7C,IAAI,IAAI,GAA6B,IAAI,CAAC;IAC1C,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CAC3C,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,KAAK,IAAI,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CACzJ,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACvI,kHAAkH;QAClH,6DAA6D;QAC7D,MAAM,OAAO,GAAG,CAAC,IAAiB,EAAE,EAAE;YACpC,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;YAC7F,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACpE,CAAC,CAAC;QACF,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBACrB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAChC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC5B,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,CAAC,CAAC;YACJ,CAAC,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1H,CAAC;IAED,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;IAC/C,MAAM,cAAc,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,cAAc;QAC5B,CAAC,CAAC;YACE,OAAO,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,YAAY,CAAC,CAAC,MAAM;YAC7F,UAAU,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,IAAI,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACvJ,MAAM,EACJ,WAAW,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,aAAa,CAAC;gBACzF,yDAAyD,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;SAC/F;QACH,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IACnG,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,YAAY,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5F,IAAI,SAAS,GAA8B,IAAI,CAAC;IAChD,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAClC,CAAC,OAAO,EAAE,EAAE,CACV,OAAO,CAAC,GAAG,KAAK,OAAO;YACvB,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,KAAK,gBAAgB,IAAI,kBAAkB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CACjJ,CAAC;QACF,SAAS,GAAG,EAAE,WAAW,EAAE,KAAK,KAAK,SAAS,EAAE,WAAW,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1H,CAAC;IAED,OAAO;QACL,KAAK;QACL,IAAI;QACJ,IAAI;QACJ,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QAC1D,OAAO;QACP,SAAS;QACT,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACtG,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,SAAS,CAAC;KAC5E,CAAC;AACJ,CAAC;AAED,mHAAmH;AACnH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,IAAY,EAAE,KAA0B;IACjF,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,uCAAuC,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACxG,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,mBAAmB,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACrG,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC;IACtB,CAAC;IACD,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAOD,yGAAyG;AACzG,SAAS,YAAY,CAAC,MAAc;IAClC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,CAAC,SAAiB,EAAE,EAAE;QAClC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,KAAK,CAAC,WAAW,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC;iBAChC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC1C,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACvC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC;oBAAE,SAAS;gBACtC,MAAM,KAAK,GAAa,EAAE,CAAC;gBAC3B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAC,+BAA+B,CAAC,EAAE,CAAC;oBAClE,IAAI,CAAC;wBACH,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;oBAChF,CAAC;oBAAC,MAAM,CAAC;wBACP,yCAAyC;oBAC3C,CAAC;gBACH,CAAC;gBACD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACvG,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,MAAM,CAAC,CAAC;IACd,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC","sourcesContent":["/**\n * The estate the full tier reads: every page of the production build (the route catalogue as Next built it, from\n * `.next/prerender-manifest.json` and each page's prerendered HTML), the sitemap files in the build, and per page its\n * indexing, internal links, section manifest and the copy the location rules compare. Nothing is crawled: a site\n * checked with only a base URL and no build has just its sampled pages, and the estate-wide checks say so.\n *\n * A page's family is the one its section manifest names. A page without a manifest takes its family from the\n * sitemap file that lists it (`service-locations-*.xml`, `locations-*.xml`) or from the other pages of its stem (the\n * path with its place replaced: `/services/decking/{place}`), so a location page missing its manifest is still\n * found; a page built from the same dynamic route as a page with a manifest takes that page's family; the\n * representative service route is a service page; home is `/`. Other pages without a manifest have no known family.\n */\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { extractLinkGroups } from \"../../../page-standard.js\";\nimport type { SiteSystemPage } from \"../../samples.js\";\nimport { resolveStreamedHtml } from \"../../streamed-html.js\";\nimport { normalisePath, sectionId, topLevelSections } from \"../enquiry/common.js\";\nimport { attr, descendants, isHiddenFromPeople, normaliseText, parseHtml, readableLines, textOf, type HtmlElement, type HtmlNode } from \"../enquiry/html.js\";\nimport type { SiteEstatePaths } from \"@brandlab-digital/site-core/strategy\";\nimport { placeOfPath, type FullGeography, type PathAliases, type PathPlace } from \"./geography.js\";\n\n/** The section manifest as SectionSequence writes it (site-core `BrandlabSectionManifest`). */\nexport interface ManifestData {\n readonly version: number;\n readonly family: string;\n readonly page?: string;\n readonly cap: number;\n readonly order: \"default\" | \"recorded\";\n readonly planned: readonly { readonly id: string; readonly requirement: string }[];\n /** A signature section (3.16.0) carries its name and, when the site placed it, the section it follows. */\n readonly rendered: readonly {\n readonly id: string;\n readonly section: string;\n readonly requirement: string;\n readonly tone?: string;\n readonly signature?: string;\n readonly after?: string;\n }[];\n readonly skipped: readonly { readonly id: string; readonly section: string; readonly requirement: string; readonly reason: string }[];\n readonly counted: number;\n readonly flags: readonly string[];\n}\n\nexport type ManifestState =\n | { readonly kind: \"none\" }\n | { readonly kind: \"invalid\"; readonly reason: string }\n | { readonly kind: \"many\"; readonly count: number }\n | { readonly kind: \"one\"; readonly manifest: ManifestData };\n\nexport const LOCATION_FAMILIES = [\"suburb\", \"service-in-suburb\", \"region\"] as const;\nexport type LocationFamily = (typeof LOCATION_FAMILIES)[number];\n\nexport function isLocationFamily(family: string | undefined): family is LocationFamily {\n return (LOCATION_FAMILIES as readonly string[]).includes(family ?? \"\");\n}\n\n/** The copy and parts of a location page the L4, L9 and L10 rules read. */\nexport interface LocationCopy {\n /** Readable lines of the page content, with the section they sit in (\"page\" outside any section). */\n readonly lines: readonly { readonly section: string; readonly text: string }[];\n readonly faqs: readonly { readonly question: string; readonly answer: string }[];\n /** The job cards of the nearby-jobs section; null when the page has none. */\n readonly jobs: readonly LocationJobCard[] | null;\n /** The price-guide section's text; null when the page has none. */\n readonly prices: string | null;\n readonly reviews: { readonly written: number; readonly googleLink: boolean; readonly rating: boolean } | null;\n readonly quoteForm: { readonly suburbField: boolean; readonly suburbValue: string } | null;\n readonly telLink: boolean;\n readonly callBar: boolean;\n}\n\n/** A nearby-job card: its text, and the job's suburb slug from the card's `data-suburb` (NearbyJobs) when it carries one. */\nexport interface LocationJobCard {\n readonly text: string;\n readonly place?: string;\n}\n\nexport interface EstatePage {\n readonly path: string;\n /** The app route Next built the page from (`/locations/[suburb]`), when known. */\n readonly srcRoute: string | undefined;\n /** The page's timed refresh in seconds as Next built it (`initialRevalidateSeconds`); false for never; absent when unknown. */\n readonly revalidate?: number | false;\n readonly indexable: boolean;\n readonly inSitemap: boolean;\n /** The sitemap file that lists the page, without its number and extension (`service-locations`). */\n readonly sitemapFile: string | undefined;\n /** Internal paths the page links to, once each. */\n readonly links: readonly string[];\n /** The main content's link groups (lists), as internal paths, for the neighbour order. */\n readonly linkGroups: readonly (readonly string[])[];\n readonly manifest: ManifestState;\n /** Top-level `data-bl-section` ids, in document order. */\n readonly sections: readonly string[];\n /** The `data-bl-signature` names of the top-level signature sections, in document order (3.16.0). */\n readonly signatures?: readonly string[];\n /**\n * Per top-level section (3.14.0): the `data-bl-slot` values inside it and the `slot:reason` pairs of its\n * `data-bl-slot-skip` attribute.\n */\n readonly slots?: ReadonlyMap<string, { readonly present: readonly string[]; readonly skipped: readonly { readonly slot: string; readonly reason: string }[] }>;\n readonly h1: string;\n /** The page's `<title>` text (3.14.0); absent when it has none. */\n readonly title?: string;\n readonly place: PathPlace | undefined;\n family: string | undefined;\n familySource: \"manifest\" | \"plan\" | \"sitemap\" | \"route\" | \"stem\" | \"path\" | undefined;\n copy: LocationCopy | undefined;\n}\n\nexport interface Estate {\n readonly pages: readonly EstatePage[];\n readonly byPath: ReadonlyMap<string, EstatePage>;\n /** True when the pages are the whole production build, not just a sample. */\n readonly complete: boolean;\n /** Paths listed in the build's sitemap files; null when the build holds no sitemap. */\n readonly sitemap: ReadonlySet<string> | null;\n /** Dynamic app routes in the build and how many pages each produced. */\n readonly dynamicRoutes: ReadonlyMap<string, number>;\n /** The timed refresh of pages a dynamic route renders on demand (`fallbackRevalidate`), for routes with a fallback. */\n readonly fallbackRevalidate: ReadonlyMap<string, number | false>;\n readonly buildDir: string;\n /** Routes the prerender manifest lists with no HTML in the build; `location` when the route is a location page's. */\n readonly missingHtml: readonly { readonly path: string; readonly location: boolean }[];\n}\n\nconst INTERNAL_ROUTES = new Set([\"/_not-found\", \"/_global-error\", \"/404\", \"/500\"]);\n\n/** Reads the estate: the whole build when `buildDir` holds one, otherwise the sampled pages. */\nexport function readEstate(input: {\n readonly pages: readonly SiteSystemPage[];\n readonly buildDir: string;\n readonly geography: FullGeography | null;\n /** Families known from elsewhere, by path (the representative service route). */\n readonly seeds?: Readonly<Record<string, string>>;\n /** The estate plan's public slugs (3.14.0). */\n readonly aliases?: PathAliases;\n /** The estate plan's family paths (3.14.0): they type region, suburb and service-in-suburb pages without a manifest. */\n readonly paths?: SiteEstatePaths;\n}): Estate {\n const missing: { path: string; srcRoute: string | undefined }[] = [];\n const manifest = readJson(join(input.buildDir, \"prerender-manifest.json\"));\n const sources = new Map<string, { html: string | (() => string); srcRoute?: string; headers?: Record<string, unknown>; revalidate?: number | false }>();\n const dynamicRoutes = new Map<string, number>();\n const fallbackRevalidate = new Map<string, number | false>();\n let complete = false;\n\n if (isRecord(manifest) && isRecord(manifest.routes)) {\n complete = true;\n const appDir = join(input.buildDir, \"server\", \"app\");\n for (const [route, entry] of isRecord(manifest.dynamicRoutes) ? Object.entries(manifest.dynamicRoutes) : []) {\n dynamicRoutes.set(route, 0);\n const fallback = isRecord(entry) ? entry.fallbackRevalidate : undefined;\n if (isRecord(entry) && entry.fallback !== false && (typeof fallback === \"number\" || fallback === false)) fallbackRevalidate.set(route, fallback);\n }\n for (const [rawPath, entry] of Object.entries(manifest.routes)) {\n if (!isRecord(entry) || !rawPath.startsWith(\"/\")) continue;\n const srcRoute = typeof entry.srcRoute === \"string\" ? entry.srcRoute : undefined;\n if (srcRoute && dynamicRoutes.has(srcRoute)) dynamicRoutes.set(srcRoute, (dynamicRoutes.get(srcRoute) ?? 0) + 1);\n if (entry.routeType !== undefined ? entry.routeType !== \"page\" : /\\.[a-z0-9]+$/i.test(rawPath)) continue;\n const path = normalisePath(rawPath);\n if (INTERNAL_ROUTES.has(path) || INTERNAL_ROUTES.has(srcRoute ?? \"\")) continue;\n const file = join(appDir, `${path === \"/\" ? \"/index\" : path}.html`);\n if (!existsSync(file)) {\n missing.push({ path, srcRoute });\n continue;\n }\n const meta = readJson(join(appDir, `${path === \"/\" ? \"/index\" : path}.meta`));\n const revalidate = entry.initialRevalidateSeconds;\n sources.set(path, {\n html: () => readFileSync(file, \"utf8\"),\n ...(srcRoute ? { srcRoute } : {}),\n ...(typeof revalidate === \"number\" || revalidate === false ? { revalidate } : {}),\n ...(isRecord(meta) && isRecord(meta.headers) ? { headers: meta.headers } : {}),\n });\n }\n }\n // Sampled pages fill in what the build does not have (a base-URL run without a build).\n for (const page of input.pages) {\n const path = normalisePath(page.path);\n if (!sources.has(path)) sources.set(path, { html: page.html });\n }\n\n const sitemapFiles = complete ? readSitemaps(join(input.buildDir, \"server\", \"app\")) : [];\n const sitemapOf = new Map<string, string>();\n for (const file of sitemapFiles) for (const path of file.paths) if (!sitemapOf.has(path)) sitemapOf.set(path, file.name);\n\n // First pass: one summary per page, links kept as written until every canonical host is known.\n const hosts = new Set<string>([\"localhost\"]);\n const read: { summary: EstatePage; hrefs: string[]; groups: string[][]; source: { html: string | (() => string) } }[] = [];\n for (const [path, source] of sources) {\n const html = resolveStreamedHtml(typeof source.html === \"string\" ? source.html : source.html());\n for (const match of html.matchAll(/<link\\b[^>]*\\brel=[\"']canonical[\"'][^>]*>/gi)) {\n const href = /\\bhref=[\"']([^\"']+)[\"']/i.exec(match[0])?.[1];\n try {\n if (href) {\n // A self-link may use the www or the bare host, whichever the canonical does not.\n const host = new URL(href).host;\n hosts.add(host);\n hosts.add(host.startsWith(\"www.\") ? host.slice(4) : `www.${host}`);\n }\n } catch {\n // A relative canonical names no host.\n }\n }\n const { summary, hrefs } = summarise(\n { path, html, ...(source.srcRoute ? { srcRoute: source.srcRoute } : {}), ...(source.headers ? { headers: source.headers } : {}), ...(source.revalidate !== undefined ? { revalidate: source.revalidate } : {}) },\n sitemapOf,\n input.geography,\n input.aliases,\n );\n read.push({ summary, hrefs, groups: extractLinkGroups(html), source });\n }\n const pages: EstatePage[] = [];\n for (const { summary, hrefs, groups } of read) {\n const links = new Set<string>();\n for (const href of hrefs) {\n const path = internalPath(href, summary.path, hosts);\n if (path && path !== summary.path) links.add(path);\n }\n pages.push({\n ...summary,\n links: [...links],\n linkGroups: groups.map((group) => group.flatMap((href) => internalPath(href, summary.path, hosts) ?? [])).filter((group) => group.length > 0),\n });\n }\n const byPath = new Map(pages.map((page) => [page.path, page]));\n inferFamilies(pages, input.seeds ?? {}, input.paths);\n // Second pass: the copy of location pages found without a manifest.\n for (const [index, page] of pages.entries()) {\n if (!isLocationFamily(page.family) || page.copy) continue;\n const source = read[index]!.source;\n page.copy = locationCopy(parseHtml(resolveStreamedHtml(typeof source.html === \"string\" ? source.html : source.html())));\n }\n const locationRoutes = new Set(pages.flatMap((page) => (isLocationFamily(page.family) && page.srcRoute && isGenerated(page.srcRoute) ? [page.srcRoute] : [])));\n const locationStems = new Set(pages.flatMap((page) => (isLocationFamily(page.family) && page.place ? [page.place.stem] : [])));\n const missingHtml = missing.map((item) => {\n const stem = input.geography ? placeOfPath(item.path, input.geography, input.aliases)?.stem : undefined;\n return { path: item.path, location: (item.srcRoute !== undefined && locationRoutes.has(item.srcRoute)) || (stem !== undefined && locationStems.has(stem)) };\n });\n return {\n pages,\n byPath,\n complete,\n sitemap: complete && sitemapFiles.length > 0 ? new Set(sitemapOf.keys()) : null,\n dynamicRoutes,\n fallbackRevalidate,\n buildDir: input.buildDir,\n missingHtml,\n };\n}\n\nfunction summarise(\n item: { path: string; html: string; srcRoute?: string; headers?: Record<string, unknown>; revalidate?: number | false },\n sitemapOf: ReadonlyMap<string, string>,\n geography: FullGeography | null,\n aliases?: PathAliases,\n): { summary: EstatePage; hrefs: string[] } {\n const root = parseHtml(item.html);\n const elements = descendants(root);\n const robots = elements\n .filter((element) => element.tag === \"meta\" && /^(robots|googlebot)$/i.test(attr(element, \"name\") ?? \"\"))\n .map((element) => attr(element, \"content\") ?? \"\")\n .join(\" \");\n const header = item.headers?.[\"x-robots-tag\"];\n const indexable = !/noindex/i.test(`${robots} ${typeof header === \"string\" ? header : \"\"}`);\n\n const hrefs = elements.filter((element) => element.tag === \"a\").map((element) => attr(element, \"href\") ?? \"\");\n const h1Element = elements.find((element) => element.tag === \"h1\");\n const place = geography ? placeOfPath(item.path, geography, aliases) : undefined;\n const page: EstatePage = {\n path: item.path,\n srcRoute: item.srcRoute,\n ...(item.revalidate !== undefined ? { revalidate: item.revalidate } : {}),\n indexable,\n inSitemap: sitemapOf.has(item.path),\n sitemapFile: sitemapOf.get(item.path),\n links: [],\n linkGroups: [],\n manifest: readManifest(elements),\n sections: topLevelSections(root).map(sectionId),\n signatures: topLevelSections(root)\n .filter((section) => sectionId(section) === \"signature\")\n .map((section) => attr(section, \"data-bl-signature\") ?? \"\"),\n slots: sectionSlots(root),\n h1: h1Element ? textOf(h1Element) : \"\",\n ...(titleOf(elements) !== undefined ? { title: titleOf(elements)! } : {}),\n place,\n family: undefined,\n familySource: undefined,\n copy: undefined,\n };\n if (page.manifest.kind === \"one\") {\n page.family = page.manifest.manifest.family;\n page.familySource = \"manifest\";\n if (isLocationFamily(page.family)) page.copy = locationCopy(root);\n }\n return { summary: page, hrefs };\n}\n\nfunction sectionSlots(root: HtmlElement): EstatePage[\"slots\"] {\n const slots = new Map<string, { present: string[]; skipped: { slot: string; reason: string }[] }>();\n for (const section of topLevelSections(root)) {\n const present = descendants(section).flatMap((element) => attr(element, \"data-bl-slot\") ?? []);\n const skipped = (attr(section, \"data-bl-slot-skip\") ?? \"\").split(/\\s+/).flatMap((pair) => {\n const [slot, reason] = pair.split(\":\");\n return slot && reason ? [{ slot, reason }] : [];\n });\n if (present.length > 0 || skipped.length > 0) slots.set(sectionId(section), { present, skipped });\n }\n return slots;\n}\n\nfunction titleOf(elements: readonly HtmlElement[]): string | undefined {\n const title = elements.find((element) => element.tag === \"title\");\n return title ? normaliseText(textOf(title)) : undefined;\n}\n\nfunction readManifest(elements: readonly HtmlElement[]): ManifestState {\n const scripts = elements.filter((element) => element.tag === \"script\" && attr(element, \"data-bl-manifest\") !== undefined);\n if (scripts.length === 0) return { kind: \"none\" };\n if (scripts.length > 1) return { kind: \"many\", count: scripts.length };\n const text = scripts[0]!.children.map((child) => (child.type === \"text\" ? child.text : \"\")).join(\"\");\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch {\n return { kind: \"invalid\", reason: \"is not valid JSON\" };\n }\n if (!isRecord(value) || typeof value.family !== \"string\" || !Array.isArray(value.planned) || !Array.isArray(value.rendered) || !Array.isArray(value.skipped)) {\n return { kind: \"invalid\", reason: \"lacks its family, planned, rendered or skipped lists\" };\n }\n const entries = (list: unknown[]) => list.every((entry) => isRecord(entry) && typeof entry.id === \"string\" && typeof entry.requirement === \"string\");\n if (!entries(value.planned) || !entries(value.rendered) || !entries(value.skipped)) {\n return { kind: \"invalid\", reason: \"has an entry without an id or requirement\" };\n }\n return {\n kind: \"one\",\n manifest: {\n version: typeof value.version === \"number\" ? value.version : 0,\n family: value.family,\n ...(typeof value.page === \"string\" ? { page: value.page } : {}),\n cap: typeof value.cap === \"number\" ? value.cap : Number.POSITIVE_INFINITY,\n order: value.order === \"recorded\" ? \"recorded\" : \"default\",\n planned: value.planned as ManifestData[\"planned\"],\n rendered: (value.rendered as Record<string, string>[]).map((entry) => ({\n id: entry.id!,\n section: typeof entry.section === \"string\" ? entry.section : entry.id!,\n requirement: entry.requirement!,\n ...(typeof entry.signature === \"string\" ? { signature: entry.signature } : {}),\n ...(typeof entry.after === \"string\" ? { after: entry.after } : {}),\n })),\n skipped: (value.skipped as Record<string, string>[]).map((entry) => ({\n id: entry.id!,\n section: typeof entry.section === \"string\" ? entry.section : entry.id!,\n requirement: entry.requirement!,\n reason: typeof entry.reason === \"string\" ? entry.reason : \"\",\n })),\n counted: typeof value.counted === \"number\" ? value.counted : 0,\n flags: Array.isArray(value.flags) ? value.flags.filter((flag): flag is string => typeof flag === \"string\") : [],\n },\n };\n}\n\nconst SUBURB_STEM = /^\\/(?:locations?|areas?|suburbs?|service-areas?|areas-we-(?:service|serve)|regions?|where-we-work)\\/\\{place\\}$/;\n\n/** A dynamic route that builds one family (not a catch-all, which serves many). */\nfunction isGenerated(route: string): boolean {\n return route.includes(\"[\") && !route.includes(\"[...\") && !route.includes(\"[[...\");\n}\n\n/**\n * Families for pages without a manifest: the sitemap file, then the family of the other pages of their dynamic route,\n * the seeds (the representative service route), the family of their stem, then `/` as home.\n */\nfunction inferFamilies(pages: readonly EstatePage[], seeds: Readonly<Record<string, string>>, paths: SiteEstatePaths | undefined): void {\n // The estate plan's family paths come first: region and suburb pages can share a dynamic route with service pages\n // (AA's /tree-services/[slug]), so the route alone cannot type them.\n const parent = (template: string) => template.slice(0, template.lastIndexOf(\"/\"));\n const suburbParents = new Map<string, string>([\n ...(paths?.serviceInSuburb ?? []).map((template) => [parent(template), \"service-in-suburb\"] as const),\n ...(paths?.suburb !== undefined ? [[parent(paths.suburb), \"suburb\"] as const] : []),\n ]);\n const regionParents = new Set([paths?.region, ...(paths?.serviceInSuburb ?? [])].flatMap((template) => (template === undefined ? [] : [parent(template)])));\n for (const page of pages) {\n const at = parent(page.path);\n // The whole last segment is the place: \"/tree-services/tree-removal-sydney\" is a service page, not a suburb page.\n if (page.family !== undefined || !page.place || page.place.stem !== `${at}/{place}`) continue;\n const family = page.place.kind === \"region\" ? (regionParents.has(at) ? \"region\" : undefined) : suburbParents.get(at);\n if (family) {\n page.family = family;\n page.familySource = \"plan\";\n }\n }\n for (const page of pages) {\n if (page.family !== undefined || !page.sitemapFile) continue;\n const file = page.sitemapFile;\n if (/service-?locations?/.test(file)) page.family = page.place?.kind === \"region\" ? \"region\" : \"service-in-suburb\";\n else if (/locations?|areas?|suburbs?/.test(file)) page.family = page.place?.kind === \"region\" ? \"region\" : \"suburb\";\n if (page.family !== undefined) page.familySource = \"sitemap\";\n }\n // A dynamic route can build hubs and suburb pages alike, so pages match on the route and on the kind of place.\n const routeKey = (page: EstatePage) => `${page.srcRoute}|${page.place?.kind ?? \"\"}`;\n const counts = new Map<string, Map<string, number>>();\n for (const page of pages) {\n if (page.familySource !== \"manifest\" || !page.srcRoute || !isGenerated(page.srcRoute)) continue;\n const families = counts.get(routeKey(page)) ?? new Map<string, number>();\n families.set(page.family!, (families.get(page.family!) ?? 0) + 1);\n counts.set(routeKey(page), families);\n }\n const routeFamilies = new Map([...counts].map(([key, families]) => [key, [...families].sort((left, right) => right[1] - left[1])[0]![0]]));\n for (const page of pages) {\n if (page.family !== undefined) continue;\n const family = (page.srcRoute ? routeFamilies.get(routeKey(page)) : undefined) ?? seeds[page.path];\n if (family) {\n page.family = family;\n page.familySource = \"route\";\n }\n }\n // The other pages of a seeded page's dynamic route share its family.\n for (const page of pages) {\n if (page.family !== undefined || !page.srcRoute || !isGenerated(page.srcRoute)) continue;\n // Only pages naming the same kind of place: a route that builds service pages and suburb pages types them apart.\n const seeded = pages.find((other) => other.familySource === \"route\" && routeKey(other) === routeKey(page));\n if (seeded) {\n page.family = seeded.family;\n page.familySource = \"route\";\n }\n }\n const stems = new Map<string, string>();\n for (const page of pages) {\n if (!page.place || (page.family !== \"suburb\" && page.family !== \"service-in-suburb\")) continue;\n if (!stems.has(page.place.stem)) stems.set(page.place.stem, page.family);\n }\n // A stem that three or more suburbs share is a family of location pages even when nothing names it: suburb pages\n // under an areas folder (`/locations/{place}`), service-in-suburb pages otherwise.\n const unnamed = new Map<string, number>();\n for (const page of pages) {\n if (page.family === undefined && page.place?.kind === \"suburb\") unnamed.set(page.place.stem, (unnamed.get(page.place.stem) ?? 0) + 1);\n }\n for (const [stem, count] of unnamed) {\n if (count >= 3 && !stems.has(stem)) stems.set(stem, SUBURB_STEM.test(stem) ? \"suburb\" : \"service-in-suburb\");\n }\n for (const page of pages) {\n if (page.family !== undefined) continue;\n if (page.path === \"/\") {\n page.family = \"home\";\n page.familySource = \"path\";\n continue;\n }\n const family = page.place ? stems.get(page.place.stem) : undefined;\n if (!family || !page.place) continue;\n page.family = page.place.kind === \"region\" ? \"region\" : family;\n page.familySource = \"stem\";\n }\n}\n\n/** The page content a person reads, without the header, footer, navigation, call bar or drawer. */\nfunction contentRoot(root: HtmlElement): HtmlElement {\n return descendants(root).find((element) => element.tag === \"main\") ?? descendants(root).find((element) => element.tag === \"body\") ?? root;\n}\n\nconst CHROME = (element: HtmlElement) =>\n [\"header\", \"footer\", \"nav\"].includes(element.tag) || [\"header\", \"footer\", \"callbar\", \"drawer\", \"utility\"].includes(attr(element, \"data-bl\") ?? \"\");\n\nfunction linesOutsideChrome(element: HtmlElement): string[] {\n // readableLines has no skip, so chrome is cut from a shallow copy of the tree.\n const prune = (node: HtmlElement): HtmlElement => ({\n ...node,\n children: node.children.flatMap((child): HtmlNode[] => (child.type === \"element\" ? (CHROME(child) ? [] : [prune(child)]) : [child])),\n });\n return readableLines(prune(element)).map((line) => line.text);\n}\n\nfunction locationCopy(root: HtmlElement): LocationCopy {\n const elements = descendants(root);\n const sections = topLevelSections(root);\n const lines = sections.length > 0\n ? sections.flatMap((section) => readableLines(section).map((line) => ({ section: sectionId(section), text: line.text })))\n : linesOutsideChrome(contentRoot(root)).map((text) => ({ section: \"page\", text }));\n const sectionOf = (id: string) => elements.find((element) => attr(element, \"data-bl-section\") === id);\n\n // The FAQs section, or on a page without sections the disclosures that ask a question.\n const faqSection = sectionOf(\"faqs\");\n const faqScope = faqSection ?? contentRoot(root);\n const faqs: { question: string; answer: string }[] = [];\n for (const details of descendants(faqScope).filter((element) => element.tag === \"details\")) {\n const summary = details.children.find((child): child is HtmlElement => child.type === \"element\" && child.tag === \"summary\");\n if (!summary) continue;\n const question = textOf(summary);\n const answer = normaliseText(textOf(details, true, (element) => element === summary));\n if (question && (faqSection || question.endsWith(\"?\"))) faqs.push({ question, answer });\n }\n if (faqs.length === 0) {\n for (const term of descendants(faqScope).filter((element) => element.tag === \"dt\")) {\n const siblings = term.parent?.children.filter((child): child is HtmlElement => child.type === \"element\") ?? [];\n const definition = siblings[siblings.indexOf(term) + 1];\n const question = textOf(term);\n if (definition?.tag === \"dd\" && (faqSection || question.endsWith(\"?\"))) faqs.push({ question, answer: textOf(definition, true) });\n }\n }\n\n const jobsSection = sectionOf(\"nearby-jobs\");\n let jobs: LocationJobCard[] | null = null;\n if (jobsSection) {\n const cards = descendants(jobsSection).filter(\n (element) => (element.tag === \"li\" || element.tag === \"article\") && !descendants(element).some((inner) => inner.tag === \"li\" || inner.tag === \"article\"),\n );\n const headings = new Set(descendants(jobsSection).filter((element) => /^h[1-6]$/.test(element.tag)).map((element) => textOf(element)));\n // The job's place is structured data on the card (NearbyJobs renders `data-suburb`), so its outcome text is never\n // read for place names when the card says where the job was.\n const placeOf = (card: HtmlElement) => {\n const carrier = [card, ...descendants(card)].find((element) => attr(element, \"data-suburb\"));\n return carrier ? attr(carrier, \"data-suburb\")!.trim() : undefined;\n };\n jobs = cards.length > 0\n ? cards.flatMap((card) => {\n const text = textOf(card, true);\n const place = placeOf(card);\n return text ? [place ? { text, place } : { text }] : [];\n })\n : readableLines(jobsSection).map((line) => line.text).filter((text) => !headings.has(text)).map((text) => ({ text }));\n }\n\n const pricesSection = sectionOf(\"price-guide\");\n const reviewsSection = sectionOf(\"reviews\");\n const reviews = reviewsSection\n ? {\n written: descendants(reviewsSection).filter((element) => element.tag === \"blockquote\").length,\n googleLink: descendants(reviewsSection).some((element) => element.tag === \"a\" && /(?:^|\\.)google\\.|g\\.page|goo\\.gl/i.test(attr(element, \"href\") ?? \"\")),\n rating:\n descendants(reviewsSection).some((element) => attr(element, \"data-bl\") === \"rating-chip\") ||\n /\\b[1-5](?:\\.\\d)?\\s*(?:out of 5|stars?|★)|\\b[1-5]\\.\\d\\b/i.test(textOf(reviewsSection, true)),\n }\n : null;\n\n const forms = elements.filter((element) => element.tag === \"form\" && !isHiddenFromPeople(element));\n const form = forms.find((element) => attr(element, \"data-bl\") === \"quote-form\") ?? forms[0];\n let quoteForm: LocationCopy[\"quoteForm\"] = null;\n if (form) {\n const field = descendants(form).find(\n (element) =>\n element.tag === \"input\" &&\n (attr(element, \"autocomplete\") === \"address-level2\" || /suburb|location/i.test(`${attr(element, \"name\") ?? \"\"} ${attr(element, \"id\") ?? \"\"}`)),\n );\n quoteForm = { suburbField: field !== undefined, suburbValue: normaliseText(field ? (attr(field, \"value\") ?? \"\") : \"\") };\n }\n\n return {\n lines,\n faqs,\n jobs,\n prices: pricesSection ? textOf(pricesSection, true) : null,\n reviews,\n quoteForm,\n telLink: elements.some((element) => element.tag === \"a\" && /^tel:/i.test(attr(element, \"href\") ?? \"\")),\n callBar: elements.some((element) => attr(element, \"data-bl\") === \"callbar\"),\n };\n}\n\n/** An internal link's normalised path, or null for other sites, anchors on the same page, mail and phone links. */\nexport function internalPath(href: string, from: string, hosts: ReadonlySet<string>): string | null {\n const value = href.trim();\n if (!value || value.startsWith(\"#\") || /^(?:mailto|tel|sms|javascript|data):/i.test(value)) return null;\n let url: URL;\n try {\n url = new URL(value, `http://localhost${from}`);\n } catch {\n return null;\n }\n if (!/^https?:$/.test(url.protocol) || !hosts.has(url.host) && !hosts.has(url.hostname)) return null;\n let path: string;\n try {\n path = decodeURIComponent(url.pathname);\n } catch {\n path = url.pathname;\n }\n return normalisePath(path);\n}\n\ninterface SitemapFile {\n readonly name: string;\n readonly paths: readonly string[];\n}\n\n/** The URL sets in the build's prerendered sitemap files (`*.xml.body`); sitemap indexes are skipped. */\nfunction readSitemaps(appDir: string): SitemapFile[] {\n if (!existsSync(appDir)) return [];\n const files: SitemapFile[] = [];\n const visit = (directory: string) => {\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n const full = join(directory, entry.name);\n if (entry.isDirectory()) visit(full);\n else if (entry.name.endsWith(\".xml.body\")) {\n const xml = readFileSync(full, \"utf8\");\n if (!/<urlset\\b/i.test(xml)) continue;\n const paths: string[] = [];\n for (const match of xml.matchAll(/<loc>\\s*([^<\\s]+)\\s*<\\/loc>/gi)) {\n try {\n paths.push(normalisePath(new URL(match[1]!.replace(/&/g, \"&\")).pathname));\n } catch {\n // A loc that is not a URL lists no page.\n }\n }\n const name = relative(appDir, full).replace(/\\.xml\\.body$/, \"\").split(\"/\").pop()!.replace(/-\\d+$/, \"\");\n files.push({ name, paths });\n }\n }\n };\n visit(appDir);\n return files;\n}\n\nfunction readJson(file: string): unknown {\n if (!existsSync(file)) return undefined;\n try {\n return JSON.parse(readFileSync(file, \"utf8\"));\n } catch {\n return undefined;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n"]}
|
|
@@ -7,6 +7,7 @@ export { headingPhrase } from "./e10-phrases.js";
|
|
|
7
7
|
export { readEstate, type Estate, type EstatePage, type LocationCopy, type ManifestData } from "./estate.js";
|
|
8
8
|
export { defineFullGeography, loadFullGeography, placeOfPath, type FullGeography, type FullGeographyInput, type PathAliases } from "./geography.js";
|
|
9
9
|
export { K12_FAMILIES, isDataBackedReason } from "./k12-manifests.js";
|
|
10
|
+
export { K13_SIGNATURE_LIMITS, signatureKey } from "./k13-signatures.js";
|
|
10
11
|
export { L3_MAX_LIST, L3_MIN_LIST, L3_TOLERANCE_KM } from "./l3-neighbours.js";
|
|
11
12
|
export { L4_MIN_ROTATION_PAGES, L4_MIN_TEMPLATE_WORDS } from "./l4-local-copy.js";
|
|
12
13
|
export { yearStamp } from "./l10-location-copy.js";
|
|
@@ -16,7 +17,7 @@ export { sydneyDay } from "./loc-index.js";
|
|
|
16
17
|
export { W3_FAMILIES, W3_MIN_REVALIDATE_SECONDS, refreshInterval } from "./w3-refresh.js";
|
|
17
18
|
export { ESTATE_PLAN_SNAPSHOT_FILE, FULL_STRATEGY_FILE, WAVE_MAX_GAP_DAYS, WAVE_MIN_GAP_DAYS, matchesWaveRoute, normalisePhrase, readFullStrategy, waveScheduleProblems } from "./strategy.js";
|
|
18
19
|
/** The full-tier checks this module runs, in the order their findings are returned. */
|
|
19
|
-
export declare const FULL_TIER_CHECK_IDS: readonly ["K12", "K12-slots", "E1-pattern", "E5", "E10", "L3", "L4", "L6", "L7", "L8", "L9", "L10", "S4", "LOC-INDEX", "W3"];
|
|
20
|
+
export declare const FULL_TIER_CHECK_IDS: readonly ["K12", "K12-slots", "K13", "E1-pattern", "E5", "E10", "L3", "L4", "L6", "L7", "L8", "L9", "L10", "S4", "LOC-INDEX", "W3"];
|
|
20
21
|
export interface FullTierRuleOptions {
|
|
21
22
|
/** The day waves are judged on. Defaults to now. */
|
|
22
23
|
readonly asOf?: Date;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/full/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,OAAO,EAAqB,KAAK,aAAa,EAAoB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/full/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,OAAO,EAAqB,KAAK,aAAa,EAAoB,MAAM,gBAAgB,CAAC;AAezF,OAAO,EAAE,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACpJ,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1F,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC1H,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE/L,uFAAuF;AACvF,eAAO,MAAM,mBAAmB,qIAA6K,CAAC;AAE9M,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;IACrB,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,oGAAoG;IACpG,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC1C,uGAAuG;IACvG,QAAQ,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;CACrD;AA8CD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAuDvC"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The full-tier rules (release 3.12.0): page families, location estates, section manifests, links and the local data
|
|
3
3
|
* contract. They read the production build's route catalogue and pages (`.next`), the project's strategy record and
|
|
4
4
|
* source, and the site's installed site-core (geography and section orders), and return findings for the ready report:
|
|
5
|
-
* K12 (families), K12-slots and E1-pattern (3.14.0), E5, E10, L3, L4, L6, L7, L8, L9, L10 (location), S4, the location indexing guard and, from 3.13.0,
|
|
5
|
+
* K12 (families), K12-slots and E1-pattern (3.14.0), K13 (signature sections, 3.16.0), E5, E10, L3, L4, L6, L7, L8, L9, L10 (location), S4, the location indexing guard and, from 3.13.0,
|
|
6
6
|
* W3 (estate refresh). The runner has the signature the ready gate registers.
|
|
7
7
|
*/
|
|
8
8
|
import { join } from "node:path";
|
|
@@ -14,6 +14,7 @@ import { readEstate } from "./estate.js";
|
|
|
14
14
|
import { loadFullGeography } from "./geography.js";
|
|
15
15
|
import { checkK12 } from "./k12-manifests.js";
|
|
16
16
|
import { checkK12Slots } from "./k12-slots.js";
|
|
17
|
+
import { checkK13 } from "./k13-signatures.js";
|
|
17
18
|
import { checkL3 } from "./l3-neighbours.js";
|
|
18
19
|
import { checkL4 } from "./l4-local-copy.js";
|
|
19
20
|
import { checkL9 } from "./l9-data-contract.js";
|
|
@@ -29,6 +30,7 @@ export { headingPhrase } from "./e10-phrases.js";
|
|
|
29
30
|
export { readEstate } from "./estate.js";
|
|
30
31
|
export { defineFullGeography, loadFullGeography, placeOfPath } from "./geography.js";
|
|
31
32
|
export { K12_FAMILIES, isDataBackedReason } from "./k12-manifests.js";
|
|
33
|
+
export { K13_SIGNATURE_LIMITS, signatureKey } from "./k13-signatures.js";
|
|
32
34
|
export { L3_MAX_LIST, L3_MIN_LIST, L3_TOLERANCE_KM } from "./l3-neighbours.js";
|
|
33
35
|
export { L4_MIN_ROTATION_PAGES, L4_MIN_TEMPLATE_WORDS } from "./l4-local-copy.js";
|
|
34
36
|
export { yearStamp } from "./l10-location-copy.js";
|
|
@@ -38,7 +40,7 @@ export { sydneyDay } from "./loc-index.js";
|
|
|
38
40
|
export { W3_FAMILIES, W3_MIN_REVALIDATE_SECONDS, refreshInterval } from "./w3-refresh.js";
|
|
39
41
|
export { ESTATE_PLAN_SNAPSHOT_FILE, FULL_STRATEGY_FILE, WAVE_MAX_GAP_DAYS, WAVE_MIN_GAP_DAYS, matchesWaveRoute, normalisePhrase, readFullStrategy, waveScheduleProblems } from "./strategy.js";
|
|
40
42
|
/** The full-tier checks this module runs, in the order their findings are returned. */
|
|
41
|
-
export const FULL_TIER_CHECK_IDS = ["K12", "K12-slots", "E1-pattern", "E5", "E10", "L3", "L4", "L6", "L7", "L8", "L9", "L10", "S4", "LOC-INDEX", "W3"];
|
|
43
|
+
export const FULL_TIER_CHECK_IDS = ["K12", "K12-slots", "K13", "E1-pattern", "E5", "E10", "L3", "L4", "L6", "L7", "L8", "L9", "L10", "S4", "LOC-INDEX", "W3"];
|
|
42
44
|
// Variable specifiers, so the package compiles without site-core; they resolve to the site's installed copy.
|
|
43
45
|
const SECTION_ORDER_MODULE = "@brandlab-digital/site-core/section-order";
|
|
44
46
|
async function loadDefaultOrder() {
|
|
@@ -129,6 +131,7 @@ export async function runFullTierRules(input, options = {}) {
|
|
|
129
131
|
const findings = [
|
|
130
132
|
...checkK12(context),
|
|
131
133
|
...checkK12Slots(context),
|
|
134
|
+
...checkK13(context),
|
|
132
135
|
...checkE1Pattern(context),
|
|
133
136
|
...checkE5(context, inbound),
|
|
134
137
|
...checkE10(context),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,2BAA2B,EAAmC,MAAM,iBAAiB,CAAC;AAG/F,OAAO,EAAoB,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAwC,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAE,oBAAoB,EAAoB,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAsE,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,WAAW,EAAiE,MAAM,gBAAgB,CAAC;AACpJ,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1F,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC1H,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE/L,uFAAuF;AACvF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAiD,CAAC;AAavM,6GAA6G;AAC7G,MAAM,oBAAoB,GAAW,2CAA2C,CAAC;AAEjF,KAAK,UAAU,gBAAgB;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAEjD,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,CAAC,mBAAmB,CAAC;QAC5C,IAAI,OAAO,QAAQ,KAAK,UAAU;YAAE,OAAO,gFAAgF,CAAC;QAC5H,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YACvB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBACtC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;YACvH,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,qDAAqD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACvH,CAAC;AACH,CAAC;AAED,mIAAmI;AACnI,SAAS,eAAe,CAAC,WAAmB;IAC1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,2BAA2B,CAAC,WAAW,CAAC,CAAC;QACxD,mFAAmF;QACnF,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI;YAClE,OAAO,EAAE,MAAM,CAAC,oBAAoB,CAAC,SAAS,CAAC;YAC/C,iBAAiB,EAAE,MAAM,CAAC,UAAU,EAAE,iBAAiB,IAAI,EAAE;SAC9D,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,EAAE,CAAC;IACnE,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,SAAS,WAAW,CAAC,IAAoD;IACvE,MAAM,IAAI,GAAG,CAAC,OAAqD,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC3J,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAA8B,EAC9B,UAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACpD,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,CAAC;IAClE,IAAI,SAAS,GAAyB,IAAI,CAAC;IAC3C,IAAI,gBAAgB,GAAG,EAAE,CAAC;IAC1B,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACpC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QAC9B,IAAI,CAAC,SAAS;YAAE,gBAAgB,GAAG,2BAA2B,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,SAAS,GAAG,MAAM,iBAAiB,EAAE,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gBAAgB,GAAG,gDAAgD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9H,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,UAAU,CAAC;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC;QAChF,SAAS;QACT,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpE,CAAC,CAAC;IACH,MAAM,OAAO,GAAgB;QAC3B,MAAM;QACN,SAAS;QACT,gBAAgB;QAChB,QAAQ;QACR,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,cAAc,EAAE,uBAAuB,CAAC,KAAK,CAAC,WAAW,CAAC;QAC1D,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;QAC7C,KAAK;QACL,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,CAAC,MAAM,gBAAgB,EAAE,CAAC;KACjE,CAAC;IACF,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG;QACf,GAAG,QAAQ,CAAC,OAAO,CAAC;QACpB,GAAG,aAAa,CAAC,OAAO,CAAC;QACzB,GAAG,cAAc,CAAC,OAAO,CAAC;QAC1B,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC;QAC5B,GAAG,QAAQ,CAAC,OAAO,CAAC;QACpB,GAAG,OAAO,CAAC,OAAO,CAAC;QACnB,GAAG,OAAO,CAAC,OAAO,CAAC;QACnB,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC;QAC5B,GAAG,OAAO,CAAC,OAAO,CAAC;QACnB,GAAG,OAAO,CAAC,OAAO,CAAC;QACnB,GAAG,OAAO,CAAC,OAAO,CAAC;QACnB,GAAG,QAAQ,CAAC,OAAO,CAAC;KACrB,CAAC;IACF,yEAAyE;IACzE,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK;QAAE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;IACvD,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,GAAG,qBAAqB,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AACpG,CAAC","sourcesContent":["/**\n * The full-tier rules (release 3.12.0): page families, location estates, section manifests, links and the local data\n * contract. They read the production build's route catalogue and pages (`.next`), the project's strategy record and\n * source, and the site's installed site-core (geography and section orders), and return findings for the ready report:\n * K12 (families), K12-slots and E1-pattern (3.14.0), E5, E10, L3, L4, L6, L7, L8, L9, L10 (location), S4, the location indexing guard and, from 3.13.0,\n * W3 (estate refresh). The runner has the signature the ready gate registers.\n */\nimport { join } from \"node:path\";\nimport { readSiteSystemProjectConfig, type SiteSystemRefreshException } from \"../../config.js\";\nimport type { SiteSystemCheckId, SiteSystemFinding } from \"../../checks.js\";\nimport type { SiteSystemRenderedInput } from \"../../runners.js\";\nimport { type FullContext } from \"./common.js\";\nimport { checkE1Pattern } from \"./e1-pattern.js\";\nimport { checkE10 } from \"./e10-phrases.js\";\nimport { readEstate } from \"./estate.js\";\nimport { loadFullGeography, type FullGeography, type PathAliases } from \"./geography.js\";\nimport { checkK12 } from \"./k12-manifests.js\";\nimport { checkK12Slots } from \"./k12-slots.js\";\nimport { checkL3 } from \"./l3-neighbours.js\";\nimport { checkL4 } from \"./l4-local-copy.js\";\nimport { checkL9 } from \"./l9-data-contract.js\";\nimport { checkL10 } from \"./l10-location-copy.js\";\nimport { checkE5, checkL6, checkL7, checkL8, inboundLinks } from \"./links.js\";\nimport { readRouteCatalogueKinds } from \"./route-kinds.js\";\nimport { checkLocationIndexing, sydneyDay } from \"./loc-index.js\";\nimport { checkS4 } from \"./s4-route-files.js\";\nimport { readFullStrategy } from \"./strategy.js\";\nimport { checkW3 } from \"./w3-refresh.js\";\n\nexport { FULL_LISTED_FAILURES, type FullContext } from \"./common.js\";\nexport { headingPhrase } from \"./e10-phrases.js\";\nexport { readEstate, type Estate, type EstatePage, type LocationCopy, type ManifestData } from \"./estate.js\";\nexport { defineFullGeography, loadFullGeography, placeOfPath, type FullGeography, type FullGeographyInput, type PathAliases } from \"./geography.js\";\nexport { K12_FAMILIES, isDataBackedReason } from \"./k12-manifests.js\";\nexport { L3_MAX_LIST, L3_MIN_LIST, L3_TOLERANCE_KM } from \"./l3-neighbours.js\";\nexport { L4_MIN_ROTATION_PAGES, L4_MIN_TEMPLATE_WORDS } from \"./l4-local-copy.js\";\nexport { yearStamp } from \"./l10-location-copy.js\";\nexport { L6_MIN_INBOUND, L6_MIN_PAGE_TYPES, L7_MAX_DEPTH, clickDepths } from \"./links.js\";\nexport { CATALOGUE_HUB_FAMILIES, ROUTE_CATALOGUE_FILE, linkingPageType, readRouteCatalogueKinds } from \"./route-kinds.js\";\nexport { sydneyDay } from \"./loc-index.js\";\nexport { W3_FAMILIES, W3_MIN_REVALIDATE_SECONDS, refreshInterval } from \"./w3-refresh.js\";\nexport { ESTATE_PLAN_SNAPSHOT_FILE, FULL_STRATEGY_FILE, WAVE_MAX_GAP_DAYS, WAVE_MIN_GAP_DAYS, matchesWaveRoute, normalisePhrase, readFullStrategy, waveScheduleProblems } from \"./strategy.js\";\n\n/** The full-tier checks this module runs, in the order their findings are returned. */\nexport const FULL_TIER_CHECK_IDS = [\"K12\", \"K12-slots\", \"E1-pattern\", \"E5\", \"E10\", \"L3\", \"L4\", \"L6\", \"L7\", \"L8\", \"L9\", \"L10\", \"S4\", \"LOC-INDEX\", \"W3\"] as const satisfies readonly SiteSystemCheckId[];\n\nexport interface FullTierRuleOptions {\n /** The day waves are judged on. Defaults to now. */\n readonly asOf?: Date;\n /** The build directory; defaults to `input.buildDir`, then `<projectRoot>/.next`. */\n readonly buildDir?: string;\n /** Places for a test; a real run loads the site's site-core geography. Null runs without places. */\n readonly geography?: FullGeography | null;\n /** Canonical section ids per family for a test; a real run loads site-core's `defaultSectionOrder`. */\n readonly defaultOrder?: FullContext[\"defaultOrder\"];\n}\n\n// Variable specifiers, so the package compiles without site-core; they resolve to the site's installed copy.\nconst SECTION_ORDER_MODULE: string = \"@brandlab-digital/site-core/section-order\";\n\nasync function loadDefaultOrder(): Promise<FullContext[\"defaultOrder\"]> {\n try {\n const module = (await import(SECTION_ORDER_MODULE)) as {\n defaultSectionOrder?: (family: string, trade?: string) => { cap: number; entries: readonly { id: string; requirement: string }[] };\n };\n const defaults = module.defaultSectionOrder;\n if (typeof defaults !== \"function\") return \"the installed site-core has no defaultSectionOrder (3.11.0 or later is needed)\";\n return (family, trade) => {\n try {\n const order = defaults(family, trade);\n return { cap: order.cap, entries: order.entries.map((entry) => ({ id: entry.id, requirement: entry.requirement })) };\n } catch {\n return undefined;\n }\n };\n } catch (error) {\n return `site-core's section orders could not be imported: ${error instanceof Error ? error.message : String(error)}`;\n }\n}\n\n/** The declared tier, the representative service route and the W3 exceptions; null tier when the config cannot be read in full. */\nfunction projectSettings(projectRoot: string): { tier: string | null; service: string | undefined; refreshExceptions: readonly SiteSystemRefreshException[] } {\n try {\n const config = readSiteSystemProjectConfig(projectRoot);\n // A config the gate cannot read in full could hide a full tier, so the checks run.\n return {\n tier: config.complete ? (config.siteSystem?.tier ?? \"none\") : null,\n service: config.representativeRoutes[\"service\"],\n refreshExceptions: config.siteSystem?.refreshExceptions ?? [],\n };\n } catch {\n return { tier: null, service: undefined, refreshExceptions: [] };\n }\n}\n\n/** The estate plan's public slugs as path aliases: public slug → registry slug. */\nfunction pathAliases(plan: NonNullable<FullContext[\"strategy\"][\"estate\"]>): PathAliases {\n const flip = (renames: Readonly<Record<string, string>> | undefined) => new Map(Object.entries(renames ?? {}).map(([registry, slug]) => [slug, registry]));\n return { regions: flip(plan.slugs?.regions), suburbs: flip(plan.slugs?.suburbs) };\n}\n\n/**\n * Runs the full-tier rules over the built estate at `projectRoot`. A site that declares a lower tier (or none) gets no\n * findings: the report shows the full checks as not run, which never blocks below the full tier.\n */\nexport async function runFullTierRules(\n input: SiteSystemRenderedInput,\n options: FullTierRuleOptions = {},\n): Promise<readonly SiteSystemFinding[]> {\n const settings = projectSettings(input.projectRoot);\n if (settings.tier !== null && settings.tier !== \"full\") return [];\n let geography: FullGeography | null = null;\n let geographyProblem = \"\";\n if (options.geography !== undefined) {\n geography = options.geography;\n if (!geography) geographyProblem = \"no geography was supplied\";\n } else {\n try {\n geography = await loadFullGeography();\n } catch (error) {\n geographyProblem = `site-core's geography could not be imported: ${error instanceof Error ? error.message : String(error)}`;\n }\n }\n const today = sydneyDay(options.asOf ?? new Date());\n const strategy = readFullStrategy(input.projectRoot, today);\n const estate = readEstate({\n pages: input.pages,\n buildDir: options.buildDir ?? input.buildDir ?? join(input.projectRoot, \".next\"),\n geography,\n ...(settings.service ? { seeds: { [settings.service]: \"service\" } } : {}),\n ...(strategy.estate?.slugs ? { aliases: pathAliases(strategy.estate) } : {}),\n ...(strategy.estate?.paths ? { paths: strategy.estate.paths } : {}),\n });\n const context: FullContext = {\n estate,\n geography,\n geographyProblem,\n strategy,\n projectRoot: input.projectRoot,\n catalogueKinds: readRouteCatalogueKinds(input.projectRoot),\n refreshExceptions: settings.refreshExceptions,\n today,\n defaultOrder: options.defaultOrder ?? (await loadDefaultOrder()),\n };\n const inbound = inboundLinks(estate);\n const findings = [\n ...checkK12(context),\n ...checkK12Slots(context),\n ...checkE1Pattern(context),\n ...checkE5(context, inbound),\n ...checkE10(context),\n ...checkL3(context),\n ...checkL4(context),\n ...checkL6(context, inbound),\n ...checkL7(context),\n ...checkL8(context),\n ...checkL9(context),\n ...checkL10(context),\n ];\n // The copy is only for L3, L4 and L10; let it go before the source scan.\n for (const page of estate.pages) page.copy = undefined;\n return [...findings, ...checkS4(context), ...checkLocationIndexing(context), ...checkW3(context)];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The full-tier rules (release 3.12.0): page families, location estates, section manifests, links and the local data\n * contract. They read the production build's route catalogue and pages (`.next`), the project's strategy record and\n * source, and the site's installed site-core (geography and section orders), and return findings for the ready report:\n * K12 (families), K12-slots and E1-pattern (3.14.0), K13 (signature sections, 3.16.0), E5, E10, L3, L4, L6, L7, L8, L9, L10 (location), S4, the location indexing guard and, from 3.13.0,\n * W3 (estate refresh). The runner has the signature the ready gate registers.\n */\nimport { join } from \"node:path\";\nimport { readSiteSystemProjectConfig, type SiteSystemRefreshException } from \"../../config.js\";\nimport type { SiteSystemCheckId, SiteSystemFinding } from \"../../checks.js\";\nimport type { SiteSystemRenderedInput } from \"../../runners.js\";\nimport { type FullContext } from \"./common.js\";\nimport { checkE1Pattern } from \"./e1-pattern.js\";\nimport { checkE10 } from \"./e10-phrases.js\";\nimport { readEstate } from \"./estate.js\";\nimport { loadFullGeography, type FullGeography, type PathAliases } from \"./geography.js\";\nimport { checkK12 } from \"./k12-manifests.js\";\nimport { checkK12Slots } from \"./k12-slots.js\";\nimport { checkK13 } from \"./k13-signatures.js\";\nimport { checkL3 } from \"./l3-neighbours.js\";\nimport { checkL4 } from \"./l4-local-copy.js\";\nimport { checkL9 } from \"./l9-data-contract.js\";\nimport { checkL10 } from \"./l10-location-copy.js\";\nimport { checkE5, checkL6, checkL7, checkL8, inboundLinks } from \"./links.js\";\nimport { readRouteCatalogueKinds } from \"./route-kinds.js\";\nimport { checkLocationIndexing, sydneyDay } from \"./loc-index.js\";\nimport { checkS4 } from \"./s4-route-files.js\";\nimport { readFullStrategy } from \"./strategy.js\";\nimport { checkW3 } from \"./w3-refresh.js\";\n\nexport { FULL_LISTED_FAILURES, type FullContext } from \"./common.js\";\nexport { headingPhrase } from \"./e10-phrases.js\";\nexport { readEstate, type Estate, type EstatePage, type LocationCopy, type ManifestData } from \"./estate.js\";\nexport { defineFullGeography, loadFullGeography, placeOfPath, type FullGeography, type FullGeographyInput, type PathAliases } from \"./geography.js\";\nexport { K12_FAMILIES, isDataBackedReason } from \"./k12-manifests.js\";\nexport { K13_SIGNATURE_LIMITS, signatureKey } from \"./k13-signatures.js\";\nexport { L3_MAX_LIST, L3_MIN_LIST, L3_TOLERANCE_KM } from \"./l3-neighbours.js\";\nexport { L4_MIN_ROTATION_PAGES, L4_MIN_TEMPLATE_WORDS } from \"./l4-local-copy.js\";\nexport { yearStamp } from \"./l10-location-copy.js\";\nexport { L6_MIN_INBOUND, L6_MIN_PAGE_TYPES, L7_MAX_DEPTH, clickDepths } from \"./links.js\";\nexport { CATALOGUE_HUB_FAMILIES, ROUTE_CATALOGUE_FILE, linkingPageType, readRouteCatalogueKinds } from \"./route-kinds.js\";\nexport { sydneyDay } from \"./loc-index.js\";\nexport { W3_FAMILIES, W3_MIN_REVALIDATE_SECONDS, refreshInterval } from \"./w3-refresh.js\";\nexport { ESTATE_PLAN_SNAPSHOT_FILE, FULL_STRATEGY_FILE, WAVE_MAX_GAP_DAYS, WAVE_MIN_GAP_DAYS, matchesWaveRoute, normalisePhrase, readFullStrategy, waveScheduleProblems } from \"./strategy.js\";\n\n/** The full-tier checks this module runs, in the order their findings are returned. */\nexport const FULL_TIER_CHECK_IDS = [\"K12\", \"K12-slots\", \"K13\", \"E1-pattern\", \"E5\", \"E10\", \"L3\", \"L4\", \"L6\", \"L7\", \"L8\", \"L9\", \"L10\", \"S4\", \"LOC-INDEX\", \"W3\"] as const satisfies readonly SiteSystemCheckId[];\n\nexport interface FullTierRuleOptions {\n /** The day waves are judged on. Defaults to now. */\n readonly asOf?: Date;\n /** The build directory; defaults to `input.buildDir`, then `<projectRoot>/.next`. */\n readonly buildDir?: string;\n /** Places for a test; a real run loads the site's site-core geography. Null runs without places. */\n readonly geography?: FullGeography | null;\n /** Canonical section ids per family for a test; a real run loads site-core's `defaultSectionOrder`. */\n readonly defaultOrder?: FullContext[\"defaultOrder\"];\n}\n\n// Variable specifiers, so the package compiles without site-core; they resolve to the site's installed copy.\nconst SECTION_ORDER_MODULE: string = \"@brandlab-digital/site-core/section-order\";\n\nasync function loadDefaultOrder(): Promise<FullContext[\"defaultOrder\"]> {\n try {\n const module = (await import(SECTION_ORDER_MODULE)) as {\n defaultSectionOrder?: (family: string, trade?: string) => { cap: number; entries: readonly { id: string; requirement: string }[] };\n };\n const defaults = module.defaultSectionOrder;\n if (typeof defaults !== \"function\") return \"the installed site-core has no defaultSectionOrder (3.11.0 or later is needed)\";\n return (family, trade) => {\n try {\n const order = defaults(family, trade);\n return { cap: order.cap, entries: order.entries.map((entry) => ({ id: entry.id, requirement: entry.requirement })) };\n } catch {\n return undefined;\n }\n };\n } catch (error) {\n return `site-core's section orders could not be imported: ${error instanceof Error ? error.message : String(error)}`;\n }\n}\n\n/** The declared tier, the representative service route and the W3 exceptions; null tier when the config cannot be read in full. */\nfunction projectSettings(projectRoot: string): { tier: string | null; service: string | undefined; refreshExceptions: readonly SiteSystemRefreshException[] } {\n try {\n const config = readSiteSystemProjectConfig(projectRoot);\n // A config the gate cannot read in full could hide a full tier, so the checks run.\n return {\n tier: config.complete ? (config.siteSystem?.tier ?? \"none\") : null,\n service: config.representativeRoutes[\"service\"],\n refreshExceptions: config.siteSystem?.refreshExceptions ?? [],\n };\n } catch {\n return { tier: null, service: undefined, refreshExceptions: [] };\n }\n}\n\n/** The estate plan's public slugs as path aliases: public slug → registry slug. */\nfunction pathAliases(plan: NonNullable<FullContext[\"strategy\"][\"estate\"]>): PathAliases {\n const flip = (renames: Readonly<Record<string, string>> | undefined) => new Map(Object.entries(renames ?? {}).map(([registry, slug]) => [slug, registry]));\n return { regions: flip(plan.slugs?.regions), suburbs: flip(plan.slugs?.suburbs) };\n}\n\n/**\n * Runs the full-tier rules over the built estate at `projectRoot`. A site that declares a lower tier (or none) gets no\n * findings: the report shows the full checks as not run, which never blocks below the full tier.\n */\nexport async function runFullTierRules(\n input: SiteSystemRenderedInput,\n options: FullTierRuleOptions = {},\n): Promise<readonly SiteSystemFinding[]> {\n const settings = projectSettings(input.projectRoot);\n if (settings.tier !== null && settings.tier !== \"full\") return [];\n let geography: FullGeography | null = null;\n let geographyProblem = \"\";\n if (options.geography !== undefined) {\n geography = options.geography;\n if (!geography) geographyProblem = \"no geography was supplied\";\n } else {\n try {\n geography = await loadFullGeography();\n } catch (error) {\n geographyProblem = `site-core's geography could not be imported: ${error instanceof Error ? error.message : String(error)}`;\n }\n }\n const today = sydneyDay(options.asOf ?? new Date());\n const strategy = readFullStrategy(input.projectRoot, today);\n const estate = readEstate({\n pages: input.pages,\n buildDir: options.buildDir ?? input.buildDir ?? join(input.projectRoot, \".next\"),\n geography,\n ...(settings.service ? { seeds: { [settings.service]: \"service\" } } : {}),\n ...(strategy.estate?.slugs ? { aliases: pathAliases(strategy.estate) } : {}),\n ...(strategy.estate?.paths ? { paths: strategy.estate.paths } : {}),\n });\n const context: FullContext = {\n estate,\n geography,\n geographyProblem,\n strategy,\n projectRoot: input.projectRoot,\n catalogueKinds: readRouteCatalogueKinds(input.projectRoot),\n refreshExceptions: settings.refreshExceptions,\n today,\n defaultOrder: options.defaultOrder ?? (await loadDefaultOrder()),\n };\n const inbound = inboundLinks(estate);\n const findings = [\n ...checkK12(context),\n ...checkK12Slots(context),\n ...checkK13(context),\n ...checkE1Pattern(context),\n ...checkE5(context, inbound),\n ...checkE10(context),\n ...checkL3(context),\n ...checkL4(context),\n ...checkL6(context, inbound),\n ...checkL7(context),\n ...checkL8(context),\n ...checkL9(context),\n ...checkL10(context),\n ];\n // The copy is only for L3, L4 and L10; let it go before the source scan.\n for (const page of estate.pages) page.copy = undefined;\n return [...findings, ...checkS4(context), ...checkLocationIndexing(context), ...checkW3(context)];\n}\n"]}
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
* family's canonical one or the alternative recorded in strategy.ts; and the page renders exactly the sections the
|
|
7
7
|
* manifest lists, in that order. A page over its cap (`cap-exceeded`) is a warning, not a failure. The contact page
|
|
8
8
|
* has its own check (K12-contact).
|
|
9
|
+
*
|
|
10
|
+
* 3.16.0: signature sections take the place the site declares, so they are left out of the order walk (an `after`
|
|
11
|
+
* must name a planned section; K13 checks the rest). An optional or recommended section with data that drops for the
|
|
12
|
+
* cap is a warning, so a clean gate still shows when the site's content was cut.
|
|
9
13
|
*/
|
|
10
14
|
import type { SiteSystemFinding } from "../../checks.js";
|
|
11
15
|
import { type FullContext } from "./common.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k12-manifests.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/full/k12-manifests.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"k12-manifests.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/full/k12-manifests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAyD,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACtG,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE5D,sGAAsG;AACtG,eAAO,MAAM,YAAY,uOAmBf,CAAC;AAEX,wHAAwH;AACxH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1D;AAMD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,EAAE,CAoEzG;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,iBAAiB,EAAE,CAoClE"}
|
|
@@ -64,6 +64,12 @@ export function manifestProblems(page, manifest, context) {
|
|
|
64
64
|
// What renders follows the plan, and the page shows exactly what the manifest lists.
|
|
65
65
|
let position = -1;
|
|
66
66
|
for (const entry of manifest.rendered) {
|
|
67
|
+
if (entry.id === "signature") {
|
|
68
|
+
if (entry.after !== undefined && !planned.includes(entry.after)) {
|
|
69
|
+
problems.push(`The manifest on ${where} places the signature "${entry.signature ?? ""}" after "${entry.after}", which is not a planned section.`);
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
67
73
|
const index = planned.indexOf(entry.id, position + 1);
|
|
68
74
|
if (index === -1) {
|
|
69
75
|
problems.push(`The manifest on ${where} lists "${entry.id}" as rendered out of its planned place.`);
|
|
@@ -118,6 +124,11 @@ export function checkK12(context) {
|
|
|
118
124
|
}
|
|
119
125
|
for (const problem of manifestProblems(page, state.manifest, context))
|
|
120
126
|
failures.push(fail("K12", page.path, problem));
|
|
127
|
+
for (const skip of state.manifest.skipped) {
|
|
128
|
+
if (skip.reason === "cap" && (skip.requirement === "O" || skip.requirement === "Rec")) {
|
|
129
|
+
failures.push(warning("K12", page.path, `${page.path} drops its ${skip.requirement === "O" ? "optional" : "recommended"} "${skip.section}" section for the cap of ${state.manifest.cap}, although its data is there.`));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
121
132
|
if (state.manifest.flags.includes("cap-exceeded")) {
|
|
122
133
|
failures.push(warning("K12", page.path, `${page.path} renders ${state.manifest.counted} sections against a cap of ${state.manifest.cap}, because its required and conditional sections all have data.`));
|
|
123
134
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k12-manifests.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/k12-manifests.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * K12 on every family (Site System v2 §3.3, §13.2): each page of a family carries one section manifest\n * (`<script type=\"application/json\" data-bl-manifest>`, written by SectionSequence). Every required section renders\n * or is skipped with a reason drawn from its data (`no-…`), never the sequencer's `not-provided`, `cap` or\n * `duplicate`; every conditional section that does not render says its data is absent; the planned order is the\n * family's canonical one or the alternative recorded in strategy.ts; and the page renders exactly the sections the\n * manifest lists, in that order. A page over its cap (`cap-exceeded`) is a warning, not a failure. The contact page\n * has its own check (K12-contact).\n */\nimport type { SiteSystemFinding } from \"../../checks.js\";\nimport { fail, listOf, notApplicable, outcome, plural, warning, type FullContext } from \"./common.js\";\nimport type { EstatePage, ManifestData } from \"./estate.js\";\n\n/** The families that carry a manifest (site-core BRANDLAB_PAGE_FAMILIES without the contact page). */\nexport const K12_FAMILIES = [\n \"home\",\n \"service\",\n \"service-in-suburb\",\n \"region\",\n \"suburb\",\n \"cost-guide\",\n \"services-hub\",\n \"locations-hub\",\n \"projects-hub\",\n \"project\",\n \"gallery\",\n \"reviews\",\n \"about\",\n \"faqs\",\n \"guides-hub\",\n \"guide\",\n \"council\",\n \"emergency\",\n] as const;\n\n/** As site-core's isDataBackedSkipReason: the section's own data is absent, or its content is in the hero checklist. */\nexport function isDataBackedReason(reason: string): boolean {\n return reason === \"merge-into-hero-checklist\" || /^no-[a-z0-9]+(?:-[a-z0-9]+)*$/.test(reason);\n}\n\nfunction sameList(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\nexport function manifestProblems(page: EstatePage, manifest: ManifestData, context: FullContext): string[] {\n const problems: string[] = [];\n const where = page.path;\n const planned = manifest.planned.map((entry) => entry.id);\n\n if (!(K12_FAMILIES as readonly string[]).includes(manifest.family)) {\n return [`The manifest on ${where} names \"${manifest.family}\", which is not a page family that carries one.`];\n }\n if (manifest.order === \"recorded\") {\n const recorded = context.strategy.recordedOrders.get(manifest.family);\n if (!recorded) problems.push(`The manifest on ${where} says its order is recorded, but strategy.ts records no order for ${manifest.family} pages.`);\n else if (!sameList(planned, recorded)) problems.push(`The sections planned on ${where} (${planned.join(\", \")}) are not the order recorded for ${manifest.family} pages (${recorded.join(\", \")}).`);\n }\n const canonical = typeof context.defaultOrder === \"string\" ? undefined : context.defaultOrder(manifest.family, context.strategy.trade);\n if (canonical) {\n const ids = canonical.entries.map((entry) => entry.id);\n if (manifest.order !== \"recorded\" && !sameList(planned, ids)) {\n problems.push(`The sections planned on ${where} (${planned.join(\", \")}) are not the canonical order for ${manifest.family} pages (${ids.join(\", \")}).`);\n }\n // Each planned section keeps the requirement the family gives it, whatever the order.\n const requirementOf = new Map(canonical.entries.map((entry) => [entry.id, entry.requirement]));\n for (const entry of manifest.planned) {\n const expected = requirementOf.get(entry.id);\n if (expected !== undefined && expected !== entry.requirement) {\n problems.push(`The manifest on ${where} marks \"${entry.id}\" as ${entry.requirement}; on ${manifest.family} pages it is ${expected}.`);\n }\n }\n if (manifest.cap !== canonical.cap) problems.push(`The manifest on ${where} gives a cap of ${manifest.cap}; ${manifest.family} pages have a cap of ${canonical.cap}.`);\n }\n if (manifest.flags.includes(\"cap-exceeded\") !== manifest.counted > manifest.cap) {\n problems.push(`The manifest on ${where} counts ${manifest.counted} sections against a cap of ${manifest.cap} but ${manifest.flags.includes(\"cap-exceeded\") ? \"flags\" : \"does not flag\"} cap-exceeded.`);\n }\n\n // What renders follows the plan, and the page shows exactly what the manifest lists.\n let position = -1;\n for (const entry of manifest.rendered) {\n const index = planned.indexOf(entry.id, position + 1);\n if (index === -1) {\n problems.push(`The manifest on ${where} lists \"${entry.id}\" as rendered out of its planned place.`);\n break;\n }\n position = index;\n }\n const listed = manifest.rendered.map((entry) => entry.section);\n if (!sameList(page.sections, listed)) {\n problems.push(`${where} renders the sections ${page.sections.join(\", \") || \"(none)\"}, but its manifest lists ${listed.join(\", \") || \"(none)\"}.`);\n }\n\n const renderedIds = new Set(manifest.rendered.map((entry) => entry.id));\n for (const entry of manifest.planned) {\n if (entry.requirement !== \"R\" && entry.requirement !== \"C\") continue;\n if (renderedIds.has(entry.id)) continue;\n const reasons = manifest.skipped.filter((skip) => skip.id === entry.id).map((skip) => skip.reason);\n if (reasons.some(isDataBackedReason)) continue;\n const reason = reasons[0] ?? \"no reason recorded\";\n problems.push(\n entry.requirement === \"R\"\n ? `${where} skips its required \"${entry.id}\" section without a reason drawn from its data (${reason}).`\n : `${where} leaves out its conditional \"${entry.id}\" section without saying its data is absent (${reason}).`,\n );\n }\n return problems;\n}\n\nexport function checkK12(context: FullContext): SiteSystemFinding[] {\n const failures: SiteSystemFinding[] = [];\n let checked = 0;\n if (typeof context.defaultOrder === \"string\") {\n failures.push(fail(\"K12\", undefined, `The canonical section orders could not be loaded (${context.defaultOrder}), so default orders were not compared.`));\n }\n for (const problem of context.strategy.problems.orders) failures.push(fail(\"K12\", \"src/data/strategy.ts\", problem));\n for (const page of context.estate.pages) {\n if (!(K12_FAMILIES as readonly string[]).includes(page.family ?? \"\")) continue;\n checked += 1;\n const state = page.manifest;\n if (state.kind === \"none\") {\n failures.push(fail(\"K12\", page.path, `${page.path} is a ${page.family} page with no section manifest; its sections go through SectionSequence.`));\n continue;\n }\n if (state.kind === \"many\") {\n failures.push(fail(\"K12\", page.path, `${page.path} carries ${state.count} section manifests; a page has one.`));\n continue;\n }\n if (state.kind === \"invalid\") {\n failures.push(fail(\"K12\", page.path, `The section manifest on ${page.path} ${state.reason}.`));\n continue;\n }\n for (const problem of manifestProblems(page, state.manifest, context)) failures.push(fail(\"K12\", page.path, problem));\n if (state.manifest.flags.includes(\"cap-exceeded\")) {\n failures.push(warning(\"K12\", page.path, `${page.path} renders ${state.manifest.counted} sections against a cap of ${state.manifest.cap}, because its required and conditional sections all have data.`));\n }\n }\n if (checked === 0) return [...failures, notApplicable(\"K12\", \"No page of a family that carries a section manifest was found.\")];\n const families = [...new Set(context.estate.pages.flatMap((page) => ((K12_FAMILIES as readonly string[]).includes(page.family ?? \"\") ? [page.family!] : [])))];\n return outcome(\"K12\", failures, `${plural(checked, \"page\")} across ${listOf(families)} carry a section manifest with every required and conditional section accounted for, in the canonical or recorded order.`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"k12-manifests.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/k12-manifests.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * K12 on every family (Site System v2 §3.3, §13.2): each page of a family carries one section manifest\n * (`<script type=\"application/json\" data-bl-manifest>`, written by SectionSequence). Every required section renders\n * or is skipped with a reason drawn from its data (`no-…`), never the sequencer's `not-provided`, `cap` or\n * `duplicate`; every conditional section that does not render says its data is absent; the planned order is the\n * family's canonical one or the alternative recorded in strategy.ts; and the page renders exactly the sections the\n * manifest lists, in that order. A page over its cap (`cap-exceeded`) is a warning, not a failure. The contact page\n * has its own check (K12-contact).\n *\n * 3.16.0: signature sections take the place the site declares, so they are left out of the order walk (an `after`\n * must name a planned section; K13 checks the rest). An optional or recommended section with data that drops for the\n * cap is a warning, so a clean gate still shows when the site's content was cut.\n */\nimport type { SiteSystemFinding } from \"../../checks.js\";\nimport { fail, listOf, notApplicable, outcome, plural, warning, type FullContext } from \"./common.js\";\nimport type { EstatePage, ManifestData } from \"./estate.js\";\n\n/** The families that carry a manifest (site-core BRANDLAB_PAGE_FAMILIES without the contact page). */\nexport const K12_FAMILIES = [\n \"home\",\n \"service\",\n \"service-in-suburb\",\n \"region\",\n \"suburb\",\n \"cost-guide\",\n \"services-hub\",\n \"locations-hub\",\n \"projects-hub\",\n \"project\",\n \"gallery\",\n \"reviews\",\n \"about\",\n \"faqs\",\n \"guides-hub\",\n \"guide\",\n \"council\",\n \"emergency\",\n] as const;\n\n/** As site-core's isDataBackedSkipReason: the section's own data is absent, or its content is in the hero checklist. */\nexport function isDataBackedReason(reason: string): boolean {\n return reason === \"merge-into-hero-checklist\" || /^no-[a-z0-9]+(?:-[a-z0-9]+)*$/.test(reason);\n}\n\nfunction sameList(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\nexport function manifestProblems(page: EstatePage, manifest: ManifestData, context: FullContext): string[] {\n const problems: string[] = [];\n const where = page.path;\n const planned = manifest.planned.map((entry) => entry.id);\n\n if (!(K12_FAMILIES as readonly string[]).includes(manifest.family)) {\n return [`The manifest on ${where} names \"${manifest.family}\", which is not a page family that carries one.`];\n }\n if (manifest.order === \"recorded\") {\n const recorded = context.strategy.recordedOrders.get(manifest.family);\n if (!recorded) problems.push(`The manifest on ${where} says its order is recorded, but strategy.ts records no order for ${manifest.family} pages.`);\n else if (!sameList(planned, recorded)) problems.push(`The sections planned on ${where} (${planned.join(\", \")}) are not the order recorded for ${manifest.family} pages (${recorded.join(\", \")}).`);\n }\n const canonical = typeof context.defaultOrder === \"string\" ? undefined : context.defaultOrder(manifest.family, context.strategy.trade);\n if (canonical) {\n const ids = canonical.entries.map((entry) => entry.id);\n if (manifest.order !== \"recorded\" && !sameList(planned, ids)) {\n problems.push(`The sections planned on ${where} (${planned.join(\", \")}) are not the canonical order for ${manifest.family} pages (${ids.join(\", \")}).`);\n }\n // Each planned section keeps the requirement the family gives it, whatever the order.\n const requirementOf = new Map(canonical.entries.map((entry) => [entry.id, entry.requirement]));\n for (const entry of manifest.planned) {\n const expected = requirementOf.get(entry.id);\n if (expected !== undefined && expected !== entry.requirement) {\n problems.push(`The manifest on ${where} marks \"${entry.id}\" as ${entry.requirement}; on ${manifest.family} pages it is ${expected}.`);\n }\n }\n if (manifest.cap !== canonical.cap) problems.push(`The manifest on ${where} gives a cap of ${manifest.cap}; ${manifest.family} pages have a cap of ${canonical.cap}.`);\n }\n if (manifest.flags.includes(\"cap-exceeded\") !== manifest.counted > manifest.cap) {\n problems.push(`The manifest on ${where} counts ${manifest.counted} sections against a cap of ${manifest.cap} but ${manifest.flags.includes(\"cap-exceeded\") ? \"flags\" : \"does not flag\"} cap-exceeded.`);\n }\n\n // What renders follows the plan, and the page shows exactly what the manifest lists.\n let position = -1;\n for (const entry of manifest.rendered) {\n if (entry.id === \"signature\") {\n if (entry.after !== undefined && !planned.includes(entry.after)) {\n problems.push(`The manifest on ${where} places the signature \"${entry.signature ?? \"\"}\" after \"${entry.after}\", which is not a planned section.`);\n }\n continue;\n }\n const index = planned.indexOf(entry.id, position + 1);\n if (index === -1) {\n problems.push(`The manifest on ${where} lists \"${entry.id}\" as rendered out of its planned place.`);\n break;\n }\n position = index;\n }\n const listed = manifest.rendered.map((entry) => entry.section);\n if (!sameList(page.sections, listed)) {\n problems.push(`${where} renders the sections ${page.sections.join(\", \") || \"(none)\"}, but its manifest lists ${listed.join(\", \") || \"(none)\"}.`);\n }\n\n const renderedIds = new Set(manifest.rendered.map((entry) => entry.id));\n for (const entry of manifest.planned) {\n if (entry.requirement !== \"R\" && entry.requirement !== \"C\") continue;\n if (renderedIds.has(entry.id)) continue;\n const reasons = manifest.skipped.filter((skip) => skip.id === entry.id).map((skip) => skip.reason);\n if (reasons.some(isDataBackedReason)) continue;\n const reason = reasons[0] ?? \"no reason recorded\";\n problems.push(\n entry.requirement === \"R\"\n ? `${where} skips its required \"${entry.id}\" section without a reason drawn from its data (${reason}).`\n : `${where} leaves out its conditional \"${entry.id}\" section without saying its data is absent (${reason}).`,\n );\n }\n return problems;\n}\n\nexport function checkK12(context: FullContext): SiteSystemFinding[] {\n const failures: SiteSystemFinding[] = [];\n let checked = 0;\n if (typeof context.defaultOrder === \"string\") {\n failures.push(fail(\"K12\", undefined, `The canonical section orders could not be loaded (${context.defaultOrder}), so default orders were not compared.`));\n }\n for (const problem of context.strategy.problems.orders) failures.push(fail(\"K12\", \"src/data/strategy.ts\", problem));\n for (const page of context.estate.pages) {\n if (!(K12_FAMILIES as readonly string[]).includes(page.family ?? \"\")) continue;\n checked += 1;\n const state = page.manifest;\n if (state.kind === \"none\") {\n failures.push(fail(\"K12\", page.path, `${page.path} is a ${page.family} page with no section manifest; its sections go through SectionSequence.`));\n continue;\n }\n if (state.kind === \"many\") {\n failures.push(fail(\"K12\", page.path, `${page.path} carries ${state.count} section manifests; a page has one.`));\n continue;\n }\n if (state.kind === \"invalid\") {\n failures.push(fail(\"K12\", page.path, `The section manifest on ${page.path} ${state.reason}.`));\n continue;\n }\n for (const problem of manifestProblems(page, state.manifest, context)) failures.push(fail(\"K12\", page.path, problem));\n for (const skip of state.manifest.skipped) {\n if (skip.reason === \"cap\" && (skip.requirement === \"O\" || skip.requirement === \"Rec\")) {\n failures.push(warning(\"K12\", page.path, `${page.path} drops its ${skip.requirement === \"O\" ? \"optional\" : \"recommended\"} \"${skip.section}\" section for the cap of ${state.manifest.cap}, although its data is there.`));\n }\n }\n if (state.manifest.flags.includes(\"cap-exceeded\")) {\n failures.push(warning(\"K12\", page.path, `${page.path} renders ${state.manifest.counted} sections against a cap of ${state.manifest.cap}, because its required and conditional sections all have data.`));\n }\n }\n if (checked === 0) return [...failures, notApplicable(\"K12\", \"No page of a family that carries a section manifest was found.\")];\n const families = [...new Set(context.estate.pages.flatMap((page) => ((K12_FAMILIES as readonly string[]).includes(page.family ?? \"\") ? [page.family!] : [])))];\n return outcome(\"K12\", failures, `${plural(checked, \"page\")} across ${listOf(families)} carry a section manifest with every required and conditional section accounted for, in the canonical or recorded order.`);\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* K13: signature sections (Site System v2 §7.7, 3.16.0). A client's signature features keep its own character inside
|
|
3
|
+
* the shared skeleton, under the same rules as every other section. Each top-level `data-bl-section="signature"` has a
|
|
4
|
+
* `data-bl-signature` name (lower-case words joined by hyphens) that matches its manifest entry; a page renders at most
|
|
5
|
+
* two on the home page, one on a service page and none elsewhere (site-core's `SIGNATURE_LIMITS`); and the home page's
|
|
6
|
+
* signatures are the ones `strategy.ts` records in `look.homeSections.signatures`, so D4 compares the real look. A
|
|
7
|
+
* recorded signature the home page doesn't render is a warning. Accessibility, budgets and truth are the page-wide
|
|
8
|
+
* checks' (axe, K3, K4, B1, T4, E8); the section contract is K8's and K11's.
|
|
9
|
+
*/
|
|
10
|
+
import type { SiteSystemFinding } from "../../checks.js";
|
|
11
|
+
import { type FullContext } from "./common.js";
|
|
12
|
+
/** As site-core's SIGNATURE_LIMITS (a test keeps the two equal). */
|
|
13
|
+
export declare const K13_SIGNATURE_LIMITS: Readonly<Record<string, number>>;
|
|
14
|
+
/** A recorded signature ("Grass-edge divider") in the form of a rendered name ("grass-edge-divider"). */
|
|
15
|
+
export declare function signatureKey(text: string): string;
|
|
16
|
+
export declare function checkK13(context: FullContext): SiteSystemFinding[];
|
|
17
|
+
//# sourceMappingURL=k13-signatures.d.ts.map
|