@haklex/rich-editor 0.0.80 → 0.0.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/AlertQuoteEditNode-BDoonB4u.js +267 -0
  2. package/dist/KaTeXRenderer-BsyRH5_t.js +214 -0
  3. package/dist/LinkCardRenderer-OEMBDUhD.js +45 -0
  4. package/dist/MermaidPlugin-Df2Cm2yX.js +67 -0
  5. package/dist/PresentDialogContext-DQw6MrNh.js +59 -0
  6. package/dist/RubyRenderer-BpDb_amz.js +14 -0
  7. package/dist/SubmitShortcutPlugin-6IvsbZD-.js +1463 -0
  8. package/dist/commands-entry.mjs +14 -23
  9. package/dist/config-tfg1FWhG.js +1149 -0
  10. package/dist/context/NestedContentRendererContext.d.ts +2 -1
  11. package/dist/context/NestedContentRendererContext.d.ts.map +1 -1
  12. package/dist/favicon-DIWusrrw.js +41 -0
  13. package/dist/index.mjs +259 -284
  14. package/dist/node-registry-CeVi2y9f.js +666 -0
  15. package/dist/nodes-entry.mjs +7 -47
  16. package/dist/plugins-entry.mjs +10 -27
  17. package/dist/renderers-entry.mjs +40 -57
  18. package/dist/rich-editor.css +2 -1
  19. package/dist/shared.css-wgGgtK_e.js +23 -0
  20. package/dist/static-entry.mjs +16 -45
  21. package/dist/styles-entry.mjs +3 -12
  22. package/dist/theme-DHOUKKSr.js +1034 -0
  23. package/package.json +4 -4
  24. package/dist/AlertQuoteEditNode-CHdvQnOr.js +0 -293
  25. package/dist/KaTeXRenderer-C8jv_5xr.js +0 -214
  26. package/dist/LinkCardRenderer-QmkOlyXb.js +0 -36
  27. package/dist/MermaidPlugin-DjLUVZvB.js +0 -97
  28. package/dist/PresentDialogContext-BpSB8tXC.js +0 -52
  29. package/dist/RubyRenderer-DbeobSoH.js +0 -13
  30. package/dist/SubmitShortcutPlugin-BFBAwTb1.js +0 -1627
  31. package/dist/config-DcR_yktp.js +0 -1236
  32. package/dist/favicon-BQgbXF_a.js +0 -43
  33. package/dist/node-registry-B2U2_LrI.js +0 -766
  34. package/dist/shared.css-DNuMYx6Q.js +0 -21
  35. package/dist/theme-CYsyGmCL.js +0 -1040
@@ -0,0 +1,1149 @@
1
+ import { A as _defineProperty, P as useNestedContentRenderer, S as ImageNode, T as FootnoteNode, g as KaTeXInlineNode, i as TagNode, j as extractTextContent, k as AlertQuoteNode, p as MentionNode, s as SpoilerNode, u as MermaidNode, y as KaTeXBlockNode } from "./theme-DHOUKKSr.js";
2
+ import { l as RendererWrapper, m as useVariant, s as useFootnoteDefinitions, u as createRendererDecoration } from "./KaTeXRenderer-BsyRH5_t.js";
3
+ import { t as LinkCardRenderer } from "./LinkCardRenderer-OEMBDUhD.js";
4
+ import { AutoLinkNode, LinkNode } from "@lexical/link";
5
+ import { createContext, createElement, use, useCallback, useEffect, useRef, useState } from "react";
6
+ import { HeadingNode, QuoteNode } from "@lexical/rich-text";
7
+ import { $createTextNode, $insertNodes, DecoratorNode, ElementNode } from "lexical";
8
+ import { HorizontalRuleNode } from "@lexical/extension";
9
+ import { CodeNode } from "@lexical/code";
10
+ import { ListItemNode, ListNode } from "@lexical/list";
11
+ import { TableCellNode, TableNode, TableRowNode } from "@lexical/table";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ import { ChevronRight, Code, Link, Video } from "lucide-react";
14
+ //#region src/components/renderers/BannerRenderer.tsx
15
+ var BannerRenderer = ({ type }) => {
16
+ return /* @__PURE__ */ jsx("span", { className: `rich-banner-icon rich-banner-icon-${type}` });
17
+ };
18
+ //#endregion
19
+ //#region src/components/renderers/BannerStaticDecorator.tsx
20
+ function BannerStaticDecorator({ bannerType, contentState }) {
21
+ const renderContent = useNestedContentRenderer();
22
+ return /* @__PURE__ */ jsxs("div", {
23
+ className: "rich-banner-inner",
24
+ children: [/* @__PURE__ */ jsx(RendererWrapper, {
25
+ defaultRenderer: BannerRenderer,
26
+ props: { type: bannerType },
27
+ rendererKey: "Banner"
28
+ }), /* @__PURE__ */ jsx("div", {
29
+ className: "rich-banner-content",
30
+ children: renderContent(contentState)
31
+ })]
32
+ });
33
+ }
34
+ //#endregion
35
+ //#region src/nodes/BannerNode.ts
36
+ var LEGACY_TYPE_MAP = {
37
+ info: "note",
38
+ success: "tip",
39
+ error: "caution"
40
+ };
41
+ function normalizeBannerType(type) {
42
+ if (type in LEGACY_TYPE_MAP) return LEGACY_TYPE_MAP[type];
43
+ return type || "note";
44
+ }
45
+ var BANNER_TYPES = [
46
+ "note",
47
+ "tip",
48
+ "important",
49
+ "warning",
50
+ "caution"
51
+ ];
52
+ var BANNER_LABELS = {
53
+ note: "Note",
54
+ tip: "Tip",
55
+ important: "Important",
56
+ warning: "Warning",
57
+ caution: "Caution"
58
+ };
59
+ var BannerNode = class BannerNode extends DecoratorNode {
60
+ static getType() {
61
+ return "banner";
62
+ }
63
+ static clone(node) {
64
+ return new BannerNode(node.__bannerType, node.__contentState, node.__key);
65
+ }
66
+ constructor(bannerType, contentState, key) {
67
+ super(key);
68
+ _defineProperty(this, "__bannerType", void 0);
69
+ _defineProperty(this, "__contentState", void 0);
70
+ this.__bannerType = bannerType;
71
+ this.__contentState = contentState || { root: {
72
+ children: [{
73
+ type: "paragraph",
74
+ children: [],
75
+ direction: null,
76
+ format: "",
77
+ indent: 0,
78
+ textFormat: 0,
79
+ textStyle: "",
80
+ version: 1
81
+ }],
82
+ direction: null,
83
+ format: "",
84
+ indent: 0,
85
+ type: "root",
86
+ version: 1
87
+ } };
88
+ }
89
+ createDOM(_config) {
90
+ const div = document.createElement("div");
91
+ div.className = `rich-banner rich-banner-${this.__bannerType}`;
92
+ return div;
93
+ }
94
+ updateDOM(prevNode, dom) {
95
+ if (prevNode.__bannerType !== this.__bannerType) dom.className = `rich-banner rich-banner-${this.__bannerType}`;
96
+ return false;
97
+ }
98
+ isInline() {
99
+ return false;
100
+ }
101
+ getBannerType() {
102
+ return this.__bannerType;
103
+ }
104
+ setBannerType(bannerType) {
105
+ const writable = this.getWritable();
106
+ writable.__bannerType = bannerType;
107
+ }
108
+ getContentState() {
109
+ return this.getLatest().__contentState;
110
+ }
111
+ setContentState(state) {
112
+ const writable = this.getWritable();
113
+ writable.__contentState = state;
114
+ }
115
+ getTextContent() {
116
+ return extractTextContent(this.__contentState);
117
+ }
118
+ static importJSON(serializedNode) {
119
+ const legacy = serializedNode;
120
+ const bannerType = normalizeBannerType(serializedNode.bannerType);
121
+ if (serializedNode.content) return new BannerNode(bannerType, serializedNode.content);
122
+ if (legacy.children) return new BannerNode(bannerType, { root: {
123
+ children: legacy.children,
124
+ direction: null,
125
+ format: "",
126
+ indent: 0,
127
+ type: "root",
128
+ version: 1
129
+ } });
130
+ return new BannerNode(bannerType);
131
+ }
132
+ exportJSON() {
133
+ return {
134
+ ...super.exportJSON(),
135
+ type: "banner",
136
+ bannerType: this.__bannerType,
137
+ content: this.__contentState,
138
+ version: 1
139
+ };
140
+ }
141
+ decorate(_editor, _config) {
142
+ return createElement(BannerStaticDecorator, {
143
+ bannerType: this.__bannerType,
144
+ contentState: this.__contentState
145
+ });
146
+ }
147
+ };
148
+ function $isBannerNode(node) {
149
+ return node instanceof BannerNode;
150
+ }
151
+ //#endregion
152
+ //#region src/context/ColorSchemeContext.tsx
153
+ var ColorSchemeContext = createContext("light");
154
+ function ColorSchemeProvider({ colorScheme, children }) {
155
+ return /* @__PURE__ */ jsx(ColorSchemeContext.Provider, {
156
+ value: colorScheme,
157
+ children
158
+ });
159
+ }
160
+ function useColorScheme() {
161
+ return use(ColorSchemeContext);
162
+ }
163
+ //#endregion
164
+ //#region src/utils/shiki.ts
165
+ var codeToHtmlFn = null;
166
+ var shikiLoadPromise = null;
167
+ function loadCodeToHtml() {
168
+ if (codeToHtmlFn) return Promise.resolve(codeToHtmlFn);
169
+ if (!shikiLoadPromise) shikiLoadPromise = import("shiki/bundle/web").then((mod) => {
170
+ codeToHtmlFn = mod.codeToHtml;
171
+ return mod.codeToHtml;
172
+ }).catch((err) => {
173
+ shikiLoadPromise = null;
174
+ throw err;
175
+ });
176
+ return shikiLoadPromise;
177
+ }
178
+ //#endregion
179
+ //#region src/components/renderers/CodeBlockRenderer.tsx
180
+ function CodeBlockRenderer({ code, language, showLineNumbers: showLineNumbersProp }) {
181
+ const variant = useVariant();
182
+ const showLineNumbers = showLineNumbersProp ?? variant !== "comment";
183
+ const shikiTheme = useColorScheme() === "dark" ? "github-dark" : "github-light";
184
+ const [highlightedHtml, setHighlightedHtml] = useState(null);
185
+ const [copied, setCopied] = useState(false);
186
+ const copyTimerRef = useRef(void 0);
187
+ useEffect(() => {
188
+ let cancelled = false;
189
+ setHighlightedHtml(null);
190
+ loadCodeToHtml().then((toHtml) => toHtml(code, {
191
+ lang: language,
192
+ theme: shikiTheme
193
+ })).then((html) => {
194
+ if (!cancelled) setHighlightedHtml(html);
195
+ }).catch(() => {
196
+ if (!cancelled) setHighlightedHtml(null);
197
+ });
198
+ return () => {
199
+ cancelled = true;
200
+ };
201
+ }, [
202
+ code,
203
+ language,
204
+ shikiTheme
205
+ ]);
206
+ useEffect(() => {
207
+ return () => clearTimeout(copyTimerRef.current);
208
+ }, []);
209
+ const handleCopy = useCallback(() => {
210
+ navigator.clipboard.writeText(code).then(() => {
211
+ setCopied(true);
212
+ clearTimeout(copyTimerRef.current);
213
+ copyTimerRef.current = setTimeout(() => setCopied(false), 2e3);
214
+ }).catch(() => {});
215
+ }, [code]);
216
+ const header = language ? /* @__PURE__ */ jsxs("div", {
217
+ className: "rich-code-block-header",
218
+ children: [/* @__PURE__ */ jsx("span", {
219
+ className: "rich-code-block-lang",
220
+ children: language
221
+ }), /* @__PURE__ */ jsx("button", {
222
+ "aria-label": copied ? "Copied to clipboard" : "Copy code",
223
+ className: "rich-code-block-copy",
224
+ type: "button",
225
+ onClick: handleCopy,
226
+ children: copied ? "Copied" : "Copy"
227
+ })]
228
+ }) : null;
229
+ const wrapperClass = showLineNumbers ? "rich-code-block rich-code-block-numbered" : "rich-code-block";
230
+ if (highlightedHtml) return /* @__PURE__ */ jsxs("div", {
231
+ className: wrapperClass,
232
+ children: [header, /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: highlightedHtml } })]
233
+ });
234
+ const lines = code.split("\n");
235
+ return /* @__PURE__ */ jsxs("div", {
236
+ className: wrapperClass,
237
+ children: [header, /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: lines.map((line, i) => /* @__PURE__ */ jsxs("span", {
238
+ className: "line",
239
+ children: [line, i < lines.length - 1 ? "\n" : ""]
240
+ }, i)) }) })]
241
+ });
242
+ }
243
+ //#endregion
244
+ //#region src/nodes/CodeBlockNode.ts
245
+ var CodeBlockNode = class CodeBlockNode extends DecoratorNode {
246
+ static getType() {
247
+ return "code-block";
248
+ }
249
+ static clone(node) {
250
+ return new CodeBlockNode(node.__code, node.__language, node.__key);
251
+ }
252
+ constructor(code, language, key) {
253
+ super(key);
254
+ _defineProperty(this, "__code", void 0);
255
+ _defineProperty(this, "__language", void 0);
256
+ this.__code = code;
257
+ this.__language = language;
258
+ }
259
+ createDOM(_config) {
260
+ const div = document.createElement("div");
261
+ div.className = "rich-code-block-wrapper";
262
+ return div;
263
+ }
264
+ updateDOM() {
265
+ return false;
266
+ }
267
+ isInline() {
268
+ return false;
269
+ }
270
+ isKeyboardSelectable() {
271
+ return true;
272
+ }
273
+ static importJSON(serializedNode) {
274
+ return $createCodeBlockNode(serializedNode.code, serializedNode.language);
275
+ }
276
+ exportJSON() {
277
+ return {
278
+ ...super.exportJSON(),
279
+ type: "code-block",
280
+ code: this.__code,
281
+ language: this.__language,
282
+ version: 1
283
+ };
284
+ }
285
+ getCode() {
286
+ return this.__code;
287
+ }
288
+ setCode(code) {
289
+ const writable = this.getWritable();
290
+ writable.__code = code;
291
+ }
292
+ getLanguage() {
293
+ return this.__language;
294
+ }
295
+ setLanguage(language) {
296
+ const writable = this.getWritable();
297
+ writable.__language = language;
298
+ }
299
+ decorate(_editor, _config) {
300
+ return createRendererDecoration("CodeBlock", CodeBlockRenderer, {
301
+ code: this.__code,
302
+ language: this.__language
303
+ });
304
+ }
305
+ };
306
+ _defineProperty(CodeBlockNode, "commandItems", [{
307
+ title: "Code Block",
308
+ icon: createElement(Code, { size: 20 }),
309
+ description: "Syntax-highlighted code",
310
+ keywords: [
311
+ "code",
312
+ "snippet",
313
+ "codeblock"
314
+ ],
315
+ section: "MEDIA",
316
+ placement: ["slash", "toolbar"],
317
+ group: "insert",
318
+ onSelect: (editor) => {
319
+ editor.update(() => {
320
+ $insertNodes([$createCodeBlockNode("", "text")]);
321
+ });
322
+ }
323
+ }]);
324
+ function $createCodeBlockNode(code, language) {
325
+ return new CodeBlockNode(code, language);
326
+ }
327
+ function $isCodeBlockNode(node) {
328
+ return node instanceof CodeBlockNode;
329
+ }
330
+ //#endregion
331
+ //#region src/utils/lucide-dom.ts
332
+ var SVG_NS = "http://www.w3.org/2000/svg";
333
+ var DEFAULT_ATTRS = {
334
+ xmlns: SVG_NS,
335
+ width: "24",
336
+ height: "24",
337
+ viewBox: "0 0 24 24",
338
+ fill: "none",
339
+ stroke: "currentColor",
340
+ "stroke-width": "2",
341
+ "stroke-linecap": "round",
342
+ "stroke-linejoin": "round"
343
+ };
344
+ function createLucideSvg(iconNode, attrs = {}) {
345
+ const svg = document.createElementNS(SVG_NS, "svg");
346
+ const merged = {
347
+ ...DEFAULT_ATTRS,
348
+ ...attrs
349
+ };
350
+ for (const [k, v] of Object.entries(merged)) svg.setAttribute(k, v);
351
+ for (const [tag, elAttrs] of iconNode) {
352
+ const el = document.createElementNS(SVG_NS, tag);
353
+ for (const [k, v] of Object.entries(elAttrs)) {
354
+ if (k === "key") continue;
355
+ el.setAttribute(k, v);
356
+ }
357
+ svg.append(el);
358
+ }
359
+ return svg;
360
+ }
361
+ //#endregion
362
+ //#region src/nodes/DetailsNode.ts
363
+ var ChevronRightIconNode = [["path", { d: "M8 6L12 10L8 14" }]];
364
+ var DetailsNode = class DetailsNode extends ElementNode {
365
+ static getType() {
366
+ return "details";
367
+ }
368
+ static clone(node) {
369
+ return new DetailsNode(node.__summary, node.__open, node.__key);
370
+ }
371
+ constructor(summary, open = false, key) {
372
+ super(key);
373
+ _defineProperty(this, "__summary", void 0);
374
+ _defineProperty(this, "__open", void 0);
375
+ this.__summary = summary;
376
+ this.__open = open;
377
+ }
378
+ createDOM(_config) {
379
+ const details = document.createElement("details");
380
+ details.className = "rich-details";
381
+ if (this.__open) details.open = true;
382
+ const summary = document.createElement("summary");
383
+ summary.className = "rich-details-summary";
384
+ const chevron = document.createElement("span");
385
+ chevron.className = "rich-details-chevron";
386
+ chevron.setAttribute("aria-hidden", "true");
387
+ chevron.append(createLucideSvg(ChevronRightIconNode, {
388
+ width: "20",
389
+ height: "20",
390
+ viewBox: "0 0 20 20",
391
+ "stroke-width": "1.5"
392
+ }));
393
+ summary.append(chevron);
394
+ const label = document.createElement("span");
395
+ label.className = "rich-details-summary-text";
396
+ label.textContent = this.__summary;
397
+ summary.append(label);
398
+ const content = document.createElement("div");
399
+ content.className = "rich-details-content";
400
+ details.append(summary, content);
401
+ return details;
402
+ }
403
+ updateDOM(prevNode, dom) {
404
+ const details = dom;
405
+ if (prevNode.__open !== this.__open) details.open = this.__open;
406
+ if (prevNode.__summary !== this.__summary) {
407
+ const label = dom.querySelector(".rich-details-summary-text");
408
+ if (label) label.textContent = this.__summary;
409
+ }
410
+ return false;
411
+ }
412
+ static importJSON(serializedNode) {
413
+ return $createDetailsNode(serializedNode.summary, serializedNode.open);
414
+ }
415
+ exportJSON() {
416
+ return {
417
+ ...super.exportJSON(),
418
+ type: "details",
419
+ summary: this.__summary,
420
+ open: this.__open,
421
+ version: 1
422
+ };
423
+ }
424
+ getSummary() {
425
+ return this.getLatest().__summary;
426
+ }
427
+ setSummary(summary) {
428
+ const writable = this.getWritable();
429
+ writable.__summary = summary;
430
+ }
431
+ getOpen() {
432
+ return this.getLatest().__open;
433
+ }
434
+ setOpen(open) {
435
+ const writable = this.getWritable();
436
+ writable.__open = open;
437
+ }
438
+ toggleOpen() {
439
+ this.setOpen(!this.getOpen());
440
+ }
441
+ getDOMSlot(element) {
442
+ const content = element.querySelector(".rich-details-content");
443
+ return super.getDOMSlot(element).withElement(content);
444
+ }
445
+ isInline() {
446
+ return false;
447
+ }
448
+ };
449
+ _defineProperty(DetailsNode, "slashMenuItems", [{
450
+ title: "Details",
451
+ icon: createElement(ChevronRight, { size: 20 }),
452
+ description: "Collapsible content block",
453
+ keywords: [
454
+ "details",
455
+ "toggle",
456
+ "collapse",
457
+ "accordion"
458
+ ],
459
+ section: "ADVANCED",
460
+ onSelect: (editor) => {
461
+ editor.update(() => {
462
+ $insertNodes([$createDetailsNode("Details")]);
463
+ });
464
+ }
465
+ }]);
466
+ function $createDetailsNode(summary, open = false) {
467
+ return new DetailsNode(summary, open);
468
+ }
469
+ //#endregion
470
+ //#region src/components/renderers/FootnoteSectionRenderer.tsx
471
+ function FootnoteSectionRenderer({ definitions }) {
472
+ const { displayNumberMap } = useFootnoteDefinitions();
473
+ const sortedEntries = Object.entries(definitions).sort(([a], [b]) => (displayNumberMap[a] ?? 0) - (displayNumberMap[b] ?? 0));
474
+ if (sortedEntries.length === 0) return null;
475
+ return /* @__PURE__ */ jsxs("div", {
476
+ className: "rich-footnote-section-content",
477
+ role: "doc-endnotes",
478
+ children: [/* @__PURE__ */ jsx("hr", { className: "rich-footnote-section-divider" }), /* @__PURE__ */ jsx("ol", {
479
+ className: "rich-footnote-section-list",
480
+ children: sortedEntries.map(([identifier, content]) => {
481
+ return /* @__PURE__ */ jsx(FootnoteSectionItem, {
482
+ content,
483
+ displayNum: displayNumberMap[identifier] ?? identifier,
484
+ identifier
485
+ }, identifier);
486
+ })
487
+ })]
488
+ });
489
+ }
490
+ function FootnoteSectionItem({ identifier, content, displayNum }) {
491
+ const targetId = `footnote-${identifier}`;
492
+ const refId = `footnote-ref-${identifier}`;
493
+ const handleBackClick = useCallback((e) => {
494
+ e.preventDefault();
495
+ const refElement = document.getElementById(refId);
496
+ if (!refElement) return;
497
+ refElement.scrollIntoView({
498
+ behavior: "smooth",
499
+ block: "center"
500
+ });
501
+ refElement.classList.add("rich-footnote-highlight");
502
+ window.setTimeout(() => {
503
+ refElement.classList.remove("rich-footnote-highlight");
504
+ }, 1200);
505
+ }, [refId]);
506
+ return /* @__PURE__ */ jsxs("li", {
507
+ className: "rich-footnote-section-item",
508
+ id: targetId,
509
+ value: typeof displayNum === "number" ? displayNum : void 0,
510
+ children: [/* @__PURE__ */ jsx("span", {
511
+ className: "rich-footnote-section-item-content",
512
+ children: content
513
+ }), /* @__PURE__ */ jsx("a", {
514
+ "aria-label": `Back to reference ${displayNum}`,
515
+ className: "rich-footnote-back-ref",
516
+ href: `#${refId}`,
517
+ role: "doc-backlink",
518
+ onClick: handleBackClick,
519
+ children: "↩"
520
+ })]
521
+ });
522
+ }
523
+ //#endregion
524
+ //#region src/nodes/FootnoteSectionNode.ts
525
+ var FootnoteSectionNode = class FootnoteSectionNode extends DecoratorNode {
526
+ static getType() {
527
+ return "footnote-section";
528
+ }
529
+ static clone(node) {
530
+ return new FootnoteSectionNode({ ...node.__definitions }, node.__key);
531
+ }
532
+ constructor(definitions, key) {
533
+ super(key);
534
+ _defineProperty(this, "__definitions", void 0);
535
+ this.__definitions = definitions;
536
+ }
537
+ createDOM(_config) {
538
+ const div = document.createElement("div");
539
+ div.className = "rich-footnote-section";
540
+ return div;
541
+ }
542
+ updateDOM() {
543
+ return false;
544
+ }
545
+ isInline() {
546
+ return false;
547
+ }
548
+ static importJSON(serializedNode) {
549
+ return $createFootnoteSectionNode(serializedNode.definitions);
550
+ }
551
+ exportJSON() {
552
+ return {
553
+ ...super.exportJSON(),
554
+ type: "footnote-section",
555
+ definitions: this.__definitions,
556
+ version: 1
557
+ };
558
+ }
559
+ getDefinitions() {
560
+ return this.getLatest().__definitions;
561
+ }
562
+ setDefinitions(definitions) {
563
+ const writable = this.getWritable();
564
+ writable.__definitions = definitions;
565
+ }
566
+ getDefinition(identifier) {
567
+ return this.getLatest().__definitions[identifier];
568
+ }
569
+ setDefinition(identifier, content) {
570
+ const writable = this.getWritable();
571
+ writable.__definitions = {
572
+ ...writable.__definitions,
573
+ [identifier]: content
574
+ };
575
+ }
576
+ removeDefinition(identifier) {
577
+ const writable = this.getWritable();
578
+ const { [identifier]: _, ...rest } = writable.__definitions;
579
+ writable.__definitions = rest;
580
+ }
581
+ decorate(_editor, _config) {
582
+ return createRendererDecoration("FootnoteSection", FootnoteSectionRenderer, {
583
+ definitions: this.__definitions,
584
+ nodeKey: this.__key
585
+ });
586
+ }
587
+ };
588
+ function $createFootnoteSectionNode(definitions = {}) {
589
+ return new FootnoteSectionNode(definitions);
590
+ }
591
+ function $isFootnoteSectionNode(node) {
592
+ return node instanceof FootnoteSectionNode;
593
+ }
594
+ //#endregion
595
+ //#region src/components/renderers/GridStaticDecorator.tsx
596
+ function GridStaticDecorator({ cols, gap, cellStates }) {
597
+ const renderContent = useNestedContentRenderer();
598
+ return /* @__PURE__ */ jsx("div", {
599
+ className: "rich-grid-inner",
600
+ style: {
601
+ display: "grid",
602
+ gridTemplateColumns: `repeat(${cols}, 1fr)`,
603
+ gap
604
+ },
605
+ children: cellStates.map((state, i) => /* @__PURE__ */ jsx("div", {
606
+ className: "rich-grid-cell",
607
+ children: renderContent(state)
608
+ }, i))
609
+ });
610
+ }
611
+ //#endregion
612
+ //#region src/nodes/GridContainerNode.ts
613
+ var GridContainerNode = class GridContainerNode extends DecoratorNode {
614
+ static getType() {
615
+ return "grid-container";
616
+ }
617
+ static clone(node) {
618
+ return new GridContainerNode(node.__cols, node.__gap, [...node.__cellStates], node.__key);
619
+ }
620
+ constructor(cols = 2, gap, cellStates, key) {
621
+ super(key);
622
+ _defineProperty(this, "__cols", void 0);
623
+ _defineProperty(this, "__gap", void 0);
624
+ _defineProperty(this, "__cellStates", void 0);
625
+ this.__cols = cols;
626
+ this.__gap = gap || "16px";
627
+ if (cellStates) this.__cellStates = cellStates;
628
+ else {
629
+ const emptyState = { root: {
630
+ children: [{
631
+ type: "paragraph",
632
+ children: [],
633
+ direction: null,
634
+ format: "",
635
+ indent: 0,
636
+ textFormat: 0,
637
+ textStyle: "",
638
+ version: 1
639
+ }],
640
+ direction: null,
641
+ format: "",
642
+ indent: 0,
643
+ type: "root",
644
+ version: 1
645
+ } };
646
+ this.__cellStates = Array.from({ length: cols }, () => emptyState);
647
+ }
648
+ }
649
+ createDOM(_config) {
650
+ const div = document.createElement("div");
651
+ div.className = "rich-grid-container";
652
+ return div;
653
+ }
654
+ updateDOM() {
655
+ return false;
656
+ }
657
+ isInline() {
658
+ return false;
659
+ }
660
+ getCols() {
661
+ return this.getLatest().__cols;
662
+ }
663
+ setCols(cols) {
664
+ const writable = this.getWritable();
665
+ const prev = writable.__cellStates.length;
666
+ writable.__cols = cols;
667
+ if (cols > prev) {
668
+ const emptyState = { root: {
669
+ children: [{
670
+ type: "paragraph",
671
+ children: [],
672
+ direction: null,
673
+ format: "",
674
+ indent: 0,
675
+ textFormat: 0,
676
+ textStyle: "",
677
+ version: 1
678
+ }],
679
+ direction: null,
680
+ format: "",
681
+ indent: 0,
682
+ type: "root",
683
+ version: 1
684
+ } };
685
+ for (let i = prev; i < cols; i++) writable.__cellStates.push(emptyState);
686
+ }
687
+ }
688
+ getGap() {
689
+ return this.getLatest().__gap;
690
+ }
691
+ setGap(gap) {
692
+ const writable = this.getWritable();
693
+ writable.__gap = gap;
694
+ }
695
+ getCellStates() {
696
+ return this.getLatest().__cellStates;
697
+ }
698
+ addCells(count) {
699
+ const writable = this.getWritable();
700
+ const emptyState = { root: {
701
+ children: [{
702
+ type: "paragraph",
703
+ children: [],
704
+ direction: null,
705
+ format: "",
706
+ indent: 0,
707
+ textFormat: 0,
708
+ textStyle: "",
709
+ version: 1
710
+ }],
711
+ direction: null,
712
+ format: "",
713
+ indent: 0,
714
+ type: "root",
715
+ version: 1
716
+ } };
717
+ for (let i = 0; i < count; i++) writable.__cellStates.push(emptyState);
718
+ }
719
+ removeCells(count) {
720
+ const states = this.getWritable().__cellStates;
721
+ const toRemove = Math.min(count, states.length);
722
+ for (let i = 0; i < toRemove; i++) {
723
+ const state = states.at(-1);
724
+ if (!state) break;
725
+ if (!(extractTextContent(state).trim() === "")) break;
726
+ states.pop();
727
+ }
728
+ }
729
+ getTextContent() {
730
+ return this.__cellStates.map((s) => extractTextContent(s)).join("\n");
731
+ }
732
+ static importJSON(serializedNode) {
733
+ const legacy = serializedNode;
734
+ const cols = legacy.cols || 2;
735
+ const rawGap = legacy.gap;
736
+ const gap = typeof rawGap === "number" ? `${rawGap}px` : rawGap;
737
+ if (legacy.cells && legacy.cells.length > 0) return new GridContainerNode(cols, gap, legacy.cells);
738
+ if (legacy.children) return new GridContainerNode(cols, gap, legacy.children.map((child) => {
739
+ return { root: {
740
+ children: [child],
741
+ direction: null,
742
+ format: "",
743
+ indent: 0,
744
+ type: "root",
745
+ version: 1
746
+ } };
747
+ }));
748
+ return new GridContainerNode(cols, gap);
749
+ }
750
+ exportJSON() {
751
+ return {
752
+ ...super.exportJSON(),
753
+ type: "grid-container",
754
+ cols: this.__cols,
755
+ gap: this.__gap,
756
+ cells: this.__cellStates,
757
+ version: 1
758
+ };
759
+ }
760
+ decorate(_editor, _config) {
761
+ return createElement(GridStaticDecorator, {
762
+ cols: this.__cols,
763
+ gap: this.__gap,
764
+ cellStates: this.__cellStates
765
+ });
766
+ }
767
+ };
768
+ function $createGridContainerNode(cols = 2, gap) {
769
+ return new GridContainerNode(cols, gap);
770
+ }
771
+ function $isGridContainerNode(node) {
772
+ return node instanceof GridContainerNode;
773
+ }
774
+ //#endregion
775
+ //#region src/nodes/LinkCardNode.ts
776
+ var LinkCardNode = class LinkCardNode extends DecoratorNode {
777
+ static getType() {
778
+ return "link-card";
779
+ }
780
+ static clone(node) {
781
+ return new LinkCardNode({
782
+ url: node.__url,
783
+ source: node.__source,
784
+ id: node.__id,
785
+ title: node.__title,
786
+ description: node.__description,
787
+ favicon: node.__favicon,
788
+ image: node.__image
789
+ }, node.__key);
790
+ }
791
+ constructor(payload, key) {
792
+ super(key);
793
+ _defineProperty(this, "__url", void 0);
794
+ _defineProperty(this, "__source", void 0);
795
+ _defineProperty(this, "__id", void 0);
796
+ _defineProperty(this, "__title", void 0);
797
+ _defineProperty(this, "__description", void 0);
798
+ _defineProperty(this, "__favicon", void 0);
799
+ _defineProperty(this, "__image", void 0);
800
+ this.__url = payload.url;
801
+ this.__source = payload.source;
802
+ this.__id = payload.id;
803
+ this.__title = payload.title;
804
+ this.__description = payload.description;
805
+ this.__favicon = payload.favicon;
806
+ this.__image = payload.image;
807
+ }
808
+ createDOM(_config) {
809
+ const div = document.createElement("div");
810
+ div.className = "rich-link-card-wrapper";
811
+ return div;
812
+ }
813
+ updateDOM() {
814
+ return false;
815
+ }
816
+ isInline() {
817
+ return false;
818
+ }
819
+ static importJSON(serializedNode) {
820
+ return $createLinkCardNode({
821
+ url: serializedNode.url,
822
+ source: serializedNode.source,
823
+ id: serializedNode.id,
824
+ title: serializedNode.title,
825
+ description: serializedNode.description,
826
+ favicon: serializedNode.favicon,
827
+ image: serializedNode.image
828
+ });
829
+ }
830
+ exportJSON() {
831
+ return {
832
+ ...super.exportJSON(),
833
+ type: "link-card",
834
+ url: this.__url,
835
+ source: this.__source,
836
+ id: this.__id,
837
+ title: this.__title,
838
+ description: this.__description,
839
+ favicon: this.__favicon,
840
+ image: this.__image,
841
+ version: 1
842
+ };
843
+ }
844
+ getUrl() {
845
+ return this.getLatest().__url;
846
+ }
847
+ setUrl(url) {
848
+ const writable = this.getWritable();
849
+ writable.__url = url;
850
+ }
851
+ getSource() {
852
+ return this.getLatest().__source;
853
+ }
854
+ setSource(source) {
855
+ const writable = this.getWritable();
856
+ writable.__source = source;
857
+ }
858
+ getId() {
859
+ return this.getLatest().__id;
860
+ }
861
+ setId(id) {
862
+ const writable = this.getWritable();
863
+ writable.__id = id;
864
+ }
865
+ decorate(_editor, _config) {
866
+ return createRendererDecoration("LinkCard", LinkCardRenderer, {
867
+ url: this.__url,
868
+ source: this.__source,
869
+ id: this.__id,
870
+ title: this.__title,
871
+ description: this.__description,
872
+ favicon: this.__favicon,
873
+ image: this.__image
874
+ });
875
+ }
876
+ };
877
+ _defineProperty(LinkCardNode, "commandItems", [{
878
+ title: "Link Card",
879
+ icon: createElement(Link, { size: 20 }),
880
+ description: "Link preview card",
881
+ keywords: [
882
+ "link",
883
+ "card",
884
+ "bookmark",
885
+ "embed"
886
+ ],
887
+ section: "MEDIA",
888
+ placement: ["slash", "toolbar"],
889
+ group: "insert",
890
+ onSelect: (editor) => {
891
+ editor.update(() => {
892
+ $insertNodes([$createLinkCardNode({ url: "" })]);
893
+ });
894
+ }
895
+ }]);
896
+ function $createLinkCardNode(payload) {
897
+ return new LinkCardNode(payload);
898
+ }
899
+ function $isLinkCardNode(node) {
900
+ return node instanceof LinkCardNode;
901
+ }
902
+ //#endregion
903
+ //#region src/nodes/RubyNode.ts
904
+ function readBaseTextFromRuby(element) {
905
+ let base = "";
906
+ for (const child of Array.from(element.childNodes)) {
907
+ if (child.nodeType === Node.TEXT_NODE) {
908
+ base += child.textContent ?? "";
909
+ continue;
910
+ }
911
+ if (child.nodeType !== Node.ELEMENT_NODE) continue;
912
+ const childElement = child;
913
+ const tag = childElement.tagName.toLowerCase();
914
+ if (tag === "rt" || tag === "rp") continue;
915
+ base += childElement.textContent ?? "";
916
+ }
917
+ return base;
918
+ }
919
+ var RubyNode = class RubyNode extends ElementNode {
920
+ static getType() {
921
+ return "ruby";
922
+ }
923
+ static clone(node) {
924
+ return new RubyNode(node.__reading, node.__key);
925
+ }
926
+ constructor(reading, key) {
927
+ super(key);
928
+ _defineProperty(this, "__reading", void 0);
929
+ this.__reading = reading;
930
+ }
931
+ static importJSON(serializedNode) {
932
+ return $createRubyNode(serializedNode.reading ?? "");
933
+ }
934
+ exportJSON() {
935
+ return {
936
+ ...super.exportJSON(),
937
+ type: "ruby",
938
+ reading: this.__reading,
939
+ version: 1
940
+ };
941
+ }
942
+ static importDOM() {
943
+ return { ruby: () => ({
944
+ conversion: (domNode) => {
945
+ if (!(domNode instanceof HTMLElement)) return null;
946
+ const reading = domNode.querySelector("rt")?.textContent ?? "";
947
+ const baseText = readBaseTextFromRuby(domNode);
948
+ const node = $createRubyNode(reading);
949
+ if (baseText) node.append($createTextNode(baseText));
950
+ return { node };
951
+ },
952
+ priority: 2
953
+ }) };
954
+ }
955
+ exportDOM() {
956
+ const ruby = document.createElement("ruby");
957
+ ruby.className = "rich-ruby";
958
+ const baseText = this.getTextContent();
959
+ if (baseText) ruby.append(baseText);
960
+ if (this.__reading) {
961
+ const rt = document.createElement("rt");
962
+ rt.className = "rich-ruby-rt";
963
+ rt.textContent = this.__reading;
964
+ ruby.append(rt);
965
+ }
966
+ return { element: ruby };
967
+ }
968
+ createDOM(_config) {
969
+ const span = document.createElement("span");
970
+ span.className = "rich-ruby";
971
+ if (this.__reading) span.dataset.ruby = this.__reading;
972
+ return span;
973
+ }
974
+ updateDOM(prevNode, dom) {
975
+ if (prevNode.__reading !== this.__reading) if (this.__reading) dom.dataset.ruby = this.__reading;
976
+ else delete dom.dataset.ruby;
977
+ return false;
978
+ }
979
+ canInsertTextBefore() {
980
+ return true;
981
+ }
982
+ canInsertTextAfter() {
983
+ return true;
984
+ }
985
+ isInline() {
986
+ return true;
987
+ }
988
+ getReading() {
989
+ return this.getLatest().__reading;
990
+ }
991
+ setReading(reading) {
992
+ const writable = this.getWritable();
993
+ writable.__reading = reading;
994
+ }
995
+ };
996
+ function $createRubyNode(reading) {
997
+ return new RubyNode(reading);
998
+ }
999
+ function $isRubyNode(node) {
1000
+ return node instanceof RubyNode;
1001
+ }
1002
+ //#endregion
1003
+ //#region src/components/renderers/VideoRenderer.tsx
1004
+ function VideoRenderer({ src, poster, width, height }) {
1005
+ return /* @__PURE__ */ jsx("figure", {
1006
+ className: "rich-video",
1007
+ children: /* @__PURE__ */ jsx("video", {
1008
+ controls: true,
1009
+ height,
1010
+ poster,
1011
+ preload: "metadata",
1012
+ src,
1013
+ style: {
1014
+ maxWidth: "100%",
1015
+ height: "auto"
1016
+ },
1017
+ width
1018
+ })
1019
+ });
1020
+ }
1021
+ //#endregion
1022
+ //#region src/nodes/VideoNode.ts
1023
+ var VideoNode = class VideoNode extends DecoratorNode {
1024
+ static getType() {
1025
+ return "video";
1026
+ }
1027
+ static clone(node) {
1028
+ return new VideoNode({
1029
+ src: node.__src,
1030
+ poster: node.__poster,
1031
+ width: node.__width,
1032
+ height: node.__height
1033
+ }, node.__key);
1034
+ }
1035
+ constructor(payload, key) {
1036
+ super(key);
1037
+ _defineProperty(this, "__src", void 0);
1038
+ _defineProperty(this, "__poster", void 0);
1039
+ _defineProperty(this, "__width", void 0);
1040
+ _defineProperty(this, "__height", void 0);
1041
+ this.__src = payload.src;
1042
+ this.__poster = payload.poster;
1043
+ this.__width = payload.width;
1044
+ this.__height = payload.height;
1045
+ }
1046
+ createDOM(_config) {
1047
+ const div = document.createElement("div");
1048
+ div.className = "rich-video-wrapper";
1049
+ return div;
1050
+ }
1051
+ updateDOM() {
1052
+ return false;
1053
+ }
1054
+ isInline() {
1055
+ return false;
1056
+ }
1057
+ static importJSON(serializedNode) {
1058
+ return $createVideoNode({
1059
+ src: serializedNode.src,
1060
+ poster: serializedNode.poster,
1061
+ width: serializedNode.width,
1062
+ height: serializedNode.height
1063
+ });
1064
+ }
1065
+ exportJSON() {
1066
+ return {
1067
+ ...super.exportJSON(),
1068
+ type: "video",
1069
+ src: this.__src,
1070
+ poster: this.__poster,
1071
+ width: this.__width,
1072
+ height: this.__height,
1073
+ version: 1
1074
+ };
1075
+ }
1076
+ getSrc() {
1077
+ return this.getLatest().__src;
1078
+ }
1079
+ setSrc(src) {
1080
+ const writable = this.getWritable();
1081
+ writable.__src = src;
1082
+ }
1083
+ decorate(_editor, _config) {
1084
+ return createRendererDecoration("Video", VideoRenderer, {
1085
+ src: this.__src,
1086
+ poster: this.__poster,
1087
+ width: this.__width,
1088
+ height: this.__height
1089
+ });
1090
+ }
1091
+ };
1092
+ _defineProperty(VideoNode, "commandItems", [{
1093
+ title: "Video",
1094
+ icon: createElement(Video, { size: 20 }),
1095
+ description: "Embed a video",
1096
+ keywords: [
1097
+ "video",
1098
+ "media",
1099
+ "mp4"
1100
+ ],
1101
+ section: "MEDIA",
1102
+ placement: ["slash", "toolbar"],
1103
+ group: "insert",
1104
+ onSelect: (editor) => {
1105
+ editor.update(() => {
1106
+ $insertNodes([$createVideoNode({ src: "" })]);
1107
+ });
1108
+ }
1109
+ }]);
1110
+ function $createVideoNode(payload) {
1111
+ return new VideoNode(payload);
1112
+ }
1113
+ //#endregion
1114
+ //#region src/config.ts
1115
+ var builtinNodes = [
1116
+ HeadingNode,
1117
+ QuoteNode,
1118
+ ListNode,
1119
+ ListItemNode,
1120
+ LinkNode,
1121
+ AutoLinkNode,
1122
+ HorizontalRuleNode,
1123
+ TableNode,
1124
+ TableCellNode,
1125
+ TableRowNode,
1126
+ CodeNode
1127
+ ];
1128
+ var customNodes = [
1129
+ SpoilerNode,
1130
+ MentionNode,
1131
+ KaTeXInlineNode,
1132
+ KaTeXBlockNode,
1133
+ ImageNode,
1134
+ AlertQuoteNode,
1135
+ CodeBlockNode,
1136
+ FootnoteNode,
1137
+ FootnoteSectionNode,
1138
+ VideoNode,
1139
+ LinkCardNode,
1140
+ DetailsNode,
1141
+ GridContainerNode,
1142
+ BannerNode,
1143
+ MermaidNode,
1144
+ RubyNode,
1145
+ TagNode
1146
+ ];
1147
+ var allNodes = [...builtinNodes, ...customNodes];
1148
+ //#endregion
1149
+ export { useColorScheme as C, BannerNode as D, BANNER_TYPES as E, normalizeBannerType as O, ColorSchemeProvider as S, BANNER_LABELS as T, $createDetailsNode as _, $createRubyNode as a, CodeBlockNode as b, $createLinkCardNode as c, $createGridContainerNode as d, $isGridContainerNode as f, FootnoteSectionNode as g, $isFootnoteSectionNode as h, VideoNode as i, BannerRenderer as k, $isLinkCardNode as l, $createFootnoteSectionNode as m, builtinNodes as n, $isRubyNode as o, GridContainerNode as p, customNodes as r, RubyNode as s, allNodes as t, LinkCardNode as u, DetailsNode as v, $isBannerNode as w, CodeBlockRenderer as x, $isCodeBlockNode as y };