├── .babelrc ├── .editorconfig ├── .gitignore ├── CNAME ├── LICENSE ├── README.md ├── dist ├── yimo-vue-editor.js └── yimo-vue-editor.js.map ├── example ├── html │ ├── index.html │ └── lang.html └── vue │ ├── App.vue │ └── main.js ├── index.html ├── mock-server ├── api │ └── upload.js └── index.js ├── package.json ├── src ├── Editor.vue ├── assets │ ├── css │ │ └── wangEditor.css │ ├── fonts │ │ ├── icomoon.eot │ │ ├── icomoon.svg │ │ ├── icomoon.ttf │ │ └── icomoon.woff │ └── js │ │ └── wangEditor.js └── index.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-3" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log 4 | yarn-error.log 5 | 6 | # Editor directories and files 7 | .idea 8 | *.suo 9 | *.ntvs* 10 | *.njsproj 11 | *.sln 12 | package-lock.json -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | vue-editor.yimo.link -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 yimogit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # yimo-vue-editor 2 | 3 | Demo address: https://vue-editor.yimo.link/example/html/index.html 4 | 5 | > Vue-editor component based on wangeditor2.5.11 wrapper 6 | > wangEditor docs:https://www.kancloud.cn/wangfupeng/wangeditor2/113961 7 | 8 | ## Used in vue projects 9 | 10 | `npm install yimo-vue-editor --save` 11 | 12 | [![](https://img.shields.io/npm/v/yimo-vue-editor.svg)](https://www.npmjs.com/package/yimo-vue-editor) 13 | 14 | ``` 15 | 18 | 19 | import YimoVueEditor from 'yimo-vue-editor' 20 | export default { 21 | components: { 22 | YimoVueEditor 23 | } 24 | } 25 | ``` 26 | 27 | ## Global introduction and configuration 28 | 29 | ``` js 30 | import YimoVueEditor from 'yimo-vue-editor' 31 | 32 | Vue.use(YimoVueEditor, { 33 | name: 'v-editor-app',//Custom name 34 | config: { 35 | uploadImgUrl:'/api/upload', // upload api 36 | printLog: false, // disabled console.log 37 | useLang: 'en' // lang config 38 | },//wagnEditor config 39 | uploadHandler: (type, resTxt) => {//Upload processing hook 40 | if (type === 'success') { 41 | var res = JSON.parse(resTxt)//Do not process the default look at the return value bit image path 42 | if (res.status !== 1) { 43 | return null 44 | } 45 | return res.data 46 | } else if (type === 'error') { 47 | //todo toast 48 | } else if (type === 'timeout') { 49 | //todo toast 50 | } 51 | return 'upload failed__' 52 | } 53 | }) 54 | ``` 55 | 56 | ## Parameter 57 | 58 | - value 59 | v-model Binding editor value 60 | - config 61 | wangEditor2.0 config ,[wangEditor docs](https://www.kancloud.cn/wangfupeng/wangeditor2/113975) 62 | - uploadHandler 63 | The processing of the return value after the image is uploaded, successfully returns the url to be inserted, fails to return an error prompt or prompts in the hook, etc. 64 | ```js 65 | var uploadHandler = (type, resTxt) => { 66 | if (type === 'success') { 67 | var res = JSON.parse(resTxt) 68 | if (res.status !== 1) { 69 | return null 70 | } 71 | return res.data.fileUrl 72 | } else if (type === 'error') { 73 | //todo toast 74 | } else if (type === 'timeout') { 75 | //todo toast 76 | } 77 | return 'upload failed__' 78 | } 79 | ``` 80 | 81 | ## Modification 82 | 83 | - delete Map menu code 84 | - hide Emoticon menu 85 | - fix Upload multiple image insertion order issues (replace after tag placement) 86 | - add Link open state setting 87 | - add Hook after uploading 88 | - add upload append filename no null 89 | - add fullscreen scroll bar 90 | 91 | ## Points to pay attention to 92 | 93 | - ie9 upload image, upload using form+iframe, can't cross domain, and the return type needs to be text/html 94 | - The log is printed as a global parameter, subject to the last setting 95 | -------------------------------------------------------------------------------- /example/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | yimo-vue-editor的使用 7 | 8 | 9 | 10 | 11 |
12 |
13 |

实例切换:{{caseType}}

14 | 15 |
16 |
17 |

单个编辑器:v-editor

18 | 19 |

全局配置的编辑器:v-editor-app

20 | 21 |
预览:
22 | 23 |
24 |
25 |
26 |

编辑器{{index+1}}:

27 |
28 | 29 |
30 |
预览编辑器{{index+1}}:
31 | 32 |
33 |
34 |
35 | 36 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /example/html/lang.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | yimo-vue-editor的使用 7 | 8 | 9 | 10 | 11 |
12 |
13 |

多语言配置

14 |
15 |
16 |

单个编辑器:v-editor

17 | 18 |

全局配置的编辑器:v-editor-app

19 | 20 |
预览:
21 | 22 |
23 |
24 | 25 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /example/vue/App.vue: -------------------------------------------------------------------------------- 1 | 57 | 58 | 91 | 92 | 101 | -------------------------------------------------------------------------------- /example/vue/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import VEditor from '../../src/index.js' 4 | 5 | Vue.use(VEditor, { 6 | name: 'v-editor-app', 7 | config: {}, 8 | uploadHandler: (type, resTxt) => { 9 | if (type === 'success') { 10 | var res = JSON.parse(resTxt) 11 | if (res.status !== 1) { 12 | return null 13 | } 14 | return res.data.fileUrl 15 | } else if (type === 'error') { 16 | //todo toast 17 | } else if (type === 'timeout') { 18 | //todo toast 19 | } 20 | return '上传失败__' 21 | } 22 | }) 23 | new Vue({ 24 | el: '#app', 25 | render: h => h(App) 26 | }) 27 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | yimo-vue-editor 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /mock-server/api/upload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 登录 3 | * 4 | * @url /upload 5 | * POST 6 | */ 7 | module.exports = function(req) { 8 | if (req.query.isIe9==='true') { 9 | req.res.set('Content-Type', 'text/html') 10 | } 11 | return { 12 | status: 1, 13 | data: { 14 | fileName: '@integer(0).jpg', 15 | filePath: '@image(200x200)', 16 | fileUrl: '@image(200x200)' 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /mock-server/index.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var express = require('express') 3 | var mockjs = require('express-mockjs') 4 | var app = express() 5 | 6 | // 自定义路径 '/api' 7 | var config = { 8 | port: 3000 9 | } 10 | app.use('/api', mockjs(path.join(__dirname, 'api'))) 11 | 12 | // 获取port参数 13 | var args = process.argv 14 | for (let i = 0; i < args.length; i++) { 15 | if (args[i] === '--port' && i < args.length - 1 && args[i + 1] > 0) { 16 | config.port = args[i + 1] 17 | break 18 | } 19 | } 20 | 21 | console.log('mock-server[mockjs-lite]:http://localhost:' + config.port) 22 | // console.log('mockjs-lite定义:http://mockjs-lite.js.org/docs/examples.html') 23 | app.listen(config.port) 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yimo-vue-editor", 3 | "description": "基于 wangeditor2.5.11 封装的 vue-editor 富文本编辑器组件", 4 | "version": "1.1.7", 5 | "author": "易墨 ", 6 | "license": "MIT", 7 | "private": false, 8 | "keywords": [ 9 | "vue", 10 | "wangeditor" 11 | ], 12 | "scripts": { 13 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot --port 1122 ", 14 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules", 15 | "mock": "node mock-server/index.js --port 2233" 16 | }, 17 | "main": "dist/yimo-vue-editor.js", 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/yimogit/yimo-vue-editor" 21 | }, 22 | "dependencies": { 23 | "jquery": "^3.3.1", 24 | "vue": "^2.5.11" 25 | }, 26 | "browserslist": [ 27 | "> 1%", 28 | "last 2 versions", 29 | "not ie <= 8" 30 | ], 31 | "devDependencies": { 32 | "babel-core": "^6.26.0", 33 | "babel-loader": "^7.1.2", 34 | "babel-preset-env": "^1.6.0", 35 | "babel-preset-stage-3": "^6.24.1", 36 | "cross-env": "^5.0.5", 37 | "css-loader": "^0.28.7", 38 | "express-mockjs": "^0.4.9", 39 | "file-loader": "^1.1.4", 40 | "object-assign": "^4.1.1", 41 | "shelljs": "^0.8.2", 42 | "url-loader": "^1.1.2", 43 | "vue-loader": "^13.0.5", 44 | "vue-template-compiler": "^2.4.4", 45 | "webpack": "^3.6.0", 46 | "webpack-dev-server": "^2.9.1" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Editor.vue: -------------------------------------------------------------------------------- 1 | 4 | 226 | 227 | 244 | -------------------------------------------------------------------------------- /src/assets/css/wangEditor.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* 编辑器边框颜色 */ 3 | /* 菜单颜色、上边框颜色 */ 4 | /* 菜单选中状态的颜色 */ 5 | /* input focus 时的颜色 */ 6 | /* 按钮颜色 */ 7 | /* tab selected 状态下的颜色 */ 8 | .wangEditor-container { 9 | position: relative; 10 | background-color: #fff; 11 | border: 1px solid #ccc; 12 | z-index: 1; 13 | width: 100%; 14 | } 15 | .wangEditor-container a:focus, 16 | .wangEditor-container button:focus { 17 | outline: none; 18 | } 19 | .wangEditor-container, 20 | .wangEditor-container * { 21 | margin: 0; 22 | padding: 0; 23 | box-sizing: border-box; 24 | line-height: 1; 25 | } 26 | .wangEditor-container img { 27 | border: none; 28 | } 29 | .wangEditor-container .clearfix:after { 30 | content: ''; 31 | display: table; 32 | clear: both; 33 | } 34 | .wangEditor-container .clearfix { 35 | *zoom: 1; 36 | } 37 | .wangEditor-container textarea { 38 | border: none; 39 | } 40 | .wangEditor-container textarea:focus { 41 | outline: none; 42 | } 43 | .wangEditor-container .height-tip { 44 | position: absolute; 45 | width: 3px; 46 | background-color: #ccc; 47 | left: 0; 48 | transition: top 0.2s; 49 | } 50 | .wangEditor-container .txt-toolbar { 51 | position: absolute; 52 | background-color: #fff; 53 | padding: 3px 5px; 54 | border-top: 2px solid #666; 55 | box-shadow: 1px 3px 3px #999; 56 | border-left: 1px solid #ccc; 57 | border-bottom: 1px solid #999; 58 | border-right: 1px solid #999; 59 | } 60 | .wangEditor-container .txt-toolbar .tip-triangle { 61 | display: block; 62 | position: absolute; 63 | width: 0; 64 | height: 0; 65 | border: 5px solid; 66 | border-color: transparent transparent #666 transparent; 67 | top: -12px; 68 | left: 50%; 69 | margin-left: -5px; 70 | } 71 | .wangEditor-container .txt-toolbar a { 72 | color: #666; 73 | display: inline-block; 74 | margin: 0 3px; 75 | padding: 5px; 76 | text-decoration: none; 77 | border-radius: 3px; 78 | } 79 | .wangEditor-container .txt-toolbar a:hover { 80 | background-color: #f1f1f1; 81 | } 82 | .wangEditor-container .img-drag-point { 83 | display: block; 84 | position: absolute; 85 | width: 12px; 86 | height: 12px; 87 | border-radius: 50%; 88 | cursor: se-resize; 89 | background-color: #666; 90 | margin-left: -6px; 91 | margin-top: -6px; 92 | box-shadow: 1px 1px 5px #999; 93 | } 94 | .wangEditor-container .wangEditor-upload-progress { 95 | position: absolute; 96 | height: 1px; 97 | background: #1e88e5; 98 | width: 0; 99 | display: none; 100 | -webkit-transition: width 0.5s; 101 | -o-transition: width 0.5s; 102 | transition: width 0.5s; 103 | } 104 | .wangEditor-fullscreen { 105 | position: fixed; 106 | top: 0; 107 | bottom: 0; 108 | left: 0; 109 | right: 0; 110 | } 111 | .wangEditor-container .code-textarea { 112 | resize: none; 113 | width: 100%; 114 | font-size: 14px; 115 | line-height: 1.5; 116 | font-family: 'Verdana'; 117 | color: #333; 118 | padding: 0 15px 0 15px; 119 | } 120 | .wangEditor-menu-container { 121 | width: 100%; 122 | border-bottom: 1px solid #f1f1f1; 123 | background-color: #fff; 124 | } 125 | .wangEditor-menu-container a { 126 | text-decoration: none; 127 | } 128 | .wangEditor-menu-container .menu-group { 129 | float: left; 130 | padding: 0 8px; 131 | border-right: 1px solid #f1f1f1; 132 | } 133 | .wangEditor-menu-container .menu-item { 134 | float: left; 135 | position: relative; 136 | text-align: center; 137 | height: 31px; 138 | width: 35px; 139 | } 140 | .wangEditor-menu-container .menu-item:hover { 141 | background-color: #f1f1f1; 142 | } 143 | .wangEditor-menu-container .menu-item a { 144 | display: block; 145 | text-align: center; 146 | color: #666; 147 | width: 100%; 148 | padding: 8px 0; 149 | font-size: 0.9em; 150 | } 151 | .wangEditor-menu-container .menu-item .selected { 152 | color: #1e88e5; 153 | } 154 | .wangEditor-menu-container .menu-item .active { 155 | background-color: #f1f1f1; 156 | } 157 | .wangEditor-menu-container .menu-item .disable { 158 | opacity: 0.5; 159 | filter: alpha(opacity=50); 160 | } 161 | .wangEditor-menu-container .menu-tip { 162 | display: block; 163 | position: absolute; 164 | z-index: 20; 165 | width: 60px; 166 | text-align: center; 167 | background-color: #666; 168 | color: #fff; 169 | padding: 7px 0; 170 | font-size: 12px; 171 | top: 100%; 172 | left: 50%; 173 | margin-left: -30px; 174 | border-radius: 2px; 175 | box-shadow: 1px 1px 5px #999; 176 | display: none; 177 | /*// 小三角 178 | .tip-triangle { 179 | display: block; 180 | position: absolute; 181 | width: 0; 182 | height: 0; 183 | border:5px solid; 184 | border-color: transparent transparent @fore-color transparent; 185 | top: -10px; 186 | left: 50%; 187 | margin-left: -5px; 188 | }*/ 189 | } 190 | .wangEditor-menu-container .menu-tip-40 { 191 | width: 40px; 192 | margin-left: -20px; 193 | } 194 | .wangEditor-menu-container .menu-tip-50 { 195 | width: 50px; 196 | margin-left: -25px; 197 | } 198 | .wangEditor-menu-shadow { 199 | /*border-bottom-width: 0;*/ 200 | border-bottom: 1px solid #f1f1f1; 201 | box-shadow: 0 1px 3px #999; 202 | } 203 | .wangEditor-container .wangEditor-txt { 204 | width: 100%; 205 | text-align: left; 206 | padding: 15px; 207 | padding-top: 0; 208 | margin-top: 5px; 209 | overflow-y: auto; 210 | } 211 | .wangEditor-container .wangEditor-txt p, 212 | .wangEditor-container .wangEditor-txt h1, 213 | .wangEditor-container .wangEditor-txt h2, 214 | .wangEditor-container .wangEditor-txt h3, 215 | .wangEditor-container .wangEditor-txt h4, 216 | .wangEditor-container .wangEditor-txt h5 { 217 | margin: 10px 0; 218 | line-height: 1.8; 219 | } 220 | .wangEditor-container .wangEditor-txt p *, 221 | .wangEditor-container .wangEditor-txt h1 *, 222 | .wangEditor-container .wangEditor-txt h2 *, 223 | .wangEditor-container .wangEditor-txt h3 *, 224 | .wangEditor-container .wangEditor-txt h4 *, 225 | .wangEditor-container .wangEditor-txt h5 * { 226 | line-height: 1.8; 227 | } 228 | .wangEditor-container .wangEditor-txt ul, 229 | .wangEditor-container .wangEditor-txt ol { 230 | padding-left: 20px; 231 | } 232 | .wangEditor-container .wangEditor-txt img { 233 | cursor: pointer; 234 | } 235 | .wangEditor-container .wangEditor-txt img.clicked { 236 | box-shadow: 1px 1px 10px #999; 237 | } 238 | .wangEditor-container .wangEditor-txt table.clicked { 239 | box-shadow: 1px 1px 10px #999; 240 | } 241 | .wangEditor-container .wangEditor-txt pre code { 242 | line-height: 1.5; 243 | } 244 | .wangEditor-container .wangEditor-txt:focus { 245 | outline: none; 246 | } 247 | .wangEditor-container .wangEditor-txt blockquote { 248 | display: block; 249 | border-left: 8px solid #d0e5f2; 250 | padding: 5px 10px; 251 | margin: 10px 0; 252 | line-height: 1.4; 253 | font-size: 100%; 254 | background-color: #f1f1f1; 255 | } 256 | .wangEditor-container .wangEditor-txt table { 257 | border: none; 258 | border-collapse: collapse; 259 | } 260 | .wangEditor-container .wangEditor-txt table td, 261 | .wangEditor-container .wangEditor-txt table th { 262 | border: 1px solid #999; 263 | padding: 3px 5px; 264 | min-width: 50px; 265 | height: 20px; 266 | } 267 | .wangEditor-container .wangEditor-txt pre { 268 | border: 1px solid #ccc; 269 | background-color: #f8f8f8; 270 | padding: 10px; 271 | margin: 5px 0px; 272 | font-size: 0.8em; 273 | border-radius: 3px; 274 | } 275 | .wangEditor-drop-list { 276 | display: none; 277 | position: absolute; 278 | background-color: #fff; 279 | overflow: hidden; 280 | z-index: 10; 281 | transition: height 0.7s; 282 | border-top: 1px solid #f1f1f1; 283 | box-shadow: 1px 3px 3px #999; 284 | border-left: 1px solid #ccc; 285 | border-bottom: 1px solid #999; 286 | border-right: 1px solid #999; 287 | } 288 | .wangEditor-drop-list a { 289 | text-decoration: none; 290 | display: block; 291 | color: #666; 292 | padding: 3px 5px; 293 | } 294 | .wangEditor-drop-list a:hover { 295 | background-color: #f1f1f1; 296 | } 297 | .wangEditor-drop-panel, 298 | .txt-toolbar { 299 | display: none; 300 | position: absolute; 301 | padding: 10px; 302 | font-size: 14px; 303 | /*border: 1px solid #cccccc;*/ 304 | background-color: #fff; 305 | z-index: 10; 306 | border-top: 2px solid #666; 307 | box-shadow: 1px 3px 3px #999; 308 | border-left: 1px solid #ccc; 309 | border-bottom: 1px solid #999; 310 | border-right: 1px solid #999; 311 | } 312 | .wangEditor-drop-panel .tip-triangle, 313 | .txt-toolbar .tip-triangle { 314 | display: block; 315 | position: absolute; 316 | width: 0; 317 | height: 0; 318 | border: 5px solid; 319 | border-color: transparent transparent #666 transparent; 320 | top: -12px; 321 | left: 50%; 322 | margin-left: -5px; 323 | } 324 | .wangEditor-drop-panel a, 325 | .txt-toolbar a { 326 | text-decoration: none; 327 | } 328 | .wangEditor-drop-panel input[type='text'], 329 | .txt-toolbar input[type='text'] { 330 | border: none; 331 | border-bottom: 1px solid #ccc; 332 | font-size: 14px; 333 | height: 20px; 334 | color: #333; 335 | padding: 3px 0; 336 | } 337 | .wangEditor-drop-panel input[type='text']:focus, 338 | .txt-toolbar input[type='text']:focus { 339 | outline: none; 340 | border-bottom: 2px solid #1e88e5; 341 | } 342 | .wangEditor-drop-panel input[type='text'].block, 343 | .txt-toolbar input[type='text'].block { 344 | display: block; 345 | width: 100%; 346 | } 347 | .wangEditor-drop-panel textarea, 348 | .txt-toolbar textarea { 349 | border: 1px solid #ccc; 350 | } 351 | .wangEditor-drop-panel textarea:focus, 352 | .txt-toolbar textarea:focus { 353 | outline: none; 354 | border-color: #1e88e5; 355 | } 356 | .wangEditor-drop-panel button, 357 | .txt-toolbar button { 358 | font-size: 14px; 359 | color: #1e88e5; 360 | border: none; 361 | padding: 10px; 362 | background-color: #fff; 363 | cursor: pointer; 364 | border-radius: 3px; 365 | } 366 | .wangEditor-drop-panel button:hover, 367 | .txt-toolbar button:hover { 368 | background-color: #f1f1f1; 369 | } 370 | .wangEditor-drop-panel button:focus, 371 | .txt-toolbar button:focus { 372 | outline: none; 373 | } 374 | .wangEditor-drop-panel button.right, 375 | .txt-toolbar button.right { 376 | float: right; 377 | margin-left: 10px; 378 | } 379 | .wangEditor-drop-panel button.gray, 380 | .txt-toolbar button.gray { 381 | color: #999; 382 | } 383 | .wangEditor-drop-panel button.link, 384 | .txt-toolbar button.link { 385 | padding: 5px 10px; 386 | } 387 | .wangEditor-drop-panel button.link:hover, 388 | .txt-toolbar button.link:hover { 389 | background-color: #fff; 390 | text-decoration: underline; 391 | } 392 | .wangEditor-drop-panel .color-item, 393 | .txt-toolbar .color-item { 394 | display: block; 395 | float: left; 396 | width: 25px; 397 | height: 25px; 398 | text-align: center; 399 | padding: 2px; 400 | border-radius: 2px; 401 | text-decoration: underline; 402 | } 403 | .wangEditor-drop-panel .color-item:hover, 404 | .txt-toolbar .color-item:hover { 405 | background-color: #f1f1f1; 406 | } 407 | .wangEditor-drop-panel .list-menu-item, 408 | .txt-toolbar .list-menu-item { 409 | display: block; 410 | float: left; 411 | color: #333; 412 | padding: 5px 5px; 413 | border-radius: 2px; 414 | } 415 | .wangEditor-drop-panel .list-menu-item:hover, 416 | .txt-toolbar .list-menu-item:hover { 417 | background-color: #f1f1f1; 418 | } 419 | .wangEditor-drop-panel table.choose-table, 420 | .txt-toolbar table.choose-table { 421 | border: none; 422 | border-collapse: collapse; 423 | } 424 | .wangEditor-drop-panel table.choose-table td, 425 | .txt-toolbar table.choose-table td { 426 | border: 1px solid #ccc; 427 | width: 16px; 428 | height: 12px; 429 | } 430 | .wangEditor-drop-panel table.choose-table td.active, 431 | .txt-toolbar table.choose-table td.active { 432 | background-color: #ccc; 433 | opacity: 0.5; 434 | filter: alpha(opacity=50); 435 | } 436 | .wangEditor-drop-panel .panel-tab .tab-container, 437 | .txt-toolbar .panel-tab .tab-container { 438 | margin-bottom: 5px; 439 | } 440 | .wangEditor-drop-panel .panel-tab .tab-container a, 441 | .txt-toolbar .panel-tab .tab-container a { 442 | display: inline-block; 443 | color: #999; 444 | text-align: center; 445 | margin: 0 5px; 446 | padding: 5px 5px; 447 | } 448 | .wangEditor-drop-panel .panel-tab .tab-container a.selected, 449 | .txt-toolbar .panel-tab .tab-container a.selected { 450 | color: #1e88e5; 451 | border-bottom: 2px solid #1e88e5; 452 | } 453 | .wangEditor-drop-panel .panel-tab .content-container .content, 454 | .txt-toolbar .panel-tab .content-container .content { 455 | display: none; 456 | } 457 | .wangEditor-drop-panel .panel-tab .content-container .content a, 458 | .txt-toolbar .panel-tab .content-container .content a { 459 | display: inline-block; 460 | margin: 2px; 461 | padding: 2px; 462 | border-radius: 2px; 463 | } 464 | .wangEditor-drop-panel .panel-tab .content-container .content a:hover, 465 | .txt-toolbar .panel-tab .content-container .content a:hover { 466 | background-color: #f1f1f1; 467 | } 468 | .wangEditor-drop-panel .panel-tab .content-container .selected, 469 | .txt-toolbar .panel-tab .content-container .selected { 470 | display: block; 471 | } 472 | .wangEditor-drop-panel .panel-tab .emotion-content-container, 473 | .txt-toolbar .panel-tab .emotion-content-container { 474 | height: 200px; 475 | overflow-y: auto; 476 | } 477 | .wangEditor-drop-panel .upload-icon-container, 478 | .txt-toolbar .upload-icon-container { 479 | color: #ccc; 480 | text-align: center; 481 | margin: 20px 20px 15px 20px !important; 482 | padding: 5px !important; 483 | font-size: 65px; 484 | cursor: pointer; 485 | border: 2px dotted #f1f1f1; 486 | display: block !important; 487 | } 488 | .wangEditor-drop-panel .upload-icon-container:hover, 489 | .txt-toolbar .upload-icon-container:hover { 490 | color: #666; 491 | border-color: #ccc; 492 | } 493 | .wangEditor-modal { 494 | position: absolute; 495 | top: 50%; 496 | left: 50%; 497 | background-color: #fff; 498 | border-top: 1px solid #f1f1f1; 499 | box-shadow: 1px 3px 3px #999; 500 | border-top: 1px solid #ccc; 501 | border-left: 1px solid #ccc; 502 | border-bottom: 1px solid #999; 503 | border-right: 1px solid #999; 504 | } 505 | .wangEditor-modal .wangEditor-modal-close { 506 | position: absolute; 507 | top: 0; 508 | right: 0; 509 | margin-top: -25px; 510 | margin-right: -25px; 511 | font-size: 1.5em; 512 | color: #666; 513 | cursor: pointer; 514 | } 515 | @font-face { 516 | font-family: 'icomoon'; 517 | src: url('../fonts/icomoon.eot'); 518 | src: url('../fonts/icomoon.eot') format('embedded-opentype'), 519 | url('../fonts/icomoon.ttf') format('truetype'), 520 | url('../fonts/icomoon.woff') format('woff'), 521 | url('../fonts/icomoon.svg') format('svg'); 522 | font-weight: normal; 523 | font-style: normal; 524 | } 525 | [class^='wangeditor-menu-img-'], 526 | [class*=' wangeditor-menu-img-'] { 527 | font-family: 'icomoon'; 528 | speak: none; 529 | font-style: normal; 530 | font-weight: normal; 531 | font-variant: normal; 532 | text-transform: none; 533 | line-height: 1; 534 | /* Better Font Rendering =========== */ 535 | -webkit-font-smoothing: antialiased; 536 | -moz-osx-font-smoothing: grayscale; 537 | } 538 | .wangeditor-menu-img-link:before { 539 | content: '\e800'; 540 | } 541 | .wangeditor-menu-img-unlink:before { 542 | content: '\e801'; 543 | } 544 | .wangeditor-menu-img-code:before { 545 | content: '\e802'; 546 | } 547 | .wangeditor-menu-img-cancel:before { 548 | content: '\e803'; 549 | } 550 | .wangeditor-menu-img-terminal:before { 551 | content: '\e804'; 552 | } 553 | .wangeditor-menu-img-angle-down:before { 554 | content: '\e805'; 555 | } 556 | .wangeditor-menu-img-font:before { 557 | content: '\e806'; 558 | } 559 | .wangeditor-menu-img-bold:before { 560 | content: '\e807'; 561 | } 562 | .wangeditor-menu-img-italic:before { 563 | content: '\e808'; 564 | } 565 | .wangeditor-menu-img-header:before { 566 | content: '\e809'; 567 | } 568 | .wangeditor-menu-img-align-left:before { 569 | content: '\e80a'; 570 | } 571 | .wangeditor-menu-img-align-center:before { 572 | content: '\e80b'; 573 | } 574 | .wangeditor-menu-img-align-right:before { 575 | content: '\e80c'; 576 | } 577 | .wangeditor-menu-img-list-bullet:before { 578 | content: '\e80d'; 579 | } 580 | .wangeditor-menu-img-indent-left:before { 581 | content: '\e80e'; 582 | } 583 | .wangeditor-menu-img-indent-right:before { 584 | content: '\e80f'; 585 | } 586 | .wangeditor-menu-img-list-numbered:before { 587 | content: '\e810'; 588 | } 589 | .wangeditor-menu-img-underline:before { 590 | content: '\e811'; 591 | } 592 | .wangeditor-menu-img-table:before { 593 | content: '\e812'; 594 | } 595 | .wangeditor-menu-img-eraser:before { 596 | content: '\e813'; 597 | } 598 | .wangeditor-menu-img-text-height:before { 599 | content: '\e814'; 600 | } 601 | .wangeditor-menu-img-brush:before { 602 | content: '\e815'; 603 | } 604 | .wangeditor-menu-img-pencil:before { 605 | content: '\e816'; 606 | } 607 | .wangeditor-menu-img-minus:before { 608 | content: '\e817'; 609 | } 610 | .wangeditor-menu-img-picture:before { 611 | content: '\e818'; 612 | } 613 | .wangeditor-menu-img-file-image:before { 614 | content: '\e819'; 615 | } 616 | .wangeditor-menu-img-cw:before { 617 | content: '\e81a'; 618 | } 619 | .wangeditor-menu-img-ccw:before { 620 | content: '\e81b'; 621 | } 622 | .wangeditor-menu-img-music:before { 623 | content: '\e911'; 624 | } 625 | .wangeditor-menu-img-play:before { 626 | content: '\e912'; 627 | } 628 | .wangeditor-menu-img-location:before { 629 | content: '\e947'; 630 | } 631 | .wangeditor-menu-img-happy:before { 632 | content: '\e9df'; 633 | } 634 | .wangeditor-menu-img-sigma:before { 635 | content: '\ea67'; 636 | } 637 | .wangeditor-menu-img-enlarge2:before { 638 | content: '\e98b'; 639 | } 640 | .wangeditor-menu-img-shrink2:before { 641 | content: '\e98c'; 642 | } 643 | .wangeditor-menu-img-newspaper:before { 644 | content: '\e904'; 645 | } 646 | .wangeditor-menu-img-camera:before { 647 | content: '\e90f'; 648 | } 649 | .wangeditor-menu-img-video-camera:before { 650 | content: '\e914'; 651 | } 652 | .wangeditor-menu-img-file-zip:before { 653 | content: '\e92b'; 654 | } 655 | .wangeditor-menu-img-stack:before { 656 | content: '\e92e'; 657 | } 658 | .wangeditor-menu-img-credit-card:before { 659 | content: '\e93f'; 660 | } 661 | .wangeditor-menu-img-address-book:before { 662 | content: '\e944'; 663 | } 664 | .wangeditor-menu-img-envelop:before { 665 | content: '\e945'; 666 | } 667 | .wangeditor-menu-img-drawer:before { 668 | content: '\e95c'; 669 | } 670 | .wangeditor-menu-img-download:before { 671 | content: '\e960'; 672 | } 673 | .wangeditor-menu-img-upload:before { 674 | content: '\e961'; 675 | } 676 | .wangeditor-menu-img-lock:before { 677 | content: '\e98f'; 678 | } 679 | .wangeditor-menu-img-unlocked:before { 680 | content: '\e990'; 681 | } 682 | .wangeditor-menu-img-wrench:before { 683 | content: '\e991'; 684 | } 685 | .wangeditor-menu-img-eye:before { 686 | content: '\e9ce'; 687 | } 688 | .wangeditor-menu-img-eye-blocked:before { 689 | content: '\e9d1'; 690 | } 691 | .wangeditor-menu-img-command:before { 692 | content: '\ea4e'; 693 | } 694 | .wangeditor-menu-img-font2:before { 695 | content: '\ea5c'; 696 | } 697 | .wangeditor-menu-img-libreoffice:before { 698 | content: '\eade'; 699 | } 700 | .wangeditor-menu-img-quotes-left:before { 701 | content: '\e977'; 702 | } 703 | .wangeditor-menu-img-strikethrough:before { 704 | content: '\ea65'; 705 | } 706 | .wangeditor-menu-img-desktop:before { 707 | content: '\f108'; 708 | } 709 | .wangeditor-menu-img-tablet:before { 710 | content: '\f10a'; 711 | } 712 | .wangeditor-menu-img-search-plus:before { 713 | content: '\f00e'; 714 | } 715 | .wangeditor-menu-img-search-minus:before { 716 | content: '\f010'; 717 | } 718 | .wangeditor-menu-img-trash-o:before { 719 | content: '\f014'; 720 | } 721 | .wangeditor-menu-img-align-justify:before { 722 | content: '\f039'; 723 | } 724 | .wangeditor-menu-img-arrows-v:before { 725 | content: '\f07d'; 726 | } 727 | .wangeditor-menu-img-sigma2:before { 728 | content: '\ea68'; 729 | } 730 | .wangeditor-menu-img-omega:before { 731 | content: '\e900'; 732 | } 733 | .wangeditor-menu-img-cancel-circle:before { 734 | content: '\e901'; 735 | } 736 | .hljs { 737 | display: block; 738 | overflow-x: auto; 739 | padding: 0.5em; 740 | color: #333; 741 | background: #f8f8f8; 742 | -webkit-text-size-adjust: none; 743 | } 744 | .hljs-comment, 745 | .diff .hljs-header { 746 | color: #998; 747 | font-style: italic; 748 | } 749 | .hljs-keyword, 750 | .css .rule .hljs-keyword, 751 | .hljs-winutils, 752 | .nginx .hljs-title, 753 | .hljs-subst, 754 | .hljs-request, 755 | .hljs-status { 756 | color: #333; 757 | font-weight: bold; 758 | } 759 | .hljs-number, 760 | .hljs-hexcolor, 761 | .ruby .hljs-constant { 762 | color: #008080; 763 | } 764 | .hljs-string, 765 | .hljs-tag .hljs-value, 766 | .hljs-doctag, 767 | .tex .hljs-formula { 768 | color: #d14; 769 | } 770 | .hljs-title, 771 | .hljs-id, 772 | .scss .hljs-preprocessor { 773 | color: #900; 774 | font-weight: bold; 775 | } 776 | .hljs-list .hljs-keyword, 777 | .hljs-subst { 778 | font-weight: normal; 779 | } 780 | .hljs-class .hljs-title, 781 | .hljs-type, 782 | .vhdl .hljs-literal, 783 | .tex .hljs-command { 784 | color: #458; 785 | font-weight: bold; 786 | } 787 | .hljs-tag, 788 | .hljs-tag .hljs-title, 789 | .hljs-rule .hljs-property, 790 | .django .hljs-tag .hljs-keyword { 791 | color: #000080; 792 | font-weight: normal; 793 | } 794 | .hljs-attribute, 795 | .hljs-variable, 796 | .lisp .hljs-body, 797 | .hljs-name { 798 | color: #008080; 799 | } 800 | .hljs-regexp { 801 | color: #009926; 802 | } 803 | .hljs-symbol, 804 | .ruby .hljs-symbol .hljs-string, 805 | .lisp .hljs-keyword, 806 | .clojure .hljs-keyword, 807 | .scheme .hljs-keyword, 808 | .tex .hljs-special, 809 | .hljs-prompt { 810 | color: #990073; 811 | } 812 | .hljs-built_in { 813 | color: #0086b3; 814 | } 815 | .hljs-preprocessor, 816 | .hljs-pragma, 817 | .hljs-pi, 818 | .hljs-doctype, 819 | .hljs-shebang, 820 | .hljs-cdata { 821 | color: #999; 822 | font-weight: bold; 823 | } 824 | .hljs-deletion { 825 | background: #fdd; 826 | } 827 | .hljs-addition { 828 | background: #dfd; 829 | } 830 | .diff .hljs-change { 831 | background: #0086b3; 832 | } 833 | .hljs-chunk { 834 | color: #aaa; 835 | } 836 | -------------------------------------------------------------------------------- /src/assets/fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yimogit/yimo-vue-editor/b243fc99a6f548b4f0268190c9b4467a673c0906/src/assets/fonts/icomoon.eot -------------------------------------------------------------------------------- /src/assets/fonts/icomoon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/assets/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yimogit/yimo-vue-editor/b243fc99a6f548b4f0268190c9b4467a673c0906/src/assets/fonts/icomoon.ttf -------------------------------------------------------------------------------- /src/assets/fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yimogit/yimo-vue-editor/b243fc99a6f548b4f0268190c9b4467a673c0906/src/assets/fonts/icomoon.woff -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import YimoVueEditor from './Editor' 2 | import E from './assets/js/wangEditor.js' 3 | 4 | const instance = YimoVueEditor 5 | 6 | const install = (Vue, globalOptions) => { 7 | let compName = instance.name 8 | if (globalOptions) { 9 | compName = globalOptions.name || compName 10 | instance.props.globalOptions.default = () => globalOptions 11 | } 12 | Vue.component(compName, instance) 13 | } 14 | instance.install = install 15 | export default instance 16 | export { E, instance, install } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: 6 | process.env.NODE_ENV === 'production' ? './src/index.js' : './example/vue/main.js', 7 | output: { 8 | path: path.resolve(__dirname, './dist'), 9 | publicPath: '/dist/', 10 | filename: process.env.NODE_ENV === 'production'?'yimo-vue-editor.js':'build.js', 11 | library: 'YimoVueEditor', // 指定的就是你使用require时的模块名 12 | libraryTarget: 'umd', // 指定输出格式 13 | umdNamedDefine: true // 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.css$/, 19 | use: ['vue-style-loader', 'css-loader'] 20 | }, 21 | { 22 | test: /\.vue$/, 23 | loader: 'vue-loader', 24 | options: { 25 | loaders: {} 26 | // other vue-loader options go here 27 | } 28 | }, 29 | { 30 | test: /\.js$/, 31 | loader: 'babel-loader', 32 | exclude: /node_modules/ 33 | }, 34 | { 35 | test: /\.(png|jpg|gif)$/, 36 | loader: 'file-loader', 37 | options: { 38 | name: '[name].[ext]?[hash]' 39 | } 40 | }, 41 | { 42 | test: /\.(svg|woff2?|eot|ttf|otf)(\?.*)?$/, 43 | loader: 'url-loader', 44 | options: { 45 | name: 'fonts/[name].[ext]?[hash]' 46 | } 47 | } 48 | ] 49 | }, 50 | resolve: { 51 | alias: { 52 | vue$: 'vue/dist/vue.esm.js' 53 | }, 54 | extensions: ['*', '.js', '.vue', '.json'] 55 | }, 56 | devServer: { 57 | proxy: { 58 | '/mockserver': { 59 | target: 'http://192.168.1.32:2233', 60 | changeOrigin: true, 61 | pathRewrite: { 62 | '^/mockserver': '' 63 | } 64 | } 65 | }, 66 | host: 'localhost', 67 | historyApiFallback: true, 68 | noInfo: true, 69 | overlay: true 70 | }, 71 | performance: { 72 | hints: false 73 | }, 74 | devtool: '#eval-source-map' 75 | } 76 | 77 | if (process.env.NODE_ENV === 'production') { 78 | module.exports.devtool = '#source-map' 79 | // http://vue-loader.vuejs.org/en/workflow/production.html 80 | module.exports.plugins = (module.exports.plugins || []).concat([ 81 | new webpack.DefinePlugin({ 82 | 'process.env': { 83 | NODE_ENV: '"' + process.env.NODE_ENV + '"' 84 | } 85 | }), 86 | new webpack.optimize.UglifyJsPlugin({ 87 | sourceMap: true, 88 | compress: { 89 | warnings: false 90 | } 91 | }), 92 | new webpack.LoaderOptionsPlugin({ 93 | minimize: true 94 | }) 95 | ]) 96 | } 97 | --------------------------------------------------------------------------------