mirror of
https://github.com/doocs/md.git
synced 2024-11-24 19:10:34 +08:00
parent
10d5ce856b
commit
fe4d6b0324
3
.gitignore
vendored
3
.gitignore
vendored
@ -43,5 +43,8 @@ yarn-error.log*
|
||||
|
||||
# mockm
|
||||
httpData
|
||||
|
||||
package-lock.json
|
||||
public/upload/**
|
||||
!public/upload/*.gitkeep
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
"crypto-js": "^4.1.1",
|
||||
"element-ui": "^2.15.6",
|
||||
"form-data": "4.0.0",
|
||||
"highlight.js": "^11.3.1",
|
||||
"jquery": "^3.6.0",
|
||||
"juice": "^8.0.0",
|
||||
"marked": "^4.0.5",
|
||||
@ -39,6 +40,7 @@
|
||||
"@vue/cli-service": "~4.5.15",
|
||||
"async-validator": "^4.0.7",
|
||||
"babel-plugin-import": "^1.13.3",
|
||||
"cache-loader": "^4.1.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"jest": "^27.4.0",
|
||||
"less": "^4.1.2",
|
||||
|
@ -20,7 +20,7 @@ body,
|
||||
/* 每个页面公共css */
|
||||
@import url("./assets/less/style-mirror.css");
|
||||
@import url("./assets/less/theme.less");
|
||||
@import url("./assets/less/code-theme.less");
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
|
@ -1,2 +0,0 @@
|
||||
@import url("./codeTheme/wechat-code-block.less");
|
||||
@import url("./codeTheme/github-code-block.less");
|
@ -1,49 +0,0 @@
|
||||
@import url("../github-v2.min.css");
|
||||
/*github code block*/
|
||||
.code-snippet__github {
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
margin: 10px 8px;
|
||||
position: relative;
|
||||
height: auto;
|
||||
background-color: #f7f7f7;
|
||||
border-radius: 8px;
|
||||
|
||||
.code-snippet__line-index {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.code__pre {
|
||||
display: grid;
|
||||
position: relative;
|
||||
counter-reset: line;
|
||||
overflow-x: auto;
|
||||
padding: 1em;
|
||||
white-space: normal;
|
||||
flex: 1;
|
||||
line-height: 20px;
|
||||
font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
code {
|
||||
display: flex;
|
||||
position: relative;
|
||||
padding-right: 8px;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
ul li {
|
||||
list-style: none;
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*wechat code block*/
|
||||
.rich_media_content .code-snippet *,
|
||||
.rich_media_content .code-snippet__wechat * {
|
||||
max-width: 1000% !important;
|
||||
}
|
||||
|
||||
.code-snippet__wechat {
|
||||
word-wrap: break-word !important;
|
||||
font-size: 14px;
|
||||
margin: 10px 8px;
|
||||
color: #333;
|
||||
position: relative;
|
||||
background-color: rgba(27, 31, 35, 0.05);
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 2px;
|
||||
display: flex;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.code-snippet__wechat .code-snippet__line-index {
|
||||
counter-reset: line;
|
||||
flex-shrink: 0;
|
||||
height: 100%;
|
||||
padding: 1em;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.code-snippet__wechat .code-snippet__line-index li {
|
||||
list-style-type: none;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.code-snippet__wechat .code-snippet__line-index li::before {
|
||||
min-width: 1.5em;
|
||||
text-align: right;
|
||||
left: -2.5em;
|
||||
counter-increment: line;
|
||||
content: counter(line);
|
||||
display: inline;
|
||||
color: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.code-snippet__wechat pre {
|
||||
overflow-x: auto;
|
||||
padding: 1em 1em 1em 1em;
|
||||
white-space: normal;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.code-snippet__wechat code {
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
white-space: pre;
|
||||
display: flex;
|
||||
position: relative;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
}
|
||||
|
||||
.code-snippet__wechat ul li {
|
||||
list-style: none;
|
||||
}
|
72
src/assets/less/github-v2.min.css
vendored
72
src/assets/less/github-v2.min.css
vendored
@ -1,72 +0,0 @@
|
||||
/*! Color themes for Google Code Prettify | MIT License | github.com/jmblog/color-themes-for-google-code-prettify */
|
||||
.prettyprint {
|
||||
font-family: Menlo, Bitstream Vera Sans Mono, DejaVu Sans Mono, Monaco,
|
||||
Consolas, monospace;
|
||||
border: 0 !important;
|
||||
}
|
||||
.pln {
|
||||
color: #333;
|
||||
}
|
||||
ol.linenums {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: #ccc;
|
||||
}
|
||||
li.L0,
|
||||
li.L1,
|
||||
li.L2,
|
||||
li.L3,
|
||||
li.L4,
|
||||
li.L5,
|
||||
li.L6,
|
||||
li.L7,
|
||||
li.L8,
|
||||
li.L9 {
|
||||
padding-left: 1em;
|
||||
background-color: #fff;
|
||||
list-style-type: decimal;
|
||||
}
|
||||
@media screen {
|
||||
.str {
|
||||
color: #183691;
|
||||
}
|
||||
.kwd {
|
||||
color: #a71d5d;
|
||||
}
|
||||
.com {
|
||||
color: #969896;
|
||||
}
|
||||
.typ {
|
||||
color: #0086b3;
|
||||
}
|
||||
.lit {
|
||||
color: #0086b3;
|
||||
}
|
||||
.pun {
|
||||
color: #333;
|
||||
}
|
||||
.opn {
|
||||
color: #333;
|
||||
}
|
||||
.clo {
|
||||
color: #333;
|
||||
}
|
||||
.tag {
|
||||
color: navy;
|
||||
}
|
||||
.atn {
|
||||
color: #795da3;
|
||||
}
|
||||
.atv {
|
||||
color: #183691;
|
||||
}
|
||||
.dec {
|
||||
color: #333;
|
||||
}
|
||||
.var {
|
||||
color: teal;
|
||||
}
|
||||
.fun {
|
||||
color: #900;
|
||||
}
|
||||
}
|
@ -57,14 +57,29 @@ export default {
|
||||
],
|
||||
codeThemeOption: [
|
||||
{
|
||||
label: "微信",
|
||||
value: "wechat",
|
||||
desc: "默认样式",
|
||||
label: "github",
|
||||
value: "https://lib.baomitu.com/highlight.js/10.7.3/styles/github.min.css",
|
||||
desc: "light",
|
||||
},
|
||||
{
|
||||
label: "GitHub",
|
||||
value: "github",
|
||||
desc: "精简风格",
|
||||
label: "solarized-light",
|
||||
value: "https://lib.baomitu.com/highlight.js/11.3.1/styles/base16/solarized-light.min.css",
|
||||
desc: "light",
|
||||
},
|
||||
{
|
||||
label: "atom-one-dark",
|
||||
value: "https://lib.baomitu.com/highlight.js/11.3.1/styles/atom-one-dark.min.css",
|
||||
desc: "dark",
|
||||
},
|
||||
{
|
||||
label: "obsidian",
|
||||
value: "https://lib.baomitu.com/highlight.js/11.3.1/styles/obsidian.min.css",
|
||||
desc: "dark",
|
||||
},
|
||||
{
|
||||
label: "vs2015",
|
||||
value: "https://lib.baomitu.com/highlight.js/11.3.1/styles/vs2015.min.css",
|
||||
desc: "dark",
|
||||
},
|
||||
],
|
||||
form: {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Renderer } from "marked";
|
||||
import hljs from 'highlight.js';
|
||||
|
||||
class WxRenderer {
|
||||
constructor(opts) {
|
||||
@ -7,9 +8,6 @@ class WxRenderer {
|
||||
let footnoteIndex = 0;
|
||||
let styleMapping = new Map();
|
||||
|
||||
const CODE_FONT_FAMILY =
|
||||
"Menlo, Operator Mono, Consolas, Monaco, monospace";
|
||||
|
||||
let merge = (base, extend) => Object.assign({}, base, extend);
|
||||
|
||||
this.buildTheme = (themeTpl) => {
|
||||
@ -25,13 +23,10 @@ class WxRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
let base_block = merge(base, {});
|
||||
let base_block = merge(base, {});
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -126,23 +121,17 @@ class WxRenderer {
|
||||
return `<blockquote ${getStyles("blockquote")}>${text}</blockquote>`;
|
||||
};
|
||||
renderer.code = (text, lang) => {
|
||||
text = text.replace(/</g, "<").replace(/>/g, ">");
|
||||
const codeLines = text
|
||||
.split("\n")
|
||||
.map(
|
||||
(line) =>
|
||||
`<code class="prettyprint"><span class="code-snippet_outer">${
|
||||
line || " "
|
||||
}</span></code>`
|
||||
);
|
||||
const codeTheme = "github";
|
||||
return `
|
||||
<section class="code-snippet__${codeTheme}">
|
||||
<pre class="code__pre" data-lang="${lang}">
|
||||
${codeLines.join("")}
|
||||
</pre>
|
||||
</section>
|
||||
`;
|
||||
lang = hljs.getLanguage(lang) ? lang : 'plaintext';
|
||||
|
||||
text = hljs.highlight(text, {language: lang}).value;
|
||||
|
||||
text = text.replace(/\r\n/g,"<br/>")
|
||||
.replace(/\n/g,"<br/>")
|
||||
.replace(/(>[^<]+)|(^[^<]+)/g, function(str) {
|
||||
return str.replace(/\s/g, ' ')
|
||||
});
|
||||
|
||||
return `<pre class="hljs code__pre" ${getStyles("code_pre")}><code class="prettyprint language-${lang}" ${getStyles("code")}>${text}</code></pre>`
|
||||
};
|
||||
renderer.codespan = (text, lang) =>
|
||||
`<code ${getStyles("codespan")}>${text}</code>`;
|
||||
|
@ -1,11 +1,9 @@
|
||||
let baseColor = "#3f3f3f"
|
||||
|
||||
export default {
|
||||
BASE: {
|
||||
"text-align": "left",
|
||||
color: "#3f3f3f",
|
||||
"line-height": "1.75",
|
||||
},
|
||||
BASE_BLOCK: {
|
||||
margin: "1em 8px",
|
||||
"line-height": "1.75"
|
||||
},
|
||||
block: {
|
||||
// 一级标题样式
|
||||
@ -17,6 +15,7 @@ export default {
|
||||
margin: "2em auto 1em",
|
||||
padding: "0 1em",
|
||||
"border-bottom": "2px solid rgba(0, 152, 116, 0.9)",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
// 二级标题样式
|
||||
@ -39,6 +38,7 @@ export default {
|
||||
"line-height": "1.2",
|
||||
"padding-left": "8px",
|
||||
"border-left": "3px solid rgba(0, 152, 116, 0.9)",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
// 四级标题样式
|
||||
@ -53,6 +53,7 @@ export default {
|
||||
p: {
|
||||
margin: "1.5em 8px",
|
||||
"letter-spacing": "0.1em",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
// 引用样式
|
||||
@ -72,18 +73,18 @@ export default {
|
||||
"font-size": "1em",
|
||||
display: "block",
|
||||
},
|
||||
|
||||
code: {
|
||||
"font-size": "80%",
|
||||
overflow: "auto",
|
||||
color: "#333",
|
||||
"white-space": "pre",
|
||||
background: "rgb(247, 247, 247)",
|
||||
code_pre: {
|
||||
"font-size": "14px",
|
||||
"overflow-x": "auto",
|
||||
"border-radius": "8px",
|
||||
padding: "10px",
|
||||
padding: "1em",
|
||||
"line-height": "1.5",
|
||||
border: "1px solid rgb(236,236,236)",
|
||||
margin: "20px 0",
|
||||
margin: "10px 8px"
|
||||
},
|
||||
code: {
|
||||
"margin": 0,
|
||||
"white-space": "nowrap",
|
||||
"font-family": "Menlo, Operator Mono, Consolas, Monaco, monospace"
|
||||
},
|
||||
|
||||
image: {
|
||||
@ -96,21 +97,25 @@ export default {
|
||||
ol: {
|
||||
"margin-left": "0",
|
||||
"padding-left": "1em",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
ul: {
|
||||
"margin-left": "0",
|
||||
"padding-left": "1em",
|
||||
"list-style": "circle",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
footnotes: {
|
||||
margin: "0.5em 8px",
|
||||
"font-size": "80%",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
figure: {
|
||||
margin: "1.5em 8px",
|
||||
color: baseColor,
|
||||
},
|
||||
hr: {
|
||||
"border-style": "solid",
|
||||
@ -127,6 +132,7 @@ export default {
|
||||
"text-indent": "-1em",
|
||||
display: "block",
|
||||
margin: "0.2em 8px",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
codespan: {
|
||||
@ -157,20 +163,24 @@ export default {
|
||||
"border-collapse": "collapse",
|
||||
"text-align": "center",
|
||||
margin: "1em 8px",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
thead: {
|
||||
background: "rgba(0, 0, 0, 0.05)",
|
||||
"font-weight": "bold",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
td: {
|
||||
border: "1px solid #dfdfdf",
|
||||
padding: "0.25em 0.5em",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
footnote: {
|
||||
"font-size": "12px",
|
||||
color: baseColor,
|
||||
},
|
||||
|
||||
figcaption: {
|
||||
|
@ -215,15 +215,6 @@ export function formatCss(content) {
|
||||
return doc;
|
||||
}
|
||||
|
||||
export function fixCodeWhiteSpace(value = "pre") {
|
||||
const preDomList = document.getElementsByClassName("code__pre");
|
||||
if (preDomList.length > 0) {
|
||||
preDomList.forEach((pre) => {
|
||||
pre.style.whiteSpace = value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出原始 Markdown 文档
|
||||
* @param {文档内容} doc
|
||||
@ -264,7 +255,6 @@ export function exportHTML() {
|
||||
|
||||
function setStyles(element) {
|
||||
switch (true) {
|
||||
case isSection(element):
|
||||
case isPre(element):
|
||||
case isCode(element):
|
||||
case isSpan(element):
|
||||
@ -275,13 +265,6 @@ export function exportHTML() {
|
||||
Array.from(element.children).forEach((child) => setStyles(child));
|
||||
}
|
||||
|
||||
// 判断是否是包裹代码块的 section 元素
|
||||
function isSection(element) {
|
||||
return (
|
||||
element.tagName === "SECTION" &&
|
||||
Array.from(element.classList).includes("code-snippet__github")
|
||||
);
|
||||
}
|
||||
// 判断是否是包裹代码块的 pre 元素
|
||||
function isPre(element) {
|
||||
return (
|
||||
|
@ -109,6 +109,22 @@
|
||||
<span class="select-item-right">{{ color.desc }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="selectCodeTheme"
|
||||
size="mini"
|
||||
placeholder="代码主题"
|
||||
@change="codeThemeChanged"
|
||||
>
|
||||
<el-option
|
||||
v-for="code in config.codeThemeOption"
|
||||
:key="code.value"
|
||||
:label="code.label"
|
||||
:value="code.value"
|
||||
>
|
||||
<span class="select-item-left">{{ code.label }}</span>
|
||||
<span class="select-item-right">{{ code.desc }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-tooltip content="自定义颜色" :effect="effect" placement="top">
|
||||
<el-color-picker
|
||||
v-model="selectColor"
|
||||
@ -205,7 +221,7 @@ export default {
|
||||
selectFont: "",
|
||||
selectSize: "",
|
||||
selectColor: "",
|
||||
selectCodeTheme: "github",
|
||||
selectCodeTheme: config.codeThemeOption[0].value
|
||||
};
|
||||
},
|
||||
components: {
|
||||
@ -275,7 +291,6 @@ export default {
|
||||
setTimeout(() => {
|
||||
let clipboardDiv = document.getElementById("output");
|
||||
solveWeChatImage();
|
||||
fixCodeWhiteSpace();
|
||||
solveHtml();
|
||||
clipboardDiv.focus();
|
||||
window.getSelection().removeAllRanges();
|
||||
@ -286,7 +301,6 @@ export default {
|
||||
window.getSelection().addRange(range);
|
||||
document.execCommand("copy");
|
||||
window.getSelection().removeAllRanges();
|
||||
fixCodeWhiteSpace("normal");
|
||||
clipboardDiv.innerHTML = this.output;
|
||||
// 输出提示
|
||||
this.$notify({
|
||||
@ -326,11 +340,13 @@ export default {
|
||||
this.fontChanged(this.config.builtinFonts[0].value);
|
||||
this.colorChanged(this.config.colorOption[0].value);
|
||||
this.sizeChanged(this.config.sizeOption[2].value);
|
||||
this.codeThemeChanged(this.config.codeThemeOption[0].value)
|
||||
this.$emit("cssChanged");
|
||||
this.selectFont = this.currentFont;
|
||||
this.selectSize = this.currentSize;
|
||||
this.selectColor = this.currentColor;
|
||||
this.showResetConfirm = false;
|
||||
this.selectCodeTheme = this.codeTheme;
|
||||
},
|
||||
cancelReset() {
|
||||
this.showResetConfirm = false;
|
||||
|
@ -149,6 +149,7 @@ export default {
|
||||
currentColor: (state) => state.currentColor,
|
||||
nightMode: (state) => state.nightMode,
|
||||
rightClickMenuVisible: (state) => state.rightClickMenuVisible,
|
||||
codeTheme: (state) => state.codeTheme,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
@ -223,6 +224,21 @@ export default {
|
||||
});
|
||||
this.onEditorRefresh();
|
||||
},
|
||||
// 切换 highlight.js 代码主题
|
||||
codeThemeChanged() {
|
||||
let cssUrl = this.codeTheme;
|
||||
let el = document.getElementById('hljs')
|
||||
if (el != undefined) {
|
||||
el.setAttribute('href', cssUrl);
|
||||
} else {
|
||||
var link = document.createElement('link');
|
||||
link.setAttribute('type','text/css');
|
||||
link.setAttribute('rel','stylesheet');
|
||||
link.setAttribute('href',cssUrl);
|
||||
link.setAttribute('id','hljs');
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
},
|
||||
beforeUpload(file) {
|
||||
// validate image
|
||||
const checkResult = checkImage(file);
|
||||
@ -318,6 +334,7 @@ export default {
|
||||
},
|
||||
// 更新编辑器
|
||||
onEditorRefresh() {
|
||||
this.codeThemeChanged(this.codeTheme);
|
||||
this.editorRefresh();
|
||||
setTimeout(() => PR.prettyPrint(), 0);
|
||||
},
|
||||
@ -532,8 +549,10 @@ export default {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
.codeMirror-wrapper {
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
@import url("../../../assets/less/app.less");
|
||||
@import url("../../../assets/less/github-v2.min.css");
|
||||
</style>
|
||||
|
@ -21,7 +21,7 @@ const state = {
|
||||
currentColor: "",
|
||||
citeStatus: 0,
|
||||
nightMode: false,
|
||||
codeTheme: "github",
|
||||
codeTheme: config.codeThemeOption[0].value,
|
||||
rightClickMenuVisible: false,
|
||||
};
|
||||
const mutations = {
|
||||
|
Loading…
Reference in New Issue
Block a user