editorconfig 0.13.3 → 0.15.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/CHANGELOG.md +4 -0
- package/README.md +1 -1
- package/bin/editorconfig +2 -41
- package/cli.d.ts +1 -0
- package/cli.js +44 -0
- package/index.d.ts +29 -0
- package/index.js +252 -0
- package/lib/fnmatch.d.ts +214 -0
- package/lib/fnmatch.js +1 -34
- package/lib/ini.d.ts +14 -0
- package/lib/ini.js +99 -63
- package/package.json +28 -13
- package/.gitmodules +0 -3
- package/editorconfig.js +0 -237
package/CHANGELOG.md
ADDED
package/README.md
CHANGED
package/bin/editorconfig
CHANGED
|
@@ -1,42 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var program = require("commander");
|
|
5
|
-
var Promise = require("bluebird");
|
|
6
|
-
|
|
7
|
-
var editorconfig = require("../editorconfig");
|
|
8
|
-
var package = require("../package.json");
|
|
9
|
-
|
|
10
|
-
program.version("EditorConfig Node.js Core Version " + package.version);
|
|
11
|
-
|
|
12
|
-
program
|
|
13
|
-
.usage([
|
|
14
|
-
"[OPTIONS] FILEPATH1 [FILEPATH2 FILEPATH3 ...]",
|
|
15
|
-
program._version,
|
|
16
|
-
"FILEPATH can be a hyphen (-) if you want path(s) to be read from stdin."
|
|
17
|
-
].join("\n\n "))
|
|
18
|
-
.option("-f <path>", "Specify conf filename other than \".editorconfig\"")
|
|
19
|
-
.option("-b <version>", "Specify version (used by devs to test compatibility)")
|
|
20
|
-
.option("-v, --version", "Display version information")
|
|
21
|
-
.parse(process.argv);
|
|
22
|
-
|
|
23
|
-
// Throw away the native -V flag in lieu of the one we've manually specified
|
|
24
|
-
// to adhere to testing requirements
|
|
25
|
-
program.options.shift();
|
|
26
|
-
|
|
27
|
-
var files = program.args;
|
|
28
|
-
|
|
29
|
-
if (!files.length) {
|
|
30
|
-
program.help();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
Promise.map(files, function(filePath) {
|
|
34
|
-
return editorconfig.parse(filePath, {config: program.F, version: program.B});
|
|
35
|
-
}).each(function(parsed, i, length) {
|
|
36
|
-
if (length > 1) {
|
|
37
|
-
console.log("[%s]", files[i]);
|
|
38
|
-
}
|
|
39
|
-
Object.keys(parsed).forEach(function(key) {
|
|
40
|
-
console.log(key + "=" + parsed[key]);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
2
|
+
var cli = require('../cli')
|
|
3
|
+
cli.default(process.argv)
|
package/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function cli(args: string[]): void;
|
package/cli.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// tslint:disable:no-console
|
|
4
|
+
var program = require("commander");
|
|
5
|
+
var editorconfig = require("./");
|
|
6
|
+
// tslint:disable-next-line:no-var-requires
|
|
7
|
+
var pkg = require('./package.json');
|
|
8
|
+
function cli(args) {
|
|
9
|
+
program.version('EditorConfig Node.js Core Version ' + pkg.version);
|
|
10
|
+
program
|
|
11
|
+
.usage([
|
|
12
|
+
'[OPTIONS] FILEPATH1 [FILEPATH2 FILEPATH3 ...]',
|
|
13
|
+
program._version,
|
|
14
|
+
'FILEPATH can be a hyphen (-) if you want path(s) to be read from stdin.',
|
|
15
|
+
].join('\n\n '))
|
|
16
|
+
.option('-f <path>', 'Specify conf filename other than \'.editorconfig\'')
|
|
17
|
+
.option('-b <version>', 'Specify version (used by devs to test compatibility)')
|
|
18
|
+
.option('-v, --version', 'Display version information')
|
|
19
|
+
.parse(args);
|
|
20
|
+
// Throw away the native -V flag in lieu of the one we've manually specified
|
|
21
|
+
// to adhere to testing requirements
|
|
22
|
+
program.options.shift();
|
|
23
|
+
var files = program.args;
|
|
24
|
+
if (!files.length) {
|
|
25
|
+
program.help();
|
|
26
|
+
}
|
|
27
|
+
files
|
|
28
|
+
.map(function (filePath) { return editorconfig.parse(filePath, {
|
|
29
|
+
config: program.F,
|
|
30
|
+
version: program.B,
|
|
31
|
+
}); })
|
|
32
|
+
.forEach(function (parsing, i, _a) {
|
|
33
|
+
var length = _a.length;
|
|
34
|
+
parsing.then(function (parsed) {
|
|
35
|
+
if (length > 1) {
|
|
36
|
+
console.log("[" + files[i] + "]");
|
|
37
|
+
}
|
|
38
|
+
Object.keys(parsed).forEach(function (key) {
|
|
39
|
+
console.log(key + "=" + parsed[key]);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
exports.default = cli;
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { parseString, ParseStringResult } from './lib/ini';
|
|
3
|
+
export { parseString };
|
|
4
|
+
export interface KnownProps {
|
|
5
|
+
end_of_line?: 'lf' | 'crlf' | 'unset';
|
|
6
|
+
indent_style?: 'tab' | 'space' | 'unset';
|
|
7
|
+
indent_size?: number | 'tab' | 'unset';
|
|
8
|
+
insert_final_newline?: true | false | 'unset';
|
|
9
|
+
tab_width?: number | 'unset';
|
|
10
|
+
trim_trailing_whitespace?: true | false | 'unset';
|
|
11
|
+
charset?: string | 'unset';
|
|
12
|
+
}
|
|
13
|
+
export interface ECFile {
|
|
14
|
+
name: string;
|
|
15
|
+
contents: string | Buffer;
|
|
16
|
+
}
|
|
17
|
+
export interface FileConfig {
|
|
18
|
+
name: string;
|
|
19
|
+
contents: ParseStringResult;
|
|
20
|
+
}
|
|
21
|
+
export interface ParseOptions {
|
|
22
|
+
config?: string;
|
|
23
|
+
version?: string;
|
|
24
|
+
root?: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function parseFromFiles(filepath: string, files: Promise<ECFile[]>, options?: ParseOptions): Promise<KnownProps>;
|
|
27
|
+
export declare function parseFromFilesSync(filepath: string, files: ECFile[], options?: ParseOptions): KnownProps;
|
|
28
|
+
export declare function parse(_filepath: string, _options?: ParseOptions): Promise<KnownProps>;
|
|
29
|
+
export declare function parseSync(_filepath: string, _options?: ParseOptions): KnownProps;
|
package/index.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
12
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
+
function step(op) {
|
|
15
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
+
while (_) try {
|
|
17
|
+
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
+
if (y = 0, t) op = [0, t.value];
|
|
19
|
+
switch (op[0]) {
|
|
20
|
+
case 0: case 1: t = op; break;
|
|
21
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
+
default:
|
|
25
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
+
if (t[2]) _.ops.pop();
|
|
30
|
+
_.trys.pop(); continue;
|
|
31
|
+
}
|
|
32
|
+
op = body.call(thisArg, _);
|
|
33
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
var fs = require("fs");
|
|
39
|
+
var path = require("path");
|
|
40
|
+
var semver = require("semver");
|
|
41
|
+
var minimatch = require("./lib/fnmatch");
|
|
42
|
+
var ini_1 = require("./lib/ini");
|
|
43
|
+
exports.parseString = ini_1.parseString;
|
|
44
|
+
// tslint:disable-next-line:no-var-requires
|
|
45
|
+
var pkg = require('./package.json');
|
|
46
|
+
var knownProps = {
|
|
47
|
+
end_of_line: true,
|
|
48
|
+
indent_style: true,
|
|
49
|
+
indent_size: true,
|
|
50
|
+
insert_final_newline: true,
|
|
51
|
+
trim_trailing_whitespace: true,
|
|
52
|
+
charset: true,
|
|
53
|
+
};
|
|
54
|
+
function fnmatch(filepath, glob) {
|
|
55
|
+
var matchOptions = { matchBase: true, dot: true, noext: true };
|
|
56
|
+
glob = glob.replace(/\*\*/g, '{*,**/**/**}');
|
|
57
|
+
return minimatch(filepath, glob, matchOptions);
|
|
58
|
+
}
|
|
59
|
+
function getConfigFileNames(filepath, options) {
|
|
60
|
+
var paths = [];
|
|
61
|
+
do {
|
|
62
|
+
filepath = path.dirname(filepath);
|
|
63
|
+
paths.push(path.join(filepath, options.config));
|
|
64
|
+
} while (filepath !== options.root);
|
|
65
|
+
return paths;
|
|
66
|
+
}
|
|
67
|
+
function processMatches(matches, version) {
|
|
68
|
+
// Set indent_size to 'tab' if indent_size is unspecified and
|
|
69
|
+
// indent_style is set to 'tab'.
|
|
70
|
+
if ('indent_style' in matches
|
|
71
|
+
&& matches.indent_style === 'tab'
|
|
72
|
+
&& !('indent_size' in matches)
|
|
73
|
+
&& semver.gte(version, '0.10.0')) {
|
|
74
|
+
matches.indent_size = 'tab';
|
|
75
|
+
}
|
|
76
|
+
// Set tab_width to indent_size if indent_size is specified and
|
|
77
|
+
// tab_width is unspecified
|
|
78
|
+
if ('indent_size' in matches
|
|
79
|
+
&& !('tab_width' in matches)
|
|
80
|
+
&& matches.indent_size !== 'tab') {
|
|
81
|
+
matches.tab_width = matches.indent_size;
|
|
82
|
+
}
|
|
83
|
+
// Set indent_size to tab_width if indent_size is 'tab'
|
|
84
|
+
if ('indent_size' in matches
|
|
85
|
+
&& 'tab_width' in matches
|
|
86
|
+
&& matches.indent_size === 'tab') {
|
|
87
|
+
matches.indent_size = matches.tab_width;
|
|
88
|
+
}
|
|
89
|
+
return matches;
|
|
90
|
+
}
|
|
91
|
+
function processOptions(options, filepath) {
|
|
92
|
+
if (options === void 0) { options = {}; }
|
|
93
|
+
return {
|
|
94
|
+
config: options.config || '.editorconfig',
|
|
95
|
+
version: options.version || pkg.version,
|
|
96
|
+
root: path.resolve(options.root || path.parse(filepath).root),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function buildFullGlob(pathPrefix, glob) {
|
|
100
|
+
switch (glob.indexOf('/')) {
|
|
101
|
+
case -1:
|
|
102
|
+
glob = '**/' + glob;
|
|
103
|
+
break;
|
|
104
|
+
case 0:
|
|
105
|
+
glob = glob.substring(1);
|
|
106
|
+
break;
|
|
107
|
+
default:
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
return path.join(pathPrefix, glob);
|
|
111
|
+
}
|
|
112
|
+
function extendProps(props, options) {
|
|
113
|
+
if (props === void 0) { props = {}; }
|
|
114
|
+
if (options === void 0) { options = {}; }
|
|
115
|
+
for (var key in options) {
|
|
116
|
+
if (options.hasOwnProperty(key)) {
|
|
117
|
+
var value = options[key];
|
|
118
|
+
var key2 = key.toLowerCase();
|
|
119
|
+
var value2 = value;
|
|
120
|
+
if (knownProps[key2]) {
|
|
121
|
+
value2 = value.toLowerCase();
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
value2 = JSON.parse(value);
|
|
125
|
+
}
|
|
126
|
+
catch (e) { }
|
|
127
|
+
if (typeof value === 'undefined' || value === null) {
|
|
128
|
+
// null and undefined are values specific to JSON (no special meaning
|
|
129
|
+
// in editorconfig) & should just be returned as regular strings.
|
|
130
|
+
value2 = String(value);
|
|
131
|
+
}
|
|
132
|
+
props[key2] = value2;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return props;
|
|
136
|
+
}
|
|
137
|
+
function parseFromConfigs(configs, filepath, options) {
|
|
138
|
+
return processMatches(configs
|
|
139
|
+
.reverse()
|
|
140
|
+
.reduce(function (matches, file) {
|
|
141
|
+
var pathPrefix = path.dirname(file.name);
|
|
142
|
+
file.contents.forEach(function (section) {
|
|
143
|
+
var glob = section[0];
|
|
144
|
+
var options2 = section[1];
|
|
145
|
+
if (!glob) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
var fullGlob = buildFullGlob(pathPrefix, glob);
|
|
149
|
+
if (!fnmatch(filepath, fullGlob)) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
matches = extendProps(matches, options2);
|
|
153
|
+
});
|
|
154
|
+
return matches;
|
|
155
|
+
}, {}), options.version);
|
|
156
|
+
}
|
|
157
|
+
function getConfigsForFiles(files) {
|
|
158
|
+
var configs = [];
|
|
159
|
+
for (var i in files) {
|
|
160
|
+
if (files.hasOwnProperty(i)) {
|
|
161
|
+
var file = files[i];
|
|
162
|
+
var contents = ini_1.parseString(file.contents);
|
|
163
|
+
configs.push({
|
|
164
|
+
name: file.name,
|
|
165
|
+
contents: contents,
|
|
166
|
+
});
|
|
167
|
+
if ((contents[0][1].root || '').toLowerCase() === 'true') {
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return configs;
|
|
173
|
+
}
|
|
174
|
+
function readConfigFiles(filepaths) {
|
|
175
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
176
|
+
return __generator(this, function (_a) {
|
|
177
|
+
return [2 /*return*/, Promise.all(filepaths.map(function (name) { return new Promise(function (resolve) {
|
|
178
|
+
fs.readFile(name, 'utf8', function (err, data) {
|
|
179
|
+
resolve({
|
|
180
|
+
name: name,
|
|
181
|
+
contents: err ? '' : data,
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
}); }))];
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function readConfigFilesSync(filepaths) {
|
|
189
|
+
var files = [];
|
|
190
|
+
var file;
|
|
191
|
+
filepaths.forEach(function (filepath) {
|
|
192
|
+
try {
|
|
193
|
+
file = fs.readFileSync(filepath, 'utf8');
|
|
194
|
+
}
|
|
195
|
+
catch (e) {
|
|
196
|
+
file = '';
|
|
197
|
+
}
|
|
198
|
+
files.push({
|
|
199
|
+
name: filepath,
|
|
200
|
+
contents: file,
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
return files;
|
|
204
|
+
}
|
|
205
|
+
function opts(filepath, options) {
|
|
206
|
+
if (options === void 0) { options = {}; }
|
|
207
|
+
var resolvedFilePath = path.resolve(filepath);
|
|
208
|
+
return [
|
|
209
|
+
resolvedFilePath,
|
|
210
|
+
processOptions(options, resolvedFilePath),
|
|
211
|
+
];
|
|
212
|
+
}
|
|
213
|
+
function parseFromFiles(filepath, files, options) {
|
|
214
|
+
if (options === void 0) { options = {}; }
|
|
215
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
216
|
+
var _a, resolvedFilePath, processedOptions;
|
|
217
|
+
return __generator(this, function (_b) {
|
|
218
|
+
_a = opts(filepath, options), resolvedFilePath = _a[0], processedOptions = _a[1];
|
|
219
|
+
return [2 /*return*/, files.then(getConfigsForFiles)
|
|
220
|
+
.then(function (configs) { return parseFromConfigs(configs, resolvedFilePath, processedOptions); })];
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
exports.parseFromFiles = parseFromFiles;
|
|
225
|
+
function parseFromFilesSync(filepath, files, options) {
|
|
226
|
+
if (options === void 0) { options = {}; }
|
|
227
|
+
var _a = opts(filepath, options), resolvedFilePath = _a[0], processedOptions = _a[1];
|
|
228
|
+
return parseFromConfigs(getConfigsForFiles(files), resolvedFilePath, processedOptions);
|
|
229
|
+
}
|
|
230
|
+
exports.parseFromFilesSync = parseFromFilesSync;
|
|
231
|
+
function parse(_filepath, _options) {
|
|
232
|
+
if (_options === void 0) { _options = {}; }
|
|
233
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
234
|
+
var _a, resolvedFilePath, processedOptions, filepaths;
|
|
235
|
+
return __generator(this, function (_b) {
|
|
236
|
+
_a = opts(_filepath, _options), resolvedFilePath = _a[0], processedOptions = _a[1];
|
|
237
|
+
filepaths = getConfigFileNames(resolvedFilePath, processedOptions);
|
|
238
|
+
return [2 /*return*/, readConfigFiles(filepaths)
|
|
239
|
+
.then(getConfigsForFiles)
|
|
240
|
+
.then(function (configs) { return parseFromConfigs(configs, resolvedFilePath, processedOptions); })];
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
exports.parse = parse;
|
|
245
|
+
function parseSync(_filepath, _options) {
|
|
246
|
+
if (_options === void 0) { _options = {}; }
|
|
247
|
+
var _a = opts(_filepath, _options), resolvedFilePath = _a[0], processedOptions = _a[1];
|
|
248
|
+
var filepaths = getConfigFileNames(resolvedFilePath, processedOptions);
|
|
249
|
+
var files = readConfigFilesSync(filepaths);
|
|
250
|
+
return parseFromConfigs(getConfigsForFiles(files), resolvedFilePath, processedOptions);
|
|
251
|
+
}
|
|
252
|
+
exports.parseSync = parseSync;
|
package/lib/fnmatch.d.ts
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// Type definitions for Minimatch 3.0
|
|
2
|
+
// Project: https://github.com/isaacs/minimatch
|
|
3
|
+
// Definitions by: vvakame <https://github.com/vvakame>
|
|
4
|
+
// Shant Marouti <https://github.com/shantmarouti>
|
|
5
|
+
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Tests a path against the pattern using the options.
|
|
9
|
+
*/
|
|
10
|
+
declare function M(target: string, pattern: string, options?: M.IOptions): boolean;
|
|
11
|
+
|
|
12
|
+
declare namespace M {
|
|
13
|
+
/**
|
|
14
|
+
* Match against the list of files, in the style of fnmatch or glob.
|
|
15
|
+
* If nothing is matched, and options.nonull is set,
|
|
16
|
+
* then return a list containing the pattern itself.
|
|
17
|
+
*/
|
|
18
|
+
function match(list: string[], pattern: string, options?: IOptions): string[];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Returns a function that tests its supplied argument, suitable for use with Array.filter
|
|
22
|
+
*/
|
|
23
|
+
function filter(pattern: string, options?: IOptions): (element: string, indexed: number, array: string[]) => boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Make a regular expression object from the pattern.
|
|
27
|
+
*/
|
|
28
|
+
function makeRe(pattern: string, options?: IOptions): RegExp;
|
|
29
|
+
|
|
30
|
+
var Minimatch: IMinimatchStatic;
|
|
31
|
+
|
|
32
|
+
interface IOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Dump a ton of stuff to stderr.
|
|
35
|
+
*
|
|
36
|
+
* @default false
|
|
37
|
+
*/
|
|
38
|
+
debug?: boolean;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Do not expand {a,b} and {1..3} brace sets.
|
|
42
|
+
*
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
nobrace?: boolean;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Disable ** matching against multiple folder names.
|
|
49
|
+
*
|
|
50
|
+
* @default false
|
|
51
|
+
*/
|
|
52
|
+
noglobstar?: boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Allow patterns to match filenames starting with a period,
|
|
56
|
+
* even if the pattern does not explicitly have a period in that spot.
|
|
57
|
+
*
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
dot?: boolean;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Disable "extglob" style patterns like +(a|b).
|
|
64
|
+
*
|
|
65
|
+
* @default false
|
|
66
|
+
*/
|
|
67
|
+
noext?: boolean;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Perform a case-insensitive match.
|
|
71
|
+
*
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
74
|
+
nocase?: boolean;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* When a match is not found by minimatch.match,
|
|
78
|
+
* return a list containing the pattern itself if this option is set.
|
|
79
|
+
* Otherwise, an empty list is returned if there are no matches.
|
|
80
|
+
*
|
|
81
|
+
* @default false
|
|
82
|
+
*/
|
|
83
|
+
nonull?: boolean;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* If set, then patterns without slashes will be matched against
|
|
87
|
+
* the basename of the path if it contains slashes.
|
|
88
|
+
*
|
|
89
|
+
* @default false
|
|
90
|
+
*/
|
|
91
|
+
matchBase?: boolean;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Suppress the behavior of treating #
|
|
95
|
+
* at the start of a pattern as a comment.
|
|
96
|
+
*
|
|
97
|
+
* @default false
|
|
98
|
+
*/
|
|
99
|
+
nocomment?: boolean;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Suppress the behavior of treating a leading ! character as negation.
|
|
103
|
+
*
|
|
104
|
+
* @default false
|
|
105
|
+
*/
|
|
106
|
+
nonegate?: boolean;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Returns from negate expressions the same as if they were not negated.
|
|
110
|
+
* (Ie, true on a hit, false on a miss.)
|
|
111
|
+
*
|
|
112
|
+
* @default false
|
|
113
|
+
*/
|
|
114
|
+
flipNegate?: boolean;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface IMinimatchStatic {
|
|
118
|
+
new(pattern: string, options?: IOptions): IMinimatch;
|
|
119
|
+
prototype: IMinimatch;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
interface IMinimatch {
|
|
123
|
+
/**
|
|
124
|
+
* The original pattern the minimatch object represents.
|
|
125
|
+
*/
|
|
126
|
+
pattern: string;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The options supplied to the constructor.
|
|
130
|
+
*/
|
|
131
|
+
options: IOptions;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A 2-dimensional array of regexp or string expressions.
|
|
135
|
+
*/
|
|
136
|
+
set: any[][]; // (RegExp | string)[][]
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* A single regular expression expressing the entire pattern.
|
|
140
|
+
* Created by the makeRe method.
|
|
141
|
+
*/
|
|
142
|
+
regexp: RegExp;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* True if the pattern is negated.
|
|
146
|
+
*/
|
|
147
|
+
negate: boolean;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* True if the pattern is a comment.
|
|
151
|
+
*/
|
|
152
|
+
comment: boolean;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* True if the pattern is ""
|
|
156
|
+
*/
|
|
157
|
+
empty: boolean;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Generate the regexp member if necessary, and return it.
|
|
161
|
+
* Will return false if the pattern is invalid.
|
|
162
|
+
*/
|
|
163
|
+
makeRe(): RegExp; // regexp or boolean
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Return true if the filename matches the pattern, or false otherwise.
|
|
167
|
+
*/
|
|
168
|
+
match(fname: string): boolean;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Take a /-split filename, and match it against a single row in the regExpSet.
|
|
172
|
+
* This method is mainly for internal use, but is exposed so that it can be used
|
|
173
|
+
* by a glob-walker that needs to avoid excessive filesystem calls.
|
|
174
|
+
*/
|
|
175
|
+
matchOne(files: string[], pattern: string[], partial: boolean): boolean;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Deprecated. For internal use.
|
|
179
|
+
*
|
|
180
|
+
* @private
|
|
181
|
+
*/
|
|
182
|
+
debug(): void;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Deprecated. For internal use.
|
|
186
|
+
*
|
|
187
|
+
* @private
|
|
188
|
+
*/
|
|
189
|
+
make(): void;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Deprecated. For internal use.
|
|
193
|
+
*
|
|
194
|
+
* @private
|
|
195
|
+
*/
|
|
196
|
+
parseNegate(): void;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Deprecated. For internal use.
|
|
200
|
+
*
|
|
201
|
+
* @private
|
|
202
|
+
*/
|
|
203
|
+
braceExpand(pattern: string, options: IOptions): void;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Deprecated. For internal use.
|
|
207
|
+
*
|
|
208
|
+
* @private
|
|
209
|
+
*/
|
|
210
|
+
parse(pattern: string, isSub?: boolean): void;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export = M;
|
package/lib/fnmatch.js
CHANGED
|
@@ -1,37 +1,10 @@
|
|
|
1
1
|
// Based on minimatch.js by isaacs <https://npmjs.org/package/minimatch>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
var platform = typeof process === "object" ? process.platform : "win32"
|
|
4
4
|
|
|
5
5
|
if (module) module.exports = minimatch
|
|
6
6
|
else exports.minimatch = minimatch
|
|
7
7
|
|
|
8
|
-
if (!require) {
|
|
9
|
-
require = function (id) {
|
|
10
|
-
switch (id) {
|
|
11
|
-
case "sigmund": return function sigmund (obj) {
|
|
12
|
-
return JSON.stringify(obj)
|
|
13
|
-
}
|
|
14
|
-
case "path": return { basename: function (f) {
|
|
15
|
-
f = f.split(/[\/\\]/)
|
|
16
|
-
var e = f.pop()
|
|
17
|
-
if (!e) e = f.pop()
|
|
18
|
-
return e
|
|
19
|
-
}}
|
|
20
|
-
case "lru-cache": return function LRUCache () {
|
|
21
|
-
// not quite an LRU, but still space-limited.
|
|
22
|
-
var cache = {}
|
|
23
|
-
var cnt = 0
|
|
24
|
-
this.set = function (k, v) {
|
|
25
|
-
cnt ++
|
|
26
|
-
if (cnt >= 100) cache = {}
|
|
27
|
-
cache[k] = v
|
|
28
|
-
}
|
|
29
|
-
this.get = function (k) { return cache[k] }
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
8
|
minimatch.Minimatch = Minimatch
|
|
36
9
|
|
|
37
10
|
var LRU = require("lru-cache")
|
|
@@ -1072,9 +1045,3 @@
|
|
|
1072
1045
|
function regExpEscape (s) {
|
|
1073
1046
|
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
|
|
1074
1047
|
}
|
|
1075
|
-
|
|
1076
|
-
})( typeof require === "function" ? require : null,
|
|
1077
|
-
this,
|
|
1078
|
-
typeof module === "object" ? module : null,
|
|
1079
|
-
typeof process === "object" ? process.platform : "win32"
|
|
1080
|
-
)
|
package/lib/ini.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { URL } from 'url';
|
|
3
|
+
/**
|
|
4
|
+
* Parses an .ini file
|
|
5
|
+
* @param file The location of the .ini file
|
|
6
|
+
*/
|
|
7
|
+
export declare function parse(file: string | number | Buffer | URL): Promise<[string | null, SectionBody][]>;
|
|
8
|
+
export declare function parseSync(file: string | number | Buffer | URL): [string | null, SectionBody][];
|
|
9
|
+
export declare type SectionName = string | null;
|
|
10
|
+
export interface SectionBody {
|
|
11
|
+
[key: string]: string;
|
|
12
|
+
}
|
|
13
|
+
export declare type ParseStringResult = Array<[SectionName, SectionBody]>;
|
|
14
|
+
export declare function parseString(data: string): ParseStringResult;
|
package/lib/ini.js
CHANGED
|
@@ -1,63 +1,99 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
1
|
+
"use strict";
|
|
2
|
+
// Based on iniparser by shockie <https://npmjs.org/package/iniparser>
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (_) try {
|
|
18
|
+
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [0, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
var fs = require("fs");
|
|
40
|
+
/**
|
|
41
|
+
* define the possible values:
|
|
42
|
+
* section: [section]
|
|
43
|
+
* param: key=value
|
|
44
|
+
* comment: ;this is a comment
|
|
45
|
+
*/
|
|
46
|
+
var regex = {
|
|
47
|
+
section: /^\s*\[(([^#;]|\\#|\\;)+)\]\s*([#;].*)?$/,
|
|
48
|
+
param: /^\s*([\w\.\-\_]+)\s*[=:]\s*(.*?)\s*([#;].*)?$/,
|
|
49
|
+
comment: /^\s*[#;].*$/,
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Parses an .ini file
|
|
53
|
+
* @param file The location of the .ini file
|
|
54
|
+
*/
|
|
55
|
+
function parse(file) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
57
|
+
return __generator(this, function (_a) {
|
|
58
|
+
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
59
|
+
fs.readFile(file, 'utf8', function (err, data) {
|
|
60
|
+
if (err) {
|
|
61
|
+
reject(err);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
resolve(parseString(data));
|
|
65
|
+
});
|
|
66
|
+
})];
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
exports.parse = parse;
|
|
71
|
+
function parseSync(file) {
|
|
72
|
+
return parseString(fs.readFileSync(file, 'utf8'));
|
|
73
|
+
}
|
|
74
|
+
exports.parseSync = parseSync;
|
|
75
|
+
function parseString(data) {
|
|
76
|
+
var sectionBody = {};
|
|
77
|
+
var sectionName = null;
|
|
78
|
+
var value = [[sectionName, sectionBody]];
|
|
79
|
+
var lines = data.split(/\r\n|\r|\n/);
|
|
80
|
+
lines.forEach(function (line) {
|
|
81
|
+
var match;
|
|
82
|
+
if (regex.comment.test(line)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (regex.param.test(line)) {
|
|
86
|
+
match = line.match(regex.param);
|
|
87
|
+
sectionBody[match[1]] =
|
|
88
|
+
match[2];
|
|
89
|
+
}
|
|
90
|
+
else if (regex.section.test(line)) {
|
|
91
|
+
match = line.match(regex.section);
|
|
92
|
+
sectionName = match[1];
|
|
93
|
+
sectionBody = {};
|
|
94
|
+
value.push([sectionName, sectionBody]);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
exports.parseString = parseString;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "editorconfig",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "EditorConfig File Locator and Interpreter for Node.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"editorconfig",
|
|
7
7
|
"core"
|
|
8
8
|
],
|
|
9
|
-
"main": "
|
|
9
|
+
"main": "index.js",
|
|
10
10
|
"bin": {
|
|
11
11
|
"editorconfig": "bin/editorconfig"
|
|
12
12
|
},
|
|
@@ -20,10 +20,19 @@
|
|
|
20
20
|
"lib": "./lib"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
23
|
+
"clean": "rimraf dist",
|
|
24
|
+
"prebuild": "npm run clean",
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"pretest": "npm run lint && npm run build && npm run copy && cmake .",
|
|
27
|
+
"test": "ctest .",
|
|
28
|
+
"pretest:ci": "npm run pretest",
|
|
29
|
+
"test:ci": "ctest -VV --output-on-failure .",
|
|
30
|
+
"lint": "npm run eclint && npm run tslint",
|
|
31
|
+
"eclint": "eclint check --indent_size ignore \"src/**\"",
|
|
32
|
+
"tslint": "tslint --project tslint.json",
|
|
33
|
+
"copy": "cpy package.json .npmignore LICENSE README.md CHANGELOG.md dist && cpy src/bin/* dist/bin && cpy src/lib/fnmatch*.* dist/lib",
|
|
34
|
+
"prepub": "npm run lint && npm run build && npm run copy",
|
|
35
|
+
"pub": "npm publish ./dist"
|
|
27
36
|
},
|
|
28
37
|
"repository": {
|
|
29
38
|
"type": "git",
|
|
@@ -33,15 +42,21 @@
|
|
|
33
42
|
"author": "EditorConfig Team",
|
|
34
43
|
"license": "MIT",
|
|
35
44
|
"dependencies": {
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
45
|
+
"@types/commander": "^2.11.0",
|
|
46
|
+
"@types/semver": "^5.4.0",
|
|
47
|
+
"commander": "^2.11.0",
|
|
48
|
+
"lru-cache": "^4.1.1",
|
|
49
|
+
"semver": "^5.4.1",
|
|
40
50
|
"sigmund": "^1.0.1"
|
|
41
51
|
},
|
|
42
52
|
"devDependencies": {
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
53
|
+
"@types/mocha": "^2.2.43",
|
|
54
|
+
"cpy-cli": "^1.0.1",
|
|
55
|
+
"eclint": "^2.4.3",
|
|
56
|
+
"mocha": "^4.0.1",
|
|
57
|
+
"rimraf": "^2.6.2",
|
|
58
|
+
"should": "^13.1.2",
|
|
59
|
+
"tslint": "^5.7.0",
|
|
60
|
+
"typescript": "^2.5.3"
|
|
46
61
|
}
|
|
47
62
|
}
|
package/.gitmodules
DELETED
package/editorconfig.js
DELETED
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
var Promise = require('bluebird');
|
|
2
|
-
var fs = require('fs');
|
|
3
|
-
var os = require('os');
|
|
4
|
-
var path = require('path');
|
|
5
|
-
var semver = require('semver');
|
|
6
|
-
var util = require('util');
|
|
7
|
-
var whenReadFile = Promise.promisify(fs.readFile);
|
|
8
|
-
|
|
9
|
-
var iniparser = require('./lib/ini');
|
|
10
|
-
var minimatch = require('./lib/fnmatch');
|
|
11
|
-
var pkg = require('./package.json');
|
|
12
|
-
|
|
13
|
-
var knownProps = [
|
|
14
|
-
'end_of_line',
|
|
15
|
-
'indent_style',
|
|
16
|
-
'indent_size',
|
|
17
|
-
'insert_final_newline',
|
|
18
|
-
'trim_trailing_whitespace',
|
|
19
|
-
'charset'
|
|
20
|
-
].reduce(function (set, prop) {
|
|
21
|
-
set[prop] = true;
|
|
22
|
-
return set;
|
|
23
|
-
}, {});
|
|
24
|
-
|
|
25
|
-
function fnmatch(filepath, glob) {
|
|
26
|
-
var matchOptions = {matchBase: true, dot: true, noext: true};
|
|
27
|
-
glob = glob.replace(/\*\*/g, '{*,**/**/**}');
|
|
28
|
-
return minimatch(filepath, glob, matchOptions);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function getConfigFileNames(filepath, options) {
|
|
32
|
-
var paths = [];
|
|
33
|
-
do {
|
|
34
|
-
filepath = path.dirname(filepath);
|
|
35
|
-
paths.push(path.join(filepath, options.config));
|
|
36
|
-
} while (filepath !== options.root);
|
|
37
|
-
return paths;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function getFilepathRoot(filepath) {
|
|
41
|
-
if (path.parse !== undefined) {
|
|
42
|
-
// Node.js >= 0.11.15
|
|
43
|
-
return path.parse(filepath).root;
|
|
44
|
-
}
|
|
45
|
-
if (os.platform() === 'win32') {
|
|
46
|
-
return path.resolve(filepath).match(/^(\\\\[^\\]+\\)?[^\\]+\\/)[0];
|
|
47
|
-
}
|
|
48
|
-
return '/';
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function processMatches(matches, version) {
|
|
52
|
-
// Set indent_size to "tab" if indent_size is unspecified and
|
|
53
|
-
// indent_style is set to "tab".
|
|
54
|
-
if ("indent_style" in matches && matches.indent_style === "tab" &&
|
|
55
|
-
!("indent_size" in matches) && semver.gte(version, "0.10.0")) {
|
|
56
|
-
matches.indent_size = "tab";
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Set tab_width to indent_size if indent_size is specified and
|
|
60
|
-
// tab_width is unspecified
|
|
61
|
-
if ("indent_size" in matches && !("tab_width" in matches) &&
|
|
62
|
-
matches.indent_size !== "tab")
|
|
63
|
-
matches.tab_width = matches.indent_size;
|
|
64
|
-
|
|
65
|
-
// Set indent_size to tab_width if indent_size is "tab"
|
|
66
|
-
if("indent_size" in matches && "tab_width" in matches &&
|
|
67
|
-
matches.indent_size === "tab")
|
|
68
|
-
matches.indent_size = matches.tab_width;
|
|
69
|
-
|
|
70
|
-
return matches;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function processOptions(options, filepath) {
|
|
74
|
-
options = options || {};
|
|
75
|
-
return {
|
|
76
|
-
config: options.config || '.editorconfig',
|
|
77
|
-
version: options.version || pkg.version,
|
|
78
|
-
root: path.resolve(options.root || getFilepathRoot(filepath))
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function buildFullGlob(pathPrefix, glob) {
|
|
83
|
-
switch (glob.indexOf('/')) {
|
|
84
|
-
case -1: glob = "**/" + glob; break;
|
|
85
|
-
case 0: glob = glob.substring(1); break;
|
|
86
|
-
}
|
|
87
|
-
return path.join(pathPrefix, glob);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function extendProps(props, options) {
|
|
91
|
-
for (var key in options) {
|
|
92
|
-
var value = options[key];
|
|
93
|
-
key = key.toLowerCase();
|
|
94
|
-
if (knownProps[key]) {
|
|
95
|
-
value = value.toLowerCase();
|
|
96
|
-
}
|
|
97
|
-
try {
|
|
98
|
-
value = JSON.parse(value);
|
|
99
|
-
} catch(e) {}
|
|
100
|
-
if (typeof value === 'undefined' || value === null) {
|
|
101
|
-
// null and undefined are values specific to JSON (no special meaning
|
|
102
|
-
// in editorconfig) & should just be returned as regular strings.
|
|
103
|
-
value = String(value);
|
|
104
|
-
}
|
|
105
|
-
props[key] = value;
|
|
106
|
-
}
|
|
107
|
-
return props;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function parseFromFiles(filepath, files, options) {
|
|
111
|
-
return getConfigsForFiles(files).then(function (configs) {
|
|
112
|
-
return configs.reverse();
|
|
113
|
-
}).reduce(function (matches, file) {
|
|
114
|
-
var pathPrefix = path.dirname(file.name);
|
|
115
|
-
file.contents.forEach(function (section) {
|
|
116
|
-
var glob = section[0], options = section[1];
|
|
117
|
-
if (!glob) return;
|
|
118
|
-
var fullGlob = buildFullGlob(pathPrefix, glob);
|
|
119
|
-
if (!fnmatch(filepath, fullGlob)) return;
|
|
120
|
-
matches = extendProps(matches, options);
|
|
121
|
-
});
|
|
122
|
-
return matches;
|
|
123
|
-
}, {}).then(function (matches) {
|
|
124
|
-
return processMatches(matches, options.version);
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function parseFromFilesSync(filepath, files, options) {
|
|
129
|
-
var configs = getConfigsForFilesSync(files);
|
|
130
|
-
configs.reverse();
|
|
131
|
-
var matches = {};
|
|
132
|
-
configs.forEach(function(config) {
|
|
133
|
-
var pathPrefix = path.dirname(config.name);
|
|
134
|
-
config.contents.forEach(function(section) {
|
|
135
|
-
var glob = section[0], options = section[1];
|
|
136
|
-
if (!glob) return;
|
|
137
|
-
var fullGlob = buildFullGlob(pathPrefix, glob);
|
|
138
|
-
if (!fnmatch(filepath, fullGlob)) return;
|
|
139
|
-
matches = extendProps(matches, options);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
return processMatches(matches, options.version);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function StopReduce(array) {
|
|
146
|
-
this.array = array;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
StopReduce.prototype = Object.create(Error.prototype);
|
|
150
|
-
|
|
151
|
-
function getConfigsForFiles(files) {
|
|
152
|
-
return Promise.reduce(files, function (configs, file) {
|
|
153
|
-
var contents = iniparser.parseString(file.contents);
|
|
154
|
-
configs.push({
|
|
155
|
-
name: file.name,
|
|
156
|
-
contents: contents
|
|
157
|
-
});
|
|
158
|
-
if ((contents[0][1].root || '').toLowerCase() === 'true') {
|
|
159
|
-
return Promise.reject(new StopReduce(configs));
|
|
160
|
-
}
|
|
161
|
-
return configs;
|
|
162
|
-
}, []).catch(StopReduce, function (stop) {
|
|
163
|
-
return stop.array;
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function getConfigsForFilesSync(files) {
|
|
168
|
-
var configs = [];
|
|
169
|
-
for (var i in files) {
|
|
170
|
-
var file = files[i];
|
|
171
|
-
var contents = iniparser.parseString(file.contents);
|
|
172
|
-
configs.push({
|
|
173
|
-
name: file.name,
|
|
174
|
-
contents: contents
|
|
175
|
-
});
|
|
176
|
-
if ((contents[0][1].root || '').toLowerCase() === 'true') {
|
|
177
|
-
break;
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
return configs;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function readConfigFiles(filepaths) {
|
|
184
|
-
return Promise.map(filepaths, function (path) {
|
|
185
|
-
return whenReadFile(path, 'utf-8').catch(function () {
|
|
186
|
-
return '';
|
|
187
|
-
}).then(function (contents) {
|
|
188
|
-
return {name: path, contents: contents};
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function readConfigFilesSync(filepaths) {
|
|
194
|
-
var files = [];
|
|
195
|
-
var file;
|
|
196
|
-
filepaths.forEach(function(filepath) {
|
|
197
|
-
try {
|
|
198
|
-
file = fs.readFileSync(filepath, 'utf8');
|
|
199
|
-
} catch (e) {
|
|
200
|
-
file = '';
|
|
201
|
-
}
|
|
202
|
-
files.push({name: filepath, contents: file});
|
|
203
|
-
});
|
|
204
|
-
return files;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
module.exports.parseFromFiles = function (filepath, files, options) {
|
|
208
|
-
return new Promise (function (resolve, reject) {
|
|
209
|
-
filepath = path.resolve(filepath);
|
|
210
|
-
options = processOptions(options, filepath);
|
|
211
|
-
resolve(parseFromFiles(filepath, files, options));
|
|
212
|
-
});
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
module.exports.parseFromFilesSync = function (filepath, files, options) {
|
|
216
|
-
filepath = path.resolve(filepath);
|
|
217
|
-
options = processOptions(options, filepath);
|
|
218
|
-
return parseFromFilesSync(filepath, files, options);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
module.exports.parse = function (filepath, options) {
|
|
222
|
-
return new Promise (function (resolve, reject) {
|
|
223
|
-
filepath = path.resolve(filepath);
|
|
224
|
-
options = processOptions(options, filepath);
|
|
225
|
-
var filepaths = getConfigFileNames(filepath, options);
|
|
226
|
-
var files = readConfigFiles(filepaths);
|
|
227
|
-
resolve(parseFromFiles(filepath, files, options));
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
module.exports.parseSync = function (filepath, options) {
|
|
232
|
-
filepath = path.resolve(filepath);
|
|
233
|
-
options = processOptions(options, filepath);
|
|
234
|
-
var filepaths = getConfigFileNames(filepath, options);
|
|
235
|
-
var files = readConfigFilesSync(filepaths);
|
|
236
|
-
return parseFromFilesSync(filepath, files, options);
|
|
237
|
-
};
|