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