@taprootio/site-authoring 0.6.2 → 0.7.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/README.md +103 -10
- package/package.json +2 -2
- package/src/api.js +281 -61
- package/src/cli.js +73 -26
- package/src/constants.js +2 -1
- package/src/content/components.js +7 -33
- package/src/content/free-form-section-registry.json +4 -2
- package/src/content/inline-facts.js +6 -0
- package/src/content/tiptap-prosemirror.ts +22 -16
- package/src/content/vocabulary.js +6 -2
- package/src/errors.js +27 -0
- package/src/fixture-contract.js +4 -4
- package/src/fixture-init.js +231 -0
- package/src/output.js +12 -2
- package/src/reference-help.js +139 -89
- package/src/settings-catalog.js +1 -0
- package/src/staging-check.js +145 -0
- package/src/theme-validation.js +31 -12
- package/src/transport.js +12 -3
- package/src/verbs/deploy.js +35 -101
- package/src/verbs/index.js +4 -1
- package/src/verbs/pull.js +22 -5
- package/src/verbs/redirects-check.js +18 -0
- package/src/verbs/status.js +34 -17
- package/src/verbs/theme-push.js +44 -9
- package/src/verbs/validate.js +51 -12
package/src/verbs/validate.js
CHANGED
|
@@ -2,8 +2,8 @@ import { lstat, realpath } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
4
|
import { NAVIGATION_MAXIMUM_DEPTH, TEMPLATE_TYPE_FREE_FORM } from "../api.js";
|
|
5
|
-
import { freeFormRootPresentation, sharedThemeContextNames } from "../content/free-form-sections.js";
|
|
6
5
|
import { VERB_VALIDATE } from "../constants.js";
|
|
6
|
+
import { freeFormRootPresentation, sharedThemeContextNames } from "../content/free-form-sections.js";
|
|
7
7
|
import { isCanonicalUuid, SiteAuthoringError } from "../errors.js";
|
|
8
8
|
import {
|
|
9
9
|
FIXTURE_CONTRACT_VERSION,
|
|
@@ -13,33 +13,34 @@ import {
|
|
|
13
13
|
FIXTURE_METADATA_FIELDS,
|
|
14
14
|
FIXTURE_ROOT_FIELDS,
|
|
15
15
|
} from "../fixture-contract.js";
|
|
16
|
-
import {
|
|
16
|
+
import { initializeFixture } from "../fixture-init.js";
|
|
17
|
+
import { appearanceManifestEntry, FOOTER_SETTINGS_FILE, footerManifestEntry } from "../footer-workspace.js";
|
|
17
18
|
import {
|
|
18
19
|
isRedirectMapRevision,
|
|
20
|
+
normalizeRedirectPath,
|
|
19
21
|
REDIRECT_KIND_GONE,
|
|
20
22
|
REDIRECTS_FILE_NAME,
|
|
21
23
|
validateRedirectsDocument,
|
|
22
|
-
normalizeRedirectPath,
|
|
23
24
|
} from "../redirects-contract.js";
|
|
24
25
|
import { boundedList, successResult } from "../session.js";
|
|
25
26
|
import { SETTINGS_GROUPS, SETTINGS_TYPE_SITE_PUBLISHING_PREFERENCES } from "../settings-catalog.js";
|
|
26
|
-
import { validateFooterWorkspaceDocument } from "./footer-push.js";
|
|
27
|
-
import { validateNavigationWorkspaceDocument } from "./nav-push.js";
|
|
28
|
-
import { validateWorkspacePageDocument, validateWorkspacePageSource } from "./pages-push.js";
|
|
29
|
-
import { validateThemeWorkspace } from "./theme-push.js";
|
|
30
27
|
import {
|
|
31
28
|
MANIFEST_VERSION,
|
|
32
29
|
NAVIGATION_FILE_NAME,
|
|
33
30
|
normalizePagePath,
|
|
34
31
|
PAGE_SOURCE_EXTENSIONS,
|
|
35
32
|
PAGE_WORKSPACE_MODE_EDITABLE,
|
|
36
|
-
pageSourceFormat,
|
|
37
33
|
PAGES_DIRECTORY,
|
|
34
|
+
pageSourceFormat,
|
|
38
35
|
readWorkspaceJson,
|
|
39
36
|
SETTINGS_DIRECTORY,
|
|
40
37
|
walkWorkspaceFiles,
|
|
41
38
|
WORKSPACE_LIMITS,
|
|
42
39
|
} from "../workspace.js";
|
|
40
|
+
import { validateFooterWorkspaceDocument } from "./footer-push.js";
|
|
41
|
+
import { validateNavigationWorkspaceDocument } from "./nav-push.js";
|
|
42
|
+
import { validateWorkspacePageDocument, validateWorkspacePageSource } from "./pages-push.js";
|
|
43
|
+
import { validateThemeWorkspace } from "./theme-push.js";
|
|
43
44
|
|
|
44
45
|
const MAXIMUM_REPORTED = 200;
|
|
45
46
|
const FIXTURE_ROOT_KEYS = new Set(FIXTURE_ROOT_FIELDS);
|
|
@@ -72,7 +73,11 @@ async function resolveFixtureRoot(cwd, fixturePath) {
|
|
|
72
73
|
);
|
|
73
74
|
}
|
|
74
75
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
75
|
-
fail(
|
|
76
|
+
fail(
|
|
77
|
+
"fixture.path_invalid",
|
|
78
|
+
"The selected authoring fixture must be a real directory, not a link or file.",
|
|
79
|
+
"fixturePath",
|
|
80
|
+
);
|
|
76
81
|
}
|
|
77
82
|
try {
|
|
78
83
|
return await realpath(candidate);
|
|
@@ -87,7 +92,11 @@ async function resolveFixtureRoot(cwd, fixturePath) {
|
|
|
87
92
|
|
|
88
93
|
function validateFixtureManifest(manifest) {
|
|
89
94
|
if (!isPlainObject(manifest)) {
|
|
90
|
-
fail(
|
|
95
|
+
fail(
|
|
96
|
+
"fixture.manifest_invalid",
|
|
97
|
+
`${FIXTURE_MANIFEST_FILE_NAME} must contain one JSON object.`,
|
|
98
|
+
FIXTURE_MANIFEST_FILE_NAME,
|
|
99
|
+
);
|
|
91
100
|
}
|
|
92
101
|
const unknownRoot = Object.keys(manifest).filter((key) => !FIXTURE_ROOT_KEYS.has(key)).sort();
|
|
93
102
|
if (unknownRoot.length > 0) {
|
|
@@ -291,7 +300,9 @@ function validateFixtureManifest(manifest) {
|
|
|
291
300
|
`${field}.sourceFormat`,
|
|
292
301
|
);
|
|
293
302
|
}
|
|
294
|
-
if (
|
|
303
|
+
if (
|
|
304
|
+
pageIds.has(entry.pageId) || resourceIds.has(entry.resourceId) || files.has(entry.file) || paths.has(pagePath)
|
|
305
|
+
) {
|
|
295
306
|
fail(
|
|
296
307
|
"fixture.page_duplicate",
|
|
297
308
|
`${field} duplicates a pageId, resourceId, source file, or page path.`,
|
|
@@ -394,6 +405,7 @@ function headerWidthHints(headerWidth, rootBandPages) {
|
|
|
394
405
|
}
|
|
395
406
|
|
|
396
407
|
export async function validateFixture(invocation = {}) {
|
|
408
|
+
if (invocation.init) return await initializeFixture(invocation, validateFixture);
|
|
397
409
|
const onProgress = typeof invocation.onProgress === "function" ? invocation.onProgress : () => {};
|
|
398
410
|
const fixtureRoot = await resolveFixtureRoot(invocation.cwd ?? process.cwd(), invocation.fixturePath);
|
|
399
411
|
onProgress(`Reading ${FIXTURE_MANIFEST_FILE_NAME}.`);
|
|
@@ -412,6 +424,29 @@ export async function validateFixture(invocation = {}) {
|
|
|
412
424
|
|
|
413
425
|
onProgress("Validating the complete light/dark theme, appearance, header, brand, and footer colors.");
|
|
414
426
|
const presentation = await validateThemeWorkspace(fixtureRoot, manifest.siteId, imageIds, settingsEntityIds);
|
|
427
|
+
const expectedAppearance = appearanceManifestEntry({
|
|
428
|
+
SETTING_TYPE_TAPROOT_STYLES: presentation.style,
|
|
429
|
+
SETTING_TYPE_BRAND: presentation.brand,
|
|
430
|
+
SETTING_TYPE_SITE_HEADER: presentation.header,
|
|
431
|
+
});
|
|
432
|
+
if (manifest.appearance !== undefined && JSON.stringify(manifest.appearance) !== JSON.stringify(expectedAppearance)) {
|
|
433
|
+
fail(
|
|
434
|
+
"fixture.appearance_invalid",
|
|
435
|
+
"The fixture appearance metadata must match its settings image identities.",
|
|
436
|
+
"appearance",
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
if (manifest.footer !== undefined) {
|
|
440
|
+
const expectedFooter = footerManifestEntry(presentation.publishing.footerSettings);
|
|
441
|
+
if (
|
|
442
|
+
!isPlainObject(manifest.footer) || Object.keys(manifest.footer).length !== Object.keys(expectedFooter).length
|
|
443
|
+
|| Object.entries(expectedFooter).some(([key, value]) =>
|
|
444
|
+
JSON.stringify(manifest.footer[key]) !== JSON.stringify(value)
|
|
445
|
+
)
|
|
446
|
+
) {
|
|
447
|
+
fail("fixture.footer_invalid", "The fixture footer metadata must match its footer document.", "footer");
|
|
448
|
+
}
|
|
449
|
+
}
|
|
415
450
|
for (const warning of presentation.themes.warnings) onProgress(`Espalier warning: ${warning}`);
|
|
416
451
|
const sharedContexts = sharedThemeContextNames(
|
|
417
452
|
presentation.style.lightTheme,
|
|
@@ -427,7 +462,11 @@ export async function validateFixture(invocation = {}) {
|
|
|
427
462
|
}
|
|
428
463
|
const untracked = pageFiles.find((file) => !declaredFiles.has(file));
|
|
429
464
|
if (untracked !== undefined) {
|
|
430
|
-
fail(
|
|
465
|
+
fail(
|
|
466
|
+
"fixture.page_untracked",
|
|
467
|
+
`Page source '${untracked}' is not bound by ${FIXTURE_MANIFEST_FILE_NAME}.`,
|
|
468
|
+
untracked,
|
|
469
|
+
);
|
|
431
470
|
}
|
|
432
471
|
const validatedPages = [];
|
|
433
472
|
const rootBandPages = [];
|