fix(docs): lot of misspelling (#1180) [skip ci]

This commit is contained in:
Josh Soref
2022-08-14 12:04:03 -04:00
committed by GitHub
parent e2f27e931d
commit ab85858528
59 changed files with 115 additions and 115 deletions

View File

@@ -32,7 +32,7 @@ It is possible to host workflows in the `.github` repository of organizations, a
## *️⃣ Organizations memberships for user accounts ## *️⃣ Organizations memberships for user accounts
By default, GitHub only display public memberships. By default, GitHub only display public memberships.
Membership visibility canbe managed in the `People` tab of your organization. Membership visibility can be managed in the `People` tab of your organization.
![Publish organization membership](/.github/readme/imgs/setup_public_membership_org.light.png#gh-light-mode-only) ![Publish organization membership](/.github/readme/imgs/setup_public_membership_org.light.png#gh-light-mode-only)
![Publish organization membership](/.github/readme/imgs/setup_public_membership_org.dark.png#gh-dark-mode-only) ![Publish organization membership](/.github/readme/imgs/setup_public_membership_org.dark.png#gh-dark-mode-only)

View File

@@ -154,7 +154,7 @@ Update profile `README.md` to include rendered image.
### 4.1 URL parameters syntax ### 4.1 URL parameters syntax
The GitHub action and the web instance uses the same engine behing the hood. The GitHub action and the web instance uses the same engine behind the hood.
It is actually possible to generate image directly from url without passing by the web ui by knowing how to pass parameters. It is actually possible to generate image directly from url without passing by the web ui by knowing how to pass parameters.

View File

@@ -1,4 +1,4 @@
# 📊 Metrics [<img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=280144&theme=dark" alt="" align="right" width="190" height="41">](https://www.producthunt.com/posts/github-metrics?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-github-metrics) # 📊 Metrics [<img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=280144&theme=dark" alt="" align="right" width="190" height="41">](https://www.producthunt.com/posts/github-metrics?utm_source=badge-featured&utm_medium=badge&utm_source=badge-github-metrics)
[![Continuous integration](https://github.com/lowlighter/metrics/actions/workflows/ci.yml/badge.svg)](https://github.com/lowlighter/metrics/actions/workflows/ci.yml) [![Continuous integration](https://github.com/lowlighter/metrics/actions/workflows/ci.yml/badge.svg)](https://github.com/lowlighter/metrics/actions/workflows/ci.yml)

View File

@@ -34,10 +34,10 @@ Be sure to read [contribution guide](/CONTRIBUTING.md) and [architecture](/ARCHI
Please respect the following guidelines: Please respect the following guidelines:
- A plugin should be independant and should not rely on other plugins - A plugin should be independent and should not rely on other plugins
- [🧱 core](/source/plugins/core/README.md) and [🗃️ base](/source/plugins/base/README.md) output can be reused though - [🧱 core](/source/plugins/core/README.md) and [🗃️ base](/source/plugins/base/README.md) output can be reused though
- A plugin should never edit its original arguments, as it is shared amongst other plugins and would create unattended side effects - A plugin should never edit its original arguments, as it is shared amongst other plugins and would create unattended side effects
- Use `imports.metadata.plugins.{plugin-name}.inputs()` to automatically typecheck and default user inputs through defined `metadata.yml` - Use `imports.metadata.plugins.{plugin-name}.inputs()` to automatically type check and default user inputs through defined `metadata.yml`
- Plugin options should respect the "lexical field" of existing option to keep consistency - Plugin options should respect the "lexical field" of existing option to keep consistency
- Plugin errors should be handled gracefully by partials with error message - Plugin errors should be handled gracefully by partials with error message
- New dependencies should be avoided, consider using existing `imports` - New dependencies should be avoided, consider using existing `imports`
@@ -210,7 +210,7 @@ export default async function(
{ {
login, //GitHub username login, //GitHub username
q, //Raw user inputs (dot notation without plugin_ prefix, don't use it directly) q, //Raw user inputs (dot notation without plugin_ prefix, don't use it directly)
imports, //Various utilitaires (axios, puppeteer, fs, etc., see /source/app/metrics/utils.mjs) imports, //Various utilities (axios, puppeteer, fs, etc., see /source/app/metrics/utils.mjs)
data, //Raw data from core/base plugin data, //Raw data from core/base plugin
computed, //Computed data from core/base plugin computed, //Computed data from core/base plugin
rest, //Rest authenticated GitHub octokit rest, //Rest authenticated GitHub octokit

View File

@@ -5,7 +5,7 @@ Plugins provide additional content and lets you customize rendered metrics.
**📦 Maintained by core team** **📦 Maintained by core team**
<% { let previous = null; for (const [plugin, {name, category, deprecation, authors = []}] of Object.entries(plugins).filter(([key, value]) => (value)&&(value.category !== "community")).sort(([an, a], [bn, b]) => a.category === b.category ? an.localeCompare(bn) : 0)) { %> <% { let previous = null; for (const [plugin, {name, category, deprecation, authors = []}] of Object.entries(plugins).filter(([key, value]) => (value)&&(value.category !== "community")).sort(([an, a], [bn, b]) => a.category === b.category ? an.localeCompare(bn) : 0)) { %>
<% if (previous !== category) { previous = category -%> <% if (previous !== category) { previous = category -%>
* **<%= `${category.charAt(0).toLocaleUpperCase()}${category.substring(1)} plugins` %>** * **<%= `${category === "github" ? "GitHub" : `${category.charAt(0).toLocaleUpperCase()}${category.substring(1)}`} plugins` %>**
<% } -%> <% } -%>
* [<%- name %> <sub>`<%= plugin %>`</sub>](/source/plugins/<%= plugin %>/README.md)<%# -%><% if (deprecation) { %> <sub>`⚠️ deprecated`</sub><% } %><%# -%> * [<%- name %> <sub>`<%= plugin %>`</sub>](/source/plugins/<%= plugin %>/README.md)<%# -%><% if (deprecation) { %> <sub>`⚠️ deprecated`</sub><% } %><%# -%>
<% }} %> <% }} %>
@@ -14,4 +14,4 @@ Plugins provide additional content and lets you customize rendered metrics.
* **[Community plugins](/source/plugins/community/README.md)** * **[Community plugins](/source/plugins/community/README.md)**
<% { let previous = null; for (const [plugin, {name, category, authors = []}] of Object.entries(plugins).filter(([key, value]) => (value)&&(value.category === "community")).sort(([an, a], [bn, b]) => a.category === b.category ? an.localeCompare(bn) : 0)) { %><%# -%> <% { let previous = null; for (const [plugin, {name, category, authors = []}] of Object.entries(plugins).filter(([key, value]) => (value)&&(value.category === "community")).sort(([an, a], [bn, b]) => a.category === b.category ? an.localeCompare(bn) : 0)) { %><%# -%>
* [<%- name %> <sub>`<%= plugin %>`</sub>](/source/plugins/community/<%= plugin %>/README.md) by <%- authors.map(author => `[@${author}](https://github.com/${author})`).join(" ") %> * [<%- name %> <sub>`<%= plugin %>`</sub>](/source/plugins/community/<%= plugin %>/README.md) by <%- authors.map(author => `[@${author}](https://github.com/${author})`).join(" ") %>
<% }} %> <% }} %>

View File

@@ -10,7 +10,7 @@ const browser = await puppeteer.launch({
}) })
const page = await browser.newPage() const page = await browser.newPage()
//Select markdown example and take screenshoot //Select markdown example and take screenshot
await page.setViewport({width: 600, height: 600}) await page.setViewport({width: 600, height: 600})
await page.goto("https://github.com/lowlighter/metrics/blob/examples/metrics.markdown.md") await page.goto("https://github.com/lowlighter/metrics/blob/examples/metrics.markdown.md")
const clip = await page.evaluate(() => { const clip = await page.evaluate(() => {

View File

@@ -354,7 +354,7 @@ jobs:
user: lowlighter user: lowlighter
plugins_errors_fatal: yes plugins_errors_fatal: yes
if: ${{ success() || failure() }} if: ${{ success() || failure() }}
- name: 💡 Coding habits and activity - Midly interesting facts - name: 💡 Coding habits and activity - Mildly interesting facts
uses: lowlighter/metrics@master uses: lowlighter/metrics@master
with: with:
filename: metrics.plugin.habits.facts.svg filename: metrics.plugin.habits.facts.svg
@@ -806,7 +806,7 @@ jobs:
user: lowlighter user: lowlighter
plugins_errors_fatal: yes plugins_errors_fatal: yes
if: ${{ success() || failure() }} if: ${{ success() || failure() }}
- name: ⏱️ Google PageSpeed - Succint report - name: ⏱️ Google PageSpeed - Succinct report
uses: lowlighter/metrics@master uses: lowlighter/metrics@master
with: with:
filename: metrics.plugin.pagespeed.svg filename: metrics.plugin.pagespeed.svg

View File

@@ -62,7 +62,7 @@ To solve this, metrics now spawns a [puppeteer](https://github.com/puppeteer/pup
![Metrics marker](/.github/readme/imgs/about_metrics_marker.png) ![Metrics marker](/.github/readme/imgs/about_metrics_marker.png)
Additional bonus of using pupeeter is that it can take screenshots, making it easy to convert SVGs to PNG output. Additional bonus of using puppeteer is that it can take screenshots, making it easy to convert SVGs to PNG output.
### 💬 Gathering external data from GitHub APIs and Third-Party services ### 💬 Gathering external data from GitHub APIs and Third-Party services
@@ -70,7 +70,7 @@ Additional bonus of using pupeeter is that it can take screenshots, making it ea
As for other external services (Twitter, Spotify, PageSpeed, ...), metrics use their respective APIs, usually making https requests through [axios](https://github.com/axios/axios) and by following their documentation. It would be overkill to install entire SDKs for these since plugins rarely uses more than 2/3 calls. As for other external services (Twitter, Spotify, PageSpeed, ...), metrics use their respective APIs, usually making https requests through [axios](https://github.com/axios/axios) and by following their documentation. It would be overkill to install entire SDKs for these since plugins rarely uses more than 2/3 calls.
In last resort, pupeeter is seldom used to scrap websites, though its use tends to make things slow and unstable (as it'll break upon HTML structural changes). In last resort, puppeteer is seldom used to scrap websites, though its use tends to make things slow and unstable (as it'll break upon HTML structural changes).
### 💬 Web instance and GitHub action similarities ### 💬 Web instance and GitHub action similarities

View File

@@ -5,7 +5,7 @@
We as members, contributors, and leaders pledge to make participation in our We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status, identity and expression, level of experience, education, socioeconomic status,
nationality, personal appearance, race, religion, or sexual identity nationality, personal appearance, race, religion, or sexual identity
and orientation. and orientation.

View File

@@ -20,7 +20,7 @@ The following contributions are accepted:
<table> <table>
<tr> <tr>
<th>Section</th> <th>Section</th>
<th>Editions</th> <th>Changes</th>
<th>Additions</th> <th>Additions</th>
<th>Notes</th> <th>Notes</th>
</tr> </tr>
@@ -41,7 +41,7 @@ The following contributions are accepted:
<td>❌</td> <td>❌</td>
<td> <td>
<ul> <ul>
<li>Templates editions are allowed with new features additions (but must remain consistent with current visuals)</li> <li>Template changes are allowed with new features additions (but must remain consistent with current visuals)</li>
<li>New templates should use <a href="https://github.com/lowlighter/metrics/blob/master/source/templates/community/README.md">📕 Community templates</a> instead</li> <li>New templates should use <a href="https://github.com/lowlighter/metrics/blob/master/source/templates/community/README.md">📕 Community templates</a> instead</li>
</ul> </ul>
</td> </td>
@@ -73,7 +73,7 @@ The following contributions are accepted:
<td>❌</td> <td>❌</td>
<td> <td>
<ul> <ul>
<li>Core editions impact all rendering process and should be avoided unless necessary</li> <li>Core changes impact all rendering process and should be avoided unless necessary</li>
<li>New dependencies should be avoided when possible</li> <li>New dependencies should be avoided when possible</li>
</ul> </ul>
</td> </td>

View File

@@ -1,4 +1,4 @@
# 📊 Metrics [<img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=280144&theme=dark" alt="" align="right" width="190" height="41">](https://www.producthunt.com/posts/github-metrics?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-github-metrics) # 📊 Metrics [<img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=280144&theme=dark" alt="" align="right" width="190" height="41">](https://www.producthunt.com/posts/github-metrics?utm_source=badge-featured&utm_medium=badge&utm_source=badge-github-metrics)
[![Continuous integration](https://github.com/lowlighter/metrics/actions/workflows/ci.yml/badge.svg)](https://github.com/lowlighter/metrics/actions/workflows/ci.yml) [![Continuous integration](https://github.com/lowlighter/metrics/actions/workflows/ci.yml/badge.svg)](https://github.com/lowlighter/metrics/actions/workflows/ci.yml)
@@ -84,7 +84,7 @@ Generate metrics that can be embedded everywhere, including your GitHub profile
</td> </td>
<td align="center"> <td align="center">
<details open><summary>Recent activity charts</summary><img alt="" width="400" src="https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.charts.svg" alt=""></img></details> <details open><summary>Recent activity charts</summary><img alt="" width="400" src="https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.charts.svg" alt=""></img></details>
<details open><summary>Midly interesting facts</summary><img alt="" width="400" src="https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.facts.svg" alt=""></img></details> <details open><summary>Mildly interesting facts</summary><img alt="" width="400" src="https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.facts.svg" alt=""></img></details>
<img width="900" height="1" alt=""> <img width="900" height="1" alt="">
</td> </td>
</tr> </tr>
@@ -408,7 +408,7 @@ Plugins provide additional content and lets you customize rendered metrics.
* **Core plugins** * **Core plugins**
* [🗃️ Base content <sub>`base`</sub>](/source/plugins/base/README.md) * [🗃️ Base content <sub>`base`</sub>](/source/plugins/base/README.md)
* [🧱 Core <sub>`core`</sub>](/source/plugins/core/README.md) * [🧱 Core <sub>`core`</sub>](/source/plugins/core/README.md)
* **Github plugins** * **GitHub plugins**
* [🏆 Achievements <sub>`achievements`</sub>](/source/plugins/achievements/README.md) * [🏆 Achievements <sub>`achievements`</sub>](/source/plugins/achievements/README.md)
* [📰 Recent activity <sub>`activity`</sub>](/source/plugins/activity/README.md) * [📰 Recent activity <sub>`activity`</sub>](/source/plugins/activity/README.md)
* [📆 Commit calendar <sub>`calendar`</sub>](/source/plugins/calendar/README.md) * [📆 Commit calendar <sub>`calendar`</sub>](/source/plugins/calendar/README.md)

2
action.yml generated
View File

@@ -436,7 +436,7 @@ inputs:
default: <default-value> default: <default-value>
plugin_habits_facts: plugin_habits_facts:
description: Midly interesting facts description: Mildly interesting facts
default: <default-value> default: <default-value>
plugin_habits_charts: plugin_habits_charts:

View File

@@ -176,11 +176,11 @@ function quit(reason) {
const api = {} const api = {}
const resources = {} const resources = {}
api.graphql = octokit.graphql.defaults({headers: {authorization: `token ${token}`}}) api.graphql = octokit.graphql.defaults({headers: {authorization: `token ${token}`}})
info("Github GraphQL API", "ok") info("GitHub GraphQL API", "ok")
const octoraw = github.getOctokit(token) const octoraw = github.getOctokit(token)
api.rest = octoraw.rest api.rest = octoraw.rest
api.rest.request = octoraw.request api.rest.request = octoraw.request
info("Github REST API", "ok") info("GitHub REST API", "ok")
//Apply mocking if needed //Apply mocking if needed
if (mocked) { if (mocked) {
Object.assign(api, await mocks(api)) Object.assign(api, await mocks(api))
@@ -397,7 +397,7 @@ function quit(reason) {
let rendered = await retry(async () => { let rendered = await retry(async () => {
const {rendered, errors} = await metrics({login: user, q}, {graphql, rest, plugins, conf, die, verify, convert}, {Plugins, Templates}) const {rendered, errors} = await metrics({login: user, q}, {graphql, rest, plugins, conf, die, verify, convert}, {Plugins, Templates})
if (errors.length) { if (errors.length) {
console.warn(`::group::${errors.length} error(s) occured`) console.warn(`::group::${errors.length} error(s) occurred`)
console.warn(util.inspect(errors, {depth: Infinity, maxStringLength: 256})) console.warn(util.inspect(errors, {depth: Infinity, maxStringLength: 256}))
console.warn("::endgroup::") console.warn("::endgroup::")
} }
@@ -459,7 +459,7 @@ function quit(reason) {
else { else {
//Cache embed svg for markdown outputs //Cache embed svg for markdown outputs
if (/markdown/.test(convert)) { if (/markdown/.test(convert)) {
const regex = /(?<match><img class="metrics-cachable" data-name="(?<name>[\s\S]+?)" src="data:image[/](?<format>(?:svg[+]xml)|jpeg|png);base64,(?<content>[/+=\w]+?)">)/ const regex = /(?<match><img class="metrics-cacheable" data-name="(?<name>[\s\S]+?)" src="data:image[/](?<format>(?:svg[+]xml)|jpeg|png);base64,(?<content>[/+=\w]+?)">)/
let matched = null let matched = null
while (matched = regex.exec(rendered)?.groups) { //eslint-disable-line no-cond-assign while (matched = regex.exec(rendered)?.groups) { //eslint-disable-line no-cond-assign
await retry(async () => { await retry(async () => {
@@ -499,7 +499,7 @@ function quit(reason) {
} }
} }
//Check editions //Check changes
if ((committer.commit) || (committer.pr)) { if ((committer.commit) || (committer.pr)) {
const git = sgit() const git = sgit()
const sha = await git.hashObject(paths.join("/renders", filename)) const sha = await git.hashObject(paths.join("/renders", filename))
@@ -690,7 +690,7 @@ function quit(reason) {
console.error(error) console.error(error)
//Print debug buffer if debug was not enabled (if it is, it's already logged on the fly) //Print debug buffer if debug was not enabled (if it is, it's already logged on the fly)
if (!DEBUG) { if (!DEBUG) {
for (const log of [info.break(), "An error occured, logging debug message :", ...debugged]) for (const log of [info.break(), "An error occurred, logging debug message :", ...debugged])
console.log(log) console.log(log)
} }
core.setFailed(error.message) core.setFailed(error.message)

View File

@@ -68,7 +68,7 @@ export default async function metrics({login, q}, {graphql, rest, plugins, conf,
if (errors.length) { if (errors.length) {
console.debug(`metrics/compute/${login} > ${errors.length} errors !`) console.debug(`metrics/compute/${login} > ${errors.length} errors !`)
if (die) if (die)
throw new Error("An error occured during rendering, dying") throw new Error("An error occurred during rendering, dying")
else else
console.debug(util.inspect(errors, {depth: Infinity, maxStringLength: 256})) console.debug(util.inspect(errors, {depth: Infinity, maxStringLength: 256}))
} }
@@ -117,7 +117,7 @@ export default async function metrics({login, q}, {graphql, rest, plugins, conf,
console.debug(`metrics/compute/${login}/embed > ${name} >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`) console.debug(`metrics/compute/${login}/embed > ${name} >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`)
if ((!name) || (typeof q !== "object") || (q === null)) { if ((!name) || (typeof q !== "object") || (q === null)) {
if (die) if (die)
throw new Error("An error occured during embed rendering, dying") throw new Error("An error occurred during embed rendering, dying")
return "<p>⚠️ Failed to execute embed function: invalid arguments</p>" return "<p>⚠️ Failed to execute embed function: invalid arguments</p>"
} }
console.debug(`metrics/compute/${login} > embed called with`) console.debug(`metrics/compute/${login} > embed called with`)
@@ -142,7 +142,7 @@ export default async function metrics({login, q}, {graphql, rest, plugins, conf,
//Compute rendering //Compute rendering
const {rendered} = await metrics({login, q}, {...arguments[1], convert: ["svg", "png", "jpeg"].includes(q["config.output"]) ? q["config.output"] : null}, arguments[2]) const {rendered} = await metrics({login, q}, {...arguments[1], convert: ["svg", "png", "jpeg"].includes(q["config.output"]) ? q["config.output"] : null}, arguments[2])
console.debug(`metrics/compute/${login}/embed > ${name} > success >>>>>>>>>>>>>>>>>>>>>>`) console.debug(`metrics/compute/${login}/embed > ${name} > success >>>>>>>>>>>>>>>>>>>>>>`)
return `<img class="metrics-cachable" data-name="${name}" src="data:image/${{png: "png", jpeg: "jpeg"}[q["config.output"]] ?? "svg+xml"};base64,${Buffer.from(rendered).toString("base64")}">` return `<img class="metrics-cacheable" data-name="${name}" src="data:image/${{png: "png", jpeg: "jpeg"}[q["config.output"]] ?? "svg+xml"};base64,${Buffer.from(rendered).toString("base64")}">`
} }
//Rendering template source //Rendering template source
let rendered = source.replace(/\{\{ (?<content>[\s\S]*?) \}\}/g, "{%= $<content> %}") let rendered = source.replace(/\{\{ (?<content>[\s\S]*?) \}\}/g, "{%= $<content> %}")

View File

@@ -63,7 +63,7 @@ export default async function presets(list, {log = true, core = null} = {}) {
catch (error) { catch (error) {
if (env === "action") if (env === "action")
console.log(`::warning::skipping preset ${file}: ${error.message}`) console.log(`::warning::skipping preset ${file}: ${error.message}`)
logger(`metrics/presets > an error occured while loading preset ${file} (${error}), ignoring`) logger(`metrics/presets > an error occurred while loading preset ${file} (${error}), ignoring`)
} }
} }
return options return options

View File

@@ -269,7 +269,7 @@ export async function spawn(command, args = [], options = {}, {prefixed = true,
}) })
} }
/**Check command existance */ /**Check command existence */
export async function which(command) { export async function which(command) {
try { try {
console.debug(`metrics/command > checking existence of ${command}`) console.debug(`metrics/command > checking existence of ${command}`)
@@ -282,7 +282,7 @@ export async function which(command) {
return false return false
} }
/**Code hightlighter */ /**Code highlighter */
export function highlight(code, lang) { export function highlight(code, lang) {
return lang in prism.languages ? prism.highlight(code, prism.languages[lang]) : code return lang in prism.languages ? prism.highlight(code, prism.languages[lang]) : code
} }
@@ -479,7 +479,7 @@ export const svg = {
console.debug("metrics/svg/resize > successfully executed user javascript") console.debug("metrics/svg/resize > successfully executed user javascript")
} }
catch (error) { catch (error) {
console.debug(`an error occured while evaluating script: ${error}`) console.debug(`an error occurred while evaluating script: ${error}`)
} }
} }
//Disable animations //Disable animations
@@ -510,7 +510,7 @@ export const svg = {
)) ))
} }
catch (error) { catch (error) {
console.debug(`metrics/svg/resize > an error occured: ${error}`) console.debug(`metrics/svg/resize > an error occurred: ${error}`)
throw error throw error
} }
//Convert if required //Convert if required

View File

@@ -69,7 +69,7 @@
<small>{{ requests.rest.remaining }} REST / {{ requests.graphql.remaining }} GraphQL / {{ requests.search.remaining }} search</small> <small>{{ requests.rest.remaining }} REST / {{ requests.graphql.remaining }} GraphQL / {{ requests.search.remaining }} search</small>
<small class="warning" v-if="preview"> <small class="warning" v-if="preview">
Metrics are rendered by <a href="https://metrics.lecoq.io/">metrics.lecoq.io</a> in preview mode. Metrics are rendered by <a href="https://metrics.lecoq.io/">metrics.lecoq.io</a> in preview mode.
Any backend editions won't be reflected but client-side rendering can still be tested. Any backend changes won't be reflected but client-side rendering can still be tested.
</small> </small>
<div class="warning" v-if="unusable.length"> <div class="warning" v-if="unusable.length">
The following plugins options are not available on this web instance: {{ unusable.join(", ") }} The following plugins options are not available on this web instance: {{ unusable.join(", ") }}

View File

@@ -76,7 +76,7 @@
<div class="about"> <div class="about">
<small class="warning mb1" v-if="preview"> <small class="warning mb1" v-if="preview">
Metrics are rendered by <a href="https://metrics.lecoq.io/">metrics.lecoq.io</a> in preview mode.<br> Metrics are rendered by <a href="https://metrics.lecoq.io/">metrics.lecoq.io</a> in preview mode.<br>
Any backend editions won't be reflected but client-side rendering can still be tested. Any backend changes won't be reflected but client-side rendering can still be tested.
</small> </small>
<div class="warning mb1" v-if="(!requests.rest.remaining)||(!requests.graphql.remaining)"> <div class="warning mb1" v-if="(!requests.rest.remaining)||(!requests.graphql.remaining)">
This web instance has run out of GitHub API requests. This web instance has run out of GitHub API requests.

View File

@@ -79,7 +79,7 @@
</div> </div>
<small class="warning" v-if="preview"> <small class="warning" v-if="preview">
Metrics insights are rendered by <a href="https://metrics.lecoq.io/">metrics.lecoq.io</a> in preview mode.<br> Metrics insights are rendered by <a href="https://metrics.lecoq.io/">metrics.lecoq.io</a> in preview mode.<br>
Any backend editions won't be reflected but client-side rendering can still be tested. Any backend changes won't be reflected but client-side rendering can still be tested.
</small> </small>
</section> </section>

View File

@@ -7,7 +7,7 @@ Plugins provide additional content and lets you customize rendered metrics.
* **Core plugins** * **Core plugins**
* [🗃️ Base content <sub>`base`</sub>](/source/plugins/base/README.md) * [🗃️ Base content <sub>`base`</sub>](/source/plugins/base/README.md)
* [🧱 Core <sub>`core`</sub>](/source/plugins/core/README.md) * [🧱 Core <sub>`core`</sub>](/source/plugins/core/README.md)
* **Github plugins** * **GitHub plugins**
* [🏆 Achievements <sub>`achievements`</sub>](/source/plugins/achievements/README.md) * [🏆 Achievements <sub>`achievements`</sub>](/source/plugins/achievements/README.md)
* [📰 Recent activity <sub>`activity`</sub>](/source/plugins/activity/README.md) * [📰 Recent activity <sub>`activity`</sub>](/source/plugins/activity/README.md)
* [📆 Commit calendar <sub>`calendar`</sub>](/source/plugins/calendar/README.md) * [📆 Commit calendar <sub>`calendar`</sub>](/source/plugins/calendar/README.md)

View File

@@ -141,7 +141,7 @@ All product and company names are trademarks™ or registered® trademarks of th
<li><code>release</code>: Publication of new releases</li> <li><code>release</code>: Publication of new releases</li>
<li><code>review</code>: Review of pull requests</li> <li><code>review</code>: Review of pull requests</li>
<li><code>comment</code>: Comments on commits, issues and pull requests</li> <li><code>comment</code>: Comments on commits, issues and pull requests</li>
<li><code>wiki</code>: Edition of wiki pages</li> <li><code>wiki</code>: Changes of wiki pages</li>
<li><code>fork</code>: Forking of repositories</li> <li><code>fork</code>: Forking of repositories</li>
<li><code>star</code>: Starring of repositories</li> <li><code>star</code>: Starring of repositories</li>
<li><code>public</code>: Repositories made public</li> <li><code>public</code>: Repositories made public</li>

View File

@@ -73,7 +73,7 @@ export default async function({login, data, rest, q, account, imports}, {enabled
const {forkee: {full_name: forked}} = payload const {forkee: {full_name: forked}} = payload
return {type: "fork", actor, timestamp, repo, forked} return {type: "fork", actor, timestamp, repo, forked}
} }
//Wiki editions //Wiki changes
case "GollumEvent": { case "GollumEvent": {
const {pages} = payload const {pages} = payload
return {type: "wiki", actor, timestamp, repo, pages: pages.map(({title}) => title)} return {type: "wiki", actor, timestamp, repo, pages: pages.map(({title}) => title)}

View File

@@ -94,7 +94,7 @@ inputs:
- `release`: Publication of new releases - `release`: Publication of new releases
- `review`: Review of pull requests - `review`: Review of pull requests
- `comment`: Comments on commits, issues and pull requests - `comment`: Comments on commits, issues and pull requests
- `wiki`: Edition of wiki pages - `wiki`: Changes of wiki pages
- `fork`: Forking of repositories - `fork`: Forking of repositories
- `star`: Starring of repositories - `star`: Starring of repositories
- `public`: Repositories made public - `public`: Repositories made public

View File

@@ -68,7 +68,7 @@ export default async function({login, data, queries, imports, q, account}, {enab
const {data: {data: {User: {favourites: {[type]: {nodes, pageInfo: cursor}}}}}} = await imports.axios.post("https://graphql.anilist.co", {variables: {name: user, page}, query: queries.anilist.favorites({type})}) const {data: {data: {User: {favourites: {[type]: {nodes, pageInfo: cursor}}}}}} = await imports.axios.post("https://graphql.anilist.co", {variables: {name: user, page}, query: queries.anilist.favorites({type})})
page++ page++
next = cursor.hasNextPage next = cursor.hasNextPage
list.push(...await Promise.all(nodes.map(media => format({media: {progess: null, score: null, media}, imports})))) list.push(...await Promise.all(nodes.map(media => format({media: {progress: null, score: null, media}, imports}))))
} }
catch (error) { catch (error) {
if (await retry({login, imports, error})) if (await retry({login, imports, error}))

View File

@@ -179,7 +179,7 @@ Broad affiliations will result in less representative metrics.</p>
<td nowrap="nowrap">⏭️ Global option<br> <td nowrap="nowrap">⏭️ Global option<br>
⏯️ Cannot be preset<br> ⏯️ Cannot be preset<br>
<b>type:</b> <code>array</code> <b>type:</b> <code>array</code>
<i>(comma-seperated)</i> <i>(comma-separated)</i>
<br> <br>
<b>default:</b> <code>→ User login</code><br></td> <b>default:</b> <code>→ User login</code><br></td>
</tr> </tr>

View File

@@ -127,7 +127,7 @@ inputs:
Specify names, surnames, username, email addresses that has been used in the past that can be used to detect commits ownerships in some plugins Specify names, surnames, username, email addresses that has been used in the past that can be used to detect commits ownerships in some plugins
type: array type: array
format: comma-seperated format: comma-separated
default: .user.login default: .user.login
example: lowlighter, lowlighter@users.noreply.github.com example: lowlighter, lowlighter@users.noreply.github.com
global: yes global: yes

View File

@@ -53,10 +53,10 @@ Be sure to read [contribution guide](/CONTRIBUTING.md) and [architecture](/ARCHI
Please respect the following guidelines: Please respect the following guidelines:
- A plugin should be independant and should not rely on other plugins - A plugin should be independent and should not rely on other plugins
- [🧱 core](/source/plugins/core/README.md) and [🗃️ base](/source/plugins/base/README.md) output can be reused though - [🧱 core](/source/plugins/core/README.md) and [🗃️ base](/source/plugins/base/README.md) output can be reused though
- A plugin should never edit its original arguments, as it is shared amongst other plugins and would create unattended side effects - A plugin should never edit its original arguments, as it is shared amongst other plugins and would create unattended side effects
- Use `imports.metadata.plugins.{plugin-name}.inputs()` to automatically typecheck and default user inputs through defined `metadata.yml` - Use `imports.metadata.plugins.{plugin-name}.inputs()` to automatically type check and default user inputs through defined `metadata.yml`
- Plugin options should respect the "lexical field" of existing option to keep consistency - Plugin options should respect the "lexical field" of existing option to keep consistency
- Plugin errors should be handled gracefully by partials with error message - Plugin errors should be handled gracefully by partials with error message
- New dependencies should be avoided, consider using existing `imports` - New dependencies should be avoided, consider using existing `imports`
@@ -229,7 +229,7 @@ export default async function(
{ {
login, //GitHub username login, //GitHub username
q, //Raw user inputs (dot notation without plugin_ prefix, don't use it directly) q, //Raw user inputs (dot notation without plugin_ prefix, don't use it directly)
imports, //Various utilitaires (axios, puppeteer, fs, etc., see /source/app/metrics/utils.mjs) imports, //Various utilities (axios, puppeteer, fs, etc., see /source/app/metrics/utils.mjs)
data, //Raw data from core/base plugin data, //Raw data from core/base plugin
computed, //Computed data from core/base plugin computed, //Computed data from core/base plugin
rest, //Rest authenticated GitHub octokit rest, //Rest authenticated GitHub octokit

View File

@@ -92,7 +92,7 @@ Tap "Copy to Clipboard"
It should result in something like `Haha, check out the places I've pooped on Poop Map https://api.poopmap.net/map?token=xxxxxxxxxx` copied. It should result in something like `Haha, check out the places I've pooped on Poop Map https://api.poopmap.net/map?token=xxxxxxxxxx` copied.
Extract the `token` query paramater from the link and use it in `plugin_poopmap_token`. Extract the `token` query parameter from the link and use it in `plugin_poopmap_token`.
This token will not expire and it will be able to access only public details. This token will not expire and it will be able to access only public details.
## Examples workflows ## Examples workflows

View File

@@ -21,7 +21,7 @@ export default async function({login, q, imports, data, account}, {enabled = fal
headers: {"x-rapidapi-key": token}, headers: {"x-rapidapi-key": token},
}) })
//Query API for sotck charts //Query API for stock charts
console.debug(`metrics/compute/${login}/plugins > stock > querying api for stock`) console.debug(`metrics/compute/${login}/plugins > stock > querying api for stock`)
const {data: {chart: {result: [{meta, timestamp, indicators: {quote: [{close}]}}]}}} = await imports.axios.get("https://yh-finance.p.rapidapi.com/stock/v2/get-chart", { const {data: {chart: {result: [{meta, timestamp, indicators: {quote: [{close}]}}]}}} = await imports.axios.get("https://yh-finance.p.rapidapi.com/stock/v2/get-chart", {
params: {interval, symbol, range: duration, region: "US"}, params: {interval, symbol, range: duration, region: "US"},

View File

@@ -107,7 +107,7 @@ All product and company names are trademarks™ or registered® trademarks of th
<td nowrap="nowrap"><h4><code>plugin_contributors_categories</code></h4></td> <td nowrap="nowrap"><h4><code>plugin_contributors_categories</code></h4></td>
<td rowspan="2"><p>Contribution categories</p> <td rowspan="2"><p>Contribution categories</p>
<p>This option requires <a href="/source/plugins/contributors/README.md#plugin_contributors_sections"><code>plugin_contributors_sections</code></a> to have <code>categories</code> in it to be effective. <p>This option requires <a href="/source/plugins/contributors/README.md#plugin_contributors_sections"><code>plugin_contributors_sections</code></a> to have <code>categories</code> in it to be effective.
Pass a JSON object mapping category with fileglobs</p> Pass a JSON object mapping category with file globs</p>
<img width="900" height="1" alt=""></td> <img width="900" height="1" alt=""></td>
</tr> </tr>
<tr> <tr>
@@ -130,9 +130,9 @@ Pass a JSON object mapping category with fileglobs</p>
## 🗂️ Setting up contribution categories ## 🗂️ Setting up contribution categories
Pass a JSON object to `plugin_contributors_categories` with categories names as keys and arrays of fileglobs as values to configure contributions categories. Pass a JSON object to `plugin_contributors_categories` with categories names as keys and arrays of file globs as values to configure contributions categories.
Each modified file by a contributor matching a fileglob will add them in said category. Each modified file by a contributor matching a file glob will add them in said category.
> 💡 File matching respect keys order > 💡 File matching respect keys order

View File

@@ -109,7 +109,7 @@ export default async function({login, q, imports, data, rest, graphql, queries,
} }
catch (error) { catch (error) {
console.debug(error) console.debug(error)
console.debug(`metrics/compute/${login}/plugins > contributors > an error occured while processing ${repository}`) console.debug(`metrics/compute/${login}/plugins > contributors > an error occurred while processing ${repository}`)
} }
finally { finally {
//Cleaning //Cleaning

View File

@@ -70,7 +70,7 @@ inputs:
Contribution categories Contribution categories
This option requires [`plugin_contributors_sections`](/source/plugins/contributors/README.md#plugin_contributors_sections) to have `categories` in it to be effective. This option requires [`plugin_contributors_sections`](/source/plugins/contributors/README.md#plugin_contributors_sections) to have `categories` in it to be effective.
Pass a JSON object mapping category with fileglobs Pass a JSON object mapping category with file globs
type: json type: json
default: | default: |
{ {

View File

@@ -55,7 +55,7 @@ Content can be manually ordered using `config_order` option.
> 💡 Omitted sections will be appended at the end using default order > 💡 Omitted sections will be appended at the end using default order
> The handles to use for each plugin and sections is based on the [`partials/_.json`](/source/templates/classic/partials/_.json) of the template. > The handles to use for each plugin and sections is based on the [`partials/_.json`](/source/templates/classic/partials/_.json) of the template.
> It may not necessarly be the plugin id (e.g. `base.header`, `base.activity+community`, `base.repositories`, etc.). > It may not necessarily be the plugin id (e.g. `base.header`, `base.activity+community`, `base.repositories`, etc.).
## 🪛 Using presets ## 🪛 Using presets
@@ -74,7 +74,7 @@ Options resolution is done in the following order:
config_presets: https://raw.githubusercontent.com/lowlighter/metrics/presets/lunar-red/preset.yaml config_presets: https://raw.githubusercontent.com/lowlighter/metrics/presets/lunar-red/preset.yaml
``` ```
Some presets are hosted on this repository on the [`@presets`](https://github.com/lowlighter/metrics/tree/presets) branch and can be used directly by using using their identifier prefixed by an arobase (`@`). Some presets are hosted on this repository on the [`@presets`](https://github.com/lowlighter/metrics/tree/presets) branch and can be used directly by using their identifier prefixed by an arobase (`@`).
*Example: using a pre-defined configuration preset* *Example: using a pre-defined configuration preset*
```yaml ```yaml
@@ -122,7 +122,7 @@ Additional JavaScript can be injected using `extras_js` option.
``` ```
> JavaScript is executed in puppeteer context during the rendering phase, **not** in *metrics* context. > JavaScript is executed in puppeteer context during the rendering phase, **not** in *metrics* context.
> It will be possible to access `document` and all other features accessibles like if the SVG was opened in a browser page > It will be possible to access `document` and all other features accessible like if the SVG was opened in a browser page
> 💡 If you make an heavy use of this option, creating a [community templates](/source/templates/community/README.md) may be a better alternative > 💡 If you make an heavy use of this option, creating a [community templates](/source/templates/community/README.md) may be a better alternative
@@ -304,7 +304,7 @@ metrics:
### Manual handling ### Manual handling
Use `config_ouput: none` to perform custom processing with outputs. Use `config_output: none` to perform custom processing with outputs.
They will be available under `/metrics_renders/{filename}` in the runner. They will be available under `/metrics_renders/{filename}` in the runner.
*Example: generate outputs and manually push them* *Example: generate outputs and manually push them*
@@ -336,7 +336,7 @@ metrics:
## ♻️ Retrying automatically failed rendering and output action ## ♻️ Retrying automatically failed rendering and output action
Rendering is subject to external factors and can fail ocassionaly. Rendering is subject to external factors and can fail occasionally.
Use `retries` and `retries_delay` options to automatically retry rendering. Use `retries` and `retries_delay` options to automatically retry rendering.
*Example: retry render up to 3 times (wait 5 minutes between each fail)* *Example: retry render up to 3 times (wait 5 minutes between each fail)*
@@ -347,7 +347,7 @@ Use `retries` and `retries_delay` options to automatically retry rendering.
retries_delay: 300 retries_delay: 300
``` ```
Output action is also subject to GitHub API rate-limiting and overall health status and can fail ocassionaly. Output action is also subject to GitHub API rate-limiting and overall health status and can fail occasionally.
Use `retries_output_action` and `retries_delay_output_action` options to automatically retry output action. Use `retries_output_action` and `retries_delay_output_action` options to automatically retry output action.
> 💡 As output action is a separate step from rendering, render step won't be called again > 💡 As output action is a separate step from rendering, render step won't be called again
@@ -362,7 +362,7 @@ Use `retries_output_action` and `retries_delay_output_action` options to automat
## 🗜️ Optimize SVG output ## 🗜️ Optimize SVG output
To reduce filesize and decrease loading time, *metrics* offers several optimization options, such as purging unused CSS and style minification, XML pretty-pretting (which also reduce diffs between changes) and general SVG optimation (still experimental). To reduce filesize and decrease loading time, *metrics* offers several optimization options, such as purging unused CSS and style minification, XML pretty-printing (which also reduce diffs between changes) and general SVG optimization (still experimental).
> 💡 This option is enabled by default! > 💡 This option is enabled by default!
@@ -525,9 +525,9 @@ When doing so, any settings which defaults on user fetched values will not be te
<li><code>none</code>: just create file in <code>/metrics_renders</code> directory of action runner</li> <li><code>none</code>: just create file in <code>/metrics_renders</code> directory of action runner</li>
<li><code>commit</code>: push output to <code>committer_branch</code></li> <li><code>commit</code>: push output to <code>committer_branch</code></li>
<li><code>pull-request</code>: push output to a new branch and open a pull request to <code>committer_branch</code></li> <li><code>pull-request</code>: push output to a new branch and open a pull request to <code>committer_branch</code></li>
<li><code>pull-request-merge</code>: same as <code>pull-request</code> and additionaly merge pull request</li> <li><code>pull-request-merge</code>: same as <code>pull-request</code> and additionally merge pull request</li>
<li><code>pull-request-squash</code>: same as <code>pull-request</code> and additionaly squash and merge pull request</li> <li><code>pull-request-squash</code>: same as <code>pull-request</code> and additionally squash and merge pull request</li>
<li><code>pull-request-rebase</code>: same as <code>pull-request</code> and additionaly rebase and merge pull request</li> <li><code>pull-request-rebase</code>: same as <code>pull-request</code> and additionally rebase and merge pull request</li>
<li><code>gist</code>: push output to <code>committer_gist</code></li> <li><code>gist</code>: push output to <code>committer_gist</code></li>
</ul> </ul>
<blockquote> <blockquote>
@@ -752,7 +752,7 @@ Size must be a supported icon size (12, 16 or 24).
<tr> <tr>
<td nowrap="nowrap"><h4><code>config_base64</code></h4></td> <td nowrap="nowrap"><h4><code>config_base64</code></h4></td>
<td rowspan="2"><p>Base64-encoded images</p> <td rowspan="2"><p>Base64-encoded images</p>
<p>Enable this option to make self-contained ouput (i.e. with no external links)</p> <p>Enable this option to make self-contained output (i.e. with no external links)</p>
<img width="900" height="1" alt=""></td> <img width="900" height="1" alt=""></td>
</tr> </tr>
<tr> <tr>

View File

@@ -146,7 +146,7 @@ export default async function({login, q}, {conf, data, rest, graphql, plugins, q
} }
if (dflags.includes("--halloween")) { if (dflags.includes("--halloween")) {
console.debug(`metrics/compute/${login} > applying dflag --halloween`) console.debug(`metrics/compute/${login} > applying dflag --halloween`)
//Haloween color replacer //Halloween color replacer
const halloween = content => const halloween = content =>
content content
.replace(/--color-calendar-graph/g, "--color-calendar-halloween-graph") .replace(/--color-calendar-graph/g, "--color-calendar-halloween-graph")

View File

@@ -100,9 +100,9 @@ inputs:
- `none`: just create file in `/metrics_renders` directory of action runner - `none`: just create file in `/metrics_renders` directory of action runner
- `commit`: push output to `committer_branch` - `commit`: push output to `committer_branch`
- `pull-request`: push output to a new branch and open a pull request to `committer_branch` - `pull-request`: push output to a new branch and open a pull request to `committer_branch`
- `pull-request-merge`: same as `pull-request` and additionaly merge pull request - `pull-request-merge`: same as `pull-request` and additionally merge pull request
- `pull-request-squash`: same as `pull-request` and additionaly squash and merge pull request - `pull-request-squash`: same as `pull-request` and additionally squash and merge pull request
- `pull-request-rebase`: same as `pull-request` and additionaly rebase and merge pull request - `pull-request-rebase`: same as `pull-request` and additionally rebase and merge pull request
- `gist`: push output to `committer_gist` - `gist`: push output to `committer_gist`
> 💡 When using `pull-request`, you will need to set the last job with a `pull-request-*` action instead, else it won't be merged > 💡 When using `pull-request`, you will need to set the last job with a `pull-request-*` action instead, else it won't be merged
@@ -291,7 +291,7 @@ inputs:
description: | description: |
Base64-encoded images Base64-encoded images
Enable this option to make self-contained ouput (i.e. with no external links) Enable this option to make self-contained output (i.e. with no external links)
type: boolean type: boolean
default: yes default: yes
global: yes global: yes

View File

@@ -82,7 +82,7 @@ export default async function({login, data, computed, imports, q, graphql, queri
} }
catch (error) { catch (error) {
console.debug(error) console.debug(error)
console.debug(`metrics/compute/${login}/plugins > followup > an error occured while processing ${owner}/${repo}, skipping...`) console.debug(`metrics/compute/${login}/plugins > followup > an error occurred while processing ${owner}/${repo}, skipping...`)
} }
} }
} }

View File

@@ -20,7 +20,7 @@ All product and company names are trademarks™ or registered® trademarks of th
<tr> <tr>
<td colspan="2" align="center"> <td colspan="2" align="center">
<details open><summary>Recent activity charts</summary><img src="https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.charts.svg" alt=""></img></details> <details open><summary>Recent activity charts</summary><img src="https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.charts.svg" alt=""></img></details>
<details open><summary>Midly interesting facts</summary><img src="https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.facts.svg" alt=""></img></details> <details open><summary>Mildly interesting facts</summary><img src="https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.facts.svg" alt=""></img></details>
<img width="900" height="1" alt=""> <img width="900" height="1" alt="">
</td> </td>
</tr> </tr>
@@ -73,7 +73,7 @@ All product and company names are trademarks™ or registered® trademarks of th
</tr> </tr>
<tr> <tr>
<td nowrap="nowrap"><h4><code>plugin_habits_facts</code></h4></td> <td nowrap="nowrap"><h4><code>plugin_habits_facts</code></h4></td>
<td rowspan="2"><p>Midly interesting facts</p> <td rowspan="2"><p>Mildly interesting facts</p>
<p>It includes indentation type, average number of characters per line of code, and most active time and day</p> <p>It includes indentation type, average number of characters per line of code, and most active time and day</p>
<img width="900" height="1" alt=""></td> <img width="900" height="1" alt=""></td>
</tr> </tr>
@@ -174,7 +174,7 @@ Configure `config_timezone` (see [supported timezone](https://en.wikipedia.org/w
<!--examples--> <!--examples-->
```yaml ```yaml
name: Midly interesting facts name: Mildly interesting facts
uses: lowlighter/metrics@latest uses: lowlighter/metrics@latest
with: with:
filename: metrics.plugin.habits.facts.svg filename: metrics.plugin.habits.facts.svg

View File

@@ -1,4 +1,4 @@
- name: Midly interesting facts - name: Mildly interesting facts
uses: lowlighter/metrics@latest uses: lowlighter/metrics@latest
with: with:
filename: metrics.plugin.habits.facts.svg filename: metrics.plugin.habits.facts.svg

View File

@@ -64,7 +64,7 @@ export default async function({login, data, rest, imports, q, account}, {enabled
habits.commits.days[day] = (habits.commits.days[day] ?? 0) + 1 habits.commits.days[day] = (habits.commits.days[day] ?? 0) + 1
habits.commits.days.max = Math.max(...Object.values(habits.commits.days)) habits.commits.days.max = Math.max(...Object.values(habits.commits.days))
//Compute day with most commits //Compute day with most commits
habits.commits.day = days.length ? ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][Object.entries(habits.commits.days).sort(([_an, a], [_bn, b]) => b - a).map(([day, _occurence]) => day)[0]] ?? NaN : NaN habits.commits.day = days.length ? ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][Object.entries(habits.commits.days).sort(([_an, a], [_bn, b]) => b - a).map(([day, _occurrence]) => day)[0]] ?? NaN : NaN
} }
//Commit hour //Commit hour
@@ -76,7 +76,7 @@ export default async function({login, data, rest, imports, q, account}, {enabled
habits.commits.hours[hour] = (habits.commits.hours[hour] ?? 0) + 1 habits.commits.hours[hour] = (habits.commits.hours[hour] ?? 0) + 1
habits.commits.hours.max = Math.max(...Object.values(habits.commits.hours)) habits.commits.hours.max = Math.max(...Object.values(habits.commits.hours))
//Compute hour with most commits //Compute hour with most commits
habits.commits.hour = hours.length ? `${Object.entries(habits.commits.hours).sort(([_an, a], [_bn, b]) => b - a).map(([hour, _occurence]) => hour)[0]}`.padStart(2, "0") : NaN habits.commits.hour = hours.length ? `${Object.entries(habits.commits.hours).sort(([_an, a], [_bn, b]) => b - a).map(([hour, _occurrence]) => hour)[0]}`.padStart(2, "0") : NaN
} }
//Indent style //Indent style

View File

@@ -4,7 +4,7 @@ description: |
This plugin displays coding habits based on recent activity, such as active hours and languages recently used. This plugin displays coding habits based on recent activity, such as active hours and languages recently used.
examples: examples:
+recent activity charts: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.charts.svg +recent activity charts: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.charts.svg
+midly interesting facts: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.facts.svg +mildly interesting facts: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.habits.facts.svg
index: 7 index: 7
supports: supports:
- user - user
@@ -39,7 +39,7 @@ inputs:
plugin_habits_facts: plugin_habits_facts:
description: | description: |
Midly interesting facts Mildly interesting facts
It includes indentation type, average number of characters per line of code, and most active time and day It includes indentation type, average number of characters per line of code, and most active time and day
type: boolean type: boolean

View File

@@ -239,7 +239,7 @@ It will be automatically hidden if empty.</p>
The default algorithm use the top languages provided of each repository you contributed to. The default algorithm use the top languages provided of each repository you contributed to.
When working in collaborative projects with a lot of people, these numbers may be less representative of your actual work. When working in collaborative projects with a lot of people, these numbers may be less representative of your actual work.
The `plugin_languages_indepth` option lets you use a more advanced algorithm for more accurates statistics. The `plugin_languages_indepth` option lets you use a more advanced algorithm for more accurate statistics.
Under the hood, it will clone your repositories, run [linguist-js](https://github.com/Nixinova/Linguist) (a JavaScript port of [GitHub linguist](https://github.com/github/linguist)) and iterate over patches matching your `commits_authoring` setting. Under the hood, it will clone your repositories, run [linguist-js](https://github.com/Nixinova/Linguist) (a JavaScript port of [GitHub linguist](https://github.com/github/linguist)) and iterate over patches matching your `commits_authoring` setting.
Since git lets you use any email and username for commits, *metrics* may not be able to detect a commit ownership if it isn't the same as your GitHub personal data. By default, it will use your GitHub username, but you can configure additional matching usernames and email addresses using `commits_authoring` option. Since git lets you use any email and username for commits, *metrics* may not be able to detect a commit ownership if it isn't the same as your GitHub personal data. By default, it will use your GitHub username, but you can configure additional matching usernames and email addresses using `commits_authoring` option.
@@ -326,7 +326,7 @@ It is possible to use custom colors using `plugin_languages_colors` option.
The following syntaxes are supported: The following syntaxes are supported:
- A predefined set from [colorsets.json](colorsets.json) *(support limited to 8 languages max)* - A predefined set from [colorsets.json](colorsets.json) *(support limited to 8 languages max)*
- `${language}:${color}` to change the color of a language *(case insensitive)* - `${language}:${color}` to change the color of a language *(case insensitive)*
- `${n}:${color}` to change the color of the the n-th language - `${n}:${color}` to change the color of the n-th language
Both hexadecimal and [named color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) are supported. Both hexadecimal and [named color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) are supported.

View File

@@ -32,7 +32,7 @@ export async function indepth({login, data, imports, repositories, gpg}, {skippe
} }
} }
catch (error) { catch (error) {
console.debug(`metrics/compute/${login}/plugins > languages > indepth > an error occured while importing gpg ${id}, skipping...`) console.debug(`metrics/compute/${login}/plugins > languages > indepth > an error occurred while importing gpg ${id}, skipping...`)
} }
finally { finally {
//Cleaning //Cleaning
@@ -73,7 +73,7 @@ export async function indepth({login, data, imports, repositories, gpg}, {skippe
await analyze(arguments[0], {results, path, categories}) await analyze(arguments[0], {results, path, categories})
} }
catch (error) { catch (error) {
console.debug(`metrics/compute/${login}/plugins > languages > indepth > an error occured while processing ${repo}, skipping...`) console.debug(`metrics/compute/${login}/plugins > languages > indepth > an error occurred while processing ${repo}, skipping...`)
} }
finally { finally {
//Cleaning //Cleaning
@@ -184,7 +184,7 @@ export async function recent({login, data, imports, rest, account}, {skipped = [
} }
} }
catch { catch {
console.debug(`metrics/compute/${login}/plugins > languages > an error occured while processing recently used languages`) console.debug(`metrics/compute/${login}/plugins > languages > an error occurred while processing recently used languages`)
} }
finally { finally {
//Cleaning //Cleaning
@@ -269,7 +269,7 @@ async function analyze({login, imports, data}, {results, path, categories = ["pr
} }
} }
catch (error) { catch (error) {
console.debug(`metrics/compute/${login}/plugins > languages > indepth > an error occured while processing line (${error.message}), skipping...`) console.debug(`metrics/compute/${login}/plugins > languages > indepth > an error occurred while processing line (${error.message}), skipping...`)
} }
}, },
}) })
@@ -279,7 +279,7 @@ async function analyze({login, imports, data}, {results, path, categories = ["pr
} }
} }
catch { catch {
console.debug(`metrics/compute/${login}/plugins > languages > indepth > an error occured on page ${page}, skipping...`) console.debug(`metrics/compute/${login}/plugins > languages > indepth > an error occurred on page ${page}, skipping...`)
results.missed.commits += per_page results.missed.commits += per_page
} }
} }

View File

@@ -33,7 +33,7 @@ export default async function({login, data, imports, rest, q, account}, {enabled
//Check if data are available //Check if data are available
if (!Array.isArray(stats)) if (!Array.isArray(stats))
return return
//Compute editions //Compute changes
repos[handle] = {added: 0, deleted: 0, changed: 0} repos[handle] = {added: 0, deleted: 0, changed: 0}
const contributors = stats.filter(({author}) => context.mode === "repository" ? true : author?.login?.toLocaleLowerCase() === login.toLocaleLowerCase()) const contributors = stats.filter(({author}) => context.mode === "repository" ? true : author?.login?.toLocaleLowerCase() === login.toLocaleLowerCase())
for (const contributor of contributors) { for (const contributor of contributors) {
@@ -42,7 +42,7 @@ export default async function({login, data, imports, rest, q, account}, {enabled
added += a added += a
deleted += d deleted += d
changed += c changed += c
//Compute editions per week //Compute changes per week
const date = new Date(w * 1000).toISOString().substring(0, 10) const date = new Date(w * 1000).toISOString().substring(0, 10)
if (!weeks[date]) if (!weeks[date])
weeks[date] = {added: 0, deleted: 0, changed: 0} weeks[date] = {added: 0, deleted: 0, changed: 0}

View File

@@ -106,7 +106,7 @@ All product and company names are trademarks™ or registered® trademarks of th
<li><code>recent</code>: display recently listened tracks</li> <li><code>recent</code>: display recently listened tracks</li>
<li><code>top</code>: display top listened artists/tracks</li> <li><code>top</code>: display top listened artists/tracks</li>
</ul> </ul>
<p>If <a href="/source/plugins/music/README.md#plugin_music_playlist"><code>plugin_music_playlist</code></a> is specifed, the default value is <code>playlist</code>, else it is <code>recent</code></p> <p>If <a href="/source/plugins/music/README.md#plugin_music_playlist"><code>plugin_music_playlist</code></a> is specified, the default value is <code>playlist</code>, else it is <code>recent</code></p>
<img width="900" height="1" alt=""></td> <img width="900" height="1" alt=""></td>
</tr> </tr>
<tr> <tr>
@@ -262,7 +262,7 @@ Extract the source link from the code pasted in your clipboard:
*(Not available)* *(Not available)*
> 😥 Unfortunately I wasn't able to find a workaround to avoid paying the $99 fee for the developer program, even using workarounds like *smart playlists*, *shortcuts* and other stuff. However if you really want this feature, you could [sponsor me](github.com/sponsors/lowlighter) and I could eventually invest in a developper account with enough money, implement it and also eventually offer service on the shared instance > 😥 Unfortunately I wasn't able to find a workaround to avoid paying the $99 fee for the developer program, even using workarounds like *smart playlists*, *shortcuts* and other stuff. However if you really want this feature, you could [sponsor me](github.com/sponsors/lowlighter) and I could eventually invest in a developer account with enough money, implement it and also eventually offer service on the shared instance
### 🔗 Get an embed playlist url for `plugin_music_playlist` ### 🔗 Get an embed playlist url for `plugin_music_playlist`

View File

@@ -50,7 +50,7 @@ export default async function({login, imports, data, q, account}, {enabled = fal
let {provider, mode, playlist, limit, user, "played.at": played_at, "time.range": time_range, "top.type": top_type, token: _token} = imports.metadata.plugins.music.inputs({data, account, q}) let {provider, mode, playlist, limit, user, "played.at": played_at, "time.range": time_range, "top.type": top_type, token: _token} = imports.metadata.plugins.music.inputs({data, account, q})
if ((sandbox) && (_token)) { if ((sandbox) && (_token)) {
token = _token token = _token
console.debug(`metrics/compute/${login}/plugins > music > overriden token value through user inputs as sandbox mode is enabled`) console.debug(`metrics/compute/${login}/plugins > music > overridden token value through user inputs as sandbox mode is enabled`)
} }
if (!imports.metadata.plugins.music.extras("token", {extras, error: false})) if (!imports.metadata.plugins.music.extras("token", {extras, error: false}))
token = "" token = ""
@@ -502,7 +502,7 @@ export default async function({login, imports, data, q, account}, {enabled = fal
} }
} }
//get all objects that have the given key name with recursivity //get all objects that have the given key name with recursively
function get_all_with_key(obj, key) { function get_all_with_key(obj, key) {
const result = [] const result = []
if (obj instanceof Object) { if (obj instanceof Object) {

View File

@@ -72,7 +72,7 @@ inputs:
- `recent`: display recently listened tracks - `recent`: display recently listened tracks
- `top`: display top listened artists/tracks - `top`: display top listened artists/tracks
If [`plugin_music_playlist`](/source/plugins/music/README.md#plugin_music_playlist) is specifed, the default value is `playlist`, else it is `recent` If [`plugin_music_playlist`](/source/plugins/music/README.md#plugin_music_playlist) is specified, the default value is `playlist`, else it is `recent`
type: string type: string
default: "" default: ""
values: values:

View File

@@ -121,7 +121,7 @@ All product and company names are trademarks™ or registered® trademarks of th
<!--examples--> <!--examples-->
```yaml ```yaml
name: Succint report name: Succinct report
uses: lowlighter/metrics@latest uses: lowlighter/metrics@latest
with: with:
filename: metrics.plugin.pagespeed.svg filename: metrics.plugin.pagespeed.svg
@@ -159,7 +159,7 @@ with:
``` ```
```yaml ```yaml
name: Succint report with PWA name: Succinct report with PWA
uses: lowlighter/metrics@latest uses: lowlighter/metrics@latest
with: with:
filename: metrics.plugin.pagespeed.svg filename: metrics.plugin.pagespeed.svg

View File

@@ -1,4 +1,4 @@
- name: Succint report - name: Succinct report
uses: lowlighter/metrics@latest uses: lowlighter/metrics@latest
with: with:
filename: metrics.plugin.pagespeed.svg filename: metrics.plugin.pagespeed.svg
@@ -30,7 +30,7 @@
plugin_pagespeed_token: ${{ secrets.PAGESPEED_TOKEN }} plugin_pagespeed_token: ${{ secrets.PAGESPEED_TOKEN }}
plugin_pagespeed_url: https://lecoq.io plugin_pagespeed_url: https://lecoq.io
- name: Succint report with PWA - name: Succinct report with PWA
uses: lowlighter/metrics@latest uses: lowlighter/metrics@latest
with: with:
filename: metrics.plugin.pagespeed.svg filename: metrics.plugin.pagespeed.svg

View File

@@ -79,7 +79,7 @@ export default async function({login, data, graphql, rest, q, queries, imports,
console.debug(`metrics/compute/${login}/plugins > people > keeping only ${limit} ${type}`) console.debug(`metrics/compute/${login}/plugins > people > keeping only ${limit} ${type}`)
result[type].splice(limit) result[type].splice(limit)
} }
//Hide real avator with identicons if enabled //Hide real avatar with identicons if enabled
if (identicons) { if (identicons) {
console.debug(`metrics/compute/${login}/plugins > people > using identicons`) console.debug(`metrics/compute/${login}/plugins > people > using identicons`)
result[type].map(user => user.avatarUrl = `https://github.com/identicons/${user.login}.png`) result[type].map(user => user.avatarUrl = `https://github.com/identicons/${user.login}.png`)

View File

@@ -38,7 +38,7 @@ export default async function({login, q, imports, data, graphql, queries, accoun
} }
catch (error) { catch (error) {
console.debug(error) console.debug(error)
console.debug(`metrics/compute/${login}/plugins > reactions > an error occured while retrieving ${type}`) console.debug(`metrics/compute/${login}/plugins > reactions > an error occurred while retrieving ${type}`)
} }
} }
console.debug(`metrics/compute/${login}/plugins > reactions > fetched ${comments.length} comments`) console.debug(`metrics/compute/${login}/plugins > reactions > fetched ${comments.length} comments`)

View File

@@ -110,7 +110,7 @@ Using this mode significantly increase file size as each frame is encoded separa
<tr> <tr>
<td nowrap="nowrap"><h4><code>plugin_skyline_settings</code></h4></td> <td nowrap="nowrap"><h4><code>plugin_skyline_settings</code></h4></td>
<td rowspan="2"><p>Advanced settings</p> <td rowspan="2"><p>Advanced settings</p>
<p>Can be configured to use alternate skyline websites different from <a href="https://skyline.github.com">skyline.github.com</a>, such as <a href="https://github.com/honzaap/GitHubCity">honzaap&#39;s GitHub City</a>.</p> <p>Can be configured to use alternate skyline websites different from <a href="https://skyline.github.com">skyline.github.com</a>, such as <a href="https://github.com/honzaap/GithubCity">honzaap&#39;s GitHub City</a>.</p>
<ul> <ul>
<li><code>url</code>: Target URL (mandatory)</li> <li><code>url</code>: Target URL (mandatory)</li>
<li><code>ready</code>: Readiness condition (A JS function that returns a boolean)</li> <li><code>ready</code>: Readiness condition (A JS function that returns a boolean)</li>

View File

@@ -64,7 +64,7 @@ inputs:
description: | description: |
Advanced settings Advanced settings
Can be configured to use alternate skyline websites different from [skyline.github.com](https://skyline.github.com), such as [honzaap's GitHub City](https://github.com/honzaap/GitHubCity). Can be configured to use alternate skyline websites different from [skyline.github.com](https://skyline.github.com), such as [honzaap's GitHub City](https://github.com/honzaap/GithubCity).
- `url`: Target URL (mandatory) - `url`: Target URL (mandatory)
- `ready`: Readiness condition (A JS function that returns a boolean) - `ready`: Readiness condition (A JS function that returns a boolean)

View File

@@ -12,7 +12,7 @@ export default async function({login, q, imports, data, account}, {enabled = fal
if (!limit) if (!limit)
limit = void limit limit = void limit
const showOnlyGithubPublicRepos = repositoriesVisibility === "public" const showOnlyGitHubPublicRepos = repositoriesVisibility === "public"
const range = { const range = {
"7": "last_7_days", "7": "last_7_days",
@@ -26,7 +26,7 @@ export default async function({login, q, imports, data, account}, {enabled = fal
const {data: {data: stats}} = await imports.axios.get(`${url}/api/v1/users/${user}/stats/${range}?api_key=${token}`) const {data: {data: stats}} = await imports.axios.get(`${url}/api/v1/users/${user}/stats/${range}?api_key=${token}`)
const projectStats = stats.projects?.map(({name, percent, total_seconds: total}) => ({name, percent: percent / 100, total})).sort((a, b) => b.percent - a.percent) const projectStats = stats.projects?.map(({name, percent, total_seconds: total}) => ({name, percent: percent / 100, total})).sort((a, b) => b.percent - a.percent)
const projects = showOnlyGithubPublicRepos ? await pickOnlyGithubPublicRepos({limit, login, axios: imports.axios, projects: projectStats}) : projectStats?.slice(0, limit) const projects = showOnlyGitHubPublicRepos ? await pickOnlyGitHubPublicRepos({limit, login, axios: imports.axios, projects: projectStats}) : projectStats?.slice(0, limit)
const result = { const result = {
sections, sections,
@@ -50,7 +50,7 @@ export default async function({login, q, imports, data, account}, {enabled = fal
} }
} }
async function pickOnlyGithubPublicRepos({projects, axios, login, limit}) { async function pickOnlyGitHubPublicRepos({projects, axios, login, limit}) {
const result = [] const result = []
for await (const project of projects) { for await (const project of projects) {

View File

@@ -32,7 +32,7 @@ Since the resulting output is a markdown file, it is possible to do additional f
The templating engine is [EJS](https://github.com/mde/ejs) and can be used to interpolate any data retrieved by metrics. The templating engine is [EJS](https://github.com/mde/ejs) and can be used to interpolate any data retrieved by metrics.
* `<%=` and `%>` are used to display escaped output * `<%=` and `%>` are used to display escaped output
* `{{` and `}}` is also supported as syntaxic sugar * `{{` and `}}` is also supported as syntactic sugar
* `<%-` and `%>` are used to display raw output * `<%-` and `%>` are used to display raw output
* `<%` and `%>` are used to execute JavaScript, and can also contains control statements such as conditionals and loops * `<%` and `%>` are used to execute JavaScript, and can also contains control statements such as conditionals and loops

View File

@@ -1,4 +1,4 @@
- name: 💡 Coding habits and activity - Midly interesting facts - name: 💡 Coding habits and activity - Mildly interesting facts
uses: lowlighter/metrics@latest uses: lowlighter/metrics@latest
with: with:
token: MOCKED_TOKEN token: MOCKED_TOKEN

View File

@@ -1,4 +1,4 @@
- name: ⏱️ Google PageSpeed - Succint report - name: ⏱️ Google PageSpeed - Succinct report
uses: lowlighter/metrics@latest uses: lowlighter/metrics@latest
with: with:
token: NOT_NEEDED token: NOT_NEEDED
@@ -27,7 +27,7 @@
plugin_pagespeed_url: https://lecoq.io plugin_pagespeed_url: https://lecoq.io
use_mocked_data: 'yes' use_mocked_data: 'yes'
verify: 'yes' verify: 'yes'
- name: ⏱️ Google PageSpeed - Succint report with PWA - name: ⏱️ Google PageSpeed - Succinct report with PWA
uses: lowlighter/metrics@latest uses: lowlighter/metrics@latest
with: with:
token: NOT_NEEDED token: NOT_NEEDED

View File

@@ -5,8 +5,8 @@ const git = require("simple-git")(path.join(__dirname, ".."))
//Edited files list //Edited files list
const diff = async () => (await git.diff(["origin/master...", "--name-status"])).split("\n").map(x => x.trim()).filter(x => /^M\s+/.test(x)).map(x => x.replace(/^M\s+/, "")) const diff = async () => (await git.diff(["origin/master...", "--name-status"])).split("\n").map(x => x.trim()).filter(x => /^M\s+/.test(x)).map(x => x.replace(/^M\s+/, ""))
//Files editions //File changes
describe("Check files editions (checkout your files if needed)", () => { describe("Check file changes (checkout your files if needed)", () => {
describe("Auto-generated files were not modified", () => describe("Auto-generated files were not modified", () =>
void test.each([ void test.each([
"README.md", "README.md",
@@ -42,7 +42,7 @@ describe("Check files editions (checkout your files if needed)", () => {
} }
}) })
//Templates editions //Template changes
describe("Check templates editions", () => { describe("Check template changes", () => {
test("Use community templates instead (see https://github.com/lowlighter/metrics/tree/master/source/templates/community)", async () => void expect((await diff()).filter(edited => /^sources[/]templates[/]/.test(edited) && /^source[/]templates[/](?:classic|terminal|markdown|repository|community)[/][\s\S]*$/.test(edited)).length).toBe(0)) test("Use community templates instead (see https://github.com/lowlighter/metrics/tree/master/source/templates/community)", async () => void expect((await diff()).filter(edited => /^sources[/]templates[/]/.test(edited) && /^source[/]templates[/](?:classic|terminal|markdown|repository|community)[/][\s\S]*$/.test(edited)).length).toBe(0))
}) })

View File

@@ -8,7 +8,7 @@ const axios = require("axios")
const faker = require("@faker-js/faker").faker const faker = require("@faker-js/faker").faker
const ejs = require("ejs") const ejs = require("ejs")
//Github action //GitHub action
const action = yaml.load(fs.readFileSync(path.join(__dirname, "../action.yml"), "utf8")) const action = yaml.load(fs.readFileSync(path.join(__dirname, "../action.yml"), "utf8"))
action.defaults = Object.fromEntries(Object.entries(action.inputs).map(([key, {default: value}]) => [key, value])) action.defaults = Object.fromEntries(Object.entries(action.inputs).map(([key, {default: value}]) => [key, value]))
action.input = vars => Object.fromEntries([...Object.entries(action.defaults), ...Object.entries(vars)].map(([key, value]) => [`INPUT_${key.toLocaleUpperCase()}`, value])) action.input = vars => Object.fromEntries([...Object.entries(action.defaults), ...Object.entries(vars)].map(([key, value]) => [`INPUT_${key.toLocaleUpperCase()}`, value]))

View File

@@ -1,6 +1,6 @@
/**Mocked data */ /**Mocked data */
export default function({faker, query, login = faker.internet.userName()}) { export default function({faker, query, login = faker.internet.userName()}) {
console.debug("metrics/compute/mocks > mocking graphql api result > repositories/randodm") console.debug("metrics/compute/mocks > mocking graphql api result > repositories/random")
return ({ return ({
user: { user: {
repositories: { repositories: {