markdownlint 0.12.0 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.eslintrc.json +52 -275
  2. package/.travis.yml +2 -2
  3. package/LICENSE +1 -1
  4. package/README.md +54 -27
  5. package/doc/CustomRules.md +7 -2
  6. package/doc/Rules.md +120 -33
  7. package/example/standalone.js +2 -2
  8. package/helpers/LICENSE +21 -0
  9. package/helpers/README.md +50 -0
  10. package/{lib/shared.js → helpers/helpers.js} +91 -82
  11. package/helpers/package.json +18 -0
  12. package/lib/cache.js +24 -0
  13. package/lib/markdownlint.js +78 -45
  14. package/lib/md001.js +3 -3
  15. package/lib/md002.js +2 -2
  16. package/lib/md003.js +5 -4
  17. package/lib/md004.js +11 -9
  18. package/lib/md005.js +12 -10
  19. package/lib/md006.js +7 -5
  20. package/lib/md007.js +7 -5
  21. package/lib/md009.js +10 -8
  22. package/lib/md010.js +5 -5
  23. package/lib/md011.js +4 -4
  24. package/lib/md012.js +4 -3
  25. package/lib/md013.js +41 -32
  26. package/lib/md014.js +7 -6
  27. package/lib/md018.js +6 -4
  28. package/lib/md019.js +6 -5
  29. package/lib/md020.js +5 -4
  30. package/lib/md021.js +6 -5
  31. package/lib/md022.js +22 -22
  32. package/lib/md023.js +5 -4
  33. package/lib/md024.js +6 -6
  34. package/lib/md025.js +11 -5
  35. package/lib/md026.js +4 -4
  36. package/lib/md027.js +6 -6
  37. package/lib/md028.js +2 -2
  38. package/lib/md029.js +17 -9
  39. package/lib/md030.js +8 -6
  40. package/lib/md031.js +7 -6
  41. package/lib/md032.js +10 -12
  42. package/lib/md033.js +27 -26
  43. package/lib/md034.js +15 -10
  44. package/lib/md035.js +3 -3
  45. package/lib/md036.js +2 -2
  46. package/lib/md037.js +12 -9
  47. package/lib/md038.js +6 -5
  48. package/lib/md039.js +7 -6
  49. package/lib/md040.js +3 -3
  50. package/lib/md041.js +17 -19
  51. package/lib/md042.js +5 -4
  52. package/lib/md043.js +5 -4
  53. package/lib/md044.js +14 -13
  54. package/lib/md045.js +3 -3
  55. package/lib/md046.js +32 -0
  56. package/lib/md047.js +18 -0
  57. package/lib/rules.js +3 -1
  58. package/package.json +12 -11
  59. package/schema/build-config-schema.js +36 -2
  60. package/schema/markdownlint-config-schema.json +178 -14
  61. package/style/cirosantilli.json +1 -1
package/lib/md041.js CHANGED
@@ -2,32 +2,30 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- const shared = require("./shared");
5
+ const { addErrorContext, frontMatterHasTitle } = require("../helpers");
6
6
 
7
7
  module.exports = {
8
- "names": [ "MD041", "first-line-h1" ],
8
+ "names": [ "MD041", "first-line-heading", "first-line-h1" ],
9
9
  "description": "First line in file should be a top level heading",
10
10
  "tags": [ "headings", "headers" ],
11
11
  "function": function MD041(params, onError) {
12
12
  const level = params.config.level || 1;
13
- const frontMatterTitle = params.config.front_matter_title;
14
13
  const tag = "h" + level;
15
- const frontMatterTitleRe =
16
- new RegExp(frontMatterTitle || "^\\s*title\\s*[:=]", "i");
17
- params.tokens.every(function forToken(token) {
18
- if (token.type === "html_block") {
19
- return true;
20
- } else if (token.type === "heading_open") {
21
- if (token.tag !== tag) {
22
- shared.addErrorContext(onError, token.lineNumber, token.line);
14
+ const foundFrontMatterTitle =
15
+ frontMatterHasTitle(
16
+ params.frontMatterLines,
17
+ params.config.front_matter_title
18
+ );
19
+ if (!foundFrontMatterTitle) {
20
+ params.tokens.every((token) => {
21
+ if (token.type === "html_block") {
22
+ return true;
23
23
  }
24
- } else if (((frontMatterTitle !== undefined) && !frontMatterTitle) ||
25
- !params.frontMatterLines.some(function forLine(line) {
26
- return frontMatterTitleRe.test(line);
27
- })) {
28
- shared.addErrorContext(onError, token.lineNumber, token.line);
29
- }
30
- return false;
31
- });
24
+ if ((token.type !== "heading_open") || (token.tag !== tag)) {
25
+ addErrorContext(onError, token.lineNumber, token.line);
26
+ }
27
+ return false;
28
+ });
29
+ }
32
30
  }
33
31
  };
package/lib/md042.js CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- const shared = require("./shared");
5
+ const { addErrorContext, filterTokens, rangeFromRegExp } =
6
+ require("../helpers");
6
7
 
7
8
  const emptyLinkRe = /\[[^\]]*](?:\((?:#?|(?:<>))\))/;
8
9
 
@@ -11,7 +12,7 @@ module.exports = {
11
12
  "description": "No empty links",
12
13
  "tags": [ "links" ],
13
14
  "function": function MD042(params, onError) {
14
- shared.filterTokens(params, "inline", function forToken(token) {
15
+ filterTokens(params, "inline", function forToken(token) {
15
16
  let inLink = false;
16
17
  let linkText = "";
17
18
  let emptyLink = false;
@@ -27,9 +28,9 @@ module.exports = {
27
28
  } else if (child.type === "link_close") {
28
29
  inLink = false;
29
30
  if (emptyLink) {
30
- shared.addErrorContext(onError, child.lineNumber,
31
+ addErrorContext(onError, child.lineNumber,
31
32
  "[" + linkText + "]()", null, null,
32
- shared.rangeFromRegExp(child.line, emptyLinkRe));
33
+ rangeFromRegExp(child.line, emptyLinkRe));
33
34
  }
34
35
  } else if (inLink) {
35
36
  linkText += child.content;
package/lib/md043.js CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- const shared = require("./shared");
5
+ const { addErrorContext, addErrorDetailIf, forEachHeading } =
6
+ require("../helpers");
6
7
 
7
8
  module.exports = {
8
9
  "names": [ "MD043", "required-headings", "required-headers" ],
@@ -18,7 +19,7 @@ module.exports = {
18
19
  let i = 0;
19
20
  let optional = false;
20
21
  let errorCount = 0;
21
- shared.forEachHeading(params, function forHeading(heading, content) {
22
+ forEachHeading(params, function forHeading(heading, content) {
22
23
  if (!errorCount) {
23
24
  const actual = levels[heading.tag] + " " + content;
24
25
  const expected = requiredHeadings[i++] || "[None]";
@@ -29,14 +30,14 @@ module.exports = {
29
30
  } else if (optional) {
30
31
  i--;
31
32
  } else {
32
- shared.addErrorDetailIf(onError, heading.lineNumber,
33
+ addErrorDetailIf(onError, heading.lineNumber,
33
34
  expected, actual);
34
35
  errorCount++;
35
36
  }
36
37
  }
37
38
  });
38
39
  if ((i < requiredHeadings.length) && !errorCount) {
39
- shared.addErrorContext(onError, params.lines.length,
40
+ addErrorContext(onError, params.lines.length,
40
41
  requiredHeadings[i]);
41
42
  }
42
43
  }
package/lib/md044.js CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- const shared = require("./shared");
5
+ const { addErrorDetailIf, bareUrlRe, escapeForRegExp, filterTokens,
6
+ forEachInlineChild, newLineRe } = require("../helpers");
6
7
 
7
8
  module.exports = {
8
9
  "names": [ "MD044", "proper-names" ],
@@ -12,35 +13,35 @@ module.exports = {
12
13
  const names = params.config.names || [];
13
14
  const codeBlocks = params.config.code_blocks;
14
15
  const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
15
- names.forEach(function forName(name) {
16
- const escapedName = shared.escapeForRegExp(name);
16
+ names.forEach((name) => {
17
+ const escapedName = escapeForRegExp(name);
17
18
  const namePattern = "\\S*\\b(" + escapedName + ")\\b\\S*";
18
19
  const anyNameRe = new RegExp(namePattern, "gi");
19
20
  function forToken(token) {
20
21
  const fenceOffset = (token.type === "fence") ? 1 : 0;
21
- token.content.split(shared.newLineRe)
22
- .forEach(function forLine(line, index) {
22
+ token.content.split(newLineRe)
23
+ .forEach((line, index) => {
23
24
  let match = null;
24
25
  while ((match = anyNameRe.exec(line)) !== null) {
25
26
  const fullMatch = match[0];
26
- if (!shared.bareUrlRe.test(fullMatch)) {
27
+ if (!bareUrlRe.test(fullMatch)) {
27
28
  const wordMatch = fullMatch
28
29
  .replace(/^\W*/, "").replace(/\W*$/, "");
29
- if (names.indexOf(wordMatch) === -1) {
30
+ if (!names.includes(wordMatch)) {
30
31
  const lineNumber = token.lineNumber + index + fenceOffset;
31
32
  const range = [ match.index + 1, wordMatch.length ];
32
- shared.addErrorDetailIf(onError, lineNumber,
33
- name, match[1], null, range);
33
+ addErrorDetailIf(onError, lineNumber,
34
+ name, match[1], null, null, range);
34
35
  }
35
36
  }
36
37
  }
37
38
  });
38
39
  }
39
- shared.forEachInlineChild(params, "text", forToken);
40
+ forEachInlineChild(params, "text", forToken);
40
41
  if (includeCodeBlocks) {
41
- shared.forEachInlineChild(params, "code_inline", forToken);
42
- shared.filterTokens(params, "code_block", forToken);
43
- shared.filterTokens(params, "fence", forToken);
42
+ forEachInlineChild(params, "code_inline", forToken);
43
+ filterTokens(params, "code_block", forToken);
44
+ filterTokens(params, "fence", forToken);
44
45
  }
45
46
  });
46
47
  }
package/lib/md045.js CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- const shared = require("./shared");
5
+ const { addError, forEachInlineChild } = require("../helpers");
6
6
 
7
7
  module.exports = {
8
8
  "names": [ "MD045", "no-alt-text" ],
9
9
  "description": "Images should have alternate text (alt text)",
10
10
  "tags": [ "accessibility", "images" ],
11
11
  "function": function MD045(params, onError) {
12
- shared.forEachInlineChild(params, "image", function forToken(token) {
12
+ forEachInlineChild(params, "image", function forToken(token) {
13
13
  if (token.content === "") {
14
- shared.addError(onError, token.lineNumber);
14
+ addError(onError, token.lineNumber);
15
15
  }
16
16
  });
17
17
  }
package/lib/md046.js ADDED
@@ -0,0 +1,32 @@
1
+ // @ts-check
2
+
3
+ "use strict";
4
+
5
+ const { addErrorDetailIf } = require("../helpers");
6
+
7
+ const tokenTypeToStyle = {
8
+ "fence": "fenced",
9
+ "code_block": "indented"
10
+ };
11
+
12
+ module.exports = {
13
+ "names": [ "MD046", "code-block-style" ],
14
+ "description": "Code block style",
15
+ "tags": [ "code" ],
16
+ "function": function MD046(params, onError) {
17
+ let expectedStyle = params.config.style || "consistent";
18
+ params.tokens
19
+ .filter((token) => token.type === "code_block" || token.type === "fence")
20
+ .forEach((token) => {
21
+ const { lineNumber, type } = token;
22
+ if (expectedStyle === "consistent") {
23
+ expectedStyle = tokenTypeToStyle[type];
24
+ }
25
+ addErrorDetailIf(
26
+ onError,
27
+ lineNumber,
28
+ expectedStyle,
29
+ tokenTypeToStyle[type]);
30
+ });
31
+ }
32
+ };
package/lib/md047.js ADDED
@@ -0,0 +1,18 @@
1
+ // @ts-check
2
+
3
+ "use strict";
4
+
5
+ const { addError, isBlankLine } = require("../helpers");
6
+
7
+ module.exports = {
8
+ "names": [ "MD047", "single-trailing-newline" ],
9
+ "description": "Files should end with a single newline character",
10
+ "tags": [ "blank_lines" ],
11
+ "function": function MD047(params, onError) {
12
+ const lastLineNumber = params.lines.length;
13
+ const lastLine = params.lines[lastLineNumber - 1];
14
+ if (!isBlankLine(lastLine)) {
15
+ addError(onError, lastLineNumber);
16
+ }
17
+ }
18
+ };
package/lib/rules.js CHANGED
@@ -48,7 +48,9 @@ const rules = [
48
48
  require("./md042"),
49
49
  require("./md043"),
50
50
  require("./md044"),
51
- require("./md045")
51
+ require("./md045"),
52
+ require("./md046"),
53
+ require("./md047")
52
54
  ];
53
55
  rules.forEach((rule) => {
54
56
  const name = rule.names[0].toLowerCase();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdownlint",
3
- "version": "0.12.0",
3
+ "version": "0.14.2",
4
4
  "description": "A Node.js style checker and lint tool for Markdown/CommonMark files.",
5
5
  "main": "lib/markdownlint.js",
6
6
  "author": "David Anson (https://dlaa.me/)",
@@ -13,39 +13,40 @@
13
13
  "bugs": "https://github.com/DavidAnson/markdownlint/issues",
14
14
  "scripts": {
15
15
  "test": "nodeunit test/markdownlint-test.js",
16
- "test-cover": "istanbul cover node_modules/nodeunit/bin/nodeunit test/markdownlint-test.js",
16
+ "test-cover": "nyc node_modules/nodeunit/bin/nodeunit test/markdownlint-test.js",
17
17
  "test-extra": "nodeunit test/markdownlint-test-extra.js",
18
18
  "debug": "node debug node_modules/nodeunit/bin/nodeunit",
19
- "lint": "eslint lib test schema && eslint --env browser --global markdownit --global markdownlint --rule \"no-unused-vars: 0, no-extend-native: 0, max-statements: 0, no-console: 0, no-var: 0\" demo && eslint --rule \"no-console: 0, no-shadow: 0, object-property-newline: 0\" example",
19
+ "lint": "eslint lib helpers test schema && eslint --env browser --global markdownit --global markdownlint --rule \"no-unused-vars: 0, no-extend-native: 0, max-statements: 0, no-console: 0, no-var: 0\" demo && eslint --rule \"no-console: 0, no-invalid-this: 0, no-shadow: 0, object-property-newline: 0\" example",
20
20
  "build-config-schema": "node schema/build-config-schema.js",
21
- "build-demo": "cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && cpy file-header.js . --rename=markdownlint-browser.js && tsc --allowJs --resolveJsonModule --outDir ../lib-es3 ../lib/markdownlint.js && browserify ../lib-es3/lib/markdownlint.js --standalone markdownlint >> markdownlint-browser.js && uglifyjs markdownlint-browser.js --compress --mangle --comments --output markdownlint-browser.min.js",
21
+ "build-demo": "cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && cpy file-header.js . --rename=markdownlint-browser.js && tsc --allowJs --resolveJsonModule --outDir ../lib-es3 ../lib/markdownlint.js && cpy ../helpers/package.json ../lib-es3/helpers && browserify ../lib-es3/lib/markdownlint.js --standalone markdownlint >> markdownlint-browser.js && uglifyjs markdownlint-browser.js --compress --mangle --comments --output markdownlint-browser.min.js",
22
22
  "build-example": "npm install --no-save --ignore-scripts grunt grunt-cli gulp through2",
23
23
  "example": "cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint"
24
24
  },
25
25
  "engines": {
26
- "node": ">=6"
26
+ "node": ">=8"
27
27
  },
28
28
  "dependencies": {
29
29
  "markdown-it": "8.4.2"
30
30
  },
31
31
  "devDependencies": {
32
- "@types/node": "~10.12.21",
32
+ "@types/node": "~12.0.0",
33
33
  "browserify": "~16.2.3",
34
34
  "cpy-cli": "~2.0.0",
35
- "eslint": "~5.12.1",
35
+ "eslint": "~5.16.0",
36
36
  "glob": "~7.1.3",
37
- "istanbul": "~0.4.5",
38
- "js-yaml": "~3.12.1",
37
+ "js-yaml": "~3.13.1",
39
38
  "markdown-it-for-inline": "~0.1.1",
40
39
  "markdown-it-katex": "~2.0.3",
41
40
  "markdown-it-sub": "~1.0.0",
42
41
  "markdown-it-sup": "~1.0.0",
42
+ "markdownlint-rule-helpers": "~0.1.0",
43
43
  "nodeunit": "~0.11.3",
44
+ "nyc": "~14.1.0",
44
45
  "rimraf": "~2.6.3",
45
46
  "toml": "~3.0.0",
46
47
  "tv4": "~1.3.0",
47
- "typescript": "~3.3.1",
48
- "uglify-js": "~3.4.9"
48
+ "typescript": "~3.4.5",
49
+ "uglify-js": "~3.5.11"
49
50
  },
50
51
  "keywords": [
51
52
  "markdown",
@@ -40,7 +40,6 @@ rules.forEach(function forRule(rule) {
40
40
  let custom = true;
41
41
  switch (rule.names[0]) {
42
42
  case "MD002":
43
- case "MD025":
44
43
  scheme.properties = {
45
44
  "level": {
46
45
  "description": "Heading level",
@@ -130,6 +129,11 @@ rules.forEach(function forRule(rule) {
130
129
  "type": "integer",
131
130
  "default": 80
132
131
  },
132
+ "heading_line_length": {
133
+ "description": "Number of characters for headings",
134
+ "type": "integer",
135
+ "default": 80
136
+ },
133
137
  "code_blocks": {
134
138
  "description": "Include code blocks",
135
139
  "type": "boolean",
@@ -152,6 +156,20 @@ rules.forEach(function forRule(rule) {
152
156
  }
153
157
  };
154
158
  break;
159
+ case "MD022":
160
+ scheme.properties = {
161
+ "lines_above": {
162
+ "description": "Blank lines above heading",
163
+ "type": "integer",
164
+ "default": 1
165
+ },
166
+ "lines_below": {
167
+ "description": "Blank lines below heading",
168
+ "type": "integer",
169
+ "default": 1
170
+ }
171
+ };
172
+ break;
155
173
  case "MD024":
156
174
  scheme.properties = {
157
175
  "allow_different_nesting": {
@@ -184,7 +202,8 @@ rules.forEach(function forRule(rule) {
184
202
  "enum": [
185
203
  "one",
186
204
  "ordered",
187
- "one_or_ordered"
205
+ "one_or_ordered",
206
+ "zero"
188
207
  ],
189
208
  "default": "one_or_ordered"
190
209
  }
@@ -235,6 +254,7 @@ rules.forEach(function forRule(rule) {
235
254
  }
236
255
  };
237
256
  break;
257
+ case "MD025":
238
258
  case "MD041":
239
259
  scheme.properties = {
240
260
  "level": {
@@ -286,6 +306,20 @@ rules.forEach(function forRule(rule) {
286
306
  }
287
307
  };
288
308
  break;
309
+ case "MD046":
310
+ scheme.properties = {
311
+ "style": {
312
+ "description": "Block style",
313
+ "type": "string",
314
+ "enum": [
315
+ "consistent",
316
+ "fenced",
317
+ "indented"
318
+ ],
319
+ "default": "consistent"
320
+ }
321
+ };
322
+ break;
289
323
  default:
290
324
  custom = false;
291
325
  break;