style: update wx-renderer

This commit is contained in:
yanglbme 2020-11-26 20:10:39 +08:00
parent 580fa64738
commit 88419529f8
3 changed files with 181 additions and 173 deletions

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "vue-md", "name": "vue-md",
"version": "1.4.4", "version": "1.4.5",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "vue-md", "name": "vue-md",
"version": "1.4.4", "version": "1.4.5",
"homepage": ".", "homepage": ".",
"description": "An open-source wechat markdown editor.", "description": "An open-source wechat markdown editor.",
"author": "doocs", "author": "doocs",

View File

@ -1,72 +1,73 @@
import marked from "marked"; import marked from "marked";
const WxRenderer = function (opts) { class WxRenderer {
this.opts = opts; constructor(opts) {
let ENV_STRETCH_IMAGE = true; this.opts = opts;
let ENV_STRETCH_IMAGE = true;
let footnotes = []; let footnotes = [];
let footnoteIndex = 0; let footnoteIndex = 0;
let styleMapping = null; let styleMapping = null;
const CODE_FONT_FAMILY = const CODE_FONT_FAMILY =
"Menlo, Operator Mono, Consolas, Monaco, monospace"; "Menlo, Operator Mono, Consolas, Monaco, monospace";
let merge = (base, extend) => Object.assign({}, base, extend); let merge = (base, extend) => Object.assign({}, base, extend);
this.buildTheme = (themeTpl) => { this.buildTheme = (themeTpl) => {
let mapping = {}; let mapping = {};
let base = merge(themeTpl.BASE, { let base = merge(themeTpl.BASE, {
"font-family": this.opts.fonts, "font-family": this.opts.fonts,
"font-size": this.opts.size, "font-size": this.opts.size,
}); });
let base_block = merge(base, {}); let base_block = merge(base, {});
for (let ele in themeTpl.inline) { for (let ele in themeTpl.inline) {
if (themeTpl.inline.hasOwnProperty(ele)) { if (themeTpl.inline.hasOwnProperty(ele)) {
let style = themeTpl.inline[ele]; let style = themeTpl.inline[ele];
mapping[ele] = merge(base, style); mapping[ele] = merge(base, style);
}
}
for (let ele in themeTpl.block) {
if (themeTpl.block.hasOwnProperty(ele)) {
let style = themeTpl.block[ele];
if (ele === "code") {
style["font-family"] = CODE_FONT_FAMILY;
} }
mapping[ele] = merge(base_block, style);
} }
}
return mapping;
};
let getStyles = (tokenName, addition) => { for (let ele in themeTpl.block) {
let arr = []; if (themeTpl.block.hasOwnProperty(ele)) {
let dict = styleMapping[tokenName]; let style = themeTpl.block[ele];
if (!dict) return ""; if (ele === "code") {
for (const key in dict) { style["font-family"] = CODE_FONT_FAMILY;
arr.push(key + ":" + dict[key]); }
} mapping[ele] = merge(base_block, style);
return `style="${arr.join(";") + (addition || "")}"`; }
};
let addFootnote = (title, link) => {
footnotes.push([++footnoteIndex, title, link]);
return footnoteIndex;
};
this.buildFootnotes = () => {
let footnoteArray = footnotes.map((x) => {
if (x[1] === x[2]) {
return `<code style="font-size: 90%; opacity: 0.6;">[${x[0]}]</code>: <i>${x[1]}</i><br/>`;
} }
return `<code style="font-size: 90%; opacity: 0.6;">[${x[0]}]</code> ${x[1]}: <i>${x[2]}</i><br/>`; return mapping;
}); };
return `<h4 ${getStyles("h4")}>引用链接</h4><p ${getStyles(
"footnotes"
)}>${footnoteArray.join("\n")}</p>`;
};
this.buildAddition = () => { let getStyles = (tokenName, addition) => {
return ` let arr = [];
let dict = styleMapping[tokenName];
if (!dict) return "";
for (const key in dict) {
arr.push(key + ":" + dict[key]);
}
return `style="${arr.join(";") + (addition || "")}"`;
};
let addFootnote = (title, link) => {
footnotes.push([++footnoteIndex, title, link]);
return footnoteIndex;
};
this.buildFootnotes = () => {
let footnoteArray = footnotes.map((x) => {
if (x[1] === x[2]) {
return `<code style="font-size: 90%; opacity: 0.6;">[${x[0]}]</code>: <i>${x[1]}</i><br/>`;
}
return `<code style="font-size: 90%; opacity: 0.6;">[${x[0]}]</code> ${x[1]}: <i>${x[2]}</i><br/>`;
});
return `<h4 ${getStyles("h4")}>引用链接</h4><p ${getStyles(
"footnotes"
)}>${footnoteArray.join("\n")}</p>`;
};
this.buildAddition = () => {
return `
<style> <style>
.preview-wrapper pre::before { .preview-wrapper pre::before {
position: absolute; position: absolute;
@ -82,128 +83,135 @@ const WxRenderer = function (opts) {
} }
</style> </style>
`; `;
};
this.setOptions = (newOpts) => {
this.opts = merge(this.opts, newOpts);
};
this.hasFootnotes = () => footnotes.length !== 0;
this.getRenderer = (status) => {
footnotes = [];
footnoteIndex = 0;
styleMapping = this.buildTheme(this.opts.theme);
let renderer = new marked.Renderer();
renderer.heading = (text, level) => {
switch (level) {
case 1:
return `<h1 ${getStyles("h1")}>${text}</h1>`;
case 2:
return `<h2 ${getStyles("h2")}>${text}</h2>`;
case 3:
return `<h3 ${getStyles("h3")}>${text}</h3>`;
default:
return `<h4 ${getStyles("h4")}>${text}</h4>`;
}
};
renderer.paragraph = (text) => {
if (text.indexOf("<figure") != -1 && text.indexOf("<img") != -1) {
return text;
}
return text.replace(/ /g, "") === ""
? ""
: `<p ${getStyles("p")}>${text}</p>`;
}; };
renderer.blockquote = (text) => { this.setOptions = (newOpts) => {
text = text.replace(/<p.*?>/g, `<p ${getStyles("blockquote_p")}>`); this.opts = merge(this.opts, newOpts);
return `<blockquote ${getStyles(
"blockquote"
)}>${text}</blockquote>`;
}; };
renderer.code = (text, lang) => {
text = text.replace(/</g, "&lt;").replace(/>/g, "&gt;"); this.hasFootnotes = () => footnotes.length !== 0;
const codeLines = text
.split("\n") this.getRenderer = (status) => {
.map( footnotes = [];
(line) => footnoteIndex = 0;
`<code class="prettyprint"><span class="code-snippet_outer">${
line || "<br>" styleMapping = this.buildTheme(this.opts.theme);
}</span></code>` let renderer = new marked.Renderer();
renderer.heading = (text, level) => {
switch (level) {
case 1:
return `<h1 ${getStyles("h1")}>${text}</h1>`;
case 2:
return `<h2 ${getStyles("h2")}>${text}</h2>`;
case 3:
return `<h3 ${getStyles("h3")}>${text}</h3>`;
default:
return `<h4 ${getStyles("h4")}>${text}</h4>`;
}
};
renderer.paragraph = (text) => {
if (
text.indexOf("<figure") != -1 &&
text.indexOf("<img") != -1
) {
return text;
}
return text.replace(/ /g, "") === ""
? ""
: `<p ${getStyles("p")}>${text}</p>`;
};
renderer.blockquote = (text) => {
text = text.replace(
/<p.*?>/g,
`<p ${getStyles("blockquote_p")}>`
); );
const codeTheme = "github"; return `<blockquote ${getStyles(
return ` "blockquote"
)}>${text}</blockquote>`;
};
renderer.code = (text, lang) => {
text = text.replace(/</g, "&lt;").replace(/>/g, "&gt;");
const codeLines = text
.split("\n")
.map(
(line) =>
`<code class="prettyprint"><span class="code-snippet_outer">${
line || "<br>"
}</span></code>`
);
const codeTheme = "github";
return `
<section class="code-snippet__${codeTheme}"> <section class="code-snippet__${codeTheme}">
<pre class="code__pre" data-lang="${lang}"> <pre class="code__pre" data-lang="${lang}">
${codeLines.join("")} ${codeLines.join("")}
</pre> </pre>
</section> </section>
`; `;
}; };
renderer.codespan = (text, lang) => renderer.codespan = (text, lang) =>
`<code ${getStyles("codespan")}>${text}</code>`; `<code ${getStyles("codespan")}>${text}</code>`;
renderer.listitem = (text) => renderer.listitem = (text) =>
`<span ${getStyles( `<span ${getStyles(
"listitem" "listitem"
)}><span style="margin-right: 10px;"><%s/></span>${text}</span>`; )}><span style="margin-right: 10px;"><%s/></span>${text}</span>`;
renderer.list = (text, ordered, start) => { renderer.list = (text, ordered, start) => {
text = text.replace(/<\/*p.*?>/g, ""); text = text.replace(/<\/*p.*?>/g, "");
let segments = text.split(`<%s/>`); let segments = text.split(`<%s/>`);
if (!ordered) { if (!ordered) {
text = segments.join("•"); text = segments.join("•");
return `<p ${getStyles("ul")}>${text}</p>`; return `<p ${getStyles("ul")}>${text}</p>`;
} }
text = segments[0]; text = segments[0];
for (let i = 1; i < segments.length; i++) { for (let i = 1; i < segments.length; i++) {
text = text + i + "." + segments[i]; text = text + i + "." + segments[i];
} }
return `<p ${getStyles("ol")}>${text}</p>`; return `<p ${getStyles("ol")}>${text}</p>`;
};
renderer.image = (href, title, text) => {
let subText = "";
if (text) {
subText = `<figcaption ${getStyles(
"figcaption"
)}>${text}</figcaption>`;
}
let figureStyles = getStyles("figure");
let imgStyles = getStyles(
ENV_STRETCH_IMAGE ? "image" : "image_org"
);
return `<figure ${figureStyles}><img ${imgStyles} src="${href}" title="${title}" alt="${text}"/>${subText}</figure>`;
};
renderer.link = (href, title, text) => {
if (href.indexOf("https://mp.weixin.qq.com") === 0) {
return `<a href="${href}" title="${
title || text
}" ${getStyles("wx_link")}>${text}</a>`;
}
if (href === text || !status) {
return text;
}
let ref = addFootnote(title || text, href);
return `<span ${getStyles(
"link"
)}>${text}<sup>[${ref}]</sup></span>`;
};
renderer.strong = (text) =>
`<strong ${getStyles("strong")}>${text}</strong>`;
renderer.em = (text) =>
`<span style="font-style: italic;">${text}</span>`;
renderer.table = (header, body) =>
`<section style="padding:0 8px;"><table class="preview-table"><thead ${getStyles(
"thead"
)}>${header}</thead><tbody>${body}</tbody></table></section>`;
// renderer.tablerow = (text) => `<tr style="">${text}</tr>`;
renderer.tablecell = (text, flags) =>
`<td ${getStyles("td")}>${text}</td>`;
renderer.hr = () =>
`<hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);">`;
return renderer;
}; };
renderer.image = (href, title, text) => { }
let subText = ""; }
if (text) {
subText = `<figcaption ${getStyles(
"figcaption"
)}>${text}</figcaption>`;
}
let figureStyles = getStyles("figure");
let imgStyles = getStyles(
ENV_STRETCH_IMAGE ? "image" : "image_org"
);
return `<figure ${figureStyles}><img ${imgStyles} src="${href}" title="${title}" alt="${text}"/>${subText}</figure>`;
};
renderer.link = (href, title, text) => {
if (href.indexOf("https://mp.weixin.qq.com") === 0) {
return `<a href="${href}" title="${title || text}" ${getStyles(
"wx_link"
)}>${text}</a>`;
}
if (href === text || !status) {
return text;
}
let ref = addFootnote(title || text, href);
return `<span ${getStyles(
"link"
)}>${text}<sup>[${ref}]</sup></span>`;
};
renderer.strong = (text) =>
`<strong ${getStyles("strong")}>${text}</strong>`;
renderer.em = (text) =>
`<span style="font-style: italic;">${text}</span>`;
renderer.table = (header, body) =>
`<section style="padding:0 8px;"><table class="preview-table"><thead ${getStyles(
"thead"
)}>${header}</thead><tbody>${body}</tbody></table></section>`;
// renderer.tablerow = (text) => `<tr style="">${text}</tr>`;
renderer.tablecell = (text, flags) =>
`<td ${getStyles("td")}>${text}</td>`;
renderer.hr = () =>
`<hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);">`;
return renderer;
};
};
export default WxRenderer; export default WxRenderer;