From a13b7e72acfac47df47a54216f065afa4da3666e Mon Sep 17 00:00:00 2001 From: Pandao Date: Sun, 15 Feb 2015 21:24:22 +0800 Subject: [PATCH] Releases v1.1.0 --- BUGS.md | 13 +- CHANGE.md | 100 +- Gulpfile.js | 2 +- README.md | 20 +- bower.json | 2 +- dist/css/editormd.css | 423 +++- dist/css/editormd.css.map | 8 +- dist/css/editormd.css.min.map | 4 +- dist/css/editormd.min.css | 6 +- dist/css/editormd.preview.css | 28 +- dist/css/editormd.preview.css.map | 8 +- dist/css/editormd.preview.css.min.map | 4 +- dist/css/editormd.preview.min.css | 4 +- dist/fonts/editormd-logo.eot | Bin 0 -> 1320 bytes dist/fonts/editormd-logo.svg | 11 + dist/fonts/editormd-logo.ttf | Bin 0 -> 1156 bytes dist/fonts/editormd-logo.woff | Bin 0 -> 1232 bytes dist/images/logos/editormd-logo-114x114.png | Bin 0 -> 5869 bytes dist/images/logos/editormd-logo-120x120.png | Bin 0 -> 6141 bytes dist/images/logos/editormd-logo-144x144.png | Bin 0 -> 7545 bytes dist/images/logos/editormd-logo-16x16.png | Bin 0 -> 1448 bytes dist/images/logos/editormd-logo-180x180.png | Bin 0 -> 7963 bytes dist/images/logos/editormd-logo-240x240.png | Bin 0 -> 10470 bytes dist/images/logos/editormd-logo-24x24.png | Bin 0 -> 1790 bytes dist/images/logos/editormd-logo-320x320.png | Bin 0 -> 14714 bytes dist/images/logos/editormd-logo-32x32.png | Bin 0 -> 2064 bytes dist/images/logos/editormd-logo-48x48.png | Bin 0 -> 2701 bytes dist/images/logos/editormd-logo-57x57.png | Bin 0 -> 3054 bytes dist/images/logos/editormd-logo-64x64.png | Bin 0 -> 3408 bytes dist/images/logos/editormd-logo-72x72.png | Bin 0 -> 3691 bytes dist/images/logos/editormd-logo-96x96.png | Bin 0 -> 4857 bytes dist/images/logos/vi.png | Bin 0 -> 46203 bytes dist/js/editormd.js | 1900 ++++++++++++++---- dist/js/editormd.min.js | 5 +- 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 + examples/127.0.0.1-8888.url | 2 + examples/css/style.css | 15 + examples/custom-toolbar.html | 140 ++ examples/dynamic-create-editormd.html | 46 + examples/flowchart.html | 19 +- examples/form-get-value.html | 85 + examples/full.html | 159 ++ examples/html-preview-markdown-to-html.html | 24 +- examples/html-tags-decode.html | 57 + examples/image-cross-domain-upload.html | 94 + examples/image-upload.html | 45 + examples/images/1.jpg | Bin 0 -> 3253 bytes examples/images/10.jpg | Bin 0 -> 64854 bytes examples/images/2.jpg | Bin 0 -> 3749 bytes examples/images/3.jpg | Bin 0 -> 34228 bytes examples/images/4.jpg | Bin 0 -> 121969 bytes examples/images/5.jpg | Bin 0 -> 4503 bytes examples/images/6.jpg | Bin 0 -> 104491 bytes examples/images/7.jpg | Bin 0 -> 9753 bytes examples/images/8.jpg | Bin 0 -> 17555 bytes examples/images/9.jpg | Bin 0 -> 37472 bytes examples/index.html | 121 +- examples/js/seajs-main.js | 74 + examples/js/zepto.min.js | 2 + examples/katex.html | 48 +- examples/multi-editormd.html | 54 + examples/multi-languages.html | 89 + examples/onchange.html | 6 +- examples/onfullscreen.html | 6 +- examples/onload.html | 6 +- examples/php/cross-domain-upload.php | 54 + examples/php/editormd.uploader.class.php | 327 ++++ examples/php/post.php | 13 + examples/php/upload.php | 46 + examples/php/upload_callback.php | 39 + examples/readonly.html | 54 + examples/sequence-diagram.html | 22 +- examples/set-get-replace-selection.html | 107 ++ examples/simple.html | 99 +- examples/test.md | 118 +- examples/toc.html | 9 +- examples/use-requirejs.html | 24 +- examples/use-seajs.html | 24 +- examples/use-zepto.html | 96 + package.json | 4 +- src/js/editormd.js | 1914 +++++++++++++++---- src/js/languages/en.js | 110 ++ src/js/languages/zh-tw.js | 110 ++ src/scss/editormd.codemirror.scss | 10 +- src/scss/editormd.dialog.scss | 144 +- src/scss/editormd.form.scss | 97 + src/scss/editormd.menu.scss | 23 +- src/scss/editormd.preview.scss | 81 +- src/scss/editormd.scss | 159 +- src/scss/lib/functions.scss | 12 +- src/scss/lib/variables.scss | 9 +- 94 files changed, 6415 insertions(+), 1166 deletions(-) create mode 100644 dist/fonts/editormd-logo.eot create mode 100644 dist/fonts/editormd-logo.svg create mode 100644 dist/fonts/editormd-logo.ttf create mode 100644 dist/fonts/editormd-logo.woff create mode 100644 dist/images/logos/editormd-logo-114x114.png create mode 100644 dist/images/logos/editormd-logo-120x120.png create mode 100644 dist/images/logos/editormd-logo-144x144.png create mode 100644 dist/images/logos/editormd-logo-16x16.png create mode 100644 dist/images/logos/editormd-logo-180x180.png create mode 100644 dist/images/logos/editormd-logo-240x240.png create mode 100644 dist/images/logos/editormd-logo-24x24.png create mode 100644 dist/images/logos/editormd-logo-320x320.png create mode 100644 dist/images/logos/editormd-logo-32x32.png create mode 100644 dist/images/logos/editormd-logo-48x48.png create mode 100644 dist/images/logos/editormd-logo-57x57.png create mode 100644 dist/images/logos/editormd-logo-64x64.png create mode 100644 dist/images/logos/editormd-logo-72x72.png create mode 100644 dist/images/logos/editormd-logo-96x96.png create mode 100644 dist/images/logos/vi.png create mode 100644 dist/js/languages/en.js create mode 100644 dist/js/languages/en.min.js create mode 100644 dist/js/languages/zh-tw.js create mode 100644 dist/js/languages/zh-tw.min.js create mode 100644 examples/127.0.0.1-8888.url create mode 100644 examples/custom-toolbar.html create mode 100644 examples/dynamic-create-editormd.html create mode 100644 examples/form-get-value.html create mode 100644 examples/full.html create mode 100644 examples/html-tags-decode.html create mode 100644 examples/image-cross-domain-upload.html create mode 100644 examples/image-upload.html create mode 100644 examples/images/1.jpg create mode 100644 examples/images/10.jpg create mode 100644 examples/images/2.jpg create mode 100644 examples/images/3.jpg create mode 100644 examples/images/4.jpg create mode 100644 examples/images/5.jpg create mode 100644 examples/images/6.jpg create mode 100644 examples/images/7.jpg create mode 100644 examples/images/8.jpg create mode 100644 examples/images/9.jpg create mode 100644 examples/js/seajs-main.js create mode 100644 examples/js/zepto.min.js create mode 100644 examples/multi-editormd.html create mode 100644 examples/multi-languages.html create mode 100644 examples/php/cross-domain-upload.php create mode 100644 examples/php/editormd.uploader.class.php create mode 100644 examples/php/post.php create mode 100644 examples/php/upload.php create mode 100644 examples/php/upload_callback.php create mode 100644 examples/readonly.html create mode 100644 examples/set-get-replace-selection.html create mode 100644 examples/use-zepto.html create mode 100644 src/js/languages/en.js create mode 100644 src/js/languages/zh-tw.js create mode 100644 src/scss/editormd.form.scss diff --git a/BUGS.md b/BUGS.md index b00ed62..34e7b48 100644 --- a/BUGS.md +++ b/BUGS.md @@ -4,14 +4,19 @@ ####IE8 -- ~~不能加载~~ -- flowChart(流程图)、sequenceDiagram(序列图)不支持IE8 +- ~~不能加载;~~ +- flowChart(流程图)、sequenceDiagram(序列图)不支持IE8; +- ~~不支持Markdown转HTML页面解析预览;~~ + +####IE8 & IE9 & IE10 + +- KaTeX会出现解析错误,但不影响程序运行; ####Sea.js -- Raphael.js无法加载 +- ~~Raphael.js无法加载;~~ ####Require.js -- CodeMirror编辑器的代码无法高亮 +- CodeMirror编辑器的代码无法高亮; diff --git a/CHANGE.md b/CHANGE.md index 5369838..fba2c29 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -2,7 +2,7 @@ #####v1.0.0 beta -基本功能完成; +预览版:基本功能完成; #####v1.0.0 releases @@ -11,6 +11,7 @@ 主要更新: - 新建分支 `mathjax-version`,但不打算继续对此分支进行开发; + - 移除MathJax,改用KaTeX[#2](https://github.com/pandao/editor.md/issues/2),解析和预览响应速度大幅度提高[#3](https://github.com/pandao/editor.md/issues/3); - 移除 `mathjax` 配置项; - 移除 `mathjaxURL` 属性; @@ -21,10 +22,105 @@ - 新增 `katexURL` 属性; - 新增 `loadKaTeX` 方法; - 新增KaTeX的示例; + - `setCodeEditor()`方法更名为`setCodeMirror()`; + - 合并CodeMirror使用到的多个JS模块文件,大幅减少HTTP请求,加快下载速度; - 新增合并后的两个模块文件:`./lib/codemirror/modes.min.js`、`./lib/codemirror/addons.min.js`; - `Gulpfile.js` 新增合并CodeMirror模块文件的任务方法`codemirror-mode`和`codemirror-addon`; - 另外在使用Require.js时,因为CodeMirror的严格模块依赖的限制,不能使用上述合并的模块文件,仍然采用动态加载多个模块文件; + - 更新 `README.md` 等相关文档和示例; -- 解决Sea.js环境下Raphael.js无法运行导致不支持流程图和时序图的问题,即必须先加载Raphael.js,后加载Sea.js; \ No newline at end of file + +- 解决Sea.js环境下Raphael.js无法运行导致不支持流程图和时序图的问题,即必须先加载Raphael.js,后加载Sea.js; + +#####v1.1.0 + +主要更新: + +- 设计并更换了Logo; +- 新增添加图片、链接、锚点链接、代码块、预格式文本等操作弹出对话框层及示例; +- 新增支持图片(跨域)上传; +- 改用`"); + markdownTextarea = this.markdownTextarea = editor.children("textarea"); + } - var infoDialogHTML = [ - "
", - "", - "
", - "

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

", - "

" + editormd.description + "

", - "

Home page: " + editormd.homePage + "

", - "

License: MIT

", - "
", - "
" - ].join("\n"); + markdownTextarea.addClass(classNames.textarea.markdown).attr("name", id + "-markdown-doc").attr("placeholder", settings.placeholder); var appendElements = [ - '
    ', - '', - '', - '
    ', - "
    " + (!settings.readOnly) ? "" : "", + ( (settings.saveHTMLToTextarea) ? "" : "" ), + "
    ", + "
    ", + "
    " ].join("\n"); - editor.append(infoDialogHTML).append(appendElements); + editor.append(appendElements).addClass(classPrefix + "vertical"); + + if (settings.markdown !== "") { + markdownTextarea.val(settings.markdown); + } + + this.htmlTextarea = editor.find("." + classNames.textarea.html); this.preview = editor.find("." + classPrefix + "preview"); - this.toolbar = editor.find("." + classPrefix + "toolbar"); this.previewContainer = this.preview.children("." + classPrefix + "preview-container"); - this.infoDialog = editor.find("." + classPrefix + "dialog-info"); this.toolbarIconHandlers = {}; - editor.addClass(classPrefix + "vertical"); - if (!settings.inRequirejs) - { + { this.loadQueues(); } else - { - _this.setCodeMirror(); - _this.setToolbar(); - _this.toolbarHandler(); + { + _this.setCodeMirror(); + _this.setToolbar(); _this.setMarked().loadedDisplay(); } @@ -250,6 +326,13 @@ var loadPath = settings.path; var loadFlowChartOrSequenceDiagram = function() { + + if (editormd.isIE8) + { + _this.setMarked().loadedDisplay(); + + return ; + } if (settings.flowChart || settings.sequenceDiagram) { @@ -300,9 +383,8 @@ editormd.loadScript(loadPath + "codemirror/addons.min", function() { - _this.setCodeMirror(); - _this.setToolbar(); - _this.toolbarHandler(); + _this.setCodeMirror(); + _this.setToolbar(); editormd.loadScript(loadPath + "marked.min", function() { @@ -315,7 +397,7 @@ }); } else - { + { loadFlowChartOrSequenceDiagram(); } }); @@ -335,32 +417,36 @@ */ setCodeMirror : function() { - var settings = this.settings; - + var settings = this.settings; var codeMirrorConfig = { - mode: this.settings.mode, - theme: "default", - tabSize: 4, - dragDrop: false, - autofocus: true, - indentUnit : 4, - lineNumbers: true, - lineWrapping: true, - matchBrackets: true, - indentWithTabs: true, - styleActiveLine: true, - styleSelectedText: true, - autoCloseBrackets: true, - showTrailingSpace: true, - highlightSelectionMatches: { + mode : settings.mode, + theme : "default", + tabSize : 4, + dragDrop : false, + autofocus : true, + readOnly : (settings.readOnly) ? "nocursor" : false, + indentUnit : 4, + lineNumbers : settings.lineNumbers, + lineWrapping : true, + matchBrackets : true, + indentWithTabs : true, + styleActiveLine : settings.styleActiveLine, + styleSelectedText : true, + autoCloseBrackets : true, + showTrailingSpace : true, + highlightSelectionMatches : { showToken: /\w/ } }; - this.codeEditor = editormd.$CodeMirror.fromTextArea(this.editor.find("." + this.classNames.textarea.markdown)[0], codeMirrorConfig); - + this.codeEditor = editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0], codeMirrorConfig); + this.codeMirror = this.editor.find(".CodeMirror"); - this.codeMirror.css("font-size", this.settings.fontSize); + + this.codeMirror.css({ + fontSize : this.settings.fontSize, + width : (!settings.watch) ? "100%" : "50%" + }); return this; }, @@ -371,8 +457,10 @@ */ showToolbar : function() { + var settings = this.settings; + if(settings.readOnly) return ; - this.settings.toolbar = true; + settings.toolbar = true; this.toolbar.show(); this.resize(); @@ -384,9 +472,10 @@ * @returns {editormd} 返回editormd的实例对象 */ - hideToolbar : function() { + hideToolbar : function() { + var settings = this.settings; - this.settings.toolbar = false; + settings.toolbar = false; this.toolbar.hide(); this.resize(); @@ -399,65 +488,711 @@ */ setToolbar : function() { - var settings = this.settings; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; + var settings = this.settings; + + if(settings.readOnly) return ; + + var editor = this.editor; + var preview = this.preview; + var classPrefix = this.classPrefix; + + editor.append('
      '); - if (!settings.toolbar) { + var toolbar = this.toolbar = editor.find("." + classPrefix + "toolbar"); + + if (!settings.toolbar) + { toolbar.hide(); + return ; - } else { + } + else + { toolbar.show(); } - var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; + var icons = settings.toolbarIcons(); + var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; - for (var i = 0, len = settings.toolbarIcons.length; i < len; i++) + for (var i = 0, len = icons.length; i < len; i++) { - var name = settings.toolbarIcons[i]; + var name = icons[i]; if (name !== "|") { var isHeader = (/h(\d)/.test(name)); + var index = name; + + if (name === "watch" && !settings.watch) { + index = "unwatch"; + } - menu += "
    • "+((isHeader) ? name : "")+"
    • "; + 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 += "
    • " + + ""+((isHeader) ? name : ( (iconClass === "") ? iconTexts : "") ) + "
    • "; } else { - menu += "
    • |
    • "; + menu += "
    • |
    • "; } } - toolbarMenu.append(menu); + toolbarMenu.html(menu); + + this.setToolbarHandler(); return this; - }, + }, + + /** + * 工具栏图标事件处理对象序列 + * @param {String} name 要获取的事件处理器名称 + * @returns {Object} 返回处理对象序列 + */ + + getToolbarHandles : function(name) { + var _this = this; + var settings = this.settings; + var lang = settings.lang; + var editor = this.editor; + var codeEditor = this.codeEditor; + var cursor = codeEditor.getCursor(); + var selection = codeEditor.getSelection(); + var classPrefix = this.classPrefix; + + var dialogLockScreen = function() { + if (settings.dialogLockScreen) { + $("html,body").css("overflow", "hidden"); + } + }; + + var dialogShowMask = function(dialog) { + dialog.css({ + top : ($(window).height() - dialog.height()) / 2 + "px", + left : ($(window).width() - dialog.width()) / 2 + "px" + }); + + if (settings.dialogShowMask) { + editor.find("." + classPrefix + "mask").css("z-index", parseInt(dialog.css("z-index")) - 1).show(); + } + }; + + var toolbarHandlers = this.toolbarHandlers = { + undo : function() { + codeEditor.undo(); + }, + redo : function() { + codeEditor.redo(); + }, + bold : function() { + + codeEditor.replaceSelection("**" + selection + "**"); + + if(selection === "") { + codeEditor.setCursor(cursor.line, cursor.ch + 2); + } + }, + del : function() { + + codeEditor.replaceSelection("~~" + selection + "~~"); + + if(selection === "") { + codeEditor.setCursor(cursor.line, cursor.ch + 2); + } + }, + + italic : function() { + codeEditor.replaceSelection("*" + selection + "*"); + + if(selection === "") { + codeEditor.setCursor(cursor.line, cursor.ch + 1); + } + }, + + quote : function() { + codeEditor.replaceSelection((selection === "") ? ["> " + selection, ""].join("\n") : "> " + selection); + codeEditor.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); + }, + + h1 : function() { + codeEditor.replaceSelection("#" + selection); + }, + + h2 : function() { + codeEditor.replaceSelection("##" + selection); + }, + + h3 : function() { + codeEditor.replaceSelection("###" + selection); + }, + + h4 : function() { + codeEditor.replaceSelection("####" + selection); + }, + + h5 : function() { + codeEditor.replaceSelection("#####" + selection); + }, + + h6 : function() { + codeEditor.replaceSelection("######" + selection); + }, + + "list-ul" : function() { + + if (selection === "") + { + codeEditor.replaceSelection("- " + selection); + } + else + { + var selectionText = selection.split("\n"); + + for (var i = 0, len = selectionText.length; i < len; i++) + { + selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; + } + + codeEditor.replaceSelection(selectionText.join("\n")); + } + }, + + "list-ol" : function() { + + if(selection === "") + { + codeEditor.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]; + } + + codeEditor.replaceSelection(selectionText.join("\n")); + } + }, + + hr : function() { + codeEditor.replaceSelection("------------"); + }, + + link : function() { + 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; + } + + codeEditor.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() { + + 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; + } + + codeEditor.replaceSelection("[" + title + "][" + name + "]\n[" + name + "]: " + url + ""); + + if (selection === "") { + codeEditor.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() { + 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 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://") + { + codeEditor.replaceSelection("![" + alt + "](" + url + " \"" + alt + "\")"); + } + else + { + codeEditor.replaceSelection("[![" + alt + "](" + url + " \"" + alt + "\")](" + link + " \"" + alt + "\")"); + } + + if (alt === "") { + codeEditor.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; + }] + } + }); + } + + 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() { + + codeEditor.replaceSelection("`" + selection + "`"); + + if (selection === "") { + codeEditor.setCursor(cursor.line, cursor.ch + 1); + } + + }, + + "code-block-tab" : function() { + var tabCodeBlockDialogName = classPrefix + "dialog-tab-code-block", tabCodeBlockDialog; + + if (editor.find("." + tabCodeBlockDialogName).length > 0) + { + tabCodeBlockDialog = editor.find("." + tabCodeBlockDialogName); + tabCodeBlockDialog.find("textarea").val(""); + + 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]; + } + + codeEditor.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() { + + 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(""); + + 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; + + codeEditor.replaceSelection(["```" + langName, codeTexts, "```"].join("\n")); + + if (langName === "") { + codeEditor.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() { + var date = new Date(); + var langName = settings.lang.name; + codeEditor.replaceSelection(editormd.dateFormat() + " " + editormd.dateFormat((langName === "zh-cn" || langName === "zh-tw") ? "cn-week-day" : "week-day")); + }, + + 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 && typeof toolbarIconHandlers[name] !== "undefined") ? toolbarHandlers[name] : toolbarHandlers; + }, /** * 工具栏图标事件处理器 * @returns {editormd} 返回editormd的实例对象 */ - toolbarHandler : function() { - var settings = this.settings; + setToolbarHandler : function() { + var _this = this; + var settings = this.settings; - if (!settings.toolbar) { + if (!settings.toolbar || settings.readOnly) { return ; - } + } - var _this = this; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var codeEditor = this.codeEditor; - var codeMirror = this.codeMirror; - var previewContainer = this.previewContainer; - var toolbarIcons = this.toolbarIcons = toolbar.find("." + this.classPrefix + "menu .fa"); + 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); + var icon = $(this).children(".fa"); var name = icon.attr("name"); var cursor = codeEditor.getCursor(); var selection = codeEditor.getSelection(); @@ -465,196 +1200,306 @@ if (name === "") { return ; } + + _this.activeIcon = icon; - //console.log("toolbarIcons.click =>", name); - - var toolbarIconHandlers = _this.toolbarIconHandlers = { - undo : function() { - codeEditor.undo(); - }, - redo : function() { - codeEditor.redo(); - }, - bold : function() { - - codeEditor.replaceSelection("**" + selection + "**"); + if (typeof toolbarIconHandlers[name] !== "undefined") + { + toolbarIconHandlers[name](); + } + 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(); + } - if(selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 2); - } - }, - del : function() { + return false; - codeEditor.replaceSelection("~~" + selection + "~~"); + }); - if(selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 2); - } - }, + 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 + }; - italic : function() { - codeEditor.replaceSelection("*" + selection + "*"); + options = $.extend(true, defaults, options); - if(selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 1); - } - }, + 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 = "
      "; - quote : function() { - codeEditor.replaceSelection((selection === "") ? ["> " + selection, ""].join("\n") : "> " + selection); - codeEditor.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); - }, + if (options.title !== "") + { + html += "
      "; + html += "" + options.title + ""; + html += "
      "; + } - h1 : function() { - codeEditor.replaceSelection("#" + selection); - }, + if (options.closed) + { + html += ""; + } - h2 : function() { - codeEditor.replaceSelection("##" + selection); - }, + html += "
      " + options.content; - h3 : function() { - codeEditor.replaceSelection("###" + selection); - }, + if (options.footer || typeof options.footer === "string") + { + html += "
      " + ( (typeof options.footer === "boolean") ? "" : options.footer) + "
      "; + } - h4 : function() { - codeEditor.replaceSelection("####" + selection); - }, + html += "
      "; - h5 : function() { - codeEditor.replaceSelection("#####" + selection); - }, + html += "
      "; + html += "
      "; + html += "
      "; - h6 : function() { - codeEditor.replaceSelection("######" + selection); - }, + editor.append(html); - "list-ul" : function() { + var dialog = editor.find("." + dialogName); + + dialog.lockScreen = function(lock) { + if (options.lockScreen) + { + $("html,body").css("overflow", (lock) ? "hidden" : ""); + } + + return dialog; + }; - if (selection === "") - { - codeEditor.replaceSelection("- " + selection); - } - else - { - var selectionText = selection.split("\n"); + dialog.showMask = function() { + if (options.mask) + { + editor.find("." + classPrefix + "mask").css(options.maskStyle).css("z-index", editormd.dialogZindex - 1).show(); + } + return dialog; + }; - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; - } + dialog.hideMask = function() { + if (options.mask) + { + editor.find("." + classPrefix + "mask").hide(); + } + + return dialog; + }; - codeEditor.replaceSelection(selectionText.join("\n")); - } - }, + dialog.loading = function(show) { + var loading = dialog.find("." + classPrefix + "dialog-mask"); + loading[(show) ? "show" : "hide"](); + + return dialog; + }; + + dialog.lockScreen(true).showMask(); - "list-ol" : function() { + 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 + }); - if(selection === "") - { - codeEditor.replaceSelection("1. " + selection); - } - else - { - var selectionText = selection.split("\n"); + var dialogPosition = function(){ + dialog.css({ + top : ($(window).height() - dialog.height()) / 2 + "px", + left : ($(window).width() - dialog.width()) / 2 + "px" + }); + }; - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : (i+1) + ". " + selectionText[i]; - } + dialogPosition(); - codeEditor.replaceSelection(selectionText.join("\n")); - } - }, + $(window).resize(dialogPosition); - hr : function() { - codeEditor.replaceSelection("------------"); - }, + dialog.children("." + classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { + dialog.hide().lockScreen(false).hideMask(); + }); - link : function() { - codeEditor.replaceSelection("[" + selection + "](" + selection + " \""+selection+"\")"); - }, + if (typeof options.buttons == "object") + { + var footer = dialog.footer = dialog.find("." + classPrefix + "dialog-footer"); - picture : function() { - codeEditor.replaceSelection("![" + selection + "](" + selection + " \""+selection+"\")"); - }, + for (var key in options.buttons) + { + var btn = options.buttons[key]; + var btnClassName = classPrefix + key + "-btn"; - code : function() { + footer.append(""); + btn[1] = $.proxy(btn[1], dialog); + footer.children("." + btnClassName).bind(mouseOrTouch("click", "touchend"), btn[1]); + } + } - codeEditor.replaceSelection("`" + selection + "`"); + if (options.title !== "" && options.drag) + { + var posX, posY; + var dialogHeader = dialog.children("." + classPrefix + "dialog-header"); - if (selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 1); - } + 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); - "code-block-tab" : function() { - codeEditor.replaceSelection(" " + selection); - }, + document.onmousemove = moveAction; + }); - "code-block" : function() { + var userCanSelect = function (obj) { + obj.removeClass(classPrefix + "user-unselect").off("selectstart"); + } - codeEditor.replaceSelection(["```", selection, "```"].join("\n")); + var userUnselect = function (obj) { + obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) { // selectstart for IE + return false; + }); + } - if (selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 3); - } + var moveAction = function (e) { + e = e || window.event; //IE - }, + var left, top, nowLeft = parseInt(dialog[0].style.left), nowTop = parseInt(dialog[0].style.top); - datetime : function() { - var date = new Date(); - codeEditor.replaceSelection(editormd.dateFormat() + " " + editormd.dateFormat("cn-week-day")); - }, - - watch : function() { - if (_this.settings.watch) - { - _this.unwatch(); - } - else - { - _this.watch(); + 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; + } - event.preventDefault(); + if( nowTop >= 0 ) { + top = e.clientY - posY; + } else { + top = 0; + document.onmousemove = null; + } - return false; - }, - preview : function() { - - _this.previewing(); - event.preventDefault(); - + document.onselectstart = function() { return false; - }, + }; - fullscreen : function() { - - _this.fullscreen(); - event.preventDefault(); + userUnselect($("body")); + userUnselect(dialog); + dialog[0].style.left = left + "px"; + dialog[0].style.top = top + "px"; + } - return false; - }, + document.onmouseup = function() { + userCanSelect($("body")); + userCanSelect(dialog); - info : function() { - _this.showInfoDialog(); - event.preventDefault(); + document.onselectstart = null; + document.onmousemove = null; + }; - return false; - } + 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); }; - toolbarIconHandlers[name](); + dialogHeader.touchDraggable(); + } - codeEditor.focus(); - event.preventDefault(); + editormd.dialogZindex += 2; - return false; + return dialog; + }, + + /** + * 创建关于Editor.md的对话框 + * @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.find("." + classPrefix + "dialog-info"); + + infoDialog.find("." + classPrefix + "dialog-close").bind(editormd.mouseOrTouch("click", "touchend"), function() { + _this.hideInfoDialog(); }); + + infoDialog.css("border", (editormd.isIE8) ? "1px solid #ddd" : ""); return this; }, @@ -667,7 +1512,29 @@ showInfoDialog : function() { $("html,body").css("overflow-x", "hidden"); - this.editor.find("." + this.classPrefix + "dialog-info").fadeIn(); + + var _this = this; + var editor = this.editor; + var classPrefix = this.classPrefix; + var infoDialog = this.infoDialog = editor.find("." + classPrefix + "dialog-info"); + + if (infoDialog.length < 1) + { + this.createInfoDialog(); + } + + infoDialog.show(); + + 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; }, @@ -679,7 +1546,7 @@ hideInfoDialog : function() { $("html,body").css("overflow-x", ""); - this.editor.find("." + this.classPrefix + "dialog-info").fadeOut(); + this.infoDialog.hide(); return this; }, @@ -697,9 +1564,9 @@ renderer : editormd.markedRenderer(markdownToC), gfm : true, tables : true, - breaks : false, + breaks : true, pedantic : false, - sanitize : true, + sanitize : (this.settings.htmlDecode) ? false : true, // 关闭忽略HTML标签,即开启识别HTML标签,默认为false smartLists : true, smartypants : true }); @@ -707,6 +1574,36 @@ return this; }, + + /** + * 编辑器界面重建,用于动态语言包或模块加载等 + * @returns {editormd} 返回editormd的实例对象 + */ + + recreateEditor : function() { + var _this = this; + var editor = this.editor; + var settings = this.settings; + var toolbarIcons = settings.toolbarIcons(); + + if (typeof this.infoDialog !== "undefined") { + this.infoDialog.remove(); + } + + if (typeof toolbarIcons["info"] !== "undefined") { + createInfoDialog(); + } + + if (!settings.readOnly) { + this.getToolbarHandles(); + this.setToolbar(); + } + + this.resize(); + + return this; + }, + /** * 加载队列完成之后的显示处理 * @returns {editormd} 返回editormd的实例对象 @@ -719,34 +1616,44 @@ var _this = this; var editor = this.editor; var preview = this.preview; - var toolbar = this.toolbar; var settings = this.settings; var codeEditor = this.codeEditor; var codeMirror = this.codeMirror; var previewContainer = this.previewContainer; var mouseOrTouch = editormd.mouseOrTouch; - var htmlTextarea = this.htmlTextarea = editor.find("."+this.classNames.textarea.html); - var markdownTextarea = this.markdownTextarea = editor.find("."+this.classNames.textarea.markdown); editor.css("background", "none"); this.saveToTextareas(); - preview.show(); - - if (settings.previewCodeHighlight) - { - previewContainer.find("pre").addClass("prettyprint linenums"); - prettyPrint(); + if(settings.watch) { + preview.show(); } - if (settings.flowChart) { - previewContainer.find(".flowchart").flowChart(); - } + var codeHighlight = function() { + if (settings.previewCodeHighlight) + { + previewContainer.find("pre").addClass("prettyprint linenums"); + prettyPrint(); + } + }; - if (settings.sequenceDiagram) { - previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } + var flowChartAndSequenceDiagramHandle = function() { + + if (editormd.isIE8) return ; + + if (settings.flowChart) { + previewContainer.find(".flowchart").flowChart(); + } + + if (settings.sequenceDiagram) { + previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); + } + }; + + codeHighlight(); + + flowChartAndSequenceDiagramHandle(); var katexHandle = function() { previewContainer.find("." + editormd.classNames.tex).each(function(){ @@ -767,26 +1674,19 @@ } } - editor.data({ - oldWidth : editor.outerWidth(), - oldHeight : editor.outerHeight() - }); + editor.data("oldWidth", editor.width()).data("oldHeight", editor.height()); // 为了兼容Zepto + + this.resize(); - this.resize(); - $(window).resize(function(){ _this.resize(); }); - $.proxy(this.settings.onload, this)(); - - editor.find("." + this.classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { - _this.hideInfoDialog(); - }); + $.proxy(settings.onload, this)(); var codeEditorBindScroll = function() { codeMirror.find(".CodeMirror-scroll").bind(mouseOrTouch("scroll", "touchmove"), function() { - var height = $(this).outerHeight(); + var height = $(this).height(); var scrollTop = $(this).scrollTop(); var percent = (scrollTop / $(this)[0].scrollHeight); @@ -811,7 +1711,7 @@ var previewBindScroll = function() { preview.bind(mouseOrTouch("scroll", "touchmove"), function() { - var height = $(this).outerHeight(); + var height = $(this).height(); var scrollTop = $(this).scrollTop(); var percent = (scrollTop / $(this)[0].scrollHeight); var codeView = codeMirror.find(".CodeMirror-scroll"); @@ -834,9 +1734,20 @@ var previewUnbindScroll = function() { preview.unbind(mouseOrTouch("scroll", "touchmove")); }; + + codeMirror.bind({ + mouseover : codeEditorBindScroll, + mouseout : codeEditorUnbindScroll, + touchstart : codeEditorBindScroll, + touchend : codeEditorUnbindScroll + }); - codeMirror.hover(codeEditorBindScroll, codeEditorUnbindScroll).bind("touchstart", codeEditorBindScroll).bind("touchend", codeEditorUnbindScroll); - preview.hover(previewBindScroll, previewUnbindScroll).bind("touchstart", previewBindScroll).bind("touchend", previewUnbindScroll); + preview.bind({ + mouseover : previewBindScroll, + mouseout : previewUnbindScroll, + touchstart : previewBindScroll, + touchend : previewUnbindScroll + }); codeEditor.on("change", function(cm, changeObj) { @@ -845,21 +1756,12 @@ } _this.saveToTextareas(); - - if (settings.previewCodeHighlight) { - preview.find("pre").addClass("prettyprint linenums"); - prettyPrint(); - } - - if (settings.flowChart) { - previewContainer.find(".flowchart").flowChart(); - } - if (settings.sequenceDiagram) { - previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } + codeHighlight(); + + flowChartAndSequenceDiagramHandle(); - if (settings.tex) { + if (settings.tex) { katexHandle(); } @@ -877,10 +1779,7 @@ width : function(width) { - this.editor.css({ - width : (typeof width === "number") ? width + "px" : width - }); - + this.editor.css("width", (typeof width === "number") ? width + "px" : width); this.resize(); return this; @@ -894,10 +1793,7 @@ height : function(height) { - this.editor.css({ - height : (typeof height === "number") ? height + "px" : height - }); - + this.editor.css("height", (typeof height === "number") ? height + "px" : height); this.resize(); return this; @@ -919,7 +1815,6 @@ var preview = this.preview; var toolbar = this.toolbar; var settings = this.settings; - var infoDialog = this.infoDialog; var codeEditor = this.codeEditor; var codeMirror = this.codeMirror; @@ -930,32 +1825,29 @@ height : (typeof height === "number") ? height + "px" : height }); } - - infoDialog.css({ - top : (editor.height() - infoDialog.height()) / 2, - left : (editor.width() - infoDialog.width()) / 2 - }); - if (settings.toolbar) { - codeMirror.css("margin-top", toolbar.outerHeight()).outerHeight(editor.height() - toolbar.outerHeight()); + if (settings.toolbar && !settings.readOnly) { + codeMirror.css("margin-top", toolbar.height() + 1).height(editor.height() - toolbar.height()); } else { - codeMirror.css("margin-top", 0).outerHeight(editor.height()); + codeMirror.css("margin-top", 0).height(editor.height()); } - if(this.settings.watch) + codeMirror.find(".CodeMirror-gutters").height(codeMirror.height()); + + if(settings.watch) { - codeMirror.outerWidth(editor.width() / 2); - preview.outerWidth(editor.width() / 2); + codeMirror.width(editor.width() / 2); + preview.width(editor.width() / 2); - if (settings.toolbar) { - preview.css("top", toolbar.outerHeight()).outerHeight(editor.height() - toolbar.outerHeight()); + if (settings.toolbar && !settings.readOnly) { + preview.css("top", toolbar.height()).height(editor.height() - toolbar.height()); } else { - preview.css("top", 0).outerHeight(editor.height()); + preview.css("top", 0).height(editor.height()); } } else { - codeMirror.outerWidth(editor.width()); + codeMirror.width(editor.width()); preview.hide(); } @@ -977,18 +1869,105 @@ var markdownToC = this.markdownToC = []; var newMarkdownDoc = editormd.$marked(codeEditor.getValue(), {renderer : editormd.markedRenderer(markdownToC)}); - this.markdownTextarea.html(codeEditor.getValue()); - this.htmlTextarea.html(newMarkdownDoc); + this.markdownTextarea.val(codeEditor.getValue()); - previewContainer.html(newMarkdownDoc); + if (settings.saveHTMLToTextarea) { + this.htmlTextarea.html(newMarkdownDoc); + } + + if(settings.watch) + { + previewContainer.html(newMarkdownDoc); - if (settings.toc) { - editormd.markdownToCRenderer(markdownToC, previewContainer, settings.tocStartLevel); + if (settings.toc) { + editormd.markdownToCRenderer(markdownToC, previewContainer, settings.tocStartLevel); + } } return this; }, + /** + * 聚焦光标位置 + * @returns {editormd} 返回editormd的实例对象 + */ + + focus : function() { + this.codeEditor.focus(); + + return this; + }, + + /** + * 设置光标的位置 + * @param {Object} cursor 要设置的光标位置键值对象,例:{line:1, ch:0} + * @returns {editormd} 返回editormd的实例对象 + */ + + setCursor : function(cursor) { + this.codeEditor.setCursor(cursor); + + return this; + }, + + /** + * 获取当前光标的位置 + * @returns {Cursor} 返回一个光标Cursor对象 + */ + + getCursor : function() { + return this.codeEditor.getCursor(); + }, + + /** + * 设置光标选中的范围 + * @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; + }, + + /** + * 获取光标选中的文本 + * @returns {String} 返回选中文本的字符串形式 + */ + + getSelection : function() { + return this.codeEditor.getSelection(); + }, + + /** + * 替换当前光标选中的文本或在当前光标处插入新字符 + * @param {String} value 要插入的字符值 + * @returns {editormd} 返回editormd的实例对象 + */ + + replaceSelection : function(value) { + this.codeEditor.replaceSelection(value); + + return this; + }, + + /** + * 在当前光标处插入新字符 + * + * 同replaceSelection()方法 + * @param {String} value 要插入的字符值 + * @returns {editormd} 返回editormd的实例对象 + */ + + insertValue : function(value) { + this.replaceSelection(value); + + return this; + }, + /** * 设置和传入编辑器的markdown源文档 * @param {String} md 要传入的markdown源文档 @@ -1012,12 +1991,56 @@ }, /** - * 获取解析后的HTML源码 + * 清空编辑器 * @returns {editormd} 返回editormd的实例对象 */ + clear : function() { + this.codeEditor.setValue(""); + this.saveToTextareas(); + + return this; + }, + + /** + * 获取解析后存放在Textarea的HTML源码 + * @returns {String} 返回HTML源码 + */ + getHTML : function() { - return this.editor.find("." + this.classNames.textarea.html).val(); + if (!settings.saveHTMLToTextarea) + { + alert("Error: settings.saveHTMLToTextarea == false"); + + return false; + } + + return this.htmlTextarea.html(); + }, + + /** + * getHTML()的别名 + * @returns {editormd} 返回HTML源码 + */ + + getTextareaSavedHTML : function() { + return this.getHTML(); + }, + + /** + * 获取预览窗口的HTML源码 + * @returns {editormd} 返回editormd的实例对象 + */ + + getPreviewedHTML : function() { + if (!settings.watch) + { + alert("Error: settings.watch == false"); + + return false; + } + + return this.preivewContainer.html(); }, /** @@ -1037,7 +2060,7 @@ icon.parent().attr("title", this.settings.lang.toolbar.watch); icon.removeClass(unWatchIcon).addClass(watchIcon); - this.codeMirror.css("border-right", "1px solid #ddd").outerWidth(this.editor.width() / 2); + this.codeMirror.css("border-right", "1px solid #ddd").width(this.editor.width() / 2); this.saveToTextareas().resize(); @@ -1064,7 +2087,7 @@ icon.parent().attr("title", this.settings.lang.toolbar.unwatch); icon.removeClass(watchIcon).addClass(unWatchIcon); - this.codeMirror.css("border-right", "none").outerWidth(this.editor.width()); + this.codeMirror.css("border-right", "none").width(this.editor.width()); this.resize(); @@ -1127,17 +2150,20 @@ toolbar.find(".fa[name=preview]").toggleClass("active"); codeMirror.toggle(); - if(codeMirror.is(":hidden")) + 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(); + }); preview.show().css({ top : 0, - //borderTop : "none", width : editor.width(), height : editor.height() }); @@ -1166,8 +2192,9 @@ 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; + this.state.preview = false; codeMirror.show(); @@ -1181,12 +2208,13 @@ preview.hide(); } + previewCloseBtn.hide().bind(editormd.mouseOrTouch("click", "touchend")); + preview.css({ background : null, - //borderTop : "1px solid #ddd", width : editor.width() / 2, - height : editor.height() - toolbar.outerHeight(), - top : (settings.toolbar) ? toolbar.outerHeight() : 0 + height : editor.height() - toolbar.height(), + top : (settings.toolbar) ? toolbar.height() : 0 }); return this; @@ -1224,6 +2252,7 @@ }).addClass(fullscreenClass); this.resize(); + $.proxy(this.settings.onfullscreen, this)(); } else @@ -1270,6 +2299,7 @@ }).removeClass(fullscreenClass); this.resize(); + $.proxy(this.settings.onfullscreenExit, this)(); @@ -1348,16 +2378,17 @@ /** * 生成TOC(Table of Contents) - * @param {Array} toc 从marked获取的TOC数组列表 - * @param {Element} container 插入TOC的容器元素 - * @param {Integer} startLevel Hx 起始层级 + * @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 || 2; + startLevel = startLevel || 1; for (var i = 0, len = toc.length; i < len; i++) { @@ -1371,7 +2402,7 @@ if (level > lastLevel) { html += ""; - } + } else if (level < lastLevel) { html += (new Array(lastLevel - level + 2)).join(""); @@ -1385,13 +2416,18 @@ lastLevel = level; } - container.find('.markdown-toc-list').html("").html(html); + var tocContainer = container.find('.markdown-toc'); + + tocContainer.children('.markdown-toc-list').html("").html(html); + + return tocContainer; }; /** * 将Markdown文档解析为HTML用于前台显示 - * @param {String} id 用于显示HTML的对象ID - * @param {Object} [options={}] 配置选项,可选 + * @param {String} id 用于显示HTML的对象ID + * @param {Object} [options={}] 配置选项,可选 + * @returns {Object} div 返回jQuery对象元素 */ editormd.markdownToHTML = function(id, options) { @@ -1401,6 +2437,7 @@ toc : true, tocStartLevel : 2, markdown : "", + htmlDecode : false, inRequirejs : false, tex : false, flowChart : false, @@ -1409,30 +2446,39 @@ }; editormd.$marked = marked; - - var settings = $.extend(true, defaults, options); + var div = $("#" + id); - var saveTo = div.find("[type=\"text/markdown\"]"); - var markdownDoc = (settings.markdown === "") ? saveTo.html() : settings.markdown; + var settings = div.settings = $.extend(true, defaults, options); + var saveTo = div.find("textarea"); + var markdownDoc = (settings.markdown === "") ? saveTo.val() : settings.markdown; var markdownToC = []; + var markedOptions = { renderer : editormd.markedRenderer(markdownToC), gfm : true, tables : true, - breaks : false, + breaks : true, pedantic : false, - sanitize : true, + sanitize : (settings.htmlDecode) ? false : true, // 是否忽略HTML标签,即是否开启HTML标签解析,为了安全性,默认不开启 smartLists : true, smartypants : true }; var markdownParsed = marked(markdownDoc, markedOptions); - saveTo.html(markdownDoc); - div.addClass("markdown-body").append(markdownParsed); - + if (editormd.isIE8) + { + saveTo.val(markdownDoc); + } + else + { + saveTo.html(markdownDoc); + } + + div.addClass("markdown-body " + this.classPrefix + "html-preview").append(markdownParsed); + if (settings.toc) { - editormd.markdownToCRenderer(markdownToC, div, settings.tocStartLevel); + div.tocContainer = this.markdownToCRenderer(markdownToC, div, settings.tocStartLevel); } if (settings.previewCodeHighlight) @@ -1440,13 +2486,16 @@ div.find("pre").addClass("prettyprint linenums"); prettyPrint(); } + + if (!editormd.isIE8) + { + if (settings.flowChart) { + div.find(".flowchart").flowChart(); + } - if (settings.flowChart) { - div.find(".flowchart").flowChart(); - } - - if (settings.sequenceDiagram) { - div.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); + if (settings.sequenceDiagram) { + div.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); + } } if (settings.tex) @@ -1459,7 +2508,7 @@ }; if (!settings.inRequirejs) { - editormd.loadKaTeX(function(){ + this.loadKaTeX(function(){ editormd.$katex = katex; katexHandle(); }); @@ -1467,10 +2516,55 @@ katexHandle(); } } + + div.getMarkdown = function() { + return (editormd.isIE8) ? saveTo.val() : saveTo.html(); + }; + + 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 - // 与Gulpfile.js对应 + // for Requires.js and Gulpfile.js editormd.codeMirrorModules = { modes : [ "css", @@ -1502,7 +2596,7 @@ "xquery", "yaml", "erlang", - "jade", + "jade" ], addons : [ @@ -1566,8 +2660,6 @@ } editormd.loadCSS(editormd.katexURL.css); - - //modules.push(editormd.katexURL.js + ".js"); return modules; }; @@ -1599,40 +2691,47 @@ document.body.appendChild(css); } }; - + + editormd.isIE = (navigator.appName == "Microsoft Internet Explorer"); + editormd.isIE8 = (editormd.isIE && navigator.appVersion.match(/8./i) == "8."); + /** * 动态加载JS文件的方法 * @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 = document.createElement("script"); - script.type = "text/javascript"; + var script = null; + script = document.createElement("script"); + script.id = fileName.replace(/[\./]+/g, "-"); + script.type = "text/javascript"; + script.src = fileName + ".js"; - script.onload = script.onreadystatechange = function() { - if(script.readyState) - { - if (script.readyState === "loaded" || script.readyState === "complete") + if (editormd.isIE8) { + + script.onreadystatechange = function() { + if(script.readyState) { - script.onreadystatechange = null; - callback(); - } - } - else - { + if (script.readyState === "loaded" || script.readyState === "complete") + { + script.onreadystatechange = null; + callback(); + } + } + }; + } + else + { + script.onload = function() { callback(); - } - }; - - script.src = fileName + ".js"; - - //console.log("script.src =>", script.src); + }; + } if (into === "head") { document.getElementsByTagName("head")[0].appendChild(script); @@ -1644,7 +2743,7 @@ // 使用国外的CDN,加载速度有时会很慢,或者自定义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", + js : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min" }; /** @@ -1680,7 +2779,7 @@ } return eventType; - }; + }; /** * 日期时间的格式化方法 @@ -1743,7 +2842,8 @@ case "week-day" : case "wd" : - datefmt = weekDay; + var weekDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + datefmt = weekDays[weekDay]; break; case "day" : @@ -1788,7 +2888,7 @@ default: datefmt = fymd + " " + hms; break; - } + }; return datefmt; }; diff --git a/dist/js/editormd.min.js b/dist/js/editormd.min.js index d6e54d5..641f586 100644 --- a/dist/js/editormd.min.js +++ b/dist/js/editormd.min.js @@ -1,2 +1,3 @@ -/*! Editor.md v1.0.0 | editormd.min.js | A simple online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-02-10 */ -!function(e){"use strict";"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define?define(["jquery"],e):window.editormd=e()}(function(){"use strict";var e=jQuery,t=function(e,i){return new t.fn.init(e,i)};return t.title="Editor.md",t.version="1.0.0",t.homePage="https://github.com/pandao/editor.md",t.description="A simple markdown doucment online editor.",t.classPrefix="editormd-",t.defaults={mode:"gfm",markdown:"",width:"100%",height:"100%",path:"./lib/",watch:!0,onload:function(){},onchange:function(){},onfullscreen:function(){},onfullscreenExit:function(){},toc:!0,tocStartLevel:2,fontSize:"13px",tex:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0,inRequirejs:!1,toolbar:!0,toolbarIcons:["undo","redo","|","bold","del","italic","quote","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","link","picture","code","code-block-tab","code-block","datetime","|","watch","preview","fullscreen","|","info"],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",picture:"fa-picture-o",code:"fa-code","code-block-tab":"fa-file-code-o","code-block":"fa-file-code-o",datetime:"fa-clock-o",watch:"fa-eye-slash",unwatch:"fa-eye",preview:"fa-search",fullscreen:"fa-arrows-alt",info:"fa-info-circle"},lang:{toolbar:{undo:"撤销",redo:"重做",bold:"粗体",del:"删除线",italic:"斜体",quote:"引用",h1:"标题1",h2:"标题2",h3:"标题3",h4:"标题4",h5:"标题5",h6:"标题6","list-ul":"无序列表","list-ol":"有序列表",hr:"横线",link:"链接",picture:"图片",code:"行内代码","code-block-tab":"代码块(缩进风格)","code-block":"代码块(多语言风格)",datetime:"日期时间",watch:"关闭实时预览",unwatch:"开启实时预览",preview:"预览HTML(按ESC还原)",fullscreen:"全屏(按ESC还原)",info:"关于"+t.title}}},t.classNames={tex:t.classPrefix+"tex"},t.$katex=null,t.$marked=null,t.$CodeMirror=null,t.$prettyPrint=null,t.prototype=t.fn={state:{preview:!1,fullscreen:!1},init:function(i,r){r=r||{};var o=this,a=this.classPrefix=t.classPrefix,s=this.editor=e("#"+i),n=this.settings=e.extend(!0,t.defaults,r),l=""===n.markdown?s.children('[type="text/markdown"]').html():n.markdown;this.id=i,this.classNames={textarea:{html:this.classPrefix+"html-textarea",markdown:this.classPrefix+"markdown-textarea"}},s.css({width:"number"==typeof n.width?n.width+"px":n.width,height:"number"==typeof n.height?n.height+"px":n.height}),s.children('[type="text/markdown"]').remove();var c=['
      ','','
      ','

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

      ","

      "+t.description+"

      ",'

      Home page: '+t.homePage+"

      ","

      License: MIT

      ","
      ","
      "].join("\n"),d=['
        ','",'','
        ',"
        "].join("\n");return s.append(c).append(d),this.preview=s.find("."+a+"preview"),this.toolbar=s.find("."+a+"toolbar"),this.previewContainer=this.preview.children("."+a+"preview-container"),this.infoDialog=s.find("."+a+"dialog-info"),this.toolbarIconHandlers={},s.addClass(a+"vertical"),n.inRequirejs?(o.setCodeMirror(),o.setToolbar(),o.toolbarHandler(),o.setMarked().loadedDisplay()):this.loadQueues(),this},loadQueues:function(){var e=this,i=this.settings,r=i.path,o=function(){i.flowChart||i.sequenceDiagram?t.loadScript(r+"raphael.min",function(){t.loadScript(r+"underscore.min",function(){!i.flowChart&&i.sequenceDiagram?t.loadScript(r+"sequence-diagram.min",function(){e.setMarked().loadedDisplay()}):i.flowChart&&!i.sequenceDiagram?t.loadScript(r+"flowchart.min",function(){t.loadScript(r+"jquery.flowchart.min",function(){e.setMarked().loadedDisplay()})}):i.flowChart&&i.sequenceDiagram&&t.loadScript(r+"flowchart.min",function(){t.loadScript(r+"jquery.flowchart.min",function(){t.loadScript(r+"sequence-diagram.min",function(){e.setMarked().loadedDisplay()})})})})}):e.setMarked().loadedDisplay()};return t.loadCSS(r+"codemirror/codemirror.min"),t.loadScript(r+"codemirror/codemirror.min",function(){t.$CodeMirror=CodeMirror,t.loadScript(r+"codemirror/modes.min",function(){t.loadScript(r+"codemirror/addons.min",function(){e.setCodeMirror(),e.setToolbar(),e.toolbarHandler(),t.loadScript(r+"marked.min",function(){t.$marked=marked,i.previewCodeHighlight?t.loadScript(r+"prettify.min",function(){o()}):o()})})})}),this},setCodeMirror:function(){var e=(this.settings,{mode:this.settings.mode,theme:"default",tabSize:4,dragDrop:!1,autofocus:!0,indentUnit:4,lineNumbers:!0,lineWrapping:!0,matchBrackets:!0,indentWithTabs:!0,styleActiveLine:!0,styleSelectedText:!0,autoCloseBrackets:!0,showTrailingSpace:!0,highlightSelectionMatches:{showToken:/\w/}});return this.codeEditor=t.$CodeMirror.fromTextArea(this.editor.find("."+this.classNames.textarea.markdown)[0],e),this.codeMirror=this.editor.find(".CodeMirror"),this.codeMirror.css("font-size",this.settings.fontSize),this},showToolbar:function(){return this.settings.toolbar=!0,this.toolbar.show(),this.resize(),this},hideToolbar:function(){return this.settings.toolbar=!1,this.toolbar.hide(),this.resize(),this},setToolbar:function(){var e=this.settings,t=(this.editor,this.preview,this.toolbar);if(!e.toolbar)return void t.hide();t.show();for(var i=t.find("."+this.classPrefix+"menu"),r="",o=0,a=e.toolbarIcons.length;a>o;o++){var s=e.toolbarIcons[o];if("|"!==s){var n=/h(\d)/.test(s);r+='
      • '+(n?s:"")+"
      • "}else r+='
      • |
      • '}return i.append(r),this},toolbarHandler:function(){var i=this.settings;if(i.toolbar){var r=this,o=(this.editor,this.preview,this.toolbar),a=this.codeEditor,s=(this.codeMirror,this.previewContainer,this.toolbarIcons=o.find("."+this.classPrefix+"menu .fa"));return s.bind(t.mouseOrTouch("click","touchend"),function(i){var o=e(this),s=o.attr("name"),n=a.getCursor(),l=a.getSelection();if(""!==s){var c=r.toolbarIconHandlers={undo:function(){a.undo()},redo:function(){a.redo()},bold:function(){a.replaceSelection("**"+l+"**"),""===l&&a.setCursor(n.line,n.ch+2)},del:function(){a.replaceSelection("~~"+l+"~~"),""===l&&a.setCursor(n.line,n.ch+2)},italic:function(){a.replaceSelection("*"+l+"*"),""===l&&a.setCursor(n.line,n.ch+1)},quote:function(){a.replaceSelection(""===l?["> "+l,""].join("\n"):"> "+l),a.setCursor(n.line,""===l?n.ch+2:n.ch+l.length+2)},h1:function(){a.replaceSelection("#"+l)},h2:function(){a.replaceSelection("##"+l)},h3:function(){a.replaceSelection("###"+l)},h4:function(){a.replaceSelection("####"+l)},h5:function(){a.replaceSelection("#####"+l)},h6:function(){a.replaceSelection("######"+l)},"list-ul":function(){if(""===l)a.replaceSelection("- "+l);else{for(var e=l.split("\n"),t=0,i=e.length;i>t;t++)e[t]=""===e[t]?"":"- "+e[t];a.replaceSelection(e.join("\n"))}},"list-ol":function(){if(""===l)a.replaceSelection("1. "+l);else{for(var e=l.split("\n"),t=0,i=e.length;i>t;t++)e[t]=""===e[t]?"":t+1+". "+e[t];a.replaceSelection(e.join("\n"))}},hr:function(){a.replaceSelection("------------")},link:function(){a.replaceSelection("["+l+"]("+l+' "'+l+'")')},picture:function(){a.replaceSelection("!["+l+"]("+l+' "'+l+'")')},code:function(){a.replaceSelection("`"+l+"`"),""===l&&a.setCursor(n.line,n.ch+1)},"code-block-tab":function(){a.replaceSelection(" "+l)},"code-block":function(){a.replaceSelection(["```",l,"```"].join("\n")),""===l&&a.setCursor(n.line,n.ch+3)},datetime:function(){new Date;a.replaceSelection(t.dateFormat()+" "+t.dateFormat("cn-week-day"))},watch:function(){return r.settings.watch?r.unwatch():r.watch(),i.preventDefault(),!1},preview:function(){return r.previewing(),i.preventDefault(),!1},fullscreen:function(){return r.fullscreen(),i.preventDefault(),!1},info:function(){return r.showInfoDialog(),i.preventDefault(),!1}};return c[s](),a.focus(),i.preventDefault(),!1}}),this}},showInfoDialog:function(){return e("html,body").css("overflow-x","hidden"),this.editor.find("."+this.classPrefix+"dialog-info").fadeIn(),this},hideInfoDialog:function(){return e("html,body").css("overflow-x",""),this.editor.find("."+this.classPrefix+"dialog-info").fadeOut(),this},setMarked:function(){var e=t.$marked,i=this.markdownToC=[];return e.setOptions({renderer:t.markedRenderer(i),gfm:!0,tables:!0,breaks:!1,pedantic:!1,sanitize:!0,smartLists:!0,smartypants:!0}),this},loadedDisplay:function(){this.state.loaded=!0;{var i=this,r=this.editor,o=this.preview,a=(this.toolbar,this.settings),s=this.codeEditor,n=this.codeMirror,l=this.previewContainer,c=t.mouseOrTouch;this.htmlTextarea=r.find("."+this.classNames.textarea.html),this.markdownTextarea=r.find("."+this.classNames.textarea.markdown)}r.css("background","none"),this.saveToTextareas(),o.show(),a.previewCodeHighlight&&(l.find("pre").addClass("prettyprint linenums"),prettyPrint()),a.flowChart&&l.find(".flowchart").flowChart(),a.sequenceDiagram&&l.find(".sequence-diagram").sequenceDiagram({theme:"simple"});var d=function(){l.find("."+t.classNames.tex).each(function(){var i=e(this);t.$katex.render(i.html(),i[0])})};a.tex&&(a.inRequirejs?d():t.loadKaTeX(function(){t.$katex=katex,d()})),r.data({oldWidth:r.outerWidth(),oldHeight:r.outerHeight()}),this.resize(),e(window).resize(function(){i.resize()}),e.proxy(this.settings.onload,this)(),r.find("."+this.classPrefix+"dialog-close").bind(c("click","touchend"),function(){i.hideInfoDialog()});var h=function(){n.find(".CodeMirror-scroll").bind(c("scroll","touchmove"),function(){var t=e(this).outerHeight(),i=e(this).scrollTop(),r=i/e(this)[0].scrollHeight;o.scrollTop(0===i?0:i+t>=e(this)[0].scrollHeight?o[0].scrollHeight:o[0].scrollHeight*r)})},u=function(){n.find(".CodeMirror-scroll").unbind(c("scroll","touchmove"))},f=function(){o.bind(c("scroll","touchmove"),function(){var t=e(this).outerHeight(),i=e(this).scrollTop(),r=i/e(this)[0].scrollHeight,o=n.find(".CodeMirror-scroll");o.scrollTop(0===i?0:i+t>=e(this)[0].scrollHeight?o[0].scrollHeight:o[0].scrollHeight*r)})},m=function(){o.unbind(c("scroll","touchmove"))};return n.hover(h,u).bind("touchstart",h).bind("touchend",u),o.hover(f,m).bind("touchstart",f).bind("touchend",m),s.on("change",function(){a.watch&&(i.saveToTextareas(),a.previewCodeHighlight&&(o.find("pre").addClass("prettyprint linenums"),prettyPrint()),a.flowChart&&l.find(".flowchart").flowChart(),a.sequenceDiagram&&l.find(".sequence-diagram").sequenceDiagram({theme:"simple"}),a.tex&&d(),e.proxy(a.onchange,i)())}),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,r=this.preview,o=this.toolbar,a=this.settings,s=this.infoDialog,n=(this.codeEditor,this.codeMirror);return e&&t&&i.css({width:"number"==typeof e?e+"px":e,height:"number"==typeof t?t+"px":t}),s.css({top:(i.height()-s.height())/2,left:(i.width()-s.width())/2}),a.toolbar?n.css("margin-top",o.outerHeight()).outerHeight(i.height()-o.outerHeight()):n.css("margin-top",0).outerHeight(i.height()),this.settings.watch?(n.outerWidth(i.width()/2),r.outerWidth(i.width()/2),a.toolbar?r.css("top",o.outerHeight()).outerHeight(i.height()-o.outerHeight()):r.css("top",0).outerHeight(i.height())):(n.outerWidth(i.width()),r.hide()),this},saveToTextareas:function(){var e=this.settings,i=this.codeEditor,r=this.previewContainer;i.save();var o=this.markdownToC=[],a=t.$marked(i.getValue(),{renderer:t.markedRenderer(o)});return this.markdownTextarea.html(i.getValue()),this.htmlTextarea.html(a),r.html(a),e.toc&&t.markdownToCRenderer(o,r,e.tocStartLevel),this},setMarkdown:function(e){return this.codeEditor.setValue(e),this.saveToTextareas(),this},getMarkdown:function(){return this.codeEditor.getValue()},getHTML:function(){return this.editor.find("."+this.classNames.textarea.html).val()},watch:function(t){t=t||function(){},this.settings.watch=!0,this.preview.show();var i=this.settings.toolbarIconsClass.watch,r=this.settings.toolbarIconsClass.unwatch,o=this.toolbar.find(".fa[name=watch]");return o.parent().attr("title",this.settings.lang.toolbar.watch),o.removeClass(r).addClass(i),this.codeMirror.css("border-right","1px solid #ddd").outerWidth(this.editor.width()/2),this.saveToTextareas().resize(),e.proxy(t,this)(),this},unwatch:function(t){t=t||function(){},this.settings.watch=!1,this.preview.hide();var i=this.settings.toolbarIconsClass.watch,r=this.settings.toolbarIconsClass.unwatch,o=this.toolbar.find(".fa[name=watch]");return o.parent().attr("title",this.settings.lang.toolbar.unwatch),o.removeClass(i).addClass(r),this.codeMirror.css("border-right","none").outerWidth(this.editor.width()),this.resize(),e.proxy(t,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 t=this,i=this.editor,r=this.preview,o=this.toolbar,a=this.settings,s=this.codeMirror;a.toolbar&&o.toggle(),o.find(".fa[name=preview]").toggleClass("active"),s.toggle(),s.is(":hidden")?(this.state.preview=!0,this.state.fullscreen&&r.css("background","#fff"),r.show().css({top:0,width:i.width(),height:i.height()})):this.previewed(),e(window).keyup(function(e){27===e.keyCode&&t.previewed()})},previewed:function(){var e=this.editor,t=this.preview,i=this.toolbar,r=this.settings,o=this.codeMirror;return this.state.preview=!1,o.show(),r.toolbar&&i.show(),this.settings.watch?t.show():t.hide(),t.css({background:null,width:e.width()/2,height:e.height()-i.outerHeight(),top:r.toolbar?i.outerHeight():0}),this},fullscreen:function(){var t=this,i=this.editor,r=(this.preview,this.toolbar),o=this.classPrefix+"fullscreen";return r.find(".fa[name=fullscreen]").parent().toggleClass("active"),i.hasClass(o)?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(o),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.classPrefix+"fullscreen";return this.state.fullscreen=!1,this.toolbar.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(i),this.resize(),e.proxy(this.settings.onfullscreenExit,this)(),this}},t.fn.init.prototype=t.fn,t.markedRenderer=function(e){var i=t.$marked,r=new i.Renderer;return e=e||[],r.heading=function(t,i,r){var o=t.toLowerCase().replace(/[^\w]+/g,"-"),a={text:t,level:i,slug:o};return e.push(a),"'+t+""},r.paragraph=function(e){var i=/\$\$(.*)\$\$/g.test(e),r=/^\$\$(.*)\$\$$/.test(e),o=r?' class="'+t.classNames.tex+'"':"",a=/^\[TOC\]$/.test(e);return e=!r&&i?e.replace(/(\$\$([^\$]*)\$\$)+/g,function(e,i){return''+i.replace(/\$/g,"")+""}):r?e.replace(/\$/g,""):e,a?'
          '+e+"
        ":""+e+"

        \n"},r.code=function(e,t){return"seq"===t||"sequence"===t?'
        '+e+"
        ":"flow"===t?'
        '+e+"
        ":i.Renderer.prototype.code.apply(this,arguments)},r},t.markdownToCRenderer=function(e,t,i){var r="",o=0;i=i||2;for(var a=0,s=e.length;s>a;a++){var n=e[a].text,l=e[a].level;i>l||(r+=l>o?"":o>l?new Array(o-l+2).join(""):"",r+='
      • '+n+"
          ",o=l)}t.find(".markdown-toc-list").html("").html(r)},t.markdownToHTML=function(i,r){r=r||{};var o={toc:!0,tocStartLevel:2,markdown:"",inRequirejs:!1,tex:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0};t.$marked=marked;var a=e.extend(!0,o,r),s=e("#"+i),n=s.find('[type="text/markdown"]'),l=""===a.markdown?n.html():a.markdown,c=[],d={renderer:t.markedRenderer(c),gfm:!0,tables:!0,breaks:!1,pedantic:!1,sanitize:!0,smartLists:!0,smartypants:!0},h=marked(l,d);if(n.html(l),s.addClass("markdown-body").append(h),a.toc&&t.markdownToCRenderer(c,s,a.tocStartLevel),a.previewCodeHighlight&&(s.find("pre").addClass("prettyprint linenums"),prettyPrint()),a.flowChart&&s.find(".flowchart").flowChart(),a.sequenceDiagram&&s.find(".sequence-diagram").sequenceDiagram({theme:"simple"}),a.tex){var u=function(){s.find("."+t.classNames.tex).each(function(){var i=e(this);t.$katex.render(i.html(),i[0])})};a.inRequirejs?u():t.loadKaTeX(function(){t.$katex=katex,u()})}},t.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"]},t.requirejsInit=function(e,i,r,o){t.$CodeMirror=e,t.$marked=i,t.$katex=r,t.$prettyPrint=o},t.requireModules=function(e){e=e||"";var i=(t.defaults,[]);i.push(e+"codemirror/codemirror.min");for(var r=t.codeMirrorModules,o=0,a=r.modes.length;a>o;o++){var s=r.modes[o];i.push(e+"codemirror/mode/"+s+"/"+s)}for(var o=0,a=r.addons.length;a>o;o++){var n=r.addons[o];i.push(e+"codemirror/addon/"+n)}return t.loadCSS(t.katexURL.css),i},t.loadCSS=function(e,t,i){i=i||"head",t=t||function(){};var r=document.createElement("link");r.type="text/css",r.rel="stylesheet",r.onload=r.onreadystatechange=function(){t()},r.href=e+".css","head"===i?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.loadScript=function(e,t,i){i=i||"head",t=t||function(){};var r=document.createElement("script");r.type="text/javascript",r.onload=r.onreadystatechange=function(){r.readyState?("loaded"===r.readyState||"complete"===r.readyState)&&(r.onreadystatechange=null,t()):t()},r.src=e+".js","head"===i?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.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"},t.loadKaTeX=function(e){t.loadCSS(t.katexURL.css,function(){t.loadScript(t.katexURL.js,e||function(){})})},t.mouseOrTouch=function(e,t){e=e||"click",t=t||"touchend";var i=e;try{document.createEvent("TouchEvent"),i=t}catch(r){}return i},t.dateFormat=function(e){e=e||"";var t=function(e){return 10>e?"0"+e:e},i=new Date,r=i.getFullYear(),o=r.toString().slice(2,4),a=t(i.getMonth()+1),s=t(i.getDate()),n=i.getDay(),l=t(i.getHours()),c=t(i.getMinutes()),d=t(i.getSeconds()),h=t(i.getMilliseconds()),u="",f=o+"-"+a+"-"+s,m=r+"-"+a+"-"+s,p=l+":"+c+":"+d;switch(e){case"UNIX Time":u=i.getTime();break;case"UTC":u=i.toUTCString();break;case"yy":u=o;break;case"year":case"yyyy":u=r;break;case"month":case"mm":u=a;break;case"cn-week-day":case"cn-wd":var g=["日","一","二","三","四","五","六"];u="星期"+g[n];break;case"week-day":case"wd":u=n;break;case"day":case"dd":u=s;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+" "+p+" "+h;break;case"full":case"yyyy-mm-dd h:i:s":default:u=m+" "+p}return u},t}); \ No newline at end of file +/*! Editor.md v1.1.0 | editormd.min.js | A simple online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-02-15 */ +!function(e){"use strict";"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define?define(["jquery"],e):window.editormd=e()}(function(){"use strict";var $="undefined"!=typeof jQuery?jQuery:Zepto;if("undefined"!=typeof $){var editormd=function(e,t){return new editormd.fn.init(e,t)};return editormd.title=editormd.$name="Editor.md",editormd.version="1.1.0",editormd.homePage="https://pandao.github.io/editor.md/",editormd.classPrefix="editormd-",editormd.defaults={mode:"gfm",markdown:"",width:"100%",height:"100%",path:"./lib/",watch:!0,placeholder:"now coding markdown...",readOnly:!1,lineNumbers:!0,styleActiveLine:!0,dialogLockScreen:!0,dialogShowMask:!0,dialogDraggable:!0,dialogMaskBgColor:"#fff",dialogMaskOpacity:.1,onload:function(){},onchange:function(){},onfullscreen:function(){},onfullscreenExit:function(){},imageUpload:!1,imageFormats:["jpg","jpeg","gif","png","bmp","webp"],imageUploadURL:"",saveHTMLToTextarea:!1,toc:!0,tocStartLevel:1,fontSize:"13px",htmlDecode:!1,tex:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0,inRequirejs:!1,toolbar:!0,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"]},toolbarTitles:{},toolbarHandlers:{},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","code-block-tab":"fa-file-code-o","code-block":"fa-file-code-o",datetime:"fa-clock-o",watch:"fa-eye-slash",unwatch:"fa-eye",preview:"fa-search",fullscreen:"fa-arrows-alt",clear:"fa-eraser",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:"行内代码","code-block-tab":"预格式文本 / 代码块(缩进风格)","code-block":"代码块(多语言风格)",datetime:"日期时间",watch:"关闭实时预览",unwatch:"开启实时预览",preview:"全窗口预览HTML(可按ESC还原)",fullscreen:"全屏(按ESC还原)",clear:"清空",info:"关于"+editormd.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:"错误:请填写代码内容。"}}}},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:{preview:!1,fullscreen:!1},init:function(e,t){t=t||{};var i=this,o=this.classPrefix=editormd.classPrefix,a=this.editor=$("#"+e),r=this.settings=$.extend(!0,editormd.defaults,t);this.id=e,this.lang=r.lang;var n=this.classNames={textarea:{html:this.classPrefix+"html-textarea",markdown:this.classPrefix+"markdown-textarea"}};a.hasClass("editormd")||a.addClass("editormd"),a.css({width:"number"==typeof r.width?r.width+"px":r.width,height:"number"==typeof r.height?r.height+"px":r.height});var s=this.markdownTextarea=a.children("textarea");s.length<1&&(a.append(""),s=this.markdownTextarea=a.children("textarea")),s.addClass(n.textarea.markdown).attr("name",e+"-markdown-doc").attr("placeholder",r.placeholder);var d=[r.readOnly?"":'',r.saveHTMLToTextarea?'':"",'
          ','
          ','
          '].join("\n");return a.append(d).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={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:{showToken:/\w/}};return this.codeEditor=editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0],t),this.codeMirror=this.editor.find(".CodeMirror"),this.codeMirror.css({fontSize:this.settings.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,d=a.length;d>s;s++){var l=a[s];if("|"!==l){var c=/h(\d)/.test(l),h=l;"watch"!==l||e.watch||(h="unwatch");var u=e.lang.toolbar[h],m=e.toolbarIconTexts[h],g=e.toolbarIconsClass[h];u="undefined"==typeof u?"":u,m="undefined"==typeof m?"":m,g="undefined"==typeof g?"":g,n+='
          • '+(c?l:""===g?m:"")+"
          • "}else n+='
          • |
          • '}return r.html(n),this.setToolbarHandler(),this}},getToolbarHandles:function(name){var _this=this,settings=this.settings,lang=settings.lang,editor=this.editor,codeEditor=this.codeEditor,cursor=codeEditor.getCursor(),selection=codeEditor.getSelection(),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(){codeEditor.undo()},redo:function(){codeEditor.redo()},bold:function(){codeEditor.replaceSelection("**"+selection+"**"),""===selection&&codeEditor.setCursor(cursor.line,cursor.ch+2)},del:function(){codeEditor.replaceSelection("~~"+selection+"~~"),""===selection&&codeEditor.setCursor(cursor.line,cursor.ch+2)},italic:function(){codeEditor.replaceSelection("*"+selection+"*"),""===selection&&codeEditor.setCursor(cursor.line,cursor.ch+1)},quote:function(){codeEditor.replaceSelection(""===selection?["> "+selection,""].join("\n"):"> "+selection),codeEditor.setCursor(cursor.line,""===selection?cursor.ch+2:cursor.ch+selection.length+2)},h1:function(){codeEditor.replaceSelection("#"+selection)},h2:function(){codeEditor.replaceSelection("##"+selection)},h3:function(){codeEditor.replaceSelection("###"+selection)},h4:function(){codeEditor.replaceSelection("####"+selection)},h5:function(){codeEditor.replaceSelection("#####"+selection)},h6:function(){codeEditor.replaceSelection("######"+selection)},"list-ul":function(){if(""===selection)codeEditor.replaceSelection("- "+selection);else{for(var e=selection.split("\n"),t=0,i=e.length;i>t;t++)e[t]=""===e[t]?"":"- "+e[t];codeEditor.replaceSelection(e.join("\n"))}},"list-ol":function(){if(""===selection)codeEditor.replaceSelection("1. "+selection);else{for(var e=selection.split("\n"),t=0,i=e.length;i>t;t++)e[t]=""===e[t]?"":t+1+". "+e[t];codeEditor.replaceSelection(e.join("\n"))}},hr:function(){codeEditor.replaceSelection("------------")},link:function(){var e,t=lang.dialog.link,i=classPrefix+"link-dialog";if(editor.find("."+i).length>0)e=editor.find("."+i),e.find("[data-url]").val("http://"),e.find("[data-title]").val(selection),dialogShowMask(e),dialogLockScreen(),e.show();else{var o='


            ';e=_this.createDialog({title:t.title,width:380,height:210,content:o,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(),i=this.find("[data-title]").val();return"http://"===e||""===e?(alert(t.urlEmpty),!1):""===i?(alert(t.titleEmpty),!1):(codeEditor.replaceSelection("["+i+"]("+e+' "'+i+'")'),this.hide().lockScreen(!1).hideMask(),!1)}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}})}},anchor:function(){var e,t=lang.dialog.anchor,i=classPrefix+"anchor-dialog";if(editor.find("."+i).length>0)e=editor.find("."+i),e.find("[data-name]").val(""),e.find("[data-url]").val("http://"),e.find("[data-title]").val(selection),dialogShowMask(e),dialogLockScreen(),e.show();else{var o='



            ';e=_this.createDialog({name:i,title:t.title,width:380,height:250,content:o,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-name]").val(),i=this.find("[data-url]").val(),o=this.find("[data-title]").val();return""===e?(alert(t.nameEmpty),!1):"http://"===i||""===i?(alert(t.urlEmpty),!1):""===o?(alert(t.titleEmpty),!1):(codeEditor.replaceSelection("["+o+"]["+e+"]\n["+e+"]: "+i),""===selection&&codeEditor.setCursor(cursor.line,cursor.ch+1),this.hide().lockScreen(!1).hideMask(),!1)}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}})}},image:function(){var 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 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):(codeEditor.replaceSelection(""===i||"http://"===i?"!["+t+"]("+e+' "'+t+'")':"[!["+t+"]("+e+' "'+t+'")]('+i+' "'+t+'")'),""===t&&codeEditor.setCursor(cursor.line,cursor.ch+2),this.hide().lockScreen(!1).hideMask(),!1)}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}})}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(){codeEditor.replaceSelection("`"+selection+"`"),""===selection&&codeEditor.setCursor(cursor.line,cursor.ch+1)},"code-block-tab":function(){var e,t=classPrefix+"dialog-tab-code-block";if(editor.find("."+t).length>0)e=editor.find("."+t),e.find("textarea").val(""),dialogShowMask(e),dialogLockScreen(),e.show();else{var i='';e=_this.createDialog({name:t,title:lang.dialog.tabCodeBlock.title,width:750,height:470,mask:settings.dialogShowMask,drag:settings.dialogDraggable,content:i,lockScreen:settings.dialogLockScreen,maskStyle:{opacity:settings.dialogMaskOpacity,backgroundColor:settings.dialogMaskBgColor},buttons:{enter:[lang.buttons.enter,function(){var e=this.find("textarea").val();if(""===e)return alert(lang.dialog.tabCodeBlock.codeEmptyAlert),!1;e=e.split("\n");for(var t in e)e[t]=" "+e[t];return codeEditor.replaceSelection(e.join("\n")),this.hide().lockScreen(!1).hideMask(),!1}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}})}},"code-block":function(){var e,t=classPrefix+"dialog-code-block";if(editor.find("."+t).length>0)e=editor.find("."+t),e.find("option:first").attr("selected","selected"),e.find("textarea").val(""),dialogShowMask(e),dialogLockScreen(),e.show();else{var i='
            '+lang.dialog.codeBlock.selectLabel+'
            ';e=_this.createDialog({name:t,title:lang.dialog.codeBlock.title,width:752,height:565,mask:settings.dialogShowMask,drag:settings.dialogDraggable,content:i,lockScreen:settings.dialogLockScreen,maskStyle:{opacity:settings.dialogMaskOpacity,backgroundColor:settings.dialogMaskBgColor},buttons:{enter:[lang.buttons.enter,function(){var e=this.find("textarea").val(),t=this.find("select").val();return""===t?(alert(lang.dialog.codeBlock.unselectedLanguageAlert),!1):""===e?(alert(lang.dialog.codeBlock.codeEmptyAlert),!1):(t="other"===t?"":t,codeEditor.replaceSelection(["```"+t,e,"```"].join("\n")),""===t&&codeEditor.setCursor(cursor.line,cursor.ch+3),this.hide().lockScreen(!1).hideMask(),!1)}],cancel:[lang.buttons.cancel,function(){return this.hide().lockScreen(!1).hideMask(),!1}]}});var o=e.find("select");for(var a in editormd.codeLanguages){var r=editormd.codeLanguages[a];o.append('")}o.append('")}},datetime:function(){var e=(new Date,settings.lang.name);codeEditor.replaceSelection(editormd.dateFormat()+" "+editormd.dateFormat("zh-cn"===e||"zh-tw"===e?"cn-week-day":"week-day"))},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")),n=e.getToolbarHandles();return r.bind(editormd.mouseOrTouch("click","touchend"),function(){var i=$(this).children(".fa"),a=i.attr("name"),r=o.getCursor(),s=o.getSelection();return""!==a?(e.activeIcon=i,"undefined"!=typeof n[a]?n[a]():"undefined"!=typeof t.toolbarHandlers[a]&&$.proxy(t.toolbarHandlers[a],e)(o,i,r,s),"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 d=i.find("."+r);d.lockScreen=function(t){return e.lockScreen&&$("html,body").css("overflow",t?"hidden":""),d},d.showMask=function(){return e.mask&&i.find("."+o+"mask").css(e.maskStyle).css("z-index",editormd.dialogZindex-1).show(),d},d.hideMask=function(){return e.mask&&i.find("."+o+"mask").hide(),d},d.loading=function(e){var t=d.find("."+o+"dialog-mask");return t[e?"show":"hide"](),d},d.lockScreen(!0).showMask(),d.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 l=function(){d.css({top:($(window).height()-d.height())/2+"px",left:($(window).width()-d.width())/2+"px"})};if(l(),$(window).resize(l),d.children("."+o+"dialog-close").bind(n("click","touchend"),function(){d.hide().lockScreen(!1).hideMask()}),"object"==typeof e.buttons){var c=d.footer=d.find("."+o+"dialog-footer");for(var h in e.buttons){var u=e.buttons[h],m=o+h+"-btn";c.append('"),u[1]=$.proxy(u[1],d),c.children("."+m).bind(n("click","touchend"),u[1])}}if(""!==e.title&&e.drag){var g,f,p=d.children("."+o+"dialog-header");e.mask||p.bind(n("click","touchend"),function(){editormd.dialogZindex+=2,d.css("z-index",editormd.dialogZindex)}),p.mousedown(function(e){e=e||window.event,g=e.clientX-parseInt(d[0].style.left),f=e.clientY-parseInt(d[0].style.top),document.onmousemove=b});var v=function(e){e.removeClass(o+"user-unselect").off("selectstart")},w=function(e){e.addClass(o+"user-unselect").on("selectstart",function(){return!1})},b=function(e){e=e||window.event;var t,i,o=parseInt(d[0].style.left),a=parseInt(d[0].style.top);o>=0?o+d.width()<=$(window).width()?t=e.clientX-g:(t=$(window).width()-d.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(d),d[0].style.left=t+"px",d[0].style.top=i+"px"};document.onmouseup=function(){v($("body")),v(d),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,d},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":""),this},showInfoDialog:function(){$("html,body").css("overflow-x","hidden");var e=this.editor,t=this.classPrefix,i=this.infoDialog=e.find("."+t+"dialog-info");i.length<1&&this.createInfoDialog(),i.show();var o=function(){i.css({top:($(window).height()-i.height())/2+"px",left:($(window).width()-i.width())/2+"px"})};return o(),$(window).resize(o),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,this.settings),t=e.toolbarIcons();return"undefined"!=typeof this.infoDialog&&this.infoDialog.remove(),"undefined"!=typeof t.info&&createInfoDialog(),e.readOnly||(this.getToolbarHandles(),this.setToolbar()),this.resize(),this},loadedDisplay:function(){this.state.loaded=!0;var e=this,t=this.editor,i=this.preview,o=this.settings,a=this.codeEditor,r=this.codeMirror,n=this.previewContainer,s=editormd.mouseOrTouch;t.css("background","none"),this.saveToTextareas(),o.watch&&i.show();var d=function(){o.previewCodeHighlight&&(n.find("pre").addClass("prettyprint linenums"),prettyPrint())},l=function(){editormd.isIE8||(o.flowChart&&n.find(".flowchart").flowChart(),o.sequenceDiagram&&n.find(".sequence-diagram").sequenceDiagram({theme:"simple"}))};d(),l();var c=function(){n.find("."+editormd.classNames.tex).each(function(){var e=$(this);editormd.$katex.render(e.html(),e[0])})};o.tex&&(o.inRequirejs?c():editormd.loadKaTeX(function(){editormd.$katex=katex,c()})),t.data("oldWidth",t.width()).data("oldHeight",t.height()),this.resize(),$(window).resize(function(){e.resize()}),$.proxy(o.onload,this)();var h=function(){r.find(".CodeMirror-scroll").bind(s("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)})},u=function(){r.find(".CodeMirror-scroll").unbind(s("scroll","touchmove"))},m=function(){i.bind(s("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)})},g=function(){i.unbind(s("scroll","touchmove"))};return r.bind({mouseover:h,mouseout:u,touchstart:h,touchend:u}),i.bind({mouseover:m,mouseout:g,touchstart:m,touchend:g}),a.on("change",function(){o.watch&&(e.saveToTextareas(),d(),l(),o.tex&&c(),$.proxy(o.onchange,e)())}),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(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.settings,t=this.codeEditor,i=this.previewContainer;t.save();var o=this.markdownToC=[],a=editormd.$marked(t.getValue(),{renderer:editormd.markedRenderer(o)});return this.markdownTextarea.val(t.getValue()),e.saveHTMLToTextarea&&this.htmlTextarea.html(a),e.watch&&(i.html(a),e.toc&&editormd.markdownToCRenderer(o,i,e.tocStartLevel)),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){return this.codeEditor.setValue(e),this.saveToTextareas(),this},getMarkdown:function(){return this.codeEditor.getValue()},clear:function(){return this.codeEditor.setValue(""),this.saveToTextareas(),this},getHTML:function(){return settings.saveHTMLToTextarea?this.htmlTextarea.html():(alert("Error: settings.saveHTMLToTextarea == false"),!1)},getTextareaSavedHTML:function(){return this.getHTML()},getPreviewedHTML:function(){return settings.watch?this.preivewContainer.html():(alert("Error: settings.watch == false"),!1)},watch:function(e){e=e||function(){},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.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()}),i.show().css({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,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.markedRenderer=function(e){var t=editormd.$marked,i=new t.Renderer;return e=e||[],i.heading=function(t,i,o){var a=t.toLowerCase().replace(/[^\w]+/g,"-"),r={text:t,level:i,slug:a};return e.push(r),"'+t+""},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,d=e[r].level;i>d||(o+=d>a?"":a>d?new Array(a-d+2).join("
        • "):"",o+='
        • '+s+"
            ",a=d)}var l=t.find(".markdown-toc");return l.children(".markdown-toc-list").html("").html(o),l},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=[],d={renderer:editormd.markedRenderer(s),gfm:!0,tables:!0,breaks:!0,pedantic:!1,sanitize:a.htmlDecode?!1:!0,smartLists:!0,smartypants:!0},l=marked(n,d);if(editormd.isIE8?r.val(n):r.html(n),o.addClass("markdown-body "+this.classPrefix+"html-preview").append(l),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.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(),d=t(i.getHours()),l=t(i.getMinutes()),c=t(i.getSeconds()),h=t(i.getMilliseconds()),u="",m=a+"-"+r+"-"+n,g=o+"-"+r+"-"+n,f=d+":"+l+":"+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=d;break;case"min":case"ii":u=l;break;case"second":case"ss":u=c;break;case"ms":u=h;break;case"yy-mm-dd":u=m;break;case"yyyy-mm-dd":u=g;break;case"yyyy-mm-dd h:i:s ms":case"full + ms":u=g+" "+f+" "+h;break;case"full":case"yyyy-mm-dd h:i:s":default:u=g+" "+f}return u},editormd}}); \ No newline at end of file diff --git a/dist/js/languages/en.js b/dist/js/languages/en.js new file mode 100644 index 0000000..246312c --- /dev/null +++ b/dist/js/languages/en.js @@ -0,0 +1,121 @@ +/* + * Editor.md + * @file languagesen.js + * @version v1.1.0 + * @description A simple online markdown editor. + * @license MIT License + * @author Pandao + * {@link https://github.com/pandao/editor.md} + * @updateTime 2015-02-15 + */ + +(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 new file mode 100644 index 0000000..12e677e --- /dev/null +++ b/dist/js/languages/en.min.js @@ -0,0 +1,2 @@ +/*! Editor.md v1.1.0 | languagesen.min.js | A simple online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-02-15 */ +!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 new file mode 100644 index 0000000..0742f1a --- /dev/null +++ b/dist/js/languages/zh-tw.js @@ -0,0 +1,121 @@ +/* + * Editor.md + * @file languageszh-tw.js + * @version v1.1.0 + * @description A simple online markdown editor. + * @license MIT License + * @author Pandao + * {@link https://github.com/pandao/editor.md} + * @updateTime 2015-02-15 + */ + +(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 new file mode 100644 index 0000000..bcc2c33 --- /dev/null +++ b/dist/js/languages/zh-tw.min.js @@ -0,0 +1,2 @@ +/*! Editor.md v1.1.0 | languageszh-tw.min.js | A simple online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-02-15 */ +!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/examples/127.0.0.1-8888.url b/examples/127.0.0.1-8888.url new file mode 100644 index 0000000..a6d9a2b --- /dev/null +++ b/examples/127.0.0.1-8888.url @@ -0,0 +1,2 @@ +[InternetShortcut] +URL=http://127.0.0.1:8888/ diff --git a/examples/css/style.css b/examples/css/style.css index ce8861c..8026fb2 100644 --- a/examples/css/style.css +++ b/examples/css/style.css @@ -70,4 +70,19 @@ body { #layout > header > h1 { font-size: 20px; margin-bottom: 10px; +} + +.btns button, .btn { + padding: 8px 10px; + background: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 3px; + border-radius: 3px; + cursor: pointer; + -webkit-transition: background 300ms ease-out; + transition: background 300ms ease-out; +} + +.btns button:hover, .btn:hover { + background: #f6f6f6; } \ No newline at end of file diff --git a/examples/custom-toolbar.html b/examples/custom-toolbar.html new file mode 100644 index 0000000..6062924 --- /dev/null +++ b/examples/custom-toolbar.html @@ -0,0 +1,140 @@ + + + + + 自定义工具栏 - Editor.md examples + + + + +
            +
            +

            自定义工具栏

            +

            Custom toolbar (icons handler)

            +
            +
            + +
            +
            + + + + + + + + \ No newline at end of file diff --git a/examples/dynamic-create-editormd.html b/examples/dynamic-create-editormd.html new file mode 100644 index 0000000..8fd1e1b --- /dev/null +++ b/examples/dynamic-create-editormd.html @@ -0,0 +1,46 @@ + + + + + 动态创建Editor.md - Editor.md examples + + + + +
            +
            +

            动态创建Editor.md

            +

            Dynamic create Editor.md

            +
            +
            + + +
            +
            +
            + + + + + \ No newline at end of file diff --git a/examples/flowchart.html b/examples/flowchart.html index dc20b7a..5035f8e 100644 --- a/examples/flowchart.html +++ b/examples/flowchart.html @@ -4,6 +4,7 @@ FlowChart - Editor.md examples +
            @@ -11,8 +12,17 @@

            FlowChart 流程图

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

            -
            - +```
            - diff --git a/examples/form-get-value.html b/examples/form-get-value.html new file mode 100644 index 0000000..3d0f0b3 --- /dev/null +++ b/examples/form-get-value.html @@ -0,0 +1,85 @@ + + + + + Form get textarea value - Editor.md examples + + + + +
            +
            +

            表单取值

            +

            Form get textarea value.

            +
            +
            +
            + +
            +
            + +
            +
            +
            + + + + + \ No newline at end of file diff --git a/examples/full.html b/examples/full.html new file mode 100644 index 0000000..098259c --- /dev/null +++ b/examples/full.html @@ -0,0 +1,159 @@ + + + + + 完整示例 - Editor.md examples + + + + +
            +
            +

            完整示例

            +

            开启HTML标签识别和解析、TeX(基于KaTeX)、流程图和时序/序列图支持;

            +
            +
            + + + + + + + + + + +
            +
            +
            + + + + + \ No newline at end of file diff --git a/examples/html-preview-markdown-to-html.html b/examples/html-preview-markdown-to-html.html index 48c8423..bed26cf 100644 --- a/examples/html-preview-markdown-to-html.html +++ b/examples/html-preview-markdown-to-html.html @@ -4,6 +4,7 @@ HTML Preview(markdown to html) - Editor.md examples + \ No newline at end of file diff --git a/examples/js/seajs-main.js b/examples/js/seajs-main.js new file mode 100644 index 0000000..f71d14e --- /dev/null +++ b/examples/js/seajs-main.js @@ -0,0 +1,74 @@ +define(function(require){ + var $ = require("jquery"); + var editormd = require("editormd"); + + require("../../src/js/languages/en"); // 加载英语语言包 + + console.log($, editormd); + + $.get("./test.md", function(md){ + testEditor = editormd("test-editormd", { + width: "90%", + height: 640, + path : '../lib/', + markdown : md, + //toolbar : false, //关闭工具栏 + htmlDecode : true, // 开启HTML标签解析,为了安全性,默认不开启 + tex : true, // 开启科学公式TeX语言支持,默认关闭 + //previewCodeHighlight : false, // 关闭预览窗口的代码高亮,默认开启 + flowChart : true, // 疑似Sea.js与Raphael.js有冲突,必须先加载Raphael.js,Editor.md才能在Sea.js下正常进行; + sequenceDiagram : true, // 同上 + onload : function() { + console.log('onload', this); + //this.fullscreen(); + //this.unwatch(); + //this.watch().fullscreen(); + + //this.setMarkdown("#PHP"); + //this.width("100%"); + //this.height(480); + //this.resize("100%", 640); + } + }); + }); + + $("#show-btn").bind('click', function(){ + testEditor.show(); + }); + + $("#hide-btn").bind('click', function(){ + testEditor.hide(); + }); + + $("#get-md-btn").bind('click', function(){ + alert(testEditor.getMarkdown()); + }); + + $("#get-html-btn").bind('click', function() { + alert(testEditor.getHTML()); + }); + + $("#watch-btn").bind('click', function() { + testEditor.watch(); + }); + + $("#unwatch-btn").bind('click', function() { + testEditor.unwatch(); + }); + + $("#preview-btn").bind('click', function() { + testEditor.previewing(); + }); + + $("#fullscreen-btn").bind('click', function() { + testEditor.fullscreen(); + }); + + $("#show-toolbar-btn").bind('click', function() { + testEditor.showToolbar(); + }); + + $("#close-toolbar-btn").bind('click', function() { + testEditor.hideToolbar(); + }); +}); \ No newline at end of file diff --git a/examples/js/zepto.min.js b/examples/js/zepto.min.js new file mode 100644 index 0000000..0d545b9 --- /dev/null +++ b/examples/js/zepto.min.js @@ -0,0 +1,2 @@ +/* Zepto v1.1.6 - zepto event ajax form ie - zeptojs.com/license */ +var Zepto=function(){function L(t){return null==t?String(t):j[S.call(t)]||"object"}function Z(t){return"function"==L(t)}function _(t){return null!=t&&t==t.window}function $(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function D(t){return"object"==L(t)}function M(t){return D(t)&&!_(t)&&Object.getPrototypeOf(t)==Object.prototype}function R(t){return"number"==typeof t.length}function k(t){return s.call(t,function(t){return null!=t})}function z(t){return t.length>0?n.fn.concat.apply([],t):t}function F(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function q(t){return t in f?f[t]:f[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function H(t,e){return"number"!=typeof e||c[F(t)]?e:e+"px"}function I(t){var e,n;return u[t]||(e=a.createElement(t),a.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),u[t]=n),u[t]}function V(t){return"children"in t?o.call(t.children):n.map(t.childNodes,function(t){return 1==t.nodeType?t:void 0})}function B(n,i,r){for(e in i)r&&(M(i[e])||A(i[e]))?(M(i[e])&&!M(n[e])&&(n[e]={}),A(i[e])&&!A(n[e])&&(n[e]=[]),B(n[e],i[e],r)):i[e]!==t&&(n[e]=i[e])}function U(t,e){return null==e?n(t):n(t).filter(e)}function J(t,e,n,i){return Z(e)?e.call(t,n,i):e}function X(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function W(e,n){var i=e.className||"",r=i&&i.baseVal!==t;return n===t?r?i.baseVal:i:void(r?i.baseVal=n:e.className=n)}function Y(t){try{return t?"true"==t||("false"==t?!1:"null"==t?null:+t+""==t?+t:/^[\[\{]/.test(t)?n.parseJSON(t):t):t}catch(e){return t}}function G(t,e){e(t);for(var n=0,i=t.childNodes.length;i>n;n++)G(t.childNodes[n],e)}var t,e,n,i,C,N,r=[],o=r.slice,s=r.filter,a=window.document,u={},f={},c={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,h=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,p=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,d=/^(?:body|html)$/i,m=/([A-Z])/g,g=["val","css","html","text","data","width","height","offset"],v=["after","prepend","before","append"],y=a.createElement("table"),x=a.createElement("tr"),b={tr:a.createElement("tbody"),tbody:y,thead:y,tfoot:y,td:x,th:x,"*":a.createElement("div")},w=/complete|loaded|interactive/,E=/^[\w-]*$/,j={},S=j.toString,T={},O=a.createElement("div"),P={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},A=Array.isArray||function(t){return t instanceof Array};return T.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var i,r=t.parentNode,o=!r;return o&&(r=O).appendChild(t),i=~T.qsa(r,e).indexOf(t),o&&O.removeChild(t),i},C=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},N=function(t){return s.call(t,function(e,n){return t.indexOf(e)==n})},T.fragment=function(e,i,r){var s,u,f;return h.test(e)&&(s=n(a.createElement(RegExp.$1))),s||(e.replace&&(e=e.replace(p,"<$1>")),i===t&&(i=l.test(e)&&RegExp.$1),i in b||(i="*"),f=b[i],f.innerHTML=""+e,s=n.each(o.call(f.childNodes),function(){f.removeChild(this)})),M(r)&&(u=n(s),n.each(r,function(t,e){g.indexOf(t)>-1?u[t](e):u.attr(t,e)})),s},T.Z=function(t,e){return t=t||[],t.__proto__=n.fn,t.selector=e||"",t},T.isZ=function(t){return t instanceof T.Z},T.init=function(e,i){var r;if(!e)return T.Z();if("string"==typeof e)if(e=e.trim(),"<"==e[0]&&l.test(e))r=T.fragment(e,RegExp.$1,i),e=null;else{if(i!==t)return n(i).find(e);r=T.qsa(a,e)}else{if(Z(e))return n(a).ready(e);if(T.isZ(e))return e;if(A(e))r=k(e);else if(D(e))r=[e],e=null;else if(l.test(e))r=T.fragment(e.trim(),RegExp.$1,i),e=null;else{if(i!==t)return n(i).find(e);r=T.qsa(a,e)}}return T.Z(r,e)},n=function(t,e){return T.init(t,e)},n.extend=function(t){var e,n=o.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){B(t,n,e)}),t},T.qsa=function(t,e){var n,i="#"==e[0],r=!i&&"."==e[0],s=i||r?e.slice(1):e,a=E.test(s);return $(t)&&a&&i?(n=t.getElementById(s))?[n]:[]:1!==t.nodeType&&9!==t.nodeType?[]:o.call(a&&!i?r?t.getElementsByClassName(s):t.getElementsByTagName(e):t.querySelectorAll(e))},n.contains=a.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},n.type=L,n.isFunction=Z,n.isWindow=_,n.isArray=A,n.isPlainObject=M,n.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},n.inArray=function(t,e,n){return r.indexOf.call(e,t,n)},n.camelCase=C,n.trim=function(t){return null==t?"":String.prototype.trim.call(t)},n.uuid=0,n.support={},n.expr={},n.map=function(t,e){var n,r,o,i=[];if(R(t))for(r=0;r=0?e:e+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return r.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return Z(t)?this.not(this.not(t)):n(s.call(this,function(e){return T.matches(e,t)}))},add:function(t,e){return n(N(this.concat(n(t,e))))},is:function(t){return this.length>0&&T.matches(this[0],t)},not:function(e){var i=[];if(Z(e)&&e.call!==t)this.each(function(t){e.call(this,t)||i.push(this)});else{var r="string"==typeof e?this.filter(e):R(e)&&Z(e.item)?o.call(e):n(e);this.forEach(function(t){r.indexOf(t)<0&&i.push(t)})}return n(i)},has:function(t){return this.filter(function(){return D(t)?n.contains(this,t):n(this).find(t).size()})},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!D(t)?t:n(t)},last:function(){var t=this[this.length-1];return t&&!D(t)?t:n(t)},find:function(t){var e,i=this;return e=t?"object"==typeof t?n(t).filter(function(){var t=this;return r.some.call(i,function(e){return n.contains(e,t)})}):1==this.length?n(T.qsa(this[0],t)):this.map(function(){return T.qsa(this,t)}):n()},closest:function(t,e){var i=this[0],r=!1;for("object"==typeof t&&(r=n(t));i&&!(r?r.indexOf(i)>=0:T.matches(i,t));)i=i!==e&&!$(i)&&i.parentNode;return n(i)},parents:function(t){for(var e=[],i=this;i.length>0;)i=n.map(i,function(t){return(t=t.parentNode)&&!$(t)&&e.indexOf(t)<0?(e.push(t),t):void 0});return U(e,t)},parent:function(t){return U(N(this.pluck("parentNode")),t)},children:function(t){return U(this.map(function(){return V(this)}),t)},contents:function(){return this.map(function(){return o.call(this.childNodes)})},siblings:function(t){return U(this.map(function(t,e){return s.call(V(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return n.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=I(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var e=Z(t);if(this[0]&&!e)var i=n(t).get(0),r=i.parentNode||this.length>1;return this.each(function(o){n(this).wrapAll(e?t.call(this,o):r?i.cloneNode(!0):i)})},wrapAll:function(t){if(this[0]){n(this[0]).before(t=n(t));for(var e;(e=t.children()).length;)t=e.first();n(t).append(this)}return this},wrapInner:function(t){var e=Z(t);return this.each(function(i){var r=n(this),o=r.contents(),s=e?t.call(this,i):t;o.length?o.wrapAll(s):r.append(s)})},unwrap:function(){return this.parent().each(function(){n(this).replaceWith(n(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(e){return this.each(function(){var i=n(this);(e===t?"none"==i.css("display"):e)?i.show():i.hide()})},prev:function(t){return n(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return n(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var i=this.innerHTML;n(this).empty().append(J(this,t,e,i))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=J(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this[0].textContent:null},attr:function(n,i){var r;return"string"!=typeof n||1 in arguments?this.each(function(t){if(1===this.nodeType)if(D(n))for(e in n)X(this,e,n[e]);else X(this,n,J(this,i,t,this.getAttribute(n)))}):this.length&&1===this[0].nodeType?!(r=this[0].getAttribute(n))&&n in this[0]?this[0][n]:r:t},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){X(this,t)},this)})},prop:function(t,e){return t=P[t]||t,1 in arguments?this.each(function(n){this[t]=J(this,e,n,this[t])}):this[0]&&this[0][t]},data:function(e,n){var i="data-"+e.replace(m,"-$1").toLowerCase(),r=1 in arguments?this.attr(i,n):this.attr(i);return null!==r?Y(r):t},val:function(t){return 0 in arguments?this.each(function(e){this.value=J(this,t,e,this.value)}):this[0]&&(this[0].multiple?n(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var i=n(this),r=J(this,t,e,i.offset()),o=i.offsetParent().offset(),s={top:r.top-o.top,left:r.left-o.left};"static"==i.css("position")&&(s.position="relative"),i.css(s)});if(!this.length)return null;var e=this[0].getBoundingClientRect();return{left:e.left+window.pageXOffset,top:e.top+window.pageYOffset,width:Math.round(e.width),height:Math.round(e.height)}},css:function(t,i){if(arguments.length<2){var r,o=this[0];if(!o)return;if(r=getComputedStyle(o,""),"string"==typeof t)return o.style[C(t)]||r.getPropertyValue(t);if(A(t)){var s={};return n.each(t,function(t,e){s[e]=o.style[C(e)]||r.getPropertyValue(e)}),s}}var a="";if("string"==L(t))i||0===i?a=F(t)+":"+H(t,i):this.each(function(){this.style.removeProperty(F(t))});else for(e in t)t[e]||0===t[e]?a+=F(e)+":"+H(e,t[e])+";":this.each(function(){this.style.removeProperty(F(e))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(n(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return t?r.some.call(this,function(t){return this.test(W(t))},q(t)):!1},addClass:function(t){return t?this.each(function(e){if("className"in this){i=[];var r=W(this),o=J(this,t,e,r);o.split(/\s+/g).forEach(function(t){n(this).hasClass(t)||i.push(t)},this),i.length&&W(this,r+(r?" ":"")+i.join(" "))}}):this},removeClass:function(e){return this.each(function(n){if("className"in this){if(e===t)return W(this,"");i=W(this),J(this,e,n,i).split(/\s+/g).forEach(function(t){i=i.replace(q(t)," ")}),W(this,i.trim())}})},toggleClass:function(e,i){return e?this.each(function(r){var o=n(this),s=J(this,e,r,W(this));s.split(/\s+/g).forEach(function(e){(i===t?!o.hasClass(e):i)?o.addClass(e):o.removeClass(e)})}):this},scrollTop:function(e){if(this.length){var n="scrollTop"in this[0];return e===t?n?this[0].scrollTop:this[0].pageYOffset:this.each(n?function(){this.scrollTop=e}:function(){this.scrollTo(this.scrollX,e)})}},scrollLeft:function(e){if(this.length){var n="scrollLeft"in this[0];return e===t?n?this[0].scrollLeft:this[0].pageXOffset:this.each(n?function(){this.scrollLeft=e}:function(){this.scrollTo(e,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),i=this.offset(),r=d.test(e[0].nodeName)?{top:0,left:0}:e.offset();return i.top-=parseFloat(n(t).css("margin-top"))||0,i.left-=parseFloat(n(t).css("margin-left"))||0,r.top+=parseFloat(n(e[0]).css("border-top-width"))||0,r.left+=parseFloat(n(e[0]).css("border-left-width"))||0,{top:i.top-r.top,left:i.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||a.body;t&&!d.test(t.nodeName)&&"static"==n(t).css("position");)t=t.offsetParent;return t})}},n.fn.detach=n.fn.remove,["width","height"].forEach(function(e){var i=e.replace(/./,function(t){return t[0].toUpperCase()});n.fn[e]=function(r){var o,s=this[0];return r===t?_(s)?s["inner"+i]:$(s)?s.documentElement["scroll"+i]:(o=this.offset())&&o[e]:this.each(function(t){s=n(this),s.css(e,J(this,r,t,s[e]()))})}}),v.forEach(function(t,e){var i=e%2;n.fn[t]=function(){var t,o,r=n.map(arguments,function(e){return t=L(e),"object"==t||"array"==t||null==e?e:T.fragment(e)}),s=this.length>1;return r.length<1?this:this.each(function(t,u){o=i?u:u.parentNode,u=0==e?u.nextSibling:1==e?u.firstChild:2==e?u:null;var f=n.contains(a.documentElement,o);r.forEach(function(t){if(s)t=t.cloneNode(!0);else if(!o)return n(t).remove();o.insertBefore(t,u),f&&G(t,function(t){null==t.nodeName||"SCRIPT"!==t.nodeName.toUpperCase()||t.type&&"text/javascript"!==t.type||t.src||window.eval.call(window,t.innerHTML)})})})},n.fn[i?t+"To":"insert"+(e?"Before":"After")]=function(e){return n(e)[t](this),this}}),T.Z.prototype=n.fn,T.uniq=N,T.deserializeValue=Y,n.zepto=T,n}();window.Zepto=Zepto,void 0===window.$&&(window.$=Zepto),function(t){function l(t){return t._zid||(t._zid=e++)}function h(t,e,n,i){if(e=p(e),e.ns)var r=d(e.ns);return(s[l(t)]||[]).filter(function(t){return!(!t||e.e&&t.e!=e.e||e.ns&&!r.test(t.ns)||n&&l(t.fn)!==l(n)||i&&t.sel!=i)})}function p(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function d(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function m(t,e){return t.del&&!u&&t.e in f||!!e}function g(t){return c[t]||u&&f[t]||t}function v(e,i,r,o,a,u,f){var h=l(e),d=s[h]||(s[h]=[]);i.split(/\s/).forEach(function(i){if("ready"==i)return t(document).ready(r);var s=p(i);s.fn=r,s.sel=a,s.e in c&&(r=function(e){var n=e.relatedTarget;return!n||n!==this&&!t.contains(this,n)?s.fn.apply(this,arguments):void 0}),s.del=u;var l=u||r;s.proxy=function(t){if(t=j(t),!t.isImmediatePropagationStopped()){t.data=o;var i=l.apply(e,t._args==n?[t]:[t].concat(t._args));return i===!1&&(t.preventDefault(),t.stopPropagation()),i}},s.i=d.length,d.push(s),"addEventListener"in e&&e.addEventListener(g(s.e),s.proxy,m(s,f))})}function y(t,e,n,i,r){var o=l(t);(e||"").split(/\s/).forEach(function(e){h(t,e,n,i).forEach(function(e){delete s[o][e.i],"removeEventListener"in t&&t.removeEventListener(g(e.e),e.proxy,m(e,r))})})}function j(e,i){return(i||!e.isDefaultPrevented)&&(i||(i=e),t.each(E,function(t,n){var r=i[t];e[t]=function(){return this[n]=x,r&&r.apply(i,arguments)},e[n]=b}),(i.defaultPrevented!==n?i.defaultPrevented:"returnValue"in i?i.returnValue===!1:i.getPreventDefault&&i.getPreventDefault())&&(e.isDefaultPrevented=x)),e}function S(t){var e,i={originalEvent:t};for(e in t)w.test(e)||t[e]===n||(i[e]=t[e]);return j(i,t)}var n,e=1,i=Array.prototype.slice,r=t.isFunction,o=function(t){return"string"==typeof t},s={},a={},u="onfocusin"in window,f={focus:"focusin",blur:"focusout"},c={mouseenter:"mouseover",mouseleave:"mouseout"};a.click=a.mousedown=a.mouseup=a.mousemove="MouseEvents",t.event={add:v,remove:y},t.proxy=function(e,n){var s=2 in arguments&&i.call(arguments,2);if(r(e)){var a=function(){return e.apply(n,s?s.concat(i.call(arguments)):arguments)};return a._zid=l(e),a}if(o(n))return s?(s.unshift(e[n],e),t.proxy.apply(null,s)):t.proxy(e[n],e);throw new TypeError("expected function")},t.fn.bind=function(t,e,n){return this.on(t,e,n)},t.fn.unbind=function(t,e){return this.off(t,e)},t.fn.one=function(t,e,n,i){return this.on(t,e,n,i,1)};var x=function(){return!0},b=function(){return!1},w=/^([A-Z]|returnValue$|layer[XY]$)/,E={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};t.fn.delegate=function(t,e,n){return this.on(e,t,n)},t.fn.undelegate=function(t,e,n){return this.off(e,t,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,s,a,u,f){var c,l,h=this;return e&&!o(e)?(t.each(e,function(t,e){h.on(t,s,a,e,f)}),h):(o(s)||r(u)||u===!1||(u=a,a=s,s=n),(r(a)||a===!1)&&(u=a,a=n),u===!1&&(u=b),h.each(function(n,r){f&&(c=function(t){return y(r,t.type,u),u.apply(this,arguments)}),s&&(l=function(e){var n,o=t(e.target).closest(s,r).get(0);return o&&o!==r?(n=t.extend(S(e),{currentTarget:o,liveFired:r}),(c||u).apply(o,[n].concat(i.call(arguments,1)))):void 0}),v(r,e,u,a,s,l||c)}))},t.fn.off=function(e,i,s){var a=this;return e&&!o(e)?(t.each(e,function(t,e){a.off(t,i,e)}),a):(o(i)||r(s)||s===!1||(s=i,i=n),s===!1&&(s=b),a.each(function(){y(this,e,s,i)}))},t.fn.trigger=function(e,n){return e=o(e)||t.isPlainObject(e)?t.Event(e):j(e),e._args=n,this.each(function(){e.type in f&&"function"==typeof this[e.type]?this[e.type]():"dispatchEvent"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,n){var i,r;return this.each(function(s,a){i=S(o(e)?t.Event(e):e),i._args=n,i.target=a,t.each(h(a,e.type||e),function(t,e){return r=e.proxy(i),i.isImmediatePropagationStopped()?!1:void 0})}),r},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(t,e){o(t)||(e=t,t=e.type);var n=document.createEvent(a[t]||"Events"),i=!0;if(e)for(var r in e)"bubbles"==r?i=!!e[r]:n[r]=e[r];return n.initEvent(t,i,!0),j(n)}}(Zepto),function(t){function h(e,n,i){var r=t.Event(n);return t(e).trigger(r,i),!r.isDefaultPrevented()}function p(t,e,i,r){return t.global?h(e||n,i,r):void 0}function d(e){e.global&&0===t.active++&&p(e,null,"ajaxStart")}function m(e){e.global&&!--t.active&&p(e,null,"ajaxStop")}function g(t,e){var n=e.context;return e.beforeSend.call(n,t,e)===!1||p(e,n,"ajaxBeforeSend",[t,e])===!1?!1:void p(e,n,"ajaxSend",[t,e])}function v(t,e,n,i){var r=n.context,o="success";n.success.call(r,t,o,e),i&&i.resolveWith(r,[t,o,e]),p(n,r,"ajaxSuccess",[e,n,t]),x(o,e,n)}function y(t,e,n,i,r){var o=i.context;i.error.call(o,n,e,t),r&&r.rejectWith(o,[n,e,t]),p(i,o,"ajaxError",[n,i,t||e]),x(e,n,i)}function x(t,e,n){var i=n.context;n.complete.call(i,e,t),p(n,i,"ajaxComplete",[e,n]),m(n)}function b(){}function w(t){return t&&(t=t.split(";",2)[0]),t&&(t==f?"html":t==u?"json":s.test(t)?"script":a.test(t)&&"xml")||"text"}function E(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function j(e){e.processData&&e.data&&"string"!=t.type(e.data)&&(e.data=t.param(e.data,e.traditional)),!e.data||e.type&&"GET"!=e.type.toUpperCase()||(e.url=E(e.url,e.data),e.data=void 0)}function S(e,n,i,r){return t.isFunction(n)&&(r=i,i=n,n=void 0),t.isFunction(i)||(r=i,i=void 0),{url:e,data:n,success:i,dataType:r}}function C(e,n,i,r){var o,s=t.isArray(n),a=t.isPlainObject(n);t.each(n,function(n,u){o=t.type(u),r&&(n=i?r:r+"["+(a||"object"==o||"array"==o?n:"")+"]"),!r&&s?e.add(u.name,u.value):"array"==o||!i&&"object"==o?C(e,u,i,n):e.add(n,u)})}var i,r,e=0,n=window.document,o=/)<[^<]*)*<\/script>/gi,s=/^(?:text|application)\/javascript/i,a=/^(?:text|application)\/xml/i,u="application/json",f="text/html",c=/^\s*$/,l=n.createElement("a");l.href=window.location.href,t.active=0,t.ajaxJSONP=function(i,r){if(!("type"in i))return t.ajax(i);var f,h,o=i.jsonpCallback,s=(t.isFunction(o)?o():o)||"jsonp"+ ++e,a=n.createElement("script"),u=window[s],c=function(e){t(a).triggerHandler("error",e||"abort")},l={abort:c};return r&&r.promise(l),t(a).on("load error",function(e,n){clearTimeout(h),t(a).off().remove(),"error"!=e.type&&f?v(f[0],l,i,r):y(null,n||"error",l,i,r),window[s]=u,f&&t.isFunction(u)&&u(f[0]),u=f=void 0}),g(l,i)===!1?(c("abort"),l):(window[s]=function(){f=arguments},a.src=i.url.replace(/\?(.+)=\?/,"?$1="+s),n.head.appendChild(a),i.timeout>0&&(h=setTimeout(function(){c("timeout")},i.timeout)),l)},t.ajaxSettings={type:"GET",beforeSend:b,success:b,error:b,complete:b,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:u,xml:"application/xml, text/xml",html:f,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},t.ajax=function(e){var a,o=t.extend({},e||{}),s=t.Deferred&&t.Deferred();for(i in t.ajaxSettings)void 0===o[i]&&(o[i]=t.ajaxSettings[i]);d(o),o.crossDomain||(a=n.createElement("a"),a.href=o.url,a.href=a.href,o.crossDomain=l.protocol+"//"+l.host!=a.protocol+"//"+a.host),o.url||(o.url=window.location.toString()),j(o);var u=o.dataType,f=/\?.+=\?/.test(o.url);if(f&&(u="jsonp"),o.cache!==!1&&(e&&e.cache===!0||"script"!=u&&"jsonp"!=u)||(o.url=E(o.url,"_="+Date.now())),"jsonp"==u)return f||(o.url=E(o.url,o.jsonp?o.jsonp+"=?":o.jsonp===!1?"":"callback=?")),t.ajaxJSONP(o,s);var C,h=o.accepts[u],p={},m=function(t,e){p[t.toLowerCase()]=[t,e]},x=/^([\w-]+:)\/\//.test(o.url)?RegExp.$1:window.location.protocol,S=o.xhr(),T=S.setRequestHeader;if(s&&s.promise(S),o.crossDomain||m("X-Requested-With","XMLHttpRequest"),m("Accept",h||"*/*"),(h=o.mimeType||h)&&(h.indexOf(",")>-1&&(h=h.split(",",2)[0]),S.overrideMimeType&&S.overrideMimeType(h)),(o.contentType||o.contentType!==!1&&o.data&&"GET"!=o.type.toUpperCase())&&m("Content-Type",o.contentType||"application/x-www-form-urlencoded"),o.headers)for(r in o.headers)m(r,o.headers[r]);if(S.setRequestHeader=m,S.onreadystatechange=function(){if(4==S.readyState){S.onreadystatechange=b,clearTimeout(C);var e,n=!1;if(S.status>=200&&S.status<300||304==S.status||0==S.status&&"file:"==x){u=u||w(o.mimeType||S.getResponseHeader("content-type")),e=S.responseText;try{"script"==u?(1,eval)(e):"xml"==u?e=S.responseXML:"json"==u&&(e=c.test(e)?null:t.parseJSON(e))}catch(i){n=i}n?y(n,"parsererror",S,o,s):v(e,S,o,s)}else y(S.statusText||null,S.status?"error":"abort",S,o,s)}},g(S,o)===!1)return S.abort(),y(null,"abort",S,o,s),S;if(o.xhrFields)for(r in o.xhrFields)S[r]=o.xhrFields[r];var N="async"in o?o.async:!0;S.open(o.type,o.url,N,o.username,o.password);for(r in p)T.apply(S,p[r]);return o.timeout>0&&(C=setTimeout(function(){S.onreadystatechange=b,S.abort(),y(null,"timeout",S,o,s)},o.timeout)),S.send(o.data?o.data:null),S},t.get=function(){return t.ajax(S.apply(null,arguments))},t.post=function(){var e=S.apply(null,arguments);return e.type="POST",t.ajax(e)},t.getJSON=function(){var e=S.apply(null,arguments);return e.dataType="json",t.ajax(e)},t.fn.load=function(e,n,i){if(!this.length)return this;var a,r=this,s=e.split(/\s/),u=S(e,n,i),f=u.success;return s.length>1&&(u.url=s[0],a=s[1]),u.success=function(e){r.html(a?t("
            ").html(e.replace(o,"")).find(a):e),f&&f.apply(r,arguments)},t.ajax(u),this};var T=encodeURIComponent;t.param=function(e,n){var i=[];return i.add=function(e,n){t.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(T(e)+"="+T(n))},C(i,e,n),i.join("&").replace(/%20/g,"+")}}(Zepto),function(t){t.fn.serializeArray=function(){var e,n,i=[],r=function(t){return t.forEach?t.forEach(r):void i.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(i,o){n=o.type,e=o.name,e&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&r(t(o).val())}),i},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(Zepto),function(t){"__proto__"in{}||t.extend(t.zepto,{Z:function(e,n){return e=e||[],t.extend(e,t.fn),e.selector=n||"",e.__Z=!0,e},isZ:function(e){return"array"===t.type(e)&&"__Z"in e}});try{getComputedStyle(void 0)}catch(e){var n=getComputedStyle;window.getComputedStyle=function(t){try{return n(t)}catch(e){return null}}}}(Zepto); \ No newline at end of file diff --git a/examples/katex.html b/examples/katex.html index ebb20de..6cce7a5 100644 --- a/examples/katex.html +++ b/examples/katex.html @@ -2,44 +2,54 @@ - Tex科学公式 - Editor.md examples + Tex科学公式语言 - Editor.md examples +
            -

            Tex科学公式

            +

            Tex科学公式语言

            基于KaTeX.js:http://khan.github.io/KaTeX/

            -

            注:默认使用cloudflare的CDN,有时加载速度会比较慢,可自定义加载地址。

            +

            注:默认使用CloudFlare的CDN,有时加载速度会比较慢,可自定义加载地址。

            -
            - + +$$\sin(\alpha)^{\theta}=\sum_{i=0}^{n}(x^i + \cos(f))$$ + +####自定义KaTeX的URL + +```javascript +//默认使用CloudFlare的CDN,有时加载速度会比较慢 +//或者直接修改源码 +editormd.katexURL = { + js : "your url", + css : "your url" +}; +``` +
            - + + + + \ No newline at end of file diff --git a/examples/multi-languages.html b/examples/multi-languages.html new file mode 100644 index 0000000..0d11396 --- /dev/null +++ b/examples/multi-languages.html @@ -0,0 +1,89 @@ + + + + + 多语言支持 - Editor.md examples + + + + +
            +
            +

            多语言支持(l18n)

            +

            multi-languages for l18n. + +

            +
            +
            + +
            +
            + + + + + + \ No newline at end of file diff --git a/examples/onchange.html b/examples/onchange.html index 6dd9c6f..1d70bed 100644 --- a/examples/onchange.html +++ b/examples/onchange.html @@ -4,6 +4,7 @@ Onchange - Editor.md examples +
            @@ -11,12 +12,11 @@

            Onchange event

            Enter F12 open the develop tools

            -
            - +
            +
            - +
            +
            - +
            +
            - + + \ No newline at end of file diff --git a/examples/readonly.html b/examples/readonly.html new file mode 100644 index 0000000..7b5c600 --- /dev/null +++ b/examples/readonly.html @@ -0,0 +1,54 @@ + + + + + 只读模式 - Editor.md examples + + + + +
            +
            +

            只读模式

            +

            Editor.md read only

            +
            +
            + +
            +
            + + + + + \ No newline at end of file diff --git a/examples/sequence-diagram.html b/examples/sequence-diagram.html index 336b154..2cfcc8e 100644 --- a/examples/sequence-diagram.html +++ b/examples/sequence-diagram.html @@ -2,17 +2,28 @@ - sequenceDiagram - Editor.md examples + SequenceDiagram - Editor.md examples +
            -

            sequenceDiagram 时序图/序列图

            +

            SequenceDiagram 时序图/序列图

            基于SequenceDiagram.js:http://bramp.github.io/js-sequence-diagrams/

            -
            - +```
            - + + + + \ No newline at end of file diff --git a/examples/simple.html b/examples/simple.html index 5eb98f3..3d2119d 100644 --- a/examples/simple.html +++ b/examples/simple.html @@ -4,99 +4,34 @@ Simple - Editor.md examples +
            -

            完整示例

            -

            开启TeX(基于KaTeX)、流程图和时序/序列图支持;

            +

            简单示例

            -
            - - - - - - - - - - -
            -
            - +
            +
            - diff --git a/examples/test.md b/examples/test.md index af14e08..1fd9ae3 100644 --- a/examples/test.md +++ b/examples/test.md @@ -9,18 +9,64 @@ #####Hello world! ######Hello world! -###横线等基本语法 +###字符效果和横线等 ---- -~~删除线~~ -*斜体字* -**强调字体** +~~删除线~~ 删除线(开启识别HTML标签时) +*斜体字* _斜体字_ +**粗体** __粗体__ +***粗斜体*** ___粗斜体___ -> 引用文本 [示例链接](http://localhost/) +上标:X2,下标:O2 + +**缩写(同HTML的abbr标签)** + +> 即更长的单词或短语的缩写形式,前提是开启识别HTML标签时,已默认开启 + +The HTML specification is maintained by the W3C. + +###引用 + +> 引用文本 + +引用的行内混合 + +> 引用:如果想要插入空白换行`即
            标签`,在插入处先键入两个以上的空格然后回车即可,[普通链接](http://localhost/)。 + +###锚点与链接 + +[普通链接](http://localhost/) + +[普通链接带标题](http://localhost/ "普通链接带标题") + +直接链接: + +[锚点链接][anchor-id] + +[anchor-id]: http://www.this-anchor-link.com/ ###多语言代码高亮 +####行内代码 + +执行命令:`npm install marked` + +####缩进风格 + +即缩进四个空格,也做为实现类似`
            `预格式化文本(Preformatted Text)的功能。
            +
            +    
            +    
            +预格式化文本:
            +
            +    | First Header  | Second Header |
            +    | ------------- | ------------- |
            +    | Content Cell  | Content Cell  |
            +    | Content Cell  | Content Cell  |
            +
             ####JS代码 
             
             ```javascript
            @@ -76,18 +122,20 @@ testBox.add("jQuery").remove("jQuery");
                 
             
             ```
            -                
            +
             ###图片
             
             ![ddd](./images/X7t2gyC.png)
            -                    
            -> 引用:如果想要插入空白换行`即
            标签`,在插入处先键入两个以上的空格然后回车即可。 + +图片加链接: + +[![xxx](http://i.imgur.com/5MCMHPl.png)](http://i.imgur.com/5MCMHPl.png) ---- ###列表 -####无序列表(横线) +####无序列表(减号) - 列表一 - 列表二 @@ -95,9 +143,21 @@ testBox.add("jQuery").remove("jQuery"); ####无序列表(星号) -* 一 -* 二 -* 三 +* 列表一 +* 列表二 +* 列表三 + +####无序列表(加号和嵌套) + ++ 列表一 ++ 列表二 + + 列表二-1 + + 列表二-2 + + 列表二-3 ++ 列表三 + * 列表一 + * 列表二 + * 列表三 ####有序列表 @@ -107,7 +167,7 @@ testBox.add("jQuery").remove("jQuery"); ---- -### 绘制表格 +###绘制表格 | 项目 | 价格 | 数量 | | -------- | -----: | :----: | @@ -125,9 +185,39 @@ Content Cell | Content Cell | Content Cell | Content Cell | | Content Cell | Content Cell | -执行命令:`npm install marked` +| Function name | Description | +| ------------- | ------------------------------ | +| `help()` | Display the help window. | +| `destroy()` | **Destroy your computer!** | + +| Item | Value | +| --------- | -----:| +| Computer | $1600 | +| Phone | $12 | +| Pipe | $1 | ---- + +####特殊符号 + +© & ¨ ™ ¡ £ +& < > ¥ € ® ± ¶ § ¦ ¯ « · + +X² Y³ ¾ ¼ × ÷ » + +18ºC " ' + +####标题(用底线的形式) + +This is an H1 +============= + +This is an H2 +------------- + +####反斜杠 + +\*literal asterisks\* ###科学公式 diff --git a/examples/toc.html b/examples/toc.html index ec87a66..8efd585 100644 --- a/examples/toc.html +++ b/examples/toc.html @@ -4,14 +4,15 @@ TOC - Editor.md examples +

            TOC(Table of Contents)示例

            -
            - +
            - -
            +
            - - +
            - + + + + + + + \ No newline at end of file diff --git a/package.json b/package.json index b709219..ead6db2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "editor.md", - "version": "1.0.0", + "version": "1.1.0", "description": "A simple online markdown editor.", "directories": { "doc": "docs", @@ -27,6 +27,8 @@ "homepage": "https://github.com/pandao/editor.md", "devDependencies": { "dateformatter": "^0.1.0", + "grunt": "^0.4.5", + "grunt-webfont": "^0.5.1", "gulp": "^3.8.10", "gulp-autoprefixer": "^2.1.0", "gulp-concat": "^2.4.2", diff --git a/src/js/editormd.js b/src/js/editormd.js index 4bc6826..946cc1d 100644 --- a/src/js/editormd.js +++ b/src/js/editormd.js @@ -1,7 +1,7 @@ /** * @fileOverview Editor.md * @author pandao - * @version 1.0.0 + * @version 1.1.0 */ ;(function(factory) { @@ -33,16 +33,19 @@ "use strict"; - var $ = jQuery; + var $ = (typeof (jQuery) !== "undefined") ? jQuery : Zepto; + + if (typeof ($) === "undefined") { + return ; + } var editormd = function (id, options) { return new editormd.fn.init(id, options); }; - editormd.title = "Editor.md"; - editormd.version = "1.0.0"; - editormd.homePage = "https://github.com/pandao/editor.md"; - editormd.description = "A simple markdown doucment online editor."; + editormd.title = editormd.$name = "Editor.md"; + editormd.version = "1.1.0"; + editormd.homePage = "https://pandao.github.io/editor.md/"; editormd.classPrefix = "editormd-"; editormd.defaults = { @@ -51,30 +54,50 @@ width : "100%", height : "100%", path : "./lib/", - watch : true, + watch : true, + placeholder : "now coding markdown...", + readOnly : false, + lineNumbers : true, + styleActiveLine : true, // 高亮显示当前行 + dialogLockScreen : true, + dialogShowMask : true, + dialogDraggable : true, + dialogMaskBgColor : "#fff", + dialogMaskOpacity : 0.1, onload : function() {}, onchange : function() {}, onfullscreen : function() {}, onfullscreenExit : function() {}, + imageUpload : false, + imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"], + imageUploadURL : "", + crossDomainUpload : false, + uploadCallbackURL : "", + saveHTMLToTextarea : false, toc : true, - tocStartLevel : 2, + tocStartLevel : 1, // 表示从H1开始生成ToC fontSize : "13px", + htmlDecode : false, // 是否开启HTML标签识别 tex : false, flowChart : false, // flowChart.js only support IE9+ sequenceDiagram : false, // sequenceDiagram.js only support IE9+ previewCodeHighlight : true, inRequirejs : false, toolbar : true, - toolbarIcons : [ - "undo", "redo", "|", - "bold", "del", "italic", "quote", "|", - "h1", "h2", "h3", "h4", "h5", "h6", "|", - "list-ul", "list-ol", "hr", "|", - "link", "picture", "code", "code-block-tab", "code-block", "datetime", "|", - "watch", "preview", "fullscreen", "|", - "info" - ], - + 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" + ] + }, + toolbarTitles : {}, + toolbarHandlers : {}, // 工具栏按钮的点击后事件处理 + toolbarIconsClass : { undo : "fa-undo", redo : "fa-repeat", @@ -92,7 +115,8 @@ "list-ol" : "fa-list-ol", hr : "fa-minus", link : "fa-link", - picture : "fa-picture-o", + anchor : "fa-anchor", + image : "fa-picture-o", code : "fa-code", "code-block-tab" : "fa-file-code-o", "code-block" : "fa-file-code-o", @@ -101,13 +125,17 @@ unwatch : "fa-eye", preview : "fa-search", fullscreen : "fa-arrows-alt", + clear : "fa-eraser", info : "fa-info-circle" }, - + + toolbarIconTexts : {}, lang : { - toolbar : { - undo : "撤销", - redo : "重做", + name : "zh-cn", + description : "开源在线Markdown编辑器
            A simple markdown doucment online editor.", + toolbar : { + undo : "撤销(Ctrl+Z)", + redo : "重做(Ctrl+Y)", bold : "粗体", del : "删除线", italic : "斜体", @@ -122,23 +150,71 @@ "list-ol" : "有序列表", hr : "横线", link : "链接", - picture : "图片", + anchor : "锚点", + image : "图片", code : "行内代码", - "code-block-tab" : "代码块(缩进风格)", - "code-block" : "代码块(多语言风格)", + "code-block-tab" : "预格式文本 / 代码块(缩进风格)", + "code-block" : "代码块(多语言风格)", datetime : "日期时间", watch : "关闭实时预览", unwatch : "开启实时预览", - preview : "预览HTML(按ESC还原)", - fullscreen : "全屏(按ESC还原)", + preview : "全窗口预览HTML(可按ESC还原)", + fullscreen : "全屏(按ESC还原)", + clear : "清空", info : "关于" + editormd.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 : "错误:请填写代码内容。" + } } } }; editormd.classNames = { - tex : editormd.classPrefix + "tex" + tex : editormd.classPrefix + "tex" }; + + editormd.dialogZindex = 99999; editormd.$katex = null; editormd.$marked = null; @@ -160,68 +236,70 @@ init : function (id, options) { - options = 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); - var markdownDoc = (settings.markdown === "") ? editor.children("[type=\"text/markdown\"]").html() : settings.markdown; - this.id = id; + var _this = this; + var classPrefix = this.classPrefix = editormd.classPrefix; + var editor = this.editor = $("#" + id); + var settings = this.settings = $.extend(true, editormd.defaults, options); - this.classNames = { + this.id = id; + this.lang = settings.lang; + + var classNames = this.classNames = { textarea : { html : this.classPrefix + "html-textarea", markdown : this.classPrefix + "markdown-textarea" } }; + 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"); - editor.children("[type=\"text/markdown\"]").remove(); + if (markdownTextarea.length < 1) + { + editor.append(""); + markdownTextarea = this.markdownTextarea = editor.children("textarea"); + } - var infoDialogHTML = [ - "
            ", - "", - "
            ", - "

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

            ", - "

            " + editormd.description + "

            ", - "

            Home page: " + editormd.homePage + "

            ", - "

            License: MIT

            ", - "
            ", - "
            " - ].join("\n"); + markdownTextarea.addClass(classNames.textarea.markdown).attr("name", id + "-markdown-doc").attr("placeholder", settings.placeholder); var appendElements = [ - '
              ', - '', - '', - '
              ', - "
              " + (!settings.readOnly) ? "" : "", + ( (settings.saveHTMLToTextarea) ? "" : "" ), + "
              ", + "
              ", + "
              " ].join("\n"); - editor.append(infoDialogHTML).append(appendElements); + editor.append(appendElements).addClass(classPrefix + "vertical"); + + if (settings.markdown !== "") { + markdownTextarea.val(settings.markdown); + } + + this.htmlTextarea = editor.find("." + classNames.textarea.html); this.preview = editor.find("." + classPrefix + "preview"); - this.toolbar = editor.find("." + classPrefix + "toolbar"); this.previewContainer = this.preview.children("." + classPrefix + "preview-container"); - this.infoDialog = editor.find("." + classPrefix + "dialog-info"); this.toolbarIconHandlers = {}; - editor.addClass(classPrefix + "vertical"); - if (!settings.inRequirejs) - { + { this.loadQueues(); } else - { - _this.setCodeMirror(); - _this.setToolbar(); - _this.toolbarHandler(); + { + _this.setCodeMirror(); + _this.setToolbar(); _this.setMarked().loadedDisplay(); } @@ -239,6 +317,13 @@ var loadPath = settings.path; var loadFlowChartOrSequenceDiagram = function() { + + if (editormd.isIE8) + { + _this.setMarked().loadedDisplay(); + + return ; + } if (settings.flowChart || settings.sequenceDiagram) { @@ -289,9 +374,8 @@ editormd.loadScript(loadPath + "codemirror/addons.min", function() { - _this.setCodeMirror(); - _this.setToolbar(); - _this.toolbarHandler(); + _this.setCodeMirror(); + _this.setToolbar(); editormd.loadScript(loadPath + "marked.min", function() { @@ -304,7 +388,7 @@ }); } else - { + { loadFlowChartOrSequenceDiagram(); } }); @@ -324,32 +408,36 @@ */ setCodeMirror : function() { - var settings = this.settings; - + var settings = this.settings; var codeMirrorConfig = { - mode: this.settings.mode, - theme: "default", - tabSize: 4, - dragDrop: false, - autofocus: true, - indentUnit : 4, - lineNumbers: true, - lineWrapping: true, - matchBrackets: true, - indentWithTabs: true, - styleActiveLine: true, - styleSelectedText: true, - autoCloseBrackets: true, - showTrailingSpace: true, - highlightSelectionMatches: { + mode : settings.mode, + theme : "default", + tabSize : 4, + dragDrop : false, + autofocus : true, + readOnly : (settings.readOnly) ? "nocursor" : false, + indentUnit : 4, + lineNumbers : settings.lineNumbers, + lineWrapping : true, + matchBrackets : true, + indentWithTabs : true, + styleActiveLine : settings.styleActiveLine, + styleSelectedText : true, + autoCloseBrackets : true, + showTrailingSpace : true, + highlightSelectionMatches : { showToken: /\w/ } }; - this.codeEditor = editormd.$CodeMirror.fromTextArea(this.editor.find("." + this.classNames.textarea.markdown)[0], codeMirrorConfig); - + this.codeEditor = editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0], codeMirrorConfig); + this.codeMirror = this.editor.find(".CodeMirror"); - this.codeMirror.css("font-size", this.settings.fontSize); + + this.codeMirror.css({ + fontSize : this.settings.fontSize, + width : (!settings.watch) ? "100%" : "50%" + }); return this; }, @@ -360,8 +448,10 @@ */ showToolbar : function() { + var settings = this.settings; + if(settings.readOnly) return ; - this.settings.toolbar = true; + settings.toolbar = true; this.toolbar.show(); this.resize(); @@ -373,9 +463,10 @@ * @returns {editormd} 返回editormd的实例对象 */ - hideToolbar : function() { + hideToolbar : function() { + var settings = this.settings; - this.settings.toolbar = false; + settings.toolbar = false; this.toolbar.hide(); this.resize(); @@ -388,65 +479,727 @@ */ setToolbar : function() { - var settings = this.settings; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; + var settings = this.settings; + + if(settings.readOnly) return ; + + var editor = this.editor; + var preview = this.preview; + var classPrefix = this.classPrefix; + + editor.append('
                '); + + var toolbar = this.toolbar = editor.find("." + classPrefix + "toolbar"); - if (!settings.toolbar) { + if (!settings.toolbar) + { toolbar.hide(); + return ; - } else { + } + else + { toolbar.show(); } - var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; + var icons = settings.toolbarIcons(); + var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; - for (var i = 0, len = settings.toolbarIcons.length; i < len; i++) + for (var i = 0, len = icons.length; i < len; i++) { - var name = settings.toolbarIcons[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]; - menu += "
              • "+((isHeader) ? name : "")+"
              • "; + title = (typeof title === "undefined") ? "" : title; + iconTexts = (typeof iconTexts === "undefined") ? "" : iconTexts; + iconClass = (typeof iconClass === "undefined") ? "" : iconClass; + + menu += "
              • " + + ""+((isHeader) ? name : ( (iconClass === "") ? iconTexts : "") ) + "
              • "; } else { - menu += "
              • |
              • "; + menu += "
              • |
              • "; } } - toolbarMenu.append(menu); + toolbarMenu.html(menu); + + this.setToolbarHandler(); return this; - }, + }, + + /** + * 工具栏图标事件处理对象序列 + * @param {String} name 要获取的事件处理器名称 + * @returns {Object} 返回处理对象序列 + */ + + getToolbarHandles : function(name) { + var _this = this; + var settings = this.settings; + var lang = settings.lang; + var editor = this.editor; + var codeEditor = this.codeEditor; + var cursor = codeEditor.getCursor(); + var selection = codeEditor.getSelection(); + var classPrefix = this.classPrefix; + + var dialogLockScreen = function() { + if (settings.dialogLockScreen) { + $("html,body").css("overflow", "hidden"); + } + }; + + var dialogShowMask = function(dialog) { + dialog.css({ + top : ($(window).height() - dialog.height()) / 2 + "px", + left : ($(window).width() - dialog.width()) / 2 + "px" + }); + + if (settings.dialogShowMask) { + editor.find("." + classPrefix + "mask").css("z-index", parseInt(dialog.css("z-index")) - 1).show(); + } + }; + + var toolbarHandlers = this.toolbarHandlers = { + undo : function() { + codeEditor.undo(); + }, + redo : function() { + codeEditor.redo(); + }, + bold : function() { + + codeEditor.replaceSelection("**" + selection + "**"); + + if(selection === "") { + codeEditor.setCursor(cursor.line, cursor.ch + 2); + } + }, + del : function() { + + codeEditor.replaceSelection("~~" + selection + "~~"); + + if(selection === "") { + codeEditor.setCursor(cursor.line, cursor.ch + 2); + } + }, + + italic : function() { + codeEditor.replaceSelection("*" + selection + "*"); + + if(selection === "") { + codeEditor.setCursor(cursor.line, cursor.ch + 1); + } + }, + + quote : function() { + codeEditor.replaceSelection((selection === "") ? ["> " + selection, ""].join("\n") : "> " + selection); + codeEditor.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); + }, + + h1 : function() { + codeEditor.replaceSelection("#" + selection); + }, + + h2 : function() { + codeEditor.replaceSelection("##" + selection); + }, + + h3 : function() { + codeEditor.replaceSelection("###" + selection); + }, + + h4 : function() { + codeEditor.replaceSelection("####" + selection); + }, + + h5 : function() { + codeEditor.replaceSelection("#####" + selection); + }, + + h6 : function() { + codeEditor.replaceSelection("######" + selection); + }, + + "list-ul" : function() { + + if (selection === "") + { + codeEditor.replaceSelection("- " + selection); + } + else + { + var selectionText = selection.split("\n"); + + for (var i = 0, len = selectionText.length; i < len; i++) + { + selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; + } + + codeEditor.replaceSelection(selectionText.join("\n")); + } + }, + + "list-ol" : function() { + + if(selection === "") + { + codeEditor.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]; + } + + codeEditor.replaceSelection(selectionText.join("\n")); + } + }, + + hr : function() { + codeEditor.replaceSelection("------------"); + }, + + link : function() { + 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; + } + + codeEditor.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() { + + 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; + } + + codeEditor.replaceSelection("[" + title + "][" + name + "]\n[" + name + "]: " + url + ""); + + if (selection === "") { + codeEditor.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() { + 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://") + { + codeEditor.replaceSelection("![" + alt + "](" + url + " \"" + alt + "\")"); + } + else + { + codeEditor.replaceSelection("[![" + alt + "](" + url + " \"" + alt + "\")](" + link + " \"" + alt + "\")"); + } + + if (alt === "") { + codeEditor.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() { + if (settings.crossDomainUpload) { + imageDialog.loading(false); + return ; + } + + 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() { + + codeEditor.replaceSelection("`" + selection + "`"); + + if (selection === "") { + codeEditor.setCursor(cursor.line, cursor.ch + 1); + } + + }, + + "code-block-tab" : function() { + var tabCodeBlockDialogName = classPrefix + "dialog-tab-code-block", tabCodeBlockDialog; + + if (editor.find("." + tabCodeBlockDialogName).length > 0) + { + tabCodeBlockDialog = editor.find("." + tabCodeBlockDialogName); + tabCodeBlockDialog.find("textarea").val(""); + + 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]; + } + + codeEditor.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() { + + 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(""); + + 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; + + codeEditor.replaceSelection(["```" + langName, codeTexts, "```"].join("\n")); + + if (langName === "") { + codeEditor.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() { + var date = new Date(); + var langName = settings.lang.name; + codeEditor.replaceSelection(editormd.dateFormat() + " " + editormd.dateFormat((langName === "zh-cn" || langName === "zh-tw") ? "cn-week-day" : "week-day")); + }, + + 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 && typeof toolbarIconHandlers[name] !== "undefined") ? toolbarHandlers[name] : toolbarHandlers; + }, /** * 工具栏图标事件处理器 * @returns {editormd} 返回editormd的实例对象 */ - toolbarHandler : function() { - var settings = this.settings; + setToolbarHandler : function() { + var _this = this; + var settings = this.settings; - if (!settings.toolbar) { + if (!settings.toolbar || settings.readOnly) { return ; - } + } - var _this = this; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var codeEditor = this.codeEditor; - var codeMirror = this.codeMirror; - var previewContainer = this.previewContainer; - var toolbarIcons = this.toolbarIcons = toolbar.find("." + this.classPrefix + "menu .fa"); + 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); + var icon = $(this).children(".fa"); var name = icon.attr("name"); var cursor = codeEditor.getCursor(); var selection = codeEditor.getSelection(); @@ -454,196 +1207,306 @@ if (name === "") { return ; } + + _this.activeIcon = icon; - //console.log("toolbarIcons.click =>", name); - - var toolbarIconHandlers = _this.toolbarIconHandlers = { - undo : function() { - codeEditor.undo(); - }, - redo : function() { - codeEditor.redo(); - }, - bold : function() { - - codeEditor.replaceSelection("**" + selection + "**"); + if (typeof toolbarIconHandlers[name] !== "undefined") + { + toolbarIconHandlers[name](); + } + 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(); + } - if(selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 2); - } - }, - del : function() { + return false; - codeEditor.replaceSelection("~~" + selection + "~~"); + }); - if(selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 2); - } - }, + 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 + }; - italic : function() { - codeEditor.replaceSelection("*" + selection + "*"); + options = $.extend(true, defaults, options); - if(selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 1); - } - }, + 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 = "
                "; - quote : function() { - codeEditor.replaceSelection((selection === "") ? ["> " + selection, ""].join("\n") : "> " + selection); - codeEditor.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); - }, + if (options.title !== "") + { + html += "
                "; + html += "" + options.title + ""; + html += "
                "; + } - h1 : function() { - codeEditor.replaceSelection("#" + selection); - }, + if (options.closed) + { + html += ""; + } - h2 : function() { - codeEditor.replaceSelection("##" + selection); - }, + html += "
                " + options.content; - h3 : function() { - codeEditor.replaceSelection("###" + selection); - }, + if (options.footer || typeof options.footer === "string") + { + html += "
                " + ( (typeof options.footer === "boolean") ? "" : options.footer) + "
                "; + } - h4 : function() { - codeEditor.replaceSelection("####" + selection); - }, + html += "
                "; - h5 : function() { - codeEditor.replaceSelection("#####" + selection); - }, + html += "
                "; + html += "
                "; + html += "
                "; - h6 : function() { - codeEditor.replaceSelection("######" + selection); - }, + editor.append(html); - "list-ul" : function() { + var dialog = editor.find("." + dialogName); + + dialog.lockScreen = function(lock) { + if (options.lockScreen) + { + $("html,body").css("overflow", (lock) ? "hidden" : ""); + } + + return dialog; + }; - if (selection === "") - { - codeEditor.replaceSelection("- " + selection); - } - else - { - var selectionText = selection.split("\n"); + dialog.showMask = function() { + if (options.mask) + { + editor.find("." + classPrefix + "mask").css(options.maskStyle).css("z-index", editormd.dialogZindex - 1).show(); + } + return dialog; + }; - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; - } + dialog.hideMask = function() { + if (options.mask) + { + editor.find("." + classPrefix + "mask").hide(); + } + + return dialog; + }; - codeEditor.replaceSelection(selectionText.join("\n")); - } - }, + dialog.loading = function(show) { + var loading = dialog.find("." + classPrefix + "dialog-mask"); + loading[(show) ? "show" : "hide"](); + + return dialog; + }; + + dialog.lockScreen(true).showMask(); - "list-ol" : function() { + 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 + }); - if(selection === "") - { - codeEditor.replaceSelection("1. " + selection); - } - else - { - var selectionText = selection.split("\n"); + var dialogPosition = function(){ + dialog.css({ + top : ($(window).height() - dialog.height()) / 2 + "px", + left : ($(window).width() - dialog.width()) / 2 + "px" + }); + }; - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : (i+1) + ". " + selectionText[i]; - } + dialogPosition(); - codeEditor.replaceSelection(selectionText.join("\n")); - } - }, + $(window).resize(dialogPosition); - hr : function() { - codeEditor.replaceSelection("------------"); - }, + dialog.children("." + classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { + dialog.hide().lockScreen(false).hideMask(); + }); - link : function() { - codeEditor.replaceSelection("[" + selection + "](" + selection + " \""+selection+"\")"); - }, + if (typeof options.buttons == "object") + { + var footer = dialog.footer = dialog.find("." + classPrefix + "dialog-footer"); - picture : function() { - codeEditor.replaceSelection("![" + selection + "](" + selection + " \""+selection+"\")"); - }, + for (var key in options.buttons) + { + var btn = options.buttons[key]; + var btnClassName = classPrefix + key + "-btn"; - code : function() { + footer.append(""); + btn[1] = $.proxy(btn[1], dialog); + footer.children("." + btnClassName).bind(mouseOrTouch("click", "touchend"), btn[1]); + } + } - codeEditor.replaceSelection("`" + selection + "`"); + if (options.title !== "" && options.drag) + { + var posX, posY; + var dialogHeader = dialog.children("." + classPrefix + "dialog-header"); - if (selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 1); - } + 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); - "code-block-tab" : function() { - codeEditor.replaceSelection(" " + selection); - }, + document.onmousemove = moveAction; + }); - "code-block" : function() { + var userCanSelect = function (obj) { + obj.removeClass(classPrefix + "user-unselect").off("selectstart"); + } - codeEditor.replaceSelection(["```", selection, "```"].join("\n")); + var userUnselect = function (obj) { + obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) { // selectstart for IE + return false; + }); + } - if (selection === "") { - codeEditor.setCursor(cursor.line, cursor.ch + 3); - } + var moveAction = function (e) { + e = e || window.event; //IE - }, + var left, top, nowLeft = parseInt(dialog[0].style.left), nowTop = parseInt(dialog[0].style.top); - datetime : function() { - var date = new Date(); - codeEditor.replaceSelection(editormd.dateFormat() + " " + editormd.dateFormat("cn-week-day")); - }, - - watch : function() { - if (_this.settings.watch) - { - _this.unwatch(); - } - else - { - _this.watch(); + 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; + } - event.preventDefault(); + if( nowTop >= 0 ) { + top = e.clientY - posY; + } else { + top = 0; + document.onmousemove = null; + } - return false; - }, - preview : function() { - - _this.previewing(); - event.preventDefault(); - + document.onselectstart = function() { return false; - }, + }; - fullscreen : function() { - - _this.fullscreen(); - event.preventDefault(); + userUnselect($("body")); + userUnselect(dialog); + dialog[0].style.left = left + "px"; + dialog[0].style.top = top + "px"; + } - return false; - }, + document.onmouseup = function() { + userCanSelect($("body")); + userCanSelect(dialog); - info : function() { - _this.showInfoDialog(); - event.preventDefault(); + document.onselectstart = null; + document.onmousemove = null; + }; - return false; - } + 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); }; - toolbarIconHandlers[name](); + dialogHeader.touchDraggable(); + } - codeEditor.focus(); - event.preventDefault(); + editormd.dialogZindex += 2; - return false; + return dialog; + }, + + /** + * 创建关于Editor.md的对话框 + * @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.find("." + classPrefix + "dialog-info"); + + infoDialog.find("." + classPrefix + "dialog-close").bind(editormd.mouseOrTouch("click", "touchend"), function() { + _this.hideInfoDialog(); }); + + infoDialog.css("border", (editormd.isIE8) ? "1px solid #ddd" : ""); return this; }, @@ -656,7 +1519,29 @@ showInfoDialog : function() { $("html,body").css("overflow-x", "hidden"); - this.editor.find("." + this.classPrefix + "dialog-info").fadeIn(); + + var _this = this; + var editor = this.editor; + var classPrefix = this.classPrefix; + var infoDialog = this.infoDialog = editor.find("." + classPrefix + "dialog-info"); + + if (infoDialog.length < 1) + { + this.createInfoDialog(); + } + + infoDialog.show(); + + 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; }, @@ -668,7 +1553,7 @@ hideInfoDialog : function() { $("html,body").css("overflow-x", ""); - this.editor.find("." + this.classPrefix + "dialog-info").fadeOut(); + this.infoDialog.hide(); return this; }, @@ -686,9 +1571,9 @@ renderer : editormd.markedRenderer(markdownToC), gfm : true, tables : true, - breaks : false, + breaks : true, pedantic : false, - sanitize : true, + sanitize : (this.settings.htmlDecode) ? false : true, // 关闭忽略HTML标签,即开启识别HTML标签,默认为false smartLists : true, smartypants : true }); @@ -696,6 +1581,36 @@ return this; }, + + /** + * 编辑器界面重建,用于动态语言包或模块加载等 + * @returns {editormd} 返回editormd的实例对象 + */ + + recreateEditor : function() { + var _this = this; + var editor = this.editor; + var settings = this.settings; + var toolbarIcons = settings.toolbarIcons(); + + if (typeof this.infoDialog !== "undefined") { + this.infoDialog.remove(); + } + + if (typeof toolbarIcons["info"] !== "undefined") { + createInfoDialog(); + } + + if (!settings.readOnly) { + this.getToolbarHandles(); + this.setToolbar(); + } + + this.resize(); + + return this; + }, + /** * 加载队列完成之后的显示处理 * @returns {editormd} 返回editormd的实例对象 @@ -708,34 +1623,44 @@ var _this = this; var editor = this.editor; var preview = this.preview; - var toolbar = this.toolbar; var settings = this.settings; var codeEditor = this.codeEditor; var codeMirror = this.codeMirror; var previewContainer = this.previewContainer; var mouseOrTouch = editormd.mouseOrTouch; - var htmlTextarea = this.htmlTextarea = editor.find("."+this.classNames.textarea.html); - var markdownTextarea = this.markdownTextarea = editor.find("."+this.classNames.textarea.markdown); editor.css("background", "none"); this.saveToTextareas(); - preview.show(); - - if (settings.previewCodeHighlight) - { - previewContainer.find("pre").addClass("prettyprint linenums"); - prettyPrint(); + if(settings.watch) { + preview.show(); } - if (settings.flowChart) { - previewContainer.find(".flowchart").flowChart(); - } + var codeHighlight = function() { + if (settings.previewCodeHighlight) + { + previewContainer.find("pre").addClass("prettyprint linenums"); + prettyPrint(); + } + }; - if (settings.sequenceDiagram) { - previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } + var flowChartAndSequenceDiagramHandle = function() { + + if (editormd.isIE8) return ; + + if (settings.flowChart) { + previewContainer.find(".flowchart").flowChart(); + } + + if (settings.sequenceDiagram) { + previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); + } + }; + + codeHighlight(); + + flowChartAndSequenceDiagramHandle(); var katexHandle = function() { previewContainer.find("." + editormd.classNames.tex).each(function(){ @@ -756,26 +1681,19 @@ } } - editor.data({ - oldWidth : editor.outerWidth(), - oldHeight : editor.outerHeight() - }); + editor.data("oldWidth", editor.width()).data("oldHeight", editor.height()); // 为了兼容Zepto + + this.resize(); - this.resize(); - $(window).resize(function(){ _this.resize(); }); - $.proxy(this.settings.onload, this)(); - - editor.find("." + this.classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { - _this.hideInfoDialog(); - }); + $.proxy(settings.onload, this)(); var codeEditorBindScroll = function() { codeMirror.find(".CodeMirror-scroll").bind(mouseOrTouch("scroll", "touchmove"), function() { - var height = $(this).outerHeight(); + var height = $(this).height(); var scrollTop = $(this).scrollTop(); var percent = (scrollTop / $(this)[0].scrollHeight); @@ -800,7 +1718,7 @@ var previewBindScroll = function() { preview.bind(mouseOrTouch("scroll", "touchmove"), function() { - var height = $(this).outerHeight(); + var height = $(this).height(); var scrollTop = $(this).scrollTop(); var percent = (scrollTop / $(this)[0].scrollHeight); var codeView = codeMirror.find(".CodeMirror-scroll"); @@ -823,9 +1741,20 @@ var previewUnbindScroll = function() { preview.unbind(mouseOrTouch("scroll", "touchmove")); }; + + codeMirror.bind({ + mouseover : codeEditorBindScroll, + mouseout : codeEditorUnbindScroll, + touchstart : codeEditorBindScroll, + touchend : codeEditorUnbindScroll + }); - codeMirror.hover(codeEditorBindScroll, codeEditorUnbindScroll).bind("touchstart", codeEditorBindScroll).bind("touchend", codeEditorUnbindScroll); - preview.hover(previewBindScroll, previewUnbindScroll).bind("touchstart", previewBindScroll).bind("touchend", previewUnbindScroll); + preview.bind({ + mouseover : previewBindScroll, + mouseout : previewUnbindScroll, + touchstart : previewBindScroll, + touchend : previewUnbindScroll + }); codeEditor.on("change", function(cm, changeObj) { @@ -834,21 +1763,12 @@ } _this.saveToTextareas(); - - if (settings.previewCodeHighlight) { - preview.find("pre").addClass("prettyprint linenums"); - prettyPrint(); - } - - if (settings.flowChart) { - previewContainer.find(".flowchart").flowChart(); - } - if (settings.sequenceDiagram) { - previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } + codeHighlight(); + + flowChartAndSequenceDiagramHandle(); - if (settings.tex) { + if (settings.tex) { katexHandle(); } @@ -866,10 +1786,7 @@ width : function(width) { - this.editor.css({ - width : (typeof width === "number") ? width + "px" : width - }); - + this.editor.css("width", (typeof width === "number") ? width + "px" : width); this.resize(); return this; @@ -883,10 +1800,7 @@ height : function(height) { - this.editor.css({ - height : (typeof height === "number") ? height + "px" : height - }); - + this.editor.css("height", (typeof height === "number") ? height + "px" : height); this.resize(); return this; @@ -908,7 +1822,6 @@ var preview = this.preview; var toolbar = this.toolbar; var settings = this.settings; - var infoDialog = this.infoDialog; var codeEditor = this.codeEditor; var codeMirror = this.codeMirror; @@ -919,32 +1832,29 @@ height : (typeof height === "number") ? height + "px" : height }); } - - infoDialog.css({ - top : (editor.height() - infoDialog.height()) / 2, - left : (editor.width() - infoDialog.width()) / 2 - }); - if (settings.toolbar) { - codeMirror.css("margin-top", toolbar.outerHeight()).outerHeight(editor.height() - toolbar.outerHeight()); + if (settings.toolbar && !settings.readOnly) { + codeMirror.css("margin-top", toolbar.height() + 1).height(editor.height() - toolbar.height()); } else { - codeMirror.css("margin-top", 0).outerHeight(editor.height()); + codeMirror.css("margin-top", 0).height(editor.height()); } - if(this.settings.watch) + codeMirror.find(".CodeMirror-gutters").height(codeMirror.height()); + + if(settings.watch) { - codeMirror.outerWidth(editor.width() / 2); - preview.outerWidth(editor.width() / 2); + codeMirror.width(editor.width() / 2); + preview.width(editor.width() / 2); - if (settings.toolbar) { - preview.css("top", toolbar.outerHeight()).outerHeight(editor.height() - toolbar.outerHeight()); + if (settings.toolbar && !settings.readOnly) { + preview.css("top", toolbar.height()).height(editor.height() - toolbar.height()); } else { - preview.css("top", 0).outerHeight(editor.height()); + preview.css("top", 0).height(editor.height()); } } else { - codeMirror.outerWidth(editor.width()); + codeMirror.width(editor.width()); preview.hide(); } @@ -966,18 +1876,105 @@ var markdownToC = this.markdownToC = []; var newMarkdownDoc = editormd.$marked(codeEditor.getValue(), {renderer : editormd.markedRenderer(markdownToC)}); - this.markdownTextarea.html(codeEditor.getValue()); - this.htmlTextarea.html(newMarkdownDoc); + this.markdownTextarea.val(codeEditor.getValue()); - previewContainer.html(newMarkdownDoc); + if (settings.saveHTMLToTextarea) { + this.htmlTextarea.html(newMarkdownDoc); + } + + if(settings.watch) + { + previewContainer.html(newMarkdownDoc); - if (settings.toc) { - editormd.markdownToCRenderer(markdownToC, previewContainer, settings.tocStartLevel); + if (settings.toc) { + editormd.markdownToCRenderer(markdownToC, previewContainer, settings.tocStartLevel); + } } return this; }, + /** + * 聚焦光标位置 + * @returns {editormd} 返回editormd的实例对象 + */ + + focus : function() { + this.codeEditor.focus(); + + return this; + }, + + /** + * 设置光标的位置 + * @param {Object} cursor 要设置的光标位置键值对象,例:{line:1, ch:0} + * @returns {editormd} 返回editormd的实例对象 + */ + + setCursor : function(cursor) { + this.codeEditor.setCursor(cursor); + + return this; + }, + + /** + * 获取当前光标的位置 + * @returns {Cursor} 返回一个光标Cursor对象 + */ + + getCursor : function() { + return this.codeEditor.getCursor(); + }, + + /** + * 设置光标选中的范围 + * @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; + }, + + /** + * 获取光标选中的文本 + * @returns {String} 返回选中文本的字符串形式 + */ + + getSelection : function() { + return this.codeEditor.getSelection(); + }, + + /** + * 替换当前光标选中的文本或在当前光标处插入新字符 + * @param {String} value 要插入的字符值 + * @returns {editormd} 返回editormd的实例对象 + */ + + replaceSelection : function(value) { + this.codeEditor.replaceSelection(value); + + return this; + }, + + /** + * 在当前光标处插入新字符 + * + * 同replaceSelection()方法 + * @param {String} value 要插入的字符值 + * @returns {editormd} 返回editormd的实例对象 + */ + + insertValue : function(value) { + this.replaceSelection(value); + + return this; + }, + /** * 设置和传入编辑器的markdown源文档 * @param {String} md 要传入的markdown源文档 @@ -1001,12 +1998,56 @@ }, /** - * 获取解析后的HTML源码 + * 清空编辑器 * @returns {editormd} 返回editormd的实例对象 */ + clear : function() { + this.codeEditor.setValue(""); + this.saveToTextareas(); + + return this; + }, + + /** + * 获取解析后存放在Textarea的HTML源码 + * @returns {String} 返回HTML源码 + */ + getHTML : function() { - return this.editor.find("." + this.classNames.textarea.html).val(); + if (!settings.saveHTMLToTextarea) + { + alert("Error: settings.saveHTMLToTextarea == false"); + + return false; + } + + return this.htmlTextarea.html(); + }, + + /** + * getHTML()的别名 + * @returns {editormd} 返回HTML源码 + */ + + getTextareaSavedHTML : function() { + return this.getHTML(); + }, + + /** + * 获取预览窗口的HTML源码 + * @returns {editormd} 返回editormd的实例对象 + */ + + getPreviewedHTML : function() { + if (!settings.watch) + { + alert("Error: settings.watch == false"); + + return false; + } + + return this.preivewContainer.html(); }, /** @@ -1026,7 +2067,7 @@ icon.parent().attr("title", this.settings.lang.toolbar.watch); icon.removeClass(unWatchIcon).addClass(watchIcon); - this.codeMirror.css("border-right", "1px solid #ddd").outerWidth(this.editor.width() / 2); + this.codeMirror.css("border-right", "1px solid #ddd").width(this.editor.width() / 2); this.saveToTextareas().resize(); @@ -1053,7 +2094,7 @@ icon.parent().attr("title", this.settings.lang.toolbar.unwatch); icon.removeClass(watchIcon).addClass(unWatchIcon); - this.codeMirror.css("border-right", "none").outerWidth(this.editor.width()); + this.codeMirror.css("border-right", "none").width(this.editor.width()); this.resize(); @@ -1116,17 +2157,20 @@ toolbar.find(".fa[name=preview]").toggleClass("active"); codeMirror.toggle(); - if(codeMirror.is(":hidden")) + 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(); + }); preview.show().css({ top : 0, - //borderTop : "none", width : editor.width(), height : editor.height() }); @@ -1155,8 +2199,9 @@ 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; + this.state.preview = false; codeMirror.show(); @@ -1170,12 +2215,13 @@ preview.hide(); } + previewCloseBtn.hide().bind(editormd.mouseOrTouch("click", "touchend")); + preview.css({ background : null, - //borderTop : "1px solid #ddd", width : editor.width() / 2, - height : editor.height() - toolbar.outerHeight(), - top : (settings.toolbar) ? toolbar.outerHeight() : 0 + height : editor.height() - toolbar.height(), + top : (settings.toolbar) ? toolbar.height() : 0 }); return this; @@ -1213,6 +2259,7 @@ }).addClass(fullscreenClass); this.resize(); + $.proxy(this.settings.onfullscreen, this)(); } else @@ -1259,6 +2306,7 @@ }).removeClass(fullscreenClass); this.resize(); + $.proxy(this.settings.onfullscreenExit, this)(); @@ -1337,16 +2385,17 @@ /** * 生成TOC(Table of Contents) - * @param {Array} toc 从marked获取的TOC数组列表 - * @param {Element} container 插入TOC的容器元素 - * @param {Integer} startLevel Hx 起始层级 + * @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 || 2; + startLevel = startLevel || 1; for (var i = 0, len = toc.length; i < len; i++) { @@ -1360,7 +2409,7 @@ if (level > lastLevel) { html += ""; - } + } else if (level < lastLevel) { html += (new Array(lastLevel - level + 2)).join("
            • "); @@ -1374,13 +2423,18 @@ lastLevel = level; } - container.find('.markdown-toc-list').html("").html(html); + var tocContainer = container.find('.markdown-toc'); + + tocContainer.children('.markdown-toc-list').html("").html(html); + + return tocContainer; }; /** * 将Markdown文档解析为HTML用于前台显示 - * @param {String} id 用于显示HTML的对象ID - * @param {Object} [options={}] 配置选项,可选 + * @param {String} id 用于显示HTML的对象ID + * @param {Object} [options={}] 配置选项,可选 + * @returns {Object} div 返回jQuery对象元素 */ editormd.markdownToHTML = function(id, options) { @@ -1390,6 +2444,7 @@ toc : true, tocStartLevel : 2, markdown : "", + htmlDecode : false, inRequirejs : false, tex : false, flowChart : false, @@ -1398,30 +2453,39 @@ }; editormd.$marked = marked; - - var settings = $.extend(true, defaults, options); + var div = $("#" + id); - var saveTo = div.find("[type=\"text/markdown\"]"); - var markdownDoc = (settings.markdown === "") ? saveTo.html() : settings.markdown; + var settings = div.settings = $.extend(true, defaults, options); + var saveTo = div.find("textarea"); + var markdownDoc = (settings.markdown === "") ? saveTo.val() : settings.markdown; var markdownToC = []; + var markedOptions = { renderer : editormd.markedRenderer(markdownToC), gfm : true, tables : true, - breaks : false, + breaks : true, pedantic : false, - sanitize : true, + sanitize : (settings.htmlDecode) ? false : true, // 是否忽略HTML标签,即是否开启HTML标签解析,为了安全性,默认不开启 smartLists : true, smartypants : true }; var markdownParsed = marked(markdownDoc, markedOptions); - saveTo.html(markdownDoc); - div.addClass("markdown-body").append(markdownParsed); - + if (editormd.isIE8) + { + saveTo.val(markdownDoc); + } + else + { + saveTo.html(markdownDoc); + } + + div.addClass("markdown-body " + this.classPrefix + "html-preview").append(markdownParsed); + if (settings.toc) { - editormd.markdownToCRenderer(markdownToC, div, settings.tocStartLevel); + div.tocContainer = this.markdownToCRenderer(markdownToC, div, settings.tocStartLevel); } if (settings.previewCodeHighlight) @@ -1429,13 +2493,16 @@ div.find("pre").addClass("prettyprint linenums"); prettyPrint(); } + + if (!editormd.isIE8) + { + if (settings.flowChart) { + div.find(".flowchart").flowChart(); + } - if (settings.flowChart) { - div.find(".flowchart").flowChart(); - } - - if (settings.sequenceDiagram) { - div.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); + if (settings.sequenceDiagram) { + div.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); + } } if (settings.tex) @@ -1448,7 +2515,7 @@ }; if (!settings.inRequirejs) { - editormd.loadKaTeX(function(){ + this.loadKaTeX(function(){ editormd.$katex = katex; katexHandle(); }); @@ -1456,10 +2523,55 @@ katexHandle(); } } + + div.getMarkdown = function() { + return (editormd.isIE8) ? saveTo.val() : saveTo.html(); + }; + + 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 - // 与Gulpfile.js对应 + // for Requires.js and Gulpfile.js editormd.codeMirrorModules = { modes : [ "css", @@ -1491,7 +2603,7 @@ "xquery", "yaml", "erlang", - "jade", + "jade" ], addons : [ @@ -1555,8 +2667,6 @@ } editormd.loadCSS(editormd.katexURL.css); - - //modules.push(editormd.katexURL.js + ".js"); return modules; }; @@ -1588,40 +2698,47 @@ document.body.appendChild(css); } }; - + + editormd.isIE = (navigator.appName == "Microsoft Internet Explorer"); + editormd.isIE8 = (editormd.isIE && navigator.appVersion.match(/8./i) == "8."); + /** * 动态加载JS文件的方法 * @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 = document.createElement("script"); - script.type = "text/javascript"; + var script = null; + script = document.createElement("script"); + script.id = fileName.replace(/[\./]+/g, "-"); + script.type = "text/javascript"; + script.src = fileName + ".js"; - script.onload = script.onreadystatechange = function() { - if(script.readyState) - { - if (script.readyState === "loaded" || script.readyState === "complete") + if (editormd.isIE8) { + + script.onreadystatechange = function() { + if(script.readyState) { - script.onreadystatechange = null; - callback(); - } - } - else - { + if (script.readyState === "loaded" || script.readyState === "complete") + { + script.onreadystatechange = null; + callback(); + } + } + }; + } + else + { + script.onload = function() { callback(); - } - }; - - script.src = fileName + ".js"; - - //console.log("script.src =>", script.src); + }; + } if (into === "head") { document.getElementsByTagName("head")[0].appendChild(script); @@ -1633,7 +2750,7 @@ // 使用国外的CDN,加载速度有时会很慢,或者自定义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", + js : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min" }; /** @@ -1669,7 +2786,7 @@ } return eventType; - }; + }; /** * 日期时间的格式化方法 @@ -1732,7 +2849,8 @@ case "week-day" : case "wd" : - datefmt = weekDay; + var weekDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + datefmt = weekDays[weekDay]; break; case "day" : @@ -1777,7 +2895,7 @@ default: datefmt = fymd + " " + hms; break; - } + }; return datefmt; }; diff --git a/src/js/languages/en.js b/src/js/languages/en.js new file mode 100644 index 0000000..ded3f97 --- /dev/null +++ b/src/js/languages/en.js @@ -0,0 +1,110 @@ +(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/src/js/languages/zh-tw.js b/src/js/languages/zh-tw.js new file mode 100644 index 0000000..2e8c658 --- /dev/null +++ b/src/js/languages/zh-tw.js @@ -0,0 +1,110 @@ +(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/src/scss/editormd.codemirror.scss b/src/scss/editormd.codemirror.scss index fec6428..ad98b4d 100644 --- a/src/scss/editormd.codemirror.scss +++ b/src/scss/editormd.codemirror.scss @@ -1,6 +1,6 @@ @charset "UTF-8"; -.editormd .CodeMirror, .editormd-preview { +.editormd .CodeMirror, #{$prefix}preview { display: inline-block; width: 50%; height: 100%; @@ -9,7 +9,7 @@ margin: 0; } -.editormd-preview { +#{$prefix}preview { position: absolute; top: 35px; right: 0; @@ -26,7 +26,7 @@ .CodeMirror { z-index: 10; float: left; - border-right: 1px solid #ddd; + border-right: 1px solid $borderColor; font-size: 13px; font-family: Consolas, 'Monaco', courier, monospace; line-height: 1.6; @@ -41,7 +41,7 @@ background: #70B7FF; } - .CodeMirror, .CodeMirror-scroll, .editormd-preview { + .CodeMirror, .CodeMirror-scroll, #{$prefix}preview { -webkit-overflow-scrolling : touch; } @@ -56,7 +56,7 @@ } .CodeMirror-empty { - outline: 1px solid #c22; + //outline: 1px solid #c22; &.CodeMirror-focused { outline: none; diff --git a/src/scss/editormd.dialog.scss b/src/scss/editormd.dialog.scss index 37726e6..6ede292 100644 --- a/src/scss/editormd.dialog.scss +++ b/src/scss/editormd.dialog.scss @@ -1,27 +1,21 @@ @charset "UTF-8"; -.editormd-dialog { - position: absolute; - top: 38%; - left: 33%; - z-index: 101; - width: 34%; - height: 24%; +#{$prefix}dialog { + color: $color; + position: fixed; + z-index: 99999; display: none; @include border-radius(3px); @include box-shadow(0 0 10px rgba(0, 0, 0, 0.3)); + //@include user-select(none); background: #fff; + font-size: 14px; } -.editormd-dialog-info { - width: 420px; - height: 160px; -} - -.editormd-dialog-container { - padding: 20px 25px 25px; +#{$prefix}dialog-container { + position: relative; + padding: 20px; line-height: 1.6; - border: 1px solid #ddd\0; h1 { font-size: 24px; @@ -38,18 +32,130 @@ font-size: 12px; color: #999; } + } + + select { + color: #999; + padding: 3px 8px; + border: 1px solid $borderColor; } } -.editormd-dialog-close { +#{$prefix}dialog-close { position: absolute; - top: 10px; - right: 10px; + top: 12px; + right: 15px; font-size: 18px; color: #ccc; + @include transition(color 300ms ease-out); &:hover { color: #999; - @include transition(all 300ms ease-out); + } +} + +#{$prefix}dialog-header { + padding: 11px 20px; + border-bottom: 1px solid #eee; + @include transition(background 300ms ease-out); + + &:hover { + background: #f6f6f6; + } +} + +#{$prefix}dialog-title { + font-size: 14px; +} + +#{$prefix}dialog-footer { + padding: 10px 0 0 0; + text-align: right; +} + +#{$prefix}dialog-info { + width: 420px; + + h1 { + font-weight: normal; + } + + #{$prefix}dialog-container { + padding: 20px 25px 25px; + } + + #{$prefix}dialog-close { + top: 10px; + right: 10px; + } +} + +#{$prefix}mask, +#{$prefix}container-mask, +#{$prefix}dialog-mask { + display: none; + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; +} + +#{$prefix}mask, +#{$prefix}container-mask, +#{$prefix}dialog-mask-bg { + background: #fff; + opacity: 0.5; + filter: alpha(opacity=50); +} + +#{$prefix}mask { + position: fixed; + background: #000; + @include opacity(0.2); + z-index: 99998; +} + +#{$prefix}container-mask { + @include opacity(0.1); +} + +#{$prefix}container-mask, +#{$prefix}dialog-mask-con { + background: url(../images/loading.gif) no-repeat center center; + @include background-size(32px 32px); +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) { + #{$prefix}container-mask, + #{$prefix}dialog-mask-con { + background-image: url(../images/loading@2x.gif); + } +} + +@media only screen and (-webkit-min-device-pixel-ratio: 3), only screen and (min-device-pixel-ratio: 3) { + #{$prefix}container-mask, + #{$prefix}dialog-mask-con { + background-image: url(../images/loading@3x.gif); } } + +#{$prefix}dialog-code-block, +#{$prefix}dialog-tab-code-block { + textarea { + width: 100%; + height: 400px; + margin-bottom: 6px; + overflow: auto; + border: 1px solid #eee; + background: #fff; + padding: 15px; + resize: none; + } +} + +#{$prefix}code-toolbar { + color: #999; + font-size: 14px; + margin: -5px 0 12px; +} \ No newline at end of file diff --git a/src/scss/editormd.form.scss b/src/scss/editormd.form.scss new file mode 100644 index 0000000..c68456b --- /dev/null +++ b/src/scss/editormd.form.scss @@ -0,0 +1,97 @@ +@charset "UTF-8"; + +// Form + +#{$prefix}form { + color: $color; + + label { + float: left; + display: block; + width: 75px; + text-align: left; + padding: 5px 0 15px 5px; + } + + br { + clear: both; + } + + iframe { + display: none; + } + + input:focus { + outline: 0; + } + + input[type="text"] { + color: #999; + padding: 7px 8px; + border: 1px solid $borderColor; + } + + input[type="text"] { + display: inline-block; + width: 242px; + } +} + +#{$prefix}form, +#{$prefix}dialog-container, +#{$prefix}dialog-footer { + + input[type="submit"], #{$prefix}btn, button { + color: $color; + min-width: 75px; + cursor: pointer; + background: #fff; + padding: 7px 10px; + border: 1px solid #ddd; + @include border-radius(3px); + @include transition(background 300ms ease-out); + + &:hover { + background: #eee; + } + } + + #{$prefix}btn { + padding: 5px 8px 4px\0; + } + + #{$prefix}btn + #{$prefix}btn { + margin-left: 8px; + } +} + +#{$prefix}file-input { + width: 75px; + height: 32px; + margin-left: 8px; + position: relative; + display: inline-block; + + input[type="file"] { + width: 75px; + height: 32px; + opacity: 0; + cursor: pointer; + background: #000; + display: inline-block; + position: absolute; + top: 0; + right: 0; + + &::-webkit-file-upload-button { + visibility: hidden; + } + } + + input[type="submit"] { + } + + &:hover input[type="submit"] { + background: #eee; + } +} \ No newline at end of file diff --git a/src/scss/editormd.menu.scss b/src/scss/editormd.menu.scss index a92e43b..9c3775f 100644 --- a/src/scss/editormd.menu.scss +++ b/src/scss/editormd.menu.scss @@ -1,6 +1,6 @@ @charset "UTF-8"; -.editormd-menu { +#{$prefix}menu { margin: 0; padding: 0; list-style: none; @@ -16,13 +16,14 @@ text-indent: -9999px; margin: 0 5px; height: 65%; - border-right: 1px solid #ddd; + border-right: 1px solid $borderColor; } > a { - color: #666; + outline: 0; + color: $color; display: inline-block; - width: 24px; + min-width: 24px; font-size: 14px; text-decoration: none; text-align: center; @@ -30,7 +31,7 @@ border: 1px solid #fff; &:hover, &.active { - border: 1px solid #ddd; + border: 1px solid $borderColor; background: #eee; @include transition(all 300ms ease-out); } @@ -41,14 +42,14 @@ padding: 5px; } - > .editormd-bold { + > #{$prefix}bold { padding: 5px 0; display: inline-block; font-weight: bold; } } - &:hover .editormd-dropdown-menu { + &:hover #{$prefix}dropdown-menu { display: block; } } @@ -58,10 +59,10 @@ } } -.editormd-dropdown-menu { +#{$prefix}dropdown-menu { display: none; background: #fff; - border: 1px solid #ddd; + border: 1px solid $borderColor; width: 148px; list-style: none; position: absolute; @@ -94,7 +95,7 @@ > li { > a { - color: #666; + color: $color; display: block; text-decoration: none; padding: 8px 10px; @@ -107,6 +108,6 @@ } > li + li { - border-top: 1px solid #ddd; + border-top: 1px solid $borderColor; } } \ No newline at end of file diff --git a/src/scss/editormd.preview.scss b/src/scss/editormd.preview.scss index 9ea9da3..8c40723 100644 --- a/src/scss/editormd.preview.scss +++ b/src/scss/editormd.preview.scss @@ -7,13 +7,16 @@ @import "github-markdown"; #{$prefix}preview-container, #{$prefix}html-preview { + text-align: left; + font-size: 14px; + line-height: 1.6; padding: 20px; blockquote { - border-left: 4px solid #ddd; + color: $color; + border-left: 4px solid $borderColor; padding-left: 20px; margin-left: 0; - color: #666; font-size: 14px; font-style: italic; } @@ -21,43 +24,47 @@ p > code { margin-left: 5px; } - - .markdown-body { - line-height: 1.6; + + abbr { + background: #ffffdd; + } - hr { - height: 1px; - border: none; - border-top: 1px solid #ddd; - background: none; - } + hr { + height: 1px; + border: none; + border-top: 1px solid $borderColor; + background: none; + } - code { - border: 1px solid #ddd; - background: #f6f6f6; - padding: 3px; - border-radius: 3px; - font-size: 13px; - font-family: Consolas, 'Monaco', courier, monospace; - } + code { + border: 1px solid $borderColor; + background: #f6f6f6; + padding: 3px; + border-radius: 3px; + font-size: 13px; + font-family: Consolas, 'Monaco', courier, monospace; + } - pre { - border: 1px solid #ddd; - background: #f6f6f6; - padding: 10px; - @include border-radius(3px); + pre { + border: 1px solid $borderColor; + background: #f6f6f6; + padding: 10px; + @include border-radius(3px); - code { - padding: 0; - } - } - - .markdown-toc { + code { + padding: 0; } + } - .markdown-toc-list { - } + table thead tr { + background-color: #F8F8F8; } + + .markdown-toc { + } + + .markdown-toc-list { + } p#{$prefix}tex { text-align: center; @@ -72,7 +79,7 @@ } .sequence-diagram text, .flowchart text { - font-size: 15px !important; + font-size : 15px !important; font-family: Arial !important; } } @@ -84,7 +91,7 @@ #{$prefix}preview-container, #{$prefix}html-preview { pre.prettyprint { padding: 10px; - border: 1px solid #ddd; + border: 1px solid $borderColor; } ol.linenums { @@ -101,4 +108,10 @@ li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 { list-style-type: decimal; } +} + +#{$prefix}html-preview { + textarea { + display : none; + } } \ No newline at end of file diff --git a/src/scss/editormd.scss b/src/scss/editormd.scss index 4307d15..571a70f 100644 --- a/src/scss/editormd.scss +++ b/src/scss/editormd.scss @@ -1,4 +1,4 @@ -@charset "utf-8"; +@charset "UTF-8"; @import "lib/variables"; @import "lib/functions"; @@ -8,31 +8,120 @@ width: 90%; height: 640px; margin: 0 auto; - position: relative; - @include box-sizing(border-box); - border: 1px solid $borderColor; text-align: left; - overflow: hidden; - background: #fff url("../images/loading.gif") no-repeat center center; - @include background-size(32px 32px); + overflow: hidden; + position: relative; + border: 1px solid $borderColor; + @include box-sizing(border-box); + font-family: "Microsoft YaHei", "微软雅黑", Helvetica, Tahoma, STXihei, "华文细黑", STHeiti, "Helvetica Neue", Helvetica, Tahoma, "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, "宋体", Heiti, "黑体", sans-serif; a { text-decoration: none; } -} -@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) { - .editormd { - background-image: url(../images/loading@2x.gif); + img { + border: none; + vertical-align: middle; + } + + > textarea, + #{$prefix}html-textarea, + #{$prefix}markdown-textarea { + width: 0; + height: 0; + outline: 0; + resize:none; + } + + input[type="text"], + input[type="button"], + input[type="submit"], + select, textarea, button { + @include appearance(none); } } -@media only screen and (-webkit-min-device-pixel-ratio: 3), only screen and (min-device-pixel-ratio: 3) { - .editormd { - background-image: url(../images/loading@3x.gif); +@font-face { + font-family: 'editormd-logo'; + src:url('../fonts/editormd-logo.eot?-5y8q6h'); + src:url('.../fonts/editormd-logo.eot?#iefix-5y8q6h') format('embedded-opentype'), + url('../fonts/editormd-logo.woff?-5y8q6h') format('woff'), + url('../fonts/editormd-logo.ttf?-5y8q6h') format('truetype'), + url('../fonts/editormd-logo.svg?-5y8q6h#icomoon') format('svg'); + font-weight: normal; + font-style: normal; +} + +#{$prefix}logo { + font-family: 'editormd-logo'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + font-size: inherit; + line-height: 1; + display: inline-block; + text-rendering: auto; + vertical-align: inherit; + + //Better Font Rendering + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + &:before { + content: "\e1987"; + /* + HTML Entity 󡦇 + example: + */ } } +#{$prefix}logo-1x { + font-size: 1em; +} + +#{$prefix}logo-lg { + font-size: 1.2em; +} + +#{$prefix}logo-2x { + font-size: 2em; +} + +#{$prefix}logo-3x { + font-size: 3em; +} + +#{$prefix}logo-4x { + font-size: 4em; +} + +#{$prefix}logo-5x { + font-size: 5em; +} + +#{$prefix}logo-6x { + font-size: 6em; +} + +#{$prefix}logo-7x { + font-size: 7em; +} + +#{$prefix}logo-8x { + font-size: 8em; +} + +#{$prefix}logo-color { + color: $mainColor; +} + +#{$prefix}user-unselect { + @include user-select(none); +} + #{$prefix}toolbar { width: 100%; min-height: 35px; @@ -48,6 +137,7 @@ #{$prefix}toolbar-container { padding: 0 8px; min-height: 35px; + @include user-select(none); } @import "editormd.menu"; @@ -61,16 +151,41 @@ position: relative; background: #fff; @include box-sizing(border-box); - - textarea { - display: none; - } } -#{$prefix}html-textarea, #{$prefix}markdown-textarea { +@import "editormd.dialog"; +@import "editormd.form"; +@import "editormd.codemirror"; +@import "editormd.preview"; + +#{$prefix}preview-close-btn { + color: #fff; + padding: 4px 6px; + font-size: 18px; + @include border-radius(500px); display: none; + background-color: #ccc; + position: absolute; + top: 20px; + right: 20px; + z-index: 19; + @include transition(background-color 300ms ease-out); } -@import "editormd.dialog"; -@import "editormd.codemirror"; -@import "editormd.preview"; \ No newline at end of file +#{$prefix}preview-close-btn:hover { + background-color: #999; +} + +#{$prefix}onlyread { + #{$prefix}toolbar { + display: none; + } + + .CodeMirror { + margin-top: 0; + } + + #{$prefix}preview { + top: 0; + } +} \ No newline at end of file diff --git a/src/scss/lib/functions.scss b/src/scss/lib/functions.scss index 69cb099..4250bda 100644 --- a/src/scss/lib/functions.scss +++ b/src/scss/lib/functions.scss @@ -1,5 +1,13 @@ @charset "UTF-8"; +// appearance + +@mixin appearance($value) { + -webkit-appearance: $value; + -moz-appearance: $value; + appearance: $value; +} + // clearfix @mixin clearfix() { @@ -129,11 +137,11 @@ // user-select -@mixin user-select($type : none) { +@mixin user-select($type) { -webkit-user-select: $type; -moz-user-select: $type; -ms-user-select: $type; - //-o-user-select: $type; + -o-user-select: $type; user-select: $type; } diff --git a/src/scss/lib/variables.scss b/src/scss/lib/variables.scss index e6cd867..e5f4b6f 100644 --- a/src/scss/lib/variables.scss +++ b/src/scss/lib/variables.scss @@ -2,5 +2,10 @@ // Global Variables -$prefix : ".editormd-"; -$borderColor: #ddd; \ No newline at end of file +$prefix : ".editormd-"; +$color : #666; +$mainColor : #2196F3; +$primaryColor : $mainColor; +$secondColor : #33CC66; +$thirdColor : #999999; +$borderColor : #ddd; \ No newline at end of file