mirror of
https://github.com/showdownjs/showdown.git
synced 2024-03-22 13:30:55 +08:00
Merge branch 'develop'
This commit is contained in:
commit
62270d4a4b
|
@ -17,7 +17,8 @@ environment:
|
|||
platform: x64
|
||||
- nodejs_version: "10"
|
||||
platform: x64
|
||||
|
||||
cache:
|
||||
- node_modules
|
||||
install:
|
||||
# Use version based on tag
|
||||
- ps: $env:package_version = (Get-Content -Raw -Path package.json | ConvertFrom-Json).version
|
||||
|
@ -26,7 +27,6 @@ install:
|
|||
# install node
|
||||
# Get the latest stable version of Node.js or io.js
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
|
||||
# install grunt-cli globally
|
||||
- npm install -g grunt-cli
|
||||
# install modules
|
||||
|
@ -35,6 +35,7 @@ install:
|
|||
test_script:
|
||||
# Output useful info for debugging
|
||||
- node --version && npm --version
|
||||
- ps: grunt test
|
||||
|
||||
# Don't actually build.
|
||||
build: off
|
||||
|
|
|
@ -7,7 +7,7 @@ node_js:
|
|||
before_install:
|
||||
- npm install -g grunt-cli
|
||||
|
||||
#travis build speed up
|
||||
# travis build speed up
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
|
|
|
@ -24,7 +24,7 @@ module.exports = function (grunt) {
|
|||
'src/showdown.js',
|
||||
'src/helpers.js',
|
||||
'src/subParsers/makehtml/*.js',
|
||||
'src/subParsers/makemd/*.js',
|
||||
'src/subParsers/makemarkdown/*.js',
|
||||
'src/converter.js',
|
||||
'src/loader.js'
|
||||
],
|
||||
|
|
1549
package-lock.json
generated
1549
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -40,7 +40,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"chai": "4.1.x",
|
||||
"grunt": "^1.0.1",
|
||||
"grunt": "^1.0.3",
|
||||
"grunt-contrib-clean": "1.1.x",
|
||||
"grunt-contrib-concat": "1.0.x",
|
||||
"grunt-contrib-jshint": "1.1.x",
|
||||
|
@ -55,11 +55,11 @@
|
|||
"quiet-grunt": "0.2.x",
|
||||
"semver": "5.4.x",
|
||||
"semver-sort": "0.0.x",
|
||||
"sinon": "5.0.x",
|
||||
"source-map-support": "0.5.x"
|
||||
"sinon": "^5.1.1",
|
||||
"source-map-support": "^0.5.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsdom": "^10.0.0",
|
||||
"yargs": "^11.0.0"
|
||||
"yargs": "^11.1.0"
|
||||
}
|
||||
}
|
||||
|
|
455
src/converter.js
455
src/converter.js
|
@ -362,7 +362,9 @@ showdown.Converter = function (converterOptions) {
|
|||
var doc = showdown.helper.document.createElement('div');
|
||||
doc.innerHTML = src;
|
||||
|
||||
var preList = substitutePreCodeTags(doc);
|
||||
var globals = {
|
||||
preList: substitutePreCodeTags(doc)
|
||||
};
|
||||
|
||||
// remove all newlines and collapse spaces
|
||||
clean(doc);
|
||||
|
@ -375,456 +377,7 @@ showdown.Converter = function (converterOptions) {
|
|||
mdDoc = '';
|
||||
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
mdDoc += parseNode(nodes[i]);
|
||||
}
|
||||
|
||||
|
||||
function parseNode (node, spansOnly) {
|
||||
|
||||
spansOnly = spansOnly || false;
|
||||
|
||||
var txt = '';
|
||||
|
||||
// edge case of text without wrapper paragraph
|
||||
if (node.nodeType === 3) {
|
||||
return parseTxt(node);
|
||||
}
|
||||
|
||||
// HTML comment
|
||||
if (node.nodeType === 8) {
|
||||
return '<!--' + node.data + '-->\n\n';
|
||||
}
|
||||
|
||||
// process only node elements
|
||||
if (node.nodeType !== 1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var tagName = node.tagName.toLowerCase();
|
||||
|
||||
switch (tagName) {
|
||||
|
||||
//
|
||||
// BLOCKS
|
||||
//
|
||||
case 'h1':
|
||||
if (!spansOnly) { txt = parseHeader(node, 1) + '\n\n'; }
|
||||
break;
|
||||
case 'h2':
|
||||
if (!spansOnly) { txt = parseHeader(node, 2) + '\n\n'; }
|
||||
break;
|
||||
case 'h3':
|
||||
if (!spansOnly) { txt = parseHeader(node, 3) + '\n\n'; }
|
||||
break;
|
||||
case 'h4':
|
||||
if (!spansOnly) { txt = parseHeader(node, 4) + '\n\n'; }
|
||||
break;
|
||||
case 'h5':
|
||||
if (!spansOnly) { txt = parseHeader(node, 5) + '\n\n'; }
|
||||
break;
|
||||
case 'h6':
|
||||
if (!spansOnly) { txt = parseHeader(node, 6) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (!spansOnly) { txt = parseParagraph(node) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'blockquote':
|
||||
if (!spansOnly) { txt = parseBlockquote(node) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'hr':
|
||||
if (!spansOnly) { txt = parseHr(node) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'ol':
|
||||
if (!spansOnly) { txt = parseList(node, 'ol') + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'ul':
|
||||
if (!spansOnly) { txt = parseList(node, 'ul') + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'precode':
|
||||
if (!spansOnly) { txt = parsePreCode(node) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'pre':
|
||||
if (!spansOnly) { txt = parsePre(node) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'table':
|
||||
if (!spansOnly) { txt = parseTable(node) + '\n\n'; }
|
||||
break;
|
||||
|
||||
//
|
||||
// SPANS
|
||||
//
|
||||
case 'code':
|
||||
txt = parseCodeSpan(node);
|
||||
break;
|
||||
|
||||
case 'em':
|
||||
case 'i':
|
||||
txt = parseEmphasis(node);
|
||||
break;
|
||||
|
||||
case 'strong':
|
||||
case 'b':
|
||||
txt = parseStrong(node);
|
||||
break;
|
||||
|
||||
case 'del':
|
||||
txt = parseDel(node);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
txt = parseLinks(node);
|
||||
break;
|
||||
|
||||
case 'img':
|
||||
txt = parseImage(node);
|
||||
break;
|
||||
|
||||
default:
|
||||
txt = node.outerHTML + '\n\n';
|
||||
}
|
||||
|
||||
// common normalization
|
||||
|
||||
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parseTxt (node) {
|
||||
var txt = node.nodeValue;
|
||||
|
||||
// multiple spaces are collapsed
|
||||
txt = txt.replace(/ +/g, ' ');
|
||||
|
||||
// replace the custom ¨NBSP; with a space
|
||||
txt = txt.replace(/¨NBSP;/g, ' ');
|
||||
|
||||
// ", <, > and & should replace escaped html entities
|
||||
txt = showdown.helper.unescapeHTMLEntities(txt);
|
||||
|
||||
// escape markdown magic characters
|
||||
// emphasis, strong and strikethrough - can appear everywhere
|
||||
// we also escape pipe (|) because of tables
|
||||
// and escape ` because of code blocks and spans
|
||||
txt = txt.replace(/([*_~|`])/g, '\\$1');
|
||||
|
||||
// escape > because of blockquotes
|
||||
txt = txt.replace(/^(\s*)>/g, '\\$1>');
|
||||
|
||||
// hash character, only troublesome at the beginning of a line because of headers
|
||||
txt = txt.replace(/^#/gm, '\\#');
|
||||
|
||||
// horizontal rules
|
||||
txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3');
|
||||
|
||||
// dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer
|
||||
txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.');
|
||||
|
||||
// +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped)
|
||||
txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2');
|
||||
|
||||
// images and links, ] followed by ( is problematic, so we escape it
|
||||
txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\(');
|
||||
|
||||
// reference URIs must also be escaped
|
||||
txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:');
|
||||
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parseList (node, type) {
|
||||
var txt = '';
|
||||
if (!node.hasChildNodes()) {
|
||||
return '';
|
||||
}
|
||||
var listItems = node.childNodes,
|
||||
listItemsLenght = listItems.length,
|
||||
listNum = node.getAttribute('start') || 1;
|
||||
|
||||
for (var i = 0; i < listItemsLenght; ++i) {
|
||||
if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// define the bullet to use in list
|
||||
var bullet = '';
|
||||
if (type === 'ol') {
|
||||
bullet = listNum.toString() + '. ';
|
||||
} else {
|
||||
bullet = '- ';
|
||||
}
|
||||
|
||||
// parse list item
|
||||
txt += bullet + parseListItem(listItems[i]);
|
||||
++listNum;
|
||||
}
|
||||
|
||||
return txt.trim();
|
||||
}
|
||||
|
||||
function parseListItem (node) {
|
||||
var listItemTxt = '';
|
||||
|
||||
var children = node.childNodes,
|
||||
childrenLenght = children.length;
|
||||
|
||||
for (var i = 0; i < childrenLenght; ++i) {
|
||||
listItemTxt += parseNode(children[i]);
|
||||
}
|
||||
// if it's only one liner, we need to add a newline at the end
|
||||
if (!/\n$/.test(listItemTxt)) {
|
||||
listItemTxt += '\n';
|
||||
} else {
|
||||
// it's multiparagraph, so we need to indent
|
||||
listItemTxt = listItemTxt
|
||||
.split('\n')
|
||||
.join('\n ')
|
||||
.replace(/^ {4}$/gm, '')
|
||||
.replace(/\n\n+/g, '\n\n');
|
||||
}
|
||||
|
||||
return listItemTxt;
|
||||
}
|
||||
|
||||
function parseHr () {
|
||||
return '---';
|
||||
}
|
||||
|
||||
function parseBlockquote (node) {
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
var innerTxt = parseNode(children[i]);
|
||||
|
||||
if (innerTxt === '') {
|
||||
continue;
|
||||
}
|
||||
txt += innerTxt;
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
txt = txt.trim();
|
||||
txt = '> ' + txt.split('\n').join('\n> ');
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parseCodeSpan (node) {
|
||||
return '`' + node.innerHTML + '`';
|
||||
}
|
||||
|
||||
function parseStrong (node) {
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
txt += '**';
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += parseNode(children[i]);
|
||||
}
|
||||
txt += '**';
|
||||
}
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parseEmphasis (node) {
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
txt += '*';
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += parseNode(children[i]);
|
||||
}
|
||||
txt += '*';
|
||||
}
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parseDel (node) {
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
txt += '~~';
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += parseNode(children[i]);
|
||||
}
|
||||
txt += '~~';
|
||||
}
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parseLinks (node) {
|
||||
var txt = '';
|
||||
if (node.hasChildNodes() && node.hasAttribute('href')) {
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
txt = '[';
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += parseNode(children[i]);
|
||||
}
|
||||
txt += '](';
|
||||
txt += '<' + node.getAttribute('href') + '>';
|
||||
if (node.hasAttribute('title')) {
|
||||
txt += ' "' + node.getAttribute('title') + '"';
|
||||
}
|
||||
txt += ')';
|
||||
}
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parseImage (node) {
|
||||
var txt = '';
|
||||
if (node.hasAttribute('src')) {
|
||||
txt += '![' + node.getAttribute('alt') + '](';
|
||||
txt += '<' + node.getAttribute('src') + '>';
|
||||
if (node.hasAttribute('width') && node.hasAttribute('height')) {
|
||||
txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height');
|
||||
}
|
||||
|
||||
if (node.hasAttribute('title')) {
|
||||
txt += ' "' + node.getAttribute('title') + '"';
|
||||
}
|
||||
txt += ')';
|
||||
}
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parseHeader (node, headerLevel) {
|
||||
var headerMark = new Array(headerLevel + 1).join('#'),
|
||||
txt = '';
|
||||
|
||||
if (node.hasChildNodes()) {
|
||||
txt = headerMark + ' ';
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += parseNode(children[i]);
|
||||
}
|
||||
}
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parseParagraph (node) {
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += parseNode(children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// some text normalization
|
||||
txt = txt.trim();
|
||||
|
||||
return txt;
|
||||
}
|
||||
|
||||
function parsePreCode (node) {
|
||||
var lang = node.getAttribute('language'),
|
||||
num = node.getAttribute('precodenum');
|
||||
return '```' + lang + '\n' + preList[num] + '\n```';
|
||||
}
|
||||
|
||||
function parsePre (node) {
|
||||
var num = node.getAttribute('prenum');
|
||||
return '<pre>' + preList[num] + '</pre>';
|
||||
}
|
||||
|
||||
function parseTable (node) {
|
||||
|
||||
var txt = '',
|
||||
tableArray = [[], []],
|
||||
headings = node.querySelectorAll('thead>tr>th'),
|
||||
rows = node.querySelectorAll('tbody>tr'),
|
||||
i, ii;
|
||||
for (i = 0; i < headings.length; ++i) {
|
||||
var headContent = parseTableCell(headings[i]),
|
||||
allign = '---';
|
||||
|
||||
if (headings[i].hasAttribute('style')) {
|
||||
var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, '');
|
||||
switch (style) {
|
||||
case 'text-align:left;':
|
||||
allign = ':---';
|
||||
break;
|
||||
case 'text-align:right;':
|
||||
allign = '---:';
|
||||
break;
|
||||
case 'text-align:center;':
|
||||
allign = ':---:';
|
||||
break;
|
||||
}
|
||||
}
|
||||
tableArray[0][i] = headContent.trim();
|
||||
tableArray[1][i] = allign;
|
||||
}
|
||||
|
||||
for (i = 0; i < rows.length; ++i) {
|
||||
var r = tableArray.push([]) - 1,
|
||||
cols = rows[i].getElementsByTagName('td');
|
||||
|
||||
for (ii = 0; ii < headings.length; ++ii) {
|
||||
var cellContent = ' ';
|
||||
if (typeof cols[ii] !== 'undefined') {
|
||||
cellContent = parseTableCell(cols[ii]);
|
||||
}
|
||||
tableArray[r].push(cellContent);
|
||||
}
|
||||
}
|
||||
|
||||
var cellSpacesCount = 3;
|
||||
for (i = 0; i < tableArray.length; ++i) {
|
||||
for (ii = 0; ii < tableArray[i].length; ++ii) {
|
||||
var strLen = tableArray[i][ii].length;
|
||||
if (strLen > cellSpacesCount) {
|
||||
cellSpacesCount = strLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < tableArray.length; ++i) {
|
||||
for (ii = 0; ii < tableArray[i].length; ++ii) {
|
||||
if (i === 1) {
|
||||
if (tableArray[i][ii].slice(-1) === ':') {
|
||||
tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':';
|
||||
} else {
|
||||
tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-');
|
||||
}
|
||||
} else {
|
||||
tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount);
|
||||
}
|
||||
}
|
||||
txt += '| ' + tableArray[i].join(' | ') + ' |\n';
|
||||
}
|
||||
|
||||
return txt.trim();
|
||||
}
|
||||
|
||||
function parseTableCell (node) {
|
||||
var txt = '';
|
||||
if (!node.hasChildNodes()) {
|
||||
return '';
|
||||
}
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += parseNode(children[i], true);
|
||||
}
|
||||
return txt.trim();
|
||||
mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals);
|
||||
}
|
||||
|
||||
function clean (node) {
|
||||
|
|
|
@ -180,6 +180,8 @@ showdown.subParser = function (name, func) {
|
|||
throw Error('SubParser named ' + name + ' not registered!');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw Error('showdown.subParser function first argument must be a string (the name of the subparser)');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
20
src/subParsers/makemarkdown/anchors.js
Normal file
20
src/subParsers/makemarkdown/anchors.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
showdown.subParser('makeMarkdown.anchors', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var txt = '';
|
||||
if (node.hasChildNodes() && node.hasAttribute('href')) {
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
txt = '[';
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
|
||||
}
|
||||
txt += '](';
|
||||
txt += '<' + node.getAttribute('href') + '>';
|
||||
if (node.hasAttribute('title')) {
|
||||
txt += ' "' + node.getAttribute('title') + '"';
|
||||
}
|
||||
txt += ')';
|
||||
}
|
||||
return txt;
|
||||
});
|
22
src/subParsers/makemarkdown/blockquote.js
Normal file
22
src/subParsers/makemarkdown/blockquote.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
showdown.subParser('makeMarkdown.blockquote', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals);
|
||||
|
||||
if (innerTxt === '') {
|
||||
continue;
|
||||
}
|
||||
txt += innerTxt;
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
txt = txt.trim();
|
||||
txt = '> ' + txt.split('\n').join('\n> ');
|
||||
return txt;
|
||||
});
|
7
src/subParsers/makemarkdown/codeBlock.js
Normal file
7
src/subParsers/makemarkdown/codeBlock.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
showdown.subParser('makeMarkdown.codeBlock', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var lang = node.getAttribute('language'),
|
||||
num = node.getAttribute('precodenum');
|
||||
return '```' + lang + '\n' + globals.preList[num] + '\n```';
|
||||
});
|
5
src/subParsers/makemarkdown/codeSpan.js
Normal file
5
src/subParsers/makemarkdown/codeSpan.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
showdown.subParser('makeMarkdown.codeSpan', function (node) {
|
||||
'use strict';
|
||||
|
||||
return '`' + node.innerHTML + '`';
|
||||
});
|
15
src/subParsers/makemarkdown/emphasis.js
Normal file
15
src/subParsers/makemarkdown/emphasis.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
showdown.subParser('makeMarkdown.emphasis', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
txt += '*';
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
|
||||
}
|
||||
txt += '*';
|
||||
}
|
||||
return txt;
|
||||
});
|
17
src/subParsers/makemarkdown/header.js
Normal file
17
src/subParsers/makemarkdown/header.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) {
|
||||
'use strict';
|
||||
|
||||
var headerMark = new Array(headerLevel + 1).join('#'),
|
||||
txt = '';
|
||||
|
||||
if (node.hasChildNodes()) {
|
||||
txt = headerMark + ' ';
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
|
||||
}
|
||||
}
|
||||
return txt;
|
||||
});
|
5
src/subParsers/makemarkdown/hr.js
Normal file
5
src/subParsers/makemarkdown/hr.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
showdown.subParser('makeMarkdown.hr', function () {
|
||||
'use strict';
|
||||
|
||||
return '---';
|
||||
});
|
18
src/subParsers/makemarkdown/image.js
Normal file
18
src/subParsers/makemarkdown/image.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
showdown.subParser('makeMarkdown.image', function (node) {
|
||||
'use strict';
|
||||
|
||||
var txt = '';
|
||||
if (node.hasAttribute('src')) {
|
||||
txt += '![' + node.getAttribute('alt') + '](';
|
||||
txt += '<' + node.getAttribute('src') + '>';
|
||||
if (node.hasAttribute('width') && node.hasAttribute('height')) {
|
||||
txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height');
|
||||
}
|
||||
|
||||
if (node.hasAttribute('title')) {
|
||||
txt += ' "' + node.getAttribute('title') + '"';
|
||||
}
|
||||
txt += ')';
|
||||
}
|
||||
return txt;
|
||||
});
|
31
src/subParsers/makemarkdown/list.js
Normal file
31
src/subParsers/makemarkdown/list.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
showdown.subParser('makeMarkdown.list', function (node, globals, type) {
|
||||
'use strict';
|
||||
|
||||
var txt = '';
|
||||
if (!node.hasChildNodes()) {
|
||||
return '';
|
||||
}
|
||||
var listItems = node.childNodes,
|
||||
listItemsLenght = listItems.length,
|
||||
listNum = node.getAttribute('start') || 1;
|
||||
|
||||
for (var i = 0; i < listItemsLenght; ++i) {
|
||||
if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// define the bullet to use in list
|
||||
var bullet = '';
|
||||
if (type === 'ol') {
|
||||
bullet = listNum.toString() + '. ';
|
||||
} else {
|
||||
bullet = '- ';
|
||||
}
|
||||
|
||||
// parse list item
|
||||
txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals);
|
||||
++listNum;
|
||||
}
|
||||
|
||||
return txt.trim();
|
||||
});
|
25
src/subParsers/makemarkdown/listItem.js
Normal file
25
src/subParsers/makemarkdown/listItem.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
showdown.subParser('makeMarkdown.listItem', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var listItemTxt = '';
|
||||
|
||||
var children = node.childNodes,
|
||||
childrenLenght = children.length;
|
||||
|
||||
for (var i = 0; i < childrenLenght; ++i) {
|
||||
listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals);
|
||||
}
|
||||
// if it's only one liner, we need to add a newline at the end
|
||||
if (!/\n$/.test(listItemTxt)) {
|
||||
listItemTxt += '\n';
|
||||
} else {
|
||||
// it's multiparagraph, so we need to indent
|
||||
listItemTxt = listItemTxt
|
||||
.split('\n')
|
||||
.join('\n ')
|
||||
.replace(/^ {4}$/gm, '')
|
||||
.replace(/\n\n+/g, '\n\n');
|
||||
}
|
||||
|
||||
return listItemTxt;
|
||||
});
|
120
src/subParsers/makemarkdown/node.js
Normal file
120
src/subParsers/makemarkdown/node.js
Normal file
|
@ -0,0 +1,120 @@
|
|||
|
||||
|
||||
showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) {
|
||||
'use strict';
|
||||
|
||||
spansOnly = spansOnly || false;
|
||||
|
||||
var txt = '';
|
||||
|
||||
// edge case of text without wrapper paragraph
|
||||
if (node.nodeType === 3) {
|
||||
return showdown.subParser('makeMarkdown.txt')(node, globals);
|
||||
}
|
||||
|
||||
// HTML comment
|
||||
if (node.nodeType === 8) {
|
||||
return '<!--' + node.data + '-->\n\n';
|
||||
}
|
||||
|
||||
// process only node elements
|
||||
if (node.nodeType !== 1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var tagName = node.tagName.toLowerCase();
|
||||
|
||||
switch (tagName) {
|
||||
|
||||
//
|
||||
// BLOCKS
|
||||
//
|
||||
case 'h1':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; }
|
||||
break;
|
||||
case 'h2':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; }
|
||||
break;
|
||||
case 'h3':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; }
|
||||
break;
|
||||
case 'h4':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; }
|
||||
break;
|
||||
case 'h5':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; }
|
||||
break;
|
||||
case 'h6':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'blockquote':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'hr':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'ol':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'ul':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'precode':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'pre':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; }
|
||||
break;
|
||||
|
||||
case 'table':
|
||||
if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; }
|
||||
break;
|
||||
|
||||
//
|
||||
// SPANS
|
||||
//
|
||||
case 'code':
|
||||
txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals);
|
||||
break;
|
||||
|
||||
case 'em':
|
||||
case 'i':
|
||||
txt = showdown.subParser('makeMarkdown.emphasis')(node, globals);
|
||||
break;
|
||||
|
||||
case 'strong':
|
||||
case 'b':
|
||||
txt = showdown.subParser('makeMarkdown.strong')(node, globals);
|
||||
break;
|
||||
|
||||
case 'del':
|
||||
txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
txt = showdown.subParser('makeMarkdown.anchors')(node, globals);
|
||||
break;
|
||||
|
||||
case 'img':
|
||||
txt = showdown.subParser('makeMarkdown.image')(node, globals);
|
||||
break;
|
||||
|
||||
default:
|
||||
txt = node.outerHTML + '\n\n';
|
||||
}
|
||||
|
||||
// common normalization
|
||||
// TODO eventually
|
||||
|
||||
return txt;
|
||||
});
|
17
src/subParsers/makemarkdown/paragraph.js
Normal file
17
src/subParsers/makemarkdown/paragraph.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
showdown.subParser('makeMarkdown.paragraph', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
|
||||
}
|
||||
}
|
||||
|
||||
// some text normalization
|
||||
txt = txt.trim();
|
||||
|
||||
return txt;
|
||||
});
|
6
src/subParsers/makemarkdown/pre.js
Normal file
6
src/subParsers/makemarkdown/pre.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
showdown.subParser('makeMarkdown.pre', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var num = node.getAttribute('prenum');
|
||||
return '<pre>' + globals.preList[num] + '</pre>';
|
||||
});
|
15
src/subParsers/makemarkdown/strikethrough.js
Normal file
15
src/subParsers/makemarkdown/strikethrough.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
showdown.subParser('makeMarkdown.strikethrough', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
txt += '~~';
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
|
||||
}
|
||||
txt += '~~';
|
||||
}
|
||||
return txt;
|
||||
});
|
15
src/subParsers/makemarkdown/strong.js
Normal file
15
src/subParsers/makemarkdown/strong.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
showdown.subParser('makeMarkdown.strong', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var txt = '';
|
||||
if (node.hasChildNodes()) {
|
||||
txt += '**';
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
|
||||
}
|
||||
txt += '**';
|
||||
}
|
||||
return txt;
|
||||
});
|
70
src/subParsers/makemarkdown/table.js
Normal file
70
src/subParsers/makemarkdown/table.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
showdown.subParser('makeMarkdown.table', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var txt = '',
|
||||
tableArray = [[], []],
|
||||
headings = node.querySelectorAll('thead>tr>th'),
|
||||
rows = node.querySelectorAll('tbody>tr'),
|
||||
i, ii;
|
||||
for (i = 0; i < headings.length; ++i) {
|
||||
var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals),
|
||||
allign = '---';
|
||||
|
||||
if (headings[i].hasAttribute('style')) {
|
||||
var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, '');
|
||||
switch (style) {
|
||||
case 'text-align:left;':
|
||||
allign = ':---';
|
||||
break;
|
||||
case 'text-align:right;':
|
||||
allign = '---:';
|
||||
break;
|
||||
case 'text-align:center;':
|
||||
allign = ':---:';
|
||||
break;
|
||||
}
|
||||
}
|
||||
tableArray[0][i] = headContent.trim();
|
||||
tableArray[1][i] = allign;
|
||||
}
|
||||
|
||||
for (i = 0; i < rows.length; ++i) {
|
||||
var r = tableArray.push([]) - 1,
|
||||
cols = rows[i].getElementsByTagName('td');
|
||||
|
||||
for (ii = 0; ii < headings.length; ++ii) {
|
||||
var cellContent = ' ';
|
||||
if (typeof cols[ii] !== 'undefined') {
|
||||
cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals);
|
||||
}
|
||||
tableArray[r].push(cellContent);
|
||||
}
|
||||
}
|
||||
|
||||
var cellSpacesCount = 3;
|
||||
for (i = 0; i < tableArray.length; ++i) {
|
||||
for (ii = 0; ii < tableArray[i].length; ++ii) {
|
||||
var strLen = tableArray[i][ii].length;
|
||||
if (strLen > cellSpacesCount) {
|
||||
cellSpacesCount = strLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < tableArray.length; ++i) {
|
||||
for (ii = 0; ii < tableArray[i].length; ++ii) {
|
||||
if (i === 1) {
|
||||
if (tableArray[i][ii].slice(-1) === ':') {
|
||||
tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':';
|
||||
} else {
|
||||
tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-');
|
||||
}
|
||||
} else {
|
||||
tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount);
|
||||
}
|
||||
}
|
||||
txt += '| ' + tableArray[i].join(' | ') + ' |\n';
|
||||
}
|
||||
|
||||
return txt.trim();
|
||||
});
|
15
src/subParsers/makemarkdown/tableCell.js
Normal file
15
src/subParsers/makemarkdown/tableCell.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
showdown.subParser('makeMarkdown.tableCell', function (node, globals) {
|
||||
'use strict';
|
||||
|
||||
var txt = '';
|
||||
if (!node.hasChildNodes()) {
|
||||
return '';
|
||||
}
|
||||
var children = node.childNodes,
|
||||
childrenLength = children.length;
|
||||
|
||||
for (var i = 0; i < childrenLength; ++i) {
|
||||
txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true);
|
||||
}
|
||||
return txt.trim();
|
||||
});
|
43
src/subParsers/makemarkdown/txt.js
Normal file
43
src/subParsers/makemarkdown/txt.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
showdown.subParser('makeMarkdown.txt', function (node) {
|
||||
'use strict';
|
||||
|
||||
var txt = node.nodeValue;
|
||||
|
||||
// multiple spaces are collapsed
|
||||
txt = txt.replace(/ +/g, ' ');
|
||||
|
||||
// replace the custom ¨NBSP; with a space
|
||||
txt = txt.replace(/¨NBSP;/g, ' ');
|
||||
|
||||
// ", <, > and & should replace escaped html entities
|
||||
txt = showdown.helper.unescapeHTMLEntities(txt);
|
||||
|
||||
// escape markdown magic characters
|
||||
// emphasis, strong and strikethrough - can appear everywhere
|
||||
// we also escape pipe (|) because of tables
|
||||
// and escape ` because of code blocks and spans
|
||||
txt = txt.replace(/([*_~|`])/g, '\\$1');
|
||||
|
||||
// escape > because of blockquotes
|
||||
txt = txt.replace(/^(\s*)>/g, '\\$1>');
|
||||
|
||||
// hash character, only troublesome at the beginning of a line because of headers
|
||||
txt = txt.replace(/^#/gm, '\\#');
|
||||
|
||||
// horizontal rules
|
||||
txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3');
|
||||
|
||||
// dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer
|
||||
txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.');
|
||||
|
||||
// +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped)
|
||||
txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2');
|
||||
|
||||
// images and links, ] followed by ( is problematic, so we escape it
|
||||
txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\(');
|
||||
|
||||
// reference URIs must also be escaped
|
||||
txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:');
|
||||
|
||||
return txt;
|
||||
});
|
Loading…
Reference in New Issue
Block a user