tiptap-markdown-react 1.3.2 → 1.4.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/{ReportContent-Bc5q1bYp.js → ReportContent-B0HdrWAi.js} +13 -13
- package/dist/{ReportContent-Bc5q1bYp.js.map → ReportContent-B0HdrWAi.js.map} +1 -1
- package/dist/{ReportContentWithCharts-DJO3xs88.js → ReportContentWithCharts-3cn7_5Tz.js} +12 -35
- package/dist/ReportContentWithCharts-3cn7_5Tz.js.map +1 -0
- package/dist/demoContent.test.d.ts +1 -0
- package/dist/{extractToc-DiI2437D.js → extractToc-Bz924Nh4.js} +239 -4
- package/dist/{extractToc-DiI2437D.js.map → extractToc-Bz924Nh4.js.map} +1 -1
- package/dist/fontSizeHeading.test.d.ts +1 -0
- package/dist/highlightMarkdown.test.d.ts +1 -0
- package/dist/index.js +84 -63
- package/dist/index.js.map +1 -1
- package/dist/markOrder.test.d.ts +1 -0
- package/dist/reader.js +2 -2
- package/dist/server.js +33 -7
- package/dist/server.js.map +1 -1
- package/dist/style-inline.css +479 -445
- package/dist/style.css +479 -445
- package/dist/textStyleServer.test.d.ts +1 -0
- package/package.json +1 -1
- package/dist/ReportContentWithCharts-DJO3xs88.js.map +0 -1
- package/dist/quoteHighlight/matchQuote.d.ts +0 -38
- package/dist/quoteHighlight/types.d.ts +0 -57
|
@@ -16,7 +16,7 @@ import { Color, TextStyle, FontSize } from "@tiptap/extension-text-style";
|
|
|
16
16
|
import StarterKit from "@tiptap/starter-kit";
|
|
17
17
|
import { createLowlight, common } from "lowlight";
|
|
18
18
|
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
19
|
-
import { p as parseChartFenceBody, s as serializeChartPayload, i as imageMarkdownTokenizer, c as imageParseMarkdown, d as imageRenderMarkdown, f as imageNodeHtml, g as imageFigureParseRule, h as imageCropAttribute, j as imageCaptionAttribute, k as imageAlignAttribute, n as normalizeChartMarkdown } from "./ReportContent-
|
|
19
|
+
import { p as parseChartFenceBody, s as serializeChartPayload, i as imageMarkdownTokenizer, c as imageParseMarkdown, d as imageRenderMarkdown, f as imageNodeHtml, g as imageFigureParseRule, h as imageCropAttribute, j as imageCaptionAttribute, k as imageAlignAttribute, n as normalizeChartMarkdown } from "./ReportContent-B0HdrWAi.js";
|
|
20
20
|
import { InlineMath, BlockMath } from "@tiptap/extension-mathematics";
|
|
21
21
|
import katex from "katex";
|
|
22
22
|
import { Emoji, shortcodeToEmoji, emojis, emojiToShortcode } from "@tiptap/extension-emoji";
|
|
@@ -1505,6 +1505,66 @@ const InlineCode = Code.extend({
|
|
|
1505
1505
|
excludes: ""
|
|
1506
1506
|
});
|
|
1507
1507
|
const lowlight = createLowlight(common);
|
|
1508
|
+
const FONT_SIZE_VALUE = /^\d+(?:\.\d+)?(?:px|em|rem|%)$/i;
|
|
1509
|
+
const HEX_COLOR = /^#[0-9a-fA-F]{3,8}$/;
|
|
1510
|
+
const RGB_COLOR = /^rgba?\(\s*(?:\d{1,3}\s*,\s*){2}\d{1,3}(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/;
|
|
1511
|
+
const HSL_COLOR = /^hsla?\(\s*[\d.]+\s*,\s*[\d.]+%\s*,\s*[\d.]+%(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/;
|
|
1512
|
+
const NAMED_COLOR = /^[a-zA-Z]{1,30}$/;
|
|
1513
|
+
function isSafeColor(value) {
|
|
1514
|
+
if (/[<>"'\\{};]/.test(value)) return false;
|
|
1515
|
+
return HEX_COLOR.test(value) || RGB_COLOR.test(value) || HSL_COLOR.test(value) || NAMED_COLOR.test(value);
|
|
1516
|
+
}
|
|
1517
|
+
function parseTextStyleAttrs(style) {
|
|
1518
|
+
const attrs = {};
|
|
1519
|
+
for (const entry of style.split(";")) {
|
|
1520
|
+
const index = entry.indexOf(":");
|
|
1521
|
+
if (index < 0) continue;
|
|
1522
|
+
const key = entry.slice(0, index).trim().toLowerCase();
|
|
1523
|
+
const value = entry.slice(index + 1).trim();
|
|
1524
|
+
if (key === "color" && isSafeColor(value)) attrs.color = value;
|
|
1525
|
+
else if (key === "font-size" && FONT_SIZE_VALUE.test(value)) {
|
|
1526
|
+
attrs.fontSize = value;
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
if (!attrs.color && !attrs.fontSize) return null;
|
|
1530
|
+
return attrs;
|
|
1531
|
+
}
|
|
1532
|
+
function readStyleAttribute(attrs) {
|
|
1533
|
+
const match = /\bstyle\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+))/i.exec(
|
|
1534
|
+
attrs
|
|
1535
|
+
);
|
|
1536
|
+
if (!match) return void 0;
|
|
1537
|
+
return (match[1] ?? match[2] ?? match[3] ?? "").trim();
|
|
1538
|
+
}
|
|
1539
|
+
function matchTextStyleSpan(src) {
|
|
1540
|
+
const open = /^<span\b([^>]*)>/i.exec(src);
|
|
1541
|
+
if (!open || /\/\s*$/.test(open[1])) return void 0;
|
|
1542
|
+
const style = readStyleAttribute(open[1]);
|
|
1543
|
+
if (style == null || !parseTextStyleAttrs(style)) return void 0;
|
|
1544
|
+
const tagRe = /<\/?span\b[^>]*>/i;
|
|
1545
|
+
let depth = 1;
|
|
1546
|
+
let cursor = open[0].length;
|
|
1547
|
+
while (cursor < src.length) {
|
|
1548
|
+
const found = tagRe.exec(src.slice(cursor));
|
|
1549
|
+
if (!found) return void 0;
|
|
1550
|
+
const tag = found[0];
|
|
1551
|
+
const at = cursor + found.index;
|
|
1552
|
+
if (tag.startsWith("</")) {
|
|
1553
|
+
depth -= 1;
|
|
1554
|
+
if (depth === 0) {
|
|
1555
|
+
return {
|
|
1556
|
+
raw: src.slice(0, at + tag.length),
|
|
1557
|
+
style,
|
|
1558
|
+
inner: src.slice(open[0].length, at)
|
|
1559
|
+
};
|
|
1560
|
+
}
|
|
1561
|
+
} else if (!/\/\s*>$/.test(tag)) {
|
|
1562
|
+
depth += 1;
|
|
1563
|
+
}
|
|
1564
|
+
cursor = at + tag.length;
|
|
1565
|
+
}
|
|
1566
|
+
return void 0;
|
|
1567
|
+
}
|
|
1508
1568
|
const MarkdownTextStyle = TextStyle.extend({
|
|
1509
1569
|
renderMarkdown(node, helpers) {
|
|
1510
1570
|
const { color, fontSize } = node.attrs ?? {};
|
|
@@ -1514,6 +1574,127 @@ const MarkdownTextStyle = TextStyle.extend({
|
|
|
1514
1574
|
if (styles.length === 0) return "";
|
|
1515
1575
|
const children = helpers.renderChildren();
|
|
1516
1576
|
return `<span style="${styles.join(";")}">${children}</span>`;
|
|
1577
|
+
},
|
|
1578
|
+
markdownTokenizer: {
|
|
1579
|
+
name: "textStyle",
|
|
1580
|
+
level: "inline",
|
|
1581
|
+
start(src) {
|
|
1582
|
+
const match = /<span\b[^>]*\bstyle\s*=/i.exec(src);
|
|
1583
|
+
return match ? match.index : -1;
|
|
1584
|
+
},
|
|
1585
|
+
tokenize(src, _tokens, lexer) {
|
|
1586
|
+
const matched = matchTextStyleSpan(src);
|
|
1587
|
+
if (!matched) return void 0;
|
|
1588
|
+
return {
|
|
1589
|
+
type: "textStyle",
|
|
1590
|
+
raw: matched.raw,
|
|
1591
|
+
style: matched.style,
|
|
1592
|
+
tokens: lexer.inlineTokens(matched.inner)
|
|
1593
|
+
};
|
|
1594
|
+
}
|
|
1595
|
+
},
|
|
1596
|
+
parseMarkdown: (token, helpers) => {
|
|
1597
|
+
const attrs = parseTextStyleAttrs(String(token.style ?? ""));
|
|
1598
|
+
const content = helpers.parseInline(token.tokens ?? []);
|
|
1599
|
+
if (!attrs) return content;
|
|
1600
|
+
return helpers.applyMark("textStyle", content, attrs);
|
|
1601
|
+
}
|
|
1602
|
+
});
|
|
1603
|
+
function readHighlightColor(attrs) {
|
|
1604
|
+
const data = /\bdata-color\s*=\s*(?:"([^"]*)"|'([^']*)')/i.exec(attrs);
|
|
1605
|
+
const fromData = ((data == null ? void 0 : data[1]) ?? (data == null ? void 0 : data[2]) ?? "").trim();
|
|
1606
|
+
if (fromData && isSafeColor(fromData)) return fromData;
|
|
1607
|
+
const style = /\bstyle\s*=\s*(?:"([^"]*)"|'([^']*)')/i.exec(attrs);
|
|
1608
|
+
const styleText = (style == null ? void 0 : style[1]) ?? (style == null ? void 0 : style[2]) ?? "";
|
|
1609
|
+
for (const entry of styleText.split(";")) {
|
|
1610
|
+
const index = entry.indexOf(":");
|
|
1611
|
+
if (index < 0) continue;
|
|
1612
|
+
const key = entry.slice(0, index).trim().toLowerCase();
|
|
1613
|
+
const value = entry.slice(index + 1).trim();
|
|
1614
|
+
if (key === "background-color" && isSafeColor(value)) return value;
|
|
1615
|
+
}
|
|
1616
|
+
return null;
|
|
1617
|
+
}
|
|
1618
|
+
function matchHighlightMark(src) {
|
|
1619
|
+
const open = /^<mark\b([^>]*)>/i.exec(src);
|
|
1620
|
+
if (!open || /\/\s*$/.test(open[1])) return void 0;
|
|
1621
|
+
if (/data-comment-ids/i.test(open[1]) || /\btmr-comment\b/.test(open[1])) {
|
|
1622
|
+
return void 0;
|
|
1623
|
+
}
|
|
1624
|
+
const color = readHighlightColor(open[1]);
|
|
1625
|
+
const tagRe = /<\/?mark\b[^>]*>/i;
|
|
1626
|
+
let depth = 1;
|
|
1627
|
+
let cursor = open[0].length;
|
|
1628
|
+
while (cursor < src.length) {
|
|
1629
|
+
const found = tagRe.exec(src.slice(cursor));
|
|
1630
|
+
if (!found) return void 0;
|
|
1631
|
+
const tag = found[0];
|
|
1632
|
+
const at = cursor + found.index;
|
|
1633
|
+
if (tag.startsWith("</")) {
|
|
1634
|
+
depth -= 1;
|
|
1635
|
+
if (depth === 0) {
|
|
1636
|
+
return {
|
|
1637
|
+
raw: src.slice(0, at + tag.length),
|
|
1638
|
+
inner: src.slice(open[0].length, at),
|
|
1639
|
+
color
|
|
1640
|
+
};
|
|
1641
|
+
}
|
|
1642
|
+
} else if (!/\/\s*>$/.test(tag)) {
|
|
1643
|
+
depth += 1;
|
|
1644
|
+
}
|
|
1645
|
+
cursor = at + tag.length;
|
|
1646
|
+
}
|
|
1647
|
+
return void 0;
|
|
1648
|
+
}
|
|
1649
|
+
const MarkdownHighlight = Highlight.extend({
|
|
1650
|
+
renderMarkdown(node, helpers) {
|
|
1651
|
+
var _a;
|
|
1652
|
+
const children = helpers.renderChildren(node);
|
|
1653
|
+
const color = typeof ((_a = node.attrs) == null ? void 0 : _a.color) === "string" ? node.attrs.color : "";
|
|
1654
|
+
if (!color || !isSafeColor(color)) return `==${children}==`;
|
|
1655
|
+
const encoded = color.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
1656
|
+
return `<mark data-color="${encoded}" style="background-color:${encoded}">${children}</mark>`;
|
|
1657
|
+
},
|
|
1658
|
+
markdownTokenizer: {
|
|
1659
|
+
name: "highlight",
|
|
1660
|
+
level: "inline",
|
|
1661
|
+
start(src) {
|
|
1662
|
+
const mark = /<mark\b/i.exec(src);
|
|
1663
|
+
const eq = src.indexOf("==");
|
|
1664
|
+
const indexes = [mark == null ? void 0 : mark.index, eq >= 0 ? eq : void 0].filter(
|
|
1665
|
+
(index) => index != null
|
|
1666
|
+
);
|
|
1667
|
+
return indexes.length ? Math.min(...indexes) : -1;
|
|
1668
|
+
},
|
|
1669
|
+
tokenize(src, _tokens, lexer) {
|
|
1670
|
+
if (src.startsWith("==")) {
|
|
1671
|
+
const match = /^(==)([^=]+)(==)/.exec(src);
|
|
1672
|
+
if (!match) return void 0;
|
|
1673
|
+
const inner = match[2].trim();
|
|
1674
|
+
return {
|
|
1675
|
+
type: "highlight",
|
|
1676
|
+
raw: match[0],
|
|
1677
|
+
text: inner,
|
|
1678
|
+
tokens: lexer.inlineTokens(inner)
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1681
|
+
const matched = matchHighlightMark(src);
|
|
1682
|
+
if (!matched) return void 0;
|
|
1683
|
+
return {
|
|
1684
|
+
type: "highlight",
|
|
1685
|
+
raw: matched.raw,
|
|
1686
|
+
color: matched.color,
|
|
1687
|
+
tokens: lexer.inlineTokens(matched.inner)
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
},
|
|
1691
|
+
parseMarkdown: (token, helpers) => {
|
|
1692
|
+
const content = helpers.parseInline(token.tokens ?? []);
|
|
1693
|
+
const color = typeof token.color === "string" ? token.color : "";
|
|
1694
|
+
if (color && isSafeColor(color)) {
|
|
1695
|
+
return helpers.applyMark("highlight", content, { color });
|
|
1696
|
+
}
|
|
1697
|
+
return helpers.applyMark("highlight", content);
|
|
1517
1698
|
}
|
|
1518
1699
|
});
|
|
1519
1700
|
function htmlTagTokenizer(tag, tokenType) {
|
|
@@ -1593,8 +1774,62 @@ const MarkdownParagraph = Paragraph.extend({
|
|
|
1593
1774
|
markdownTokenizer: paragraphMarkdownTokenizer,
|
|
1594
1775
|
parseMarkdown: paragraphParseMarkdown
|
|
1595
1776
|
});
|
|
1777
|
+
function clearFontSizeInTextblocks({ state, tr }) {
|
|
1778
|
+
const markType = state.schema.marks.textStyle;
|
|
1779
|
+
const boldType = state.schema.marks.bold;
|
|
1780
|
+
const ranges = [];
|
|
1781
|
+
const { from, to } = state.selection;
|
|
1782
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
1783
|
+
if (!node.isTextblock) return;
|
|
1784
|
+
const start = pos + 1;
|
|
1785
|
+
const end = pos + node.nodeSize - 1;
|
|
1786
|
+
if (boldType) tr.removeMark(start, end, boldType);
|
|
1787
|
+
if (!markType) return false;
|
|
1788
|
+
node.descendants((child, childPos) => {
|
|
1789
|
+
if (!child.isText) return;
|
|
1790
|
+
const mark = child.marks.find((item) => item.type === markType);
|
|
1791
|
+
if (!(mark == null ? void 0 : mark.attrs.fontSize)) return;
|
|
1792
|
+
const childStart = pos + 1 + childPos;
|
|
1793
|
+
ranges.push({
|
|
1794
|
+
from: childStart,
|
|
1795
|
+
to: childStart + child.nodeSize,
|
|
1796
|
+
attrs: { ...mark.attrs, fontSize: null }
|
|
1797
|
+
});
|
|
1798
|
+
});
|
|
1799
|
+
return false;
|
|
1800
|
+
});
|
|
1801
|
+
for (const range of ranges) {
|
|
1802
|
+
if (!markType) continue;
|
|
1803
|
+
tr.removeMark(range.from, range.to, markType);
|
|
1804
|
+
const keep = Object.values(range.attrs).some(
|
|
1805
|
+
(value) => value != null && value !== ""
|
|
1806
|
+
);
|
|
1807
|
+
if (keep) tr.addMark(range.from, range.to, markType.create(range.attrs));
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1596
1810
|
const MarkdownHeading = Heading.extend({
|
|
1597
|
-
renderMarkdown: headingRenderMarkdown
|
|
1811
|
+
renderMarkdown: headingRenderMarkdown,
|
|
1812
|
+
addCommands() {
|
|
1813
|
+
var _a;
|
|
1814
|
+
const parent = (_a = this.parent) == null ? void 0 : _a.call(this);
|
|
1815
|
+
return {
|
|
1816
|
+
...parent,
|
|
1817
|
+
setHeading: (attributes) => (props) => {
|
|
1818
|
+
var _a2, _b;
|
|
1819
|
+
if (!this.options.levels.includes(attributes.level)) return false;
|
|
1820
|
+
clearFontSizeInTextblocks(props);
|
|
1821
|
+
return ((_b = (_a2 = parent == null ? void 0 : parent.setHeading) == null ? void 0 : _a2.call(parent, attributes)) == null ? void 0 : _b(props)) ?? false;
|
|
1822
|
+
},
|
|
1823
|
+
toggleHeading: (attributes) => (props) => {
|
|
1824
|
+
var _a2, _b;
|
|
1825
|
+
if (!this.options.levels.includes(attributes.level)) return false;
|
|
1826
|
+
if (!props.editor.isActive(this.name, attributes)) {
|
|
1827
|
+
clearFontSizeInTextblocks(props);
|
|
1828
|
+
}
|
|
1829
|
+
return ((_b = (_a2 = parent == null ? void 0 : parent.toggleHeading) == null ? void 0 : _a2.call(parent, attributes)) == null ? void 0 : _b(props)) ?? false;
|
|
1830
|
+
}
|
|
1831
|
+
};
|
|
1832
|
+
}
|
|
1598
1833
|
});
|
|
1599
1834
|
const DetailsBlock = Details.extend({
|
|
1600
1835
|
addAttributes() {
|
|
@@ -1638,7 +1873,7 @@ const baseExtensions = [
|
|
|
1638
1873
|
// 正文字号:官方 FontSize(v3 起并入 text-style 包),以内联样式挂在 TextStyle
|
|
1639
1874
|
// 的 <span> 上(如 style="font-size: 16px"),与 Color 同基座,三端共用。
|
|
1640
1875
|
FontSize.configure({ types: [TextStyle.name] }),
|
|
1641
|
-
|
|
1876
|
+
MarkdownHighlight.configure({ multicolor: true }),
|
|
1642
1877
|
MarkdownSuperscript,
|
|
1643
1878
|
MarkdownSubscript,
|
|
1644
1879
|
TableKit.configure({
|
|
@@ -1760,4 +1995,4 @@ export {
|
|
|
1760
1995
|
NUMBERING_FORMAT_LABELS as u,
|
|
1761
1996
|
NUMBERING_FORMAT_PREVIEWS as v
|
|
1762
1997
|
};
|
|
1763
|
-
//# sourceMappingURL=extractToc-
|
|
1998
|
+
//# sourceMappingURL=extractToc-Bz924Nh4.js.map
|