@haklex/rich-editor 0.0.81 → 0.0.83

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 (66) hide show
  1. package/dist/AlertQuoteEditNode-B2q-1u6S.js +293 -0
  2. package/dist/KaTeXRenderer-BFryJSIS.js +218 -0
  3. package/dist/LinkCardRenderer-QmkOlyXb.js +36 -0
  4. package/dist/MermaidPlugin-BEtIhQHn.js +97 -0
  5. package/dist/PresentDialogContext-D5dHWtzD.js +58 -0
  6. package/dist/RubyRenderer-cm5eDc9q.js +14 -0
  7. package/dist/SubmitShortcutPlugin-o2y6b-8f.js +1650 -0
  8. package/dist/commands-entry.mjs +23 -14
  9. package/dist/components/LinkFavicon.d.ts.map +1 -1
  10. package/dist/components/renderers/FootnoteRenderer.d.ts.map +1 -1
  11. package/dist/components/renderers/FootnoteSectionEditRenderer.d.ts.map +1 -1
  12. package/dist/components/renderers/FootnoteSectionRenderer.d.ts.map +1 -1
  13. package/dist/components/renderers/FootnoteStaticRenderer.d.ts.map +1 -1
  14. package/dist/components/renderers/RubyRenderer.d.ts.map +1 -1
  15. package/dist/components/renderers/TagRenderer.d.ts.map +1 -1
  16. package/dist/config-BP_kyJbW.js +1363 -0
  17. package/dist/config-edit.d.ts.map +1 -1
  18. package/dist/config.d.ts.map +1 -1
  19. package/dist/context/NestedContentRendererContext.d.ts +2 -1
  20. package/dist/context/NestedContentRendererContext.d.ts.map +1 -1
  21. package/dist/favicon-BQgbXF_a.js +43 -0
  22. package/dist/index.mjs +283 -259
  23. package/dist/node-registry-Dzp7X3R4.js +811 -0
  24. package/dist/nodes/AlertQuoteNode.d.ts.map +1 -1
  25. package/dist/nodes/CommentNode.d.ts +21 -0
  26. package/dist/nodes/CommentNode.d.ts.map +1 -0
  27. package/dist/nodes/FootnoteNode.d.ts.map +1 -1
  28. package/dist/nodes/FootnoteSectionNode.d.ts.map +1 -1
  29. package/dist/nodes/RubyNode.d.ts.map +1 -1
  30. package/dist/nodes/SpoilerNode.d.ts.map +1 -1
  31. package/dist/nodes/TagNode.d.ts.map +1 -1
  32. package/dist/nodes-entry.d.ts +2 -0
  33. package/dist/nodes-entry.d.ts.map +1 -1
  34. package/dist/nodes-entry.mjs +50 -7
  35. package/dist/plugins/MarkdownPastePlugin.d.ts.map +1 -1
  36. package/dist/plugins-entry.mjs +27 -10
  37. package/dist/renderers-entry.mjs +61 -40
  38. package/dist/rich-editor.css +1 -2
  39. package/dist/static-entry.d.ts +1 -1
  40. package/dist/static-entry.d.ts.map +1 -1
  41. package/dist/static-entry.mjs +55 -16
  42. package/dist/styles/shared.css.d.ts +164 -0
  43. package/dist/styles/shared.css.d.ts.map +1 -1
  44. package/dist/styles/theme.d.ts.map +1 -1
  45. package/dist/styles-entry.d.ts +2 -2
  46. package/dist/styles-entry.d.ts.map +1 -1
  47. package/dist/styles-entry.mjs +14 -3
  48. package/dist/theme-Cg8JUW_j.js +1034 -0
  49. package/dist/transformers/comment.d.ts +4 -0
  50. package/dist/transformers/comment.d.ts.map +1 -0
  51. package/dist/transformers/index.d.ts +1 -0
  52. package/dist/transformers/index.d.ts.map +1 -1
  53. package/dist/utils-gy2c_HWc.js +24 -0
  54. package/package.json +4 -4
  55. package/dist/AlertQuoteEditNode-BDoonB4u.js +0 -267
  56. package/dist/KaTeXRenderer-BsyRH5_t.js +0 -214
  57. package/dist/LinkCardRenderer-OEMBDUhD.js +0 -45
  58. package/dist/MermaidPlugin-Df2Cm2yX.js +0 -67
  59. package/dist/PresentDialogContext-DQw6MrNh.js +0 -59
  60. package/dist/RubyRenderer-BpDb_amz.js +0 -14
  61. package/dist/SubmitShortcutPlugin-6IvsbZD-.js +0 -1463
  62. package/dist/config-tfg1FWhG.js +0 -1149
  63. package/dist/favicon-DIWusrrw.js +0 -41
  64. package/dist/node-registry-CeVi2y9f.js +0 -666
  65. package/dist/shared.css-wgGgtK_e.js +0 -23
  66. package/dist/theme-DHOUKKSr.js +0 -1034
@@ -0,0 +1,1034 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { DecoratorNode, createCommand, $insertNodes, $getSelection, $isRangeSelection, $getNodeByKey, ElementNode, TextNode } from "lexical";
5
+ import { createContext, use, createElement, useState, useCallback, useEffect, useMemo } from "react";
6
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
7
+ import { a as RendererWrapper, c as createRendererDecoration, h as FootnoteStaticRenderer, j as decodeThumbHash, K as KaTeXRenderer } from "./KaTeXRenderer-BFryJSIS.js";
8
+ import { OctagonAlert, TriangleAlert, MessageSquareWarning, Lightbulb, Info, ImageIcon, Sigma, Workflow, Tag } from "lucide-react";
9
+ import { s as semanticClassNames, b as sharedStyles } from "./utils-gy2c_HWc.js";
10
+ const NestedContentRendererContext = createContext(null);
11
+ const NestedContentRendererProvider = NestedContentRendererContext.Provider;
12
+ function useOptionalNestedContentRenderer() {
13
+ return use(NestedContentRendererContext);
14
+ }
15
+ function useNestedContentRenderer() {
16
+ const fn = use(NestedContentRendererContext);
17
+ if (!fn) {
18
+ throw new Error("useNestedContentRenderer must be used within a NestedContentRendererProvider");
19
+ }
20
+ return fn;
21
+ }
22
+ const InfoIcon = () => /* @__PURE__ */ jsx(Info, { size: 16 });
23
+ const LightbulbIcon = () => /* @__PURE__ */ jsx(Lightbulb, { size: 16 });
24
+ const MessageWarningIcon = () => /* @__PURE__ */ jsx(MessageSquareWarning, { size: 16 });
25
+ const TriangleAlertIcon = () => /* @__PURE__ */ jsx(TriangleAlert, { size: 16 });
26
+ const OctagonAlertIcon = () => /* @__PURE__ */ jsx(OctagonAlert, { size: 16 });
27
+ const ALERT_ICONS = {
28
+ note: InfoIcon,
29
+ tip: LightbulbIcon,
30
+ important: MessageWarningIcon,
31
+ warning: TriangleAlertIcon,
32
+ caution: OctagonAlertIcon
33
+ };
34
+ const AlertRenderer = ({ type }) => {
35
+ const Icon = ALERT_ICONS[type];
36
+ return /* @__PURE__ */ jsxs("div", { className: `rich-alert-header rich-alert-header-${type}`, children: [
37
+ /* @__PURE__ */ jsx("span", { className: "rich-alert-icon", children: /* @__PURE__ */ jsx(Icon, {}) }),
38
+ /* @__PURE__ */ jsx("span", { className: "rich-alert-label", children: ALERT_LABELS[type] })
39
+ ] });
40
+ };
41
+ function AlertStaticDecorator({ alertType, contentState }) {
42
+ const renderContent = useNestedContentRenderer();
43
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
44
+ /* @__PURE__ */ jsx(
45
+ RendererWrapper,
46
+ {
47
+ defaultRenderer: AlertRenderer,
48
+ props: { type: alertType },
49
+ rendererKey: "Alert"
50
+ }
51
+ ),
52
+ /* @__PURE__ */ jsx("div", { className: "rich-alert-content", children: renderContent(contentState) })
53
+ ] });
54
+ }
55
+ function extractTextContent(state) {
56
+ function walk(node) {
57
+ if (node.text) return node.text;
58
+ if (node.children) return node.children.map(walk).join("");
59
+ if (node.root) return walk(node.root);
60
+ return "";
61
+ }
62
+ return walk(state);
63
+ }
64
+ const ALERT_TYPES = ["note", "tip", "important", "warning", "caution"];
65
+ const ALERT_LABELS = {
66
+ note: "Note",
67
+ tip: "Tip",
68
+ important: "Important",
69
+ warning: "Warning",
70
+ caution: "Caution"
71
+ };
72
+ class AlertQuoteNode extends DecoratorNode {
73
+ constructor(alertType, contentState, key) {
74
+ super(key);
75
+ __publicField(this, "__alertType");
76
+ __publicField(this, "__contentState");
77
+ this.__alertType = alertType;
78
+ this.__contentState = contentState || {
79
+ root: {
80
+ children: [
81
+ {
82
+ type: "paragraph",
83
+ children: [],
84
+ direction: null,
85
+ format: "",
86
+ indent: 0,
87
+ textFormat: 0,
88
+ textStyle: "",
89
+ version: 1
90
+ }
91
+ ],
92
+ direction: null,
93
+ format: "",
94
+ indent: 0,
95
+ type: "root",
96
+ version: 1
97
+ }
98
+ };
99
+ }
100
+ static getType() {
101
+ return "alert-quote";
102
+ }
103
+ static clone(node) {
104
+ return new AlertQuoteNode(node.__alertType, node.__contentState, node.__key);
105
+ }
106
+ createDOM(_config) {
107
+ const div = document.createElement("div");
108
+ div.className = `${semanticClassNames.alert} ${sharedStyles.alert} rich-alert-${this.__alertType}`;
109
+ return div;
110
+ }
111
+ updateDOM(prevNode, dom) {
112
+ if (prevNode.__alertType !== this.__alertType) {
113
+ dom.className = `${semanticClassNames.alert} ${sharedStyles.alert} rich-alert-${this.__alertType}`;
114
+ }
115
+ return false;
116
+ }
117
+ isInline() {
118
+ return false;
119
+ }
120
+ getAlertType() {
121
+ return this.__alertType;
122
+ }
123
+ setAlertType(alertType) {
124
+ const writable = this.getWritable();
125
+ writable.__alertType = alertType;
126
+ }
127
+ getContentState() {
128
+ return this.getLatest().__contentState;
129
+ }
130
+ setContentState(state) {
131
+ const writable = this.getWritable();
132
+ writable.__contentState = state;
133
+ }
134
+ getTextContent() {
135
+ return extractTextContent(this.__contentState);
136
+ }
137
+ static importJSON(serializedNode) {
138
+ return new AlertQuoteNode(serializedNode.alertType, serializedNode.content);
139
+ }
140
+ exportJSON() {
141
+ return {
142
+ ...super.exportJSON(),
143
+ type: "alert-quote",
144
+ alertType: this.__alertType,
145
+ content: this.__contentState,
146
+ version: 1
147
+ };
148
+ }
149
+ decorate(_editor, _config) {
150
+ return createElement(AlertStaticDecorator, {
151
+ alertType: this.__alertType,
152
+ contentState: this.__contentState
153
+ });
154
+ }
155
+ }
156
+ function $isAlertQuoteNode(node) {
157
+ return node instanceof AlertQuoteNode;
158
+ }
159
+ class FootnoteNode extends DecoratorNode {
160
+ constructor(identifier, key) {
161
+ super(key);
162
+ __publicField(this, "__identifier");
163
+ this.__identifier = identifier;
164
+ }
165
+ static getType() {
166
+ return "footnote";
167
+ }
168
+ static clone(node) {
169
+ return new FootnoteNode(node.__identifier, node.__key);
170
+ }
171
+ createDOM(_config) {
172
+ const sup = document.createElement("sup");
173
+ sup.className = `${semanticClassNames.footnote} ${sharedStyles.footnote}`;
174
+ return sup;
175
+ }
176
+ updateDOM() {
177
+ return false;
178
+ }
179
+ isInline() {
180
+ return true;
181
+ }
182
+ static importJSON(serializedNode) {
183
+ return $createFootnoteNode(serializedNode.identifier);
184
+ }
185
+ exportJSON() {
186
+ return {
187
+ ...super.exportJSON(),
188
+ type: "footnote",
189
+ identifier: this.__identifier,
190
+ version: 1
191
+ };
192
+ }
193
+ getIdentifier() {
194
+ return this.getLatest().__identifier;
195
+ }
196
+ setIdentifier(identifier) {
197
+ const writable = this.getWritable();
198
+ writable.__identifier = identifier;
199
+ }
200
+ decorate(_editor, _config) {
201
+ return createRendererDecoration("Footnote", FootnoteStaticRenderer, {
202
+ identifier: this.__identifier
203
+ });
204
+ }
205
+ }
206
+ function $createFootnoteNode(identifier) {
207
+ return new FootnoteNode(identifier);
208
+ }
209
+ function ImageRenderer({
210
+ src,
211
+ altText,
212
+ width,
213
+ height,
214
+ caption,
215
+ thumbhash,
216
+ accent
217
+ }) {
218
+ const [loaded, setLoaded] = useState(false);
219
+ const [zoomed, setZoomed] = useState(false);
220
+ const handleLoad = useCallback(() => setLoaded(true), []);
221
+ const handleZoomOpen = useCallback(() => {
222
+ if (!loaded) return;
223
+ setZoomed(true);
224
+ }, [loaded]);
225
+ const handleZoomClose = useCallback(() => setZoomed(false), []);
226
+ useEffect(() => {
227
+ if (!zoomed) return;
228
+ const onKeyDown = (e) => {
229
+ if (e.key === "Escape") setZoomed(false);
230
+ };
231
+ document.addEventListener("keydown", onKeyDown);
232
+ return () => document.removeEventListener("keydown", onKeyDown);
233
+ }, [zoomed]);
234
+ useEffect(() => {
235
+ if (!zoomed) return;
236
+ const prev = document.body.style.overflow;
237
+ document.body.style.overflow = "hidden";
238
+ return () => {
239
+ document.body.style.overflow = prev;
240
+ };
241
+ }, [zoomed]);
242
+ const handleContainerKeyDown = useCallback(
243
+ (e) => {
244
+ if ((e.key === "Enter" || e.key === " ") && loaded) {
245
+ e.preventDefault();
246
+ setZoomed(true);
247
+ }
248
+ },
249
+ [loaded]
250
+ );
251
+ const placeholderUrl = useMemo(
252
+ () => thumbhash ? decodeThumbHash(thumbhash) : void 0,
253
+ [thumbhash]
254
+ );
255
+ const aspectStyle = width && height ? { aspectRatio: `${width} / ${height}`, maxWidth: "100%", width } : { maxWidth: "100%" };
256
+ return /* @__PURE__ */ jsxs("figure", { className: "rich-image", children: [
257
+ /* @__PURE__ */ jsx(
258
+ "div",
259
+ {
260
+ "aria-label": loaded ? `Zoom image: ${altText}` : void 0,
261
+ className: `rich-image-container${loaded ? " rich-image-loaded" : ""}`,
262
+ role: "button",
263
+ tabIndex: loaded ? 0 : -1,
264
+ style: {
265
+ ...aspectStyle,
266
+ backgroundColor: !loaded && !placeholderUrl ? accent : void 0,
267
+ backgroundImage: !loaded && placeholderUrl ? `url(${placeholderUrl})` : void 0,
268
+ backgroundSize: "cover",
269
+ cursor: loaded ? "zoom-in" : void 0
270
+ },
271
+ onClick: handleZoomOpen,
272
+ onKeyDown: handleContainerKeyDown,
273
+ children: /* @__PURE__ */ jsx(
274
+ "img",
275
+ {
276
+ alt: altText,
277
+ className: loaded ? "rich-image-visible" : "rich-image-hidden",
278
+ height,
279
+ loading: "lazy",
280
+ src,
281
+ style: { maxWidth: "100%", height: "auto" },
282
+ width,
283
+ onLoad: handleLoad
284
+ }
285
+ )
286
+ }
287
+ ),
288
+ caption && /* @__PURE__ */ jsx("figcaption", { children: caption }),
289
+ zoomed && /* @__PURE__ */ jsx(
290
+ "div",
291
+ {
292
+ "aria-label": `Zoomed image: ${altText}`,
293
+ "aria-modal": "true",
294
+ className: "rich-image-zoom-overlay",
295
+ role: "dialog",
296
+ tabIndex: 0,
297
+ onClick: handleZoomClose,
298
+ children: /* @__PURE__ */ jsx("img", { alt: altText, className: "rich-image-zoom-img", src })
299
+ }
300
+ )
301
+ ] });
302
+ }
303
+ const OPEN_IMAGE_UPLOAD_DIALOG_COMMAND = createCommand(
304
+ "OPEN_IMAGE_UPLOAD_DIALOG_COMMAND"
305
+ );
306
+ function sanitizeImageSrc(src) {
307
+ const trimmed = src.trim();
308
+ if (/^(?:javascript\s*:|vbscript\s*:|data\s*:(?!image\/))/i.test(trimmed)) {
309
+ return "";
310
+ }
311
+ return trimmed;
312
+ }
313
+ function sanitizeColor(value) {
314
+ if (!value) return void 0;
315
+ const trimmed = value.trim();
316
+ if (/^#[\da-f]{3,8}$/i.test(trimmed)) return trimmed;
317
+ if (/^(?:rgb|hsl)a?\([^)]+\)$/i.test(trimmed)) return trimmed;
318
+ if (/^[a-z]{3,20}$/i.test(trimmed)) return trimmed;
319
+ return void 0;
320
+ }
321
+ const _ImageNode = class _ImageNode extends DecoratorNode {
322
+ constructor(payload, key) {
323
+ super(key);
324
+ __publicField(this, "__src");
325
+ __publicField(this, "__altText");
326
+ __publicField(this, "__width");
327
+ __publicField(this, "__height");
328
+ __publicField(this, "__caption");
329
+ __publicField(this, "__thumbhash");
330
+ __publicField(this, "__accent");
331
+ this.__src = sanitizeImageSrc(payload.src);
332
+ this.__altText = payload.altText;
333
+ this.__width = payload.width;
334
+ this.__height = payload.height;
335
+ this.__caption = payload.caption;
336
+ this.__thumbhash = payload.thumbhash;
337
+ this.__accent = sanitizeColor(payload.accent);
338
+ }
339
+ static getType() {
340
+ return "image";
341
+ }
342
+ static clone(node) {
343
+ return new _ImageNode(
344
+ {
345
+ src: node.__src,
346
+ altText: node.__altText,
347
+ width: node.__width,
348
+ height: node.__height,
349
+ caption: node.__caption,
350
+ thumbhash: node.__thumbhash,
351
+ accent: node.__accent
352
+ },
353
+ node.__key
354
+ );
355
+ }
356
+ createDOM(_config) {
357
+ const div = document.createElement("div");
358
+ div.className = "rich-image-wrapper";
359
+ return div;
360
+ }
361
+ updateDOM() {
362
+ return false;
363
+ }
364
+ isInline() {
365
+ return false;
366
+ }
367
+ static importJSON(serializedNode) {
368
+ return $createImageNode({
369
+ src: serializedNode.src,
370
+ altText: serializedNode.altText,
371
+ width: serializedNode.width,
372
+ height: serializedNode.height,
373
+ caption: serializedNode.caption,
374
+ thumbhash: serializedNode.thumbhash,
375
+ accent: serializedNode.accent
376
+ });
377
+ }
378
+ exportJSON() {
379
+ return {
380
+ ...super.exportJSON(),
381
+ type: "image",
382
+ src: this.__src,
383
+ altText: this.__altText,
384
+ width: this.__width,
385
+ height: this.__height,
386
+ caption: this.__caption,
387
+ thumbhash: this.__thumbhash,
388
+ accent: this.__accent,
389
+ version: 1
390
+ };
391
+ }
392
+ setSrc(src) {
393
+ const writable = this.getWritable();
394
+ writable.__src = sanitizeImageSrc(src);
395
+ }
396
+ setAltText(altText) {
397
+ const writable = this.getWritable();
398
+ writable.__altText = altText;
399
+ }
400
+ setCaption(caption) {
401
+ const writable = this.getWritable();
402
+ writable.__caption = caption;
403
+ }
404
+ setDimensions(width, height) {
405
+ const writable = this.getWritable();
406
+ writable.__width = width;
407
+ writable.__height = height;
408
+ }
409
+ setThumbhash(thumbhash) {
410
+ const writable = this.getWritable();
411
+ writable.__thumbhash = thumbhash;
412
+ }
413
+ setAccent(accent) {
414
+ const writable = this.getWritable();
415
+ writable.__accent = sanitizeColor(accent);
416
+ }
417
+ getSrc() {
418
+ return this.__src;
419
+ }
420
+ getAltText() {
421
+ return this.__altText;
422
+ }
423
+ getCaption() {
424
+ return this.__caption;
425
+ }
426
+ getWidth() {
427
+ return this.__width;
428
+ }
429
+ getHeight() {
430
+ return this.__height;
431
+ }
432
+ getThumbhash() {
433
+ return this.__thumbhash;
434
+ }
435
+ getAccent() {
436
+ return this.__accent;
437
+ }
438
+ decorate(_editor, _config) {
439
+ return createRendererDecoration("Image", ImageRenderer, {
440
+ src: this.__src,
441
+ altText: this.__altText,
442
+ width: this.__width,
443
+ height: this.__height,
444
+ caption: this.__caption,
445
+ thumbhash: this.__thumbhash,
446
+ accent: this.__accent
447
+ });
448
+ }
449
+ };
450
+ __publicField(_ImageNode, "commandItems", [
451
+ {
452
+ title: "Image",
453
+ icon: createElement(ImageIcon, { size: 20 }),
454
+ description: "Upload or embed an image",
455
+ keywords: ["image", "picture", "photo"],
456
+ section: "MEDIA",
457
+ placement: ["slash", "toolbar"],
458
+ group: "insert",
459
+ onSelect: (editor) => {
460
+ const opened = editor.dispatchCommand(OPEN_IMAGE_UPLOAD_DIALOG_COMMAND, void 0);
461
+ if (opened) return;
462
+ editor.update(() => {
463
+ $insertNodes([$createImageNode({ src: "", altText: "" })]);
464
+ });
465
+ }
466
+ }
467
+ ]);
468
+ let ImageNode = _ImageNode;
469
+ function $createImageNode(payload) {
470
+ return new ImageNode(payload);
471
+ }
472
+ function $isImageNode(node) {
473
+ return node instanceof ImageNode;
474
+ }
475
+ const _KaTeXBlockNode = class _KaTeXBlockNode extends DecoratorNode {
476
+ constructor(equation, key) {
477
+ super(key);
478
+ __publicField(this, "__equation");
479
+ this.__equation = equation;
480
+ }
481
+ static getType() {
482
+ return "katex-block";
483
+ }
484
+ static clone(node) {
485
+ return new _KaTeXBlockNode(node.__equation, node.__key);
486
+ }
487
+ createDOM(_config) {
488
+ const div = document.createElement("div");
489
+ div.className = "rich-katex-block-wrapper";
490
+ return div;
491
+ }
492
+ updateDOM() {
493
+ return false;
494
+ }
495
+ isInline() {
496
+ return false;
497
+ }
498
+ static importJSON(serializedNode) {
499
+ return $createKaTeXBlockNode(serializedNode.equation);
500
+ }
501
+ exportJSON() {
502
+ return {
503
+ ...super.exportJSON(),
504
+ type: "katex-block",
505
+ equation: this.__equation,
506
+ version: 1
507
+ };
508
+ }
509
+ getEquation() {
510
+ return this.__equation;
511
+ }
512
+ setEquation(equation) {
513
+ const writable = this.getWritable();
514
+ writable.__equation = equation;
515
+ }
516
+ decorate(_editor, _config) {
517
+ return createRendererDecoration("KaTeX", KaTeXRenderer, {
518
+ equation: this.__equation,
519
+ displayMode: true
520
+ });
521
+ }
522
+ };
523
+ __publicField(_KaTeXBlockNode, "slashMenuItems", [
524
+ {
525
+ title: "Math Equation",
526
+ icon: createElement(Sigma, { size: 20 }),
527
+ description: "KaTeX block formula",
528
+ keywords: ["math", "equation", "latex", "katex"],
529
+ section: "ADVANCED",
530
+ onSelect: (editor) => {
531
+ editor.update(() => {
532
+ $insertNodes([$createKaTeXBlockNode("")]);
533
+ });
534
+ }
535
+ }
536
+ ]);
537
+ let KaTeXBlockNode = _KaTeXBlockNode;
538
+ function $createKaTeXBlockNode(equation) {
539
+ return new KaTeXBlockNode(equation);
540
+ }
541
+ function $isKaTeXBlockNode(node) {
542
+ return node instanceof KaTeXBlockNode;
543
+ }
544
+ class KaTeXInlineNode extends DecoratorNode {
545
+ constructor(equation, key) {
546
+ super(key);
547
+ __publicField(this, "__equation");
548
+ this.__equation = equation;
549
+ }
550
+ static getType() {
551
+ return "katex-inline";
552
+ }
553
+ static clone(node) {
554
+ return new KaTeXInlineNode(node.__equation, node.__key);
555
+ }
556
+ createDOM(_config) {
557
+ return document.createElement("span");
558
+ }
559
+ updateDOM() {
560
+ return false;
561
+ }
562
+ isInline() {
563
+ return true;
564
+ }
565
+ static importJSON(serializedNode) {
566
+ return $createKaTeXInlineNode(serializedNode.equation);
567
+ }
568
+ exportJSON() {
569
+ return {
570
+ ...super.exportJSON(),
571
+ type: "katex-inline",
572
+ equation: this.__equation,
573
+ version: 1
574
+ };
575
+ }
576
+ getEquation() {
577
+ return this.__equation;
578
+ }
579
+ setEquation(equation) {
580
+ const writable = this.getWritable();
581
+ writable.__equation = equation;
582
+ }
583
+ decorate(_editor, _config) {
584
+ return createRendererDecoration("KaTeX", KaTeXRenderer, {
585
+ equation: this.__equation,
586
+ displayMode: false
587
+ });
588
+ }
589
+ }
590
+ function $createKaTeXInlineNode(equation) {
591
+ return new KaTeXInlineNode(equation);
592
+ }
593
+ function $isKaTeXInlineNode(node) {
594
+ return node instanceof KaTeXInlineNode;
595
+ }
596
+ function MentionRenderer({ handle, displayName }) {
597
+ const normalizedHandle = handle.replace(/^@+/, "");
598
+ const label = displayName || normalizedHandle;
599
+ return /* @__PURE__ */ jsx("span", { className: "rich-mention rich-mention-plain", children: /* @__PURE__ */ jsxs("span", { className: "rich-mention-handle", children: [
600
+ "@",
601
+ label
602
+ ] }) });
603
+ }
604
+ const _MentionNode = class _MentionNode extends DecoratorNode {
605
+ constructor(platform, handle, displayName, key) {
606
+ super(key);
607
+ __publicField(this, "__platform");
608
+ __publicField(this, "__handle");
609
+ __publicField(this, "__displayName");
610
+ this.__platform = platform;
611
+ this.__handle = handle;
612
+ this.__displayName = displayName;
613
+ }
614
+ static getType() {
615
+ return "mention";
616
+ }
617
+ static clone(node) {
618
+ return new _MentionNode(
619
+ node.__platform,
620
+ node.__handle,
621
+ node.__displayName,
622
+ node.__key
623
+ );
624
+ }
625
+ createDOM(_config) {
626
+ const el = document.createElement("span");
627
+ el.style.display = "inline-flex";
628
+ el.style.alignItems = "center";
629
+ el.style.height = "1lh";
630
+ return el;
631
+ }
632
+ updateDOM() {
633
+ return false;
634
+ }
635
+ isInline() {
636
+ return true;
637
+ }
638
+ getPlatform() {
639
+ return this.getLatest().__platform;
640
+ }
641
+ getHandle() {
642
+ return this.getLatest().__handle;
643
+ }
644
+ getDisplayName() {
645
+ return this.getLatest().__displayName;
646
+ }
647
+ static importJSON(serializedNode) {
648
+ return $createMentionNode(
649
+ serializedNode.platform,
650
+ serializedNode.handle,
651
+ serializedNode.displayName
652
+ );
653
+ }
654
+ exportJSON() {
655
+ return {
656
+ ...super.exportJSON(),
657
+ type: "mention",
658
+ platform: this.__platform,
659
+ handle: this.__handle,
660
+ ...this.__displayName ? { displayName: this.__displayName } : {},
661
+ version: 1
662
+ };
663
+ }
664
+ decorate(_editor, _config) {
665
+ return createRendererDecoration("Mention", MentionRenderer, {
666
+ platform: this.__platform,
667
+ handle: this.__handle,
668
+ displayName: this.__displayName
669
+ });
670
+ }
671
+ };
672
+ __publicField(_MentionNode, "slashMenuItems", [
673
+ {
674
+ title: "Mention",
675
+ icon: createElement(
676
+ "span",
677
+ { style: { fontSize: 16, fontWeight: 700 } },
678
+ "@"
679
+ ),
680
+ description: "Mention a social account",
681
+ keywords: ["mention", "at", "@", "github", "twitter"],
682
+ section: "INLINE",
683
+ onSelect: (editor) => {
684
+ editor.update(() => {
685
+ const selection = $getSelection();
686
+ if ($isRangeSelection(selection)) {
687
+ selection.insertText("@");
688
+ }
689
+ });
690
+ }
691
+ }
692
+ ]);
693
+ let MentionNode = _MentionNode;
694
+ function $createMentionNode(platform, handle, displayName) {
695
+ return new MentionNode(platform, handle, displayName);
696
+ }
697
+ function $isMentionNode(node) {
698
+ return node instanceof MentionNode;
699
+ }
700
+ function MermaidRenderer({ content }) {
701
+ return /* @__PURE__ */ jsx("div", { className: "rich-mermaid-block", children: /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: content }) }) });
702
+ }
703
+ const _MermaidNode = class _MermaidNode extends DecoratorNode {
704
+ constructor(diagram, key) {
705
+ super(key);
706
+ __publicField(this, "__diagram");
707
+ this.__diagram = diagram;
708
+ }
709
+ static getType() {
710
+ return "mermaid";
711
+ }
712
+ static clone(node) {
713
+ return new _MermaidNode(node.__diagram, node.__key);
714
+ }
715
+ createDOM(_config) {
716
+ const div = document.createElement("div");
717
+ div.className = "rich-mermaid-wrapper";
718
+ return div;
719
+ }
720
+ updateDOM() {
721
+ return false;
722
+ }
723
+ isInline() {
724
+ return false;
725
+ }
726
+ static importJSON(serializedNode) {
727
+ return $createMermaidNode(serializedNode.diagram);
728
+ }
729
+ exportJSON() {
730
+ return {
731
+ ...super.exportJSON(),
732
+ type: "mermaid",
733
+ diagram: this.__diagram,
734
+ version: 1
735
+ };
736
+ }
737
+ getDiagram() {
738
+ return this.__diagram;
739
+ }
740
+ setDiagram(diagram) {
741
+ const writable = this.getWritable();
742
+ writable.__diagram = diagram;
743
+ }
744
+ decorate(editor, _config) {
745
+ const nodeKey = this.__key;
746
+ return createRendererDecoration("Mermaid", MermaidRenderer, {
747
+ content: this.__diagram,
748
+ onContentChange: (newDiagram) => {
749
+ editor.update(() => {
750
+ const node = $getNodeByKey(nodeKey);
751
+ if (node) {
752
+ node.setDiagram(newDiagram);
753
+ }
754
+ });
755
+ }
756
+ });
757
+ }
758
+ };
759
+ __publicField(_MermaidNode, "commandItems", [
760
+ {
761
+ title: "Mermaid Diagram",
762
+ icon: createElement(Workflow, { size: 20 }),
763
+ description: "Flowchart, sequence diagram",
764
+ keywords: ["mermaid", "diagram", "chart", "flowchart"],
765
+ section: "MEDIA",
766
+ placement: ["slash", "toolbar"],
767
+ group: "insert",
768
+ onSelect: (editor) => {
769
+ editor.update(() => {
770
+ $insertNodes([
771
+ $createMermaidNode("graph TD\n A[Start] --> B[End]")
772
+ ]);
773
+ });
774
+ }
775
+ }
776
+ ]);
777
+ let MermaidNode = _MermaidNode;
778
+ function $createMermaidNode(diagram) {
779
+ return new MermaidNode(diagram);
780
+ }
781
+ function $isMermaidNode(node) {
782
+ return node instanceof MermaidNode;
783
+ }
784
+ class SpoilerNode extends ElementNode {
785
+ static getType() {
786
+ return "spoiler";
787
+ }
788
+ static clone(node) {
789
+ return new SpoilerNode(node.__key);
790
+ }
791
+ constructor(key) {
792
+ super(key);
793
+ }
794
+ createDOM(_config) {
795
+ const span = document.createElement("span");
796
+ span.className = `${semanticClassNames.spoiler} ${sharedStyles.spoiler}`;
797
+ span.setAttribute("role", "button");
798
+ span.setAttribute("tabindex", "0");
799
+ span.setAttribute("aria-label", "Spoiler (click to reveal)");
800
+ const toggle = () => {
801
+ if (span.isContentEditable) return;
802
+ span.classList.toggle(semanticClassNames.spoilerRevealed);
803
+ const revealed = span.classList.toggle(sharedStyles.spoilerRevealed);
804
+ span.setAttribute(
805
+ "aria-label",
806
+ revealed ? "Spoiler (revealed)" : "Spoiler (click to reveal)"
807
+ );
808
+ };
809
+ span.addEventListener("click", toggle);
810
+ span.addEventListener("keydown", (e) => {
811
+ if (e.key === "Enter" || e.key === " ") {
812
+ e.preventDefault();
813
+ toggle();
814
+ }
815
+ });
816
+ return span;
817
+ }
818
+ updateDOM() {
819
+ return false;
820
+ }
821
+ static importJSON(_serializedNode) {
822
+ return $createSpoilerNode();
823
+ }
824
+ exportJSON() {
825
+ return {
826
+ ...super.exportJSON(),
827
+ type: "spoiler",
828
+ version: 1
829
+ };
830
+ }
831
+ canInsertTextBefore() {
832
+ return true;
833
+ }
834
+ canInsertTextAfter() {
835
+ return true;
836
+ }
837
+ isInline() {
838
+ return true;
839
+ }
840
+ }
841
+ function $createSpoilerNode() {
842
+ return new SpoilerNode();
843
+ }
844
+ function stringToHue(str) {
845
+ let hash = 0;
846
+ for (let i = 0; i < str.length; i++) {
847
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
848
+ }
849
+ const hue = hash % 360;
850
+ return hue < 0 ? hue + 360 : hue;
851
+ }
852
+ function getTagBgColor(text) {
853
+ const hue = stringToHue(text);
854
+ const sat = 70 + hue % 21;
855
+ const light = 40 + hue % 31;
856
+ const bgSat = sat > 30 ? sat - 30 : 0;
857
+ const bgLight = light < 80 ? light + 20 : 100;
858
+ return `hsla(${hue}, ${bgSat}%, ${bgLight}%, 0.7)`;
859
+ }
860
+ const tagClassName = `${semanticClassNames.tag} ${sharedStyles.tag}`;
861
+ const _TagNode = class _TagNode extends TextNode {
862
+ static getType() {
863
+ return "tag";
864
+ }
865
+ static clone(node) {
866
+ return new _TagNode(node.__text, node.__key);
867
+ }
868
+ static importDOM() {
869
+ return {
870
+ span: () => ({
871
+ conversion: (domNode) => {
872
+ if (!(domNode instanceof HTMLElement)) return null;
873
+ if (!domNode.classList.contains(semanticClassNames.tag)) return null;
874
+ return {
875
+ node: $createTagNode(domNode.textContent ?? "")
876
+ };
877
+ },
878
+ priority: 2
879
+ })
880
+ };
881
+ }
882
+ constructor(text, key) {
883
+ super(text, key);
884
+ }
885
+ createDOM(config) {
886
+ const element = super.createDOM(config);
887
+ element.classList.add(semanticClassNames.tag, sharedStyles.tag);
888
+ element.style.backgroundColor = getTagBgColor(this.getTextContent());
889
+ return element;
890
+ }
891
+ updateDOM(prevNode, dom, config) {
892
+ const updated = super.updateDOM(prevNode, dom, config);
893
+ dom.classList.add(semanticClassNames.tag, sharedStyles.tag);
894
+ if (prevNode.__text !== this.__text) {
895
+ dom.style.backgroundColor = getTagBgColor(this.__text);
896
+ }
897
+ return updated;
898
+ }
899
+ exportDOM(_editor) {
900
+ const element = document.createElement("span");
901
+ element.className = tagClassName;
902
+ element.style.backgroundColor = getTagBgColor(this.getTextContent());
903
+ element.textContent = this.getTextContent();
904
+ return { element };
905
+ }
906
+ getText() {
907
+ return this.getTextContent();
908
+ }
909
+ canInsertTextBefore() {
910
+ return false;
911
+ }
912
+ canInsertTextAfter() {
913
+ return false;
914
+ }
915
+ isTextEntity() {
916
+ return true;
917
+ }
918
+ static importJSON(serializedNode) {
919
+ const node = $createTagNode(serializedNode.text ?? "");
920
+ node.setFormat(serializedNode.format ?? 0);
921
+ node.setDetail(serializedNode.detail ?? 0);
922
+ node.setMode(serializedNode.mode ?? "normal");
923
+ node.setStyle(serializedNode.style ?? "");
924
+ return node;
925
+ }
926
+ exportJSON() {
927
+ return {
928
+ ...super.exportJSON(),
929
+ type: "tag",
930
+ version: 1
931
+ };
932
+ }
933
+ };
934
+ __publicField(_TagNode, "commandItems", [
935
+ {
936
+ title: "Tag",
937
+ icon: createElement(Tag, { size: 20 }),
938
+ description: "Insert a tag",
939
+ keywords: ["tag", "label", "badge"],
940
+ section: "INLINE",
941
+ placement: ["slash", "toolbar"],
942
+ group: "insert",
943
+ onSelect: (editor, queryString) => {
944
+ editor.update(() => {
945
+ $insertNodes([$createTagNode(queryString || "tag")]);
946
+ });
947
+ }
948
+ }
949
+ ]);
950
+ let TagNode = _TagNode;
951
+ function $createTagNode(text) {
952
+ return new TagNode(text);
953
+ }
954
+ function $isTagNode(node) {
955
+ return node instanceof TagNode;
956
+ }
957
+ const shared = (key) => `${semanticClassNames[key]} ${sharedStyles[key]}`;
958
+ const editorTheme = {
959
+ text: {
960
+ bold: shared("textBold"),
961
+ italic: shared("textItalic"),
962
+ underline: shared("textUnderline"),
963
+ strikethrough: shared("textStrikethrough"),
964
+ superscript: shared("textSuperscript"),
965
+ subscript: shared("textSubscript"),
966
+ code: shared("textCode"),
967
+ highlight: shared("textHighlight")
968
+ },
969
+ heading: {
970
+ h1: shared("headingH1"),
971
+ h2: shared("headingH2"),
972
+ h3: shared("headingH3"),
973
+ h4: shared("headingH4"),
974
+ h5: shared("headingH5"),
975
+ h6: shared("headingH6")
976
+ },
977
+ list: {
978
+ ol: shared("listOl"),
979
+ ul: shared("listUl"),
980
+ listitem: shared("listItem"),
981
+ listitemChecked: shared("listItemChecked"),
982
+ listitemUnchecked: shared("listItemUnchecked"),
983
+ checklist: shared("checklist"),
984
+ nested: {
985
+ listitem: shared("listNestedItem")
986
+ }
987
+ },
988
+ quote: shared("quote"),
989
+ link: shared("link"),
990
+ paragraph: shared("paragraph"),
991
+ code: "rich-code-block",
992
+ table: shared("table"),
993
+ tableCell: shared("tableCell"),
994
+ tableCellHeader: shared("tableCellHeader"),
995
+ tableScrollableWrapper: shared("tableScrollableWrapper"),
996
+ /** Used by @lexical/extension HorizontalRuleNode */
997
+ hr: shared("hr")
998
+ };
999
+ export {
1000
+ $createImageNode as $,
1001
+ ALERT_LABELS as A,
1002
+ FootnoteNode as F,
1003
+ ImageNode as I,
1004
+ KaTeXBlockNode as K,
1005
+ MentionNode as M,
1006
+ NestedContentRendererProvider as N,
1007
+ OPEN_IMAGE_UPLOAD_DIALOG_COMMAND as O,
1008
+ SpoilerNode as S,
1009
+ TagNode as T,
1010
+ $createMentionNode as a,
1011
+ $createMermaidNode as b,
1012
+ $createTagNode as c,
1013
+ $isImageNode as d,
1014
+ $isKaTeXBlockNode as e,
1015
+ $isKaTeXInlineNode as f,
1016
+ $isMentionNode as g,
1017
+ $isMermaidNode as h,
1018
+ $isTagNode as i,
1019
+ ALERT_TYPES as j,
1020
+ KaTeXInlineNode as k,
1021
+ MermaidNode as l,
1022
+ getTagBgColor as m,
1023
+ editorTheme as n,
1024
+ extractTextContent as o,
1025
+ useOptionalNestedContentRenderer as p,
1026
+ $isAlertQuoteNode as q,
1027
+ AlertRenderer as r,
1028
+ AlertQuoteNode as s,
1029
+ $createKaTeXInlineNode as t,
1030
+ useNestedContentRenderer as u,
1031
+ $createKaTeXBlockNode as v,
1032
+ $createFootnoteNode as w,
1033
+ $createSpoilerNode as x
1034
+ };