fix(subParsers/lists.js): partial fix for odd behavior on multiple consecutive lists

Consecutive lists we're previously being condensed into one unique list, with odd paragraph output.
This fix correctly splits lists, but does not change the weird paragraph output

closes #142
This commit is contained in:
Estevao Soares dos Santos 2015-06-13 14:59:14 +01:00
parent 00db9d1c09
commit 0bdd02b2cc
6 changed files with 79 additions and 28 deletions

BIN
dist/showdown.js vendored

Binary file not shown.

BIN
dist/showdown.js.map vendored

Binary file not shown.

BIN
dist/showdown.min.js vendored

Binary file not shown.

Binary file not shown.

View File

@ -4,13 +4,15 @@
showdown.subParser('lists', function (text, options, globals) { showdown.subParser('lists', function (text, options, globals) {
'use strict'; 'use strict';
var spl = '~1';
/** /**
* Process the contents of a single ordered or unordered list, splitting it * Process the contents of a single ordered or unordered list, splitting it
* into individual list items. * into individual list items.
* @param {string} listStr * @param {string} listStr
* @returns {string|*} * @returns {string}
*/ */
var processListItems = function (listStr) { function processListItems (listStr) {
// The $g_list_level global keeps track of when we're inside a list. // The $g_list_level global keeps track of when we're inside a list.
// Each time we enter a list, we increment it; when we leave a list, // Each time we enter a list, we increment it; when we leave a list,
// we decrement. If it's zero, we're not in a list anymore. // we decrement. If it's zero, we're not in a list anymore.
@ -50,8 +52,9 @@ showdown.subParser('lists', function (text, options, globals) {
(?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+)) (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
/gm, function(){...}); /gm, function(){...});
*/ */
listStr = listStr.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm, var rgx = /(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm;
function (wholeMatch, m1, m2, m3, m4) {
listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4) {
var item = showdown.subParser('outdent')(m4, options, globals); var item = showdown.subParser('outdent')(m4, options, globals);
//m1 - LeadingLine //m1 - LeadingLine
@ -64,7 +67,10 @@ showdown.subParser('lists', function (text, options, globals) {
item = showdown.subParser('spanGamut')(item, options, globals); item = showdown.subParser('spanGamut')(item, options, globals);
} }
return '<li>' + item + '</li>\n'; // this is a "hack" to differentiate between ordered and unordered lists
// related to issue #142
var tp = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
return spl + tp + '<li>' + item + '</li>\n';
}); });
// attacklab: strip sentinel // attacklab: strip sentinel
@ -72,13 +78,53 @@ showdown.subParser('lists', function (text, options, globals) {
globals.gListLevel--; globals.gListLevel--;
return listStr; return listStr;
}; }
/**
* Slit consecutive ol/ul lists (related to issue 142)
* @param {Array} results
* @param {string} listType
* @returns {string|*}
*/
function splitConsecutiveLists (results, listType) {
var cthulhu = /(<p[^>]+?>|<p>|<\/p>)/img,
holder = [[]],
res = '',
y = 0;
// Initialize first sublist
holder[0].type = listType;
for (var i = 0; i < results.length; ++i) {
var txt = results[i].slice(2),
nListType = results[i].slice(0, 2);
if (listType != nListType) {
y++;
holder[y] = [];
holder[y].type = nListType;
listType = nListType;
}
holder[y].push(txt);
}
for (i = 0; i < holder.length; ++i) {
res += '<' + holder[i].type + '>\n';
for (var ii = 0; ii < holder[i].length; ++ii) {
if (holder[i].length > 1 && ii === holder[i].length - 1 && !cthulhu.test(holder[i][ii - 1])) {
//holder[i][ii] = holder[i][ii].replace(cthulhu, '');
}
res += holder[i][ii];
}
res += '</' + holder[i].type + '>\n';
}
return res;
}
// attacklab: add sentinel to hack around khtml/safari bug: // attacklab: add sentinel to hack around khtml/safari bug:
// http://bugs.webkit.org/show_bug.cgi?id=11231 // http://bugs.webkit.org/show_bug.cgi?id=11231
text += '~0'; text += '~0';
// Re-usable pattern to match any entirel ul or ol list: // Re-usable pattern to match any entire ul or ol list:
/* /*
var whole_list = / var whole_list = /
@ -105,35 +151,40 @@ showdown.subParser('lists', function (text, options, globals) {
if (globals.gListLevel) { if (globals.gListLevel) {
text = text.replace(wholeList, function (wholeMatch, m1, m2) { text = text.replace(wholeList, function (wholeMatch, m1, m2) {
var list = m1, var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol',
listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; result = processListItems(m1);
// Turn double returns into triple returns, so that we can make a // Turn double returns into triple returns, so that we can make a
// paragraph for the last item in a list, if necessary: // paragraph for the last item in a list, if necessary:
list = list.replace(/\n{2,}/g, '\n\n\n'); //list = list.replace(/\n{2,}/g, '\n\n\n');
//result = processListItems(list);
var result = processListItems(list);
// Trim any trailing whitespace, to put the closing `</$list_type>` // Trim any trailing whitespace, to put the closing `</$list_type>`
// up on the preceding line, to get it past the current stupid // up on the preceding line, to get it past the current stupid
// HTML block parser. This is a hack to work around the terrible // HTML block parser. This is a hack to work around the terrible
// hack that is the HTML block parser. // hack that is the HTML block parser.
result = result.replace(/\s+$/, ''); result = result.replace(/\s+$/, '');
result = '<' + listType + '>' + result + '</' + listType + '>\n'; var splRes = result.split(spl);
splRes.shift();
result = splitConsecutiveLists(splRes, listType);
return result; return result;
}); });
} else { } else {
wholeList = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g; wholeList = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
//wholeList = /(\n\n|^\n?)( {0,3}([*+-]|\d+\.)[ \t]+[\s\S]+?)(?=(~0)|(\n\n(?!\t| {2,}| {0,3}([*+-]|\d+\.)[ \t])))/g;
text = text.replace(wholeList, function (wholeMatch, m1, m2, m3) { text = text.replace(wholeList, function (wholeMatch, m1, m2, m3) {
// Turn double returns into triple returns, so that we can make a // Turn double returns into triple returns, so that we can make a
// paragraph for the last item in a list, if necessary: // paragraph for the last item in a list, if necessary:
var list = m2.replace(/\n{2,}/g, '\n\n\n'), var list = m2.replace(/\n{2,}/g, '\n\n\n'),
//var list = (m2.slice(-2) !== '~0') ? m2 + '\n' : m2, //add a newline after the list
listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol', listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol',
result = processListItems(list); result = processListItems(list),
splRes = result.split(spl);
return m1 + '<' + listType + '>\n' + result + '</' + listType + '>\n'; splRes.shift();
return m1 + splitConsecutiveLists(splRes, listType) + '\n';
}); });
} }

View File

@ -1,8 +1,8 @@
<ul> <ul>
<li>Item 1</li> <li>Item 1</li>
<li>Item 2</li> <li><p>Item 2</p></li>
</ul> </ul>
<ol> <ol>
<li>Item 1</li> <li><p>Item 1</p></li>
<li>Item 2</li> <li>Item 2</li>
</ol> </ol>