@phtngyn/cms 0.1.0-beta.0 → 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -1
- package/package.json +5 -5
- package/src/Authoring.d.ts +13 -1
- package/src/{AuthoringSchema-BQ5kbhVB.js → Configuration-DyKo0sLS.js} +595 -367
- package/src/Configuration-DyKo0sLS.js.map +1 -0
- package/src/{DocumentEngine-Da0kWotL.js → DocumentEngine-DYObwMDY.js} +44 -66
- package/src/DocumentEngine-DYObwMDY.js.map +1 -0
- package/src/DocumentModel.d.ts +4 -0
- package/src/DocumentModel.js.map +1 -1
- package/src/{HttpPaths-86qLGB90.js → HttpPaths-BbS21Jy8.js} +4 -2
- package/src/{HttpPaths-86qLGB90.js.map → HttpPaths-BbS21Jy8.js.map} +1 -1
- package/src/Module.js +27 -76
- package/src/Module.js.map +1 -1
- package/src/{StudioHttp-BTLLooh0.js → StudioHttp-jR2-bc01.js} +44 -242
- package/src/StudioHttp-jR2-bc01.js.map +1 -0
- package/src/{connection-ZGtL54qY.js → connection-CBTY-TzB.js} +3 -3
- package/src/{connection-ZGtL54qY.js.map → connection-CBTY-TzB.js.map} +1 -1
- package/src/{installation-BNKaVjni.js → installation-DeuBiFRE.js} +488 -236
- package/src/installation-DeuBiFRE.js.map +1 -0
- package/src/internal/authoring-catalog.js +147 -0
- package/src/internal/authoring-catalog.js.map +1 -0
- package/src/internal/authoring-compiler.js +2 -1
- package/src/internal/authoring-compiler.js.map +1 -1
- package/src/internal/authoring-metadata.js +67 -48
- package/src/internal/authoring-metadata.js.map +1 -1
- package/src/internal/configuration.js +5 -6
- package/src/internal/configuration.js.map +1 -1
- package/src/internal/document-model.js +3 -2
- package/src/internal/document-model.js.map +1 -1
- package/src/internal/studio-app.js +66 -0
- package/src/internal/studio-app.js.map +1 -0
- package/src/location-DtYv2aes.js +36 -0
- package/src/location-DtYv2aes.js.map +1 -0
- package/src/{metadata-Czvi3E4K.js → metadata-DE1Mc2td.js} +2 -2
- package/src/{metadata-Czvi3E4K.js.map → metadata-DE1Mc2td.js.map} +1 -1
- package/src/{models-Citx8jBi.js → models-BkMgeaOL.js} +252 -3
- package/src/models-BkMgeaOL.js.map +1 -0
- package/src/{models-DS5ClMsH.js → models-C3witQBK.js} +8 -31
- package/src/models-C3witQBK.js.map +1 -0
- package/src/runtime/blocks.js +17 -0
- package/src/runtime/blocks.js.map +1 -0
- package/src/runtime/collaboration.js +9 -4
- package/src/runtime/collaboration.js.map +1 -1
- package/src/runtime/delivery/DocumentRenderer.js +6 -3
- package/src/runtime/delivery/DocumentRenderer.js.map +1 -1
- package/src/runtime/delivery/blocks.js +6 -0
- package/src/runtime/delivery/blocks.js.map +1 -0
- package/src/runtime/delivery/context.js +12 -0
- package/src/runtime/delivery/context.js.map +1 -0
- package/src/runtime/delivery/document-page.js +5 -3
- package/src/runtime/delivery/document-page.js.map +1 -1
- package/src/runtime/delivery/document.js +18 -2
- package/src/runtime/delivery/document.js.map +1 -1
- package/src/runtime/delivery/error.js +11 -0
- package/src/runtime/delivery/error.js.map +1 -0
- package/src/runtime/delivery/plugin.js +21 -0
- package/src/runtime/delivery/plugin.js.map +1 -0
- package/src/runtime/delivery/useDocument.js +6 -3
- package/src/runtime/delivery/useDocument.js.map +1 -1
- package/src/runtime/delivery/useDocumentQuery.js +6 -3
- package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
- package/src/runtime/installation.js +1 -1
- package/src/runtime/plugin.js +3 -3
- package/src/runtime/plugin.js.map +1 -1
- package/src/runtime/preview/connection.js +1 -1
- package/src/runtime/preview/controller.js +29 -10
- package/src/runtime/preview/controller.js.map +1 -1
- package/src/runtime/preview/overlay.js +65 -0
- package/src/runtime/preview/overlay.js.map +1 -0
- package/src/runtime/preview/plugin.client.js +21 -34
- package/src/runtime/preview/plugin.client.js.map +1 -1
- package/src/runtime/preview/preview.css +72 -4
- package/src/runtime/preview/store.js +1 -1
- package/src/runtime/studio-app.js +5 -1
- package/src/runtime/studio-app.js.map +1 -1
- package/src/runtime/studio-entry.js +36 -0
- package/src/runtime/studio-entry.js.map +1 -0
- package/src/runtime/studio-navigation.js +11 -0
- package/src/runtime/studio-navigation.js.map +1 -0
- package/src/{store-Nl4uxEXx.js → store-CfFFx9Ua.js} +3 -3
- package/src/{store-Nl4uxEXx.js.map → store-CfFFx9Ua.js.map} +1 -1
- package/studio/CreateDocumentDialog--L9lTfx6.js +256 -0
- package/studio/collaboration-DUuu678R.js +4565 -0
- package/studio/documentPlanning-BXX04Woe.js +28989 -0
- package/studio/dom-to-image-more.min-D6jGGdrW.js +877 -0
- package/studio/editor-PexnXkJY.js +30817 -0
- package/studio/host.css +3 -0
- package/studio/host.js +44179 -0
- package/studio/rolldown-runtime-B0aSnxlc.js +20 -0
- package/dist/studio/assets/ActivityEntryRow-D--fRvWI.js +0 -1
- package/dist/studio/assets/ActivityView-D-XBBUHb.js +0 -1
- package/dist/studio/assets/CreateDocumentDialog-CH8UH1QM.js +0 -1
- package/dist/studio/assets/DocumentsView-CxRpmAxt.js +0 -34
- package/dist/studio/assets/DropdownMenu-BSb1l7fr.js +0 -1
- package/dist/studio/assets/Input-DVao38h7.js +0 -3
- package/dist/studio/assets/MediaView-BHrPIjxB.js +0 -1
- package/dist/studio/assets/Modal-VNrXGa5C.js +0 -1
- package/dist/studio/assets/OverviewView-DfP6-mLZ.js +0 -1
- package/dist/studio/assets/Select-BJZIs9sY.js +0 -1
- package/dist/studio/assets/SettingsView-CerHe-ua.js +0 -1
- package/dist/studio/assets/Skeleton-CWJNi3nS.js +0 -1
- package/dist/studio/assets/StudioPageHeader-DP9HDAF2.js +0 -1
- package/dist/studio/assets/UsersView-cP3REkH2.js +0 -1
- package/dist/studio/assets/collaboration-BLnCzfvV.js +0 -4
- package/dist/studio/assets/context-dY4fNbn3.js +0 -1
- package/dist/studio/assets/editor-CE07wW83.js +0 -137
- package/dist/studio/assets/gateway-BAyQgCse.js +0 -10
- package/dist/studio/assets/index-CjoaPLhZ.js +0 -28
- package/dist/studio/assets/index-s2rPqCmP.css +0 -2
- package/dist/studio/assets/render-BkxbK2St.js +0 -83
- package/dist/studio/assets/rolldown-runtime-DK3Fl9T5.js +0 -1
- package/dist/studio/assets/useMediaLibrary-D7qR7aBf.js +0 -1
- package/dist/studio/index.html +0 -76
- package/src/AuthoringSchema-BQ5kbhVB.js.map +0 -1
- package/src/Configuration-BGYFD2N1.js +0 -150
- package/src/Configuration-BGYFD2N1.js.map +0 -1
- package/src/DocumentEngine-Da0kWotL.js.map +0 -1
- package/src/StudioHttp-BTLLooh0.js.map +0 -1
- package/src/installation-BNKaVjni.js.map +0 -1
- package/src/internal/component-metadata.js +0 -37
- package/src/internal/component-metadata.js.map +0 -1
- package/src/models-Citx8jBi.js.map +0 -1
- package/src/models-DS5ClMsH.js.map +0 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { n as CmsMarkdownDocument } from "./models-
|
|
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-
|
|
1
|
+
import { C as MarkdownNode, dt as Locale, ft as SourceDirectory, lt as AddressPattern, n as CmsMarkdownDocument, ut as CollectionName } from "./models-BkMgeaOL.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-DE1Mc2td.js";
|
|
3
3
|
import { Effect, Option, Predicate, Schema } from "effect";
|
|
4
|
+
import { Extension } from "@tiptap/core";
|
|
5
|
+
import { ySyncPluginKey } from "@tiptap/y-tiptap";
|
|
4
6
|
import { resolveAttributes } from "comark/utils";
|
|
5
7
|
import { createMarkdownParser } from "comark/parse";
|
|
6
8
|
import alert from "comark/plugins/alert";
|
|
@@ -11,8 +13,6 @@ import headings from "comark/plugins/headings";
|
|
|
11
13
|
import security from "comark/plugins/security";
|
|
12
14
|
import taskList from "comark/plugins/task-list";
|
|
13
15
|
import toc from "comark/plugins/toc";
|
|
14
|
-
import { Extension } from "@tiptap/core";
|
|
15
|
-
import { ySyncPluginKey } from "@tiptap/y-tiptap";
|
|
16
16
|
|
|
17
17
|
//#region ../document/src/internal/comark/bindings.ts
|
|
18
18
|
const isJsonObject$3 = Schema.is(Schema.JsonObject);
|
|
@@ -95,10 +95,10 @@ function normalizeCmsComponentBindings(document, components) {
|
|
|
95
95
|
}
|
|
96
96
|
function matchesCmsComponentPropType(value, type) {
|
|
97
97
|
switch (type) {
|
|
98
|
+
case "object": return isJsonObject$3(value);
|
|
98
99
|
case "array": return Array.isArray(value);
|
|
99
100
|
case "boolean": return Predicate.isBoolean(value);
|
|
100
101
|
case "number": return Predicate.isNumber(value);
|
|
101
|
-
case "object": return isJsonObject$3(value);
|
|
102
102
|
case "string": return Predicate.isString(value);
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -107,7 +107,7 @@ function normalizeComponentNode(node, components) {
|
|
|
107
107
|
const [tag, originalAttributes, ...originalChildren] = node;
|
|
108
108
|
const attributes = mutableJsonObject(originalAttributes);
|
|
109
109
|
const definition = components.get(tag.toLocaleLowerCase());
|
|
110
|
-
if (definition) for (const prop of definition.props) {
|
|
110
|
+
if (definition) for (const prop of definition.authoring.props) {
|
|
111
111
|
if (prop.type === "string" || `:${prop.name}` in attributes || !(prop.name in attributes)) continue;
|
|
112
112
|
const value = attributes[prop.name];
|
|
113
113
|
if (Predicate.isUndefined(value)) continue;
|
|
@@ -137,272 +137,6 @@ function sameJson(left, right) {
|
|
|
137
137
|
return !Predicate.isUndefined(right) && JSON.stringify(left) === JSON.stringify(right);
|
|
138
138
|
}
|
|
139
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
140
|
//#endregion
|
|
407
141
|
//#region ../document/src/internal/editor/attributes.ts
|
|
408
142
|
function compactJsonAttributes(attributes) {
|
|
@@ -578,7 +312,7 @@ function decodeBlock(node, context, renderData) {
|
|
|
578
312
|
content: decodeBlocks(children, context, childRenderData)
|
|
579
313
|
};
|
|
580
314
|
case "pre": {
|
|
581
|
-
const code = children.find(isElementNode);
|
|
315
|
+
const code = children.find(isElementNode$1);
|
|
582
316
|
return {
|
|
583
317
|
type: "codeBlock",
|
|
584
318
|
attrs: mergeJsonAttributes(commonAttrs, { language: nonEmptyStringAttribute(attrs.language) ?? nonEmptyStringAttribute(code?.[1].class)?.replace(/^language-/u, "") }),
|
|
@@ -643,7 +377,7 @@ function decodeSlot(node, context, renderData) {
|
|
|
643
377
|
};
|
|
644
378
|
}
|
|
645
379
|
function decodeListItems(nodes, context, renderData) {
|
|
646
|
-
return nodes.filter(isElementNode).filter((node) => node[0] === "li").map((node) => decodeBlock(node, context, renderData));
|
|
380
|
+
return nodes.filter(isElementNode$1).filter((node) => node[0] === "li").map((node) => decodeBlock(node, context, renderData));
|
|
647
381
|
}
|
|
648
382
|
function decodeInlines(nodes, context, renderData, inheritedMarks = []) {
|
|
649
383
|
const result = [];
|
|
@@ -681,105 +415,371 @@ function decodeInlines(nodes, context, renderData, inheritedMarks = []) {
|
|
|
681
415
|
result.push(withMarks({ type: "hardBreak" }, inheritedMarks));
|
|
682
416
|
continue;
|
|
683
417
|
}
|
|
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;
|
|
418
|
+
if (node[0] === "img") {
|
|
419
|
+
result.push(withMarks({
|
|
420
|
+
type: "image",
|
|
421
|
+
attrs: mergeJsonAttributes(decodeEditorImageAttributes(cleanAttrs(node[1])), { cmsNodeId: claimIdentity(context, node[1]) })
|
|
422
|
+
}, inheritedMarks));
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
result.push(withMarks({
|
|
426
|
+
type: "cmsInlineOpaque",
|
|
427
|
+
attrs: {
|
|
428
|
+
label: node[0],
|
|
429
|
+
node: stripInternalMetadata(node)
|
|
430
|
+
}
|
|
431
|
+
}, inheritedMarks));
|
|
432
|
+
}
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
function claimIdentity(context, attributes) {
|
|
436
|
+
return claimIdentityValue(context, attributes ? editorMetadata(attributes)?.nodeId : void 0);
|
|
437
|
+
}
|
|
438
|
+
function claimIdentityValue(context, candidate) {
|
|
439
|
+
const existing = editorNodeId(candidate);
|
|
440
|
+
if (existing !== void 0 && !context.usedIds.has(existing)) {
|
|
441
|
+
context.usedIds.add(existing);
|
|
442
|
+
return existing;
|
|
443
|
+
}
|
|
444
|
+
for (let attempt = 0; attempt < 100; attempt++) {
|
|
445
|
+
const created = createEditorNodeId();
|
|
446
|
+
if (!context.usedIds.has(created)) {
|
|
447
|
+
context.usedIds.add(created);
|
|
448
|
+
return created;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
throw new Error("The editor identity factory did not produce a unique identity.");
|
|
452
|
+
}
|
|
453
|
+
function opaqueBlock(node, label, cmsNodeId) {
|
|
454
|
+
return {
|
|
455
|
+
type: "cmsOpaque",
|
|
456
|
+
attrs: {
|
|
457
|
+
cmsNodeId,
|
|
458
|
+
label,
|
|
459
|
+
node: stripInternalMetadata(node)
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
function stripInternalMetadata(node) {
|
|
464
|
+
if (node[0] === null) return [
|
|
465
|
+
null,
|
|
466
|
+
cleanAttrs(node[1]),
|
|
467
|
+
node[2]
|
|
468
|
+
];
|
|
469
|
+
const [tag, attributes, ...children] = node;
|
|
470
|
+
return [
|
|
471
|
+
tag,
|
|
472
|
+
cleanAttrs(attributes),
|
|
473
|
+
...children.map((child) => Predicate.isString(child) ? child : stripInternalMetadata(child))
|
|
474
|
+
];
|
|
475
|
+
}
|
|
476
|
+
function slotContent(content) {
|
|
477
|
+
return content.length ? content : [{
|
|
478
|
+
type: "paragraph",
|
|
479
|
+
attrs: { cmsSynthetic: true }
|
|
480
|
+
}];
|
|
481
|
+
}
|
|
482
|
+
function slotName(attrs) {
|
|
483
|
+
return nonEmptyStringAttribute(attrs.name) ?? "default";
|
|
484
|
+
}
|
|
485
|
+
function cleanAttrs(attrs) {
|
|
486
|
+
const { $: _internal, "data-cms-node": _marker, ...clean } = attrs;
|
|
487
|
+
return structuredClone(clean);
|
|
488
|
+
}
|
|
489
|
+
function textContent$1(nodes) {
|
|
490
|
+
const text = nodes.map((node) => Predicate.isString(node) ? node : node[0] === null ? node[2] : textContent$1(elementChildren(node))?.map((child) => child.text ?? "").join("") ?? "").join("");
|
|
491
|
+
return text ? [{
|
|
492
|
+
type: "text",
|
|
493
|
+
text
|
|
494
|
+
}] : void 0;
|
|
495
|
+
}
|
|
496
|
+
function isInlineElement(node) {
|
|
497
|
+
return node[0] !== null && (isComarkMark(node[0]) || node[0] === "br" || node[0] === "img" || jsonObject(node[1].$).block === 0);
|
|
498
|
+
}
|
|
499
|
+
function isSlotTemplate(node) {
|
|
500
|
+
return isElementNode$1(node) && node[0] === "template";
|
|
501
|
+
}
|
|
502
|
+
function isElementNode$1(node) {
|
|
503
|
+
return Array.isArray(node) && Predicate.isString(node[0]);
|
|
504
|
+
}
|
|
505
|
+
function elementChildren(node) {
|
|
506
|
+
const [, , ...children] = node;
|
|
507
|
+
return children;
|
|
508
|
+
}
|
|
509
|
+
function jsonObject(value) {
|
|
510
|
+
return isJsonObject$1(value) ? value : {};
|
|
511
|
+
}
|
|
512
|
+
function mergeJsonAttributes(attributes, additions) {
|
|
513
|
+
return compactJsonAttributes(Object.assign({}, attributes, additions));
|
|
514
|
+
}
|
|
515
|
+
function withMarks(content, marks) {
|
|
516
|
+
return marks.length ? Object.assign({}, content, { marks }) : content;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
//#endregion
|
|
520
|
+
//#region ../document/src/internal/comark/source-mapping.ts
|
|
521
|
+
const SOURCE_MAPPINGS_META_KEY = "__cmsSourceMappings";
|
|
522
|
+
const BLOCK_TAGS = /* @__PURE__ */ new Map([
|
|
523
|
+
["blockquote_open", "blockquote"],
|
|
524
|
+
["bullet_list_open", "ul"],
|
|
525
|
+
["list_item_open", "li"],
|
|
526
|
+
["ordered_list_open", "ol"],
|
|
527
|
+
["paragraph_open", "p"],
|
|
528
|
+
["table_open", "table"],
|
|
529
|
+
["tbody_open", "tbody"],
|
|
530
|
+
["td_open", "td"],
|
|
531
|
+
["th_open", "th"],
|
|
532
|
+
["thead_open", "thead"],
|
|
533
|
+
["tr_open", "tr"]
|
|
534
|
+
]);
|
|
535
|
+
const ComarkToken = Schema.Struct({
|
|
536
|
+
attrs: Schema.optionalKey(Schema.NullOr(Schema.Array(Schema.Tuple([Schema.String, Schema.String])))),
|
|
537
|
+
hidden: Schema.optionalKey(Schema.Boolean),
|
|
538
|
+
level: Schema.optionalKey(Schema.Finite),
|
|
539
|
+
map: Schema.optionalKey(Schema.NullOr(Schema.Tuple([Schema.Finite, Schema.Finite]))),
|
|
540
|
+
nesting: Schema.optionalKey(Schema.Finite),
|
|
541
|
+
tag: Schema.optionalKey(Schema.String),
|
|
542
|
+
type: Schema.optionalKey(Schema.String)
|
|
543
|
+
});
|
|
544
|
+
const WRAPPER_TAGS = /* @__PURE__ */ new Set([
|
|
545
|
+
"blockquote",
|
|
546
|
+
"ol",
|
|
547
|
+
"pre",
|
|
548
|
+
"table",
|
|
549
|
+
"ul"
|
|
550
|
+
]);
|
|
551
|
+
/** Captures the durable source before frontmatter or other pre-parse stages mutate it. */
|
|
552
|
+
function sourceCapturePlugin() {
|
|
553
|
+
return {
|
|
554
|
+
name: "cms-source-capture",
|
|
555
|
+
pre(state) {
|
|
556
|
+
state.__cmsOriginalMarkdown = state.markdown;
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
/** Translate Comark block token line maps into exact JavaScript source offsets. */
|
|
561
|
+
function sourceMappingPlugin() {
|
|
562
|
+
return {
|
|
563
|
+
name: "cms-source-mapping",
|
|
564
|
+
post(state) {
|
|
565
|
+
const source = state.__cmsOriginalMarkdown ?? state.markdown;
|
|
566
|
+
const descriptors = createBlockDescriptors(state.tokens.flatMap((token) => {
|
|
567
|
+
const decoded = Schema.decodeUnknownOption(ComarkToken)(token);
|
|
568
|
+
return decoded._tag === "Some" ? [decoded.value] : [];
|
|
569
|
+
}), source, state.markdown, state.parsedLines ?? 0);
|
|
570
|
+
const mappings = [];
|
|
571
|
+
mapNodes(state.tree.nodes, descriptors, [], mappings);
|
|
572
|
+
state.tree.meta[SOURCE_MAPPINGS_META_KEY] = mappings;
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
function createBlockDescriptors(tokens, source, parsedMarkdown, parsedLines) {
|
|
577
|
+
const roots = [];
|
|
578
|
+
const stack = [];
|
|
579
|
+
const sourceLineStarts = indexLineStarts(source);
|
|
580
|
+
const parsedLineStarts = indexLineStarts(parsedMarkdown);
|
|
581
|
+
const parsedOffset = source.lastIndexOf(parsedMarkdown);
|
|
582
|
+
const slotMaps = createSlotTokenMaps(tokens, parsedMarkdown);
|
|
583
|
+
for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex++) {
|
|
584
|
+
const token = tokens[tokenIndex];
|
|
585
|
+
if (!token) continue;
|
|
586
|
+
const tag = blockTag(token);
|
|
587
|
+
const tokenMap = token.map ?? slotMaps.get(tokenIndex);
|
|
588
|
+
if (!tag || !tokenMap) continue;
|
|
589
|
+
const level = token.level ?? 0;
|
|
590
|
+
while (true) {
|
|
591
|
+
const current = stack.at(-1);
|
|
592
|
+
if (!current || current.level < level) break;
|
|
593
|
+
stack.pop();
|
|
594
|
+
}
|
|
595
|
+
const descriptor = {
|
|
596
|
+
children: [],
|
|
597
|
+
range: rangeFromParsedLines(source, sourceLineStarts, parsedMarkdown, parsedLineStarts, parsedOffset, tokenMap[0], tokenMap[1] + (token.type === "mdc_block_open" ? 1 : 0), parsedLines),
|
|
598
|
+
tag
|
|
599
|
+
};
|
|
600
|
+
((stack.at(-1)?.descriptor)?.children ?? roots).push(descriptor);
|
|
601
|
+
if (token.nesting === 1) stack.push({
|
|
602
|
+
descriptor,
|
|
603
|
+
level
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
return roots.map(collapseComarkWrapper).map(groupProjectedSlotContent);
|
|
607
|
+
}
|
|
608
|
+
function blockTag(token) {
|
|
609
|
+
if (token.hidden || !token.type) return void 0;
|
|
610
|
+
if (token.type === "heading_open") return token.tag;
|
|
611
|
+
if (token.type === "mdc_block_open" || token.type === "mdc_block_shorthand" && token.nesting !== -1) return token.tag || "component";
|
|
612
|
+
if (token.type === "mdc_block_slot" && token.nesting === 1) return "template";
|
|
613
|
+
if ([
|
|
614
|
+
"fence",
|
|
615
|
+
"fenced_code_block",
|
|
616
|
+
"code_block"
|
|
617
|
+
].includes(token.type)) return "pre";
|
|
618
|
+
if (token.type === "math_block") return "math";
|
|
619
|
+
if (token.type === "html_block") return "*";
|
|
620
|
+
if (token.type === "hr") return "hr";
|
|
621
|
+
return BLOCK_TAGS.get(token.type);
|
|
622
|
+
}
|
|
623
|
+
function createSlotTokenMaps(tokens, parsedMarkdown) {
|
|
624
|
+
const maps = /* @__PURE__ */ new Map();
|
|
625
|
+
const markers = slotMarkers(parsedMarkdown);
|
|
626
|
+
const stack = [];
|
|
627
|
+
let nextMarker = 0;
|
|
628
|
+
for (let index = 0; index < tokens.length; index++) {
|
|
629
|
+
const token = tokens[index];
|
|
630
|
+
if (!token || token.type !== "mdc_block_slot") continue;
|
|
631
|
+
if (token.nesting === 1) {
|
|
632
|
+
const name = token.attrs?.[0]?.[0]?.replace(/^#/u, "");
|
|
633
|
+
let markerIndex = nextMarker;
|
|
634
|
+
while (markerIndex < markers.length && markers[markerIndex]?.name !== name) markerIndex++;
|
|
635
|
+
const marker = markers[markerIndex];
|
|
636
|
+
if (marker) {
|
|
637
|
+
stack.push({
|
|
638
|
+
index,
|
|
639
|
+
marker: marker.line
|
|
640
|
+
});
|
|
641
|
+
nextMarker = markerIndex + 1;
|
|
642
|
+
}
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
if (token.nesting !== -1) continue;
|
|
646
|
+
const open = stack.pop();
|
|
647
|
+
if (!open) continue;
|
|
648
|
+
let endLine = open.marker + 1;
|
|
649
|
+
for (let childIndex = open.index + 1; childIndex < index; childIndex++) {
|
|
650
|
+
const child = tokens[childIndex];
|
|
651
|
+
const map = child?.map ?? maps.get(childIndex);
|
|
652
|
+
if (child && map) endLine = Math.max(endLine, map[1] + (child.type === "mdc_block_open" ? 1 : 0));
|
|
690
653
|
}
|
|
691
|
-
|
|
692
|
-
type: "cmsInlineOpaque",
|
|
693
|
-
attrs: {
|
|
694
|
-
label: node[0],
|
|
695
|
-
node: stripInternalMetadata(node)
|
|
696
|
-
}
|
|
697
|
-
}, inheritedMarks));
|
|
654
|
+
maps.set(open.index, [open.marker, endLine]);
|
|
698
655
|
}
|
|
699
|
-
return
|
|
656
|
+
return maps;
|
|
700
657
|
}
|
|
701
|
-
function
|
|
702
|
-
return
|
|
658
|
+
function slotMarkers(source) {
|
|
659
|
+
return source.split(/\r?\n/u).flatMap((line, index) => {
|
|
660
|
+
const name = line.match(/^\s*#([^\s{]+)/u)?.[1];
|
|
661
|
+
return name ? [{
|
|
662
|
+
line: index,
|
|
663
|
+
name
|
|
664
|
+
}] : [];
|
|
665
|
+
});
|
|
703
666
|
}
|
|
704
|
-
function
|
|
705
|
-
const
|
|
706
|
-
if (
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
667
|
+
function collapseComarkWrapper(descriptor) {
|
|
668
|
+
const children = descriptor.children.map(collapseComarkWrapper);
|
|
669
|
+
if (WRAPPER_TAGS.has(descriptor.tag) && children.length === 1 && children[0]?.tag === descriptor.tag) return {
|
|
670
|
+
...descriptor,
|
|
671
|
+
children: children[0].children
|
|
672
|
+
};
|
|
673
|
+
return {
|
|
674
|
+
...descriptor,
|
|
675
|
+
children
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
/** Comark projects siblings after a named slot into that active slot. */
|
|
679
|
+
function groupProjectedSlotContent(descriptor) {
|
|
680
|
+
const grouped = [];
|
|
681
|
+
let activeSlot;
|
|
682
|
+
for (const rawChild of descriptor.children) {
|
|
683
|
+
const child = groupProjectedSlotContent(rawChild);
|
|
684
|
+
if (child.tag === "template") {
|
|
685
|
+
activeSlot = child;
|
|
686
|
+
grouped.push(child);
|
|
687
|
+
continue;
|
|
715
688
|
}
|
|
689
|
+
if (!activeSlot) {
|
|
690
|
+
grouped.push(child);
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
activeSlot.children.push(child);
|
|
694
|
+
if (child.range.end.offset > activeSlot.range.end.offset) activeSlot.range = {
|
|
695
|
+
start: activeSlot.range.start,
|
|
696
|
+
end: child.range.end
|
|
697
|
+
};
|
|
716
698
|
}
|
|
717
|
-
throw new Error("The editor identity factory did not produce a unique identity.");
|
|
718
|
-
}
|
|
719
|
-
function opaqueBlock(node, label, cmsNodeId) {
|
|
720
699
|
return {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
cmsNodeId,
|
|
724
|
-
label,
|
|
725
|
-
node: stripInternalMetadata(node)
|
|
726
|
-
}
|
|
700
|
+
...descriptor,
|
|
701
|
+
children: grouped
|
|
727
702
|
};
|
|
728
703
|
}
|
|
729
|
-
function
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
node
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
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";
|
|
704
|
+
function mapNodes(nodes, descriptors, parentPath, mappings) {
|
|
705
|
+
let descriptorIndex = 0;
|
|
706
|
+
for (let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++) {
|
|
707
|
+
const node = nodes[nodeIndex];
|
|
708
|
+
if (!node || !isElementNode(node)) continue;
|
|
709
|
+
let matchIndex = descriptorIndex;
|
|
710
|
+
while (matchIndex < descriptors.length && descriptors[matchIndex]?.tag !== "*" && descriptors[matchIndex]?.tag !== node[0]) matchIndex++;
|
|
711
|
+
const descriptor = descriptors[matchIndex];
|
|
712
|
+
if (!descriptor) continue;
|
|
713
|
+
descriptorIndex = matchIndex + 1;
|
|
714
|
+
const nodePath = [...parentPath, nodeIndex];
|
|
715
|
+
mappings.push({
|
|
716
|
+
nodePath,
|
|
717
|
+
range: descriptor.range
|
|
718
|
+
});
|
|
719
|
+
const [, , ...children] = node;
|
|
720
|
+
mapNodes(children, descriptor.children, nodePath, mappings);
|
|
721
|
+
}
|
|
767
722
|
}
|
|
768
723
|
function isElementNode(node) {
|
|
769
724
|
return Array.isArray(node) && Predicate.isString(node[0]);
|
|
770
725
|
}
|
|
771
|
-
function
|
|
772
|
-
const
|
|
773
|
-
|
|
726
|
+
function indexLineStarts(source) {
|
|
727
|
+
const starts = [0];
|
|
728
|
+
for (let offset = 0; offset < source.length; offset++) if (source.charCodeAt(offset) === 10) starts.push(offset + 1);
|
|
729
|
+
return starts;
|
|
774
730
|
}
|
|
775
|
-
function
|
|
776
|
-
|
|
731
|
+
function rangeFromParsedLines(source, sourceLineStarts, parsedMarkdown, parsedLineStarts, parsedOffset, startLine, endLine, fallbackLineOffset) {
|
|
732
|
+
const startOffset = parsedOffset >= 0 ? parsedOffset + (parsedLineStarts[startLine] ?? parsedMarkdown.length) : sourceLineStarts[startLine + fallbackLineOffset] ?? source.length;
|
|
733
|
+
const endOffset = parsedOffset >= 0 ? parsedOffset + (parsedLineStarts[endLine] ?? parsedMarkdown.length) : sourceLineStarts[endLine + fallbackLineOffset] ?? source.length;
|
|
734
|
+
return {
|
|
735
|
+
start: pointAt(source, sourceLineStarts, startOffset),
|
|
736
|
+
end: pointAt(source, sourceLineStarts, Math.max(startOffset, endOffset))
|
|
737
|
+
};
|
|
777
738
|
}
|
|
778
|
-
function
|
|
779
|
-
|
|
739
|
+
function pointAt(source, lineStarts, rawOffset) {
|
|
740
|
+
const offset = Math.min(Math.max(rawOffset, 0), source.length);
|
|
741
|
+
let low = 0;
|
|
742
|
+
let high = lineStarts.length - 1;
|
|
743
|
+
while (low < high) {
|
|
744
|
+
const middle = Math.ceil((low + high) / 2);
|
|
745
|
+
if ((lineStarts[middle] ?? source.length) <= offset) low = middle;
|
|
746
|
+
else high = middle - 1;
|
|
747
|
+
}
|
|
748
|
+
return {
|
|
749
|
+
offset,
|
|
750
|
+
line: low + 1,
|
|
751
|
+
column: offset - (lineStarts[low] ?? 0) + 1
|
|
752
|
+
};
|
|
780
753
|
}
|
|
781
|
-
|
|
782
|
-
|
|
754
|
+
|
|
755
|
+
//#endregion
|
|
756
|
+
//#region ../document/src/internal/comark/grammar.ts
|
|
757
|
+
/**
|
|
758
|
+
* Changes when parsing, normalization, or projection semantics change. Stored
|
|
759
|
+
* with compiled documents so migrations can identify stale derived content.
|
|
760
|
+
*/
|
|
761
|
+
const DOCUMENT_ENGINE_FINGERPRINT = "comark@0.6.2/frontmatter+alert+task-list+components+attributes+security+headings+toc+source-mapping/v1";
|
|
762
|
+
/** One explicit grammar for authoring, preview, delivery, and analysis projections. */
|
|
763
|
+
function createDocumentParser() {
|
|
764
|
+
return createMarkdownParser({
|
|
765
|
+
autoClose: false,
|
|
766
|
+
registerDefaultPlugins: false,
|
|
767
|
+
plugins: [
|
|
768
|
+
sourceCapturePlugin(),
|
|
769
|
+
frontmatter(),
|
|
770
|
+
alert(),
|
|
771
|
+
taskList(),
|
|
772
|
+
components(),
|
|
773
|
+
attributes(),
|
|
774
|
+
security(),
|
|
775
|
+
headings(),
|
|
776
|
+
toc({
|
|
777
|
+
depth: 5,
|
|
778
|
+
searchDepth: 6
|
|
779
|
+
}),
|
|
780
|
+
sourceMappingPlugin()
|
|
781
|
+
]
|
|
782
|
+
});
|
|
783
783
|
}
|
|
784
784
|
|
|
785
785
|
//#endregion
|
|
@@ -804,14 +804,52 @@ const parseAuthoringContent = Effect.fn("AuthoringSchema.parseContent")(function
|
|
|
804
804
|
return (yield* Schema.decodeUnknownEffect(CmsMarkdownDocument)(body)).nodes;
|
|
805
805
|
});
|
|
806
806
|
const isJsonObject = Schema.is(Schema.JsonObject);
|
|
807
|
-
/**
|
|
808
|
-
function
|
|
809
|
-
if (!
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
807
|
+
/** Resolves collection selectors for both insertion controls and authoritative validation. */
|
|
808
|
+
function collectionComponents(components, body) {
|
|
809
|
+
if (!body) return components;
|
|
810
|
+
return components.filter((component) => body.blocks?.includes(component.name) || component.authoring.group !== void 0 && body.groups?.includes(component.authoring.group));
|
|
811
|
+
}
|
|
812
|
+
/** Configuration errors belong to developers, before an installation adopts the catalog. */
|
|
813
|
+
function validateCollectionBody(components, body) {
|
|
814
|
+
return [
|
|
815
|
+
...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}.`)])),
|
|
816
|
+
...(body?.blocks ?? []).filter((name) => !components.some((component) => component.name === name)).map((name) => `Unknown block "${name}".`),
|
|
817
|
+
...(body?.groups ?? []).filter((group) => !components.some((component) => component.authoring.group === group)).map((group) => `Unknown block group "${group}".`)
|
|
818
|
+
];
|
|
819
|
+
}
|
|
820
|
+
function contentIssues(node, schemas, allowed, purpose, collectionAllowed = allowed) {
|
|
821
|
+
const issues = [];
|
|
822
|
+
if (node.type === "cmsBlock") {
|
|
823
|
+
const name = String(node.attrs?.tag).toLowerCase();
|
|
824
|
+
const schema = schemas.get(name);
|
|
825
|
+
if (!schema) issues.push("This block is unavailable. Ask your site developer to restore its definition.");
|
|
826
|
+
else {
|
|
827
|
+
if (!allowed.has(name)) issues.push(`${schema.definition.label} is not allowed in this content region.`);
|
|
828
|
+
issues.push(...schema.validate(node, purpose));
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
if (node.type === "cmsOpaque" || node.type === "cmsInlineOpaque") issues.push("This content is unsupported. Ask your site developer to update it before publishing.");
|
|
832
|
+
if (node.type === "cmsBlock") {
|
|
833
|
+
const schema = schemas.get(String(node.attrs?.tag).toLowerCase());
|
|
834
|
+
for (const region of node.content ?? []) {
|
|
835
|
+
const slot = schema?.definition.slots.find((candidate) => candidate.name === region.attrs?.name);
|
|
836
|
+
const permitted = slot?.input === "blocks" ? new Set(collectionComponents([...schemas].map(([name, schema]) => ({
|
|
837
|
+
name,
|
|
838
|
+
authoring: schema.definition
|
|
839
|
+
})), slot.blocks === void 0 && slot.groups === void 0 ? void 0 : slot).map((component) => component.name).filter((name) => collectionAllowed.has(name))) : collectionAllowed;
|
|
840
|
+
issues.push(...contentIssues(region, schemas, permitted, purpose, collectionAllowed));
|
|
841
|
+
}
|
|
842
|
+
return issues;
|
|
813
843
|
}
|
|
814
|
-
return
|
|
844
|
+
return [...issues, ...(node.content ?? []).flatMap((child) => contentIssues(child, schemas, allowed, purpose, collectionAllowed))];
|
|
845
|
+
}
|
|
846
|
+
/** Validates authored blocks during single-document compilation as well as catalog publication. */
|
|
847
|
+
function validateAuthoringDocument(body, components, bodyPolicy) {
|
|
848
|
+
if (!components) return [];
|
|
849
|
+
const definitions = [...components.values()];
|
|
850
|
+
const schemas = new Map(definitions.map((component) => [component.name, createAuthoringSchema(component.name, component.authoring)]));
|
|
851
|
+
const allowed = new Set(collectionComponents(definitions, bodyPolicy).map((component) => component.name));
|
|
852
|
+
return comarkToEditor(body.nodes, createCmsComarkRenderData(body)).flatMap((node) => contentIssues(node, schemas, allowed, "publish"));
|
|
815
853
|
}
|
|
816
854
|
function createAuthoringSchema(name, definition) {
|
|
817
855
|
const fields = new Map(definition.props.map((field) => [field.name, field]));
|
|
@@ -902,10 +940,30 @@ function createAuthoringSchema(name, definition) {
|
|
|
902
940
|
function propertyIssue(field, value, purpose) {
|
|
903
941
|
if (value === void 0) return field.required && purpose === "publish" ? `${field.label} is required.` : void 0;
|
|
904
942
|
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}.`;
|
|
943
|
+
if (!(field.type === "string" ? Predicate.isString(value) : field.type === "number" ? Predicate.isNumber(value) && Number.isFinite(value) : field.type === "boolean" ? Predicate.isBoolean(value) : field.type === "array" ? Array.isArray(value) : isJsonObject(value))) return `${field.label} must be ${field.type}.`;
|
|
944
|
+
if (field.type === "object" || field.type === "array") {
|
|
945
|
+
const entries = Array.isArray(value) ? value : [value];
|
|
946
|
+
const ids = /* @__PURE__ */ new Set();
|
|
947
|
+
for (const entry of entries) {
|
|
948
|
+
if (!isJsonObject(entry)) return `${field.label} must contain objects.`;
|
|
949
|
+
if (field.type === "array") {
|
|
950
|
+
const id = entry.id;
|
|
951
|
+
if (!Predicate.isString(id) || !id || ids.has(id)) return `${field.label} items need unique identities.`;
|
|
952
|
+
ids.add(id);
|
|
953
|
+
}
|
|
954
|
+
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.`;
|
|
955
|
+
for (const child of field.fields ?? []) {
|
|
956
|
+
const issue = propertyIssue(child, entry[child.name], purpose);
|
|
957
|
+
if (issue) return `${field.label}: ${issue}`;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
if (purpose === "publish" && field.required && value === "" && (field.input === "image" || field.input === "link")) return `${field.label} is required.`;
|
|
962
|
+
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
963
|
if (field.options.length && !field.options.some((option) => option.value === value)) return `${field.label} must use one of its available choices.`;
|
|
907
964
|
}
|
|
908
965
|
function validRegion(slot, content) {
|
|
966
|
+
if (slot.input === "blocks") return content.every((node) => node.type === "cmsBlock" || node.type === "paragraph" && !node.content?.length);
|
|
909
967
|
const types = /* @__PURE__ */ new Set([
|
|
910
968
|
"paragraph",
|
|
911
969
|
"text",
|
|
@@ -920,7 +978,177 @@ function validRegion(slot, content) {
|
|
|
920
978
|
const valid = (node) => types.has(node.type ?? "") && (node.marks ?? []).every((mark) => marks.has(mark.type)) && (node.content ?? []).every(valid);
|
|
921
979
|
return content.every(valid);
|
|
922
980
|
}
|
|
981
|
+
/** URL values remain ordinary Vue strings and use the document model's public paths. */
|
|
982
|
+
function validAuthoringUrl(value, input) {
|
|
983
|
+
if (value.trim() !== value || value.includes("\\")) return false;
|
|
984
|
+
for (const character of value) if (character.charCodeAt(0) <= 32) return false;
|
|
985
|
+
if (value.startsWith("/") && !value.startsWith("//")) return true;
|
|
986
|
+
if (input === "link" && value.startsWith("#")) return true;
|
|
987
|
+
try {
|
|
988
|
+
const url = new URL(value);
|
|
989
|
+
return [
|
|
990
|
+
"https:",
|
|
991
|
+
"http:",
|
|
992
|
+
...input === "link" ? ["mailto:", "tel:"] : []
|
|
993
|
+
].includes(url.protocol);
|
|
994
|
+
} catch {
|
|
995
|
+
return false;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
//#endregion
|
|
1000
|
+
//#region ../protocol/src/Authoring.ts
|
|
1001
|
+
/** Serializable component authoring data resolved by the framework compiler. */
|
|
1002
|
+
const BlockProp = Schema.Struct({
|
|
1003
|
+
name: Schema.NonEmptyString,
|
|
1004
|
+
label: Schema.NonEmptyString,
|
|
1005
|
+
help: Schema.optionalKey(Schema.String),
|
|
1006
|
+
type: Schema.Literals([
|
|
1007
|
+
"string",
|
|
1008
|
+
"number",
|
|
1009
|
+
"boolean",
|
|
1010
|
+
"object",
|
|
1011
|
+
"array"
|
|
1012
|
+
]),
|
|
1013
|
+
input: Schema.Literals([
|
|
1014
|
+
"text",
|
|
1015
|
+
"textarea",
|
|
1016
|
+
"select",
|
|
1017
|
+
"number",
|
|
1018
|
+
"toggle",
|
|
1019
|
+
"image",
|
|
1020
|
+
"link",
|
|
1021
|
+
"object",
|
|
1022
|
+
"list"
|
|
1023
|
+
]),
|
|
1024
|
+
required: Schema.Boolean,
|
|
1025
|
+
nullable: Schema.Boolean,
|
|
1026
|
+
defaultValue: Schema.optionalKey(Schema.Json),
|
|
1027
|
+
fields: Schema.optionalKey(Schema.Array(Schema.suspend(() => BlockProp))),
|
|
1028
|
+
options: Schema.Array(Schema.Struct({
|
|
1029
|
+
value: Schema.String,
|
|
1030
|
+
label: Schema.String
|
|
1031
|
+
}))
|
|
1032
|
+
});
|
|
1033
|
+
const BlockSlot = Schema.Struct({
|
|
1034
|
+
name: Schema.NonEmptyString,
|
|
1035
|
+
label: Schema.NonEmptyString,
|
|
1036
|
+
help: Schema.optionalKey(Schema.String),
|
|
1037
|
+
required: Schema.Boolean,
|
|
1038
|
+
input: Schema.Literals([
|
|
1039
|
+
"text",
|
|
1040
|
+
"rich-text",
|
|
1041
|
+
"blocks"
|
|
1042
|
+
]),
|
|
1043
|
+
blocks: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),
|
|
1044
|
+
groups: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),
|
|
1045
|
+
features: Schema.Array(Schema.Literals([
|
|
1046
|
+
"bold",
|
|
1047
|
+
"italic",
|
|
1048
|
+
"link",
|
|
1049
|
+
"bullet-list",
|
|
1050
|
+
"code"
|
|
1051
|
+
])),
|
|
1052
|
+
initial: Schema.optionalKey(Schema.Array(MarkdownNode))
|
|
1053
|
+
});
|
|
1054
|
+
const BlockAuthoring = Schema.Struct({
|
|
1055
|
+
version: Schema.Literal(1),
|
|
1056
|
+
label: Schema.NonEmptyString,
|
|
1057
|
+
description: Schema.optionalKey(Schema.String),
|
|
1058
|
+
group: Schema.optionalKey(Schema.String),
|
|
1059
|
+
icon: Schema.optionalKey(Schema.String),
|
|
1060
|
+
props: Schema.Array(BlockProp),
|
|
1061
|
+
slots: Schema.Array(BlockSlot),
|
|
1062
|
+
initialProps: Schema.JsonObject
|
|
1063
|
+
});
|
|
1064
|
+
|
|
1065
|
+
//#endregion
|
|
1066
|
+
//#region ../protocol/src/Configuration.ts
|
|
1067
|
+
/** Validated installation configuration shared by authoring, compilation, Studio, and Nuxt. */
|
|
1068
|
+
const fieldPresentation = {
|
|
1069
|
+
path: Schema.NonEmptyString,
|
|
1070
|
+
label: Schema.NonEmptyString,
|
|
1071
|
+
description: Schema.optionalKey(Schema.String),
|
|
1072
|
+
defaultValue: Schema.optionalKey(Schema.Json),
|
|
1073
|
+
required: Schema.Boolean
|
|
1074
|
+
};
|
|
1075
|
+
const BooleanAuthoringField = Schema.Struct({
|
|
1076
|
+
type: Schema.tag("boolean"),
|
|
1077
|
+
...fieldPresentation,
|
|
1078
|
+
input: Schema.Literal("toggle")
|
|
1079
|
+
});
|
|
1080
|
+
const DateAuthoringField = Schema.Struct({
|
|
1081
|
+
type: Schema.tag("date"),
|
|
1082
|
+
...fieldPresentation,
|
|
1083
|
+
input: Schema.Literal("date")
|
|
1084
|
+
});
|
|
1085
|
+
const NumberAuthoringField = Schema.Struct({
|
|
1086
|
+
type: Schema.tag("number"),
|
|
1087
|
+
...fieldPresentation,
|
|
1088
|
+
input: Schema.Literals(["number", "select"]),
|
|
1089
|
+
options: Schema.Array(Schema.Finite)
|
|
1090
|
+
});
|
|
1091
|
+
const StringAuthoringField = Schema.Struct({
|
|
1092
|
+
type: Schema.tag("string"),
|
|
1093
|
+
...fieldPresentation,
|
|
1094
|
+
input: Schema.Literals([
|
|
1095
|
+
"select",
|
|
1096
|
+
"text",
|
|
1097
|
+
"textarea"
|
|
1098
|
+
]),
|
|
1099
|
+
options: Schema.Array(Schema.String)
|
|
1100
|
+
});
|
|
1101
|
+
const StringArrayAuthoringField = Schema.Struct({
|
|
1102
|
+
type: Schema.tag("string[]"),
|
|
1103
|
+
...fieldPresentation,
|
|
1104
|
+
input: Schema.Literal("multiselect"),
|
|
1105
|
+
options: Schema.Array(Schema.String)
|
|
1106
|
+
});
|
|
1107
|
+
const DocumentField = Schema.Union([
|
|
1108
|
+
BooleanAuthoringField,
|
|
1109
|
+
DateAuthoringField,
|
|
1110
|
+
NumberAuthoringField,
|
|
1111
|
+
StringArrayAuthoringField,
|
|
1112
|
+
StringAuthoringField
|
|
1113
|
+
]);
|
|
1114
|
+
const CollectionBody = Schema.Struct({
|
|
1115
|
+
blocks: Schema.optionalKey(Schema.Array(Schema.NonEmptyString)),
|
|
1116
|
+
groups: Schema.optionalKey(Schema.Array(Schema.NonEmptyString))
|
|
1117
|
+
});
|
|
1118
|
+
const CollectionDefinition = Schema.Struct({
|
|
1119
|
+
collection: CollectionName,
|
|
1120
|
+
body: Schema.optionalKey(CollectionBody),
|
|
1121
|
+
label: Schema.NonEmptyString,
|
|
1122
|
+
description: Schema.String,
|
|
1123
|
+
directory: SourceDirectory,
|
|
1124
|
+
addressPattern: AddressPattern,
|
|
1125
|
+
hierarchy: Schema.Boolean,
|
|
1126
|
+
canCreate: Schema.Boolean,
|
|
1127
|
+
authoringFields: Schema.Array(DocumentField)
|
|
1128
|
+
}).annotate({ identifier: "CollectionDefinition" });
|
|
1129
|
+
const LocaleConfiguration = Schema.Struct({
|
|
1130
|
+
locales: Schema.Array(Locale),
|
|
1131
|
+
defaultLocale: Locale,
|
|
1132
|
+
fallbackLocale: Schema.NullOr(Locale),
|
|
1133
|
+
prefixDefaultLocale: Schema.Boolean
|
|
1134
|
+
}).annotate({ identifier: "LocaleConfiguration" });
|
|
1135
|
+
const DocumentConfiguration = Schema.Struct({
|
|
1136
|
+
types: Schema.Array(CollectionDefinition),
|
|
1137
|
+
locales: Schema.optionalKey(LocaleConfiguration)
|
|
1138
|
+
}).annotate({ identifier: "DocumentConfiguration" });
|
|
1139
|
+
const ComponentDefinition = Schema.Struct({
|
|
1140
|
+
authoring: BlockAuthoring,
|
|
1141
|
+
name: Schema.NonEmptyString
|
|
1142
|
+
}).annotate({ identifier: "ComponentDefinition" });
|
|
1143
|
+
const AuthoringCatalog = Schema.Struct({
|
|
1144
|
+
revision: Schema.NonEmptyString,
|
|
1145
|
+
components: Schema.Array(ComponentDefinition)
|
|
1146
|
+
});
|
|
1147
|
+
const MediaConfiguration = Schema.Struct({
|
|
1148
|
+
enabled: Schema.Boolean,
|
|
1149
|
+
maxUploadBytes: Schema.Int.check(Schema.isGreaterThan(0))
|
|
1150
|
+
});
|
|
923
1151
|
|
|
924
1152
|
//#endregion
|
|
925
|
-
export {
|
|
926
|
-
//# sourceMappingURL=
|
|
1153
|
+
export { finiteNumberAttribute as C, projectCmsEditorComponentAttributes as D, normalizeCmsComponentBindings as E, resolveCmsComarkAttributes as O, compactJsonAttributes as S, encodeCmsEditorComponentAttributes as T, comarkTagForEditorMark as _, BlockAuthoring as a, encodeEditorImageAttributes as b, validateAuthoringDocument as c, EditorRenderFailed as d, DOCUMENT_ENGINE_FINGERPRINT as f, EDITOR_MARK_TYPES as g, comarkToEditor as h, MediaConfiguration as i, withCmsComarkProps as k, validateCollectionBody as l, SOURCE_MAPPINGS_META_KEY as m, ComponentDefinition as n, createAuthoringSchema as o, createDocumentParser as p, DocumentConfiguration as r, parseAuthoringContent as s, AuthoringCatalog as t, EditorDocumentInvalid as u, isEditorMark as v, nonEmptyStringAttribute as w, normalizeEditorImageLayout as x, EDITOR_IMAGE_LAYOUT_ATTRIBUTE as y };
|
|
1154
|
+
//# sourceMappingURL=Configuration-DyKo0sLS.js.map
|