linguist-js 2.1.3 → 2.3.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/dist/cli.js +26 -20
- package/dist/helpers/convert-glob.js +11 -0
- package/dist/helpers/read-file.js +5 -2
- package/dist/index.js +62 -32
- package/dist/types.d.ts +2 -0
- package/package.json +8 -8
- package/readme.md +7 -0
- package/dist/test.js +0 -3
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)
|
|
@@ -49,17 +51,23 @@ if (args.analyze)
|
|
|
49
51
|
(async () => {
|
|
50
52
|
// Fetch language data
|
|
51
53
|
const root = args.analyze === true ? '.' : args.analyze;
|
|
52
|
-
const
|
|
54
|
+
const data = await (0, index_1.default)(root, args);
|
|
55
|
+
const { files, languages, unknown } = data;
|
|
56
|
+
// Get file count
|
|
57
|
+
const totalFiles = (0, walk_tree_1.default)(root).files.length;
|
|
53
58
|
// Print output
|
|
54
59
|
if (!args.json) {
|
|
55
60
|
const sortedEntries = Object.entries(languages.results).sort((a, b) => a[1].bytes < b[1].bytes ? +1 : -1);
|
|
56
61
|
const totalBytes = languages.bytes;
|
|
57
|
-
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`);
|
|
58
63
|
console.log(`\n Language analysis results:`);
|
|
59
|
-
let
|
|
64
|
+
let count = 0;
|
|
65
|
+
if (sortedEntries.length === 0)
|
|
66
|
+
console.log(` None`);
|
|
67
|
+
// List parsed results
|
|
60
68
|
for (const [lang, { bytes, color }] of sortedEntries) {
|
|
61
69
|
const fmtd = {
|
|
62
|
-
index: (++
|
|
70
|
+
index: (++count).toString().padStart(2, ' '),
|
|
63
71
|
lang: lang.padEnd(24, ' '),
|
|
64
72
|
percent: (bytes / (totalBytes || 1) * 100).toFixed(2).padStart(5, ' '),
|
|
65
73
|
bytes: bytes.toLocaleString().padStart(10, ' '),
|
|
@@ -68,35 +76,33 @@ if (args.analyze)
|
|
|
68
76
|
console.log(` ${fmtd.index}. ${fmtd.icon} ${fmtd.lang} ${fmtd.percent}% ${fmtd.bytes} B`);
|
|
69
77
|
}
|
|
70
78
|
console.log(` Total: ${totalBytes.toLocaleString()} B`);
|
|
79
|
+
// List unknown files/extensions
|
|
71
80
|
if (unknown.bytes > 0) {
|
|
72
81
|
console.log(`\n Unknown files and extensions:`);
|
|
73
82
|
for (const [name, bytes] of Object.entries(unknown.filenames)) {
|
|
74
83
|
console.log(` '${name}': ${bytes.toLocaleString()} B`);
|
|
75
84
|
}
|
|
76
85
|
for (const [ext, bytes] of Object.entries(unknown.extensions)) {
|
|
77
|
-
console.log(` '
|
|
86
|
+
console.log(` '*${ext}': ${bytes.toLocaleString()} B`);
|
|
78
87
|
}
|
|
79
88
|
console.log(` Total: ${unknown.bytes.toLocaleString()} B`);
|
|
80
89
|
}
|
|
81
90
|
}
|
|
82
|
-
else {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
throw Error(`TraversalError: Key '${part}' cannot be found on output object.`);
|
|
90
|
-
nestedData = nestedData[part];
|
|
91
|
-
}
|
|
92
|
-
console.log(nestedData);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
console.log(JSON.stringify(data, null, 2).replace(/{\s+"type".+?}/sg, obj => obj.replace(/\n\s+/g, ' ')));
|
|
91
|
+
else if (args.tree) {
|
|
92
|
+
const treeParts = args.tree.split('.');
|
|
93
|
+
let nestedData = data;
|
|
94
|
+
for (const part of treeParts) {
|
|
95
|
+
if (!nestedData[part])
|
|
96
|
+
throw Error(`TraversalError: Key '${part}' cannot be found on output object.`);
|
|
97
|
+
nestedData = nestedData[part];
|
|
96
98
|
}
|
|
99
|
+
console.log(nestedData);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.dir(data, { depth: null });
|
|
97
103
|
}
|
|
98
104
|
})();
|
|
99
105
|
else {
|
|
100
|
-
console.log(`Welcome to linguist-js,
|
|
106
|
+
console.log(`Welcome to linguist-js, a JavaScript port of GitHub's language analyzer.`);
|
|
101
107
|
console.log(`Type 'linguist --help' for a list of commands.`);
|
|
102
108
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const glob_to_regexp_1 = __importDefault(require("glob-to-regexp"));
|
|
7
|
+
function parseGitGlob(path) {
|
|
8
|
+
const globPath = `**/${path}`.replace(/\\/g, '/').replace(/\[:(space|digit):\]/g, (_, val) => `\\${val[0]}`);
|
|
9
|
+
return (0, glob_to_regexp_1.default)(globPath, { globstar: true, extended: true });
|
|
10
|
+
}
|
|
11
|
+
exports.default = parseGitGlob;
|
|
@@ -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
|
@@ -12,10 +12,10 @@ const walk_tree_1 = __importDefault(require("./helpers/walk-tree"));
|
|
|
12
12
|
const load_data_1 = __importDefault(require("./helpers/load-data"));
|
|
13
13
|
const read_file_1 = __importDefault(require("./helpers/read-file"));
|
|
14
14
|
const convert_pcre_1 = __importDefault(require("./helpers/convert-pcre"));
|
|
15
|
-
const
|
|
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;
|
|
18
|
+
var _r, _s, _t;
|
|
19
19
|
const langData = await (0, load_data_1.default)('languages.yml').then(js_yaml_1.default.load);
|
|
20
20
|
const vendorData = await (0, load_data_1.default)('vendor.yml').then(js_yaml_1.default.load);
|
|
21
21
|
const heuristicsData = await (0, load_data_1.default)('heuristics.yml').then(js_yaml_1.default.load);
|
|
@@ -34,7 +34,16 @@ async function analyse(input, opts = {}) {
|
|
|
34
34
|
opts.keepVendored ? [] : vendorData.map(path => RegExp(path)),
|
|
35
35
|
(_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
36
|
].flat();
|
|
37
|
-
let
|
|
37
|
+
let files, folders;
|
|
38
|
+
if (opts.fileContent) {
|
|
39
|
+
opts.fileContent = Array.isArray(opts.fileContent) ? opts.fileContent : [opts.fileContent];
|
|
40
|
+
files = [`${input}`];
|
|
41
|
+
folders = [''];
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const data = (0, walk_tree_1.default)(input !== null && input !== void 0 ? input : '.', ignoredFiles);
|
|
45
|
+
({ files, folders } = data);
|
|
46
|
+
}
|
|
38
47
|
// Apply aliases
|
|
39
48
|
opts = { checkIgnored: !opts.quick, checkAttributes: !opts.quick, checkHeuristics: !opts.quick, checkShebang: !opts.quick, ...opts };
|
|
40
49
|
// Ignore specific languages
|
|
@@ -50,26 +59,26 @@ async function analyse(input, opts = {}) {
|
|
|
50
59
|
const customIgnored = [];
|
|
51
60
|
const customBinary = [];
|
|
52
61
|
const customText = [];
|
|
53
|
-
if (!opts.quick) {
|
|
62
|
+
if (!opts.fileContent && !opts.quick) {
|
|
54
63
|
for (const folder of folders) {
|
|
55
64
|
// Skip if folder is marked in gitattributes
|
|
56
|
-
if (customIgnored.some(path =>
|
|
65
|
+
if (customIgnored.some(path => (0, convert_glob_1.default)(path).test(folder)))
|
|
57
66
|
continue;
|
|
58
67
|
// Parse gitignores
|
|
59
68
|
const ignoresFile = path_1.default.join(folder, '.gitignore');
|
|
60
69
|
if (opts.checkIgnored && fs_1.default.existsSync(ignoresFile)) {
|
|
61
70
|
const ignoresData = await (0, read_file_1.default)(ignoresFile);
|
|
62
71
|
const ignoresList = ignoresData.split(/\r?\n/).filter(line => line.trim() && !line.startsWith('#'));
|
|
63
|
-
const ignoredPaths = ignoresList.map(path =>
|
|
64
|
-
customIgnored.push(...ignoredPaths
|
|
72
|
+
const ignoredPaths = ignoresList.map(path => (0, convert_glob_1.default)(path).source);
|
|
73
|
+
customIgnored.push(...ignoredPaths);
|
|
65
74
|
}
|
|
66
75
|
// Parse gitattributes
|
|
67
76
|
const attributesFile = path_1.default.join(folder, '.gitattributes');
|
|
68
77
|
if (opts.checkAttributes && fs_1.default.existsSync(attributesFile)) {
|
|
69
78
|
const attributesData = await (0, read_file_1.default)(attributesFile);
|
|
70
|
-
const relPathToRegex = (path) =>
|
|
79
|
+
const relPathToRegex = (path) => (0, convert_glob_1.default)(path).source.substr(1).replace(folder, '');
|
|
71
80
|
// Explicit text/binary associations
|
|
72
|
-
const contentTypeMatches = attributesData.matchAll(/^(\S+).*?(-?binary|-?text)/gm);
|
|
81
|
+
const contentTypeMatches = attributesData.matchAll(/^(\S+).*?(-?binary|-?text)(?!=auto)/gm);
|
|
73
82
|
for (const [_line, path, type] of contentTypeMatches) {
|
|
74
83
|
if (['text', '-binary'].includes(type))
|
|
75
84
|
customText.push(relPathToRegex(path));
|
|
@@ -90,14 +99,14 @@ async function analyse(input, opts = {}) {
|
|
|
90
99
|
if (overrideLang)
|
|
91
100
|
forcedLang = overrideLang[0];
|
|
92
101
|
}
|
|
93
|
-
const fullPath = folder +
|
|
102
|
+
const fullPath = folder + (0, convert_glob_1.default)(path).source.substr(1);
|
|
94
103
|
overrides[fullPath] = forcedLang;
|
|
95
104
|
}
|
|
96
105
|
}
|
|
97
106
|
}
|
|
98
107
|
}
|
|
99
108
|
// Check vendored files
|
|
100
|
-
if (!opts.keepVendored) {
|
|
109
|
+
if (!opts.fileContent && !opts.keepVendored) {
|
|
101
110
|
// Filter out any files that match a vendor file path
|
|
102
111
|
const matcher = (match) => RegExp(match.replace(/\/$/, '/.+$').replace(/^\.\//, ''));
|
|
103
112
|
files = files.filter(file => !customIgnored.some(pattern => matcher(pattern).test(file)));
|
|
@@ -115,22 +124,30 @@ async function analyse(input, opts = {}) {
|
|
|
115
124
|
const overridesArray = Object.entries(overrides);
|
|
116
125
|
// List all languages that could be associated with a given file
|
|
117
126
|
for (const file of files) {
|
|
118
|
-
|
|
127
|
+
let firstLine;
|
|
128
|
+
if (opts.fileContent) {
|
|
129
|
+
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;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
if (!fs_1.default.existsSync(file) || fs_1.default.lstatSync(file).isDirectory())
|
|
133
|
+
continue;
|
|
134
|
+
firstLine = await (0, read_file_1.default)(file, true).catch(() => null);
|
|
135
|
+
}
|
|
136
|
+
// Skip if file is unreadable
|
|
137
|
+
if (firstLine === null)
|
|
119
138
|
continue;
|
|
120
139
|
// Check shebang line for explicit classification
|
|
121
|
-
if (!opts.quick && opts.checkShebang) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
140
|
+
if (!opts.quick && opts.checkShebang && firstLine.startsWith('#!')) {
|
|
141
|
+
// Find matching interpreters
|
|
142
|
+
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')); });
|
|
143
|
+
if (matches.length) {
|
|
144
|
+
// Add explicitly-identified language
|
|
145
|
+
const forcedLang = matches[0][0];
|
|
146
|
+
addResult(file, forcedLang);
|
|
130
147
|
}
|
|
131
148
|
}
|
|
132
149
|
// Check override for manual language classification
|
|
133
|
-
if (!opts.quick && opts.checkAttributes) {
|
|
150
|
+
if (!opts.fileContent && !opts.quick && opts.checkAttributes) {
|
|
134
151
|
const match = overridesArray.find(item => RegExp(item[0]).test(file));
|
|
135
152
|
if (match) {
|
|
136
153
|
const forcedLang = match[1];
|
|
@@ -142,7 +159,7 @@ async function analyse(input, opts = {}) {
|
|
|
142
159
|
let skipExts = false;
|
|
143
160
|
for (const lang in langData) {
|
|
144
161
|
// Check if filename is a match
|
|
145
|
-
const matchesName = (
|
|
162
|
+
const matchesName = (_g = langData[lang].filenames) === null || _g === void 0 ? void 0 : _g.some(name => path_1.default.basename(file.toLowerCase()) === name.toLowerCase());
|
|
146
163
|
if (matchesName) {
|
|
147
164
|
addResult(file, lang);
|
|
148
165
|
skipExts = true;
|
|
@@ -151,7 +168,7 @@ async function analyse(input, opts = {}) {
|
|
|
151
168
|
if (!skipExts)
|
|
152
169
|
for (const lang in langData) {
|
|
153
170
|
// Check if extension is a match
|
|
154
|
-
const matchesExt = (
|
|
171
|
+
const matchesExt = (_h = langData[lang].extensions) === null || _h === void 0 ? void 0 : _h.some(ext => file.toLowerCase().endsWith(ext.toLowerCase()));
|
|
155
172
|
if (matchesExt)
|
|
156
173
|
addResult(file, lang);
|
|
157
174
|
}
|
|
@@ -162,7 +179,7 @@ async function analyse(input, opts = {}) {
|
|
|
162
179
|
// Narrow down file associations to the best fit
|
|
163
180
|
for (const file in fileAssociations) {
|
|
164
181
|
// Skip binary files
|
|
165
|
-
if (!opts.keepBinary) {
|
|
182
|
+
if (!opts.fileContent && !opts.keepBinary) {
|
|
166
183
|
const isCustomText = customText.some(path => RegExp(path).test(file));
|
|
167
184
|
const isCustomBinary = customBinary.some(path => RegExp(path).test(file));
|
|
168
185
|
const isBinaryExt = binary_extensions_1.default.some(ext => file.endsWith('.' + ext));
|
|
@@ -196,7 +213,9 @@ async function analyse(input, opts = {}) {
|
|
|
196
213
|
if (heuristic.named_pattern)
|
|
197
214
|
normalise(heuristicsData.named_patterns[heuristic.named_pattern]);
|
|
198
215
|
// Check file contents and apply heuristic patterns
|
|
199
|
-
const fileContent = await (0, read_file_1.default)(file);
|
|
216
|
+
const fileContent = await (0, read_file_1.default)(file).catch(() => null);
|
|
217
|
+
if (fileContent === null)
|
|
218
|
+
continue;
|
|
200
219
|
if (!patterns.length || patterns.some(pattern => (0, convert_pcre_1.default)(pattern).test(fileContent))) {
|
|
201
220
|
results.files.results[file] = heuristic.language;
|
|
202
221
|
break;
|
|
@@ -204,10 +223,10 @@ async function analyse(input, opts = {}) {
|
|
|
204
223
|
}
|
|
205
224
|
}
|
|
206
225
|
// If no heuristics, assign a language
|
|
207
|
-
(
|
|
226
|
+
(_j = (_r = results.files.results)[file]) !== null && _j !== void 0 ? _j : (_r[file] = fileAssociations[file][0]);
|
|
208
227
|
}
|
|
209
228
|
// Skip specified categories
|
|
210
|
-
if ((
|
|
229
|
+
if ((_k = opts.categories) === null || _k === void 0 ? void 0 : _k.length) {
|
|
211
230
|
const categories = ['data', 'markup', 'programming', 'prose'];
|
|
212
231
|
const hiddenCategories = categories.filter(cat => !opts.categories.includes(cat));
|
|
213
232
|
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
@@ -224,25 +243,36 @@ async function analyse(input, opts = {}) {
|
|
|
224
243
|
}
|
|
225
244
|
}
|
|
226
245
|
}
|
|
246
|
+
// Convert paths to relative
|
|
247
|
+
if (!opts.fileContent && opts.relativePaths) {
|
|
248
|
+
const newMap = {};
|
|
249
|
+
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
250
|
+
let relPath = path_1.default.relative(process.cwd(), file).replace(/\\/g, '/');
|
|
251
|
+
if (!relPath.startsWith('../'))
|
|
252
|
+
relPath = './' + relPath;
|
|
253
|
+
newMap[relPath] = lang;
|
|
254
|
+
}
|
|
255
|
+
results.files.results = newMap;
|
|
256
|
+
}
|
|
227
257
|
// Load language bytes size
|
|
228
258
|
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
229
259
|
if (lang && !langData[lang])
|
|
230
260
|
continue;
|
|
231
|
-
const fileSize = fs_1.default.statSync(file).size;
|
|
261
|
+
const fileSize = (_o = (_m = (_l = opts.fileContent) === null || _l === void 0 ? void 0 : _l[files.indexOf(file)]) === null || _m === void 0 ? void 0 : _m.length) !== null && _o !== void 0 ? _o : fs_1.default.statSync(file).size;
|
|
232
262
|
results.files.bytes += fileSize;
|
|
233
263
|
// If no language found, add extension in other section
|
|
234
264
|
if (!lang) {
|
|
235
265
|
const ext = path_1.default.extname(file);
|
|
236
266
|
const unknownType = ext === '' ? 'filenames' : 'extensions';
|
|
237
267
|
const name = ext === '' ? path_1.default.basename(file) : ext;
|
|
238
|
-
(
|
|
268
|
+
(_p = (_s = results.unknown[unknownType])[name]) !== null && _p !== void 0 ? _p : (_s[name] = 0);
|
|
239
269
|
results.unknown[unknownType][name] += fileSize;
|
|
240
270
|
results.unknown.bytes += fileSize;
|
|
241
271
|
continue;
|
|
242
272
|
}
|
|
243
273
|
// Add language and bytes data to corresponding section
|
|
244
274
|
const { type } = langData[lang];
|
|
245
|
-
(
|
|
275
|
+
(_q = (_t = results.languages.results)[lang]) !== null && _q !== void 0 ? _q : (_t[lang] = { type, bytes: 0, color: langData[lang].color });
|
|
246
276
|
if (opts.childLanguages)
|
|
247
277
|
results.languages.results[lang].parent = langData[lang].group;
|
|
248
278
|
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.
|
|
3
|
+
"version": "2.3.0",
|
|
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`:
|
package/dist/test.js
DELETED