Browse Source

Simplified loose/tight logic. Closes #50

pull/14/head
Vitaly Puzrin 10 years ago
parent
commit
d5c588b130
  1. 49
      lib/renderer.js
  2. 37
      lib/rules_block/list.js
  3. 2
      lib/rules_block/paragraph.js

49
lib/renderer.js

@ -108,11 +108,11 @@ rules.ordered_list_close = function (tokens, idx /*, options*/) {
}; };
rules.paragraph_open = function (/*tokens, idx, options*/) { rules.paragraph_open = function (tokens, idx/*, options*/) {
return '<p>'; return tokens[idx].tight ? '' : '<p>';
}; };
rules.paragraph_close = function (tokens, idx /*, options*/) { rules.paragraph_close = function (tokens, idx /*, options*/) {
return '</p>' + getBreak(tokens, idx); return (tokens[idx].tight ? '' : '</p>') + getBreak(tokens, idx);
}; };
@ -240,52 +240,15 @@ Renderer.prototype.renderInline = function (tokens, options) {
Renderer.prototype.render = function (tokens, options) { Renderer.prototype.render = function (tokens, options) {
var i, len, name, var i, len,
result = '', result = '',
rules = this.rules, rules = this.rules;
tightStack = [];
// wrap paragraphs on top level by default
var tight = false;
for (i = 0, len = tokens.length; i < len; i++) { 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') { if (tokens[i].type === 'inline') {
result += this.renderInline(tokens[i].children, options); result += this.renderInline(tokens[i].children, options);
} else { } else {
result += rules[name](tokens, i, options); result += rules[tokens[i].type](tokens, i, options);
} }
} }

37
lib/rules_block/list.js

@ -88,7 +88,9 @@ module.exports = function list(state, startLine, endLine, silent) {
prevEmptyEnd, prevEmptyEnd,
listLines, listLines,
itemLines, 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 // Detect list type and position after marker
if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) { if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {
@ -117,7 +119,6 @@ module.exports = function list(state, startLine, endLine, silent) {
state.tokens.push({ state.tokens.push({
type: 'ordered_list_open', type: 'ordered_list_open',
order: markerValue, order: markerValue,
tight: true,
lines: listLines = [ startLine, 0 ], lines: listLines = [ startLine, 0 ],
level: state.level++ level: state.level++
}); });
@ -125,7 +126,6 @@ module.exports = function list(state, startLine, endLine, silent) {
} else { } else {
state.tokens.push({ state.tokens.push({
type: 'bullet_list_open', type: 'bullet_list_open',
tight: true,
lines: listLines = [ startLine, 0 ], lines: listLines = [ startLine, 0 ],
level: state.level++ 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 any of list item is tight, mark list as tight
if (!state.tight || prevEmptyEnd) { if (!state.tight || prevEmptyEnd) {
state.tokens[listTokIdx].tight = false; tight = false;
} }
// Item become loose if finish with empty line, // Item become loose if finish with empty line,
// but we should filter last element, because it means list finish // 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.tight = oldTight;
state.parentType = oldParentType; 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; nextLine = startLine = state.line;
itemLines[1] = nextLine; itemLines[1] = nextLine;
@ -234,13 +237,27 @@ module.exports = function list(state, startLine, endLine, silent) {
} }
// Finilize list // Finilize list
if (isOrdered) { state.tokens.push({
state.tokens.push({ type: 'ordered_list_close', level: --state.level }); type: isOrdered ? 'ordered_list_close' : 'bullet_list_close',
} else { level: --state.level
state.tokens.push({ type: 'bullet_list_close', level: --state.level }); });
}
listLines[1] = nextLine; listLines[1] = nextLine;
state.line = 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; return true;
}; };

2
lib/rules_block/paragraph.js

@ -42,6 +42,7 @@ module.exports = function paragraph(state, startLine/*, endLine*/) {
if (content.length) { if (content.length) {
state.tokens.push({ state.tokens.push({
type: 'paragraph_open', type: 'paragraph_open',
tight: false,
lines: [ startLine, state.line ], lines: [ startLine, state.line ],
level: state.level level: state.level
}); });
@ -54,6 +55,7 @@ module.exports = function paragraph(state, startLine/*, endLine*/) {
}); });
state.tokens.push({ state.tokens.push({
type: 'paragraph_close', type: 'paragraph_close',
tight: false,
level: state.level level: state.level
}); });
} }

Loading…
Cancel
Save