@phtngyn/cms 0.1.0-beta.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.
Files changed (120) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +90 -0
  3. package/dist/studio/assets/ActivityEntryRow-D--fRvWI.js +1 -0
  4. package/dist/studio/assets/ActivityView-D-XBBUHb.js +1 -0
  5. package/dist/studio/assets/CreateDocumentDialog-CH8UH1QM.js +1 -0
  6. package/dist/studio/assets/DocumentsView-CxRpmAxt.js +34 -0
  7. package/dist/studio/assets/DropdownMenu-BSb1l7fr.js +1 -0
  8. package/dist/studio/assets/Input-DVao38h7.js +3 -0
  9. package/dist/studio/assets/MediaView-BHrPIjxB.js +1 -0
  10. package/dist/studio/assets/Modal-VNrXGa5C.js +1 -0
  11. package/dist/studio/assets/OverviewView-DfP6-mLZ.js +1 -0
  12. package/dist/studio/assets/Select-BJZIs9sY.js +1 -0
  13. package/dist/studio/assets/SettingsView-CerHe-ua.js +1 -0
  14. package/dist/studio/assets/Skeleton-CWJNi3nS.js +1 -0
  15. package/dist/studio/assets/StudioPageHeader-DP9HDAF2.js +1 -0
  16. package/dist/studio/assets/UsersView-cP3REkH2.js +1 -0
  17. package/dist/studio/assets/collaboration-BLnCzfvV.js +4 -0
  18. package/dist/studio/assets/context-dY4fNbn3.js +1 -0
  19. package/dist/studio/assets/editor-CE07wW83.js +137 -0
  20. package/dist/studio/assets/gateway-BAyQgCse.js +10 -0
  21. package/dist/studio/assets/index-CjoaPLhZ.js +28 -0
  22. package/dist/studio/assets/index-s2rPqCmP.css +2 -0
  23. package/dist/studio/assets/render-BkxbK2St.js +83 -0
  24. package/dist/studio/assets/rolldown-runtime-DK3Fl9T5.js +1 -0
  25. package/dist/studio/assets/useMediaLibrary-D7qR7aBf.js +1 -0
  26. package/dist/studio/index.html +76 -0
  27. package/package.json +75 -0
  28. package/src/Authoring.d.ts +46 -0
  29. package/src/Authoring.js +1 -0
  30. package/src/AuthoringSchema-BQ5kbhVB.js +926 -0
  31. package/src/AuthoringSchema-BQ5kbhVB.js.map +1 -0
  32. package/src/Configuration-BGYFD2N1.js +150 -0
  33. package/src/Configuration-BGYFD2N1.js.map +1 -0
  34. package/src/Configuration.d.ts +44 -0
  35. package/src/Configuration.js +9 -0
  36. package/src/Configuration.js.map +1 -0
  37. package/src/DocumentEngine-Da0kWotL.js +851 -0
  38. package/src/DocumentEngine-Da0kWotL.js.map +1 -0
  39. package/src/DocumentModel.d.ts +30 -0
  40. package/src/DocumentModel.js +15 -0
  41. package/src/DocumentModel.js.map +1 -0
  42. package/src/HttpPaths-86qLGB90.js +15 -0
  43. package/src/HttpPaths-86qLGB90.js.map +1 -0
  44. package/src/Module.d.ts +12 -0
  45. package/src/Module.js +167 -0
  46. package/src/Module.js.map +1 -0
  47. package/src/StudioHttp-BTLLooh0.js +916 -0
  48. package/src/StudioHttp-BTLLooh0.js.map +1 -0
  49. package/src/connection-ZGtL54qY.js +94 -0
  50. package/src/connection-ZGtL54qY.js.map +1 -0
  51. package/src/installation-BNKaVjni.js +9128 -0
  52. package/src/installation-BNKaVjni.js.map +1 -0
  53. package/src/internal/authoring-compiler.js +120 -0
  54. package/src/internal/authoring-compiler.js.map +1 -0
  55. package/src/internal/authoring-metadata.js +163 -0
  56. package/src/internal/authoring-metadata.js.map +1 -0
  57. package/src/internal/cms-config.js +46 -0
  58. package/src/internal/cms-config.js.map +1 -0
  59. package/src/internal/component-metadata.js +37 -0
  60. package/src/internal/component-metadata.js.map +1 -0
  61. package/src/internal/configuration.js +93 -0
  62. package/src/internal/configuration.js.map +1 -0
  63. package/src/internal/document-model.js +236 -0
  64. package/src/internal/document-model.js.map +1 -0
  65. package/src/internal/field-metadata.js +6 -0
  66. package/src/internal/field-metadata.js.map +1 -0
  67. package/src/metadata-Czvi3E4K.js +190 -0
  68. package/src/metadata-Czvi3E4K.js.map +1 -0
  69. package/src/models-Citx8jBi.js +306 -0
  70. package/src/models-Citx8jBi.js.map +1 -0
  71. package/src/models-DS5ClMsH.js +153 -0
  72. package/src/models-DS5ClMsH.js.map +1 -0
  73. package/src/runtime/api.js +9 -0
  74. package/src/runtime/api.js.map +1 -0
  75. package/src/runtime/collaboration.js +40 -0
  76. package/src/runtime/collaboration.js.map +1 -0
  77. package/src/runtime/delivery/DocumentField.js +23 -0
  78. package/src/runtime/delivery/DocumentField.js.map +1 -0
  79. package/src/runtime/delivery/DocumentRenderer.js +51 -0
  80. package/src/runtime/delivery/DocumentRenderer.js.map +1 -0
  81. package/src/runtime/delivery/DocumentScope.js +41 -0
  82. package/src/runtime/delivery/DocumentScope.js.map +1 -0
  83. package/src/runtime/delivery/document-page.js +23 -0
  84. package/src/runtime/delivery/document-page.js.map +1 -0
  85. package/src/runtime/delivery/document.js +25 -0
  86. package/src/runtime/delivery/document.js.map +1 -0
  87. package/src/runtime/delivery/preview.d.ts +11 -0
  88. package/src/runtime/delivery/preview.js +6 -0
  89. package/src/runtime/delivery/preview.js.map +1 -0
  90. package/src/runtime/delivery/types.d.ts +80 -0
  91. package/src/runtime/delivery/types.js +1 -0
  92. package/src/runtime/delivery/useDocument.d.ts +6 -0
  93. package/src/runtime/delivery/useDocument.js +20 -0
  94. package/src/runtime/delivery/useDocument.js.map +1 -0
  95. package/src/runtime/delivery/useDocumentQuery.d.ts +7 -0
  96. package/src/runtime/delivery/useDocumentQuery.js +26 -0
  97. package/src/runtime/delivery/useDocumentQuery.js.map +1 -0
  98. package/src/runtime/installation.js +3 -0
  99. package/src/runtime/plugin.js +32 -0
  100. package/src/runtime/plugin.js.map +1 -0
  101. package/src/runtime/preview/CmsStudioPreviewMarker.js +15 -0
  102. package/src/runtime/preview/CmsStudioPreviewMarker.js.map +1 -0
  103. package/src/runtime/preview/comark-document.js +38 -0
  104. package/src/runtime/preview/comark-document.js.map +1 -0
  105. package/src/runtime/preview/connection.js +3 -0
  106. package/src/runtime/preview/controller.js +247 -0
  107. package/src/runtime/preview/controller.js.map +1 -0
  108. package/src/runtime/preview/plugin.client.js +70 -0
  109. package/src/runtime/preview/plugin.client.js.map +1 -0
  110. package/src/runtime/preview/preview.css +9 -0
  111. package/src/runtime/preview/protocol.d.ts +10 -0
  112. package/src/runtime/preview/protocol.js +11 -0
  113. package/src/runtime/preview/protocol.js.map +1 -0
  114. package/src/runtime/preview/store.js +4 -0
  115. package/src/runtime/preview/targets.js +102 -0
  116. package/src/runtime/preview/targets.js.map +1 -0
  117. package/src/runtime/studio-app.js +13 -0
  118. package/src/runtime/studio-app.js.map +1 -0
  119. package/src/store-Nl4uxEXx.js +221 -0
  120. package/src/store-Nl4uxEXx.js.map +1 -0
@@ -0,0 +1,926 @@
1
+ import { n as CmsMarkdownDocument } from "./models-Citx8jBi.js";
2
+ import { a as createEditorNodeId, c as createCmsComarkRenderData, f as toMutableComarkAttributes, l as mutableJson, n as editorMetadata, o as editorNodeId, u as mutableJsonObject } from "./metadata-Czvi3E4K.js";
3
+ import { Effect, Option, Predicate, Schema } from "effect";
4
+ import { resolveAttributes } from "comark/utils";
5
+ import { createMarkdownParser } from "comark/parse";
6
+ import alert from "comark/plugins/alert";
7
+ import attributes from "comark/plugins/attributes";
8
+ import components from "comark/plugins/components";
9
+ import frontmatter from "comark/plugins/frontmatter";
10
+ import headings from "comark/plugins/headings";
11
+ import security from "comark/plugins/security";
12
+ import taskList from "comark/plugins/task-list";
13
+ import toc from "comark/plugins/toc";
14
+ import { Extension } from "@tiptap/core";
15
+ import { ySyncPluginKey } from "@tiptap/y-tiptap";
16
+
17
+ //#region ../document/src/internal/comark/bindings.ts
18
+ const isJsonObject$3 = Schema.is(Schema.JsonObject);
19
+ const decodeJson = Schema.decodeUnknownOption(Schema.Json);
20
+ /** Normalizes bindings exactly as Comark's framework renderers do before passing props to a component. */
21
+ function resolveCmsComarkAttributes(attributes, renderData) {
22
+ const resolved = /* @__PURE__ */ new Map();
23
+ for (const [name, value] of Object.entries(resolveAttributes(toMutableComarkAttributes(attributes), renderData, { parseJson: true }))) {
24
+ if (Predicate.isUndefined(value)) {
25
+ resolved.set(name, void 0);
26
+ continue;
27
+ }
28
+ const decoded = decodeJson(value);
29
+ if (Option.isNone(decoded)) throw new Error(`Comark resolved non-JSON attribute "${name}".`);
30
+ resolved.set(name, decoded.value);
31
+ }
32
+ return resolved;
33
+ }
34
+ /** Projects bindings to editable values while retaining enough metadata to reconstruct their authored form. */
35
+ function projectCmsEditorComponentAttributes(attributes, renderData) {
36
+ const resolved = resolveCmsComarkAttributes(attributes, renderData);
37
+ const props = {};
38
+ for (const [name, value] of resolved) if (!Predicate.isUndefined(value)) props[name] = mutableJson(value);
39
+ const bindings = {};
40
+ for (const [authoredName, authoredValue] of Object.entries(attributes)) {
41
+ if (!authoredName.startsWith(":") || authoredName.length === 1) continue;
42
+ const name = authoredName.slice(1);
43
+ if (!resolved.has(name)) continue;
44
+ const literal = jsonLiteral(authoredValue);
45
+ if (!Predicate.isString(authoredValue) || literal !== authoredValue) {
46
+ bindings[name] = { kind: "literal" };
47
+ continue;
48
+ }
49
+ const resolvedValue = resolved.get(name);
50
+ bindings[name] = Object.assign({
51
+ expression: authoredValue,
52
+ kind: "expression"
53
+ }, Predicate.isUndefined(resolvedValue) ? void 0 : { resolved: mutableJson(resolvedValue) });
54
+ }
55
+ return {
56
+ bindings,
57
+ props,
58
+ renderData: withCmsComarkProps(renderData, resolved)
59
+ };
60
+ }
61
+ /** Reconstructs authored bindings, keeping expressions until a user replaces their resolved value. */
62
+ function encodeCmsEditorComponentAttributes(props, bindings) {
63
+ const attributes = mutableJsonObject(props);
64
+ for (const [name, encodedBinding] of Object.entries(bindings)) {
65
+ const binding = jsonObject$2(encodedBinding);
66
+ const kind = binding.kind;
67
+ if (kind !== "literal" && kind !== "expression") continue;
68
+ const current = props[name];
69
+ if (Predicate.isUndefined(current)) {
70
+ const expression = binding.expression;
71
+ if (kind === "expression" && Predicate.isString(expression)) attributes[`:${name}`] = expression;
72
+ continue;
73
+ }
74
+ delete attributes[name];
75
+ const expression = binding.expression;
76
+ const resolved = binding.resolved;
77
+ attributes[`:${name}`] = kind === "expression" && Predicate.isString(expression) && Object.hasOwn(binding, "resolved") && sameJson(current, resolved) ? expression : mutableJson(current);
78
+ }
79
+ return attributes;
80
+ }
81
+ function withCmsComarkProps(renderData, attributes) {
82
+ return attributes.size > 0 ? {
83
+ ...renderData,
84
+ props: Object.fromEntries(attributes)
85
+ } : renderData;
86
+ }
87
+ /** Restores typed component bindings that Comark's block-YAML roundtrip can emit as plain attributes. */
88
+ function normalizeCmsComponentBindings(document, components) {
89
+ if (!components) return document;
90
+ return CmsMarkdownDocument.make({
91
+ frontmatter: document.frontmatter,
92
+ meta: document.meta,
93
+ nodes: document.nodes.map((node) => normalizeComponentNode(node, components))
94
+ });
95
+ }
96
+ function matchesCmsComponentPropType(value, type) {
97
+ switch (type) {
98
+ case "array": return Array.isArray(value);
99
+ case "boolean": return Predicate.isBoolean(value);
100
+ case "number": return Predicate.isNumber(value);
101
+ case "object": return isJsonObject$3(value);
102
+ case "string": return Predicate.isString(value);
103
+ }
104
+ }
105
+ function normalizeComponentNode(node, components) {
106
+ if (Predicate.isString(node) || node[0] === null) return node;
107
+ const [tag, originalAttributes, ...originalChildren] = node;
108
+ const attributes = mutableJsonObject(originalAttributes);
109
+ const definition = components.get(tag.toLocaleLowerCase());
110
+ if (definition) for (const prop of definition.props) {
111
+ if (prop.type === "string" || `:${prop.name}` in attributes || !(prop.name in attributes)) continue;
112
+ const value = attributes[prop.name];
113
+ if (Predicate.isUndefined(value)) continue;
114
+ if (!matchesCmsComponentPropType(jsonLiteral(value), prop.type)) continue;
115
+ delete attributes[prop.name];
116
+ attributes[`:${prop.name}`] = value;
117
+ }
118
+ return [
119
+ tag,
120
+ attributes,
121
+ ...originalChildren.map((child) => normalizeComponentNode(child, components))
122
+ ];
123
+ }
124
+ function jsonLiteral(value) {
125
+ if (!Predicate.isString(value)) return value;
126
+ try {
127
+ const decoded = decodeJson(JSON.parse(value));
128
+ return Option.isSome(decoded) ? decoded.value : value;
129
+ } catch {
130
+ return value;
131
+ }
132
+ }
133
+ function jsonObject$2(value) {
134
+ return isJsonObject$3(value) ? value : {};
135
+ }
136
+ function sameJson(left, right) {
137
+ return !Predicate.isUndefined(right) && JSON.stringify(left) === JSON.stringify(right);
138
+ }
139
+
140
+ //#endregion
141
+ //#region ../document/src/internal/comark/source-mapping.ts
142
+ const SOURCE_MAPPINGS_META_KEY = "__cmsSourceMappings";
143
+ const BLOCK_TAGS = /* @__PURE__ */ new Map([
144
+ ["blockquote_open", "blockquote"],
145
+ ["bullet_list_open", "ul"],
146
+ ["list_item_open", "li"],
147
+ ["ordered_list_open", "ol"],
148
+ ["paragraph_open", "p"],
149
+ ["table_open", "table"],
150
+ ["tbody_open", "tbody"],
151
+ ["td_open", "td"],
152
+ ["th_open", "th"],
153
+ ["thead_open", "thead"],
154
+ ["tr_open", "tr"]
155
+ ]);
156
+ const ComarkToken = Schema.Struct({
157
+ attrs: Schema.optionalKey(Schema.NullOr(Schema.Array(Schema.Tuple([Schema.String, Schema.String])))),
158
+ hidden: Schema.optionalKey(Schema.Boolean),
159
+ level: Schema.optionalKey(Schema.Finite),
160
+ map: Schema.optionalKey(Schema.NullOr(Schema.Tuple([Schema.Finite, Schema.Finite]))),
161
+ nesting: Schema.optionalKey(Schema.Finite),
162
+ tag: Schema.optionalKey(Schema.String),
163
+ type: Schema.optionalKey(Schema.String)
164
+ });
165
+ const WRAPPER_TAGS = /* @__PURE__ */ new Set([
166
+ "blockquote",
167
+ "ol",
168
+ "pre",
169
+ "table",
170
+ "ul"
171
+ ]);
172
+ /** Captures the durable source before frontmatter or other pre-parse stages mutate it. */
173
+ function sourceCapturePlugin() {
174
+ return {
175
+ name: "cms-source-capture",
176
+ pre(state) {
177
+ state.__cmsOriginalMarkdown = state.markdown;
178
+ }
179
+ };
180
+ }
181
+ /** Translate Comark block token line maps into exact JavaScript source offsets. */
182
+ function sourceMappingPlugin() {
183
+ return {
184
+ name: "cms-source-mapping",
185
+ post(state) {
186
+ const source = state.__cmsOriginalMarkdown ?? state.markdown;
187
+ const descriptors = createBlockDescriptors(state.tokens.flatMap((token) => {
188
+ const decoded = Schema.decodeUnknownOption(ComarkToken)(token);
189
+ return decoded._tag === "Some" ? [decoded.value] : [];
190
+ }), source, state.markdown, state.parsedLines ?? 0);
191
+ const mappings = [];
192
+ mapNodes(state.tree.nodes, descriptors, [], mappings);
193
+ state.tree.meta[SOURCE_MAPPINGS_META_KEY] = mappings;
194
+ }
195
+ };
196
+ }
197
+ function createBlockDescriptors(tokens, source, parsedMarkdown, parsedLines) {
198
+ const roots = [];
199
+ const stack = [];
200
+ const sourceLineStarts = indexLineStarts(source);
201
+ const parsedLineStarts = indexLineStarts(parsedMarkdown);
202
+ const parsedOffset = source.lastIndexOf(parsedMarkdown);
203
+ const slotMaps = createSlotTokenMaps(tokens, parsedMarkdown);
204
+ for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex++) {
205
+ const token = tokens[tokenIndex];
206
+ if (!token) continue;
207
+ const tag = blockTag(token);
208
+ const tokenMap = token.map ?? slotMaps.get(tokenIndex);
209
+ if (!tag || !tokenMap) continue;
210
+ const level = token.level ?? 0;
211
+ while (true) {
212
+ const current = stack.at(-1);
213
+ if (!current || current.level < level) break;
214
+ stack.pop();
215
+ }
216
+ const descriptor = {
217
+ children: [],
218
+ range: rangeFromParsedLines(source, sourceLineStarts, parsedMarkdown, parsedLineStarts, parsedOffset, tokenMap[0], tokenMap[1] + (token.type === "mdc_block_open" ? 1 : 0), parsedLines),
219
+ tag
220
+ };
221
+ ((stack.at(-1)?.descriptor)?.children ?? roots).push(descriptor);
222
+ if (token.nesting === 1) stack.push({
223
+ descriptor,
224
+ level
225
+ });
226
+ }
227
+ return roots.map(collapseComarkWrapper).map(groupProjectedSlotContent);
228
+ }
229
+ function blockTag(token) {
230
+ if (token.hidden || !token.type) return void 0;
231
+ if (token.type === "heading_open") return token.tag;
232
+ if (token.type === "mdc_block_open" || token.type === "mdc_block_shorthand" && token.nesting !== -1) return token.tag || "component";
233
+ if (token.type === "mdc_block_slot" && token.nesting === 1) return "template";
234
+ if ([
235
+ "fence",
236
+ "fenced_code_block",
237
+ "code_block"
238
+ ].includes(token.type)) return "pre";
239
+ if (token.type === "math_block") return "math";
240
+ if (token.type === "html_block") return "*";
241
+ if (token.type === "hr") return "hr";
242
+ return BLOCK_TAGS.get(token.type);
243
+ }
244
+ function createSlotTokenMaps(tokens, parsedMarkdown) {
245
+ const maps = /* @__PURE__ */ new Map();
246
+ const markers = slotMarkers(parsedMarkdown);
247
+ const stack = [];
248
+ let nextMarker = 0;
249
+ for (let index = 0; index < tokens.length; index++) {
250
+ const token = tokens[index];
251
+ if (!token || token.type !== "mdc_block_slot") continue;
252
+ if (token.nesting === 1) {
253
+ const name = token.attrs?.[0]?.[0]?.replace(/^#/u, "");
254
+ let markerIndex = nextMarker;
255
+ while (markerIndex < markers.length && markers[markerIndex]?.name !== name) markerIndex++;
256
+ const marker = markers[markerIndex];
257
+ if (marker) {
258
+ stack.push({
259
+ index,
260
+ marker: marker.line
261
+ });
262
+ nextMarker = markerIndex + 1;
263
+ }
264
+ continue;
265
+ }
266
+ if (token.nesting !== -1) continue;
267
+ const open = stack.pop();
268
+ if (!open) continue;
269
+ let endLine = open.marker + 1;
270
+ for (let childIndex = open.index + 1; childIndex < index; childIndex++) {
271
+ const child = tokens[childIndex];
272
+ const map = child?.map ?? maps.get(childIndex);
273
+ if (child && map) endLine = Math.max(endLine, map[1] + (child.type === "mdc_block_open" ? 1 : 0));
274
+ }
275
+ maps.set(open.index, [open.marker, endLine]);
276
+ }
277
+ return maps;
278
+ }
279
+ function slotMarkers(source) {
280
+ return source.split(/\r?\n/u).flatMap((line, index) => {
281
+ const name = line.match(/^\s*#([^\s{]+)/u)?.[1];
282
+ return name ? [{
283
+ line: index,
284
+ name
285
+ }] : [];
286
+ });
287
+ }
288
+ function collapseComarkWrapper(descriptor) {
289
+ const children = descriptor.children.map(collapseComarkWrapper);
290
+ if (WRAPPER_TAGS.has(descriptor.tag) && children.length === 1 && children[0]?.tag === descriptor.tag) return {
291
+ ...descriptor,
292
+ children: children[0].children
293
+ };
294
+ return {
295
+ ...descriptor,
296
+ children
297
+ };
298
+ }
299
+ /** Comark projects siblings after a named slot into that active slot. */
300
+ function groupProjectedSlotContent(descriptor) {
301
+ const grouped = [];
302
+ let activeSlot;
303
+ for (const rawChild of descriptor.children) {
304
+ const child = groupProjectedSlotContent(rawChild);
305
+ if (child.tag === "template") {
306
+ activeSlot = child;
307
+ grouped.push(child);
308
+ continue;
309
+ }
310
+ if (!activeSlot) {
311
+ grouped.push(child);
312
+ continue;
313
+ }
314
+ activeSlot.children.push(child);
315
+ if (child.range.end.offset > activeSlot.range.end.offset) activeSlot.range = {
316
+ start: activeSlot.range.start,
317
+ end: child.range.end
318
+ };
319
+ }
320
+ return {
321
+ ...descriptor,
322
+ children: grouped
323
+ };
324
+ }
325
+ function mapNodes(nodes, descriptors, parentPath, mappings) {
326
+ let descriptorIndex = 0;
327
+ for (let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++) {
328
+ const node = nodes[nodeIndex];
329
+ if (!node || !isElementNode$1(node)) continue;
330
+ let matchIndex = descriptorIndex;
331
+ while (matchIndex < descriptors.length && descriptors[matchIndex]?.tag !== "*" && descriptors[matchIndex]?.tag !== node[0]) matchIndex++;
332
+ const descriptor = descriptors[matchIndex];
333
+ if (!descriptor) continue;
334
+ descriptorIndex = matchIndex + 1;
335
+ const nodePath = [...parentPath, nodeIndex];
336
+ mappings.push({
337
+ nodePath,
338
+ range: descriptor.range
339
+ });
340
+ const [, , ...children] = node;
341
+ mapNodes(children, descriptor.children, nodePath, mappings);
342
+ }
343
+ }
344
+ function isElementNode$1(node) {
345
+ return Array.isArray(node) && Predicate.isString(node[0]);
346
+ }
347
+ function indexLineStarts(source) {
348
+ const starts = [0];
349
+ for (let offset = 0; offset < source.length; offset++) if (source.charCodeAt(offset) === 10) starts.push(offset + 1);
350
+ return starts;
351
+ }
352
+ function rangeFromParsedLines(source, sourceLineStarts, parsedMarkdown, parsedLineStarts, parsedOffset, startLine, endLine, fallbackLineOffset) {
353
+ const startOffset = parsedOffset >= 0 ? parsedOffset + (parsedLineStarts[startLine] ?? parsedMarkdown.length) : sourceLineStarts[startLine + fallbackLineOffset] ?? source.length;
354
+ const endOffset = parsedOffset >= 0 ? parsedOffset + (parsedLineStarts[endLine] ?? parsedMarkdown.length) : sourceLineStarts[endLine + fallbackLineOffset] ?? source.length;
355
+ return {
356
+ start: pointAt(source, sourceLineStarts, startOffset),
357
+ end: pointAt(source, sourceLineStarts, Math.max(startOffset, endOffset))
358
+ };
359
+ }
360
+ function pointAt(source, lineStarts, rawOffset) {
361
+ const offset = Math.min(Math.max(rawOffset, 0), source.length);
362
+ let low = 0;
363
+ let high = lineStarts.length - 1;
364
+ while (low < high) {
365
+ const middle = Math.ceil((low + high) / 2);
366
+ if ((lineStarts[middle] ?? source.length) <= offset) low = middle;
367
+ else high = middle - 1;
368
+ }
369
+ return {
370
+ offset,
371
+ line: low + 1,
372
+ column: offset - (lineStarts[low] ?? 0) + 1
373
+ };
374
+ }
375
+
376
+ //#endregion
377
+ //#region ../document/src/internal/comark/grammar.ts
378
+ /**
379
+ * Changes when parsing, normalization, or projection semantics change. Stored
380
+ * with compiled documents so migrations can identify stale derived content.
381
+ */
382
+ const DOCUMENT_ENGINE_FINGERPRINT = "comark@0.6.2/frontmatter+alert+task-list+components+attributes+security+headings+toc+source-mapping/v1";
383
+ /** One explicit grammar for authoring, preview, delivery, and analysis projections. */
384
+ function createDocumentParser() {
385
+ return createMarkdownParser({
386
+ autoClose: false,
387
+ registerDefaultPlugins: false,
388
+ plugins: [
389
+ sourceCapturePlugin(),
390
+ frontmatter(),
391
+ alert(),
392
+ taskList(),
393
+ components(),
394
+ attributes(),
395
+ security(),
396
+ headings(),
397
+ toc({
398
+ depth: 5,
399
+ searchDepth: 6
400
+ }),
401
+ sourceMappingPlugin()
402
+ ]
403
+ });
404
+ }
405
+
406
+ //#endregion
407
+ //#region ../document/src/internal/editor/attributes.ts
408
+ function compactJsonAttributes(attributes) {
409
+ return Object.fromEntries(Object.entries(attributes).filter((entry) => entry[1] !== void 0));
410
+ }
411
+ function nonEmptyStringAttribute(value) {
412
+ return Predicate.isString(value) && value ? value : void 0;
413
+ }
414
+ function finiteNumberAttribute(value, fallback) {
415
+ const number = Predicate.isNumber(value) ? value : Number(value);
416
+ return Number.isFinite(number) ? number : fallback;
417
+ }
418
+
419
+ //#endregion
420
+ //#region ../document/src/internal/editor/image.ts
421
+ const isJsonObject$2 = Schema.is(Schema.JsonObject);
422
+ const EditorImageLayout = Schema.Literals([
423
+ "natural",
424
+ "content",
425
+ "full"
426
+ ]);
427
+ const isEditorImageLayout = Schema.is(EditorImageLayout);
428
+ const EDITOR_IMAGE_LAYOUT_ATTRIBUTE = "data-cms-layout";
429
+ const IMAGE_DECORATIVE_ATTRIBUTE = "data-cms-decorative";
430
+ const IMAGE_SEMANTIC_ATTRIBUTES = /* @__PURE__ */ new Set([
431
+ "alt",
432
+ IMAGE_DECORATIVE_ATTRIBUTE,
433
+ EDITOR_IMAGE_LAYOUT_ATTRIBUTE,
434
+ "src",
435
+ "title"
436
+ ]);
437
+ function decodeEditorImageAttributes(attributes) {
438
+ const cmsProps = Object.fromEntries(Object.entries(attributes).filter(([name]) => !IMAGE_SEMANTIC_ATTRIBUTES.has(name)));
439
+ return compactJsonAttributes({
440
+ alt: attributes[IMAGE_DECORATIVE_ATTRIBUTE] !== void 0 ? "" : Predicate.isString(attributes.alt) ? attributes.alt : null,
441
+ cmsProps: Object.keys(cmsProps).length ? cmsProps : null,
442
+ layout: normalizeEditorImageLayout(attributes[EDITOR_IMAGE_LAYOUT_ATTRIBUTE]),
443
+ src: stringValue(attributes.src) || null,
444
+ title: stringValue(attributes.title) || null
445
+ });
446
+ }
447
+ function encodeEditorImageAttributes(value) {
448
+ const attributes = jsonObject$1(value);
449
+ const alt = attributes.alt;
450
+ const layout = normalizeEditorImageLayout(attributes.layout);
451
+ return compactJsonAttributes(Object.assign({}, jsonObject$1(attributes.cmsProps), {
452
+ alt: Predicate.isString(alt) ? alt : void 0,
453
+ [IMAGE_DECORATIVE_ATTRIBUTE]: alt === "" ? "true" : void 0,
454
+ [EDITOR_IMAGE_LAYOUT_ATTRIBUTE]: layout === "natural" ? void 0 : layout,
455
+ src: stringValue(attributes.src) || void 0,
456
+ title: stringValue(attributes.title) || void 0
457
+ }));
458
+ }
459
+ function normalizeEditorImageLayout(value) {
460
+ return isEditorImageLayout(value) ? value : "natural";
461
+ }
462
+ function jsonObject$1(value) {
463
+ return isJsonObject$2(value) ? value : {};
464
+ }
465
+ function stringValue(value) {
466
+ return Predicate.isString(value) || Predicate.isNumber(value) ? String(value) : "";
467
+ }
468
+
469
+ //#endregion
470
+ //#region ../document/src/internal/editor/marks.ts
471
+ const EDITOR_MARKS = [
472
+ ["bold", "strong"],
473
+ ["code", "code"],
474
+ ["italic", "em"],
475
+ ["link", "a"],
476
+ ["strike", "del"],
477
+ ["underline", "u"]
478
+ ];
479
+ const EDITOR_MARK_TYPES = EDITOR_MARKS.map(([type]) => type);
480
+ const editorToComark = new Map(EDITOR_MARKS);
481
+ const comarkToEditor$1 = new Map(EDITOR_MARKS.map(([type, tag]) => [tag, type]));
482
+ function comarkTagForEditorMark(type) {
483
+ return editorToComark.get(type);
484
+ }
485
+ function editorMarkForComarkTag(tag) {
486
+ return comarkToEditor$1.get(tag);
487
+ }
488
+ function isEditorMark(type) {
489
+ return editorToComark.has(type);
490
+ }
491
+ function isComarkMark(tag) {
492
+ return comarkToEditor$1.has(tag);
493
+ }
494
+
495
+ //#endregion
496
+ //#region ../document/src/internal/comark/to-editor.ts
497
+ const isJsonObject$1 = Schema.is(Schema.JsonObject);
498
+ const OPAQUE_BLOCK_TAGS = /* @__PURE__ */ new Set([
499
+ "math",
500
+ "table",
501
+ "tbody",
502
+ "td",
503
+ "th",
504
+ "thead",
505
+ "tr"
506
+ ]);
507
+ function comarkToEditor(nodes, renderData = {
508
+ data: {},
509
+ frontmatter: {},
510
+ meta: {},
511
+ props: {}
512
+ }) {
513
+ return decodeBlocks(nodes, { usedIds: /* @__PURE__ */ new Set() }, renderData);
514
+ }
515
+ function decodeBlocks(nodes, context, renderData, wrapInlineContent = false) {
516
+ const content = [];
517
+ let inlineNodes = [];
518
+ const flushInlineNodes = () => {
519
+ const inline = decodeInlines(inlineNodes, context, renderData);
520
+ if (inline.length) content.push({
521
+ type: "paragraph",
522
+ attrs: wrapInlineContent ? { cmsSynthetic: true } : { cmsNodeId: claimIdentity(context) },
523
+ content: inline
524
+ });
525
+ inlineNodes = [];
526
+ };
527
+ for (const node of nodes) {
528
+ if (Predicate.isString(node) || isInlineElement(node)) {
529
+ inlineNodes.push(node);
530
+ continue;
531
+ }
532
+ flushInlineNodes();
533
+ content.push(decodeBlock(node, context, renderData));
534
+ }
535
+ flushInlineNodes();
536
+ return content;
537
+ }
538
+ function decodeBlock(node, context, renderData) {
539
+ if (node[0] === null) return opaqueBlock(node, "Comment", claimIdentity(context, node[1]));
540
+ const [tag, rawAttributes, ...children] = node;
541
+ const attrs = cleanAttrs(rawAttributes);
542
+ const childRenderData = withCmsComarkProps(renderData, resolveCmsComarkAttributes(rawAttributes, renderData));
543
+ const metadata = editorMetadata(rawAttributes);
544
+ const cmsNodeId = claimIdentity(context, rawAttributes);
545
+ const commonAttrs = compactJsonAttributes({
546
+ cmsNodeId,
547
+ cmsProps: attrs
548
+ });
549
+ if (/^h[1-6]$/u.test(tag)) return {
550
+ type: "heading",
551
+ attrs: mergeJsonAttributes(commonAttrs, { level: Number(tag.slice(1)) }),
552
+ content: decodeInlines(children, context, childRenderData)
553
+ };
554
+ switch (tag) {
555
+ case "p": return {
556
+ type: "paragraph",
557
+ attrs: commonAttrs,
558
+ content: decodeInlines(children, context, childRenderData)
559
+ };
560
+ case "blockquote": return {
561
+ type: "blockquote",
562
+ attrs: commonAttrs,
563
+ content: decodeBlocks(children, context, childRenderData)
564
+ };
565
+ case "ul": return {
566
+ type: "bulletList",
567
+ attrs: commonAttrs,
568
+ content: decodeListItems(children, context, childRenderData)
569
+ };
570
+ case "ol": return {
571
+ type: "orderedList",
572
+ attrs: mergeJsonAttributes(commonAttrs, { start: finiteNumberAttribute(attrs.start, 1) }),
573
+ content: decodeListItems(children, context, childRenderData)
574
+ };
575
+ case "li": return {
576
+ type: "listItem",
577
+ attrs: commonAttrs,
578
+ content: decodeBlocks(children, context, childRenderData)
579
+ };
580
+ case "pre": {
581
+ const code = children.find(isElementNode);
582
+ return {
583
+ type: "codeBlock",
584
+ attrs: mergeJsonAttributes(commonAttrs, { language: nonEmptyStringAttribute(attrs.language) ?? nonEmptyStringAttribute(code?.[1].class)?.replace(/^language-/u, "") }),
585
+ content: textContent$1(code ? elementChildren(code) : children)
586
+ };
587
+ }
588
+ case "hr": return {
589
+ type: "horizontalRule",
590
+ attrs: commonAttrs
591
+ };
592
+ default:
593
+ if (OPAQUE_BLOCK_TAGS.has(tag)) return opaqueBlock(node, tag, cmsNodeId);
594
+ const projection = projectCmsEditorComponentAttributes(rawAttributes, renderData);
595
+ return {
596
+ type: "cmsBlock",
597
+ attrs: compactJsonAttributes({
598
+ bindings: projection.bindings,
599
+ cmsNodeId,
600
+ props: projection.props,
601
+ tag
602
+ }),
603
+ content: decodeComponentSlots(children, context, projection.renderData, metadata?.implicitSlotId)
604
+ };
605
+ }
606
+ }
607
+ function decodeComponentSlots(children, context, renderData, implicitSlotId) {
608
+ const templates = children.filter(isSlotTemplate);
609
+ const regular = children.filter((node) => !isSlotTemplate(node));
610
+ const slots = templates.map((node) => decodeSlot(node, context, renderData));
611
+ if (!regular.length) return slots;
612
+ const defaultContent = slotContent(decodeBlocks(regular, context, renderData, true));
613
+ const explicitDefault = slots.find((slot) => slot.attrs?.name === "default");
614
+ if (explicitDefault) {
615
+ explicitDefault.content = [...explicitDefault.content ?? [], ...defaultContent];
616
+ return slots;
617
+ }
618
+ return [{
619
+ type: "cmsSlot",
620
+ attrs: {
621
+ cmsNodeId: claimIdentityValue(context, implicitSlotId),
622
+ implicit: true,
623
+ name: "default",
624
+ props: {}
625
+ },
626
+ content: defaultContent
627
+ }, ...slots];
628
+ }
629
+ function decodeSlot(node, context, renderData) {
630
+ const attrs = cleanAttrs(node[1]);
631
+ const childRenderData = withCmsComarkProps(renderData, resolveCmsComarkAttributes(node[1], renderData));
632
+ const name = slotName(attrs);
633
+ const { name: _name, ...slotProps } = attrs;
634
+ return {
635
+ type: "cmsSlot",
636
+ attrs: {
637
+ cmsNodeId: claimIdentity(context, node[1]),
638
+ implicit: false,
639
+ name,
640
+ props: slotProps
641
+ },
642
+ content: slotContent(decodeBlocks(elementChildren(node), context, childRenderData, true))
643
+ };
644
+ }
645
+ function decodeListItems(nodes, context, renderData) {
646
+ return nodes.filter(isElementNode).filter((node) => node[0] === "li").map((node) => decodeBlock(node, context, renderData));
647
+ }
648
+ function decodeInlines(nodes, context, renderData, inheritedMarks = []) {
649
+ const result = [];
650
+ for (const node of nodes) {
651
+ if (Predicate.isString(node)) {
652
+ if (node) result.push(withMarks({
653
+ type: "text",
654
+ text: node
655
+ }, inheritedMarks));
656
+ continue;
657
+ }
658
+ if (node[0] === null) {
659
+ result.push(withMarks({
660
+ type: "cmsInlineOpaque",
661
+ attrs: {
662
+ label: "Comment",
663
+ node: stripInternalMetadata(node)
664
+ }
665
+ }, inheritedMarks));
666
+ continue;
667
+ }
668
+ const markType = editorMarkForComarkTag(node[0]);
669
+ if (markType) {
670
+ const attrs = cleanAttrs(node[1]);
671
+ const childRenderData = withCmsComarkProps(renderData, resolveCmsComarkAttributes(node[1], renderData));
672
+ const markAttrs = markType === "link" ? mergeJsonAttributes(attrs, { cmsProps: attrs }) : Object.keys(attrs).length ? { cmsProps: attrs } : void 0;
673
+ const mark = markAttrs === void 0 ? { type: markType } : {
674
+ attrs: markAttrs,
675
+ type: markType
676
+ };
677
+ result.push(...decodeInlines(elementChildren(node), context, childRenderData, [...inheritedMarks, mark]));
678
+ continue;
679
+ }
680
+ if (node[0] === "br") {
681
+ result.push(withMarks({ type: "hardBreak" }, inheritedMarks));
682
+ continue;
683
+ }
684
+ if (node[0] === "img") {
685
+ result.push(withMarks({
686
+ type: "image",
687
+ attrs: mergeJsonAttributes(decodeEditorImageAttributes(cleanAttrs(node[1])), { cmsNodeId: claimIdentity(context, node[1]) })
688
+ }, inheritedMarks));
689
+ continue;
690
+ }
691
+ result.push(withMarks({
692
+ type: "cmsInlineOpaque",
693
+ attrs: {
694
+ label: node[0],
695
+ node: stripInternalMetadata(node)
696
+ }
697
+ }, inheritedMarks));
698
+ }
699
+ return result;
700
+ }
701
+ function claimIdentity(context, attributes) {
702
+ return claimIdentityValue(context, attributes ? editorMetadata(attributes)?.nodeId : void 0);
703
+ }
704
+ function claimIdentityValue(context, candidate) {
705
+ const existing = editorNodeId(candidate);
706
+ if (existing !== void 0 && !context.usedIds.has(existing)) {
707
+ context.usedIds.add(existing);
708
+ return existing;
709
+ }
710
+ for (let attempt = 0; attempt < 100; attempt++) {
711
+ const created = createEditorNodeId();
712
+ if (!context.usedIds.has(created)) {
713
+ context.usedIds.add(created);
714
+ return created;
715
+ }
716
+ }
717
+ throw new Error("The editor identity factory did not produce a unique identity.");
718
+ }
719
+ function opaqueBlock(node, label, cmsNodeId) {
720
+ return {
721
+ type: "cmsOpaque",
722
+ attrs: {
723
+ cmsNodeId,
724
+ label,
725
+ node: stripInternalMetadata(node)
726
+ }
727
+ };
728
+ }
729
+ function stripInternalMetadata(node) {
730
+ if (node[0] === null) return [
731
+ null,
732
+ cleanAttrs(node[1]),
733
+ node[2]
734
+ ];
735
+ const [tag, attributes, ...children] = node;
736
+ return [
737
+ tag,
738
+ cleanAttrs(attributes),
739
+ ...children.map((child) => Predicate.isString(child) ? child : stripInternalMetadata(child))
740
+ ];
741
+ }
742
+ function slotContent(content) {
743
+ return content.length ? content : [{
744
+ type: "paragraph",
745
+ attrs: { cmsSynthetic: true }
746
+ }];
747
+ }
748
+ function slotName(attrs) {
749
+ return nonEmptyStringAttribute(attrs.name) ?? "default";
750
+ }
751
+ function cleanAttrs(attrs) {
752
+ const { $: _internal, "data-cms-node": _marker, ...clean } = attrs;
753
+ return structuredClone(clean);
754
+ }
755
+ function textContent$1(nodes) {
756
+ const text = nodes.map((node) => Predicate.isString(node) ? node : node[0] === null ? node[2] : textContent$1(elementChildren(node))?.map((child) => child.text ?? "").join("") ?? "").join("");
757
+ return text ? [{
758
+ type: "text",
759
+ text
760
+ }] : void 0;
761
+ }
762
+ function isInlineElement(node) {
763
+ return node[0] !== null && (isComarkMark(node[0]) || node[0] === "br" || node[0] === "img" || jsonObject(node[1].$).block === 0);
764
+ }
765
+ function isSlotTemplate(node) {
766
+ return isElementNode(node) && node[0] === "template";
767
+ }
768
+ function isElementNode(node) {
769
+ return Array.isArray(node) && Predicate.isString(node[0]);
770
+ }
771
+ function elementChildren(node) {
772
+ const [, , ...children] = node;
773
+ return children;
774
+ }
775
+ function jsonObject(value) {
776
+ return isJsonObject$1(value) ? value : {};
777
+ }
778
+ function mergeJsonAttributes(attributes, additions) {
779
+ return compactJsonAttributes(Object.assign({}, attributes, additions));
780
+ }
781
+ function withMarks(content, marks) {
782
+ return marks.length ? Object.assign({}, content, { marks }) : content;
783
+ }
784
+
785
+ //#endregion
786
+ //#region ../document/src/internal/editor/errors.ts
787
+ var EditorDocumentInvalid = class extends Schema.TaggedError()("EditorDocument.Invalid", {
788
+ message: Schema.NonEmptyString,
789
+ cause: Schema.Defect()
790
+ }) {};
791
+ var EditorRenderFailed = class extends Schema.TaggedError()("EditorDocument.RenderFailed", { cause: Schema.Defect() }) {};
792
+
793
+ //#endregion
794
+ //#region ../document/src/AuthoringSchema.ts
795
+ /** Compiles insertion content with the same grammar used for publication. */
796
+ const parseAuthoringContent = Effect.fn("AuthoringSchema.parseContent")(function* (markdown) {
797
+ const body = yield* Effect.tryPromise({
798
+ try: () => createDocumentParser()(markdown),
799
+ catch: (cause) => new EditorDocumentInvalid({
800
+ cause,
801
+ message: "Invalid initial Markdown content."
802
+ })
803
+ });
804
+ return (yield* Schema.decodeUnknownEffect(CmsMarkdownDocument)(body)).nodes;
805
+ });
806
+ const isJsonObject = Schema.is(Schema.JsonObject);
807
+ /** Validates authored blocks during single-document compilation as well as catalog publication. */
808
+ function validateAuthoringDocument(body, components) {
809
+ if (!components || ![...components.values()].some((component) => component.authoring)) return [];
810
+ function visit(node) {
811
+ const component = node.type === "cmsBlock" ? components?.get(String(node.attrs?.tag).toLowerCase()) : void 0;
812
+ return [...component?.authoring ? createAuthoringSchema(component.name, component.authoring).validate(node, "publish") : [], ...(node.content ?? []).flatMap(visit)];
813
+ }
814
+ return comarkToEditor(body.nodes, createCmsComarkRenderData(body)).flatMap(visit);
815
+ }
816
+ function createAuthoringSchema(name, definition) {
817
+ const fields = new Map(definition.props.map((field) => [field.name, field]));
818
+ const slots = new Map(definition.slots.map((slot) => [slot.name, slot]));
819
+ if (fields.size !== definition.props.length || slots.size !== definition.slots.length) throw new Error(`${definition.label}: authoring names must be unique.`);
820
+ const initialProps = {
821
+ ...Object.fromEntries(definition.props.flatMap((field) => field.defaultValue === void 0 ? [] : [[field.name, field.defaultValue]])),
822
+ ...definition.initialProps
823
+ };
824
+ for (const field of definition.props) {
825
+ if (field.defaultValue === void 0) continue;
826
+ const issue = propertyIssue(field, field.defaultValue, "working");
827
+ if (issue) throw new Error(`Invalid default for ${definition.label}: ${issue}`);
828
+ }
829
+ function createSlot(slotName) {
830
+ const slot = slots.get(slotName);
831
+ if (!slot) throw new Error(`${definition.label}: unknown content region ${slotName}.`);
832
+ const content = slot.initial ? comarkToEditor(slot.initial) : [];
833
+ return {
834
+ type: "cmsSlot",
835
+ attrs: {
836
+ cmsNodeId: createEditorNodeId(),
837
+ name: slotName,
838
+ implicit: slotName === "default",
839
+ props: {}
840
+ },
841
+ content: content.length ? content : [{
842
+ type: "paragraph",
843
+ attrs: { cmsNodeId: createEditorNodeId() }
844
+ }]
845
+ };
846
+ }
847
+ function createContent() {
848
+ return {
849
+ type: "cmsBlock",
850
+ attrs: {
851
+ cmsNodeId: createEditorNodeId(),
852
+ tag: name,
853
+ props: structuredClone(initialProps)
854
+ },
855
+ content: definition.slots.filter((slot) => slot.required || slot.initial !== void 0).map((slot) => createSlot(slot.name))
856
+ };
857
+ }
858
+ function validate(node, purpose) {
859
+ const issues = [];
860
+ const attributes = node.attrs?.props;
861
+ const values = isJsonObject(attributes) ? attributes : {};
862
+ for (const key of Object.keys(values)) if (!fields.has(key)) issues.push(`${definition.label}: ${key} is not editable.`);
863
+ for (const field of definition.props) {
864
+ const issue = propertyIssue(field, values[field.name] ?? (values[field.name] === null ? null : field.defaultValue), purpose);
865
+ if (issue) issues.push(issue);
866
+ }
867
+ const used = /* @__PURE__ */ new Set();
868
+ for (const region of node.content ?? []) {
869
+ const key = String(region.attrs?.name ?? "default");
870
+ const slot = slots.get(key);
871
+ if (!slot || region.type !== "cmsSlot") {
872
+ issues.push(`${definition.label}: unsupported content region ${key}.`);
873
+ continue;
874
+ }
875
+ if (used.has(key)) issues.push(`${slot.label} can only appear once.`);
876
+ used.add(key);
877
+ if (!validRegion(slot, region.content ?? [])) issues.push(`${slot.label} contains unsupported formatting or blocks.`);
878
+ }
879
+ for (const slot of definition.slots) if (slot.required && !used.has(slot.name)) issues.push(`${slot.label} is required.`);
880
+ return issues;
881
+ }
882
+ const schema = {
883
+ definition,
884
+ createContent,
885
+ createSlot,
886
+ validate,
887
+ setProperty(current, key, value) {
888
+ const field = fields.get(key);
889
+ if (!field) throw new Error(`${definition.label}: ${key} is not editable.`);
890
+ const issue = propertyIssue(field, value, "working");
891
+ if (issue) throw new Error(issue);
892
+ const next = Object.fromEntries(Object.entries(current));
893
+ if (value === void 0) delete next[key];
894
+ else next[key] = value;
895
+ return next;
896
+ }
897
+ };
898
+ const issues = validate(createContent(), "publish");
899
+ if (issues.length) throw new Error(`Invalid initial content for ${definition.label}: ${issues.join(" ")}`);
900
+ return schema;
901
+ }
902
+ function propertyIssue(field, value, purpose) {
903
+ if (value === void 0) return field.required && purpose === "publish" ? `${field.label} is required.` : void 0;
904
+ if (value === null && field.nullable) return void 0;
905
+ if (!(field.type === "string" ? Predicate.isString(value) : field.type === "number" ? Predicate.isNumber(value) && Number.isFinite(value) : Predicate.isBoolean(value))) return `${field.label} must be ${field.type}.`;
906
+ if (field.options.length && !field.options.some((option) => option.value === value)) return `${field.label} must use one of its available choices.`;
907
+ }
908
+ function validRegion(slot, content) {
909
+ const types = /* @__PURE__ */ new Set([
910
+ "paragraph",
911
+ "text",
912
+ "hardBreak"
913
+ ]);
914
+ const marks = /* @__PURE__ */ new Set();
915
+ if (slot.input === "text" && content.length > 1) return false;
916
+ if (slot.input === "rich-text") for (const feature of slot.features) if (feature === "bullet-list") {
917
+ types.add("bulletList");
918
+ types.add("listItem");
919
+ } else marks.add(feature);
920
+ const valid = (node) => types.has(node.type ?? "") && (node.marks ?? []).every((mark) => marks.has(mark.type)) && (node.content ?? []).every(valid);
921
+ return content.every(valid);
922
+ }
923
+
924
+ //#endregion
925
+ export { withCmsComarkProps as C, resolveCmsComarkAttributes as S, createDocumentParser as _, EditorRenderFailed as a, matchesCmsComponentPropType as b, comarkTagForEditorMark as c, encodeEditorImageAttributes as d, normalizeEditorImageLayout as f, DOCUMENT_ENGINE_FINGERPRINT as g, nonEmptyStringAttribute as h, EditorDocumentInvalid as i, isEditorMark as l, finiteNumberAttribute as m, parseAuthoringContent as n, comarkToEditor as o, compactJsonAttributes as p, validateAuthoringDocument as r, EDITOR_MARK_TYPES as s, createAuthoringSchema as t, EDITOR_IMAGE_LAYOUT_ATTRIBUTE as u, SOURCE_MAPPINGS_META_KEY as v, normalizeCmsComponentBindings as x, encodeCmsEditorComponentAttributes as y };
926
+ //# sourceMappingURL=AuthoringSchema-BQ5kbhVB.js.map