mirror of
https://github.com/showdownjs/showdown.git
synced 2024-03-22 13:30:55 +08:00
add links
This commit is contained in:
parent
5a14ce02db
commit
c48801d8fa
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "showdown",
|
"name": "showdown",
|
||||||
"version": "2.0.0",
|
"version": "3.0.0-alpha",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "showdown",
|
"name": "showdown",
|
||||||
"version": "2.0.0",
|
"version": "3.0.0-alpha",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "^9.0.0",
|
"commander": "^9.0.0",
|
||||||
|
|
|
@ -140,9 +140,9 @@ showdown.subParser('makehtml.image', function (text, options, globals) {
|
||||||
startEvent = globals.converter.dispatch(startEvent);
|
startEvent = globals.converter.dispatch(startEvent);
|
||||||
text = startEvent.output;
|
text = startEvent.output;
|
||||||
|
|
||||||
let inlineRegExp = /!\[([^\]]*?)][ \t]*\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\5)?[ \t]?\)/g,
|
let inlineRegExp = /!\[([^\]]*?)][ \t]*\([ \t]?<?(\S+?(?:\(\S*?\)\S*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\5)?[ \t]?\)/g,
|
||||||
crazyRegExp = /!\[([^\]]*?)][ \t]*\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\5)?[ \t]?\)/g,
|
crazyRegExp = /!\[([^\]]*?)][ \t]*\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\5)?[ \t]?\)/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,
|
base64RegExp = /!\[([^\]]*?)][ \t]*\([ \t]?<?(data:.+?\/.+?;base64,[A-Za-z\d+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
|
||||||
referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]/g,
|
referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]/g,
|
||||||
refShortcutRegExp = /!\[([^\[\]]+)]/g;
|
refShortcutRegExp = /!\[([^\[\]]+)]/g;
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,19 @@ showdown.subParser('makehtml.link', function (text, options, globals) {
|
||||||
* @param {string|null} [url]
|
* @param {string|null} [url]
|
||||||
* @param {string|null} [title]
|
* @param {string|null} [title]
|
||||||
* @param {boolean} [emptyCase]
|
* @param {boolean} [emptyCase]
|
||||||
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function writeAnchorTag (subEvtName, pattern, wholeMatch, text, linkId, url, title, emptyCase) {
|
function writeAnchorTag (subEvtName, pattern, wholeMatch, text, linkId, url, title, emptyCase) {
|
||||||
|
|
||||||
let otp = '';
|
let matches = {
|
||||||
let target = null;
|
_wholeMatch: wholeMatch,
|
||||||
|
_linkId: linkId,
|
||||||
|
_url: url,
|
||||||
|
_title: title,
|
||||||
|
text: text
|
||||||
|
},
|
||||||
|
otp,
|
||||||
|
attributes = {};
|
||||||
|
|
||||||
title = title || null;
|
title = title || null;
|
||||||
url = url || null;
|
url = url || null;
|
||||||
|
@ -55,35 +63,85 @@ showdown.subParser('makehtml.link', function (text, options, globals) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url);
|
||||||
url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
|
url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
|
||||||
|
attributes.href = url;
|
||||||
|
|
||||||
if (title && showdown.helper.isString(title)) {
|
if (title && showdown.helper.isString(title)) {
|
||||||
title = title
|
title = title
|
||||||
.replace(/"/g, '"')
|
.replace(/"/g, '"')
|
||||||
.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
|
.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
|
||||||
|
attributes.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optionLinksInNewWindow only applies
|
// optionLinksInNewWindow only applies
|
||||||
// to external links. Hash links (#) open in same page
|
// to external links. Hash links (#) open in same page
|
||||||
if (options.openLinksInNewWindow && !/^#/.test(url)) {
|
if (options.openLinksInNewWindow && !/^#/.test(url)) {
|
||||||
// escaped _
|
attributes.rel = 'noopener noreferrer';
|
||||||
target = ' rel="noopener noreferrer" target="¨E95Eblank"';
|
attributes.target = '¨E95Eblank'; // escaped _
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text can be a markdown element, so we run through the appropriate parsers
|
let captureStartEvent = new showdown.Event('makehtml.link.' + subEvtName + '.onCapture', wholeMatch);
|
||||||
text = showdown.subParser('makehtml.codeSpan')(text, options, globals);
|
captureStartEvent
|
||||||
text = showdown.subParser('makehtml.emoji')(text, options, globals);
|
.setOutput(null)
|
||||||
text = showdown.subParser('makehtml.underline')(text, options, globals);
|
._setGlobals(globals)
|
||||||
text = showdown.subParser('makehtml.emphasisAndStrong')(text, options, globals);
|
._setOptions(options)
|
||||||
text = showdown.subParser('makehtml.strikethrough')(text, options, globals);
|
.setRegexp(pattern)
|
||||||
text = showdown.subParser('makehtml.ellipsis')(text, options, globals);
|
.setMatches(matches)
|
||||||
text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals);
|
.setAttributes(attributes);
|
||||||
|
captureStartEvent = globals.converter.dispatch(captureStartEvent);
|
||||||
|
|
||||||
|
// if something was passed as output, it takes precedence
|
||||||
|
// and will be used as output
|
||||||
|
if (captureStartEvent.output && captureStartEvent.output !== '') {
|
||||||
|
otp = captureStartEvent.output;
|
||||||
|
} else {
|
||||||
|
attributes = captureStartEvent.attributes;
|
||||||
|
text = captureStartEvent.matches.text || '';
|
||||||
|
// Text can be a markdown element, so we run through the appropriate parsers
|
||||||
|
text = showdown.subParser('makehtml.codeSpan')(text, options, globals);
|
||||||
|
text = showdown.subParser('makehtml.emoji')(text, options, globals);
|
||||||
|
text = showdown.subParser('makehtml.underline')(text, options, globals);
|
||||||
|
text = showdown.subParser('makehtml.emphasisAndStrong')(text, options, globals);
|
||||||
|
text = showdown.subParser('makehtml.strikethrough')(text, options, globals);
|
||||||
|
text = showdown.subParser('makehtml.ellipsis')(text, options, globals);
|
||||||
|
text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals);
|
||||||
|
otp = '<a' + showdown.helper._populateAttributes(attributes) + '>' + text + '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
let beforeHashEvent = new showdown.Event('makehtml.link.' + subEvtName + '.onHash', otp);
|
||||||
return otp;
|
beforeHashEvent
|
||||||
|
.setOutput(otp)
|
||||||
|
._setGlobals(globals)
|
||||||
|
._setOptions(options);
|
||||||
|
beforeHashEvent = globals.converter.dispatch(beforeHashEvent);
|
||||||
|
otp = beforeHashEvent.output;
|
||||||
|
return showdown.subParser('makehtml.hashHTMLSpans')(otp, options, globals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} mail
|
||||||
|
* @returns {{mail: string, url: string}}
|
||||||
|
*/
|
||||||
|
function parseMail (mail) {
|
||||||
|
let url = 'mailto:';
|
||||||
|
mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals);
|
||||||
|
if (options.encodeEmails) {
|
||||||
|
url = showdown.helper.encodeEmailAddress(url + mail);
|
||||||
|
mail = showdown.helper.encodeEmailAddress(mail);
|
||||||
|
} else {
|
||||||
|
url = url + mail;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
mail: mail,
|
||||||
|
url: url
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Parser starts here
|
||||||
|
//
|
||||||
let startEvent = new showdown.Event('makehtml.link.onStart', text);
|
let startEvent = new showdown.Event('makehtml.link.onStart', text);
|
||||||
startEvent
|
startEvent
|
||||||
.setOutput(text)
|
.setOutput(text)
|
||||||
|
@ -92,10 +150,172 @@ showdown.subParser('makehtml.link', function (text, options, globals) {
|
||||||
startEvent = globals.converter.dispatch(startEvent);
|
startEvent = globals.converter.dispatch(startEvent);
|
||||||
text = startEvent.output;
|
text = startEvent.output;
|
||||||
|
|
||||||
let referenceRegex = /\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g;
|
|
||||||
|
|
||||||
// 1. Handle reference-style links: [link text] [id]
|
// 1. Handle reference-style links: [link text] [id]
|
||||||
text = text.replace(referenceRegex, function (wholeMatch, altText, linkId) {
|
let referenceRegex = /\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]/g;
|
||||||
return writeAnchorTag ('reference', referenceRegex, wholeMatch, altText, linkId, '');
|
text = text.replace(referenceRegex, function (wholeMatch, text, linkId) {
|
||||||
|
// bail if we find 2 newlines somewhere
|
||||||
|
if (/\n\n/.test(wholeMatch)) {
|
||||||
|
return wholeMatch;
|
||||||
|
}
|
||||||
|
return writeAnchorTag ('reference', referenceRegex, wholeMatch, text, linkId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 2. Handle inline-style links: [link text](url "optional title")
|
||||||
|
// 2.1. Look for empty cases: []() and [empty]() and []("title")
|
||||||
|
let inlineEmptyRegex = /\[(.*?)]\(<? ?>? ?(["'](.*)["'])?\)/g;
|
||||||
|
text = text.replace(inlineEmptyRegex, function (wholeMatch, text, m1, title) {
|
||||||
|
return writeAnchorTag ('inline', inlineEmptyRegex, wholeMatch, text, null, null, title, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2.2. Look for cases with crazy urls like ./image/cat1).png
|
||||||
|
// the url mus be enclosed in <>
|
||||||
|
let inlineCrazyRegex = /\[((?:\[[^\]]*]|[^\[\]])*)]\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\4))?[ \t]?\)/g;
|
||||||
|
text = text.replace(inlineCrazyRegex, function (wholeMatch, text, url, m1, m2, title) {
|
||||||
|
return writeAnchorTag ('inline', inlineCrazyRegex, wholeMatch, text, null, url, title);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2.3. inline links with no title or titles wrapped in ' or ":
|
||||||
|
// [text](url.com) || [text](<url.com>) || [text](url.com "title") || [text](<url.com> "title")
|
||||||
|
let inlineNormalRegex1 = /\[([\S ]*?)]\s?\( *<?([^\s'"]*?(?:\(\S*?\)\S*?)?)>?\s*(?:(['"])(.*?)\3)? *\)/g;
|
||||||
|
text = text.replace(inlineNormalRegex1, function (wholeMatch, text, url, m1, title) {
|
||||||
|
return writeAnchorTag ('inline', inlineNormalRegex1, wholeMatch, text, null, url, title);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2.4. inline links with titles wrapped in (): [foo](bar.com (title))
|
||||||
|
let inlineNormalRegex2 = /\[([\S ]*?)]\s?\( *<?([^\s'"]*?(?:\(\S*?\)\S*?)?)>?\s+\((.*?)\) *\)/g;
|
||||||
|
text = text.replace(inlineNormalRegex2, function (wholeMatch, text, url, title) {
|
||||||
|
return writeAnchorTag ('inline', inlineNormalRegex2, wholeMatch, text, null, url, title);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 3. Handle reference-style shortcuts: [link text]
|
||||||
|
// These must come last in case there's a [link text][1] or [link text](/foo)
|
||||||
|
let referenceShortcutRegex = /\[([^\[\]]+)]/g;
|
||||||
|
text = text.replace(referenceShortcutRegex, function (wholeMatch, text) {
|
||||||
|
return writeAnchorTag ('reference', referenceShortcutRegex, wholeMatch, text);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. Handle angle brackets links -> `<http://example.com/>`
|
||||||
|
// Must come after links, because you can use < and > delimiters in inline links like [this](<url>).
|
||||||
|
|
||||||
|
// 4.1. Handle links first
|
||||||
|
let angleBracketsLinksRegex = /<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi;
|
||||||
|
text = text.replace(angleBracketsLinksRegex, function (wholeMatch, url, urlStart) {
|
||||||
|
let text = url;
|
||||||
|
url = (urlStart === 'www.') ? 'http://' + url : url;
|
||||||
|
return writeAnchorTag ('angleBrackets', angleBracketsLinksRegex, wholeMatch, text, null, url);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4.2. Then mail adresses
|
||||||
|
let angleBracketsMailRegex = /<(?:mailto:)?([-.\w]+@[-a-z\d]+(\.[-a-z\d]+)*\.[a-z]+)>/gi;
|
||||||
|
text = text.replace(angleBracketsMailRegex, function (wholeMatch, mail) {
|
||||||
|
const m = parseMail(mail);
|
||||||
|
return writeAnchorTag ('angleBrackets', angleBracketsMailRegex, wholeMatch, m.mail, null, m.url);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 5. Handle GithubMentions (if option is enabled)
|
||||||
|
if (options.ghMentions) {
|
||||||
|
let ghMentionsRegex = /(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi;
|
||||||
|
text = text.replace(ghMentionsRegex, function (wholeMatch, st, escape, mentions, username) {
|
||||||
|
// bail if the mentions was escaped
|
||||||
|
if (escape === '\\') {
|
||||||
|
return st + mentions;
|
||||||
|
}
|
||||||
|
// check if options.ghMentionsLink is a string
|
||||||
|
// TODO Validation should be done at initialization not at runtime
|
||||||
|
if (!showdown.helper.isString(options.ghMentionsLink)) {
|
||||||
|
throw new Error('ghMentionsLink option must be a string');
|
||||||
|
}
|
||||||
|
let url = options.ghMentionsLink.replace(/\{u}/g, username);
|
||||||
|
return st + writeAnchorTag ('reference', ghMentionsRegex, wholeMatch, mentions, null, url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6 and 7 have to come here to prevent naked links to catch html
|
||||||
|
// 6. Handle <a> tags
|
||||||
|
text = text.replace(/<a\s[^>]*>[\s\S]*<\/a>/g, function (wholeMatch) {
|
||||||
|
return showdown.helper._hashHTMLSpan(wholeMatch, globals);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 7. Handle <img> tags
|
||||||
|
text = text.replace(/<img\s[^>]*\/?>/g, function (wholeMatch) {
|
||||||
|
return showdown.helper._hashHTMLSpan(wholeMatch, globals);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 8. Handle naked links (if option is enabled)
|
||||||
|
if (options.simplifiedAutoLink) {
|
||||||
|
// 8.1. Check for naked URLs
|
||||||
|
// we also include leading markdown magic chars [_*~] for cases like __https://www.google.com/foobar__
|
||||||
|
let nakedUrlRegex = /([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`´.-][^\s<>"'`´]*?\.[a-z\d.]+[^\s<>"']*)\1/gi;
|
||||||
|
text = text.replace(nakedUrlRegex, function (wholeMatch, leadingMDChars, url, urlPrefix) {
|
||||||
|
// we now will start traversing the url from the front to back, looking for punctuation chars [_*~,;:.!?\)\]]
|
||||||
|
const len = url.length;
|
||||||
|
let suffix = '';
|
||||||
|
|
||||||
|
for (let i = len - 1; i >= 0; --i) {
|
||||||
|
let char = url.charAt(i);
|
||||||
|
if (/[_*~,;:.!?]/.test(char)) {
|
||||||
|
// it's a punctuation char so we remove it from the url
|
||||||
|
url = url.slice(0, -1);
|
||||||
|
// and prepend it to the suffix
|
||||||
|
suffix = char + suffix;
|
||||||
|
} else if (/[)\]]/.test(char)) {
|
||||||
|
// it's a parenthesis so we need to check for "balance" (kinda)
|
||||||
|
let opPar, clPar;
|
||||||
|
if (/\)/.test(char)) {
|
||||||
|
// it's a curved parenthesis
|
||||||
|
opPar = url.match(/\(/g) || [];
|
||||||
|
clPar = url.match(/\)/g);
|
||||||
|
} else {
|
||||||
|
// it's a squared parenthesis
|
||||||
|
opPar = url.match(/\[/g) || [];
|
||||||
|
clPar = url.match(/]/g);
|
||||||
|
}
|
||||||
|
if (opPar.length < clPar.length) {
|
||||||
|
// there are more closing Parenthesis than opening so chop it!!!!!
|
||||||
|
url = url.slice(0, -1);
|
||||||
|
// and prepend it to the suffix
|
||||||
|
suffix = char + suffix;
|
||||||
|
} else {
|
||||||
|
// it's (kinda) balanced so our work is done
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// it's not a punctuation or a parenthesis so our work is done
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we copy the treated url to the text variable
|
||||||
|
let txt = url;
|
||||||
|
// finally, if it's a www shortcut, we prepend http
|
||||||
|
url = (urlPrefix === 'www.') ? 'http://' + url : url;
|
||||||
|
|
||||||
|
// url part is done so let's take care of text now
|
||||||
|
// we need to escape the text (because of links such as www.example.com/foo__bar__baz)
|
||||||
|
txt = txt.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
|
||||||
|
|
||||||
|
// and return the link tag, with the leadingMDChars and suffix. The leadingMDChars are added at the end too because
|
||||||
|
// we consumed those characters in the regexp
|
||||||
|
return leadingMDChars +
|
||||||
|
writeAnchorTag ('autoLink', nakedUrlRegex, wholeMatch, txt, null, url) +
|
||||||
|
suffix +
|
||||||
|
leadingMDChars;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 8.2. Now check for naked mail
|
||||||
|
let nakedMailRegex = /(^|\s)(?:mailto:)?([A-Za-z\d!#$%&'*+-/=?^_`{|}~.]+@[-a-z\d]+(\.[-a-z\d]+)*\.[a-z]+)(?=$|\s)/gmi;
|
||||||
|
text = text.replace(nakedMailRegex, function (wholeMatch, leadingChar, mail) {
|
||||||
|
const m = parseMail(mail);
|
||||||
|
return leadingChar + writeAnchorTag ('autoLink', nakedMailRegex, wholeMatch, m.mail, null, m.url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let afterEvent = new showdown.Event('makehtml.link.onEnd', text);
|
||||||
|
afterEvent
|
||||||
|
.setOutput(text)
|
||||||
|
._setGlobals(globals)
|
||||||
|
._setOptions(options);
|
||||||
|
afterEvent = globals.converter.dispatch(afterEvent);
|
||||||
|
return afterEvent.output;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,429 +0,0 @@
|
||||||
////
|
|
||||||
// makehtml/links.js
|
|
||||||
// Copyright (c) 2018 ShowdownJS
|
|
||||||
//
|
|
||||||
// Transforms MD links into `<a>` html anchors
|
|
||||||
//
|
|
||||||
// A link contains link text (the visible text), a link destination (the URI that is the link destination), and
|
|
||||||
// optionally a link title. There are two basic kinds of links in Markdown.
|
|
||||||
// In inline links the destination and title are given immediately after the link text.
|
|
||||||
// In reference links the destination and title are defined elsewhere in the document.
|
|
||||||
//
|
|
||||||
// ***Author:***
|
|
||||||
// - Estevão Soares dos Santos (Tivie) <https://github.com/tivie>
|
|
||||||
////
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
/**
|
|
||||||
* Helper function: Wrapper function to pass as second replace parameter
|
|
||||||
*
|
|
||||||
* @param {RegExp} rgx
|
|
||||||
* @param {string} evtRootName
|
|
||||||
* @param {{}} options
|
|
||||||
* @param {{}} globals
|
|
||||||
* @param {boolean} emptyCase
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
function replaceAnchorTagReference (rgx, evtRootName, options, globals, emptyCase) {
|
|
||||||
emptyCase = !!emptyCase;
|
|
||||||
return function (wholeMatch, text, id, url, m5, m6, title) {
|
|
||||||
// bail we we find 2 newlines somewhere
|
|
||||||
if (/\n\n/.test(wholeMatch)) {
|
|
||||||
return wholeMatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals);
|
|
||||||
return writeAnchorTag(evt, options, globals, emptyCase);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function replaceAnchorTagBaseUrl (rgx, evtRootName, options, globals, emptyCase) {
|
|
||||||
return function (wholeMatch, text, id, url, m5, m6, title) {
|
|
||||||
url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url);
|
|
||||||
|
|
||||||
var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals);
|
|
||||||
return writeAnchorTag(evt, options, globals, emptyCase);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO Normalize this
|
|
||||||
* Helper function: Create a capture event
|
|
||||||
* @param {RegExp} rgx
|
|
||||||
* @param {String} evtName Event name
|
|
||||||
* @param {String} wholeMatch
|
|
||||||
* @param {String} text
|
|
||||||
* @param {String} id
|
|
||||||
* @param {String} url
|
|
||||||
* @param {String} title
|
|
||||||
* @param {{}} options
|
|
||||||
* @param {{}} globals
|
|
||||||
* @returns {showdown.Event|*}
|
|
||||||
*/
|
|
||||||
function createEvent (rgx, evtName, wholeMatch, text, id, url, title, options, globals) {
|
|
||||||
return globals.converter._dispatch(evtName, wholeMatch, options, globals, {
|
|
||||||
regexp: rgx,
|
|
||||||
matches: {
|
|
||||||
wholeMatch: wholeMatch,
|
|
||||||
text: text,
|
|
||||||
id: id,
|
|
||||||
url: url,
|
|
||||||
title: title
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper Function: Normalize and write an anchor tag based on passed parameters
|
|
||||||
* @param evt
|
|
||||||
* @param options
|
|
||||||
* @param globals
|
|
||||||
* @param {boolean} emptyCase
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function writeAnchorTag (evt, options, globals, emptyCase) {
|
|
||||||
|
|
||||||
var wholeMatch = evt.matches.wholeMatch;
|
|
||||||
var text = evt.matches.text;
|
|
||||||
var id = evt.matches.id;
|
|
||||||
var url = evt.matches.url;
|
|
||||||
var title = evt.matches.title;
|
|
||||||
var target = '';
|
|
||||||
|
|
||||||
if (!title) {
|
|
||||||
title = '';
|
|
||||||
}
|
|
||||||
id = (id) ? id.toLowerCase() : '';
|
|
||||||
|
|
||||||
if (emptyCase) {
|
|
||||||
url = '';
|
|
||||||
} else if (!url) {
|
|
||||||
if (!id) {
|
|
||||||
// lower-case and turn embedded newlines into spaces
|
|
||||||
id = text.toLowerCase().replace(/ ?\n/g, ' ');
|
|
||||||
}
|
|
||||||
url = '#' + id;
|
|
||||||
|
|
||||||
if (!showdown.helper.isUndefined(globals.gUrls[id])) {
|
|
||||||
url = globals.gUrls[id];
|
|
||||||
if (!showdown.helper.isUndefined(globals.gTitles[id])) {
|
|
||||||
title = globals.gTitles[id];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return wholeMatch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//url = showdown.helper.escapeCharacters(url, '*_:~', false); // replaced line to improve performance
|
|
||||||
url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
|
|
||||||
|
|
||||||
if (title !== '' && title !== null) {
|
|
||||||
title = title.replace(/"/g, '"');
|
|
||||||
//title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance
|
|
||||||
title = title.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
|
|
||||||
title = ' title="' + title + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
// optionLinksInNewWindow only applies
|
|
||||||
// to external links. Hash links (#) open in same page
|
|
||||||
if (options.openLinksInNewWindow && !/^#/.test(url)) {
|
|
||||||
// escaped _
|
|
||||||
target = ' rel="noopener noreferrer" target="¨E95Eblank"';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text can be a markdown element, so we run through the appropriate parsers
|
|
||||||
text = showdown.subParser('makehtml.codeSpan')(text, options, globals);
|
|
||||||
text = showdown.subParser('makehtml.emoji')(text, options, globals);
|
|
||||||
text = showdown.subParser('makehtml.underline')(text, options, globals);
|
|
||||||
text = showdown.subParser('makehtml.emphasisAndStrong')(text, options, globals);
|
|
||||||
text = showdown.subParser('makehtml.strikethrough')(text, options, globals);
|
|
||||||
text = showdown.subParser('makehtml.ellipsis')(text, options, globals);
|
|
||||||
text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals);
|
|
||||||
|
|
||||||
//evt = createEvent(rgx, evtRootName + '.captureEnd', wholeMatch, text, id, url, title, options, globals);
|
|
||||||
|
|
||||||
var result = '<a href="' + url + '"' + title + target + '>' + text + '</a>';
|
|
||||||
|
|
||||||
//evt = createEvent(rgx, evtRootName + '.beforeHash', wholeMatch, text, id, url, title, options, globals);
|
|
||||||
|
|
||||||
result = showdown.subParser('makehtml.hashHTMLSpans')(result, options, globals);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
var evtRootName = 'makehtml.links';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn Markdown link shortcuts into XHTML <a> tags.
|
|
||||||
*/
|
|
||||||
showdown.subParser('makehtml.links', function (text, options, globals) {
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
|
|
||||||
|
|
||||||
// 1. Handle reference-style links: [link text] [id]
|
|
||||||
text = showdown.subParser('makehtml.links.reference')(text, options, globals);
|
|
||||||
|
|
||||||
// 2. Handle inline-style links: [link text](url "optional title")
|
|
||||||
text = showdown.subParser('makehtml.links.inline')(text, options, globals);
|
|
||||||
|
|
||||||
// 3. Handle reference-style shortcuts: [link text]
|
|
||||||
// These must come last in case there's a [link text][1] or [link text](/foo)
|
|
||||||
text = showdown.subParser('makehtml.links.referenceShortcut')(text, options, globals);
|
|
||||||
|
|
||||||
// 4. Handle angle brackets links -> `<http://example.com/>`
|
|
||||||
// Must come after links, because you can use < and > delimiters in inline links like [this](<url>).
|
|
||||||
text = showdown.subParser('makehtml.links.angleBrackets')(text, options, globals);
|
|
||||||
|
|
||||||
// 5. Handle GithubMentions (if option is enabled)
|
|
||||||
text = showdown.subParser('makehtml.links.ghMentions')(text, options, globals);
|
|
||||||
|
|
||||||
// 6. Handle <a> tags and img tags
|
|
||||||
text = text.replace(/<a\s[^>]*>[\s\S]*<\/a>/g, function (wholeMatch) {
|
|
||||||
return showdown.helper._hashHTMLSpan(wholeMatch, globals);
|
|
||||||
});
|
|
||||||
|
|
||||||
text = text.replace(/<img\s[^>]*\/?>/g, function (wholeMatch) {
|
|
||||||
return showdown.helper._hashHTMLSpan(wholeMatch, globals);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 7. Handle naked links (if option is enabled)
|
|
||||||
text = showdown.subParser('makehtml.links.naked')(text, options, globals);
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
|
|
||||||
return text;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO WRITE THIS DOCUMENTATION
|
|
||||||
*/
|
|
||||||
showdown.subParser('makehtml.links.inline', function (text, options, globals) {
|
|
||||||
var evtRootName = evtRootName + '.inline';
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
|
|
||||||
|
|
||||||
// 1. Look for empty cases: []() and [empty]() and []("title")
|
|
||||||
var rgxEmpty = /\[(.*?)]()()()()\(<? ?>? ?(?:["'](.*)["'])?\)/g;
|
|
||||||
text = text.replace(rgxEmpty, replaceAnchorTagBaseUrl(rgxEmpty, evtRootName, options, globals, true));
|
|
||||||
|
|
||||||
// 2. Look for cases with crazy urls like ./image/cat1).png
|
|
||||||
var rgxCrazy = /\[((?:\[[^\]]*]|[^\[\]])*)]()\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g;
|
|
||||||
text = text.replace(rgxCrazy, replaceAnchorTagBaseUrl(rgxCrazy, evtRootName, options, globals));
|
|
||||||
|
|
||||||
// 3. inline links with no title or titles wrapped in ' or ":
|
|
||||||
// [text](url.com) || [text](<url.com>) || [text](url.com "title") || [text](<url.com> "title")
|
|
||||||
//var rgx2 = /\[[ ]*[\s]?[ ]*([^\n\[\]]*?)[ ]*[\s]?[ ]*] ?()\(<?[ ]*[\s]?[ ]*([^\s'"]*)>?(?:[ ]*[\n]?[ ]*()(['"])(.*?)\5)?[ ]*[\s]?[ ]*\)/; // this regex is too slow!!!
|
|
||||||
var rgx2 = /\[([\S ]*?)]\s?()\( *<?([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s*(?:()(['"])(.*?)\5)? *\)/g;
|
|
||||||
text = text.replace(rgx2, replaceAnchorTagBaseUrl(rgx2, evtRootName, options, globals));
|
|
||||||
|
|
||||||
// 4. inline links with titles wrapped in (): [foo](bar.com (title))
|
|
||||||
var rgx3 = /\[([\S ]*?)]\s?()\( *<?([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s+()()\((.*?)\) *\)/g;
|
|
||||||
text = text.replace(rgx3, replaceAnchorTagBaseUrl(rgx3, evtRootName, options, globals));
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
|
|
||||||
|
|
||||||
return text;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO WRITE THIS DOCUMENTATION
|
|
||||||
*/
|
|
||||||
showdown.subParser('makehtml.links.reference', function (text, options, globals) {
|
|
||||||
var evtRootName = evtRootName + '.reference';
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
|
|
||||||
|
|
||||||
var rgx = /\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g;
|
|
||||||
text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals));
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
|
|
||||||
|
|
||||||
return text;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO WRITE THIS DOCUMENTATION
|
|
||||||
*/
|
|
||||||
showdown.subParser('makehtml.links.referenceShortcut', function (text, options, globals) {
|
|
||||||
var evtRootName = evtRootName + '.referenceShortcut';
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
|
|
||||||
|
|
||||||
var rgx = /\[([^\[\]]+)]()()()()()/g;
|
|
||||||
text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals));
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
|
|
||||||
|
|
||||||
return text;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO WRITE THIS DOCUMENTATION
|
|
||||||
*/
|
|
||||||
showdown.subParser('makehtml.links.ghMentions', function (text, options, globals) {
|
|
||||||
var evtRootName = evtRootName + 'ghMentions';
|
|
||||||
|
|
||||||
if (!options.ghMentions) {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
|
|
||||||
|
|
||||||
var rgx = /(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi;
|
|
||||||
|
|
||||||
text = text.replace(rgx, function (wholeMatch, st, escape, mentions, username) {
|
|
||||||
// bail if the mentions was escaped
|
|
||||||
if (escape === '\\') {
|
|
||||||
return st + mentions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if options.ghMentionsLink is a string
|
|
||||||
// TODO Validation should be done at initialization not at runtime
|
|
||||||
if (!showdown.helper.isString(options.ghMentionsLink)) {
|
|
||||||
throw new Error('ghMentionsLink option must be a string');
|
|
||||||
}
|
|
||||||
var url = options.ghMentionsLink.replace(/{u}/g, username);
|
|
||||||
var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, mentions, null, url, null, options, globals);
|
|
||||||
// captureEnd Event is triggered inside writeAnchorTag function
|
|
||||||
return st + writeAnchorTag(evt, options, globals);
|
|
||||||
});
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
|
|
||||||
|
|
||||||
return text;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO WRITE THIS DOCUMENTATION
|
|
||||||
*/
|
|
||||||
showdown.subParser('makehtml.links.angleBrackets', function (text, options, globals) {
|
|
||||||
var evtRootName = 'makehtml.links.angleBrackets';
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
|
|
||||||
|
|
||||||
// 1. Parse links first
|
|
||||||
var urlRgx = /<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi;
|
|
||||||
text = text.replace(urlRgx, function (wholeMatch, url, urlStart) {
|
|
||||||
var text = url;
|
|
||||||
url = (urlStart === 'www.') ? 'http://' + url : url;
|
|
||||||
var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals);
|
|
||||||
return writeAnchorTag(evt, options, globals);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2. Then Mail Addresses
|
|
||||||
var mailRgx = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
|
|
||||||
text = text.replace(mailRgx, function (wholeMatch, mail) {
|
|
||||||
var url = 'mailto:';
|
|
||||||
mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals);
|
|
||||||
if (options.encodeEmails) {
|
|
||||||
url = showdown.helper.encodeEmailAddress(url + mail);
|
|
||||||
mail = showdown.helper.encodeEmailAddress(mail);
|
|
||||||
} else {
|
|
||||||
url = url + mail;
|
|
||||||
}
|
|
||||||
var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals);
|
|
||||||
return writeAnchorTag(evt, options, globals);
|
|
||||||
});
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
|
|
||||||
return text;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO MAKE THIS WORK (IT'S NOT ACTIVATED)
|
|
||||||
* TODO WRITE THIS DOCUMENTATION
|
|
||||||
*/
|
|
||||||
showdown.subParser('makehtml.links.naked', function (text, options, globals) {
|
|
||||||
if (!options.simplifiedAutoLink) {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
var evtRootName = 'makehtml.links.naked';
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
|
|
||||||
|
|
||||||
// 2. Now we check for
|
|
||||||
// we also include leading markdown magic chars [_*~] for cases like __https://www.google.com/foobar__
|
|
||||||
var urlRgx = /([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`´.-][^\s<>"'`´]*?\.[a-z\d.]+[^\s<>"']*)\1/gi;
|
|
||||||
text = text.replace(urlRgx, function (wholeMatch, leadingMDChars, url, urlPrefix) {
|
|
||||||
|
|
||||||
// we now will start traversing the url from the front to back, looking for punctuation chars [_*~,;:.!?\)\]]
|
|
||||||
var len = url.length;
|
|
||||||
var suffix = '';
|
|
||||||
for (var i = len - 1; i >= 0; --i) {
|
|
||||||
var char = url.charAt(i);
|
|
||||||
|
|
||||||
if (/[_*~,;:.!?]/.test(char)) {
|
|
||||||
// it's a punctuation char
|
|
||||||
// we remove it from the url
|
|
||||||
url = url.slice(0, -1);
|
|
||||||
// and prepend it to the suffix
|
|
||||||
suffix = char + suffix;
|
|
||||||
} else if (/\)/.test(char)) {
|
|
||||||
var opPar = url.match(/\(/g) || [];
|
|
||||||
var clPar = url.match(/\)/g);
|
|
||||||
|
|
||||||
// it's a curved parenthesis so we need to check for "balance" (kinda)
|
|
||||||
if (opPar.length < clPar.length) {
|
|
||||||
// there are more closing Parenthesis than opening so chop it!!!!!
|
|
||||||
url = url.slice(0, -1);
|
|
||||||
// and prepend it to the suffix
|
|
||||||
suffix = char + suffix;
|
|
||||||
} else {
|
|
||||||
// it's (kinda) balanced so our work is done
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (/]/.test(char)) {
|
|
||||||
var opPar2 = url.match(/\[/g) || [];
|
|
||||||
var clPar2 = url.match(/\]/g);
|
|
||||||
// it's a squared parenthesis so we need to check for "balance" (kinda)
|
|
||||||
if (opPar2.length < clPar2.length) {
|
|
||||||
// there are more closing Parenthesis than opening so chop it!!!!!
|
|
||||||
url = url.slice(0, -1);
|
|
||||||
// and prepend it to the suffix
|
|
||||||
suffix = char + suffix;
|
|
||||||
} else {
|
|
||||||
// it's (kinda) balanced so our work is done
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// it's not a punctuation or a parenthesis so our work is done
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we copy the treated url to the text variable
|
|
||||||
var text = url;
|
|
||||||
// finally, if it's a www shortcut, we prepend http
|
|
||||||
url = (urlPrefix === 'www.') ? 'http://' + url : url;
|
|
||||||
|
|
||||||
// url part is done so let's take care of text now
|
|
||||||
// we need to escape the text (because of links such as www.example.com/foo__bar__baz)
|
|
||||||
text = text.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
|
|
||||||
|
|
||||||
// finally we dispatch the event
|
|
||||||
var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals);
|
|
||||||
|
|
||||||
// and return the link tag, with the leadingMDChars and suffix. The leadingMDChars are added at the end too because
|
|
||||||
// we consumed those characters in the regexp
|
|
||||||
return leadingMDChars + writeAnchorTag(evt, options, globals) + suffix + leadingMDChars;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2. Then mails
|
|
||||||
var mailRgx = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi;
|
|
||||||
text = text.replace(mailRgx, function (wholeMatch, leadingChar, mail) {
|
|
||||||
var url = 'mailto:';
|
|
||||||
mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals);
|
|
||||||
if (options.encodeEmails) {
|
|
||||||
url = showdown.helper.encodeEmailAddress(url + mail);
|
|
||||||
mail = showdown.helper.encodeEmailAddress(mail);
|
|
||||||
} else {
|
|
||||||
url = url + mail;
|
|
||||||
}
|
|
||||||
var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals);
|
|
||||||
return leadingChar + writeAnchorTag(evt, options, globals);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
|
|
||||||
return text;
|
|
||||||
});
|
|
||||||
})();
|
|
|
@ -20,7 +20,7 @@ showdown.subParser('makehtml.spanGamut', function (text, options, globals) {
|
||||||
// Process link and image tags. Images must come first,
|
// Process link and image tags. Images must come first,
|
||||||
// because ![foo][f] looks like a link.
|
// because ![foo][f] looks like a link.
|
||||||
text = showdown.subParser('makehtml.image')(text, options, globals);
|
text = showdown.subParser('makehtml.image')(text, options, globals);
|
||||||
text = showdown.subParser('makehtml.links')(text, options, globals);
|
text = showdown.subParser('makehtml.link')(text, options, globals);
|
||||||
|
|
||||||
text = showdown.subParser('makehtml.emoji')(text, options, globals);
|
text = showdown.subParser('makehtml.emoji')(text, options, globals);
|
||||||
text = showdown.subParser('makehtml.underline')(text, options, globals);
|
text = showdown.subParser('makehtml.underline')(text, options, globals);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* Created by Estevao on 08-06-2015.
|
* Created by Estevao on 08-06-2015.
|
||||||
*/
|
*/
|
||||||
var bootstrap = require('./makehtml.bootstrap.js'),
|
const bootstrap = require('./makehtml.bootstrap.js'),
|
||||||
showdown = bootstrap.showdown,
|
showdown = bootstrap.showdown,
|
||||||
assertion = bootstrap.assertion,
|
assertion = bootstrap.assertion,
|
||||||
testsuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/'),
|
testsuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/'),
|
||||||
|
@ -29,8 +29,8 @@ describe('makeHtml() features testsuite', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
describe('issues', function () {
|
describe('issues', function () {
|
||||||
for (var i = 0; i < testsuite.length; ++i) {
|
for (let i = 0; i < testsuite.length; ++i) {
|
||||||
var converter;
|
let converter;
|
||||||
if (testsuite[i].name === '#143.support-image-dimensions') {
|
if (testsuite[i].name === '#143.support-image-dimensions') {
|
||||||
converter = new showdown.Converter({parseImgDimensions: true});
|
converter = new showdown.Converter({parseImgDimensions: true});
|
||||||
} else if (testsuite[i].name === '#69.header-level-start') {
|
} else if (testsuite[i].name === '#69.header-level-start') {
|
||||||
|
@ -114,9 +114,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test Table Syntax Support **/
|
/** test Table Syntax Support **/
|
||||||
describe('table support', function () {
|
describe('table support', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = tableSuite;
|
suite = tableSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
if (suite[i].name === 'basic-with-header-ids') {
|
if (suite[i].name === 'basic-with-header-ids') {
|
||||||
converter = new showdown.Converter({tables: true, tablesHeaderId: true});
|
converter = new showdown.Converter({tables: true, tablesHeaderId: true});
|
||||||
} else if (suite[i].name === '#179.parse-md-in-table-ths') {
|
} else if (suite[i].name === '#179.parse-md-in-table-ths') {
|
||||||
|
@ -130,9 +130,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test simplifiedAutoLink Support **/
|
/** test simplifiedAutoLink Support **/
|
||||||
describe('simplifiedAutoLink support in', function () {
|
describe('simplifiedAutoLink support in', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = simplifiedAutoLinkSuite;
|
suite = simplifiedAutoLinkSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
if (suite[i].name === 'emphasis-and-strikethrough') {
|
if (suite[i].name === 'emphasis-and-strikethrough') {
|
||||||
converter = new showdown.Converter({simplifiedAutoLink: true, strikethrough: true});
|
converter = new showdown.Converter({simplifiedAutoLink: true, strikethrough: true});
|
||||||
} else if (suite[i].name === 'disallow-underscores') {
|
} else if (suite[i].name === 'disallow-underscores') {
|
||||||
|
@ -148,9 +148,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test openLinksInNewWindow support **/
|
/** test openLinksInNewWindow support **/
|
||||||
describe('openLinksInNewWindow support in', function () {
|
describe('openLinksInNewWindow support in', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = openLinksInNewWindowSuite;
|
suite = openLinksInNewWindowSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
if (suite[i].name === 'simplifiedAutoLink') {
|
if (suite[i].name === 'simplifiedAutoLink') {
|
||||||
converter = new showdown.Converter({openLinksInNewWindow: true, simplifiedAutoLink: true});
|
converter = new showdown.Converter({openLinksInNewWindow: true, simplifiedAutoLink: true});
|
||||||
} else {
|
} else {
|
||||||
|
@ -162,9 +162,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test disableForced4SpacesIndentedSublists support **/
|
/** test disableForced4SpacesIndentedSublists support **/
|
||||||
describe('disableForced4SpacesIndentedSublists support in', function () {
|
describe('disableForced4SpacesIndentedSublists support in', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = disableForced4SpacesIndentedSublistsSuite;
|
suite = disableForced4SpacesIndentedSublistsSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
converter = new showdown.Converter({disableForced4SpacesIndentedSublists: true});
|
converter = new showdown.Converter({disableForced4SpacesIndentedSublists: true});
|
||||||
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
||||||
}
|
}
|
||||||
|
@ -172,9 +172,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test rawHeaderId support **/
|
/** test rawHeaderId support **/
|
||||||
describe('rawHeaderId support', function () {
|
describe('rawHeaderId support', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = rawHeaderIdSuite;
|
suite = rawHeaderIdSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
if (suite[i].name === 'with-prefixHeaderId') {
|
if (suite[i].name === 'with-prefixHeaderId') {
|
||||||
converter = new showdown.Converter({rawHeaderId: true, prefixHeaderId: '/prefix/'});
|
converter = new showdown.Converter({rawHeaderId: true, prefixHeaderId: '/prefix/'});
|
||||||
} else {
|
} else {
|
||||||
|
@ -186,9 +186,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test rawPrefixHeaderId support **/
|
/** test rawPrefixHeaderId support **/
|
||||||
describe('rawPrefixHeaderId support', function () {
|
describe('rawPrefixHeaderId support', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = rawPrefixHeaderIdSuite;
|
suite = rawPrefixHeaderIdSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
converter = new showdown.Converter({rawPrefixHeaderId: true, prefixHeaderId: '/prefix/'});
|
converter = new showdown.Converter({rawPrefixHeaderId: true, prefixHeaderId: '/prefix/'});
|
||||||
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test emojis support **/
|
/** test emojis support **/
|
||||||
describe('emojis support', function () {
|
describe('emojis support', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = emojisSuite,
|
suite = emojisSuite,
|
||||||
imgSrcRegexp = /<img[^>]+src=("https?:\/\/[^"]+"|'https?:\/\/[^']+')/g;
|
imgSrcRegexp = /<img[^>]+src=("https?:\/\/[^"]+"|'https?:\/\/[^']+')/g;
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ describe('makeHtml() features testsuite', function () {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
if (suite[i].name === 'simplifiedautolinks') {
|
if (suite[i].name === 'simplifiedautolinks') {
|
||||||
converter = new showdown.Converter({emoji: true, simplifiedAutoLink: true});
|
converter = new showdown.Converter({emoji: true, simplifiedAutoLink: true});
|
||||||
} else {
|
} else {
|
||||||
|
@ -231,7 +231,7 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
||||||
|
|
||||||
var imgUrl = imgSrcRegexp.exec(suite[i].expected);
|
let imgUrl = imgSrcRegexp.exec(suite[i].expected);
|
||||||
if (imgUrl) {
|
if (imgUrl) {
|
||||||
it('should use a working emoji URL', testImageUrlExists(imgUrl[1]));
|
it('should use a working emoji URL', testImageUrlExists(imgUrl[1]));
|
||||||
}
|
}
|
||||||
|
@ -240,9 +240,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test underline support **/
|
/** test underline support **/
|
||||||
describe('underline support', function () {
|
describe('underline support', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = underlineSuite;
|
suite = underlineSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
if (suite[i].name === 'simplifiedautolinks') {
|
if (suite[i].name === 'simplifiedautolinks') {
|
||||||
converter = new showdown.Converter({underline: true, simplifiedAutoLink: true});
|
converter = new showdown.Converter({underline: true, simplifiedAutoLink: true});
|
||||||
} else {
|
} else {
|
||||||
|
@ -254,9 +254,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test ellipsis option **/
|
/** test ellipsis option **/
|
||||||
describe('ellipsis option', function () {
|
describe('ellipsis option', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = ellipsisSuite;
|
suite = ellipsisSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
converter = new showdown.Converter({ellipsis: false});
|
converter = new showdown.Converter({ellipsis: false});
|
||||||
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
||||||
}
|
}
|
||||||
|
@ -264,9 +264,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test literalMidWordUnderscores option **/
|
/** test literalMidWordUnderscores option **/
|
||||||
describe('literalMidWordUnderscores option', function () {
|
describe('literalMidWordUnderscores option', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = literalMidWordUnderscoresSuite;
|
suite = literalMidWordUnderscoresSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
converter = new showdown.Converter({literalMidWordUnderscores: true});
|
converter = new showdown.Converter({literalMidWordUnderscores: true});
|
||||||
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
||||||
}
|
}
|
||||||
|
@ -275,9 +275,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
/** test literalMidWordAsterisks option **/
|
/** test literalMidWordAsterisks option **/
|
||||||
/*
|
/*
|
||||||
describe('literalMidWordAsterisks option', function () {
|
describe('literalMidWordAsterisks option', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = literalMidWordAsterisksSuite;
|
suite = literalMidWordAsterisksSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
converter = new showdown.Converter({literalMidWordAsterisks: true});
|
converter = new showdown.Converter({literalMidWordAsterisks: true});
|
||||||
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
||||||
}
|
}
|
||||||
|
@ -286,9 +286,9 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test completeHTMLDocument option **/
|
/** test completeHTMLDocument option **/
|
||||||
describe('completeHTMLDocument option', function () {
|
describe('completeHTMLDocument option', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = completeHTMLOutputSuite;
|
suite = completeHTMLOutputSuite;
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
converter = new showdown.Converter({completeHTMLDocument: true});
|
converter = new showdown.Converter({completeHTMLDocument: true});
|
||||||
|
|
||||||
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
||||||
|
@ -297,10 +297,10 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test metadata option **/
|
/** test metadata option **/
|
||||||
describe('metadata option', function () {
|
describe('metadata option', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = metadataSuite;
|
suite = metadataSuite;
|
||||||
|
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
if (suite[i].name === 'embeded-in-output' ||
|
if (suite[i].name === 'embeded-in-output' ||
|
||||||
suite[i].name === 'embeded-two-consecutive-metadata-blocks' ||
|
suite[i].name === 'embeded-two-consecutive-metadata-blocks' ||
|
||||||
suite[i].name === 'embeded-two-consecutive-metadata-blocks-different-symbols') {
|
suite[i].name === 'embeded-two-consecutive-metadata-blocks-different-symbols') {
|
||||||
|
@ -316,10 +316,10 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test metadata option **/
|
/** test metadata option **/
|
||||||
describe('splitAdjacentBlockquotes option', function () {
|
describe('splitAdjacentBlockquotes option', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = splitAdjacentBlockquotesSuite;
|
suite = splitAdjacentBlockquotesSuite;
|
||||||
|
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
converter = new showdown.Converter({splitAdjacentBlockquotes: true});
|
converter = new showdown.Converter({splitAdjacentBlockquotes: true});
|
||||||
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
||||||
}
|
}
|
||||||
|
@ -327,10 +327,10 @@ describe('makeHtml() features testsuite', function () {
|
||||||
|
|
||||||
/** test moreStyling option **/
|
/** test moreStyling option **/
|
||||||
describe('moreStyling option', function () {
|
describe('moreStyling option', function () {
|
||||||
var converter,
|
let converter,
|
||||||
suite = moreStyling;
|
suite = moreStyling;
|
||||||
|
|
||||||
for (var i = 0; i < suite.length; ++i) {
|
for (let i = 0; i < suite.length; ++i) {
|
||||||
converter = new showdown.Converter({moreStyling: true, tasklists: true});
|
converter = new showdown.Converter({moreStyling: true, tasklists: true});
|
||||||
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,12 @@
|
||||||
|
|
||||||
describe('showdown.Event', function () {
|
describe('showdown.Event', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
let eventList = {
|
//let eventList = {};
|
||||||
|
|
||||||
};
|
|
||||||
describe('event listeners', function () {
|
describe('event listeners', function () {
|
||||||
|
|
||||||
it('should listen to triggered event', function () {
|
it('should listen to triggered event', function () {
|
||||||
|
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user