linguist-js 2.7.1 → 2.8.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 CHANGED
@@ -24,11 +24,13 @@ commander_1.program
24
24
  .option('-F|--listFiles [bool]', 'Whether to list every matching file under the language results', false)
25
25
  .option('-q|--quick [bool]', 'Skip complex language analysis (alias for -{A|I|H|S}=false)', false)
26
26
  .option('-o|--offline [bool]', 'Use packaged data files instead of fetching latest from GitHub', false)
27
+ .option('-L|--calculateLines [bool]', 'Calculate lines of code totals', true)
27
28
  .option('-V|--keepVendored [bool]', 'Prevent skipping over vendored/generated files', false)
28
29
  .option('-B|--keepBinary [bool]', 'Prevent skipping over binary files', false)
29
30
  .option('-r|--relativePaths [bool]', 'Convert absolute file paths to relative', false)
30
31
  .option('-A|--checkAttributes [bool]', 'Force the checking of gitattributes files', true)
31
32
  .option('-I|--checkIgnored [bool]', 'Force the checking of gitignore files', true)
33
+ .option('-D|--checkDetected [bool]', 'Force files marked with linguist-detectable to always appear in output', true)
32
34
  .option('-H|--checkHeuristics [bool]', 'Apply heuristics to ambiguous languages', true)
33
35
  .option('-S|--checkShebang [bool]', 'Check shebang lines for explicit classification', true)
34
36
  .option('-M|--checkModeline [bool]', 'Check modelines for explicit classification', true)
@@ -79,16 +81,17 @@ if (args.analyze)
79
81
  }
80
82
  }
81
83
  // List parsed results
82
- for (const [lang, { bytes, color }] of sortedEntries) {
84
+ for (const [lang, { bytes, lines, color }] of sortedEntries) {
83
85
  const percent = (bytes) => bytes / (totalBytes || 1) * 100;
84
86
  const fmtd = {
85
87
  index: (++count).toString().padStart(2, ' '),
86
88
  lang: lang.padEnd(24, ' '),
87
89
  percent: percent(bytes).toFixed(2).padStart(5, ' '),
88
90
  bytes: bytes.toLocaleString().padStart(10, ' '),
91
+ loc: lines.code.toLocaleString().padStart(10, ' '),
89
92
  icon: colouredMsg(hexToRgb(color !== null && color !== void 0 ? color : '#ededed'), '\u2588'),
90
93
  };
91
- console.log(` ${fmtd.index}. ${fmtd.icon} ${fmtd.lang} ${fmtd.percent}% ${fmtd.bytes} B`);
94
+ console.log(` ${fmtd.index}. ${fmtd.icon} ${fmtd.lang} ${fmtd.percent}% ${fmtd.bytes} B ${fmtd.loc} LOC`);
92
95
  // If using `listFiles` option, list all files tagged as this language
93
96
  if (args.listFiles) {
94
97
  console.log(); // padding
@@ -3,6 +3,7 @@ export type FlagAttributes = {
3
3
  'vendored': boolean | null;
4
4
  'generated': boolean | null;
5
5
  'documentation': boolean | null;
6
+ 'detectable': boolean | null;
6
7
  'binary': boolean | null;
7
8
  'language': T.LanguageResult;
8
9
  };
@@ -21,10 +21,12 @@ function parseAttributes(content, folderRoot = '.') {
21
21
  const falseParts = (str) => attrParts.filter(part => part.includes(str) && isFalse(part));
22
22
  const hasTrueParts = (str) => trueParts(str).length > 0;
23
23
  const hasFalseParts = (str) => falseParts(str).length > 0;
24
+ const boolOrNullVal = (str) => hasTrueParts(str) ? true : hasFalseParts(str) ? false : null;
24
25
  const attrs = {
25
- 'generated': hasTrueParts('linguist-generated') ? true : hasFalseParts('linguist-generated') ? false : null,
26
- 'vendored': hasTrueParts('linguist-vendored') ? true : hasFalseParts('linguist-vendored') ? false : null,
27
- 'documentation': hasTrueParts('linguist-documentation') ? true : hasFalseParts('linguist-documentation') ? false : null,
26
+ 'generated': boolOrNullVal('linguist-generated'),
27
+ 'vendored': boolOrNullVal('linguist-vendored'),
28
+ 'documentation': boolOrNullVal('linguist-documentation'),
29
+ 'detectable': boolOrNullVal('linguist-detectable'),
28
30
  'binary': hasTrueParts('binary') || hasFalseParts('text') ? true : hasFalseParts('binary') || hasTrueParts('text') ? false : null,
29
31
  'language': (_b = (_a = trueParts('linguist-language').at(-1)) === null || _a === void 0 ? void 0 : _a.split('=')[1]) !== null && _b !== void 0 ? _b : null,
30
32
  };
@@ -2,4 +2,4 @@
2
2
  * Read part of a file on disc.
3
3
  * @throws 'EPERM' if the file is not readable.
4
4
  */
5
- export default function readFile(filename: string, onlyFirstLine?: boolean): Promise<string>;
5
+ export default function readFileChunk(filename: string, onlyFirstLine?: boolean): Promise<string>;
@@ -8,7 +8,7 @@ const fs_1 = __importDefault(require("fs"));
8
8
  * Read part of a file on disc.
9
9
  * @throws 'EPERM' if the file is not readable.
10
10
  */
11
- async function readFile(filename, onlyFirstLine = false) {
11
+ async function readFileChunk(filename, onlyFirstLine = false) {
12
12
  const chunkSize = 100;
13
13
  const stream = fs_1.default.createReadStream(filename, { highWaterMark: chunkSize });
14
14
  let content = '';
@@ -20,4 +20,4 @@ async function readFile(filename, onlyFirstLine = false) {
20
20
  }
21
21
  return content;
22
22
  }
23
- exports.default = readFile;
23
+ exports.default = readFileChunk;
package/dist/index.js CHANGED
@@ -39,14 +39,16 @@ const parse_gitattributes_1 = __importDefault(require("./helpers/parse-gitattrib
39
39
  const convert_pcre_1 = __importDefault(require("./helpers/convert-pcre"));
40
40
  const norm_path_1 = require("./helpers/norm-path");
41
41
  async function analyse(rawPaths, opts = {}) {
42
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
43
- var _r, _s;
42
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
43
+ var _u, _v;
44
44
  const useRawContent = opts.fileContent !== undefined;
45
45
  const input = [rawPaths !== null && rawPaths !== void 0 ? rawPaths : []].flat();
46
46
  const manualFileContent = [(_a = opts.fileContent) !== null && _a !== void 0 ? _a : []].flat();
47
47
  // Normalise input option arguments
48
48
  opts = {
49
+ calculateLines: (_b = opts.calculateLines) !== null && _b !== void 0 ? _b : true,
49
50
  checkIgnored: !opts.quick,
51
+ checkDetected: !opts.quick,
50
52
  checkAttributes: !opts.quick,
51
53
  checkHeuristics: !opts.quick,
52
54
  checkShebang: !opts.quick,
@@ -65,9 +67,9 @@ async function analyse(rawPaths, opts = {}) {
65
67
  const extensions = {};
66
68
  const globOverrides = {};
67
69
  const results = {
68
- files: { count: 0, bytes: 0, results: {}, alternatives: {} },
69
- languages: { count: 0, bytes: 0, results: {} },
70
- unknown: { count: 0, bytes: 0, extensions: {}, filenames: {} },
70
+ files: { count: 0, bytes: 0, lines: { total: 0, content: 0, code: 0 }, results: {}, alternatives: {} },
71
+ languages: { count: 0, bytes: 0, lines: { total: 0, content: 0, code: 0 }, results: {} },
72
+ unknown: { count: 0, bytes: 0, lines: { total: 0, content: 0, code: 0 }, extensions: {}, filenames: {} },
71
73
  };
72
74
  // Set a common root path so that vendor paths do not incorrectly match parent folders
73
75
  const resolvedInput = input.map(path => (0, norm_path_1.normPath)(path_1.default.resolve(path)));
@@ -81,7 +83,7 @@ async function analyse(rawPaths, opts = {}) {
81
83
  // Prepare list of ignored files
82
84
  const ignored = (0, ignore_1.default)();
83
85
  ignored.add('.git/');
84
- ignored.add((_b = opts.ignoredFiles) !== null && _b !== void 0 ? _b : []);
86
+ ignored.add((_c = opts.ignoredFiles) !== null && _c !== void 0 ? _c : []);
85
87
  const regexIgnores = opts.keepVendored ? [] : vendorPaths.map(path => RegExp(path, 'i'));
86
88
  // Load file paths and folders
87
89
  let files;
@@ -176,7 +178,7 @@ async function analyse(rawPaths, opts = {}) {
176
178
  files.push(...unignoredList);
177
179
  }
178
180
  // Ignore specific languages
179
- for (const lang of (_c = opts.ignoredLanguages) !== null && _c !== void 0 ? _c : []) {
181
+ for (const lang of (_d = opts.ignoredLanguages) !== null && _d !== void 0 ? _d : []) {
180
182
  for (const key in langData) {
181
183
  if (lang.toLowerCase() === key.toLowerCase()) {
182
184
  delete langData[key];
@@ -229,7 +231,7 @@ async function analyse(rawPaths, opts = {}) {
229
231
  // Check first line for readability
230
232
  let firstLine;
231
233
  if (useRawContent) {
232
- firstLine = (_e = (_d = manualFileContent[files.indexOf(file)]) === null || _d === void 0 ? void 0 : _d.split('\n')[0]) !== null && _e !== void 0 ? _e : null;
234
+ firstLine = (_f = (_e = manualFileContent[files.indexOf(file)]) === null || _e === void 0 ? void 0 : _e.split('\n')[0]) !== null && _f !== void 0 ? _f : null;
233
235
  }
234
236
  else if (fs_1.default.existsSync(file) && !fs_1.default.lstatSync(file).isDirectory()) {
235
237
  firstLine = await (0, read_file_1.default)(file, true).catch(() => null);
@@ -248,7 +250,7 @@ async function analyse(rawPaths, opts = {}) {
248
250
  const langMatcher = (lang) => `\\b${lang.toLowerCase().replace(/\W/g, '\\$&')}(?![\\w#+*]|-\*-)`;
249
251
  // Check for interpreter match
250
252
  if (opts.checkShebang && hasShebang) {
251
- const matchesInterpretor = (_f = data.interpreters) === null || _f === void 0 ? void 0 : _f.some(interpreter => firstLine.match(`\\b${interpreter}\\b`));
253
+ const matchesInterpretor = (_g = data.interpreters) === null || _g === void 0 ? void 0 : _g.some(interpreter => firstLine.match(`\\b${interpreter}\\b`));
252
254
  if (matchesInterpretor)
253
255
  matches.push(lang);
254
256
  }
@@ -256,7 +258,7 @@ async function analyse(rawPaths, opts = {}) {
256
258
  if (opts.checkModeline && hasModeline) {
257
259
  const modelineText = firstLine.toLowerCase().replace(/^.*-\*-(.+)-\*-.*$/, '$1');
258
260
  const matchesLang = modelineText.match(langMatcher(lang));
259
- const matchesAlias = (_g = data.aliases) === null || _g === void 0 ? void 0 : _g.some(lang => modelineText.match(langMatcher(lang)));
261
+ const matchesAlias = (_h = data.aliases) === null || _h === void 0 ? void 0 : _h.some(lang => modelineText.match(langMatcher(lang)));
260
262
  if (matchesLang || matchesAlias)
261
263
  matches.push(lang);
262
264
  }
@@ -275,7 +277,7 @@ async function analyse(rawPaths, opts = {}) {
275
277
  let skipExts = false;
276
278
  // Check if filename is a match
277
279
  for (const lang in langData) {
278
- const matchesName = (_h = langData[lang].filenames) === null || _h === void 0 ? void 0 : _h.some(name => path_1.default.basename(file.toLowerCase()) === name.toLowerCase());
280
+ const matchesName = (_j = langData[lang].filenames) === null || _j === void 0 ? void 0 : _j.some(name => path_1.default.basename(file.toLowerCase()) === name.toLowerCase());
279
281
  if (matchesName) {
280
282
  addResult(file, lang);
281
283
  skipExts = true;
@@ -285,7 +287,7 @@ async function analyse(rawPaths, opts = {}) {
285
287
  const possibleExts = [];
286
288
  if (!skipExts)
287
289
  for (const lang in langData) {
288
- const extMatches = (_j = langData[lang].extensions) === null || _j === void 0 ? void 0 : _j.filter(ext => file.toLowerCase().endsWith(ext.toLowerCase()));
290
+ const extMatches = (_k = langData[lang].extensions) === null || _k === void 0 ? void 0 : _k.filter(ext => file.toLowerCase().endsWith(ext.toLowerCase()));
289
291
  if (extMatches === null || extMatches === void 0 ? void 0 : extMatches.length) {
290
292
  for (const ext of extMatches)
291
293
  possibleExts.push({ ext, lang });
@@ -331,7 +333,7 @@ async function analyse(rawPaths, opts = {}) {
331
333
  heuristic.language = heuristic.language[0];
332
334
  }
333
335
  // Make sure the results includes this language
334
- const languageGroup = (_k = langData[heuristic.language]) === null || _k === void 0 ? void 0 : _k.group;
336
+ const languageGroup = (_l = langData[heuristic.language]) === null || _l === void 0 ? void 0 : _l.group;
335
337
  const matchesLang = fileAssociations[file].includes(heuristic.language);
336
338
  const matchesParent = languageGroup && fileAssociations[file].includes(languageGroup);
337
339
  if (!matchesLang && !matchesParent)
@@ -376,17 +378,23 @@ async function analyse(rawPaths, opts = {}) {
376
378
  }
377
379
  }
378
380
  // Skip specified categories
379
- if ((_l = opts.categories) === null || _l === void 0 ? void 0 : _l.length) {
381
+ if ((_m = opts.categories) === null || _m === void 0 ? void 0 : _m.length) {
380
382
  const categories = ['data', 'markup', 'programming', 'prose'];
381
383
  const hiddenCategories = categories.filter(cat => !opts.categories.includes(cat));
382
384
  for (const [file, lang] of Object.entries(results.files.results)) {
383
- if (!hiddenCategories.some(cat => { var _a; return lang && ((_a = langData[lang]) === null || _a === void 0 ? void 0 : _a.type) === cat; })) {
385
+ // Skip if language is not hidden
386
+ if (!hiddenCategories.some(cat => { var _a; return lang && ((_a = langData[lang]) === null || _a === void 0 ? void 0 : _a.type) === cat; }))
384
387
  continue;
388
+ // Skip if language is forced as detectable
389
+ if (opts.checkDetected) {
390
+ const detectable = (0, ignore_1.default)().add(getFlaggedGlobs('detectable', true));
391
+ if (detectable.ignores(relPath(file)))
392
+ continue;
385
393
  }
394
+ // Delete result otherwise
386
395
  delete results.files.results[file];
387
- if (lang) {
396
+ if (lang)
388
397
  delete results.languages.results[lang];
389
- }
390
398
  }
391
399
  for (const category of hiddenCategories) {
392
400
  for (const [lang, { type }] of Object.entries(results.languages.results)) {
@@ -412,26 +420,59 @@ async function analyse(rawPaths, opts = {}) {
412
420
  for (const [file, lang] of Object.entries(results.files.results)) {
413
421
  if (lang && !langData[lang])
414
422
  continue;
415
- 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;
423
+ // Calculate file size
424
+ const fileSize = (_p = (_o = manualFileContent[files.indexOf(file)]) === null || _o === void 0 ? void 0 : _o.length) !== null && _p !== void 0 ? _p : fs_1.default.statSync(file).size;
425
+ // Calculate lines of code
426
+ const loc = { total: 0, content: 0, code: 0 };
427
+ if (opts.calculateLines) {
428
+ const fileContent = (_r = ((_q = manualFileContent[files.indexOf(file)]) !== null && _q !== void 0 ? _q : fs_1.default.readFileSync(file).toString())) !== null && _r !== void 0 ? _r : '';
429
+ const allLines = fileContent.split(/\r?\n/gm);
430
+ loc.total = allLines.length;
431
+ loc.content = allLines.filter(line => line.trim().length > 0).length;
432
+ const codeLines = fileContent
433
+ .replace(/^\s*(\/\/|# |;|--).+/gm, '')
434
+ .replace(/\/\*.+\*\/|<!--.+-->/sg, '');
435
+ loc.code = codeLines.split(/\r?\n/gm).filter(line => line.trim().length > 0).length;
436
+ }
437
+ // Apply to files totals
416
438
  results.files.bytes += fileSize;
417
- // If no language found, add extension in other section
418
- if (!lang) {
439
+ results.files.lines.total += loc.total;
440
+ results.files.lines.content += loc.content;
441
+ results.files.lines.code += loc.code;
442
+ // Add results to 'languages' section if language match found, or 'unknown' section otherwise
443
+ if (lang) {
444
+ const { type } = langData[lang];
445
+ // set default if unset
446
+ (_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 });
447
+ // apply results to 'languages' section
448
+ if (opts.childLanguages) {
449
+ results.languages.results[lang].parent = langData[lang].group;
450
+ }
451
+ results.languages.results[lang].bytes += fileSize;
452
+ results.languages.bytes += fileSize;
453
+ results.languages.results[lang].lines.total += loc.total;
454
+ results.languages.results[lang].lines.content += loc.content;
455
+ results.languages.results[lang].lines.code += loc.code;
456
+ results.languages.lines.total += loc.total;
457
+ results.languages.lines.content += loc.content;
458
+ results.languages.lines.code += loc.code;
459
+ }
460
+ else {
419
461
  const ext = path_1.default.extname(file);
420
- const unknownType = ext === '' ? 'filenames' : 'extensions';
421
- const name = ext === '' ? path_1.default.basename(file) : ext;
422
- (_p = (_r = results.unknown[unknownType])[name]) !== null && _p !== void 0 ? _p : (_r[name] = 0);
462
+ const unknownType = ext ? 'extensions' : 'filenames';
463
+ const name = ext || path_1.default.basename(file);
464
+ // apply results to 'unknown' section
465
+ (_t = (_v = results.unknown[unknownType])[name]) !== null && _t !== void 0 ? _t : (_v[name] = 0);
423
466
  results.unknown[unknownType][name] += fileSize;
424
467
  results.unknown.bytes += fileSize;
425
- continue;
468
+ results.unknown.lines.total += loc.total;
469
+ results.unknown.lines.content += loc.content;
470
+ results.unknown.lines.code += loc.code;
426
471
  }
427
- // Add language and bytes data to corresponding section
428
- const { type } = langData[lang];
429
- (_q = (_s = results.languages.results)[lang]) !== null && _q !== void 0 ? _q : (_s[lang] = { type, bytes: 0, color: langData[lang].color });
430
- if (opts.childLanguages) {
431
- results.languages.results[lang].parent = langData[lang].group;
432
- }
433
- results.languages.results[lang].bytes += fileSize;
434
- results.languages.bytes += fileSize;
472
+ }
473
+ // Set lines output to NaN when line calculation is disabled
474
+ if (opts.calculateLines === false) {
475
+ results.files.lines = { total: NaN, content: NaN, code: NaN };
435
476
  }
436
477
  // Set counts
437
478
  results.files.count = Object.keys(results.files.results).length;
package/dist/types.d.ts CHANGED
@@ -19,7 +19,9 @@ export interface Options {
19
19
  childLanguages?: boolean;
20
20
  quick?: boolean;
21
21
  offline?: boolean;
22
+ calculateLines?: boolean;
22
23
  checkIgnored?: boolean;
24
+ checkDetected?: boolean;
23
25
  checkAttributes?: boolean;
24
26
  checkHeuristics?: boolean;
25
27
  checkShebang?: boolean;
@@ -29,6 +31,11 @@ export interface Results {
29
31
  files: {
30
32
  count: Integer;
31
33
  bytes: Bytes;
34
+ lines: {
35
+ total: Integer;
36
+ content: Integer;
37
+ code: Integer;
38
+ };
32
39
  /** Note: Results use slashes as delimiters even on Windows. */
33
40
  results: Record<FilePath, LanguageResult>;
34
41
  alternatives: Record<FilePath, LanguageResult[]>;
@@ -36,8 +43,18 @@ export interface Results {
36
43
  languages: {
37
44
  count: Integer;
38
45
  bytes: Bytes;
46
+ lines: {
47
+ total: Integer;
48
+ content: Integer;
49
+ code: Integer;
50
+ };
39
51
  results: Record<Language, {
40
52
  bytes: Bytes;
53
+ lines: {
54
+ total: Integer;
55
+ content: Integer;
56
+ code: Integer;
57
+ };
41
58
  type: Category;
42
59
  parent?: Language;
43
60
  color?: `#${string}`;
@@ -46,6 +63,11 @@ export interface Results {
46
63
  unknown: {
47
64
  count: Integer;
48
65
  bytes: Bytes;
66
+ lines: {
67
+ total: Integer;
68
+ content: Integer;
69
+ code: Integer;
70
+ };
49
71
  extensions: Record<string, Bytes>;
50
72
  filenames: Record<string, Bytes>;
51
73
  };
package/ext/generated.rb CHANGED
@@ -8,7 +8,9 @@
8
8
  - (Gopkg|glide)\.lock
9
9
  - poetry\.lock
10
10
  - pdm\.lock
11
+ - uv\.lock
11
12
  - (^|\/)(\w+\.)?esy.lock$
13
+ - deno\.lock
12
14
  - npm-shrinkwrap\.json
13
15
  - package-lock\.json
14
16
  - pnpm-lock\.yaml
@@ -17,7 +19,9 @@
17
19
  - composer\.lock
18
20
  - .\.zep\.(?:c|h|php)$
19
21
  - Cargo\.lock
22
+ - Cargo\.toml\.orig
20
23
  - (^|\/)flake\.lock$
24
+ - (^|\/)MODULE\.bazel\.lock$
21
25
  - Pipfile\.lock
22
26
  - (?:^|\/)\.terraform\.lock\.hcl$
23
27
  - ppport\.h$
@@ -59,6 +59,8 @@ disambiguations:
59
59
  - language: Asymptote
60
60
  - extensions: ['.bas']
61
61
  rules:
62
+ - language: B4X
63
+ pattern: '\A\W{0,3}(?:.*(?:\r?\n|\r)){0,9}B4(?:J|A|R|i)=true'
62
64
  - language: FreeBasic
63
65
  pattern: '^[ \t]*#(?i)(?:define|endif|endmacro|ifn?def|include|lang|macro)(?:$|\s)'
64
66
  - language: BASIC
@@ -107,6 +109,11 @@ disambiguations:
107
109
  rules:
108
110
  - language: XML
109
111
  pattern: '^(\s*)(?i:<Project|<Import|<Property|<?xml|xmlns)'
112
+ - extensions: ['.cairo']
113
+ rules:
114
+ - language: Cairo Zero
115
+ pattern: '(^(\s*)%lang(\s+)([A-Za-z0-9_]+))|(^(\s*)%builtins(\s+)([A-Za-z0-9_]+\s*)*$)|(^(\s*)from(\s+)starkware\.(cairo|starknet)\.([A-Za-z0-9_.\s]+?)import)|(,\s*ap\+\+;$)|(;\s*ap\+\+$)'
116
+ - language: Cairo
110
117
  - extensions: ['.ch']
111
118
  rules:
112
119
  - language: xBase
@@ -190,7 +197,7 @@ disambiguations:
190
197
  - language: Erlang
191
198
  pattern: '^\s*(?:%%|main\s*\(.*?\)\s*->)'
192
199
  - language: JavaScript
193
- pattern: '\/\/|("|'')use strict\1|export\s+default\s|\/\*(?:.|[\r\n])*?\*\/'
200
+ pattern: '\/\/|["'']use strict["'']|export\s+default\s|\/\*(?:.|[\r\n])*?\*\/'
194
201
  - extensions: ['.ex']
195
202
  rules:
196
203
  - language: Elixir
@@ -315,7 +322,7 @@ disambiguations:
315
322
  - extensions: ['.ice']
316
323
  rules:
317
324
  - language: JSON
318
- pattern: '\A\s*[{\[]'
325
+ named_pattern: json
319
326
  - language: Slice
320
327
  - extensions: ['.inc']
321
328
  rules:
@@ -433,6 +440,8 @@ disambiguations:
433
440
  rules:
434
441
  - language: XML
435
442
  pattern: '<!ENTITY '
443
+ - language: NMODL
444
+ pattern: '\b(NEURON|INITIAL|UNITS)\b'
436
445
  - language: Modula-2
437
446
  pattern: '^\s*(?i:MODULE|END) [\w\.]+;'
438
447
  - language: [Linux Kernel Module, AMPL]
@@ -470,6 +479,11 @@ disambiguations:
470
479
  - language: NL
471
480
  pattern: '^(b|g)[0-9]+ '
472
481
  - language: NewLisp
482
+ - extensions: ['.nr']
483
+ rules:
484
+ - language: Roff
485
+ pattern: '^\.'
486
+ - language: Noir
473
487
  - extensions: ['.nu']
474
488
  rules:
475
489
  - language: Nushell
@@ -494,6 +508,13 @@ disambiguations:
494
508
  pattern: '<\?hh'
495
509
  - language: PHP
496
510
  pattern: '<\?[^h]'
511
+ - extensions: ['.pkl']
512
+ rules:
513
+ - language: Pkl
514
+ pattern:
515
+ - '^\s*(module|import|amends|extends|local|const|fixed|abstract|open|class|typealias|@\w+)\b'
516
+ - '^\s*[a-zA-Z0-9_$]+\s*(=|{|:)|^\s*`[^`]+`\s*(=|{|:)|for\s*\(|when\s*\('
517
+ - language: Pickle
497
518
  - extensions: ['.pl']
498
519
  rules:
499
520
  - language: Prolog
@@ -507,7 +528,7 @@ disambiguations:
507
528
  - extensions: ['.plist']
508
529
  rules:
509
530
  - language: XML Property List
510
- pattern: '^\s*(?:<\?xml\s|<!DOCTYPE\s+plist|<plist(?:\s+version\s*=\s*(["''])\d+(?:\.\d+)?\1)?\s*>\s*$)'
531
+ pattern: '^\s*(?:<\?xml\s|<!DOCTYPE\s+plist|<plist(?:\s+version\s*=\s*["'']\d+(?:\.\d+)?["''])?\s*>\s*$)'
511
532
  - language: OpenStep Property List
512
533
  - extensions: ['.plt']
513
534
  rules:
@@ -599,6 +620,11 @@ disambiguations:
599
620
  pattern:
600
621
  - '^\s*(let|module|type)\s+\w*\s+=\s+'
601
622
  - '^\s*(?:include|open)\s+\w+\s*$'
623
+ - extensions: ['.resource']
624
+ rules:
625
+ - language: RobotFramework
626
+ pattern:
627
+ - '^\*{3} (Settings|Variables|Keywords) \*{3}$'
602
628
  - extensions: ['.rno']
603
629
  rules:
604
630
  - language: RUNOFF
@@ -720,6 +746,10 @@ disambiguations:
720
746
  rules:
721
747
  - language: Vim Help File
722
748
  pattern: '(?:(?:^|[ \t])(?:vi|Vi(?=m))(?:m[<=>]?[0-9]+|m)?|[ \t]ex)(?=:(?=[ \t]*set?[ \t][^\r\n:]+:)|:(?![ \t]*set?[ \t]))(?:(?:[ \t]*:[ \t]*|[ \t])\w*(?:[ \t]*=(?:[^\\\s]|\\.)*)?)*[ \t:](?:filetype|ft|syntax)[ \t]*=(help)(?=$|\s|:)'
749
+ - language: Hosts File
750
+ pattern: '(?xi) ^(?<ipv4>(?!\.)(?:\.?(?: 25[0-5]| 2[0-4]\d| 1\d\d| [1-9]?\d)\b){4})(?<cidr>/(3[0-2]|[12]?\d)\b)?(?<domains>[ \t]+\w[-\w]* (?:\.\w[-\w]*)*(?<!-)\b)*+'
751
+
752
+ (?=$|\s)
723
753
  - language: Adblock Filter List
724
754
  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>)*+\]'
725
755
  - language: Text
@@ -745,6 +775,12 @@ disambiguations:
745
775
  - language: Vim Script
746
776
  pattern: '^UseVimball'
747
777
  - language: VBA
778
+ - extensions: ['.vcf']
779
+ rules:
780
+ - language: TSV
781
+ pattern: '\A##fileformat=VCF'
782
+ - language: vCard
783
+ pattern: '\ABEGIN:VCARD'
748
784
  - extensions: ['.w']
749
785
  rules:
750
786
  - language: OpenEdge ABL
@@ -774,7 +810,7 @@ disambiguations:
774
810
  - extensions: ['.yy']
775
811
  rules:
776
812
  - language: JSON
777
- pattern: '\"modelName\"\:\s*\"GM'
813
+ named_pattern: json
778
814
  - language: Yacc
779
815
  named_patterns:
780
816
  cpp:
@@ -796,6 +832,7 @@ named_patterns:
796
832
  - '^\s*(?>(?:autoexec|private)\s+){0,2}function\s+(?>(?:autoexec|private)\s+){0,2}\w+\s*\('
797
833
  - '\b(?:level|self)[ \t]+thread[ \t]+(?:\[\[[ \t]*(?>\w+\.)*\w+[ \t]*\]\]|\w+)[ \t]*\([^\r\n\)]*\)[ \t]*;'
798
834
  - '^[ \t]*#[ \t]*(?:precache|using_animtree)[ \t]*\('
835
+ json: '\A\s*[{\[]'
799
836
  key_equals_value: '^[^#!;][^=]*='
800
837
  m68k:
801
838
  - '(?im)\bmoveq(?:\.l)?\s+#(?:\$-?[0-9a-f]{1,3}|%[0-1]{1,8}|-?[0-9]{1,3}),\s*d[0-7]\b'
package/ext/languages.yml CHANGED
@@ -463,6 +463,18 @@ Awk:
463
463
  tm_scope: source.awk
464
464
  ace_mode: text
465
465
  language_id: 28
466
+ B4X:
467
+ type: programming
468
+ color: "#00e4ff"
469
+ extensions:
470
+ - ".bas"
471
+ tm_scope: source.vba
472
+ aliases:
473
+ - basic for android
474
+ ace_mode: text
475
+ codemirror_mode: vb
476
+ codemirror_mime_type: text/x-vb
477
+ language_id: 96642275
466
478
  BASIC:
467
479
  type: programming
468
480
  extensions:
@@ -471,6 +483,14 @@ BASIC:
471
483
  ace_mode: text
472
484
  color: "#ff0000"
473
485
  language_id: 28923963
486
+ BQN:
487
+ type: programming
488
+ color: "#2b7067"
489
+ extensions:
490
+ - ".bqn"
491
+ tm_scope: source.bqn
492
+ ace_mode: text
493
+ language_id: 330386870
474
494
  Ballerina:
475
495
  type: programming
476
496
  extensions:
@@ -896,6 +916,18 @@ Cabal Config:
896
916
  codemirror_mime_type: text/x-haskell
897
917
  tm_scope: source.cabal
898
918
  language_id: 677095381
919
+ Caddyfile:
920
+ type: data
921
+ color: "#22b638"
922
+ aliases:
923
+ - Caddy
924
+ extensions:
925
+ - ".caddyfile"
926
+ filenames:
927
+ - Caddyfile
928
+ ace_mode: text
929
+ tm_scope: source.Caddyfile
930
+ language_id: 615465151
899
931
  Cadence:
900
932
  type: programming
901
933
  color: "#00ef8b"
@@ -911,7 +943,17 @@ Cairo:
911
943
  tm_scope: source.cairo
912
944
  extensions:
913
945
  - ".cairo"
946
+ group: Cairo
914
947
  language_id: 620599567
948
+ Cairo Zero:
949
+ type: programming
950
+ color: "#ff4a48"
951
+ ace_mode: text
952
+ tm_scope: source.cairo0
953
+ extensions:
954
+ - ".cairo"
955
+ group: Cairo
956
+ language_id: 891399890
915
957
  CameLIGO:
916
958
  type: programming
917
959
  color: "#3be133"
@@ -931,6 +973,16 @@ Cap'n Proto:
931
973
  - ".capnp"
932
974
  ace_mode: text
933
975
  language_id: 52
976
+ Carbon:
977
+ type: programming
978
+ color: "#222222"
979
+ extensions:
980
+ - ".carbon"
981
+ ace_mode: golang
982
+ codemirror_mode: go
983
+ codemirror_mime_type: text/x-go
984
+ tm_scope: source.v
985
+ language_id: 55627273
934
986
  CartoCSS:
935
987
  type: programming
936
988
  aliases:
@@ -1344,6 +1396,17 @@ Cycript:
1344
1396
  codemirror_mode: javascript
1345
1397
  codemirror_mime_type: text/javascript
1346
1398
  language_id: 78
1399
+ Cylc:
1400
+ type: data
1401
+ color: "#00b3fd"
1402
+ extensions:
1403
+ - ".cylc"
1404
+ filenames:
1405
+ - suite.rc
1406
+ tm_scope: source.cylc
1407
+ ace_mode: ini
1408
+ group: INI
1409
+ language_id: 476447814
1347
1410
  Cypher:
1348
1411
  type: programming
1349
1412
  color: "#34c0eb"
@@ -1571,6 +1634,14 @@ Dotenv:
1571
1634
  tm_scope: source.dotenv
1572
1635
  ace_mode: text
1573
1636
  language_id: 111148035
1637
+ Dune:
1638
+ type: programming
1639
+ ace_mode: lisp
1640
+ filenames:
1641
+ - dune-project
1642
+ tm_scope: source.dune
1643
+ color: "#89421e"
1644
+ language_id: 754574151
1574
1645
  Dylan:
1575
1646
  type: programming
1576
1647
  color: "#6c616e"
@@ -1916,6 +1987,14 @@ FIGlet Font:
1916
1987
  tm_scope: source.figfont
1917
1988
  ace_mode: text
1918
1989
  language_id: 686129783
1990
+ FIRRTL:
1991
+ type: programming
1992
+ color: "#2f632f"
1993
+ extensions:
1994
+ - ".fir"
1995
+ tm_scope: source.firrtl
1996
+ ace_mode: text
1997
+ language_id: 906694254
1919
1998
  FLUX:
1920
1999
  type: programming
1921
2000
  color: "#88ccff"
@@ -2654,7 +2733,7 @@ HCL:
2654
2733
  ace_mode: ruby
2655
2734
  codemirror_mode: ruby
2656
2735
  codemirror_mime_type: text/x-ruby
2657
- tm_scope: source.terraform
2736
+ tm_scope: source.hcl
2658
2737
  language_id: 144
2659
2738
  HLSL:
2660
2739
  type: programming
@@ -2883,6 +2962,7 @@ Hosts File:
2883
2962
  filenames:
2884
2963
  - HOSTS
2885
2964
  - hosts
2965
+ - hosts.txt
2886
2966
  aliases:
2887
2967
  - hosts
2888
2968
  tm_scope: source.hosts
@@ -3176,6 +3256,7 @@ JSON:
3176
3256
  - ".tern-config"
3177
3257
  - ".tern-project"
3178
3258
  - ".watchmanconfig"
3259
+ - MODULE.bazel.lock
3179
3260
  - Pipfile.lock
3180
3261
  - composer.lock
3181
3262
  - deno.lock
@@ -3197,6 +3278,7 @@ JSON with Comments:
3197
3278
  - ".code-snippets"
3198
3279
  - ".code-workspace"
3199
3280
  - ".sublime-build"
3281
+ - ".sublime-color-scheme"
3200
3282
  - ".sublime-commands"
3201
3283
  - ".sublime-completions"
3202
3284
  - ".sublime-keymap"
@@ -3310,6 +3392,17 @@ Java Server Pages:
3310
3392
  codemirror_mode: htmlembedded
3311
3393
  codemirror_mime_type: application/x-jsp
3312
3394
  language_id: 182
3395
+ Java Template Engine:
3396
+ type: programming
3397
+ color: "#2A6277"
3398
+ group: Java
3399
+ aliases:
3400
+ - jte
3401
+ extensions:
3402
+ - ".jte"
3403
+ ace_mode: text
3404
+ tm_scope: text.html.jte
3405
+ language_id: 599494012
3313
3406
  JavaScript:
3314
3407
  type: programming
3315
3408
  tm_scope: source.js
@@ -3462,6 +3555,13 @@ Julia:
3462
3555
  codemirror_mode: julia
3463
3556
  codemirror_mime_type: text/x-julia
3464
3557
  language_id: 184
3558
+ Julia REPL:
3559
+ type: programming
3560
+ color: "#a270ba"
3561
+ tm_scope: source.julia.console
3562
+ group: Julia
3563
+ ace_mode: text
3564
+ language_id: 220689142
3465
3565
  Jupyter Notebook:
3466
3566
  type: markup
3467
3567
  ace_mode: json
@@ -3483,9 +3583,14 @@ Just:
3483
3583
  color: "#384d54"
3484
3584
  tm_scope: source.just
3485
3585
  filenames:
3586
+ - ".JUSTFILE"
3587
+ - ".Justfile"
3588
+ - ".justfile"
3486
3589
  - JUSTFILE
3487
3590
  - Justfile
3488
3591
  - justfile
3592
+ extensions:
3593
+ - ".just"
3489
3594
  ace_mode: text
3490
3595
  language_id: 128447695
3491
3596
  KRL:
@@ -3823,6 +3928,14 @@ Literate Haskell:
3823
3928
  codemirror_mode: haskell-literate
3824
3929
  codemirror_mime_type: text/x-literate-haskell
3825
3930
  language_id: 207
3931
+ LiveCode Script:
3932
+ type: programming
3933
+ color: "#0c5ba5"
3934
+ extensions:
3935
+ - ".livecodescript"
3936
+ tm_scope: source.livecodescript
3937
+ ace_mode: text
3938
+ language_id: 891017
3826
3939
  LiveScript:
3827
3940
  type: programming
3828
3941
  color: "#499886"
@@ -3896,6 +4009,18 @@ Lua:
3896
4009
  interpreters:
3897
4010
  - lua
3898
4011
  language_id: 213
4012
+ Luau:
4013
+ type: programming
4014
+ tm_scope: source.luau
4015
+ ace_mode: lua
4016
+ codemirror_mode: lua
4017
+ codemirror_mime_type: text/x-lua
4018
+ color: "#00A2FF"
4019
+ extensions:
4020
+ - ".luau"
4021
+ interpreters:
4022
+ - luau
4023
+ language_id: 365050359
3899
4024
  M:
3900
4025
  type: programming
3901
4026
  aliases:
@@ -4431,6 +4556,14 @@ NL:
4431
4556
  tm_scope: none
4432
4557
  ace_mode: text
4433
4558
  language_id: 241
4559
+ NMODL:
4560
+ type: programming
4561
+ color: "#00356B"
4562
+ extensions:
4563
+ - ".mod"
4564
+ tm_scope: none
4565
+ ace_mode: text
4566
+ language_id: 136456478
4434
4567
  NPM Config:
4435
4568
  type: data
4436
4569
  color: "#cb3837"
@@ -4596,6 +4729,18 @@ Nix:
4596
4729
  tm_scope: source.nix
4597
4730
  ace_mode: nix
4598
4731
  language_id: 252
4732
+ Noir:
4733
+ type: programming
4734
+ aliases:
4735
+ - nargo
4736
+ ace_mode: rust
4737
+ codemirror_mode: rust
4738
+ codemirror_mime_type: text/x-rustsrc
4739
+ extensions:
4740
+ - ".nr"
4741
+ color: "#2f1f49"
4742
+ tm_scope: source.nr
4743
+ language_id: 813068465
4599
4744
  Nu:
4600
4745
  type: programming
4601
4746
  color: "#c9df40"
@@ -4990,7 +5135,8 @@ PEG.js:
4990
5135
  color: "#234d6b"
4991
5136
  extensions:
4992
5137
  - ".pegjs"
4993
- tm_scope: source.pegjs
5138
+ - ".peggy"
5139
+ tm_scope: source.peggy
4994
5140
  ace_mode: javascript
4995
5141
  codemirror_mode: javascript
4996
5142
  codemirror_mime_type: text/javascript
@@ -5256,6 +5402,16 @@ Pip Requirements:
5256
5402
  ace_mode: text
5257
5403
  tm_scope: source.pip-requirements
5258
5404
  language_id: 684385621
5405
+ Pkl:
5406
+ type: programming
5407
+ color: "#6b9543"
5408
+ extensions:
5409
+ - ".pkl"
5410
+ interpreters:
5411
+ - pkl
5412
+ tm_scope: source.pkl
5413
+ ace_mode: text
5414
+ language_id: 288822799
5259
5415
  PlantUML:
5260
5416
  type: data
5261
5417
  color: "#fbbd16"
@@ -5351,7 +5507,7 @@ PowerBuilder:
5351
5507
  - ".sra"
5352
5508
  - ".sru"
5353
5509
  - ".srw"
5354
- tm_scope: none
5510
+ tm_scope: source.powerbuilder
5355
5511
  ace_mode: text
5356
5512
  language_id: 292
5357
5513
  PowerShell:
@@ -5733,6 +5889,14 @@ RMarkdown:
5733
5889
  - ".rmd"
5734
5890
  tm_scope: text.md
5735
5891
  language_id: 313
5892
+ RON:
5893
+ type: data
5894
+ color: "#a62c00"
5895
+ extensions:
5896
+ - ".ron"
5897
+ ace_mode: rust
5898
+ tm_scope: source.ron
5899
+ language_id: 587855233
5736
5900
  RPC:
5737
5901
  type: programming
5738
5902
  aliases:
@@ -6008,6 +6172,7 @@ RobotFramework:
6008
6172
  color: "#00c0b5"
6009
6173
  extensions:
6010
6174
  - ".robot"
6175
+ - ".resource"
6011
6176
  tm_scope: text.robot
6012
6177
  ace_mode: text
6013
6178
  language_id: 324
@@ -6500,6 +6665,7 @@ Shell:
6500
6665
  - shell-script
6501
6666
  - bash
6502
6667
  - zsh
6668
+ - envrc
6503
6669
  extensions:
6504
6670
  - ".sh"
6505
6671
  - ".bash"
@@ -6522,6 +6688,7 @@ Shell:
6522
6688
  - ".bash_profile"
6523
6689
  - ".bashrc"
6524
6690
  - ".cshrc"
6691
+ - ".envrc"
6525
6692
  - ".flaskenv"
6526
6693
  - ".kshrc"
6527
6694
  - ".login"
@@ -6957,10 +7124,12 @@ TOML:
6957
7124
  - ".toml"
6958
7125
  filenames:
6959
7126
  - Cargo.lock
7127
+ - Cargo.toml.orig
6960
7128
  - Gopkg.lock
6961
7129
  - Pipfile
6962
7130
  - pdm.lock
6963
7131
  - poetry.lock
7132
+ - uv.lock
6964
7133
  tm_scope: source.toml
6965
7134
  ace_mode: toml
6966
7135
  codemirror_mode: toml
@@ -6981,6 +7150,9 @@ TSV:
6981
7150
  tm_scope: source.generic-db
6982
7151
  extensions:
6983
7152
  - ".tsv"
7153
+ - ".vcf"
7154
+ aliases:
7155
+ - tab-seperated values
6984
7156
  language_id: 1035892117
6985
7157
  TSX:
6986
7158
  type: programming
@@ -7248,6 +7420,7 @@ TypeScript:
7248
7420
  interpreters:
7249
7421
  - deno
7250
7422
  - ts-node
7423
+ - tsx
7251
7424
  extensions:
7252
7425
  - ".ts"
7253
7426
  - ".cts"
@@ -7464,6 +7637,7 @@ Vim Script:
7464
7637
  - vim
7465
7638
  - viml
7466
7639
  - nvim
7640
+ - vimscript
7467
7641
  extensions:
7468
7642
  - ".vim"
7469
7643
  - ".vba"
@@ -7520,7 +7694,7 @@ Visual Basic 6.0:
7520
7694
  - ".ctl"
7521
7695
  - ".Dsr"
7522
7696
  - ".frm"
7523
- tm_scope: source.vbnet
7697
+ tm_scope: source.vba
7524
7698
  aliases:
7525
7699
  - vb6
7526
7700
  - vb 6
@@ -8147,6 +8321,7 @@ Zig:
8147
8321
  color: "#ec915c"
8148
8322
  extensions:
8149
8323
  - ".zig"
8324
+ - ".zig.zon"
8150
8325
  tm_scope: source.zig
8151
8326
  ace_mode: text
8152
8327
  language_id: 646424281
@@ -8171,6 +8346,17 @@ cURL Config:
8171
8346
  tm_scope: source.curlrc
8172
8347
  ace_mode: text
8173
8348
  language_id: 992375436
8349
+ crontab:
8350
+ type: data
8351
+ color: "#ead7ac"
8352
+ aliases:
8353
+ - cron
8354
+ - cron table
8355
+ filenames:
8356
+ - crontab
8357
+ tm_scope: text.crontab
8358
+ ace_mode: tcl
8359
+ language_id: 705203557
8174
8360
  desktop:
8175
8361
  type: data
8176
8362
  extensions:
@@ -8231,6 +8417,19 @@ hoon:
8231
8417
  extensions:
8232
8418
  - ".hoon"
8233
8419
  language_id: 560883276
8420
+ iCalendar:
8421
+ type: data
8422
+ color: "#ec564c"
8423
+ extensions:
8424
+ - ".ics"
8425
+ - ".ical"
8426
+ tm_scope: source.iCalendar
8427
+ aliases:
8428
+ - iCal
8429
+ ace_mode: properties
8430
+ codemirror_mode: properties
8431
+ codemirror_mime_type: text/x-properties
8432
+ language_id: 98384424
8234
8433
  jq:
8235
8434
  color: "#c7254e"
8236
8435
  ace_mode: text
@@ -8353,6 +8552,27 @@ sed:
8353
8552
  ace_mode: text
8354
8553
  tm_scope: source.sed
8355
8554
  language_id: 847830017
8555
+ templ:
8556
+ type: markup
8557
+ color: "#66D0DD"
8558
+ extensions:
8559
+ - ".templ"
8560
+ ace_mode: text
8561
+ tm_scope: source.templ
8562
+ language_id: 795579337
8563
+ vCard:
8564
+ type: data
8565
+ color: "#ee2647"
8566
+ extensions:
8567
+ - ".vcf"
8568
+ tm_scope: source.vcard
8569
+ aliases:
8570
+ - virtual contact file
8571
+ - electronic business card
8572
+ ace_mode: properties
8573
+ codemirror_mode: properties
8574
+ codemirror_mime_type: text/x-properties
8575
+ language_id: 851476558
8356
8576
  wisp:
8357
8577
  type: programming
8358
8578
  ace_mode: clojure
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linguist-js",
3
- "version": "2.7.1",
3
+ "version": "2.8.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": {
@@ -11,7 +11,7 @@
11
11
  "node": ">=12"
12
12
  },
13
13
  "scripts": {
14
- "download-files": "npx tsx@4 build/download-files",
14
+ "download-files": "npx tsx@3 build/download-files",
15
15
  "pre-publish": "npm run download-files && npm test && npm run perf",
16
16
  "perf": "tsc && node test/perf",
17
17
  "test": "tsc && node test/folder && node test/unit"
@@ -38,11 +38,11 @@
38
38
  },
39
39
  "homepage": "https://github.com/Nixinova/Linguist#readme",
40
40
  "dependencies": {
41
- "binary-extensions": "^2.2.0 <3",
41
+ "binary-extensions": "^2.3.0 <3",
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.3.1",
45
+ "ignore": "^5.3.2",
46
46
  "isbinaryfile": "^4.0.10 <5",
47
47
  "js-yaml": "^4.1.0",
48
48
  "node-cache": "^5.1.2"
package/readme.md CHANGED
@@ -50,6 +50,11 @@ Running LinguistJS on this folder will return the following JSON:
50
50
  "files": {
51
51
  "count": 5,
52
52
  "bytes": 6020,
53
+ "lines": {
54
+ "total": 100,
55
+ "content": 90,
56
+ "code": 80,
57
+ },
53
58
  "results": {
54
59
  "/src/index.ts": "TypeScript",
55
60
  "/src/cli.js": "JavaScript",
@@ -64,16 +69,26 @@ Running LinguistJS on this folder will return the following JSON:
64
69
  "languages": {
65
70
  "count": 3,
66
71
  "bytes": 6010,
72
+ "lines": {
73
+ "total": 90,
74
+ "content": 80,
75
+ "code": 70,
76
+ },
67
77
  "results": {
68
- "JavaScript": { "type": "programming", "bytes": 1000, "color": "#f1e05a" },
69
- "Markdown": { "type": "prose", "bytes": 3000, "color": "#083fa1" },
70
- "Ruby": { "type": "programming", "bytes": 10, "color": "#701516" },
71
- "TypeScript": { "type": "programming", "bytes": 2000, "color": "#2b7489" },
78
+ "JavaScript": { "type": "programming", "bytes": 1000, "lines": { "total": 49, "content": 49, "code": 44 }, "color": "#f1e05a" },
79
+ "Markdown": { "type": "prose", "bytes": 3000, "lines": { "total": 10, "content": 5, "code": 5 }, "color": "#083fa1" },
80
+ "Ruby": { "type": "programming", "bytes": 10, "lines": { "total": 1, "content": 1, "code": 1 }, "color": "#701516" },
81
+ "TypeScript": { "type": "programming", "bytes": 2000, "lines": { "total": 30, "content": 25, "code": 20 }, "color": "#2b7489" },
72
82
  },
73
83
  },
74
84
  "unknown": {
75
85
  "count": 1,
76
86
  "bytes": 10,
87
+ "lines": {
88
+ "total": 10,
89
+ "content": 10,
90
+ "code": 10,
91
+ },
77
92
  "filenames": {
78
93
  "no-lang": 10,
79
94
  },
@@ -127,9 +142,11 @@ const { files, languages, unknown } = await linguist(fileNames, { fileContent, .
127
142
  Whether to display sub-languages instead of their parents when possible (defaults to `false`).
128
143
  - `quick` (boolean):
129
144
  Whether to skip complex language analysis such as the checking of heuristics and gitattributes statements (defaults to `false`).
130
- Alias for `checkAttributes:false, checkIgnored:false, checkHeuristics:false, checkShebang:false, checkModeline:false`.
145
+ Alias for `checkAttributes:false, checkIgnored:false, checkDetected:false, checkHeuristics:false, checkShebang:false, checkModeline:false`.
131
146
  - `offline` (boolean):
132
147
  Whether to use pre-packaged metadata files instead of fetching them from GitHub at runtime (defaults to `false`).
148
+ - `calculateLines` (boolean):
149
+ Whether to calculate line of code totals (defaults to `true`).
133
150
  - `keepVendored` (boolean):
134
151
  Whether to keep vendored files (dependencies, etc) (defaults to `false`).
135
152
  Does nothing when `fileContent` is set.
@@ -143,6 +160,8 @@ const { files, languages, unknown } = await linguist(fileNames, { fileContent, .
143
160
  - `checkIgnored` (boolean):
144
161
  Force the checking of `.gitignore` files (defaults to `true` unless `quick` is set).
145
162
  Does nothing when `fileContent` is set.
163
+ - `checkDetected` (boolean):
164
+ Force files marked with `linguist-detectable` to show up in the output, even if the file is not part of the declared `categories`.
146
165
  - `checkHeuristics` (boolean):
147
166
  Apply heuristics to ambiguous languages (defaults to `true` unless `quick` is set).
148
167
  - `checkShebang` (boolean):
@@ -187,6 +206,8 @@ linguist --version
187
206
  Alias for `--checkAttributes=false --checkIgnored=false --checkHeuristics=false --checkShebang=false --checkModeline=false`.
188
207
  - `--offline`:
189
208
  Use pre-packaged metadata files instead of fetching them from GitHub at runtime.
209
+ - `--calculateLines`:
210
+ Calculate line of code totals from files.
190
211
  - `--keepVendored`:
191
212
  Include vendored files (auto-generated files, dependencies folder, etc) in the output.
192
213
  - `--keepBinary`:
@@ -199,6 +220,9 @@ linguist --version
199
220
  - `--checkIgnored`:
200
221
  Force the checking of `.gitignore` files.
201
222
  Use alongside `--quick` to override it disabling this option.
223
+ - `--checkDetected`:
224
+ Force files marked with `linguist-detectable` to show up in the output, even if the file is not part of the declared `--categories`.
225
+ Use alongside `--quick` to override it disabling this option.
202
226
  - `--checkHeuristics`:
203
227
  Apply heuristics to ambiguous languages.
204
228
  Use alongside `--quick` to override it disabling this option.