@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.
- package/dist/AlertQuoteEditNode-C55sxsR3.js +267 -0
- package/dist/KaTeXRenderer-CQQT3BMw.js +215 -0
- package/dist/LinkCardRenderer-CigqFwCv.js +45 -0
- package/dist/MermaidPlugin-BrOr-wQi.js +67 -0
- package/dist/RubyRenderer-jOkydJHg.js +15 -0
- package/dist/SubmitShortcutPlugin-DhyVFzoj.js +2186 -0
- package/dist/commands-entry.mjs +54 -74
- package/dist/components/decorators/PollEditDecorator.d.ts +13 -0
- package/dist/components/decorators/PollEditDecorator.d.ts.map +1 -0
- package/dist/components/renderers/PollRenderer.d.ts +3 -0
- package/dist/components/renderers/PollRenderer.d.ts.map +1 -0
- package/dist/config-B5BuLljq.js +1633 -0
- package/dist/config-edit.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/context/PollDataContext.d.ts +11 -0
- package/dist/context/PollDataContext.d.ts.map +1 -0
- package/dist/extractPolls-DO31LNrp.js +116 -0
- package/dist/grid.css-CJCkLTZc.js +44 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +121 -180
- package/dist/katex.css-CIOEOXyd.js +145 -0
- package/dist/node-registry-Dz5OTkh4.js +946 -0
- package/dist/nodes/PollEditNode.d.ts +14 -0
- package/dist/nodes/PollEditNode.d.ts.map +1 -0
- package/dist/nodes/PollNode.d.ts +52 -0
- package/dist/nodes/PollNode.d.ts.map +1 -0
- package/dist/nodes-entry.d.ts +3 -0
- package/dist/nodes-entry.d.ts.map +1 -1
- package/dist/nodes-entry.mjs +5 -50
- package/dist/normalizeSerializedEditorState-B-1wmGzd.js +78 -0
- package/dist/plugins-entry.mjs +3 -28
- package/dist/renderers-entry.mjs +41 -61
- package/dist/rich-editor.css +2 -1
- package/dist/static-entry.d.ts +5 -0
- package/dist/static-entry.d.ts.map +1 -1
- package/dist/static-entry.mjs +16 -66
- package/dist/styles/index.d.ts +2 -0
- package/dist/styles/index.d.ts.map +1 -1
- package/dist/styles/poll-edit.css.d.ts +35 -0
- package/dist/styles/poll-edit.css.d.ts.map +1 -0
- package/dist/styles/poll.css.d.ts +43 -0
- package/dist/styles/poll.css.d.ts.map +1 -0
- package/dist/styles-entry.mjs +3 -21
- package/dist/theme-B5B2EOWM.js +1099 -0
- package/dist/types/poll.d.ts +36 -0
- package/dist/types/poll.d.ts.map +1 -0
- package/dist/types/renderer-config.d.ts +3 -0
- package/dist/types/renderer-config.d.ts.map +1 -1
- package/dist/utils/extractPolls.d.ts +4 -0
- package/dist/utils/extractPolls.d.ts.map +1 -0
- package/package.json +30 -30
- package/dist/AlertQuoteEditNode-sPNf3_7P.js +0 -293
- package/dist/KaTeXRenderer-CQyQzNTJ.js +0 -218
- package/dist/LinkCardRenderer-QmkOlyXb.js +0 -36
- package/dist/MermaidPlugin-DKuGUcCG.js +0 -101
- package/dist/PresentDialogContext-DRroMIoK.js +0 -71
- package/dist/RubyRenderer-CJQmODir.js +0 -14
- package/dist/SubmitShortcutPlugin-D9uKYHda.js +0 -2427
- package/dist/config-Dl3ZkytB.js +0 -1362
- package/dist/grid.css-Md5-Cfx_.js +0 -11
- package/dist/katex.css-Csc-7N7u.js +0 -28
- package/dist/node-registry-CovhHUB6.js +0 -824
- package/dist/normalizeSerializedEditorState-k5G4xSi9.js +0 -85
- package/dist/theme-lEwScxEX.js +0 -1113
package/dist/theme-lEwScxEX.js
DELETED
|
@@ -1,1113 +0,0 @@
|
|
|
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, getRegisteredNode, $getEditor, $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-CQyQzNTJ.js";
|
|
8
|
-
import { OctagonAlert, TriangleAlert, MessageSquareWarning, Lightbulb, Info, ImageIcon, Sigma, Workflow, Tag } from "lucide-react";
|
|
9
|
-
import { s as semanticClassNames, d as sharedStyles } from "./katex.css-Csc-7N7u.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 DEFAULT_KATEX_EQUATION = "x^2 + y^2 = z^2";
|
|
476
|
-
function resolveKaTeXEquation(equation, options) {
|
|
477
|
-
if (options?.autoOpenOnMount && !equation.trim()) {
|
|
478
|
-
return DEFAULT_KATEX_EQUATION;
|
|
479
|
-
}
|
|
480
|
-
return equation;
|
|
481
|
-
}
|
|
482
|
-
function isMissingActiveEditorError(error) {
|
|
483
|
-
return error instanceof Error && error.message.includes("Unable to find an active editor");
|
|
484
|
-
}
|
|
485
|
-
function getRegisteredNodeKlass(nodeType, fallbackKlass) {
|
|
486
|
-
try {
|
|
487
|
-
const registeredNode = getRegisteredNode($getEditor(), nodeType);
|
|
488
|
-
const registeredKlass = registeredNode?.klass;
|
|
489
|
-
if (registeredKlass && (registeredKlass === fallbackKlass || registeredKlass.prototype instanceof fallbackKlass)) {
|
|
490
|
-
return registeredKlass;
|
|
491
|
-
}
|
|
492
|
-
} catch (error) {
|
|
493
|
-
if (!isMissingActiveEditorError(error)) {
|
|
494
|
-
throw error;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
return fallbackKlass;
|
|
498
|
-
}
|
|
499
|
-
const _KaTeXBlockNode = class _KaTeXBlockNode extends DecoratorNode {
|
|
500
|
-
constructor(equation, key, autoOpenOnMount = false) {
|
|
501
|
-
super(key);
|
|
502
|
-
__publicField(this, "__equation");
|
|
503
|
-
__publicField(this, "__autoOpenOnMount");
|
|
504
|
-
this.__equation = equation;
|
|
505
|
-
this.__autoOpenOnMount = autoOpenOnMount;
|
|
506
|
-
}
|
|
507
|
-
static getType() {
|
|
508
|
-
return "katex-block";
|
|
509
|
-
}
|
|
510
|
-
static clone(node) {
|
|
511
|
-
return new _KaTeXBlockNode(
|
|
512
|
-
node.__equation,
|
|
513
|
-
node.__key,
|
|
514
|
-
node.__autoOpenOnMount
|
|
515
|
-
);
|
|
516
|
-
}
|
|
517
|
-
createDOM(_config) {
|
|
518
|
-
const div = document.createElement("div");
|
|
519
|
-
div.className = "rich-katex-block-wrapper";
|
|
520
|
-
return div;
|
|
521
|
-
}
|
|
522
|
-
updateDOM() {
|
|
523
|
-
return false;
|
|
524
|
-
}
|
|
525
|
-
isInline() {
|
|
526
|
-
return false;
|
|
527
|
-
}
|
|
528
|
-
static importJSON(serializedNode) {
|
|
529
|
-
return $createKaTeXBlockNode(serializedNode.equation);
|
|
530
|
-
}
|
|
531
|
-
exportJSON() {
|
|
532
|
-
return {
|
|
533
|
-
...super.exportJSON(),
|
|
534
|
-
type: "katex-block",
|
|
535
|
-
equation: this.__equation,
|
|
536
|
-
version: 1
|
|
537
|
-
};
|
|
538
|
-
}
|
|
539
|
-
getEquation() {
|
|
540
|
-
return this.__equation;
|
|
541
|
-
}
|
|
542
|
-
setEquation(equation) {
|
|
543
|
-
const writable = this.getWritable();
|
|
544
|
-
writable.__equation = equation;
|
|
545
|
-
}
|
|
546
|
-
getShouldAutoOpenOnMount() {
|
|
547
|
-
return this.getLatest().__autoOpenOnMount;
|
|
548
|
-
}
|
|
549
|
-
setShouldAutoOpenOnMount(autoOpenOnMount) {
|
|
550
|
-
const writable = this.getWritable();
|
|
551
|
-
writable.__autoOpenOnMount = autoOpenOnMount;
|
|
552
|
-
}
|
|
553
|
-
decorate(_editor, _config) {
|
|
554
|
-
return createRendererDecoration("KaTeX", KaTeXRenderer, {
|
|
555
|
-
equation: this.__equation,
|
|
556
|
-
displayMode: true
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
};
|
|
560
|
-
__publicField(_KaTeXBlockNode, "slashMenuItems", [
|
|
561
|
-
{
|
|
562
|
-
title: "Math Equation",
|
|
563
|
-
icon: createElement(Sigma, { size: 20 }),
|
|
564
|
-
description: "KaTeX block formula",
|
|
565
|
-
keywords: ["math", "equation", "latex", "katex"],
|
|
566
|
-
section: "ADVANCED",
|
|
567
|
-
onSelect: (editor) => {
|
|
568
|
-
editor.update(() => {
|
|
569
|
-
$insertNodes([
|
|
570
|
-
$createKaTeXBlockNode("", { autoOpenOnMount: true })
|
|
571
|
-
]);
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
]);
|
|
576
|
-
let KaTeXBlockNode = _KaTeXBlockNode;
|
|
577
|
-
function $createKaTeXBlockNode(equation, options) {
|
|
578
|
-
const NodeKlass = getRegisteredNodeKlass(
|
|
579
|
-
KaTeXBlockNode.getType(),
|
|
580
|
-
KaTeXBlockNode
|
|
581
|
-
);
|
|
582
|
-
const node = new NodeKlass(resolveKaTeXEquation(equation, options));
|
|
583
|
-
if (options?.autoOpenOnMount) {
|
|
584
|
-
node.setShouldAutoOpenOnMount(true);
|
|
585
|
-
}
|
|
586
|
-
return node;
|
|
587
|
-
}
|
|
588
|
-
function $isKaTeXBlockNode(node) {
|
|
589
|
-
return node instanceof KaTeXBlockNode;
|
|
590
|
-
}
|
|
591
|
-
class KaTeXInlineNode extends DecoratorNode {
|
|
592
|
-
constructor(equation, key, autoOpenOnMount = false, color = null) {
|
|
593
|
-
super(key);
|
|
594
|
-
__publicField(this, "__equation");
|
|
595
|
-
__publicField(this, "__autoOpenOnMount");
|
|
596
|
-
__publicField(this, "__color");
|
|
597
|
-
this.__equation = equation;
|
|
598
|
-
this.__autoOpenOnMount = autoOpenOnMount;
|
|
599
|
-
this.__color = color;
|
|
600
|
-
}
|
|
601
|
-
static getType() {
|
|
602
|
-
return "katex-inline";
|
|
603
|
-
}
|
|
604
|
-
static clone(node) {
|
|
605
|
-
return new KaTeXInlineNode(node.__equation, node.__key, node.__autoOpenOnMount, node.__color);
|
|
606
|
-
}
|
|
607
|
-
createDOM(_config) {
|
|
608
|
-
return document.createElement("span");
|
|
609
|
-
}
|
|
610
|
-
updateDOM() {
|
|
611
|
-
return false;
|
|
612
|
-
}
|
|
613
|
-
isInline() {
|
|
614
|
-
return true;
|
|
615
|
-
}
|
|
616
|
-
static importJSON(serializedNode) {
|
|
617
|
-
const node = $createKaTeXInlineNode(serializedNode.equation);
|
|
618
|
-
if (serializedNode.color) node.setColor(serializedNode.color);
|
|
619
|
-
return node;
|
|
620
|
-
}
|
|
621
|
-
exportJSON() {
|
|
622
|
-
return {
|
|
623
|
-
...super.exportJSON(),
|
|
624
|
-
type: "katex-inline",
|
|
625
|
-
equation: this.__equation,
|
|
626
|
-
color: this.__color,
|
|
627
|
-
version: 1
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
getEquation() {
|
|
631
|
-
return this.__equation;
|
|
632
|
-
}
|
|
633
|
-
setEquation(equation) {
|
|
634
|
-
const writable = this.getWritable();
|
|
635
|
-
writable.__equation = equation;
|
|
636
|
-
}
|
|
637
|
-
getShouldAutoOpenOnMount() {
|
|
638
|
-
return this.getLatest().__autoOpenOnMount;
|
|
639
|
-
}
|
|
640
|
-
setShouldAutoOpenOnMount(autoOpenOnMount) {
|
|
641
|
-
const writable = this.getWritable();
|
|
642
|
-
writable.__autoOpenOnMount = autoOpenOnMount;
|
|
643
|
-
}
|
|
644
|
-
getColor() {
|
|
645
|
-
return this.getLatest().__color;
|
|
646
|
-
}
|
|
647
|
-
setColor(color) {
|
|
648
|
-
const writable = this.getWritable();
|
|
649
|
-
writable.__color = color;
|
|
650
|
-
}
|
|
651
|
-
decorate(_editor, _config) {
|
|
652
|
-
const decoration = createRendererDecoration("KaTeX", KaTeXRenderer, {
|
|
653
|
-
equation: this.__equation,
|
|
654
|
-
displayMode: false
|
|
655
|
-
});
|
|
656
|
-
if (!this.__color) return decoration;
|
|
657
|
-
return createElement("span", { style: { color: this.__color } }, decoration);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
function $createKaTeXInlineNode(equation, options) {
|
|
661
|
-
const NodeKlass = getRegisteredNodeKlass(KaTeXInlineNode.getType(), KaTeXInlineNode);
|
|
662
|
-
const node = new NodeKlass(resolveKaTeXEquation(equation, options));
|
|
663
|
-
if (options?.autoOpenOnMount) {
|
|
664
|
-
node.setShouldAutoOpenOnMount(true);
|
|
665
|
-
}
|
|
666
|
-
return node;
|
|
667
|
-
}
|
|
668
|
-
function $isKaTeXInlineNode(node) {
|
|
669
|
-
return node instanceof KaTeXInlineNode;
|
|
670
|
-
}
|
|
671
|
-
function MentionRenderer({ handle, displayName }) {
|
|
672
|
-
const normalizedHandle = handle.replace(/^@+/, "");
|
|
673
|
-
const label = displayName || normalizedHandle;
|
|
674
|
-
return /* @__PURE__ */ jsx("span", { className: "rich-mention rich-mention-plain", children: /* @__PURE__ */ jsxs("span", { className: "rich-mention-handle", children: [
|
|
675
|
-
"@",
|
|
676
|
-
label
|
|
677
|
-
] }) });
|
|
678
|
-
}
|
|
679
|
-
const _MentionNode = class _MentionNode extends DecoratorNode {
|
|
680
|
-
constructor(platform, handle, displayName, key) {
|
|
681
|
-
super(key);
|
|
682
|
-
__publicField(this, "__platform");
|
|
683
|
-
__publicField(this, "__handle");
|
|
684
|
-
__publicField(this, "__displayName");
|
|
685
|
-
this.__platform = platform;
|
|
686
|
-
this.__handle = handle;
|
|
687
|
-
this.__displayName = displayName;
|
|
688
|
-
}
|
|
689
|
-
static getType() {
|
|
690
|
-
return "mention";
|
|
691
|
-
}
|
|
692
|
-
static clone(node) {
|
|
693
|
-
return new _MentionNode(
|
|
694
|
-
node.__platform,
|
|
695
|
-
node.__handle,
|
|
696
|
-
node.__displayName,
|
|
697
|
-
node.__key
|
|
698
|
-
);
|
|
699
|
-
}
|
|
700
|
-
createDOM(_config) {
|
|
701
|
-
const el = document.createElement("span");
|
|
702
|
-
el.style.display = "inline-flex";
|
|
703
|
-
el.style.alignItems = "center";
|
|
704
|
-
el.style.height = "1lh";
|
|
705
|
-
return el;
|
|
706
|
-
}
|
|
707
|
-
updateDOM() {
|
|
708
|
-
return false;
|
|
709
|
-
}
|
|
710
|
-
isInline() {
|
|
711
|
-
return true;
|
|
712
|
-
}
|
|
713
|
-
getPlatform() {
|
|
714
|
-
return this.getLatest().__platform;
|
|
715
|
-
}
|
|
716
|
-
getHandle() {
|
|
717
|
-
return this.getLatest().__handle;
|
|
718
|
-
}
|
|
719
|
-
getDisplayName() {
|
|
720
|
-
return this.getLatest().__displayName;
|
|
721
|
-
}
|
|
722
|
-
static importJSON(serializedNode) {
|
|
723
|
-
return $createMentionNode(
|
|
724
|
-
serializedNode.platform,
|
|
725
|
-
serializedNode.handle,
|
|
726
|
-
serializedNode.displayName
|
|
727
|
-
);
|
|
728
|
-
}
|
|
729
|
-
exportJSON() {
|
|
730
|
-
return {
|
|
731
|
-
...super.exportJSON(),
|
|
732
|
-
type: "mention",
|
|
733
|
-
platform: this.__platform,
|
|
734
|
-
handle: this.__handle,
|
|
735
|
-
...this.__displayName ? { displayName: this.__displayName } : {},
|
|
736
|
-
version: 1
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
decorate(_editor, _config) {
|
|
740
|
-
return createRendererDecoration("Mention", MentionRenderer, {
|
|
741
|
-
platform: this.__platform,
|
|
742
|
-
handle: this.__handle,
|
|
743
|
-
displayName: this.__displayName
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
};
|
|
747
|
-
__publicField(_MentionNode, "slashMenuItems", [
|
|
748
|
-
{
|
|
749
|
-
title: "Mention",
|
|
750
|
-
icon: createElement(
|
|
751
|
-
"span",
|
|
752
|
-
{ style: { fontSize: 16, fontWeight: 700 } },
|
|
753
|
-
"@"
|
|
754
|
-
),
|
|
755
|
-
description: "Mention a social account",
|
|
756
|
-
keywords: ["mention", "at", "@", "github", "twitter"],
|
|
757
|
-
section: "INLINE",
|
|
758
|
-
onSelect: (editor) => {
|
|
759
|
-
editor.update(() => {
|
|
760
|
-
const selection = $getSelection();
|
|
761
|
-
if ($isRangeSelection(selection)) {
|
|
762
|
-
selection.insertText("@");
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
]);
|
|
768
|
-
let MentionNode = _MentionNode;
|
|
769
|
-
function $createMentionNode(platform, handle, displayName) {
|
|
770
|
-
return new MentionNode(platform, handle, displayName);
|
|
771
|
-
}
|
|
772
|
-
function $isMentionNode(node) {
|
|
773
|
-
return node instanceof MentionNode;
|
|
774
|
-
}
|
|
775
|
-
function MermaidRenderer({ content }) {
|
|
776
|
-
return /* @__PURE__ */ jsx("div", { className: "rich-mermaid-block", children: /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: content }) }) });
|
|
777
|
-
}
|
|
778
|
-
const _MermaidNode = class _MermaidNode extends DecoratorNode {
|
|
779
|
-
constructor(diagram, key) {
|
|
780
|
-
super(key);
|
|
781
|
-
__publicField(this, "__diagram");
|
|
782
|
-
this.__diagram = diagram;
|
|
783
|
-
}
|
|
784
|
-
static getType() {
|
|
785
|
-
return "mermaid";
|
|
786
|
-
}
|
|
787
|
-
static clone(node) {
|
|
788
|
-
return new _MermaidNode(node.__diagram, node.__key);
|
|
789
|
-
}
|
|
790
|
-
createDOM(_config) {
|
|
791
|
-
const div = document.createElement("div");
|
|
792
|
-
div.className = "rich-mermaid-wrapper";
|
|
793
|
-
return div;
|
|
794
|
-
}
|
|
795
|
-
updateDOM() {
|
|
796
|
-
return false;
|
|
797
|
-
}
|
|
798
|
-
isInline() {
|
|
799
|
-
return false;
|
|
800
|
-
}
|
|
801
|
-
static importJSON(serializedNode) {
|
|
802
|
-
return $createMermaidNode(serializedNode.diagram);
|
|
803
|
-
}
|
|
804
|
-
exportJSON() {
|
|
805
|
-
return {
|
|
806
|
-
...super.exportJSON(),
|
|
807
|
-
type: "mermaid",
|
|
808
|
-
diagram: this.__diagram,
|
|
809
|
-
version: 1
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
getDiagram() {
|
|
813
|
-
return this.__diagram;
|
|
814
|
-
}
|
|
815
|
-
setDiagram(diagram) {
|
|
816
|
-
const writable = this.getWritable();
|
|
817
|
-
writable.__diagram = diagram;
|
|
818
|
-
}
|
|
819
|
-
decorate(editor, _config) {
|
|
820
|
-
const nodeKey = this.__key;
|
|
821
|
-
return createRendererDecoration("Mermaid", MermaidRenderer, {
|
|
822
|
-
content: this.__diagram,
|
|
823
|
-
onContentChange: (newDiagram) => {
|
|
824
|
-
editor.update(() => {
|
|
825
|
-
const node = $getNodeByKey(nodeKey);
|
|
826
|
-
if (node) {
|
|
827
|
-
node.setDiagram(newDiagram);
|
|
828
|
-
}
|
|
829
|
-
});
|
|
830
|
-
}
|
|
831
|
-
});
|
|
832
|
-
}
|
|
833
|
-
};
|
|
834
|
-
__publicField(_MermaidNode, "commandItems", [
|
|
835
|
-
{
|
|
836
|
-
title: "Mermaid Diagram",
|
|
837
|
-
icon: createElement(Workflow, { size: 20 }),
|
|
838
|
-
description: "Flowchart, sequence diagram",
|
|
839
|
-
keywords: ["mermaid", "diagram", "chart", "flowchart"],
|
|
840
|
-
section: "MEDIA",
|
|
841
|
-
placement: ["slash", "toolbar"],
|
|
842
|
-
group: "insert",
|
|
843
|
-
onSelect: (editor) => {
|
|
844
|
-
editor.update(() => {
|
|
845
|
-
$insertNodes([
|
|
846
|
-
$createMermaidNode("graph TD\n A[Start] --> B[End]")
|
|
847
|
-
]);
|
|
848
|
-
});
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
]);
|
|
852
|
-
let MermaidNode = _MermaidNode;
|
|
853
|
-
function $createMermaidNode(diagram) {
|
|
854
|
-
return new MermaidNode(diagram);
|
|
855
|
-
}
|
|
856
|
-
function $isMermaidNode(node) {
|
|
857
|
-
return node instanceof MermaidNode;
|
|
858
|
-
}
|
|
859
|
-
class SpoilerNode extends ElementNode {
|
|
860
|
-
static getType() {
|
|
861
|
-
return "spoiler";
|
|
862
|
-
}
|
|
863
|
-
static clone(node) {
|
|
864
|
-
return new SpoilerNode(node.__key);
|
|
865
|
-
}
|
|
866
|
-
constructor(key) {
|
|
867
|
-
super(key);
|
|
868
|
-
}
|
|
869
|
-
createDOM(_config) {
|
|
870
|
-
const span = document.createElement("span");
|
|
871
|
-
span.className = `${semanticClassNames.spoiler} ${sharedStyles.spoiler}`;
|
|
872
|
-
span.setAttribute("role", "button");
|
|
873
|
-
span.setAttribute("tabindex", "0");
|
|
874
|
-
span.setAttribute("aria-label", "Spoiler (click to reveal)");
|
|
875
|
-
const toggle = () => {
|
|
876
|
-
if (span.isContentEditable) return;
|
|
877
|
-
span.classList.toggle(semanticClassNames.spoilerRevealed);
|
|
878
|
-
const revealed = span.classList.toggle(sharedStyles.spoilerRevealed);
|
|
879
|
-
span.setAttribute(
|
|
880
|
-
"aria-label",
|
|
881
|
-
revealed ? "Spoiler (revealed)" : "Spoiler (click to reveal)"
|
|
882
|
-
);
|
|
883
|
-
};
|
|
884
|
-
span.addEventListener("click", toggle);
|
|
885
|
-
span.addEventListener("keydown", (e) => {
|
|
886
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
887
|
-
e.preventDefault();
|
|
888
|
-
toggle();
|
|
889
|
-
}
|
|
890
|
-
});
|
|
891
|
-
return span;
|
|
892
|
-
}
|
|
893
|
-
updateDOM() {
|
|
894
|
-
return false;
|
|
895
|
-
}
|
|
896
|
-
static importJSON(_serializedNode) {
|
|
897
|
-
return $createSpoilerNode();
|
|
898
|
-
}
|
|
899
|
-
exportJSON() {
|
|
900
|
-
return {
|
|
901
|
-
...super.exportJSON(),
|
|
902
|
-
type: "spoiler",
|
|
903
|
-
version: 1
|
|
904
|
-
};
|
|
905
|
-
}
|
|
906
|
-
canInsertTextBefore() {
|
|
907
|
-
return true;
|
|
908
|
-
}
|
|
909
|
-
canInsertTextAfter() {
|
|
910
|
-
return true;
|
|
911
|
-
}
|
|
912
|
-
isInline() {
|
|
913
|
-
return true;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
function $createSpoilerNode() {
|
|
917
|
-
return new SpoilerNode();
|
|
918
|
-
}
|
|
919
|
-
function $isSpoilerNode(node) {
|
|
920
|
-
return node instanceof SpoilerNode;
|
|
921
|
-
}
|
|
922
|
-
function stringToHue(str) {
|
|
923
|
-
let hash = 0;
|
|
924
|
-
for (let i = 0; i < str.length; i++) {
|
|
925
|
-
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
|
926
|
-
}
|
|
927
|
-
const hue = hash % 360;
|
|
928
|
-
return hue < 0 ? hue + 360 : hue;
|
|
929
|
-
}
|
|
930
|
-
function getTagBgColor(text) {
|
|
931
|
-
const hue = stringToHue(text);
|
|
932
|
-
const sat = 70 + hue % 21;
|
|
933
|
-
const light = 40 + hue % 31;
|
|
934
|
-
const bgSat = sat > 30 ? sat - 30 : 0;
|
|
935
|
-
const bgLight = light < 80 ? light + 20 : 100;
|
|
936
|
-
return `hsla(${hue}, ${bgSat}%, ${bgLight}%, 0.7)`;
|
|
937
|
-
}
|
|
938
|
-
const tagClassName = `${semanticClassNames.tag} ${sharedStyles.tag}`;
|
|
939
|
-
const _TagNode = class _TagNode extends TextNode {
|
|
940
|
-
static getType() {
|
|
941
|
-
return "tag";
|
|
942
|
-
}
|
|
943
|
-
static clone(node) {
|
|
944
|
-
return new _TagNode(node.__text, node.__key);
|
|
945
|
-
}
|
|
946
|
-
static importDOM() {
|
|
947
|
-
return {
|
|
948
|
-
span: () => ({
|
|
949
|
-
conversion: (domNode) => {
|
|
950
|
-
if (!(domNode instanceof HTMLElement)) return null;
|
|
951
|
-
if (!domNode.classList.contains(semanticClassNames.tag)) return null;
|
|
952
|
-
return {
|
|
953
|
-
node: $createTagNode(domNode.textContent ?? "")
|
|
954
|
-
};
|
|
955
|
-
},
|
|
956
|
-
priority: 2
|
|
957
|
-
})
|
|
958
|
-
};
|
|
959
|
-
}
|
|
960
|
-
constructor(text, key) {
|
|
961
|
-
super(text, key);
|
|
962
|
-
}
|
|
963
|
-
createDOM(config) {
|
|
964
|
-
const element = super.createDOM(config);
|
|
965
|
-
element.classList.add(semanticClassNames.tag, sharedStyles.tag);
|
|
966
|
-
element.style.backgroundColor = getTagBgColor(this.getTextContent());
|
|
967
|
-
return element;
|
|
968
|
-
}
|
|
969
|
-
updateDOM(prevNode, dom, config) {
|
|
970
|
-
const updated = super.updateDOM(prevNode, dom, config);
|
|
971
|
-
dom.classList.add(semanticClassNames.tag, sharedStyles.tag);
|
|
972
|
-
if (prevNode.__text !== this.__text) {
|
|
973
|
-
dom.style.backgroundColor = getTagBgColor(this.__text);
|
|
974
|
-
}
|
|
975
|
-
return updated;
|
|
976
|
-
}
|
|
977
|
-
exportDOM(_editor) {
|
|
978
|
-
const element = document.createElement("span");
|
|
979
|
-
element.className = tagClassName;
|
|
980
|
-
element.style.backgroundColor = getTagBgColor(this.getTextContent());
|
|
981
|
-
element.textContent = this.getTextContent();
|
|
982
|
-
return { element };
|
|
983
|
-
}
|
|
984
|
-
getText() {
|
|
985
|
-
return this.getTextContent();
|
|
986
|
-
}
|
|
987
|
-
canInsertTextBefore() {
|
|
988
|
-
return false;
|
|
989
|
-
}
|
|
990
|
-
canInsertTextAfter() {
|
|
991
|
-
return false;
|
|
992
|
-
}
|
|
993
|
-
isTextEntity() {
|
|
994
|
-
return true;
|
|
995
|
-
}
|
|
996
|
-
static importJSON(serializedNode) {
|
|
997
|
-
const node = $createTagNode(serializedNode.text ?? "");
|
|
998
|
-
node.setFormat(serializedNode.format ?? 0);
|
|
999
|
-
node.setDetail(serializedNode.detail ?? 0);
|
|
1000
|
-
node.setMode(serializedNode.mode ?? "normal");
|
|
1001
|
-
node.setStyle(serializedNode.style ?? "");
|
|
1002
|
-
return node;
|
|
1003
|
-
}
|
|
1004
|
-
exportJSON() {
|
|
1005
|
-
return {
|
|
1006
|
-
...super.exportJSON(),
|
|
1007
|
-
type: "tag",
|
|
1008
|
-
version: 1
|
|
1009
|
-
};
|
|
1010
|
-
}
|
|
1011
|
-
};
|
|
1012
|
-
__publicField(_TagNode, "commandItems", [
|
|
1013
|
-
{
|
|
1014
|
-
title: "Tag",
|
|
1015
|
-
icon: createElement(Tag, { size: 20 }),
|
|
1016
|
-
description: "Insert a tag",
|
|
1017
|
-
keywords: ["tag", "label", "badge"],
|
|
1018
|
-
section: "INLINE",
|
|
1019
|
-
placement: ["slash", "toolbar"],
|
|
1020
|
-
group: "insert",
|
|
1021
|
-
onSelect: (editor, queryString) => {
|
|
1022
|
-
editor.update(() => {
|
|
1023
|
-
$insertNodes([$createTagNode(queryString || "tag")]);
|
|
1024
|
-
});
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
]);
|
|
1028
|
-
let TagNode = _TagNode;
|
|
1029
|
-
function $createTagNode(text) {
|
|
1030
|
-
return new TagNode(text);
|
|
1031
|
-
}
|
|
1032
|
-
function $isTagNode(node) {
|
|
1033
|
-
return node instanceof TagNode;
|
|
1034
|
-
}
|
|
1035
|
-
const shared = (key) => `${semanticClassNames[key]} ${sharedStyles[key]}`;
|
|
1036
|
-
const editorTheme = {
|
|
1037
|
-
text: {
|
|
1038
|
-
bold: shared("textBold"),
|
|
1039
|
-
italic: shared("textItalic"),
|
|
1040
|
-
underline: shared("textUnderline"),
|
|
1041
|
-
strikethrough: shared("textStrikethrough"),
|
|
1042
|
-
superscript: shared("textSuperscript"),
|
|
1043
|
-
subscript: shared("textSubscript"),
|
|
1044
|
-
code: shared("textCode"),
|
|
1045
|
-
highlight: shared("textHighlight")
|
|
1046
|
-
},
|
|
1047
|
-
heading: {
|
|
1048
|
-
h1: shared("headingH1"),
|
|
1049
|
-
h2: shared("headingH2"),
|
|
1050
|
-
h3: shared("headingH3"),
|
|
1051
|
-
h4: shared("headingH4"),
|
|
1052
|
-
h5: shared("headingH5"),
|
|
1053
|
-
h6: shared("headingH6")
|
|
1054
|
-
},
|
|
1055
|
-
list: {
|
|
1056
|
-
ol: shared("listOl"),
|
|
1057
|
-
ul: shared("listUl"),
|
|
1058
|
-
listitem: shared("listItem"),
|
|
1059
|
-
listitemChecked: shared("listItemChecked"),
|
|
1060
|
-
listitemUnchecked: shared("listItemUnchecked"),
|
|
1061
|
-
checklist: shared("checklist"),
|
|
1062
|
-
nested: {
|
|
1063
|
-
listitem: shared("listNestedItem")
|
|
1064
|
-
}
|
|
1065
|
-
},
|
|
1066
|
-
quote: shared("quote"),
|
|
1067
|
-
link: shared("link"),
|
|
1068
|
-
paragraph: shared("paragraph"),
|
|
1069
|
-
code: "rich-code-block",
|
|
1070
|
-
table: shared("table"),
|
|
1071
|
-
tableCell: shared("tableCell"),
|
|
1072
|
-
tableCellHeader: shared("tableCellHeader"),
|
|
1073
|
-
tableScrollableWrapper: shared("tableScrollableWrapper"),
|
|
1074
|
-
/** Used by @lexical/extension HorizontalRuleNode */
|
|
1075
|
-
hr: shared("hr")
|
|
1076
|
-
};
|
|
1077
|
-
export {
|
|
1078
|
-
$createImageNode as $,
|
|
1079
|
-
ALERT_LABELS as A,
|
|
1080
|
-
FootnoteNode as F,
|
|
1081
|
-
ImageNode as I,
|
|
1082
|
-
KaTeXBlockNode as K,
|
|
1083
|
-
MentionNode as M,
|
|
1084
|
-
NestedContentRendererProvider as N,
|
|
1085
|
-
OPEN_IMAGE_UPLOAD_DIALOG_COMMAND as O,
|
|
1086
|
-
SpoilerNode as S,
|
|
1087
|
-
TagNode as T,
|
|
1088
|
-
$createMentionNode as a,
|
|
1089
|
-
$createMermaidNode as b,
|
|
1090
|
-
$createTagNode as c,
|
|
1091
|
-
$isImageNode as d,
|
|
1092
|
-
$isKaTeXBlockNode as e,
|
|
1093
|
-
$isKaTeXInlineNode as f,
|
|
1094
|
-
$isMentionNode as g,
|
|
1095
|
-
$isMermaidNode as h,
|
|
1096
|
-
$isTagNode as i,
|
|
1097
|
-
ALERT_TYPES as j,
|
|
1098
|
-
KaTeXInlineNode as k,
|
|
1099
|
-
MermaidNode as l,
|
|
1100
|
-
getTagBgColor as m,
|
|
1101
|
-
editorTheme as n,
|
|
1102
|
-
extractTextContent as o,
|
|
1103
|
-
useOptionalNestedContentRenderer as p,
|
|
1104
|
-
$createSpoilerNode as q,
|
|
1105
|
-
$isSpoilerNode as r,
|
|
1106
|
-
$isAlertQuoteNode as s,
|
|
1107
|
-
AlertRenderer as t,
|
|
1108
|
-
useNestedContentRenderer as u,
|
|
1109
|
-
AlertQuoteNode as v,
|
|
1110
|
-
$createKaTeXInlineNode as w,
|
|
1111
|
-
$createKaTeXBlockNode as x,
|
|
1112
|
-
$createFootnoteNode as y
|
|
1113
|
-
};
|