Update MD031/blanks-around-fences to include list_items parameter (fixes #200).

This commit is contained in:
David Anson 2019-08-02 22:58:41 -07:00
parent 4d11e60cfe
commit c5b74d22b9
9 changed files with 178 additions and 9 deletions

View file

@ -1015,6 +1015,8 @@ Tags: code, blank_lines
Aliases: blanks-around-fences Aliases: blanks-around-fences
Parameters: list_items (boolean; default true)
This rule is triggered when fenced code blocks are either not preceded or not This rule is triggered when fenced code blocks are either not preceded or not
followed by a blank line: followed by a blank line:
@ -1050,6 +1052,10 @@ Some more text
Rationale: Aside from aesthetic reasons, some parsers, including kramdown, will Rationale: Aside from aesthetic reasons, some parsers, including kramdown, will
not parse fenced code blocks that don't have blank lines before and after them. not parse fenced code blocks that don't have blank lines before and after them.
Set the `list_items` parameter to `false` to disable this rule for list items.
Disabling this behavior for lists can be useful if it is necessary to create a
[tight](https://spec.commonmark.org/0.29/#tight) list containing a code fence.
<a name="md032"></a> <a name="md032"></a>
## MD032 - Lists should be surrounded by blank lines ## MD032 - Lists should be surrounded by blank lines

View file

@ -150,7 +150,7 @@ module.exports.filterTokens = filterTokens;
// Get line metadata array // Get line metadata array
module.exports.getLineMetadata = function getLineMetadata(params) { module.exports.getLineMetadata = function getLineMetadata(params) {
const lineMetadata = params.lines.map(function mapLine(line, index) { const lineMetadata = params.lines.map(function mapLine(line, index) {
return [ line, index, false, 0, false ]; return [ line, index, false, 0, false, false ];
}); });
filterTokens(params, "fence", function forToken(token) { filterTokens(params, "fence", function forToken(token) {
lineMetadata[token.map[0]][3] = 1; lineMetadata[token.map[0]][3] = 1;
@ -169,6 +169,11 @@ module.exports.getLineMetadata = function getLineMetadata(params) {
lineMetadata[i][4] = true; lineMetadata[i][4] = true;
} }
}); });
filterTokens(params, "list_item_open", function forToken(token) {
for (let i = token.map[0]; i < token.map[1]; i++) {
lineMetadata[i][5] = true;
}
});
return lineMetadata; return lineMetadata;
}; };

View file

@ -10,10 +10,13 @@ module.exports = {
"description": "Fenced code blocks should be surrounded by blank lines", "description": "Fenced code blocks should be surrounded by blank lines",
"tags": [ "code", "blank_lines" ], "tags": [ "code", "blank_lines" ],
"function": function MD031(params, onError) { "function": function MD031(params, onError) {
const listItems = params.config.list_items;
const includeListItems = (listItems === undefined) ? true : !!listItems;
const { lines } = params; const { lines } = params;
forEachLine(lineMetadata(), (line, i, inCode, onFence) => { forEachLine(lineMetadata(), (line, i, inCode, onFence, inTable, inItem) => {
if (((onFence > 0) && !isBlankLine(lines[i - 1])) || if ((((onFence > 0) && !isBlankLine(lines[i - 1])) ||
((onFence < 0) && !isBlankLine(lines[i + 1]))) { ((onFence < 0) && !isBlankLine(lines[i + 1]))) &&
(includeListItems || !inItem)) {
addErrorContext(onError, i + 1, lines[i].trim()); addErrorContext(onError, i + 1, lines[i].trim());
} }
}); });

View file

@ -238,6 +238,15 @@ rules.forEach(function forRule(rule) {
} }
}; };
break; break;
case "MD031":
scheme.properties = {
"list_items": {
"description": "Include list items",
"type": "boolean",
"default": true
}
};
break;
case "MD033": case "MD033":
scheme.properties = { scheme.properties = {
"allowed_elements": { "allowed_elements": {

View file

@ -867,13 +867,35 @@
}, },
"MD031": { "MD031": {
"description": "MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines", "description": "MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines",
"type": "boolean", "type": [
"default": true "boolean",
"object"
],
"default": true,
"properties": {
"list_items": {
"description": "Include list items",
"type": "boolean",
"default": true
}
},
"additionalProperties": false
}, },
"blanks-around-fences": { "blanks-around-fences": {
"description": "MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines", "description": "MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines",
"type": "boolean", "type": [
"default": true "boolean",
"object"
],
"default": true,
"properties": {
"list_items": {
"description": "Include list items",
"type": "boolean",
"default": true
}
},
"additionalProperties": false
}, },
"MD032": { "MD032": {
"description": "MD032/blanks-around-lists - Lists should be surrounded by blank lines", "description": "MD032/blanks-around-lists - Lists should be surrounded by blank lines",

View file

@ -0,0 +1,6 @@
{
"default": true,
"MD031": {
"list_items": false
}
}

View file

@ -0,0 +1,59 @@
# Lists with Fenced Code, Tight
- Item
```text
fence
```
- Item
- Item
```text
fence
```
- Item
Text
- Item
```text
fence
```
- Item
- Item
```text
fence
```
- Item
Text
1. Item
```text
fence
```
1. Item
1. Item
```text
fence
```
1. Item
Text
1. Item
```text
fence
```
1. Item
1. Item
```text
fence
```
1. Item

View file

@ -0,0 +1,59 @@
# Lists with Fenced Code
- Item
```text
fence
```
- Item
- Item
```text
fence
```
- Item
Text
- Item
```text
fence {MD031:21} {MD031:23}
```
- Item
- Item
```text
fence {MD031:26} {MD031:28}
```
- Item
Text
1. Item
```text
fence
```
1. Item
1. Item
```text
fence
```
1. Item
Text
1. Item
```text
fence {MD031:51} {MD031:53}
```
1. Item
1. Item
```text
fence {MD031:56} {MD031:58}
```
1. Item

View file

@ -1169,7 +1169,7 @@ module.exports.readme = function readme(test) {
}; };
module.exports.doc = function doc(test) { module.exports.doc = function doc(test) {
test.expect(327); test.expect(328);
fs.readFile("doc/Rules.md", helpers.utf8Encoding, fs.readFile("doc/Rules.md", helpers.utf8Encoding,
function readFile(err, contents) { function readFile(err, contents) {
test.ifError(err); test.ifError(err);