linguist-js 2.9.0 → 2.9.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.
Files changed (38) hide show
  1. package/dist/cli.js +7 -0
  2. package/dist/helpers/convert-pcre.js +1 -1
  3. package/dist/helpers/load-data.js +2 -3
  4. package/dist/helpers/parse-gitattributes.js +1 -1
  5. package/dist/helpers/parse-gitignore.js +1 -1
  6. package/dist/helpers/read-file.js +1 -1
  7. package/dist/helpers/walk-tree.js +1 -1
  8. package/dist/index.js +1 -1
  9. package/ext/generated.rb +1 -1
  10. package/ext/heuristics.yml +45 -14
  11. package/ext/languages.yml +42 -3
  12. package/license.md +1 -1
  13. package/package.json +2 -2
  14. package/dist/package.json +0 -56
  15. package/dist/src/cli.d.ts +0 -1
  16. package/dist/src/cli.js +0 -146
  17. package/dist/src/helpers/convert-pcre.d.ts +0 -2
  18. package/dist/src/helpers/convert-pcre.js +0 -38
  19. package/dist/src/helpers/load-data.d.ts +0 -4
  20. package/dist/src/helpers/load-data.js +0 -37
  21. package/dist/src/helpers/norm-path.d.ts +0 -2
  22. package/dist/src/helpers/norm-path.js +0 -15
  23. package/dist/src/helpers/parse-gitattributes.d.ts +0 -17
  24. package/dist/src/helpers/parse-gitattributes.js +0 -37
  25. package/dist/src/helpers/parse-gitignore.d.ts +0 -1
  26. package/dist/src/helpers/parse-gitignore.js +0 -12
  27. package/dist/src/helpers/read-file.d.ts +0 -5
  28. package/dist/src/helpers/read-file.js +0 -23
  29. package/dist/src/helpers/walk-tree.d.ts +0 -20
  30. package/dist/src/helpers/walk-tree.js +0 -85
  31. package/dist/src/index.d.ts +0 -4
  32. package/dist/src/index.js +0 -485
  33. package/dist/src/schema.d.ts +0 -37
  34. package/dist/src/schema.js +0 -2
  35. package/dist/src/types.d.ts +0 -74
  36. package/dist/src/types.js +0 -2
  37. package/dist/version.d.ts +0 -2
  38. package/dist/version.js +0 -4
package/dist/src/index.js DELETED
@@ -1,485 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- const node_fs_1 = __importDefault(require("node:fs"));
30
- const node_path_1 = __importDefault(require("node:path"));
31
- const js_yaml_1 = __importDefault(require("js-yaml"));
32
- const ignore_1 = __importDefault(require("ignore"));
33
- const common_path_prefix_1 = __importDefault(require("common-path-prefix"));
34
- const binary_extensions_1 = __importDefault(require("binary-extensions"));
35
- const isbinaryfile_1 = require("isbinaryfile");
36
- const walk_tree_1 = __importDefault(require("./helpers/walk-tree"));
37
- const load_data_1 = __importStar(require("./helpers/load-data"));
38
- const read_file_1 = __importDefault(require("./helpers/read-file"));
39
- const parse_gitattributes_1 = __importDefault(require("./helpers/parse-gitattributes"));
40
- const convert_pcre_1 = __importDefault(require("./helpers/convert-pcre"));
41
- const norm_path_1 = require("./helpers/norm-path");
42
- async function analyse(rawPaths, opts = {}) {
43
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
44
- var _u, _v;
45
- const useRawContent = opts.fileContent !== undefined;
46
- const input = [rawPaths !== null && rawPaths !== void 0 ? rawPaths : []].flat();
47
- const manualFileContent = [(_a = opts.fileContent) !== null && _a !== void 0 ? _a : []].flat();
48
- // Normalise input option arguments
49
- opts = {
50
- calculateLines: (_b = opts.calculateLines) !== null && _b !== void 0 ? _b : true, // default to true if unset
51
- checkIgnored: !opts.quick,
52
- checkDetected: !opts.quick,
53
- checkAttributes: !opts.quick,
54
- checkHeuristics: !opts.quick,
55
- checkShebang: !opts.quick,
56
- checkModeline: !opts.quick,
57
- ...opts,
58
- };
59
- // Load data from github-linguist web repo
60
- const langData = await (0, load_data_1.default)('languages.yml', opts.offline).then(js_yaml_1.default.load);
61
- const vendorData = await (0, load_data_1.default)('vendor.yml', opts.offline).then(js_yaml_1.default.load);
62
- const docData = await (0, load_data_1.default)('documentation.yml', opts.offline).then(js_yaml_1.default.load);
63
- const heuristicsData = await (0, load_data_1.default)('heuristics.yml', opts.offline).then(js_yaml_1.default.load);
64
- const generatedData = await (0, load_data_1.default)('generated.rb', opts.offline).then(load_data_1.parseGeneratedDataFile);
65
- const vendorPaths = [...vendorData, ...docData, ...generatedData];
66
- // Setup main variables
67
- const fileAssociations = {};
68
- const extensions = {};
69
- const globOverrides = {};
70
- const results = {
71
- files: { count: 0, bytes: 0, lines: { total: 0, content: 0, code: 0 }, results: {}, alternatives: {} },
72
- languages: { count: 0, bytes: 0, lines: { total: 0, content: 0, code: 0 }, results: {} },
73
- unknown: { count: 0, bytes: 0, lines: { total: 0, content: 0, code: 0 }, extensions: {}, filenames: {} },
74
- };
75
- // Set a common root path so that vendor paths do not incorrectly match parent folders
76
- const resolvedInput = input.map(path => (0, norm_path_1.normPath)(node_path_1.default.resolve(path)));
77
- const commonRoot = (input.length > 1 ? (0, common_path_prefix_1.default)(resolvedInput) : resolvedInput[0]).replace(/\/?$/, '');
78
- const relPath = (file) => useRawContent ? file : (0, norm_path_1.normPath)(node_path_1.default.relative(commonRoot, file));
79
- const unRelPath = (file) => useRawContent ? file : (0, norm_path_1.normPath)(node_path_1.default.resolve(commonRoot, file));
80
- // Other helper functions
81
- const fileMatchesGlobs = (file, ...globs) => (0, ignore_1.default)().add(globs).ignores(relPath(file));
82
- const filterOutIgnored = (files, ignored) => ignored.filter(files.map(relPath)).map(unRelPath);
83
- //*PREPARE FILES AND DATA*//
84
- // Prepare list of ignored files
85
- const ignored = (0, ignore_1.default)();
86
- ignored.add('.git/');
87
- ignored.add((_c = opts.ignoredFiles) !== null && _c !== void 0 ? _c : []);
88
- const regexIgnores = opts.keepVendored ? [] : vendorPaths.map(path => RegExp(path, 'i'));
89
- // Load file paths and folders
90
- let files;
91
- if (useRawContent) {
92
- // Uses raw file content
93
- files = input;
94
- }
95
- else {
96
- // Uses directory on disc
97
- const data = (0, walk_tree_1.default)({ init: true, commonRoot, folderRoots: resolvedInput, folders: resolvedInput, ignored });
98
- files = data.files;
99
- }
100
- // Fetch and normalise gitattributes data of all subfolders and save to metadata
101
- const manualAttributes = {}; // Maps file globs to gitattribute boolean flags
102
- const getFlaggedGlobs = (attr, val) => {
103
- return Object.entries(manualAttributes).filter(([, attrs]) => attrs[attr] === val).map(([glob,]) => glob);
104
- };
105
- const findAttrsForPath = (filePath) => {
106
- const resultAttrs = {};
107
- for (const glob in manualAttributes) {
108
- if ((0, ignore_1.default)().add(glob).ignores(relPath(filePath))) {
109
- const matchingAttrs = manualAttributes[glob];
110
- for (const [attr, val] of Object.entries(matchingAttrs)) {
111
- if (val !== null)
112
- resultAttrs[attr] = val;
113
- }
114
- }
115
- }
116
- if (!JSON.stringify(resultAttrs)) {
117
- return null;
118
- }
119
- return resultAttrs;
120
- };
121
- if (!useRawContent && opts.checkAttributes) {
122
- const nestedAttrFiles = files.filter(file => file.endsWith('.gitattributes'));
123
- for (const attrFile of nestedAttrFiles) {
124
- const relAttrFile = relPath(attrFile);
125
- const relAttrFolder = node_path_1.default.dirname(relAttrFile);
126
- const contents = await (0, read_file_1.default)(attrFile);
127
- const parsed = (0, parse_gitattributes_1.default)(contents, relAttrFolder);
128
- for (const { glob, attrs } of parsed) {
129
- manualAttributes[glob] = attrs;
130
- }
131
- }
132
- }
133
- // Remove files that are linguist-ignored via regex by default unless explicitly unignored in gitattributes
134
- const filesToIgnore = [];
135
- for (const file of files) {
136
- const relFile = relPath(file);
137
- const isRegexIgnored = regexIgnores.some(pattern => pattern.test(relFile));
138
- if (!isRegexIgnored) {
139
- // Checking overrides is moot if file is not even marked as ignored by default
140
- continue;
141
- }
142
- const fileAttrs = findAttrsForPath(file);
143
- if ((fileAttrs === null || fileAttrs === void 0 ? void 0 : fileAttrs.generated) === false || (fileAttrs === null || fileAttrs === void 0 ? void 0 : fileAttrs.vendored) === false) {
144
- // File is explicitly marked as *not* to be ignored
145
- // do nothing
146
- }
147
- else {
148
- filesToIgnore.push(file);
149
- }
150
- }
151
- files = files.filter(file => !filesToIgnore.includes(file));
152
- // Apply vendor file path matches and filter out vendored files
153
- if (!opts.keepVendored) {
154
- // Get data of files that have been manually marked with metadata
155
- const vendorTrueGlobs = [...getFlaggedGlobs('vendored', true), ...getFlaggedGlobs('generated', true), ...getFlaggedGlobs('documentation', true)];
156
- const vendorFalseGlobs = [...getFlaggedGlobs('vendored', false), ...getFlaggedGlobs('generated', false), ...getFlaggedGlobs('documentation', false)];
157
- // Set up glob ignore object to use for expanding globs to match files
158
- const vendorTrueIgnore = (0, ignore_1.default)().add(vendorTrueGlobs);
159
- const vendorFalseIgnore = (0, ignore_1.default)().add(vendorFalseGlobs);
160
- // Remove all files marked as vendored by default
161
- const excludedFiles = files.filter(file => vendorPaths.some(pathPtn => RegExp(pathPtn, 'i').test(relPath(file))));
162
- files = files.filter(file => !excludedFiles.includes(file));
163
- // Re-add removed files that are overridden manually in gitattributes
164
- const overriddenExcludedFiles = excludedFiles.filter(file => vendorFalseIgnore.ignores(relPath(file)));
165
- files.push(...overriddenExcludedFiles);
166
- // Remove files explicitly marked as vendored in gitattributes
167
- files = files.filter(file => !vendorTrueIgnore.ignores(relPath(file)));
168
- }
169
- // Filter out binary files
170
- if (!opts.keepBinary) {
171
- // Filter out files that are binary by default
172
- files = files.filter(file => !binary_extensions_1.default.some(ext => file.endsWith('.' + ext)));
173
- // Filter out manually specified binary files
174
- const binaryIgnored = (0, ignore_1.default)().add(getFlaggedGlobs('binary', true));
175
- files = filterOutIgnored(files, binaryIgnored);
176
- // Re-add files manually marked not as binary
177
- const binaryUnignored = (0, ignore_1.default)().add(getFlaggedGlobs('binary', false));
178
- const unignoredList = filterOutIgnored(files, binaryUnignored);
179
- files.push(...unignoredList);
180
- }
181
- // Ignore specific languages
182
- for (const lang of (_d = opts.ignoredLanguages) !== null && _d !== void 0 ? _d : []) {
183
- for (const key in langData) {
184
- if (lang.toLowerCase() === key.toLowerCase()) {
185
- delete langData[key];
186
- break;
187
- }
188
- }
189
- }
190
- // Establish language overrides taken from gitattributes
191
- const forcedLangs = Object.entries(manualAttributes).filter(([, attrs]) => attrs.language);
192
- for (const [globPath, attrs] of forcedLangs) {
193
- let forcedLang = attrs.language;
194
- if (!forcedLang)
195
- continue;
196
- // If specified language is an alias, associate it with its full name
197
- if (!langData[forcedLang]) {
198
- const overrideLang = Object.entries(langData).find(entry => { var _a; return (_a = entry[1].aliases) === null || _a === void 0 ? void 0 : _a.includes(forcedLang.toLowerCase()); });
199
- if (overrideLang) {
200
- forcedLang = overrideLang[0];
201
- }
202
- }
203
- globOverrides[globPath] = forcedLang;
204
- }
205
- //*PARSE LANGUAGES*//
206
- const addResult = (file, result) => {
207
- if (!fileAssociations[file]) {
208
- fileAssociations[file] = [];
209
- extensions[file] = '';
210
- }
211
- // Set parent to result group if it is present
212
- // Is nullish if either `opts.childLanguages` is set or if there is no group
213
- const finalResult = !opts.childLanguages && result && langData[result] && langData[result].group || result;
214
- if (!fileAssociations[file].includes(finalResult)) {
215
- fileAssociations[file].push(finalResult);
216
- }
217
- extensions[file] = node_path_1.default.extname(file).toLowerCase();
218
- };
219
- const definiteness = {};
220
- const fromShebang = {};
221
- fileLoop: for (const file of files) {
222
- // Check manual override
223
- for (const globMatch in globOverrides) {
224
- if (!fileMatchesGlobs(file, globMatch))
225
- continue;
226
- // If the given file matches the glob, apply the override to the file
227
- const forcedLang = globOverrides[globMatch];
228
- addResult(file, forcedLang);
229
- definiteness[file] = true;
230
- continue fileLoop; // no need to check other heuristics, the classified language has been found
231
- }
232
- // Check first line for readability
233
- let firstLine;
234
- if (useRawContent) {
235
- firstLine = (_f = (_e = manualFileContent[files.indexOf(file)]) === null || _e === void 0 ? void 0 : _e.split('\n')[0]) !== null && _f !== void 0 ? _f : null;
236
- }
237
- else if (node_fs_1.default.existsSync(file) && !node_fs_1.default.lstatSync(file).isDirectory()) {
238
- firstLine = await (0, read_file_1.default)(file, true).catch(() => null);
239
- }
240
- else
241
- continue;
242
- // Skip if file is unreadable or blank
243
- if (firstLine === null)
244
- continue;
245
- // Check first line for explicit classification
246
- const hasShebang = opts.checkShebang && /^#!/.test(firstLine);
247
- const hasModeline = opts.checkModeline && /-\*-|(syntax|filetype|ft)\s*=/.test(firstLine);
248
- if (!opts.quick && (hasShebang || hasModeline)) {
249
- const matches = [];
250
- for (const [lang, data] of Object.entries(langData)) {
251
- const langMatcher = (lang) => `\\b${lang.toLowerCase().replace(/\W/g, '\\$&')}(?![\\w#+*]|-\*-)`;
252
- // Check for interpreter match
253
- if (opts.checkShebang && hasShebang) {
254
- const matchesInterpretor = (_g = data.interpreters) === null || _g === void 0 ? void 0 : _g.some(interpreter => firstLine.match(`\\b${interpreter}\\b`));
255
- if (matchesInterpretor)
256
- matches.push(lang);
257
- }
258
- // Check modeline declaration
259
- if (opts.checkModeline && hasModeline) {
260
- const modelineText = firstLine.toLowerCase().replace(/^.*-\*-(.+)-\*-.*$/, '$1');
261
- const matchesLang = modelineText.match(langMatcher(lang));
262
- const matchesAlias = (_h = data.aliases) === null || _h === void 0 ? void 0 : _h.some(lang => modelineText.match(langMatcher(lang)));
263
- if (matchesLang || matchesAlias)
264
- matches.push(lang);
265
- }
266
- }
267
- // Add identified language(s)
268
- if (matches.length) {
269
- for (const match of matches)
270
- addResult(file, match);
271
- if (matches.length === 1)
272
- definiteness[file] = true;
273
- fromShebang[file] = true;
274
- continue;
275
- }
276
- }
277
- // Search each language
278
- let skipExts = false;
279
- // Check if filename is a match
280
- for (const lang in langData) {
281
- const matchesName = (_j = langData[lang].filenames) === null || _j === void 0 ? void 0 : _j.some(name => node_path_1.default.basename(file.toLowerCase()) === name.toLowerCase());
282
- if (matchesName) {
283
- addResult(file, lang);
284
- skipExts = true;
285
- }
286
- }
287
- // Check if extension is a match
288
- const possibleExts = [];
289
- if (!skipExts)
290
- for (const lang in langData) {
291
- const extMatches = (_k = langData[lang].extensions) === null || _k === void 0 ? void 0 : _k.filter(ext => file.toLowerCase().endsWith(ext.toLowerCase()));
292
- if (extMatches === null || extMatches === void 0 ? void 0 : extMatches.length) {
293
- for (const ext of extMatches)
294
- possibleExts.push({ ext, lang });
295
- }
296
- }
297
- // Apply more specific extension if available
298
- const isComplexExt = (ext) => /\..+\./.test(ext);
299
- const hasComplexExt = possibleExts.some(data => isComplexExt(data.ext));
300
- for (const { ext, lang } of possibleExts) {
301
- if (hasComplexExt && !isComplexExt(ext))
302
- continue;
303
- if (!hasComplexExt && isComplexExt(ext))
304
- continue;
305
- addResult(file, lang);
306
- }
307
- // Fallback to null if no language matches
308
- if (!fileAssociations[file]) {
309
- addResult(file, null);
310
- }
311
- }
312
- // Narrow down file associations to the best fit
313
- for (const file in fileAssociations) {
314
- // Skip if file has explicit association
315
- if (definiteness[file]) {
316
- results.files.results[file] = fileAssociations[file][0];
317
- continue;
318
- }
319
- // Skip binary files
320
- if (!useRawContent && !opts.keepBinary) {
321
- if (await (0, isbinaryfile_1.isBinaryFile)(file))
322
- continue;
323
- }
324
- // Parse heuristics if applicable
325
- if (opts.checkHeuristics)
326
- for (const heuristics of heuristicsData.disambiguations) {
327
- // Make sure the extension matches the current file
328
- if (!fromShebang[file] && !heuristics.extensions.includes(extensions[file]))
329
- continue;
330
- // Load heuristic rules
331
- for (const heuristic of heuristics.rules) {
332
- // Make sure the language is not an array
333
- if (Array.isArray(heuristic.language)) {
334
- heuristic.language = heuristic.language[0];
335
- }
336
- // Make sure the results includes this language
337
- const languageGroup = (_l = langData[heuristic.language]) === null || _l === void 0 ? void 0 : _l.group;
338
- const matchesLang = fileAssociations[file].includes(heuristic.language);
339
- const matchesParent = languageGroup && fileAssociations[file].includes(languageGroup);
340
- if (!matchesLang && !matchesParent)
341
- continue;
342
- // Normalise heuristic data
343
- const patterns = [];
344
- const normalise = (contents) => patterns.push(...[contents].flat());
345
- if (heuristic.pattern)
346
- normalise(heuristic.pattern);
347
- if (heuristic.named_pattern)
348
- normalise(heuristicsData.named_patterns[heuristic.named_pattern]);
349
- if (heuristic.and) {
350
- for (const data of heuristic.and) {
351
- if (data.pattern)
352
- normalise(data.pattern);
353
- if (data.named_pattern)
354
- normalise(heuristicsData.named_patterns[data.named_pattern]);
355
- }
356
- }
357
- // Check file contents and apply heuristic patterns
358
- const fileContent = opts.fileContent ? manualFileContent[files.indexOf(file)] : await (0, read_file_1.default)(file).catch(() => null);
359
- // Skip if file read errors
360
- if (fileContent === null)
361
- continue;
362
- // Apply heuristics
363
- if (!patterns.length || patterns.some(pattern => (0, convert_pcre_1.default)(pattern).test(fileContent))) {
364
- results.files.results[file] = heuristic.language;
365
- break;
366
- }
367
- }
368
- }
369
- // If no heuristics, assign a language
370
- if (!results.files.results[file]) {
371
- const possibleLangs = fileAssociations[file];
372
- // Assign first language as a default option
373
- const defaultLang = possibleLangs[0];
374
- const alternativeLangs = possibleLangs.slice(1);
375
- results.files.results[file] = defaultLang;
376
- // List alternative languages if there are any
377
- if (alternativeLangs.length > 0)
378
- results.files.alternatives[file] = alternativeLangs;
379
- }
380
- }
381
- // Skip specified categories
382
- if ((_m = opts.categories) === null || _m === void 0 ? void 0 : _m.length) {
383
- const categories = ['data', 'markup', 'programming', 'prose'];
384
- const hiddenCategories = categories.filter(cat => !opts.categories.includes(cat));
385
- for (const [file, lang] of Object.entries(results.files.results)) {
386
- // Skip if language is not hidden
387
- if (!hiddenCategories.some(cat => { var _a; return lang && ((_a = langData[lang]) === null || _a === void 0 ? void 0 : _a.type) === cat; }))
388
- continue;
389
- // Skip if language is forced as detectable
390
- if (opts.checkDetected) {
391
- const detectable = (0, ignore_1.default)().add(getFlaggedGlobs('detectable', true));
392
- if (detectable.ignores(relPath(file)))
393
- continue;
394
- }
395
- // Delete result otherwise
396
- delete results.files.results[file];
397
- if (lang)
398
- delete results.languages.results[lang];
399
- }
400
- for (const category of hiddenCategories) {
401
- for (const [lang, { type }] of Object.entries(results.languages.results)) {
402
- if (type === category) {
403
- delete results.languages.results[lang];
404
- }
405
- }
406
- }
407
- }
408
- // Convert paths to relative
409
- if (!useRawContent && opts.relativePaths) {
410
- const newMap = {};
411
- for (const [file, lang] of Object.entries(results.files.results)) {
412
- let relPath = (0, norm_path_1.normPath)(node_path_1.default.relative(process.cwd(), file));
413
- if (!relPath.startsWith('../')) {
414
- relPath = './' + relPath;
415
- }
416
- newMap[relPath] = lang;
417
- }
418
- results.files.results = newMap;
419
- }
420
- // Load language bytes size
421
- for (const [file, lang] of Object.entries(results.files.results)) {
422
- if (lang && !langData[lang])
423
- continue;
424
- // Calculate file size
425
- const fileSize = (_p = (_o = manualFileContent[files.indexOf(file)]) === null || _o === void 0 ? void 0 : _o.length) !== null && _p !== void 0 ? _p : node_fs_1.default.statSync(file).size;
426
- // Calculate lines of code
427
- const loc = { total: 0, content: 0, code: 0 };
428
- if (opts.calculateLines) {
429
- const fileContent = (_r = ((_q = manualFileContent[files.indexOf(file)]) !== null && _q !== void 0 ? _q : node_fs_1.default.readFileSync(file).toString())) !== null && _r !== void 0 ? _r : '';
430
- const allLines = fileContent.split(/\r?\n/gm);
431
- loc.total = allLines.length;
432
- loc.content = allLines.filter(line => line.trim().length > 0).length;
433
- const codeLines = fileContent
434
- .replace(/^\s*(\/\/|# |;|--).+/gm, '')
435
- .replace(/\/\*.+\*\/|<!--.+-->/sg, '');
436
- loc.code = codeLines.split(/\r?\n/gm).filter(line => line.trim().length > 0).length;
437
- }
438
- // Apply to files totals
439
- results.files.bytes += fileSize;
440
- results.files.lines.total += loc.total;
441
- results.files.lines.content += loc.content;
442
- results.files.lines.code += loc.code;
443
- // Add results to 'languages' section if language match found, or 'unknown' section otherwise
444
- if (lang) {
445
- const { type } = langData[lang];
446
- // set default if unset
447
- (_s = (_u = results.languages.results)[lang]) !== null && _s !== void 0 ? _s : (_u[lang] = { type, bytes: 0, lines: { total: 0, content: 0, code: 0 }, color: langData[lang].color });
448
- // apply results to 'languages' section
449
- if (opts.childLanguages) {
450
- results.languages.results[lang].parent = langData[lang].group;
451
- }
452
- results.languages.results[lang].bytes += fileSize;
453
- results.languages.bytes += fileSize;
454
- results.languages.results[lang].lines.total += loc.total;
455
- results.languages.results[lang].lines.content += loc.content;
456
- results.languages.results[lang].lines.code += loc.code;
457
- results.languages.lines.total += loc.total;
458
- results.languages.lines.content += loc.content;
459
- results.languages.lines.code += loc.code;
460
- }
461
- else {
462
- const ext = node_path_1.default.extname(file);
463
- const unknownType = ext ? 'extensions' : 'filenames';
464
- const name = ext || node_path_1.default.basename(file);
465
- // apply results to 'unknown' section
466
- (_t = (_v = results.unknown[unknownType])[name]) !== null && _t !== void 0 ? _t : (_v[name] = 0);
467
- results.unknown[unknownType][name] += fileSize;
468
- results.unknown.bytes += fileSize;
469
- results.unknown.lines.total += loc.total;
470
- results.unknown.lines.content += loc.content;
471
- results.unknown.lines.code += loc.code;
472
- }
473
- }
474
- // Set lines output to NaN when line calculation is disabled
475
- if (opts.calculateLines === false) {
476
- results.files.lines = { total: NaN, content: NaN, code: NaN };
477
- }
478
- // Set counts
479
- results.files.count = Object.keys(results.files.results).length;
480
- results.languages.count = Object.keys(results.languages.results).length;
481
- results.unknown.count = Object.keys({ ...results.unknown.extensions, ...results.unknown.filenames }).length;
482
- // Return
483
- return results;
484
- }
485
- exports.default = analyse;
@@ -1,37 +0,0 @@
1
- import { Category, Language } from './types';
2
- export interface LanguagesScema {
3
- [name: string]: {
4
- language_id: number;
5
- fs_name?: Language;
6
- type: Category;
7
- group?: Language;
8
- color?: `#${string}`;
9
- aliases?: string[];
10
- extensions?: `.${string}`[];
11
- filenames?: string[];
12
- interpreters?: string[];
13
- tm_scope?: `${'source' | 'text'}.${string}`;
14
- ace_mode?: string;
15
- codemirror_mode?: string;
16
- codemirror_mime_type?: `${string}/${string}`;
17
- wrap?: boolean;
18
- };
19
- }
20
- interface HeuristicsRules {
21
- pattern?: string;
22
- named_pattern?: string;
23
- named_patterns?: string[];
24
- negative_pattern?: string;
25
- }
26
- export interface HeuristicsSchema {
27
- disambiguations: Array<{
28
- extensions: string[];
29
- rules: Array<HeuristicsRules & {
30
- language: string | string[];
31
- and?: HeuristicsRules[];
32
- }>;
33
- }>;
34
- named_patterns: Record<string, string | string[]>;
35
- }
36
- export type VendorSchema = string[];
37
- export {};
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,74 +0,0 @@
1
- export type LanguageResult = string | null;
2
- export type Language = string;
3
- export type Category = 'data' | 'markup' | 'programming' | 'prose';
4
- export type FilePath = string;
5
- export type Bytes = Integer;
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 & {};
11
- export interface Options {
12
- fileContent?: string | string[];
13
- ignoredFiles?: string[];
14
- ignoredLanguages?: Language[];
15
- categories?: Category[];
16
- keepVendored?: boolean;
17
- keepBinary?: boolean;
18
- relativePaths?: boolean;
19
- childLanguages?: boolean;
20
- quick?: boolean;
21
- offline?: boolean;
22
- calculateLines?: boolean;
23
- checkIgnored?: boolean;
24
- checkDetected?: boolean;
25
- checkAttributes?: boolean;
26
- checkHeuristics?: boolean;
27
- checkShebang?: boolean;
28
- checkModeline?: boolean;
29
- }
30
- export interface Results {
31
- files: {
32
- count: Integer;
33
- bytes: Bytes;
34
- lines: {
35
- total: Integer;
36
- content: Integer;
37
- code: Integer;
38
- };
39
- /** Note: Results use slashes as delimiters even on Windows. */
40
- results: Record<FilePath, LanguageResult>;
41
- alternatives: Record<FilePath, LanguageResult[]>;
42
- };
43
- languages: {
44
- count: Integer;
45
- bytes: Bytes;
46
- lines: {
47
- total: Integer;
48
- content: Integer;
49
- code: Integer;
50
- };
51
- results: Record<Language, {
52
- bytes: Bytes;
53
- lines: {
54
- total: Integer;
55
- content: Integer;
56
- code: Integer;
57
- };
58
- type: Category;
59
- parent?: Language;
60
- color?: `#${string}`;
61
- }>;
62
- };
63
- unknown: {
64
- count: Integer;
65
- bytes: Bytes;
66
- lines: {
67
- total: Integer;
68
- content: Integer;
69
- code: Integer;
70
- };
71
- extensions: Record<string, Bytes>;
72
- filenames: Record<string, Bytes>;
73
- };
74
- }
package/dist/src/types.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
package/dist/version.d.ts DELETED
@@ -1,2 +0,0 @@
1
- declare const VERSION = "2.8.0";
2
- export default VERSION;
package/dist/version.js DELETED
@@ -1,4 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const VERSION = '2.8.0';
4
- exports.default = VERSION;