tiptap-markdown-react 0.8.6 → 0.8.8
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/README.md +5 -2
- package/dist/components/EditorToolbar.d.ts +32 -2
- package/dist/icons/index.d.ts +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +174 -54
- package/dist/index.js.map +1 -1
- package/dist/insertMarkdown.d.ts +3 -0
- package/dist/insertMarkdown.test.d.ts +1 -0
- package/dist/labels.d.ts +13 -0
- package/dist/style.css +70 -51
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -222,7 +222,7 @@ Three ways to get markdown into the editor, all built in:
|
|
|
222
222
|
|
|
223
223
|
- **Paste markdown text** — plain-text paste is heuristically detected (headings, lists, links, fences, tables…) and parsed into rich content. Rich-text (HTML) paste is untouched; Shift+paste always inserts plain text; pasting inside a code block is never converted. Opt out with `markdownPaste={false}`.
|
|
224
224
|
- **Drop / paste `.md` files** — drag a `.md` / `.markdown` file into the editor (inserted at drop point) or paste a copied file (inserted at cursor). Opt out with `markdownFileDrop={false}`.
|
|
225
|
-
- **Toolbar import** —
|
|
225
|
+
- **Toolbar import** — the main-bar **Import** button opens a file picker and inserts the parsed file at the cursor (label: `labels.importDocument`). `.md` / `.markdown` is read in-package; any other file is handed to `onImportDocument`, so hosts decide which formats to accept (`importAccept`) and how to convert them. Without that callback the picker stays `.md`-only.
|
|
226
226
|
|
|
227
227
|
The underlying extensions `MarkdownPaste` / `MarkdownFileDrop` (and the `looksLikeMarkdown` heuristic) are exported for custom pipelines.
|
|
228
228
|
|
|
@@ -232,7 +232,10 @@ The underlying extensions `MarkdownPaste` / `MarkdownFileDrop` (and the `looksLi
|
|
|
232
232
|
| --- | --- | --- |
|
|
233
233
|
| `editor` | `Editor` | The instance from `onEditorReady`. |
|
|
234
234
|
| `onImageUpload` | `(file: File) => Promise<string>` | Upload handler returning a URL. Omit to hide the image button. |
|
|
235
|
-
| `onError` | `(err
|
|
235
|
+
| `onError` | `(err, source?: 'image' \| 'markdown' \| 'import') => void` | Side-effect error callback (e.g. failed upload). |
|
|
236
|
+
| `onImportDocument` | `(file, ctx) => Promise<ImportDocumentResult \| string>` | Converts a non-Markdown file to Markdown. `ctx.signal` aborts on cancel/unmount; `ctx.onProgress` reports upload/convert progress back. Omit and Import only takes `.md`. |
|
|
237
|
+
| `importAccept` | `string` | Extra `accept` for the Import picker, e.g. `.docx,.csv,.pdf`. The package never validates extensions itself. |
|
|
238
|
+
| `showImport` | `boolean` | Show the Import button (default `true`). |
|
|
236
239
|
| `labels` | `Partial<ToolbarLabels>` | i18n labels. |
|
|
237
240
|
| `extraToolbarItems` | `ExtraToolbarItem[]` | Custom items appended to the "More" menu. |
|
|
238
241
|
| `labels.inlineMath` / `blockMath` | `string` | More-menu equation items. |
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { Editor } from '@tiptap/react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { ToolbarLabels } from '../labels';
|
|
4
|
+
import { SourceRef } from '../citationUtils';
|
|
5
|
+
/** `onImportDocument` 的成功返回。给字符串等价于 `{ markdown }`。 */
|
|
6
|
+
export interface ImportDocumentResult {
|
|
7
|
+
markdown: string;
|
|
8
|
+
sources?: SourceRef[];
|
|
9
|
+
}
|
|
10
|
+
/** 导入进度。宿主自行决定怎么展示(包只据此禁用按钮)。 */
|
|
11
|
+
export interface ImportDocumentProgress {
|
|
12
|
+
/** 0–1。通常只有上传阶段可测;转换阶段可省略。 */
|
|
13
|
+
ratio?: number;
|
|
14
|
+
phase: 'upload' | 'convert';
|
|
15
|
+
}
|
|
16
|
+
export interface ImportDocumentContext {
|
|
17
|
+
/** 用户点取消或组件卸载时 abort,宿主据此中断请求。 */
|
|
18
|
+
signal: AbortSignal;
|
|
19
|
+
onProgress?: (p: ImportDocumentProgress) => void;
|
|
20
|
+
}
|
|
4
21
|
/** More 菜单里注入的自定义项(宿主用它扩展工具栏,如「导入项目报告」)。 */
|
|
5
22
|
export interface ExtraToolbarItem {
|
|
6
23
|
key: string;
|
|
@@ -22,7 +39,20 @@ export interface EditorToolbarProps {
|
|
|
22
39
|
* 副作用错误回调(图片上传 / Markdown 导入失败),供宿主弹自己的提示。
|
|
23
40
|
* `source` 区分来源,避免一律显示「图片上传失败」。
|
|
24
41
|
*/
|
|
25
|
-
onError?: (err: unknown, source?: 'image' | 'markdown') => void;
|
|
42
|
+
onError?: (err: unknown, source?: 'image' | 'markdown' | 'import') => void;
|
|
43
|
+
/**
|
|
44
|
+
* 非 Markdown 文件的转换:收到文件,返回可插入的 Markdown。未提供则导入只吃 .md。
|
|
45
|
+
* 包内不校验扩展名——格式白名单由宿主的 `importAccept` 与本回调自己负责。
|
|
46
|
+
* 抛错转交 onError(..., 'import');`AbortError` 视为用户取消,不报错。
|
|
47
|
+
*/
|
|
48
|
+
onImportDocument?: (file: File, ctx: ImportDocumentContext) => Promise<ImportDocumentResult | string>;
|
|
49
|
+
/**
|
|
50
|
+
* 追加到导入 input 的 accept(默认已含 `.md,.markdown,text/markdown`)。
|
|
51
|
+
* 例:`.doc,.docx,.csv,.pdf`。仅在传了 `onImportDocument` 时生效。
|
|
52
|
+
*/
|
|
53
|
+
importAccept?: string;
|
|
54
|
+
/** 是否显示导入按钮,默认 `true`。卡片等场景可关掉。 */
|
|
55
|
+
showImport?: boolean;
|
|
26
56
|
labels?: Partial<ToolbarLabels>;
|
|
27
57
|
/** 追加到 More 菜单末尾的自定义项。 */
|
|
28
58
|
extraToolbarItems?: ExtraToolbarItem[];
|
|
@@ -32,4 +62,4 @@ export interface EditorToolbarProps {
|
|
|
32
62
|
* 顶部操作栏(antd-free,Radix Popover 菜单 + 内联 SVG 图标)。位置由父级控制,
|
|
33
63
|
* 这里只渲染按钮 + 反映 editor 激活态。不含业务耦合,扩展项经 extraToolbarItems 注入。
|
|
34
64
|
*/
|
|
35
|
-
export declare function EditorToolbar({ editor, onImageUpload, onError, labels, extraToolbarItems, className, }: EditorToolbarProps): import("react").JSX.Element;
|
|
65
|
+
export declare function EditorToolbar({ editor, onImageUpload, onError, onImportDocument, importAccept, showImport, labels, extraToolbarItems, className, }: EditorToolbarProps): import("react").JSX.Element;
|
package/dist/icons/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare const StrikethroughIcon: (p: IconProps) => import("react").JSX.El
|
|
|
17
17
|
export declare const CodeIcon: (p: IconProps) => import("react").JSX.Element;
|
|
18
18
|
export declare const LinkIcon: (p: IconProps) => import("react").JSX.Element;
|
|
19
19
|
export declare const ImageIcon: (p: IconProps) => import("react").JSX.Element;
|
|
20
|
+
export declare const ImportIcon: (p: IconProps) => import("react").JSX.Element;
|
|
20
21
|
export declare const ListUnorderedIcon: (p: IconProps) => import("react").JSX.Element;
|
|
21
22
|
export declare const ListOrderedIcon: (p: IconProps) => import("react").JSX.Element;
|
|
22
23
|
export declare const ListChecksIcon: (p: IconProps) => import("react").JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { MarkdownWysiwygEditor, type MarkdownWysiwygEditorHandle, type MarkdownWysiwygEditorProps, } from './components/MarkdownWysiwygEditor';
|
|
2
2
|
export { MarkdownPreview, type MarkdownPreviewProps, } from './components/MarkdownPreview';
|
|
3
|
-
export { EditorToolbar, type EditorToolbarProps, type ExtraToolbarItem, } from './components/EditorToolbar';
|
|
3
|
+
export { EditorToolbar, type EditorToolbarProps, type ExtraToolbarItem, type ImportDocumentContext, type ImportDocumentProgress, type ImportDocumentResult, } from './components/EditorToolbar';
|
|
4
4
|
export { ColorPalette, type ColorPaletteProps } from './components/ColorPalette';
|
|
5
5
|
export { TocPanel, type TocPanelProps } from './components/TocPanel';
|
|
6
6
|
export { CodeBlockView } from './components/CodeBlockView';
|
package/dist/index.js
CHANGED
|
@@ -327,10 +327,10 @@ function nextComment(editor, dir = "next") {
|
|
|
327
327
|
focusComment(editor, target);
|
|
328
328
|
return target;
|
|
329
329
|
}
|
|
330
|
-
const MD_FILE_RE = /\.(md|markdown)$/i;
|
|
330
|
+
const MD_FILE_RE$1 = /\.(md|markdown)$/i;
|
|
331
331
|
const MD_MIME_TYPES = ["text/markdown", "text/x-markdown", ""];
|
|
332
332
|
async function insertMarkdownFiles(editor, files, pos) {
|
|
333
|
-
const mdFiles = files.filter((f) => MD_FILE_RE.test(f.name));
|
|
333
|
+
const mdFiles = files.filter((f) => MD_FILE_RE$1.test(f.name));
|
|
334
334
|
if (mdFiles.length === 0) return;
|
|
335
335
|
const markdown = editor.markdown;
|
|
336
336
|
if (!markdown) return;
|
|
@@ -461,6 +461,11 @@ const ImageIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
|
461
461
|
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
|
|
462
462
|
/* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
|
|
463
463
|
] });
|
|
464
|
+
const ImportIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
465
|
+
/* @__PURE__ */ jsx("path", { d: "M12 3v12" }),
|
|
466
|
+
/* @__PURE__ */ jsx("path", { d: "m8 11 4 4 4-4" }),
|
|
467
|
+
/* @__PURE__ */ jsx("path", { d: "M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4" })
|
|
468
|
+
] });
|
|
464
469
|
const ListUnorderedIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
465
470
|
/* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "6", y2: "6" }),
|
|
466
471
|
/* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "12", y2: "12" }),
|
|
@@ -572,6 +577,12 @@ const defaultToolbarLabels = {
|
|
|
572
577
|
image: "Image",
|
|
573
578
|
imageUploadFailed: "Image upload failed",
|
|
574
579
|
importMarkdownFailed: "Markdown import failed",
|
|
580
|
+
importDocument: "Import",
|
|
581
|
+
importDocumentBusy: "Importing…",
|
|
582
|
+
importDocumentUploading: (percent) => `Uploading ${percent}%`,
|
|
583
|
+
importDocumentConverting: "Converting…",
|
|
584
|
+
importDocumentCancel: "Cancel",
|
|
585
|
+
importDocumentFailed: "Import failed",
|
|
575
586
|
blockquote: "Blockquote",
|
|
576
587
|
bulletList: "Bullet list",
|
|
577
588
|
orderedList: "Ordered list",
|
|
@@ -980,46 +991,84 @@ function MarkdownPreview({
|
|
|
980
991
|
}
|
|
981
992
|
function insertMarkdown(editor, markdown, sources = []) {
|
|
982
993
|
const prepared = enrichMarkdownCitations(markdown, sources);
|
|
983
|
-
|
|
994
|
+
if (!prepared) return;
|
|
995
|
+
if (tryInsertMarkdown(editor, prepared)) return;
|
|
996
|
+
for (const block of splitTopLevelBlocks(prepared)) {
|
|
997
|
+
if (tryInsertMarkdown(editor, block)) continue;
|
|
998
|
+
insertPlainParagraph(editor, stripToPlainText(block));
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
function tryInsertMarkdown(editor, markdown) {
|
|
1002
|
+
try {
|
|
1003
|
+
return editor.chain().focus().insertContent(markdown, { contentType: "markdown" }).run();
|
|
1004
|
+
} catch {
|
|
1005
|
+
return false;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
function insertPlainParagraph(editor, text) {
|
|
1009
|
+
if (!text) return;
|
|
1010
|
+
editor.chain().focus().insertContent({
|
|
1011
|
+
type: "paragraph",
|
|
1012
|
+
content: [{ type: "text", text }]
|
|
1013
|
+
}).run();
|
|
1014
|
+
}
|
|
1015
|
+
function splitTopLevelBlocks(markdown) {
|
|
1016
|
+
const out = [];
|
|
1017
|
+
for (const [i2, part] of markdown.split(/(```[\s\S]*?```)/).entries()) {
|
|
1018
|
+
if (!part) continue;
|
|
1019
|
+
if (i2 % 2 === 1) {
|
|
1020
|
+
out.push(part);
|
|
1021
|
+
continue;
|
|
1022
|
+
}
|
|
1023
|
+
for (const block of part.split(/\n{2,}/)) {
|
|
1024
|
+
if (block.trim()) out.push(block);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
return out;
|
|
984
1028
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
const
|
|
989
|
-
const
|
|
990
|
-
const
|
|
991
|
-
const
|
|
992
|
-
const
|
|
993
|
-
const
|
|
994
|
-
const
|
|
995
|
-
const
|
|
996
|
-
const
|
|
997
|
-
const
|
|
998
|
-
const
|
|
999
|
-
const
|
|
1000
|
-
const
|
|
1001
|
-
const
|
|
1002
|
-
const
|
|
1003
|
-
const
|
|
1004
|
-
const
|
|
1005
|
-
const
|
|
1006
|
-
const
|
|
1007
|
-
const
|
|
1008
|
-
const
|
|
1009
|
-
const
|
|
1010
|
-
const
|
|
1011
|
-
const
|
|
1012
|
-
const
|
|
1013
|
-
const
|
|
1014
|
-
const
|
|
1015
|
-
const
|
|
1016
|
-
const
|
|
1017
|
-
const
|
|
1029
|
+
function stripToPlainText(markdown) {
|
|
1030
|
+
return markdown.replace(/!\[[^\]]*\]\([^)]+\)/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/^#{1,6}\s+/gm, "").replace(/^[ \t]*[-*+]\s+/gm, "").replace(/^[ \t]*\d+\.\s+/gm, "").replace(/[*_~`]+/g, "").replace(/<[^>]+>/g, "").replace(/\|/g, " ").replace(/\s+/g, " ").trim();
|
|
1031
|
+
}
|
|
1032
|
+
const toolbar = "_toolbar_1ybhg_2";
|
|
1033
|
+
const inner = "_inner_1ybhg_15";
|
|
1034
|
+
const btn = "_btn_1ybhg_27";
|
|
1035
|
+
const btnActive = "_btnActive_1ybhg_50";
|
|
1036
|
+
const importCancel = "_importCancel_1ybhg_66";
|
|
1037
|
+
const tableBubble = "_tableBubble_1ybhg_85";
|
|
1038
|
+
const txtIcon = "_txtIcon_1ybhg_97";
|
|
1039
|
+
const colorIcon = "_colorIcon_1ybhg_105";
|
|
1040
|
+
const colorIconGlyph = "_colorIconGlyph_1ybhg_113";
|
|
1041
|
+
const colorIconBar = "_colorIconBar_1ybhg_119";
|
|
1042
|
+
const scriptTrigger = "_scriptTrigger_1ybhg_126";
|
|
1043
|
+
const scriptTriggerGlyph = "_scriptTriggerGlyph_1ybhg_146";
|
|
1044
|
+
const divider = "_divider_1ybhg_154";
|
|
1045
|
+
const styleTrigger = "_styleTrigger_1ybhg_163";
|
|
1046
|
+
const styleTriggerLabel = "_styleTriggerLabel_1ybhg_192";
|
|
1047
|
+
const styleTriggerCaret = "_styleTriggerCaret_1ybhg_200";
|
|
1048
|
+
const styleItem = "_styleItem_1ybhg_206";
|
|
1049
|
+
const styleIcon = "_styleIcon_1ybhg_212";
|
|
1050
|
+
const scriptGlyph = "_scriptGlyph_1ybhg_222";
|
|
1051
|
+
const menu = "_menu_1ybhg_234";
|
|
1052
|
+
const menuItem = "_menuItem_1ybhg_245";
|
|
1053
|
+
const menuItemSelected = "_menuItemSelected_1ybhg_271";
|
|
1054
|
+
const popoverContent$1 = "_popoverContent_1ybhg_285";
|
|
1055
|
+
const mathLayer = "_mathLayer_1ybhg_289";
|
|
1056
|
+
const mathStack = "_mathStack_1ybhg_294";
|
|
1057
|
+
const mathStackBlock = "_mathStackBlock_1ybhg_301";
|
|
1058
|
+
const mathHint = "_mathHint_1ybhg_306";
|
|
1059
|
+
const mathHintBlock = "_mathHintBlock_1ybhg_318";
|
|
1060
|
+
const mathHintIcon = "_mathHintIcon_1ybhg_324";
|
|
1061
|
+
const mathField = "_mathField_1ybhg_355";
|
|
1062
|
+
const mathFieldBlock = "_mathFieldBlock_1ybhg_367";
|
|
1063
|
+
const mathInput = "_mathInput_1ybhg_374";
|
|
1064
|
+
const mathDone = "_mathDone_1ybhg_392";
|
|
1065
|
+
const mathDoneKbd = "_mathDoneKbd_1ybhg_417";
|
|
1018
1066
|
const styles$3 = {
|
|
1019
1067
|
toolbar,
|
|
1020
1068
|
inner,
|
|
1021
1069
|
btn,
|
|
1022
1070
|
btnActive,
|
|
1071
|
+
importCancel,
|
|
1023
1072
|
tableBubble,
|
|
1024
1073
|
txtIcon,
|
|
1025
1074
|
colorIcon,
|
|
@@ -1356,6 +1405,7 @@ function ToolbarButton({
|
|
|
1356
1405
|
title,
|
|
1357
1406
|
active: active2,
|
|
1358
1407
|
disabled,
|
|
1408
|
+
busy,
|
|
1359
1409
|
onClick,
|
|
1360
1410
|
children
|
|
1361
1411
|
}) {
|
|
@@ -1366,6 +1416,7 @@ function ToolbarButton({
|
|
|
1366
1416
|
title,
|
|
1367
1417
|
"aria-label": title,
|
|
1368
1418
|
"aria-pressed": active2,
|
|
1419
|
+
"aria-busy": busy,
|
|
1369
1420
|
disabled,
|
|
1370
1421
|
className: `${styles$3.btn} ${active2 ? styles$3.btnActive : ""}`,
|
|
1371
1422
|
onMouseDown: (e) => e.preventDefault(),
|
|
@@ -1471,10 +1522,15 @@ function ColorPopover({
|
|
|
1471
1522
|
}
|
|
1472
1523
|
const HEADING_LEVELS = [1, 2, 3, 4, 5, 6];
|
|
1473
1524
|
const FONT_SIZES = ["12px", "14px", "16px", "18px", "20px", "24px", "30px"];
|
|
1525
|
+
const MD_FILE_RE = /\.(md|markdown)$/i;
|
|
1526
|
+
const MD_ACCEPT = ".md,.markdown,text/markdown";
|
|
1474
1527
|
function EditorToolbar({
|
|
1475
1528
|
editor,
|
|
1476
1529
|
onImageUpload,
|
|
1477
1530
|
onError,
|
|
1531
|
+
onImportDocument,
|
|
1532
|
+
importAccept,
|
|
1533
|
+
showImport = true,
|
|
1478
1534
|
labels,
|
|
1479
1535
|
extraToolbarItems,
|
|
1480
1536
|
className
|
|
@@ -1586,20 +1642,62 @@ function EditorToolbar({
|
|
|
1586
1642
|
onError == null ? void 0 : onError(err, "image");
|
|
1587
1643
|
}
|
|
1588
1644
|
};
|
|
1589
|
-
const
|
|
1590
|
-
const
|
|
1645
|
+
const importInputRef = useRef(null);
|
|
1646
|
+
const [importing, setImporting] = useState(
|
|
1647
|
+
null
|
|
1648
|
+
);
|
|
1649
|
+
const importAbortRef = useRef(null);
|
|
1650
|
+
useEffect(() => () => {
|
|
1651
|
+
var _a;
|
|
1652
|
+
return (_a = importAbortRef.current) == null ? void 0 : _a.abort();
|
|
1653
|
+
}, []);
|
|
1654
|
+
const handleImportChange = async (e) => {
|
|
1591
1655
|
var _a;
|
|
1592
1656
|
const file = (_a = e.target.files) == null ? void 0 : _a[0];
|
|
1593
1657
|
e.target.value = "";
|
|
1594
1658
|
if (!file) return;
|
|
1659
|
+
if (MD_FILE_RE.test(file.name)) {
|
|
1660
|
+
try {
|
|
1661
|
+
insertMarkdown(editor, await file.text());
|
|
1662
|
+
} catch (err) {
|
|
1663
|
+
console.error("markdown import failed:", err);
|
|
1664
|
+
onError == null ? void 0 : onError(err, "markdown");
|
|
1665
|
+
}
|
|
1666
|
+
return;
|
|
1667
|
+
}
|
|
1668
|
+
if (!onImportDocument) {
|
|
1669
|
+
onError == null ? void 0 : onError(new Error(`unsupported file: ${file.name}`), "import");
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
const ctrl = new AbortController();
|
|
1673
|
+
importAbortRef.current = ctrl;
|
|
1674
|
+
setImporting({ phase: "upload" });
|
|
1595
1675
|
try {
|
|
1596
|
-
const
|
|
1597
|
-
|
|
1676
|
+
const raw = await onImportDocument(file, {
|
|
1677
|
+
signal: ctrl.signal,
|
|
1678
|
+
onProgress: (p) => {
|
|
1679
|
+
if (!ctrl.signal.aborted) setImporting(p);
|
|
1680
|
+
}
|
|
1681
|
+
});
|
|
1682
|
+
const md = typeof raw === "string" ? raw : raw.markdown;
|
|
1683
|
+
const sources = typeof raw === "string" ? [] : raw.sources ?? [];
|
|
1684
|
+
insertMarkdown(editor, md, sources);
|
|
1598
1685
|
} catch (err) {
|
|
1599
|
-
|
|
1600
|
-
|
|
1686
|
+
if (!ctrl.signal.aborted) {
|
|
1687
|
+
console.error("document import failed:", err);
|
|
1688
|
+
onError == null ? void 0 : onError(err, "import");
|
|
1689
|
+
}
|
|
1690
|
+
} finally {
|
|
1691
|
+
if (importAbortRef.current === ctrl) importAbortRef.current = null;
|
|
1692
|
+
setImporting(null);
|
|
1601
1693
|
}
|
|
1602
1694
|
};
|
|
1695
|
+
const importTitle = (() => {
|
|
1696
|
+
if (!importing) return t.importDocument;
|
|
1697
|
+
if (importing.phase === "convert") return t.importDocumentConverting;
|
|
1698
|
+
const pct = Math.round((importing.ratio ?? 0) * 100);
|
|
1699
|
+
return t.importDocumentUploading(pct);
|
|
1700
|
+
})();
|
|
1603
1701
|
const applyTextColor = (color) => {
|
|
1604
1702
|
if (color) chain().setColor(color).run();
|
|
1605
1703
|
else chain().unsetColor().run();
|
|
@@ -1951,6 +2049,34 @@ function EditorToolbar({
|
|
|
1951
2049
|
}
|
|
1952
2050
|
)
|
|
1953
2051
|
] }) : null,
|
|
2052
|
+
showImport ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2053
|
+
/* @__PURE__ */ jsx(
|
|
2054
|
+
ToolbarButton,
|
|
2055
|
+
{
|
|
2056
|
+
title: importTitle,
|
|
2057
|
+
disabled: !!importing,
|
|
2058
|
+
busy: !!importing,
|
|
2059
|
+
onClick: () => {
|
|
2060
|
+
var _a;
|
|
2061
|
+
return (_a = importInputRef.current) == null ? void 0 : _a.click();
|
|
2062
|
+
},
|
|
2063
|
+
children: /* @__PURE__ */ jsx(ImportIcon, {})
|
|
2064
|
+
}
|
|
2065
|
+
),
|
|
2066
|
+
importing ? /* @__PURE__ */ jsx(
|
|
2067
|
+
"button",
|
|
2068
|
+
{
|
|
2069
|
+
type: "button",
|
|
2070
|
+
className: styles$3.importCancel,
|
|
2071
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
2072
|
+
onClick: () => {
|
|
2073
|
+
var _a;
|
|
2074
|
+
return (_a = importAbortRef.current) == null ? void 0 : _a.abort();
|
|
2075
|
+
},
|
|
2076
|
+
children: t.importDocumentCancel
|
|
2077
|
+
}
|
|
2078
|
+
) : null
|
|
2079
|
+
] }) : null,
|
|
1954
2080
|
/* @__PURE__ */ jsx(
|
|
1955
2081
|
ToolbarButton,
|
|
1956
2082
|
{
|
|
@@ -2033,13 +2159,6 @@ function EditorToolbar({
|
|
|
2033
2159
|
] })
|
|
2034
2160
|
}
|
|
2035
2161
|
),
|
|
2036
|
-
/* @__PURE__ */ jsx(MenuItem, { onSelect: () => {
|
|
2037
|
-
var _a;
|
|
2038
|
-
return (_a = mdFileInputRef.current) == null ? void 0 : _a.click();
|
|
2039
|
-
}, children: /* @__PURE__ */ jsxs("span", { className: styles$3.styleItem, children: [
|
|
2040
|
-
/* @__PURE__ */ jsx("span", { className: styles$3.styleIcon, children: "M↓" }),
|
|
2041
|
-
t.importMarkdown
|
|
2042
|
-
] }) }),
|
|
2043
2162
|
extraToolbarItems == null ? void 0 : extraToolbarItems.map((item2) => /* @__PURE__ */ jsx(
|
|
2044
2163
|
MenuItem,
|
|
2045
2164
|
{
|
|
@@ -2058,16 +2177,16 @@ function EditorToolbar({
|
|
|
2058
2177
|
] })
|
|
2059
2178
|
}
|
|
2060
2179
|
),
|
|
2061
|
-
/* @__PURE__ */ jsx(
|
|
2180
|
+
showImport ? /* @__PURE__ */ jsx(
|
|
2062
2181
|
"input",
|
|
2063
2182
|
{
|
|
2064
|
-
ref:
|
|
2183
|
+
ref: importInputRef,
|
|
2065
2184
|
type: "file",
|
|
2066
|
-
accept:
|
|
2185
|
+
accept: onImportDocument && importAccept ? `${MD_ACCEPT},${importAccept}` : MD_ACCEPT,
|
|
2067
2186
|
hidden: true,
|
|
2068
|
-
onChange:
|
|
2187
|
+
onChange: handleImportChange
|
|
2069
2188
|
}
|
|
2070
|
-
),
|
|
2189
|
+
) : null,
|
|
2071
2190
|
mathEdit ? /* @__PURE__ */ jsx(
|
|
2072
2191
|
MathEditorPopover,
|
|
2073
2192
|
{
|
|
@@ -2481,6 +2600,7 @@ export {
|
|
|
2481
2600
|
CommentPopover,
|
|
2482
2601
|
EditorToolbar,
|
|
2483
2602
|
ImageIcon,
|
|
2603
|
+
ImportIcon,
|
|
2484
2604
|
ItalicIcon,
|
|
2485
2605
|
LinkIcon,
|
|
2486
2606
|
ListChecksIcon,
|