@owomark/core 0.1.6 → 0.1.8

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 (38) hide show
  1. package/README.md +30 -10
  2. package/dist/.build-manifest.json +131 -0
  3. package/dist/browser.d.ts +66 -0
  4. package/dist/browser.js +396 -0
  5. package/dist/chunk-3KTK7CSS.js +82 -0
  6. package/dist/chunk-5JNL3LHV.js +215 -0
  7. package/dist/chunk-ASRCHEFF.js +0 -0
  8. package/dist/chunk-BKJCBEI7.js +397 -0
  9. package/dist/chunk-CJSBFWKS.js +549 -0
  10. package/dist/chunk-OOH46GIF.js +95 -0
  11. package/dist/chunk-ROJILHRQ.js +192 -0
  12. package/dist/chunk-WFPUIPWU.js +34 -0
  13. package/dist/chunk-WVGCRIJO.js +5885 -0
  14. package/dist/chunk-WXVKSKP3.js +191 -0
  15. package/dist/chunk-YZYJIXGO.js +0 -0
  16. package/dist/editor-core-BSoeizSI.d.ts +249 -0
  17. package/dist/index.d.ts +77 -87
  18. package/dist/index.js +127 -248
  19. package/dist/internal/dom-adapter.d.ts +37 -1
  20. package/dist/internal/dom-adapter.js +9 -2
  21. package/dist/public-cCK3rvQc.d.ts +473 -0
  22. package/dist/registry-6IkGJsLt.d.ts +74 -0
  23. package/dist/semantic/components/index.d.ts +9 -0
  24. package/dist/semantic/components/index.js +11 -0
  25. package/dist/semantic/editor/index.d.ts +9 -0
  26. package/dist/semantic/editor/index.js +13 -0
  27. package/dist/semantic/index.d.ts +7 -0
  28. package/dist/semantic/index.js +106 -0
  29. package/dist/semantic/runtime/index.d.ts +9 -0
  30. package/dist/semantic/runtime/index.js +13 -0
  31. package/dist/semantic/shared/index.d.ts +10 -0
  32. package/dist/semantic/shared/index.js +17 -0
  33. package/dist/semantic/syntax/index.d.ts +151 -0
  34. package/dist/semantic/syntax/index.js +63 -0
  35. package/dist/types-BdOo-u1R.d.ts +83 -0
  36. package/package.json +29 -1
  37. package/dist/chunk-6CBUAORJ.js +0 -3337
  38. package/dist/dom-adapter-C8wuoffZ.d.ts +0 -471
@@ -0,0 +1,549 @@
1
+ import {
2
+ expandDirtyRange,
3
+ expandWithContext
4
+ } from "./chunk-WFPUIPWU.js";
5
+
6
+ // src/model/selection/block-cache.ts
7
+ var blockCacheMap = /* @__PURE__ */ new WeakMap();
8
+ function getBlocks(root) {
9
+ let cached = blockCacheMap.get(root);
10
+ if (cached) {
11
+ return cached;
12
+ }
13
+ cached = Array.from(root.querySelectorAll("[data-owo-block]"));
14
+ blockCacheMap.set(root, cached);
15
+ return cached;
16
+ }
17
+ function invalidateBlockCache(root) {
18
+ blockCacheMap.delete(root);
19
+ }
20
+ function getOwnerBlock(root, node) {
21
+ if (node === root) {
22
+ return null;
23
+ }
24
+ if (node.nodeType === Node.ELEMENT_NODE) {
25
+ const el = node;
26
+ if (el.hasAttribute("data-owo-block")) {
27
+ return el;
28
+ }
29
+ return el.closest?.("[data-owo-block]");
30
+ }
31
+ return node.parentElement?.closest("[data-owo-block]") ?? null;
32
+ }
33
+ function getModelTextLength(root) {
34
+ const blocks = getBlocks(root);
35
+ if (blocks.length === 0) {
36
+ return 0;
37
+ }
38
+ let len = 0;
39
+ for (let index = 0; index < blocks.length; index += 1) {
40
+ if (index > 0) {
41
+ len += 1;
42
+ }
43
+ len += blocks[index].textContent?.length ?? 0;
44
+ }
45
+ return len;
46
+ }
47
+
48
+ // src/model/selection/linear-dom.ts
49
+ function countTextWithinBlockBefore(block, target) {
50
+ const walker = block.ownerDocument.createTreeWalker(block, NodeFilter.SHOW_TEXT);
51
+ let count = 0;
52
+ while (walker.nextNode()) {
53
+ const textNode = walker.currentNode;
54
+ if (textNode === target) {
55
+ break;
56
+ }
57
+ const pos = textNode.compareDocumentPosition(target);
58
+ const isBeforeTarget = (pos & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
59
+ const isInsideTarget = (pos & Node.DOCUMENT_POSITION_CONTAINED_BY) !== 0;
60
+ if (isBeforeTarget && !isInsideTarget) {
61
+ count += textNode.textContent?.length ?? 0;
62
+ } else {
63
+ break;
64
+ }
65
+ }
66
+ return count;
67
+ }
68
+ function countTextBefore(root, target) {
69
+ const blocks = getBlocks(root);
70
+ const targetBlock = getOwnerBlock(root, target);
71
+ let count = 0;
72
+ for (let index = 0; index < blocks.length; index += 1) {
73
+ const block = blocks[index];
74
+ if (index > 0) {
75
+ count += 1;
76
+ }
77
+ if (block === targetBlock) {
78
+ count += countTextWithinBlockBefore(block, target);
79
+ return count;
80
+ }
81
+ const pos = block.compareDocumentPosition(target);
82
+ if ((pos & Node.DOCUMENT_POSITION_FOLLOWING) !== 0) {
83
+ count += block.textContent?.length ?? 0;
84
+ } else {
85
+ return count;
86
+ }
87
+ }
88
+ return count;
89
+ }
90
+ function countBlockStartOffset(root, targetBlock) {
91
+ const blocks = getBlocks(root);
92
+ let offset = 0;
93
+ for (const block of blocks) {
94
+ if (block === targetBlock) {
95
+ return offset;
96
+ }
97
+ offset += (block.textContent?.length ?? 0) + 1;
98
+ }
99
+ return offset;
100
+ }
101
+ function firstPositionInBlock(block) {
102
+ const walker = block.ownerDocument.createTreeWalker(block, NodeFilter.SHOW_TEXT);
103
+ if (walker.nextNode()) {
104
+ return { node: walker.currentNode, offset: 0 };
105
+ }
106
+ return { node: block, offset: 0 };
107
+ }
108
+ function lastPositionInBlock(block) {
109
+ const walker = block.ownerDocument.createTreeWalker(block, NodeFilter.SHOW_TEXT);
110
+ let lastText = null;
111
+ while (walker.nextNode()) {
112
+ lastText = walker.currentNode;
113
+ }
114
+ if (lastText) {
115
+ return { node: lastText, offset: lastText.textContent?.length ?? 0 };
116
+ }
117
+ return { node: block, offset: block.childNodes.length };
118
+ }
119
+ function nodeOffsetToLinear(root, node, offset) {
120
+ if (!root.contains(node)) {
121
+ return null;
122
+ }
123
+ if (node === root) {
124
+ const targetChild2 = root.childNodes[offset];
125
+ if (targetChild2) {
126
+ return countTextBefore(root, targetChild2);
127
+ }
128
+ return getModelTextLength(root);
129
+ }
130
+ if (node.nodeType === Node.TEXT_NODE) {
131
+ return countTextBefore(root, node) + offset;
132
+ }
133
+ const el = node;
134
+ const targetChild = el.childNodes[offset];
135
+ if (targetChild) {
136
+ return countTextBefore(root, targetChild);
137
+ }
138
+ const block = getOwnerBlock(root, node);
139
+ if (block) {
140
+ return countBlockStartOffset(root, block) + (node === block ? block.textContent?.length ?? 0 : countTextWithinBlockBefore(block, node) + (node.textContent?.length ?? 0));
141
+ }
142
+ return getModelTextLength(root);
143
+ }
144
+ function linearToNodeOffset(root, offset) {
145
+ const blocks = getBlocks(root);
146
+ if (blocks.length === 0) {
147
+ return { node: root, offset: 0 };
148
+ }
149
+ let pos = 0;
150
+ for (let index = 0; index < blocks.length; index += 1) {
151
+ const block = blocks[index];
152
+ if (index > 0) {
153
+ if (pos === offset) {
154
+ return firstPositionInBlock(block);
155
+ }
156
+ pos += 1;
157
+ }
158
+ const blockTextLen = block.textContent?.length ?? 0;
159
+ if (pos + blockTextLen >= offset) {
160
+ const inBlockOffset = offset - pos;
161
+ if (inBlockOffset === 0) {
162
+ return firstPositionInBlock(block);
163
+ }
164
+ const walker = block.ownerDocument.createTreeWalker(block, NodeFilter.SHOW_TEXT);
165
+ let blockPos = 0;
166
+ while (walker.nextNode()) {
167
+ const textNode = walker.currentNode;
168
+ const len = textNode.textContent?.length ?? 0;
169
+ if (blockPos + len >= inBlockOffset) {
170
+ return { node: textNode, offset: inBlockOffset - blockPos };
171
+ }
172
+ blockPos += len;
173
+ }
174
+ return lastPositionInBlock(block);
175
+ }
176
+ pos += blockTextLen;
177
+ }
178
+ return lastPositionInBlock(blocks[blocks.length - 1]);
179
+ }
180
+
181
+ // src/model/selection/dom-range.ts
182
+ function domRangeToOffset(root, range) {
183
+ const anchor = nodeOffsetToLinear(root, range.startContainer, range.startOffset);
184
+ const focus = nodeOffsetToLinear(root, range.endContainer, range.endOffset);
185
+ if (anchor === null || focus === null) {
186
+ return null;
187
+ }
188
+ return { anchor, focus };
189
+ }
190
+ function offsetToDomRange(root, selection) {
191
+ const doc = root.ownerDocument;
192
+ const range = doc.createRange();
193
+ const textLen = getModelTextLength(root);
194
+ const clampedAnchor = Math.max(0, Math.min(selection.anchor, textLen));
195
+ const clampedFocus = Math.max(0, Math.min(selection.focus, textLen));
196
+ const start = linearToNodeOffset(root, Math.min(clampedAnchor, clampedFocus));
197
+ const end = linearToNodeOffset(root, Math.max(clampedAnchor, clampedFocus));
198
+ if (!start || !end) {
199
+ return null;
200
+ }
201
+ range.setStart(start.node, start.offset);
202
+ range.setEnd(end.node, end.offset);
203
+ return range;
204
+ }
205
+
206
+ // src/model/selection/index.ts
207
+ function restoreSelection(root, selection) {
208
+ const textLen = getModelTextLength(root);
209
+ const clamped = {
210
+ anchor: Math.max(0, Math.min(selection.anchor, textLen)),
211
+ focus: Math.max(0, Math.min(selection.focus, textLen))
212
+ };
213
+ const range = offsetToDomRange(root, clamped);
214
+ if (!range) {
215
+ return;
216
+ }
217
+ const sel = root.ownerDocument.getSelection();
218
+ if (!sel) {
219
+ return;
220
+ }
221
+ sel.removeAllRanges();
222
+ if (clamped.anchor <= clamped.focus) {
223
+ sel.addRange(range);
224
+ return;
225
+ }
226
+ sel.addRange(range);
227
+ sel.collapseToEnd();
228
+ const focusPos = linearToNodeOffset(root, clamped.focus);
229
+ if (focusPos) {
230
+ sel.extend(focusPos.node, focusPos.offset);
231
+ }
232
+ }
233
+ function readSelection(root) {
234
+ const sel = root.ownerDocument.getSelection();
235
+ if (!sel || sel.rangeCount === 0) {
236
+ return null;
237
+ }
238
+ if (!root.contains(sel.anchorNode)) {
239
+ return null;
240
+ }
241
+ const anchor = nodeOffsetToLinear(root, sel.anchorNode, sel.anchorOffset);
242
+ const focus = nodeOffsetToLinear(root, sel.focusNode, sel.focusOffset);
243
+ if (anchor === null || focus === null) {
244
+ return null;
245
+ }
246
+ return { anchor, focus };
247
+ }
248
+
249
+ // src/render/blockquote-bars.ts
250
+ var BQ_BAR_WIDTH = 3;
251
+ var BQ_GAP = 12;
252
+ var BQ_STEP = BQ_BAR_WIDTH + BQ_GAP;
253
+ function buildBlockquoteBarsBoxShadow(depth) {
254
+ if (depth <= 1) return null;
255
+ const shadows = [];
256
+ for (let i = depth - 1; i >= 1; i--) {
257
+ const barEnd = i * BQ_STEP;
258
+ shadows.push(`inset ${barEnd}px 0 0 0 var(--owo-editor-bg, #ffffff)`);
259
+ shadows.push(`inset ${barEnd + BQ_BAR_WIDTH}px 0 0 0 var(--owo-editor-border-strong, #cbd5e1)`);
260
+ }
261
+ return shadows.join(", ");
262
+ }
263
+
264
+ // src/render/block-render.ts
265
+ var TOKEN_CLASS_EXEMPTIONS = /* @__PURE__ */ new Set(["text"]);
266
+ function applyBlockquoteBarsStyle(el, depth) {
267
+ const shadow = buildBlockquoteBarsBoxShadow(depth);
268
+ if (!shadow) return;
269
+ el.style.paddingLeft = `${depth * BQ_STEP}px`;
270
+ el.style.boxShadow = shadow;
271
+ }
272
+ var TOKEN_TO_CLASS = {
273
+ "text": "",
274
+ "strong-marker": "owo-syntax-marker",
275
+ "strong": "owo-syntax-strong",
276
+ "emphasis-marker": "owo-syntax-marker",
277
+ "emphasis": "owo-syntax-emphasis",
278
+ "custom-inline-marker": "owo-syntax-marker",
279
+ "custom-inline": "owo-syntax-custom-inline",
280
+ "code-marker": "owo-syntax-marker",
281
+ "code": "owo-syntax-inline-code",
282
+ "link-bracket": "owo-syntax-marker",
283
+ "link-text": "owo-syntax-link-text",
284
+ "link-url": "owo-syntax-link-url",
285
+ "reference-bracket": "owo-syntax-marker",
286
+ "reference-label": "owo-syntax-link-url",
287
+ "image-marker": "owo-syntax-marker",
288
+ "image-alt": "owo-syntax-link-text",
289
+ "image-url": "owo-syntax-link-url",
290
+ "heading-marker": "owo-syntax-heading-marker",
291
+ "list-marker": "owo-syntax-list-marker",
292
+ "task-marker": "owo-syntax-task-marker",
293
+ "task-marker-checked": "owo-syntax-task-marker-checked",
294
+ "table-separator": "owo-syntax-table-separator",
295
+ "blockquote-marker": "owo-syntax-blockquote-marker",
296
+ "fence-marker": "owo-syntax-fence",
297
+ "fence-lang": "owo-syntax-fence-lang",
298
+ "code-block-text": "owo-syntax-code-block",
299
+ "strikethrough-marker": "owo-syntax-marker",
300
+ "strikethrough": "owo-syntax-strikethrough",
301
+ "math-marker": "owo-syntax-marker",
302
+ "math-text": "owo-syntax-math",
303
+ "hr": "owo-syntax-hr",
304
+ "html": "owo-syntax-html"
305
+ };
306
+ var BLOCK_TYPE_TO_CLASS = {
307
+ "heading": "owo-block-heading",
308
+ "paragraph": "owo-block-paragraph",
309
+ "unordered-list": "owo-block-list",
310
+ "ordered-list": "owo-block-list",
311
+ "blockquote": "owo-block-blockquote",
312
+ "code-fence": "owo-block-code-fence",
313
+ "side-annotation": "owo-block-directive-container",
314
+ "side-note-definition": "owo-block-directive-container",
315
+ "directive-container": "owo-block-directive-container",
316
+ "custom-block": "owo-block-directive-container",
317
+ "thematic-break": "owo-block-hr",
318
+ "math-block": "owo-block-math",
319
+ "table": "owo-block-table"
320
+ };
321
+ function createBlockElement(doc, tokens, blockIndex, blockType, headingLevel, depth) {
322
+ const div = doc.createElement("div");
323
+ div.setAttribute("data-owo-block", String(blockIndex));
324
+ div.className = BLOCK_TYPE_TO_CLASS[blockType] || "owo-block-paragraph";
325
+ if (blockType === "heading" && headingLevel) {
326
+ div.setAttribute("data-owo-heading", String(headingLevel));
327
+ }
328
+ if (blockType === "blockquote" && depth && depth > 0) {
329
+ div.setAttribute("data-owo-depth", String(depth));
330
+ applyBlockquoteBarsStyle(div, depth);
331
+ }
332
+ renderTokensInto(doc, div, tokens);
333
+ return div;
334
+ }
335
+ function renderTokensInto(doc, container, tokens) {
336
+ for (const token of tokens) {
337
+ const cls = TOKEN_TO_CLASS[token.type];
338
+ const parts = token.text.split("\n");
339
+ for (let i = 0; i < parts.length; i++) {
340
+ if (i > 0) {
341
+ container.appendChild(doc.createTextNode("\n"));
342
+ }
343
+ const part = parts[i];
344
+ if (!part && i < parts.length - 1) continue;
345
+ const leaf = doc.createElement("span");
346
+ leaf.setAttribute("data-owo-leaf", "true");
347
+ leaf.textContent = part;
348
+ if (cls) {
349
+ const decorator = doc.createElement("span");
350
+ decorator.className = cls;
351
+ decorator.setAttribute("data-owo-token", token.type);
352
+ if (token.syntaxKey) {
353
+ decorator.setAttribute("data-owo-syntax-key", token.syntaxKey);
354
+ }
355
+ decorator.appendChild(leaf);
356
+ container.appendChild(decorator);
357
+ } else {
358
+ if (part) {
359
+ container.appendChild(leaf);
360
+ }
361
+ }
362
+ }
363
+ }
364
+ if (container.childNodes.length === 0) {
365
+ container.appendChild(doc.createElement("br"));
366
+ }
367
+ }
368
+ function renderDecoratorsInto(doc, container, decorators) {
369
+ for (const decorator of decorators) {
370
+ const cls = TOKEN_TO_CLASS[decorator.type];
371
+ const text = decorator.leaves.map((leaf) => leaf.text).join("");
372
+ const parts = text.split("\n");
373
+ for (let index = 0; index < parts.length; index += 1) {
374
+ if (index > 0) {
375
+ container.appendChild(doc.createTextNode("\n"));
376
+ }
377
+ const part = parts[index];
378
+ if (!part && index < parts.length - 1) {
379
+ continue;
380
+ }
381
+ const leaf = doc.createElement("span");
382
+ leaf.setAttribute("data-owo-leaf", "true");
383
+ leaf.textContent = part;
384
+ if (cls) {
385
+ const decoratorEl = doc.createElement("span");
386
+ decoratorEl.className = cls;
387
+ decoratorEl.setAttribute("data-owo-token", decorator.type);
388
+ if (decorator.syntaxKey) {
389
+ decoratorEl.setAttribute("data-owo-syntax-key", decorator.syntaxKey);
390
+ }
391
+ decoratorEl.appendChild(leaf);
392
+ container.appendChild(decoratorEl);
393
+ } else if (part) {
394
+ container.appendChild(leaf);
395
+ }
396
+ }
397
+ }
398
+ if (container.childNodes.length === 0) {
399
+ container.appendChild(doc.createElement("br"));
400
+ }
401
+ }
402
+ function createBlockElementFromDecorators(doc, decorators, blockIndex, blockType, headingLevel, depth) {
403
+ const div = doc.createElement("div");
404
+ div.setAttribute("data-owo-block", String(blockIndex));
405
+ div.className = BLOCK_TYPE_TO_CLASS[blockType] || "owo-block-paragraph";
406
+ if (blockType === "heading" && headingLevel) {
407
+ div.setAttribute("data-owo-heading", String(headingLevel));
408
+ }
409
+ if (blockType === "blockquote" && depth && depth > 0) {
410
+ div.setAttribute("data-owo-depth", String(depth));
411
+ applyBlockquoteBarsStyle(div, depth);
412
+ }
413
+ renderDecoratorsInto(doc, div, decorators);
414
+ return div;
415
+ }
416
+ function updateBlockElementFromDecorators(doc, existing, decorators, blockType, headingLevel, depth) {
417
+ const newClass = BLOCK_TYPE_TO_CLASS[blockType] || "owo-block-paragraph";
418
+ if (existing.className !== newClass) {
419
+ existing.className = newClass;
420
+ }
421
+ if (blockType === "heading" && headingLevel) {
422
+ existing.setAttribute("data-owo-heading", String(headingLevel));
423
+ } else {
424
+ existing.removeAttribute("data-owo-heading");
425
+ }
426
+ if (blockType === "blockquote" && depth && depth > 0) {
427
+ existing.setAttribute("data-owo-depth", String(depth));
428
+ applyBlockquoteBarsStyle(existing, depth);
429
+ } else {
430
+ existing.removeAttribute("data-owo-depth");
431
+ existing.style.paddingLeft = "";
432
+ existing.style.boxShadow = "";
433
+ }
434
+ existing.textContent = "";
435
+ renderDecoratorsInto(doc, existing, decorators);
436
+ return true;
437
+ }
438
+ function updateBlockElement(doc, existing, tokens, blockType, headingLevel, depth) {
439
+ const newClass = BLOCK_TYPE_TO_CLASS[blockType] || "owo-block-paragraph";
440
+ if (existing.className !== newClass) {
441
+ existing.className = newClass;
442
+ }
443
+ if (blockType === "heading" && headingLevel) {
444
+ existing.setAttribute("data-owo-heading", String(headingLevel));
445
+ } else {
446
+ existing.removeAttribute("data-owo-heading");
447
+ }
448
+ if (blockType === "blockquote" && depth && depth > 0) {
449
+ existing.setAttribute("data-owo-depth", String(depth));
450
+ applyBlockquoteBarsStyle(existing, depth);
451
+ } else {
452
+ existing.removeAttribute("data-owo-depth");
453
+ existing.style.paddingLeft = "";
454
+ existing.style.boxShadow = "";
455
+ }
456
+ existing.textContent = "";
457
+ renderTokensInto(doc, existing, tokens);
458
+ return true;
459
+ }
460
+
461
+ // src/render/dom-patch.ts
462
+ function fullRender(root, doc) {
463
+ const ownerDoc = root.ownerDocument;
464
+ root.textContent = "";
465
+ let offset = 0;
466
+ for (let i = 0; i < doc.blocks.length; i++) {
467
+ const block = doc.blocks[i];
468
+ const el = createBlockElementFromDecorators(
469
+ ownerDoc,
470
+ block.decorators,
471
+ i,
472
+ block.type,
473
+ block.type === "heading" ? block.headingLevel : void 0,
474
+ block.depth
475
+ );
476
+ root.appendChild(el);
477
+ offset += block.raw.length + 1;
478
+ }
479
+ invalidateBlockCache(root);
480
+ }
481
+ function patchDirtyBlocks(root, doc, dirty) {
482
+ const ownerDoc = root.ownerDocument;
483
+ const blockElements = getBlockElements(root);
484
+ if (blockElements.length !== doc.blocks.length) {
485
+ fullRender(root, doc);
486
+ return;
487
+ }
488
+ for (let i = dirty.startBlock; i <= dirty.endBlock && i < doc.blocks.length; i++) {
489
+ const block = doc.blocks[i];
490
+ const existing = blockElements[i];
491
+ if (existing) {
492
+ updateBlockElementFromDecorators(
493
+ ownerDoc,
494
+ existing,
495
+ block.decorators,
496
+ block.type,
497
+ block.type === "heading" ? block.headingLevel : void 0,
498
+ block.depth
499
+ );
500
+ }
501
+ }
502
+ }
503
+ function detectAndRenderDirty(root, oldDoc, newDoc, fullFallback = false) {
504
+ const oldBlockCount = oldDoc.blocks.length;
505
+ const newBlockCount = newDoc.blocks.length;
506
+ if (oldBlockCount !== newBlockCount) {
507
+ fullRender(root, newDoc);
508
+ return;
509
+ }
510
+ let dirty = null;
511
+ for (let i = 0; i < newBlockCount; i++) {
512
+ if (newDoc.blocks[i].raw !== oldDoc.blocks[i].raw || newDoc.blocks[i].type !== oldDoc.blocks[i].type || newDoc.blocks[i].tokenizationContextKey !== oldDoc.blocks[i].tokenizationContextKey) {
513
+ dirty = expandDirtyRange(dirty, i, newBlockCount);
514
+ }
515
+ }
516
+ if (dirty) {
517
+ const expanded = expandWithContext(dirty, newBlockCount);
518
+ if (expanded) patchDirtyBlocks(root, newDoc, expanded);
519
+ } else if (fullFallback) {
520
+ fullRender(root, newDoc);
521
+ }
522
+ }
523
+ function getBlockElements(root) {
524
+ const elements = [];
525
+ for (const child of root.children) {
526
+ if (child instanceof HTMLElement && child.hasAttribute("data-owo-block")) {
527
+ elements.push(child);
528
+ }
529
+ }
530
+ return elements;
531
+ }
532
+
533
+ export {
534
+ invalidateBlockCache,
535
+ domRangeToOffset,
536
+ offsetToDomRange,
537
+ restoreSelection,
538
+ readSelection,
539
+ BQ_STEP,
540
+ buildBlockquoteBarsBoxShadow,
541
+ TOKEN_CLASS_EXEMPTIONS,
542
+ TOKEN_TO_CLASS,
543
+ BLOCK_TYPE_TO_CLASS,
544
+ createBlockElement,
545
+ updateBlockElement,
546
+ fullRender,
547
+ patchDirtyBlocks,
548
+ detectAndRenderDirty
549
+ };
@@ -0,0 +1,95 @@
1
+ // src/semantic/shared/registry.ts
2
+ function deepFreezeValue(value) {
3
+ if (Array.isArray(value)) {
4
+ for (const item of value) {
5
+ deepFreezeValue(item);
6
+ }
7
+ return Object.freeze(value);
8
+ }
9
+ if (value && typeof value === "object") {
10
+ for (const nestedValue of Object.values(value)) {
11
+ deepFreezeValue(nestedValue);
12
+ }
13
+ return Object.freeze(value);
14
+ }
15
+ return value;
16
+ }
17
+ function freezeDescriptor(descriptor) {
18
+ return deepFreezeValue(descriptor);
19
+ }
20
+ function createDescriptorRegistry(descriptors, familyName) {
21
+ const frozen = descriptors.map((descriptor) => freezeDescriptor({ ...descriptor }));
22
+ const index = /* @__PURE__ */ new Map();
23
+ for (const descriptor of frozen) {
24
+ if (index.has(descriptor.key)) {
25
+ throw new Error(`[owomark/semantic] duplicate ${familyName} descriptor key "${descriptor.key}"`);
26
+ }
27
+ index.set(descriptor.key, descriptor);
28
+ }
29
+ return {
30
+ list() {
31
+ return frozen;
32
+ },
33
+ get(key) {
34
+ return index.get(key);
35
+ }
36
+ };
37
+ }
38
+ function requireDescriptor(registry, key, familyName) {
39
+ const descriptor = registry.get(key);
40
+ if (!descriptor) {
41
+ throw new Error(`[owomark/semantic] unknown ${familyName} descriptor "${key}"`);
42
+ }
43
+ return descriptor;
44
+ }
45
+
46
+ // src/semantic/shared/validation.ts
47
+ function assertSpecIds(specIds, family, key) {
48
+ if (specIds.length === 0) {
49
+ throw new Error(`[owomark/semantic] ${family} descriptor "${key}" must declare at least one specId`);
50
+ }
51
+ }
52
+ function validateSyntaxDescriptors(descriptors) {
53
+ for (const descriptor of descriptors) {
54
+ assertSpecIds(descriptor.specIds, "syntax", descriptor.key);
55
+ }
56
+ }
57
+ function validateComponentDescriptors(descriptors) {
58
+ const directiveNames = /* @__PURE__ */ new Set();
59
+ for (const descriptor of descriptors) {
60
+ assertSpecIds(descriptor.specIds, "component", descriptor.key);
61
+ if (directiveNames.has(descriptor.directiveName)) {
62
+ throw new Error(`[owomark/semantic] duplicate component directive "${descriptor.directiveName}"`);
63
+ }
64
+ directiveNames.add(descriptor.directiveName);
65
+ }
66
+ }
67
+ function validateRuntimeDescriptors(descriptors) {
68
+ const blockTypes = /* @__PURE__ */ new Set();
69
+ for (const descriptor of descriptors) {
70
+ assertSpecIds(descriptor.specIds, "runtime", descriptor.key);
71
+ if (blockTypes.has(descriptor.blockType)) {
72
+ throw new Error(`[owomark/semantic] duplicate runtime block type "${descriptor.blockType}"`);
73
+ }
74
+ blockTypes.add(descriptor.blockType);
75
+ }
76
+ }
77
+ function validateEditorEntryDescriptors(descriptors) {
78
+ const commandIds = /* @__PURE__ */ new Set();
79
+ for (const descriptor of descriptors) {
80
+ assertSpecIds(descriptor.specIds, "editor", descriptor.key);
81
+ if (commandIds.has(descriptor.commandId)) {
82
+ throw new Error(`[owomark/semantic] duplicate editor command id "${descriptor.commandId}"`);
83
+ }
84
+ commandIds.add(descriptor.commandId);
85
+ }
86
+ }
87
+
88
+ export {
89
+ createDescriptorRegistry,
90
+ requireDescriptor,
91
+ validateSyntaxDescriptors,
92
+ validateComponentDescriptors,
93
+ validateRuntimeDescriptors,
94
+ validateEditorEntryDescriptors
95
+ };