8000 feat(textlint): Add .textlintignore support (#748) · textlint/textlint@637e9a5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 637e9a5

Browse files
authored
feat(textlint): Add .textlintignore support (#748)
* fix(textlint): fix cwd option handling * feat(textlint): add textlintignore support * docs(README): update README * docs(website): add ignoring text guide
1 parent bb2c2ab commit 637e9a5

File tree

20 files changed

+234
-32
lines changed

20 files changed

+234
-32
lines changed

README.md

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -93,40 +93,43 @@ Run `textlint -h` for information on how to use the CLI.
9393
$ textlint [options] file.md [file|dir|glob*]
9494
9595
Options:
96-
-h, --help Show help.
97-
-c, --config path::String Use configuration from this file or sharable config.
98-
--init Create the config file if not existed. - default: false
99-
--fix Automatically fix problems
100-
--dry-run Enable dry-run mode for --fix. Only show result, don't change the file.
101-
--debug Outputs debugging information
102-
-v, --version Outputs the version number.
103-
96+
-h, --help Show help.
97+
-c, --config path::String Use configuration from this file or sharable config.
98+
--ignore-path path::String Specify path to a file containing patterns that describes files to ignore. - default: .textlintignore
99+
--init Create the config file if not existed. - default: false
100+
--fix Automatically fix problems
101+
--dry-run Enable dry-run mode for --fix. Only show result, don't change the file.
102+
--debug Outputs debugging information
103+
-v, --version Outputs the version number.
104+
104105
Using stdin:
105-
--stdin Lint text provided on <STDIN>. - default: false
106-
--stdin-filename String Specify filename to process STDIN as
107-
106+
--stdin Lint text provided on <STDIN>. - default: false
107+
--stdin-filename String Specify filename to process STDIN as
108+
108109
Output:
109110
-o, --output-file path::String Enable report to be written to a file.
110-
-f, --format String Use a specific output format.
111-
Available formatter : checkstyle, compact, jslint-xml, json, junit, pretty-error, stylish, table, tap, unix
112-
Available formatter for --fix: compats, diff, json, stylish
113-
--no-color Disable color in piped output.
114-
--quiet Report errors only. - default: false
115-
111+
-f, --format String Use a specific output format.
112+
Available formatter : checkstyle, compact, jslint-xml, json, junit, pretty-error, stylish, table, tap, unix
113+
Available formatter for --fix: compats, diff, json, stylish
114+
--no-color Disable color in piped output.
115+
--quiet Report errors only. - default: false
116+
116117
Specifying rules and plugins:
117-
--no-textlintrc Disable .textlintrc
118-
--plugin [String] Set plugin package name
119-
--rule [path::String] Set rule package name
120-
--preset [path::String] Set preset package name and load rules from preset package.
121-
--rulesdir [path::String] Set rules from this directory and set all default rules to off.
122-
118+
--no-textlintrc Disable .textlintrc
119+
--plugin [String] Set plugin package name
120+
--rule [String] Set rule package name
121+
--preset [String] Set preset package name and load rules from preset package.
122+
--rulesdir [path::String] Use additional rules from this directory
123+
123124
Caching:
124-
--cache Only check changed files - default: false
125+
--cache Only check changed files - default: false
125126
--cache-location path::String Path to the cache file or directory
126-
127+
127128
Experimental:
128-
--experimental Enable experimental flag.Some feature use on experimental.
129+
--experimental Enable experimental flag.Some feature use on experimental.
129130
--rules-base-directory path::String Set module base directory. textlint load modules(rules/presets/plugins) from the base directory.
131+
--parallel Lint files in parallel
132+
--max-concurrency Number maxConcurrency for --parallel
130133
131134
```
132135

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ title: Documentation
77

88
- [Getting Started](./getting-started.md)
99
- [Configuring](./configuring.md)
10+
- [Ignoring Text](./ignore.md)
1011

1112
## Developer Guide
1213

docs/ignore.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
id: ignore
3+
title: Ignoring Text
4+
---
5+
6+
Use `.textlintignore` to ignore certain files and folders completely.
7+
8+
Use [textlint-filter-rule-comments](https://github.com/textlint/textlint-filter-rule-comments) to ignore parts of files.
9+
10+
### Ignoring Files: .textlintignore
11+
12+
To exclude files from linting, create a `.textlintignore` file in the root of your project.
13+
14+
Example:
15+
16+
```
17+
# Ignore file:
18+
ignored.md
19+
20+
# Ignore by glob pattern:
21+
vendor/**
22+
```
23+
24+
:memo: textlint supports [glob pattern of node-glob](https://github.com/isaacs/node-glob#glob-primer).
25+
26+
You can also specify path to a file containing patterns that describes files to ignore by `--ignore-path` flag.
27+
28+
### Ignoring parts of files
29+
30+
[textlint-filter-rule-comments](https://github.com/textlint/textlint-filter-rule-comments) provide filtering function by using comments.
31+
32+
```
33+
<!-- textlint-disable -->
34+
35+
Disables all rules between comments
36+
37+
<!-- textlint-enable -->`
38+
```
39+
40+
Allow to short `textlint-filter-rule-comments` to `comments`.
41+
42+
Add filter rule name to `filters` field.
43+
44+
```json
45+
{
46+
"filters": {
47+
"comments": true
48+
}
49+
}
50+
```

packages/textlint/src/config/config.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ const defaultOptions = Object.freeze({
7878
// --cache : enable or disable
7979
cache: false,
8080
// --cache-location: cache file path
81-
cacheLocation: path.resolve(process.cwd(), ".textlintcache")
81+
cacheLocation: path.resolve(process.cwd(), ".textlintcache"),
82+
// --ignore-path: ".textlintignore" file path
83+
ignoreFile: path.resolve(process.cwd(), ".textlintignore")
8284
});
8385

8486
export interface ConfigStatics {
@@ -131,6 +133,8 @@ export interface ConfigAutoLoadingOptions {
131133
// FIXME: current working dir
132134
// It does not cover all working dir
133135
cwd?: string;
136+
// ".textlintignore" file path
137+
ignoreFile?: string | undefined;
134138
}
135139

136140
// Priority: CLI > Code options > config file
@@ -152,6 +156,7 @@ export class Config {
152156
color: boolean;
153157
cache: boolean;
154158
cacheLocation: string;
159+
ignoreFile: string | undefined;
155160

156161
/**
157162
* @return {string} rc config filename
@@ -193,6 +198,11 @@ export class Config {
193198
: defaultOptions.cacheLocation;
194199
// --rules-base-directory "other/node_modules"
195200
options.rulesBaseDirectory = cliOptions.rulesBaseDirectory || defaultOptions.rulesBaseDirectory;
201+
// --ignore-path="path/to/file"
202+
options.ignoreFile =
203+
cliOptions.ignorePath !== undefined
204+
? path.resolve(process.cwd(), cliOptions.ignorePath)
205+
: defaultOptions.ignoreFile;
196206
return this.initWithAutoLoading(options);
197207
}
198208

@@ -410,6 +420,10 @@ export class Config {
410420
*/
411421
this.cacheLocation = options.cacheLocation !== undefined ? options.cacheLocation : defaultOptions.cacheLocation;
412422
this._assertCacheLocation(this.cacheLocation);
423+
/**
424+
* @type {string}
425+
*/
426+
this.ignoreFile = options.ignoreFile !== undefined ? options.ignoreFile : defaultOptions.ignoreFile;
413427
}
414428

415429
private _assertCacheLocation(locationPath: string) {

packages/textlint/src/engine/textlint-engine-core.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ new TextLintEngine({
230230
const patterns = pathsToGlobPatterns(files, {
231231
extensions: this.textlintrcDescriptor.availableExtensions
232232
});
233-
const targetFiles = findFiles(patterns);
233+
const targetFiles = findFiles(patterns, { ignoreFilePath: this.config.ignoreFile });
234234
// Maybe, unAvailableFilePath should be warning.
235235
// But, The user can use glob pattern like `src/**/*` as arguments.
236236
// pathsToGlobPatterns not modified that pattern.

packages/textlint/src/options.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ export const options = optionator({
3232
description: "Use configuration from this file or sharable config.",
3333
example: "--config /path/to/.textlintrc"
3434
},
35+
{
36+
option: "ignore-path",
37+
type: "path::String",
38+
description: "Specify path to a file containing patterns that describes files to ignore.",
39+
default: ".textlintignore",
40+
example: "--ignore-path /path/to/.textlintignore"
41+
},
3542
{
3643
option: "init",
3744
type: "Boolean",

packages/textlint/src/parallel/lint-worker-master.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export const lintParallel = <T extends "lint" | "fix">(
4444
const patterns = pathsToGlobPatterns(files, {
4545
extensions: descriptor.availableExtensions
4646
});
47-
const targetFiles = findFiles(patterns);
47+
const targetFiles = findFiles(patterns, { ignoreFilePath: options.config.ignoreFile });
4848
const concurrency = options.concurrency !== undefined ? options.concurrency : os.cpus().length;
4949
const chunkSize = Math.min(MAX_CHUNK_SIZE, Math.ceil(targetFiles.length / concurrency));
5050
const promises: Promise<LintWorkerResults<typeof options["type"]>>[] = [];

packages/textlint/src/util/find-util.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ const pathToGlob = require("path-to-glob-pattern");
44
const glob = require("glob");
55
const path = require("path");
66
const fs = require("fs");
7+
const debug = require("debug")("textlint:find-util");
8+
const DEFAULT_IGNORE_PATTERNS = Object.freeze(["**/.git/**", "**/node_modules/**"]);
9+
export type FindFilesOptions = {
10+
cwd?: string;
11+
ignoreFilePath?: string;
12+
};
13+
const mapGitIgnorePatternTo = (base: string) => (ignore: string) => {
14+
if (ignore.startsWith("!")) {
15+
return "!" + path.posix.join(base, ignore.slice(1));
16+
}
17+
return path.posix.join(base, ignore);
18+
};
719
const isFile = (filePath: string) => {
820
try {
921
return fs.statSync(filePath).isFile();
@@ -29,11 +41,29 @@ export function pathsToGlobPatterns(
2941
/**
3042
* found files by glob pattern
3143
* @param {string[]} patterns
32-
* @param {{cwd?: string }} options
44+
* @param {FindFilesOptions} options
3345
* @returns {string[]} file path list
3446
*/
35-
export function findFiles(patterns: string[], options: { cwd?: string } = {}): string[] {
47+
export function findFiles(patterns: string[], options: FindFilesOptions = {}): string[] {
3648
const cwd = options.cwd || process.cwd();
49+
const ignoredPatterns: string[] = [];
50+
ignoredPatterns.push(...DEFAULT_IGNORE_PATTERNS);
51+
if (options.ignoreFilePath) {
52+
const baseDir = path.resolve(cwd, path.dirname(options.ignoreFilePath));
53+
const normalizeIgnoreFilePath = path.resolve(cwd, options.ignoreFilePath);
54+
debug("findFiles ignore baseDir: %s, normalizeIgnoreFilePath: %s", baseDir, normalizeIgnoreFilePath);
55+
if (fs.existsSync(normalizeIgnoreFilePath)) {
56+
const ignored = fs
57+
.readFileSync(normalizeIgnoreFilePath, "utf-8")
58+
.split(/\r?\n/)
59+
.filter((line: string) => !/^\s*$/.test(line) && !/^\s*#/.test(line))
60+
.map(mapGitIgnorePatternTo(baseDir));
61+
debug("ignored: %o", ignored);
62+
ignoredPatterns.push(...ignored);
63+
}
64+
}
65+
debug("search patterns: %o", patterns);
66+
debug("search ignore patterns: %o", ignoredPatterns);
3767
const files: string[] = [];
3868
const addFile = (filePath: string) => {
3969
if (files.indexOf(filePath) === -1) {
@@ -46,7 +76,10 @@ export function findFiles(patterns: string[], options: { cwd?: string } = {}): s
4676
addFile(fs.realpathSync(file));
4777
} else {
4878
glob.sync(pattern, {
49-
nodir: true
79+
cwd,
80+
absolute: true,
81+
nodir: true,
82+
ignore: ignoredPatterns
5083
}).forEach((filePath: string) => {
5184
// workaround for windows
5285
// https://github.com/isaacs/node-glob/issues/74#issuecomment-31548810
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ignored.md
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test.

0 commit comments

Comments
 (0)
0