From e504e13cbdeab56c934700a03c0618e892847e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=92=83=E7=99=BD?= <18511759309@163.com> Date: Fri, 4 Jun 2021 14:14:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=88=9D=E5=A7=8B=E5=8C=96=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/App.vue | 12 +- src/assets/js/utils.js | 40 ++ src/assets/style/global.less | 1 + src/assets/style/markdown.less | 486 +++++++++++++++++++++++++ src/assets/style/variable.less | 4 +- src/components/content/md-preview.vue | 4 +- src/components/footer/md-footer.vue | 11 +- src/components/footer/upload-files.vue | 47 ++- src/components/header/md-header.vue | 8 +- src/main.js | 18 +- src/store/index.js | 9 +- 12 files changed, 604 insertions(+), 38 deletions(-) create mode 100644 src/assets/style/markdown.less diff --git a/package.json b/package.json index 72fedbd..f83d79d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "scripts": { - "dev": "webpack serve --mode=development", + "start": "webpack serve --mode=development", "build": "webpack --mode=production" }, "devDependencies": { diff --git a/src/App.vue b/src/App.vue index 5edf81a..77dd908 100644 --- a/src/App.vue +++ b/src/App.vue @@ -3,7 +3,10 @@ - + @@ -28,13 +32,13 @@ export default { .md_container { width: 1000px; margin: 200px auto; - border: 1px solid var(--md-editor-theme-color); + border: 1px solid var(--md-editor-border-color); border-radius: 4px; padding: 10px 16px; box-sizing: border-box; transition: border 0.3s; &.active { - border: 1px solid var(--md-editor-theme-color-active); + border: 1px solid var(--md-editor-border-color-active); } } diff --git a/src/assets/js/utils.js b/src/assets/js/utils.js index 987ef1b..5210d2a 100644 --- a/src/assets/js/utils.js +++ b/src/assets/js/utils.js @@ -1,3 +1,4 @@ +// 获取选中文本信息 export function getSelectionInfo(selectorId) { const selector = document.getElementById(selectorId); // const selection = window.getSelection(); @@ -9,6 +10,7 @@ export function getSelectionInfo(selectorId) { }; } +// 工具栏格式化文本 export function formatText(text, selectionInfo, startStr = "", endStr = "") { if (!selectionInfo) return text + startStr + endStr; return ( @@ -19,3 +21,41 @@ export function formatText(text, selectionInfo, startStr = "", endStr = "") { text.slice(selectionInfo.selectionEnd) ); } + +// 初始化样式 +export function initStyle({ + borderColor, + borderColorActive, + textColor, + textColorActive +}) { + if (borderColor) { + document.documentElement.style.setProperty( + "--md-editor-border-color", + borderColor + ); + } + if (borderColorActive) { + document.documentElement.style.setProperty( + "--md-editor-border-color-active", + borderColorActive + ); + } + if (textColor) { + document.documentElement.style.setProperty( + "--md-editor-text-color", + textColor + ); + } + if (textColorActive) { + document.documentElement.style.setProperty( + "--md-editor-text-color-active", + textColorActive + ); + } +} + +// +export function isNotEmpty(val) { + return val !== null && val !== undefined; +} diff --git a/src/assets/style/global.less b/src/assets/style/global.less index b8e4449..5f2b23a 100644 --- a/src/assets/style/global.less +++ b/src/assets/style/global.less @@ -1,5 +1,6 @@ @import "./variable.less"; @import "./iconfont.less"; +@import './markdown.less'; * { padding: 0; diff --git a/src/assets/style/markdown.less b/src/assets/style/markdown.less new file mode 100644 index 0000000..9cf97af --- /dev/null +++ b/src/assets/style/markdown.less @@ -0,0 +1,486 @@ +.htmledit_views address, +.htmledit_views cite, +.htmledit_views dfn, +.htmledit_views em, +.htmledit_views i, +.htmledit_views span[lang], +.htmledit_views var { + font-style: italic; +} +.htmledit_views { + font-family: -apple-system, SF UI Text, Arial, PingFang SC, Hiragino Sans GB, + Microsoft YaHei, WenQuanYi Micro Hei, sans-serif, SimHei, SimSun; +} +.cke_editable { + margin: 24px; + word-wrap: break-word; +} +.htmledit_views img.right { + border: 1px solid #ccc; + float: right; + margin-left: 15px; + padding: 5px; +} +.htmledit_views img.left { + border: 1px solid #ccc; + float: left; + margin-right: 15px; + padding: 5px; +} +.htmledit_views .marker { + background-color: #ff0; +} +.htmledit_views figure { + text-align: center; + margin: 0 24px; + display: inline-block; +} +.htmledit_views figure > figcaption { + text-align: center; + margin: 8px; + color: #999; + font-size: 14px; + display: block; +} +.htmledit_views a > img { + padding: 1px; + margin: 1px; + border: none; + outline: #0782c1 solid 1px; +} +.htmledit_views .code-featured { + border: 5px solid red; +} +.htmledit_views .math-featured { + padding: 20px; + box-shadow: 0 0 2px rgba(200, 0, 0, 1); + background-color: rgba(255, 0, 0, 0.05); + margin: 10px; +} +.htmledit_views .image-clean { + border: 0; + background: 0 0; + padding: 0; +} +.htmledit_views .image-clean > figcaption { + font-size: 0.9em; + text-align: right; +} +.htmledit_views .image-grayscale { + background-color: #fff; + color: #666; +} +.htmledit_views .image-grayscale img, +.htmledit_views img.image-grayscale { + filter: grayscale(100%); +} +.htmledit_views .embed-240p { + max-width: 426px; + max-height: 240px; + margin: 0 auto; +} +.htmledit_views .embed-360p { + max-width: 640px; + max-height: 360px; + margin: 0 auto; +} +.htmledit_views .embed-480p { + max-width: 854px; + max-height: 480px; + margin: 0 auto; +} +.htmledit_views .embed-720p { + max-width: 1280px; + max-height: 720px; + margin: 0 auto; +} +.htmledit_views .embed-1080p { + max-width: 1920px; + max-height: 1080px; + margin: 0 auto; +} +.htmledit_views p { + font-size: 18px; + color: #4d4d4d; + font-weight: 400; + line-height: 26px !important; + margin: 0 0 16px; + overflow-x: auto; + overflow-y: hidden; +} +p[align="center"] { + text-align: center; +} +.htmledit_views img { + max-width: 100%; + height: auto; +} +.htmledit_views strong, +.htmledit_views strong span { + font-weight: 700; +} +.htmledit_views * { + box-sizing: border-box; +} +.htmledit_views h1, +.htmledit_views h2, +.htmledit_views h3, +.htmledit_views h4, +.htmledit_views h5, +.htmledit_views h6 { + color: #4f4f4f; + margin: 8px 0 16px; + font-weight: 700; +} +.htmledit_views ol, +.htmledit_views ul { + margin: 0 0 24px; + padding: 0; + font-size: 16px; +} +.htmledit_views ul ol { + margin: 0 0 24px 32px; +} +.htmledit_views ul li { + list-style-type: disc; + margin: 8px 0 0 32px; +} +.htmledit_views ol li { + list-style-type: decimal; + margin-left: 40px; + margin-top: 8px; +} +.htmledit_views h1 { + font-size: 28px; + line-height: 36px; +} +.htmledit_views h2 { + font-size: 24px; + line-height: 32px; +} +.htmledit_views h3 { + font-size: 22px; + line-height: 30px; +} +.htmledit_views h4 { + font-size: 20px; + line-height: 28px; +} +.htmledit_views h5 { + font-size: 18px; + line-height: 26px; +} +.htmledit_views h6 { + font-size: 16px; + line-height: 24px; +} +.htmledit_views blockquote { + display: block; + padding: 16px 16px 0; + margin: 0 0 24px; + border-left: 8px solid #dddfe4; + background: #eef0f4; + overflow: auto; + overflow-scrolling: touch; + word-wrap: normal; + word-break: normal; +} +.htmledit_views blockquote ol, +.htmledit_views blockquote ul { + margin-bottom: 16px; + padding: 0; + font-size: 16px; + line-height: 24px; +} +.htmledit_views blockquote ol li, +.htmledit_views blockquote ul li { + margin-bottom: 0; +} +.htmledit_views blockquote p { + font-size: 16px; + line-height: 26px; + font-weight: 400; + margin-bottom: 16px; + color: #4f4f4f; +} +.htmledit_views hr { + margin: 24px 0; + border: none; + border-bottom: solid #ccc 1px; +} +.htmledit_views table tr { + border: 0; + border-top: 1px solid #ddd; + background-color: #fff; +} +.htmledit_views table { + border-collapse: collapse; + display: table; + width: 100%; + text-align: left; + margin-bottom: 24px; + margin-left: auto; + margin-right: auto; +} +.htmledit_views tbody { + border: 0; +} +.htmledit_views table tr:nth-child(2n) { + background-color: #f7f7f7; +} +.htmledit_views table tr td, +.htmledit_views table tr th { + border: 1px solid #ddd; + font-size: 14px; + color: #4f4f4f; + line-height: 22px; + padding: 8px; + text-align: left; +} +.htmledit_views table tr td p, +.htmledit_views table tr th p { + font-size: 14px; + color: #4f4f4f; + margin: 0; + padding: 0; + text-align: left; + line-height: 22px; +} +.htmledit_views table tr th p { + font-weight: 700; +} +.htmledit_views table tr td code, +.htmledit_views table tr th code { + white-space: normal; + word-break: break-word; +} +.htmledit_views table tr th { + font-weight: 700; + background-color: #eff3f5; +} +.htmledit_views dl { + margin: 24px; +} +.htmledit_views dl dt { + margin: 8px; + font-weight: 700; +} +.htmledit_views dl dt dd { + margin: 8px; +} +.htmledit_views abbr[data-original-title], +.htmledit_views abbr[title] { + cursor: help; + border-bottom: 1px dotted #999; +} +.htmledit_views .initialism { + font-size: 90%; + text-transform: uppercase; +} +.htmledit_views pre { + white-space: pre-wrap; + word-wrap: break-word; + margin: 0 0 24px; + overflow-x: auto; + padding: 8px; +} +.marker { + background-color: #ff0; +} +htmledit_views img.mathcode { + margin: 0 8px; +} +.htmledit_views kbd, +.htmledit_views pre, +.htmledit_views samp { + font-family: Consolas, Inconsolata, Courier, monospace; + font-size: 14px; + line-height: 22px; + color: #000; +} +.htmledit_views code ol li div.hljs-ln-code, +.htmledit_views code ol li div.hljs-ln-numbers, +.htmledit_views pre code, +.htmledit_views pre code div, +.htmledit_views pre code span { + font-family: "Source Code Pro", "DejaVu Sans Mono", "Ubuntu Mono", + "Anonymous Pro", "Droid Sans Mono", Menlo, Monaco, Consolas, Inconsolata, + Courier, monospace, "PingFang SC", "Microsoft YaHei", sans-serif; +} +.htmledit_views code { + border-radius: 4px; +} +.htmledit_views a { + color: #4ea1db; + text-decoration: none; +} +.htmledit_views a:focus, +.htmledit_views a:hover { + color: #ca0c16; +} +.htmledit_views a:visited { + color: #6795b5; +} +.htmledit_views .hot-keyword:visited { + color: #3399ea; +} +.htmledit_views .footnote { + vertical-align: top; + position: relative; + top: -4px; + font-size: 12px; +} +.htmledit_views .flow-chart, +.htmledit_views .sequence-diagram { + text-align: center; + margin-bottom: 24px; + font-size: 14px !important; +} +.htmledit_views .flow-chart [fill="#000"], +.htmledit_views .flow-chart [fill="#000000"], +.htmledit_views .flow-chart [fill="black"], +.htmledit_views .sequence-diagram [fill="#000"], +.htmledit_views .sequence-diagram [fill="#000000"], +.htmledit_views .sequence-diagram [fill="black"] { + fill: #4f4f4f; +} +.htmledit_views .flow-chart [stroke="#000000"], +.htmledit_views .sequence-diagram [stroke="#000000"] { + stroke: #4f4f4f; +} +.htmledit_views .MathJax_SVG_Display { + text-align: center; + margin: 24px 0; + font-size: 18px; + font-weight: 400; + color: #4f4f4f; + position: relative; + text-indent: 0; + max-width: none; + max-height: none; + min-width: 0; + min-height: 0; + width: 100%; +} +.htmledit_views pre code { + display: block; + line-height: 22px; + overflow-x: auto; + white-space: pre; + word-wrap: normal; + border-radius: 4px; + padding: 8px; + tab-size: 4; +} +.htmledit_views pre code code.hljs { + padding: 0; +} +.htmledit_views pre code:not(.hljs) { + background-color: #f3f4f5; +} +.htmledit_views pre code, +.htmledit_views pre code div, +.htmledit_views pre code span { + font-size: 14px; +} +.htmledit_views .prettyprint, +.htmledit_views pre.prettyprint { + margin: 0 0 24px; + padding: 8px 16px 4px 56px; + background-color: #f6f8fa; + border: none; +} +.htmledit_views .prettyprint .pre-numbering { + position: absolute; + width: 48px; + background-color: #eef0f4; + top: 0; + left: 0; + margin: 0; + padding: 8px 0; + list-style: none; + text-align: right; +} +.htmledit_views .pre-numbering li { + padding: 0 8px; + list-style: none; + margin: 0; +} +.htmledit_views dl dd { + margin: 0 0 8px 40px; +} +.htmledit_views kbd { + padding: 2px 8px; + border: 1px solid rgba(63, 63, 63, 0.25); + box-shadow: 0 1px 0 rgba(63, 63, 63, 0.25); + background-color: #fff; + color: #333; + border-radius: 4px; + display: inline-block; + margin: 0 2px; + white-space: nowrap; +} +.htmledit_views .dp-highlighter { + font-size: 12px; + text-align: left; + margin: 0 0 24px; +} +.htmledit_views code ol { + margin: 0; + overflow: hidden; +} +.htmledit_views code ol li { + list-style-type: none; + margin-left: 0; + margin-top: 0; + height: 22px; +} +.htmledit_views code ol li div.hljs-ln-code { + margin-left: 8px; +} +.htmledit_views code ol li div.hljs-ln-code, +.htmledit_views code ol li div.hljs-ln-numbers { + float: left; + height: 22px; +} +.htmledit_views code ol li div.hljs-ln-numbers { + width: 24px; + border-right: 1px solid #c5c5c5; +} +.htmledit_views code ol li div.hljs-ln-numbers .hljs-ln-line { + word-wrap: normal; +} +.htmledit_views code ol.hundred li div.hljs-ln-numbers { + width: 30px; +} +.htmledit_views code ol.thousand li div.hljs-ln-numbers { + width: 36px; +} +.htmledit_views .csdn-data-video { + width: 200px; +} +.htmledit_views .csdn-data-video img { + margin: 0; + display: block; + width: 200px; + height: 112px; +} +.htmledit_views .csdn-data-video p { + margin-top: 10px; + margin-bottom: 0; + font-size: 14px; +} +.htmledit_views pre[data-from="code-for-outside"] { + overflow: hidden; +} +.htmledit_views pre[data-from="code-for-outside"] code { + overflow-x: auto; + overflow-y: hidden; +} +.htmledit_views pre[data-from="code-for-outside"] code * { + overflow: visible; + overflow-wrap: break-word; +} +.htmledit_views pre[data-from="code-for-outside"] p code { + padding: 0; +} diff --git a/src/assets/style/variable.less b/src/assets/style/variable.less index a57d93a..3b531ed 100644 --- a/src/assets/style/variable.less +++ b/src/assets/style/variable.less @@ -1,6 +1,6 @@ :root { - --md-editor-theme-color: #dbdbdb; - --md-editor-theme-color-active: #409eff; + --md-editor-border-color: #dbdbdb; + --md-editor-border-color-active: #409eff; --md-editor-text-color: #303030; --md-editor-text-color-active: #000; } diff --git a/src/components/content/md-preview.vue b/src/components/content/md-preview.vue index 52f6c9a..63a883c 100644 --- a/src/components/content/md-preview.vue +++ b/src/components/content/md-preview.vue @@ -1,5 +1,5 @@ @@ -32,7 +32,7 @@ export default { }; diff --git a/src/components/footer/upload-files.vue b/src/components/footer/upload-files.vue index 416a060..0d50afe 100644 --- a/src/components/footer/upload-files.vue +++ b/src/components/footer/upload-files.vue @@ -1,16 +1,50 @@ @@ -23,9 +57,12 @@ export default { cursor: pointer; display: inline-block; vertical-align: bottom; - &:hover { - color: var(--md-editor-text-color-active); - } + } + &:hover { + color: var(--md-editor-text-color-active); + } + .md_upload { + display: none; } } diff --git a/src/components/header/md-header.vue b/src/components/header/md-header.vue index cc5b61d..a7e6071 100644 --- a/src/components/header/md-header.vue +++ b/src/components/header/md-header.vue @@ -43,9 +43,9 @@ export default { align-items: center; height: 32px; transition: border-bottom 0.3s; - border-bottom: 1px solid var(--md-editor-theme-color); + border-bottom: 1px solid var(--md-editor-border-color); &.active { - border-bottom: 1px solid var(--md-editor-theme-color-active); + border-bottom: 1px solid var(--md-editor-border-color-active); } .header_tabs { display: flex; @@ -76,7 +76,7 @@ export default { color: var(--md-editor-text-color-active); &::after { width: 100%; - background: var(--md-editor-theme-color); + background: var(--md-editor-border-color); } } &.active { @@ -84,7 +84,7 @@ export default { font-weight: 700; &::after { width: 100%; - background: var(--md-editor-theme-color-active); + background: var(--md-editor-border-color-active); } } & + .tab_item { diff --git a/src/main.js b/src/main.js index 3f56a6c..028e166 100644 --- a/src/main.js +++ b/src/main.js @@ -1,19 +1,15 @@ import Vue from "vue"; import App from "./App"; import store from "./store"; +import { initStyle, isNotEmpty } from "@/assets/js/utils"; import "@/assets/style/global.less"; -function initStyle(val) { - document.documentElement.style.setProperty( - "--md-editor-theme-color-active", - val - ); -} - -function MdEditor(obj) { - const { el, onChange, themeActive } = obj; +function initMdEditor(obj) { + const { el, onChange, canAttachFile, themeOptions } = obj; if (!el || !document.querySelector(el)) throw new Error("请指定容器"); - initStyle(themeActive); + if (isNotEmpty(themeOptions)) initStyle(themeOptions); + if (isNotEmpty(canAttachFile)) + store.commit("setCanAttachFile", canAttachFile); new Vue({ store, @@ -28,4 +24,4 @@ function MdEditor(obj) { }).$mount(el); } -window.MdEditor = MdEditor; +window.MdEditor = initMdEditor; diff --git a/src/store/index.js b/src/store/index.js index 7ed726a..60b39a5 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -52,9 +52,10 @@ export default new Vuex.Store({ } ], ulNum: 1, - text: "4564564564657567\n3456456456456", + text: "# 456456456\n## 4657567\n3456456456456", selectionInfo: "", - html: "" + html: "", + canAttachFile: true }, mutations: { setFullScreen(state, val) { @@ -68,6 +69,7 @@ export default new Vuex.Store({ }, setText(state, val) { state.text = val; + state.selectionInfo = ""; }, setSelectionInfo(state, val) { state.selectionInfo = val; @@ -77,6 +79,9 @@ export default new Vuex.Store({ }, setUlNum(state, val) { state.ulNum = val; + }, + setCanAttachFile(state, val) { + state.canAttachFile = val; } } }); -- GitLab