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