@thescaffold/editor-addons 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,4328 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ ADDON_IMPLEMENTATIONS: () => ADDON_IMPLEMENTATIONS,
34
+ AccessibilityAddon: () => AccessibilityAddon,
35
+ AccessibilityAddonImpl: () => AccessibilityAddonImpl,
36
+ AlignmentAddon: () => AlignmentAddon,
37
+ AlignmentAddonImpl: () => AlignmentAddonImpl,
38
+ AudioAddon: () => AudioAddon,
39
+ AudioAddonImpl: () => AudioAddonImpl,
40
+ AutoSaveAddon: () => AutoSaveAddon,
41
+ AutoSaveAddonImpl: () => AutoSaveAddonImpl,
42
+ AwarenessAddon: () => AwarenessAddon,
43
+ AwarenessAddonImpl: () => AwarenessAddonImpl,
44
+ BlockHandlesAddon: () => BlockHandlesAddon,
45
+ BlockHandlesAddonImpl: () => BlockHandlesAddonImpl,
46
+ BlockquoteAddon: () => BlockquoteAddon,
47
+ BlockquoteAddonImpl: () => BlockquoteAddonImpl,
48
+ BoldAddon: () => BoldAddon,
49
+ BoldAddonImpl: () => BoldAddonImpl,
50
+ BookmarkAddon: () => BookmarkAddon,
51
+ BookmarkAddonImpl: () => BookmarkAddonImpl,
52
+ BracketMatchingAddon: () => BracketMatchingAddon,
53
+ BracketMatchingAddonImpl: () => BracketMatchingAddonImpl,
54
+ BreadcrumbAddon: () => BreadcrumbAddon,
55
+ BreadcrumbAddonImpl: () => BreadcrumbAddonImpl,
56
+ BubbleMenuAddon: () => BubbleMenuAddon,
57
+ BubbleMenuAddonImpl: () => BubbleMenuAddonImpl,
58
+ BulletListAddon: () => BulletListAddon,
59
+ BulletListAddonImpl: () => BulletListAddonImpl,
60
+ CalloutAddon: () => CalloutAddon,
61
+ CalloutAddonImpl: () => CalloutAddonImpl,
62
+ ClearFormattingAddon: () => ClearFormattingAddon,
63
+ ClearFormattingAddonImpl: () => ClearFormattingAddonImpl,
64
+ CodeAddon: () => CodeAddon,
65
+ CodeAddonImpl: () => CodeAddonImpl,
66
+ CodeAutoCompleteAddon: () => CodeAutoCompleteAddon,
67
+ CodeAutoCompleteAddonImpl: () => CodeAutoCompleteAddonImpl,
68
+ CodeBlockAddon: () => CodeBlockAddon,
69
+ CodeBlockAddonImpl: () => CodeBlockAddonImpl,
70
+ CodeFoldingAddon: () => CodeFoldingAddon,
71
+ CodeFoldingAddonImpl: () => CodeFoldingAddonImpl,
72
+ CodeLintAddon: () => CodeLintAddon,
73
+ CodeLintAddonImpl: () => CodeLintAddonImpl,
74
+ CollabAddon: () => CollabAddon,
75
+ CollabAddonImpl: () => CollabAddonImpl,
76
+ ColumnsAddon: () => ColumnsAddon,
77
+ ColumnsAddonImpl: () => ColumnsAddonImpl,
78
+ CommandPaletteAddon: () => CommandPaletteAddon,
79
+ CommandPaletteAddonImpl: () => CommandPaletteAddonImpl,
80
+ CommandsAddon: () => CommandsAddon,
81
+ CommandsAddonImpl: () => CommandsAddonImpl,
82
+ CommentsAddon: () => CommentsAddon,
83
+ CommentsAddonImpl: () => CommentsAddonImpl,
84
+ ContentAddon: () => ContentAddon,
85
+ ContentAddonImpl: () => ContentAddonImpl,
86
+ ContextMenuAddon: () => ContextMenuAddon,
87
+ ContextMenuAddonImpl: () => ContextMenuAddonImpl,
88
+ CountAddon: () => CountAddon,
89
+ CountAddonImpl: () => CountAddonImpl,
90
+ CoverAddon: () => CoverAddon,
91
+ CoverAddonImpl: () => CoverAddonImpl,
92
+ DetailsAddon: () => DetailsAddon,
93
+ DetailsAddonImpl: () => DetailsAddonImpl,
94
+ DiffAddon: () => DiffAddon,
95
+ DiffAddonImpl: () => DiffAddonImpl,
96
+ DividerAddon: () => DividerAddon,
97
+ DividerAddonImpl: () => DividerAddonImpl,
98
+ DocxAddon: () => DocxAddon,
99
+ DocxAddonImpl: () => DocxAddonImpl,
100
+ EmbedAddon: () => EmbedAddon,
101
+ EmbedAddonImpl: () => EmbedAddonImpl,
102
+ EmojiAddon: () => EmojiAddon,
103
+ EmojiAddonImpl: () => EmojiAddonImpl,
104
+ EquationAddon: () => EquationAddon,
105
+ EquationAddonImpl: () => EquationAddonImpl,
106
+ FileAddon: () => FileAddon,
107
+ FileAddonImpl: () => FileAddonImpl,
108
+ FocusModeAddon: () => FocusModeAddon,
109
+ FocusModeAddonImpl: () => FocusModeAddonImpl,
110
+ FontFamilyAddon: () => FontFamilyAddon,
111
+ FontFamilyAddonImpl: () => FontFamilyAddonImpl,
112
+ FontSizeAddon: () => FontSizeAddon,
113
+ FontSizeAddonImpl: () => FontSizeAddonImpl,
114
+ FootnoteAddon: () => FootnoteAddon,
115
+ FootnoteAddonImpl: () => FootnoteAddonImpl,
116
+ FullScreenAddon: () => FullScreenAddon,
117
+ FullScreenAddonImpl: () => FullScreenAddonImpl,
118
+ GrammarAddon: () => GrammarAddon,
119
+ GrammarAddonImpl: () => GrammarAddonImpl,
120
+ HeadingsAddon: () => HeadingsAddon,
121
+ HeadingsAddonImpl: () => HeadingsAddonImpl,
122
+ HighlightAddon: () => HighlightAddon,
123
+ HighlightAddonImpl: () => HighlightAddonImpl,
124
+ HistoryAddon: () => HistoryAddon,
125
+ HistoryAddonImpl: () => HistoryAddonImpl,
126
+ ImageAddon: () => ImageAddon,
127
+ ImageAddonImpl: () => ImageAddonImpl,
128
+ IndentAddon: () => IndentAddon,
129
+ IndentAddonImpl: () => IndentAddonImpl,
130
+ InlineCodeAddon: () => InlineCodeAddon,
131
+ InlineCodeAddonImpl: () => InlineCodeAddonImpl,
132
+ InputRulesAddon: () => InputRulesAddon,
133
+ InputRulesAddonImpl: () => InputRulesAddonImpl,
134
+ ItalicAddon: () => ItalicAddon,
135
+ ItalicAddonImpl: () => ItalicAddonImpl,
136
+ KeymapAddon: () => KeymapAddon,
137
+ KeymapAddonImpl: () => KeymapAddonImpl,
138
+ LineHeightAddon: () => LineHeightAddon,
139
+ LineHeightAddonImpl: () => LineHeightAddonImpl,
140
+ LineNumbersAddon: () => LineNumbersAddon,
141
+ LineNumbersAddonImpl: () => LineNumbersAddonImpl,
142
+ LinkAddon: () => LinkAddon,
143
+ LinkAddonImpl: () => LinkAddonImpl,
144
+ ListsAddon: () => ListsAddon,
145
+ MarkdownAddon: () => MarkdownAddon,
146
+ MarkdownAddonImpl: () => MarkdownAddonImpl,
147
+ MentionAddon: () => MentionAddon,
148
+ MentionAddonImpl: () => MentionAddonImpl,
149
+ MiniMapAddon: () => MiniMapAddon,
150
+ MiniMapAddonImpl: () => MiniMapAddonImpl,
151
+ OrderedListAddon: () => OrderedListAddon,
152
+ OrderedListAddonImpl: () => OrderedListAddonImpl,
153
+ OutlineAddon: () => OutlineAddon,
154
+ OutlineAddonImpl: () => OutlineAddonImpl,
155
+ PageBreakAddon: () => PageBreakAddon,
156
+ PageBreakAddonImpl: () => PageBreakAddonImpl,
157
+ PageSetupAddon: () => PageSetupAddon,
158
+ PageSetupAddonImpl: () => PageSetupAddonImpl,
159
+ ParagraphSpacingAddon: () => ParagraphSpacingAddon,
160
+ ParagraphSpacingAddonImpl: () => ParagraphSpacingAddonImpl,
161
+ PdfAddon: () => PdfAddon,
162
+ PdfAddonImpl: () => PdfAddonImpl,
163
+ PlaceholderAddon: () => PlaceholderAddon,
164
+ PlaceholderAddonImpl: () => PlaceholderAddonImpl,
165
+ PresenceAddon: () => PresenceAddon,
166
+ PresenceAddonImpl: () => PresenceAddonImpl,
167
+ PrintAddon: () => PrintAddon,
168
+ PrintAddonImpl: () => PrintAddonImpl,
169
+ ReadOnlyAddon: () => ReadOnlyAddon,
170
+ ReadOnlyAddonImpl: () => ReadOnlyAddonImpl,
171
+ ReadingTimeAddon: () => ReadingTimeAddon,
172
+ ReadingTimeAddonImpl: () => ReadingTimeAddonImpl,
173
+ SchemaAddon: () => SchemaAddon,
174
+ SchemaAddonImpl: () => SchemaAddonImpl,
175
+ SearchAddon: () => SearchAddon,
176
+ SearchAddonImpl: () => SearchAddonImpl,
177
+ SlashMenuAddon: () => SlashMenuAddon,
178
+ SlashMenuAddonImpl: () => SlashMenuAddonImpl,
179
+ SmartChipAddon: () => SmartChipAddon,
180
+ SmartChipAddonImpl: () => SmartChipAddonImpl,
181
+ SpellCheckAddon: () => SpellCheckAddon,
182
+ SpellCheckAddonImpl: () => SpellCheckAddonImpl,
183
+ StatusBarAddon: () => StatusBarAddon,
184
+ StatusBarAddonImpl: () => StatusBarAddonImpl,
185
+ StrikethroughAddon: () => StrikethroughAddon,
186
+ StrikethroughAddonImpl: () => StrikethroughAddonImpl,
187
+ SubscriptAddon: () => SubscriptAddon,
188
+ SubscriptAddonImpl: () => SubscriptAddonImpl,
189
+ SuggestionsAddon: () => SuggestionsAddon,
190
+ SuggestionsAddonImpl: () => SuggestionsAddonImpl,
191
+ SuperscriptAddon: () => SuperscriptAddon,
192
+ SuperscriptAddonImpl: () => SuperscriptAddonImpl,
193
+ TableAddon: () => TableAddon,
194
+ TableAddonImpl: () => TableAddonImpl,
195
+ TableOfContentsAddon: () => TableOfContentsAddon,
196
+ TableOfContentsAddonImpl: () => TableOfContentsAddonImpl,
197
+ TaskListAddon: () => TaskListAddon,
198
+ TaskListAddonImpl: () => TaskListAddonImpl,
199
+ TemplatesAddon: () => TemplatesAddon,
200
+ TemplatesAddonImpl: () => TemplatesAddonImpl,
201
+ TextColorAddon: () => TextColorAddon,
202
+ TextColorAddonImpl: () => TextColorAddonImpl,
203
+ ToggleListAddon: () => ToggleListAddon,
204
+ ToggleListAddonImpl: () => ToggleListAddonImpl,
205
+ ToolbarAddon: () => ToolbarAddon,
206
+ ToolbarAddonImpl: () => ToolbarAddonImpl,
207
+ UnderlineAddon: () => UnderlineAddon,
208
+ UnderlineAddonImpl: () => UnderlineAddonImpl,
209
+ VersionAddon: () => VersionAddon,
210
+ VersionAddonImpl: () => VersionAddonImpl,
211
+ VideoAddon: () => VideoAddon,
212
+ VideoAddonImpl: () => VideoAddonImpl,
213
+ createCommandGroup: () => createCommandGroup
214
+ });
215
+ module.exports = __toCommonJS(src_exports);
216
+
217
+ // src/base/commands/index.ts
218
+ function CommandsAddon() {
219
+ return {
220
+ id: "x/commands",
221
+ dependencies: ["x/schema"],
222
+ impl: CommandsAddonImpl
223
+ };
224
+ }
225
+ var CommandsAddonImpl = {
226
+ id: "x/commands",
227
+ init(ctx) {
228
+ ctx.commands.register({
229
+ id: "selectAll",
230
+ label: "Select All",
231
+ shortcut: "Mod-a",
232
+ isEnabled: () => true,
233
+ isActive: () => false,
234
+ execute: () => true
235
+ });
236
+ return {};
237
+ }
238
+ };
239
+
240
+ // src/base/history/index.ts
241
+ function HistoryAddon() {
242
+ return { id: "x/history", impl: HistoryAddonImpl };
243
+ }
244
+ var HistoryAddonImpl = {
245
+ id: "x/history",
246
+ init(ctx) {
247
+ const ctxImpl = ctx;
248
+ ctx.commands.register({
249
+ id: "undo",
250
+ label: "Undo",
251
+ icon: "undo",
252
+ shortcut: "Mod-z",
253
+ isEnabled: () => true,
254
+ isActive: () => false,
255
+ execute: () => ctxImpl.dispatchPmCommand("undo")
256
+ });
257
+ ctx.commands.register({
258
+ id: "redo",
259
+ label: "Redo",
260
+ icon: "redo",
261
+ shortcut: "Mod-Shift-z",
262
+ isEnabled: () => true,
263
+ isActive: () => false,
264
+ execute: () => ctxImpl.dispatchPmCommand("redo")
265
+ });
266
+ return {};
267
+ }
268
+ };
269
+
270
+ // src/base/input-rules/index.ts
271
+ function InputRulesAddon() {
272
+ return {
273
+ id: "x/input-rules",
274
+ dependencies: ["x/schema"],
275
+ impl: InputRulesAddonImpl
276
+ };
277
+ }
278
+ var InputRulesAddonImpl = {
279
+ id: "x/input-rules",
280
+ init(_ctx) {
281
+ return {};
282
+ }
283
+ };
284
+
285
+ // src/base/keymap/index.ts
286
+ function KeymapAddon(config) {
287
+ return {
288
+ id: "x/keymap",
289
+ config,
290
+ dependencies: ["x/commands"],
291
+ impl: KeymapAddonImpl
292
+ };
293
+ }
294
+ var IS_MAC = typeof navigator !== "undefined" && /Mac|iP(hone|ad|od)/.test(navigator.platform);
295
+ function normalizeShortcut(shortcut) {
296
+ return shortcut.split("-").map((part) => part.trim().toLowerCase()).filter(Boolean).sort((a, b) => {
297
+ const order = ["mod", "meta", "ctrl", "alt", "shift"];
298
+ const ai = order.indexOf(a);
299
+ const bi = order.indexOf(b);
300
+ if (ai === -1 && bi === -1) return 0;
301
+ if (ai === -1) return 1;
302
+ if (bi === -1) return -1;
303
+ return ai - bi;
304
+ }).join("-");
305
+ }
306
+ function eventToShortcut(e) {
307
+ const parts = [];
308
+ if (e.metaKey || e.ctrlKey) parts.push("mod");
309
+ if (e.altKey) parts.push("alt");
310
+ if (e.shiftKey) parts.push("shift");
311
+ let key = e.key;
312
+ if (key.length === 1) key = key.toLowerCase();
313
+ if (key === " ") key = "space";
314
+ parts.push(key.toLowerCase());
315
+ return parts.join("-");
316
+ }
317
+ var KeymapAddonImpl = {
318
+ id: "x/keymap",
319
+ init(ctx, config = {}) {
320
+ const disabled = new Set(config.disabled ?? []);
321
+ const overrides = config.overrides ?? {};
322
+ const handleKeydown = (e) => {
323
+ const shortcut = eventToShortcut(e);
324
+ for (const cmd of ctx.commands.getAll()) {
325
+ if (disabled.has(cmd.id)) continue;
326
+ const cmdShortcut = overrides[cmd.id] ?? cmd.shortcut;
327
+ if (!cmdShortcut) continue;
328
+ if (normalizeShortcut(cmdShortcut) === shortcut) {
329
+ if (cmd.isEnabled?.(ctx) === false) continue;
330
+ e.preventDefault();
331
+ cmd.execute(ctx);
332
+ return;
333
+ }
334
+ }
335
+ };
336
+ const content = ctx.getSlot("content");
337
+ const target = content ?? document;
338
+ target.addEventListener("keydown", handleKeydown, true);
339
+ return {
340
+ destroy() {
341
+ target.removeEventListener(
342
+ "keydown",
343
+ handleKeydown,
344
+ true
345
+ );
346
+ }
347
+ };
348
+ }
349
+ };
350
+
351
+ // src/base/schema/index.ts
352
+ function SchemaAddon(config) {
353
+ return { id: "x/schema", config, impl: SchemaAddonImpl };
354
+ }
355
+ var SchemaAddonImpl = {
356
+ id: "x/schema",
357
+ initSchema(ctx, _config = {}) {
358
+ ctx.addNode({
359
+ name: "doc",
360
+ content: "block+"
361
+ });
362
+ ctx.addNode({
363
+ name: "paragraph",
364
+ group: "block",
365
+ content: "inline*",
366
+ attrs: {
367
+ align: { default: null },
368
+ indent: { default: 0 },
369
+ lineHeight: { default: null }
370
+ },
371
+ parseDOM: [
372
+ {
373
+ tag: "p",
374
+ getAttrs: (el) => {
375
+ const e = el;
376
+ return {
377
+ align: e.style.textAlign || null,
378
+ indent: parseInt(e.dataset["indent"] ?? "0", 10) || 0,
379
+ lineHeight: e.style.lineHeight || null
380
+ };
381
+ }
382
+ }
383
+ ],
384
+ toDOM: (node) => {
385
+ const style = [];
386
+ if (node.attrs.align) style.push(`text-align:${node.attrs.align}`);
387
+ if (node.attrs.lineHeight)
388
+ style.push(`line-height:${node.attrs.lineHeight}`);
389
+ const attrs = {};
390
+ if (style.length > 0) attrs["style"] = style.join(";");
391
+ if (node.attrs.indent > 0)
392
+ attrs["data-indent"] = String(node.attrs.indent);
393
+ return ["p", attrs, 0];
394
+ }
395
+ });
396
+ ctx.addNode({
397
+ name: "text",
398
+ group: "inline"
399
+ });
400
+ ctx.addNode({
401
+ name: "hardBreak",
402
+ group: "inline",
403
+ inline: true,
404
+ selectable: false,
405
+ parseDOM: [{ tag: "br" }],
406
+ toDOM: () => ["br"]
407
+ });
408
+ },
409
+ init(_ctx, _config = {}) {
410
+ return {};
411
+ }
412
+ };
413
+
414
+ // src/marks/index.ts
415
+ function BoldAddon() {
416
+ return { id: "x/bold", dependencies: ["x/schema"], impl: BoldAddonImpl };
417
+ }
418
+ var BoldAddonImpl = {
419
+ id: "x/bold",
420
+ initSchema(ctx) {
421
+ ctx.addMark({
422
+ name: "bold",
423
+ parseDOM: [
424
+ { tag: "strong" },
425
+ { tag: "b" },
426
+ { style: "font-weight=bold" }
427
+ ],
428
+ toDOM: () => ["strong", 0]
429
+ });
430
+ },
431
+ init(ctx) {
432
+ ctx.commands.register({
433
+ id: "bold",
434
+ label: "Bold",
435
+ icon: "bold",
436
+ shortcut: "Mod-b",
437
+ isEnabled: (c) => c.selection.canHaveMark("bold"),
438
+ isActive: (c) => c.selection.hasMark("bold"),
439
+ execute: (c) => {
440
+ c.addMark("bold");
441
+ return true;
442
+ }
443
+ });
444
+ return {};
445
+ }
446
+ };
447
+ function ItalicAddon() {
448
+ return { id: "x/italic", dependencies: ["x/schema"], impl: ItalicAddonImpl };
449
+ }
450
+ var ItalicAddonImpl = {
451
+ id: "x/italic",
452
+ initSchema(ctx) {
453
+ ctx.addMark({
454
+ name: "italic",
455
+ parseDOM: [{ tag: "em" }, { tag: "i" }, { style: "font-style=italic" }],
456
+ toDOM: () => ["em", 0]
457
+ });
458
+ },
459
+ init(ctx) {
460
+ ctx.commands.register({
461
+ id: "italic",
462
+ label: "Italic",
463
+ icon: "italic",
464
+ shortcut: "Mod-i",
465
+ isEnabled: (c) => c.selection.canHaveMark("italic"),
466
+ isActive: (c) => c.selection.hasMark("italic"),
467
+ execute: (c) => {
468
+ c.addMark("italic");
469
+ return true;
470
+ }
471
+ });
472
+ return {};
473
+ }
474
+ };
475
+ function UnderlineAddon() {
476
+ return {
477
+ id: "x/underline",
478
+ dependencies: ["x/schema"],
479
+ impl: UnderlineAddonImpl
480
+ };
481
+ }
482
+ var UnderlineAddonImpl = {
483
+ id: "x/underline",
484
+ initSchema(ctx) {
485
+ ctx.addMark({
486
+ name: "underline",
487
+ parseDOM: [{ tag: "u" }, { style: "text-decoration=underline" }],
488
+ toDOM: () => ["u", 0]
489
+ });
490
+ },
491
+ init(ctx) {
492
+ ctx.commands.register({
493
+ id: "underline",
494
+ label: "Underline",
495
+ icon: "underline",
496
+ shortcut: "Mod-u",
497
+ isEnabled: (c) => c.selection.canHaveMark("underline"),
498
+ isActive: (c) => c.selection.hasMark("underline"),
499
+ execute: (c) => {
500
+ c.addMark("underline");
501
+ return true;
502
+ }
503
+ });
504
+ return {};
505
+ }
506
+ };
507
+ function StrikethroughAddon() {
508
+ return {
509
+ id: "x/strikethrough",
510
+ dependencies: ["x/schema"],
511
+ impl: StrikethroughAddonImpl
512
+ };
513
+ }
514
+ var StrikethroughAddonImpl = {
515
+ id: "x/strikethrough",
516
+ initSchema(ctx) {
517
+ ctx.addMark({
518
+ name: "strikethrough",
519
+ parseDOM: [{ tag: "s" }, { tag: "del" }, { tag: "strike" }],
520
+ toDOM: () => ["s", 0]
521
+ });
522
+ },
523
+ init(ctx) {
524
+ ctx.commands.register({
525
+ id: "strikethrough",
526
+ label: "Strikethrough",
527
+ icon: "strikethrough",
528
+ isEnabled: (c) => c.selection.canHaveMark("strikethrough"),
529
+ isActive: (c) => c.selection.hasMark("strikethrough"),
530
+ execute: (c) => {
531
+ c.addMark("strikethrough");
532
+ return true;
533
+ }
534
+ });
535
+ return {};
536
+ }
537
+ };
538
+ function InlineCodeAddon() {
539
+ return {
540
+ id: "x/inline-code",
541
+ dependencies: ["x/schema"],
542
+ impl: InlineCodeAddonImpl
543
+ };
544
+ }
545
+ var InlineCodeAddonImpl = {
546
+ id: "x/inline-code",
547
+ initSchema(ctx) {
548
+ ctx.addMark({
549
+ name: "code",
550
+ parseDOM: [{ tag: "code" }],
551
+ toDOM: () => ["code", 0]
552
+ });
553
+ },
554
+ init(ctx) {
555
+ ctx.commands.register({
556
+ id: "inlineCode",
557
+ label: "Inline Code",
558
+ icon: "code",
559
+ isEnabled: (c) => c.selection.canHaveMark("code"),
560
+ isActive: (c) => c.selection.hasMark("code"),
561
+ execute: (c) => {
562
+ c.addMark("code");
563
+ return true;
564
+ }
565
+ });
566
+ return {};
567
+ }
568
+ };
569
+ function SubscriptAddon() {
570
+ return {
571
+ id: "x/subscript",
572
+ dependencies: ["x/schema"],
573
+ impl: SubscriptAddonImpl
574
+ };
575
+ }
576
+ var SubscriptAddonImpl = {
577
+ id: "x/subscript",
578
+ initSchema(ctx) {
579
+ ctx.addMark({
580
+ name: "subscript",
581
+ excludes: "superscript",
582
+ parseDOM: [{ tag: "sub" }],
583
+ toDOM: () => ["sub", 0]
584
+ });
585
+ },
586
+ init(ctx) {
587
+ ctx.commands.register({
588
+ id: "subscript",
589
+ label: "Subscript",
590
+ icon: "subscript",
591
+ isEnabled: (c) => c.selection.canHaveMark("subscript"),
592
+ isActive: (c) => c.selection.hasMark("subscript"),
593
+ execute: (c) => {
594
+ c.addMark("subscript");
595
+ return true;
596
+ }
597
+ });
598
+ return {};
599
+ }
600
+ };
601
+ function SuperscriptAddon() {
602
+ return {
603
+ id: "x/superscript",
604
+ dependencies: ["x/schema"],
605
+ impl: SuperscriptAddonImpl
606
+ };
607
+ }
608
+ var SuperscriptAddonImpl = {
609
+ id: "x/superscript",
610
+ initSchema(ctx) {
611
+ ctx.addMark({
612
+ name: "superscript",
613
+ excludes: "subscript",
614
+ parseDOM: [{ tag: "sup" }],
615
+ toDOM: () => ["sup", 0]
616
+ });
617
+ },
618
+ init(ctx) {
619
+ ctx.commands.register({
620
+ id: "superscript",
621
+ label: "Superscript",
622
+ icon: "superscript",
623
+ isEnabled: (c) => c.selection.canHaveMark("superscript"),
624
+ isActive: (c) => c.selection.hasMark("superscript"),
625
+ execute: (c) => {
626
+ c.addMark("superscript");
627
+ return true;
628
+ }
629
+ });
630
+ return {};
631
+ }
632
+ };
633
+ function HighlightAddon(config) {
634
+ return {
635
+ id: "x/highlight",
636
+ config,
637
+ dependencies: ["x/schema"],
638
+ impl: HighlightAddonImpl
639
+ };
640
+ }
641
+ var HighlightAddonImpl = {
642
+ id: "x/highlight",
643
+ initSchema(ctx) {
644
+ ctx.addMark({
645
+ name: "highlight",
646
+ attrs: { color: { default: "#ffff00" } },
647
+ parseDOM: [{ tag: "mark" }],
648
+ toDOM: (mark) => [
649
+ "mark",
650
+ { style: `background:${mark.attrs.color}` },
651
+ 0
652
+ ]
653
+ });
654
+ },
655
+ init(ctx, config = {}) {
656
+ ctx.commands.register({
657
+ id: "highlight",
658
+ label: "Highlight",
659
+ icon: "highlight",
660
+ isEnabled: (c) => c.selection.canHaveMark("highlight"),
661
+ isActive: (c) => c.selection.hasMark("highlight"),
662
+ execute: (c) => {
663
+ c.addMark("highlight", { color: config.defaultColor ?? "#ffff00" });
664
+ return true;
665
+ }
666
+ });
667
+ return {};
668
+ }
669
+ };
670
+ function TextColorAddon(config) {
671
+ return {
672
+ id: "x/text-color",
673
+ config,
674
+ dependencies: ["x/schema"],
675
+ impl: TextColorAddonImpl
676
+ };
677
+ }
678
+ var TextColorAddonImpl = {
679
+ id: "x/text-color",
680
+ initSchema(ctx) {
681
+ ctx.addMark({
682
+ name: "textColor",
683
+ attrs: { color: { default: null } },
684
+ parseDOM: [{ style: "color", getAttrs: (v) => ({ color: v }) }],
685
+ toDOM: (mark) => [
686
+ "span",
687
+ { style: `color:${mark.attrs.color}` },
688
+ 0
689
+ ]
690
+ });
691
+ },
692
+ init(ctx, config = {}) {
693
+ ctx.commands.register({
694
+ id: "textColor",
695
+ label: "Text Color",
696
+ icon: "text-color",
697
+ isEnabled: (c) => c.selection.canHaveMark("textColor"),
698
+ isActive: (c) => c.selection.hasMark("textColor"),
699
+ execute: (c) => {
700
+ c.addMark("textColor", { color: config.defaultColor ?? "#000000" });
701
+ return true;
702
+ }
703
+ });
704
+ ctx.commands.register({
705
+ id: "clearTextColor",
706
+ label: "Clear Text Color",
707
+ isEnabled: (c) => c.selection.hasMark("textColor"),
708
+ isActive: () => false,
709
+ execute: (c) => {
710
+ c.removeMark("textColor");
711
+ return true;
712
+ }
713
+ });
714
+ return {};
715
+ }
716
+ };
717
+ function FontFamilyAddon(config) {
718
+ return {
719
+ id: "x/font-family",
720
+ config,
721
+ dependencies: ["x/schema"],
722
+ impl: FontFamilyAddonImpl
723
+ };
724
+ }
725
+ var FontFamilyAddonImpl = {
726
+ id: "x/font-family",
727
+ initSchema(ctx) {
728
+ ctx.addMark({
729
+ name: "fontFamily",
730
+ attrs: { family: { default: null } },
731
+ parseDOM: [
732
+ { style: "font-family", getAttrs: (v) => ({ family: v }) }
733
+ ],
734
+ toDOM: (mark) => [
735
+ "span",
736
+ { style: `font-family:${mark.attrs.family}` },
737
+ 0
738
+ ]
739
+ });
740
+ },
741
+ init(ctx) {
742
+ ctx.commands.register({
743
+ id: "fontFamily",
744
+ label: "Font Family",
745
+ icon: "font-family",
746
+ isEnabled: () => true,
747
+ isActive: () => false,
748
+ execute: (c, args) => {
749
+ const family = args?.family;
750
+ if (!family) return false;
751
+ c.addMark("fontFamily", { family });
752
+ return true;
753
+ }
754
+ });
755
+ ctx.commands.register({
756
+ id: "clearFontFamily",
757
+ label: "Clear Font Family",
758
+ isEnabled: (c) => c.selection.hasMark("fontFamily"),
759
+ isActive: () => false,
760
+ execute: (c) => {
761
+ c.removeMark("fontFamily");
762
+ return true;
763
+ }
764
+ });
765
+ return {};
766
+ }
767
+ };
768
+ function FontSizeAddon(config) {
769
+ return {
770
+ id: "x/font-size",
771
+ config,
772
+ dependencies: ["x/schema"],
773
+ impl: FontSizeAddonImpl
774
+ };
775
+ }
776
+ var FontSizeAddonImpl = {
777
+ id: "x/font-size",
778
+ initSchema(ctx) {
779
+ ctx.addMark({
780
+ name: "fontSize",
781
+ attrs: { size: { default: null } },
782
+ parseDOM: [
783
+ { style: "font-size", getAttrs: (v) => ({ size: v }) }
784
+ ],
785
+ toDOM: (mark) => [
786
+ "span",
787
+ { style: `font-size:${mark.attrs.size}` },
788
+ 0
789
+ ]
790
+ });
791
+ },
792
+ init(ctx) {
793
+ ctx.commands.register({
794
+ id: "fontSize",
795
+ label: "Font Size",
796
+ isEnabled: () => true,
797
+ isActive: () => false,
798
+ execute: (c, args) => {
799
+ const size = args?.size;
800
+ if (!size) return false;
801
+ c.addMark("fontSize", { size });
802
+ return true;
803
+ }
804
+ });
805
+ ctx.commands.register({
806
+ id: "increaseFontSize",
807
+ label: "Increase Font Size",
808
+ isEnabled: () => true,
809
+ isActive: () => false,
810
+ execute: () => true
811
+ });
812
+ ctx.commands.register({
813
+ id: "decreaseFontSize",
814
+ label: "Decrease Font Size",
815
+ isEnabled: () => true,
816
+ isActive: () => false,
817
+ execute: () => true
818
+ });
819
+ ctx.commands.register({
820
+ id: "clearFontSize",
821
+ label: "Clear Font Size",
822
+ isEnabled: (c) => c.selection.hasMark("fontSize"),
823
+ isActive: () => false,
824
+ execute: (c) => {
825
+ c.removeMark("fontSize");
826
+ return true;
827
+ }
828
+ });
829
+ return {};
830
+ }
831
+ };
832
+ function ClearFormattingAddon() {
833
+ return {
834
+ id: "x/clear-formatting",
835
+ dependencies: ["x/commands"],
836
+ impl: ClearFormattingAddonImpl
837
+ };
838
+ }
839
+ var ClearFormattingAddonImpl = {
840
+ id: "x/clear-formatting",
841
+ init(ctx) {
842
+ ctx.commands.register({
843
+ id: "clearFormatting",
844
+ label: "Clear Formatting",
845
+ icon: "clear-formatting",
846
+ shortcut: "Mod-\\",
847
+ isEnabled: () => true,
848
+ isActive: () => false,
849
+ execute: (c) => {
850
+ for (const m of c.schema.getMarks()) c.removeMark(m.name);
851
+ return true;
852
+ }
853
+ });
854
+ return {};
855
+ }
856
+ };
857
+
858
+ // src/formatting/index.ts
859
+ function AlignmentAddon() {
860
+ return {
861
+ id: "x/alignment",
862
+ dependencies: ["x/schema"],
863
+ impl: AlignmentAddonImpl
864
+ };
865
+ }
866
+ var AlignmentAddonImpl = {
867
+ id: "x/alignment",
868
+ init(ctx) {
869
+ const setAttrs = (c, patch) => c.setBlockAttrs(patch);
870
+ for (const align of ["left", "center", "right", "justify"]) {
871
+ const id = `align${align.charAt(0).toUpperCase()}${align.slice(1)}`;
872
+ ctx.commands.register({
873
+ id,
874
+ label: `Align ${align.charAt(0).toUpperCase()}${align.slice(1)}`,
875
+ icon: `align-${align}`,
876
+ isEnabled: () => true,
877
+ isActive: () => false,
878
+ execute: (c) => setAttrs(c, { align })
879
+ });
880
+ }
881
+ return {};
882
+ }
883
+ };
884
+ function LineHeightAddon(config) {
885
+ return {
886
+ id: "x/line-height",
887
+ config,
888
+ dependencies: ["x/schema"],
889
+ impl: LineHeightAddonImpl
890
+ };
891
+ }
892
+ var LineHeightAddonImpl = {
893
+ id: "x/line-height",
894
+ init(ctx) {
895
+ ctx.commands.register({
896
+ id: "lineHeight",
897
+ label: "Line Height",
898
+ isEnabled: () => true,
899
+ isActive: () => false,
900
+ execute: (c, args) => {
901
+ const value = args?.value;
902
+ if (value == null) return false;
903
+ return c.setBlockAttrs({ lineHeight: String(value) });
904
+ }
905
+ });
906
+ return {};
907
+ }
908
+ };
909
+ function ParagraphSpacingAddon() {
910
+ return {
911
+ id: "x/paragraph-spacing",
912
+ dependencies: ["x/schema"],
913
+ impl: ParagraphSpacingAddonImpl
914
+ };
915
+ }
916
+ var ParagraphSpacingAddonImpl = {
917
+ id: "x/paragraph-spacing",
918
+ init(ctx) {
919
+ ctx.commands.register({
920
+ id: "paragraphSpacing",
921
+ label: "Paragraph Spacing",
922
+ isEnabled: () => true,
923
+ isActive: () => false,
924
+ execute: (c, args) => {
925
+ const value = args?.value;
926
+ if (value == null) return false;
927
+ return c.setBlockAttrs({ paragraphSpacing: String(value) });
928
+ }
929
+ });
930
+ return {};
931
+ }
932
+ };
933
+ function IndentAddon() {
934
+ return { id: "x/indent", dependencies: ["x/schema"], impl: IndentAddonImpl };
935
+ }
936
+ var IndentAddonImpl = {
937
+ id: "x/indent",
938
+ init(ctx) {
939
+ const bump = (c, delta) => {
940
+ const view = c._prosemirror;
941
+ if (!view) return false;
942
+ const { from, to } = view.state.selection;
943
+ let current = 0;
944
+ view.state.doc.nodeAt(from)?.attrs;
945
+ const node = view.state.doc.nodeAt(Math.max(0, from - 1));
946
+ if (node && typeof node.attrs?.["indent"] === "number")
947
+ current = node.attrs["indent"];
948
+ const next = Math.max(0, Math.min(10, current + delta));
949
+ return c.setBlockAttrs({ indent: next });
950
+ };
951
+ ctx.commands.register({
952
+ id: "indent",
953
+ label: "Indent",
954
+ icon: "indent",
955
+ shortcut: "Tab",
956
+ isEnabled: () => true,
957
+ isActive: () => false,
958
+ execute: (c) => bump(c, 1)
959
+ });
960
+ ctx.commands.register({
961
+ id: "outdent",
962
+ label: "Outdent",
963
+ icon: "outdent",
964
+ shortcut: "Shift-Tab",
965
+ isEnabled: () => true,
966
+ isActive: () => false,
967
+ execute: (c) => bump(c, -1)
968
+ });
969
+ return {};
970
+ }
971
+ };
972
+
973
+ // src/blocks/index.ts
974
+ function HeadingsAddon() {
975
+ return {
976
+ id: "x/headings",
977
+ dependencies: ["x/schema"],
978
+ impl: HeadingsAddonImpl
979
+ };
980
+ }
981
+ var HeadingsAddonImpl = {
982
+ id: "x/headings",
983
+ initSchema(ctx) {
984
+ ctx.addNode({
985
+ name: "heading",
986
+ group: "block",
987
+ content: "inline*",
988
+ attrs: {
989
+ level: { default: 1 },
990
+ align: { default: null },
991
+ indent: { default: 0 },
992
+ lineHeight: { default: null }
993
+ },
994
+ parseDOM: [1, 2, 3, 4, 5, 6].map((level) => ({
995
+ tag: `h${level}`,
996
+ getAttrs: () => ({ level })
997
+ })),
998
+ toDOM: (node) => {
999
+ const style = [];
1000
+ if (node.attrs.align) style.push(`text-align:${node.attrs.align}`);
1001
+ if (node.attrs.lineHeight)
1002
+ style.push(`line-height:${node.attrs.lineHeight}`);
1003
+ const attrs = {};
1004
+ if (style.length > 0) attrs["style"] = style.join(";");
1005
+ if (node.attrs.indent > 0)
1006
+ attrs["data-indent"] = String(node.attrs.indent);
1007
+ return [`h${node.attrs.level}`, attrs, 0];
1008
+ }
1009
+ });
1010
+ },
1011
+ init(ctx) {
1012
+ const ctxImpl = ctx;
1013
+ for (let level = 1; level <= 6; level++) {
1014
+ ctx.commands.register({
1015
+ id: `heading${level}`,
1016
+ label: `Heading ${level}`,
1017
+ icon: `h${level}`,
1018
+ shortcut: `Mod-Alt-${level}`,
1019
+ isEnabled: () => true,
1020
+ isActive: () => false,
1021
+ execute: () => ctxImpl.setBlockType("heading", { level })
1022
+ });
1023
+ }
1024
+ ctx.commands.register({
1025
+ id: "paragraph",
1026
+ label: "Paragraph",
1027
+ shortcut: "Mod-Alt-0",
1028
+ isEnabled: () => true,
1029
+ isActive: () => false,
1030
+ execute: () => ctxImpl.setBlockType("paragraph")
1031
+ });
1032
+ return {};
1033
+ }
1034
+ };
1035
+ function BlockquoteAddon() {
1036
+ return {
1037
+ id: "x/blockquote",
1038
+ dependencies: ["x/schema"],
1039
+ impl: BlockquoteAddonImpl
1040
+ };
1041
+ }
1042
+ var BlockquoteAddonImpl = {
1043
+ id: "x/blockquote",
1044
+ initSchema(ctx) {
1045
+ ctx.addNode({
1046
+ name: "blockquote",
1047
+ group: "block",
1048
+ content: "block+",
1049
+ parseDOM: [{ tag: "blockquote" }],
1050
+ toDOM: () => ["blockquote", 0]
1051
+ });
1052
+ },
1053
+ init(ctx) {
1054
+ const ctxImpl = ctx;
1055
+ ctx.commands.register({
1056
+ id: "blockquote",
1057
+ label: "Blockquote",
1058
+ icon: "blockquote",
1059
+ shortcut: "Mod-Shift-.",
1060
+ isEnabled: () => true,
1061
+ isActive: () => false,
1062
+ execute: () => ctxImpl.wrapInBlock("blockquote") || ctxImpl.liftBlock()
1063
+ });
1064
+ return {};
1065
+ }
1066
+ };
1067
+ function DividerAddon() {
1068
+ return {
1069
+ id: "x/divider",
1070
+ dependencies: ["x/schema"],
1071
+ impl: DividerAddonImpl
1072
+ };
1073
+ }
1074
+ var DividerAddonImpl = {
1075
+ id: "x/divider",
1076
+ initSchema(ctx) {
1077
+ ctx.addNode({
1078
+ name: "horizontalRule",
1079
+ group: "block",
1080
+ parseDOM: [{ tag: "hr" }],
1081
+ toDOM: () => ["hr"]
1082
+ });
1083
+ },
1084
+ init(ctx) {
1085
+ ctx.commands.register({
1086
+ id: "insertDivider",
1087
+ label: "Divider",
1088
+ icon: "divider",
1089
+ isEnabled: () => true,
1090
+ isActive: () => false,
1091
+ execute: (c) => {
1092
+ c.insertNode("horizontalRule");
1093
+ return true;
1094
+ }
1095
+ });
1096
+ return {};
1097
+ }
1098
+ };
1099
+ function PageBreakAddon() {
1100
+ return {
1101
+ id: "x/page-break",
1102
+ dependencies: ["x/schema"],
1103
+ impl: PageBreakAddonImpl
1104
+ };
1105
+ }
1106
+ var PageBreakAddonImpl = {
1107
+ id: "x/page-break",
1108
+ initSchema(ctx) {
1109
+ ctx.addNode({
1110
+ name: "pageBreak",
1111
+ group: "block",
1112
+ parseDOM: [{ tag: "div[data-page-break]" }],
1113
+ toDOM: () => [
1114
+ "div",
1115
+ { "data-page-break": "true", style: "page-break-after:always" }
1116
+ ]
1117
+ });
1118
+ },
1119
+ init(ctx) {
1120
+ ctx.commands.register({
1121
+ id: "insertPageBreak",
1122
+ label: "Page Break",
1123
+ icon: "page-break",
1124
+ isEnabled: () => true,
1125
+ isActive: () => false,
1126
+ execute: (c) => {
1127
+ c.insertNode("pageBreak");
1128
+ return true;
1129
+ }
1130
+ });
1131
+ return {};
1132
+ }
1133
+ };
1134
+ function CalloutAddon(config) {
1135
+ return {
1136
+ id: "x/callout",
1137
+ config,
1138
+ dependencies: ["x/schema"],
1139
+ impl: CalloutAddonImpl
1140
+ };
1141
+ }
1142
+ var CalloutAddonImpl = {
1143
+ id: "x/callout",
1144
+ initSchema(ctx) {
1145
+ ctx.addNode({
1146
+ name: "callout",
1147
+ group: "block",
1148
+ content: "block+",
1149
+ attrs: { type: { default: "info" } },
1150
+ parseDOM: [
1151
+ {
1152
+ tag: "div[data-callout]",
1153
+ getAttrs: (el) => ({
1154
+ type: el.getAttribute("data-callout")
1155
+ })
1156
+ }
1157
+ ],
1158
+ toDOM: (node) => [
1159
+ "div",
1160
+ {
1161
+ "data-callout": node.attrs.type,
1162
+ class: `xe-callout xe-callout--${node.attrs.type}`
1163
+ },
1164
+ 0
1165
+ ]
1166
+ });
1167
+ },
1168
+ init(ctx, config = {}) {
1169
+ const types = config.types ?? [
1170
+ "info",
1171
+ "success",
1172
+ "warning",
1173
+ "error",
1174
+ "tip",
1175
+ "note"
1176
+ ];
1177
+ const defaultType = types[0] ?? "info";
1178
+ ctx.commands.register({
1179
+ id: "insertCallout",
1180
+ label: "Callout",
1181
+ icon: "callout",
1182
+ isEnabled: () => true,
1183
+ isActive: () => false,
1184
+ execute: (c, args) => {
1185
+ const type = args?.type ?? defaultType;
1186
+ c.insertNode("callout", { type }, { type: "paragraph" });
1187
+ return true;
1188
+ }
1189
+ });
1190
+ for (const type of types) {
1191
+ ctx.commands.register({
1192
+ id: `insertCallout_${type}`,
1193
+ label: `Callout: ${type}`,
1194
+ icon: `callout-${type}`,
1195
+ isEnabled: () => true,
1196
+ isActive: () => false,
1197
+ execute: (c) => {
1198
+ c.insertNode("callout", { type }, { type: "paragraph" });
1199
+ return true;
1200
+ }
1201
+ });
1202
+ }
1203
+ return {};
1204
+ }
1205
+ };
1206
+ function DetailsAddon() {
1207
+ return {
1208
+ id: "x/details",
1209
+ dependencies: ["x/schema"],
1210
+ impl: DetailsAddonImpl
1211
+ };
1212
+ }
1213
+ var DetailsAddonImpl = {
1214
+ id: "x/details",
1215
+ initSchema(ctx) {
1216
+ ctx.addNode({
1217
+ name: "details",
1218
+ group: "block",
1219
+ content: "summary block+",
1220
+ parseDOM: [{ tag: "details" }],
1221
+ toDOM: () => ["details", 0]
1222
+ });
1223
+ ctx.addNode({
1224
+ name: "summary",
1225
+ content: "inline*",
1226
+ parseDOM: [{ tag: "summary" }],
1227
+ toDOM: () => ["summary", 0]
1228
+ });
1229
+ },
1230
+ init(ctx) {
1231
+ ctx.commands.register({
1232
+ id: "insertDetails",
1233
+ label: "Details / Toggle",
1234
+ icon: "details",
1235
+ isEnabled: () => true,
1236
+ isActive: () => false,
1237
+ execute: (c) => {
1238
+ c.insertNode("details", void 0, [
1239
+ { type: "summary" },
1240
+ { type: "paragraph" }
1241
+ ]);
1242
+ return true;
1243
+ }
1244
+ });
1245
+ return {};
1246
+ }
1247
+ };
1248
+ function ColumnsAddon(config) {
1249
+ return {
1250
+ id: "x/columns",
1251
+ config,
1252
+ dependencies: ["x/schema"],
1253
+ impl: ColumnsAddonImpl
1254
+ };
1255
+ }
1256
+ var ColumnsAddonImpl = {
1257
+ id: "x/columns",
1258
+ initSchema(ctx) {
1259
+ ctx.addNode({
1260
+ name: "columns",
1261
+ group: "block",
1262
+ content: "column+",
1263
+ attrs: { ratio: { default: "1:1" } },
1264
+ parseDOM: [{ tag: "div[data-columns]" }],
1265
+ toDOM: () => ["div", { "data-columns": "true", class: "xe-columns" }, 0]
1266
+ });
1267
+ ctx.addNode({
1268
+ name: "column",
1269
+ content: "block+",
1270
+ parseDOM: [{ tag: "div[data-column]" }],
1271
+ toDOM: () => ["div", { "data-column": "true", class: "xe-column" }, 0]
1272
+ });
1273
+ },
1274
+ init(ctx, config = {}) {
1275
+ ctx.commands.register({
1276
+ id: "insertColumns",
1277
+ label: "Columns",
1278
+ icon: "columns",
1279
+ isEnabled: () => true,
1280
+ isActive: () => false,
1281
+ execute: (c) => {
1282
+ c.insertNode("columns", void 0, [
1283
+ { type: "column", content: [{ type: "paragraph" }] },
1284
+ { type: "column", content: [{ type: "paragraph" }] }
1285
+ ]);
1286
+ return true;
1287
+ }
1288
+ });
1289
+ ctx.commands.register({
1290
+ id: "addColumn",
1291
+ label: "Add Column",
1292
+ isEnabled: () => true,
1293
+ isActive: () => false,
1294
+ execute: () => true
1295
+ });
1296
+ ctx.commands.register({
1297
+ id: "removeColumn",
1298
+ label: "Remove Column",
1299
+ isEnabled: () => true,
1300
+ isActive: () => false,
1301
+ execute: () => true
1302
+ });
1303
+ ctx.commands.register({
1304
+ id: "setColumnRatio",
1305
+ label: "Set Column Ratio",
1306
+ isEnabled: () => true,
1307
+ isActive: () => false,
1308
+ execute: () => true
1309
+ });
1310
+ return {};
1311
+ }
1312
+ };
1313
+ function CodeBlockAddon(config) {
1314
+ return {
1315
+ id: "x/code-block",
1316
+ config,
1317
+ dependencies: ["x/schema"],
1318
+ impl: CodeBlockAddonImpl
1319
+ };
1320
+ }
1321
+ var CodeBlockAddonImpl = {
1322
+ id: "x/code-block",
1323
+ initSchema(ctx) {
1324
+ ctx.addNode({
1325
+ name: "codeBlock",
1326
+ group: "block",
1327
+ content: "text*",
1328
+ attrs: { language: { default: "" } },
1329
+ parseDOM: [{ tag: "pre", preserveWhitespace: "full" }],
1330
+ toDOM: () => ["pre", ["code", 0]]
1331
+ });
1332
+ },
1333
+ init(ctx) {
1334
+ const ctxImpl = ctx;
1335
+ ctx.commands.register({
1336
+ id: "insertCodeBlock",
1337
+ label: "Code Block",
1338
+ icon: "code-block",
1339
+ shortcut: "Mod-Alt-c",
1340
+ isEnabled: () => true,
1341
+ isActive: () => false,
1342
+ execute: () => ctxImpl.setBlockType("codeBlock")
1343
+ });
1344
+ ctx.commands.register({
1345
+ id: "copyCodeBlock",
1346
+ label: "Copy Code",
1347
+ isEnabled: () => true,
1348
+ isActive: () => false,
1349
+ execute: (c) => {
1350
+ const text = c.getContent("text");
1351
+ if (typeof navigator !== "undefined" && navigator.clipboard) {
1352
+ navigator.clipboard.writeText(text).catch(() => {
1353
+ });
1354
+ }
1355
+ return true;
1356
+ }
1357
+ });
1358
+ return {};
1359
+ }
1360
+ };
1361
+
1362
+ // src/lists/index.ts
1363
+ function BulletListAddon() {
1364
+ return {
1365
+ id: "x/bullet-list",
1366
+ dependencies: ["x/schema"],
1367
+ impl: BulletListAddonImpl
1368
+ };
1369
+ }
1370
+ var BulletListAddonImpl = {
1371
+ id: "x/bullet-list",
1372
+ initSchema(ctx) {
1373
+ ctx.addNode({
1374
+ name: "bulletList",
1375
+ group: "block",
1376
+ content: "listItem+",
1377
+ parseDOM: [{ tag: "ul" }],
1378
+ toDOM: () => ["ul", 0]
1379
+ });
1380
+ ctx.addNode({
1381
+ name: "listItem",
1382
+ content: "paragraph block*",
1383
+ parseDOM: [{ tag: "li" }],
1384
+ toDOM: () => ["li", 0]
1385
+ });
1386
+ },
1387
+ init(ctx) {
1388
+ const ctxImpl = ctx;
1389
+ ctx.commands.register({
1390
+ id: "bulletList",
1391
+ label: "Bullet List",
1392
+ icon: "bullet-list",
1393
+ shortcut: "Mod-Shift-8",
1394
+ isEnabled: () => true,
1395
+ isActive: () => false,
1396
+ execute: () => ctxImpl.wrapInBlock("bulletList") || ctxImpl.liftBlock()
1397
+ });
1398
+ return {};
1399
+ }
1400
+ };
1401
+ function OrderedListAddon() {
1402
+ return {
1403
+ id: "x/ordered-list",
1404
+ dependencies: ["x/schema"],
1405
+ impl: OrderedListAddonImpl
1406
+ };
1407
+ }
1408
+ var OrderedListAddonImpl = {
1409
+ id: "x/ordered-list",
1410
+ initSchema(ctx) {
1411
+ ctx.addNode({
1412
+ name: "orderedList",
1413
+ group: "block",
1414
+ content: "listItem+",
1415
+ attrs: { order: { default: 1 } },
1416
+ parseDOM: [
1417
+ {
1418
+ tag: "ol",
1419
+ getAttrs: (el) => ({
1420
+ order: parseInt(el.getAttribute("start") ?? "1", 10)
1421
+ })
1422
+ }
1423
+ ],
1424
+ toDOM: (node) => node.attrs.order === 1 ? ["ol", 0] : ["ol", { start: node.attrs.order }, 0]
1425
+ });
1426
+ },
1427
+ init(ctx) {
1428
+ const ctxImpl = ctx;
1429
+ ctx.commands.register({
1430
+ id: "orderedList",
1431
+ label: "Ordered List",
1432
+ icon: "ordered-list",
1433
+ shortcut: "Mod-Shift-7",
1434
+ isEnabled: () => true,
1435
+ isActive: () => false,
1436
+ execute: () => ctxImpl.wrapInBlock("orderedList") || ctxImpl.liftBlock()
1437
+ });
1438
+ return {};
1439
+ }
1440
+ };
1441
+ function TaskListAddon() {
1442
+ return {
1443
+ id: "x/task-list",
1444
+ dependencies: ["x/schema"],
1445
+ impl: TaskListAddonImpl
1446
+ };
1447
+ }
1448
+ var TaskListAddonImpl = {
1449
+ id: "x/task-list",
1450
+ initSchema(ctx) {
1451
+ ctx.addNode({
1452
+ name: "taskList",
1453
+ group: "block",
1454
+ content: "taskItem+",
1455
+ parseDOM: [{ tag: "ul[data-task-list]" }],
1456
+ toDOM: () => ["ul", { "data-task-list": "true" }, 0]
1457
+ });
1458
+ ctx.addNode({
1459
+ name: "taskItem",
1460
+ content: "paragraph block*",
1461
+ attrs: { checked: { default: false } },
1462
+ parseDOM: [{ tag: "li[data-task-item]" }],
1463
+ toDOM: (node) => [
1464
+ "li",
1465
+ { "data-task-item": "true", "data-checked": node.attrs.checked },
1466
+ 0
1467
+ ]
1468
+ });
1469
+ },
1470
+ init(ctx) {
1471
+ const ctxImpl = ctx;
1472
+ ctx.commands.register({
1473
+ id: "taskList",
1474
+ label: "Task List",
1475
+ icon: "task-list",
1476
+ shortcut: "Mod-Shift-9",
1477
+ isEnabled: () => true,
1478
+ isActive: () => false,
1479
+ execute: () => ctxImpl.wrapInBlock("taskList") || ctxImpl.liftBlock()
1480
+ });
1481
+ return {};
1482
+ }
1483
+ };
1484
+ function ToggleListAddon() {
1485
+ return {
1486
+ id: "x/toggle-list",
1487
+ dependencies: ["x/schema"],
1488
+ impl: ToggleListAddonImpl
1489
+ };
1490
+ }
1491
+ var ToggleListAddonImpl = {
1492
+ id: "x/toggle-list",
1493
+ initSchema(ctx) {
1494
+ ctx.addNode({
1495
+ name: "toggleList",
1496
+ group: "block",
1497
+ content: "toggleItem+",
1498
+ parseDOM: [{ tag: "ul[data-toggle-list]" }],
1499
+ toDOM: () => ["ul", { "data-toggle-list": "true" }, 0]
1500
+ });
1501
+ ctx.addNode({
1502
+ name: "toggleItem",
1503
+ content: "paragraph block*",
1504
+ attrs: { open: { default: true } },
1505
+ parseDOM: [{ tag: "li[data-toggle-item]" }],
1506
+ toDOM: () => ["li", { "data-toggle-item": "true" }, 0]
1507
+ });
1508
+ },
1509
+ init(ctx) {
1510
+ ctx.commands.register({
1511
+ id: "toggleList",
1512
+ label: "Toggle List",
1513
+ icon: "toggle-list",
1514
+ isEnabled: () => true,
1515
+ isActive: () => false,
1516
+ execute: (c) => {
1517
+ c.insertNode("toggleList", void 0, [
1518
+ { type: "toggleItem", content: [{ type: "paragraph" }] }
1519
+ ]);
1520
+ return true;
1521
+ }
1522
+ });
1523
+ return {};
1524
+ }
1525
+ };
1526
+ function ListsAddon() {
1527
+ return [
1528
+ BulletListAddon(),
1529
+ OrderedListAddon(),
1530
+ TaskListAddon(),
1531
+ ToggleListAddon()
1532
+ ];
1533
+ }
1534
+
1535
+ // src/tables/index.ts
1536
+ function TableAddon(config) {
1537
+ return {
1538
+ id: "x/table",
1539
+ config,
1540
+ dependencies: ["x/schema"],
1541
+ impl: TableAddonImpl
1542
+ };
1543
+ }
1544
+ var _tablesCache = null;
1545
+ var _tablesPromise = null;
1546
+ async function loadTables() {
1547
+ if (_tablesCache) return _tablesCache;
1548
+ if (!_tablesPromise) {
1549
+ _tablesPromise = import("prosemirror-tables").then((mod) => {
1550
+ _tablesCache = mod;
1551
+ return _tablesCache;
1552
+ });
1553
+ }
1554
+ return _tablesPromise;
1555
+ }
1556
+ function getView(ctx) {
1557
+ return ctx._prosemirror ?? null;
1558
+ }
1559
+ var TableAddonImpl = {
1560
+ id: "x/table",
1561
+ initSchema(ctx) {
1562
+ ctx.addNode({
1563
+ name: "table",
1564
+ group: "block",
1565
+ content: "tableRow+",
1566
+ tableRole: "table",
1567
+ isolating: true,
1568
+ parseDOM: [{ tag: "table" }],
1569
+ toDOM: () => ["table", ["tbody", 0]]
1570
+ });
1571
+ ctx.addNode({
1572
+ name: "tableRow",
1573
+ content: "(tableHeader | tableCell)+",
1574
+ tableRole: "row",
1575
+ parseDOM: [{ tag: "tr" }],
1576
+ toDOM: () => ["tr", 0]
1577
+ });
1578
+ ctx.addNode({
1579
+ name: "tableHeader",
1580
+ content: "block+",
1581
+ tableRole: "header_cell",
1582
+ isolating: true,
1583
+ attrs: {
1584
+ colspan: { default: 1 },
1585
+ rowspan: { default: 1 },
1586
+ colwidth: { default: null },
1587
+ align: { default: null },
1588
+ background: { default: null }
1589
+ },
1590
+ parseDOM: [
1591
+ {
1592
+ tag: "th",
1593
+ getAttrs: (el) => readCellAttrs(el)
1594
+ }
1595
+ ],
1596
+ toDOM: (node) => [
1597
+ "th",
1598
+ cellDomAttrs(node.attrs),
1599
+ 0
1600
+ ]
1601
+ });
1602
+ ctx.addNode({
1603
+ name: "tableCell",
1604
+ content: "block+",
1605
+ tableRole: "cell",
1606
+ isolating: true,
1607
+ attrs: {
1608
+ colspan: { default: 1 },
1609
+ rowspan: { default: 1 },
1610
+ colwidth: { default: null },
1611
+ align: { default: null },
1612
+ background: { default: null }
1613
+ },
1614
+ parseDOM: [
1615
+ {
1616
+ tag: "td",
1617
+ getAttrs: (el) => readCellAttrs(el)
1618
+ }
1619
+ ],
1620
+ toDOM: (node) => [
1621
+ "td",
1622
+ cellDomAttrs(node.attrs),
1623
+ 0
1624
+ ]
1625
+ });
1626
+ },
1627
+ init(ctx, config) {
1628
+ void loadTables();
1629
+ ctx.commands.register({
1630
+ id: "insertTable",
1631
+ label: "Insert Table",
1632
+ icon: "table",
1633
+ isEnabled: () => true,
1634
+ isActive: () => false,
1635
+ execute: (c, args) => {
1636
+ const a = args ?? {};
1637
+ const maxCols = config?.maxCols ?? 20;
1638
+ const maxRows = config?.maxRows ?? 100;
1639
+ const rows = clamp(a.rows ?? 3, 1, maxRows);
1640
+ const cols = clamp(a.cols ?? 3, 1, maxCols);
1641
+ const header = a.withHeader ?? true;
1642
+ const headerRow = header ? [
1643
+ {
1644
+ type: "tableRow",
1645
+ content: Array.from({ length: cols }, () => ({
1646
+ type: "tableHeader",
1647
+ content: [{ type: "paragraph" }]
1648
+ }))
1649
+ }
1650
+ ] : [];
1651
+ const bodyRows = Array.from(
1652
+ { length: header ? Math.max(0, rows - 1) : rows },
1653
+ () => ({
1654
+ type: "tableRow",
1655
+ content: Array.from({ length: cols }, () => ({
1656
+ type: "tableCell",
1657
+ content: [{ type: "paragraph" }]
1658
+ }))
1659
+ })
1660
+ );
1661
+ c.insertNode("table", void 0, [
1662
+ ...headerRow,
1663
+ ...bodyRows
1664
+ ]);
1665
+ return true;
1666
+ }
1667
+ });
1668
+ registerTableCommand(
1669
+ ctx,
1670
+ "addRowBefore",
1671
+ "Add Row Before",
1672
+ (t) => t.addRowBefore
1673
+ );
1674
+ registerTableCommand(
1675
+ ctx,
1676
+ "addRowAfter",
1677
+ "Add Row After",
1678
+ (t) => t.addRowAfter
1679
+ );
1680
+ registerTableCommand(ctx, "deleteRow", "Delete Row", (t) => t.deleteRow);
1681
+ registerTableCommand(
1682
+ ctx,
1683
+ "addColumnBefore",
1684
+ "Add Column Before",
1685
+ (t) => t.addColumnBefore
1686
+ );
1687
+ registerTableCommand(
1688
+ ctx,
1689
+ "addColumnAfter",
1690
+ "Add Column After",
1691
+ (t) => t.addColumnAfter
1692
+ );
1693
+ registerTableCommand(
1694
+ ctx,
1695
+ "deleteColumn",
1696
+ "Delete Column",
1697
+ (t) => t.deleteColumn
1698
+ );
1699
+ registerTableCommand(
1700
+ ctx,
1701
+ "addColBefore",
1702
+ "Add Column Before",
1703
+ (t) => t.addColumnBefore
1704
+ );
1705
+ registerTableCommand(
1706
+ ctx,
1707
+ "addColAfter",
1708
+ "Add Column After",
1709
+ (t) => t.addColumnAfter
1710
+ );
1711
+ registerTableCommand(
1712
+ ctx,
1713
+ "deleteCol",
1714
+ "Delete Column",
1715
+ (t) => t.deleteColumn
1716
+ );
1717
+ registerTableCommand(ctx, "mergeCells", "Merge Cells", (t) => t.mergeCells);
1718
+ registerTableCommand(ctx, "splitCell", "Split Cell", (t) => t.splitCell);
1719
+ registerTableCommand(
1720
+ ctx,
1721
+ "toggleHeaderRow",
1722
+ "Toggle Header Row",
1723
+ (t) => t.toggleHeaderRow
1724
+ );
1725
+ registerTableCommand(
1726
+ ctx,
1727
+ "toggleHeaderCol",
1728
+ "Toggle Header Column",
1729
+ (t) => t.toggleHeaderColumn
1730
+ );
1731
+ registerTableCommand(
1732
+ ctx,
1733
+ "toggleHeaderColumn",
1734
+ "Toggle Header Column",
1735
+ (t) => t.toggleHeaderColumn
1736
+ );
1737
+ registerTableCommand(
1738
+ ctx,
1739
+ "goToNextCell",
1740
+ "Next Cell",
1741
+ (t) => t.goToNextCell(1)
1742
+ );
1743
+ registerTableCommand(
1744
+ ctx,
1745
+ "goToPrevCell",
1746
+ "Previous Cell",
1747
+ (t) => t.goToNextCell(-1)
1748
+ );
1749
+ ctx.commands.register({
1750
+ id: "setCellAlignment",
1751
+ label: "Set Cell Alignment",
1752
+ isEnabled: () => true,
1753
+ isActive: () => false,
1754
+ execute: (c, args) => {
1755
+ const align = args?.align ?? null;
1756
+ return setCellAttr(c, "align", align);
1757
+ }
1758
+ });
1759
+ ctx.commands.register({
1760
+ id: "setCellBackground",
1761
+ label: "Set Cell Background",
1762
+ isEnabled: () => true,
1763
+ isActive: () => false,
1764
+ execute: (c, args) => {
1765
+ const bg = args?.background ?? args?.color ?? null;
1766
+ return setCellAttr(c, "background", bg);
1767
+ }
1768
+ });
1769
+ ctx.commands.register({
1770
+ id: "deleteTable",
1771
+ label: "Delete Table",
1772
+ icon: "table-delete",
1773
+ isEnabled: () => true,
1774
+ isActive: () => false,
1775
+ execute: (c) => {
1776
+ const view = getView(c);
1777
+ if (!view) return false;
1778
+ if (_tablesCache) {
1779
+ const ok = _tablesCache.deleteTable(view.state, view.dispatch);
1780
+ if (ok) return true;
1781
+ }
1782
+ const found = findTableNode(view);
1783
+ if (!found) return false;
1784
+ const tr = view.state.tr.delete(found.from, found.from + found.size);
1785
+ view.dispatch(tr);
1786
+ return true;
1787
+ }
1788
+ });
1789
+ return {};
1790
+ }
1791
+ };
1792
+ function clamp(n, min, max) {
1793
+ return Math.max(min, Math.min(max, n));
1794
+ }
1795
+ function readCellAttrs(el) {
1796
+ const colspan = parseInt(el.getAttribute("colspan") ?? "1", 10);
1797
+ const rowspan = parseInt(el.getAttribute("rowspan") ?? "1", 10);
1798
+ const widthAttr = el.getAttribute("data-colwidth");
1799
+ let colwidth = null;
1800
+ if (widthAttr) {
1801
+ const widths = widthAttr.split(",").map((s) => parseInt(s, 10));
1802
+ if (widths.every((w) => !isNaN(w)) && widths.length === colspan) {
1803
+ colwidth = widths;
1804
+ }
1805
+ }
1806
+ const align = el.style.textAlign || el.getAttribute("data-align") || null;
1807
+ const background = el.style.backgroundColor || el.getAttribute("data-background") || null;
1808
+ return { colspan, rowspan, colwidth, align, background };
1809
+ }
1810
+ function cellDomAttrs(attrs) {
1811
+ const out = {};
1812
+ const colspan = attrs["colspan"] ?? 1;
1813
+ const rowspan = attrs["rowspan"] ?? 1;
1814
+ if (colspan !== 1) out["colspan"] = String(colspan);
1815
+ if (rowspan !== 1) out["rowspan"] = String(rowspan);
1816
+ const colwidth = attrs["colwidth"];
1817
+ if (colwidth) out["data-colwidth"] = colwidth.join(",");
1818
+ const align = attrs["align"];
1819
+ const background = attrs["background"];
1820
+ const styles = [];
1821
+ if (align) styles.push(`text-align:${align}`);
1822
+ if (background) styles.push(`background-color:${background}`);
1823
+ if (styles.length > 0) out["style"] = styles.join(";");
1824
+ if (align) out["data-align"] = align;
1825
+ if (background) out["data-background"] = background;
1826
+ return out;
1827
+ }
1828
+ function registerTableCommand(ctx, id, label, pick) {
1829
+ ctx.commands.register({
1830
+ id,
1831
+ label,
1832
+ isEnabled: () => true,
1833
+ isActive: () => false,
1834
+ execute: (c) => {
1835
+ const view = getView(c);
1836
+ if (!view) return false;
1837
+ if (_tablesCache) {
1838
+ const cmd = pick(_tablesCache);
1839
+ if (!cmd) return false;
1840
+ return cmd(view.state, view.dispatch);
1841
+ }
1842
+ void loadTables();
1843
+ return false;
1844
+ }
1845
+ });
1846
+ }
1847
+ function setCellAttr(ctx, name, value) {
1848
+ const view = getView(ctx);
1849
+ if (!view) return false;
1850
+ if (!_tablesCache) {
1851
+ void loadTables();
1852
+ return false;
1853
+ }
1854
+ return _tablesCache.setCellAttr(name, value)(view.state, view.dispatch);
1855
+ }
1856
+ function findTableNode(view) {
1857
+ let result = null;
1858
+ view.state.doc.descendants((node, pos) => {
1859
+ if (!result && node.type.name === "table") {
1860
+ result = { from: pos, size: node.nodeSize };
1861
+ }
1862
+ });
1863
+ return result;
1864
+ }
1865
+
1866
+ // src/media/index.ts
1867
+ function ImageAddon(config) {
1868
+ return {
1869
+ id: "x/image",
1870
+ config,
1871
+ dependencies: ["x/schema"],
1872
+ impl: ImageAddonImpl
1873
+ };
1874
+ }
1875
+ var ImageAddonImpl = {
1876
+ id: "x/image",
1877
+ initSchema(ctx) {
1878
+ ctx.addNode({
1879
+ name: "image",
1880
+ group: "block",
1881
+ atom: true,
1882
+ draggable: true,
1883
+ attrs: {
1884
+ src: {},
1885
+ alt: { default: "" },
1886
+ title: { default: null },
1887
+ width: { default: null },
1888
+ align: { default: "center" }
1889
+ },
1890
+ parseDOM: [
1891
+ {
1892
+ tag: "img[src]",
1893
+ getAttrs: (el) => ({
1894
+ src: el.getAttribute("src"),
1895
+ alt: el.getAttribute("alt"),
1896
+ title: el.getAttribute("title")
1897
+ })
1898
+ }
1899
+ ],
1900
+ toDOM: (node) => ["img", node.attrs]
1901
+ });
1902
+ },
1903
+ init(ctx) {
1904
+ ctx.commands.register({
1905
+ id: "insertImage",
1906
+ label: "Image",
1907
+ icon: "image",
1908
+ isEnabled: () => true,
1909
+ isActive: () => false,
1910
+ execute: (c, args) => {
1911
+ const a = args ?? {};
1912
+ if (!a.src) return false;
1913
+ c.insertNode("image", {
1914
+ src: a.src,
1915
+ alt: a.alt ?? "",
1916
+ title: a.title ?? null,
1917
+ width: a.width ?? null,
1918
+ align: a.align ?? "center"
1919
+ });
1920
+ return true;
1921
+ }
1922
+ });
1923
+ ctx.commands.register({
1924
+ id: "setImageAlt",
1925
+ label: "Set Image Alt",
1926
+ isEnabled: () => true,
1927
+ isActive: () => false,
1928
+ execute: () => true
1929
+ });
1930
+ ctx.commands.register({
1931
+ id: "setImageSize",
1932
+ label: "Set Image Size",
1933
+ isEnabled: () => true,
1934
+ isActive: () => false,
1935
+ execute: () => true
1936
+ });
1937
+ ctx.commands.register({
1938
+ id: "alignImageLeft",
1939
+ label: "Align Image Left",
1940
+ isEnabled: () => true,
1941
+ isActive: () => false,
1942
+ execute: () => true
1943
+ });
1944
+ ctx.commands.register({
1945
+ id: "alignImageCenter",
1946
+ label: "Align Image Center",
1947
+ isEnabled: () => true,
1948
+ isActive: () => false,
1949
+ execute: () => true
1950
+ });
1951
+ ctx.commands.register({
1952
+ id: "alignImageRight",
1953
+ label: "Align Image Right",
1954
+ isEnabled: () => true,
1955
+ isActive: () => false,
1956
+ execute: () => true
1957
+ });
1958
+ ctx.commands.register({
1959
+ id: "alignImageFull",
1960
+ label: "Align Image Full",
1961
+ isEnabled: () => true,
1962
+ isActive: () => false,
1963
+ execute: () => true
1964
+ });
1965
+ return {};
1966
+ }
1967
+ };
1968
+ function VideoAddon(config) {
1969
+ return {
1970
+ id: "x/video",
1971
+ config,
1972
+ dependencies: ["x/schema"],
1973
+ impl: VideoAddonImpl
1974
+ };
1975
+ }
1976
+ var VideoAddonImpl = {
1977
+ id: "x/video",
1978
+ initSchema(ctx) {
1979
+ ctx.addNode({
1980
+ name: "video",
1981
+ group: "block",
1982
+ atom: true,
1983
+ attrs: {
1984
+ src: {},
1985
+ provider: { default: "upload" },
1986
+ poster: { default: null },
1987
+ width: { default: null }
1988
+ },
1989
+ parseDOM: [
1990
+ {
1991
+ tag: "video[src]",
1992
+ getAttrs: (el) => ({ src: el.getAttribute("src") })
1993
+ }
1994
+ ],
1995
+ toDOM: (node) => [
1996
+ "video",
1997
+ { src: node.attrs["src"], controls: "true" }
1998
+ ]
1999
+ });
2000
+ },
2001
+ init(ctx) {
2002
+ ctx.commands.register({
2003
+ id: "insertVideo",
2004
+ label: "Video",
2005
+ icon: "video",
2006
+ isEnabled: () => true,
2007
+ isActive: () => false,
2008
+ execute: (c, args) => {
2009
+ const a = args ?? {};
2010
+ if (!a.src) return false;
2011
+ c.insertNode("video", {
2012
+ src: a.src,
2013
+ provider: a.provider ?? "upload",
2014
+ poster: a.poster ?? null,
2015
+ width: a.width ?? null
2016
+ });
2017
+ return true;
2018
+ }
2019
+ });
2020
+ return {};
2021
+ }
2022
+ };
2023
+ function AudioAddon(config) {
2024
+ return {
2025
+ id: "x/audio",
2026
+ config,
2027
+ dependencies: ["x/schema"],
2028
+ impl: AudioAddonImpl
2029
+ };
2030
+ }
2031
+ var AudioAddonImpl = {
2032
+ id: "x/audio",
2033
+ initSchema(ctx) {
2034
+ ctx.addNode({
2035
+ name: "audio",
2036
+ group: "block",
2037
+ atom: true,
2038
+ attrs: { src: {}, title: { default: "" } },
2039
+ parseDOM: [
2040
+ {
2041
+ tag: "audio[src]",
2042
+ getAttrs: (el) => ({ src: el.getAttribute("src") })
2043
+ }
2044
+ ],
2045
+ toDOM: (node) => [
2046
+ "audio",
2047
+ { src: node.attrs["src"], controls: "true" }
2048
+ ]
2049
+ });
2050
+ },
2051
+ init(ctx) {
2052
+ ctx.commands.register({
2053
+ id: "insertAudio",
2054
+ label: "Audio",
2055
+ icon: "audio",
2056
+ isEnabled: () => true,
2057
+ isActive: () => false,
2058
+ execute: (c, args) => {
2059
+ const a = args ?? {};
2060
+ if (!a.src) return false;
2061
+ c.insertNode("audio", { src: a.src, title: a.title ?? "" });
2062
+ return true;
2063
+ }
2064
+ });
2065
+ return {};
2066
+ }
2067
+ };
2068
+ function FileAddon(config) {
2069
+ return {
2070
+ id: "x/file",
2071
+ config,
2072
+ dependencies: ["x/schema"],
2073
+ impl: FileAddonImpl
2074
+ };
2075
+ }
2076
+ var FileAddonImpl = {
2077
+ id: "x/file",
2078
+ initSchema(ctx) {
2079
+ ctx.addNode({
2080
+ name: "file",
2081
+ group: "block",
2082
+ atom: true,
2083
+ attrs: {
2084
+ src: {},
2085
+ name: {},
2086
+ size: { default: 0 },
2087
+ mimeType: { default: "" }
2088
+ },
2089
+ parseDOM: [{ tag: "a[data-file]" }],
2090
+ toDOM: (node) => [
2091
+ "a",
2092
+ {
2093
+ href: node.attrs["src"],
2094
+ download: node.attrs["name"],
2095
+ "data-file": "true"
2096
+ },
2097
+ String(node.attrs["name"])
2098
+ ]
2099
+ });
2100
+ },
2101
+ init(ctx) {
2102
+ ctx.commands.register({
2103
+ id: "insertFile",
2104
+ label: "File",
2105
+ icon: "file",
2106
+ isEnabled: () => true,
2107
+ isActive: () => false,
2108
+ execute: (c, args) => {
2109
+ const a = args ?? {};
2110
+ const src = a.src ?? a.url;
2111
+ if (!src) return false;
2112
+ c.insertNode("file", {
2113
+ src,
2114
+ name: a.name ?? "file",
2115
+ size: a.size ?? 0,
2116
+ mimeType: a.mimeType ?? ""
2117
+ });
2118
+ return true;
2119
+ }
2120
+ });
2121
+ return {};
2122
+ }
2123
+ };
2124
+ function EmbedAddon(config) {
2125
+ return {
2126
+ id: "x/embed",
2127
+ config,
2128
+ dependencies: ["x/schema"],
2129
+ impl: EmbedAddonImpl
2130
+ };
2131
+ }
2132
+ var EmbedAddonImpl = {
2133
+ id: "x/embed",
2134
+ initSchema(ctx) {
2135
+ ctx.addNode({
2136
+ name: "embed",
2137
+ group: "block",
2138
+ atom: true,
2139
+ attrs: {
2140
+ url: {},
2141
+ provider: { default: "" },
2142
+ width: { default: null },
2143
+ height: { default: null }
2144
+ },
2145
+ parseDOM: [{ tag: "iframe[data-embed]" }],
2146
+ toDOM: (node) => [
2147
+ "iframe",
2148
+ { src: node.attrs["url"], "data-embed": "true", class: "xe-embed" }
2149
+ ]
2150
+ });
2151
+ },
2152
+ init(ctx) {
2153
+ ctx.commands.register({
2154
+ id: "insertEmbed",
2155
+ label: "Embed",
2156
+ icon: "embed",
2157
+ isEnabled: () => true,
2158
+ isActive: () => false,
2159
+ execute: (c, args) => {
2160
+ const a = args ?? {};
2161
+ if (!a.url) return false;
2162
+ c.insertNode("embed", {
2163
+ url: a.url,
2164
+ provider: a.provider ?? "",
2165
+ width: a.width ?? null,
2166
+ height: a.height ?? null
2167
+ });
2168
+ return true;
2169
+ }
2170
+ });
2171
+ return {};
2172
+ }
2173
+ };
2174
+ function BookmarkAddon(config) {
2175
+ return {
2176
+ id: "x/bookmark",
2177
+ config,
2178
+ dependencies: ["x/schema"],
2179
+ impl: BookmarkAddonImpl
2180
+ };
2181
+ }
2182
+ var BookmarkAddonImpl = {
2183
+ id: "x/bookmark",
2184
+ initSchema(ctx) {
2185
+ ctx.addNode({
2186
+ name: "bookmark",
2187
+ group: "block",
2188
+ atom: true,
2189
+ attrs: {
2190
+ url: {},
2191
+ title: { default: "" },
2192
+ description: { default: "" },
2193
+ image: { default: null },
2194
+ favicon: { default: null }
2195
+ },
2196
+ parseDOM: [{ tag: "div[data-bookmark]" }],
2197
+ toDOM: () => ["div", { "data-bookmark": "true", class: "xe-bookmark" }]
2198
+ });
2199
+ },
2200
+ init(ctx) {
2201
+ ctx.commands.register({
2202
+ id: "insertBookmark",
2203
+ label: "Bookmark",
2204
+ icon: "bookmark",
2205
+ isEnabled: () => true,
2206
+ isActive: () => false,
2207
+ execute: (c, args) => {
2208
+ const a = args ?? {};
2209
+ if (!a.url) return false;
2210
+ c.insertNode("bookmark", {
2211
+ url: a.url,
2212
+ title: a.title ?? "",
2213
+ description: a.description ?? "",
2214
+ image: a.image ?? null,
2215
+ favicon: a.favicon ?? null
2216
+ });
2217
+ return true;
2218
+ }
2219
+ });
2220
+ return {};
2221
+ }
2222
+ };
2223
+
2224
+ // src/inline/index.ts
2225
+ function LinkAddon(config) {
2226
+ return {
2227
+ id: "x/link",
2228
+ config,
2229
+ dependencies: ["x/schema"],
2230
+ impl: LinkAddonImpl
2231
+ };
2232
+ }
2233
+ var LinkAddonImpl = {
2234
+ id: "x/link",
2235
+ initSchema(ctx) {
2236
+ ctx.addMark({
2237
+ name: "link",
2238
+ attrs: {
2239
+ href: {},
2240
+ title: { default: null },
2241
+ target: { default: "_blank" }
2242
+ },
2243
+ inclusive: false,
2244
+ parseDOM: [
2245
+ {
2246
+ tag: "a[href]",
2247
+ getAttrs: (el) => ({
2248
+ href: el.getAttribute("href"),
2249
+ title: el.getAttribute("title"),
2250
+ target: el.getAttribute("target")
2251
+ })
2252
+ }
2253
+ ],
2254
+ toDOM: (mark) => ["a", mark.attrs, 0]
2255
+ });
2256
+ },
2257
+ init(ctx, config = {}) {
2258
+ ctx.commands.register({
2259
+ id: "insertLink",
2260
+ label: "Insert Link",
2261
+ icon: "link",
2262
+ shortcut: "Mod-k",
2263
+ isEnabled: () => true,
2264
+ isActive: (c) => c.selection.hasMark("link"),
2265
+ execute: (c, args) => {
2266
+ const a = args ?? {};
2267
+ let url = a.href;
2268
+ if (!url) {
2269
+ if (typeof window === "undefined") return false;
2270
+ const prompted = window.prompt("Enter URL", "https://");
2271
+ if (!prompted) return false;
2272
+ url = prompted;
2273
+ }
2274
+ if (config.validate && !config.validate(url)) return false;
2275
+ c.addMark("link", {
2276
+ href: url,
2277
+ title: a.title ?? null,
2278
+ target: a.target ?? config.defaultTarget ?? "_blank"
2279
+ });
2280
+ return true;
2281
+ }
2282
+ });
2283
+ ctx.commands.register({
2284
+ id: "editLink",
2285
+ label: "Edit Link",
2286
+ isEnabled: (c) => c.selection.hasMark("link"),
2287
+ isActive: () => false,
2288
+ execute: (c) => {
2289
+ if (typeof window === "undefined") return false;
2290
+ const url = window.prompt("Edit URL", "https://");
2291
+ if (!url) return false;
2292
+ c.addMark("link", {
2293
+ href: url,
2294
+ target: config.defaultTarget ?? "_blank"
2295
+ });
2296
+ return true;
2297
+ }
2298
+ });
2299
+ ctx.commands.register({
2300
+ id: "removeLink",
2301
+ label: "Remove Link",
2302
+ isEnabled: (c) => c.selection.hasMark("link"),
2303
+ isActive: () => false,
2304
+ execute: (c) => {
2305
+ c.removeMark("link");
2306
+ return true;
2307
+ }
2308
+ });
2309
+ ctx.commands.register({
2310
+ id: "openLink",
2311
+ label: "Open Link",
2312
+ isEnabled: (c) => c.selection.hasMark("link"),
2313
+ isActive: () => false,
2314
+ execute: () => true
2315
+ });
2316
+ return {};
2317
+ }
2318
+ };
2319
+ function MentionAddon(config) {
2320
+ return {
2321
+ id: "x/mention",
2322
+ config,
2323
+ dependencies: ["x/schema"],
2324
+ impl: MentionAddonImpl
2325
+ };
2326
+ }
2327
+ var MentionAddonImpl = {
2328
+ id: "x/mention",
2329
+ initSchema(ctx) {
2330
+ ctx.addNode({
2331
+ name: "mention",
2332
+ group: "inline",
2333
+ inline: true,
2334
+ atom: true,
2335
+ attrs: { id: {}, label: {}, type: { default: "user" } },
2336
+ parseDOM: [{ tag: "span[data-mention]" }],
2337
+ toDOM: (node) => [
2338
+ "span",
2339
+ {
2340
+ "data-mention": node.attrs["type"],
2341
+ "data-id": node.attrs["id"],
2342
+ class: "xe-mention"
2343
+ },
2344
+ `@${node.attrs["label"]}`
2345
+ ]
2346
+ });
2347
+ },
2348
+ init(ctx) {
2349
+ ctx.commands.register({
2350
+ id: "insertMention",
2351
+ label: "Mention",
2352
+ icon: "mention",
2353
+ isEnabled: () => true,
2354
+ isActive: () => false,
2355
+ execute: (c, args) => {
2356
+ const a = args ?? {};
2357
+ if (!a.id || !a.label) return false;
2358
+ c.insertNode("mention", {
2359
+ id: a.id,
2360
+ label: a.label,
2361
+ type: a.type ?? "user"
2362
+ });
2363
+ return true;
2364
+ }
2365
+ });
2366
+ return {};
2367
+ }
2368
+ };
2369
+ function EmojiAddon(config) {
2370
+ return {
2371
+ id: "x/emoji",
2372
+ config,
2373
+ dependencies: ["x/schema"],
2374
+ impl: EmojiAddonImpl
2375
+ };
2376
+ }
2377
+ var EmojiAddonImpl = {
2378
+ id: "x/emoji",
2379
+ initSchema(ctx) {
2380
+ ctx.addNode({
2381
+ name: "emoji",
2382
+ group: "inline",
2383
+ inline: true,
2384
+ atom: true,
2385
+ attrs: { id: {}, native: {} },
2386
+ parseDOM: [{ tag: "span[data-emoji]" }],
2387
+ toDOM: (node) => [
2388
+ "span",
2389
+ { "data-emoji": node.attrs["id"], class: "xe-emoji" },
2390
+ node.attrs["native"]
2391
+ ]
2392
+ });
2393
+ },
2394
+ init(ctx) {
2395
+ ctx.commands.register({
2396
+ id: "insertEmoji",
2397
+ label: "Emoji",
2398
+ icon: "emoji",
2399
+ isEnabled: () => true,
2400
+ isActive: () => false,
2401
+ execute: (c, args) => {
2402
+ const a = args ?? {};
2403
+ const id = a.id ?? a.shortcode ?? "smile";
2404
+ const native = a.native ?? "\u{1F642}";
2405
+ c.insertNode("emoji", { id, native });
2406
+ return true;
2407
+ }
2408
+ });
2409
+ return {};
2410
+ }
2411
+ };
2412
+ function EquationAddon(config) {
2413
+ return {
2414
+ id: "x/equation",
2415
+ config,
2416
+ dependencies: ["x/schema"],
2417
+ impl: EquationAddonImpl
2418
+ };
2419
+ }
2420
+ var EquationAddonImpl = {
2421
+ id: "x/equation",
2422
+ initSchema(ctx) {
2423
+ ctx.addMark({
2424
+ name: "equation",
2425
+ parseDOM: [{ tag: "span[data-equation]" }],
2426
+ toDOM: () => [
2427
+ "span",
2428
+ { "data-equation": "true", class: "xe-equation-inline" },
2429
+ 0
2430
+ ]
2431
+ });
2432
+ ctx.addNode({
2433
+ name: "equationBlock",
2434
+ group: "block",
2435
+ atom: true,
2436
+ attrs: { src: {} },
2437
+ parseDOM: [{ tag: "div[data-equation-block]" }],
2438
+ toDOM: () => [
2439
+ "div",
2440
+ { "data-equation-block": "true", class: "xe-equation-block" }
2441
+ ]
2442
+ });
2443
+ },
2444
+ init(ctx) {
2445
+ ctx.commands.register({
2446
+ id: "insertEquationBlock",
2447
+ label: "Equation Block",
2448
+ icon: "equation-block",
2449
+ isEnabled: () => true,
2450
+ isActive: () => false,
2451
+ execute: (c, args) => {
2452
+ const src = args?.latex ?? args?.src ?? "";
2453
+ c.insertNode("equationBlock", { src });
2454
+ return true;
2455
+ }
2456
+ });
2457
+ ctx.commands.register({
2458
+ id: "insertEquation",
2459
+ label: "Equation",
2460
+ icon: "equation",
2461
+ isEnabled: () => true,
2462
+ isActive: () => false,
2463
+ execute: (c, args) => c.execCommand("insertEquationBlock", args)
2464
+ });
2465
+ ctx.commands.register({
2466
+ id: "insertInlineEquation",
2467
+ label: "Inline Equation",
2468
+ icon: "equation",
2469
+ isEnabled: () => true,
2470
+ isActive: () => false,
2471
+ execute: (c) => {
2472
+ c.addMark("equation");
2473
+ return true;
2474
+ }
2475
+ });
2476
+ ctx.commands.register({
2477
+ id: "editEquation",
2478
+ label: "Edit Equation",
2479
+ isEnabled: () => true,
2480
+ isActive: () => false,
2481
+ execute: () => true
2482
+ });
2483
+ return {};
2484
+ }
2485
+ };
2486
+ function FootnoteAddon() {
2487
+ return {
2488
+ id: "x/footnote",
2489
+ dependencies: ["x/schema"],
2490
+ impl: FootnoteAddonImpl
2491
+ };
2492
+ }
2493
+ var FootnoteAddonImpl = {
2494
+ id: "x/footnote",
2495
+ initSchema(ctx) {
2496
+ ctx.addNode({
2497
+ name: "footnoteRef",
2498
+ group: "inline",
2499
+ inline: true,
2500
+ atom: true,
2501
+ attrs: { id: {}, index: { default: 1 } },
2502
+ parseDOM: [{ tag: "sup[data-footnote-ref]" }],
2503
+ toDOM: (node) => [
2504
+ "sup",
2505
+ { "data-footnote-ref": node.attrs["id"], class: "xe-footnote-ref" },
2506
+ `[${node.attrs["index"]}]`
2507
+ ]
2508
+ });
2509
+ ctx.addNode({
2510
+ name: "footnote",
2511
+ group: "block",
2512
+ content: "block+",
2513
+ attrs: { id: {} },
2514
+ parseDOM: [{ tag: "div[data-footnote]" }],
2515
+ toDOM: () => [
2516
+ "div",
2517
+ { "data-footnote": "true", class: "xe-footnote" },
2518
+ 0
2519
+ ]
2520
+ });
2521
+ },
2522
+ init(ctx) {
2523
+ let _footnoteCounter = 0;
2524
+ ctx.commands.register({
2525
+ id: "insertFootnote",
2526
+ label: "Footnote",
2527
+ icon: "footnote",
2528
+ isEnabled: () => true,
2529
+ isActive: () => false,
2530
+ execute: (c, args) => {
2531
+ const a = args ?? {};
2532
+ const id = a.id ?? `fn-${++_footnoteCounter}`;
2533
+ c.insertNode("footnote", { id }, [
2534
+ {
2535
+ type: "paragraph",
2536
+ content: a.text ? [{ type: "text", text: a.text }] : []
2537
+ }
2538
+ ]);
2539
+ return true;
2540
+ }
2541
+ });
2542
+ ctx.commands.register({
2543
+ id: "editFootnote",
2544
+ label: "Edit Footnote",
2545
+ isEnabled: () => true,
2546
+ isActive: () => false,
2547
+ execute: () => true
2548
+ });
2549
+ return {};
2550
+ }
2551
+ };
2552
+ function SmartChipAddon(config) {
2553
+ return {
2554
+ id: "x/smart-chip",
2555
+ config,
2556
+ dependencies: ["x/mention"],
2557
+ impl: SmartChipAddonImpl
2558
+ };
2559
+ }
2560
+ var SmartChipAddonImpl = {
2561
+ id: "x/smart-chip",
2562
+ initSchema(ctx) {
2563
+ ctx.addNode({
2564
+ name: "smartChip",
2565
+ group: "inline",
2566
+ inline: true,
2567
+ atom: true,
2568
+ attrs: {
2569
+ kind: { default: "generic" },
2570
+ value: { default: "" },
2571
+ label: { default: null }
2572
+ },
2573
+ parseDOM: [{ tag: "span[data-smart-chip]" }],
2574
+ toDOM: (node) => [
2575
+ "span",
2576
+ {
2577
+ "data-smart-chip": node.attrs["kind"],
2578
+ "data-value": node.attrs["value"],
2579
+ class: "xe-smart-chip"
2580
+ },
2581
+ String(node.attrs["label"] ?? node.attrs["value"])
2582
+ ]
2583
+ });
2584
+ },
2585
+ init(ctx) {
2586
+ ctx.commands.register({
2587
+ id: "insertSmartChip",
2588
+ label: "Smart Chip",
2589
+ icon: "smart-chip",
2590
+ isEnabled: () => true,
2591
+ isActive: () => false,
2592
+ execute: (c, args) => {
2593
+ const a = args ?? {};
2594
+ c.insertNode("smartChip", {
2595
+ kind: a.kind ?? "generic",
2596
+ value: a.value ?? "",
2597
+ label: a.label ?? null
2598
+ });
2599
+ return true;
2600
+ }
2601
+ });
2602
+ return {};
2603
+ }
2604
+ };
2605
+
2606
+ // src/ui-shell/command-group.ts
2607
+ function createCommandGroup(ctx, opts) {
2608
+ const mode = opts.mode ?? "inline";
2609
+ const density = opts.density ?? (mode === "popover" ? "compact" : "comfortable");
2610
+ const orientation = opts.orientation ?? "horizontal";
2611
+ const showLabels = opts.showLabels ?? false;
2612
+ const showTooltips = opts.showTooltips ?? true;
2613
+ let loading = opts.loading ?? /* @__PURE__ */ new Set();
2614
+ const el = document.createElement("div");
2615
+ el.className = `xe-cgroup xe-cgroup--${mode} xe-cgroup--${density} xe-cgroup--${orientation}`;
2616
+ el.setAttribute("role", "group");
2617
+ el.setAttribute("aria-orientation", orientation);
2618
+ if (opts.label) el.setAttribute("aria-label", opts.label);
2619
+ const entries = [];
2620
+ for (const cmdId of opts.commands) {
2621
+ const cmd = ctx.commands.get(cmdId);
2622
+ if (!cmd) continue;
2623
+ const btn = document.createElement("button");
2624
+ btn.type = "button";
2625
+ btn.className = "xe-cgroup__btn";
2626
+ btn.dataset["cmdId"] = cmdId;
2627
+ btn.setAttribute("aria-label", cmd.label);
2628
+ btn.tabIndex = -1;
2629
+ if (cmd.icon) {
2630
+ const svg = ctx.icons.get(cmd.icon);
2631
+ const iconWrap = document.createElement("span");
2632
+ iconWrap.className = "xe-cgroup__icon";
2633
+ iconWrap.innerHTML = svg ?? cmd.icon;
2634
+ btn.appendChild(iconWrap);
2635
+ }
2636
+ if (showLabels) {
2637
+ const label = document.createElement("span");
2638
+ label.className = "xe-cgroup__label";
2639
+ label.textContent = cmd.label;
2640
+ btn.appendChild(label);
2641
+ }
2642
+ btn.addEventListener("click", (ev) => {
2643
+ ev.preventDefault();
2644
+ if (btn.disabled) return;
2645
+ if (loading.has(cmdId)) return;
2646
+ if (opts.onActivate) opts.onActivate(cmdId);
2647
+ else ctx.execCommand(cmdId);
2648
+ });
2649
+ btn.addEventListener("mousedown", (ev) => {
2650
+ ev.preventDefault();
2651
+ });
2652
+ el.appendChild(btn);
2653
+ entries.push({ cmdId, cmd, btn });
2654
+ }
2655
+ let activeIndex = entries.findIndex(
2656
+ (e) => !(e.cmd.isEnabled?.(ctx) === false)
2657
+ );
2658
+ if (activeIndex < 0 && entries.length > 0) activeIndex = 0;
2659
+ if (activeIndex >= 0) entries[activeIndex].btn.tabIndex = 0;
2660
+ const setActive = (next, focus) => {
2661
+ if (next < 0 || next >= entries.length) return;
2662
+ if (entries[next].btn.disabled) return;
2663
+ if (activeIndex >= 0 && activeIndex < entries.length) {
2664
+ entries[activeIndex].btn.tabIndex = -1;
2665
+ }
2666
+ activeIndex = next;
2667
+ entries[activeIndex].btn.tabIndex = 0;
2668
+ if (focus) entries[activeIndex].btn.focus();
2669
+ };
2670
+ const findNext = (from, dir) => {
2671
+ if (entries.length === 0) return -1;
2672
+ for (let i = 1; i <= entries.length; i++) {
2673
+ const idx = (from + dir * i + entries.length * i) % entries.length;
2674
+ if (!entries[idx].btn.disabled) return idx;
2675
+ }
2676
+ return -1;
2677
+ };
2678
+ const onKeyDown = (ev) => {
2679
+ const nextKey = orientation === "horizontal" ? "ArrowRight" : "ArrowDown";
2680
+ const prevKey = orientation === "horizontal" ? "ArrowLeft" : "ArrowUp";
2681
+ if (ev.key === nextKey) {
2682
+ ev.preventDefault();
2683
+ const n = findNext(activeIndex, 1);
2684
+ if (n >= 0) setActive(n, true);
2685
+ } else if (ev.key === prevKey) {
2686
+ ev.preventDefault();
2687
+ const n = findNext(activeIndex, -1);
2688
+ if (n >= 0) setActive(n, true);
2689
+ } else if (ev.key === "Home") {
2690
+ ev.preventDefault();
2691
+ for (let i = 0; i < entries.length; i++) {
2692
+ if (!entries[i].btn.disabled) {
2693
+ setActive(i, true);
2694
+ break;
2695
+ }
2696
+ }
2697
+ } else if (ev.key === "End") {
2698
+ ev.preventDefault();
2699
+ for (let i = entries.length - 1; i >= 0; i--) {
2700
+ if (!entries[i].btn.disabled) {
2701
+ setActive(i, true);
2702
+ break;
2703
+ }
2704
+ }
2705
+ }
2706
+ };
2707
+ el.addEventListener("keydown", onKeyDown);
2708
+ const onFocusIn = (ev) => {
2709
+ const target = ev.target;
2710
+ if (!target) return;
2711
+ const idx = entries.findIndex((e) => e.btn === target);
2712
+ if (idx >= 0 && idx !== activeIndex) setActive(idx, false);
2713
+ };
2714
+ el.addEventListener("focusin", onFocusIn);
2715
+ const update = () => {
2716
+ for (const entry of entries) {
2717
+ const { cmd, btn, cmdId } = entry;
2718
+ const enabled = cmd.isEnabled?.(ctx) ?? true;
2719
+ const active = cmd.isActive?.(ctx) ?? false;
2720
+ const isLoading = loading.has(cmdId);
2721
+ btn.disabled = !enabled || isLoading;
2722
+ btn.setAttribute("aria-disabled", String(!enabled));
2723
+ btn.setAttribute("aria-pressed", String(active));
2724
+ if (isLoading) btn.setAttribute("aria-busy", "true");
2725
+ else btn.removeAttribute("aria-busy");
2726
+ btn.classList.toggle("xe-cgroup__btn--active", active);
2727
+ btn.classList.toggle("xe-cgroup__btn--disabled", !enabled);
2728
+ btn.classList.toggle("xe-cgroup__btn--loading", isLoading);
2729
+ const tooltipText = showTooltips && cmd.label ? cmd.shortcut ? `${cmd.label} (${cmd.shortcut})` : cmd.label : "";
2730
+ if (tooltipText) btn.title = tooltipText;
2731
+ else btn.removeAttribute("title");
2732
+ const hasSpinner = btn.querySelector(".xe-cgroup__spinner");
2733
+ if (isLoading && !hasSpinner) {
2734
+ const spinner = document.createElement("span");
2735
+ spinner.className = "xe-cgroup__spinner";
2736
+ spinner.setAttribute("aria-hidden", "true");
2737
+ btn.appendChild(spinner);
2738
+ } else if (!isLoading && hasSpinner) {
2739
+ hasSpinner.remove();
2740
+ }
2741
+ }
2742
+ if (activeIndex >= 0 && activeIndex < entries.length && entries[activeIndex].btn.disabled) {
2743
+ const n = findNext(activeIndex, 1);
2744
+ if (n >= 0) setActive(n, false);
2745
+ }
2746
+ };
2747
+ update();
2748
+ const focusFirst = () => {
2749
+ const n = findNext(-1, 1);
2750
+ if (n >= 0) setActive(n, true);
2751
+ };
2752
+ const focusLast = () => {
2753
+ const n = findNext(entries.length, -1);
2754
+ if (n >= 0) setActive(n, true);
2755
+ };
2756
+ const setLoading = (next) => {
2757
+ loading = next;
2758
+ update();
2759
+ };
2760
+ const destroy = () => {
2761
+ el.removeEventListener("keydown", onKeyDown);
2762
+ el.removeEventListener("focusin", onFocusIn);
2763
+ el.remove();
2764
+ };
2765
+ return { el, update, focusFirst, focusLast, setLoading, destroy };
2766
+ }
2767
+
2768
+ // src/ui-shell/index.ts
2769
+ function ToolbarAddon(config) {
2770
+ return {
2771
+ id: "x/toolbar",
2772
+ config,
2773
+ dependencies: ["x/commands"],
2774
+ impl: ToolbarAddonImpl
2775
+ };
2776
+ }
2777
+ var ToolbarAddonImpl = {
2778
+ id: "x/toolbar",
2779
+ init(ctx, config = {}) {
2780
+ const container = ctx.getSlot("toolbar");
2781
+ if (!container) return {};
2782
+ const toolbar = document.createElement("div");
2783
+ toolbar.className = "xe-toolbar";
2784
+ toolbar.setAttribute("role", "toolbar");
2785
+ container.appendChild(toolbar);
2786
+ let groupHandles = [];
2787
+ let lastGroupsKey = "";
2788
+ const render = () => {
2789
+ const groups = config.groups ?? [
2790
+ { commands: ctx.commands.getAll().map((c) => c.id) }
2791
+ ];
2792
+ const groupsKey = JSON.stringify(
2793
+ groups.map((g) => [g.label ?? "", g.commands])
2794
+ );
2795
+ if (groupsKey === lastGroupsKey) {
2796
+ for (const h of groupHandles) h.update();
2797
+ return;
2798
+ }
2799
+ lastGroupsKey = groupsKey;
2800
+ for (const h of groupHandles) h.destroy();
2801
+ groupHandles = [];
2802
+ toolbar.innerHTML = "";
2803
+ for (const group of groups) {
2804
+ const handle = createCommandGroup(ctx, {
2805
+ commands: group.commands,
2806
+ label: group.label,
2807
+ mode: "inline",
2808
+ density: "comfortable",
2809
+ showLabels: config.showLabels,
2810
+ showTooltips: config.showTooltips
2811
+ });
2812
+ toolbar.appendChild(handle.el);
2813
+ groupHandles.push(handle);
2814
+ }
2815
+ };
2816
+ render();
2817
+ const unsub = ctx.on("selection:change", () => {
2818
+ for (const h of groupHandles) h.update();
2819
+ });
2820
+ const unsub2 = ctx.on("doc:change", render);
2821
+ return {
2822
+ destroy() {
2823
+ unsub();
2824
+ unsub2();
2825
+ for (const h of groupHandles) h.destroy();
2826
+ groupHandles = [];
2827
+ toolbar.remove();
2828
+ }
2829
+ };
2830
+ }
2831
+ };
2832
+ function BubbleMenuAddon(config) {
2833
+ return {
2834
+ id: "x/bubble-menu",
2835
+ config,
2836
+ dependencies: ["x/commands"],
2837
+ impl: BubbleMenuAddonImpl
2838
+ };
2839
+ }
2840
+ var DEFAULT_BUBBLE_COMMANDS = [
2841
+ "bold",
2842
+ "italic",
2843
+ "underline",
2844
+ "strikethrough",
2845
+ "inlineCode",
2846
+ "insertLink"
2847
+ ];
2848
+ var BubbleMenuAddonImpl = {
2849
+ id: "x/bubble-menu",
2850
+ init(ctx, config = {}) {
2851
+ const menu = document.createElement("div");
2852
+ menu.className = "xe-bubble-menu";
2853
+ menu.style.display = "none";
2854
+ menu.style.position = "absolute";
2855
+ ctx.getSlot("overlay")?.appendChild(menu);
2856
+ const commands = (config.commands ?? DEFAULT_BUBBLE_COMMANDS).filter(
2857
+ (id) => !!ctx.commands.get(id)
2858
+ );
2859
+ const group = createCommandGroup(ctx, {
2860
+ commands,
2861
+ mode: "popover",
2862
+ density: "compact",
2863
+ showTooltips: true,
2864
+ label: "Selection actions"
2865
+ });
2866
+ menu.appendChild(group.el);
2867
+ const unsub = ctx.on("selection:change", () => {
2868
+ if (ctx.selection.empty) {
2869
+ menu.style.display = "none";
2870
+ } else {
2871
+ menu.style.display = "flex";
2872
+ group.update();
2873
+ }
2874
+ });
2875
+ const unsub2 = ctx.on("doc:change", () => group.update());
2876
+ return {
2877
+ destroy() {
2878
+ unsub();
2879
+ unsub2();
2880
+ group.destroy();
2881
+ menu.remove();
2882
+ }
2883
+ };
2884
+ }
2885
+ };
2886
+ function SlashMenuAddon(config) {
2887
+ return {
2888
+ id: "x/slash-menu",
2889
+ config,
2890
+ dependencies: ["x/commands"],
2891
+ impl: SlashMenuAddonImpl
2892
+ };
2893
+ }
2894
+ var SlashMenuAddonImpl = {
2895
+ id: "x/slash-menu",
2896
+ init(ctx, config = {}) {
2897
+ const content = ctx.getSlot("content");
2898
+ let menu = null;
2899
+ let groupHandles = [];
2900
+ const close = () => {
2901
+ for (const h of groupHandles) h.destroy();
2902
+ groupHandles = [];
2903
+ if (menu) {
2904
+ menu.remove();
2905
+ menu = null;
2906
+ }
2907
+ };
2908
+ const buildGroups = () => {
2909
+ if (config.groups && config.groups.length > 0) return config.groups;
2910
+ const all = ctx.commands.getAll().slice(0, config.maxVisible ?? 30).map((c) => c.id);
2911
+ return [{ label: "Commands", commands: all }];
2912
+ };
2913
+ const open = () => {
2914
+ close();
2915
+ menu = document.createElement("div");
2916
+ menu.className = "xe-slash-menu";
2917
+ menu.setAttribute("data-xe-slash", "true");
2918
+ const groups = buildGroups();
2919
+ for (const grp of groups) {
2920
+ if (grp.label) {
2921
+ const header = document.createElement("div");
2922
+ header.className = "xe-slash-menu__label";
2923
+ header.textContent = grp.label;
2924
+ menu.appendChild(header);
2925
+ }
2926
+ const handle = createCommandGroup(ctx, {
2927
+ commands: grp.commands,
2928
+ label: grp.label,
2929
+ mode: "popover",
2930
+ density: "compact",
2931
+ orientation: "vertical",
2932
+ showLabels: true,
2933
+ showTooltips: false,
2934
+ onActivate: (cmdId) => {
2935
+ ctx.execCommand(cmdId);
2936
+ close();
2937
+ }
2938
+ });
2939
+ menu.appendChild(handle.el);
2940
+ groupHandles.push(handle);
2941
+ }
2942
+ const host = ctx.getSlot("overlay") ?? content ?? document.body;
2943
+ host.appendChild(menu);
2944
+ menu.addEventListener("keydown", (ev) => {
2945
+ if (ev.key === "Escape") {
2946
+ ev.preventDefault();
2947
+ close();
2948
+ }
2949
+ });
2950
+ groupHandles[0]?.focusFirst();
2951
+ };
2952
+ const onKeydown = (e) => {
2953
+ if (e.key === "/") {
2954
+ setTimeout(open, 0);
2955
+ } else if (e.key === "Escape" && menu) {
2956
+ e.preventDefault();
2957
+ close();
2958
+ }
2959
+ };
2960
+ const target = content ?? document;
2961
+ target.addEventListener("keydown", onKeydown);
2962
+ document.addEventListener(
2963
+ "click",
2964
+ (ev) => {
2965
+ if (menu && !menu.contains(ev.target)) close();
2966
+ },
2967
+ true
2968
+ );
2969
+ return {
2970
+ destroy() {
2971
+ close();
2972
+ target.removeEventListener("keydown", onKeydown);
2973
+ }
2974
+ };
2975
+ }
2976
+ };
2977
+ function CommandPaletteAddon(config) {
2978
+ return {
2979
+ id: "x/command-palette",
2980
+ config,
2981
+ dependencies: ["x/commands"],
2982
+ impl: CommandPaletteAddonImpl
2983
+ };
2984
+ }
2985
+ var CommandPaletteAddonImpl = {
2986
+ id: "x/command-palette",
2987
+ init(ctx, _config = {}) {
2988
+ let palette = null;
2989
+ const close = () => {
2990
+ if (palette) {
2991
+ palette.remove();
2992
+ palette = null;
2993
+ }
2994
+ };
2995
+ const open = () => {
2996
+ close();
2997
+ palette = document.createElement("div");
2998
+ palette.className = "xe-command-palette";
2999
+ palette.setAttribute("data-xe-palette", "true");
3000
+ palette.style.cssText = "position:fixed; top:20%; left:50%; transform:translateX(-50%); background:var(--xe-bg,#fff); border:1px solid var(--xe-border,#ddd); border-radius:8px; padding:10px; width:420px; max-height:60vh; overflow:auto; box-shadow:0 12px 48px rgba(0,0,0,0.2); z-index:1000;";
3001
+ const input = document.createElement("input");
3002
+ input.type = "text";
3003
+ input.placeholder = "Search commands\u2026";
3004
+ input.style.cssText = "width:100%; padding:8px; border:1px solid var(--xe-border,#ddd); border-radius:4px; box-sizing:border-box;";
3005
+ const list = document.createElement("div");
3006
+ list.className = "xe-command-palette-list";
3007
+ list.style.cssText = "margin-top:8px; max-height:50vh; overflow:auto;";
3008
+ const renderList = (q = "") => {
3009
+ list.innerHTML = "";
3010
+ const ql = q.toLowerCase();
3011
+ for (const cmd of ctx.commands.getAll()) {
3012
+ if (ql && !cmd.label.toLowerCase().includes(ql) && !cmd.id.toLowerCase().includes(ql))
3013
+ continue;
3014
+ const row = document.createElement("button");
3015
+ row.type = "button";
3016
+ row.textContent = cmd.label;
3017
+ row.style.cssText = "display:block; width:100%; text-align:left; padding:6px 8px; border:0; background:transparent; cursor:pointer;";
3018
+ row.addEventListener("mousedown", (ev) => {
3019
+ ev.preventDefault();
3020
+ ctx.execCommand(cmd.id);
3021
+ close();
3022
+ });
3023
+ list.appendChild(row);
3024
+ }
3025
+ };
3026
+ input.addEventListener("input", () => renderList(input.value));
3027
+ input.addEventListener("keydown", (ev) => {
3028
+ if (ev.key === "Escape") close();
3029
+ });
3030
+ palette.appendChild(input);
3031
+ palette.appendChild(list);
3032
+ renderList();
3033
+ document.body.appendChild(palette);
3034
+ input.focus();
3035
+ };
3036
+ const handleKeydown = (e) => {
3037
+ const mod = e.metaKey || e.ctrlKey;
3038
+ if (mod && (e.key === "k" || e.key === "K")) {
3039
+ e.preventDefault();
3040
+ ctx.emit("command-palette:open");
3041
+ open();
3042
+ }
3043
+ };
3044
+ document.addEventListener("keydown", handleKeydown);
3045
+ return {
3046
+ destroy() {
3047
+ close();
3048
+ document.removeEventListener("keydown", handleKeydown);
3049
+ }
3050
+ };
3051
+ }
3052
+ };
3053
+ function BlockHandlesAddon(config) {
3054
+ return { id: "x/block-handles", config, impl: BlockHandlesAddonImpl };
3055
+ }
3056
+ var BlockHandlesAddonImpl = {
3057
+ id: "x/block-handles",
3058
+ init(_ctx) {
3059
+ return {};
3060
+ }
3061
+ };
3062
+ function ContextMenuAddon() {
3063
+ return {
3064
+ id: "x/context-menu",
3065
+ dependencies: ["x/commands"],
3066
+ impl: ContextMenuAddonImpl
3067
+ };
3068
+ }
3069
+ var ContextMenuAddonImpl = {
3070
+ id: "x/context-menu",
3071
+ init(ctx) {
3072
+ const content = ctx.getSlot("content");
3073
+ const handleContextMenu = (e) => {
3074
+ e.preventDefault();
3075
+ ctx.emit("context-menu:open", { x: e.clientX, y: e.clientY });
3076
+ };
3077
+ content?.addEventListener("contextmenu", handleContextMenu);
3078
+ return {
3079
+ destroy() {
3080
+ content?.removeEventListener("contextmenu", handleContextMenu);
3081
+ }
3082
+ };
3083
+ }
3084
+ };
3085
+ function StatusBarAddon(config) {
3086
+ return { id: "x/status-bar", config, impl: StatusBarAddonImpl };
3087
+ }
3088
+ var StatusBarAddonImpl = {
3089
+ id: "x/status-bar",
3090
+ init(ctx, config = {}) {
3091
+ const container = ctx.getSlot("statusbar");
3092
+ if (!container) return {};
3093
+ const slots = config.slots ?? ["wordCount", "charCount"];
3094
+ const bar = document.createElement("div");
3095
+ bar.className = "xe-status-bar";
3096
+ bar.style.display = "flex";
3097
+ bar.style.gap = "12px";
3098
+ bar.style.padding = "4px 8px";
3099
+ container.appendChild(bar);
3100
+ const slotEls = /* @__PURE__ */ new Map();
3101
+ for (const slot of slots) {
3102
+ const el = document.createElement("span");
3103
+ el.dataset["slot"] = slot;
3104
+ el.className = `xe-status-${slot}`;
3105
+ bar.appendChild(el);
3106
+ slotEls.set(slot, el);
3107
+ }
3108
+ let words = 0, chars = 0, peerCount = 0, readingMinutes = 0;
3109
+ const render = () => {
3110
+ for (const [slot, el] of slotEls) {
3111
+ switch (slot) {
3112
+ case "wordCount":
3113
+ el.textContent = `Words: ${words}`;
3114
+ break;
3115
+ case "charCount":
3116
+ el.textContent = `Chars: ${chars}`;
3117
+ break;
3118
+ case "readingTime":
3119
+ el.textContent = `${readingMinutes}m read`;
3120
+ break;
3121
+ case "peers":
3122
+ el.textContent = peerCount > 0 ? `${peerCount} peer${peerCount === 1 ? "" : "s"}` : "Solo";
3123
+ break;
3124
+ case "cursorPos":
3125
+ el.textContent = `Pos: ${ctx.selection.from}`;
3126
+ break;
3127
+ case "saveStatus":
3128
+ el.textContent = "Saved";
3129
+ break;
3130
+ }
3131
+ }
3132
+ };
3133
+ render();
3134
+ const unsubs = [
3135
+ ctx.on("count:update", ((payload) => {
3136
+ const p = payload ?? {};
3137
+ if (typeof p.words === "number") words = p.words;
3138
+ if (typeof p.chars === "number") chars = p.chars;
3139
+ render();
3140
+ })),
3141
+ ctx.on("readingTime:update", ((payload) => {
3142
+ const p = payload ?? {};
3143
+ if (typeof p.minutes === "number") readingMinutes = p.minutes;
3144
+ render();
3145
+ })),
3146
+ ctx.on("collab:awareness", ((payload) => {
3147
+ const p = payload ?? {};
3148
+ if (typeof p.count === "number") peerCount = p.count;
3149
+ render();
3150
+ })),
3151
+ ctx.on("collab:sync", ((payload) => {
3152
+ const p = payload ?? {};
3153
+ if (p.state === "disconnected") {
3154
+ peerCount = 0;
3155
+ render();
3156
+ }
3157
+ })),
3158
+ ctx.on("selection:change", render),
3159
+ ctx.on("auto-save:saved", () => {
3160
+ const el = slotEls.get("saveStatus");
3161
+ if (el) {
3162
+ el.textContent = "Saved \u2713";
3163
+ setTimeout(() => {
3164
+ el.textContent = "Saved";
3165
+ }, 1500);
3166
+ }
3167
+ })
3168
+ ];
3169
+ return {
3170
+ destroy() {
3171
+ for (const u of unsubs) u();
3172
+ bar.remove();
3173
+ }
3174
+ };
3175
+ }
3176
+ };
3177
+
3178
+ // src/structure/index.ts
3179
+ function TableOfContentsAddon(config) {
3180
+ return {
3181
+ id: "x/toc",
3182
+ config,
3183
+ dependencies: ["x/headings"],
3184
+ impl: TableOfContentsAddonImpl
3185
+ };
3186
+ }
3187
+ var TableOfContentsAddonImpl = {
3188
+ id: "x/toc",
3189
+ initSchema(ctx) {
3190
+ ctx.addNode({
3191
+ name: "tableOfContents",
3192
+ group: "block",
3193
+ atom: true,
3194
+ parseDOM: [{ tag: "nav[data-toc]" }],
3195
+ toDOM: () => ["nav", { "data-toc": "true", class: "xe-toc" }]
3196
+ });
3197
+ },
3198
+ init(ctx) {
3199
+ ctx.commands.register({
3200
+ id: "insertTableOfContents",
3201
+ label: "Table of Contents",
3202
+ icon: "toc",
3203
+ isEnabled: () => true,
3204
+ isActive: () => false,
3205
+ execute: (c) => {
3206
+ c.insertNode("tableOfContents");
3207
+ return true;
3208
+ }
3209
+ });
3210
+ ctx.commands.register({
3211
+ id: "toggleOutlinePanel",
3212
+ label: "Toggle Outline Panel",
3213
+ isEnabled: () => true,
3214
+ isActive: () => false,
3215
+ execute: () => true
3216
+ });
3217
+ return {};
3218
+ }
3219
+ };
3220
+ function OutlineAddon() {
3221
+ return {
3222
+ id: "x/outline",
3223
+ dependencies: ["x/headings"],
3224
+ impl: OutlineAddonImpl
3225
+ };
3226
+ }
3227
+ var OutlineAddonImpl = {
3228
+ id: "x/outline",
3229
+ init(_ctx) {
3230
+ return {};
3231
+ }
3232
+ };
3233
+ function CoverAddon(config) {
3234
+ return { id: "x/cover", config, impl: CoverAddonImpl };
3235
+ }
3236
+ var CoverAddonImpl = {
3237
+ id: "x/cover",
3238
+ init(ctx) {
3239
+ ctx.commands.register({
3240
+ id: "setCover",
3241
+ label: "Set Cover",
3242
+ isEnabled: () => true,
3243
+ isActive: () => false,
3244
+ execute: () => true
3245
+ });
3246
+ ctx.commands.register({
3247
+ id: "removeCover",
3248
+ label: "Remove Cover",
3249
+ isEnabled: () => true,
3250
+ isActive: () => false,
3251
+ execute: () => true
3252
+ });
3253
+ ctx.commands.register({
3254
+ id: "repositionCover",
3255
+ label: "Reposition Cover",
3256
+ isEnabled: () => true,
3257
+ isActive: () => false,
3258
+ execute: () => true
3259
+ });
3260
+ return {};
3261
+ }
3262
+ };
3263
+ function BreadcrumbAddon(config) {
3264
+ return { id: "x/breadcrumb", config, impl: BreadcrumbAddonImpl };
3265
+ }
3266
+ var BreadcrumbAddonImpl = {
3267
+ id: "x/breadcrumb",
3268
+ init(_ctx) {
3269
+ return {};
3270
+ }
3271
+ };
3272
+ function TemplatesAddon() {
3273
+ return {
3274
+ id: "x/templates",
3275
+ dependencies: ["x/content"],
3276
+ impl: TemplatesAddonImpl
3277
+ };
3278
+ }
3279
+ var TemplatesAddonImpl = {
3280
+ id: "x/templates",
3281
+ init(ctx) {
3282
+ ctx.commands.register({
3283
+ id: "insertTemplate",
3284
+ label: "Insert Template",
3285
+ icon: "template",
3286
+ isEnabled: () => true,
3287
+ isActive: () => false,
3288
+ execute: () => true
3289
+ });
3290
+ return {};
3291
+ }
3292
+ };
3293
+ function PageSetupAddon(config) {
3294
+ return { id: "x/page-setup", config, impl: PageSetupAddonImpl };
3295
+ }
3296
+ var PageSetupAddonImpl = {
3297
+ id: "x/page-setup",
3298
+ init(ctx) {
3299
+ ctx.commands.register({
3300
+ id: "pageSetup",
3301
+ label: "Page Setup",
3302
+ isEnabled: () => true,
3303
+ isActive: () => false,
3304
+ execute: () => true
3305
+ });
3306
+ return {};
3307
+ }
3308
+ };
3309
+
3310
+ // src/export/index.ts
3311
+ function ContentAddon() {
3312
+ return { id: "x/content", impl: ContentAddonImpl };
3313
+ }
3314
+ function downloadString(filename, content, mimeType) {
3315
+ if (typeof document === "undefined" || typeof URL === "undefined") return;
3316
+ const blob = new Blob([content], { type: mimeType });
3317
+ const url = URL.createObjectURL(blob);
3318
+ const a = document.createElement("a");
3319
+ a.href = url;
3320
+ a.download = filename;
3321
+ a.style.display = "none";
3322
+ document.body.appendChild(a);
3323
+ a.click();
3324
+ setTimeout(() => {
3325
+ a.remove();
3326
+ URL.revokeObjectURL(url);
3327
+ }, 0);
3328
+ }
3329
+ var ContentAddonImpl = {
3330
+ id: "x/content",
3331
+ init(ctx) {
3332
+ ctx.commands.register({
3333
+ id: "exportJson",
3334
+ label: "Export as JSON",
3335
+ isEnabled: () => true,
3336
+ isActive: () => false,
3337
+ execute: (c) => {
3338
+ downloadString(
3339
+ "document.json",
3340
+ c.getContent("json"),
3341
+ "application/json"
3342
+ );
3343
+ return true;
3344
+ }
3345
+ });
3346
+ ctx.commands.register({
3347
+ id: "exportHtml",
3348
+ label: "Export as HTML",
3349
+ isEnabled: () => true,
3350
+ isActive: () => false,
3351
+ execute: (c) => {
3352
+ downloadString("document.html", c.getContent("html"), "text/html");
3353
+ return true;
3354
+ }
3355
+ });
3356
+ ctx.commands.register({
3357
+ id: "exportMarkdown",
3358
+ label: "Export as Markdown",
3359
+ isEnabled: () => true,
3360
+ isActive: () => false,
3361
+ execute: (c) => {
3362
+ downloadString(
3363
+ "document.md",
3364
+ c.getContent("markdown"),
3365
+ "text/markdown"
3366
+ );
3367
+ return true;
3368
+ }
3369
+ });
3370
+ ctx.commands.register({
3371
+ id: "exportText",
3372
+ label: "Export as Text",
3373
+ isEnabled: () => true,
3374
+ isActive: () => false,
3375
+ execute: (c) => {
3376
+ downloadString("document.txt", c.getContent("text"), "text/plain");
3377
+ return true;
3378
+ }
3379
+ });
3380
+ return {};
3381
+ }
3382
+ };
3383
+ function DocxAddon() {
3384
+ return { id: "x/docx", dependencies: ["x/content"], impl: DocxAddonImpl };
3385
+ }
3386
+ var DocxAddonImpl = {
3387
+ id: "x/docx",
3388
+ init(ctx) {
3389
+ ctx.commands.register({
3390
+ id: "exportDocx",
3391
+ label: "Export as DOCX",
3392
+ icon: "docx",
3393
+ isEnabled: () => true,
3394
+ isActive: () => false,
3395
+ execute: () => true
3396
+ });
3397
+ ctx.commands.register({
3398
+ id: "importDocx",
3399
+ label: "Import DOCX",
3400
+ isEnabled: () => true,
3401
+ isActive: () => false,
3402
+ execute: () => true
3403
+ });
3404
+ return {};
3405
+ }
3406
+ };
3407
+ function PdfAddon() {
3408
+ return { id: "x/pdf", dependencies: ["x/content"], impl: PdfAddonImpl };
3409
+ }
3410
+ var PdfAddonImpl = {
3411
+ id: "x/pdf",
3412
+ init(ctx) {
3413
+ ctx.commands.register({
3414
+ id: "exportPdf",
3415
+ label: "Export as PDF",
3416
+ icon: "pdf",
3417
+ isEnabled: () => true,
3418
+ isActive: () => false,
3419
+ execute: () => true
3420
+ });
3421
+ return {};
3422
+ }
3423
+ };
3424
+ function PrintAddon() {
3425
+ return { id: "x/print", impl: PrintAddonImpl };
3426
+ }
3427
+ var PrintAddonImpl = {
3428
+ id: "x/print",
3429
+ init(ctx) {
3430
+ ctx.commands.register({
3431
+ id: "print",
3432
+ label: "Print",
3433
+ icon: "print",
3434
+ shortcut: "Mod-p",
3435
+ isEnabled: () => true,
3436
+ isActive: () => false,
3437
+ execute: () => {
3438
+ window.print();
3439
+ return true;
3440
+ }
3441
+ });
3442
+ return {};
3443
+ }
3444
+ };
3445
+
3446
+ // src/tools/index.ts
3447
+ function SearchAddon() {
3448
+ return { id: "x/search", impl: SearchAddonImpl };
3449
+ }
3450
+ var SearchAddonImpl = {
3451
+ id: "x/search",
3452
+ init(ctx) {
3453
+ ctx.commands.register({
3454
+ id: "findReplace",
3455
+ label: "Find & Replace",
3456
+ icon: "search",
3457
+ shortcut: "Mod-f",
3458
+ isEnabled: () => true,
3459
+ isActive: () => false,
3460
+ execute: () => true
3461
+ });
3462
+ ctx.commands.register({
3463
+ id: "findNext",
3464
+ label: "Find Next",
3465
+ shortcut: "F3",
3466
+ isEnabled: () => true,
3467
+ isActive: () => false,
3468
+ execute: () => true
3469
+ });
3470
+ ctx.commands.register({
3471
+ id: "findPrevious",
3472
+ label: "Find Previous",
3473
+ shortcut: "Shift-F3",
3474
+ isEnabled: () => true,
3475
+ isActive: () => false,
3476
+ execute: () => true
3477
+ });
3478
+ return {};
3479
+ }
3480
+ };
3481
+ function SpellCheckAddon() {
3482
+ return { id: "x/spell-check", impl: SpellCheckAddonImpl };
3483
+ }
3484
+ var SpellCheckAddonImpl = {
3485
+ id: "x/spell-check",
3486
+ init(_ctx) {
3487
+ return {};
3488
+ }
3489
+ };
3490
+ function GrammarAddon() {
3491
+ return {
3492
+ id: "x/grammar",
3493
+ dependencies: ["x/spell-check"],
3494
+ impl: GrammarAddonImpl
3495
+ };
3496
+ }
3497
+ var GrammarAddonImpl = {
3498
+ id: "x/grammar",
3499
+ init(_ctx) {
3500
+ return {};
3501
+ }
3502
+ };
3503
+ function AutoSaveAddon(config) {
3504
+ return {
3505
+ id: "x/auto-save",
3506
+ config,
3507
+ dependencies: ["x/content"],
3508
+ impl: AutoSaveAddonImpl
3509
+ };
3510
+ }
3511
+ var AutoSaveAddonImpl = {
3512
+ id: "x/auto-save",
3513
+ init(ctx, config) {
3514
+ const interval = config.interval ?? 5e3;
3515
+ let timer = null;
3516
+ let dirty = false;
3517
+ const schedSave = () => {
3518
+ dirty = true;
3519
+ if (timer) clearTimeout(timer);
3520
+ timer = setTimeout(async () => {
3521
+ if (!dirty) return;
3522
+ dirty = false;
3523
+ const content = ctx.getContent(config.format ?? "json");
3524
+ await config.save(content, config.format ?? "json").catch(() => {
3525
+ });
3526
+ ctx.emit("auto-save:saved");
3527
+ }, interval);
3528
+ };
3529
+ const unsub = ctx.on("doc:change", schedSave);
3530
+ return {
3531
+ destroy() {
3532
+ unsub();
3533
+ if (timer) clearTimeout(timer);
3534
+ }
3535
+ };
3536
+ }
3537
+ };
3538
+ function ReadOnlyAddon(config) {
3539
+ return { id: "x/read-only", config, impl: ReadOnlyAddonImpl };
3540
+ }
3541
+ var ReadOnlyAddonImpl = {
3542
+ id: "x/read-only",
3543
+ init(ctx, config = {}) {
3544
+ let readOnly = config.readOnly ?? false;
3545
+ const ctxImpl = ctx;
3546
+ if (readOnly) ctxImpl.setEditable(false);
3547
+ ctx.commands.register({
3548
+ id: "toggleReadOnly",
3549
+ label: "Toggle Read Only",
3550
+ isEnabled: () => true,
3551
+ isActive: () => readOnly,
3552
+ execute: () => {
3553
+ readOnly = !readOnly;
3554
+ ctxImpl.setEditable(!readOnly);
3555
+ ctx.emit("read-only:change", { readOnly });
3556
+ return true;
3557
+ }
3558
+ });
3559
+ return {};
3560
+ }
3561
+ };
3562
+
3563
+ // src/collab/index.ts
3564
+ function CollabAddon(config) {
3565
+ return { id: "x/collab", config, impl: CollabAddonImpl };
3566
+ }
3567
+ var CollabAddonImpl = {
3568
+ id: "x/collab",
3569
+ init(ctx, _config) {
3570
+ const binder = ctx._collabBinder;
3571
+ if (!binder?.awareness) return {};
3572
+ const aw = binder.awareness;
3573
+ const emitPeerCount = () => {
3574
+ const states = aw.getStates();
3575
+ const others = Math.max(0, states.size - 1);
3576
+ ctx.emit("collab:awareness", { count: others });
3577
+ };
3578
+ const handler = () => emitPeerCount();
3579
+ aw.on("update", handler);
3580
+ emitPeerCount();
3581
+ return {
3582
+ destroy() {
3583
+ aw.off("update", handler);
3584
+ }
3585
+ };
3586
+ }
3587
+ };
3588
+ function AwarenessAddon(config) {
3589
+ return {
3590
+ id: "x/awareness",
3591
+ config,
3592
+ dependencies: ["x/collab"],
3593
+ impl: AwarenessAddonImpl
3594
+ };
3595
+ }
3596
+ var AwarenessAddonImpl = {
3597
+ id: "x/awareness",
3598
+ init(ctx, config = {}) {
3599
+ const binder = ctx._collabBinder;
3600
+ const aw = binder?.awareness;
3601
+ if (!aw) return {};
3602
+ const palette = [
3603
+ "#e74c3c",
3604
+ "#3498db",
3605
+ "#2ecc71",
3606
+ "#f39c12",
3607
+ "#9b59b6",
3608
+ "#1abc9c"
3609
+ ];
3610
+ const identity = config.identity ?? {
3611
+ id: typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `user-${Math.random().toString(36).slice(2, 10)}`,
3612
+ name: "Anonymous",
3613
+ color: palette[Math.floor(Math.random() * palette.length)]
3614
+ };
3615
+ aw.setLocalStateField("user", identity);
3616
+ if (config.schemaVersion) {
3617
+ aw.setLocalStateField("schemaVersion", config.schemaVersion);
3618
+ }
3619
+ return {
3620
+ destroy() {
3621
+ try {
3622
+ aw.setLocalState(null);
3623
+ } catch {
3624
+ }
3625
+ }
3626
+ };
3627
+ }
3628
+ };
3629
+ function PresenceAddon() {
3630
+ return {
3631
+ id: "x/presence",
3632
+ dependencies: ["x/collab", "x/awareness"],
3633
+ impl: PresenceAddonImpl
3634
+ };
3635
+ }
3636
+ var PresenceAddonImpl = {
3637
+ id: "x/presence",
3638
+ init(_ctx) {
3639
+ return {};
3640
+ }
3641
+ };
3642
+ function CommentsAddon(config) {
3643
+ return { id: "x/comments", config, impl: CommentsAddonImpl };
3644
+ }
3645
+ var CommentsAddonImpl = {
3646
+ id: "x/comments",
3647
+ init(ctx) {
3648
+ ctx.commands.register({
3649
+ id: "addComment",
3650
+ label: "Add Comment",
3651
+ icon: "comment",
3652
+ shortcut: "Mod-Alt-m",
3653
+ isEnabled: () => true,
3654
+ isActive: () => false,
3655
+ execute: () => true
3656
+ });
3657
+ ctx.commands.register({
3658
+ id: "resolveComment",
3659
+ label: "Resolve Comment",
3660
+ isEnabled: () => true,
3661
+ isActive: () => false,
3662
+ execute: () => true
3663
+ });
3664
+ ctx.commands.register({
3665
+ id: "toggleComments",
3666
+ label: "Toggle Comments Panel",
3667
+ isEnabled: () => true,
3668
+ isActive: () => false,
3669
+ execute: () => true
3670
+ });
3671
+ return {};
3672
+ }
3673
+ };
3674
+ function SuggestionsAddon() {
3675
+ return {
3676
+ id: "x/suggestions",
3677
+ dependencies: ["x/schema", "x/commands"],
3678
+ impl: SuggestionsAddonImpl
3679
+ };
3680
+ }
3681
+ var SuggestionsAddonImpl = {
3682
+ id: "x/suggestions",
3683
+ init(ctx) {
3684
+ ctx.commands.register({
3685
+ id: "toggleSuggestions",
3686
+ label: "Toggle Tracked Changes",
3687
+ isEnabled: () => true,
3688
+ isActive: () => false,
3689
+ execute: () => true
3690
+ });
3691
+ ctx.commands.register({
3692
+ id: "acceptSuggestion",
3693
+ label: "Accept Change",
3694
+ isEnabled: () => true,
3695
+ isActive: () => false,
3696
+ execute: () => true
3697
+ });
3698
+ ctx.commands.register({
3699
+ id: "rejectSuggestion",
3700
+ label: "Reject Change",
3701
+ isEnabled: () => true,
3702
+ isActive: () => false,
3703
+ execute: () => true
3704
+ });
3705
+ ctx.commands.register({
3706
+ id: "acceptAllSuggestions",
3707
+ label: "Accept All Changes",
3708
+ isEnabled: () => true,
3709
+ isActive: () => false,
3710
+ execute: () => true
3711
+ });
3712
+ ctx.commands.register({
3713
+ id: "rejectAllSuggestions",
3714
+ label: "Reject All Changes",
3715
+ isEnabled: () => true,
3716
+ isActive: () => false,
3717
+ execute: () => true
3718
+ });
3719
+ return {};
3720
+ }
3721
+ };
3722
+ function VersionAddon() {
3723
+ return {
3724
+ id: "x/version",
3725
+ dependencies: ["x/content"],
3726
+ impl: VersionAddonImpl
3727
+ };
3728
+ }
3729
+ var VersionAddonImpl = {
3730
+ id: "x/version",
3731
+ init(ctx) {
3732
+ ctx.commands.register({
3733
+ id: "createSnapshot",
3734
+ label: "Create Snapshot",
3735
+ isEnabled: () => true,
3736
+ isActive: () => false,
3737
+ execute: () => true
3738
+ });
3739
+ ctx.commands.register({
3740
+ id: "restoreSnapshot",
3741
+ label: "Restore Snapshot",
3742
+ isEnabled: () => true,
3743
+ isActive: () => false,
3744
+ execute: () => true
3745
+ });
3746
+ ctx.commands.register({
3747
+ id: "viewHistory",
3748
+ label: "View History",
3749
+ isEnabled: () => true,
3750
+ isActive: () => false,
3751
+ execute: () => true
3752
+ });
3753
+ return {};
3754
+ }
3755
+ };
3756
+
3757
+ // src/code/index.ts
3758
+ function CodeAddon(config) {
3759
+ return { id: "x/code", config, impl: CodeAddonImpl };
3760
+ }
3761
+ var CodeAddonImpl = {
3762
+ id: "x/code",
3763
+ init(_ctx) {
3764
+ return {};
3765
+ }
3766
+ };
3767
+ function LineNumbersAddon() {
3768
+ return {
3769
+ id: "x/line-numbers",
3770
+ dependencies: ["x/code"],
3771
+ impl: LineNumbersAddonImpl
3772
+ };
3773
+ }
3774
+ var LineNumbersAddonImpl = {
3775
+ id: "x/line-numbers",
3776
+ init(_ctx) {
3777
+ return {};
3778
+ }
3779
+ };
3780
+ function CodeFoldingAddon() {
3781
+ return {
3782
+ id: "x/code-folding",
3783
+ dependencies: ["x/code"],
3784
+ impl: CodeFoldingAddonImpl
3785
+ };
3786
+ }
3787
+ var CodeFoldingAddonImpl = {
3788
+ id: "x/code-folding",
3789
+ init(ctx) {
3790
+ ctx.commands.register({
3791
+ id: "foldCode",
3792
+ label: "Fold Code",
3793
+ isEnabled: () => true,
3794
+ isActive: () => false,
3795
+ execute: () => true
3796
+ });
3797
+ ctx.commands.register({
3798
+ id: "unfoldCode",
3799
+ label: "Unfold Code",
3800
+ isEnabled: () => true,
3801
+ isActive: () => false,
3802
+ execute: () => true
3803
+ });
3804
+ ctx.commands.register({
3805
+ id: "foldAll",
3806
+ label: "Fold All",
3807
+ isEnabled: () => true,
3808
+ isActive: () => false,
3809
+ execute: () => true
3810
+ });
3811
+ ctx.commands.register({
3812
+ id: "unfoldAll",
3813
+ label: "Unfold All",
3814
+ isEnabled: () => true,
3815
+ isActive: () => false,
3816
+ execute: () => true
3817
+ });
3818
+ return {};
3819
+ }
3820
+ };
3821
+ function BracketMatchingAddon() {
3822
+ return {
3823
+ id: "x/bracket-matching",
3824
+ dependencies: ["x/code"],
3825
+ impl: BracketMatchingAddonImpl
3826
+ };
3827
+ }
3828
+ var BracketMatchingAddonImpl = {
3829
+ id: "x/bracket-matching",
3830
+ init(_ctx) {
3831
+ return {};
3832
+ }
3833
+ };
3834
+ function CodeAutoCompleteAddon(config) {
3835
+ return {
3836
+ id: "x/code-autocomplete",
3837
+ config,
3838
+ dependencies: ["x/code"],
3839
+ impl: CodeAutoCompleteAddonImpl
3840
+ };
3841
+ }
3842
+ var CodeAutoCompleteAddonImpl = {
3843
+ id: "x/code-autocomplete",
3844
+ init(_ctx) {
3845
+ return {};
3846
+ }
3847
+ };
3848
+ function CodeLintAddon(config) {
3849
+ return {
3850
+ id: "x/code-lint",
3851
+ config,
3852
+ dependencies: ["x/code"],
3853
+ impl: CodeLintAddonImpl
3854
+ };
3855
+ }
3856
+ var CodeLintAddonImpl = {
3857
+ id: "x/code-lint",
3858
+ init(_ctx) {
3859
+ return {};
3860
+ }
3861
+ };
3862
+ function DiffAddon(config) {
3863
+ return {
3864
+ id: "x/diff",
3865
+ config,
3866
+ dependencies: ["x/code"],
3867
+ impl: DiffAddonImpl
3868
+ };
3869
+ }
3870
+ var DiffAddonImpl = {
3871
+ id: "x/diff",
3872
+ init(ctx) {
3873
+ ctx.commands.register({
3874
+ id: "toggleDiff",
3875
+ label: "Toggle Diff",
3876
+ isEnabled: () => true,
3877
+ isActive: () => false,
3878
+ execute: () => true
3879
+ });
3880
+ return {};
3881
+ }
3882
+ };
3883
+ function MiniMapAddon() {
3884
+ return { id: "x/minimap", dependencies: ["x/code"], impl: MiniMapAddonImpl };
3885
+ }
3886
+ var MiniMapAddonImpl = {
3887
+ id: "x/minimap",
3888
+ init(_ctx) {
3889
+ return {};
3890
+ }
3891
+ };
3892
+
3893
+ // src/utility/index.ts
3894
+ function PlaceholderAddon(config) {
3895
+ return { id: "x/placeholder", config, impl: PlaceholderAddonImpl };
3896
+ }
3897
+ var PlaceholderAddonImpl = {
3898
+ id: "x/placeholder",
3899
+ init(ctx, config) {
3900
+ const container = ctx.getSlot("content");
3901
+ if (!container) return {};
3902
+ const el = document.createElement("div");
3903
+ el.className = "xe-placeholder";
3904
+ el.textContent = config.text;
3905
+ el.style.pointerEvents = "none";
3906
+ el.style.position = "absolute";
3907
+ el.style.color = "var(--xe-fg)";
3908
+ el.style.opacity = "0.4";
3909
+ container.style.position = "relative";
3910
+ container.appendChild(el);
3911
+ const update = () => {
3912
+ const isEmpty = ctx.getContent("text").trim() === "";
3913
+ el.style.display = isEmpty ? "block" : "none";
3914
+ };
3915
+ update();
3916
+ const unsub = ctx.on("doc:change", update);
3917
+ return {
3918
+ destroy() {
3919
+ unsub();
3920
+ el.remove();
3921
+ }
3922
+ };
3923
+ }
3924
+ };
3925
+ function CountAddon(config) {
3926
+ return { id: "x/count", config, impl: CountAddonImpl };
3927
+ }
3928
+ var CountAddonImpl = {
3929
+ id: "x/count",
3930
+ init(ctx, config = {}) {
3931
+ const update = () => {
3932
+ const text = ctx.getContent("text");
3933
+ const words = text.trim() === "" ? 0 : text.trim().split(/\s+/).length;
3934
+ const chars = text.length;
3935
+ ctx.emit("count:update", { words, chars });
3936
+ };
3937
+ update();
3938
+ const unsub = ctx.on("doc:change", update);
3939
+ return { destroy: unsub };
3940
+ }
3941
+ };
3942
+ function ReadingTimeAddon() {
3943
+ return { id: "x/reading-time", impl: ReadingTimeAddonImpl };
3944
+ }
3945
+ var ReadingTimeAddonImpl = {
3946
+ id: "x/reading-time",
3947
+ init(ctx) {
3948
+ const update = () => {
3949
+ const text = ctx.getContent("text");
3950
+ const words = text.trim() === "" ? 0 : text.trim().split(/\s+/).length;
3951
+ const minutes = Math.ceil(words / 200);
3952
+ ctx.emit("readingTime:update", { minutes, words });
3953
+ };
3954
+ const unsub = ctx.on("doc:change", update);
3955
+ return { destroy: unsub };
3956
+ }
3957
+ };
3958
+ function FocusModeAddon(config) {
3959
+ return { id: "x/focus-mode", config, impl: FocusModeAddonImpl };
3960
+ }
3961
+ var FocusModeAddonImpl = {
3962
+ id: "x/focus-mode",
3963
+ init(ctx) {
3964
+ let active = false;
3965
+ ctx.commands.register({
3966
+ id: "toggleFocusMode",
3967
+ label: "Toggle Focus Mode",
3968
+ icon: "focus",
3969
+ isEnabled: () => true,
3970
+ isActive: () => active,
3971
+ execute: () => {
3972
+ active = !active;
3973
+ ctx.emit("focus-mode:change", { active });
3974
+ return true;
3975
+ }
3976
+ });
3977
+ return {};
3978
+ }
3979
+ };
3980
+ function FullScreenAddon() {
3981
+ return { id: "x/fullscreen", impl: FullScreenAddonImpl };
3982
+ }
3983
+ var FullScreenAddonImpl = {
3984
+ id: "x/fullscreen",
3985
+ init(ctx) {
3986
+ ctx.commands.register({
3987
+ id: "toggleFullScreen",
3988
+ label: "Toggle Full Screen",
3989
+ icon: "fullscreen",
3990
+ shortcut: "F11",
3991
+ isEnabled: () => true,
3992
+ isActive: () => !!document.fullscreenElement,
3993
+ execute: () => {
3994
+ if (document.fullscreenElement) {
3995
+ document.exitFullscreen?.();
3996
+ } else {
3997
+ ctx.shadowRoot?.host?.requestFullscreen?.();
3998
+ }
3999
+ return true;
4000
+ }
4001
+ });
4002
+ return {};
4003
+ }
4004
+ };
4005
+ function AccessibilityAddon() {
4006
+ return { id: "x/accessibility", impl: AccessibilityAddonImpl };
4007
+ }
4008
+ var AccessibilityAddonImpl = {
4009
+ id: "x/accessibility",
4010
+ init(ctx) {
4011
+ const content = ctx.getSlot("content");
4012
+ if (content) {
4013
+ content.setAttribute("role", "textbox");
4014
+ content.setAttribute("aria-multiline", "true");
4015
+ }
4016
+ const toolbar = ctx.getSlot("toolbar");
4017
+ if (toolbar) {
4018
+ toolbar.setAttribute("role", "toolbar");
4019
+ }
4020
+ return {};
4021
+ }
4022
+ };
4023
+ function MarkdownAddon(config) {
4024
+ return {
4025
+ id: "x/markdown",
4026
+ config,
4027
+ dependencies: ["x/schema"],
4028
+ impl: MarkdownAddonImpl
4029
+ };
4030
+ }
4031
+ var MarkdownAddonImpl = {
4032
+ id: "x/markdown",
4033
+ init(ctx) {
4034
+ ctx.commands.register({
4035
+ id: "toggleMarkdownMode",
4036
+ label: "Toggle Markdown Mode",
4037
+ isEnabled: () => true,
4038
+ isActive: () => false,
4039
+ execute: () => true
4040
+ });
4041
+ ctx.commands.register({
4042
+ id: "toggleMarkdownPreview",
4043
+ label: "Toggle Markdown Preview",
4044
+ isEnabled: () => true,
4045
+ isActive: () => false,
4046
+ execute: () => true
4047
+ });
4048
+ return {};
4049
+ }
4050
+ };
4051
+
4052
+ // src/index.ts
4053
+ var ADDON_IMPLEMENTATIONS = /* @__PURE__ */ new Map([
4054
+ [SchemaAddonImpl.id, SchemaAddonImpl],
4055
+ [CommandsAddonImpl.id, CommandsAddonImpl],
4056
+ [KeymapAddonImpl.id, KeymapAddonImpl],
4057
+ [HistoryAddonImpl.id, HistoryAddonImpl],
4058
+ [InputRulesAddonImpl.id, InputRulesAddonImpl],
4059
+ [BoldAddonImpl.id, BoldAddonImpl],
4060
+ [ItalicAddonImpl.id, ItalicAddonImpl],
4061
+ [UnderlineAddonImpl.id, UnderlineAddonImpl],
4062
+ [StrikethroughAddonImpl.id, StrikethroughAddonImpl],
4063
+ [InlineCodeAddonImpl.id, InlineCodeAddonImpl],
4064
+ [SubscriptAddonImpl.id, SubscriptAddonImpl],
4065
+ [SuperscriptAddonImpl.id, SuperscriptAddonImpl],
4066
+ [HighlightAddonImpl.id, HighlightAddonImpl],
4067
+ [TextColorAddonImpl.id, TextColorAddonImpl],
4068
+ [FontFamilyAddonImpl.id, FontFamilyAddonImpl],
4069
+ [FontSizeAddonImpl.id, FontSizeAddonImpl],
4070
+ [ClearFormattingAddonImpl.id, ClearFormattingAddonImpl],
4071
+ [AlignmentAddonImpl.id, AlignmentAddonImpl],
4072
+ [LineHeightAddonImpl.id, LineHeightAddonImpl],
4073
+ [ParagraphSpacingAddonImpl.id, ParagraphSpacingAddonImpl],
4074
+ [IndentAddonImpl.id, IndentAddonImpl],
4075
+ [HeadingsAddonImpl.id, HeadingsAddonImpl],
4076
+ [BlockquoteAddonImpl.id, BlockquoteAddonImpl],
4077
+ [DividerAddonImpl.id, DividerAddonImpl],
4078
+ [PageBreakAddonImpl.id, PageBreakAddonImpl],
4079
+ [CalloutAddonImpl.id, CalloutAddonImpl],
4080
+ [DetailsAddonImpl.id, DetailsAddonImpl],
4081
+ [ColumnsAddonImpl.id, ColumnsAddonImpl],
4082
+ [CodeBlockAddonImpl.id, CodeBlockAddonImpl],
4083
+ [BulletListAddonImpl.id, BulletListAddonImpl],
4084
+ [OrderedListAddonImpl.id, OrderedListAddonImpl],
4085
+ [TaskListAddonImpl.id, TaskListAddonImpl],
4086
+ [ToggleListAddonImpl.id, ToggleListAddonImpl],
4087
+ [TableAddonImpl.id, TableAddonImpl],
4088
+ [ImageAddonImpl.id, ImageAddonImpl],
4089
+ [VideoAddonImpl.id, VideoAddonImpl],
4090
+ [AudioAddonImpl.id, AudioAddonImpl],
4091
+ [FileAddonImpl.id, FileAddonImpl],
4092
+ [EmbedAddonImpl.id, EmbedAddonImpl],
4093
+ [BookmarkAddonImpl.id, BookmarkAddonImpl],
4094
+ [LinkAddonImpl.id, LinkAddonImpl],
4095
+ [MentionAddonImpl.id, MentionAddonImpl],
4096
+ [EmojiAddonImpl.id, EmojiAddonImpl],
4097
+ [EquationAddonImpl.id, EquationAddonImpl],
4098
+ [FootnoteAddonImpl.id, FootnoteAddonImpl],
4099
+ [SmartChipAddonImpl.id, SmartChipAddonImpl],
4100
+ [ToolbarAddonImpl.id, ToolbarAddonImpl],
4101
+ [BubbleMenuAddonImpl.id, BubbleMenuAddonImpl],
4102
+ [SlashMenuAddonImpl.id, SlashMenuAddonImpl],
4103
+ [CommandPaletteAddonImpl.id, CommandPaletteAddonImpl],
4104
+ [BlockHandlesAddonImpl.id, BlockHandlesAddonImpl],
4105
+ [ContextMenuAddonImpl.id, ContextMenuAddonImpl],
4106
+ [StatusBarAddonImpl.id, StatusBarAddonImpl],
4107
+ [TableOfContentsAddonImpl.id, TableOfContentsAddonImpl],
4108
+ [OutlineAddonImpl.id, OutlineAddonImpl],
4109
+ [CoverAddonImpl.id, CoverAddonImpl],
4110
+ [BreadcrumbAddonImpl.id, BreadcrumbAddonImpl],
4111
+ [TemplatesAddonImpl.id, TemplatesAddonImpl],
4112
+ [PageSetupAddonImpl.id, PageSetupAddonImpl],
4113
+ [ContentAddonImpl.id, ContentAddonImpl],
4114
+ [DocxAddonImpl.id, DocxAddonImpl],
4115
+ [PdfAddonImpl.id, PdfAddonImpl],
4116
+ [PrintAddonImpl.id, PrintAddonImpl],
4117
+ [SearchAddonImpl.id, SearchAddonImpl],
4118
+ [SpellCheckAddonImpl.id, SpellCheckAddonImpl],
4119
+ [GrammarAddonImpl.id, GrammarAddonImpl],
4120
+ [AutoSaveAddonImpl.id, AutoSaveAddonImpl],
4121
+ [ReadOnlyAddonImpl.id, ReadOnlyAddonImpl],
4122
+ [CollabAddonImpl.id, CollabAddonImpl],
4123
+ [AwarenessAddonImpl.id, AwarenessAddonImpl],
4124
+ [PresenceAddonImpl.id, PresenceAddonImpl],
4125
+ [CommentsAddonImpl.id, CommentsAddonImpl],
4126
+ [SuggestionsAddonImpl.id, SuggestionsAddonImpl],
4127
+ [VersionAddonImpl.id, VersionAddonImpl],
4128
+ [CodeAddonImpl.id, CodeAddonImpl],
4129
+ [LineNumbersAddonImpl.id, LineNumbersAddonImpl],
4130
+ [CodeFoldingAddonImpl.id, CodeFoldingAddonImpl],
4131
+ [BracketMatchingAddonImpl.id, BracketMatchingAddonImpl],
4132
+ [CodeAutoCompleteAddonImpl.id, CodeAutoCompleteAddonImpl],
4133
+ [CodeLintAddonImpl.id, CodeLintAddonImpl],
4134
+ [DiffAddonImpl.id, DiffAddonImpl],
4135
+ [MiniMapAddonImpl.id, MiniMapAddonImpl],
4136
+ [PlaceholderAddonImpl.id, PlaceholderAddonImpl],
4137
+ [CountAddonImpl.id, CountAddonImpl],
4138
+ [ReadingTimeAddonImpl.id, ReadingTimeAddonImpl],
4139
+ [FocusModeAddonImpl.id, FocusModeAddonImpl],
4140
+ [FullScreenAddonImpl.id, FullScreenAddonImpl],
4141
+ [AccessibilityAddonImpl.id, AccessibilityAddonImpl],
4142
+ [MarkdownAddonImpl.id, MarkdownAddonImpl]
4143
+ ]);
4144
+ // Annotate the CommonJS export names for ESM import in node:
4145
+ 0 && (module.exports = {
4146
+ ADDON_IMPLEMENTATIONS,
4147
+ AccessibilityAddon,
4148
+ AccessibilityAddonImpl,
4149
+ AlignmentAddon,
4150
+ AlignmentAddonImpl,
4151
+ AudioAddon,
4152
+ AudioAddonImpl,
4153
+ AutoSaveAddon,
4154
+ AutoSaveAddonImpl,
4155
+ AwarenessAddon,
4156
+ AwarenessAddonImpl,
4157
+ BlockHandlesAddon,
4158
+ BlockHandlesAddonImpl,
4159
+ BlockquoteAddon,
4160
+ BlockquoteAddonImpl,
4161
+ BoldAddon,
4162
+ BoldAddonImpl,
4163
+ BookmarkAddon,
4164
+ BookmarkAddonImpl,
4165
+ BracketMatchingAddon,
4166
+ BracketMatchingAddonImpl,
4167
+ BreadcrumbAddon,
4168
+ BreadcrumbAddonImpl,
4169
+ BubbleMenuAddon,
4170
+ BubbleMenuAddonImpl,
4171
+ BulletListAddon,
4172
+ BulletListAddonImpl,
4173
+ CalloutAddon,
4174
+ CalloutAddonImpl,
4175
+ ClearFormattingAddon,
4176
+ ClearFormattingAddonImpl,
4177
+ CodeAddon,
4178
+ CodeAddonImpl,
4179
+ CodeAutoCompleteAddon,
4180
+ CodeAutoCompleteAddonImpl,
4181
+ CodeBlockAddon,
4182
+ CodeBlockAddonImpl,
4183
+ CodeFoldingAddon,
4184
+ CodeFoldingAddonImpl,
4185
+ CodeLintAddon,
4186
+ CodeLintAddonImpl,
4187
+ CollabAddon,
4188
+ CollabAddonImpl,
4189
+ ColumnsAddon,
4190
+ ColumnsAddonImpl,
4191
+ CommandPaletteAddon,
4192
+ CommandPaletteAddonImpl,
4193
+ CommandsAddon,
4194
+ CommandsAddonImpl,
4195
+ CommentsAddon,
4196
+ CommentsAddonImpl,
4197
+ ContentAddon,
4198
+ ContentAddonImpl,
4199
+ ContextMenuAddon,
4200
+ ContextMenuAddonImpl,
4201
+ CountAddon,
4202
+ CountAddonImpl,
4203
+ CoverAddon,
4204
+ CoverAddonImpl,
4205
+ DetailsAddon,
4206
+ DetailsAddonImpl,
4207
+ DiffAddon,
4208
+ DiffAddonImpl,
4209
+ DividerAddon,
4210
+ DividerAddonImpl,
4211
+ DocxAddon,
4212
+ DocxAddonImpl,
4213
+ EmbedAddon,
4214
+ EmbedAddonImpl,
4215
+ EmojiAddon,
4216
+ EmojiAddonImpl,
4217
+ EquationAddon,
4218
+ EquationAddonImpl,
4219
+ FileAddon,
4220
+ FileAddonImpl,
4221
+ FocusModeAddon,
4222
+ FocusModeAddonImpl,
4223
+ FontFamilyAddon,
4224
+ FontFamilyAddonImpl,
4225
+ FontSizeAddon,
4226
+ FontSizeAddonImpl,
4227
+ FootnoteAddon,
4228
+ FootnoteAddonImpl,
4229
+ FullScreenAddon,
4230
+ FullScreenAddonImpl,
4231
+ GrammarAddon,
4232
+ GrammarAddonImpl,
4233
+ HeadingsAddon,
4234
+ HeadingsAddonImpl,
4235
+ HighlightAddon,
4236
+ HighlightAddonImpl,
4237
+ HistoryAddon,
4238
+ HistoryAddonImpl,
4239
+ ImageAddon,
4240
+ ImageAddonImpl,
4241
+ IndentAddon,
4242
+ IndentAddonImpl,
4243
+ InlineCodeAddon,
4244
+ InlineCodeAddonImpl,
4245
+ InputRulesAddon,
4246
+ InputRulesAddonImpl,
4247
+ ItalicAddon,
4248
+ ItalicAddonImpl,
4249
+ KeymapAddon,
4250
+ KeymapAddonImpl,
4251
+ LineHeightAddon,
4252
+ LineHeightAddonImpl,
4253
+ LineNumbersAddon,
4254
+ LineNumbersAddonImpl,
4255
+ LinkAddon,
4256
+ LinkAddonImpl,
4257
+ ListsAddon,
4258
+ MarkdownAddon,
4259
+ MarkdownAddonImpl,
4260
+ MentionAddon,
4261
+ MentionAddonImpl,
4262
+ MiniMapAddon,
4263
+ MiniMapAddonImpl,
4264
+ OrderedListAddon,
4265
+ OrderedListAddonImpl,
4266
+ OutlineAddon,
4267
+ OutlineAddonImpl,
4268
+ PageBreakAddon,
4269
+ PageBreakAddonImpl,
4270
+ PageSetupAddon,
4271
+ PageSetupAddonImpl,
4272
+ ParagraphSpacingAddon,
4273
+ ParagraphSpacingAddonImpl,
4274
+ PdfAddon,
4275
+ PdfAddonImpl,
4276
+ PlaceholderAddon,
4277
+ PlaceholderAddonImpl,
4278
+ PresenceAddon,
4279
+ PresenceAddonImpl,
4280
+ PrintAddon,
4281
+ PrintAddonImpl,
4282
+ ReadOnlyAddon,
4283
+ ReadOnlyAddonImpl,
4284
+ ReadingTimeAddon,
4285
+ ReadingTimeAddonImpl,
4286
+ SchemaAddon,
4287
+ SchemaAddonImpl,
4288
+ SearchAddon,
4289
+ SearchAddonImpl,
4290
+ SlashMenuAddon,
4291
+ SlashMenuAddonImpl,
4292
+ SmartChipAddon,
4293
+ SmartChipAddonImpl,
4294
+ SpellCheckAddon,
4295
+ SpellCheckAddonImpl,
4296
+ StatusBarAddon,
4297
+ StatusBarAddonImpl,
4298
+ StrikethroughAddon,
4299
+ StrikethroughAddonImpl,
4300
+ SubscriptAddon,
4301
+ SubscriptAddonImpl,
4302
+ SuggestionsAddon,
4303
+ SuggestionsAddonImpl,
4304
+ SuperscriptAddon,
4305
+ SuperscriptAddonImpl,
4306
+ TableAddon,
4307
+ TableAddonImpl,
4308
+ TableOfContentsAddon,
4309
+ TableOfContentsAddonImpl,
4310
+ TaskListAddon,
4311
+ TaskListAddonImpl,
4312
+ TemplatesAddon,
4313
+ TemplatesAddonImpl,
4314
+ TextColorAddon,
4315
+ TextColorAddonImpl,
4316
+ ToggleListAddon,
4317
+ ToggleListAddonImpl,
4318
+ ToolbarAddon,
4319
+ ToolbarAddonImpl,
4320
+ UnderlineAddon,
4321
+ UnderlineAddonImpl,
4322
+ VersionAddon,
4323
+ VersionAddonImpl,
4324
+ VideoAddon,
4325
+ VideoAddonImpl,
4326
+ createCommandGroup
4327
+ });
4328
+ //# sourceMappingURL=index.cjs.map