@taprootio/site-authoring 0.12.5 → 0.12.7
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/README.md +13 -3
- package/package.json +2 -2
- package/src/capabilities.js +1 -1
- package/src/cli.js +50 -2
- package/src/constants.js +3 -0
- package/src/content/components.js +21 -0
- package/src/content/free-form-section-registry.json +6 -1
- package/src/delivery-check.js +2 -11
- package/src/field-schema.json +217 -0
- package/src/field-validation.js +715 -0
- package/src/fixture-contract.js +1 -1
- package/src/fixture-init.js +15 -0
- package/src/forms-api.js +192 -0
- package/src/forms-contract.js +274 -0
- package/src/forms-workspace.js +100 -0
- package/src/reference-help.js +154 -6
- package/src/settings-catalog.js +3 -0
- package/src/verbs/delivery-check.js +0 -7
- package/src/verbs/forms-pull.js +67 -0
- package/src/verbs/forms-push.js +227 -0
- package/src/verbs/forms-validate.js +36 -0
- package/src/verbs/index.js +11 -0
- package/src/verbs/pull.js +8 -0
- package/src/verbs/validate.js +57 -0
package/src/verbs/validate.js
CHANGED
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
} from "../fixture-contract.js";
|
|
16
16
|
import { initializeFixture } from "../fixture-init.js";
|
|
17
17
|
import { appearanceManifestEntry, FOOTER_SETTINGS_FILE, footerManifestEntry } from "../footer-workspace.js";
|
|
18
|
+
import { readWorkspaceForms } from "../forms-workspace.js";
|
|
19
|
+
import { FORMS_DIRECTORY } from "../forms-contract.js";
|
|
18
20
|
import {
|
|
19
21
|
isRedirectMapRevision,
|
|
20
22
|
normalizeRedirectPath,
|
|
@@ -405,6 +407,57 @@ function headerWidthHints(headerWidth, rootBandPages) {
|
|
|
405
407
|
}];
|
|
406
408
|
}
|
|
407
409
|
|
|
410
|
+
/**
|
|
411
|
+
* The fixture's forms, when it carries any. The manifest binding and the files
|
|
412
|
+
* must name the same keys: a form file the manifest does not mention would be
|
|
413
|
+
* validated by no one, and a key with no file would be a baseline for nothing.
|
|
414
|
+
* Returns undefined for a fixture with no forms.
|
|
415
|
+
*/
|
|
416
|
+
async function validateFixtureForms(fixtureRoot, bound, onProgress) {
|
|
417
|
+
const files = await readWorkspaceForms(fixtureRoot);
|
|
418
|
+
if (bound === undefined) {
|
|
419
|
+
if (files.length > 0) {
|
|
420
|
+
fail(
|
|
421
|
+
"fixture.forms_unbound",
|
|
422
|
+
"The fixture carries form files but its manifest does not bind them in 'forms'.",
|
|
423
|
+
"forms",
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
return undefined;
|
|
427
|
+
}
|
|
428
|
+
const items = isPlainObject(bound) && isPlainObject(bound.items) ? bound.items : undefined;
|
|
429
|
+
const keys = items === undefined ? [] : Object.keys(items).sort();
|
|
430
|
+
if (
|
|
431
|
+
items === undefined
|
|
432
|
+
|| Object.keys(bound).length !== 1
|
|
433
|
+
|| keys.length === 0
|
|
434
|
+
|| keys.some((key) =>
|
|
435
|
+
!isPlainObject(items[key])
|
|
436
|
+
|| Object.keys(items[key]).sort().join() !== "id,version"
|
|
437
|
+
|| !isCanonicalUuid(items[key].id)
|
|
438
|
+
|| !Number.isSafeInteger(items[key].version)
|
|
439
|
+
|| items[key].version < 1
|
|
440
|
+
)
|
|
441
|
+
) {
|
|
442
|
+
fail(
|
|
443
|
+
"fixture.forms_invalid",
|
|
444
|
+
"The fixture manifest's 'forms' must be { items: { <key>: { id, version } } } with at least one form, "
|
|
445
|
+
+ "a canonical UUID id, and a positive version.",
|
|
446
|
+
"forms",
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
const fileKeys = files.map((form) => form.key);
|
|
450
|
+
if (fileKeys.join() !== keys.join()) {
|
|
451
|
+
fail(
|
|
452
|
+
"fixture.forms_mismatch",
|
|
453
|
+
`The fixture manifest binds forms [${keys.join(", ")}] but ${FORMS_DIRECTORY}/ holds [${fileKeys.join(", ")}].`,
|
|
454
|
+
"forms",
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
onProgress(`Validated ${files.length} form file${files.length === 1 ? "" : "s"} against the shared field schema.`);
|
|
458
|
+
return files;
|
|
459
|
+
}
|
|
460
|
+
|
|
408
461
|
export async function validateFixture(invocation = {}) {
|
|
409
462
|
if (invocation.init) return await initializeFixture(invocation, validateFixture);
|
|
410
463
|
const onProgress = typeof invocation.onProgress === "function" ? invocation.onProgress : () => {};
|
|
@@ -597,6 +650,8 @@ export async function validateFixture(invocation = {}) {
|
|
|
597
650
|
},
|
|
598
651
|
);
|
|
599
652
|
|
|
653
|
+
const forms = await validateFixtureForms(fixtureRoot, manifest.forms, onProgress);
|
|
654
|
+
|
|
600
655
|
const reportedPages = boundedList(validatedPages, MAXIMUM_REPORTED);
|
|
601
656
|
onProgress(
|
|
602
657
|
`Validated ${validatedPages.length} page(s), ${navigation.items} navigation item(s), two themes, appearance, and footer without credentials or mutation.`,
|
|
@@ -620,6 +675,7 @@ export async function validateFixture(invocation = {}) {
|
|
|
620
675
|
entries: redirects.entries.length,
|
|
621
676
|
gone: redirects.entries.filter((entry) => entry.kind === REDIRECT_KIND_GONE).length,
|
|
622
677
|
},
|
|
678
|
+
...(forms === undefined ? {} : { forms: { count: forms.length } }),
|
|
623
679
|
themes: 2,
|
|
624
680
|
appearanceSettings: presentation.scalarOperations.length,
|
|
625
681
|
footer: true,
|
|
@@ -636,6 +692,7 @@ export async function validateFixture(invocation = {}) {
|
|
|
636
692
|
"navigation shape and local page-resource references",
|
|
637
693
|
"redirect-map shape, normalization, chains, loops, and fixture-local path occupancy",
|
|
638
694
|
"complete theme, appearance, header, brand, and footer semantics",
|
|
695
|
+
"form files, when the manifest binds any, against the shared field schema",
|
|
639
696
|
"fixture-local image identities and reserved delivery origins",
|
|
640
697
|
],
|
|
641
698
|
doesNotProve: [
|