├── .babelrc ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── LICENSE ├── README.EN.md ├── README.md ├── dist ├── index.js └── static │ └── fonts │ ├── iconfont.0f693eba.eot │ ├── iconfont.35e220a6.svg │ ├── iconfont.a614fc0f.ttf │ └── iconfont.fe07082d.woff ├── doc └── UPDATELOG.md ├── example ├── globals.d.ts ├── index.html ├── index.scss ├── index.tsx ├── src │ ├── app.module.scss │ ├── app.module.scss.d.ts │ └── app.tsx └── static │ └── help.md ├── index.d.ts ├── package.json ├── src ├── components │ ├── toolbar_left.tsx │ └── toolbar_right.tsx ├── index.tsx └── lib │ ├── css │ ├── index.scss │ └── index.scss.d.ts │ ├── fonts │ ├── iconfont.css │ ├── iconfont.css.d.ts │ ├── iconfont.eot │ ├── iconfont.svg │ ├── iconfont.ttf │ ├── iconfont.woff │ └── iconfont.woff2 │ ├── helpers │ ├── function.ts │ ├── highlight.ts │ ├── keydownListen.ts │ └── marked.ts │ ├── index.ts │ └── lang │ ├── en │ └── index.json │ └── zh-CN │ └── index.json ├── tsconfig.json └── webpack ├── webpack.base.config.js ├── webpack.dev.config.js ├── webpack.dist.config.js └── webpack.prod.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-react" 4 | ], 5 | "plugins": [ 6 | "@babel/plugin-proposal-class-properties", 7 | "@babel/plugin-transform-modules-commonjs" 8 | ] 9 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['eslint-config-for/react', 'eslint-config-for/typescript'] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | playground/ 3 | .DS_Store -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 一行最多 100 字符 3 | printWidth: 100, 4 | // 使用 2 个空格缩进 5 | tabWidth: 2, 6 | // 不使用缩进符,而使用空格 7 | useTabs: false, 8 | // 行尾需要有分号 9 | semi: false, 10 | // 使用单引号 11 | singleQuote: true, 12 | // jsx 不使用单引号,而使用双引号 13 | jsxSingleQuote: false, 14 | // 末尾不需要逗号 15 | trailingComma: 'none', 16 | // 大括号内的首尾需要空格 17 | bracketSpacing: true, 18 | // jsx 标签的反尖括号需要换行 19 | jsxBracketSameLine: false, 20 | // 箭头函数,只有一个参数的时候,也需要括号 21 | arrowParens: 'always', 22 | // 每个文件格式化的范围是文件的全部内容 23 | rangeStart: 0, 24 | rangeEnd: Infinity, 25 | // 不需要写文件开头的 @prettier 26 | requirePragma: false, 27 | // 不需要自动在文件开头插入 @prettier 28 | insertPragma: false, 29 | // 使用默认的折行标准 30 | proseWrap: 'preserve', 31 | // 根据显示样式决定 html 要不要折行 32 | htmlWhitespaceSensitivity: 'css', 33 | // 换行符使用 lf 34 | endOfLine: 'lf' 35 | }; 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 kkfor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.EN.md: -------------------------------------------------------------------------------- 1 | # for-editor 2 | 3 | > for-editor-A markdown editor based on React 4 | 5 | - [demo](https://md.kkfor.com) 6 | - [github](https://github.com/kkfor/for-editor) 7 | 8 | ### Install 9 | 10 | ```js 11 | npm install for-editor -S 12 | ``` 13 | 14 | ### Use 15 | 16 | ```js 17 | import React, { Component } from 'react' 18 | import ReactDOM from 'react-dom' 19 | import Editor from 'for-editor' 20 | 21 | class App extends Component { 22 | constructor() { 23 | super() 24 | this.state = { 25 | value: '' 26 | } 27 | } 28 | 29 | handleChange(value) { 30 | this.setState({ 31 | value 32 | }) 33 | } 34 | 35 | render() { 36 | const { value } = this.state 37 | return this.handleChange()} /> 38 | } 39 | } 40 | 41 | ReactDOM.render(, document.getElementById('root')) 42 | ``` 43 | 44 | ### Api 45 | 46 | #### props 47 | 48 | | name | type | default | description | 49 | | ----------- | ------- | --------------------------- | ------------------------------------------------------------------------------------------------------ | 50 | | value | String | - | value | 51 | | language | String | zh-CN | Language switch, zh-CN: Simplified Chinese, en: English | 52 | | placeholder | String | Begin editing... | The default prompt text when the textarea is empty | 53 | | lineNum | Boolean | true | Show lineNum | 54 | | style | Object | - | editor styles | 55 | | height | String | 600px | editor height | 56 | | preview | Boolean | false | preview switch | 57 | | expand | Boolean | false | fullscreen switch | 58 | | subfield | Boolean | false | true: Double columns - Edit preview same screen(notice: preview: true), Single Columns - otherwise not | 59 | | toolbar | Object | As in the following example | toolbars | 60 | 61 | ```js 62 | /* 63 | The default toolbar properties are all true, 64 | You can customize the object to cover them. 65 | eg: { 66 | h1: true, 67 | code: true, 68 | preview: true, 69 | } 70 | At this point, the toolbar only displays the three function keys. 71 | notice: Toolbar will be hidden when empty object. 72 | */ 73 | 74 | toolbar: { 75 | h1: true, 76 | h2: true, 77 | h3: true, 78 | h4: true, 79 | img: true, 80 | link: true, 81 | code: true, 82 | preview: true, 83 | expand: true, 84 | /* v0.0.9 */ 85 | undo: true, 86 | redo: true, 87 | save: true, 88 | /* v0.2.3 */ 89 | subfield: true 90 | } 91 | ``` 92 | 93 | #### events 94 | 95 | | name | params | default | description | 96 | | -------- | ------------- | ------- | ------------------------------------------- | 97 | | onChange | String: value | - | Edit area change callback event | 98 | | onSave | String: value | - | Ctrl+s and click save button callback event | 99 | | addImg | File: file | - | upload image callback event | 100 | 101 | ##### upload image 102 | 103 | ```js 104 | class App extends Component { 105 | constructor() { 106 | super() 107 | this.state = { 108 | value: '' 109 | } 110 | this.$vm = React.createRef() 111 | } 112 | 113 | handleChange(value) { 114 | this.setState({ 115 | value 116 | }) 117 | } 118 | 119 | addImg($file) { 120 | this.$vm.current.$img2Url($file.name, 'file_url') 121 | console.log($file) 122 | } 123 | 124 | render() { 125 | const { value } = this.state 126 | 127 | return ( 128 | this.addImg($file)} 132 | onChange={(value) => this.handleChange(value)} 133 | /> 134 | ) 135 | } 136 | } 137 | ``` 138 | 139 | #### hot key 140 | 141 | | name | description | 142 | | ------ | ----------- | 143 | | tab | two space | 144 | | ctrl+s | save | 145 | | ctrl+z | undo | 146 | | ctrl+y | redo | 147 | 148 | ### Update 149 | 150 | - [Update Log](./doc/UPDATELOG.md) 151 | 152 | # Licence 153 | 154 | for-editor is [MIT Licence](./LICENSE). 155 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # for-editor 2 | 3 | > for-editor 是一个基于 react 的 markdown 语法编辑器 4 | 5 | ### [English Documents](./README.EN.md) 6 | 7 | - [demo](https://md.kkfor.com) 8 | - [github](https://github.com/kkfor/for-editor) 9 | 10 | ### 安装 11 | 12 | ```js 13 | npm install for-editor -S 14 | ``` 15 | 16 | ### 使用 17 | 18 | ```js 19 | import React, { Component } from 'react' 20 | import ReactDOM from 'react-dom' 21 | import Editor from 'for-editor' 22 | 23 | class App extends Component { 24 | constructor() { 25 | super() 26 | this.state = { 27 | value: '' 28 | } 29 | } 30 | 31 | handleChange(value) { 32 | this.setState({ 33 | value 34 | }) 35 | } 36 | 37 | render() { 38 | const { value } = this.state 39 | return this.handleChange()} /> 40 | } 41 | } 42 | 43 | ReactDOM.render(, document.getElementById('root')) 44 | ``` 45 | 46 | ### Api 47 | 48 | #### 属性 49 | 50 | | name | type | default | description | 51 | | ----------- | ------- | ----------- | ---------------------------------- | 52 | | value | String | - | 输入框内容 | 53 | | placeholder | String | 开始编辑... | 占位文本 | 54 | | lineNum | Boolean | true | 是否显示行号 | 55 | | style | Object | - | 编辑器样式 | 56 | | height | String | 600px | 编辑器高度 | 57 | | preview | Boolean | false | 预览模式 | 58 | | expand | Boolean | false | 全屏模式 | 59 | | subfield | Boolean | false | 双栏模式(预览模式激活下有效) | 60 | | language | String | zh-CN | 语言(支持 zh-CN:中文简体, en:英文) | 61 | | toolbar | Object | 如下 | 自定义工具栏 | 62 | 63 | ```js 64 | /* 65 | 默认工具栏按钮全部开启, 传入自定义对象 66 | 例如: { 67 | h1: true, // h1 68 | code: true, // 代码块 69 | preview: true, // 预览 70 | } 71 | 此时, 仅仅显示此三个功能键 72 | 注:传入空对象则不显示工具栏 73 | */ 74 | 75 | toolbar: { 76 | h1: true, // h1 77 | h2: true, // h2 78 | h3: true, // h3 79 | h4: true, // h4 80 | img: true, // 图片 81 | link: true, // 链接 82 | code: true, // 代码块 83 | preview: true, // 预览 84 | expand: true, // 全屏 85 | /* v0.0.9 */ 86 | undo: true, // 撤销 87 | redo: true, // 重做 88 | save: true, // 保存 89 | /* v0.2.3 */ 90 | subfield: true, // 单双栏模式 91 | } 92 | ``` 93 | 94 | #### 事件 95 | 96 | | name | params 参数 | default | description | 97 | | -------- | ------------- | ------- | -------------- | 98 | | onChange | String: value | - | 内容改变时回调 | 99 | | onSave | String: value | - | 保存时回调 | 100 | | addImg | File: file | - | 添加图片时回调 | 101 | 102 | ##### 图片上传 103 | 104 | ```js 105 | class App extends Component { 106 | constructor() { 107 | super() 108 | this.state = { 109 | value: '', 110 | } 111 | this.$vm = React.createRef() 112 | } 113 | 114 | handleChange(value) { 115 | this.setState({ 116 | value 117 | }) 118 | } 119 | 120 | addImg($file) { 121 | this.$vm.current.$img2Url($file.name, 'file_url') 122 | console.log($file) 123 | } 124 | 125 | render() { 126 | const { value } = this.state 127 | 128 | return ( 129 | this.addImg($file)} 133 | onChange={value => this.handleChange(value)} 134 | /> 135 | ) 136 | } 137 | } 138 | ``` 139 | 140 | #### 快捷键 141 | 142 | | name | description | 143 | | ------ | ------------ | 144 | | tab | 两个空格缩进 | 145 | | ctrl+s | 保存 | 146 | | ctrl+z | 上一步 | 147 | | ctrl+y | 下一步 | 148 | 149 | ### 更新 150 | 151 | - [Update Log](./doc/UPDATELOG.md) 152 | 153 | ### Licence 154 | 155 | for-editor is [MIT Licence](./LICENSE). 156 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}(window,function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=5)}([function(e,t,n){"use strict";e.exports=n(6)},function(e,t,n){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var o=(a=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(a))))+" */"),i=r.sources.map(function(e){return"/*# sourceURL="+r.sourceRoot+e+" */"});return[n].concat(i).concat([o]).join("\n")}var a;return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n}).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var r={},o=0;o=0&&u.splice(t,1)}function m(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var r=function(){0;return n.nc}();r&&(e.attrs.nonce=r)}return b(t,e.attrs),h(e,t),t}function b(e,t){Object.keys(t).forEach(function(n){e.setAttribute(n,t[n])})}function v(e,t){var n,r,o,i;if(t.transform&&e.css){if(!(i="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=i}if(t.singleton){var a=c++;n=l||(l=m(t)),r=x.bind(null,n,a,!1),o=x.bind(null,n,a,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",b(t,e.attrs),h(e,t),t}(t),r=function(e,t,n){var r=n.css,o=n.sourceMap,i=void 0===t.convertToAbsoluteUrls&&o;(t.convertToAbsoluteUrls||i)&&(r=f(r));o&&(r+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(o))))+" */");var a=new Blob([r],{type:"text/css"}),s=e.href;e.href=URL.createObjectURL(a),s&&URL.revokeObjectURL(s)}.bind(null,n,t),o=function(){g(n),n.href&&URL.revokeObjectURL(n.href)}):(n=m(t),r=function(e,t){var n=t.css,r=t.media;r&&e.setAttribute("media",r);if(e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}.bind(null,n),o=function(){g(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else o()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=a()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=p(e,t);return d(n,t),function(e){for(var r=[],o=0;o=0?e:"zh-CN";n.setState({words:g.CONFIG.language[t]})},n.handleChange=function(e){var t=e.target.value;n.props.onChange(t)},n.saveHistory=function(e){var t=n.state,r=t.history,o=t.historyIndex;r.splice(o+1,r.length),r.length>=20&&r.shift(),o=r.length,r.push(e),n.setState({history:r,historyIndex:o})},n.save=function(){n.props.onSave(n.$vm.current.value)},n.undo=function(){var e=n.state,t=e.history,r=e.historyIndex;(r-=1)<0||(n.props.onChange(t[r]),n.setState({historyIndex:r}))},n.redo=function(){var e=n.state,t=e.history,r=e.historyIndex;(r+=1)>=t.length||(n.props.onChange(t[r]),n.setState({historyIndex:r}))},n.toolBarLeftClick=function(e){var t=n.state.words,r={h1:{prefix:"# ",subfix:"",str:t.h1},h2:{prefix:"## ",subfix:"",str:t.h2},h3:{prefix:"### ",subfix:"",str:t.h3},h4:{prefix:"#### ",subfix:"",str:t.h4},img:{prefix:"![alt](",subfix:")",str:"url"},link:{prefix:"[title](",subfix:")",str:"url"},code:{prefix:"```",subfix:"\n\n```",str:"language"},tab:{prefix:" ",subfix:"",str:""}};if(r.hasOwnProperty(e)&&n.$vm.current){var o=h.insertText(n.$vm.current,r[e]);n.props.onChange(o)}var i={undo:n.undo,redo:n.redo,save:n.save};i.hasOwnProperty(e)&&i[e]()},n.addImg=function(e,t){n.props.addImg(e,t)},n.$img2Url=function(e,t){var r=h.insertText(n.$vm.current,{prefix:"!["+e+"]("+t+")",subfix:"",str:""});n.props.onChange(r)},n.toolBarRightClick=function(e){var t={preview:function(){n.setState({preview:!n.state.preview})},expand:function(){n.setState({expand:!n.state.expand})},subfield:function(){var e=n.state,t=e.preview,r=e.subfield;t?r?n.setState({subfield:!1,preview:!1}):n.setState({subfield:!0}):r?n.setState({subfield:!1}):n.setState({preview:!0,subfield:!0})}};t.hasOwnProperty(e)&&t[e]()},n.focusText=function(){n.$vm.current.focus()},n.handleScoll=function(e){var t=n.$blockEdit.current.scrollTop/(n.$scrollEdit.current.scrollHeight-e.currentTarget.offsetHeight);n.$blockPreview.current.scrollTop=(n.$scrollPreview.current.scrollHeight-n.$blockPreview.current.offsetHeight)*t},n.state={preview:t.preview,expand:t.expand,subfield:t.subfield,history:[],historyIndex:0,lineIndex:1,value:t.value,words:{}},n}return o(t,e),t.prototype.componentDidMount=function(){var e=this,t=this.props.value;f.default(this.$vm.current,function(t){e.toolBarLeftClick(t)}),this.reLineNum(t),this.initLanguage()},t.prototype.componentDidUpdate=function(e){var t=this,n=this.props,r=n.value,o=n.preview,i=n.expand,a=n.subfield,s=this.state,l=s.history,c=s.historyIndex;e.value!==r&&this.reLineNum(r),r!==l[c]&&(window.clearTimeout(this.currentTimeout),this.currentTimeout=window.setTimeout(function(){t.saveHistory(r)},500)),a!==e.subfield&&this.state.subfield!==a&&this.setState({subfield:a}),o!==e.preview&&this.state.preview!==o&&this.setState({preview:o}),i!==e.expand&&this.state.expand!==i&&this.setState({expand:i})},t.prototype.reLineNum=function(e){var t=e?e.split("\n").length:1;this.setState({lineIndex:t})},t.prototype.render=function(){var e=this.state,t=e.preview,n=e.expand,r=e.subfield,o=e.lineIndex,a=e.words,s=this.props,f=s.value,h=s.placeholder,g=s.fontSize,m=s.disabled,b=s.height,v=s.style,y=s.toolbar,w=c.default({"for-editor-edit":!0,"for-panel":!0,"for-active":t&&r,"for-edit-preview":t&&!r}),x=c.default({"for-panel":!0,"for-editor-preview":!0,"for-active":t&&r}),k=c.default({"for-container":!0,"for-fullscreen":n}),_=c.default({"for-line-num":!0,hidden:!this.props.lineNum});return l.createElement("div",{className:k,style:i({height:b},v)},Boolean(Object.keys(y).length)&&l.createElement("div",{className:"for-toolbar"},l.createElement(d.default,i({toolbar:y,words:a,onClick:this.toolBarLeftClick,addImg:this.addImg},this.props)),l.createElement(p.default,{toolbar:y,words:a,preview:t,expand:n,subfield:r,onClick:this.toolBarRightClick})),l.createElement("div",{className:"for-editor",style:{fontSize:g}},l.createElement("div",{className:w,ref:this.$blockEdit,onScroll:this.handleScoll,onClick:this.focusText},l.createElement("div",{className:"for-editor-block",ref:this.$scrollEdit},function(){for(var e=[],t=0;tT.length&&T.push(e)}function L(e,t,n){return null==e?0:function e(t,n,r,o){var s=typeof t;"undefined"!==s&&"boolean"!==s||(t=null);var l=!1;if(null===t)l=!0;else switch(s){case"string":case"number":l=!0;break;case"object":switch(t.$$typeof){case i:case a:l=!0}}if(l)return r(o,t,""===n?"."+D(t,0):n),1;if(l=0,n=""===n?".":n+":",Array.isArray(t))for(var c=0;c"+e+"

"},a.link=function(e,t,n){return""+n+""},t.default=function(e){return"string"!=typeof e?"":o.default(e,{renderer:a})}},function(e,t,n){(function(t){!function(t){"use strict";var n={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:m,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,nptable:m,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,table:m,lheading:/^([^\n]+)\n {0,3}(=|-){2,} *(?:\n+|$)/,paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,text:/^[^\n]+/};function r(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||x.defaults,this.rules=n.normal,this.options.pedantic?this.rules=n.pedantic:this.options.gfm&&(this.options.tables?this.rules=n.tables:this.rules=n.gfm)}n._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,n._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,n.def=d(n.def).replace("label",n._label).replace("title",n._title).getRegex(),n.bullet=/(?:[*+-]|\d{1,9}\.)/,n.item=/^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/,n.item=d(n.item,"gm").replace(/bull/g,n.bullet).getRegex(),n.list=d(n.list).replace(/bull/g,n.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+n.def.source+")").getRegex(),n._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",n._comment=//,n.html=d(n.html,"i").replace("comment",n._comment).replace("tag",n._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),n.paragraph=d(n.paragraph).replace("hr",n.hr).replace("heading",n.heading).replace("lheading",n.lheading).replace("tag",n._tag).getRegex(),n.blockquote=d(n.blockquote).replace("paragraph",n.paragraph).getRegex(),n.normal=b({},n),n.gfm=b({},n.normal,{fences:/^ {0,3}(`{3,}|~{3,})([^`\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/}),n.gfm.paragraph=d(n.paragraph).replace("(?!","(?!"+n.gfm.fences.source.replace("\\1","\\2")+"|"+n.list.source.replace("\\1","\\3")+"|").getRegex(),n.tables=b({},n.gfm,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/}),n.pedantic=b({},n.normal,{html:d("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",n._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/}),r.rules=n,r.lex=function(e,t){return new r(t).lex(e)},r.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},r.prototype.token=function(e,t){var r,o,i,a,s,l,c,u,f,d,p,h,g,m,b,w;for(e=e.replace(/^ +$/gm,"");e;)if((i=this.rules.newline.exec(e))&&(e=e.substring(i[0].length),i[0].length>1&&this.tokens.push({type:"space"})),i=this.rules.code.exec(e)){var x=this.tokens[this.tokens.length-1];e=e.substring(i[0].length),x&&"paragraph"===x.type?x.text+="\n"+i[0].trimRight():(i=i[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",codeBlockStyle:"indented",text:this.options.pedantic?i:y(i,"\n")}))}else if(i=this.rules.fences.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"code",lang:i[2]?i[2].trim():i[2],text:i[3]||""});else if(i=this.rules.heading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"heading",depth:i[1].length,text:i[2]});else if((i=this.rules.nptable.exec(e))&&(l={type:"table",header:v(i[1].replace(/^ *| *\| *$/g,"")),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3]?i[3].replace(/\n$/,"").split("\n"):[]}).header.length===l.align.length){for(e=e.substring(i[0].length),p=0;p ?/gm,""),this.token(i,t),this.tokens.push({type:"blockquote_end"});else if(i=this.rules.list.exec(e)){for(e=e.substring(i[0].length),c={type:"list_start",ordered:m=(a=i[2]).length>1,start:m?+a:"",loose:!1},this.tokens.push(c),u=[],r=!1,g=(i=i[0].match(this.rules.item)).length,p=0;p1?1===s.length:s.length>1||this.options.smartLists&&s!==a)&&(e=i.slice(p+1).join("\n")+e,p=g-1)),o=r||/\n\n(?!\s*$)/.test(l),p!==g-1&&(r="\n"===l.charAt(l.length-1),o||(o=r)),o&&(c.loose=!0),w=void 0,(b=/^\[[ xX]\] /.test(l))&&(w=" "!==l[1],l=l.replace(/^\[[ xX]\] +/,"")),f={type:"list_item_start",task:b,checked:w,loose:o},u.push(f),this.tokens.push(f),this.token(l,!1),this.tokens.push({type:"list_item_end"});if(c.loose)for(g=u.length,p=0;p?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:m,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(href(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong:/^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,em:/^_([^\s_])_(?!_)|^\*([^\s*<\[])\*(?!\*)|^_([^\s<][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:m,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\?@\\[^_{|}~",o.em=d(o.em).replace(/punctuation/g,o._punctuation).getRegex(),o._escapes=/\\([!"#$%&'()*+,\-.\/:;<=>?@\[\]\\^_`{|}~])/g,o._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,o._email=/[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,o.autolink=d(o.autolink).replace("scheme",o._scheme).replace("email",o._email).getRegex(),o._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,o.tag=d(o.tag).replace("comment",n._comment).replace("attribute",o._attribute).getRegex(),o._label=/(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|`(?!`)|[^\[\]\\`])*?/,o._href=/\s*(<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*)/,o._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,o.link=d(o.link).replace("label",o._label).replace("href",o._href).replace("title",o._title).getRegex(),o.reflink=d(o.reflink).replace("label",o._label).getRegex(),o.normal=b({},o),o.pedantic=b({},o.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link:d(/^!?\[(label)\]\((.*?)\)/).replace("label",o._label).getRegex(),reflink:d(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",o._label).getRegex()}),o.gfm=b({},o.normal,{escape:d(o.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~+(?=\S)([\s\S]*?\S)~+/,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\/i.test(a[0])&&(this.inLink=!1),!this.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(a[0])?this.inRawBlock=!0:this.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(a[0])&&(this.inRawBlock=!1),e=e.substring(a[0].length),l+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(a[0]):u(a[0]):a[0];else if(a=this.rules.link.exec(e)){var c=w(a[2],"()");if(c>-1){var f=a[0].length-(a[2].length-c)-(a[3]||"").length;a[2]=a[2].substring(0,c),a[0]=a[0].substring(0,f).trim(),a[3]=""}e=e.substring(a[0].length),this.inLink=!0,r=a[2],this.options.pedantic?(t=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(r))?(r=t[1],o=t[3]):o="":o=a[3]?a[3].slice(1,-1):"",r=r.trim().replace(/^<([\s\S]*)>$/,"$1"),l+=this.outputLink(a,{href:i.escapes(r),title:i.escapes(o)}),this.inLink=!1}else if((a=this.rules.reflink.exec(e))||(a=this.rules.nolink.exec(e))){if(e=e.substring(a[0].length),t=(a[2]||a[1]).replace(/\s+/g," "),!(t=this.links[t.toLowerCase()])||!t.href){l+=a[0].charAt(0),e=a[0].substring(1)+e;continue}this.inLink=!0,l+=this.outputLink(a,t),this.inLink=!1}else if(a=this.rules.strong.exec(e))e=e.substring(a[0].length),l+=this.renderer.strong(this.output(a[4]||a[3]||a[2]||a[1]));else if(a=this.rules.em.exec(e))e=e.substring(a[0].length),l+=this.renderer.em(this.output(a[6]||a[5]||a[4]||a[3]||a[2]||a[1]));else if(a=this.rules.code.exec(e))e=e.substring(a[0].length),l+=this.renderer.codespan(u(a[2].trim(),!0));else if(a=this.rules.br.exec(e))e=e.substring(a[0].length),l+=this.renderer.br();else if(a=this.rules.del.exec(e))e=e.substring(a[0].length),l+=this.renderer.del(this.output(a[1]));else if(a=this.rules.autolink.exec(e))e=e.substring(a[0].length),r="@"===a[2]?"mailto:"+(n=u(this.mangle(a[1]))):n=u(a[1]),l+=this.renderer.link(r,null,n);else if(this.inLink||!(a=this.rules.url.exec(e))){if(a=this.rules.text.exec(e))e=e.substring(a[0].length),this.inRawBlock?l+=this.renderer.text(a[0]):l+=this.renderer.text(u(this.smartypants(a[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else{if("@"===a[2])r="mailto:"+(n=u(a[0]));else{do{s=a[0],a[0]=this.rules._backpedal.exec(a[0])[0]}while(s!==a[0]);n=u(a[0]),r="www."===a[1]?"http://"+n:n}e=e.substring(a[0].length),l+=this.renderer.link(r,null,n)}return l},i.escapes=function(e){return e?e.replace(i.rules._escapes,"$1"):e},i.prototype.outputLink=function(e,t){var n=t.href,r=t.title?u(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,u(e[1]))},i.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014\/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014\/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},i.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",r=e.length,o=0;o.5&&(t="x"+t.toString(16)),n+="&#"+t+";";return n},a.prototype.code=function(e,t,n){var r=(t||"").match(/\S*/)[0];if(this.options.highlight){var o=this.options.highlight(e,r);null!=o&&o!==e&&(n=!0,e=o)}return r?'
'+(n?e:u(e,!0))+"
\n":"
"+(n?e:u(e,!0))+"
"},a.prototype.blockquote=function(e){return"
\n"+e+"
\n"},a.prototype.html=function(e){return e},a.prototype.heading=function(e,t,n,r){return this.options.headerIds?"'+e+"\n":""+e+"\n"},a.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},a.prototype.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"},a.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},a.prototype.checkbox=function(e){return" "},a.prototype.paragraph=function(e){return"

    "+e+"

    \n"},a.prototype.table=function(e,t){return t&&(t=""+t+""),"\n\n"+e+"\n"+t+"
    \n"},a.prototype.tablerow=function(e){return"\n"+e+"\n"},a.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"\n"},a.prototype.strong=function(e){return""+e+""},a.prototype.em=function(e){return""+e+""},a.prototype.codespan=function(e){return""+e+""},a.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},a.prototype.del=function(e){return""+e+""},a.prototype.link=function(e,t,n){if(null===(e=p(this.options.sanitize,this.options.baseUrl,e)))return n;var r='"},a.prototype.image=function(e,t,n){if(null===(e=p(this.options.sanitize,this.options.baseUrl,e)))return n;var r=''+n+'":">"},a.prototype.text=function(e){return e},s.prototype.strong=s.prototype.em=s.prototype.codespan=s.prototype.del=s.prototype.text=function(e){return e},s.prototype.link=s.prototype.image=function(e,t,n){return""+n},s.prototype.br=function(){return""},l.parse=function(e,t){return new l(t).parse(e)},l.prototype.parse=function(e){this.inline=new i(e.links,this.options),this.inlineText=new i(e.links,b({},this.options,{renderer:new s})),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},l.prototype.next=function(){return this.token=this.tokens.pop(),this.token},l.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},l.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},l.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,f(this.inlineText.output(this.token.text)),this.slugger);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,o="",i="";for(n="",e=0;e?@[\]^`{|}~]/g,"").replace(/\s/g,"-");if(this.seen.hasOwnProperty(t)){var n=t;do{this.seen[n]++,t=n+"-"+this.seen[n]}while(this.seen.hasOwnProperty(t))}return this.seen[t]=0,t},u.escapeTest=/[&<>"']/,u.escapeReplace=/[&<>"']/g,u.replacements={"&":"&","<":"<",">":">",'"':""","'":"'"},u.escapeTestNoEncode=/[<>"']|&(?!#?\w+;)/,u.escapeReplaceNoEncode=/[<>"']|&(?!#?\w+;)/g;var h={},g=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function m(){}function b(e){for(var t,n,r=1;r=0&&"\\"===n[o];)r=!r;return r?"|":" |"}).split(/ \|/),r=0;if(n.length>t)n.splice(t);else for(;n.lengthAn error occurred:

    "+u(e.message+"",!0)+"
    ";throw e}}m.exec=m,x.options=x.setOptions=function(e){return b(x.defaults,e),x},x.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new a,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tables:!0,xhtml:!1}},x.defaults=x.getDefaults(),x.Parser=l,x.parser=l.parse,x.Renderer=a,x.TextRenderer=s,x.Lexer=r,x.lexer=r.lex,x.InlineLexer=i,x.inlineLexer=i.output,x.Slugger=c,x.parse=x,e.exports=x}(this||"undefined"!=typeof window&&window)}).call(this,n(10))},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";t.__esModule=!0;var r=n(12);r.registerLanguage("css",n(13)),r.registerLanguage("json",n(14)),r.registerLanguage("less",n(15)),r.registerLanguage("scss",n(16)),r.registerLanguage("javascript",n(17)),r.registerLanguage("typescript",n(18)),t.default=r},function(e,t,n){!function(e){"object"==typeof window&&window||"object"==typeof self&&self;(function(e){var t,n=[],r=Object.keys,o={},i={},a=/^(no-?highlight|plain|text)$/i,s=/\blang(?:uage)?-([\w-]+)\b/i,l=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,c="",u={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};function f(e){return e.replace(/&/g,"&").replace(//g,">")}function d(e){return e.nodeName.toLowerCase()}function p(e,t){var n=e&&e.exec(t);return n&&0===n.index}function h(e){return a.test(e)}function g(e){var t,n={},r=Array.prototype.slice.call(arguments,1);for(t in e)n[t]=e[t];return r.forEach(function(e){for(t in e)n[t]=e[t]}),n}function m(e){var t=[];return function e(n,r){for(var o=n.firstChild;o;o=o.nextSibling)3===o.nodeType?r+=o.nodeValue.length:1===o.nodeType&&(t.push({event:"start",offset:r,node:o}),r=e(o,r),d(o).match(/br|hr|img|input/)||t.push({event:"stop",offset:r,node:o}));return r}(e,0),t}function b(e){if(t&&!e.langApiRestored){for(var n in e.langApiRestored=!0,t)e[n]&&(e[t[n]]=e[n]);(e.contains||[]).concat(e.variants||[]).forEach(b)}}function v(e){function t(e){return e&&e.source||e}function n(n,r){return new RegExp(t(n),"m"+(e.case_insensitive?"i":"")+(r?"g":""))}!function o(i,a){if(i.compiled)return;i.compiled=!0;i.keywords=i.keywords||i.beginKeywords;if(i.keywords){var s={},l=function(t,n){e.case_insensitive&&(n=n.toLowerCase()),n.split(" ").forEach(function(e){var n=e.split("|");s[n[0]]=[t,n[1]?Number(n[1]):1]})};"string"==typeof i.keywords?l("keyword",i.keywords):r(i.keywords).forEach(function(e){l(e,i.keywords[e])}),i.keywords=s}i.lexemesRe=n(i.lexemes||/\w+/,!0);a&&(i.beginKeywords&&(i.begin="\\b("+i.beginKeywords.split(" ").join("|")+")\\b"),i.begin||(i.begin=/\B|\b/),i.beginRe=n(i.begin),i.endSameAsBegin&&(i.end=i.begin),i.end||i.endsWithParent||(i.end=/\B|\b/),i.end&&(i.endRe=n(i.end)),i.terminator_end=t(i.end)||"",i.endsWithParent&&a.terminator_end&&(i.terminator_end+=(i.end?"|":"")+a.terminator_end));i.illegal&&(i.illegalRe=n(i.illegal));null==i.relevance&&(i.relevance=1);i.contains||(i.contains=[]);i.contains=Array.prototype.concat.apply([],i.contains.map(function(e){return function(e){e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map(function(t){return g(e,{variants:null},t)}));return e.cached_variants||e.endsWithParent&&[g(e)]||[e]}("self"===e?i:e)}));i.contains.forEach(function(e){o(e,i)});i.starts&&o(i.starts,a);var c=i.contains.map(function(e){return e.beginKeywords?"\\.?(?:"+e.begin+")\\.?":e.begin}).concat([i.terminator_end,i.illegal]).map(t).filter(Boolean);i.terminators=c.length?n(function(e,n){for(var r=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,o=0,i="",a=0;a0&&(i+=n);l.length>0;){var c=r.exec(l);if(null==c){i+=l;break}i+=l.substring(0,c.index),l=l.substring(c.index+c[0].length),"\\"==c[0][0]&&c[1]?i+="\\"+String(Number(c[1])+s):(i+=c[0],"("==c[0]&&o++)}}return i}(c,"|"),!0):{exec:function(){return null}}}(e)}function y(e,t,n,r){function i(e){return new RegExp(e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")}function a(e,t){var n=g.case_insensitive?t[0].toLowerCase():t[0];return e.keywords.hasOwnProperty(n)&&e.keywords[n]}function s(e,t,n,r){var o=r?"":u.classPrefix,i='',e?i+t+a:t}function l(){k+=null!=b.subLanguage?function(){var e="string"==typeof b.subLanguage;if(e&&!o[b.subLanguage])return f(_);var t=e?y(b.subLanguage,_,!0,x[b.subLanguage]):w(_,b.subLanguage.length?b.subLanguage:void 0);b.relevance>0&&(O+=t.relevance);e&&(x[b.subLanguage]=t.top);return s(t.language,t.value,!1,!0)}():function(){var e,t,n,r;if(!b.keywords)return f(_);r="",t=0,b.lexemesRe.lastIndex=0,n=b.lexemesRe.exec(_);for(;n;)r+=f(_.substring(t,n.index)),(e=a(b,n))?(O+=e[1],r+=s(e[0],f(n[0]))):r+=f(n[0]),t=b.lexemesRe.lastIndex,n=b.lexemesRe.exec(_);return r+f(_.substr(t))}(),_=""}function d(e){k+=e.className?s(e.className,"",!0):"",b=Object.create(e,{parent:{value:b}})}function h(e,t){if(_+=e,null==t)return l(),0;var r=function(e,t){var n,r;for(n=0,r=t.contains.length;n")+'"');return _+=t,t.length||1}var g=E(e);if(!g)throw new Error('Unknown language: "'+e+'"');v(g);var m,b=r||g,x={},k="";for(m=b;m!==g;m=m.parent)m.className&&(k=s(m.className,"",!0)+k);var _="",O=0;try{for(var N,S,C=0;b.terminators.lastIndex=C,N=b.terminators.exec(t);)S=h(t.substring(C,N.index),N[0]),C=N.index+S;for(h(t.substr(C)),m=b;m.parent;m=m.parent)m.className&&(k+=c);return{relevance:O,value:k,language:e,top:b}}catch(e){if(e.message&&-1!==e.message.indexOf("Illegal"))return{relevance:0,value:f(t)};throw e}}function w(e,t){t=t||u.languages||r(o);var n={relevance:0,value:f(e)},i=n;return t.filter(E).filter(O).forEach(function(t){var r=y(t,e,!1);r.language=t,r.relevance>i.relevance&&(i=r),r.relevance>n.relevance&&(i=n,n=r)}),i.language&&(n.second_best=i),n}function x(e){return u.tabReplace||u.useBR?e.replace(l,function(e,t){return u.useBR&&"\n"===e?"
    ":u.tabReplace?t.replace(/\t/g,u.tabReplace):""}):e}function k(e){var t,r,o,a,l,c=function(e){var t,n,r,o,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",n=s.exec(i))return E(n[1])?n[1]:"no-highlight";for(i=i.split(/\s+/),t=0,r=i.length;t/g,"\n"):t=e,l=t.textContent,o=c?y(c,l,!0):w(l),(r=m(t)).length&&((a=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=o.value,o.value=function(e,t,r){var o=0,i="",a=[];function s(){return e.length&&t.length?e[0].offset!==t[0].offset?e[0].offset"}function c(e){i+=""}function u(e){("start"===e.event?l:c)(e.node)}for(;e.length||t.length;){var p=s();if(i+=f(r.substring(o,p[0].offset)),o=p[0].offset,p===e){a.reverse().forEach(c);do{u(p.splice(0,1)[0]),p=s()}while(p===e&&p.length&&p[0].offset===o);a.reverse().forEach(l)}else"start"===p[0].event?a.push(p[0].node):a.pop(),u(p.splice(0,1)[0])}return i+f(r.substr(o))}(r,m(a),l)),o.value=x(o.value),e.innerHTML=o.value,e.className=function(e,t,n){var r=t?i[t]:n,o=[e.trim()];e.match(/\bhljs\b/)||o.push("hljs");-1===e.indexOf(r)&&o.push(r);return o.join(" ").trim()}(e.className,c,o.language),e.result={language:o.language,re:o.relevance},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.relevance}))}function _(){if(!_.called){_.called=!0;var e=document.querySelectorAll("pre code");n.forEach.call(e,k)}}function E(e){return e=(e||"").toLowerCase(),o[e]||o[i[e]]}function O(e){var t=E(e);return t&&!t.disableAutodetect}e.highlight=y,e.highlightAuto=w,e.fixMarkup=x,e.highlightBlock=k,e.configure=function(e){u=g(u,e)},e.initHighlighting=_,e.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",_,!1),addEventListener("load",_,!1)},e.registerLanguage=function(t,n){var r=o[t]=n(e);b(r),r.aliases&&r.aliases.forEach(function(e){i[e]=t})},e.listLanguages=function(){return r(o)},e.getLanguage=E,e.autoDetection=O,e.inherit=g,e.IDENT_RE="[a-zA-Z]\\w*",e.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",e.NUMBER_RE="\\b\\d+(\\.\\d+)?",e.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BINARY_NUMBER_RE="\\b(0b[01]+)",e.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BACKSLASH_ESCAPE={begin:"\\\\[\\s\\S]",relevance:0},e.APOS_STRING_MODE={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},e.QUOTE_STRING_MODE={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},e.PHRASAL_WORDS_MODE={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.COMMENT=function(t,n,r){var o=e.inherit({className:"comment",begin:t,end:n,contains:[]},r||{});return o.contains.push(e.PHRASAL_WORDS_MODE),o.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|XXX):",relevance:0}),o},e.C_LINE_COMMENT_MODE=e.COMMENT("//","$"),e.C_BLOCK_COMMENT_MODE=e.COMMENT("/\\*","\\*/"),e.HASH_COMMENT_MODE=e.COMMENT("#","$"),e.NUMBER_MODE={className:"number",begin:e.NUMBER_RE,relevance:0},e.C_NUMBER_MODE={className:"number",begin:e.C_NUMBER_RE,relevance:0},e.BINARY_NUMBER_MODE={className:"number",begin:e.BINARY_NUMBER_RE,relevance:0},e.CSS_NUMBER_MODE={className:"number",begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},e.REGEXP_MODE={className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,{begin:/\[/,end:/\]/,relevance:0,contains:[e.BACKSLASH_ESCAPE]}]},e.TITLE_MODE={className:"title",begin:e.IDENT_RE,relevance:0},e.UNDERSCORE_TITLE_MODE={className:"title",begin:e.UNDERSCORE_IDENT_RE,relevance:0},e.METHOD_GUARD={begin:"\\.\\s*"+e.UNDERSCORE_IDENT_RE,relevance:0}})(t)}()},function(e,t){e.exports=function(e){var t={begin:/[A-Z\_\.\-]+\s*:/,returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute",begin:/\S/,end:":",excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0,contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in",begin:/[\w-]+/},{begin:/\(/,end:/\)/,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]}]},e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}]}}]};return{case_insensitive:!0,illegal:/[=\/|'\$]/,contains:[e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:/\.[A-Za-z0-9_-]+/},{className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$"},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"@(font-face|page)",lexemes:"[a-z-]+",keywords:"font-face page"},{begin:"@",end:"[{;]",illegal:/:/,contains:[{className:"keyword",begin:/\w+/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},{begin:"{",end:"}",illegal:/\S/,contains:[e.C_BLOCK_COMMENT_MODE,t]}]}}},function(e,t){e.exports=function(e){var t={literal:"true false null"},n=[e.QUOTE_STRING_MODE,e.C_NUMBER_MODE],r={end:",",endsWithParent:!0,excludeEnd:!0,contains:n,keywords:t},o={begin:"{",end:"}",contains:[{className:"attr",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE],illegal:"\\n"},e.inherit(r,{begin:/:/})],illegal:"\\S"},i={begin:"\\[",end:"\\]",contains:[e.inherit(r)],illegal:"\\S"};return n.splice(n.length,0,o,i),{contains:n,keywords:t,illegal:"\\S"}}},function(e,t){e.exports=function(e){var t="([\\w-]+|@{[\\w-]+})",n=[],r=[],o=function(e){return{className:"string",begin:"~?"+e+".*?"+e}},i=function(e,t,n){return{className:e,begin:t,relevance:n}},a={begin:"\\(",end:"\\)",contains:r,relevance:0};r.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,o("'"),o('"'),e.CSS_NUMBER_MODE,{begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]",excludeEnd:!0}},i("number","#[0-9A-Fa-f]+\\b"),a,i("variable","@@?[\\w-]+",10),i("variable","@{[\\w-]+}"),i("built_in","~?`[^`]*?`"),{className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0},{className:"meta",begin:"!important"});var s=r.concat({begin:"{",end:"}",contains:n}),l={beginKeywords:"when",endsWithParent:!0,contains:[{beginKeywords:"and not"}].concat(r)},c={begin:t+"\\s*:",returnBegin:!0,end:"[;}]",relevance:0,contains:[{className:"attribute",begin:t,end:":",excludeEnd:!0,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:r}}]},u={className:"keyword",begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{end:"[;{}]",returnEnd:!0,contains:r,relevance:0}},f={className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:s}},d={variants:[{begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:t,end:"{"}],returnBegin:!0,returnEnd:!0,illegal:"[<='$\"]",relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,l,i("keyword","all\\b"),i("variable","@{[\\w-]+}"),i("selector-tag",t+"%?",0),i("selector-id","#"+t),i("selector-class","\\."+t,0),i("selector-tag","&",0),{className:"selector-attr",begin:"\\[",end:"\\]"},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"\\(",end:"\\)",contains:s},{begin:"!important"}]};return n.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,u,f,c,d),{case_insensitive:!0,illegal:"[=>'/<($\"]",contains:n}}},function(e,t){e.exports=function(e){var t={className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"},n={className:"number",begin:"#[0-9A-Fa-f]+"};e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE;return{case_insensitive:!0,illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:"\\#[A-Za-z0-9_-]+",relevance:0},{className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},{className:"selector-attr",begin:"\\[",end:"\\]",illegal:"$"},{className:"selector-tag",begin:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",relevance:0},{begin:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"},{begin:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"},t,{className:"attribute",begin:"\\b(z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",illegal:"[^\\s]"},{begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{begin:":",end:";",contains:[t,n,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{className:"meta",begin:"!important"}]},{begin:"@",end:"[{;]",keywords:"mixin include extend for if else each while charset import debug media page content font-face namespace warn",contains:[t,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,n,e.CSS_NUMBER_MODE,{begin:"\\s[A-Za-z0-9_.-]+",relevance:0}]}]}}},function(e,t){e.exports=function(e){var t="[A-Za-z$_][0-9A-Za-z$_]*",n={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},r={className:"number",variants:[{begin:"\\b(0[bB][01]+)"},{begin:"\\b(0[oO][0-7]+)"},{begin:e.C_NUMBER_RE}],relevance:0},o={className:"subst",begin:"\\$\\{",end:"\\}",keywords:n,contains:[]},i={className:"string",begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE,o]};o.contains=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,r,e.REGEXP_MODE];var a=o.contains.concat([e.C_BLOCK_COMMENT_MODE,e.C_LINE_COMMENT_MODE]);return{aliases:["js","jsx"],keywords:n,contains:[{className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},{className:"meta",begin:/^#!/,end:/$/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,r,{begin:/[{,]\s*/,relevance:0,contains:[{begin:t+"\\s*:",returnBegin:!0,relevance:0,contains:[{className:"attr",begin:t,relevance:0}]}]},{begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.REGEXP_MODE,{className:"function",begin:"(\\(.*?\\)|"+t+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:t},{begin:/\(\s*\)/},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,contains:a}]}]},{className:"",begin:/\s/,end:/\s*/,skip:!0},{begin://,subLanguage:"xml",contains:[{begin:/<[A-Za-z0-9\\._:-]+\s*\/>/,skip:!0},{begin:/<[A-Za-z0-9\\._:-]+/,end:/(\/[A-Za-z0-9\\._:-]+|[A-Za-z0-9\\._:-]+\/)>/,skip:!0,contains:[{begin:/<[A-Za-z0-9\\._:-]+\s*\/>/,skip:!0},"self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/\{/,excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:t}),{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:a}],illegal:/\[|%/},{begin:/\$[(.]/},e.METHOD_GUARD,{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"constructor get set",end:/\{/,excludeEnd:!0}],illegal:/#(?!!)/}}},function(e,t){e.exports=function(e){var t={keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class public private protected get set super static implements enum export import declare type namespace abstract as from extends async await",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document any number boolean string void Promise"},n={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*"},r={begin:"\\(",end:/\)/,keywords:t,contains:["self",e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.NUMBER_MODE]},o={className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,n,r]};return{aliases:["ts"],keywords:t,contains:[{className:"meta",begin:/^\s*['"]use strict['"]/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string",begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE,{className:"subst",begin:"\\$\\{",end:"\\}"}]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"number",variants:[{begin:"\\b(0[bB][01]+)"},{begin:"\\b(0[oO][0-7]+)"},{begin:e.C_NUMBER_RE}],relevance:0},{begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.REGEXP_MODE,{className:"function",begin:"(\\(.*?\\)|"+e.IDENT_RE+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:e.IDENT_RE},{begin:/\(\s*\)/},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:["self",e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]}]}]}],relevance:0},{className:"function",begin:"function",end:/[\{;]/,excludeEnd:!0,keywords:t,contains:["self",e.inherit(e.TITLE_MODE,{begin:"[A-Za-z$_][0-9A-Za-z$_]*"}),o],illegal:/%/,relevance:0},{beginKeywords:"constructor",end:/\{/,excludeEnd:!0,contains:["self",o]},{begin:/module\./,keywords:{built_in:"module"},relevance:0},{beginKeywords:"module",end:/\{/,excludeEnd:!0},{beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:"interface extends"},{begin:/\$[(.]/},{begin:"\\."+e.IDENT_RE,relevance:0},n,r]}}},function(e,t,n){"use strict";t.__esModule=!0;var r=83,o=90,i=89,a=9;t.default=function(e,t){e.addEventListener("keydown",function(e){if(e.ctrlKey||e.metaKey||e.altKey||e.shiftKey){if((e.ctrlKey||e.metaKey)&&!e.altKey&&!e.shiftKey)switch(e.keyCode){case o:e.preventDefault(),t("undo");break;case i:e.preventDefault(),t("redo");break;case r:e.preventDefault(),t("save")}}else switch(e.keyCode){case a:e.preventDefault(),t("tab")}})}},function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t};t.__esModule=!0;var a=i(n(0)),s=function(e){function t(t){var n=e.call(this,t)||this;return n.state={imgHidden:!0,imgList:[]},n}return o(t,e),t.prototype.onClick=function(e){this.props.onClick(e)},t.prototype.imgClick=function(){this.setState({imgHidden:!this.state.imgHidden})},t.prototype.imgMouseOver=function(){window.clearTimeout(this.timer),this.setState({imgHidden:!1})},t.prototype.imgMouseOut=function(){var e=this;this.timer=window.setTimeout(function(){e.setState({imgHidden:!0})},150)},t.prototype.addImgUrl=function(){this.props.onClick("img")},t.prototype.addImgFile=function(e){var t=this.state.imgList,n=t.length;t.push(e.target.files[0]),this.setState({imgList:t}),this.props.addImg(e.target.files[0],n),e.target.value=""},t.prototype.render=function(){var e=this,t=this.props,n=t.toolbar,r=t.words,o=this.state.imgHidden;return a.createElement("ul",null,n.undo&&a.createElement("li",{onClick:function(){return e.onClick("undo")},title:r.undo+" (ctrl+z)"},a.createElement("i",{className:"foricon for-undo"})),n.redo&&a.createElement("li",{onClick:function(){return e.onClick("redo")},title:r.redo+" (ctrl+y)"},a.createElement("i",{className:"foricon for-redo"})),n.h1&&a.createElement("li",{onClick:function(){return e.onClick("h1")},title:r.h1},"H1"),n.h2&&a.createElement("li",{onClick:function(){return e.onClick("h2")},title:r.h2},"H2"),n.h3&&a.createElement("li",{onClick:function(){return e.onClick("h3")},title:r.h3},"H3"),n.h4&&a.createElement("li",{onClick:function(){return e.onClick("h4")},title:r.h4},"H4"),n.img&&a.createElement("li",{className:"for-toolbar-img",onMouseOver:function(){return e.imgMouseOver()},onMouseOut:function(){return e.imgMouseOut()}},a.createElement("i",{className:"foricon for-image"}),a.createElement("ul",{style:o?{display:"none"}:{}},a.createElement("li",{onClick:function(){return e.addImgUrl()}},r.addImgLink),a.createElement("li",null,r.addImg,a.createElement("input",{type:"file",accept:"image/gif,image/jpeg,image/jpg,image/png,image/svg",onChange:function(t){return e.addImgFile(t)}})))),n.link&&a.createElement("li",{onClick:function(){return e.onClick("link")},title:r.link},a.createElement("i",{className:"foricon for-link"})),n.code&&a.createElement("li",{onClick:function(){return e.onClick("code")},title:r.code},a.createElement("i",{className:"foricon for-code"})),n.save&&a.createElement("li",{onClick:function(){return e.onClick("save")},title:r.save+" (ctrl+s)"},a.createElement("i",{className:"foricon for-save"})))},t.defaultProps={onClick:function(){},toolbar:{},words:{}},t}(a.Component);t.default=s},function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};t.__esModule=!0;var s=i(n(0)),l=a(n(3)),c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.onClick=function(e){this.props.onClick(e)},t.prototype.render=function(){var e=this,t=this.props,n=t.preview,r=t.expand,o=t.subfield,i=t.toolbar,a=t.words,c=l.default({"for-active":n}),u=l.default({"for-active":r}),f=l.default({"for-active":o});return s.createElement("ul",null,i.expand&&s.createElement("li",{className:u,onClick:function(){return e.onClick("expand")},title:u?a.fullscreenOff:a.fullscreenOn},u?s.createElement("i",{className:"foricon for-contract"}):s.createElement("i",{className:"foricon for-expand"})),i.preview&&s.createElement("li",{className:c,onClick:function(){return e.onClick("preview")},title:a.preview},c?s.createElement("i",{className:"foricon for-eye-off"}):s.createElement("i",{className:"foricon for-eye"})),i.subfield&&s.createElement("li",{className:f,onClick:function(){return e.onClick("subfield")},title:f?a.singleColumn:a.doubleColumn},s.createElement("i",{className:"foricon for-subfield"})))},t.defaultProps={onClick:function(){},toolbars:{},words:{}},t}(s.Component);t.default=c},function(e,t,n){"use strict";t.__esModule=!0,t.insertText=function(e,t){var n=t.prefix,r=t.str,o=void 0===r?"":r,i=t.subfix,a=void 0===i?"":i,s=e.value;if(e.selectionStart||0===e.selectionStart){var l=e.selectionStart,c=e.selectionEnd,u=e.scrollTop;l===c?(e.value=s.substring(0,l)+n+o+a+s.substring(c,s.length),e.selectionStart=l+n.length,e.selectionEnd=c+n.length+o.length):(e.value=s.substring(0,l)+n+s.substring(l,c)+a+s.substring(c,s.length),e.selectionStart=l+n.length,e.selectionEnd=c+n.length),e.focus(),u>=0&&(e.scrollTop=u)}return e.value}},function(e,t,n){var r=n(24);"string"==typeof r&&(r=[[e.i,r,""]]);var o={hmr:!0,transform:void 0,insertInto:void 0};n(2)(r,o);r.locals&&(e.exports=r.locals)},function(e,t,n){(e.exports=n(1)(!1)).push([e.i,"/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */\n\n/* Tomorrow Comment */\n.hljs-comment,\n.hljs-quote {\n color: #8e908c;\n}\n\n/* Tomorrow Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-deletion {\n color: #c82829;\n}\n\n/* Tomorrow Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-meta,\n.hljs-link {\n color: #f5871f;\n}\n\n/* Tomorrow Yellow */\n.hljs-attribute {\n color: #eab700;\n}\n\n/* Tomorrow Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n color: #718c00;\n}\n\n/* Tomorrow Blue */\n.hljs-title,\n.hljs-section {\n color: #4271ae;\n}\n\n/* Tomorrow Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n color: #8959a8;\n}\n\n.hljs {\n display: block;\n overflow-x: auto;\n background: white;\n color: #4d4d4c;\n padding: 0.5em;\n}\n\n.hljs-emphasis {\n font-style: italic;\n}\n\n.hljs-strong {\n font-weight: bold;\n}\n",""])},function(e,t){e.exports=function(e){var t="undefined"!=typeof window&&window.location;if(!t)throw new Error("fixUrls requires window.location");if(!e||"string"!=typeof e)return e;var n=t.protocol+"//"+t.host,r=n+t.pathname.replace(/\/[^\/]*$/,"/");return e.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi,function(e,t){var o,i=t.trim().replace(/^"(.*)"$/,function(e,t){return t}).replace(/^'(.*)'$/,function(e,t){return t});return/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(i)?e:(o=0===i.indexOf("//")?i:0===i.indexOf("/")?n+i:r+i.replace(/^\.\//,""),"url("+JSON.stringify(o)+")")})}},function(e,t,n){var r=n(27);"string"==typeof r&&(r=[[e.i,r,""]]);var o={hmr:!0,transform:void 0,insertInto:void 0};n(2)(r,o);r.locals&&(e.exports=r.locals)},function(e,t,n){t=e.exports=n(1)(!1);var r=n(28),o=r(n(4)),i=r(n(4)+"#iefix"),a=r(n(29)),s=r(n(30)),l=r(n(31)+"#foricon");t.push([e.i,'@font-face {font-family: "foricon";\n src: url('+o+"); /* IE9 */\n src: url("+i+") format('embedded-opentype'), \n url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAiYAAsAAAAAEKwAAAhKAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCECgqTEI8pATYCJAM0CxwABCAFhGEHgQgb4Q2jopRu9sj+IsE2lvbwQSEYAzUIDVc+fN1ilSTZf3ZUbnJocJqIh//2+98+M3NF/0fUmunqJEIRD43EIpEgxN8JiYiHpKF4KJDe5VxtAY3K+PZI3iMqVJhLNy2nn24PFGj5yvD846b94P0JUAkJVZkYzCTMlO2FZE47N3oeTjm480jroXU6c2FiGrchXq82lhAo7AS5xIq3b779XN2Nd6hHnWV6+XfTs203xPQjYiERNSQ8ingVbYRMKpRCKQl4vjE1L2vqzkLL0a+QscB230ygt13EuH5++wC+IqJBm8d5ysFXUhRDWGidtebEIl4CR5ueqw4DL8qfj78m4ZNUWXTgjbtnCRz+YHeaqDcK5znXAIu7LIw3I+MoUMbiodZ9GyyWEZY+x3baTAtdfkhRwA/k5qvFqJOsqFb/8hqtTm8wErWIjUxYUVJ/IJViyYmU4IaU4Y5U4IFUwROphhdSA2+kFj5IHXyRevghDXBhvTKvqdNmYC/I49z8ThR4W05S+ZeFpy0ThYMzZAuBmbDIyGgsOiEhMSEjI6+mOkWmRx5dxoTjBoMeajQe0Y/n8JzFRWcdGwkBkpW8xLiENNZpaVQFTRwMJqOMkkSMjB3OC+Mlih4D5umdPFvbEF+8NaOqzlqwhTVVbbZqCrdkmmu3xWuLto7meWjyi4RakkizIIASXFaf0XWu86jObvjpsYenOyd9mpFeEu4mtfRMmz2lI1Vw7Uk3GpAQxCtC6OcBcAKKqOiSimu9xOQ6MAhqD1+33ZTlFSdcO24CEbuNGlYqrsnToAvHd2e3YDFeagAaIKVlTXY1YNM5NgBAEMjJ1+iZJLoohKdxJkaJ35SfZU5SUSrxCRbkRKHdZhJ5xg4HdNQvsTi6ynS4+niCqvREGzQg4PLpHL7Q4nRZz7Hqoq3j9d9zNuRxum6//2+93lVNWKmhlpRQtHpDo/pYoZpEpWKirGvoYFtChH6cx/GqjKocuu4054kzgZqwxUunh876yaH50kyBZBsOBd6Wwy1Xn6WuCuchUbOxcShOrKkqsJR2QerPtBFQsnZddm0TtuGcd57n6xIeQ2UeI66FdK4DwNdBzB+qTw9B6NtyddlwTtukgTQK9eB1VOFAECwdAzfPIiCvoqesKRAT6/j5e7xFvmGiCcMneA43EeRbDL8K5NW8wvGovzXFhDkMMm7lFv11nGWhQEpkp0XdKL88ngmvZoFznZiq8TMV46ddte2GqhKr61izpqrqbKYgz0sR7FLMdLkKf4ZDu7iD9iIzjBrMjGmN0jhbRNpGG7RvWxvfyA5tG9Ng2s0Ldmi/uVZrC9kibEfkwo6EBKFb127dEIRN3+f2z9xqa41mZJ3bjPTP6zWrtXZ61ffrpVu1HpI5qtq2MSbeJue72Tc/3y7b4XZol0tVcnOdTyemjS5pfU4xl98FlPJF4Hhg9nf51vyxs/YX/K36W3sxNHBkPjll8PiLwV+POsH06cCp6e1299YcHjkYi3brvH0HxQ6hqFf/DuprNehxZ2sQ3leMKRjowzBmn+L7dz2kmfAVpdbWv3s/n1DI+f170tkblmCe+SRsXqE1V7S3lKkQy+pQogcBRaezZLfvgkwYNWXecCuFGAyVmvmtliWkRqRmF3PM11Yb9NO05dQmJjdpYyvQGUxrVSqHP4RN5dQ0ba6+WjvfsTShlcG2NL77fG2VLpdSDbfOyx8/CunSLidTqwPBbT9yLgMwuLhB+kJd68z+9ilz5CGGXkcbjUEGczCqJzB9FGhxRhX8lfP2aNOpl4/uRNt9v9f/c+n5PzAi+Do1XTpgwC5k1ZomR+yeJZqgjBrmPHvpPLM+8UUXupI0gEkeEBqY7BqQfNn7Y1gTj10+8qUHvv33P1zb1T1c9MP3PXp17FXQs1OPnj5f6J+Lz/+FnPw67XFxx/7i3i77o0AhlWQLos9SV66OciUPBMlKiufT/6N7p7eWSnqRzj9Nnny5eUx7U7RRNkYZgSnKRFa0iQoaDSdlji95p/vwxeQwU2aHabvREabCDiOYc7sEewoR9Mny6/IX7Dr2RUaWP0FL7t/zkM+IxY40zWYIqqAl9x54iGekd0mJTIv0RpWKpajnwb2SBvS6BVSWIvAp9t6UDR2a8QeWlKr9NFh4M6iA5W9/IwHp2bvv4M08Op/0zC4Oz37406nThlFsXkD3bjoUdzLMF3/prOovDTsws+J0SJtOm6aj6ZhWoXwox5SXuYBJo9Hjup5Df5jTydvFWHoCt/IZylTWVES2pyXRYP0P2+anqkkAi7Alq1PUsDdJ1inWRg3YjRJ+yLlsfkph0CxBZG3VyMDxGQwifUX993Anz6TaH93m3dc++i9yxvc/eXZQsgjbwE1xK4loOMR//SzCCWVli1Knshi71OwgcfKEW5XQx+UsQFSw2td5xDoxzkmjWMYgwa0gwz2gwMO6yuCUrtY4r+sdcbL5YI2GJUpHK7FFF2avQIKvQYafQIGfdZX1/km9gv91vZvhXXCwP17CE42cMGGzFcuFamTipjCjetD6DtO+4npiLeKeUHd5GRsPRrX6C2xQtz+gm6cTIsmkVjU7792SsKoUa7UqUNAgI2qnw6HUHToQqobQNRriKDdNMDOr5DlBacgcEu5cur/ZHZTqVfh4CP0QStgTJN0EszhmbGBkBheskQx5DZ07c6kJirMklhLdr6sx51elQKpxjcK0elIMmgtkIGtR1ZoaxlNJKRucV9ShvQB60QdOkSJHiSrqaKKNLvoYYowpZuWWStDJa56ihSt0cdnyJrE1Jsrum+xw56NXhHaVN6Xd8Tn6L0tFmgvyhEfESkpPqKqvmw4AAA==') format('woff2'),\n url("+a+") format('woff'),\n url("+s+") format('truetype'), \n url("+l+') format(\'svg\'); /* iOS 4.1- */\n}\n\n.foricon {\n font-family: "foricon" !important;\n font-size: inherit;\n font-style: normal;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n.for-code:before {\n content: "\\e620";\n}\n\n.for-image:before {\n content: "\\e621";\n}\n\n.for-eye:before {\n content: "\\e622";\n}\n\n.for-expand:before {\n content: "\\e623";\n}\n\n.for-redo:before {\n content: "\\e624";\n}\n\n.for-undo:before {\n content: "\\e625";\n}\n\n.for-quote:before {\n content: "\\e626";\n}\n\n.for-link:before {\n content: "\\e627";\n}\n\n.for-save:before {\n content: "\\e628";\n}\n\n.for-contract:before {\n content: "\\e629";\n}\n\n.for-eye-off:before {\n content: "\\e62a";\n}\n\n.for-subfield:before {\n content: "\\e62b";\n}\n\n',""])},function(e,t,n){"use strict";e.exports=function(e,t){return"string"!=typeof e?e:(/^['"].*['"]$/.test(e)&&(e=e.slice(1,-1)),/["'() \t\n]/.test(e)||t?'"'+e.replace(/"/g,'\\"').replace(/\n/g,"\\n")+'"':e)}},function(e,t,n){e.exports=n.p+"static/fonts/iconfont.fe07082d.woff"},function(e,t,n){e.exports=n.p+"static/fonts/iconfont.a614fc0f.ttf"},function(e,t,n){e.exports=n.p+"static/fonts/iconfont.35e220a6.svg"},function(e,t,n){var r=n(33);"string"==typeof r&&(r=[[e.i,r,""]]);var o={hmr:!0,transform:void 0,insertInto:void 0};n(2)(r,o);r.locals&&(e.exports=r.locals)},function(e,t,n){(e.exports=n(1)(!1)).push([e.i,".for-container {\n font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;\n display: flex;\n flex-direction: column;\n height: 600px;\n border: 1px solid #ddd;\n border-radius: 8px;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 12px;\n background: #fff;\n font-size: 14px; }\n .for-container ul,\n .for-container ol,\n .for-container li {\n margin: 0;\n padding: 0; }\n .for-container.for-fullscreen {\n position: fixed;\n z-index: 99999;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n height: 100% !important; }\n .for-container > div:first-child {\n border-top-left-radius: 8px;\n border-top-right-radius: 8px; }\n .for-container .for-hidden {\n display: none; }\n .for-container .for-toolbar {\n font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;\n display: flex;\n justify-content: space-between;\n padding: 0 6px;\n border-bottom: 1px solid #ddd;\n color: #555;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none; }\n .for-container .for-toolbar > ul {\n display: flex; }\n .for-container .for-toolbar > ul > li {\n display: flex;\n align-items: center;\n padding: 4px 6px;\n margin: 8px 4px;\n border-radius: 4px;\n line-height: normal; }\n .for-container .for-toolbar > ul > li.for-toolbar-img {\n position: relative; }\n .for-container .for-toolbar > ul > li.for-toolbar-img > ul {\n position: absolute;\n top: 100%;\n left: -50px;\n width: 140px;\n margin-top: 4px;\n background: #fff;\n border-radius: 4px;\n box-shadow: rgba(0, 0, 0, 0.1) 0 2px 8px 0;\n z-index: 99;\n line-height: 2.8;\n text-align: center; }\n .for-container .for-toolbar > ul > li.for-toolbar-img > ul li {\n position: relative; }\n .for-container .for-toolbar > ul > li.for-toolbar-img > ul li:hover {\n background: #e9e9e9; }\n .for-container .for-toolbar > ul > li.for-toolbar-img > ul li:first-child {\n border-radius: 4px 4px 0 0; }\n .for-container .for-toolbar > ul > li.for-toolbar-img > ul li:last-child {\n border-radius: 0 0 4px 4px; }\n .for-container .for-toolbar > ul > li.for-toolbar-img > ul li input {\n position: absolute;\n width: 100%;\n opacity: 0;\n left: 0;\n top: 0;\n bottom: 0;\n cursor: pointer; }\n .for-container .for-toolbar > ul > li.for-active {\n background: #ddd; }\n .for-container .for-toolbar > ul > li:hover {\n cursor: pointer;\n background: #e9e9e9; }\n .for-container .for-toolbar > ul > li i {\n font-size: 1.2em; }\n .for-container .for-editor {\n display: flex;\n justify-content: space-between;\n height: 100%;\n color: #2c3e50;\n border-radius: 0 0 8px 8px;\n overflow: hidden; }\n .for-container .for-editor .for-panel {\n height: 100%;\n flex: 0 0 100%;\n overflow: auto;\n transition: all 0.2s linear 0s; }\n .for-container .for-editor .for-panel.for-active {\n flex: 0 0 50%; }\n .for-container .for-editor .for-panel .for-preview {\n min-height: 100%;\n box-sizing: border-box;\n padding: 10px 14px;\n background: #fcfcfc; }\n .for-container .for-editor .for-editor-edit {\n line-height: 1.6;\n height: 100%; }\n .for-container .for-editor .for-editor-edit.for-edit-preview {\n width: 0;\n flex: 0 0 0; }\n .for-container .for-editor .for-editor-edit .for-editor-block {\n display: flex;\n min-height: 100%; }\n .for-container .for-editor .for-editor-edit .for-line-num {\n list-style: none;\n background: #eee;\n padding: 8px 0 120px;\n min-width: 30px;\n text-align: center; }\n .for-container .for-editor .for-editor-edit .for-line-num.hidden {\n display: none; }\n .for-container .for-editor .for-editor-edit .for-line-num li {\n list-style: none; }\n .for-container .for-editor .for-editor-edit .for-editor-content {\n flex: 1;\n position: relative;\n height: 100%;\n margin-left: 10px; }\n .for-container .for-editor .for-editor-edit .for-editor-content pre {\n padding: 8px 0;\n display: block;\n white-space: pre-wrap;\n word-wrap: break-word;\n visibility: hidden;\n margin: 0;\n font-family: inherit; }\n .for-container textarea {\n font-family: 'Consolas', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;\n box-sizing: border-box;\n position: absolute;\n top: 0;\n bottom: 0;\n padding: 8px 0;\n display: block;\n height: 100%;\n width: 100%;\n overflow: hidden;\n resize: none;\n border: none;\n outline: none;\n font-size: inherit;\n color: inherit;\n background: none;\n line-height: inherit; }\n .for-container .for-markdown-preview {\n line-height: 2; }\n .for-container .for-markdown-preview p,\n .for-container .for-markdown-preview blockquote,\n .for-container .for-markdown-preview ul,\n .for-container .for-markdown-preview ol,\n .for-container .for-markdown-preview dl,\n .for-container .for-markdown-preview pre {\n margin-top: 0;\n margin-bottom: 0.6em; }\n .for-container .for-markdown-preview h1,\n .for-container .for-markdown-preview h2 {\n border-bottom: 1px solid #e2e2e2; }\n .for-container .for-markdown-preview h1,\n .for-container .for-markdown-preview h2,\n .for-container .for-markdown-preview h3,\n .for-container .for-markdown-preview h4,\n .for-container .for-markdown-preview h5,\n .for-container .for-markdown-preview h6 {\n padding: 0;\n margin: 0 0 0.6em;\n font-weight: 600;\n text-indent: 0; }\n .for-container .for-markdown-preview h1:target,\n .for-container .for-markdown-preview h2:target,\n .for-container .for-markdown-preview h3:target,\n .for-container .for-markdown-preview h4:target,\n .for-container .for-markdown-preview h5:target,\n .for-container .for-markdown-preview h6:target {\n padding-top: 4.5rem; }\n .for-container .for-markdown-preview a {\n color: #0366d6;\n text-decoration: none; }\n .for-container .for-markdown-preview a:hover {\n text-decoration: underline; }\n .for-container .for-markdown-preview ul,\n .for-container .for-markdown-preview ol {\n padding: 0.2em 0.8em; }\n .for-container .for-markdown-preview ul > li,\n .for-container .for-markdown-preview ol > li {\n line-height: 2;\n padding-left: 0.2em;\n margin-left: 0.2em;\n list-style-type: disc; }\n .for-container .for-markdown-preview ul > li > p,\n .for-container .for-markdown-preview ol > li > p {\n text-indent: 0; }\n .for-container .for-markdown-preview ul > li > ul:last-child,\n .for-container .for-markdown-preview ol > li > ul:last-child {\n margin-bottom: 0; }\n .for-container .for-markdown-preview ul > li > ul li,\n .for-container .for-markdown-preview ol > li > ul li {\n list-style-type: circle; }\n .for-container .for-markdown-preview ul > li > ul li > ul li,\n .for-container .for-markdown-preview ol > li > ul li > ul li {\n list-style-type: square; }\n .for-container .for-markdown-preview > ul,\n .for-container .for-markdown-preview ol {\n padding: 0 20px; }\n .for-container .for-markdown-preview ol > li {\n list-style-type: decimal; }\n .for-container .for-markdown-preview blockquote {\n margin: 0;\n margin-bottom: 0.6em;\n padding: 0 1em;\n color: #6a737d;\n border-left: 0.25em solid #dfe2e5; }\n .for-container .for-markdown-preview blockquote p {\n text-indent: 0; }\n .for-container .for-markdown-preview blockquote p:first-child {\n margin-top: 0; }\n .for-container .for-markdown-preview blockquote p:last-child {\n margin-bottom: 0; }\n .for-container .for-markdown-preview pre {\n padding: 0.6em;\n overflow: auto;\n line-height: 1.6;\n background-color: #f0f0f0;\n border-radius: 3px; }\n .for-container .for-markdown-preview pre code {\n padding: 0;\n margin: 0;\n font-size: 100%;\n background: transparent; }\n .for-container .for-markdown-preview code {\n padding: 0.2em 0.4em;\n margin: 0;\n background-color: #f0f0f0;\n border-radius: 3px; }\n .for-container .for-markdown-preview hr {\n margin-bottom: 0.6em;\n height: 1px;\n background: #dadada;\n border: none; }\n .for-container .for-markdown-preview table {\n width: 100%;\n border: 1px solid #ddd;\n margin-bottom: 0.6em;\n border-collapse: collapse;\n text-align: left; }\n .for-container .for-markdown-preview table thead {\n background: #eee; }\n .for-container .for-markdown-preview table th,\n .for-container .for-markdown-preview table td {\n padding: 0.1em 0.4em;\n border: 1px solid #ddd; }\n .for-container .for-markdown-preview img {\n display: block;\n margin: 0 auto;\n max-width: 100%;\n margin-bottom: 0.6em; }\n",""])},function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};t.__esModule=!0;var o=r(n(35)),i=r(n(36));t.CONFIG={language:{"zh-CN":o.default,en:i.default},langList:["zh-CN","en"],toolbar:{h1:!0,h2:!0,h3:!0,h4:!0,img:!0,link:!0,code:!0,preview:!0,expand:!0,undo:!0,redo:!0,save:!0,subfield:!0}}},function(e){e.exports=JSON.parse('{"placeholder":"开始编辑...","undo":"上一步","redo":"下一步","h1":"一级标题","h2":"二级标题","h3":"三级标题","h4":"四级标题","img":"添加图片链接","link":"链接","code":"代码块","save":"保存","preview":"预览","singleColumn":"单栏","doubleColumn":"双栏","fullscreenOn":"全屏编辑","fullscreenOff":"退出全屏","addImgLink":"添加图片链接","addImg":"上传图片"}')},function(e){e.exports=JSON.parse('{"placeholder":"Begin editing...","undo":"Undo","redo":"Redo","h1":"Header 1","h2":"Header 2","h3":"Header 3","h4":"Header 4","img":"Image Link","link":"Link","code":"Code","save":"Save","preview":"Preview","singleColumn":"Single Column","doubleColumn":"Double Columns","fullscreenOn":"FullScreen ON","fullscreenOff":"FullScreen OFF","addImgLink":"Add Image Link","addImg":"Upload Image"}')}])}); -------------------------------------------------------------------------------- /dist/static/fonts/iconfont.0f693eba.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkfor/for-editor/d97c009dd13c39c02163327a85500cf4de1cc90a/dist/static/fonts/iconfont.0f693eba.eot -------------------------------------------------------------------------------- /dist/static/fonts/iconfont.35e220a6.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 | -------------------------------------------------------------------------------- /dist/static/fonts/iconfont.a614fc0f.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkfor/for-editor/d97c009dd13c39c02163327a85500cf4de1cc90a/dist/static/fonts/iconfont.a614fc0f.ttf -------------------------------------------------------------------------------- /dist/static/fonts/iconfont.fe07082d.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkfor/for-editor/d97c009dd13c39c02163327a85500cf4de1cc90a/dist/static/fonts/iconfont.fe07082d.woff -------------------------------------------------------------------------------- /doc/UPDATELOG.md: -------------------------------------------------------------------------------- 1 | - 2019-12-11 v0.3.5 2 | - 修复双栏,预览,全屏bug [#45](https://github.com/kkfor/for-editor/pull/45) 3 | - 2019-08-20 v0.3.4 4 | - 修复typescrit定义问题 [#36](https://github.com/kkfor/for-editor/issues/35) 5 | - 2019-08-20 v0.3.2 6 | - 修复图片上传bug 7 | - 优化typescript d.ts声明 [#35](https://github.com/kkfor/for-editor/issues/35) 8 | - 2019-08-19 v0.3.1 9 | - 添加图片上传功能 [#32](https://github.com/kkfor/for-editor/issues/32) 10 | - 优化代码 11 | - 2019-07-05 v0.3.0 12 | - 添加d.ts声明文件,修复bug [#27](https://github.com/kkfor/for-editor/issues/27) 13 | - 2019-07-03 v0.2.9 14 | - 修复bug [#26](https://github.com/kkfor/for-editor/issues/26) 15 | - 2019-07-03 v0.2.8 16 | - 新增预览设置,支持中文、英文 17 | - 2019-07-01 v0.2.7 18 | - 修复bug [#24](https://github.com/kkfor/for-editor/issues/24) 19 | - 优化样式 20 | - 2019-06-21 v0.2.6 21 | - 优化一些样式 22 | - 2019-06-20 v0.2.5 23 | - 新增工具栏按钮显示隐藏功能 24 | - 优化预览过渡效果 25 | - 2019-06-19 v0.2.3 26 | - 修复双栏模式bug 27 | - 2019-06-19 v0.2.2 28 | - 增加同步滚动功能 29 | - 增加双栏模式 30 | - 2019-06-17 v0.2.1 31 | - 修复预览样式bug 32 | - 2019-06-17 v0.2.0 33 | - 重构项目,优化页面结构 34 | - 2019-02-02 v0.0.12 35 | - 修复编辑器自定义高度bug 36 | - 2019-01-10 v0.0.11 37 | - 优化代码预览样式 38 | - 2019-01-09 v0.0.10 39 | - 优化代码结构 40 | - 2019-01-07 v0.0.9 41 | - 新增上一步,下一步,tab快捷键功能 42 | - 新增保存功能 43 | - 优化图标状态 44 | - 优化页面样式 45 | - 2018-12-29 v0.0.8 46 | - 添加行号显示功能 47 | - 优化快捷插入标签时,光标选中文本内容 48 | - 修复异步加载数据时编辑框回显问题 49 | - 优化编辑区域行间距 50 | - 2018-12-27 v0.0.6 51 | - 优化图标按钮 52 | - 修改组件UnMount时错误bug 53 | - 新增组件placeholder属性 54 | - 2018-12-26 v0.0.5 55 | - 添加上一步,下一步按钮及功能 56 | - 2018-12-25 v0.0.4 57 | - 修复firefox下显示bug 58 | - 2018-12-24 v0.0.3 59 | - 增加全屏功能 60 | - 修改onChange参数为输入框内容 61 | - 优化编辑框输入字体 62 | - 修复快捷插入标签时,滚动条位置bug 63 | - 修复firefox下显示问题 64 | - 2018-12-23 v0.0.0 65 | - 编辑器基础功能,快捷插入markdown标签,预览功能 -------------------------------------------------------------------------------- /example/globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.md' -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | for-editor | 基于react的markdown编辑器 8 | 9 | 10 | 11 |
    12 | 13 | -------------------------------------------------------------------------------- /example/index.scss: -------------------------------------------------------------------------------- 1 | #root { 2 | height: 100%; 3 | } -------------------------------------------------------------------------------- /example/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './src/app' 4 | import './index.scss' 5 | 6 | ReactDOM.render(, document.getElementById('root')) 7 | -------------------------------------------------------------------------------- /example/src/app.module.scss: -------------------------------------------------------------------------------- 1 | html { 2 | height: 100%; 3 | } 4 | 5 | body { 6 | height: 100%; 7 | margin: 0; 8 | } 9 | 10 | .main { 11 | padding-bottom: 40px; 12 | 13 | h1, 14 | ul, 15 | li { 16 | margin: 0; 17 | padding: 0; 18 | } 19 | 20 | ul, 21 | li { 22 | list-style: none; 23 | } 24 | 25 | a { 26 | color: inherit; 27 | } 28 | 29 | .top { 30 | display: flex; 31 | justify-content: space-between; 32 | height: 80px; 33 | line-height: 80px; 34 | padding: 0 20px; 35 | margin-bottom: 30px; 36 | font-size: 18px; 37 | color: #fff; 38 | background: linear-gradient(160deg, #852178, #019845); 39 | } 40 | 41 | .editor { 42 | width: 90%; 43 | max-width: 1400px; 44 | margin: 0 auto; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /example/src/app.module.scss.d.ts: -------------------------------------------------------------------------------- 1 | // This file is automatically generated. 2 | // Please do not change this file! 3 | interface CssExports { 4 | 'editor': string; 5 | 'main': string; 6 | 'top': string; 7 | } 8 | declare var cssExports: CssExports; 9 | export = cssExports; 10 | -------------------------------------------------------------------------------- /example/src/app.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Editor from '../../src/index' 3 | // import Editor from '../../dist' 4 | import * as styles from './app.module.scss' 5 | import value from '../static/help.md' 6 | 7 | interface IS { 8 | value: string 9 | mobile: boolean 10 | } 11 | 12 | 13 | class App extends Component<{}, IS> { 14 | 15 | private $vm = React.createRef() 16 | 17 | constructor(props: any) { 18 | super(props) 19 | 20 | this.state = { 21 | value: '', 22 | mobile: false 23 | } 24 | } 25 | 26 | componentDidMount() { 27 | this.resize() 28 | window.addEventListener('resize', () => { 29 | this.resize() 30 | }) 31 | setTimeout(() => { 32 | this.setState({ 33 | value 34 | }) 35 | }, 200) 36 | } 37 | 38 | resize() { 39 | if (window.matchMedia('(min-width: 768px)').matches) { 40 | this.setState({ 41 | mobile: false 42 | }) 43 | } else { 44 | this.setState({ 45 | mobile: true 46 | }) 47 | } 48 | } 49 | 50 | handleChange(value: string) { 51 | this.setState({ 52 | value 53 | }) 54 | } 55 | 56 | handleSave(value: string) { 57 | console.log('触发保存事件', value) 58 | } 59 | 60 | addImg($file: File) { 61 | this.$vm.current.$img2Url($file.name, 'file_url') 62 | console.log($file) 63 | } 64 | 65 | render() { 66 | const { value, mobile } = this.state 67 | 68 | return ( 69 |
    70 | 84 |
    85 | {mobile && ( 86 | this.handleChange(value)} 99 | onSave={value => this.handleSave(value)} 100 | /> 101 | )} 102 | {!mobile && ( 103 | this.addImg($file)} 109 | onChange={value => this.handleChange(value)} 110 | onSave={value => this.handleSave(value)} 111 | /> 112 | )} 113 |
    114 |
    115 | ) 116 | } 117 | } 118 | 119 | export default App 120 | -------------------------------------------------------------------------------- /example/static/help.md: -------------------------------------------------------------------------------- 1 | > `for-editor` is a markdown editor 2 | 3 | # for-editor 4 | 5 | this is a markdown editor 6 | 7 | ## for-editor 8 | 9 | this is a markdown editor 10 | 11 | ### for-editor 12 | 13 | ```js 14 | const editor = 'for-editor' 15 | ``` 16 | 17 | - item1 18 | - subitem1 19 | - subitem2 20 | - subitem3 21 | - item2 22 | - item3 23 | 24 | --- 25 | 26 | 1. item1 27 | 2. item2 28 | 3. item3 29 | 30 | ### table 31 | 32 | | title | description | 33 | | ---------- | --------------- | 34 | | for-editor | markdown editor | 35 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | export interface IToolbar { 3 | h1?: boolean 4 | h2?: boolean 5 | h3?: boolean 6 | h4?: boolean 7 | img?: boolean 8 | link?: boolean 9 | code?: boolean 10 | preview?: boolean 11 | expand?: boolean 12 | undo?: boolean 13 | redo?: boolean 14 | save?: boolean 15 | subfield?: boolean 16 | } 17 | export interface IWords { 18 | placeholder?: string 19 | h1?: string 20 | h2?: string 21 | h3?: string 22 | h4?: string 23 | undo?: string 24 | redo?: string 25 | img?: string 26 | link?: string 27 | code?: string 28 | save?: string 29 | preview?: string 30 | singleColumn?: string 31 | doubleColumn?: string 32 | fullscreenOn?: string 33 | fullscreenOff?: string 34 | addImgLink?: string 35 | addImg?: string 36 | } 37 | interface IP { 38 | value?: string 39 | lineNum?: number 40 | onChange?: (value: string) => void 41 | onSave?: (value: string) => void 42 | placeholder?: string 43 | fontSize?: string 44 | disabled?: boolean 45 | style?: object 46 | height?: string 47 | preview?: boolean 48 | expand?: boolean 49 | subfield?: boolean 50 | toolbar?: IToolbar 51 | language?: string 52 | addImg?: (file: File, index: number) => void 53 | } 54 | interface IS { 55 | preview: boolean 56 | expand: boolean 57 | subfield: boolean 58 | history: string[] 59 | historyIndex: number 60 | lineIndex: number 61 | value: string 62 | words: IWords 63 | } 64 | declare class MdEditor extends React.Component { 65 | static defaultProps: { 66 | lineNum: boolean 67 | onChange: () => void 68 | onSave: () => void 69 | addImg: () => void 70 | fontSize: string 71 | disabled: boolean 72 | preview: boolean 73 | expand: boolean 74 | subfield: boolean 75 | style: {} 76 | toolbar: IToolbar 77 | language: string 78 | }; 79 | 80 | $img2Url: (name: string, url: string) => void; 81 | 82 | private $vm; 83 | private $scrollEdit; 84 | private $scrollPreview; 85 | private $blockEdit; 86 | private $blockPreview; 87 | private currentTimeout; 88 | } 89 | export default MdEditor 90 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "for-editor", 3 | "version": "0.3.5", 4 | "description": "react markdown editor", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "start": "npm run dev", 8 | "dev": "webpack-dev-server --config webpack/webpack.dev.config.js", 9 | "build": "webpack --config webpack/webpack.prod.config.js", 10 | "dist": "webpack --config webpack/webpack.dist.config.js", 11 | "lint": "eslint --ext .js,.jsx --ignore-path .gitignore ." 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/kkfor/for-editor.git" 16 | }, 17 | "keywords": [ 18 | "javascript", 19 | "react", 20 | "markdown", 21 | "editor" 22 | ], 23 | "author": "kkfor", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/kkfor/for-editor/issues" 27 | }, 28 | "files": [ 29 | "dist/", 30 | "index.d.ts", 31 | "LICENSE" 32 | ], 33 | "homepage": "https://github.com/kkfor/for-editor#readme", 34 | "devDependencies": { 35 | "@babel/core": "^7.2.2", 36 | "@babel/plugin-proposal-class-properties": "^7.2.3", 37 | "@babel/preset-env": "^7.2.3", 38 | "@babel/preset-react": "^7.0.0", 39 | "@types/classnames": "^2.2.9", 40 | "@types/marked": "^0.6.5", 41 | "@types/react": "^16.8.16", 42 | "@types/react-dom": "^16.8.4", 43 | "@typescript-eslint/eslint-plugin": "^1.13.0", 44 | "@typescript-eslint/parser": "^1.13.0", 45 | "autoprefixer": "^9.5.1", 46 | "babel-core": "^7.0.0-bridge.0", 47 | "babel-eslint": "^10.0.2", 48 | "babel-loader": "^8.0.4", 49 | "classnames": "^2.2.6", 50 | "clean-webpack-plugin": "^3.0.0", 51 | "css-loader": "^2.0.2", 52 | "css-modules-typescript-loader": "^2.0.4", 53 | "eslint": "^6.1.0", 54 | "eslint-config-for": "^0.0.1", 55 | "eslint-plugin-react": "^7.14.3", 56 | "file-loader": "^4.0.0", 57 | "html-webpack-plugin": "^3.2.0", 58 | "node-sass": "^4.11.0", 59 | "postcss-loader": "^3.0.0", 60 | "prettier": "^1.15.3", 61 | "raw-loader": "^3.0.0", 62 | "react": "^16.7.0", 63 | "react-dom": "^16.7.0", 64 | "sass-loader": "^7.1.0", 65 | "style-loader": "^0.23.1", 66 | "ts-loader": "^6.0.0", 67 | "typescript": "^3.5.3", 68 | "uglifyjs-webpack-plugin": "^2.1.0", 69 | "webpack": "^4.28.1", 70 | "webpack-cli": "^3.1.2", 71 | "webpack-dev-server": "^3.1.10", 72 | "webpack-merge": "^4.1.5" 73 | }, 74 | "dependencies": { 75 | "highlight.js": "^9.13.1", 76 | "marked": "^1.1.1" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/components/toolbar_left.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { IToolbar, IWords } from '../index' 3 | interface IP { 4 | onClick: (type: string) => void 5 | addImg: (file: File, index: number) => void 6 | toolbar: IToolbar 7 | words: IWords 8 | } 9 | 10 | interface IS { 11 | imgHidden: boolean 12 | imgList: File[] 13 | } 14 | 15 | class Toolbars extends React.Component { 16 | static defaultProps = { 17 | onClick: () => {}, 18 | toolbar: {}, 19 | words: {} 20 | } 21 | 22 | private timer: number 23 | 24 | constructor(props: IP) { 25 | super(props) 26 | 27 | this.state = { 28 | imgHidden: true, 29 | imgList: [] 30 | } 31 | } 32 | 33 | onClick(type: string) { 34 | this.props.onClick(type) 35 | } 36 | 37 | imgClick() { 38 | this.setState({ 39 | imgHidden: !this.state.imgHidden 40 | }) 41 | } 42 | 43 | imgMouseOver() { 44 | window.clearTimeout(this.timer) 45 | this.setState({ 46 | imgHidden: false 47 | }) 48 | } 49 | 50 | imgMouseOut() { 51 | this.timer = window.setTimeout(() => { 52 | this.setState({ 53 | imgHidden: true 54 | }) 55 | }, 150) 56 | } 57 | 58 | addImgUrl() { 59 | this.props.onClick('img') 60 | } 61 | 62 | addImgFile(e: any) { 63 | let { imgList } = this.state 64 | const index = imgList.length 65 | imgList.push(e.target.files[0]) 66 | this.setState({ 67 | imgList 68 | }) 69 | this.props.addImg(e.target.files[0], index) 70 | e.target.value = '' 71 | } 72 | 73 | render() { 74 | const { toolbar, words } = this.props 75 | const { imgHidden } = this.state 76 | return ( 77 |
      78 | {toolbar.undo && ( 79 |
    • this.onClick('undo')} title={`${words.undo} (ctrl+z)`}> 80 | 81 |
    • 82 | )} 83 | {toolbar.redo && ( 84 |
    • this.onClick('redo')} title={`${words.redo} (ctrl+y)`}> 85 | 86 |
    • 87 | )} 88 | {toolbar.h1 && ( 89 |
    • this.onClick('h1')} title={words.h1}> 90 | H1 91 |
    • 92 | )} 93 | {toolbar.h2 && ( 94 |
    • this.onClick('h2')} title={words.h2}> 95 | H2 96 |
    • 97 | )} 98 | {toolbar.h3 && ( 99 |
    • this.onClick('h3')} title={words.h3}> 100 | H3 101 |
    • 102 | )} 103 | {toolbar.h4 && ( 104 |
    • this.onClick('h4')} title={words.h4}> 105 | H4 106 |
    • 107 | )} 108 | {toolbar.img && ( 109 |
    • this.imgMouseOver()} onMouseOut={() => this.imgMouseOut()}> 110 | 111 |
        112 |
      • this.addImgUrl()}>{words.addImgLink}
      • 113 |
      • 114 | {words.addImg} 115 | this.addImgFile(e)}/> 116 |
      • 117 |
      118 |
    • 119 | )} 120 | {toolbar.link && ( 121 |
    • this.onClick('link')} title={words.link}> 122 | 123 |
    • 124 | )} 125 | {toolbar.code && ( 126 |
    • this.onClick('code')} title={words.code}> 127 | 128 |
    • 129 | )} 130 | {toolbar.save && ( 131 |
    • this.onClick('save')} title={`${words.save} (ctrl+s)`}> 132 | 133 |
    • 134 | )} 135 |
    136 | ) 137 | } 138 | } 139 | 140 | export default Toolbars 141 | -------------------------------------------------------------------------------- /src/components/toolbar_right.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import classNames from 'classnames' 3 | import { IToolbar, IWords } from '../index' 4 | 5 | interface IP { 6 | onClick: (type: string) => void 7 | toolbar: IToolbar 8 | preview: boolean 9 | expand: boolean 10 | subfield: boolean 11 | words: IWords 12 | } 13 | 14 | class Toolbars extends React.Component { 15 | static defaultProps = { 16 | onClick: () => {}, 17 | toolbars: {}, 18 | words: {} 19 | } 20 | 21 | onClick(type: string) { 22 | this.props.onClick(type) 23 | } 24 | 25 | render() { 26 | const { preview, expand, subfield, toolbar, words } = this.props 27 | 28 | const previewActive = classNames({ 29 | 'for-active': preview 30 | }) 31 | const expandActive = classNames({ 32 | 'for-active': expand 33 | }) 34 | const subfieldActive = classNames({ 35 | 'for-active': subfield 36 | }) 37 | return ( 38 |
      39 | {toolbar.expand && ( 40 |
    • this.onClick('expand')} 43 | title={expandActive ? words.fullscreenOff : words.fullscreenOn} 44 | > 45 | {expandActive ? ( 46 | 47 | ) : ( 48 | 49 | )} 50 |
    • 51 | )} 52 | {toolbar.preview && ( 53 |
    • this.onClick('preview')} 56 | title={words.preview} 57 | > 58 | {previewActive ? ( 59 | 60 | ) : ( 61 | 62 | )} 63 |
    • 64 | )} 65 | {toolbar.subfield && ( 66 |
    • this.onClick('subfield')} 69 | title={subfieldActive ? words.singleColumn : words.doubleColumn} 70 | > 71 | 72 |
    • 73 | )} 74 |
    75 | ) 76 | } 77 | } 78 | 79 | export default Toolbars 80 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import classNames from 'classnames' 3 | import marked from './lib/helpers/marked' 4 | import keydownListen from './lib/helpers/keydownListen' 5 | import ToolbarLeft from './components/toolbar_left' 6 | import ToolbarRight from './components/toolbar_right' 7 | import { insertText } from './lib/helpers/function' 8 | import 'highlight.js/styles/tomorrow.css' 9 | import './lib/fonts/iconfont.css' 10 | import './lib/css/index.scss' 11 | import { CONFIG } from './lib' 12 | 13 | export interface IToolbar { 14 | h1?: boolean 15 | h2?: boolean 16 | h3?: boolean 17 | h4?: boolean 18 | img?: boolean 19 | link?: boolean 20 | code?: boolean 21 | preview?: boolean 22 | expand?: boolean 23 | undo?: boolean 24 | redo?: boolean 25 | save?: boolean 26 | subfield?: boolean 27 | } 28 | 29 | export interface IWords { 30 | placeholder?: string 31 | h1?: string 32 | h2?: string 33 | h3?: string 34 | h4?: string 35 | undo?: string 36 | redo?: string 37 | img?: string 38 | link?: string 39 | code?: string 40 | save?: string 41 | preview?: string 42 | singleColumn?: string 43 | doubleColumn?: string 44 | fullscreenOn?: string 45 | fullscreenOff?: string 46 | addImgLink?: string 47 | addImg?: string 48 | } 49 | 50 | interface ILeft { 51 | prefix: string 52 | subfix: string 53 | str: string 54 | } 55 | interface IP { 56 | value?: string 57 | lineNum?: number 58 | onChange?: (value: string) => void 59 | onSave?: (value: string) => void 60 | placeholder?: string 61 | fontSize?: string 62 | disabled?: boolean 63 | style?: object 64 | height?: string 65 | preview?: boolean 66 | expand?: boolean 67 | subfield?: boolean 68 | toolbar?: IToolbar 69 | language?: string 70 | addImg?: (file: File, index: number) => void 71 | } 72 | 73 | interface IS { 74 | preview: boolean 75 | expand: boolean 76 | subfield: boolean 77 | history: string[] 78 | historyIndex: number 79 | lineIndex: number 80 | value: string 81 | words: IWords 82 | } 83 | 84 | class MdEditor extends React.Component { 85 | static defaultProps = { 86 | lineNum: true, 87 | onChange: () => { }, 88 | onSave: () => { }, 89 | addImg: () => { }, 90 | fontSize: '14px', 91 | disabled: false, 92 | preview: false, 93 | expand: false, 94 | subfield: false, 95 | style: {}, 96 | toolbar: CONFIG.toolbar, 97 | language: 'zh-CN' 98 | } 99 | private $vm = React.createRef() 100 | private $scrollEdit = React.createRef() 101 | private $scrollPreview = React.createRef() 102 | private $blockEdit = React.createRef() 103 | private $blockPreview = React.createRef() 104 | private currentTimeout: number 105 | constructor(props: IP) { 106 | super(props) 107 | 108 | this.state = { 109 | preview: props.preview, 110 | expand: props.expand, 111 | subfield: props.subfield, 112 | history: [], 113 | historyIndex: 0, 114 | lineIndex: 1, 115 | value: props.value, 116 | words: {} 117 | } 118 | } 119 | 120 | componentDidMount() { 121 | const { value } = this.props 122 | keydownListen(this.$vm.current, (type: string) => { 123 | this.toolBarLeftClick(type) 124 | }) 125 | this.reLineNum(value) 126 | this.initLanguage() 127 | } 128 | 129 | componentDidUpdate(preProps: IP) { 130 | const { value, preview, expand, subfield } = this.props 131 | const { history, historyIndex } = this.state 132 | if (preProps.value !== value) { 133 | this.reLineNum(value) 134 | } 135 | if (value !== history[historyIndex]) { 136 | window.clearTimeout(this.currentTimeout) 137 | this.currentTimeout = window.setTimeout(() => { 138 | this.saveHistory(value) 139 | }, 500) 140 | } 141 | if (subfield !== preProps.subfield && this.state.subfield !== subfield) { 142 | this.setState({ subfield }); 143 | } 144 | if (preview !== preProps.preview && this.state.preview !== preview) { 145 | this.setState({ preview }); 146 | } 147 | if (expand !== preProps.expand && this.state.expand !== expand) { 148 | this.setState({ expand }); 149 | } 150 | } 151 | 152 | initLanguage = (): void => { 153 | const { language } = this.props 154 | const lang = CONFIG.langList.indexOf(language) >= 0 ? language : 'zh-CN' 155 | this.setState({ 156 | words: CONFIG.language[lang] 157 | }) 158 | } 159 | 160 | // 输入框改变 161 | handleChange = (e: React.ChangeEvent): void => { 162 | const value = e.target.value 163 | this.props.onChange(value) 164 | } 165 | 166 | // 保存记录 167 | saveHistory = (value: string): void => { 168 | let { history, historyIndex } = this.state 169 | // 撤销后修改,删除当前以后记录 170 | history.splice(historyIndex + 1, history.length) 171 | if (history.length >= 20) { 172 | history.shift() 173 | } 174 | // 记录当前位置 175 | historyIndex = history.length 176 | history.push(value) 177 | this.setState({ 178 | history, 179 | historyIndex 180 | }) 181 | } 182 | 183 | // 重新计算行号 184 | reLineNum(value: string) { 185 | const lineIndex = value ? value.split('\n').length : 1 186 | this.setState({ 187 | lineIndex 188 | }) 189 | } 190 | 191 | // 保存 192 | save = (): void => { 193 | this.props.onSave(this.$vm.current!.value) 194 | } 195 | 196 | // 撤销 197 | undo = (): void => { 198 | let { history, historyIndex } = this.state 199 | historyIndex = historyIndex - 1 200 | if (historyIndex < 0) return 201 | this.props.onChange(history[historyIndex]) 202 | this.setState({ 203 | historyIndex 204 | }) 205 | } 206 | 207 | // 重做 208 | redo = (): void => { 209 | let { history, historyIndex } = this.state 210 | historyIndex = historyIndex + 1 211 | if (historyIndex >= history.length) return 212 | this.props.onChange(history[historyIndex]) 213 | this.setState({ 214 | historyIndex 215 | }) 216 | } 217 | 218 | // 菜单点击 219 | toolBarLeftClick = (type: string): void => { 220 | const { words } = this.state 221 | const insertTextObj: any = { 222 | h1: { 223 | prefix: '# ', 224 | subfix: '', 225 | str: words.h1 226 | }, 227 | h2: { 228 | prefix: '## ', 229 | subfix: '', 230 | str: words.h2 231 | }, 232 | h3: { 233 | prefix: '### ', 234 | subfix: '', 235 | str: words.h3 236 | }, 237 | h4: { 238 | prefix: '#### ', 239 | subfix: '', 240 | str: words.h4 241 | }, 242 | img: { 243 | prefix: '![alt](', 244 | subfix: ')', 245 | str: 'url' 246 | }, 247 | link: { 248 | prefix: '[title](', 249 | subfix: ')', 250 | str: 'url' 251 | }, 252 | code: { 253 | prefix: '```', 254 | subfix: '\n\n```', 255 | str: 'language' 256 | }, 257 | tab: { 258 | prefix: ' ', 259 | subfix: '', 260 | str: '' 261 | } 262 | } 263 | 264 | if (insertTextObj.hasOwnProperty(type)) { 265 | if (this.$vm.current) { 266 | const value = insertText(this.$vm.current, insertTextObj[type]) 267 | this.props.onChange(value) 268 | } 269 | } 270 | 271 | const otherLeftClick: any = { 272 | undo: this.undo, 273 | redo: this.redo, 274 | save: this.save 275 | } 276 | if (otherLeftClick.hasOwnProperty(type)) { 277 | otherLeftClick[type]() 278 | } 279 | } 280 | 281 | // 添加图片 282 | addImg = (file: File, index: number) => { 283 | this.props.addImg(file, index) 284 | } 285 | 286 | $img2Url = (name: string, url: string) => { 287 | const value = insertText(this.$vm.current, { 288 | prefix: `![${name}](${url})`, 289 | subfix: '', 290 | str: '' 291 | }) 292 | this.props.onChange(value) 293 | } 294 | 295 | // 右侧菜单 296 | toolBarRightClick = (type: string): void => { 297 | const toolbarRightPreviewClick = () => { 298 | this.setState({ 299 | preview: !this.state.preview 300 | }) 301 | } 302 | const toolbarRightExpandClick = () => { 303 | this.setState({ 304 | expand: !this.state.expand 305 | }) 306 | } 307 | 308 | const toolbarRightSubfieldClick = () => { 309 | const { preview, subfield } = this.state 310 | if (preview) { 311 | if (subfield) { 312 | this.setState({ 313 | subfield: false, 314 | preview: false 315 | }) 316 | } else { 317 | this.setState({ 318 | subfield: true 319 | }) 320 | } 321 | } else { 322 | if (subfield) { 323 | this.setState({ 324 | subfield: false 325 | }) 326 | } else { 327 | this.setState({ 328 | preview: true, 329 | subfield: true 330 | }) 331 | } 332 | } 333 | } 334 | 335 | const rightClick: any = { 336 | preview: toolbarRightPreviewClick, 337 | expand: toolbarRightExpandClick, 338 | subfield: toolbarRightSubfieldClick 339 | } 340 | if (rightClick.hasOwnProperty(type)) { 341 | rightClick[type]() 342 | } 343 | } 344 | 345 | focusText = (): void => { 346 | this.$vm.current!.focus() 347 | } 348 | 349 | handleScoll = (e: React.UIEvent): void => { 350 | const radio = 351 | this.$blockEdit.current!.scrollTop / 352 | (this.$scrollEdit.current!.scrollHeight - e.currentTarget.offsetHeight) 353 | this.$blockPreview.current!.scrollTop = 354 | (this.$scrollPreview.current!.scrollHeight - this.$blockPreview.current!.offsetHeight) * radio 355 | } 356 | 357 | render() { 358 | const { preview, expand, subfield, lineIndex, words } = this.state 359 | const { value, placeholder, fontSize, disabled, height, style, toolbar } = this.props 360 | const editorClass = classNames({ 361 | 'for-editor-edit': true, 362 | 'for-panel': true, 363 | 'for-active': preview && subfield, 364 | 'for-edit-preview': preview && !subfield 365 | }) 366 | const previewClass = classNames({ 367 | 'for-panel': true, 368 | 'for-editor-preview': true, 369 | 'for-active': preview && subfield 370 | }) 371 | const fullscreen = classNames({ 372 | 'for-container': true, 373 | 'for-fullscreen': expand 374 | }) 375 | const lineNumStyles = classNames({ 376 | 'for-line-num': true, 377 | hidden: !this.props.lineNum 378 | }) 379 | 380 | // 行号 381 | function lineNum() { 382 | const list = [] 383 | for (let i = 0; i < lineIndex; i++) { 384 | list.push(
  • {i + 1}
  • ) 385 | } 386 | return
      {list}
    387 | } 388 | 389 | return ( 390 |
    391 | {/* 菜单栏 */} 392 | {Boolean(Object.keys(toolbar).length) && ( 393 |
    394 | 401 | 409 |
    410 | )} 411 | {/* 内容区 */} 412 |
    413 | {/* 编辑区 */} 414 |
    420 |
    421 | {lineNum()} 422 |
    423 |
    {value} 
    424 |