@phtngyn/cms 0.1.0-beta.0 → 0.1.0-beta.2

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 (181) hide show
  1. package/README.md +260 -6
  2. package/package.json +31 -16
  3. package/src/Authoring.d.ts +13 -1
  4. package/src/Configuration-Br7tE9Qt.d.ts +68 -0
  5. package/src/{AuthoringSchema-BQ5kbhVB.js → Configuration-CA_jvQKG.js} +599 -492
  6. package/src/Configuration-CA_jvQKG.js.map +1 -0
  7. package/src/Configuration.d.ts +2 -44
  8. package/src/Configuration.js +0 -1
  9. package/src/Configuration.js.map +1 -1
  10. package/src/{DocumentEngine-Da0kWotL.js → DocumentEngine-CgiBQU4g.js} +110 -84
  11. package/src/DocumentEngine-CgiBQU4g.js.map +1 -0
  12. package/src/DocumentModel-BB9igGC7.d.ts +34 -0
  13. package/src/DocumentModel.d.ts +2 -30
  14. package/src/DocumentModel.js +13 -3
  15. package/src/DocumentModel.js.map +1 -1
  16. package/src/Forms-BsJMev5_.d.ts +74 -0
  17. package/src/Forms-CfcI3tPU.js +79 -0
  18. package/src/Forms-CfcI3tPU.js.map +1 -0
  19. package/src/Forms-DxbkU3_5.js +367 -0
  20. package/src/Forms-DxbkU3_5.js.map +1 -0
  21. package/src/Forms.d.ts +35 -0
  22. package/src/Forms.js +13 -0
  23. package/src/Forms.js.map +1 -0
  24. package/src/HttpPaths-c9nLZ9H2.js +21 -0
  25. package/src/HttpPaths-c9nLZ9H2.js.map +1 -0
  26. package/src/I18n-DZK4CkJF.d.ts +21 -0
  27. package/src/I18n.d.ts +2 -0
  28. package/src/I18n.js +1 -0
  29. package/src/Module.js +78 -81
  30. package/src/Module.js.map +1 -1
  31. package/src/S3MediaObjects-JKMAWyVB.js +2664 -0
  32. package/src/S3MediaObjects-JKMAWyVB.js.map +1 -0
  33. package/src/Seed.d.ts +6 -0
  34. package/src/Seed.js +34 -0
  35. package/src/Seed.js.map +1 -0
  36. package/src/Seo-402YumpT.d.ts +198 -0
  37. package/src/{connection-ZGtL54qY.js → connection-B-iz0Y9Y.js} +5 -7
  38. package/src/connection-B-iz0Y9Y.js.map +1 -0
  39. package/src/{installation-BNKaVjni.js → installation-DgF2M1gL.js} +1162 -2147
  40. package/src/installation-DgF2M1gL.js.map +1 -0
  41. package/src/internal/authoring-catalog.js +153 -0
  42. package/src/internal/authoring-catalog.js.map +1 -0
  43. package/src/internal/authoring-compiler.js +2 -2
  44. package/src/internal/authoring-compiler.js.map +1 -1
  45. package/src/internal/authoring-metadata.js +68 -49
  46. package/src/internal/authoring-metadata.js.map +1 -1
  47. package/src/internal/cms-config.js +0 -1
  48. package/src/internal/cms-config.js.map +1 -1
  49. package/src/internal/configuration.js +25 -13
  50. package/src/internal/configuration.js.map +1 -1
  51. package/src/internal/document-model.js +66 -20
  52. package/src/internal/document-model.js.map +1 -1
  53. package/src/internal/form-capabilities.js +12 -0
  54. package/src/internal/form-capabilities.js.map +1 -0
  55. package/src/internal/i18n.js +47 -0
  56. package/src/internal/i18n.js.map +1 -0
  57. package/src/internal/studio-app.js +66 -0
  58. package/src/internal/studio-app.js.map +1 -0
  59. package/src/location-CFKTeK1K.js +35 -0
  60. package/src/location-CFKTeK1K.js.map +1 -0
  61. package/src/{metadata-Czvi3E4K.js → metadata-BEZPWh-3.js} +3 -72
  62. package/src/metadata-BEZPWh-3.js.map +1 -0
  63. package/src/{models-DS5ClMsH.js → models-BWm1pTAf.js} +9 -31
  64. package/src/models-BWm1pTAf.js.map +1 -0
  65. package/src/models-DwYioyNV.js +726 -0
  66. package/src/models-DwYioyNV.js.map +1 -0
  67. package/src/runtime/blocks.js +30 -0
  68. package/src/runtime/blocks.js.map +1 -0
  69. package/src/runtime/collaboration.js +9 -4
  70. package/src/runtime/collaboration.js.map +1 -1
  71. package/src/runtime/delivery/DocumentRenderer.js +10 -4
  72. package/src/runtime/delivery/DocumentRenderer.js.map +1 -1
  73. package/src/runtime/delivery/blocks.js +8 -0
  74. package/src/runtime/delivery/blocks.js.map +1 -0
  75. package/src/runtime/delivery/context.js +12 -0
  76. package/src/runtime/delivery/context.js.map +1 -0
  77. package/src/runtime/delivery/document-page.js +14 -12
  78. package/src/runtime/delivery/document-page.js.map +1 -1
  79. package/src/runtime/delivery/document.js +21 -3
  80. package/src/runtime/delivery/document.js.map +1 -1
  81. package/src/runtime/delivery/error.js +11 -0
  82. package/src/runtime/delivery/error.js.map +1 -0
  83. package/src/runtime/delivery/plugin.js +41 -0
  84. package/src/runtime/delivery/plugin.js.map +1 -0
  85. package/src/runtime/delivery/types.d.ts +5 -0
  86. package/src/runtime/delivery/useCmsDocumentSeo.d.ts +56 -0
  87. package/src/runtime/delivery/useCmsDocumentSeo.js +99 -0
  88. package/src/runtime/delivery/useCmsDocumentSeo.js.map +1 -0
  89. package/src/runtime/delivery/useDocument.js +5 -2
  90. package/src/runtime/delivery/useDocument.js.map +1 -1
  91. package/src/runtime/delivery/useDocumentQuery.js +5 -2
  92. package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
  93. package/src/runtime/forms/document.js +38 -0
  94. package/src/runtime/forms/document.js.map +1 -0
  95. package/src/runtime/forms/useCmsForm.js +149 -0
  96. package/src/runtime/forms/useCmsForm.js.map +1 -0
  97. package/src/runtime/i18n/translator.js +22 -0
  98. package/src/runtime/i18n/translator.js.map +1 -0
  99. package/src/runtime/i18n/useCmsI18n.d.ts +9 -0
  100. package/src/runtime/i18n/useCmsI18n.js +29 -0
  101. package/src/runtime/i18n/useCmsI18n.js.map +1 -0
  102. package/src/runtime/installation.js +1 -1
  103. package/src/runtime/plugin.js +3 -3
  104. package/src/runtime/plugin.js.map +1 -1
  105. package/src/runtime/preview/comark-document.js +0 -1
  106. package/src/runtime/preview/comark-document.js.map +1 -1
  107. package/src/runtime/preview/connection.js +1 -1
  108. package/src/runtime/preview/controller.js +37 -11
  109. package/src/runtime/preview/controller.js.map +1 -1
  110. package/src/runtime/preview/overlay.js +65 -0
  111. package/src/runtime/preview/overlay.js.map +1 -0
  112. package/src/runtime/preview/plugin.client.js +59 -61
  113. package/src/runtime/preview/plugin.client.js.map +1 -1
  114. package/src/runtime/preview/preview.css +72 -4
  115. package/src/runtime/preview/protocol.js.map +1 -1
  116. package/src/runtime/preview/store.js +1 -1
  117. package/src/runtime/preview/targets.js +0 -1
  118. package/src/runtime/preview/targets.js.map +1 -1
  119. package/src/runtime/sitemap-entries.js +17 -0
  120. package/src/runtime/sitemap-entries.js.map +1 -0
  121. package/src/runtime/sitemap.js +24 -0
  122. package/src/runtime/sitemap.js.map +1 -0
  123. package/src/runtime/studio-app.js +5 -1
  124. package/src/runtime/studio-app.js.map +1 -1
  125. package/src/runtime/studio-entry.js +36 -0
  126. package/src/runtime/studio-entry.js.map +1 -0
  127. package/src/runtime/studio-navigation.js +11 -0
  128. package/src/runtime/studio-navigation.js.map +1 -0
  129. package/src/scalars-B2lgGUnj.js +26 -0
  130. package/src/scalars-B2lgGUnj.js.map +1 -0
  131. package/src/{store-Nl4uxEXx.js → store-DjJs3I7k.js} +12 -7
  132. package/src/store-DjJs3I7k.js.map +1 -0
  133. package/studio/CreateDocumentDialog-CTeIFlPb.js +256 -0
  134. package/studio/collaboration-DcK2F6v9.js +4566 -0
  135. package/studio/documentPlanning-Bfv-d7OU.js +29820 -0
  136. package/studio/dom-to-image-more.min-D6jGGdrW.js +877 -0
  137. package/studio/editor-Bzlh3zXt.js +30827 -0
  138. package/studio/host.css +3 -0
  139. package/studio/host.js +46614 -0
  140. package/studio/rolldown-runtime-B0aSnxlc.js +20 -0
  141. package/dist/studio/assets/ActivityEntryRow-D--fRvWI.js +0 -1
  142. package/dist/studio/assets/ActivityView-D-XBBUHb.js +0 -1
  143. package/dist/studio/assets/CreateDocumentDialog-CH8UH1QM.js +0 -1
  144. package/dist/studio/assets/DocumentsView-CxRpmAxt.js +0 -34
  145. package/dist/studio/assets/DropdownMenu-BSb1l7fr.js +0 -1
  146. package/dist/studio/assets/Input-DVao38h7.js +0 -3
  147. package/dist/studio/assets/MediaView-BHrPIjxB.js +0 -1
  148. package/dist/studio/assets/Modal-VNrXGa5C.js +0 -1
  149. package/dist/studio/assets/OverviewView-DfP6-mLZ.js +0 -1
  150. package/dist/studio/assets/Select-BJZIs9sY.js +0 -1
  151. package/dist/studio/assets/SettingsView-CerHe-ua.js +0 -1
  152. package/dist/studio/assets/Skeleton-CWJNi3nS.js +0 -1
  153. package/dist/studio/assets/StudioPageHeader-DP9HDAF2.js +0 -1
  154. package/dist/studio/assets/UsersView-cP3REkH2.js +0 -1
  155. package/dist/studio/assets/collaboration-BLnCzfvV.js +0 -4
  156. package/dist/studio/assets/context-dY4fNbn3.js +0 -1
  157. package/dist/studio/assets/editor-CE07wW83.js +0 -137
  158. package/dist/studio/assets/gateway-BAyQgCse.js +0 -10
  159. package/dist/studio/assets/index-CjoaPLhZ.js +0 -28
  160. package/dist/studio/assets/index-s2rPqCmP.css +0 -2
  161. package/dist/studio/assets/render-BkxbK2St.js +0 -83
  162. package/dist/studio/assets/rolldown-runtime-DK3Fl9T5.js +0 -1
  163. package/dist/studio/assets/useMediaLibrary-D7qR7aBf.js +0 -1
  164. package/dist/studio/index.html +0 -76
  165. package/src/AuthoringSchema-BQ5kbhVB.js.map +0 -1
  166. package/src/Configuration-BGYFD2N1.js +0 -150
  167. package/src/Configuration-BGYFD2N1.js.map +0 -1
  168. package/src/DocumentEngine-Da0kWotL.js.map +0 -1
  169. package/src/HttpPaths-86qLGB90.js +0 -15
  170. package/src/HttpPaths-86qLGB90.js.map +0 -1
  171. package/src/StudioHttp-BTLLooh0.js +0 -916
  172. package/src/StudioHttp-BTLLooh0.js.map +0 -1
  173. package/src/connection-ZGtL54qY.js.map +0 -1
  174. package/src/installation-BNKaVjni.js.map +0 -1
  175. package/src/internal/component-metadata.js +0 -37
  176. package/src/internal/component-metadata.js.map +0 -1
  177. package/src/metadata-Czvi3E4K.js.map +0 -1
  178. package/src/models-Citx8jBi.js +0 -306
  179. package/src/models-Citx8jBi.js.map +0 -1
  180. package/src/models-DS5ClMsH.js.map +0 -1
  181. package/src/store-Nl4uxEXx.js.map +0 -1
@@ -1,7 +1,10 @@
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";
1
+ import { r as FormCapabilities } from "./Forms-CfcI3tPU.js";
2
+ import { c as resolveCmsComarkAttributes, d as createCmsComarkRenderData, l as withCmsComarkProps, r as formStructureIssues, s as projectCmsEditorComponentAttributes } from "./Forms-DxbkU3_5.js";
3
+ import { C as MarkdownNode, Dt as Locale, Et as CollectionName, Ot as SourceDirectory, Tt as AddressPattern, n as CmsMarkdownDocument } from "./models-DwYioyNV.js";
4
+ import { a as createEditorNodeId, n as editorMetadata, o as editorNodeId } from "./metadata-BEZPWh-3.js";
3
5
  import { Effect, Option, Predicate, Schema } from "effect";
4
- import { resolveAttributes } from "comark/utils";
6
+ import { Extension } from "@tiptap/core";
7
+ import { ySyncPluginKey } from "@tiptap/y-tiptap";
5
8
  import { createMarkdownParser } from "comark/parse";
6
9
  import alert from "comark/plugins/alert";
7
10
  import attributes from "comark/plugins/attributes";
@@ -11,399 +14,7 @@ import headings from "comark/plugins/headings";
11
14
  import security from "comark/plugins/security";
12
15
  import taskList from "comark/plugins/task-list";
13
16
  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
17
 
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
18
  //#region ../document/src/internal/editor/attributes.ts
408
19
  function compactJsonAttributes(attributes) {
409
20
  return Object.fromEntries(Object.entries(attributes).filter((entry) => entry[1] !== void 0));
@@ -578,11 +189,11 @@ function decodeBlock(node, context, renderData) {
578
189
  content: decodeBlocks(children, context, childRenderData)
579
190
  };
580
191
  case "pre": {
581
- const code = children.find(isElementNode);
192
+ const code = children.find(isElementNode$1);
582
193
  return {
583
194
  type: "codeBlock",
584
195
  attrs: mergeJsonAttributes(commonAttrs, { language: nonEmptyStringAttribute(attrs.language) ?? nonEmptyStringAttribute(code?.[1].class)?.replace(/^language-/u, "") }),
585
- content: textContent$1(code ? elementChildren(code) : children)
196
+ content: textContent(code ? elementChildren(code) : children)
586
197
  };
587
198
  }
588
199
  case "hr": return {
@@ -643,7 +254,7 @@ function decodeSlot(node, context, renderData) {
643
254
  };
644
255
  }
645
256
  function decodeListItems(nodes, context, renderData) {
646
- return nodes.filter(isElementNode).filter((node) => node[0] === "li").map((node) => decodeBlock(node, context, renderData));
257
+ return nodes.flatMap((node) => isElementNode$1(node) && node[0] === "li" ? [decodeBlock(node, context, renderData)] : []);
647
258
  }
648
259
  function decodeInlines(nodes, context, renderData, inheritedMarks = []) {
649
260
  const result = [];
@@ -681,105 +292,368 @@ function decodeInlines(nodes, context, renderData, inheritedMarks = []) {
681
292
  result.push(withMarks({ type: "hardBreak" }, inheritedMarks));
682
293
  continue;
683
294
  }
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;
295
+ if (node[0] === "img") {
296
+ result.push(withMarks({
297
+ type: "image",
298
+ attrs: mergeJsonAttributes(decodeEditorImageAttributes(cleanAttrs(node[1])), { cmsNodeId: claimIdentity(context, node[1]) })
299
+ }, inheritedMarks));
300
+ continue;
301
+ }
302
+ result.push(withMarks({
303
+ type: "cmsInlineOpaque",
304
+ attrs: {
305
+ label: node[0],
306
+ node: stripInternalMetadata(node)
307
+ }
308
+ }, inheritedMarks));
309
+ }
310
+ return result;
311
+ }
312
+ function claimIdentity(context, attributes) {
313
+ return claimIdentityValue(context, attributes ? editorMetadata(attributes)?.nodeId : void 0);
314
+ }
315
+ function claimIdentityValue(context, candidate) {
316
+ const existing = editorNodeId(candidate);
317
+ if (existing !== void 0 && !context.usedIds.has(existing)) {
318
+ context.usedIds.add(existing);
319
+ return existing;
320
+ }
321
+ for (let attempt = 0; attempt < 100; attempt++) {
322
+ const created = createEditorNodeId();
323
+ if (!context.usedIds.has(created)) {
324
+ context.usedIds.add(created);
325
+ return created;
326
+ }
327
+ }
328
+ throw new Error("The editor identity factory did not produce a unique identity.");
329
+ }
330
+ function opaqueBlock(node, label, cmsNodeId) {
331
+ return {
332
+ type: "cmsOpaque",
333
+ attrs: {
334
+ cmsNodeId,
335
+ label,
336
+ node: stripInternalMetadata(node)
337
+ }
338
+ };
339
+ }
340
+ function stripInternalMetadata(node) {
341
+ if (node[0] === null) return [
342
+ null,
343
+ cleanAttrs(node[1]),
344
+ node[2]
345
+ ];
346
+ const [tag, attributes, ...children] = node;
347
+ return [
348
+ tag,
349
+ cleanAttrs(attributes),
350
+ ...children.map((child) => Predicate.isString(child) ? child : stripInternalMetadata(child))
351
+ ];
352
+ }
353
+ function slotContent(content) {
354
+ return content.length ? content : [{
355
+ type: "paragraph",
356
+ attrs: { cmsSynthetic: true }
357
+ }];
358
+ }
359
+ function slotName(attrs) {
360
+ return nonEmptyStringAttribute(attrs.name) ?? "default";
361
+ }
362
+ function cleanAttrs(attrs) {
363
+ const { $: _internal, "data-cms-node": _marker, ...clean } = attrs;
364
+ return structuredClone(clean);
365
+ }
366
+ function textContent(nodes) {
367
+ const text = nodes.map((node) => Predicate.isString(node) ? node : node[0] === null ? node[2] : textContent(elementChildren(node))?.map((child) => child.text ?? "").join("") ?? "").join("");
368
+ return text ? [{
369
+ type: "text",
370
+ text
371
+ }] : void 0;
372
+ }
373
+ function isInlineElement(node) {
374
+ return node[0] !== null && (isComarkMark(node[0]) || node[0] === "br" || node[0] === "img" || jsonObject(node[1].$).block === 0);
375
+ }
376
+ function isSlotTemplate(node) {
377
+ return isElementNode$1(node) && node[0] === "template";
378
+ }
379
+ function isElementNode$1(node) {
380
+ return Array.isArray(node) && Predicate.isString(node[0]);
381
+ }
382
+ function elementChildren(node) {
383
+ const [, , ...children] = node;
384
+ return children;
385
+ }
386
+ function jsonObject(value) {
387
+ return isJsonObject$1(value) ? value : {};
388
+ }
389
+ function mergeJsonAttributes(attributes, additions) {
390
+ return compactJsonAttributes(Object.assign({}, attributes, additions));
391
+ }
392
+ function withMarks(content, marks) {
393
+ return marks.length ? Object.assign({}, content, { marks }) : content;
394
+ }
395
+
396
+ //#endregion
397
+ //#region ../document/src/internal/comark/source-mapping.ts
398
+ const SOURCE_MAPPINGS_META_KEY = "__cmsSourceMappings";
399
+ const BLOCK_TAGS = /* @__PURE__ */ new Map([
400
+ ["blockquote_open", "blockquote"],
401
+ ["bullet_list_open", "ul"],
402
+ ["list_item_open", "li"],
403
+ ["ordered_list_open", "ol"],
404
+ ["paragraph_open", "p"],
405
+ ["table_open", "table"],
406
+ ["tbody_open", "tbody"],
407
+ ["td_open", "td"],
408
+ ["th_open", "th"],
409
+ ["thead_open", "thead"],
410
+ ["tr_open", "tr"]
411
+ ]);
412
+ const ComarkToken = Schema.Struct({
413
+ attrs: Schema.optionalKey(Schema.NullOr(Schema.Array(Schema.Tuple([Schema.String, Schema.String])))),
414
+ hidden: Schema.optionalKey(Schema.Boolean),
415
+ level: Schema.optionalKey(Schema.Finite),
416
+ map: Schema.optionalKey(Schema.NullOr(Schema.Tuple([Schema.Finite, Schema.Finite]))),
417
+ nesting: Schema.optionalKey(Schema.Finite),
418
+ tag: Schema.optionalKey(Schema.String),
419
+ type: Schema.optionalKey(Schema.String)
420
+ });
421
+ const WRAPPER_TAGS = /* @__PURE__ */ new Set([
422
+ "blockquote",
423
+ "ol",
424
+ "pre",
425
+ "table",
426
+ "ul"
427
+ ]);
428
+ function sourceCapturePlugin() {
429
+ return {
430
+ name: "cms-source-capture",
431
+ pre(state) {
432
+ state.__cmsOriginalMarkdown = state.markdown;
433
+ }
434
+ };
435
+ }
436
+ function sourceMappingPlugin() {
437
+ return {
438
+ name: "cms-source-mapping",
439
+ post(state) {
440
+ const source = state.__cmsOriginalMarkdown ?? state.markdown;
441
+ const descriptors = createBlockDescriptors(state.tokens.flatMap((token) => {
442
+ const decoded = Schema.decodeUnknownOption(ComarkToken)(token);
443
+ return Option.isSome(decoded) ? [decoded.value] : [];
444
+ }), source, state.markdown, state.parsedLines ?? 0);
445
+ const mappings = [];
446
+ mapNodes(state.tree.nodes, descriptors, [], mappings);
447
+ state.tree.meta[SOURCE_MAPPINGS_META_KEY] = mappings;
448
+ }
449
+ };
450
+ }
451
+ function createBlockDescriptors(tokens, source, parsedMarkdown, parsedLines) {
452
+ const roots = [];
453
+ const stack = [];
454
+ const sourceLineStarts = indexLineStarts(source);
455
+ const parsedLineStarts = indexLineStarts(parsedMarkdown);
456
+ const parsedOffset = source.lastIndexOf(parsedMarkdown);
457
+ const slotMaps = createSlotTokenMaps(tokens, parsedMarkdown);
458
+ for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex++) {
459
+ const token = tokens[tokenIndex];
460
+ if (!token) continue;
461
+ const tag = blockTag(token);
462
+ const tokenMap = token.map ?? slotMaps.get(tokenIndex);
463
+ if (!tag || !tokenMap) continue;
464
+ const level = token.level ?? 0;
465
+ while (true) {
466
+ const current = stack.at(-1);
467
+ if (!current || current.level < level) break;
468
+ stack.pop();
469
+ }
470
+ const descriptor = {
471
+ children: [],
472
+ range: rangeFromParsedLines(source, sourceLineStarts, parsedMarkdown, parsedLineStarts, parsedOffset, tokenMap[0], tokenMap[1] + (token.type === "mdc_block_open" ? 1 : 0), parsedLines),
473
+ tag
474
+ };
475
+ ((stack.at(-1)?.descriptor)?.children ?? roots).push(descriptor);
476
+ if (token.nesting === 1) stack.push({
477
+ descriptor,
478
+ level
479
+ });
480
+ }
481
+ return roots.map(collapseComarkWrapper).map(groupProjectedSlotContent);
482
+ }
483
+ function blockTag(token) {
484
+ if (token.hidden || !token.type) return void 0;
485
+ if (token.type === "heading_open") return token.tag;
486
+ if (token.type === "mdc_block_open" || token.type === "mdc_block_shorthand" && token.nesting !== -1) return token.tag || "component";
487
+ if (token.type === "mdc_block_slot" && token.nesting === 1) return "template";
488
+ if ([
489
+ "fence",
490
+ "fenced_code_block",
491
+ "code_block"
492
+ ].includes(token.type)) return "pre";
493
+ if (token.type === "math_block") return "math";
494
+ if (token.type === "html_block") return "*";
495
+ if (token.type === "hr") return "hr";
496
+ return BLOCK_TAGS.get(token.type);
497
+ }
498
+ function createSlotTokenMaps(tokens, parsedMarkdown) {
499
+ const maps = /* @__PURE__ */ new Map();
500
+ const markers = slotMarkers(parsedMarkdown);
501
+ const stack = [];
502
+ let nextMarker = 0;
503
+ for (let index = 0; index < tokens.length; index++) {
504
+ const token = tokens[index];
505
+ if (!token || token.type !== "mdc_block_slot") continue;
506
+ if (token.nesting === 1) {
507
+ const name = token.attrs?.[0]?.[0]?.replace(/^#/u, "");
508
+ let markerIndex = nextMarker;
509
+ while (markerIndex < markers.length && markers[markerIndex]?.name !== name) markerIndex++;
510
+ const marker = markers[markerIndex];
511
+ if (marker) {
512
+ stack.push({
513
+ index,
514
+ marker: marker.line
515
+ });
516
+ nextMarker = markerIndex + 1;
517
+ }
518
+ continue;
519
+ }
520
+ if (token.nesting !== -1) continue;
521
+ const open = stack.pop();
522
+ if (!open) continue;
523
+ let endLine = open.marker + 1;
524
+ for (let childIndex = open.index + 1; childIndex < index; childIndex++) {
525
+ const child = tokens[childIndex];
526
+ const map = child?.map ?? maps.get(childIndex);
527
+ if (child && map) endLine = Math.max(endLine, map[1] + (child.type === "mdc_block_open" ? 1 : 0));
690
528
  }
691
- result.push(withMarks({
692
- type: "cmsInlineOpaque",
693
- attrs: {
694
- label: node[0],
695
- node: stripInternalMetadata(node)
696
- }
697
- }, inheritedMarks));
529
+ maps.set(open.index, [open.marker, endLine]);
698
530
  }
699
- return result;
531
+ return maps;
700
532
  }
701
- function claimIdentity(context, attributes) {
702
- return claimIdentityValue(context, attributes ? editorMetadata(attributes)?.nodeId : void 0);
533
+ function slotMarkers(source) {
534
+ return source.split(/\r?\n/u).flatMap((line, index) => {
535
+ const name = line.match(/^\s*#([^\s{]+)/u)?.[1];
536
+ return name ? [{
537
+ line: index,
538
+ name
539
+ }] : [];
540
+ });
703
541
  }
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;
542
+ function collapseComarkWrapper(descriptor) {
543
+ const children = descriptor.children.map(collapseComarkWrapper);
544
+ if (WRAPPER_TAGS.has(descriptor.tag) && children.length === 1 && children[0]?.tag === descriptor.tag) return {
545
+ ...descriptor,
546
+ children: children[0].children
547
+ };
548
+ return {
549
+ ...descriptor,
550
+ children
551
+ };
552
+ }
553
+ /** Comark projects siblings after a named slot into that active slot. */
554
+ function groupProjectedSlotContent(descriptor) {
555
+ const grouped = [];
556
+ let activeSlot;
557
+ for (const rawChild of descriptor.children) {
558
+ const child = groupProjectedSlotContent(rawChild);
559
+ if (child.tag === "template") {
560
+ activeSlot = child;
561
+ grouped.push(child);
562
+ continue;
563
+ }
564
+ if (!activeSlot) {
565
+ grouped.push(child);
566
+ continue;
715
567
  }
568
+ activeSlot.children.push(child);
569
+ if (child.range.end.offset > activeSlot.range.end.offset) activeSlot.range = {
570
+ start: activeSlot.range.start,
571
+ end: child.range.end
572
+ };
716
573
  }
717
- throw new Error("The editor identity factory did not produce a unique identity.");
718
- }
719
- function opaqueBlock(node, label, cmsNodeId) {
720
574
  return {
721
- type: "cmsOpaque",
722
- attrs: {
723
- cmsNodeId,
724
- label,
725
- node: stripInternalMetadata(node)
726
- }
575
+ ...descriptor,
576
+ children: grouped
727
577
  };
728
578
  }
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";
579
+ function mapNodes(nodes, descriptors, parentPath, mappings) {
580
+ let descriptorIndex = 0;
581
+ for (let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++) {
582
+ const node = nodes[nodeIndex];
583
+ if (!node || !isElementNode(node)) continue;
584
+ let matchIndex = descriptorIndex;
585
+ while (matchIndex < descriptors.length && descriptors[matchIndex]?.tag !== "*" && descriptors[matchIndex]?.tag !== node[0]) matchIndex++;
586
+ const descriptor = descriptors[matchIndex];
587
+ if (!descriptor) continue;
588
+ descriptorIndex = matchIndex + 1;
589
+ const nodePath = [...parentPath, nodeIndex];
590
+ mappings.push({
591
+ nodePath,
592
+ range: descriptor.range
593
+ });
594
+ const [, , ...children] = node;
595
+ mapNodes(children, descriptor.children, nodePath, mappings);
596
+ }
767
597
  }
768
598
  function isElementNode(node) {
769
599
  return Array.isArray(node) && Predicate.isString(node[0]);
770
600
  }
771
- function elementChildren(node) {
772
- const [, , ...children] = node;
773
- return children;
601
+ function indexLineStarts(source) {
602
+ const starts = [0];
603
+ for (let offset = 0; offset < source.length; offset++) if (source.charCodeAt(offset) === 10) starts.push(offset + 1);
604
+ return starts;
774
605
  }
775
- function jsonObject(value) {
776
- return isJsonObject$1(value) ? value : {};
606
+ function rangeFromParsedLines(source, sourceLineStarts, parsedMarkdown, parsedLineStarts, parsedOffset, startLine, endLine, fallbackLineOffset) {
607
+ const startOffset = parsedOffset >= 0 ? parsedOffset + (parsedLineStarts[startLine] ?? parsedMarkdown.length) : sourceLineStarts[startLine + fallbackLineOffset] ?? source.length;
608
+ const endOffset = parsedOffset >= 0 ? parsedOffset + (parsedLineStarts[endLine] ?? parsedMarkdown.length) : sourceLineStarts[endLine + fallbackLineOffset] ?? source.length;
609
+ return {
610
+ start: pointAt(source, sourceLineStarts, startOffset),
611
+ end: pointAt(source, sourceLineStarts, Math.max(startOffset, endOffset))
612
+ };
777
613
  }
778
- function mergeJsonAttributes(attributes, additions) {
779
- return compactJsonAttributes(Object.assign({}, attributes, additions));
614
+ function pointAt(source, lineStarts, rawOffset) {
615
+ const offset = Math.min(Math.max(rawOffset, 0), source.length);
616
+ let low = 0;
617
+ let high = lineStarts.length - 1;
618
+ while (low < high) {
619
+ const middle = Math.ceil((low + high) / 2);
620
+ if ((lineStarts[middle] ?? source.length) <= offset) low = middle;
621
+ else high = middle - 1;
622
+ }
623
+ return {
624
+ offset,
625
+ line: low + 1,
626
+ column: offset - (lineStarts[low] ?? 0) + 1
627
+ };
780
628
  }
781
- function withMarks(content, marks) {
782
- return marks.length ? Object.assign({}, content, { marks }) : content;
629
+
630
+ //#endregion
631
+ //#region ../document/src/internal/comark/grammar.ts
632
+ /**
633
+ * Changes when parsing, normalization, or projection semantics change. Stored
634
+ * with compiled documents so migrations can identify stale derived content.
635
+ */
636
+ const DOCUMENT_ENGINE_FINGERPRINT = "comark@0.6.2/frontmatter+alert+task-list+components+attributes+security+headings+toc+source-mapping/v1";
637
+ function createDocumentParser() {
638
+ return createMarkdownParser({
639
+ autoClose: false,
640
+ registerDefaultPlugins: false,
641
+ plugins: [
642
+ sourceCapturePlugin(),
643
+ frontmatter(),
644
+ alert(),
645
+ taskList(),
646
+ components(),
647
+ attributes(),
648
+ security(),
649
+ headings(),
650
+ toc({
651
+ depth: 5,
652
+ searchDepth: 6
653
+ }),
654
+ sourceMappingPlugin()
655
+ ]
656
+ });
783
657
  }
784
658
 
785
659
  //#endregion
@@ -792,7 +666,6 @@ var EditorRenderFailed = class extends Schema.TaggedError()("EditorDocument.Rend
792
666
 
793
667
  //#endregion
794
668
  //#region ../document/src/AuthoringSchema.ts
795
- /** Compiles insertion content with the same grammar used for publication. */
796
669
  const parseAuthoringContent = Effect.fn("AuthoringSchema.parseContent")(function* (markdown) {
797
670
  const body = yield* Effect.tryPromise({
798
671
  try: () => createDocumentParser()(markdown),
@@ -804,14 +677,53 @@ const parseAuthoringContent = Effect.fn("AuthoringSchema.parseContent")(function
804
677
  return (yield* Schema.decodeUnknownEffect(CmsMarkdownDocument)(body)).nodes;
805
678
  });
806
679
  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)];
680
+ function collectionComponents(components, body) {
681
+ if (!body) return components;
682
+ return components.filter((component) => body.blocks?.includes(component.name) || component.authoring.group !== void 0 && body.groups?.includes(component.authoring.group));
683
+ }
684
+ /** Configuration errors belong to developers, before an installation adopts the catalog. */
685
+ function validateCollectionBody(components, body) {
686
+ return [
687
+ ...components.flatMap((component) => component.authoring.slots.flatMap((slot) => [...(slot.blocks ?? []).filter((name) => !components.some((candidate) => candidate.name === name)).map((name) => `Unknown block "${name}" in ${slot.label}.`), ...(slot.groups ?? []).filter((group) => !components.some((candidate) => candidate.authoring.group === group)).map((group) => `Unknown block group "${group}" in ${slot.label}.`)])),
688
+ ...(body?.blocks ?? []).filter((name) => !components.some((component) => component.name === name)).map((name) => `Unknown block "${name}".`),
689
+ ...(body?.groups ?? []).filter((group) => !components.some((component) => component.authoring.group === group)).map((group) => `Unknown block group "${group}".`)
690
+ ];
691
+ }
692
+ function contentIssues(node, schemas, allowed, purpose, collectionAllowed = allowed) {
693
+ const issues = [];
694
+ if (node.type === "cmsBlock") {
695
+ const name = String(node.attrs?.tag).toLowerCase();
696
+ const schema = schemas.get(name);
697
+ if (!schema) issues.push("This block is unavailable. Ask your site developer to restore its definition.");
698
+ else {
699
+ if (!allowed.has(name)) issues.push(`${schema.definition.label} is not allowed in this content region.`);
700
+ issues.push(...schema.validate(node, purpose));
701
+ if (purpose === "publish" && schema.definition.form) issues.push(...formStructureIssues(node.attrs?.props?.steps, schema.definition.form, name));
702
+ }
703
+ }
704
+ if (node.type === "cmsOpaque" || node.type === "cmsInlineOpaque") issues.push("This content is unsupported. Ask your site developer to update it before publishing.");
705
+ if (node.type === "cmsBlock") {
706
+ const schema = schemas.get(String(node.attrs?.tag).toLowerCase());
707
+ for (const region of node.content ?? []) {
708
+ const slot = schema?.definition.slots.find((candidate) => candidate.name === region.attrs?.name);
709
+ const permitted = slot?.input === "blocks" ? new Set(collectionComponents([...schemas].map(([name, schema]) => ({
710
+ name,
711
+ authoring: schema.definition
712
+ })), slot.blocks === void 0 && slot.groups === void 0 ? void 0 : slot).map((component) => component.name).filter((name) => collectionAllowed.has(name))) : collectionAllowed;
713
+ issues.push(...contentIssues(region, schemas, permitted, purpose, collectionAllowed));
714
+ }
715
+ return issues;
813
716
  }
814
- return comarkToEditor(body.nodes, createCmsComarkRenderData(body)).flatMap(visit);
717
+ return [...issues, ...(node.content ?? []).flatMap((child) => contentIssues(child, schemas, allowed, purpose, collectionAllowed))];
718
+ }
719
+ /** Resolves a component catalog once so document compilation can reuse its authoring rules. */
720
+ function createAuthoringDocumentValidator(components) {
721
+ const definitions = [...components.values()];
722
+ const schemas = new Map(definitions.map((component) => [component.name, createAuthoringSchema(component.name, component.authoring)]));
723
+ return (body, bodyPolicy) => {
724
+ const allowed = new Set(collectionComponents(definitions, bodyPolicy).map((component) => component.name));
725
+ return comarkToEditor(body.nodes, createCmsComarkRenderData(body)).flatMap((node) => contentIssues(node, schemas, allowed, "publish"));
726
+ };
815
727
  }
816
728
  function createAuthoringSchema(name, definition) {
817
729
  const fields = new Map(definition.props.map((field) => [field.name, field]));
@@ -902,10 +814,36 @@ function createAuthoringSchema(name, definition) {
902
814
  function propertyIssue(field, value, purpose) {
903
815
  if (value === void 0) return field.required && purpose === "publish" ? `${field.label} is required.` : void 0;
904
816
  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}.`;
817
+ let valid;
818
+ if (field.type === "string") valid = Predicate.isString(value);
819
+ else if (field.type === "number") valid = Predicate.isNumber(value) && Number.isFinite(value);
820
+ else if (field.type === "boolean") valid = Predicate.isBoolean(value);
821
+ else if (field.type === "array") valid = Array.isArray(value);
822
+ else valid = isJsonObject(value);
823
+ if (!valid) return `${field.label} must be ${field.type}.`;
824
+ if (field.type === "object" || field.type === "array") {
825
+ const entries = Array.isArray(value) ? value : [value];
826
+ const ids = /* @__PURE__ */ new Set();
827
+ for (const entry of entries) {
828
+ if (!isJsonObject(entry)) return `${field.label} must contain objects.`;
829
+ if (field.type === "array") {
830
+ const id = entry.id;
831
+ if (!Predicate.isString(id) || !id || ids.has(id)) return `${field.label} items need unique identities.`;
832
+ ids.add(id);
833
+ }
834
+ for (const key of Object.keys(entry)) if (!(field.type === "array" && key === "id") && !field.fields?.some((child) => child.name === key)) return `${field.label} contains an unavailable field.`;
835
+ for (const child of field.fields ?? []) {
836
+ const issue = propertyIssue(child, entry[child.name], purpose);
837
+ if (issue) return `${field.label}: ${issue}`;
838
+ }
839
+ }
840
+ }
841
+ if (purpose === "publish" && field.required && value === "" && (field.input === "image" || field.input === "link")) return `${field.label} is required.`;
842
+ if (purpose === "publish" && Predicate.isString(value) && value && (field.input === "image" || field.input === "link") && !validAuthoringUrl(value, field.input)) return `${field.label} needs a valid ${field.input === "image" ? "image URL" : "link"}.`;
906
843
  if (field.options.length && !field.options.some((option) => option.value === value)) return `${field.label} must use one of its available choices.`;
907
844
  }
908
845
  function validRegion(slot, content) {
846
+ if (slot.input === "blocks") return content.every((node) => node.type === "cmsBlock" || node.type === "paragraph" && !node.content?.length);
909
847
  const types = /* @__PURE__ */ new Set([
910
848
  "paragraph",
911
849
  "text",
@@ -920,7 +858,176 @@ function validRegion(slot, content) {
920
858
  const valid = (node) => types.has(node.type ?? "") && (node.marks ?? []).every((mark) => marks.has(mark.type)) && (node.content ?? []).every(valid);
921
859
  return content.every(valid);
922
860
  }
861
+ /** URL values remain ordinary Vue strings and use the document model's public paths. */
862
+ function validAuthoringUrl(value, input) {
863
+ if (value.trim() !== value || value.includes("\\")) return false;
864
+ for (const character of value) if (character.charCodeAt(0) <= 32) return false;
865
+ if (value.startsWith("/") && !value.startsWith("//")) return true;
866
+ if (input === "link" && value.startsWith("#")) return true;
867
+ try {
868
+ const url = new URL(value);
869
+ return [
870
+ "https:",
871
+ "http:",
872
+ ...input === "link" ? ["mailto:", "tel:"] : []
873
+ ].includes(url.protocol);
874
+ } catch {
875
+ return false;
876
+ }
877
+ }
878
+
879
+ //#endregion
880
+ //#region ../protocol/src/Authoring.ts
881
+ const BlockProp = Schema.Struct({
882
+ name: Schema.NonEmptyString,
883
+ label: Schema.NonEmptyString,
884
+ help: Schema.optionalKey(Schema.String),
885
+ type: Schema.Literals([
886
+ "string",
887
+ "number",
888
+ "boolean",
889
+ "object",
890
+ "array"
891
+ ]),
892
+ input: Schema.Literals([
893
+ "text",
894
+ "textarea",
895
+ "select",
896
+ "number",
897
+ "toggle",
898
+ "image",
899
+ "link",
900
+ "object",
901
+ "list"
902
+ ]),
903
+ required: Schema.Boolean,
904
+ nullable: Schema.Boolean,
905
+ defaultValue: Schema.optionalKey(Schema.Json),
906
+ fields: Schema.optionalKey(Schema.Array(Schema.suspend(() => BlockProp))),
907
+ options: Schema.Array(Schema.Struct({
908
+ value: Schema.String,
909
+ label: Schema.String
910
+ }))
911
+ });
912
+ const BlockSlot = Schema.Struct({
913
+ name: Schema.NonEmptyString,
914
+ label: Schema.NonEmptyString,
915
+ help: Schema.optionalKey(Schema.String),
916
+ required: Schema.Boolean,
917
+ input: Schema.Literals([
918
+ "text",
919
+ "rich-text",
920
+ "blocks"
921
+ ]),
922
+ blocks: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),
923
+ groups: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),
924
+ features: Schema.Array(Schema.Literals([
925
+ "bold",
926
+ "italic",
927
+ "link",
928
+ "bullet-list",
929
+ "code"
930
+ ])),
931
+ initial: Schema.optionalKey(Schema.Array(MarkdownNode))
932
+ });
933
+ const BlockAuthoring = Schema.Struct({
934
+ version: Schema.Literal(1),
935
+ form: Schema.optionalKey(FormCapabilities),
936
+ label: Schema.NonEmptyString,
937
+ description: Schema.optionalKey(Schema.String),
938
+ group: Schema.optionalKey(Schema.String),
939
+ icon: Schema.optionalKey(Schema.String),
940
+ props: Schema.Array(BlockProp),
941
+ slots: Schema.Array(BlockSlot),
942
+ initialProps: Schema.JsonObject
943
+ });
944
+
945
+ //#endregion
946
+ //#region ../protocol/src/Configuration.ts
947
+ const fieldPresentation = {
948
+ path: Schema.NonEmptyString,
949
+ label: Schema.NonEmptyString,
950
+ description: Schema.optionalKey(Schema.String),
951
+ defaultValue: Schema.optionalKey(Schema.Json),
952
+ required: Schema.Boolean
953
+ };
954
+ const BooleanAuthoringField = Schema.Struct({
955
+ type: Schema.tag("boolean"),
956
+ ...fieldPresentation,
957
+ input: Schema.Literal("toggle")
958
+ });
959
+ const DateAuthoringField = Schema.Struct({
960
+ type: Schema.tag("date"),
961
+ ...fieldPresentation,
962
+ input: Schema.Literal("date")
963
+ });
964
+ const NumberAuthoringField = Schema.Struct({
965
+ type: Schema.tag("number"),
966
+ ...fieldPresentation,
967
+ input: Schema.Literals(["number", "select"]),
968
+ options: Schema.Array(Schema.Finite)
969
+ });
970
+ const StringAuthoringField = Schema.Struct({
971
+ type: Schema.tag("string"),
972
+ ...fieldPresentation,
973
+ input: Schema.Literals([
974
+ "select",
975
+ "text",
976
+ "textarea"
977
+ ]),
978
+ options: Schema.Array(Schema.String)
979
+ });
980
+ const StringArrayAuthoringField = Schema.Struct({
981
+ type: Schema.tag("string[]"),
982
+ ...fieldPresentation,
983
+ input: Schema.Literal("multiselect"),
984
+ options: Schema.Array(Schema.String)
985
+ });
986
+ const DocumentField = Schema.Union([
987
+ BooleanAuthoringField,
988
+ DateAuthoringField,
989
+ NumberAuthoringField,
990
+ StringArrayAuthoringField,
991
+ StringAuthoringField
992
+ ]);
993
+ const CollectionBody = Schema.Struct({
994
+ blocks: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),
995
+ groups: Schema.optionalKey(Schema.Array(Schema.NonEmptyString))
996
+ });
997
+ const CollectionDefinition = Schema.Struct({
998
+ collection: CollectionName,
999
+ body: Schema.optionalKey(CollectionBody),
1000
+ label: Schema.NonEmptyString,
1001
+ description: Schema.String,
1002
+ directory: SourceDirectory,
1003
+ addressPattern: AddressPattern,
1004
+ hierarchy: Schema.Boolean,
1005
+ canCreate: Schema.Boolean,
1006
+ authoringFields: Schema.Array(DocumentField)
1007
+ }).annotate({ identifier: "CollectionDefinition" });
1008
+ const LocaleConfiguration = Schema.Struct({
1009
+ locales: Schema.Array(Locale),
1010
+ defaultLocale: Locale,
1011
+ fallbackLocale: Schema.NullOr(Locale),
1012
+ prefixDefaultLocale: Schema.Boolean
1013
+ }).annotate({ identifier: "LocaleConfiguration" });
1014
+ const DocumentConfiguration = Schema.Struct({
1015
+ types: Schema.Array(CollectionDefinition),
1016
+ locales: Schema.optionalKey(LocaleConfiguration)
1017
+ }).annotate({ identifier: "DocumentConfiguration" });
1018
+ const ComponentDefinition = Schema.Struct({
1019
+ authoring: BlockAuthoring,
1020
+ name: Schema.NonEmptyString
1021
+ }).annotate({ identifier: "ComponentDefinition" });
1022
+ const AuthoringCatalog = Schema.Struct({
1023
+ revision: Schema.NonEmptyString,
1024
+ components: Schema.Array(ComponentDefinition)
1025
+ });
1026
+ const MediaConfiguration = Schema.Struct({
1027
+ enabled: Schema.Boolean,
1028
+ maxUploadBytes: Schema.Int.check(Schema.isGreaterThan(0))
1029
+ });
923
1030
 
924
1031
  //#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
1032
+ export { finiteNumberAttribute as C, compactJsonAttributes as S, comarkTagForEditorMark as _, BlockAuthoring as a, encodeEditorImageAttributes as b, parseAuthoringContent as c, EditorRenderFailed as d, DOCUMENT_ENGINE_FINGERPRINT as f, EDITOR_MARK_TYPES as g, comarkToEditor as h, MediaConfiguration as i, validateCollectionBody as l, SOURCE_MAPPINGS_META_KEY as m, ComponentDefinition as n, createAuthoringDocumentValidator as o, createDocumentParser as p, DocumentConfiguration as r, createAuthoringSchema as s, AuthoringCatalog as t, EditorDocumentInvalid as u, isEditorMark as v, nonEmptyStringAttribute as w, normalizeEditorImageLayout as x, EDITOR_IMAGE_LAYOUT_ATTRIBUTE as y };
1033
+ //# sourceMappingURL=Configuration-CA_jvQKG.js.map