linguist-js 2.6.1 → 2.7.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 +36 -2
- package/dist/helpers/parse-gitattributes.d.ts +16 -0
- package/dist/helpers/parse-gitattributes.js +38 -0
- package/dist/helpers/walk-tree.d.ts +2 -2
- package/dist/helpers/walk-tree.js +9 -7
- package/dist/index.js +132 -118
- package/dist/types.d.ts +4 -0
- package/ext/generated.rb +1 -0
- package/ext/heuristics.yml +26 -11
- package/ext/languages.yml +129 -12
- package/package.json +3 -3
- package/readme.md +19 -5
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const VERSION = require('../package.json').version;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
7
9
|
const commander_1 = require("commander");
|
|
8
10
|
const index_1 = __importDefault(require("./index"));
|
|
9
11
|
const colouredMsg = ([r, g, b], msg) => `\u001B[${38};2;${r};${g};${b}m${msg}${'\u001b[0m'}`;
|
|
@@ -18,6 +20,7 @@ commander_1.program
|
|
|
18
20
|
.option('-C|--childLanguages [bool]', 'Display child languages instead of their parents', false)
|
|
19
21
|
.option('-j|--json [bool]', 'Display the output as JSON', false)
|
|
20
22
|
.option('-t|--tree <traversal>', 'Which part of the output JSON to display (dot-delimited)')
|
|
23
|
+
.option('-F|--listFiles [bool]', 'Whether to list every matching file under the language results', false)
|
|
21
24
|
.option('-q|--quick [bool]', 'Skip complex language analysis (alias for -{A|I|H|S}=false)', false)
|
|
22
25
|
.option('-o|--offline [bool]', 'Use packaged data files instead of fetching latest from GitHub', false)
|
|
23
26
|
.option('-V|--keepVendored [bool]', 'Prevent skipping over vendored/generated files', false)
|
|
@@ -59,21 +62,52 @@ if (args.analyze)
|
|
|
59
62
|
const sortedEntries = Object.entries(languages.results).sort((a, b) => a[1].bytes < b[1].bytes ? +1 : -1);
|
|
60
63
|
const totalBytes = languages.bytes;
|
|
61
64
|
console.log(`\n Analysed ${files.bytes.toLocaleString()} B from ${files.count} files with linguist-js`);
|
|
62
|
-
console.log(`\n Language analysis results
|
|
65
|
+
console.log(`\n Language analysis results: \n`);
|
|
63
66
|
let count = 0;
|
|
64
67
|
if (sortedEntries.length === 0)
|
|
65
68
|
console.log(` None`);
|
|
69
|
+
// Collate files per language
|
|
70
|
+
const filesPerLanguage = {};
|
|
71
|
+
if (args.listFiles) {
|
|
72
|
+
for (const language of Object.keys(languages.results)) {
|
|
73
|
+
filesPerLanguage[language] = [];
|
|
74
|
+
}
|
|
75
|
+
for (const [file, lang] of Object.entries(files.results)) {
|
|
76
|
+
if (lang)
|
|
77
|
+
filesPerLanguage[lang].push(file);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
66
80
|
// List parsed results
|
|
67
81
|
for (const [lang, { bytes, color }] of sortedEntries) {
|
|
82
|
+
const percent = (bytes) => bytes / (totalBytes || 1) * 100;
|
|
68
83
|
const fmtd = {
|
|
69
84
|
index: (++count).toString().padStart(2, ' '),
|
|
70
85
|
lang: lang.padEnd(24, ' '),
|
|
71
|
-
percent: (bytes
|
|
86
|
+
percent: percent(bytes).toFixed(2).padStart(5, ' '),
|
|
72
87
|
bytes: bytes.toLocaleString().padStart(10, ' '),
|
|
73
88
|
icon: colouredMsg(hexToRgb(color !== null && color !== void 0 ? color : '#ededed'), '\u2588'),
|
|
74
89
|
};
|
|
75
90
|
console.log(` ${fmtd.index}. ${fmtd.icon} ${fmtd.lang} ${fmtd.percent}% ${fmtd.bytes} B`);
|
|
91
|
+
// If using `listFiles` option, list all files tagged as this language
|
|
92
|
+
if (args.listFiles) {
|
|
93
|
+
console.log(); // padding
|
|
94
|
+
for (const file of filesPerLanguage[lang]) {
|
|
95
|
+
let relFile = path_1.default.relative(path_1.default.resolve('.'), file).replace(/\\/g, '/');
|
|
96
|
+
if (!relFile.startsWith('../'))
|
|
97
|
+
relFile = './' + relFile;
|
|
98
|
+
const bytes = (await fs_1.default.promises.stat(file)).size;
|
|
99
|
+
const fmtd2 = {
|
|
100
|
+
file: relFile.padEnd(42, ' '),
|
|
101
|
+
percent: percent(bytes).toFixed(2).padStart(5, ' '),
|
|
102
|
+
bytes: bytes.toLocaleString().padStart(10, ' '),
|
|
103
|
+
};
|
|
104
|
+
console.log(` ${fmtd.icon} ${fmtd2.file} ${fmtd2.percent}% ${fmtd2.bytes} B`);
|
|
105
|
+
}
|
|
106
|
+
console.log(); // padding
|
|
107
|
+
}
|
|
76
108
|
}
|
|
109
|
+
if (!args.listFiles)
|
|
110
|
+
console.log(); // padding
|
|
77
111
|
console.log(` Total: ${totalBytes.toLocaleString()} B`);
|
|
78
112
|
// List unknown files/extensions
|
|
79
113
|
if (unknown.bytes > 0) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as T from '../types';
|
|
2
|
+
export type FlagAttributes = {
|
|
3
|
+
'vendored': boolean | null;
|
|
4
|
+
'generated': boolean | null;
|
|
5
|
+
'documentation': boolean | null;
|
|
6
|
+
'binary': boolean | null;
|
|
7
|
+
'language': T.LanguageResult;
|
|
8
|
+
};
|
|
9
|
+
export type ParsedGitattributes = Array<{
|
|
10
|
+
glob: T.FileGlob;
|
|
11
|
+
attrs: FlagAttributes;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Parses a gitattributes file.
|
|
15
|
+
*/
|
|
16
|
+
export default function parseAttributes(content: string, folderRoot?: string): ParsedGitattributes;
|
|
@@ -0,0 +1,38 @@
|
|
|
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 path_1 = __importDefault(require("path"));
|
|
7
|
+
/**
|
|
8
|
+
* Parses a gitattributes file.
|
|
9
|
+
*/
|
|
10
|
+
function parseAttributes(content, folderRoot = '.') {
|
|
11
|
+
var _a, _b;
|
|
12
|
+
const output = [];
|
|
13
|
+
for (const rawLine of content.split('\n')) {
|
|
14
|
+
const line = rawLine.replace(/#.*/, '').trim();
|
|
15
|
+
if (!line)
|
|
16
|
+
continue;
|
|
17
|
+
const parts = line.split(/\s+/g);
|
|
18
|
+
const fileGlob = parts[0];
|
|
19
|
+
const relFileGlob = path_1.default.join(folderRoot, fileGlob).replace(/\\/g, '/');
|
|
20
|
+
const attrParts = parts.slice(1);
|
|
21
|
+
const isTrue = (str) => !str.startsWith('-') && !str.endsWith('=false');
|
|
22
|
+
const isFalse = (str) => str.startsWith('-') || str.endsWith('=false');
|
|
23
|
+
const trueParts = (str) => attrParts.filter(part => part.includes(str) && isTrue(part));
|
|
24
|
+
const falseParts = (str) => attrParts.filter(part => part.includes(str) && isFalse(part));
|
|
25
|
+
const hasTrueParts = (str) => trueParts(str).length > 0;
|
|
26
|
+
const hasFalseParts = (str) => falseParts(str).length > 0;
|
|
27
|
+
const attrs = {
|
|
28
|
+
'generated': hasTrueParts('linguist-generated') ? true : hasFalseParts('linguist-generated') ? false : null,
|
|
29
|
+
'vendored': hasTrueParts('linguist-vendored') ? true : hasFalseParts('linguist-vendored') ? false : null,
|
|
30
|
+
'documentation': hasTrueParts('linguist-documentation') ? true : hasFalseParts('linguist-documentation') ? false : null,
|
|
31
|
+
'binary': hasTrueParts('binary') || hasFalseParts('text') ? true : hasFalseParts('binary') || hasTrueParts('text') ? false : null,
|
|
32
|
+
'language': (_b = (_a = trueParts('linguist-language').at(-1)) === null || _a === void 0 ? void 0 : _a.split('=')[1]) !== null && _b !== void 0 ? _b : null,
|
|
33
|
+
};
|
|
34
|
+
output.push({ glob: relFileGlob, attrs });
|
|
35
|
+
}
|
|
36
|
+
return output;
|
|
37
|
+
}
|
|
38
|
+
exports.default = parseAttributes;
|
|
@@ -8,8 +8,8 @@ interface WalkInput {
|
|
|
8
8
|
folderRoots: string[];
|
|
9
9
|
/** The absolute path of folders being checked */
|
|
10
10
|
folders: string[];
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
/** An instantiated Ignore object listing ignored files */
|
|
12
|
+
ignored: Ignore;
|
|
13
13
|
}
|
|
14
14
|
interface WalkOutput {
|
|
15
15
|
files: string[];
|
|
@@ -11,7 +11,7 @@ let allFolders;
|
|
|
11
11
|
;
|
|
12
12
|
/** Generate list of files in a directory. */
|
|
13
13
|
function walk(data) {
|
|
14
|
-
const { init, commonRoot, folderRoots, folders,
|
|
14
|
+
const { init, commonRoot, folderRoots, folders, ignored } = data;
|
|
15
15
|
// Initialise files and folders lists
|
|
16
16
|
if (init) {
|
|
17
17
|
allFiles = new Set();
|
|
@@ -34,11 +34,13 @@ function walk(data) {
|
|
|
34
34
|
// Create absolute path for disc operations
|
|
35
35
|
const path = path_1.default.resolve(commonRoot, file).replace(/\\/g, '/');
|
|
36
36
|
const localPath = localRoot ? file.replace(`./${localRoot}/`, '') : file.replace('./', '');
|
|
37
|
-
// Skip if nonexistant
|
|
37
|
+
// Skip if nonexistant
|
|
38
38
|
const nonExistant = !fs_1.default.existsSync(path);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
if (nonExistant)
|
|
40
|
+
continue;
|
|
41
|
+
// Skip if marked as ignored
|
|
42
|
+
const isIgnored = ignored.test(localPath).ignored;
|
|
43
|
+
if (isIgnored)
|
|
42
44
|
continue;
|
|
43
45
|
// Add absolute folder path to list
|
|
44
46
|
allFolders.add(path_1.default.resolve(folder).replace(/\\/g, '/'));
|
|
@@ -46,7 +48,7 @@ function walk(data) {
|
|
|
46
48
|
if (file.endsWith('/')) {
|
|
47
49
|
// Recurse into subfolders
|
|
48
50
|
allFolders.add(path);
|
|
49
|
-
walk({ init: false, commonRoot
|
|
51
|
+
walk({ init: false, commonRoot, folderRoots, folders: [path], ignored });
|
|
50
52
|
}
|
|
51
53
|
else {
|
|
52
54
|
// Add file path to list
|
|
@@ -57,7 +59,7 @@ function walk(data) {
|
|
|
57
59
|
// Recurse into all folders
|
|
58
60
|
else {
|
|
59
61
|
for (const i in folders) {
|
|
60
|
-
walk({ init: false, commonRoot
|
|
62
|
+
walk({ init: false, commonRoot, folderRoots: [folderRoots[i]], folders: [folders[i]], ignored });
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
// Return absolute files and folders lists
|
package/dist/index.js
CHANGED
|
@@ -35,13 +35,23 @@ const isbinaryfile_1 = require("isbinaryfile");
|
|
|
35
35
|
const walk_tree_1 = __importDefault(require("./helpers/walk-tree"));
|
|
36
36
|
const load_data_1 = __importStar(require("./helpers/load-data"));
|
|
37
37
|
const read_file_1 = __importDefault(require("./helpers/read-file"));
|
|
38
|
+
const parse_gitattributes_1 = __importDefault(require("./helpers/parse-gitattributes"));
|
|
38
39
|
const convert_pcre_1 = __importDefault(require("./helpers/convert-pcre"));
|
|
39
|
-
async function analyse(
|
|
40
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q
|
|
41
|
-
var
|
|
40
|
+
async function analyse(rawPaths, opts = {}) {
|
|
41
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
42
|
+
var _r, _s;
|
|
42
43
|
const useRawContent = opts.fileContent !== undefined;
|
|
43
|
-
input = [
|
|
44
|
-
|
|
44
|
+
const input = [rawPaths !== null && rawPaths !== void 0 ? rawPaths : []].flat();
|
|
45
|
+
const manualFileContent = [(_a = opts.fileContent) !== null && _a !== void 0 ? _a : []].flat();
|
|
46
|
+
// Normalise input option arguments
|
|
47
|
+
opts = {
|
|
48
|
+
checkIgnored: !opts.quick,
|
|
49
|
+
checkAttributes: !opts.quick,
|
|
50
|
+
checkHeuristics: !opts.quick,
|
|
51
|
+
checkShebang: !opts.quick,
|
|
52
|
+
checkModeline: !opts.quick,
|
|
53
|
+
...opts,
|
|
54
|
+
};
|
|
45
55
|
// Load data from github-linguist web repo
|
|
46
56
|
const langData = await (0, load_data_1.default)('languages.yml', opts.offline).then(js_yaml_1.default.load);
|
|
47
57
|
const vendorData = await (0, load_data_1.default)('vendor.yml', opts.offline).then(js_yaml_1.default.load);
|
|
@@ -52,30 +62,33 @@ async function analyse(input, opts = {}) {
|
|
|
52
62
|
// Setup main variables
|
|
53
63
|
const fileAssociations = {};
|
|
54
64
|
const extensions = {};
|
|
55
|
-
const
|
|
65
|
+
const globOverrides = {};
|
|
56
66
|
const results = {
|
|
57
67
|
files: { count: 0, bytes: 0, results: {}, alternatives: {} },
|
|
58
68
|
languages: { count: 0, bytes: 0, results: {} },
|
|
59
69
|
unknown: { count: 0, bytes: 0, extensions: {}, filenames: {} },
|
|
60
70
|
};
|
|
61
|
-
// Prepare list of ignored files
|
|
62
|
-
const gitignores = (0, ignore_1.default)();
|
|
63
|
-
const regexIgnores = [];
|
|
64
|
-
gitignores.add('.git');
|
|
65
|
-
if (!opts.keepVendored)
|
|
66
|
-
regexIgnores.push(...vendorPaths.map(path => RegExp(path, 'i')));
|
|
67
|
-
if (opts.ignoredFiles)
|
|
68
|
-
gitignores.add(opts.ignoredFiles);
|
|
69
71
|
// Set a common root path so that vendor paths do not incorrectly match parent folders
|
|
70
72
|
const normPath = (file) => file.replace(/\\/g, '/');
|
|
71
73
|
const resolvedInput = input.map(path => normPath(path_1.default.resolve(path)));
|
|
72
74
|
const commonRoot = (input.length > 1 ? (0, common_path_prefix_1.default)(resolvedInput) : resolvedInput[0]).replace(/\/?$/, '');
|
|
73
75
|
const localRoot = (folder) => folder.replace(commonRoot, '').replace(/^\//, '');
|
|
74
|
-
const relPath = (file) => normPath(path_1.default.relative(commonRoot, file));
|
|
75
|
-
const unRelPath = (file) => normPath(path_1.default.resolve(commonRoot, file));
|
|
76
|
-
|
|
76
|
+
const relPath = (file) => useRawContent ? file : normPath(path_1.default.relative(commonRoot, file));
|
|
77
|
+
const unRelPath = (file) => useRawContent ? file : normPath(path_1.default.resolve(commonRoot, file));
|
|
78
|
+
// Other helper functions
|
|
79
|
+
const fileMatchesGlobs = (file, ...globs) => (0, ignore_1.default)().add(globs).ignores(relPath(file));
|
|
80
|
+
const filterOutIgnored = (files, ignored) => ignored.filter(files.map(relPath)).map(unRelPath);
|
|
81
|
+
//*PREPARE FILES AND DATA*//
|
|
82
|
+
// Prepare list of ignored files
|
|
83
|
+
const ignored = (0, ignore_1.default)();
|
|
84
|
+
ignored.add('.git/');
|
|
85
|
+
ignored.add((_b = opts.ignoredFiles) !== null && _b !== void 0 ? _b : []);
|
|
86
|
+
const regexIgnores = [];
|
|
87
|
+
if (!opts.keepVendored)
|
|
88
|
+
regexIgnores.push(...vendorPaths.map(path => RegExp(path, 'i')));
|
|
77
89
|
// Load file paths and folders
|
|
78
|
-
let files
|
|
90
|
+
let files;
|
|
91
|
+
let folders;
|
|
79
92
|
if (useRawContent) {
|
|
80
93
|
// Uses raw file content
|
|
81
94
|
files = input;
|
|
@@ -83,21 +96,76 @@ async function analyse(input, opts = {}) {
|
|
|
83
96
|
}
|
|
84
97
|
else {
|
|
85
98
|
// Uses directory on disc
|
|
86
|
-
const data = (0, walk_tree_1.default)({ init: true, commonRoot, folderRoots: resolvedInput, folders: resolvedInput,
|
|
99
|
+
const data = (0, walk_tree_1.default)({ init: true, commonRoot, folderRoots: resolvedInput, folders: resolvedInput, ignored });
|
|
87
100
|
files = data.files;
|
|
88
101
|
folders = data.folders;
|
|
89
102
|
}
|
|
90
|
-
//
|
|
91
|
-
opts
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
// Load gitignore data and apply ignores rules
|
|
104
|
+
if (!useRawContent && opts.checkIgnored) {
|
|
105
|
+
const nestedIgnoreFiles = files.filter(file => file.endsWith('.gitignore'));
|
|
106
|
+
for (const ignoresFile of nestedIgnoreFiles) {
|
|
107
|
+
const relIgnoresFile = relPath(ignoresFile);
|
|
108
|
+
const relIgnoresFolder = path_1.default.dirname(relIgnoresFile);
|
|
109
|
+
// Parse gitignores
|
|
110
|
+
const ignoresDataRaw = await (0, read_file_1.default)(ignoresFile);
|
|
111
|
+
const ignoresData = ignoresDataRaw.replace(/#.+|\s+$/gm, '');
|
|
112
|
+
const absoluteIgnoresData = ignoresData
|
|
113
|
+
// '.file' -> 'root/*/.file'
|
|
114
|
+
.replace(/^(?=[^\s\/\\])/gm, localRoot(relIgnoresFolder) + '/*/')
|
|
115
|
+
// '/folder' -> 'root/folder'
|
|
116
|
+
.replace(/^[\/\\]/gm, localRoot(relIgnoresFolder) + '/');
|
|
117
|
+
ignored.add(absoluteIgnoresData);
|
|
118
|
+
files = filterOutIgnored(files, ignored);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Fetch and normalise gitattributes data of all subfolders and save to metadata
|
|
122
|
+
const manualAttributes = {}; // Maps file globs to gitattribute boolean flags
|
|
123
|
+
const getFlaggedGlobs = (attr, val) => {
|
|
124
|
+
return Object.entries(manualAttributes).filter(([, attrs]) => attrs[attr] === val).map(([glob,]) => glob);
|
|
98
125
|
};
|
|
126
|
+
if (!useRawContent && opts.checkAttributes) {
|
|
127
|
+
const nestedAttrFiles = files.filter(file => file.endsWith('.gitattributes'));
|
|
128
|
+
for (const attrFile of nestedAttrFiles) {
|
|
129
|
+
const relAttrFile = relPath(attrFile);
|
|
130
|
+
const relAttrFolder = path_1.default.dirname(relAttrFile);
|
|
131
|
+
const contents = await (0, read_file_1.default)(attrFile);
|
|
132
|
+
const parsed = (0, parse_gitattributes_1.default)(contents, relAttrFolder);
|
|
133
|
+
for (const { glob, attrs } of parsed) {
|
|
134
|
+
manualAttributes[glob] = attrs;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Apply vendor file path matches and filter out vendored files
|
|
139
|
+
if (!opts.keepVendored) {
|
|
140
|
+
// Get data of files that have been manually marked with metadata
|
|
141
|
+
const vendorTrueGlobs = [...getFlaggedGlobs('vendored', true), ...getFlaggedGlobs('generated', true), ...getFlaggedGlobs('documentation', true)];
|
|
142
|
+
const vendorFalseGlobs = [...getFlaggedGlobs('vendored', false), ...getFlaggedGlobs('generated', false), ...getFlaggedGlobs('documentation', false)];
|
|
143
|
+
// Set up glob ignore object to use for expanding globs to match files
|
|
144
|
+
const vendorTrueIgnore = (0, ignore_1.default)().add(vendorTrueGlobs);
|
|
145
|
+
const vendorFalseIgnore = (0, ignore_1.default)().add(vendorFalseGlobs);
|
|
146
|
+
// Remove all files marked as vendored by default
|
|
147
|
+
const excludedFiles = files.filter(file => vendorPaths.some(pathPtn => RegExp(pathPtn, 'i').test(relPath(file))));
|
|
148
|
+
files = files.filter(file => !excludedFiles.includes(file));
|
|
149
|
+
// Re-add removed files that are overridden manually in gitattributes
|
|
150
|
+
const overriddenExcludedFiles = excludedFiles.filter(file => vendorFalseIgnore.ignores(relPath(file)));
|
|
151
|
+
files.push(...overriddenExcludedFiles);
|
|
152
|
+
// Remove files explicitly marked as vendored in gitattributes
|
|
153
|
+
files = files.filter(file => !vendorTrueIgnore.ignores(relPath(file)));
|
|
154
|
+
}
|
|
155
|
+
// Filter out binary files
|
|
156
|
+
if (!opts.keepBinary) {
|
|
157
|
+
// Filter out files that are binary by default
|
|
158
|
+
files = files.filter(file => !binary_extensions_1.default.some(ext => file.endsWith('.' + ext)));
|
|
159
|
+
// Filter out manually specified binary files
|
|
160
|
+
const binaryIgnored = (0, ignore_1.default)().add(getFlaggedGlobs('binary', true));
|
|
161
|
+
files = filterOutIgnored(files, binaryIgnored);
|
|
162
|
+
// Re-add files manually marked not as binary
|
|
163
|
+
const binaryUnignored = (0, ignore_1.default)().add(getFlaggedGlobs('binary', false));
|
|
164
|
+
const unignoredList = filterOutIgnored(files, binaryUnignored);
|
|
165
|
+
files.push(...unignoredList);
|
|
166
|
+
}
|
|
99
167
|
// Ignore specific languages
|
|
100
|
-
for (const lang of (
|
|
168
|
+
for (const lang of (_c = opts.ignoredLanguages) !== null && _c !== void 0 ? _c : []) {
|
|
101
169
|
for (const key in langData) {
|
|
102
170
|
if (lang.toLowerCase() === key.toLowerCase()) {
|
|
103
171
|
delete langData[key];
|
|
@@ -105,71 +173,22 @@ async function analyse(input, opts = {}) {
|
|
|
105
173
|
}
|
|
106
174
|
}
|
|
107
175
|
}
|
|
108
|
-
//
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
// Parse gitignores
|
|
120
|
-
const ignoresFile = path_1.default.join(folder, '.gitignore');
|
|
121
|
-
if (opts.checkIgnored && fs_1.default.existsSync(ignoresFile)) {
|
|
122
|
-
const ignoresData = await (0, read_file_1.default)(ignoresFile);
|
|
123
|
-
const localIgnoresData = ignoresData.replace(/^[\/\\]/g, localRoot(folder) + '/');
|
|
124
|
-
gitignores.add(localIgnoresData);
|
|
125
|
-
}
|
|
126
|
-
// Parse gitattributes
|
|
127
|
-
const attributesFile = path_1.default.join(folder, '.gitattributes');
|
|
128
|
-
if (opts.checkAttributes && fs_1.default.existsSync(attributesFile)) {
|
|
129
|
-
const attributesData = await (0, read_file_1.default)(attributesFile);
|
|
130
|
-
// Explicit text/binary associations
|
|
131
|
-
const contentTypeMatches = attributesData.matchAll(/^(\S+).*?(-?binary|-?text)(?!=auto)/gm);
|
|
132
|
-
for (const [_line, path, type] of contentTypeMatches) {
|
|
133
|
-
if (['text', '-binary'].includes(type)) {
|
|
134
|
-
customText.add(localFilePath(path));
|
|
135
|
-
}
|
|
136
|
-
if (['-text', 'binary'].includes(type)) {
|
|
137
|
-
customBinary.add(localFilePath(path));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// Custom vendor options
|
|
141
|
-
const vendorMatches = attributesData.matchAll(/^(\S+).*[^-]linguist-(vendored|generated|documentation)(?!=false)/gm);
|
|
142
|
-
for (const [_line, path] of vendorMatches) {
|
|
143
|
-
gitignores.add(localFilePath(path));
|
|
144
|
-
}
|
|
145
|
-
// Custom file associations
|
|
146
|
-
const customLangMatches = attributesData.matchAll(/^(\S+).*[^-]linguist-language=(\S+)/gm);
|
|
147
|
-
for (let [_line, path, forcedLang] of customLangMatches) {
|
|
148
|
-
// If specified language is an alias, associate it with its full name
|
|
149
|
-
if (!langData[forcedLang]) {
|
|
150
|
-
const overrideLang = Object.entries(langData).find(entry => { var _a; return (_a = entry[1].aliases) === null || _a === void 0 ? void 0 : _a.includes(forcedLang.toLowerCase()); });
|
|
151
|
-
if (overrideLang) {
|
|
152
|
-
forcedLang = overrideLang[0];
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
const fullPath = path_1.default.join(relPath(folder), path);
|
|
156
|
-
overrides[fullPath] = forcedLang;
|
|
157
|
-
}
|
|
176
|
+
// Establish language overrides taken from gitattributes
|
|
177
|
+
const forcedLangs = Object.entries(manualAttributes).filter(([, attrs]) => attrs.language);
|
|
178
|
+
for (const [globPath, attrs] of forcedLangs) {
|
|
179
|
+
let forcedLang = attrs.language;
|
|
180
|
+
if (!forcedLang)
|
|
181
|
+
continue;
|
|
182
|
+
// If specified language is an alias, associate it with its full name
|
|
183
|
+
if (!langData[forcedLang]) {
|
|
184
|
+
const overrideLang = Object.entries(langData).find(entry => { var _a; return (_a = entry[1].aliases) === null || _a === void 0 ? void 0 : _a.includes(forcedLang.toLowerCase()); });
|
|
185
|
+
if (overrideLang) {
|
|
186
|
+
forcedLang = overrideLang[0];
|
|
158
187
|
}
|
|
159
188
|
}
|
|
189
|
+
globOverrides[globPath] = forcedLang;
|
|
160
190
|
}
|
|
161
|
-
|
|
162
|
-
if (!opts.keepVendored) {
|
|
163
|
-
// Filter out any files that match a vendor file path
|
|
164
|
-
if (useRawContent) {
|
|
165
|
-
files = gitignores.filter(files);
|
|
166
|
-
files = files.filter(file => !regexIgnores.find(match => match.test(file)));
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
files = gitignores.filter(files.map(localPath)).map(unRelPath);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
// Load all files and parse languages
|
|
191
|
+
//*PARSE LANGUAGES*//
|
|
173
192
|
const addResult = (file, result) => {
|
|
174
193
|
if (!fileAssociations[file]) {
|
|
175
194
|
fileAssociations[file] = [];
|
|
@@ -177,26 +196,36 @@ async function analyse(input, opts = {}) {
|
|
|
177
196
|
}
|
|
178
197
|
// Set parent to result group if it is present
|
|
179
198
|
// Is nullish if either `opts.childLanguages` is set or if there is no group
|
|
180
|
-
const finalResult = !opts.childLanguages && result && langData[result].group || result;
|
|
181
|
-
if (!fileAssociations[file].includes(finalResult))
|
|
199
|
+
const finalResult = !opts.childLanguages && result && langData[result] && langData[result].group || result;
|
|
200
|
+
if (!fileAssociations[file].includes(finalResult)) {
|
|
182
201
|
fileAssociations[file].push(finalResult);
|
|
202
|
+
}
|
|
183
203
|
extensions[file] = path_1.default.extname(file).toLowerCase();
|
|
184
204
|
};
|
|
185
|
-
const overridesArray = Object.entries(overrides);
|
|
186
|
-
// List all languages that could be associated with a given file
|
|
187
205
|
const definiteness = {};
|
|
188
206
|
const fromShebang = {};
|
|
189
|
-
for (const file of files) {
|
|
207
|
+
fileLoop: for (const file of files) {
|
|
208
|
+
// Check manual override
|
|
209
|
+
for (const globMatch in globOverrides) {
|
|
210
|
+
if (!fileMatchesGlobs(file, globMatch))
|
|
211
|
+
continue;
|
|
212
|
+
// If the given file matches the glob, apply the override to the file
|
|
213
|
+
const forcedLang = globOverrides[globMatch];
|
|
214
|
+
addResult(file, forcedLang);
|
|
215
|
+
definiteness[file] = true;
|
|
216
|
+
continue fileLoop; // no need to check other heuristics, the classified language has been found
|
|
217
|
+
}
|
|
218
|
+
// Check first line for readability
|
|
190
219
|
let firstLine;
|
|
191
220
|
if (useRawContent) {
|
|
192
|
-
firstLine = (_e = (_d =
|
|
221
|
+
firstLine = (_e = (_d = manualFileContent[files.indexOf(file)]) === null || _d === void 0 ? void 0 : _d.split('\n')[0]) !== null && _e !== void 0 ? _e : null;
|
|
193
222
|
}
|
|
194
223
|
else if (fs_1.default.existsSync(file) && !fs_1.default.lstatSync(file).isDirectory()) {
|
|
195
224
|
firstLine = await (0, read_file_1.default)(file, true).catch(() => null);
|
|
196
225
|
}
|
|
197
226
|
else
|
|
198
227
|
continue;
|
|
199
|
-
// Skip if file is unreadable
|
|
228
|
+
// Skip if file is unreadable or blank
|
|
200
229
|
if (firstLine === null)
|
|
201
230
|
continue;
|
|
202
231
|
// Check first line for explicit classification
|
|
@@ -231,17 +260,6 @@ async function analyse(input, opts = {}) {
|
|
|
231
260
|
continue;
|
|
232
261
|
}
|
|
233
262
|
}
|
|
234
|
-
// Check override for manual language classification
|
|
235
|
-
if (!useRawContent && !opts.quick && opts.checkAttributes) {
|
|
236
|
-
const isOverridden = (path) => (0, ignore_1.default)().add(path).ignores(relPath(file));
|
|
237
|
-
const match = overridesArray.find(item => isOverridden(item[0]));
|
|
238
|
-
if (match) {
|
|
239
|
-
const forcedLang = match[1];
|
|
240
|
-
addResult(file, forcedLang);
|
|
241
|
-
definiteness[file] = true;
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
263
|
// Search each language
|
|
246
264
|
let skipExts = false;
|
|
247
265
|
// Check if filename is a match
|
|
@@ -286,12 +304,8 @@ async function analyse(input, opts = {}) {
|
|
|
286
304
|
}
|
|
287
305
|
// Skip binary files
|
|
288
306
|
if (!useRawContent && !opts.keepBinary) {
|
|
289
|
-
|
|
290
|
-
const isCustomBinary = customBinary.ignores(relPath(file));
|
|
291
|
-
const isBinaryExt = binary_extensions_1.default.some(ext => file.endsWith('.' + ext));
|
|
292
|
-
if (!isCustomText && (isCustomBinary || isBinaryExt || await (0, isbinaryfile_1.isBinaryFile)(file))) {
|
|
307
|
+
if (await (0, isbinaryfile_1.isBinaryFile)(file))
|
|
293
308
|
continue;
|
|
294
|
-
}
|
|
295
309
|
}
|
|
296
310
|
// Parse heuristics if applicable
|
|
297
311
|
if (opts.checkHeuristics)
|
|
@@ -327,7 +341,7 @@ async function analyse(input, opts = {}) {
|
|
|
327
341
|
}
|
|
328
342
|
}
|
|
329
343
|
// Check file contents and apply heuristic patterns
|
|
330
|
-
const fileContent =
|
|
344
|
+
const fileContent = opts.fileContent ? manualFileContent[files.indexOf(file)] : await (0, read_file_1.default)(file).catch(() => null);
|
|
331
345
|
// Skip if file read errors
|
|
332
346
|
if (fileContent === null)
|
|
333
347
|
continue;
|
|
@@ -351,7 +365,7 @@ async function analyse(input, opts = {}) {
|
|
|
351
365
|
}
|
|
352
366
|
}
|
|
353
367
|
// Skip specified categories
|
|
354
|
-
if ((
|
|
368
|
+
if ((_l = opts.categories) === null || _l === void 0 ? void 0 : _l.length) {
|
|
355
369
|
const categories = ['data', 'markup', 'programming', 'prose'];
|
|
356
370
|
const hiddenCategories = categories.filter(cat => !opts.categories.includes(cat));
|
|
357
371
|
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
@@ -387,21 +401,21 @@ async function analyse(input, opts = {}) {
|
|
|
387
401
|
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
388
402
|
if (lang && !langData[lang])
|
|
389
403
|
continue;
|
|
390
|
-
const fileSize = (
|
|
404
|
+
const fileSize = (_o = (_m = manualFileContent[files.indexOf(file)]) === null || _m === void 0 ? void 0 : _m.length) !== null && _o !== void 0 ? _o : fs_1.default.statSync(file).size;
|
|
391
405
|
results.files.bytes += fileSize;
|
|
392
406
|
// If no language found, add extension in other section
|
|
393
407
|
if (!lang) {
|
|
394
408
|
const ext = path_1.default.extname(file);
|
|
395
409
|
const unknownType = ext === '' ? 'filenames' : 'extensions';
|
|
396
410
|
const name = ext === '' ? path_1.default.basename(file) : ext;
|
|
397
|
-
(
|
|
411
|
+
(_p = (_r = results.unknown[unknownType])[name]) !== null && _p !== void 0 ? _p : (_r[name] = 0);
|
|
398
412
|
results.unknown[unknownType][name] += fileSize;
|
|
399
413
|
results.unknown.bytes += fileSize;
|
|
400
414
|
continue;
|
|
401
415
|
}
|
|
402
416
|
// Add language and bytes data to corresponding section
|
|
403
417
|
const { type } = langData[lang];
|
|
404
|
-
(
|
|
418
|
+
(_q = (_s = results.languages.results)[lang]) !== null && _q !== void 0 ? _q : (_s[lang] = { type, bytes: 0, color: langData[lang].color });
|
|
405
419
|
if (opts.childLanguages) {
|
|
406
420
|
results.languages.results[lang].parent = langData[lang].group;
|
|
407
421
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -4,6 +4,10 @@ export type Category = 'data' | 'markup' | 'programming' | 'prose';
|
|
|
4
4
|
export type FilePath = string;
|
|
5
5
|
export type Bytes = Integer;
|
|
6
6
|
export type Integer = number;
|
|
7
|
+
export type RelFile = string & {};
|
|
8
|
+
export type AbsFile = string & {};
|
|
9
|
+
export type AbsFolder = string & {};
|
|
10
|
+
export type FileGlob = string & {};
|
|
7
11
|
export interface Options {
|
|
8
12
|
fileContent?: string | string[];
|
|
9
13
|
ignoredFiles?: string[];
|
package/ext/generated.rb
CHANGED
package/ext/heuristics.yml
CHANGED
|
@@ -45,7 +45,7 @@ disambiguations:
|
|
|
45
45
|
- language: Public Key
|
|
46
46
|
pattern: '^(----[- ]BEGIN|ssh-(rsa|dss)) '
|
|
47
47
|
- language: AsciiDoc
|
|
48
|
-
pattern: '^[=-]
|
|
48
|
+
pattern: '^[=-]+\s|\{\{[A-Za-z]'
|
|
49
49
|
- language: AGS Script
|
|
50
50
|
pattern: '^(\/\/.+|((import|export)\s+)?(function|int|float|char)\s+((room|repeatedly|on|game)_)?([A-Za-z]+[A-Za-z_0-9]+)\s*[;\(])'
|
|
51
51
|
- extensions: ['.asm']
|
|
@@ -101,6 +101,8 @@ disambiguations:
|
|
|
101
101
|
- (?i:^\s*(end\ssub)$)
|
|
102
102
|
- (?i:^\s*(?=^function\s)(?:function\s*\w+\(.*?\)\s*as\s*\w*)|(?::\s*function\(.*?\)\s*as\s*\w*)$)
|
|
103
103
|
- (?i:^\s*(end\sfunction)$)
|
|
104
|
+
- language: Bluespec BH
|
|
105
|
+
pattern: '^package\s+[A-Za-z_][A-Za-z0-9_'']*(?:\s*\(|\s+where)'
|
|
104
106
|
- extensions: ['.builds']
|
|
105
107
|
rules:
|
|
106
108
|
- language: XML
|
|
@@ -132,7 +134,7 @@ disambiguations:
|
|
|
132
134
|
- extensions: ['.cmp']
|
|
133
135
|
rules:
|
|
134
136
|
- language: Gerber Image
|
|
135
|
-
pattern: '^[DGMT][0-9]{2}
|
|
137
|
+
pattern: '^[DGMT][0-9]{2}\*(?:\r?\n|\r)'
|
|
136
138
|
- extensions: ['.cs']
|
|
137
139
|
rules:
|
|
138
140
|
- language: Smalltalk
|
|
@@ -242,7 +244,7 @@ disambiguations:
|
|
|
242
244
|
- extensions: ['.ftl']
|
|
243
245
|
rules:
|
|
244
246
|
- language: FreeMarker
|
|
245
|
-
pattern: '^(?:<|[a-zA-Z-][a-zA-Z0-9_-]+[ \t]+\w)|\$\{\w+[^\n]*?\}|^[ \t]*(?:<#--.*?-->|<#([a-z]+)(?=\s|>)[^>]*>.*?</#\1>|\[#--.*?--\]|\[#([a-z]+)(?=\s|\])[^\]]*\].*?\[#\2\])'
|
|
247
|
+
pattern: '^(?:<|[a-zA-Z-][a-zA-Z0-9_-]+[ \t]+\w)|\$\{\w+[^\r\n]*?\}|^[ \t]*(?:<#--.*?-->|<#([a-z]+)(?=\s|>)[^>]*>.*?</#\1>|\[#--.*?--\]|\[#([a-z]+)(?=\s|\])[^\]]*\].*?\[#\2\])'
|
|
246
248
|
- language: Fluent
|
|
247
249
|
pattern: '^-?[a-zA-Z][a-zA-Z0-9_-]* *=|\{\$-?[a-zA-Z][-\w]*(?:\.[a-zA-Z][-\w]*)?\}'
|
|
248
250
|
- extensions: ['.g']
|
|
@@ -250,7 +252,7 @@ disambiguations:
|
|
|
250
252
|
- language: GAP
|
|
251
253
|
pattern: '\s*(Declare|BindGlobal|KeyDependentOperation|Install(Method|GlobalFunction)|SetPackageInfo)'
|
|
252
254
|
- language: G-code
|
|
253
|
-
pattern: '^[MG][0-9]
|
|
255
|
+
pattern: '^[MG][0-9]+(?:\r?\n|\r)'
|
|
254
256
|
- extensions: ['.gd']
|
|
255
257
|
rules:
|
|
256
258
|
- language: GAP
|
|
@@ -350,6 +352,12 @@ disambiguations:
|
|
|
350
352
|
pattern: '^\.[A-Za-z]{2}(\s|$)'
|
|
351
353
|
- language: PicoLisp
|
|
352
354
|
pattern: '^\((de|class|rel|code|data|must)\s'
|
|
355
|
+
- extensions: ['.lean']
|
|
356
|
+
rules:
|
|
357
|
+
- language: Lean
|
|
358
|
+
pattern: '^import [a-z]'
|
|
359
|
+
- language: Lean 4
|
|
360
|
+
pattern: '^import [A-Z]'
|
|
353
361
|
- extensions: ['.ls']
|
|
354
362
|
rules:
|
|
355
363
|
- language: LoomScript
|
|
@@ -395,7 +403,7 @@ disambiguations:
|
|
|
395
403
|
- language: Win32 Message File
|
|
396
404
|
pattern: '(?i)^[ \t]*(?>\/\*\s*)?MessageId=|^\.$'
|
|
397
405
|
- language: M4
|
|
398
|
-
pattern: '^dnl|^divert\((?:-?\d+)?\)|^\w+\(`[^\n]*?''[),]'
|
|
406
|
+
pattern: '^dnl|^divert\((?:-?\d+)?\)|^\w+\(`[^\r\n]*?''[),]'
|
|
399
407
|
- language: Monkey C
|
|
400
408
|
pattern: '\b(?:using|module|function|class|var)\s+\w'
|
|
401
409
|
- extensions: ['.md']
|
|
@@ -440,7 +448,7 @@ disambiguations:
|
|
|
440
448
|
- language: XML
|
|
441
449
|
pattern: '^\s*<\?xml\s+version'
|
|
442
450
|
- language: Gerber Image
|
|
443
|
-
pattern: '^[DGMT][0-9]{2}
|
|
451
|
+
pattern: '^[DGMT][0-9]{2}\*(?:\r?\n|\r)'
|
|
444
452
|
- language: Text
|
|
445
453
|
pattern: 'THE_TITLE'
|
|
446
454
|
- extensions: ['.nl']
|
|
@@ -504,7 +512,7 @@ disambiguations:
|
|
|
504
512
|
- extensions: ['.pod']
|
|
505
513
|
rules:
|
|
506
514
|
- language: Pod 6
|
|
507
|
-
pattern: '^[\s&&[^\n]]*=(comment|begin pod|begin para|item\d+)'
|
|
515
|
+
pattern: '^[\s&&[^\r\n]]*=(comment|begin pod|begin para|item\d+)'
|
|
508
516
|
- language: Pod
|
|
509
517
|
- extensions: ['.pp']
|
|
510
518
|
rules:
|
|
@@ -543,7 +551,7 @@ disambiguations:
|
|
|
543
551
|
- extensions: ['.q']
|
|
544
552
|
rules:
|
|
545
553
|
- language: q
|
|
546
|
-
pattern: '((?i:[A-Z.][\w.]*:\{)
|
|
554
|
+
pattern: '((?i:[A-Z.][\w.]*:\{)|^\\(cd?|d|l|p|ts?) )'
|
|
547
555
|
- language: HiveQL
|
|
548
556
|
pattern: '(?i:SELECT\s+[\w*,]+\s+FROM|(CREATE|ALTER|DROP)\s(DATABASE|SCHEMA|TABLE))'
|
|
549
557
|
- extensions: ['.qs']
|
|
@@ -556,6 +564,8 @@ disambiguations:
|
|
|
556
564
|
rules:
|
|
557
565
|
- language: Rebol
|
|
558
566
|
pattern: '(?i:\bRebol\b)'
|
|
567
|
+
- language: Rez
|
|
568
|
+
pattern: '(#include\s+["<](Types\.r|Carbon\/Carbon\.r)[">])|((resource|data|type)\s+''[A-Za-z0-9]{4}''\s+((\(.*\)\s+){0,1}){)'
|
|
559
569
|
- language: R
|
|
560
570
|
pattern: '<-|^\s*#'
|
|
561
571
|
- extensions: ['.re']
|
|
@@ -615,7 +625,7 @@ disambiguations:
|
|
|
615
625
|
- language: Solidity
|
|
616
626
|
pattern: '\bpragma\s+solidity\b|\b(?:abstract\s+)?contract\s+(?!\d)[a-zA-Z0-9$_]+(?:\s+is\s+(?:[a-zA-Z0-9$_][^\{]*?)?)?\s*\{'
|
|
617
627
|
- language: Gerber Image
|
|
618
|
-
pattern: '^[DGMT][0-9]{2}
|
|
628
|
+
pattern: '^[DGMT][0-9]{2}\*(?:\r?\n|\r)'
|
|
619
629
|
- extensions: ['.sql']
|
|
620
630
|
rules:
|
|
621
631
|
- language: PLpgSQL
|
|
@@ -645,7 +655,7 @@ disambiguations:
|
|
|
645
655
|
- extensions: ['.stl']
|
|
646
656
|
rules:
|
|
647
657
|
- language: STL
|
|
648
|
-
pattern: '\A\s*solid(
|
|
658
|
+
pattern: '\A\s*solid(?:$|\s)[\s\S]*^endsolid(?:$|\s)'
|
|
649
659
|
- extensions: ['.sw']
|
|
650
660
|
rules:
|
|
651
661
|
- language: Sway
|
|
@@ -699,10 +709,15 @@ disambiguations:
|
|
|
699
709
|
- language: Adblock Filter List
|
|
700
710
|
pattern: '\A\[(?<version>(?:[Aa]d[Bb]lock(?:[ \t][Pp]lus)?|u[Bb]lock(?:[ \t][Oo]rigin)?|[Aa]d[Gg]uard)(?:[ \t] \d+(?:\.\d+)*+)?)(?:[ \t]?;[ \t]?\g<version>)*+\]'
|
|
701
711
|
- language: Text
|
|
712
|
+
- extensions: ['.typ']
|
|
713
|
+
rules:
|
|
714
|
+
- language: Typst
|
|
715
|
+
pattern: '^#(import|show|let|set)'
|
|
716
|
+
- language: XML
|
|
702
717
|
- extensions: ['.url']
|
|
703
718
|
rules:
|
|
704
719
|
- language: INI
|
|
705
|
-
pattern: '^\[InternetShortcut\](?:\r?\n|\r)(?>[^\s\[][^\n]*(?:\r?\n|\r))*URL='
|
|
720
|
+
pattern: '^\[InternetShortcut\](?:\r?\n|\r)(?>[^\s\[][^\r\n]*(?:\r?\n|\r))*URL='
|
|
706
721
|
- extensions: ['.v']
|
|
707
722
|
rules:
|
|
708
723
|
- language: Coq
|
package/ext/languages.yml
CHANGED
|
@@ -606,9 +606,28 @@ Bluespec:
|
|
|
606
606
|
color: "#12223c"
|
|
607
607
|
extensions:
|
|
608
608
|
- ".bsv"
|
|
609
|
+
aliases:
|
|
610
|
+
- bluespec bsv
|
|
611
|
+
- bsv
|
|
609
612
|
tm_scope: source.bsv
|
|
610
613
|
ace_mode: verilog
|
|
614
|
+
codemirror_mode: verilog
|
|
615
|
+
codemirror_mime_type: text/x-systemverilog
|
|
611
616
|
language_id: 36
|
|
617
|
+
Bluespec BH:
|
|
618
|
+
type: programming
|
|
619
|
+
group: Bluespec
|
|
620
|
+
color: "#12223c"
|
|
621
|
+
extensions:
|
|
622
|
+
- ".bs"
|
|
623
|
+
aliases:
|
|
624
|
+
- bh
|
|
625
|
+
- bluespec classic
|
|
626
|
+
tm_scope: source.haskell
|
|
627
|
+
ace_mode: haskell
|
|
628
|
+
codemirror_mode: haskell
|
|
629
|
+
codemirror_mime_type: text/x-haskell
|
|
630
|
+
language_id: 641580358
|
|
612
631
|
Boo:
|
|
613
632
|
type: programming
|
|
614
633
|
color: "#d4bec1"
|
|
@@ -1607,7 +1626,7 @@ ECL:
|
|
|
1607
1626
|
ECLiPSe:
|
|
1608
1627
|
type: programming
|
|
1609
1628
|
color: "#001d9d"
|
|
1610
|
-
group:
|
|
1629
|
+
group: Prolog
|
|
1611
1630
|
extensions:
|
|
1612
1631
|
- ".ecl"
|
|
1613
1632
|
tm_scope: source.prolog.eclipse
|
|
@@ -1689,6 +1708,17 @@ Ecmarkup:
|
|
|
1689
1708
|
aliases:
|
|
1690
1709
|
- ecmarkdown
|
|
1691
1710
|
language_id: 844766630
|
|
1711
|
+
EdgeQL:
|
|
1712
|
+
type: programming
|
|
1713
|
+
color: "#31A7FF"
|
|
1714
|
+
aliases:
|
|
1715
|
+
- esdl
|
|
1716
|
+
extensions:
|
|
1717
|
+
- ".edgeql"
|
|
1718
|
+
- ".esdl"
|
|
1719
|
+
ace_mode: text
|
|
1720
|
+
tm_scope: source.edgeql
|
|
1721
|
+
language_id: 925235833
|
|
1692
1722
|
EditorConfig:
|
|
1693
1723
|
type: data
|
|
1694
1724
|
color: "#fff1f2"
|
|
@@ -2144,6 +2174,7 @@ GLSL:
|
|
|
2144
2174
|
- ".tese"
|
|
2145
2175
|
- ".vert"
|
|
2146
2176
|
- ".vrx"
|
|
2177
|
+
- ".vs"
|
|
2147
2178
|
- ".vsh"
|
|
2148
2179
|
- ".vshader"
|
|
2149
2180
|
tm_scope: source.glsl
|
|
@@ -2205,20 +2236,20 @@ Gemini:
|
|
|
2205
2236
|
wrap: true
|
|
2206
2237
|
tm_scope: source.gemini
|
|
2207
2238
|
language_id: 310828396
|
|
2208
|
-
Genero:
|
|
2239
|
+
Genero 4gl:
|
|
2209
2240
|
type: programming
|
|
2210
2241
|
color: "#63408e"
|
|
2211
2242
|
extensions:
|
|
2212
2243
|
- ".4gl"
|
|
2213
|
-
tm_scope: source.genero
|
|
2244
|
+
tm_scope: source.genero-4gl
|
|
2214
2245
|
ace_mode: text
|
|
2215
2246
|
language_id: 986054050
|
|
2216
|
-
Genero
|
|
2247
|
+
Genero per:
|
|
2217
2248
|
type: markup
|
|
2218
2249
|
color: "#d8df39"
|
|
2219
2250
|
extensions:
|
|
2220
2251
|
- ".per"
|
|
2221
|
-
tm_scope: source.genero-
|
|
2252
|
+
tm_scope: source.genero-per
|
|
2222
2253
|
ace_mode: text
|
|
2223
2254
|
language_id: 902995658
|
|
2224
2255
|
Genie:
|
|
@@ -2316,7 +2347,6 @@ Gherkin:
|
|
|
2316
2347
|
Git Attributes:
|
|
2317
2348
|
type: data
|
|
2318
2349
|
color: "#F44D27"
|
|
2319
|
-
group: INI
|
|
2320
2350
|
aliases:
|
|
2321
2351
|
- gitattributes
|
|
2322
2352
|
filenames:
|
|
@@ -2361,6 +2391,15 @@ Gleam:
|
|
|
2361
2391
|
- ".gleam"
|
|
2362
2392
|
tm_scope: source.gleam
|
|
2363
2393
|
language_id: 1054258749
|
|
2394
|
+
Glimmer JS:
|
|
2395
|
+
type: programming
|
|
2396
|
+
extensions:
|
|
2397
|
+
- ".gjs"
|
|
2398
|
+
ace_mode: javascript
|
|
2399
|
+
color: "#F5835F"
|
|
2400
|
+
tm_scope: source.gjs
|
|
2401
|
+
group: JavaScript
|
|
2402
|
+
language_id: 5523150
|
|
2364
2403
|
Glyph:
|
|
2365
2404
|
type: programming
|
|
2366
2405
|
color: "#c1ac7f"
|
|
@@ -2489,6 +2528,15 @@ Gradle:
|
|
|
2489
2528
|
tm_scope: source.groovy.gradle
|
|
2490
2529
|
ace_mode: text
|
|
2491
2530
|
language_id: 136
|
|
2531
|
+
Gradle Kotlin DSL:
|
|
2532
|
+
group: Gradle
|
|
2533
|
+
type: data
|
|
2534
|
+
color: "#02303a"
|
|
2535
|
+
extensions:
|
|
2536
|
+
- ".gradle.kts"
|
|
2537
|
+
ace_mode: text
|
|
2538
|
+
tm_scope: source.kotlin
|
|
2539
|
+
language_id: 432600901
|
|
2492
2540
|
Grammatical Framework:
|
|
2493
2541
|
type: programming
|
|
2494
2542
|
aliases:
|
|
@@ -2603,8 +2651,8 @@ HOCON:
|
|
|
2603
2651
|
extensions:
|
|
2604
2652
|
- ".hocon"
|
|
2605
2653
|
filenames:
|
|
2606
|
-
- .scalafix.conf
|
|
2607
|
-
- .scalafmt.conf
|
|
2654
|
+
- ".scalafix.conf"
|
|
2655
|
+
- ".scalafmt.conf"
|
|
2608
2656
|
tm_scope: source.hocon
|
|
2609
2657
|
ace_mode: text
|
|
2610
2658
|
language_id: 679725279
|
|
@@ -2812,6 +2860,8 @@ Hosts File:
|
|
|
2812
2860
|
filenames:
|
|
2813
2861
|
- HOSTS
|
|
2814
2862
|
- hosts
|
|
2863
|
+
aliases:
|
|
2864
|
+
- hosts
|
|
2815
2865
|
tm_scope: source.hosts
|
|
2816
2866
|
ace_mode: text
|
|
2817
2867
|
language_id: 231021894
|
|
@@ -2910,7 +2960,6 @@ Idris:
|
|
|
2910
2960
|
Ignore List:
|
|
2911
2961
|
type: data
|
|
2912
2962
|
color: "#000000"
|
|
2913
|
-
group: INI
|
|
2914
2963
|
aliases:
|
|
2915
2964
|
- ignore
|
|
2916
2965
|
- gitignore
|
|
@@ -3104,6 +3153,7 @@ JSON:
|
|
|
3104
3153
|
- ".watchmanconfig"
|
|
3105
3154
|
- Pipfile.lock
|
|
3106
3155
|
- composer.lock
|
|
3156
|
+
- deno.lock
|
|
3107
3157
|
- flake.lock
|
|
3108
3158
|
- mcmod.info
|
|
3109
3159
|
language_id: 174
|
|
@@ -3120,6 +3170,7 @@ JSON with Comments:
|
|
|
3120
3170
|
extensions:
|
|
3121
3171
|
- ".jsonc"
|
|
3122
3172
|
- ".code-snippets"
|
|
3173
|
+
- ".code-workspace"
|
|
3123
3174
|
- ".sublime-build"
|
|
3124
3175
|
- ".sublime-commands"
|
|
3125
3176
|
- ".sublime-completions"
|
|
@@ -3623,6 +3674,14 @@ Lean:
|
|
|
3623
3674
|
tm_scope: source.lean
|
|
3624
3675
|
ace_mode: text
|
|
3625
3676
|
language_id: 197
|
|
3677
|
+
Lean 4:
|
|
3678
|
+
type: programming
|
|
3679
|
+
group: Lean
|
|
3680
|
+
extensions:
|
|
3681
|
+
- ".lean"
|
|
3682
|
+
tm_scope: source.lean4
|
|
3683
|
+
ace_mode: text
|
|
3684
|
+
language_id: 455147478
|
|
3626
3685
|
Less:
|
|
3627
3686
|
type: markup
|
|
3628
3687
|
color: "#1d365d"
|
|
@@ -4374,7 +4433,7 @@ Nasal:
|
|
|
4374
4433
|
extensions:
|
|
4375
4434
|
- ".nas"
|
|
4376
4435
|
tm_scope: source.nasal
|
|
4377
|
-
ace_mode:
|
|
4436
|
+
ace_mode: nasal
|
|
4378
4437
|
language_id: 178322513
|
|
4379
4438
|
Nearley:
|
|
4380
4439
|
type: programming
|
|
@@ -4823,6 +4882,8 @@ Option List:
|
|
|
4823
4882
|
- ackrc
|
|
4824
4883
|
filenames:
|
|
4825
4884
|
- ".ackrc"
|
|
4885
|
+
- ".rspec"
|
|
4886
|
+
- ".yardopts"
|
|
4826
4887
|
- ackrc
|
|
4827
4888
|
- mocha.opts
|
|
4828
4889
|
tm_scope: source.opts
|
|
@@ -5101,6 +5162,8 @@ Pic:
|
|
|
5101
5162
|
extensions:
|
|
5102
5163
|
- ".pic"
|
|
5103
5164
|
- ".chem"
|
|
5165
|
+
aliases:
|
|
5166
|
+
- pikchr
|
|
5104
5167
|
ace_mode: text
|
|
5105
5168
|
codemirror_mode: troff
|
|
5106
5169
|
codemirror_mime_type: text/troff
|
|
@@ -5257,6 +5320,14 @@ PowerShell:
|
|
|
5257
5320
|
interpreters:
|
|
5258
5321
|
- pwsh
|
|
5259
5322
|
language_id: 293
|
|
5323
|
+
Praat:
|
|
5324
|
+
type: programming
|
|
5325
|
+
color: "#c8506d"
|
|
5326
|
+
tm_scope: source.praat
|
|
5327
|
+
ace_mode: praat
|
|
5328
|
+
extensions:
|
|
5329
|
+
- ".praat"
|
|
5330
|
+
language_id: 106029007
|
|
5260
5331
|
Prisma:
|
|
5261
5332
|
type: data
|
|
5262
5333
|
color: "#0c344b"
|
|
@@ -5851,6 +5922,14 @@ RenderScript:
|
|
|
5851
5922
|
tm_scope: none
|
|
5852
5923
|
ace_mode: text
|
|
5853
5924
|
language_id: 323
|
|
5925
|
+
Rez:
|
|
5926
|
+
type: programming
|
|
5927
|
+
extensions:
|
|
5928
|
+
- ".r"
|
|
5929
|
+
tm_scope: source.rez
|
|
5930
|
+
ace_mode: text
|
|
5931
|
+
color: "#FFDAB3"
|
|
5932
|
+
language_id: 498022874
|
|
5854
5933
|
Rich Text Format:
|
|
5855
5934
|
type: markup
|
|
5856
5935
|
extensions:
|
|
@@ -6740,7 +6819,7 @@ Svelte:
|
|
|
6740
6819
|
language_id: 928734530
|
|
6741
6820
|
Sway:
|
|
6742
6821
|
type: programming
|
|
6743
|
-
color: "#
|
|
6822
|
+
color: "#00F58C"
|
|
6744
6823
|
extensions:
|
|
6745
6824
|
- ".sw"
|
|
6746
6825
|
tm_scope: source.sway
|
|
@@ -6748,6 +6827,14 @@ Sway:
|
|
|
6748
6827
|
codemirror_mode: rust
|
|
6749
6828
|
codemirror_mime_type: text/x-rustsrc
|
|
6750
6829
|
language_id: 271471144
|
|
6830
|
+
Sweave:
|
|
6831
|
+
type: prose
|
|
6832
|
+
color: "#198ce7"
|
|
6833
|
+
extensions:
|
|
6834
|
+
- ".rnw"
|
|
6835
|
+
tm_scope: text.tex.latex.sweave
|
|
6836
|
+
ace_mode: tex
|
|
6837
|
+
language_id: 558779190
|
|
6751
6838
|
Swift:
|
|
6752
6839
|
type: programming
|
|
6753
6840
|
color: "#F05138"
|
|
@@ -6784,7 +6871,7 @@ TI Program:
|
|
|
6784
6871
|
TL-Verilog:
|
|
6785
6872
|
type: programming
|
|
6786
6873
|
extensions:
|
|
6787
|
-
|
|
6874
|
+
- ".tlv"
|
|
6788
6875
|
tm_scope: source.tlverilog
|
|
6789
6876
|
ace_mode: verilog
|
|
6790
6877
|
color: "#C40023"
|
|
@@ -6939,6 +7026,17 @@ Terra:
|
|
|
6939
7026
|
interpreters:
|
|
6940
7027
|
- lua
|
|
6941
7028
|
language_id: 371
|
|
7029
|
+
Terraform Template:
|
|
7030
|
+
type: markup
|
|
7031
|
+
extensions:
|
|
7032
|
+
- ".tftpl"
|
|
7033
|
+
color: "#7b42bb"
|
|
7034
|
+
tm_scope: source.hcl.terraform
|
|
7035
|
+
ace_mode: ruby
|
|
7036
|
+
codemirror_mode: ruby
|
|
7037
|
+
codemirror_mime_type: text/x-ruby
|
|
7038
|
+
group: HCL
|
|
7039
|
+
language_id: 856832701
|
|
6942
7040
|
Texinfo:
|
|
6943
7041
|
type: prose
|
|
6944
7042
|
wrap: true
|
|
@@ -7023,6 +7121,14 @@ Thrift:
|
|
|
7023
7121
|
- ".thrift"
|
|
7024
7122
|
ace_mode: text
|
|
7025
7123
|
language_id: 374
|
|
7124
|
+
Toit:
|
|
7125
|
+
type: programming
|
|
7126
|
+
color: "#c2c9fb"
|
|
7127
|
+
extensions:
|
|
7128
|
+
- ".toit"
|
|
7129
|
+
tm_scope: source.toit
|
|
7130
|
+
ace_mode: text
|
|
7131
|
+
language_id: 356554395
|
|
7026
7132
|
Turing:
|
|
7027
7133
|
type: programming
|
|
7028
7134
|
color: "#cf142b"
|
|
@@ -7077,6 +7183,16 @@ TypeScript:
|
|
|
7077
7183
|
codemirror_mode: javascript
|
|
7078
7184
|
codemirror_mime_type: application/typescript
|
|
7079
7185
|
language_id: 378
|
|
7186
|
+
Typst:
|
|
7187
|
+
type: programming
|
|
7188
|
+
color: "#239dad"
|
|
7189
|
+
aliases:
|
|
7190
|
+
- typ
|
|
7191
|
+
extensions:
|
|
7192
|
+
- ".typ"
|
|
7193
|
+
tm_scope: source.typst
|
|
7194
|
+
ace_mode: text
|
|
7195
|
+
language_id: 704730682
|
|
7080
7196
|
Unified Parallel C:
|
|
7081
7197
|
type: programming
|
|
7082
7198
|
color: "#4e3617"
|
|
@@ -7687,6 +7803,7 @@ XML:
|
|
|
7687
7803
|
- ".tml"
|
|
7688
7804
|
- ".ts"
|
|
7689
7805
|
- ".tsx"
|
|
7806
|
+
- ".typ"
|
|
7690
7807
|
- ".ui"
|
|
7691
7808
|
- ".urdf"
|
|
7692
7809
|
- ".ux"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "linguist-js",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.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": {
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
"commander": "^9.5.0 <10",
|
|
43
43
|
"common-path-prefix": "^3.0.0",
|
|
44
44
|
"cross-fetch": "^3.1.8 <4",
|
|
45
|
-
"ignore": "^5.
|
|
45
|
+
"ignore": "^5.3.1",
|
|
46
46
|
"isbinaryfile": "^4.0.10 <5",
|
|
47
47
|
"js-yaml": "^4.1.0",
|
|
48
48
|
"node-cache": "^5.1.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@types/js-yaml": "^4.0.
|
|
51
|
+
"@types/js-yaml": "^4.0.9",
|
|
52
52
|
"@types/node": "ts5.0",
|
|
53
53
|
"deep-object-diff": "^1.1.9",
|
|
54
54
|
"typescript": "~5.0.4 <5.1"
|
package/readme.md
CHANGED
|
@@ -95,9 +95,17 @@ Running LinguistJS on this folder will return the following JSON:
|
|
|
95
95
|
|
|
96
96
|
```js
|
|
97
97
|
const linguist = require('linguist-js');
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const
|
|
98
|
+
|
|
99
|
+
// Analyse folder on disc
|
|
100
|
+
const folder = './src';
|
|
101
|
+
const options = { keepVendored: false, quick: false };
|
|
102
|
+
const { files, languages, unknown } = await linguist(folder, options);
|
|
103
|
+
|
|
104
|
+
// Analyse file content from raw input
|
|
105
|
+
const fileNames = ['file1.ts', 'file2.ts', 'ignoreme.js'];
|
|
106
|
+
const fileContent = ['#!/usr/bin/env node', 'console.log("Example");', '"ignored"'];
|
|
107
|
+
const options = { ignoredFiles: ['ignore*'] };
|
|
108
|
+
const { files, languages, unknown } = await linguist(fileNames, { fileContent, ...options });
|
|
101
109
|
```
|
|
102
110
|
|
|
103
111
|
- `linguist(entry?, opts?)` (default export):
|
|
@@ -122,7 +130,7 @@ const { files, languages, unknown } = linguist(folder, options);
|
|
|
122
130
|
Alias for `checkAttributes:false, checkIgnored:false, checkHeuristics:false, checkShebang:false, checkModeline:false`.
|
|
123
131
|
- `offline` (boolean):
|
|
124
132
|
Whether to use pre-packaged metadata files instead of fetching them from GitHub at runtime (defaults to `false`).
|
|
125
|
-
|
|
133
|
+
- `keepVendored` (boolean):
|
|
126
134
|
Whether to keep vendored files (dependencies, etc) (defaults to `false`).
|
|
127
135
|
Does nothing when `fileContent` is set.
|
|
128
136
|
- `keepBinary` (boolean):
|
|
@@ -160,14 +168,20 @@ linguist --version
|
|
|
160
168
|
A list of languages to exclude from the output.
|
|
161
169
|
- `--categories <categories...>`:
|
|
162
170
|
A list of language categories that should be displayed in the output.
|
|
163
|
-
|
|
171
|
+
Must be one or more of `data`, `prose`, `programming`, `markup`.
|
|
164
172
|
- `--childLanguages`:
|
|
165
173
|
Display sub-languages instead of their parents, when possible.
|
|
166
174
|
- `--json`:
|
|
175
|
+
Only affects the CLI output.
|
|
167
176
|
Display the outputted language data as JSON.
|
|
168
177
|
- `--tree <traversal>`:
|
|
178
|
+
Only affects the CLI output.
|
|
169
179
|
A dot-delimited traversal to the nested object that should be logged to the console instead of the entire output.
|
|
170
180
|
Requires `--json` to be specified.
|
|
181
|
+
- `--listFiles`:
|
|
182
|
+
Only affects the visual CLI output.
|
|
183
|
+
List each matching file and its size under each outputted language result.
|
|
184
|
+
Does nothing if `--json` is specified.
|
|
171
185
|
- `--quick`:
|
|
172
186
|
Skip the checking of `.gitattributes` and `.gitignore` files for manual language classifications.
|
|
173
187
|
Alias for `--checkAttributes=false --checkIgnored=false --checkHeuristics=false --checkShebang=false --checkModeline=false`.
|