Merge branch 'master' of github.com:doocs/md

This commit is contained in:
JimQing 2020-07-03 21:20:37 +08:00
commit 5d9c77d48a
24 changed files with 1083 additions and 1051 deletions

View File

@ -1,30 +1,28 @@
module.exports = { module.exports = {
root: true, root: true,
env: { env: {
node: true node: true
}, },
'extends': [ 'extends': [
'plugin:vue/essential', 'plugin:vue/essential',
'@vue/standard' '@vue/standard'
], ],
rules: { rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'camelcase': 'off', 'camelcase': 'off',
'eqeqeq': 'off' 'eqeqeq': 'off'
}, },
parserOptions: { parserOptions: {
parser: 'babel-eslint' parser: 'babel-eslint'
}, },
overrides: [ overrides: [{
{ files: [
files: [ '**/__tests__/*.{j,t}s?(x)',
'**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)'
'**/tests/unit/**/*.spec.{j,t}s?(x)' ],
], env: {
env: { jest: true
jest: true }
} }]
}
]
} }

View File

@ -43,6 +43,9 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
- [x] 支持自定义 CSS 样式并实时渲染 - [x] 支持自定义 CSS 样式并实时渲染
- [x] 支持一键恢复至默认内容及样式 - [x] 支持一键恢复至默认内容及样式
- [x] 支持打开或关闭引用链接的选项 - [x] 支持打开或关闭引用链接的选项
- [ ] 支持在编辑框右键弹出功能选项卡
- [ ] 支持更加人性化的插入表格功能
![select-and-change-color-theme](https://imgkr.cn-bj.ufileos.com/32c05c23-6309-491f-bd0d-f22a62c944b4.gif) ![select-and-change-color-theme](https://imgkr.cn-bj.ufileos.com/32c05c23-6309-491f-bd0d-f22a62c944b4.gif)

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
presets: [ presets: [
'@vue/cli-plugin-babel/preset' '@vue/cli-plugin-babel/preset'
] ]
} }

View File

@ -1,3 +1,3 @@
module.exports = { module.exports = {
preset: '@vue/cli-plugin-unit-jest' preset: '@vue/cli-plugin-unit-jest'
} }

View File

@ -1,42 +1,42 @@
{ {
"name": "vue-md", "name": "vue-md",
"version": "1.3.2", "version": "1.3.2",
"private": true, "private": true,
"homepage": "https://doocs.gitee.io/md", "homepage": "https://doocs.gitee.io/md",
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
"build": "vue-cli-service build", "build": "vue-cli-service build",
"lint": "vue-cli-service lint", "lint": "vue-cli-service lint",
"test:unit": "vue-cli-service test:unit" "test:unit": "vue-cli-service test:unit"
}, },
"dependencies": { "dependencies": {
"axios": "^0.19.1", "axios": "^0.19.1",
"codemirror": "^5.50.2", "codemirror": "^5.50.2",
"core-js": "^3.4.4", "core-js": "^3.4.4",
"element-ui": "^2.13.0", "element-ui": "^2.13.0",
"jquery": "^3.4.1", "jquery": "^3.4.1",
"juice": "^6.0.0", "juice": "^6.0.0",
"markdown": "^0.5.0", "markdown": "^0.5.0",
"marked": "^0.8.0", "marked": "^0.8.0",
"prettier": "^2.0.5", "prettier": "^2.0.5",
"prettify": "^0.1.7", "prettify": "^0.1.7",
"vue": "^2.6.10", "vue": "^2.6.10",
"vue-router": "^3.1.3", "vue-router": "^3.1.3",
"vuex": "^3.1.2" "vuex": "^3.1.2"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^4.1.0", "@vue/cli-plugin-babel": "^4.1.0",
"@vue/cli-plugin-eslint": "^4.1.0", "@vue/cli-plugin-eslint": "^4.1.0",
"@vue/cli-plugin-unit-jest": "^4.1.0", "@vue/cli-plugin-unit-jest": "^4.1.0",
"@vue/cli-service": "^4.1.0", "@vue/cli-service": "^4.1.0",
"@vue/eslint-config-standard": "^4.0.0", "@vue/eslint-config-standard": "^4.0.0",
"@vue/test-utils": "1.0.0-beta.29", "@vue/test-utils": "1.0.0-beta.29",
"babel-eslint": "^10.0.3", "babel-eslint": "^10.0.3",
"eslint": "^5.16.0", "eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0", "eslint-plugin-vue": "^5.0.0",
"less-loader": "^6.0.0", "less-loader": "^6.0.0",
"node-sass": "^4.12.0", "node-sass": "^4.12.0",
"sass-loader": "^8.0.0", "sass-loader": "^8.0.0",
"vue-template-compiler": "^2.6.10" "vue-template-compiler": "^2.6.10"
} }
} }

View File

@ -1,234 +1,245 @@
* { * {
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
input, button, textarea { input,
font-family: inherit; button,
textarea {
font-family: inherit;
} }
h1, h2, h3, h4, h5, h6 { h1,
font-weight: normal; h2,
h3,
h4,
h5,
h6 {
font-weight: normal;
} }
em { em {
font-style: normal !important; font-style: normal !important;
} }
html, body { html,
height: 100%; body {
font-family: 'PingFang SC', BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif; height: 100%;
font-family: 'PingFang SC', BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif;
} }
.el-message__icon { .el-message__icon {
display: none display: none
} }
.container { .container {
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.top { .top {
height: 60px; height: 60px;
padding: 10px 20px; padding: 10px 20px;
display: flex; display: flex;
align-items: center; align-items: center;
margin-right: 20px; margin-right: 20px;
} }
.web-title { .web-title {
margin: 0 15px 0 5px; margin: 0 15px 0 5px;
} }
.web-icon { .web-icon {
width: auto; width: auto;
height: 1.5rem; height: 1.5rem;
vertical-align: middle; vertical-align: middle;
} }
#editor { #editor {
height: 100%; height: 100%;
display: block; display: block;
border: none; border: none;
width: 100%; width: 100%;
padding: 10px; padding: 10px;
} }
section { section {
height: 100%; height: 100%;
} }
.main-body { .main-body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding-top: 0; padding-top: 0;
padding-bottom: 10px; padding-bottom: 10px;
} }
.ctrl { .ctrl {
flex-basis: 60px; flex-basis: 60px;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;
display: flex; display: flex;
align-items: center; align-items: center;
} }
.preview-wrapper { .preview-wrapper {
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
padding: 0; padding: 0;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
display: flex; display: flex;
overflow: scroll; overflow: scroll;
word-break: break-all; word-break: break-all;
} }
.main-section { .main-section {
display: flex; display: flex;
height: 100%; height: 100%;
} }
.hint { .hint {
opacity: 0.6; opacity: 0.6;
margin: 20px 0; margin: 20px 0;
} }
.preview { .preview {
margin: 0 -20px; margin: 0 -20px;
width: 375px; width: 375px;
padding: 20px; padding: 20px;
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
outline: none; outline: none;
box-shadow: 0 0 60px rgba(0, 0, 0, 0.1); box-shadow: 0 0 60px rgba(0, 0, 0, 0.1);
} }
.preview table { .preview table {
margin-bottom: 10px; margin-bottom: 10px;
border-collapse: collapse; border-collapse: collapse;
display: table; display: table;
width: 100% !important; width: 100% !important;
} }
/* /*
.preview table tr:nth-child(even){ .preview table tr:nth-child(even){
background: rgb(250, 250, 250); background: rgb(250, 250, 250);
} }
*/ */
.select-item-left { .select-item-left {
float: left; float: left;
} }
.select-item-right { .select-item-right {
float: right; float: right;
color: #8492a6; color: #8492a6;
font-size: 13px; font-size: 13px;
} }
.CodeMirror { .CodeMirror {
height: 100% !important; height: 100% !important;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
font-size: 14px; font-size: 14px;
padding: 20px; padding: 20px;
width: 100% !important; width: 100% !important;
font-family: 'PingFang SC', BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif !important; font-family: 'PingFang SC', BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif !important;
} }
/* ele ui */ /* ele ui */
.el-form-item { .el-form-item {
margin-bottom: 0 !important; margin-bottom: 0 !important;
} }
.el-tooltip { .el-tooltip {
cursor: pointer; cursor: pointer;
} }
/*wechat code block*/ /*wechat code block*/
.rich_media_content .code-snippet *, .rich_media_content .code-snippet__fix * { .rich_media_content .code-snippet *,
max-width: 1000% !important; .rich_media_content .code-snippet__fix * {
max-width: 1000% !important;
} }
.code-snippet__fix { .code-snippet__fix {
word-wrap: break-word !important; word-wrap: break-word !important;
font-size: 14px; font-size: 14px;
margin: 10px 8px; margin: 10px 8px;
color: #333; color: #333;
position: relative; position: relative;
background-color: rgb(238,238,238); background-color: rgb(238, 238, 238);
border: 1px solid #f0f0f0; border: 1px solid #f0f0f0;
border-radius: 2px; border-radius: 2px;
display: flex; display: flex;
line-height: 24px; line-height: 24px;
} }
.code-snippet__fix .code-snippet__line-index { .code-snippet__fix .code-snippet__line-index {
counter-reset: line; counter-reset: line;
flex-shrink: 0; flex-shrink: 0;
height: 100%; height: 100%;
padding: 1em; padding: 1em;
list-style-type: none; list-style-type: none;
} }
.code-snippet__fix .code-snippet__line-index li { .code-snippet__fix .code-snippet__line-index li {
list-style-type: none; list-style-type: none;
text-align: right; text-align: right;
} }
.code-snippet__fix .code-snippet__line-index li::before { .code-snippet__fix .code-snippet__line-index li::before {
min-width: 1.5em; min-width: 1.5em;
text-align: right; text-align: right;
left: -2.5em; left: -2.5em;
counter-increment: line; counter-increment: line;
content: counter(line); content: counter(line);
display: inline; display: inline;
color: rgba(0, 0, 0, 0.15); color: rgba(0, 0, 0, 0.15);
} }
.code-snippet__fix pre { .code-snippet__fix pre {
overflow-x: auto; overflow-x: auto;
padding: 1em 1em 1em 1em; padding: 1em 1em 1em 1em;
white-space: normal; white-space: normal;
flex: 1; flex: 1;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
} }
.code-snippet__fix code { .code-snippet__fix code {
text-align: left; text-align: left;
font-size: 14px; font-size: 14px;
white-space: pre; white-space: pre;
display: flex; display: flex;
position: relative; position: relative;
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
} }
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 6px; width: 6px;
height: 6px; height: 6px;
background-color: #FFF; background-color: #FFF;
} }
::-webkit-scrollbar-track { ::-webkit-scrollbar-track {
border-radius: 6px; border-radius: 6px;
background-color: rgba(200, 200, 200, 0.3); background-color: rgba(200, 200, 200, 0.3);
} }
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
border-radius: 6px; border-radius: 6px;
background-color: rgba(144, 146, 152, 0.5); background-color: rgba(144, 146, 152, 0.5);
transition: background-color .3s; transition: background-color .3s;
} }
::-webkit-scrollbar-thumb:hover { ::-webkit-scrollbar-thumb:hover {
background-color: rgba(144, 146, 152, 0.5); background-color: rgba(144, 146, 152, 0.5);
} }
.CodeMirror-vscrollbar:focus { .CodeMirror-vscrollbar:focus {
outline: none; outline: none;
} }
.CodeMirror-scroll, .preview-wrapper { .CodeMirror-scroll,
.preview-wrapper {
overflow: unset; overflow: unset;
overflow-y: scroll; overflow-y: scroll;
} }

View File

@ -1,47 +1,47 @@
.loading { .loading {
text-align: center; text-align: center;
position: fixed; position: fixed;
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
z-index: 99999; z-index: 99999;
background-color: #f2f2f2; background-color: #f2f2f2;
} }
.loading_night { .loading_night {
background-color: #303133; background-color: #303133;
} }
.loading-wrapper { .loading-wrapper {
position: fixed; position: fixed;
top: 50%; top: 50%;
left: 50%; left: 50%;
-webkit-transform: translateX(-50%) translateY(-50%); -webkit-transform: translateX(-50%) translateY(-50%);
-moz-transform: translateX(-50%) translateY(-50%); -moz-transform: translateX(-50%) translateY(-50%);
-ms-transform: translateX(-50%) translateY(-50%); -ms-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%); transform: translateX(-50%) translateY(-50%);
} }
.loading-text { .loading-text {
line-height: 1.4; line-height: 1.4;
font-size: 1.2rem; font-size: 1.2rem;
font-weight: bold; font-weight: bold;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.loading-anim { .loading-anim {
width: 35px; width: 35px;
height: 35px; height: 35px;
border: 5px solid rgba(189, 189, 189, 0.25); border: 5px solid rgba(189, 189, 189, 0.25);
border-left-color: rgba(66, 185, 131, 0.9); border-left-color: rgba(66, 185, 131, 0.9);
border-top-color: rgba(66, 185, 131, 0.9); border-top-color: rgba(66, 185, 131, 0.9);
border-radius: 50%; border-radius: 50%;
display: inline-block; display: inline-block;
animation: rotate 600ms infinite linear; animation: rotate 600ms infinite linear;
} }
@keyframes rotate { @keyframes rotate {
to { to {
transform: rotate(1turn) transform: rotate(1turn)
} }
} }

View File

@ -14,91 +14,111 @@
font-size: 16px; font-size: 16px;
padding: 20px; padding: 20px;
line-height: 25px; line-height: 25px;
} }
.cm-s-style-mirror div.CodeMirror-selected {
.cm-s-style-mirror div.CodeMirror-selected {
background: #e0e0e0; background: #e0e0e0;
} }
.cm-s-style-mirror .CodeMirror-line::selection,
.cm-s-style-mirror .CodeMirror-line > span::selection, .cm-s-style-mirror .CodeMirror-line::selection,
.cm-s-style-mirror .CodeMirror-line > span > span::selection { .cm-s-style-mirror .CodeMirror-line>span::selection,
.cm-s-style-mirror .CodeMirror-line>span>span::selection {
background: #e0e0e0; background: #e0e0e0;
} }
.cm-s-style-mirror .CodeMirror-line::-moz-selection,
.cm-s-style-mirror .CodeMirror-line > span::-moz-selection, .cm-s-style-mirror .CodeMirror-line::-moz-selection,
.cm-s-style-mirror .CodeMirror-line > span > span::-moz-selection { .cm-s-style-mirror .CodeMirror-line>span::-moz-selection,
.cm-s-style-mirror .CodeMirror-line>span>span::-moz-selection {
background: #e0e0e0; background: #e0e0e0;
} }
.cm-s-style-mirror .CodeMirror-gutters {
.cm-s-style-mirror .CodeMirror-gutters {
background: #f5f5f5; background: #f5f5f5;
border-right: 0px; border-right: 0px;
} }
.cm-s-style-mirror .CodeMirror-guttermarker {
.cm-s-style-mirror .CodeMirror-guttermarker {
color: #ac4142; color: #ac4142;
} }
.cm-s-style-mirror .CodeMirror-guttermarker-subtle {
.cm-s-style-mirror .CodeMirror-guttermarker-subtle {
color: #b0b0b0; color: #b0b0b0;
} }
.cm-s-style-mirror .CodeMirror-linenumber {
.cm-s-style-mirror .CodeMirror-linenumber {
color: #b0b0b0; color: #b0b0b0;
} }
.cm-s-style-mirror .CodeMirror-cursor {
.cm-s-style-mirror .CodeMirror-cursor {
border-left: 1px solid #505050; border-left: 1px solid #505050;
} }
.cm-s-style-mirror span.cm-comment { .cm-s-style-mirror span.cm-comment {
color:green; color: green;
} }
.cm-s-style-mirror span.cm-atom {
color: #aa759f;
}
.cm-s-style-mirror span.cm-number {
color: #aa759f;
}
.cm-s-style-mirror span.cm-property, .cm-s-style-mirror span.cm-atom {
.cm-s-style-mirror span.cm-attribute { color: #aa759f;
}
.cm-s-style-mirror span.cm-number {
color: #aa759f;
}
.cm-s-style-mirror span.cm-property,
.cm-s-style-mirror span.cm-attribute {
color: #90a959; color: #90a959;
} }
.cm-s-style-mirror span.cm-keyword {
.cm-s-style-mirror span.cm-keyword {
color: #023a52; color: #023a52;
} }
.cm-s-style-mirror span.cm-string {
color: #e46918;
}
.cm-s-style-mirror span.cm-variable { .cm-s-style-mirror span.cm-string {
color: #e46918;
}
.cm-s-style-mirror span.cm-variable {
color: #90a959; color: #90a959;
} }
.cm-s-style-mirror span.cm-variable-2 {
.cm-s-style-mirror span.cm-variable-2 {
color: #00695f; color: #00695f;
} }
.cm-s-style-mirror span.cm-variable-3 {
.cm-s-style-mirror span.cm-variable-3 {
color: #2e6e8a; color: #2e6e8a;
} }
.cm-s-style-mirror span.cm-def {
.cm-s-style-mirror span.cm-def {
color: #d28445; color: #d28445;
} }
.cm-s-style-mirror span.cm-bracket {
.cm-s-style-mirror span.cm-bracket {
color: #202020; color: #202020;
} }
.cm-s-style-mirror span.cm-tag {
color:#000; .cm-s-style-mirror span.cm-tag {
} color: #000;
.cm-s-style-mirror span.cm-link { }
.cm-s-style-mirror span.cm-link {
color: #b26a00; color: #b26a00;
} }
.cm-s-style-mirror span.cm-error {
.cm-s-style-mirror span.cm-error {
/* background: #ac4142; /* background: #ac4142;
color: #f5f5f5; */ color: #f5f5f5; */
text-decoration: underline; text-decoration: underline;
text-decoration-style: wavy; text-decoration-style: wavy;
text-decoration-color: #df8d8e; text-decoration-color: #df8d8e;
} }
.cm-s-style-mirror .CodeMirror-activeline-background {
background: #dddcdc;
}
.cm-s-style-mirror .CodeMirror-matchingbracket {
color: rgb(32,32,32) !important;
background-color: rgba(0,0,0,0.1) !important;
}
.cm-s-style-mirror .CodeMirror-activeline-background {
background: #dddcdc;
}
.cm-s-style-mirror .CodeMirror-matchingbracket {
color: rgb(32, 32, 32) !important;
background-color: rgba(0, 0, 0, 0.1) !important;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -1,55 +1,28 @@
<!DOCTYPE html> <!DOCTYPE html>
<!--
_.._ ,------------.
,' `. ( 你终于发现我啦 )
/ __) __` \ `-,----------'
( (`-`(-') ) _.-'
/) \ = / (
/' |--' . \
( ,---| `-.)__`
)( `-.,--' _`-.
'/,' ( Uu",
(_ , `/,-' )
`.__, : `-'/ /`--'
| `--' |
` `-._ /
\ (
/\ . \.
/ |` \ ,-\
/ \| .) / \
( ,'|\ ,' :
| \,`.`--"/ }
`,' \ |,' /
/ "-._ `-/ |
"-. "-.,'| ;
/ _/["---'""]
: / |"- '
' | /
` |
-->
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="keywords" content="md,markdown,markdown-editor,wechat,official-account,yanglbme,doocs"> <meta name="keywords" content="md,markdown,markdown-editor,wechat,official-account,yanglbme,doocs">
<meta name="description" content="Wechat Markdown Editor | 一款高度简洁的微信 Markdown 编辑器"> <meta name="description" content="Wechat Markdown Editor | 一款高度简洁的微信 Markdown 编辑器">
<meta name="viewport" <meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>微信 Markdown 编辑器</title> <title>微信 Markdown 编辑器</title>
<link rel="shortcut icon" href="https://imgkr.cn-bj.ufileos.com/f3accc83-b854-4e99-afb5-8a6465e1d84f.png"> <link rel="shortcut icon" href="https://imgkr.cn-bj.ufileos.com/f3accc83-b854-4e99-afb5-8a6465e1d84f.png">
<link rel="apple-touch-icon-precomposed" href="https://imgkr.cn-bj.ufileos.com/f3accc83-b854-4e99-afb5-8a6465e1d84f.png"> <link rel="apple-touch-icon-precomposed"
<link rel="stylesheet" href="assets/css/loading.css"> href="https://imgkr.cn-bj.ufileos.com/f3accc83-b854-4e99-afb5-8a6465e1d84f.png">
<link rel="stylesheet" href="libs/css/index.css"> <link rel="stylesheet" href="assets/css/loading.css">
<link rel="stylesheet" href="libs/css/code-themes/github-v2.min.css"> <link rel="stylesheet" href="libs/css/index.css">
<link rel="stylesheet" href="libs/css/style-mirror.css"> <link rel="stylesheet" href="libs/css/code-themes/github-v2.min.css">
<link rel="stylesheet" href="libs/css/animate.css"> <link rel="stylesheet" href="libs/css/style-mirror.css">
<link rel="stylesheet" href="assets/css/app.css"> <link rel="stylesheet" href="libs/css/animate.css">
<link rel="stylesheet" href="assets/css/app.css">
</head> </head>
<body> <body>
<div id="app" > <div id="app">
</div> </div>
</body> </body>
</html> </html>

View File

@ -1,36 +1,36 @@
.CodeMirror-hints { .CodeMirror-hints {
position: absolute; position: absolute;
z-index: 10; z-index: 10;
overflow: hidden; overflow: hidden;
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 2px; padding: 2px;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2); -webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2); -moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2); box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
border-radius: 3px; border-radius: 3px;
border: 1px solid silver; border: 1px solid silver;
background: white; background: white;
font-size: 90%; font-size: 90%;
font-family: monospace; font-family: monospace;
max-height: 20em; max-height: 20em;
overflow-y: auto; overflow-y: auto;
} }
.CodeMirror-hint { .CodeMirror-hint {
margin: 0; margin: 0;
padding: 0 4px; padding: 0 4px;
border-radius: 2px; border-radius: 2px;
white-space: pre; white-space: pre;
color: black; color: black;
cursor: pointer; cursor: pointer;
} }
li.CodeMirror-hint-active { li.CodeMirror-hint-active {
background: #08f; background: #08f;
color: white; color: white;
} }

View File

@ -14,91 +14,111 @@
font-size: 16px; font-size: 16px;
padding: 20px; padding: 20px;
line-height: 25px; line-height: 25px;
} }
.cm-s-style-mirror div.CodeMirror-selected {
.cm-s-style-mirror div.CodeMirror-selected {
background: #e0e0e0; background: #e0e0e0;
} }
.cm-s-style-mirror .CodeMirror-line::selection,
.cm-s-style-mirror .CodeMirror-line > span::selection, .cm-s-style-mirror .CodeMirror-line::selection,
.cm-s-style-mirror .CodeMirror-line > span > span::selection { .cm-s-style-mirror .CodeMirror-line>span::selection,
.cm-s-style-mirror .CodeMirror-line>span>span::selection {
background: #e0e0e0; background: #e0e0e0;
} }
.cm-s-style-mirror .CodeMirror-line::-moz-selection,
.cm-s-style-mirror .CodeMirror-line > span::-moz-selection, .cm-s-style-mirror .CodeMirror-line::-moz-selection,
.cm-s-style-mirror .CodeMirror-line > span > span::-moz-selection { .cm-s-style-mirror .CodeMirror-line>span::-moz-selection,
.cm-s-style-mirror .CodeMirror-line>span>span::-moz-selection {
background: #e0e0e0; background: #e0e0e0;
} }
.cm-s-style-mirror .CodeMirror-gutters {
.cm-s-style-mirror .CodeMirror-gutters {
background: #f5f5f5; background: #f5f5f5;
border-right: 0px; border-right: 0px;
} }
.cm-s-style-mirror .CodeMirror-guttermarker {
.cm-s-style-mirror .CodeMirror-guttermarker {
color: #ac4142; color: #ac4142;
} }
.cm-s-style-mirror .CodeMirror-guttermarker-subtle {
.cm-s-style-mirror .CodeMirror-guttermarker-subtle {
color: #b0b0b0; color: #b0b0b0;
} }
.cm-s-style-mirror .CodeMirror-linenumber {
.cm-s-style-mirror .CodeMirror-linenumber {
color: #b0b0b0; color: #b0b0b0;
} }
.cm-s-style-mirror .CodeMirror-cursor {
.cm-s-style-mirror .CodeMirror-cursor {
border-left: 1px solid #505050; border-left: 1px solid #505050;
} }
.cm-s-style-mirror span.cm-comment { .cm-s-style-mirror span.cm-comment {
color:green; color: green;
} }
.cm-s-style-mirror span.cm-atom {
color: #aa759f;
}
.cm-s-style-mirror span.cm-number {
color: #aa759f;
}
.cm-s-style-mirror span.cm-property, .cm-s-style-mirror span.cm-atom {
.cm-s-style-mirror span.cm-attribute { color: #aa759f;
}
.cm-s-style-mirror span.cm-number {
color: #aa759f;
}
.cm-s-style-mirror span.cm-property,
.cm-s-style-mirror span.cm-attribute {
color: #90a959; color: #90a959;
} }
.cm-s-style-mirror span.cm-keyword {
.cm-s-style-mirror span.cm-keyword {
color: #023a52; color: #023a52;
} }
.cm-s-style-mirror span.cm-string {
color: #e46918;
}
.cm-s-style-mirror span.cm-variable { .cm-s-style-mirror span.cm-string {
color: #e46918;
}
.cm-s-style-mirror span.cm-variable {
color: #90a959; color: #90a959;
} }
.cm-s-style-mirror span.cm-variable-2 {
.cm-s-style-mirror span.cm-variable-2 {
color: #00695f; color: #00695f;
} }
.cm-s-style-mirror span.cm-variable-3 {
.cm-s-style-mirror span.cm-variable-3 {
color: #2e6e8a; color: #2e6e8a;
} }
.cm-s-style-mirror span.cm-def {
.cm-s-style-mirror span.cm-def {
color: #d28445; color: #d28445;
} }
.cm-s-style-mirror span.cm-bracket {
.cm-s-style-mirror span.cm-bracket {
color: #202020; color: #202020;
} }
.cm-s-style-mirror span.cm-tag {
color:#000; .cm-s-style-mirror span.cm-tag {
} color: #000;
.cm-s-style-mirror span.cm-link { }
.cm-s-style-mirror span.cm-link {
color: #b26a00; color: #b26a00;
} }
.cm-s-style-mirror span.cm-error {
.cm-s-style-mirror span.cm-error {
/* background: #ac4142; /* background: #ac4142;
color: #f5f5f5; */ color: #f5f5f5; */
text-decoration: underline; text-decoration: underline;
text-decoration-style: wavy; text-decoration-style: wavy;
text-decoration-color: #df8d8e; text-decoration-color: #df8d8e;
} }
.cm-s-style-mirror .CodeMirror-activeline-background {
background: #dddcdc;
}
.cm-s-style-mirror .CodeMirror-matchingbracket {
color: rgb(32,32,32) !important;
background-color: rgba(0,0,0,0.1) !important;
}
.cm-s-style-mirror .CodeMirror-activeline-background {
background: #dddcdc;
}
.cm-s-style-mirror .CodeMirror-matchingbracket {
color: rgb(32, 32, 32) !important;
background-color: rgba(0, 0, 0, 0.1) !important;
}

View File

@ -21,9 +21,6 @@ export default {
setTimeout(() => { setTimeout(() => {
this.loading = false this.loading = false
}, 200) }, 200)
window.console &&
window.console.log &&
(console.log("Think big, train fast, learn deep. See https://github.com/yanglbme"))
} }
} }

View File

@ -20,11 +20,7 @@ service.interceptors.request.use(
); );
service.interceptors.response.use(res => { service.interceptors.response.use(res => {
if (res.data.success) { return res.data.success ? res.data : Promise.reject(res.data);
return res.data;
}
console.log(res);
return Promise.reject(res.data);
}, error => Promise.reject(error)); }, error => Promise.reject(error));
export default service; export default service;

View File

@ -1,16 +1,17 @@
<template> <template>
<div class="loading" id="loading"> <div class="loading" id="loading">
<div class="loading-wrapper"> <div class="loading-wrapper">
<div class="loading-text">Loading...</div> <div class="loading-text">Loading...</div>
<div class="loading-anim"></div> <div class="loading-anim"></div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
}
}
</script> </script>
<style scoped> <style scoped>

View File

@ -1,22 +1,22 @@
import Vue from 'vue' import Vue from 'vue'
import { import {
Container, Container,
Header, Header,
Upload, Upload,
Tooltip, Tooltip,
Form, Form,
FormItem, FormItem,
Select, Select,
Option, Option,
ColorPicker, ColorPicker,
Switch, Switch,
Button, Button,
Main, Main,
Col, Col,
Row, Row,
Dialog, Dialog,
Loading, Loading,
Message Message
} from 'element-ui' } from 'element-ui'
Vue.use(Container) Vue.use(Container)

View File

@ -1,214 +1,218 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
import CodeMirror from "codemirror/lib/codemirror"; import CodeMirror from "codemirror/lib/codemirror";
(function(CodeMirror) { (function (CodeMirror) {
var defaults = { var defaults = {
pairs: "()[]{}''\"\"", pairs: "()[]{}''\"\"",
closeBefore: ")]}'\":;>", closeBefore: ")]}'\":;>",
triples: "", triples: "",
explode: "[]{}" explode: "[]{}"
};
var Pos = CodeMirror.Pos;
CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
cm.removeKeyMap(keyMap);
cm.state.closeBrackets = null;
}
if (val) {
ensureBound(getOption(val, "pairs"));
cm.state.closeBrackets = val;
cm.addKeyMap(keyMap);
}
});
function getOption(conf, name) {
if (name == "pairs" && typeof conf == "string") return conf;
if (typeof conf == "object" && conf[name] != null) return conf[name];
return defaults[name];
}
var keyMap = { Backspace: handleBackspace, Enter: handleEnter };
function ensureBound(chars) {
for (var i = 0; i < chars.length; i++) {
var ch = chars.charAt(i),
key = "'" + ch + "'";
if (!keyMap[key]) keyMap[key] = handler(ch);
}
}
ensureBound(defaults.pairs + "`");
function handler(ch) {
return function(cm) {
return handleChar(cm, ch);
}; };
}
function getConfig(cm) { var Pos = CodeMirror.Pos;
var deflt = cm.state.closeBrackets;
if (!deflt || deflt.override) return deflt;
var mode = cm.getModeAt(cm.getCursor());
return mode.closeBrackets || deflt;
}
function handleBackspace(cm) { CodeMirror.defineOption("autoCloseBrackets", false, function (cm, val, old) {
var conf = getConfig(cm); if (old && old != CodeMirror.Init) {
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; cm.removeKeyMap(keyMap);
cm.state.closeBrackets = null;
var pairs = getOption(conf, "pairs"); }
var ranges = cm.listSelections(); if (val) {
for (var i = 0; i < ranges.length; i++) { ensureBound(getOption(val, "pairs"));
if (!ranges[i].empty()) return CodeMirror.Pass; cm.state.closeBrackets = val;
var around = charsAround(cm, ranges[i].head); cm.addKeyMap(keyMap);
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; }
}
for (var i = ranges.length - 1; i >= 0; i--) {
var cur = ranges[i].head;
cm.replaceRange(
"",
Pos(cur.line, cur.ch - 1),
Pos(cur.line, cur.ch + 1),
"+delete"
);
}
}
function handleEnter(cm) {
var conf = getConfig(cm);
var explode = conf && getOption(conf, "explode");
if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var around = charsAround(cm, ranges[i].head);
if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
}
cm.operation(function() {
var linesep = cm.lineSeparator() || "\n";
cm.replaceSelection(linesep + linesep, null);
cm.execCommand("goCharLeft");
ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var line = ranges[i].head.line;
cm.indentLine(line, null, true);
cm.indentLine(line + 1, null, true);
}
}); });
}
function contractSelection(sel) { function getOption(conf, name) {
var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0; if (name == "pairs" && typeof conf == "string") return conf;
return { if (typeof conf == "object" && conf[name] != null) return conf[name];
anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)), return defaults[name];
head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1)) }
var keyMap = {
Backspace: handleBackspace,
Enter: handleEnter
}; };
}
function handleChar(cm, ch) { function ensureBound(chars) {
var conf = getConfig(cm); for (var i = 0; i < chars.length; i++) {
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; var ch = chars.charAt(i),
key = "'" + ch + "'";
if (!keyMap[key]) keyMap[key] = handler(ch);
}
}
ensureBound(defaults.pairs + "`");
var pairs = getOption(conf, "pairs"); function handler(ch) {
var pos = pairs.indexOf(ch); return function (cm) {
if (pos == -1) return CodeMirror.Pass; return handleChar(cm, ch);
};
var closeBefore = getOption(conf, "closeBefore");
var triples = getOption(conf, "triples");
var identical = pairs.charAt(pos + 1) == ch;
var ranges = cm.listSelections();
var opening = pos % 2 == 0;
var type;
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i],
cur = range.head,
curType;
var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
if (opening && !range.empty()) {
curType = "surround";
} else if ((identical || !opening) && next == ch) {
if (identical && stringStartsAfter(cm, cur)) curType = "both";
else if (
triples.indexOf(ch) >= 0 &&
cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch
)
curType = "skipThree";
else curType = "skip";
} else if (
identical &&
cur.ch > 1 &&
triples.indexOf(ch) >= 0 &&
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch
) {
if (
cur.ch > 2 &&
/\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))
)
return CodeMirror.Pass;
curType = "addFour";
} else if (identical) {
var prev =
cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur);
if (
!CodeMirror.isWordChar(next) &&
prev != ch &&
!CodeMirror.isWordChar(prev)
)
curType = "both";
else return CodeMirror.Pass;
} else if (
opening &&
(next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)
) {
curType = "both";
} else {
return CodeMirror.Pass;
}
if (!type) type = curType;
else if (type != curType) return CodeMirror.Pass;
} }
var left = pos % 2 ? pairs.charAt(pos - 1) : ch; function getConfig(cm) {
var right = pos % 2 ? ch : pairs.charAt(pos + 1); var deflt = cm.state.closeBrackets;
cm.operation(function() { if (!deflt || deflt.override) return deflt;
if (type == "skip") { var mode = cm.getModeAt(cm.getCursor());
cm.execCommand("goCharRight"); return mode.closeBrackets || deflt;
} else if (type == "skipThree") { }
for (var i = 0; i < 3; i++) cm.execCommand("goCharRight");
} else if (type == "surround") {
var sels = cm.getSelections();
for (var i = 0; i < sels.length; i++) sels[i] = left + sels[i] + right;
cm.replaceSelections(sels, "around");
sels = cm.listSelections().slice();
for (var i = 0; i < sels.length; i++)
sels[i] = contractSelection(sels[i]);
cm.setSelections(sels);
} else if (type == "both") {
cm.replaceSelection(left + right, null);
cm.triggerElectric(left + right);
cm.execCommand("goCharLeft");
} else if (type == "addFour") {
cm.replaceSelection(left + left + left + left, "before");
cm.execCommand("goCharRight");
}
});
}
function charsAround(cm, pos) { function handleBackspace(cm) {
var str = cm.getRange(Pos(pos.line, pos.ch - 1), Pos(pos.line, pos.ch + 1)); var conf = getConfig(cm);
return str.length == 2 ? str : null; if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
}
function stringStartsAfter(cm, pos) { var pairs = getOption(conf, "pairs");
var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1)); var ranges = cm.listSelections();
return ( for (var i = 0; i < ranges.length; i++) {
/\bstring/.test(token.type) && if (!ranges[i].empty()) return CodeMirror.Pass;
token.start == pos.ch && var around = charsAround(cm, ranges[i].head);
(pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos))) if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
); }
} for (var i = ranges.length - 1; i >= 0; i--) {
var cur = ranges[i].head;
cm.replaceRange(
"",
Pos(cur.line, cur.ch - 1),
Pos(cur.line, cur.ch + 1),
"+delete"
);
}
}
function handleEnter(cm) {
var conf = getConfig(cm);
var explode = conf && getOption(conf, "explode");
if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var around = charsAround(cm, ranges[i].head);
if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
}
cm.operation(function () {
var linesep = cm.lineSeparator() || "\n";
cm.replaceSelection(linesep + linesep, null);
cm.execCommand("goCharLeft");
ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var line = ranges[i].head.line;
cm.indentLine(line, null, true);
cm.indentLine(line + 1, null, true);
}
});
}
function contractSelection(sel) {
var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
return {
anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))
};
}
function handleChar(cm, ch) {
var conf = getConfig(cm);
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
var pairs = getOption(conf, "pairs");
var pos = pairs.indexOf(ch);
if (pos == -1) return CodeMirror.Pass;
var closeBefore = getOption(conf, "closeBefore");
var triples = getOption(conf, "triples");
var identical = pairs.charAt(pos + 1) == ch;
var ranges = cm.listSelections();
var opening = pos % 2 == 0;
var type;
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i],
cur = range.head,
curType;
var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
if (opening && !range.empty()) {
curType = "surround";
} else if ((identical || !opening) && next == ch) {
if (identical && stringStartsAfter(cm, cur)) curType = "both";
else if (
triples.indexOf(ch) >= 0 &&
cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch
)
curType = "skipThree";
else curType = "skip";
} else if (
identical &&
cur.ch > 1 &&
triples.indexOf(ch) >= 0 &&
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch
) {
if (
cur.ch > 2 &&
/\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))
)
return CodeMirror.Pass;
curType = "addFour";
} else if (identical) {
var prev =
cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur);
if (
!CodeMirror.isWordChar(next) &&
prev != ch &&
!CodeMirror.isWordChar(prev)
)
curType = "both";
else return CodeMirror.Pass;
} else if (
opening &&
(next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)
) {
curType = "both";
} else {
return CodeMirror.Pass;
}
if (!type) type = curType;
else if (type != curType) return CodeMirror.Pass;
}
var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
var right = pos % 2 ? ch : pairs.charAt(pos + 1);
cm.operation(function () {
if (type == "skip") {
cm.execCommand("goCharRight");
} else if (type == "skipThree") {
for (var i = 0; i < 3; i++) cm.execCommand("goCharRight");
} else if (type == "surround") {
var sels = cm.getSelections();
for (var i = 0; i < sels.length; i++) sels[i] = left + sels[i] + right;
cm.replaceSelections(sels, "around");
sels = cm.listSelections().slice();
for (var i = 0; i < sels.length; i++)
sels[i] = contractSelection(sels[i]);
cm.setSelections(sels);
} else if (type == "both") {
cm.replaceSelection(left + right, null);
cm.triggerElectric(left + right);
cm.execCommand("goCharLeft");
} else if (type == "addFour") {
cm.replaceSelection(left + left + left + left, "before");
cm.execCommand("goCharRight");
}
});
}
function charsAround(cm, pos) {
var str = cm.getRange(Pos(pos.line, pos.ch - 1), Pos(pos.line, pos.ch + 1));
return str.length == 2 ? str : null;
}
function stringStartsAfter(cm, pos) {
var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1));
return (
/\bstring/.test(token.type) &&
token.start == pos.ch &&
(pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos)))
);
}
})(CodeMirror); })(CodeMirror);

View File

@ -1,6 +1,5 @@
export default { export default {
builtinFonts: [ builtinFonts: [{
{
label: '无衬线', label: '无衬线',
value: '-apple-system-font,BlinkMacSystemFont, Helvetica Neue, PingFang SC, Hiragino Sans GB , Microsoft YaHei UI , Microsoft YaHei ,Arial,sans-serif' value: '-apple-system-font,BlinkMacSystemFont, Helvetica Neue, PingFang SC, Hiragino Sans GB , Microsoft YaHei UI , Microsoft YaHei ,Arial,sans-serif'
}, },
@ -9,8 +8,7 @@ export default {
value: "Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif" value: "Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif"
} }
], ],
sizeOption: [ sizeOption: [{
{
label: '12px', label: '12px',
value: '12px', value: '12px',
desc: '更小' desc: '更小'
@ -36,8 +34,7 @@ export default {
desc: '更大' desc: '更大'
} }
], ],
colorOption: [ colorOption: [{
{
label: '经典蓝', label: '经典蓝',
value: 'rgba(15, 76, 129, 1)', value: 'rgba(15, 76, 129, 1)',
hex: '最新流行' hex: '最新流行'

View File

@ -1,28 +1,27 @@
import juice from 'juice' import juice from 'juice'
export function solveWeChatImage() { export function solveWeChatImage() {
const clipboardDiv = document.getElementById('output'); const clipboardDiv = document.getElementById('output');
const images = clipboardDiv.getElementsByTagName("img"); const images = clipboardDiv.getElementsByTagName("img");
for (let i = 0; i < images.length; i++) { for (let i = 0; i < images.length; i++) {
const image = images[i]; const image = images[i];
const width = image.getAttribute("width"); const width = image.getAttribute("width");
const height = image.getAttribute("height"); const height = image.getAttribute("height");
image.removeAttribute("width"); image.removeAttribute("width");
image.removeAttribute("height"); image.removeAttribute("height");
image.style.width = width; image.style.width = width;
image.style.height = height; image.style.height = height;
} }
} }
export function solveHtml(nightMode = false) { export function solveHtml(nightMode = false) {
const element = document.getElementById("output-wrapper"); const element = document.getElementById("output-wrapper");
let html = element.innerHTML let html = element.innerHTML
let res = ""; let res = "";
res = juice.inlineContent( res = juice.inlineContent(
html, html, {
{ inlinePseudoElements: true,
inlinePseudoElements: true, preserveImportant: true
preserveImportant: true }
} );
); return res;
return res;
} }

View File

@ -1,84 +1,96 @@
import CodeMirror from "codemirror/lib/codemirror"; import CodeMirror from "codemirror/lib/codemirror";
(function () { (function () {
CodeMirror.extendMode('css', { CodeMirror.extendMode('css', {
commentStart: '/*', commentStart: '/*',
commentEnd: '*/', commentEnd: '*/',
newlineAfterToken: function (type, content) { newlineAfterToken: function (type, content) {
return /^[;{}]$/.test(content) return /^[;{}]$/.test(content)
}
})
// Comment/uncomment the specified range
CodeMirror.defineExtension('commentRange', function (isComment, from, to) {
var cm = this; var curMode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(from).state).mode
cm.operation(function () {
if (isComment) { // Comment range
cm.replaceRange(curMode.commentEnd, to)
cm.replaceRange(curMode.commentStart, from)
if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
{ cm.setCursor(from.line, from.ch + curMode.commentStart.length) }
} else { // Uncomment range
var selText = cm.getRange(from, to)
var startIndex = selText.indexOf(curMode.commentStart)
var endIndex = selText.lastIndexOf(curMode.commentEnd)
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
// Take string till comment start
selText = selText.substr(0, startIndex) +
// From comment start till comment end
selText.substring(startIndex + curMode.commentStart.length, endIndex) +
// From comment end till string end
selText.substr(endIndex + curMode.commentEnd.length)
} }
cm.replaceRange(selText, from, to)
}
}) })
})
// Applies automatic mode-aware indentation to the specified range // Comment/uncomment the specified range
CodeMirror.defineExtension('autoIndentRange', function (from, to) { CodeMirror.defineExtension('commentRange', function (isComment, from, to) {
var cmInstance = this var cm = this;
this.operation(function () { var curMode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(from).state).mode
for (var i = from.line; i <= to.line; i++) { cm.operation(function () {
cmInstance.indentLine(i, 'smart') if (isComment) { // Comment range
} cm.replaceRange(curMode.commentEnd, to)
cm.replaceRange(curMode.commentStart, from)
if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
{
cm.setCursor(from.line, from.ch + curMode.commentStart.length)
}
} else { // Uncomment range
var selText = cm.getRange(from, to)
var startIndex = selText.indexOf(curMode.commentStart)
var endIndex = selText.lastIndexOf(curMode.commentEnd)
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
// Take string till comment start
selText = selText.substr(0, startIndex) +
// From comment start till comment end
selText.substring(startIndex + curMode.commentStart.length, endIndex) +
// From comment end till string end
selText.substr(endIndex + curMode.commentEnd.length)
}
cm.replaceRange(selText, from, to)
}
})
}) })
})
// Applies automatic formatting to the specified range // Applies automatic mode-aware indentation to the specified range
CodeMirror.defineExtension('autoFormatRange', function (from, to) { CodeMirror.defineExtension('autoIndentRange', function (from, to) {
var cm = this var cmInstance = this
var outer = cm.getMode(); var text = cm.getRange(from, to).split('\n') this.operation(function () {
var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state) for (var i = from.line; i <= to.line; i++) {
var tabSize = cm.getOption('tabSize') cmInstance.indentLine(i, 'smart')
}
})
})
var out = ''; var lines = 0; var atSol = from.ch == 0 // Applies automatic formatting to the specified range
function newline () { CodeMirror.defineExtension('autoFormatRange', function (from, to) {
out += '\n' var cm = this
atSol = true var outer = cm.getMode();
++lines var text = cm.getRange(from, to).split('\n')
} var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state)
var tabSize = cm.getOption('tabSize')
for (var i = 0; i < text.length; ++i) { var out = '';
var stream = new CodeMirror.StringStream(text[i], tabSize) var lines = 0;
while (!stream.eol()) { var atSol = from.ch == 0
var inner = CodeMirror.innerMode(outer, state)
var style = outer.token(stream, state); var cur = stream.current() function newline() {
stream.start = stream.pos out += '\n'
if (!atSol || /\S/.test(cur)) { atSol = true
out += cur ++lines
atSol = false
} }
if (!atSol && inner.mode.newlineAfterToken &&
inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i + 1] || '', inner.state)) { newline() }
}
if (!stream.pos && outer.blankLine) outer.blankLine(state)
if (!atSol) newline()
}
cm.operation(function () { for (var i = 0; i < text.length; ++i) {
cm.replaceRange(out, from, to) var stream = new CodeMirror.StringStream(text[i], tabSize)
for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur) { cm.indentLine(cur, 'smart') } while (!stream.eol()) {
cm.setSelection(from, cm.getCursor(false)) var inner = CodeMirror.innerMode(outer, state)
var style = outer.token(stream, state);
var cur = stream.current()
stream.start = stream.pos
if (!atSol || /\S/.test(cur)) {
out += cur
atSol = false
}
if (!atSol && inner.mode.newlineAfterToken &&
inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i + 1] || '', inner.state)) {
newline()
}
}
if (!stream.pos && outer.blankLine) outer.blankLine(state)
if (!atSol) newline()
}
cm.operation(function () {
cm.replaceRange(out, from, to)
for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur) {
cm.indentLine(cur, 'smart')
}
cm.setSelection(from, cm.getCursor(false))
})
}) })
})
})() })()

View File

@ -1,73 +1,73 @@
import marked from 'marked' import marked from 'marked'
const WxRenderer = function (opts) { const WxRenderer = function (opts) {
this.opts = opts this.opts = opts
let ENV_STRETCH_IMAGE = true 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 = 'Menlo, Operator Mono, Consolas, Monaco, monospace' const CODE_FONT_FAMILY = '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]
if (ele === 'codespan') { if (ele === 'codespan') {
style['font-family'] = CODE_FONT_FAMILY style['font-family'] = CODE_FONT_FAMILY
style['white-space'] = 'normal' style['white-space'] = 'normal'
}
mapping[ele] = merge(base, style)
}
} }
mapping[ele] = merge(base, style)
}
}
for (let ele in themeTpl.block) { for (let ele in themeTpl.block) {
if (themeTpl.block.hasOwnProperty(ele)) { if (themeTpl.block.hasOwnProperty(ele)) {
let style = themeTpl.block[ele] let style = themeTpl.block[ele]
if (ele === 'code') { if (ele === 'code') {
style['font-family'] = CODE_FONT_FAMILY style['font-family'] = CODE_FONT_FAMILY
}
mapping[ele] = merge(base_block, style)
}
} }
mapping[ele] = merge(base_block, style) return mapping
}
} }
return mapping
}
let getStyles = (tokenName, addition) => { let getStyles = (tokenName, addition) => {
let arr = [] let arr = []
let dict = styleMapping[tokenName] let dict = styleMapping[tokenName]
if (!dict) return '' if (!dict) return ''
for (const key in dict) { for (const key in dict) {
arr.push(key + ':' + dict[key]) arr.push(key + ':' + dict[key])
}
return `style="${arr.join(';') + (addition || '')}"`
} }
return `style="${arr.join(';') + (addition || '')}"`
}
let addFootnote = (title, link) => { let addFootnote = (title, link) => {
footnotes.push([++footnoteIndex, title, link]) footnotes.push([++footnoteIndex, title, link])
return footnoteIndex return footnoteIndex
} }
this.buildFootnotes = () => { this.buildFootnotes = () => {
let footnoteArray = footnotes.map(x => { let footnoteArray = footnotes.map(x => {
if (x[1] === x[2]) { 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>: <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 `<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>` return `<h4 ${getStyles('h4')}>引用链接</h4><p ${getStyles('footnotes')}>${footnoteArray.join('\n')}</p>`
} }
this.buildAddition = () => { this.buildAddition = () => {
return ` return `
<style> <style>
.preview-wrapper pre::before { .preview-wrapper pre::before {
font-family: "SourceSansPro", "HelveticaNeue", Arial, sans-serif; font-family: "SourceSansPro", "HelveticaNeue", Arial, sans-serif;
@ -84,60 +84,60 @@ 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.*?>/, `<p ${getStyles('blockquote_p')}>`) this.opts = merge(this.opts, newOpts)
return `<blockquote ${getStyles('blockquote')}>${text}</blockquote>`
} }
renderer.code = (text, infoString) => {
text = text.replace(/</g, '&lt;')
text = text.replace(/>/g, '&gt;')
let lines = text.split('\n') this.hasFootnotes = () => footnotes.length !== 0
let codeLines = []
let numbers = []
for (let i = 0; i < lines.length; i++) { this.getRenderer = (status) => {
const line = lines[i] footnotes = []
codeLines.push(`<code class="prettyprint"><span class="code-snippet_outer">${(line || '<br>')}</span></code>`) footnoteIndex = 0
numbers.push('<li></li>')
}
let lang = infoString || ''
return ` 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 => {
text = text.replace(/<p.*?>/, `<p ${getStyles('blockquote_p')}>`)
return `<blockquote ${getStyles('blockquote')}>${text}</blockquote>`
}
renderer.code = (text, infoString) => {
text = text.replace(/</g, '&lt;')
text = text.replace(/>/g, '&gt;')
let lines = text.split('\n')
let codeLines = []
let numbers = []
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
codeLines.push(`<code class="prettyprint"><span class="code-snippet_outer">${(line || '<br>')}</span></code>`)
numbers.push('<li></li>')
}
let lang = infoString || ''
return `
<section class="code-snippet__fix code-snippet__js"> <section class="code-snippet__fix code-snippet__js">
<ul class="code-snippet__line-index code-snippet__js">${numbers.join('')}</ul> <ul class="code-snippet__line-index code-snippet__js">${numbers.join('')}</ul>
<pre class="code-snippet__js" data-lang="${lang}"> <pre class="code-snippet__js" data-lang="${lang}">
@ -145,53 +145,53 @@ const WxRenderer = function (opts) {
</pre> </pre>
</section> </section>
` `
}
renderer.codespan = (text, infoString) => `<code ${getStyles('codespan')}>${text}</code>`
renderer.listitem = text => `<span ${getStyles('listitem')}><span style="margin-right: 10px;"><%s/></span>${text}</span>`
renderer.list = (text, ordered, start) => {
text = text.replace(/<\/*p.*?>/g, '')
let segments = text.split(`<%s/>`)
if (!ordered) {
text = segments.join('•')
return `<p ${getStyles('ul')}>${text}</p>`
}
text = segments[0]
for (let i = 1; i < segments.length; i++) {
text = text + i + '.' + segments[i]
}
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>`
} else if (href === text) {
return text
} else {
if (status) {
let ref = addFootnote(title || text, href)
return `<span ${getStyles('link')}>${text}<sup>[${ref}]</sup></span>`
} else {
return text
} }
} renderer.codespan = (text, infoString) => `<code ${getStyles('codespan')}>${text}</code>`
renderer.listitem = text => `<span ${getStyles('listitem')}><span style="margin-right: 10px;"><%s/></span>${text}</span>`
renderer.list = (text, ordered, start) => {
text = text.replace(/<\/*p.*?>/g, '')
let segments = text.split(`<%s/>`)
if (!ordered) {
text = segments.join('•')
return `<p ${getStyles('ul')}>${text}</p>`
}
text = segments[0]
for (let i = 1; i < segments.length; i++) {
text = text + i + '.' + segments[i]
}
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>`
} else if (href === text) {
return text
} else {
if (status) {
let ref = addFootnote(title || text, href)
return `<span ${getStyles('link')}>${text}<sup>[${ref}]</sup></span>`
} else {
return text
}
}
}
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.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

View File

@ -1,23 +1,23 @@
// 左右栏同步滚动 // 左右栏同步滚动
$(document).ready(() => { $(document).ready(() => {
let timeout; let timeout;
$('div.CodeMirror-scroll, #preview').on("scroll", function callback() { $('div.CodeMirror-scroll, #preview').on("scroll", function callback() {
clearTimeout(timeout); clearTimeout(timeout);
let source = $(this), let source = $(this),
target = $(source.is("#preview") ? 'div.CodeMirror-scroll' : '#preview'); target = $(source.is("#preview") ? 'div.CodeMirror-scroll' : '#preview');
target.off("scroll"); target.off("scroll");
let source0 = source[0]; let source0 = source[0];
let target0 = target[0]; let target0 = target[0];
let percentage = source0.scrollTop / (source0.scrollHeight - source0.offsetHeight); let percentage = source0.scrollTop / (source0.scrollHeight - source0.offsetHeight);
let height = percentage * (target0.scrollHeight - target0.offsetHeight); let height = percentage * (target0.scrollHeight - target0.offsetHeight);
target0.scrollTo(0, height); target0.scrollTo(0, height);
timeout = setTimeout(() => { timeout = setTimeout(() => {
target.on("scroll", callback); target.on("scroll", callback);
}, 100); }, 100);
}); });
}); });

View File

@ -1,11 +1,25 @@
import default_theme from './themes/default-theme' import default_theme from './themes/default-theme'
import prettier from 'prettier/standalone' import prettier from 'prettier/standalone'
import prettierMarkdown from 'prettier/parser-markdown' import prettierMarkdown from 'prettier/parser-markdown'
// 设置自定义颜色 // 设置自定义颜色
export function setColorWithTemplate (template) { export function setColorWithTemplate(template) {
return function (color) { return function (color) {
let custom_theme = JSON.parse(JSON.stringify(template))
custom_theme.block.h1['border-bottom'] = `2px solid ${color}`
custom_theme.block.h2['background'] = color
custom_theme.block.h3['border-left'] = `3px solid ${color}`
custom_theme.block.h4['color'] = color
custom_theme.inline.strong['color'] = color
return custom_theme
}
}
export const setColorWithCustomTemplate = function setColorWithCustomTemplate(
template,
color
) {
let custom_theme = JSON.parse(JSON.stringify(template)) let custom_theme = JSON.parse(JSON.stringify(template))
custom_theme.block.h1['border-bottom'] = `2px solid ${color}` custom_theme.block.h1['border-bottom'] = `2px solid ${color}`
custom_theme.block.h2['background'] = color custom_theme.block.h2['background'] = color
@ -13,83 +27,69 @@ export function setColorWithTemplate (template) {
custom_theme.block.h4['color'] = color custom_theme.block.h4['color'] = color
custom_theme.inline.strong['color'] = color custom_theme.inline.strong['color'] = color
return custom_theme return custom_theme
}
}
export const setColorWithCustomTemplate = function setColorWithCustomTemplate (
template,
color
) {
let custom_theme = JSON.parse(JSON.stringify(template))
custom_theme.block.h1['border-bottom'] = `2px solid ${color}`
custom_theme.block.h2['background'] = color
custom_theme.block.h3['border-left'] = `3px solid ${color}`
custom_theme.block.h4['color'] = color
custom_theme.inline.strong['color'] = color
return custom_theme
} }
// 设置自定义字体大小 // 设置自定义字体大小
export function setFontSizeWithTemplate (template) { export function setFontSizeWithTemplate(template) {
return function (fontSize) { return function (fontSize) {
let custom_theme = JSON.parse(JSON.stringify(template)) let custom_theme = JSON.parse(JSON.stringify(template))
custom_theme.block.h1['font-size'] = `${fontSize * 1.14}px` custom_theme.block.h1['font-size'] = `${fontSize * 1.14}px`
custom_theme.block.h2['font-size'] = `${fontSize * 1.1}px` custom_theme.block.h2['font-size'] = `${fontSize * 1.1}px`
custom_theme.block.h3['font-size'] = `${fontSize}px` custom_theme.block.h3['font-size'] = `${fontSize}px`
custom_theme.block.h4['font-size'] = `${fontSize}px` custom_theme.block.h4['font-size'] = `${fontSize}px`
return custom_theme return custom_theme
} }
} }
export const setColor = setColorWithTemplate(default_theme) export const setColor = setColorWithTemplate(default_theme)
export const setFontSize = setFontSizeWithTemplate(default_theme) export const setFontSize = setFontSizeWithTemplate(default_theme)
export function customCssWithTemplate (jsonString, color, theme) { export function customCssWithTemplate(jsonString, color, theme) {
let custom_theme = JSON.parse(JSON.stringify(theme)) let custom_theme = JSON.parse(JSON.stringify(theme))
// block // block
custom_theme.block.h1['border-bottom'] = `2px solid ${color}` custom_theme.block.h1['border-bottom'] = `2px solid ${color}`
custom_theme.block.h2['background'] = color custom_theme.block.h2['background'] = color
custom_theme.block.h3['border-left'] = `3px solid ${color}` custom_theme.block.h3['border-left'] = `3px solid ${color}`
custom_theme.block.h4['color'] = color custom_theme.block.h4['color'] = color
custom_theme.inline.strong['color'] = color custom_theme.inline.strong['color'] = color
custom_theme.block.h1 = Object.assign(custom_theme.block.h1, jsonString.h1) custom_theme.block.h1 = Object.assign(custom_theme.block.h1, jsonString.h1)
custom_theme.block.h2 = Object.assign(custom_theme.block.h2, jsonString.h2) custom_theme.block.h2 = Object.assign(custom_theme.block.h2, jsonString.h2)
custom_theme.block.h3 = Object.assign(custom_theme.block.h3, jsonString.h3) custom_theme.block.h3 = Object.assign(custom_theme.block.h3, jsonString.h3)
custom_theme.block.h4 = Object.assign(custom_theme.block.h4, jsonString.h4) custom_theme.block.h4 = Object.assign(custom_theme.block.h4, jsonString.h4)
custom_theme.block.p = Object.assign(custom_theme.block.p, jsonString.p) custom_theme.block.p = Object.assign(custom_theme.block.p, jsonString.p)
custom_theme.block.blockquote = Object.assign( custom_theme.block.blockquote = Object.assign(
custom_theme.block.blockquote, custom_theme.block.blockquote,
jsonString.blockquote jsonString.blockquote
) )
custom_theme.block.blockquote_p = Object.assign( custom_theme.block.blockquote_p = Object.assign(
custom_theme.block.blockquote_p, custom_theme.block.blockquote_p,
jsonString.blockquote_p jsonString.blockquote_p
) )
custom_theme.block.image = Object.assign( custom_theme.block.image = Object.assign(
custom_theme.block.image, custom_theme.block.image,
jsonString.image jsonString.image
) )
// inline // inline
custom_theme.inline.strong = Object.assign( custom_theme.inline.strong = Object.assign(
custom_theme.inline.strong, custom_theme.inline.strong,
jsonString.strong jsonString.strong
) )
custom_theme.inline.codespan = Object.assign( custom_theme.inline.codespan = Object.assign(
custom_theme.inline.codespan, custom_theme.inline.codespan,
jsonString.codespan jsonString.codespan
) )
custom_theme.inline.link = Object.assign( custom_theme.inline.link = Object.assign(
custom_theme.inline.link, custom_theme.inline.link,
jsonString.link jsonString.link
) )
custom_theme.inline.wx_link = Object.assign( custom_theme.inline.wx_link = Object.assign(
custom_theme.inline.wx_link, custom_theme.inline.wx_link,
jsonString.wx_link jsonString.wx_link
) )
return custom_theme return custom_theme
} }
/** /**
@ -97,77 +97,78 @@ export function customCssWithTemplate (jsonString, color, theme) {
* *
* @param {css字符串} css * @param {css字符串} css
*/ */
export function css2json (css) { export function css2json(css) {
// 移除CSS所有注释 // 移除CSS所有注释
while ( let open, close;
(open = css.indexOf('/*')) !== -1 && while (
(close = css.indexOf('*/')) !== -1 (open = css.indexOf('/*')) !== -1 &&
) { (close = css.indexOf('*/')) !== -1
css = css.substring(0, open) + css.substring(close + 2) ) {
} css = css.substring(0, open) + css.substring(close + 2)
// 初始化返回值
let json = {}
while (css.length > 0 && css.indexOf('{') !== -1 && css.indexOf('}') !== -1) {
// 存储第一个左/右花括号的下标
const lbracket = css.indexOf('{')
const rbracket = css.indexOf('}')
// 第一步将声明转换为Object
// `font: 'Times New Roman' 1em; color: #ff0000; margin-top: 1em;`
// ==>
// `{"font": "'Times New Roman' 1em", "color": "#ff0000", "margin-top": "1em"}`
// 辅助方法将array转为object
function toObject (array) {
let ret = {}
array.forEach(e => {
const index = e.indexOf(':')
const property = e.substring(0, index).trim()
const value = e.substring(index + 1).trim()
ret[property] = value
})
return ret
} }
// 切割声明块并移除空白符,然后放入数组中 // 初始化返回值
let declarations = css let json = {}
.substring(lbracket + 1, rbracket)
.split(';')
.map(e => e.trim())
.filter(e => e.length > 0) // 移除所有""空值
// 转为Object对象 while (css.length > 0 && css.indexOf('{') !== -1 && css.indexOf('}') !== -1) {
declarations = toObject(declarations) // 存储第一个左/右花括号的下标
const lbracket = css.indexOf('{')
const rbracket = css.indexOf('}')
// 第二步:选择器处理,每个选择器会与它对应的声明相关联,如: // 第一步将声明转换为Object
// `h1, p#bar {color: red}` // `font: 'Times New Roman' 1em; color: #ff0000; margin-top: 1em;`
// ==> // ==>
// {"h1": {color: red}, "p#bar": {color: red}} // `{"font": "'Times New Roman' 1em", "color": "#ff0000", "margin-top": "1em"}`
let selectors = css // 辅助方法将array转为object
.substring(0, lbracket) function toObject(array) {
// 以,切割,并移除空格:`"h1, p#bar, span.foo"` => ["h1", "p#bar", "span.foo"] let ret = {}
.split(',') array.forEach(e => {
.map(selector => selector.trim()) const index = e.indexOf(':')
const property = e.substring(0, index).trim()
const value = e.substring(index + 1).trim()
ret[property] = value
})
return ret
}
// 迭代赋值 // 切割声明块并移除空白符,然后放入数组中
selectors.forEach(selector => { let declarations = css
// 若不存在,则先初始化 .substring(lbracket + 1, rbracket)
if (!json[selector]) json[selector] = {} .split(';')
// 赋值到JSON .map(e => e.trim())
Object.keys(declarations).forEach(key => { .filter(e => e.length > 0) // 移除所有""空值
json[selector][key] = declarations[key]
})
})
// 继续下个声明块 // 转为Object对象
css = css.slice(rbracket + 1).trim() declarations = toObject(declarations)
}
// 返回JSON形式的结果串 // 第二步:选择器处理,每个选择器会与它对应的声明相关联,如:
return json // `h1, p#bar {color: red}`
// ==>
// {"h1": {color: red}, "p#bar": {color: red}}
let selectors = css
.substring(0, lbracket)
// 以,切割,并移除空格:`"h1, p#bar, span.foo"` => ["h1", "p#bar", "span.foo"]
.split(',')
.map(selector => selector.trim())
// 迭代赋值
selectors.forEach(selector => {
// 若不存在,则先初始化
if (!json[selector]) json[selector] = {}
// 赋值到JSON
Object.keys(declarations).forEach(key => {
json[selector][key] = declarations[key]
})
})
// 继续下个声明块
css = css.slice(rbracket + 1).trim()
}
// 返回JSON形式的结果串
return json
} }
@ -197,9 +198,9 @@ export function isImageIllegal(file) {
} }
export function formatDoc(content) { export function formatDoc(content) {
const doc = prettier.format(content, { const doc = prettier.format(content, {
parser: 'markdown', parser: 'markdown',
plugins: [prettierMarkdown] plugins: [prettierMarkdown]
}) })
return doc return doc
} }

View File

@ -14,7 +14,7 @@
/> />
</el-header> </el-header>
<el-main class="main-body"> <el-main class="main-body">
<el-row :gutter="10" class="main-section"> <el-row class="main-section">
<el-col :span="12"> <el-col :span="12">
<textarea id="editor" type="textarea" placeholder="Your markdown text here." v-model="source"> <textarea id="editor" type="textarea" placeholder="Your markdown text here." v-model="source">
</textarea> </textarea>