Comparing version 0.2.0 to 0.3.0
@@ -62,2 +62,2 @@ // | ||
// | ||
var Showdown={};Showdown.converter=function(){var a,b,c,d=0;this.makeHtml=function(d){return a=new Array,b=new Array,c=new Array,d=d.replace(/~/g,"~T"),d=d.replace(/\$/g,"~D"),d=d.replace(/\r\n/g,"\n"),d=d.replace(/\r/g,"\n"),d="\n\n"+d+"\n\n",d=F(d),d=d.replace(/^[ \t]+$/mg,""),d=f(d),d=e(d),d=h(d),d=D(d),d=d.replace(/~D/g,"$$"),d=d.replace(/~T/g,"~"),d};var e=function(c){var c=c.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,function(c,d,e,f,g){return d=d.toLowerCase(),a[d]=z(e),f?f+g:(g&&(b[d]=g.replace(/"/g,""")),"")});return c},f=function(a){a=a.replace(/\n/g,"\n\n");var b="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del",c="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math";return a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,g),a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,g),a=a.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,g),a=a.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,g),a=a.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,g),a=a.replace(/\n\n/g,"\n"),a},g=function(a,b){var d=b;return d=d.replace(/\n\n/g,"\n"),d=d.replace(/^\n/,""),d=d.replace(/\n+$/g,""),d="\n\n~K"+(c.push(d)-1)+"K\n\n",d},h=function(a){a=o(a);var b=t("<hr />");return a=a.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,b),a=a.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,b),a=a.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,b),a=q(a),a=s(a),a=r(a),a=x(a),a=f(a),a=y(a),a},i=function(a){return a=u(a),a=j(a),a=A(a),a=m(a),a=k(a),a=B(a),a=z(a),a=w(a),a=a.replace(/ +\n/g," <br />\n"),a},j=function(a){var b=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;return a=a.replace(b,function(a){var b=a.replace(/(.)<\/?code>(?=.)/g,"$1`");return b=G(b,"\\`*_"),b}),a},k=function(a){return a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,l),a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,l),a=a.replace(/(\[([^\[\]]+)\])()()()()()/g,l),a},l=function(c,d,e,f,g,h,i,j){j==undefined&&(j="");var k=d,l=e,m=f.toLowerCase(),n=g,o=j;if(n==""){m==""&&(m=l.toLowerCase().replace(/ ?\n/g," ")),n="#"+m;if(a[m]!=undefined)n=a[m],b[m]!=undefined&&(o=b[m]);else{if(!(k.search(/\(\s*\)$/m)>-1))return k;n=""}}n=G(n,"*_");var p='<a href="'+n+'"';return o!=""&&(o=o.replace(/"/g,"""),o=G(o,"*_"),p+=' title="'+o+'"'),p+=">"+l+"</a>",p},m=function(a){return a=a.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,n),a=a.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,n),a},n=function(c,d,e,f,g,h,i,j){var k=d,l=e,m=f.toLowerCase(),n=g,o=j;o||(o="");if(n==""){m==""&&(m=l.toLowerCase().replace(/ ?\n/g," ")),n="#"+m;if(a[m]==undefined)return k;n=a[m],b[m]!=undefined&&(o=b[m])}l=l.replace(/"/g,"""),n=G(n,"*_");var p='<img src="'+n+'" alt="'+l+'"';return o=o.replace(/"/g,"""),o=G(o,"*_"),p+=' title="'+o+'"',p+=" />",p},o=function(a){function b(a){return a.replace(/[^\w]/g,"").toLowerCase()}return a=a.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(a,c){return t('<h1 id="'+b(c)+'">'+i(c)+"</h1>")}),a=a.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(a,c){return t('<h2 id="'+b(c)+'">'+i(c)+"</h2>")}),a=a.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(a,c,d){var e=c.length;return t("<h"+e+' id="'+b(d)+'">'+i(d)+"</h"+e+">")}),a},p,q=function(a){a+="~0";var b=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;return d?a=a.replace(b,function(a,b,c){var d=b,e=c.search(/[*+-]/g)>-1?"ul":"ol";d=d.replace(/\n{2,}/g,"\n\n\n");var f=p(d);return f=f.replace(/\s+$/,""),f="<"+e+">"+f+"</"+e+">\n",f}):(b=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g,a=a.replace(b,function(a,b,c,d){var e=b,f=c,g=d.search(/[*+-]/g)>-1?"ul":"ol",f=f.replace(/\n{2,}/g,"\n\n\n"),h=p(f);return h=e+"<"+g+">\n"+h+"</"+g+">\n",h})),a=a.replace(/~0/,""),a};p=function(a){return d++,a=a.replace(/\n{2,}$/,"\n"),a+="~0",a=a.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(a,b,c,d,e){var f=e,g=b,j=c;return g||f.search(/\n{2,}/)>-1?f=h(E(f)):(f=q(E(f)),f=f.replace(/\n$/,""),f=i(f)),"<li>"+f+"</li>\n"}),a=a.replace(/~0/g,""),d--,a};var r=function(a){return a+="~0",a=a.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(a,b,c){var d=b,e=c;return d=v(E(d)),d=F(d),d=d.replace(/^\n+/g,""),d=d.replace(/\n+$/g,""),d="<pre><code>"+d+"\n</code></pre>",t(d)+e}),a=a.replace(/~0/,""),a},s=function(a){return a+="~0",a=a.replace(/\n```(.*)\n([^`]+)\n```/g,function(a,b,c){var d=b,e=c;return e=v(e),e=F(e),e=e.replace(/^\n+/g,""),e=e.replace(/\n+$/g,""),e="<pre><code class="+d+">"+e+"\n</code></pre>",t(e)}),a=a.replace(/~0/,""),a},t=function(a){return a=a.replace(/(^\n+|\n+$)/g,""),"\n\n~K"+(c.push(a)-1)+"K\n\n"},u=function(a){return a=a.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(a,b,c,d,e){var f=d;return f=f.replace(/^([ \t]*)/g,""),f=f.replace(/[ \t]*$/g,""),f=v(f),b+"<code>"+f+"</code>"}),a},v=function(a){return a=a.replace(/&/g,"&"),a=a.replace(/</g,"<"),a=a.replace(/>/g,">"),a=G(a,"*_{}[]\\",!1),a},w=function(a){return a=a.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,"<strong>$2</strong>"),a=a.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"<em>$2</em>"),a},x=function(a){return a=a.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(a,b){var c=b;return c=c.replace(/^[ \t]*>[ \t]?/gm,"~0"),c=c.replace(/~0/g,""),c=c.replace(/^[ \t]+$/gm,""),c=h(c),c=c.replace(/(^|\n)/g,"$1 "),c=c.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(a,b){var c=b;return c=c.replace(/^ /mg,"~0"),c=c.replace(/~0/g,""),c}),t("<blockquote>\n"+c+"\n</blockquote>")}),a},y=function(a){a=a.replace(/^\n+/g,""),a=a.replace(/\n+$/g,"");var b=a.split(/\n{2,}/g),d=new Array,e=b.length;for(var f=0;f<e;f++){var g=b[f];g.search(/~K(\d+)K/g)>=0?d.push(g):g.search(/\S/)>=0&&(g=i(g),g=g.replace(/^([ \t]*)/g,"<p>"),g+="</p>",d.push(g))}e=d.length;for(var f=0;f<e;f++)while(d[f].search(/~K(\d+)K/)>=0){var h=c[RegExp.$1];h=h.replace(/\$/g,"$$$$"),d[f]=d[f].replace(/~K\d+K/,h)}return d.join("\n\n")},z=function(a){return a=a.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"),a=a.replace(/<(?![a-z\/?\$!])/gi,"<"),a},A=function(a){return a=a.replace(/\\(\\)/g,H),a=a.replace(/\\([`*_{}\[\]()>#+-.!])/g,H),a},B=function(a){return a=a.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,'<a href="$1">$1</a>'),a=a.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(a,b){return C(D(b))}),a},C=function(a){function b(a){var b="0123456789ABCDEF",c=a.charCodeAt(0);return b.charAt(c>>4)+b.charAt(c&15)}var c=[function(a){return"&#"+a.charCodeAt(0)+";"},function(a){return"&#x"+b(a)+";"},function(a){return a}];return a="mailto:"+a,a=a.replace(/./g,function(a){if(a=="@")a=c[Math.floor(Math.random()*2)](a);else if(a!=":"){var b=Math.random();a=b>.9?c[2](a):b>.45?c[1](a):c[0](a)}return a}),a='<a href="'+a+'">'+a+"</a>",a=a.replace(/">.+:/g,'">'),a},D=function(a){return a=a.replace(/~E(\d+)E/g,function(a,b){var c=parseInt(b);return String.fromCharCode(c)}),a},E=function(a){return a=a.replace(/^(\t|[ ]{1,4})/gm,"~0"),a=a.replace(/~0/g,""),a},F=function(a){return a=a.replace(/\t(?=\t)/g," "),a=a.replace(/\t/g,"~A~B"),a=a.replace(/~B(.+?)~A/g,function(a,b,c){var d=b,e=4-d.length%4;for(var f=0;f<e;f++)d+=" ";return d}),a=a.replace(/~A/g," "),a=a.replace(/~B/g,""),a},G=function(a,b,c){var d="(["+b.replace(/([\[\]\\])/g,"\\$1")+"])";c&&(d="\\\\"+d);var e=new RegExp(d,"g");return a=a.replace(e,H),a},H=function(a,b){var c=b.charCodeAt(0);return"~E"+c+"E"}},typeof exports!="undefined"&&(exports=Showdown); | ||
var Showdown={extensions:{}},forEach=Showdown.forEach=function(a,b){if(typeof a.forEach=="function")a.forEach(b);else{var c,d=a.length;for(c=0;c<d;c++)b(a[c],c,a)}},stdExtName=function(a){return a.replace(/[_-]||\s/g,"").toLowerCase()};Showdown.converter=function(a){var b,c,d,e=0,f=[],g=[];if(typeof module!="undefind"&&typeof exports!="undefined"&&typeof require!="undefind"){var h=require("fs");if(h){var i=h.readdirSync((__dirname||".")+"/extensions").filter(function(a){return~a.indexOf(".js")}).map(function(a){return a.replace(/\.js$/,"")});i.forEach(function(a){var b=stdExtName(a);Showdown.extensions[b]=require("./extensions/"+a)})}}a&&a.extensions&&a.extensions.forEach(function(a){typeof a=="string"&&(a=Showdown.extensions[stdExtName(a)]);if(typeof a!="function")throw"Extension '"+a+"' could not be loaded. It was either not found or is not a valid extension.";a(this).forEach(function(a){a.type?a.type==="language"||a.type==="lang"?f.push(a):(a.type==="output"||a.type==="html")&&g.push(a):g.push(a)})}),this.makeHtml=function(a){return b={},c={},d=[],a=a.replace(/~/g,"~T"),a=a.replace(/\$/g,"~D"),a=a.replace(/\r\n/g,"\n"),a=a.replace(/\r/g,"\n"),a="\n\n"+a+"\n\n",a=L(a),a=a.replace(/^[ \t]+$/mg,""),f.forEach(function(b){a=j(b,a)}),a=y(a),a=l(a),a=k(a),a=n(a),a=J(a),a=a.replace(/~D/g,"$$"),a=a.replace(/~T/g,"~"),g.forEach(function(b){a=j(b,a)}),a};var j=function(a,b){if(a.regex){var c=new RegExp(a.regex,"g");return b.replace(c,a.replace)}if(a.filter)return a.filter(b)},k=function(a){return a+="~0",a=a.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm,function(a,d,e,f,g){return d=d.toLowerCase(),b[d]=F(e),f?f+g:(g&&(c[d]=g.replace(/"/g,""")),"")}),a=a.replace(/~0/,""),a},l=function(a){a=a.replace(/\n/g,"\n\n");var b="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside",c="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside";return a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,m),a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm,m),a=a.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,m),a=a.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,m),a=a.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,m),a=a.replace(/\n\n/g,"\n"),a},m=function(a,b){var c=b;return c=c.replace(/\n\n/g,"\n"),c=c.replace(/^\n/,""),c=c.replace(/\n+$/g,""),c="\n\n~K"+(d.push(c)-1)+"K\n\n",c},n=function(a){a=u(a);var b=z("<hr />");return a=a.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,b),a=a.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,b),a=a.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,b),a=w(a),a=x(a),a=D(a),a=l(a),a=E(a),a},o=function(a){return a=A(a),a=p(a),a=G(a),a=s(a),a=q(a),a=H(a),a=F(a),a=C(a),a=a.replace(/ +\n/g," <br />\n"),a},p=function(a){var b=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;return a=a.replace(b,function(a){var b=a.replace(/(.)<\/?code>(?=.)/g,"$1`");return b=M(b,"\\`*_"),b}),a},q=function(a){return a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,r),a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,r),a=a.replace(/(\[([^\[\]]+)\])()()()()()/g,r),a},r=function(a,d,e,f,g,h,i,j){j==undefined&&(j="");var k=d,l=e,m=f.toLowerCase(),n=g,o=j;if(n==""){m==""&&(m=l.toLowerCase().replace(/ ?\n/g," ")),n="#"+m;if(b[m]!=undefined)n=b[m],c[m]!=undefined&&(o=c[m]);else{if(!(k.search(/\(\s*\)$/m)>-1))return k;n=""}}n=M(n,"*_");var p='<a href="'+n+'"';return o!=""&&(o=o.replace(/"/g,"""),o=M(o,"*_"),p+=' title="'+o+'"'),p+=">"+l+"</a>",p},s=function(a){return a=a.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,t),a=a.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,t),a},t=function(a,d,e,f,g,h,i,j){var k=d,l=e,m=f.toLowerCase(),n=g,o=j;o||(o="");if(n==""){m==""&&(m=l.toLowerCase().replace(/ ?\n/g," ")),n="#"+m;if(b[m]==undefined)return k;n=b[m],c[m]!=undefined&&(o=c[m])}l=l.replace(/"/g,"""),n=M(n,"*_");var p='<img src="'+n+'" alt="'+l+'"';return o=o.replace(/"/g,"""),o=M(o,"*_"),p+=' title="'+o+'"',p+=" />",p},u=function(a){function b(a){return a.replace(/[^\w]/g,"").toLowerCase()}return a=a.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(a,c){return z('<h1 id="'+b(c)+'">'+o(c)+"</h1>")}),a=a.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(a,c){return z('<h2 id="'+b(c)+'">'+o(c)+"</h2>")}),a=a.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(a,c,d){var e=c.length;return z("<h"+e+' id="'+b(d)+'">'+o(d)+"</h"+e+">")}),a},v,w=function(a){a+="~0";var b=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;return e?a=a.replace(b,function(a,b,c){var d=b,e=c.search(/[*+-]/g)>-1?"ul":"ol";d=d.replace(/\n{2,}/g,"\n\n\n");var f=v(d);return f=f.replace(/\s+$/,""),f="<"+e+">"+f+"</"+e+">\n",f}):(b=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g,a=a.replace(b,function(a,b,c,d){var e=b,f=c,g=d.search(/[*+-]/g)>-1?"ul":"ol",f=f.replace(/\n{2,}/g,"\n\n\n"),h=v(f);return h=e+"<"+g+">\n"+h+"</"+g+">\n",h})),a=a.replace(/~0/,""),a};v=function(a){return e++,a=a.replace(/\n{2,}$/,"\n"),a+="~0",a=a.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(a,b,c,d,e){var f=e,g=b,h=c;return g||f.search(/\n{2,}/)>-1?f=n(K(f)):(f=w(K(f)),f=f.replace(/\n$/,""),f=o(f)),"<li>"+f+"</li>\n"}),a=a.replace(/~0/g,""),e--,a};var x=function(a){return a+="~0",a=a.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(a,b,c){var d=b,e=c;return d=B(K(d)),d=L(d),d=d.replace(/^\n+/g,""),d=d.replace(/\n+$/g,""),d="<pre><code>"+d+"\n</code></pre>",z(d)+e}),a=a.replace(/~0/,""),a},y=function(a){return a+="~0",a=a.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,function(a,b,c){var d=b,e=c;return e=B(e),e=L(e),e=e.replace(/^\n+/g,""),e=e.replace(/\n+$/g,""),e="<pre><code"+(d?' class="'+d+'"':"")+">"+e+"\n</code></pre>",z(e)}),a=a.replace(/~0/,""),a},z=function(a){return a=a.replace(/(^\n+|\n+$)/g,""),"\n\n~K"+(d.push(a)-1)+"K\n\n"},A=function(a){return a=a.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(a,b,c,d,e){var f=d;return f=f.replace(/^([ \t]*)/g,""),f=f.replace(/[ \t]*$/g,""),f=B(f),b+"<code>"+f+"</code>"}),a},B=function(a){return a=a.replace(/&/g,"&"),a=a.replace(/</g,"<"),a=a.replace(/>/g,">"),a=M(a,"*_{}[]\\",!1),a},C=function(a){return a=a.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,"<strong>$2</strong>"),a=a.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"<em>$2</em>"),a},D=function(a){return a=a.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(a,b){var c=b;return c=c.replace(/^[ \t]*>[ \t]?/gm,"~0"),c=c.replace(/~0/g,""),c=c.replace(/^[ \t]+$/gm,""),c=n(c),c=c.replace(/(^|\n)/g,"$1 "),c=c.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(a,b){var c=b;return c=c.replace(/^ /mg,"~0"),c=c.replace(/~0/g,""),c}),z("<blockquote>\n"+c+"\n</blockquote>")}),a},E=function(a){a=a.replace(/^\n+/g,""),a=a.replace(/\n+$/g,"");var b=a.split(/\n{2,}/g),c=[],e=b.length;for(var f=0;f<e;f++){var g=b[f];g.search(/~K(\d+)K/g)>=0?c.push(g):g.search(/\S/)>=0&&(g=o(g),g=g.replace(/^([ \t]*)/g,"<p>"),g+="</p>",c.push(g))}e=c.length;for(var f=0;f<e;f++)while(c[f].search(/~K(\d+)K/)>=0){var h=d[RegExp.$1];h=h.replace(/\$/g,"$$$$"),c[f]=c[f].replace(/~K\d+K/,h)}return c.join("\n\n")},F=function(a){return a=a.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"),a=a.replace(/<(?![a-z\/?\$!])/gi,"<"),a},G=function(a){return a=a.replace(/\\(\\)/g,N),a=a.replace(/\\([`*_{}\[\]()>#+-.!])/g,N),a},H=function(a){return a=a.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,'<a href="$1">$1</a>'),a=a.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(a,b){return I(J(b))}),a},I=function(a){var b=[function(a){return"&#"+a.charCodeAt(0)+";"},function(a){return"&#x"+a.charCodeAt(0).toString(16)+";"},function(a){return a}];return a="mailto:"+a,a=a.replace(/./g,function(a){if(a=="@")a=b[Math.floor(Math.random()*2)](a);else if(a!=":"){var c=Math.random();a=c>.9?b[2](a):c>.45?b[1](a):b[0](a)}return a}),a='<a href="'+a+'">'+a+"</a>",a=a.replace(/">.+:/g,'">'),a},J=function(a){return a=a.replace(/~E(\d+)E/g,function(a,b){var c=parseInt(b);return String.fromCharCode(c)}),a},K=function(a){return a=a.replace(/^(\t|[ ]{1,4})/gm,"~0"),a=a.replace(/~0/g,""),a},L=function(a){return a=a.replace(/\t(?=\t)/g," "),a=a.replace(/\t/g,"~A~B"),a=a.replace(/~B(.+?)~A/g,function(a,b,c){var d=b,e=4-d.length%4;for(var f=0;f<e;f++)d+=" ";return d}),a=a.replace(/~A/g," "),a=a.replace(/~B/g,""),a},M=function(a,b,c){var d="(["+b.replace(/([\[\]\\])/g,"\\$1")+"])";c&&(d="\\\\"+d);var e=new RegExp(d,"g");return a=a.replace(e,N),a},N=function(a,b){var c=b.charCodeAt(0);return"~E"+c+"E"}},typeof module!="undefined"&&(module.exports=Showdown),typeof define=="function"&&define.amd&&define("showdown",function(){return Showdown}); |
{ | ||
"name": "showdown", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"author": "John Fraser", | ||
@@ -14,7 +14,12 @@ "contributors": [ | ||
"Cat Chen", | ||
"Titus Stone" | ||
"Titus Stone", | ||
"Rob Sutherland", | ||
"Pavel Lang", | ||
"Ben Combee", | ||
"Adam Backstrom" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/coreyti/showdown.git" | ||
"url": "https://github.com/coreyti/showdown.git", | ||
"web": "https://github.com/coreyti/showdown" | ||
}, | ||
@@ -25,4 +30,7 @@ "devDependencies": { | ||
}, | ||
"licenses": [{ "type": "BSD" }], | ||
"licenses": [{ | ||
"type": "BSD", | ||
"url": "https://github.com/coreyti/showdown/raw/master/license.txt" | ||
}], | ||
"main": "./src/showdown" | ||
} |
174
README.md
@@ -0,6 +1,4 @@ | ||
# NOTE -- Showdown on GitHub | ||
NOTE -- Showdown on GitHub | ||
========================== | ||
Please note that I, Corey, am not the author of Showdown. Rather, I found it | ||
**Please note** that I, Corey, am not the author of Showdown. Rather, I found it | ||
some time back at <http://attacklab.net/showdown/> | ||
@@ -24,4 +22,3 @@ (website removed, see: <http://wayback.archive.org/web/*/http://attacklab.net/showdown>) | ||
Showdown -- A JavaScript port of Markdown | ||
========================================= | ||
# Showdown -- A JavaScript port of Markdown | ||
@@ -38,6 +35,5 @@ Showdown Copyright (c) 2007 John Fraser. | ||
Quick Example | ||
------------- | ||
## Quick Example | ||
``` js | ||
```js | ||
var Showdown = require('showdown'); | ||
@@ -49,11 +45,9 @@ var converter = new Showdown.converter(); | ||
// <h1 id="hellomarkdown">hello, markdown</h1> | ||
``` | ||
What's it for? | ||
-------------- | ||
## What's it for? | ||
Developers can use Showdown to: | ||
* Add in-browser preview to existing Markdown apps | ||
* Add in-browser preview to existing Markdown apps | ||
@@ -65,3 +59,3 @@ Showdown's output is (almost always) identical to | ||
* Add Markdown input to programs that don't support it | ||
* Add Markdown input to programs that don't support it | ||
@@ -76,3 +70,3 @@ Any app that accepts HTML input can now be made to speak | ||
* Add Markdown input to closed-source web apps | ||
* Add Markdown input to closed-source web apps | ||
@@ -85,3 +79,3 @@ You can write bookmarklets or userscripts to extend | ||
* Build new web apps from scratch | ||
* Build new web apps from scratch | ||
@@ -99,13 +93,12 @@ A Showdown front-end can send back text in Markdown, | ||
Browser Compatibility | ||
--------------------- | ||
## Browser Compatibility | ||
Showdown has been tested successfully with: | ||
- Firefox 1.5 and 2.0 | ||
- Internet Explorer 6 and 7 | ||
- Safari 2.0.4 | ||
- Opera 8.54 and 9.10 | ||
- Netscape 8.1.2 | ||
- Konqueror 3.5.4 | ||
* Firefox 1.5 and 2.0 | ||
* Internet Explorer 6 and 7 | ||
* Safari 2.0.4 | ||
* Opera 8.54 and 9.10 | ||
* Netscape 8.1.2 | ||
* Konqueror 3.5.4 | ||
@@ -115,9 +108,33 @@ In theory, Showdown will work in any browser that supports ECMA 262 3rd Edition (JavaScript 1.5). The converter itself might even work in things that aren't web browsers, like Acrobat. No promises. | ||
Known Differences in Output | ||
--------------------------- | ||
## Extensions | ||
In most cases, Showdown's output is identical to that of Perl Markdown v1.0.2b7. What follows is a list of all known deviations. Please email me if you find more. | ||
Showdown allows additional functionality to be loaded via extensions. | ||
### Client-side Extension Usage | ||
* This release uses the HTML parser from Markdown 1.0.2b2, | ||
```js | ||
<script src="src/showdown.js" /> | ||
<script src="src/extensions/twitter.js" /> | ||
var converter = new Showdown().converter({ extensions: 'twitter' }); | ||
``` | ||
### Server-side Extension Usage | ||
```js | ||
// Using a bundled extension | ||
var Showdown = require('showdown'); | ||
var converter = new Showdown().converter({ extensions: ['twitter'] }); | ||
// Using a custom extension | ||
var mine = require('./custom-extensions/mine'); | ||
var converter = new Showdown().converter({ extensions: ['twitter', mine] }); | ||
``` | ||
## Known Differences in Output | ||
In most cases, Showdown's output is identical to that of Perl Markdown v1.0.2b7. What follows is a list of all known deviations. Please file an issue if you find more. | ||
* This release uses the HTML parser from Markdown 1.0.2b2, | ||
which means it fails `Inline HTML (Advanced).text` from | ||
@@ -132,5 +149,4 @@ the Markdown test suite: | ||
* Showdown doesn't support the markdown="1" attribute: | ||
* Showdown doesn't support the markdown="1" attribute: | ||
<div markdown="1"> | ||
@@ -147,3 +163,3 @@ Markdown does *not* work in here. | ||
* You can only nest square brackets in link titles to a | ||
* You can only nest square brackets in link titles to a | ||
depth of two levels: | ||
@@ -157,3 +173,3 @@ | ||
* When sublists have paragraphs, Showdown produces equivalent | ||
* When sublists have paragraphs, Showdown produces equivalent | ||
HTML with a slightly different arrangement of newlines: | ||
@@ -179,3 +195,3 @@ | ||
* Markdown.pl creates empty title attributes for | ||
* Markdown.pl creates empty title attributes for | ||
inline-style images: | ||
@@ -196,3 +212,3 @@ | ||
* With crazy input, Markdown will mistakenly put | ||
* With crazy input, Markdown will mistakenly put | ||
`<strong>` or `<em>` tags in URLs: | ||
@@ -207,4 +223,3 @@ | ||
Tests | ||
--------------------------- | ||
## Tests | ||
A suite of tests is available which require node.js. Once node is installed, run the following command from the project root to install the development dependencies: | ||
@@ -221,2 +236,73 @@ | ||
## Creating Markdown Extensions | ||
A showdown extension is simply a function which returns an array of extensions. Each single extension can be one of two types: | ||
* Language Extension -- Language extensions are ones that that add new markdown syntax to showdown. For example, say you wanted `^^youtube http://www.youtube.com/watch?v=oHg5SJYRHA0` to automatically render as an embedded YouTube video, that would be a language extension. | ||
* Output Modifiers -- After showdown has run, and generated HTML, an output modifier would change that HTML. For example, say you wanted to change `<div class="header">` to be `<header>`, that would be an output modifier. | ||
Each extension can provide two combinations of interfaces for showdown. | ||
### Regex/Replace | ||
Regex/replace style extensions are very similar to javascripts `string.replace` function. Two properties are given, `regex` and `replace`. `regex` is a string and `replace` can be either a string or a function. If `replace` is a string, it can use the `$1` syntax for group substitution, exactly as if it were making use of `string.replace` (internally it does this actually); The value of `regex` is assumed to be a global replacement. | ||
**Example:** | ||
``` js | ||
var demo = function(converter) { | ||
return [ | ||
// Replace escaped @ symbols | ||
{ type: 'lang', regex: '\\@', replace: '@' } | ||
]; | ||
} | ||
``` | ||
### Filter | ||
Alternately, if you'd just like to do everything yourself, you can specify a filter which is a callback with a single input parameter, text (the current source text within the showdown engine). | ||
**Example:** | ||
``` js | ||
var demo = function(converter) { | ||
return [ | ||
// Replace escaped @ symbols | ||
{ type: 'lang', function(text) { | ||
return text.replace(/\\@/g, '@'); | ||
}} | ||
]; | ||
} | ||
``` | ||
### Implementation Concerns | ||
One bit which should be taken into account is maintaining both client-side and server-side compatibility. This can be achieved with a few lines of boilerplate code. First, to prevent polluting the global scope for client-side code, the extension definition should be wrapped in a self-executing function. | ||
``` js | ||
(function(){ | ||
// Your extension here | ||
}()); | ||
``` | ||
Second, client-side extensions should add a property onto `Showdown.extensions` which matches the name of the file. As an example, a file named `demo.js` should then add `Showdown.extensions.demo`. Server-side extensions can simply export themselves. | ||
``` js | ||
(function(){ | ||
var demo = function(converter) { | ||
// ... extension code here ... | ||
}; | ||
// Client-side export | ||
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.demo = demo; } | ||
// Server-side export | ||
if (typeof module !== 'undefined') module.exports = demo; | ||
}()); | ||
``` | ||
### Testing Extensions | ||
The showdown test runner is setup to automatically test cases for extensions. To add test cases for an extension, create a new folder under `./test/extensions` which matches the name of the `.js` file in `./src/extensions`. Place any test cases into the filder using the md/html format and they will automatically be run when tests are run. | ||
Credits | ||
@@ -230,7 +316,9 @@ --------------------------- | ||
Author of Markdown | ||
* Maintenance | ||
* Maintenance/Contributions | ||
* [Corey Innis](http://github.com/coreyti):<br/> | ||
GitHub project maintainer | ||
* [Remy Sharp](http://remysharp.com/):<br/> | ||
* [Remy Sharp](https://github.com/remy/):<br/> | ||
CommonJS-compatibility and more | ||
* [Konstantin Käfer](https://github.com/kkaefer/):<br/> | ||
CommonJS packaging | ||
* [Roger Braun](https://github.com/rogerbraun):<br/> | ||
@@ -243,3 +331,11 @@ Github-style code blocks | ||
* [Titus Stone](https://github.com/tstone):<br/> | ||
Mocha tests + bug fixes | ||
**Mocha tests**, **extension mechanism**, and bug fixes | ||
* [Rob Sutherland](https://github.com/roberocity):<br/> | ||
The idea that lead to extensions | ||
* [Pavel Lang](https://github.com/langpavel):<br/> | ||
Code cleanup | ||
* [Ben Combee](https://github.com/unwiredben):<br/> | ||
Regex optimization | ||
* [Adam Backstrom](https://github.com/abackstrom):<br/> | ||
WebKit bugfix | ||
@@ -67,5 +67,26 @@ // | ||
// | ||
var Showdown = {}; | ||
var Showdown = { extensions: {} }; | ||
// | ||
// forEach | ||
// | ||
var forEach = Showdown.forEach = function(obj, callback) { | ||
if (typeof obj.forEach === 'function') { | ||
obj.forEach(callback); | ||
} else { | ||
var i, len = obj.length; | ||
for (i = 0; i < len; i++) { | ||
callback(obj[i], i, obj); | ||
} | ||
} | ||
}; | ||
// | ||
// Standard extension naming | ||
// | ||
var stdExtName = function(s) { | ||
return s.replace(/[_-]||\s/g, '').toLowerCase(); | ||
}; | ||
// | ||
// converter | ||
@@ -76,3 +97,3 @@ // | ||
// | ||
Showdown.converter = function() { | ||
Showdown.converter = function(converter_options) { | ||
@@ -92,3 +113,65 @@ // | ||
// Global extensions | ||
var g_lang_extensions = []; | ||
var g_output_modifiers = []; | ||
// | ||
// Automatic Extension Loading (node only): | ||
// | ||
if (typeof module !== 'undefind' && typeof exports !== 'undefined' && typeof require !== 'undefind') { | ||
var fs = require('fs'); | ||
if (fs) { | ||
// Search extensions folder | ||
var extensions = fs.readdirSync((__dirname || '.')+'/extensions').filter(function(file){ | ||
return ~file.indexOf('.js'); | ||
}).map(function(file){ | ||
return file.replace(/\.js$/, ''); | ||
}); | ||
// Load extensions into Showdown namespace | ||
extensions.forEach(function(ext){ | ||
var name = stdExtName(ext); | ||
Showdown.extensions[name] = require('./extensions/' + ext); | ||
}); | ||
} | ||
} | ||
// | ||
// Options: | ||
// | ||
// Parse extensinos options into separate arrays | ||
if (converter_options && converter_options.extensions) { | ||
// Iterate over each plugin | ||
converter_options.extensions.forEach(function(plugin){ | ||
// Assume it's a bundled plugin if a string is given | ||
if (typeof plugin === 'string') { | ||
plugin = Showdown.extensions[stdExtName(plugin)]; | ||
} | ||
if (typeof plugin === 'function') { | ||
// Iterate over each extension within that plugin | ||
plugin(this).forEach(function(ext){ | ||
// Sort extensions by type | ||
if (ext.type) { | ||
if (ext.type === 'language' || ext.type === 'lang') { | ||
g_lang_extensions.push(ext); | ||
} else if (ext.type === 'output' || ext.type === 'html') { | ||
g_output_modifiers.push(ext); | ||
} | ||
} else { | ||
// Assume language extension | ||
g_output_modifiers.push(ext); | ||
} | ||
}); | ||
} else { | ||
throw "Extension '" + plugin + "' could not be loaded. It was either not found or is not a valid extension."; | ||
} | ||
}); | ||
} | ||
this.makeHtml = function(text) { | ||
@@ -106,5 +189,5 @@ // | ||
// articles): | ||
g_urls = new Array(); | ||
g_titles = new Array(); | ||
g_html_blocks = new Array(); | ||
g_urls = {}; | ||
g_titles = {}; | ||
g_html_blocks = []; | ||
@@ -138,2 +221,7 @@ // attacklab: Replace ~ with ~T | ||
// Run language extensions | ||
g_lang_extensions.forEach(function(x){ | ||
text = _ExecuteExtension(x, text); | ||
}); | ||
// Handle github codeblocks prior to running HashHTML so that | ||
@@ -159,2 +247,7 @@ // HTML contained within the codeblock gets escaped propertly | ||
// Run output modifiers | ||
g_output_modifiers.forEach(function(x){ | ||
text = _ExecuteExtension(x, text); | ||
}); | ||
return text; | ||
@@ -164,2 +257,11 @@ }; | ||
var _ExecuteExtension = function(ext, text) { | ||
if (ext.regex) { | ||
var re = new RegExp(ext.regex, 'g'); | ||
return text.replace(re, ext.replace); | ||
} else if (ext.filter) { | ||
return ext.filter(text); | ||
} | ||
}; | ||
var _StripLinkDefinitions = function(text) { | ||
@@ -194,3 +296,7 @@ // | ||
*/ | ||
var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm, | ||
// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug | ||
text += "~0"; | ||
text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm, | ||
function (wholeMatch,m1,m2,m3,m4) { | ||
@@ -212,2 +318,5 @@ m1 = m1.toLowerCase(); | ||
// attacklab: strip sentinel | ||
text = text.replace(/~0/,""); | ||
return text; | ||
@@ -271,3 +380,3 @@ } | ||
[^\r]*? // any number of lines, minimally matching | ||
.*</\2> // the matching end tag | ||
</\2> // the matching end tag | ||
[ \t]* // trailing spaces/tabs | ||
@@ -278,3 +387,3 @@ (?=\n+) // followed by a newline | ||
*/ | ||
text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,hashElement); | ||
text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm,hashElement); | ||
@@ -497,3 +606,3 @@ // Special case just for <hr />. It was easier to make a special case than | ||
*/ | ||
text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag); | ||
text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag); | ||
@@ -1104,3 +1213,3 @@ // | ||
var grafs = text.split(/\n{2,}/g); | ||
var grafsOut = new Array(); | ||
var grafsOut = []; | ||
@@ -1224,12 +1333,5 @@ // | ||
// attacklab: why can't javascript speak hex? | ||
function char2hex(ch) { | ||
var hexDigits = '0123456789ABCDEF'; | ||
var dec = ch.charCodeAt(0); | ||
return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15)); | ||
} | ||
var encode = [ | ||
function(ch){return "&#"+ch.charCodeAt(0)+";";}, | ||
function(ch){return "&#x"+char2hex(ch)+";";}, | ||
function(ch){return "&#x"+ch.charCodeAt(0).toString(16)+";";}, | ||
function(ch){return ch;} | ||
@@ -1354,3 +1456,13 @@ ]; | ||
// export | ||
if (typeof module !== 'undefined') module.exports = Showdown; | ||
// stolen from AMD branch of underscore | ||
// AMD define happens at the end for compatibility with AMD loaders | ||
// that don't enforce next-turn semantics on modules. | ||
if (typeof define === 'function' && define.amd) { | ||
define('showdown', function() { | ||
return Showdown; | ||
}); | ||
} |
@@ -10,3 +10,8 @@ | ||
<aside>ignore me</aside> | ||
<article>read | ||
me</article> | ||
<aside> | ||
ignore me | ||
</aside> | ||
the end |
106
test/run.js
var showdown = new require('../src/showdown'), | ||
convertor = new showdown.converter(), | ||
fs = require('fs'), | ||
@@ -7,39 +6,82 @@ path = require('path'), | ||
// Load test cases from disk | ||
var cases = fs.readdirSync('test/cases').filter(function(file){ | ||
return ~file.indexOf('.md'); | ||
}).map(function(file){ | ||
return file.replace('.md', ''); | ||
var runTestsInDir = function(dir, converter) { | ||
// Load test cases from disk | ||
var cases = fs.readdirSync(dir).filter(function(file){ | ||
return ~file.indexOf('.md'); | ||
}).map(function(file){ | ||
return file.replace('.md', ''); | ||
}); | ||
// Run each test case (markdown -> html) | ||
cases.forEach(function(test){ | ||
var name = test.replace(/[-.]/g, ' '); | ||
it (name, function(){ | ||
var mdpath = path.join(dir, test + '.md'), | ||
htmlpath = path.join(dir, test + '.html'), | ||
md = fs.readFileSync(mdpath, 'utf8'), | ||
expected = fs.readFileSync(htmlpath, 'utf8').trim(), | ||
actual = converter.makeHtml(md).trim(); | ||
// Normalize line returns | ||
expected = expected.replace(/\r/g, ''); | ||
// Ignore all leading/trailing whitespace | ||
expected = expected.split('\n').map(function(x){ | ||
return x.trim(); | ||
}).join('\n'); | ||
actual = actual.split('\n').map(function(x){ | ||
return x.trim(); | ||
}).join('\n'); | ||
// Convert whitespace to a visible character so that it shows up on error reports | ||
expected = expected.replace(/ /g, '·'); | ||
expected = expected.replace(/\n/g, '•\n'); | ||
actual = actual.replace(/ /g, '·'); | ||
actual = actual.replace(/\n/g, '•\n'); | ||
// Compare | ||
actual.should.equal(expected); | ||
}); | ||
}); | ||
}; | ||
// | ||
// :: Markdown to HTML testing :: | ||
// | ||
describe('Markdown', function() { | ||
var converter = new showdown.converter(); | ||
runTestsInDir('test/cases', converter); | ||
}); | ||
// Run each test case | ||
cases.forEach(function(test){ | ||
var name = test.replace(/[-.]/g, ' '); | ||
it (name, function(){ | ||
var mdpath = path.join('test/cases', test + '.md'), | ||
htmlpath = path.join('test/cases', test + '.html'), | ||
md = fs.readFileSync(mdpath, 'utf8'), | ||
expected = fs.readFileSync(htmlpath, 'utf8').trim(), | ||
actual = convertor.makeHtml(md).trim(); | ||
// Normalize line returns | ||
expected = expected.replace(/\r/g, ''); | ||
// | ||
// :: Extensions Testing :: | ||
// | ||
// Ignore all leading/trailing whitespace | ||
expected = expected.split('\n').map(function(x){ | ||
return x.trim(); | ||
}).join('\n'); | ||
actual = actual.split('\n').map(function(x){ | ||
return x.trim(); | ||
}).join('\n'); | ||
if (path.existsSync('test/extensions')) { | ||
// Convert whitespace to a visible character so that it shows up on error reports | ||
expected = expected.replace(/ /g, '·'); | ||
expected = expected.replace(/\n/g, '•\n'); | ||
actual = actual.replace(/ /g, '·'); | ||
actual = actual.replace(/\n/g, '•\n'); | ||
describe('extensions', function() { | ||
// Search all sub-folders looking for directory-specific tests | ||
var extensions = fs.readdirSync('test/extensions').filter(function(file){ | ||
return fs.lstatSync('test/extensions/' + file).isDirectory(); | ||
}); | ||
// Compare | ||
actual.should.equal(expected); | ||
// Run tests in each extension sub-folder | ||
extensions.forEach(function(ext){ | ||
// Make sure extension exists | ||
var src = 'src/extensions/' + ext + '.js'; | ||
if (!path.existsSync(src)) { | ||
throw "Attempting tests for '" + ext + "' but sourc file (" + src + ") was not found."; | ||
} | ||
var converter = new showdown.converter({ extensions: [ ext ] }); | ||
var dir = 'test/extensions/' + ext; | ||
runTestsInDir(dir, converter); | ||
}); | ||
}); | ||
}); | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
187937
117
1680
325
3
6