editorconfig 0.15.2 → 1.0.0

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.
package/README.md CHANGED
@@ -1,12 +1,11 @@
1
1
  # EditorConfig JavaScript Core
2
2
 
3
- [![Build Status](https://travis-ci.org/editorconfig/editorconfig-core-js.svg?branch=master)](https://travis-ci.org/editorconfig/editorconfig-core-js)
4
- [![dependencies Status](https://david-dm.org/editorconfig/editorconfig-core-js/status.svg)](https://david-dm.org/editorconfig/editorconfig-core-js)
3
+ [![Tests](https://github.com/editorconfig/editorconfig-core-js/actions/workflows/node.js.yml/badge.svg)](https://github.com/editorconfig/editorconfig-core-js/actions/workflows/node.js.yml)
4
+ [![Coverage Status](https://coveralls.io/repos/github/editorconfig/editorconfig-core-js/badge.svg?branch=master)](https://coveralls.io/github/editorconfig/editorconfig-core-js?branch=master)
5
5
 
6
6
  The EditorConfig JavaScript core will provide the same functionality as the
7
7
  [EditorConfig C Core][] and [EditorConfig Python Core][].
8
8
 
9
-
10
9
  ## Installation
11
10
 
12
11
  You need [node][] to use this package.
@@ -25,33 +24,74 @@ $ npm install -g editorconfig
25
24
 
26
25
  ## Usage
27
26
 
28
- ### in Node.js:
29
-
30
- #### parse(filePath[, options])
27
+ ### Options
31
28
 
32
- options is an object with the following defaults:
29
+ Most of the API takes an `options` object, which has the following defaults:
33
30
 
34
31
  ```js
35
32
  {
36
33
  config: '.editorconfig',
37
34
  version: pkg.version,
38
- root: '/'
35
+ root: '/',
36
+ files: undefined,
37
+ cache: undefined,
39
38
  };
40
39
  ```
41
40
 
42
- Search for `.editorconfig` starting from the current directory to the root directory.
41
+ <dl>
42
+ <dt>config</dt>
43
+ <dd>The name of the config file to look for in the current and every parent
44
+ directory.</dd>
45
+
46
+ <dt>version</dt>
47
+ <dd>Which editorconfig spec version to use. Earlier versions had different
48
+ defaults.</dd>
49
+
50
+ <dt>root</dt>
51
+ <dd>What directory to stop processing in, even if we haven't found a file
52
+ containing root=true. Defaults to the root of the filesystem containing
53
+ `process.cwd()`.</dd>
54
+
55
+ <dt>files</dt>
56
+ <dd>Pass in an empty array, which will be filled with one object for each
57
+ config file processed. The objects will have the shape
58
+ `{filename: "[DIRECTORY]/.editorconfig", glob: "*"}`</dd>
59
+
60
+ <dt>cache</dt>
61
+ <dd>If you are going to process more than one file in the same project, pass
62
+ in a cache object. It must have `get(string): object|undefined` and
63
+ `set(string, object)` methods, like a JavaScript Map. A long-running
64
+ process might want to consider that this cache might grow over time,
65
+ and that the config files might change over time. However, we leave any
66
+ complexity of that nature to the caller, since there are so many different
67
+ approaches that might be taken based on latency, memory, and CPU trade-offs.
68
+ Note that some of the objects in the cache will be for files that did not
69
+ exist. Those objects will have a `notfound: true` property. All of the
70
+ objects will have a `name: string` property that contains the
71
+ fully-qualified file name of the config file and a `root: boolean` property
72
+ that describes if the config file had a `root=true` at the top. Any other
73
+ properties in the objects should be treated as opaque.</dd>
74
+ </dl>
75
+
76
+ ### in Node.js:
77
+
78
+ #### parse(filePath[, options])
79
+
80
+ Search for `.editorconfig` files starting from the current directory to the
81
+ root directory. Combine all of the sections whose section names match
82
+ filePath into a single object.
43
83
 
44
84
  Example:
45
85
 
46
86
  ```js
47
- var editorconfig = require('editorconfig');
48
- var path = require('path');
49
- var filePath = path.join(__dirname, '/sample.js');
50
- var promise = editorconfig.parse(filePath);
51
- promise.then(function onFulfilled(result) {
52
- console.log(result);
53
- });
87
+ const editorconfig = require('editorconfig');
88
+ const path = require('path');
54
89
 
90
+ const filePath = path.join(__dirname, 'sample.js');
91
+
92
+ (async () => {
93
+ console.log(await editorconfig.parse(filePath, {files: []}));
94
+ })();
55
95
  /*
56
96
  {
57
97
  indent_style: 'space',
@@ -62,6 +102,10 @@ promise.then(function onFulfilled(result) {
62
102
  insert_final_newline: true,
63
103
  tab_width: 2
64
104
  };
105
+ assert.deepEqual(files, [
106
+ { fileName: '[DIRECTORY]/.editorconfig', glob: '*' },
107
+ { fileName: '[DIRECTORY]/.editorconfig', glob: '*.js' }
108
+ ])
65
109
  */
66
110
  ```
67
111
 
@@ -69,44 +113,42 @@ promise.then(function onFulfilled(result) {
69
113
 
70
114
  Synchronous version of `editorconfig.parse()`.
71
115
 
72
- #### parseString(fileContent)
116
+ #### parseBuffer(fileContent)
73
117
 
74
- The `parse()` function above uses `parseString()` under the hood. If you have your file contents
75
- just pass it to `parseString()` and it'll return the same results as `parse()`.
118
+ The `parse()` function above uses `parseBuffer()` under the hood. If you have
119
+ the contents of a config file, and want to see what is being processed for
120
+ just that file rather than the full directory hierarchy, this might be useful.
76
121
 
77
- #### parseFromFiles(filePath, configs[, options])
122
+ #### parseString(fileContent)
78
123
 
79
- options is an object with the following defaults:
124
+ This is a thin wrapper around `parseBuffer()` for backward-compatibility.
125
+ Prefer `parseBuffer()` to avoid an unnecessary UTF8-to-UTF16-to-UTF8
126
+ conversion. Deprecated.
80
127
 
81
- ```js
82
- {
83
- config: '.editorconfig',
84
- version: pkg.version,
85
- root: '/'
86
- };
87
- ```
128
+ #### parseFromFiles(filePath, configs[, options])
88
129
 
89
- Specify the `.editorconfig`.
130
+ Low-level interface, which exists only for backward-compatibility. Deprecated.
90
131
 
91
132
  Example:
92
133
 
93
134
  ```js
94
- var editorconfig = require('editorconfig');
95
- var fs = require('fs');
96
- var path = require('path');
97
- var configPath = path.join(__dirname, '/.editorconfig');
98
- var configs = [
135
+ const editorconfig = require('editorconfig');
136
+ const fs = require('fs');
137
+ const path = require('path');
138
+
139
+ const configPath = path.join(__dirname, '.editorconfig');
140
+ const configs = [
99
141
  {
100
142
  name: configPath,
101
143
  contents: fs.readFileSync(configPath, 'utf8')
102
144
  }
103
145
  ];
104
- var filePath = path.join(__dirname, '/sample.js');
105
- var promise = editorconfig.parseFromFiles(filePath, configs);
106
- promise.then(function onFulfilled(result) {
107
- console.log(result)
108
- });
109
146
 
147
+ const filePath = path.join(__dirname, '/sample.js');
148
+
149
+ (async () => {
150
+ console.log(await editorconfig.parseFromFiles(filePath, Promise.resolve(configs)))
151
+ })();
110
152
  /*
111
153
  {
112
154
  indent_style: 'space',
@@ -122,25 +164,26 @@ promise.then(function onFulfilled(result) {
122
164
 
123
165
  #### parseFromFilesSync(filePath, configs[, options])
124
166
 
125
- Synchronous version of `editorconfig.parseFromFiles()`.
167
+ Synchronous version of `editorconfig.parseFromFiles()`. Deprecated.
126
168
 
127
169
  ### in Command Line
128
170
 
129
171
  ```bash
130
172
  $ ./bin/editorconfig
131
173
 
132
- Usage: editorconfig [OPTIONS] FILEPATH1 [FILEPATH2 FILEPATH3 ...]
133
-
134
- EditorConfig Node.js Core Version 0.11.4-development
135
-
136
- FILEPATH can be a hyphen (-) if you want path(s) to be read from stdin.
174
+ Usage: editorconfig [options] <FILEPATH...>
137
175
 
138
- Options:
176
+ Arguments:
177
+ FILEPATH Files to find configuration for. Can be a hyphen (-) if you
178
+ want path(s) to be read from stdin.
139
179
 
140
- -h, --help output usage information
141
- -V, --version output the version number
142
- -f <path> Specify conf filename other than ".editorconfig"
143
- -b <version> Specify version (used by devs to test compatibility)
180
+ Options:
181
+ -v, --version Display version information from the package
182
+ -f <path> Specify conf filename other than '.editorconfig'
183
+ -b <version> Specify version (used by devs to test compatibility)
184
+ --files Output file names that contributed to the configuration,
185
+ rather than the configuation itself
186
+ -h, --help display help for command
144
187
  ```
145
188
 
146
189
  Example:
@@ -154,6 +197,13 @@ tab_width=8
154
197
  trim_trailing_whitespace=sometimes
155
198
  ```
156
199
 
200
+ ```bash
201
+ $ ./bin/editorconfig --files /home/zoidberg/humans/anatomy.md
202
+ /home/zoidberg/.editorconfig [*]
203
+ /home/zoidberg/.editorconfig [*.md]
204
+ /home/zoidberg/humans/.editorconfig [*]
205
+ ```
206
+
157
207
  ## Development
158
208
 
159
209
  To install dependencies for this package run this in the package directory:
@@ -166,8 +216,7 @@ Next, run the following commands:
166
216
 
167
217
  ```bash
168
218
  $ npm run build
169
- $ npm run copy
170
- $ npm link ./dist
219
+ $ npm link
171
220
  ```
172
221
 
173
222
  The global editorconfig will now point to the files in your development
@@ -197,7 +246,7 @@ $ npm test
197
246
  To run the tests with increased verbosity (for debugging test failures):
198
247
 
199
248
  ```bash
200
- $ npm run-script test-verbose
249
+ $ npm run ci
201
250
  ```
202
251
 
203
252
  [EditorConfig C Core]: https://github.com/editorconfig/editorconfig-core
package/bin/editorconfig CHANGED
@@ -1,3 +1,6 @@
1
1
  #!/usr/bin/env node
2
- var cli = require('../src/cli')
3
- cli.default(process.argv)
2
+ var cli = require('../lib/cli')
3
+ cli.default(process.argv).catch(e => {
4
+ console.error(e)
5
+ process.exit(1)
6
+ })
package/lib/cli.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { type OutputConfiguration } from 'commander';
2
+ import * as editorconfig from './';
3
+ /**
4
+ * Command line interface for editorconfig. Pulled out into a separate module
5
+ * to make it easier to test.
6
+ *
7
+ * @param args Usually process.argv. Note that the first two parameters are
8
+ * usually 'node' and 'editorconfig'
9
+ * @param testing If testing, you may pass in a Commander OutputConfiguration
10
+ * so that you can capture stdout and stderror. If `testing` is provided,
11
+ * this routine will throw an error instead of calling `process.exit`.
12
+ * @returns An array of combined properties, one for each file argument.
13
+ */
14
+ export default function cli(args: string[], testing?: OutputConfiguration): Promise<editorconfig.Props[]>;
package/lib/cli.js ADDED
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const commander_1 = require("commander");
30
+ const editorconfig = __importStar(require("./"));
31
+ const package_json_1 = __importDefault(require("../package.json"));
32
+ /**
33
+ * Default output routine, goes to stdout.
34
+ *
35
+ * @param s String to output
36
+ */
37
+ function writeStdOut(s) {
38
+ process.stdout.write(s);
39
+ }
40
+ /**
41
+ * Command line interface for editorconfig. Pulled out into a separate module
42
+ * to make it easier to test.
43
+ *
44
+ * @param args Usually process.argv. Note that the first two parameters are
45
+ * usually 'node' and 'editorconfig'
46
+ * @param testing If testing, you may pass in a Commander OutputConfiguration
47
+ * so that you can capture stdout and stderror. If `testing` is provided,
48
+ * this routine will throw an error instead of calling `process.exit`.
49
+ * @returns An array of combined properties, one for each file argument.
50
+ */
51
+ async function cli(args, testing) {
52
+ const program = new commander_1.Command();
53
+ let writeOut = writeStdOut;
54
+ if (testing) {
55
+ if (testing.writeOut) {
56
+ // eslint-disable-next-line @typescript-eslint/unbound-method
57
+ writeOut = testing.writeOut;
58
+ }
59
+ program.configureOutput(testing);
60
+ program.exitOverride();
61
+ }
62
+ program.version('EditorConfig Node.js Core Version ' + package_json_1.default.version, '-v, --version', 'Display version information')
63
+ .showHelpAfterError()
64
+ .argument('<FILEPATH...>', 'Files to find configuration for. Can be a hyphen (-) if you want path(s) to be read from stdin.')
65
+ .option('-f <path>', 'Specify conf filename other than \'.editorconfig\'')
66
+ .option('-b <version>', 'Specify version (used by devs to test compatibility)')
67
+ .option('--files', 'Output file names that contributed to the configuration, rather than the configuation itself')
68
+ .parse(args);
69
+ const files = program.args;
70
+ const opts = program.opts();
71
+ const cache = new Map();
72
+ const visited = opts.files ?
73
+ files.map(() => []) :
74
+ undefined;
75
+ // Process sequentially so caching works
76
+ async function processAll() {
77
+ const p = [];
78
+ let i = 0;
79
+ for (const filePath of files) {
80
+ p.push(await editorconfig.parse(filePath, {
81
+ config: opts.f,
82
+ version: opts.b,
83
+ files: visited ? visited[i++] : undefined,
84
+ cache,
85
+ }));
86
+ }
87
+ return p;
88
+ }
89
+ return await processAll().then((parsed) => {
90
+ const header = parsed.length > 1;
91
+ parsed.forEach((props, i) => {
92
+ if (header) {
93
+ writeOut(`[${files[i]}]\n`);
94
+ }
95
+ if (visited) {
96
+ for (const v of visited[i]) {
97
+ writeOut(`${v.fileName} [${v.glob}]\n`);
98
+ }
99
+ }
100
+ else {
101
+ for (const [key, value] of Object.entries(props)) {
102
+ writeOut(`${key}=${String(value)}\n`);
103
+ }
104
+ }
105
+ });
106
+ return parsed;
107
+ });
108
+ }
109
+ exports.default = cli;
package/lib/index.d.ts ADDED
@@ -0,0 +1,105 @@
1
+ /// <reference types="node" />
2
+ import minimatch from 'minimatch';
3
+ export interface KnownProps {
4
+ end_of_line?: 'lf' | 'crlf' | 'unset';
5
+ indent_style?: 'tab' | 'space' | 'unset';
6
+ indent_size?: number | 'tab' | 'unset';
7
+ insert_final_newline?: true | false | 'unset';
8
+ tab_width?: number | 'unset';
9
+ trim_trailing_whitespace?: true | false | 'unset';
10
+ charset?: string | 'unset';
11
+ }
12
+ interface UnknownMap {
13
+ [index: string]: unknown;
14
+ }
15
+ export declare type Props = KnownProps & UnknownMap;
16
+ export interface ECFile {
17
+ name: string;
18
+ contents?: Buffer;
19
+ }
20
+ declare type SectionGlob = minimatch.Minimatch | null;
21
+ declare type GlobbedProps = [SectionName, Props, SectionGlob][];
22
+ export interface ProcessedFileConfig {
23
+ root: boolean;
24
+ name: string;
25
+ config: GlobbedProps;
26
+ notfound?: true;
27
+ }
28
+ export interface Visited {
29
+ fileName: string;
30
+ glob: string;
31
+ }
32
+ export interface Cache {
33
+ get(path: string): ProcessedFileConfig | undefined;
34
+ set(path: string, config: ProcessedFileConfig): this;
35
+ }
36
+ export interface ParseOptions {
37
+ config?: string;
38
+ version?: string;
39
+ root?: string;
40
+ files?: Visited[];
41
+ cache?: Cache;
42
+ }
43
+ export declare type SectionName = string | null;
44
+ export interface SectionBody {
45
+ [key: string]: string;
46
+ }
47
+ export declare type ParseStringResult = [SectionName, SectionBody][];
48
+ /**
49
+ * Parse a buffer using the faster one-ini WASM approach into something
50
+ * relatively easy to deal with in JS.
51
+ *
52
+ * @param data UTF8-encoded bytes.
53
+ * @returns Parsed contents. Will be truncated if there was a parse error.
54
+ */
55
+ export declare function parseBuffer(data: Buffer): ParseStringResult;
56
+ /**
57
+ * Parses a string. If possible, you should always use ParseBuffer instead,
58
+ * since this function does a UTF16-to-UTF8 conversion first.
59
+ *
60
+ * @param data String to parse.
61
+ * @returns Parsed contents. Will be truncated if there was a parse error.
62
+ * @deprecated Use {@link ParseBuffer} instead.
63
+ */
64
+ export declare function parseString(data: string): ParseStringResult;
65
+ /**
66
+ * Low-level interface, which exists only for backward-compatibility.
67
+ * Deprecated.
68
+ *
69
+ * @param filepath The name of the target file, relative to process.cwd().
70
+ * @param files A promise for a list of objects describing the files.
71
+ * @param options All options
72
+ * @returns The properties found for filepath
73
+ * @deprecated
74
+ */
75
+ export declare function parseFromFiles(filepath: string, files: Promise<ECFile[]>, options?: ParseOptions): Promise<Props>;
76
+ /**
77
+ * Low-level interface, which exists only for backward-compatibility.
78
+ * Deprecated.
79
+ *
80
+ * @param filepath The name of the target file, relative to process.cwd().
81
+ * @param files A list of objects describing the files.
82
+ * @param options All options
83
+ * @returns The properties found for filepath
84
+ * @deprecated
85
+ */
86
+ export declare function parseFromFilesSync(filepath: string, files: ECFile[], options?: ParseOptions): Props;
87
+ /**
88
+ * Find all of the properties from matching sections in config files in the
89
+ * same directory or toward the root of the filesystem.
90
+ *
91
+ * @param filepath The target file name, relative to process.cwd().
92
+ * @param options All options
93
+ * @returns Combined properties for the target file
94
+ */
95
+ export declare function parse(filepath: string, options?: ParseOptions): Promise<Props>;
96
+ /**
97
+ * Find all of the properties from matching sections in config files in the
98
+ * same directory or toward the root of the filesystem. Synchronous.
99
+ *
100
+ * @param filepath The target file name, relative to process.cwd().
101
+ * @param options All options
102
+ * @returns Combined properties for the target file
103
+ */
104
+ export declare function parseSync(filepath: string, options?: ParseOptions): Props;
105
+ export {};