Merge branch 'develop' into feature/event_mediator

Conflicts:
	dist/showdown.js
	dist/showdown.js.map
	dist/showdown.min.js
	dist/showdown.min.js.map
	src/converter.js
	src/subParsers/blockGamut.js
	src/subParsers/codeSpans.js
This commit is contained in:
Estevão Soares dos Santos 2015-10-19 03:20:20 +01:00
commit f4cb29e05a
68 changed files with 343 additions and 44 deletions

View File

@ -1,3 +1,15 @@
<a name"1.2.3"></a>
### 1.2.3 (2015-08-27)
#### Bug Fixes
* **blockGamut:** fix for headings inside blockquotes ([3df70624](http://github.com/showdownjs/showdown/commit/3df70624), closes [#191](http://github.com/showdownjs/showdown/issues/191))
* **blockQuote:** fix 'github style codeblocks' not being parsed inside 'blockquote' ([ed2cf595](http://github.com/showdownjs/showdown/commit/ed2cf595), closes [#192](http://github.com/showdownjs/showdown/issues/192))
* **simpleAutoLinks:** fix emails being treated as simple urls ([7dc3fb1d](http://github.com/showdownjs/showdown/commit/7dc3fb1d), closes [#187](http://github.com/showdownjs/showdown/issues/187))
* **tables:** fix md tables being parsed inside indented code blocks. ([50256233](http://github.com/showdownjs/showdown/commit/50256233), closes [#193](http://github.com/showdownjs/showdown/issues/193))
<a name"1.2.2"></a>
### 1.2.2 (2015-08-02)

View File

@ -16,7 +16,7 @@ module.exports = function (grunt) {
options: {
sourceMap: true,
banner: ';/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n(function(){\n',
footer: '}).call(this);'
footer: '}).call(this);\n'
},
dist: {
src: [
@ -52,6 +52,15 @@ module.exports = function (grunt) {
}
},
endline: {
dist: {
files: {
'dist/<%= pkg.name %>.js': 'dist/<%= pkg.name %>.js',
'dist/<%= pkg.name %>.min.js': 'dist/<%= pkg.name %>.min.js'
}
}
},
jshint: {
options: {
jshintrc: '.jshintrc'
@ -76,10 +85,28 @@ module.exports = function (grunt) {
}
},
changelog: {
conventionalChangelog: {
options: {
repository: 'http://github.com/showdownjs/showdown',
dest: 'CHANGELOG.md'
changelogOpts: {
preset: 'angular'
}
},
release: {
src: 'CHANGELOG.md'
}
},
conventionalGithubReleaser: {
release: {
options: {
auth: {
type: 'oauth',
token: process.env.GH_TOEKN
},
changelogOpts: {
preset: 'angular'
}
}
}
},
@ -162,8 +189,8 @@ module.exports = function (grunt) {
grunt.registerTask('lint', ['jshint', 'jscs']);
grunt.registerTask('test', ['clean', 'lint', 'concat:test', 'simplemocha:node', 'clean']);
grunt.registerTask('build', ['test', 'concat:dist', 'uglify']);
grunt.registerTask('prep-release', ['build', 'changelog']);
grunt.registerTask('build', ['test', 'concat:dist', 'uglify', 'endline']);
grunt.registerTask('prep-release', ['build', 'conventionalChangelog']);
// Default task(s).
grunt.registerTask('default', ['test']);

View File

@ -11,6 +11,16 @@ Showdown is a Javascript Markdown to HTML converter, based on the original works
Check a live Demo here http://showdownjs.github.io/demo/
## Who uses Showdown (or a fork)
- [GoogleCloudPlatform](https://github.com/GoogleCloudPlatform)
- [Ghost](https://ghost.org/)
- [Meteor](https://www.meteor.com/)
- [Stackexchange](http://stackexchange.com/) - forked as [PageDown](https://code.google.com/p/pagedown/)
- [docular](https://github.com/Vertafore/docular)
- [and some others...](https://www.npmjs.com/browse/depended/showdown)
## Installation
### Download tarball

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

@ -1,6 +1,6 @@
{
"name": "showdown",
"version": "1.2.2",
"version": "1.2.3",
"description": "A Markdown to HTML converter written in Javascript",
"author": "Estevão Santos",
"homepage": "http://showdownjs.github.io/showdown/",
@ -45,7 +45,9 @@
"grunt-contrib-concat": "^0.5.0",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-uglify": "^0.6.0",
"grunt-conventional-changelog": "^1.1.0",
"grunt-conventional-changelog": "^4.0.0",
"grunt-conventional-github-releaser": "^0.3.0",
"grunt-endline": "^0.4.0",
"grunt-jscs": "^1.2.0",
"grunt-simple-mocha": "^0.4.0",
"js-beautify": "^1.5.6",

View File

@ -6,12 +6,7 @@
* Showdown Converter class
* @class
* @param {object} [converterOptions]
* @returns {
* {makeHtml: Function},
* {setOption: Function},
* {getOption: Function},
* {getOptions: Function}
* }
* @returns {Converter}
*/
showdown.Converter = function (converterOptions) {
'use strict';
@ -38,8 +33,12 @@ showdown.Converter = function (converterOptions) {
*/
outputModifiers = [],
listeners = {
};
/**
* Event listeners
* @private
* @type {{}}
*/
listeners = {};
_constructor();
@ -234,6 +233,7 @@ showdown.Converter = function (converterOptions) {
var globals = {
gHtmlBlocks: [],
gHtmlSpans: [],
gUrls: {},
gTitles: {},
gDimensions: {},
@ -276,8 +276,10 @@ showdown.Converter = function (converterOptions) {
// run the sub parsers
text = showdown.subParser('githubCodeBlocks')(text, options, globals);
text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
text = showdown.subParser('hashHTMLSpans')(text, options, globals);
text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
text = showdown.subParser('blockGamut')(text, options, globals);
text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
text = showdown.subParser('unescapeSpecialChars')(text, options, globals);
// attacklab: Restore dollar signs

View File

@ -106,6 +106,68 @@ showdown.helper.escapeCharacters = function escapeCharacters(text, charsToEscape
return text;
};
/**
* matchRecursiveRegExp
*
* (c) 2007 Steven Levithan <stevenlevithan.com>
* MIT License
*
* Accepts a string to search, a left and right format delimiter
* as regex patterns, and optional regex flags. Returns an array
* of matches, allowing nested instances of left/right delimiters.
* Use the "g" flag to return all matches, otherwise only the
* first is returned. Be careful to ensure that the left and
* right format delimiters produce mutually exclusive matches.
* Backreferences are not supported within the right delimiter
* due to how it is internally combined with the left delimiter.
* When matching strings whose format delimiters are unbalanced
* to the left or right, the output is intentionally as a
* conventional regex library with recursion support would
* produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
* "<" and ">" as the delimiters (both strings contain a single,
* balanced instance of "<x>").
*
* examples:
* matchRecursiveRegExp("test", "\\(", "\\)")
* returns: []
* matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
* returns: ["t<<e>><s>", ""]
* matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
* returns: ["test"]
*/
showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
'use strict';
var f = flags || '',
g = f.indexOf('g') > -1,
x = new RegExp(left + '|' + right, f),
l = new RegExp(left, f.replace(/g/g, '')),
a = [],
t, s, m, start, end;
do {
t = 0;
while ((m = x.exec(str))) {
if (l.test(m[0])) {
if (!(t++)) {
start = m[0];
s = x.lastIndex;
}
} else if (t) {
if (!--t) {
end = m[0];
var match = str.slice(s, m.index);
a.push([start + match + end, match]);
if (!g) {
return a;
}
}
}
}
} while (t && (x.lastIndex = s));
return a;
};
/**
* POLYFILLS
*/
@ -118,6 +180,10 @@ if (showdown.helper.isUndefined(console)) {
log: function (msg) {
'use strict';
alert(msg);
},
error: function (msg) {
'use strict';
throw msg;
}
};
}

View File

@ -5,7 +5,7 @@ showdown.subParser('autoLinks', function (text, options, globals) {
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,
simpleMailRegex = /(?:^|[ \n\t])([A-Za-z0-9!#$%&'*+-/=?^_`\{|}~\.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?:$|[ \n\t])/gi,
delimMailRegex = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
text = text.replace(delimUrlRegex, '<a href=\"$1\">$1</a>');
@ -15,7 +15,7 @@ showdown.subParser('autoLinks', function (text, options, globals) {
if (options.simplifiedAutoLink) {
text = text.replace(simpleURLRegex, '<a href=\"$1\">$1</a>');
text = text.replace(simpleMailRegex, '<a href=\"$1\">$1</a>');
text = text.replace(simpleMailRegex, replaceMail);
}
function replaceMail(wholeMatch, m1) {

View File

@ -7,6 +7,9 @@ showdown.subParser('blockGamut', function (text, options, globals) {
text = globals.converter._dispatch('blockGamut.before', text, options);
// we parse blockquotes first so that we can have headings and hrs
// inside blockquotes
text = showdown.subParser('blockQuotes')(text, options, globals);
text = showdown.subParser('headers')(text, options, globals);
// Do Horizontal Rules:
@ -15,10 +18,9 @@ showdown.subParser('blockGamut', function (text, options, globals) {
text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, key);
text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, key);
text = showdown.subParser('tables')(text, options, globals);
text = showdown.subParser('lists')(text, options, globals);
text = showdown.subParser('codeBlocks')(text, options, globals);
text = showdown.subParser('blockQuotes')(text, options, globals);
text = showdown.subParser('tables')(text, options, globals);
// We already ran _HashHTMLBlocks() before, in Markdown(), but that
// was to escape raw HTML in the original Markdown source. This time,

View File

@ -15,7 +15,7 @@ showdown.subParser('blockQuotes', function (text, options, globals) {
/gm, function(){...});
*/
text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, function (wholeMatch, m1) {
text = text.replace(/((^[ \t]{0,3}>[ \t]?.+\n(.+\n)*\n*)+)/gm, function (wholeMatch, m1) {
var bq = m1;
// attacklab: hack around Konqueror 3.5.4 bug:
@ -26,6 +26,7 @@ showdown.subParser('blockQuotes', function (text, options, globals) {
bq = bq.replace(/~0/g, '');
bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
bq = showdown.subParser('githubCodeBlocks')(bq, options, globals);
bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
bq = bq.replace(/(^|\n)/g, '$1 ');

View File

@ -27,13 +27,6 @@ showdown.subParser('codeSpans', function (text, options, globals) {
'use strict';
text = globals.converter._dispatch('codeSpans.before', text, options);
//special case -> literal html code tag
text = text.replace(/(<code[^><]*?>)([^]*?)<\/code>/g, function (wholeMatch, tag, c) {
c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
c = showdown.subParser('encodeCode')(c);
return tag + c + '</code>';
});
/*
text = text.replace(/

View File

@ -0,0 +1,26 @@
/**
* Hash span elements that should not be parsed as markdown
*/
showdown.subParser('hashHTMLSpans', function (text, config, globals) {
'use strict';
var matches = showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');
for (var i = 0; i < matches.length; ++i) {
text = text.replace(matches[i][0], '~L' + (globals.gHtmlSpans.push(matches[i][0]) - 1) + 'L');
}
return text;
});
/**
* Unhash HTML spans
*/
showdown.subParser('unhashHTMLSpans', function (text, config, globals) {
'use strict';
for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
text = text.replace('~L' + i + 'L', globals.gHtmlSpans[i]);
}
return text;
});

View File

@ -9,8 +9,8 @@ showdown.subParser('italicsAndBold', function (text, options, globals) {
text = text.replace(/(^|\s|>|\b)__(?=\S)([^]+?)__(?=\b|<|\s|$)/gm, '$1<strong>$2</strong>');
text = text.replace(/(^|\s|>|\b)_(?=\S)([^]+?)_(?=\b|<|\s|$)/gm, '$1<em>$2</em>');
//asterisks
text = text.replace(/\*\*(?=\S)([^]+?)\*\*/g, '<strong>$1</strong>');
text = text.replace(/\*(?=\S)([^]+?)\*/g, '<em>$1</em>');
text = text.replace(/(\*\*)(?=\S)([^\r]*?\S[*]*)\1/g, '<strong>$2</strong>');
text = text.replace(/(\*)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>');
} else {
// <strong> must go first:

View File

@ -9,6 +9,7 @@ showdown.subParser('lists', function (text, options, globals) {
* Process the contents of a single ordered or unordered list, splitting it
* into individual list items.
* @param {string} listStr
* @param {boolean} trimTrailing
* @returns {string}
*/
function processListItems (listStr, trimTrailing) {
@ -96,6 +97,7 @@ showdown.subParser('lists', function (text, options, globals) {
* Check and parse consecutive lists (better fix for issue #142)
* @param {string} list
* @param {string} listType
* @param {boolean} trimTrailing
* @returns {string}
*/
function parseConsecutiveLists(list, listType, trimTrailing) {

View File

@ -0,0 +1,9 @@
<blockquote>
<p>a blockquote with a 4 space indented line (not code)</p>
</blockquote>
<p>sep</p>
<blockquote>
<p>a blockquote</p>
</blockquote>
<pre><code>with some code after
</code></pre>

View File

@ -0,0 +1,8 @@
> a blockquote
with a 4 space indented line (not code)
sep
> a blockquote
with some code after

View File

@ -0,0 +1,8 @@
<pre><code>&gt; this is a pseudo blockquote
&gt; inside a code block
</code></pre>
<p>foo</p>
<pre><code>&gt; this is another bq
inside code
</code></pre>

View File

@ -0,0 +1,7 @@
> this is a pseudo blockquote
> inside a code block
foo
> this is another bq
inside code

View File

@ -0,0 +1,15 @@
<blockquote>
<p>Define a function in javascript:</p>
<pre><code>function MyFunc(a) {
var s = '`';
}
</code></pre>
<blockquote>
<p>And some nested quote</p>
<pre><code class="html language-html">&lt;div&gt;HTML!&lt;/div&gt;
</code></pre>
</blockquote>
</blockquote>

View File

@ -0,0 +1,13 @@
> Define a function in javascript:
>
> ```
> function MyFunc(a) {
> var s = '`';
> }
> ```
>
>> And some nested quote
>>
>> ```html
>> <div>HTML!</div>
>> ```

View File

@ -0,0 +1,9 @@
<p><code>some **code** yeah</code></p>
<p>some <code>inline **code** block</code></p>
<p><code>some inline **code**</code> block</p>
<p>yo dawg <code start="true">some <code start="false">code</code> inception</code></p>
<div>some **div** yeah</div>

View File

@ -0,0 +1,9 @@
<code>some **code** yeah</code>
some <code>inline **code** block</code>
<code>some inline **code**</code> block
yo dawg <code start="true">some <code start="false">code</code> inception</code>
<div>some **div** yeah</div>

View File

@ -0,0 +1,5 @@
<p>pointer *ptr *thing</p>
<p>something _else _bla</p>
<p>something __else __bla</p>

View File

@ -0,0 +1,5 @@
pointer *ptr *thing
something _else _bla
something __else __bla

View File

@ -0,0 +1,7 @@
<p><a href="http://website.com/img@x2.jpg">http://website.com/img@x2.jpg</a></p>
<p><a href="http://website.com/img-x2.jpg">http://website.com/img-x2.jpg</a></p>
<p><a href="http://website.com/img@x2">http://website.com/img@x2</a></p>
<p><a href="http://website.com/img@.jpg">http://website.com/img@.jpg</a></p>

View File

@ -0,0 +1,7 @@
http://website.com/img@x2.jpg
http://website.com/img-x2.jpg
http://website.com/img@x2
http://website.com/img@.jpg

View File

@ -0,0 +1,8 @@
<p>some text</p>
<pre><code>| Tables | Are | Cool |
| ------------- |:-------------:| -----:|
| **col 3 is** | right-aligned | $1600 |
| col 2 is | *centered* | $12 |
| zebra stripes | ~~are neat~~ | $1 |
</code></pre>

View File

@ -0,0 +1,8 @@
some text
| Tables | Are | Cool |
| ------------- |:-------------:| -----:|
| **col 3 is** | right-aligned | $1600 |
| col 2 is | *centered* | $12 |
| zebra stripes | ~~are neat~~ | $1 |

View File

@ -0,0 +1,4 @@
<blockquote>
<p>a blockquote</p>
<h1 id="followedbyanheading">followed by an heading</h1>
</blockquote>

View File

@ -0,0 +1,2 @@
> a blockquote
# followed by an heading

View File

@ -0,0 +1,20 @@
<p>Test pre in a list</p>
<ul>
<li>&amp; &lt;</li>
<li><code>&amp; &lt;</code>
<ul>
<li>&amp; &lt;</li>
<li><code>&amp; &lt;</code>
<ul>
<li>&amp; &lt;</li>
<li><code>&amp; &lt;</code>
<ul>
<li>&amp; &lt;</li>
<li><code>&amp; &lt;</code></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

View File

@ -0,0 +1,10 @@
Test pre in a list
- & <
- `& <`
- & <
- `& <`
- & <
- `& <`
- & <
- `& <`

View File

@ -11,39 +11,41 @@ describe('makeHtml() features testsuite', function () {
'use strict';
for (var i = 0; i < testsuite.length; ++i) {
var converter;
if (testsuite[i].name === '#143.support_image_dimensions') {
if (testsuite[i].name === '#143.support-image-dimensions') {
converter = new showdown.Converter({parseImgDimensions: true});
} else if (testsuite[i].name === '#69.header_level_start') {
} else if (testsuite[i].name === '#69.header-level-start') {
converter = new showdown.Converter({headerLevelStart: 3});
} else if (testsuite[i].name === '#164.1.simple_autolink') {
} else if (testsuite[i].name === '#164.1.simple-autolink' || testsuite[i].name === '#204.certain-links-with-at-and-dot-break-url') {
converter = new showdown.Converter({simplifiedAutoLink: true});
} else if (testsuite[i].name === '#164.2.disallow_underscore_emphasis_mid_word') {
} else if (testsuite[i].name === '#164.2.disallow-underscore-emphasis-mid-word') {
converter = new showdown.Converter({literalMidWordUnderscores: true});
} else if (testsuite[i].name === '#164.3.strikethrough') {
converter = new showdown.Converter({strikethrough: true});
} else if (testsuite[i].name === 'disable_gh_codeblocks') {
} else if (testsuite[i].name === 'disable-gh-codeblocks') {
converter = new showdown.Converter({ghCodeBlocks: false});
} else if (testsuite[i].name === '#164.4.tasklists') {
converter = new showdown.Converter({tasklists: true});
} else if (testsuite[i].name === 'autolink_and_disallow_underscores') {
} else if (testsuite[i].name === 'autolink-and-disallow-underscores') {
converter = new showdown.Converter({literalMidWordUnderscores: true, simplifiedAutoLink: true});
} else if (testsuite[i].name === '#198.literalMidWordUnderscores-changes-behavior-of-asterisk') {
converter = new showdown.Converter({literalMidWordUnderscores: true});
} else {
converter = new showdown.Converter();
}
it(testsuite[i].name, assertion(testsuite[i], converter));
it(testsuite[i].name.replace(/-/g, ' '), assertion(testsuite[i], converter));
}
describe('table support', function () {
var converter;
for (var i = 0; i < tableSuite.length; ++i) {
if (tableSuite[i].name === 'basic_with_header_ids') {
if (tableSuite[i].name === 'basic-with-header-ids') {
converter = new showdown.Converter({tables: true, tableHeaderId: true});
} else if (tableSuite[i].name === '#179.parse_md_in_table_ths') {
} else if (tableSuite[i].name === '#179.parse-md-in-table-ths') {
converter = new showdown.Converter({tables: true, strikethrough: true});
} else {
converter = new showdown.Converter({tables: true});
}
it(tableSuite[i].name, assertion(tableSuite[i], converter));
it(tableSuite[i].name.replace(/-/g, ' '), assertion(tableSuite[i], converter));
}
});

View File

@ -17,6 +17,6 @@ var bootstrap = require('../bootstrap.js'),
describe('makeHtml() ghost testsuite', function () {
'use strict';
for (var i = 0; i < testsuite.length; ++i) {
it(testsuite[i].name, assertion(testsuite[i], converter));
it(testsuite[i].name.replace(/-/g, ' '), assertion(testsuite[i], converter));
}
});

View File

@ -9,6 +9,6 @@ var bootstrap = require('../bootstrap.js'),
describe('makeHtml() issues testsuite', function () {
'use strict';
for (var i = 0; i < testsuite.length; ++i) {
it(testsuite[i].name, assertion(testsuite[i], converter));
it(testsuite[i].name.replace(/-/g, ' '), assertion(testsuite[i], converter));
}
});

View File

@ -7,6 +7,6 @@ var bootstrap = require('../bootstrap.js'),
describe('makeHtml() karlcow testsuite', function () {
'use strict';
for (var i = 0; i < testsuite.length; ++i) {
it(testsuite[i].name, assertion(testsuite[i], converter));
it(testsuite[i].name.replace(/-/g, ' '), assertion(testsuite[i], converter));
}
});

View File

@ -6,6 +6,6 @@ var bootstrap = require('../bootstrap.js'),
describe('makeHtml() standard testsuite', function () {
'use strict';
for (var i = 0; i < testsuite.length; ++i) {
it(testsuite[i].name, assertion(testsuite[i], converter));
it(testsuite[i].name.replace(/-/g, ' '), assertion(testsuite[i], converter));
}
});