@taprootio/site-authoring 0.30.0 → 0.32.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 +87 -12
- package/examples/riverbend-wellness/settings/taproot-styles.json +1 -0
- package/package.json +2 -2
- package/src/api.js +110 -3
- package/src/appearance-contract.js +11 -0
- package/src/block-flow.js +117 -0
- package/src/changelog.json +45 -0
- package/src/cli.js +102 -6
- package/src/constants.js +3 -0
- package/src/content/components.js +28 -15
- package/src/content/external-link.js +77 -0
- package/src/content/free-form-section-registry.json +30 -4
- package/src/content/free-form-sections.js +29 -1
- package/src/content/image-description-document.js +108 -0
- package/src/content/image-description-validation.js +70 -0
- package/src/content/tiptap-prosemirror.ts +85 -27
- package/src/content/validate-document.js +2 -0
- package/src/image-description-contract.js +84 -0
- package/src/navigation-readiness.js +47 -0
- package/src/output.js +8 -0
- package/src/page-metadata.js +10 -10
- package/src/page-structure-checks.js +50 -45
- package/src/presentation-reference.js +9 -0
- package/src/reference-help.js +23 -10
- package/src/setting-reference.js +9 -0
- package/src/settings-catalog.js +1 -0
- package/src/site-check-findings.js +18 -12
- package/src/site-check-rules.json +10 -6
- package/src/typed-pages.js +25 -9
- package/src/verbs/deploy.js +11 -0
- package/src/verbs/index.js +10 -0
- package/src/verbs/media-images.js +67 -0
- package/src/verbs/pages-push.js +2 -1
- package/src/verbs/status.js +19 -5
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { getSiteImageDescription, listSiteImageDescriptions, updateSiteImageDescription, withRefusalGuidance } from "../api.js";
|
|
2
|
+
import { VERB_MEDIA_IMAGES_DESCRIBE, VERB_MEDIA_IMAGES_GET, VERB_MEDIA_IMAGES_LIST } from "../constants.js";
|
|
3
|
+
import { SiteAuthoringError } from "../errors.js";
|
|
4
|
+
import { imageDescriptionOptions, imageListOptions, requireImageId } from "../image-description-contract.js";
|
|
5
|
+
import { serializeResult } from "../output.js";
|
|
6
|
+
import { openSession, successResult, warnIfExternalWritesPaused } from "../session.js";
|
|
7
|
+
import { ApiError } from "../transport.js";
|
|
8
|
+
|
|
9
|
+
export async function mediaImagesList(invocation) {
|
|
10
|
+
const options = imageListOptions(invocation);
|
|
11
|
+
const { client, siteId, onProgress } = await openSession(invocation);
|
|
12
|
+
const images = await withRefusalGuidance(onProgress, VERB_MEDIA_IMAGES_LIST, () =>
|
|
13
|
+
listSiteImageDescriptions(client, siteId, options));
|
|
14
|
+
const result = successResult(VERB_MEDIA_IMAGES_LIST, siteId, {
|
|
15
|
+
images: { ...images, count: images.items.length, missingDescription: options.missingDescription },
|
|
16
|
+
});
|
|
17
|
+
try {
|
|
18
|
+
serializeResult(result);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
if (!(error instanceof SiteAuthoringError) || error.code !== "output.too_large") throw error;
|
|
21
|
+
throw new SiteAuthoringError("media.image_page_too_large",
|
|
22
|
+
"This page exceeds the output bound. Repeat the same cursor with a smaller --page-size; no items were omitted.",
|
|
23
|
+
{ field: "pageSize" });
|
|
24
|
+
}
|
|
25
|
+
onProgress(`${images.items.length} image(s) returned${images.nextPageToken ? "; use images.nextPageToken for the next page" : ""}.`);
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function mediaImagesGet(invocation) {
|
|
30
|
+
const imageId = requireImageId(invocation.imageId);
|
|
31
|
+
const { client, siteId, onProgress } = await openSession(invocation);
|
|
32
|
+
const image = await withRefusalGuidance(onProgress, VERB_MEDIA_IMAGES_GET, () =>
|
|
33
|
+
getSiteImageDescription(client, siteId, imageId));
|
|
34
|
+
onProgress(`Read image ${image.imageId}, description revision ${image.descriptionRevision}.`);
|
|
35
|
+
return successResult(VERB_MEDIA_IMAGES_GET, siteId, { image });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function mediaImagesDescribe(invocation) {
|
|
39
|
+
const imageId = requireImageId(invocation.imageId);
|
|
40
|
+
const body = imageDescriptionOptions(invocation);
|
|
41
|
+
const session = await openSession(invocation);
|
|
42
|
+
warnIfExternalWritesPaused(session, VERB_MEDIA_IMAGES_DESCRIBE);
|
|
43
|
+
const { client, siteId, onProgress } = session;
|
|
44
|
+
const image = await withRefusalGuidance(onProgress, VERB_MEDIA_IMAGES_DESCRIBE, async () => {
|
|
45
|
+
try {
|
|
46
|
+
return await updateSiteImageDescription(client, siteId, imageId, body);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (error instanceof ApiError && error.hasField("ExpectedRevision")) {
|
|
49
|
+
throw new SiteAuthoringError("media.image_description_conflict",
|
|
50
|
+
"The description changed. Read it with 'media images get', reconcile the text, and supply that revision.",
|
|
51
|
+
{ field: "expectedRevision", status: error.status });
|
|
52
|
+
}
|
|
53
|
+
if (error instanceof ApiError && error.hasField("OnlyIfMissing")) {
|
|
54
|
+
throw new SiteAuthoringError("media.image_description_exists", "This image already has a default description; nothing changed.",
|
|
55
|
+
{ field: "onlyIfMissing", status: error.status });
|
|
56
|
+
}
|
|
57
|
+
if (error instanceof ApiError && error.hasField("DefaultDescription")) {
|
|
58
|
+
throw new SiteAuthoringError("media.image_description_invalid",
|
|
59
|
+
error.descriptionFor("DefaultDescription") ?? "Taproot refused the default description.",
|
|
60
|
+
{ field: "defaultDescription", status: error.status });
|
|
61
|
+
}
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
onProgress(`Saved image ${image.imageId}, description revision ${image.descriptionRevision}. Deploy to update published usages.`);
|
|
66
|
+
return successResult(VERB_MEDIA_IMAGES_DESCRIBE, siteId, { image });
|
|
67
|
+
}
|
package/src/verbs/pages-push.js
CHANGED
|
@@ -1548,7 +1548,8 @@ export async function planPages({
|
|
|
1548
1548
|
pagePath,
|
|
1549
1549
|
title: sentTitle,
|
|
1550
1550
|
// Only the owner's own description is warned about for length: the derived one is not theirs to shorten.
|
|
1551
|
-
|
|
1551
|
+
declaredDescription: generated ? document_.data.customDescription : declaredDescription,
|
|
1552
|
+
metadataDescriptionKnown: generated || typeof declaredDescription === "string",
|
|
1552
1553
|
contentKey,
|
|
1553
1554
|
unchanged,
|
|
1554
1555
|
description: sentDescription,
|
package/src/verbs/status.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describeNavigationReadiness, reportNavigationReadiness } from "../navigation-readiness.js";
|
|
1
2
|
import {
|
|
2
3
|
getDeploySelection,
|
|
3
4
|
getPublishingReadiness,
|
|
@@ -162,7 +163,7 @@ export async function status(invocation) {
|
|
|
162
163
|
if (!presentationOnly) {
|
|
163
164
|
onProgress("Reading image processing state.");
|
|
164
165
|
({ images, summary, truncated } = await listSiteImages(client, siteId));
|
|
165
|
-
onProgress("Reading
|
|
166
|
+
onProgress("Reading the stored deployment health report.");
|
|
166
167
|
health = await getSiteHealth(client, siteId);
|
|
167
168
|
}
|
|
168
169
|
const reportedFindings = boundedList(health.findings, MAXIMUM_HEALTH_FINDINGS);
|
|
@@ -184,10 +185,14 @@ export async function status(invocation) {
|
|
|
184
185
|
const reportedDeployments = boundedList(deployments, MAXIMUM_DEPLOYMENTS);
|
|
185
186
|
const blockers = boundedList(readiness.blockers, MAXIMUM_BLOCKERS);
|
|
186
187
|
|
|
188
|
+
onProgress(describeNavigationReadiness(readiness.navigationReadiness));
|
|
189
|
+
const assessed = ["complete", "incomplete"].includes(health.status) && Boolean(health.deploymentId);
|
|
187
190
|
if (!presentationOnly) {
|
|
188
|
-
onProgress(
|
|
189
|
-
`Site health: ${health.errorCount} problem(s) and ${health.warningCount} warning(s)
|
|
190
|
-
|
|
191
|
+
onProgress(assessed
|
|
192
|
+
? `Site health (${health.environment}, checked ${health.checkedAt}): ${health.errorCount} problem(s) and ${health.warningCount} warning(s). Unpublished changes are outside this report.`
|
|
193
|
+
: health.status === "not_checked"
|
|
194
|
+
? "Site health: not checked yet. Deploy the site to create a report."
|
|
195
|
+
: "Site health: no complete supported deployment assessment is available.");
|
|
191
196
|
}
|
|
192
197
|
|
|
193
198
|
return successResult(VERB_STATUS, siteId, {
|
|
@@ -196,6 +201,7 @@ export async function status(invocation) {
|
|
|
196
201
|
...(presentationOnly ? { authoringSurface: SURFACE_DOCS_PRESENTATION } : {}),
|
|
197
202
|
readiness: {
|
|
198
203
|
state: readiness.state,
|
|
204
|
+
navigationReadiness: reportNavigationReadiness(readiness.navigationReadiness),
|
|
199
205
|
approvedPageCount: readiness.approvedPageCount,
|
|
200
206
|
blockedPageCount: readiness.blockedPageCount,
|
|
201
207
|
hasCandidateChanges: readiness.hasCandidateChanges,
|
|
@@ -227,12 +233,20 @@ export async function status(invocation) {
|
|
|
227
233
|
...(truncated ? { listTruncated: true } : {}),
|
|
228
234
|
},
|
|
229
235
|
siteHealth: presentationOnly ? { covered: false, reason: DOCS_SITE_NOT_COVERED_NOTE } : {
|
|
230
|
-
covered:
|
|
236
|
+
covered: assessed,
|
|
237
|
+
status: health.status ?? "unknown",
|
|
238
|
+
...(assessed ? {
|
|
239
|
+
deploymentId: health.deploymentId, outputReleaseId: health.outputReleaseId,
|
|
240
|
+
inputHash: health.inputHash, checkedAt: health.checkedAt, ruleVersion: health.ruleVersion,
|
|
241
|
+
coverage: health.coverage, assessedPages: health.assessedPageCount, environment: health.environment,
|
|
242
|
+
unpublishedChangesAssessed: false,
|
|
231
243
|
errors: health.errorCount,
|
|
232
244
|
warnings: health.warningCount,
|
|
233
245
|
pages: health.pageCount,
|
|
234
246
|
findings: reportedFindings.items,
|
|
247
|
+
imageFindings: health.images,
|
|
235
248
|
...(reportedFindings.truncated || health.truncated ? { findingsTruncated: true } : {}),
|
|
249
|
+
} : { reason: health.status === "not_checked" ? "Not checked yet; deploy the site to create a report." : "A complete supported deployment assessment is unavailable." }),
|
|
236
250
|
},
|
|
237
251
|
});
|
|
238
252
|
});
|