@brandlab-digital/site-core 0.1.0-alpha.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.
@@ -0,0 +1,17 @@
1
+ export declare const CANONICAL_LEAD_EVENTS: readonly ["phone_call", "contact_form"];
2
+ export type CanonicalLeadEvent = (typeof CANONICAL_LEAD_EVENTS)[number];
3
+ export type GtagTransport = (command: 'event', eventName: string, params: Record<string, unknown>) => void;
4
+ export declare function isCanonicalLeadEvent(value: string): value is CanonicalLeadEvent;
5
+ export declare function normalizeGoogleAdsConversionId(conversionId: string): string;
6
+ export declare function getGoogleAdsContactSendTo(options: {
7
+ conversionId?: string | null;
8
+ conversionLabel?: string | null;
9
+ }): string | undefined;
10
+ export declare function sendBrandlabAnalyticsEvent(options: {
11
+ enabled: boolean;
12
+ measurementId?: string | null;
13
+ gtag?: GtagTransport;
14
+ eventName: string;
15
+ params: Record<string, unknown>;
16
+ }): boolean;
17
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,yCAA0C,CAAA;AAE5E,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAA;AACvE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;AAE1G,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,kBAAkB,CAE/E;AAED,wBAAgB,8BAA8B,CAAC,YAAY,EAAE,MAAM,UAGlE;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE;IACjD,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC,sBASA;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE;IAClD,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,IAAI,CAAC,EAAE,aAAa,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC,WAWA"}
@@ -0,0 +1,27 @@
1
+ export const CANONICAL_LEAD_EVENTS = ['phone_call', 'contact_form'];
2
+ export function isCanonicalLeadEvent(value) {
3
+ return CANONICAL_LEAD_EVENTS.includes(value);
4
+ }
5
+ export function normalizeGoogleAdsConversionId(conversionId) {
6
+ const trimmed = conversionId.trim();
7
+ return trimmed.startsWith('AW-') ? trimmed : `AW-${trimmed}`;
8
+ }
9
+ export function getGoogleAdsContactSendTo(options) {
10
+ const conversionId = options.conversionId?.trim();
11
+ const conversionLabel = options.conversionLabel?.trim();
12
+ if (!conversionId || !conversionLabel) {
13
+ return undefined;
14
+ }
15
+ return `${normalizeGoogleAdsConversionId(conversionId)}/${conversionLabel}`;
16
+ }
17
+ export function sendBrandlabAnalyticsEvent(options) {
18
+ if (!options.enabled || !options.measurementId || typeof options.gtag !== 'function') {
19
+ return false;
20
+ }
21
+ options.gtag('event', options.eventName, {
22
+ ...options.params,
23
+ send_to: options.measurementId,
24
+ });
25
+ return true;
26
+ }
27
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,YAAY,EAAE,cAAc,CAAU,CAAA;AAK5E,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,qBAAqB,CAAC,QAAQ,CAAC,KAA2B,CAAC,CAAA;AACpE,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,YAAoB;IACjE,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,CAAA;IACnC,OAAO,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,EAAE,CAAA;AAC9D,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAGzC;IACC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,IAAI,EAAE,CAAA;IACjD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,EAAE,IAAI,EAAE,CAAA;IAEvD,IAAI,CAAC,YAAY,IAAI,CAAC,eAAe,EAAE,CAAC;QACtC,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,GAAG,8BAA8B,CAAC,YAAY,CAAC,IAAI,eAAe,EAAE,CAAA;AAC7E,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,OAM1C;IACC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACrF,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE;QACvC,GAAG,OAAO,CAAC,MAAM;QACjB,OAAO,EAAE,OAAO,CAAC,aAAa;KAC/B,CAAC,CAAA;IAEF,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface BreadcrumbItem {
2
+ name: string;
3
+ href?: string;
4
+ }
5
+ export interface BuildBreadcrumbsOptions {
6
+ labelResolver?: (segment: string, options?: BuildBreadcrumbsOptions) => string;
7
+ }
8
+ export declare function formatSegmentTitle(segment: string): string;
9
+ export declare function buildBreadcrumbs(path: string, options?: BuildBreadcrumbsOptions): BreadcrumbItem[];
10
+ //# sourceMappingURL=breadcrumbs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../src/breadcrumbs.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,KAAK,MAAM,CAAA;CAC/E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,uBAAuB,GAChC,cAAc,EAAE,CAiBlB"}
@@ -0,0 +1,24 @@
1
+ export function formatSegmentTitle(segment) {
2
+ return segment
3
+ .split('-')
4
+ .filter(Boolean)
5
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
6
+ .join(' ');
7
+ }
8
+ export function buildBreadcrumbs(path, options) {
9
+ if (path === '/')
10
+ return [{ name: 'Home', href: '/' }];
11
+ const resolveLabel = options?.labelResolver ?? formatSegmentTitle;
12
+ const breadcrumbs = [{ name: 'Home', href: '/' }];
13
+ const segments = path.split('?')[0]?.split('/').filter(Boolean) ?? [];
14
+ let currentPath = '';
15
+ for (const segment of segments) {
16
+ currentPath += `/${segment}`;
17
+ breadcrumbs.push({
18
+ name: resolveLabel(segment, options),
19
+ href: currentPath,
20
+ });
21
+ }
22
+ return breadcrumbs;
23
+ }
24
+ //# sourceMappingURL=breadcrumbs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breadcrumbs.js","sourceRoot":"","sources":["../src/breadcrumbs.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,OAAO,OAAO;SACX,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,OAAiC;IAEjC,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAA;IAEtD,MAAM,YAAY,GAAG,OAAO,EAAE,aAAa,IAAI,kBAAkB,CAAA;IACjE,MAAM,WAAW,GAAqB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAA;IACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;IACrE,IAAI,WAAW,GAAG,EAAE,CAAA;IAEpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,WAAW,IAAI,IAAI,OAAO,EAAE,CAAA;QAC5B,WAAW,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC;YACpC,IAAI,EAAE,WAAW;SAClB,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,WAAW,CAAA;AACpB,CAAC"}
@@ -0,0 +1,59 @@
1
+ export interface ContactAttachmentPolicy {
2
+ maxFiles: number;
3
+ maxFileSizeBytes: number;
4
+ maxTotalSizeBytes: number;
5
+ allowedTypes: readonly ContactAttachmentMimeType[];
6
+ }
7
+ export type ContactAttachmentMimeType = 'image/jpeg' | 'image/jpg' | 'image/png' | 'image/webp' | 'image/gif' | 'image/heic' | 'image/heif';
8
+ export declare const DEFAULT_CONTACT_ATTACHMENT_POLICY: {
9
+ readonly maxFiles: 5;
10
+ readonly maxFileSizeBytes: number;
11
+ readonly maxTotalSizeBytes: number;
12
+ readonly allowedTypes: readonly ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif", "image/heic", "image/heif"];
13
+ };
14
+ export declare function contactAttachmentAccept(policy?: {
15
+ readonly maxFiles: 5;
16
+ readonly maxFileSizeBytes: number;
17
+ readonly maxTotalSizeBytes: number;
18
+ readonly allowedTypes: readonly ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif", "image/heic", "image/heif"];
19
+ }): string;
20
+ export declare function contactAttachmentTypeLabel(policy?: {
21
+ readonly maxFiles: 5;
22
+ readonly maxFileSizeBytes: number;
23
+ readonly maxTotalSizeBytes: number;
24
+ readonly allowedTypes: readonly ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif", "image/heic", "image/heif"];
25
+ }): string;
26
+ export declare function isAllowedContactAttachmentType(value: string, policy?: {
27
+ readonly maxFiles: 5;
28
+ readonly maxFileSizeBytes: number;
29
+ readonly maxTotalSizeBytes: number;
30
+ readonly allowedTypes: readonly ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif", "image/heic", "image/heif"];
31
+ }): value is ContactAttachmentMimeType;
32
+ export declare function resolveContactAttachmentType(filename: string, fileType?: string, policy?: {
33
+ readonly maxFiles: 5;
34
+ readonly maxFileSizeBytes: number;
35
+ readonly maxTotalSizeBytes: number;
36
+ readonly allowedTypes: readonly ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif", "image/heic", "image/heif"];
37
+ }): ContactAttachmentMimeType | null;
38
+ export declare function createContactAttachmentFilename(options: {
39
+ index: number;
40
+ contentType: ContactAttachmentMimeType;
41
+ prefix?: string;
42
+ }): string;
43
+ export declare function validateContactAttachment(file: {
44
+ filename: string;
45
+ size: number;
46
+ type?: string;
47
+ }, policy?: {
48
+ readonly maxFiles: 5;
49
+ readonly maxFileSizeBytes: number;
50
+ readonly maxTotalSizeBytes: number;
51
+ readonly allowedTypes: readonly ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif", "image/heic", "image/heif"];
52
+ }): {
53
+ ok: true;
54
+ contentType: ContactAttachmentMimeType;
55
+ } | {
56
+ ok: false;
57
+ message: string;
58
+ };
59
+ //# sourceMappingURL=contact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact.d.ts","sourceRoot":"","sources":["../src/contact.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,MAAM,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,SAAS,yBAAyB,EAAE,CAAA;CACnD;AAED,MAAM,MAAM,yBAAyB,GACjC,YAAY,GACZ,WAAW,GACX,WAAW,GACX,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,YAAY,CAAA;AAEhB,eAAO,MAAM,iCAAiC;;;;;CAaF,CAAA;AAY5C,wBAAgB,uBAAuB,CAAC,MAAM;;;;;CAAoC,UAEjF;AAED,wBAAgB,0BAA0B,CAAC,MAAM;;;;;CAAoC,UAYpF;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,MAAM,EACb,MAAM;;;;;CAAoC,GACzC,KAAK,IAAI,yBAAyB,CAEpC;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM;;;;;CAAoC,GACzC,yBAAyB,GAAG,IAAI,CAYlC;AAED,wBAAgB,+BAA+B,CAAC,OAAO,EAAE;IACvD,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,yBAAyB,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,UAGA;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EACvD,MAAM;;;;;CAAoC,GAExC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,yBAAyB,CAAA;CAAE,GACpD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAoBjC"}
@@ -0,0 +1,76 @@
1
+ export const DEFAULT_CONTACT_ATTACHMENT_POLICY = {
2
+ maxFiles: 5,
3
+ maxFileSizeBytes: 5 * 1024 * 1024,
4
+ maxTotalSizeBytes: 15 * 1024 * 1024,
5
+ allowedTypes: [
6
+ 'image/jpeg',
7
+ 'image/jpg',
8
+ 'image/png',
9
+ 'image/webp',
10
+ 'image/gif',
11
+ 'image/heic',
12
+ 'image/heif',
13
+ ],
14
+ };
15
+ const EXTENSION_TO_MIME = {
16
+ jpg: 'image/jpeg',
17
+ jpeg: 'image/jpeg',
18
+ png: 'image/png',
19
+ gif: 'image/gif',
20
+ webp: 'image/webp',
21
+ heic: 'image/heic',
22
+ heif: 'image/heif',
23
+ };
24
+ export function contactAttachmentAccept(policy = DEFAULT_CONTACT_ATTACHMENT_POLICY) {
25
+ return [...new Set(policy.allowedTypes)].join(',');
26
+ }
27
+ export function contactAttachmentTypeLabel(policy = DEFAULT_CONTACT_ATTACHMENT_POLICY) {
28
+ const labels = policy.allowedTypes
29
+ .map((type) => {
30
+ const subtype = type.split('/')[1] ?? type;
31
+ if (subtype === 'jpeg' || subtype === 'jpg')
32
+ return 'JPG';
33
+ if (subtype === 'webp')
34
+ return 'WebP';
35
+ return subtype.toUpperCase();
36
+ })
37
+ .filter((label, index, labels) => labels.indexOf(label) === index);
38
+ if (labels.length <= 1)
39
+ return labels[0] ?? '';
40
+ return `${labels.slice(0, -1).join(', ')}, or ${labels[labels.length - 1]}`;
41
+ }
42
+ export function isAllowedContactAttachmentType(value, policy = DEFAULT_CONTACT_ATTACHMENT_POLICY) {
43
+ return policy.allowedTypes.includes(value);
44
+ }
45
+ export function resolveContactAttachmentType(filename, fileType, policy = DEFAULT_CONTACT_ATTACHMENT_POLICY) {
46
+ const normalizedType = fileType?.trim().toLowerCase();
47
+ if (normalizedType && isAllowedContactAttachmentType(normalizedType, policy)) {
48
+ return normalizedType;
49
+ }
50
+ const extension = filename.toLowerCase().split('.').pop();
51
+ if (!extension)
52
+ return null;
53
+ const mappedType = EXTENSION_TO_MIME[extension];
54
+ return mappedType && isAllowedContactAttachmentType(mappedType, policy) ? mappedType : null;
55
+ }
56
+ export function createContactAttachmentFilename(options) {
57
+ const extension = options.contentType.split('/')[1] || 'jpg';
58
+ return `${options.prefix ?? 'tree-photo'}-${options.index + 1}.${extension}`;
59
+ }
60
+ export function validateContactAttachment(file, policy = DEFAULT_CONTACT_ATTACHMENT_POLICY) {
61
+ const contentType = resolveContactAttachmentType(file.filename, file.type, policy);
62
+ if (!contentType) {
63
+ return {
64
+ ok: false,
65
+ message: `"${file.filename}" is not a supported image type. Please upload ${contactAttachmentTypeLabel(policy)} files.`,
66
+ };
67
+ }
68
+ if (file.size > policy.maxFileSizeBytes) {
69
+ return {
70
+ ok: false,
71
+ message: `Image "${file.filename}" is too large. Maximum size is 5MB per image.`,
72
+ };
73
+ }
74
+ return { ok: true, contentType };
75
+ }
76
+ //# sourceMappingURL=contact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact.js","sourceRoot":"","sources":["../src/contact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ export type BrandlabMetadataTitleMode = 'templated' | 'absolute';
2
+ export interface BrandlabSocialImage {
3
+ url: string;
4
+ twitterUrl?: string;
5
+ width?: number;
6
+ height?: number;
7
+ alt?: string;
8
+ }
9
+ export interface BuildSeoMetadataInput {
10
+ brandName: string;
11
+ siteUrl: string;
12
+ locale: string;
13
+ titleTemplate: string;
14
+ defaultSocialImage: BrandlabSocialImage;
15
+ title: string;
16
+ description: string;
17
+ pathname: string;
18
+ titleMode?: BrandlabMetadataTitleMode;
19
+ noindex?: boolean;
20
+ keywords?: string[];
21
+ article?: {
22
+ publishedTime?: string;
23
+ modifiedTime?: string;
24
+ authors?: string[];
25
+ };
26
+ socialImage?: BrandlabSocialImage;
27
+ }
28
+ export interface BrandlabSeoMetadata {
29
+ title: string | {
30
+ absolute: string;
31
+ };
32
+ resolvedTitle: string;
33
+ description: string;
34
+ canonicalPath: string;
35
+ canonicalUrl: string;
36
+ alternates: {
37
+ canonical: string;
38
+ };
39
+ keywords?: string[];
40
+ robots?: {
41
+ index: false;
42
+ follow: false;
43
+ googleBot: {
44
+ index: false;
45
+ follow: false;
46
+ };
47
+ };
48
+ openGraph: {
49
+ title: string;
50
+ description: string;
51
+ url: string;
52
+ siteName: string;
53
+ locale: string;
54
+ type: 'website' | 'article';
55
+ images: BrandlabSocialImage[];
56
+ publishedTime?: string;
57
+ modifiedTime?: string;
58
+ authors?: string[];
59
+ };
60
+ twitter: {
61
+ card: 'summary_large_image';
62
+ title: string;
63
+ description: string;
64
+ images: string[];
65
+ };
66
+ }
67
+ export declare function normalizeMetadataTitle(title: string, options: {
68
+ brandName: string;
69
+ titleMode?: BrandlabMetadataTitleMode;
70
+ }): string;
71
+ export declare function applyTitleTemplate(title: string, template: string): string;
72
+ export declare function normalizeCanonicalPath(pathname: string): string;
73
+ export declare function getAbsoluteUrl(siteUrl: string, pathname: string): string;
74
+ export declare function buildSeoMetadata(input: BuildSeoMetadataInput): BrandlabSeoMetadata;
75
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,yBAAyB,GAAG,WAAW,GAAG,UAAU,CAAA;AAEhE,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,kBAAkB,EAAE,mBAAmB,CAAA;IACvC,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,yBAAyB,CAAA;IACrC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,OAAO,CAAC,EAAE;QACR,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KACnB,CAAA;IACD,WAAW,CAAC,EAAE,mBAAmB,CAAA;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IACpC,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IACjC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,KAAK,CAAA;QACZ,MAAM,EAAE,KAAK,CAAA;QACb,SAAS,EAAE;YAAE,KAAK,EAAE,KAAK,CAAC;YAAC,MAAM,EAAE,KAAK,CAAA;SAAE,CAAA;KAC3C,CAAA;IACD,SAAS,EAAE;QACT,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,SAAS,GAAG,SAAS,CAAA;QAC3B,MAAM,EAAE,mBAAmB,EAAE,CAAA;QAC7B,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KACnB,CAAA;IACD,OAAO,EAAE;QACP,IAAI,EAAE,qBAAqB,CAAA;QAC3B,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,MAAM,EAAE,MAAM,EAAE,CAAA;KACjB,CAAA;CACF;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,yBAAyB,CAAA;CAAE,UAoBtE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAEjE;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,UAetD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAI/D;AAMD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,mBAAmB,CA4DlF"}
@@ -0,0 +1,96 @@
1
+ export function normalizeMetadataTitle(title, options) {
2
+ const normalizedTitle = title.trim();
3
+ if (!normalizedTitle) {
4
+ throw new Error('Metadata title cannot be empty.');
5
+ }
6
+ const brandSuffix = `| ${options.brandName}`.toLowerCase();
7
+ if (options.titleMode !== 'absolute' &&
8
+ normalizedTitle.toLowerCase().includes(brandSuffix)) {
9
+ throw new Error(`Metadata title "${normalizedTitle}" already includes the brand suffix. Pass a page-specific title only.`);
10
+ }
11
+ return normalizedTitle;
12
+ }
13
+ export function applyTitleTemplate(title, template) {
14
+ return template.replace('%s', title);
15
+ }
16
+ export function normalizeCanonicalPath(pathname) {
17
+ if (!pathname) {
18
+ throw new Error('pathname is required.');
19
+ }
20
+ const path = pathname.startsWith('http')
21
+ ? new URL(pathname).pathname
22
+ : pathname.split('?')[0]?.split('#')[0];
23
+ if (!path?.startsWith('/')) {
24
+ throw new Error(`Canonical pathname must be root-relative: "${pathname}".`);
25
+ }
26
+ const normalized = path.replace(/\/{2,}/g, '/');
27
+ return normalized === '/' ? '/' : normalized.replace(/\/+$/, '');
28
+ }
29
+ export function getAbsoluteUrl(siteUrl, pathname) {
30
+ const base = siteUrl.replace(/\/+$/, '');
31
+ const path = normalizeCanonicalPath(pathname);
32
+ return `${base}${path}`;
33
+ }
34
+ function normalizeSocialImageUrl(siteUrl, imageUrl) {
35
+ return imageUrl.startsWith('http') ? imageUrl : getAbsoluteUrl(siteUrl, imageUrl);
36
+ }
37
+ export function buildSeoMetadata(input) {
38
+ const titleMode = input.titleMode ?? 'templated';
39
+ const pageTitle = normalizeMetadataTitle(input.title, {
40
+ brandName: input.brandName,
41
+ titleMode,
42
+ });
43
+ const resolvedTitle = titleMode === 'absolute' ? pageTitle : applyTitleTemplate(pageTitle, input.titleTemplate);
44
+ const canonicalPath = normalizeCanonicalPath(input.pathname);
45
+ const canonicalUrl = getAbsoluteUrl(input.siteUrl, canonicalPath);
46
+ const socialImage = input.socialImage
47
+ ? {
48
+ ...input.socialImage,
49
+ url: normalizeSocialImageUrl(input.siteUrl, input.socialImage.url),
50
+ }
51
+ : input.defaultSocialImage;
52
+ const twitterImage = input.socialImage
53
+ ? socialImage.url
54
+ : input.defaultSocialImage.twitterUrl ?? input.defaultSocialImage.url;
55
+ return {
56
+ title: titleMode === 'absolute' ? { absolute: pageTitle } : pageTitle,
57
+ resolvedTitle,
58
+ description: input.description,
59
+ canonicalPath,
60
+ canonicalUrl,
61
+ alternates: {
62
+ canonical: canonicalPath,
63
+ },
64
+ ...(input.keywords && input.keywords.length > 0 ? { keywords: input.keywords } : {}),
65
+ ...(input.noindex
66
+ ? {
67
+ robots: {
68
+ index: false,
69
+ follow: false,
70
+ googleBot: { index: false, follow: false },
71
+ },
72
+ }
73
+ : {}),
74
+ openGraph: {
75
+ title: resolvedTitle,
76
+ description: input.description,
77
+ url: canonicalUrl,
78
+ siteName: input.brandName,
79
+ locale: input.locale,
80
+ type: input.article ? 'article' : 'website',
81
+ images: [socialImage],
82
+ ...(input.article?.publishedTime ? { publishedTime: input.article.publishedTime } : {}),
83
+ ...(input.article?.modifiedTime ? { modifiedTime: input.article.modifiedTime } : {}),
84
+ ...(input.article?.authors && input.article.authors.length > 0
85
+ ? { authors: input.article.authors }
86
+ : {}),
87
+ },
88
+ twitter: {
89
+ card: 'summary_large_image',
90
+ title: resolvedTitle,
91
+ description: input.description,
92
+ images: [twitterImage],
93
+ },
94
+ };
95
+ }
96
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ export type Schema<T> = {
2
+ '@context': 'https://schema.org';
3
+ } & T;
4
+ export interface BreadcrumbItem {
5
+ name: string;
6
+ href?: string;
7
+ }
8
+ export declare function sanitizeJsonLd(data: unknown): string;
9
+ export declare function createSchema<T extends Record<string, unknown>>(data: T): Schema<T>;
10
+ export declare function createSchemaGraph(...nodes: unknown[]): Schema<{
11
+ '@graph': unknown[];
12
+ }>;
13
+ export interface SchemaIdRoutes {
14
+ service: (slug: string) => string;
15
+ blogPost: (slug: string) => string;
16
+ }
17
+ export interface SchemaIdOptions {
18
+ siteUrl: string;
19
+ anchors?: {
20
+ business?: string;
21
+ website?: string;
22
+ service?: string;
23
+ article?: string;
24
+ };
25
+ routes: SchemaIdRoutes;
26
+ }
27
+ export declare function createSchemaIdHelpers(options: SchemaIdOptions): {
28
+ businessId: () => string;
29
+ websiteId: () => string;
30
+ serviceIdForSlug: (slug: string) => string;
31
+ serviceIdForPath: (pathOrUrl: string) => string;
32
+ blogPostId: (slug: string) => string;
33
+ blogPostPageId: (slug: string) => string;
34
+ };
35
+ export declare function buildBreadcrumbListSchema(breadcrumbs: BreadcrumbItem[], options: {
36
+ absoluteUrl: (path: string) => string;
37
+ }): {
38
+ '@type': string;
39
+ itemListElement: {
40
+ '@type': string;
41
+ position: number;
42
+ name: string;
43
+ item: {
44
+ '@type': string;
45
+ '@id': string;
46
+ url: string;
47
+ name: string;
48
+ } | undefined;
49
+ }[];
50
+ };
51
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI;IACtB,UAAU,EAAE,oBAAoB,CAAA;CACjC,GAAG,CAAC,CAAA;AAEL,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAOpD;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAKlF;AAED,wBAAgB,iBAAiB,CAAC,GAAG,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CAyBtF;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB,CAAA;IACD,MAAM,EAAE,cAAc,CAAA;CACvB;AAaD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe;;;6BAajC,MAAM;kCAED,MAAM;uBAEjB,MAAM;2BAEF,MAAM;EAEhC;AAED,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,cAAc,EAAE,EAC7B,OAAO,EAAE;IAAE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE;;;;;;;;;;;;;EAkBnD"}
package/dist/schema.js ADDED
@@ -0,0 +1,80 @@
1
+ export function sanitizeJsonLd(data) {
2
+ return JSON.stringify(data)
3
+ .replace(/</g, '\\u003c')
4
+ .replace(/>/g, '\\u003e')
5
+ .replace(/&/g, '\\u0026')
6
+ .replace(/\u2028/g, '\\u2028')
7
+ .replace(/\u2029/g, '\\u2029');
8
+ }
9
+ export function createSchema(data) {
10
+ return {
11
+ '@context': 'https://schema.org',
12
+ ...data,
13
+ };
14
+ }
15
+ export function createSchemaGraph(...nodes) {
16
+ const filtered = nodes.filter(Boolean);
17
+ if (process.env.NODE_ENV !== 'production') {
18
+ const ids = filtered
19
+ .map((node) => node && typeof node === 'object'
20
+ ? node['@id']
21
+ : undefined)
22
+ .filter((id) => typeof id === 'string');
23
+ const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);
24
+ if (duplicates.length > 0) {
25
+ console.warn(`[schema] Duplicate @id values in one graph: ${[...new Set(duplicates)].join(', ')}. ` +
26
+ 'Each entity must have a unique @id within a single page graph.');
27
+ }
28
+ }
29
+ return {
30
+ '@context': 'https://schema.org',
31
+ '@graph': filtered,
32
+ };
33
+ }
34
+ function normalizeSiteUrl(siteUrl) {
35
+ return siteUrl.replace(/\/+$/, '');
36
+ }
37
+ function absoluteUrl(siteUrl, pathOrUrl) {
38
+ if (pathOrUrl.startsWith('http'))
39
+ return pathOrUrl;
40
+ const base = normalizeSiteUrl(siteUrl);
41
+ const path = pathOrUrl.startsWith('/') ? pathOrUrl : `/${pathOrUrl}`;
42
+ return `${base}${path}`;
43
+ }
44
+ export function createSchemaIdHelpers(options) {
45
+ const siteUrl = normalizeSiteUrl(options.siteUrl);
46
+ const anchors = {
47
+ business: '/#business',
48
+ website: '/#website',
49
+ service: '#service',
50
+ article: '#article',
51
+ ...options.anchors,
52
+ };
53
+ return {
54
+ businessId: () => `${siteUrl}${anchors.business}`,
55
+ websiteId: () => `${siteUrl}${anchors.website}`,
56
+ serviceIdForSlug: (slug) => `${absoluteUrl(siteUrl, options.routes.service(slug))}${anchors.service}`,
57
+ serviceIdForPath: (pathOrUrl) => `${absoluteUrl(siteUrl, pathOrUrl)}${anchors.service}`,
58
+ blogPostId: (slug) => `${absoluteUrl(siteUrl, options.routes.blogPost(slug))}${anchors.article}`,
59
+ blogPostPageId: (slug) => absoluteUrl(siteUrl, options.routes.blogPost(slug)),
60
+ };
61
+ }
62
+ export function buildBreadcrumbListSchema(breadcrumbs, options) {
63
+ return {
64
+ '@type': 'BreadcrumbList',
65
+ itemListElement: breadcrumbs.map((crumb, index) => ({
66
+ '@type': 'ListItem',
67
+ position: index + 1,
68
+ name: crumb.name,
69
+ item: crumb.href
70
+ ? {
71
+ '@type': 'WebPage',
72
+ '@id': options.absoluteUrl(crumb.href),
73
+ url: options.absoluteUrl(crumb.href),
74
+ name: crumb.name,
75
+ }
76
+ : undefined,
77
+ })),
78
+ };
79
+ }
80
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ export type SitemapChangeFrequency = 'yearly' | 'monthly' | 'weekly' | 'daily' | 'never';
2
+ export interface SitemapEntry {
3
+ url: string;
4
+ lastModified?: string | Date;
5
+ changeFrequency?: SitemapChangeFrequency;
6
+ priority?: number;
7
+ }
8
+ export declare const SITEMAP_PRIORITY: {
9
+ readonly home: 1;
10
+ readonly service: 0.9;
11
+ readonly servicesIndex: 0.8;
12
+ readonly contactPage: 0.8;
13
+ readonly regionHub: 0.7;
14
+ readonly serviceRegion: 0.7;
15
+ readonly serviceLocation: 0.5;
16
+ readonly blogPost: 0.6;
17
+ readonly about: 0.6;
18
+ readonly faqs: 0.6;
19
+ readonly blogIndex: 0.7;
20
+ readonly locationsIndex: 0.7;
21
+ readonly suburb: 0.5;
22
+ readonly gallery: 0.5;
23
+ readonly legal: 0.3;
24
+ readonly fallback: 0.5;
25
+ };
26
+ export declare const SITEMAP_FREQUENCY: {
27
+ readonly home: "monthly";
28
+ readonly service: "monthly";
29
+ readonly serviceRegion: "monthly";
30
+ readonly serviceLocation: "monthly";
31
+ readonly blog: "weekly";
32
+ readonly location: "monthly";
33
+ readonly legal: "yearly";
34
+ readonly rarelyUpdated: "yearly";
35
+ };
36
+ export declare function escapeXml(value: string): string;
37
+ export declare function getSitemapXmlHeaders(): {
38
+ 'content-type': string;
39
+ 'cache-control': string;
40
+ };
41
+ export declare function serializeSitemap(entries: readonly SitemapEntry[]): string;
42
+ export declare function serializeSitemapIndex(paths: readonly string[], options: {
43
+ absoluteUrl: (path: string) => string;
44
+ }): string;
45
+ export declare function shouldIndexSite(options: {
46
+ nodeEnv?: string;
47
+ vercelEnv?: string;
48
+ allowIndexing?: string;
49
+ }): boolean;
50
+ //# sourceMappingURL=sitemaps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sitemaps.d.ts","sourceRoot":"","sources":["../src/sitemaps.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAA;AAExF,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,eAAe,CAAC,EAAE,sBAAsB,CAAA;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;CAiBnB,CAAA;AAEV,eAAO,MAAM,iBAAiB;;;;;;;;;CAS6B,CAAA;AAE3D,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO/C;AAQD,wBAAgB,oBAAoB;;;EAKnC;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CA0BzE;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,EAAE;IAAE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,GACjD,MAAM,CAiBR;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,WAMA"}
@@ -0,0 +1,95 @@
1
+ export const SITEMAP_PRIORITY = {
2
+ home: 1.0,
3
+ service: 0.9,
4
+ servicesIndex: 0.8,
5
+ contactPage: 0.8,
6
+ regionHub: 0.7,
7
+ serviceRegion: 0.7,
8
+ serviceLocation: 0.5,
9
+ blogPost: 0.6,
10
+ about: 0.6,
11
+ faqs: 0.6,
12
+ blogIndex: 0.7,
13
+ locationsIndex: 0.7,
14
+ suburb: 0.5,
15
+ gallery: 0.5,
16
+ legal: 0.3,
17
+ fallback: 0.5,
18
+ };
19
+ export const SITEMAP_FREQUENCY = {
20
+ home: 'monthly',
21
+ service: 'monthly',
22
+ serviceRegion: 'monthly',
23
+ serviceLocation: 'monthly',
24
+ blog: 'weekly',
25
+ location: 'monthly',
26
+ legal: 'yearly',
27
+ rarelyUpdated: 'yearly',
28
+ };
29
+ export function escapeXml(value) {
30
+ return value
31
+ .replace(/&/g, '&amp;')
32
+ .replace(/</g, '&lt;')
33
+ .replace(/>/g, '&gt;')
34
+ .replace(/"/g, '&quot;')
35
+ .replace(/'/g, '&apos;');
36
+ }
37
+ function formatLastModified(value) {
38
+ if (!value)
39
+ return null;
40
+ if (value instanceof Date)
41
+ return value.toISOString();
42
+ return new Date(value).toISOString();
43
+ }
44
+ export function getSitemapXmlHeaders() {
45
+ return {
46
+ 'content-type': 'application/xml; charset=utf-8',
47
+ 'cache-control': 'public, max-age=3600, s-maxage=3600',
48
+ };
49
+ }
50
+ export function serializeSitemap(entries) {
51
+ const urls = entries
52
+ .map((entry) => {
53
+ const lastModified = formatLastModified(entry.lastModified);
54
+ return [
55
+ ' <url>',
56
+ ` <loc>${escapeXml(entry.url)}</loc>`,
57
+ lastModified ? ` <lastmod>${lastModified}</lastmod>` : null,
58
+ entry.changeFrequency ? ` <changefreq>${entry.changeFrequency}</changefreq>` : null,
59
+ typeof entry.priority === 'number'
60
+ ? ` <priority>${entry.priority.toFixed(1)}</priority>`
61
+ : null,
62
+ ' </url>',
63
+ ]
64
+ .filter(Boolean)
65
+ .join('\n');
66
+ })
67
+ .join('\n');
68
+ return [
69
+ '<?xml version="1.0" encoding="UTF-8"?>',
70
+ '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
71
+ urls,
72
+ '</urlset>',
73
+ ].join('\n');
74
+ }
75
+ export function serializeSitemapIndex(paths, options) {
76
+ const entries = paths
77
+ .map((path) => [
78
+ ' <sitemap>',
79
+ ` <loc>${escapeXml(options.absoluteUrl(path))}</loc>`,
80
+ ' </sitemap>',
81
+ ].join('\n'))
82
+ .join('\n');
83
+ return [
84
+ '<?xml version="1.0" encoding="UTF-8"?>',
85
+ '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
86
+ entries,
87
+ '</sitemapindex>',
88
+ ].join('\n');
89
+ }
90
+ export function shouldIndexSite(options) {
91
+ const isProduction = options.vercelEnv === 'production' ||
92
+ (!options.vercelEnv && options.nodeEnv === 'production');
93
+ return isProduction || options.allowIndexing === '1';
94
+ }
95
+ //# sourceMappingURL=sitemaps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sitemaps.js","sourceRoot":"","sources":["../src/sitemaps.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@brandlab-digital/site-core",
3
+ "version": "0.1.0-alpha.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "files": ["dist"],
8
+ "scripts": {
9
+ "build": "tsc -p tsconfig.json",
10
+ "test": "vitest run",
11
+ "typecheck": "tsc --noEmit -p tsconfig.json"
12
+ },
13
+ "exports": {
14
+ "./metadata": {
15
+ "types": "./dist/metadata.d.ts",
16
+ "import": "./dist/metadata.js"
17
+ },
18
+ "./schema": {
19
+ "types": "./dist/schema.d.ts",
20
+ "import": "./dist/schema.js"
21
+ },
22
+ "./breadcrumbs": {
23
+ "types": "./dist/breadcrumbs.d.ts",
24
+ "import": "./dist/breadcrumbs.js"
25
+ },
26
+ "./sitemaps": {
27
+ "types": "./dist/sitemaps.d.ts",
28
+ "import": "./dist/sitemaps.js"
29
+ },
30
+ "./contact": {
31
+ "types": "./dist/contact.d.ts",
32
+ "import": "./dist/contact.js"
33
+ },
34
+ "./analytics": {
35
+ "types": "./dist/analytics.d.ts",
36
+ "import": "./dist/analytics.js"
37
+ }
38
+ }
39
+ }