linguist-js 2.9.2 → 3.0.0-pre
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/bin/index.js +1 -1
- package/dist/analyser/classifiers/byAttributes.d.ts +3 -0
- package/dist/analyser/classifiers/byAttributes.js +13 -0
- package/dist/analyser/classifiers/byExtension.d.ts +3 -0
- package/dist/analyser/classifiers/byExtension.js +31 -0
- package/dist/analyser/classifiers/byFilename.d.ts +3 -0
- package/dist/analyser/classifiers/byFilename.js +10 -0
- package/dist/analyser/classifiers/byHeuristics.d.ts +3 -0
- package/dist/analyser/classifiers/byHeuristics.js +67 -0
- package/dist/analyser/classifiers/byModeline.d.ts +3 -0
- package/dist/analyser/classifiers/byModeline.js +22 -0
- package/dist/analyser/classifiers/byShebang.d.ts +3 -0
- package/dist/analyser/classifiers/byShebang.js +27 -0
- package/dist/analyser/index.d.ts +3 -0
- package/dist/analyser/index.js +12 -0
- package/dist/analyser/pipeline/aggregate.d.ts +2 -0
- package/dist/analyser/pipeline/aggregate.js +98 -0
- package/dist/analyser/pipeline/classify.d.ts +3 -0
- package/dist/analyser/pipeline/classify.js +31 -0
- package/dist/analyser/pipeline/filter.d.ts +2 -0
- package/dist/analyser/pipeline/filter.js +14 -0
- package/dist/analyser/pipeline/heuristics.d.ts +3 -0
- package/dist/analyser/pipeline/heuristics.js +12 -0
- package/dist/analyser/pipeline/normalise.d.ts +2 -0
- package/dist/analyser/pipeline/normalise.js +9 -0
- package/dist/cli/output/default.d.ts +3 -0
- package/dist/cli/output/default.js +106 -0
- package/dist/cli/output/tree.d.ts +3 -0
- package/dist/cli/output/tree.js +11 -0
- package/dist/cli/runCliAnalysis.d.ts +2 -0
- package/dist/cli/runCliAnalysis.js +26 -0
- package/dist/cli/utils.d.ts +2 -0
- package/dist/cli/utils.js +9 -0
- package/dist/cli.js +14 -143
- package/dist/entry/analyseFs.d.ts +2 -0
- package/dist/entry/analyseFs.js +11 -0
- package/dist/entry/analyseRaw.d.ts +4 -0
- package/dist/entry/analyseRaw.js +11 -0
- package/dist/index.d.ts +19 -4
- package/dist/index.js +18 -483
- package/dist/input/fromFilesystem.d.ts +4 -0
- package/dist/input/fromFilesystem.js +115 -0
- package/dist/input/fromRawContent.d.ts +2 -0
- package/dist/input/fromRawContent.js +19 -0
- package/dist/input/normaliseOpts.d.ts +2 -0
- package/dist/input/normaliseOpts.js +13 -0
- package/dist/program/classes/attributes.d.ts +11 -0
- package/dist/program/classes/attributes.js +37 -0
- package/dist/{helpers/load-data.d.ts → program/data/loadDataFiles.d.ts} +1 -1
- package/dist/program/data/loadDataFiles.js +32 -0
- package/dist/program/data/retrieveData.d.ts +12 -0
- package/dist/program/data/retrieveData.js +27 -0
- package/dist/{helpers/norm-path.d.ts → program/fs/normalisedPath.d.ts} +1 -0
- package/dist/program/fs/normalisedPath.js +17 -0
- package/dist/program/fs/readFile.js +17 -0
- package/dist/{helpers/walk-tree.d.ts → program/fs/walkTree.d.ts} +1 -1
- package/dist/{helpers/walk-tree.js → program/fs/walkTree.js} +22 -30
- package/dist/{helpers/parse-gitattributes.d.ts → program/parsing/parseGitattributes.d.ts} +2 -2
- package/dist/{helpers/parse-gitattributes.js → program/parsing/parseGitattributes.js} +4 -8
- package/dist/{helpers/parse-gitignore.js → program/parsing/parseGitignore.js} +1 -4
- package/dist/program/processFiles.d.ts +9 -0
- package/dist/program/processFiles.js +111 -0
- package/dist/{helpers/convert-pcre.js → program/utils/pcre.js} +1 -4
- package/dist/{schema.d.ts → types/schema.d.ts} +1 -1
- package/dist/types/schema.js +1 -0
- package/dist/{types.d.ts → types/types.d.ts} +35 -24
- package/dist/types/types.js +1 -0
- package/ext/generated.rb +6 -0
- package/ext/heuristics.yml +102 -11
- package/ext/languages.yml +518 -88
- package/ext/vendor.yml +1 -0
- package/package.json +14 -13
- package/readme.md +82 -87
- package/dist/helpers/load-data.js +0 -37
- package/dist/helpers/norm-path.js +0 -15
- package/dist/helpers/read-file.js +0 -23
- package/dist/schema.js +0 -2
- package/dist/types.js +0 -2
- /package/dist/{helpers/read-file.d.ts → program/fs/readFile.d.ts} +0 -0
- /package/dist/{helpers/parse-gitignore.d.ts → program/parsing/parseGitignore.d.ts} +0 -0
- /package/dist/{helpers/convert-pcre.d.ts → program/utils/pcre.d.ts} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const commander_1 = require("commander");
|
|
10
|
-
const index_1 = __importDefault(require("./index"));
|
|
11
|
-
const norm_path_1 = require("./helpers/norm-path");
|
|
12
|
-
const colouredMsg = ([r, g, b], msg) => `\u001B[${38};2;${r};${g};${b}m${msg}${'\u001b[0m'}`;
|
|
13
|
-
const hexToRgb = (hex) => [parseInt(hex.slice(1, 3), 16), parseInt(hex.slice(3, 5), 16), parseInt(hex.slice(5, 7), 16)];
|
|
14
|
-
commander_1.program
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import FS from 'node:fs';
|
|
3
|
+
import runCliAnalysis from './cli/runCliAnalysis.js';
|
|
4
|
+
const packageJson = JSON.parse(FS.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
|
|
5
|
+
const VERSION = packageJson.version;
|
|
6
|
+
program
|
|
15
7
|
.name('linguist')
|
|
16
|
-
.usage('--
|
|
17
|
-
.option('-a|--
|
|
8
|
+
.usage('--analyse [<folders...>] [<options...>]')
|
|
9
|
+
.option('-a|--analyse [folders...]', 'Analyse the languages of all files in a folder')
|
|
18
10
|
.option('-i|--ignoredFiles <files...>', `A list of file path globs to ignore`)
|
|
19
11
|
.option('-l|--ignoredLanguages <languages...>', `A list of languages to ignore`)
|
|
20
12
|
.option('-c|--categories <categories...>', 'Language categories to include in output')
|
|
@@ -37,8 +29,8 @@ commander_1.program
|
|
|
37
29
|
.option('-M|--checkModeline [bool]', 'Check modelines for explicit classification', true)
|
|
38
30
|
.helpOption(`-h|--help`, 'Display this help message')
|
|
39
31
|
.version(VERSION, '-v|--version', 'Display the installed version of linguist-js');
|
|
40
|
-
|
|
41
|
-
const args =
|
|
32
|
+
program.parse(process.argv);
|
|
33
|
+
const args = program.opts();
|
|
42
34
|
// Normalise arguments
|
|
43
35
|
for (const arg in args) {
|
|
44
36
|
const normalise = (val) => {
|
|
@@ -55,131 +47,10 @@ for (const arg in args) {
|
|
|
55
47
|
args[arg] = normalise(args[arg]);
|
|
56
48
|
}
|
|
57
49
|
// Run Linguist
|
|
58
|
-
if (args.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// Check arguments
|
|
62
|
-
const validCategories = ['data', 'programming', 'prose', 'markup'];
|
|
63
|
-
if ((_a = args.categories) === null || _a === void 0 ? void 0 : _a.some((category) => !validCategories.includes(category))) {
|
|
64
|
-
console.log(`Error: '${args.categories.join(', ')}' contains an invalid category. Valid options: ${validCategories.join(', ')}.`);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
// Fetch language data
|
|
68
|
-
const root = args.analyze === true ? '.' : args.analyze;
|
|
69
|
-
const data = await (0, index_1.default)(root, args);
|
|
70
|
-
const { files, languages, unknown } = data;
|
|
71
|
-
// Print output
|
|
72
|
-
if (!args.json) {
|
|
73
|
-
// Ignore languages with a bytes/% size less than the declared min size
|
|
74
|
-
if (args.minSize) {
|
|
75
|
-
const totalSize = languages.bytes;
|
|
76
|
-
const minSizeAmt = parseFloat(args.minSize.replace(/[a-z]+$/i, '')); // '2KB' -> 2
|
|
77
|
-
const minSizeUnit = args.minSize.replace(/^\d+/, '').toLowerCase(); // '2KB' -> 'kb'
|
|
78
|
-
const checkBytes = minSizeUnit !== 'loc'; // whether to check bytes or loc
|
|
79
|
-
const conversionFactors = {
|
|
80
|
-
'b': n => n,
|
|
81
|
-
'kb': n => n * 1e3,
|
|
82
|
-
'mb': n => n * 1e6,
|
|
83
|
-
'%': n => n * totalSize / 100,
|
|
84
|
-
'loc': n => n,
|
|
85
|
-
};
|
|
86
|
-
const minBytesSize = conversionFactors[minSizeUnit](+minSizeAmt);
|
|
87
|
-
const other = { bytes: 0, lines: { total: 0, content: 0, code: 0 } };
|
|
88
|
-
// Apply specified minimums: delete language results that do not reach the threshold
|
|
89
|
-
for (const [lang, data] of Object.entries(languages.results)) {
|
|
90
|
-
const checkUnit = checkBytes ? data.bytes : data.lines.code;
|
|
91
|
-
if (checkUnit < minBytesSize) {
|
|
92
|
-
// Add to 'other' count
|
|
93
|
-
other.bytes += data.bytes;
|
|
94
|
-
other.lines.total += data.lines.total;
|
|
95
|
-
other.lines.content += data.lines.content;
|
|
96
|
-
other.lines.code += data.lines.code;
|
|
97
|
-
// Remove language result
|
|
98
|
-
delete languages.results[lang];
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (other.bytes) {
|
|
102
|
-
languages.results["Other"] = { ...other, type: null };
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
const sortedEntries = Object.entries(languages.results).sort((a, b) => (a[1].bytes < b[1].bytes ? +1 : -1));
|
|
106
|
-
const totalBytes = languages.bytes;
|
|
107
|
-
console.log(`\n Analysed ${files.bytes.toLocaleString()} B from ${files.count} files with linguist-js`);
|
|
108
|
-
console.log(`\n Language analysis results: \n`);
|
|
109
|
-
let count = 0;
|
|
110
|
-
if (sortedEntries.length === 0)
|
|
111
|
-
console.log(` None`);
|
|
112
|
-
// Collate files per language
|
|
113
|
-
const filesPerLanguage = {};
|
|
114
|
-
if (args.listFiles) {
|
|
115
|
-
for (const language of Object.keys(languages.results)) {
|
|
116
|
-
filesPerLanguage[language] = [];
|
|
117
|
-
}
|
|
118
|
-
for (const [file, lang] of Object.entries(files.results)) {
|
|
119
|
-
if (lang)
|
|
120
|
-
filesPerLanguage[lang].push(file);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
// List parsed results
|
|
124
|
-
for (const [lang, { bytes, lines, color }] of sortedEntries) {
|
|
125
|
-
const percent = (bytes) => bytes / (totalBytes || 1) * 100;
|
|
126
|
-
const fmtd = {
|
|
127
|
-
index: (++count).toString().padStart(2, ' '),
|
|
128
|
-
lang: lang.padEnd(24, ' '),
|
|
129
|
-
percent: percent(bytes).toFixed(2).padStart(5, ' '),
|
|
130
|
-
bytes: bytes.toLocaleString().padStart(10, ' '),
|
|
131
|
-
loc: lines.code.toLocaleString().padStart(10, ' '),
|
|
132
|
-
icon: colouredMsg(hexToRgb(color !== null && color !== void 0 ? color : '#ededed'), '\u2588'),
|
|
133
|
-
};
|
|
134
|
-
console.log(` ${fmtd.index}. ${fmtd.icon} ${fmtd.lang} ${fmtd.percent}% ${fmtd.bytes} B ${fmtd.loc} LOC`);
|
|
135
|
-
// If using `listFiles` option, list all files tagged as this language
|
|
136
|
-
if (args.listFiles) {
|
|
137
|
-
console.log(); // padding
|
|
138
|
-
for (const file of filesPerLanguage[lang]) {
|
|
139
|
-
let relFile = (0, norm_path_1.normPath)(path_1.default.relative(path_1.default.resolve('.'), file));
|
|
140
|
-
if (!relFile.startsWith('../'))
|
|
141
|
-
relFile = './' + relFile;
|
|
142
|
-
const bytes = (await fs_1.default.promises.stat(file)).size;
|
|
143
|
-
const fmtd2 = {
|
|
144
|
-
file: relFile.padEnd(42, ' '),
|
|
145
|
-
percent: percent(bytes).toFixed(2).padStart(5, ' '),
|
|
146
|
-
bytes: bytes.toLocaleString().padStart(10, ' '),
|
|
147
|
-
};
|
|
148
|
-
console.log(` ${fmtd.icon} ${fmtd2.file} ${fmtd2.percent}% ${fmtd2.bytes} B`);
|
|
149
|
-
}
|
|
150
|
-
console.log(); // padding
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
if (!args.listFiles)
|
|
154
|
-
console.log(); // padding
|
|
155
|
-
console.log(` Total: ${totalBytes.toLocaleString()} B`);
|
|
156
|
-
// List unknown files/extensions
|
|
157
|
-
if (unknown.bytes > 0) {
|
|
158
|
-
console.log(`\n Unknown files and extensions:`);
|
|
159
|
-
for (const [name, bytes] of Object.entries(unknown.filenames)) {
|
|
160
|
-
console.log(` '${name}': ${bytes.toLocaleString()} B`);
|
|
161
|
-
}
|
|
162
|
-
for (const [ext, bytes] of Object.entries(unknown.extensions)) {
|
|
163
|
-
console.log(` '*${ext}': ${bytes.toLocaleString()} B`);
|
|
164
|
-
}
|
|
165
|
-
console.log(` Total: ${unknown.bytes.toLocaleString()} B`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else if (args.tree) {
|
|
169
|
-
const treeParts = args.tree.split('.');
|
|
170
|
-
let nestedData = data;
|
|
171
|
-
for (const part of treeParts) {
|
|
172
|
-
if (!nestedData[part])
|
|
173
|
-
throw Error(`TraversalError: Key '${part}' cannot be found on output object.`);
|
|
174
|
-
nestedData = nestedData[part];
|
|
175
|
-
}
|
|
176
|
-
console.log(nestedData);
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
console.dir(data, { depth: null });
|
|
180
|
-
}
|
|
181
|
-
})();
|
|
50
|
+
if (args.analyse) {
|
|
51
|
+
void runCliAnalysis(args);
|
|
52
|
+
}
|
|
182
53
|
else {
|
|
183
|
-
console.log(`Welcome to linguist-js, a JavaScript port of
|
|
54
|
+
console.log(`Welcome to linguist-js, a JavaScript port of the github-linguist language analyser.`);
|
|
184
55
|
console.log(`Type 'linguist --help' for a list of commands.`);
|
|
185
56
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import analyseVirtualFiles from '../analyser/index.js';
|
|
2
|
+
import fromFilesystem from '../input/fromFilesystem.js';
|
|
3
|
+
import normaliseOpts from '../input/normaliseOpts.js';
|
|
4
|
+
import retrieveData from '../program/data/retrieveData.js';
|
|
5
|
+
export default async function analyseFs(inputPaths, inputOptions = {}) {
|
|
6
|
+
const options = normaliseOpts(inputOptions);
|
|
7
|
+
// Load data from github-linguist web repo
|
|
8
|
+
const { langData, heuristicsData, vendorPaths } = await retrieveData(options.offline ?? false);
|
|
9
|
+
const files = await fromFilesystem(inputPaths, options, vendorPaths);
|
|
10
|
+
return analyseVirtualFiles(files, langData, heuristicsData, options);
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import analyseVirtualFiles from '../analyser/index.js';
|
|
2
|
+
import fromRawContent from '../input/fromRawContent.js';
|
|
3
|
+
import normaliseOpts from '../input/normaliseOpts.js';
|
|
4
|
+
import retrieveData from '../program/data/retrieveData.js';
|
|
5
|
+
export default async function analyseRaw(inputContent, inputOptions = {}) {
|
|
6
|
+
const options = normaliseOpts(inputOptions);
|
|
7
|
+
// Load data from github-linguist web repo
|
|
8
|
+
const { langData, heuristicsData, vendorPaths } = await retrieveData(options.offline ?? false);
|
|
9
|
+
const files = fromRawContent(inputContent, vendorPaths);
|
|
10
|
+
return analyseVirtualFiles(files, langData, heuristicsData, options);
|
|
11
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
declare
|
|
4
|
-
|
|
1
|
+
import analyseFs from './entry/analyseFs.js';
|
|
2
|
+
import analyseRaw from './entry/analyseRaw.js';
|
|
3
|
+
declare const _default: {
|
|
4
|
+
/**
|
|
5
|
+
* Analyse a list of folders and return language statistics
|
|
6
|
+
* @param inputPaths - An array of file paths to analyse
|
|
7
|
+
* @param options - Configuration options for the analysis
|
|
8
|
+
* @returns A promise that resolves to the analysis results
|
|
9
|
+
*/
|
|
10
|
+
analyseFolders: typeof analyseFs;
|
|
11
|
+
/**
|
|
12
|
+
* Analyse raw content and return language statistics
|
|
13
|
+
* @param inputContent - An object where keys are filenames and values are file contents
|
|
14
|
+
* @param options - Configuration options for the analysis
|
|
15
|
+
* @returns A promise that resolves to the analysis results
|
|
16
|
+
*/
|
|
17
|
+
analyseRawContent: typeof analyseRaw;
|
|
18
|
+
};
|
|
19
|
+
export default _default;
|