@shapio/schema 0.3.1 → 0.4.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/dist/index.d.ts +14 -2
- package/dist/index.js +157 -57
- package/dist/index.js.map +1 -1
- package/dist/resolve-7-z9VQqw.d.ts +91 -0
- package/dist/resolve-viddCEYd.js +91 -0
- package/dist/resolve-viddCEYd.js.map +1 -0
- package/dist/seoResolve.d.ts +2 -0
- package/dist/seoResolve.js +2 -0
- package/package.json +6 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { a as isEmptyRichText, i as RichTextResult, n as RichTextNode, o as richTextMediaIds, r as RichTextProblem, s as validateRichText, t as RichTextDocument } from "./validate-Oyo0GJ9j.js";
|
|
2
|
+
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, f as SeoLocaleDefaultsSchema, 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, u as SeoDefaultsSchema, v as SEO_TITLE_PLACEHOLDER, x as SEO_TWITTER_HANDLE_PATTERN, y as SEO_TITLE_SOFT_MAX } from "./resolve-7-z9VQqw.js";
|
|
2
3
|
import { Static, TSchema, Type } from "typebox";
|
|
3
4
|
//#region src/ids.d.ts
|
|
4
5
|
/**
|
|
@@ -1171,7 +1172,7 @@ export type ThemeVariant = (typeof THEME_VARIANTS)[number];
|
|
|
1171
1172
|
/** A theme key: used in `data-theme` and in CSS selectors, so deliberately narrow. */
|
|
1172
1173
|
export declare const THEME_KEY_PATTERN: RegExp;
|
|
1173
1174
|
/** The themes the admin ships; an extension theme may not reuse these keys. */
|
|
1174
|
-
export declare const BUILT_IN_THEME_KEYS: readonly ["shapio", "classic", "murdered-out", "snowed"];
|
|
1175
|
+
export declare const BUILT_IN_THEME_KEYS: readonly ["shapio", "classic", "murdered-out", "forest", "snowed", "butter"];
|
|
1175
1176
|
export type BuiltInThemeKey = (typeof BUILT_IN_THEME_KEYS)[number];
|
|
1176
1177
|
/**
|
|
1177
1178
|
* A token value an extension may use: a hex colour or a colour function whose arguments are numbers, units
|
|
@@ -1208,5 +1209,16 @@ export type ContrastCheck = {
|
|
|
1208
1209
|
/** Every pair the variant must meet, with its ratio. Missing tokens report an undefined ratio. */
|
|
1209
1210
|
export declare const checkThemeContrast: (tokens: Readonly<Record<string, string>>, variant: ThemeVariant) => ContrastCheck[];
|
|
1210
1211
|
//#endregion
|
|
1211
|
-
|
|
1212
|
+
//#region src/seo/field.d.ts
|
|
1213
|
+
/** Whether a field holds the built-in SEO component (by stable ID, whatever its API ID or editor). */
|
|
1214
|
+
export declare const isSeoField: (field: FieldDefinition) => boolean;
|
|
1215
|
+
//#endregion
|
|
1216
|
+
//#region src/seo/definition.d.ts
|
|
1217
|
+
/**
|
|
1218
|
+
* The built-in SEO component as first created. All fields are public and none has a length limit: the 70 and
|
|
1219
|
+
* 160 character marks are admin-only counters (`SEO_TITLE_SOFT_MAX`), never validation.
|
|
1220
|
+
*/
|
|
1221
|
+
export declare const seoComponentDefinition: () => ComponentDefinition;
|
|
1222
|
+
//#endregion
|
|
1223
|
+
export { DEFAULT_SEO_KEYS, EMPTY_SEO_DEFAULTS, ResolveSeoContext, RichTextDocument, RichTextNode, RichTextProblem, RichTextResult, 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, SeoDefaults, SeoDefaultsSchema, SeoFieldKey, SeoKeys, SeoLocaleDefaults, SeoLocaleDefaultsSchema, applyTitleTemplate, isEmptyRichText, isValidTitleTemplate, resolveSeo, richTextMediaIds, seoDefaultsForLocale, validateRichText };
|
|
1212
1224
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { _ as STABLE_ID_PATTERN, a as MAX_RICHTEXT_DEPTH, c as BIGINTEGER_PATTERN, d as DECIMAL_PATTERN, f as RICHTEXT_FORMAT, g as UID_PATTERN, h as TIME_PATTERN, i as MARK_RULES, l as DATETIME_PATTERN, m as SLUG_PATTERN, n as richTextMediaIds, o as NODE_RULES, p as RICHTEXT_FORMAT_VERSION, r as validateRichText, s as SAFE_LINK_PATTERN, t as isEmptyRichText, u as DATE_PATTERN, v as createStableId, y as isStableId } from "./validate-BQGutaBo.js";
|
|
2
|
+
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-viddCEYd.js";
|
|
2
3
|
import { Type } from "typebox";
|
|
3
4
|
import pluralize from "pluralize";
|
|
4
5
|
import { Value } from "typebox/value";
|
|
@@ -103,7 +104,7 @@ const STORAGE_FAMILY = {
|
|
|
103
104
|
* defaulted properties may be omitted. `normalizeDefinition` turns input into the normalized types below,
|
|
104
105
|
* which are what Shapio stores, hashes and diffs.
|
|
105
106
|
*/
|
|
106
|
-
const closed$
|
|
107
|
+
const closed$3 = { additionalProperties: false };
|
|
107
108
|
const MODEL_KINDS = ["collection", "singleton"];
|
|
108
109
|
const DEFINITION_KINDS = [...MODEL_KINDS, "component"];
|
|
109
110
|
const SORT_DIRECTIONS = ["asc", "desc"];
|
|
@@ -121,7 +122,7 @@ const EditorChoiceInputSchema = Type.Object({
|
|
|
121
122
|
maxLength: 128
|
|
122
123
|
}),
|
|
123
124
|
options: Type.Optional(Type.Record(Type.String(), Type.Unknown()))
|
|
124
|
-
}, closed$
|
|
125
|
+
}, closed$3);
|
|
125
126
|
const FieldInputSchema = Type.Object({
|
|
126
127
|
id: Type.Optional(Type.String()),
|
|
127
128
|
apiKey: Type.String(),
|
|
@@ -144,7 +145,7 @@ const FieldInputSchema = Type.Object({
|
|
|
144
145
|
/** Type-specific settings, validated against SETTINGS_SCHEMAS[type]. */
|
|
145
146
|
settings: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
146
147
|
editor: Type.Optional(EditorChoiceInputSchema)
|
|
147
|
-
}, closed$
|
|
148
|
+
}, closed$3);
|
|
148
149
|
const FieldGroupSchema = Type.Object({
|
|
149
150
|
id: Type.String({
|
|
150
151
|
minLength: 1,
|
|
@@ -152,7 +153,7 @@ const FieldGroupSchema = Type.Object({
|
|
|
152
153
|
}),
|
|
153
154
|
label: Label,
|
|
154
155
|
fieldIds: Type.Array(Type.String())
|
|
155
|
-
}, closed$
|
|
156
|
+
}, closed$3);
|
|
156
157
|
const ModelDisplayInputSchema = Type.Object({
|
|
157
158
|
/** Field whose value labels an entry in lists, pickers and relation summaries. */
|
|
158
159
|
titleFieldId: Type.Optional(Type.String()),
|
|
@@ -161,7 +162,7 @@ const ModelDisplayInputSchema = Type.Object({
|
|
|
161
162
|
defaultSort: Type.Optional(Type.Object({
|
|
162
163
|
fieldId: Type.String(),
|
|
163
164
|
direction: Type.Enum(SORT_DIRECTIONS)
|
|
164
|
-
}, closed$
|
|
165
|
+
}, closed$3)),
|
|
165
166
|
/** Editor layout: named sections of the entry form. */
|
|
166
167
|
groups: Type.Optional(Type.Array(FieldGroupSchema)),
|
|
167
168
|
/** Fields rendered as blocks in the entry document's canvas, in order. Default: see `effectiveLayout`. */
|
|
@@ -170,11 +171,11 @@ const ModelDisplayInputSchema = Type.Object({
|
|
|
170
171
|
coverFieldId: Type.Optional(Type.String()),
|
|
171
172
|
/** Properties shown as chips in the document's strip. Default: the first non-empty ones. */
|
|
172
173
|
stripFieldIds: Type.Optional(Type.Array(Type.String()))
|
|
173
|
-
}, closed$
|
|
174
|
+
}, closed$3);
|
|
174
175
|
const ComponentDisplayInputSchema = Type.Object({
|
|
175
176
|
titleFieldId: Type.Optional(Type.String()),
|
|
176
177
|
groups: Type.Optional(Type.Array(FieldGroupSchema))
|
|
177
|
-
}, closed$
|
|
178
|
+
}, closed$3);
|
|
178
179
|
const definitionBase = {
|
|
179
180
|
id: Type.Optional(Type.String()),
|
|
180
181
|
apiKey: Type.String(),
|
|
@@ -194,7 +195,7 @@ const ModelDefinitionInputSchema = Type.Object({
|
|
|
194
195
|
/** Entries have separate draft and published states. Default true. */
|
|
195
196
|
draftAndPublish: Type.Optional(Type.Boolean()),
|
|
196
197
|
display: Type.Optional(ModelDisplayInputSchema)
|
|
197
|
-
}, closed$
|
|
198
|
+
}, closed$3);
|
|
198
199
|
const ComponentDefinitionInputSchema = Type.Object({
|
|
199
200
|
...definitionBase,
|
|
200
201
|
kind: Type.Literal("component"),
|
|
@@ -207,7 +208,7 @@ const ComponentDefinitionInputSchema = Type.Object({
|
|
|
207
208
|
maxLength: 64
|
|
208
209
|
})),
|
|
209
210
|
display: Type.Optional(ComponentDisplayInputSchema)
|
|
210
|
-
}, closed$
|
|
211
|
+
}, closed$3);
|
|
211
212
|
const DefinitionInputSchema = Type.Union([ModelDefinitionInputSchema, ComponentDefinitionInputSchema]);
|
|
212
213
|
const isComponentDefinition = (definition) => definition.kind === "component";
|
|
213
214
|
const isModelDefinition = (definition) => definition.kind !== "component";
|
|
@@ -235,7 +236,7 @@ const LocaleInputSchema = Type.Object({
|
|
|
235
236
|
* enum values...). Each schema is closed (`additionalProperties: false`) so a typo in a hand-edited schema
|
|
236
237
|
* file is reported instead of ignored. Defaults are applied by `normalizeDefinition`.
|
|
237
238
|
*/
|
|
238
|
-
const closed$
|
|
239
|
+
const closed$2 = { additionalProperties: false };
|
|
239
240
|
const NonNegativeInt = Type.Integer({ minimum: 0 });
|
|
240
241
|
const pattern = (regex) => Type.String({ pattern: regex.source });
|
|
241
242
|
const lengthRules = {
|
|
@@ -263,7 +264,7 @@ const EnumValueSchema = Type.Object({
|
|
|
263
264
|
minLength: 1,
|
|
264
265
|
maxLength: 200
|
|
265
266
|
})
|
|
266
|
-
}, closed$
|
|
267
|
+
}, closed$2);
|
|
267
268
|
const SETTINGS_SCHEMAS = {
|
|
268
269
|
string: Type.Object({
|
|
269
270
|
...lengthRules,
|
|
@@ -271,20 +272,20 @@ const SETTINGS_SCHEMAS = {
|
|
|
271
272
|
minLength: 1,
|
|
272
273
|
maxLength: 500
|
|
273
274
|
}))
|
|
274
|
-
}, closed$
|
|
275
|
-
text: Type.Object(lengthRules, closed$
|
|
275
|
+
}, closed$2),
|
|
276
|
+
text: Type.Object(lengthRules, closed$2),
|
|
276
277
|
richtext: Type.Object({
|
|
277
278
|
formatVersion: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
278
279
|
maxLength: Type.Optional(Type.Integer({ minimum: 1 }))
|
|
279
|
-
}, closed$
|
|
280
|
+
}, closed$2),
|
|
280
281
|
number: Type.Object({
|
|
281
282
|
min: Type.Optional(Type.Number()),
|
|
282
283
|
max: Type.Optional(Type.Number())
|
|
283
|
-
}, closed$
|
|
284
|
+
}, closed$2),
|
|
284
285
|
integer: Type.Object({
|
|
285
286
|
min: Type.Optional(Type.Integer()),
|
|
286
287
|
max: Type.Optional(Type.Integer())
|
|
287
|
-
}, closed$
|
|
288
|
+
}, closed$2),
|
|
288
289
|
decimal: Type.Object({
|
|
289
290
|
precision: Type.Optional(Type.Integer({
|
|
290
291
|
minimum: 1,
|
|
@@ -296,70 +297,74 @@ const SETTINGS_SCHEMAS = {
|
|
|
296
297
|
})),
|
|
297
298
|
min: Type.Optional(pattern(DECIMAL_PATTERN)),
|
|
298
299
|
max: Type.Optional(pattern(DECIMAL_PATTERN))
|
|
299
|
-
}, closed$
|
|
300
|
+
}, closed$2),
|
|
300
301
|
biginteger: Type.Object({
|
|
301
302
|
min: Type.Optional(pattern(BIGINTEGER_PATTERN)),
|
|
302
303
|
max: Type.Optional(pattern(BIGINTEGER_PATTERN))
|
|
303
|
-
}, closed$
|
|
304
|
-
boolean: Type.Object({}, closed$
|
|
304
|
+
}, closed$2),
|
|
305
|
+
boolean: Type.Object({}, closed$2),
|
|
305
306
|
date: Type.Object({
|
|
306
307
|
min: Type.Optional(pattern(DATE_PATTERN)),
|
|
307
308
|
max: Type.Optional(pattern(DATE_PATTERN))
|
|
308
|
-
}, closed$
|
|
309
|
+
}, closed$2),
|
|
309
310
|
datetime: Type.Object({
|
|
310
311
|
min: Type.Optional(pattern(DATETIME_PATTERN)),
|
|
311
312
|
max: Type.Optional(pattern(DATETIME_PATTERN))
|
|
312
|
-
}, closed$
|
|
313
|
+
}, closed$2),
|
|
313
314
|
time: Type.Object({
|
|
314
315
|
min: Type.Optional(pattern(TIME_PATTERN)),
|
|
315
316
|
max: Type.Optional(pattern(TIME_PATTERN))
|
|
316
|
-
}, closed$
|
|
317
|
+
}, closed$2),
|
|
317
318
|
enum: Type.Object({
|
|
318
319
|
values: Type.Array(EnumValueSchema, {
|
|
319
320
|
minItems: 1,
|
|
320
321
|
maxItems: 500
|
|
321
322
|
}),
|
|
322
323
|
multiple: Type.Optional(Type.Boolean())
|
|
323
|
-
}, closed$
|
|
324
|
-
json: Type.Object({}, closed$
|
|
324
|
+
}, closed$2),
|
|
325
|
+
json: Type.Object({}, closed$2),
|
|
325
326
|
slug: Type.Object({
|
|
326
327
|
...lengthRules,
|
|
327
328
|
sourceFieldId: Type.Optional(Type.String())
|
|
328
|
-
}, closed$
|
|
329
|
-
email: Type.Object({}, closed$
|
|
329
|
+
}, closed$2),
|
|
330
|
+
email: Type.Object({}, closed$2),
|
|
330
331
|
url: Type.Object({ protocols: Type.Optional(Type.Array(Type.Enum([
|
|
331
332
|
"http",
|
|
332
333
|
"https",
|
|
333
334
|
"mailto",
|
|
334
335
|
"tel"
|
|
335
|
-
]), { minItems: 1 })) }, closed$
|
|
336
|
-
uid: Type.Object(lengthRules, closed$
|
|
336
|
+
]), { minItems: 1 })) }, closed$2),
|
|
337
|
+
uid: Type.Object(lengthRules, closed$2),
|
|
337
338
|
media: Type.Object({
|
|
338
339
|
multiple: Type.Optional(Type.Boolean()),
|
|
339
340
|
allowedKinds: Type.Optional(Type.Array(Type.Enum(MEDIA_KINDS), { minItems: 1 })),
|
|
340
341
|
...countRules
|
|
341
|
-
}, closed$
|
|
342
|
+
}, closed$2),
|
|
342
343
|
relation: Type.Object({
|
|
343
344
|
target: Type.String(),
|
|
344
345
|
cardinality: Type.Enum(RELATION_CARDINALITIES),
|
|
345
346
|
...countRules
|
|
346
|
-
}, closed$
|
|
347
|
+
}, closed$2),
|
|
347
348
|
component: Type.Object({
|
|
348
349
|
component: Type.String(),
|
|
349
350
|
repeatable: Type.Optional(Type.Boolean()),
|
|
350
351
|
...countRules
|
|
351
|
-
}, closed$
|
|
352
|
+
}, closed$2),
|
|
352
353
|
dynamiczone: Type.Object({
|
|
353
354
|
components: Type.Array(Type.String(), {
|
|
354
355
|
minItems: 1,
|
|
355
356
|
maxItems: 100
|
|
356
357
|
}),
|
|
357
358
|
...countRules
|
|
358
|
-
}, closed$
|
|
359
|
+
}, closed$2)
|
|
359
360
|
};
|
|
360
361
|
//#endregion
|
|
362
|
+
//#region src/seo/field.ts
|
|
363
|
+
/** Whether a field holds the built-in SEO component (by stable ID, whatever its API ID or editor). */
|
|
364
|
+
const isSeoField = (field) => field.type === "component" && field.settings.component === "f3905a00-d2a3-4c62-899a-c894bfd6cb9b" && !field.settings.repeatable;
|
|
365
|
+
//#endregion
|
|
361
366
|
//#region src/editors/catalogue.ts
|
|
362
|
-
const closed = { additionalProperties: false };
|
|
367
|
+
const closed$1 = { additionalProperties: false };
|
|
363
368
|
const Placeholder = Type.Optional(Type.String({ maxLength: 200 }));
|
|
364
369
|
const isMultipleEnum = (field) => field.type === "enum" && field.settings.multiple;
|
|
365
370
|
const entries = [
|
|
@@ -371,7 +376,7 @@ const entries = [
|
|
|
371
376
|
"url",
|
|
372
377
|
"uid"
|
|
373
378
|
],
|
|
374
|
-
optionsSchema: Type.Object({ placeholder: Placeholder }, closed)
|
|
379
|
+
optionsSchema: Type.Object({ placeholder: Placeholder }, closed$1)
|
|
375
380
|
},
|
|
376
381
|
{
|
|
377
382
|
id: "textarea",
|
|
@@ -382,7 +387,7 @@ const entries = [
|
|
|
382
387
|
minimum: 2,
|
|
383
388
|
maximum: 40
|
|
384
389
|
}))
|
|
385
|
-
}, closed)
|
|
390
|
+
}, closed$1)
|
|
386
391
|
},
|
|
387
392
|
{
|
|
388
393
|
id: "color",
|
|
@@ -390,12 +395,12 @@ const entries = [
|
|
|
390
395
|
optionsSchema: Type.Object({
|
|
391
396
|
format: Type.Optional(Type.Enum(["hex", "rgb"])),
|
|
392
397
|
presets: Type.Optional(Type.Array(Type.String({ maxLength: 32 }), { maxItems: 50 }))
|
|
393
|
-
}, closed)
|
|
398
|
+
}, closed$1)
|
|
394
399
|
},
|
|
395
400
|
{
|
|
396
401
|
id: "richText",
|
|
397
402
|
dataTypes: ["richtext"],
|
|
398
|
-
optionsSchema: Type.Object({ toolbar: Type.Optional(Type.Enum(["full", "minimal"])) }, closed)
|
|
403
|
+
optionsSchema: Type.Object({ toolbar: Type.Optional(Type.Enum(["full", "minimal"])) }, closed$1)
|
|
399
404
|
},
|
|
400
405
|
{
|
|
401
406
|
id: "numberInput",
|
|
@@ -408,17 +413,17 @@ const entries = [
|
|
|
408
413
|
optionsSchema: Type.Object({
|
|
409
414
|
placeholder: Placeholder,
|
|
410
415
|
step: Type.Optional(Type.Number({ exclusiveMinimum: 0 }))
|
|
411
|
-
}, closed)
|
|
416
|
+
}, closed$1)
|
|
412
417
|
},
|
|
413
418
|
{
|
|
414
419
|
id: "toggle",
|
|
415
420
|
dataTypes: ["boolean"],
|
|
416
|
-
optionsSchema: Type.Object({}, closed)
|
|
421
|
+
optionsSchema: Type.Object({}, closed$1)
|
|
417
422
|
},
|
|
418
423
|
{
|
|
419
424
|
id: "checkbox",
|
|
420
425
|
dataTypes: ["boolean"],
|
|
421
|
-
optionsSchema: Type.Object({}, closed)
|
|
426
|
+
optionsSchema: Type.Object({}, closed$1)
|
|
422
427
|
},
|
|
423
428
|
{
|
|
424
429
|
id: "segmented",
|
|
@@ -426,35 +431,35 @@ const entries = [
|
|
|
426
431
|
optionsSchema: Type.Object({
|
|
427
432
|
trueLabel: Type.Optional(Type.String({ maxLength: 50 })),
|
|
428
433
|
falseLabel: Type.Optional(Type.String({ maxLength: 50 }))
|
|
429
|
-
}, closed),
|
|
434
|
+
}, closed$1),
|
|
430
435
|
supports: (field) => !isMultipleEnum(field)
|
|
431
436
|
},
|
|
432
437
|
{
|
|
433
438
|
id: "select",
|
|
434
439
|
dataTypes: ["enum"],
|
|
435
|
-
optionsSchema: Type.Object({ placeholder: Placeholder }, closed)
|
|
440
|
+
optionsSchema: Type.Object({ placeholder: Placeholder }, closed$1)
|
|
436
441
|
},
|
|
437
442
|
{
|
|
438
443
|
id: "radio",
|
|
439
444
|
dataTypes: ["enum"],
|
|
440
|
-
optionsSchema: Type.Object({ layout: Type.Optional(Type.Enum(["vertical", "horizontal"])) }, closed),
|
|
445
|
+
optionsSchema: Type.Object({ layout: Type.Optional(Type.Enum(["vertical", "horizontal"])) }, closed$1),
|
|
441
446
|
supports: (field) => !isMultipleEnum(field)
|
|
442
447
|
},
|
|
443
448
|
{
|
|
444
449
|
id: "checkboxGroup",
|
|
445
450
|
dataTypes: ["enum"],
|
|
446
|
-
optionsSchema: Type.Object({ layout: Type.Optional(Type.Enum(["vertical", "horizontal"])) }, closed),
|
|
451
|
+
optionsSchema: Type.Object({ layout: Type.Optional(Type.Enum(["vertical", "horizontal"])) }, closed$1),
|
|
447
452
|
supports: isMultipleEnum
|
|
448
453
|
},
|
|
449
454
|
{
|
|
450
455
|
id: "datePicker",
|
|
451
456
|
dataTypes: ["date"],
|
|
452
|
-
optionsSchema: Type.Object({}, closed)
|
|
457
|
+
optionsSchema: Type.Object({}, closed$1)
|
|
453
458
|
},
|
|
454
459
|
{
|
|
455
460
|
id: "dateTimePicker",
|
|
456
461
|
dataTypes: ["datetime"],
|
|
457
|
-
optionsSchema: Type.Object({ display: Type.Optional(Type.Enum(["local", "utc"])) }, closed)
|
|
462
|
+
optionsSchema: Type.Object({ display: Type.Optional(Type.Enum(["local", "utc"])) }, closed$1)
|
|
458
463
|
},
|
|
459
464
|
{
|
|
460
465
|
id: "timePicker",
|
|
@@ -462,12 +467,12 @@ const entries = [
|
|
|
462
467
|
optionsSchema: Type.Object({ stepMinutes: Type.Optional(Type.Integer({
|
|
463
468
|
minimum: 1,
|
|
464
469
|
maximum: 60
|
|
465
|
-
})) }, closed)
|
|
470
|
+
})) }, closed$1)
|
|
466
471
|
},
|
|
467
472
|
{
|
|
468
473
|
id: "slugInput",
|
|
469
474
|
dataTypes: ["slug"],
|
|
470
|
-
optionsSchema: Type.Object({ placeholder: Placeholder }, closed)
|
|
475
|
+
optionsSchema: Type.Object({ placeholder: Placeholder }, closed$1)
|
|
471
476
|
},
|
|
472
477
|
{
|
|
473
478
|
id: "jsonEditor",
|
|
@@ -475,27 +480,33 @@ const entries = [
|
|
|
475
480
|
optionsSchema: Type.Object({ rows: Type.Optional(Type.Integer({
|
|
476
481
|
minimum: 3,
|
|
477
482
|
maximum: 80
|
|
478
|
-
})) }, closed)
|
|
483
|
+
})) }, closed$1)
|
|
479
484
|
},
|
|
480
485
|
{
|
|
481
486
|
id: "mediaPicker",
|
|
482
487
|
dataTypes: ["media"],
|
|
483
|
-
optionsSchema: Type.Object({}, closed)
|
|
488
|
+
optionsSchema: Type.Object({}, closed$1)
|
|
484
489
|
},
|
|
485
490
|
{
|
|
486
491
|
id: "relationPicker",
|
|
487
492
|
dataTypes: ["relation"],
|
|
488
|
-
optionsSchema: Type.Object({ allowInlineCreate: Type.Optional(Type.Boolean()) }, closed)
|
|
493
|
+
optionsSchema: Type.Object({ allowInlineCreate: Type.Optional(Type.Boolean()) }, closed$1)
|
|
489
494
|
},
|
|
490
495
|
{
|
|
491
496
|
id: "componentEditor",
|
|
492
497
|
dataTypes: ["component"],
|
|
493
|
-
optionsSchema: Type.Object({ collapsed: Type.Optional(Type.Boolean()) }, closed)
|
|
498
|
+
optionsSchema: Type.Object({ collapsed: Type.Optional(Type.Boolean()) }, closed$1)
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
id: SEO_EDITOR_ID,
|
|
502
|
+
dataTypes: ["component"],
|
|
503
|
+
optionsSchema: Type.Object({}, closed$1),
|
|
504
|
+
supports: isSeoField
|
|
494
505
|
},
|
|
495
506
|
{
|
|
496
507
|
id: "dynamicZoneEditor",
|
|
497
508
|
dataTypes: ["dynamiczone"],
|
|
498
|
-
optionsSchema: Type.Object({ collapsed: Type.Optional(Type.Boolean()) }, closed)
|
|
509
|
+
optionsSchema: Type.Object({ collapsed: Type.Optional(Type.Boolean()) }, closed$1)
|
|
499
510
|
}
|
|
500
511
|
];
|
|
501
512
|
const EDITOR_CATALOGUE = new Map(entries.map((entry) => [entry.id, entry]));
|
|
@@ -939,7 +950,10 @@ const RESERVED_TYPE_NAMES = [
|
|
|
939
950
|
"SnapshotChangeKind",
|
|
940
951
|
"SnapshotChangeLocale",
|
|
941
952
|
"SnapshotChangePage",
|
|
942
|
-
"SnapshotInfo"
|
|
953
|
+
"SnapshotInfo",
|
|
954
|
+
"SiteInfo",
|
|
955
|
+
"SiteSeoDefaults",
|
|
956
|
+
"SiteSeoLocale"
|
|
943
957
|
];
|
|
944
958
|
/**
|
|
945
959
|
* Model and component API keys the admin uses as static URL segments (`/content/new`,
|
|
@@ -973,7 +987,8 @@ const RESERVED_FIELD_API_KEYS = [
|
|
|
973
987
|
const RESERVED_QUERY_NAMES = [
|
|
974
988
|
"_schemaVersion",
|
|
975
989
|
"_changes",
|
|
976
|
-
"_snapshot"
|
|
990
|
+
"_snapshot",
|
|
991
|
+
"_site"
|
|
977
992
|
];
|
|
978
993
|
/** Every name a definition contributes to the GraphQL schema. */
|
|
979
994
|
const generatedNames = (definition) => {
|
|
@@ -2412,7 +2427,9 @@ const BUILT_IN_THEME_KEYS = [
|
|
|
2412
2427
|
"shapio",
|
|
2413
2428
|
"classic",
|
|
2414
2429
|
"murdered-out",
|
|
2415
|
-
"
|
|
2430
|
+
"forest",
|
|
2431
|
+
"snowed",
|
|
2432
|
+
"butter"
|
|
2416
2433
|
];
|
|
2417
2434
|
/**
|
|
2418
2435
|
* A token value an extension may use: a hex colour or a colour function whose arguments are numbers, units
|
|
@@ -2525,6 +2542,89 @@ const checkThemeContrast = (tokens, variant) => {
|
|
|
2525
2542
|
return [...THEME_TEXT_PAIRS.map((pair) => measure(pair, 4.5)), ...uiPairs.map((pair) => measure(pair, 3))];
|
|
2526
2543
|
};
|
|
2527
2544
|
//#endregion
|
|
2528
|
-
|
|
2545
|
+
//#region src/seo/definition.ts
|
|
2546
|
+
/**
|
|
2547
|
+
* The built-in SEO component as first created. All fields are public and none has a length limit: the 70 and
|
|
2548
|
+
* 160 character marks are admin-only counters (`SEO_TITLE_SOFT_MAX`), never validation.
|
|
2549
|
+
*/
|
|
2550
|
+
const seoComponentDefinition = () => normalizeDefinition({
|
|
2551
|
+
id: SEO_COMPONENT_ID,
|
|
2552
|
+
kind: "component",
|
|
2553
|
+
apiKey: "seo",
|
|
2554
|
+
label: "SEO",
|
|
2555
|
+
description: "Search and social metadata: title, description, image, canonical URL and indexing.",
|
|
2556
|
+
category: "Built-in",
|
|
2557
|
+
icon: "search",
|
|
2558
|
+
fields: [
|
|
2559
|
+
{
|
|
2560
|
+
id: SEO_FIELD_IDS.title,
|
|
2561
|
+
apiKey: "title",
|
|
2562
|
+
label: "Title",
|
|
2563
|
+
type: "string"
|
|
2564
|
+
},
|
|
2565
|
+
{
|
|
2566
|
+
id: SEO_FIELD_IDS.description,
|
|
2567
|
+
apiKey: "description",
|
|
2568
|
+
label: "Description",
|
|
2569
|
+
type: "text"
|
|
2570
|
+
},
|
|
2571
|
+
{
|
|
2572
|
+
id: SEO_FIELD_IDS.image,
|
|
2573
|
+
apiKey: "image",
|
|
2574
|
+
label: "Social image",
|
|
2575
|
+
type: "media",
|
|
2576
|
+
settings: {
|
|
2577
|
+
multiple: false,
|
|
2578
|
+
allowedKinds: ["image"]
|
|
2579
|
+
}
|
|
2580
|
+
},
|
|
2581
|
+
{
|
|
2582
|
+
id: SEO_FIELD_IDS.canonical,
|
|
2583
|
+
apiKey: "canonical",
|
|
2584
|
+
label: "Canonical URL",
|
|
2585
|
+
type: "url",
|
|
2586
|
+
settings: { protocols: ["https", "http"] }
|
|
2587
|
+
},
|
|
2588
|
+
{
|
|
2589
|
+
id: SEO_FIELD_IDS.noindex,
|
|
2590
|
+
apiKey: "noindex",
|
|
2591
|
+
label: "Hide from search engines",
|
|
2592
|
+
type: "boolean"
|
|
2593
|
+
}
|
|
2594
|
+
],
|
|
2595
|
+
display: { titleFieldId: SEO_FIELD_IDS.title }
|
|
2596
|
+
});
|
|
2597
|
+
//#endregion
|
|
2598
|
+
//#region src/seo/defaults.ts
|
|
2599
|
+
const closed = { additionalProperties: false };
|
|
2600
|
+
/** Media asset IDs are UUIDs. */
|
|
2601
|
+
const ASSET_ID_PATTERN = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
2602
|
+
/** One locale's default texts. Every key is optional: a missing one falls back along the locale chain. */
|
|
2603
|
+
const SeoLocaleDefaultsSchema = Type.Object({
|
|
2604
|
+
siteName: Type.Optional(Type.String({
|
|
2605
|
+
minLength: 1,
|
|
2606
|
+
maxLength: 200
|
|
2607
|
+
})),
|
|
2608
|
+
titleTemplate: Type.Optional(Type.String({
|
|
2609
|
+
minLength: 2,
|
|
2610
|
+
maxLength: 200,
|
|
2611
|
+
pattern: SEO_TITLE_TEMPLATE_PATTERN.source
|
|
2612
|
+
})),
|
|
2613
|
+
description: Type.Optional(Type.String({
|
|
2614
|
+
minLength: 1,
|
|
2615
|
+
maxLength: 1e3
|
|
2616
|
+
}))
|
|
2617
|
+
}, closed);
|
|
2618
|
+
/**
|
|
2619
|
+
* A site's SEO defaults (`sites.seo_defaults`): texts per locale code, the default social image (a public
|
|
2620
|
+
* image asset of the same site) and the Twitter handle for the whole site.
|
|
2621
|
+
*/
|
|
2622
|
+
const SeoDefaultsSchema = Type.Object({
|
|
2623
|
+
locales: Type.Record(Type.String({ pattern: LOCALE_CODE_PATTERN.source }), SeoLocaleDefaultsSchema, { additionalProperties: false }),
|
|
2624
|
+
imageId: Type.Union([Type.String({ pattern: ASSET_ID_PATTERN.source }), Type.Null()]),
|
|
2625
|
+
twitterHandle: Type.Union([Type.String({ pattern: SEO_TWITTER_HANDLE_PATTERN.source }), Type.Null()])
|
|
2626
|
+
}, closed);
|
|
2627
|
+
//#endregion
|
|
2628
|
+
export { API_KEY_PATTERN, BIGINTEGER_PATTERN, BUILT_IN_THEME_KEYS, CANVAS_ELIGIBLE, CHANGE_KINDS, COMPONENT_TYPE_SUFFIXES, CUSTOM_EDITOR_ID_PATTERN, ComponentDefinitionInputSchema, ComponentDisplayInputSchema, DATA_TYPES, DATETIME_PATTERN, DATE_PATTERN, DECIMAL_PATTERN, DEFAULT_EDITORS, DEFAULT_SEO_KEYS, DEFINITION_KINDS, DefinitionInputSchema, EDITOR_CATALOGUE, EMPTY_SEO_DEFAULTS, EditorChoiceInputSchema, EnumValueSchema, FieldInputSchema, INLINE_TITLE_TYPES, LOCALE_CODE_PATTERN, LOCK_FILE_FORMAT_VERSION, LOCK_FILE_PATH, LocaleInputSchema, LockEntrySchema, LockFileError, LockFileSchema, MARK_RULES, MAX_API_KEY_LENGTH, MAX_COMPONENT_DEPTH, MAX_DESCRIPTION_LENGTH, MAX_FALLBACK_CHAIN, MAX_FIELDS_PER_DEFINITION, MAX_LABEL_LENGTH, MAX_RICHTEXT_DEPTH, MEDIA_KINDS, MODEL_KINDS, MODEL_TYPE_SUFFIXES, MUTATION_PREFIXES, ModelDefinitionInputSchema, ModelDisplayInputSchema, NODE_RULES, PLURAL_FALLBACK_SUFFIX, REFERENCE_DATA_TYPES, RELATION_CARDINALITIES, RESERVED_DEFINITION_API_KEYS, RESERVED_FIELD_API_KEYS, RESERVED_QUERY_NAMES, RESERVED_TYPE_NAMES, RICHTEXT_FORMAT, RICHTEXT_FORMAT_VERSION, SAFE_LINK_PATTERN, SCALAR_DATA_TYPES, SCHEMA_KIND_DIRECTORIES, 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, SETTINGS_SCHEMAS, SITES_DIRECTORY, SLUG_PATTERN, SORT_DIRECTIONS, STABLE_ID_PATTERN, STORAGE_FAMILY, STRIP_DEFAULT_COUNT, SchemaValidationError, SeoDefaultsSchema, SeoLocaleDefaultsSchema, TEXT_TITLE_FIELD_TYPES, THEME_BRAND_TOKENS, THEME_COLOUR_PATTERN, THEME_DARK_UI_PAIRS, THEME_KEY_PATTERN, THEME_SEMANTIC_TOKENS, THEME_TEXT_PAIRS, THEME_TOKENS, THEME_UI_PAIRS, THEME_VARIANTS, TIME_PATTERN, TITLE_FIELD_TYPES, UID_PATTERN, UNIQUE_CAPABLE_DATA_TYPES, applyTitleTemplate, assignIds, canonicalJson, checkApiKeySyntax, checkDefaultValue, checkThemeContrast, classifyChange, classifyChanges, classifyLocaleChange, collectionQueryName, contrastRatio, createStableId, decideSync, diffDefinitions, effectiveLayout, effectiveTitleField, embeddedComponentIds, escapeHtml, findDependentModels, findReferencingDefinitions, foldApiKey, generatedNames, hashDefinition, isApiKeySyntaxValid, isCanvasEligible, isComponentDefinition, isCoverEligible, isCustomEditorId, isDataType, isEmptyRichText, isModelDefinition, isSeoField, isStableId, isValidTitleTemplate, issue, listCompatibleEditors, lockCoversSite, lockEntriesForSite, mergePulledLock, normalizeDefinition, parseDefinition, parseLockFile, plainTextToRichText, renderRichTextHtml, renormalizeDefinition, resolveSeo, richTextMediaIds, richTextToPlainText, routeKeyOf, schemaFilePath, scopeDirectory, scopeOfSchemaFilePath, seoComponentDefinition, seoDefaultsForLocale, serializeDefinition, serializeLockFile, sha256, stripFieldsOf, suggestPlural, summarizeChanges, toTypeName, upgradeLockFile, validateDefinition, validateRichText, validateSchema, withDerivedPlural, withSiteCovered };
|
|
2529
2629
|
|
|
2530
2630
|
//# sourceMappingURL=index.js.map
|