tiptap-markdown-react 0.8.8 → 0.8.10

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/index.js CHANGED
@@ -6,10 +6,10 @@ import Image from "@tiptap/extension-image";
6
6
  import { TableOfContents } from "@tiptap/extension-table-of-contents";
7
7
  import { NodeViewWrapper, ReactNodeViewRenderer, NodeViewContent, useEditor, EditorContent, useEditorState } from "@tiptap/react";
8
8
  import { forwardRef, useEffect, useRef, useImperativeHandle, useMemo, useState, useId, useCallback, useContext, createContext } from "react";
9
- import { C as CitationRef, m as mergeCommentIntervals, a as mapCommentAnchors, e as enrichMarkdownCitations, s as styles$5, b as baseExtensions, c as CommentMark, l as lowlight, d as makeTocGetId, p as pureCodeBlock, f as pureImage, r as renderMathInto, g as subscribeMathClick, R as ReportContent } from "./extractToc-Dft8DJ1g.js";
10
- import { h, i, j, k } from "./extractToc-Dft8DJ1g.js";
9
+ import { C as CitationRef, m as mergeCommentIntervals, a as mapCommentAnchors, e as enrichMarkdownCitations, s as styles$5, b as baseExtensions, c as CommentMark, l as lowlight, d as makeTocGetId, p as pureCodeBlock, f as pureImage, r as renderMathInto, g as subscribeMathClick, R as ReportContent } from "./extractToc-DiY1iu1J.js";
10
+ import { h, i, j, k } from "./extractToc-DiY1iu1J.js";
11
11
  import { Slice, Fragment } from "@tiptap/pm/model";
12
- import { Extension } from "@tiptap/core";
12
+ import { Extension, Node as Node$1 } from "@tiptap/core";
13
13
  import { PluginKey, Plugin } from "@tiptap/pm/state";
14
14
  import { DecorationSet, Decoration } from "@tiptap/pm/view";
15
15
  import { FileHandlePlugin } from "@tiptap/extension-file-handler";
@@ -327,6 +327,88 @@ function nextComment(editor, dir = "next") {
327
327
  focusComment(editor, target);
328
328
  return target;
329
329
  }
330
+ function findPlaceholderPos(doc) {
331
+ let found = null;
332
+ doc.descendants((node, pos) => {
333
+ if (node.type.name === "importPlaceholder") {
334
+ found = pos;
335
+ return false;
336
+ }
337
+ });
338
+ return found;
339
+ }
340
+ const ImportPlaceholder = Node$1.create({
341
+ name: "importPlaceholder",
342
+ group: "block",
343
+ atom: true,
344
+ selectable: false,
345
+ draggable: false,
346
+ addAttributes() {
347
+ return {
348
+ label: {
349
+ default: "",
350
+ parseHTML: (el) => el.getAttribute("data-label") ?? "",
351
+ renderHTML: (attrs) => attrs.label ? { "data-label": attrs.label } : {}
352
+ }
353
+ };
354
+ },
355
+ parseHTML() {
356
+ return [{ tag: 'div[data-type="import-placeholder"]' }];
357
+ },
358
+ renderHTML({ node, HTMLAttributes }) {
359
+ const label = String(node.attrs.label ?? "");
360
+ return [
361
+ "div",
362
+ {
363
+ ...HTMLAttributes,
364
+ "data-type": "import-placeholder",
365
+ class: "tmr-import-placeholder",
366
+ contenteditable: "false",
367
+ "aria-live": "polite",
368
+ "aria-busy": "true"
369
+ },
370
+ ["span", { class: "tmr-import-placeholder-spin", "aria-hidden": "true" }],
371
+ ["span", { class: "tmr-import-placeholder-label" }, label]
372
+ ];
373
+ },
374
+ renderMarkdown() {
375
+ return "";
376
+ },
377
+ addCommands() {
378
+ return {
379
+ insertImportPlaceholder: (label) => ({ chain }) => chain().focus().insertContent({
380
+ type: this.name,
381
+ attrs: { label }
382
+ }).command(({ tr }) => {
383
+ tr.setMeta("addToHistory", false);
384
+ tr.setMeta("preventUpdate", true);
385
+ return true;
386
+ }).run(),
387
+ updateImportPlaceholder: (label) => ({ tr, dispatch, state }) => {
388
+ const pos = findPlaceholderPos(state.doc);
389
+ if (pos == null) return false;
390
+ if (dispatch) {
391
+ dispatch(
392
+ tr.setNodeMarkup(pos, void 0, { label }).setMeta("addToHistory", false).setMeta("preventUpdate", true)
393
+ );
394
+ }
395
+ return true;
396
+ },
397
+ removeImportPlaceholder: () => ({ tr, dispatch, state }) => {
398
+ const pos = findPlaceholderPos(state.doc);
399
+ if (pos == null) return false;
400
+ const node = state.doc.nodeAt(pos);
401
+ if (!node) return false;
402
+ if (dispatch) {
403
+ dispatch(
404
+ tr.delete(pos, pos + node.nodeSize).setMeta("addToHistory", false).setMeta("preventUpdate", true)
405
+ );
406
+ }
407
+ return true;
408
+ }
409
+ };
410
+ }
411
+ });
330
412
  const MD_FILE_RE$1 = /\.(md|markdown)$/i;
331
413
  const MD_MIME_TYPES = ["text/markdown", "text/x-markdown", ""];
332
414
  async function insertMarkdownFiles(editor, files, pos) {
@@ -578,10 +660,11 @@ const defaultToolbarLabels = {
578
660
  imageUploadFailed: "Image upload failed",
579
661
  importMarkdownFailed: "Markdown import failed",
580
662
  importDocument: "Import",
663
+ importDocumentHint: "Import a file",
664
+ importDocumentOther: "Document",
581
665
  importDocumentBusy: "Importing…",
582
666
  importDocumentUploading: (percent) => `Uploading ${percent}%`,
583
667
  importDocumentConverting: "Converting…",
584
- importDocumentCancel: "Cancel",
585
668
  importDocumentFailed: "Import failed",
586
669
  blockquote: "Blockquote",
587
670
  bulletList: "Bullet list",
@@ -590,7 +673,7 @@ const defaultToolbarLabels = {
590
673
  more: "More",
591
674
  codeBlock: "Code block",
592
675
  hr: "Divider",
593
- importMarkdown: "Import Markdown",
676
+ importMarkdown: "Markdown",
594
677
  tableInsert: "Insert table",
595
678
  tableAddColumnBefore: "Add column before",
596
679
  tableAddColumnAfter: "Add column after",
@@ -829,6 +912,7 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
829
912
  ...baseExtensions,
830
913
  CodeBlock.configure({ lowlight, codeBlockLabels }),
831
914
  ImageWithConfirmDelete.configure({ inline: false }),
915
+ ImportPlaceholder,
832
916
  createCitationRef({ renderCitation }),
833
917
  CommentMark,
834
918
  commentAnchorExtension({
@@ -989,6 +1073,32 @@ function MarkdownPreview({
989
1073
  }
990
1074
  );
991
1075
  }
1076
+ const MD_FILE_RE = /\.(md|markdown)$/i;
1077
+ const MD_ACCEPT = ".md,.markdown,text/markdown";
1078
+ function resolveImportMenuItems({
1079
+ labels,
1080
+ onImportDocument,
1081
+ importAccept,
1082
+ importMenuItems
1083
+ }) {
1084
+ if (importMenuItems == null ? void 0 : importMenuItems.length) return importMenuItems;
1085
+ const markdown = {
1086
+ key: "markdown",
1087
+ label: labels.importMarkdown,
1088
+ accept: MD_ACCEPT
1089
+ };
1090
+ if (onImportDocument && importAccept) {
1091
+ return [
1092
+ markdown,
1093
+ {
1094
+ key: "document",
1095
+ label: labels.importDocumentOther,
1096
+ accept: importAccept
1097
+ }
1098
+ ];
1099
+ }
1100
+ return [markdown];
1101
+ }
992
1102
  function insertMarkdown(editor, markdown, sources = []) {
993
1103
  const prepared = enrichMarkdownCitations(markdown, sources);
994
1104
  if (!prepared) return;
@@ -1029,46 +1139,44 @@ function splitTopLevelBlocks(markdown) {
1029
1139
  function stripToPlainText(markdown) {
1030
1140
  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
1141
  }
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";
1142
+ const toolbar = "_toolbar_16b09_2";
1143
+ const inner = "_inner_16b09_15";
1144
+ const btn = "_btn_16b09_27";
1145
+ const btnActive = "_btnActive_16b09_50";
1146
+ const tableBubble = "_tableBubble_16b09_66";
1147
+ const txtIcon = "_txtIcon_16b09_78";
1148
+ const colorIcon = "_colorIcon_16b09_86";
1149
+ const colorIconGlyph = "_colorIconGlyph_16b09_94";
1150
+ const colorIconBar = "_colorIconBar_16b09_100";
1151
+ const scriptTrigger = "_scriptTrigger_16b09_107";
1152
+ const scriptTriggerGlyph = "_scriptTriggerGlyph_16b09_127";
1153
+ const divider = "_divider_16b09_135";
1154
+ const styleTrigger = "_styleTrigger_16b09_144";
1155
+ const styleTriggerLabel = "_styleTriggerLabel_16b09_173";
1156
+ const styleTriggerCaret = "_styleTriggerCaret_16b09_181";
1157
+ const styleItem = "_styleItem_16b09_187";
1158
+ const styleIcon = "_styleIcon_16b09_193";
1159
+ const scriptGlyph = "_scriptGlyph_16b09_203";
1160
+ const menu = "_menu_16b09_215";
1161
+ const menuItem = "_menuItem_16b09_226";
1162
+ const menuItemSelected = "_menuItemSelected_16b09_252";
1163
+ const popoverContent$1 = "_popoverContent_16b09_266";
1164
+ const mathLayer = "_mathLayer_16b09_270";
1165
+ const mathStack = "_mathStack_16b09_275";
1166
+ const mathStackBlock = "_mathStackBlock_16b09_282";
1167
+ const mathHint = "_mathHint_16b09_287";
1168
+ const mathHintBlock = "_mathHintBlock_16b09_299";
1169
+ const mathHintIcon = "_mathHintIcon_16b09_305";
1170
+ const mathField = "_mathField_16b09_336";
1171
+ const mathFieldBlock = "_mathFieldBlock_16b09_348";
1172
+ const mathInput = "_mathInput_16b09_355";
1173
+ const mathDone = "_mathDone_16b09_373";
1174
+ const mathDoneKbd = "_mathDoneKbd_16b09_398";
1066
1175
  const styles$3 = {
1067
1176
  toolbar,
1068
1177
  inner,
1069
1178
  btn,
1070
1179
  btnActive,
1071
- importCancel,
1072
1180
  tableBubble,
1073
1181
  txtIcon,
1074
1182
  colorIcon,
@@ -1522,14 +1630,13 @@ function ColorPopover({
1522
1630
  }
1523
1631
  const HEADING_LEVELS = [1, 2, 3, 4, 5, 6];
1524
1632
  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";
1527
1633
  function EditorToolbar({
1528
1634
  editor,
1529
1635
  onImageUpload,
1530
1636
  onError,
1531
1637
  onImportDocument,
1532
1638
  importAccept,
1639
+ importMenuItems,
1533
1640
  showImport = true,
1534
1641
  labels,
1535
1642
  extraToolbarItems,
@@ -1671,18 +1778,24 @@ function EditorToolbar({
1671
1778
  }
1672
1779
  const ctrl = new AbortController();
1673
1780
  importAbortRef.current = ctrl;
1674
- setImporting({ phase: "upload" });
1781
+ setImporting({ phase: "upload", ratio: 0 });
1782
+ const labelOf = (p) => p.phase === "convert" ? t.importDocumentConverting : t.importDocumentUploading(Math.round((p.ratio ?? 0) * 100));
1783
+ editor.commands.insertImportPlaceholder(labelOf({ phase: "upload", ratio: 0 }));
1675
1784
  try {
1676
1785
  const raw = await onImportDocument(file, {
1677
1786
  signal: ctrl.signal,
1678
1787
  onProgress: (p) => {
1679
- if (!ctrl.signal.aborted) setImporting(p);
1788
+ if (ctrl.signal.aborted) return;
1789
+ setImporting(p);
1790
+ editor.commands.updateImportPlaceholder(labelOf(p));
1680
1791
  }
1681
1792
  });
1793
+ editor.commands.removeImportPlaceholder();
1682
1794
  const md = typeof raw === "string" ? raw : raw.markdown;
1683
1795
  const sources = typeof raw === "string" ? [] : raw.sources ?? [];
1684
1796
  insertMarkdown(editor, md, sources);
1685
1797
  } catch (err) {
1798
+ editor.commands.removeImportPlaceholder();
1686
1799
  if (!ctrl.signal.aborted) {
1687
1800
  console.error("document import failed:", err);
1688
1801
  onError == null ? void 0 : onError(err, "import");
@@ -1692,12 +1805,20 @@ function EditorToolbar({
1692
1805
  setImporting(null);
1693
1806
  }
1694
1807
  };
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
- })();
1808
+ const importItems = resolveImportMenuItems({
1809
+ labels: t,
1810
+ onImportDocument,
1811
+ importAccept,
1812
+ importMenuItems
1813
+ });
1814
+ const pickImport = (accept) => {
1815
+ const input = importInputRef.current;
1816
+ if (!input) return;
1817
+ input.accept = accept;
1818
+ input.value = "";
1819
+ input.click();
1820
+ };
1821
+ const importTitle = importing ? t.importDocumentBusy : t.importDocumentHint;
1701
1822
  const applyTextColor = (color) => {
1702
1823
  if (color) chain().setColor(color).run();
1703
1824
  else chain().unsetColor().run();
@@ -2049,34 +2170,41 @@ function EditorToolbar({
2049
2170
  }
2050
2171
  )
2051
2172
  ] }) : 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();
2173
+ showImport ? /* @__PURE__ */ jsx(
2174
+ MenuPopover,
2175
+ {
2176
+ trigger: /* @__PURE__ */ jsxs(
2177
+ "button",
2178
+ {
2179
+ type: "button",
2180
+ className: styles$3.styleTrigger,
2181
+ title: importTitle,
2182
+ "aria-label": importTitle,
2183
+ "aria-busy": !!importing,
2184
+ disabled: !!importing,
2185
+ onMouseDown: (e) => e.preventDefault(),
2186
+ children: [
2187
+ /* @__PURE__ */ jsx("span", { className: styles$3.styleTriggerLabel, children: t.importDocument }),
2188
+ /* @__PURE__ */ jsx(
2189
+ ChevronDownIcon,
2190
+ {
2191
+ size: 12,
2192
+ className: styles$3.styleTriggerCaret
2193
+ }
2194
+ )
2195
+ ]
2196
+ }
2197
+ ),
2198
+ children: importItems.map((item2) => /* @__PURE__ */ jsx(
2199
+ MenuItem,
2200
+ {
2201
+ onSelect: () => pickImport(item2.accept),
2202
+ children: item2.label
2075
2203
  },
2076
- children: t.importDocumentCancel
2077
- }
2078
- ) : null
2079
- ] }) : null,
2204
+ item2.key
2205
+ ))
2206
+ }
2207
+ ) : null,
2080
2208
  /* @__PURE__ */ jsx(
2081
2209
  ToolbarButton,
2082
2210
  {
@@ -2182,7 +2310,6 @@ function EditorToolbar({
2182
2310
  {
2183
2311
  ref: importInputRef,
2184
2312
  type: "file",
2185
- accept: onImportDocument && importAccept ? `${MD_ACCEPT},${importAccept}` : MD_ACCEPT,
2186
2313
  hidden: true,
2187
2314
  onChange: handleImportChange
2188
2315
  }
@@ -2601,6 +2728,7 @@ export {
2601
2728
  EditorToolbar,
2602
2729
  ImageIcon,
2603
2730
  ImportIcon,
2731
+ ImportPlaceholder,
2604
2732
  ItalicIcon,
2605
2733
  LinkIcon,
2606
2734
  ListChecksIcon,