From 75c95d7f01a296a749372086cf7685e6f4ec7525 Mon Sep 17 00:00:00 2001 From: Pandao Date: Tue, 10 Mar 2015 00:04:50 +0800 Subject: [PATCH] Releases v1.2.0 --- BUGS.md | 4 +- CHANGE.md | 100 +- Gulpfile.js | 255 +- README.md | 51 +- bower.json | 2 +- {dist/css => css}/editormd.css | 218 +- css/editormd.css.map | 19 + css/editormd.css.min.map | 2 + {dist/css => css}/editormd.logo.css | 33 +- css/editormd.logo.css.map | 19 + css/editormd.logo.css.min.map | 2 + css/editormd.logo.min.css | 9 + css/editormd.min.css | 26 + {dist/css => css}/editormd.preview.css | 17 +- css/editormd.preview.css.map | 19 + css/editormd.preview.css.min.map | 2 + css/editormd.preview.min.css | 9 + dist/css/editormd.css.map | 18 - dist/css/editormd.css.min.map | 2 - dist/css/editormd.logo.css.map | 18 - dist/css/editormd.logo.css.min.map | 2 - dist/css/editormd.logo.min.css | 2 - dist/css/editormd.min.css | 5 - dist/css/editormd.preview.css.map | 18 - dist/css/editormd.preview.css.min.map | 2 - dist/css/editormd.preview.min.css | 2 - dist/js/editormd.min.js | 3 - dist/js/languages/en.js | 121 - dist/js/languages/en.min.js | 2 - dist/js/languages/zh-tw.js | 121 - dist/js/languages/zh-tw.min.js | 2 - docs/html/index.html | 149 - docs/html/scripts/linenumber.js | 25 - .../scripts/prettify/Apache-License-2.0.txt | 202 - docs/html/scripts/prettify/lang-css.js | 2 - docs/html/scripts/prettify/prettify.js | 28 - docs/html/styles/jsdoc-default.css | 334 -- docs/html/styles/prettify-jsdoc.css | 111 - docs/html/styles/prettify-tomorrow.css | 132 - editormd.amd.js | 3422 +++++++++++++++++ editormd.amd.min.js | 3 + dist/js/editormd.js => editormd.js | 2823 ++++++++------ editormd.min.js | 3 + examples/127.0.0.1-8888.url | 2 - examples/@links.html | 97 + examples/change-mode.html | 508 +++ examples/code-fold.html | 44 + examples/custom-keyboard-shortcuts.html | 88 + examples/custom-toolbar.html | 52 +- examples/define-plugin.html | 153 + examples/dynamic-create-editormd.html | 9 +- examples/emoji.html | 225 ++ examples/extends.html | 153 + examples/external-use.html | 119 + examples/flowchart.html | 21 +- examples/form-get-value.html | 5 +- examples/full.html | 84 +- examples/html-preview-markdown-to-html.html | 46 +- examples/html-tags-decode.html | 48 +- examples/image-cross-domain-upload.html | 5 +- examples/image-upload.html | 39 +- examples/images/1.jpg | Bin 3253 -> 0 bytes examples/images/10.jpg | Bin 64854 -> 0 bytes examples/images/2.jpg | Bin 3749 -> 0 bytes examples/images/3.jpg | Bin 34228 -> 0 bytes examples/images/5.jpg | Bin 4503 -> 0 bytes examples/images/6.jpg | Bin 104491 -> 0 bytes examples/images/7.jpg | Bin 9753 -> 95090 bytes examples/images/9.jpg | Bin 37472 -> 0 bytes examples/images/X7t2gyC.png | Bin 104946 -> 0 bytes examples/index.html | 57 +- examples/katex.html | 47 +- examples/manually-load-modules.html | 92 + examples/multi-editormd.html | 5 +- examples/multi-languages.html | 22 +- examples/on-off.html | 59 + examples/onchange.html | 7 +- examples/onfullscreen.html | 7 +- examples/onload.html | 7 +- examples/onpreviewing-onpreviewed.html | 38 + examples/onresize.html | 40 + examples/onscroll-onpreviewscroll.html | 45 + examples/onwatch-onunwatch.html | 43 + examples/readonly.html | 5 +- examples/resettings.html | 148 + examples/search-replace.html | 46 + examples/sequence-diagram.html | 13 +- examples/set-get-replace-selection.html | 5 +- examples/simple.html | 22 +- examples/task-lists.html | 47 + examples/test.md | 96 +- examples/themes.html | 119 + examples/toc.html | 5 +- examples/use-requirejs.html | 165 +- examples/use-seajs.html | 53 +- examples/use-zepto.html | 36 +- {dist/fonts => fonts}/FontAwesome.otf | Bin {dist/fonts => fonts}/editormd-logo.eot | Bin {dist/fonts => fonts}/editormd-logo.svg | 0 {dist/fonts => fonts}/editormd-logo.ttf | Bin {dist/fonts => fonts}/editormd-logo.woff | Bin {dist/fonts => fonts}/fontawesome-webfont.eot | Bin {dist/fonts => fonts}/fontawesome-webfont.svg | 0 {dist/fonts => fonts}/fontawesome-webfont.ttf | Bin .../fonts => fonts}/fontawesome-webfont.woff | Bin .../fonts => fonts}/fontawesome-webfont.woff2 | Bin {dist/images => images}/loading.gif | Bin {dist/images => images}/loading@2x.gif | Bin {dist/images => images}/loading@3x.gif | Bin .../logos/editormd-favicon-16x16.ico | Bin .../logos/editormd-favicon-24x24.ico | Bin .../logos/editormd-favicon-32x32.ico | Bin .../logos/editormd-favicon-48x48.ico | Bin .../logos/editormd-favicon-64x64.ico | Bin .../logos/editormd-logo-114x114.png | Bin .../logos/editormd-logo-120x120.png | Bin .../logos/editormd-logo-144x144.png | Bin .../logos/editormd-logo-16x16.png | Bin .../logos/editormd-logo-180x180.png | Bin .../logos/editormd-logo-240x240.png | Bin .../logos/editormd-logo-24x24.png | Bin .../logos/editormd-logo-320x320.png | Bin .../logos/editormd-logo-32x32.png | Bin .../logos/editormd-logo-48x48.png | Bin .../logos/editormd-logo-57x57.png | Bin .../logos/editormd-logo-64x64.png | Bin .../logos/editormd-logo-72x72.png | Bin .../logos/editormd-logo-96x96.png | Bin {dist/images => images}/logos/vi.png | Bin {src/js/languages => languages}/en.js | 24 +- {src/js/languages => languages}/zh-tw.js | 24 +- lib/codemirror/addons.min.js | 5 +- lib/codemirror/codemirror.js | 2 + lib/codemirror/modes.min.js | 2 +- lib/codemirror/theme/3024-day.css | 38 + lib/codemirror/theme/3024-night.css | 37 + lib/codemirror/theme/ambiance-mobile.css | 5 + lib/codemirror/theme/ambiance.css | 77 + lib/codemirror/theme/base16-dark.css | 36 + lib/codemirror/theme/base16-light.css | 36 + lib/codemirror/theme/blackboard.css | 30 + lib/codemirror/theme/cobalt.css | 23 + lib/codemirror/theme/eclipse.css | 23 + lib/codemirror/theme/elegant.css | 13 + lib/codemirror/theme/erlang-dark.css | 32 + lib/codemirror/theme/lesser-dark.css | 45 + lib/codemirror/theme/mbo.css | 35 + lib/codemirror/theme/mdn-like.css | 44 + lib/codemirror/theme/midnight.css | 45 + lib/codemirror/theme/monokai.css | 31 + lib/codemirror/theme/neat.css | 12 + lib/codemirror/theme/neo.css | 43 + lib/codemirror/theme/night.css | 26 + lib/codemirror/theme/paraiso-dark.css | 36 + lib/codemirror/theme/paraiso-light.css | 36 + lib/codemirror/theme/pastel-on-dark.css | 50 + lib/codemirror/theme/rubyblue.css | 23 + lib/codemirror/theme/solarized.css | 165 + lib/codemirror/theme/the-matrix.css | 28 + .../theme/tomorrow-night-eighties.css | 36 + lib/codemirror/theme/twilight.css | 30 + lib/codemirror/theme/vibrant-ink.css | 32 + lib/codemirror/theme/xq-dark.css | 51 + lib/codemirror/theme/xq-light.css | 43 + lib/jquery.flowchart.min.js | 5 +- lib/sequence-diagram.min.js | 3 +- lib/underscore.min.js | 6 +- package.json | 4 +- .../anchor-link-dialog/anchor-link-dialog.js | 142 + .../code-block-dialog/code-block-dialog.js | 237 ++ plugins/emoji-dialog/Noname5.js | 28 + plugins/emoji-dialog/emoji-dialog.js | 325 ++ plugins/emoji-dialog/emoji.json | 28 + plugins/help-dialog/help-dialog.js | 102 + plugins/help-dialog/help.md | 39 + .../html-entities-dialog.js | 173 + .../html-entities-dialog/html-entities.json | 936 +++++ plugins/image-dialog/image-dialog.js | 210 + plugins/link-dialog/link-dialog.js | 133 + plugins/plugin-template.js | 111 + .../preformatted-text-dialog.js | 167 + plugins/table-dialog/table-dialog.js | 218 ++ plugins/test-plugin/test-plugin.js | 66 + {src/scss => scss}/editormd.codemirror.scss | 0 {src/scss => scss}/editormd.dialog.scss | 4 +- {src/scss => scss}/editormd.form.scss | 33 +- scss/editormd.grid.scss | 36 + {src/scss => scss}/editormd.logo.scss | 12 +- {src/scss => scss}/editormd.menu.scss | 0 {src/scss => scss}/editormd.preview.scss | 7 +- {src/scss => scss}/editormd.scss | 4 +- scss/editormd.tab.scss | 49 + {src/scss => scss}/font-awesome.scss | 0 {src/scss => scss}/github-markdown.scss | 0 scss/lib/prefixes.scss | 791 ++++ {src/scss => scss}/lib/variables.scss | 0 {src/scss => scss}/prettify.scss | 0 src/{js => }/editormd.js | 2818 ++++++++------ src/scss/lib/functions.scss | 294 -- tests/codemirror-searchbox-test.html | 109 + tests/js/searchbox.js | 674 ++++ tests/marked-@at-test.html | 221 ++ tests/marked-emoji-test.html | 231 ++ tests/marked-todo-list-test.html | 61 + 204 files changed, 16208 insertions(+), 4553 deletions(-) rename {dist/css => css}/editormd.css (87%) create mode 100644 css/editormd.css.map create mode 100644 css/editormd.css.min.map rename {dist/css => css}/editormd.logo.css (67%) create mode 100644 css/editormd.logo.css.map create mode 100644 css/editormd.logo.css.min.map create mode 100644 css/editormd.logo.min.css create mode 100644 css/editormd.min.css rename {dist/css => css}/editormd.preview.css (93%) create mode 100644 css/editormd.preview.css.map create mode 100644 css/editormd.preview.css.min.map create mode 100644 css/editormd.preview.min.css delete mode 100644 dist/css/editormd.css.map delete mode 100644 dist/css/editormd.css.min.map delete mode 100644 dist/css/editormd.logo.css.map delete mode 100644 dist/css/editormd.logo.css.min.map delete mode 100644 dist/css/editormd.logo.min.css delete mode 100644 dist/css/editormd.min.css delete mode 100644 dist/css/editormd.preview.css.map delete mode 100644 dist/css/editormd.preview.css.min.map delete mode 100644 dist/css/editormd.preview.min.css delete mode 100644 dist/js/editormd.min.js delete mode 100644 dist/js/languages/en.js delete mode 100644 dist/js/languages/en.min.js delete mode 100644 dist/js/languages/zh-tw.js delete mode 100644 dist/js/languages/zh-tw.min.js delete mode 100644 docs/html/index.html delete mode 100644 docs/html/scripts/linenumber.js delete mode 100644 docs/html/scripts/prettify/Apache-License-2.0.txt delete mode 100644 docs/html/scripts/prettify/lang-css.js delete mode 100644 docs/html/scripts/prettify/prettify.js delete mode 100644 docs/html/styles/jsdoc-default.css delete mode 100644 docs/html/styles/prettify-jsdoc.css delete mode 100644 docs/html/styles/prettify-tomorrow.css create mode 100644 editormd.amd.js create mode 100644 editormd.amd.min.js rename dist/js/editormd.js => editormd.js (54%) create mode 100644 editormd.min.js delete mode 100644 examples/127.0.0.1-8888.url create mode 100644 examples/@links.html create mode 100644 examples/change-mode.html create mode 100644 examples/code-fold.html create mode 100644 examples/custom-keyboard-shortcuts.html create mode 100644 examples/define-plugin.html create mode 100644 examples/emoji.html create mode 100644 examples/extends.html create mode 100644 examples/external-use.html delete mode 100644 examples/images/1.jpg delete mode 100644 examples/images/10.jpg delete mode 100644 examples/images/2.jpg delete mode 100644 examples/images/3.jpg delete mode 100644 examples/images/5.jpg delete mode 100644 examples/images/6.jpg delete mode 100644 examples/images/9.jpg delete mode 100644 examples/images/X7t2gyC.png create mode 100644 examples/manually-load-modules.html create mode 100644 examples/on-off.html create mode 100644 examples/onpreviewing-onpreviewed.html create mode 100644 examples/onresize.html create mode 100644 examples/onscroll-onpreviewscroll.html create mode 100644 examples/onwatch-onunwatch.html create mode 100644 examples/resettings.html create mode 100644 examples/search-replace.html create mode 100644 examples/task-lists.html create mode 100644 examples/themes.html rename {dist/fonts => fonts}/FontAwesome.otf (100%) rename {dist/fonts => fonts}/editormd-logo.eot (100%) rename {dist/fonts => fonts}/editormd-logo.svg (100%) rename {dist/fonts => fonts}/editormd-logo.ttf (100%) rename {dist/fonts => fonts}/editormd-logo.woff (100%) rename {dist/fonts => fonts}/fontawesome-webfont.eot (100%) rename {dist/fonts => fonts}/fontawesome-webfont.svg (100%) rename {dist/fonts => fonts}/fontawesome-webfont.ttf (100%) rename {dist/fonts => fonts}/fontawesome-webfont.woff (100%) rename {dist/fonts => fonts}/fontawesome-webfont.woff2 (100%) rename {dist/images => images}/loading.gif (100%) rename {dist/images => images}/loading@2x.gif (100%) rename {dist/images => images}/loading@3x.gif (100%) rename {dist/images => images}/logos/editormd-favicon-16x16.ico (100%) rename {dist/images => images}/logos/editormd-favicon-24x24.ico (100%) rename {dist/images => images}/logos/editormd-favicon-32x32.ico (100%) rename {dist/images => images}/logos/editormd-favicon-48x48.ico (100%) rename {dist/images => images}/logos/editormd-favicon-64x64.ico (100%) rename {dist/images => images}/logos/editormd-logo-114x114.png (100%) rename {dist/images => images}/logos/editormd-logo-120x120.png (100%) rename {dist/images => images}/logos/editormd-logo-144x144.png (100%) rename {dist/images => images}/logos/editormd-logo-16x16.png (100%) rename {dist/images => images}/logos/editormd-logo-180x180.png (100%) rename {dist/images => images}/logos/editormd-logo-240x240.png (100%) rename {dist/images => images}/logos/editormd-logo-24x24.png (100%) rename {dist/images => images}/logos/editormd-logo-320x320.png (100%) rename {dist/images => images}/logos/editormd-logo-32x32.png (100%) rename {dist/images => images}/logos/editormd-logo-48x48.png (100%) rename {dist/images => images}/logos/editormd-logo-57x57.png (100%) rename {dist/images => images}/logos/editormd-logo-64x64.png (100%) rename {dist/images => images}/logos/editormd-logo-72x72.png (100%) rename {dist/images => images}/logos/editormd-logo-96x96.png (100%) rename {dist/images => images}/logos/vi.png (100%) rename {src/js/languages => languages}/en.js (83%) rename {src/js/languages => languages}/zh-tw.js (84%) create mode 100644 lib/codemirror/codemirror.js create mode 100644 lib/codemirror/theme/3024-day.css create mode 100644 lib/codemirror/theme/3024-night.css create mode 100644 lib/codemirror/theme/ambiance-mobile.css create mode 100644 lib/codemirror/theme/ambiance.css create mode 100644 lib/codemirror/theme/base16-dark.css create mode 100644 lib/codemirror/theme/base16-light.css create mode 100644 lib/codemirror/theme/blackboard.css create mode 100644 lib/codemirror/theme/cobalt.css create mode 100644 lib/codemirror/theme/eclipse.css create mode 100644 lib/codemirror/theme/elegant.css create mode 100644 lib/codemirror/theme/erlang-dark.css create mode 100644 lib/codemirror/theme/lesser-dark.css create mode 100644 lib/codemirror/theme/mbo.css create mode 100644 lib/codemirror/theme/mdn-like.css create mode 100644 lib/codemirror/theme/midnight.css create mode 100644 lib/codemirror/theme/monokai.css create mode 100644 lib/codemirror/theme/neat.css create mode 100644 lib/codemirror/theme/neo.css create mode 100644 lib/codemirror/theme/night.css create mode 100644 lib/codemirror/theme/paraiso-dark.css create mode 100644 lib/codemirror/theme/paraiso-light.css create mode 100644 lib/codemirror/theme/pastel-on-dark.css create mode 100644 lib/codemirror/theme/rubyblue.css create mode 100644 lib/codemirror/theme/solarized.css create mode 100644 lib/codemirror/theme/the-matrix.css create mode 100644 lib/codemirror/theme/tomorrow-night-eighties.css create mode 100644 lib/codemirror/theme/twilight.css create mode 100644 lib/codemirror/theme/vibrant-ink.css create mode 100644 lib/codemirror/theme/xq-dark.css create mode 100644 lib/codemirror/theme/xq-light.css create mode 100644 plugins/anchor-link-dialog/anchor-link-dialog.js create mode 100644 plugins/code-block-dialog/code-block-dialog.js create mode 100644 plugins/emoji-dialog/Noname5.js create mode 100644 plugins/emoji-dialog/emoji-dialog.js create mode 100644 plugins/emoji-dialog/emoji.json create mode 100644 plugins/help-dialog/help-dialog.js create mode 100644 plugins/help-dialog/help.md create mode 100644 plugins/html-entities-dialog/html-entities-dialog.js create mode 100644 plugins/html-entities-dialog/html-entities.json create mode 100644 plugins/image-dialog/image-dialog.js create mode 100644 plugins/link-dialog/link-dialog.js create mode 100644 plugins/plugin-template.js create mode 100644 plugins/preformatted-text-dialog/preformatted-text-dialog.js create mode 100644 plugins/table-dialog/table-dialog.js create mode 100644 plugins/test-plugin/test-plugin.js rename {src/scss => scss}/editormd.codemirror.scss (100%) rename {src/scss => scss}/editormd.dialog.scss (93%) rename {src/scss => scss}/editormd.form.scss (67%) create mode 100644 scss/editormd.grid.scss rename {src/scss => scss}/editormd.logo.scss (84%) rename {src/scss => scss}/editormd.menu.scss (100%) rename {src/scss => scss}/editormd.preview.scss (90%) rename {src/scss => scss}/editormd.scss (92%) create mode 100644 scss/editormd.tab.scss rename {src/scss => scss}/font-awesome.scss (100%) rename {src/scss => scss}/github-markdown.scss (100%) create mode 100644 scss/lib/prefixes.scss rename {src/scss => scss}/lib/variables.scss (100%) rename {src/scss => scss}/prettify.scss (100%) rename src/{js => }/editormd.js (54%) delete mode 100644 src/scss/lib/functions.scss create mode 100644 tests/codemirror-searchbox-test.html create mode 100644 tests/js/searchbox.js create mode 100644 tests/marked-@at-test.html create mode 100644 tests/marked-emoji-test.html create mode 100644 tests/marked-todo-list-test.html diff --git a/BUGS.md b/BUGS.md index 34e7b48..9c61c2d 100644 --- a/BUGS.md +++ b/BUGS.md @@ -18,5 +18,5 @@ ####Require.js -- CodeMirror编辑器的代码无法高亮; - +- ~~CodeMirror编辑器的代码无法高亮;~~ +- ~~sequenceDiagram不支持: `Uncaught TypeError: Cannot call method 'isArray' of undefined.`~~ diff --git a/CHANGE.md b/CHANGE.md index cba356a..0eeea49 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -1,4 +1,6 @@ -####更新日志 +##更新日志 + +###v1.0.x #####v1.0.0 beta @@ -34,6 +36,8 @@ - 解决Sea.js环境下Raphael.js无法运行导致不支持流程图和时序图的问题,即必须先加载Raphael.js,后加载Sea.js; +###v1.1.x + #####v1.1.0 主要更新: @@ -206,4 +210,96 @@ - 新增了`editormd.trim()`,用于清除字符串两边的空格; - 修改了所有相关的示例文件和测试用例`marked-heading-link-test.html`; -- 修改了`README.md`,添加了`Shields.io`图标; \ No newline at end of file +- 修改了`README.md`,添加了`Shields.io`图标; + +###v1.2 + +#####v1.2.0 + +v1.2.0 主要更新: + +- 新增代码折叠、搜索替换、自定义样式主题和自定义快捷键等功能; +- 新增Emoji表情、@Link、GFM Task Lists支持; +- 新增表格插入、Emoji表情插入、HTML实体字符插入、使用帮助等对话框; +- 新增插件扩展机制; +- 新增手动加载依赖模块方式; +- 改用`Prefixes.css`作CSS前缀预处理; +- 改进和增强工具栏自定义功能,完善事件监听和处理方法; +- 部分功能改进(更加方便的预格式文本/代码插入、自动闭合标签等)、新增多个方法、改进Require.js支持和修复多个Bug等等; + +**具体更新如下:** + +- 新建v1.1.x分支; + - v1.2文件结构变动较大; + +- 新增代码折叠、自动闭合标签和搜索替换功能; + - 搜索快捷键`Ctrl + F / Command + F`; + - 替换快捷键`Ctrl + Shift + F / Command + Option + F`; + - 折叠快捷键`Ctrl + Q / Command + Q` + +- 新增自定义主题支持; + - 新增3个成员方法`setTheme()`、`setCodeMirrorOption()`和`getCodeMirrorOption()`; + +- 新增@Link支持; + +- 新增GFM Task Lists支持; + +- 新增Emoji表情支持; + - 支持Github emoji`:emoji-name:`、FontAwesome icons(`:fa-xxx:`)、Twitter emoji(twemoji) (`:tw-xxxx:`)、Editor.md logo icons(`:editormd-logo:`)形式的Emoji; + - 新增属性`editormd.emoji`、`editormd.twemoji`、`editormd.urls`和`editormd.regex`; + +- 新增HTML实体字符插入、插入表格和使用帮助对话框; + - 修改了`createDialog()`等方法; + - 新增`mask`成员属性和锁屏方法`editormd.lockScreen()`、`editormd.fn.lockScreen()`; + +- 改进插入预格式文本和代码对话框; + - 将` + > 提示1:如果没有Markdown源内容或者通过Ajax异步加载Markdown源文档等,可以不添加`"),s=this.markdownTextarea=a.children("textarea")),s.addClass(n.textarea.markdown).attr("name",e+"-markdown-doc").attr("placeholder",r.placeholder);var l=[r.readOnly?"":'',r.saveHTMLToTextarea?'':"",'
','
','
'].join("\n");return a.append(l).addClass(o+"vertical"),""!==r.markdown&&s.val(r.markdown),this.htmlTextarea=a.find("."+n.textarea.html),this.preview=a.find("."+o+"preview"),this.previewContainer=this.preview.children("."+o+"preview-container"),this.toolbarIconHandlers={},r.inRequirejs?(i.setCodeMirror(),i.setToolbar(),i.setMarked().loadedDisplay()):this.loadQueues(),this},loadQueues:function(){var e=this,t=this.settings,i=t.path,o=function(){return editormd.isIE8?void e.setMarked().loadedDisplay():void(t.flowChart||t.sequenceDiagram?editormd.loadScript(i+"raphael.min",function(){editormd.loadScript(i+"underscore.min",function(){!t.flowChart&&t.sequenceDiagram?editormd.loadScript(i+"sequence-diagram.min",function(){e.setMarked().loadedDisplay()}):t.flowChart&&!t.sequenceDiagram?editormd.loadScript(i+"flowchart.min",function(){editormd.loadScript(i+"jquery.flowchart.min",function(){e.setMarked().loadedDisplay()})}):t.flowChart&&t.sequenceDiagram&&editormd.loadScript(i+"flowchart.min",function(){editormd.loadScript(i+"jquery.flowchart.min",function(){editormd.loadScript(i+"sequence-diagram.min",function(){e.setMarked().loadedDisplay()})})})})}):e.setMarked().loadedDisplay())};return editormd.loadCSS(i+"codemirror/codemirror.min"),editormd.loadScript(i+"codemirror/codemirror.min",function(){editormd.$CodeMirror=CodeMirror,editormd.loadScript(i+"codemirror/modes.min",function(){editormd.loadScript(i+"codemirror/addons.min",function(){e.setCodeMirror(),e.setToolbar(),editormd.loadScript(i+"marked.min",function(){editormd.$marked=marked,t.previewCodeHighlight?editormd.loadScript(i+"prettify.min",function(){o()}):o()})})})}),this},setCodeMirror:function(){var e=this.settings,t=this.editor,i={mode:e.mode,theme:"default",tabSize:4,dragDrop:!1,autofocus:!0,readOnly:e.readOnly?"nocursor":!1,indentUnit:4,lineNumbers:e.lineNumbers,lineWrapping:!0,matchBrackets:!0,indentWithTabs:!0,styleActiveLine:e.styleActiveLine,styleSelectedText:!0,autoCloseBrackets:!0,showTrailingSpace:!0,highlightSelectionMatches:e.matchWordHighlight?{showToken:"onselected"==e.matchWordHighlight?!1:/\w/}:!1};return this.codeEditor=editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0],i),this.codeMirror=t.find(".CodeMirror"),this.codeMirror.css({fontSize:e.fontSize,width:e.watch?"50%":"100%"}),this},showToolbar:function(){var e=this.settings;if(!e.readOnly)return e.toolbar=!0,this.toolbar.show(),this.resize(),this},hideToolbar:function(){var e=this.settings;return e.toolbar=!1,this.toolbar.hide(),this.resize(),this},setToolbar:function(){var e=this.settings;if(!e.readOnly){var t=this.editor,i=(this.preview,this.classPrefix);t.append('
    ');var o=this.toolbar=t.find("."+i+"toolbar");if(!e.toolbar)return void o.hide();o.show();for(var a=e.toolbarIcons(),r=o.find("."+this.classPrefix+"menu"),n="",s=0,l=a.length;l>s;s++){var d=a[s];if("|"!==d){var c=/h(\d)/.test(d),h=d;"watch"!==d||e.watch||(h="unwatch");var u=e.lang.toolbar[h],g=e.toolbarIconTexts[h],m=e.toolbarIconsClass[h];u="undefined"==typeof u?"":u,g="undefined"==typeof g?"":g,m="undefined"==typeof m?"":m,n+='
  • '+(c?d:""===m?g:"")+"
  • "}else n+='
  • |
  • '}return r.html(n),this.setToolbarHandler(),this}},getToolbarHandles:function(name){var _this=this,settings=this.settings,lang=settings.lang,editor=this.editor,classPrefix=this.classPrefix,dialogLockScreen=function(){settings.dialogLockScreen&&$("html,body").css("overflow","hidden")},dialogShowMask=function(e){e.css({top:($(window).height()-e.height())/2+"px",left:($(window).width()-e.width())/2+"px"}),settings.dialogShowMask&&editor.find("."+classPrefix+"mask").css("z-index",parseInt(e.css("z-index"))-1).show()},toolbarHandlers=this.toolbarHandlers={undo:function(e){e.undo()},redo:function(e){e.redo()},bold:function(e){var t=e.getCursor(),i=e.getSelection();e.replaceSelection("**"+i+"**"),""===i&&e.setCursor(t.line,t.ch+2)},del:function(e){var t=e.getCursor(),i=e.getSelection();e.replaceSelection("~~"+i+"~~"),""===i&&e.setCursor(t.line,t.ch+2)},italic:function(e){var t=e.getCursor(),i=e.getSelection();e.replaceSelection("*"+i+"*"),""===i&&e.setCursor(t.line,t.ch+1)},quote:function(e){var t=e.getCursor(),i=e.getSelection();e.replaceSelection("> "+i),e.setCursor(t.line,""===i?t.ch+2:t.ch+i.length+2)},h1:function(e){var t=e.getSelection();e.replaceSelection("# "+t)},h2:function(e){var t=e.getSelection();e.replaceSelection("## "+t)},h3:function(e){var t=e.getSelection();e.replaceSelection("### "+t)},h4:function(e){var t=e.getSelection();e.replaceSelection("#### "+t)},h5:function(e){var t=e.getSelection();e.replaceSelection("##### "+t)},h6:function(e){var t=e.getSelection();e.replaceSelection("###### "+t)},"list-ul":function(e){var t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("- "+t);else{for(var i=t.split("\n"),o=0,a=i.length;a>o;o++)i[o]=""===i[o]?"":"- "+i[o];e.replaceSelection(i.join("\n"))}},"list-ol":function(e){var t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("1. "+t);else{for(var i=t.split("\n"),o=0,a=i.length;a>o;o++)i[o]=""===i[o]?"":o+1+". "+i[o];e.replaceSelection(i.join("\n"))}},hr:function(e){e.getCursor(),e.getSelection();e.replaceSelection("------------")},link:function(e){var t,i=e.getSelection(),o=lang.dialog.link,a=classPrefix+"link-dialog";if(editor.find("."+a).length>0)t=editor.find("."+a),t.find("[data-url]").val("http://"),t.find("[data-title]").val(i),dialogShowMask(t),dialogLockScreen(),t.show();else{var r='


    ';t=_this.createDialog({title:o.title,width:380,height:210,content:r,mask:settings.dialogShowMask,drag:settings.dialogDraggable,lockScreen:settings.dialogLockScreen,maskStyle:{opacity:settings.dialogMaskOpacity,backgroundColor:settings.dialogMaskBgColor},buttons:{enter:[lang.buttons.enter,function(){var t=this.find("[data-url]").val(),i=this.find("[data-title]").val();return"http://"===t||""===t?(alert(o.urlEmpty),!1):""===i?(alert(o.titleEmpty),!1):(e.replaceSelection("["+i+"]("+t+' "'+i+'")'),this.hide().lockScreen(!1).hideMask(),!1)}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}})}},anchor:function(e){var t,i=e.getCursor(),o=e.getSelection(),a=lang.dialog.anchor,r=classPrefix+"anchor-dialog";if(editor.find("."+r).length>0)t=editor.find("."+r),t.find("[data-name]").val(""),t.find("[data-url]").val("http://"),t.find("[data-title]").val(o),dialogShowMask(t),dialogLockScreen(),t.show();else{var n='



    ';t=_this.createDialog({name:r,title:a.title,width:380,height:250,content:n,mask:settings.dialogShowMask,drag:settings.dialogDraggable,lockScreen:settings.dialogLockScreen,maskStyle:{opacity:settings.dialogMaskOpacity,backgroundColor:settings.dialogMaskBgColor},buttons:{enter:[lang.buttons.enter,function(){var t=this.find("[data-name]").val(),r=this.find("[data-url]").val(),n=this.find("[data-title]").val();return""===t?(alert(a.nameEmpty),!1):"http://"===r||""===r?(alert(a.urlEmpty),!1):""===n?(alert(a.titleEmpty),!1):(e.replaceSelection("["+n+"]["+t+"]\n["+t+"]: "+r),""===o&&e.setCursor(i.line,i.ch+1),this.hide().lockScreen(!1).hideMask(),!1)}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}})}},image:function(cm){var cursor=cm.getCursor(),selection=cm.getSelection(),imageLang=lang.dialog.image,iframeName=classPrefix+"image-iframe",imageDialogName=classPrefix+"image-dialog",imageDialog;if(editor.find("."+imageDialogName).length>0)imageDialog=editor.find("."+imageDialogName),imageDialog.find('[type="text"]').val(""),imageDialog.find('[type="file"]').val(""),imageDialog.find("[data-link]").val("http://"),dialogShowMask(imageDialog),dialogLockScreen(),imageDialog.show();else{var guid=(new Date).getTime(),action=settings.imageUploadURL+"?guid="+guid;settings.crossDomainUpload&&(action+="&callback="+settings.uploadCallbackURL+"&dialog_id=editormd-image-dialog-"+guid);var imageDialogHTML=(settings.imageUpload?'
    ':'
    ')+(settings.imageUpload?'':"")+"'+function(){return settings.imageUpload?'
    ':""}()+"


    '+(settings.imageUpload?"":"
    ");imageDialog=_this.createDialog({title:imageLang.title,width:settings.imageUpload?465:380,height:250,name:imageDialogName,content:imageDialogHTML,mask:settings.dialogShowMask,drag:settings.dialogDraggable,lockScreen:settings.dialogLockScreen,maskStyle:{opacity:settings.dialogMaskOpacity,backgroundColor:settings.dialogMaskBgColor},buttons:{enter:[lang.buttons.enter,function(){var e=this.find("[data-url]").val(),t=this.find("[data-alt]").val(),i=this.find("[data-link]").val();return""===e?(alert(imageLang.imageURLEmpty),!1):(cm.replaceSelection(""===i||"http://"===i?"!["+t+"]("+e+' "'+t+'")':"[!["+t+"]("+e+' "'+t+'")]('+i+' "'+t+'")'),""===t&&cm.setCursor(cursor.line,cursor.ch+2),this.hide().lockScreen(!1).hideMask(),!1)}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}}),imageDialog.attr("id",classPrefix+"image-dialog-"+guid)}var fileInput=imageDialog.find('[name="'+classPrefix+'image-file"]');fileInput.bind("change",function(){var fileName=fileInput.val(),isImage=new RegExp("(\\.("+settings.imageFormats.join("|")+"))$");if(""===fileName)alert(imageLang.uploadFileEmpty);else if(isImage.test(fileName)){imageDialog.loading(!0);var submitHandler=function(){var uploadIframe=document.getElementById(iframeName);uploadIframe.onload=function(){imageDialog.loading(!1);var json=uploadIframe.contentWindow.document.body.innerHTML;return json="undefined"!=typeof JSON.parse?JSON.parse(json):eval("("+json+")"),1===json.success?imageDialog.find("[data-url]").val(json.url):alert(json.message),!1}};imageDialog.find('[type="submit"]').bind(editormd.mouseOrTouch("click","touchend"),submitHandler).trigger("click")}else alert(imageLang.formatNotAllowed+settings.imageFormats.join(", "));return!1})},code:function(e){var t=e.getCursor(),i=e.getSelection();e.replaceSelection("`"+i+"`"),""===i&&e.setCursor(t.line,t.ch+1)},"code-block-tab":function(e){var t,i=(e.getCursor(),e.getSelection()),o=classPrefix+"dialog-tab-code-block";if(editor.find("."+o).length>0)t=editor.find("."+o),t.find("textarea").val(i),dialogShowMask(t),dialogLockScreen(),t.show();else{var a='";t=_this.createDialog({name:o,title:lang.dialog.tabCodeBlock.title,width:750,height:470,mask:settings.dialogShowMask,drag:settings.dialogDraggable,content:a,lockScreen:settings.dialogLockScreen,maskStyle:{opacity:settings.dialogMaskOpacity,backgroundColor:settings.dialogMaskBgColor},buttons:{enter:[lang.buttons.enter,function(){var t=this.find("textarea").val();if(""===t)return alert(lang.dialog.tabCodeBlock.codeEmptyAlert),!1;t=t.split("\n");for(var i in t)t[i]=" "+t[i];return e.replaceSelection(t.join("\n")),this.hide().lockScreen(!1).hideMask(),!1}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}})}},"code-block":function(e){var t,i=e.getCursor(),o=e.getSelection(),a=classPrefix+"dialog-code-block";if(editor.find("."+a).length>0)t=editor.find("."+a),t.find("option:first").attr("selected","selected"),t.find("textarea").val(o),dialogShowMask(t),dialogLockScreen(),t.show();else{var r='
    '+lang.dialog.codeBlock.selectLabel+'
    ";t=_this.createDialog({name:a,title:lang.dialog.codeBlock.title,width:752,height:565,mask:settings.dialogShowMask,drag:settings.dialogDraggable,content:r,lockScreen:settings.dialogLockScreen,maskStyle:{opacity:settings.dialogMaskOpacity,backgroundColor:settings.dialogMaskBgColor},buttons:{enter:[lang.buttons.enter,function(){var t=this.find("textarea").val(),o=this.find("select").val();return""===o?(alert(lang.dialog.codeBlock.unselectedLanguageAlert),!1):""===t?(alert(lang.dialog.codeBlock.codeEmptyAlert),!1):(o="other"===o?"":o,e.replaceSelection(["```"+o,t,"```"].join("\n")),""===o&&e.setCursor(i.line,i.ch+3),this.hide().lockScreen(!1).hideMask(),!1)}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}});var n=t.find("select");for(var s in editormd.codeLanguages){var l=editormd.codeLanguages[s];n.append('")}n.append('")}},datetime:function(e){var t=(e.getSelection(),new Date,settings.lang.name),i=editormd.dateFormat()+" "+editormd.dateFormat("zh-cn"===t||"zh-tw"===t?"cn-week-day":"week-day");e.replaceSelection(i)},watch:function(){_this[_this.settings.watch?"unwatch":"watch"]()},preview:function(){_this.previewing()},fullscreen:function(){_this.fullscreen()},clear:function(){_this.clear()},info:function(){_this.showInfoDialog()}};return name&&"undefined"!=typeof toolbarIconHandlers[name]?toolbarHandlers[name]:toolbarHandlers},setToolbarHandler:function(){var e=this,t=this.settings;if(t.toolbar&&!t.readOnly){var i=(this.editor,this.preview,this.toolbar),o=this.codeEditor,a=(this.codeMirror,this.classPrefix),r=(this.previewContainer,this.toolbarIcons=i.find("."+a+"menu a"));return r.bind(editormd.mouseOrTouch("click","touchend"),function(){var i=$(this).children(".fa"),a=i.attr("name"),r=o.getCursor(),n=o.getSelection(),s=e.getToolbarHandles();return""!==a?(e.activeIcon=i,"undefined"!=typeof s[a]?s[a](o):"undefined"!=typeof t.toolbarHandlers[a]&&$.proxy(t.toolbarHandlers[a],e)(o,i,r,n),"link"!==a&&"anchor"!==a&&"image"!==a&&"code-block"!==a&&"code-block-tab"!==a&&"watch"!==a&&"preview"!==a&&"fullscreen"!==a&&"info"!==a&&o.focus(),!1):void 0}),this}},createDialog:function(e){var t={name:"",width:420,height:240,title:"",drag:!0,closed:!0,content:"",mask:!0,maskStyle:{backgroundColor:"#fff",opacity:.1},lockScreen:!0,footer:!0,buttons:!1};e=$.extend(!0,t,e);var i=this.editor,o=this.classPrefix,a=(new Date).getTime(),r=""===e.name?o+"dialog-"+a:e.name,n=editormd.mouseOrTouch,s='
    ';""!==e.title&&(s+='
    ",s+=''+e.title+"",s+="
    "),e.closed&&(s+=''),s+='
    '+e.content,(e.footer||"string"==typeof e.footer)&&(s+='"),s+="
    ",s+='
    ',s+='
    ',s+="
    ",i.append(s);var l=i.find("."+r);l.lockScreen=function(t){return e.lockScreen&&$("html,body").css("overflow",t?"hidden":""),l},l.showMask=function(){return e.mask&&i.find("."+o+"mask").css(e.maskStyle).css("z-index",editormd.dialogZindex-1).show(),l},l.hideMask=function(){return e.mask&&i.find("."+o+"mask").hide(),l},l.loading=function(e){var t=l.find("."+o+"dialog-mask");return t[e?"show":"hide"](),l},l.lockScreen(!0).showMask(),l.show().css({zIndex:editormd.dialogZindex,border:editormd.isIE8?"1px solid #ddd":"",width:"number"==typeof e.width?e.width+"px":e.width,height:"number"==typeof e.height?e.height+"px":e.height});var d=function(){l.css({top:($(window).height()-l.height())/2+"px",left:($(window).width()-l.width())/2+"px"})};if(d(),$(window).resize(d),l.children("."+o+"dialog-close").bind(n("click","touchend"),function(){l.hide().lockScreen(!1).hideMask()}),"object"==typeof e.buttons){var c=l.footer=l.find("."+o+"dialog-footer");for(var h in e.buttons){var u=e.buttons[h],g=o+h+"-btn";c.append('"),u[1]=$.proxy(u[1],l),c.children("."+g).bind(n("click","touchend"),u[1])}}if(""!==e.title&&e.drag){var m,f,p=l.children("."+o+"dialog-header");e.mask||p.bind(n("click","touchend"),function(){editormd.dialogZindex+=2,l.css("z-index",editormd.dialogZindex)}),p.mousedown(function(e){e=e||window.event,m=e.clientX-parseInt(l[0].style.left),f=e.clientY-parseInt(l[0].style.top),document.onmousemove=k});var v=function(e){e.removeClass(o+"user-unselect").off("selectstart")},w=function(e){e.addClass(o+"user-unselect").on("selectstart",function(){return!1})},k=function(e){e=e||window.event;var t,i,o=parseInt(l[0].style.left),a=parseInt(l[0].style.top);o>=0?o+l.width()<=$(window).width()?t=e.clientX-m:(t=$(window).width()-l.width(),document.onmousemove=null):(t=0,document.onmousemove=null),a>=0?i=e.clientY-f:(i=0,document.onmousemove=null),document.onselectstart=function(){return!1},w($("body")),w(l),l[0].style.left=t+"px",l[0].style.top=i+"px"};document.onmouseup=function(){v($("body")),v(l),document.onselectstart=null,document.onmousemove=null},p.touchDraggable=function(){var e=null,t=function(t){var i=t.originalEvent,o=$(this).parent().position();e={x:i.changedTouches[0].pageX-o.left,y:i.changedTouches[0].pageY-o.top}},i=function(t){t.preventDefault();var i=t.originalEvent;$(this).parent().css({top:i.changedTouches[0].pageY-e.y,left:i.changedTouches[0].pageX-e.x})};this.bind("touchstart",t).bind("touchmove",i)},p.touchDraggable()}return editormd.dialogZindex+=2,l},createInfoDialog:function(){var e=this,t=this.editor,i=this.classPrefix,o=['
    ','
    ','

    '+editormd.title+"v"+editormd.version+"

    ","

    "+this.lang.description+"

    ",'

    Home page: '+editormd.homePage+"

    ","

    License: MIT

    ","
    ",'',"
    "].join("\n");t.append(o);var a=this.infoDialog=t.find("."+i+"dialog-info");return a.find("."+i+"dialog-close").bind(editormd.mouseOrTouch("click","touchend"),function(){e.hideInfoDialog()}),a.css("border",editormd.isIE8?"1px solid #ddd":"").show(),this.infoDialogPosition(),this},infoDialogPosition:function(){var e=this.infoDialog,t=function(){e.css({top:($(window).height()-e.height())/2+"px",left:($(window).width()-e.width())/2+"px"})};return t(),$(window).resize(t),this},showInfoDialog:function(){$("html,body").css("overflow-x","hidden");var e=this.editor,t=this.classPrefix,i=this.infoDialog=e.find("."+t+"dialog-info");return i.length<1&&this.createInfoDialog(),i.show(),this.infoDialogPosition(),this},hideInfoDialog:function(){return $("html,body").css("overflow-x",""),this.infoDialog.hide(),this},setMarked:function(){var e=editormd.$marked,t=this.markdownToC=[];return e.setOptions({renderer:editormd.markedRenderer(t),gfm:!0,tables:!0,breaks:!0,pedantic:!1,sanitize:this.settings.htmlDecode?!1:!0,smartLists:!0,smartypants:!0}),this},recreateEditor:function(){var e=this.editor,t=this.settings,i=t.toolbarIcons();return"undefined"!=typeof this.infoDialog&&this.infoDialog.remove(),"undefined"!=typeof i.info&&createInfoDialog(),t.readOnly||(e.find(".editormd-dialog").length>0&&e.find(".editormd-dialog").remove(),this.getToolbarHandles(),this.setToolbar()),this.resize(),this},previewCodeHighlight:function(){var e=this.settings,t=this.previewContainer;return e.previewCodeHighlight&&(t.find("pre").addClass("prettyprint linenums"),prettyPrint()),this},katexRender:function(){var e=this.previewContainer;return e.find("."+editormd.classNames.tex).each(function(){var e=$(this);editormd.$katex.render(e.html(),e[0])}),this},flowChartAndSequenceDiagramRender:function(){var e=this.settings,t=this.previewContainer;return editormd.isIE8?void 0:(e.flowChart&&t.find(".flowchart").flowChart(),e.sequenceDiagram&&t.find(".sequence-diagram").sequenceDiagram({theme:"simple"}),this)},loadedDisplay:function(){var e=this,t=this.editor,i=this.preview,o=this.settings,a=this.codeEditor,r=this.codeMirror,n=(this.previewContainer,editormd.mouseOrTouch);t.find("."+this.classPrefix+"container-mask").hide(),this.saveToTextareas(),o.watch&&i.show(),t.data("oldWidth",t.width()).data("oldHeight",t.height()),this.resize(),$(window).resize(function(){e.resize()});var s=function(){r.find(".CodeMirror-scroll").bind(n("scroll","touchmove"),function(){var e=$(this).height(),t=$(this).scrollTop(),o=t/$(this)[0].scrollHeight;i.scrollTop(0===t?0:t+e>=$(this)[0].scrollHeight?i[0].scrollHeight:i[0].scrollHeight*o)})},l=function(){r.find(".CodeMirror-scroll").unbind(n("scroll","touchmove"))},d=function(){i.bind(n("scroll","touchmove"),function(){var e=$(this).height(),t=$(this).scrollTop(),i=t/$(this)[0].scrollHeight,o=r.find(".CodeMirror-scroll");o.scrollTop(0===t?0:t+e>=$(this)[0].scrollHeight?o[0].scrollHeight:o[0].scrollHeight*i)})},c=function(){i.unbind(n("scroll","touchmove"))};return r.bind({mouseover:s,mouseout:l,touchstart:s,touchend:l}),i.bind({mouseover:d,mouseout:c,touchstart:d,touchend:c}),a.on("change",function(){e.saveToTextareas()}),$.proxy(o.onload,this)(),this.state.loaded=!0,this},width:function(e){return this.editor.css("width","number"==typeof e?e+"px":e),this.resize(),this},height:function(e){return this.editor.css("height","number"==typeof e?e+"px":e),this.resize(),this},resize:function(e,t){e=e||null,t=t||null;var i=this.editor,o=this.preview,a=this.toolbar,r=this.settings,n=(this.codeEditor,this.codeMirror);return e&&t&&i.css({width:"number"==typeof e?e+"px":e,height:"number"==typeof t?t+"px":t}),r.toolbar&&!r.readOnly?n.css("margin-top",a.height()+1).height(i.height()-a.height()):n.css("margin-top",0).height(i.height()),n.find(".CodeMirror-gutters").height(n.height()),r.watch?(n.width(i.width()/2),o.width(this.state.preview?i.width():i.width()/2),r.toolbar&&!r.readOnly?o.css("top",a.height()).height(i.height()-a.height()):o.css("top",0).height(i.height())):(n.width(i.width()),o.hide()),this},saveToTextareas:function(){var e=this,t=this.state,i=this.settings,o=this.codeEditor,a=this.previewContainer,r=o.getValue(),n=this.markdownToC=[],s=editormd.$marked(r,{renderer:editormd.markedRenderer(n)});if(this.markdownTextarea[0].innerText=r,o.save(),i.saveHTMLToTextarea&&this.htmlTextarea.html(s),i.watch||!i.watch&&t.preview){a.html(s),this.previewCodeHighlight(),i.toc&&editormd.markdownToCRenderer(n,a,i.tocStartLevel),i.inRequirejs||editormd.kaTeXLoaded?this.katexRender():editormd.loadKaTeX(function(){editormd.$katex=katex,editormd.kaTeXLoaded=!0,e.katexRender()});var l=setTimeout(function(){clearTimeout(l),e.flowChartAndSequenceDiagramRender()},10);t.loaded&&$.proxy(i.onchange,this)()}return this},focus:function(){return this.codeEditor.focus(),this},setCursor:function(e){return this.codeEditor.setCursor(e),this},getCursor:function(){return this.codeEditor.getCursor()},setSelection:function(e,t){return this.codeEditor.setSelection(e,t),this},getSelection:function(){return this.codeEditor.getSelection()},replaceSelection:function(e){return this.codeEditor.replaceSelection(e),this},insertValue:function(e){return this.replaceSelection(e),this},setMarkdown:function(e){this.settings;return this.codeEditor.setValue(e),this},getMarkdown:function(){return this.codeEditor.getValue()},clear:function(){return this.codeEditor.setValue(""),this},getHTML:function(){return this.settings.saveHTMLToTextarea?this.htmlTextarea.html():(alert("Error: settings.saveHTMLToTextarea == false"),!1)},getTextareaSavedHTML:function(){return this.getHTML()},getPreviewedHTML:function(){return this.settings.watch?this.previewContainer.html():(alert("Error: settings.watch == false"),!1)},watch:function(e){e=e||function(){},this.state.watching=this.settings.watch=!0,this.preview.show();var t=this.settings.toolbarIconsClass.watch,i=this.settings.toolbarIconsClass.unwatch,o=this.toolbar.find(".fa[name=watch]");return o.parent().attr("title",this.settings.lang.toolbar.watch),o.removeClass(i).addClass(t),this.codeMirror.css("border-right","1px solid #ddd").width(this.editor.width()/2),this.saveToTextareas().resize(),$.proxy(e,this)(),this},unwatch:function(e){e=e||function(){},this.state.watching=this.settings.watch=!1,this.preview.hide();var t=this.settings.toolbarIconsClass.watch,i=this.settings.toolbarIconsClass.unwatch,o=this.toolbar.find(".fa[name=watch]");return o.parent().attr("title",this.settings.lang.toolbar.unwatch),o.removeClass(t).addClass(i),this.codeMirror.css("border-right","none").width(this.editor.width()),this.resize(),$.proxy(e,this)(),this},show:function(e){e=e||function(){};var t=this;return this.editor.show(function(){$.proxy(e,t)()}),this},hide:function(e){e=e||function(){};var t=this;return this.editor.hide(function(){$.proxy(e,t)()}),this},previewing:function(){var e=this,t=this.editor,i=this.preview,o=this.toolbar,a=this.settings,r=this.codeMirror;a.toolbar&&(o.toggle(),o.find(".fa[name=preview]").toggleClass("active")),r.toggle(),"none"===r.css("display")?(this.state.preview=!0,this.state.fullscreen&&i.css("background","#fff"),t.find("."+this.classPrefix+"preview-close-btn").show().bind(editormd.mouseOrTouch("click","touchend"),function(){e.previewed()}),a.watch||this.saveToTextareas(),i.show().css({position:"static",top:0,width:t.width(),height:t.height()})):this.previewed(),$(window).keyup(function(t){27===t.keyCode&&e.previewed()})},previewed:function(){var e=this.editor,t=this.preview,i=this.toolbar,o=this.settings,a=this.codeMirror,r=e.find("."+this.classPrefix+"preview-close-btn");return this.state.preview=!1,a.show(),o.toolbar&&i.show(),this.settings.watch?t.show():t.hide(),r.hide().bind(editormd.mouseOrTouch("click","touchend")),t.css({background:null,position:"absolute",width:e.width()/2,height:e.height()-i.height(),top:o.toolbar?i.height():0}),this},fullscreen:function(){var e=this,t=this.editor,i=(this.preview,this.toolbar),o=this.classPrefix+"fullscreen";return i.find(".fa[name=fullscreen]").parent().toggleClass("active"),t.hasClass(o)?this.fullscreenExit():(this.state.fullscreen=!0,$("html,body").css("overflow","hidden"),t.css({position:"fixed",top:0,left:0,margin:0,border:"none",width:$(window).width(),height:$(window).height()}).addClass(o),this.resize(),$.proxy(this.settings.onfullscreen,this)()),$(window).keyup(function(t){e.state.preview||27===t.keyCode&&e.fullscreenExit() -}),this},fullscreenExit:function(){var e=this.editor,t=this.classPrefix+"fullscreen";return this.state.fullscreen=!1,this.toolbar.find(".fa[name=fullscreen]").parent().removeClass("active"),$("html,body").css("overflow",""),e.css({position:"",top:"",left:"",margin:"0 auto",width:e.data("oldWidth"),height:e.data("oldHeight"),border:"1px solid #ddd"}).removeClass(t),this.resize(),$.proxy(this.settings.onfullscreenExit,this)(),this}},editormd.fn.init.prototype=editormd.fn,editormd.trim=function(e){return String.prototype.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")};var trim=editormd.trim;return editormd.markedRenderer=function(e){var t=editormd.$marked,i=new t.Renderer;return e=e||[],i.heading=function(t,i){var o=t,a=/\s*\]*)\>(.*)\<\/a\>\s*/;if(a.test(t)){var r=[];t=t.split(/\]+)\>([^\>]*)\<\/a\>/);for(var n=0,s=t.length;s>n;n++)r.push(t[n].replace(/\s*href\=\"(.*)\"\s*/g,""));t=r.join(" ")}t=trim(t);var l=t.toLowerCase().replace(/[^\w]+/g,"-"),d={text:t,level:i,slug:l},c=/^[\u4e00-\u9fa5]+$/.test(t),h=c?escape(t).replace(/\%/g,""):t.toLowerCase().replace(/[^\w]+/g,"-");e.push(d);var u="';return u+='',u+='',u+=a?o:t,u+=""},i.paragraph=function(e){var t=/\$\$(.*)\$\$/g.test(e),i=/^\$\$(.*)\$\$$/.test(e),o=i?' class="'+editormd.classNames.tex+'"':"",a=/^\[TOC\]$/.test(e);return e=!i&&t?e.replace(/(\$\$([^\$]*)\$\$)+/g,function(e,t){return''+t.replace(/\$/g,"")+""}):i?e.replace(/\$/g,""):e,a?'
      '+e+"
    ":""+e+"

    \n"},i.code=function(e,i){return"seq"===i||"sequence"===i?'
    '+e+"
    ":"flow"===i?'
    '+e+"
    ":t.Renderer.prototype.code.apply(this,arguments)},i},editormd.markdownToCRenderer=function(e,t,i){var o="",a=0;i=i||1;for(var r=0,n=e.length;n>r;r++){var s=e[r].text,l=e[r].level;i>l||(o+=l>a?"":a>l?new Array(a-l+2).join(""):"",o+='
  • '+s+"
      ",a=l)}var d=t.find(".markdown-toc");return d.children(".markdown-toc-list").html("").html(o),d},editormd.markdownToHTML=function(e,t){t=t||{};var i={toc:!0,tocStartLevel:2,markdown:"",htmlDecode:!1,inRequirejs:!1,tex:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0};editormd.$marked=marked;var o=$("#"+e),a=o.settings=$.extend(!0,i,t),r=o.find("textarea"),n=""===a.markdown?r.val():a.markdown,s=[],l={renderer:editormd.markedRenderer(s),gfm:!0,tables:!0,breaks:!0,pedantic:!1,sanitize:a.htmlDecode?!1:!0,smartLists:!0,smartypants:!0},d=marked(n,l);if(editormd.isIE8?r.val(n):r.html(n),o.addClass("markdown-body "+this.classPrefix+"html-preview").append(d),a.toc&&(o.tocContainer=this.markdownToCRenderer(s,o,a.tocStartLevel)),a.previewCodeHighlight&&(o.find("pre").addClass("prettyprint linenums"),prettyPrint()),editormd.isIE8||(a.flowChart&&o.find(".flowchart").flowChart(),a.sequenceDiagram&&o.find(".sequence-diagram").sequenceDiagram({theme:"simple"})),a.tex){var c=function(){o.find("."+editormd.classNames.tex).each(function(){var e=$(this);editormd.$katex.render(e.html(),e[0])})};a.inRequirejs?c():this.loadKaTeX(function(){editormd.$katex=katex,c()})}return o.getMarkdown=function(){return editormd.isIE8?r.val():r.html()},o},editormd.codeLanguages={asp:"ASP",actionscript:"ActionScript(3.0)/Flash/Flex",bash:"Bash/Bat",css:"CSS",c:"C",cpp:"C++",csharp:"C#",coffeescript:"CoffeeScript",d:"D",dart:"Dart",delphi:"Delphi/Pascal",erlang:"Erlang",go:"Golang",groovy:"Groovy",html:"HTML",java:"Java",json:"JSON",javascript:"Javascript",lua:"Lua",less:"LESS",markdown:"Markdown","objective-c":"Objective-C",php:"PHP",perl:"Perl",python:"Python",r:"R",rst:"reStructedText",ruby:"Ruby",sql:"SQL",sass:"SASS/SCSS",shell:"Shell",scala:"Scala",swift:"Swift",vb:"VB/VBScript",xml:"XML",yaml:"YAML"},editormd.codeMirrorModules={modes:["css","sass","shell","sql","clike","php","xml","markdown","javascript","htmlmixed","gfm","http","go","dart","coffeescript","nginx","python","perl","lua","r","ruby","rst","smartymixed","vb","vbscript","velocity","xquery","yaml","erlang","jade"],addons:["edit/trailingspace","dialog/dialog","search/searchcursor","search/search","scroll/annotatescrollbar","search/matchesonscrollbar","display/placeholder","edit/closetag","fold/xml-fold","mode/overlay","selection/active-line","edit/closebrackets","display/fullscreen","search/searchcursor","search/match-highlighter"]},editormd.requirejsInit=function(e,t,i,o){editormd.$CodeMirror=e,editormd.$marked=t,editormd.$katex=i,editormd.$prettyPrint=o},editormd.requireModules=function(e){e=e||"";var t=(editormd.defaults,[]);t.push(e+"codemirror/codemirror.min");for(var i=editormd.codeMirrorModules,o=0,a=i.modes.length;a>o;o++){var r=i.modes[o];t.push(e+"codemirror/mode/"+r+"/"+r)}for(var o=0,a=i.addons.length;a>o;o++){var n=i.addons[o];t.push(e+"codemirror/addon/"+n)}return editormd.loadCSS(editormd.katexURL.css),t},editormd.loadCSS=function(e,t,i){i=i||"head",t=t||function(){};var o=document.createElement("link");o.type="text/css",o.rel="stylesheet",o.onload=o.onreadystatechange=function(){t()},o.href=e+".css","head"===i?document.getElementsByTagName("head")[0].appendChild(o):document.body.appendChild(o)},editormd.isIE="Microsoft Internet Explorer"==navigator.appName,editormd.isIE8=editormd.isIE&&"8."==navigator.appVersion.match(/8./i),editormd.loadScript=function(e,t,i){i=i||"head",t=t||function(){};var o=null;o=document.createElement("script"),o.id=e.replace(/[\./]+/g,"-"),o.type="text/javascript",o.src=e+".js",editormd.isIE8?o.onreadystatechange=function(){o.readyState&&("loaded"===o.readyState||"complete"===o.readyState)&&(o.onreadystatechange=null,t())}:o.onload=function(){t()},"head"===i?document.getElementsByTagName("head")[0].appendChild(o):document.body.appendChild(o)},editormd.katexURL={css:"//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min",js:"//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min"},editormd.kaTeXLoaded=!1,editormd.loadKaTeX=function(e){editormd.loadCSS(editormd.katexURL.css,function(){editormd.loadScript(editormd.katexURL.js,e||function(){})})},editormd.mouseOrTouch=function(e,t){e=e||"click",t=t||"touchend";var i=e;try{document.createEvent("TouchEvent"),i=t}catch(o){}return i},editormd.dateFormat=function(e){e=e||"";var t=function(e){return 10>e?"0"+e:e},i=new Date,o=i.getFullYear(),a=o.toString().slice(2,4),r=t(i.getMonth()+1),n=t(i.getDate()),s=i.getDay(),l=t(i.getHours()),d=t(i.getMinutes()),c=t(i.getSeconds()),h=t(i.getMilliseconds()),u="",g=a+"-"+r+"-"+n,m=o+"-"+r+"-"+n,f=l+":"+d+":"+c;switch(e){case"UNIX Time":u=i.getTime();break;case"UTC":u=i.toUTCString();break;case"yy":u=a;break;case"year":case"yyyy":u=o;break;case"month":case"mm":u=r;break;case"cn-week-day":case"cn-wd":var p=["日","一","二","三","四","五","六"];u="星期"+p[s];break;case"week-day":case"wd":var v=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];u=v[s];break;case"day":case"dd":u=n;break;case"hour":case"hh":u=l;break;case"min":case"ii":u=d;break;case"second":case"ss":u=c;break;case"ms":u=h;break;case"yy-mm-dd":u=g;break;case"yyyy-mm-dd":u=m;break;case"yyyy-mm-dd h:i:s ms":case"full + ms":u=m+" "+f+" "+h;break;case"full":case"yyyy-mm-dd h:i:s":default:u=m+" "+f}return u},editormd}}); \ No newline at end of file diff --git a/dist/js/languages/en.js b/dist/js/languages/en.js deleted file mode 100644 index 211a071..0000000 --- a/dist/js/languages/en.js +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Editor.md - * @file languages\en.js - * @version v1.1.9 - * @description A simple online markdown editor. - * @license MIT License - * @author Pandao - * {@link https://github.com/pandao/editor.md} - * @updateTime 2015-03-04 - */ - -(function(){ - var factory = function (exports) { - var lang = { - name : "en", - description : "A simple markdown doucment online editor.", - toolbar : { - undo : "Undo(Ctrl+Z)", - redo : "Redo(Ctrl+Y)", - bold : "Bold", - del : "Strikethrough", - italic : "Italic", - quote : "Block quote", - h1 : "Heading 1", - h2 : "Heading 2", - h3 : "Heading 3", - h4 : "Heading 4", - h5 : "Heading 5", - h6 : "Heading 6", - "list-ul" : "Unordered list", - "list-ol" : "Ordered list", - hr : "Horizontal line", - link : "Link", - anchor : "Anchor", - image : "Image", - code : "Code inline", - "code-block-tab" : "Preformatted text / Code block (Tab indent)", - "code-block" : "Code block (Multi-languages)", - datetime : "Datetime", - watch : "Unwatch", - unwatch : "Watch", - preview : "HTML Preview (Enter ESC exit)", - fullscreen : "Fullscreen (Enter ESC exit)", - clear : "Clear", - info : "About " + exports.title - }, - buttons : { - enter : "Enter", - cancel : "Cancel" - }, - dialog : { - link : { - title : "Link", - url : "Address", - urlTitle : "Title", - urlEmpty : "Error: Please fill in the link address.", - titleEmpty : "Error: Please fill in the link title." - }, - anchor : { - title : "Anchor link", - name : "Name", - url : "Address", - urlTitle : "Title", - nameEmpty: "Error: anchor name can't be empty.", - titleEmpty : "Error: Please fill in anchor link title.", - urlEmpty : "Error: Please fill in anchor link." - }, - image : { - title : "Image", - url : "Address", - link : "Link", - alt : "Title", - uploadButton : "Upload", - imageURLEmpty : "Error: picture url address can't be empty.", - uploadFileEmpty : "Error: upload pictures cannot be empty!", - formatNotAllowed : "Error: only allows to upload pictures file, upload allowed image file format:" - }, - tabCodeBlock : { - title : "Preformatted text / Codes", - codeEmptyAlert : "Error: Please fill in the Preformatted text or content of the codes." - }, - codeBlock : { - title : "Code block", - selectLabel : "Languages: ", - selectDefaultText : "select a code language...", - otherLanguage : "Other languages", - unselectedLanguageAlert : "Error: Please select the code language.", - codeEmptyAlert : "Error: Please fill in the code content." - } - } - }; - - exports.defaults.lang = lang; - }; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) { // for Require.js - - define(["editormd"], function(editormd) { - factory(editormd); - }); - - } else { // for Sea.js - define(function(require) { - var editormd = require("../editormd"); - factory(editormd); - }); - } - } - else - { - factory(window.editormd); - } - -})(); \ No newline at end of file diff --git a/dist/js/languages/en.min.js b/dist/js/languages/en.min.js deleted file mode 100644 index 4ad389c..0000000 --- a/dist/js/languages/en.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! Editor.md v1.1.9 | languages\en.min.js | A simple online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-03-04 */ -!function(){var e=function(e){var t={name:"en",description:"A simple markdown doucment online editor.",toolbar:{undo:"Undo(Ctrl+Z)",redo:"Redo(Ctrl+Y)",bold:"Bold",del:"Strikethrough",italic:"Italic",quote:"Block quote",h1:"Heading 1",h2:"Heading 2",h3:"Heading 3",h4:"Heading 4",h5:"Heading 5",h6:"Heading 6","list-ul":"Unordered list","list-ol":"Ordered list",hr:"Horizontal line",link:"Link",anchor:"Anchor",image:"Image",code:"Code inline","code-block-tab":"Preformatted text / Code block (Tab indent)","code-block":"Code block (Multi-languages)",datetime:"Datetime",watch:"Unwatch",unwatch:"Watch",preview:"HTML Preview (Enter ESC exit)",fullscreen:"Fullscreen (Enter ESC exit)",clear:"Clear",info:"About "+e.title},buttons:{enter:"Enter",cancel:"Cancel"},dialog:{link:{title:"Link",url:"Address",urlTitle:"Title",urlEmpty:"Error: Please fill in the link address.",titleEmpty:"Error: Please fill in the link title."},anchor:{title:"Anchor link",name:"Name",url:"Address",urlTitle:"Title",nameEmpty:"Error: anchor name can't be empty.",titleEmpty:"Error: Please fill in anchor link title.",urlEmpty:"Error: Please fill in anchor link."},image:{title:"Image",url:"Address",link:"Link",alt:"Title",uploadButton:"Upload",imageURLEmpty:"Error: picture url address can't be empty.",uploadFileEmpty:"Error: upload pictures cannot be empty!",formatNotAllowed:"Error: only allows to upload pictures file, upload allowed image file format:"},tabCodeBlock:{title:"Preformatted text / Codes",codeEmptyAlert:"Error: Please fill in the Preformatted text or content of the codes."},codeBlock:{title:"Code block",selectLabel:"Languages: ",selectDefaultText:"select a code language...",otherLanguage:"Other languages",unselectedLanguageAlert:"Error: Please select the code language.",codeEmptyAlert:"Error: Please fill in the code content."}}};e.defaults.lang=t};"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?module.exports=e:"function"==typeof define?define.amd?define(["editormd"],function(t){e(t)}):define(function(t){var l=t("../editormd");e(l)}):e(window.editormd)}(); \ No newline at end of file diff --git a/dist/js/languages/zh-tw.js b/dist/js/languages/zh-tw.js deleted file mode 100644 index 17e6b2b..0000000 --- a/dist/js/languages/zh-tw.js +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Editor.md - * @file languages\zh-tw.js - * @version v1.1.9 - * @description A simple online markdown editor. - * @license MIT License - * @author Pandao - * {@link https://github.com/pandao/editor.md} - * @updateTime 2015-03-04 - */ - -(function(){ - var factory = function (exports) { - var lang = { - name : "zh-tw", - description : "開源在線Markdown編輯器
      A simple markdown doucment online editor.", - toolbar : { - undo : "撤銷(Ctrl+Z)", - redo : "重做(Ctrl+Y)", - bold : "粗體", - del : "刪除線", - italic : "斜體", - quote : "引用", - h1 : "標題1", - h2 : "標題2", - h3 : "標題3", - h4 : "標題4", - h5 : "標題5", - h6 : "標題6", - "list-ul" : "無序列表", - "list-ol" : "有序列表", - hr : "横线", - link : "链接", - anchor : "錨點", - image : "圖片", - code : "行內代碼", - "code-block-tab" : "預格式文本 / 代碼塊(縮進風格)", - "code-block" : "代碼塊(多語言風格)", - datetime : "日期時間", - watch : "關閉實時預覽", - unwatch : "開啟實時預覽", - preview : "全窗口預覽HTML(可按ESC還原)", - fullscreen : "全屏(可按ESC還原)", - clear : "清空", - info : "關於" + exports.title - }, - buttons : { - enter : "確定", - cancel : "取消" - }, - dialog : { - link : { - title : "添加鏈接", - url : "鏈接地址", - urlTitle : "鏈接標題", - urlEmpty : "錯誤:請填寫鏈接地址。", - titleEmpty : "錯誤:請填寫鏈接標題。" - }, - anchor : { - title : "添加錨點鏈接", - name : "錨點名稱", - url : "鏈接地址", - urlTitle : "鏈接標題", - nameEmpty: "錯誤:錨點名稱不能為空。", - titleEmpty : "錯誤:請填寫錨點鏈接標題。", - urlEmpty : "錯誤:請填寫錨點鏈接地址。" - }, - image : { - title : "添加圖片", - url : "圖片地址", - link : "圖片鏈接", - alt : "圖片描述", - uploadButton : "本地上傳", - imageURLEmpty : "錯誤:圖片地址不能為空。", - uploadFileEmpty : "錯誤:上傳的圖片不能為空!", - formatNotAllowed : "錯誤:只允許上傳圖片文件,允許上傳的圖片文件格式有:" - }, - tabCodeBlock : { - title : "添加預格式文本或代碼塊", - codeEmptyAlert : "錯誤:請填寫預格式文本或代碼的內容。" - }, - codeBlock : { - title : "添加代碼塊", - selectLabel : "代碼語言:", - selectDefaultText : "請語言代碼語言", - otherLanguage : "其他語言", - unselectedLanguageAlert : "錯誤:請選擇代碼所屬的語言類型。", - codeEmptyAlert : "錯誤:請填寫代碼內容。" - } - } - }; - - exports.defaults.lang = lang; - }; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) { // for Require.js - - define(["editormd"], function(editormd) { - factory(editormd); - }); - - } else { // for Sea.js - define(function(require) { - var editormd = require("../editormd"); - factory(editormd); - }); - } - } - else - { - factory(window.editormd); - } - -})(); \ No newline at end of file diff --git a/dist/js/languages/zh-tw.min.js b/dist/js/languages/zh-tw.min.js deleted file mode 100644 index 832a3e4..0000000 --- a/dist/js/languages/zh-tw.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! Editor.md v1.1.9 | languages\zh-tw.min.js | A simple online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-03-04 */ -!function(){var e=function(e){var t={name:"zh-tw",description:"開源在線Markdown編輯器
      A simple markdown doucment online editor.",toolbar:{undo:"撤銷(Ctrl+Z)",redo:"重做(Ctrl+Y)",bold:"粗體",del:"刪除線",italic:"斜體",quote:"引用",h1:"標題1",h2:"標題2",h3:"標題3",h4:"標題4",h5:"標題5",h6:"標題6","list-ul":"無序列表","list-ol":"有序列表",hr:"横线",link:"链接",anchor:"錨點",image:"圖片",code:"行內代碼","code-block-tab":"預格式文本 / 代碼塊(縮進風格)","code-block":"代碼塊(多語言風格)",datetime:"日期時間",watch:"關閉實時預覽",unwatch:"開啟實時預覽",preview:"全窗口預覽HTML(可按ESC還原)",fullscreen:"全屏(可按ESC還原)",clear:"清空",info:"關於"+e.title},buttons:{enter:"確定",cancel:"取消"},dialog:{link:{title:"添加鏈接",url:"鏈接地址",urlTitle:"鏈接標題",urlEmpty:"錯誤:請填寫鏈接地址。",titleEmpty:"錯誤:請填寫鏈接標題。"},anchor:{title:"添加錨點鏈接",name:"錨點名稱",url:"鏈接地址",urlTitle:"鏈接標題",nameEmpty:"錯誤:錨點名稱不能為空。",titleEmpty:"錯誤:請填寫錨點鏈接標題。",urlEmpty:"錯誤:請填寫錨點鏈接地址。"},image:{title:"添加圖片",url:"圖片地址",link:"圖片鏈接",alt:"圖片描述",uploadButton:"本地上傳",imageURLEmpty:"錯誤:圖片地址不能為空。",uploadFileEmpty:"錯誤:上傳的圖片不能為空!",formatNotAllowed:"錯誤:只允許上傳圖片文件,允許上傳的圖片文件格式有:"},tabCodeBlock:{title:"添加預格式文本或代碼塊",codeEmptyAlert:"錯誤:請填寫預格式文本或代碼的內容。"},codeBlock:{title:"添加代碼塊",selectLabel:"代碼語言:",selectDefaultText:"請語言代碼語言",otherLanguage:"其他語言",unselectedLanguageAlert:"錯誤:請選擇代碼所屬的語言類型。",codeEmptyAlert:"錯誤:請填寫代碼內容。"}}};e.defaults.lang=t};"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?module.exports=e:"function"==typeof define?define.amd?define(["editormd"],function(t){e(t)}):define(function(t){var l=t("../editormd");e(l)}):e(window.editormd)}(); \ No newline at end of file diff --git a/docs/html/index.html b/docs/html/index.html deleted file mode 100644 index 23fa80d..0000000 --- a/docs/html/index.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - JSDoc: Index - - - - - - - - - - -
      - -

      Index

      - - - - - - - -

      - - - - - - - - - - - - - - -
      -

      Editor.md

      -

      -

      - - - - -

      -

      Editor.md is an online(In-browser) markdown editor, based on CodeMirror & jQuery.

      -

      Features

      -
        -
      • Support Standard Markdown and GFM(GitHub Flavored Markdown);
      • -
      • Full-featured: Real-time Preview, Image (cross-domain) upload, Multi-languages, L18n, Syntax highlighting...;
      • -
      • Support ToC (Table of Contents);
      • -
      • Compatible with all major browsers (IE8+), compatible Zepto.js and iPad;
      • -
      • Support identification and interpretation of the HTML tags;
      • -
      • Support TeX (LaTeX expressions, Based on KaTeX);
      • -
      • Support Flowchart and Sequence Diagram of Markdown extended syntax;
      • -
      • Support AMD/CMD (Require.js & Sea.js) Module Loader;
      • -
      -

      README & Examples (English)

      -
      -

      Editor.md 是一个基于CodeMirror和jQuery构建的Markdown在线编辑器。

      -

      editormd-screenshot

      -

      主要特性

      -
        -
      • 支持Markdown标准和Github风格;
      • -
      • 支持实时预览、图片(跨域)上传和多语言语法高亮;
      • -
      • 兼容主流的浏览器(IE8+)和Zepto.js,且支持iPad等平板设备;
      • -
      • 支持ToC(Table of Contents)
      • -
      • 支持识别和解析HTML标签,具有几乎无限的扩展性;
      • -
      • 支持TeX科学公式(基于KaTeX);
      • -
      • 支持流程图 flowchart 和时序图 sequenceDiagram;
      • -
      • 支持AMD/CMD模块化加载(支持 Require.js & Sea.js);
      • -
      -

      在线演示

      -

      https://pandao.github.io/editor.md/examples/index.html

      -

      下载和安装

      -

      通过Github下载安装,或者通过bower安装:

      -
      bower install editor.md
      -

      使用方法

      -

      HTML:

      -
      <link rel="stylesheet" href="../dist/css/editormd.css" />
      -<div id="test-editormd">
      -    <textarea>###Hello world!</textarea>
      -</div>
      -
      -

      提示1:如果没有Markdown源内容或者通过Ajax异步加载Markdown源文档等,可以不添加<textarea>,会自动添加;

      -

      提示2:如果不想出现textarea闪现,则在textarea加上 style="display:none;";

      -
      -

      javascript:

      -
      <script src="../lib/jquery.min.js"></script>
      -<script src="../src/js/editormd.js"></script>
      -<script type="text/javascript">
      -    $(function() {
      -        var testEditor = editormd("test-editormd", {
      -            path : '../lib/' // codemirror、marked等依赖的库的路径
      -        });
      -    });
      -</script>
      -
      -

      Require.js的使用方法:https://github.com/pandao/editor.md/tree/master/examples/use-requirejs.html

      -

      Sea.js的使用方法:https://github.com/pandao/editor.md/tree/master/examples/use-seajs.html

      -
      -

      依赖项目及感谢

      - -

      更新日志

      -

      查看更新日志

      -

      License

      -

      The MIT License.

      -

      Copyright (c) 2015 Pandao

      -
      -
      - - - - - - -
      - - - -
      - -
      - Documentation generated by JSDoc 3.3.0-alpha5 on Wed Mar 04 2015 17:12:36 GMT+0800 (中国标准时间) -
      - - - - - \ No newline at end of file diff --git a/docs/html/scripts/linenumber.js b/docs/html/scripts/linenumber.js deleted file mode 100644 index 8d52f7e..0000000 --- a/docs/html/scripts/linenumber.js +++ /dev/null @@ -1,25 +0,0 @@ -/*global document */ -(function() { - var source = document.getElementsByClassName('prettyprint source linenums'); - var i = 0; - var lineNumber = 0; - var lineId; - var lines; - var totalLines; - var anchorHash; - - if (source && source[0]) { - anchorHash = document.location.hash.substring(1); - lines = source[0].getElementsByTagName('li'); - totalLines = lines.length; - - for (; i < totalLines; i++) { - lineNumber++; - lineId = 'line' + lineNumber; - lines[i].id = lineId; - if (lineId === anchorHash) { - lines[i].className += ' selected'; - } - } - } -})(); diff --git a/docs/html/scripts/prettify/Apache-License-2.0.txt b/docs/html/scripts/prettify/Apache-License-2.0.txt deleted file mode 100644 index d645695..0000000 --- a/docs/html/scripts/prettify/Apache-License-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/docs/html/scripts/prettify/lang-css.js b/docs/html/scripts/prettify/lang-css.js deleted file mode 100644 index 041e1f5..0000000 --- a/docs/html/scripts/prettify/lang-css.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", -/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/docs/html/scripts/prettify/prettify.js b/docs/html/scripts/prettify/prettify.js deleted file mode 100644 index eef5ad7..0000000 --- a/docs/html/scripts/prettify/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p p:first-child -{ - margin-top: 0; - padding-top: 0; -} - -.params td.description > p:last-child -{ - margin-bottom: 0; - padding-bottom: 0; -} - -.disabled { - color: #454545; -} diff --git a/docs/html/styles/prettify-jsdoc.css b/docs/html/styles/prettify-jsdoc.css deleted file mode 100644 index 5a2526e..0000000 --- a/docs/html/styles/prettify-jsdoc.css +++ /dev/null @@ -1,111 +0,0 @@ -/* JSDoc prettify.js theme */ - -/* plain text */ -.pln { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* string content */ -.str { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a keyword */ -.kwd { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a comment */ -.com { - font-weight: normal; - font-style: italic; -} - -/* a type name */ -.typ { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* a literal value */ -.lit { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* punctuation */ -.pun { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* lisp open bracket */ -.opn { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* lisp close bracket */ -.clo { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a markup tag name */ -.tag { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a markup attribute name */ -.atn { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a markup attribute value */ -.atv { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a declaration */ -.dec { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a variable name */ -.var { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* a function name */ -.fun { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { - margin-top: 0; - margin-bottom: 0; -} diff --git a/docs/html/styles/prettify-tomorrow.css b/docs/html/styles/prettify-tomorrow.css deleted file mode 100644 index aa2908c..0000000 --- a/docs/html/styles/prettify-tomorrow.css +++ /dev/null @@ -1,132 +0,0 @@ -/* Tomorrow Theme */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* Pretty printing styles. Used with prettify.js. */ -/* SPAN elements with the classes below are added by prettyprint. */ -/* plain text */ -.pln { - color: #4d4d4c; } - -@media screen { - /* string content */ - .str { - color: #718c00; } - - /* a keyword */ - .kwd { - color: #8959a8; } - - /* a comment */ - .com { - color: #8e908c; } - - /* a type name */ - .typ { - color: #4271ae; } - - /* a literal value */ - .lit { - color: #f5871f; } - - /* punctuation */ - .pun { - color: #4d4d4c; } - - /* lisp open bracket */ - .opn { - color: #4d4d4c; } - - /* lisp close bracket */ - .clo { - color: #4d4d4c; } - - /* a markup tag name */ - .tag { - color: #c82829; } - - /* a markup attribute name */ - .atn { - color: #f5871f; } - - /* a markup attribute value */ - .atv { - color: #3e999f; } - - /* a declaration */ - .dec { - color: #f5871f; } - - /* a variable name */ - .var { - color: #c82829; } - - /* a function name */ - .fun { - color: #4271ae; } } -/* Use higher contrast and text-weight for printable form. */ -@media print, projection { - .str { - color: #060; } - - .kwd { - color: #006; - font-weight: bold; } - - .com { - color: #600; - font-style: italic; } - - .typ { - color: #404; - font-weight: bold; } - - .lit { - color: #044; } - - .pun, .opn, .clo { - color: #440; } - - .tag { - color: #006; - font-weight: bold; } - - .atn { - color: #404; } - - .atv { - color: #060; } } -/* Style */ -/* -pre.prettyprint { - background: white; - font-family: Menlo, Monaco, Consolas, monospace; - font-size: 12px; - line-height: 1.5; - border: 1px solid #ccc; - padding: 10px; } -*/ - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { - margin-top: 0; - margin-bottom: 0; } - -/* IE indents via margin-left */ -li.L0, -li.L1, -li.L2, -li.L3, -li.L4, -li.L5, -li.L6, -li.L7, -li.L8, -li.L9 { - /* */ } - -/* Alternate shading for lines */ -li.L1, -li.L3, -li.L5, -li.L7, -li.L9 { - /* */ } diff --git a/editormd.amd.js b/editormd.amd.js new file mode 100644 index 0000000..281a9dd --- /dev/null +++ b/editormd.amd.js @@ -0,0 +1,3422 @@ +/* + * Editor.md + * + * @file editormd.amd.js + * @version v1.2.0 + * @description A simple online markdown editor. + * @license MIT License + * @author Pandao + * {@link https://github.com/pandao/editor.md} + * @updateTime 2015-03-10 + */ + +;(function(factory) { + "use strict"; + + // CommonJS/Node.js + if (typeof require === "function" && typeof exports === "object" && typeof module === "object") + { + module.exports = factory; + } + else if (typeof define === "function") // AMD/CMD/Sea.js + { + if (define.amd) // for Require.js + { + var cmModePath = "codemirror/mode/"; + var cmAddonPath = "codemirror/addon/"; + + var codeMirrorModules = [ + "jquery", "marked", "prettify", + "katex", "raphael", "underscore", "flowchart", "jqueryflowchart", "sequenceDiagram", + + "codemirror/lib/codemirror", + cmModePath + "css/css", + cmModePath + "sass/sass", + cmModePath + "shell/shell", + cmModePath + "sql/sql", + cmModePath + "clike/clike", + cmModePath + "php/php", + cmModePath + "xml/xml", + cmModePath + "markdown/markdown", + cmModePath + "javascript/javascript", + cmModePath + "htmlmixed/htmlmixed", + cmModePath + "gfm/gfm", + cmModePath + "http/http", + cmModePath + "go/go", + cmModePath + "dart/dart", + cmModePath + "coffeescript/coffeescript", + cmModePath + "nginx/nginx", + cmModePath + "python/python", + cmModePath + "perl/perl", + cmModePath + "lua/lua", + cmModePath + "r/r", + cmModePath + "ruby/ruby", + cmModePath + "rst/rst", + cmModePath + "smartymixed/smartymixed", + cmModePath + "vb/vb", + cmModePath + "vbscript/vbscript", + cmModePath + "velocity/velocity", + cmModePath + "xquery/xquery", + cmModePath + "yaml/yaml", + cmModePath + "erlang/erlang", + cmModePath + "jade/jade", + + cmAddonPath + "edit/trailingspace", + cmAddonPath + "dialog/dialog", + cmAddonPath + "search/searchcursor", + cmAddonPath + "search/search", + cmAddonPath + "scroll/annotatescrollbar", + cmAddonPath + "search/matchesonscrollbar", + cmAddonPath + "display/placeholder", + cmAddonPath + "edit/closetag", + cmAddonPath + "fold/foldcode", + cmAddonPath + "fold/foldgutter", + cmAddonPath + "fold/indent-fold", + cmAddonPath + "fold/brace-fold", + cmAddonPath + "fold/xml-fold", + cmAddonPath + "fold/markdown-fold", + cmAddonPath + "fold/comment-fold", + cmAddonPath + "mode/overlay", + cmAddonPath + "selection/active-line", + cmAddonPath + "edit/closebrackets", + cmAddonPath + "display/fullscreen", + cmAddonPath + "search/match-highlighter" + ]; + + define(codeMirrorModules, factory); + } + else + { + define(["jquery"], factory); // for Sea.js + } + } + else + { + window.editormd = factory(); + } + +}(function() { + + /** + * editormd + * + * @param {String} id 编辑器的ID + * @param {Object} options 配置选项 Key/Value + * @returns {Object} editormd 返回editormd对象 + */ + + if (typeof define == "function" && define.amd) { + $ = arguments[0]; + marked = arguments[1]; + prettify = arguments[2]; + katex = arguments[3]; + Raphael = arguments[4]; + _ = arguments[5]; + flowchart = arguments[6]; + CodeMirror = arguments[9]; + } + + "use strict"; + + var $ = (typeof (jQuery) !== "undefined") ? jQuery : Zepto; + + if (typeof ($) === "undefined") { + return ; + } + + var editormd = function (id, options) { + return new editormd.fn.init(id, options); + }; + + editormd.title = editormd.$name = "Editor.md"; + editormd.version = "1.2.0"; + editormd.homePage = "https://pandao.github.io/editor.md/"; + editormd.classPrefix = "editormd-"; + + editormd.toolbarModes = { + full : [ + "undo", "redo", "|", + "bold", "del", "italic", "quote", "|", + "h1", "h2", "h3", "h4", "h5", "h6", "|", + "list-ul", "list-ol", "hr", "|", + "link", "anchor", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "htmlEntities", "|", + "watch", "preview", "fullscreen", "clear", "|", + "help", "info" + ], + simple : [ + "undo", "redo", "|", + "bold", "del", "italic", "quote", "|", + "h1", "h2", "h3", "h4", "h5", "h6", "|", + "list-ul", "list-ol", "hr", "|", + "watch", "preview", "fullscreen", "|", + "help", "info" + ], + mini : [ + "undo", "redo", "|", + "watch", "preview", "|", + "help", "info" + ] + }; + + editormd.defaults = { + mode : "gfm", //gfm or markdown + theme : "default", + value : "", // value for CodeMirror, if mode not gfm/markdown + markdown : "", + width : "100%", + height : "100%", + path : "./lib/", // Dependents module file directory + autoLoadModules : true, // Automatic load dependent module files + watch : true, + placeholder : "now coding markdown...", + codeFold : false, + autoCloseTags : true, + searchReplace : false, + readOnly : false, + lineNumbers : true, + matchWordHighlight : true, // options: true, false, "onselected" + styleActiveLine : true, // Highlight the current line + dialogLockScreen : true, + dialogShowMask : true, + dialogDraggable : true, + dialogMaskBgColor : "#fff", + dialogMaskOpacity : 0.1, + fontSize : "13px", + saveHTMLToTextarea : false, + + onload : function() {}, + onresize : function() {}, + onchange : function() {}, + onwatch : null, + onunwatch : null, + onpreviewing : function() {}, + onpreviewed : function() {}, + onfullscreen : function() {}, + onfullscreenExit : function() {}, + onscroll : function() {}, + onpreviewscroll : function() {}, + + imageUpload : false, + imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"], + imageUploadURL : "", + crossDomainUpload : false, + uploadCallbackURL : "", + + toc : true, // Table of contents + tocStartLevel : 1, // Said from H1 to create ToC + htmlDecode : false, // Open the HTML tag identification + taskList : false, // Enable Github Flavored Markdown task lists + emoji : false, // :emoji: , Support Github emoji, Twitter Emoji (Twemoji); + // Support FontAwesome icon emoji :fa-xxx: > Using fontAwesome icon web fonts; + // Support Editor.md logo icon emoji :editormd-logo: :editormd-logo-1x: > 1~8x; + tex : false, // TeX(LaTeX), based on KaTeX + flowChart : false, // flowChart.js only support IE9+ + sequenceDiagram : false, // sequenceDiagram.js only support IE9+ + previewCodeHighlight : true, + + inRequirejs : false, // if using Require.js, you must set true value. + + toolbar : true, // show/hide toolbar + toolbarIcons : function() { + return editormd.toolbarModes.full; // return array + }, + toolbarTitles : {}, + toolbarHandlers : {}, + toolbarCustomIcons : {}, // using html tag create toolbar icon, unused default tag. + toolbarIconsClass : { + undo : "fa-undo", + redo : "fa-repeat", + bold : "fa-bold", + del : "fa-strikethrough", + italic : "fa-italic", + quote : "fa-quote-left", + h1 : editormd.classPrefix + "bold", + h2 : editormd.classPrefix + "bold", + h3 : editormd.classPrefix + "bold", + h4 : editormd.classPrefix + "bold", + h5 : editormd.classPrefix + "bold", + h6 : editormd.classPrefix + "bold", + "list-ul" : "fa-list-ul", + "list-ol" : "fa-list-ol", + hr : "fa-minus", + link : "fa-link", + anchor : "fa-anchor", + image : "fa-picture-o", + code : "fa-code", + "preformatted-text" : "fa-file-code-o", + "code-block" : "fa-file-code-o", + table : "fa-table", + datetime : "fa-clock-o", + emoji : "fa-smile-o", + htmlEntities : "fa-copyright", + watch : "fa-eye-slash", + unwatch : "fa-eye", + preview : "fa-search", + fullscreen : "fa-arrows-alt", + clear : "fa-eraser", + help : "fa-question-circle", + info : "fa-info-circle" + }, + toolbarIconTexts : {}, + + lang : { + name : "zh-cn", + description : "开源在线Markdown编辑器
      A simple markdown doucment online editor.", + toolbar : { + undo : "撤销(Ctrl+Z)", + redo : "重做(Ctrl+Y)", + bold : "粗体", + del : "删除线", + italic : "斜体", + quote : "引用", + h1 : "标题1", + h2 : "标题2", + h3 : "标题3", + h4 : "标题4", + h5 : "标题5", + h6 : "标题6", + "list-ul" : "无序列表", + "list-ol" : "有序列表", + hr : "横线", + link : "链接", + anchor : "锚点", + image : "添加图片", + code : "行内代码", + "preformatted-text" : "预格式文本 / 代码块(缩进风格)", + "code-block" : "代码块(多语言风格)", + table : "添加表格", + datetime : "日期时间", + emoji : "Emoji表情", + htmlEntities : "HTML实体字符", + watch : "关闭实时预览", + unwatch : "开启实时预览", + preview : "全窗口预览HTML(可按ESC还原)", + fullscreen : "全屏(按ESC还原)", + clear : "清空", + help : "使用帮助", + info : "关于" + editormd.title + }, + buttons : { + enter : "确定", + cancel : "取消", + close : "关闭" + }, + dialog : { + link : { + title : "添加链接", + url : "链接地址", + urlTitle : "链接标题", + urlEmpty : "错误:请填写链接地址。" + }, + anchor : { + title : "添加锚点链接", + name : "锚点名称", + url : "链接地址", + urlTitle : "链接标题", + nameEmpty: "错误:锚点名称不能为空。", + titleEmpty : "错误:请填写锚点链接标题。", + urlEmpty : "错误:请填写锚点链接地址。" + }, + image : { + title : "添加图片", + url : "图片地址", + link : "图片链接", + alt : "图片描述", + uploadButton : "本地上传", + imageURLEmpty : "错误:图片地址不能为空。", + uploadFileEmpty : "错误:上传的图片不能为空。", + formatNotAllowed : "错误:只允许上传图片文件,允许上传的图片文件格式有:" + }, + preformattedText : { + title : "添加预格式文本或代码块", + emptyAlert : "错误:请填写预格式文本或代码的内容。" + }, + codeBlock : { + title : "添加代码块", + selectLabel : "代码语言:", + selectDefaultText : "请选择代码语言", + otherLanguage : "其他语言", + unselectedLanguageAlert : "错误:请选择代码所属的语言类型。", + codeEmptyAlert : "错误:请填写代码内容。" + }, + htmlEntities : { + title : "HTML 实体字符" + }, + help : { + title : "使用帮助" + } + } + } + }; + + editormd.classNames = { + tex : editormd.classPrefix + "tex" + }; + + editormd.dialogZindex = 99999; + + editormd.$katex = null; + editormd.$marked = null; + editormd.$CodeMirror = null; + editormd.$prettyPrint = null; + + editormd.prototype = editormd.fn = { + state : { + watching : false, + loaded : false, + preview : false, + fullscreen : false + }, + + /** + * 构造函数/实例初始化 + * Constructor / instance initialization + * + * @param {String} id 编辑器的ID + * @param {Object} [options={}] 配置选项 Key/Value + * @returns {editormd} 返回editormd的实例对象 + */ + + init : function (id, options) { + + options = options || {}; + + var _this = this; + var classPrefix = this.classPrefix = editormd.classPrefix; + var editor = this.editor = $("#" + id); + var settings = this.settings = $.extend(true, editormd.defaults, options); + + this.id = id; + this.lang = settings.lang; + + var classNames = this.classNames = { + textarea : { + html : this.classPrefix + "html-textarea", + markdown : this.classPrefix + "markdown-textarea" + } + }; + + this.state.watching = (settings.watch) ? true : false; + + if (!editor.hasClass("editormd")) { + editor.addClass("editormd"); + } + + editor.css({ + width : (typeof settings.width === "number") ? settings.width + "px" : settings.width, + height : (typeof settings.height === "number") ? settings.height + "px" : settings.height + }); + + var markdownTextarea = this.markdownTextarea = editor.children("textarea"); + + if (markdownTextarea.length < 1) + { + editor.append(""); + markdownTextarea = this.markdownTextarea = editor.children("textarea"); + } + + markdownTextarea.addClass(classNames.textarea.markdown).attr("name", id + "-markdown-doc").attr("placeholder", settings.placeholder); + + var appendElements = [ + (!settings.readOnly) ? "
      " : "", + ( (settings.saveHTMLToTextarea) ? "" : "" ), + "
      ", + "
      ", + "
      " + ].join("\n"); + + editor.append(appendElements).addClass(classPrefix + "vertical"); + + this.mask = editor.children("." + classPrefix + "mask"); + + if (settings.markdown !== "") + { + markdownTextarea.val(settings.markdown); + } + + this.htmlTextarea = editor.children("." + classNames.textarea.html); + this.preview = editor.children("." + classPrefix + "preview"); + this.previewContainer = this.preview.children("." + classPrefix + "preview-container"); + + if (typeof define === "function" && define.amd) + { + if (typeof katex !== "undefined") + { + editormd.$katex = katex; + } + + if (settings.searchReplace) + { + editormd.loadCSS(settings.path + "codemirror/addon/dialog/dialog"); + editormd.loadCSS(settings.path + "codemirror/addon/search/matchesonscrollbar"); + } + } + + if (typeof define === "function" || !settings.autoLoadModules) + { + if (typeof CodeMirror !== "undefined") editormd.$CodeMirror = CodeMirror; + if (typeof marked !== "undefined") editormd.$marked = marked; + + _this.setCodeMirror(); + _this.setToolbar(); + _this.loadedDisplay(); + } + else + { + this.loadQueues(); + } + + return this; + }, + + /** + * 所需组件加载队列 + * Required components loading queue + * + * @returns {editormd} 返回editormd的实例对象 + */ + + loadQueues : function() { + var _this = this; + var settings = this.settings; + var loadPath = settings.path; + + var loadFlowChartOrSequenceDiagram = function() { + + if (editormd.isIE8) + { + _this.loadedDisplay(); + + return ; + } + + if (settings.flowChart || settings.sequenceDiagram) + { + editormd.loadScript(loadPath + "raphael.min", function() { + + editormd.loadScript(loadPath + "underscore.min", function() { + + if (!settings.flowChart && settings.sequenceDiagram) + { + editormd.loadScript(loadPath + "sequence-diagram.min", function() { + _this.loadedDisplay(); + }); + } + else if (settings.flowChart && !settings.sequenceDiagram) + { + editormd.loadScript(loadPath + "flowchart.min", function() { + editormd.loadScript(loadPath + "jquery.flowchart.min", function() { + _this.loadedDisplay(); + }); + }); + } + else if (settings.flowChart && settings.sequenceDiagram) + { + editormd.loadScript(loadPath + "flowchart.min", function() { + editormd.loadScript(loadPath + "jquery.flowchart.min", function() { + editormd.loadScript(loadPath + "sequence-diagram.min", function() { + _this.loadedDisplay(); + }); + }); + }); + } + }); + + }); + } + else + { + _this.loadedDisplay(); + } + }; + + editormd.loadCSS(loadPath + "codemirror/codemirror.min"); + + if (settings.searchReplace) + { + editormd.loadCSS(loadPath + "codemirror/addon/dialog/dialog"); + editormd.loadCSS(loadPath + "codemirror/addon/search/matchesonscrollbar"); + } + + if (settings.codeFold) + { + editormd.loadCSS(loadPath + "codemirror/addon/fold/foldgutter"); + } + + editormd.loadScript(loadPath + "codemirror/codemirror.min", function() { + + editormd.$CodeMirror = CodeMirror; + + editormd.loadScript(loadPath + "codemirror/modes.min", function() { + + editormd.loadScript(loadPath + "codemirror/addons.min", function() { + + _this.setCodeMirror(); + + if (settings.mode !== "gfm" && settings.mode !== "markdown") + { + _this.loadedDisplay(); + + return false; + } + + _this.setToolbar(); + + editormd.loadScript(loadPath + "marked.min", function() { + + editormd.$marked = marked; + + if (settings.previewCodeHighlight) + { + editormd.loadScript(loadPath + "prettify.min", function() { + loadFlowChartOrSequenceDiagram(); + }); + } + else + { + loadFlowChartOrSequenceDiagram(); + } + }); + + }); + + }); + + }); + + return this; + }, + + /** + * 设置CodeMirror的主题 + * Setting CodeMirror theme + * + * @returns {editormd} 返回editormd的实例对象 + */ + + setTheme : function(theme) { + var settings = this.settings; + settings.theme = theme; + + if (theme !== "default") + { + editormd.loadCSS(settings.path + "codemirror/theme/" + settings.theme); + } + + this.cm.setOption("theme", theme); + + return this; + }, + + /** + * 配置和初始化CodeMirror组件 + * CodeMirror initialization + * + * @returns {editormd} 返回editormd的实例对象 + */ + + setCodeMirror : function() { + var settings = this.settings; + var editor = this.editor; + + if (settings.theme !== "default") + { + editormd.loadCSS(settings.path + "codemirror/theme/" + settings.theme); + } + + var codeMirrorConfig = { + mode : settings.mode, + theme : settings.theme, + tabSize : 4, + dragDrop : false, + autofocus : true, + autoCloseTags : settings.autoCloseTags, + readOnly : (settings.readOnly) ? "nocursor" : false, + indentUnit : 4, + lineNumbers : settings.lineNumbers, + lineWrapping : true, + extraKeys : {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }}, + foldGutter : settings.codeFold, + gutters : ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], + matchBrackets : true, + indentWithTabs : true, + styleActiveLine : settings.styleActiveLine, + styleSelectedText : true, + autoCloseBrackets : true, + showTrailingSpace : true, + highlightSelectionMatches : ( (!settings.matchWordHighlight) ? false : { showToken: (settings.matchWordHighlight == "onselected") ? false : /\w/ } ) + }; + + this.codeEditor = this.cm = editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0], codeMirrorConfig); + this.codeMirror = this.cmElement = editor.children(".CodeMirror"); + + if (settings.value !== "") + { + this.cm.setValue(settings.value); + } + + this.codeMirror.css({ + fontSize : settings.fontSize, + width : (!settings.watch) ? "100%" : "50%" + }); + + return this; + }, + + /** + * 获取CodeMirror的配置选项 + * Get CodeMirror setting options + * + * @returns {Mixed} return CodeMirror setting option value + */ + + getCodeMirrorOption : function(key) { + return this.cm.getOption(key); + }, + + /** + * 配置和重配置CodeMirror的选项 + * CodeMirror setting options / resettings + * + * @returns {editormd} 返回editormd的实例对象 + */ + + setCodeMirrorOption : function(key, value) { + + this.cm.setOption(key, value); + + return this; + }, + + addKeyMap : function(map, bottom) { + this.cm.addKeyMap(map, bottom); + + return this; + }, + + removeKeyMap : function(map) { + this.cm.removeKeyMap(map); + + return this; + }, + + /** + * 扩展当前实例对象,可同时设置多个或者只设置一个 + * Extend editormd instance object, can mutil setting. + * + * @returns {editormd} this(editormd instance object.) + */ + + extends : function() { + if (typeof arguments[1] !== "undefined") + { + if (typeof arguments[1] == "function") + { + arguments[1] = $.proxy(arguments[1], this); + } + + this[arguments[0]] = arguments[1]; + } + + if (typeof arguments[0] === "object" && typeof arguments[0].length === "undefined") + { + $.extend(true, this, arguments[0]); + } + + return this; + }, + + /** + * 设置或扩展当前实例对象,单个设置 + * Extend editormd instance object, one by one + * + * @param {String|Object} key option key + * @param {String|Object} value option value + * @returns {editormd} this(editormd instance object.) + */ + + set : function (key, value) { + + if (typeof value !== "undefined" && typeof value == "function") + { + value = $.proxy(value, this); + } + + this[key] = value; + + return this; + }, + + /** + * 重新配置 + * Resetting editor options + * + * @param {String|Object} key option key + * @param {String|Object} value option value + * @returns {editormd} this(editormd instance object.) + */ + + config : function(key, value) { + var settings = this.settings; + + if (typeof key == "object") + { + settings = $.extend(true, settings, key); + } + + if (typeof key == "string") + { + settings[key] = value; + } + + this.settings = settings; + this.recreate(); + + return this; + }, + + /** + * 注册事件处理方法 + * Bind editor event handle + * + * @param {String} eventType event type + * @param {Function} callback 回调函数 + * @returns {editormd} this(editormd instance object.) + */ + + on : function(eventType, callback) { + var settings = this.settings; + + if (typeof settings["on" + eventType] !== "undefined") + { + settings["on" + eventType] = $.proxy(callback, this); + } + + return this; + }, + + /** + * 解除事件处理方法 + * Unbind editor event handle + * + * @param {String} eventType event type + * @returns {editormd} this(editormd instance object.) + */ + + off : function(eventType) { + var settings = this.settings; + + if (typeof settings["on" + eventType] !== "undefined") + { + settings["on" + eventType] = function(){}; + } + + return this; + }, + + /** + * 显示工具栏 + * Display toolbar + * + * @param {Function} [callback=function(){}] 回调函数 + * @returns {editormd} 返回editormd的实例对象 + */ + + showToolbar : function(callback) { + var settings = this.settings; + + if(settings.readOnly) return ; + + if (settings.toolbar && (this.toolbar.length < 1 || this.toolbar.find("." + this.classPrefix + "menu").html() === "") ) + { + this.setToolbar(); + } + + settings.toolbar = true; + + this.toolbar.show(); + this.resize(); + + $.proxy(callback || function(){}, this)(); + + return this; + }, + + /** + * 隐藏工具栏 + * Hide toolbar + * + * @param {Function} [callback=function(){}] 回调函数 + * @returns {editormd} this(editormd instance object.) + */ + + hideToolbar : function(callback) { + var settings = this.settings; + + settings.toolbar = false; + this.toolbar.hide(); + this.resize(); + + $.proxy(callback || function(){}, this)(); + + return this; + }, + + /** + * 配置和初始化工具栏 + * Set toolbar and Initialization + * + * @returns {editormd} 返回editormd的实例对象 + */ + + setToolbar : function() { + var settings = this.settings; + + if(settings.readOnly) return ; + + var editor = this.editor; + var preview = this.preview; + var classPrefix = this.classPrefix; + + var toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); + + if (settings.toolbar && toolbar.length < 1) + { + editor.append('
        '); + toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); + } + + if (!settings.toolbar) + { + toolbar.hide(); + + return ; + } + //else + //{ + toolbar.show(); + //} + + var icons = (typeof settings.toolbarIcons === "function") ? settings.toolbarIcons() + : ((typeof settings.toolbarIcons === "string") ? editormd.toolbarModes[settings.toolbarIcons] : settings.toolbarIcons); + + var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; + + for (var i = 0, len = icons.length; i < len; i++) + { + var name = icons[i]; + + if (name !== "|") + { + var isHeader = (/h(\d)/.test(name)); + var index = name; + + if (name === "watch" && !settings.watch) { + index = "unwatch"; + } + + var title = settings.lang.toolbar[index]; + var iconTexts = settings.toolbarIconTexts[index]; + var iconClass = settings.toolbarIconsClass[index]; + + title = (typeof title === "undefined") ? "" : title; + iconTexts = (typeof iconTexts === "undefined") ? "" : iconTexts; + iconClass = (typeof iconClass === "undefined") ? "" : iconClass; + + menu += "
      • "; + + if (typeof settings.toolbarCustomIcons[name] !== "undefined") + { + menu += settings.toolbarCustomIcons[name]; + } + else + { + menu += "" + + ""+((isHeader) ? name : ( (iconClass === "") ? iconTexts : "") ) + "" + + ""; + } + + menu += "
      • "; + } + else + { + menu += "
      • |
      • "; + } + } + + toolbarMenu.html(menu); + + this.setToolbarHandler(); + + return this; + }, + + /** + * 工具栏图标事件处理对象序列 + * Get toolbar icons event handlers + * + * @param {Object} cm CodeMirror的实例对象 + * @param {String} name 要获取的事件处理器名称 + * @returns {Object} 返回处理对象序列 + */ + + dialogLockScreen : function() { + $.proxy(editormd.dialogLockScreen, this)(); + + return this; + }, + + dialogShowMask : function(dialog) { + $.proxy(editormd.dialogShowMask, this)(dialog); + + return this; + }, + + getToolbarHandles : function(name) { + var toolbarHandlers = this.toolbarHandlers = editormd.toolbarHandlers; + + return (name && typeof toolbarIconHandlers[name] !== "undefined") ? toolbarHandlers[name] : toolbarHandlers; + }, + + /** + * 工具栏图标事件处理器 + * Bind toolbar icons event handle + * + * @returns {editormd} 返回editormd的实例对象 + */ + + setToolbarHandler : function() { + var _this = this; + var settings = this.settings; + + if (!settings.toolbar || settings.readOnly) { + return ; + } + + var editor = this.editor; + var preview = this.preview; + var toolbar = this.toolbar; + var codeEditor = this.codeEditor; + var codeMirror = this.codeMirror; + var classPrefix = this.classPrefix; + var previewContainer = this.previewContainer; + var toolbarIcons = this.toolbarIcons = toolbar.find("." + classPrefix + "menu a"); + var toolbarIconHandlers = this.getToolbarHandles(); + + toolbarIcons.bind(editormd.mouseOrTouch("click", "touchend"), function(event) { + + var icon = $(this).children(".fa"); + var name = icon.attr("name"); + var cursor = codeEditor.getCursor(); + var selection = codeEditor.getSelection(); + + if (name === "") { + return ; + } + + _this.activeIcon = icon; + + if (typeof toolbarIconHandlers[name] !== "undefined") + { + $.proxy(toolbarIconHandlers[name], _this)(codeEditor); + } + else + { + if (typeof settings.toolbarHandlers[name] !== "undefined") + { + $.proxy(settings.toolbarHandlers[name], _this)(codeEditor, icon, cursor, selection); + } + } + + if (name !== "link" && name !== "anchor" && name !== "image" && name !== "code-block" && + name !== "preformatted-text" && name !== "watch" && name !== "preview" && name !== "fullscreen" && name !== "info") + { + codeEditor.focus(); + } + + return false; + + }); + + return this; + }, + + /** + * 动态创建对话框 + * Creating custom dialogs + * + * @param {Object} options 配置项键值对 Key/Value + * @returns {dialog} 返回创建的dialog的jQuery实例对象 + */ + + createDialog : function(options) { + return $.proxy(editormd.createDialog, this)(options); + }, + + /** + * 创建关于Editor.md的对话框 + * Create about Editor.md dialog + * + * @returns {editormd} 返回editormd的实例对象 + */ + + createInfoDialog : function() { + var _this = this; + var editor = this.editor; + var classPrefix = this.classPrefix; + + var infoDialogHTML = [ + "
        ", + "
        ", + "

        " + editormd.title + "v" + editormd.version + "

        ", + "

        " + this.lang.description + "

        ", + "

        Home page: " + editormd.homePage + "

        ", + "

        License: MIT

        ", + "
        ", + "", + "
        " + ].join("\n"); + + editor.append(infoDialogHTML); + + var infoDialog = this.infoDialog = editor.children("." + classPrefix + "dialog-info"); + + infoDialog.find("." + classPrefix + "dialog-close").bind(editormd.mouseOrTouch("click", "touchend"), function() { + _this.hideInfoDialog(); + }); + + infoDialog.css("border", (editormd.isIE8) ? "1px solid #ddd" : "").css("z-index", editormd.dialogZindex).show(); + + this.infoDialogPosition(); + + return this; + }, + + /** + * 关于Editor.md对话居中定位 + * Editor.md dialog position handle + * + * @returns {editormd} 返回editormd的实例对象 + */ + + infoDialogPosition : function() { + var infoDialog = this.infoDialog; + + var _infoDialogPosition = function() { + infoDialog.css({ + top : ($(window).height() - infoDialog.height()) / 2 + "px", + left : ($(window).width() - infoDialog.width()) / 2 + "px" + }); + }; + + _infoDialogPosition(); + + $(window).resize(_infoDialogPosition); + + return this; + }, + + /** + * 显示关于Editor.md + * Display about Editor.md dialog + * + * @returns {editormd} 返回editormd的实例对象 + */ + + showInfoDialog : function() { + + $("html,body").css("overflow-x", "hidden"); + + var _this = this; + var editor = this.editor; + var settings = this.settings; + var classPrefix = this.classPrefix; + var infoDialog = this.infoDialog = editor.children("." + classPrefix + "dialog-info"); + + if (infoDialog.length < 1) + { + this.createInfoDialog(); + } + + this.lockScreen(true); + + this.mask.css({ + opacity : settings.dialogMaskOpacity, + backgroundColor : settings.dialogMaskBgColor + }).show(); + + infoDialog.css("z-index", editormd.dialogZindex).show(); + + this.infoDialogPosition(); + + return this; + }, + + /** + * 隐藏关于Editor.md + * Hide about Editor.md dialog + * + * @returns {editormd} 返回editormd的实例对象 + */ + + hideInfoDialog : function() { + $("html,body").css("overflow-x", ""); + this.infoDialog.hide(); + this.mask.hide(); + this.lockScreen(false); + + return this; + }, + + /** + * 锁屏 + * lock screen + * + * @param {Boolean} lock Boolean 布尔值,是否锁屏 + * @returns {editormd} 返回editormd的实例对象 + */ + + lockScreen : function(lock) { + editormd.lockScreen(lock); + + return this; + }, + + /** + * 编辑器界面重建,用于动态语言包或模块加载等 + * Recreate editor + * + * @returns {editormd} 返回editormd的实例对象 + */ + + recreate : function() { + var _this = this; + var editor = this.editor; + var settings = this.settings; + var toolbarIcons = settings.toolbarIcons(); + + this.codeMirror.remove(); + + this.setCodeMirror(); + + if (typeof this.infoDialog !== "undefined") { + this.infoDialog.remove(); + } + + if (typeof toolbarIcons["info"] !== "undefined") { + createInfoDialog(); + } + + if (!settings.readOnly) + { + if (editor.find(".editormd-dialog").length > 0) { + editor.find(".editormd-dialog").remove(); + } + + if (settings.toolbar) + { + this.getToolbarHandles(); + this.setToolbar(); + } + } + + this.saveToTextareas(); + this.resize(); + + return this; + }, + + /** + * 高亮预览HTML的pre代码部分 + * highlight of preview codes + * + * @returns {editormd} 返回editormd的实例对象 + */ + + previewCodeHighlight : function() { + var settings = this.settings; + var previewContainer = this.previewContainer; + + if (settings.previewCodeHighlight) + { + previewContainer.find("pre").addClass("prettyprint linenums"); + + if (typeof prettyPrint !== "undefined") + { + prettyPrint(); + } + } + + return this; + }, + + /** + * 解析TeX(KaTeX)科学公式 + * TeX(KaTeX) Renderer + * + * @returns {editormd} 返回editormd的实例对象 + */ + + katexRender : function() { + + var previewContainer = this.previewContainer; + + previewContainer.find("." + editormd.classNames.tex).each(function(){ + var tex = $(this); + editormd.$katex.render(tex.html(), tex[0]); + }); + + return this; + }, + + /** + * 解析和渲染流程图及时序图 + * FlowChart and SequenceDiagram Renderer + * + * @returns {editormd} 返回editormd的实例对象 + */ + + flowChartAndSequenceDiagramRender : function() { + + var settings = this.settings; + var previewContainer = this.previewContainer; + + if (editormd.isIE8) return ; + + if (settings.flowChart) { + previewContainer.find(".flowchart").flowChart(); + } + + if (settings.sequenceDiagram) { + previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); + } + + return this; + }, + + /** + * 加载队列完成之后的显示处理 + * Display handle of the module queues loaded after. + * + * @returns {editormd} 返回editormd的实例对象 + */ + + loadedDisplay : function() { + + var _this = this; + var editor = this.editor; + var preview = this.preview; + var settings = this.settings; + var codeEditor = this.codeEditor; + var codeMirror = this.codeMirror; + var previewContainer = this.previewContainer; + var mouseOrTouch = editormd.mouseOrTouch; + + editor.children("." + this.classPrefix + "container-mask").hide(); + + this.saveToTextareas(); + + if(settings.watch) { + preview.show(); + } + + editor.data("oldWidth", editor.width()).data("oldHeight", editor.height()); // 为了兼容Zepto + + this.resize(); + + $(window).resize(function(){ + _this.resize(); + }); + + var codeEditorBindScroll = function() { + codeMirror.find(".CodeMirror-scroll").bind(mouseOrTouch("scroll", "touchmove"), function(event) { + var height = $(this).height(); + var scrollTop = $(this).scrollTop(); + var percent = (scrollTop / $(this)[0].scrollHeight); + + if (scrollTop === 0) + { + preview.scrollTop(0); + } + else if (scrollTop + height >= $(this)[0].scrollHeight) + { + preview.scrollTop(preview[0].scrollHeight); + } + else + { + preview.scrollTop(preview[0].scrollHeight * percent); + } + + $.proxy(settings.onscroll, this)(event); + }); + }; + + var codeEditorUnbindScroll = function() { + codeMirror.find(".CodeMirror-scroll").unbind(mouseOrTouch("scroll", "touchmove")); + }; + + var previewBindScroll = function() { + preview.bind(mouseOrTouch("scroll", "touchmove"), function() { + var height = $(this).height(); + var scrollTop = $(this).scrollTop(); + var percent = (scrollTop / $(this)[0].scrollHeight); + var codeView = codeMirror.find(".CodeMirror-scroll"); + + if(scrollTop === 0) + { + codeView.scrollTop(0); + } + else if (scrollTop + height >= $(this)[0].scrollHeight) + { + codeView.scrollTop(codeView[0].scrollHeight); + } + else + { + codeView.scrollTop(codeView[0].scrollHeight * percent); + } + + $.proxy(settings.onpreviewscroll, this)(event); + }); + }; + + var previewUnbindScroll = function() { + preview.unbind(mouseOrTouch("scroll", "touchmove")); + }; + + codeMirror.bind({ + mouseover : codeEditorBindScroll, + mouseout : codeEditorUnbindScroll, + touchstart : codeEditorBindScroll, + touchend : codeEditorUnbindScroll + }); + + preview.bind({ + mouseover : previewBindScroll, + mouseout : previewUnbindScroll, + touchstart : previewBindScroll, + touchend : previewUnbindScroll + }); + + codeEditor.on("change", function(cm, changeObj) { + _this.saveToTextareas(); + }); + + $.proxy(settings.onload, this)(); + + this.state.loaded = true; + + return this; + }, + + /** + * 设置编辑器的宽度 + * Set editor width + * + * @param {Number|String} width 编辑器宽度值 + * @returns {editormd} 返回editormd的实例对象 + */ + + width : function(width) { + + this.editor.css("width", (typeof width === "number") ? width + "px" : width); + this.resize(); + + return this; + }, + + /** + * 设置编辑器的高度 + * Set editor height + * + * @param {Number|String} height 编辑器高度值 + * @returns {editormd} 返回editormd的实例对象 + */ + + height : function(height) { + + this.editor.css("height", (typeof height === "number") ? height + "px" : height); + this.resize(); + + return this; + }, + + /** + * 调整编辑器的尺寸和布局 + * Resize editor layout + * + * @param {Number|String} [width=null] 编辑器宽度值 + * @param {Number|String} [height=null] 编辑器高度值 + * @returns {editormd} 返回editormd的实例对象 + */ + + resize : function(width, height) { + + width = width || null; + height = height || null; + + var editor = this.editor; + var preview = this.preview; + var toolbar = this.toolbar; + var settings = this.settings; + var codeEditor = this.codeEditor; + var codeMirror = this.codeMirror; + + if(width && height) + { + editor.css({ + width : (typeof width === "number") ? width + "px" : width, + height : (typeof height === "number") ? height + "px" : height + }); + } + + if (settings.toolbar && !settings.readOnly) { + codeMirror.css("margin-top", toolbar.height() + 1).height(editor.height() - toolbar.height()); + } else { + codeMirror.css("margin-top", 0).height(editor.height()); + } + + codeMirror.find(".CodeMirror-gutters").height(codeMirror.height()); + + if(settings.watch) + { + codeMirror.width(editor.width() / 2); + preview.width((!this.state.preview) ? editor.width() / 2 : editor.width()); + + if (settings.toolbar && !settings.readOnly) { + preview.css("top", toolbar.height()).height(editor.height() - toolbar.height()); + } else { + preview.css("top", 0).height(editor.height()); + } + } + else + { + codeMirror.width(editor.width()); + preview.hide(); + } + + if (this.state.loaded) + { + $.proxy(settings.onresize, this)(); + } + + return this; + }, + + /** + * 分别将Markdown源码和解析的HTML源码保存到对应的textarea + * Saving Markdown and HTML source code to Textarea + * + * @returns {editormd} 返回editormd的实例对象 + */ + + saveToTextareas : function() { + var _this = this; + var state = this.state; + var settings = this.settings; + var codeEditor = this.codeEditor; + var previewContainer = this.previewContainer; + + var codeMirrorValue = codeEditor.getValue(); + + if (settings.mode !== "gfm" && settings.mode !== "markdown") + { + this.markdownTextarea[0].innerText = codeMirrorValue; + + return this; + } + + var marked = editormd.$marked; + var markdownToC = this.markdownToC = []; + var rendererOptions = this.markedRendererOptions = { + toc : settings.toc, + tocStartLevel : settings.tocStartLevel, + taskList : settings.taskList, + emoji : settings.emoji, + tex : settings.tex, + flowChart : settings.flowChart, + sequenceDiagram : settings.sequenceDiagram, + previewCodeHighlight : settings.previewCodeHighlight, + }; + + var markedOptions = this.markedOptions = { + renderer : editormd.markedRenderer(markdownToC, rendererOptions), + gfm : true, + tables : true, + breaks : true, + pedantic : false, + sanitize : (settings.htmlDecode) ? false : true, // 关闭忽略HTML标签,即开启识别HTML标签,默认为false + smartLists : true, + smartypants : true + }; + + marked.setOptions(markedOptions); + + codeMirrorValue = editormd.filterHTMLTags(codeMirrorValue, settings.htmlDecode); + + var newMarkdownDoc = editormd.$marked(codeMirrorValue, markedOptions); + + this.markdownTextarea[0].innerText = codeMirrorValue; + + codeEditor.save(); + + if (settings.saveHTMLToTextarea) + { + this.htmlTextarea.html(newMarkdownDoc); + } + + if(settings.watch || (!settings.watch && state.preview)) + { + previewContainer.html(newMarkdownDoc); + + this.previewCodeHighlight(); + + if (settings.toc) { + editormd.markdownToCRenderer(markdownToC, previewContainer, settings.tocStartLevel); + } + + if (settings.tex) + { + if (!settings.inRequirejs && !editormd.kaTeXLoaded) { + editormd.loadKaTeX(function(){ + editormd.$katex = katex; + editormd.kaTeXLoaded = true; + _this.katexRender(); + }); + } else { + this.katexRender(); + } + } + + if (settings.flowChart || settings.sequenceDiagram) + { + var timer = setTimeout(function(){ + clearTimeout(timer); + _this.flowChartAndSequenceDiagramRender(); + }, 10); + } + + if (state.loaded) + { + $.proxy(settings.onchange, this)(); + } + } + + return this; + }, + + /** + * 聚焦光标位置 + * Focusing the cursor position + * + * @returns {editormd} 返回editormd的实例对象 + */ + + focus : function() { + this.codeEditor.focus(); + + return this; + }, + + /** + * 设置光标的位置 + * Set cursor position + * + * @param {Object} cursor 要设置的光标位置键值对象,例:{line:1, ch:0} + * @returns {editormd} 返回editormd的实例对象 + */ + + setCursor : function(cursor) { + this.codeEditor.setCursor(cursor); + + return this; + }, + + /** + * 获取当前光标的位置 + * Get the current position of the cursor + * + * @returns {Cursor} 返回一个光标Cursor对象 + */ + + getCursor : function() { + return this.codeEditor.getCursor(); + }, + + /** + * 设置光标选中的范围 + * Set cursor selected ranges + * + * @param {Object} from 开始位置的光标键值对象,例:{line:1, ch:0} + * @param {Object} to 结束位置的光标键值对象,例:{line:1, ch:0} + * @returns {editormd} 返回editormd的实例对象 + */ + + setSelection : function(from, to) { + + this.codeEditor.setSelection(from, to); + + return this; + }, + + /** + * 获取光标选中的文本 + * Get the texts from cursor selected + * + * @returns {String} 返回选中文本的字符串形式 + */ + + getSelection : function() { + return this.codeEditor.getSelection(); + }, + + /** + * 替换当前光标选中的文本或在当前光标处插入新字符 + * Replace the text at the current cursor selected or insert a new character at the current cursor position + * + * @param {String} value 要插入的字符值 + * @returns {editormd} 返回editormd的实例对象 + */ + + replaceSelection : function(value) { + this.codeEditor.replaceSelection(value); + + return this; + }, + + /** + * 在当前光标处插入新字符 + * Insert a new character at the current cursor position + * + * 同replaceSelection()方法 + * With the replaceSelection() method + * + * @param {String} value 要插入的字符值 + * @returns {editormd} 返回editormd的实例对象 + */ + + insertValue : function(value) { + this.replaceSelection(value); + + return this; + }, + + /** + * 设置和传入编辑器的markdown源文档 + * Set Markdown source document + * + * @param {String} md 要传入的markdown源文档 + * @returns {editormd} 返回editormd的实例对象 + */ + + setMarkdown : function(md) { + var settings = this.settings; + + this.codeEditor.setValue(md || settings.markdown); + + return this; + }, + + /** + * 获取编辑器的markdown源文档 + * Set Editor.md markdown/CodeMirror value + * + * @returns {editormd} 返回editormd的实例对象 + */ + + getMarkdown : function() { + return this.codeEditor.getValue(); + }, + + /** + * 获取编辑器的源文档 + * Get CodeMirror value + * + * @returns {editormd} 返回editormd的实例对象 + */ + + getValue : function() { + return this.codeEditor.getValue(); + }, + + /** + * 设置编辑器的源文档 + * Set CodeMirror value + * + * @param {String} value set code/value/string/text + * @returns {editormd} 返回editormd的实例对象 + */ + + setValue : function(value) { + this.codeEditor.setValue(value); + + return this; + }, + + /** + * 清空编辑器 + * Empty CodeMirror editor container + * + * @returns {editormd} 返回editormd的实例对象 + */ + + clear : function() { + this.codeEditor.setValue(""); + + return this; + }, + + /** + * 获取解析后存放在Textarea的HTML源码 + * Get parsed html code from Textarea + * + * @returns {String} 返回HTML源码 + */ + + getHTML : function() { + if (!this.settings.saveHTMLToTextarea) + { + alert("Error: settings.saveHTMLToTextarea == false"); + + return false; + } + + return this.htmlTextarea.html(); + }, + + /** + * getHTML()的别名 + * getHTML (alias) + * + * @returns {String} Return html code 返回HTML源码 + */ + + getTextareaSavedHTML : function() { + return this.getHTML(); + }, + + /** + * 获取预览窗口的HTML源码 + * Get html from preview container + * + * @returns {editormd} 返回editormd的实例对象 + */ + + getPreviewedHTML : function() { + if (!this.settings.watch) + { + alert("Error: settings.watch == false"); + + return false; + } + + return this.previewContainer.html(); + }, + + /** + * 开启实时预览 + * Enable real-time watching + * + * @returns {editormd} 返回editormd的实例对象 + */ + + watch : function(callback) { + var settings = this.settings; + this.state.watching = settings.watch = true; + this.preview.show(); + + var watchIcon = settings.toolbarIconsClass.watch; + var unWatchIcon = settings.toolbarIconsClass.unwatch; + var icon = this.toolbar.find(".fa[name=watch]"); + icon.parent().attr("title", settings.lang.toolbar.watch); + icon.removeClass(unWatchIcon).addClass(watchIcon); + + this.codeMirror.css("border-right", "1px solid #ddd").width(this.editor.width() / 2); + + this.saveToTextareas().resize(); + + if (!settings.onwatch) + { + settings.onwatch = callback || function() {}; + } + + $.proxy(settings.onwatch, this)(); + + return this; + }, + + /** + * 关闭实时预览 + * Disable real-time watching + * + * @returns {editormd} 返回editormd的实例对象 + */ + + unwatch : function(callback) { + var settings = this.settings; + this.state.watching = settings.watch = false; + this.preview.hide(); + + var watchIcon = settings.toolbarIconsClass.watch; + var unWatchIcon = settings.toolbarIconsClass.unwatch; + + if (this.toolbar) + { + var icon = this.toolbar.find(".fa[name=watch]"); + icon.parent().attr("title", settings.lang.toolbar.unwatch); + icon.removeClass(watchIcon).addClass(unWatchIcon); + } + + this.codeMirror.css("border-right", "none").width(this.editor.width()); + + this.resize(); + + if (!settings.onunwatch) + { + settings.onunwatch = callback || function() {}; + } + + $.proxy(settings.onunwatch, this)(); + + return this; + }, + + /** + * 显示编辑器 + * Show editor + * + * @param {Function} [callback=function()] 回调函数 + * @returns {editormd} 返回editormd的实例对象 + */ + + show : function(callback) { + callback = callback || function() {}; + + var _this = this; + this.editor.show(function(){ + $.proxy(callback, _this)(); + }); + + return this; + }, + + /** + * 隐藏编辑器 + * Hide editor + * + * @param {Function} [callback=function()] 回调函数 + * @returns {editormd} 返回editormd的实例对象 + */ + + hide : function(callback) { + callback = callback || function() {}; + + var _this = this; + this.editor.hide(function(){ + $.proxy(callback, _this)(); + }); + + return this; + }, + + /** + * 隐藏编辑器部分,只预览HTML + * Enter preview html state + * + * @returns {editormd} 返回editormd的实例对象 + */ + + previewing : function() { + + var _this = this; + var editor = this.editor; + var preview = this.preview; + var toolbar = this.toolbar; + var settings = this.settings; + var codeMirror = this.codeMirror; + + if (settings.toolbar) { + toolbar.toggle(); + toolbar.find(".fa[name=preview]").toggleClass("active"); + } + + codeMirror.toggle(); + + if(codeMirror.css("display") === "none") // 为了兼容Zepto,而不使用codeMirror.is(":hidden") + { + this.state.preview = true; + + if(this.state.fullscreen) { + preview.css("background", "#fff"); + } + + editor.find("." + this.classPrefix + "preview-close-btn").show().bind(editormd.mouseOrTouch("click", "touchend"), function(){ + _this.previewed(); + }); + + if(!settings.watch) + { + this.saveToTextareas(); + } + + preview.show().css({ + position : "static", + top : 0, + width : editor.width(), + height : editor.height() + }); + + if (this.state.loaded) + { + $.proxy(settings.onpreviewing, this)(); + } + } + else + { + this.previewed(); + } + + $(window).keyup(function(event) { + if (event.keyCode === 27) { + _this.previewed(); + } + }); + }, + + /** + * 显示编辑器部分,退出只预览HTML + * Exit preview html state + * + * @returns {editormd} 返回editormd的实例对象 + */ + + previewed : function() { + + var editor = this.editor; + var preview = this.preview; + var toolbar = this.toolbar; + var settings = this.settings; + var codeMirror = this.codeMirror; + var previewCloseBtn = editor.find("." + this.classPrefix + "preview-close-btn"); + + this.state.preview = false; + + codeMirror.show(); + + if (settings.toolbar) { + toolbar.show(); + } + + if(this.settings.watch) { + preview.show(); + } else { + preview.hide(); + } + + previewCloseBtn.hide().bind(editormd.mouseOrTouch("click", "touchend")); + + preview.css({ + background : null, + position : "absolute", + width : editor.width() / 2, + height : editor.height() - toolbar.height(), + top : (settings.toolbar) ? toolbar.height() : 0 + }); + + if (this.state.loaded) + { + $.proxy(settings.onpreviewed, this)(); + } + + return this; + }, + + /** + * 编辑器全屏显示 + * Fullscreen show + * + * @returns {editormd} 返回editormd的实例对象 + */ + + fullscreen : function() { + + var _this = this; + var editor = this.editor; + var preview = this.preview; + var toolbar = this.toolbar; + var fullscreenClass = this.classPrefix + "fullscreen"; + + if (toolbar) { + toolbar.find(".fa[name=fullscreen]").parent().toggleClass("active"); + } + + if (!editor.hasClass(fullscreenClass)) + { + this.state.fullscreen = true; + + $("html,body").css("overflow", "hidden"); + + editor.css({ + position : "fixed", + top : 0, + left : 0, + margin : 0, + border : "none", + width : $(window).width(), + height : $(window).height() + }).addClass(fullscreenClass); + + this.resize(); + + $.proxy(this.settings.onfullscreen, this)(); + } + else + { + this.fullscreenExit(); + } + + $(window).keyup(function(event) { + if (_this.state.preview) { + return ; + } + + if (event.keyCode === 27) { + _this.fullscreenExit(); + } + }); + + return this; + }, + + /** + * 编辑器退出全屏显示 + * Exit fullscreen state + * + * @returns {editormd} 返回editormd的实例对象 + */ + + fullscreenExit : function() { + + var editor = this.editor; + var toolbar = this.toolbar; + var fullscreenClass = this.classPrefix + "fullscreen"; + this.state.fullscreen = false; + + if (toolbar) { + toolbar.find(".fa[name=fullscreen]").parent().removeClass("active"); + } + + $("html,body").css("overflow", ""); + + editor.css({ + position : "", + top : "", + left : "", + margin : "0 auto", + width : editor.data("oldWidth"), + height : editor.data("oldHeight"), + border : "1px solid #ddd" + }).removeClass(fullscreenClass); + + this.resize(); + + + $.proxy(this.settings.onfullscreenExit, this)(); + + return this; + }, + + executePlugin : function(name, path) { + + var _this = this; + var cm = this.cm; + + if (typeof define == "function") { + + this[name](cm); + + return ; + } + + path = this.settings.path + "../plugins/" + path; + + if ($.inArray(path, editormd.loadFiles.plugin) < 0) + { + editormd.loadPlugin(path, function() { + editormd.loadPlugins[name] = _this[name]; + _this[name](cm); + }); + } + else + { + $.proxy(editormd.loadPlugins[name], this)(cm); + } + } + }; + + editormd.fn.init.prototype = editormd.fn; + + editormd.dialogLockScreen = function() { + var settings = this.settings; + + if (settings.dialogLockScreen) + { + $("html,body").css("overflow", "hidden"); + } + }; + + editormd.dialogShowMask = function(dialog) { + var editor = this.editor; + var settings = this.settings; + + dialog.css({ + top : ($(window).height() - dialog.height()) / 2 + "px", + left : ($(window).width() - dialog.width()) / 2 + "px" + }); + + if (settings.dialogShowMask) { + editor.children("." + this.classPrefix + "mask").css("z-index", parseInt(dialog.css("z-index")) - 1).show(); + } + }; + + editormd.toolbarHandlers = { + undo : function() { + this.cm.undo(); + }, + + redo : function() { + this.cm.redo(); + }, + + bold : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("**" + selection + "**"); + + if(selection === "") { + cm.setCursor(cursor.line, cursor.ch + 2); + } + }, + + del : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("~~" + selection + "~~"); + + if(selection === "") { + cm.setCursor(cursor.line, cursor.ch + 2); + } + }, + + italic : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("*" + selection + "*"); + + if(selection === "") { + cm.setCursor(cursor.line, cursor.ch + 1); + } + }, + + quote : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("> " + selection); + cm.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); + }, + + h1 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("# " + selection); + }, + + h2 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("## " + selection); + }, + + h3 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("### " + selection); + }, + + h4 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("#### " + selection); + }, + + h5 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("##### " + selection); + }, + + h6 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("###### " + selection); + }, + + "list-ul" : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + if (selection === "") + { + cm.replaceSelection("- " + selection); + } + else + { + var selectionText = selection.split("\n"); + + for (var i = 0, len = selectionText.length; i < len; i++) + { + selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; + } + + cm.replaceSelection(selectionText.join("\n")); + } + }, + + "list-ol" : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + if(selection === "") + { + cm.replaceSelection("1. " + selection); + } + else + { + var selectionText = selection.split("\n"); + + for (var i = 0, len = selectionText.length; i < len; i++) + { + selectionText[i] = (selectionText[i] === "") ? "" : (i+1) + ". " + selectionText[i]; + } + + cm.replaceSelection(selectionText.join("\n")); + } + }, + + hr : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("------------"); + }, + + link : function() { + this.executePlugin("linkDialog", "link-dialog/link-dialog"); + }, + + anchor : function() { + this.executePlugin("anchorLinkDialog", "anchor-link-dialog/anchor-link-dialog"); + }, + + image : function() { + this.executePlugin("imageDialog", "image-dialog/image-dialog"); + }, + + code : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("`" + selection + "`"); + + if (selection === "") { + cm.setCursor(cursor.line, cursor.ch + 1); + } + }, + + "code-block" : function() { + this.executePlugin("codeBlockDialog", "code-block-dialog/code-block-dialog"); + }, + + "preformatted-text" : function() { + this.executePlugin("preformattedTextDialog", "preformatted-text-dialog/preformatted-text-dialog"); + }, + + table : function() { + this.executePlugin("tableDialog", "table-dialog/table-dialog"); + }, + + datetime : function() { + var cm = this.cm; + var selection = cm.getSelection(); + var date = new Date(); + var langName = this.settings.lang.name; + var datefmt = editormd.dateFormat() + " " + editormd.dateFormat((langName === "zh-cn" || langName === "zh-tw") ? "cn-week-day" : "week-day"); + + cm.replaceSelection(datefmt); + }, + + emoji : function() { + this.executePlugin("emojiDialog", "emoji-dialog/emoji-dialog"); + }, + + htmlEntities : function() { + this.executePlugin("htmlEntitiesDialog", "html-entities-dialog/html-entities-dialog"); + }, + + watch : function() { + this[this.settings.watch ? "unwatch" : "watch"](); + }, + + preview : function() { + this.previewing(); + }, + + fullscreen : function() { + this.fullscreen(); + }, + + clear : function() { + this.clear(); + }, + + help : function() { + this.executePlugin("helpDialog", "help-dialog/help-dialog"); + }, + + info : function() { + this.showInfoDialog(); + } + }; + + /** + * 清除字符串两边的空格 + * Clear the space of strings both sides. + * + * @param {String} str string + * @returns {String} trimed string + */ + + editormd.trim = function(str) { + return (!String.prototype.trim) ? str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '') : str.trim(); + }; + + var trim = editormd.trim; + + editormd.urls = { + atLinkBase : "https://github.com/" + }; + + editormd.regex = { + atLink : /@(\w+)/g, + emoji : /:([\-\w]+):/g, + twemoji : /:(tw-([\w]+)-?(\w+)?):/g, + fontAwesome : /:(fa-([\w]+)-?(\w+)?):/g, + editormdLogo : /:(editormd-logo-?(\w+)?):/g + }; + + // Emoji graphics files url path + editormd.emoji = { + path : "http://www.emoji-cheat-sheet.com/graphics/emojis/", + ext : ".png" + }; + + // Twitter Emoji (Twemoji) graphics files url path + editormd.twemoji = { + path : "http://twemoji.maxcdn.com/36x36/", + ext : ".png" + }; + + /** + * 自定义marked的解析器 + * Custom Marked renderer rules + * + * @param {Array} markdownToC 传入用于接收TOC的数组 + * @returns {Renderer} markedRenderer 返回marked的Renderer自定义对象 + */ + + editormd.markedRenderer = function(markdownToC, options) { + var defaults = { + toc : true, // Table of contents + tocStartLevel : 1, // Said from H1 to create ToC + taskList : false, // Enable Github Flavored Markdown task lists + emoji : false, // :emoji: , Support Twemoji, fontAwesome, Editor.md logo emojis. + tex : false, // TeX(LaTeX), based on KaTeX + flowChart : false, // flowChart.js only support IE9+ + sequenceDiagram : false, // sequenceDiagram.js only support IE9+ + }; + + var atLinkReg = editormd.regex.atLink; + + var settings = $.extend(defaults, options || {}); + var marked = editormd.$marked; + var markedRenderer = new marked.Renderer(); + markdownToC = markdownToC || []; + + var emojiReg = editormd.regex.emoji; + var twemojiReg = editormd.regex.twemoji; + var faIconReg = editormd.regex.fontAwesome; + var editormdLogoReg = editormd.regex.editormdLogo; + + markedRenderer.emoji = function(text) { + var matchs = text.match(emojiReg); + + if (!matchs || !settings.emoji) { + return text; + } + + for (var i = 0, len = matchs.length; i < len; i++) + { + text = text.replace(new RegExp(matchs[i]), function($1, $2){ + var faMatchs = $1.match(faIconReg); + var name = $1.replace(/:/g, ""); + + if (faMatchs) + { + for (var fa = 0, len1 = faMatchs.length; fa < len1; fa++) + { + var faName = faMatchs[fa].replace(/:/g, ""); + + return ""; + } + } + else + { + var emdlogoMathcs = $1.match(editormdLogoReg); + var twemojiMatchs = $1.match(twemojiReg); + + if (emdlogoMathcs) + { + for (var x = 0, len2 = emdlogoMathcs.length; x < len2; x++) + { + var logoName = emdlogoMathcs[x].replace(/:/g, ""); + return ""; + } + } + else if (twemojiMatchs) + { + for (var t = 0, len3 = twemojiMatchs.length; t < len3; t++) + { + var twe = twemojiMatchs[t].replace(/:/g, "").replace("tw-", ""); + return "\"twemoji-""; + } + } + else + { + return "\":""; + } + } + }); + } + + return text; + }; + + markedRenderer.atLink = function(text) { + + if (atLinkReg.test(text)) + { + text = text.replace(atLinkReg, function($1, $2) { + return "" + $1 + ""; + }); + } + + return text; + }; + + markedRenderer.link = function (href, title, text) { + + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase(); + } catch(e) { + return ""; + } + + if (prot.indexOf("javascript:") === 0) { + return ""; + } + } + + var out = "" + text.replace(/@/g, "@") + ""; + } + + if (title) { + out += " title=\"" + title + "\""; + } + + out += ">" + text + ""; + + return out; + } + + markedRenderer.heading = function(text, level, raw) { + + var linkText = text; + var hasLinkReg = /\s*\]*)\>(.*)\<\/a\>\s*/; + var getLinkTextReg = /\s*\]+)\>([^\>]*)\<\/a\>\s*/g; + + if (hasLinkReg.test(text)) + { + var tempText = []; + text = text.split(/\]+)\>([^\>]*)\<\/a\>/); + + for (var i = 0, len = text.length; i < len; i++) + { + tempText.push(text[i].replace(/\s*href\=\"(.*)\"\s*/g, "")); + } + + text = tempText.join(" "); + } + + text = trim(text); + + var escapedText = text.toLowerCase().replace(/[^\w]+/g, "-"); + var toc = { + text : text, + level : level, + slug : escapedText + }; + + var isChinese = /^[\u4e00-\u9fa5]+$/.test(text); + var id = (isChinese) ? escape(text).replace(/\%/g, "") : text.toLowerCase().replace(/[^\w]+/g, "-"); + + markdownToC.push(toc); + + var headingHTML = ""; + + headingHTML += ""; + headingHTML += ""; + headingHTML += (hasLinkReg) ? this.atLink(this.emoji(linkText)) : this.atLink(this.emoji(text)); + headingHTML += ""; + + return headingHTML; + }; + + markedRenderer.paragraph = function(text) { + var isTeXInline = /\$\$(.*)\$\$/g.test(text); + var isTeXLine = /^\$\$(.*)\$\$$/.test(text); + var isTeXAddClass = (isTeXLine) ? " class=\"" + editormd.classNames.tex + "\"" : ""; + var isToC = /^\[TOC\]$/.test(text); + + if (!isTeXLine && isTeXInline) + { + text = text.replace(/(\$\$([^\$]*)\$\$)+/g, function($1, $2) { + return "" + $2.replace(/\$/g, "") + ""; + }); + } + else + { + text = (isTeXLine) ? text.replace(/\$/g, "") : text; + } + + return (isToC) ? "
          " + text + "
        " + : "" + this.atLink(this.emoji(text)) + "

        \n"; + }; + + markedRenderer.code = function (code, lang, escaped) { + + if (lang === "seq" || lang === "sequence") + { + return "
        " + code + "
        "; + } + else if ( lang === "flow") + { + return "
        " + code + "
        "; + } + else + { + + return marked.Renderer.prototype.code.apply(this, arguments); + } + }; + + markedRenderer.tablecell = function(content, flags) { + var type = (flags.header) ? "th" : "td"; + var tag = (flags.align) ? "<" + type +" style=\"text-align:" + flags.align + "\">" : "<" + type + ">"; + + return tag + this.atLink(this.emoji(content)) + "\n"; + }; + + markedRenderer.listitem = function(text) { + if (settings.taskList && /^\s*\[[x\s]\]\s*/.test(text)) + { + text = text.replace(/^\s*\[\s\]\s*/, " ") + .replace(/^\s*\[x\]\s*/, " "); + + return "
      • " + this.atLink(this.emoji(text)) + "
      • "; + } + else + { + return "
      • " + this.atLink(this.emoji(text)) + "
      • "; + } + }; + + return markedRenderer; + }; + + /** + * + * 生成TOC(Table of Contents) + * Creating ToC (Table of Contents) + * + * @param {Array} toc 从marked获取的TOC数组列表 + * @param {Element} container 插入TOC的容器元素 + * @param {Integer} startLevel Hx 起始层级 + * @returns {Object} tocContainer 返回ToC列表容器层的jQuery对象元素 + */ + + editormd.markdownToCRenderer = function(toc, container, startLevel) { + + var html = ""; + var lastLevel = 0; + startLevel = startLevel || 1; + + for (var i = 0, len = toc.length; i < len; i++) + { + var text = toc[i].text; + var level = toc[i].level; + + if (level < startLevel) { + continue; + } + + if (level > lastLevel) + { + html += ""; + } + else if (level < lastLevel) + { + html += (new Array(lastLevel - level + 2)).join("
    • "); + } + else + { + html += ""; + } + + html += "
    • " + text + "
        "; + lastLevel = level; + } + + var tocContainer = container.find('.markdown-toc'); + + tocContainer.children('.markdown-toc-list').html("").html(html); + + return tocContainer; + }; + + /** + * 简单地过滤指定的HTML标签 + * Filter custom html tags + * + * @param {String} html 要过滤HTML + * @param {String} filters 要过滤的标签 + * @returns {String} html 返回过滤的HTML + */ + + editormd.filterHTMLTags = function(html, filters) { + + if (typeof filters === "string") + { + var filterTags = filters.split(","); + + for (var i = 0, len = filterTags.length; i < len; i++) + { + var tag = filterTags[i]; + + html = html.replace(new RegExp("\<\s*"+tag+"\s*([^\>]*)\>", "igm"), "").replace(new RegExp("\<\s*\/"+tag+"\s*\>", "igm"), ""); + } + } + + return html; + }; + + /** + * 将Markdown文档解析为HTML用于前台显示 + * Parse Markdown to HTML for Font-end preview. + * + * @param {String} id 用于显示HTML的对象ID + * @param {Object} [options={}] 配置选项,可选 + * @returns {Object} div 返回jQuery对象元素 + */ + + editormd.markdownToHTML = function(id, options) { + var defaults = { + gfm : true, + toc : true, + tocStartLevel : 1, + markdown : "", + htmlDecode : false, + inRequirejs : false, + tex : false, + taskList : false, // Github Flavored Markdown task lists + emoji : false, + flowChart : false, + sequenceDiagram : false, + previewCodeHighlight : true + }; + + editormd.$marked = marked; + + var div = $("#" + id); + var settings = div.settings = $.extend(true, defaults, options || {}); + var saveTo = div.find("textarea"); + var markdownDoc = (settings.markdown === "") ? saveTo.val() : settings.markdown; + var markdownToC = []; + + var rendererOptions = { + toc : settings.toc, + tocStartLevel : settings.tocStartLevel, + taskList : settings.taskList, + emoji : settings.emoji, + tex : settings.tex, + flowChart : settings.flowChart, + sequenceDiagram : settings.sequenceDiagram, + previewCodeHighlight : settings.previewCodeHighlight, + }; + + var markedOptions = { + renderer : editormd.markedRenderer(markdownToC, rendererOptions), + gfm : settings.gfm, + tables : true, + breaks : true, + pedantic : false, + sanitize : (settings.htmlDecode) ? false : true, // 是否忽略HTML标签,即是否开启HTML标签解析,为了安全性,默认不开启 + smartLists : true, + smartypants : true + }; + + markdownDoc = editormd.filterHTMLTags(markdownDoc, settings.htmlDecode); + + var markdownParsed = marked(markdownDoc, markedOptions); + + if (editormd.isIE8) + { + saveTo.val(markdownDoc); + } + else + { + saveTo.html(markdownDoc); + } + + div.addClass("markdown-body " + this.classPrefix + "html-preview").append(markdownParsed); + + if (settings.toc) { + div.tocContainer = this.markdownToCRenderer(markdownToC, div, settings.tocStartLevel); + } + + if (settings.previewCodeHighlight) + { + div.find("pre").addClass("prettyprint linenums"); + prettyPrint(); + } + + if (!editormd.isIE8) + { + if (settings.flowChart) { + div.find(".flowchart").flowChart(); + } + + if (settings.sequenceDiagram) { + div.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); + } + } + + if (settings.tex) + { + var katexHandle = function() { + div.find("." + editormd.classNames.tex).each(function(){ + var tex = $(this); + editormd.$katex.render(tex.html(), tex[0]); + }); + }; + + if (!settings.inRequirejs) { + this.loadKaTeX(function(){ + editormd.$katex = katex; + katexHandle(); + }); + } else { + katexHandle(); + } + } + + div.getMarkdown = function() { + return (editormd.isIE8) ? saveTo.val() : saveTo.html(); + }; + + return div; + }; + + editormd.themes = [ + "default", + "3024-day", "3024-night", + "ambiance", "ambiance-mobile", + "base16-dark", "base16-light", "blackboard", + "cobalt", + "eclipse", "elegant", "erlang-dark", + "lesser-dark", + "mbo", "mdn-like", "midnight", "monokai", + "neat", "neo", "night", + "paraiso-dark", "paraiso-light", "pastel-on-dark", + "rubyblue", + "solarized", + "the-matrix", "tomorrow-night-eighties", "twilight", + "vibrant-ink", + "xq-dark", "xq-light" + ]; + + editormd.loadPlugins = {}; + + editormd.loadFiles = { + js : [], + css : [], + plugin : [] + }; + + /** + * 动态加载Editor.md插件,但不立即执行 + * Load editor.md plugins + * + * @param {String} fileName 插件文件路径 + * @param {Function} [callback=function()] 加载成功后执行的回调函数 + * @param {String} [into="head"] 嵌入页面的位置 + */ + + editormd.loadPlugin = function(fileName, callback, into) { + callback = callback || function() {}; + + this.loadScript(fileName, function() { + editormd.loadFiles.plugin.push(fileName); + callback(); + }, into); + }; + + /** + * 动态加载CSS文件的方法 + * Load css file method + * + * @param {String} fileName CSS文件名 + * @param {Function} [callback=function()] 加载成功后执行的回调函数 + * @param {String} [into="head"] 嵌入页面的位置 + */ + + editormd.loadCSS = function(fileName, callback, into) { + into = into || "head"; + callback = callback || function() {}; + + var css = document.createElement("link"); + css.type = "text/css"; + css.rel = "stylesheet"; + css.onload = css.onreadystatechange = function() { + editormd.loadFiles.css.push(fileName); + callback(); + }; + + css.href = fileName + ".css"; + + if(into === "head") { + document.getElementsByTagName("head")[0].appendChild(css); + } else { + document.body.appendChild(css); + } + }; + + editormd.isIE = (navigator.appName == "Microsoft Internet Explorer"); + editormd.isIE8 = (editormd.isIE && navigator.appVersion.match(/8./i) == "8."); + + /** + * 动态加载JS文件的方法 + * Load javascript file method + * + * @param {String} fileName JS文件名 + * @param {Function} [callback=function()] 加载成功后执行的回调函数 + * @param {String} [into="head"] 嵌入页面的位置 + */ + + editormd.loadScript = function(fileName, callback, into) { + + into = into || "head"; + callback = callback || function() {}; + + var script = null; + script = document.createElement("script"); + script.id = fileName.replace(/[\./]+/g, "-"); + script.type = "text/javascript"; + script.src = fileName + ".js"; + + if (editormd.isIE8) { + + script.onreadystatechange = function() { + if(script.readyState) + { + if (script.readyState === "loaded" || script.readyState === "complete") + { + script.onreadystatechange = null; + editormd.loadFiles.js.push(fileName); + callback(); + } + } + }; + } + else + { + script.onload = function() { + editormd.loadFiles.js.push(fileName); + callback(); + }; + } + + if (into === "head") { + document.getElementsByTagName("head")[0].appendChild(script); + } else { + document.body.appendChild(script); + } + }; + + // 使用国外的CDN,加载速度有时会很慢,或者自定义URL + // You can custom KaTeX load url. + editormd.katexURL = { + css : "http://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min", + js : "http://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min" + }; + + editormd.kaTeXLoaded = false; + + /** + * 加载KaTeX文件 + * load KaTeX files + * + * @param {Function} [callback=function()] 加载成功后执行的回调函数 + */ + + editormd.loadKaTeX = function (callback) { + editormd.loadCSS(editormd.katexURL.css, function(){ + editormd.loadScript(editormd.katexURL.js, callback || function(){}); + }); + }; + + /** + * 锁屏 + * lock screen + * + * @param {Boolean} lock Boolean 布尔值,是否锁屏 + * @returns {void} + */ + + editormd.lockScreen = function(lock) { + $("html,body").css("overflow", (lock) ? "hidden" : ""); + }; + + /** + * 动态创建对话框 + * Creating custom dialogs + * + * @param {Object} options 配置项键值对 Key/Value + * @returns {dialog} 返回创建的dialog的jQuery实例对象 + */ + + editormd.createDialog = function(options) { + var defaults = { + name : "", + width : 420, + height: 240, + title : "", + drag : true, + closed : true, + content : "", + mask : true, + maskStyle : { + backgroundColor : "#fff", + opacity : 0.1 + }, + lockScreen : true, + footer : true, + buttons : false + }; + + options = $.extend(true, defaults, options); + + var editor = this.editor; + var classPrefix = editormd.classPrefix; + var guid = (new Date).getTime(); + var dialogName = ( (options.name === "") ? classPrefix + "dialog-" + guid : options.name); + var mouseOrTouch = editormd.mouseOrTouch; + + var html = "
        "; + + if (options.title !== "") + { + html += "
        "; + html += "" + options.title + ""; + html += "
        "; + } + + if (options.closed) + { + html += ""; + } + + html += "
        " + options.content; + + if (options.footer || typeof options.footer === "string") + { + html += "
        " + ( (typeof options.footer === "boolean") ? "" : options.footer) + "
        "; + } + + html += "
        "; + + html += "
        "; + html += "
        "; + html += "
        "; + + editor.append(html); + + var dialog = editor.find("." + dialogName); + + dialog.lockScreen = function(lock) { + if (options.lockScreen) + { + $("html,body").css("overflow", (lock) ? "hidden" : ""); + } + + return dialog; + }; + + dialog.showMask = function() { + if (options.mask) + { + editor.find("." + classPrefix + "mask").css(options.maskStyle).css("z-index", editormd.dialogZindex - 1).show(); + } + return dialog; + }; + + dialog.hideMask = function() { + if (options.mask) + { + editor.find("." + classPrefix + "mask").hide(); + } + + return dialog; + }; + + dialog.loading = function(show) { + var loading = dialog.find("." + classPrefix + "dialog-mask"); + loading[(show) ? "show" : "hide"](); + + return dialog; + }; + + dialog.lockScreen(true).showMask(); + + dialog.show().css({ + zIndex : editormd.dialogZindex, + border : (editormd.isIE8) ? "1px solid #ddd" : "", + width : (typeof options.width === "number") ? options.width + "px" : options.width, + height : (typeof options.height === "number") ? options.height + "px" : options.height + }); + + var dialogPosition = function(){ + dialog.css({ + top : ($(window).height() - dialog.height()) / 2 + "px", + left : ($(window).width() - dialog.width()) / 2 + "px" + }); + }; + + dialogPosition(); + + $(window).resize(dialogPosition); + + dialog.children("." + classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { + dialog.hide().lockScreen(false).hideMask(); + }); + + if (typeof options.buttons == "object") + { + var footer = dialog.footer = dialog.find("." + classPrefix + "dialog-footer"); + + for (var key in options.buttons) + { + var btn = options.buttons[key]; + var btnClassName = classPrefix + key + "-btn"; + + footer.append(""); + btn[1] = $.proxy(btn[1], dialog); + footer.children("." + btnClassName).bind(mouseOrTouch("click", "touchend"), btn[1]); + } + } + + if (options.title !== "" && options.drag) + { + var posX, posY; + var dialogHeader = dialog.children("." + classPrefix + "dialog-header"); + + if (!options.mask) { + dialogHeader.bind(mouseOrTouch("click", "touchend"), function(){ + editormd.dialogZindex += 2; + dialog.css("z-index", editormd.dialogZindex); + }); + } + + dialogHeader.mousedown(function(e) { + e = e || window.event; //IE + posX = e.clientX - parseInt(dialog[0].style.left); + posY = e.clientY - parseInt(dialog[0].style.top); + + document.onmousemove = moveAction; + }); + + var userCanSelect = function (obj) { + obj.removeClass(classPrefix + "user-unselect").off("selectstart"); + } + + var userUnselect = function (obj) { + obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) { // selectstart for IE + return false; + }); + } + + var moveAction = function (e) { + e = e || window.event; //IE + + var left, top, nowLeft = parseInt(dialog[0].style.left), nowTop = parseInt(dialog[0].style.top); + + if( nowLeft >= 0 ) { + if( nowLeft + dialog.width() <= $(window).width()) { + left = e.clientX - posX; + } else { + left = $(window).width() - dialog.width(); + document.onmousemove = null; + } + } else { + left = 0; + document.onmousemove = null; + } + + if( nowTop >= 0 ) { + top = e.clientY - posY; + } else { + top = 0; + document.onmousemove = null; + } + + + document.onselectstart = function() { + return false; + }; + + userUnselect($("body")); + userUnselect(dialog); + dialog[0].style.left = left + "px"; + dialog[0].style.top = top + "px"; + } + + document.onmouseup = function() { + userCanSelect($("body")); + userCanSelect(dialog); + + document.onselectstart = null; + document.onmousemove = null; + }; + + dialogHeader.touchDraggable = function() { + var offset = null; + var start = function(e) { + var orig = e.originalEvent; + var pos = $(this).parent().position(); + + offset = { + x : orig.changedTouches[0].pageX - pos.left, + y : orig.changedTouches[0].pageY - pos.top + }; + }; + + var move = function(e) { + e.preventDefault(); + var orig = e.originalEvent; + + $(this).parent().css({ + top : orig.changedTouches[0].pageY - offset.y, + left : orig.changedTouches[0].pageX - offset.x + }); + }; + + this.bind("touchstart", start).bind("touchmove", move); + }; + + dialogHeader.touchDraggable(); + } + + editormd.dialogZindex += 2; + + return dialog; + }; + + /** + * 鼠标和触摸事件的判断/选择方法 + * MouseEvent or TouchEvent type switch + * + * @param {String} [mouseEventType="click"] 供选择的鼠标事件 + * @param {String} [touchEventType="touchend"] 供选择的触摸事件 + * @returns {String} EventType 返回事件类型名称 + */ + + editormd.mouseOrTouch = function(mouseEventType, touchEventType) { + mouseEventType = mouseEventType || "click"; + touchEventType = touchEventType || "touchend"; + + var eventType = mouseEventType; + + try + { + document.createEvent("TouchEvent"); + eventType = touchEventType; + } + catch(e) { + } + + return eventType; + }; + + /** + * 日期时间的格式化方法 + * Datetime format method + * + * @param {String} [format=""] 日期时间的格式,类似PHP的格式 + * @returns {String} datefmt 返回格式化后的日期时间字符串 + */ + + editormd.dateFormat = function(format) { + format = format || ""; + + var addZero = function(d) { + return (d < 10) ? "0" + d : d; + }; + + var date = new Date; + var year = date.getFullYear(); + var year2 = year.toString().slice(2, 4); + var month = addZero(date.getMonth() + 1); + var day = addZero(date.getDate()); + var weekDay = date.getDay(); + var hour = addZero(date.getHours()); + var min = addZero(date.getMinutes()); + var second = addZero(date.getSeconds()); + var ms = addZero(date.getMilliseconds()); + var datefmt = ""; + + var ymd = year2 + "-" + month + "-" + day; + var fymd = year + "-" + month + "-" + day; + var hms = hour + ":" + min + ":" + second; + + switch (format) + { + case "UNIX Time" : + datefmt = date.getTime(); + break; + + case "UTC" : + datefmt = date.toUTCString(); + break; + + case "yy" : + datefmt = year2; + break; + + case "year" : + case "yyyy" : + datefmt = year; + break; + + case "month" : + case "mm" : + datefmt = month; + break; + + case "cn-week-day" : + case "cn-wd" : + var cnWeekDays = ["日", "一", "二", "三", "四", "五", "六"]; + datefmt = "星期" + cnWeekDays[weekDay]; + break; + + case "week-day" : + case "wd" : + var weekDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + datefmt = weekDays[weekDay]; + break; + + case "day" : + case "dd" : + datefmt = day; + break; + + case "hour" : + case "hh" : + datefmt = hour; + break; + + case "min" : + case "ii" : + datefmt = min; + break; + + case "second" : + case "ss" : + datefmt = second; + break; + + case "ms" : + datefmt = ms; + break; + + case "yy-mm-dd" : + datefmt = ymd; + break; + + case "yyyy-mm-dd" : + datefmt = fymd; + break; + + case "yyyy-mm-dd h:i:s ms" : + case "full + ms" : + datefmt = fymd + " " + hms + " " + ms; + break; + + case "full" : + case "yyyy-mm-dd h:i:s" : + default: + datefmt = fymd + " " + hms; + break; + }; + + return datefmt; + }; + + return editormd; + +})); diff --git a/editormd.amd.min.js b/editormd.amd.min.js new file mode 100644 index 0000000..17d6154 --- /dev/null +++ b/editormd.amd.min.js @@ -0,0 +1,3 @@ +/*! Editor.md v1.2.0 | editormd.amd.min.js | A simple online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-03-10 */ +!function(e){"use strict";if("function"==typeof require&&"object"==typeof exports&&"object"==typeof module)module.exports=e;else if("function"==typeof define)if(define.amd){var t="codemirror/mode/",i="codemirror/addon/",o=["jquery","marked","prettify","katex","raphael","underscore","flowchart","jqueryflowchart","sequenceDiagram","codemirror/lib/codemirror",t+"css/css",t+"sass/sass",t+"shell/shell",t+"sql/sql",t+"clike/clike",t+"php/php",t+"xml/xml",t+"markdown/markdown",t+"javascript/javascript",t+"htmlmixed/htmlmixed",t+"gfm/gfm",t+"http/http",t+"go/go",t+"dart/dart",t+"coffeescript/coffeescript",t+"nginx/nginx",t+"python/python",t+"perl/perl",t+"lua/lua",t+"r/r",t+"ruby/ruby",t+"rst/rst",t+"smartymixed/smartymixed",t+"vb/vb",t+"vbscript/vbscript",t+"velocity/velocity",t+"xquery/xquery",t+"yaml/yaml",t+"erlang/erlang",t+"jade/jade",i+"edit/trailingspace",i+"dialog/dialog",i+"search/searchcursor",i+"search/search",i+"scroll/annotatescrollbar",i+"search/matchesonscrollbar",i+"display/placeholder",i+"edit/closetag",i+"fold/foldcode",i+"fold/foldgutter",i+"fold/indent-fold",i+"fold/brace-fold",i+"fold/xml-fold",i+"fold/markdown-fold",i+"fold/comment-fold",i+"mode/overlay",i+"selection/active-line",i+"edit/closebrackets",i+"display/fullscreen",i+"search/match-highlighter"];define(o,e)}else define(["jquery"],e);else window.editormd=e()}(function(){"function"==typeof define&&define.amd&&(e=arguments[0],marked=arguments[1],prettify=arguments[2],katex=arguments[3],Raphael=arguments[4],_=arguments[5],flowchart=arguments[6],CodeMirror=arguments[9]);var e="undefined"!=typeof jQuery?jQuery:Zepto;if("undefined"!=typeof e){var t=function(e,i){return new t.fn.init(e,i)};t.title=t.$name="Editor.md",t.version="1.2.0",t.homePage="https://pandao.github.io/editor.md/",t.classPrefix="editormd-",t.toolbarModes={full:["undo","redo","|","bold","del","italic","quote","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","link","anchor","image","code","preformatted-text","code-block","table","datetime","emoji","htmlEntities","|","watch","preview","fullscreen","clear","|","help","info"],simple:["undo","redo","|","bold","del","italic","quote","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","watch","preview","fullscreen","|","help","info"],mini:["undo","redo","|","watch","preview","|","help","info"]},t.defaults={mode:"gfm",theme:"default",value:"",markdown:"",width:"100%",height:"100%",path:"./lib/",autoLoadModules:!0,watch:!0,placeholder:"now coding markdown...",codeFold:!1,autoCloseTags:!0,searchReplace:!1,readOnly:!1,lineNumbers:!0,matchWordHighlight:!0,styleActiveLine:!0,dialogLockScreen:!0,dialogShowMask:!0,dialogDraggable:!0,dialogMaskBgColor:"#fff",dialogMaskOpacity:.1,fontSize:"13px",saveHTMLToTextarea:!1,onload:function(){},onresize:function(){},onchange:function(){},onwatch:null,onunwatch:null,onpreviewing:function(){},onpreviewed:function(){},onfullscreen:function(){},onfullscreenExit:function(){},onscroll:function(){},onpreviewscroll:function(){},imageUpload:!1,imageFormats:["jpg","jpeg","gif","png","bmp","webp"],imageUploadURL:"",crossDomainUpload:!1,uploadCallbackURL:"",toc:!0,tocStartLevel:1,htmlDecode:!1,taskList:!1,emoji:!1,tex:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0,inRequirejs:!1,toolbar:!0,toolbarIcons:function(){return t.toolbarModes.full},toolbarTitles:{},toolbarHandlers:{},toolbarCustomIcons:{},toolbarIconsClass:{undo:"fa-undo",redo:"fa-repeat",bold:"fa-bold",del:"fa-strikethrough",italic:"fa-italic",quote:"fa-quote-left",h1:t.classPrefix+"bold",h2:t.classPrefix+"bold",h3:t.classPrefix+"bold",h4:t.classPrefix+"bold",h5:t.classPrefix+"bold",h6:t.classPrefix+"bold","list-ul":"fa-list-ul","list-ol":"fa-list-ol",hr:"fa-minus",link:"fa-link",anchor:"fa-anchor",image:"fa-picture-o",code:"fa-code","preformatted-text":"fa-file-code-o","code-block":"fa-file-code-o",table:"fa-table",datetime:"fa-clock-o",emoji:"fa-smile-o",htmlEntities:"fa-copyright",watch:"fa-eye-slash",unwatch:"fa-eye",preview:"fa-search",fullscreen:"fa-arrows-alt",clear:"fa-eraser",help:"fa-question-circle",info:"fa-info-circle"},toolbarIconTexts:{},lang:{name:"zh-cn",description:"开源在线Markdown编辑器
        A simple markdown doucment online editor.",toolbar:{undo:"撤销(Ctrl+Z)",redo:"重做(Ctrl+Y)",bold:"粗体",del:"删除线",italic:"斜体",quote:"引用",h1:"标题1",h2:"标题2",h3:"标题3",h4:"标题4",h5:"标题5",h6:"标题6","list-ul":"无序列表","list-ol":"有序列表",hr:"横线",link:"链接",anchor:"锚点",image:"添加图片",code:"行内代码","preformatted-text":"预格式文本 / 代码块(缩进风格)","code-block":"代码块(多语言风格)",table:"添加表格",datetime:"日期时间",emoji:"Emoji表情",htmlEntities:"HTML实体字符",watch:"关闭实时预览",unwatch:"开启实时预览",preview:"全窗口预览HTML(可按ESC还原)",fullscreen:"全屏(按ESC还原)",clear:"清空",help:"使用帮助",info:"关于"+t.title},buttons:{enter:"确定",cancel:"取消",close:"关闭"},dialog:{link:{title:"添加链接",url:"链接地址",urlTitle:"链接标题",urlEmpty:"错误:请填写链接地址。"},anchor:{title:"添加锚点链接",name:"锚点名称",url:"链接地址",urlTitle:"链接标题",nameEmpty:"错误:锚点名称不能为空。",titleEmpty:"错误:请填写锚点链接标题。",urlEmpty:"错误:请填写锚点链接地址。"},image:{title:"添加图片",url:"图片地址",link:"图片链接",alt:"图片描述",uploadButton:"本地上传",imageURLEmpty:"错误:图片地址不能为空。",uploadFileEmpty:"错误:上传的图片不能为空。",formatNotAllowed:"错误:只允许上传图片文件,允许上传的图片文件格式有:"},preformattedText:{title:"添加预格式文本或代码块",emptyAlert:"错误:请填写预格式文本或代码的内容。"},codeBlock:{title:"添加代码块",selectLabel:"代码语言:",selectDefaultText:"请选择代码语言",otherLanguage:"其他语言",unselectedLanguageAlert:"错误:请选择代码所属的语言类型。",codeEmptyAlert:"错误:请填写代码内容。"},htmlEntities:{title:"HTML 实体字符"},help:{title:"使用帮助"}}}},t.classNames={tex:t.classPrefix+"tex"},t.dialogZindex=99999,t.$katex=null,t.$marked=null,t.$CodeMirror=null,t.$prettyPrint=null,t.prototype=t.fn={state:{watching:!1,loaded:!1,preview:!1,fullscreen:!1},init:function(i,o){o=o||{};var r=this,a=this.classPrefix=t.classPrefix,n=this.editor=e("#"+i),s=this.settings=e.extend(!0,t.defaults,o);this.id=i,this.lang=s.lang;var l=this.classNames={textarea:{html:this.classPrefix+"html-textarea",markdown:this.classPrefix+"markdown-textarea"}};this.state.watching=s.watch?!0:!1,n.hasClass("editormd")||n.addClass("editormd"),n.css({width:"number"==typeof s.width?s.width+"px":s.width,height:"number"==typeof s.height?s.height+"px":s.height});var c=this.markdownTextarea=n.children("textarea");c.length<1&&(n.append(""),c=this.markdownTextarea=n.children("textarea")),c.addClass(l.textarea.markdown).attr("name",i+"-markdown-doc").attr("placeholder",s.placeholder);var d=[s.readOnly?"":'',s.saveHTMLToTextarea?'':"",'
        ','
        ','
        '].join("\n");return n.append(d).addClass(a+"vertical"),this.mask=n.children("."+a+"mask"),""!==s.markdown&&c.val(s.markdown),this.htmlTextarea=n.children("."+l.textarea.html),this.preview=n.children("."+a+"preview"),this.previewContainer=this.preview.children("."+a+"preview-container"),"function"==typeof define&&define.amd&&("undefined"!=typeof katex&&(t.$katex=katex),s.searchReplace&&(t.loadCSS(s.path+"codemirror/addon/dialog/dialog"),t.loadCSS(s.path+"codemirror/addon/search/matchesonscrollbar"))),"function"!=typeof define&&s.autoLoadModules?this.loadQueues():("undefined"!=typeof CodeMirror&&(t.$CodeMirror=CodeMirror),"undefined"!=typeof marked&&(t.$marked=marked),r.setCodeMirror(),r.setToolbar(),r.loadedDisplay()),this},loadQueues:function(){var e=this,i=this.settings,o=i.path,r=function(){return t.isIE8?void e.loadedDisplay():void(i.flowChart||i.sequenceDiagram?t.loadScript(o+"raphael.min",function(){t.loadScript(o+"underscore.min",function(){!i.flowChart&&i.sequenceDiagram?t.loadScript(o+"sequence-diagram.min",function(){e.loadedDisplay()}):i.flowChart&&!i.sequenceDiagram?t.loadScript(o+"flowchart.min",function(){t.loadScript(o+"jquery.flowchart.min",function(){e.loadedDisplay()})}):i.flowChart&&i.sequenceDiagram&&t.loadScript(o+"flowchart.min",function(){t.loadScript(o+"jquery.flowchart.min",function(){t.loadScript(o+"sequence-diagram.min",function(){e.loadedDisplay()})})})})}):e.loadedDisplay())};return t.loadCSS(o+"codemirror/codemirror.min"),i.searchReplace&&(t.loadCSS(o+"codemirror/addon/dialog/dialog"),t.loadCSS(o+"codemirror/addon/search/matchesonscrollbar")),i.codeFold&&t.loadCSS(o+"codemirror/addon/fold/foldgutter"),t.loadScript(o+"codemirror/codemirror.min",function(){t.$CodeMirror=CodeMirror,t.loadScript(o+"codemirror/modes.min",function(){t.loadScript(o+"codemirror/addons.min",function(){return e.setCodeMirror(),"gfm"!==i.mode&&"markdown"!==i.mode?(e.loadedDisplay(),!1):(e.setToolbar(),void t.loadScript(o+"marked.min",function(){t.$marked=marked,i.previewCodeHighlight?t.loadScript(o+"prettify.min",function(){r()}):r()}))})})}),this},setTheme:function(e){var i=this.settings;return i.theme=e,"default"!==e&&t.loadCSS(i.path+"codemirror/theme/"+i.theme),this.cm.setOption("theme",e),this},setCodeMirror:function(){var e=this.settings,i=this.editor;"default"!==e.theme&&t.loadCSS(e.path+"codemirror/theme/"+e.theme);var o={mode:e.mode,theme:e.theme,tabSize:4,dragDrop:!1,autofocus:!0,autoCloseTags:e.autoCloseTags,readOnly:e.readOnly?"nocursor":!1,indentUnit:4,lineNumbers:e.lineNumbers,lineWrapping:!0,extraKeys:{"Ctrl-Q":function(e){e.foldCode(e.getCursor())}},foldGutter:e.codeFold,gutters:["CodeMirror-linenumbers","CodeMirror-foldgutter"],matchBrackets:!0,indentWithTabs:!0,styleActiveLine:e.styleActiveLine,styleSelectedText:!0,autoCloseBrackets:!0,showTrailingSpace:!0,highlightSelectionMatches:e.matchWordHighlight?{showToken:"onselected"==e.matchWordHighlight?!1:/\w/}:!1};return this.codeEditor=this.cm=t.$CodeMirror.fromTextArea(this.markdownTextarea[0],o),this.codeMirror=this.cmElement=i.children(".CodeMirror"),""!==e.value&&this.cm.setValue(e.value),this.codeMirror.css({fontSize:e.fontSize,width:e.watch?"50%":"100%"}),this},getCodeMirrorOption:function(e){return this.cm.getOption(e)},setCodeMirrorOption:function(e,t){return this.cm.setOption(e,t),this},addKeyMap:function(e,t){return this.cm.addKeyMap(e,t),this},removeKeyMap:function(e){return this.cm.removeKeyMap(e),this},"extends":function(){return"undefined"!=typeof arguments[1]&&("function"==typeof arguments[1]&&(arguments[1]=e.proxy(arguments[1],this)),this[arguments[0]]=arguments[1]),"object"==typeof arguments[0]&&"undefined"==typeof arguments[0].length&&e.extend(!0,this,arguments[0]),this},set:function(t,i){return"undefined"!=typeof i&&"function"==typeof i&&(i=e.proxy(i,this)),this[t]=i,this},config:function(t,i){var o=this.settings;return"object"==typeof t&&(o=e.extend(!0,o,t)),"string"==typeof t&&(o[t]=i),this.settings=o,this.recreate(),this},on:function(t,i){var o=this.settings;return"undefined"!=typeof o["on"+t]&&(o["on"+t]=e.proxy(i,this)),this},off:function(e){var t=this.settings;return"undefined"!=typeof t["on"+e]&&(t["on"+e]=function(){}),this},showToolbar:function(t){var i=this.settings;if(!i.readOnly)return i.toolbar&&(this.toolbar.length<1||""===this.toolbar.find("."+this.classPrefix+"menu").html())&&this.setToolbar(),i.toolbar=!0,this.toolbar.show(),this.resize(),e.proxy(t||function(){},this)(),this},hideToolbar:function(t){var i=this.settings;return i.toolbar=!1,this.toolbar.hide(),this.resize(),e.proxy(t||function(){},this)(),this},setToolbar:function(){var e=this.settings;if(!e.readOnly){var i=this.editor,o=(this.preview,this.classPrefix),r=this.toolbar=i.children("."+o+"toolbar");if(e.toolbar&&r.length<1&&(i.append('
          '),r=this.toolbar=i.children("."+o+"toolbar")),!e.toolbar)return void r.hide();r.show();for(var a="function"==typeof e.toolbarIcons?e.toolbarIcons():"string"==typeof e.toolbarIcons?t.toolbarModes[e.toolbarIcons]:e.toolbarIcons,n=r.find("."+this.classPrefix+"menu"),s="",l=0,c=a.length;c>l;l++){var d=a[l];if("|"!==d){var h=/h(\d)/.test(d),u=d;"watch"!==d||e.watch||(u="unwatch");var f=e.lang.toolbar[u],m=e.toolbarIconTexts[u],g=e.toolbarIconsClass[u];f="undefined"==typeof f?"":f,m="undefined"==typeof m?"":m,g="undefined"==typeof g?"":g,s+="
        • ",s+="undefined"!=typeof e.toolbarCustomIcons[d]?e.toolbarCustomIcons[d]:''+(h?d:""===g?m:"")+"",s+="
        • "}else s+='
        • |
        • '}return n.html(s),this.setToolbarHandler(),this}},dialogLockScreen:function(){return e.proxy(t.dialogLockScreen,this)(),this},dialogShowMask:function(i){return e.proxy(t.dialogShowMask,this)(i),this},getToolbarHandles:function(e){var i=this.toolbarHandlers=t.toolbarHandlers;return e&&"undefined"!=typeof toolbarIconHandlers[e]?i[e]:i},setToolbarHandler:function(){var i=this,o=this.settings;if(o.toolbar&&!o.readOnly){var r=(this.editor,this.preview,this.toolbar),a=this.codeEditor,n=(this.codeMirror,this.classPrefix),s=(this.previewContainer,this.toolbarIcons=r.find("."+n+"menu a")),l=this.getToolbarHandles();return s.bind(t.mouseOrTouch("click","touchend"),function(){var t=e(this).children(".fa"),r=t.attr("name"),n=a.getCursor(),s=a.getSelection();return""!==r?(i.activeIcon=t,"undefined"!=typeof l[r]?e.proxy(l[r],i)(a):"undefined"!=typeof o.toolbarHandlers[r]&&e.proxy(o.toolbarHandlers[r],i)(a,t,n,s),"link"!==r&&"anchor"!==r&&"image"!==r&&"code-block"!==r&&"preformatted-text"!==r&&"watch"!==r&&"preview"!==r&&"fullscreen"!==r&&"info"!==r&&a.focus(),!1):void 0}),this}},createDialog:function(i){return e.proxy(t.createDialog,this)(i)},createInfoDialog:function(){var e=this,i=this.editor,o=this.classPrefix,r=['
          ','
          ','

          '+t.title+"v"+t.version+"

          ","

          "+this.lang.description+"

          ",'

          Home page: '+t.homePage+"

          ","

          License: MIT

          ","
          ",'',"
          "].join("\n");i.append(r);var a=this.infoDialog=i.children("."+o+"dialog-info");return a.find("."+o+"dialog-close").bind(t.mouseOrTouch("click","touchend"),function(){e.hideInfoDialog()}),a.css("border",t.isIE8?"1px solid #ddd":"").css("z-index",t.dialogZindex).show(),this.infoDialogPosition(),this},infoDialogPosition:function(){var t=this.infoDialog,i=function(){t.css({top:(e(window).height()-t.height())/2+"px",left:(e(window).width()-t.width())/2+"px"})};return i(),e(window).resize(i),this},showInfoDialog:function(){e("html,body").css("overflow-x","hidden");var i=this.editor,o=this.settings,r=this.classPrefix,a=this.infoDialog=i.children("."+r+"dialog-info");return a.length<1&&this.createInfoDialog(),this.lockScreen(!0),this.mask.css({opacity:o.dialogMaskOpacity,backgroundColor:o.dialogMaskBgColor}).show(),a.css("z-index",t.dialogZindex).show(),this.infoDialogPosition(),this},hideInfoDialog:function(){return e("html,body").css("overflow-x",""),this.infoDialog.hide(),this.mask.hide(),this.lockScreen(!1),this},lockScreen:function(e){return t.lockScreen(e),this},recreate:function(){var e=this.editor,t=this.settings,i=t.toolbarIcons();return this.codeMirror.remove(),this.setCodeMirror(),"undefined"!=typeof this.infoDialog&&this.infoDialog.remove(),"undefined"!=typeof i.info&&createInfoDialog(),t.readOnly||(e.find(".editormd-dialog").length>0&&e.find(".editormd-dialog").remove(),t.toolbar&&(this.getToolbarHandles(),this.setToolbar())),this.saveToTextareas(),this.resize(),this},previewCodeHighlight:function(){var e=this.settings,t=this.previewContainer;return e.previewCodeHighlight&&(t.find("pre").addClass("prettyprint linenums"),"undefined"!=typeof prettyPrint&&prettyPrint()),this},katexRender:function(){var i=this.previewContainer;return i.find("."+t.classNames.tex).each(function(){var i=e(this);t.$katex.render(i.html(),i[0])}),this},flowChartAndSequenceDiagramRender:function(){var e=this.settings,i=this.previewContainer;return t.isIE8?void 0:(e.flowChart&&i.find(".flowchart").flowChart(),e.sequenceDiagram&&i.find(".sequence-diagram").sequenceDiagram({theme:"simple"}),this)},loadedDisplay:function(){var i=this,o=this.editor,r=this.preview,a=this.settings,n=this.codeEditor,s=this.codeMirror,l=(this.previewContainer,t.mouseOrTouch);o.children("."+this.classPrefix+"container-mask").hide(),this.saveToTextareas(),a.watch&&r.show(),o.data("oldWidth",o.width()).data("oldHeight",o.height()),this.resize(),e(window).resize(function(){i.resize()});var c=function(){s.find(".CodeMirror-scroll").bind(l("scroll","touchmove"),function(t){var i=e(this).height(),o=e(this).scrollTop(),n=o/e(this)[0].scrollHeight;r.scrollTop(0===o?0:o+i>=e(this)[0].scrollHeight?r[0].scrollHeight:r[0].scrollHeight*n),e.proxy(a.onscroll,this)(t)})},d=function(){s.find(".CodeMirror-scroll").unbind(l("scroll","touchmove"))},h=function(){r.bind(l("scroll","touchmove"),function(){var t=e(this).height(),i=e(this).scrollTop(),o=i/e(this)[0].scrollHeight,r=s.find(".CodeMirror-scroll");r.scrollTop(0===i?0:i+t>=e(this)[0].scrollHeight?r[0].scrollHeight:r[0].scrollHeight*o),e.proxy(a.onpreviewscroll,this)(event)})},u=function(){r.unbind(l("scroll","touchmove"))};return s.bind({mouseover:c,mouseout:d,touchstart:c,touchend:d}),r.bind({mouseover:h,mouseout:u,touchstart:h,touchend:u}),n.on("change",function(){i.saveToTextareas()}),e.proxy(a.onload,this)(),this.state.loaded=!0,this},width:function(e){return this.editor.css("width","number"==typeof e?e+"px":e),this.resize(),this},height:function(e){return this.editor.css("height","number"==typeof e?e+"px":e),this.resize(),this},resize:function(t,i){t=t||null,i=i||null;var o=this.editor,r=this.preview,a=this.toolbar,n=this.settings,s=(this.codeEditor,this.codeMirror);return t&&i&&o.css({width:"number"==typeof t?t+"px":t,height:"number"==typeof i?i+"px":i}),n.toolbar&&!n.readOnly?s.css("margin-top",a.height()+1).height(o.height()-a.height()):s.css("margin-top",0).height(o.height()),s.find(".CodeMirror-gutters").height(s.height()),n.watch?(s.width(o.width()/2),r.width(this.state.preview?o.width():o.width()/2),n.toolbar&&!n.readOnly?r.css("top",a.height()).height(o.height()-a.height()):r.css("top",0).height(o.height())):(s.width(o.width()),r.hide()),this.state.loaded&&e.proxy(n.onresize,this)(),this},saveToTextareas:function(){var i=this,o=this.state,r=this.settings,a=this.codeEditor,n=this.previewContainer,s=a.getValue();if("gfm"!==r.mode&&"markdown"!==r.mode)return this.markdownTextarea[0].innerText=s,this;var l=t.$marked,c=this.markdownToC=[],d=this.markedRendererOptions={toc:r.toc,tocStartLevel:r.tocStartLevel,taskList:r.taskList,emoji:r.emoji,tex:r.tex,flowChart:r.flowChart,sequenceDiagram:r.sequenceDiagram,previewCodeHighlight:r.previewCodeHighlight},h=this.markedOptions={renderer:t.markedRenderer(c,d),gfm:!0,tables:!0,breaks:!0,pedantic:!1,sanitize:r.htmlDecode?!1:!0,smartLists:!0,smartypants:!0};l.setOptions(h),s=t.filterHTMLTags(s,r.htmlDecode);var u=t.$marked(s,h);if(this.markdownTextarea[0].innerText=s,a.save(),r.saveHTMLToTextarea&&this.htmlTextarea.html(u),r.watch||!r.watch&&o.preview){if(n.html(u),this.previewCodeHighlight(),r.toc&&t.markdownToCRenderer(c,n,r.tocStartLevel),r.tex&&(r.inRequirejs||t.kaTeXLoaded?this.katexRender():t.loadKaTeX(function(){t.$katex=katex,t.kaTeXLoaded=!0,i.katexRender()})),r.flowChart||r.sequenceDiagram)var f=setTimeout(function(){clearTimeout(f),i.flowChartAndSequenceDiagramRender()},10);o.loaded&&e.proxy(r.onchange,this)()}return this},focus:function(){return this.codeEditor.focus(),this},setCursor:function(e){return this.codeEditor.setCursor(e),this},getCursor:function(){return this.codeEditor.getCursor()},setSelection:function(e,t){return this.codeEditor.setSelection(e,t),this},getSelection:function(){return this.codeEditor.getSelection()},replaceSelection:function(e){return this.codeEditor.replaceSelection(e),this},insertValue:function(e){return this.replaceSelection(e),this},setMarkdown:function(e){var t=this.settings;return this.codeEditor.setValue(e||t.markdown),this},getMarkdown:function(){return this.codeEditor.getValue()},getValue:function(){return this.codeEditor.getValue()},setValue:function(e){return this.codeEditor.setValue(e),this},clear:function(){return this.codeEditor.setValue(""),this},getHTML:function(){return this.settings.saveHTMLToTextarea?this.htmlTextarea.html():(alert("Error: settings.saveHTMLToTextarea == false"),!1)},getTextareaSavedHTML:function(){return this.getHTML()},getPreviewedHTML:function(){return this.settings.watch?this.previewContainer.html():(alert("Error: settings.watch == false"),!1)},watch:function(t){var i=this.settings;this.state.watching=i.watch=!0,this.preview.show();var o=i.toolbarIconsClass.watch,r=i.toolbarIconsClass.unwatch,a=this.toolbar.find(".fa[name=watch]");return a.parent().attr("title",i.lang.toolbar.watch),a.removeClass(r).addClass(o),this.codeMirror.css("border-right","1px solid #ddd").width(this.editor.width()/2),this.saveToTextareas().resize(),i.onwatch||(i.onwatch=t||function(){}),e.proxy(i.onwatch,this)(),this},unwatch:function(t){var i=this.settings;this.state.watching=i.watch=!1,this.preview.hide();var o=i.toolbarIconsClass.watch,r=i.toolbarIconsClass.unwatch;if(this.toolbar){var a=this.toolbar.find(".fa[name=watch]");a.parent().attr("title",i.lang.toolbar.unwatch),a.removeClass(o).addClass(r)}return this.codeMirror.css("border-right","none").width(this.editor.width()),this.resize(),i.onunwatch||(i.onunwatch=t||function(){}),e.proxy(i.onunwatch,this)(),this},show:function(t){t=t||function(){};var i=this;return this.editor.show(function(){e.proxy(t,i)()}),this},hide:function(t){t=t||function(){};var i=this;return this.editor.hide(function(){e.proxy(t,i)()}),this},previewing:function(){var i=this,o=this.editor,r=this.preview,a=this.toolbar,n=this.settings,s=this.codeMirror;n.toolbar&&(a.toggle(),a.find(".fa[name=preview]").toggleClass("active")),s.toggle(),"none"===s.css("display")?(this.state.preview=!0,this.state.fullscreen&&r.css("background","#fff"),o.find("."+this.classPrefix+"preview-close-btn").show().bind(t.mouseOrTouch("click","touchend"),function(){i.previewed()}),n.watch||this.saveToTextareas(),r.show().css({position:"static",top:0,width:o.width(),height:o.height()}),this.state.loaded&&e.proxy(n.onpreviewing,this)()):this.previewed(),e(window).keyup(function(e){27===e.keyCode&&i.previewed()})},previewed:function(){var i=this.editor,o=this.preview,r=this.toolbar,a=this.settings,n=this.codeMirror,s=i.find("."+this.classPrefix+"preview-close-btn");return this.state.preview=!1,n.show(),a.toolbar&&r.show(),this.settings.watch?o.show():o.hide(),s.hide().bind(t.mouseOrTouch("click","touchend")),o.css({background:null,position:"absolute",width:i.width()/2,height:i.height()-r.height(),top:a.toolbar?r.height():0}),this.state.loaded&&e.proxy(a.onpreviewed,this)(),this},fullscreen:function(){var t=this,i=this.editor,o=(this.preview,this.toolbar),r=this.classPrefix+"fullscreen";return o&&o.find(".fa[name=fullscreen]").parent().toggleClass("active"),i.hasClass(r)?this.fullscreenExit():(this.state.fullscreen=!0,e("html,body").css("overflow","hidden"),i.css({position:"fixed",top:0,left:0,margin:0,border:"none",width:e(window).width(),height:e(window).height()}).addClass(r),this.resize(),e.proxy(this.settings.onfullscreen,this)()),e(window).keyup(function(e){t.state.preview||27===e.keyCode&&t.fullscreenExit()}),this},fullscreenExit:function(){var t=this.editor,i=this.toolbar,o=this.classPrefix+"fullscreen";return this.state.fullscreen=!1,i&&i.find(".fa[name=fullscreen]").parent().removeClass("active"),e("html,body").css("overflow",""),t.css({position:"",top:"",left:"",margin:"0 auto",width:t.data("oldWidth"),height:t.data("oldHeight"),border:"1px solid #ddd"}).removeClass(o),this.resize(),e.proxy(this.settings.onfullscreenExit,this)(),this},executePlugin:function(i,o){var r=this,a=this.cm;return"function"==typeof define?void this[i](a):(o=this.settings.path+"../plugins/"+o,void(e.inArray(o,t.loadFiles.plugin)<0?t.loadPlugin(o,function(){t.loadPlugins[i]=r[i],r[i](a)}):e.proxy(t.loadPlugins[i],this)(a)))}},t.fn.init.prototype=t.fn,t.dialogLockScreen=function(){var t=this.settings;t.dialogLockScreen&&e("html,body").css("overflow","hidden")},t.dialogShowMask=function(t){var i=this.editor,o=this.settings;t.css({top:(e(window).height()-t.height())/2+"px",left:(e(window).width()-t.width())/2+"px"}),o.dialogShowMask&&i.children("."+this.classPrefix+"mask").css("z-index",parseInt(t.css("z-index"))-1).show()},t.toolbarHandlers={undo:function(){this.cm.undo()},redo:function(){this.cm.redo()},bold:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("**"+i+"**"),""===i&&e.setCursor(t.line,t.ch+2)},del:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("~~"+i+"~~"),""===i&&e.setCursor(t.line,t.ch+2)},italic:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("*"+i+"*"),""===i&&e.setCursor(t.line,t.ch+1)},quote:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("> "+i),e.setCursor(t.line,""===i?t.ch+2:t.ch+i.length+2)},h1:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("# "+t)},h2:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("## "+t)},h3:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("### "+t)},h4:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("#### "+t)},h5:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("##### "+t)},h6:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("###### "+t)},"list-ul":function(){var e=this.cm,t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("- "+t);else{for(var i=t.split("\n"),o=0,r=i.length;r>o;o++)i[o]=""===i[o]?"":"- "+i[o];e.replaceSelection(i.join("\n"))}},"list-ol":function(){var e=this.cm,t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("1. "+t);else{for(var i=t.split("\n"),o=0,r=i.length;r>o;o++)i[o]=""===i[o]?"":o+1+". "+i[o];e.replaceSelection(i.join("\n"))}},hr:function(){{var e=this.cm;e.getCursor(),e.getSelection()}e.replaceSelection("------------")},link:function(){this.executePlugin("linkDialog","link-dialog/link-dialog")},anchor:function(){this.executePlugin("anchorLinkDialog","anchor-link-dialog/anchor-link-dialog")},image:function(){this.executePlugin("imageDialog","image-dialog/image-dialog")},code:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("`"+i+"`"),""===i&&e.setCursor(t.line,t.ch+1)},"code-block":function(){this.executePlugin("codeBlockDialog","code-block-dialog/code-block-dialog")},"preformatted-text":function(){this.executePlugin("preformattedTextDialog","preformatted-text-dialog/preformatted-text-dialog")},table:function(){this.executePlugin("tableDialog","table-dialog/table-dialog")},datetime:function(){var e=this.cm,i=(e.getSelection(),new Date,this.settings.lang.name),o=t.dateFormat()+" "+t.dateFormat("zh-cn"===i||"zh-tw"===i?"cn-week-day":"week-day");e.replaceSelection(o)},emoji:function(){this.executePlugin("emojiDialog","emoji-dialog/emoji-dialog")},htmlEntities:function(){this.executePlugin("htmlEntitiesDialog","html-entities-dialog/html-entities-dialog")},watch:function(){this[this.settings.watch?"unwatch":"watch"]()},preview:function(){this.previewing()},fullscreen:function(){this.fullscreen()},clear:function(){this.clear()},help:function(){this.executePlugin("helpDialog","help-dialog/help-dialog")},info:function(){this.showInfoDialog()}},t.trim=function(e){return String.prototype.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")};var i=t.trim;return t.urls={atLinkBase:"https://github.com/"},t.regex={atLink:/@(\w+)/g,emoji:/:([\-\w]+):/g,twemoji:/:(tw-([\w]+)-?(\w+)?):/g,fontAwesome:/:(fa-([\w]+)-?(\w+)?):/g,editormdLogo:/:(editormd-logo-?(\w+)?):/g},t.emoji={path:"http://www.emoji-cheat-sheet.com/graphics/emojis/",ext:".png"},t.twemoji={path:"http://twemoji.maxcdn.com/36x36/",ext:".png"},t.markedRenderer=function(o,r){var a={toc:!0,tocStartLevel:1,taskList:!1,emoji:!1,tex:!1,flowChart:!1,sequenceDiagram:!1},n=t.regex.atLink,s=e.extend(a,r||{}),l=t.$marked,c=new l.Renderer;o=o||[];var d=t.regex.emoji,h=t.regex.twemoji,u=t.regex.fontAwesome,f=t.regex.editormdLogo;return c.emoji=function(e){var i=e.match(d);if(!i||!s.emoji)return e;for(var o=0,r=i.length;r>o;o++)e=e.replace(new RegExp(i[o]),function(e){var i=e.match(u),o=e.replace(/:/g,"");if(i)for(var r=0,a=i.length;a>r;r++){var n=i[r].replace(/:/g,"");return''}else{var s=e.match(f),l=e.match(h);if(s)for(var c=0,d=s.length;d>c;c++){var m=s[c].replace(/:/g,"");return''}else{if(!l)return':'+o+':';for(var g=0,p=l.length;p>g;g++){var w=l[g].replace(/:/g,"").replace("tw-","");return'twemoji-'+w+''}}}});return e},c.atLink=function(e){return n.test(e)&&(e=e.replace(n,function(e,i){return''+e+""})),e},c.link=function(e,t,i){if(this.options.sanitize){try{var o=decodeURIComponent(unescape(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(r){return""}if(0===o.indexOf("javascript:"))return""}var a=''+i.replace(/@/g,"@")+""):(t&&(a+=' title="'+t+'"'),a+=">"+i+"")},c.heading=function(e,t){var r=e,a=/\s*\]*)\>(.*)\<\/a\>\s*/;if(a.test(e)){var n=[];e=e.split(/\]+)\>([^\>]*)\<\/a\>/);for(var s=0,l=e.length;l>s;s++)n.push(e[s].replace(/\s*href\=\"(.*)\"\s*/g,""));e=n.join(" ")}e=i(e);var c=e.toLowerCase().replace(/[^\w]+/g,"-"),d={text:e,level:t,slug:c},h=/^[\u4e00-\u9fa5]+$/.test(e),u=h?escape(e).replace(/\%/g,""):e.toLowerCase().replace(/[^\w]+/g,"-");o.push(d);var f="';return f+='',f+='',f+=this.atLink(a?this.emoji(r):this.emoji(e)),f+=""},c.paragraph=function(e){var i=/\$\$(.*)\$\$/g.test(e),o=/^\$\$(.*)\$\$$/.test(e),r=o?' class="'+t.classNames.tex+'"':"",a=/^\[TOC\]$/.test(e);return e=!o&&i?e.replace(/(\$\$([^\$]*)\$\$)+/g,function(e,i){return''+i.replace(/\$/g,"")+""}):o?e.replace(/\$/g,""):e,a?'
            '+e+"
          ":""+this.atLink(this.emoji(e))+"

          \n"},c.code=function(e,t){return"seq"===t||"sequence"===t?'
          '+e+"
          ":"flow"===t?'
          '+e+"
          ":l.Renderer.prototype.code.apply(this,arguments)},c.tablecell=function(e,t){var i=t.header?"th":"td",o=t.align?"<"+i+' style="text-align:'+t.align+'">':"<"+i+">";return o+this.atLink(this.emoji(e))+"\n"},c.listitem=function(e){return s.taskList&&/^\s*\[[x\s]\]\s*/.test(e)?(e=e.replace(/^\s*\[\s\]\s*/,' ').replace(/^\s*\[x\]\s*/,' '),'
        • '+this.atLink(this.emoji(e))+"
        • "):"
        • "+this.atLink(this.emoji(e))+"
        • "},c},t.markdownToCRenderer=function(e,t,i){var o="",r=0;i=i||1;for(var a=0,n=e.length;n>a;a++){var s=e[a].text,l=e[a].level;i>l||(o+=l>r?"":r>l?new Array(r-l+2).join("
      • "):"",o+='
      • '+s+"
          ",r=l)}var c=t.find(".markdown-toc");return c.children(".markdown-toc-list").html("").html(o),c},t.filterHTMLTags=function(e,t){if("string"==typeof t)for(var i=t.split(","),o=0,r=i.length;r>o;o++){var a=i[o]; +e=e.replace(new RegExp("]*)>","igm"),"").replace(new RegExp("","igm"),"")}return e},t.markdownToHTML=function(i,o){var r={gfm:!0,toc:!0,tocStartLevel:1,markdown:"",htmlDecode:!1,inRequirejs:!1,tex:!1,taskList:!1,emoji:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0};t.$marked=marked;var a=e("#"+i),n=a.settings=e.extend(!0,r,o||{}),s=a.find("textarea"),l=""===n.markdown?s.val():n.markdown,c=[],d={toc:n.toc,tocStartLevel:n.tocStartLevel,taskList:n.taskList,emoji:n.emoji,tex:n.tex,flowChart:n.flowChart,sequenceDiagram:n.sequenceDiagram,previewCodeHighlight:n.previewCodeHighlight},h={renderer:t.markedRenderer(c,d),gfm:n.gfm,tables:!0,breaks:!0,pedantic:!1,sanitize:n.htmlDecode?!1:!0,smartLists:!0,smartypants:!0};l=t.filterHTMLTags(l,n.htmlDecode);var u=marked(l,h);if(t.isIE8?s.val(l):s.html(l),a.addClass("markdown-body "+this.classPrefix+"html-preview").append(u),n.toc&&(a.tocContainer=this.markdownToCRenderer(c,a,n.tocStartLevel)),n.previewCodeHighlight&&(a.find("pre").addClass("prettyprint linenums"),prettyPrint()),t.isIE8||(n.flowChart&&a.find(".flowchart").flowChart(),n.sequenceDiagram&&a.find(".sequence-diagram").sequenceDiagram({theme:"simple"})),n.tex){var f=function(){a.find("."+t.classNames.tex).each(function(){var i=e(this);t.$katex.render(i.html(),i[0])})};n.inRequirejs?f():this.loadKaTeX(function(){t.$katex=katex,f()})}return a.getMarkdown=function(){return t.isIE8?s.val():s.html()},a},t.themes=["default","3024-day","3024-night","ambiance","ambiance-mobile","base16-dark","base16-light","blackboard","cobalt","eclipse","elegant","erlang-dark","lesser-dark","mbo","mdn-like","midnight","monokai","neat","neo","night","paraiso-dark","paraiso-light","pastel-on-dark","rubyblue","solarized","the-matrix","tomorrow-night-eighties","twilight","vibrant-ink","xq-dark","xq-light"],t.loadPlugins={},t.loadFiles={js:[],css:[],plugin:[]},t.loadPlugin=function(e,i,o){i=i||function(){},this.loadScript(e,function(){t.loadFiles.plugin.push(e),i()},o)},t.loadCSS=function(e,i,o){o=o||"head",i=i||function(){};var r=document.createElement("link");r.type="text/css",r.rel="stylesheet",r.onload=r.onreadystatechange=function(){t.loadFiles.css.push(e),i()},r.href=e+".css","head"===o?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.isIE="Microsoft Internet Explorer"==navigator.appName,t.isIE8=t.isIE&&"8."==navigator.appVersion.match(/8./i),t.loadScript=function(e,i,o){o=o||"head",i=i||function(){};var r=null;r=document.createElement("script"),r.id=e.replace(/[\./]+/g,"-"),r.type="text/javascript",r.src=e+".js",t.isIE8?r.onreadystatechange=function(){r.readyState&&("loaded"===r.readyState||"complete"===r.readyState)&&(r.onreadystatechange=null,t.loadFiles.js.push(e),i())}:r.onload=function(){t.loadFiles.js.push(e),i()},"head"===o?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.katexURL={css:"http://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min",js:"http://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min"},t.kaTeXLoaded=!1,t.loadKaTeX=function(e){t.loadCSS(t.katexURL.css,function(){t.loadScript(t.katexURL.js,e||function(){})})},t.lockScreen=function(t){e("html,body").css("overflow",t?"hidden":"")},t.createDialog=function(i){var o={name:"",width:420,height:240,title:"",drag:!0,closed:!0,content:"",mask:!0,maskStyle:{backgroundColor:"#fff",opacity:.1},lockScreen:!0,footer:!0,buttons:!1};i=e.extend(!0,o,i);var r=this.editor,a=t.classPrefix,n=(new Date).getTime(),s=""===i.name?a+"dialog-"+n:i.name,l=t.mouseOrTouch,c='
          ';""!==i.title&&(c+='
          ",c+=''+i.title+"",c+="
          "),i.closed&&(c+=''),c+='
          '+i.content,(i.footer||"string"==typeof i.footer)&&(c+='"),c+="
          ",c+='
          ',c+='
          ',c+="
          ",r.append(c);var d=r.find("."+s);d.lockScreen=function(t){return i.lockScreen&&e("html,body").css("overflow",t?"hidden":""),d},d.showMask=function(){return i.mask&&r.find("."+a+"mask").css(i.maskStyle).css("z-index",t.dialogZindex-1).show(),d},d.hideMask=function(){return i.mask&&r.find("."+a+"mask").hide(),d},d.loading=function(e){var t=d.find("."+a+"dialog-mask");return t[e?"show":"hide"](),d},d.lockScreen(!0).showMask(),d.show().css({zIndex:t.dialogZindex,border:t.isIE8?"1px solid #ddd":"",width:"number"==typeof i.width?i.width+"px":i.width,height:"number"==typeof i.height?i.height+"px":i.height});var h=function(){d.css({top:(e(window).height()-d.height())/2+"px",left:(e(window).width()-d.width())/2+"px"})};if(h(),e(window).resize(h),d.children("."+a+"dialog-close").bind(l("click","touchend"),function(){d.hide().lockScreen(!1).hideMask()}),"object"==typeof i.buttons){var u=d.footer=d.find("."+a+"dialog-footer");for(var f in i.buttons){var m=i.buttons[f],g=a+f+"-btn";u.append('"),m[1]=e.proxy(m[1],d),u.children("."+g).bind(l("click","touchend"),m[1])}}if(""!==i.title&&i.drag){var p,w,v=d.children("."+a+"dialog-header");i.mask||v.bind(l("click","touchend"),function(){t.dialogZindex+=2,d.css("z-index",t.dialogZindex)}),v.mousedown(function(e){e=e||window.event,p=e.clientX-parseInt(d[0].style.left),w=e.clientY-parseInt(d[0].style.top),document.onmousemove=k});var x=function(e){e.removeClass(a+"user-unselect").off("selectstart")},b=function(e){e.addClass(a+"user-unselect").on("selectstart",function(){return!1})},k=function(t){t=t||window.event;var i,o,r=parseInt(d[0].style.left),a=parseInt(d[0].style.top);r>=0?r+d.width()<=e(window).width()?i=t.clientX-p:(i=e(window).width()-d.width(),document.onmousemove=null):(i=0,document.onmousemove=null),a>=0?o=t.clientY-w:(o=0,document.onmousemove=null),document.onselectstart=function(){return!1},b(e("body")),b(d),d[0].style.left=i+"px",d[0].style.top=o+"px"};document.onmouseup=function(){x(e("body")),x(d),document.onselectstart=null,document.onmousemove=null},v.touchDraggable=function(){var t=null,i=function(i){var o=i.originalEvent,r=e(this).parent().position();t={x:o.changedTouches[0].pageX-r.left,y:o.changedTouches[0].pageY-r.top}},o=function(i){i.preventDefault();var o=i.originalEvent;e(this).parent().css({top:o.changedTouches[0].pageY-t.y,left:o.changedTouches[0].pageX-t.x})};this.bind("touchstart",i).bind("touchmove",o)},v.touchDraggable()}return t.dialogZindex+=2,d},t.mouseOrTouch=function(e,t){e=e||"click",t=t||"touchend";var i=e;try{document.createEvent("TouchEvent"),i=t}catch(o){}return i},t.dateFormat=function(e){e=e||"";var t=function(e){return 10>e?"0"+e:e},i=new Date,o=i.getFullYear(),r=o.toString().slice(2,4),a=t(i.getMonth()+1),n=t(i.getDate()),s=i.getDay(),l=t(i.getHours()),c=t(i.getMinutes()),d=t(i.getSeconds()),h=t(i.getMilliseconds()),u="",f=r+"-"+a+"-"+n,m=o+"-"+a+"-"+n,g=l+":"+c+":"+d;switch(e){case"UNIX Time":u=i.getTime();break;case"UTC":u=i.toUTCString();break;case"yy":u=r;break;case"year":case"yyyy":u=o;break;case"month":case"mm":u=a;break;case"cn-week-day":case"cn-wd":var p=["日","一","二","三","四","五","六"];u="星期"+p[s];break;case"week-day":case"wd":var w=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];u=w[s];break;case"day":case"dd":u=n;break;case"hour":case"hh":u=l;break;case"min":case"ii":u=c;break;case"second":case"ss":u=d;break;case"ms":u=h;break;case"yy-mm-dd":u=f;break;case"yyyy-mm-dd":u=m;break;case"yyyy-mm-dd h:i:s ms":case"full + ms":u=m+" "+g+" "+h;break;case"full":case"yyyy-mm-dd h:i:s":default:u=m+" "+g}return u},t}}); \ No newline at end of file diff --git a/dist/js/editormd.js b/editormd.js similarity index 54% rename from dist/js/editormd.js rename to editormd.js index e63f8e1..f8e0f14 100644 --- a/dist/js/editormd.js +++ b/editormd.js @@ -1,18 +1,13 @@ /* * Editor.md + * * @file editormd.js - * @version v1.1.9 + * @version v1.2.0 * @description A simple online markdown editor. * @license MIT License * @author Pandao * {@link https://github.com/pandao/editor.md} - * @updateTime 2015-03-04 - */ - -/** - * @fileOverview Editor.md - * @author pandao - * @version 1.1.9 + * @updateTime 2015-03-10 */ ;(function(factory) { @@ -21,18 +16,25 @@ // CommonJS/Node.js if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { - module.exports = factory(); + module.exports = factory; } else if (typeof define === "function") // AMD/CMD/Sea.js { - define(["jquery"], factory); + if (define.amd) // for Require.js + { + /* Require.js define replace */ + } + else + { + define(["jquery"], factory); // for Sea.js + } } else { window.editormd = factory(); } -}(function() { +}(function() { /** * editormd @@ -41,6 +43,8 @@ * @param {Object} options 配置选项 Key/Value * @returns {Object} editormd 返回editormd对象 */ + + /* Require.js assignment replace */ "use strict"; @@ -54,19 +58,50 @@ return new editormd.fn.init(id, options); }; - editormd.title = editormd.$name = "Editor.md"; - editormd.version = "1.1.9"; - editormd.homePage = "https://pandao.github.io/editor.md/"; - editormd.classPrefix = "editormd-"; + editormd.title = editormd.$name = "Editor.md"; + editormd.version = "1.2.0"; + editormd.homePage = "https://pandao.github.io/editor.md/"; + editormd.classPrefix = "editormd-"; - editormd.defaults = { + editormd.toolbarModes = { + full : [ + "undo", "redo", "|", + "bold", "del", "italic", "quote", "|", + "h1", "h2", "h3", "h4", "h5", "h6", "|", + "list-ul", "list-ol", "hr", "|", + "link", "anchor", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "htmlEntities", "|", + "watch", "preview", "fullscreen", "clear", "|", + "help", "info" + ], + simple : [ + "undo", "redo", "|", + "bold", "del", "italic", "quote", "|", + "h1", "h2", "h3", "h4", "h5", "h6", "|", + "list-ul", "list-ol", "hr", "|", + "watch", "preview", "fullscreen", "|", + "help", "info" + ], + mini : [ + "undo", "redo", "|", + "watch", "preview", "|", + "help", "info" + ] + }; + + editormd.defaults = { mode : "gfm", //gfm or markdown + theme : "default", + value : "", // value for CodeMirror, if mode not gfm/markdown markdown : "", width : "100%", height : "100%", - path : "./lib/", + path : "./lib/", // Dependents module file directory + autoLoadModules : true, // Automatic load dependent module files watch : true, placeholder : "now coding markdown...", + codeFold : false, + autoCloseTags : true, + searchReplace : false, readOnly : false, lineNumbers : true, matchWordHighlight : true, // options: true, false, "onselected" @@ -76,40 +111,48 @@ dialogDraggable : true, dialogMaskBgColor : "#fff", dialogMaskOpacity : 0.1, + fontSize : "13px", + saveHTMLToTextarea : false, + onload : function() {}, + onresize : function() {}, onchange : function() {}, + onwatch : null, + onunwatch : null, + onpreviewing : function() {}, + onpreviewed : function() {}, onfullscreen : function() {}, onfullscreenExit : function() {}, + onscroll : function() {}, + onpreviewscroll : function() {}, + imageUpload : false, imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"], imageUploadURL : "", crossDomainUpload : false, uploadCallbackURL : "", - saveHTMLToTextarea : false, - toc : true, + + toc : true, // Table of contents tocStartLevel : 1, // Said from H1 to create ToC - fontSize : "13px", - htmlDecode : false, // Open the HTML tag identification - tex : false, + htmlDecode : false, // Open the HTML tag identification + taskList : false, // Enable Github Flavored Markdown task lists + emoji : false, // :emoji: , Support Github emoji, Twitter Emoji (Twemoji); + // Support FontAwesome icon emoji :fa-xxx: > Using fontAwesome icon web fonts; + // Support Editor.md logo icon emoji :editormd-logo: :editormd-logo-1x: > 1~8x; + tex : false, // TeX(LaTeX), based on KaTeX flowChart : false, // flowChart.js only support IE9+ sequenceDiagram : false, // sequenceDiagram.js only support IE9+ previewCodeHighlight : true, - inRequirejs : false, - toolbar : true, + + inRequirejs : false, // if using Require.js, you must set true value. + + toolbar : true, // show/hide toolbar toolbarIcons : function() { - return [ - "undo", "redo", "|", - "bold", "del", "italic", "quote", "|", - "h1", "h2", "h3", "h4", "h5", "h6", "|", - "list-ul", "list-ol", "hr", "|", - "link", "anchor", "image", "code", "code-block-tab", "code-block", "datetime", "|", - "watch", "preview", "fullscreen", "clear", "|", - "info" - ] + return editormd.toolbarModes.full; // return array }, toolbarTitles : {}, toolbarHandlers : {}, - + toolbarCustomIcons : {}, // using html tag create toolbar icon, unused default tag. toolbarIconsClass : { undo : "fa-undo", redo : "fa-repeat", @@ -130,18 +173,22 @@ anchor : "fa-anchor", image : "fa-picture-o", code : "fa-code", - "code-block-tab" : "fa-file-code-o", + "preformatted-text" : "fa-file-code-o", "code-block" : "fa-file-code-o", + table : "fa-table", datetime : "fa-clock-o", + emoji : "fa-smile-o", + htmlEntities : "fa-copyright", watch : "fa-eye-slash", unwatch : "fa-eye", preview : "fa-search", fullscreen : "fa-arrows-alt", clear : "fa-eraser", + help : "fa-question-circle", info : "fa-info-circle" - }, - + }, toolbarIconTexts : {}, + lang : { name : "zh-cn", description : "开源在线Markdown编辑器
          A simple markdown doucment online editor.", @@ -163,29 +210,33 @@ hr : "横线", link : "链接", anchor : "锚点", - image : "图片", + image : "添加图片", code : "行内代码", - "code-block-tab" : "预格式文本 / 代码块(缩进风格)", + "preformatted-text" : "预格式文本 / 代码块(缩进风格)", "code-block" : "代码块(多语言风格)", + table : "添加表格", datetime : "日期时间", + emoji : "Emoji表情", + htmlEntities : "HTML实体字符", watch : "关闭实时预览", unwatch : "开启实时预览", preview : "全窗口预览HTML(可按ESC还原)", fullscreen : "全屏(按ESC还原)", clear : "清空", + help : "使用帮助", info : "关于" + editormd.title }, buttons : { enter : "确定", - cancel : "取消" + cancel : "取消", + close : "关闭" }, dialog : { link : { title : "添加链接", url : "链接地址", urlTitle : "链接标题", - urlEmpty : "错误:请填写链接地址。", - titleEmpty : "错误:请填写链接标题。" + urlEmpty : "错误:请填写链接地址。" }, anchor : { title : "添加锚点链接", @@ -206,9 +257,9 @@ uploadFileEmpty : "错误:上传的图片不能为空。", formatNotAllowed : "错误:只允许上传图片文件,允许上传的图片文件格式有:" }, - tabCodeBlock : { + preformattedText : { title : "添加预格式文本或代码块", - codeEmptyAlert : "错误:请填写预格式文本或代码的内容。" + emptyAlert : "错误:请填写预格式文本或代码的内容。" }, codeBlock : { title : "添加代码块", @@ -217,6 +268,12 @@ otherLanguage : "其他语言", unselectedLanguageAlert : "错误:请选择代码所属的语言类型。", codeEmptyAlert : "错误:请填写代码内容。" + }, + htmlEntities : { + title : "HTML 实体字符" + }, + help : { + title : "使用帮助" } } } @@ -225,7 +282,7 @@ editormd.classNames = { tex : editormd.classPrefix + "tex" }; - + editormd.dialogZindex = 99999; editormd.$katex = null; @@ -243,6 +300,8 @@ /** * 构造函数/实例初始化 + * Constructor / instance initialization + * * @param {String} id 编辑器的ID * @param {Object} [options={}] 配置选项 Key/Value * @returns {editormd} 返回editormd的实例对象 @@ -298,26 +357,43 @@ editor.append(appendElements).addClass(classPrefix + "vertical"); + this.mask = editor.children("." + classPrefix + "mask"); + if (settings.markdown !== "") { markdownTextarea.val(settings.markdown); } - this.htmlTextarea = editor.find("." + classNames.textarea.html); - - this.preview = editor.find("." + classPrefix + "preview"); + this.htmlTextarea = editor.children("." + classNames.textarea.html); + this.preview = editor.children("." + classPrefix + "preview"); this.previewContainer = this.preview.children("." + classPrefix + "preview-container"); - this.toolbarIconHandlers = {}; - if (!settings.inRequirejs) + if (typeof define === "function" && define.amd) { - this.loadQueues(); + if (typeof katex !== "undefined") + { + editormd.$katex = katex; + } + + if (settings.searchReplace) + { + editormd.loadCSS(settings.path + "codemirror/addon/dialog/dialog"); + editormd.loadCSS(settings.path + "codemirror/addon/search/matchesonscrollbar"); + } + } + + if (typeof define === "function" || !settings.autoLoadModules) + { + if (typeof CodeMirror !== "undefined") editormd.$CodeMirror = CodeMirror; + if (typeof marked !== "undefined") editormd.$marked = marked; + + _this.setCodeMirror(); + _this.setToolbar(); + _this.loadedDisplay(); } else { - _this.setCodeMirror(); - _this.setToolbar(); - _this.setMarked().loadedDisplay(); + this.loadQueues(); } return this; @@ -325,6 +401,8 @@ /** * 所需组件加载队列 + * Required components loading queue + * * @returns {editormd} 返回editormd的实例对象 */ @@ -337,7 +415,7 @@ if (editormd.isIE8) { - _this.setMarked().loadedDisplay(); + _this.loadedDisplay(); return ; } @@ -351,14 +429,14 @@ if (!settings.flowChart && settings.sequenceDiagram) { editormd.loadScript(loadPath + "sequence-diagram.min", function() { - _this.setMarked().loadedDisplay(); + _this.loadedDisplay(); }); } else if (settings.flowChart && !settings.sequenceDiagram) { editormd.loadScript(loadPath + "flowchart.min", function() { editormd.loadScript(loadPath + "jquery.flowchart.min", function() { - _this.setMarked().loadedDisplay(); + _this.loadedDisplay(); }); }); } @@ -367,7 +445,7 @@ editormd.loadScript(loadPath + "flowchart.min", function() { editormd.loadScript(loadPath + "jquery.flowchart.min", function() { editormd.loadScript(loadPath + "sequence-diagram.min", function() { - _this.setMarked().loadedDisplay(); + _this.loadedDisplay(); }); }); }); @@ -378,11 +456,23 @@ } else { - _this.setMarked().loadedDisplay(); + _this.loadedDisplay(); } }; - editormd.loadCSS(loadPath + "codemirror/codemirror.min"); + editormd.loadCSS(loadPath + "codemirror/codemirror.min"); + + if (settings.searchReplace) + { + editormd.loadCSS(loadPath + "codemirror/addon/dialog/dialog"); + editormd.loadCSS(loadPath + "codemirror/addon/search/matchesonscrollbar"); + } + + if (settings.codeFold) + { + editormd.loadCSS(loadPath + "codemirror/addon/fold/foldgutter"); + } + editormd.loadScript(loadPath + "codemirror/codemirror.min", function() { editormd.$CodeMirror = CodeMirror; @@ -391,7 +481,15 @@ editormd.loadScript(loadPath + "codemirror/addons.min", function() { - _this.setCodeMirror(); + _this.setCodeMirror(); + + if (settings.mode !== "gfm" && settings.mode !== "markdown") + { + _this.loadedDisplay(); + + return false; + } + _this.setToolbar(); editormd.loadScript(loadPath + "marked.min", function() { @@ -419,38 +517,74 @@ return this; }, + /** + * 设置CodeMirror的主题 + * Setting CodeMirror theme + * + * @returns {editormd} 返回editormd的实例对象 + */ + + setTheme : function(theme) { + var settings = this.settings; + settings.theme = theme; + + if (theme !== "default") + { + editormd.loadCSS(settings.path + "codemirror/theme/" + settings.theme); + } + + this.cm.setOption("theme", theme); + + return this; + }, + /** * 配置和初始化CodeMirror组件 + * CodeMirror initialization + * * @returns {editormd} 返回editormd的实例对象 */ setCodeMirror : function() { var settings = this.settings; var editor = this.editor; + + if (settings.theme !== "default") + { + editormd.loadCSS(settings.path + "codemirror/theme/" + settings.theme); + } + var codeMirrorConfig = { mode : settings.mode, - theme : "default", + theme : settings.theme, tabSize : 4, dragDrop : false, autofocus : true, + autoCloseTags : settings.autoCloseTags, readOnly : (settings.readOnly) ? "nocursor" : false, indentUnit : 4, lineNumbers : settings.lineNumbers, lineWrapping : true, + extraKeys : {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }}, + foldGutter : settings.codeFold, + gutters : ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], matchBrackets : true, indentWithTabs : true, styleActiveLine : settings.styleActiveLine, styleSelectedText : true, autoCloseBrackets : true, showTrailingSpace : true, - highlightSelectionMatches : ( (!settings.matchWordHighlight) ? false : { - showToken: (settings.matchWordHighlight == "onselected") ? false : /\w/ - }) + highlightSelectionMatches : ( (!settings.matchWordHighlight) ? false : { showToken: (settings.matchWordHighlight == "onselected") ? false : /\w/ } ) }; - this.codeEditor = editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0], codeMirrorConfig); - this.codeMirror = editor.find(".CodeMirror"); + this.codeEditor = this.cm = editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0], codeMirrorConfig); + this.codeMirror = this.cmElement = editor.children(".CodeMirror"); + if (settings.value !== "") + { + this.cm.setValue(settings.value); + } + this.codeMirror.css({ fontSize : settings.fontSize, width : (!settings.watch) ? "100%" : "50%" @@ -459,39 +593,209 @@ return this; }, + /** + * 获取CodeMirror的配置选项 + * Get CodeMirror setting options + * + * @returns {Mixed} return CodeMirror setting option value + */ + + getCodeMirrorOption : function(key) { + return this.cm.getOption(key); + }, + + /** + * 配置和重配置CodeMirror的选项 + * CodeMirror setting options / resettings + * + * @returns {editormd} 返回editormd的实例对象 + */ + + setCodeMirrorOption : function(key, value) { + + this.cm.setOption(key, value); + + return this; + }, + + addKeyMap : function(map, bottom) { + this.cm.addKeyMap(map, bottom); + + return this; + }, + + removeKeyMap : function(map) { + this.cm.removeKeyMap(map); + + return this; + }, + + /** + * 扩展当前实例对象,可同时设置多个或者只设置一个 + * Extend editormd instance object, can mutil setting. + * + * @returns {editormd} this(editormd instance object.) + */ + + extends : function() { + if (typeof arguments[1] !== "undefined") + { + if (typeof arguments[1] == "function") + { + arguments[1] = $.proxy(arguments[1], this); + } + + this[arguments[0]] = arguments[1]; + } + + if (typeof arguments[0] === "object" && typeof arguments[0].length === "undefined") + { + $.extend(true, this, arguments[0]); + } + + return this; + }, + + /** + * 设置或扩展当前实例对象,单个设置 + * Extend editormd instance object, one by one + * + * @param {String|Object} key option key + * @param {String|Object} value option value + * @returns {editormd} this(editormd instance object.) + */ + + set : function (key, value) { + + if (typeof value !== "undefined" && typeof value == "function") + { + value = $.proxy(value, this); + } + + this[key] = value; + + return this; + }, + + /** + * 重新配置 + * Resetting editor options + * + * @param {String|Object} key option key + * @param {String|Object} value option value + * @returns {editormd} this(editormd instance object.) + */ + + config : function(key, value) { + var settings = this.settings; + + if (typeof key == "object") + { + settings = $.extend(true, settings, key); + } + + if (typeof key == "string") + { + settings[key] = value; + } + + this.settings = settings; + this.recreate(); + + return this; + }, + + /** + * 注册事件处理方法 + * Bind editor event handle + * + * @param {String} eventType event type + * @param {Function} callback 回调函数 + * @returns {editormd} this(editormd instance object.) + */ + + on : function(eventType, callback) { + var settings = this.settings; + + if (typeof settings["on" + eventType] !== "undefined") + { + settings["on" + eventType] = $.proxy(callback, this); + } + + return this; + }, + + /** + * 解除事件处理方法 + * Unbind editor event handle + * + * @param {String} eventType event type + * @returns {editormd} this(editormd instance object.) + */ + + off : function(eventType) { + var settings = this.settings; + + if (typeof settings["on" + eventType] !== "undefined") + { + settings["on" + eventType] = function(){}; + } + + return this; + }, + /** * 显示工具栏 + * Display toolbar + * + * @param {Function} [callback=function(){}] 回调函数 * @returns {editormd} 返回editormd的实例对象 */ - showToolbar : function() { + showToolbar : function(callback) { var settings = this.settings; + if(settings.readOnly) return ; + if (settings.toolbar && (this.toolbar.length < 1 || this.toolbar.find("." + this.classPrefix + "menu").html() === "") ) + { + this.setToolbar(); + } + settings.toolbar = true; + this.toolbar.show(); this.resize(); + + $.proxy(callback || function(){}, this)(); return this; }, /** * 隐藏工具栏 - * @returns {editormd} 返回editormd的实例对象 + * Hide toolbar + * + * @param {Function} [callback=function(){}] 回调函数 + * @returns {editormd} this(editormd instance object.) */ - hideToolbar : function() { - var settings = this.settings; + hideToolbar : function(callback) { + var settings = this.settings; settings.toolbar = false; this.toolbar.hide(); this.resize(); + + $.proxy(callback || function(){}, this)(); return this; }, /** * 配置和初始化工具栏 + * Set toolbar and Initialization + * * @returns {editormd} 返回editormd的实例对象 */ @@ -504,9 +808,13 @@ var preview = this.preview; var classPrefix = this.classPrefix; - editor.append('
            '); + var toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); - var toolbar = this.toolbar = editor.find("." + classPrefix + "toolbar"); + if (settings.toolbar && toolbar.length < 1) + { + editor.append('
              '); + toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); + } if (!settings.toolbar) { @@ -514,12 +822,14 @@ return ; } - else - { - toolbar.show(); - } + //else + //{ + toolbar.show(); + //} + + var icons = (typeof settings.toolbarIcons === "function") ? settings.toolbarIcons() + : ((typeof settings.toolbarIcons === "string") ? editormd.toolbarModes[settings.toolbarIcons] : settings.toolbarIcons); - var icons = settings.toolbarIcons(); var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; for (var i = 0, len = icons.length; i < len; i++) @@ -543,8 +853,20 @@ iconTexts = (typeof iconTexts === "undefined") ? "" : iconTexts; iconClass = (typeof iconClass === "undefined") ? "" : iconClass; - menu += "
            • " + - ""+((isHeader) ? name : ( (iconClass === "") ? iconTexts : "") ) + "
            • "; + menu += "
            • "; + + if (typeof settings.toolbarCustomIcons[name] !== "undefined") + { + menu += settings.toolbarCustomIcons[name]; + } + else + { + menu += "" + + ""+((isHeader) ? name : ( (iconClass === "") ? iconTexts : "") ) + "" + + ""; + } + + menu += "
            • "; } else { @@ -561,975 +883,110 @@ /** * 工具栏图标事件处理对象序列 + * Get toolbar icons event handlers + * * @param {Object} cm CodeMirror的实例对象 * @param {String} name 要获取的事件处理器名称 * @returns {Object} 返回处理对象序列 */ + + dialogLockScreen : function() { + $.proxy(editormd.dialogLockScreen, this)(); + + return this; + }, + + dialogShowMask : function(dialog) { + $.proxy(editormd.dialogShowMask, this)(dialog); + + return this; + }, + + getToolbarHandles : function(name) { + var toolbarHandlers = this.toolbarHandlers = editormd.toolbarHandlers; + + return (name && typeof toolbarIconHandlers[name] !== "undefined") ? toolbarHandlers[name] : toolbarHandlers; + }, + + /** + * 工具栏图标事件处理器 + * Bind toolbar icons event handle + * + * @returns {editormd} 返回editormd的实例对象 + */ - getToolbarHandles : function(name) { - var _this = this; - var settings = this.settings; - var lang = settings.lang; - var editor = this.editor; - var classPrefix = this.classPrefix; + setToolbarHandler : function() { + var _this = this; + var settings = this.settings; - var dialogLockScreen = function() { - if (settings.dialogLockScreen) { - $("html,body").css("overflow", "hidden"); - } - }; + if (!settings.toolbar || settings.readOnly) { + return ; + } - var dialogShowMask = function(dialog) { - dialog.css({ - top : ($(window).height() - dialog.height()) / 2 + "px", - left : ($(window).width() - dialog.width()) / 2 + "px" - }); + var editor = this.editor; + var preview = this.preview; + var toolbar = this.toolbar; + var codeEditor = this.codeEditor; + var codeMirror = this.codeMirror; + var classPrefix = this.classPrefix; + var previewContainer = this.previewContainer; + var toolbarIcons = this.toolbarIcons = toolbar.find("." + classPrefix + "menu a"); + var toolbarIconHandlers = this.getToolbarHandles(); - if (settings.dialogShowMask) { - editor.find("." + classPrefix + "mask").css("z-index", parseInt(dialog.css("z-index")) - 1).show(); - } - }; - - var toolbarHandlers = this.toolbarHandlers = { - undo : function(cm) { - cm.undo(); - }, - redo : function(cm) { - cm.redo(); - }, - bold : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("**" + selection + "**"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - del : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("~~" + selection + "~~"); + toolbarIcons.bind(editormd.mouseOrTouch("click", "touchend"), function(event) { - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, + var icon = $(this).children(".fa"); + var name = icon.attr("name"); + var cursor = codeEditor.getCursor(); + var selection = codeEditor.getSelection(); - italic : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("*" + selection + "*"); + if (name === "") { + return ; + } + + _this.activeIcon = icon; - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); + if (typeof toolbarIconHandlers[name] !== "undefined") + { + $.proxy(toolbarIconHandlers[name], _this)(codeEditor); + } + else + { + if (typeof settings.toolbarHandlers[name] !== "undefined") + { + $.proxy(settings.toolbarHandlers[name], _this)(codeEditor, icon, cursor, selection); } - }, + } + + if (name !== "link" && name !== "anchor" && name !== "image" && name !== "code-block" && + name !== "preformatted-text" && name !== "watch" && name !== "preview" && name !== "fullscreen" && name !== "info") + { + codeEditor.focus(); + } - quote : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("> " + selection); - cm.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); - }, - - h1 : function(cm) { - var selection = cm.getSelection(); - - cm.replaceSelection("# " + selection); - }, - - h2 : function(cm) { - var selection = cm.getSelection(); - - cm.replaceSelection("## " + selection); - }, - - h3 : function(cm) { - var selection = cm.getSelection(); - - cm.replaceSelection("### " + selection); - }, - - h4 : function(cm) { - var selection = cm.getSelection(); - - cm.replaceSelection("#### " + selection); - }, - - h5 : function(cm) { - var selection = cm.getSelection(); - - cm.replaceSelection("##### " + selection); - }, - - h6 : function(cm) { - var selection = cm.getSelection(); - - cm.replaceSelection("###### " + selection); - }, - - "list-ul" : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (selection === "") - { - cm.replaceSelection("- " + selection); - } - else - { - var selectionText = selection.split("\n"); - - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; - } - - cm.replaceSelection(selectionText.join("\n")); - } - }, - - "list-ol" : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if(selection === "") - { - cm.replaceSelection("1. " + selection); - } - else - { - var selectionText = selection.split("\n"); - - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : (i+1) + ". " + selectionText[i]; - } - - cm.replaceSelection(selectionText.join("\n")); - } - }, - - hr : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("------------"); - }, - - link : function(cm) { - var selection = cm.getSelection(); - var linkLang = lang.dialog.link; - var linkDialogName = classPrefix + "link-dialog", linkDialog; - - if (editor.find("." + linkDialogName).length > 0) - { - linkDialog = editor.find("." + linkDialogName); - linkDialog.find("[data-url]").val("http://"); - linkDialog.find("[data-title]").val(selection); - - dialogShowMask(linkDialog); - dialogLockScreen(); - linkDialog.show(); - } - else - { - var linkDialogHTML = "
              " + - "" + - "" + - "
              " + - "" + - "" + - "
              " + - "
              "; - - linkDialog = _this.createDialog({ - title : linkLang.title, - width : 380, - height : 210, - content : linkDialogHTML, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var url = this.find("[data-url]").val(); - var title = this.find("[data-title]").val(); - - if (url === "http://" || url === "") - { - alert(linkLang.urlEmpty); - return false; - } - - if (title === "") - { - alert(linkLang.titleEmpty); - return false; - } - - cm.replaceSelection("[" + title + "](" + url + " \""+title+"\")"); - - this.hide().lockScreen(false).hideMask(); - - return false; - }], - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - return false; - }] - } - }); - } - }, - - anchor : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var anchorLang = lang.dialog.anchor; - var anchorDialogName = classPrefix + "anchor-dialog", anchorDialog; - - if (editor.find("." + anchorDialogName).length > 0) - { - anchorDialog = editor.find("." + anchorDialogName); - anchorDialog.find("[data-name]").val(""); - anchorDialog.find("[data-url]").val("http://"); - anchorDialog.find("[data-title]").val(selection); - - dialogShowMask(anchorDialog); - dialogLockScreen(); - anchorDialog.show(); - } - else - { - var anchorDialogHTML = "
              " + - "" + - "" + - "
              " + - "" + - "" + - "
              " + - "" + - "" + - "
              " + - "
              "; - - anchorDialog = _this.createDialog({ - name : anchorDialogName, - title : anchorLang.title, - width : 380, - height : 250, - content : anchorDialogHTML, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var name = this.find("[data-name]").val(); - var url = this.find("[data-url]").val(); - var title = this.find("[data-title]").val(); - - if (name === "") - { - alert(anchorLang.nameEmpty); - return false; - } - - if (url === "http://" || url === "") - { - alert(anchorLang.urlEmpty); - return false; - } - - if (title === "") - { - alert(anchorLang.titleEmpty); - return false; - } - - cm.replaceSelection("[" + title + "][" + name + "]\n[" + name + "]: " + url + ""); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - - this.hide().lockScreen(false).hideMask(); - - return false; - }], - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - return false; - }] - } - }); - } - }, - - image : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var imageLang = lang.dialog.image; - var iframeName = classPrefix + "image-iframe"; - var imageDialogName = classPrefix + "image-dialog", imageDialog; - - if (editor.find("." + imageDialogName).length > 0) - { - imageDialog = editor.find("." + imageDialogName); - imageDialog.find("[type=\"text\"]").val(""); - imageDialog.find("[type=\"file\"]").val(""); - imageDialog.find("[data-link]").val("http://"); - - dialogShowMask(imageDialog); - dialogLockScreen(); - imageDialog.show(); - } - else - { - var guid = (new Date).getTime(); - var action = settings.imageUploadURL + "?guid=" + guid; - - if (settings.crossDomainUpload) - { - action += "&callback=" + settings.uploadCallbackURL + "&dialog_id=editormd-image-dialog-" + guid; - } - - var imageDialogHTML = ( (settings.imageUpload) ? "
              " : "
              " ) + - ( (settings.imageUpload) ? "" : "" ) + - "" + - "" + (function(){ - return (settings.imageUpload) ? "
              " + - "" + - "" + - "
              " : ""; - })() + - "
              " + - "" + - "" + - "
              " + - "" + - "" + - "
              " + - ( (settings.imageUpload) ? "" : "
              "); - - //var imageFooterHTML = ""; - - imageDialog = _this.createDialog({ - title : imageLang.title, - width : (settings.imageUpload) ? 465 : 380, - height : 250, - name : imageDialogName, - content : imageDialogHTML, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var url = this.find("[data-url]").val(); - var alt = this.find("[data-alt]").val(); - var link = this.find("[data-link]").val(); - - if (url === "") - { - alert(imageLang.imageURLEmpty); - return false; - } - - if (link === "" || link === "http://") - { - cm.replaceSelection("![" + alt + "](" + url + " \"" + alt + "\")"); - } - else - { - cm.replaceSelection("[![" + alt + "](" + url + " \"" + alt + "\")](" + link + " \"" + alt + "\")"); - } - - if (alt === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - - this.hide().lockScreen(false).hideMask(); - - return false; - }], - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - return false; - }] - } - }); - - imageDialog.attr("id", classPrefix + "image-dialog-" + guid); - } - - var fileInput = imageDialog.find("[name=\"" + classPrefix + "image-file\"]"); - - fileInput.bind("change", function() { - var fileName = fileInput.val(); - var isImage = new RegExp("(\\.(" + settings.imageFormats.join("|") + "))$"); // /(\.(webp|jpg|jpeg|gif|bmp|png))$/ - - if (fileName === "") - { - alert(imageLang.uploadFileEmpty); - } - else if (!isImage.test(fileName)) - { - alert(imageLang.formatNotAllowed + settings.imageFormats.join(", ")); - } - else - { - imageDialog.loading(true); - - var submitHandler = function() { - - var uploadIframe = document.getElementById(iframeName); - - uploadIframe.onload = function() { - imageDialog.loading(false); - - var json = uploadIframe.contentWindow.document.body.innerHTML; - json = (typeof JSON.parse !== "undefined") ? JSON.parse(json) : eval("(" + json + ")"); - - if (json.success === 1) - { - imageDialog.find("[data-url]").val(json.url); - } - else - { - alert(json.message); - } - - return false; - }; - }; - - imageDialog.find("[type=\"submit\"]").bind(editormd.mouseOrTouch("click", "touchend"), submitHandler).trigger("click"); - - } - - return false; - }); - }, - - code : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("`" + selection + "`"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - - }, - - "code-block-tab" : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var tabCodeBlockDialogName = classPrefix + "dialog-tab-code-block", tabCodeBlockDialog; - - if (editor.find("." + tabCodeBlockDialogName).length > 0) - { - tabCodeBlockDialog = editor.find("." + tabCodeBlockDialogName); - tabCodeBlockDialog.find("textarea").val(selection); - - dialogShowMask(tabCodeBlockDialog); - dialogLockScreen(); - tabCodeBlockDialog.show(); - } - else - { - var tabCodeBlockDialogHTML = ""; - - tabCodeBlockDialog = _this.createDialog({ - name : tabCodeBlockDialogName, - title : lang.dialog.tabCodeBlock.title, - width : 750, - height : 470, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - content : tabCodeBlockDialogHTML, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var codeTexts = this.find("textarea").val(); - - if (codeTexts === "") - { - alert(lang.dialog.tabCodeBlock.codeEmptyAlert); - return false; - } - - codeTexts = codeTexts.split("\n"); - - for (var i in codeTexts) - { - codeTexts[i] = " " + codeTexts[i]; - } - - cm.replaceSelection(codeTexts.join("\n")); - - this.hide().lockScreen(false).hideMask(); - - return false; - }], - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - return false; - }] - } - }); - } - }, - - "code-block" : function(cm) { - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var codeBlockDialogName = classPrefix + "dialog-code-block", codeBlockDialog; - - if (editor.find("." + codeBlockDialogName).length > 0) - { - codeBlockDialog = editor.find("." + codeBlockDialogName); - codeBlockDialog.find("option:first").attr("selected", "selected"); - codeBlockDialog.find("textarea").val(selection); - - dialogShowMask(codeBlockDialog); - dialogLockScreen(); - codeBlockDialog.show(); - } - else - { - var codeBlockDialogHTML = "
              " + - lang.dialog.codeBlock.selectLabel + "" + - "
              " + - ""; - - codeBlockDialog = _this.createDialog({ - name : codeBlockDialogName, - title : lang.dialog.codeBlock.title, - width : 752, - height : 565, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - content : codeBlockDialogHTML, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var codeTexts = this.find("textarea").val(); - var langName = this.find("select").val(); - - if (langName === "") - { - alert(lang.dialog.codeBlock.unselectedLanguageAlert); - return false; - } - - if (codeTexts === "") - { - alert(lang.dialog.codeBlock.codeEmptyAlert); - return false; - } - - langName = (langName === "other") ? "" : langName; - - cm.replaceSelection(["```" + langName, codeTexts, "```"].join("\n")); - - if (langName === "") { - cm.setCursor(cursor.line, cursor.ch + 3); - } - - this.hide().lockScreen(false).hideMask(); - - return false; - }], - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - return false; - }] - } - }); - - var langSelect = codeBlockDialog.find("select"); - - for (var key in editormd.codeLanguages) - { - var codeLang = editormd.codeLanguages[key]; - langSelect.append(""); - } - - langSelect.append(""); - } - }, - - datetime : function(cm) { - var selection = cm.getSelection(); - var date = new Date(); - var langName = settings.lang.name; - var datefmt = editormd.dateFormat() + " " + editormd.dateFormat((langName === "zh-cn" || langName === "zh-tw") ? "cn-week-day" : "week-day"); - - cm.replaceSelection(datefmt); - }, - - watch : function(cm) { - _this[_this.settings.watch ? "unwatch" : "watch"](); - }, - - preview : function(cm) { - - _this.previewing(); - }, - - fullscreen : function(cm) { - - _this.fullscreen(); - }, - - clear : function(cm) { - _this.clear(); - }, - - info : function(cm) { - _this.showInfoDialog(); - } - }; - - return (name && typeof toolbarIconHandlers[name] !== "undefined") ? toolbarHandlers[name] : toolbarHandlers; - }, - - /** - * 工具栏图标事件处理器 - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbarHandler : function() { - var _this = this; - var settings = this.settings; - - if (!settings.toolbar || settings.readOnly) { - return ; - } - - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var codeEditor = this.codeEditor; - var codeMirror = this.codeMirror; - var classPrefix = this.classPrefix; - var previewContainer = this.previewContainer; - var toolbarIcons = this.toolbarIcons = toolbar.find("." + classPrefix + "menu a"); - - toolbarIcons.bind(editormd.mouseOrTouch("click", "touchend"), function(event) { - - var icon = $(this).children(".fa"); - var name = icon.attr("name"); - var cursor = codeEditor.getCursor(); - var selection = codeEditor.getSelection(); - var toolbarIconHandlers = _this.getToolbarHandles(); - - if (name === "") { - return ; - } - - _this.activeIcon = icon; - - if (typeof toolbarIconHandlers[name] !== "undefined") - { - toolbarIconHandlers[name](codeEditor); - } - else - { - if (typeof settings.toolbarHandlers[name] !== "undefined") - { - $.proxy(settings.toolbarHandlers[name], _this)(codeEditor, icon, cursor, selection); - } - } - - if (name !== "link" && name !== "anchor" && name !== "image" && name !== "code-block" && name !== "code-block-tab" && name !== "watch" && name !== "preview" && name !== "fullscreen" && name !== "info") - { - codeEditor.focus(); - } - - return false; - - }); - - return this; - }, - - /** - * 动态创建对话框 - * @param {Object} options 配置项键值对 Key/Value - * @returns {dialog} 返回创建的dialog的jQuery实例对象 - */ - - createDialog : function(options) { - var defaults = { - name : "", - width : 420, - height: 240, - title : "", - drag : true, - closed : true, - content : "", - mask : true, - maskStyle : { - backgroundColor : "#fff", - opacity : 0.1 - }, - lockScreen : true, - footer : true, - buttons : false - }; - - options = $.extend(true, defaults, options); - - var editor = this.editor; - var classPrefix = this.classPrefix; - var guid = (new Date).getTime(); - var dialogName = ( (options.name === "") ? classPrefix + "dialog-" + guid : options.name); - var mouseOrTouch = editormd.mouseOrTouch; - - var html = "
              "; - - if (options.title !== "") - { - html += "
              "; - html += "" + options.title + ""; - html += "
              "; - } - - if (options.closed) - { - html += ""; - } - - html += "
              " + options.content; - - if (options.footer || typeof options.footer === "string") - { - html += "
              " + ( (typeof options.footer === "boolean") ? "" : options.footer) + "
              "; - } - - html += "
              "; - - html += "
              "; - html += "
              "; - html += "
              "; - - editor.append(html); - - var dialog = editor.find("." + dialogName); - - dialog.lockScreen = function(lock) { - if (options.lockScreen) - { - $("html,body").css("overflow", (lock) ? "hidden" : ""); - } - - return dialog; - }; - - dialog.showMask = function() { - if (options.mask) - { - editor.find("." + classPrefix + "mask").css(options.maskStyle).css("z-index", editormd.dialogZindex - 1).show(); - } - return dialog; - }; - - dialog.hideMask = function() { - if (options.mask) - { - editor.find("." + classPrefix + "mask").hide(); - } - - return dialog; - }; - - dialog.loading = function(show) { - var loading = dialog.find("." + classPrefix + "dialog-mask"); - loading[(show) ? "show" : "hide"](); - - return dialog; - }; - - dialog.lockScreen(true).showMask(); - - dialog.show().css({ - zIndex : editormd.dialogZindex, - border : (editormd.isIE8) ? "1px solid #ddd" : "", - width : (typeof options.width === "number") ? options.width + "px" : options.width, - height : (typeof options.height === "number") ? options.height + "px" : options.height - }); - - var dialogPosition = function(){ - dialog.css({ - top : ($(window).height() - dialog.height()) / 2 + "px", - left : ($(window).width() - dialog.width()) / 2 + "px" - }); - }; - - dialogPosition(); - - $(window).resize(dialogPosition); - - dialog.children("." + classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { - dialog.hide().lockScreen(false).hideMask(); - }); - - if (typeof options.buttons == "object") - { - var footer = dialog.footer = dialog.find("." + classPrefix + "dialog-footer"); - - for (var key in options.buttons) - { - var btn = options.buttons[key]; - var btnClassName = classPrefix + key + "-btn"; - - footer.append(""); - btn[1] = $.proxy(btn[1], dialog); - footer.children("." + btnClassName).bind(mouseOrTouch("click", "touchend"), btn[1]); - } - } - - if (options.title !== "" && options.drag) - { - var posX, posY; - var dialogHeader = dialog.children("." + classPrefix + "dialog-header"); - - if (!options.mask) { - dialogHeader.bind(mouseOrTouch("click", "touchend"), function(){ - editormd.dialogZindex += 2; - dialog.css("z-index", editormd.dialogZindex); - }); - } - - dialogHeader.mousedown(function(e) { - e = e || window.event; //IE - posX = e.clientX - parseInt(dialog[0].style.left); - posY = e.clientY - parseInt(dialog[0].style.top); - - document.onmousemove = moveAction; - }); - - var userCanSelect = function (obj) { - obj.removeClass(classPrefix + "user-unselect").off("selectstart"); - } - - var userUnselect = function (obj) { - obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) { // selectstart for IE - return false; - }); - } - - var moveAction = function (e) { - e = e || window.event; //IE - - var left, top, nowLeft = parseInt(dialog[0].style.left), nowTop = parseInt(dialog[0].style.top); - - if( nowLeft >= 0 ) { - if( nowLeft + dialog.width() <= $(window).width()) { - left = e.clientX - posX; - } else { - left = $(window).width() - dialog.width(); - document.onmousemove = null; - } - } else { - left = 0; - document.onmousemove = null; - } - - if( nowTop >= 0 ) { - top = e.clientY - posY; - } else { - top = 0; - document.onmousemove = null; - } - - - document.onselectstart = function() { - return false; - }; - - userUnselect($("body")); - userUnselect(dialog); - dialog[0].style.left = left + "px"; - dialog[0].style.top = top + "px"; - } - - document.onmouseup = function() { - userCanSelect($("body")); - userCanSelect(dialog); - - document.onselectstart = null; - document.onmousemove = null; - }; - - dialogHeader.touchDraggable = function() { - var offset = null; - var start = function(e) { - var orig = e.originalEvent; - var pos = $(this).parent().position(); - - offset = { - x : orig.changedTouches[0].pageX - pos.left, - y : orig.changedTouches[0].pageY - pos.top - }; - }; - - var move = function(e) { - e.preventDefault(); - var orig = e.originalEvent; - - $(this).parent().css({ - top : orig.changedTouches[0].pageY - offset.y, - left : orig.changedTouches[0].pageX - offset.x - }); - }; - - this.bind("touchstart", start).bind("touchmove", move); - }; - - dialogHeader.touchDraggable(); - } + return false; - editormd.dialogZindex += 2; + }); - return dialog; + return this; + }, + + /** + * 动态创建对话框 + * Creating custom dialogs + * + * @param {Object} options 配置项键值对 Key/Value + * @returns {dialog} 返回创建的dialog的jQuery实例对象 + */ + + createDialog : function(options) { + return $.proxy(editormd.createDialog, this)(options); }, /** * 创建关于Editor.md的对话框 + * Create about Editor.md dialog + * * @returns {editormd} 返回editormd的实例对象 */ @@ -1552,13 +1009,13 @@ editor.append(infoDialogHTML); - var infoDialog = this.infoDialog = editor.find("." + classPrefix + "dialog-info"); + var infoDialog = this.infoDialog = editor.children("." + classPrefix + "dialog-info"); infoDialog.find("." + classPrefix + "dialog-close").bind(editormd.mouseOrTouch("click", "touchend"), function() { _this.hideInfoDialog(); }); - infoDialog.css("border", (editormd.isIE8) ? "1px solid #ddd" : "").show(); + infoDialog.css("border", (editormd.isIE8) ? "1px solid #ddd" : "").css("z-index", editormd.dialogZindex).show(); this.infoDialogPosition(); @@ -1567,6 +1024,8 @@ /** * 关于Editor.md对话居中定位 + * Editor.md dialog position handle + * * @returns {editormd} 返回editormd的实例对象 */ @@ -1589,6 +1048,8 @@ /** * 显示关于Editor.md + * Display about Editor.md dialog + * * @returns {editormd} 返回editormd的实例对象 */ @@ -1598,15 +1059,23 @@ var _this = this; var editor = this.editor; + var settings = this.settings; var classPrefix = this.classPrefix; - var infoDialog = this.infoDialog = editor.find("." + classPrefix + "dialog-info"); + var infoDialog = this.infoDialog = editor.children("." + classPrefix + "dialog-info"); if (infoDialog.length < 1) { this.createInfoDialog(); } + + this.lockScreen(true); + + this.mask.css({ + opacity : settings.dialogMaskOpacity, + backgroundColor : settings.dialogMaskBgColor + }).show(); - infoDialog.show(); + infoDialog.css("z-index", editormd.dialogZindex).show(); this.infoDialogPosition(); @@ -1615,49 +1084,50 @@ /** * 隐藏关于Editor.md + * Hide about Editor.md dialog + * * @returns {editormd} 返回editormd的实例对象 */ - hideInfoDialog : function() { + hideInfoDialog : function() { $("html,body").css("overflow-x", ""); this.infoDialog.hide(); + this.mask.hide(); + this.lockScreen(false); return this; }, /** - * 配置和初始化marked组件 - * @returns {editormd} 返回editormd的实例对象 + * 锁屏 + * lock screen + * + * @param {Boolean} lock Boolean 布尔值,是否锁屏 + * @returns {editormd} 返回editormd的实例对象 */ - setMarked : function() { - var marked = editormd.$marked; - var markdownToC = this.markdownToC = []; - - marked.setOptions({ - renderer : editormd.markedRenderer(markdownToC), - gfm : true, - tables : true, - breaks : true, - pedantic : false, - sanitize : (this.settings.htmlDecode) ? false : true, // 关闭忽略HTML标签,即开启识别HTML标签,默认为false - smartLists : true, - smartypants : true - }); + lockScreen : function(lock) { + editormd.lockScreen(lock); return this; }, /** * 编辑器界面重建,用于动态语言包或模块加载等 + * Recreate editor + * * @returns {editormd} 返回editormd的实例对象 */ - recreateEditor : function() { + recreate : function() { var _this = this; var editor = this.editor; var settings = this.settings; - var toolbarIcons = settings.toolbarIcons(); + var toolbarIcons = settings.toolbarIcons(); + + this.codeMirror.remove(); + + this.setCodeMirror(); if (typeof this.infoDialog !== "undefined") { this.infoDialog.remove(); @@ -1673,10 +1143,14 @@ editor.find(".editormd-dialog").remove(); } - this.getToolbarHandles(); - this.setToolbar(); + if (settings.toolbar) + { + this.getToolbarHandles(); + this.setToolbar(); + } } + this.saveToTextareas(); this.resize(); return this; @@ -1684,6 +1158,8 @@ /** * 高亮预览HTML的pre代码部分 + * highlight of preview codes + * * @returns {editormd} 返回editormd的实例对象 */ @@ -1694,7 +1170,11 @@ if (settings.previewCodeHighlight) { previewContainer.find("pre").addClass("prettyprint linenums"); - prettyPrint(); + + if (typeof prettyPrint !== "undefined") + { + prettyPrint(); + } } return this; @@ -1702,6 +1182,8 @@ /** * 解析TeX(KaTeX)科学公式 + * TeX(KaTeX) Renderer + * * @returns {editormd} 返回editormd的实例对象 */ @@ -1719,6 +1201,8 @@ /** * 解析和渲染流程图及时序图 + * FlowChart and SequenceDiagram Renderer + * * @returns {editormd} 返回editormd的实例对象 */ @@ -1742,6 +1226,8 @@ /** * 加载队列完成之后的显示处理 + * Display handle of the module queues loaded after. + * * @returns {editormd} 返回editormd的实例对象 */ @@ -1756,7 +1242,7 @@ var previewContainer = this.previewContainer; var mouseOrTouch = editormd.mouseOrTouch; - editor.find("." + this.classPrefix + "container-mask").hide(); + editor.children("." + this.classPrefix + "container-mask").hide(); this.saveToTextareas(); @@ -1773,7 +1259,7 @@ }); var codeEditorBindScroll = function() { - codeMirror.find(".CodeMirror-scroll").bind(mouseOrTouch("scroll", "touchmove"), function() { + codeMirror.find(".CodeMirror-scroll").bind(mouseOrTouch("scroll", "touchmove"), function(event) { var height = $(this).height(); var scrollTop = $(this).scrollTop(); var percent = (scrollTop / $(this)[0].scrollHeight); @@ -1790,6 +1276,8 @@ { preview.scrollTop(preview[0].scrollHeight * percent); } + + $.proxy(settings.onscroll, this)(event); }); }; @@ -1816,6 +1304,8 @@ { codeView.scrollTop(codeView[0].scrollHeight * percent); } + + $.proxy(settings.onpreviewscroll, this)(event); }); }; @@ -1837,7 +1327,7 @@ touchend : previewUnbindScroll }); - codeEditor.on("change", function(cm, changeObj) { + codeEditor.on("change", function(cm, changeObj) { _this.saveToTextareas(); }); @@ -1850,6 +1340,8 @@ /** * 设置编辑器的宽度 + * Set editor width + * * @param {Number|String} width 编辑器宽度值 * @returns {editormd} 返回editormd的实例对象 */ @@ -1864,6 +1356,8 @@ /** * 设置编辑器的高度 + * Set editor height + * * @param {Number|String} height 编辑器高度值 * @returns {editormd} 返回editormd的实例对象 */ @@ -1878,6 +1372,8 @@ /** * 调整编辑器的尺寸和布局 + * Resize editor layout + * * @param {Number|String} [width=null] 编辑器宽度值 * @param {Number|String} [height=null] 编辑器高度值 * @returns {editormd} 返回editormd的实例对象 @@ -1927,12 +1423,19 @@ codeMirror.width(editor.width()); preview.hide(); } + + if (this.state.loaded) + { + $.proxy(settings.onresize, this)(); + } return this; }, /** * 分别将Markdown源码和解析的HTML源码保存到对应的textarea + * Saving Markdown and HTML source code to Textarea + * * @returns {editormd} 返回editormd的实例对象 */ @@ -1944,14 +1447,50 @@ var previewContainer = this.previewContainer; var codeMirrorValue = codeEditor.getValue(); - var markdownToC = this.markdownToC = []; - var newMarkdownDoc = editormd.$marked(codeMirrorValue, {renderer : editormd.markedRenderer(markdownToC)}); + + if (settings.mode !== "gfm" && settings.mode !== "markdown") + { + this.markdownTextarea[0].innerText = codeMirrorValue; + + return this; + } + + var marked = editormd.$marked; + var markdownToC = this.markdownToC = []; + var rendererOptions = this.markedRendererOptions = { + toc : settings.toc, + tocStartLevel : settings.tocStartLevel, + taskList : settings.taskList, + emoji : settings.emoji, + tex : settings.tex, + flowChart : settings.flowChart, + sequenceDiagram : settings.sequenceDiagram, + previewCodeHighlight : settings.previewCodeHighlight, + }; + + var markedOptions = this.markedOptions = { + renderer : editormd.markedRenderer(markdownToC, rendererOptions), + gfm : true, + tables : true, + breaks : true, + pedantic : false, + sanitize : (settings.htmlDecode) ? false : true, // 关闭忽略HTML标签,即开启识别HTML标签,默认为false + smartLists : true, + smartypants : true + }; + + marked.setOptions(markedOptions); + + codeMirrorValue = editormd.filterHTMLTags(codeMirrorValue, settings.htmlDecode); + + var newMarkdownDoc = editormd.$marked(codeMirrorValue, markedOptions); this.markdownTextarea[0].innerText = codeMirrorValue; codeEditor.save(); - if (settings.saveHTMLToTextarea) { + if (settings.saveHTMLToTextarea) + { this.htmlTextarea.html(newMarkdownDoc); } @@ -1964,21 +1503,27 @@ if (settings.toc) { editormd.markdownToCRenderer(markdownToC, previewContainer, settings.tocStartLevel); } - - if (!settings.inRequirejs && !editormd.kaTeXLoaded) { - editormd.loadKaTeX(function(){ - editormd.$katex = katex; - editormd.kaTeXLoaded = true; - _this.katexRender(); - }); - } else { - this.katexRender(); - } - var timer = setTimeout(function(){ - clearTimeout(timer); - _this.flowChartAndSequenceDiagramRender(); - }, 10); + if (settings.tex) + { + if (!settings.inRequirejs && !editormd.kaTeXLoaded) { + editormd.loadKaTeX(function(){ + editormd.$katex = katex; + editormd.kaTeXLoaded = true; + _this.katexRender(); + }); + } else { + this.katexRender(); + } + } + + if (settings.flowChart || settings.sequenceDiagram) + { + var timer = setTimeout(function(){ + clearTimeout(timer); + _this.flowChartAndSequenceDiagramRender(); + }, 10); + } if (state.loaded) { @@ -1991,6 +1536,8 @@ /** * 聚焦光标位置 + * Focusing the cursor position + * * @returns {editormd} 返回editormd的实例对象 */ @@ -2002,6 +1549,8 @@ /** * 设置光标的位置 + * Set cursor position + * * @param {Object} cursor 要设置的光标位置键值对象,例:{line:1, ch:0} * @returns {editormd} 返回editormd的实例对象 */ @@ -2014,6 +1563,8 @@ /** * 获取当前光标的位置 + * Get the current position of the cursor + * * @returns {Cursor} 返回一个光标Cursor对象 */ @@ -2023,6 +1574,8 @@ /** * 设置光标选中的范围 + * Set cursor selected ranges + * * @param {Object} from 开始位置的光标键值对象,例:{line:1, ch:0} * @param {Object} to 结束位置的光标键值对象,例:{line:1, ch:0} * @returns {editormd} 返回editormd的实例对象 @@ -2037,6 +1590,8 @@ /** * 获取光标选中的文本 + * Get the texts from cursor selected + * * @returns {String} 返回选中文本的字符串形式 */ @@ -2046,6 +1601,8 @@ /** * 替换当前光标选中的文本或在当前光标处插入新字符 + * Replace the text at the current cursor selected or insert a new character at the current cursor position + * * @param {String} value 要插入的字符值 * @returns {editormd} 返回editormd的实例对象 */ @@ -2058,8 +1615,11 @@ /** * 在当前光标处插入新字符 + * Insert a new character at the current cursor position * * 同replaceSelection()方法 + * With the replaceSelection() method + * * @param {String} value 要插入的字符值 * @returns {editormd} 返回editormd的实例对象 */ @@ -2072,6 +1632,8 @@ /** * 设置和传入编辑器的markdown源文档 + * Set Markdown source document + * * @param {String} md 要传入的markdown源文档 * @returns {editormd} 返回editormd的实例对象 */ @@ -2079,13 +1641,15 @@ setMarkdown : function(md) { var settings = this.settings; - this.codeEditor.setValue(md); + this.codeEditor.setValue(md || settings.markdown); return this; }, /** * 获取编辑器的markdown源文档 + * Set Editor.md markdown/CodeMirror value + * * @returns {editormd} 返回editormd的实例对象 */ @@ -2093,8 +1657,35 @@ return this.codeEditor.getValue(); }, + /** + * 获取编辑器的源文档 + * Get CodeMirror value + * + * @returns {editormd} 返回editormd的实例对象 + */ + + getValue : function() { + return this.codeEditor.getValue(); + }, + + /** + * 设置编辑器的源文档 + * Set CodeMirror value + * + * @param {String} value set code/value/string/text + * @returns {editormd} 返回editormd的实例对象 + */ + + setValue : function(value) { + this.codeEditor.setValue(value); + + return this; + }, + /** * 清空编辑器 + * Empty CodeMirror editor container + * * @returns {editormd} 返回editormd的实例对象 */ @@ -2106,6 +1697,8 @@ /** * 获取解析后存放在Textarea的HTML源码 + * Get parsed html code from Textarea + * * @returns {String} 返回HTML源码 */ @@ -2122,7 +1715,9 @@ /** * getHTML()的别名 - * @returns {editormd} 返回HTML源码 + * getHTML (alias) + * + * @returns {String} Return html code 返回HTML源码 */ getTextareaSavedHTML : function() { @@ -2131,6 +1726,8 @@ /** * 获取预览窗口的HTML源码 + * Get html from preview container + * * @returns {editormd} 返回editormd的实例对象 */ @@ -2147,62 +1744,80 @@ /** * 开启实时预览 + * Enable real-time watching + * * @returns {editormd} 返回editormd的实例对象 */ - watch : function(callback) { - callback = callback || function() {}; - - this.state.watching = this.settings.watch = true; + watch : function(callback) { + var settings = this.settings; + this.state.watching = settings.watch = true; this.preview.show(); - var watchIcon = this.settings.toolbarIconsClass.watch; - var unWatchIcon = this.settings.toolbarIconsClass.unwatch; + var watchIcon = settings.toolbarIconsClass.watch; + var unWatchIcon = settings.toolbarIconsClass.unwatch; var icon = this.toolbar.find(".fa[name=watch]"); - icon.parent().attr("title", this.settings.lang.toolbar.watch); + icon.parent().attr("title", settings.lang.toolbar.watch); icon.removeClass(unWatchIcon).addClass(watchIcon); this.codeMirror.css("border-right", "1px solid #ddd").width(this.editor.width() / 2); this.saveToTextareas().resize(); - $.proxy(callback, this)(); + if (!settings.onwatch) + { + settings.onwatch = callback || function() {}; + } + + $.proxy(settings.onwatch, this)(); return this; }, /** * 关闭实时预览 + * Disable real-time watching + * * @returns {editormd} 返回editormd的实例对象 */ unwatch : function(callback) { - callback = callback || function() {}; - - this.state.watching = this.settings.watch = false; + var settings = this.settings; + this.state.watching = settings.watch = false; this.preview.hide(); - var watchIcon = this.settings.toolbarIconsClass.watch; - var unWatchIcon = this.settings.toolbarIconsClass.unwatch; + var watchIcon = settings.toolbarIconsClass.watch; + var unWatchIcon = settings.toolbarIconsClass.unwatch; - var icon = this.toolbar.find(".fa[name=watch]"); - icon.parent().attr("title", this.settings.lang.toolbar.unwatch); - icon.removeClass(watchIcon).addClass(unWatchIcon); + if (this.toolbar) + { + var icon = this.toolbar.find(".fa[name=watch]"); + icon.parent().attr("title", settings.lang.toolbar.unwatch); + icon.removeClass(watchIcon).addClass(unWatchIcon); + } this.codeMirror.css("border-right", "none").width(this.editor.width()); this.resize(); - $.proxy(callback, this)(); + if (!settings.onunwatch) + { + settings.onunwatch = callback || function() {}; + } + + $.proxy(settings.onunwatch, this)(); return this; }, /** * 显示编辑器 + * Show editor + * * @param {Function} [callback=function()] 回调函数 * @returns {editormd} 返回editormd的实例对象 */ + show : function(callback) { callback = callback || function() {}; @@ -2216,6 +1831,8 @@ /** * 隐藏编辑器 + * Hide editor + * * @param {Function} [callback=function()] 回调函数 * @returns {editormd} 返回editormd的实例对象 */ @@ -2233,6 +1850,8 @@ /** * 隐藏编辑器部分,只预览HTML + * Enter preview html state + * * @returns {editormd} 返回editormd的实例对象 */ @@ -2266,18 +1885,6 @@ if(!settings.watch) { - /*var codeEditor = this.codeEditor; - var previewContainer = this.previewContainer; - - codeEditor.save(); - - var markdownToC = this.markdownToC = []; - var newMarkdownDoc = editormd.$marked(codeEditor.getValue(), {renderer : editormd.markedRenderer(markdownToC)}); - previewContainer.html(newMarkdownDoc); - - if (settings.toc) { - editormd.markdownToCRenderer(markdownToC, previewContainer, settings.tocStartLevel); - }*/ this.saveToTextareas(); } @@ -2287,6 +1894,11 @@ width : editor.width(), height : editor.height() }); + + if (this.state.loaded) + { + $.proxy(settings.onpreviewing, this)(); + } } else { @@ -2302,6 +1914,8 @@ /** * 显示编辑器部分,退出只预览HTML + * Exit preview html state + * * @returns {editormd} 返回editormd的实例对象 */ @@ -2337,12 +1951,19 @@ height : editor.height() - toolbar.height(), top : (settings.toolbar) ? toolbar.height() : 0 }); + + if (this.state.loaded) + { + $.proxy(settings.onpreviewed, this)(); + } return this; }, /** * 编辑器全屏显示 + * Fullscreen show + * * @returns {editormd} 返回editormd的实例对象 */ @@ -2354,7 +1975,9 @@ var toolbar = this.toolbar; var fullscreenClass = this.classPrefix + "fullscreen"; - toolbar.find(".fa[name=fullscreen]").parent().toggleClass("active"); + if (toolbar) { + toolbar.find(".fa[name=fullscreen]").parent().toggleClass("active"); + } if (!editor.hasClass(fullscreenClass)) { @@ -2396,16 +2019,21 @@ /** * 编辑器退出全屏显示 + * Exit fullscreen state + * * @returns {editormd} 返回editormd的实例对象 */ fullscreenExit : function() { var editor = this.editor; + var toolbar = this.toolbar; var fullscreenClass = this.classPrefix + "fullscreen"; this.state.fullscreen = false; - this.toolbar.find(".fa[name=fullscreen]").parent().removeClass("active"); + if (toolbar) { + toolbar.find(".fa[name=fullscreen]").parent().removeClass("active"); + } $("html,body").css("overflow", ""); @@ -2419,21 +2047,300 @@ border : "1px solid #ddd" }).removeClass(fullscreenClass); - this.resize(); + this.resize(); + + + $.proxy(this.settings.onfullscreenExit, this)(); + + return this; + }, + + executePlugin : function(name, path) { + + var _this = this; + var cm = this.cm; + + if (typeof define == "function") { + + this[name](cm); + + return ; + } + + path = this.settings.path + "../plugins/" + path; + + if ($.inArray(path, editormd.loadFiles.plugin) < 0) + { + editormd.loadPlugin(path, function() { + editormd.loadPlugins[name] = _this[name]; + _this[name](cm); + }); + } + else + { + $.proxy(editormd.loadPlugins[name], this)(cm); + } + } + }; + + editormd.fn.init.prototype = editormd.fn; + + editormd.dialogLockScreen = function() { + var settings = this.settings; + + if (settings.dialogLockScreen) + { + $("html,body").css("overflow", "hidden"); + } + }; + + editormd.dialogShowMask = function(dialog) { + var editor = this.editor; + var settings = this.settings; + + dialog.css({ + top : ($(window).height() - dialog.height()) / 2 + "px", + left : ($(window).width() - dialog.width()) / 2 + "px" + }); + + if (settings.dialogShowMask) { + editor.children("." + this.classPrefix + "mask").css("z-index", parseInt(dialog.css("z-index")) - 1).show(); + } + }; + + editormd.toolbarHandlers = { + undo : function() { + this.cm.undo(); + }, + + redo : function() { + this.cm.redo(); + }, + + bold : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("**" + selection + "**"); + + if(selection === "") { + cm.setCursor(cursor.line, cursor.ch + 2); + } + }, + + del : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("~~" + selection + "~~"); + + if(selection === "") { + cm.setCursor(cursor.line, cursor.ch + 2); + } + }, + + italic : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("*" + selection + "*"); + + if(selection === "") { + cm.setCursor(cursor.line, cursor.ch + 1); + } + }, + + quote : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("> " + selection); + cm.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); + }, + + h1 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("# " + selection); + }, + + h2 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("## " + selection); + }, + + h3 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("### " + selection); + }, + + h4 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("#### " + selection); + }, + + h5 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("##### " + selection); + }, + + h6 : function() { + var cm = this.cm; + var selection = cm.getSelection(); + + cm.replaceSelection("###### " + selection); + }, + + "list-ul" : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + if (selection === "") + { + cm.replaceSelection("- " + selection); + } + else + { + var selectionText = selection.split("\n"); + + for (var i = 0, len = selectionText.length; i < len; i++) + { + selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; + } + + cm.replaceSelection(selectionText.join("\n")); + } + }, + + "list-ol" : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + if(selection === "") + { + cm.replaceSelection("1. " + selection); + } + else + { + var selectionText = selection.split("\n"); + + for (var i = 0, len = selectionText.length; i < len; i++) + { + selectionText[i] = (selectionText[i] === "") ? "" : (i+1) + ". " + selectionText[i]; + } + + cm.replaceSelection(selectionText.join("\n")); + } + }, + + hr : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("------------"); + }, + + link : function() { + this.executePlugin("linkDialog", "link-dialog/link-dialog"); + }, + + anchor : function() { + this.executePlugin("anchorLinkDialog", "anchor-link-dialog/anchor-link-dialog"); + }, + + image : function() { + this.executePlugin("imageDialog", "image-dialog/image-dialog"); + }, + + code : function() { + var cm = this.cm; + var cursor = cm.getCursor(); + var selection = cm.getSelection(); + + cm.replaceSelection("`" + selection + "`"); + + if (selection === "") { + cm.setCursor(cursor.line, cursor.ch + 1); + } + }, + + "code-block" : function() { + this.executePlugin("codeBlockDialog", "code-block-dialog/code-block-dialog"); + }, + + "preformatted-text" : function() { + this.executePlugin("preformattedTextDialog", "preformatted-text-dialog/preformatted-text-dialog"); + }, + + table : function() { + this.executePlugin("tableDialog", "table-dialog/table-dialog"); + }, + + datetime : function() { + var cm = this.cm; + var selection = cm.getSelection(); + var date = new Date(); + var langName = this.settings.lang.name; + var datefmt = editormd.dateFormat() + " " + editormd.dateFormat((langName === "zh-cn" || langName === "zh-tw") ? "cn-week-day" : "week-day"); + + cm.replaceSelection(datefmt); + }, + + emoji : function() { + this.executePlugin("emojiDialog", "emoji-dialog/emoji-dialog"); + }, + + htmlEntities : function() { + this.executePlugin("htmlEntitiesDialog", "html-entities-dialog/html-entities-dialog"); + }, + + watch : function() { + this[this.settings.watch ? "unwatch" : "watch"](); + }, + + preview : function() { + this.previewing(); + }, - - $.proxy(this.settings.onfullscreenExit, this)(); + fullscreen : function() { + this.fullscreen(); + }, - return this; + clear : function() { + this.clear(); + }, + + help : function() { + this.executePlugin("helpDialog", "help-dialog/help-dialog"); + }, + + info : function() { + this.showInfoDialog(); } }; - editormd.fn.init.prototype = editormd.fn; - /** * 清除字符串两边的空格 + * Clear the space of strings both sides. + * * @param {String} str string - * @returns {String} trim string + * @returns {String} trimed string */ editormd.trim = function(str) { @@ -2442,16 +2349,161 @@ var trim = editormd.trim; + editormd.urls = { + atLinkBase : "https://github.com/" + }; + + editormd.regex = { + atLink : /@(\w+)/g, + emoji : /:([\-\w]+):/g, + twemoji : /:(tw-([\w]+)-?(\w+)?):/g, + fontAwesome : /:(fa-([\w]+)-?(\w+)?):/g, + editormdLogo : /:(editormd-logo-?(\w+)?):/g + }; + + // Emoji graphics files url path + editormd.emoji = { + path : "http://www.emoji-cheat-sheet.com/graphics/emojis/", + ext : ".png" + }; + + // Twitter Emoji (Twemoji) graphics files url path + editormd.twemoji = { + path : "http://twemoji.maxcdn.com/36x36/", + ext : ".png" + }; + /** * 自定义marked的解析器 + * Custom Marked renderer rules + * * @param {Array} markdownToC 传入用于接收TOC的数组 - * @returns {Renderer} markedRenderer 返回marked的Renderer自定义对象 + * @returns {Renderer} markedRenderer 返回marked的Renderer自定义对象 */ - editormd.markedRenderer = function(markdownToC) { - var marked = editormd.$marked; - var markedRenderer = new marked.Renderer(); - markdownToC = markdownToC || []; + editormd.markedRenderer = function(markdownToC, options) { + var defaults = { + toc : true, // Table of contents + tocStartLevel : 1, // Said from H1 to create ToC + taskList : false, // Enable Github Flavored Markdown task lists + emoji : false, // :emoji: , Support Twemoji, fontAwesome, Editor.md logo emojis. + tex : false, // TeX(LaTeX), based on KaTeX + flowChart : false, // flowChart.js only support IE9+ + sequenceDiagram : false, // sequenceDiagram.js only support IE9+ + }; + + var atLinkReg = editormd.regex.atLink; + + var settings = $.extend(defaults, options || {}); + var marked = editormd.$marked; + var markedRenderer = new marked.Renderer(); + markdownToC = markdownToC || []; + + var emojiReg = editormd.regex.emoji; + var twemojiReg = editormd.regex.twemoji; + var faIconReg = editormd.regex.fontAwesome; + var editormdLogoReg = editormd.regex.editormdLogo; + + markedRenderer.emoji = function(text) { + var matchs = text.match(emojiReg); + + if (!matchs || !settings.emoji) { + return text; + } + + for (var i = 0, len = matchs.length; i < len; i++) + { + text = text.replace(new RegExp(matchs[i]), function($1, $2){ + var faMatchs = $1.match(faIconReg); + var name = $1.replace(/:/g, ""); + + if (faMatchs) + { + for (var fa = 0, len1 = faMatchs.length; fa < len1; fa++) + { + var faName = faMatchs[fa].replace(/:/g, ""); + + return ""; + } + } + else + { + var emdlogoMathcs = $1.match(editormdLogoReg); + var twemojiMatchs = $1.match(twemojiReg); + + if (emdlogoMathcs) + { + for (var x = 0, len2 = emdlogoMathcs.length; x < len2; x++) + { + var logoName = emdlogoMathcs[x].replace(/:/g, ""); + return ""; + } + } + else if (twemojiMatchs) + { + for (var t = 0, len3 = twemojiMatchs.length; t < len3; t++) + { + var twe = twemojiMatchs[t].replace(/:/g, "").replace("tw-", ""); + return "\"twemoji-""; + } + } + else + { + return "\":""; + } + } + }); + } + + return text; + }; + + markedRenderer.atLink = function(text) { + + if (atLinkReg.test(text)) + { + text = text.replace(atLinkReg, function($1, $2) { + return "" + $1 + ""; + }); + } + + return text; + }; + + markedRenderer.link = function (href, title, text) { + + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase(); + } catch(e) { + return ""; + } + + if (prot.indexOf("javascript:") === 0) { + return ""; + } + } + + var out = "" + text.replace(/@/g, "@") + ""; + } + + if (title) { + out += " title=\"" + title + "\""; + } + + out += ">" + text + ""; + + return out; + } markedRenderer.heading = function(text, level, raw) { @@ -2490,7 +2542,7 @@ headingHTML += ""; headingHTML += ""; - headingHTML += (hasLinkReg) ? linkText : text; + headingHTML += (hasLinkReg) ? this.atLink(this.emoji(linkText)) : this.atLink(this.emoji(text)); headingHTML += ""; return headingHTML; @@ -2514,7 +2566,7 @@ } return (isToC) ? "
                " + text + "
              " - : "" + text + "

              \n"; + : "" + this.atLink(this.emoji(text)) + "

              \n"; }; markedRenderer.code = function (code, lang, escaped) { @@ -2533,12 +2585,36 @@ return marked.Renderer.prototype.code.apply(this, arguments); } }; + + markedRenderer.tablecell = function(content, flags) { + var type = (flags.header) ? "th" : "td"; + var tag = (flags.align) ? "<" + type +" style=\"text-align:" + flags.align + "\">" : "<" + type + ">"; + + return tag + this.atLink(this.emoji(content)) + "\n"; + }; + + markedRenderer.listitem = function(text) { + if (settings.taskList && /^\s*\[[x\s]\]\s*/.test(text)) + { + text = text.replace(/^\s*\[\s\]\s*/, " ") + .replace(/^\s*\[x\]\s*/, " "); + + return "
            • " + this.atLink(this.emoji(text)) + "
            • "; + } + else + { + return "
            • " + this.atLink(this.emoji(text)) + "
            • "; + } + }; return markedRenderer; }; /** + * * 生成TOC(Table of Contents) + * Creating ToC (Table of Contents) + * * @param {Array} toc 从marked获取的TOC数组列表 * @param {Element} container 插入TOC的容器元素 * @param {Integer} startLevel Hx 起始层级 @@ -2584,39 +2660,79 @@ return tocContainer; }; + /** + * 简单地过滤指定的HTML标签 + * Filter custom html tags + * + * @param {String} html 要过滤HTML + * @param {String} filters 要过滤的标签 + * @returns {String} html 返回过滤的HTML + */ + + editormd.filterHTMLTags = function(html, filters) { + + if (typeof filters === "string") + { + var filterTags = filters.split(","); + + for (var i = 0, len = filterTags.length; i < len; i++) + { + var tag = filterTags[i]; + + html = html.replace(new RegExp("\<\s*"+tag+"\s*([^\>]*)\>", "igm"), "").replace(new RegExp("\<\s*\/"+tag+"\s*\>", "igm"), ""); + } + } + + return html; + }; + /** * 将Markdown文档解析为HTML用于前台显示 + * Parse Markdown to HTML for Font-end preview. + * * @param {String} id 用于显示HTML的对象ID * @param {Object} [options={}] 配置选项,可选 * @returns {Object} div 返回jQuery对象元素 */ - editormd.markdownToHTML = function(id, options) { - options = options || {}; - + editormd.markdownToHTML = function(id, options) { var defaults = { + gfm : true, toc : true, - tocStartLevel : 2, + tocStartLevel : 1, markdown : "", htmlDecode : false, inRequirejs : false, tex : false, + taskList : false, // Github Flavored Markdown task lists + emoji : false, flowChart : false, sequenceDiagram : false, previewCodeHighlight : true }; - editormd.$marked = marked; + editormd.$marked = marked; var div = $("#" + id); - var settings = div.settings = $.extend(true, defaults, options); + var settings = div.settings = $.extend(true, defaults, options || {}); var saveTo = div.find("textarea"); var markdownDoc = (settings.markdown === "") ? saveTo.val() : settings.markdown; var markdownToC = []; + var rendererOptions = { + toc : settings.toc, + tocStartLevel : settings.tocStartLevel, + taskList : settings.taskList, + emoji : settings.emoji, + tex : settings.tex, + flowChart : settings.flowChart, + sequenceDiagram : settings.sequenceDiagram, + previewCodeHighlight : settings.previewCodeHighlight, + }; + var markedOptions = { - renderer : editormd.markedRenderer(markdownToC), - gfm : true, + renderer : editormd.markedRenderer(markdownToC, rendererOptions), + gfm : settings.gfm, tables : true, breaks : true, pedantic : false, @@ -2625,6 +2741,8 @@ smartypants : true }; + markdownDoc = editormd.filterHTMLTags(markdownDoc, settings.htmlDecode); + var markdownParsed = marked(markdownDoc, markedOptions); if (editormd.isIE8) @@ -2685,155 +2803,60 @@ return div; }; - // for CodeBlock dialog select - editormd.codeLanguages = { - asp : "ASP", - actionscript : "ActionScript(3.0)/Flash/Flex", - bash : "Bash/Bat", - css : "CSS", - c : "C", - cpp : "C++", - csharp : "C#", - coffeescript : "CoffeeScript", - d : "D", - dart : "Dart", - delphi : "Delphi/Pascal", - erlang : "Erlang", - go : "Golang", - groovy : "Groovy", - html : "HTML", - java : "Java", - json : "JSON", - javascript : "Javascript", - lua : "Lua", - less : "LESS", - markdown : "Markdown", - "objective-c" : "Objective-C", - php : "PHP", - perl : "Perl", - python : "Python", - r : "R", - rst : "reStructedText", - ruby : "Ruby", - sql : "SQL", - sass : "SASS/SCSS", - shell : "Shell", - scala : "Scala", - swift : "Swift", - vb : "VB/VBScript", - xml : "XML", - yaml : "YAML" - }; - - // for Requires.js and Gulpfile.js - editormd.codeMirrorModules = { - modes : [ - "css", - "sass", - "shell", - "sql", - "clike", - "php", - "xml", - "markdown", - "javascript", - "htmlmixed", - "gfm", - "http", - "go", - "dart", - "coffeescript", - "nginx", - "python", - "perl", - "lua", - "r", - "ruby", - "rst", - "smartymixed", - "vb", - "vbscript", - "velocity", - "xquery", - "yaml", - "erlang", - "jade" - ], - - addons : [ - "edit/trailingspace", - "dialog/dialog", - "search/searchcursor", - "search/search", - "scroll/annotatescrollbar", - "search/matchesonscrollbar", - "display/placeholder", - "edit/closetag", - "fold/xml-fold", - "mode/overlay", - "selection/active-line", - "edit/closebrackets", - "display/fullscreen", - "search/searchcursor", - "search/match-highlighter" - ] - }; - - /** - * 用于支持Require.js加载的方法,注入 - * @param {Function} CodeMirror CodeMirror对象 - * @param {Function} marked marked对象 - * @param {Function} prettyPrint prettyPrint函数 - */ + editormd.themes = [ + "default", + "3024-day", "3024-night", + "ambiance", "ambiance-mobile", + "base16-dark", "base16-light", "blackboard", + "cobalt", + "eclipse", "elegant", "erlang-dark", + "lesser-dark", + "mbo", "mdn-like", "midnight", "monokai", + "neat", "neo", "night", + "paraiso-dark", "paraiso-light", "pastel-on-dark", + "rubyblue", + "solarized", + "the-matrix", "tomorrow-night-eighties", "twilight", + "vibrant-ink", + "xq-dark", "xq-light" + ]; + + editormd.loadPlugins = {}; - editormd.requirejsInit = function(CodeMirror, marked, katex, prettyPrint) { - editormd.$CodeMirror = CodeMirror; - editormd.$marked = marked; - editormd.$katex = katex; - editormd.$prettyPrint = prettyPrint; + editormd.loadFiles = { + js : [], + css : [], + plugin : [] }; /** - * 用于Require.js加载的模块队列 - * @param {String} [loadPath=""] 基本路径,默认为空 - * @returns {Array} modules 返回队列路径数组 + * 动态加载Editor.md插件,但不立即执行 + * Load editor.md plugins + * + * @param {String} fileName 插件文件路径 + * @param {Function} [callback=function()] 加载成功后执行的回调函数 + * @param {String} [into="head"] 嵌入页面的位置 */ - editormd.requireModules = function(loadPath) { - loadPath = loadPath || ""; - var settings = editormd.defaults; - var modules = []; - - modules.push(loadPath + "codemirror/codemirror.min"); - - var codeMirrorModules = editormd.codeMirrorModules; - - for (var i = 0, len = codeMirrorModules.modes.length; i < len; i++) - { - var modeName = codeMirrorModules.modes[i]; - modules.push(loadPath + "codemirror/mode/" + modeName + "/" + modeName); - } - - for (var i = 0, len = codeMirrorModules.addons.length; i < len; i++) - { - var addonName = codeMirrorModules.addons[i]; - modules.push(loadPath + "codemirror/addon/" + addonName); - } + editormd.loadPlugin = function(fileName, callback, into) { + callback = callback || function() {}; - editormd.loadCSS(editormd.katexURL.css); - - return modules; + this.loadScript(fileName, function() { + editormd.loadFiles.plugin.push(fileName); + callback(); + }, into); }; /** * 动态加载CSS文件的方法 + * Load css file method + * * @param {String} fileName CSS文件名 * @param {Function} [callback=function()] 加载成功后执行的回调函数 * @param {String} [into="head"] 嵌入页面的位置 */ editormd.loadCSS = function(fileName, callback, into) { - into = into || "head"; callback = callback || function() {}; @@ -2841,6 +2864,7 @@ css.type = "text/css"; css.rel = "stylesheet"; css.onload = css.onreadystatechange = function() { + editormd.loadFiles.css.push(fileName); callback(); }; @@ -2858,6 +2882,8 @@ /** * 动态加载JS文件的方法 + * Load javascript file method + * * @param {String} fileName JS文件名 * @param {Function} [callback=function()] 加载成功后执行的回调函数 * @param {String} [into="head"] 嵌入页面的位置 @@ -2882,6 +2908,7 @@ if (script.readyState === "loaded" || script.readyState === "complete") { script.onreadystatechange = null; + editormd.loadFiles.js.push(fileName); callback(); } } @@ -2890,6 +2917,7 @@ else { script.onload = function() { + editormd.loadFiles.js.push(fileName); callback(); }; } @@ -2902,15 +2930,18 @@ }; // 使用国外的CDN,加载速度有时会很慢,或者自定义URL + // You can custom KaTeX load url. editormd.katexURL = { - css : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min", - js : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min" + css : "http://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min", + js : "http://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min" }; editormd.kaTeXLoaded = false; /** - * 加载KaTex文件 + * 加载KaTeX文件 + * load KaTeX files + * * @param {Function} [callback=function()] 加载成功后执行的回调函数 */ @@ -2919,9 +2950,267 @@ editormd.loadScript(editormd.katexURL.js, callback || function(){}); }); }; + + /** + * 锁屏 + * lock screen + * + * @param {Boolean} lock Boolean 布尔值,是否锁屏 + * @returns {void} + */ + + editormd.lockScreen = function(lock) { + $("html,body").css("overflow", (lock) ? "hidden" : ""); + }; + + /** + * 动态创建对话框 + * Creating custom dialogs + * + * @param {Object} options 配置项键值对 Key/Value + * @returns {dialog} 返回创建的dialog的jQuery实例对象 + */ + + editormd.createDialog = function(options) { + var defaults = { + name : "", + width : 420, + height: 240, + title : "", + drag : true, + closed : true, + content : "", + mask : true, + maskStyle : { + backgroundColor : "#fff", + opacity : 0.1 + }, + lockScreen : true, + footer : true, + buttons : false + }; + + options = $.extend(true, defaults, options); + + var editor = this.editor; + var classPrefix = editormd.classPrefix; + var guid = (new Date).getTime(); + var dialogName = ( (options.name === "") ? classPrefix + "dialog-" + guid : options.name); + var mouseOrTouch = editormd.mouseOrTouch; + + var html = "
              "; + + if (options.title !== "") + { + html += "
              "; + html += "" + options.title + ""; + html += "
              "; + } + + if (options.closed) + { + html += ""; + } + + html += "
              " + options.content; + + if (options.footer || typeof options.footer === "string") + { + html += "
              " + ( (typeof options.footer === "boolean") ? "" : options.footer) + "
              "; + } + + html += "
              "; + + html += "
              "; + html += "
              "; + html += "
              "; + + editor.append(html); + + var dialog = editor.find("." + dialogName); + + dialog.lockScreen = function(lock) { + if (options.lockScreen) + { + $("html,body").css("overflow", (lock) ? "hidden" : ""); + } + + return dialog; + }; + + dialog.showMask = function() { + if (options.mask) + { + editor.find("." + classPrefix + "mask").css(options.maskStyle).css("z-index", editormd.dialogZindex - 1).show(); + } + return dialog; + }; + + dialog.hideMask = function() { + if (options.mask) + { + editor.find("." + classPrefix + "mask").hide(); + } + + return dialog; + }; + + dialog.loading = function(show) { + var loading = dialog.find("." + classPrefix + "dialog-mask"); + loading[(show) ? "show" : "hide"](); + + return dialog; + }; + + dialog.lockScreen(true).showMask(); + + dialog.show().css({ + zIndex : editormd.dialogZindex, + border : (editormd.isIE8) ? "1px solid #ddd" : "", + width : (typeof options.width === "number") ? options.width + "px" : options.width, + height : (typeof options.height === "number") ? options.height + "px" : options.height + }); + + var dialogPosition = function(){ + dialog.css({ + top : ($(window).height() - dialog.height()) / 2 + "px", + left : ($(window).width() - dialog.width()) / 2 + "px" + }); + }; + + dialogPosition(); + + $(window).resize(dialogPosition); + + dialog.children("." + classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { + dialog.hide().lockScreen(false).hideMask(); + }); + + if (typeof options.buttons == "object") + { + var footer = dialog.footer = dialog.find("." + classPrefix + "dialog-footer"); + + for (var key in options.buttons) + { + var btn = options.buttons[key]; + var btnClassName = classPrefix + key + "-btn"; + + footer.append(""); + btn[1] = $.proxy(btn[1], dialog); + footer.children("." + btnClassName).bind(mouseOrTouch("click", "touchend"), btn[1]); + } + } + + if (options.title !== "" && options.drag) + { + var posX, posY; + var dialogHeader = dialog.children("." + classPrefix + "dialog-header"); + + if (!options.mask) { + dialogHeader.bind(mouseOrTouch("click", "touchend"), function(){ + editormd.dialogZindex += 2; + dialog.css("z-index", editormd.dialogZindex); + }); + } + + dialogHeader.mousedown(function(e) { + e = e || window.event; //IE + posX = e.clientX - parseInt(dialog[0].style.left); + posY = e.clientY - parseInt(dialog[0].style.top); + + document.onmousemove = moveAction; + }); + + var userCanSelect = function (obj) { + obj.removeClass(classPrefix + "user-unselect").off("selectstart"); + } + + var userUnselect = function (obj) { + obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) { // selectstart for IE + return false; + }); + } + + var moveAction = function (e) { + e = e || window.event; //IE + + var left, top, nowLeft = parseInt(dialog[0].style.left), nowTop = parseInt(dialog[0].style.top); + + if( nowLeft >= 0 ) { + if( nowLeft + dialog.width() <= $(window).width()) { + left = e.clientX - posX; + } else { + left = $(window).width() - dialog.width(); + document.onmousemove = null; + } + } else { + left = 0; + document.onmousemove = null; + } + + if( nowTop >= 0 ) { + top = e.clientY - posY; + } else { + top = 0; + document.onmousemove = null; + } + + + document.onselectstart = function() { + return false; + }; + + userUnselect($("body")); + userUnselect(dialog); + dialog[0].style.left = left + "px"; + dialog[0].style.top = top + "px"; + } + + document.onmouseup = function() { + userCanSelect($("body")); + userCanSelect(dialog); + + document.onselectstart = null; + document.onmousemove = null; + }; + + dialogHeader.touchDraggable = function() { + var offset = null; + var start = function(e) { + var orig = e.originalEvent; + var pos = $(this).parent().position(); + + offset = { + x : orig.changedTouches[0].pageX - pos.left, + y : orig.changedTouches[0].pageY - pos.top + }; + }; + + var move = function(e) { + e.preventDefault(); + var orig = e.originalEvent; + + $(this).parent().css({ + top : orig.changedTouches[0].pageY - offset.y, + left : orig.changedTouches[0].pageX - offset.x + }); + }; + + this.bind("touchstart", start).bind("touchmove", move); + }; + + dialogHeader.touchDraggable(); + } + + editormd.dialogZindex += 2; + + return dialog; + }; /** * 鼠标和触摸事件的判断/选择方法 + * MouseEvent or TouchEvent type switch + * * @param {String} [mouseEventType="click"] 供选择的鼠标事件 * @param {String} [touchEventType="touchend"] 供选择的触摸事件 * @returns {String} EventType 返回事件类型名称 @@ -2946,6 +3235,8 @@ /** * 日期时间的格式化方法 + * Datetime format method + * * @param {String} [format=""] 日期时间的格式,类似PHP的格式 * @returns {String} datefmt 返回格式化后的日期时间字符串 */ diff --git a/editormd.min.js b/editormd.min.js new file mode 100644 index 0000000..350c987 --- /dev/null +++ b/editormd.min.js @@ -0,0 +1,3 @@ +/*! Editor.md v1.2.0 | editormd.min.js | A simple online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-03-10 */ +!function(e){"use strict";"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?module.exports=e:"function"==typeof define?define.amd||define(["jquery"],e):window.editormd=e()}(function(){"use strict";var e="undefined"!=typeof jQuery?jQuery:Zepto;if("undefined"!=typeof e){var t=function(e,i){return new t.fn.init(e,i)};t.title=t.$name="Editor.md",t.version="1.2.0",t.homePage="https://pandao.github.io/editor.md/",t.classPrefix="editormd-",t.toolbarModes={full:["undo","redo","|","bold","del","italic","quote","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","link","anchor","image","code","preformatted-text","code-block","table","datetime","emoji","htmlEntities","|","watch","preview","fullscreen","clear","|","help","info"],simple:["undo","redo","|","bold","del","italic","quote","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","watch","preview","fullscreen","|","help","info"],mini:["undo","redo","|","watch","preview","|","help","info"]},t.defaults={mode:"gfm",theme:"default",value:"",markdown:"",width:"100%",height:"100%",path:"./lib/",autoLoadModules:!0,watch:!0,placeholder:"now coding markdown...",codeFold:!1,autoCloseTags:!0,searchReplace:!1,readOnly:!1,lineNumbers:!0,matchWordHighlight:!0,styleActiveLine:!0,dialogLockScreen:!0,dialogShowMask:!0,dialogDraggable:!0,dialogMaskBgColor:"#fff",dialogMaskOpacity:.1,fontSize:"13px",saveHTMLToTextarea:!1,onload:function(){},onresize:function(){},onchange:function(){},onwatch:null,onunwatch:null,onpreviewing:function(){},onpreviewed:function(){},onfullscreen:function(){},onfullscreenExit:function(){},onscroll:function(){},onpreviewscroll:function(){},imageUpload:!1,imageFormats:["jpg","jpeg","gif","png","bmp","webp"],imageUploadURL:"",crossDomainUpload:!1,uploadCallbackURL:"",toc:!0,tocStartLevel:1,htmlDecode:!1,taskList:!1,emoji:!1,tex:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0,inRequirejs:!1,toolbar:!0,toolbarIcons:function(){return t.toolbarModes.full},toolbarTitles:{},toolbarHandlers:{},toolbarCustomIcons:{},toolbarIconsClass:{undo:"fa-undo",redo:"fa-repeat",bold:"fa-bold",del:"fa-strikethrough",italic:"fa-italic",quote:"fa-quote-left",h1:t.classPrefix+"bold",h2:t.classPrefix+"bold",h3:t.classPrefix+"bold",h4:t.classPrefix+"bold",h5:t.classPrefix+"bold",h6:t.classPrefix+"bold","list-ul":"fa-list-ul","list-ol":"fa-list-ol",hr:"fa-minus",link:"fa-link",anchor:"fa-anchor",image:"fa-picture-o",code:"fa-code","preformatted-text":"fa-file-code-o","code-block":"fa-file-code-o",table:"fa-table",datetime:"fa-clock-o",emoji:"fa-smile-o",htmlEntities:"fa-copyright",watch:"fa-eye-slash",unwatch:"fa-eye",preview:"fa-search",fullscreen:"fa-arrows-alt",clear:"fa-eraser",help:"fa-question-circle",info:"fa-info-circle"},toolbarIconTexts:{},lang:{name:"zh-cn",description:"开源在线Markdown编辑器
              A simple markdown doucment online editor.",toolbar:{undo:"撤销(Ctrl+Z)",redo:"重做(Ctrl+Y)",bold:"粗体",del:"删除线",italic:"斜体",quote:"引用",h1:"标题1",h2:"标题2",h3:"标题3",h4:"标题4",h5:"标题5",h6:"标题6","list-ul":"无序列表","list-ol":"有序列表",hr:"横线",link:"链接",anchor:"锚点",image:"添加图片",code:"行内代码","preformatted-text":"预格式文本 / 代码块(缩进风格)","code-block":"代码块(多语言风格)",table:"添加表格",datetime:"日期时间",emoji:"Emoji表情",htmlEntities:"HTML实体字符",watch:"关闭实时预览",unwatch:"开启实时预览",preview:"全窗口预览HTML(可按ESC还原)",fullscreen:"全屏(按ESC还原)",clear:"清空",help:"使用帮助",info:"关于"+t.title},buttons:{enter:"确定",cancel:"取消",close:"关闭"},dialog:{link:{title:"添加链接",url:"链接地址",urlTitle:"链接标题",urlEmpty:"错误:请填写链接地址。"},anchor:{title:"添加锚点链接",name:"锚点名称",url:"链接地址",urlTitle:"链接标题",nameEmpty:"错误:锚点名称不能为空。",titleEmpty:"错误:请填写锚点链接标题。",urlEmpty:"错误:请填写锚点链接地址。"},image:{title:"添加图片",url:"图片地址",link:"图片链接",alt:"图片描述",uploadButton:"本地上传",imageURLEmpty:"错误:图片地址不能为空。",uploadFileEmpty:"错误:上传的图片不能为空。",formatNotAllowed:"错误:只允许上传图片文件,允许上传的图片文件格式有:"},preformattedText:{title:"添加预格式文本或代码块",emptyAlert:"错误:请填写预格式文本或代码的内容。"},codeBlock:{title:"添加代码块",selectLabel:"代码语言:",selectDefaultText:"请选择代码语言",otherLanguage:"其他语言",unselectedLanguageAlert:"错误:请选择代码所属的语言类型。",codeEmptyAlert:"错误:请填写代码内容。"},htmlEntities:{title:"HTML 实体字符"},help:{title:"使用帮助"}}}},t.classNames={tex:t.classPrefix+"tex"},t.dialogZindex=99999,t.$katex=null,t.$marked=null,t.$CodeMirror=null,t.$prettyPrint=null,t.prototype=t.fn={state:{watching:!1,loaded:!1,preview:!1,fullscreen:!1},init:function(i,o){o=o||{};var r=this,n=this.classPrefix=t.classPrefix,a=this.editor=e("#"+i),s=this.settings=e.extend(!0,t.defaults,o);this.id=i,this.lang=s.lang;var l=this.classNames={textarea:{html:this.classPrefix+"html-textarea",markdown:this.classPrefix+"markdown-textarea"}};this.state.watching=s.watch?!0:!1,a.hasClass("editormd")||a.addClass("editormd"),a.css({width:"number"==typeof s.width?s.width+"px":s.width,height:"number"==typeof s.height?s.height+"px":s.height});var c=this.markdownTextarea=a.children("textarea");c.length<1&&(a.append(""),c=this.markdownTextarea=a.children("textarea")),c.addClass(l.textarea.markdown).attr("name",i+"-markdown-doc").attr("placeholder",s.placeholder);var d=[s.readOnly?"":'',s.saveHTMLToTextarea?'':"",'
              ','
              ','
              '].join("\n");return a.append(d).addClass(n+"vertical"),this.mask=a.children("."+n+"mask"),""!==s.markdown&&c.val(s.markdown),this.htmlTextarea=a.children("."+l.textarea.html),this.preview=a.children("."+n+"preview"),this.previewContainer=this.preview.children("."+n+"preview-container"),"function"==typeof define&&define.amd&&("undefined"!=typeof katex&&(t.$katex=katex),s.searchReplace&&(t.loadCSS(s.path+"codemirror/addon/dialog/dialog"),t.loadCSS(s.path+"codemirror/addon/search/matchesonscrollbar"))),"function"!=typeof define&&s.autoLoadModules?this.loadQueues():("undefined"!=typeof CodeMirror&&(t.$CodeMirror=CodeMirror),"undefined"!=typeof marked&&(t.$marked=marked),r.setCodeMirror(),r.setToolbar(),r.loadedDisplay()),this},loadQueues:function(){var e=this,i=this.settings,o=i.path,r=function(){return t.isIE8?void e.loadedDisplay():void(i.flowChart||i.sequenceDiagram?t.loadScript(o+"raphael.min",function(){t.loadScript(o+"underscore.min",function(){!i.flowChart&&i.sequenceDiagram?t.loadScript(o+"sequence-diagram.min",function(){e.loadedDisplay()}):i.flowChart&&!i.sequenceDiagram?t.loadScript(o+"flowchart.min",function(){t.loadScript(o+"jquery.flowchart.min",function(){e.loadedDisplay()})}):i.flowChart&&i.sequenceDiagram&&t.loadScript(o+"flowchart.min",function(){t.loadScript(o+"jquery.flowchart.min",function(){t.loadScript(o+"sequence-diagram.min",function(){e.loadedDisplay()})})})})}):e.loadedDisplay())};return t.loadCSS(o+"codemirror/codemirror.min"),i.searchReplace&&(t.loadCSS(o+"codemirror/addon/dialog/dialog"),t.loadCSS(o+"codemirror/addon/search/matchesonscrollbar")),i.codeFold&&t.loadCSS(o+"codemirror/addon/fold/foldgutter"),t.loadScript(o+"codemirror/codemirror.min",function(){t.$CodeMirror=CodeMirror,t.loadScript(o+"codemirror/modes.min",function(){t.loadScript(o+"codemirror/addons.min",function(){return e.setCodeMirror(),"gfm"!==i.mode&&"markdown"!==i.mode?(e.loadedDisplay(),!1):(e.setToolbar(),void t.loadScript(o+"marked.min",function(){t.$marked=marked,i.previewCodeHighlight?t.loadScript(o+"prettify.min",function(){r()}):r()}))})})}),this},setTheme:function(e){var i=this.settings;return i.theme=e,"default"!==e&&t.loadCSS(i.path+"codemirror/theme/"+i.theme),this.cm.setOption("theme",e),this},setCodeMirror:function(){var e=this.settings,i=this.editor;"default"!==e.theme&&t.loadCSS(e.path+"codemirror/theme/"+e.theme);var o={mode:e.mode,theme:e.theme,tabSize:4,dragDrop:!1,autofocus:!0,autoCloseTags:e.autoCloseTags,readOnly:e.readOnly?"nocursor":!1,indentUnit:4,lineNumbers:e.lineNumbers,lineWrapping:!0,extraKeys:{"Ctrl-Q":function(e){e.foldCode(e.getCursor())}},foldGutter:e.codeFold,gutters:["CodeMirror-linenumbers","CodeMirror-foldgutter"],matchBrackets:!0,indentWithTabs:!0,styleActiveLine:e.styleActiveLine,styleSelectedText:!0,autoCloseBrackets:!0,showTrailingSpace:!0,highlightSelectionMatches:e.matchWordHighlight?{showToken:"onselected"==e.matchWordHighlight?!1:/\w/}:!1};return this.codeEditor=this.cm=t.$CodeMirror.fromTextArea(this.markdownTextarea[0],o),this.codeMirror=this.cmElement=i.children(".CodeMirror"),""!==e.value&&this.cm.setValue(e.value),this.codeMirror.css({fontSize:e.fontSize,width:e.watch?"50%":"100%"}),this},getCodeMirrorOption:function(e){return this.cm.getOption(e)},setCodeMirrorOption:function(e,t){return this.cm.setOption(e,t),this},addKeyMap:function(e,t){return this.cm.addKeyMap(e,t),this},removeKeyMap:function(e){return this.cm.removeKeyMap(e),this},"extends":function(){return"undefined"!=typeof arguments[1]&&("function"==typeof arguments[1]&&(arguments[1]=e.proxy(arguments[1],this)),this[arguments[0]]=arguments[1]),"object"==typeof arguments[0]&&"undefined"==typeof arguments[0].length&&e.extend(!0,this,arguments[0]),this},set:function(t,i){return"undefined"!=typeof i&&"function"==typeof i&&(i=e.proxy(i,this)),this[t]=i,this},config:function(t,i){var o=this.settings;return"object"==typeof t&&(o=e.extend(!0,o,t)),"string"==typeof t&&(o[t]=i),this.settings=o,this.recreate(),this},on:function(t,i){var o=this.settings;return"undefined"!=typeof o["on"+t]&&(o["on"+t]=e.proxy(i,this)),this},off:function(e){var t=this.settings;return"undefined"!=typeof t["on"+e]&&(t["on"+e]=function(){}),this},showToolbar:function(t){var i=this.settings;if(!i.readOnly)return i.toolbar&&(this.toolbar.length<1||""===this.toolbar.find("."+this.classPrefix+"menu").html())&&this.setToolbar(),i.toolbar=!0,this.toolbar.show(),this.resize(),e.proxy(t||function(){},this)(),this},hideToolbar:function(t){var i=this.settings;return i.toolbar=!1,this.toolbar.hide(),this.resize(),e.proxy(t||function(){},this)(),this},setToolbar:function(){var e=this.settings;if(!e.readOnly){var i=this.editor,o=(this.preview,this.classPrefix),r=this.toolbar=i.children("."+o+"toolbar");if(e.toolbar&&r.length<1&&(i.append('
                '),r=this.toolbar=i.children("."+o+"toolbar")),!e.toolbar)return void r.hide();r.show();for(var n="function"==typeof e.toolbarIcons?e.toolbarIcons():"string"==typeof e.toolbarIcons?t.toolbarModes[e.toolbarIcons]:e.toolbarIcons,a=r.find("."+this.classPrefix+"menu"),s="",l=0,c=n.length;c>l;l++){var d=n[l];if("|"!==d){var h=/h(\d)/.test(d),u=d;"watch"!==d||e.watch||(u="unwatch");var f=e.lang.toolbar[u],g=e.toolbarIconTexts[u],m=e.toolbarIconsClass[u];f="undefined"==typeof f?"":f,g="undefined"==typeof g?"":g,m="undefined"==typeof m?"":m,s+="
              • ",s+="undefined"!=typeof e.toolbarCustomIcons[d]?e.toolbarCustomIcons[d]:''+(h?d:""===m?g:"")+"",s+="
              • "}else s+='
              • |
              • '}return a.html(s),this.setToolbarHandler(),this}},dialogLockScreen:function(){return e.proxy(t.dialogLockScreen,this)(),this},dialogShowMask:function(i){return e.proxy(t.dialogShowMask,this)(i),this},getToolbarHandles:function(e){var i=this.toolbarHandlers=t.toolbarHandlers;return e&&"undefined"!=typeof toolbarIconHandlers[e]?i[e]:i},setToolbarHandler:function(){var i=this,o=this.settings;if(o.toolbar&&!o.readOnly){var r=(this.editor,this.preview,this.toolbar),n=this.codeEditor,a=(this.codeMirror,this.classPrefix),s=(this.previewContainer,this.toolbarIcons=r.find("."+a+"menu a")),l=this.getToolbarHandles();return s.bind(t.mouseOrTouch("click","touchend"),function(){var t=e(this).children(".fa"),r=t.attr("name"),a=n.getCursor(),s=n.getSelection();return""!==r?(i.activeIcon=t,"undefined"!=typeof l[r]?e.proxy(l[r],i)(n):"undefined"!=typeof o.toolbarHandlers[r]&&e.proxy(o.toolbarHandlers[r],i)(n,t,a,s),"link"!==r&&"anchor"!==r&&"image"!==r&&"code-block"!==r&&"preformatted-text"!==r&&"watch"!==r&&"preview"!==r&&"fullscreen"!==r&&"info"!==r&&n.focus(),!1):void 0}),this}},createDialog:function(i){return e.proxy(t.createDialog,this)(i)},createInfoDialog:function(){var e=this,i=this.editor,o=this.classPrefix,r=['
                ','
                ','

                '+t.title+"v"+t.version+"

                ","

                "+this.lang.description+"

                ",'

                Home page: '+t.homePage+"

                ","

                License: MIT

                ","
                ",'',"
                "].join("\n");i.append(r);var n=this.infoDialog=i.children("."+o+"dialog-info");return n.find("."+o+"dialog-close").bind(t.mouseOrTouch("click","touchend"),function(){e.hideInfoDialog()}),n.css("border",t.isIE8?"1px solid #ddd":"").css("z-index",t.dialogZindex).show(),this.infoDialogPosition(),this},infoDialogPosition:function(){var t=this.infoDialog,i=function(){t.css({top:(e(window).height()-t.height())/2+"px",left:(e(window).width()-t.width())/2+"px"})};return i(),e(window).resize(i),this},showInfoDialog:function(){e("html,body").css("overflow-x","hidden");var i=this.editor,o=this.settings,r=this.classPrefix,n=this.infoDialog=i.children("."+r+"dialog-info");return n.length<1&&this.createInfoDialog(),this.lockScreen(!0),this.mask.css({opacity:o.dialogMaskOpacity,backgroundColor:o.dialogMaskBgColor}).show(),n.css("z-index",t.dialogZindex).show(),this.infoDialogPosition(),this},hideInfoDialog:function(){return e("html,body").css("overflow-x",""),this.infoDialog.hide(),this.mask.hide(),this.lockScreen(!1),this},lockScreen:function(e){return t.lockScreen(e),this},recreate:function(){var e=this.editor,t=this.settings,i=t.toolbarIcons();return this.codeMirror.remove(),this.setCodeMirror(),"undefined"!=typeof this.infoDialog&&this.infoDialog.remove(),"undefined"!=typeof i.info&&createInfoDialog(),t.readOnly||(e.find(".editormd-dialog").length>0&&e.find(".editormd-dialog").remove(),t.toolbar&&(this.getToolbarHandles(),this.setToolbar())),this.saveToTextareas(),this.resize(),this},previewCodeHighlight:function(){var e=this.settings,t=this.previewContainer;return e.previewCodeHighlight&&(t.find("pre").addClass("prettyprint linenums"),"undefined"!=typeof prettyPrint&&prettyPrint()),this},katexRender:function(){var i=this.previewContainer;return i.find("."+t.classNames.tex).each(function(){var i=e(this);t.$katex.render(i.html(),i[0])}),this},flowChartAndSequenceDiagramRender:function(){var e=this.settings,i=this.previewContainer;return t.isIE8?void 0:(e.flowChart&&i.find(".flowchart").flowChart(),e.sequenceDiagram&&i.find(".sequence-diagram").sequenceDiagram({theme:"simple"}),this)},loadedDisplay:function(){var i=this,o=this.editor,r=this.preview,n=this.settings,a=this.codeEditor,s=this.codeMirror,l=(this.previewContainer,t.mouseOrTouch);o.children("."+this.classPrefix+"container-mask").hide(),this.saveToTextareas(),n.watch&&r.show(),o.data("oldWidth",o.width()).data("oldHeight",o.height()),this.resize(),e(window).resize(function(){i.resize()});var c=function(){s.find(".CodeMirror-scroll").bind(l("scroll","touchmove"),function(t){var i=e(this).height(),o=e(this).scrollTop(),a=o/e(this)[0].scrollHeight;r.scrollTop(0===o?0:o+i>=e(this)[0].scrollHeight?r[0].scrollHeight:r[0].scrollHeight*a),e.proxy(n.onscroll,this)(t)})},d=function(){s.find(".CodeMirror-scroll").unbind(l("scroll","touchmove"))},h=function(){r.bind(l("scroll","touchmove"),function(){var t=e(this).height(),i=e(this).scrollTop(),o=i/e(this)[0].scrollHeight,r=s.find(".CodeMirror-scroll");r.scrollTop(0===i?0:i+t>=e(this)[0].scrollHeight?r[0].scrollHeight:r[0].scrollHeight*o),e.proxy(n.onpreviewscroll,this)(event)})},u=function(){r.unbind(l("scroll","touchmove"))};return s.bind({mouseover:c,mouseout:d,touchstart:c,touchend:d}),r.bind({mouseover:h,mouseout:u,touchstart:h,touchend:u}),a.on("change",function(){i.saveToTextareas()}),e.proxy(n.onload,this)(),this.state.loaded=!0,this},width:function(e){return this.editor.css("width","number"==typeof e?e+"px":e),this.resize(),this},height:function(e){return this.editor.css("height","number"==typeof e?e+"px":e),this.resize(),this},resize:function(t,i){t=t||null,i=i||null;var o=this.editor,r=this.preview,n=this.toolbar,a=this.settings,s=(this.codeEditor,this.codeMirror);return t&&i&&o.css({width:"number"==typeof t?t+"px":t,height:"number"==typeof i?i+"px":i}),a.toolbar&&!a.readOnly?s.css("margin-top",n.height()+1).height(o.height()-n.height()):s.css("margin-top",0).height(o.height()),s.find(".CodeMirror-gutters").height(s.height()),a.watch?(s.width(o.width()/2),r.width(this.state.preview?o.width():o.width()/2),a.toolbar&&!a.readOnly?r.css("top",n.height()).height(o.height()-n.height()):r.css("top",0).height(o.height())):(s.width(o.width()),r.hide()),this.state.loaded&&e.proxy(a.onresize,this)(),this},saveToTextareas:function(){var i=this,o=this.state,r=this.settings,n=this.codeEditor,a=this.previewContainer,s=n.getValue();if("gfm"!==r.mode&&"markdown"!==r.mode)return this.markdownTextarea[0].innerText=s,this;var l=t.$marked,c=this.markdownToC=[],d=this.markedRendererOptions={toc:r.toc,tocStartLevel:r.tocStartLevel,taskList:r.taskList,emoji:r.emoji,tex:r.tex,flowChart:r.flowChart,sequenceDiagram:r.sequenceDiagram,previewCodeHighlight:r.previewCodeHighlight},h=this.markedOptions={renderer:t.markedRenderer(c,d),gfm:!0,tables:!0,breaks:!0,pedantic:!1,sanitize:r.htmlDecode?!1:!0,smartLists:!0,smartypants:!0};l.setOptions(h),s=t.filterHTMLTags(s,r.htmlDecode);var u=t.$marked(s,h);if(this.markdownTextarea[0].innerText=s,n.save(),r.saveHTMLToTextarea&&this.htmlTextarea.html(u),r.watch||!r.watch&&o.preview){if(a.html(u),this.previewCodeHighlight(),r.toc&&t.markdownToCRenderer(c,a,r.tocStartLevel),r.tex&&(r.inRequirejs||t.kaTeXLoaded?this.katexRender():t.loadKaTeX(function(){t.$katex=katex,t.kaTeXLoaded=!0,i.katexRender()})),r.flowChart||r.sequenceDiagram)var f=setTimeout(function(){clearTimeout(f),i.flowChartAndSequenceDiagramRender()},10);o.loaded&&e.proxy(r.onchange,this)()}return this},focus:function(){return this.codeEditor.focus(),this},setCursor:function(e){return this.codeEditor.setCursor(e),this},getCursor:function(){return this.codeEditor.getCursor()},setSelection:function(e,t){return this.codeEditor.setSelection(e,t),this},getSelection:function(){return this.codeEditor.getSelection()},replaceSelection:function(e){return this.codeEditor.replaceSelection(e),this},insertValue:function(e){return this.replaceSelection(e),this},setMarkdown:function(e){var t=this.settings;return this.codeEditor.setValue(e||t.markdown),this},getMarkdown:function(){return this.codeEditor.getValue()},getValue:function(){return this.codeEditor.getValue()},setValue:function(e){return this.codeEditor.setValue(e),this},clear:function(){return this.codeEditor.setValue(""),this},getHTML:function(){return this.settings.saveHTMLToTextarea?this.htmlTextarea.html():(alert("Error: settings.saveHTMLToTextarea == false"),!1)},getTextareaSavedHTML:function(){return this.getHTML()},getPreviewedHTML:function(){return this.settings.watch?this.previewContainer.html():(alert("Error: settings.watch == false"),!1)},watch:function(t){var i=this.settings;this.state.watching=i.watch=!0,this.preview.show();var o=i.toolbarIconsClass.watch,r=i.toolbarIconsClass.unwatch,n=this.toolbar.find(".fa[name=watch]");return n.parent().attr("title",i.lang.toolbar.watch),n.removeClass(r).addClass(o),this.codeMirror.css("border-right","1px solid #ddd").width(this.editor.width()/2),this.saveToTextareas().resize(),i.onwatch||(i.onwatch=t||function(){}),e.proxy(i.onwatch,this)(),this},unwatch:function(t){var i=this.settings;this.state.watching=i.watch=!1,this.preview.hide();var o=i.toolbarIconsClass.watch,r=i.toolbarIconsClass.unwatch;if(this.toolbar){var n=this.toolbar.find(".fa[name=watch]");n.parent().attr("title",i.lang.toolbar.unwatch),n.removeClass(o).addClass(r)}return this.codeMirror.css("border-right","none").width(this.editor.width()),this.resize(),i.onunwatch||(i.onunwatch=t||function(){}),e.proxy(i.onunwatch,this)(),this},show:function(t){t=t||function(){};var i=this;return this.editor.show(function(){e.proxy(t,i)()}),this},hide:function(t){t=t||function(){};var i=this;return this.editor.hide(function(){e.proxy(t,i)()}),this},previewing:function(){var i=this,o=this.editor,r=this.preview,n=this.toolbar,a=this.settings,s=this.codeMirror;a.toolbar&&(n.toggle(),n.find(".fa[name=preview]").toggleClass("active")),s.toggle(),"none"===s.css("display")?(this.state.preview=!0,this.state.fullscreen&&r.css("background","#fff"),o.find("."+this.classPrefix+"preview-close-btn").show().bind(t.mouseOrTouch("click","touchend"),function(){i.previewed()}),a.watch||this.saveToTextareas(),r.show().css({position:"static",top:0,width:o.width(),height:o.height()}),this.state.loaded&&e.proxy(a.onpreviewing,this)()):this.previewed(),e(window).keyup(function(e){27===e.keyCode&&i.previewed()})},previewed:function(){var i=this.editor,o=this.preview,r=this.toolbar,n=this.settings,a=this.codeMirror,s=i.find("."+this.classPrefix+"preview-close-btn");return this.state.preview=!1,a.show(),n.toolbar&&r.show(),this.settings.watch?o.show():o.hide(),s.hide().bind(t.mouseOrTouch("click","touchend")),o.css({background:null,position:"absolute",width:i.width()/2,height:i.height()-r.height(),top:n.toolbar?r.height():0}),this.state.loaded&&e.proxy(n.onpreviewed,this)(),this},fullscreen:function(){var t=this,i=this.editor,o=(this.preview,this.toolbar),r=this.classPrefix+"fullscreen";return o&&o.find(".fa[name=fullscreen]").parent().toggleClass("active"),i.hasClass(r)?this.fullscreenExit():(this.state.fullscreen=!0,e("html,body").css("overflow","hidden"),i.css({position:"fixed",top:0,left:0,margin:0,border:"none",width:e(window).width(),height:e(window).height()}).addClass(r),this.resize(),e.proxy(this.settings.onfullscreen,this)()),e(window).keyup(function(e){t.state.preview||27===e.keyCode&&t.fullscreenExit()}),this},fullscreenExit:function(){var t=this.editor,i=this.toolbar,o=this.classPrefix+"fullscreen";return this.state.fullscreen=!1,i&&i.find(".fa[name=fullscreen]").parent().removeClass("active"),e("html,body").css("overflow",""),t.css({position:"",top:"",left:"",margin:"0 auto",width:t.data("oldWidth"),height:t.data("oldHeight"),border:"1px solid #ddd"}).removeClass(o),this.resize(),e.proxy(this.settings.onfullscreenExit,this)(),this},executePlugin:function(i,o){var r=this,n=this.cm;return"function"==typeof define?void this[i](n):(o=this.settings.path+"../plugins/"+o,void(e.inArray(o,t.loadFiles.plugin)<0?t.loadPlugin(o,function(){t.loadPlugins[i]=r[i],r[i](n)}):e.proxy(t.loadPlugins[i],this)(n)))}},t.fn.init.prototype=t.fn,t.dialogLockScreen=function(){var t=this.settings;t.dialogLockScreen&&e("html,body").css("overflow","hidden")},t.dialogShowMask=function(t){var i=this.editor,o=this.settings;t.css({top:(e(window).height()-t.height())/2+"px",left:(e(window).width()-t.width())/2+"px"}),o.dialogShowMask&&i.children("."+this.classPrefix+"mask").css("z-index",parseInt(t.css("z-index"))-1).show()},t.toolbarHandlers={undo:function(){this.cm.undo()},redo:function(){this.cm.redo()},bold:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("**"+i+"**"),""===i&&e.setCursor(t.line,t.ch+2)},del:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("~~"+i+"~~"),""===i&&e.setCursor(t.line,t.ch+2)},italic:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("*"+i+"*"),""===i&&e.setCursor(t.line,t.ch+1)},quote:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("> "+i),e.setCursor(t.line,""===i?t.ch+2:t.ch+i.length+2)},h1:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("# "+t)},h2:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("## "+t)},h3:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("### "+t)},h4:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("#### "+t)},h5:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("##### "+t)},h6:function(){var e=this.cm,t=e.getSelection();e.replaceSelection("###### "+t)},"list-ul":function(){var e=this.cm,t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("- "+t);else{for(var i=t.split("\n"),o=0,r=i.length;r>o;o++)i[o]=""===i[o]?"":"- "+i[o];e.replaceSelection(i.join("\n"))}},"list-ol":function(){var e=this.cm,t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("1. "+t);else{for(var i=t.split("\n"),o=0,r=i.length;r>o;o++)i[o]=""===i[o]?"":o+1+". "+i[o];e.replaceSelection(i.join("\n"))}},hr:function(){{var e=this.cm;e.getCursor(),e.getSelection()}e.replaceSelection("------------")},link:function(){this.executePlugin("linkDialog","link-dialog/link-dialog")},anchor:function(){this.executePlugin("anchorLinkDialog","anchor-link-dialog/anchor-link-dialog")},image:function(){this.executePlugin("imageDialog","image-dialog/image-dialog")},code:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("`"+i+"`"),""===i&&e.setCursor(t.line,t.ch+1)},"code-block":function(){this.executePlugin("codeBlockDialog","code-block-dialog/code-block-dialog")},"preformatted-text":function(){this.executePlugin("preformattedTextDialog","preformatted-text-dialog/preformatted-text-dialog")},table:function(){this.executePlugin("tableDialog","table-dialog/table-dialog")},datetime:function(){var e=this.cm,i=(e.getSelection(),new Date,this.settings.lang.name),o=t.dateFormat()+" "+t.dateFormat("zh-cn"===i||"zh-tw"===i?"cn-week-day":"week-day");e.replaceSelection(o)},emoji:function(){this.executePlugin("emojiDialog","emoji-dialog/emoji-dialog")},htmlEntities:function(){this.executePlugin("htmlEntitiesDialog","html-entities-dialog/html-entities-dialog")},watch:function(){this[this.settings.watch?"unwatch":"watch"]()},preview:function(){this.previewing()},fullscreen:function(){this.fullscreen()},clear:function(){this.clear()},help:function(){this.executePlugin("helpDialog","help-dialog/help-dialog")},info:function(){this.showInfoDialog()}},t.trim=function(e){return String.prototype.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")};var i=t.trim;return t.urls={atLinkBase:"https://github.com/"},t.regex={atLink:/@(\w+)/g,emoji:/:([\-\w]+):/g,twemoji:/:(tw-([\w]+)-?(\w+)?):/g,fontAwesome:/:(fa-([\w]+)-?(\w+)?):/g,editormdLogo:/:(editormd-logo-?(\w+)?):/g},t.emoji={path:"http://www.emoji-cheat-sheet.com/graphics/emojis/",ext:".png"},t.twemoji={path:"http://twemoji.maxcdn.com/36x36/",ext:".png"},t.markedRenderer=function(o,r){var n={toc:!0,tocStartLevel:1,taskList:!1,emoji:!1,tex:!1,flowChart:!1,sequenceDiagram:!1},a=t.regex.atLink,s=e.extend(n,r||{}),l=t.$marked,c=new l.Renderer;o=o||[];var d=t.regex.emoji,h=t.regex.twemoji,u=t.regex.fontAwesome,f=t.regex.editormdLogo;return c.emoji=function(e){var i=e.match(d);if(!i||!s.emoji)return e;for(var o=0,r=i.length;r>o;o++)e=e.replace(new RegExp(i[o]),function(e){var i=e.match(u),o=e.replace(/:/g,"");if(i)for(var r=0,n=i.length;n>r;r++){var a=i[r].replace(/:/g,"");return''}else{var s=e.match(f),l=e.match(h);if(s)for(var c=0,d=s.length;d>c;c++){var g=s[c].replace(/:/g,"");return''}else{if(!l)return':'+o+':';for(var m=0,p=l.length;p>m;m++){var w=l[m].replace(/:/g,"").replace("tw-","");return'twemoji-'+w+''}}}});return e},c.atLink=function(e){return a.test(e)&&(e=e.replace(a,function(e,i){return''+e+""})),e},c.link=function(e,t,i){if(this.options.sanitize){try{var o=decodeURIComponent(unescape(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(r){return""}if(0===o.indexOf("javascript:"))return""}var n=''+i.replace(/@/g,"@")+""):(t&&(n+=' title="'+t+'"'),n+=">"+i+"")},c.heading=function(e,t){var r=e,n=/\s*\]*)\>(.*)\<\/a\>\s*/;if(n.test(e)){var a=[];e=e.split(/\]+)\>([^\>]*)\<\/a\>/);for(var s=0,l=e.length;l>s;s++)a.push(e[s].replace(/\s*href\=\"(.*)\"\s*/g,""));e=a.join(" ")}e=i(e);var c=e.toLowerCase().replace(/[^\w]+/g,"-"),d={text:e,level:t,slug:c},h=/^[\u4e00-\u9fa5]+$/.test(e),u=h?escape(e).replace(/\%/g,""):e.toLowerCase().replace(/[^\w]+/g,"-");o.push(d);var f="';return f+='',f+='',f+=this.atLink(n?this.emoji(r):this.emoji(e)),f+=""},c.paragraph=function(e){var i=/\$\$(.*)\$\$/g.test(e),o=/^\$\$(.*)\$\$$/.test(e),r=o?' class="'+t.classNames.tex+'"':"",n=/^\[TOC\]$/.test(e);return e=!o&&i?e.replace(/(\$\$([^\$]*)\$\$)+/g,function(e,i){return''+i.replace(/\$/g,"")+""}):o?e.replace(/\$/g,""):e,n?'
                  '+e+"
                ":""+this.atLink(this.emoji(e))+"

                \n"},c.code=function(e,t){return"seq"===t||"sequence"===t?'
                '+e+"
                ":"flow"===t?'
                '+e+"
                ":l.Renderer.prototype.code.apply(this,arguments)},c.tablecell=function(e,t){var i=t.header?"th":"td",o=t.align?"<"+i+' style="text-align:'+t.align+'">':"<"+i+">";return o+this.atLink(this.emoji(e))+"\n"},c.listitem=function(e){return s.taskList&&/^\s*\[[x\s]\]\s*/.test(e)?(e=e.replace(/^\s*\[\s\]\s*/,' ').replace(/^\s*\[x\]\s*/,' '),'
              • '+this.atLink(this.emoji(e))+"
              • "):"
              • "+this.atLink(this.emoji(e))+"
              • "},c},t.markdownToCRenderer=function(e,t,i){var o="",r=0;i=i||1;for(var n=0,a=e.length;a>n;n++){var s=e[n].text,l=e[n].level;i>l||(o+=l>r?"":r>l?new Array(r-l+2).join("
            • "):"",o+='
            • '+s+"
                ",r=l)}var c=t.find(".markdown-toc");return c.children(".markdown-toc-list").html("").html(o),c},t.filterHTMLTags=function(e,t){if("string"==typeof t)for(var i=t.split(","),o=0,r=i.length;r>o;o++){var n=i[o];e=e.replace(new RegExp("]*)>","igm"),"").replace(new RegExp("","igm"),"")}return e},t.markdownToHTML=function(i,o){var r={gfm:!0,toc:!0,tocStartLevel:1,markdown:"",htmlDecode:!1,inRequirejs:!1,tex:!1,taskList:!1,emoji:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0};t.$marked=marked;var n=e("#"+i),a=n.settings=e.extend(!0,r,o||{}),s=n.find("textarea"),l=""===a.markdown?s.val():a.markdown,c=[],d={toc:a.toc,tocStartLevel:a.tocStartLevel,taskList:a.taskList,emoji:a.emoji,tex:a.tex,flowChart:a.flowChart,sequenceDiagram:a.sequenceDiagram,previewCodeHighlight:a.previewCodeHighlight},h={renderer:t.markedRenderer(c,d),gfm:a.gfm,tables:!0,breaks:!0,pedantic:!1,sanitize:a.htmlDecode?!1:!0,smartLists:!0,smartypants:!0};l=t.filterHTMLTags(l,a.htmlDecode);var u=marked(l,h);if(t.isIE8?s.val(l):s.html(l),n.addClass("markdown-body "+this.classPrefix+"html-preview").append(u),a.toc&&(n.tocContainer=this.markdownToCRenderer(c,n,a.tocStartLevel)),a.previewCodeHighlight&&(n.find("pre").addClass("prettyprint linenums"),prettyPrint()),t.isIE8||(a.flowChart&&n.find(".flowchart").flowChart(),a.sequenceDiagram&&n.find(".sequence-diagram").sequenceDiagram({theme:"simple"})),a.tex){var f=function(){n.find("."+t.classNames.tex).each(function(){var i=e(this);t.$katex.render(i.html(),i[0])}) +};a.inRequirejs?f():this.loadKaTeX(function(){t.$katex=katex,f()})}return n.getMarkdown=function(){return t.isIE8?s.val():s.html()},n},t.themes=["default","3024-day","3024-night","ambiance","ambiance-mobile","base16-dark","base16-light","blackboard","cobalt","eclipse","elegant","erlang-dark","lesser-dark","mbo","mdn-like","midnight","monokai","neat","neo","night","paraiso-dark","paraiso-light","pastel-on-dark","rubyblue","solarized","the-matrix","tomorrow-night-eighties","twilight","vibrant-ink","xq-dark","xq-light"],t.loadPlugins={},t.loadFiles={js:[],css:[],plugin:[]},t.loadPlugin=function(e,i,o){i=i||function(){},this.loadScript(e,function(){t.loadFiles.plugin.push(e),i()},o)},t.loadCSS=function(e,i,o){o=o||"head",i=i||function(){};var r=document.createElement("link");r.type="text/css",r.rel="stylesheet",r.onload=r.onreadystatechange=function(){t.loadFiles.css.push(e),i()},r.href=e+".css","head"===o?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.isIE="Microsoft Internet Explorer"==navigator.appName,t.isIE8=t.isIE&&"8."==navigator.appVersion.match(/8./i),t.loadScript=function(e,i,o){o=o||"head",i=i||function(){};var r=null;r=document.createElement("script"),r.id=e.replace(/[\./]+/g,"-"),r.type="text/javascript",r.src=e+".js",t.isIE8?r.onreadystatechange=function(){r.readyState&&("loaded"===r.readyState||"complete"===r.readyState)&&(r.onreadystatechange=null,t.loadFiles.js.push(e),i())}:r.onload=function(){t.loadFiles.js.push(e),i()},"head"===o?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.katexURL={css:"http://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min",js:"http://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min"},t.kaTeXLoaded=!1,t.loadKaTeX=function(e){t.loadCSS(t.katexURL.css,function(){t.loadScript(t.katexURL.js,e||function(){})})},t.lockScreen=function(t){e("html,body").css("overflow",t?"hidden":"")},t.createDialog=function(i){var o={name:"",width:420,height:240,title:"",drag:!0,closed:!0,content:"",mask:!0,maskStyle:{backgroundColor:"#fff",opacity:.1},lockScreen:!0,footer:!0,buttons:!1};i=e.extend(!0,o,i);var r=this.editor,n=t.classPrefix,a=(new Date).getTime(),s=""===i.name?n+"dialog-"+a:i.name,l=t.mouseOrTouch,c='
                ';""!==i.title&&(c+='
                ",c+=''+i.title+"",c+="
                "),i.closed&&(c+=''),c+='
                '+i.content,(i.footer||"string"==typeof i.footer)&&(c+='"),c+="
                ",c+='
                ',c+='
                ',c+="
                ",r.append(c);var d=r.find("."+s);d.lockScreen=function(t){return i.lockScreen&&e("html,body").css("overflow",t?"hidden":""),d},d.showMask=function(){return i.mask&&r.find("."+n+"mask").css(i.maskStyle).css("z-index",t.dialogZindex-1).show(),d},d.hideMask=function(){return i.mask&&r.find("."+n+"mask").hide(),d},d.loading=function(e){var t=d.find("."+n+"dialog-mask");return t[e?"show":"hide"](),d},d.lockScreen(!0).showMask(),d.show().css({zIndex:t.dialogZindex,border:t.isIE8?"1px solid #ddd":"",width:"number"==typeof i.width?i.width+"px":i.width,height:"number"==typeof i.height?i.height+"px":i.height});var h=function(){d.css({top:(e(window).height()-d.height())/2+"px",left:(e(window).width()-d.width())/2+"px"})};if(h(),e(window).resize(h),d.children("."+n+"dialog-close").bind(l("click","touchend"),function(){d.hide().lockScreen(!1).hideMask()}),"object"==typeof i.buttons){var u=d.footer=d.find("."+n+"dialog-footer");for(var f in i.buttons){var g=i.buttons[f],m=n+f+"-btn";u.append('"),g[1]=e.proxy(g[1],d),u.children("."+m).bind(l("click","touchend"),g[1])}}if(""!==i.title&&i.drag){var p,w,v=d.children("."+n+"dialog-header");i.mask||v.bind(l("click","touchend"),function(){t.dialogZindex+=2,d.css("z-index",t.dialogZindex)}),v.mousedown(function(e){e=e||window.event,p=e.clientX-parseInt(d[0].style.left),w=e.clientY-parseInt(d[0].style.top),document.onmousemove=k});var x=function(e){e.removeClass(n+"user-unselect").off("selectstart")},b=function(e){e.addClass(n+"user-unselect").on("selectstart",function(){return!1})},k=function(t){t=t||window.event;var i,o,r=parseInt(d[0].style.left),n=parseInt(d[0].style.top);r>=0?r+d.width()<=e(window).width()?i=t.clientX-p:(i=e(window).width()-d.width(),document.onmousemove=null):(i=0,document.onmousemove=null),n>=0?o=t.clientY-w:(o=0,document.onmousemove=null),document.onselectstart=function(){return!1},b(e("body")),b(d),d[0].style.left=i+"px",d[0].style.top=o+"px"};document.onmouseup=function(){x(e("body")),x(d),document.onselectstart=null,document.onmousemove=null},v.touchDraggable=function(){var t=null,i=function(i){var o=i.originalEvent,r=e(this).parent().position();t={x:o.changedTouches[0].pageX-r.left,y:o.changedTouches[0].pageY-r.top}},o=function(i){i.preventDefault();var o=i.originalEvent;e(this).parent().css({top:o.changedTouches[0].pageY-t.y,left:o.changedTouches[0].pageX-t.x})};this.bind("touchstart",i).bind("touchmove",o)},v.touchDraggable()}return t.dialogZindex+=2,d},t.mouseOrTouch=function(e,t){e=e||"click",t=t||"touchend";var i=e;try{document.createEvent("TouchEvent"),i=t}catch(o){}return i},t.dateFormat=function(e){e=e||"";var t=function(e){return 10>e?"0"+e:e},i=new Date,o=i.getFullYear(),r=o.toString().slice(2,4),n=t(i.getMonth()+1),a=t(i.getDate()),s=i.getDay(),l=t(i.getHours()),c=t(i.getMinutes()),d=t(i.getSeconds()),h=t(i.getMilliseconds()),u="",f=r+"-"+n+"-"+a,g=o+"-"+n+"-"+a,m=l+":"+c+":"+d;switch(e){case"UNIX Time":u=i.getTime();break;case"UTC":u=i.toUTCString();break;case"yy":u=r;break;case"year":case"yyyy":u=o;break;case"month":case"mm":u=n;break;case"cn-week-day":case"cn-wd":var p=["日","一","二","三","四","五","六"];u="星期"+p[s];break;case"week-day":case"wd":var w=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];u=w[s];break;case"day":case"dd":u=a;break;case"hour":case"hh":u=l;break;case"min":case"ii":u=c;break;case"second":case"ss":u=d;break;case"ms":u=h;break;case"yy-mm-dd":u=f;break;case"yyyy-mm-dd":u=g;break;case"yyyy-mm-dd h:i:s ms":case"full + ms":u=g+" "+m+" "+h;break;case"full":case"yyyy-mm-dd h:i:s":default:u=g+" "+m}return u},t}}); \ No newline at end of file diff --git a/examples/127.0.0.1-8888.url b/examples/127.0.0.1-8888.url deleted file mode 100644 index a6d9a2b..0000000 --- a/examples/127.0.0.1-8888.url +++ /dev/null @@ -1,2 +0,0 @@ -[InternetShortcut] -URL=http://127.0.0.1:8888/ diff --git a/examples/@links.html b/examples/@links.html new file mode 100644 index 0000000..2f1eed1 --- /dev/null +++ b/examples/@links.html @@ -0,0 +1,97 @@ + + + + + @links - Editor.md examples + + + + + +
                +
                +

                @links

                +

                Github Flavored Markdown extended syntax

                +
                +
                + +
                +
                + + + + + \ No newline at end of file diff --git a/examples/change-mode.html b/examples/change-mode.html new file mode 100644 index 0000000..3a4da8d --- /dev/null +++ b/examples/change-mode.html @@ -0,0 +1,508 @@ + + + + + Chnage mode - Editor.md examples + + + + + + +
                +
                +

                Chnage mode

                +

                Become to the code editor

                +

                Modes :   Themes : + +

                +
                +
                + + +
                +
                + + + + + + + + + + +
                +
                + +
                +
                + + + + + \ No newline at end of file diff --git a/examples/code-fold.html b/examples/code-fold.html new file mode 100644 index 0000000..fb00756 --- /dev/null +++ b/examples/code-fold.html @@ -0,0 +1,44 @@ + + + + + Code fold - Editor.md examples + + + + + +
                +
                +

                Code fold

                +

                Switch code fold : Press Ctrl + Q / Command + Q

                +
                +
                + +
                +
                + + + + + \ No newline at end of file diff --git a/examples/custom-keyboard-shortcuts.html b/examples/custom-keyboard-shortcuts.html new file mode 100644 index 0000000..4bae7ee --- /dev/null +++ b/examples/custom-keyboard-shortcuts.html @@ -0,0 +1,88 @@ + + + + + Custom keyboard shortcuts - Editor.md examples + + + + + +
                +
                +

                Custom keyboard shortcuts

                +
                +
                + +
                +
                + + + + + \ No newline at end of file diff --git a/examples/custom-toolbar.html b/examples/custom-toolbar.html index 6cb1ef9..4533354 100644 --- a/examples/custom-toolbar.html +++ b/examples/custom-toolbar.html @@ -4,7 +4,8 @@ 自定义工具栏 - Editor.md examples - + +
                @@ -13,15 +14,16 @@

                Custom toolbar (icons handler)

                - +
                +
                + + + + + \ No newline at end of file diff --git a/examples/dynamic-create-editormd.html b/examples/dynamic-create-editormd.html index 7e7f61e..9b8aa38 100644 --- a/examples/dynamic-create-editormd.html +++ b/examples/dynamic-create-editormd.html @@ -4,7 +4,8 @@ 动态创建Editor.md - Editor.md examples - + +
                @@ -25,13 +26,13 @@ $(function() { $("#create-btn").click(function(){ - $.getScript("../src/js/editormd.js", function() { + $.getScript("../editormd.js", function() { $("#layout").append("
                "); testEditormd = editormd("test-editormd", { width: "90%", - height: 240, - markdown : "###动态创建Editor.md\n\nDynamic create Editor.md", + height: 640, + markdown : "### 动态创建Editor.md\n\nDynamic create Editor.md", path : '../lib/' }); }); diff --git a/examples/emoji.html b/examples/emoji.html new file mode 100644 index 0000000..2429f48 --- /dev/null +++ b/examples/emoji.html @@ -0,0 +1,225 @@ + + + + + Emoji - Editor.md examples + + + + + + +
                +
                +

                Emoji表情

                +

                Supports:

                + +
                + + +
                +
                +
                + +
                +
                + + + + + \ No newline at end of file diff --git a/examples/extends.html b/examples/extends.html new file mode 100644 index 0000000..3948af2 --- /dev/null +++ b/examples/extends.html @@ -0,0 +1,153 @@ + + + + + Expanded Editor.md - Editor.md examples + + + + + +
                +
                +

                Expanded Editor.md

                +

                Expanded of member methods and properties

                +
                +
                + +
                +
                + + + + + \ No newline at end of file diff --git a/examples/external-use.html b/examples/external-use.html new file mode 100644 index 0000000..b8a7eb3 --- /dev/null +++ b/examples/external-use.html @@ -0,0 +1,119 @@ + + + + + External use - Editor.md examples + + + + + +
                +
                +

                External use

                +

                External use of toolbar handlers / modal dialog

                +
                +
                + + + + + + + + +
                +
                + +
                +
                + + + + + + + + \ No newline at end of file diff --git a/examples/flowchart.html b/examples/flowchart.html index bcda9fb..d8db673 100644 --- a/examples/flowchart.html +++ b/examples/flowchart.html @@ -4,30 +4,31 @@ FlowChart - Editor.md examples - + +

                FlowChart 流程图

                -

                基于flowchart.js:http://adrai.github.io/flowchart.js/

                +

                Based on flowchart.js:http://adrai.github.io/flowchart.js/

                -
                - + V1eWH?%WDrGzxe+6v|gLv50<8z9*aJf67t3p z54h`%%4RP$Zt|QX$1fF^RE2|7d>#kI#ZW*N+uDFw*B@!S-GV77-?;aDdRlg7cFB#~ zkHaxB#>wsgkII*kK);XJ@&a1F;v*+0ISs`nMr?((J-)s#KDR88#jQ?+6EI>qlPd3a{J0G-}#j`dmToc!v3JqhSD3B)3X(&^KumaJ^BP-3@B?6XFe z)oq$EF|BFm0jo1W^Rh1_*xWH>di#{hihxYy>4bbY<^!(MD~u%h*xVz#()f|ybbF%? zA8kb=3iLIiJu1m&d$4Ke!HH95FJ89JX!V&Ll+`aTU9$Yc?FP}84=-8=ife_CMvOgp{+^pSAqn%Ums#3hR6wUM5a2!%u z!234VhGX(E)lS@8-l*LhBhy7eMg|9`U1walV$+9HGS}}sVF}7z)`%@A(`onIExmBxk@NpQd+!+>N0yxn?*7~TvGIQGi`daYWjwQ55>BV`AjoE76aR_-0P*RF2-YD($qb=%r|^+7?FvNAw|H;Onb z8H_W5gx8<+j@n|Jo0j49>k(gFdru;)3J6R<@C4B@n7&8?EE1?2)Ub2FRJU>amy?PY zuh`PBbB6@kiUm#1fRD@8ZQgPI@c5kzIwLWiE?SU*jgqOm2*#)nlyP z6Qeo#_EXKAdCR|=GzW%|)=a?AilOA_Nq;y-`8ZENM8A&mrsuXmc_Jz1C+h2$1(hIb z8_jKQRgcF+=Rk(g0d>&zK&@^)?5e6+Jz+}e`t8Sb?kGrMz*s#NCBx~mx$}$$!|RT` zfbUM_5bM;Y9fz1`?Bma-?c9F?R48Z+!Y`>Diwee{59xY=qWc~*DE-{^)h5)-^=H9- z5(uZgesrW32)40t{}z6`ON zFRj|RnHFUYCRuU8;RrYx(JRRPCVE@bnJGmJCeEnbv~}O3jzQeV@+nyr-xrM0UQtPm z688kqvIm_H+48(J%<|iG(+eAClKKN8$3md51t=y`vU}5jSf!PVRK!xx zDp1eK&3gqmA3J-Uh-8g82jYXd<_@MAF4Hk=U(>L6!t}Y*=PurT`1Fv@3MN84gH9EX z3MnQi5PlK!is&SVP=S1p9rlsuMtJ1Ke=;w6MU`C@AASh;ieM=QqKT-GQBUP2=+OO^ z9#Ei@XOzt@U3B8yZ5t8saI%>e0j|uX09{E&vIwz8c?DlbT0u34OKs2NXV0$LvKOo< zI~kc;w4iw2QWq12DMJQC3au=}N9)YzCVRS&5txbmfMkrXY6px_(a&g`kZOY_m5}LJ z4Acu5oLRcCxMG>x!@~Gqxo+o`Yd1$9KKEAg3T84Xv@Tm(S~;Y1+L6A?^y{%HGb>9f zmiB6Gz%Be-mI@{nx7f4sLN6w~uaL&{Rm!*exW|ULgwv{CQwhOea6WLXE~7P=)sq|yeNbUKg4beEyFWp4vd$Gc(|m9K z(hU=)%$;4ja6`ks>$lsqdUq(AiY3v(R6<;i#N+@kk46{uum;tkL@QgPUR*+jl0-hP zAbLxEUDXAC4)Gh6NWsqmQaap$hmU&?96DWIwE~FX-0GE0M=x{^+I?&m4`&Rdpv73Y z8Ysa)idHItd6Gq?HLjdju&|DmL#*aYmsW4sOiS{xTeRT<1~^BF@C{~0!dcnoPd)55 zZD>3&vt+@%7Y+j#W!m8YFLl4hg4oXX1T!5m>x_HyVvnw$uV?5`w#t`U+WFDkMt zFQz~uXjnEWgYg9QW~B^H1=>0XPMp5DxVCOaQ3cd$^Y+6}y7cJ8jc5jlf}Rk7GlAt{ zq(mLYL9L$USYy0`VVIDBQXsNP!7V5{oQ2n&!8F0jJr>{Lb9bv3ubVQf8dz83?nAd8 zJT*BP;61S{8fl=9P}d8xdSn9?%n45B*jO^xx!)yw?nTARr@rWkWP&_8=@>{Jm|rje z{9#dRa9(J>y>8>S;*yH#v&w5%Z@qZ^iOJ{G``jQc?3# z#M)ec3^-O)HY!kULW-W%;C`!*r=_fki8ep#T)uI8(VTg+=ajFk+kEoOvOnJfg-=4ybiK-Al@K)!H7u7vKcvv;jNQdNc-*mT?}5ts z%f6X5r@V6U&i$vmhi!B?0gZ3Lf?%NJIuQl{#!^waw5;6pMi5I~$2xZA%(})V51X|U z5g3pSyN-SI={LvDTnUL8=s{03P59$#3%p3z6*g?8Jl{h}en&>#7iiRiXM1!icf~7+ zEKXnCAIc=svOg#uIC%DVf1JMW$ax^LHX;lt04Boat8bfQ$;dN?cBYh+Rrc$hb_N+K zZhwM_W)GdY`RRn>>e@|RLsqbBKr#6v3ED3(P=X0W)kkk#dUpRr(gQZd$T4nlB{4Aa zM~^zAEO+(hK18n+PJUBfPrig>Dc_HRqhe4Q!ozt(F(HBM?jDU}(WR*S4m!D$DonHd53rkjQ zomH}A(#-18s@3Zo4_>+3rE>oxv4CT}%qw`Y`O?ab zn>_;JSTNfyL|Bh;@FJicXnX@9IDJWkMp1ddM4!0yaQV8OMdiyU&8RM`T(M%^?xrJ` zZ$0Sk8n9aNP>@qpOa>hd2lbDo(P3R2GRzh6g>0b_Mi=-mJOfX{E6`}F?1FM8Jf3!6yZL`i_wa0L;d zDWK+SwtO360mm{?;%LM&(+KwTI1j}{$0$~&BeEHf-h4c;b>FG-n)TC)tG_9#TC}=; z>%QY>uRna;qt}~hZy*8vn3DoUk)wnAfRw1>qauzO25`@c=yM>f@D@-9XfD+ISu|$g zbKr0TX8eA~(89!#KxKqw$4t6b6GR|U_1s6GJls)8fglV~FN z!wI9)*EVRre6M}S!P86DG)yh3`g+E^lFH@l8unef*{Zd9Xmm26Y^Mbi^gEcOc+?EN zulAtAu>i4vW4$TF%5f|}EFUi$-C-jZfty}EQND2Pq-kYmFWvA*;?TV_-~jDNi=Y{DX7maSUVfr9Ba#ih`8&hGRH7lSUkI3q(fz&I)KJ0Ht$z1ab#s zCzN~yNx!mdB!8TITDed9m8c~3ux%v+BV3UyK>4bqCo(!fOLdjRFt6YVNn%V+q-3w3 zYi_7T}3g|GT)TopfxhUs~`HP=CHQ`>_ zNb-6*Vxo96q0C;;WqFqo=y6bO&On;tWYjW@)S<;sUvJ&8>(t`99Yy6!XUs-K&1TXwEmU0+(hc+&Lp8AVky=PamLuxevtQ`6}i_q)s>7Yz`iR)dz1n5xE6 z)UK+0&FF?V5rX91a{w37aT*T||w5zC@8-`3ajRj)!GN zkg>2lWDnkH*Y7@dZB_k&;;PlNOKYahs+=@^Zh6)6RqMBJ+`MN8h=2I>`HMGh-+9v3 z-ajy88q!z?hbTB_0*|zOG*~j)^6NX zzi0E7J^PxDoj!Z@#?42MTDrP>wIJ!R)&>OxS6cw?LH6!m-NVP7moDEqe)8hJ{l~X7 z?%B9$`{Jc_vx_UfnO#1$bpF)xnuTk&Y&~$|)b$5l2Fl@2c_kUD;qa$bi%O}msB}H5 zvq_O1Avei8e2FK$-{lp|BbL%)qB7vc!VQccgVMYbLCLx$6)NV-V_5OJ`S)wtvttIBXi$Sdrj5BsdI% z{y}|DpRTRF@8<2tr_WwFaPTC|m-@}SR@K#)l+B+uqx74iiYes_%a+!y-?9I|xvMSx zIvo~T=)1SXP2!_+4=Uwbrv z(V9t9OIFs^U%qzNh6f|@oLk?Ad;&=RoKIiz0s%cjEgp{fQGioSX=oIr;76x{jN~Rz z_o(}Grz9l(VbPB)4)lsIEP+vg7<4c>vXBGa!)Bv#NgaqiKwNW#Q%EY)R%ef@hvU*^sf>@Oc7PqvUFdyPr1}ds7Y=}lG zZ*=D|Ah+6qvCuMbWB1012vT97KB|py?mxYK*P(TrcGs?~uU@!% z&fG;a=ggl`Ts>`eC6wt!Rce9zDKqE6bx!%>iuo%SFWazo8juMP4dwt+Ny?&&A#WO+a}YJE!b+WAg=3uujJ(#5u4Doc<)#heFtyB|=HP)8930yWP@%;NY2s!)lZ5_Yv7rsD>j01YTSNc&;ApKPc+|o(AleX>74;0m;|m& zM>7m7!!Lp&)}wWGR*{`IkCNS-Q&?hNg9A_Eeh9}Z+>cU)s_byDbHnh6T0J}lgItnf zR+G_;180ZzRBMO+;+2+t2QTg1d#b*1--^111&h~|lrK>`I^XFz@!=kBW|u4|tysEn z$=WsRw>NA*xO3l$L&q;(y85uIA{W|~8zOHi$Z6j%(#T)(qE-!;=j`W*aLMW794U6?F1z}I_Cg#gwQd~(R znN*ags!J6$8&VGniH$t31ebaP0y^#$`CU;`o1lO^?Xip;h$g%HjoWu0o>5!{TyVqA z6I})xP}Utxnh4H7Nm?q2I1IrCc;Hw&uDpH3LL4iR$Ry{?1;lb%Jt|@;%}olRm~_zk zIIAwG3|r`XEQBqOcu=Ci1wgD?11i~1T5qd!Z!MtpmhIR=El#e4lQQF5b zKF;Gu$Cog^I9jV$V(k!g<`B-=h@E`49ji%uX0h|D$K-WS;+lb)9 zMNIB4001BWNkln@{Mg#uctnWYkykK}SRx?Sw}@{ZMdMV#p|!!51QX26NDhAzY;Zh^#4pI= z1+Y;LcUM85%EW$3qf^Zl!9@i zAlCQdSfd*AIq~y@idTpiimudSQK*=M=G}}yg;L%~t`ngLK{Tbn;7=+F(+GfNh2XgqkgWdLdj#y5}_=vFfg&B*HrQA;QFR172nCBJ(8j;rq$ zVi{bZA`N6r>3CkTF?rSaG7_u-i`p1Tb&MFCf$R4=w(LAoTDf%M^z!2J#fw*N-go3; z^R1QvgB$Y+-bh?ZB9C@lF(TkTx2hq^VqAvigBw;rS6)I_DUo|jN}*R08MLSaUxIo0 zAtQGAcFX>wmzJ(>D66cUJhP&#YU#R$rpvdV>g-;cl@(GY8PMcm3(m2e2xvVfHiB4* zmmt=H#ZTHzxQbZxXvE6eOwd6$RjD=6|XT?`0Jc}06RPm{po<^<-ReaNT3oiadh&9$r zMj`H^w5nt#5@s@HCgLVCo?kZtaE%#p(cp%m2--Y~xVTEkac)HFQN{2g!PVzMd=mlS zgud2H#+9Fo=hm6Vc)(st8Ip z@_>ni7LZIi@pC_yXHl=v^=}ukc(fjoM|wWzt0#HIJrjk7atG5sNybB|C;j%r=WZ=r z)i|?k@i((7=FVTWaqGd87j8f4)>)ihZ-@_bNinIc@X1IYig_ieE{?MK0xA?Vst`wo zkE3Tmf2t}p7>!fjkj=%kwDp~9zPq7eZ~20iGfEarEti+lZz3f=~d0s*x!HtZxG)q7`Ydb1BJ6aJW}gEUAMy61%_^;#yI}R&`h7>w z+_>L1Y;pyeZ~`oGI+(B!+@Ld}1#1^IE~;U{p^>-5e;i^_VgT7dCcn;rEdW){;g-8G zDxi)Q`KgqaPQx{S6IbdZ{fGkJnb4@;N#?#B{hSg7_Z-K1J&5(3_&Ja+cpYCPzUHSB zUpq>CEtwbpy9NJ=5Gyaf($~TW$tDseJZ&OUCL*mCBbnBd=xQKS1_G`yiD2M;x0uEk zevV!gQ49tA3Yk)3|Ip8w2~k~}d~sEOa>N=dzA4AEbK;w!Vo;Qd!2r-B_9Okc9)Fqm z=vU0BwMWGNj^2L<5NnKc9yBNFYowrHVCV^6nNaL*R^d-SAZ@%?pN7L!W zD;vtImrt2l{>}7~vUxR&mabW`x_;Zvg9nbBJ$LEWt$S@y?my~mc{=d4Q>PS7Yy04X z$9;DmbY8vj@cgA)hmM}xymjBw6&vO+T2(T4;k21^i%YBKRxYWjUBB<}`Kxz3hs`9) zkiyGEM7H`;pg*-3hk|Sip5Yu>2SZ%SajbV8u~dDRBP)3s5R6HRR|+W(GXSzX0wx2P z4^CeKxDIp`!^w6}Oy`PpYO!mN`j1|?*L3pwmOZDIuH9L&WK+q4bwyRHiz`;msaRD~ zRaaWQrle~1oXS=3A^fXy$tHLV9&S2u?dZk(*B|wF3}ZT1*x^mU*Fu3I=<+8~L=cY5 zG$k}hiHlRKqx!yZ7gesDQ?as0DaDnm6ct)mRJE$CX6?e2jdfcNY~6qE!0DUt?!zwQ zkkxA@IWm&*OGu02p^O!DCeDKP1~zPbrf#G4r^>PD_kv^P5zCx&4dva$xdq;57NrYo z@|+qZW1%IxH{lLu^DFZxx(RN8dwK+Pk4I!Ytds}}cvFKHDCIHqFeejH*&WQlm%vx4 zOXzCgUm+Yo{oN5ubCgd%A2ju&5X+20!}+{XDVgvjGA#*Zv&)N$`ML7K4_~b$%*c#| z8Hyh%v*+fN^MX0vmnv!aw=%`ty6ff>s4aVgkR@9rP1& zEOm)H*C}sLe02gpql;fR$5QX}W0HL<;wupcY|g(#s%s$y3-V2HELC=NeM`Mx==zaJ zNb3FKSYy=DXf0|UF}w2-kJL!$haBr$kpE@v`~7`iuY+SDf(*=>5#;(krzg#+x!&4$ z>iWYoH(TCNxdGS5XKu8eyxMlXW$;WtD+s}(mUTryh ztL5~K$8S!2kp1T4)7RUsJm_D%X7{|M^D&<|aF>5G919u^3uVvW?*8Pfk~{5#FbLml*Q0Xs+QS>I0~2R0 z*mb0tW@RP0EkDk&UZ@zqon!rAMf&fZW4-zEqYz8kXQRhBlFc^kKe>7Lv1nFy1=6`_ zkvCPa5L!5epI)$PJ0KPjkw=nTP~T>P{S=7B+dT0u9XYME)*Z|!mC3$Y*|X5#;go#l z`qSzaTNxgmi19*C^0$cpBM>V}^VzD}EoW}Dhmt4==*^0sg`XoL8Jm}%JZJu}(`Tkx z6BW$|V(_nZKNfU7)ZyH%&WgpGlwqHGD_zf~sE2An6Na^r!Mt2gf@*$hh0gSI#FZ>$(lzJmz-^xQ=o zk2gPp$y{)YnO5udZTA5h4o|-hfMiD%h=HN}r4!?_sGY8M!RS`=~lJvZR`IB=j zC5I#nh*hzq{@}TLP=`X0)f*}5=3+2S*dYh~<&5%Sm)A^3jbudKKCC9)czye^pbiSh z>ME&T17i ztC{nL93B%D0mMSu9OFi(TzQ%9{z*6%AQsKbN*<;++4ag2GRApWdBwUNyAPhD!zq(1 zV8OyDl?K7*=U^ePjWCW_#V*z3T$6C|SM608adZVK-XY2!FE#7qDPIoXN z7aVkUucR(Hye7ng?<^qJ3(3uE?>_ZVzNmcY+`XE*osx`vWv)OPZAJ;pqvM`m3u0k8 z#5#Q80aEDScjf;_l|tAtt8w`z7gyVT0?DTFNRo)4uD3Fy!{-WneSTuZ0*+NWf31R8 z?3?ZST>E?2%&HB$j-9)yoQR0BP?8ZC|0y%Ynny)uo5>gLR2xUEal{%&tT&HX`2`iE zIv20qed%uJ(MykxH9v;(pxb1olnogq|C+pl?*d}skt~qQ2{WoMKj=Mj@!|2yEl{pL z8dR%PpjjUlVyWFKSZGd%1wQ&}=KizSPh5R)?8^Pq*V};l^qJ`I+?Vz~BNkskthJl> zRxjOf<<8TS7w(+CbpO=V)_a{s3!~C~(Kx=2HI7*0i1n@^mJThbAddChFN)@`+*Z6` zUB$A7&!<*>J$oV8n>u&o!{%7Pt4>{c^7CJPK7UnXNzI12OX`ajtoxgP{-R4qzCx`3 z`^>QjKrF#XM*sB>Q)g5xFI%!<&cd||>bCylCzICiI7*=tm?HVCxF06RV%Th5ebcXh zH)Z~chSG&=E0%1WTC(IfpUrUlV@9tEr$04%b?rqp zd`}TeRL|5fQ_`>_^!2QTSSafiQPLe4yG^GquiU(c5wdzbU?f>n?%Yv+Y}TLm8nJRa z_hIVQuG@3;!UJALyNLra*@{QLo<7e(u{Jzx$HP{FMKo(5pNi>h!xD2_!$vWJz(3o@EgkBNeAojPX;AePOO z$c6AJk!&B{I+le-2N-@iy?Vgv2SK3g@kna(-s3CkcT-$OhxrXe)QHXsXI0Pe=&t_& zI2Ofam#yEs<506Zl!A5u?b$Wtm@sv&jfhyVkQED=@u*(u{gHg92B=doBEVb(?PF}Wt&+emFU=E^#kD1tjftWa>!pCL_e+-o%65rvAzaV6E9I?g` zYaFrO5yY~46RiWzzxmbYv*)dxHE-q2xy#|^>sbpP_E-w}Y(7-Pf)Abk)aR4SCrqs< zu3j^}tafJk%CDwXG@ZJIg;IuR4|#gu5laGYF=57hxWYZ!ofb*$J#pzTfAO2SHLGXL zT~u7PVtUDvc}q8;^AE@FsQpk7Ywzx(S78n+={-e_mHEei{d`7gP4V0%MP-YN=Pmzw z#)4Za1A%5KKC|u6*?G0=TZgRI zTl#K4)m(2G`u&6wjU!}HPKoIWuze!^~Z_D_gV++&ZZ-gqb>uW3B8^T-v7mB$fl9I?g`>)qv8ciRoK%2(KZDXl94h2}D)i#CF8 z1;iS=Md<_NSXOUhTFKIuKD*tI#3v$|1848ftKGsVy7j~M3eqqd_nlw4=>Ub2C!tgn z!;a9T*)@Z;)jHq=@j-UbR)AO)%NpQ;4;!%%$6~XM zP3Kl^K0qTviCmz7+0a4%PB>PVj{JOjwUv?30kBGI)Na_fOt3(dS$1h00I{Catv@khnevBf7X%+I_pu$CKi!qepYA#$e(pwXuEJm#)$iiSp@lC&ESi%W zo6fJ=e6T<$M-c1BbF5sgL?g~)fLOOWOXjbk02 z9yW#9G3sRAkui^Mj7nZX6y3gV&+a2v2tX|0SWLVNI2J;zSPs%y86lS96&&YSXEKWmp1Bo*>gK(LU{SUFWOvgRgN`|SmTH_j##hAvGON<7-&I9^G1qyV1g49 zEreu3sDmCb6LBjpX&G_I6W3EQGzke|z$*-Tc?-!Y2h;I3f;CdCh5@YNtz<;ULMp*bUQhx6J;`WxpNN~ z&^JJPqQ*48^Bl`Gnqv{j&ae@j6OY<(9=aHM(22pn_+bx{0vc1xAnA}6CgVdO7Zx?p z5;T{hwON;&(=j|WrWJ>VDsU{}tss^fACEu<7hGZa`qj?j1$CH|F}TC(P)8X?ph;=y zVi?kDpQ3JsUW1WuC3uxc8A(a$Q^`!A-h>xX6JaoBL=7X@a44e2gN6_k7#@0BLSKvY zqhuu5VMYM`Xm$(0v6ipf)pY1G&dOSxb5V)zagH^PSmTKGeZ7L}sS`RT+UE~yJVDA4 zAsk{qlNw@@PTZ%XSRE$o$wa@GH@ResJMDH#VKWDFzB9nvFdo1R;Ei-f%|v97OuJm7 zo$&StJcC~NM0);!=64FQ5Sv7Y3W6f$P@V-s?D541=@e#9+lZ)z3|R@*jw2MuTmtSC zp&fd?>0u_}bc=dIcoOCqcZ70KQYnI@=l5`#>-->IlZvbb`jW#j(&&^L9)$yAygLJ9NBr`l1zsa@^)*2E42R!OP;FW&)$d6UF=-o?02m(haF{y+h~;#}NQYz~ zrG78Gf`+<|jt?;DK_&%Fs-cq@necl3L(%vkA-k;!Qpl`c*LZgC1#>Lh;o$g#QHv7K}B(k4m5kiL*8g_Akx7`TScMUpSF6u7!&UD$q%A26Yarip_>)k zqe8z=bh!kdIqfE8Jp~41)=bD=r%bx!K|0&YW_tYTuwE9mS%3sk9H8vpRgN|0{3jqAu(;Ee zGUExGJ7LF?4tLUuC6oklqALD7%&}lzgiU1BKqR$Pc9@Cx`8eDu*fFU)AhJ5C-y?Xf zF$ zk{Fim_M{AS68KhoKpdh)D+9b-8uTQsq<}kuI2P67qK-=1bdI(q3(a3v@ourh8zgvn z(T2lKM{g0F+{*+t5x&zvefGX{EOI0gXKX-Lei8Q-Q!i45oc*I#m&Xz7bs-ihjtaFJ zTXM$-yrYO^RN;gG+63q&Ih;wiN9-Twc6CK}THXRo*Z+3)c-joTLp%&m8ouk`%O z^1#p6+I*2G0kfrS<-G+}9p8K%KYH5P-}PwDTK8Z4QYc-Z{nbqE$MXr?eOqD_I8;`2 z-ffPBI}(FTtlN(~S#1mJbjOanDb|LuKANYj1Z}X;Ot6;@IGv85!|b=YDMm0c2_qe1 zTl)AX?Hz(|z>{!OJcd&?qn-+KJxsjEmr;+PHNLCsSjIfZ($E|*Y{o(chh41IN0@1X ziDGU)?u{A^E+-Qrh^WOC^i#B7uXTCI{s2eOe0+G&{&g9KF%~*W*#dqmP1*sJe6)cX z_J?e=l87D2{+19+8Q408qla9gGkoO9!y{iViTHps1!z3z)Ho@Z&q4b2{*XCJ(?(ms z!S{s3P67{U46GyUw}-qq>%^l*inZgMgBFLqtZ$GOS_!`^WTt(T%fk>pZOE^4x&>F* zM6ra6idh}3(Mouu79vIarO?f@!B6M;Dd7ndNV@oa%Qj!!by9M3ZZq8*j6|_iUY}8UALRBopnvNsZYvNchEbn;a1yToEh9evarz6wLO1}0M@=yPj zFeZE$X8p@gJl#De?SS@YpE{l09^BhkdrY6C9JPz7sf&Fw3IHp5M*()ovoaUdEO5pYLp`TK=fI z+IaM25KkDKNoDTwrgt?~Pz^vg5&V!RhEu%p==rM?zOgT<8~Ch5yQrS?(Sz&v-dVcY zT2gPo?H$Ya_Wy3$jg9m4a~DN=&7EAr*<*D4aUt&X5>&E%%h5+)PYpi2efRgp!-ubQ zaS;O%Rqd5RHQqF0fsBM;4v2kAHX0UhxUYM1?0@}x!<}{-Bf3}bY}>H^;)xKcpa1|M z07*naRJ3Z(VK%i1nH{78Gf0$w$Y&!;u%NS5Qw0j5TF-X75Onqx+uouYNt?l5{jl{?#P+ z!@*uj3>6*f{ObwE>9gZ^dvGDt@x`wVznwU^Y)9ndCGLN!aM`>>Cu98C-#e|X7i88D zkr_+ehKr^`u?3;r=_CBwfHjdZ)NQd>EbGgN4rs1_m=U{h+uwYzt*Rkm5v^Em!`3_O z6-49Kh*)5fw#Arm&@f^4@T`jPqhas0$G)bsrazPkZjJfVqM`bxMAJj;AHJqo%vHYF zQBmKQl`Vr-_aCb4n8)bPMjtx|zx+~seAD;Udb`_qOJWJTxTey;-D(ZFqh_2N@^GELXcrrc8GXi|O<~sWbF}riTDpnqwU(-d5mV35pZy_x z;-<55t*&S}=kh+CP-NS8-k6qK?_b6zRBA)P?x37H-r4-W{TJ)(`L=b3Xn%}hkxgeTx? zCgCP-#FZb-pB?ZcciO*BuOL6@k(|zq#VtSO5}x)p_n-fUqC_vHr+@alP>11`-N@Z? zVOG6muJkhM6-SYeG-wR=-W} zEMgJ4#d&CfVMegKxgLp6{B4Ev_BoBr8@q>Xzpk-(9Czff?TeYdy?e;=)dMZ2U`V!q z_AC9)OD0)%tlQ4cUe}k6+qym2-+mT$4&P4&tbrKr3h6vy^~8{O)+>mbg+MXc@Vw8G zdYTr(6BhbT-PCci#L4=qP5Mt}4WHOSR4*e>KXe_t>8q(5kY)e2-Ok@txw$OeJAi*y zY{jrHUp7L?!>g8RCe9V>Z}*6)R=~;@|885As*EKPyb11 zZgqzU$FZYbA5USwsKNdE?v-`gFBWv3Kj@yn#&PJ5n+sB3%?sYMyCbqKn4zo^;Yi}n z2&)U*U2@10wtu$R+iTZ{WKSsR`CXZB>YS@L8f_Kpjl;df!j06XGlQ}ms9qObxXvNV z=Bsz<-&fefWVbgiI$|xKPwV~5e|A3VY3F2*JJziw-uK806bq_EggV>+IovQ4(okU= z&fBs43NG<%h|>!WYegHn;j35+9EC2eBR-5C9^%BHVgW}+aa0RZ2n1xK*J*j7` z>~{{aRF5+uXlc>zPMO`=F2Cs2nL7XGkIaId_@X(w|M`DO?A%A4KcW3^Us@mBwOwv> z|3g_Do9w-E$@15Kj2yW-xNYCv_1l9+tpC(?_ka8cYRhTIFy(P%%(&F&S0aq_3pwv7 z$5OPak>WLs;BfKgu*m$&V&=%H;iH$WI$h@%3%r*fMvR8O-_P>54H1*R_8dAO_POu< z+i&Q{RxFY9F5DQJRO^&=e^o6rZqJ2lz1{tmOBWqqOy>Mi>+HF{g$*IU9DVRq^Vzh3 z#c3cV(!&OCT(JJ9PfQxKi;+mX(C5o(oVOL-j$XleOEhIYc3uBjrS8Gy!d5v3x#5*V5iDaV_DHo)mRhW{4JC z?#M8n@H(;K&!-1kTC4=e1XIR&8%&Gpf-FWHy3$E|ZIui0sxsDVH~zXbxc8M>M;&D1trfMH+^Wz8WOW<7wG zf)KoUly4&&FEAPqp}<1J}1XMGxDdp zAQVS5i-=k2q}IW9Xh;~2pdBo!_wML4Fyu>@D}N%y$~FLEZP|y?)!=MCOA|7* zEqKg~C$zK>#6#Sr4$ZQILnrrmPad$gbYOa&Y41_p_9M>KTP)p!I!^+lSo+!{Q}q_} zrXzkgj&*6V6{ne12V3`^>FKj!MBIvT2CBfZ)Ie$kjXEs)MiC2?AaETDEos0==+=>w zi)swY$-hRDFPL%$n$^*~!zsAE33319+jDENb!Yu_fV%cnU$srMpn=$NUI@zGX>zZtTJd%a;bSk6f0%mVmb z5}iSOuX;rz(gFl$Qu7MFHpEg)SCF080b=oT#nO7fOQ?f^K%wWV>`<|;u-8gPTF*SP zeqP*+L+%gSy*KSuf-*lr-!NeL16A<3Oj4=rNQDx8XG+ zma>k;2x6C$o?YKMv8?s~`Zv$cX4maj)2G#*#d{3P8wYJYTEEFrwL@FB+`O_O)PZRZ z+@wCM@|N!6?&?{L_j^(rUT&3BPEK-rGIx%jw0$04?Wj9)K&bn1+j@X5H)S-ZNoYGpJi_Yf(wR~*!k z?;m1~$=sIbNuc6Lm_hNYy~OE927q}R#T#GDt9aumpOa}M!h*lkV>|iCph0kwFrth( zoVr=iq%yF46vi0kJT~o4PM4Bn{~V>;KODpw30BG5!fGk(Ss8tfyP8`w|A}G<0Fxj% z1IFnw(TK+km_&rKO{ebt$ehiiLQR9QGGr4EBweg*)NX@{Rt7P4mcK< zg$gU9Ar~&FkRe3pF(>QA6G29H1Vhe1)JDqyX4WWc=Hel5+C_;jHybsG8A}Y0N*!6r z=n2tO)F8#pV#3MBO+Ma0MeKOkiLnK*W1-!2ZkBpeh^56O9VP0Rh`Qa%#>9YQO_~je zrEEk)wc^zs#6~I#Q_hOTtW+$DbG(hV2jdSou9xR*bijlY7LL^!qiuiq#Ikc+)EvSC zIBAdB+(F6U;mwTO=^vuGu$#pwZ@&-k=EMCA^sF>$PNE9v5y#3NI(M&X`Bq>&YVJGh zYvx#}Tj8hOQCj6#=O2s&CMY8l>M-Q>8JHMul9F1AGg#d2$bd)GGQqe#V092-2j>pT z+S+y9Uwp%80#T2-E9z+_6R{z}hhaWlln7*>oWFML>sj3oS|UWuuMJ&iED z#XB7ESVB-e+#K}wvzb;ZN@FgkmDYPB1`}>O+eROI>b&rfIQGDFc1VXgdAm+Wx$Ss7 zY>G3kn1@ab6Tbe4Xr)E+-%5w(&m(+{-JjGlqT9tvdLK}Gvx~4&;!wl6eSh(fx_xJT zOtyziYlD2Z4*%@EM65#ma{-M69UdH_q_1oC|9aXwOAtnKP>=K>s~k|Eu1oRV271uu zFPzb;szg+9&fyiN%-{Tvv)3BAOg|AH%>)PkGPnzB^Lgc*{{+ja;%A;2#o<0I zuiyxPE4~Yom0{3;K2?;gU}55v@`=q8H!6Nxr$0q==o8Q~s+Ed`((ort6}u+`h~@Ij zRyuLxiPl1^9mAXH7!j3ebOutw0MCbIER@9~xlfFwIFg(7b$bQ(pHMg!+L)39D)@Dr z(}I$vS;7IJm2C56y6BjOVf0kQYsgZrxXu@}+S4Xm){4dZ0=_<H#mI4tjKk%ZQO{C)hzEHHgat0oLLV;Gl?Y$sr$S#sP`LL5-w!rfe+_u`B0> zY=YV2Hsj$gk4(7OwrGT~rp=x#HQ)%|>oNp=xP#L$F~$Kv$QlY7O|clvlr&@?#j*0I zjl9ks#83@MLnd6o)SYWjzNx9DxQx{-TJ2m*G-h&(eye14i*{Gi={QZo)5DFAW=~fYW zYkV9d%g0)X-xhB-hcX5#Oh%A~bO+O*c3>7qv+}wfC$2sk3MFAu3&8S0i$YIYW0;aajllSUv7u@h(9){9 zh9~pGPyEn0mSTg8KxPe|WS?8A+kdTg&$W%GTly>>YasO)i?2F(t8Vv&$JVgc6Sw$M zS30a!jpvphynXbZR?oyN{>0&1eO22otv>wd(o?e|EH$?dRc|>{f2`faBs8SY;7#^A z6Kf9LSi0-<1D(eb&2Bx@vhnEcJkEonFKeO#W-^4ic-j>)(cxZ?G(;r_>6C_sYv#I` z?Dk6$Gn(oqJnFKB)KqeIFl-5Kkl^lxdAB=GTZBQ*?_@}$JMMNRb$FC{gB;61i9LZ( zzdy`s(>=lL;IOrLPBBUFJzl9N6u_M^hbz+)3>xT&9ZTpbanKX(4F!gL9t|U6t~g;A zU6|x>31&RvAVt3$W%uX`B-^8y0`PGy?bG^vR)VuTlYmTCca$?mhrBH16uNw(4VQ*I zD0`Ehl1RH`bBD!n>iDH=3s!E3MCE=OWuLQqUZYnKz8|`eaPoHoDao5H+OYD@&pkfX|6RG?+V2v^3{&#?3_dqw4a& zfY=t!>Ii=@EN^+uS(?m*XmQ6KZ1&=fC-bV7Gosu}1WdlbqiBS*34^rM5*F{WJmFwF zLY&Kul;E%@iaR6|CKx@UlTDe0n3azWi>UyW1xdSuEa?#2LP^q|>hZ_!u`J~XbcSKf za84g*4Dn94pr!cs0FOC%D;73-BRw%m>kbn!dDW&JTaRDBSg@r;7cF(_$@gyuac<*z z47q&isFq>}aKRMJTUw@omx)rCZvr=?^QNjI(T2N^`{5z{^bX5{g+Q_ zW~@HicEaz%?%QKv(+raF9j6{G zTi3Mf!c(0$YjsCV{$%6%_KL=fYmeS;8Fm>wQlBTW`BY2I*3)`Oe(mY4+7zfXtUj6dBA8|{_!7gZ@Un*MH!l)9UN|x^{9P#n>%gA zB_#!F$V!HQ7wS+xQ{+-ZxI%Eamve*@0Xz{kiB7O9se~1aIf$SW_k&t@JJS|i&@w#b z5PJN)*D4HqqlC+^X9A=vU|{^D(+|{b_*VO+Z3k=X)(}$G>OvWZZQl56MJ$(_bG!L= zD$V(`i`FgQTU<@`;T#dCtN|w$wGq4>=WSTb<%(PJ*f5O}4w3e_4MW)?pjljQWX2A9 zL@g;;-Ow6rzYpa>hWP@o5RRA;Ml9$rJl4;Ebs|$X(Z+kcj2O~qtT0-zgx#IAx#BJ+ zJ@~}XeXe<0&1|2B9cBQqgWjmzuJ@%A>Gb=|J5CbahJZgV zY6aX8e;fs}CG_}s#>Q(Hl=~RP5hzYYBgUf;d8gFrO=7l~4NGX~c+f2Mdy)}j3M`Ud zKgXIw20CcP(a5*EStG^4Fo3b7Cu0m9AHLpUJ^K*%(quGIyS8c15hZs!&MJ(bdjE2_ z6Uw?Q3Wt{TR9NR>4gSofcE{gMsNL1v`RUxokBZluh3v1VubR8@@U>yvUrk(gqQwBi zX77#upM70d)p+sLJuUJ-J=FaCqsl7-mQ_dZ{mbM=PgLI5{Nz9U#WxKHF3sI==5J?g zCVBbm1$(D0+TA;B`fc&1wMScpWM;{>Gc(p6yQ;PQ-8Z!xo0{o_JZ074imm65JQ(?OmG(dRV)-?V?@qt#fB(fd`>%Di8$Eyd(TugH9z1k$&3zb{Z+p%@`1v2o_TL|9 zBV%_ow3dnDF}b;)`KV~S*^{=j-1ak%|Mi=Vj-(94`K#*9i?&~UU=04#6Y;5o}*7Om98Nd|BtyT6Oa$Ja*BBfwqc7Tv58|PV{h#HV}hpZ=_h-7GjMN_r}x1 z>$VRk1oy_H{$-mS5psx*7~C9?`Zwkk1lkAM#DRxh4tda`#b_z6)*-YZltg*1dlm+ha2^UffiAwZJM`Sf7rTYjp6Kh+`}4e8K)y{ z1c>qo{a&u0;fJVLpGWKiT*t)$TClq%4a#R99`uBV=wO#W)Z+>00xb4acj#A>b}U~$ zlud*TlFKbxUfVjB>JsN>gn1^uk3qColF6xccWTC!hA&J)vQOAEq)cTXvYp z4tg>MJcd%olDw5*Z78{-)bHhugwN*+l6G#Gj`jLd{Y}f3->-Gx0G?)&ugYdN1R2Ti`=QcMJG-taQ78B&H`(9_P zpyC+R6D%FfUb@ver+iT+p0({dHMppO?(Ee}UgPd@T0Kc45yR{PiWk6u3&w_(wLNv& zHMew+^SvHv(3{ZX35O$vIkWxVlmU}8B+5LAIRz`h1HA@A4W@}6CK|y3!RlmUgFZ3b zPg#pLI(lz=V^ZzfeY=h-=VM`UYL=CuMP)Vu_?E^wA zQcW%gCWEA768$(|v+eYM``x^c=QY~>v32_{{^`V(YfnC^+k1ZH(fikW9JXNke5>K3 zvQ7W_H*>d~e_{$`^t819M)xnLt^M;)m!5xWHu*(MIJy6h{&R#%8qowUmLLz`*Zil%-fjQ+1Por5xe`| zjNWKwq|wu;HIiEGr0yo0-84-H?+pnMAm{*s4)or82O5ALpaTdJ-kb8it}E~Bn(}ow z&%ITJ0tj}uBm(U22gHfXTg9qdCr{?d?_{1lnPb*pe^m*Hr8J?4@Hy}b?mKyD{r=NV z7jKaUM?9=*e6;KRFWr4(GM`!Yi%e6|K7-GH%jfR1(kh(A46FfTC1zA@L`KrXF0R`{ z_dC22v)6zJd!4~{zlWoIPnWIhDA{Iq#)nP*KD&F+Y?AssgEd=+fAg8a;dN>$*N3^f z2aVmFTcP*QY2*c}U**!_9)&Tcb8@mrcY6MDaexfsH=aKG>PutXVzkDTdZwH9Drr`2 zc4JmX;|Y)0z#L?B7&AfoC72g;#+ZlW)Tg=j)(6)r%RCBd$iqu~5v|?RZ}s%MX*mp| z!=v^El}>iT!x)@_5xa|U$JJ&Yv+`;?Z!q&ZH*eCjey2}fR`+~u%_z@W6(IwdS+?LT zMqUu?go&16j71eSQ1(Z^`HVdC$me1DzgS7UYPb2ly9=0M+l`q+K2lnJ&iludRL&w#kTv=S4>1$=ZzV({#IW^&jyVL zkI1fE9ruL>snD3+qYg3>AJcCMs@)#u!L4fxexoDxZe^q&^XgfC-?7;47!MTzcn&u^~pI->kn!z{y{q|H@&#cp>}b@CQf1xlMaS7+YC0Q zn+=38mTJ8JxW3RGVXC&CIDGC7DFBiNY%J*y(8fw3mf#f}r@UH!{I^TjAG-RSVxs5o z4}OtbXYj^yHXQzP&E9L>(hrOGA8PI+fFo4s^NdY5pN#43F@ueL)}#CNlKSei_Z#l^ z|K!s;lHm{Bdhve#A)O;KYUO{jxc2J9;Z0}Se!FVh-RA?#HeW6}@CdpwOfvPC+kX1h zrk^jV>Qz{pU&;Ue!-ATVkJcZ%x9#-(>(9rO_TV##?W^_2{{Dl4qFt9{mY{q}MBeJ8PTeeQ`kLvvVxpwXER_!JIyvE~gY?uA~vyG!p z-Vo(~y{u~AjrO~P*sqt@Xjr~O;r;bj>jrgt zDaDRj-4c^uqYIfmw4${7@IU>>ARQuGM{OT1lRarPTz%nFyC+6^MjLOsI)-%jUUuGl zqQOmi4AprWHY008KjIuH*@pf0_ns>c40258r>U;);iJdZ9bFE}EqgjNeEOEBi_bex|{D>gCTr%8FuOde)f)|Pv7ly5ohijpFN)#9#Wip>gq6d zx&0#!heOHgjj?`Eo`x0aUESLpxP!;^Gy3Q!8n7DJj~fQw}azr0wqo%TlfL67;M_UNAzE zUwYJRXGy-fc`&bTtLOT)@zv{aSJa5f$o!QjfyP+J@CHZe1U`-ei8r6t9P9_a<2J@jaVtKAc4GsZLU@jw55W78{L-GwLr^wm~-kZ&Eg{^yU@Js-sX>KECUdnhp77H_`t`;rs= zDrf1=OD#$l{LqTcXR<2ysGO1i>$kZNC05YAm!1qh?9)E%QDq>MhZ>jFoa~XAw9aV$zUEKz>hm`q%-?ZE?}=V| z*!^#x=Bzt>Go$X@#uInV!C2jq>+dZtt3GyT`TDab?(U_5(f|M;07*naRCXJE(Q8lp zmsTG7)t4K#?7!5l(rZ2Osy+8sRv*l-Kbo`oq|6zq+;`)mkk?erO)#vbFI?iOVjs1Gj#-IPL zg^y#;WRCy+KV*9wx|eM*)Sa`B4Bh^x_qoe=`^)OPcAWC-ohl5~;v2Rx8j{uzyGF}4 zk1zUVPfN$R!EburKd@wp_1cxTmF3=(Pdtw&djIJw^+(zI>^;VUy|Rj(^3_{dv$f+l zU(!d9sy<&RU7kVx^7qz-nfRjZoqYKD)ARbDer7P4J6vI~VrO+9OHQ$BjJ7L-?ZKF~ z@!pO9`L8Z?+`*$!?2D2Y%Zl_{&rK}cKm12U%vRS?^z0J`?u{HEhv>b?6RQ= z>93dKN1MmFm`y_|GuM;#2Rm~%4Ah*pI`|$l-t)7M4Uapz*q~YEwan^yEMXo=P5u#! zErj#;nnv<=>>v*vFz4(X4#r0aefR@)$5TojPXUw%-m+;h~k`^>$1=I;EB)TuL_>$l4{ zU1EETL(9tAe*dv#^Ipkj}7;TaoGFI}^zVAu5za(DduSLLnUGJ=h5KlkLlCDqF+Pdt{mu6N?U z{(5KDj`NE*pZm$D^=o!Eo^BcZ?@PC=Z#er!(e6#>Uf`Zs?)Dp>79U!>^V}yT$Npi# z`bXW`l5J;xm$3yj?b3AzZ$BTw{gEA4U;Ji8P0r@SD=YSnV6OIY{1*!g^0r?p+H<{V z$2l2T$v-|DEB!c|oM0qIPoJE+-yxBcEJ&3U^Wz@Aa}0aV7 z27@yOBO)<+hc%8zuVh0iyWSCj2M(&N?L+!rDJVC!6!%RSz3|D7Vcq?XF{3jk#pxcY zscV85)w%oSmRF<3A(aglbkk~?&kkb64jjKycyeC=08$$trg6nDe=TXeE_b<9zPPcd zMEZ~ar*RA)+q_5e(I+M!Z!cUYS@gBp&-MPX$Z}up)CVMlPhw)V80(WWYMge+eM-02 zw5W#Kap)=Y`gk7qTUfN;&_&r=DlaPVAw6SCqJ7RP7 zIc;jp=QG)d7p&g;(+|e!fV$(Q=Dk8y%&P9~RsJd;i}056gYNA$+WI|?F(+n>sBk0? zV-{wN@~T+gckEnO_3FMjZ*j&{Wu?j;CqQkGXYY)DP=fJJ!-si>qv!1oUT0@4hc8mO zTRQoGW^omLwq3ubOnv8-x-iFf`pNjBYF#Ke@c5?wy;Twim~jDI&#J7m=oJLvR1=I< z9qQtE|EK@$#`8P6SWL5Yo&3QA3r{Qmt%!Qq?e36`&+^azrB$ZZ zM0s~vt?lr&!ARV8`HAwEnfi!X-8XEzKMrfMVZt!*AD?6GUHx>3P`Xic`e{XdFCj_SKd$mW?=?FEqrd#4e^g_-uEC1e8uwKj?vLm^yh4nR2b01Q zFpWD@A1u}z)be{BqlJ47G~d5&t@RH%^!`>tWyISa4gBmw)467Q;b#25Ep^61&Z<4V z)$4Qt-YMe;%ptiO)90-Yb&gl>JAe3xj#z2Y?V?fwt)jJtVXQzjWGK}Ir!oh1wg{-c zJ{dAhopW#`K-aHhXJbxm+qP}nwz08oYvTzf*d!aG*)C1M@lQOmM%N!3XXwa|=mMEin=4 zmO1i~S(>Flkgd3d7D|!7xJAf^HixBMbTO0+`iixfW!LcwegsEOO9Ww0yd-p`86u?# zpTUJ;of)jarNw6x<9vQ)nxfIq-e*%sTEO4|a{57`=jzDGj^B z!B_exS;LO(g<^`kfRUmw5VEje{zV`FZ6`eMVX>mw#@zSdUD=>sAOID!$Ouo>*Aau5 zfvu>WPhrsy;H+zKLSwu*e&6)zdb0Z&ywo^ImXRiGc-^%nfvL3!g@X8mhDhgGHK-DE z%Y-8+`Zh`qZoZ;rHY%Evw#*YsZrryYxJ^TxZDXeyaQ9k<`kZQRC^&oB`<^{#M+s$r zH+|*{WTof(Vlqm)5Lec0x*k{Fu!n~QylK44;>~Q{)@#2#yD4(bY^?~sr4<3ViK!Up zUCArOUh%`XkYS3}$K7F>0Eo>BP9i`TZ`}~jQC@E16(i^CPmWcBat_2h!e=7I_7_zq z4!@W79y5#)b_~Skt`lM#It0#Xlt;;&nP$ab!;(+m*L|MaD?FMrpT@?L{W2XHClX5pfd(12*OK9a==V+Y2Q*q&&_A1vxHSCf+g09mJJ+LJlDZ zmU9n#a$84c;9sAY$IpCDx{9(8$tP>PsES@htZ`>;w{p_$=sYeXUt~W5qrauv++s z=&YxEC`Oz~J0SZ3pb+01+$HR88{MdJ#q${UjG(0WGno&Op+*8LgMpun1yLq#FS-tb z_te}^AD5%X#|KLpXe}@By1uAjf{mnN)$LUlb6Y#eHN-HL*LUs zv3fIJ8qRp-tybx24zUC(5QZP+h|dscRxaC)90+1_mz)Ye-I^M+aN|M$x4det?72Vk8ahY$ozeUAA-E{4L%x z?9`l%613K55Y`8JLTwIyTRdYQiC3FA%VBw&a>t{W0Ucl`sS*!p1T-*9cnSo+Gz;@_ z{9@A8{?ZA|Ro=Rx0}}GOh@DtYJEff+G<u;|q8$4OmtaG2i0Fl;=86QVUzPt|*00t6 zdqE5sbh`Wy{w3!v^Y1`?gweOh=C;*S^UcJhk02TD1e7^zb_mT9mx&s$h(@}#b>HCr zxY?k00LsD}4qV>Ew62%$t>QXemRQ1B_f_h)Qw-)s>g6!JZuZ(>Q!nu|+OV z*D?&t-?ob|;W3dR`39+&xnVy-Ih;Pf+4(#0^*YRA8rtDZuQQXiOXE4P!_P-C$B1)= z#`W?5A#jj(`Kg(Fd6W^H+joC%2jx>z96#{RrZz|KGIr7zd**9z6(=M0o`*XT==f_<^B~&ph<#wMaX5X( z0;N9Ezl)p8ZNCk>Go1ov$6uA6&=ip!Grr(lnb_vQyBB(8g|g)9&(YxE#tW$WmAqU& zSmo`^U7wL^+Sd4UJKtiOjZ@q*m`hjQ{tz@;3^n>MZDo9rOw!KiQ{h?nyMdFdK3vxO zp2%zoy*Xop%hrbfbIH@6^2BBwf6Dd|Idwfb&-BE#_degGh{Cy_&iGpHDp?dG9as z?pvn^U9I{KJBe=RvTt{J)=^XyZuK*b46_^=l0gM-ekq}2Y)qIUTa1>qcgILVHx99< zLDyuWJUrvqkVJW@AWt-8#HK6$!h-8Zf-wWE6y!)a)0Tdavr_Y(q#x(%&?qncZb0aK4i@ z@SBQh^+?3NB)G(fI%7M>H~}R)QQAUcH9ZIs3oY1mZOF3Gf{al1^e|47VD{X`{u~P6*Wde>`Q!O0yvb9azqwNCI z%6nxcrN~nzRq&KyOI&zM+Hi5gO}k0U9BdKI>8`ey^V@o3ZTh8-JMh-?!H;mt3J8bvei6pqtrGbk-ZRt*0`t<))z?G{$#&ZZ-A-m9*Qt-ODvw z8As2W?x_++{th_>R0UjUyO)JO-_GlsPp-C|;M6K}tjB}b&Tx2GI6FT{sn4@YK5DI> zW(VHrIu2WXf%93L(6_ip-*v>jMjHn&^P<0PzBuKSK20uTC`-|n>+d6{_GGW4&*iOy zg0>$UCa8#Z@E%>rE%FyY?L>s;xs8nnn03^=TNou$KhtwvWsdql zU(f%Z0)9npTI2BkhVT6QdZ@#2J3z?U_DndOZUuW(d6~bAx4b6iW`C%;_sP$1kF1rd zHY_D$BH@$oA?Q;@PiF#40 zHI7)%|1oNHfJtQg8Klga9y=Qh{th@Ke5314>3tJub z2re4Y17GX6psmrzc_V0Smy}O5E_TPYPTwZCfT?i&j~2TN8x=`7xSNF=o~#Ke zE8sSJNF>+{eNodb^JDQkcnHtzc2Q|8ra#o>UDe_y_nY(?oYK-*I}Jay}{fdR778L47?#Qyh3=}P5 zFKo4(OsIf0VrFLd8=0@R_8Xg!9aoVVNalKP95hvpqO_2(6QhkE?aP+BHr5MmCa*|F zN1=0VP(}F>!AfX9*UUG?ZWC8?HPpV$XHh{tCE7h-*DoNhaT-BSGRmWXqq#>K25vD@ zxwt@qonmsGbcZkwUonf9@>{9XTFbqSJw|*8xAy)nA&D^oR7+7A|xPoC-BIL9q=Mk(Nn|8X+#VE-ptJOk`*d$?x&_B?8pH>|AG}FA!V*Jr zT7bO>%;T2iCP5NV)DeYT2m{7`*$)bSvA00I=KCi?Z+m{px5z06GBlnHow_O+Q)GIm zA0f2l;>;K&uWb1#r50I@6Hl}*dS}rS)1suEIC5l4^X|F#Vq@EhiNa-DSLk-GTIEBh zSnh3zEhNtsIuW`db_B)7DV675)Nxe*74Q^Ti7S&bi`S6XH z7J_^8otGSdvOM>7YpFtev%aH5Ap-S)`bVBL0`;c!>~;v1%Sei+K#l3k@yt_-g-90p5>iddQ)$-mZi_^EKBc;(WqQgi zE3L8cIcr}rZdTgze2pdtIlS@=S@R0bQ&pwNaRu9P<%;tnR@%Sc!KEKT_(kcIH3=^& z9k=Tb2tCz8*a!+TnS^Q-A-w%6ZU_wJBc!^J?9f*G!JxDQuGf61y%;dETg4X2k%X^` zrcSv90yXxCP#va_xwMpxzMiUOsvHM_7UW_TE!4mk=v$T1g>oQ-IjPdl`Y>n;@zX41 zAUJ7>MEL1A*qzO%$yWr-K72W&snO^eg*egrqrLKMvHJ0lZ{gifGbUFppJ`*Nl(NKt zhx;jV)g2F9c%lz}YZSS^+>OFskfVnu7PS^*H8kpdHcS`HvfVT*uu|l=dn0um_{?Is zOY6dxGNXhyqwP?s(d@nKQR5=2ha$xA&EQKs)aSj?K~%`qw3ZJGoK0?TsI2NmX>S1= z)X+nI-K7UR9b!NL<05LDqBH|EXGEYaRz@oITV=G|FJ!*KFJKp?Wg!)+{icA~|82lo zv?gpcr5x$w23K|Rs5v#JPjj?Rn(dkm0jZX=(W_S4AMu;;$EE+R%2D*A9t~Zcj7E)DwM+xHH3v@}#Wn(+ zD&!|W^!_X+C{3;4KAJO0=l>PKDG3=`rnzV}4sg~i7+P7zR9n=6gu$On1=2v@pqDOdEa=Qe^o5)b9eolj^_NY#h-Ua%ofFm)haaUVjccx=^r>gtQe{~nEn1EMiqNl;ODqiVHkBc4|qj8UG!Y)jQ$rG{cD9f4c>rFF=o5&(O) z_uc>Ly#E^WtMGnCfasi@nE3p>`A0O!;<_@3bx7>wwEgRmJNTY^dV1OgB{~CPkp({? z_}M%7OS?8g3Wb7NsG4c#5Q~9<84@r#F}3;s_3(Z4S*&_1;7i z@TKQPO#|`Is4GF0)jSmj)-ZsaIsCS3Wk~~(Yo$xuh3E_6V)i<0N8Wlv09v_%8iEkK z6DBen-o-PU4{%+s|JRQech_tFg;%=%=7I9|2geV3k<@ylBHc$3Pr1Qace*QvGfi71 z9t*QOG}gD__g5<^&BoPzp_Prqe4#Pavw}XxmM%Hx2+_-Mf_@d-twwA*-t>*6Cd;$Y zOB8Sl5|3Uke(TL^1aVzLGqPAmQ{psnYF8wN6o~a85jc@!Y;PR zwGPS(x0?7c2w~v^xPh=DHNt*}TZH?L(rwC!Z~=mufgAsn7PHxEUhZ{T15PX>a zW&9ldzb#azjjU{Tw>Q7qWNj8EyAa;3(b%jnRmH^@D0j(nsT+bcW^}}r<$a)>2*c6V zh7O4>x4xgdoINXdbT_r=yFqOCe4Kx&i8*1XN73EzKewUWSzp$#wbTv}2PZ0jXv#9J$GNpPi_YIMSwQ9v;T3*U(+C-3%im6Qf(@! z)110~=i_QLZnDPvIMZo{xna_{nX>`N)eslNwCPf^KPSSw2nRL-9p@Di@bLHUS5xkG5rcuD zu6Oj^S2D9@=|MT*>GO8-vK8-$8+9nZCI0zdBqTyXU&su|D&g6fFT>|IWk8t>=aI zyAuBE0UxKMB`JUAirOdH5TI;C!P+T8Gb7aiSR(e8cQJ~?p`atK=SymuX~qh_`) z7mTzYts52mYTY2)zt1?;?3U75iy2h;wU#pdPRlm^&YKnwF2R6Tpu5M}c`4`eCXsi- zmW?eAAFux5F7{aO`oiji2bhLt4Q8B`k^@7^BP7Dz(?Q`T<96Ri=FiVBeEGlYgJG1y z#~nK?T#mfMU5I(Vt-!MKciAM3sa^qVuFMw#yz9)>d;Y(aQ!U z?z8zr{fi|lje1{?yx(JAEW8Q4@8?*w1vEwMzgkB@+)~(|2uFPh&NQ=nE#P)MA((rD zJTvEAel$x-j4=kgp>F?=_Z}hElYh_7W7tJI-6JxeVVAvhoOb=Ug%8p^QGw(g+7((E z;s|MdbA&|U45e92(!yqmu)uYEYGN_>SeCY<{RO@^h$PvRL3GR^g?UV5>UVUFf>_GM ze_eeJntaVa5ZOw5Bsv=XjC4;}LI$u{ZjMc(XS;U9fUcz4^*L2@xEo!}5&@2X;S6wB zU3cc}^I91wx%GfeXhs(Pod|qrf@TAb+Zh&=>*TyKZ&K+SgSJePnO&KjL=^r0J)mR9 z>3MWzm5|5d{MR@@+?A$TF(}pRR#7!a$qyR(&Kd(m)zQGl$4dVWba$|v(F@DbLKm_P zebOa0j#TzFzKnNpLZinzLfL{{fwVcwa%lh8g45>8RwkYKdxpWy*n^HDQ4`Dz{#~c2 zfuZ@2krf+IMdH-JVEAk^ON@2TPhdDYVd6D>C z3ObI{5|xvr6DLWg(+a9RTY8a<3o#gg!&CocttP)!3Xz=sEe%+Nc&DC{7Eb;1ea%yZ zAx&7wKbrFuwdA2O^-tJZ-gZjYelG0nn+t%R{mo)d+2MLDs)EgR8)GOGtGrPS^N2J? zCp3YwFqjPE2=l97)GMYNf@9t_&QrltsU=2gbDy2 ziElXZcR6vN;fq+HTXhK6tIyUjhLZ=D^Nt%v(V47KL}bT4S7I=y-4xS01RbDdt;o@Q zc%eI#AK!sP*z{|MWY2|NFGOoOCEjR8Bv7x>CVc#x1Nfx>#iF!zc7%45)dIx_V~ zcR0`Z+ZkBn{O$QV2!zfpdtJ-Q?Svw5LoiFLcVnTt`~BdD^@@&gMu0&(E1!7}Pw>P3 z$GQ}7Jh!~jh!oGsp#AiJa{+$$Ab95)q=YUcF#B0LC5{$|Wf?S&yseH!!8}o-z7L;s zf*HnAkksvZ1uTr9^Az&1ejTu!M@LF6DX2>Z#^_(Vn?PjqCN$U(L+8qCI{5}`KL13C zL)9r{lhF+ZMkdf4fG=NR9$u16g60u*qkfAJda0JgjIo_ktZ-v{_<&zLH!l(V3C~7G zwsxI6fA^K-mEGl^k2Yr;xLQkAwmxy%xR&P13XL6uU{>i}79Wu6vvN0_1&ZK$e9plKEj!t}y!qyYKnA4tgalO2+nc|} zGQu{?w{7{ac)zZ&ll0y?jdoLiaNqR)B3lrWKjap~sh|D+m)@IS$RK&0(`rdid|wQJ zT5I!hy^1EkWRERu%#UFf6X4xp0Aa?uZ#Di9wjg_l)xK+jB7Bwk?>dRzN$3(YrrYiP zb$c{W5v8+%v(2#g-t1`%$2Q9A#y42&EHjso`pf2D8yG2$#2i$_E76`)>1eEAWRMty z87Idj#1Pqzg*jzl7|9cfUM(Wm(v9GD^r>TSz&jpG_p2&5>Nn2 z@L(sEqskNbHG+&h$N=(EFJDtY)lykVZcV-~P>;Ut-N)Q$y<$IhBlK>1IS(N8cKOA* zFxCN?Qg<=v>GK2XQ0wh~_Hp)_>5CpE0#m0)nYI@Z`>#!`zkg2DZm}{#7Q(H$g`znE zfn5k;XyT>Vh*U|}qr(wTR~4I{kDd8KMkP2c0!KM10WI&2$Q;6eDW+O_;Fea4m%OW` zVbED*(ccSa6>9q8H2qkWJgmFn%(kCGZCyQ9@2>F2nh3TeG{%1cjtsxHTQtZk=xen@n7_mMgYp zSDbSw!M{^OzV^N4H~oqtH23q@X`vf=bebPgL&%hV%c1juFa9hwPSZCCiKqMR|0{t~ zBOC&7@%QoF`3@mgBktO!ju8qXv#p}O-OAf^c%>EK#q`E^V;poV`k1+0e(@8VY%gE( z8j;&`y}Z?5X-g%q-2%VT=ke(Sc4kLJIz9o2o?JeoKsMs5p>;!}Dw63?F6C0_5eUO)MxFxst_%k7L7#TKvqZaP)KwdY?>2 zKiR)SQh5)Z$8B1bl#KeByKusv&`%>dyM#-^MmHv5;W#o3uuqSae*Kgb!8`z2u?^(3 zTeG?H`|kdZds9cY@5#PS^u;p{C*{V(rz~Qee%<7DM1?xy0+@UwNe-qxSNG?FO1Oc` zeZNF+0U+%8aeKj~b*GcDyZ_F_g`L*~sz~R|l@t1l6W0RuJpm}39#E@KEw%IV1Q*1!*_V*YiDt)!t&;(2PF8tIJ>NAN-c)!}6;d zt-Yz>X5&x|#Rd$N0-Dg#xL`N(EJa(VT6hI+-C>RHQA&oJO$X8ASm}0k2w~=2xdioo z{05XTv*GiIt4p^GbGlT)NdGy6s=x^FvL!A~LFX^07?`>y?1+F(@3B1Nn{5NPe@h%|w>O2}ME@KZa5?!LInIlrlLq-9fPT-Od01g-47jIL2d z`w;0-ux|DtFVA>vG%Cr@*RWSVC2XDzd~WY&9PBDhDPg1hO4AdoF(^4H6%{zca=6eu zp+c2!0iicBldW7wMj~<(k%7=s38{MurGoqjV)I2H6A9+|_^nKx1W&&YBb>o~Uzx6Ma2qn(54YKM#x5)Vz#RG~;4SAzywP1EBhAsF?) zD;EN**R2W|<_CUAdFDz4-fUQ8Tb9DVw*%A7s1$(d@p4F_I($Ig-j3SJ6T%Ih=%lXi zI)C=(V%Ygn3PUBgqIZfGUdE@Vh@~(i&D@?n(OvsTN^yh!jmvL(-{5Fv<&&7F8Hu)I zXK4!glZqONhU++yo{BWaRn{`4I6#8wPZ|fpupwjgfxjetcALJr1}?4V4SI2Q5NtY^V0KY9ojR9 z`hV}8TY{mYTGN5^fpW~-7it3iz1@fmTg`JKF^VF;rD4v+BQxvRzSi`$A4T5b$RfEv zc2woVi~o&5PCfahD&`z?e4JdzE8n6_y^Dqg3!dAL25rQkr^{9PlY9uBr(WR~whEKE z{HbIwTZ0Foj2{JdytHUDl_L-}d&5-($gX{ZzT?Bjm#;e0C@0Uo9-+$Ct}ruK2g{5w z$qji0(`YSO(zdZMgVrguYv*E63Ys&GPumewlay)d=gFl%S+madyZ5U))wI zGM?`R+g&Z2^_L?>Krt>bZmuzbG|(Q@w4uLWIZ1c=TzBqif3)a3jaO_1&AI7AbA`(i#c z<|wCJ7kU}bO!y=`puHZw{?)#%=ig`sC%;nko_lC9*>#+K7JS)g|DO&@d*es1FW3yt z0&_s9mq{QGfl-d(278D-q!)ax5WP%2wk>*!dO0KH@4U`#4gA*xcK-H|Emi-J7``Mh*|ZsN$~-p zm9xc4z_-GmjbKk>SPWrN3L8387uHMYiRxv5W@tTrsi6DY)O@p36ptpqOq<}aKdZp0 z+HuC+zdO=#GrNBA9cF9<4#4Dmq_J>U)bZ8a9L-vGMJjc_{U_Z0{p5vn;DiLk06Vmut6~Sw??Q5QQWiPC0h|J~yosLpu z$>5x0L`()MQN;LB<@!|o)MOU3vQ}^5Lo~upiO)m-LDXdPy~vD|2N8UKxq2?qHBbTO zqmoS}+V8J#@2^(*Cmo0FJ6@-{f~KF~$a9I`uKTb!r6L=tIV$eoY_DH#4>o@~;*2XZ zC5C4M_LBA>;xa9~km=%|NFW^4MMOdDXfqXQMQWyjY>ODDkuop&DMbX1#UHjw5D`Qq zUl%sSggz1@rOGEJZ!nRW47vkN4tfzk+HGv2<1!AYXB~l?7m{=%w9=q1aNm86!T1Fs zS)thBIljV2+M)*WWy|Gu9 z!sQ+%w2?to|FQ`SgF%;pwHLiiW%xs4UOTJ0NFmZiaKT^9MQHZWYuuH#9>frwDEybt zE@euBWpn`qiVfG0PkF_M@OdZ8QXKr7^sEMOHr~X%Ixufjx)>X{S(GSprOJc*2xB4J zi&po}xE(9{@dXO>|ReG)w}^sb|hu!-ro8IiAtQ zbEaBm9%qEWahxe;hOJ+owZ#o(wg4U4N}GJsz!aY!Kgnf#B0)vbgLjuwv-QPW-f6gxB z`>)^kCz*}Ad{T@SnG4;R;et7)174RWj$yCr!T4^;Au_%zOd)+sJ3E98{|r|*%r(D5 zPNZQG1jRs4q#!6Io6`1=xi$z-Iq$l+0D%U7z$1;BA1N}Eh5hanv`jnb$0liKdG^w> zdFQDG7Mc1e3}V#4fkpB)l_@AKgPJ75cs5}JP;0DZi-(9PGU>e^r|Jbp%z6up2wXjy z0Q;uYOr9Tf8OLQwI0AkfXBNIHC2VA_?N{$Hnu`t$8u+L!f@r7+P%uAm?T=pc83}KK zf63UhfYC$^R69m^WBI0Nbuyrebn|+iKZH`!zfmu-?BfqK%)M*!+_6`Mr>E0;_nN`L z+Po>g5$O!f{;6X;OO$bL5atbBrK{GI#a5(jSVMnSfxfn3}!(G*k61-UpD!Me;+RW@Qs!! zGykbq>XSlm&>+t|v3KS}qh#KKjao|1hnl6b;DFfs;q!V>xaaZ`+xt=?%q_C%*_r;1 z>=jm+qDG})rO~86HB5R|KajPIP@`8n_fYlD<0o$7?bW+%Lz}ZoCHvXz>hc+q-@9ip zI?&scR_gWT3RXGr?Fa!^KOz%Sz$$0g+E@@h5VLzgRjP5n9}LAJ>o(` zhMyJiHz8zTU$j(QIx+Zj`Obf~6NrS%R3g!X5?XjXEa!yMyqnf&I*&uf#N4+=CTQ9{ zt=@UjcM_L5h8a6fn6>`Bmb(ypzrW(3jJ0UA%}VjHDdUy-*C<1fkt2Ml#CR$O9dD%? z2x6SXn$9;+|Lxw>GuOfxg01rU`xt!E(COSdWV-Om0%wcGCnXXFFhC$t`10hopF4NPU8Nf5F z;0i+(nyq>cTgNHk6&n?BM!KaDP7S#X`q9*P0|#hh~TzIuUb%p3 zUMLX!^xE_{HFw+aAUop7^QkIcrmk}lnTfW?uA2s!(jH?6?WLuP{aL{06mFqed=H<} zQoH->h&XmVy+X1L$h~lK4lZ>|pS|AF6cd`hz9`rz=`8Exlgw3t>rAk#@F?x##h}wY z+Paz_*|wxZ?#exES9FpXyA7boaB{y8a~x+zy_8l@X~^kDn|;`9iX+gAL+DC6>CwTw z3(s%Q(E*!|KQFSIrNgy%^gmlsYT%p+q^YU!vQ^Ykl7H})kLj*ZFKHwcXpplFFk^{1 zBG-fM#kD-eW7jvl(=}JM)_;R>zr&;Zj#W_Cu!*f6 z?>8??F;rP9jy3N>6K`PQz~c6FH!V5ICQrw`?Ym^v!qRxXvMELvn`YW#V_DkH0P$*i zXd#jq3M@X^k@&Z$pGt-&DX$ohX&3?UfUfC2eJdE(&I^@eD<<@DQ|~~uaUT@1_?~Dr8tkaQ!0K_rWW>1v$$0-{<)pgs%GF4AI^mewu59t>M6te#W!h9$V(O}V$)Y8}kV1#j7iDRuce3=M?C02V9H*r-&QNzLJ2Mhsjp4ynnoFP+e7$xAo`J&B zh{B+pOnHJ%$IgIT3!$YG2bB%T@idAv(c{wxUPkgTSTK5uF6c;^0>wk~1ev5?a#f)c z6Ds!uns#?e*@5V3+Gdf*d2XDqRKG{kUw*6|o)Y24xViM1m;b?#lB%f0l9G~#-dlBS ztauuNmC~3iA4v6F?5}e zqknhp^z^6WBYh?_y{@|J?Qs|ymXvR(7GEg8O#<{6TniVuMZDn$M8oh5qWc+O%(^!x zK$q{8L=pYOEdFq32&8;9U962MmuerB&vZ`vA3v&|YkT&)E< zSX#N7-u~i$E_9K-Nsy6YklgX+HNZ?5P9uLhw|xE;o0~D&%(b$#)BR5&;#D;hgQe@T z3#OXaX#h8pN%ppJZE$=hugCC(dYrpECqO+mV95KyU8E-kx(DOi&NVEP1gsSD$*d96 z6tiJB-Nm2&G8n;3^mn|UdB>N|6XCf6wuresSFiVXcTMrjwLhJAegBOoBb1qHh$fvW znqu`U{zih!AW>z=y@N0tub{`UfP@_gdrB&uS#T5K$x_$UlnVM@qyY96FBqck{Wa{C?p3Y7_P_>FFi-#cT2v#D|Xz|iQ5U50< zN5fJ77GoCph=4JdqaT)$eUl<7(u6ythq`Okm@+w%g)QCQJJ5vj-i^LKud4){Kh@7n zPBPI5cwD~By-27Oqfx<+x}G`pamR<@h9(z+QDFT5C@K0ktZv>Np8Y~@mDfJ8z^Sw4 z@%X!UpC#@#b$Bo>L^L*PXxhzLTp|{24>7tIJBFj1M1GfHLyLhuo|TH0UV-Eyg9%ey zAal|q)ANTQUTeQ)1anSbyq(5e|LZmJ%*e)ropZ}|X& zpF!@j%{`dz)i$UAcd{vF*_DD#h|B9`43wd3-)m%Oq}zP5ab;cbLD!wb3g41;ojp%9 zm#d3~29^rFF;7BaAtcJbFOedET9lZFhz!JX;wRuR8`05hH(E%Z<$7)^8@4a5S1zf`lma9`_L-;^()>j@im_#M z7%hHVI=WcSYXgqWFx48N(0yZ9t(HyS_$Z*0cKuY=g_({>c+9odf`dpLfua^?=&&cu znn=fC+O4YE$WO^AO4I)7`QCF-dD9{QASU3pb)7jsW@OqqJ0LXLxja<#Dr~v)lUFd0 zv70jG1k%#zRKb)~SD|(-Wt0Cg{saDk8?bgMVjSMExz)8id=dRSdTC>WiP!aM=Xhfq zPgk;*?T)UNtEkf_(81t~d$YE`XF`E5%X3YgrV@A&N>g}DD!*tz!^DNIgqQor+B3IE zzaW`vk~gZ(Zff)RTAF9QHchLYCG6lNuVA0?Uuugn9f5o)DEUSm)_ zAAhfpq}RNkPIG>@+w*PQwdrg7fUM4bAA?EvWYMXxrSuo%AC3dekP=V(H(Ifw;w>Fr z;tVMq#P@dRM3U>xtCLL2<4nv3!`_pz>Wk^5 zjbBkxSTKTU5-pwKlo2?t$k()aeSUPMgW`I0^{lsj9+V+NBI3iI5<1f1#du?IPD(OC za&98A3Nz6YHUQjJL4VGG&yDUk!BGUcnx=cXJ4AXfE&`uB;I^52#V;IqY4Vb27YY37 zm2t@C-4+(5kyqsiCsKR?8YzqDU?Sn|h$4j2iw43&8ERlL9aEyfzs9sZ$h4+x>wWLMuiG$S$zvN_yPy&$p6g+ z;F<3NQ-m;w-T<@07>iGo(9>Y#5)C=6jwXss|C($A+9Gh0qM`HwmI}vy%auJF4_~1` zb7=dOh6&mU+IpL{wiDe=^Ul%C^M4$`T)UAU;YaULIt~8ts-@p?5tP5j^jE&-nuylS z+vw{N-E0T{r~=ZlxAC+UbI>=mbeSza8ICFy+ID$7UKhMG8+j#!?BJ!Jk1mI6SZCq^ z5y}*uTKbW@!nt9~VP5(suW$KLj0}ExJuj^T`0*39HJrz1n5UWPqF@IG_o%OheX7)| zyM>H%`N_Y9f)Qf)XJ4-b*h74UdC>msVV34!tM^;-)c<1h?q>><+>dW93{v%`B=+t2RdE?C=_OJ{+ z%)m1Bf`IImP5~1vYvoksjDZb{ldS|6eT3;ruY{VOUrgU(%l1aU7*o}_rA48yh;UE`=SfzDf zWFuFGGp23Fs7A?4#o31{7_1-)p13{Zo8Y z$;-p*fT!^K7DH!HvP`t3%`8sIO8KqllahKVy(@sKxudq>c_@e7bFAKv6x{b^;)S_SKrb4Hdh3cdR(bmBB~b98a*1}Gul z<}>)I{y}MGr>!RH-YPn3=c^jv-Pajq!|`!csVHcE*|JG@F%n*i4O4V8Cuxa9!NG)^egiEPh=M1;MC8@Cu5P5EzxIe}&W2vy`)RLG#$)qJ-f@{!+b z$zems2*g#{XkzKKvbvsA>(-=oVr6}JBoYSjdG*vfp2!Do4TRpc+OIfoHG01P?0$bX zw0F2XbpQ}tlPbdaIJ^l&=nggYm?XzUhE-|LQ7(aK&Mle-cgIKGxTN8W1pL4MB$z)i zHyMFmccH*fyeqM#NA6rC&6xb<_p8C6_owy0&jMs*&&S6Ld%IY9d3N_EZOdce3@zAE zUW#^ljGn2K(RIz%WyX3A3l+V4GooDVs&m!4ns#U4$&8`@Q$And@%Un9%56~og1c$3 z8&@nLG$SD#bdJgQILZCc0rXGdT)2&6^Wbkb(;}Z1Rhkk*!z$4SJXE-5!}%PvG0)BM zN)0zxH}-Z;LT;D154}O}KNIq}HG#EX7y3E{IURKL+~jRE^u09fy*!YurSX5a;su62 zuy}QOha>E3R~$E*EZ-BaI-jpYsJHB#&aZA(&pkLMl`g2So=N%<*-~UgqG?3M`^vD< zbTZDLil#nn!;%BO{guEiD1fRFC!o3I5w@%hM`ZgEgAX9~UwQg_n6udVd@Lxle++l(UEf9yz}xRmVf1LQ!;bV&gE&x4 z#7MpL>;yX}%NJ}m_)U7aiFiD0tOx7g95+`qwX+&%XU8Y?GjdYWin21a8|f;+zHazW zufx=`NSqB&uNOqKRSE2a3|`G{mm{gl-vK&L+QSy8Wq@ ziXf`1cD0OEb#*n=^3$^NQVNj8G75^?_)u);mwkEZ@7*%PzKu_f%}h?yGXQJqcYYyb z^L8rd^F1~m&HtWj)M_y2ahlMJN^$|uJ%A_?fzqu+6SbwNWw~YjydrK7g5}bhm`jK; zBh5DtwJc07QEU-2DgReD`2-hRh1^7di0t(HsEsLhKCNs_m$dLn5|Y7-ga|`a@>2g- z!s8Ry(~Iq0rUv3!xOi6S?pu}0|Do-y;;QPRcE9QF?(S}+ySq!e8>A$p8>BQPo!fHPF|ung<}X%A$=3-V@(|+ zPv6f+bM&&g@fP7&_qAQ2Ey?#Z610(~rs(hhR>yLELst6VX8mcI%a#x|g++Dp5)aT!4>n@2zar%4l_26C4-=^Gr=vhw?}SEutDGVc#aV&7%A#w z9^+?cXLY9;g6rnhTUMrC+RI-a@=j(fWyK4FO)D9gJ7aFX*%ceciTzntOs`1$yVSM^ zN$jt~4zhjo*-X?tDAS^sa}VxmQ*UTR_c;*v<@-Ezf82QC+D((qOJPv%K!{sK&uvCW zm0Q(o*$#V!QnxB(w|JBPK9Iu%ExS6w$N&BGzn}k~FaJM%I|$7(+GYRjdg0($I9o(F zQO2jbrUETl@eKj^kgq*Mw-5Sr(@QtuRpja60iJ7EKa{~P_V-%5e#9(I-RfanP>=d< zk+VXbT0&|YmgEiiKOUn~1mTnW+1~|{^(z<)11~2FpRX&E#GmhjFL!5ypIcm??}A@C z>b19Nxg_pvMz!dfJk{g#yQLva74fiw)vW&M3g4hUkByCC9WTSeFk3x(+gUG*h*Qd& zCo}bYdDLZnUFO-wDOoB*wW`phLW)8v6#Og#A%Zr5_Cq|67Js6u9f1`urOe_m`?WGO z`QPt}KPUeXuo^BpEL2JM<55X4vpDP`qqS?5CLIbM9*wxwdNTFqcxARwT%3Wy?&fHT zM8MT~sb*=p&RCkVwG-*lGKsYm78zO=-iiuAYA#KfBJf=DaG_kiK*RwG8z!|(quF{g z90B8qg9?K}EKg#HMZbRWqkd8u;?=x7MZS+*joY0cep0;LkCV8$OWyzdlqBG~?ss?k!vrM))pH~GC1^)2hu2{+1Pb=& zVY|!sPI3WPQjbZ?Z_PH~PyFcd<H}Q>_Kp#%EamtwJ&!K9Ptg%8QZy!IJ`Qh_jgf zyn-4cP8;UWS&2r%e|@(3GRaU_wngkphtDXByv6Gn(){P{EZU(s13VXQ`oHb-i&XjN z>zBud7k_zH^CgUT=P>WUGI5TfBZdti1gow>HCM>{h}Zwx-kFOt+#xEm)#dx``Su8G zRQ#ZnUW4iDQn^I1J+M8F7ON#tVByfC9mYqkD$D{eWCf!a7z{dGf0#2oSuTg-I14RP zki$!vU-Q)>bVEdB3|sBz8!bk3BJ@q)MlzaUlEuNu%;ddl0oOM;I2a03Y{U4iT$x}l zMn=f%;CvVbh{8q*53}IE-kys!XxOw&&G685wh`$PSh8DTp2hqI(>LHv_>@G!G5Cw4 z?CAN=*?`w!susMeg*hY5dAN~g=1o(w!uD`vHD+U?zx_tp^0u0azAghyU z3|%2@&g-2iC=-}ONbqZIP6$|7<%5nO;uOY%rLugq!hfd=Cr6twRku?OjX)FJ}%8sdbfvP z<#o9{cNH+PMw!7zUP@r3S%pFNlr(i(si$LK8=h6ri$TGnJ*Jk8vlqldtkozEQ}W#! zgyKaI+kUHGZ?fGH_;8s{kiJJO3cjj_d)$7M{+~>6O{(0&XEU7%_wn6jTH$)o-H#mu z9C{T6GQ0@pPzjf{)}iN1L>(H!+P%7t4QK_<j=amzKjEa#}maByY!5rv`wKF7;-Z3%Et zbzK;x)WXT0uB=AUmRAN}nm~dk1y6)EKukXvcs?F*oyJM%*Tac8-Ww#Je-G9Xzr#XA ze2wl$XcA2kEVw0zGiWK0k4=+?Fhbyud)+q0P6sE82ry}&tfSG%cwc0usMSpGip1kt}KB5IH)t2lpflYN~esxpn=+{ zTf4q)VtxkV9PWp*$J>+dRhl%}II@)W!xGc~!ae(zRwMPQR=R+uybL8mj%;(Kdg1a> zY`6Dum|_k40r3ZBvLjfVi6#&sXGN|)gO{If3*rTi%F3(E`1p7lJ-L)(SgF=~Xk=)f zgQbrIzjS$6Y!%1&x3rQ;<|5-2)95|Yl0j^RFhgKCV}&V+uHgdEoS?P`L%`;TyoSiV zJpT>FVQYq971QV38}s49pxAzTB6$g1?LdGnU8-~271m?el6-rOAN?xCncxus740pWYL!6w`fqJGid zR0fM%-%VyGr6D2*hiUIB2$7r5w;hAzcZ!9JotOeUOb+#C0|kRo{R?Q_&E9`v<255!-&bQ2-b_hP|H?-?U9-zXTCBntXvdrW~ z<~FC4$i_pDlkhuZ>W7QrGikv>(DhBNJxy=uUatgmx#?=cC*3^g{8D~g8_=EoYuKzn zLjUKlObDytZi`xpu}I{W9?z7iRcvKSkChLTdrXESrM0!TC|)X?rLrLIh|e5S`ets zW>ulmvf8gQv>-L1y3HIQtb(HOf%v;>#%#o!4_*`fe>laPE)97;6bbzKK8gO~>i8O& z_ER@qbR)b2(w$myxLC_?{K0pnA`}Yva@%b)%THpAjVG?l8yu1PCeMx@ut*!79@54= ztXRfERGf%Em4>MUN#mL52fC4QwA82P=VU3%Vsi4*1en52!&&gO6|o2+%dtCATn(Fx zM@AUkwK6D2qa2GHk~s#OR6a&%KQNA!>p2!udX3vZ2e)|LemyFrc%K0RI(uh{xp1J7 z48|GlI7Z2=a9-;#;#&pmA?$L6GOI*3=gDd&1Gow`>!=Nm5ntTLs#cU~>YEdTQmyQ{ zp2YA>Zv!!m1k4@=ToP-p4A z0~B%<1fzv(ySp3VNEpQBZ%sPkI`wGP#ctB+zB3y8KRfSl+luLk zU=&k!o6AalKK;UdR2OF{P<)?(;HyL@StHx?{=M4t_Ue}hm&I@d5U05goNsu1PuG1n zgY-R+Uiths*vsAWQ2;AdzdF?S6Uoy+gy|MzCa zZPfGe+JVQ>@W@ON>vEx78B_&B87%tfWJ2JG`ZG3@&SZH8Fq>f9QD1@gf{8Mu@BlVN z!0qqt6E7fyR6cND_S<8Qsj^kllDSYRG)gZFHENNhqqJ$7Zm3+g@N)+$S85G;ypMEFu(?`)c7X7+nG{h2)|b=-O{qP%YwGslxCW&?`X95T~moZ|SMmTN({jfnL0 zVDcknfrSz4a<5=m%B`D^%oXZGLlCI_T9*LQ<9OCcY$N}WScqkdmrneegaXfMz3xSq$?2gJ{O37H^<10e+55zud(^=&&keMyp?=R7~8=@ zdAv{;t+EU&HxhJS(HEe$AD$7=Nn>822ULUPc`{cFL-2DvG3}!X$?7_g72wZ9lv$^j z4c1y6u7E0gPsk<3vW4^aG|TLrq1cZRF^)rs_}+9D!{dCZd}ta-EB>IIS;RgfV%IY8 zoSd0~qvCg6k5OgSERm^+zHg18+oz|zE0PQc5nZpzQkFS-k&y#WHpPV;>w90|gJ)w} zE)X&l$VJ#5;!o$&x`>g`!_yfozKr;&)NAB|?&bgk_hc%ewyGVf0jtwJjk8R<+si@a zjn61D$wK|>9(!^fTaZbcwg_FPdMw9~AtY&arYNd=BL;I39SN5!RSbdy!>SXV_AqNf#u^ z+X!&~@IbEwd-ydc3%sf+x1}1q8Ld-xCJwY%v*wC?;{bQ3W36P&>8Q2c=?skftbwOJ zAe6&zilYe&sx7RC$A`Q=!8h+ttd9#h=jscVmBw5fAD-&gn;5EneJI$A$2k6+g>;u{ z8Mt5`qEfcAKt)GTr1sap3eOhzni};MrG_^6$UyOx54A`kBctrSW~rQo{QZ5?m%wo& zT}A|DP#(!r3}Rm;x?UPIDo zKD{NRy>i?G2w8E|d}cDVcrI+otmJFWkFcd1jTsrty3HR7Mm0YmjV|2po*EdnJ1hDe zsI=)cnC1%=Z_z4qGUFR##7%IBl^ftHpKbJ^;4#wdv%IKSTj8)Ye}^TBal}NPM9o2%13v@~iVPz=HHRiYIfiV|cjJ=jBwHH5 zer8-o)?NZ7aO!Z?d_!5wWR`=d>4#HOwbijJq|ZfctFHvrM&va-92frkJjW4C1(^(U|uwkqz5bpFgH zSkwS{^}VCOxlZhF^Q|Vq{^5? zBw53I&Ff-{rNKVFJ5lON`HIE3oz=}zozYK7RgtW_7^ddgm z!BQG-Jh#k>{mI>Yf@*8I?U4_oVq}ns|6$Y z(EAqI(|nE(OV(rYyX;$+NO)Z3EOs>Aod&eWPy<>uIRjEml)v*P{UIY`C>pSH#A~!> zRJQB$1Mb_y8nDpX(W^m?c}HWO)q>n}Qml^Q!wXLI_;UE~GYm36Of@;z!Jb8$R3SHx zPDH4lAQneT_v$6*Hk-exX1S5l`MCb}>Ee^`?^Q{2R2Fs3?2f2vS-YPGI(%-0LRc&% z1x!7JZ;phzVJ#2QrsDCg!;Z#&Ycb%O8IvvMrtGshbK#rKYr+fHGg1E(U56_1lZ+@E zlM?e&eS$+dafhrivync9q-ZeuWn*WF;U+I-ow5Bd3t)=Xpc^o_9Y0!*_LUL})ms?T zJxrcAq3g~5@HV42uwekSC`=1=^L$wNtfgM=US&KF@=)kUi{XP(@rPOv{&F^k8-RgFl`!^_pyQ_FIGv+>`=@{K$G^8e@x|Qc-EB+Z5AyiHj!p2S zKwuMgoHn8{UgX>J%ZjDl)AGKA>Mlr7_vzpGJgn}{;2*;W4Az7ZtqMA0ZtlAU|M?Dn z0tY*Oxz#~i%$YMuUHKHYbQMPn6u>3Ddt16SI-1c0@eOEN*A$8aKrWTZDPZC%z}Pgo z20dOkX%bT=s^j9Qo0bg{)N4z9<~`4k-%b(Kkw#5OU8vrNE|L{UUm1m$Bb^30=G7@o zAv3xy87B?dXReC350`se7gYvxw?N++?N;c**efp;D}rK}?}H@r^-vR^wNh-Av?F}R zAgY$Mu_lp=Wa;8=GaEiC%frIT@@N6u1!V(fD>hD?!7MNp)N}b01={%Wo!Pt0?Wiz4 zd1aB!G5jsRHB}O-npzf1MRI-<8LKE|OVUVKaA;2U8f}7Is0nlyl92i?Vf?PTNvmAR z0m;TPO?s{EN4ssRmtWmE%x?}hC^@`g&Vj0ES4QcZg?$NueCSdiWh_P-4s?@wCi^F7 zD)ceNM3?~_D~OdgA)CGaa!V{-RFU-+$I zv*k%m3J}I>V6+x~A`eJdQKG(n@?#n#ArtmzUiTRFWEw0D%W?GIiDek9p?E%z243&} z58ut1wu*G;K0d0$sd>6x4hsIv*A#?i#8pLjuGA{4V$YT-e08b~%c*fY8KGWxN6U3A zRzr3bl4EgrERJkZ6R?|vlgJuPg2c5y#Udo?QQ({d6Adsak^c4}96tA`G2{p$ zUX(J>zA6*R?Ka@B-*mr+CdFOFf~+i*t>b!awgRWAdk z2dNgv#VSeR;t~j6T`wgkeQu`2X&J}OFxk6Rd$NekZb8|aFhwuNDS3v#!$;oL&W86c0gz&Vu5Mc2ldtV+`@d&qNL7WKGj5 z6Z^~j%Q(e20kt3@%P!n4P066E>%-^Mv*#}&+s~)I10ywS)S})WiYbK@VX-NZsXy(m z>eX`cM`Bcf_KMfVZcM(LG^z4ul|SC2{1P-`49*en$*4l;`(i&r0txRHBsp}2AdKbe|e zbuWqJjpxHItPhdKoX5^+AbI6U+Mud}Qf@xtu^0ypdyv>WosJ$pZyDKY5P}lF4TJss zck?Ab!P=nOv@80P8WwhB6URYCsR3f?*F;5%uc&yG9+LF5vzdP8V-ho?a^-WcXy>8S z{7(my@S)9b8f~aC0~T7tty*KzLa@xw z({Bfl=XzS&YTK_A)!G+VHIPaaIhWY(il-f4(v9}x7Z9X~YLv-p-MJHDDDhQel#0e2 z-(d+UW9hJqQREOoYAp=bMC!759X<%vGI((){>4c-Cmv63_pDS*qhwDE{k4)ehG! zel==e|Kg2&PdB{kz#GM(%|bK&o(u(d9%a1tD&{PagYol$bPO)zBxrQS?&MGQ*hI zbr2)e?q%MoFstdoS4wdy)Hc;CAXT_@Vu^;q%v)tdE_hnJ3Z{l*Mkbb_z=u(dA8>AgN`6hq%tlhzT;E#`xhP~tlzSZ!3%tQK|f6Zq)eMq{vG z<1hL3Q*eLf-ci4oeJy%9L30h`{MNV=DfIadP(;d=0Z;cA2Ca;y=4c$DxT)2g*#^CQ zTSTmt{8j9NL}M~8%wK)#kemF3alaw*HhIxzt8GP;VyfgBFc_y|p@xScN){L2Z3Hyr zJ2;S>4JTqgL1S|t(1!hz!N^KO#EU{D!ftn|K}4?dFYTS9EIq46uV>^qOYe}@E{>O2 zzK-zYqh|Rsb&bKH_~Z6id1 zjQGsZ!4Hr>jI+5sOZFtuvg%N03| zV`JqZRGDlP>LN-%$R_ji@<>rx%qBoJ&Z*+{v1x_S-}x(r)pptlw55S0x~jhw+yT?o z-{UtsX%(}kRT{-#o92Wo?h?s9g^AxRY8&8_ZA+>r%X{9*%c$@aGIl}WjbP-2EFA)y zuHzpB4=KSy$veQ6KW^r1rlcN6iS%yA{|2S7ivDH_l4-7Iy~wG>=d=v$6oe(|PZG%} znDu9*aD(uTGd^(1&{TY^@cqzu>15Z#Lee#yn>qS(Ptg@ZQ&}7h?Cnckr&fBqwB$9> zNEO7@#xsdbLUM_&d={Jyt4gM@?Wi_Y$Oc(6-cYoQQ8Trxw(c&6ODbYxp9VDzm}TY^ z$THcC^-8s_rCKwh3FLJrzJQ1L(kaDAU1S|dRNp55vvfKVh7BC!qUdR%WhE$7*-O|I zMtUG2)$FUO>9IR7Q1%$@$L#a0)jlQCxV-E&;}Q)Ap$OzfU(Kggs;IqSribc=!V$E2 zfB~O?kDzJQD|Yn>D`=x9qvUHhWj`;*8ety=nJijmnFUOyl(v*s1n?t>)ll_{dFqb0 zqbYu|k@PP>GZAyhntUL2CDMtdIX2c;S8v>!3pm#} zxS!DU7fhZ|=gHg_>}LI_o^zWK6nV2aF5zSLN3=E>9-uQVlrPgx@<%y`o1!YBZ&^n? zLpq1DB#=FOfK-FXtBf+|?HV~s(fh=$l*F=cuKaVF%7Zf_#fuQ}T?E)=8{NdW)OQim zOhuN8tOpfu-{qz@Wu@-jU`4S*!)Fomc#d$C&*6JoAo+6M5q_Q9D|Kls6(3^RYVg=& zGmx-&u7guaPUq2kl{#EK9?z~Z5h7poUbJjFbPy6h-70qOh|n`^xRYGo1Een!=~+tPKJ`s z(q1tL0^Y_2ifN&Y;znc zXy@UOzH3?TMYbi6vg!|$DBtSm`JosRD>}|ZG%fg(q2j3>CvYvv*CFGP8z$fT)J|Bi zqL7*rzGE*_Fd_I7(T$6y=E|-m$pm?!lxGgIDfntp0-( zXYXfOr%H*sk+vXG(n{==Qc3TU#;qi=v$YTyi7Qme{@WiY6j2bN)i;sL6?e(MWPAB4 zJrh^n2ZP{E%@L+s#wvHeCVFWVMfBvzL}{x)W}gN-!ckJ z0dxWUPx<$xz!Kbw#bJ0q+U&O3&t)}!u%5_x%m0z7M29aS&%x%?)5BFY(ZlzpvT6PA z@?X^9-hG%~X;3QX_%N~JSmefZ@x++<(oXi{x6F*&dpcM`<4$*~cCj0k zURL=N8{&t_T|7&`Z(Iu6$eT_g4TED7crUG3=>Jgxyx4#X|YkIYOJCKdPcbn=dvw5#*+{ldF zG7DjZ`w1T=Mlniiqrp=q1ofUL{cj&X&oau2InhjgiX9P1+}Y9Ml!M!&HIDb?djE2c z@uE>8gY=y}$NnH2IKN3z^1BYW({ks$-8SK`!x&Xg0Cq5n(P}sG3!(r^4P5|akS(x~ zL06iD+dAfpixKF!11u*5`EW9*%L#OD6iOcs$XMb(90<7jVedgj7(Bs8tGr}DsS!``P-pewB-~N2V zX};e3_KML|eb#$AlP%!ph|Uhjh`&PC7xZAa`VfD4S7l4Eq-l%&N8Hd`PVPEjomXj= zx}xl!y*!`YooyCoC+_=$8~FFnT?dj~d6D-xe;(f6tG~FE-#mr4Kgg|u4rF~__j*JM zL=&Xjh;;LGs<+_wN9vk4ceri3MnkXE=pL_ky?LS&F0X#$2iGl>zdTOP_m=+m;!`qd zFLOzCx{!>6^CWspR%#>r+c%qSP6QgTL{f?|^Dr19?$1we&uc+*-l(Pi02rcAGj8uj zN2U_6+*vr1wuKZw6viMs*vhT`vmyzdY174>(QI1(QLE2OzGY$*)o^3I&6}=l+{zV@L)S zY&)UgB2*6$!;f3x7-EkHrQoJmJWA5D227^Xfv$S}-z00a;t!zhU8a}@AhAzo2Wr4u zG3SqaF=cL_OS_!=&zS7?B0HYb&UKo)W7284M5_7ke0-Pm*Qok14D zd(JTmT?6HiUTKR?E`s=XkBLB{Xq`E%r#Rf_#TGCe{RA;K8~eLGWbeHJF%oArxl-rB zI05sYnV!|YM z#x$Z`=BR4qB<#Z4dH-H`hq!nCV&CW<{kNtHr(*xEWICgd6!I#qg8DxLD#^xj5hqd+ zQ>?>wCWn~Mae~eX$h?fm6AUszcS_nM6viA4o~f%{l5#__ziZfh5A8zy>?wyOZN>oPZD@_4b~GJT%zJr?qW zylc8qF7=N|0gAR4@TuvuRydCL(c(~o6w0VAw(twq@SyiU`sE@D2x}PlK?o-FJQbuC zbS4cAEQ(NiI958$kt+1IS_AG*!J0hT90>jgy)dYyZ}NZU!lX`WBD{uzfq!~j85m!l zc43Jk(bEBo5HvmkC=fnK{2nkT=_2J}`5}fNSc9f1+VuQz+&}imX&Dt7RzKVguun)| zG1LZa2lcBG^n$bhAl02gWE9;&w$QTO=zS|BkK8H^6ns`lUy-m-`ai``M67vx z`h(>;bRI#?_H#BAN!r<)6#BDcM)H`^}Mj`Q0{9Gm2%3a$LH1 z(3t?=lgbxb|PLo@$|Iv`|d{dcGj2>OTA01bTt zh0+|)gEim7HUh2*h&R_eNX&|(FTc4SU}E( z73-sjSNp#3c(1Z1_ja1yiy~*K*+yBbQ5wCDd{{RS&@_T?FRia1Uhy~}K8H%Qd;bQj z9rTrXK0Sndc>h{|XHI^`HqzDN^}q1K5#y~adOf!-JFMFFYAD?AWVH!~b`DqV0Ezc{ z*QKWio0ZB7C*%B=YqVvV|C&??Sctx^x+^%rd@CaQr5H^%8tlE%yx58RX%?bWVCa zEtuBkyVXrjQ}*5Su*+Zx8JKUqKiMv#3^ zVT^f&p)$7EXe7n)0}1jBEt(W@SEN#uk>gxL^4uDo8JVBJ%4{Q!L6>${tCB7>wY7eE ze6@7EvvYYORm&J|cc&7X$V*#WgW8SXE_*0KM65Q^=_Ij$&$Tusl>3LvOsQknkBxMd z*A9Q1i;fCQ1*Iw$hH|)t4Lh_=X->`OOV|Z=e3ho5vPMftrnlwkROV+w$F%43Adp6A$mG9jl$2Eqo&d>bE(a$KV}U=@i(})NRnXp1&_0`+-KLaq_$}cJSa^SK zPXZn;Z4NoD#!-cB__)|womSYpyww}i0xzXnEFWIIrSgC+Us4ogchq4*R%=Q3=ReGF zY?dBGSNBJqlsw9J-|z^xK23~8tQHg0(p#BEKra$?ev^F}4(r(!E1KjzpyGMbihdF;qc*+W{)hoA?I1=Ekp3kHOiOi_3vOo6rhf!855 z5CfT8lHe#!Nm_vWWVtR^L@vs`JXtj0mQ}kVVVz{{9Y^Y(Z12T5$-y!}-hf1_GaKj! zQWAHQS&2n&t_*PEAfD6x1)TJIVm_q?(@)(W$#t$kWDmF)BN&Nf8}^9j#rY9$hhaKeiXGHEDLlYv_)|P2M%f# zOTj&-;&NJryT$a%Ti(sXzLQp1*zERZ864S!K|n_gSZjAdiO_~cMz`#{`XX#nG?4c< z8Z8O>(pJ|^hrq!8UTK7engG-yS;Xn+qluPoe>HncpMXI8`Vn><9+hwoSi7!z00${h z!bL@|B-^wW^*YcXmwk)S8S$NeeZ8|2mv9uD(h%X*^^fP4!oMnZrmM7Za|(Ln^dg_5 zyIrv*l3JH0$EzECJ!`DR=yx4ocUi4)h5;2nyeL&nsS7Z$PfC}FIL;)VhuYz!o_z6< z(Det0EM!*4&pmahn$)*5EqfB3#lagUkv++*;(~0<(7yHjV~M&}A8{hMr(o>Tu*h zJRv?Q)UxEkPaYeKTSMV*4FNsouu!H53jbE0U=R>6#O^6QzyO2NP_cYOS?+LvzD1}2 z`D8BAD6sd*p^vuS?8?G47VAriJ)MsXl3TwgruXoN_h-hI%Yu6+x5JAUCx`D@EF~X- ztOMoHJvg8%Tvwu&FO*I_WgOtp|LMQGPW#>_dUO+1YL}q_Kt4auY(Al_98Inn@v#zQ zUI5KFbTBx6u)1J}Aks9<#E2*#AGColYO-Odps9* zp~TTj!+_%wbBQ@A)j#T7lI!tzHp$Ru04xASP8|m4R{AFKRRv1YMMnOZhUL$>-O*Sa znc{fWed7A?NVpf?Dur3H65Dve7!)0=DJp!;sZ6F5lrJ+gky?y!r$rchbTph2G*2L43$6UsXZA_B#FmksW8oUYjw%_2I##^!vxE-Ln&6Y z>PgX8y^>!j8?{&47zzVDK~K%A9!!6rR+%@0i?65%Q$WyukJMs8VF^{JxuNt30L5cQ zri9nw@MtCXF|y90N?)?Mqz~eqH~U|Uxhvv0#+;NAs9$I@iCnPcIi$77bVcvew)P~@@k}8Q1|O;bOgpz38oWBtVv>zjNVd?MU)VvFzD~dijmVu z4O}o5w5`ryVq<;VJ4A)>pt8VUDFLDV0?dMdQ@|3ls=~AbR=xVXw(wa~hR;dPVb~R* zsuw)>rm(V3p<&~5bOxY~XN`-*hm>iNf5ZS#0z0JuVPJv66+w8HxT=&3f}PA+6ptR- zg+cF2h+Tx}JSPc7Kd%9)eTE%NnGG<9U!|9X#*F-etg29Hm4=HpLO;led!|FM2E#tU z!1y_!5*LA>(HfM4<5T!otB2@{KW$?SF~94oK&k!WHh~Ik zu#yk7NKxcH;OK?Nxh6Ex?Wq3m+Xl@h+-*nmRyVx#<7OJL_f(K;1;GeS7Tub3^zV3? z$wh*hm|>j;D#pLxD?*>7lkJ9+i%vSCqbf%~WTp(SO*P6jv3UKifQLs)6Y8*-#%d~% zVr^zOZm&g-aah){6HKD}(OQ7!()2T3bl2jRWmF3d!sE{BwS`5AFbBPXYqqoj=(r*w z9q10f)2{sx%v1BbZ39}Ay9G}%#_GHsoRt1ZA)Fea5}4$zub`iA z>VHT_i8B}GJ4J(QQN>t4AI%JMKFL|kAg1c|Vge;oNRH58BmtVnWFjI#4K)^@Cj+t~ zR>56l4Q1R02Nbqba7dt|AgT6JJ3=?XWkO_X(Z8{+L=WhfGFz*GUyb*`AaK;tEEvK4 zH>bl?MXLNm_gq4Pt_x&;u8QIwgsWqvmlZYk<4(uVEKo6B|z?l?H-!-@~um>u+3l+y+OuZ#+)dUv141!XHh(?q(!-KvuGu z(nMn6AZU${QUAao^qlht%QDty;U=Im4! z*N=exbgIfU&@wBPLqp?FWi^+s=39iH(4+#>ZMvMC*sM*5(jTD~vSi^m5Npv#0TNr{ z=h5ZNyRQ7kL8l>q7CQRtqo{HmF~kjmZAv6m+KY&$E@>tKO|P1?3r-k5Ko!*7jVAX; z)LCvVS;k4N{o-@D(m)aM3*?SoXo!jvE}wA)J=8+TvWXYS@F1f2lksa;3DL4EDvr4S zB#s*zK2+0m)JViF@vCzHx@qY=rv5h&i7-hF)c17`Y^P4-)B2_$6N`+-h4odLNM|&{ zsf#_(+D4u_;{HbYMf0iRYRGB_3U4Su?ue5p1X)fJ7eN`eWvBwwpaH;&H0qt}dSmx^ z1CY&-p|FsYVG<%HjUhcn^XA~c$7UT)EAPFWtvqo#29}9o7lvFdQ`?=tNePLJX;}?% zT|X^JrU2`E<$~Itu|%33oX?EF+7^jVV+@87Paz~$;|W+&(IjzuwfNoeO7o>z9{(Ue zVB;2Xtkc@4!bQe2GjX3M-2DF0a|e98bZ-S+yzCNDVDIVVAVMLB=oZPAD`h~U7)`^V z#x*3Ig%F{}Meeu4jj}5pvVlVkZM$UxrcEN{76U=*uhg}X%xi-L~TY(D1 zx~`?b`<6ZkYYi{-a1+Am=$)SBACea7+FEjN0KuG=3#!Yw+-QSD=u2=_+nv5itHIRN z_F4<~&K?Z7P_8rZs0I9W6)B6-g@+x3VRpI3Y*qsqcKGWNcu*Kf`J~AMxd{@pj;m|E zM=d~9apZEX8hs7wtF^q$PrO$ zNKuoKF=xG3UqBgCY|ls;g>@R0DVelWDjlOxd(O&IYPm?_9yXlqHXjdq%{BTS^Jpxn zTg4<$trGuOuWMAPtc1Z;(B5Dweftw`J{p6feo7w46geW+n$Ji9PRi6mTrR(DA+%XT zi*ibk$SrYdr6kxAE5v+|p%stu>AgYQ~{kc)Gnbui)ffL>z8 zR-6JwLAULpjEiI^Fnf$>z##$irO_2^(xX~V0L(K@M!Z*@G6(1i9pB)`dc3v>;DVq%`an%BfGUMqu?^=9A3&97lM&X$GU_a9{_+(<$T7Os;@_ zosq5`+te|}H;ZqQdo(E?hVPA!!=&f{;yAF6b}ptVJ}92Um%Fl;W`iz4qWJa}8O-CDjLK&zgr1nWu&ss zlVL(|(inCXB;0DAb9N!BTqzy}c?o0PeVXfZ{eu0K4KT++7nEZDgv*zB`7gvp8{5nQSP8#0bqTE`4G zd5wYO+bPKA9}@hAjm_^D;hkk;c@;B{5C!9BcVJ7bcczL35-~A`4d9#L^R~G?*isY( z3DoWhmdzgMCU^0<+k{i~u#=om%xX{qh2h4(WyDYWLN#fmwrx%bm`b76vJS>xnRG0{YzJL ziKqFM`h!vcntE|8(c6HLoDo5TaLqyG#~c~_>U*wT0XshZk7Rjy!_H+`6HN=1(k(2 zP--CAxquGMmP{iUfFKp|Qr`*VD zVsb!e=ntuBo(IFp6k>s$^!wTf*E*!1oj@V0%UF8^nmoW&k@l;t^D(nQsCmMD^))o& zpA+-wX}n#b%K&UrJQ2+M8G+4KnpgkkVFrSOmH+eT4R=(MRq#qinSKKApHJTY3kI-6 z-{Z3Asn|(}ZzdA+E#ypssA+sA^X&e>rdbk!$zrXuH3eciC|!_h)v`H@-~D~Wb@?|3 z2ajq1433lBdhN_Y-4|djV3s%bSj$sVy!h`Ocv<<5=j)R zS@eHOyYgtL*FHWC216M8n#nSjq{$K~VMw-XNihw&46=m`iQ<}M#=eg!*_X{cNKeT-TkpJJg*c2lLg_ z?evO=`;*42A2O2W#heFr)eW<(u>Q+_K;*ftaRC}F1;hcxa-?wgGs;;JiC%^N@{2n`Jd5C)9P zBYAM+mptd4)C76c7Q?Qq*u>MNcivnRh(V&+*HV`YRrqZ*@sQ$yFUgH)(gQj&IqQ4wLwgp(-Ka1Bc0dgv9lxgwv5eV&-4W zJy+<1@6U=x_^XW0cEr=FK$wdx#k^$9m7;rW6NI)ub8tX%Z=4A4RPQ9O0r$X6_*88H zO(uHxipBIWLIw7GHeZNR3UtURBS0Pl=AlAa$8W4|8c+wsH*}xZu?=kB&sVKm+`XD` z6m|G!vX*AXKYe^406yMkvcBcj@=78%$pO_}`jhMv2Pnt6(($yoezj`<|~n#@zw zh<4@8%E^4>J{HU6&6pXxYGgjyv*+t{%-*l{L%xi+w6#l(UG6Q{*6KdEmS~LYMn1}u zvra!?_(*&QtO;UKpE%pT!r7Lco=ClL3~ zO2y1uanm(9`lAarl(<=DFVuUop%%!om{|<(L_b_iooF8StY$-^^}gJFh?r9r+5pSR ztN;|LFQ*+Zs#5{p^aNn2xX%08nJ4d-0pfu~ONYS3b31R^U~K{Gc~$mA)7ff%R*t}j z>Vrohb}x9_wRJwl@=}Mc70*xj6p^Hu#|HYvw@8vH(pdl6km7oRO8O~D_8LgOoT-~s zVkAk18tbw+ybimy=%`|9BrZmnoQC;Dm>4t2Qk7B7vD1v`6W)pVkJ8tVpjG@+7LcQ0 zd0Xz+;Ot<+(1}%wh+rU(4=1-)%#K1bGIfVseA2jU2u$bTzF}ZzpL!rt zwvVOyHG${c5>DVu`5Um!lL~~as^l8g6e~?s=XaAbCaoaDg)zsrva4oop}w)FFr zkT|Qj+@=mE3zG$sG)whCtnmlHoY1y0a*I~k29hC1ag?zqss`N-Tn5H;2*&}xg&fRH z()xg8mk*;mmxslFpr)q{?BP(Q0VF0iuwJS~g77Ff)Xnj}P2@(uUUPAZyG+h~MfsHq z8<8iOQOo3)?{szGMrDS~SpoS|DP%yaqckAjHZ%6A1!6BIcUoG&A{2=X7RhHJMS*{IgV4_08Sj#G1gcGVQ72um7(JNnH7K&mtS_C1=)lWyrQhQP3f2M`b!#RJ*_qZ$tK`vvhnp#%c>HDOhQ zW7O8;ed4I`ui1AGaUMOX5e!anaPrlOU2k}5O6H&4WqWdC;y@mib8*mcjQ0;r8t8(^ zu6%V-SmwPNY6L5B=fRL%BN7TyN{M=NVi%)x#5iHPIm3KwZ^#15c>fiW}FF-jtD{l3iGV-2)?^E zNDzcqbj2~Bvoog3lJ1hKr_X2KkE(dtwhe4%J+U?=zYU{l?#J)`Ap;0ZH@JzKlGwZ@ zT%UWUJM;EE6Sv6C;;Kp)UEX5rB{hp#b_TCoA*5Wz9Yyw0!A+pNH$@L@RGZofNvBY~ z{qJT>D)RNyK8gO-`CR|Mn`aP){-%Woo*vzBYX)@P=mL>oL3H6X5v*~%!cjXg^TA*` z)`CUER1c~7HnFt!cVN7`Ung_U9Qh1%3L&}8=}eg#^@5PBkrtnt!_78#bu0rO^3s9o zQ(*7?ien^(+wD<)I^VewQ0=x0OlL@}tI$%ePvPJNE2bD{Le0^BFtc-5+ZUF8an_tI zi-5vh=O#zNP=uNA*l!5*3$Ri4|dSL>7Msx@^7R^t=&ByjC1^5dy+I2;fW*|bzP0h{CVF)H9$;Pmws3H|)))S?(2moO- z-TLp{yh~L00ae1S?mLwUeP*B7DG%g=#IJI+>i(|M`w zu(5AqXC1mV-t(x$Cxh3{S^9=ry(b7liZ10Ah=TJ7F2^(CWLKwJ99LDMd*VWdGk^>A zFIll%WBXQc^65RNK+wFstyZj4U1fIZSmwh;Zi?ZR_e3#xzVGi zXbH)%eIBulxZTv6^}xIU-dzOZq5Ih%p)OP?0WcP>2 zP1yv=4yd{+D8-Wi`mGBeS7P<(>tD%7RNk{Nm~mo>Ba@eeLg3vLNNv z^8He2L{i;=$g6gdAj`lPhp3sFP5EUTt$stOe(J;=35}3RZy)z~S0cw7ALp?udHt}R zMFCULP+!Tl-9?k?95H@A!KUQA?ziZMr+_}3psK93?J)ws|0X+z_YAlYRiRR4P-B-Y z^Am5kaLIPS(QxLH%7our)43?BDqZAP=T+S8MGry68yoDVw9Xc;hMei`m0ANWy|;IN zMWii%Qo^9{Qd^eahj|W102_k%<9I*1g^a#qi13|)V`_@32ZN*z{aUuR-i%aPC@Qz` zzvvN^8)WnPInuTPz!3Lp1v{-<>gT&ES{ zU#iG-$8_eAe;6If+<>tQ;xyRhK>v6BS8xBT5C8Lx{^usQ_j2|GH*@6T5V*B42zXhZ Lwl%B6xX1nni@+ml diff --git a/examples/index.html b/examples/index.html index 5b9cded..ed61b72 100644 --- a/examples/index.html +++ b/examples/index.html @@ -4,7 +4,8 @@ Editor.md examples - + + + + + \ No newline at end of file diff --git a/tests/js/searchbox.js b/tests/js/searchbox.js new file mode 100644 index 0000000..ff95f56 --- /dev/null +++ b/tests/js/searchbox.js @@ -0,0 +1,674 @@ +/* global CodeMirror */ +/* global define */ + +(function(mod) { + 'use strict'; + + if (typeof exports === 'object' && typeof module === 'object') // CommonJS + mod(require('../../lib/codemirror')); + else if (typeof define === 'function' && define.amd) // AMD + define(['../../lib/codemirror'], mod); + else + mod(CodeMirror); +})(function(CodeMirror) { + 'use strict'; + + var Search; + + CodeMirror.defineOption('searchbox', false, function(cm) { + cm.addKeyMap({ + 'Ctrl-F': function() { + if (!Search) + Search = new SearchBox(cm); + + Search.show(); + }, + + 'Esc': function() { + if (Search && Search.isVisible()) { + Search.hide(); + + if (typeof event !== 'undefined') + event.stopPropagation(); + } + + return false; + }, + + 'Cmd-F': function() { + if (!Search) + Search = new SearchBox(cm); + + Search.show(); + } + }); + }); + + function SearchBox(cm) { + var self = this; + + init(); + + function initElements(el) { + self.searchBox = el.querySelector('.ace_search_form'); + self.replaceBox = el.querySelector('.ace_replace_form'); + self.searchOptions = el.querySelector('.ace_search_options'); + + self.regExpOption = el.querySelector('[action=toggleRegexpMode]'); + self.caseSensitiveOption = el.querySelector('[action=toggleCaseSensitive]'); + self.wholeWordOption = el.querySelector('[action=toggleWholeWords]'); + + self.searchInput = self.searchBox.querySelector('.ace_search_field'); + self.replaceInput = self.replaceBox.querySelector('.ace_search_field'); + } + + function init() { + var el = self.element = addHtml(); + + addStyle(); + + initElements(el); + bindKeys(); + + el.addEventListener('mousedown', function(e) { + setTimeout(function(){ + self.activeInput.focus(); + }, 0); + + e.stopPropagation(); + }); + + el.addEventListener('click', function(e) { + var t = e.target || e.srcElement; + var action = t.getAttribute('action'); + if (action && self[action]) + self[action](); + else if (self.commands[action]) + self.commands[action](); + + e.stopPropagation(); + }); + + self.searchInput.addEventListener('input', function() { + self.$onChange.schedule(20); + }); + + self.searchInput.addEventListener('focus', function() { + self.activeInput = self.searchInput; + }); + + self.replaceInput.addEventListener('focus', function() { + self.activeInput = self.replaceInput; + }); + + self.$onChange = delayedCall(function() { + self.find(false, false); + }); + } + + function bindKeys() { + var sb = self, + obj = { + 'Ctrl-F|Cmd-F|Ctrl-H|Command-Alt-F': function() { + var isReplace = sb.isReplace = !sb.isReplace; + sb.replaceBox.style.display = isReplace ? '' : 'none'; + sb[isReplace ? 'replaceInput' : 'searchInput'].focus(); + }, + 'Ctrl-G|Cmd-G': function() { + sb.findNext(); + }, + 'Ctrl-Shift-G|Cmd-Shift-G': function() { + sb.findPrev(); + }, + 'Esc': function() { + setTimeout(function() { sb.hide();}); + }, + 'Enter': function() { + if (sb.activeInput === sb.replaceInput) + sb.replace(); + sb.findNext(); + }, + 'Shift-Enter': function() { + if (sb.activeInput === sb.replaceInput) + sb.replace(); + sb.findPrev(); + }, + 'Alt-Enter': function() { + if (sb.activeInput === sb.replaceInput) + sb.replaceAll(); + sb.findAll(); + }, + 'Tab': function() { + if (self.activeInput === self.replaceInput) + self.searchInput.focus(); + else + self.replaceInput.focus(); + } + }; + + self.element.addEventListener('keydown', function(event) { + Object.keys(obj).some(function(name) { + var is = key(name, event); + + if (is) { + event.stopPropagation(); + event.preventDefault(); + obj[name](event); + } + + return is; + }); + }); + } + + this.commands = { + toggleRegexpMode: function() { + self.regExpOption.checked = !self.regExpOption.checked; + self.$syncOptions(); + }, + + toggleCaseSensitive: function() { + self.caseSensitiveOption.checked = !self.caseSensitiveOption.checked; + self.$syncOptions(); + }, + + toggleWholeWords: function() { + self.wholeWordOption.checked = !self.wholeWordOption.checked; + self.$syncOptions(); + } + }; + + this.$syncOptions = function() { + setCssClass(this.regExpOption, 'checked', this.regExpOption.checked); + setCssClass(this.wholeWordOption, 'checked', this.wholeWordOption.checked); + setCssClass(this.caseSensitiveOption, 'checked', this.caseSensitiveOption.checked); + + this.find(false, false); + }; + + this.find = function(skipCurrent, backwards) { + var value = this.searchInput.value, + options = { + skipCurrent: skipCurrent, + backwards: backwards, + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }; + + find(value, options, function(searchCursor) { + var current = searchCursor.matches(false, searchCursor.from()); + cm.setSelection(current.from, current.to); + }); + }; + + function find(value, options, callback) { + var done, + noMatch, searchCursor, next, prev, matches, cursor, + position, + o = options, + is = true, + caseSensitive = o.caseSensitive, + regExp = o.regExp, + wholeWord = o.wholeWord; + + if (regExp || wholeWord) { + if (options.wholeWord) + value = '\\b' + value + '\\b'; + + value = RegExp(value); + } + + if (o.backwards) + position = o.skipCurrent ? 'from': 'to'; + else + position = o.skipCurrent ? 'to' : 'from'; + + cursor = cm.getCursor(position); + searchCursor = cm.getSearchCursor(value, cursor, !caseSensitive); + + next = searchCursor.findNext.bind(searchCursor), + prev = searchCursor.findPrevious.bind(searchCursor), + matches = searchCursor.matches.bind(searchCursor); + + if (o.backwards && !prev()) { + is = next(); + + if (is) { + cm.setCursor(cm.doc.size - 1, 0); + find(true, true, callback); + done = true; + } + } else if (!o.backwards && !next()) { + is = prev(); + + if (is) { + cm.setCursor(0, 0); + find(true, false, callback); + done = true; + } + } + + noMatch = !is && self.searchInput.value; + setCssClass(self.searchBox, 'ace_nomatch', noMatch); + + if (!done && is) + callback(searchCursor); + } + + this.findNext = function() { + this.find(true, false); + }; + + this.findPrev = function() { + this.find(true, true); + }; + + this.findAll = function(){ + /* + var range = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + */ + + var value = this.searchInput.value, + range, + noMatch = !range && this.searchInput.value; + + setCssClass(this.searchBox, 'ace_nomatch', noMatch); + + if (cm.showMatchesOnScrollbar) + cm.showMatchesOnScrollbar(value); + + this.hide(); + }; + + this.replace = function() { + if (!cm.getOption('readOnly')) + cm.replaceSelection(this.replaceInput.value, 'start'); + }; + + this.replaceAndFindNext = function() { + if (!cm.getOption('readOnly')) { + this.editor.replace(this.replaceInput.value); + this.findNext(); + } + }; + + this.replaceAll = function() { + var value, + cursor, + from = this.searchInput.value, + to = this.replaceInput.value, + reg = RegExp(from, 'g'); + + if (!cm.getOption('readOnly')) { + cursor = cm.getCursor(); + value = cm.getValue(); + value = value.replace(reg, to); + + cm.setValue(value); + cm.setCursor(cursor); + } + }; + + this.hide = function() { + this.element.style.display = 'none'; + cm.focus(); + }; + + this.isVisible = function() { + var is = this.element.style.display === ''; + + return is; + }; + + this.show = function(value, isReplace) { + this.element.style.display = ''; + this.replaceBox.style.display = isReplace ? '' : 'none'; + + this.isReplace = isReplace; + + if (value) + this.searchInput.value = value; + + this.searchInput.focus(); + this.searchInput.select(); + }; + + this.isFocused = function() { + var el = document.activeElement; + return el === this.searchInput || el === this.replaceInput; + }; + + function addStyle() { + var style = document.createElement('style'), + css = [ + '.ace_search {', + 'background-color: #ddd;', + 'border: 1px solid #cbcbcb;', + 'border-top: 0 none;', + 'max-width: 325px;', + 'overflow: hidden;', + 'margin: 0;', + 'padding: 4px;', + 'padding-right: 6px;', + 'padding-bottom: 0;', + 'position: absolute;', + 'top: 0px;', + 'z-index: 99;', + 'white-space: normal;', + '}', + '.ace_search.left {', + 'border-left: 0 none;', + 'border-radius: 0px 0px 5px 0px;', + 'left: 0;', + '}', + '.ace_search.right {', + 'border-radius: 0px 0px 0px 5px;', + 'border-right: 0 none;', + 'right: 0;', + '}', + '.ace_search_form, .ace_replace_form {', + 'border-radius: 3px;', + 'border: 1px solid #cbcbcb;', + 'float: left;', + 'margin-bottom: 4px;', + 'overflow: hidden;', + '}', + '.ace_search_form.ace_nomatch {', + 'outline: 1px solid red;', + '}', + '.ace_search_field {', + 'background-color: white;', + 'border-right: 1px solid #cbcbcb;', + 'border: 0 none;', + '-webkit-box-sizing: border-box;', + '-moz-box-sizing: border-box;', + 'box-sizing: border-box;', + 'float: left;', + 'height: 22px;', + 'outline: 0;', + 'padding: 0 7px;', + 'width: 214px;', + 'margin: 0;', + '}', + '.ace_searchbtn,', + '.ace_replacebtn {', + 'background: #fff;', + 'border: 0 none;', + 'border-left: 1px solid #dcdcdc;', + 'cursor: pointer;', + 'float: left;', + 'height: 22px;', + 'margin: 0;', + 'padding: 0;', + 'position: relative;', + '}', + '.ace_searchbtn:last-child,', + '.ace_replacebtn:last-child {', + 'border-top-right-radius: 3px;', + 'border-bottom-right-radius: 3px;', + '}', + '.ace_searchbtn:disabled {', + 'background: none;', + 'cursor: default;', + '}', + '.ace_searchbtn {', + 'background-position: 50% 50%;', + 'background-repeat: no-repeat;', + 'width: 27px;', + '}', + '.ace_searchbtn.prev {', + 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); ', + '}', + '.ace_searchbtn.next {', + 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); ', + '}', + '.ace_searchbtn_close {', + 'background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;', + 'border-radius: 50%;', + 'border: 0 none;', + 'color: #656565;', + 'cursor: pointer;', + 'float: right;', + 'font: 16px/16px Arial;', + 'height: 14px;', + 'margin: 5px 1px 9px 5px;', + 'padding: 0;', + 'text-align: center;', + 'width: 14px;', + '}', + '.ace_searchbtn_close:hover {', + 'background-color: #656565;', + 'background-position: 50% 100%;', + 'color: white;', + '}', + '.ace_replacebtn.prev {', + 'width: 54px', + '}', + '.ace_replacebtn.next {', + 'width: 27px', + '}', + '.ace_button {', + 'margin-left: 2px;', + 'cursor: pointer;', + '-webkit-user-select: none;', + '-moz-user-select: none;', + '-o-user-select: none;', + '-ms-user-select: none;', + 'user-select: none;', + 'overflow: hidden;', + 'opacity: 0.7;', + 'border: 1px solid rgba(100,100,100,0.23);', + 'padding: 1px;', + '-moz-box-sizing: border-box;', + 'box-sizing: border-box;', + 'color: black;', + '}', + '.ace_button:hover {', + 'background-color: #eee;', + 'opacity:1;', + '}', + '.ace_button:active {', + 'background-color: #ddd;', + '}', + '.ace_button.checked {', + 'border-color: #3399ff;', + 'opacity:1;', + '}', + '.ace_search_options{', + 'margin-bottom: 3px;', + 'text-align: right;', + '-webkit-user-select: none;', + '-moz-user-select: none;', + '-o-user-select: none;', + '-ms-user-select: none;', + 'user-select: none;', + '}' + ].join(''); + + style.setAttribute('data-name', 'js-searchbox'); + + style.textContent = css; + + document.head.appendChild(style); + } + + function addHtml() { + var elSearch, + el = document.querySelector('.CodeMirror'), + div = document.createElement('div'), + html = [ + '' + ].join(''); + + div.innerHTML = html; + + elSearch = div.firstChild; + + el.parentElement.appendChild(elSearch); + + return elSearch; + } + } + + function setCssClass(el, className, condition) { + var list = el.classList; + + list[condition ? 'add' : 'remove'](className); + } + + function delayedCall(fcn, defaultTimeout) { + var timer, + callback = function() { + timer = null; + fcn(); + }, + + _self = function(timeout) { + if (!timer) + timer = setTimeout(callback, timeout || defaultTimeout); + }; + + _self.delay = function(timeout) { + timer && clearTimeout(timer); + timer = setTimeout(callback, timeout || defaultTimeout); + }; + _self.schedule = _self; + + _self.call = function() { + this.cancel(); + fcn(); + }; + + _self.cancel = function() { + timer && clearTimeout(timer); + timer = null; + }; + + _self.isPending = function() { + return timer; + }; + + return _self; + } + + /* https://github.com/coderaiser/key */ + function key(str, event) { + var right, + KEY = { + BACKSPACE : 8, + TAB : 9, + ENTER : 13, + ESC : 27, + + SPACE : 32, + PAGE_UP : 33, + PAGE_DOWN : 34, + END : 35, + HOME : 36, + UP : 38, + DOWN : 40, + + INSERT : 45, + DELETE : 46, + + INSERT_MAC : 96, + + ASTERISK : 106, + PLUS : 107, + MINUS : 109, + + F1 : 112, + F2 : 113, + F3 : 114, + F4 : 115, + F5 : 116, + F6 : 117, + F7 : 118, + F8 : 119, + F9 : 120, + F10 : 121, + + SLASH : 191, + TRA : 192, /* Typewritten Reverse Apostrophe (`) */ + BACKSLASH : 220 + }; + + keyCheck(str, event); + + right = str.split('|').some(function(combination) { + var wrong; + + wrong = combination.split('-').some(function(key) { + var right; + + switch(key) { + case 'Ctrl': + right = event.ctrlKey; + break; + + case 'Shift': + right = event.shiftKey; + break; + + case 'Alt': + right = event.altKey; + break; + + case 'Cmd': + right = event.metaKey; + break; + + default: + if (key.length === 1) + right = event.keyCode === key.charCodeAt(0); + else + Object.keys(KEY).some(function(name) { + var up = key.toUpperCase(); + + if (up === name) + right = event.keyCode === KEY[name]; + }); + break; + } + + return !right; + }); + + return !wrong; + }); + + return right; + } + + function keyCheck(str, event) { + if (typeof str !== 'string') + throw(Error('str should be string!')); + + if (typeof event !== 'object') + throw(Error('event should be object!')); + } + +}); diff --git a/tests/marked-@at-test.html b/tests/marked-@at-test.html new file mode 100644 index 0000000..be8239d --- /dev/null +++ b/tests/marked-@at-test.html @@ -0,0 +1,221 @@ + + + + Marked @ Test + + + + + + + +
                 ~~@mentions~~, #refs @tylerlong `inline code @tylerlong`, [links](), **formatting**, and tags supported @pandao;
                +list syntax required (any unordered or ordered list supported) @pandao;
                +this is @pandao a complete item @pandao;
                +link [@pandao](https://github.com/pandao "@pandao") @
                +link [@pandao](https://github.com/pandao "@pandao") 
                +this is an incomplete item **@pandao**;
                +*@pandao* this is an incomplete item ___@pandao___;
                +# Github: @pandao
                +## Github: @pandao
                +### Github: @tylerlong
                +#### Github: @tylerlong
                +##### Github: @tylerlong
                +###### Github: @tylerlong
                + 
                +- dafssdfsdaf@chjj dfsdfsdf
                +- dafssdfsdaf@chjj dfsdfsdf     
                +    - dafssdfsdaf@chjj dfsdfsdf
                +    - dafss@pandao dfsdaf@chjj dfsdfsdf
                +- dafssd:  @pandao fsdaf@chjj dfsdfsdf @codemirror  @pandao
                +    + dafssdfsdaf@chjj dfsdfsdf
                +    + dafss@pandaodfsdaf@chjj dfsdfsdf
                +
                +
                +1. @chjj 第一行@pandao fsdaf@chjj dfsdfsdf :fa-save::  @pandao
                +    - dafssdfsdaf@chjj dfsdfsdf
                +    - dafss@pandao dfsdaf@chjj dfsdfsdf
                +2. @chjj 第二行@pandao fsdaf@chjj dfsdfsdf @codemirror  @pandao
                +3. 第三行@pandao fsdaf@chjj dfsdfsdf :fa-save::  @pandao
                +
                +> Blockquotes @pandao
                +
                +> dd@pandao引用文本(Blockquotes @pandao)fdasfad @_pandao fdasfad @xxx454xxx fdasfad @xx_x454xxx454
                +
                +|@pandao First Header  | Second@pandao Header@pandao |
                +| ------------- | ------------- |
                +| Content@pandao Cell  | @pandao Content Cell @pandao|
                +| Con@pandao tent Cell@pandao  | Content@pan-dao Cell dfsdfsdf @pan_dao |
                +
                +dsfdf@pandao fasdfsdfsfddffd@pandao
                +
                +    dfasfasdfasdf:bangbang:
                +
                +This is an H1 @pandao
                +=============
                +
                +This @pandao an H2 @pandao
                +-------------
                +
                + + + + + \ No newline at end of file diff --git a/tests/marked-emoji-test.html b/tests/marked-emoji-test.html new file mode 100644 index 0000000..f54dbca --- /dev/null +++ b/tests/marked-emoji-test.html @@ -0,0 +1,231 @@ + + + + Marked Emoji Test + + + + + + + +
                +
                > Blockquotes
                +dasfsadfasdf:fa-edit: :warning: :smiley:dsafsdfsad\:fdsfdf\:f dfdf:   :fa-save::fa-star:  :fa-truck:
                +**fdfasd:smiley:dsfsdfsfd** ~~fsdfds:smiley:dfsdfsdf :fa-info:~~
                +*dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf*
                +___Emphasis :fa-gear: Italic:smiley:___  __Emphasis:smiley:__
                +# H1 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf
                +## H2 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf
                +### H3 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-save:dsfsdf
                +#### H4 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-save:dsfsdf
                +##### H5 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-save:dsfsdf
                +###### H6 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-star:dsfsdf
                +[:smiley:](http://www.emoji-cheat-sheet.com/ "link + emoji") link + emoji
                +- dafssdfsdaf:smiley:dfsdfsdf
                +- dafssdfsdaf:smiley:dfsdfsdf     
                +    - dafssdfsdaf:smiley:dfsdfsdf
                +    - dafss:fa-truck:dfsdaf:smiley:dfsdfsdf
                +- dafssd:  :fa-truck:fsdaf:smiley:dfsdfsdf :fa-star::  :fa-truck:
                +    + dafssdfsdaf:smiley:dfsdfsdf
                +    + dafss:fa-truck:dfsdaf:smiley:dfsdfsdf
                +
                +
                +1. :smiley:第一行:fa-truck:fsdaf:smiley:dfsdfsdf :fa-save::  :fa-truck:
                +    - dafssdfsdaf:smiley:dfsdfsdf
                +    - dafss:fa-truck:dfsdaf:smiley:dfsdfsdf
                +2. :smiley:第二行:fa-truck:fsdaf:smiley:dfsdfsdf :fa-star::  :fa-truck:
                +3. 第三行:fa-truck:fsdaf:smiley:dfsdfsdf :fa-save::  :fa-truck:
                +
                +> Blockquotes
                +
                +> dd:smiley:引用文本(Blockquotes:smiley:)fdasfad :fa-star:: dfd :fa-truck:
                +
                +|:100: First Header  | Second:smiley: Header:smiley: |
                +| ------------- | ------------- |
                +| Content:fa-truck: Cell  | :smiley:Content Cell :smiley: |
                +| Con:fa-truck:tent Cell:bangbang:  | Content Cell dfsdfsdf :fa-star: :dfdf  :fa-truck: |
                +
                +:fa-heart:fasdfsdfsfddffd:editormd-logo: :editormd-logo: :editormd-logo-4x:
                +
                +    dfasfasdfasdf:bangbang:
                +
                +This is an H1 :editormd-logo-4x:
                +=============
                +
                +This  :fa-save::  :fa-truck:is an H2 :100:
                +-------------
                +
                + + + + + \ No newline at end of file diff --git a/tests/marked-todo-list-test.html b/tests/marked-todo-list-test.html new file mode 100644 index 0000000..1c2ea23 --- /dev/null +++ b/tests/marked-todo-list-test.html @@ -0,0 +1,61 @@ + + + + Marked Emoji Test + + + + + + + + + + + \ No newline at end of file