@brandlab-digital/conformance 3.13.0 → 3.15.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.
Files changed (152) hide show
  1. package/README.md +68 -2
  2. package/dist/analytics-e2e.d.ts +10 -16
  3. package/dist/analytics-e2e.d.ts.map +1 -1
  4. package/dist/analytics-e2e.js +61 -3
  5. package/dist/analytics-e2e.js.map +1 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +4 -1
  8. package/dist/cli.js.map +1 -1
  9. package/dist/current-release.js +5 -5
  10. package/dist/current-release.js.map +1 -1
  11. package/dist/engineering.d.ts.map +1 -1
  12. package/dist/engineering.js +18 -2
  13. package/dist/engineering.js.map +1 -1
  14. package/dist/estate-snapshot.d.ts +54 -0
  15. package/dist/estate-snapshot.d.ts.map +1 -0
  16. package/dist/estate-snapshot.js +164 -0
  17. package/dist/estate-snapshot.js.map +1 -0
  18. package/dist/estate.d.ts +38 -0
  19. package/dist/estate.d.ts.map +1 -1
  20. package/dist/estate.js +71 -28
  21. package/dist/estate.js.map +1 -1
  22. package/dist/media-snapshot.d.ts +53 -0
  23. package/dist/media-snapshot.d.ts.map +1 -0
  24. package/dist/media-snapshot.js +66 -0
  25. package/dist/media-snapshot.js.map +1 -0
  26. package/dist/project.d.ts +20 -0
  27. package/dist/project.d.ts.map +1 -1
  28. package/dist/project.js +92 -2
  29. package/dist/project.js.map +1 -1
  30. package/dist/ready-cli.d.ts.map +1 -1
  31. package/dist/ready-cli.js +8 -3
  32. package/dist/ready-cli.js.map +1 -1
  33. package/dist/rule-registry.d.ts +5 -0
  34. package/dist/rule-registry.d.ts.map +1 -1
  35. package/dist/rule-registry.js +1 -0
  36. package/dist/rule-registry.js.map +1 -1
  37. package/dist/site-system/checks.d.ts +28 -3
  38. package/dist/site-system/checks.d.ts.map +1 -1
  39. package/dist/site-system/checks.js +5 -2
  40. package/dist/site-system/checks.js.map +1 -1
  41. package/dist/site-system/config.d.ts +13 -0
  42. package/dist/site-system/config.d.ts.map +1 -1
  43. package/dist/site-system/config.js +30 -1
  44. package/dist/site-system/config.js.map +1 -1
  45. package/dist/site-system/index.d.ts +1 -1
  46. package/dist/site-system/index.d.ts.map +1 -1
  47. package/dist/site-system/index.js +1 -1
  48. package/dist/site-system/index.js.map +1 -1
  49. package/dist/site-system/journeys/conversion.d.ts.map +1 -1
  50. package/dist/site-system/journeys/conversion.js +15 -2
  51. package/dist/site-system/journeys/conversion.js.map +1 -1
  52. package/dist/site-system/journeys/menu.d.ts.map +1 -1
  53. package/dist/site-system/journeys/menu.js +24 -1
  54. package/dist/site-system/journeys/menu.js.map +1 -1
  55. package/dist/site-system/journeys/page-helpers.d.ts.map +1 -1
  56. package/dist/site-system/journeys/page-helpers.js +1 -1
  57. package/dist/site-system/journeys/page-helpers.js.map +1 -1
  58. package/dist/site-system/journeys/plan.d.ts +13 -3
  59. package/dist/site-system/journeys/plan.d.ts.map +1 -1
  60. package/dist/site-system/journeys/plan.js +12 -2
  61. package/dist/site-system/journeys/plan.js.map +1 -1
  62. package/dist/site-system/journeys/shell.d.ts +1 -1
  63. package/dist/site-system/journeys/shell.js +2 -2
  64. package/dist/site-system/journeys/shell.js.map +1 -1
  65. package/dist/site-system/report.d.ts.map +1 -1
  66. package/dist/site-system/report.js +42 -8
  67. package/dist/site-system/report.js.map +1 -1
  68. package/dist/site-system/rule-modules.d.ts.map +1 -1
  69. package/dist/site-system/rule-modules.js +5 -0
  70. package/dist/site-system/rule-modules.js.map +1 -1
  71. package/dist/site-system/rules/delivery/h13-inbox.d.ts +23 -0
  72. package/dist/site-system/rules/delivery/h13-inbox.d.ts.map +1 -0
  73. package/dist/site-system/rules/delivery/h13-inbox.js +208 -0
  74. package/dist/site-system/rules/delivery/h13-inbox.js.map +1 -0
  75. package/dist/site-system/rules/delivery/index.d.ts +12 -0
  76. package/dist/site-system/rules/delivery/index.d.ts.map +1 -0
  77. package/dist/site-system/rules/delivery/index.js +7 -0
  78. package/dist/site-system/rules/delivery/index.js.map +1 -0
  79. package/dist/site-system/rules/form/c7-thank-you.d.ts +7 -1
  80. package/dist/site-system/rules/form/c7-thank-you.d.ts.map +1 -1
  81. package/dist/site-system/rules/form/c7-thank-you.js +26 -3
  82. package/dist/site-system/rules/form/c7-thank-you.js.map +1 -1
  83. package/dist/site-system/rules/form/index.d.ts.map +1 -1
  84. package/dist/site-system/rules/form/index.js +11 -1
  85. package/dist/site-system/rules/form/index.js.map +1 -1
  86. package/dist/site-system/rules/full/common.d.ts +2 -0
  87. package/dist/site-system/rules/full/common.d.ts.map +1 -1
  88. package/dist/site-system/rules/full/common.js.map +1 -1
  89. package/dist/site-system/rules/full/e1-pattern.d.ts +4 -0
  90. package/dist/site-system/rules/full/e1-pattern.d.ts.map +1 -0
  91. package/dist/site-system/rules/full/e1-pattern.js +47 -0
  92. package/dist/site-system/rules/full/e1-pattern.js.map +1 -0
  93. package/dist/site-system/rules/full/estate.d.ts +26 -3
  94. package/dist/site-system/rules/full/estate.d.ts.map +1 -1
  95. package/dist/site-system/rules/full/estate.js +58 -9
  96. package/dist/site-system/rules/full/estate.js.map +1 -1
  97. package/dist/site-system/rules/full/geography.d.ts +15 -2
  98. package/dist/site-system/rules/full/geography.d.ts.map +1 -1
  99. package/dist/site-system/rules/full/geography.js +15 -2
  100. package/dist/site-system/rules/full/geography.js.map +1 -1
  101. package/dist/site-system/rules/full/index.d.ts +4 -3
  102. package/dist/site-system/rules/full/index.d.ts.map +1 -1
  103. package/dist/site-system/rules/full/index.js +20 -5
  104. package/dist/site-system/rules/full/index.js.map +1 -1
  105. package/dist/site-system/rules/full/k12-slots.d.ts +4 -0
  106. package/dist/site-system/rules/full/k12-slots.d.ts.map +1 -0
  107. package/dist/site-system/rules/full/k12-slots.js +40 -0
  108. package/dist/site-system/rules/full/k12-slots.js.map +1 -0
  109. package/dist/site-system/rules/full/l10-location-copy.d.ts +1 -1
  110. package/dist/site-system/rules/full/l10-location-copy.d.ts.map +1 -1
  111. package/dist/site-system/rules/full/l10-location-copy.js +5 -2
  112. package/dist/site-system/rules/full/l10-location-copy.js.map +1 -1
  113. package/dist/site-system/rules/full/l3-neighbours.d.ts +3 -2
  114. package/dist/site-system/rules/full/l3-neighbours.d.ts.map +1 -1
  115. package/dist/site-system/rules/full/l3-neighbours.js +4 -1
  116. package/dist/site-system/rules/full/l3-neighbours.js.map +1 -1
  117. package/dist/site-system/rules/full/l4-local-copy.d.ts +2 -1
  118. package/dist/site-system/rules/full/l4-local-copy.d.ts.map +1 -1
  119. package/dist/site-system/rules/full/l4-local-copy.js +8 -3
  120. package/dist/site-system/rules/full/l4-local-copy.js.map +1 -1
  121. package/dist/site-system/rules/full/l9-data-contract.js +2 -2
  122. package/dist/site-system/rules/full/l9-data-contract.js.map +1 -1
  123. package/dist/site-system/rules/full/links.d.ts +3 -1
  124. package/dist/site-system/rules/full/links.d.ts.map +1 -1
  125. package/dist/site-system/rules/full/links.js +15 -5
  126. package/dist/site-system/rules/full/links.js.map +1 -1
  127. package/dist/site-system/rules/full/loc-index.d.ts +5 -0
  128. package/dist/site-system/rules/full/loc-index.d.ts.map +1 -1
  129. package/dist/site-system/rules/full/loc-index.js +43 -2
  130. package/dist/site-system/rules/full/loc-index.js.map +1 -1
  131. package/dist/site-system/rules/full/route-kinds.d.ts +15 -0
  132. package/dist/site-system/rules/full/route-kinds.d.ts.map +1 -0
  133. package/dist/site-system/rules/full/route-kinds.js +52 -0
  134. package/dist/site-system/rules/full/route-kinds.js.map +1 -0
  135. package/dist/site-system/rules/full/strategy.d.ts +6 -0
  136. package/dist/site-system/rules/full/strategy.d.ts.map +1 -1
  137. package/dist/site-system/rules/full/strategy.js +98 -10
  138. package/dist/site-system/rules/full/strategy.js.map +1 -1
  139. package/dist/site-system/rules/sections/k2-skin-coverage.d.ts +2 -2
  140. package/dist/site-system/rules/sections/k2-skin-coverage.d.ts.map +1 -1
  141. package/dist/site-system/rules/sections/k2-skin-coverage.js +13 -2
  142. package/dist/site-system/rules/sections/k2-skin-coverage.js.map +1 -1
  143. package/dist/site-system/rules/sections/t6-media-entries.d.ts.map +1 -1
  144. package/dist/site-system/rules/sections/t6-media-entries.js +69 -5
  145. package/dist/site-system/rules/sections/t6-media-entries.js.map +1 -1
  146. package/dist/site-system/runners.js +1 -1
  147. package/dist/site-system/runners.js.map +1 -1
  148. package/dist/site-system-e2e.d.ts +1 -1
  149. package/dist/site-system-e2e.d.ts.map +1 -1
  150. package/dist/site-system-e2e.js +17 -4
  151. package/dist/site-system-e2e.js.map +1 -1
  152. package/package.json +10 -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 { placeOfPath, type FullGeography, 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 string[] | 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\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 readonly h1: string;\n readonly place: PathPlace | undefined;\n family: string | undefined;\n familySource: \"manifest\" | \"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}): 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 );\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 ?? {});\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)?.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): { 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) : 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 h1: h1Element ? textOf(h1Element) : \"\",\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 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>>): void {\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 const seeded = pages.find((other) => other.familySource === \"route\" && other.srcRoute === page.srcRoute);\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: string[] | 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 jobs = cards.length > 0\n ? cards.map((card) => textOf(card, true)).filter(Boolean)\n : readableLines(jobsSection).map((line) => line.text).filter((text) => !headings.has(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(/&amp;/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":"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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(/&amp;/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"]}
@@ -50,11 +50,24 @@ export interface PathPlace {
50
50
  /** The path with the place replaced by `{place}`: pages sharing a stem are one family's pages. */
51
51
  readonly stem: string;
52
52
  }
53
+ /** Public slugs that differ from the registry's (strategy.ts `estate.slugs`, 3.14.0): public slug → registry slug. */
54
+ export interface PathAliases {
55
+ readonly regions: ReadonlyMap<string, string>;
56
+ readonly suburbs: ReadonlyMap<string, string>;
57
+ }
53
58
  /**
54
59
  * The place a path names: its last segment, or the end of its last segment after a hyphen (`/tree-removal-ryde`),
55
- * when that is a registry suburb or region (`{region}-area` included). The longest match wins.
60
+ * when that is a registry suburb or region (`{region}-area` included), or a public slug the estate plan renames
61
+ * (`ryde` for the region `ryde-area`, `ryde-suburb` for the suburb `ryde`), read first. The longest match wins.
56
62
  */
57
- export declare function placeOfPath(path: string, geography: FullGeography): PathPlace | undefined;
63
+ export declare function placeOfPath(path: string, geography: FullGeography, aliases?: PathAliases): PathPlace | undefined;
58
64
  /** A place's display name, for messages and for matching it in copy. */
65
+ /**
66
+ * Tree and plant names that start with a place name ("Sydney blue gum", "Port Jackson fig"). Masked before a job's
67
+ * free text is read for places, so a species is never taken for the suburb the job was in.
68
+ */
69
+ export declare const PLACE_COMPOUND_NAMES: RegExp;
70
+ /** The text with place-named species masked, for reading the places a job's free text names. */
71
+ export declare function withoutCompoundNames(text: string): string;
59
72
  export declare function placeName(slug: string, geography: FullGeography): string;
60
73
  //# sourceMappingURL=geography.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"geography.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/full/geography.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAmB,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAExG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC3D,wCAAwC;IACxC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC3D,wGAAwG;IACxG,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,mBAAmB,GAAG;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC,EAAE,CAAC;IACxF,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IAClH,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CACxC;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAoC5E;AAaD,iEAAiE;AACjE,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,aAAa,CAAC,CAmB1D;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACnC,kGAAkG;IAClG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,GAAG,SAAS,GAAG,SAAS,CAoBzF;AAMD,wEAAwE;AACxE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,GAAG,MAAM,CAExE"}
1
+ {"version":3,"file":"geography.d.ts","sourceRoot":"","sources":["../../../../src/site-system/rules/full/geography.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAmB,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAExG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC3D,wCAAwC;IACxC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC3D,wGAAwG;IACxG,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,mBAAmB,GAAG;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC,EAAE,CAAC;IACxF,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IAClH,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CACxC;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAoC5E;AAaD,iEAAiE;AACjE,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,aAAa,CAAC,CAmB1D;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACnC,kGAAkG;IAClG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,sHAAsH;AACtH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAsBhH;AAMD,wEAAwE;AACxE;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QACsG,CAAC;AAExI,gGAAgG;AAChG,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,GAAG,MAAM,CAExE"}
@@ -72,14 +72,18 @@ export function loadFullGeography() {
72
72
  }
73
73
  /**
74
74
  * The place a path names: its last segment, or the end of its last segment after a hyphen (`/tree-removal-ryde`),
75
- * when that is a registry suburb or region (`{region}-area` included). The longest match wins.
75
+ * when that is a registry suburb or region (`{region}-area` included), or a public slug the estate plan renames
76
+ * (`ryde` for the region `ryde-area`, `ryde-suburb` for the suburb `ryde`), read first. The longest match wins.
76
77
  */
77
- export function placeOfPath(path, geography) {
78
+ export function placeOfPath(path, geography, aliases) {
78
79
  const segments = path.split("/");
79
80
  const last = segments.pop() ?? "";
80
81
  if (!last)
81
82
  return undefined;
82
83
  const parent = segments.join("/");
84
+ const alias = aliases?.suburbs.get(last) ?? aliases?.regions.get(last);
85
+ if (alias !== undefined)
86
+ return { slug: alias, kind: aliases?.suburbs.has(last) ? "suburb" : "region", stem: `${parent}/{place}` };
83
87
  const kindOf = (slug) => {
84
88
  if (geography.suburbs.has(slug))
85
89
  return "suburb";
@@ -105,6 +109,15 @@ function regionSlug(slug, geography) {
105
109
  return !geography.suburbs.has(slug) && !geography.regions.has(slug) && slug.endsWith("-area") ? slug.slice(0, -5) : slug;
106
110
  }
107
111
  /** A place's display name, for messages and for matching it in copy. */
112
+ /**
113
+ * Tree and plant names that start with a place name ("Sydney blue gum", "Port Jackson fig"). Masked before a job's
114
+ * free text is read for places, so a species is never taken for the suburb the job was in.
115
+ */
116
+ export const PLACE_COMPOUND_NAMES = /\b(?:sydney\s+(?:blue|red)\s+gums?|sydney\s+peppermints?|sydney\s+golden\s+wattles?|port\s+jackson\s+(?:figs?|pines?|mallees?))\b/gi;
117
+ /** The text with place-named species masked, for reading the places a job's free text names. */
118
+ export function withoutCompoundNames(text) {
119
+ return text.replace(PLACE_COMPOUND_NAMES, (match) => " ".repeat(match.length));
120
+ }
108
121
  export function placeName(slug, geography) {
109
122
  return geography.suburbs.get(slug)?.name ?? geography.regions.get(slug)?.name ?? slug;
110
123
  }
@@ -1 +1 @@
1
- {"version":3,"file":"geography.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/geography.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The places the full tier reasons about: registry suburbs with their region and centre, and the regions. They come\n * from the site's installed site-core geography at run time (the conformance package compiles without site-core), or\n * from `defineFullGeography` in a test.\n */\nimport { createPlaceMask, type SuburbCentre, type SuburbCentreLookup } from \"../../../page-standard.js\";\n\nexport interface FullGeographySuburb {\n readonly slug: string;\n readonly name: string;\n /** The registry region the suburb belongs to. */\n readonly region: string;\n /** The suburb's council, when known. */\n readonly council?: string;\n}\n\nexport interface FullGeographyRegion {\n readonly slug: string;\n readonly name: string;\n /** Every name the region goes by (name, search name and alternates). */\n readonly names: readonly string[];\n}\n\nexport interface FullGeography {\n readonly centreOf: SuburbCentreLookup;\n readonly suburbs: ReadonlyMap<string, FullGeographySuburb>;\n /** Regions and sub-regions, by slug. */\n readonly regions: ReadonlyMap<string, FullGeographyRegion>;\n /** Masks every place name and postcode in lowercase text, so name-swapped copy compares as the same. */\n readonly mask: (text: string) => string;\n /** Lowercase place names (suburbs and regions) and their slugs. */\n readonly names: ReadonlyMap<string, string>;\n /** The slugs of the places a piece of copy names, longest name first (\"North Ryde\" before \"Ryde\"). */\n readonly placesIn: (text: string) => string[];\n}\n\nexport interface FullGeographyInput {\n readonly suburbs: readonly (FullGeographySuburb & { readonly centre?: SuburbCentre })[];\n readonly regions: readonly { readonly slug: string; readonly name: string; readonly names?: readonly string[] }[];\n readonly centreOf?: SuburbCentreLookup;\n}\n\nexport function defineFullGeography(input: FullGeographyInput): FullGeography {\n const suburbs = new Map<string, FullGeographySuburb>();\n const centres = new Map<string, SuburbCentre>();\n for (const suburb of input.suburbs) {\n if (suburbs.has(suburb.slug)) continue;\n suburbs.set(suburb.slug, { slug: suburb.slug, name: suburb.name, region: suburb.region, ...(suburb.council ? { council: suburb.council } : {}) });\n if (suburb.centre) centres.set(suburb.slug, suburb.centre);\n }\n const regions = new Map<string, FullGeographyRegion>();\n for (const region of input.regions) {\n if (!regions.has(region.slug)) regions.set(region.slug, { slug: region.slug, name: region.name, names: [...new Set([region.name, ...(region.names ?? [])])] });\n }\n const names = new Map<string, string>();\n for (const suburb of suburbs.values()) names.set(suburb.name.toLowerCase(), suburb.slug);\n for (const region of regions.values()) for (const name of region.names) if (!names.has(name.toLowerCase())) names.set(name.toLowerCase(), region.slug);\n const alternation = [...names.keys()]\n .filter((name) => name.length >= 3)\n .sort((left, right) => right.length - left.length)\n .map((name) => name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\s+/g, \"\\\\s+\"));\n const pattern = alternation.length > 0 ? new RegExp(`\\\\b(?:${alternation.join(\"|\")})\\\\b`, \"gi\") : null;\n return {\n centreOf: input.centreOf ?? ((slug) => centres.get(slug)),\n suburbs,\n regions,\n mask: createPlaceMask([...names.keys()]),\n names,\n placesIn: (text) => {\n if (!pattern) return [];\n const found = new Set<string>();\n for (const match of text.matchAll(pattern)) {\n const slug = names.get(match[0].toLowerCase().replace(/\\s+/g, \" \"));\n if (slug) found.add(slug);\n }\n return [...found];\n },\n };\n}\n\ninterface RegistryLike {\n suburbs: readonly { slug: string; name: string; regionSlug: string; councilSlug: string }[];\n nonSuburbLocalities: readonly { slug: string; name: string; regionSlug: string; councilSlug: string }[];\n regions: readonly { slug: string; name: string; seoName: string; alternateNames?: readonly string[] }[];\n subRegions: readonly { slug: string; name: string }[];\n}\n\n// A variable specifier, so the package compiles without site-core; it resolves to the site's installed copy.\nconst GEOGRAPHY_MODULE: string = \"@brandlab-digital/site-core/geography\";\nlet loaded: Promise<FullGeography> | undefined;\n\n/** The site's installed site-core geography (3.4.0 or later). */\nexport function loadFullGeography(): Promise<FullGeography> {\n loaded ??= (import(GEOGRAPHY_MODULE) as Promise<{\n getSuburbCentre?: SuburbCentreLookup;\n sydneyGeography: RegistryLike;\n centralCoastGeography: RegistryLike;\n }>).then((module) => {\n if (typeof module.getSuburbCentre !== \"function\") throw new Error(\"the installed site-core geography has no suburb centres (3.4.0 or later is needed)\");\n const registries = [module.sydneyGeography, module.centralCoastGeography];\n return defineFullGeography({\n suburbs: registries.flatMap((registry) =>\n [...registry.suburbs, ...registry.nonSuburbLocalities].map((place) => ({ slug: place.slug, name: place.name, region: place.regionSlug, council: place.councilSlug }))),\n regions: registries.flatMap((registry) => [\n ...registry.regions.map((region) => ({ slug: region.slug, name: region.name, names: [region.seoName, ...(region.alternateNames ?? [])] })),\n ...registry.subRegions.map((region) => ({ slug: region.slug, name: region.name })),\n ]),\n centreOf: module.getSuburbCentre,\n });\n });\n return loaded;\n}\n\nexport interface PathPlace {\n readonly slug: string;\n readonly kind: \"suburb\" | \"region\";\n /** The path with the place replaced by `{place}`: pages sharing a stem are one family's pages. */\n readonly stem: string;\n}\n\n/**\n * The place a path names: its last segment, or the end of its last segment after a hyphen (`/tree-removal-ryde`),\n * when that is a registry suburb or region (`{region}-area` included). The longest match wins.\n */\nexport function placeOfPath(path: string, geography: FullGeography): PathPlace | undefined {\n const segments = path.split(\"/\");\n const last = segments.pop() ?? \"\";\n if (!last) return undefined;\n const parent = segments.join(\"/\");\n const kindOf = (slug: string): PathPlace[\"kind\"] | undefined => {\n if (geography.suburbs.has(slug)) return \"suburb\";\n if (geography.regions.has(slug)) return \"region\";\n if (slug.endsWith(\"-area\") && geography.regions.has(slug.slice(0, -5))) return \"region\";\n return undefined;\n };\n const whole = kindOf(last);\n if (whole) return { slug: regionSlug(last, geography), kind: whole, stem: `${parent}/{place}` };\n const parts = last.split(\"-\");\n for (let start = 1; start < parts.length; start += 1) {\n const slug = parts.slice(start).join(\"-\");\n const kind = kindOf(slug);\n if (kind) return { slug: regionSlug(slug, geography), kind, stem: `${parent}/${parts.slice(0, start).join(\"-\")}-{place}` };\n }\n return undefined;\n}\n\nfunction regionSlug(slug: string, geography: FullGeography): string {\n return !geography.suburbs.has(slug) && !geography.regions.has(slug) && slug.endsWith(\"-area\") ? slug.slice(0, -5) : slug;\n}\n\n/** A place's display name, for messages and for matching it in copy. */\nexport function placeName(slug: string, geography: FullGeography): string {\n return geography.suburbs.get(slug)?.name ?? geography.regions.get(slug)?.name ?? slug;\n}\n"]}
1
+ {"version":3,"file":"geography.js","sourceRoot":"","sources":["../../../../src/site-system/rules/full/geography.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The places the full tier reasons about: registry suburbs with their region and centre, and the regions. They come\n * from the site's installed site-core geography at run time (the conformance package compiles without site-core), or\n * from `defineFullGeography` in a test.\n */\nimport { createPlaceMask, type SuburbCentre, type SuburbCentreLookup } from \"../../../page-standard.js\";\n\nexport interface FullGeographySuburb {\n readonly slug: string;\n readonly name: string;\n /** The registry region the suburb belongs to. */\n readonly region: string;\n /** The suburb's council, when known. */\n readonly council?: string;\n}\n\nexport interface FullGeographyRegion {\n readonly slug: string;\n readonly name: string;\n /** Every name the region goes by (name, search name and alternates). */\n readonly names: readonly string[];\n}\n\nexport interface FullGeography {\n readonly centreOf: SuburbCentreLookup;\n readonly suburbs: ReadonlyMap<string, FullGeographySuburb>;\n /** Regions and sub-regions, by slug. */\n readonly regions: ReadonlyMap<string, FullGeographyRegion>;\n /** Masks every place name and postcode in lowercase text, so name-swapped copy compares as the same. */\n readonly mask: (text: string) => string;\n /** Lowercase place names (suburbs and regions) and their slugs. */\n readonly names: ReadonlyMap<string, string>;\n /** The slugs of the places a piece of copy names, longest name first (\"North Ryde\" before \"Ryde\"). */\n readonly placesIn: (text: string) => string[];\n}\n\nexport interface FullGeographyInput {\n readonly suburbs: readonly (FullGeographySuburb & { readonly centre?: SuburbCentre })[];\n readonly regions: readonly { readonly slug: string; readonly name: string; readonly names?: readonly string[] }[];\n readonly centreOf?: SuburbCentreLookup;\n}\n\nexport function defineFullGeography(input: FullGeographyInput): FullGeography {\n const suburbs = new Map<string, FullGeographySuburb>();\n const centres = new Map<string, SuburbCentre>();\n for (const suburb of input.suburbs) {\n if (suburbs.has(suburb.slug)) continue;\n suburbs.set(suburb.slug, { slug: suburb.slug, name: suburb.name, region: suburb.region, ...(suburb.council ? { council: suburb.council } : {}) });\n if (suburb.centre) centres.set(suburb.slug, suburb.centre);\n }\n const regions = new Map<string, FullGeographyRegion>();\n for (const region of input.regions) {\n if (!regions.has(region.slug)) regions.set(region.slug, { slug: region.slug, name: region.name, names: [...new Set([region.name, ...(region.names ?? [])])] });\n }\n const names = new Map<string, string>();\n for (const suburb of suburbs.values()) names.set(suburb.name.toLowerCase(), suburb.slug);\n for (const region of regions.values()) for (const name of region.names) if (!names.has(name.toLowerCase())) names.set(name.toLowerCase(), region.slug);\n const alternation = [...names.keys()]\n .filter((name) => name.length >= 3)\n .sort((left, right) => right.length - left.length)\n .map((name) => name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\s+/g, \"\\\\s+\"));\n const pattern = alternation.length > 0 ? new RegExp(`\\\\b(?:${alternation.join(\"|\")})\\\\b`, \"gi\") : null;\n return {\n centreOf: input.centreOf ?? ((slug) => centres.get(slug)),\n suburbs,\n regions,\n mask: createPlaceMask([...names.keys()]),\n names,\n placesIn: (text) => {\n if (!pattern) return [];\n const found = new Set<string>();\n for (const match of text.matchAll(pattern)) {\n const slug = names.get(match[0].toLowerCase().replace(/\\s+/g, \" \"));\n if (slug) found.add(slug);\n }\n return [...found];\n },\n };\n}\n\ninterface RegistryLike {\n suburbs: readonly { slug: string; name: string; regionSlug: string; councilSlug: string }[];\n nonSuburbLocalities: readonly { slug: string; name: string; regionSlug: string; councilSlug: string }[];\n regions: readonly { slug: string; name: string; seoName: string; alternateNames?: readonly string[] }[];\n subRegions: readonly { slug: string; name: string }[];\n}\n\n// A variable specifier, so the package compiles without site-core; it resolves to the site's installed copy.\nconst GEOGRAPHY_MODULE: string = \"@brandlab-digital/site-core/geography\";\nlet loaded: Promise<FullGeography> | undefined;\n\n/** The site's installed site-core geography (3.4.0 or later). */\nexport function loadFullGeography(): Promise<FullGeography> {\n loaded ??= (import(GEOGRAPHY_MODULE) as Promise<{\n getSuburbCentre?: SuburbCentreLookup;\n sydneyGeography: RegistryLike;\n centralCoastGeography: RegistryLike;\n }>).then((module) => {\n if (typeof module.getSuburbCentre !== \"function\") throw new Error(\"the installed site-core geography has no suburb centres (3.4.0 or later is needed)\");\n const registries = [module.sydneyGeography, module.centralCoastGeography];\n return defineFullGeography({\n suburbs: registries.flatMap((registry) =>\n [...registry.suburbs, ...registry.nonSuburbLocalities].map((place) => ({ slug: place.slug, name: place.name, region: place.regionSlug, council: place.councilSlug }))),\n regions: registries.flatMap((registry) => [\n ...registry.regions.map((region) => ({ slug: region.slug, name: region.name, names: [region.seoName, ...(region.alternateNames ?? [])] })),\n ...registry.subRegions.map((region) => ({ slug: region.slug, name: region.name })),\n ]),\n centreOf: module.getSuburbCentre,\n });\n });\n return loaded;\n}\n\nexport interface PathPlace {\n readonly slug: string;\n readonly kind: \"suburb\" | \"region\";\n /** The path with the place replaced by `{place}`: pages sharing a stem are one family's pages. */\n readonly stem: string;\n}\n\n/** Public slugs that differ from the registry's (strategy.ts `estate.slugs`, 3.14.0): public slug → registry slug. */\nexport interface PathAliases {\n readonly regions: ReadonlyMap<string, string>;\n readonly suburbs: ReadonlyMap<string, string>;\n}\n\n/**\n * The place a path names: its last segment, or the end of its last segment after a hyphen (`/tree-removal-ryde`),\n * when that is a registry suburb or region (`{region}-area` included), or a public slug the estate plan renames\n * (`ryde` for the region `ryde-area`, `ryde-suburb` for the suburb `ryde`), read first. The longest match wins.\n */\nexport function placeOfPath(path: string, geography: FullGeography, aliases?: PathAliases): PathPlace | undefined {\n const segments = path.split(\"/\");\n const last = segments.pop() ?? \"\";\n if (!last) return undefined;\n const parent = segments.join(\"/\");\n const alias = aliases?.suburbs.get(last) ?? aliases?.regions.get(last);\n if (alias !== undefined) return { slug: alias, kind: aliases?.suburbs.has(last) ? \"suburb\" : \"region\", stem: `${parent}/{place}` };\n const kindOf = (slug: string): PathPlace[\"kind\"] | undefined => {\n if (geography.suburbs.has(slug)) return \"suburb\";\n if (geography.regions.has(slug)) return \"region\";\n if (slug.endsWith(\"-area\") && geography.regions.has(slug.slice(0, -5))) return \"region\";\n return undefined;\n };\n const whole = kindOf(last);\n if (whole) return { slug: regionSlug(last, geography), kind: whole, stem: `${parent}/{place}` };\n const parts = last.split(\"-\");\n for (let start = 1; start < parts.length; start += 1) {\n const slug = parts.slice(start).join(\"-\");\n const kind = kindOf(slug);\n if (kind) return { slug: regionSlug(slug, geography), kind, stem: `${parent}/${parts.slice(0, start).join(\"-\")}-{place}` };\n }\n return undefined;\n}\n\nfunction regionSlug(slug: string, geography: FullGeography): string {\n return !geography.suburbs.has(slug) && !geography.regions.has(slug) && slug.endsWith(\"-area\") ? slug.slice(0, -5) : slug;\n}\n\n/** A place's display name, for messages and for matching it in copy. */\n/**\n * Tree and plant names that start with a place name (\"Sydney blue gum\", \"Port Jackson fig\"). Masked before a job's\n * free text is read for places, so a species is never taken for the suburb the job was in.\n */\nexport const PLACE_COMPOUND_NAMES =\n /\\b(?:sydney\\s+(?:blue|red)\\s+gums?|sydney\\s+peppermints?|sydney\\s+golden\\s+wattles?|port\\s+jackson\\s+(?:figs?|pines?|mallees?))\\b/gi;\n\n/** The text with place-named species masked, for reading the places a job's free text names. */\nexport function withoutCompoundNames(text: string): string {\n return text.replace(PLACE_COMPOUND_NAMES, (match) => \" \".repeat(match.length));\n}\n\nexport function placeName(slug: string, geography: FullGeography): string {\n return geography.suburbs.get(slug)?.name ?? geography.regions.get(slug)?.name ?? slug;\n}\n"]}
@@ -5,17 +5,18 @@ import { type FullGeography } from "./geography.js";
5
5
  export { FULL_LISTED_FAILURES, type FullContext } from "./common.js";
6
6
  export { headingPhrase } from "./e10-phrases.js";
7
7
  export { readEstate, type Estate, type EstatePage, type LocationCopy, type ManifestData } from "./estate.js";
8
- export { defineFullGeography, loadFullGeography, placeOfPath, type FullGeography, type FullGeographyInput } from "./geography.js";
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
10
  export { L3_MAX_LIST, L3_MIN_LIST, L3_TOLERANCE_KM } from "./l3-neighbours.js";
11
11
  export { L4_MIN_ROTATION_PAGES, L4_MIN_TEMPLATE_WORDS } from "./l4-local-copy.js";
12
12
  export { yearStamp } from "./l10-location-copy.js";
13
13
  export { L6_MIN_INBOUND, L6_MIN_PAGE_TYPES, L7_MAX_DEPTH, clickDepths } from "./links.js";
14
+ export { CATALOGUE_HUB_FAMILIES, ROUTE_CATALOGUE_FILE, linkingPageType, readRouteCatalogueKinds } from "./route-kinds.js";
14
15
  export { sydneyDay } from "./loc-index.js";
15
16
  export { W3_FAMILIES, W3_MIN_REVALIDATE_SECONDS, refreshInterval } from "./w3-refresh.js";
16
- export { FULL_STRATEGY_FILE, WAVE_MAX_GAP_DAYS, WAVE_MIN_GAP_DAYS, matchesWaveRoute, normalisePhrase, readFullStrategy, waveScheduleProblems } from "./strategy.js";
17
+ export { ESTATE_PLAN_SNAPSHOT_FILE, FULL_STRATEGY_FILE, WAVE_MAX_GAP_DAYS, WAVE_MIN_GAP_DAYS, matchesWaveRoute, normalisePhrase, readFullStrategy, waveScheduleProblems } from "./strategy.js";
17
18
  /** The full-tier checks this module runs, in the order their findings are returned. */
18
- export declare const FULL_TIER_CHECK_IDS: readonly ["K12", "E5", "E10", "L3", "L4", "L6", "L7", "L8", "L9", "L10", "S4", "LOC-INDEX", "W3"];
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"];
19
20
  export interface FullTierRuleOptions {
20
21
  /** The day waves are judged on. Defaults to now. */
21
22
  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;AAG/C,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAYvE,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,MAAM,gBAAgB,CAAC;AAClI,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,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEpK,uFAAuF;AACvF,eAAO,MAAM,mBAAmB,mGAA2I,CAAC;AAE5K,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;AAwCD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAgDvC"}
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;AAczF,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,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,8HAAsK,CAAC;AAEvM,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,CAsDvC"}
@@ -2,21 +2,24 @@
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), 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), 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";
9
9
  import { readSiteSystemProjectConfig } from "../../config.js";
10
10
  import {} from "./common.js";
11
+ import { checkE1Pattern } from "./e1-pattern.js";
11
12
  import { checkE10 } from "./e10-phrases.js";
12
13
  import { readEstate } from "./estate.js";
13
14
  import { loadFullGeography } from "./geography.js";
14
15
  import { checkK12 } from "./k12-manifests.js";
16
+ import { checkK12Slots } from "./k12-slots.js";
15
17
  import { checkL3 } from "./l3-neighbours.js";
16
18
  import { checkL4 } from "./l4-local-copy.js";
17
19
  import { checkL9 } from "./l9-data-contract.js";
18
20
  import { checkL10 } from "./l10-location-copy.js";
19
21
  import { checkE5, checkL6, checkL7, checkL8, inboundLinks } from "./links.js";
22
+ import { readRouteCatalogueKinds } from "./route-kinds.js";
20
23
  import { checkLocationIndexing, sydneyDay } from "./loc-index.js";
21
24
  import { checkS4 } from "./s4-route-files.js";
22
25
  import { readFullStrategy } from "./strategy.js";
@@ -30,11 +33,12 @@ export { L3_MAX_LIST, L3_MIN_LIST, L3_TOLERANCE_KM } from "./l3-neighbours.js";
30
33
  export { L4_MIN_ROTATION_PAGES, L4_MIN_TEMPLATE_WORDS } from "./l4-local-copy.js";
31
34
  export { yearStamp } from "./l10-location-copy.js";
32
35
  export { L6_MIN_INBOUND, L6_MIN_PAGE_TYPES, L7_MAX_DEPTH, clickDepths } from "./links.js";
36
+ export { CATALOGUE_HUB_FAMILIES, ROUTE_CATALOGUE_FILE, linkingPageType, readRouteCatalogueKinds } from "./route-kinds.js";
33
37
  export { sydneyDay } from "./loc-index.js";
34
38
  export { W3_FAMILIES, W3_MIN_REVALIDATE_SECONDS, refreshInterval } from "./w3-refresh.js";
35
- export { FULL_STRATEGY_FILE, WAVE_MAX_GAP_DAYS, WAVE_MIN_GAP_DAYS, matchesWaveRoute, normalisePhrase, readFullStrategy, waveScheduleProblems } from "./strategy.js";
39
+ export { ESTATE_PLAN_SNAPSHOT_FILE, FULL_STRATEGY_FILE, WAVE_MAX_GAP_DAYS, WAVE_MIN_GAP_DAYS, matchesWaveRoute, normalisePhrase, readFullStrategy, waveScheduleProblems } from "./strategy.js";
36
40
  /** The full-tier checks this module runs, in the order their findings are returned. */
37
- export const FULL_TIER_CHECK_IDS = ["K12", "E5", "E10", "L3", "L4", "L6", "L7", "L8", "L9", "L10", "S4", "LOC-INDEX", "W3"];
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"];
38
42
  // Variable specifiers, so the package compiles without site-core; they resolve to the site's installed copy.
39
43
  const SECTION_ORDER_MODULE = "@brandlab-digital/site-core/section-order";
40
44
  async function loadDefaultOrder() {
@@ -72,6 +76,11 @@ function projectSettings(projectRoot) {
72
76
  return { tier: null, service: undefined, refreshExceptions: [] };
73
77
  }
74
78
  }
79
+ /** The estate plan's public slugs as path aliases: public slug → registry slug. */
80
+ function pathAliases(plan) {
81
+ const flip = (renames) => new Map(Object.entries(renames ?? {}).map(([registry, slug]) => [slug, registry]));
82
+ return { regions: flip(plan.slugs?.regions), suburbs: flip(plan.slugs?.suburbs) };
83
+ }
75
84
  /**
76
85
  * Runs the full-tier rules over the built estate at `projectRoot`. A site that declares a lower tier (or none) gets no
77
86
  * findings: the report shows the full checks as not run, which never blocks below the full tier.
@@ -95,19 +104,23 @@ export async function runFullTierRules(input, options = {}) {
95
104
  geographyProblem = `site-core's geography could not be imported: ${error instanceof Error ? error.message : String(error)}`;
96
105
  }
97
106
  }
107
+ const today = sydneyDay(options.asOf ?? new Date());
108
+ const strategy = readFullStrategy(input.projectRoot, today);
98
109
  const estate = readEstate({
99
110
  pages: input.pages,
100
111
  buildDir: options.buildDir ?? input.buildDir ?? join(input.projectRoot, ".next"),
101
112
  geography,
102
113
  ...(settings.service ? { seeds: { [settings.service]: "service" } } : {}),
114
+ ...(strategy.estate?.slugs ? { aliases: pathAliases(strategy.estate) } : {}),
115
+ ...(strategy.estate?.paths ? { paths: strategy.estate.paths } : {}),
103
116
  });
104
- const today = sydneyDay(options.asOf ?? new Date());
105
117
  const context = {
106
118
  estate,
107
119
  geography,
108
120
  geographyProblem,
109
- strategy: readFullStrategy(input.projectRoot, today),
121
+ strategy,
110
122
  projectRoot: input.projectRoot,
123
+ catalogueKinds: readRouteCatalogueKinds(input.projectRoot),
111
124
  refreshExceptions: settings.refreshExceptions,
112
125
  today,
113
126
  defaultOrder: options.defaultOrder ?? (await loadDefaultOrder()),
@@ -115,6 +128,8 @@ export async function runFullTierRules(input, options = {}) {
115
128
  const inbound = inboundLinks(estate);
116
129
  const findings = [
117
130
  ...checkK12(context),
131
+ ...checkK12Slots(context),
132
+ ...checkE1Pattern(context),
118
133
  ...checkE5(context, inbound),
119
134
  ...checkE10(context),
120
135
  ...checkL3(context),