Javascript转义所有但文本相关的HTML标签(<h1>,<p>,<img/>等)

时间:2016-09-10 13:44:11

标签: javascript jquery html

使用 Javascript &amp; jQuery ,除了与H1,img等内容相关的标签之外,我怎么能逃脱所有HTML?我已转换markdown text to HTML并将其放入div中,但我不希望我的用户撰写<script>代码,<div>或任何类型的漏洞。

有没有办法可以安全地在我的网站上使用从markdown转换的html?

(一个很好的例子是stackoverflow,这个文本使用markdown但不允许我用<script>alert("Hi");</script>来利用它)

1 个答案:

答案 0 :(得分:0)

编辑:我已将此方法上传到我的github。有关使用的信息,请阅读README。在这里查看我的markdown2html repo

我提出的一种方法是在github上使用marked包并结合自定义函数。

包含marked JS code (位于此答案的底部)之后,您可以使用我所做的以下功能来转义降价内的所有HTML标记除了代码标记内的那些(``)

这是我用纯javascript编写的函数与github上的marked包结合使用;

// INCLUDE MARKED JS CODE (LINK ABOVE) BEFORE USING THIS FUNCTION

function markdownToHTML(markdown) {
    // Define variables
    var re = /``.*?``/g,
        str = markdown,
        lastIndex = 0,
        escaped = "";

    // Escape <, > and & from non-code markdown
    while ((match = re.exec(str)) != null) {
        // Define variables to escape and to leave
        var dangerous = markdown.substring(lastIndex, match.index);
        var safe = match[0];

        // Escape dangerous markdown
        dangerous = dangerous.replace(/<[^>]+>/g, function(wholeMatch, innerTag) {
            while (wholeMatch.charAt(0) == "<")
                wholeMatch = wholeMatch.replace("<", "&lt;");
            while (wholeMatch.charAt(wholeMatch.length - 1) == ">")
                wholeMatch = wholeMatch.replace(/.$/, "&gt;");
            return wholeMatch;
        });

        // Add escaped strings to new escaped string
        escaped += dangerous;
        escaped += safe;

        // Set lastIndex to end index of match
        lastIndex = match.index + match[0].length;
    }

    escaped += markdown.substring(lastIndex, markdown.length).replace(/<[^>]+>/g, function(wholeMatch, innerTag) {
        while (wholeMatch.charAt(0) == "<")
            wholeMatch = wholeMatch.replace("<", "&lt;");
        while (wholeMatch.charAt(wholeMatch.length - 1) == ">")
            wholeMatch = wholeMatch.replace(/.$/, "&gt;");
        return wholeMatch;
    });

    // Return SAFE markdown and convert to HTML
    return marked(escaped);
}

要使用此功能,只需调用它,第一个参数是您想要安全转换为HTML的标记。这是一个例子;

document.body.innerHTML = markdownToHTML("This **text** should be escaped.\nIf I try to create a div by using:\n<div style='width:100px;height:100px;background-color:red;'>My Div</div>\nit will be escaped...\n\nWhere as if I use it in a code section like so:\n``<div style='width:100px;height:100px;background-color:red;'>My Div</div>``\nit should be left alone and **not** escaped.");
  

<强>输出:

Markdown to HTML Output

Use this JS code "Marked" from github to use the marked() function

完整的代码段:

&#13;
&#13;
// Include marked
(function() { function e(e) { this.tokens = [], this.tokens.links = {}, this.options = e || a.defaults, this.rules = p.normal, this.options.gfm && (this.options.tables ? this.rules = p.tables : this.rules = p.gfm) } function t(e, t) { if (this.options = t || a.defaults, this.links = e, this.rules = u.normal, this.renderer = this.options.renderer || new n, this.renderer.options = this.options, !this.links) throw new Error("Tokens array requires a `links` property."); this.options.gfm ? this.options.breaks ? this.rules = u.breaks : this.rules = u.gfm : this.options.pedantic && (this.rules = u.pedantic) } function n(e) { this.options = e || {} } function r(e) { this.tokens = [], this.token = null, this.options = e || a.defaults, this.options.renderer = this.options.renderer || new n, this.renderer = this.options.renderer, this.renderer.options = this.options } function s(e, t) { return e.replace(t ? /&/g : /&(?!#?\w+;)/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;") } function i(e) { return e.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(e, t) { return t = t.toLowerCase(), "colon" === t ? ":" : "#" === t.charAt(0) ? "x" === t.charAt(1) ? String.fromCharCode(parseInt(t.substring(2), 16)) : String.fromCharCode(+t.substring(1)) : "" }) } function l(e, t) { return e = e.source, t = t || "", function n(r, s) { return r ? (s = s.source || s, s = s.replace(/(^|[^\[])\^/g, "$1"), e = e.replace(r, s), n) : new RegExp(e, t) } } function o() { } function h(e) { for (var t, n, r = 1; r < arguments.length; r++){ t = arguments[r]; for (n in t) Object.prototype.hasOwnProperty.call(t, n) && (e[n] = t[n]) } return e } function a(t, n, i) { if (i || "function" == typeof n) { i || (i = n, n = null), n = h({}, a.defaults, n || {}); var l, o, p = n.highlight, u = 0; try { l = e.lex(t, n) } catch (c) { return i(c) } o = l.length; var g = function(e) { if (e) return n.highlight = p, i(e); var t; try { t = r.parse(l, n) } catch (s) { e = s } return n.highlight = p, e ? i(e) : i(null, t) }; if (!p || p.length < 3) return g(); if (delete n.highlight, !o) return g(); for (; u < l.length; u++)!function(e) { return "code" !== e.type ? --o || g() : p(e.text, e.lang, function(t, n) { return t ? g(t) : null == n || n === e.text ? --o || g() : (e.text = n, e.escaped = !0, void (--o || g())) }) } (l[u]) } else try { return n && (n = h({}, a.defaults, n)), r.parse(e.lex(t, n), n) } catch (c) { if (c.message += "\nPlease report this to https://github.com/chjj/marked.", (n || a.defaults).silent) return "<p>An error occured:</p><pre>" + s(c.message + "", !0) + "</pre>"; throw c } } var p = { newline: /^\n+/, code: /^( {4}[^\n]+\n*)+/, fences: o, hr: /^( *[-*_]){3,} *(?:\n+|$)/, heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, nptable: o, lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, table: o, paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, text: /^[^\n]+/ }; p.bullet = /(?:[*+-]|\d+\.)/, p.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/, p.item = l(p.item, "gm")(/bull/g, p.bullet)(), p.list = l(p.list)(/bull/g, p.bullet)("hr", "\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def", "\\n+(?=" + p.def.source + ")")(), p.blockquote = l(p.blockquote)("def", p.def)(), p._tag = "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b", p.html = l(p.html)("comment", /<!--[\s\S]*?-->/)("closed", /<(tag)[\s\S]+?<\/\1>/)("closing", /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g, p._tag)(), p.paragraph = l(p.paragraph)("hr", p.hr)("heading", p.heading)("lheading", p.lheading)("blockquote", p.blockquote)("tag", "<" + p._tag)("def", p.def)(), p.normal = h({}, p), p.gfm = h({}, p.normal, { fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/, paragraph: /^/, heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ }), p.gfm.paragraph = l(p.paragraph)("(?!", "(?!" + p.gfm.fences.source.replace("\\1", "\\2") + "|" + p.list.source.replace("\\1", "\\3") + "|")(), p.tables = h({}, p.gfm, { nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ }), e.rules = p, e.lex = function(t, n) { var r = new e(n); return r.lex(t) }, e.prototype.lex = function(e) { return e = e.replace(/\r\n|\r/g, "\n").replace(/\t/g, "    ").replace(/\u00a0/g, " ").replace(/\u2424/g, "\n"), this.token(e, !0) }, e.prototype.token = function(e, t, n) { for (var r, s, i, l, o, h, a, u, c, e = e.replace(/^ +$/gm, ""); e;)if ((i = this.rules.newline.exec(e)) && (e = e.substring(i[0].length), i[0].length > 1 && this.tokens.push({ type: "space" })), i = this.rules.code.exec(e)) e = e.substring(i[0].length), i = i[0].replace(/^ {4}/gm, ""), this.tokens.push({ type: "code", text: this.options.pedantic ? i : i.replace(/\n+$/, "") }); else if (i = this.rules.fences.exec(e)) e = e.substring(i[0].length), this.tokens.push({ type: "code", lang: i[2], text: i[3] || "" }); else if (i = this.rules.heading.exec(e)) e = e.substring(i[0].length), this.tokens.push({ type: "heading", depth: i[1].length, text: i[2] }); else if (t && (i = this.rules.nptable.exec(e))) { for (e = e.substring(i[0].length), h = { type: "table", header: i[1].replace(/^ *| *\| *$/g, "").split(/ *\| */), align: i[2].replace(/^ *|\| *$/g, "").split(/ *\| */), cells: i[3].replace(/\n$/, "").split("\n") }, u = 0; u < h.align.length; u++)/^ *-+: *$/.test(h.align[u]) ? h.align[u] = "right" : /^ *:-+: *$/.test(h.align[u]) ? h.align[u] = "center" : /^ *:-+ *$/.test(h.align[u]) ? h.align[u] = "left" : h.align[u] = null; for (u = 0; u < h.cells.length; u++)h.cells[u] = h.cells[u].split(/ *\| */); this.tokens.push(h) } else if (i = this.rules.lheading.exec(e)) e = e.substring(i[0].length), this.tokens.push({ type: "heading", depth: "=" === i[2] ? 1 : 2, text: i[1] }); else if (i = this.rules.hr.exec(e)) e = e.substring(i[0].length), this.tokens.push({ type: "hr" }); else if (i = this.rules.blockquote.exec(e)) e = e.substring(i[0].length), this.tokens.push({ type: "blockquote_start" }), i = i[0].replace(/^ *> ?/gm, ""), this.token(i, t, !0), this.tokens.push({ type: "blockquote_end" }); else if (i = this.rules.list.exec(e)) { for (e = e.substring(i[0].length), l = i[2], this.tokens.push({ type: "list_start", ordered: l.length > 1 }), i = i[0].match(this.rules.item), r = !1, c = i.length, u = 0; c > u; u++)h = i[u], a = h.length, h = h.replace(/^ *([*+-]|\d+\.) +/, ""), ~h.indexOf("\n ") && (a -= h.length, h = this.options.pedantic ? h.replace(/^ {1,4}/gm, "") : h.replace(new RegExp("^ {1," + a + "}", "gm"), "")), this.options.smartLists && u !== c - 1 && (o = p.bullet.exec(i[u + 1])[0], l === o || l.length > 1 && o.length > 1 || (e = i.slice(u + 1).join("\n") + e, u = c - 1)), s = r || /\n\n(?!\s*$)/.test(h), u !== c - 1 && (r = "\n" === h.charAt(h.length - 1), s || (s = r)), this.tokens.push({ type: s ? "loose_item_start" : "list_item_start" }), this.token(h, !1, n), this.tokens.push({ type: "list_item_end" }); this.tokens.push({ type: "list_end" }) } else if (i = this.rules.html.exec(e)) e = e.substring(i[0].length), this.tokens.push({ type: this.options.sanitize ? "paragraph" : "html", pre: !this.options.sanitizer && ("pre" === i[1] || "script" === i[1] || "style" === i[1]), text: i[0] }); else if (!n && t && (i = this.rules.def.exec(e))) e = e.substring(i[0].length), this.tokens.links[i[1].toLowerCase()] = { href: i[2], title: i[3] }; else if (t && (i = this.rules.table.exec(e))) { for (e = e.substring(i[0].length), h = { type: "table", header: i[1].replace(/^ *| *\| *$/g, "").split(/ *\| */), align: i[2].replace(/^ *|\| *$/g, "").split(/ *\| */), cells: i[3].replace(/(?: *\| *)?\n$/, "").split("\n") }, u = 0; u < h.align.length; u++)/^ *-+: *$/.test(h.align[u]) ? h.align[u] = "right" : /^ *:-+: *$/.test(h.align[u]) ? h.align[u] = "center" : /^ *:-+ *$/.test(h.align[u]) ? h.align[u] = "left" : h.align[u] = null; for (u = 0; u < h.cells.length; u++)h.cells[u] = h.cells[u].replace(/^ *\| *| *\| *$/g, "").split(/ *\| */); this.tokens.push(h) } else if (t && (i = this.rules.paragraph.exec(e))) e = e.substring(i[0].length), this.tokens.push({ type: "paragraph", text: "\n" === i[1].charAt(i[1].length - 1) ? i[1].slice(0, -1) : i[1] }); else if (i = this.rules.text.exec(e)) e = e.substring(i[0].length), this.tokens.push({ type: "text", text: i[0] }); else if (e) throw new Error("Infinite loop on byte: " + e.charCodeAt(0)); return this.tokens }; var u = { escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, url: o, tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, link: /^!?\[(inside)\]\(href\)/, reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, br: /^ {2,}\n(?!\s*$)/, del: o, text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/ }; u._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/, u._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/, u.link = l(u.link)("inside", u._inside)("href", u._href)(), u.reflink = l(u.reflink)("inside", u._inside)(), u.normal = h({}, u), u.pedantic = h({}, u.normal, { strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ }), u.gfm = h({}, u.normal, { escape: l(u.escape)("])", "~|])")(), url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, del: /^~~(?=\S)([\s\S]*?\S)~~/, text: l(u.text)("]|", "~]|")("|", "|https?://|")() }), u.breaks = h({}, u.gfm, { br: l(u.br)("{2,}", "*")(), text: l(u.gfm.text)("{2,}", "*")() }), t.rules = u, t.output = function(e, n, r) { var s = new t(n, r); return s.output(e) }, t.prototype.output = function(e) { for (var t, n, r, i, l = ""; e;)if (i = this.rules.escape.exec(e)) e = e.substring(i[0].length), l += i[1]; else if (i = this.rules.autolink.exec(e)) e = e.substring(i[0].length), "@" === i[2] ? (n = ":" === i[1].charAt(6) ? this.mangle(i[1].substring(7)) : this.mangle(i[1]), r = this.mangle("mailto:") + n) : (n = s(i[1]), r = n), l += this.renderer.link(r, null, n); else if (this.inLink || !(i = this.rules.url.exec(e))) { if (i = this.rules.tag.exec(e)) !this.inLink && /^<a /i.test(i[0]) ? this.inLink = !0 : this.inLink && /^<\/a>/i.test(i[0]) && (this.inLink = !1), e = e.substring(i[0].length), l += this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(i[0]) : s(i[0]) : i[0]; else if (i = this.rules.link.exec(e)) e = e.substring(i[0].length), this.inLink = !0, l += this.outputLink(i, { href: i[2], title: i[3] }), this.inLink = !1; else if ((i = this.rules.reflink.exec(e)) || (i = this.rules.nolink.exec(e))) { if (e = e.substring(i[0].length), t = (i[2] || i[1]).replace(/\s+/g, " "), t = this.links[t.toLowerCase()], !t || !t.href) { l += i[0].charAt(0), e = i[0].substring(1) + e; continue } this.inLink = !0, l += this.outputLink(i, t), this.inLink = !1 } else if (i = this.rules.strong.exec(e)) e = e.substring(i[0].length), l += this.renderer.strong(this.output(i[2] || i[1])); else if (i = this.rules.em.exec(e)) e = e.substring(i[0].length), l += this.renderer.em(this.output(i[2] || i[1])); else if (i = this.rules.code.exec(e)) e = e.substring(i[0].length), l += this.renderer.codespan(s(i[2], !0)); else if (i = this.rules.br.exec(e)) e = e.substring(i[0].length), l += this.renderer.br(); else if (i = this.rules.del.exec(e)) e = e.substring(i[0].length), l += this.renderer.del(this.output(i[1])); else if (i = this.rules.text.exec(e)) e = e.substring(i[0].length), l += this.renderer.text(s(this.smartypants(i[0]))); else if (e) throw new Error("Infinite loop on byte: " + e.charCodeAt(0)) } else e = e.substring(i[0].length), n = s(i[1]), r = n, l += this.renderer.link(r, null, n); return l }, t.prototype.outputLink = function(e, t) { var n = s(t.href), r = t.title ? s(t.title) : null; return "!" !== e[0].charAt(0) ? this.renderer.link(n, r, this.output(e[1])) : this.renderer.image(n, r, s(e[1])) }, t.prototype.smartypants = function(e) { return this.options.smartypants ? e.replace(/---/g, "—").replace(/--/g, "–").replace(/(^|[-\u2014\/(\[{"\s])'/g, "$1‘").replace(/'/g, "’").replace(/(^|[-\u2014\/(\[{\u2018\s])"/g, "$1“").replace(/"/g, "”").replace(/\.{3}/g, "…") : e }, t.prototype.mangle = function(e) { if (!this.options.mangle) return e; for (var t, n = "", r = e.length, s = 0; r > s; s++)t = e.charCodeAt(s), Math.random() > .5 && (t = "x" + t.toString(16)), n += "&#" + t + ";"; return n }, n.prototype.code = function(e, t, n) { if (this.options.highlight) { var r = this.options.highlight(e, t); null != r && r !== e && (n = !0, e = r) } return t ? '<pre><code class="' + this.options.langPrefix + s(t, !0) + '">' + (n ? e : s(e, !0)) + "\n</code></pre>\n" : "<pre><code>" + (n ? e : s(e, !0)) + "\n</code></pre>" }, n.prototype.blockquote = function(e) { return "<blockquote>\n" + e + "</blockquote>\n" }, n.prototype.html = function(e) { return e }, n.prototype.heading = function(e, t, n) { return "<h" + t + ' id="' + this.options.headerPrefix + n.toLowerCase().replace(/[^\w]+/g, "-") + '">' + e + "</h" + t + ">\n" }, n.prototype.hr = function() { return this.options.xhtml ? "<hr/>\n" : "<hr>\n" }, n.prototype.list = function(e, t) { var n = t ? "ol" : "ul"; return "<" + n + ">\n" + e + "</" + n + ">\n" }, n.prototype.listitem = function(e) { return "<li>" + e + "</li>\n" }, n.prototype.paragraph = function(e) { return "<p>" + e + "</p>\n" }, n.prototype.table = function(e, t) { return "<table>\n<thead>\n" + e + "</thead>\n<tbody>\n" + t + "</tbody>\n</table>\n" }, n.prototype.tablerow = function(e) { return "<tr>\n" + e + "</tr>\n" }, n.prototype.tablecell = function(e, t) { var n = t.header ? "th" : "td", r = t.align ? "<" + n + ' style="text-align:' + t.align + '">' : "<" + n + ">"; return r + e + "</" + n + ">\n" }, n.prototype.strong = function(e) { return "<strong>" + e + "</strong>" }, n.prototype.em = function(e) { return "<em>" + e + "</em>" }, n.prototype.codespan = function(e) { return "<code>" + e + "</code>" }, n.prototype.br = function() { return this.options.xhtml ? "<br/>" : "<br>" }, n.prototype.del = function(e) { return "<del>" + e + "</del>" }, n.prototype.link = function(e, t, n) { if (this.options.sanitize) { try { var r = decodeURIComponent(i(e)).replace(/[^\w:]/g, "").toLowerCase() } catch (s) { return "" } if (0 === r.indexOf("javascript:") || 0 === r.indexOf("vbscript:")) return "" } var l = '<a href="' + e + '"'; return t && (l += ' title="' + t + '"'), l += ">" + n + "</a>" }, n.prototype.image = function(e, t, n) { var r = '<img src="' + e + '" alt="' + n + '"'; return t && (r += ' title="' + t + '"'), r += this.options.xhtml ? "/>" : ">" }, n.prototype.text = function(e) { return e }, r.parse = function(e, t, n) { var s = new r(t, n); return s.parse(e) }, r.prototype.parse = function(e) { this.inline = new t(e.links, this.options, this.renderer), this.tokens = e.reverse(); for (var n = ""; this.next();)n += this.tok(); return n }, r.prototype.next = function() { return this.token = this.tokens.pop() }, r.prototype.peek = function() { return this.tokens[this.tokens.length - 1] || 0 }, r.prototype.parseText = function() { for (var e = this.token.text; "text" === this.peek().type;)e += "\n" + this.next().text; return this.inline.output(e) }, r.prototype.tok = function() { switch (this.token.type) { case "space": return ""; case "hr": return this.renderer.hr(); case "heading": return this.renderer.heading(this.inline.output(this.token.text), this.token.depth, this.token.text); case "code": return this.renderer.code(this.token.text, this.token.lang, this.token.escaped); case "table": var e, t, n, r, s, i = "", l = ""; for (n = "", e = 0; e < this.token.header.length; e++)r = { header: !0, align: this.token.align[e] }, n += this.renderer.tablecell(this.inline.output(this.token.header[e]), { header: !0, align: this.token.align[e] }); for (i += this.renderer.tablerow(n), e = 0; e < this.token.cells.length; e++){ for (t = this.token.cells[e], n = "", s = 0; s < t.length; s++)n += this.renderer.tablecell(this.inline.output(t[s]), { header: !1, align: this.token.align[s] }); l += this.renderer.tablerow(n) } return this.renderer.table(i, l); case "blockquote_start": for (var l = ""; "blockquote_end" !== this.next().type;)l += this.tok(); return this.renderer.blockquote(l); case "list_start": for (var l = "", o = this.token.ordered; "list_end" !== this.next().type;)l += this.tok(); return this.renderer.list(l, o); case "list_item_start": for (var l = ""; "list_item_end" !== this.next().type;)l += "text" === this.token.type ? this.parseText() : this.tok(); return this.renderer.listitem(l); case "loose_item_start": for (var l = ""; "list_item_end" !== this.next().type;)l += this.tok(); return this.renderer.listitem(l); case "html": var h = this.token.pre || this.options.pedantic ? this.token.text : this.inline.output(this.token.text); return this.renderer.html(h); case "paragraph": return this.renderer.paragraph(this.inline.output(this.token.text)); case "text": return this.renderer.paragraph(this.parseText()) } }, o.exec = o, a.options = a.setOptions = function(e) { return h(a.defaults, e), a }, a.defaults = { gfm: !0, tables: !0, breaks: !1, pedantic: !1, sanitize: !1, sanitizer: null, mangle: !0, smartLists: !1, silent: !1, highlight: null, langPrefix: "lang-", smartypants: !1, headerPrefix: "", renderer: new n, xhtml: !1 }, a.Parser = r, a.parser = r.parse, a.Renderer = n, a.Lexer = e, a.lexer = e.lex, a.InlineLexer = t, a.inlineLexer = t.output, a.parse = a, "undefined" != typeof module && "object" == typeof exports ? module.exports = a : "function" == typeof define && define.amd ? define(function() { return a }) : this.marked = a }).call(function() { return this || ("undefined" != typeof window ? window : global) } ());

function markdownToHTML(markdown) {
	// Define variables
	var re = /``.*?``/g,
		str = markdown,
		lastIndex = 0,
		escaped = "";
	
	// Escape <, > and & from non-code markdown
	while ((match = re.exec(str)) != null) {
		// Define variables to escape and to leave
		var dangerous = markdown.substring(lastIndex, match.index);
		var safe = match[0];

		// Escape dangerous markdown
		dangerous = dangerous.replace(/<[^>]+>/g, function(wholeMatch, innerTag) {
			while (wholeMatch.charAt(0) == "<")
				wholeMatch = wholeMatch.replace("<", "&lt;");
			while (wholeMatch.charAt(wholeMatch.length - 1) == ">")
				wholeMatch = wholeMatch.replace(/.$/, "&gt;");
			return wholeMatch;
		});

		// Add escaped strings to new escaped string
		escaped += dangerous;
		escaped += safe;

		// Set lastIndex to end index of match
		lastIndex = match.index + match[0].length;
	}

	escaped += markdown.substring(lastIndex, markdown.length).replace(/<[^>]+>/g, function(wholeMatch, innerTag) {
		while (wholeMatch.charAt(0) == "<")
			wholeMatch = wholeMatch.replace("<", "&lt;");
		while (wholeMatch.charAt(wholeMatch.length - 1) == ">")
			wholeMatch = wholeMatch.replace(/.$/, "&gt;");
		return wholeMatch;
	});

	// Return SAFE markdown and convert to HTML
	return marked(escaped);
}

document.getElementById("converted-markdown").innerHTML = markdownToHTML("This **text** should be escaped.\nIf I try to create a div by using:\n<div style='width:100px;height:100px;background-color:red;'>My Div</div>\nit will be escaped...\n\nWhere as if I use it in a code section like so:\n``<div style='width:100px;height:100px;background-color:red;'>My Div</div>``\nit should be left alone and **not** escaped.");
&#13;
<div id="converted-markdown"></div>
&#13;
&#13;
&#13;