├── .babelrc ├── .editorconfig ├── .gitignore ├── README.md ├── demo ├── index.html ├── ui1.jpg └── ui2.jpg ├── dist ├── best-editor.css ├── best-editor.js ├── best-editor.min.css └── fonts │ ├── iconfont.eot │ └── iconfont.ttf ├── package.json ├── src ├── assets │ ├── iconfont.css │ ├── iconfont.eot │ ├── iconfont.svg │ ├── iconfont.ttf │ └── iconfont.woff ├── core │ ├── best-editor.js │ ├── dom.js │ ├── handle │ │ ├── image-handle.js │ │ ├── link-handle.js │ │ ├── list-handle.js │ │ ├── paste-handle.js │ │ └── video-handle.js │ ├── handler.js │ ├── request.js │ ├── selection.js │ └── toolbar.js ├── main.js ├── scss │ └── main.scss └── ui │ ├── image-dialog.html │ ├── image-upload.html │ ├── link-dialog.html │ ├── toolbar.html │ └── video-dialog.html └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env"] 3 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = crlf 7 | charset = utf-8 8 | 9 | trim_trailing_whitespace = false 10 | insert_final_newline = false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | 一款简洁实用的web富文本编辑器,拥有着现代化UI风格的界面。比现有的富文本编辑器多了一些特色功能。图片上传,支持本地和链接,且拥有图片上传状态预览框。文章粘贴做了格式优化,并支持图片上传到自己的服务器。 4 | 5 | [![](https://raw.githubusercontent.com/zc9/best-editor/master/demo/ui1.jpg)](https://raw.githubusercontent.com/zc9/best-editor/master/demo/ui1.jpg) 6 | 7 | # 文档 8 | - 说明文档参考 [Wiki](https://github.com/zc9/best-editor/wiki) 9 | 10 | # 下载安装 11 | - 直接下载:[https://github.com/zc9/best-editor/releases](https://github.com/zc9/best-editor/releases) 12 | - `npm`下载:`npm install --save best-editor` 13 | 14 | 15 | # 运行环境 16 | 17 | 目前测试的环境:edge、ie10、chrome。建议运行在基于webkit内核的浏览器上,拥有更好的体验。 18 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | best-editor 9 | 10 | 11 | 25 | 26 | 27 |
28 |
29 | 30 |
31 | 32 | 33 | 46 | 47 | -------------------------------------------------------------------------------- /demo/ui1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zc9/best-editor/a9c2a6c5df297f5691da65e4b71e5a03ba93b809/demo/ui1.jpg -------------------------------------------------------------------------------- /demo/ui2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zc9/best-editor/a9c2a6c5df297f5691da65e4b71e5a03ba93b809/demo/ui2.jpg -------------------------------------------------------------------------------- /dist/best-editor.css: -------------------------------------------------------------------------------- 1 | .best-editor-container { 2 | display: flex; 3 | flex-direction: column; } 4 | .best-editor-container.full-screen { 5 | position: fixed; 6 | z-index: 9999; 7 | top: 0; 8 | left: 0; 9 | right: 0; 10 | bottom: 0; 11 | width: 100% !important; 12 | height: 100% !important; 13 | background-color: #d9d9d9; } 14 | .best-editor-container.full-screen .best-editor { 15 | width: 60%; 16 | margin: 0 auto; 17 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); 18 | margin-top: 35px; 19 | margin-bottom: 20px; } 20 | .best-editor-container .best-editor-toolbar { 21 | background-color: #d9d9d9; 22 | border-bottom: 1px solid #ccc; 23 | user-select: none; 24 | box-sizing: border-box; } 25 | .best-editor-container .best-editor-toolbar ul { 26 | zoom: 1; 27 | list-style: none; 28 | word-break: break-all; } 29 | .best-editor-container .best-editor-toolbar ul li { 30 | list-style: none; 31 | float: left; } 32 | .best-editor-container .best-editor-toolbar ul li a { 33 | height: 39px; 34 | line-height: 39px; 35 | color: #595959; 36 | padding: 0 14px; 37 | display: inline-block; 38 | font-size: 16px; 39 | font-weight: bold; 40 | cursor: pointer; } 41 | .best-editor-container .best-editor-toolbar ul li a:hover { 42 | color: #f2f2f2; 43 | background-color: #595959; } 44 | .best-editor-container .best-editor-toolbar ul:after { 45 | content: "."; 46 | display: block; 47 | height: 0; 48 | clear: both; 49 | visibility: hidden; } 50 | .best-editor-container .best-editor { 51 | flex: 1; 52 | outline: none; 53 | padding: 30px; 54 | box-sizing: border-box; 55 | padding-top: 15px; 56 | overflow-y: auto; 57 | background: #fff; } 58 | .best-editor-container .best-editor p { 59 | margin: 15px 0; 60 | word-break: break-word; } 61 | .best-editor-container .best-editor h1, .best-editor-container .best-editor h2, .best-editor-container .best-editor h3, .best-editor-container .best-editor h4, .best-editor-container .best-editor h5, .best-editor-container .best-editor h6 { 62 | margin: 15px 0; } 63 | .best-editor-container .best-editor a { 64 | text-decoration: none; 65 | color: #3194d0; } 66 | .best-editor-container .best-editor blockquote { 67 | padding: 20px; 68 | background-color: #f2f2f2; 69 | border-left: 6px solid #b3b3b3; 70 | word-break: break-word; 71 | font-size: 16px; 72 | font-weight: 400; 73 | line-height: 30px; 74 | margin: 0 0 20px; } 75 | .best-editor-container .best-editor iframe { 76 | display: block; 77 | margin: 0 auto; } 78 | .best-editor-container .best-editor ul, .best-editor-container .best-editor ol { 79 | list-style-position: inside; 80 | margin: 15px 0; } 81 | .best-editor-container .best-editor .image-box { 82 | text-align: center; 83 | font-size: 0; 84 | margin: 15px 0; } 85 | .best-editor-container .best-editor .image-box > img { 86 | max-width: 100%; 87 | width: auto; 88 | height: auto; 89 | vertical-align: middle; 90 | border: 0; } 91 | .best-editor-container .best-editor .image-box .image-upload { 92 | width: 443px; 93 | padding: 5px 16px 5px 5px; 94 | margin: 0 auto; 95 | border: 1px solid #d9d9d9; 96 | overflow: hidden; 97 | font-size: 14px; 98 | -webkit-box-sizing: border-box; 99 | box-sizing: border-box; } 100 | .best-editor-container .best-editor .image-box .image-upload .preview-image { 101 | display: block; 102 | float: left; 103 | width: 90px; 104 | height: 90px; 105 | object-fit: cover; 106 | margin-right: 20px; } 107 | .best-editor-container .best-editor .image-box .image-upload .status-bar { 108 | display: block; 109 | float: right; 110 | width: 305px; } 111 | .best-editor-container .best-editor .image-box .image-upload .status-bar .upload-error-msg { 112 | color: #f50; } 113 | .best-editor-container .best-editor .image-box .image-upload .status-bar .status-area a { 114 | float: right; 115 | margin-left: 20px; 116 | cursor: pointer; 117 | color: #999; } 118 | .best-editor-container .best-editor .image-box .image-upload .status-bar .status-area .upload-btn-retry { 119 | display: none; } 120 | .best-editor-container .best-editor .image-box .image-upload .status-bar .uploading-icon { 121 | height: 3px; 122 | width: 305px; 123 | min-height: 3px; 124 | display: block; 125 | margin: 25px 0 20px; 126 | background: url(data:image/gif;base64,R0lGODlhMgEDAMQfACV79DaH+avH8bDK9rDJ7ajI8qvI7q3K8a/M92Oc7ih776/K9KrL9KbH8KbK8jV/7i9+7xhw8bjT+ICw8pLF+sHW9a3H8ajH8azJ8LPL9q3L9rPL7zB/8SV89zSH/f///yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTMyIDc5LjE1OTI4NCwgMjAxNi8wNC8xOS0xMzoxMzo0MCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUuNSAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2QTdFQzI3OUUyMUQxMUU2OEVGMUVFRTY0NzY1NUJEMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo2QTdFQzI3QUUyMUQxMUU2OEVGMUVFRTY0NzY1NUJEMyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjZBN0VDMjc3RTIxRDExRTY4RUYxRUVFNjQ3NjU1QkQzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjZBN0VDMjc4RTIxRDExRTY4RUYxRUVFNjQ3NjU1QkQzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEBQMAHwAsAAAAADIBAwAABZ6gJYyjZZ5oqq5s676wKlx0bZOzre987//AoNBXKBYaSKSxmGwsj8nLszmNLptOY66Gu+G2l6+XZKDhGoMBYo3IuN3puDwjr9vv+Lx+j6dr/oCBgoOEhYaHiImKi4FsCIKOj4CRkI6NlpdrlZGcnZ6fnH+OBQSlpqeoqaqrrK2ur7AYsrO0tba3uLm6u7y9vr/AwcAHwsIHxBilBwsNIQAh+QQFAwAfACwGAAAABQACAAAFBqAgikhZhgAh+QQFAwAfACwAAAAAAwADAAAFB+AkfeIgbiEAIfkEBQMAHwAsAAAAACsBAwAABUFg1wHAGCUZYXxs676tIM9wbd94ru987//AoHBILLIEgWTAE4CgNoQgYoowWq/YrHbL7e4gjzD48fSaz+i0ep0OAQAh+QQFAwAfACwEAAAAngADAAAFOuD3AV1pmlEiCWzrinAsz3Rt33iu77ztCiKPcEgETCoLjXLJZPae0Kh0+uR8INhslqNIVKjgsHgMDgEAIfkEBQMAHwAsBAAAAB8AAwAABSbg93ViaXZoqnbRU2xm4Jn059147nXBl5WLR80EKRqPEI7iIYCVQgAh+QQFAwAfACwEAAAAKAADAAAFJGAHAF1pnmiqolGQEYEnz3Rt33eXZBnHQcCgcEgsDjmKwGYTAgAh+QQFAwAfACwBAAAAOQADAAAFJ2DXASQgnmiqrmx7RolkBV5t33iu77zeJZUMZEgsGo/IpBLJgVUIIQAh+QQFAwAfACwGAAAA1QADAAAFR2D3jWRpnmiqjl3rvrDSVKsp3HWukze+/8Bg8EK8CC7CZM3DbDqfj9lit6hqlNisdqtDeLlcjnhMJneitOBhdWivwfC4nBQCACH5BAUDAB8ALAkAAABSAAMAAAUv4CeOZGmeaKqWXeu+sNJIRV2seK6rXu//wMdMQ/xwdiLOEcksKZ/QKAcglByumBAAIfkEBQMAHwAsUwAAABMAAwAABRVgJ45kCUBN5q1s63pBI3F0bd/AI4cAIfkEBQMAHwAsBgAAANMAAwAABUIgIIpfaZ7nCKBs675wLH9dbd949BDa7P/AoPAkKA5NgaNy2fI4n1BoJ7FBMK/YLAoShHC14BlnTC6bAY9qeM2GhQAAIfkEBQMAHwAsHQAAAO0AAwAABUYg8I1kaZ5oqq5sa3ZwLM9RUl2Xq++8m/e+j2Ao+AGPyKTS5Gk6n9DOpLKsWq9YFmfLyXqV3LCYW6N+z6iD+oD+rNXH9yEEACH5BAUDAB8ALBwAAADSAAMAAAU+4CeOZGmeaKqubJt2cCzL0dNkbq7v/Hp5vaBwuPMYj0hkJ1CQEJ/QqHRKVXGu2CwWAngYNtUnZozpHc5nVQgAIfkEBQMAHwAsAAAAAMkAAwAABUXgVgTR13Vfqq5sqwKwK890bd94Pp987wMKiuRy0RlbGUQAdWw6n9AozkOtWq+PhkSqy2wcAQB3TC6bU5y0es0GZLdnWggAIfkEBQMAHwAsAAAAAPIAAwAABW+gJYpEEURfqq5sC6hvK69AXc94ru9877edoHA4jDwMiF+uwWwof4LVYDrIZBCJzvMT2LYC4K53TC7vPOi0Ot0JGCTmz+JAX8RnmoV+Qej3NxQnYxCEEHeHiIk7HIyNjo4ARxl3IxZbGJiYOQycDCEAIfkEBQMAHwAsBAAAACsBAwAABXXgJ1gkKU0R8K1s67bdK890bd94ru955/9AYCQhMTQaNGTrwry4mpfCssmrWq+rwSDD5Z442LAnTC6bq560er3uJCqbwyI3n2m157zeRSBsNn4VEwo7HIZge4mKiziHjo+GQxUfJDQWNAeZBy+anZqMOJ5WnSEAIfkEBQMAHwAsBwAAAN0AAwAABXDgJ35WaUpJ9AEsML6iC8803N51/rZ67//AoHDUKRqPxsjjcxg1ntCodAp9Za6ZQQYlCwRenqF4TC6bz0GPes1edwKHzGtBr9vveDqB8CFs/oAoKjkQhRBoiImKi2Qcjo+QjwAPBhs1GJgYM5maIxghACH5BAUDAB8ALAcAAAAoAQMAAAVQ4CeOpGUaaDVFZOu+cCzPdG3feK67Xe//PsDjg9gZj8hb5pNpbg4blSJJrVqvWJ1ny+12Hw1JdjzemDeu81naIbvf8HiLQ6/b6wqwWM6vmUMAIfkEBQMAHwAsFAAAAB0BAwAABXCgJY5jRn2foqBs674sAAMybKP1l9987//AoFDYKRqPxsjDgBg6f4Vo9PnKWK9XyYkTCFC/4LB4TA56zuj0uRM4SDRlqmZ+cGZQzddmz9emxhCBgoJUg3GHiIkfHIyNjo0ADwQbHxiKTpZCmR8HdQchACH5BAUDAB8ALB0AAAAQAQMAAAVyoCWOljRFgKIq3we8LtzOdG3feK7vfO//wGCwQywai5GEBHMp0JyzglRaE1ittKtAaDNYM+BwpjJhBc47j5rLbrvf8DhPTa/XO0qEvqbpaxA9C3I4GhuGhxsmETocjRyDkJGSk3GOlpccSRIHnHCcnZIhACH5BAUDAB8ALCQAAADvAAMAAAVjoCUKRWFIU/StwOq+cCzPdG3feK7vfL93wKAwqKBIZqWkclnIOBHQDAriq1qv2Kx2W/N4v+DvoyE5uDTotHqt3rg3BDdK4YLY73eufs/v+z8cgYKDgQoPRisHZi4YGDCNji8hACH5BAUDAB8ALCcAAADiAAMAAAVT4CeMgmWe0qR8bOu+sAsAcc3Odq7vfO//wKCvQywaiZFE5TNoNjPQqITy4Aiv2Kx2y+36POCwGAyYVA6fDWvDbm+mH4XVS6/b73gfZ8/v85MVGCEAIfkEBQMAHwAsJwAAAAgBAwAABWGgJYpfaY6o4CSR6b4uUAIyDNNzbe8f7fM+HG9ILBqPyKTy1Wk6n81IQnJYwjCYjFYL23oHjInCSi6bz+i0muxpu9/tzhSxHm7u+PuqhYT4IX1/dYOEhYZEHImKi4kKU2shACH5BAUDAB8ALDkAAADyAAMAAAVaoCWOYzVFQKqmX+u+sNvFdN12OG7vfO//wKBw+MsZj5HAxmITZJ5QqGlGrFqv2Kx2i/V4v2BvJyHJ1BCLz2bNXpsAkLg8zg1C6vi8ft+CPB4QHIKDghFkBDshACH5BAUDAB8ALEIAAADrAAMAAAVSoCWOY5VEX/oBLKCmLfvOdA23dq7vfO//wKBQ2Ckaj8VIovLJOJ/PyqQzrFqv2Kx2y/V4v2BvZznYmM9nKSoFabtf7jZ3Tq/b75w8x6bv+5VMIQAh+QQFAwAfACxLAAAA5wADAAAFQqAljqNEddGnrmzrvnAsz3Rt33iu73vn/75IZkgkViifDm/JbDqf0OjSQ61SO5usVnvkKF4BjnRMLpvPOY56rY6EAAAh+QQFAwAfACxUAAAAeQADAAAFNaAljuRGddGnrmzrAm4sz3Rt3yug71nv/xLHp4MrGo/I5CrADHw20Ki04ggoOEoVZJvteoshACH5BAUDAB8ALAEAAACJAAMAAAU+4Cd+1mieaKqubOu+VizPVtY8EaDv/Pt1QGBmOPQZj8ikishkShiBjrK1qVan2Kz2Y+12JZiHAkIumyGvcwgAIfkEBQMAHwAsAQAAABEBAwAABVegIIpfaZ5oqq5s66Ij+bZWbdvCdWXXE5mAoHBILAZnyKRyyWy+hM6odIaoIqafjHa7HVQlmkAHSy6bz1iCmoBuu1mbuHwelxweChNkz+ej+oAQb4OEZiEAIfkEBQMAHwAsAgAAAJIAAwAABTZgIX5kaZ5oqq5s676wac10bVuZEETw4MfAoJCFGL4yyKRymZEgEhyjdEqtDjfYrHb7UERbjxAAIfkEBQMAHwAsAQAAABIBAwAABUvgJ36FMJ5oqq5s66pFXLx03Vp4ru/VFNnAD2BIDBqPyBZgBBiMnMmoVKWZWjPYrHbbe1hXgXDgSy6bz+i0ccNuu9s9hXpOT0LukBAAIfkEBQMAHwAskQAAACQAAwAABSOgJY5kaUlJBKxf675vJs90nVUJEOxw3waboHBI3OAivmQrBAAh+QQFAwAfACw2AAAAfwADAAAFO6AgCl9pnmiqrukosrBLwjRs3XieC0UhJRGEsEYsooRDo2nAZCqVmah0ShVWJoqndsvt1jbgsHgMvipCACH5BAUDAB8ALDUAAACUAAMAAAU3oPCNZGmeaKqOxeq+cAxbdG3fuDQpcu+Pg+DgRyzGMsikcrmsTB4fj3FKrVpXm6x2y9U6FZBPCAAh+QQFAwAfACwAAAAAJgEDAAAFY6ACKZP0nWiqrmzrpkVcvHRNy/Yqz3nv/yqLcEgsDjOCAADIbOYAUGgg8ChlnNgUArXNAgeIcPcnHnvPvox6zW6vJYgEB00HTqcfyKNqqvv/gB8Eg4GFKBuIiYqLiw8KhpAsIQAh+QQFAwAfACwAAAAAIgEDAAAFdSCkfEppnmh6Bs72vXAszy/zCnSuC3zv/z2dcEgsGo9Io6DAbDqfTckkkqxWO6+AdsvtermPhM0KGxw0GrIMwW673261fE6fIz7wvLsyGdX/Hx4PLw+FhoeIiQ8chQl3cwcHBICURy6VmJQbm5ydnpt8fplqIQAh+QQFAwAfACwZAAAACQEDAAAFdOAnKmRpnmgZBdTxWWIsz3Rc3Hiu63Xv/8CgcEgsGnWOpHKprEwiH4BRBKhar1hRYMvter9dTsAhGWSmMgR6zW67326EfE6vz50dOPAhevj/gIGCfwoPAxt6aAcLLmsLj4mRkmwblZaXmJZOUGsQnp+goB8hACH5BAUDAB8ALDQAAADcAAMAAAVboAKMZGmepEJJgvC9cCzPr0vfeK7vfO//wJ1jSCwahxrDIxL4eJ6eAHRKrT5Wg6B2y+16v16EeEwuiyWEQOfBgXDa77h8Llc8GhKwfs/v+2cbgYKDhIESGw8AIQAh+QQFAwAfACw1AAAA6wADAAAFZ6Aiil9pnugJrGzrvmuUSMJnpXiu73zvm4Jg8LcrEI9IlGPJbDodgsqkFKgGkh+PdsvterWciSSTwZrP54F6gG67dYi4fE5HZCqUzmO/T3L+gIGCg396YhtviYqLjIyIG5CRkpN4CiEAIfkEBQMAHwAsYwAAAM4AAwAABVngB4xkaZ5AFDTb9xVwLM9ubd94ru987//AoBA3KxYRhkfk42k6n9Coh5PQSFyIrHbLHXq/4LB4/EEcuOithBD4cN7wuHz+ViQyLbJ+z+/3N4CBgoMbaw8AIQAh+QQFAwAfACx6AAAAuAADAAAFQyAgjmRpAtFUfWzrvnD8CjQt33iu73zvy4UCreEpGo/IpKej+v0GUKhzSq1ae4gsosDper/gMAfQvJrP6LR6syFsGiEAIfkEBQMAHwAskAAAABcAAwAABRYgII5kWUaJ5K1s67rcJHF0bd829MghACH5BAUDAB8ALDoAAACBAAMAAAU04CeOZGmeaKqubOt+QCzP9BwlEvHufO//H49wSCwSObgMZLkEnphNpxTIqVqv2GvngfuEAAAh+QQFAwAfACwAAAAA+AADAAAFSeD0AV9pnmiqrmzrvnAsz3TNAniu73mUSIKgcEgc2lKUh+fIbDqf0KjNQ61arwEq4Ifoer9SVePDCZvP6LSZw267327FT93KhAAAIfkEBQMAHwAsAAAAABcBAwAABV+gII5kaZZVEn1s675wLM90bd94ru/8B/zAoPAXmUg+jqRyyXT0nqyBdLqoVqdS6wIrTQGg4LB4TC67POi0eo1+GDPmOGFOr9vv9tQqzu/7/zocgoOEhRwAbkdjG3wZIQAh+QQFAwAfACwZAAAA/gADAAAFY+AnjGRpnuiILVQQKV8sz3Rt33iu73zv/0AZYEgsGiOBz6FXCOIWUOhgOohKqVUr1prRBDpJp3hMLpvPH496zW6DPxI0kECv2+/4fH3TAsj/gIGCOhyFhoeIHABhORmOGXIbIQAh+QQFAwAfACw4AAAA3wADAAAFXaAgjmRpnmbBTEr7vXAsz3Rt33iu73z/AcCgcKiYSAQ+3GLAZC6ey+YA+pROoVLN6hEIJL/gsHi885jP6PTDmCHHCPC4fE6vzw8IyuPDcfv/gIEvHISFhodrEn8LIQAh+QQFAwAfACxaAAAAxAADAAAFYaBQjGNjNmSqrqkgTdGnKF9t33iu73zv/8BgEEAsGouRhAQj1GmeGoZ0Sq1ar6/OJxBoer/gsHjnKZvPZohSjCAc3m+MfE6v2+uEFwDCH/v/gIAcg4SFhAoJFT4ZNRuMOCEAIfkEBQMAHwAsegAAALIAAwAABVdgIY5kaZ7F4QSRonxwLM90bd94ru874P9AXyQhYdgaOSSMwWw6n9BoZtX5BHjYrHbLnXm+4PD3QezGDpi0es1uuzEbRgDwgZjv+DyPw+/7+QoJFTEbXSEAIfkEBQMAHwAsZQAAALwAAwAABWvgJ45kaZ5oWhZX415FLM/0vFFBpO587/9AEWBILAIiCYlIw9SUms5nU8qkVklQhnbL7Xq3EkegEyybz2aPes32QCaVz2E+L9Hro/vBTuf3SXcYgoOEhYaDGwgBAGiNjo8jHJKTlBwKCXEfIQAh+QQFAwAfACxqAAAAwgADAAAFdGAjfmQpjiV5pt91XuzZsHQq02uh6/K+n74NpRNRKGrIpHLJbCoB0GhUAZlICs6sFqnpdlleDdjLKJvD5rJXQiEFAtu4fE7z2O/3wINSOXwQdIFIB4SELIV+KYgHGI0Yi46NhWwfVBCCmJlIHJydnRB7FSUhACH5BAUDAB8ALFkAAADZAAMAAAVW4CeOZGmeaKqubOuSxdXMdG3PhxNEb+//J4BwKIwENgKgcslskjRQhnRKrTIQiETHyXV6vuBvJ7FZbDbdtLp7YBwW8Lh8ftgwAoq1vvXg+P9+AAkfBCEAIfkEBQMAHwAsxwAAAGsAAwAABT3gJ45kOTZoqq4CsVFPZM50bd/4B+xyTjLAoHC42GwcAY5vyWyKPJ5A57BYLq7YrHZxcFECCqfYqZxxzpEQACH5BAUDAB8ALOgAAAA+AAMAAAUpYCOOZHkJGdVFX+u+cCzPMGPfOK7tEhXQwKBwQSwajYdkL6AQOp+fRwgAIfkEBQMAHwAsAQAAACUBAwAABUzgJ45kaZ5oqq5s675wLM90/TZ4ruvFRnERmwnRIgptRlhShGgen9AoiiGNMa7YrGarYWgklE+nSi5DCQSzes2uLd7w+GFOBwcUUU4IACH5BAUDAB8ALAUBAAAQAAMAAAUYYCGKTdmMgpRESNtqsOYiVdIdeK7ndRQCACH5BAUDAB8ALBEBAAAOAAMAAAUXYFE0ZHOJBSYlEYJoMOy6a3fceE5UbAgAIfkEBQMAHwAsGwEAAA0AAwAABRZgcTVkU5wS9a1a2yJwRXHfYd+3rCghACH5BAUDAB8ALCQBAAALAAMAAAUWYFE0JLlR3YcgWqsxkvN1R20TVfMpIQAh+QQFAwAfACwGAAAALAEDAAAFOeAnjmRpnmiqrmzrvnAsz3Rt3/BV7MV1NYNgEEcsujQIo3LJbDplDCRiOi08r9isdsvtHr7fzeYSAgA7) 50% no-repeat; } 127 | 128 | .best-editor-dialog { 129 | position: fixed; 130 | top: 0; 131 | left: 0; 132 | right: 0; 133 | bottom: 0; 134 | z-index: 9999999999999; 135 | background-color: rgba(255, 255, 255, 0.7); } 136 | .best-editor-dialog .wrap { 137 | position: absolute; 138 | top: 50%; 139 | left: 50%; 140 | transform: translate(-50%, -50%); 141 | width: 412px; 142 | background-color: #fff; 143 | border-radius: 6px; 144 | -webkit-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); 145 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); 146 | padding: 16px; 147 | box-sizing: border-box; } 148 | .best-editor-dialog .wrap .head .close { 149 | text-align: right; } 150 | .best-editor-dialog .wrap .head .close a { 151 | cursor: pointer; 152 | font-size: 24px; 153 | color: #999; 154 | transition: color .3s ease; } 155 | .best-editor-dialog .wrap .head .close a:hover { 156 | color: #4d4d4d; } 157 | .best-editor-dialog .wrap .head h3 { 158 | font-size: 22px; 159 | padding-bottom: 26px; 160 | text-align: center; } 161 | .best-editor-dialog .wrap .body { 162 | padding: 15px 30px 30px; } 163 | .best-editor-dialog .wrap .body .upload-btn { 164 | position: relative; 165 | height: 42px; 166 | margin-bottom: 20px; 167 | background: #555; 168 | overflow: hidden; 169 | text-align: center; 170 | line-height: 42px; 171 | color: #fff; 172 | font-size: 14px; 173 | cursor: pointer; } 174 | .best-editor-dialog .wrap .body .upload-btn input { 175 | position: absolute; 176 | top: -12000px; 177 | right: 0; 178 | left: 0; } 179 | .best-editor-dialog .wrap .body .input-box { 180 | display: flex; 181 | margin-bottom: 20px; } 182 | .best-editor-dialog .wrap .body .input-box > div { 183 | height: 42px; 184 | border: 1px solid #ccc; 185 | box-sizing: border-box; 186 | line-height: 42px; } 187 | .best-editor-dialog .wrap .body .input-box .icon-box { 188 | text-align: center; 189 | background-color: #eee; 190 | width: 38px; 191 | color: #595959; } 192 | .best-editor-dialog .wrap .body .input-box .input { 193 | border-left: 0; 194 | flex: 1; } 195 | .best-editor-dialog .wrap .body .input-box .input input { 196 | border: 0; 197 | outline: none; 198 | width: 99%; 199 | border-left: 0; 200 | box-sizing: border-box; 201 | padding: 0 10px; 202 | color: #595959; } 203 | .best-editor-dialog .wrap .body .switch-box { 204 | color: #888; 205 | cursor: pointer; 206 | font-size: 14px; 207 | padding-bottom: 10px; 208 | text-align: center; } 209 | .best-editor-dialog .wrap .body .waring-txt { 210 | height: 20px; 211 | line-height: 20px; 212 | color: #bc6351; 213 | font-size: 14px; 214 | margin-bottom: 5px; } 215 | .best-editor-dialog .wrap .body .btn-box { 216 | font-size: 14px; 217 | text-align: right; 218 | height: 30px; 219 | line-height: 20px; 220 | user-select: none; 221 | color: #595959; } 222 | .best-editor-dialog .wrap .body .btn-box > span { 223 | display: inline-block; 224 | transition: color .3s ease; 225 | cursor: pointer; 226 | padding: 4px 12px; 227 | font-size: 14px; 228 | font-weight: 500; } 229 | .best-editor-dialog .wrap .body .btn-box .cancel:hover { 230 | color: #000; } 231 | .best-editor-dialog .wrap .body .btn-box .confirm { 232 | color: #42c02e; 233 | background-color: #fff; 234 | border: 1px solid #42c02e; 235 | border-radius: 15px; 236 | margin-left: 15px; } 237 | 238 | 239 | @font-face {font-family: "iconfont"; 240 | src: url(fonts/iconfont.eot); /* IE9*/ 241 | src: url(fonts/iconfont.eot#iefix) format('embedded-opentype'), 242 | url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'), 243 | url(fonts/iconfont.ttf) format('truetype') 244 | } 245 | 246 | .iconfont { 247 | font-family:"iconfont" !important; 248 | font-style:normal; 249 | -webkit-font-smoothing: antialiased; 250 | -moz-osx-font-smoothing: grayscale; 251 | } 252 | 253 | .icon-font:before { content: "\E618"; } 254 | 255 | .icon-bold:before { content: "\E675"; } 256 | 257 | .icon-list-ul:before { content: "\EB3D"; } 258 | 259 | .icon-strikethrough:before { content: "\ECF6"; } 260 | 261 | .icon-italic:before { content: "\E702"; } 262 | 263 | .icon-redo:before { content: "\E811"; } 264 | 265 | .icon-undo:before { content: "\E824"; } 266 | 267 | .icon-full-screen-exit:before { content: "\E623"; } 268 | 269 | .icon-full-screen:before { content: "\E625"; } 270 | 271 | .icon-list-ol:before { content: "\E6C1"; } 272 | 273 | .icon-help:before { content: "\E659"; } 274 | 275 | .icon-underline:before { content: "\E65A"; } 276 | 277 | .icon-713bianjiqi_yinyong:before { content: "\E65D"; } 278 | 279 | .icon-align-center:before { content: "\E661"; } 280 | 281 | .icon-align-left:before { content: "\E662"; } 282 | 283 | .icon-align-right:before { content: "\E663"; } 284 | 285 | .icon-link:before { content: "\E664"; } 286 | 287 | .icon-picture:before { content: "\E665"; } 288 | 289 | .icon-quotes:before { content: "\E715"; } 290 | 291 | .icon-video:before { content: "\E6EF"; } 292 | 293 | .icon-close:before { content: "\E676"; } 294 | 295 | 296 | 297 | /*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9CZXN0RWRpdG9yLy4vc3JjL3Njc3MvbWFpbi5zY3NzIiwid2VicGFjazovL0Jlc3RFZGl0b3IvLi9zcmMvYXNzZXRzL2ljb25mb250LmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBLHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQSx3QkFBd0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0I7QUFDeEI7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLG05UkFBbTlSOztBQUU5L1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkM7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQztBQUNuQztBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7OztBQzFPNUIsWUFBWTtBQUNaLCtCQUErQjtBQUMvQjtBQUNBLG9DQUFvQyxjQUFjO0FBQ2xEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG1CQUFtQixrQkFBa0I7O0FBRXJDLG1CQUFtQixrQkFBa0I7O0FBRXJDLHNCQUFzQixrQkFBa0I7O0FBRXhDLDRCQUE0QixrQkFBa0I7O0FBRTlDLHFCQUFxQixrQkFBa0I7O0FBRXZDLG1CQUFtQixrQkFBa0I7O0FBRXJDLG1CQUFtQixrQkFBa0I7O0FBRXJDLCtCQUErQixrQkFBa0I7O0FBRWpELDBCQUEwQixrQkFBa0I7O0FBRTVDLHNCQUFzQixrQkFBa0I7O0FBRXhDLG1CQUFtQixrQkFBa0I7O0FBRXJDLHdCQUF3QixrQkFBa0I7O0FBRTFDLGtDQUFrQyxrQkFBa0I7O0FBRXBELDJCQUEyQixrQkFBa0I7O0FBRTdDLHlCQUF5QixrQkFBa0I7O0FBRTNDLDBCQUEwQixrQkFBa0I7O0FBRTVDLG1CQUFtQixrQkFBa0I7O0FBRXJDLHNCQUFzQixrQkFBa0I7O0FBRXhDLHFCQUFxQixrQkFBa0I7O0FBRXZDLG9CQUFvQixrQkFBa0I7O0FBRXRDLG9CQUFvQixrQkFBa0IiLCJmaWxlIjoiYmVzdC1lZGl0b3IuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLmJlc3QtZWRpdG9yLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47IH1cbiAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lci5mdWxsLXNjcmVlbiB7XG4gICAgcG9zaXRpb246IGZpeGVkO1xuICAgIHotaW5kZXg6IDk5OTk7XG4gICAgdG9wOiAwO1xuICAgIGxlZnQ6IDA7XG4gICAgcmlnaHQ6IDA7XG4gICAgYm90dG9tOiAwO1xuICAgIHdpZHRoOiAxMDAlICFpbXBvcnRhbnQ7XG4gICAgaGVpZ2h0OiAxMDAlICFpbXBvcnRhbnQ7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2Q5ZDlkOTsgfVxuICAgIC5iZXN0LWVkaXRvci1jb250YWluZXIuZnVsbC1zY3JlZW4gLmJlc3QtZWRpdG9yIHtcbiAgICAgIHdpZHRoOiA2MCU7XG4gICAgICBtYXJnaW46IDAgYXV0bztcbiAgICAgIGJveC1zaGFkb3c6IDAgMCAyMHB4IHJnYmEoMCwgMCwgMCwgMC4xKTtcbiAgICAgIG1hcmdpbi10b3A6IDM1cHg7XG4gICAgICBtYXJnaW4tYm90dG9tOiAyMHB4OyB9XG4gIC5iZXN0LWVkaXRvci1jb250YWluZXIgLmJlc3QtZWRpdG9yLXRvb2xiYXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNkOWQ5ZDk7XG4gICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNjY2M7XG4gICAgdXNlci1zZWxlY3Q6IG5vbmU7XG4gICAgYm94LXNpemluZzogYm9yZGVyLWJveDsgfVxuICAgIC5iZXN0LWVkaXRvci1jb250YWluZXIgLmJlc3QtZWRpdG9yLXRvb2xiYXIgdWwge1xuICAgICAgem9vbTogMTtcbiAgICAgIGxpc3Qtc3R5bGU6IG5vbmU7XG4gICAgICB3b3JkLWJyZWFrOiBicmVhay1hbGw7IH1cbiAgICAgIC5iZXN0LWVkaXRvci1jb250YWluZXIgLmJlc3QtZWRpdG9yLXRvb2xiYXIgdWwgbGkge1xuICAgICAgICBsaXN0LXN0eWxlOiBub25lO1xuICAgICAgICBmbG9hdDogbGVmdDsgfVxuICAgICAgICAuYmVzdC1lZGl0b3ItY29udGFpbmVyIC5iZXN0LWVkaXRvci10b29sYmFyIHVsIGxpIGEge1xuICAgICAgICAgIGhlaWdodDogMzlweDtcbiAgICAgICAgICBsaW5lLWhlaWdodDogMzlweDtcbiAgICAgICAgICBjb2xvcjogIzU5NTk1OTtcbiAgICAgICAgICBwYWRkaW5nOiAwIDE0cHg7XG4gICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICAgICAgICAgIGZvbnQtc2l6ZTogMTZweDtcbiAgICAgICAgICBmb250LXdlaWdodDogYm9sZDtcbiAgICAgICAgICBjdXJzb3I6IHBvaW50ZXI7IH1cbiAgICAgICAgICAuYmVzdC1lZGl0b3ItY29udGFpbmVyIC5iZXN0LWVkaXRvci10b29sYmFyIHVsIGxpIGE6aG92ZXIge1xuICAgICAgICAgICAgY29sb3I6ICNmMmYyZjI7XG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNTk1OTU5OyB9XG4gICAgICAuYmVzdC1lZGl0b3ItY29udGFpbmVyIC5iZXN0LWVkaXRvci10b29sYmFyIHVsOmFmdGVyIHtcbiAgICAgICAgY29udGVudDogXCIuXCI7XG4gICAgICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgICAgICBoZWlnaHQ6IDA7XG4gICAgICAgIGNsZWFyOiBib3RoO1xuICAgICAgICB2aXNpYmlsaXR5OiBoaWRkZW47IH1cbiAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3Ige1xuICAgIGZsZXg6IDE7XG4gICAgb3V0bGluZTogbm9uZTtcbiAgICBwYWRkaW5nOiAzMHB4O1xuICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG4gICAgcGFkZGluZy10b3A6IDE1cHg7XG4gICAgb3ZlcmZsb3cteTogYXV0bztcbiAgICBiYWNrZ3JvdW5kOiAjZmZmOyB9XG4gICAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgcCB7XG4gICAgICBtYXJnaW46IDE1cHggMDtcbiAgICAgIHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7IH1cbiAgICAuYmVzdC1lZGl0b3ItY29udGFpbmVyIC5iZXN0LWVkaXRvciBoMSwgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgaDIsIC5iZXN0LWVkaXRvci1jb250YWluZXIgLmJlc3QtZWRpdG9yIGgzLCAuYmVzdC1lZGl0b3ItY29udGFpbmVyIC5iZXN0LWVkaXRvciBoNCwgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgaDUsIC5iZXN0LWVkaXRvci1jb250YWluZXIgLmJlc3QtZWRpdG9yIGg2IHtcbiAgICAgIG1hcmdpbjogMTVweCAwOyB9XG4gICAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgYSB7XG4gICAgICB0ZXh0LWRlY29yYXRpb246IG5vbmU7XG4gICAgICBjb2xvcjogIzMxOTRkMDsgfVxuICAgIC5iZXN0LWVkaXRvci1jb250YWluZXIgLmJlc3QtZWRpdG9yIGJsb2NrcXVvdGUge1xuICAgICAgcGFkZGluZzogMjBweDtcbiAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMmYyZjI7XG4gICAgICBib3JkZXItbGVmdDogNnB4IHNvbGlkICNiM2IzYjM7XG4gICAgICB3b3JkLWJyZWFrOiBicmVhay13b3JkO1xuICAgICAgZm9udC1zaXplOiAxNnB4O1xuICAgICAgZm9udC13ZWlnaHQ6IDQwMDtcbiAgICAgIGxpbmUtaGVpZ2h0OiAzMHB4O1xuICAgICAgbWFyZ2luOiAwIDAgMjBweDsgfVxuICAgIC5iZXN0LWVkaXRvci1jb250YWluZXIgLmJlc3QtZWRpdG9yIGlmcmFtZSB7XG4gICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgIG1hcmdpbjogMCBhdXRvOyB9XG4gICAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgdWwsIC5iZXN0LWVkaXRvci1jb250YWluZXIgLmJlc3QtZWRpdG9yIG9sIHtcbiAgICAgIGxpc3Qtc3R5bGUtcG9zaXRpb246IGluc2lkZTtcbiAgICAgIG1hcmdpbjogMTVweCAwOyB9XG4gICAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgLmltYWdlLWJveCB7XG4gICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gICAgICBmb250LXNpemU6IDA7XG4gICAgICBtYXJnaW46IDE1cHggMDsgfVxuICAgICAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgLmltYWdlLWJveCA+IGltZyB7XG4gICAgICAgIG1heC13aWR0aDogMTAwJTtcbiAgICAgICAgd2lkdGg6IGF1dG87XG4gICAgICAgIGhlaWdodDogYXV0bztcbiAgICAgICAgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcbiAgICAgICAgYm9yZGVyOiAwOyB9XG4gICAgICAuYmVzdC1lZGl0b3ItY29udGFpbmVyIC5iZXN0LWVkaXRvciAuaW1hZ2UtYm94IC5pbWFnZS11cGxvYWQge1xuICAgICAgICB3aWR0aDogNDQzcHg7XG4gICAgICAgIHBhZGRpbmc6IDVweCAxNnB4IDVweCA1cHg7XG4gICAgICAgIG1hcmdpbjogMCBhdXRvO1xuICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjZDlkOWQ5O1xuICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgICBmb250LXNpemU6IDE0cHg7XG4gICAgICAgIC13ZWJraXQtYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDsgfVxuICAgICAgICAuYmVzdC1lZGl0b3ItY29udGFpbmVyIC5iZXN0LWVkaXRvciAuaW1hZ2UtYm94IC5pbWFnZS11cGxvYWQgLnByZXZpZXctaW1hZ2Uge1xuICAgICAgICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgICAgICAgIGZsb2F0OiBsZWZ0O1xuICAgICAgICAgIHdpZHRoOiA5MHB4O1xuICAgICAgICAgIGhlaWdodDogOTBweDtcbiAgICAgICAgICBvYmplY3QtZml0OiBjb3ZlcjtcbiAgICAgICAgICBtYXJnaW4tcmlnaHQ6IDIwcHg7IH1cbiAgICAgICAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgLmltYWdlLWJveCAuaW1hZ2UtdXBsb2FkIC5zdGF0dXMtYmFyIHtcbiAgICAgICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgICAgICBmbG9hdDogcmlnaHQ7XG4gICAgICAgICAgd2lkdGg6IDMwNXB4OyB9XG4gICAgICAgICAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgLmltYWdlLWJveCAuaW1hZ2UtdXBsb2FkIC5zdGF0dXMtYmFyIC51cGxvYWQtZXJyb3ItbXNnIHtcbiAgICAgICAgICAgIGNvbG9yOiAjZjUwOyB9XG4gICAgICAgICAgLmJlc3QtZWRpdG9yLWNvbnRhaW5lciAuYmVzdC1lZGl0b3IgLmltYWdlLWJveCAuaW1hZ2UtdXBsb2FkIC5zdGF0dXMtYmFyIC5zdGF0dXMtYXJlYSBhIHtcbiAgICAgICAgICAgIGZsb2F0OiByaWdodDtcbiAgICAgICAgICAgIG1hcmdpbi1sZWZ0OiAyMHB4O1xuICAgICAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgICAgICAgY29sb3I6ICM5OTk7IH1cbiAgICAgICAgICAuYmVzdC1lZGl0b3ItY29udGFpbmVyIC5iZXN0LWVkaXRvciAuaW1hZ2UtYm94IC5pbWFnZS11cGxvYWQgLnN0YXR1cy1iYXIgLnN0YXR1cy1hcmVhIC51cGxvYWQtYnRuLXJldHJ5IHtcbiAgICAgICAgICAgIGRpc3BsYXk6IG5vbmU7IH1cbiAgICAgICAgICAuYmVzdC1lZGl0b3ItY29udGFpbmVyIC5iZXN0LWVkaXRvciAuaW1hZ2UtYm94IC5pbWFnZS11cGxvYWQgLnN0YXR1cy1iYXIgLnVwbG9hZGluZy1pY29uIHtcbiAgICAgICAgICAgIGhlaWdodDogM3B4O1xuICAgICAgICAgICAgd2lkdGg6IDMwNXB4O1xuICAgICAgICAgICAgbWluLWhlaWdodDogM3B4O1xuICAgICAgICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgICAgICAgICBtYXJnaW46IDI1cHggMCAyMHB4O1xuICAgICAgICAgICAgYmFja2dyb3VuZDogdXJsKGRhdGE6aW1hZ2UvZ2lmO2Jhc2U2NCxSMGxHT0RsaE1nRURBTVFmQUNWNzlEYUgrYXZIOGJESzlyREo3YWpJOHF2STdxM0s4YS9NOTJPYzdpaDc3Ni9LOUtyTDlLYkg4S2JLOGpWLzdpOSs3eGh3OGJqVCtJQ3c4cExGK3NIVzlhM0g4YWpIOGF6SjhMUEw5cTNMOXJQTDd6Qi84U1Y4OXpTSC9mLy8veUgvQzA1RlZGTkRRVkJGTWk0d0F3RUFBQUFoL3d0WVRWQWdSR0YwWVZoTlVEdy9lSEJoWTJ0bGRDQmlaV2RwYmowaTc3dS9JaUJwWkQwaVZ6Vk5NRTF3UTJWb2FVaDZjbVZUZWs1VVkzcHJZemxrSWo4K0lEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlrRmtiMkpsSUZoTlVDQkRiM0psSURVdU5pMWpNVE15SURjNUxqRTFPVEk0TkN3Z01qQXhOaTh3TkM4eE9TMHhNem94TXpvME1DQWdJQ0FnSUNBZ0lqNGdQSEprWmpwU1JFWWdlRzFzYm5NNmNtUm1QU0pvZEhSd09pOHZkM2QzTG5jekxtOXlaeTh4T1RrNUx6QXlMekl5TFhKa1ppMXplVzUwWVhndGJuTWpJajRnUEhKa1pqcEVaWE5qY21sd2RHbHZiaUJ5WkdZNllXSnZkWFE5SWlJZ2VHMXNibk02ZUcxd1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZJaUI0Yld4dWN6cDRiWEJOVFQwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0wyMXRMeUlnZUcxc2JuTTZjM1JTWldZOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXpWSGx3WlM5U1pYTnZkWEpqWlZKbFppTWlJSGh0Y0RwRGNtVmhkRzl5Vkc5dmJEMGlRV1J2WW1VZ1VHaHZkRzl6YUc5d0lFTkRJREl3TVRVdU5TQW9UV0ZqYVc1MGIzTm9LU0lnZUcxd1RVMDZTVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG8yUVRkRlF6STNPVVV5TVVReE1VVTJPRVZHTVVWRlJUWTBOelkxTlVKRU15SWdlRzF3VFUwNlJHOWpkVzFsYm5SSlJEMGllRzF3TG1ScFpEbzJRVGRGUXpJM1FVVXlNVVF4TVVVMk9FVkdNVVZGUlRZME56WTFOVUpFTXlJK0lEeDRiWEJOVFRwRVpYSnBkbVZrUm5KdmJTQnpkRkpsWmpwcGJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09qWkJOMFZETWpjM1JUSXhSREV4UlRZNFJVWXhSVVZGTmpRM05qVTFRa1F6SWlCemRGSmxaanBrYjJOMWJXVnVkRWxFUFNKNGJYQXVaR2xrT2paQk4wVkRNamM0UlRJeFJERXhSVFk0UlVZeFJVVkZOalEzTmpVMVFrUXpJaTgrSUR3dmNtUm1Pa1JsYzJOeWFYQjBhVzl1UGlBOEwzSmtaanBTUkVZK0lEd3ZlRHA0YlhCdFpYUmhQaUE4UDNod1lXTnJaWFFnWlc1a1BTSnlJajgrQWYvKy9mejcrdm40OS9iMTlQUHk4ZkR2N3UzczYrcnA2T2ZtNWVUajR1SGczOTdkM052YTJkalgxdFhVMDlMUjBNL096Y3pMeXNuSXg4YkZ4TVBDd2NDL3ZyMjh1N3E1dUxlMnRiU3pzckd3cjY2dHJLdXFxYWlucHFXa282S2hvSitlblp5Ym1wbVlsNWFWbEpPU2taQ1BqbzJNaTRxSmlJZUdoWVNEZ29HQWYzNTlmSHQ2ZVhoM2RuVjBjM0p4Y0c5dWJXeHJhbWxvWjJabFpHTmlZV0JmWGwxY1cxcFpXRmRXVlZSVFVsRlFUMDVOVEV0S1NVaEhSa1ZFUTBKQlFEOCtQVHc3T2prNE56WTFORE15TVRBdkxpMHNLeW9wS0NjbUpTUWpJaUVnSHg0ZEhCc2FHUmdYRmhVVUV4SVJFQThPRFF3TENna0lCd1lGQkFNQ0FRQUFJZmtFQlFNQUh3QXNBQUFBQURJQkF3QUFCWjZnSll5alpaNW9xcTVzNjc2d0tseDBiWk96cmU5ODcvL0FvTkJYS0JZYVNLU3htR3dzajhuTHN6bU5McHRPWTY2R3UrRzJsNitYWktEaEdvTUJZbzNJdU4zcHVEd2pyOXZ2K0x4K2o2ZHIvb0NCZ29PRWhZYUhpSW1LaTRGc0NJS09qNENSa0k2TmxwZHJsWkdjblo2Zm5IK09CUVNscHFlb3FhcXJySzJ1cjdBWXNyTzB0YmEzdUxtNnU3eTl2ci9Bd2NBSHdzSUh4QmlsQndzTklRQWgrUVFGQXdBZkFDd0dBQUFBQlFBQ0FBQUZCcUFnaWtoWmhnQWgrUVFGQXdBZkFDd0FBQUFBQXdBREFBQUZCK0FrZmVJZ2JpRUFJZmtFQlFNQUh3QXNBQUFBQUNzQkF3QUFCVUZnMXdIQUdDVVpZWHhzNjc2dElNOXdiZDk0cnU5ODcvL0FvSEJJTExJRWdXVEFFNENnTm9RZ1lvb3dXcS9ZckhiTDdlNGdqekQ0OGZTYXoraTBlcDBPQVFBaCtRUUZBd0FmQUN3RUFBQUFuZ0FEQUFBRk91RDNBVjFwbWxFaUNXenJpbkFzejNSdDMzaXU3N3p0Q2lLUGNFZ0VUQ29MalhMSlpQYWUwS2gwK3VSOElOaHNscU5JVktqZ3NIZ01EZ0VBSWZrRUJRTUFId0FzQkFBQUFCOEFBd0FBQlNiZzkzVmlhWFpvcW5iUlUyeG00Sm4wNTkxNDduWEJsNVdMUjgwRUtScVBFSTdpSVlDVlFnQWgrUVFGQXdBZkFDd0VBQUFBS0FBREFBQUZKR0FIQUYxcG5taXFvbEdRRVlFbnozUnQzM2VYWkJuSFFjQ2djRWdzRGptS3dHWVRBZ0FoK1FRRkF3QWZBQ3dCQUFBQU9RQURBQUFGSjJEWEFTUWdubWlxcm14N1JvbGtCVjV0MzNpdTc3emVKWlVNWkVnc0dvL0lwQkxKZ1ZVSUlRQWgrUVFGQXdBZkFDd0dBQUFBMVFBREFBQUZSMkQzaldScG5taXFqbDNydnJEU1ZLc3AzSFd1a3plKy84Qmc4RUs4Q0M3Q1pNM0RiRHFmajlsaXQ2aHFsTmlzZHF0RGVMbGNqbmhNSm5laXRPQmhkV2l2d2ZDNG5CUUNBQ0g1QkFVREFCOEFMQWtBQUFCU0FBTUFBQVV2NENlT1pHbWVhS3FXWGV1K3NOSklSVjJzZUs2clh1Ly93TWRNUS94d2RpTE9FY2tzS1ovUUtBY2dsQnl1bUJBQUlma0VCUU1BSHdBc1V3QUFBQk1BQXdBQUJSVmdKNDVrQ1VCTjVxMXM2M3BCSTNGMGJkL0FJNGNBSWZrRUJRTUFId0FzQmdBQUFOTUFBd0FBQlVJZ0lJcGZhWjduQ0tCczY3NXdMSDlkYmQ5NDlCRGE3UC9Bb1BBa0tBNU5nYU55MmZJNG4xQm9KN0ZCTUsvWUxBb1NoSEMxNEJsblRDNmJBWTlxZU0yR2hRQUFJZmtFQlFNQUh3QXNIUUFBQU8wQUF3QUFCVVlnOEkxa2FaNW9xcTVzYTNad0xNOVJVbDJYcSsrOG0vZStqMkFvK0FHUHlLVFM1R2s2bjlET3BMS3NXcTlZRm1mTHlYcVYzTENZVzZOK3o2aUQrb0Qrck5YSDl5RUVBQ0g1QkFVREFCOEFMQndBQUFEU0FBTUFBQVUrNENlT1pHbWVhS3F1Ykp0MmNDekwwZE5rYnE3di9IcDV2YUJ3dVBNWWowaGtKMUNRRUovUXFIUktWWEd1MkN3V0FuZ1lOdFVuWm96cEhjNW5WUWdBSWZrRUJRTUFId0FzQUFBQUFNa0FBd0FBQlVYZ1ZnVFIxM1ZmcXE1c3F3S3dLODkwYmQ5NFBwOTg3d01LaXVSeTBSbGJHVVFBZFd3Nm45QW96a090V3ErUGhrU3F5MndjQVFCM1RDNmJVNXkwZXMwR1pMZG5XZ2dBSWZrRUJRTUFId0FzQUFBQUFQSUFBd0FBQlcrZ0pZcEVFVVJmcXE1c0M2aHZLNjlBWGM5NHJ1OTg3N2Vkb0hBNGpEd01pRit1d1d3b2Y0TFZZRHJJWkJDSnp2TVQyTFlDNEs1M1RDN3ZQT2kwT3QwSkdDVG16K0pBWDhSbm1vVitRZWozTnhRbll4Q0VFSGVIaUlrN0hJeU5qbzRBUnhsM0l4WmJHSmlZT1F5Y0RDRUFJZmtFQlFNQUh3QXNCQUFBQUNzQkF3QUFCWFhnSjFna0tVMFI4SzFzNjdiZEs4OTBiZDk0cnU5NTUvOUFZQ1FoTVRRYU5HVHJ3cnk0bXBmQ3NzbXJXcStyd1NERDVaNDQyTEFuVEM2YnE1NjBlcjN1SkNxYnd5STNuMm0xNTd6ZVJTQnNObjRWRXdvN0hJWmdlNG1LaXppSGpvK0dReFVmSkRRV05BZVpCeSthblpxTU9KNVduU0VBSWZrRUJRTUFId0FzQndBQUFOMEFBd0FBQlhEZ0ozNVdhVXBKOUFFc01MNmlDODgwM041MS9yWjY3Ly9Bb0hEVUtScVB4c2pqY3hnMW50Q29kQXA5WmE2WlFRWWxDd1JlbnFGNFRDNmJ6MEdQZXMxZWR3S0h6R3RCcjl2dmVEcUI4Q0ZzL29Bb0tqa1FoUkJvaUltS2kyUWNqbytRandBUEJoczFHSmdZTTVtYUl4Z2hBQ0g1QkFVREFCOEFMQWNBQUFBb0FRTUFBQVZRNENlT3BHVWFhRFZGWk91K2NDelBkRzNmZUs2N1hlLy9Qc0RqZzlnWmo4aGI1cE5wYmc0YmxTSkpyVnF2V0oxbnkrMTJIdzFKZGp6ZW1EZXU4MW5hSWJ2ZjhIaUxRNi9iNndxd1dNNnZtVU1BSWZrRUJRTUFId0FzRkFBQUFCMEJBd0FBQlhDZ0pZNWpSbjJmb3FCczY3NHNBQU15YktQMWw5OTg3Ly9Bb0ZEWUtScVB4c2pEZ0JnNmY0Vm85UG5LV0s5WHlZa1RDRkMvNExCNFRBNTZ6dWowdVJNNFNEUmxxbVorY0daUXpkZG16OWVteGhDQmdvSlVnM0dIaUlrZkhJeU5qbzBBRHdRYkh4aUtUcFpDbVI4SGRRY2hBQ0g1QkFVREFCOEFMQjBBQUFBUUFRTUFBQVZ5b0NXT2xqUkZnS0lxM3dlOEx0ek9kRzNmZUs3dmZPLy93R0N3UXl3YWk1R0VCSE1wMEp5emdsUmFFMWl0dEt0QWFETllNK0J3cGpKaEJjNDdqNXJMYnJ2ZjhEaFBUYS9YTzBxRXZxYnBheEE5QzNJNEdodUdoeHNtRVRvY2pSeURrSkdTazNHT2xwY2NTUklIbkhDY25aSWhBQ0g1QkFVREFCOEFMQ1FBQUFEdkFBTUFBQVZqb0NVS1JXRklVL1N0d09xK2NDelBkRzNmZUs3dmZMOTN3S0F3cUtCSVpxV2tjbG5JT0JIUURBcmlxMXF2Mkt4MlcvTjR2K0R2b3lFNXVEVG90SHF0M3JnM0JEZEs0WUxZNzNldWZzL3YrejhjZ1lLRGdRb1BSaXNIWmk0WUdEQ05qaThoQUNINUJBVURBQjhBTENjQUFBRGlBQU1BQUFWVDRDZU1nbVdlMHFSOGJPdStzQXNBY2MzT2RxN3ZmTy8vd0tDdlF5d2FpWkZFNVROb05qUFFxSVR5NEFpdjJLeDJ5KzM2UE9Dd0dBeVlWQTZmRFd2RGJtK21INFhWUzYvYjczZ2ZaOC92ODVNVkdDRUFJZmtFQlFNQUh3QXNKd0FBQUFnQkF3QUFCV0dnSllwZmFZNm80Q1NSNmI0dVVBSXlETk56YmU4ZjdmTStIRzlJTEJxUHlLVHkxV2s2bjgxSVFuSll3akNZakZZTDIzb0hqSW5DU2k2YnoraTBtdXhwdTkvdHpoU3hIbTd1K1B1cWhZVDRJWDEvZFlPRWhZWkVISW1LaTRrS1Uyc2hBQ0g1QkFVREFCOEFMRGtBQUFEeUFBTUFBQVZhb0NXT1l6VkZRS3FtWCt1K3NOdkZkTjEyT0c3dmZPLy93S0J3K01zWmo1SEF4bUlUWko1UXFHbEdyRnF2Mkt4MmkvVjR2MkJ2SnlISjFCQ0x6MmJOWHBzQWtMZzh6ZzFDNnZpOGZ0K0NQQjRRSElLRGdoRmtCRHNoQUNINUJBVURBQjhBTEVJQUFBRHJBQU1BQUFWU29DV09ZNVZFWC9vQkxLQ21MZnZPZEEyM2RxN3ZmTy8vd0tCUTJDa2FqOFZJb3ZMSk9KL1B5cVF6ckZxdjJLeDJ5L1Y0djJCdlp6blltTTluS1NvRmFidGY3alozVHEvYjc1dzh4NmJ2KzVWTUlRQWgrUVFGQXdBZkFDeExBQUFBNXdBREFBQUZRcUFsanFORWRkR25ybXpydm5Bc3ozUnQzM2l1NzN2bi83NUlaa2drVmlpZkRtL0piRHFmME9qU1E2MVNPNXVzVm52a0tGNEJqblJNTHB2UE9ZNTZyWTZFQUFBaCtRUUZBd0FmQUN4VUFBQUFlUUFEQUFBRk5hQWxqdVJHZGRHbnJtenJBbTRzejNSdDN5dWc3MW52L3hMSHA0TXJHby9JNUNyQURIdzIwS2kwNGdnb09Fb1ZaSnZ0ZW9zaEFDSDVCQVVEQUI4QUxBRUFBQUNKQUFNQUFBVSs0Q2QrMW1pZWFLcXViT3UrVml6UFZ0WThFYUR2L1B0MVFHQm1PUFFaajhpa2lzaGtTaGlCanJLMXFWYW4yS3oyWSsxMkpaaUhBa0l1bXlHdmN3Z0FJZmtFQlFNQUh3QXNBUUFBQUJFQkF3QUFCVmVnSUlwZmFaNW9xcTVzNjZJaitiWldiZHZDZFdYWEU1bUFvSEJJTEFabnlLUnl5V3kraE02b2RJYW9JcWFmakhhN0hWUWxta0FIU3k2YnoxaUNtb0J1dTFtYnVId2VseHdlQ2hOa3orZWorb0FRYjRPRVppRUFJZmtFQlFNQUh3QXNBZ0FBQUpJQUF3QUFCVFpnSVg1a2FaNW9xcTVzNjc2d2FjMTBiVnVaRUVUdzRNZkFvSkNGR0w0eXlLUnltWkVnRWh5amRFcXREamZZckhiN1VFUmJqeEFBSWZrRUJRTUFId0FzQVFBQUFCSUJBd0FBQlV2Z0ozNkZNSjVvcXE1czY2cEZYTHgwM1ZwNHJ1L1ZGTm5BRDJCSURCcVB5QlpnQkJpTW5NbW9WS1daV2pQWXJIYmJlMWhYZ1hEZ1N5NmJ6K2kwY2NOdXU5czloWHBPVDBMdWtCQUFJZmtFQlFNQUh3QXNrUUFBQUNRQUF3QUFCU09nSlk1a2FVbEpCS3hmNjc1dkpzOTBuVlVKRU94dzN3YWJvSEJJM09BaXZtUXJCQUFoK1FRRkF3QWZBQ3cyQUFBQWZ3QURBQUFGTzZBZ0NsOXBubWlxcnVrb3NyQkx3alJzM1hpZUMwVWhKUkdFc0VZc29vUkRvMm5BWkNxVm1haDBTaFZXSm9xbmRzdnQxamJnc0hnTXZpcENBQ0g1QkFVREFCOEFMRFVBQUFDVUFBTUFBQVUzb1BDTlpHbWVhS3FPeGVxK2NBeGJkRzNmdURRcGN1K1BnK0RnUnl6R01zaWtjcm1zVEI0ZmozRktyVnBYbTZ4Mnk5VTZGWkJQQ0FBaCtRUUZBd0FmQUN3QUFBQUFKZ0VEQUFBRlk2QUNLWlAwbldpcXJtenJwa1ZjdkhSTnkvWXF6M252L3lxTGNFZ3NEak9DQUFESWJPWUFVR2dnOENobG5OZ1VBclhOQWdlSWNQY25IbnZQdm94NnpXNnZKWWdFQjAwSFRxY2Z5S05xcXZ2L2dCOEVnNEdGS0J1SWlZcUxpdzhLaHBBc0lRQWgrUVFGQXdBZkFDd0FBQUFBSWdFREFBQUZkU0NrZkVwcG5taDZCczcydlhBc3p5L3pDblN1QzN6di96MmRjRWdzR285SW82REFiRHFmVGNra2txeFdPNitBZHN2dGVybVBoTTBLR3h3MEdySU13VzY3MzI2MWZFNmZJejd3dkxzeUdkWC9IeDRQTHcrRmhvZUlpUThjaFFsM2N3Y0hCSUNVUnk2Vm1KUWJtNXlkbnB0OGZwbHFJUUFoK1FRRkF3QWZBQ3daQUFBQUNRRURBQUFGZE9BbkttUnBubWdaQmRUeFdXSXN6M1JjM0hpdTYzWHYvOENnY0Vnc0duV09wSEtwckV3aUg0QlJCS2hhcjFoUllNdnRlcjlkVHNBaEdXU21NZ1I2elc2NzMyNkVmRTZ2ejUwZE9QQWhldmovZ0lHQ2Z3b1BBeHQ2YUFjTExtc0xqNG1Sa213YmxaYVhtSlpPVUdzUW5wK2dvQjhoQUNINUJBVURBQjhBTERRQUFBRGNBQU1BQUFWYm9BS01aR21lcEVKSmd2QzljQ3pQcjB2ZmVLN3ZmTy8vd0oxalNDd2FoeHJESXhMNGVKNmVBSFJLclQ1V2c2QjJ5KzE2djE2RWVFd3VpeVdFUU9mQmdYRGE3N2g4TGxjOEdoS3dmcy92KzJjYmdZS0RoSUVTR3c4QUlRQWgrUVFGQXdBZkFDdzFBQUFBNndBREFBQUZaNkFpaWw5cG51Z0pyR3pydm11VVNNSm5wWGl1NzN6dm00Smc4TGNyRUk5SWxHUEpiRG9kZ3Nxa0ZLZ0draCtQZHN2dGVyV2NpU1NUd1pyUDU0RjZnRzY3ZFlpNGZFNUhaQ3FVem1PL1QzTCtnSUdDZzM5NllodHZpWXFMakl5SUc1Q1JrcE40Q2lFQUlma0VCUU1BSHdBc1l3QUFBTTRBQXdBQUJWbmdCNHhrYVo1QUZEVGI5eFZ3TE05dWJkOTRydTk4Ny8vQW9CQTNLeFlSaGtmazQyazZuOUNvaDVQUVNGeUlySGJMSFhxLzRMQjQvRUVjdU9pdGhCRDRjTjd3dUh6K1ZpUXlMYkoreisvM040Q0Jnb01iYXc4QUlRQWgrUVFGQXdBZkFDeDZBQUFBdUFBREFBQUZReUFnam1ScEF0RlVmV3pydm5EOENqUXQzM2l1NzN6dnk0VUNyZUVwR28vSXBLZWordjBHVUtoelNxMWFlNGdzb3NEcGVyL2dNQWZRdkpyUDZMUjZzeUZzR2lFQUlma0VCUU1BSHdBc2tBQUFBQmNBQXdBQUJSWWdJSTVrV1VhSjVLMXM2N3JjSkhGMGJkODI5TWdoQUNINUJBVURBQjhBTERvQUFBQ0JBQU1BQUFVMDRDZU9aR21lYUtxdWJPdCtRQ3pQOUJ3bEV2SHVmTy8vSDQ5d1NDd1NPYmdNWkxrRW5waE5weFRJcVZxdjJHdm5nZnVFQUFBaCtRUUZBd0FmQUN3QUFBQUErQUFEQUFBRlNlRDBBVjlwbm1pcXJtenJ2bkFzejNUTkFuaXU3M21VU0lLZ2NFZ2MybEtVaCtmSWJEcWYwS2pOUTYxYXJ3RXE0SWZvZXI5U1ZlUERDWnZQNkxTWncyNjczMjdGVDkzS2hBQUFJZmtFQlFNQUh3QXNBQUFBQUJjQkF3QUFCVitnSUk1a2FaWlZFbjFzNjc1d0xNOTBiZDk0cnUvOEIvekFvUEFYbVVnK2pxUnl5WFQwbnF5QmRMcW9WcWRTNndJclRRR2c0TEI0VEM2N1BPaTBlbzErR0RQbU9HRk9yOXZ2OXRRcXp1Lzcvem9jZ29PRWhSd0Fia2RqRzN3WklRQWgrUVFGQXdBZkFDd1pBQUFBL2dBREFBQUZZK0FuakdScG51aUlMVlFRS1Y4c3ozUnQzM2l1NzN6di8wQVpZRWdzR2lPQno2RlhDT0lXVU9oZ09vaEtxVlVyMXByUkJEcEpwM2hNTHB2UEg0OTZ6VzZEUHhJMGtFQ3YyKy80ZkgzVEFzai9nSUdDT2h5RmhvZUlIQUJoT1JtT0dYSWJJUUFoK1FRRkF3QWZBQ3c0QUFBQTN3QURBQUFGWGFBZ2ptUnBubWJCVEVyN3ZYQXN6M1J0MzNpdTczei9BY0NnY0tpWVNBUSszR0xBWkM2ZXkrWUErcFJPb1ZMTjZoRUlKTC9nc0hpODg1alA2UFREbUNISENQQzRmRTZ2enc4SXl1UERjZnYvZ0lFdkhJU0Zob2RyRW44TElRQWgrUVFGQXdBZkFDeGFBQUFBeEFBREFBQUZZYUJRakdOak5tU3FycWtnVGRHbktGOXQzM2l1NzN6di84QmdFRUFzR291UmhBUWoxR21lR29aMFNxMWFyNi9PSnhCb2VyL2dzSGpuS1p2UFpvaFNqQ0FjM20rTWZFNnYyK3VFRndEQ0gvdi9nSUFjZzRTRmhBb0pGVDRaTlJ1TU9DRUFJZmtFQlFNQUh3QXNlZ0FBQUxJQUF3QUFCVmRnSVk1a2FaN0Y0UVNSb254d0xNOTBiZDk0cnU4NzRQOUFYeVFoWWRnYU9TU013V3c2bjlCb1p0WDVCSGpZckhiTG5YbSs0UEQzUWV6R0RwaTBlczF1dXpFYlJnRHdnWmp2K0R5UHcrLzcrUW9KRlRFYlhTRUFJZmtFQlFNQUh3QXNaUUFBQUx3QUF3QUFCV3ZnSjQ1a2FaNW9XaFpYNDE1RkxNLzB2RkZCcE81ODcvOUFFV0JJTEFJaUNZbEl3OVNVbXM1blU4cWtWa2xRaG5iTDdYcTNFa2VnRXl5YnoyYVBlczMyUUNhVnoyRStMOUhyby92QlR1ZjNTWGNZZ29PRWhZYURHd2dCQUdpTmpvOGpISktUbEJ3S0NYRWZJUUFoK1FRRkF3QWZBQ3hxQUFBQXdnQURBQUFGZEdBamZtUXBqaVY1cHQ5MVh1elpzSFFxMDJ1aDYvSytuNzROcFJOUktHcklwSExKYkNvQjBHaFVBWmxJQ3M2c0ZxbnBkbGxlRGRqTEtKdkQ1ckpYUWlFRkF0dTRmRTd6Mk8vM3dJTlNPWHdRZElGSUI0U0VMSVYrS1lnSEdJMFlpNDZOaFd3ZlZCQ0NtSmxJSEp5ZG5SQjdGU1VoQUNINUJBVURBQjhBTEZrQUFBRFpBQU1BQUFWVzRDZU9aR21lYUtxdWJPdVN4ZFhNZEczUGh4TkViKy8vSjRCd0tJd0VOZ0tnY3Nsc2tqUlFoblJLclRJUWlFVEh5WFY2dnVCdko3RlpiRGJkdExwN1lCd1c4TGg4ZnRnd0FvcTF2dlhnK1A5K0FBa2ZCQ0VBSWZrRUJRTUFId0FzeHdBQUFHc0FBd0FBQlQzZ0o0NWtPVFpvcXE0Q3NWRlBaTTUwYmQvNEIreHlUakxBb0hDNDJHd2NBWTV2eVd5S1BKNUE1N0JZTHE3WXJIWnhjRkVDQ3FmWXFaeHh6cEVRQUNINUJBVURBQjhBTE9nQUFBQStBQU1BQUFVcFlDT09aSGtKR2RWRlgrdStjQ3pQTUdQZk9LN3RFaFhRd0tCd1FTd2FqWWRrTDZBUU9wK2ZSd2dBSWZrRUJRTUFId0FzQVFBQUFDVUJBd0FBQlV6Z0o0NWthWjVvcXE1czY3NXdMTTkwL1RaNHJ1dkZSbkVSbXduUklncHRSbGhTaEdnZW45QW9paUdOTWE3WXJHYXJZV2drbEUrblNpNURDUVN6ZXMydUxkN3crR0ZPQndjVVVVNElBQ0g1QkFVREFCOEFMQVVCQUFBUUFBTUFBQVVZWUNHS1RkbU1ncFJFU050cXNPWWlWZElkZUs3bmRSUUNBQ0g1QkFVREFCOEFMQkVCQUFBT0FBTUFBQVVYWUZFMFpIT0pCU1lsRVlKb01PeTZhM2ZjZUU1VWJBZ0FJZmtFQlFNQUh3QXNHd0VBQUEwQUF3QUFCUlpnY1RWa1U1d1M5YTFhMnlKd1JYSGZZZCszckNnaEFDSDVCQVVEQUI4QUxDUUJBQUFMQUFNQUFBVVdZRkUwSkxsUjNZY2dXcXN4a3ZOMVIyMFRWZk1wSVFBaCtRUUZBd0FmQUN3R0FBQUFMQUVEQUFBRk9lQW5qbVJwbm1pcXJtenJ2bkFzejNSdDMvQlY3TVYxTllOZ0VFY3N1alFJbzNMSmJEcGxEQ1JpT2kwOHI5aXNkc3Z0SHI3ZnplWVNBZ0E3KSA1MCUgbm8tcmVwZWF0OyB9XG5cbi5iZXN0LWVkaXRvci1kaWFsb2cge1xuICBwb3NpdGlvbjogZml4ZWQ7XG4gIHRvcDogMDtcbiAgbGVmdDogMDtcbiAgcmlnaHQ6IDA7XG4gIGJvdHRvbTogMDtcbiAgei1pbmRleDogOTk5OTk5OTk5OTk5OTtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjcpOyB9XG4gIC5iZXN0LWVkaXRvci1kaWFsb2cgLndyYXAge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDUwJTtcbiAgICBsZWZ0OiA1MCU7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7XG4gICAgd2lkdGg6IDQxMnB4O1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNmZmY7XG4gICAgYm9yZGVyLXJhZGl1czogNnB4O1xuICAgIC13ZWJraXQtYm94LXNoYWRvdzogMCAycHggOHB4IHJnYmEoMCwgMCwgMCwgMC4yKTtcbiAgICBib3gtc2hhZG93OiAwIDJweCA4cHggcmdiYSgwLCAwLCAwLCAwLjIpO1xuICAgIHBhZGRpbmc6IDE2cHg7XG4gICAgYm94LXNpemluZzogYm9yZGVyLWJveDsgfVxuICAgIC5iZXN0LWVkaXRvci1kaWFsb2cgLndyYXAgLmhlYWQgLmNsb3NlIHtcbiAgICAgIHRleHQtYWxpZ246IHJpZ2h0OyB9XG4gICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5oZWFkIC5jbG9zZSBhIHtcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgICBmb250LXNpemU6IDI0cHg7XG4gICAgICAgIGNvbG9yOiAjOTk5O1xuICAgICAgICB0cmFuc2l0aW9uOiBjb2xvciAuM3MgZWFzZTsgfVxuICAgICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5oZWFkIC5jbG9zZSBhOmhvdmVyIHtcbiAgICAgICAgICBjb2xvcjogIzRkNGQ0ZDsgfVxuICAgIC5iZXN0LWVkaXRvci1kaWFsb2cgLndyYXAgLmhlYWQgaDMge1xuICAgICAgZm9udC1zaXplOiAyMnB4O1xuICAgICAgcGFkZGluZy1ib3R0b206IDI2cHg7XG4gICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7IH1cbiAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5ib2R5IHtcbiAgICAgIHBhZGRpbmc6IDE1cHggMzBweCAzMHB4OyB9XG4gICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5ib2R5IC51cGxvYWQtYnRuIHtcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgICAgICBoZWlnaHQ6IDQycHg7XG4gICAgICAgIG1hcmdpbi1ib3R0b206IDIwcHg7XG4gICAgICAgIGJhY2tncm91bmQ6ICM1NTU7XG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgICAgICAgbGluZS1oZWlnaHQ6IDQycHg7XG4gICAgICAgIGNvbG9yOiAjZmZmO1xuICAgICAgICBmb250LXNpemU6IDE0cHg7XG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjsgfVxuICAgICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5ib2R5IC51cGxvYWQtYnRuIGlucHV0IHtcbiAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICAgICAgdG9wOiAtMTIwMDBweDtcbiAgICAgICAgICByaWdodDogMDtcbiAgICAgICAgICBsZWZ0OiAwOyB9XG4gICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5ib2R5IC5pbnB1dC1ib3gge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBtYXJnaW4tYm90dG9tOiAyMHB4OyB9XG4gICAgICAgIC5iZXN0LWVkaXRvci1kaWFsb2cgLndyYXAgLmJvZHkgLmlucHV0LWJveCA+IGRpdiB7XG4gICAgICAgICAgaGVpZ2h0OiA0MnB4O1xuICAgICAgICAgIGJvcmRlcjogMXB4IHNvbGlkICNjY2M7XG4gICAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICAgICAgICBsaW5lLWhlaWdodDogNDJweDsgfVxuICAgICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5ib2R5IC5pbnB1dC1ib3ggLmljb24tYm94IHtcbiAgICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2VlZTtcbiAgICAgICAgICB3aWR0aDogMzhweDtcbiAgICAgICAgICBjb2xvcjogIzU5NTk1OTsgfVxuICAgICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5ib2R5IC5pbnB1dC1ib3ggLmlucHV0IHtcbiAgICAgICAgICBib3JkZXItbGVmdDogMDtcbiAgICAgICAgICBmbGV4OiAxOyB9XG4gICAgICAgICAgLmJlc3QtZWRpdG9yLWRpYWxvZyAud3JhcCAuYm9keSAuaW5wdXQtYm94IC5pbnB1dCBpbnB1dCB7XG4gICAgICAgICAgICBib3JkZXI6IDA7XG4gICAgICAgICAgICBvdXRsaW5lOiBub25lO1xuICAgICAgICAgICAgd2lkdGg6IDk5JTtcbiAgICAgICAgICAgIGJvcmRlci1sZWZ0OiAwO1xuICAgICAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICAgICAgICAgIHBhZGRpbmc6IDAgMTBweDtcbiAgICAgICAgICAgIGNvbG9yOiAjNTk1OTU5OyB9XG4gICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5ib2R5IC5zd2l0Y2gtYm94IHtcbiAgICAgICAgY29sb3I6ICM4ODg7XG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICAgICAgZm9udC1zaXplOiAxNHB4O1xuICAgICAgICBwYWRkaW5nLWJvdHRvbTogMTBweDtcbiAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOyB9XG4gICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5ib2R5IC53YXJpbmctdHh0IHtcbiAgICAgICAgaGVpZ2h0OiAyMHB4O1xuICAgICAgICBsaW5lLWhlaWdodDogMjBweDtcbiAgICAgICAgY29sb3I6ICNiYzYzNTE7XG4gICAgICAgIGZvbnQtc2l6ZTogMTRweDtcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogNXB4OyB9XG4gICAgICAuYmVzdC1lZGl0b3ItZGlhbG9nIC53cmFwIC5ib2R5IC5idG4tYm94IHtcbiAgICAgICAgZm9udC1zaXplOiAxNHB4O1xuICAgICAgICB0ZXh0LWFsaWduOiByaWdodDtcbiAgICAgICAgaGVpZ2h0OiAzMHB4O1xuICAgICAgICBsaW5lLWhlaWdodDogMjBweDtcbiAgICAgICAgdXNlci1zZWxlY3Q6IG5vbmU7XG4gICAgICAgIGNvbG9yOiAjNTk1OTU5OyB9XG4gICAgICAgIC5iZXN0LWVkaXRvci1kaWFsb2cgLndyYXAgLmJvZHkgLmJ0bi1ib3ggPiBzcGFuIHtcbiAgICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gICAgICAgICAgdHJhbnNpdGlvbjogY29sb3IgLjNzIGVhc2U7XG4gICAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgICAgIHBhZGRpbmc6IDRweCAxMnB4O1xuICAgICAgICAgIGZvbnQtc2l6ZTogMTRweDtcbiAgICAgICAgICBmb250LXdlaWdodDogNTAwOyB9XG4gICAgICAgIC5iZXN0LWVkaXRvci1kaWFsb2cgLndyYXAgLmJvZHkgLmJ0bi1ib3ggLmNhbmNlbDpob3ZlciB7XG4gICAgICAgICAgY29sb3I6ICMwMDA7IH1cbiAgICAgICAgLmJlc3QtZWRpdG9yLWRpYWxvZyAud3JhcCAuYm9keSAuYnRuLWJveCAuY29uZmlybSB7XG4gICAgICAgICAgY29sb3I6ICM0MmMwMmU7XG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjtcbiAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjNDJjMDJlO1xuICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDE1cHg7XG4gICAgICAgICAgbWFyZ2luLWxlZnQ6IDE1cHg7IH1cbiIsIlxyXG5AZm9udC1mYWNlIHtmb250LWZhbWlseTogXCJpY29uZm9udFwiO1xyXG4gIHNyYzogdXJsKGZvbnRzL2ljb25mb250LmVvdCk7IC8qIElFOSovXHJcbiAgc3JjOiB1cmwoZm9udHMvaWNvbmZvbnQuZW90I2llZml4KSBmb3JtYXQoJ2VtYmVkZGVkLW9wZW50eXBlJyksIFxyXG4gIHVybCgnZGF0YTphcHBsaWNhdGlvbi94LWZvbnQtd29mZjtjaGFyc2V0PXV0Zi04O2Jhc2U2NCxkMDlHUmdBQkFBQUFBQTZVQUFzQUFBQUFGZ2dBQVFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQkhVMVZDQUFBQkNBQUFBRE1BQUFCQ3NQNno3VTlUTHpJQUFBRThBQUFBUkFBQUFGWThqazdvWTIxaGNBQUFBWUFBQUFEL0FBQUMrSk5aaG8xbmJIbG1BQUFDZ0FBQUNVRUFBQTAwdGlHYWtHaGxZV1FBQUF2RUFBQUFNUUFBQURZU1lLZ09hR2hsWVFBQUMvZ0FBQUFnQUFBQUpBZmZBNUJvYlhSNEFBQU1HQUFBQUJzQUFBQllXQVAvOTJ4dlkyRUFBQXcwQUFBQUxnQUFBQzRucUNTT2JXRjRjQUFBREdRQUFBQWZBQUFBSUFFbUFJTnVZVzFsQUFBTWhBQUFBVVVBQUFKdFBsVCtmWEJ2YzNRQUFBM01BQUFBeFFBQUFRN3Q3VUFxZUp4allHUmdZT0Jpa0dQUVlXQjBjZk1KWWVCZ1lHR0FBSkFNWTA1bWVpSlFETW9EeXJHQWFRNGdab09JQWdDS0l3TlBBSGljWTJCa1lXQ2N3TURLd01IVXlYU0dnWUdoSDBJenZtWXdZdVJnWUdCaVlHVm13QW9DMGx4VEdCeWVTYno1eHR6d3Y0RWhocm1Cb1FFb3pBaVNBd0R4MXd6M2VKemxrazFLQTBFUWhWOVB4dmczL293NjRGSk1zaEd2a0lNa2tFVk1jb1RrY081eW1UY0RHY2d1Mi9ocW5naUM2QUdzNGh2b3BwaXVycThCbkFEb2lWZVJBNmxGUWdTMW03cjlIaTY2L1J6dldqOHBWY2RIRGpqaWxET3V1T0dXK3pxcnE2WnNocnR4ZXpnZXZ5b21xcGh6L1ZQRnI1RzZreUtmbFMvcTQzdEd4Um5PY1lrQ1Y3akdEVzVSNGc0Wkt2WDdvSHZkbzQ5VGRSKzM2djl4Mm4rSUlqNnArRnhWWWNpRVp3Nk1aZ3FPaktZTFRvem1ERTVOL0lrem85bURjeU1MNEp1UkQzQmhaQVpjR2prQ1YwYTJ3TFdSTjNCanV0NjJKdDRlOTBaV1VXY20zbTFkR1psR1V4bzVSek0wc28vZDJNUWJidzhHK1FkbmJXYXBBSGljalZkOWJCeEhGWiszYzdkN2QzdGY2OXVQKzc3ZFc5K3U3Mnp2bmUremNYTzJreERYYnBMbWc0U1FwbW9EYlExQ1RVQVFWMjFSaWhVRk5XMGlKVzBFb29IeUIwSGhqeVpWSXdGRkNOZHRDaFdJU0pWQVFrb2pwTFlVVUZ1Q0dsUzFGZmpXdkxsejBzUTBFdlo2M3B2ZjI1bDlNL1BlNzQwSlI4alNSWHFjMmtRaGFVSzhwbFVHUStBRk0yKzFvTm1xcVJxb1BOUnN5K1lGT3Z0UWxOL3AvbkViSC8xYU1PeUJxaEQ1ZW9TSDJ6eGh0Ky8zVTMwaE1XeEIrSzIzd2lBSGFTWU1FRnA4UzFUZ3dmbktnTlZQOElmaXQvNUQ3MFdoa21GeUx5RUZ0Vlp0MUczSFkrWUZXVlh3ajljb1ltTmNvKzV3UFpBOUNyVEcyRE1PS0JwUjIrSEszQmpVcXZocWxpcHltQXBaWUFLZE52TVJnSjhYakY4cElkTW9Gekw5WVMvd25CQlJqR0o3SkptcGpocUpBWS9YL1FmNEp2c29EeFNBRTdtK2xEakFqZnhycmVpSTV0b3hKeDNWU3Jua3BobHpkTXQyUi8yODJyaHYvMVQwSjZzTU5TdjVPRy95SzhsOHR1QUVZTllUMGtkTFpqMGJGaEwzSjhLTmtDYTY2OHBjME1kSC9GRWg3alhnUGNVamVNQlRBcjgzbENtTldjbkJUQ1lhbE83ZFVOMWNNOFBVeXhPQ3o5SmxEOUFZOFJHSkdLUkVSc250aExSa1BtL1ZtMVcxY1ZYQkJmS21rYmZhVUcvV0RPemZ6Q0N0NkYrYTJEMXg3YUVGVWVoTSt3SUJIL2VDSUM1ZStqVDBlbjMzY0hmZ1I4N0V4RjBURSs3YmUzMmk2R01OSnpwZGkvdlhmV3dFYXlCenpZcG52YlMwOUR0Y1Y0dEVTSlhjUXdoVTFReGM1MW5Cc3EwR3lxcW1zbDlGamtBWkVEUHpQSjU1RnhScUNHTXNkbi9OZk5lTVkyMXJIQm90TlFlcWx1VXdXQUJEeUtML1pDNHY5ck1XdUdnby9mUjMwdXVzY1o3M1VhSGlTMmRyNjlkdTJ2and3SzJHK3RoN25uZ29wUmFIUzg3a212SVczZThCL0JuMSswSWVLbGNuaTRXZGRVZUd1WUN2d09iQ3BpQW5icWwvNlNrUm85R1p6SXNSemdNNzlQcTZhbW1US2FhaW9STnFkbUtWbnBhVDZVQXdwUGtGcjA4WVMwbXFrdUJrUlJjOVJpbWVYVzlYU2xIY0FwWUUzQkxua2dyR2ZqZWlXN0ZtcStHQTNkSXdsc2VCRjhJZzhCRUlRd1Q0REM0UWRiU3lUUkVnRUIvUmZBRnVkWVZYeWxwZ3owaGx3TjVNK1dRajRmTUlmVU55VkhRY0VIUmxTS25WakxXNnd3ZEZNUmtDOWMzUlVJQnlkUytsWGszMWhmeUtNcmpuNVQzVFZjWHY1eE54RG53QUFtVytMWDFJejlNQTVpYUpaVUZyT2RCQS82cDRESVlrb0JOaFRMNnRreHNhYmJwd2JQS1I4cU93OVZENzFOMExMa3pObkIzZlVUNjQ4ZGdDclNPODdkRFlldkM2aEN6UCtVcHZUbHlUWUV1R2pYbUxzMk5IdzlrZDRNamRwOXFIWU51M3lvOU1IbHZ3UUx1eDRiWXRPSndHWVAzWUlmZTVSOHQxL043R2crVWQ0MmRuRmx6aXdUbC9TMzlCYnlGZUltTEdhSmdyTmFVbUdURlRNU1FUYW8xYXc0ZzFUTWxvVE0wZmNGK2RuNGZSQS9Ed2dYbjMxUU1IWVBUYjJNVWVqQzRlbjBlWW9hUTc1MS9vTXpUenlad3hOb0ZKdTdOQmQyYXFzTTljbkFYcjNPenNPZmQxN3BWellNMmVPemNMQWZmMVdYam0zR3lualVhdWJ4YnhYbDdQWWZ4L0UxbDFGWmttbnlNejVFRkNOTXlBdk4zQ3cyNDI2b0xOSW1CRVVNeEdUVUVLaXlrbXBzUVlyZU41QzNhWDRKRFZPS0hXOEs1TWZqYWtaZkk0UTAxWmFWeEpBSytQTzZzdFBXMUk4ZFdSV0ZnV1crMkZWc2FFMTJqU3NsSlNPQ21QaEp0R2FaVmR0bUdhZnVGR2ZsaG9BM2pqeFR2YTlJczNvNGpzY01PcUpxVm92MGRQeERRUnNqdHJhNFJCdUgyM0xHWXFtVVFpSFRIeUdiMWNURmVTdVlqNXdqV09nSCt2V3ZWVVFCbWMvdnVmZXhUaUM5eElJZDE2OFJKOW1hN0JVNUZKdXhkREdEemR3S0U5OXBQNUdJSmhEdk1GMlI5M0Q3TUtxd2Z1WUJpV0FTd1N5SkVjTEhTODNzN0NpNng5U1U0bUI1TEp2ZjVVM2gvMGNoNCtoVHNUbC91aUFTT1p6Y1JTRVRXL1pyRFl6dE0xVjBlOHVORHAzSjhxSnBQRkZBekdrcm8vSlBKeVZvN0Z6VlFzR3BXRG1xNVBhS0gwTGYzWlJpN0IwaHg5UDA5L1RDZHhGVmo4V2diR2tLRkVRSks3WnkrVm9kSHJNcmR0ekRWRTdxTGppeS9EekthK2V4NjRiMWZmRmtodGxINXdkdmZqZGpZaGJSYlcwME5OUHVvKzh0VTk5KytIaDJKQ3N5bkUzQVBmUDFJZU11LzhMQnlNOHQxdjRxYTl4SjNIQ0M3amJwa3NmNXQxQzFOWGtIRGZhcXg2T2xENEZNekdkK25FSFBmQXRsUi9mK3J3enloTU4rZWEwd0RUYm1BbDBzVFg0T0RXdlZ5aDJRK2VueDVlSXEwcGdLbldYSFBxL1A5QzNOYTl6QzFQMTdjSEtlQlphc1JrL3NYWUNiSUF4VDBRdXEzUlJidzMwYy9nSG12Y0NkYnVZNDA3M1FVS3JPM3MvVVJmeGs4WXc3bytiT3pMT1liaDVDN3BUaTduNkpjTUpveGV6bjlBajlMZ2RmNFlXU3hRZ3VGZzNtai9oMzZXTzQwZmluZDJ4N0dGWDhmMVhNSmR6WFR1TkdzN2Q2N0FhUkQwaWc2c2VSTnlJNmpscXJtVkdxZFhjc3Y3aGR6NUkrVE9QcExGQ3ZvWnJCaDVqSk5XczlidnJXcFpMQk9Dd1dPRlVGRmlYV3kySUc4eXI1aFo3ZG56Sm5TOUxiSWE0aUI5MTFwVm9Gb3M2dWZGRVJnR1IrbUxpcnc0NkY3NEx2eW1IUFRuamM3YW9WQkF6OE9aSng3UEdFWWFZaUFIVkYvRXo0ZUtSNCtBa3RLTnBMdm9kZ0t5UCt3UHB1VVBqbHdVQTBhZkJjQkVBZTlTSTJCbGl3Qm1kZ2pjNXlFN2tzUGl3cVBONU55ejJNMWkxeXNhK1JoY1hlTlIrZ0hkMzQzWGNUS0JhK1JabWErUGc0V1ZqNWV4eGxmWnBjL0dHcGhuWlZGck5hc0k0bVZCYlk1RHN3NmFXc1Y3YWgwSDVRVWNvTUYycGFuc2tlVXJ4VjNtbVlHQjQ2VUhTbWNNVVlQSHJtcFhycmQzdHNlakExR0lSaUpNdXU5SElySXM3OEUzcm1paWNRWkhIQjhZT0dQdUtzSUx5OHFWRzh6dUhmRklCS0k0RktYN1BzcnVtdjdtSVRTSjk1NGNHY0I3THNGRDBDUk1Od3dhVzhKMEt4akx1V2RnUjNMQUc0WWVsMUZEQkp1ZXhNT0RyTFo0b1NkcGZmSEM0Q2hlVUFacHZTczcwMUNaR2htWnFyeEk3MzduM1ZQY3U1RFRPaWMxM09tY3hzMmdyTURvVU9ma0VIdDNpSnNaR24ydFVLbE1WeXFkaitGRDkrbnZMWFBURXYwbDBpdXJUVjFXUlhjd0U1R1hrQmxNVnZlUnBMQitXR2JYVitRc05ESmZyeGtaYVpqMHk0ZWZveUFGWVhOUWtvSWYwZjBiNjB6cHZJMXdEd1cwZmtpL3NhbldVeW1oeng5MmQ0VWtLUVIzSUhUcnBsbDg4ZGFRZEJPWVhaYytYbnJUNDZNNS9QOGtqcjQ2b0xOTGtzYXpHTmViV0VEdHBnV1NsLzR3ZmRuOTArVjBld2hncUoyK0RLVmx2VE1QTFJyd0JZTyt4QnRQUHZsRzRwcldPUTEvZUtkM0o2T0VtME1lSUtBSk5wWlV2STIxTkc3SHN6dWV2ZnJBM0hXZC93S0ZVVzlUQUFBQWVKeGpZR1JnWUFEaXhPN2dpbmgrbTY4TTNDd01JSEI5d1NadUdQMy94LzhHRmc3bWFpQ1hnNEVKSkFvQVBqWUwyZ0FBQUhpY1kyQmtZR0J1K04vQUVNUEMrUC9IL3g4c0hBeEFFUlFnQmdDZ1B3WjJlSnhqWVdCZ1lFSEdqUC8vSTlob2NrVGgvejlBTkFDbDhRUlFBQUFBQUFBQU5nREFBU3dCdGdJRUFpNENXQUtDQXF3RFRnT3NBK1lFTkFSOEJNd0ZQZ1dvQmZvR1VBYUFCcG9BQUhpY1kyQmtZR0FRWXlobllHTUFBU1lnNWdKQ0JvYi9ZRDREQUJiRkFhb0FlSnhsajAxT3d6QVFoVi82QjZRU3FxaGdoK1FGWWdFby9SR3JibGhVYXZkZGROK21UcHNxaVNQSHJkUURjQjZPd0FrNEF0eUFPL0JJSjVzMmxzZmZ2SGxqVHdEYzRBY2VqdDh0OTVFOVhESTdjZzBYdUJldVUzOFFicEJmaEp0bzQxVzRSZjFOMk1jenBzSnRkR0Y1ZzllNFl2YUVkMkVQSFh3STEzQ05UK0U2OVMvaEJ2bGJ1SWs3L0FxMzBQSHF3ajdtWGxlNGpVY3Y5c2RXTDV4ZXFlVkJ4YUhKSXBNNXY0S1pYdStTaGEzUzZweHJXOFFtVTRPZ1gwbFRuV2xiM1ZQczEwUG5JaFZaazZvSnF6cEpqTXF0MmVyUUJSdm44bEd2RjRrZWhDYmxXR1ArdHNZQ2puRUZoU1VPakRGQ0dHU0l5dWpvTzFWbTlLK3hROEplZTFZOXplZDBXeFRVLzNPRkFRTDB6MXhUdXJMU2VUcFBnVDFmRzFKMWRDdHV5NTZVTkpGZXpVa1Nza0plMXJaVVF1b0JObVZYamhGNlhOR0pQeWhuU1A4QUNWcHV5QUFBQUhpY2JZekJVc0pBRUVTM2NaTkFBb0tnK0JVNVdCNzhIQXMyazJSa2FoZDJaeTM1ZTFPVml3ZmZxYnVydTgzQ3pOVG1mNDVZNEFFV0JVcFVXR0tGR2czVzJPQVJXK3p3aEQwT2VNWUxqbmcxdGc5ZTdUbElWd2tuYmJOc2trYStrSTR4NUdFc1dVL0N6a2JxZ3MyK0M3cytpN1RKUlNMZjBnOXI4eWVZUDRMWWtlUzZtdW9VaFQwZFB0N2V6M3p5WDN6anp6djdlL0REZXJvZGZPdklLOFY2TmtLOU5yT01QSXhxcC9HbHVyTFRIS204NWFDVWltL3VLQlJPUWlKamZnSCt4RVlSQUFBQScpIGZvcm1hdCgnd29mZicpLFxyXG4gIHVybChmb250cy9pY29uZm9udC50dGYpIGZvcm1hdCgndHJ1ZXR5cGUnKVxyXG59XHJcblxyXG4uaWNvbmZvbnQge1xyXG4gIGZvbnQtZmFtaWx5OlwiaWNvbmZvbnRcIiAhaW1wb3J0YW50O1xyXG4gIGZvbnQtc3R5bGU6bm9ybWFsO1xyXG4gIC13ZWJraXQtZm9udC1zbW9vdGhpbmc6IGFudGlhbGlhc2VkO1xyXG4gIC1tb3otb3N4LWZvbnQtc21vb3RoaW5nOiBncmF5c2NhbGU7XHJcbn1cclxuXHJcbi5pY29uLWZvbnQ6YmVmb3JlIHsgY29udGVudDogXCJcXEU2MThcIjsgfVxyXG5cclxuLmljb24tYm9sZDpiZWZvcmUgeyBjb250ZW50OiBcIlxcRTY3NVwiOyB9XHJcblxyXG4uaWNvbi1saXN0LXVsOmJlZm9yZSB7IGNvbnRlbnQ6IFwiXFxFQjNEXCI7IH1cclxuXHJcbi5pY29uLXN0cmlrZXRocm91Z2g6YmVmb3JlIHsgY29udGVudDogXCJcXEVDRjZcIjsgfVxyXG5cclxuLmljb24taXRhbGljOmJlZm9yZSB7IGNvbnRlbnQ6IFwiXFxFNzAyXCI7IH1cclxuXHJcbi5pY29uLXJlZG86YmVmb3JlIHsgY29udGVudDogXCJcXEU4MTFcIjsgfVxyXG5cclxuLmljb24tdW5kbzpiZWZvcmUgeyBjb250ZW50OiBcIlxcRTgyNFwiOyB9XHJcblxyXG4uaWNvbi1mdWxsLXNjcmVlbi1leGl0OmJlZm9yZSB7IGNvbnRlbnQ6IFwiXFxFNjIzXCI7IH1cclxuXHJcbi5pY29uLWZ1bGwtc2NyZWVuOmJlZm9yZSB7IGNvbnRlbnQ6IFwiXFxFNjI1XCI7IH1cclxuXHJcbi5pY29uLWxpc3Qtb2w6YmVmb3JlIHsgY29udGVudDogXCJcXEU2QzFcIjsgfVxyXG5cclxuLmljb24taGVscDpiZWZvcmUgeyBjb250ZW50OiBcIlxcRTY1OVwiOyB9XHJcblxyXG4uaWNvbi11bmRlcmxpbmU6YmVmb3JlIHsgY29udGVudDogXCJcXEU2NUFcIjsgfVxyXG5cclxuLmljb24tNzEzYmlhbmppcWlfeWlueW9uZzpiZWZvcmUgeyBjb250ZW50OiBcIlxcRTY1RFwiOyB9XHJcblxyXG4uaWNvbi1hbGlnbi1jZW50ZXI6YmVmb3JlIHsgY29udGVudDogXCJcXEU2NjFcIjsgfVxyXG5cclxuLmljb24tYWxpZ24tbGVmdDpiZWZvcmUgeyBjb250ZW50OiBcIlxcRTY2MlwiOyB9XHJcblxyXG4uaWNvbi1hbGlnbi1yaWdodDpiZWZvcmUgeyBjb250ZW50OiBcIlxcRTY2M1wiOyB9XHJcblxyXG4uaWNvbi1saW5rOmJlZm9yZSB7IGNvbnRlbnQ6IFwiXFxFNjY0XCI7IH1cclxuXHJcbi5pY29uLXBpY3R1cmU6YmVmb3JlIHsgY29udGVudDogXCJcXEU2NjVcIjsgfVxyXG5cclxuLmljb24tcXVvdGVzOmJlZm9yZSB7IGNvbnRlbnQ6IFwiXFxFNzE1XCI7IH1cclxuXHJcbi5pY29uLXZpZGVvOmJlZm9yZSB7IGNvbnRlbnQ6IFwiXFxFNkVGXCI7IH1cclxuXHJcbi5pY29uLWNsb3NlOmJlZm9yZSB7IGNvbnRlbnQ6IFwiXFxFNjc2XCI7IH1cclxuXHJcbiJdLCJzb3VyY2VSb290IjoiIn0=*/ -------------------------------------------------------------------------------- /dist/best-editor.min.css: -------------------------------------------------------------------------------- 1 | .best-editor-container { 2 | display: flex; 3 | flex-direction: column; } 4 | .best-editor-container.full-screen { 5 | position: fixed; 6 | z-index: 9999; 7 | top: 0; 8 | left: 0; 9 | right: 0; 10 | bottom: 0; 11 | width: 100% !important; 12 | height: 100% !important; 13 | background-color: #d9d9d9; } 14 | .best-editor-container.full-screen .best-editor { 15 | width: 60%; 16 | margin: 0 auto; 17 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); 18 | margin-top: 35px; 19 | margin-bottom: 20px; } 20 | .best-editor-container .best-editor-toolbar { 21 | background-color: #d9d9d9; 22 | border-bottom: 1px solid #ccc; 23 | user-select: none; 24 | box-sizing: border-box; } 25 | .best-editor-container .best-editor-toolbar ul { 26 | zoom: 1; 27 | list-style: none; 28 | word-break: break-all; } 29 | .best-editor-container .best-editor-toolbar ul li { 30 | list-style: none; 31 | float: left; } 32 | .best-editor-container .best-editor-toolbar ul li a { 33 | height: 39px; 34 | line-height: 39px; 35 | color: #595959; 36 | padding: 0 14px; 37 | display: inline-block; 38 | font-size: 16px; 39 | font-weight: bold; 40 | cursor: pointer; } 41 | .best-editor-container .best-editor-toolbar ul li a:hover { 42 | color: #f2f2f2; 43 | background-color: #595959; } 44 | .best-editor-container .best-editor-toolbar ul:after { 45 | content: "."; 46 | display: block; 47 | height: 0; 48 | clear: both; 49 | visibility: hidden; } 50 | .best-editor-container .best-editor { 51 | flex: 1; 52 | outline: none; 53 | padding: 30px; 54 | box-sizing: border-box; 55 | padding-top: 15px; 56 | overflow-y: auto; 57 | background: #fff; } 58 | .best-editor-container .best-editor p { 59 | margin: 15px 0; 60 | word-break: break-word; } 61 | .best-editor-container .best-editor h1, .best-editor-container .best-editor h2, .best-editor-container .best-editor h3, .best-editor-container .best-editor h4, .best-editor-container .best-editor h5, .best-editor-container .best-editor h6 { 62 | margin: 15px 0; } 63 | .best-editor-container .best-editor a { 64 | text-decoration: none; 65 | color: #3194d0; } 66 | .best-editor-container .best-editor blockquote { 67 | padding: 20px; 68 | background-color: #f2f2f2; 69 | border-left: 6px solid #b3b3b3; 70 | word-break: break-word; 71 | font-size: 16px; 72 | font-weight: 400; 73 | line-height: 30px; 74 | margin: 0 0 20px; } 75 | .best-editor-container .best-editor iframe { 76 | display: block; 77 | margin: 0 auto; } 78 | .best-editor-container .best-editor ul, .best-editor-container .best-editor ol { 79 | list-style-position: inside; 80 | margin: 15px 0; } 81 | .best-editor-container .best-editor .image-box { 82 | text-align: center; 83 | font-size: 0; 84 | margin: 15px 0; } 85 | .best-editor-container .best-editor .image-box > img { 86 | max-width: 100%; 87 | width: auto; 88 | height: auto; 89 | vertical-align: middle; 90 | border: 0; } 91 | .best-editor-container .best-editor .image-box .image-upload { 92 | width: 443px; 93 | padding: 5px 16px 5px 5px; 94 | margin: 0 auto; 95 | border: 1px solid #d9d9d9; 96 | overflow: hidden; 97 | font-size: 14px; 98 | -webkit-box-sizing: border-box; 99 | box-sizing: border-box; } 100 | .best-editor-container .best-editor .image-box .image-upload .preview-image { 101 | display: block; 102 | float: left; 103 | width: 90px; 104 | height: 90px; 105 | object-fit: cover; 106 | margin-right: 20px; } 107 | .best-editor-container .best-editor .image-box .image-upload .status-bar { 108 | display: block; 109 | float: right; 110 | width: 305px; } 111 | .best-editor-container .best-editor .image-box .image-upload .status-bar .upload-error-msg { 112 | color: #f50; } 113 | .best-editor-container .best-editor .image-box .image-upload .status-bar .status-area a { 114 | float: right; 115 | margin-left: 20px; 116 | cursor: pointer; 117 | color: #999; } 118 | .best-editor-container .best-editor .image-box .image-upload .status-bar .status-area .upload-btn-retry { 119 | display: none; } 120 | .best-editor-container .best-editor .image-box .image-upload .status-bar .uploading-icon { 121 | height: 3px; 122 | width: 305px; 123 | min-height: 3px; 124 | display: block; 125 | margin: 25px 0 20px; 126 | background: url(data:image/gif;base64,R0lGODlhMgEDAMQfACV79DaH+avH8bDK9rDJ7ajI8qvI7q3K8a/M92Oc7ih776/K9KrL9KbH8KbK8jV/7i9+7xhw8bjT+ICw8pLF+sHW9a3H8ajH8azJ8LPL9q3L9rPL7zB/8SV89zSH/f///yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTMyIDc5LjE1OTI4NCwgMjAxNi8wNC8xOS0xMzoxMzo0MCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUuNSAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2QTdFQzI3OUUyMUQxMUU2OEVGMUVFRTY0NzY1NUJEMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo2QTdFQzI3QUUyMUQxMUU2OEVGMUVFRTY0NzY1NUJEMyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjZBN0VDMjc3RTIxRDExRTY4RUYxRUVFNjQ3NjU1QkQzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjZBN0VDMjc4RTIxRDExRTY4RUYxRUVFNjQ3NjU1QkQzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEBQMAHwAsAAAAADIBAwAABZ6gJYyjZZ5oqq5s676wKlx0bZOzre987//AoNBXKBYaSKSxmGwsj8nLszmNLptOY66Gu+G2l6+XZKDhGoMBYo3IuN3puDwjr9vv+Lx+j6dr/oCBgoOEhYaHiImKi4FsCIKOj4CRkI6NlpdrlZGcnZ6fnH+OBQSlpqeoqaqrrK2ur7AYsrO0tba3uLm6u7y9vr/AwcAHwsIHxBilBwsNIQAh+QQFAwAfACwGAAAABQACAAAFBqAgikhZhgAh+QQFAwAfACwAAAAAAwADAAAFB+AkfeIgbiEAIfkEBQMAHwAsAAAAACsBAwAABUFg1wHAGCUZYXxs676tIM9wbd94ru987//AoHBILLIEgWTAE4CgNoQgYoowWq/YrHbL7e4gjzD48fSaz+i0ep0OAQAh+QQFAwAfACwEAAAAngADAAAFOuD3AV1pmlEiCWzrinAsz3Rt33iu77ztCiKPcEgETCoLjXLJZPae0Kh0+uR8INhslqNIVKjgsHgMDgEAIfkEBQMAHwAsBAAAAB8AAwAABSbg93ViaXZoqnbRU2xm4Jn059147nXBl5WLR80EKRqPEI7iIYCVQgAh+QQFAwAfACwEAAAAKAADAAAFJGAHAF1pnmiqolGQEYEnz3Rt33eXZBnHQcCgcEgsDjmKwGYTAgAh+QQFAwAfACwBAAAAOQADAAAFJ2DXASQgnmiqrmx7RolkBV5t33iu77zeJZUMZEgsGo/IpBLJgVUIIQAh+QQFAwAfACwGAAAA1QADAAAFR2D3jWRpnmiqjl3rvrDSVKsp3HWukze+/8Bg8EK8CC7CZM3DbDqfj9lit6hqlNisdqtDeLlcjnhMJneitOBhdWivwfC4nBQCACH5BAUDAB8ALAkAAABSAAMAAAUv4CeOZGmeaKqWXeu+sNJIRV2seK6rXu//wMdMQ/xwdiLOEcksKZ/QKAcglByumBAAIfkEBQMAHwAsUwAAABMAAwAABRVgJ45kCUBN5q1s63pBI3F0bd/AI4cAIfkEBQMAHwAsBgAAANMAAwAABUIgIIpfaZ7nCKBs675wLH9dbd949BDa7P/AoPAkKA5NgaNy2fI4n1BoJ7FBMK/YLAoShHC14BlnTC6bAY9qeM2GhQAAIfkEBQMAHwAsHQAAAO0AAwAABUYg8I1kaZ5oqq5sa3ZwLM9RUl2Xq++8m/e+j2Ao+AGPyKTS5Gk6n9DOpLKsWq9YFmfLyXqV3LCYW6N+z6iD+oD+rNXH9yEEACH5BAUDAB8ALBwAAADSAAMAAAU+4CeOZGmeaKqubJt2cCzL0dNkbq7v/Hp5vaBwuPMYj0hkJ1CQEJ/QqHRKVXGu2CwWAngYNtUnZozpHc5nVQgAIfkEBQMAHwAsAAAAAMkAAwAABUXgVgTR13Vfqq5sqwKwK890bd94Pp987wMKiuRy0RlbGUQAdWw6n9AozkOtWq+PhkSqy2wcAQB3TC6bU5y0es0GZLdnWggAIfkEBQMAHwAsAAAAAPIAAwAABW+gJYpEEURfqq5sC6hvK69AXc94ru9877edoHA4jDwMiF+uwWwof4LVYDrIZBCJzvMT2LYC4K53TC7vPOi0Ot0JGCTmz+JAX8RnmoV+Qej3NxQnYxCEEHeHiIk7HIyNjo4ARxl3IxZbGJiYOQycDCEAIfkEBQMAHwAsBAAAACsBAwAABXXgJ1gkKU0R8K1s67bdK890bd94ru955/9AYCQhMTQaNGTrwry4mpfCssmrWq+rwSDD5Z442LAnTC6bq560er3uJCqbwyI3n2m157zeRSBsNn4VEwo7HIZge4mKiziHjo+GQxUfJDQWNAeZBy+anZqMOJ5WnSEAIfkEBQMAHwAsBwAAAN0AAwAABXDgJ35WaUpJ9AEsML6iC8803N51/rZ67//AoHDUKRqPxsjjcxg1ntCodAp9Za6ZQQYlCwRenqF4TC6bz0GPes1edwKHzGtBr9vveDqB8CFs/oAoKjkQhRBoiImKi2Qcjo+QjwAPBhs1GJgYM5maIxghACH5BAUDAB8ALAcAAAAoAQMAAAVQ4CeOpGUaaDVFZOu+cCzPdG3feK67Xe//PsDjg9gZj8hb5pNpbg4blSJJrVqvWJ1ny+12Hw1JdjzemDeu81naIbvf8HiLQ6/b6wqwWM6vmUMAIfkEBQMAHwAsFAAAAB0BAwAABXCgJY5jRn2foqBs674sAAMybKP1l9987//AoFDYKRqPxsjDgBg6f4Vo9PnKWK9XyYkTCFC/4LB4TA56zuj0uRM4SDRlqmZ+cGZQzddmz9emxhCBgoJUg3GHiIkfHIyNjo0ADwQbHxiKTpZCmR8HdQchACH5BAUDAB8ALB0AAAAQAQMAAAVyoCWOljRFgKIq3we8LtzOdG3feK7vfO//wGCwQywai5GEBHMp0JyzglRaE1ittKtAaDNYM+BwpjJhBc47j5rLbrvf8DhPTa/XO0qEvqbpaxA9C3I4GhuGhxsmETocjRyDkJGSk3GOlpccSRIHnHCcnZIhACH5BAUDAB8ALCQAAADvAAMAAAVjoCUKRWFIU/StwOq+cCzPdG3feK7vfL93wKAwqKBIZqWkclnIOBHQDAriq1qv2Kx2W/N4v+DvoyE5uDTotHqt3rg3BDdK4YLY73eufs/v+z8cgYKDgQoPRisHZi4YGDCNji8hACH5BAUDAB8ALCcAAADiAAMAAAVT4CeMgmWe0qR8bOu+sAsAcc3Odq7vfO//wKCvQywaiZFE5TNoNjPQqITy4Aiv2Kx2y+36POCwGAyYVA6fDWvDbm+mH4XVS6/b73gfZ8/v85MVGCEAIfkEBQMAHwAsJwAAAAgBAwAABWGgJYpfaY6o4CSR6b4uUAIyDNNzbe8f7fM+HG9ILBqPyKTy1Wk6n81IQnJYwjCYjFYL23oHjInCSi6bz+i0muxpu9/tzhSxHm7u+PuqhYT4IX1/dYOEhYZEHImKi4kKU2shACH5BAUDAB8ALDkAAADyAAMAAAVaoCWOYzVFQKqmX+u+sNvFdN12OG7vfO//wKBw+MsZj5HAxmITZJ5QqGlGrFqv2Kx2i/V4v2BvJyHJ1BCLz2bNXpsAkLg8zg1C6vi8ft+CPB4QHIKDghFkBDshACH5BAUDAB8ALEIAAADrAAMAAAVSoCWOY5VEX/oBLKCmLfvOdA23dq7vfO//wKBQ2Ckaj8VIovLJOJ/PyqQzrFqv2Kx2y/V4v2BvZznYmM9nKSoFabtf7jZ3Tq/b75w8x6bv+5VMIQAh+QQFAwAfACxLAAAA5wADAAAFQqAljqNEddGnrmzrvnAsz3Rt33iu73vn/75IZkgkViifDm/JbDqf0OjSQ61SO5usVnvkKF4BjnRMLpvPOY56rY6EAAAh+QQFAwAfACxUAAAAeQADAAAFNaAljuRGddGnrmzrAm4sz3Rt3yug71nv/xLHp4MrGo/I5CrADHw20Ki04ggoOEoVZJvteoshACH5BAUDAB8ALAEAAACJAAMAAAU+4Cd+1mieaKqubOu+VizPVtY8EaDv/Pt1QGBmOPQZj8ikishkShiBjrK1qVan2Kz2Y+12JZiHAkIumyGvcwgAIfkEBQMAHwAsAQAAABEBAwAABVegIIpfaZ5oqq5s66Ij+bZWbdvCdWXXE5mAoHBILAZnyKRyyWy+hM6odIaoIqafjHa7HVQlmkAHSy6bz1iCmoBuu1mbuHwelxweChNkz+ej+oAQb4OEZiEAIfkEBQMAHwAsAgAAAJIAAwAABTZgIX5kaZ5oqq5s676wac10bVuZEETw4MfAoJCFGL4yyKRymZEgEhyjdEqtDjfYrHb7UERbjxAAIfkEBQMAHwAsAQAAABIBAwAABUvgJ36FMJ5oqq5s66pFXLx03Vp4ru/VFNnAD2BIDBqPyBZgBBiMnMmoVKWZWjPYrHbbe1hXgXDgSy6bz+i0ccNuu9s9hXpOT0LukBAAIfkEBQMAHwAskQAAACQAAwAABSOgJY5kaUlJBKxf675vJs90nVUJEOxw3waboHBI3OAivmQrBAAh+QQFAwAfACw2AAAAfwADAAAFO6AgCl9pnmiqrukosrBLwjRs3XieC0UhJRGEsEYsooRDo2nAZCqVmah0ShVWJoqndsvt1jbgsHgMvipCACH5BAUDAB8ALDUAAACUAAMAAAU3oPCNZGmeaKqOxeq+cAxbdG3fuDQpcu+Pg+DgRyzGMsikcrmsTB4fj3FKrVpXm6x2y9U6FZBPCAAh+QQFAwAfACwAAAAAJgEDAAAFY6ACKZP0nWiqrmzrpkVcvHRNy/Yqz3nv/yqLcEgsDjOCAADIbOYAUGgg8ChlnNgUArXNAgeIcPcnHnvPvox6zW6vJYgEB00HTqcfyKNqqvv/gB8Eg4GFKBuIiYqLiw8KhpAsIQAh+QQFAwAfACwAAAAAIgEDAAAFdSCkfEppnmh6Bs72vXAszy/zCnSuC3zv/z2dcEgsGo9Io6DAbDqfTckkkqxWO6+AdsvtermPhM0KGxw0GrIMwW673261fE6fIz7wvLsyGdX/Hx4PLw+FhoeIiQ8chQl3cwcHBICURy6VmJQbm5ydnpt8fplqIQAh+QQFAwAfACwZAAAACQEDAAAFdOAnKmRpnmgZBdTxWWIsz3Rc3Hiu63Xv/8CgcEgsGnWOpHKprEwiH4BRBKhar1hRYMvter9dTsAhGWSmMgR6zW67326EfE6vz50dOPAhevj/gIGCfwoPAxt6aAcLLmsLj4mRkmwblZaXmJZOUGsQnp+goB8hACH5BAUDAB8ALDQAAADcAAMAAAVboAKMZGmepEJJgvC9cCzPr0vfeK7vfO//wJ1jSCwahxrDIxL4eJ6eAHRKrT5Wg6B2y+16v16EeEwuiyWEQOfBgXDa77h8Llc8GhKwfs/v+2cbgYKDhIESGw8AIQAh+QQFAwAfACw1AAAA6wADAAAFZ6Aiil9pnugJrGzrvmuUSMJnpXiu73zvm4Jg8LcrEI9IlGPJbDodgsqkFKgGkh+PdsvterWciSSTwZrP54F6gG67dYi4fE5HZCqUzmO/T3L+gIGCg396YhtviYqLjIyIG5CRkpN4CiEAIfkEBQMAHwAsYwAAAM4AAwAABVngB4xkaZ5AFDTb9xVwLM9ubd94ru987//AoBA3KxYRhkfk42k6n9Coh5PQSFyIrHbLHXq/4LB4/EEcuOithBD4cN7wuHz+ViQyLbJ+z+/3N4CBgoMbaw8AIQAh+QQFAwAfACx6AAAAuAADAAAFQyAgjmRpAtFUfWzrvnD8CjQt33iu73zvy4UCreEpGo/IpKej+v0GUKhzSq1ae4gsosDper/gMAfQvJrP6LR6syFsGiEAIfkEBQMAHwAskAAAABcAAwAABRYgII5kWUaJ5K1s67rcJHF0bd829MghACH5BAUDAB8ALDoAAACBAAMAAAU04CeOZGmeaKqubOt+QCzP9BwlEvHufO//H49wSCwSObgMZLkEnphNpxTIqVqv2GvngfuEAAAh+QQFAwAfACwAAAAA+AADAAAFSeD0AV9pnmiqrmzrvnAsz3TNAniu73mUSIKgcEgc2lKUh+fIbDqf0KjNQ61arwEq4Ifoer9SVePDCZvP6LSZw267327FT93KhAAAIfkEBQMAHwAsAAAAABcBAwAABV+gII5kaZZVEn1s675wLM90bd94ru/8B/zAoPAXmUg+jqRyyXT0nqyBdLqoVqdS6wIrTQGg4LB4TC67POi0eo1+GDPmOGFOr9vv9tQqzu/7/zocgoOEhRwAbkdjG3wZIQAh+QQFAwAfACwZAAAA/gADAAAFY+AnjGRpnuiILVQQKV8sz3Rt33iu73zv/0AZYEgsGiOBz6FXCOIWUOhgOohKqVUr1prRBDpJp3hMLpvPH496zW6DPxI0kECv2+/4fH3TAsj/gIGCOhyFhoeIHABhORmOGXIbIQAh+QQFAwAfACw4AAAA3wADAAAFXaAgjmRpnmbBTEr7vXAsz3Rt33iu73z/AcCgcKiYSAQ+3GLAZC6ey+YA+pROoVLN6hEIJL/gsHi885jP6PTDmCHHCPC4fE6vzw8IyuPDcfv/gIEvHISFhodrEn8LIQAh+QQFAwAfACxaAAAAxAADAAAFYaBQjGNjNmSqrqkgTdGnKF9t33iu73zv/8BgEEAsGouRhAQj1GmeGoZ0Sq1ar6/OJxBoer/gsHjnKZvPZohSjCAc3m+MfE6v2+uEFwDCH/v/gIAcg4SFhAoJFT4ZNRuMOCEAIfkEBQMAHwAsegAAALIAAwAABVdgIY5kaZ7F4QSRonxwLM90bd94ru874P9AXyQhYdgaOSSMwWw6n9BoZtX5BHjYrHbLnXm+4PD3QezGDpi0es1uuzEbRgDwgZjv+DyPw+/7+QoJFTEbXSEAIfkEBQMAHwAsZQAAALwAAwAABWvgJ45kaZ5oWhZX415FLM/0vFFBpO587/9AEWBILAIiCYlIw9SUms5nU8qkVklQhnbL7Xq3EkegEyybz2aPes32QCaVz2E+L9Hro/vBTuf3SXcYgoOEhYaDGwgBAGiNjo8jHJKTlBwKCXEfIQAh+QQFAwAfACxqAAAAwgADAAAFdGAjfmQpjiV5pt91XuzZsHQq02uh6/K+n74NpRNRKGrIpHLJbCoB0GhUAZlICs6sFqnpdlleDdjLKJvD5rJXQiEFAtu4fE7z2O/3wINSOXwQdIFIB4SELIV+KYgHGI0Yi46NhWwfVBCCmJlIHJydnRB7FSUhACH5BAUDAB8ALFkAAADZAAMAAAVW4CeOZGmeaKqubOuSxdXMdG3PhxNEb+//J4BwKIwENgKgcslskjRQhnRKrTIQiETHyXV6vuBvJ7FZbDbdtLp7YBwW8Lh8ftgwAoq1vvXg+P9+AAkfBCEAIfkEBQMAHwAsxwAAAGsAAwAABT3gJ45kOTZoqq4CsVFPZM50bd/4B+xyTjLAoHC42GwcAY5vyWyKPJ5A57BYLq7YrHZxcFECCqfYqZxxzpEQACH5BAUDAB8ALOgAAAA+AAMAAAUpYCOOZHkJGdVFX+u+cCzPMGPfOK7tEhXQwKBwQSwajYdkL6AQOp+fRwgAIfkEBQMAHwAsAQAAACUBAwAABUzgJ45kaZ5oqq5s675wLM90/TZ4ruvFRnERmwnRIgptRlhShGgen9AoiiGNMa7YrGarYWgklE+nSi5DCQSzes2uLd7w+GFOBwcUUU4IACH5BAUDAB8ALAUBAAAQAAMAAAUYYCGKTdmMgpRESNtqsOYiVdIdeK7ndRQCACH5BAUDAB8ALBEBAAAOAAMAAAUXYFE0ZHOJBSYlEYJoMOy6a3fceE5UbAgAIfkEBQMAHwAsGwEAAA0AAwAABRZgcTVkU5wS9a1a2yJwRXHfYd+3rCghACH5BAUDAB8ALCQBAAALAAMAAAUWYFE0JLlR3YcgWqsxkvN1R20TVfMpIQAh+QQFAwAfACwGAAAALAEDAAAFOeAnjmRpnmiqrmzrvnAsz3Rt3/BV7MV1NYNgEEcsujQIo3LJbDplDCRiOi08r9isdsvtHr7fzeYSAgA7) 50% no-repeat; } 127 | 128 | .best-editor-dialog { 129 | position: fixed; 130 | top: 0; 131 | left: 0; 132 | right: 0; 133 | bottom: 0; 134 | z-index: 9999999999999; 135 | background-color: rgba(255, 255, 255, 0.7); } 136 | .best-editor-dialog .wrap { 137 | position: absolute; 138 | top: 50%; 139 | left: 50%; 140 | transform: translate(-50%, -50%); 141 | width: 412px; 142 | background-color: #fff; 143 | border-radius: 6px; 144 | -webkit-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); 145 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); 146 | padding: 16px; 147 | box-sizing: border-box; } 148 | .best-editor-dialog .wrap .head .close { 149 | text-align: right; } 150 | .best-editor-dialog .wrap .head .close a { 151 | cursor: pointer; 152 | font-size: 24px; 153 | color: #999; 154 | transition: color .3s ease; } 155 | .best-editor-dialog .wrap .head .close a:hover { 156 | color: #4d4d4d; } 157 | .best-editor-dialog .wrap .head h3 { 158 | font-size: 22px; 159 | padding-bottom: 26px; 160 | text-align: center; } 161 | .best-editor-dialog .wrap .body { 162 | padding: 15px 30px 30px; } 163 | .best-editor-dialog .wrap .body .upload-btn { 164 | position: relative; 165 | height: 42px; 166 | margin-bottom: 20px; 167 | background: #555; 168 | overflow: hidden; 169 | text-align: center; 170 | line-height: 42px; 171 | color: #fff; 172 | font-size: 14px; 173 | cursor: pointer; } 174 | .best-editor-dialog .wrap .body .upload-btn input { 175 | position: absolute; 176 | top: -12000px; 177 | right: 0; 178 | left: 0; } 179 | .best-editor-dialog .wrap .body .input-box { 180 | display: flex; 181 | margin-bottom: 20px; } 182 | .best-editor-dialog .wrap .body .input-box > div { 183 | height: 42px; 184 | border: 1px solid #ccc; 185 | box-sizing: border-box; 186 | line-height: 42px; } 187 | .best-editor-dialog .wrap .body .input-box .icon-box { 188 | text-align: center; 189 | background-color: #eee; 190 | width: 38px; 191 | color: #595959; } 192 | .best-editor-dialog .wrap .body .input-box .input { 193 | border-left: 0; 194 | flex: 1; } 195 | .best-editor-dialog .wrap .body .input-box .input input { 196 | border: 0; 197 | outline: none; 198 | width: 99%; 199 | border-left: 0; 200 | box-sizing: border-box; 201 | padding: 0 10px; 202 | color: #595959; } 203 | .best-editor-dialog .wrap .body .switch-box { 204 | color: #888; 205 | cursor: pointer; 206 | font-size: 14px; 207 | padding-bottom: 10px; 208 | text-align: center; } 209 | .best-editor-dialog .wrap .body .waring-txt { 210 | height: 20px; 211 | line-height: 20px; 212 | color: #bc6351; 213 | font-size: 14px; 214 | margin-bottom: 5px; } 215 | .best-editor-dialog .wrap .body .btn-box { 216 | font-size: 14px; 217 | text-align: right; 218 | height: 30px; 219 | line-height: 20px; 220 | user-select: none; 221 | color: #595959; } 222 | .best-editor-dialog .wrap .body .btn-box > span { 223 | display: inline-block; 224 | transition: color .3s ease; 225 | cursor: pointer; 226 | padding: 4px 12px; 227 | font-size: 14px; 228 | font-weight: 500; } 229 | .best-editor-dialog .wrap .body .btn-box .cancel:hover { 230 | color: #000; } 231 | .best-editor-dialog .wrap .body .btn-box .confirm { 232 | color: #42c02e; 233 | background-color: #fff; 234 | border: 1px solid #42c02e; 235 | border-radius: 15px; 236 | margin-left: 15px; } 237 | 238 | 239 | @font-face {font-family: "iconfont"; 240 | src: url(fonts/iconfont.eot); /* IE9*/ 241 | src: url(fonts/iconfont.eot#iefix) format('embedded-opentype'), 242 | url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'), 243 | url(fonts/iconfont.ttf) format('truetype') 244 | } 245 | 246 | .iconfont { 247 | font-family:"iconfont" !important; 248 | font-style:normal; 249 | -webkit-font-smoothing: antialiased; 250 | -moz-osx-font-smoothing: grayscale; 251 | } 252 | 253 | .icon-font:before { content: "\E618"; } 254 | 255 | .icon-bold:before { content: "\E675"; } 256 | 257 | .icon-list-ul:before { content: "\EB3D"; } 258 | 259 | .icon-strikethrough:before { content: "\ECF6"; } 260 | 261 | .icon-italic:before { content: "\E702"; } 262 | 263 | .icon-redo:before { content: "\E811"; } 264 | 265 | .icon-undo:before { content: "\E824"; } 266 | 267 | .icon-full-screen-exit:before { content: "\E623"; } 268 | 269 | .icon-full-screen:before { content: "\E625"; } 270 | 271 | .icon-list-ol:before { content: "\E6C1"; } 272 | 273 | .icon-help:before { content: "\E659"; } 274 | 275 | .icon-underline:before { content: "\E65A"; } 276 | 277 | .icon-713bianjiqi_yinyong:before { content: "\E65D"; } 278 | 279 | .icon-align-center:before { content: "\E661"; } 280 | 281 | .icon-align-left:before { content: "\E662"; } 282 | 283 | .icon-align-right:before { content: "\E663"; } 284 | 285 | .icon-link:before { content: "\E664"; } 286 | 287 | .icon-picture:before { content: "\E665"; } 288 | 289 | .icon-quotes:before { content: "\E715"; } 290 | 291 | .icon-video:before { content: "\E6EF"; } 292 | 293 | .icon-close:before { content: "\E676"; } 294 | 295 | 296 | -------------------------------------------------------------------------------- /dist/fonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zc9/best-editor/a9c2a6c5df297f5691da65e4b71e5a03ba93b809/dist/fonts/iconfont.eot -------------------------------------------------------------------------------- /dist/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zc9/best-editor/a9c2a6c5df297f5691da65e4b71e5a03ba93b809/dist/fonts/iconfont.ttf -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "best-editor", 3 | "version": "0.0.4", 4 | "description": "best-editor 一款简洁实用的web富文本编辑器", 5 | "homepage": "https://github.com/zc9/best-editor", 6 | "author": { 7 | "name": "zc9", 8 | "url": "https://github.com/zc9" 9 | }, 10 | "keywords": [ 11 | "best-editor", 12 | "bestEditor", 13 | "editor", 14 | "编辑器", 15 | "web富文本编辑器" 16 | ], 17 | "main": "dist/best-editor.js", 18 | "maintainers": [ 19 | { 20 | "name": "zc9", 21 | "web": "https://github.com/zc9", 22 | "mail": "zouchao911@163.com" 23 | } 24 | ], 25 | "repositories": [ 26 | { 27 | "type": "git", 28 | "url": "https://github.com/zc9/best-editor" 29 | } 30 | ], 31 | "scripts": { 32 | "build": "webpack --mode=production", 33 | "dev": "webpack --mode=development --progress --colors --watch", 34 | "test": "echo \"Error: no test specified\" && exit 1" 35 | }, 36 | "license": "MIT", 37 | "devDependencies": { 38 | "babel-core": "^6.26.3", 39 | "babel-loader": "^7.1.5", 40 | "babel-preset-env": "^1.7.0", 41 | "css-loader": "^1.0.0", 42 | "file-loader": "^1.1.11", 43 | "html-loader": "^0.5.5", 44 | "mini-css-extract-plugin": "^0.4.1", 45 | "node-sass": "^4.9.2", 46 | "sass-loader": "^7.1.0", 47 | "style-loader": "^0.21.0", 48 | "uglifyjs-webpack-plugin": "^1.2.7", 49 | "webpack": "^4.16.4", 50 | "webpack-cli": "^3.1.0" 51 | }, 52 | "dependencies": { 53 | "babel-polyfill": "^6.26.0", 54 | "mito": "^1.0.5" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/assets/iconfont.css: -------------------------------------------------------------------------------- 1 | 2 | @font-face {font-family: "iconfont"; 3 | src: url('iconfont.eot?t=1534759179951'); /* IE9*/ 4 | src: url('iconfont.eot?t=1534759179951#iefix') format('embedded-opentype'), /* IE6-IE8 */ 5 | url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'), 6 | url('iconfont.ttf?t=1534759179951') format('truetype') 7 | } 8 | 9 | .iconfont { 10 | font-family:"iconfont" !important; 11 | font-style:normal; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | .icon-font:before { content: "\e618"; } 17 | 18 | .icon-bold:before { content: "\e675"; } 19 | 20 | .icon-list-ul:before { content: "\eb3d"; } 21 | 22 | .icon-strikethrough:before { content: "\ecf6"; } 23 | 24 | .icon-italic:before { content: "\e702"; } 25 | 26 | .icon-redo:before { content: "\e811"; } 27 | 28 | .icon-undo:before { content: "\e824"; } 29 | 30 | .icon-full-screen-exit:before { content: "\e623"; } 31 | 32 | .icon-full-screen:before { content: "\e625"; } 33 | 34 | .icon-list-ol:before { content: "\e6c1"; } 35 | 36 | .icon-help:before { content: "\e659"; } 37 | 38 | .icon-underline:before { content: "\e65a"; } 39 | 40 | .icon-713bianjiqi_yinyong:before { content: "\e65d"; } 41 | 42 | .icon-align-center:before { content: "\e661"; } 43 | 44 | .icon-align-left:before { content: "\e662"; } 45 | 46 | .icon-align-right:before { content: "\e663"; } 47 | 48 | .icon-link:before { content: "\e664"; } 49 | 50 | .icon-picture:before { content: "\e665"; } 51 | 52 | .icon-quotes:before { content: "\e715"; } 53 | 54 | .icon-video:before { content: "\e6ef"; } 55 | 56 | .icon-close:before { content: "\e676"; } 57 | 58 | -------------------------------------------------------------------------------- /src/assets/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zc9/best-editor/a9c2a6c5df297f5691da65e4b71e5a03ba93b809/src/assets/iconfont.eot -------------------------------------------------------------------------------- /src/assets/iconfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Created by iconfont 9 | 10 | 11 | 12 | 13 | 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 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/assets/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zc9/best-editor/a9c2a6c5df297f5691da65e4b71e5a03ba93b809/src/assets/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zc9/best-editor/a9c2a6c5df297f5691da65e4b71e5a03ba93b809/src/assets/iconfont.woff -------------------------------------------------------------------------------- /src/core/best-editor.js: -------------------------------------------------------------------------------- 1 | import $ from '../core/dom'; 2 | import Toolbar from '../core/toolbar'; 3 | import Handler from '../core/handler'; 4 | import Selection from '../core/selection'; 5 | import Request from '../core/request'; 6 | 7 | class BestEditor { 8 | constructor (container, opts = {}) { 9 | this.config = {}; 10 | this.selection = new Selection(); 11 | var $container = $(container); 12 | this.toolbar = new Toolbar(opts.toolbar); 13 | var $toolbar = this.toolbar.$elem; 14 | this.$toolbar = $toolbar; 15 | $container.append($toolbar); 16 | $container.addClass('best-editor-container'); 17 | this.$container = $container; 18 | if (opts.imageUpload) { 19 | this.config.imageUpload = opts.imageUpload; 20 | } 21 | if (opts.imageLinkUpload) { 22 | this.config.imageLinkUpload = opts.imageLinkUpload; 23 | } 24 | //create editor 25 | var $editor = $(document.createElement('div')); 26 | $editor.attr('contenteditable', true); 27 | $editor.addClass('best-editor'); 28 | $container.append($editor); 29 | $editor.append('


'); 30 | this.$editor = $editor; 31 | 32 | this.handler = new Handler(this); 33 | 34 | this._saveSelectionRealTime(); 35 | 36 | this._handleKeyDownEvent(); 37 | 38 | this._handleKeyUpEvent(); 39 | 40 | this._handleTabEvent(); 41 | 42 | this._handlePasteEvent(); 43 | 44 | this._handleCmd(); 45 | 46 | 47 | console.log('BestEditor Created'); 48 | } 49 | 50 | //handle toolbar cmd 51 | _handleCmd () { 52 | var _sel = window.getSelection(); 53 | var _this = this; 54 | 55 | this.toolbar.$elem.find('[data-cmd]').bind('mousedown', function (event) { 56 | _this.selection.save(); 57 | var cmd = $(this).attr('data-cmd'); 58 | var cmdValue = $(this).attr('data-cmd-value'); 59 | 60 | console.log('command:', cmd, cmdValue); 61 | var cmdHandle = _this.handler.getHandle(cmd); 62 | if (cmdHandle) { 63 | cmdHandle(event); 64 | } else { 65 | _this.handler.execCommand(cmd, cmdValue); 66 | } 67 | event.preventDefault(); 68 | }) 69 | } 70 | 71 | addHandle (cmd, handle) { 72 | if (cmd && handle) { 73 | this.handler.addHandle(cmd, handle); 74 | } 75 | } 76 | getHTML() { 77 | return this.$editor.html(); 78 | } 79 | //save the editor selection in real time 80 | _saveSelectionRealTime () { 81 | var _this = this; 82 | function _saveSelection() { 83 | _this.selection.save(); 84 | } 85 | this.$editor.bind('keyup', _saveSelection) 86 | this.$editor.bind('mousedown', function (event) { 87 | _this.$editor.bind('mouseleave', _saveSelection) 88 | }) 89 | this.$editor.bind('mouseup', function (event) { 90 | _saveSelection(); 91 | _this.$editor.unbind('mouseleave', _saveSelection); 92 | }) 93 | 94 | } 95 | 96 | //handle the editor keyup event 97 | _handleKeyUpEvent () { 98 | var _this = this; 99 | this.$editor.bind('keyup', function (event) { 100 | 101 | //handle the editor enter key event 102 | if(event.keyCode === 13) { 103 | var selectionElem = _this.selection.getContainerElement(); 104 | var $parentElem = $(selectionElem).parent(); 105 | if (!$parentElem.equal(_this.$editor)) { 106 | return; 107 | } 108 | 109 | var tagName = selectionElem.tagName.toUpperCase(); 110 | if (tagName === 'P') { 111 | return; 112 | } else { 113 | var text = selectionElem.innerHTML.replace(/<.*?>/g, () => ''); 114 | var $p = $('


'); 115 | $p.insertBefore(selectionElem); 116 | $p.html(text); 117 | _this.selection.createRangeByElement($p[0]); 118 | _this.selection.restore(); 119 | $(selectionElem).remove(); 120 | } 121 | } 122 | if (event.keyCode === 8) { 123 | var txtHtml = _this.$editor.html().toLowerCase().trim(); 124 | if (!txtHtml || txtHtml === '
') { 125 | var $p = $('


') 126 | _this.$editor.html(''); 127 | _this.$editor.append($p); 128 | _this.selection.createRangeByElement($p[0], false, true); 129 | _this.selection.restore() 130 | } 131 | } 132 | }) 133 | } 134 | //handle the editor keydown event 135 | _handleKeyDownEvent () { 136 | var _this = this; 137 | this.$editor.bind('keydown', function (event) { 138 | 139 | //handle the editor backspace key event 140 | if (event.keyCode === 8) { 141 | if ($(this).html().trim() == '


') { 142 | event.preventDefault(); 143 | } 144 | } 145 | if (event.keyCode !== 13) { 146 | var selectionElem = _this.selection.getContainerElement(); 147 | var $selectionElem = $(selectionElem); 148 | if ($selectionElem.hasClass('image-box')) { 149 | event.preventDefault(); 150 | if (event.keyCode === 8) { 151 | _this.selection.createRangeByElement(selectionElem); 152 | _this.selection.delete(); 153 | } 154 | } 155 | } 156 | 157 | }); 158 | } 159 | //handle the editor tab key event 160 | _handleTabEvent () { 161 | var _this = this; 162 | this.$editor.bind('keydown', function (event) { 163 | if (event.keyCode !== 9) { 164 | return; 165 | } 166 | var selectionElem = _this.selection.getContainerElement(); 167 | if (!selectionElem) { 168 | return; 169 | } 170 | _this.handler.insertHTML('    '); 171 | event.preventDefault(); 172 | 173 | }); 174 | } 175 | //handle the editor paste event 176 | _handlePasteEvent () { 177 | this.$editor.bind('paste', (e) => { 178 | e.preventDefault(); 179 | this.handler.getHandle('paste')(e); 180 | }); 181 | } 182 | 183 | } 184 | export default BestEditor; -------------------------------------------------------------------------------- /src/core/dom.js: -------------------------------------------------------------------------------- 1 | class D { 2 | constructor (selector) { 3 | this.length = 0; 4 | this.selector = null; 5 | if (typeof selector === 'string') { 6 | if (/^ this[i] = d); 17 | this.length = doms.length; 18 | } 19 | this.selector = selector || ''; 20 | 21 | } else if (selector && typeof selector === 'object') { 22 | if (selector instanceof D) { 23 | for (var i = 0; i < selector.length; i++) { 24 | this[i] = selector[i]; 25 | this.length++; 26 | } 27 | } else if (selector && selector.length) { 28 | var doms = selector; 29 | doms.forEach((d, i) => this[i] = d); 30 | this.length = doms.length; 31 | } else { 32 | this[0] = selector; 33 | this.length++; 34 | } 35 | this.selector = selector; 36 | } 37 | } 38 | 39 | attr (prop, value = null) { 40 | if (!value) { 41 | return this.length ? this[0].getAttribute(prop) : ''; 42 | } else { 43 | for (var i = 0; i < this.length; i++) { 44 | this[i].setAttribute(prop, value); 45 | } 46 | } 47 | 48 | } 49 | 50 | val (val) { 51 | if (val) { 52 | for (var i = 0; i < this.length; i++) { 53 | this[i].value = val; 54 | } 55 | } else { 56 | return this.length ? this[0].value : ''; 57 | } 58 | } 59 | 60 | focus () { 61 | for (var i = 0; i < this.length; i++) { 62 | this[i].focus(); 63 | } 64 | } 65 | 66 | html (htmlStr = null) { 67 | if (!htmlStr) { 68 | return this.length ? this[0].innerHTML : ''; 69 | } else { 70 | for (var i = 0; i < this.length; i++) { 71 | this[i].innerHTML = htmlStr; 72 | } 73 | } 74 | } 75 | text (text = null) { 76 | if (!text) { 77 | return this.length ? this[0].innerText : ''; 78 | } else { 79 | for (var i = 0; i < this.length; i++) { 80 | this[i].innerText = text; 81 | } 82 | } 83 | } 84 | height (height = null) { 85 | if (!height) { 86 | return this.length ? this[0].getBoundingClientRect().height : null; 87 | } else { 88 | for (var i = 0; i < this.length; i++) { 89 | this[i].style.height = height + 'px'; 90 | } 91 | } 92 | } 93 | 94 | width (width = null) { 95 | if (!width) { 96 | return this.length ? this[0].getBoundingClientRect().width : null; 97 | } else { 98 | for (var i = 0; i < this.length; i++) { 99 | this[i].style.width = height + 'px'; 100 | } 101 | } 102 | } 103 | 104 | find (selector) { 105 | for (var i = 0; i < this.length; i++) { 106 | var slice = Array.prototype.slice; 107 | var doms = slice.apply(this[i].querySelectorAll(selector)); 108 | if (doms.length) { 109 | return new D(doms); 110 | } 111 | } 112 | return new D(null); 113 | } 114 | 115 | append (dom) { 116 | if (typeof dom === 'string') { 117 | for (var i = 0; i < this.length; i++) { 118 | this[i].insertAdjacentHTML('beforeend', dom); 119 | } 120 | } else if (dom instanceof D) { 121 | for (var i = 0; i < this.length; i++) { 122 | for (var j = 0; j < dom.length; j++) { 123 | this[i].appendChild(dom[j]); 124 | } 125 | } 126 | } else { 127 | for (var i = 0; i < this.length; i++) { 128 | this[i].appendChild(dom); 129 | } 130 | } 131 | } 132 | 133 | hide () { 134 | for (var i = 0; i < this.length; i++) { 135 | this[i].style.display = 'none'; 136 | } 137 | } 138 | 139 | show () { 140 | for (var i = 0; i < this.length; i++) { 141 | this[i].style.display = 'block'; 142 | } 143 | } 144 | 145 | parent () { 146 | return this.length ? new D(this[0].parentNode) : new D(null); 147 | } 148 | 149 | insertBefore (selector) { 150 | var $beforeElem = new D(selector); 151 | if ($beforeElem.length) { 152 | var beforeElem = $beforeElem[0]; 153 | var parent = beforeElem.parentNode; 154 | for (var i = 0; i < this.length; i++) { 155 | parent.insertBefore(this[i], beforeElem); 156 | } 157 | } 158 | } 159 | 160 | insertAfter (selector) { 161 | var $afterElem = new D(selector); 162 | if ($afterElem.length) { 163 | var afterElem = $afterElem[0]; 164 | var parent = afterElem.parentNode; 165 | for (var i = 0; i < this.length; i++) { 166 | if (parent.lastChild === afterElem) { 167 | parent.appendChild(this[i]); 168 | } else { 169 | parent.insertBefore(this[i], afterElem.nextSibling); 170 | } 171 | } 172 | } 173 | } 174 | 175 | equal ($elem) { 176 | if (!this.length) { 177 | return false; 178 | } 179 | if ($elem.nodeType === 1) { 180 | return this[0] === $elem; 181 | } else { 182 | return this[0] === $elem[0]; 183 | } 184 | } 185 | 186 | remove () { 187 | for (var i = 0; i < this.length; i++) { 188 | var elem = this[i]; 189 | if (elem.remove) { 190 | elem.remove(); 191 | } else { 192 | var parent = elem.parentElement; 193 | parent && parent.removeChild(elem); 194 | } 195 | } 196 | 197 | } 198 | 199 | bind (event, handler) { 200 | for (var i = 0; i < this.length; i++) { 201 | this[i].addEventListener(event, function (evt) { 202 | handler.call(evt.currentTarget, evt); 203 | }); 204 | } 205 | } 206 | unbind (event, handler) { 207 | for (var i = 0; i < this.length; i++) { 208 | this[i].removeEventListener(event, handler); 209 | } 210 | } 211 | addClass (className) { 212 | for (var i = 0; i < this.length; i++) { 213 | var classArr = []; 214 | var elem = this[i]; 215 | if (elem.className) { 216 | classArr = elem.className.split(' '); 217 | } 218 | var classArr1 = className.split(' '); 219 | classArr.push.apply(classArr, classArr1); 220 | elem.className = classArr.join(' '); 221 | } 222 | } 223 | 224 | removeClass (className) { 225 | for (var i = 0; i < this.length; i++) { 226 | var elem = this[i]; 227 | var classArr = []; 228 | if (elem.className) { 229 | classArr = elem.className.split(' '); 230 | } 231 | classArr = classArr.filter(item => { 232 | item = item.trim(); 233 | if (!item || item === className) { 234 | return false; 235 | } 236 | return true; 237 | }); 238 | elem.className = classArr.join(' '); 239 | } 240 | } 241 | 242 | hasClass (className) { 243 | for (var i = 0; i < this.length; i++) { 244 | var elem = this[i]; 245 | var classArr = []; 246 | if (elem.className) { 247 | classArr = elem.className.split(' '); 248 | } 249 | if (classArr.indexOf(className) !== -1) { 250 | return true; 251 | } 252 | } 253 | return false; 254 | } 255 | } 256 | 257 | export default function (selector) { 258 | return new D(selector); 259 | }; -------------------------------------------------------------------------------- /src/core/handle/image-handle.js: -------------------------------------------------------------------------------- 1 | import $ from '../dom'; 2 | import imageDialogTpl from '../../ui/image-dialog.html'; 3 | import imageUploadTpl from '../../ui/image-upload.html'; 4 | import mito from 'mito'; 5 | import Request from '../../core/request'; 6 | class ImageHandle { 7 | constructor (context) { 8 | this.context = context; 9 | } 10 | do () { 11 | this.type = 1; 12 | this._create(); 13 | this._bindEvent(); 14 | } 15 | _create () { 16 | this.$elem = $(imageDialogTpl); 17 | $('body').append(this.$elem); 18 | } 19 | _bindEvent () { 20 | var _this = this; 21 | var $uploadBtn = this.$elem.find('.upload-btn'); 22 | var $inputBox = this.$elem.find('.input-box'); 23 | var $confirm = this.$elem.find('.confirm'); 24 | 25 | this.$elem.find('.close').bind('click', function (event) { 26 | _this._destroy(); 27 | }) 28 | this.$elem.find('.cancel').bind('click', function (event) { 29 | _this._destroy(); 30 | }) 31 | 32 | this.$elem.find('.switch-box').bind('click', function (event) { 33 | 34 | if (_this.type === 1) { 35 | $(this).text('或上传本地图片'); 36 | $inputBox[0].style.display = 'flex'; 37 | $uploadBtn.hide(); 38 | $confirm[0].style.display = 'inline-block'; 39 | _this.type = 2; 40 | } else { 41 | $inputBox.hide(); 42 | $uploadBtn.show(); 43 | $(this).text('或选择网络图片'); 44 | $confirm.hide(); 45 | _this.type = 1; 46 | } 47 | }); 48 | var $linkInput = this.$elem.find('#linkInput'); 49 | 50 | var $waringTxt = this.$elem.find('.waring-txt'); 51 | 52 | $confirm.bind('click', function (event) { 53 | var link = $linkInput.val(); 54 | if (!link.length) { 55 | $waringTxt.text('链接不能为空'); 56 | } else { 57 | _this._destroy(); 58 | _this._insertImage(2, [link], null); 59 | } 60 | }); 61 | var fileInput = this.$elem.find('input')[0]; 62 | 63 | this.$elem.find('.upload-btn').bind('click', (event) => { 64 | var fileInput = this.$elem.find('input')[0]; 65 | fileInput.click(); 66 | fileInput.onchange = (evt) => { 67 | fileInput.val = ''; 68 | var files = evt.target.files; 69 | var i = 0; 70 | var images = []; 71 | var _this = this; 72 | function loadFile () { 73 | if (i >= files.length) { 74 | _this._destroy(); 75 | _this._insertImage(1, images, files); 76 | return; 77 | } 78 | 79 | var file = files[i++]; 80 | var reader = new FileReader(); 81 | 82 | reader.readAsDataURL(file); 83 | reader.onload = () => { 84 | var data = reader.result; 85 | images.push(data); 86 | loadFile(); 87 | } 88 | } 89 | loadFile(); 90 | 91 | } 92 | }); 93 | 94 | } 95 | 96 | _uploadImage (type, $imageBox, image) { 97 | var config = this.context.bestEditor.config; 98 | var $uploadErrorMsg = $imageBox.find('.upload-error-msg'); 99 | var request = new Request(); 100 | var _this = this; 101 | function _upload() { 102 | if (type === 1) { 103 | if (config.imageUpload) { 104 | var formData = new FormData(); 105 | formData.append('file', image); 106 | request.post(config.imageUpload, formData) 107 | .then(function (data) { 108 | if (data.code == 0) { 109 | $imageBox.find('.image-upload').remove(); 110 | $imageBox.append(`
`); 111 | } 112 | 113 | }) 114 | .catch (function (status, msg) { 115 | $uploadErrorMsg.text('网络异常!'); 116 | }) 117 | } 118 | } else if (type === 2) { 119 | if (config.imageLinkUpload) { 120 | request.get(config.imageLinkUpload + '?imageUrl=' + image) 121 | .then(function (data) { 122 | if (data.code == 0) { 123 | $imageBox.find('.image-upload').remove(); 124 | $imageBox.append(`
`); 125 | } 126 | 127 | }) 128 | .catch (function (status, msg) { 129 | $uploadErrorMsg.text('网络异常!'); 130 | }) 131 | } 132 | } 133 | } 134 | 135 | _upload(); 136 | //cancel upload 137 | $imageBox.find('.upload-btn-cancel').bind('click', function (event) { 138 | console.log('cancel upload!'); 139 | $imageBox.remove(); 140 | request.abort(); 141 | }) 142 | 143 | //retry upload 144 | $imageBox.find('.upload-btn-retry').bind('click', function (event) { 145 | $uploadErrorMsg.text('正在上传'); 146 | _upload(); 147 | }) 148 | } 149 | 150 | //upload images 151 | _uploadImages (type, $imageBoxArr, images) { 152 | for (var i = 0; i < $imageBoxArr.length; i++) { 153 | var $imageBox = $imageBoxArr[i]; 154 | var image; 155 | if (!images && type === 2) { 156 | image = $imageBox.find('.image-upload img')[0].src; 157 | } else { 158 | image = images[i]; 159 | } 160 | this._uploadImage(type, $imageBox, image); 161 | } 162 | } 163 | 164 | //insert image tag to editor 165 | _insertImage (type, images, files) { 166 | 167 | var selectionElem = this.context.bestEditor.selection.getContainerElement(); 168 | var config = this.context.bestEditor.config; 169 | if (/^p$/i.test(selectionElem.tagName)) { 170 | 171 | var curRange = this.context.bestEditor.selection.getCurrentRange(); 172 | 173 | var text = selectionElem.innerText.trim(); 174 | var text1 = text.substring(0, curRange.startOffset); 175 | var text2 = text.substr(curRange.startOffset); 176 | if (text1.length > 0) { 177 | selectionElem.innerText = text1; 178 | } 179 | 180 | var afterElem = selectionElem; 181 | var $imageBoxArr = []; 182 | var $imageBox; 183 | for (var image of images) { 184 | if (type === 2 && !config.imageLinkUpload) { 185 | $imageBox = $(`

`); 186 | $imageBox.insertAfter(afterElem); 187 | afterElem = $imageBox[0]; 188 | this.context.bestEditor.selection.createRangeByElement($imageBox[0], false, true); 189 | this.context.bestEditor.selection.restore(); 190 | } else { 191 | var imageUpload = mito(imageUploadTpl)({imageUrl: image}); 192 | $imageBox = $(`
`); 193 | $imageBox.append(imageUpload); 194 | $imageBox.insertAfter(afterElem); 195 | afterElem = $imageBox[0]; 196 | $imageBoxArr.push($imageBox); 197 | } 198 | } 199 | if (text.length === 0) { 200 | $(selectionElem).remove(); 201 | } 202 | if (text2.length > 0) { 203 | var $p = $(`

${text2}

`) 204 | $p.insertAfter($imageBox); 205 | this.context.bestEditor.selection.createRangeByElement($p[0], false); 206 | this.context.bestEditor.selection.restore(); 207 | } else { 208 | var $p = $('


'); 209 | $p.insertAfter($imageBox); 210 | this.context.bestEditor.selection.createRangeByElement($p[0], false); 211 | this.context.bestEditor.selection.restore(); 212 | } 213 | if (type === 1 || config.imageLinkUpload) { 214 | this._uploadImages(type, $imageBoxArr, type === 1 ? files : images); 215 | } 216 | } else { 217 | // var $imageBoxArr = []; 218 | // for (var image of images) { 219 | // var imageUpload = mito(imageUploadTpl)({imageUrl: image}); 220 | // var $imageBox = $(`
`); 221 | // $imageBox.append(imageUpload); 222 | // var range = this.context.bestEditor.selection.getCurrentRange(); 223 | // range.insertNode($imageBox[0]); 224 | // //this.context.insertHTML($imageBox[0].outerHTML); 225 | // $imageBoxArr.push($imageBox); 226 | // // console.log($imageBox.parent().remove()); 227 | // } 228 | // this._uploadImages(type, $imageBoxArr, type === 1 ? files : images); 229 | } 230 | console.log('insertImage') 231 | } 232 | 233 | _destroy () { 234 | this.$elem.remove(); 235 | this.context.bestEditor.selection.restore(); 236 | } 237 | 238 | } 239 | export default ImageHandle; -------------------------------------------------------------------------------- /src/core/handle/link-handle.js: -------------------------------------------------------------------------------- 1 | import $ from '../dom'; 2 | import linkDialogTpl from '../../ui/link-dialog.html'; 3 | 4 | class LinkHandle { 5 | constructor (context) { 6 | this.context = context; 7 | } 8 | do () { 9 | 10 | this._create(); 11 | this.bindEvent(); 12 | } 13 | _create () { 14 | this.$elem = $(linkDialogTpl); 15 | $('body').append(this.$elem); 16 | this.selectionElem = null; 17 | } 18 | bindEvent () { 19 | var _this = this; 20 | 21 | var $confirm = this.$elem.find('.confirm'); 22 | 23 | this.$elem.find('.close').bind('click', function (event) { 24 | _this._destroy(); 25 | }) 26 | this.$elem.find('.cancel').bind('click', function (event) { 27 | _this._destroy(); 28 | }) 29 | 30 | 31 | var $linkInput = this.$elem.find('#linkInput'); 32 | var $linkText = this.$elem.find('#linkText'); 33 | var $waringTxt = this.$elem.find('.waring-txt'); 34 | 35 | var selectionElem = this.context.bestEditor.selection.getContainerElement(); 36 | 37 | if (selectionElem) { 38 | if (/^a$/i.test(selectionElem.tagName)) { 39 | this.selectionElem = selectionElem; 40 | $linkText.val(selectionElem.innerText); 41 | $linkInput.val(selectionElem.href); 42 | } else { 43 | $linkText.val(this.context.bestEditor.selection.getText()); 44 | } 45 | } 46 | 47 | $confirm.bind('click', function (event) { 48 | 49 | var link = $linkInput.val(); 50 | var linkText = $linkText.val(); 51 | if (!link.length) { 52 | $waringTxt.text('链接地址不能为空'); 53 | } else if (!linkText.length) { 54 | $waringTxt.text('链接文本不能为空'); 55 | } else { 56 | _this._destroy(); 57 | _this._insertLink(link, linkText); 58 | } 59 | }) 60 | } 61 | 62 | _insertLink (link, linkText) { 63 | 64 | if (this.selectionElem) { 65 | this.context.bestEditor.selection.createRangeByElement(this.selectionElem); 66 | this.context.bestEditor.selection.delete(); 67 | } 68 | this.context.bestEditor.selection.restore(); 69 | this.context.insertHTML(`${linkText}`) 70 | 71 | } 72 | 73 | _destroy () { 74 | this.$elem.remove(); 75 | this.context.bestEditor.selection.restore(); 76 | } 77 | 78 | } 79 | export default LinkHandle; -------------------------------------------------------------------------------- /src/core/handle/list-handle.js: -------------------------------------------------------------------------------- 1 | import $ from '../dom'; 2 | class ListHandle { 3 | constructor (context) { 4 | this.context = context; 5 | } 6 | handleUnOrderList () { 7 | this._handleList('unorder'); 8 | } 9 | 10 | handleOrderList () { 11 | this._handleList('order'); 12 | } 13 | 14 | _handleList (flag) { 15 | if (flag === 'unorder') { 16 | this.context.execCommand('insertUnorderedList'); 17 | } else { 18 | this.context.execCommand('insertOrderedList'); 19 | } 20 | this.context.bestEditor.selection.save(); 21 | 22 | var bestEditor = this.context.bestEditor; 23 | 24 | //fix ul wrapper 25 | var selectionElem = bestEditor.selection.getContainerElement(); 26 | console.log(selectionElem) 27 | var $selectionElem = $(selectionElem); 28 | if (/^li$/i.test(selectionElem.tagName)) { 29 | $selectionElem = $selectionElem.parent(); 30 | } 31 | if (!/^ol|ul$/i.test($selectionElem[0].tagName)) { 32 | return; 33 | } 34 | var $parent = $selectionElem.parent() 35 | if ($parent.equal(bestEditor.$editor)) { 36 | return; 37 | } 38 | $selectionElem.insertAfter($parent); 39 | $parent.remove(); 40 | 41 | } 42 | } 43 | export default ListHandle; -------------------------------------------------------------------------------- /src/core/handle/paste-handle.js: -------------------------------------------------------------------------------- 1 | import imageUploadTpl from '../../ui/image-upload.html'; 2 | import mito from 'mito'; 3 | import $ from '../dom'; 4 | import ImageHandle from './image-handle'; 5 | 6 | class PasteHandle { 7 | constructor (context) { 8 | this.inlineTags = ['label', 'i', 'em', 'span', 'strike', 'u', 'a', 'input', 'font', 'br', 'strong', 'select', 'textarea', 'b']; 9 | this.context = context; 10 | this.imageHandle = new ImageHandle(context); 11 | } 12 | getPasteText (e) { 13 | var clipboardData = e.clipboardData || (e.originalEvent && e.originalEvent.clipboardData); 14 | var pasteText; 15 | if (clipboardData == null) { 16 | pasteText = window.clipboardData && window.clipboardData.getData('text'); 17 | } else { 18 | pasteText = clipboardData.getData('text/plain'); 19 | } 20 | return pasteText; 21 | } 22 | 23 | getPasteHTML (e, filterStyle, ignoreImg) { 24 | var clipboardData = e.clipboardData || (e.originalEvent && e.originalEvent.clipboardData); 25 | var pasteHTML, pasteText; 26 | if (clipboardData == null) { 27 | pasteText = window.clipboardData && window.clipboardData.getData('text'); 28 | } else { 29 | pasteHTML = clipboardData.getData('text/html'); 30 | pasteText = clipboardData.getData('text/plain') 31 | } 32 | 33 | if (!pasteHTML && pasteText) { 34 | this.contentType = 1; 35 | pasteHTML = '

' + this._replaceHtmlSymbol(pasteText) + '

'; 36 | return pasteHTML; 37 | } 38 | if (!pasteHTML) { 39 | return; 40 | } 41 | 42 | pasteHTML = pasteHTML.replace(/<(meta|script|link).+?>/igm, ''); 43 | pasteHTML = pasteHTML.replace(//mg, '') 44 | pasteHTML = pasteHTML.replace(/\s?data-.+?=('|").+?('|")/igm, ''); 45 | pasteHTML = pasteHTML.replace(/<\/?(body|html)>/igm, ''); 46 | 47 | 48 | if (ignoreImg) { 49 | pasteHTML = pasteHTML.replace(//igm, ''); 50 | } 51 | if (filterStyle) { 52 | pasteHTML = pasteHTML.replace(/\s?(class|style)=('|").*?('|")/igm, ''); 53 | } else { 54 | pasteHTML = pasteHTML.replace(/\s?class=('|").*?('|")/igm, ''); 55 | } 56 | pasteHTML = this._optimizeHTML(pasteHTML); 57 | return pasteHTML; 58 | } 59 | do (e) { 60 | 61 | var selectionElem = this.context.bestEditor.selection.getContainerElement(); 62 | var text = selectionElem.innerText.trim(); 63 | var html = this.getPasteHTML(e, true, false); 64 | 65 | if (this.contentType === 1) { 66 | this.context.insertHTML(html); 67 | return; 68 | } 69 | if (text.length === 0) { 70 | $(selectionElem).remove(); 71 | } 72 | this.context.insertHTML(html); 73 | 74 | if (this.context.bestEditor.config.imageLinkUpload) { 75 | var $imageBoxs = this.context.bestEditor.$editor.find('.image-box'); 76 | var $imageBoxsArr = []; 77 | if ($imageBoxs.elems.length > 0) { 78 | for (var imageBox of $imageBoxs.elems) { 79 | $imageBoxsArr.push($(imageBox)); 80 | } 81 | } 82 | if ($imageBoxsArr.length > 0) { 83 | this.imageHandle._uploadImages(2, $imageBoxsArr); 84 | } 85 | } 86 | 87 | } 88 | _hasBlockTag (elem) { 89 | for (var i = 0; i < elem.children.length; i++) { 90 | var child = elem.children[i]; 91 | var nodeName = child.nodeName.toLowerCase(); 92 | if (this.inlineTags.indexOf(nodeName) === -1) { 93 | return true; 94 | } 95 | } 96 | return false; 97 | } 98 | _getElementStr (elem) { 99 | var strArr = []; 100 | for (var i = 0; i < elem.childNodes.length; i++) { 101 | var node = elem.childNodes[i]; 102 | if (node.nodeType === 3) { 103 | var text = node.nodeValue.trim(); 104 | if (text.length > 0) { 105 | strArr.push(text); 106 | } 107 | 108 | } else if (node.nodeType === 1) { 109 | var nodeName = node.nodeName.toLowerCase(); 110 | if (this.inlineTags.indexOf(nodeName) !== -1 && !this._hasBlockTag(node)) { 111 | if (node.innerText.length > 0) { 112 | strArr.push(node.outerHTML); 113 | } 114 | } 115 | } 116 | } 117 | if (strArr.length > 0) { 118 | var nodeName = elem.nodeName.toLowerCase(); 119 | if (nodeName === 'div') { 120 | nodeName = 'p'; 121 | } 122 | return '<' + nodeName + '>' + strArr.join('') + ''; 123 | } 124 | return ''; 125 | } 126 | 127 | _optimizeDom (elem) { 128 | var strArr = []; 129 | var str = this._getElementStr(elem); 130 | if (str.length > 0) { 131 | strArr.push(str); 132 | } 133 | for (var i = 0; i < elem.children.length; i++) { 134 | var child = elem.children[i]; 135 | var nodeName = child.nodeName.toLowerCase(); 136 | if (this.inlineTags.indexOf(nodeName) === -1 || this._hasBlockTag(child)) { 137 | if (nodeName === 'img') { 138 | if (!this.context.bestEditor.config.imageLinkUpload) { 139 | strArr.push(`

`); 140 | } else { 141 | var imageUpload = mito(imageUploadTpl)({imageUrl: child.src}); 142 | strArr.push(`
${imageUpload}
`); 143 | } 144 | } else { 145 | str = this._optimizeDom(child); 146 | if (str.length > 0) { 147 | strArr.push(str); 148 | } 149 | } 150 | } 151 | } 152 | return strArr.join(''); 153 | } 154 | 155 | 156 | _optimizeHTML (html) { 157 | var divElem = document.createElement('div'); 158 | divElem.innerHTML = html; 159 | return this._optimizeDom(divElem); 160 | } 161 | 162 | _replaceHtmlSymbol (html) { 163 | return html.replace(//gm, '>') 165 | .replace(/"/gm, '"') 166 | .replace(/(\r\n|\r|\n)/g, '
'); 167 | } 168 | } 169 | export default PasteHandle; -------------------------------------------------------------------------------- /src/core/handle/video-handle.js: -------------------------------------------------------------------------------- 1 | import $ from '../dom'; 2 | import videoDialogTpl from '../../ui/video-dialog.html'; 3 | 4 | class ImageHandle { 5 | constructor (context) { 6 | this.context = context; 7 | } 8 | do () { 9 | this.type = 1; 10 | this._create(); 11 | this.bindEvent(); 12 | } 13 | _create () { 14 | this.$elem = $(videoDialogTpl); 15 | $('body').append(this.$elem); 16 | } 17 | bindEvent () { 18 | var _this = this; 19 | var $uploadBtn = this.$elem.find('.upload-btn'); 20 | var $inputBox = this.$elem.find('.input-box'); 21 | var $confirm = this.$elem.find('.confirm'); 22 | 23 | this.$elem.find('.close').bind('click', function (event) { 24 | _this._destroy(); 25 | }) 26 | this.$elem.find('.cancel').bind('click', function (event) { 27 | _this._destroy(); 28 | }) 29 | 30 | 31 | var $linkInput = this.$elem.find('#linkInput'); 32 | 33 | var $waringTxt = this.$elem.find('.waring-txt'); 34 | 35 | $confirm.bind('click', function (event) { 36 | var link = $linkInput.val(); 37 | if (!link.length) { 38 | $waringTxt.text('视频链接不能为空'); 39 | } else { 40 | _this._destroy(); 41 | _this._insertVideo(link); 42 | } 43 | }) 44 | 45 | } 46 | 47 | _insertVideo (link) { 48 | console.log('_insertVideo'); 49 | this.context.execCommand('insertHTML', link); 50 | } 51 | 52 | _destroy () { 53 | this.$elem.remove(); 54 | this.context.bestEditor.selection.restore(); 55 | } 56 | 57 | } 58 | export default ImageHandle; -------------------------------------------------------------------------------- /src/core/handler.js: -------------------------------------------------------------------------------- 1 | import $ from '../core/dom'; 2 | import ListHandle from './handle/list-handle'; 3 | import ImageHandle from './handle/image-handle'; 4 | import LinkHandle from './handle/link-handle'; 5 | import VideoHandle from './handle/video-handle'; 6 | import PasteHandle from './handle/paste-handle'; 7 | 8 | class Handler { 9 | constructor (bestEditor) { 10 | this.bestEditor = bestEditor; 11 | var listHandle = new ListHandle(this); 12 | var imageHandle = new ImageHandle(this); 13 | var linkHandle = new LinkHandle(this); 14 | var videoHandle = new VideoHandle(this); 15 | var pasteHandle = new PasteHandle(this); 16 | this.handleMap = { 17 | 'insertUnorderedList': listHandle.handleUnOrderList.bind(listHandle), 18 | 'insertOrderedList': listHandle.handleOrderList.bind(listHandle), 19 | 'image': imageHandle.do.bind(imageHandle), 20 | 'link': linkHandle.do.bind(linkHandle), 21 | 'video': videoHandle.do.bind(videoHandle), 22 | 'paste': pasteHandle.do.bind(pasteHandle), 23 | 'fullscreen': this.handleFullScreen.bind(this), 24 | } 25 | 26 | } 27 | 28 | addHandle (cmd, handle) { 29 | this.handleMap[cmd] = handle; 30 | } 31 | 32 | //handle full screen 33 | handleFullScreen (event) { 34 | var $elem = $(event.currentTarget); 35 | var $i = $elem.find('i'); 36 | if (this.bestEditor.$container.hasClass('full-screen')) { 37 | this.bestEditor.$container.removeClass('full-screen'); 38 | $i.addClass('icon-full-screen'); 39 | $elem.attr('title', '全屏'); 40 | $i.removeClass('icon-full-screen-exit'); 41 | } else { 42 | this.bestEditor.$container.addClass('full-screen'); 43 | $i.removeClass('icon-full-screen'); 44 | $i.addClass('icon-full-screen-exit'); 45 | $elem.attr('title', '退出全屏'); 46 | } 47 | this.bestEditor.$editor[0].focus(); 48 | this.bestEditor.selection.restore(); 49 | } 50 | 51 | getHandle (cmd) { 52 | return this.handleMap[cmd]; 53 | } 54 | 55 | execCommand (cmd, value = null) { 56 | if (value) { 57 | document.execCommand(cmd, false, value); 58 | } else { 59 | document.execCommand(cmd, false, null); 60 | } 61 | } 62 | 63 | queryCommandSupported (name) { 64 | return document.queryCommandSupported(name) 65 | } 66 | 67 | insertHTML (html) { 68 | var sel, range; 69 | if (window.getSelection) { 70 | // IE9 and non-IE 71 | sel = window.getSelection(); 72 | if (sel.getRangeAt && sel.rangeCount) { 73 | range = sel.getRangeAt(0); 74 | range.deleteContents(); 75 | 76 | // Range.createContextualFragment() would be useful here but is 77 | // only relatively recently standardized and is not supported in 78 | // some browsers (IE9, for one) 79 | var el = document.createElement('div'); 80 | el.innerHTML = html; 81 | var frag = document.createDocumentFragment(), node, lastNode; 82 | while ( (node = el.firstChild) ) { 83 | lastNode = frag.appendChild(node); 84 | } 85 | range.insertNode(frag); 86 | // Preserve the selection 87 | if (lastNode) { 88 | range = range.cloneRange(); 89 | range.setStartAfter(lastNode); 90 | range.collapse(true); 91 | sel.removeAllRanges(); 92 | sel.addRange(range); 93 | } 94 | } 95 | } else if (document.selection && document.selection.type != 'Control') { 96 | // IE < 9 97 | document.selection.createRange().pasteHTML(html); 98 | } 99 | } 100 | } 101 | export default Handler; -------------------------------------------------------------------------------- /src/core/request.js: -------------------------------------------------------------------------------- 1 | class Request { 2 | 3 | constructor () { 4 | this.xmlHttp = null; 5 | } 6 | 7 | _getXMLHttpRequest () { 8 | return new XMLHttpRequest(); 9 | } 10 | 11 | get (url) { 12 | return new Promise((resolve, reject) => { 13 | var xmlHttp = this._getXMLHttpRequest(); 14 | this.xmlHttp = xmlHttp; 15 | xmlHttp.open('get', url, true); 16 | xmlHttp.send(); 17 | xmlHttp.onreadystatechange = function () { 18 | if (xmlHttp.readyState === 4) { 19 | if (xmlHttp.status === 200) { 20 | resolve(JSON.parse(xmlHttp.responseText)); 21 | } else { 22 | reject(xmlHttp.status, xmlHttp.statusText); 23 | } 24 | } 25 | } 26 | }); 27 | } 28 | 29 | post (url, data) { 30 | return new Promise((resolve, reject) => { 31 | var xmlHttp = this._getXMLHttpRequest(); 32 | this.xmlHttp = xmlHttp; 33 | xmlHttp.open('post', url, true); 34 | xmlHttp.send(data); 35 | xmlHttp.onreadystatechange = function () { 36 | if (xmlHttp.readyState === 4) { 37 | if (xmlHttp.status === 200) { 38 | resolve(JSON.parse(xmlHttp.responseText)); 39 | } else { 40 | reject(xmlHttp.status, xmlHttp.statusText); 41 | } 42 | } 43 | } 44 | }); 45 | } 46 | 47 | abort () { 48 | if (this.xmlHttp) { 49 | this.xmlHttp.abort(); 50 | } 51 | } 52 | } 53 | export default Request; -------------------------------------------------------------------------------- /src/core/selection.js: -------------------------------------------------------------------------------- 1 | class Selection { 2 | constructor () { 3 | this._curRange = null; 4 | this._context = window.getSelection(); 5 | console.log(this._context) 6 | } 7 | 8 | save (range) { 9 | 10 | if (range) { 11 | this._curRange = range; 12 | return; 13 | } 14 | 15 | var selection = this._context; 16 | if (selection.rangeCount === 0) { 17 | return; 18 | } 19 | 20 | range = selection.getRangeAt(0); 21 | this._curRange = range; 22 | } 23 | 24 | getCurrentRange () { 25 | return this._curRange; 26 | } 27 | 28 | restore () { 29 | var selection = this._context; 30 | selection.removeAllRanges(); 31 | selection.addRange(this._curRange); 32 | } 33 | 34 | getText () { 35 | var range = this._curRange; 36 | if (range) { 37 | return this._curRange.toString(); 38 | } else { 39 | return ''; 40 | } 41 | } 42 | 43 | getContainerElement (range) { 44 | range = range || this._curRange; 45 | if (range) { 46 | var elem = range.commonAncestorContainer; 47 | return elem.nodeType === 1 ? elem : elem.parentNode; 48 | } 49 | return null; 50 | } 51 | getStartElement (range) { 52 | range = range || this._curRange; 53 | if (range) { 54 | var elem = range.startContainer; 55 | return elem.nodeType === 1 ? elem : elem.parentNode; 56 | } 57 | return null; 58 | } 59 | getEndElement (range) { 60 | range = range || this._curRange; 61 | if (range) { 62 | var elem = range.endContainer; 63 | return elem.nodeType === 1 ? elem : elem.parentNode; 64 | } 65 | return null; 66 | } 67 | 68 | createRangeByElement (elem, toStart = null, isContent = false) { 69 | var range = document.createRange(); 70 | if (isContent) { 71 | range.selectNodeContents(elem); 72 | } else { 73 | range.selectNode(elem); 74 | } 75 | if (typeof toStart === 'boolean') { 76 | range.collapse(toStart); 77 | } 78 | this.save(range); 79 | } 80 | 81 | delete () { 82 | var range = this._curRange; 83 | if (range) { 84 | range.deleteContents(); 85 | this.save(); 86 | } 87 | } 88 | 89 | selectRange (range) { 90 | this._context.removeAllRanges(); 91 | this._context.addRange(range); 92 | } 93 | 94 | } 95 | export default Selection; -------------------------------------------------------------------------------- /src/core/toolbar.js: -------------------------------------------------------------------------------- 1 | import toolbarTpl from '../ui/toolbar.html'; 2 | import $ from '../core/dom'; 3 | import mito from 'mito'; 4 | const DEFAULT_TOOLS = { 5 | bold: { 6 | cmd: 'bold', 7 | title: '粗体', 8 | icon: '' 9 | }, 10 | italic: { 11 | cmd: 'italic', 12 | title: '斜体', 13 | icon: '' 14 | }, 15 | underline: { 16 | cmd: 'underline', 17 | title: '下划线', 18 | icon: '' 19 | }, 20 | strikethrough: { 21 | cmd: 'strikethrough', 22 | title: '删除线', 23 | icon: '' 24 | }, 25 | 26 | link: { 27 | cmd: 'link', 28 | title: '插入链接', 29 | icon: '' 30 | }, 31 | image: { 32 | cmd: 'image', 33 | title: '插入图片', 34 | icon: '' 35 | }, 36 | video: { 37 | cmd: 'video', 38 | title: '插入视频', 39 | icon: '' 40 | }, 41 | unorderlist: { 42 | cmd: 'insertUnorderedList', 43 | title: '无序列表', 44 | icon: '' 45 | }, 46 | orderlist: { 47 | cmd: 'insertOrderedList', 48 | title: '有序列表', 49 | icon: '' 50 | }, 51 | h1: { 52 | cmd: 'formatBlock', 53 | value: '

', 54 | title: '标题1', 55 | icon: 'H1' 56 | }, 57 | h2: { 58 | cmd: 'formatBlock', 59 | value: '

', 60 | title: '标题2', 61 | icon: 'H2' 62 | }, 63 | h3: { 64 | cmd: 'formatBlock', 65 | value: '

', 66 | title: '标题3', 67 | icon: 'H3' 68 | }, 69 | h4: { 70 | cmd: 'formatBlock', 71 | value: '

', 72 | title: '标题4', 73 | icon: 'H4' 74 | }, 75 | alignLeft: { 76 | cmd: 'justifyLeft', 77 | title: '左对齐', 78 | icon: '' 79 | }, 80 | alignCenter: { 81 | cmd: 'justifyCenter', 82 | title: '居中对齐', 83 | icon: '' 84 | }, 85 | alignRight: { 86 | cmd: 'justifyRight', 87 | title: '右对齐', 88 | icon: '' 89 | }, 90 | undo: { 91 | cmd: 'undo', 92 | title: '撤销', 93 | icon: '' 94 | }, 95 | redo: { 96 | cmd: 'redo', 97 | title: '重做', 98 | icon: '' 99 | }, 100 | full: { 101 | cmd: 'fullscreen', 102 | title: '全屏', 103 | icon: '' 104 | } 105 | } 106 | class Toolbar { 107 | constructor (tools = null) { 108 | var toolbarStr = null; 109 | if (tools) { 110 | if (typeof tools === 'string') { 111 | toolbarStr = tools; 112 | } else if (tools instanceof Array) { 113 | var customTools = {}; 114 | for (var tool of tools) { 115 | if (typeof tool === 'string') { 116 | customTools[tool] = DEFAULT_TOOLS[tool]; 117 | } else if (typeof tool === 'object') { 118 | for (var k in tool) { 119 | customTools[tool] = tool[k]; 120 | } 121 | } 122 | } 123 | toolbarStr = mito(toolbarTpl)({tools: customTools}); 124 | } else if (typeof tools === 'object') { 125 | toolbarStr = mito(toolbarTpl)({tools: tools}); 126 | } 127 | } else { 128 | toolbarStr = mito(toolbarTpl)({tools: DEFAULT_TOOLS}); 129 | } 130 | this.$elem = $(toolbarStr); 131 | } 132 | } 133 | export default Toolbar; -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import './scss/main.scss'; 2 | import 'babel-polyfill'; 3 | import BestEditor from './core/best-editor'; 4 | import './assets/iconfont.css'; 5 | module.exports = BestEditor; -------------------------------------------------------------------------------- /src/scss/main.scss: -------------------------------------------------------------------------------- 1 | .best-editor-container { 2 | display: flex; 3 | flex-direction: column; 4 | &.full-screen { 5 | position: fixed; 6 | z-index: 9999; 7 | top: 0; 8 | left: 0; 9 | right: 0; 10 | bottom: 0; 11 | width: 100% !important; 12 | height: 100% !important; 13 | background-color: #d9d9d9; 14 | .best-editor { 15 | width: 60%; 16 | margin: 0 auto; 17 | box-shadow: 0 0 20px rgba(0, 0, 0, .1); 18 | margin-top: 35px; 19 | margin-bottom: 20px; 20 | } 21 | } 22 | .best-editor-toolbar { 23 | background-color: #d9d9d9; 24 | border-bottom: 1px solid #ccc; 25 | user-select: none; 26 | box-sizing: border-box; 27 | ul { 28 | zoom:1; 29 | list-style: none; 30 | word-break: break-all; 31 | li { 32 | list-style: none; 33 | float: left; 34 | a { 35 | height: 39px; 36 | line-height: 39px; 37 | color: #595959; 38 | padding: 0 14px; 39 | display: inline-block; 40 | font-size: 16px; 41 | font-weight: bold; 42 | cursor: pointer; 43 | &:hover { 44 | color:#f2f2f2; 45 | background-color:#595959 46 | } 47 | } 48 | } 49 | &:after{ 50 | content: "."; 51 | display: block; 52 | height: 0; 53 | clear: both; 54 | visibility: hidden; 55 | } 56 | } 57 | } 58 | .best-editor { 59 | flex: 1; 60 | outline: none; 61 | padding: 30px; 62 | box-sizing: border-box; 63 | padding-top: 15px; 64 | overflow-y: auto; 65 | background: #fff; 66 | p { 67 | margin: 15px 0; 68 | word-break: break-word; 69 | } 70 | h1, h2, h3, h4, h5, h6 { 71 | margin: 15px 0; 72 | } 73 | a { 74 | text-decoration: none; 75 | color: #3194d0; 76 | } 77 | blockquote { 78 | padding: 20px; 79 | background-color: #f2f2f2; 80 | border-left: 6px solid #b3b3b3; 81 | word-break: break-word; 82 | font-size: 16px; 83 | font-weight: 400; 84 | line-height: 30px; 85 | margin: 0 0 20px; 86 | } 87 | iframe { 88 | display: block; 89 | margin: 0 auto; 90 | } 91 | ul, ol { 92 | list-style-position: inside; 93 | margin: 15px 0; 94 | } 95 | 96 | .image-box { 97 | text-align: center; 98 | font-size: 0; 99 | margin: 15px 0; 100 | > img { 101 | max-width: 100%; 102 | width: auto; 103 | height: auto; 104 | vertical-align: middle; 105 | border: 0; 106 | } 107 | .image-upload { 108 | width: 443px; 109 | padding: 5px 16px 5px 5px; 110 | margin: 0 auto; 111 | border: 1px solid #d9d9d9; 112 | overflow: hidden; 113 | font-size: 14px; 114 | -webkit-box-sizing: border-box; 115 | box-sizing: border-box; 116 | .preview-image { 117 | display: block; 118 | float: left; 119 | width: 90px; 120 | height: 90px; 121 | object-fit: cover; 122 | margin-right: 20px; 123 | } 124 | .status-bar { 125 | display: block; 126 | float: right; 127 | width: 305px; 128 | .upload-error-msg { 129 | color: #f50; 130 | } 131 | .status-area { 132 | a { 133 | float: right; 134 | margin-left: 20px; 135 | cursor: pointer; 136 | color: #999; 137 | } 138 | .upload-btn-retry { 139 | display: none; 140 | } 141 | } 142 | .uploading-icon { 143 | height: 3px; 144 | width: 305px; 145 | min-height: 3px; 146 | display: block; 147 | margin: 25px 0 20px; 148 | background: url(data:image/gif;base64,R0lGODlhMgEDAMQfACV79DaH+avH8bDK9rDJ7ajI8qvI7q3K8a/M92Oc7ih776/K9KrL9KbH8KbK8jV/7i9+7xhw8bjT+ICw8pLF+sHW9a3H8ajH8azJ8LPL9q3L9rPL7zB/8SV89zSH/f///yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTMyIDc5LjE1OTI4NCwgMjAxNi8wNC8xOS0xMzoxMzo0MCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUuNSAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2QTdFQzI3OUUyMUQxMUU2OEVGMUVFRTY0NzY1NUJEMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo2QTdFQzI3QUUyMUQxMUU2OEVGMUVFRTY0NzY1NUJEMyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjZBN0VDMjc3RTIxRDExRTY4RUYxRUVFNjQ3NjU1QkQzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjZBN0VDMjc4RTIxRDExRTY4RUYxRUVFNjQ3NjU1QkQzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv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) 50% no-repeat; 149 | } 150 | } 151 | 152 | } 153 | } 154 | } 155 | } 156 | .best-editor-dialog { 157 | position: fixed; 158 | top: 0; 159 | left: 0; 160 | right: 0; 161 | bottom: 0; 162 | z-index: 9999999999999; 163 | background-color: hsla(0, 0%, 100%, .7); 164 | .wrap { 165 | position: absolute; 166 | top: 50%; 167 | left: 50%; 168 | transform: translate(-50%, -50%); 169 | width: 412px; 170 | background-color: #fff; 171 | border-radius: 6px; 172 | -webkit-box-shadow: 0 2px 8px rgba(0,0,0,.2); 173 | box-shadow: 0 2px 8px rgba(0,0,0,.2); 174 | padding: 16px; 175 | box-sizing: border-box; 176 | .head { 177 | .close { 178 | text-align: right; 179 | a { 180 | cursor: pointer; 181 | font-size: 24px; 182 | color: #999; 183 | transition: color .3s ease; 184 | &:hover { 185 | color: #4d4d4d; 186 | } 187 | } 188 | } 189 | h3 { 190 | font-size: 22px; 191 | padding-bottom: 26px; 192 | text-align: center; 193 | } 194 | } 195 | 196 | .body { 197 | padding: 15px 30px 30px; 198 | .upload-btn { 199 | position: relative; 200 | height: 42px; 201 | margin-bottom: 20px; 202 | background: #555; 203 | overflow: hidden; 204 | text-align: center; 205 | line-height: 42px; 206 | color: #fff; 207 | font-size: 14px; 208 | cursor: pointer; 209 | input { 210 | position: absolute; 211 | top: -12000px; 212 | right: 0; 213 | left: 0; 214 | } 215 | } 216 | .input-box { 217 | display: flex; 218 | margin-bottom: 20px; 219 | > div { 220 | height: 42px; 221 | border: 1px solid #ccc; 222 | box-sizing: border-box; 223 | line-height: 42px; 224 | } 225 | .icon-box { 226 | text-align: center; 227 | background-color: #eee; 228 | width: 38px; 229 | color: #595959; 230 | } 231 | .input { 232 | border-left: 0; 233 | flex: 1; 234 | input { 235 | border: 0; 236 | outline: none; 237 | width: 99%; 238 | border-left: 0; 239 | box-sizing: border-box; 240 | padding: 0 10px; 241 | color: #595959; 242 | } 243 | } 244 | } 245 | .switch-box { 246 | 247 | color: #888; 248 | cursor: pointer; 249 | font-size: 14px; 250 | padding-bottom: 10px; 251 | text-align: center; 252 | } 253 | .waring-txt { 254 | height: 20px; 255 | line-height: 20px; 256 | color: #bc6351; 257 | font-size: 14px; 258 | margin-bottom: 5px; 259 | } 260 | .btn-box { 261 | font-size: 14px; 262 | text-align: right; 263 | height: 30px; 264 | line-height: 20px; 265 | user-select: none; 266 | color: #595959; 267 | > span { 268 | display: inline-block; 269 | transition: color .3s ease; 270 | cursor: pointer; 271 | 272 | padding: 4px 12px; 273 | font-size: 14px; 274 | font-weight: 500; 275 | } 276 | .cancel { 277 | &:hover { 278 | color: #000; 279 | } 280 | } 281 | .confirm { 282 | color: #42c02e; 283 | background-color: #fff; 284 | border: 1px solid #42c02e; 285 | border-radius: 15px; 286 | margin-left: 15px; 287 | } 288 | 289 | } 290 | } 291 | 292 | 293 | } 294 | } -------------------------------------------------------------------------------- /src/ui/image-dialog.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

5 |
6 |

插入图片

7 |
8 |
9 |
10 |
点击上传(可多张)
11 | 15 |
或选择网络图片
16 |
17 |
18 | 取 消 19 | 20 |
21 |
22 |
23 |
-------------------------------------------------------------------------------- /src/ui/image-upload.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | 正在上传... 7 | 取消 8 | 重新上传 9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /src/ui/link-dialog.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

5 |
6 |

插入链接

7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | 取 消 21 | 确 认 22 |
23 |
24 | 25 |
26 |
-------------------------------------------------------------------------------- /src/ui/toolbar.html: -------------------------------------------------------------------------------- 1 |
2 | 13 |
-------------------------------------------------------------------------------- /src/ui/video-dialog.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

5 |
6 |

插入视频

7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 取 消 17 | 确 认 18 |
19 |
20 | 21 |
22 |
-------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 4 | module.exports = (env, argv) => { 5 | var DEV = argv.mode === 'development'; 6 | var config = { 7 | entry: './src/main.js', 8 | devtool: DEV ? 'inline-source-map' : '', 9 | output: { 10 | filename: DEV ? 'best-editor-dev.js' : 'best-editor.js', 11 | path: path.resolve(__dirname, 'dist'), 12 | library: 'BestEditor', 13 | libraryTarget: 'umd', 14 | umdNamedDefine: true 15 | }, 16 | module: { 17 | rules: [{ 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel-loader' 21 | }, { 22 | test: /\.css$/, 23 | use: [MiniCssExtractPlugin.loader, 'css-loader'] 24 | }, { 25 | test: /\.scss$/, 26 | use: [{ 27 | loader: MiniCssExtractPlugin.loader 28 | }, { 29 | loader: 'css-loader' 30 | }, { 31 | loader: 'sass-loader' 32 | }] 33 | }, { 34 | test: /\.html$/, 35 | use: [{ 36 | loader: 'html-loader', 37 | options: { 38 | minimize: true, 39 | removeComments: false, 40 | collapseWhitespace: false 41 | } 42 | }], 43 | }, { 44 | test: /\.(ttf|eot|woff|woff2)$/, 45 | use: { 46 | loader: 'file-loader', 47 | options: { 48 | name: 'fonts/[name].[ext]', 49 | }, 50 | } 51 | }] 52 | }, 53 | plugins: [ 54 | new MiniCssExtractPlugin({ 55 | filename: DEV ? 'best-editor.css' : 'best-editor.min.css' 56 | }) 57 | ] 58 | }; 59 | return config; 60 | }; 61 | 62 | --------------------------------------------------------------------------------