No autolinking inside of code blocks

closes #865

- rejigged markdown to have some functionality before showdown runs, and other functionality before.
- autolinking now happens last, so it can be smarter
This commit is contained in:
Hannah Wolfe 2013-09-27 11:35:44 +01:00
parent 8c6519fde7
commit e411ed6889
2 changed files with 59 additions and 21 deletions

View File

@ -16,11 +16,10 @@
}
},
{
// GFM newline and underscore modifications
// GFM newline and underscore modifications, happen BEFORE showdown
type : 'lang',
filter : function (text) {
var extractions = {},
imageMarkdownRegex = /^(?:\{(.*?)\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim,
var preExtractions = {},
hashID = 0;
function hashId() {
@ -30,19 +29,10 @@
// Extract pre blocks
text = text.replace(/<pre>[\s\S]*?<\/pre>/gim, function (x) {
var hash = hashId();
extractions[hash] = x;
preExtractions[hash] = x;
return "{gfm-js-extract-pre-" + hash + "}";
}, 'm');
// better URL support, but no title support
text = text.replace(imageMarkdownRegex, function (match, key, alt, src) {
if (src) {
return '<img src="' + src + '" alt="' + alt + '" />';
}
return '';
});
//prevent foo_bar and foo_bar_baz from ending up with an italic word in the middle
text = text.replace(/(^(?! {4}|\t)\w+_\w+_\w[\w_]*)/gm, function (x) {
return x.replace(/_/gm, '\\_');
@ -53,8 +43,9 @@
return x.match(/\n{2}/) ? x : x.trim() + " \n";
});
text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) {
return "\n\n" + extractions[y];
return "\n\n" + preExtractions[y];
});
@ -62,25 +53,43 @@
}
},
{
// Auto-link URLs and emails
type : 'lang',
// GFM autolinking & custom image handling, happens AFTER showdown
type : 'html',
filter : function (text) {
var extractions = {},
var refExtractions = {},
preExtractions = {},
imageMarkdownRegex = /^(?:\{(.*?)\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim,
hashID = 0;
function hashId() {
return hashID++;
}
// Extract pre blocks
text = text.replace(/<(pre|code)>[\s\S]*?<\/(\1)>/gim, function (x) {
var hash = hashId();
preExtractions[hash] = x;
return "{gfm-js-extract-pre-" + hash + "}";
}, 'm');
// filter out def urls
// from Marked https://github.com/chjj/marked/blob/master/lib/marked.js#L24
text = text.replace(/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/gmi,
function (x) {
var hash = hashId();
extractions[hash] = x;
refExtractions[hash] = x;
return "{gfm-js-extract-ref-url-" + hash + "}";
});
// better URL support, but no title support
text = text.replace(imageMarkdownRegex, function (match, key, alt, src) {
if (src) {
return '<img src="' + src + '" alt="' + alt + '" />';
}
return '';
});
// match a URL
// adapted from https://gist.github.com/jorilallo/1283095#L158
// and http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript
@ -95,13 +104,18 @@
return lookBehind ? wholeMatch : "<a href='" + wholeMatch + "'>" + wholeMatch + "</a>";
});
// match emil
// match email
text = text.replace(/[a-z0-9_\-+=.]+@[a-z0-9\-]+(\.[a-z0-9-]+)+/gmi, function (wholeMatch) {
return "<a href='mailto:" + wholeMatch + "'>" + wholeMatch + "</a>";
});
// replace extractions
text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) {
return preExtractions[y];
});
text = text.replace(/\{gfm-js-extract-ref-url-([0-9]+)\}/gi, function (x, y) {
return "\n\n" + extractions[y];
return "\n\n" + refExtractions[y];
});
return text;

View File

@ -178,7 +178,7 @@ describe("Showdown client side converter", function () {
},
{
input: "# http://google.co.uk",
output: /^<h1 id="ahrefhttpgooglecoukhttpgooglecouka"><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/h1>$/
output: /^<h1 id="httpgooglecouk"><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/h1>$/
},
{
input: "* http://google.co.uk",
@ -279,6 +279,30 @@ describe("Showdown client side converter", function () {
});
});
it("should NOT auto-link URLS inside of code/pre blocks", function () {
var testPhrases = [
{
input: "```\nurl: http://google.co.uk\n```",
output: /^<pre><code>url: http:\/\/google.co.uk \n<\/code><\/pre>$/
},
{
input: "`url: http://google.co.uk`",
output: /^<p><code>url: http:\/\/google.co.uk<\/code><\/p>$/
},
{
input: "Hello type some `url: http://google.co.uk` stuff",
output: /^<p>Hello type some <code>url: http:\/\/google.co.uk<\/code> stuff<\/p>$/
}
],
processedMarkup;
testPhrases.forEach(function (testPhrase) {
processedMarkup = converter.makeHtml(testPhrase.input);
processedMarkup.should.match(testPhrase.output);
});
});
it("should not display anything for reference URL", function () {
var testPhrases = [
{