tiptap-markdown-react 0.12.1 → 0.14.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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { Markdown, MarkdownManager } from "@tiptap/markdown";
3
- import { c as renderOrUpdateChart, d as destroyChart } from "./scrollToTocHeading-DVdii3VR.js";
4
- import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-DVdii3VR.js";
3
+ import { c as renderOrUpdateChart, d as destroyChart } from "./scrollToTocHeading-DKL19FQG.js";
4
+ import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-DKL19FQG.js";
5
5
  import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
6
6
  import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
7
7
  import FindAndReplace, { FindAndReplacePluginKey, createSearchRegex } from "@tiptap/extension-find-and-replace";
@@ -11,10 +11,10 @@ import { TableOfContents } from "@tiptap/extension-table-of-contents";
11
11
  import { NodeViewWrapper, ReactNodeViewRenderer, useEditorState, NodeViewContent, useEditor, EditorContent } from "@tiptap/react";
12
12
  import { createPortal } from "react-dom";
13
13
  import { useState, useEffect, useCallback, useRef, useMemo, forwardRef, useImperativeHandle, useId, useContext, createContext } from "react";
14
- import { e as enrichMarkdownCitations, b as styles$6 } from "./ReportContent-CfvE4CYH.js";
15
- import { R as R2, a as a2, s as s2 } from "./ReportContent-CfvE4CYH.js";
16
- import { C as CitationRef, i as mergeCommentIntervals, h as mapCommentAnchors, p as prepareChartMarkdown, j as reportChart, b as baseExtensions, f as CommentMark, l as lowlight, m as makeTocGetId, k as parseCodeTokenAsChartOrCodeBlock, a as pureCodeBlock, c as pureImage, n as renderMathInto, o as subscribeMathClick, d as pureChart } from "./extractToc-BT3OquOq.js";
17
- import { g, e, s as s3 } from "./extractToc-BT3OquOq.js";
14
+ import { e as enrichMarkdownCitations, c as styles$6 } from "./ReportContent-DxldXfpO.js";
15
+ import { R as R2, a as a2, b as b2, s as s2 } from "./ReportContent-DxldXfpO.js";
16
+ import { C as CitationRef, i as mergeCommentIntervals, h as mapCommentAnchors, p as prepareChartMarkdown, j as reportChart, b as baseExtensions, f as CommentMark, l as lowlight, m as makeTocGetId, k as parseCodeTokenAsChartOrCodeBlock, a as pureCodeBlock, c as pureImage, n as renderMathInto, o as subscribeMathClick, d as pureChart } from "./extractToc-C2zqDjSP.js";
17
+ import { g, e, s as s3 } from "./extractToc-C2zqDjSP.js";
18
18
  import { Slice, Fragment } from "@tiptap/pm/model";
19
19
  import { Extension, Node as Node$1 } from "@tiptap/core";
20
20
  import { PluginKey, Plugin, NodeSelection, TextSelection } from "@tiptap/pm/state";
@@ -184,19 +184,19 @@ function commentAnchorPlugin(options = {}) {
184
184
  const decos = [];
185
185
  const bounds = blockBounds(state.doc);
186
186
  if (showGutter) {
187
- for (const b2 of bounds) {
187
+ for (const b3 of bounds) {
188
188
  const idsInBlock = [];
189
189
  for (const [id, ranges] of byId) {
190
- if (rangesIntersectBlock(ranges, b2.start, b2.end)) {
190
+ if (rangesIntersectBlock(ranges, b3.start, b3.end)) {
191
191
  idsInBlock.push(id);
192
192
  }
193
193
  }
194
194
  if (idsInBlock.length > 0) {
195
195
  decos.push(
196
196
  Decoration.widget(
197
- b2.start,
198
- (view) => gutterDom(idsInBlock, view, b2.start),
199
- { side: -1, key: `tmr-gutter:${b2.start}` }
197
+ b3.start,
198
+ (view) => gutterDom(idsInBlock, view, b3.start),
199
+ { side: -1, key: `tmr-gutter:${b3.start}` }
200
200
  )
201
201
  );
202
202
  }
@@ -210,10 +210,10 @@ function commentAnchorPlugin(options = {}) {
210
210
  Decoration.inline(r2.from, r2.to, { class: "tmr-comment-active" })
211
211
  );
212
212
  }
213
- for (const b2 of bounds) {
214
- if (rangesIntersectBlock(ranges, b2.start, b2.end)) {
213
+ for (const b3 of bounds) {
214
+ if (rangesIntersectBlock(ranges, b3.start, b3.end)) {
215
215
  decos.push(
216
- Decoration.node(b2.start, b2.end, {
216
+ Decoration.node(b3.start, b3.end, {
217
217
  class: "tmr-comment-block-active"
218
218
  })
219
219
  );
@@ -525,6 +525,14 @@ const TableDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
525
525
  /* @__PURE__ */ jsx("path", { d: "M15 5v14" }),
526
526
  /* @__PURE__ */ jsx("path", { d: "m7 2 10 20" })
527
527
  ] });
528
+ const CopyIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
529
+ /* @__PURE__ */ jsx("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
530
+ /* @__PURE__ */ jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
531
+ ] });
532
+ const ChevronsUpDownIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
533
+ /* @__PURE__ */ jsx("path", { d: "m7 15 5 5 5-5" }),
534
+ /* @__PURE__ */ jsx("path", { d: "m7 9 5-5 5 5" })
535
+ ] });
528
536
  const defaultChartLabels = {
529
537
  tabLabel: (chartType, index) => `${chartType} ${index + 1}`,
530
538
  done: "Done",
@@ -608,7 +616,10 @@ const defaultTocLabels = {
608
616
  };
609
617
  const defaultCodeBlockLabels = {
610
618
  autoDetect: "Auto-detect",
611
- delete: "Delete code block"
619
+ delete: "Delete code block",
620
+ copy: "Copy code",
621
+ expand: "Expand code",
622
+ collapse: "Collapse code"
612
623
  };
613
624
  const defaultCommentLabels = {
614
625
  open: "Open",
@@ -1281,29 +1292,45 @@ function createChart(options = {}) {
1281
1292
  }
1282
1293
  });
1283
1294
  }
1284
- const wrapper = "_wrapper_5i2vi_2";
1285
- const header$1 = "_header_5i2vi_18";
1286
- const langTrigger = "_langTrigger_5i2vi_28";
1287
- const langChevron = "_langChevron_5i2vi_50";
1288
- const langBadge = "_langBadge_5i2vi_56";
1289
- const langMenu = "_langMenu_5i2vi_71";
1290
- const langItem = "_langItem_5i2vi_84";
1291
- const langItemSelected = "_langItemSelected_5i2vi_103";
1292
- const langItemCheck = "_langItemCheck_5i2vi_108";
1293
- const deleteBtn = "_deleteBtn_5i2vi_116";
1294
- const pre = "_pre_5i2vi_136";
1295
+ const wrapper = "_wrapper_16490_2";
1296
+ const header$1 = "_header_16490_18";
1297
+ const langTrigger = "_langTrigger_16490_28";
1298
+ const langChevron = "_langChevron_16490_50";
1299
+ const readonlyHeader = "_readonlyHeader_16490_56";
1300
+ const langBadge = "_langBadge_16490_64";
1301
+ const langMenu = "_langMenu_16490_78";
1302
+ const langItem = "_langItem_16490_91";
1303
+ const langItemSelected = "_langItemSelected_16490_110";
1304
+ const langItemCheck = "_langItemCheck_16490_115";
1305
+ const deleteBtn = "_deleteBtn_16490_123";
1306
+ const pre = "_pre_16490_143";
1307
+ const readonly = "_readonly_16490_56";
1308
+ const expanded = "_expanded_16490_162";
1309
+ const gutter = "_gutter_16490_168";
1310
+ const gutterLine = "_gutterLine_16490_185";
1311
+ const readonlyActions = "_readonlyActions_16490_189";
1312
+ const actionBtn = "_actionBtn_16490_195";
1313
+ const langBraces = "_langBraces_16490_214";
1295
1314
  const styles$4 = {
1296
1315
  wrapper,
1297
1316
  header: header$1,
1298
1317
  langTrigger,
1299
1318
  langChevron,
1319
+ readonlyHeader,
1300
1320
  langBadge,
1301
1321
  langMenu,
1302
1322
  langItem,
1303
1323
  langItemSelected,
1304
1324
  langItemCheck,
1305
1325
  deleteBtn,
1306
- pre
1326
+ pre,
1327
+ readonly,
1328
+ expanded,
1329
+ gutter,
1330
+ gutterLine,
1331
+ readonlyActions,
1332
+ actionBtn,
1333
+ langBraces
1307
1334
  };
1308
1335
  const LANGUAGES = [
1309
1336
  { value: "", label: "Auto-detect" },
@@ -1341,7 +1368,60 @@ function CodeBlockView({
1341
1368
  const current = LANGUAGES.find((l) => l.value === language);
1342
1369
  const currentLabel = current ? current.value === "" ? labels.autoDetect : current.label : labels.autoDetect;
1343
1370
  const editable = editor.isEditable;
1344
- return /* @__PURE__ */ jsxs(NodeViewWrapper, { className: styles$4.wrapper, children: [
1371
+ const readonly2 = !editable;
1372
+ const [copied, setCopied] = useState(false);
1373
+ const [expanded2, setExpanded] = useState(false);
1374
+ const [scrollable, setScrollable] = useState(false);
1375
+ const [lineCount, setLineCount] = useState(
1376
+ () => Math.max((node.textContent ?? "").split("\n").length, 1)
1377
+ );
1378
+ const preRef = useRef(null);
1379
+ useEffect(() => {
1380
+ if (!readonly2) return;
1381
+ const pre2 = preRef.current;
1382
+ if (!pre2) return;
1383
+ const update = () => {
1384
+ setLineCount(Math.max((pre2.textContent ?? "").split("\n").length, 1));
1385
+ setScrollable(pre2.scrollHeight > pre2.clientHeight + 2);
1386
+ };
1387
+ update();
1388
+ const mo = new MutationObserver(update);
1389
+ mo.observe(pre2, { childList: true, subtree: true, characterData: true });
1390
+ window.addEventListener("resize", update);
1391
+ return () => {
1392
+ mo.disconnect();
1393
+ window.removeEventListener("resize", update);
1394
+ };
1395
+ }, [readonly2, expanded2]);
1396
+ const handleCopy = () => {
1397
+ var _a2;
1398
+ const text = node.textContent ?? "";
1399
+ const done = () => {
1400
+ setCopied(true);
1401
+ window.setTimeout(() => setCopied(false), 1500);
1402
+ };
1403
+ if ((_a2 = navigator.clipboard) == null ? void 0 : _a2.writeText) {
1404
+ navigator.clipboard.writeText(text).then(done, () => {
1405
+ });
1406
+ return;
1407
+ }
1408
+ const ta = document.createElement("textarea");
1409
+ ta.value = text;
1410
+ document.body.appendChild(ta);
1411
+ ta.select();
1412
+ try {
1413
+ document.execCommand("copy");
1414
+ done();
1415
+ } catch {
1416
+ }
1417
+ ta.remove();
1418
+ };
1419
+ const wrapperClass = [
1420
+ styles$4.wrapper,
1421
+ readonly2 ? styles$4.readonly : "",
1422
+ expanded2 ? styles$4.expanded : ""
1423
+ ].filter(Boolean).join(" ");
1424
+ return /* @__PURE__ */ jsxs(NodeViewWrapper, { className: wrapperClass, children: [
1345
1425
  editable ? /* @__PURE__ */ jsxs("div", { className: styles$4.header, contentEditable: false, children: [
1346
1426
  /* @__PURE__ */ jsxs(DropdownMenu.Root, { children: [
1347
1427
  /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
@@ -1393,10 +1473,51 @@ function CodeBlockView({
1393
1473
  }
1394
1474
  )
1395
1475
  ] }) : (
1396
- // 只读:只展示语言标签,无下拉 / 删除等交互件
1397
- /* @__PURE__ */ jsx("div", { className: styles$4.langBadge, contentEditable: false, children: currentLabel })
1476
+ // 只读头部:左侧语言标签,右侧复制 + 展开收起(内容不超限高时隐藏展开钮)
1477
+ /* @__PURE__ */ jsxs("div", { className: styles$4.readonlyHeader, contentEditable: false, children: [
1478
+ /* @__PURE__ */ jsxs("span", { className: styles$4.langBadge, children: [
1479
+ /* @__PURE__ */ jsx("span", { className: styles$4.langBraces, children: "{}" }),
1480
+ currentLabel
1481
+ ] }),
1482
+ /* @__PURE__ */ jsxs("span", { className: styles$4.readonlyActions, children: [
1483
+ /* @__PURE__ */ jsx(
1484
+ "button",
1485
+ {
1486
+ type: "button",
1487
+ className: styles$4.actionBtn,
1488
+ onClick: handleCopy,
1489
+ "aria-label": labels.copy,
1490
+ title: labels.copy,
1491
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, { size: 14 }) : /* @__PURE__ */ jsx(CopyIcon, { size: 14 })
1492
+ }
1493
+ ),
1494
+ scrollable ? /* @__PURE__ */ jsx(
1495
+ "button",
1496
+ {
1497
+ type: "button",
1498
+ className: styles$4.actionBtn,
1499
+ onClick: () => setExpanded((v) => !v),
1500
+ "aria-label": expanded2 ? labels.collapse : labels.expand,
1501
+ title: expanded2 ? labels.collapse : labels.expand,
1502
+ "aria-expanded": expanded2,
1503
+ children: /* @__PURE__ */ jsx(ChevronsUpDownIcon, { size: 14 })
1504
+ }
1505
+ ) : null
1506
+ ] })
1507
+ ] })
1398
1508
  ),
1399
- /* @__PURE__ */ jsx("pre", { className: styles$4.pre, children: /* @__PURE__ */ jsx(NodeViewContent, { as: "code" }) })
1509
+ /* @__PURE__ */ jsxs("pre", { ref: preRef, className: styles$4.pre, children: [
1510
+ readonly2 ? /* @__PURE__ */ jsx(
1511
+ "span",
1512
+ {
1513
+ className: styles$4.gutter,
1514
+ contentEditable: false,
1515
+ "aria-hidden": "true",
1516
+ children: Array.from({ length: lineCount }, (_, i) => /* @__PURE__ */ jsx("span", { className: styles$4.gutterLine, children: i + 1 }, i))
1517
+ }
1518
+ ) : null,
1519
+ /* @__PURE__ */ jsx(NodeViewContent, { as: "code" })
1520
+ ] })
1400
1521
  ] });
1401
1522
  }
1402
1523
  const CodeBlock = CodeBlockLowlight.extend({
@@ -1654,14 +1775,14 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
1654
1775
  (_a = onCommentClickRef.current) == null ? void 0 : _a.call(onCommentClickRef, click);
1655
1776
  (_b = onActiveCommentChangeRef.current) == null ? void 0 : _b.call(onActiveCommentChangeRef, click.commentIds[0] ?? null);
1656
1777
  }
1657
- const gutter = transaction.getMeta(COMMENT_GUTTER_META);
1658
- if (gutter) {
1778
+ const gutter2 = transaction.getMeta(COMMENT_GUTTER_META);
1779
+ if (gutter2) {
1659
1780
  (_c = onCommentClickRef.current) == null ? void 0 : _c.call(onCommentClickRef, {
1660
- commentIds: gutter.commentIds,
1781
+ commentIds: gutter2.commentIds,
1661
1782
  anchorEl: null,
1662
- pos: gutter.pos
1783
+ pos: gutter2.pos
1663
1784
  });
1664
- (_d = onActiveCommentChangeRef.current) == null ? void 0 : _d.call(onActiveCommentChangeRef, gutter.commentIds[0] ?? null);
1785
+ (_d = onActiveCommentChangeRef.current) == null ? void 0 : _d.call(onActiveCommentChangeRef, gutter2.commentIds[0] ?? null);
1665
1786
  }
1666
1787
  };
1667
1788
  editor.on("transaction", onTransaction);
@@ -1735,10 +1856,18 @@ function MarkdownPreview({
1735
1856
  ),
1736
1857
  [markdown, sources]
1737
1858
  );
1859
+ const previewCodeBlock = useMemo(
1860
+ () => pureCodeBlock.extend({
1861
+ addNodeView() {
1862
+ return ReactNodeViewRenderer(CodeBlockView);
1863
+ }
1864
+ }),
1865
+ []
1866
+ );
1738
1867
  const extensions = useMemo(
1739
1868
  () => [
1740
1869
  ...baseExtensions,
1741
- pureCodeBlock,
1870
+ previewCodeBlock,
1742
1871
  pureImage,
1743
1872
  createChart({ editable: false }),
1744
1873
  createCitationRef({ renderCitation }),
@@ -3566,7 +3695,7 @@ function getMarkdownForRange(editor, from, to, options = {}) {
3566
3695
  let first = 0;
3567
3696
  let last = blocks.length - 1;
3568
3697
  if (expand) {
3569
- first = blocks.findIndex((b2) => b2.to > start);
3698
+ first = blocks.findIndex((b3) => b3.to > start);
3570
3699
  if (first < 0) return null;
3571
3700
  for (let i = blocks.length - 1; i >= first; i -= 1) {
3572
3701
  if (blocks[i].from < end) {
@@ -3577,7 +3706,7 @@ function getMarkdownForRange(editor, from, to, options = {}) {
3577
3706
  start = blocks[first].from;
3578
3707
  end = blocks[last].to;
3579
3708
  }
3580
- const parts = blocks.map((b2) => manager.serialize({ type: "doc", content: [b2.json] }));
3709
+ const parts = blocks.map((b3) => manager.serialize({ type: "doc", content: [b3.json] }));
3581
3710
  const full = editor.getMarkdown();
3582
3711
  if (expand && parts.join(BLOCK_SEPARATOR) === full) {
3583
3712
  const markdown2 = parts.slice(first, last + 1).join(BLOCK_SEPARATOR);
@@ -3650,6 +3779,7 @@ export {
3650
3779
  CheckIcon,
3651
3780
  ChevronDownIcon,
3652
3781
  ChevronUpIcon,
3782
+ ChevronsUpDownIcon,
3653
3783
  a as CitationInteractive,
3654
3784
  CitationRef,
3655
3785
  CodeBlockView,
@@ -3660,6 +3790,7 @@ export {
3660
3790
  ColumnDeleteIcon,
3661
3791
  CommentMark,
3662
3792
  CommentPopover,
3793
+ CopyIcon,
3663
3794
  EditorToolbar,
3664
3795
  FIND_DEBOUNCE_MS,
3665
3796
  default2 as FindAndReplace,
@@ -3715,6 +3846,7 @@ export {
3715
3846
  defaultTocLabels,
3716
3847
  defaultToolbarLabels,
3717
3848
  enrichMarkdownCitations,
3849
+ b2 as extractFootnoteSources,
3718
3850
  e as extractToc,
3719
3851
  f as findCitationRefElement,
3720
3852
  findRangeByAnchor,