@taprootio/site-authoring 0.11.0 → 0.11.1
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taprootio/site-authoring",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Taproot site authoring CLI: sign in once in the browser, then pull, validate, push, preview, approve, and deploy a site from the terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "ISC",
|
package/src/constants.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import packageMetadata from "../package.json" with { type: "json" };
|
|
2
|
+
|
|
1
3
|
export const CLI_NAME = "@taprootio/site-authoring";
|
|
2
|
-
export const CLI_VERSION =
|
|
4
|
+
export const CLI_VERSION = packageMetadata.version;
|
|
3
5
|
export const CLI_BINARY_NAME = "taproot-site";
|
|
4
6
|
export const RESULT_SCHEMA_VERSION = 1;
|
|
5
7
|
export const CONFIG_FILE_NAME = "taproot-site.json";
|
|
@@ -10,6 +10,17 @@
|
|
|
10
10
|
import freeFormSectionRegistry from "./free-form-section-registry.json" with { type: "json" };
|
|
11
11
|
|
|
12
12
|
export const TIPTAP_SITE_DEFAULT = "site-default";
|
|
13
|
+
export const DEFAULT_TIPTAP_IMAGE_MAX_IMAGES_PER_ROW = 2;
|
|
14
|
+
export const TIPTAP_IMAGE_MAX_IMAGES_PER_ROW_OPTIONS = [1, 2, 3] as const;
|
|
15
|
+
export const TIPTAP_IMAGE_NARROW_CONTENT_REM = 40;
|
|
16
|
+
|
|
17
|
+
export function normalizeTiptapImageMaxImagesPerRow(value: unknown): number {
|
|
18
|
+
const count = Number(value);
|
|
19
|
+
return TIPTAP_IMAGE_MAX_IMAGES_PER_ROW_OPTIONS.some(option => option === count)
|
|
20
|
+
? count
|
|
21
|
+
: DEFAULT_TIPTAP_IMAGE_MAX_IMAGES_PER_ROW;
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
export const DEFAULT_TIPTAP_IMAGE_MAX_HEIGHT_VH = 60;
|
|
14
25
|
export const TIPTAP_IMAGE_MAX_HEIGHT_OPTIONS = [45, 60, 75, 90] as const;
|
|
15
26
|
const SECTION_CONTEXT_PATTERN = new RegExp(
|
|
@@ -64,6 +75,7 @@ export interface RenderProseMirrorOptions {
|
|
|
64
75
|
/** Normalize free-form root flow into full-bleed Espalier sections. */
|
|
65
76
|
freeFormSections?: boolean;
|
|
66
77
|
imageDefaults?: {
|
|
78
|
+
maxImagesPerRow?: number | null;
|
|
67
79
|
placement?: TiptapImagePresentationPlacement | string | null;
|
|
68
80
|
/** The page shell emits this default once so rich-text formats inherit it. */
|
|
69
81
|
maxHeightVh?: TiptapImageMaxHeightVh | number | null;
|
|
@@ -71,7 +83,10 @@ export interface RenderProseMirrorOptions {
|
|
|
71
83
|
/** Generator-only render hooks for structured nodes that need page context. */
|
|
72
84
|
nodeRenderers?: {
|
|
73
85
|
componentBlock?: (node: ProseMirrorNode) => string | undefined;
|
|
74
|
-
taprootImage?: (
|
|
86
|
+
taprootImage?: (
|
|
87
|
+
node: ProseMirrorNode,
|
|
88
|
+
context: { groupColumns?: number; fullWidth: boolean },
|
|
89
|
+
) => string | undefined;
|
|
75
90
|
/** Emits an adopted fragment's canonical bytes; without it the node renders nothing. */
|
|
76
91
|
integrationFragment?: (node: ProseMirrorNode) => string | undefined;
|
|
77
92
|
};
|
|
@@ -151,14 +166,26 @@ function isTextBlock(type: string): boolean {
|
|
|
151
166
|
}
|
|
152
167
|
|
|
153
168
|
type RenderPlacement = "root" | "section" | "nested";
|
|
169
|
+
type RenderOptionsWithLayout = RenderProseMirrorOptions & { fullWidthImages?: boolean };
|
|
154
170
|
|
|
155
171
|
function renderNodes(
|
|
156
172
|
nodes: readonly ProseMirrorNode[],
|
|
157
|
-
options:
|
|
173
|
+
options: RenderOptionsWithLayout,
|
|
158
174
|
placement: RenderPlacement,
|
|
159
175
|
): string {
|
|
160
|
-
|
|
161
|
-
|
|
176
|
+
let imageRunEnd = 0;
|
|
177
|
+
let groupColumns: number | undefined;
|
|
178
|
+
return nodes.map((node, index) => {
|
|
179
|
+
const isImage = node.type === "taprootImage";
|
|
180
|
+
if (isImage && index >= imageRunEnd) {
|
|
181
|
+
imageRunEnd = index + 1;
|
|
182
|
+
while (imageRunEnd < nodes.length && nodes[imageRunEnd].type === "taprootImage") imageRunEnd++;
|
|
183
|
+
const count = imageRunEnd - index;
|
|
184
|
+
groupColumns = count > 1
|
|
185
|
+
? Math.min(count, normalizeTiptapImageMaxImagesPerRow(options.imageDefaults?.maxImagesPerRow))
|
|
186
|
+
: undefined;
|
|
187
|
+
}
|
|
188
|
+
const html = renderNode(node, options, placement, false, isImage ? groupColumns : undefined);
|
|
162
189
|
options.onRenderedNode?.(node, html);
|
|
163
190
|
return html;
|
|
164
191
|
}).join("");
|
|
@@ -217,9 +244,10 @@ function isRootBandComponent(node: ProseMirrorNode): boolean {
|
|
|
217
244
|
|
|
218
245
|
function renderNode(
|
|
219
246
|
node: ProseMirrorNode,
|
|
220
|
-
options:
|
|
247
|
+
options: RenderOptionsWithLayout,
|
|
221
248
|
placement: RenderPlacement,
|
|
222
249
|
compactFollowing = false,
|
|
250
|
+
groupColumns?: number,
|
|
223
251
|
): string {
|
|
224
252
|
switch (node.type) {
|
|
225
253
|
case "doc":
|
|
@@ -263,7 +291,8 @@ function renderNode(
|
|
|
263
291
|
case "table":
|
|
264
292
|
return placement === "root" || placement === "section" ? renderTable(node, options) : "";
|
|
265
293
|
case "taprootImage":
|
|
266
|
-
return options.nodeRenderers?.taprootImage?.(node
|
|
294
|
+
return options.nodeRenderers?.taprootImage?.(node, { groupColumns, fullWidth: options.fullWidthImages === true })
|
|
295
|
+
?? renderTaprootImage(node, options);
|
|
267
296
|
case "inlineFacts":
|
|
268
297
|
return renderInlineFacts(node, options, placement);
|
|
269
298
|
case "componentBlock":
|
|
@@ -737,7 +766,7 @@ function renderSection(
|
|
|
737
766
|
const content = renderElement(
|
|
738
767
|
"div",
|
|
739
768
|
{ "data-section-content": true },
|
|
740
|
-
renderNodes(nodes, options, contentPlacement),
|
|
769
|
+
renderNodes(nodes, { ...options, fullWidthImages: contentPadding === "none" }, contentPlacement),
|
|
741
770
|
);
|
|
742
771
|
const surfaced = surface === "none"
|
|
743
772
|
? content
|
|
@@ -1181,6 +1210,7 @@ function resolveImagePresentation(
|
|
|
1181
1210
|
if (maxHeightOverride) styleParts.push(`--taproot-article-image-max-height: ${maxHeightOverride}`);
|
|
1182
1211
|
if (borderWidthOverride) styleParts.push(`--esp-image-border: ${imageBorderValue(borderWidthOverride)}`);
|
|
1183
1212
|
return {
|
|
1213
|
+
"data-tiptap-image": normalizeTiptapImageMaxImagesPerRow(defaults?.maxImagesPerRow),
|
|
1184
1214
|
// The page shell owns the inherited site default so HTML and structured
|
|
1185
1215
|
// rich text share it. Serialize only an explicit legacy choice; this
|
|
1186
1216
|
// includes 60vh when it intentionally overrides a taller site default.
|
package/src/settings-catalog.js
CHANGED
|
@@ -125,6 +125,7 @@ export const SETTINGS_GROUPS = Object.freeze([
|
|
|
125
125
|
// the same as the site behaves.
|
|
126
126
|
{ name: "hideLightboxComments", wireType: "boolean" },
|
|
127
127
|
{ name: "tiptapImageMaxHeightVh", wireType: "int" },
|
|
128
|
+
{ name: "tiptapImageMaxImagesPerRow", wireType: "int" },
|
|
128
129
|
{ name: "tiptapImageBorderWidth", wireType: "int" },
|
|
129
130
|
{ name: "albumBorderWidth", wireType: "int" },
|
|
130
131
|
{ name: "albumMaxImagesPerRow", wireType: "int" },
|