tiptap-markdown-react 0.18.0 → 0.19.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/README.md +97 -15
- package/THIRD_PARTY_LICENSES.md +45 -1
- package/dist/{ReportContent-MgbebxPV.js → ReportContent-B8jIzhy3.js} +8 -8
- package/dist/ReportContent-B8jIzhy3.js.map +1 -0
- package/dist/chart/columnMatching.d.ts +1 -1
- package/dist/chart/types.d.ts +1 -1
- package/dist/commentAnchor/commentMapper.d.ts +1 -1
- package/dist/components/EditorToolbar.d.ts +1 -1
- package/dist/components/ImageAlignTools.d.ts +19 -0
- package/dist/components/ImageUploadView.d.ts +10 -0
- package/dist/components/MarkdownWysiwygEditor.d.ts +47 -1
- package/dist/components/imageUpload.dom.test.d.ts +1 -0
- package/dist/extensions.d.ts +12 -0
- package/dist/{extractToc-BaR6LP1f.js → extractToc-CGrBMGvM.js} +433 -9
- package/dist/extractToc-CGrBMGvM.js.map +1 -0
- package/dist/icons/index.d.ts +9 -0
- package/dist/imageAlign.d.ts +29 -0
- package/dist/imageAlign.dom.test.d.ts +1 -0
- package/dist/imageCaption.d.ts +12 -0
- package/dist/imageMarkdown.d.ts +86 -0
- package/dist/imageResize.dom.test.d.ts +1 -0
- package/dist/imageUpload.d.ts +63 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +1355 -245
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +52 -0
- package/dist/paragraphMarkdown.d.ts +19 -0
- package/dist/paragraphStyles.d.ts +38 -0
- package/dist/paragraphStyles.dom.test.d.ts +1 -0
- package/dist/reader.js +2 -2
- package/dist/resetImageSize.d.ts +12 -0
- package/dist/{scrollToTocHeading-BTQWajGD.js → scrollToTocHeading-B2QmL4wi.js} +2 -2
- package/dist/{scrollToTocHeading-BTQWajGD.js.map → scrollToTocHeading-B2QmL4wi.js.map} +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +4 -4
- package/dist/style-inline.css +671 -140
- package/dist/style.css +671 -140
- package/package.json +5 -2
- package/dist/ReportContent-MgbebxPV.js.map +0 -1
- package/dist/extractToc-BaR6LP1f.js.map +0 -1
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import { Node, mergeAttributes, Mark } from "@tiptap/core";
|
|
1
|
+
import { Node, mergeAttributes, Mark, Extension } from "@tiptap/core";
|
|
2
2
|
import Code from "@tiptap/extension-code";
|
|
3
3
|
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
|
4
|
+
import Heading from "@tiptap/extension-heading";
|
|
4
5
|
import Highlight from "@tiptap/extension-highlight";
|
|
5
6
|
import Image from "@tiptap/extension-image";
|
|
7
|
+
import Paragraph from "@tiptap/extension-paragraph";
|
|
6
8
|
import Subscript from "@tiptap/extension-subscript";
|
|
7
9
|
import Superscript from "@tiptap/extension-superscript";
|
|
8
10
|
import { TableKit } from "@tiptap/extension-table";
|
|
9
11
|
import TaskItem from "@tiptap/extension-task-item";
|
|
10
12
|
import TaskList from "@tiptap/extension-task-list";
|
|
13
|
+
import TextAlign from "@tiptap/extension-text-align";
|
|
11
14
|
import { Color, TextStyle, FontSize } from "@tiptap/extension-text-style";
|
|
12
15
|
import StarterKit from "@tiptap/starter-kit";
|
|
13
16
|
import { createLowlight, common } from "lowlight";
|
|
14
17
|
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
15
|
-
import { p as parseChartFenceBody, s as serializeChartPayload, n as normalizeChartMarkdown } from "./ReportContent-
|
|
18
|
+
import { p as parseChartFenceBody, s as serializeChartPayload, n as normalizeChartMarkdown } from "./ReportContent-B8jIzhy3.js";
|
|
16
19
|
import { InlineMath, BlockMath } from "@tiptap/extension-mathematics";
|
|
17
20
|
import katex from "katex";
|
|
18
21
|
const CitationRef = Node.create({
|
|
@@ -580,6 +583,176 @@ function parseCodeTokenAsChartOrCodeBlock(token, helpers, codeBlockName = "codeB
|
|
|
580
583
|
token.text ? [helpers.createTextNode(token.text)] : []
|
|
581
584
|
);
|
|
582
585
|
}
|
|
586
|
+
const IMAGE_ALIGN_VALUES = /* @__PURE__ */ new Set(["left", "center", "right"]);
|
|
587
|
+
function normalizeImageAlign(value) {
|
|
588
|
+
return typeof value === "string" && IMAGE_ALIGN_VALUES.has(value) ? value : null;
|
|
589
|
+
}
|
|
590
|
+
const imageAlignAttribute = {
|
|
591
|
+
default: null,
|
|
592
|
+
parseHTML: (element) => normalizeImageAlign(element.getAttribute("data-align")),
|
|
593
|
+
renderHTML: (attributes) => {
|
|
594
|
+
const align = normalizeImageAlign(attributes.align);
|
|
595
|
+
return align ? { "data-align": align } : {};
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
const imageCaptionAttribute = {
|
|
599
|
+
default: null,
|
|
600
|
+
parseHTML: (element) => {
|
|
601
|
+
var _a;
|
|
602
|
+
const figure = element.closest("figure");
|
|
603
|
+
return normalizeImageCaption(
|
|
604
|
+
((_a = figure == null ? void 0 : figure.querySelector("figcaption")) == null ? void 0 : _a.textContent) ?? null
|
|
605
|
+
);
|
|
606
|
+
},
|
|
607
|
+
renderHTML: () => ({})
|
|
608
|
+
};
|
|
609
|
+
function imageNodeHtml(output) {
|
|
610
|
+
const caption = normalizeImageCaption(output.attrs.caption);
|
|
611
|
+
if (!caption) return ["img", output.htmlAttributes];
|
|
612
|
+
return [
|
|
613
|
+
"figure",
|
|
614
|
+
{ class: "tmr-image-figure" },
|
|
615
|
+
["img", output.htmlAttributes],
|
|
616
|
+
["figcaption", { class: "tmr-image-caption" }, caption]
|
|
617
|
+
];
|
|
618
|
+
}
|
|
619
|
+
function imageFigureParseRule() {
|
|
620
|
+
return {
|
|
621
|
+
tag: "figure",
|
|
622
|
+
getAttrs: (element) => {
|
|
623
|
+
const img = element.querySelector("img");
|
|
624
|
+
if (!img) return false;
|
|
625
|
+
const caption = element.querySelector("figcaption");
|
|
626
|
+
return {
|
|
627
|
+
src: img.getAttribute("src"),
|
|
628
|
+
alt: img.getAttribute("alt"),
|
|
629
|
+
title: img.getAttribute("title"),
|
|
630
|
+
width: toPixel(img.getAttribute("width")),
|
|
631
|
+
height: toPixel(img.getAttribute("height")),
|
|
632
|
+
align: normalizeImageAlign(img.getAttribute("data-align")),
|
|
633
|
+
caption: normalizeImageCaption((caption == null ? void 0 : caption.textContent) ?? null)
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function attrValue(attrs, name) {
|
|
639
|
+
const pattern = new RegExp(
|
|
640
|
+
`(?:^|\\s)${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s"'=<>]+))`,
|
|
641
|
+
"i"
|
|
642
|
+
);
|
|
643
|
+
const match = pattern.exec(attrs);
|
|
644
|
+
if (!match) return null;
|
|
645
|
+
return match[1] ?? match[2] ?? match[3] ?? null;
|
|
646
|
+
}
|
|
647
|
+
const ENTITIES = {
|
|
648
|
+
"&": "&",
|
|
649
|
+
"<": "<",
|
|
650
|
+
">": ">",
|
|
651
|
+
""": '"',
|
|
652
|
+
"'": "'"
|
|
653
|
+
};
|
|
654
|
+
function decodeEntities(text) {
|
|
655
|
+
return text.replace(/&(?:amp|lt|gt|quot|#39);/g, (m) => ENTITIES[m] ?? m);
|
|
656
|
+
}
|
|
657
|
+
function encodeAttr$1(value) {
|
|
658
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
659
|
+
}
|
|
660
|
+
function encodeText(value) {
|
|
661
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
662
|
+
}
|
|
663
|
+
function normalizeImageCaption(value) {
|
|
664
|
+
if (typeof value !== "string") return null;
|
|
665
|
+
const text = value.trim();
|
|
666
|
+
return text === "" ? null : text;
|
|
667
|
+
}
|
|
668
|
+
function toPixel(value) {
|
|
669
|
+
if (value == null) return null;
|
|
670
|
+
const n = Number(value);
|
|
671
|
+
return Number.isFinite(n) && n > 0 ? Math.round(n) : null;
|
|
672
|
+
}
|
|
673
|
+
function imageRenderMarkdown(node) {
|
|
674
|
+
const attrs = node.attrs ?? {};
|
|
675
|
+
const src = typeof attrs.src === "string" ? attrs.src : "";
|
|
676
|
+
const alt = typeof attrs.alt === "string" ? attrs.alt : "";
|
|
677
|
+
const title = typeof attrs.title === "string" ? attrs.title : "";
|
|
678
|
+
const width = toPixel(attrs.width == null ? null : String(attrs.width));
|
|
679
|
+
const height = toPixel(attrs.height == null ? null : String(attrs.height));
|
|
680
|
+
const align = normalizeImageAlign(attrs.align);
|
|
681
|
+
const caption = normalizeImageCaption(attrs.caption);
|
|
682
|
+
if (width == null && height == null && !align && !caption) {
|
|
683
|
+
return title ? `` : ``;
|
|
684
|
+
}
|
|
685
|
+
const parts = [`src="${encodeAttr$1(src)}"`];
|
|
686
|
+
if (alt) parts.push(`alt="${encodeAttr$1(alt)}"`);
|
|
687
|
+
if (title) parts.push(`title="${encodeAttr$1(title)}"`);
|
|
688
|
+
if (width != null) parts.push(`width="${width}"`);
|
|
689
|
+
if (height != null) parts.push(`height="${height}"`);
|
|
690
|
+
if (align) parts.push(`data-align="${align}"`);
|
|
691
|
+
const imgTag = `<img ${parts.join(" ")}>`;
|
|
692
|
+
if (!caption) return imgTag;
|
|
693
|
+
return `<figure>
|
|
694
|
+
${imgTag}
|
|
695
|
+
<figcaption>${encodeText(caption)}</figcaption>
|
|
696
|
+
</figure>`;
|
|
697
|
+
}
|
|
698
|
+
function imageTokenFromImgTag(raw, attrsString, caption = null) {
|
|
699
|
+
const srcValue = attrValue(attrsString, "src");
|
|
700
|
+
if (!srcValue) return void 0;
|
|
701
|
+
const alt = attrValue(attrsString, "alt");
|
|
702
|
+
const title = attrValue(attrsString, "title");
|
|
703
|
+
return {
|
|
704
|
+
type: "image",
|
|
705
|
+
raw,
|
|
706
|
+
src: decodeEntities(srcValue),
|
|
707
|
+
alt: alt == null ? null : decodeEntities(alt),
|
|
708
|
+
title: title == null ? null : decodeEntities(title),
|
|
709
|
+
width: toPixel(attrValue(attrsString, "width")),
|
|
710
|
+
height: toPixel(attrValue(attrsString, "height")),
|
|
711
|
+
align: normalizeImageAlign(attrValue(attrsString, "data-align")),
|
|
712
|
+
caption
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
const imageMarkdownTokenizer = {
|
|
716
|
+
name: "image",
|
|
717
|
+
level: "block",
|
|
718
|
+
start(src) {
|
|
719
|
+
const figure = /<figure[\s>]/i.exec(src);
|
|
720
|
+
const img = /<img[\s>]/i.exec(src);
|
|
721
|
+
const indexes = [figure == null ? void 0 : figure.index, img == null ? void 0 : img.index].filter(
|
|
722
|
+
(index) => index != null
|
|
723
|
+
);
|
|
724
|
+
return indexes.length ? Math.min(...indexes) : -1;
|
|
725
|
+
},
|
|
726
|
+
tokenize(src) {
|
|
727
|
+
const figure = /^<figure\s*>([\s\S]*?)<\/figure\s*>/i.exec(src);
|
|
728
|
+
if (figure) {
|
|
729
|
+
const inner = figure[1] ?? "";
|
|
730
|
+
const img = /<img\s+([^>]*?)\s*\/?>/.exec(inner);
|
|
731
|
+
if (!img) return void 0;
|
|
732
|
+
const cap = /<figcaption[^>]*>([\s\S]*?)<\/figcaption\s*>/i.exec(inner);
|
|
733
|
+
const caption = cap ? normalizeImageCaption(
|
|
734
|
+
decodeEntities((cap[1] ?? "").replace(/<[^>]*>/g, ""))
|
|
735
|
+
) : null;
|
|
736
|
+
return imageTokenFromImgTag(figure[0], img[1] ?? "", caption);
|
|
737
|
+
}
|
|
738
|
+
const match = /^<img\s+([^>]*?)\s*\/?>/.exec(src);
|
|
739
|
+
if (!match) return void 0;
|
|
740
|
+
return imageTokenFromImgTag(match[0], match[1] ?? "");
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
function imageParseMarkdown(token, helpers) {
|
|
744
|
+
const src = typeof token.src === "string" ? token.src : token.href ?? null;
|
|
745
|
+
const alt = typeof token.alt === "string" ? token.alt : token.text ?? null;
|
|
746
|
+
return helpers.createNode("image", {
|
|
747
|
+
src,
|
|
748
|
+
alt,
|
|
749
|
+
title: token.title ?? null,
|
|
750
|
+
width: token.width ?? null,
|
|
751
|
+
height: token.height ?? null,
|
|
752
|
+
align: token.align ?? null,
|
|
753
|
+
caption: normalizeImageCaption(token.caption)
|
|
754
|
+
});
|
|
755
|
+
}
|
|
583
756
|
const KATEX_OPTIONS = { throwOnError: false };
|
|
584
757
|
let mathClickListener = null;
|
|
585
758
|
function subscribeMathClick(listener) {
|
|
@@ -683,6 +856,196 @@ $$`;
|
|
|
683
856
|
katexOptions: { ...KATEX_OPTIONS, displayMode: true },
|
|
684
857
|
onClick: (node, pos) => emitClick("block", node, pos)
|
|
685
858
|
});
|
|
859
|
+
const INDENT_STEP_EM = 2;
|
|
860
|
+
const TEXT_ALIGN_VALUES = /* @__PURE__ */ new Set(["left", "center", "right", "justify"]);
|
|
861
|
+
function encodeAttr(value) {
|
|
862
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
863
|
+
}
|
|
864
|
+
const KNOWN_STYLE_KEYS = ["text-align", "margin-left", "line-height"];
|
|
865
|
+
function paragraphStyleString(attrs) {
|
|
866
|
+
const parts = [];
|
|
867
|
+
const align = typeof attrs.textAlign === "string" ? attrs.textAlign : null;
|
|
868
|
+
if (align && TEXT_ALIGN_VALUES.has(align)) {
|
|
869
|
+
parts.push(`text-align: ${align}`);
|
|
870
|
+
}
|
|
871
|
+
const indent = Number(attrs.indent);
|
|
872
|
+
if (Number.isFinite(indent) && indent > 0) {
|
|
873
|
+
parts.push(`margin-left: ${indent * INDENT_STEP_EM}em`);
|
|
874
|
+
}
|
|
875
|
+
const lineHeight = Number(attrs.lineHeight);
|
|
876
|
+
if (Number.isFinite(lineHeight) && lineHeight > 0) {
|
|
877
|
+
parts.push(`line-height: ${lineHeight}`);
|
|
878
|
+
}
|
|
879
|
+
return parts.join("; ");
|
|
880
|
+
}
|
|
881
|
+
function parseParagraphStyleAttrs(style) {
|
|
882
|
+
const attrs = {};
|
|
883
|
+
for (const entry of style.split(";")) {
|
|
884
|
+
const index = entry.indexOf(":");
|
|
885
|
+
if (index < 0) continue;
|
|
886
|
+
const key = entry.slice(0, index).trim().toLowerCase();
|
|
887
|
+
const value = entry.slice(index + 1).trim();
|
|
888
|
+
if (!value) continue;
|
|
889
|
+
if (key === "text-align" && TEXT_ALIGN_VALUES.has(value)) {
|
|
890
|
+
attrs.textAlign = value;
|
|
891
|
+
} else if (key === "margin-left") {
|
|
892
|
+
const match = /^([\d.]+)em$/.exec(value);
|
|
893
|
+
const em = match ? Number.parseFloat(match[1]) : NaN;
|
|
894
|
+
const level = Number.isFinite(em) && em > 0 ? Math.round(em / INDENT_STEP_EM) : 0;
|
|
895
|
+
if (level > 0) attrs.indent = level;
|
|
896
|
+
} else if (key === "line-height") {
|
|
897
|
+
const parsed = Number.parseFloat(value);
|
|
898
|
+
if (Number.isFinite(parsed) && parsed > 0) attrs.lineHeight = parsed;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
return attrs;
|
|
902
|
+
}
|
|
903
|
+
function hasKnownStyle(style) {
|
|
904
|
+
const lowered = style.toLowerCase();
|
|
905
|
+
return KNOWN_STYLE_KEYS.some((key) => lowered.includes(`${key}:`));
|
|
906
|
+
}
|
|
907
|
+
function paragraphRenderMarkdown(node, helpers) {
|
|
908
|
+
const children = helpers.renderChildren(node.content ?? []);
|
|
909
|
+
const style = paragraphStyleString(
|
|
910
|
+
node.attrs ?? {}
|
|
911
|
+
);
|
|
912
|
+
if (!style) return children;
|
|
913
|
+
return `<p style="${encodeAttr(style)}">${children}</p>`;
|
|
914
|
+
}
|
|
915
|
+
function headingRenderMarkdown(node, helpers) {
|
|
916
|
+
var _a;
|
|
917
|
+
const children = helpers.renderChildren(node.content ?? []);
|
|
918
|
+
const level = Math.min(
|
|
919
|
+
Math.max(Number((_a = node.attrs) == null ? void 0 : _a.level) || 1, 1),
|
|
920
|
+
6
|
|
921
|
+
);
|
|
922
|
+
const style = paragraphStyleString(
|
|
923
|
+
node.attrs ?? {}
|
|
924
|
+
);
|
|
925
|
+
if (!style) return `${"#".repeat(level)} ${children}`;
|
|
926
|
+
return `<h${level} style="${encodeAttr(style)}">${children}</h${level}>`;
|
|
927
|
+
}
|
|
928
|
+
const paragraphMarkdownTokenizer = {
|
|
929
|
+
name: "paragraph",
|
|
930
|
+
level: "block",
|
|
931
|
+
start(src) {
|
|
932
|
+
const match = /<(?:p|h[1-6])\s+style=/i.exec(src);
|
|
933
|
+
return match ? match.index : -1;
|
|
934
|
+
},
|
|
935
|
+
tokenize(src, _tokens, lexer) {
|
|
936
|
+
const match = /^<(p|h([1-6]))\s+style="([^"]*)"\s*>([\s\S]*?)<\/\1\s*>/i.exec(
|
|
937
|
+
src
|
|
938
|
+
);
|
|
939
|
+
if (!match) return void 0;
|
|
940
|
+
const [, tag, headingLevel, style, inner] = match;
|
|
941
|
+
if (!hasKnownStyle(style)) return void 0;
|
|
942
|
+
return {
|
|
943
|
+
type: "paragraph",
|
|
944
|
+
raw: match[0],
|
|
945
|
+
tag,
|
|
946
|
+
hLevel: headingLevel ? Number(headingLevel) : null,
|
|
947
|
+
style,
|
|
948
|
+
// 行内内容交给 marked 的 lexer 解析:bold / link 等照常还原(与 sup/sub 同一手法)
|
|
949
|
+
tokens: lexer.inlineTokens(inner ?? "")
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
const ROW_BLOCK_TYPES = /* @__PURE__ */ new Set(["image", "chart"]);
|
|
954
|
+
function paragraphParseMarkdown(token, helpers) {
|
|
955
|
+
const attrs = parseParagraphStyleAttrs(String(token.style ?? ""));
|
|
956
|
+
const content = helpers.parseInline(token.tokens ?? []);
|
|
957
|
+
const blockOnly = content.length > 0 && Object.keys(attrs).length === 0 && content.every((child) => ROW_BLOCK_TYPES.has(String(child.type)));
|
|
958
|
+
if (blockOnly) return content;
|
|
959
|
+
if (token.hLevel) {
|
|
960
|
+
return helpers.createNode("heading", { level: token.hLevel, ...attrs }, content);
|
|
961
|
+
}
|
|
962
|
+
return helpers.createNode("paragraph", attrs, content);
|
|
963
|
+
}
|
|
964
|
+
function parseIndentValue(value, stepEm) {
|
|
965
|
+
if (!value) return null;
|
|
966
|
+
const match = /^([\d.]+)em$/.exec(value.trim());
|
|
967
|
+
if (!match) return null;
|
|
968
|
+
const em = Number.parseFloat(match[1]);
|
|
969
|
+
if (!Number.isFinite(em) || em <= 0) return null;
|
|
970
|
+
const level = Math.round(em / stepEm);
|
|
971
|
+
return level > 0 ? level : null;
|
|
972
|
+
}
|
|
973
|
+
function parseLineHeightValue(value) {
|
|
974
|
+
if (!value) return null;
|
|
975
|
+
const parsed = Number.parseFloat(value);
|
|
976
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
977
|
+
}
|
|
978
|
+
function clampIndent(level, max) {
|
|
979
|
+
if (!Number.isFinite(level) || level <= 0) return 0;
|
|
980
|
+
return Math.min(Math.round(level), max);
|
|
981
|
+
}
|
|
982
|
+
const ParagraphStyles = Extension.create({
|
|
983
|
+
name: "paragraphStyles",
|
|
984
|
+
addOptions() {
|
|
985
|
+
return {
|
|
986
|
+
types: [],
|
|
987
|
+
indentStepEm: 2,
|
|
988
|
+
maxIndent: 8
|
|
989
|
+
};
|
|
990
|
+
},
|
|
991
|
+
addGlobalAttributes() {
|
|
992
|
+
return [
|
|
993
|
+
{
|
|
994
|
+
types: this.options.types,
|
|
995
|
+
attributes: {
|
|
996
|
+
indent: {
|
|
997
|
+
default: null,
|
|
998
|
+
parseHTML: (element) => parseIndentValue(element.style.marginLeft, this.options.indentStepEm),
|
|
999
|
+
renderHTML: (attributes) => {
|
|
1000
|
+
const level = clampIndent(
|
|
1001
|
+
Number(attributes.indent),
|
|
1002
|
+
this.options.maxIndent
|
|
1003
|
+
);
|
|
1004
|
+
if (level === 0) return {};
|
|
1005
|
+
return {
|
|
1006
|
+
style: `margin-left: ${level * this.options.indentStepEm}em`
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
},
|
|
1010
|
+
lineHeight: {
|
|
1011
|
+
default: null,
|
|
1012
|
+
parseHTML: (element) => parseLineHeightValue(element.style.lineHeight),
|
|
1013
|
+
renderHTML: (attributes) => {
|
|
1014
|
+
const value = Number(attributes.lineHeight);
|
|
1015
|
+
if (!Number.isFinite(value) || value <= 0) return {};
|
|
1016
|
+
return { style: `line-height: ${value}` };
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
];
|
|
1022
|
+
},
|
|
1023
|
+
addCommands() {
|
|
1024
|
+
const runOnTypes = (attrs) => (props) => this.options.types.map((type) => props.commands.updateAttributes(type, attrs)).some((response) => response);
|
|
1025
|
+
const currentIndent = ({ editor }) => {
|
|
1026
|
+
for (const type of this.options.types) {
|
|
1027
|
+
const value = editor.getAttributes(type).indent;
|
|
1028
|
+
if (value != null) return Number(value) || 0;
|
|
1029
|
+
}
|
|
1030
|
+
return 0;
|
|
1031
|
+
};
|
|
1032
|
+
return {
|
|
1033
|
+
setIndent: (level) => (props) => {
|
|
1034
|
+
const next = clampIndent(Number(level), this.options.maxIndent);
|
|
1035
|
+
return runOnTypes({ indent: next || null })(props);
|
|
1036
|
+
},
|
|
1037
|
+
increaseIndent: () => (props) => runOnTypes({
|
|
1038
|
+
indent: clampIndent(currentIndent(props) + 1, this.options.maxIndent) || null
|
|
1039
|
+
})(props),
|
|
1040
|
+
decreaseIndent: () => (props) => runOnTypes({
|
|
1041
|
+
indent: clampIndent(currentIndent(props) - 1, this.options.maxIndent) || null
|
|
1042
|
+
})(props),
|
|
1043
|
+
setLineHeight: (value) => (props) => runOnTypes({
|
|
1044
|
+
lineHeight: value == null ? null : parseLineHeightValue(String(value))
|
|
1045
|
+
})(props)
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
686
1049
|
const InlineCode = Code.extend({
|
|
687
1050
|
excludes: ""
|
|
688
1051
|
});
|
|
@@ -739,10 +1102,61 @@ const MarkdownSubscript = Subscript.extend({
|
|
|
739
1102
|
const pureCodeBlock = CodeBlockLowlight.extend({
|
|
740
1103
|
parseMarkdown: (token, helpers) => parseCodeTokenAsChartOrCodeBlock(token, helpers, "codeBlock")
|
|
741
1104
|
}).configure({ lowlight });
|
|
742
|
-
const pureImage = Image.
|
|
1105
|
+
const pureImage = Image.extend({
|
|
1106
|
+
addAttributes() {
|
|
1107
|
+
var _a;
|
|
1108
|
+
return {
|
|
1109
|
+
...((_a = Image.config.addAttributes) == null ? void 0 : _a.call(this)) ?? {},
|
|
1110
|
+
align: imageAlignAttribute,
|
|
1111
|
+
caption: imageCaptionAttribute
|
|
1112
|
+
};
|
|
1113
|
+
},
|
|
1114
|
+
parseHTML() {
|
|
1115
|
+
return [
|
|
1116
|
+
imageFigureParseRule(),
|
|
1117
|
+
{
|
|
1118
|
+
tag: this.options.allowBase64 ? "img[src]" : 'img[src]:not([src^="data:"])'
|
|
1119
|
+
}
|
|
1120
|
+
];
|
|
1121
|
+
},
|
|
1122
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
1123
|
+
return imageNodeHtml({
|
|
1124
|
+
attrs: node.attrs,
|
|
1125
|
+
htmlAttributes: mergeAttributes(
|
|
1126
|
+
this.options.HTMLAttributes,
|
|
1127
|
+
HTMLAttributes
|
|
1128
|
+
)
|
|
1129
|
+
});
|
|
1130
|
+
},
|
|
1131
|
+
renderMarkdown: imageRenderMarkdown,
|
|
1132
|
+
parseMarkdown: imageParseMarkdown,
|
|
1133
|
+
markdownTokenizer: imageMarkdownTokenizer
|
|
1134
|
+
}).configure({ inline: false });
|
|
1135
|
+
const MarkdownParagraph = Paragraph.extend({
|
|
1136
|
+
renderMarkdown: paragraphRenderMarkdown,
|
|
1137
|
+
markdownTokenizer: paragraphMarkdownTokenizer,
|
|
1138
|
+
parseMarkdown: paragraphParseMarkdown
|
|
1139
|
+
});
|
|
1140
|
+
const MarkdownHeading = Heading.extend({
|
|
1141
|
+
renderMarkdown: headingRenderMarkdown
|
|
1142
|
+
});
|
|
743
1143
|
const baseExtensions = [
|
|
744
|
-
// 禁用 StarterKit 内置 codeBlock / code
|
|
745
|
-
|
|
1144
|
+
// 禁用 StarterKit 内置 codeBlock / code(改用 lowlight 代码块 + 可共存的 InlineCode)
|
|
1145
|
+
// 与 paragraph / heading(改用带 markdown 样式往返的版本,见上)
|
|
1146
|
+
StarterKit.configure({
|
|
1147
|
+
codeBlock: false,
|
|
1148
|
+
code: false,
|
|
1149
|
+
paragraph: false,
|
|
1150
|
+
heading: false
|
|
1151
|
+
}),
|
|
1152
|
+
MarkdownParagraph,
|
|
1153
|
+
MarkdownHeading,
|
|
1154
|
+
// 段落级样式:文字对齐用官方扩展(免费);缩进 / 行高自研(官方无此扩展)。
|
|
1155
|
+
// 三者都往节点 style 上写片段,tiptap 的 mergeAttributes 对 style 做拼接合并。
|
|
1156
|
+
TextAlign.configure({ types: [MarkdownParagraph.name, MarkdownHeading.name] }),
|
|
1157
|
+
ParagraphStyles.configure({
|
|
1158
|
+
types: [MarkdownParagraph.name, MarkdownHeading.name]
|
|
1159
|
+
}),
|
|
746
1160
|
InlineCode,
|
|
747
1161
|
MarkdownTextStyle,
|
|
748
1162
|
Color.configure({ types: [TextStyle.name] }),
|
|
@@ -840,7 +1254,9 @@ function extractToc(doc, lockedTitles = []) {
|
|
|
840
1254
|
return items;
|
|
841
1255
|
}
|
|
842
1256
|
export {
|
|
1257
|
+
subscribeMathClick as A,
|
|
843
1258
|
CitationRef as C,
|
|
1259
|
+
ParagraphStyles as P,
|
|
844
1260
|
pureCodeBlock as a,
|
|
845
1261
|
baseExtensions as b,
|
|
846
1262
|
pureImage as c,
|
|
@@ -854,10 +1270,18 @@ export {
|
|
|
854
1270
|
parseCodeTokenAsChartOrCodeBlock as k,
|
|
855
1271
|
lowlight as l,
|
|
856
1272
|
makeTocGetId as m,
|
|
857
|
-
|
|
858
|
-
|
|
1273
|
+
normalizeImageAlign as n,
|
|
1274
|
+
imageMarkdownTokenizer as o,
|
|
859
1275
|
prepareChartMarkdown as p,
|
|
1276
|
+
imageParseMarkdown as q,
|
|
860
1277
|
renderMathElementHtml as r,
|
|
861
|
-
stabilizeMarkdown as s
|
|
1278
|
+
stabilizeMarkdown as s,
|
|
1279
|
+
imageRenderMarkdown as t,
|
|
1280
|
+
imageNodeHtml as u,
|
|
1281
|
+
imageFigureParseRule as v,
|
|
1282
|
+
imageCaptionAttribute as w,
|
|
1283
|
+
imageAlignAttribute as x,
|
|
1284
|
+
normalizeImageCaption as y,
|
|
1285
|
+
renderMathInto as z
|
|
862
1286
|
};
|
|
863
|
-
//# sourceMappingURL=extractToc-
|
|
1287
|
+
//# sourceMappingURL=extractToc-CGrBMGvM.js.map
|