diff --git a/package-lock.json b/package-lock.json index f07449e0..a39f0e7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "faker": "^5.5.3", "jimp": "^0.16.1", "js-yaml": "^4.1.0", - "linguist-js": "^1.6.1", + "linguist-js": "^1.7.0", "marked": "^3.0.0", "memory-cache": "^0.2.0", "minimatch": "^3.0.4", @@ -6384,9 +6384,9 @@ } }, "node_modules/linguist-js": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/linguist-js/-/linguist-js-1.6.1.tgz", - "integrity": "sha512-OuJw2QI/B5bZ4RZ4vY2B8C0GCDagxpJZvLjKxoatSEhBtCbjI5pWmHe40i/tnqGfccbNGBzIXWtSd7G9gYv3yA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/linguist-js/-/linguist-js-1.7.0.tgz", + "integrity": "sha512-nxBJBe3Dk8gJwHHNtqzZ9NuHvtIYxb/QjVpxOniJp5cu+vhUJ9a7CBOAiFwgJVQdxwH4ihui/ZFVnnv8WX7wqA==", "dependencies": { "binary-extensions": "^2.2.0", "commander": "^8.1.0", @@ -9041,9 +9041,9 @@ } }, "node_modules/tar": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", - "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.7.tgz", + "integrity": "sha512-PBoRkOJU0X3lejJ8GaRCsobjXTgFofRDSPdSUhRSdlwJfifRlQBwGXitDItdGFu0/h0XDMCkig0RN1iT7DBxhA==", "devOptional": true, "dependencies": { "chownr": "^2.0.0", @@ -14985,9 +14985,9 @@ } }, "linguist-js": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/linguist-js/-/linguist-js-1.6.1.tgz", - "integrity": "sha512-OuJw2QI/B5bZ4RZ4vY2B8C0GCDagxpJZvLjKxoatSEhBtCbjI5pWmHe40i/tnqGfccbNGBzIXWtSd7G9gYv3yA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/linguist-js/-/linguist-js-1.7.0.tgz", + "integrity": "sha512-nxBJBe3Dk8gJwHHNtqzZ9NuHvtIYxb/QjVpxOniJp5cu+vhUJ9a7CBOAiFwgJVQdxwH4ihui/ZFVnnv8WX7wqA==", "requires": { "binary-extensions": "^2.2.0", "commander": "^8.1.0", @@ -17073,9 +17073,9 @@ } }, "tar": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", - "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.7.tgz", + "integrity": "sha512-PBoRkOJU0X3lejJ8GaRCsobjXTgFofRDSPdSUhRSdlwJfifRlQBwGXitDItdGFu0/h0XDMCkig0RN1iT7DBxhA==", "devOptional": true, "requires": { "chownr": "^2.0.0", diff --git a/package.json b/package.json index 7030b8c3..a053af66 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "faker": "^5.5.3", "jimp": "^0.16.1", "js-yaml": "^4.1.0", - "linguist-js": "^1.6.1", + "linguist-js": "^1.7.0", "marked": "^3.0.0", "memory-cache": "^0.2.0", "minimatch": "^3.0.4", diff --git a/source/plugins/languages/README.md b/source/plugins/languages/README.md index 5b3ce717..62df2db2 100644 --- a/source/plugins/languages/README.md +++ b/source/plugins/languages/README.md @@ -60,7 +60,7 @@ For better results, it's advised to add either your surnames and eventually no-r plugin_languages_sections: most-used, recently-used # Display most used and recently used languages stats plugin_languages_indepth: no # Get indepth stats (see documentation before enabling) plugin_languages_categories: programming # Display only languages that match these categories in most-used section - plugin_languages_categories: markup, programming, data # Display only languages that match these categories in recently-used section + plugin_languages_recent_categories: markup, programming, data # Display only languages that match these categories in recently-used section plugin_languages_recent_load: 500 # Load up to 500 events to compute recently used stats plugin_languages_recent_days: 7 # Limit recently used stats to last week commits_authoring: lowlighter@users.noreply.github.com # Surnames or email addresses used to identify your commits diff --git a/source/plugins/languages/analyzers.mjs b/source/plugins/languages/analyzers.mjs index ff727deb..0be1657a 100644 --- a/source/plugins/languages/analyzers.mjs +++ b/source/plugins/languages/analyzers.mjs @@ -4,7 +4,7 @@ import linguist from "linguist-js" export async function indepth({login, data, imports, repositories}, {skipped, categories}) { //Compute repositories stats from fetched repositories - const results = {total:0, lines:{}, stats:{}, commits:0, files:0, missed:0} + const results = {total:0, lines:{}, stats:{}, colors:{}, commits:0, files:0, missed:0} for (const repository of repositories) { //Skip repository if asked if ((skipped.includes(repository.name.toLocaleLowerCase())) || (skipped.includes(`${repository.owner.login}/${repository.name}`.toLocaleLowerCase()))) { @@ -48,7 +48,7 @@ export async function recent({login, data, imports, rest, account}, {skipped = [ //Get user recent activity console.debug(`metrics/compute/${login}/plugins > languages > querying api`) - const commits = [], pages = Math.ceil(load/100), results = {total:0, lines:{}, stats:{}, commits:0, files:0, missed:0, days} + const commits = [], pages = Math.ceil(load/100), results = {total:0, lines:{}, stats:{}, colors:{}, commits:0, files:0, missed:0, days} try { for (let page = 1; page <= pages; page++) { console.debug(`metrics/compute/${login}/plugins > languages > loading page ${page}`) @@ -140,6 +140,7 @@ async function analyze({login, imports, data}, {results, path, categories = ["pr //Gather language data console.debug(`metrics/compute/${login}/plugins > languages > indepth > running linguist`) const {results:files, languages:languageResults} = await linguist(path) + Object.assign(results.colors, Object.fromEntries(Object.entries(languageResults.all).map(([lang, {color}]) => [lang, color]))) //Processing diff const per_page = 1 @@ -212,7 +213,7 @@ if (/languages.analyzers.mjs$/.test(process.argv[1])) { //Prepare call const imports = await import("../../app/metrics/utils.mjs") - const results = {total:0, lines:{}, stats:{}, missed:0} + const results = {total:0, lines:{}, colors:{}, stats:{}, missed:0} console.debug = log => /exited with code null/.test(log) ? console.error(log.replace(/^.*--max-count=(?\d+) --skip=(?\d+).*$/, (_, step, start) => `error: skipped commits ${start} from ${Number(start)+Number(step)}`)) : null //Analyze repository diff --git a/source/plugins/languages/index.mjs b/source/plugins/languages/index.mjs index 58ccfe27..e9ba1a5b 100644 --- a/source/plugins/languages/index.mjs +++ b/source/plugins/languages/index.mjs @@ -38,6 +38,7 @@ export default async function({login, data, imports, q, rest, account}, {enabled //Iterate through user's repositories and retrieve languages data console.debug(`metrics/compute/${login}/plugins > languages > processing ${data.user.repositories.nodes.length} repositories`) const languages = {unique, sections, details, indepth, colors:{}, total:0, stats:{}, "stats.recent":{}} + const customColors = {} for (const repository of data.user.repositories.nodes) { //Skip repository if asked if ((skipped.includes(repository.name.toLocaleLowerCase())) || (skipped.includes(`${repository.owner.login}/${repository.name}`.toLocaleLowerCase()))) { @@ -47,7 +48,10 @@ export default async function({login, data, imports, q, rest, account}, {enabled //Process repository languages for (const {size, node:{color, name}} of Object.values(repository.languages.edges)) { languages.stats[name] = (languages.stats[name] ?? 0) + size - languages.colors[name] = colors[name.toLocaleLowerCase()] ?? color ?? "#ededed" + if (colors[name.toLocaleLowerCase()]) + customColors[name] = colors[name.toLocaleLowerCase()] + if (!languages.colors[name]) + languages.colors[name] = color languages.total += size } } @@ -58,12 +62,15 @@ export default async function({login, data, imports, q, rest, account}, {enabled if ((sections.includes("recently-used"))&&(context.mode === "user")) { console.debug(`metrics/compute/${login}/plugins > languages > using recent analyzer`) languages["stats.recent"] = await recent_analyzer({login, data, imports, rest, account}, {skipped, categories:_recent_categories ?? categories, days:_recent_days, load:_recent_load}) + Object.assign(languages.colors, languages["stats.recent"].colors) } //Indepth mode if (indepth) { console.debug(`metrics/compute/${login}/plugins > languages > switching to indepth mode (this may take some time)`) + const existingColors = languages.colors Object.assign(languages, await indepth_analyzer({login, data, imports, repositories}, {skipped, categories})) + Object.assign(languages.colors, existingColors) console.debug(`metrics/compute/${login}/plugins > languages > indepth analysis missed ${languages.missed} commits`) } } @@ -74,11 +81,14 @@ export default async function({login, data, imports, q, rest, account}, {enabled languages[section] = Object.entries(stats).filter(([name]) => !ignored.includes(name.toLocaleLowerCase())).sort(([_an, a], [_bn, b]) => b - a).slice(0, limit).map(([name, value]) => ({name, value, size:value, color:languages.colors[name], x:0})).filter(({value}) => value / total > threshold) const visible = {total:Object.values(languages[section]).map(({size}) => size).reduce((a, b) => a + b, 0)} for (let i = 0; i < languages[section].length; i++) { + const {name} = languages[section][i] languages[section][i].value /= visible.total languages[section][i].x = (languages[section][i - 1]?.x ?? 0) + (languages[section][i - 1]?.value ?? 0) - languages[section][i].lines = lines[languages[section][i].name] ?? 0 - if ((colors[i]) && (!colors[languages[section][i].name.toLocaleLowerCase()])) + languages[section][i].lines = lines[name] ?? 0 + if ((colors[i]) && (!colors[name.toLocaleLowerCase()])) languages[section][i].color = colors[i] + else + languages[section][i].color = customColors[name] ?? languages.colors[name] ?? "#ededed" } }