feat(simplifiedAutoLink): add support for GFM autolinks

Github Flavored Markdown detects urls and mails embeded in the text without any extra markup or delimiter.
This commit adds this feature to showdown through an option called "simplifiedAutoLink".
Related to #164
This commit is contained in:
Estevão Soares dos Santos 2015-07-11 02:42:53 +01:00
parent 1e2bbcfd5c
commit cff0237299
12 changed files with 133 additions and 53 deletions

View File

@ -95,15 +95,42 @@ module.exports = function (grunt) {
timeout: 3000,
ignoreLeaks: false,
reporter: 'spec'
},
issues: {
src: 'test/node/testsuite.issues.js',
options: {
globals: ['should'],
timeout: 3000,
ignoreLeaks: false,
reporter: 'spec'
}
}
},
issues: {
src: 'test/node/testsuite.issues.js',
options: {
globals: ['should'],
timeout: 3000,
ignoreLeaks: false,
reporter: 'spec'
}
},
standard: {
src: 'test/node/testsuite.standard.js',
options: {
globals: ['should'],
timeout: 3000,
ignoreLeaks: false,
reporter: 'spec'
}
},
features: {
src: 'test/node/testsuite.features.js',
options: {
globals: ['should'],
timeout: 3000,
ignoreLeaks: false,
reporter: 'spec'
}
},
single: {
src: 'test/node/**/*.js',
options: {
globals: ['should'],
timeout: 3000,
ignoreLeaks: false,
reporter: 'spec'
}
}
}
@ -113,6 +140,21 @@ module.exports = function (grunt) {
require('load-grunt-tasks')(grunt);
grunt.registerTask('single-test', function (grep) {
'use strict';
grunt.config.merge({
simplemocha: {
single: {
options: {
grep: grep
}
}
}
});
grunt.task.run('simplemocha:node');
});
grunt.registerTask('concatenate', ['concat:dist']);
grunt.registerTask('lint', ['jshint', 'jscs']);
grunt.registerTask('test', ['lint', 'concat:test', 'simplemocha:node', 'clean']);

40
dist/showdown.js vendored
View File

@ -1,4 +1,4 @@
;/*! showdown 10-07-2015 */
;/*! showdown 11-07-2015 */
(function(){
/**
* Created by Tivie on 06-01-2015.
@ -13,7 +13,8 @@ var showdown = {},
prefixHeaderId: false,
noHeaderId: false,
headerLevelStart: 1,
parseImgDimensions: false
parseImgDimensions: false,
simplifiedAutoLink: false
},
globalOptions = JSON.parse(JSON.stringify(defaultOptions)); //clone default options out of laziness =P
@ -867,33 +868,32 @@ showdown.subParser('anchors', function (text, config, globals) {
});
showdown.subParser('autoLinks', function (text) {
showdown.subParser('autoLinks', function (text, options) {
'use strict';
text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, '<a href=\"$1\">$1</a>');
//simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
var simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)(?=\s|$)(?!["<>])/gi,
delimUrlRegex = /<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi,
simpleMailRegex = /\b(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)\b/gi,
delimMailRegex = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
text = text.replace(delimUrlRegex, '<a href=\"$1\">$1</a>');
text = text.replace(delimMailRegex, replaceMail);
//simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
// Email addresses: <address@domain.foo>
/*
text = text.replace(/
<
(?:mailto:)?
(
[-.\w]+
\@
[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
)
>
/gi);
*/
var pattern = /<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
text = text.replace(pattern, function (wholeMatch, m1) {
if (options.simplifiedAutoLink) {
text = text.replace(simpleURLRegex, '<a href=\"$1\">$1</a>');
text = text.replace(simpleMailRegex, '<a href=\"$1\">$1</a>');
}
function replaceMail(wholeMatch, m1) {
var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1);
return showdown.subParser('encodeEmailAddress')(unescapedStr);
});
}
return text;
});
/**

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,8 @@ var showdown = {},
prefixHeaderId: false,
noHeaderId: false,
headerLevelStart: 1,
parseImgDimensions: false
parseImgDimensions: false,
simplifiedAutoLink: false
},
globalOptions = JSON.parse(JSON.stringify(defaultOptions)); //clone default options out of laziness =P

View File

@ -1,28 +1,27 @@
showdown.subParser('autoLinks', function (text) {
showdown.subParser('autoLinks', function (text, options) {
'use strict';
text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, '<a href=\"$1\">$1</a>');
//simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
var simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)(?=\s|$)(?!["<>])/gi,
delimUrlRegex = /<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi,
simpleMailRegex = /\b(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)\b/gi,
delimMailRegex = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
text = text.replace(delimUrlRegex, '<a href=\"$1\">$1</a>');
text = text.replace(delimMailRegex, replaceMail);
//simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
// Email addresses: <address@domain.foo>
/*
text = text.replace(/
<
(?:mailto:)?
(
[-.\w]+
\@
[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
)
>
/gi);
*/
var pattern = /<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
text = text.replace(pattern, function (wholeMatch, m1) {
if (options.simplifiedAutoLink) {
text = text.replace(simpleURLRegex, '<a href=\"$1\">$1</a>');
text = text.replace(simpleMailRegex, '<a href=\"$1\">$1</a>');
}
function replaceMail(wholeMatch, m1) {
var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1);
return showdown.subParser('encodeEmailAddress')(unescapedStr);
});
}
return text;
});

View File

@ -0,0 +1,11 @@
<p>foo.bar</p>
<p>www.foobar</p>
<p><a href="www.foobar.com">www.foobar.com</a></p>
<p><a href="http://foobar.com">http://foobar.com</a></p>
<p><a href="https://www.foobar.com/baz?bazinga=nhecos;">https://www.foobar.com/baz?bazinga=nhecos;</a></p>
<p><a href="http://www.google.com/">http://www.google.com</a></p>

View File

@ -0,0 +1,11 @@
foo.bar
www.foobar
www.foobar.com
http://foobar.com
https://www.foobar.com/baz?bazinga=nhecos;
<a href="http://www.google.com/">http://www.google.com</a>

View File

@ -22,7 +22,8 @@ describe('showdown.options', function () {
prefixHeaderId: false,
noHeaderId: false,
headerLevelStart: 1,
parseImgDimensions: false
parseImgDimensions: false,
simplifiedAutoLink: false
};
expect(showdown.getDefaultOptions()).to.be.eql(opts);
});

View File

@ -14,6 +14,8 @@ describe('makeHtml() features testsuite', function () {
converter = new showdown.Converter({parseImgDimensions: true});
} else if (testsuite[i].name === '#69.header_level_start') {
converter = new showdown.Converter({headerLevelStart: 3});
} else if (testsuite[i].name === '#164.1.simple_autolink') {
converter = new showdown.Converter({simplifiedAutoLink: true});
} else {
converter = new showdown.Converter();
}

View File

@ -0,0 +1,13 @@
/**
* Created by Estevao on 10-07-2015.
*/
/*
var showdown = require('../dist/showdown.js'),
bootstrap = require('./bootstrap.js'),
assertion = bootstrap.assertion,
testsuite = bootstrap.getTestSuite('test/features/');
describe('makeHtml() single test', function () {
'use strict';
});
*/