diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..e08a89dd --- /dev/null +++ b/.eslintrc @@ -0,0 +1,161 @@ +{ + "ecmaFeatures": {}, + "parser": "espree", + "env": { + "browser": false, + "node": true, + "amd": false, + "mocha": false, + "jasmine": false + }, + + "rules": { + "no-alert": 2, + "no-array-constructor": 2, + "no-bitwise": 2, + "no-caller": 2, + "no-catch-shadow": 2, + "no-comma-dangle": 2, + "no-cond-assign": 2, + "no-console": 2, + "no-constant-condition": 2, + "no-control-regex": 2, + "no-debugger": 2, + "no-delete-var": 2, + "no-div-regex": 2, + "no-dupe-keys": 2, + "no-else-return": 2, + "no-empty": 2, + "no-empty-class": 2, + "no-empty-label": 2, + "no-eq-null": 2, + "no-eval": 2, + "no-ex-assign": 2, + "no-extend-native": 2, + "no-extra-bind": 2, + "no-extra-boolean-cast": 2, + "no-extra-parens": 0, + "no-extra-semi": 2, + "no-extra-strict": 2, + "no-fallthrough": 2, + "no-floating-decimal": 2, + "no-func-assign": 2, + "no-implied-eval": 2, + "no-inline-comments": 0, + "no-inner-declarations": [2, "functions"], + "no-invalid-regexp": 2, + "no-irregular-whitespace": 2, + "no-iterator": 2, + "no-label-var": 2, + "no-labels": 2, + "no-lone-blocks": 2, + "no-lonely-if": 2, + "no-loop-func": 2, + "no-mixed-requires": [2, true], + "no-mixed-spaces-and-tabs": [2, false], + "no-multi-spaces": 2, + "no-multi-str": 2, + "no-multiple-empty-lines": [2, { "max": 2 }], + "no-native-reassign": 2, + "no-negated-in-lhs": 2, + "no-nested-ternary": 2, + "no-new": 2, + "no-new-func": 2, + "no-new-object": 2, + "no-new-require": 2, + "no-new-wrappers": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-octal-escape": 2, + "no-path-concat": 2, + "no-plusplus": 0, + "no-process-env": 2, + "no-process-exit": 2, + "no-proto": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-reserved-keys": 2, + "no-restricted-modules": 0, + "no-return-assign": 2, + "no-script-url": 2, + "no-self-compare": 2, + "no-sequences": 2, + "no-shadow": 2, + "no-shadow-restricted-names": 2, + "no-space-before-semi": 2, + "no-spaced-func": 2, + "no-sparse-arrays": 2, + "no-sync": 2, + "no-ternary": 0, + "no-trailing-spaces": 2, + "no-throw-literal": 2, + "no-undef": 2, + "no-undef-init": 2, + "no-undefined": 2, + "no-underscore-dangle": 2, + "no-unreachable": 2, + "no-unused-expressions": 2, + "no-unused-vars": [2, { "vars": "all", "args": "after-used" }], + "no-use-before-define": 2, + "no-void": 2, + "no-var": 0, + "no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }], + "no-with": 2, + "no-wrap-func": 2, + + "block-scoped-var": 2, + "brace-style": [2, "1tbs"], + "camelcase": 2, + "comma-spacing": 2, + "comma-style": 2, + "complexity": [2, 11], + "consistent-return": 2, + "consistent-this": [2, "self"], + "curly": [2, "all"], + "default-case": 2, + "dot-notation": [2, { "allowKeywords": true }], + "eol-last": 2, + "eqeqeq": 2, + "func-names": 2, + "func-style": [2, "declaration"], + "generator-star": 2, + "global-strict": [2, "always"], + "guard-for-in": 2, + "handle-callback-err": 2, + "indent": [2, 2], + "key-spacing": [2, { "beforeColon": false, "afterColon": true }], + "max-depth": [2, 4], + "max-len": [2, 80, 2], + "max-nested-callbacks": [2, 2], + "max-params": [2, 3], + "max-statements": [0, 10], + "new-cap": 2, + "new-parens": 2, + "one-var": 0, + "operator-assignment": [2, "always"], + "padded-blocks": [2, "never"], + "quote-props": 2, + "quotes": [2, "double"], + "radix": 2, + "semi": 2, + "sort-vars": 0, + "space-after-function-name": [2, "never"], + "space-after-keywords": [2, "always"], + "space-before-blocks": [2, "always"], + "space-before-function-parentheses": [2, "never"], + "space-in-brackets": [2, "always", { "propertyName": false }], + "space-in-parens": [2, "never"], + "space-infix-ops": 2, + "space-return-throw-case": 2, + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "spaced-line-comment": [2, "always"], + "strict": 2, + "use-isnan": 2, + "valid-jsdoc": 2, + "valid-typeof": 2, + "vars-on-top": 0, + "wrap-iife": 2, + "wrap-regex": 0, + "yoda": [2, "never"] + } +} diff --git a/lib/markdownlint.js b/lib/markdownlint.js index 87fff9c0..ca1c1fdc 100644 --- a/lib/markdownlint.js +++ b/lib/markdownlint.js @@ -3,25 +3,42 @@ var fs = require("fs"); var rules = require("./rules"); -function lintFile(file, options) { - var results = {}; - var contents = fs.readFileSync(file, { encoding: "utf8" }); - var lines = contents.split(/\r\n|\n/g); - Object.keys(rules).forEach(function(name) { - var rule = rules[name]; - var errors = rule(lines); - if (errors.length) { - results[name] = errors; +function lintFile(file, options, callback) { + fs.readFile(file, { "encoding": "utf8" }, function readFile(err, contents) { + if (err) { + callback(err); + } else { + var lines = contents.split(/\r\n|\n/g); + var result = {}; + Object.keys(rules).forEach(function forRule(name) { + var rule = rules[name]; + var errors = rule(lines); + if (errors.length) { + result[name] = errors; + } + }); + callback(null, result); } }); - return results; } -module.exports = function(options) { +module.exports = function markdownlint(options, callback) { var results = {}; var files = options.files || []; - files.forEach(function(file) { - results[file] = lintFile(file, options); - }); - return results; + function lintFiles() { + var file = files.shift(); + if (file) { + lintFile(file, options, function lintFileCallback(err, result) { + if (err) { + callback(err); + } else { + results[file] = result; + lintFiles(); + } + }); + } else { + callback(null, results); + } + } + lintFiles(); }; diff --git a/lib/rules.js b/lib/rules.js index 2419ef99..83485c30 100644 --- a/lib/rules.js +++ b/lib/rules.js @@ -3,20 +3,20 @@ function padAndTrim(lines) { return [].concat( "", - lines.map(function(line) { + lines.map(function mapLine(line) { return line.trim(); }), ""); } module.exports = { - MD031: function(lines) { + "MD031": function MD031(lines) { // Some parsers have trouble detecting fenced code blocks without // surrounding whitespace, so examine the lines directly. lines = padAndTrim(lines); var errors = []; var inCode = false; - lines.forEach(function(line, lineNum) { + lines.forEach(function forLine(line, lineNum) { if (line.match(/^(```|~~~)/)) { inCode = !inCode; if ((inCode && lines[lineNum - 1].length) || diff --git a/package.json b/package.json index 12d0c968..2ab3317b 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,11 @@ "url": "https://github.com/DavidAnson/markdownlint/issues" }, "scripts": { - "test": "nodeunit" + "test": "nodeunit", + "lint": "eslint lib test" }, "devDependencies": { + "eslint": "^0.15.0", "nodeunit": "^0.9.0" }, "keywords": [ diff --git a/test/markdownlint-test.js b/test/markdownlint-test.js index 871f438f..b33a2c53 100644 --- a/test/markdownlint-test.js +++ b/test/markdownlint-test.js @@ -5,31 +5,40 @@ var path = require("path"); var markdownlint = require("../lib/markdownlint"); function createTestForFile(file) { - return function(test) { - test.expect(1); - var contents = fs.readFileSync(file, { encoding: "utf8" }); - var lines = contents.split(/\r\n|\n/g); - var results = {}; - lines.forEach(function(line, lineNum) { - var match = line.match(/\{(MD\d+)(?::(\d+))?\}/); - if (match) { - var rule = match[1]; - var lines = results[rule] || []; - lines.push(lineNum + 1); - results[rule] = lines; - } - }); - var actual = markdownlint({ - files: [ file ] - }); - var expected = {}; - expected[file] = results; - test.deepEqual(actual, expected, "Line numbers are not correct."); - test.done(); + return function testForFile(test) { + test.expect(3); + fs.readFile( + file, + { "encoding": "utf8" }, + function readFileCallback(err, contents) { + test.ifError(err); + var lines = contents.split(/\r\n|\n/g); + var results = {}; + lines.forEach(function forLine(line, lineNum) { + var match = line.match(/\{(MD\d+)(?::(\d+))?\}/); + if (match) { + var rule = match[1]; + var errors = results[rule] || []; + errors.push(lineNum + 1); + results[rule] = errors; + } + }); + markdownlint({ + "files": [ file ] + }, function markdownlintCallback(errr, actual) { + test.ifError(errr); + var expected = {}; + expected[file] = results; + test.deepEqual(actual, expected, "Line numbers are not correct."); + test.done(); + }); + }); }; } -fs.readdirSync(__dirname).forEach(function(file) { +/* eslint-disable no-sync, for synchronous test method creation */ +fs.readdirSync(__dirname).forEach(function forFile(file) { +/* eslint-enable no-sync */ if (file.match(/\.md$/)) { module.exports[file] = createTestForFile(path.join(__dirname, file)); }