Add new plugin "isocalendar"

This commit is contained in:
lowlighter
2020-11-03 18:19:25 +01:00
parent 4210806623
commit 24819054c6
10 changed files with 300 additions and 27 deletions

View File

@@ -100,6 +100,16 @@ jobs:
plugins_errors_fatal: yes
dryrun: yes
- name: Isocalendar plugin
uses: lowlighter/metrics@master
with:
token: ${{ secrets.METRICS_TOKEN }}
base: ""
repositories: 1
plugin_isocalendar: yes
plugins_errors_fatal: yes
dryrun: yes
- name: Habits plugin
uses: lowlighter/metrics@master
with:

View File

@@ -85,8 +85,12 @@ This way you'll be able to rapidly test SVG renders with your browser.
* To make HTTP/S requests
* [actions/toolkit](https://github.com/actions/toolkit/tree/master) and [vercel/ncc](https://github.com/vercel/ncc)
* To build the GitHub Action
* [vuejs/vue](https://github.com/vuejs/vue)
* [vuejs/vue](https://github.com/vuejs/vue) and [egoist/vue-prism-component](https://github.com/egoist/vue-prism-component) + [PrismJS/prism](https://github.com/PrismJS/prism)
* To display server application
* [puppeteer/puppeteer](https://github.com/puppeteer/puppeteer)
* To scrap the web
* [libxmljs/libxmljs](https://github.com/libxmljs/libxmljs)
* To test and verify SVG validity
### 🗛 Fonts

View File

@@ -14,9 +14,9 @@ But there's more with [plugins](https://github.com/lowlighter/metrics/tree/maste
| **Most used languages plugin** | **Follow-up plugin** | **Coding Habits plugin** |
|[<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.languages.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.languages.svg)|[<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.followup.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.followup.svg)|[<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.habits.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.habits.svg)|
| **Repositories traffic plugin** | **Lines of code plugin** | **Recent posts plugin** |
|[<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.traffic.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.traffic.svg)|[<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.lines.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.lines.traffic.svg)| [<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.posts.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.lines.posts.svg) |
| |
| More to come soon ! |
|[<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.traffic.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.traffic.svg)|[<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.lines.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.lines.svg)| [<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.posts.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.posts.svg) |
| **Isometric calendar plugin** | |
|[<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.isocalendar.svg" alt="" width="240">](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.isocalendar.svg) | More to come soon ! |
| Classic template | Terminal template | |
| :----------------: | :----------------: | :----------------: |
@@ -522,11 +522,32 @@ Now that you've got your `client_id`, `client_secret` and `refresh_token` you ca
</details>
#### 📅 Isometric calendar
The *isocalendar* plugin allows you to display an isometric view of your commits calendar, along with a few stats like your current streak and your commit average per day.
![Isocalendar plugin](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.isocalendar.svg)
<details>
<summary>💬 About</summary>
It will consume an additional GitHub request.
Add the following to your workflow :
```yaml
- uses: lowlighter/metrics@latest
with:
# ... other options
plugin_isocalendar: yes
```
</details>
#### 👨‍💻 Lines
The *lines* of code plugin allows you to compute the number of lines of code you added and removed across all of your repositories.
![Languages plugin](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.lines.svg)
![Lines plugin](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.lines.svg)
<details>
<summary>💬 About</summary>
@@ -547,7 +568,7 @@ Add the following to your workflow :
The repositories *traffic* plugin allows you to compute the number of pages views across your repositories.
![Languages plugin](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.traffic.svg)
![Traffic plugin](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.traffic.svg)
<details>
<summary>💬 About</summary>
@@ -697,3 +718,4 @@ See [GitHub Logos and Usage](https://github.com/logos) for more information.
* [anuraghazra/github-readme-stats](https://github.com/anuraghazra/github-readme-stats)
* [jstrieb/github-stats](https://github.com/jstrieb/github-stats)
* [ankurparihar/readme-pagespeed-insights](https://github.com/ankurparihar/readme-pagespeed-insights)
* [jasonlong/isometric-contributions](https://github.com/jasonlong/isometric-contributions)

View File

@@ -182,6 +182,12 @@ inputs:
description: Posts source
default: ""
# Isometric calendar plugin
# Display an isometric view of your commits calendar, along with a few stats like current streak and average commits per day
plugin_isocalendar:
description:
default: no
# Enable debug mode
# Be sure to put all secrets in your repository secrets before to avoid any leaks !
debug:

103
action/dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -81,6 +81,7 @@
followup:{enabled:bool(core.getInput("plugin_followup"))},
music:{enabled:bool(core.getInput("plugin_music"))},
posts:{enabled:bool(core.getInput("plugin_posts"))},
isocalendar:{enabled:bool(core.getInput("isocalendar"))},
}
let q = Object.fromEntries(Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => [key, true]))
console.log(`Plugins enabled | ${Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => key).join(", ")}`)

View File

@@ -39,8 +39,11 @@
"enabled":false, "//":"Enable or disable music recently played / random track from playlist",
"token":null, "//":"Music provider token (may be required depending on provider)"
},
"posts":{ "//":"posts plugin",
"posts":{ "//":"Posts plugin",
"enabled":false, "//":"Enable or disable recents posts"
},
"isocalendar":{ "//":"Isometric calendar plugin",
"enabled":false, "//":"Enable or disable isometric calendar"
}
}
}

View File

@@ -1,6 +1,7 @@
//Imports
import followup from "./followup/index.mjs"
import habits from "./habits/index.mjs"
import isocalendar from "./isocalendar/index.mjs"
import languages from "./languages/index.mjs"
import lines from "./lines/index.mjs"
import music from "./music/index.mjs"
@@ -13,6 +14,7 @@
export default {
followup,
habits,
isocalendar,
languages,
lines,
music,

View File

@@ -0,0 +1,93 @@
//Setup
export default async function ({login, graphql, q}, {enabled = false} = {}) {
//Plugin execution
try {
//Check if plugin is enabled and requirements are met
if ((!enabled)||(!q.isocalendar))
return null
//Compute start day (need to )
const from = new Date(Date.now()-180*24*60*60*1000)
const day = from.getDay()||7
if (day !== 1)
from.setHours(-24*(day-1))
//Retrieve more data from contribution calendar
const {user:{calendar:{contributionCalendar:calendar}}} = await graphql(`
query Calendar {
user(login: $login) {
calendar:contributionsCollection(from: $calendar.from, to: $calendar.to) {
contributionCalendar {
weeks {
contributionDays {
contributionCount
color
date
}
}
}
}
}
}
`
.replace(/[$]login/, `"${login}"`)
.replace(/[$]calendar.to/, `"${(new Date()).toISOString()}"`)
.replace(/[$]calendar.from/, `"${from.toISOString()}"`)
)
//Compute max contribution per day to scale
let max = 0, streak = {max:0, current:0}, values = [], average = 0
for (const week of calendar.weeks) {
for (const day of week.contributionDays) {
values.push(day.contributionCount)
max = Math.max(max, day.contributionCount)
streak.current = day.contributionCount ? streak.current+1 : 0
streak.max = Math.max(streak.max, streak.current)
}
}
average = (values.reduce((a, b) => a + b, 0)/values.length).toFixed(2).replace(/.0+$/, "")
//Compute SVG
const size = 6
let i = 0, j = 0
let svg = `
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="margin-top: -52px;" viewBox="0,0 480,170">
<filter id="brightness1">
<feComponentTransfer>
<feFuncR type="linear" slope="0.6" />
<feFuncG type="linear" slope="0.6" />
<feFuncB type="linear" slope="0.6" />
</feComponentTransfer>
</filter>
<filter id="brightness2">
<feComponentTransfer>
<feFuncR type="linear" slope="0.2" />
<feFuncG type="linear" slope="0.2" />
<feFuncB type="linear" slope="0.2" />
</feComponentTransfer>
</filter>
<g transform="scale(4) translate(12, 0)">`
//Iterate through weeks
for (const week of calendar.weeks) {
svg += `<g transform="translate(${i*1.7}, ${i})">`
j = 0
//Iterate through days
for (const day of week.contributionDays) {
const ratio = day.contributionCount/max
svg += `
<g transform="translate(${j*-1.7}, ${j+(1-ratio)*size})">
<path fill="${day.color}" d="M1.7,2 0,1 1.7,0 3.4,1 z" />
<path fill="${day.color}" filter="url(#brightness1)" d="M0,1 1.7,2 1.7,${2+ratio*size} 0,${1+ratio*size} z" />
<path fill="${day.color}" filter="url(#brightness2)" d="M1.7,2 3.4,1 3.4,${1+ratio*size} 1.7,${2+ratio*size} z" />
</g>`
j++
}
svg += `</g>`
i++
}
svg += `</g></svg>`
//Results
return {streak, max, average, svg}
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
}
}

View File

@@ -10,7 +10,8 @@
+ (!!computed.plugins.languages)*96
+ (!!computed.plugins.music)*64 + (computed.plugins.music ? computed.plugins.music.tracks ? 14+Math.max(0, computed.plugins.music.tracks.length-1)*36 : 0 : 0)
+ (!!computed.plugins.posts)*64 + (computed.plugins.posts ? computed.plugins.posts.posts ? Math.max(0, computed.plugins.posts.posts.length)*40 : 0 : 0)
+ Math.max(0, (((!!base.metadata)+(!!base.header)+((!!base.activity)||(!!base.community))+(!!base.repositories)+((!!computed.plugins.habits))+(!!computed.plugins.pagespeed)+(!!computed.plugins.languages)+(!!computed.plugins.music)+(!!computed.plugins.posts))-1))*4
+ (!!computed.plugins.isocalendar)*180
+ Math.max(0, (((!!base.metadata)+(!!base.header)+((!!base.activity)||(!!base.community))+(!!base.repositories)+((!!computed.plugins.habits))+(!!computed.plugins.pagespeed)+(!!computed.plugins.languages)+(!!computed.plugins.music)+(!!computed.plugins.posts)+(!!computed.plugins.isocalendar))-1))*4
%>">
<defs><style><%= fonts %></style></defs>
@@ -125,7 +126,7 @@
</h2>
<div class="row">
<section>
<div class="field">
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8.75.75a.75.75 0 00-1.5 0V2h-.984c-.305 0-.604.08-.869.23l-1.288.737A.25.25 0 013.984 3H1.75a.75.75 0 000 1.5h.428L.066 9.192a.75.75 0 00.154.838l.53-.53-.53.53v.001l.002.002.002.002.006.006.016.015.045.04a3.514 3.514 0 00.686.45A4.492 4.492 0 003 11c.88 0 1.556-.22 2.023-.454a3.515 3.515 0 00.686-.45l.045-.04.016-.015.006-.006.002-.002.001-.002L5.25 9.5l.53.53a.75.75 0 00.154-.838L3.822 4.5h.162c.305 0 .604-.08.869-.23l1.289-.737a.25.25 0 01.124-.033h.984V13h-2.5a.75.75 0 000 1.5h6.5a.75.75 0 000-1.5h-2.5V3.5h.984a.25.25 0 01.124.033l1.29.736c.264.152.563.231.868.231h.162l-2.112 4.692a.75.75 0 00.154.838l.53-.53-.53.53v.001l.002.002.002.002.006.006.016.015.045.04a3.517 3.517 0 00.686.45A4.492 4.492 0 0013 11c.88 0 1.556-.22 2.023-.454a3.512 3.512 0 00.686-.45l.045-.04.01-.01.006-.005.006-.006.002-.002.001-.002-.529-.531.53.53a.75.75 0 00.154-.838L13.823 4.5h.427a.75.75 0 000-1.5h-2.234a.25.25 0 01-.124-.033l-1.29-.736A1.75 1.75 0 009.735 2H8.75V.75zM1.695 9.227c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327l-1.305 2.9zm10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327l-1.305 2.9z"></path></svg>
<% if (computed.licenses.favorite.length) { %>
Prefer <%= computed.licenses.favorite %> license
@@ -438,6 +439,40 @@
</section>
<% } %>
<% if (computed.plugins.isocalendar) { %>
<section>
<h2 class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4.75 0a.75.75 0 01.75.75V2h5V.75a.75.75 0 011.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0113.25 16H2.75A1.75 1.75 0 011 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 014.75 0zm0 3.5h8.5a.25.25 0 01.25.25V6h-11V3.75a.25.25 0 01.25-.25h2zm-2.25 4v6.75c0 .138.112.25.25.25h10.5a.25.25 0 00.25-.25V7.5h-11z"/></svg>
Contributions calendar
</h2>
<div class="row">
<section>
<% if (computed.plugins.isocalendar.error) { %>
<div class="field error">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4.47.22A.75.75 0 015 0h6a.75.75 0 01.53.22l4.25 4.25c.141.14.22.331.22.53v6a.75.75 0 01-.22.53l-4.25 4.25A.75.75 0 0111 16H5a.75.75 0 01-.53-.22L.22 11.53A.75.75 0 010 11V5a.75.75 0 01.22-.53L4.47.22zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5H5.31zM8 4a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 018 4zm0 8a1 1 0 100-2 1 1 0 000 2z"></path></svg>
<%= computed.plugins.isocalendar.error.message %>
</div>
<% } %>
</section>
<% if (!computed.plugins.isocalendar.error) { %>
<section>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.998 14.5c2.832 0 5-1.98 5-4.5 0-1.463-.68-2.19-1.879-3.383l-.036-.037c-1.013-1.008-2.3-2.29-2.834-4.434-.322.256-.63.579-.864.953-.432.696-.621 1.58-.046 2.73.473.947.67 2.284-.278 3.232-.61.61-1.545.84-2.403.633a2.788 2.788 0 01-1.436-.874A3.21 3.21 0 003 10c0 2.53 2.164 4.5 4.998 4.5zM9.533.753C9.496.34 9.16.009 8.77.146 7.035.75 4.34 3.187 5.997 6.5c.344.689.285 1.218.003 1.5-.419.419-1.54.487-2.04-.832-.173-.454-.659-.762-1.035-.454C2.036 7.44 1.5 8.702 1.5 10c0 3.512 2.998 6 6.498 6s6.5-2.5 6.5-6c0-2.137-1.128-3.26-2.312-4.438-1.19-1.184-2.436-2.425-2.653-4.81z"/></svg>
Current streak <%= computed.plugins.isocalendar.streak.current %> day<%= s(computed.plugins.isocalendar.streak.current) %>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.5 1.75a.75.75 0 00-1.5 0v12.5c0 .414.336.75.75.75h14.5a.75.75 0 000-1.5H1.5V1.75zm14.28 2.53a.75.75 0 00-1.06-1.06L10 7.94 7.53 5.47a.75.75 0 00-1.06 0L3.22 8.72a.75.75 0 001.06 1.06L7 7.06l2.47 2.47a.75.75 0 001.06 0l5.25-5.25z"></path></svg>
~ <%= computed.plugins.isocalendar.average %> commits per day
</div>
</section>
<% } %>
</div>
<% if (computed.plugins.isocalendar.svg) { %>
<%- computed.plugins.isocalendar.svg %>
<% } %>
</section>
<% } %>
<% if (base.metadata) { %>
<footer>
<span>These metrics <%= !computed.token.scopes.includes("repo") ? "does not include" : "includes" %> private contributions</span>

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 46 KiB