diff --git a/lib/renderer.js b/lib/renderer.js index 483d72df..c4b66c89 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -108,11 +108,11 @@ rules.ordered_list_close = function (tokens, idx /*, options*/) { }; -rules.paragraph_open = function (/*tokens, idx, options*/) { - return '

'; +rules.paragraph_open = function (tokens, idx/*, options*/) { + return tokens[idx].tight ? '' : '

'; }; rules.paragraph_close = function (tokens, idx /*, options*/) { - return '

' + getBreak(tokens, idx); + return (tokens[idx].tight ? '' : '

') + getBreak(tokens, idx); }; @@ -240,52 +240,15 @@ Renderer.prototype.renderInline = function (tokens, options) { Renderer.prototype.render = function (tokens, options) { - var i, len, name, + var i, len, result = '', - rules = this.rules, - tightStack = []; - - // wrap paragraphs on top level by default - var tight = false; + rules = this.rules; for (i = 0, len = tokens.length; i < len; i++) { - name = tokens[i].type; - - // Dirty stack machine to track lists style (loose/tight) - if (name === 'ordered_list_open' || name === 'bullet_list_open') { - tightStack.push(tight); - tight = tokens[i].tight; - } - if (name === 'ordered_list_close' || name === 'bullet_list_close') { - tight = tightStack.pop(); - } - if (name === 'blockquote_open') { - tightStack.push(tight); - tight = false; - } - if (name === 'blockquote_close') { - tight = tightStack.pop(); - } - - - // in tight mode just ignore paragraphs for lists - // TODO - track right nesting to blockquotes - if (name === 'paragraph_open' && tight) { - continue; - } - if (name === 'paragraph_close' && tight) { - // Quick hack - texts should have LF if followed by blocks - if (tokens[i + 1].type !== 'list_item_close') { - result += '\n'; - } - - continue; - } - if (tokens[i].type === 'inline') { result += this.renderInline(tokens[i].children, options); } else { - result += rules[name](tokens, i, options); + result += rules[tokens[i].type](tokens, i, options); } } diff --git a/lib/rules_block/list.js b/lib/rules_block/list.js index 3403128d..21018683 100644 --- a/lib/rules_block/list.js +++ b/lib/rules_block/list.js @@ -88,7 +88,9 @@ module.exports = function list(state, startLine, endLine, silent) { prevEmptyEnd, listLines, itemLines, - terminatorRules = state.parser._rulesListTerm, i, l, terminate; + tight = true, + terminatorRules = state.parser._rulesListTerm, + i, l, terminate, level, tokens; // Detect list type and position after marker if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) { @@ -117,7 +119,6 @@ module.exports = function list(state, startLine, endLine, silent) { state.tokens.push({ type: 'ordered_list_open', order: markerValue, - tight: true, lines: listLines = [ startLine, 0 ], level: state.level++ }); @@ -125,7 +126,6 @@ module.exports = function list(state, startLine, endLine, silent) { } else { state.tokens.push({ type: 'bullet_list_open', - tight: true, lines: listLines = [ startLine, 0 ], level: state.level++ }); @@ -183,7 +183,7 @@ module.exports = function list(state, startLine, endLine, silent) { // If any of list item is tight, mark list as tight if (!state.tight || prevEmptyEnd) { - state.tokens[listTokIdx].tight = false; + tight = false; } // Item become loose if finish with empty line, // but we should filter last element, because it means list finish @@ -194,7 +194,10 @@ module.exports = function list(state, startLine, endLine, silent) { state.tight = oldTight; state.parentType = oldParentType; - state.tokens.push({ type: 'list_item_close', level: --state.level }); + state.tokens.push({ + type: 'list_item_close', + level: --state.level + }); nextLine = startLine = state.line; itemLines[1] = nextLine; @@ -234,13 +237,27 @@ module.exports = function list(state, startLine, endLine, silent) { } // Finilize list - if (isOrdered) { - state.tokens.push({ type: 'ordered_list_close', level: --state.level }); - } else { - state.tokens.push({ type: 'bullet_list_close', level: --state.level }); - } + state.tokens.push({ + type: isOrdered ? 'ordered_list_close' : 'bullet_list_close', + level: --state.level + }); listLines[1] = nextLine; state.line = nextLine; + + // mark paragraphs tight if needed + if (tight) { + level = state.level + 2; + tokens = state.tokens; + + for (i = listTokIdx + 2, l = tokens.length - 2; i < l; i++) { + if (tokens[i].level === level && tokens[i].type === 'paragraph_open') { + tokens[i].tight = true; + i += 2; + tokens[i].tight = true; + } + } + } + return true; }; diff --git a/lib/rules_block/paragraph.js b/lib/rules_block/paragraph.js index ce502af8..76afd7c3 100644 --- a/lib/rules_block/paragraph.js +++ b/lib/rules_block/paragraph.js @@ -42,6 +42,7 @@ module.exports = function paragraph(state, startLine/*, endLine*/) { if (content.length) { state.tokens.push({ type: 'paragraph_open', + tight: false, lines: [ startLine, state.line ], level: state.level }); @@ -54,6 +55,7 @@ module.exports = function paragraph(state, startLine/*, endLine*/) { }); state.tokens.push({ type: 'paragraph_close', + tight: false, level: state.level }); }