linguist-js 2.1.4 → 2.3.1
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/dist/cli.js +13 -5
- package/dist/helpers/convert-glob.js +1 -1
- package/dist/helpers/convert-pcre.js +7 -4
- package/dist/helpers/read-file.js +5 -2
- package/dist/index.js +60 -28
- package/dist/types.d.ts +2 -0
- package/package.json +8 -8
- package/readme.md +7 -0
package/dist/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const VERSION = require('../package.json').version;
|
|
7
7
|
const commander_1 = require("commander");
|
|
8
8
|
const index_1 = __importDefault(require("./index"));
|
|
9
|
+
const walk_tree_1 = __importDefault(require("./helpers/walk-tree"));
|
|
9
10
|
const colouredMsg = ([r, g, b], msg) => `\u001B[${38};2;${r};${g};${b}m${msg}${'\u001b[0m'}`;
|
|
10
11
|
const hexToRgb = (hex) => [parseInt(hex.slice(1, 3), 16), parseInt(hex.slice(3, 5), 16), parseInt(hex.slice(5, 7), 16)];
|
|
11
12
|
commander_1.program
|
|
@@ -21,6 +22,7 @@ commander_1.program
|
|
|
21
22
|
.option('-q|--quick [bool]', 'Skip complex language analysis (alias for -{A|I|H|S}=false)', false)
|
|
22
23
|
.option('-V|--keepVendored [bool]', 'Prevent skipping over vendored/generated files', false)
|
|
23
24
|
.option('-B|--keepBinary [bool]', 'Prevent skipping over binary files', false)
|
|
25
|
+
.option('-r|--relativePaths [bool]', 'Convert absolute file paths to relative', false)
|
|
24
26
|
.option('-A|--checkAttributes [bool]', 'Force the checking of gitattributes files', true)
|
|
25
27
|
.option('-I|--checkIgnored [bool]', 'Force the checking of gitignore files', true)
|
|
26
28
|
.option('-H|--checkHeuristics [bool]', 'Apply heuristics to ambiguous languages', true)
|
|
@@ -51,16 +53,21 @@ if (args.analyze)
|
|
|
51
53
|
const root = args.analyze === true ? '.' : args.analyze;
|
|
52
54
|
const data = await (0, index_1.default)(root, args);
|
|
53
55
|
const { files, languages, unknown } = data;
|
|
56
|
+
// Get file count
|
|
57
|
+
const totalFiles = (0, walk_tree_1.default)(root).files.length;
|
|
54
58
|
// Print output
|
|
55
59
|
if (!args.json) {
|
|
56
60
|
const sortedEntries = Object.entries(languages.results).sort((a, b) => a[1].bytes < b[1].bytes ? +1 : -1);
|
|
57
61
|
const totalBytes = languages.bytes;
|
|
58
|
-
console.log(`\n Analysed ${files.bytes.toLocaleString()} B from ${files.count}
|
|
62
|
+
console.log(`\n Analysed ${files.bytes.toLocaleString()} B from ${totalFiles} files (${totalFiles - files.count} ignored) with linguist-js`);
|
|
59
63
|
console.log(`\n Language analysis results:`);
|
|
60
|
-
let
|
|
64
|
+
let count = 0;
|
|
65
|
+
if (sortedEntries.length === 0)
|
|
66
|
+
console.log(` None`);
|
|
67
|
+
// List parsed results
|
|
61
68
|
for (const [lang, { bytes, color }] of sortedEntries) {
|
|
62
69
|
const fmtd = {
|
|
63
|
-
index: (++
|
|
70
|
+
index: (++count).toString().padStart(2, ' '),
|
|
64
71
|
lang: lang.padEnd(24, ' '),
|
|
65
72
|
percent: (bytes / (totalBytes || 1) * 100).toFixed(2).padStart(5, ' '),
|
|
66
73
|
bytes: bytes.toLocaleString().padStart(10, ' '),
|
|
@@ -69,13 +76,14 @@ if (args.analyze)
|
|
|
69
76
|
console.log(` ${fmtd.index}. ${fmtd.icon} ${fmtd.lang} ${fmtd.percent}% ${fmtd.bytes} B`);
|
|
70
77
|
}
|
|
71
78
|
console.log(` Total: ${totalBytes.toLocaleString()} B`);
|
|
79
|
+
// List unknown files/extensions
|
|
72
80
|
if (unknown.bytes > 0) {
|
|
73
81
|
console.log(`\n Unknown files and extensions:`);
|
|
74
82
|
for (const [name, bytes] of Object.entries(unknown.filenames)) {
|
|
75
83
|
console.log(` '${name}': ${bytes.toLocaleString()} B`);
|
|
76
84
|
}
|
|
77
85
|
for (const [ext, bytes] of Object.entries(unknown.extensions)) {
|
|
78
|
-
console.log(` '
|
|
86
|
+
console.log(` '*${ext}': ${bytes.toLocaleString()} B`);
|
|
79
87
|
}
|
|
80
88
|
console.log(` Total: ${unknown.bytes.toLocaleString()} B`);
|
|
81
89
|
}
|
|
@@ -95,6 +103,6 @@ if (args.analyze)
|
|
|
95
103
|
}
|
|
96
104
|
})();
|
|
97
105
|
else {
|
|
98
|
-
console.log(`Welcome to linguist-js,
|
|
106
|
+
console.log(`Welcome to linguist-js, a JavaScript port of GitHub's language analyzer.`);
|
|
99
107
|
console.log(`Type 'linguist --help' for a list of commands.`);
|
|
100
108
|
}
|
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const glob_to_regexp_1 = __importDefault(require("glob-to-regexp"));
|
|
7
7
|
function parseGitGlob(path) {
|
|
8
|
-
const globPath = `**/${path}`.replace(/\[:(space|digit):\]
|
|
8
|
+
const globPath = `**/${path}`.replace(/\\/g, '/').replace(/\[:(space|digit):\]/g, (_, val) => `\\${val[0]}`);
|
|
9
9
|
return (0, glob_to_regexp_1.default)(globPath, { globstar: true, extended: true });
|
|
10
10
|
}
|
|
11
11
|
exports.default = parseGitGlob;
|
|
@@ -3,23 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
/** Convert a PCRE regex into JS. */
|
|
4
4
|
function pcre(regex) {
|
|
5
5
|
let finalRegex = regex;
|
|
6
|
+
const replace = (search, replace) => finalRegex = finalRegex.replace(search, replace);
|
|
6
7
|
const finalFlags = new Set();
|
|
7
8
|
// Convert inline flag declarations
|
|
8
9
|
const inlineMatches = regex.matchAll(/\?([a-z]):/g);
|
|
9
10
|
const startMatches = regex.matchAll(/\(\?([a-z]+)\)/g);
|
|
10
11
|
for (const [match, flags] of [...inlineMatches, ...startMatches]) {
|
|
11
|
-
|
|
12
|
+
replace(match, '');
|
|
12
13
|
[...flags].forEach(flag => finalFlags.add(flag));
|
|
13
14
|
}
|
|
14
|
-
// Remove invalid
|
|
15
|
-
|
|
15
|
+
// Remove invalid syntax
|
|
16
|
+
replace(/([*+]){2}/g, '$1');
|
|
17
|
+
replace(/\(\?>/g, '(?:');
|
|
16
18
|
// Remove start/end-of-file markers
|
|
17
19
|
if (/\\[AZ]/.test(finalRegex)) {
|
|
18
|
-
|
|
20
|
+
replace(/\\A/g, '^').replace(/\\Z/g, '$');
|
|
19
21
|
finalFlags.delete('m');
|
|
20
22
|
}
|
|
21
23
|
else
|
|
22
24
|
finalFlags.add('m');
|
|
25
|
+
// Return final regex
|
|
23
26
|
return RegExp(finalRegex, [...finalFlags].join(''));
|
|
24
27
|
}
|
|
25
28
|
exports.default = pcre;
|
|
@@ -4,12 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const fs_1 = __importDefault(require("fs"));
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Read part of a file on disc.
|
|
9
|
+
* @throws 'EPERM' if the file is not readable.
|
|
10
|
+
*/
|
|
8
11
|
async function readFile(filename, onlyFirstLine = false) {
|
|
9
12
|
const chunkSize = 100;
|
|
10
13
|
const stream = fs_1.default.createReadStream(filename, { highWaterMark: chunkSize });
|
|
11
14
|
let content = '';
|
|
12
|
-
for await (const data of stream) {
|
|
15
|
+
for await (const data of stream) { // may throw
|
|
13
16
|
content += data.toString();
|
|
14
17
|
if (onlyFirstLine && content.includes('\n')) {
|
|
15
18
|
return content.split(/\r?\n/)[0];
|
package/dist/index.js
CHANGED
|
@@ -14,8 +14,9 @@ const read_file_1 = __importDefault(require("./helpers/read-file"));
|
|
|
14
14
|
const convert_pcre_1 = __importDefault(require("./helpers/convert-pcre"));
|
|
15
15
|
const convert_glob_1 = __importDefault(require("./helpers/convert-glob"));
|
|
16
16
|
async function analyse(input, opts = {}) {
|
|
17
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
18
|
-
var
|
|
17
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
18
|
+
var _s, _t, _u;
|
|
19
|
+
const useRawContent = opts.fileContent !== undefined;
|
|
19
20
|
const langData = await (0, load_data_1.default)('languages.yml').then(js_yaml_1.default.load);
|
|
20
21
|
const vendorData = await (0, load_data_1.default)('vendor.yml').then(js_yaml_1.default.load);
|
|
21
22
|
const heuristicsData = await (0, load_data_1.default)('heuristics.yml').then(js_yaml_1.default.load);
|
|
@@ -34,7 +35,16 @@ async function analyse(input, opts = {}) {
|
|
|
34
35
|
opts.keepVendored ? [] : vendorData.map(path => RegExp(path)),
|
|
35
36
|
(_b = (_a = opts.ignoredFiles) === null || _a === void 0 ? void 0 : _a.map(path => (0, glob_to_regexp_1.default)('*' + path + '*', { extended: true }))) !== null && _b !== void 0 ? _b : [],
|
|
36
37
|
].flat();
|
|
37
|
-
let
|
|
38
|
+
let files, folders;
|
|
39
|
+
if (opts.fileContent) {
|
|
40
|
+
opts.fileContent = Array.isArray(opts.fileContent) ? opts.fileContent : [opts.fileContent];
|
|
41
|
+
files = [`${input}`];
|
|
42
|
+
folders = [''];
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const data = (0, walk_tree_1.default)(input !== null && input !== void 0 ? input : '.', ignoredFiles);
|
|
46
|
+
({ files, folders } = data);
|
|
47
|
+
}
|
|
38
48
|
// Apply aliases
|
|
39
49
|
opts = { checkIgnored: !opts.quick, checkAttributes: !opts.quick, checkHeuristics: !opts.quick, checkShebang: !opts.quick, ...opts };
|
|
40
50
|
// Ignore specific languages
|
|
@@ -50,7 +60,7 @@ async function analyse(input, opts = {}) {
|
|
|
50
60
|
const customIgnored = [];
|
|
51
61
|
const customBinary = [];
|
|
52
62
|
const customText = [];
|
|
53
|
-
if (!opts.quick) {
|
|
63
|
+
if (!useRawContent && !opts.quick) {
|
|
54
64
|
for (const folder of folders) {
|
|
55
65
|
// Skip if folder is marked in gitattributes
|
|
56
66
|
if (customIgnored.some(path => (0, convert_glob_1.default)(path).test(folder)))
|
|
@@ -69,7 +79,7 @@ async function analyse(input, opts = {}) {
|
|
|
69
79
|
const attributesData = await (0, read_file_1.default)(attributesFile);
|
|
70
80
|
const relPathToRegex = (path) => (0, convert_glob_1.default)(path).source.substr(1).replace(folder, '');
|
|
71
81
|
// Explicit text/binary associations
|
|
72
|
-
const contentTypeMatches = attributesData.matchAll(/^(\S+).*?(-?binary|-?text)/gm);
|
|
82
|
+
const contentTypeMatches = attributesData.matchAll(/^(\S+).*?(-?binary|-?text)(?!=auto)/gm);
|
|
73
83
|
for (const [_line, path, type] of contentTypeMatches) {
|
|
74
84
|
if (['text', '-binary'].includes(type))
|
|
75
85
|
customText.push(relPathToRegex(path));
|
|
@@ -97,7 +107,7 @@ async function analyse(input, opts = {}) {
|
|
|
97
107
|
}
|
|
98
108
|
}
|
|
99
109
|
// Check vendored files
|
|
100
|
-
if (!opts.keepVendored) {
|
|
110
|
+
if (!useRawContent && !opts.keepVendored) {
|
|
101
111
|
// Filter out any files that match a vendor file path
|
|
102
112
|
const matcher = (match) => RegExp(match.replace(/\/$/, '/.+$').replace(/^\.\//, ''));
|
|
103
113
|
files = files.filter(file => !customIgnored.some(pattern => matcher(pattern).test(file)));
|
|
@@ -110,27 +120,35 @@ async function analyse(input, opts = {}) {
|
|
|
110
120
|
}
|
|
111
121
|
const parent = !opts.childLanguages && result && langData[result].group || false;
|
|
112
122
|
fileAssociations[file].push(parent || result);
|
|
113
|
-
extensions[file] = path_1.default.extname(file);
|
|
123
|
+
extensions[file] = path_1.default.extname(file).toLowerCase();
|
|
114
124
|
};
|
|
115
125
|
const overridesArray = Object.entries(overrides);
|
|
116
126
|
// List all languages that could be associated with a given file
|
|
117
127
|
for (const file of files) {
|
|
118
|
-
|
|
128
|
+
let firstLine;
|
|
129
|
+
if (opts.fileContent) {
|
|
130
|
+
firstLine = (_f = (_e = (_d = opts.fileContent) === null || _d === void 0 ? void 0 : _d[files.indexOf(file)]) === null || _e === void 0 ? void 0 : _e.split('\n')[0]) !== null && _f !== void 0 ? _f : null;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
if (!fs_1.default.existsSync(file) || fs_1.default.lstatSync(file).isDirectory())
|
|
134
|
+
continue;
|
|
135
|
+
firstLine = await (0, read_file_1.default)(file, true).catch(() => null);
|
|
136
|
+
}
|
|
137
|
+
// Skip if file is unreadable
|
|
138
|
+
if (firstLine === null)
|
|
119
139
|
continue;
|
|
120
140
|
// Check shebang line for explicit classification
|
|
121
|
-
if (!opts.quick && opts.checkShebang) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
141
|
+
if (!opts.quick && opts.checkShebang && firstLine.startsWith('#!')) {
|
|
142
|
+
// Find matching interpreters
|
|
143
|
+
const matches = Object.entries(langData).filter(([, data]) => { var _a; return (_a = data.interpreters) === null || _a === void 0 ? void 0 : _a.some(interpreter => firstLine.match('\\b' + interpreter + '\\b')); });
|
|
144
|
+
if (matches.length) {
|
|
145
|
+
// Add explicitly-identified language
|
|
146
|
+
const forcedLang = matches[0][0];
|
|
147
|
+
addResult(file, forcedLang);
|
|
130
148
|
}
|
|
131
149
|
}
|
|
132
150
|
// Check override for manual language classification
|
|
133
|
-
if (!opts.quick && opts.checkAttributes) {
|
|
151
|
+
if (!useRawContent && !opts.quick && opts.checkAttributes) {
|
|
134
152
|
const match = overridesArray.find(item => RegExp(item[0]).test(file));
|
|
135
153
|
if (match) {
|
|
136
154
|
const forcedLang = match[1];
|
|
@@ -142,7 +160,7 @@ async function analyse(input, opts = {}) {
|
|
|
142
160
|
let skipExts = false;
|
|
143
161
|
for (const lang in langData) {
|
|
144
162
|
// Check if filename is a match
|
|
145
|
-
const matchesName = (
|
|
163
|
+
const matchesName = (_g = langData[lang].filenames) === null || _g === void 0 ? void 0 : _g.some(name => path_1.default.basename(file.toLowerCase()) === name.toLowerCase());
|
|
146
164
|
if (matchesName) {
|
|
147
165
|
addResult(file, lang);
|
|
148
166
|
skipExts = true;
|
|
@@ -151,7 +169,7 @@ async function analyse(input, opts = {}) {
|
|
|
151
169
|
if (!skipExts)
|
|
152
170
|
for (const lang in langData) {
|
|
153
171
|
// Check if extension is a match
|
|
154
|
-
const matchesExt = (
|
|
172
|
+
const matchesExt = (_h = langData[lang].extensions) === null || _h === void 0 ? void 0 : _h.some(ext => file.toLowerCase().endsWith(ext.toLowerCase()));
|
|
155
173
|
if (matchesExt)
|
|
156
174
|
addResult(file, lang);
|
|
157
175
|
}
|
|
@@ -162,7 +180,7 @@ async function analyse(input, opts = {}) {
|
|
|
162
180
|
// Narrow down file associations to the best fit
|
|
163
181
|
for (const file in fileAssociations) {
|
|
164
182
|
// Skip binary files
|
|
165
|
-
if (!opts.keepBinary) {
|
|
183
|
+
if (!useRawContent && !opts.keepBinary) {
|
|
166
184
|
const isCustomText = customText.some(path => RegExp(path).test(file));
|
|
167
185
|
const isCustomBinary = customBinary.some(path => RegExp(path).test(file));
|
|
168
186
|
const isBinaryExt = binary_extensions_1.default.some(ext => file.endsWith('.' + ext));
|
|
@@ -184,8 +202,9 @@ async function analyse(input, opts = {}) {
|
|
|
184
202
|
heuristic.language = heuristic.language[0];
|
|
185
203
|
}
|
|
186
204
|
// Make sure the results includes this language
|
|
205
|
+
const languageGroup = (_j = langData[heuristic.language]) === null || _j === void 0 ? void 0 : _j.group;
|
|
187
206
|
const matchesLang = fileAssociations[file].includes(heuristic.language);
|
|
188
|
-
const matchesParent =
|
|
207
|
+
const matchesParent = languageGroup && fileAssociations[file].includes(languageGroup);
|
|
189
208
|
if (!matchesLang && !matchesParent)
|
|
190
209
|
continue;
|
|
191
210
|
// Normalise heuristic data
|
|
@@ -196,7 +215,9 @@ async function analyse(input, opts = {}) {
|
|
|
196
215
|
if (heuristic.named_pattern)
|
|
197
216
|
normalise(heuristicsData.named_patterns[heuristic.named_pattern]);
|
|
198
217
|
// Check file contents and apply heuristic patterns
|
|
199
|
-
const fileContent = await (0, read_file_1.default)(file);
|
|
218
|
+
const fileContent = await (0, read_file_1.default)(file).catch(() => null);
|
|
219
|
+
if (fileContent === null)
|
|
220
|
+
continue;
|
|
200
221
|
if (!patterns.length || patterns.some(pattern => (0, convert_pcre_1.default)(pattern).test(fileContent))) {
|
|
201
222
|
results.files.results[file] = heuristic.language;
|
|
202
223
|
break;
|
|
@@ -204,10 +225,10 @@ async function analyse(input, opts = {}) {
|
|
|
204
225
|
}
|
|
205
226
|
}
|
|
206
227
|
// If no heuristics, assign a language
|
|
207
|
-
(
|
|
228
|
+
(_k = (_s = results.files.results)[file]) !== null && _k !== void 0 ? _k : (_s[file] = fileAssociations[file][0]);
|
|
208
229
|
}
|
|
209
230
|
// Skip specified categories
|
|
210
|
-
if ((
|
|
231
|
+
if ((_l = opts.categories) === null || _l === void 0 ? void 0 : _l.length) {
|
|
211
232
|
const categories = ['data', 'markup', 'programming', 'prose'];
|
|
212
233
|
const hiddenCategories = categories.filter(cat => !opts.categories.includes(cat));
|
|
213
234
|
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
@@ -224,25 +245,36 @@ async function analyse(input, opts = {}) {
|
|
|
224
245
|
}
|
|
225
246
|
}
|
|
226
247
|
}
|
|
248
|
+
// Convert paths to relative
|
|
249
|
+
if (!useRawContent && opts.relativePaths) {
|
|
250
|
+
const newMap = {};
|
|
251
|
+
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
252
|
+
let relPath = path_1.default.relative(process.cwd(), file).replace(/\\/g, '/');
|
|
253
|
+
if (!relPath.startsWith('../'))
|
|
254
|
+
relPath = './' + relPath;
|
|
255
|
+
newMap[relPath] = lang;
|
|
256
|
+
}
|
|
257
|
+
results.files.results = newMap;
|
|
258
|
+
}
|
|
227
259
|
// Load language bytes size
|
|
228
260
|
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
229
261
|
if (lang && !langData[lang])
|
|
230
262
|
continue;
|
|
231
|
-
const fileSize = fs_1.default.statSync(file).size;
|
|
263
|
+
const fileSize = (_p = (_o = (_m = opts.fileContent) === null || _m === void 0 ? void 0 : _m[files.indexOf(file)]) === null || _o === void 0 ? void 0 : _o.length) !== null && _p !== void 0 ? _p : fs_1.default.statSync(file).size;
|
|
232
264
|
results.files.bytes += fileSize;
|
|
233
265
|
// If no language found, add extension in other section
|
|
234
266
|
if (!lang) {
|
|
235
267
|
const ext = path_1.default.extname(file);
|
|
236
268
|
const unknownType = ext === '' ? 'filenames' : 'extensions';
|
|
237
269
|
const name = ext === '' ? path_1.default.basename(file) : ext;
|
|
238
|
-
(
|
|
270
|
+
(_q = (_t = results.unknown[unknownType])[name]) !== null && _q !== void 0 ? _q : (_t[name] = 0);
|
|
239
271
|
results.unknown[unknownType][name] += fileSize;
|
|
240
272
|
results.unknown.bytes += fileSize;
|
|
241
273
|
continue;
|
|
242
274
|
}
|
|
243
275
|
// Add language and bytes data to corresponding section
|
|
244
276
|
const { type } = langData[lang];
|
|
245
|
-
(
|
|
277
|
+
(_r = (_u = results.languages.results)[lang]) !== null && _r !== void 0 ? _r : (_u[lang] = { type, bytes: 0, color: langData[lang].color });
|
|
246
278
|
if (opts.childLanguages)
|
|
247
279
|
results.languages.results[lang].parent = langData[lang].group;
|
|
248
280
|
results.languages.results[lang].bytes += fileSize;
|
package/dist/types.d.ts
CHANGED
|
@@ -5,11 +5,13 @@ export declare type FilePath = string;
|
|
|
5
5
|
export declare type Bytes = Integer;
|
|
6
6
|
export declare type Integer = number;
|
|
7
7
|
export interface Options {
|
|
8
|
+
fileContent?: string | string[];
|
|
8
9
|
ignoredFiles?: string[];
|
|
9
10
|
ignoredLanguages?: Language[];
|
|
10
11
|
categories?: Category[];
|
|
11
12
|
keepVendored?: boolean;
|
|
12
13
|
keepBinary?: boolean;
|
|
14
|
+
relativePaths?: boolean;
|
|
13
15
|
childLanguages?: boolean;
|
|
14
16
|
quick?: boolean;
|
|
15
17
|
checkIgnored?: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "linguist-js",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "Analyse languages used in a folder. Powered by GitHub Linguist, although it doesn't need to be installed.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -37,18 +37,18 @@
|
|
|
37
37
|
"homepage": "https://github.com/Nixinova/Linguist#readme",
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"binary-extensions": "^2.2.0",
|
|
40
|
-
"commander": "^
|
|
41
|
-
"cross-fetch": "^3.1.
|
|
40
|
+
"commander": "^9.0.0",
|
|
41
|
+
"cross-fetch": "^3.1.5",
|
|
42
42
|
"glob-to-regexp": "~0.4.1",
|
|
43
43
|
"isbinaryfile": "^4.0.8",
|
|
44
44
|
"js-yaml": "^4.1.0",
|
|
45
45
|
"node-cache": "^5.1.2"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@types/glob-to-regexp": "ts4.
|
|
49
|
-
"@types/js-yaml": "ts4.
|
|
50
|
-
"@types/node": "ts4.
|
|
51
|
-
"deep-object-diff": "^1.1.
|
|
52
|
-
"typescript": "~4.
|
|
48
|
+
"@types/glob-to-regexp": "ts4.6",
|
|
49
|
+
"@types/js-yaml": "ts4.6",
|
|
50
|
+
"@types/node": "ts4.6",
|
|
51
|
+
"deep-object-diff": "^1.1.7",
|
|
52
|
+
"typescript": "~4.6.1-rc"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/readme.md
CHANGED
|
@@ -77,6 +77,7 @@ Running Linguist on this folder will return the following JSON:
|
|
|
77
77
|
### Notes
|
|
78
78
|
|
|
79
79
|
- File paths in the output use only forward slashes as delimiters, even on Windows.
|
|
80
|
+
- This tool does not work when offline.
|
|
80
81
|
- Do not rely on any language classification output from Linguist being unchanged between runs.
|
|
81
82
|
Language data is fetched each run from the latest classifications of [`github-linguist`](https://github.com/github/linguist).
|
|
82
83
|
This data is subject to change at any time and may change the results of a run even when using the same version of Linguist.
|
|
@@ -99,6 +100,8 @@ const { files, languages, unknown } = linguist(folder, options);
|
|
|
99
100
|
Analyse multiple folders using the syntax `"{folder1,folder2,...}"`.
|
|
100
101
|
- `opts` (optional; object):
|
|
101
102
|
An object containing analyser options.
|
|
103
|
+
- `fileContent` (string or string array):
|
|
104
|
+
Provides the file content associated with the file name(s) given as `entry` to analyse instead of reading from a folder on disk.
|
|
102
105
|
- `ignoredFiles` (string array):
|
|
103
106
|
A list of file path globs to explicitly ignore.
|
|
104
107
|
- `ignoredLanguages` (string array):
|
|
@@ -115,6 +118,8 @@ const { files, languages, unknown } = linguist(folder, options);
|
|
|
115
118
|
Whether to keep vendored files (dependencies, etc) (defaults to `false`).
|
|
116
119
|
- `keepBinary` (boolean):
|
|
117
120
|
Whether binary files should be included in the output (defaults to `false`).
|
|
121
|
+
- `relativePaths` (boolean):
|
|
122
|
+
Change the absolute file paths in the output to be relative to the current working directory (defaults to `false`).
|
|
118
123
|
- `checkAttributes` (boolean):
|
|
119
124
|
Force the checking of `.gitattributes` files (defaults to `true` unless `quick` is set).
|
|
120
125
|
- `checkIgnored` (boolean):
|
|
@@ -155,6 +160,8 @@ linguist --help
|
|
|
155
160
|
Whether to include vendored files (auto-generated files, dependencies folder, etc).
|
|
156
161
|
- `--keepBinary`:
|
|
157
162
|
Whether binary files should be excluded from the output.
|
|
163
|
+
- `--relativePaths`:
|
|
164
|
+
Change the absolute file paths in the output to be relative to the current working directory.
|
|
158
165
|
- `--checkAttributes`:
|
|
159
166
|
Force the checking of `.gitatributes` files (use alongside `--quick` to overwrite).
|
|
160
167
|
- `--checkIgnored`:
|