Skip to content

Commit bf1453c

Browse files
authored
Add option plugin_languages_details (lowlighter#87)
1 parent 5e57107 commit bf1453c

File tree

8 files changed

+91
-18
lines changed

8 files changed

+91
-18
lines changed

source/app/metrics/utils.mjs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@
3636
return `${(n/v).toFixed(2).substr(0, 4).replace(/[.]0*$/, "")} ${u}B`
3737
return `${n} byte${n > 1 ? "s" : ""}`
3838
}
39+
format.bytes = bytes
40+
41+
/** Percentage formatter */
42+
export function percentage(n, {rescale = true} = {}) {
43+
return `${(n*(rescale ? 100 : 1)).toFixed(2)
44+
.replace(/(?<=[.])([1-9]*)(0+)$/, (m, a, b) => a)
45+
.replace(/[.]$/, "")}%`
46+
}
47+
format.percentage = percentage
3948

4049
/** Array shuffler */
4150
export function shuffle(array) {

source/plugins/base/index.mjs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
return (postprocess.skip({login, data}), {})
1515

1616
//Base parts (legacy handling for web instance)
17-
const defaulted = ("base" in q) ? !!q.base : true
17+
const defaulted = ("base" in q) ? legacy.converter(q.base) ?? true : true
1818
for (const part of conf.settings.plugins.base.parts)
19-
data.base[part] = `base.${part}` in q ? !!q[ `base.${part}`] : defaulted
19+
data.base[part] = `base.${part}` in q ? legacy.converter(q[ `base.${part}`]) : defaulted
2020

2121
//Iterate through account types
2222
for (const account of ["user", "organization"]) {
@@ -108,4 +108,16 @@
108108
packages:{totalCount:0},
109109
})
110110
}
111+
}
112+
113+
//Legacy functions
114+
const legacy = {
115+
converter(value) {
116+
if (/^(?:[Tt]rue|[Oo]n|[Yy]es|1)$/.test(value))
117+
return true
118+
if (/^(?:[Ff]alse|[Oo]ff|[Nn]o|0)$/.test(value))
119+
return false
120+
if (Number.isFinite(Number(value)))
121+
return !!(Number(value))
122+
}
111123
}

source/plugins/languages/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ It is also possible to use a predefined set of colors from [colorsets.json](colo
2626
plugin_languages_ignored: html, css # List of languages to ignore
2727
plugin_languages_skipped: my-test-repo # List of repositories to skip
2828
plugin_languages_colors: "0:orange, javascript:#ff0000, ..." # Make most used languages orange and JavaScript red
29+
plugin_languages_details: bytes-size, percentage # Additionally display total bytes size and percentage
2930
```

source/plugins/languages/index.mjs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
return null
88

99
//Load inputs
10-
let {ignored, skipped, colors} = imports.metadata.plugins.languages.inputs({data, account, q})
10+
let {ignored, skipped, colors, details} = imports.metadata.plugins.languages.inputs({data, account, q})
1111

1212
//Custom colors
1313
const colorsets = JSON.parse(`${await imports.fs.readFile(`${imports.__module(import.meta.url)}/colorsets.json`)}`)
@@ -18,7 +18,7 @@
1818

1919
//Iterate through user's repositories and retrieve languages data
2020
console.debug(`metrics/compute/${login}/plugins > languages > processing ${data.user.repositories.nodes.length} repositories`)
21-
const languages = {colors:{}, total:0, stats:{}}
21+
const languages = {details, colors:{}, total:0, stats:{}}
2222
for (const repository of data.user.repositories.nodes) {
2323
//Skip repository if asked
2424
if (skipped.includes(repository.name.toLocaleLowerCase())) {
@@ -41,9 +41,10 @@
4141

4242
//Compute languages stats
4343
console.debug(`metrics/compute/${login}/plugins > languages > computing stats`)
44-
Object.keys(languages.stats).map(name => languages.stats[name] /= languages.total)
45-
languages.favorites = Object.entries(languages.stats).sort(([an, a], [bn, b]) => b - a).slice(0, 8).map(([name, value]) => ({name, value, color:languages.colors[name], x:0}))
44+
languages.favorites = Object.entries(languages.stats).sort(([an, a], [bn, b]) => b - a).slice(0, 8).map(([name, value]) => ({name, value, size:value, color:languages.colors[name], x:0}))
45+
const visible = {total:Object.values(languages.favorites).map(({size}) => size).reduce((a, b) => a + b, 0)}
4646
for (let i = 0; i < languages.favorites.length; i++) {
47+
languages.favorites[i].value /= visible.total
4748
languages.favorites[i].x = (languages.favorites[i-1]?.x ?? 0) + (languages.favorites[i-1]?.value ?? 0)
4849
if ((colors[i])&&(!colors[languages.favorites[i].name.toLocaleLowerCase()]))
4950
languages.favorites[i].color = colors[i]

source/plugins/languages/metadata.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ inputs:
2626
format: comma-separated
2727
default: ""
2828

29-
# Overrides
29+
# Overrides default languages colors
3030
# Use `${n}:${color}` to change the color of the n-th most used language (e.g. "0:red" to make your most used language red)
3131
# Use `${language}:${color}` to change the color of named language (e.g. "javascript:red" to make JavaScript language red, language case is ignored)
3232
# Use a value from `colorsets.json` to use a predefined set of colors
@@ -38,3 +38,13 @@ inputs:
3838
- comma-separated
3939
- /((?<index>[0-9])|(?<language>[-+a-z0-9#])):(?<color>#?[-a-z0-9]+)/
4040
default: github
41+
42+
# Languages additional details
43+
plugin_languages_details:
44+
description:
45+
type: array
46+
format: comma-separated
47+
values:
48+
- bytes-size # Languages total size written in bytes
49+
- percentage # Languages proportions in %
50+
default: ""

source/templates/classic/partials/languages.ejs

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<% if (plugins.languages) { %>
22
<section class="column">
3-
<h3>Most used languages</h3>
3+
<h2 class="field">
4+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.5 2.75a.25.25 0 01.25-.25h12.5a.25.25 0 01.25.25v8.5a.25.25 0 01-.25.25h-6.5a.75.75 0 00-.53.22L4.5 14.44v-2.19a.75.75 0 00-.75-.75h-2a.25.25 0 01-.25-.25v-8.5zM1.75 1A1.75 1.75 0 000 2.75v8.5C0 12.216.784 13 1.75 13H3v1.543a1.457 1.457 0 002.487 1.03L8.061 13h6.189A1.75 1.75 0 0016 11.25v-8.5A1.75 1.75 0 0014.25 1H1.75zm5.03 3.47a.75.75 0 010 1.06L5.31 7l1.47 1.47a.75.75 0 01-1.06 1.06l-2-2a.75.75 0 010-1.06l2-2a.75.75 0 011.06 0zm2.44 0a.75.75 0 000 1.06L10.69 7 9.22 8.47a.75.75 0 001.06 1.06l2-2a.75.75 0 000-1.06l-2-2a.75.75 0 00-1.06 0z"></path></svg>
5+
Most used languages
6+
</h2>
47
<% if (plugins.languages.error) { %>
58
<section>
69
<div class="field error">
@@ -18,14 +21,35 @@
1821
<rect mask="url(#languages-bar)" x="<%= x*460 %>" y="0" width="<%= value*460 %>" height="8" fill="<%= color %>"/>
1922
<% } %>
2023
</svg>
21-
<div class="field center horizontal-wrap fill-width">
22-
<% for (const {name, value, color} of plugins.languages.favorites) { %>
23-
<div class="field center no-wrap language">
24-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="<%= color %>" fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8z"></path></svg>
25-
<%= name %>
26-
</div>
27-
<% } %>
28-
</div>
24+
<% if (plugins.languages.details?.length) { %>
25+
<div class="row fill-width">
26+
<% for (const row of [0, 1]) { %>
27+
<section>
28+
<% for (const {name, value, color, size} of plugins.languages.favorites.filter((_, i) => i%2 === row)) { %>
29+
<div class="field language details">
30+
<div class="field">
31+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="<%= color %>" fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8z"></path></svg>
32+
<%= name %>
33+
</div>
34+
<small>
35+
<% if (plugins.languages.details.includes("bytes-size")) { %> <div><%= f.bytes(size) %></div><% } %>
36+
<% if (plugins.languages.details.includes("percentage")) { %> <div><%= f.percentage(value) %></div><% } %>
37+
</small>
38+
</div>
39+
<% } %>
40+
</section>
41+
<% } %>
42+
</div>
43+
<% } else { %>
44+
<div class="field center horizontal-wrap fill-width">
45+
<% for (const {name, value, color} of plugins.languages.favorites) { %>
46+
<div class="field center no-wrap language">
47+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="<%= color %>" fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8z"></path></svg>
48+
<%= name %>
49+
</div>
50+
<% } %>
51+
</div>
52+
<% } %>
2953
<% } %>
3054
</section>
3155
<% } %>

source/templates/classic/style.css

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,20 @@
114114
flex-grow: 0;
115115
}
116116

117-
.field.language small {
118-
margin-left: 4px;
117+
.field.language.details {
118+
display: flex;
119+
justify-content: space-between;
120+
}
121+
122+
.field.language.details small {
123+
display: flex;
124+
justify-content: space-between;
119125
color: #666666;
126+
text-align: right;
127+
}
128+
129+
.field.language.details > *, .field.language.details small > * {
130+
flex: 1 1 0;
120131
}
121132

122133
/* Labels */

tests/testscases.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,16 @@
105105
plugin_languages:true,
106106
plugin_languages_colors:"complementary",
107107
}],
108+
["Language plugin (with details)", {
109+
plugin_languages:true,
110+
plugin_languages_details:"percentage",
111+
}],
108112
["Language plugin (complete)", {
109113
plugin_languages:true,
110114
plugin_languages_ignored:"html, css, dockerfile",
111115
plugin_languages_skipped:"metrics",
112116
plugin_languages_colors:"rainbow",
117+
plugin_languages_details:"bytes-size, percentage",
113118
}],
114119
["Follow-up plugin (default)", {
115120
plugin_followup:true,

0 commit comments

Comments
 (0)