linguist-js 3.0.0 → 3.0.2

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.
@@ -1,3 +1,4 @@
1
+ import ignore from 'ignore';
1
2
  export function filterFiles(files, opts) {
2
3
  return files.filter((file) => {
3
4
  // Skip binary files
@@ -9,6 +10,10 @@ export function filterFiles(files, opts) {
9
10
  // Skip vendored, generated, or documentation files
10
11
  return false;
11
12
  }
13
+ // Skip manually ignored files
14
+ if (opts.ignoredFiles?.length && ignore().add(opts.ignoredFiles).ignores((file.path))) {
15
+ return false;
16
+ }
12
17
  return true;
13
18
  });
14
19
  }
@@ -1,3 +1,4 @@
1
+ import binaryData from 'binary-extensions';
1
2
  import commonPrefix from 'common-path-prefix';
2
3
  import ignore from 'ignore';
3
4
  import FS from 'node:fs';
@@ -6,7 +7,6 @@ import Attributes from '../program/classes/attributes.js';
6
7
  import { getFileExtension, normPath } from '../program/fs/normalisedPath.js';
7
8
  import walkTree from '../program/fs/walkTree.js';
8
9
  import parseGitattributes from '../program/parsing/parseGitattributes.js';
9
- const binaryData = JSON.parse(FS.readFileSync(new URL('../../node_modules/binary-extensions/binary-extensions.json', import.meta.url), 'utf-8'));
10
10
  export default async function fromFilesystem(input, opts, vendorPaths) {
11
11
  const resolvedInput = input.map((path) => normPath(Path.resolve(path)));
12
12
  const commonRoot = (resolvedInput.length > 1 ? commonPrefix(resolvedInput) : resolvedInput[0]).replace(/\/?$/, '');
@@ -1,3 +1,4 @@
1
+ import YAML from 'js-yaml';
1
2
  import Cache from 'node-cache';
2
3
  import FS from 'node:fs';
3
4
  import Path from 'node:path';
@@ -14,8 +15,15 @@ async function loadWebFile(file) {
14
15
  // Load file content, falling back to the local file if the request fails
15
16
  const fileContent = await fetch(dataUrl(file))
16
17
  .then((data) => data.text())
17
- .catch(async () => await loadLocalFile(file));
18
+ .catch(async (x) => void x);
19
+ if (!fileContent) {
20
+ return await loadLocalFile(file);
21
+ }
18
22
  cache.set(file, fileContent);
23
+ // Clean up lengthy files
24
+ if (file === 'generated.rb') {
25
+ return YAML.dump(parseGeneratedDataFile(fileContent));
26
+ }
19
27
  return fileContent;
20
28
  }
21
29
  async function loadLocalFile(file) {
@@ -1,10 +1,7 @@
1
- import { HeuristicsSchema, LanguagesScema, VendorSchema } from '../../types/schema.js';
1
+ import { HeuristicsSchema, LanguagesScema } from '../../types/schema.js';
2
2
  type LoadedData = {
3
3
  langData: LanguagesScema;
4
- vendorData: VendorSchema;
5
- docData: VendorSchema;
6
4
  heuristicsData: HeuristicsSchema;
7
- generatedData: string[];
8
5
  vendorPaths: string[];
9
6
  };
10
7
  /** Load data from github-linguist web repo or cached local file. */
@@ -1,22 +1,19 @@
1
1
  import YAML from 'js-yaml';
2
- import { loadFile, parseGeneratedDataFile } from './loadDataFiles.js';
2
+ import { loadFile } from './loadDataFiles.js';
3
3
  let data = null;
4
4
  async function initRetrieveData(offline) {
5
- // Only load the data on mont
5
+ // Only load the data on mount
6
6
  if (data)
7
7
  return;
8
8
  const langData = (await loadFile('languages.yml', offline).then(YAML.load));
9
9
  const vendorData = (await loadFile('vendor.yml', offline).then(YAML.load));
10
10
  const docData = (await loadFile('documentation.yml', offline).then(YAML.load));
11
11
  const heuristicsData = (await loadFile('heuristics.yml', offline).then(YAML.load));
12
- const generatedData = (await loadFile('generated.rb', offline).then(parseGeneratedDataFile));
12
+ const generatedData = (await loadFile('generated.rb', offline).then(YAML.load));
13
13
  const vendorPaths = [...vendorData, ...docData, ...generatedData];
14
14
  data = {
15
15
  langData,
16
- vendorData,
17
- docData,
18
16
  heuristicsData,
19
- generatedData,
20
17
  vendorPaths,
21
18
  };
22
19
  }
@@ -31,7 +31,8 @@ export default function walkTree(data) {
31
31
  const ignoredPaths = parseGitignore(gitignoreContents);
32
32
  const rootRelIgnoredPaths = ignoredPaths.map((ignorePath) =>
33
33
  // get absolute path of the ignore glob
34
- normPath(folder, ignorePath)
34
+ // use '/**/' to ensure matches in subfolders are also ignored
35
+ normPath(folder, '**', ignorePath)
35
36
  // convert abs ignore glob to be relative to the root folder
36
37
  .replace(commonRoot + '/', ''));
37
38
  ignored.add(rootRelIgnoredPaths);
@@ -14,6 +14,7 @@ export default function pcre(regex) {
14
14
  // Remove PCRE-only syntax
15
15
  replace(/([*+]){2}/g, '$1');
16
16
  replace(/\(\?>/g, '(?:');
17
+ replace(/\\g\<[^>]+\>/g, '.*?'); // referenced named groups not supported
17
18
  // Remove start/end-of-file markers
18
19
  if (/\\[AZ]/.test(finalRegex)) {
19
20
  replace(/\\A/g, '^');
@@ -176,6 +176,13 @@ disambiguations:
176
176
  rules:
177
177
  - language: Gerber Image
178
178
  pattern: '^[DGMT][0-9]{2}\*(?:\r?\n|\r)'
179
+ - extensions: ['.container', '.mount', '.network', '.service', '.socket', '.target', '.timer']
180
+ rules:
181
+ - language: INI
182
+ and:
183
+ - pattern: '^[#\s]*\[[^\]]+\]\s*$'
184
+ - named_pattern: key_equals_value
185
+ - negative_pattern: '^[^#;=\[]+[^ \r\n=]$'
179
186
  - extensions: ['.cs']
180
187
  rules:
181
188
  - language: Smalltalk
@@ -597,6 +604,15 @@ disambiguations:
597
604
  pattern:
598
605
  - '(?i)\bDEFINE\s+(?:VARIABLE|TEMP-TABLE|BUFFER|QUERY|INPUT\s+PARAMETER|OUTPUT\s+PARAMETER)\b'
599
606
  - '(?i)\bEND(?:\s+(?:PROCEDURE|FUNCTION|DO|FOR\s+EACH))?\.'
607
+ - extensions: ['.pc']
608
+ rules:
609
+ - language: Pro*C
610
+ pattern: '^\s*EXEC\s+SQL\s'
611
+ - language: pkg-config
612
+ and:
613
+ - pattern: '^Name:[ \t]+\S'
614
+ - pattern: '^Description:[ \t]+\S'
615
+ - pattern: '^Version:[ \t]+\S'
600
616
  - extensions: ['.php']
601
617
  rules:
602
618
  - language: Hack
package/ext/languages.yml CHANGED
@@ -513,6 +513,16 @@ B4X:
513
513
  codemirror_mode: vb
514
514
  codemirror_mime_type: text/x-vb
515
515
  language_id: 96642275
516
+ BAML:
517
+ type: programming
518
+ color: "#a855f7"
519
+ extensions:
520
+ - ".baml"
521
+ tm_scope: source.baml
522
+ ace_mode: io
523
+ codemirror_mode: stylus
524
+ codemirror_mime_type: text/x-styl
525
+ language_id: 502521509
516
526
  BASIC:
517
527
  type: programming
518
528
  extensions:
@@ -673,6 +683,16 @@ BlitzMax:
673
683
  tm_scope: source.blitzmax
674
684
  ace_mode: text
675
685
  language_id: 35
686
+ Blueprint:
687
+ type: markup
688
+ color: "#3584E4"
689
+ extensions:
690
+ - ".blp"
691
+ aliases:
692
+ - blp
693
+ tm_scope: source.blueprint
694
+ ace_mode: text
695
+ language_id: 765545512
676
696
  Bluespec:
677
697
  type: programming
678
698
  color: "#12223c"
@@ -792,7 +812,7 @@ C#:
792
812
  codemirror_mode: clike
793
813
  codemirror_mime_type: text/x-csharp
794
814
  tm_scope: source.cs
795
- color: "#178600"
815
+ color: "#7355dd"
796
816
  aliases:
797
817
  - csharp
798
818
  - cake
@@ -2618,6 +2638,8 @@ Git Config:
2618
2638
  filenames:
2619
2639
  - ".gitconfig"
2620
2640
  - ".gitmodules"
2641
+ - ".tgitconfig"
2642
+ - config.worktree
2621
2643
  ace_mode: ini
2622
2644
  codemirror_mode: properties
2623
2645
  codemirror_mime_type: text/x-properties
@@ -2885,6 +2907,23 @@ Groovy Server Pages:
2885
2907
  codemirror_mode: htmlembedded
2886
2908
  codemirror_mime_type: application/x-jsp
2887
2909
  language_id: 143
2910
+ GtkRC:
2911
+ type: data
2912
+ color: "#7fe719"
2913
+ aliases:
2914
+ - gtk
2915
+ - gtk 1
2916
+ - gtk 2
2917
+ extensions:
2918
+ - ".gtkrc"
2919
+ filenames:
2920
+ - gtkrc
2921
+ - gtkrc-2.0
2922
+ tm_scope: source.gtkrc
2923
+ ace_mode: ruby
2924
+ codemirror_mode: ruby
2925
+ codemirror_mime_type: text/x-ruby
2926
+ language_id: 876401352
2888
2927
  HAProxy:
2889
2928
  type: data
2890
2929
  color: "#106da9"
@@ -3234,12 +3273,19 @@ INI:
3234
3273
  - ".ini"
3235
3274
  - ".cfg"
3236
3275
  - ".cnf"
3276
+ - ".container"
3237
3277
  - ".dof"
3238
3278
  - ".frm"
3239
3279
  - ".lektorproject"
3280
+ - ".mount"
3281
+ - ".network"
3240
3282
  - ".prefs"
3241
3283
  - ".pro"
3242
3284
  - ".properties"
3285
+ - ".service"
3286
+ - ".socket"
3287
+ - ".target"
3288
+ - ".timer"
3243
3289
  - ".url"
3244
3290
  filenames:
3245
3291
  - ".buckconfig"
@@ -3253,6 +3299,7 @@ INI:
3253
3299
  - vlcrc
3254
3300
  tm_scope: source.ini
3255
3301
  aliases:
3302
+ - conf
3256
3303
  - dosini
3257
3304
  ace_mode: ini
3258
3305
  codemirror_mode: properties
@@ -3303,11 +3350,13 @@ Ignore List:
3303
3350
  - ".atomignore"
3304
3351
  - ".babelignore"
3305
3352
  - ".bzrignore"
3353
+ - ".ckignore"
3306
3354
  - ".coffeelintignore"
3307
3355
  - ".cvsignore"
3308
3356
  - ".dockerignore"
3309
3357
  - ".easignore"
3310
3358
  - ".eleventyignore"
3359
+ - ".eslint-ignore"
3311
3360
  - ".eslintignore"
3312
3361
  - ".gitignore"
3313
3362
  - ".ignore"
@@ -3315,6 +3364,7 @@ Ignore List:
3315
3364
  - ".nodemonignore"
3316
3365
  - ".npmignore"
3317
3366
  - ".prettierignore"
3367
+ - ".rgignore"
3318
3368
  - ".stylelintignore"
3319
3369
  - ".vercelignore"
3320
3370
  - ".vscodeignore"
@@ -3471,6 +3521,7 @@ JSON:
3471
3521
  - ".jsonl"
3472
3522
  - ".mcmeta"
3473
3523
  - ".sarif"
3524
+ - ".slnlaunch"
3474
3525
  - ".tact"
3475
3526
  - ".tfstate"
3476
3527
  - ".tfstate.backup"
@@ -3696,8 +3747,10 @@ JavaScript:
3696
3747
  filenames:
3697
3748
  - Jakefile
3698
3749
  interpreters:
3750
+ - bun
3699
3751
  - chakra
3700
3752
  - d8
3753
+ - deno
3701
3754
  - gjs
3702
3755
  - js
3703
3756
  - node
@@ -4526,6 +4579,7 @@ Makefile:
4526
4579
  - Makefile.frag
4527
4580
  - Makefile.in
4528
4581
  - Makefile.inc
4582
+ - Makefile.pc
4529
4583
  - Makefile.wat
4530
4584
  - makefile
4531
4585
  - makefile.sco
@@ -5487,6 +5541,19 @@ Org:
5487
5541
  tm_scope: none
5488
5542
  ace_mode: text
5489
5543
  language_id: 267
5544
+ OverPy:
5545
+ type: programming
5546
+ color: "#78b355"
5547
+ wrap: true
5548
+ extensions:
5549
+ - ".opy"
5550
+ tm_scope: source.opy
5551
+ aliases:
5552
+ - opy
5553
+ ace_mode: python
5554
+ codemirror_mode: python
5555
+ codemirror_mime_type: text/x-python
5556
+ language_id: 492781155
5490
5557
  OverpassQL:
5491
5558
  type: programming
5492
5559
  color: "#cce2aa"
@@ -5912,6 +5979,16 @@ PostScript:
5912
5979
  - postscr
5913
5980
  ace_mode: text
5914
5981
  language_id: 291
5982
+ Power Query:
5983
+ type: programming
5984
+ aliases:
5985
+ - powerquery
5986
+ extensions:
5987
+ - ".pq"
5988
+ tm_scope: source.powerquery
5989
+ ace_mode: text
5990
+ color: "#d38e0d"
5991
+ language_id: 37496382
5915
5992
  PowerBuilder:
5916
5993
  type: programming
5917
5994
  color: "#8f0f8d"
@@ -5956,6 +6033,17 @@ Prisma:
5956
6033
  tm_scope: source.prisma
5957
6034
  ace_mode: prisma
5958
6035
  language_id: 499933428
6036
+ Pro*C:
6037
+ fs_name: ProC
6038
+ color: "#bb8368"
6039
+ type: programming
6040
+ extensions:
6041
+ - ".pc"
6042
+ tm_scope: source.c
6043
+ ace_mode: c_cpp
6044
+ codemirror_mode: clike
6045
+ codemirror_mime_type: text/x-csrc
6046
+ language_id: 991047534
5959
6047
  Processing:
5960
6048
  type: programming
5961
6049
  color: "#0096D8"
@@ -6577,6 +6665,14 @@ Redirect Rules:
6577
6665
  tm_scope: source.redirects
6578
6666
  ace_mode: text
6579
6667
  language_id: 1020148948
6668
+ Redscript:
6669
+ type: programming
6670
+ color: "#f44336"
6671
+ extensions:
6672
+ - ".reds"
6673
+ tm_scope: source.redscript
6674
+ ace_mode: text
6675
+ language_id: 686691365
6580
6676
  Regular Expression:
6581
6677
  type: data
6582
6678
  color: "#009a00"
@@ -6647,6 +6743,17 @@ RobotFramework:
6647
6743
  tm_scope: text.robot
6648
6744
  ace_mode: robot
6649
6745
  language_id: 324
6746
+ Robots Exclusion Rules:
6747
+ type: data
6748
+ aliases:
6749
+ - robots
6750
+ - robots txt
6751
+ - robotx.txt
6752
+ filenames:
6753
+ - robots.txt
6754
+ ace_mode: text
6755
+ tm_scope: text.robots-txt
6756
+ language_id: 674736065
6650
6757
  Roc:
6651
6758
  type: programming
6652
6759
  color: "#7c38f5"
@@ -7901,6 +8008,7 @@ Text:
7901
8008
  - README.me
7902
8009
  - README.mysql
7903
8010
  - README.nss
8011
+ - README.pc
7904
8012
  - click.me
7905
8013
  - delete.me
7906
8014
  - keep.me
@@ -8217,6 +8325,7 @@ Valve Data Format:
8217
8325
  - vdf
8218
8326
  extensions:
8219
8327
  - ".vdf"
8328
+ - ".vmf"
8220
8329
  ace_mode: text
8221
8330
  tm_scope: source.keyvalues
8222
8331
  language_id: 544060961
@@ -9050,11 +9159,11 @@ crontab:
9050
9159
  ace_mode: tcl
9051
9160
  language_id: 705203557
9052
9161
  desktop:
9162
+ group: INI
9053
9163
  type: data
9054
9164
  extensions:
9055
9165
  - ".desktop"
9056
9166
  - ".desktop.in"
9057
- - ".service"
9058
9167
  tm_scope: source.desktop
9059
9168
  ace_mode: text
9060
9169
  language_id: 412
@@ -9208,6 +9317,19 @@ ooc:
9208
9317
  tm_scope: source.ooc
9209
9318
  ace_mode: text
9210
9319
  language_id: 418
9320
+ pkg-config:
9321
+ type: data
9322
+ color: "#2b5e82"
9323
+ aliases:
9324
+ - pkgconf
9325
+ extensions:
9326
+ - ".pc"
9327
+ - ".pc.in"
9328
+ tm_scope: source.pkgconf
9329
+ ace_mode: properties
9330
+ codemirror_mode: properties
9331
+ codemirror_mime_type: text/x-properties
9332
+ language_id: 925023573
9211
9333
  q:
9212
9334
  type: programming
9213
9335
  extensions:
@@ -9234,16 +9356,6 @@ reStructuredText:
9234
9356
  codemirror_mode: rst
9235
9357
  codemirror_mime_type: text/x-rst
9236
9358
  language_id: 419
9237
- robots.txt:
9238
- type: data
9239
- aliases:
9240
- - robots
9241
- - robots txt
9242
- filenames:
9243
- - robots.txt
9244
- ace_mode: text
9245
- tm_scope: text.robots-txt
9246
- language_id: 674736065
9247
9359
  sed:
9248
9360
  type: programming
9249
9361
  color: "#64b970"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linguist-js",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Analyse the programming languages used in a folder or from raw content, using the same rules that GitHub Linguist does.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -45,14 +45,14 @@
45
45
  "common-path-prefix": "^3.0.0",
46
46
  "ignore": "^7.0.5",
47
47
  "isbinaryfile": "^6.0.0",
48
- "js-yaml": "^4.1.1",
48
+ "js-yaml": "^4.3.0",
49
49
  "node-cache": "^5.1.2"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/js-yaml": "^4.0.9",
53
- "@types/node": "^25.9.1",
53
+ "@types/node": "^25.9.4",
54
54
  "deep-object-diff": "^1.1.9",
55
- "prettier": "^3.8.3",
55
+ "prettier": "^3.9.4",
56
56
  "typescript": "~6.0.3"
57
57
  }
58
58
  }
package/readme.md CHANGED
@@ -50,8 +50,8 @@ Running LinguistJS on this will return the following JSON:
50
50
  {
51
51
  "files": {
52
52
  "count": 4,
53
- "bytes": 31,
54
- "lines": { "total": 8, "content": 4, "code": 4 },
53
+ "bytes": 6010,
54
+ "lines": { "total": 150, "content": 75 },
55
55
  "results": {
56
56
  "/info.md": "Markdown",
57
57
  "/no-lang": null,
@@ -61,35 +61,25 @@ Running LinguistJS on this will return the following JSON:
61
61
  },
62
62
  "languages": {
63
63
  "count": 3,
64
- "bytes": 18,
65
- "lines": { "total": 6, "content": 3, "code": 3 },
64
+ "bytes": 6000,
65
+ "lines": { "total": 147, "content": 74 },
66
66
  "results": {
67
- "Markdown": {
68
- "type": "prose",
69
- "bytes": 6,
70
- "lines": { "total": 2, "content": 1, "code": 1 },
71
- "color": "#083fa1"
72
- },
73
- "JavaScript": {
74
- "type": "programming",
75
- "bytes": 6,
76
- "lines": { "total": 2, "content": 1, "code": 1 },
77
- "color": "#f1e05a"
78
- },
79
- "TypeScript": {
80
- "type": "programming",
81
- "bytes": 6,
82
- "lines": { "total": 2, "content": 1, "code": 1 },
83
- "color": "#3178c6"
84
- }
67
+ "Markdown": { "count": 1, "bytes": 3000, "lines": { "total": 10, "content": 5 } },
68
+ "JavaScript": { "count": 1, "bytes": 1000, "lines": { "total": 46, "content": 23 } },
69
+ "TypeScript": { "count": 1, "bytes": 2000, "lines": { "total": 91, "content": 46 } }
85
70
  }
86
71
  },
87
72
  "unknown": {
88
73
  "count": 1,
89
- "bytes": 13,
90
- "lines": { "total": 2, "content": 1, "code": 1 },
74
+ "bytes": 10,
75
+ "lines": { "total": 3, "content": 1 },
91
76
  "extensions": {},
92
- "filenames": { "no-lang": 13 }
77
+ "filenames": { "no-lang": 10 }
78
+ },
79
+ "repository": {
80
+ "Markdown": { "type": "prose", "color": "#083fa1" },
81
+ "JavaScript": { "type": "programming", "color": "#f1e05a" },
82
+ "TypeScript": { "type": "programming", "color": "#3178c6" }
93
83
  }
94
84
  }
95
85
  ```
@@ -126,15 +116,15 @@ const { files, languages, unknown, repository } = await linguist.analyseRawConte
126
116
  **Exports:**
127
117
 
128
118
  - `analyseFolders(folders?, opts?)`:
129
- Analyse the language of all files found in a folder or folders.
119
+ Analyse the language of all files found in a list of folders.
130
120
  - `folders` (optional; string array):
131
121
  A list of folders to analyse (defaults to `['./']`).
132
122
  - `opts` (optional; object):
133
123
  An object containing analyser options.
134
- - `analyseRawContent(folders?, opts?)`:
135
- Analyse the language of all files found in a folder or folders.
136
- - `entry` (optional; string or string array):
137
- A list of folders to analyse (defaults to `['./']`).
124
+ - `analyseRawContent(fileContent, opts?)`:
125
+ Analyse the language of of preloaded file content.
126
+ - `fileContent` (string-string map):
127
+ A mapping of file name to file content to analyse.
138
128
  - `opts` (optional; object):
139
129
  An object containing analyser options.
140
130