From c97c87338eaec9929cff8107a430c6de3b9bab96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=92=83=E7=99=BD?= <18511759309@163.com> Date: Thu, 3 Jun 2021 20:52:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E9=94=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 5 +- src/App.vue | 58 ++++------- src/assets/js/utils.js | 21 ++++ src/assets/style/{ => font}/iconfont.ttf | Bin 4276 -> 4436 bytes src/assets/style/iconfont.less | 6 +- src/assets/style/variable.less | 2 + src/components/content/md-preview.vue | 42 ++++++++ src/components/content/md-textarea.vue | 98 +++++++++++++++++++ src/components/{ => footer}/md-footer.vue | 12 ++- src/components/{ => footer}/upload-files.vue | 6 +- src/components/{ => header}/md-header.vue | 67 +++---------- src/components/header/tool-button.vue | 84 ++++++++++++++++ src/components/md-preview.vue | 26 ----- src/components/tool-button.vue | 27 ----- src/main.js | 12 ++- src/store/index.js | 82 ++++++++++++++++ webpack.config.js | 2 +- 17 files changed, 396 insertions(+), 154 deletions(-) create mode 100644 src/assets/js/utils.js rename src/assets/style/{ => font}/iconfont.ttf (70%) create mode 100644 src/components/content/md-preview.vue create mode 100644 src/components/content/md-textarea.vue rename src/components/{ => footer}/md-footer.vue (62%) rename src/components/{ => footer}/upload-files.vue (74%) rename src/components/{ => header}/md-header.vue (66%) create mode 100644 src/components/header/tool-button.vue delete mode 100644 src/components/md-preview.vue delete mode 100644 src/components/tool-button.vue create mode 100644 src/store/index.js diff --git a/package.json b/package.json index f52d470..72fedbd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "scripts": { "dev": "webpack serve --mode=development", - "build": "webpack" + "build": "webpack --mode=production" }, "devDependencies": { "css-loader": "^5.2.6", @@ -17,6 +17,7 @@ }, "dependencies": { "marked": "^2.0.6", - "vue": "^2.6.12" + "vue": "^2.6.12", + "vuex": "^3.6.2" } } diff --git a/src/App.vue b/src/App.vue index b492281..5edf81a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,40 +1,26 @@ @@ -46,15 +32,9 @@ export default { border-radius: 4px; padding: 10px 16px; box-sizing: border-box; - textarea { - display: block; - width: 100%; - padding: 10px 0; - box-sizing: border-box; - color: #303030; - resize: none; - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", - "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; + transition: border 0.3s; + &.active { + border: 1px solid var(--md-editor-theme-color-active); } } diff --git a/src/assets/js/utils.js b/src/assets/js/utils.js new file mode 100644 index 0000000..987ef1b --- /dev/null +++ b/src/assets/js/utils.js @@ -0,0 +1,21 @@ +export function getSelectionInfo(selectorId) { + const selector = document.getElementById(selectorId); + // const selection = window.getSelection(); + const { selectionStart = 0, selectionEnd = 0 } = selector; + if (selectionStart === selectionEnd) return ""; + return { + selectionStart, + selectionEnd + }; +} + +export function formatText(text, selectionInfo, startStr = "", endStr = "") { + if (!selectionInfo) return text + startStr + endStr; + return ( + text.slice(0, selectionInfo.selectionStart) + + startStr + + text.slice(selectionInfo.selectionStart, selectionInfo.selectionEnd) + + endStr + + text.slice(selectionInfo.selectionEnd) + ); +} diff --git a/src/assets/style/iconfont.ttf b/src/assets/style/font/iconfont.ttf similarity index 70% rename from src/assets/style/iconfont.ttf rename to src/assets/style/font/iconfont.ttf index c38c2b749614c2a4ea8c5806f3f2b1553ae6172d..366bbc963725015ecf438f02a9a00de1462d263d 100644 GIT binary patch delta 639 zcmZutJ!n%=6h7y^*Sw_pX&Mc&O?jkELxxlk(ijjiIJg!Eag+Me)+Caj7n(pSNFh^^ zM5+%VV+Xe^N*s$w2cd)Dpo6GTmphojAQhY%zZ(Y^-+kXb=X~eyO_^Ap1b?wc=n)@QE%BCigD=*!p0qkne%Mknn$VmArJ;!}No$K)4c*mK_V z&8I?lV&YuxXp&KywTZU^JB{)q(rF((^AuE!G-O!DWI`t86`7MaWJ`{||G+3)%)@Ljrx>QI+)z5gQW2nhm$kj`=aw&x6K~kWtlz1=lqpKvNpEf;grStx#s*_FvSZ yeip2;&Qt7SgWc@mY4);@{Ty)Cf_I|9db3rsYW1d7wM*5)dd<~n+9j)sQGWp3Lyijo delta 460 zcmZurJuE{}6#mYASKHUu7ft+CiQkH)36mI#Fc~T_SpB^CtE8{3sHByML_!RH^H?kl zoiKo@sb(hZ_r_0iG(Kz; z=JX)XM>+SKMk+zo*y6g6^O~4pj<#3yea!-Th8LQN_*8Q3^)Uc=i@9NU4p?H3^uBg`vh@!@m9~n4;^2350 z-Q0TuiA5gp!OM!v8W5$@wt+kmwr#zOvL@o{e;3eD04J|j*;By5UhJB^6FQY_=D)&6 z1D>3}fMy9f<7crO_jEu{qDx#V#mbPBvQ@4E*^HcYWf%02Qtlx^3P~y;2RX?_D!EA` S59wCU+pjv3(}@Wq27Cj7VO;e9 diff --git a/src/assets/style/iconfont.less b/src/assets/style/iconfont.less index d293a53..18804d5 100644 --- a/src/assets/style/iconfont.less +++ b/src/assets/style/iconfont.less @@ -1,6 +1,6 @@ @font-face { font-family: "iconfont"; /* Project id */ - src: url('iconfont.ttf?t=1622541171105') format('truetype'); + src: url('./font/iconfont.ttf?t=1622632202276') format('truetype'); } .iconfont { @@ -51,6 +51,10 @@ content: "\eaef"; } +.icon-quxiaoquanping_o:before { + content: "\eb98"; +} + .icon-tupian:before { content: "\e607"; } diff --git a/src/assets/style/variable.less b/src/assets/style/variable.less index 7e73aae..a57d93a 100644 --- a/src/assets/style/variable.less +++ b/src/assets/style/variable.less @@ -1,4 +1,6 @@ :root { --md-editor-theme-color: #dbdbdb; --md-editor-theme-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 new file mode 100644 index 0000000..52f6c9a --- /dev/null +++ b/src/components/content/md-preview.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/components/content/md-textarea.vue b/src/components/content/md-textarea.vue new file mode 100644 index 0000000..6c8a941 --- /dev/null +++ b/src/components/content/md-textarea.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/components/md-footer.vue b/src/components/footer/md-footer.vue similarity index 62% rename from src/components/md-footer.vue rename to src/components/footer/md-footer.vue index 0978a52..2c84329 100644 --- a/src/components/md-footer.vue +++ b/src/components/footer/md-footer.vue @@ -1,15 +1,19 @@ @@ -22,6 +26,10 @@ export default { padding-top: 10px; box-sizing: border-box; font-size: 14px; - color: #666; + color: var(--md-editor-text-color); + transition: border-top 0.3s; + &.active { + border-top: 1px solid var(--md-editor-theme-color-active); + } } diff --git a/src/components/upload-files.vue b/src/components/footer/upload-files.vue similarity index 74% rename from src/components/upload-files.vue rename to src/components/footer/upload-files.vue index 4016d63..416a060 100644 --- a/src/components/upload-files.vue +++ b/src/components/footer/upload-files.vue @@ -1,6 +1,6 @@ @@ -19,12 +19,12 @@ export default { cursor: pointer; .icon { font-size: 20px; - color: #666; + color: var(--md-editor-text-color); cursor: pointer; display: inline-block; vertical-align: bottom; &:hover { - color: #000; + color: var(--md-editor-text-color-active); } } } diff --git a/src/components/md-header.vue b/src/components/header/md-header.vue similarity index 66% rename from src/components/md-header.vue rename to src/components/header/md-header.vue index b7332f3..cc5b61d 100644 --- a/src/components/md-header.vue +++ b/src/components/header/md-header.vue @@ -1,15 +1,15 @@ @@ -83,7 +42,11 @@ export default { justify-content: space-between; align-items: center; height: 32px; + transition: border-bottom 0.3s; border-bottom: 1px solid var(--md-editor-theme-color); + &.active { + border-bottom: 1px solid var(--md-editor-theme-color-active); + } .header_tabs { display: flex; justify-content: space-between; @@ -91,7 +54,7 @@ export default { padding-bottom: 10px; box-sizing: border-box; .tab_item { - color: #666; + color: var(--md-editor-text-color); cursor: pointer; position: relative; padding: 0 6px; @@ -110,14 +73,14 @@ export default { } &:hover { - color: #000; + color: var(--md-editor-text-color-active); &::after { width: 100%; - background: #666; + background: var(--md-editor-theme-color); } } &.active { - color: #000; + color: var(--md-editor-text-color-active); font-weight: 700; &::after { width: 100%; diff --git a/src/components/header/tool-button.vue b/src/components/header/tool-button.vue new file mode 100644 index 0000000..5d026f4 --- /dev/null +++ b/src/components/header/tool-button.vue @@ -0,0 +1,84 @@ + + + diff --git a/src/components/md-preview.vue b/src/components/md-preview.vue deleted file mode 100644 index f3354e6..0000000 --- a/src/components/md-preview.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/src/components/tool-button.vue b/src/components/tool-button.vue deleted file mode 100644 index e60cd26..0000000 --- a/src/components/tool-button.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/src/main.js b/src/main.js index c209aa1..3f56a6c 100644 --- a/src/main.js +++ b/src/main.js @@ -1,12 +1,22 @@ import Vue from "vue"; import App from "./App"; +import store from "./store"; import "@/assets/style/global.less"; +function initStyle(val) { + document.documentElement.style.setProperty( + "--md-editor-theme-color-active", + val + ); +} + function MdEditor(obj) { - const { el, onChange } = obj; + const { el, onChange, themeActive } = obj; if (!el || !document.querySelector(el)) throw new Error("请指定容器"); + initStyle(themeActive); new Vue({ + store, render: h => h(App, { on: { diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..7ed726a --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,82 @@ +import Vue from "vue"; +import Vuex from "vuex"; + +Vue.use(Vuex); + +export default new Vuex.Store({ + state: { + fullScreen: false, + isFocus: false, + showPreview: false, + toolButtonList: [ + { + name: "bold", + icon: "bold", + format: "**" + }, + { + name: "italic", + icon: "italic" + }, + { + name: "quote", + icon: "baojiaquotation" + }, + { + name: "code", + icon: "code" + }, + { + name: "link", + icon: "lianjie" + }, + { + name: "ul", + icon: "unorderedList" + }, + { + name: "ol", + icon: "youxuliebiao" + }, + { + name: "task", + icon: "renwu" + }, + { + name: "table", + icon: "biaoge" + }, + { + name: "fullScreen", + icon: "fullScreen" + } + ], + ulNum: 1, + text: "4564564564657567\n3456456456456", + selectionInfo: "", + html: "" + }, + mutations: { + setFullScreen(state, val) { + state.fullScreen = val; + }, + setShowPreview(state, val) { + state.showPreview = val; + }, + setFocus(state, val) { + state.isFocus = val; + }, + setText(state, val) { + state.text = val; + }, + setSelectionInfo(state, val) { + state.selectionInfo = val; + }, + setHtml(state, val) { + state.html = val; + }, + setUlNum(state, val) { + state.ulNum = val; + } + } +}); diff --git a/webpack.config.js b/webpack.config.js index a121d8a..0b68260 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -28,7 +28,7 @@ module.exports = { }, { - test: /\.ttf$/, + test: /\.(ttf|woff|png)$/, loader: "url-loader" } ] -- GitLab