@brandlab-digital/site-core 0.1.0-alpha.18 → 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/locations.js DELETED
@@ -1,118 +0,0 @@
1
- /**
2
- * Location-page gate primitives and geography-registry contracts
3
- * (Brandlab Location Pages Standard §5, §7).
4
- *
5
- * The programmatic-quality gate is lifted from the accepted benchmark
6
- * implementation (sydney-tree-services `src/data/services/quality.ts`) so
7
- * every project derives draft/noindex/indexable the same way. The registry
8
- * types describe `standards/registry/sydney-geography.json` and the committed
9
- * snapshots client repos validate against.
10
- */
11
- export function isIndexableProgrammaticRecord(record) {
12
- return record.indexationStatus === 'indexable';
13
- }
14
- export function getProofLevelFromAssetIds(proofAssetIds) {
15
- if (proofAssetIds.some((proofAssetId) => proofAssetId.startsWith('project:'))) {
16
- return 'project';
17
- }
18
- if (proofAssetIds.some((proofAssetId) => proofAssetId.startsWith('region-review:'))) {
19
- return 'review';
20
- }
21
- if (proofAssetIds.some((proofAssetId) => proofAssetId.startsWith('council-source:'))) {
22
- return 'council';
23
- }
24
- return 'none';
25
- }
26
- /**
27
- * The portfolio indexation gate: thin content or missing proof can never be
28
- * invited into the index; fewer than three unique local signals keeps a page
29
- * in draft (standard §7.1).
30
- */
31
- export function resolveIndexationStatus({ contentDepth, proofLevel, uniqueLocalSignals, }) {
32
- if (contentDepth === 'thin' || proofLevel === 'none') {
33
- return 'noindex';
34
- }
35
- if (uniqueLocalSignals.length < 3) {
36
- return 'draft';
37
- }
38
- return 'indexable';
39
- }
40
- /** Canonical Brandlab slugify — identical to the benchmark implementation. */
41
- export function toLocationSlug(name) {
42
- return name
43
- .toLowerCase()
44
- .replace(/[^a-z0-9]+/g, '-')
45
- .replace(/(^-|-$)/g, '');
46
- }
47
- /** Resolve a possibly-legacy region/council slug to its canonical form. */
48
- export function resolveRegistryAlias(slug, registry) {
49
- return registry.aliases[slug] ?? slug;
50
- }
51
- /**
52
- * Validate a project catalog subset against the shared registry. Alias slugs
53
- * are resolved before comparison so migrated repos that kept live URLs can
54
- * still pass. Returns an empty array when the subset is clean.
55
- */
56
- export function validateCatalogAgainstRegistry(catalog, registry) {
57
- const issues = [];
58
- const regionSlugSet = new Set(registry.regions.map((region) => region.slug));
59
- const subRegionSlugSet = new Set(registry.subRegions.map((subRegion) => subRegion.slug));
60
- const councilSlugSet = new Set(registry.councils.map((council) => council.slug));
61
- const suburbBySlug = new Map(registry.suburbs.map((suburb) => [suburb.slug, suburb]));
62
- for (const rawRegionSlug of catalog.regionSlugs) {
63
- const regionSlug = resolveRegistryAlias(rawRegionSlug, registry);
64
- if (!regionSlugSet.has(regionSlug) && !subRegionSlugSet.has(regionSlug)) {
65
- issues.push({
66
- kind: 'unknown-region',
67
- slug: rawRegionSlug,
68
- detail: `Region slug "${rawRegionSlug}" is not a registry region, sub-region, or alias.`,
69
- });
70
- }
71
- }
72
- for (const suburb of catalog.suburbs) {
73
- const resolvedSuburbSlug = suburbBySlug.has(suburb.slug)
74
- ? suburb.slug
75
- : resolveRegistryAlias(suburb.slug, registry);
76
- const registrySuburb = suburbBySlug.get(resolvedSuburbSlug);
77
- if (!registrySuburb) {
78
- issues.push({
79
- kind: 'unknown-suburb',
80
- slug: suburb.slug,
81
- detail: `Suburb slug "${suburb.slug}" is not in the registry (not gazetted, or needs adding to the registry first).`,
82
- });
83
- continue;
84
- }
85
- const regionSlug = resolveRegistryAlias(suburb.regionSlug, registry);
86
- const regionMatches = registrySuburb.regionSlug === regionSlug ||
87
- registry.subRegions.some((subRegion) => subRegion.slug === regionSlug &&
88
- subRegion.parentRegionSlug === registrySuburb.regionSlug &&
89
- (!subRegion.suburbSlugs || subRegion.suburbSlugs.includes(registrySuburb.slug)));
90
- if (!regionMatches) {
91
- issues.push({
92
- kind: 'suburb-region-mismatch',
93
- slug: suburb.slug,
94
- detail: `Suburb "${suburb.slug}" is assigned to "${suburb.regionSlug}" but the registry places it in "${registrySuburb.regionSlug}".`,
95
- });
96
- }
97
- if (suburb.councilSlug) {
98
- const councilSlug = resolveRegistryAlias(suburb.councilSlug, registry);
99
- if (!councilSlugSet.has(councilSlug)) {
100
- issues.push({
101
- kind: 'unknown-council',
102
- slug: suburb.councilSlug,
103
- detail: `Council slug "${suburb.councilSlug}" is not a registry council or alias.`,
104
- });
105
- }
106
- else if (registrySuburb.councilSlug !== councilSlug &&
107
- !registrySuburb.sharedCouncilSlugs?.includes(councilSlug)) {
108
- issues.push({
109
- kind: 'suburb-council-mismatch',
110
- slug: suburb.slug,
111
- detail: `Suburb "${suburb.slug}" is assigned to council "${suburb.councilSlug}" but the registry places it under "${registrySuburb.councilSlug}".`,
112
- });
113
- }
114
- }
115
- }
116
- return issues;
117
- }
118
- //# sourceMappingURL=locations.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"locations.js","sourceRoot":"","sources":["../src/locations.ts"],"names":[],"mappings":"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"}
@@ -1,8 +0,0 @@
1
- export interface RichTextHrefPolicy {
2
- allowedProtocols?: readonly string[];
3
- allowInternalPaths?: boolean;
4
- allowHashLinks?: boolean;
5
- }
6
- export declare function sanitizeRichTextHref(href: string, { allowedProtocols, allowInternalPaths, allowHashLinks, }?: RichTextHrefPolicy): string | null;
7
- export declare function assertSafeRichTextHref(href: string, policy?: RichTextHrefPolicy): string;
8
- //# sourceMappingURL=rich-text.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rich-text.d.ts","sourceRoot":"","sources":["../src/rich-text.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AASD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,EACE,gBAA4C,EAC5C,kBAAyB,EACzB,cAAqB,GACtB,GAAE,kBAAuB,GACzB,MAAM,GAAG,IAAI,CAuBf;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB,UAQ/E"}
package/dist/rich-text.js DELETED
@@ -1,34 +0,0 @@
1
- const DEFAULT_ALLOWED_PROTOCOLS = ['https:', 'mailto:', 'tel:'];
2
- const CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/;
3
- function normalizeAllowedProtocols(protocols) {
4
- return new Set(protocols.map((protocol) => protocol.toLowerCase()));
5
- }
6
- export function sanitizeRichTextHref(href, { allowedProtocols = DEFAULT_ALLOWED_PROTOCOLS, allowInternalPaths = true, allowHashLinks = true, } = {}) {
7
- const value = href.trim();
8
- if (!value || CONTROL_CHARACTER_PATTERN.test(value)) {
9
- return null;
10
- }
11
- if (allowHashLinks && value.startsWith('#')) {
12
- return value;
13
- }
14
- if (allowInternalPaths && value.startsWith('/')) {
15
- return value.startsWith('//') ? null : value;
16
- }
17
- try {
18
- const url = new URL(value);
19
- return normalizeAllowedProtocols(allowedProtocols).has(url.protocol.toLowerCase())
20
- ? value
21
- : null;
22
- }
23
- catch {
24
- return null;
25
- }
26
- }
27
- export function assertSafeRichTextHref(href, policy) {
28
- const sanitizedHref = sanitizeRichTextHref(href, policy);
29
- if (!sanitizedHref) {
30
- throw new Error('Unsafe rich text link href.');
31
- }
32
- return sanitizedHref;
33
- }
34
- //# sourceMappingURL=rich-text.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rich-text.js","sourceRoot":"","sources":["../src/rich-text.ts"],"names":[],"mappings":"AAMA,MAAM,yBAAyB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAU,CAAA;AACxE,MAAM,yBAAyB,GAAG,uBAAuB,CAAA;AAEzD,SAAS,yBAAyB,CAAC,SAA4B;IAC7D,OAAO,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;AACrE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAAY,EACZ,EACE,gBAAgB,GAAG,yBAAyB,EAC5C,kBAAkB,GAAG,IAAI,EACzB,cAAc,GAAG,IAAI,MACC,EAAE;IAE1B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAEzB,IAAI,CAAC,KAAK,IAAI,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,cAAc,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,kBAAkB,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAA;IAC9C,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;QAC1B,OAAO,yBAAyB,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;YAChF,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,IAAI,CAAA;IACV,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,MAA2B;IAC9E,MAAM,aAAa,GAAG,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAExD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAChD,CAAC;IAED,OAAO,aAAa,CAAA;AACtB,CAAC"}