@shapio/schema 0.5.9 → 0.5.11
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/index.d.ts +19 -13
- package/dist/index.js +20 -14
- package/dist/index.js.map +1 -1
- package/dist/{resolve-viddCEYd.js → resolve-Csjpkpue.js} +2 -2
- package/dist/{resolve-viddCEYd.js.map → resolve-Csjpkpue.js.map} +1 -1
- package/dist/{resolve-7-z9VQqw.d.ts → resolve-DlXILdG3.d.ts} +2 -2
- package/dist/seoResolve.d.ts +1 -1
- package/dist/seoResolve.js +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* The built-in SEO component (plan seo-fields). It is ordinary schema data, created through the change planner
|
|
4
4
|
* and always shared with every site; what makes it "the" SEO component is its stable ID, never its API ID, so
|
|
5
|
-
* a renamed or extended copy is still
|
|
5
|
+
* a renamed or extended copy is still recognized and an unrelated `seo` component (an import) never is.
|
|
6
6
|
*/
|
|
7
7
|
const SEO_COMPONENT_ID = "f3905a00-d2a3-4c62-899a-c894bfd6cb9b";
|
|
8
8
|
/** The API ID the built-in is created with (it may be renamed later; detection never relies on it). */
|
|
@@ -88,4 +88,4 @@ const resolveSeo = (raw, context) => {
|
|
|
88
88
|
//#endregion
|
|
89
89
|
export { isValidTitleTemplate as a, SEO_COMPONENT_ID as c, SEO_FIELD_IDS as d, SEO_TITLE_PLACEHOLDER as f, SEO_TWITTER_HANDLE_PATTERN as h, applyTitleTemplate as i, SEO_DESCRIPTION_SOFT_MAX as l, SEO_TITLE_TEMPLATE_PATTERN as m, resolveSeo as n, seoDefaultsForLocale as o, SEO_TITLE_SOFT_MAX as p, EMPTY_SEO_DEFAULTS as r, SEO_COMPONENT_API_KEY as s, DEFAULT_SEO_KEYS as t, SEO_EDITOR_ID as u };
|
|
90
90
|
|
|
91
|
-
//# sourceMappingURL=resolve-
|
|
91
|
+
//# sourceMappingURL=resolve-Csjpkpue.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-
|
|
1
|
+
{"version":3,"file":"resolve-Csjpkpue.js","names":[],"sources":["../src/seo/ids.ts","../src/seo/locale.ts","../src/seo/resolve.ts"],"sourcesContent":["/**\n * The built-in SEO component (plan seo-fields). It is ordinary schema data, created through the change planner\n * and always shared with every site; what makes it \"the\" SEO component is its stable ID, never its API ID, so\n * a renamed or extended copy is still recognized and an unrelated `seo` component (an import) never is.\n */\nexport const SEO_COMPONENT_ID = 'f3905a00-d2a3-4c62-899a-c894bfd6cb9b';\n\n/** The API ID the built-in is created with (it may be renamed later; detection never relies on it). */\nexport const SEO_COMPONENT_API_KEY = 'seo';\n\n/** Stable field IDs of the built-in's fields. Resolver and admin look fields up by these. */\nexport const SEO_FIELD_IDS = {\n title: '3fe294a9-6af9-4019-8b32-43010822e45a',\n description: '6d1917f3-94a2-4391-ba1f-a98d14577b93',\n image: 'd27c9354-4afc-4583-93b4-367214a7714a',\n canonical: '17b374b6-cd85-444e-8403-20c7458ed29e',\n noindex: 'e8346f99-dc3c-4b5c-906f-4854e03c9a57',\n} as const;\n\nexport type SeoFieldKey = keyof typeof SEO_FIELD_IDS;\n\n/** The built-in editor for a field holding the SEO component (preview and counters in the admin). */\nexport const SEO_EDITOR_ID = 'seoEditor';\n\n/** Admin-only counters: lengths past which search results usually truncate. Never enforced. */\nexport const SEO_TITLE_SOFT_MAX = 70;\nexport const SEO_DESCRIPTION_SOFT_MAX = 160;\n\n/** The placeholder a title template must contain exactly once. */\nexport const SEO_TITLE_PLACEHOLDER = '%s';\n\n/** A title template holds the placeholder exactly once, e.g. `%s · Acme`. */\nexport const SEO_TITLE_TEMPLATE_PATTERN = /^(?:(?!%s)[\\s\\S])*%s(?:(?!%s)[\\s\\S])*$/;\n\n/** A Twitter/X handle with its `@`. */\nexport const SEO_TWITTER_HANDLE_PATTERN = /^@[A-Za-z0-9_]{1,15}$/;\n","import type { SeoDefaults, SeoLocaleDefaults } from './defaults.js';\nimport { SEO_TITLE_PLACEHOLDER, SEO_TITLE_TEMPLATE_PATTERN } from './ids.js';\n\n/** No defaults saved yet. */\nexport const EMPTY_SEO_DEFAULTS: SeoDefaults = { locales: {}, imageId: null, twitterHandle: null };\n\nexport const isValidTitleTemplate = (template: string): boolean => SEO_TITLE_TEMPLATE_PATTERN.test(template);\n\n/**\n * One locale's effective default texts: each key from the first locale of the chain that sets it (the\n * requested locale, then its fallbacks, then the default locale).\n */\nexport const seoDefaultsForLocale = (\n defaults: Pick<SeoDefaults, 'locales'>,\n localeChain: readonly string[],\n): SeoLocaleDefaults => {\n const pick = (key: keyof SeoLocaleDefaults) =>\n localeChain.map((code) => defaults.locales[code]?.[key]).find((value) => value !== undefined);\n const siteName = pick('siteName');\n const titleTemplate = pick('titleTemplate');\n const description = pick('description');\n return {\n ...(siteName !== undefined ? { siteName } : {}),\n ...(titleTemplate !== undefined ? { titleTemplate } : {}),\n ...(description !== undefined ? { description } : {}),\n };\n};\n\n/** Applies a title template (`%s` replaced once); an invalid template leaves the title as is. */\nexport const applyTitleTemplate = (title: string, template: string | undefined): string =>\n template !== undefined && isValidTitleTemplate(template)\n ? template.replace(SEO_TITLE_PLACEHOLDER, () => title)\n : title;\n","import type { SeoLocaleDefaults } from './defaults.js';\nimport type { SeoFieldKey } from './ids.js';\nimport { applyTitleTemplate } from './locale.js';\n\n/** The API IDs under which a delivered SEO value carries each built-in field (absent: removed or retyped). */\nexport type SeoKeys = Partial<Record<SeoFieldKey, string>>;\n\n/** The API IDs the built-in component is created with. */\nexport const DEFAULT_SEO_KEYS: Required<SeoKeys> = {\n title: 'title',\n description: 'description',\n image: 'image',\n canonical: 'canonical',\n noindex: 'noindex',\n};\n\nexport type ResolveSeoContext = {\n /** The site's default texts for the entry's locale (`seoDefaultsForLocale`). */\n defaults: SeoLocaleDefaults;\n /** The default social image in the delivered asset shape, or null. */\n image: unknown;\n /** The entry's own title (its title field) when the SEO title is empty; null when none is readable. */\n fallbackTitle: string | null;\n /** Where each field sits in `raw`; defaults to the built-in API IDs. */\n keys?: SeoKeys;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst text = (value: unknown): string | null =>\n typeof value === 'string' && value.trim() !== '' ? value : null;\n\n/**\n * The effective SEO values of one delivered entry, in the same shape as the raw value (plan seo-fields): the\n * title is the entry's SEO title, else its own title, through the site's template (the bare site name when\n * neither exists, never templated); description and image fall back to the site's defaults; canonical stays\n * the entry's value or null; noindex is a boolean. Other keys (fields a user added) pass through. Pure.\n */\nexport const resolveSeo = (raw: unknown, context: ResolveSeoContext): Record<string, unknown> => {\n const keys = context.keys ?? DEFAULT_SEO_KEYS;\n const output: Record<string, unknown> = isRecord(raw) ? { ...raw } : {};\n const value = (key: SeoFieldKey) => (keys[key] === undefined ? undefined : output[keys[key]]);\n const set = (key: SeoFieldKey, next: unknown) => {\n if (keys[key] !== undefined) {\n output[keys[key]] = next;\n }\n };\n const base = text(value('title')) ?? text(context.fallbackTitle);\n set(\n 'title',\n base !== null\n ? applyTitleTemplate(base, context.defaults.titleTemplate)\n : (context.defaults.siteName ?? null),\n );\n set('description', text(value('description')) ?? context.defaults.description ?? null);\n set('image', value('image') ?? context.image ?? null);\n set('canonical', text(value('canonical')));\n set('noindex', value('noindex') === true);\n return output;\n};\n"],"mappings":";;;;;;AAKA,MAAa,mBAAmB;;AAGhC,MAAa,wBAAwB;;AAGrC,MAAa,gBAAgB;CAC3B,OAAO;CACP,aAAa;CACb,OAAO;CACP,WAAW;CACX,SAAS;AACX;;AAKA,MAAa,gBAAgB;;AAG7B,MAAa,qBAAqB;AAClC,MAAa,2BAA2B;;AAGxC,MAAa,wBAAwB;;AAGrC,MAAa,6BAA6B;;AAG1C,MAAa,6BAA6B;;;;AC/B1C,MAAa,qBAAkC;CAAE,SAAS,CAAC;CAAG,SAAS;CAAM,eAAe;AAAK;AAEjG,MAAa,wBAAwB,aAA8B,2BAA2B,KAAK,QAAQ;;;;;AAM3G,MAAa,wBACX,UACA,gBACsB;CACtB,MAAM,QAAQ,QACZ,YAAY,KAAK,SAAS,SAAS,QAAQ,KAAK,GAAG,IAAI,CAAC,CAAC,MAAM,UAAU,UAAU,KAAA,CAAS;CAC9F,MAAM,WAAW,KAAK,UAAU;CAChC,MAAM,gBAAgB,KAAK,eAAe;CAC1C,MAAM,cAAc,KAAK,aAAa;CACtC,OAAO;EACL,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,kBAAkB,KAAA,IAAY,EAAE,cAAc,IAAI,CAAC;EACvD,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;CACrD;AACF;;AAGA,MAAa,sBAAsB,OAAe,aAChD,aAAa,KAAA,KAAa,qBAAqB,QAAQ,IACnD,SAAS,QAAA,YAAqC,KAAK,IACnD;;;;ACxBN,MAAa,mBAAsC;CACjD,OAAO;CACP,aAAa;CACb,OAAO;CACP,WAAW;CACX,SAAS;AACX;AAaA,MAAM,YAAY,UAChB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAErE,MAAM,QAAQ,UACZ,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,KAAK,QAAQ;;;;;;;AAQ7D,MAAa,cAAc,KAAc,YAAwD;CAC/F,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,SAAkC,SAAS,GAAG,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC;CACtE,MAAM,SAAS,QAAsB,KAAK,SAAS,KAAA,IAAY,KAAA,IAAY,OAAO,KAAK;CACvF,MAAM,OAAO,KAAkB,SAAkB;EAC/C,IAAI,KAAK,SAAS,KAAA,GAChB,OAAO,KAAK,QAAQ;CAExB;CACA,MAAM,OAAO,KAAK,MAAM,OAAO,CAAC,KAAK,KAAK,QAAQ,aAAa;CAC/D,IACE,SACA,SAAS,OACL,mBAAmB,MAAM,QAAQ,SAAS,aAAa,IACtD,QAAQ,SAAS,YAAY,IACpC;CACA,IAAI,eAAe,KAAK,MAAM,aAAa,CAAC,KAAK,QAAQ,SAAS,eAAe,IAAI;CACrF,IAAI,SAAS,MAAM,OAAO,KAAK,QAAQ,SAAS,IAAI;CACpD,IAAI,aAAa,KAAK,MAAM,WAAW,CAAC,CAAC;CACzC,IAAI,WAAW,MAAM,SAAS,MAAM,IAAI;CACxC,OAAO;AACT"}
|
|
@@ -3,7 +3,7 @@ import { Static, Type } from "typebox";
|
|
|
3
3
|
/**
|
|
4
4
|
* The built-in SEO component (plan seo-fields). It is ordinary schema data, created through the change planner
|
|
5
5
|
* and always shared with every site; what makes it "the" SEO component is its stable ID, never its API ID, so
|
|
6
|
-
* a renamed or extended copy is still
|
|
6
|
+
* a renamed or extended copy is still recognized and an unrelated `seo` component (an import) never is.
|
|
7
7
|
*/
|
|
8
8
|
declare const SEO_COMPONENT_ID = "f3905a00-d2a3-4c62-899a-c894bfd6cb9b";
|
|
9
9
|
/** The API ID the built-in is created with (it may be renamed later; detection never relies on it). */
|
|
@@ -88,4 +88,4 @@ type ResolveSeoContext = {
|
|
|
88
88
|
declare const resolveSeo: (raw: unknown, context: ResolveSeoContext) => Record<string, unknown>;
|
|
89
89
|
//#endregion
|
|
90
90
|
export { SeoFieldKey as S, SEO_FIELD_IDS as _, EMPTY_SEO_DEFAULTS as a, SEO_TITLE_TEMPLATE_PATTERN as b, seoDefaultsForLocale as c, SeoLocaleDefaults as d, SeoLocaleDefaultsSchema as f, SEO_EDITOR_ID as g, SEO_DESCRIPTION_SOFT_MAX as h, resolveSeo as i, SeoDefaults as l, SEO_COMPONENT_ID as m, ResolveSeoContext as n, applyTitleTemplate as o, SEO_COMPONENT_API_KEY as p, SeoKeys as r, isValidTitleTemplate as s, DEFAULT_SEO_KEYS as t, SeoDefaultsSchema as u, SEO_TITLE_PLACEHOLDER as v, SEO_TWITTER_HANDLE_PATTERN as x, SEO_TITLE_SOFT_MAX as y };
|
|
91
|
-
//# sourceMappingURL=resolve-
|
|
91
|
+
//# sourceMappingURL=resolve-DlXILdG3.d.ts.map
|
package/dist/seoResolve.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { S as SeoFieldKey, _ as SEO_FIELD_IDS, a as EMPTY_SEO_DEFAULTS, b as SEO_TITLE_TEMPLATE_PATTERN, c as seoDefaultsForLocale, d as SeoLocaleDefaults, g as SEO_EDITOR_ID, h as SEO_DESCRIPTION_SOFT_MAX, i as resolveSeo, l as SeoDefaults, m as SEO_COMPONENT_ID, n as ResolveSeoContext, o as applyTitleTemplate, p as SEO_COMPONENT_API_KEY, r as SeoKeys, s as isValidTitleTemplate, t as DEFAULT_SEO_KEYS, v as SEO_TITLE_PLACEHOLDER, x as SEO_TWITTER_HANDLE_PATTERN, y as SEO_TITLE_SOFT_MAX } from "./resolve-
|
|
1
|
+
import { S as SeoFieldKey, _ as SEO_FIELD_IDS, a as EMPTY_SEO_DEFAULTS, b as SEO_TITLE_TEMPLATE_PATTERN, c as seoDefaultsForLocale, d as SeoLocaleDefaults, g as SEO_EDITOR_ID, h as SEO_DESCRIPTION_SOFT_MAX, i as resolveSeo, l as SeoDefaults, m as SEO_COMPONENT_ID, n as ResolveSeoContext, o as applyTitleTemplate, p as SEO_COMPONENT_API_KEY, r as SeoKeys, s as isValidTitleTemplate, t as DEFAULT_SEO_KEYS, v as SEO_TITLE_PLACEHOLDER, x as SEO_TWITTER_HANDLE_PATTERN, y as SEO_TITLE_SOFT_MAX } from "./resolve-DlXILdG3.js";
|
|
2
2
|
export { DEFAULT_SEO_KEYS, EMPTY_SEO_DEFAULTS, ResolveSeoContext, SEO_COMPONENT_API_KEY, SEO_COMPONENT_ID, SEO_DESCRIPTION_SOFT_MAX, SEO_EDITOR_ID, SEO_FIELD_IDS, SEO_TITLE_PLACEHOLDER, SEO_TITLE_SOFT_MAX, SEO_TITLE_TEMPLATE_PATTERN, SEO_TWITTER_HANDLE_PATTERN, type SeoDefaults, SeoFieldKey, SeoKeys, type SeoLocaleDefaults, applyTitleTemplate, isValidTitleTemplate, resolveSeo, seoDefaultsForLocale };
|
package/dist/seoResolve.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as isValidTitleTemplate, c as SEO_COMPONENT_ID, d as SEO_FIELD_IDS, f as SEO_TITLE_PLACEHOLDER, h as SEO_TWITTER_HANDLE_PATTERN, i as applyTitleTemplate, l as SEO_DESCRIPTION_SOFT_MAX, m as SEO_TITLE_TEMPLATE_PATTERN, n as resolveSeo, o as seoDefaultsForLocale, p as SEO_TITLE_SOFT_MAX, r as EMPTY_SEO_DEFAULTS, s as SEO_COMPONENT_API_KEY, t as DEFAULT_SEO_KEYS, u as SEO_EDITOR_ID } from "./resolve-
|
|
1
|
+
import { a as isValidTitleTemplate, c as SEO_COMPONENT_ID, d as SEO_FIELD_IDS, f as SEO_TITLE_PLACEHOLDER, h as SEO_TWITTER_HANDLE_PATTERN, i as applyTitleTemplate, l as SEO_DESCRIPTION_SOFT_MAX, m as SEO_TITLE_TEMPLATE_PATTERN, n as resolveSeo, o as seoDefaultsForLocale, p as SEO_TITLE_SOFT_MAX, r as EMPTY_SEO_DEFAULTS, s as SEO_COMPONENT_API_KEY, t as DEFAULT_SEO_KEYS, u as SEO_EDITOR_ID } from "./resolve-Csjpkpue.js";
|
|
2
2
|
export { DEFAULT_SEO_KEYS, EMPTY_SEO_DEFAULTS, SEO_COMPONENT_API_KEY, SEO_COMPONENT_ID, SEO_DESCRIPTION_SOFT_MAX, SEO_EDITOR_ID, SEO_FIELD_IDS, SEO_TITLE_PLACEHOLDER, SEO_TITLE_SOFT_MAX, SEO_TITLE_TEMPLATE_PATTERN, SEO_TWITTER_HANDLE_PATTERN, applyTitleTemplate, isValidTitleTemplate, resolveSeo, seoDefaultsForLocale };
|