UNPKG

4.88 kBJavaScriptView Raw
1(function() {
2 /*
3 Helpers for finding CoffeeLint config in standard locations, similar to how
4 JSHint does.
5 */
6 var expandModuleNames, extendConfig, findFile, findFileResults, fs, getConfig, loadJSON, loadNpmConfig, path, resolve, stripComments;
7
8 fs = require('fs');
9
10 path = require('path');
11
12 stripComments = require('strip-json-comments');
13
14 resolve = require('resolve').sync;
15
16 // Cache for findFile
17 findFileResults = {};
18
19 // Searches for a file with a specified name starting with 'dir' and going all
20 // the way up either until it finds the file or hits the root.
21 findFile = function(name, dir) {
22 var filename, parent;
23 dir = dir || process.cwd();
24 filename = path.normalize(path.join(dir, name));
25 if (findFileResults[filename]) {
26 return findFileResults[filename];
27 }
28 parent = path.resolve(dir, '../');
29 if (fs.existsSync(filename)) {
30 return findFileResults[filename] = filename;
31 } else if (dir === parent) {
32 return findFileResults[filename] = null;
33 } else {
34 return findFile(name, parent);
35 }
36 };
37
38 // Possibly find CoffeeLint configuration within a package.json file.
39 loadNpmConfig = function(dir) {
40 var fp, ref;
41 fp = findFile('package.json', dir);
42 if (fp) {
43 return (ref = loadJSON(fp)) != null ? ref.coffeelintConfig : void 0;
44 }
45 };
46
47 // Parse a JSON file gracefully.
48 loadJSON = function(filename) {
49 var e;
50 try {
51 return JSON.parse(stripComments(fs.readFileSync(filename).toString()));
52 } catch (error) {
53 e = error;
54 process.stderr.write(`Could not load JSON file '${filename}': ${e}`);
55 return null;
56 }
57 };
58
59 // Tries to find a configuration file in either project directory (if file is
60 // given), as either the package.json's 'coffeelintConfig' property, or a project
61 // specific 'coffeelint.json' or a global 'coffeelint.json' in the home
62 // directory.
63 getConfig = function(dir) {
64 var envs, home, npmConfig, projConfig;
65 if (process.env.COFFEELINT_CONFIG && fs.existsSync(process.env.COFFEELINT_CONFIG)) {
66 return loadJSON(process.env.COFFEELINT_CONFIG);
67 }
68 npmConfig = loadNpmConfig(dir);
69 if (npmConfig) {
70 return npmConfig;
71 }
72 projConfig = findFile('coffeelint.json', dir);
73 if (projConfig) {
74 return loadJSON(projConfig);
75 }
76 envs = process.env.USERPROFILE || process.env.HOME || process.env.HOMEPATH;
77 home = path.normalize(path.join(envs, 'coffeelint.json'));
78 if (fs.existsSync(home)) {
79 return loadJSON(home);
80 }
81 };
82
83 // configfinder is the only part of coffeelint that actually has the full
84 // filename and can accurately resolve module names. This will find all of the
85 // modules and expand them into full paths so that they can be found when the
86 // source and config are passed to `coffeelint.lint`
87 expandModuleNames = function(dir, config) {
88 var coffeelint, data, ruleName;
89 for (ruleName in config) {
90 data = config[ruleName];
91 if (!((data != null ? data.module : void 0) != null)) {
92 continue;
93 }
94 config[ruleName]._module = config[ruleName].module;
95 config[ruleName].module = resolve(data.module, {
96 basedir: dir,
97 extensions: ['.js', '.coffee', '.litcoffee', '.coffee.md']
98 });
99 }
100 coffeelint = config.coffeelint;
101 if ((coffeelint != null ? coffeelint.transforms : void 0) != null) {
102 coffeelint._transforms = coffeelint.transforms;
103 coffeelint.transforms = coffeelint.transforms.map(function(moduleName) {
104 return resolve(moduleName, {
105 basedir: dir,
106 extensions: ['.js', '.coffee', '.litcoffee', '.coffee.md']
107 });
108 });
109 }
110 if ((coffeelint != null ? coffeelint.coffeescript : void 0) != null) {
111 coffeelint._coffeescript = coffeelint.coffeescript;
112 coffeelint.coffeescript = resolve(coffeelint.coffeescript, {
113 basedir: dir,
114 extensions: ['.js', '.coffee', '.litcoffee', '.coffee.md']
115 });
116 }
117 return config;
118 };
119
120 extendConfig = function(config) {
121 var extendedConfig, parentConfig, rule, ruleName;
122 if (!config.extends) {
123 return config;
124 }
125 parentConfig = require(config.extends);
126 extendedConfig = {};
127 for (ruleName in config) {
128 rule = config[ruleName];
129 extendedConfig[ruleName] = rule;
130 }
131 for (ruleName in parentConfig) {
132 rule = parentConfig[ruleName];
133 extendedConfig[ruleName] = config[ruleName] || rule;
134 }
135 return extendedConfig;
136 };
137
138 exports.getConfig = function(filename = null) {
139 var config, dir;
140 if (filename) {
141 dir = path.dirname(path.resolve(filename));
142 } else {
143 dir = process.cwd();
144 }
145 config = getConfig(dir);
146 if (config) {
147 config = extendConfig(config);
148 config = expandModuleNames(dir, config);
149 }
150 return config;
151 };
152
153}).call(this);