feat(base64-wrapping): support for wrapping base64 strings

Wrapping base64 strings, which are usually extremely long lines of text, is now supported.
Newlines can be added arbitrarily, as long as they appear after the comma (,) character.

Closes #429
This commit is contained in:
Estevao Soares dos Santos 2017-09-08 20:46:01 +01:00
parent ff24bdba9f
commit 8c593a4f11
9 changed files with 79 additions and 25 deletions

47
dist/showdown.js vendored
View File

@ -1,4 +1,4 @@
;/*! showdown v 1.7.3 - 23-08-2017 */
;/*! showdown v 1.7.4 - 08-09-2017 */
(function(){
/**
* Created by Tivie on 13-07-2015.
@ -586,7 +586,7 @@ showdown.helper.isFunction = function (a) {
*/
showdown.helper.isArray = function (a) {
'use strict';
return a.constructor === Array;
return Array.isArray(a);
};
/**
@ -2246,9 +2246,15 @@ showdown.subParser('images', function (text, options, globals) {
var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,
referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[(.*?)]()()()()()/g,
base64RegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,
refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g;
function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) {
url = url.replace(/\s/g, '');
return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
}
function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
var gUrls = globals.gUrls,
@ -2318,13 +2324,17 @@ showdown.subParser('images', function (text, options, globals) {
text = text.replace(referenceRegExp, writeImageTag);
// Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
// base64 encoded images
text = text.replace(base64RegExp, writeImageTagBase64);
// cases with crazy urls like ./image/cat1).png
text = text.replace(crazyRegExp, writeImageTag);
// normal cases
text = text.replace(inlineRegExp, writeImageTag);
// handle reference-style shortcuts: |[img text]
// handle reference-style shortcuts: ![img text]
text = text.replace(refShortcutRegExp, writeImageTag);
text = globals.converter._dispatch('images.after', text, options, globals);
@ -2774,14 +2784,20 @@ showdown.subParser('strikethrough', function (text, options, globals) {
showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
'use strict';
var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm;
var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,
base64Regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm;
// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
text += '¨0';
text = text.replace(regex, function (wholeMatch, linkId, url, width, height, blankLines, title) {
var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
linkId = linkId.toLowerCase();
globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
if (url.match(/^data:.+?\/.+?;base64,/)) {
// remove newlines
globals.gUrls[linkId] = url.replace(/\s/g, '');
} else {
globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
}
if (blankLines) {
// Oops, found blank lines, so it's not a title.
@ -2801,7 +2817,12 @@ showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
}
// Completely remove the definition from the text
return '';
});
};
// first we try to find base64 link references
text = text.replace(base64Regex, replaceFunc);
text = text.replace(regex, replaceFunc);
// attacklab: strip sentinel
text = text.replace(/¨0/, '');
@ -2968,17 +2989,17 @@ showdown.subParser('unescapeSpecialChars', function (text, options, globals) {
var root = this;
// CommonJS/nodeJS Loader
if (typeof module !== 'undefined' && module.exports) {
module.exports = showdown;
// AMD Loader
} else if (typeof define === 'function' && define.amd) {
if (typeof define === 'function' && define.amd) {
define(function () {
'use strict';
return showdown;
});
// CommonJS/nodeJS Loader
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = showdown;
// Regular Browser loader
} else {
root.showdown = showdown;

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

@ -1,6 +1,6 @@
{
"name": "showdown",
"version": "1.7.3",
"version": "1.7.4",
"description": "A Markdown to HTML converter written in Javascript",
"author": "Estevão Santos",
"homepage": "http://showdownjs.github.io/showdown/",

View File

@ -8,9 +8,15 @@ showdown.subParser('images', function (text, options, globals) {
var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,
referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[(.*?)]()()()()()/g,
base64RegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,
refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g;
function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) {
url = url.replace(/\s/g, '');
return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
}
function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
var gUrls = globals.gUrls,
@ -80,13 +86,17 @@ showdown.subParser('images', function (text, options, globals) {
text = text.replace(referenceRegExp, writeImageTag);
// Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
// base64 encoded images
text = text.replace(base64RegExp, writeImageTagBase64);
// cases with crazy urls like ./image/cat1).png
text = text.replace(crazyRegExp, writeImageTag);
// normal cases
text = text.replace(inlineRegExp, writeImageTag);
// handle reference-style shortcuts: |[img text]
// handle reference-style shortcuts: ![img text]
text = text.replace(refShortcutRegExp, writeImageTag);
text = globals.converter._dispatch('images.after', text, options, globals);

View File

@ -6,14 +6,20 @@
showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
'use strict';
var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm;
var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,
base64Regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm;
// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
text += '¨0';
text = text.replace(regex, function (wholeMatch, linkId, url, width, height, blankLines, title) {
var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
linkId = linkId.toLowerCase();
globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
if (url.match(/^data:.+?\/.+?;base64,/)) {
// remove newlines
globals.gUrls[linkId] = url.replace(/\s/g, '');
} else {
globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
}
if (blankLines) {
// Oops, found blank lines, so it's not a title.
@ -33,7 +39,12 @@ showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
}
// Completely remove the definition from the text
return '';
});
};
// first we try to find base64 link references
text = text.replace(base64Regex, replaceFunc);
text = text.replace(regex, replaceFunc);
// attacklab: strip sentinel
text = text.replace(/¨0/, '');

View File

@ -0,0 +1,3 @@
<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYSURBVBhXYwCC/2AAZYEoOAMs8Z+BgQEAXdcR7/Q1gssAAAAASUVORK5CYII=" alt="foo" /></p>
<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYSURBVBhXYwCC/2AAZYEoOAMs8Z+BgQEAXdcR7/Q1gssAAAAASUVORK5CYII=" alt="bar" /></p>

View File

@ -0,0 +1,9 @@
![foo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAAXNSR0IArs4c6QAAAARnQU1BAA
Cxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYSURBVBhXYwCC/2AAZYEoOAMs8Z+BgQEAXdcR7/Q1gssAAAAASUVORK5CYII=)
![bar][]
[bar]:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAAXNSR0IArs4c6QAAAARnQU1BAA
Cxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYSURBVBhXYwCC/2AAZYEoOAMs8Z+BgQEAXdcR7/Q1gssAAAAASUVORK5CYII=