linguist-js 2.1.3 → 2.3.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
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const VERSION = require('../package.json').version;
7
7
  const commander_1 = require("commander");
8
8
  const index_1 = __importDefault(require("./index"));
9
+ const walk_tree_1 = __importDefault(require("./helpers/walk-tree"));
9
10
  const colouredMsg = ([r, g, b], msg) => `\u001B[${38};2;${r};${g};${b}m${msg}${'\u001b[0m'}`;
10
11
  const hexToRgb = (hex) => [parseInt(hex.slice(1, 3), 16), parseInt(hex.slice(3, 5), 16), parseInt(hex.slice(5, 7), 16)];
11
12
  commander_1.program
@@ -21,6 +22,7 @@ commander_1.program
21
22
  .option('-q|--quick [bool]', 'Skip complex language analysis (alias for -{A|I|H|S}=false)', false)
22
23
  .option('-V|--keepVendored [bool]', 'Prevent skipping over vendored/generated files', false)
23
24
  .option('-B|--keepBinary [bool]', 'Prevent skipping over binary files', false)
25
+ .option('-r|--relativePaths [bool]', 'Convert absolute file paths to relative', false)
24
26
  .option('-A|--checkAttributes [bool]', 'Force the checking of gitattributes files', true)
25
27
  .option('-I|--checkIgnored [bool]', 'Force the checking of gitignore files', true)
26
28
  .option('-H|--checkHeuristics [bool]', 'Apply heuristics to ambiguous languages', true)
@@ -49,17 +51,23 @@ if (args.analyze)
49
51
  (async () => {
50
52
  // Fetch language data
51
53
  const root = args.analyze === true ? '.' : args.analyze;
52
- const { files, languages, unknown } = await (0, index_1.default)(root, args);
54
+ const data = await (0, index_1.default)(root, args);
55
+ const { files, languages, unknown } = data;
56
+ // Get file count
57
+ const totalFiles = (0, walk_tree_1.default)(root).files.length;
53
58
  // Print output
54
59
  if (!args.json) {
55
60
  const sortedEntries = Object.entries(languages.results).sort((a, b) => a[1].bytes < b[1].bytes ? +1 : -1);
56
61
  const totalBytes = languages.bytes;
57
- console.log(`\n Analysed ${files.bytes.toLocaleString()} B from ${files.count} files with linguist-js`);
62
+ console.log(`\n Analysed ${files.bytes.toLocaleString()} B from ${totalFiles} files (${totalFiles - files.count} ignored) with linguist-js`);
58
63
  console.log(`\n Language analysis results:`);
59
- let i = 0;
64
+ let count = 0;
65
+ if (sortedEntries.length === 0)
66
+ console.log(` None`);
67
+ // List parsed results
60
68
  for (const [lang, { bytes, color }] of sortedEntries) {
61
69
  const fmtd = {
62
- index: (++i).toString().padStart(2, ' '),
70
+ index: (++count).toString().padStart(2, ' '),
63
71
  lang: lang.padEnd(24, ' '),
64
72
  percent: (bytes / (totalBytes || 1) * 100).toFixed(2).padStart(5, ' '),
65
73
  bytes: bytes.toLocaleString().padStart(10, ' '),
@@ -68,35 +76,33 @@ if (args.analyze)
68
76
  console.log(` ${fmtd.index}. ${fmtd.icon} ${fmtd.lang} ${fmtd.percent}% ${fmtd.bytes} B`);
69
77
  }
70
78
  console.log(` Total: ${totalBytes.toLocaleString()} B`);
79
+ // List unknown files/extensions
71
80
  if (unknown.bytes > 0) {
72
81
  console.log(`\n Unknown files and extensions:`);
73
82
  for (const [name, bytes] of Object.entries(unknown.filenames)) {
74
83
  console.log(` '${name}': ${bytes.toLocaleString()} B`);
75
84
  }
76
85
  for (const [ext, bytes] of Object.entries(unknown.extensions)) {
77
- console.log(` '${ext}': ${bytes.toLocaleString()} B`);
86
+ console.log(` '*${ext}': ${bytes.toLocaleString()} B`);
78
87
  }
79
88
  console.log(` Total: ${unknown.bytes.toLocaleString()} B`);
80
89
  }
81
90
  }
82
- else {
83
- const data = { files, languages, unknown };
84
- if (args.tree) {
85
- const treeParts = args.tree.split('.');
86
- let nestedData = data;
87
- for (const part of treeParts) {
88
- if (!nestedData[part])
89
- throw Error(`TraversalError: Key '${part}' cannot be found on output object.`);
90
- nestedData = nestedData[part];
91
- }
92
- console.log(nestedData);
93
- }
94
- else {
95
- console.log(JSON.stringify(data, null, 2).replace(/{\s+"type".+?}/sg, obj => obj.replace(/\n\s+/g, ' ')));
91
+ else if (args.tree) {
92
+ const treeParts = args.tree.split('.');
93
+ let nestedData = data;
94
+ for (const part of treeParts) {
95
+ if (!nestedData[part])
96
+ throw Error(`TraversalError: Key '${part}' cannot be found on output object.`);
97
+ nestedData = nestedData[part];
96
98
  }
99
+ console.log(nestedData);
100
+ }
101
+ else {
102
+ console.dir(data, { depth: null });
97
103
  }
98
104
  })();
99
105
  else {
100
- console.log(`Welcome to linguist-js, the JavaScript port of GitHub's language analyzer.`);
106
+ console.log(`Welcome to linguist-js, a JavaScript port of GitHub's language analyzer.`);
101
107
  console.log(`Type 'linguist --help' for a list of commands.`);
102
108
  }
@@ -0,0 +1,11 @@
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 glob_to_regexp_1 = __importDefault(require("glob-to-regexp"));
7
+ function parseGitGlob(path) {
8
+ const globPath = `**/${path}`.replace(/\\/g, '/').replace(/\[:(space|digit):\]/g, (_, val) => `\\${val[0]}`);
9
+ return (0, glob_to_regexp_1.default)(globPath, { globstar: true, extended: true });
10
+ }
11
+ exports.default = parseGitGlob;
@@ -4,12 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const fs_1 = __importDefault(require("fs"));
7
- /** Read part of a file on disc. */
7
+ /**
8
+ * Read part of a file on disc.
9
+ * @throws 'EPERM' if the file is not readable.
10
+ */
8
11
  async function readFile(filename, onlyFirstLine = false) {
9
12
  const chunkSize = 100;
10
13
  const stream = fs_1.default.createReadStream(filename, { highWaterMark: chunkSize });
11
14
  let content = '';
12
- for await (const data of stream) {
15
+ for await (const data of stream) { // may throw
13
16
  content += data.toString();
14
17
  if (onlyFirstLine && content.includes('\n')) {
15
18
  return content.split(/\r?\n/)[0];
package/dist/index.js CHANGED
@@ -12,10 +12,10 @@ const walk_tree_1 = __importDefault(require("./helpers/walk-tree"));
12
12
  const load_data_1 = __importDefault(require("./helpers/load-data"));
13
13
  const read_file_1 = __importDefault(require("./helpers/read-file"));
14
14
  const convert_pcre_1 = __importDefault(require("./helpers/convert-pcre"));
15
- const convertToRegex = (path) => (0, glob_to_regexp_1.default)('**/' + path, { globstar: true, extended: true });
15
+ const convert_glob_1 = __importDefault(require("./helpers/convert-glob"));
16
16
  async function analyse(input, opts = {}) {
17
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
18
- var _k, _l, _m;
17
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
18
+ var _r, _s, _t;
19
19
  const langData = await (0, load_data_1.default)('languages.yml').then(js_yaml_1.default.load);
20
20
  const vendorData = await (0, load_data_1.default)('vendor.yml').then(js_yaml_1.default.load);
21
21
  const heuristicsData = await (0, load_data_1.default)('heuristics.yml').then(js_yaml_1.default.load);
@@ -34,7 +34,16 @@ async function analyse(input, opts = {}) {
34
34
  opts.keepVendored ? [] : vendorData.map(path => RegExp(path)),
35
35
  (_b = (_a = opts.ignoredFiles) === null || _a === void 0 ? void 0 : _a.map(path => (0, glob_to_regexp_1.default)('*' + path + '*', { extended: true }))) !== null && _b !== void 0 ? _b : [],
36
36
  ].flat();
37
- let { files, folders } = (0, walk_tree_1.default)(input !== null && input !== void 0 ? input : '.', ignoredFiles);
37
+ let files, folders;
38
+ if (opts.fileContent) {
39
+ opts.fileContent = Array.isArray(opts.fileContent) ? opts.fileContent : [opts.fileContent];
40
+ files = [`${input}`];
41
+ folders = [''];
42
+ }
43
+ else {
44
+ const data = (0, walk_tree_1.default)(input !== null && input !== void 0 ? input : '.', ignoredFiles);
45
+ ({ files, folders } = data);
46
+ }
38
47
  // Apply aliases
39
48
  opts = { checkIgnored: !opts.quick, checkAttributes: !opts.quick, checkHeuristics: !opts.quick, checkShebang: !opts.quick, ...opts };
40
49
  // Ignore specific languages
@@ -50,26 +59,26 @@ async function analyse(input, opts = {}) {
50
59
  const customIgnored = [];
51
60
  const customBinary = [];
52
61
  const customText = [];
53
- if (!opts.quick) {
62
+ if (!opts.fileContent && !opts.quick) {
54
63
  for (const folder of folders) {
55
64
  // Skip if folder is marked in gitattributes
56
- if (customIgnored.some(path => convertToRegex(path).test(folder)))
65
+ if (customIgnored.some(path => (0, convert_glob_1.default)(path).test(folder)))
57
66
  continue;
58
67
  // Parse gitignores
59
68
  const ignoresFile = path_1.default.join(folder, '.gitignore');
60
69
  if (opts.checkIgnored && fs_1.default.existsSync(ignoresFile)) {
61
70
  const ignoresData = await (0, read_file_1.default)(ignoresFile);
62
71
  const ignoresList = ignoresData.split(/\r?\n/).filter(line => line.trim() && !line.startsWith('#'));
63
- const ignoredPaths = ignoresList.map(path => convertToRegex(path).source);
64
- customIgnored.push(...ignoredPaths.map(file => file.replace(folder, '')));
72
+ const ignoredPaths = ignoresList.map(path => (0, convert_glob_1.default)(path).source);
73
+ customIgnored.push(...ignoredPaths);
65
74
  }
66
75
  // Parse gitattributes
67
76
  const attributesFile = path_1.default.join(folder, '.gitattributes');
68
77
  if (opts.checkAttributes && fs_1.default.existsSync(attributesFile)) {
69
78
  const attributesData = await (0, read_file_1.default)(attributesFile);
70
- const relPathToRegex = (path) => convertToRegex(path).source.substr(1).replace(folder, '');
79
+ const relPathToRegex = (path) => (0, convert_glob_1.default)(path).source.substr(1).replace(folder, '');
71
80
  // Explicit text/binary associations
72
- const contentTypeMatches = attributesData.matchAll(/^(\S+).*?(-?binary|-?text)/gm);
81
+ const contentTypeMatches = attributesData.matchAll(/^(\S+).*?(-?binary|-?text)(?!=auto)/gm);
73
82
  for (const [_line, path, type] of contentTypeMatches) {
74
83
  if (['text', '-binary'].includes(type))
75
84
  customText.push(relPathToRegex(path));
@@ -90,14 +99,14 @@ async function analyse(input, opts = {}) {
90
99
  if (overrideLang)
91
100
  forcedLang = overrideLang[0];
92
101
  }
93
- const fullPath = folder + convertToRegex(path).source.substr(1);
102
+ const fullPath = folder + (0, convert_glob_1.default)(path).source.substr(1);
94
103
  overrides[fullPath] = forcedLang;
95
104
  }
96
105
  }
97
106
  }
98
107
  }
99
108
  // Check vendored files
100
- if (!opts.keepVendored) {
109
+ if (!opts.fileContent && !opts.keepVendored) {
101
110
  // Filter out any files that match a vendor file path
102
111
  const matcher = (match) => RegExp(match.replace(/\/$/, '/.+$').replace(/^\.\//, ''));
103
112
  files = files.filter(file => !customIgnored.some(pattern => matcher(pattern).test(file)));
@@ -115,22 +124,30 @@ async function analyse(input, opts = {}) {
115
124
  const overridesArray = Object.entries(overrides);
116
125
  // List all languages that could be associated with a given file
117
126
  for (const file of files) {
118
- if (!fs_1.default.existsSync(file) || fs_1.default.lstatSync(file).isDirectory())
127
+ let firstLine;
128
+ if (opts.fileContent) {
129
+ firstLine = (_f = (_e = (_d = opts.fileContent) === null || _d === void 0 ? void 0 : _d[files.indexOf(file)]) === null || _e === void 0 ? void 0 : _e.split('\n')[0]) !== null && _f !== void 0 ? _f : null;
130
+ }
131
+ else {
132
+ if (!fs_1.default.existsSync(file) || fs_1.default.lstatSync(file).isDirectory())
133
+ continue;
134
+ firstLine = await (0, read_file_1.default)(file, true).catch(() => null);
135
+ }
136
+ // Skip if file is unreadable
137
+ if (firstLine === null)
119
138
  continue;
120
139
  // Check shebang line for explicit classification
121
- if (!opts.quick && opts.checkShebang) {
122
- const firstLine = await (0, read_file_1.default)(file, true);
123
- if (firstLine.startsWith('#!')) {
124
- const matches = Object.entries(langData).filter(([, data]) => { var _a; return (_a = data.interpreters) === null || _a === void 0 ? void 0 : _a.some(interpreter => firstLine.match('\\b' + interpreter + '\\b')); });
125
- if (matches.length) {
126
- const forcedLang = matches[0][0];
127
- addResult(file, forcedLang);
128
- continue;
129
- }
140
+ if (!opts.quick && opts.checkShebang && firstLine.startsWith('#!')) {
141
+ // Find matching interpreters
142
+ const matches = Object.entries(langData).filter(([, data]) => { var _a; return (_a = data.interpreters) === null || _a === void 0 ? void 0 : _a.some(interpreter => firstLine.match('\\b' + interpreter + '\\b')); });
143
+ if (matches.length) {
144
+ // Add explicitly-identified language
145
+ const forcedLang = matches[0][0];
146
+ addResult(file, forcedLang);
130
147
  }
131
148
  }
132
149
  // Check override for manual language classification
133
- if (!opts.quick && opts.checkAttributes) {
150
+ if (!opts.fileContent && !opts.quick && opts.checkAttributes) {
134
151
  const match = overridesArray.find(item => RegExp(item[0]).test(file));
135
152
  if (match) {
136
153
  const forcedLang = match[1];
@@ -142,7 +159,7 @@ async function analyse(input, opts = {}) {
142
159
  let skipExts = false;
143
160
  for (const lang in langData) {
144
161
  // Check if filename is a match
145
- const matchesName = (_d = langData[lang].filenames) === null || _d === void 0 ? void 0 : _d.some(name => path_1.default.basename(file.toLowerCase()) === name.toLowerCase());
162
+ const matchesName = (_g = langData[lang].filenames) === null || _g === void 0 ? void 0 : _g.some(name => path_1.default.basename(file.toLowerCase()) === name.toLowerCase());
146
163
  if (matchesName) {
147
164
  addResult(file, lang);
148
165
  skipExts = true;
@@ -151,7 +168,7 @@ async function analyse(input, opts = {}) {
151
168
  if (!skipExts)
152
169
  for (const lang in langData) {
153
170
  // Check if extension is a match
154
- const matchesExt = (_e = langData[lang].extensions) === null || _e === void 0 ? void 0 : _e.some(ext => file.toLowerCase().endsWith(ext.toLowerCase()));
171
+ const matchesExt = (_h = langData[lang].extensions) === null || _h === void 0 ? void 0 : _h.some(ext => file.toLowerCase().endsWith(ext.toLowerCase()));
155
172
  if (matchesExt)
156
173
  addResult(file, lang);
157
174
  }
@@ -162,7 +179,7 @@ async function analyse(input, opts = {}) {
162
179
  // Narrow down file associations to the best fit
163
180
  for (const file in fileAssociations) {
164
181
  // Skip binary files
165
- if (!opts.keepBinary) {
182
+ if (!opts.fileContent && !opts.keepBinary) {
166
183
  const isCustomText = customText.some(path => RegExp(path).test(file));
167
184
  const isCustomBinary = customBinary.some(path => RegExp(path).test(file));
168
185
  const isBinaryExt = binary_extensions_1.default.some(ext => file.endsWith('.' + ext));
@@ -196,7 +213,9 @@ async function analyse(input, opts = {}) {
196
213
  if (heuristic.named_pattern)
197
214
  normalise(heuristicsData.named_patterns[heuristic.named_pattern]);
198
215
  // Check file contents and apply heuristic patterns
199
- const fileContent = await (0, read_file_1.default)(file);
216
+ const fileContent = await (0, read_file_1.default)(file).catch(() => null);
217
+ if (fileContent === null)
218
+ continue;
200
219
  if (!patterns.length || patterns.some(pattern => (0, convert_pcre_1.default)(pattern).test(fileContent))) {
201
220
  results.files.results[file] = heuristic.language;
202
221
  break;
@@ -204,10 +223,10 @@ async function analyse(input, opts = {}) {
204
223
  }
205
224
  }
206
225
  // If no heuristics, assign a language
207
- (_f = (_k = results.files.results)[file]) !== null && _f !== void 0 ? _f : (_k[file] = fileAssociations[file][0]);
226
+ (_j = (_r = results.files.results)[file]) !== null && _j !== void 0 ? _j : (_r[file] = fileAssociations[file][0]);
208
227
  }
209
228
  // Skip specified categories
210
- if ((_g = opts.categories) === null || _g === void 0 ? void 0 : _g.length) {
229
+ if ((_k = opts.categories) === null || _k === void 0 ? void 0 : _k.length) {
211
230
  const categories = ['data', 'markup', 'programming', 'prose'];
212
231
  const hiddenCategories = categories.filter(cat => !opts.categories.includes(cat));
213
232
  for (const [file, lang] of Object.entries(results.files.results)) {
@@ -224,25 +243,36 @@ async function analyse(input, opts = {}) {
224
243
  }
225
244
  }
226
245
  }
246
+ // Convert paths to relative
247
+ if (!opts.fileContent && opts.relativePaths) {
248
+ const newMap = {};
249
+ for (const [file, lang] of Object.entries(results.files.results)) {
250
+ let relPath = path_1.default.relative(process.cwd(), file).replace(/\\/g, '/');
251
+ if (!relPath.startsWith('../'))
252
+ relPath = './' + relPath;
253
+ newMap[relPath] = lang;
254
+ }
255
+ results.files.results = newMap;
256
+ }
227
257
  // Load language bytes size
228
258
  for (const [file, lang] of Object.entries(results.files.results)) {
229
259
  if (lang && !langData[lang])
230
260
  continue;
231
- const fileSize = fs_1.default.statSync(file).size;
261
+ const fileSize = (_o = (_m = (_l = opts.fileContent) === null || _l === void 0 ? void 0 : _l[files.indexOf(file)]) === null || _m === void 0 ? void 0 : _m.length) !== null && _o !== void 0 ? _o : fs_1.default.statSync(file).size;
232
262
  results.files.bytes += fileSize;
233
263
  // If no language found, add extension in other section
234
264
  if (!lang) {
235
265
  const ext = path_1.default.extname(file);
236
266
  const unknownType = ext === '' ? 'filenames' : 'extensions';
237
267
  const name = ext === '' ? path_1.default.basename(file) : ext;
238
- (_h = (_l = results.unknown[unknownType])[name]) !== null && _h !== void 0 ? _h : (_l[name] = 0);
268
+ (_p = (_s = results.unknown[unknownType])[name]) !== null && _p !== void 0 ? _p : (_s[name] = 0);
239
269
  results.unknown[unknownType][name] += fileSize;
240
270
  results.unknown.bytes += fileSize;
241
271
  continue;
242
272
  }
243
273
  // Add language and bytes data to corresponding section
244
274
  const { type } = langData[lang];
245
- (_j = (_m = results.languages.results)[lang]) !== null && _j !== void 0 ? _j : (_m[lang] = { type, bytes: 0, color: langData[lang].color });
275
+ (_q = (_t = results.languages.results)[lang]) !== null && _q !== void 0 ? _q : (_t[lang] = { type, bytes: 0, color: langData[lang].color });
246
276
  if (opts.childLanguages)
247
277
  results.languages.results[lang].parent = langData[lang].group;
248
278
  results.languages.results[lang].bytes += fileSize;
package/dist/types.d.ts CHANGED
@@ -5,11 +5,13 @@ export declare type FilePath = string;
5
5
  export declare type Bytes = Integer;
6
6
  export declare type Integer = number;
7
7
  export interface Options {
8
+ fileContent?: string | string[];
8
9
  ignoredFiles?: string[];
9
10
  ignoredLanguages?: Language[];
10
11
  categories?: Category[];
11
12
  keepVendored?: boolean;
12
13
  keepBinary?: boolean;
14
+ relativePaths?: boolean;
13
15
  childLanguages?: boolean;
14
16
  quick?: boolean;
15
17
  checkIgnored?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linguist-js",
3
- "version": "2.1.3",
3
+ "version": "2.3.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": {
@@ -37,18 +37,18 @@
37
37
  "homepage": "https://github.com/Nixinova/Linguist#readme",
38
38
  "dependencies": {
39
39
  "binary-extensions": "^2.2.0",
40
- "commander": "^8.2.0",
41
- "cross-fetch": "^3.1.4",
40
+ "commander": "^9.0.0",
41
+ "cross-fetch": "^3.1.5",
42
42
  "glob-to-regexp": "~0.4.1",
43
43
  "isbinaryfile": "^4.0.8",
44
44
  "js-yaml": "^4.1.0",
45
45
  "node-cache": "^5.1.2"
46
46
  },
47
47
  "devDependencies": {
48
- "@types/glob-to-regexp": "ts4.4",
49
- "@types/js-yaml": "ts4.4",
50
- "@types/node": "ts4.4",
51
- "deep-object-diff": "^1.1.0",
52
- "typescript": "~4.4.3"
48
+ "@types/glob-to-regexp": "ts4.6",
49
+ "@types/js-yaml": "ts4.6",
50
+ "@types/node": "ts4.6",
51
+ "deep-object-diff": "^1.1.7",
52
+ "typescript": "~4.6.1-rc"
53
53
  }
54
54
  }
package/readme.md CHANGED
@@ -77,6 +77,7 @@ Running Linguist on this folder will return the following JSON:
77
77
  ### Notes
78
78
 
79
79
  - File paths in the output use only forward slashes as delimiters, even on Windows.
80
+ - This tool does not work when offline.
80
81
  - Do not rely on any language classification output from Linguist being unchanged between runs.
81
82
  Language data is fetched each run from the latest classifications of [`github-linguist`](https://github.com/github/linguist).
82
83
  This data is subject to change at any time and may change the results of a run even when using the same version of Linguist.
@@ -99,6 +100,8 @@ const { files, languages, unknown } = linguist(folder, options);
99
100
  Analyse multiple folders using the syntax `"{folder1,folder2,...}"`.
100
101
  - `opts` (optional; object):
101
102
  An object containing analyser options.
103
+ - `fileContent` (string or string array):
104
+ Provides the file content associated with the file name(s) given as `entry` to analyse instead of reading from a folder on disk.
102
105
  - `ignoredFiles` (string array):
103
106
  A list of file path globs to explicitly ignore.
104
107
  - `ignoredLanguages` (string array):
@@ -115,6 +118,8 @@ const { files, languages, unknown } = linguist(folder, options);
115
118
  Whether to keep vendored files (dependencies, etc) (defaults to `false`).
116
119
  - `keepBinary` (boolean):
117
120
  Whether binary files should be included in the output (defaults to `false`).
121
+ - `relativePaths` (boolean):
122
+ Change the absolute file paths in the output to be relative to the current working directory (defaults to `false`).
118
123
  - `checkAttributes` (boolean):
119
124
  Force the checking of `.gitattributes` files (defaults to `true` unless `quick` is set).
120
125
  - `checkIgnored` (boolean):
@@ -155,6 +160,8 @@ linguist --help
155
160
  Whether to include vendored files (auto-generated files, dependencies folder, etc).
156
161
  - `--keepBinary`:
157
162
  Whether binary files should be excluded from the output.
163
+ - `--relativePaths`:
164
+ Change the absolute file paths in the output to be relative to the current working directory.
158
165
  - `--checkAttributes`:
159
166
  Force the checking of `.gitatributes` files (use alongside `--quick` to overwrite).
160
167
  - `--checkIgnored`:
package/dist/test.js DELETED
@@ -1,3 +0,0 @@
1
- const classificator = require('classificator');
2
- const b = classificator();
3
- b.toJson();