diff --git a/BUGS.md b/BUGS.md index 34e7b48..9c61c2d 100644 --- a/BUGS.md +++ b/BUGS.md @@ -18,5 +18,5 @@ ####Require.js -- CodeMirror编辑器的代码无法高亮; - +- ~~CodeMirror编辑器的代码无法高亮;~~ +- ~~sequenceDiagram不支持: `Uncaught TypeError: Cannot call method 'isArray' of undefined.`~~ diff --git a/CHANGE.md b/CHANGE.md index cba356a..0eeea49 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -1,4 +1,6 @@ -####更新日志 +##更新日志 + +###v1.0.x #####v1.0.0 beta @@ -34,6 +36,8 @@ - 解决Sea.js环境下Raphael.js无法运行导致不支持流程图和时序图的问题,即必须先加载Raphael.js,后加载Sea.js; +###v1.1.x + #####v1.1.0 主要更新: @@ -206,4 +210,96 @@ - 新增了`editormd.trim()`,用于清除字符串两边的空格; - 修改了所有相关的示例文件和测试用例`marked-heading-link-test.html`; -- 修改了`README.md`,添加了`Shields.io`图标; \ No newline at end of file +- 修改了`README.md`,添加了`Shields.io`图标; + +###v1.2 + +#####v1.2.0 + +v1.2.0 主要更新: + +- 新增代码折叠、搜索替换、自定义样式主题和自定义快捷键等功能; +- 新增Emoji表情、@Link、GFM Task Lists支持; +- 新增表格插入、Emoji表情插入、HTML实体字符插入、使用帮助等对话框; +- 新增插件扩展机制; +- 新增手动加载依赖模块方式; +- 改用`Prefixes.css`作CSS前缀预处理; +- 改进和增强工具栏自定义功能,完善事件监听和处理方法; +- 部分功能改进(更加方便的预格式文本/代码插入、自动闭合标签等)、新增多个方法、改进Require.js支持和修复多个Bug等等; + +**具体更新如下:** + +- 新建v1.1.x分支; + - v1.2文件结构变动较大; + +- 新增代码折叠、自动闭合标签和搜索替换功能; + - 搜索快捷键`Ctrl + F / Command + F`; + - 替换快捷键`Ctrl + Shift + F / Command + Option + F`; + - 折叠快捷键`Ctrl + Q / Command + Q` + +- 新增自定义主题支持; + - 新增3个成员方法`setTheme()`、`setCodeMirrorOption()`和`getCodeMirrorOption()`; + +- 新增@Link支持; + +- 新增GFM Task Lists支持; + +- 新增Emoji表情支持; + - 支持Github emoji`:emoji-name:`、FontAwesome icons(`:fa-xxx:`)、Twitter emoji(twemoji) (`:tw-xxxx:`)、Editor.md logo icons(`:editormd-logo:`)形式的Emoji; + - 新增属性`editormd.emoji`、`editormd.twemoji`、`editormd.urls`和`editormd.regex`; + +- 新增HTML实体字符插入、插入表格和使用帮助对话框; + - 修改了`createDialog()`等方法; + - 新增`mask`成员属性和锁屏方法`editormd.lockScreen()`、`editormd.fn.lockScreen()`; + +- 改进插入预格式文本和代码对话框; + - 将` + > 提示1:如果没有Markdown源内容或者通过Ajax异步加载Markdown源文档等,可以不添加`"),s=this.markdownTextarea=a.children("textarea")),s.addClass(n.textarea.markdown).attr("name",e+"-markdown-doc").attr("placeholder",r.placeholder);var l=[r.readOnly?"":'',r.saveHTMLToTextarea?'':"",'
','
','
'].join("\n");return a.append(l).addClass(o+"vertical"),""!==r.markdown&&s.val(r.markdown),this.htmlTextarea=a.find("."+n.textarea.html),this.preview=a.find("."+o+"preview"),this.previewContainer=this.preview.children("."+o+"preview-container"),this.toolbarIconHandlers={},r.inRequirejs?(i.setCodeMirror(),i.setToolbar(),i.setMarked().loadedDisplay()):this.loadQueues(),this},loadQueues:function(){var e=this,t=this.settings,i=t.path,o=function(){return editormd.isIE8?void e.setMarked().loadedDisplay():void(t.flowChart||t.sequenceDiagram?editormd.loadScript(i+"raphael.min",function(){editormd.loadScript(i+"underscore.min",function(){!t.flowChart&&t.sequenceDiagram?editormd.loadScript(i+"sequence-diagram.min",function(){e.setMarked().loadedDisplay()}):t.flowChart&&!t.sequenceDiagram?editormd.loadScript(i+"flowchart.min",function(){editormd.loadScript(i+"jquery.flowchart.min",function(){e.setMarked().loadedDisplay()})}):t.flowChart&&t.sequenceDiagram&&editormd.loadScript(i+"flowchart.min",function(){editormd.loadScript(i+"jquery.flowchart.min",function(){editormd.loadScript(i+"sequence-diagram.min",function(){e.setMarked().loadedDisplay()})})})})}):e.setMarked().loadedDisplay())};return editormd.loadCSS(i+"codemirror/codemirror.min"),editormd.loadScript(i+"codemirror/codemirror.min",function(){editormd.$CodeMirror=CodeMirror,editormd.loadScript(i+"codemirror/modes.min",function(){editormd.loadScript(i+"codemirror/addons.min",function(){e.setCodeMirror(),e.setToolbar(),editormd.loadScript(i+"marked.min",function(){editormd.$marked=marked,t.previewCodeHighlight?editormd.loadScript(i+"prettify.min",function(){o()}):o()})})})}),this},setCodeMirror:function(){var e=this.settings,t=this.editor,i={mode:e.mode,theme:"default",tabSize:4,dragDrop:!1,autofocus:!0,readOnly:e.readOnly?"nocursor":!1,indentUnit:4,lineNumbers:e.lineNumbers,lineWrapping:!0,matchBrackets:!0,indentWithTabs:!0,styleActiveLine:e.styleActiveLine,styleSelectedText:!0,autoCloseBrackets:!0,showTrailingSpace:!0,highlightSelectionMatches:e.matchWordHighlight?{showToken:"onselected"==e.matchWordHighlight?!1:/\w/}:!1};return this.codeEditor=editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0],i),this.codeMirror=t.find(".CodeMirror"),this.codeMirror.css({fontSize:e.fontSize,width:e.watch?"50%":"100%"}),this},showToolbar:function(){var e=this.settings;if(!e.readOnly)return e.toolbar=!0,this.toolbar.show(),this.resize(),this},hideToolbar:function(){var e=this.settings;return e.toolbar=!1,this.toolbar.hide(),this.resize(),this},setToolbar:function(){var e=this.settings;if(!e.readOnly){var t=this.editor,i=(this.preview,this.classPrefix);t.append('
');var o=this.toolbar=t.find("."+i+"toolbar");if(!e.toolbar)return void o.hide();o.show();for(var a=e.toolbarIcons(),r=o.find("."+this.classPrefix+"menu"),n="",s=0,l=a.length;l>s;s++){var d=a[s];if("|"!==d){var c=/h(\d)/.test(d),h=d;"watch"!==d||e.watch||(h="unwatch");var u=e.lang.toolbar[h],g=e.toolbarIconTexts[h],m=e.toolbarIconsClass[h];u="undefined"==typeof u?"":u,g="undefined"==typeof g?"":g,m="undefined"==typeof m?"":m,n+='
  • '+(c?d:""===m?g:"")+"
  • "}else n+='
  • |
  • '}return r.html(n),this.setToolbarHandler(),this}},getToolbarHandles:function(name){var _this=this,settings=this.settings,lang=settings.lang,editor=this.editor,classPrefix=this.classPrefix,dialogLockScreen=function(){settings.dialogLockScreen&&$("html,body").css("overflow","hidden")},dialogShowMask=function(e){e.css({top:($(window).height()-e.height())/2+"px",left:($(window).width()-e.width())/2+"px"}),settings.dialogShowMask&&editor.find("."+classPrefix+"mask").css("z-index",parseInt(e.css("z-index"))-1).show()},toolbarHandlers=this.toolbarHandlers={undo:function(e){e.undo()},redo:function(e){e.redo()},bold:function(e){var t=e.getCursor(),i=e.getSelection();e.replaceSelection("**"+i+"**"),""===i&&e.setCursor(t.line,t.ch+2)},del:function(e){var t=e.getCursor(),i=e.getSelection();e.replaceSelection("~~"+i+"~~"),""===i&&e.setCursor(t.line,t.ch+2)},italic:function(e){var t=e.getCursor(),i=e.getSelection();e.replaceSelection("*"+i+"*"),""===i&&e.setCursor(t.line,t.ch+1)},quote:function(e){var t=e.getCursor(),i=e.getSelection();e.replaceSelection("> "+i),e.setCursor(t.line,""===i?t.ch+2:t.ch+i.length+2)},h1:function(e){var t=e.getSelection();e.replaceSelection("# "+t)},h2:function(e){var t=e.getSelection();e.replaceSelection("## "+t)},h3:function(e){var t=e.getSelection();e.replaceSelection("### "+t)},h4:function(e){var t=e.getSelection();e.replaceSelection("#### "+t)},h5:function(e){var t=e.getSelection();e.replaceSelection("##### "+t)},h6:function(e){var t=e.getSelection();e.replaceSelection("###### "+t)},"list-ul":function(e){var t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("- "+t);else{for(var i=t.split("\n"),o=0,a=i.length;a>o;o++)i[o]=""===i[o]?"":"- "+i[o];e.replaceSelection(i.join("\n"))}},"list-ol":function(e){var t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("1. "+t);else{for(var i=t.split("\n"),o=0,a=i.length;a>o;o++)i[o]=""===i[o]?"":o+1+". "+i[o];e.replaceSelection(i.join("\n"))}},hr:function(e){e.getCursor(),e.getSelection();e.replaceSelection("------------")},link:function(e){var t,i=e.getSelection(),o=lang.dialog.link,a=classPrefix+"link-dialog";if(editor.find("."+a).length>0)t=editor.find("."+a),t.find("[data-url]").val("http://"),t.find("[data-title]").val(i),dialogShowMask(t),dialogLockScreen(),t.show();else{var r='


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



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


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

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

    ","

    "+this.lang.description+"

    ",'

    Home page: '+editormd.homePage+"

    ","

    License: MIT

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

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

      Index

      - - - - - - - -

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

      Editor.md

      -

      -

      - - - - -

      -

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

      -

      Features

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

      README & Examples (English)

      -
      -

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

      -

      editormd-screenshot

      -

      主要特性

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

      在线演示

      -

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

      -

      下载和安装

      -

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

      -
      bower install editor.md
      -

      使用方法

      -

      HTML:

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

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

      -

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

      -
      -

      javascript:

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

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

      -

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

      -
      -

      依赖项目及感谢

      - -

      更新日志

      -

      查看更新日志

      -

      License

      -

      The MIT License.

      -

      Copyright (c) 2015 Pandao

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

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

        ", + "

        " + this.lang.description + "

        ", + "

        Home page: " + editormd.homePage + "

        ", + "

        License: MIT

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

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

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

          ","

          "+this.lang.description+"

          ",'

          Home page: '+t.homePage+"

          ","

          License: MIT

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

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

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

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

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

                ","

                "+this.lang.description+"

                ",'

                Home page: '+t.homePage+"

                ","

                License: MIT

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

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

                @links

                +

                Github Flavored Markdown extended syntax

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

                Chnage mode

                +

                Become to the code editor

                +

                Modes :   Themes : + +

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

                Code fold

                +

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

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

                Custom keyboard shortcuts

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

                Custom toolbar (icons handler)

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

                Emoji表情

                +

                Supports:

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

                Expanded Editor.md

                +

                Expanded of member methods and properties

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

                External use

                +

                External use of toolbar handlers / modal dialog

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

                FlowChart 流程图

                -

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

                +

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

                -
                - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/multi-editormd.html b/examples/multi-editormd.html index 8febb9e..0ed81ab 100644 --- a/examples/multi-editormd.html +++ b/examples/multi-editormd.html @@ -4,7 +4,8 @@ 多个Editor.md并存 - Editor.md examples - + + + + + \ No newline at end of file diff --git a/tests/js/searchbox.js b/tests/js/searchbox.js new file mode 100644 index 0000000..ff95f56 --- /dev/null +++ b/tests/js/searchbox.js @@ -0,0 +1,674 @@ +/* global CodeMirror */ +/* global define */ + +(function(mod) { + 'use strict'; + + if (typeof exports === 'object' && typeof module === 'object') // CommonJS + mod(require('../../lib/codemirror')); + else if (typeof define === 'function' && define.amd) // AMD + define(['../../lib/codemirror'], mod); + else + mod(CodeMirror); +})(function(CodeMirror) { + 'use strict'; + + var Search; + + CodeMirror.defineOption('searchbox', false, function(cm) { + cm.addKeyMap({ + 'Ctrl-F': function() { + if (!Search) + Search = new SearchBox(cm); + + Search.show(); + }, + + 'Esc': function() { + if (Search && Search.isVisible()) { + Search.hide(); + + if (typeof event !== 'undefined') + event.stopPropagation(); + } + + return false; + }, + + 'Cmd-F': function() { + if (!Search) + Search = new SearchBox(cm); + + Search.show(); + } + }); + }); + + function SearchBox(cm) { + var self = this; + + init(); + + function initElements(el) { + self.searchBox = el.querySelector('.ace_search_form'); + self.replaceBox = el.querySelector('.ace_replace_form'); + self.searchOptions = el.querySelector('.ace_search_options'); + + self.regExpOption = el.querySelector('[action=toggleRegexpMode]'); + self.caseSensitiveOption = el.querySelector('[action=toggleCaseSensitive]'); + self.wholeWordOption = el.querySelector('[action=toggleWholeWords]'); + + self.searchInput = self.searchBox.querySelector('.ace_search_field'); + self.replaceInput = self.replaceBox.querySelector('.ace_search_field'); + } + + function init() { + var el = self.element = addHtml(); + + addStyle(); + + initElements(el); + bindKeys(); + + el.addEventListener('mousedown', function(e) { + setTimeout(function(){ + self.activeInput.focus(); + }, 0); + + e.stopPropagation(); + }); + + el.addEventListener('click', function(e) { + var t = e.target || e.srcElement; + var action = t.getAttribute('action'); + if (action && self[action]) + self[action](); + else if (self.commands[action]) + self.commands[action](); + + e.stopPropagation(); + }); + + self.searchInput.addEventListener('input', function() { + self.$onChange.schedule(20); + }); + + self.searchInput.addEventListener('focus', function() { + self.activeInput = self.searchInput; + }); + + self.replaceInput.addEventListener('focus', function() { + self.activeInput = self.replaceInput; + }); + + self.$onChange = delayedCall(function() { + self.find(false, false); + }); + } + + function bindKeys() { + var sb = self, + obj = { + 'Ctrl-F|Cmd-F|Ctrl-H|Command-Alt-F': function() { + var isReplace = sb.isReplace = !sb.isReplace; + sb.replaceBox.style.display = isReplace ? '' : 'none'; + sb[isReplace ? 'replaceInput' : 'searchInput'].focus(); + }, + 'Ctrl-G|Cmd-G': function() { + sb.findNext(); + }, + 'Ctrl-Shift-G|Cmd-Shift-G': function() { + sb.findPrev(); + }, + 'Esc': function() { + setTimeout(function() { sb.hide();}); + }, + 'Enter': function() { + if (sb.activeInput === sb.replaceInput) + sb.replace(); + sb.findNext(); + }, + 'Shift-Enter': function() { + if (sb.activeInput === sb.replaceInput) + sb.replace(); + sb.findPrev(); + }, + 'Alt-Enter': function() { + if (sb.activeInput === sb.replaceInput) + sb.replaceAll(); + sb.findAll(); + }, + 'Tab': function() { + if (self.activeInput === self.replaceInput) + self.searchInput.focus(); + else + self.replaceInput.focus(); + } + }; + + self.element.addEventListener('keydown', function(event) { + Object.keys(obj).some(function(name) { + var is = key(name, event); + + if (is) { + event.stopPropagation(); + event.preventDefault(); + obj[name](event); + } + + return is; + }); + }); + } + + this.commands = { + toggleRegexpMode: function() { + self.regExpOption.checked = !self.regExpOption.checked; + self.$syncOptions(); + }, + + toggleCaseSensitive: function() { + self.caseSensitiveOption.checked = !self.caseSensitiveOption.checked; + self.$syncOptions(); + }, + + toggleWholeWords: function() { + self.wholeWordOption.checked = !self.wholeWordOption.checked; + self.$syncOptions(); + } + }; + + this.$syncOptions = function() { + setCssClass(this.regExpOption, 'checked', this.regExpOption.checked); + setCssClass(this.wholeWordOption, 'checked', this.wholeWordOption.checked); + setCssClass(this.caseSensitiveOption, 'checked', this.caseSensitiveOption.checked); + + this.find(false, false); + }; + + this.find = function(skipCurrent, backwards) { + var value = this.searchInput.value, + options = { + skipCurrent: skipCurrent, + backwards: backwards, + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }; + + find(value, options, function(searchCursor) { + var current = searchCursor.matches(false, searchCursor.from()); + cm.setSelection(current.from, current.to); + }); + }; + + function find(value, options, callback) { + var done, + noMatch, searchCursor, next, prev, matches, cursor, + position, + o = options, + is = true, + caseSensitive = o.caseSensitive, + regExp = o.regExp, + wholeWord = o.wholeWord; + + if (regExp || wholeWord) { + if (options.wholeWord) + value = '\\b' + value + '\\b'; + + value = RegExp(value); + } + + if (o.backwards) + position = o.skipCurrent ? 'from': 'to'; + else + position = o.skipCurrent ? 'to' : 'from'; + + cursor = cm.getCursor(position); + searchCursor = cm.getSearchCursor(value, cursor, !caseSensitive); + + next = searchCursor.findNext.bind(searchCursor), + prev = searchCursor.findPrevious.bind(searchCursor), + matches = searchCursor.matches.bind(searchCursor); + + if (o.backwards && !prev()) { + is = next(); + + if (is) { + cm.setCursor(cm.doc.size - 1, 0); + find(true, true, callback); + done = true; + } + } else if (!o.backwards && !next()) { + is = prev(); + + if (is) { + cm.setCursor(0, 0); + find(true, false, callback); + done = true; + } + } + + noMatch = !is && self.searchInput.value; + setCssClass(self.searchBox, 'ace_nomatch', noMatch); + + if (!done && is) + callback(searchCursor); + } + + this.findNext = function() { + this.find(true, false); + }; + + this.findPrev = function() { + this.find(true, true); + }; + + this.findAll = function(){ + /* + var range = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + */ + + var value = this.searchInput.value, + range, + noMatch = !range && this.searchInput.value; + + setCssClass(this.searchBox, 'ace_nomatch', noMatch); + + if (cm.showMatchesOnScrollbar) + cm.showMatchesOnScrollbar(value); + + this.hide(); + }; + + this.replace = function() { + if (!cm.getOption('readOnly')) + cm.replaceSelection(this.replaceInput.value, 'start'); + }; + + this.replaceAndFindNext = function() { + if (!cm.getOption('readOnly')) { + this.editor.replace(this.replaceInput.value); + this.findNext(); + } + }; + + this.replaceAll = function() { + var value, + cursor, + from = this.searchInput.value, + to = this.replaceInput.value, + reg = RegExp(from, 'g'); + + if (!cm.getOption('readOnly')) { + cursor = cm.getCursor(); + value = cm.getValue(); + value = value.replace(reg, to); + + cm.setValue(value); + cm.setCursor(cursor); + } + }; + + this.hide = function() { + this.element.style.display = 'none'; + cm.focus(); + }; + + this.isVisible = function() { + var is = this.element.style.display === ''; + + return is; + }; + + this.show = function(value, isReplace) { + this.element.style.display = ''; + this.replaceBox.style.display = isReplace ? '' : 'none'; + + this.isReplace = isReplace; + + if (value) + this.searchInput.value = value; + + this.searchInput.focus(); + this.searchInput.select(); + }; + + this.isFocused = function() { + var el = document.activeElement; + return el === this.searchInput || el === this.replaceInput; + }; + + function addStyle() { + var style = document.createElement('style'), + css = [ + '.ace_search {', + 'background-color: #ddd;', + 'border: 1px solid #cbcbcb;', + 'border-top: 0 none;', + 'max-width: 325px;', + 'overflow: hidden;', + 'margin: 0;', + 'padding: 4px;', + 'padding-right: 6px;', + 'padding-bottom: 0;', + 'position: absolute;', + 'top: 0px;', + 'z-index: 99;', + 'white-space: normal;', + '}', + '.ace_search.left {', + 'border-left: 0 none;', + 'border-radius: 0px 0px 5px 0px;', + 'left: 0;', + '}', + '.ace_search.right {', + 'border-radius: 0px 0px 0px 5px;', + 'border-right: 0 none;', + 'right: 0;', + '}', + '.ace_search_form, .ace_replace_form {', + 'border-radius: 3px;', + 'border: 1px solid #cbcbcb;', + 'float: left;', + 'margin-bottom: 4px;', + 'overflow: hidden;', + '}', + '.ace_search_form.ace_nomatch {', + 'outline: 1px solid red;', + '}', + '.ace_search_field {', + 'background-color: white;', + 'border-right: 1px solid #cbcbcb;', + 'border: 0 none;', + '-webkit-box-sizing: border-box;', + '-moz-box-sizing: border-box;', + 'box-sizing: border-box;', + 'float: left;', + 'height: 22px;', + 'outline: 0;', + 'padding: 0 7px;', + 'width: 214px;', + 'margin: 0;', + '}', + '.ace_searchbtn,', + '.ace_replacebtn {', + 'background: #fff;', + 'border: 0 none;', + 'border-left: 1px solid #dcdcdc;', + 'cursor: pointer;', + 'float: left;', + 'height: 22px;', + 'margin: 0;', + 'padding: 0;', + 'position: relative;', + '}', + '.ace_searchbtn:last-child,', + '.ace_replacebtn:last-child {', + 'border-top-right-radius: 3px;', + 'border-bottom-right-radius: 3px;', + '}', + '.ace_searchbtn:disabled {', + 'background: none;', + 'cursor: default;', + '}', + '.ace_searchbtn {', + 'background-position: 50% 50%;', + 'background-repeat: no-repeat;', + 'width: 27px;', + '}', + '.ace_searchbtn.prev {', + 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); ', + '}', + '.ace_searchbtn.next {', + 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); ', + '}', + '.ace_searchbtn_close {', + 'background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;', + 'border-radius: 50%;', + 'border: 0 none;', + 'color: #656565;', + 'cursor: pointer;', + 'float: right;', + 'font: 16px/16px Arial;', + 'height: 14px;', + 'margin: 5px 1px 9px 5px;', + 'padding: 0;', + 'text-align: center;', + 'width: 14px;', + '}', + '.ace_searchbtn_close:hover {', + 'background-color: #656565;', + 'background-position: 50% 100%;', + 'color: white;', + '}', + '.ace_replacebtn.prev {', + 'width: 54px', + '}', + '.ace_replacebtn.next {', + 'width: 27px', + '}', + '.ace_button {', + 'margin-left: 2px;', + 'cursor: pointer;', + '-webkit-user-select: none;', + '-moz-user-select: none;', + '-o-user-select: none;', + '-ms-user-select: none;', + 'user-select: none;', + 'overflow: hidden;', + 'opacity: 0.7;', + 'border: 1px solid rgba(100,100,100,0.23);', + 'padding: 1px;', + '-moz-box-sizing: border-box;', + 'box-sizing: border-box;', + 'color: black;', + '}', + '.ace_button:hover {', + 'background-color: #eee;', + 'opacity:1;', + '}', + '.ace_button:active {', + 'background-color: #ddd;', + '}', + '.ace_button.checked {', + 'border-color: #3399ff;', + 'opacity:1;', + '}', + '.ace_search_options{', + 'margin-bottom: 3px;', + 'text-align: right;', + '-webkit-user-select: none;', + '-moz-user-select: none;', + '-o-user-select: none;', + '-ms-user-select: none;', + 'user-select: none;', + '}' + ].join(''); + + style.setAttribute('data-name', 'js-searchbox'); + + style.textContent = css; + + document.head.appendChild(style); + } + + function addHtml() { + var elSearch, + el = document.querySelector('.CodeMirror'), + div = document.createElement('div'), + html = [ + '' + ].join(''); + + div.innerHTML = html; + + elSearch = div.firstChild; + + el.parentElement.appendChild(elSearch); + + return elSearch; + } + } + + function setCssClass(el, className, condition) { + var list = el.classList; + + list[condition ? 'add' : 'remove'](className); + } + + function delayedCall(fcn, defaultTimeout) { + var timer, + callback = function() { + timer = null; + fcn(); + }, + + _self = function(timeout) { + if (!timer) + timer = setTimeout(callback, timeout || defaultTimeout); + }; + + _self.delay = function(timeout) { + timer && clearTimeout(timer); + timer = setTimeout(callback, timeout || defaultTimeout); + }; + _self.schedule = _self; + + _self.call = function() { + this.cancel(); + fcn(); + }; + + _self.cancel = function() { + timer && clearTimeout(timer); + timer = null; + }; + + _self.isPending = function() { + return timer; + }; + + return _self; + } + + /* https://github.com/coderaiser/key */ + function key(str, event) { + var right, + KEY = { + BACKSPACE : 8, + TAB : 9, + ENTER : 13, + ESC : 27, + + SPACE : 32, + PAGE_UP : 33, + PAGE_DOWN : 34, + END : 35, + HOME : 36, + UP : 38, + DOWN : 40, + + INSERT : 45, + DELETE : 46, + + INSERT_MAC : 96, + + ASTERISK : 106, + PLUS : 107, + MINUS : 109, + + F1 : 112, + F2 : 113, + F3 : 114, + F4 : 115, + F5 : 116, + F6 : 117, + F7 : 118, + F8 : 119, + F9 : 120, + F10 : 121, + + SLASH : 191, + TRA : 192, /* Typewritten Reverse Apostrophe (`) */ + BACKSLASH : 220 + }; + + keyCheck(str, event); + + right = str.split('|').some(function(combination) { + var wrong; + + wrong = combination.split('-').some(function(key) { + var right; + + switch(key) { + case 'Ctrl': + right = event.ctrlKey; + break; + + case 'Shift': + right = event.shiftKey; + break; + + case 'Alt': + right = event.altKey; + break; + + case 'Cmd': + right = event.metaKey; + break; + + default: + if (key.length === 1) + right = event.keyCode === key.charCodeAt(0); + else + Object.keys(KEY).some(function(name) { + var up = key.toUpperCase(); + + if (up === name) + right = event.keyCode === KEY[name]; + }); + break; + } + + return !right; + }); + + return !wrong; + }); + + return right; + } + + function keyCheck(str, event) { + if (typeof str !== 'string') + throw(Error('str should be string!')); + + if (typeof event !== 'object') + throw(Error('event should be object!')); + } + +}); diff --git a/tests/marked-@at-test.html b/tests/marked-@at-test.html new file mode 100644 index 0000000..be8239d --- /dev/null +++ b/tests/marked-@at-test.html @@ -0,0 +1,221 @@ + + + + Marked @ Test + + + + + + + +
                 ~~@mentions~~, #refs @tylerlong `inline code @tylerlong`, [links](), **formatting**, and tags supported @pandao;
                +list syntax required (any unordered or ordered list supported) @pandao;
                +this is @pandao a complete item @pandao;
                +link [@pandao](https://github.com/pandao "@pandao") @
                +link [@pandao](https://github.com/pandao "@pandao") 
                +this is an incomplete item **@pandao**;
                +*@pandao* this is an incomplete item ___@pandao___;
                +# Github: @pandao
                +## Github: @pandao
                +### Github: @tylerlong
                +#### Github: @tylerlong
                +##### Github: @tylerlong
                +###### Github: @tylerlong
                + 
                +- dafssdfsdaf@chjj dfsdfsdf
                +- dafssdfsdaf@chjj dfsdfsdf     
                +    - dafssdfsdaf@chjj dfsdfsdf
                +    - dafss@pandao dfsdaf@chjj dfsdfsdf
                +- dafssd:  @pandao fsdaf@chjj dfsdfsdf @codemirror  @pandao
                +    + dafssdfsdaf@chjj dfsdfsdf
                +    + dafss@pandaodfsdaf@chjj dfsdfsdf
                +
                +
                +1. @chjj 第一行@pandao fsdaf@chjj dfsdfsdf :fa-save::  @pandao
                +    - dafssdfsdaf@chjj dfsdfsdf
                +    - dafss@pandao dfsdaf@chjj dfsdfsdf
                +2. @chjj 第二行@pandao fsdaf@chjj dfsdfsdf @codemirror  @pandao
                +3. 第三行@pandao fsdaf@chjj dfsdfsdf :fa-save::  @pandao
                +
                +> Blockquotes @pandao
                +
                +> dd@pandao引用文本(Blockquotes @pandao)fdasfad @_pandao fdasfad @xxx454xxx fdasfad @xx_x454xxx454
                +
                +|@pandao First Header  | Second@pandao Header@pandao |
                +| ------------- | ------------- |
                +| Content@pandao Cell  | @pandao Content Cell @pandao|
                +| Con@pandao tent Cell@pandao  | Content@pan-dao Cell dfsdfsdf @pan_dao |
                +
                +dsfdf@pandao fasdfsdfsfddffd@pandao
                +
                +    dfasfasdfasdf:bangbang:
                +
                +This is an H1 @pandao
                +=============
                +
                +This @pandao an H2 @pandao
                +-------------
                +
                + + + + + \ No newline at end of file diff --git a/tests/marked-emoji-test.html b/tests/marked-emoji-test.html new file mode 100644 index 0000000..f54dbca --- /dev/null +++ b/tests/marked-emoji-test.html @@ -0,0 +1,231 @@ + + + + Marked Emoji Test + + + + + + + +
                +
                > Blockquotes
                +dasfsadfasdf:fa-edit: :warning: :smiley:dsafsdfsad\:fdsfdf\:f dfdf:   :fa-save::fa-star:  :fa-truck:
                +**fdfasd:smiley:dsfsdfsfd** ~~fsdfds:smiley:dfsdfsdf :fa-info:~~
                +*dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf*
                +___Emphasis :fa-gear: Italic:smiley:___  __Emphasis:smiley:__
                +# H1 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf
                +## H2 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf
                +### H3 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-save:dsfsdf
                +#### H4 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-save:dsfsdf
                +##### H5 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-save:dsfsdf
                +###### H6 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-star:dsfsdf
                +[:smiley:](http://www.emoji-cheat-sheet.com/ "link + emoji") link + emoji
                +- dafssdfsdaf:smiley:dfsdfsdf
                +- dafssdfsdaf:smiley:dfsdfsdf     
                +    - dafssdfsdaf:smiley:dfsdfsdf
                +    - dafss:fa-truck:dfsdaf:smiley:dfsdfsdf
                +- dafssd:  :fa-truck:fsdaf:smiley:dfsdfsdf :fa-star::  :fa-truck:
                +    + dafssdfsdaf:smiley:dfsdfsdf
                +    + dafss:fa-truck:dfsdaf:smiley:dfsdfsdf
                +
                +
                +1. :smiley:第一行:fa-truck:fsdaf:smiley:dfsdfsdf :fa-save::  :fa-truck:
                +    - dafssdfsdaf:smiley:dfsdfsdf
                +    - dafss:fa-truck:dfsdaf:smiley:dfsdfsdf
                +2. :smiley:第二行:fa-truck:fsdaf:smiley:dfsdfsdf :fa-star::  :fa-truck:
                +3. 第三行:fa-truck:fsdaf:smiley:dfsdfsdf :fa-save::  :fa-truck:
                +
                +> Blockquotes
                +
                +> dd:smiley:引用文本(Blockquotes:smiley:)fdasfad :fa-star:: dfd :fa-truck:
                +
                +|:100: First Header  | Second:smiley: Header:smiley: |
                +| ------------- | ------------- |
                +| Content:fa-truck: Cell  | :smiley:Content Cell :smiley: |
                +| Con:fa-truck:tent Cell:bangbang:  | Content Cell dfsdfsdf :fa-star: :dfdf  :fa-truck: |
                +
                +:fa-heart:fasdfsdfsfddffd:editormd-logo: :editormd-logo: :editormd-logo-4x:
                +
                +    dfasfasdfasdf:bangbang:
                +
                +This is an H1 :editormd-logo-4x:
                +=============
                +
                +This  :fa-save::  :fa-truck:is an H2 :100:
                +-------------
                +
                + + + + + \ No newline at end of file diff --git a/tests/marked-todo-list-test.html b/tests/marked-todo-list-test.html new file mode 100644 index 0000000..1c2ea23 --- /dev/null +++ b/tests/marked-todo-list-test.html @@ -0,0 +1,61 @@ + + + + Marked Emoji Test + + + + + + + + + + + \ No newline at end of file