linguist-js
Advanced tools
Comparing version 2.4.2 to 2.5.0
@@ -22,2 +22,3 @@ "use strict"; | ||
.option('-q|--quick [bool]', 'Skip complex language analysis (alias for -{A|I|H|S}=false)', false) | ||
.option('-o|--offline [bool]', 'Use packaged data files instead of fetching latest from GitHub', false) | ||
.option('-V|--keepVendored [bool]', 'Prevent skipping over vendored/generated files', false) | ||
@@ -24,0 +25,0 @@ .option('-B|--keepBinary [bool]', 'Prevent skipping over binary files', false) |
@@ -6,7 +6,8 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const promises_1 = __importDefault(require("fs/promises")); | ||
const path_1 = __importDefault(require("path")); | ||
const cross_fetch_1 = __importDefault(require("cross-fetch")); | ||
const node_cache_1 = __importDefault(require("node-cache")); | ||
const cache = new node_cache_1.default({}); | ||
/** Load a data file from github-linguist. */ | ||
async function loadFile(file) { | ||
async function loadWebFile(file) { | ||
// Return cache if it exists | ||
@@ -22,2 +23,10 @@ const cachedContent = cache.get(file); | ||
} | ||
async function loadLocalFile(file) { | ||
const filePath = path_1.default.resolve(__dirname, '../../ext', file); | ||
return promises_1.default.readFile(filePath).then(buffer => buffer.toString()); | ||
} | ||
/** Load a data file from github-linguist. */ | ||
async function loadFile(file, offline = false) { | ||
return offline ? loadLocalFile(file) : loadWebFile(file); | ||
} | ||
exports.default = loadFile; |
@@ -23,7 +23,7 @@ "use strict"; | ||
// Load data from github-linguist web repo | ||
const langData = await (0, load_data_1.default)('languages.yml').then(js_yaml_1.default.load); | ||
const vendorData = await (0, load_data_1.default)('vendor.yml').then(js_yaml_1.default.load); | ||
const docData = await (0, load_data_1.default)('documentation.yml').then(js_yaml_1.default.load); | ||
const heuristicsData = await (0, load_data_1.default)('heuristics.yml').then(js_yaml_1.default.load); | ||
const generatedData = await (0, load_data_1.default)('generated.rb').then(text => { var _a; return (_a = text.match(/(?<=name\.match\(\/).+?(?=(?<!\\)\/)/gm)) !== null && _a !== void 0 ? _a : []; }); | ||
const langData = await (0, load_data_1.default)('languages.yml', opts.offline).then(js_yaml_1.default.load); | ||
const vendorData = await (0, load_data_1.default)('vendor.yml', opts.offline).then(js_yaml_1.default.load); | ||
const docData = await (0, load_data_1.default)('documentation.yml', opts.offline).then(js_yaml_1.default.load); | ||
const heuristicsData = await (0, load_data_1.default)('heuristics.yml', opts.offline).then(js_yaml_1.default.load); | ||
const generatedData = await (0, load_data_1.default)('generated.rb', opts.offline).then(text => { var _a; return (_a = text.match(/(?<=name\.match\(\/).+?(?=(?<!\\)\/)/gm)) !== null && _a !== void 0 ? _a : []; }); | ||
const vendorPaths = [...vendorData, ...docData, ...generatedData]; | ||
@@ -90,4 +90,5 @@ // Setup main variables | ||
// Skip if folder is marked in gitattributes | ||
if (relPath(folder) && gitignores.ignores(relPath(folder))) | ||
if (relPath(folder) && gitignores.ignores(relPath(folder))) { | ||
continue; | ||
} | ||
// Parse gitignores | ||
@@ -106,6 +107,8 @@ const ignoresFile = path_1.default.join(folder, '.gitignore'); | ||
for (const [_line, path, type] of contentTypeMatches) { | ||
if (['text', '-binary'].includes(type)) | ||
if (['text', '-binary'].includes(type)) { | ||
customText.add(path); | ||
if (['-text', 'binary'].includes(type)) | ||
} | ||
if (['-text', 'binary'].includes(type)) { | ||
customBinary.add(path); | ||
} | ||
} | ||
@@ -123,4 +126,5 @@ // Custom vendor options | ||
const overrideLang = Object.entries(langData).find(entry => { var _a; return (_a = entry[1].aliases) === null || _a === void 0 ? void 0 : _a.includes(forcedLang.toLowerCase()); }); | ||
if (overrideLang) | ||
if (overrideLang) { | ||
forcedLang = overrideLang[0]; | ||
} | ||
} | ||
@@ -161,7 +165,7 @@ const fullPath = relPath(folder) + '/' + path; | ||
} | ||
else { | ||
if (!fs_1.default.existsSync(file) || fs_1.default.lstatSync(file).isDirectory()) | ||
continue; | ||
else if (fs_1.default.existsSync(file) && !fs_1.default.lstatSync(file).isDirectory()) { | ||
firstLine = await (0, read_file_1.default)(file, true).catch(() => null); | ||
} | ||
else | ||
continue; | ||
// Skip if file is unreadable | ||
@@ -183,6 +187,7 @@ if (firstLine === null) | ||
// Add language | ||
if (opts.checkShebang && matchesInterpretor) | ||
const interpretorCheck = opts.checkShebang && matchesInterpretor; | ||
const modelineCheck = opts.checkModeline && (matchesLang || matchesAlias); | ||
if (interpretorCheck || modelineCheck) { | ||
matches.push(lang); | ||
if (opts.checkModeline && (matchesLang || matchesAlias)) | ||
matches.push(lang); | ||
} | ||
} | ||
@@ -222,8 +227,10 @@ if (matches.length) { | ||
const matchesExt = (_j = langData[lang].extensions) === null || _j === void 0 ? void 0 : _j.some(ext => file.toLowerCase().endsWith(ext.toLowerCase())); | ||
if (matchesExt) | ||
if (matchesExt) { | ||
addResult(file, lang); | ||
} | ||
} | ||
// Fallback to null if no language matches | ||
if (!fileAssociations[file]) | ||
if (!fileAssociations[file]) { | ||
addResult(file, null); | ||
} | ||
} | ||
@@ -290,12 +297,15 @@ // Narrow down file associations to the best fit | ||
for (const [file, lang] of Object.entries(results.files.results)) { | ||
if (!hiddenCategories.some(cat => { var _a; return lang && ((_a = langData[lang]) === null || _a === void 0 ? void 0 : _a.type) === cat; })) | ||
if (!hiddenCategories.some(cat => { var _a; return lang && ((_a = langData[lang]) === null || _a === void 0 ? void 0 : _a.type) === cat; })) { | ||
continue; | ||
} | ||
delete results.files.results[file]; | ||
if (lang) | ||
if (lang) { | ||
delete results.languages.results[lang]; | ||
} | ||
} | ||
for (const category of hiddenCategories) { | ||
for (const [lang, { type }] of Object.entries(results.languages.results)) { | ||
if (type === category) | ||
if (type === category) { | ||
delete results.languages.results[lang]; | ||
} | ||
} | ||
@@ -309,4 +319,5 @@ } | ||
let relPath = path_1.default.relative(process.cwd(), file).replace(/\\/g, '/'); | ||
if (!relPath.startsWith('../')) | ||
if (!relPath.startsWith('../')) { | ||
relPath = './' + relPath; | ||
} | ||
newMap[relPath] = lang; | ||
@@ -335,4 +346,5 @@ } | ||
(_s = (_v = results.languages.results)[lang]) !== null && _s !== void 0 ? _s : (_v[lang] = { type, bytes: 0, color: langData[lang].color }); | ||
if (opts.childLanguages) | ||
if (opts.childLanguages) { | ||
results.languages.results[lang].parent = langData[lang].group; | ||
} | ||
results.languages.results[lang].bytes += fileSize; | ||
@@ -339,0 +351,0 @@ results.languages.bytes += fileSize; |
@@ -17,2 +17,3 @@ export declare type LanguageResult = string | null; | ||
quick?: boolean; | ||
offline?: boolean; | ||
checkIgnored?: boolean; | ||
@@ -19,0 +20,0 @@ checkAttributes?: boolean; |
{ | ||
"name": "linguist-js", | ||
"version": "2.4.2", | ||
"version": "2.5.0", | ||
"description": "Analyse languages used in a folder. Powered by GitHub Linguist, although it doesn't need to be installed.", | ||
"main": "dist/index.js", | ||
"bin": { | ||
"linguist-js": "bin/index.js", | ||
"linguist": "bin/index.js" | ||
@@ -13,3 +14,4 @@ }, | ||
"scripts": { | ||
"prepare": "npm test && npm run perf", | ||
"download-files": "npx tsx build/download-files", | ||
"prepare": "npm run download-files && npm test && npm run perf", | ||
"perf": "tsc && node test/perf", | ||
@@ -21,3 +23,4 @@ "test": "tsc && node test/folder && echo --- && node test/unit" | ||
"dist/**/*.js", | ||
"dist/*.d.ts" | ||
"dist/*.d.ts", | ||
"ext/" | ||
], | ||
@@ -42,3 +45,3 @@ "repository": { | ||
"binary-extensions": "^2.2.0", | ||
"commander": "^9.1.0", | ||
"commander": "^9.2.0", | ||
"common-path-prefix": "^3.0.0", | ||
@@ -56,4 +59,4 @@ "cross-fetch": "^3.1.5", | ||
"deep-object-diff": "^1.1.7", | ||
"typescript": "~4.6.2" | ||
"typescript": "~4.6.4" | ||
} | ||
} |
@@ -116,3 +116,5 @@ [![Latest version](https://img.shields.io/github/v/release/Nixinova/Linguist?label=latest%20version&style=flat-square)](https://github.com/Nixinova/Linguist/releases) | ||
Alias for `checkAttributes:false, checkIgnored:false, checkHeuristics:false, checkShebang:false, checkModeline:false`. | ||
- `keepVendored` (boolean): | ||
- `offline` (boolean): | ||
Whether to use pre-packaged metadata files instead of fetching them from GitHub at runtime (defaults to `false`). | ||
- `keepVendored` (boolean): | ||
Whether to keep vendored files (dependencies, etc) (defaults to `false`). | ||
@@ -164,2 +166,4 @@ Does nothing when `fileContent` is set. | ||
Alias for `--checkAttributes=false --checkIgnored=false --checkHeuristics=false --checkShebang=false --checkModeline=false`. | ||
- `--offline`: | ||
Use pre-packaged metadata files instead of fetching them from GitHub at runtime. | ||
- `--keepVendored`: | ||
@@ -166,0 +170,0 @@ Whether to include vendored files (auto-generated files, dependencies folder, etc). |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
206539
21
697
187
4
Updatedcommander@^9.2.0