Skip to content

Commit f1162b9

Browse files
committed
Add support for .markdownlintignore file (fixes #61).
1 parent 8942af7 commit f1162b9

File tree

9 files changed

+65
-8
lines changed

9 files changed

+65
-8
lines changed

README.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,28 @@ With shells like Bash, it may be necessary to quote globs so they are not interp
3636
For example, `--ignore *.md` would be expanded by Bash to `--ignore a.md b.md ...` before invoking `markdownlint-cli`, causing it to ignore only the first file because `--ignore` takes a single parameter (though it can be used multiple times).
3737
Quoting the glob like `--ignore '*.md'` passes it through unexpanded and ignores the set of files.
3838

39-
#### Examples
39+
#### Globbing examples
4040

4141
To lint all Markdown files in a Node.js project (excluding dependencies), the following commands might be used:
4242

4343
Windows CMD: `markdownlint **/*.md --ignore node_modules`
4444

4545
Linux Bash: `markdownlint '**/*.md' --ignore node_modules`
4646

47+
### Ignoring files
48+
49+
If present in the current folder, a `.markdownlintignore` file will be used to ignore files and /or directories according to the rules for [gitignore][gitignore].
50+
51+
The order of operations is:
52+
53+
- Enumerate files/directories/globs on the command line
54+
- Apply exclusions from `.markdownlintignore`
55+
- Apply exclusions from `-i`/`--ignore` option(s)
56+
4757
### Fixing errors
4858

49-
When the `--fix` option is specified, `markdownlint-cli` tries to apply all fixes reported by the active rules and reports any errors that remain. Because this option makes changes to the input files, it is good to make a backup first or work with files under source control so any unwanted changes can be undone.
59+
When the `--fix` option is specified, `markdownlint-cli` tries to apply all fixes reported by the active rules and reports any errors that remain.
60+
Because this option makes changes to the input files, it is good to make a backup first or work with files under source control so any unwanted changes can be undone.
5061

5162
> Because not all rules include fix information when reporting errors, fixes may overlap, and not all errors are fixable, `--fix` will not usually address all errors.
5263
@@ -70,12 +81,16 @@ The example of configuration file:
7081

7182
See [test configuration file][test-config] or [style folder][style-folder] for more examples.
7283

73-
CLI argument `--config` is not mandatory. If it is not provided, `markdownlint-cli` looks for file `.markdownlint.json`/`.markdownlint.yaml`/`.markdownlint.yml` in current folder, or for file `.markdownlintrc` in current or all upper folders. The algorithm is described in details on [rc package page][rc-standards]. If `--config` argument is provided, the file must be valid JSON, JSONC, or YAML.
84+
CLI argument `--config` is not mandatory.
85+
If it is not provided, `markdownlint-cli` looks for file `.markdownlint.json`/`.markdownlint.yaml`/`.markdownlint.yml` in current folder, or for file `.markdownlintrc` in current or all upper folders.
86+
The algorithm is described in details on [rc package page][rc-standards].
87+
If `--config` argument is provided, the file must be valid JSON, JSONC, or YAML.
7488

7589
## Related
7690

7791
- [markdownlint][markdownlint] - API for this module
7892
- [glob][glob] - Pattern matching implementation
93+
- [ignore][ignore] - `.markdownlintignore` implementation
7994

8095
## License
8196

@@ -95,3 +110,5 @@ MIT © Igor Shubovych
95110
[rc-standards]: https://www.npmjs.com/package/rc#standards
96111
[glob]: https://github.com/isaacs/node-glob
97112
[globprimer]: https://github.com/isaacs/node-glob/blob/master/README.md#glob-primer
113+
[ignore]: https://github.com/kaelzhang/node-ignore
114+
[gitignore]: https://git-scm.com/docs/gitignore

markdownlint.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const jsoncParser = require('jsonc-parser');
1212
const differenceWith = require('lodash.differencewith');
1313
const flatten = require('lodash.flatten');
1414
const extend = require('deep-extend');
15+
const ignore = require('ignore');
1516
const markdownlint = require('markdownlint');
1617
const markdownlintRuleHelpers = require('markdownlint-rule-helpers');
1718
const rc = require('rc');
@@ -29,6 +30,7 @@ const projectConfigFiles = [
2930
'.markdownlint.yml'
3031
];
3132
const configFileParsers = [jsoncParse, jsYaml.safeLoad];
33+
const fsOptions = {encoding: 'utf8'};
3234

3335
function readConfiguration(args) {
3436
let config = rc('markdownlint', {});
@@ -214,7 +216,16 @@ function loadCustomRules(rules) {
214216
}));
215217
}
216218

217-
const files = prepareFileList(program.args, ['md', 'markdown']);
219+
const markdownlintIgnore = '.markdownlintignore';
220+
let ignoreFilter = () => true;
221+
if (fs.existsSync(markdownlintIgnore)) {
222+
const ignoreText = fs.readFileSync(markdownlintIgnore, fsOptions);
223+
const ignoreInstance = ignore().add(ignoreText);
224+
ignoreFilter = fileInfo => !ignoreInstance.ignores(fileInfo.original);
225+
}
226+
227+
const files = prepareFileList(program.args, ['md', 'markdown'])
228+
.filter(ignoreFilter);
218229
const ignores = prepareFileList(program.ignore, ['md', 'markdown'], files);
219230
const customRules = loadCustomRules(program.rules);
220231
const diff = differenceWith(files, ignores, function (a, b) {
@@ -242,7 +253,6 @@ function lintAndPrint(stdin, files) {
242253
...lintOptions,
243254
resultVersion: 3
244255
};
245-
const fsOptions = {encoding: 'utf8'};
246256
files.forEach(file => {
247257
fixOptions.files = [file];
248258
const fixResult = markdownlint.sync(fixOptions);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"deep-extend": "~0.5.1",
4242
"get-stdin": "~5.0.1",
4343
"glob": "~7.1.2",
44+
"ignore": "~5.1.4",
4445
"js-yaml": "~3.13.1",
4546
"jsonc-parser": "~2.2.0",
4647
"lodash.differencewith": "~4.5.0",
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# comment followed by blank line
2+
3+
# star-star pattern with trailing space
4+
**/*.markdown
5+
# negated star pattern
6+
!subd*/incorrect.markdown

test/markdownlintignore/correct.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# header
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# header
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# header
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# header

test/test.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ test('glob linting works with failing files', async t => {
106106
t.fail();
107107
} catch (error) {
108108
t.deepEqual(error.stdout, '');
109-
t.deepEqual(error.stderr.match(errorPattern).length, 16);
109+
t.deepEqual(error.stderr.match(errorPattern).length, 17);
110110
}
111111
});
112112

@@ -166,7 +166,7 @@ test('glob linting with failing files has fewer errors when ignored by dir', asy
166166
t.fail();
167167
} catch (error) {
168168
t.deepEqual(error.stdout, '');
169-
t.deepEqual(error.stderr.match(errorPattern).length, 8);
169+
t.deepEqual(error.stderr.match(errorPattern).length, 9);
170170
}
171171
});
172172

@@ -178,7 +178,7 @@ test('glob linting with failing files has fewer errors when ignored by dir and a
178178
t.fail();
179179
} catch (error) {
180180
t.deepEqual(error.stdout, '');
181-
t.deepEqual(error.stderr.match(errorPattern).length, 8);
181+
t.deepEqual(error.stderr.match(errorPattern).length, 9);
182182
}
183183
});
184184

@@ -626,3 +626,22 @@ test('fixing errors with a glob yields fewer errors', async t => {
626626
fs.unlinkSync(fixSubFileC);
627627
}
628628
});
629+
630+
test('.markdownlintignore is applied correctly', async t => {
631+
try {
632+
await execa(
633+
path.resolve('..', 'markdownlint.js'), ['.'], {
634+
cwd: path.join(__dirname, 'markdownlintignore'),
635+
stripFinalNewline: false
636+
});
637+
t.fail();
638+
} catch (error) {
639+
const expected = [
640+
'incorrect.md:1 MD047/single-trailing-newline Files should end with a single newline character',
641+
'subdir/incorrect.markdown:1 MD047/single-trailing-newline Files should end with a single newline character',
642+
''
643+
].join('\n');
644+
t.deepEqual(error.stdout, '');
645+
t.deepEqual(error.stderr, expected);
646+
}
647+
});

0 commit comments

Comments
 (0)