tiptap-markdown-react 0.8.6 → 0.8.7

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 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** — "Import Markdown" in the toolbar's More menu opens a file picker and inserts the parsed file at the cursor (label: `labels.importMarkdown`).
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: unknown) => void` | Side-effect error callback (e.g. failed upload). |
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;
@@ -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,10 @@ 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
+ importDocumentCancel: "Cancel",
583
+ importDocumentFailed: "Import failed",
575
584
  blockquote: "Blockquote",
576
585
  bulletList: "Bullet list",
577
586
  orderedList: "Ordered list",
@@ -980,46 +989,84 @@ function MarkdownPreview({
980
989
  }
981
990
  function insertMarkdown(editor, markdown, sources = []) {
982
991
  const prepared = enrichMarkdownCitations(markdown, sources);
983
- editor.chain().focus().insertContent(prepared, { contentType: "markdown" }).run();
992
+ if (!prepared) return;
993
+ if (tryInsertMarkdown(editor, prepared)) return;
994
+ for (const block of splitTopLevelBlocks(prepared)) {
995
+ if (tryInsertMarkdown(editor, block)) continue;
996
+ insertPlainParagraph(editor, stripToPlainText(block));
997
+ }
998
+ }
999
+ function tryInsertMarkdown(editor, markdown) {
1000
+ try {
1001
+ return editor.chain().focus().insertContent(markdown, { contentType: "markdown" }).run();
1002
+ } catch {
1003
+ return false;
1004
+ }
1005
+ }
1006
+ function insertPlainParagraph(editor, text) {
1007
+ if (!text) return;
1008
+ editor.chain().focus().insertContent({
1009
+ type: "paragraph",
1010
+ content: [{ type: "text", text }]
1011
+ }).run();
1012
+ }
1013
+ function splitTopLevelBlocks(markdown) {
1014
+ const out = [];
1015
+ for (const [i2, part] of markdown.split(/(```[\s\S]*?```)/).entries()) {
1016
+ if (!part) continue;
1017
+ if (i2 % 2 === 1) {
1018
+ out.push(part);
1019
+ continue;
1020
+ }
1021
+ for (const block of part.split(/\n{2,}/)) {
1022
+ if (block.trim()) out.push(block);
1023
+ }
1024
+ }
1025
+ return out;
984
1026
  }
985
- const toolbar = "_toolbar_16b09_2";
986
- const inner = "_inner_16b09_15";
987
- const btn = "_btn_16b09_27";
988
- const btnActive = "_btnActive_16b09_50";
989
- const tableBubble = "_tableBubble_16b09_66";
990
- const txtIcon = "_txtIcon_16b09_78";
991
- const colorIcon = "_colorIcon_16b09_86";
992
- const colorIconGlyph = "_colorIconGlyph_16b09_94";
993
- const colorIconBar = "_colorIconBar_16b09_100";
994
- const scriptTrigger = "_scriptTrigger_16b09_107";
995
- const scriptTriggerGlyph = "_scriptTriggerGlyph_16b09_127";
996
- const divider = "_divider_16b09_135";
997
- const styleTrigger = "_styleTrigger_16b09_144";
998
- const styleTriggerLabel = "_styleTriggerLabel_16b09_173";
999
- const styleTriggerCaret = "_styleTriggerCaret_16b09_181";
1000
- const styleItem = "_styleItem_16b09_187";
1001
- const styleIcon = "_styleIcon_16b09_193";
1002
- const scriptGlyph = "_scriptGlyph_16b09_203";
1003
- const menu = "_menu_16b09_215";
1004
- const menuItem = "_menuItem_16b09_226";
1005
- const menuItemSelected = "_menuItemSelected_16b09_252";
1006
- const popoverContent$1 = "_popoverContent_16b09_266";
1007
- const mathLayer = "_mathLayer_16b09_270";
1008
- const mathStack = "_mathStack_16b09_275";
1009
- const mathStackBlock = "_mathStackBlock_16b09_282";
1010
- const mathHint = "_mathHint_16b09_287";
1011
- const mathHintBlock = "_mathHintBlock_16b09_299";
1012
- const mathHintIcon = "_mathHintIcon_16b09_305";
1013
- const mathField = "_mathField_16b09_336";
1014
- const mathFieldBlock = "_mathFieldBlock_16b09_348";
1015
- const mathInput = "_mathInput_16b09_355";
1016
- const mathDone = "_mathDone_16b09_373";
1017
- const mathDoneKbd = "_mathDoneKbd_16b09_398";
1027
+ function stripToPlainText(markdown) {
1028
+ 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();
1029
+ }
1030
+ const toolbar = "_toolbar_1ybhg_2";
1031
+ const inner = "_inner_1ybhg_15";
1032
+ const btn = "_btn_1ybhg_27";
1033
+ const btnActive = "_btnActive_1ybhg_50";
1034
+ const importCancel = "_importCancel_1ybhg_66";
1035
+ const tableBubble = "_tableBubble_1ybhg_85";
1036
+ const txtIcon = "_txtIcon_1ybhg_97";
1037
+ const colorIcon = "_colorIcon_1ybhg_105";
1038
+ const colorIconGlyph = "_colorIconGlyph_1ybhg_113";
1039
+ const colorIconBar = "_colorIconBar_1ybhg_119";
1040
+ const scriptTrigger = "_scriptTrigger_1ybhg_126";
1041
+ const scriptTriggerGlyph = "_scriptTriggerGlyph_1ybhg_146";
1042
+ const divider = "_divider_1ybhg_154";
1043
+ const styleTrigger = "_styleTrigger_1ybhg_163";
1044
+ const styleTriggerLabel = "_styleTriggerLabel_1ybhg_192";
1045
+ const styleTriggerCaret = "_styleTriggerCaret_1ybhg_200";
1046
+ const styleItem = "_styleItem_1ybhg_206";
1047
+ const styleIcon = "_styleIcon_1ybhg_212";
1048
+ const scriptGlyph = "_scriptGlyph_1ybhg_222";
1049
+ const menu = "_menu_1ybhg_234";
1050
+ const menuItem = "_menuItem_1ybhg_245";
1051
+ const menuItemSelected = "_menuItemSelected_1ybhg_271";
1052
+ const popoverContent$1 = "_popoverContent_1ybhg_285";
1053
+ const mathLayer = "_mathLayer_1ybhg_289";
1054
+ const mathStack = "_mathStack_1ybhg_294";
1055
+ const mathStackBlock = "_mathStackBlock_1ybhg_301";
1056
+ const mathHint = "_mathHint_1ybhg_306";
1057
+ const mathHintBlock = "_mathHintBlock_1ybhg_318";
1058
+ const mathHintIcon = "_mathHintIcon_1ybhg_324";
1059
+ const mathField = "_mathField_1ybhg_355";
1060
+ const mathFieldBlock = "_mathFieldBlock_1ybhg_367";
1061
+ const mathInput = "_mathInput_1ybhg_374";
1062
+ const mathDone = "_mathDone_1ybhg_392";
1063
+ const mathDoneKbd = "_mathDoneKbd_1ybhg_417";
1018
1064
  const styles$3 = {
1019
1065
  toolbar,
1020
1066
  inner,
1021
1067
  btn,
1022
1068
  btnActive,
1069
+ importCancel,
1023
1070
  tableBubble,
1024
1071
  txtIcon,
1025
1072
  colorIcon,
@@ -1356,6 +1403,7 @@ function ToolbarButton({
1356
1403
  title,
1357
1404
  active: active2,
1358
1405
  disabled,
1406
+ busy,
1359
1407
  onClick,
1360
1408
  children
1361
1409
  }) {
@@ -1366,6 +1414,7 @@ function ToolbarButton({
1366
1414
  title,
1367
1415
  "aria-label": title,
1368
1416
  "aria-pressed": active2,
1417
+ "aria-busy": busy,
1369
1418
  disabled,
1370
1419
  className: `${styles$3.btn} ${active2 ? styles$3.btnActive : ""}`,
1371
1420
  onMouseDown: (e) => e.preventDefault(),
@@ -1471,10 +1520,15 @@ function ColorPopover({
1471
1520
  }
1472
1521
  const HEADING_LEVELS = [1, 2, 3, 4, 5, 6];
1473
1522
  const FONT_SIZES = ["12px", "14px", "16px", "18px", "20px", "24px", "30px"];
1523
+ const MD_FILE_RE = /\.(md|markdown)$/i;
1524
+ const MD_ACCEPT = ".md,.markdown,text/markdown";
1474
1525
  function EditorToolbar({
1475
1526
  editor,
1476
1527
  onImageUpload,
1477
1528
  onError,
1529
+ onImportDocument,
1530
+ importAccept,
1531
+ showImport = true,
1478
1532
  labels,
1479
1533
  extraToolbarItems,
1480
1534
  className
@@ -1586,20 +1640,61 @@ function EditorToolbar({
1586
1640
  onError == null ? void 0 : onError(err, "image");
1587
1641
  }
1588
1642
  };
1589
- const mdFileInputRef = useRef(null);
1590
- const handleMdFileChange = async (e) => {
1643
+ const importInputRef = useRef(null);
1644
+ const [importing, setImporting] = useState(
1645
+ null
1646
+ );
1647
+ const importAbortRef = useRef(null);
1648
+ useEffect(() => () => {
1649
+ var _a;
1650
+ return (_a = importAbortRef.current) == null ? void 0 : _a.abort();
1651
+ }, []);
1652
+ const handleImportChange = async (e) => {
1591
1653
  var _a;
1592
1654
  const file = (_a = e.target.files) == null ? void 0 : _a[0];
1593
1655
  e.target.value = "";
1594
1656
  if (!file) return;
1657
+ if (MD_FILE_RE.test(file.name)) {
1658
+ try {
1659
+ insertMarkdown(editor, await file.text());
1660
+ } catch (err) {
1661
+ console.error("markdown import failed:", err);
1662
+ onError == null ? void 0 : onError(err, "markdown");
1663
+ }
1664
+ return;
1665
+ }
1666
+ if (!onImportDocument) {
1667
+ onError == null ? void 0 : onError(new Error(`unsupported file: ${file.name}`), "import");
1668
+ return;
1669
+ }
1670
+ const ctrl = new AbortController();
1671
+ importAbortRef.current = ctrl;
1672
+ setImporting({ phase: "upload" });
1595
1673
  try {
1596
- const text = await file.text();
1597
- insertMarkdown(editor, text);
1674
+ const raw = await onImportDocument(file, {
1675
+ signal: ctrl.signal,
1676
+ onProgress: (p) => {
1677
+ if (!ctrl.signal.aborted) setImporting(p);
1678
+ }
1679
+ });
1680
+ const md = typeof raw === "string" ? raw : raw.markdown;
1681
+ const sources = typeof raw === "string" ? [] : raw.sources ?? [];
1682
+ insertMarkdown(editor, md, sources);
1598
1683
  } catch (err) {
1599
- console.error("markdown import failed:", err);
1600
- onError == null ? void 0 : onError(err, "markdown");
1684
+ if (!ctrl.signal.aborted) {
1685
+ console.error("document import failed:", err);
1686
+ onError == null ? void 0 : onError(err, "import");
1687
+ }
1688
+ } finally {
1689
+ if (importAbortRef.current === ctrl) importAbortRef.current = null;
1690
+ setImporting(null);
1601
1691
  }
1602
1692
  };
1693
+ const importTitle = (() => {
1694
+ if (!importing) return t.importDocument;
1695
+ const pct = importing.phase === "upload" && importing.ratio != null ? ` ${Math.round(importing.ratio * 100)}%` : "";
1696
+ return `${t.importDocumentBusy}${pct}`;
1697
+ })();
1603
1698
  const applyTextColor = (color) => {
1604
1699
  if (color) chain().setColor(color).run();
1605
1700
  else chain().unsetColor().run();
@@ -1951,6 +2046,34 @@ function EditorToolbar({
1951
2046
  }
1952
2047
  )
1953
2048
  ] }) : null,
2049
+ showImport ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
2050
+ /* @__PURE__ */ jsx(
2051
+ ToolbarButton,
2052
+ {
2053
+ title: importTitle,
2054
+ disabled: !!importing,
2055
+ busy: !!importing,
2056
+ onClick: () => {
2057
+ var _a;
2058
+ return (_a = importInputRef.current) == null ? void 0 : _a.click();
2059
+ },
2060
+ children: /* @__PURE__ */ jsx(ImportIcon, {})
2061
+ }
2062
+ ),
2063
+ importing ? /* @__PURE__ */ jsx(
2064
+ "button",
2065
+ {
2066
+ type: "button",
2067
+ className: styles$3.importCancel,
2068
+ onMouseDown: (e) => e.preventDefault(),
2069
+ onClick: () => {
2070
+ var _a;
2071
+ return (_a = importAbortRef.current) == null ? void 0 : _a.abort();
2072
+ },
2073
+ children: t.importDocumentCancel
2074
+ }
2075
+ ) : null
2076
+ ] }) : null,
1954
2077
  /* @__PURE__ */ jsx(
1955
2078
  ToolbarButton,
1956
2079
  {
@@ -2033,13 +2156,6 @@ function EditorToolbar({
2033
2156
  ] })
2034
2157
  }
2035
2158
  ),
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
2159
  extraToolbarItems == null ? void 0 : extraToolbarItems.map((item2) => /* @__PURE__ */ jsx(
2044
2160
  MenuItem,
2045
2161
  {
@@ -2058,16 +2174,16 @@ function EditorToolbar({
2058
2174
  ] })
2059
2175
  }
2060
2176
  ),
2061
- /* @__PURE__ */ jsx(
2177
+ showImport ? /* @__PURE__ */ jsx(
2062
2178
  "input",
2063
2179
  {
2064
- ref: mdFileInputRef,
2180
+ ref: importInputRef,
2065
2181
  type: "file",
2066
- accept: ".md,.markdown,text/markdown",
2182
+ accept: onImportDocument && importAccept ? `${MD_ACCEPT},${importAccept}` : MD_ACCEPT,
2067
2183
  hidden: true,
2068
- onChange: handleMdFileChange
2184
+ onChange: handleImportChange
2069
2185
  }
2070
- ),
2186
+ ) : null,
2071
2187
  mathEdit ? /* @__PURE__ */ jsx(
2072
2188
  MathEditorPopover,
2073
2189
  {
@@ -2481,6 +2597,7 @@ export {
2481
2597
  CommentPopover,
2482
2598
  EditorToolbar,
2483
2599
  ImageIcon,
2600
+ ImportIcon,
2484
2601
  ItalicIcon,
2485
2602
  LinkIcon,
2486
2603
  ListChecksIcon,