feat(literalMidWordUnderscores): add support for GFM literal midword underscores

Github Flavored Markdown does not parse underscores in the middle of a word as emphasis/bold.
This commit adds this feature to showdown through an option called "literalMidWordUnderscores".

Related to #164
This commit is contained in:
Estevão Soares dos Santos 2015-07-11 15:45:58 +01:00
parent cff0237299
commit 0c0cd7db99
11 changed files with 53 additions and 21 deletions

BIN
dist/showdown.js vendored

Binary file not shown.

BIN
dist/showdown.js.map vendored

Binary file not shown.

BIN
dist/showdown.min.js vendored

Binary file not shown.

Binary file not shown.

View File

@ -22,11 +22,7 @@ showdown.Converter = function (converterOptions) {
* @private * @private
* @type {{}} * @type {{}}
*/ */
options = { options = {},
omitExtraWLInCodeBlocks: false,
prefixHeaderId: false,
noHeaderId: false
},
/** /**
* Language extensions used by this converter * Language extensions used by this converter

View File

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

View File

@ -1,9 +1,19 @@
showdown.subParser('italicsAndBold', function (text) { showdown.subParser('italicsAndBold', function (text, options) {
'use strict'; 'use strict';
// <strong> must go first:
text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, '<strong>$2</strong>');
text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>'); if (options.literalMidWordUnderscores) {
//underscores
// Since we are consuming a \s character, we need to add it
text = text.replace(/(\s)__(?=\S)([^]+?)__(?=\s)/g, '$1<strong>$2</strong>');
text = text.replace(/(\s)_(?=\S)([^]+?)_(?=\s)/g, '$1<em>$2</em>');
//asterisks
text = text.replace(/\*\*(?=\S)([^]+?)\*\*/g, '<strong>$1</strong>');
text = text.replace(/\*(?=\S)([^]+?)\*/g, '<em>$1</em>');
} else {
// <strong> must go first:
text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, '<strong>$2</strong>');
text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>');
}
return text; return text;
}); });

View File

@ -0,0 +1,11 @@
<p>this is a sentence_with_mid underscores</p>
<p>this is a sentence with just_one underscore</p>
<p>this <em>should be parsed</em> as emphasis</p>
<p>this is double__underscore__mid word</p>
<p>this has just__one double underscore</p>
<p>this <strong>should be parsed</strong> as bold</p>

View File

@ -0,0 +1,11 @@
this is a sentence_with_mid underscores
this is a sentence with just_one underscore
this _should be parsed_ as emphasis
this is double__underscore__mid word
this has just__one double underscore
this __should be parsed__ as bold

View File

@ -18,12 +18,13 @@ describe('showdown.options', function () {
describe('getDefaultOptions()', function () { describe('getDefaultOptions()', function () {
it('should get default options', function () { it('should get default options', function () {
var opts = { var opts = {
omitExtraWLInCodeBlocks: false, omitExtraWLInCodeBlocks: false,
prefixHeaderId: false, prefixHeaderId: false,
noHeaderId: false, noHeaderId: false,
headerLevelStart: 1, headerLevelStart: 1,
parseImgDimensions: false, parseImgDimensions: false,
simplifiedAutoLink: false simplifiedAutoLink: false,
literalMidWordUnderscores: false
}; };
expect(showdown.getDefaultOptions()).to.be.eql(opts); expect(showdown.getDefaultOptions()).to.be.eql(opts);
}); });

View File

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