@krantho/seo-shared 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/document-metadata.d.ts +7 -0
- package/dist/document-metadata.d.ts.map +1 -0
- package/dist/document-metadata.js +62 -0
- package/dist/document-metadata.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/json-ld-serialize.d.ts +17 -0
- package/dist/json-ld-serialize.d.ts.map +1 -0
- package/dist/json-ld-serialize.js +19 -0
- package/dist/json-ld-serialize.js.map +1 -0
- package/dist/resolve-effective-types.d.ts +14 -0
- package/dist/resolve-effective-types.d.ts.map +1 -0
- package/dist/resolve-effective-types.js +13 -0
- package/dist/resolve-effective-types.js.map +1 -0
- package/dist/seo-config-types.d.ts +40 -0
- package/dist/seo-config-types.d.ts.map +1 -0
- package/dist/seo-config-types.js +20 -0
- package/dist/seo-config-types.js.map +1 -0
- package/dist/seo-field-map.d.ts +71 -0
- package/dist/seo-field-map.d.ts.map +1 -0
- package/dist/seo-field-map.js +80 -0
- package/dist/seo-field-map.js.map +1 -0
- package/package.json +29 -3
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Descoped
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SeoConfigData } from './seo-config-types.js';
|
|
2
|
+
/** Optional document-owned graph data. The CMS stores this ordinary portable contract. */
|
|
3
|
+
export declare const DOCUMENT_SEO_METADATA_SCHEMA: Record<string, unknown>;
|
|
4
|
+
/** Scope policy is dynamic context; the document's own overrides come from its revision. */
|
|
5
|
+
export declare function documentSeoConfig(metadata: Readonly<Record<string, Record<string, unknown>>>): SeoConfigData | null;
|
|
6
|
+
export declare function documentSeoProperties(metadata: Readonly<Record<string, Record<string, unknown>>>): Record<string, unknown>;
|
|
7
|
+
//# sourceMappingURL=document-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-metadata.d.ts","sourceRoot":"","sources":["../src/document-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,0FAA0F;AAC1F,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAqChE,CAAA;AAED,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAC1D,aAAa,GAAG,IAAI,CAItB;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAC1D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAczB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** Optional document-owned graph data. The CMS stores this ordinary portable contract. */
|
|
2
|
+
export const DOCUMENT_SEO_METADATA_SCHEMA = {
|
|
3
|
+
type: 'object',
|
|
4
|
+
additionalProperties: false,
|
|
5
|
+
properties: {
|
|
6
|
+
entities: {
|
|
7
|
+
type: 'array',
|
|
8
|
+
items: {
|
|
9
|
+
type: 'object',
|
|
10
|
+
additionalProperties: false,
|
|
11
|
+
properties: {
|
|
12
|
+
'@type': { type: 'string' },
|
|
13
|
+
'@id': { type: 'string' },
|
|
14
|
+
role: { type: 'string' },
|
|
15
|
+
properties: { type: 'object', additionalProperties: {} },
|
|
16
|
+
},
|
|
17
|
+
required: ['@type', 'properties'],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
fieldMappings: { type: 'object', additionalProperties: { type: 'string' } },
|
|
21
|
+
structure: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
additionalProperties: false,
|
|
24
|
+
properties: {
|
|
25
|
+
kind: { type: 'string' },
|
|
26
|
+
trail: {
|
|
27
|
+
type: 'array',
|
|
28
|
+
items: {
|
|
29
|
+
type: 'object',
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
properties: { name: { type: 'string' }, url: { type: 'string' } },
|
|
32
|
+
required: ['name'],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
required: ['entities'],
|
|
39
|
+
};
|
|
40
|
+
/** Scope policy is dynamic context; the document's own overrides come from its revision. */
|
|
41
|
+
export function documentSeoConfig(metadata) {
|
|
42
|
+
const group = metadata['seo'];
|
|
43
|
+
if (!group || !Array.isArray(group['entities']))
|
|
44
|
+
return null;
|
|
45
|
+
return group;
|
|
46
|
+
}
|
|
47
|
+
export function documentSeoProperties(metadata) {
|
|
48
|
+
const graph = documentSeoConfig(metadata)?.entities[0]?.properties ?? {};
|
|
49
|
+
const sharing = metadata['sharing'] ?? {};
|
|
50
|
+
const editorial = metadata['editorial'] ?? {};
|
|
51
|
+
const publication = metadata['publication'] ?? {};
|
|
52
|
+
return {
|
|
53
|
+
...graph,
|
|
54
|
+
...(sharing['title'] !== undefined ? { headline: sharing['title'] } : {}),
|
|
55
|
+
...(sharing['description'] !== undefined ? { description: sharing['description'] } : {}),
|
|
56
|
+
...(sharing['image'] !== undefined ? { image: sharing['image'] } : {}),
|
|
57
|
+
...(sharing['canonicalUrl'] !== undefined ? { url: sharing['canonicalUrl'] } : {}),
|
|
58
|
+
...(editorial['byline'] !== undefined ? { author: editorial['byline'] } : {}),
|
|
59
|
+
...(publication['date'] !== undefined ? { datePublished: publication['date'] } : {}),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=document-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-metadata.js","sourceRoot":"","sources":["../src/document-metadata.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { DOCUMENT_SEO_METADATA_SCHEMA, documentSeoConfig, documentSeoProperties, } from './document-metadata.js';
|
|
2
|
+
export { serializeJsonLd } from './json-ld-serialize.js';
|
|
3
|
+
export { resolveEffectiveTypes, type ScopeWithEntities, } from './resolve-effective-types.js';
|
|
4
|
+
export { inferSeoConfigScope, type SeoConfigData, type SeoConfigEntity, type SeoStructureDefaults, } from './seo-config-types.js';
|
|
5
|
+
export { buildSeoFieldMap, resolveSeoField, SEO_FIELD_CANDIDATES, type SeoFieldConcept, type SeoFieldMap, } from './seo-field-map.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EACL,qBAAqB,EACrB,KAAK,iBAAiB,GACvB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,oBAAoB,GAC1B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { DOCUMENT_SEO_METADATA_SCHEMA, documentSeoConfig, documentSeoProperties, } from './document-metadata.js';
|
|
2
|
+
export { serializeJsonLd } from './json-ld-serialize.js';
|
|
3
|
+
export { resolveEffectiveTypes, } from './resolve-effective-types.js';
|
|
4
|
+
export { inferSeoConfigScope, } from './seo-config-types.js';
|
|
5
|
+
export { buildSeoFieldMap, resolveSeoField, SEO_FIELD_CANDIDATES, } from './seo-field-map.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EACL,qBAAqB,GAEtB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EACL,mBAAmB,GAIpB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GAGrB,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize a JSON-LD value for embedding inside a `<script type="application/ld+json">` tag.
|
|
3
|
+
*
|
|
4
|
+
* Escapes `<` to `\u003c` to prevent premature tag termination — the standard
|
|
5
|
+
* XSS mitigation for inline JSON-LD. Every framework component that emits a
|
|
6
|
+
* JSON-LD script tag needs this exact escape; previously four copies of
|
|
7
|
+
* `JSON.stringify(data).replace(/</g, '\\u003c')` were maintained independently
|
|
8
|
+
* in `@krantho/seo` (two files), `@krantho/ui-react` (one file), and
|
|
9
|
+
* `@krantho/ui-svelte` (one file). Consolidating here eliminates the drift risk.
|
|
10
|
+
*
|
|
11
|
+
* Note: the `>` and `&` characters are intentionally NOT escaped — JSON never
|
|
12
|
+
* produces a bare `>` inside string values (it escapes them as part of normal
|
|
13
|
+
* JSON), and `&` is safe inside `<script>` content because script bodies are
|
|
14
|
+
* not parsed as HTML entities.
|
|
15
|
+
*/
|
|
16
|
+
export declare function serializeJsonLd(data: unknown): string;
|
|
17
|
+
//# sourceMappingURL=json-ld-serialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-ld-serialize.d.ts","sourceRoot":"","sources":["../src/json-ld-serialize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAErD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize a JSON-LD value for embedding inside a `<script type="application/ld+json">` tag.
|
|
3
|
+
*
|
|
4
|
+
* Escapes `<` to `\u003c` to prevent premature tag termination — the standard
|
|
5
|
+
* XSS mitigation for inline JSON-LD. Every framework component that emits a
|
|
6
|
+
* JSON-LD script tag needs this exact escape; previously four copies of
|
|
7
|
+
* `JSON.stringify(data).replace(/</g, '\\u003c')` were maintained independently
|
|
8
|
+
* in `@krantho/seo` (two files), `@krantho/ui-react` (one file), and
|
|
9
|
+
* `@krantho/ui-svelte` (one file). Consolidating here eliminates the drift risk.
|
|
10
|
+
*
|
|
11
|
+
* Note: the `>` and `&` characters are intentionally NOT escaped — JSON never
|
|
12
|
+
* produces a bare `>` inside string values (it escapes them as part of normal
|
|
13
|
+
* JSON), and `&` is safe inside `<script>` content because script bodies are
|
|
14
|
+
* not parsed as HTML entities.
|
|
15
|
+
*/
|
|
16
|
+
export function serializeJsonLd(data) {
|
|
17
|
+
return JSON.stringify(data).replace(/</g, '\\u003c');
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=json-ld-serialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-ld-serialize.js","sourceRoot":"","sources":["../src/json-ld-serialize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAAC,IAAa;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;AACtD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the effective Schema.org types for a document by cascading
|
|
3
|
+
* through the scope hierarchy: document → collection → site.
|
|
4
|
+
*
|
|
5
|
+
* The first scope with configured entity types wins. If no scope has
|
|
6
|
+
* types, returns an empty array.
|
|
7
|
+
*/
|
|
8
|
+
export interface ScopeWithEntities {
|
|
9
|
+
readonly entities: readonly {
|
|
10
|
+
readonly '@type': string;
|
|
11
|
+
}[];
|
|
12
|
+
}
|
|
13
|
+
export declare function resolveEffectiveTypes(document: ScopeWithEntities | null, collection: ScopeWithEntities | null, site: ScopeWithEntities | null): readonly string[];
|
|
14
|
+
//# sourceMappingURL=resolve-effective-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-effective-types.d.ts","sourceRoot":"","sources":["../src/resolve-effective-types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC3D;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,EAClC,UAAU,EAAE,iBAAiB,GAAG,IAAI,EACpC,IAAI,EAAE,iBAAiB,GAAG,IAAI,GAC7B,SAAS,MAAM,EAAE,CAQnB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function resolveEffectiveTypes(document, collection, site) {
|
|
2
|
+
const docTypes = document?.entities.map((e) => e['@type']) ?? [];
|
|
3
|
+
if (docTypes.length > 0)
|
|
4
|
+
return docTypes;
|
|
5
|
+
const colTypes = collection?.entities.map((e) => e['@type']) ?? [];
|
|
6
|
+
if (colTypes.length > 0)
|
|
7
|
+
return colTypes;
|
|
8
|
+
const siteTypes = site?.entities.map((e) => e['@type']) ?? [];
|
|
9
|
+
if (siteTypes.length > 0)
|
|
10
|
+
return siteTypes;
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=resolve-effective-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-effective-types.js","sourceRoot":"","sources":["../src/resolve-effective-types.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,qBAAqB,CACnC,QAAkC,EAClC,UAAoC,EACpC,IAA8B;IAE9B,MAAM,QAAQ,GAAG,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAA;IAChE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAA;IACxC,MAAM,QAAQ,GAAG,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAA;IAClE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAA;IACxC,MAAM,SAAS,GAAG,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAA;IAC7D,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IAC1C,OAAO,EAAE,CAAA;AACX,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical SEO configuration types.
|
|
3
|
+
*
|
|
4
|
+
* These are the single source of truth for the entity/config shape used
|
|
5
|
+
* across all packages: persistence adapters, SEO graph composition, the
|
|
6
|
+
* Studio, and the API handlers.
|
|
7
|
+
*/
|
|
8
|
+
/** A single Schema.org entity in the SEO configuration. */
|
|
9
|
+
export interface SeoConfigEntity {
|
|
10
|
+
readonly '@type': string;
|
|
11
|
+
readonly '@id'?: string | undefined;
|
|
12
|
+
readonly role?: string | undefined;
|
|
13
|
+
readonly properties: Readonly<Record<string, unknown>>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The page structure a scope gives its pages when their template states none:
|
|
17
|
+
* the trail above them, root first (the page itself is added), and their kind.
|
|
18
|
+
*/
|
|
19
|
+
export interface SeoStructureDefaults {
|
|
20
|
+
readonly trail?: ReadonlyArray<{
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly url?: string | undefined;
|
|
23
|
+
}> | undefined;
|
|
24
|
+
readonly kind?: string | undefined;
|
|
25
|
+
}
|
|
26
|
+
/** SEO configuration data — the content stored per scope (site/collection/document/route). */
|
|
27
|
+
export interface SeoConfigData {
|
|
28
|
+
readonly entities: readonly SeoConfigEntity[];
|
|
29
|
+
readonly fieldMappings?: Readonly<Record<string, string>> | undefined;
|
|
30
|
+
readonly structure?: SeoStructureDefaults | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Site scope only: a robots.txt body served verbatim in place of the
|
|
33
|
+
* generated one. Kept beside the entities, never among them, so no page's
|
|
34
|
+
* structured data states it.
|
|
35
|
+
*/
|
|
36
|
+
readonly robotsTxt?: string | undefined;
|
|
37
|
+
}
|
|
38
|
+
/** Infer SEO config scope from a config ID. */
|
|
39
|
+
export declare function inferSeoConfigScope(id: string): 'site' | 'collection' | 'document' | 'route';
|
|
40
|
+
//# sourceMappingURL=seo-config-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-config-types.d.ts","sourceRoot":"","sources":["../src/seo-config-types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CACvD;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,CAAC,EACX,aAAa,CAAC;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC,GAC3E,SAAS,CAAA;IACb,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC;AAED,8FAA8F;AAC9F,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IACrE,QAAQ,CAAC,SAAS,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAA;IACrD;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC;AAED,+CAA+C;AAC/C,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAM5F"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical SEO configuration types.
|
|
3
|
+
*
|
|
4
|
+
* These are the single source of truth for the entity/config shape used
|
|
5
|
+
* across all packages: persistence adapters, SEO graph composition, the
|
|
6
|
+
* Studio, and the API handlers.
|
|
7
|
+
*/
|
|
8
|
+
/** Infer SEO config scope from a config ID. */
|
|
9
|
+
export function inferSeoConfigScope(id) {
|
|
10
|
+
if (id === 'site')
|
|
11
|
+
return 'site';
|
|
12
|
+
if (id.startsWith('collection:'))
|
|
13
|
+
return 'collection';
|
|
14
|
+
if (id.startsWith('route:'))
|
|
15
|
+
return 'route';
|
|
16
|
+
if (id.startsWith('doc:'))
|
|
17
|
+
return 'document';
|
|
18
|
+
return 'document';
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=seo-config-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-config-types.js","sourceRoot":"","sources":["../src/seo-config-types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkCH,+CAA+C;AAC/C,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,IAAI,EAAE,KAAK,MAAM;QAAE,OAAO,MAAM,CAAA;IAChC,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,YAAY,CAAA;IACrD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAA;IAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,UAAU,CAAA;IAC5C,OAAO,UAAU,CAAA;AACnB,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SEO field map — resolves SEO concepts to actual CMS field names.
|
|
3
|
+
*
|
|
4
|
+
* Given the CMS field names from a collection schema, determines which
|
|
5
|
+
* CMS field serves each SEO concept (description, title, author, etc.).
|
|
6
|
+
* The CMS schema is the source of truth — SEO adapts to it.
|
|
7
|
+
*
|
|
8
|
+
* This module is the canonical implementation. It lives in @krantho/seo-shared
|
|
9
|
+
* (a zero-dependency package) so it can be consumed by any package that needs
|
|
10
|
+
* field discovery without forcing a dependency on @krantho/seo (which is
|
|
11
|
+
* optional). @krantho/seo re-exports from here for backwards compatibility.
|
|
12
|
+
*/
|
|
13
|
+
/** All SEO concepts that can be mapped to CMS fields */
|
|
14
|
+
export interface SeoFieldMap {
|
|
15
|
+
/** CMS field that serves as the page title */
|
|
16
|
+
title: string | null;
|
|
17
|
+
/** CMS field that serves as the SEO description (meta-description > description) */
|
|
18
|
+
description: string | null;
|
|
19
|
+
/** CMS field for the author */
|
|
20
|
+
author: string | null;
|
|
21
|
+
/** CMS field for the publication date */
|
|
22
|
+
datePublished: string | null;
|
|
23
|
+
/** CMS field for the primary image */
|
|
24
|
+
image: string | null;
|
|
25
|
+
/** CMS field for canonical URL override */
|
|
26
|
+
canonicalUrl: string | null;
|
|
27
|
+
/** CMS field for robots index directive */
|
|
28
|
+
robotsIndex: string | null;
|
|
29
|
+
/** CMS field for robots follow directive */
|
|
30
|
+
robotsFollow: string | null;
|
|
31
|
+
/** CMS field for OG title override */
|
|
32
|
+
ogTitle: string | null;
|
|
33
|
+
/** CMS field for OG description override */
|
|
34
|
+
ogDescription: string | null;
|
|
35
|
+
/** CMS field for OG image override */
|
|
36
|
+
ogImage: string | null;
|
|
37
|
+
/** CMS field for OG type override */
|
|
38
|
+
ogType: string | null;
|
|
39
|
+
}
|
|
40
|
+
/** Type alias for an SEO concept name */
|
|
41
|
+
export type SeoFieldConcept = keyof SeoFieldMap;
|
|
42
|
+
/**
|
|
43
|
+
* Well-known SEO field candidates in priority order (highest first).
|
|
44
|
+
*
|
|
45
|
+
* When extending this list, add the most specific name first. The first
|
|
46
|
+
* candidate found in the CMS schema wins.
|
|
47
|
+
*
|
|
48
|
+
* Note on `image` vs `ogImage` overlap: both list `og-image` first by design.
|
|
49
|
+
* If a CMS schema has only an `og-image` field, both the canonical page image
|
|
50
|
+
* (used for JSON-LD) and the social-share image (used for og:image meta tags)
|
|
51
|
+
* should resolve to it. Authors who want different values can add a separate
|
|
52
|
+
* `image` or `hero-image` field — `image` will then prefer that and `ogImage`
|
|
53
|
+
* will continue to use `og-image`.
|
|
54
|
+
*/
|
|
55
|
+
export declare const SEO_FIELD_CANDIDATES: Record<SeoFieldConcept, readonly string[]>;
|
|
56
|
+
/**
|
|
57
|
+
* Build an SEO field map from the CMS fields actually present in a collection.
|
|
58
|
+
*
|
|
59
|
+
* The CMS schema is the source of truth. This function discovers which
|
|
60
|
+
* fields exist and maps them to SEO concepts. If a field doesn't exist
|
|
61
|
+
* in the schema, the SEO concept maps to null.
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildSeoFieldMap(cmsFieldNames: readonly string[]): SeoFieldMap;
|
|
64
|
+
/**
|
|
65
|
+
* Resolve an SEO concept's value from CMS content fields.
|
|
66
|
+
*
|
|
67
|
+
* Uses the field map to find the right CMS field, then reads the value.
|
|
68
|
+
* Returns empty string if no field is mapped or value is missing.
|
|
69
|
+
*/
|
|
70
|
+
export declare function resolveSeoField(fieldMap: SeoFieldMap, concept: SeoFieldConcept, fields: Record<string, unknown>): string;
|
|
71
|
+
//# sourceMappingURL=seo-field-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-field-map.d.ts","sourceRoot":"","sources":["../src/seo-field-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wDAAwD;AACxD,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,oFAAoF;IACpF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,+BAA+B;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,yCAAyC;IACzC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,sCAAsC;IACtC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,2CAA2C;IAC3C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,2CAA2C;IAC3C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,4CAA4C;IAC5C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,sCAAsC;IACtC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,4CAA4C;IAC5C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,sCAAsC;IACtC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,qCAAqC;IACrC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,yCAAyC;AACzC,MAAM,MAAM,eAAe,GAAG,MAAM,WAAW,CAAA;AAE/C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAa3E,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CAqB9E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAKR"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SEO field map — resolves SEO concepts to actual CMS field names.
|
|
3
|
+
*
|
|
4
|
+
* Given the CMS field names from a collection schema, determines which
|
|
5
|
+
* CMS field serves each SEO concept (description, title, author, etc.).
|
|
6
|
+
* The CMS schema is the source of truth — SEO adapts to it.
|
|
7
|
+
*
|
|
8
|
+
* This module is the canonical implementation. It lives in @krantho/seo-shared
|
|
9
|
+
* (a zero-dependency package) so it can be consumed by any package that needs
|
|
10
|
+
* field discovery without forcing a dependency on @krantho/seo (which is
|
|
11
|
+
* optional). @krantho/seo re-exports from here for backwards compatibility.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Well-known SEO field candidates in priority order (highest first).
|
|
15
|
+
*
|
|
16
|
+
* When extending this list, add the most specific name first. The first
|
|
17
|
+
* candidate found in the CMS schema wins.
|
|
18
|
+
*
|
|
19
|
+
* Note on `image` vs `ogImage` overlap: both list `og-image` first by design.
|
|
20
|
+
* If a CMS schema has only an `og-image` field, both the canonical page image
|
|
21
|
+
* (used for JSON-LD) and the social-share image (used for og:image meta tags)
|
|
22
|
+
* should resolve to it. Authors who want different values can add a separate
|
|
23
|
+
* `image` or `hero-image` field — `image` will then prefer that and `ogImage`
|
|
24
|
+
* will continue to use `og-image`.
|
|
25
|
+
*/
|
|
26
|
+
export const SEO_FIELD_CANDIDATES = {
|
|
27
|
+
title: ['title', 'name'],
|
|
28
|
+
description: ['meta-description', 'description', 'ingress', 'excerpt'],
|
|
29
|
+
author: ['author'],
|
|
30
|
+
datePublished: ['published-date', 'date'],
|
|
31
|
+
image: ['og-image', 'image', 'hero-image'],
|
|
32
|
+
canonicalUrl: ['canonical-url'],
|
|
33
|
+
robotsIndex: ['robots-index'],
|
|
34
|
+
robotsFollow: ['robots-follow'],
|
|
35
|
+
ogTitle: ['og-title'],
|
|
36
|
+
ogDescription: ['og-description'],
|
|
37
|
+
ogImage: ['og-image', 'image'],
|
|
38
|
+
ogType: ['og-type'],
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Build an SEO field map from the CMS fields actually present in a collection.
|
|
42
|
+
*
|
|
43
|
+
* The CMS schema is the source of truth. This function discovers which
|
|
44
|
+
* fields exist and maps them to SEO concepts. If a field doesn't exist
|
|
45
|
+
* in the schema, the SEO concept maps to null.
|
|
46
|
+
*/
|
|
47
|
+
export function buildSeoFieldMap(cmsFieldNames) {
|
|
48
|
+
const fieldSet = new Set(cmsFieldNames);
|
|
49
|
+
function resolve(candidates) {
|
|
50
|
+
return candidates.find((f) => fieldSet.has(f)) ?? null;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
title: resolve(SEO_FIELD_CANDIDATES.title),
|
|
54
|
+
description: resolve(SEO_FIELD_CANDIDATES.description),
|
|
55
|
+
author: resolve(SEO_FIELD_CANDIDATES.author),
|
|
56
|
+
datePublished: resolve(SEO_FIELD_CANDIDATES.datePublished),
|
|
57
|
+
image: resolve(SEO_FIELD_CANDIDATES.image),
|
|
58
|
+
canonicalUrl: resolve(SEO_FIELD_CANDIDATES.canonicalUrl),
|
|
59
|
+
robotsIndex: resolve(SEO_FIELD_CANDIDATES.robotsIndex),
|
|
60
|
+
robotsFollow: resolve(SEO_FIELD_CANDIDATES.robotsFollow),
|
|
61
|
+
ogTitle: resolve(SEO_FIELD_CANDIDATES.ogTitle),
|
|
62
|
+
ogDescription: resolve(SEO_FIELD_CANDIDATES.ogDescription),
|
|
63
|
+
ogImage: resolve(SEO_FIELD_CANDIDATES.ogImage),
|
|
64
|
+
ogType: resolve(SEO_FIELD_CANDIDATES.ogType),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Resolve an SEO concept's value from CMS content fields.
|
|
69
|
+
*
|
|
70
|
+
* Uses the field map to find the right CMS field, then reads the value.
|
|
71
|
+
* Returns empty string if no field is mapped or value is missing.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveSeoField(fieldMap, concept, fields) {
|
|
74
|
+
const cmsField = fieldMap[concept];
|
|
75
|
+
if (!cmsField)
|
|
76
|
+
return '';
|
|
77
|
+
const value = fields[cmsField];
|
|
78
|
+
return typeof value === 'string' && value.length > 0 ? value : '';
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=seo-field-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-field-map.js","sourceRoot":"","sources":["../src/seo-field-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAiCH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAA+C;IAC9E,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,CAAC,kBAAkB,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,CAAC;IACtE,MAAM,EAAE,CAAC,QAAQ,CAAC;IAClB,aAAa,EAAE,CAAC,gBAAgB,EAAE,MAAM,CAAC;IACzC,KAAK,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,YAAY,CAAC;IAC1C,YAAY,EAAE,CAAC,eAAe,CAAC;IAC/B,WAAW,EAAE,CAAC,cAAc,CAAC;IAC7B,YAAY,EAAE,CAAC,eAAe,CAAC;IAC/B,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,aAAa,EAAE,CAAC,gBAAgB,CAAC;IACjC,OAAO,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC;IAC9B,MAAM,EAAE,CAAC,SAAS,CAAC;CACpB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,aAAgC;IAC/D,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAA;IAEvC,SAAS,OAAO,CAAC,UAA6B;QAC5C,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;IACxD,CAAC;IAED,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC;QAC1C,WAAW,EAAE,OAAO,CAAC,oBAAoB,CAAC,WAAW,CAAC;QACtD,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC;QAC5C,aAAa,EAAE,OAAO,CAAC,oBAAoB,CAAC,aAAa,CAAC;QAC1D,KAAK,EAAE,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC;QAC1C,YAAY,EAAE,OAAO,CAAC,oBAAoB,CAAC,YAAY,CAAC;QACxD,WAAW,EAAE,OAAO,CAAC,oBAAoB,CAAC,WAAW,CAAC;QACtD,YAAY,EAAE,OAAO,CAAC,oBAAoB,CAAC,YAAY,CAAC;QACxD,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,OAAO,CAAC;QAC9C,aAAa,EAAE,OAAO,CAAC,oBAAoB,CAAC,aAAa,CAAC;QAC1D,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,OAAO,CAAC;QAC9C,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC;KAC7C,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAqB,EACrB,OAAwB,EACxB,MAA+B;IAE/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAClC,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAA;IACxB,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;AACnE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@krantho/seo-shared",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"homepage": "https://krantho.com",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/descoped/krantho.git",
|
|
9
|
+
"directory": "packages/seo-shared"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/descoped/krantho/issues"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"typescript": "^6.0.3"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"clean": "rm -rf dist"
|
|
31
|
+
}
|
|
6
32
|
}
|
package/README.md
DELETED