@wenyan-md/core 3.0.8 → 3.0.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/core.js +166 -44
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/parser/frontMatterParser.d.ts +1 -0
- package/dist/types/core/renderer/mermaidPostRender.d.ts +1 -0
- package/dist/types/core/utils.d.ts +1 -0
- package/dist/wechat.js +5 -1
- package/dist/wrapper.js +67 -9
- package/package.json +1 -1
package/dist/core.js
CHANGED
|
@@ -100,6 +100,12 @@ async function loadCssBySource(source) {
|
|
|
100
100
|
throw new Error("Unknown source type");
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
+
function createSvgDataUrl(svg) {
|
|
104
|
+
if (!svg.hasAttribute("xmlns")) {
|
|
105
|
+
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
|
|
106
|
+
}
|
|
107
|
+
return `data:image/svg+xml,${encodeURIComponent(svg.outerHTML)}`;
|
|
108
|
+
}
|
|
103
109
|
const __vite_glob_0_0$1 = "pre{background:#282c34}pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}";
|
|
104
110
|
const __vite_glob_0_1$1 = "pre{background:#fafafa}pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#383a42;background:#fafafa}.hljs-comment,.hljs-quote{color:#a0a1a7;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#a626a4}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e45649}.hljs-literal{color:#0184bb}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#50a14f}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#986801}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#4078f2}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#c18401}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}";
|
|
105
111
|
const __vite_glob_0_2$1 = "pre{background:#282936}pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#e9e9f4;background:#282936}.hljs ::selection,.hljs::selection{background-color:#4d4f68;color:#e9e9f4}.hljs-comment{color:#626483}.hljs-tag{color:#62d6e8}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#e9e9f4}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ea51b2}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#b45bcf}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#00f769}.hljs-strong{font-weight:700;color:#00f769}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#ebff87}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#a1efe4}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#62d6e8}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#b45bcf}.hljs-emphasis{color:#b45bcf;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#00f769}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}\n";
|
|
@@ -196,7 +202,7 @@ async function handleFrontMatter(markdown) {
|
|
|
196
202
|
const { attributes, body } = fm(markdown);
|
|
197
203
|
const result = { content: body || "" };
|
|
198
204
|
let head = "";
|
|
199
|
-
const { title, description, cover, author, source_url, need_open_comment, only_fans_can_comment, image_list } = attributes;
|
|
205
|
+
const { title, description, cover, author, source_url, need_open_comment, only_fans_can_comment, image_list, type } = attributes;
|
|
200
206
|
if (title) {
|
|
201
207
|
result.title = title;
|
|
202
208
|
}
|
|
@@ -207,9 +213,6 @@ async function handleFrontMatter(markdown) {
|
|
|
207
213
|
if (cover) {
|
|
208
214
|
result.cover = cover;
|
|
209
215
|
}
|
|
210
|
-
if (head) {
|
|
211
|
-
result.content = head + result.content;
|
|
212
|
-
}
|
|
213
216
|
if (author) {
|
|
214
217
|
result.author = author;
|
|
215
218
|
}
|
|
@@ -225,6 +228,12 @@ async function handleFrontMatter(markdown) {
|
|
|
225
228
|
if (image_list) {
|
|
226
229
|
result.image_list = image_list;
|
|
227
230
|
}
|
|
231
|
+
if (type) {
|
|
232
|
+
result.type = type;
|
|
233
|
+
}
|
|
234
|
+
if (head) {
|
|
235
|
+
result.content = head + result.content;
|
|
236
|
+
}
|
|
228
237
|
return result;
|
|
229
238
|
}
|
|
230
239
|
const parseOptions = {
|
|
@@ -467,6 +476,44 @@ function createMarkedClient() {
|
|
|
467
476
|
};
|
|
468
477
|
}
|
|
469
478
|
},
|
|
479
|
+
// Obsidian WikiLinks 图片语法扩展 ![[filename]] / ![[filename|alt]] / ![[filename|width]] / ![[filename|widthxheight]]
|
|
480
|
+
{
|
|
481
|
+
name: "wikiImage",
|
|
482
|
+
level: "inline",
|
|
483
|
+
start(src) {
|
|
484
|
+
return src.match(/!\[\[/)?.index;
|
|
485
|
+
},
|
|
486
|
+
tokenizer(src) {
|
|
487
|
+
const rule = /^!\[\[([^\]|]+?)(?:\|([^\]]*))?\]\]/;
|
|
488
|
+
const match = rule.exec(src);
|
|
489
|
+
if (!match) return;
|
|
490
|
+
const href = match[1].trim();
|
|
491
|
+
const modifier = match[2]?.trim() ?? "";
|
|
492
|
+
const dimOnly = /^(\d+)(?:x(\d+))?$/.exec(modifier);
|
|
493
|
+
const alt = dimOnly ? "" : modifier;
|
|
494
|
+
const width = dimOnly ? dimOnly[1] : "";
|
|
495
|
+
const height = dimOnly ? dimOnly[2] ?? "" : "";
|
|
496
|
+
return {
|
|
497
|
+
type: "wikiImage",
|
|
498
|
+
raw: match[0],
|
|
499
|
+
href,
|
|
500
|
+
alt,
|
|
501
|
+
width,
|
|
502
|
+
height,
|
|
503
|
+
tokens: []
|
|
504
|
+
};
|
|
505
|
+
},
|
|
506
|
+
renderer(token) {
|
|
507
|
+
const href = normalizeHref(token.href);
|
|
508
|
+
const altAttr = token.alt ? ` alt="${token.alt}"` : "";
|
|
509
|
+
const titleAttr = token.alt ? ` title="${token.alt}"` : "";
|
|
510
|
+
const styleParts = [];
|
|
511
|
+
if (token.width) styleParts.push(`width:${token.width}px`);
|
|
512
|
+
if (token.height) styleParts.push(`height:${token.height}px`);
|
|
513
|
+
const styleAttr = styleParts.length ? ` style="${styleParts.join("; ")}"` : "";
|
|
514
|
+
return `<img src="${href}"${altAttr}${titleAttr}${styleAttr}>`;
|
|
515
|
+
}
|
|
516
|
+
},
|
|
470
517
|
// 自定义图片语法扩展 ![](){...}
|
|
471
518
|
{
|
|
472
519
|
name: "attributeImage",
|
|
@@ -646,24 +693,7 @@ function containsMermaidCodeBlock(html) {
|
|
|
646
693
|
return html.includes("language-mermaid");
|
|
647
694
|
}
|
|
648
695
|
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
649
|
-
function
|
|
650
|
-
const mathElements = element.querySelectorAll("mjx-container");
|
|
651
|
-
mathElements.forEach((mathContainer) => {
|
|
652
|
-
const svg = mathContainer.querySelector("svg");
|
|
653
|
-
if (!svg) return;
|
|
654
|
-
svg.style.width = svg.getAttribute("width") || "";
|
|
655
|
-
svg.style.height = svg.getAttribute("height") || "";
|
|
656
|
-
svg.removeAttribute("width");
|
|
657
|
-
svg.removeAttribute("height");
|
|
658
|
-
const parent = mathContainer.parentElement;
|
|
659
|
-
if (parent) {
|
|
660
|
-
mathContainer.remove();
|
|
661
|
-
parent.appendChild(svg);
|
|
662
|
-
if (parent.classList.contains("block-equation")) {
|
|
663
|
-
parent.setAttribute("style", "text-align: center; margin-bottom: 1rem;");
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
});
|
|
696
|
+
function postRenderMermaidDiagrams(element) {
|
|
667
697
|
const mermaidSvgs = element.querySelectorAll('[data-wenyan-diagram="mermaid"] svg');
|
|
668
698
|
mermaidSvgs.forEach((svg) => {
|
|
669
699
|
svg.style.maxWidth = "100%";
|
|
@@ -671,21 +701,6 @@ function wechatPostRender(element) {
|
|
|
671
701
|
inlineMermaidSvgStyles(svg);
|
|
672
702
|
flattenMermaidMarkers(svg);
|
|
673
703
|
});
|
|
674
|
-
const codeElements = element.querySelectorAll("pre code");
|
|
675
|
-
codeElements.forEach((codeEl) => {
|
|
676
|
-
codeEl.innerHTML = codeEl.innerHTML.replace(/\n/g, "<br>").replace(/(>[^<]+)|(^[^<]+)/g, (str) => str.replace(/\s/g, " "));
|
|
677
|
-
});
|
|
678
|
-
const listElements = element.querySelectorAll("li");
|
|
679
|
-
listElements.forEach((li) => {
|
|
680
|
-
const doc = element.ownerDocument;
|
|
681
|
-
const section = doc.createElement("section");
|
|
682
|
-
while (li.firstChild) {
|
|
683
|
-
section.appendChild(li.firstChild);
|
|
684
|
-
}
|
|
685
|
-
li.appendChild(section);
|
|
686
|
-
});
|
|
687
|
-
element.style.color = "rgb(0, 0, 0)";
|
|
688
|
-
element.style.caretColor = "rgb(0, 0, 0)";
|
|
689
704
|
}
|
|
690
705
|
function inlineMermaidSvgStyles(svg) {
|
|
691
706
|
const styleElements = Array.from(svg.querySelectorAll("style"));
|
|
@@ -949,6 +964,50 @@ function isInlineStyleTarget(node) {
|
|
|
949
964
|
}
|
|
950
965
|
return node instanceof defaultView.SVGElement || node instanceof defaultView.HTMLElement;
|
|
951
966
|
}
|
|
967
|
+
function wechatPostRender(element) {
|
|
968
|
+
const mathElements = element.querySelectorAll("mjx-container");
|
|
969
|
+
mathElements.forEach((mathContainer) => {
|
|
970
|
+
const svg = mathContainer.querySelector("svg");
|
|
971
|
+
if (!svg) return;
|
|
972
|
+
svg.style.width = svg.getAttribute("width") || "";
|
|
973
|
+
svg.style.height = svg.getAttribute("height") || "";
|
|
974
|
+
svg.removeAttribute("width");
|
|
975
|
+
svg.removeAttribute("height");
|
|
976
|
+
const parent = mathContainer.parentElement;
|
|
977
|
+
if (parent) {
|
|
978
|
+
mathContainer.remove();
|
|
979
|
+
parent.appendChild(svg);
|
|
980
|
+
if (parent.classList.contains("block-equation")) {
|
|
981
|
+
parent.setAttribute("style", "text-align: center; margin-bottom: 1rem;");
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
});
|
|
985
|
+
postRenderMermaidDiagrams(element);
|
|
986
|
+
const codeElements = element.querySelectorAll("pre code");
|
|
987
|
+
codeElements.forEach((codeEl) => {
|
|
988
|
+
codeEl.innerHTML = codeEl.innerHTML.replace(/\n/g, "<br>").replace(/(>[^<]+)|(^[^<]+)/g, (str) => str.replace(/\s/g, " "));
|
|
989
|
+
});
|
|
990
|
+
const listElements = element.querySelectorAll("li");
|
|
991
|
+
listElements.forEach((li) => {
|
|
992
|
+
const doc = element.ownerDocument;
|
|
993
|
+
const section = doc.createElement("section");
|
|
994
|
+
while (li.firstChild) {
|
|
995
|
+
section.appendChild(li.firstChild);
|
|
996
|
+
}
|
|
997
|
+
li.appendChild(section);
|
|
998
|
+
});
|
|
999
|
+
const nestedLists = element.querySelectorAll(
|
|
1000
|
+
"li > section > ul, li > section > ol"
|
|
1001
|
+
);
|
|
1002
|
+
nestedLists.forEach((nestedList) => {
|
|
1003
|
+
const li = nestedList.closest("li");
|
|
1004
|
+
if (li) {
|
|
1005
|
+
li.insertAdjacentElement("afterend", nestedList);
|
|
1006
|
+
}
|
|
1007
|
+
});
|
|
1008
|
+
element.style.color = "rgb(0, 0, 0)";
|
|
1009
|
+
element.style.caretColor = "rgb(0, 0, 0)";
|
|
1010
|
+
}
|
|
952
1011
|
const themeModifier = createCssModifier({});
|
|
953
1012
|
function renderTheme(wenyanElement, themeCss) {
|
|
954
1013
|
const modifiedCss = themeModifier(themeCss);
|
|
@@ -1492,6 +1551,8 @@ function getContentForZhihu(wenyanElement) {
|
|
|
1492
1551
|
return wenyanElement.outerHTML;
|
|
1493
1552
|
}
|
|
1494
1553
|
function getContentForToutiao(wenyanElement) {
|
|
1554
|
+
postRenderMermaidDiagrams(wenyanElement);
|
|
1555
|
+
processMermaid(wenyanElement);
|
|
1495
1556
|
const containers = wenyanElement.querySelectorAll("mjx-container");
|
|
1496
1557
|
const doc = wenyanElement.ownerDocument;
|
|
1497
1558
|
containers.forEach((container) => {
|
|
@@ -1500,11 +1561,7 @@ function getContentForToutiao(wenyanElement) {
|
|
|
1500
1561
|
return;
|
|
1501
1562
|
}
|
|
1502
1563
|
const img = doc.createElement("img");
|
|
1503
|
-
|
|
1504
|
-
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
|
|
1505
|
-
}
|
|
1506
|
-
const encodedSVG = encodeURIComponent(svg.outerHTML);
|
|
1507
|
-
img.src = `data:image/svg+xml,${encodedSVG}`;
|
|
1564
|
+
img.src = createSvgDataUrl(svg);
|
|
1508
1565
|
const style = svg.getAttribute("style");
|
|
1509
1566
|
if (style) {
|
|
1510
1567
|
img.setAttribute("style", style);
|
|
@@ -1519,10 +1576,67 @@ function getContentForToutiao(wenyanElement) {
|
|
|
1519
1576
|
});
|
|
1520
1577
|
return wenyanElement.outerHTML;
|
|
1521
1578
|
}
|
|
1579
|
+
function processMermaid(root) {
|
|
1580
|
+
const figures = root.querySelectorAll('[data-wenyan-diagram="mermaid"]');
|
|
1581
|
+
const doc = root.ownerDocument;
|
|
1582
|
+
figures.forEach((figure) => {
|
|
1583
|
+
const svg = figure.querySelector("svg");
|
|
1584
|
+
if (!svg) {
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
let svgString = svg.outerHTML;
|
|
1588
|
+
svgString = fixMermaidSvgForServerRender(svgString);
|
|
1589
|
+
const img = doc.createElement("img");
|
|
1590
|
+
const encodedData = btoa(unescape(encodeURIComponent(svgString)));
|
|
1591
|
+
img.src = `data:image/svg+xml;base64,${encodedData}`;
|
|
1592
|
+
const style = svg.getAttribute("style");
|
|
1593
|
+
if (style) {
|
|
1594
|
+
img.setAttribute("style", style);
|
|
1595
|
+
}
|
|
1596
|
+
const ariaLabel = figure.getAttribute("aria-label") || figure.getAttribute("title") || svg.getAttribute("aria-label") || svg.getAttribute("title");
|
|
1597
|
+
if (ariaLabel) {
|
|
1598
|
+
img.alt = ariaLabel;
|
|
1599
|
+
}
|
|
1600
|
+
figure.replaceWith(img);
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
function fixMermaidSvgForServerRender(svgString) {
|
|
1604
|
+
const baseFontSize = 16;
|
|
1605
|
+
let fixedSvg = svgString;
|
|
1606
|
+
fixedSvg = fixedSvg.replace(/([xy]|dx|dy)="([-0-9.]+)em"/g, (_, attr, val) => {
|
|
1607
|
+
const pxValue = parseFloat(val) * baseFontSize;
|
|
1608
|
+
return `${attr}="${pxValue}px"`;
|
|
1609
|
+
});
|
|
1610
|
+
let previousSvg;
|
|
1611
|
+
do {
|
|
1612
|
+
previousSvg = fixedSvg;
|
|
1613
|
+
fixedSvg = fixedSvg.replace(/<tspan(?![^>]*\b[xy]=)[^>]*>([\s\S]*?)<\/tspan>/g, "$1");
|
|
1614
|
+
} while (fixedSvg !== previousSvg);
|
|
1615
|
+
fixedSvg = fixedSvg.replace(/<tspan([^>]+)>/g, (match, attrs) => {
|
|
1616
|
+
const yMatch = attrs.match(/y="([-0-9.]+)(?:px)?"/);
|
|
1617
|
+
const dyMatch = attrs.match(/dy="([-0-9.]+)(?:px)?"/);
|
|
1618
|
+
if (yMatch && dyMatch) {
|
|
1619
|
+
const yVal = parseFloat(yMatch[1]);
|
|
1620
|
+
const dyVal = parseFloat(dyMatch[1]);
|
|
1621
|
+
const finalY = yVal + dyVal;
|
|
1622
|
+
let newAttrs = attrs.replace(/y="[-0-9.]+(?:px)?"\s*/, "").replace(/dy="[-0-9.]+(?:px)?"\s*/, "");
|
|
1623
|
+
return `<tspan ${newAttrs.trim()} y="${finalY}">`;
|
|
1624
|
+
}
|
|
1625
|
+
return match;
|
|
1626
|
+
});
|
|
1627
|
+
fixedSvg = fixedSvg.replace(/class="([^"]*?)text-inner-tspan([^"]*?)"/g, 'class="$1$2"');
|
|
1628
|
+
fixedSvg = fixedSvg.replace(/\sclass=""/g, "");
|
|
1629
|
+
return fixedSvg;
|
|
1630
|
+
}
|
|
1631
|
+
const DEFAULT_MERMAID_FONT_FAMILY = "'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans CJK SC', 'Source Han Sans SC', Arial, sans-serif";
|
|
1522
1632
|
const DEFAULT_MERMAID_CONFIG = {
|
|
1633
|
+
fontFamily: DEFAULT_MERMAID_FONT_FAMILY,
|
|
1523
1634
|
htmlLabels: false,
|
|
1524
1635
|
flowchart: {
|
|
1525
1636
|
htmlLabels: false
|
|
1637
|
+
},
|
|
1638
|
+
themeVariables: {
|
|
1639
|
+
fontFamily: DEFAULT_MERMAID_FONT_FAMILY
|
|
1526
1640
|
}
|
|
1527
1641
|
};
|
|
1528
1642
|
async function replaceMermaidCodeBlocks(root, renderDiagram) {
|
|
@@ -1587,6 +1701,7 @@ function createMermaidRenderError(error) {
|
|
|
1587
1701
|
}
|
|
1588
1702
|
function createMermaidConfig(overrides = {}) {
|
|
1589
1703
|
const flowchartOverrides = getRecord(overrides.flowchart);
|
|
1704
|
+
const themeVariablesOverrides = getRecord(overrides.themeVariables);
|
|
1590
1705
|
return {
|
|
1591
1706
|
...DEFAULT_MERMAID_CONFIG,
|
|
1592
1707
|
startOnLoad: false,
|
|
@@ -1595,6 +1710,10 @@ function createMermaidConfig(overrides = {}) {
|
|
|
1595
1710
|
flowchart: {
|
|
1596
1711
|
...getRecord(DEFAULT_MERMAID_CONFIG.flowchart),
|
|
1597
1712
|
...flowchartOverrides
|
|
1713
|
+
},
|
|
1714
|
+
themeVariables: {
|
|
1715
|
+
...getRecord(DEFAULT_MERMAID_CONFIG.themeVariables),
|
|
1716
|
+
...themeVariablesOverrides
|
|
1598
1717
|
}
|
|
1599
1718
|
};
|
|
1600
1719
|
}
|
|
@@ -1625,12 +1744,15 @@ async function createWenyanCore(options = {}) {
|
|
|
1625
1744
|
async handleFrontMatter(markdown) {
|
|
1626
1745
|
return await handleFrontMatter(markdown);
|
|
1627
1746
|
},
|
|
1628
|
-
async renderMarkdown(markdown) {
|
|
1747
|
+
async renderMarkdown(markdown, disableMermaid = false) {
|
|
1629
1748
|
let html = await markedClient.parse(markdown);
|
|
1630
1749
|
if (isConvertMathJax) {
|
|
1631
1750
|
html = mathJaxParser.parser(html);
|
|
1632
1751
|
}
|
|
1633
|
-
|
|
1752
|
+
if (!disableMermaid) {
|
|
1753
|
+
html = await mermaidParser.parser(html);
|
|
1754
|
+
}
|
|
1755
|
+
return html;
|
|
1634
1756
|
},
|
|
1635
1757
|
async applyStylesWithTheme(wenyanElement, options2 = {}) {
|
|
1636
1758
|
const {
|
|
@@ -15,7 +15,7 @@ export interface ApplyStylesOptions {
|
|
|
15
15
|
}
|
|
16
16
|
export declare function createWenyanCore(options?: WenyanOptions): Promise<{
|
|
17
17
|
handleFrontMatter(markdown: string): Promise<FrontMatterResult>;
|
|
18
|
-
renderMarkdown(markdown: string): Promise<string>;
|
|
18
|
+
renderMarkdown(markdown: string, disableMermaid?: boolean): Promise<string>;
|
|
19
19
|
applyStylesWithTheme(wenyanElement: HTMLElement, options?: ApplyStylesOptions): Promise<string>;
|
|
20
20
|
applyStylesWithResolvedCss(wenyanElement: HTMLElement, options: {
|
|
21
21
|
themeCss: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function postRenderMermaidDiagrams(element: HTMLElement): void;
|
package/dist/wechat.js
CHANGED
|
@@ -40,9 +40,13 @@ function createWechatClient(httpAdapter) {
|
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
+
const WECHAT_ERROR_HINTS = {
|
|
44
|
+
45166: "内容超长。小绿书模式有内容长度限制,请精简正文后重试。"
|
|
45
|
+
};
|
|
43
46
|
function assertWechatSuccess(data) {
|
|
44
47
|
if ("errcode" in data) {
|
|
45
|
-
|
|
48
|
+
const hint = WECHAT_ERROR_HINTS[data.errcode];
|
|
49
|
+
throw new Error(hint ? `${data.errcode}: ${hint} (${data.errmsg})` : `${data.errcode}: ${data.errmsg}`);
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
52
|
export {
|
package/dist/wrapper.js
CHANGED
|
@@ -269,7 +269,8 @@ function needUpload(url) {
|
|
|
269
269
|
return !/^(https?:\/\/|data:|asset:\/\/)/i.test(url);
|
|
270
270
|
}
|
|
271
271
|
async function uploadLocalImage(originalUrl, serverUrl, headers, relativePath) {
|
|
272
|
-
const
|
|
272
|
+
const decodedUrl = decodeURIComponent(originalUrl);
|
|
273
|
+
const imagePath = RuntimeEnv.resolveLocalPath(decodedUrl, relativePath);
|
|
273
274
|
let fileBuffer;
|
|
274
275
|
try {
|
|
275
276
|
fileBuffer = await readBinaryFile(imagePath);
|
|
@@ -435,7 +436,8 @@ async function uploadImage(imageUrl, accessToken, fileName, relativePath, appId)
|
|
|
435
436
|
const contentType = response.headers.get("content-type") || "image/jpeg";
|
|
436
437
|
fileData = new Blob([arrayBuffer], { type: contentType });
|
|
437
438
|
} else {
|
|
438
|
-
const
|
|
439
|
+
const decodedUrl = decodeURIComponent(imageUrl);
|
|
440
|
+
const resolvedPath = RuntimeEnv.resolveLocalPath(decodedUrl, relativePath);
|
|
439
441
|
const stats = await stat(resolvedPath);
|
|
440
442
|
if (stats.size === 0) {
|
|
441
443
|
throw new Error(`本地图片大小为0,无法上传: ${resolvedPath}`);
|
|
@@ -731,14 +733,14 @@ function ensureSvgPolyfills(window) {
|
|
|
731
733
|
value() {
|
|
732
734
|
const tagName = this.tagName.toLowerCase();
|
|
733
735
|
if (tagName === "text" || tagName === "tspan") {
|
|
734
|
-
const
|
|
735
|
-
const
|
|
736
|
+
const width = getEstimatedTextWidth(this);
|
|
737
|
+
const height = getEstimatedFontSize(this);
|
|
736
738
|
return {
|
|
737
739
|
x: 0,
|
|
738
|
-
y: -
|
|
740
|
+
y: -height,
|
|
739
741
|
width,
|
|
740
|
-
height
|
|
741
|
-
top: -
|
|
742
|
+
height,
|
|
743
|
+
top: -height,
|
|
742
744
|
right: width,
|
|
743
745
|
bottom: 0,
|
|
744
746
|
left: 0,
|
|
@@ -809,12 +811,61 @@ function ensureSvgPolyfills(window) {
|
|
|
809
811
|
configurable: true,
|
|
810
812
|
writable: true,
|
|
811
813
|
value() {
|
|
812
|
-
|
|
813
|
-
return Math.max(text.length * 8, 16);
|
|
814
|
+
return getEstimatedTextWidth(this);
|
|
814
815
|
}
|
|
815
816
|
});
|
|
816
817
|
}
|
|
817
818
|
}
|
|
819
|
+
function getEstimatedTextWidth(element) {
|
|
820
|
+
const text = element.textContent ?? "";
|
|
821
|
+
const fontSize = getEstimatedFontSize(element);
|
|
822
|
+
const visualLength = Array.from(text).reduce((length, character) => {
|
|
823
|
+
return length + (isWideCharacter(character) ? 2 : 1);
|
|
824
|
+
}, 0);
|
|
825
|
+
return Math.max(visualLength * (fontSize / 2), fontSize);
|
|
826
|
+
}
|
|
827
|
+
function getEstimatedFontSize(element) {
|
|
828
|
+
const inlineFontSize = element.getAttribute("font-size");
|
|
829
|
+
if (inlineFontSize) {
|
|
830
|
+
const parsed = Number.parseFloat(inlineFontSize);
|
|
831
|
+
if (Number.isFinite(parsed)) {
|
|
832
|
+
return parsed;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
const computedFontSize = element.ownerDocument.defaultView?.getComputedStyle(element).fontSize;
|
|
836
|
+
if (computedFontSize) {
|
|
837
|
+
const parsed = Number.parseFloat(computedFontSize);
|
|
838
|
+
if (Number.isFinite(parsed)) {
|
|
839
|
+
return parsed;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
return 16;
|
|
843
|
+
}
|
|
844
|
+
function isWideCharacter(character) {
|
|
845
|
+
return character.codePointAt(0) > 255;
|
|
846
|
+
}
|
|
847
|
+
async function extractAndCleanImages(body) {
|
|
848
|
+
const html = await wenyanCoreInstance.renderMarkdown(body);
|
|
849
|
+
const dom = new JSDOM(`<body><section id="wenyan">${html}</section></body>`);
|
|
850
|
+
const document = dom.window.document;
|
|
851
|
+
const wenyan = document.getElementById("wenyan");
|
|
852
|
+
const images = Array.from(wenyan.querySelectorAll("img"));
|
|
853
|
+
const imagePaths = images.map((img) => img.getAttribute("src")).filter((src) => !!src).map((src) => {
|
|
854
|
+
try {
|
|
855
|
+
return decodeURI(src);
|
|
856
|
+
} catch {
|
|
857
|
+
return src;
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
for (const img of images) {
|
|
861
|
+
const parent = img.parentElement;
|
|
862
|
+
img.remove();
|
|
863
|
+
if (parent && parent.tagName === "P" && parent.textContent?.trim() === "") {
|
|
864
|
+
parent.remove();
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
return { imagePaths, cleanedHtml: wenyan.outerHTML };
|
|
868
|
+
}
|
|
818
869
|
const nodeMermaidRenderer = createNodeMermaidRenderer();
|
|
819
870
|
const wenyanCoreInstance = await createWenyanCore({
|
|
820
871
|
mermaid: {
|
|
@@ -859,6 +910,13 @@ async function renderStyledContent(content, options = {}, coreInstance = wenyanC
|
|
|
859
910
|
async function prepareRenderContext(inputContent, options, getInputContent) {
|
|
860
911
|
const { content, absoluteDirPath } = await getInputContent(inputContent, options.file);
|
|
861
912
|
const preHandlerContent = await wenyanCoreInstance.handleFrontMatter(content);
|
|
913
|
+
if (preHandlerContent.type === "image" && !preHandlerContent.image_list) {
|
|
914
|
+
const { imagePaths, cleanedHtml } = await extractAndCleanImages(preHandlerContent.content);
|
|
915
|
+
if (imagePaths.length > 0) {
|
|
916
|
+
preHandlerContent.image_list = imagePaths;
|
|
917
|
+
preHandlerContent.content = cleanedHtml;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
862
920
|
if (preHandlerContent.image_list && preHandlerContent.image_list.length > 0) {
|
|
863
921
|
return { gzhContent: preHandlerContent, absoluteDirPath };
|
|
864
922
|
}
|
package/package.json
CHANGED