diff --git a/lib/rules.js b/lib/rules.js index c38a1d43..16620dcf 100644 --- a/lib/rules.js +++ b/lib/rules.js @@ -85,42 +85,43 @@ function forEachHeading(params, callback) { } // Returns (nested) lists as a flat array (in order) -function flattenLists(tokens, filterBy) { - var lists = []; - var stack = []; - var current = null; - var lastWithMap = { "map": [ 0, 1 ] }; - tokens.forEach(function forToken(token) { - if ((token.type === "bullet_list_open") || - (token.type === "ordered_list_open")) { - // Save current context and start a new one - stack.push(current); - current = { - "ordered": (token.type === "ordered_list_open"), - "open": token, - "items": [], - "nesting": stack.length - 1, - "lastLineIndex": -1, - "insert": lists.length - }; - } else if ((token.type === "bullet_list_close") || - (token.type === "ordered_list_close")) { - // Finalize current context and restore previous - current.lastLineIndex = lastWithMap.map[1]; - if ((filterBy === undefined) || (filterBy === current.ordered)) { +function flattenLists(params) { + if (!params.flattenLists) { + var lists = []; + var stack = []; + var current = null; + var lastWithMap = { "map": [ 0, 1 ] }; + params.tokens.forEach(function forToken(token) { + if ((token.type === "bullet_list_open") || + (token.type === "ordered_list_open")) { + // Save current context and start a new one + stack.push(current); + current = { + "ordered": (token.type === "ordered_list_open"), + "open": token, + "items": [], + "nesting": stack.length - 1, + "lastLineIndex": -1, + "insert": lists.length + }; + } else if ((token.type === "bullet_list_close") || + (token.type === "ordered_list_close")) { + // Finalize current context and restore previous + current.lastLineIndex = lastWithMap.map[1]; lists.splice(current.insert, 0, current); delete current.insert; + current = stack.pop(); + } else if (token.type === "list_item_open") { + // Add list item + current.items.push(token); + } else if (token.map) { + // Track last token with map + lastWithMap = token; } - current = stack.pop(); - } else if (token.type === "list_item_open") { - // Add list item - current.items.push(token); - } else if (token.map) { - // Track last token with map - lastWithMap = token; - } - }); - return lists; + }); + params.flattenLists = lists; + } + return params.flattenLists; } module.exports = [ @@ -180,15 +181,17 @@ module.exports = [ "tags": [ "bullet", "ul" ], "func": function MD004(params, errors) { var style = params.options.style || "consistent"; - flattenLists(params.tokens, false).forEach(function forList(list) { - if (style === "consistent") { - style = unorderedListStyleFor(list.items[0]); - } - list.items.forEach(function forItem(item) { - if (unorderedListStyleFor(item) !== style) { - errors.push(item.lineNumber); + flattenLists(params).forEach(function forList(list) { + if (!list.ordered) { + if (style === "consistent") { + style = unorderedListStyleFor(list.items[0]); } - }); + list.items.forEach(function forItem(item) { + if (unorderedListStyleFor(item) !== style) { + errors.push(item.lineNumber); + } + }); + } }); } }, @@ -198,7 +201,7 @@ module.exports = [ "desc": "Inconsistent indentation for list items at the same level", "tags": [ "bullet", "ul", "indentation" ], "func": function MD005(params, errors) { - flattenLists(params.tokens).forEach(function forList(list) { + flattenLists(params).forEach(function forList(list) { var indent = indentFor(list.items[0]); list.items.forEach(function forItem(item) { if (indentFor(item) !== indent) { @@ -214,8 +217,8 @@ module.exports = [ "desc": "Consider starting bulleted lists at the beginning of the line", "tags": [ "bullet", "ul", "indentation" ], "func": function MD006(params, errors) { - flattenLists(params.tokens, false).forEach(function forList(list) { - if (!list.nesting && indentFor(list.open)) { + flattenLists(params).forEach(function forList(list) { + if (!list.ordered && !list.nesting && indentFor(list.open)) { errors.push(list.open.lineNumber); } }); @@ -229,13 +232,15 @@ module.exports = [ "func": function MD007(params, errors) { var optionsIndent = params.options.indent || 2; var prevIndent = 0; - flattenLists(params.tokens, false).forEach(function forList(list) { - var indent = indentFor(list.open); - if ((indent > prevIndent) && - ((indent - prevIndent) !== optionsIndent)) { - errors.push(list.open.lineNumber); + flattenLists(params).forEach(function forList(list) { + if (!list.ordered) { + var indent = indentFor(list.open); + if ((indent > prevIndent) && + ((indent - prevIndent) !== optionsIndent)) { + errors.push(list.open.lineNumber); + } + prevIndent = indent; } - prevIndent = indent; }); } }, @@ -531,17 +536,19 @@ module.exports = [ "tags": [ "ol" ], "func": function MD029(params, errors) { var style = params.options.style || "one"; - flattenLists(params.tokens, true).forEach(function forList(list) { - var number = 1; - list.items.forEach(function forItem(item) { - var re = new RegExp("^\\s*" + String(number) + "\\."); - if (!re.test(item.line)) { - errors.push(item.lineNumber); - } - if (style === "ordered") { - number++; - } - }); + flattenLists(params).forEach(function forList(list) { + if (list.ordered) { + var number = 1; + list.items.forEach(function forItem(item) { + var re = new RegExp("^\\s*" + String(number) + "\\."); + if (!re.test(item.line)) { + errors.push(item.lineNumber); + } + if (style === "ordered") { + number++; + } + }); + } }); } }, @@ -555,7 +562,7 @@ module.exports = [ var olSingle = params.options.ol_single || 1; var ulMulti = params.options.ul_multi || 1; var olMulti = params.options.ol_multi || 1; - flattenLists(params.tokens).forEach(function forList(list) { + flattenLists(params).forEach(function forList(list) { var lineCount = list.lastLineIndex - list.open.map[0]; var allSingle = lineCount === list.items.length; var expectedSpaces = list.ordered ?