@haklex/rich-editor 0.0.79 → 0.0.81

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.
@@ -0,0 +1,41 @@
1
+ //#region src/utils/favicon.ts
2
+ var FAVICON_VARIANTS = [
3
+ "/favicon.ico",
4
+ "/favicon.png",
5
+ "/favicon.svg",
6
+ "/apple-touch-icon.png",
7
+ "/apple-touch-icon-precomposed.png"
8
+ ];
9
+ var faviconCache = /* @__PURE__ */ new Map();
10
+ function getHostname(href) {
11
+ try {
12
+ const url = new URL(href);
13
+ if (url.protocol !== "http:" && url.protocol !== "https:") return null;
14
+ return url.hostname;
15
+ } catch {
16
+ return null;
17
+ }
18
+ }
19
+ function probeImage(url) {
20
+ return new Promise((resolve) => {
21
+ const img = new Image();
22
+ img.onload = () => resolve(url);
23
+ img.onerror = () => resolve(null);
24
+ img.src = url;
25
+ });
26
+ }
27
+ async function probeFavicon(hostname) {
28
+ const cached = faviconCache.get(hostname);
29
+ if (cached !== void 0) return cached;
30
+ for (const variant of FAVICON_VARIANTS) {
31
+ const result = await probeImage(`https://${hostname}${variant}`);
32
+ if (result) {
33
+ faviconCache.set(hostname, result);
34
+ return result;
35
+ }
36
+ }
37
+ faviconCache.set(hostname, null);
38
+ return null;
39
+ }
40
+ //#endregion
41
+ export { probeFavicon as n, getHostname as t };
package/dist/index.mjs CHANGED
@@ -1,310 +1,285 @@
1
- import { F as FootnotePlugin, O as OnChangePlugin, S as SubmitShortcutPlugin, E as EditorRefPlugin, a as AutoFocusPlugin, d as ImageUploadProvider, g as defaultImageUpload, C as CorePlugins, I as ImageUploadPlugin, L as LinkFaviconPlugin, c as BlockIdPlugin, f as blockIdState } from "./SubmitShortcutPlugin-BFBAwTb1.js";
2
- import { L, P, u } from "./PresentDialogContext-BpSB8tXC.js";
1
+ import { a as AutoFocusPlugin, c as defaultImageUpload, d as ImageUploadProvider, i as EditorRefPlugin, l as BlockIdPlugin, n as OnChangePlugin, o as LinkFaviconPlugin, p as CorePlugins, r as FootnotePlugin, s as ImageUploadPlugin, t as SubmitShortcutPlugin, u as blockIdState } from "./SubmitShortcutPlugin-6IvsbZD-.js";
2
+ import { n as setResolvedEditNodes, r as allEditNodes } from "./node-registry-CeVi2y9f.js";
3
+ import { F as useOptionalNestedContentRenderer, N as NestedContentRendererProvider, P as useNestedContentRenderer, t as editorTheme } from "./theme-DHOUKKSr.js";
4
+ import { a as FootnoteDefinitionsProvider, c as useFootnoteDisplayNumber, d as RendererConfigProvider, f as useRendererConfig, m as useVariant, o as useFootnoteContent, p as useRendererMode, s as useFootnoteDefinitions } from "./KaTeXRenderer-BsyRH5_t.js";
5
+ import { C as useColorScheme, S as ColorSchemeProvider } from "./config-tfg1FWhG.js";
6
+ import "./LinkCardRenderer-OEMBDUhD.js";
7
+ import "./AlertQuoteEditNode-BDoonB4u.js";
8
+ import { n as usePresentDialog, r as LinkFavicon, t as PresentDialogProvider } from "./PresentDialogContext-DQw6MrNh.js";
9
+ import { a as KaTeXPlugin, c as AlertPlugin, n as MermaidPlugin, s as ImagePlugin } from "./MermaidPlugin-Df2Cm2yX.js";
10
+ /* empty css */
11
+ import { a as commentVariant, i as noteVariant, n as clsx, o as articleVariant, r as getVariantClass, t as richContent } from "./shared.css-wgGgtK_e.js";
12
+ import { $getRoot, $getSelection, $getState, $isElementNode, $isLineBreakNode, $isRangeSelection, $isTextNode } from "lexical";
3
13
  import { jsx, jsxs } from "react/jsx-runtime";
4
- import { s as setResolvedEditNodes, a as allEditNodes } from "./node-registry-B2U2_LrI.js";
5
- import { I as ImagePlugin, K as KaTeXPlugin, A as AlertPlugin, M as MermaidPlugin } from "./MermaidPlugin-DjLUVZvB.js";
14
+ import { ContentEditable } from "@lexical/react/LexicalContentEditable";
15
+ import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
16
+ import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
6
17
  import { PortalThemeProvider } from "@haklex/rich-style-token";
7
18
  import { LexicalComposer } from "@lexical/react/LexicalComposer";
8
- import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
9
19
  import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
10
- import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
11
- import { C as ColorSchemeProvider } from "./config-DcR_yktp.js";
12
- import { u as u2 } from "./config-DcR_yktp.js";
13
- import { R as RendererConfigProvider } from "./KaTeXRenderer-C8jv_5xr.js";
14
- import { F, u as u3, b, d, e, f, g } from "./KaTeXRenderer-C8jv_5xr.js";
15
- import { n as editorTheme } from "./theme-CYsyGmCL.js";
16
- import { N, u as u4, p } from "./theme-CYsyGmCL.js";
17
- import { ContentEditable as ContentEditable$1 } from "@lexical/react/LexicalContentEditable";
18
- /* empty css */
19
- import { b as clsx, g as getVariantClass } from "./shared.css-DNuMYx6Q.js";
20
- import { a, c, n, r } from "./shared.css-DNuMYx6Q.js";
21
20
  import { articleTheme, commentTheme, noteTheme, vars } from "@haklex/rich-style-token/styles";
22
- import { $getRoot, $getSelection, $isRangeSelection, $getState, $isElementNode, $isTextNode, $isLineBreakNode } from "lexical";
21
+ //#region src/components/ContentEditable.css.ts
23
22
  var contentWrapper = "b94s950";
24
23
  var content = "b94s951";
25
24
  var placeholder = "b94s952";
26
- function ContentEditable({ className, placeholder: placeholder$1, hasHeader }) {
27
- const paddingTop = hasHeader ? 40 : 12;
28
- return /* @__PURE__ */ jsx(
29
- "div",
30
- {
31
- className: clsx("rich-editor__content-wrapper", contentWrapper),
32
- style: { "--ce-padding-top": `${paddingTop}px` },
33
- children: /* @__PURE__ */ jsx(
34
- ContentEditable$1,
35
- {
36
- "aria-placeholder": placeholder$1 ?? "",
37
- className: clsx("rich-editor__content", content, className),
38
- placeholder: /* @__PURE__ */ jsx(
39
- "div",
40
- {
41
- className: clsx("rich-editor__placeholder", placeholder),
42
- style: { display: placeholder$1 ? void 0 : "none" },
43
- children: placeholder$1
44
- }
45
- )
46
- }
47
- )
48
- }
49
- );
25
+ //#endregion
26
+ //#region src/components/ContentEditable.tsx
27
+ function ContentEditable$1({ className, placeholder: placeholder$1, hasHeader }) {
28
+ const paddingTop = hasHeader ? 40 : 12;
29
+ return /* @__PURE__ */ jsx("div", {
30
+ className: clsx("rich-editor__content-wrapper", contentWrapper),
31
+ style: { "--ce-padding-top": `${paddingTop}px` },
32
+ children: /* @__PURE__ */ jsx(ContentEditable, {
33
+ "aria-placeholder": placeholder$1 ?? "",
34
+ className: clsx("rich-editor__content", content, className),
35
+ placeholder: /* @__PURE__ */ jsx("div", {
36
+ className: clsx("rich-editor__placeholder", placeholder),
37
+ style: { display: placeholder$1 ? void 0 : "none" },
38
+ children: placeholder$1
39
+ })
40
+ })
41
+ });
50
42
  }
51
- function RichEditorShell({
52
- nodes,
53
- initialValue,
54
- onChange,
55
- variant = "article",
56
- theme = "light",
57
- placeholder: placeholder2 = "Write something...",
58
- onSubmit,
59
- autoFocus = false,
60
- className,
61
- contentClassName,
62
- style,
63
- actions,
64
- header,
65
- onEditorReady,
66
- rendererConfig,
67
- debounceMs,
68
- children
69
- }) {
70
- setResolvedEditNodes(nodes);
71
- const initialConfig = {
72
- namespace: "RichEditor",
73
- theme: editorTheme,
74
- nodes,
75
- editable: true,
76
- onError: (error) => {
77
- console.error("[RichEditor]", error);
78
- },
79
- ...initialValue ? { editorState: JSON.stringify(initialValue) } : {}
80
- };
81
- const variantClass = getVariantClass(variant);
82
- return /* @__PURE__ */ jsx(PortalThemeProvider, { className: variantClass, theme, children: /* @__PURE__ */ jsx(ColorSchemeProvider, { colorScheme: theme, children: /* @__PURE__ */ jsx(RendererConfigProvider, { config: rendererConfig, mode: "editor", variant, children: /* @__PURE__ */ jsx(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx(FootnotePlugin, { children: /* @__PURE__ */ jsxs(
83
- "div",
84
- {
85
- suppressHydrationWarning: true,
86
- className: clsx("rich-editor", variantClass, className),
87
- "data-theme": theme,
88
- style: { ...style, maxWidth: "none" },
89
- children: [
90
- header,
91
- /* @__PURE__ */ jsx(
92
- RichTextPlugin,
93
- {
94
- ErrorBoundary: LexicalErrorBoundary,
95
- contentEditable: /* @__PURE__ */ jsx(
96
- ContentEditable,
97
- {
98
- className: contentClassName,
99
- hasHeader: !!header,
100
- placeholder: placeholder2
101
- }
102
- )
103
- }
104
- ),
105
- /* @__PURE__ */ jsx(HistoryPlugin, {}),
106
- /* @__PURE__ */ jsx(OnChangePlugin, { debounceMs, onChange }),
107
- /* @__PURE__ */ jsx(SubmitShortcutPlugin, { onSubmit }),
108
- /* @__PURE__ */ jsx(EditorRefPlugin, { onEditorReady }),
109
- autoFocus && /* @__PURE__ */ jsx(AutoFocusPlugin, {}),
110
- children,
111
- actions && /* @__PURE__ */ jsx("div", { className: "rich-editor__actions", children: actions })
112
- ]
113
- }
114
- ) }) }) }) }) });
43
+ //#endregion
44
+ //#region src/components/RichEditorShell.tsx
45
+ function RichEditorShell({ nodes, initialValue, onChange, variant = "article", theme = "light", placeholder = "Write something...", onSubmit, autoFocus = false, className, contentClassName, style, actions, header, onEditorReady, rendererConfig, debounceMs, children }) {
46
+ setResolvedEditNodes(nodes);
47
+ const initialConfig = {
48
+ namespace: "RichEditor",
49
+ theme: editorTheme,
50
+ nodes,
51
+ editable: true,
52
+ onError: (error) => {
53
+ console.error("[RichEditor]", error);
54
+ },
55
+ ...initialValue ? { editorState: JSON.stringify(initialValue) } : {}
56
+ };
57
+ const variantClass = getVariantClass(variant);
58
+ return /* @__PURE__ */ jsx(PortalThemeProvider, {
59
+ className: variantClass,
60
+ theme,
61
+ children: /* @__PURE__ */ jsx(ColorSchemeProvider, {
62
+ colorScheme: theme,
63
+ children: /* @__PURE__ */ jsx(RendererConfigProvider, {
64
+ config: rendererConfig,
65
+ mode: "editor",
66
+ variant,
67
+ children: /* @__PURE__ */ jsx(LexicalComposer, {
68
+ initialConfig,
69
+ children: /* @__PURE__ */ jsx(FootnotePlugin, { children: /* @__PURE__ */ jsxs("div", {
70
+ suppressHydrationWarning: true,
71
+ className: clsx("rich-editor", variantClass, className),
72
+ "data-theme": theme,
73
+ style: {
74
+ ...style,
75
+ maxWidth: "none"
76
+ },
77
+ children: [
78
+ header,
79
+ /* @__PURE__ */ jsx(RichTextPlugin, {
80
+ ErrorBoundary: LexicalErrorBoundary,
81
+ contentEditable: /* @__PURE__ */ jsx(ContentEditable$1, {
82
+ className: contentClassName,
83
+ hasHeader: !!header,
84
+ placeholder
85
+ })
86
+ }),
87
+ /* @__PURE__ */ jsx(HistoryPlugin, {}),
88
+ /* @__PURE__ */ jsx(OnChangePlugin, {
89
+ debounceMs,
90
+ onChange
91
+ }),
92
+ /* @__PURE__ */ jsx(SubmitShortcutPlugin, { onSubmit }),
93
+ /* @__PURE__ */ jsx(EditorRefPlugin, { onEditorReady }),
94
+ autoFocus && /* @__PURE__ */ jsx(AutoFocusPlugin, {}),
95
+ children,
96
+ actions && /* @__PURE__ */ jsx("div", {
97
+ className: "rich-editor__actions",
98
+ children: actions
99
+ })
100
+ ]
101
+ }) })
102
+ })
103
+ })
104
+ })
105
+ });
115
106
  }
107
+ //#endregion
108
+ //#region src/components/RichEditor.tsx
116
109
  function RichEditor({ extraNodes, imageUpload, children, ...shellProps }) {
117
- const nodes = extraNodes ? [...allEditNodes, ...extraNodes] : allEditNodes;
118
- const resolvedImageUpload = imageUpload ?? defaultImageUpload;
119
- return /* @__PURE__ */ jsx(ImageUploadProvider, { upload: resolvedImageUpload, children: /* @__PURE__ */ jsxs(RichEditorShell, { nodes, ...shellProps, children: [
120
- /* @__PURE__ */ jsx(CorePlugins, {}),
121
- /* @__PURE__ */ jsx(ImagePlugin, {}),
122
- /* @__PURE__ */ jsx(ImageUploadPlugin, { onUpload: resolvedImageUpload }),
123
- /* @__PURE__ */ jsx(KaTeXPlugin, {}),
124
- /* @__PURE__ */ jsx(AlertPlugin, {}),
125
- /* @__PURE__ */ jsx(MermaidPlugin, {}),
126
- /* @__PURE__ */ jsx(LinkFaviconPlugin, {}),
127
- /* @__PURE__ */ jsx(BlockIdPlugin, {}),
128
- children
129
- ] }) });
110
+ const nodes = extraNodes ? [...allEditNodes, ...extraNodes] : allEditNodes;
111
+ const resolvedImageUpload = imageUpload ?? defaultImageUpload;
112
+ return /* @__PURE__ */ jsx(ImageUploadProvider, {
113
+ upload: resolvedImageUpload,
114
+ children: /* @__PURE__ */ jsxs(RichEditorShell, {
115
+ nodes,
116
+ ...shellProps,
117
+ children: [
118
+ /* @__PURE__ */ jsx(CorePlugins, {}),
119
+ /* @__PURE__ */ jsx(ImagePlugin, {}),
120
+ /* @__PURE__ */ jsx(ImageUploadPlugin, { onUpload: resolvedImageUpload }),
121
+ /* @__PURE__ */ jsx(KaTeXPlugin, {}),
122
+ /* @__PURE__ */ jsx(AlertPlugin, {}),
123
+ /* @__PURE__ */ jsx(MermaidPlugin, {}),
124
+ /* @__PURE__ */ jsx(LinkFaviconPlugin, {}),
125
+ /* @__PURE__ */ jsx(BlockIdPlugin, {}),
126
+ children
127
+ ]
128
+ })
129
+ });
130
130
  }
131
+ //#endregion
132
+ //#region src/utils/comment-anchor.ts
131
133
  function computeBlockFingerprint(block) {
132
- const text = block.getTextContent();
133
- const input = text.slice(0, 200) + String(text.length);
134
- let hash = 5381;
135
- for (let i = 0; i < input.length; i++) {
136
- hash = (hash << 5) + hash + (input.codePointAt(i) ?? 0) | 0;
137
- }
138
- return (hash >>> 0).toString(16);
134
+ const text = block.getTextContent();
135
+ const input = text.slice(0, 200) + String(text.length);
136
+ let hash = 5381;
137
+ for (let i = 0; i < input.length; i++) hash = (hash << 5) + hash + (input.codePointAt(i) ?? 0) | 0;
138
+ return (hash >>> 0).toString(16);
139
139
  }
140
140
  function $getRootBlock(node) {
141
- const root = $getRoot();
142
- let current = node;
143
- while (current) {
144
- const parent = current.getParent();
145
- if (parent === root && "getChildren" in current) {
146
- return current;
147
- }
148
- current = parent;
149
- }
150
- return null;
141
+ const root = $getRoot();
142
+ let current = node;
143
+ while (current) {
144
+ const parent = current.getParent();
145
+ if (parent === root && "getChildren" in current) return current;
146
+ current = parent;
147
+ }
148
+ return null;
151
149
  }
152
150
  function $resolveSelectionPoint(selection, which) {
153
- const point = selection[which];
154
- const node = point.getNode();
155
- if ($isElementNode(node)) {
156
- const children = node.getChildren();
157
- if (point.offset < children.length) {
158
- return { node: children[point.offset], offset: 0 };
159
- }
160
- const last = children.at(-1);
161
- if (last && $isTextNode(last)) {
162
- return { node: last, offset: last.getTextContentSize() };
163
- }
164
- return { node, offset: 0 };
165
- }
166
- return { node, offset: point.offset };
151
+ const point = selection[which];
152
+ const node = point.getNode();
153
+ if ($isElementNode(node)) {
154
+ const children = node.getChildren();
155
+ if (point.offset < children.length) return {
156
+ node: children[point.offset],
157
+ offset: 0
158
+ };
159
+ const last = children.at(-1);
160
+ if (last && $isTextNode(last)) return {
161
+ node: last,
162
+ offset: last.getTextContentSize()
163
+ };
164
+ return {
165
+ node,
166
+ offset: 0
167
+ };
168
+ }
169
+ return {
170
+ node,
171
+ offset: point.offset
172
+ };
167
173
  }
168
174
  function $getTextOffsetInBlock(block, targetNode, targetOffset) {
169
- let offset = 0;
170
- function walk(node) {
171
- if (node.is(targetNode)) {
172
- offset += targetOffset;
173
- return true;
174
- }
175
- if ($isTextNode(node)) {
176
- offset += node.getTextContentSize();
177
- } else if ($isLineBreakNode(node)) {
178
- offset += 1;
179
- } else if ($isElementNode(node)) {
180
- for (const child of node.getChildren()) {
181
- if (walk(child)) return true;
182
- }
183
- }
184
- return false;
185
- }
186
- for (const child of block.getChildren()) {
187
- if (walk(child)) break;
188
- }
189
- return offset;
175
+ let offset = 0;
176
+ function walk(node) {
177
+ if (node.is(targetNode)) {
178
+ offset += targetOffset;
179
+ return true;
180
+ }
181
+ if ($isTextNode(node)) offset += node.getTextContentSize();
182
+ else if ($isLineBreakNode(node)) offset += 1;
183
+ else if ($isElementNode(node)) {
184
+ for (const child of node.getChildren()) if (walk(child)) return true;
185
+ }
186
+ return false;
187
+ }
188
+ for (const child of block.getChildren()) if (walk(child)) break;
189
+ return offset;
190
190
  }
191
191
  function $buildBlockAnchorData(block) {
192
- const blockId = $getState(block, blockIdState);
193
- if (!blockId) {
194
- return { ok: false, error: "no-block-id" };
195
- }
196
- return {
197
- ok: true,
198
- anchor: {
199
- mode: "block",
200
- blockId,
201
- blockType: block.getType(),
202
- blockFingerprint: computeBlockFingerprint(block),
203
- snapshotText: block.getTextContent().slice(0, 300)
204
- }
205
- };
192
+ const blockId = $getState(block, blockIdState);
193
+ if (!blockId) return {
194
+ ok: false,
195
+ error: "no-block-id"
196
+ };
197
+ return {
198
+ ok: true,
199
+ anchor: {
200
+ mode: "block",
201
+ blockId,
202
+ blockType: block.getType(),
203
+ blockFingerprint: computeBlockFingerprint(block),
204
+ snapshotText: block.getTextContent().slice(0, 300)
205
+ }
206
+ };
206
207
  }
207
208
  function buildBlockAnchor(editor, blockKey) {
208
- return editor.read(() => {
209
- if (blockKey) {
210
- const node = $getRoot().getChildren().find((c2) => c2.getKey() === blockKey);
211
- if (!node || !("getChildren" in node)) {
212
- return { ok: false, error: "not-root-block" };
213
- }
214
- return $buildBlockAnchorData(node);
215
- }
216
- const selection = $getSelection();
217
- if (!$isRangeSelection(selection)) {
218
- return { ok: false, error: "no-selection" };
219
- }
220
- const anchorNode = selection.anchor.getNode();
221
- const block = $getRootBlock(anchorNode);
222
- if (!block) {
223
- return { ok: false, error: "not-root-block" };
224
- }
225
- return $buildBlockAnchorData(block);
226
- });
209
+ return editor.read(() => {
210
+ if (blockKey) {
211
+ const node = $getRoot().getChildren().find((c) => c.getKey() === blockKey);
212
+ if (!node || !("getChildren" in node)) return {
213
+ ok: false,
214
+ error: "not-root-block"
215
+ };
216
+ return $buildBlockAnchorData(node);
217
+ }
218
+ const selection = $getSelection();
219
+ if (!$isRangeSelection(selection)) return {
220
+ ok: false,
221
+ error: "no-selection"
222
+ };
223
+ const block = $getRootBlock(selection.anchor.getNode());
224
+ if (!block) return {
225
+ ok: false,
226
+ error: "not-root-block"
227
+ };
228
+ return $buildBlockAnchorData(block);
229
+ });
227
230
  }
228
231
  function buildRangeAnchor(editor) {
229
- return editor.read(() => {
230
- const selection = $getSelection();
231
- if (!$isRangeSelection(selection)) {
232
- return { ok: false, error: "no-selection" };
233
- }
234
- if (selection.isCollapsed()) {
235
- return { ok: false, error: "collapsed" };
236
- }
237
- const anchorBlock = $getRootBlock(selection.anchor.getNode());
238
- const focusBlock = $getRootBlock(selection.focus.getNode());
239
- if (!anchorBlock || !focusBlock) {
240
- return { ok: false, error: "not-root-block" };
241
- }
242
- if (anchorBlock !== focusBlock) {
243
- return { ok: false, error: "cross-block" };
244
- }
245
- const block = anchorBlock;
246
- const blockId = $getState(block, blockIdState);
247
- if (!blockId) {
248
- return { ok: false, error: "no-block-id" };
249
- }
250
- const anchorPoint = $resolveSelectionPoint(selection, "anchor");
251
- const focusPoint = $resolveSelectionPoint(selection, "focus");
252
- let startOffset = $getTextOffsetInBlock(block, anchorPoint.node, anchorPoint.offset);
253
- let endOffset = $getTextOffsetInBlock(block, focusPoint.node, focusPoint.offset);
254
- if (startOffset > endOffset) {
255
- [startOffset, endOffset] = [endOffset, startOffset];
256
- }
257
- const text = block.getTextContent();
258
- const quote = text.slice(startOffset, endOffset);
259
- const prefix = text.slice(Math.max(0, startOffset - 50), startOffset);
260
- const suffix = text.slice(endOffset, endOffset + 50);
261
- return {
262
- ok: true,
263
- anchor: {
264
- mode: "range",
265
- blockId,
266
- blockType: block.getType(),
267
- blockFingerprint: computeBlockFingerprint(block),
268
- snapshotText: text.slice(0, 300),
269
- quote,
270
- prefix,
271
- suffix,
272
- startOffset,
273
- endOffset
274
- }
275
- };
276
- });
232
+ return editor.read(() => {
233
+ const selection = $getSelection();
234
+ if (!$isRangeSelection(selection)) return {
235
+ ok: false,
236
+ error: "no-selection"
237
+ };
238
+ if (selection.isCollapsed()) return {
239
+ ok: false,
240
+ error: "collapsed"
241
+ };
242
+ const anchorBlock = $getRootBlock(selection.anchor.getNode());
243
+ const focusBlock = $getRootBlock(selection.focus.getNode());
244
+ if (!anchorBlock || !focusBlock) return {
245
+ ok: false,
246
+ error: "not-root-block"
247
+ };
248
+ if (anchorBlock !== focusBlock) return {
249
+ ok: false,
250
+ error: "cross-block"
251
+ };
252
+ const block = anchorBlock;
253
+ const blockId = $getState(block, blockIdState);
254
+ if (!blockId) return {
255
+ ok: false,
256
+ error: "no-block-id"
257
+ };
258
+ const anchorPoint = $resolveSelectionPoint(selection, "anchor");
259
+ const focusPoint = $resolveSelectionPoint(selection, "focus");
260
+ let startOffset = $getTextOffsetInBlock(block, anchorPoint.node, anchorPoint.offset);
261
+ let endOffset = $getTextOffsetInBlock(block, focusPoint.node, focusPoint.offset);
262
+ if (startOffset > endOffset) [startOffset, endOffset] = [endOffset, startOffset];
263
+ const text = block.getTextContent();
264
+ const quote = text.slice(startOffset, endOffset);
265
+ const prefix = text.slice(Math.max(0, startOffset - 50), startOffset);
266
+ const suffix = text.slice(endOffset, endOffset + 50);
267
+ return {
268
+ ok: true,
269
+ anchor: {
270
+ mode: "range",
271
+ blockId,
272
+ blockType: block.getType(),
273
+ blockFingerprint: computeBlockFingerprint(block),
274
+ snapshotText: text.slice(0, 300),
275
+ quote,
276
+ prefix,
277
+ suffix,
278
+ startOffset,
279
+ endOffset
280
+ }
281
+ };
282
+ });
277
283
  }
278
- export {
279
- ColorSchemeProvider,
280
- CorePlugins,
281
- F as FootnoteDefinitionsProvider,
282
- L as LinkFavicon,
283
- N as NestedContentRendererProvider,
284
- P as PresentDialogProvider,
285
- RendererConfigProvider,
286
- RichEditor,
287
- RichEditorShell,
288
- articleTheme,
289
- a as articleVariant,
290
- buildBlockAnchor,
291
- buildRangeAnchor,
292
- commentTheme,
293
- c as commentVariant,
294
- editorTheme,
295
- getVariantClass,
296
- noteTheme,
297
- n as noteVariant,
298
- r as richContent,
299
- u2 as useColorScheme,
300
- u3 as useFootnoteContent,
301
- b as useFootnoteDefinitions,
302
- d as useFootnoteDisplayNumber,
303
- u4 as useNestedContentRenderer,
304
- p as useOptionalNestedContentRenderer,
305
- u as usePresentDialog,
306
- e as useRendererConfig,
307
- f as useRendererMode,
308
- g as useVariant,
309
- vars
310
- };
284
+ //#endregion
285
+ export { ColorSchemeProvider, CorePlugins, FootnoteDefinitionsProvider, LinkFavicon, NestedContentRendererProvider, PresentDialogProvider, RendererConfigProvider, RichEditor, RichEditorShell, articleTheme, articleVariant, buildBlockAnchor, buildRangeAnchor, commentTheme, commentVariant, editorTheme, getVariantClass, noteTheme, noteVariant, richContent, useColorScheme, useFootnoteContent, useFootnoteDefinitions, useFootnoteDisplayNumber, useNestedContentRenderer, useOptionalNestedContentRenderer, usePresentDialog, useRendererConfig, useRendererMode, useVariant, vars };