Add new plugin "isocalendar"
This commit is contained in:
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
32
README.md
32
README.md
@@ -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.
|
||||
|
||||

|
||||
|
||||
<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.
|
||||
|
||||

|
||||

|
||||
|
||||
<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.
|
||||
|
||||

|
||||

|
||||
|
||||
<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)
|
||||
|
||||
@@ -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
103
action/dist/index.js
vendored
File diff suppressed because one or more lines are too long
@@ -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(", ")}`)
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
93
src/plugins/isocalendar/index.mjs
Normal file
93
src/plugins/isocalendar/index.mjs
Normal 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`}}
|
||||
}
|
||||
}
|
||||
@@ -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 |
Reference in New Issue
Block a user