diff --git a/build/MDEditor.min.js b/build/MDEditor.min.js index 177aa2a..2f83eb8 100644 --- a/build/MDEditor.min.js +++ b/build/MDEditor.min.js @@ -9,7 +9,7 @@ lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, - html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/, + html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, table: noop, paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, @@ -25,8 +25,9 @@ block.paragraph = replace(block.paragraph)("hr", block.hr)("heading", block.heading)("lheading", block.lheading)("blockquote", block.blockquote)("tag", "<" + block._tag)("def", block.def)(); block.normal = merge({}, block); block.gfm = merge({}, block.normal, { - fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/, - paragraph: /^/ + fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/, + paragraph: /^/, + heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ }); block.gfm.paragraph = replace(block.paragraph)("(?!", "(?!" + block.gfm.fences.source.replace("\\1", "\\2") + "|" + block.list.source.replace("\\1", "\\3") + "|")(); block.tables = merge({}, block.gfm, { @@ -80,7 +81,7 @@ this.tokens.push({ type: "code", lang: cap[2], - text: cap[3] + text: cap[3] || "" }); continue; } @@ -194,7 +195,7 @@ src = src.substring(cap[0].length); this.tokens.push({ type: this.options.sanitize ? "paragraph" : "html", - pre: cap[1] === "pre" || cap[1] === "script" || cap[1] === "style", + pre: !this.options.sanitizer && (cap[1] === "pre" || cap[1] === "script" || cap[1] === "style"), text: cap[0] }); continue; @@ -263,7 +264,7 @@ reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, - em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, + em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, br: /^ {2,}\n(?!\s*$)/, del: noop, @@ -346,7 +347,7 @@ this.inLink = false; } src = src.substring(cap[0].length); - out += this.options.sanitize ? escape(cap[0]) : cap[0]; + out += this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) : cap[0]; continue; } if (cap = this.rules.link.exec(src)) { @@ -400,7 +401,7 @@ } if (cap = this.rules.text.exec(src)) { src = src.substring(cap[0].length); - out += escape(this.smartypants(cap[0])); + out += this.renderer.text(escape(this.smartypants(cap[0]))); continue; } if (src) { @@ -415,9 +416,10 @@ }; InlineLexer.prototype.smartypants = function(text) { if (!this.options.smartypants) return text; - return text.replace(/--/g, "—").replace(/(^|[-\u2014/(\[{"\s])'/g, "$1‘").replace(/'/g, "’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g, "$1“").replace(/"/g, "”").replace(/\.{3}/g, "…"); + return text.replace(/---/g, "—").replace(/--/g, "–").replace(/(^|[-\u2014/(\[{"\s])'/g, "$1‘").replace(/'/g, "’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g, "$1“").replace(/"/g, "”").replace(/\.{3}/g, "…"); }; InlineLexer.prototype.mangle = function(text) { + if (!this.options.mangle) return text; var out = "", l = text.length, i = 0, ch; for (;i < l; i++) { ch = text.charCodeAt(i); @@ -499,7 +501,7 @@ } catch (e) { return ""; } - if (prot.indexOf("javascript:") === 0) { + if (prot.indexOf("javascript:") === 0 || prot.indexOf("vbscript:") === 0) { return ""; } } @@ -518,6 +520,9 @@ out += this.options.xhtml ? "/>" : ">"; return out; }; + Renderer.prototype.text = function(text) { + return text; + }; function Parser(options) { this.tokens = []; this.token = null; @@ -766,6 +771,8 @@ breaks: false, pedantic: false, sanitize: false, + sanitizer: null, + mangle: true, smartLists: false, silent: false, highlight: null, @@ -891,69 +898,71 @@ css(self.textarea, "min-height", opts.minheight + "px"); css(self.preview, "min-height", opts.minheight + "px"); } - MDEditor.prototype.load = function() { - var self = this, box = self.obj[0], index = 0; - if (box) { - if (box.innerHTML !== "") self.opts.value = box.innerHTML.replace(/\>\;/g, ">").replace(/\<\;/g, "<"), - box.innerHTML = ""; - box.appendChild(self.preview), box.appendChild(self.tools), box.appendChild(self.textarea); - } - self.setMD(); - addEvent(self.btn_preview, "click", function(event) { - index = parseInt(self.preview.style.zIndex); - if (index === 9) { - self.preview.style.zIndex = 0; - this.innerHTML = "预览"; - } else { - self.preview.style.zIndex = 9; - this.innerHTML = "编辑"; - } - self.setHTML(self.getMD()); + MDEditor.prototype = { + load: function() { + var self = this, box = self.obj[0], index = 0; + if (box) { + if (box.innerHTML !== "") self.opts.value = box.innerHTML.replace(/\>\;/g, ">").replace(/\<\;/g, "<"), + box.innerHTML = ""; + box.appendChild(self.preview), box.appendChild(self.tools), box.appendChild(self.textarea); + } + self.setMD(); + addEvent(self.btn_preview, "click", function(event) { + index = parseInt(self.preview.style.zIndex); + if (index === 9) { + self.preview.style.zIndex = 0; + this.innerHTML = "预览"; + } else { + self.preview.style.zIndex = 9; + this.innerHTML = "编辑"; + } + self.setHTML(self.getMD()); + css(self.preview, { + height: self.textarea.offsetHeight + "px" + }); + }); css(self.preview, { height: self.textarea.offsetHeight + "px" }); - }); - css(self.preview, { - height: self.textarea.offsetHeight + "px" - }); - addEvent(self.textarea, "input propertychange", function(event) { - if (this.scrollHeight < self.opts.maxheight) { - css(self.textarea, { - height: this.scrollHeight + "px", - overflow: "hidden" - }); - } else { - css(self.textarea, { - height: self.opts.maxheight + "px", - overflow: "auto" + addEvent(self.textarea, "input propertychange", function(event) { + if (this.scrollHeight < self.opts.maxheight) { + css(self.textarea, { + height: this.scrollHeight + "px", + overflow: "hidden" + }); + } else { + css(self.textarea, { + height: self.opts.maxheight + "px", + overflow: "auto" + }); + } + css(self.preview, { + height: self.textarea.offsetHeight + "px" }); - } - css(self.preview, { - height: self.textarea.offsetHeight + "px" + self.opts.value = this.value; + self.callback(event, self.opts); }); - self.opts.value = this.value; - self.callback(event, self.opts); - }); - return this; - }; - MDEditor.prototype.getMD = function() { - return this.textarea.value; - }; - MDEditor.prototype.setMD = function(val) { - if (marked) this.textarea.value = val ? val : this.opts.value; - this.textarea.style.height = (this.textarea.scrollHeight < this.opts.maxheight ? this.textarea.scrollHeight : this.opts.maxheight) + "px"; - return this; - }; - MDEditor.prototype.getHTML = function() { - if (marked) return marked(this.getMD()); else return this.preview.innerHTML; - }; - MDEditor.prototype.input = function(evn) { - this.callback = evn; - return this; - }; - MDEditor.prototype.setHTML = function(val) { - if (marked) this.preview.innerHTML = marked(val ? val : this.opts.value); - return this; + return this; + }, + getMD: function() { + return this.textarea.value; + }, + setMD: function(val) { + if (marked) this.textarea.value = val ? val : this.opts.value; + this.textarea.style.height = (this.textarea.scrollHeight < this.opts.maxheight ? this.textarea.scrollHeight : this.opts.maxheight) + "px"; + return this; + }, + getHTML: function() { + if (marked) return marked(this.getMD()); else return this.preview.innerHTML; + }, + setHTML: function(val) { + if (marked) this.preview.innerHTML = marked(val ? val : this.opts.value); + return this; + }, + input: function(evn) { + this.callback = evn; + return this; + } }; if (typeof window.define === "function" && window.define.amd) { window.define(function() { diff --git a/lib/MDEditor.js b/lib/MDEditor.js index 5f13f38..0e00868 100644 --- a/lib/MDEditor.js +++ b/lib/MDEditor.js @@ -140,95 +140,95 @@ css(self.textarea,'min-height',opts.minheight + "px"); css(self.preview,'min-height',opts.minheight + "px"); } - /** - * [load 加载编辑器] - */ - MDEditor.prototype.load = function(){ - var self = this,box = self.obj[0],index=0; - - if(box) { - if(box.innerHTML!=="") - self.opts.value = box.innerHTML - .replace(/\>\;/g,'>') - .replace(/\<\;/g,'<'), - box.innerHTML=''; - box.appendChild(self.preview), - box.appendChild(self.tools), - box.appendChild(self.textarea); - } - self.setMD(); - - addEvent(self.btn_preview,'click', function(event) { - index = parseInt(self.preview.style.zIndex) - if(index === 9){ - self.preview.style.zIndex = 0 - this.innerHTML = "预览" - }else{ - self.preview.style.zIndex = 9 - this.innerHTML = "编辑" - } - self.setHTML(self.getMD()) - css(self.preview,{'height':self.textarea.offsetHeight + "px"}); - }); - css(self.preview,{'height':self.textarea.offsetHeight + "px"}); - - //实时监听输入框值变化 HTML5事件 - addEvent(self.textarea,'input propertychange', function(event) { - if(this.scrollHeight') + .replace(/\<\;/g,'<'), + box.innerHTML=''; + box.appendChild(self.preview), + box.appendChild(self.tools), + box.appendChild(self.textarea); } - css(self.preview,{'height':self.textarea.offsetHeight + "px"}); - self.opts.value = this.value - self.callback(event,self.opts) - }); - return this; - } - /** - * [getMD 获取markdown的字符串] - * @return {[type]} [返回markdown字符串] - */ - MDEditor.prototype.getMD =function(){ - return this.textarea.value - } - - /** - * [setMD 设置markdown的字符串] - */ - MDEditor.prototype.setMD =function(val){ - if(marked) this.textarea.value = val?val:this.opts.value; - this.textarea.style.height = (this.textarea.scrollHeight