From ed0da41973f442403dfb7d0a7bda701f37d107a3 Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Tue, 18 May 2021 22:31:53 +0200 Subject: [PATCH] Add `config_display` option to support `regular` and `large` renders (#310) --- source/app/metrics/index.mjs | 2 +- source/app/web/statics/app.placeholder.js | 4 +- source/plugins/contributors/index.mjs | 2 +- source/plugins/core/README.md | 15 ++ source/plugins/core/index.mjs | 5 +- source/plugins/core/metadata.yml | 9 + source/plugins/licenses/index.mjs | 2 +- source/plugins/screenshot/index.mjs | 2 +- source/plugins/skyline/index.mjs | 2 +- source/plugins/stargazers/index.mjs | 2 +- source/plugins/stock/index.mjs | 2 +- source/templates/classic/image.svg | 2 +- .../classic/partials/achievements.ejs | 4 +- source/templates/classic/partials/anilist.ejs | 104 +++++------ .../partials/base.activity+community.ejs | 2 +- .../classic/partials/base.repositories.ejs | 122 +++++++------ .../templates/classic/partials/followup.ejs | 2 +- source/templates/classic/partials/gists.ejs | 4 +- source/templates/classic/partials/habits.ejs | 4 +- .../templates/classic/partials/languages.ejs | 16 +- .../templates/classic/partials/pagespeed.ejs | 83 ++++++--- source/templates/classic/partials/posts.ejs | 46 ++--- .../templates/classic/partials/projects.ejs | 12 +- .../classic/partials/stackoverflow.ejs | 170 +++++++++--------- source/templates/classic/partials/stars.ejs | 4 +- source/templates/classic/partials/support.ejs | 6 +- source/templates/classic/partials/tweets.ejs | 2 +- .../templates/classic/partials/wakatime.ejs | 10 +- source/templates/classic/style.css | 58 +++++- source/templates/repository/image.svg | 2 +- .../repository/partials/activity.ejs | 78 +++++--- .../repository/partials/followup.ejs | 81 +++++---- .../repository/partials/languages.ejs | 16 +- .../repository/partials/licenses.ejs | 18 +- .../repository/partials/pagespeed.ejs | 83 ++++++--- .../repository/partials/projects.ejs | 12 +- 36 files changed, 586 insertions(+), 402 deletions(-) diff --git a/source/app/metrics/index.mjs b/source/app/metrics/index.mjs index a5e59bb3..ea26a3e4 100644 --- a/source/app/metrics/index.mjs +++ b/source/app/metrics/index.mjs @@ -26,7 +26,7 @@ export default async function metrics({login, q}, {graphql, rest, plugins, conf, //Initialization const pending = [] const {queries} = conf - const data = {animated:true, base:{}, config:{}, errors:[], plugins:{}, computed:{}} + const data = {animated:true, large:false, base:{}, config:{}, errors:[], plugins:{}, computed:{}} const imports = { plugins:Plugins, templates:Templates, diff --git a/source/app/web/statics/app.placeholder.js b/source/app/web/statics/app.placeholder.js index bf2034dc..bc302849 100644 --- a/source/app/web/statics/app.placeholder.js +++ b/source/app/web/statics/app.placeholder.js @@ -51,9 +51,11 @@ return await ejs.render(partial, data, { async: true, rmWhitespace: true }) }, //Meta-data - meta: { version: set.version, author: "lowlighter" }, + meta: { version: set.version, author: "lowlighter", generated:new Date().toGMTString().replace(/GMT$/g, "").trim() }, //Animated animated: false, + //Display size + large: set.config.display === "large", //Config config: set.config, //Base elements diff --git a/source/plugins/contributors/index.mjs b/source/plugins/contributors/index.mjs index 3937fd62..390dd932 100644 --- a/source/plugins/contributors/index.mjs +++ b/source/plugins/contributors/index.mjs @@ -33,7 +33,7 @@ export default async function({login, q, imports, data, rest, graphql, queries, console.debug(`metrics/compute/${login}/plugins > contributors > no more page to load`) break } - commits.push(...loaded) + commits.push(...loaded.filter(commit => commit?.author?.login)) } catch (error) { if (/Git Repository is empty/.test(error)) diff --git a/source/plugins/core/README.md b/source/plugins/core/README.md index 1ece8b7e..d74b7326 100644 --- a/source/plugins/core/README.md +++ b/source/plugins/core/README.md @@ -140,6 +140,21 @@ It may increase filesize since it replace unicode characters by SVG images. config_twemoji: yes ``` +### â†”ī¸ Controlling display size + +Some templates like `classic` and `repositories` support different output display size: +- `regular` (default) will render a medium-sized image, which is suitable for both desktop and mobile displays and is preferable when using data-intensive metrics (since text may be scaled down on small devices) +- `large` will render a large-sized image, which may be more suitable for some plugins (like displaying topics icons, repository contributors, etc.) + +#### â„šī¸ Examples workflows + +```yaml +- uses: lowlighter/metrics@latest + with: + # ... other options + config_display: large +``` + ### đŸŽžī¸ SVG CSS Animations As rendered metrics use HTML and CSS, some templates have animations. diff --git a/source/plugins/core/index.mjs b/source/plugins/core/index.mjs index 71bf2c98..05db6c27 100644 --- a/source/plugins/core/index.mjs +++ b/source/plugins/core/index.mjs @@ -6,7 +6,7 @@ //Setup export default async function({login, q}, {conf, data, rest, graphql, plugins, queries, account, convert, template}, {pending, imports}) { //Load inputs - const {"config.animations":animations, "config.timezone":_timezone, "debug.flags":dflags} = imports.metadata.plugins.core.inputs({data, account, q}) + const {"config.animations":animations, "config.display":display, "config.timezone":_timezone, "debug.flags":dflags} = imports.metadata.plugins.core.inputs({data, account, q}) imports.metadata.templates[template].check({q, account, format:convert}) //Init @@ -29,6 +29,9 @@ export default async function({login, q}, {conf, data, rest, graphql, plugins, q } } + //Display + data.large = display === "large" + //Animations data.animated = animations console.debug(`metrics/compute/${login} > animations ${data.animated ? "enabled" : "disabled"}`) diff --git a/source/plugins/core/metadata.yml b/source/plugins/core/metadata.yml index 45751754..20d9045d 100644 --- a/source/plugins/core/metadata.yml +++ b/source/plugins/core/metadata.yml @@ -167,6 +167,15 @@ inputs: type: boolean default: yes + # Render display width + config_display: + description: Render display width + type: string + default: regular + values: + - regular # 480px width + - large # 960px width (may not be supported by all templates) + # Enable SVG CSS animations config_animations: description: SVG CSS animations diff --git a/source/plugins/licenses/index.mjs b/source/plugins/licenses/index.mjs index b41e95e1..4d2261b4 100644 --- a/source/plugins/licenses/index.mjs +++ b/source/plugins/licenses/index.mjs @@ -57,7 +57,7 @@ export default async function({login, q, imports, data, graphql, queries, accoun //Spawn licensed process console.debug(`metrics/compute/${login}/plugins > licenses > running licensed`) JSON.parse(await imports.run("licensed list --format=json --licenses", {cwd:path})).apps - .map(({sources}) => sources?.flatMap(source => source.dependencies.map(({dependency, license}) => { + .map(({sources}) => sources?.flatMap(source => source.dependencies?.map(({dependency, license}) => { used[license] = (used[license] ?? 0) + 1 result.dependencies.push(dependency) result.known += (license in licenses) diff --git a/source/plugins/screenshot/index.mjs b/source/plugins/screenshot/index.mjs index 3279ec26..ef19a733 100644 --- a/source/plugins/screenshot/index.mjs +++ b/source/plugins/screenshot/index.mjs @@ -28,7 +28,7 @@ export default async function({login, q, imports, data, account}, {enabled = fal }, selector) console.debug(`metrics/compute/${login}/plugins > screenshot > coordinates ${JSON.stringify(clip)}`) const [buffer] = await imports.record({page, ...clip, frames:1, background}) - const screenshot = await (await imports.jimp.read(Buffer.from(buffer.split(",").pop(), "base64"))).resize(Math.min(454, clip.width), imports.jimp.AUTO) + const screenshot = await (await imports.jimp.read(Buffer.from(buffer.split(",").pop(), "base64"))).resize(Math.min(454 * (1 + data.large), clip.width), imports.jimp.AUTO) await browser.close() //Results diff --git a/source/plugins/skyline/index.mjs b/source/plugins/skyline/index.mjs index 8c886572..48309fae 100644 --- a/source/plugins/skyline/index.mjs +++ b/source/plugins/skyline/index.mjs @@ -12,7 +12,7 @@ export default async function({login, q, imports, data, account}, {enabled = fal year = new Date().getFullYear() console.debug(`metrics/compute/${login}/plugins > skyline > year set to ${year}`) } - const width = 454 + const width = 454 * (1 + data.large) const height = 284 //Start puppeteer and navigate to skyline.github.com diff --git a/source/plugins/stargazers/index.mjs b/source/plugins/stargazers/index.mjs index decba950..d2ad2e85 100644 --- a/source/plugins/stargazers/index.mjs +++ b/source/plugins/stargazers/index.mjs @@ -31,7 +31,7 @@ export default async function({login, graphql, data, imports, q, queries, accoun console.debug(`metrics/compute/${login}/plugins > stargazers > loaded ${dates.length} stargazers in total`) //Compute stargazers increments - const days = 14 + const days = 14 * (1 + data.large/2) const increments = {dates:Object.fromEntries([...new Array(days).fill(null).map((_, i) => [new Date(Date.now() - i * 24 * 60 * 60 * 1000).toISOString().slice(0, 10), 0]).reverse()]), max:NaN, min:NaN} dates .map(date => date.toISOString().slice(0, 10)) diff --git a/source/plugins/stock/index.mjs b/source/plugins/stock/index.mjs index a3812120..b417f9a4 100644 --- a/source/plugins/stock/index.mjs +++ b/source/plugins/stock/index.mjs @@ -32,7 +32,7 @@ export default async function({login, q, imports, data, account}, {enabled = fal //Generating chart console.debug(`metrics/compute/${login}/plugins > stock > generating chart`) const chart = await imports.chartist("line", { - width:480, + width:480 * (1 + data.large), height:160, showPoint:false, axisX:{showGrid:false, labelInterpolationFnc:(value, index) => index % Math.floor(close.length / 4) === 0 ? value : null}, diff --git a/source/templates/classic/image.svg b/source/templates/classic/image.svg index aee792fe..a4fd2b1e 100644 --- a/source/templates/classic/image.svg +++ b/source/templates/classic/image.svg @@ -1,4 +1,4 @@ - + diff --git a/source/templates/classic/partials/achievements.ejs b/source/templates/classic/partials/achievements.ejs index ad35f968..09b72f14 100644 --- a/source/templates/classic/partials/achievements.ejs +++ b/source/templates/classic/partials/achievements.ejs @@ -5,7 +5,7 @@ Achievements
-
+
<% if (plugins.achievements.error) { %>
@@ -13,7 +13,7 @@
<% } else { %> <% for (const {title, text, icon, rank, leaderboard = null, progress = 0, unlock = null} of plugins.achievements.list) { %> -
"> +
largeable-width-half">
diff --git a/source/templates/classic/partials/anilist.ejs b/source/templates/classic/partials/anilist.ejs index 429732ab..4b31f937 100644 --- a/source/templates/classic/partials/anilist.ejs +++ b/source/templates/classic/partials/anilist.ejs @@ -46,64 +46,66 @@ <%= {favorites:`Favorites ${media}s`, watching:"Currently watching", reading:"Currently reading"}[list] %> - <% for (const {name, type, description, release, status, genres, scores, progress, released, artwork} of plugins.anilist.lists[media][list]) { %> -
- -
-
- <%= name %> -
-
-
- <% if (type === "ANIME") { %> - - Anime - <% } else if (type === "MANGA") { %> - - Manga - <% } else { %> - - Other - <% } %> -
-
- - <%= status === "NOT_YET_RELEASED" ? "Not yet released" : `${release} ${{FINISHED:"", RELEASING:"(releasing)", NOT_YET_RELEASED:"(unreleased)", CANCELLED:"(cancelled)", HIATUS:"(hiatus)"}[status]}` %> -
- <% if (scores.community) { %> -
- - <%= scores.community %>% +
+ <% for (const {name, type, description, release, status, genres, scores, progress, released, artwork} of plugins.anilist.lists[media][list]) { %> +
+ +
+
+ <%= name %>
- <% } %> - <% if (Number.isFinite(progress)) { %> -
- <% if (progress === released) { %> - - <% } else { %> - +
+
+ <% if (type === "ANIME") { %> + + Anime + <% } else if (type === "MANGA") { %> + + Manga + <% } else { %> + + Other + <% } %> +
+
+ + <%= status === "NOT_YET_RELEASED" ? "Not yet released" : `${release} ${{FINISHED:"", RELEASING:"(releasing)", NOT_YET_RELEASED:"(unreleased)", CANCELLED:"(cancelled)", HIATUS:"(hiatus)"}[status]}` %> +
+ <% if (scores.community) { %> +
+ + <%= scores.community %>% +
+ <% } %> + <% if (Number.isFinite(progress)) { %> +
+ <% if (progress === released) { %> + + <% } else { %> + + <% } %> + <%= type === "ANIME" ? "Episode" : type === "MANGA" ? "Chapter" : "" %> <%= progress %><%= released ? `/${released}` : "" %> +
+ <% } else { %> +
+ + <%= progress %><%= released %> <%= type === "ANIME" ? `episode${s(released)}` : type === "MANGA" ? `chapter${s(released)}` : "" %> +
<% } %> - <%= type === "ANIME" ? "Episode" : type === "MANGA" ? "Chapter" : "" %> <%= progress %><%= released ? `/${released}` : "" %>
- <% } else { %> -
- - <%= progress %><%= released %> <%= type === "ANIME" ? `episode${s(released)}` : type === "MANGA" ? `chapter${s(released)}` : "" %> +
+
+ + <%= genres.join(", ") %> +
+
+
+ <%= description %>
- <% } %> -
-
-
- - <%= genres.join(", ") %>
-
- <%= description %> -
-
+ <% } %>
- <% } %>
<% } %> <% } %> diff --git a/source/templates/classic/partials/base.activity+community.ejs b/source/templates/classic/partials/base.activity+community.ejs index 98554855..ace046c8 100644 --- a/source/templates/classic/partials/base.activity+community.ejs +++ b/source/templates/classic/partials/base.activity+community.ejs @@ -1,5 +1,5 @@ <% if ((account === "user")&&((base.activity)||(base.community))) { %> -
+
<% if (base.activity) { %>
diff --git a/source/templates/classic/partials/base.repositories.ejs b/source/templates/classic/partials/base.repositories.ejs index db9ee1c4..93798ec1 100644 --- a/source/templates/classic/partials/base.repositories.ejs +++ b/source/templates/classic/partials/base.repositories.ejs @@ -1,69 +1,73 @@ <% if (base.repositories) { %> -
-

- - <%= user.repositories.totalCount %> Repositor<%= s(user.repositories.totalCount, "y") %> <%= computed.repositories.forked ? `(including ${computed.repositories.forked} fork${s(computed.repositories.forked)})` : "" %> -

+
-
- - <% if (computed.licenses.favorite.length) { %> - Prefers <%= computed.licenses.favorite %> license - <% } else { %> - No license preference - <% } %> -
-
- - <%= computed.repositories.releases %> Release<%= s(computed.repositories.releases) %> -
-
- - <%= user.packages.totalCount %> Package<%= s(user.packages.totalCount) %> -
-
- - <%= computed.diskUsage %> used -
- <% if (plugins.lines) { %> -
- - <% if (plugins.lines.error) { %> - <%= plugins.lines.error.message %> +

+ + <%= user.repositories.totalCount %> Repositor<%= s(user.repositories.totalCount, "y") %> <%= computed.repositories.forked ? `(including ${computed.repositories.forked} fork${s(computed.repositories.forked)})` : "" %> +

+
+
+
+ + <% if (computed.licenses.favorite.length) { %> + Prefers <%= computed.licenses.favorite %> license <% } else { %> - <%= f(plugins.lines.added) %> added, <%= f(plugins.lines.deleted) %> removed + No license preference <% } %>
- <% } %> -
-
-
- - <%= user.sponsorshipsAsMaintainer.totalCount %> Sponsor<%= s(user.sponsorshipsAsMaintainer.totalCount) %> -
-
- - <%= computed.repositories.stargazers %> Stargazer<%= s(computed.repositories.stargazers) %> -
-
- - <%= computed.repositories.forks %> Forker<%= s(computed.repositories.forks) %> -
-
- - <%= computed.repositories.watchers %> Watcher<%= s(computed.repositories.watchers) %> -
- <% if (plugins.traffic) { %> -
- - <% if (plugins.traffic.error) { %> - <%= plugins.traffic.error.message %> - <% } else { %> - <%= f(plugins.traffic.views.count) %> view<%= s(plugins.traffic.views.count) %> in last two weeks - <% } %> +
+ + <%= computed.repositories.releases %> Release<%= s(computed.repositories.releases) %>
- <% } %> +
+ + <%= user.packages.totalCount %> Package<%= s(user.packages.totalCount) %> +
+
+ + <%= computed.diskUsage %> used +
+ <% if (plugins.lines) { %> +
+ + <% if (plugins.lines.error) { %> + <%= plugins.lines.error.message %> + <% } else { %> + <%= f(plugins.lines.added) %> added, <%= f(plugins.lines.deleted) %> removed + <% } %> +
+ <% } %> +
+
+
+ + <%= user.sponsorshipsAsMaintainer.totalCount %> Sponsor<%= s(user.sponsorshipsAsMaintainer.totalCount) %> +
+
+ + <%= computed.repositories.stargazers %> Stargazer<%= s(computed.repositories.stargazers) %> +
+
+ + <%= computed.repositories.forks %> Forker<%= s(computed.repositories.forks) %> +
+
+ + <%= computed.repositories.watchers %> Watcher<%= s(computed.repositories.watchers) %> +
+ <% if (plugins.traffic) { %> +
+ + <% if (plugins.traffic.error) { %> + <%= plugins.traffic.error.message %> + <% } else { %> + <%= f(plugins.traffic.views.count) %> view<%= s(plugins.traffic.views.count) %> in last two weeks + <% } %> +
+ <% } %> +
+
diff --git a/source/templates/classic/partials/followup.ejs b/source/templates/classic/partials/followup.ejs index e0d2b81a..a6ebb576 100644 --- a/source/templates/classic/partials/followup.ejs +++ b/source/templates/classic/partials/followup.ejs @@ -14,7 +14,7 @@
<% } else { %> <% for (const name of plugins.followup.sections) { const section = {repositories:plugins.followup, user:plugins.followup?.user}[name] %> -
+

<%= {repositories:`On ${user.login}'${[...user.login].pop() === "s" ? "" : "s"} repositories`, user:`Created by ${user.login}`}[name] %>

diff --git a/source/templates/classic/partials/gists.ejs b/source/templates/classic/partials/gists.ejs index 47d84c91..b5b52aec 100644 --- a/source/templates/classic/partials/gists.ejs +++ b/source/templates/classic/partials/gists.ejs @@ -13,7 +13,7 @@
<% } else { %> -
+
<%= plugins.gists.files %> File<%= s(plugins.gists.files) %> @@ -23,7 +23,7 @@ <%= plugins.gists.comments %> Comment<%= s(plugins.gists.comments) %>
-
+
<%= plugins.gists.stargazers %> Stargazer<%= s(plugins.gists.stargazers) %> diff --git a/source/templates/classic/partials/habits.ejs b/source/templates/classic/partials/habits.ejs index 401261e4..e28cfab0 100644 --- a/source/templates/classic/partials/habits.ejs +++ b/source/templates/classic/partials/habits.ejs @@ -32,7 +32,7 @@ <% if (plugins.habits.charts) { %> <% if (!Number.isNaN(plugins.habits.commits.hour)) { %> -
+

Commit activity per time of the day

<% for (let h = 0; h < 24; h++) { const p = (plugins.habits.commits.hours[h]??0)/(plugins.habits.commits.hours.max??1); %> @@ -46,7 +46,7 @@
<% } %> -
+
<% if (!Number.isNaN(plugins.habits.commits.day)) { %>

Commit activity per day

diff --git a/source/templates/classic/partials/languages.ejs b/source/templates/classic/partials/languages.ejs index 742d21d2..f1bc1c87 100644 --- a/source/templates/classic/partials/languages.ejs +++ b/source/templates/classic/partials/languages.ejs @@ -11,21 +11,21 @@ <%= plugins.languages.error.message %>
- <% } else { %> - + <% } else { const width = 460 * (1 + large) %> + - + - + <% for (const {name, value, color, x} of plugins.languages.favorites) { %> - + <% } %> - <% if (plugins.languages.details?.length) { %> + <% if (plugins.languages.details?.length) { const rows = large ? [0, 1, 2, 3] : [0, 1] %>
- <% for (const row of [0, 1]) { %> + <% for (const row of rows) { %>
- <% for (const {name, value, color, size} of plugins.languages.favorites.filter((_, i) => i%2 === row)) { %> + <% for (const {name, value, color, size} of plugins.languages.favorites.filter((_, i) => i%rows.length === row)) { %>
diff --git a/source/templates/classic/partials/pagespeed.ejs b/source/templates/classic/partials/pagespeed.ejs index 370d601e..7a978ca7 100644 --- a/source/templates/classic/partials/pagespeed.ejs +++ b/source/templates/classic/partials/pagespeed.ejs @@ -44,36 +44,63 @@ <% if (plugins.pagespeed.detailed) { %>
-
- - Time to interactive -
-
- - Speed Index -
-
- - Total Blocking Time -
-
- - First Contentful Paint -
-
- - Largest Contentful Paint -
-
- - Cumulative Layout Shift -
+
+ + Time to interactive +
+
+ + Speed Index +
+
+ + Total Blocking Time +
+
+
+ <% for (const {score, suffix = "", threshold} of [ + {score:plugins.pagespeed.metrics.firstContentfulPaint/1000, suffix:"s", threshold:[2.336, 4]}, + {score:plugins.pagespeed.metrics.largestContentfulPaint/1000, suffix:"s", threshold:[2.5, 4]}, + {score:+plugins.pagespeed.metrics.cumulativeLayoutShift, threshold:[.1, .25]} + ]) { %> +
+
+ <% if (!Number.isNaN(score)) { %> + <%= score.toFixed(2).replace(/[.]0+$/, "") %> <%= suffix %> + <% } else { %> + N/A + <% } %> +
+ <% if (Number.isNaN(score)) { %> + + <% } else if (score <= threshold[0]) { %> + + <% } else if (score <= threshold[1]) { %> + + <% } else { %> + + <% } %> +
+ <% } %> +
+
+
+
+
+ + First Contentful Paint +
+
+ + Largest Contentful Paint +
+
+ + Cumulative Layout Shift +
<% for (const {score, suffix = "", threshold} of [ - {score:plugins.pagespeed.metrics.interactive/1000, suffix:"s", threshold:[3.785, 7.3]}, - {score:plugins.pagespeed.metrics.speedIndex/1000, suffix:"s", threshold:[3.387, 5.8]}, - {score:plugins.pagespeed.metrics.totalBlockingTime/1000, suffix:"s", threshold:[.287, .6]}, {score:plugins.pagespeed.metrics.firstContentfulPaint/1000, suffix:"s", threshold:[2.336, 4]}, {score:plugins.pagespeed.metrics.largestContentfulPaint/1000, suffix:"s", threshold:[2.5, 4]}, {score:+plugins.pagespeed.metrics.cumulativeLayoutShift, threshold:[.1, .25]} @@ -103,7 +130,7 @@ <% if (plugins.pagespeed.screenshot) { %>
- +
<% } %> diff --git a/source/templates/classic/partials/posts.ejs b/source/templates/classic/partials/posts.ejs index 4394fb82..eba4c047 100644 --- a/source/templates/classic/partials/posts.ejs +++ b/source/templates/classic/partials/posts.ejs @@ -16,32 +16,34 @@ From <%= plugins.posts.source %>
- <% if (plugins.posts.list.length) { %> - <% for (const {title, description, image, date} of plugins.posts.list) { %> -
- -
-
-
<%= f.date(new Date(date), {dateStyle:"short"}) %>
- <% if (plugins.posts.covers) { %> -
- <% } %> -
-
-
<%= title %>
- <% if (plugins.posts.descriptions) { %> -
<%= description %>
- <% } %> +
+ <% if (plugins.posts.list.length) { %> + <% for (const {title, description, image, date} of plugins.posts.list) { %> +
+ +
+
+
<%= f.date(new Date(date), {dateStyle:"short"}) %>
+ <% if (plugins.posts.covers) { %> +
+ <% } %> +
+
+
<%= title %>
+ <% if (plugins.posts.descriptions) { %> +
<%= description %>
+ <% } %> +
+ <% } %> + <% } else { %> +
+ + No recent posts
<% } %> - <% } else { %> -
- - No recent posts -
- <% } %> +
<% } %>
diff --git a/source/templates/classic/partials/projects.ejs b/source/templates/classic/partials/projects.ejs index 599d000b..ab33fc19 100644 --- a/source/templates/classic/partials/projects.ejs +++ b/source/templates/classic/partials/projects.ejs @@ -48,15 +48,15 @@
<% } %>
- <% if (progress.enabled) { %> + <% if (progress.enabled) { const width = 460 * (1 + large) %>
- + - + - - - + + +
<% } %> diff --git a/source/templates/classic/partials/stackoverflow.ejs b/source/templates/classic/partials/stackoverflow.ejs index 2360d196..25429253 100644 --- a/source/templates/classic/partials/stackoverflow.ejs +++ b/source/templates/classic/partials/stackoverflow.ejs @@ -14,8 +14,8 @@
<% } else { %> -
-
+
+
<%= plugins.stackoverflow.user.reputation %> reputation point<%= s(plugins.stackoverflow.user.reputation) %> @@ -29,7 +29,7 @@ <%= plugins.stackoverflow.user.comments %> comment<%= s(plugins.stackoverflow.user.comments) %>
-
+
<%= plugins.stackoverflow.user.badges %> badge<%= s(plugins.stackoverflow.user.badges) %> @@ -57,101 +57,103 @@ <%= {"questions-recent":"Recent questions", "questions-top":"Top questions", "answers-recent":"Recent answers", "answers-top":"Top answers"}[section] %> - <% for (const {type, ...entry} of plugins.stackoverflow[section]) { %> -
- <% if (type === "question") { %> -
- - <%- entry.title %> -
-
-
- - <%= entry.tags.join(", ") %> +
+ <% for (const {type, ...entry} of plugins.stackoverflow[section]) { %> +
+ <% if (type === "question") { %> +
+ + <%- entry.title %>
- <% if (entry.answered) { %> +
- - Resolved + + <%= entry.tags.join(", ") %>
- <% } %> -
-
- <%- entry.body %> -
-
-
- - <%= f(entry.upvotes) %> + <% if (entry.answered) { %> +
+ + Resolved +
+ <% } %>
-
- - <%= f(entry.downvotes) %> +
+ <%- entry.body %>
-
- - <%= f(entry.views) %> +
+
+ + <%= f(entry.upvotes) %> +
+
+ + <%= f(entry.downvotes) %> +
+
+ + <%= f(entry.views) %> +
+
+ + <%= f(entry.answers) %> +
+
+ + <%= f(entry.comments) %> +
+
+ + <%= entry.created %> +
-
+ <% } else if (type === "answer") { %> +
- <%= f(entry.answers) %> + <%- entry.question?.title %>
-
- - <%= f(entry.comments) %> -
-
- - <%= entry.created %> -
-
- <% } else if (type === "answer") { %> -
- - <%- entry.question?.title %> -
-
-
- - <%= entry.question?.tags.join(", ") %> -
- <% if (entry.question?.answered) { %> +
- - Resolved + + <%= entry.question?.tags.join(", ") %>
- <% } %> -
-
- <%- entry.body %> -
-
-
- - <%= f(entry.upvotes) %> + <% if (entry.question?.answered) { %> +
+ + Resolved +
+ <% } %>
-
- - <%= f(entry.downvotes) %> +
+ <%- entry.body %>
-
- - <%= f(entry.comments) %> -
-
- - <%= entry.created %> -
- <% if (entry.accepted) { %> +
- - Accepted + + <%= f(entry.upvotes) %>
- <% } %> -
- <% } %> -
- <% } %> +
+ + <%= f(entry.downvotes) %> +
+
+ + <%= f(entry.comments) %> +
+
+ + <%= entry.created %> +
+ <% if (entry.accepted) { %> +
+ + Accepted +
+ <% } %> +
+ <% } %> +
+ <% } %> +
diff --git a/source/templates/classic/partials/stars.ejs b/source/templates/classic/partials/stars.ejs index 223e48b5..ca2e3f87 100644 --- a/source/templates/classic/partials/stars.ejs +++ b/source/templates/classic/partials/stars.ejs @@ -5,7 +5,7 @@ Recently starred repositories
-
+
<% if (plugins.stars.error) { %>
@@ -13,7 +13,7 @@
<% } else { %> <% for (const {starred, node:repository} of plugins.stars.repositories) { %> -
+
<% if (repository.isFork) { %> diff --git a/source/templates/classic/partials/support.ejs b/source/templates/classic/partials/support.ejs index 27abf969..8cb7f939 100644 --- a/source/templates/classic/partials/support.ejs +++ b/source/templates/classic/partials/support.ejs @@ -14,8 +14,8 @@
<% } else { %> -
-
+
+
<%= plugins.support.stats.hearts %> heart<%= s(plugins.support.stats.hearts) %> received @@ -29,7 +29,7 @@ <%= plugins.support.stats.posts %> post<%= s(plugins.support.stats.posts) %>
-
+
<%= plugins.support.badges.count %> badge<%= s(plugins.support.badges.count) %> diff --git a/source/templates/classic/partials/tweets.ejs b/source/templates/classic/partials/tweets.ejs index d468cff3..4a28904d 100644 --- a/source/templates/classic/partials/tweets.ejs +++ b/source/templates/classic/partials/tweets.ejs @@ -29,7 +29,7 @@
<%- text %> <% if (attachments?.length) { %> -
+
<% for (const {image, title, description, website} of attachments) { %>
diff --git a/source/templates/classic/partials/wakatime.ejs b/source/templates/classic/partials/wakatime.ejs index 4fb9120a..84754981 100644 --- a/source/templates/classic/partials/wakatime.ejs +++ b/source/templates/classic/partials/wakatime.ejs @@ -14,7 +14,7 @@
<% } else { %>
-
+
<% if (plugins.wakatime.sections.includes("time")) { %>
@@ -34,7 +34,7 @@
<% } %>
-
+
<% if (plugins.wakatime.sections.includes("time")) { %>
@@ -56,10 +56,10 @@
- <% { const sections = plugins.wakatime.sections.filter(x => /-graphs$/.test(x)).map(x => x.replace(/-graphs$/, "")) %> - <% for (let i = 0; i < sections.length; i+=2) { %> + <% { const sections = plugins.wakatime.sections.filter(x => /-graphs$/.test(x)).map(x => x.replace(/-graphs$/, "")), slots = 2 + large %> + <% for (let i = 0; i < sections.length; i+=slots) { %>
- <% for (let j = 0; j < 2; j++) { const key = sections[i+j] ; const section = plugins.wakatime[key] ; if (!key) continue %> + <% for (let j = 0; j < slots; j++) { const key = sections[i+j] ; const section = plugins.wakatime[key] ; if (!key) continue %>

<%= {languages:"Language activity", projects:"Projects activity", editors:"Code editors", os:"Operating systems"}[key] %>

diff --git a/source/templates/classic/style.css b/source/templates/classic/style.css index e0944737..e0501161 100644 --- a/source/templates/classic/style.css +++ b/source/templates/classic/style.css @@ -5,6 +5,36 @@ color: #777777; } +/* Large SVG context */ + svg.large .largeable { + width: 474px; + } + svg.large .largeable > .row { + width: 100%; + } + svg.large .largeable-align-start { + align-items: flex-start; + } + svg.large .column.largeable, svg.large .row.largeable, svg.large .largeable-inline-flex { + display: inline-flex; + } + svg.large .largeable-flex-wrap, svg.large .largeable-column-fields { + display: flex; + flex-wrap: wrap; + } + svg.large .largeable-column-fields > .field { + width: 230px; + } + svg.large .chart.largeable { + width: 458px; + } + svg.large .largeable-width-auto { + width: auto; + } + svg.large .largeable-width-half { + width: 50%; + } + /* Headers */ h1, h2, h3 { margin: 8px 0 2px; @@ -292,6 +322,18 @@ border-radius: 5px; } + svg.large .audits { + display: inline-flex; + width: 474px; + } + svg.large .audits section:last-child > .field { + justify-content: right; + } + svg.large .screenshot { + width: 904px; + height: 630px; + } + /* Music plugin */ .tracklist { display: flex; @@ -310,6 +352,7 @@ .track img { margin: 0 10px; border-radius: 7px; + flex-shrink: 0; } .track .name { font-size: 14px; @@ -320,6 +363,16 @@ font-size: 12px; color: #666666; } + .track .infos { + flex-grow: 1; + } + svg.large .tracklist { + flex-direction: row; + flex-wrap: wrap; + } + svg.large .track { + width: 25%; + } /* Posts plugin */ .post { @@ -599,7 +652,6 @@ .activity .bold, .activity .user { font-weight: 600; - margin: 0 4px; } .activity .details, .activity .timestamp { @@ -640,6 +692,10 @@ -webkit-box-orient: vertical; } + svg.large .activity .field { + max-width: 900px; + } + /* People */ .people { padding: 0 10px; diff --git a/source/templates/repository/image.svg b/source/templates/repository/image.svg index c2dcb17c..c24a5bc3 100644 --- a/source/templates/repository/image.svg +++ b/source/templates/repository/image.svg @@ -1,4 +1,4 @@ - + diff --git a/source/templates/repository/partials/activity.ejs b/source/templates/repository/partials/activity.ejs index 5e10d649..92d79b03 100644 --- a/source/templates/repository/partials/activity.ejs +++ b/source/templates/repository/partials/activity.ejs @@ -18,18 +18,22 @@ No recent activity
<% } %> - <% for (const {actor, type, repo, timestamp, ...event} of plugins.activity.events) { const _ = letter => `
${actor}
${letter.toLocaleLowerCase()}` %> + <% for (const {actor, type, repo, timestamp, ...event} of plugins.activity.events) { const _ = letter => `${actor} ${letter.toLocaleLowerCase()}` %>
<% if (/^ref/.test(type)) { %>
- <% if (event.ref.type === "branch") { %> + <% if (event.ref.type === "repository") { %> + + <% } else if (event.ref.type === "branch") { %> <% } else { %> <% } %> - <%- /create/.test(type) ? `${_("C")}reated new` : `${_("D")}eleted` %> - <%= event.ref.type %>
<%= event.ref.name %>
in
<%= repo %>
+
+ <%- /create/.test(type) ? `${_("C")}reated new` : `${_("D")}eleted` %> + <%= event.ref.type %> <% if (event.ref.type !== "repository") { %> <%= event.ref.name %> in <% } %> <%= repo %> +
<% } %> <% if (type === "comment") { %> @@ -39,17 +43,21 @@ <% } else if ((event.on === "issue")||(event.on === "commit")) { %> <% } %> - <%- _("C") %>ommented on
#<%= event.number %> <%= event.title %>
+
+ <%- _("C") %>ommented on #<%= event.number %> <%= event.title %> +
-
-
<%= event.on === "commit" ? "committed" : "opened" %> by <%= event.user %> in
<%= repo %>
-
<%= event.content %>
+
+
<%= event.on === "commit" ? "committed" : "opened" %> by <%= event.user %> in <%= repo %>
+
<%- event.content %>
<% } %> <% if (type === "wiki") { %>
- <%- _("U") %>pdated <%= event.pages.length %> wiki page<%= s(event.pages.length) %> in
<%= repo %>
+
+ <%- _("U") %>pdated <%= event.pages.length %> wiki page<%= s(event.pages.length) %> in <%= repo %> +
<% for (const page of event.pages) { %> @@ -62,56 +70,68 @@ <% if (type === "pr") { %>
- <%- event.action === "opened" ? `${_("O")}pened` : `${_("M")}erged` %>
#<%= event.number %> <%= event.title %>
+
+ <%- event.action === "opened" ? `${_("O")}pened` : event.action === "merged" ? `${_("M")}erged` : `${_("C")}losed` %> #<%= event.number %> <%= event.title %> +
-
opened <%= user.login !== event.user ? `by ${event.user}` : "" %> in
<%= repo %>
-
<%= event.files.changed %> file<%= s(event.files.changed) %> changed
++<%= event.lines.added %> --<%= event.lines.deleted%>
+
<%= user.login !== event.user ? `opened by ${event.user}` : "" %> in <%= repo %>
+
<%= event.files.changed %> file<%= s(event.files.changed) %> changed ++<%= event.lines.added %> --<%= event.lines.deleted%>
<% } %> <% if (type === "issue") { %>
- <%- event.action === "opened" ? `${_("O")}pened` : event.action === "reopened" ? `${_("R")}eopened` : `${_("C")}losed` %>
#<%= event.number %> <%= event.title %>
+
+ <%- event.action === "opened" ? `${_("O")}pened` : event.action === "reopened" ? `${_("R")}eopened` : `${_("C")}losed` %> #<%= event.number %> <%= event.title %> +
-
opened <%= user.login !== event.user ? `by ${event.user}` : "" %> in
<%= repo %>
+
opened <%= user.login !== event.user ? `by ${event.user}` : "" %> in <%= repo %>
<% } %> <% if (type === "fork") { %>
- <%- _("F") %>orked
<%= repo %>
+
+ <%- _("F") %>orked <%= repo %> to <%= event.forked %> +
<% } %> <% if (type === "public") { %>
- <%- _("M") %>ade
<%= repo %>
public +
+ <%- _("M") %>ade <%= repo %> public +
<% } %> <% if (type === "review") { %>
- <%- _("R") %>eviewed
#<%= event.number %> <%= event.title %>
+
+ <%- _("R") %>eviewed #<%= event.number %> <%= event.title %> +
-
opened <%= user.login !== event.user ? `by ${event.user}` : "" %> in
<%= repo %>
+
opened <%= user.login !== event.user ? `by ${event.user}` : "" %> in <%= repo %>
<% } %> <% if (type === "push") { %>
- <%- _("P") %>ushed <%= event.size %> commit<%= s(event.size) %> in
<%= repo %>
+
+ <%- _("P") %>ushed <%= event.size %> commit<%= s(event.size) %> in <%= repo %> +
<% if (event.branch) { %> -
on branch
<%= event.branch %>
+
on branch <%= event.branch %>
<% } %> <% for (const commit of event.commits) { %>
-
#<%= commit.sha %>
-
<%= commit.message %>
+ #<%= commit.sha %> + <%= commit.message %>
<% } %>
@@ -119,20 +139,26 @@ <% if (type === "release") { %>
- <%- event.draft ? `${_("D")}rafted release` : event.prerelease ? `${_("P")}re-released` : `${_("R")}eleased` %> -
<%= event.name %>
of
<%= repo %>
+
+ <%- event.draft ? `${_("D")}rafted release` : event.prerelease ? `${_("P")}re-released` : `${_("R")}eleased` %> + <%= event.name %> of <%= repo %> +
<% } %> <% if (type === "star") { %>
- <%- _("S") %>tarred
<%= repo %>
+
+ <%- _("S") %>tarred <%= repo %> +
<% } %> <% if (type === "member") { %>
- <%- _("A") %>dded <%= event.user %> as collaborator in
<%= repo %>
+
+ <%- _("A") %>dded <%= event.user %> as collaborator in <%= repo %> +
<% } %> <% if (plugins.activity.timestamps) { %> diff --git a/source/templates/repository/partials/followup.ejs b/source/templates/repository/partials/followup.ejs index 100fd34c..7fcd44b5 100644 --- a/source/templates/repository/partials/followup.ejs +++ b/source/templates/repository/partials/followup.ejs @@ -10,25 +10,27 @@ <%= plugins.followup.error.message %>
- <% } else { %> - - - - - - - - -
-
- - <%= plugins.followup.issues.closed %> Closed + <% } else { const section = plugins.followup, width = 220*(1+large) %> +
+ + + + + + + + +
+
+ + <%= section.issues.open %> open +
+
+ + <%= section.issues.closed %> closed +
-
- - <%= plugins.followup.issues.open %> Open -
-
+
<% } %>
@@ -41,25 +43,32 @@ <%= plugins.followup.error.message %>
- <% } else { %> - - - - - - - - -
-
- - <%= plugins.followup.pr.merged %> Merged + <% } else { const section = plugins.followup, width = 220*(1+large) %> +
+ + + + + + + + + +
+
+ + <%= section.pr.open %> open +
+
+ + <%= section.pr.closed %> closed +
+
+ + <%= section.pr.merged %> merged +
-
- - <%= plugins.followup.pr.open %> Open -
-
+
<% } %>
diff --git a/source/templates/repository/partials/languages.ejs b/source/templates/repository/partials/languages.ejs index 742d21d2..f1bc1c87 100644 --- a/source/templates/repository/partials/languages.ejs +++ b/source/templates/repository/partials/languages.ejs @@ -11,21 +11,21 @@ <%= plugins.languages.error.message %>
- <% } else { %> - + <% } else { const width = 460 * (1 + large) %> + - + - + <% for (const {name, value, color, x} of plugins.languages.favorites) { %> - + <% } %> - <% if (plugins.languages.details?.length) { %> + <% if (plugins.languages.details?.length) { const rows = large ? [0, 1, 2, 3] : [0, 1] %>
- <% for (const row of [0, 1]) { %> + <% for (const row of rows) { %>
- <% for (const {name, value, color, size} of plugins.languages.favorites.filter((_, i) => i%2 === row)) { %> + <% for (const {name, value, color, size} of plugins.languages.favorites.filter((_, i) => i%rows.length === row)) { %>
diff --git a/source/templates/repository/partials/licenses.ejs b/source/templates/repository/partials/licenses.ejs index ada1da96..a8b96b1a 100644 --- a/source/templates/repository/partials/licenses.ejs +++ b/source/templates/repository/partials/licenses.ejs @@ -13,7 +13,7 @@
<% } else { %>
-
+
<%= plugins.licenses.default?.spdxId ?? "No license provided" %> @@ -23,7 +23,7 @@ <%= plugins.licenses.dependencies.length %> dependenc<%= s(plugins.licenses.dependencies.length, "y") %>
-
+
<%= plugins.licenses.known %> known license<%= s(plugins.licenses.known) %> used @@ -34,23 +34,23 @@
- <% if (plugins.licenses.ratio) { %> + <% if (plugins.licenses.ratio) { const width = 460 * (1 + large), rows = large ? [0, 1, 2, 3] : [0, 1] %> %>
- + - + - + <% for (const {name, value, color, x} of plugins.licenses.list) { %> - + <% } %>
- <% for (const row of [0, 1]) { %> + <% for (const row of rows) { %>
- <% for (const {name, value, color, count} of plugins.licenses.list.filter((_, i) => i%2 === row)) { %> + <% for (const {name, value, color, count} of plugins.licenses.list.filter((_, i) => i%rows.length === row)) { %>
diff --git a/source/templates/repository/partials/pagespeed.ejs b/source/templates/repository/partials/pagespeed.ejs index 370d601e..7a978ca7 100644 --- a/source/templates/repository/partials/pagespeed.ejs +++ b/source/templates/repository/partials/pagespeed.ejs @@ -44,36 +44,63 @@ <% if (plugins.pagespeed.detailed) { %>
-
- - Time to interactive -
-
- - Speed Index -
-
- - Total Blocking Time -
-
- - First Contentful Paint -
-
- - Largest Contentful Paint -
-
- - Cumulative Layout Shift -
+
+ + Time to interactive +
+
+ + Speed Index +
+
+ + Total Blocking Time +
+
+
+ <% for (const {score, suffix = "", threshold} of [ + {score:plugins.pagespeed.metrics.firstContentfulPaint/1000, suffix:"s", threshold:[2.336, 4]}, + {score:plugins.pagespeed.metrics.largestContentfulPaint/1000, suffix:"s", threshold:[2.5, 4]}, + {score:+plugins.pagespeed.metrics.cumulativeLayoutShift, threshold:[.1, .25]} + ]) { %> +
+
+ <% if (!Number.isNaN(score)) { %> + <%= score.toFixed(2).replace(/[.]0+$/, "") %> <%= suffix %> + <% } else { %> + N/A + <% } %> +
+ <% if (Number.isNaN(score)) { %> + + <% } else if (score <= threshold[0]) { %> + + <% } else if (score <= threshold[1]) { %> + + <% } else { %> + + <% } %> +
+ <% } %> +
+
+
+
+
+ + First Contentful Paint +
+
+ + Largest Contentful Paint +
+
+ + Cumulative Layout Shift +
<% for (const {score, suffix = "", threshold} of [ - {score:plugins.pagespeed.metrics.interactive/1000, suffix:"s", threshold:[3.785, 7.3]}, - {score:plugins.pagespeed.metrics.speedIndex/1000, suffix:"s", threshold:[3.387, 5.8]}, - {score:plugins.pagespeed.metrics.totalBlockingTime/1000, suffix:"s", threshold:[.287, .6]}, {score:plugins.pagespeed.metrics.firstContentfulPaint/1000, suffix:"s", threshold:[2.336, 4]}, {score:plugins.pagespeed.metrics.largestContentfulPaint/1000, suffix:"s", threshold:[2.5, 4]}, {score:+plugins.pagespeed.metrics.cumulativeLayoutShift, threshold:[.1, .25]} @@ -103,7 +130,7 @@ <% if (plugins.pagespeed.screenshot) { %>
- +
<% } %> diff --git a/source/templates/repository/partials/projects.ejs b/source/templates/repository/partials/projects.ejs index 1b2d4b32..b1c413ac 100644 --- a/source/templates/repository/partials/projects.ejs +++ b/source/templates/repository/partials/projects.ejs @@ -39,15 +39,15 @@
<% } %>
- <% if (progress.enabled) { %> + <% if (progress.enabled) { const width = 460 * (1 + large) %>
- + - + - - - + + +
<% } %>