diff --git a/package.json b/package.json index f52d4701182f8cf7fb0070856b5891a8b180880b..72fedbd6dd685dc0c3f34a29f64623717203d720 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 b492281b096f76d3141beb9408bc9ce5ace87a0d..5edf81ae505434dbd84fcb015f148939090b7ac2 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 0000000000000000000000000000000000000000..987ef1b75da3fffe6338c649eab090ca9dad001f --- /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 Binary files a/src/assets/style/iconfont.ttf and b/src/assets/style/font/iconfont.ttf differ diff --git a/src/assets/style/iconfont.less b/src/assets/style/iconfont.less index d293a5330bd3b1be85d11b3a295322155896986f..18804d5472445a8e8151a764345ab828dc7abc95 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 7e73aae9aeb6b3b8376d208ec03f0aa49baa0480..a57d93a55c82055111f295f1a12696c32a2e0323 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 0000000000000000000000000000000000000000..52f6c9a3024c1a8073124c545c7f65b0b03d18ab --- /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 0000000000000000000000000000000000000000..6c8a941444f1d12e5ba67301322f9f64f682d929 --- /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 0978a5291dacdb45888ae7ffffab05c3a7d00238..2c84329ab894bb68facf2d72d9ff42453408608c 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 4016d6371c3be5e1ed6a559c6d84486e3b67b9d7..416a060d73e57df545796c2f43c4d868f979c807 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 b7332f31c5691587d63e6be6e1580ce637b84099..cc5b61dd68ed0d9abbe577b193da7fa48a033199 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 0000000000000000000000000000000000000000..5d026f45a8558f83c6a41b7f04981d732349c712 --- /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 f3354e6f48f713dd7c57ee5c36ef1bc42006b31a..0000000000000000000000000000000000000000 --- 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 e60cd26dd930bc429cf6b085672aa628f2d67930..0000000000000000000000000000000000000000 --- a/src/components/tool-button.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/src/main.js b/src/main.js index c209aa17d63e37ed83193f6656dc32afc1186dd5..3f56a6c1f280463d38f31b9b54173e4263e45aa1 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 0000000000000000000000000000000000000000..7ed726acbfa7dd437af1c7a8d9d9e163b2e777f6 --- /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 a121d8ae7b30f32697c6bf5c38a298bdedc6f261..0b682605b9865cba18a1fbfc13b0714ec2a06714 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -28,7 +28,7 @@ module.exports = { }, { - test: /\.ttf$/, + test: /\.(ttf|woff|png)$/, loader: "url-loader" } ]