Feat miscelleanous 1 (#28)

* Improve logs and better handling of plugins errors

* Add support for timezones

* Prepare next release
This commit is contained in:
Simon Lecoq authored and GitHub committed 2020-12-27 22:30:53 +01:00
1 parent 619113295c
commit 016ab9aca1
24 files changed
+242 -148

No files matched your search

+30 -12
View File
@@ -213,14 +213,19 @@ The `README.md` of it will be displayed on your user profile :
From the `Developer settings` of your account settings, select `Personal access tokens` to create a new token.
No additional scopes are needed, unless you want to include your private repositories metrics or if you want to use the `traffic` plugin.
No additional scopes are needed, unless you want to include your private repositories metrics.
![Setup a GitHub personal token](.github/readme/imgs/setup_personal_token.png)
Be sure to enable `Include private contributions on my profile` in your account settings if you want to include your private contributions :
With a scope-less token, you can still display private contributions by enabling `Include private contributions on my profile` in your account settings :
![Enable "Include private contributions on my profile`"](.github/readme/imgs/setup_private_contributions.png)
Some plugins also require additional scopes, which is indicated in their respective documentation.
In case your token does not have the required scope (and `plugins_errors_fatal` is not enabled), it will be directly notified in the plugin render like below :
![Plugin error example](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.error.svg)
### 2. Set your GitHub token in your personal repository secrets
Go to the `Settings` of your personal repository to create a new secret and paste your freshly generated GitHub token there.
@@ -258,8 +263,6 @@ When using a token with additional permissions, it is advised to fork this repos
```
In this case, consider watching new releases of this repository to stay up-to-date and enjoy latest features !
If you prefer examples rather than theory, check out this [workflow](https://github.com/lowlighter/lowlighter/blob/master/.github/workflows/metrics.yml) file which generates metrics daily.
#### Preview vs release
It is possible to use `@master` instead of `@latest` to use new features before their official release.
@@ -271,6 +274,12 @@ A new metrics image will be generated and committed to your repository on each r
![Action update example](.github/readme/imgs/example_action_update.png)
#### Workflow examples
Check out this [workflow](https://github.com/lowlighter/lowlighter/blob/master/.github/workflows/metrics.yml) file which generates metrics daily.
Note that most of steps presented there are illustrative examples for this readme and are actually not needed to generate your own metrics.
### 4. Embed the link into your README.md
Edit your repository readme and add your metrics image :
@@ -867,6 +876,8 @@ Add the following to your workflow :
### 🗂️ Projects
⚠️ This plugin requires a personal token with public_repo scope.
The *projects* plugin displays the progress of your profile projects.
![Projects plugin](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.projects.svg)
@@ -876,6 +887,8 @@ The *projects* plugin displays the progress of your profile projects.
It will consume an additional GitHub request.
Because of GitHub REST API limitation, provided token requires `public_repo` scope to access projects informations.
Add the following to your workflow :
```yaml
- uses: lowlighter/metrics@latest
@@ -926,7 +939,7 @@ Add the following to your workflow :
### 🧮 Traffic
⚠️ This plugin requires a personal token with full repo scope.
⚠️ This plugin requires a personal token with repo scope.
The repositories *traffic* plugin displays the number of pages views across your repositories.
@@ -955,8 +968,6 @@ Add the following to your workflow :
### 🐤 Tweets
🚧 This plugin is available as pre-release on @master
The recent *tweets* plugin displays your latest tweets of the [twitter](https://twitter.com) attached mentioned on your account :
![Tweets plugin](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.tweets.svg)
@@ -1030,7 +1041,7 @@ If you're using GitHub Api in other projects, you could reach the rate limit.
![Habits plugin (facts)](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.habits.facts.svg)
These facts are generated from your recent coding activity.
The indent style is deduced from the diffs of your recent commits.
The indent style is deduced from the diffs of your recent commits.
Add the following to your workflow :
```yaml
@@ -1042,14 +1053,12 @@ Add the following to your workflow :
plugin_habits_days: 14
```
🚧 The following feature is available as pre-release on @master
You can display charts in this section :
![Habits plugin (charts)](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.habits.charts.svg)
These charts are generated from your recent coding activity.
Languages metrics are computed with [github/linguist](https://github.com/github/linguist) from the diffs of your recent commits.
These charts are generated from your recent coding activity.
Languages metrics are computed with [github/linguist](https://github.com/github/linguist) from the diffs of your recent commits.
Add the following to your workflow instead :
```yaml
@@ -1063,6 +1072,15 @@ Add the following to your workflow instead :
plugin_habits_charts: yes
```
By default, dates are based on the Greenwich meridian (England time). In order to these metrics to be accurate, be sure to set your timezone (see [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for a list of supported timezones) :
```yaml
- uses: lowlighter/metrics@latest
with:
# ... other options
config_timezone: Europe/Paris
```
</details>
### 🎫 Gists
+7
View File
@@ -40,6 +40,13 @@ inputs:
description: Optimize SVG image
default: yes
# Set timezone used by metrics
# See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
# Some plugins will use this setting to calibrate dates
config_timezone:
description: Timezone used by metrics
default: ""
# Number of repositories to use for metrics
# A high number increase metrics accuracy, but will consume additional API requests when using plugins
repositories:
+12 -12
View File
@@ -1,4 +1,4 @@
module.exports=(()=>{var _Mathhypot=Math.hypot,_Mathacos=Math.acos,_Mathtan=Math.tan,_Mathasin=Math.asin,_Mathsin=Math.sin,_Mathcos=Math.cos,_MathPI=Math.PI,_Mathsqrt=Math.sqrt,_NumberisInteger=Number.isInteger,_Stringprototype=String.prototype,_NumberPOSITIVE_INFINITY=Number.POSITIVE_INFINITY,_NumberNEGATIVE_INFINITY=Number.NEGATIVE_INFINITY,_NumberMAX_SAFE_INTEGER=Number.MAX_SAFE_INTEGER,_Mathround=Math.round,_StringfromCharCode=String.fromCharCode,_Mathabs=Math.abs,_Mathpow=Math.pow,_Mathfloor=Math.floor,_Mathceil=Math.ceil,_Mathmax=Math.max,_Mathmin=Math.min;function __webpack_require__(e){if(__webpack_module_cache__[e])return __webpack_module_cache__[e].exports;var t=__webpack_module_cache__[e]={exports:{}},r=!0;try{__webpack_modules__[e].call(t.exports,t,t.exports,__webpack_require__),r=!1}finally{r&&delete __webpack_module_cache__[e]}return t.exports}var __webpack_modules__={45274:(e,t,r)=>{"use strict";async function n({log:e=!0}={}){const t=e?console.debug:()=>null;t(`metrics/setup > setup`);const n="src/templates",a={templates:{},settings:{},statics:r.ab+"html",node_modules:b.resolve("node_modules")};if(t(`metrics/setup > load settings.json`),y.existsSync(r.ab+"settings.json")?(a.settings=JSON.parse(`${await y.promises.readFile(b.resolve("settings.json"))}`),t(`metrics/setup > load settings.json > success`)):t(`metrics/setup > load settings.json > (missing)`),a.settings.templates||(a.settings.templates={default:"classic",enabled:[]}),a.settings.plugins||(a.settings.plugins={}),a.settings.plugins.base={parts:["header","activity","community","repositories","metadata"]},a.settings.debug&&t(a.settings),t(`metrics/setup > load package.json`),y.existsSync(r.ab+"package.json")?(a.package=JSON.parse(`${await y.promises.readFile(b.resolve("package.json"))}`),t(`metrics/setup > load package.json > success`)):(t(`metrics/setup > load package.json > (missing)`),a.package={version:"2.9.0-beta",author:"lowlighter"}),y.existsSync(r.ab+"templates"))for(const e of await y.promises.readdir(n)){if(/.*[.]mjs$/.test(e))continue;t(`metrics/setup > load template [${e}]`);const r=[`${n}/${e}/query.graphql`,`${n}/${e}/image.svg`,`${n}/${e}/style.css`,`${n}/${e}/fonts.css`],[o,i,s,l]=await Promise.all(r.map(async e=>`${await y.promises.readFile(b.resolve(e))}`));a.templates[e]={query:o,image:i,style:s,fonts:l},t(`metrics/setup > load template [${e}] > success`),a.settings.debug&&Object.defineProperty(a.templates,e,{get(){t(`metrics/setup > reload template [${e}]`);const[n,a,o,i]=r.map(e=>`${y.readFileSync(b.resolve(e))}`);return t(`metrics/setup > reload template [${e}] > success`),{query:n,image:a,style:o,fonts:i}}})}else t(`metrics/setup > load templates from build`),a.templates=JSON.parse(Buffer.from(`eyJjbGFzc2ljIjp7InF1ZXJ5IjoicXVlcnkgTWV0cmljcyB7XHJcbiAgdXNlcihsb2dpbjogJGxvZ2luKSB7XHJcbiAgICBkYXRhYmFzZUlkXHJcbiAgICBuYW1lXHJcbiAgICBsb2dpblxyXG4gICAgY3JlYXRlZEF0XHJcbiAgICBhdmF0YXJVcmxcclxuICAgIHdlYnNpdGVVcmxcclxuICAgIGlzSGlyZWFibGVcclxuICAgIHR3aXR0ZXJVc2VybmFtZVxyXG4gICAgZ2lzdHMge1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICByZXBvc2l0b3JpZXMobGFzdDogJHJlcG9zaXRvcmllcywgaXNGb3JrOiBmYWxzZSwgb3duZXJBZmZpbGlhdGlvbnM6IE9XTkVSKSB7XHJcbiAgICAgIHRvdGFsQ291bnRcclxuICAgICAgdG90YWxEaXNrVXNhZ2VcclxuICAgICAgbm9kZXMge1xyXG4gICAgICAgIG5hbWVcclxuICAgICAgICB3YXRjaGVycyB7XHJcbiAgICAgICAgICB0b3RhbENvdW50XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHN0YXJnYXplcnMge1xyXG4gICAgICAgICAgdG90YWxDb3VudFxyXG4gICAgICAgIH1cclxuICAgICAgICBsYW5ndWFnZXMoZmlyc3Q6IDQpIHtcclxuICAgICAgICAgIGVkZ2VzIHtcclxuICAgICAgICAgICAgc2l6ZVxyXG4gICAgICAgICAgICBub2RlIHtcclxuICAgICAgICAgICAgICBjb2xvclxyXG4gICAgICAgICAgICAgIG5hbWVcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpc3N1ZXNfb3BlbjogaXNzdWVzKHN0YXRlczogT1BFTikge1xyXG4gICAgICAgICAgdG90YWxDb3VudFxyXG4gICAgICAgIH1cclxuICAgICAgICBpc3N1ZXNfY2xvc2VkOiBpc3N1ZXMoc3RhdGVzOiBDTE9TRUQpIHtcclxuICAgICAgICAgIHRvdGFsQ291bnRcclxuICAgICAgICB9XHJcbiAgICAgICAgcHJfb3BlbjogcHVsbFJlcXVlc3RzKHN0YXRlczogT1BFTikge1xyXG4gICAgICAgICAgdG90YWxDb3VudFxyXG4gICAgICAgIH1cclxuICAgICAgICBwcl9tZXJnZWQ6IHB1bGxSZXF1ZXN0cyhzdGF0ZXM6IE1FUkdFRCkge1xyXG4gICAgICAgICAgdG90YWxDb3VudFxyXG4gICAgICAgIH1cclxuICAgICAgICByZWxlYXNlcyB7XHJcbiAgICAgICAgICB0b3RhbENvdW50XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZvcmtDb3VudFxyXG4gICAgICAgIGxpY2Vuc2VJbmZvIHtcclxuICAgICAgICAgIHNwZHhJZFxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcGFja2FnZXMge1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICBzdGFycmVkUmVwb3NpdG9yaWVzIHtcclxuICAgICAgdG90YWxDb3VudFxyXG4gICAgfVxyXG4gICAgd2F0Y2hpbmcge1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICBzcG9uc29yc2hpcHNBc1Nwb25zb3Ige1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICBzcG9uc29yc2hpcHNBc01haW50YWluZXIge1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICBjb250cmlidXRpb25zQ29sbGVjdGlvbiB7XHJcbiAgICAgIHRvdGFsUmVwb3NpdG9yaWVzV2l0aENvbnRyaWJ1dGVkQ29tbWl0c1xyXG4gICAgICB0b3RhbENvbW1pdENvbnRyaWJ1dGlvbnNcclxuICAgICAgcmVzdHJpY3RlZENvbnRyaWJ1dGlvbnNDb3VudFxyXG4gICAgICB0b3RhbElzc3VlQ29udHJpYnV0aW9uc1xyXG4gICAgICB0b3RhbFB1b Line truncated
module.exports=(()=>{var _Mathhypot=Math.hypot,_Mathacos=Math.acos,_Mathtan=Math.tan,_Mathasin=Math.asin,_Mathsin=Math.sin,_Mathcos=Math.cos,_MathPI=Math.PI,_Mathsqrt=Math.sqrt,_NumberisInteger=Number.isInteger,_NumberPOSITIVE_INFINITY=Number.POSITIVE_INFINITY,_NumberNEGATIVE_INFINITY=Number.NEGATIVE_INFINITY,_Stringprototype=String.prototype,_NumberMAX_SAFE_INTEGER=Number.MAX_SAFE_INTEGER,_StringfromCharCode=String.fromCharCode,_Mathabs=Math.abs,_Mathpow=Math.pow,_Mathround=Math.round,_Mathfloor=Math.floor,_Mathceil=Math.ceil,_Mathmax=Math.max,_Mathmin=Math.min;function __webpack_require__(e){if(__webpack_module_cache__[e])return __webpack_module_cache__[e].exports;var t=__webpack_module_cache__[e]={exports:{}},r=!0;try{__webpack_modules__[e].call(t.exports,t,t.exports,__webpack_require__),r=!1}finally{r&&delete __webpack_module_cache__[e]}return t.exports}var __webpack_modules__={45274:(e,t,r)=>{"use strict";async function n({log:e=!0}={}){const t=e?console.debug:()=>null;t(`metrics/setup > setup`);const n="src/templates",a={templates:{},settings:{},statics:r.ab+"html",node_modules:b.resolve("node_modules")};if(t(`metrics/setup > load settings.json`),y.existsSync(r.ab+"settings.json")?(a.settings=JSON.parse(`${await y.promises.readFile(b.resolve("settings.json"))}`),t(`metrics/setup > load settings.json > success`)):t(`metrics/setup > load settings.json > (missing)`),a.settings.templates||(a.settings.templates={default:"classic",enabled:[]}),a.settings.plugins||(a.settings.plugins={}),a.settings.plugins.base={parts:["header","activity","community","repositories","metadata"]},a.settings.debug&&t(S.inspect(a.settings,{depth:1/0,maxStringLength:256})),t(`metrics/setup > load package.json`),y.existsSync(r.ab+"package.json")?(a.package=JSON.parse(`${await y.promises.readFile(b.resolve("package.json"))}`),t(`metrics/setup > load package.json > success`)):(t(`metrics/setup > load package.json > (missing)`),a.package={version:"2.9.0",author:"lowlighter"}),y.existsSync(r.ab+"templates"))for(const e of await y.promises.readdir(n)){if(/.*[.]mjs$/.test(e))continue;t(`metrics/setup > load template [${e}]`);const r=[`${n}/${e}/query.graphql`,`${n}/${e}/image.svg`,`${n}/${e}/style.css`,`${n}/${e}/fonts.css`],[o,i,s,l]=await Promise.all(r.map(async e=>`${await y.promises.readFile(b.resolve(e))}`));a.templates[e]={query:o,image:i,style:s,fonts:l},t(`metrics/setup > load template [${e}] > success`),a.settings.debug&&Object.defineProperty(a.templates,e,{get(){t(`metrics/setup > reload template [${e}]`);const[n,a,o,i]=r.map(e=>`${y.readFileSync(b.resolve(e))}`);return t(`metrics/setup > reload template [${e}] > success`),{query:n,image:a,style:o,fonts:i}}})}else t(`metrics/setup > load templates from build`),a.templates=JSON.parse(Buffer.from(`eyJjbGFzc2ljIjp7InF1ZXJ5IjoicXVlcnkgTWV0cmljcyB7XHJcbiAgdXNlcihsb2dpbjogJGxvZ2luKSB7XHJcbiAgICBkYXRhYmFzZUlkXHJcbiAgICBuYW1lXHJcbiAgICBsb2dpblxyXG4gICAgY3JlYXRlZEF0XHJcbiAgICBhdmF0YXJVcmxcclxuICAgIHdlYnNpdGVVcmxcclxuICAgIGlzSGlyZWFibGVcclxuICAgIHR3aXR0ZXJVc2VybmFtZVxyXG4gICAgZ2lzdHMge1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICByZXBvc2l0b3JpZXMobGFzdDogJHJlcG9zaXRvcmllcywgaXNGb3JrOiBmYWxzZSwgb3duZXJBZmZpbGlhdGlvbnM6IE9XTkVSKSB7XHJcbiAgICAgIHRvdGFsQ291bnRcclxuICAgICAgdG90YWxEaXNrVXNhZ2VcclxuICAgICAgbm9kZXMge1xyXG4gICAgICAgIG5hbWVcclxuICAgICAgICB3YXRjaGVycyB7XHJcbiAgICAgICAgICB0b3RhbENvdW50XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHN0YXJnYXplcnMge1xyXG4gICAgICAgICAgdG90YWxDb3VudFxyXG4gICAgICAgIH1cclxuICAgICAgICBsYW5ndWFnZXMoZmlyc3Q6IDQpIHtcclxuICAgICAgICAgIGVkZ2VzIHtcclxuICAgICAgICAgICAgc2l6ZVxyXG4gICAgICAgICAgICBub2RlIHtcclxuICAgICAgICAgICAgICBjb2xvclxyXG4gICAgICAgICAgICAgIG5hbWVcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpc3N1ZXNfb3BlbjogaXNzdWVzKHN0YXRlczogT1BFTikge1xyXG4gICAgICAgICAgdG90YWxDb3VudFxyXG4gICAgICAgIH1cclxuICAgICAgICBpc3N1ZXNfY2xvc2VkOiBpc3N1ZXMoc3RhdGVzOiBDTE9TRUQpIHtcclxuICAgICAgICAgIHRvdGFsQ291bnRcclxuICAgICAgICB9XHJcbiAgICAgICAgcHJfb3BlbjogcHVsbFJlcXVlc3RzKHN0YXRlczogT1BFTikge1xyXG4gICAgICAgICAgdG90YWxDb3VudFxyXG4gICAgICAgIH1cclxuICAgICAgICBwcl9tZXJnZWQ6IHB1bGxSZXF1ZXN0cyhzdGF0ZXM6IE1FUkdFRCkge1xyXG4gICAgICAgICAgdG90YWxDb3VudFxyXG4gICAgICAgIH1cclxuICAgICAgICByZWxlYXNlcyB7XHJcbiAgICAgICAgICB0b3RhbENvdW50XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZvcmtDb3VudFxyXG4gICAgICAgIGxpY2Vuc2VJbmZvIHtcclxuICAgICAgICAgIHNwZHhJZFxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcGFja2FnZXMge1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICBzdGFycmVkUmVwb3NpdG9yaWVzIHtcclxuICAgICAgdG90YWxDb3VudFxyXG4gICAgfVxyXG4gICAgd2F0Y2hpbmcge1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICBzcG9uc29yc2hpcHNBc1Nwb25zb3Ige1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICBzcG9uc29yc2hpcHNBc01haW50YWluZXIge1xyXG4gICAgICB0b3RhbENvdW50XHJcbiAgICB9XHJcbiAgICBjb250cmlidXRpb25zQ29sbGVjdGlvbiB7XHJcbiAgICAgIHRvdGFsUmVwb3NpdG9yaWVzV2l0aENvbnRyaWJ1dGVkQ29tbWl0c1xyXG4gICAgICB0b3RhbENvbW1pdENvbnRyaWJ1dGlvbnNcclxuICAgICAgcmVzdHJpY3RlZENvbnRyaWJ1dGlvbnNDb3VudFxyXG4gICAgICB0b3RhbElzc3VlQ29 Line truncated
query Gists {
user(login: "${e}") {
gists(last: 100) {
@@ -16,7 +16,7 @@ module.exports=(()=>{var _Mathhypot=Math.hypot,_Mathacos=Math.acos,_Mathtan=Math
}
}
}
`);let o=0,i=0,s=0;for(const e of a.nodes)e.isFork||(o+=e.stargazerCount,i+=e.forks.totalCount,s+=e.comments.totalCount);return{totalCount:a.totalCount,stargazers:o,forks:i,comments:s}}catch(e){throw console.debug(e),{error:{message:`An error occured`}}}},habits:async function({login:e,rest:t,imports:r,q:n},{enabled:a=!1,from:o=100}={}){try{if(!a||!n.habits)return null;let{"habits.from":i=o.from??500,"habits.days":s=30,"habits.facts":l=!0,"habits.charts":d=!1}=n;i=_Mathmax(1,_Mathmin(1e3,+i)),s=_Mathmax(1,_Mathmin(30,+i));const p={facts:l,charts:d,commits:{hour:NaN,hours:{},day:NaN,days:{}},indents:{style:"",spaces:0,tabs:0},linguist:{available:!1,ordered:[],languages:{}}},c=_Mathceil(i/100),u=[];try{for(let r=0;r<c;r++)console.debug(`metrics/compute/${e}/plugins > habits > loaded page ${r}`),u.push(...(await t.activity.listEventsForAuthenticatedUser({username:e,per_page:100,page:r})).data)}catch{console.debug(`metrics/compute/${e}/plugins > habits > no more events to load`)}console.debug(`metrics/compute/${e}/plugins > habits > no more events to load (${u.length} loaded)`);const m=u.filter(({type:e})=>"PushEvent"===e).filter(({actor:t})=>t.login===e).filter(({created_at:e})=>new Date(e)>new Date(Date.now()-1e3*(60*(60*(24*s)))));console.debug(`metrics/compute/${e}/plugins > habits > filtered out ${m.length} commits`);const g=m[0]?.actor?.id??0,h=[...(await Promise.allSettled(m.flatMap(({payload:e})=>e.commits).map(e=>e.url).map(async e=>(await t.request(e)).data.files)))].filter(({status:e})=>"fulfilled"===e).map(({value:e})=>e).flatMap(e=>e.map(e=>({name:r.paths.basename(e.filename),patch:e.patch??""}))).map(({name:e,patch:t})=>({name:e,patch:t.split("\n").filter(e=>/^[-+]/.test(e)).map(e=>e.substring(1)).join("\n")}));{const e=m.map(({created_at:e})=>new Date(e).getDay());for(const t of e)p.commits.days[t]=(p.commits.days[t]??0)+1;p.commits.days.max=_Mathmax(...Object.values(p.commits.days)),p.commits.day=e.length?["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][Object.entries(p.commits.days).sort(([e,t],[r,n])=>n-t).map(([e,t])=>e)[0]]??NaN:NaN}{const e=m.map(({created_at:e})=>new Date(e).getHours());for(const t of e)p.commits.hours[t]=(p.commits.hours[t]??0)+1;p.commits.hours.max=_Mathmax(...Object.values(p.commits.hours)),p.commits.hour=e.length?`${Object.entries(p.commits.hours).sort(([e,t],[r,n])=>n-t).map(([e,t])=>e)[0]}`.padStart(2,"0"):NaN}if(h.map(({patch:e})=>e.match(/((?:\t)|(?: )) /gm)??[]).forEach(e=>p.indents[/^\t/.test(e)?"tabs":"spaces"]++),p.indents.style=p.indents.spaces>p.indents.tabs?"spaces":p.indents.tabs>p.indents.spaces?"tabs":"",d){const t={win32:"wsl"}[process.platform]??"";if(h.length&&(await r.run(`${t} which github-linguist`))){p.linguist.available=!0;const n=r.paths.join(r.os.tmpdir(),`${g}`);await r.fs.mkdir(n,{recursive:!0}),await Promise.all(h.map(async({name:e,patch:t},a)=>await r.fs.writeFile(r.paths.join(n,`${a}${r.paths.extname(e)}`),t))),console.debug(`metrics/compute/${e}/plugins > habits > created temp dir ${n} with ${h.length} files`),await r.run(`git init && git add . && git config user.name "linguist" && git config user.email "null@github.com" && git commit -m "linguist"`,{cwd:n}).catch(console.debug),await r.run(`git status`,{cwd:n}),console.debug(`metrics/compute/${e}/plugins > habits > created temp git repository`),console.debug(`metrics/compute/${e}/plugins > habits > running linguist`),(await r.run(`${t} github-linguist`,{cwd:n})).split("\n").map(e=>e.match(/(?<value>[\d.]+)%\s+(?<language>\w+)/)?.groups).filter(e=>e).map(({value:e,language:t})=>p.linguist.languages[t]=(p.linguist.languages[t]??0)+e/100),p.linguist.ordered=Object.entries(p.linguist.languages).sort(([e,t],[r,n])=>n-t)}else console.debug(`metrics/compute/${e}/plugins > habits > linguist is not available`)}return p}catch(e){throw console.debug(e),{error:{message:`An error occured`}}}},isocalendar:async function({login:e,graphql:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.isocalendar)return null;let{"isocalendar.duration":a="half-year"}=r;a=["full-year","half-year"].includes(a)?a:"full-year";const o=new Date,s=new Date(o);"full-year"===a?s.setFullYear(o.getFullYear()-1):s.setHours(-4320);const l=new Date(s);l.setHours(-336);const d={};for(const[r,n,a]of[["padding",l,s],["weeks",s,o]]){console.debug(`metrics/compute/${e}/plugins > isocalendar > loading "${r}" from "${n.toISOString()}" to "${a.toISOString()}"`);const{user:{calendar:{contributionCalendar:{weeks:o}}}}=await t(`
`);console.debug(`metrics/compute/${e}/plugins > gists > processing ${a.nodes.length} gists`);let o=0,i=0,s=0;for(const e of a.nodes)e.isFork||(o+=e.stargazerCount,i+=e.forks.totalCount,s+=e.comments.totalCount);return{totalCount:a.totalCount,stargazers:o,forks:i,comments:s}}catch(e){throw{error:{message:"An error occured",instance:e}}}},habits:async function({login:e,rest:t,imports:r,data:n,q:a},{enabled:o=!1,from:i=100}={}){try{if(!o||!a.habits)return null;let{"habits.from":s=i.from??500,"habits.days":l=30,"habits.facts":d=!0,"habits.charts":p=!1}=a;s=_Mathmax(1,_Mathmin(1e3,+s)),l=_Mathmax(1,_Mathmin(30,+s));const c={facts:d,charts:p,commits:{hour:NaN,hours:{},day:NaN,days:{}},indents:{style:"",spaces:0,tabs:0},linguist:{available:!1,ordered:[],languages:{}}},u=_Mathceil(s/100),m=n.config.timezone?.offset??0;console.debug(`metrics/compute/${e}/plugins > habits > querying api`);const g=[];try{for(let r=0;r<u;r++)console.debug(`metrics/compute/${e}/plugins > habits > loading page ${r}`),g.push(...(await t.activity.listEventsForAuthenticatedUser({username:e,per_page:100,page:r})).data)}catch{console.debug(`metrics/compute/${e}/plugins > habits > no more page to load`)}console.debug(`metrics/compute/${e}/plugins > habits > ${g.length} events loaded`);const h=g.filter(({type:e})=>"PushEvent"===e).filter(({actor:t})=>t.login===e).filter(({created_at:e})=>new Date(e)>new Date(Date.now()-1e3*(60*(60*(24*l)))));console.debug(`metrics/compute/${e}/plugins > habits > filtered out ${h.length} push events over last ${l} days`),console.debug(`metrics/compute/${e}/plugins > habits > loading patches`);const f=[...(await Promise.allSettled(h.flatMap(({payload:e})=>e.commits).map(e=>e.url).map(async e=>(await t.request(e)).data.files)))].filter(({status:e})=>"fulfilled"===e).map(({value:e})=>e).flatMap(e=>e.map(e=>({name:r.paths.basename(e.filename),patch:e.patch??""}))).map(({name:e,patch:t})=>({name:e,patch:t.split("\n").filter(e=>/^[-+]/.test(e)).map(e=>e.substring(1)).join("\n")}));{console.debug(`metrics/compute/${e}/plugins > habits > searching most active day of week`);const t=h.map(({created_at:e})=>new Date(new Date(e).getTime()+m).getDay());for(const e of t)c.commits.days[e]=(c.commits.days[e]??0)+1;c.commits.days.max=_Mathmax(...Object.values(c.commits.days)),c.commits.day=t.length?["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][Object.entries(c.commits.days).sort(([e,t],[r,n])=>n-t).map(([e,t])=>e)[0]]??NaN:NaN}{console.debug(`metrics/compute/${e}/plugins > habits > searching most active time of day`);const t=h.map(({created_at:e})=>new Date(new Date(e).getTime()+m).getHours());for(const e of t)c.commits.hours[e]=(c.commits.hours[e]??0)+1;c.commits.hours.max=_Mathmax(...Object.values(c.commits.hours)),c.commits.hour=t.length?`${Object.entries(c.commits.hours).sort(([e,t],[r,n])=>n-t).map(([e,t])=>e)[0]}`.padStart(2,"0"):NaN}if(console.debug(`metrics/compute/${e}/plugins > habits > searching indent style`),f.map(({patch:e})=>e.match(/((?:\t)|(?: )) /gm)??[]).forEach(e=>c.indents[/^\t/.test(e)?"tabs":"spaces"]++),c.indents.style=c.indents.spaces>c.indents.tabs?"spaces":c.indents.tabs>c.indents.spaces?"tabs":"",p){console.debug(`metrics/compute/${e}/plugins > habits > searching recently used languages using linguist`);const t={win32:"wsl"}[process.platform]??"";if(f.length&&(await r.run(`${t} which github-linguist`))){c.linguist.available=!0;const n=r.paths.join(r.os.tmpdir(),`${h[0]?.actor?.id??0}`);console.debug(`metrics/compute/${e}/plugins > habits > creating temp dir ${n} with ${f.length} files`),await r.fs.mkdir(n,{recursive:!0}),await Promise.all(f.map(async({name:e,patch:t},a)=>await r.fs.writeFile(r.paths.join(n,`${a}${r.paths.extname(e)}`),t))),console.debug(`metrics/compute/${e}/plugins > habits > creating temp git repository`),await r.run(`git init && git add . && git config user.name "linguist" && git config user.email "null@github.com" && git commit -m "linguist"`,{cwd:n}).catch(console.debug),await r.run(`git status`,{cwd:n}),console.debug(`metrics/compute/${e}/plugins > habits > running linguist`),(await r.run(`${t} github-linguist --breakdown`,{cwd:n})).split("\n").map(e=>e.match(/(?<value>[\d.]+)%\s+(?<language>\w+)/)?.groups).filter(e=>e).map(({value:e,language:t})=>c.linguist.languages[t]=(c.linguist.languages[t]??0)+e/100),c.linguist.ordered=Object.entries(c.linguist.languages).sort(([e,t],[r,n])=>n-t)}else console.debug(`metrics/compute/${e}/plugins > habits > linguist not available`)}return c}catch(e){if(e.error?.message)throw e;throw{error:{message:"An error occured",instance:e}}}},isocalendar:async function({login:e,graphql:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.isocalendar)return null;let{"isocalendar.duration":a="half-year"}=r;a=["full-year","half-year"].includes(a)?a:"full-year";const o=new Date,s=new Date(o);"full-year"===a?s.setFullYear(o.getFullYear()-1):s.setHours(-4320);const l=new Date(s);l.setHours(-336),console.debug(`metrics/compute/${e}Line truncated
query Calendar {
user(login: "${e}") {
calendar:contributionsCollection(from: "${n.toISOString()}", to: "${a.toISOString()}") {
@@ -32,7 +32,7 @@ module.exports=(()=>{var _Mathhypot=Math.hypot,_Mathacos=Math.acos,_Mathtan=Math
}
}
}
`);d[r]=o}const p=d.weeks[0].contributionDays,c=d.padding.flatMap(({contributionDays:e})=>e).filter(({date:e})=>!p.map(({date:e})=>e).includes(e));for(;7>p.length;)p.unshift(c.pop());let u=0,m={max:0,current:0},g=[],h=0;for(const e of d.weeks)for(const t of e.contributionDays)g.push(t.contributionCount),u=_Mathmax(u,t.contributionCount),m.current=t.contributionCount?m.current+1:0,m.max=_Mathmax(m.max,m.current);h=(g.reduce((e,t)=>e+t,0)/g.length).toFixed(2).replace(/[.]0+$/,"");const f=6;let y=0,i=0,b=`
`);d[r]=o}console.debug(`metrics/compute/${e}/plugins > isocalendar > applying padding`);const p=d.weeks[0].contributionDays,c=d.padding.flatMap(({contributionDays:e})=>e).filter(({date:e})=>!p.map(({date:e})=>e).includes(e));for(;7>p.length;)p.unshift(c.pop());console.debug(`metrics/compute/${e}/plugins > isocalendar > computing stats`);let u=0,m={max:0,current:0},g=[],h=0;for(const e of d.weeks)for(const t of e.contributionDays)g.push(t.contributionCount),u=_Mathmax(u,t.contributionCount),m.current=t.contributionCount?m.current+1:0,m.max=_Mathmax(m.max,m.current);h=(g.reduce((e,t)=>e+t,0)/g.length).toFixed(2).replace(/[.]0+$/,""),console.debug(`metrics/compute/${e}/plugins > isocalendar > computing svg render`);const f=6;let y=0,i=0,b=`
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="margin-top: -52px;" viewBox="0,0 480,${"full-year"===a?270:170}">
${[1,2].map(e=>`
<filter id="brightness${e}">
@@ -45,7 +45,7 @@ module.exports=(()=>{var _Mathhypot=Math.hypot,_Mathacos=Math.acos,_Mathtan=Math
<path fill="${t.color}" d="M1.7,2 0,1 1.7,0 3.4,1 z" />
<path fill="${t.color}" filter="url(#brightness1)" d="M0,1 1.7,2 1.7,${2+e*f} 0,${1+e*f} z" />
<path fill="${t.color}" filter="url(#brightness2)" d="M1.7,2 3.4,1 3.4,${1+e*f} 1.7,${2+e*f} z" />
</g>`,i++}b+=`</g>`,y++}return b+=`</g></svg>`,{streak:m,max:u,average:h,svg:b,duration:a}}catch(e){throw console.debug(e),{error:{message:`An error occured`}}}},languages:async function({login:e,data:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.languages)return null;let{"languages.ignored":a="","languages.skipped":o=""}=r;a=decodeURIComponent(a).split(",").map(e=>e.trim().toLocaleLowerCase()).filter(e=>e),o=decodeURIComponent(o).split(",").map(e=>e.trim().toLocaleLowerCase()).filter(e=>e);const s={colors:{},total:0,stats:{}};for(const r of t.user.repositories.nodes){if(o.includes(r.name.toLocaleLowerCase())){console.debug(`metrics/compute/${e}/plugins > languages > skipped repository ${r.name}`);continue}for(const{size:t,node:{color:n,name:o}}of Object.values(r.languages.edges)){if(a.includes(o.toLocaleLowerCase())){console.debug(`metrics/compute/${e}/plugins > languages > ignored language ${o}`);continue}s.stats[o]=(s.stats[o]??0)+t,s.colors[o]=n??"#ededed",s.total+=t}}Object.keys(s.stats).map(e=>s.stats[e]/=s.total),s.favorites=Object.entries(s.stats).sort(([e,t],[r,n])=>n-t).slice(0,8).map(([e,t])=>({name:e,value:t,color:s.colors[e],x:0}));for(let e=1;e<s.favorites.length;e++)s.favorites[e].x=s.favorites[e-1].x+s.favorites[e-1].value;return s}catch(e){throw console.debug(e),{error:{message:`An error occured`}}}},lines:async function({login:e,data:t,imports:r,rest:n,q:a},{enabled:o=!1}={}){try{if(!o||!a.lines)return null;const i=t.user.repositories.nodes.map(({name:e})=>e)??[],s={added:0,deleted:0},l=await Promise.all(i.map(async t=>await n.repos.getContributorsStats({owner:e,repo:t})));return l.map(({data:t})=>{if(Array.isArray(t)){const[r]=t.filter(({author:t})=>t.login===e);r&&r.weeks.forEach(({a:e,d:t})=>(s.added+=e,s.deleted+=t))}}),s.added=r.format(s.added),s.deleted=r.format(s.deleted),s}catch(e){throw console.debug(e),{error:{message:`An error occured`}}}},music:a,pagespeed:async function({login:e,imports:t,data:r,q:n},{enabled:a=!1,token:o=null}={}){try{if(!a||!n.pagespeed||!r.user.websiteUrl)return null;let{"pagespeed.detailed":i=!1}=n;i=!!i;let s=r.user.websiteUrl;/^https?:[/][/]/.test(s)||(s=`https://${s}`);const l={url:s,detailed:i,scores:[],metrics:{}},d=new Map;if(await Promise.all(["performance","accessibility","best-practices","seo"].map(async r=>{const{score:n,title:a}=(await t.axios.get(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?category=${r}&url=${s}&key=${o}`)).data.lighthouseResult.categories[r];d.set(r,{score:n,title:a}),console.debug(`metrics/compute/${e}/plugins > pagespeed > ${r} audit performed`)})),l.scores=[d.get("performance"),d.get("accessibility"),d.get("best-practices"),d.get("seo")],i&&Object.assign(l.metrics,...(await t.axios.get(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?&url=${s}&key=${o}`)).data.lighthouseResult.audits.metrics.details.items),4>l.scores.filter(e=>e).length)throw{error:{message:"Incomplete PageSpeed results"},url:s};return l}catch(e){if(e.response?.status)throw{error:{message:`PageSpeed token error (code ${e.response.status})`},url};if(e.error?.message)throw e;throw console.debug(e),{error:{message:`An error occured`}}}},posts:async function({imports:e,data:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.posts)return null;const a=t.user.login;let{"posts.source":o="","posts.limit":i=4}=r;i=_Mathmax(1,_Mathmin(30,+i));let s=null;switch(o){case"dev.to":{s=(await e.axios.get(`https://dev.to/api/articles?username=${a}&state=fresh`)).data.map(({title:e,readable_publish_date:t})=>({title:e,date:t}));break}default:throw{error:{message:`Unsupported source "${o}"`}};}if(Array.isArray(s))return 0<i&&(console.debug(`metrics/compute/${a}/plugins > posts > keeping only ${i} posts`),s=s.slice(0,i)),{source:o,list:s};throw{error:{message:`An error occured (could not retrieve posts)`}}}catch(e){throw console.debug(e),{error:{message:`An error occured`}}}},projects:async function({login:e,graphql:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.projects)return null;let{"projects.limit":a=4}=r;a=_Mathmax(1,_Mathmin(100,+a));const{user:{projects:o}}=await t(`
</g>`,i++}b+=`</g>`,y++}return b+=`</g></svg>`,{streak:m,max:u,average:h,svg:b,duration:a}}catch(e){throw{error:{message:"An error occured",instance:e}}}},languages:async function({login:e,data:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.languages)return null;let{"languages.ignored":a="","languages.skipped":o=""}=r;a=decodeURIComponent(a).split(",").map(e=>e.trim().toLocaleLowerCase()).filter(e=>e),o=decodeURIComponent(o).split(",").map(e=>e.trim().toLocaleLowerCase()).filter(e=>e),console.debug(`metrics/compute/${e}/plugins > languages > processing ${t.user.repositories.nodes.length} repositories`);const s={colors:{},total:0,stats:{}};for(const r of t.user.repositories.nodes){if(o.includes(r.name.toLocaleLowerCase())){console.debug(`metrics/compute/${e}/plugins > languages > skipped repository ${r.name}`);continue}for(const{size:t,node:{color:n,name:o}}of Object.values(r.languages.edges)){if(a.includes(o.toLocaleLowerCase())){console.debug(`metrics/compute/${e}/plugins > languages > ignored language ${o}`);continue}s.stats[o]=(s.stats[o]??0)+t,s.colors[o]=n??"#ededed",s.total+=t}}console.debug(`metrics/compute/${e}/plugins > languages > computing stats`),Object.keys(s.stats).map(e=>s.stats[e]/=s.total),s.favorites=Object.entries(s.stats).sort(([e,t],[r,n])=>n-t).slice(0,8).map(([e,t])=>({name:e,value:t,color:s.colors[e],x:0}));for(let e=1;e<s.favorites.length;e++)s.favorites[e].x=s.favorites[e-1].x+s.favorites[e-1].value;return s}catch(e){throw{error:{message:"An error occured",instance:e}}}},lines:async function({login:e,data:t,imports:r,rest:n,q:a},{enabled:o=!1}={}){try{if(!o||!a.lines)return null;const i=t.user.repositories.nodes.map(({name:e})=>e)??[];console.debug(`metrics/compute/${e}/plugins > lines > querying api`);const s={added:0,deleted:0},l=await Promise.all(i.map(async t=>await n.repos.getContributorsStats({owner:e,repo:t})));return console.debug(`metrics/compute/${e}/plugins > lines > computing total diff`),l.map(({data:t})=>{if(Array.isArray(t)){const[r]=t.filter(({author:t})=>t.login===e);r&&r.weeks.forEach(({a:e,d:t})=>(s.added+=e,s.deleted+=t))}}),s.added=r.format(s.added),s.deleted=r.format(s.deleted),s}catch(e){throw{error:{message:"An error occured",instance:e}}}},music:a,pagespeed:async function({login:e,imports:t,data:r,q:n},{enabled:a=!1,token:o=null}={}){try{if(!a||!n.pagespeed||!r.user.websiteUrl)return null;let{"pagespeed.detailed":i=!1}=n;i=!!i;let s=r.user.websiteUrl;/^https?:[/][/]/.test(s)||(s=`https://${s}`);const l={url:s,detailed:i,scores:[],metrics:{}};console.debug(`metrics/compute/${e}/plugins > pagespeed > querying api for ${s}`);const d=new Map;if(await Promise.all(["performance","accessibility","best-practices","seo"].map(async r=>{console.debug(`metrics/compute/${e}/plugins > pagespeed > performing audit ${r}`);const n=await t.axios.get(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?category=${r}&url=${s}&key=${o}`);console.debug(n.data);const{score:a,title:i}=n.data.lighthouseResult.categories[r];d.set(r,{score:a,title:i}),console.debug(`metrics/compute/${e}/plugins > pagespeed > performed audit ${r} (status code ${n.status})`)})),l.scores=[d.get("performance"),d.get("accessibility"),d.get("best-practices"),d.get("seo")],i){console.debug(`metrics/compute/${e}/plugins > pagespeed > performing detailed audit`);const r=await t.axios.get(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?&url=${s}&key=${o}`);console.debug(r.data),Object.assign(l.metrics,...r.data.lighthouseResult.audits.metrics.details.items),console.debug(`metrics/compute/${e}/plugins > pagespeed > performed detailed audit (status code ${r.status})`)}return l}catch(e){let t="An error occured";if(e.isAxiosError){const r=e.response?.status,n=e.response?.data?.error?.message?.match(/Lighthouse returned error: (?<description>[A-Z_]+)/)?.groups?.description??null;t=`API returned ${r}${n?` (${n})`:""}`,e=e.response?.data??null}throw{error:{message:t,instance:e}}}},posts:async function({imports:e,data:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.posts)return null;const a=t.user.login;let{"posts.source":o="","posts.limit":i=4}=r;i=_Mathmax(1,_Mathmin(30,+i)),console.debug(`metrics/compute/${a}/plugins > posts > processing with source ${o}`);let s=null;switch(o){case"dev.to":{console.debug(`metrics/compute/${a}/plugins > posts > querying api`),s=(await e.axios.get(`https://dev.to/api/articles?username=${a}&state=fresh`)).data.map(({title:e,readable_publish_date:t})=>({title:e,date:t}));break}default:throw{error:{message:`Unsupported source "${o}"`}};}if(Array.isArray(s))return 0<i&&(console.debug(`metrics/compute/${a}/plugins > posts > keeping only ${i} posts`),s=s.slice(0,i)),{source:o,list:s};throw{error:{message:`An error occured (could not retrieve posts)`}}}catch(e){throw{error:{message:"An error occured",instance:e}}}},projects:async function({login:e,graphql:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.projects)return null;let{"projects.limit":a=4}=r;a=_Mathmax(1,_Mathmin(1Line truncated
query Projects {
user(login: "${e}") {
projects(last: ${a}, states: OPEN, orderBy: {field: UPDATED_AT, direction: DESC}) {
@@ -63,32 +63,32 @@ module.exports=(()=>{var _Mathhypot=Math.hypot,_Mathacos=Math.acos,_Mathtan=Math
}
}
}
`),i=[];for(const e of o.nodes){const t=(Date.now()-new Date(e.updatedAt).getTime())/86400000;let r=1>t?"less than 1 day ago":30>t?`${_Mathfloor(t)} day${2<=t?"s":""} ago`:new Date(e.updatedAt).toDateString().substring(4);const{enabled:n,todoCount:a,inProgressCount:o,doneCount:s}=e.progress;i.push({name:e.name,updated:r,progress:{enabled:n,todo:a,doing:o,done:s,total:a+o+s}})}return{list:i,totalCount:o.totalCount}}catch(e){throw console.debug(e),{error:{message:`An error occured`}}}},topics:async function({login:e,imports:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.topics)return null;let{"topics.sort":a="stars","topics.limit":o=15}=r;const i="random"===a;a={starred:"created",activity:"updated",stars:"stars",random:"created"}[a]??"starred",o=_Mathmax(1,_Mathmin(20,+o));let s=[];console.debug(`metrics/compute/${e}/plugins > topics > starting browser`);const l=await t.puppeteer.launch({headless:!0,executablePath:process.env.PUPPETEER_BROWSER_PATH,args:["--no-sandbox","--disable-extensions","--disable-setuid-sandbox","--disable-dev-shm-usage"]});console.debug(`metrics/compute/${e}/plugins > topics > loaded ${await l.version()}`);const d=await l.newPage();for(let t=1;100>=t;t++){console.debug(`metrics/compute/${e}/plugins > topics > loading page ${t}`),await d.goto(`https://github.com/stars/${e}/topics?direction=desc&page=${t}&sort=${a}`);const r=d.mainFrame();await Promise.race([r.waitForSelector("ul.repo-list"),r.waitForSelector(".blankslate")]);const n=await r.evaluate(()=>[...document.querySelectorAll("ul.repo-list li")].map(e=>({name:e.querySelector(".f3").innerText,description:e.querySelector(".f5").innerText,icon:e.querySelector("img")?.src??null})));if(!n.length)break;s.push(...n)}if(console.debug(`metrics/compute/${e}/plugins > music > closing browser`),await l.close(),i&&(s=t.shuffle(s)),0<o){console.debug(`metrics/compute/${e}/plugins > topics > keeping only ${o} topics`);const t=s.slice(o);s=s.slice(0,o),s.push({name:`And ${t.length} more...`,description:t.map(({name:e})=>e).join(", "),icon:null})}for(const r of s)r.icon&&(console.debug(`metrics/compute/${e}/plugins > topics > processing ${r.name}`),r.icon=await t.imgb64(r.icon)),r.description=t.htmlescape(r.description);return{list:s}}catch(e){throw console.debug(e),{error:{message:`An error occured`}}}},traffic:async function({login:e,imports:t,data:r,rest:n,q:a},{enabled:o=!1}={}){try{if(!o||!a.traffic)return null;const i=r.user.repositories.nodes.map(({name:e})=>e)??[],s={count:0,uniques:0},l=await Promise.all(i.map(async t=>await n.repos.getViews({owner:e,repo:t})));return l.filter(({data:e})=>e).map(({data:{count:e,uniques:t}})=>(s.count+=e,s.uniques+=t)),s.count=t.format(s.count),s.uniques=t.format(s.uniques),{views:s}}catch(e){if(403===e.status)throw{error:{message:`Insufficient token rights`}};throw console.debug(e),{error:{message:`An error occured`}}}},tweets:async function({login:e,imports:t,data:r,q:n},{enabled:a=!1,token:o=null}={}){try{if(!a||!n.tweets)return null;let{"tweets.limit":i=2}=n;i=_Mathmax(1,_Mathmin(10,+i));const s=r.user.twitterUsername;console.debug(`metrics/compute/${e}/plugins > tweets > loading twitter profile (@${s})`);const{data:{data:l=null}}=await t.axios.get(`https://api.twitter.com/2/users/by/username/${s}?user.fields=profile_image_url,verified`,{headers:{Authorization:`Bearer ${o}`}});console.debug(`metrics/compute/${e}/plugins > tweets > loading tweets`);const{data:{data:d=[]}}=await t.axios.get(`https://api.twitter.com/2/tweets/search/recent?query=from:${s}&tweet.fields=created_at&expansions=entities.mentions.username`,{headers:{Authorization:`Bearer ${o}`}});return l?.profile_image_url&&(console.debug(`metrics/compute/${e}/plugins > tweets > loading profile image`),l.profile_image=await t.imgb64(l.profile_image_url)),0<i&&(console.debug(`metrics/compute/${e}/plugins > tweets > keeping only ${i} tweets`),d.splice(i)),await Promise.all(d.map(async r=>{r.mentions=r.entities?.mentions.map(({username:e})=>e)??[],console.debug(`metrics/compute/${e}/plugins > tweets > formatting tweet ${r.id}`),r.text=t.htmlescape(t.htmlescape(r.text,{"<":!0,">":!0}).replace(new RegExp(`@(${r.mentions.join("|")})`,"gi"),` <span class="mention">@$1</span> `).replace(/(?<!&)[#|#]([a-z0-9_\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u00ff\u0100-\u024f\u0253-\u0254\u0256-\u0257\u0300-\u036f\u1e00-\u1eff\u0400-\u04ff\u0500-\u0527\u2de0-\u2dff\ua640-\ua69f\u0591-\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05d0-\u05ea\u05f0-\u05f4\ufb12-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4f\u0610-\u061a\u0620-\u065f\u066e-\u06d3\u06d5-\u06dc\u06de-\u06e8\u06ea-\u06ef\u06fa-\u06fc\u0750-\u077f\u08a2-\u08ac\u08e4-\u08fe\ufb50-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\u200c-\u200c\u0e01-\u0e3a\u0e40-\u0e4e\u1100-\u11ff\u3130-\u3185\ua960-\ua97f\uac00-\ud7af\ud7b0-\ud7ff\uffa1-\uffdc\u30a1-\u30fa\u30fc-\u30fe\uff66-\uff9f\uff10-\uff19\uff21-\uff3a\uff41-\uff5a\u3041-\u3096\u3099-\u309e\u3400-\u Line truncated
`);console.debug(`metrics/compute/${e}/plugins > posts > processing ${o.nodes.length} projects`);const i=[];for(const e of o.nodes){const t=(Date.now()-new Date(e.updatedAt).getTime())/86400000;let r=1>t?"less than 1 day ago":30>t?`${_Mathfloor(t)} day${2<=t?"s":""} ago`:new Date(e.updatedAt).toDateString().substring(4);const{enabled:n,todoCount:a,inProgressCount:o,doneCount:s}=e.progress;i.push({name:e.name,updated:r,progress:{enabled:n,todo:a,doing:o,done:s,total:a+o+s}})}return{list:i,totalCount:o.totalCount}}catch(e){let t="An error occured";throw e.errors?.map(({type:e})=>e)?.includes("INSUFFICIENT_SCOPES")&&(t="Insufficient token rights"),{error:{message:t,instance:e}}}},topics:async function({login:e,imports:t,q:r},{enabled:n=!1}={}){try{if(!n||!r.topics)return null;let{"topics.sort":a="stars","topics.limit":o=15}=r;const i="random"===a;a={starred:"created",activity:"updated",stars:"stars",random:"created"}[a]??"starred",o=_Mathmax(1,_Mathmin(20,+o)),console.debug(`metrics/compute/${e}/plugins > topics > searching starred topics`);let s=[];console.debug(`metrics/compute/${e}/plugins > topics > starting browser`);const l=await t.puppeteer.launch({headless:!0,executablePath:process.env.PUPPETEER_BROWSER_PATH,args:["--no-sandbox","--disable-extensions","--disable-setuid-sandbox","--disable-dev-shm-usage"]});console.debug(`metrics/compute/${e}/plugins > topics > started ${await l.version()}`);const d=await l.newPage();for(let t=1;100>=t;t++){console.debug(`metrics/compute/${e}/plugins > topics > loading page ${t}`),await d.goto(`https://github.com/stars/${e}/topics?direction=desc&page=${t}&sort=${a}`);const r=d.mainFrame();await Promise.race([r.waitForSelector("ul.repo-list"),r.waitForSelector(".blankslate")]);const n=await r.evaluate(()=>[...document.querySelectorAll("ul.repo-list li")].map(e=>({name:e.querySelector(".f3").innerText,description:e.querySelector(".f5").innerText,icon:e.querySelector("img")?.src??null})));if(console.debug(`metrics/compute/${e}/plugins > topics > extracted ${n.length} starred topics`),!n.length){console.debug(`metrics/compute/${e}/plugins > topics > no more page to load`);break}s.push(...n)}if(console.debug(`metrics/compute/${e}/plugins > music > closing browser`),await l.close(),i&&(console.debug(`metrics/compute/${e}/plugins > topics > shuffling topics`),s=t.shuffle(s)),0<o){console.debug(`metrics/compute/${e}/plugins > topics > keeping only ${o} topics`);const t=s.slice(o);s=s.slice(0,o),s.push({name:`And ${t.length} more...`,description:t.map(({name:e})=>e).join(", "),icon:null})}console.debug(`metrics/compute/${e}/plugins > topics > loading artworks`);for(const r of s)r.icon&&(console.debug(`metrics/compute/${e}/plugins > topics > processing ${r.name}`),r.icon=await t.imgb64(r.icon)),r.description=t.htmlescape(r.description);return{list:s}}catch(e){throw{error:{message:"An error occured",instance:e}}}},traffic:async function({login:e,imports:t,data:r,rest:n,q:a},{enabled:o=!1}={}){try{if(!o||!a.traffic)return null;const i=r.user.repositories.nodes.map(({name:e})=>e)??[];console.debug(`metrics/compute/${e}/plugins > traffic > querying api`);const s={count:0,uniques:0},l=await Promise.all(i.map(async t=>await n.repos.getViews({owner:e,repo:t})));return console.debug(`metrics/compute/${e}/plugins > traffic > computing stats`),l.filter(({data:e})=>e).map(({data:{count:e,uniques:t}})=>(s.count+=e,s.uniques+=t)),s.count=t.format(s.count),s.uniques=t.format(s.uniques),{views:s}}catch(e){let t="An error occured";throw 403===e.status&&(t="Insufficient token rights"),{error:{message:t,instance:e}}}},tweets:async function({login:e,imports:t,data:r,q:n},{enabled:a=!1,token:o=null}={}){try{if(!a||!n.tweets)return null;let{"tweets.limit":i=2}=n;i=_Mathmax(1,_Mathmin(10,+i));const s=r.user.twitterUsername;console.debug(`metrics/compute/${e}/plugins > tweets > loading twitter profile (@${s})`);const{data:{data:l=null}}=await t.axios.get(`https://api.twitter.com/2/users/by/username/${s}?user.fields=profile_image_url,verified`,{headers:{Authorization:`Bearer ${o}`}});console.debug(`metrics/compute/${e}/plugins > tweets > querying api`);const{data:{data:d=[]}}=await t.axios.get(`https://api.twitter.com/2/tweets/search/recent?query=from:${s}&tweet.fields=created_at&expansions=entities.mentions.username`,{headers:{Authorization:`Bearer ${o}`}});return l?.profile_image_url&&(console.debug(`metrics/compute/${e}/plugins > tweets > loading profile image`),l.profile_image=await t.imgb64(l.profile_image_url)),0<i&&(console.debug(`metrics/compute/${e}/plugins > tweets > keeping only ${i} tweets`),d.splice(i)),await Promise.all(d.map(async r=>{r.mentions=r.entities?.mentions.map(({username:e})=>e)??[],console.debug(`metrics/compute/${e}/plugins > tweets > formatting tweet ${r.id}`),r.text=t.htmlescape(t.htmlescape(r.text,{"<":!0,">":!0}).replace(new RegExp(`@(${r.mentions.join("|")})`,"gi"),` <span class="mention">@$1</span> `).replace(/(?<!&)[#|#]([a-z0-9_\u00c0-\u00d6\u00d8-\u00f6 Line truncated
query Sha {
repository(owner: "${t.context.repo.owner}", name: "${t.context.repo.repo}") {
object(expression: "${r}:${m}") { ... on Blob { oid } }
}
}
`);o=e}catch(e){console.debug(e)}console.log(`Previous render sha | ${o||"none"}`),await a.repos.createOrUpdateFileContents({...t.context.repo,path:m,message:`Update ${m} - [Skip GitHub Action]`,content:Buffer.from(w).toString("base64"),...(o?{sha:o}:{})}),console.log(`Commit to repo | ok`)}console.log(`Success !`),process.exit(0)}catch(t){if(console.error(t),!i(e.getInput("debug")))for(const e of["_".repeat(64),"An error occured, logging debug message :",...s])console.log(e);e.setFailed(t.message),process.exit(1)}})().catch(()=>process.exit(1))},12541:function(e,t,r){"use strict";function n(e,t,r){const n=new p(e,t,r);process.stdout.write(n.toString()+s.EOL)}function a(e){return l.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function o(e){return l.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/:/g,"%3A").replace(/,/g,"%2C")}var i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t["default"]=e,t};Object.defineProperty(t,"__esModule",{value:!0});const s=i(r(12087)),l=r(74332);t.issueCommand=n,t.issue=function(e,t=""){n(e,{},t)};const d="::";class p{constructor(e,t,r){e||(e="missing.command"),this.command=e,this.properties=t,this.message=r}toString(){let e=d+this.command;if(this.properties&&0<Object.keys(this.properties).length){e+=" ";let t=!0;for(const r in this.properties)if(this.properties.hasOwnProperty(r)){const n=this.properties[r];n&&(t?t=!1:e+=",",e+=`${r}=${o(n)}`)}}return e+=`${d}${a(this.message)}`,e}}},32882:function(e,t,r){"use strict";function n(e){process.exitCode=g.Failure,a(e)}function a(e){d.issue("error",e instanceof Error?e.toString():e)}function o(e){d.issue("group",e)}function i(){d.issue("endgroup")}var s=this&&this.__awaiter||function(e,t,r,n){function a(e){return e instanceof r?e:new r(function(t){t(e)})}return new(r||(r=Promise))(function(r,o){function i(e){try{l(n.next(e))}catch(t){o(t)}}function s(e){try{l(n["throw"](e))}catch(t){o(t)}}function l(e){e.done?r(e.value):a(e.value).then(i,s)}l((n=n.apply(e,t||[])).next())})},l=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t["default"]=e,t};Object.defineProperty(t,"__esModule",{value:!0});const d=r(12541),p=r(29582),c=r(74332),u=l(r(12087)),m=l(r(85622));var g;(function(e){e[e.Success=0]="Success",e[e.Failure=1]="Failure"})(g=t.ExitCode||(t.ExitCode={})),t.exportVariable=function(e,t){const r=c.toCommandValue(t);process.env[e]=r;const n=process.env.GITHUB_ENV||"";if(n){const t=`${e}<<${"_GitHubActionsFileCommandDelimeter_"}${u.EOL}${r}${u.EOL}${"_GitHubActionsFileCommandDelimeter_"}`;p.issueCommand("ENV",t)}else d.issueCommand("set-env",{name:e},r)},t.setSecret=function(e){d.issueCommand("add-mask",{},e)},t.addPath=function(e){const t=process.env.GITHUB_PATH||"";t?p.issueCommand("PATH",e):d.issueCommand("add-path",{},e),process.env.PATH=`${e}${m.delimiter}${process.env.PATH}`},t.getInput=function(e,t){const r=process.env[`INPUT_${e.replace(/ /g,"_").toUpperCase()}`]||"";if(t&&t.required&&!r)throw new Error(`Input required and not supplied: ${e}`);return r.trim()},t.setOutput=function(e,t){d.issueCommand("set-output",{name:e},t)},t.setCommandEcho=function(e){d.issue("echo",e?"on":"off")},t.setFailed=n,t.isDebug=function(){return"1"===process.env.RUNNER_DEBUG},t.debug=function(e){d.issueCommand("debug",{},e)},t.error=a,t.warning=function(e){d.issue("warning",e instanceof Error?e.toString():e)},t.info=function(e){process.stdout.write(e+u.EOL)},t.startGroup=o,t.endGroup=i,t.group=function(e,t){return s(this,void 0,void 0,function*(){o(e);let r;try{r=yield t()}finally{i()}return r})},t.saveState=function(e,t){d.issueCommand("save-state",{name:e},t)},t.getState=function(e){return process.env[`STATE_${e}`]||""}},29582:function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t["default"]=e,t};Object.defineProperty(t,"__esModule",{value:!0});const a=n(r(35747)),o=n(r(12087)),i=r(74332);t.issueCommand=function(e,t){const r=process.env[`GITHUB_${e}`];if(!r)throw new Error(`Unable to find environment variable for file command ${e}`);if(!a.existsSync(r))throw new Error(`Missing file at path: ${r}`);a.appendFileSync(r,`${i.toCommandValue(t)}${o.EOL}`,{encoding:"utf8"})}},74332:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.toCommandValue=function(e){return null===e||void 0===e?"":"string"==typeof e||e instanceof String?e:JSON.stringify(e)}},84873:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Context=void 0;const n=r(35747),a=r(12087);class o{constructor(){if(this.payload={},process.env.GITHUB_EVENT_PATH)if(n.existsSync(process.env.GITHUB_EVENT_PATH))this.p Line truncated
`);o=e}catch(e){console.debug(e)}console.log(`Previous render sha | ${o??"none"}`),await a.repos.createOrUpdateFileContents({...t.context.repo,path:m,message:`Update ${m} - [Skip GitHub Action]`,content:Buffer.from(T).toString("base64"),...(o?{sha:o}:{})}),console.log(`Commit to repo | ok`)}console.log(`Success !`),process.exit(0)}catch(t){if(console.error(t),!i(e.getInput("debug")))for(const e of["_".repeat(64),"An error occured, logging debug message :",...s])console.log(e);e.setFailed(t.message),process.exit(1)}})().catch(()=>process.exit(1))},12541:function(e,t,r){"use strict";function n(e,t,r){const n=new p(e,t,r);process.stdout.write(n.toString()+s.EOL)}function a(e){return l.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function o(e){return l.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/:/g,"%3A").replace(/,/g,"%2C")}var i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t["default"]=e,t};Object.defineProperty(t,"__esModule",{value:!0});const s=i(r(12087)),l=r(74332);t.issueCommand=n,t.issue=function(e,t=""){n(e,{},t)};const d="::";class p{constructor(e,t,r){e||(e="missing.command"),this.command=e,this.properties=t,this.message=r}toString(){let e=d+this.command;if(this.properties&&0<Object.keys(this.properties).length){e+=" ";let t=!0;for(const r in this.properties)if(this.properties.hasOwnProperty(r)){const n=this.properties[r];n&&(t?t=!1:e+=",",e+=`${r}=${o(n)}`)}}return e+=`${d}${a(this.message)}`,e}}},32882:function(e,t,r){"use strict";function n(e){process.exitCode=g.Failure,a(e)}function a(e){d.issue("error",e instanceof Error?e.toString():e)}function o(e){d.issue("group",e)}function i(){d.issue("endgroup")}var s=this&&this.__awaiter||function(e,t,r,n){function a(e){return e instanceof r?e:new r(function(t){t(e)})}return new(r||(r=Promise))(function(r,o){function i(e){try{l(n.next(e))}catch(t){o(t)}}function s(e){try{l(n["throw"](e))}catch(t){o(t)}}function l(e){e.done?r(e.value):a(e.value).then(i,s)}l((n=n.apply(e,t||[])).next())})},l=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t["default"]=e,t};Object.defineProperty(t,"__esModule",{value:!0});const d=r(12541),p=r(29582),c=r(74332),u=l(r(12087)),m=l(r(85622));var g;(function(e){e[e.Success=0]="Success",e[e.Failure=1]="Failure"})(g=t.ExitCode||(t.ExitCode={})),t.exportVariable=function(e,t){const r=c.toCommandValue(t);process.env[e]=r;const n=process.env.GITHUB_ENV||"";if(n){const t=`${e}<<${"_GitHubActionsFileCommandDelimeter_"}${u.EOL}${r}${u.EOL}${"_GitHubActionsFileCommandDelimeter_"}`;p.issueCommand("ENV",t)}else d.issueCommand("set-env",{name:e},r)},t.setSecret=function(e){d.issueCommand("add-mask",{},e)},t.addPath=function(e){const t=process.env.GITHUB_PATH||"";t?p.issueCommand("PATH",e):d.issueCommand("add-path",{},e),process.env.PATH=`${e}${m.delimiter}${process.env.PATH}`},t.getInput=function(e,t){const r=process.env[`INPUT_${e.replace(/ /g,"_").toUpperCase()}`]||"";if(t&&t.required&&!r)throw new Error(`Input required and not supplied: ${e}`);return r.trim()},t.setOutput=function(e,t){d.issueCommand("set-output",{name:e},t)},t.setCommandEcho=function(e){d.issue("echo",e?"on":"off")},t.setFailed=n,t.isDebug=function(){return"1"===process.env.RUNNER_DEBUG},t.debug=function(e){d.issueCommand("debug",{},e)},t.error=a,t.warning=function(e){d.issue("warning",e instanceof Error?e.toString():e)},t.info=function(e){process.stdout.write(e+u.EOL)},t.startGroup=o,t.endGroup=i,t.group=function(e,t){return s(this,void 0,void 0,function*(){o(e);let r;try{r=yield t()}finally{i()}return r})},t.saveState=function(e,t){d.issueCommand("save-state",{name:e},t)},t.getState=function(e){return process.env[`STATE_${e}`]||""}},29582:function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t["default"]=e,t};Object.defineProperty(t,"__esModule",{value:!0});const a=n(r(35747)),o=n(r(12087)),i=r(74332);t.issueCommand=function(e,t){const r=process.env[`GITHUB_${e}`];if(!r)throw new Error(`Unable to find environment variable for file command ${e}`);if(!a.existsSync(r))throw new Error(`Missing file at path: ${r}`);a.appendFileSync(r,`${i.toCommandValue(t)}${o.EOL}`,{encoding:"utf8"})}},74332:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.toCommandValue=function(e){return null===e||void 0===e?"":"string"==typeof e||e instanceof String?e:JSON.stringify(e)}},84873:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Context=void 0;const n=r(35747),a=r(12087);class o{constructor(){if(this.payload={},process.env.GITHUB_EVENT_PATH)if(n.existsSync(process.env.GITHUB_EVENT_PATH))this.p Line truncated
* @file Embedded JavaScript templating engine. {@link http://ejs.co}
* @author Matthew Eernisse <mde@fleegix.org>
* @author Tiancheng "Timothy" Gu <timothygu99@gmail.com>
* @project EJS
* @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0}
*/function n(e,r){var n;if(r.some(function(r){return n=t.resolveInclude(e,r,!0),g.existsSync(n)}))return n}function a(e,r){var a=r.views,o=/^[A-Za-z]+:\\|^\//.exec(e),i,s;if(o&&o.length)e=e.replace(/^\/*/,""),i=Array.isArray(r.root)?n(e,r.root):t.resolveInclude(e,r.root||"/",!0);else if(r.filename&&(s=t.resolveInclude(e,r.filename),g.existsSync(s)&&(i=s)),!i&&Array.isArray(a)&&(i=n(e,a)),!i&&"function"!=typeof r.includer)throw new Error("Could not find the include file \""+r.escapeFunction(e)+"\"");return i}function i(e,r){var n=e.filename,a=1<arguments.length,o;if(e.cache){if(!n)throw new Error("cache option requires a filename");if(o=t.cache.get(n),o)return o;a||(r=l(n).toString().replace(x,""))}else if(!a){if(!n)throw new Error("Internal EJS error: no file name or template provided");r=l(n).toString().replace(x,"")}return o=t.compile(r,e),e.cache&&t.cache.set(n,o),o}function s(e,r,n){var a;if(!n){if("function"==typeof t.promiseImpl)return new t.promiseImpl(function(t,n){try{a=i(e)(r),t(a)}catch(e){n(e)}});throw new Error("Please provide a callback function")}else{try{a=i(e)(r)}catch(e){return n(e)}n(null,a)}}function l(e){return t.fileLoader(e)}function p(e,t){var r=h.shallowCopy({},t);if(r.filename=a(e,r),"function"==typeof t.includer){var n=t.includer(e,r.filename);if(n&&(n.filename&&(r.filename=n.filename),n.template))return i(r,n.template)}return i(r)}function c(e,t,r,n,a){var o=t.split("\n"),s=_Mathmax(n-3,0),l=_Mathmin(o.length,n+3),d=a(r),p=o.slice(s,l).map(function(e,t){var r=t+s+1;return(r==n?" >> ":" ")+r+"| "+e}).join("\n");throw e.path=d,e.message=(d||"ejs")+":"+n+"\n"+p+"\n\n"+e.message,e}function u(e){return e.replace(/;(\s*$)/,"$1")}function m(e,r){r=r||{};var n={};this.templateText=e,this.mode=null,this.truncate=!1,this.currentLine=1,this.source="",n.client=r.client||!1,n.escapeFunction=r.escape||r.escapeFunction||h.escapeXML,n.compileDebug=!1!==r.compileDebug,n.debug=!!r.debug,n.filename=r.filename,n.openDelimiter=r.openDelimiter||t.openDelimiter||"<",n.closeDelimiter=r.closeDelimiter||t.closeDelimiter||">",n.delimiter=r.delimiter||t.delimiter||"%",n.strict=r.strict||!1,n.context=r.context,n.cache=r.cache||!1,n.rmWhitespace=r.rmWhitespace,n.root=r.root,n.includer=r.includer,n.outputFunctionName=r.outputFunctionName,n.localsName=r.localsName||t.localsName||"locals",n.views=r.views,n.async=r.async,n.destructuredLocals=r.destructuredLocals,n.legacyInclude="undefined"==typeof r.legacyInclude||!!r.legacyInclude,n._with=!n.strict&&("undefined"==typeof r._with||r._with),this.opts=n,this.regex=this.createRegex()}var g=r(35747),o=r(85622),h=r(74998),f=!1,y=r(52021).i8,b=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"],S=b.concat("cache"),x=/^\uFEFF/;t.cache=h.cache,t.fileLoader=g.readFileSync,t.localsName="locals",t.promiseImpl=new Function("return this;")().Promise,t.resolveInclude=function(e,t,r){var n=o.dirname,a=o.extname,i=o.resolve,s=i(r?t:n(t),e),l=a(e);return l||(s+=".ejs"),s},t.compile=function(e,t){var r;return t&&t.scope&&(!f&&(console.warn("`scope` option is deprecated and will be removed in EJS 3"),f=!0),!t.context&&(t.context=t.scope),delete t.scope),r=new m(e,t),r.compile()},t.render=function(e,t,r){var n=t||{},a=r||{};return 2==arguments.length&&h.shallowCopyFromList(a,n,b),i(a,e)(n)},t.renderFile=function(){var e=Array.prototype.slice.call(arguments),t=e.shift(),r={filename:t},n,a,o;return"function"==typeof arguments[arguments.length-1]&&(n=e.pop()),e.length?(a=e.shift(),e.length?h.shallowCopy(r,e.pop()):(a.settings&&(a.settings.views&&(r.views=a.settings.views),a.settings["view cache"]&&(r.cache=!0),o=a.settings["view options"],o&&h.shallowCopy(r,o)),h.shallowCopyFromList(r,a,S)),r.filename=t):a={},s(r,a,n)},t.Template=m,t.clearCache=function(){t.cache.reset()},m.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"},m.prototype={createRegex:function(){var e="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)",t=h.escapeRegExpChars(this.opts.delimiter),r=h.escapeRegExpChars(this.opts.openDelimiter),n=h.escapeRegExpChars(this.opts.closeDelimiter);return e=e.replace(/%/g,t).replace(/</g,r).replace(/>/g,n),new RegExp(e)},compile:function(){var t=this.opts,r="",n="",a=t.escapeFunction,s,l,e;if(!this.source){if(this.generateSource(),r+=" var __output = \"\";\n function __append(s) { if (s !== undefined && s !== null) __output += s }\n",t.outputFunctionName&&(r+=" var "+t.outputFunctionName+" = __append;\n"),t.destructuredLocals&&t.destructuredLocals.length){for(var d=" var __locals = ("+t.localsName+" || {}),\n",u=0,m;u<t.destructuredLocals.length;u++)m=t.destructuredLocals[u],0<u&&(d+=",\n "),d+=m+" = __locals."+m;r+=d+";\n"}!1!==t._with&&(r+=" with ("+t.localsName+" || {}) {\n",n+=" }\n"),n+=" return __output;\n",this.source=r+this.source+n}s=t.compileDebug?"var __line = 1\n , __lines = "+JSON.stringify(this.templateText)+"\n , __filename = "+(t.filename?JSON.stringify(t.filename):"un Line truncated
*/function n(e,r){var n;if(r.some(function(r){return n=t.resolveInclude(e,r,!0),g.existsSync(n)}))return n}function a(e,r){var a=r.views,o=/^[A-Za-z]+:\\|^\//.exec(e),i,s;if(o&&o.length)e=e.replace(/^\/*/,""),i=Array.isArray(r.root)?n(e,r.root):t.resolveInclude(e,r.root||"/",!0);else if(r.filename&&(s=t.resolveInclude(e,r.filename),g.existsSync(s)&&(i=s)),!i&&Array.isArray(a)&&(i=n(e,a)),!i&&"function"!=typeof r.includer)throw new Error("Could not find the include file \""+r.escapeFunction(e)+"\"");return i}function i(e,r){var n=e.filename,a=1<arguments.length,o;if(e.cache){if(!n)throw new Error("cache option requires a filename");if(o=t.cache.get(n),o)return o;a||(r=l(n).toString().replace(x,""))}else if(!a){if(!n)throw new Error("Internal EJS error: no file name or template provided");r=l(n).toString().replace(x,"")}return o=t.compile(r,e),e.cache&&t.cache.set(n,o),o}function s(e,r,n){var a;if(!n){if("function"==typeof t.promiseImpl)return new t.promiseImpl(function(t,n){try{a=i(e)(r),t(a)}catch(e){n(e)}});throw new Error("Please provide a callback function")}else{try{a=i(e)(r)}catch(e){return n(e)}n(null,a)}}function l(e){return t.fileLoader(e)}function p(e,t){var r=h.shallowCopy({},t);if(r.filename=a(e,r),"function"==typeof t.includer){var n=t.includer(e,r.filename);if(n&&(n.filename&&(r.filename=n.filename),n.template))return i(r,n.template)}return i(r)}function c(e,t,r,n,a){var o=t.split("\n"),s=_Mathmax(n-3,0),l=_Mathmin(o.length,n+3),d=a(r),p=o.slice(s,l).map(function(e,t){var r=t+s+1;return(r==n?" >> ":" ")+r+"| "+e}).join("\n");throw e.path=d,e.message=(d||"ejs")+":"+n+"\n"+p+"\n\n"+e.message,e}function u(e){return e.replace(/;(\s*$)/,"$1")}function m(e,r){r=r||{};var n={};this.templateText=e,this.mode=null,this.truncate=!1,this.currentLine=1,this.source="",n.client=r.client||!1,n.escapeFunction=r.escape||r.escapeFunction||h.escapeXML,n.compileDebug=!1!==r.compileDebug,n.debug=!!r.debug,n.filename=r.filename,n.openDelimiter=r.openDelimiter||t.openDelimiter||"<",n.closeDelimiter=r.closeDelimiter||t.closeDelimiter||">",n.delimiter=r.delimiter||t.delimiter||"%",n.strict=r.strict||!1,n.context=r.context,n.cache=r.cache||!1,n.rmWhitespace=r.rmWhitespace,n.root=r.root,n.includer=r.includer,n.outputFunctionName=r.outputFunctionName,n.localsName=r.localsName||t.localsName||"locals",n.views=r.views,n.async=r.async,n.destructuredLocals=r.destructuredLocals,n.legacyInclude="undefined"==typeof r.legacyInclude||!!r.legacyInclude,n._with=!n.strict&&("undefined"==typeof r._with||r._with),this.opts=n,this.regex=this.createRegex()}var g=r(35747),o=r(85622),h=r(74998),f=!1,y=r(52021).i8,b=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"],S=b.concat("cache"),x=/^\uFEFF/;t.cache=h.cache,t.fileLoader=g.readFileSync,t.localsName="locals",t.promiseImpl=new Function("return this;")().Promise,t.resolveInclude=function(e,t,r){var n=o.dirname,a=o.extname,i=o.resolve,s=i(r?t:n(t),e),l=a(e);return l||(s+=".ejs"),s},t.compile=function(e,t){var r;return t&&t.scope&&(!f&&(console.warn("`scope` option is deprecated and will be removed in EJS 3"),f=!0),!t.context&&(t.context=t.scope),delete t.scope),r=new m(e,t),r.compile()},t.render=function(e,t,r){var n=t||{},a=r||{};return 2==arguments.length&&h.shallowCopyFromList(a,n,b),i(a,e)(n)},t.renderFile=function(){var e=Array.prototype.slice.call(arguments),t=e.shift(),r={filename:t},n,a,o;return"function"==typeof arguments[arguments.length-1]&&(n=e.pop()),e.length?(a=e.shift(),e.length?h.shallowCopy(r,e.pop()):(a.settings&&(a.settings.views&&(r.views=a.settings.views),a.settings["view cache"]&&(r.cache=!0),o=a.settings["view options"],o&&h.shallowCopy(r,o)),h.shallowCopyFromList(r,a,S)),r.filename=t):a={},s(r,a,n)},t.Template=m,t.clearCache=function(){t.cache.reset()},m.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"},m.prototype={createRegex:function(){var e="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)",t=h.escapeRegExpChars(this.opts.delimiter),r=h.escapeRegExpChars(this.opts.openDelimiter),n=h.escapeRegExpChars(this.opts.closeDelimiter);return e=e.replace(/%/g,t).replace(/</g,r).replace(/>/g,n),new RegExp(e)},compile:function(){var t=this.opts,r="",n="",a=t.escapeFunction,s,l,e;if(!this.source){if(this.generateSource(),r+=" var __output = \"\";\n function __append(s) { if (s !== undefined && s !== null) __output += s }\n",t.outputFunctionName&&(r+=" var "+t.outputFunctionName+" = __append;\n"),t.destructuredLocals&&t.destructuredLocals.length){for(var d=" var __locals = ("+t.localsName+" || {}),\n",u=0,m;u<t.destructuredLocals.length;u++)m=t.destructuredLocals[u],0<u&&(d+=",\n "),d+=m+" = __locals."+m;r+=d+";\n"}!1!==t._with&&(r+=" with ("+t.localsName+" || {}) {\n",n+=" }\n"),n+=" return __output;\n",this.source=r+this.source+n}s=t.compileDebug?"var __line = 1\n , __lines = "+JSON.stringify(this.templateText)+"\n , __filename = "+(t.filename?JSON.stringify(t.filename):"un Line truncated
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
*
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*/function r(e){return"[object Object]"===Object.prototype.toString.call(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.isPlainObject=function(e){var t,n;return!1!==r(e)&&((t=e.constructor,void 0===t)||(n=t.prototype,!1!==r(n)&&!1!==n.hasOwnProperty("isPrototypeOf")))}},31894:(e,t,r)=>{"use strict";var n=r(7158);e.exports=n},7158:(e,t,r)=>{"use strict";function n(e){return function(){throw new Error("Function "+e+" is deprecated and cannot be used.")}}var a=r(3434),o=r(86156);e.exports.Type=r(78099),e.exports.Schema=r(58126),e.exports.FAILSAFE_SCHEMA=r(21712),e.exports.JSON_SCHEMA=r(75698),e.exports.CORE_SCHEMA=r(11277),e.exports.DEFAULT_SAFE_SCHEMA=r(23713),e.exports.DEFAULT_FULL_SCHEMA=r(17028),e.exports.load=a.load,e.exports.loadAll=a.loadAll,e.exports.safeLoad=a.safeLoad,e.exports.safeLoadAll=a.safeLoadAll,e.exports.dump=o.dump,e.exports.safeDump=o.safeDump,e.exports.YAMLException=r(41030),e.exports.MINIMAL_SCHEMA=r(21712),e.exports.SAFE_SCHEMA=r(23713),e.exports.DEFAULT_SCHEMA=r(17028),e.exports.scan=n("scan"),e.exports.parse=n("parse"),e.exports.compose=n("compose"),e.exports.addConstructor=n("addConstructor")},39990:e=>{"use strict";function t(e){return"undefined"==typeof e||null===e}e.exports.isNothing=t,e.exports.isObject=function(e){return"object"==typeof e&&null!==e},e.exports.toArray=function(e){return Array.isArray(e)?e:t(e)?[]:[e]},e.exports.repeat=function(e,t){var r="",n;for(n=0;n<t;n+=1)r+=e;return r},e.exports.isNegativeZero=function(e){return 0===e&&_NumberNEGATIVE_INFINITY===1/e},e.exports.extend=function(e,t){var r,n,a,o;if(t)for(o=Object.keys(t),r=0,n=o.length;r<n;r+=1)a=o[r],e[a]=t[a];return e}},86156:(e,t,r)=>{"use strict";function n(e,t){var r,n,a,o,i,s,l;if(null===t)return{};for(r={},n=Object.keys(t),(a=0,o=n.length);a<o;a+=1)i=n[a],s=t[i]+"","!!"===i.slice(0,2)&&(i="tag:yaml.org,2002:"+i.slice(2)),l=e.compiledTypeMap.fallback[i],l&&q.call(l.styleAliases,s)&&(s=l.styleAliases[s]),r[i]=s;return r}function a(e){var t,r,n;if(t=e.toString(16).toUpperCase(),255>=e)r="x",n=2;else if(65535>=e)r="u",n=4;else if(4294967295>=e)r="U",n=8;else throw new R("code point within a string may not be greater than 0xFFFFFFFF");return"\\"+r+z.repeat("0",n-t.length)+t}function o(e){this.schema=e.schema||M,this.indent=_Mathmax(1,e.indent||2),this.noArrayIndent=e.noArrayIndent||!1,this.skipInvalid=e.skipInvalid||!1,this.flowLevel=z.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=n(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.condenseFlow=e.condenseFlow||!1,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function i(e,t){for(var r=z.repeat(" ",t),n=0,a=-1,o="",i=e.length,s;n<i;)a=e.indexOf("\n",n),-1===a?(s=e.slice(n),n=i):(s=e.slice(n,a+1),n=a+1),s.length&&"\n"!==s&&(o+=r),o+=s;return o}function s(e,t){return"\n"+z.repeat(" ",e.indent*t)}function l(e,t){var r,n,a;for(r=0,n=e.implicitTypes.length;r<n;r+=1)if(a=e.implicitTypes[r],a.resolve(t))return!0;return!1}function d(e){return 32===e||9===e}function p(e){return 32<=e&&126>=e||161<=e&&55295>=e&&8232!==e&&8233!==e||57344<=e&&65533>=e&&65279!==e||65536<=e&&1114111>=e}function u(e){return p(e)&&!d(e)&&65279!==e&&13!==e&&10!==e}function m(e,t){return p(e)&&65279!==e&&44!==e&&91!==e&&93!==e&&123!==e&&125!==e&&58!==e&&(35!==e||t&&u(t))}function g(e){return p(e)&&65279!==e&&!d(e)&&45!==e&&63!==e&&58!==e&&44!==e&&91!==e&&93!==e&&123!==e&&125!==e&&35!==e&&38!==e&&42!==e&&33!==e&&124!==e&&61!==e&&62!==e&&39!==e&&34!==e&&37!==e&&64!==e&&96!==e}function h(e){return /^\n* /.test(e)}function f(e,t,r,n,a){var o=!1,s=!1,l=-1!==n,c=-1,u=g(e.charCodeAt(0))&&!d(e.charCodeAt(e.length-1)),f,y,b;if(t)for(f=0;f<e.length;f++){if(y=e.charCodeAt(f),!p(y))return 5;b=0<f?e.charCodeAt(f-1):null,u=u&&m(y,b)}else{for(f=0;f<e.length;f++){if(y=e.charCodeAt(f),10===y)o=!0,l&&(s=s||f-c-1>n&&" "!==e[c+1],c=f);else if(!p(y))return 5;b=0<f?e.charCodeAt(f-1):null,u=u&&m(y,b)}s=s||l&&f-c-1>n&&" "!==e[c+1]}return o||s?9<r&&h(e)?5:s?4:3:u&&!a(e)?1:2}function y(e,t,r,n){e.dump=function(){function a(t){return l(e,t)}if(0===t.length)return"''";if(!e.noCompatMode&&-1!==N.indexOf(t))return"'"+t+"'";var o=e.indent*_Mathmax(1,r),s=-1===e.lineWidth?-1:_Mathmax(_Mathmin(e.lineWidth,40),e.lineWidth-o),d=n||-1<e.flowLevel&&r>=e.flowLevel;switch(f(t,d,e.indent,s,a)){case 1:return t;case 2:return"'"+t.replace(/'/g,"''")+"'";case 3:return"|"+b(t,e.indent)+S(i(t,o));case 4:return">"+b(t,e.indent)+S(i(x(t,s),o));case 5:return"\""+k(t,s)+"\"";default:throw new R("impossible error: invalid scalar style");}}()}function b(e,t){var r=h(e)?t+"":"",n="\n"===e[e.length-1],a=n&&("\n"===e[e.length-2]||"\n"===e),o=a?"+":n?"":"-";return r+o+"\n"}function S(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function x(e,t){for(var r=/(\n+)([^\n]*)/g,n=function(){var n=e.indexOf("\n");returnLine truncated
*/function r(e){return"[object Object]"===Object.prototype.toString.call(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.isPlainObject=function(e){var t,n;return!1!==r(e)&&((t=e.constructor,void 0===t)||(n=t.prototype,!1!==r(n)&&!1!==n.hasOwnProperty("isPrototypeOf")))}},31894:(e,t,r)=>{"use strict";var n=r(7158);e.exports=n},7158:(e,t,r)=>{"use strict";function n(e){return function(){throw new Error("Function "+e+" is deprecated and cannot be used.")}}var a=r(3434),o=r(86156);e.exports.Type=r(78099),e.exports.Schema=r(58126),e.exports.FAILSAFE_SCHEMA=r(21712),e.exports.JSON_SCHEMA=r(75698),e.exports.CORE_SCHEMA=r(11277),e.exports.DEFAULT_SAFE_SCHEMA=r(23713),e.exports.DEFAULT_FULL_SCHEMA=r(17028),e.exports.load=a.load,e.exports.loadAll=a.loadAll,e.exports.safeLoad=a.safeLoad,e.exports.safeLoadAll=a.safeLoadAll,e.exports.dump=o.dump,e.exports.safeDump=o.safeDump,e.exports.YAMLException=r(41030),e.exports.MINIMAL_SCHEMA=r(21712),e.exports.SAFE_SCHEMA=r(23713),e.exports.DEFAULT_SCHEMA=r(17028),e.exports.scan=n("scan"),e.exports.parse=n("parse"),e.exports.compose=n("compose"),e.exports.addConstructor=n("addConstructor")},39990:e=>{"use strict";function t(e){return"undefined"==typeof e||null===e}e.exports.isNothing=t,e.exports.isObject=function(e){return"object"==typeof e&&null!==e},e.exports.toArray=function(e){return Array.isArray(e)?e:t(e)?[]:[e]},e.exports.repeat=function(e,t){var r="",n;for(n=0;n<t;n+=1)r+=e;return r},e.exports.isNegativeZero=function(e){return 0===e&&_NumberNEGATIVE_INFINITY===1/e},e.exports.extend=function(e,t){var r,n,a,o;if(t)for(o=Object.keys(t),r=0,n=o.length;r<n;r+=1)a=o[r],e[a]=t[a];return e}},86156:(e,t,r)=>{"use strict";function n(e,t){var r,n,a,o,i,s,l;if(null===t)return{};for(r={},n=Object.keys(t),(a=0,o=n.length);a<o;a+=1)i=n[a],s=t[i]+"","!!"===i.slice(0,2)&&(i="tag:yaml.org,2002:"+i.slice(2)),l=e.compiledTypeMap.fallback[i],l&&q.call(l.styleAliases,s)&&(s=l.styleAliases[s]),r[i]=s;return r}function a(e){var t,r,n;if(t=e.toString(16).toUpperCase(),255>=e)r="x",n=2;else if(65535>=e)r="u",n=4;else if(4294967295>=e)r="U",n=8;else throw new R("code point within a string may not be greater than 0xFFFFFFFF");return"\\"+r+z.repeat("0",n-t.length)+t}function o(e){this.schema=e.schema||I,this.indent=_Mathmax(1,e.indent||2),this.noArrayIndent=e.noArrayIndent||!1,this.skipInvalid=e.skipInvalid||!1,this.flowLevel=z.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=n(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.condenseFlow=e.condenseFlow||!1,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function i(e,t){for(var r=z.repeat(" ",t),n=0,a=-1,o="",i=e.length,s;n<i;)a=e.indexOf("\n",n),-1===a?(s=e.slice(n),n=i):(s=e.slice(n,a+1),n=a+1),s.length&&"\n"!==s&&(o+=r),o+=s;return o}function s(e,t){return"\n"+z.repeat(" ",e.indent*t)}function l(e,t){var r,n,a;for(r=0,n=e.implicitTypes.length;r<n;r+=1)if(a=e.implicitTypes[r],a.resolve(t))return!0;return!1}function d(e){return 32===e||9===e}function p(e){return 32<=e&&126>=e||161<=e&&55295>=e&&8232!==e&&8233!==e||57344<=e&&65533>=e&&65279!==e||65536<=e&&1114111>=e}function u(e){return p(e)&&!d(e)&&65279!==e&&13!==e&&10!==e}function m(e,t){return p(e)&&65279!==e&&44!==e&&91!==e&&93!==e&&123!==e&&125!==e&&58!==e&&(35!==e||t&&u(t))}function g(e){return p(e)&&65279!==e&&!d(e)&&45!==e&&63!==e&&58!==e&&44!==e&&91!==e&&93!==e&&123!==e&&125!==e&&35!==e&&38!==e&&42!==e&&33!==e&&124!==e&&61!==e&&62!==e&&39!==e&&34!==e&&37!==e&&64!==e&&96!==e}function h(e){return /^\n* /.test(e)}function f(e,t,r,n,a){var o=!1,s=!1,l=-1!==n,c=-1,u=g(e.charCodeAt(0))&&!d(e.charCodeAt(e.length-1)),f,y,b;if(t)for(f=0;f<e.length;f++){if(y=e.charCodeAt(f),!p(y))return 5;b=0<f?e.charCodeAt(f-1):null,u=u&&m(y,b)}else{for(f=0;f<e.length;f++){if(y=e.charCodeAt(f),10===y)o=!0,l&&(s=s||f-c-1>n&&" "!==e[c+1],c=f);else if(!p(y))return 5;b=0<f?e.charCodeAt(f-1):null,u=u&&m(y,b)}s=s||l&&f-c-1>n&&" "!==e[c+1]}return o||s?9<r&&h(e)?5:s?4:3:u&&!a(e)?1:2}function y(e,t,r,n){e.dump=function(){function a(t){return l(e,t)}if(0===t.length)return"''";if(!e.noCompatMode&&-1!==N.indexOf(t))return"'"+t+"'";var o=e.indent*_Mathmax(1,r),s=-1===e.lineWidth?-1:_Mathmax(_Mathmin(e.lineWidth,40),e.lineWidth-o),d=n||-1<e.flowLevel&&r>=e.flowLevel;switch(f(t,d,e.indent,s,a)){case 1:return t;case 2:return"'"+t.replace(/'/g,"''")+"'";case 3:return"|"+b(t,e.indent)+S(i(t,o));case 4:return">"+b(t,e.indent)+S(i(x(t,s),o));case 5:return"\""+k(t,s)+"\"";default:throw new R("impossible error: invalid scalar style");}}()}function b(e,t){var r=h(e)?t+"":"",n="\n"===e[e.length-1],a=n&&("\n"===e[e.length-2]||"\n"===e),o=a?"+":n?"":"-";return r+o+"\n"}function S(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function x(e,t){for(var r=/(\n+)([^\n]*)/g,n=function(){var n=e.indexOf("\n");returnLine truncated
(() => {
${r}
const checkWaitForOptions = ${function(e,t,r){if(!e)return r;if(!t&&!r)return e;const n=e.nodeType===Node.TEXT_NODE?e.parentElement:e,a=window.getComputedStyle(n),o=a&&"hidden"!==a.visibility&&function(){const e=n.getBoundingClientRect();return!!(e.top||e.bottom||e.width||e.height)}();return t===o||r===!o?e:null}};
return (${e})(...args)
})() `},readProtocolStream:async function(e,t,r){if(!g.isNode&&r)throw new Error("Cannot write to a path outside of Node.js environment.");const n=g.isNode?await s():null;let a=!1,o;r&&n&&(o=await n.promises.open(r,"w"));const i=[];for(;!a;){const s=await e.send("IO.read",{handle:t});a=s.eof;const l=Buffer.from(s.data,s.base64Encoded?"base64":void 0);i.push(l),r&&n&&(await n.promises.writeFile(o,l))}r&&(await o.close()),await e.send("IO.close",{handle:t});let l=null;try{l=Buffer.concat(i)}finally{return l}},waitWithTimeout:async function(e,t,r){let n;const a=new c.TimeoutError(`waiting for ${t} failed: timeout ${r}ms exceeded`),o=new Promise((e,t)=>n=t);let i=null;r&&(i=setTimeout(()=>n(a),r));try{return await Promise.race([e,o])}finally{i&&clearTimeout(i)}},waitForEvent:async function(e,t,r,o,i){function s(){a([m]),clearTimeout(l)}let l,d,p;const u=new Promise((e,t)=>{d=e,p=t}),m=n(e,t,e=>{r(e)&&d(e)});o&&(l=setTimeout(()=>{p(new c.TimeoutError("Timeout exceeded while waiting for event"))},o));const g=await Promise.race([u,i]).then(e=>(s(),e),e=>{throw s(),e});if(g instanceof Error)throw g;return g},isString:o,isNumber:function(e){return"number"==typeof e||e instanceof Number},importFSModule:s,addEventListener:n,removeEventListeners:a,valueFromRemoteObject:function(e){if(m.assert(!e.objectId,"Cannot extract value when objectId is given"),e.unserializableValue){if("bigint"===e.type&&"undefined"!=typeof BigInt)return BigInt(e.unserializableValue.replace("n",""));switch(e.unserializableValue){case"-0":return-0;case"NaN":return NaN;case"Infinity":return 1/0;case"-Infinity":return-Infinity;default:throw new Error("Unsupported unserializable value: "+e.unserializableValue);}}return e.value},getExceptionMessage:function(e){if(e.exception)return e.exception.description||e.exception.value;let t=e.text;if(e.stackTrace)for(const r of e.stackTrace.callFrames){const e=r.url+":"+r.lineNumber+":"+r.columnNumber,n=r.functionName||"<anonymous>";t+=`\n at ${n} (${e})`}return t},releaseObject:async function(e,r){r.objectId&&(await e.send("Runtime.releaseObject",{objectId:r.objectId}).catch(e=>{t.debugError(e)}))}}},23222:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isNode=void 0,t.isNode=!!("undefined"!=typeof process&&process.version)},80527:function(e,t,r){"use strict";var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.initializePuppeteerNode=void 0;const a=r(9323),o=r(14148),i=n(r(10837));t.initializePuppeteerNode=e=>{const t=i.default.sync(__dirname);let r=o.PUPPETEER_REVISIONS.chromium;const n="puppeteer-core"===e,s=n?void 0:process.env.PUPPETEER_PRODUCT||process.env.npm_config_puppeteer_product||process.env.npm_package_config_puppeteer_product;return n||"firefox"!==s||(r=o.PUPPETEER_REVISIONS.firefox),new a.PuppeteerNode({projectRoot:t,preferredRevision:r,isPuppeteerCore:n,productName:s})}},90176:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});const n=r(80527),a=r(23222);if(!a.isNode)throw new Error("Trying to run Puppeteer-Node in a web environment.");t.default=n.initializePuppeteerNode("puppeteer")},77463:function(e,t,r){"use strict";function n(e,t,r){if("chrome"===e){if("linux"===t)return"chrome-linux";if("mac"===t)return"chrome-mac";if("win32"===t||"win64"===t)return 591479<parseInt(r,10)?"chrome-win":"chrome-win32"}else if("firefox"===e)return t}function a(e,t,r,a){const o=x.format(R[e][t],r,a,n(e,t,a));return o}function o(){b.stat("/usr/bin/chromium-browser",function(e,t){if(void 0===t)throw console.error(`The chromium binary is not available for arm64: `),console.error(`If you are on Ubuntu, you can install with: `),console.error(`\n apt-get install chromium-browser\n`),new Error})}function i(e){return new Promise(t=>{b.access(e,e=>t(!e))})}function s(e,t){const r=S.basename(t),n=r.split("-");if(2!==n.length)return null;const[a,o]=n;return R[e][a]?{product:e,platform:a,revision:o}:null}function l(e,t,r){function n(e){a+=e.length,r(a,o)}z(`Downloading binary from ${e}`);let a=0,o=0,i,s;const l=new Promise((e,t)=>{i=e,s=t}),d=u(e,"GET",a=>{if(200!==a.statusCode){const t=new Error(`Download failed: server returned code ${a.statusCode}. URL: ${e}`);return a.resume(),void s(t)}const l=b.createWriteStream(t);l.on("finish",()=>i()),l.on("error",e=>s(e)),a.pipe(l),o=parseInt(a.headers["content-length"],10),r&&a.on("data",n)});return d.on("error",e=>s(e)),l}function d(e,t){if(z(`Installing ${e} to ${t}`),e.endsWith(".zip"))return _.default(e,{dir:t});if(e.endsWith(".tar.bz2"))return p(e,t);if(e.endsWith(".dmg"))return W(t).then(()=>c(e,t));throw new Error(`Unsupported archive format: ${e}`)}function p(e,t){const n=r(16974),a=r(1650);return new Promise((r,o)=>{const i=n.extract(t);i.on("error",o),i.on("finish",r);const s=b.createReadStream(e);s.pipe(a()).pipe(i)})}function c(e,t){function r(){if(n){const e=`hdiutil detach "${n}" -quiet`;z(`Unmounting ${n}`),v.exec(e,e=>{e&&console. Line truncated
})() `},readProtocolStream:async function(e,t,r){if(!g.isNode&&r)throw new Error("Cannot write to a path outside of Node.js environment.");const n=g.isNode?await s():null;let a=!1,o;r&&n&&(o=await n.promises.open(r,"w"));const i=[];for(;!a;){const s=await e.send("IO.read",{handle:t});a=s.eof;const l=Buffer.from(s.data,s.base64Encoded?"base64":void 0);i.push(l),r&&n&&(await n.promises.writeFile(o,l))}r&&(await o.close()),await e.send("IO.close",{handle:t});let l=null;try{l=Buffer.concat(i)}finally{return l}},waitWithTimeout:async function(e,t,r){let n;const a=new c.TimeoutError(`waiting for ${t} failed: timeout ${r}ms exceeded`),o=new Promise((e,t)=>n=t);let i=null;r&&(i=setTimeout(()=>n(a),r));try{return await Promise.race([e,o])}finally{i&&clearTimeout(i)}},waitForEvent:async function(e,t,r,o,i){function s(){a([m]),clearTimeout(l)}let l,d,p;const u=new Promise((e,t)=>{d=e,p=t}),m=n(e,t,e=>{r(e)&&d(e)});o&&(l=setTimeout(()=>{p(new c.TimeoutError("Timeout exceeded while waiting for event"))},o));const g=await Promise.race([u,i]).then(e=>(s(),e),e=>{throw s(),e});if(g instanceof Error)throw g;return g},isString:o,isNumber:function(e){return"number"==typeof e||e instanceof Number},importFSModule:s,addEventListener:n,removeEventListeners:a,valueFromRemoteObject:function(e){if(m.assert(!e.objectId,"Cannot extract value when objectId is given"),e.unserializableValue){if("bigint"===e.type&&"undefined"!=typeof BigInt)return BigInt(e.unserializableValue.replace("n",""));switch(e.unserializableValue){case"-0":return-0;case"NaN":return NaN;case"Infinity":return 1/0;case"-Infinity":return-Infinity;default:throw new Error("Unsupported unserializable value: "+e.unserializableValue);}}return e.value},getExceptionMessage:function(e){if(e.exception)return e.exception.description||e.exception.value;let t=e.text;if(e.stackTrace)for(const r of e.stackTrace.callFrames){const e=r.url+":"+r.lineNumber+":"+r.columnNumber,n=r.functionName||"<anonymous>";t+=`\n at ${n} (${e})`}return t},releaseObject:async function(e,r){r.objectId&&(await e.send("Runtime.releaseObject",{objectId:r.objectId}).catch(e=>{t.debugError(e)}))}}},23222:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isNode=void 0,t.isNode=!!("undefined"!=typeof process&&process.version)},80527:function(e,t,r){"use strict";var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.initializePuppeteerNode=void 0;const a=r(9323),o=r(14148),i=n(r(10837));t.initializePuppeteerNode=e=>{const t=i.default.sync(__dirname);let r=o.PUPPETEER_REVISIONS.chromium;const n="puppeteer-core"===e,s=n?void 0:process.env.PUPPETEER_PRODUCT||process.env.npm_config_puppeteer_product||process.env.npm_package_config_puppeteer_product;return n||"firefox"!==s||(r=o.PUPPETEER_REVISIONS.firefox),new a.PuppeteerNode({projectRoot:t,preferredRevision:r,isPuppeteerCore:n,productName:s})}},90176:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});const n=r(80527),a=r(23222);if(!a.isNode)throw new Error("Trying to run Puppeteer-Node in a web environment.");t.default=n.initializePuppeteerNode("puppeteer")},77463:function(e,t,r){"use strict";function n(e,t,r){if("chrome"===e){if("linux"===t)return"chrome-linux";if("mac"===t)return"chrome-mac";if("win32"===t||"win64"===t)return 591479<parseInt(r,10)?"chrome-win":"chrome-win32"}else if("firefox"===e)return t}function a(e,t,r,a){const o=x.format(R[e][t],r,a,n(e,t,a));return o}function o(){b.stat("/usr/bin/chromium-browser",function(e,t){if(void 0===t)throw console.error(`The chromium binary is not available for arm64: `),console.error(`If you are on Ubuntu, you can install with: `),console.error(`\n apt-get install chromium-browser\n`),new Error})}function i(e){return new Promise(t=>{b.access(e,e=>t(!e))})}function s(e,t){const r=S.basename(t),n=r.split("-");if(2!==n.length)return null;const[a,o]=n;return R[e][a]?{product:e,platform:a,revision:o}:null}function l(e,t,r){function n(e){a+=e.length,r(a,o)}z(`Downloading binary from ${e}`);let a=0,o=0,i,s;const l=new Promise((e,t)=>{i=e,s=t}),d=u(e,"GET",a=>{if(200!==a.statusCode){const t=new Error(`Download failed: server returned code ${a.statusCode}. URL: ${e}`);return a.resume(),void s(t)}const l=b.createWriteStream(t);l.on("finish",()=>i()),l.on("error",e=>s(e)),a.pipe(l),o=parseInt(a.headers["content-length"],10),r&&a.on("data",n)});return d.on("error",e=>s(e)),l}function d(e,t){if(z(`Installing ${e} to ${t}`),e.endsWith(".zip"))return _.default(e,{dir:t});if(e.endsWith(".tar.bz2"))return p(e,t);if(e.endsWith(".dmg"))return W(t).then(()=>c(e,t));throw new Error(`Unsupported archive format: ${e}`)}function p(e,t){const n=r(16974),a=r(1650);return new Promise((r,o)=>{const i=n.extract(t);i.on("error",o),i.on("finish",r);const s=b.createReadStream(e);s.pipe(a()).pipe(i)})}function c(e,t){function r(){if(n){const e=`hdiutil detach "${n}" -quiet`;z(`Unmounting ${n}`),v.exec(e,e=>{e&&console. Line truncated
This means that, on future Puppeteer launches, Puppeteer might not be able to launch the browser.
Please check your open processes and ensure that the browser processes that Puppeteer launched have been killed.
If you think this is a bug, please report it on the Puppeteer issue tracker.`}\nError cause: ${e.stack}`)}u.helper.removeEventListeners(this._listeners)}async setupConnection(e){const{usePipe:t,timeout:r,slowMo:a,preferredRevision:o}=e;if(!t){const e=await n(this.proc,r,o),t=await g.NodeWebSocketTransport.create(e);this.connection=new m.Connection(e,t,a)}else{const{3:e,4:t}=this.proc.stdio,r=new h.PipeTransport(e,t);this.connection=new m.Connection("",r,a)}return this.connection}}},93935:function(e,t,r){"use strict";function n(e){let t;if(!e._isPuppeteerCore){const e=process.env.PUPPETEER_EXECUTABLE_PATH||process.env.npm_config_puppeteer_executable_path||process.env.npm_package_config_puppeteer_executable_path;if(e){const t=d.existsSync(e)?null:"Tried to use PUPPETEER_EXECUTABLE_PATH env variable to launch browser but did not find any executable at: "+e;return{executablePath:e,missingText:t}}t=process.env.PUPPETEER_DOWNLOAD_PATH||process.env.npm_config_puppeteer_download_path||process.env.npm_package_config_puppeteer_download_path}const r=new p.BrowserFetcher(e._projectRoot,{product:e.product,path:t});if(!e._isPuppeteerCore&&"chrome"===e.product){const e=process.env.PUPPETEER_CHROMIUM_REVISION;if(e){const t=r.revisionInfo(e),n=t.local?null:"Tried to use PUPPETEER_CHROMIUM_REVISION env variable to launch browser but did not find executable at: "+t.executablePath;return{executablePath:t.executablePath,missingText:n}}}const n=r.revisionInfo(e._preferredRevision),a=n.local?null:`Could not find browser revision ${e._preferredRevision}. Run "PUPPETEER_PRODUCT=firefox npm install" or "PUPPETEER_PRODUCT=firefox yarn install" to download a supported Firefox browser binary.`;return{executablePath:n.executablePath,missingText:a}}var a=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r),Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e["default"]=t}),i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)"default"!=r&&Object.hasOwnProperty.call(e,r)&&a(t,e,r);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0});const s=i(r(12087)),l=i(r(85622)),d=i(r(35747)),p=r(77463),c=r(10487),u=r(15228),m=r(31669),g=m.promisify(d.mkdtemp),h=m.promisify(d.writeFile);class f{constructor(e,t,r){this._projectRoot=e,this._preferredRevision=t,this._isPuppeteerCore=r}async launch(e={}){const{ignoreDefaultArgs:t=!1,args:r=[],dumpio:a=!1,executablePath:o=null,pipe:i=!1,env:d=process.env,handleSIGINT:p=!0,handleSIGTERM:m=!0,handleSIGHUP:h=!0,ignoreHTTPSErrors:f=!1,defaultViewport:y={width:800,height:600},slowMo:b=0,timeout:S=3e4}=e,x=l.join(s.tmpdir(),"puppeteer_dev_chrome_profile-"),v=[];t?Array.isArray(t)?v.push(...this.defaultArgs(e).filter(e=>!t.includes(e))):v.push(...r):v.push(...this.defaultArgs(e));let k=null;v.some(e=>e.startsWith("--remote-debugging-"))||v.push(i?"--remote-debugging-pipe":"--remote-debugging-port=0"),v.some(e=>e.startsWith("--user-data-dir"))||(k=await g(x),v.push(`--user-data-dir=${k}`));let C=o;if("arm64"===s.arch())C="/usr/bin/chromium-browser";else if(!o){const{missingText:e,executablePath:t}=n(this);if(e)throw new Error(e);C=t}const _=v.includes("--remote-debugging-pipe"),w=new u.BrowserRunner(C,v,k);w.start({handleSIGHUP:h,handleSIGTERM:m,handleSIGINT:p,dumpio:a,env:d,pipe:_});try{const e=await w.setupConnection({usePipe:_,timeout:S,slowMo:b,preferredRevision:this._preferredRevision}),t=await c.Browser.create(e,[],f,y,w.proc,w.close.bind(w));return await t.waitForTarget(e=>"page"===e.type()),t}catch(e){throw w.kill(),e}}defaultArgs(e={}){const t=["--disable-background-networking","--enable-features=NetworkService,NetworkServiceInProcess","--disable-background-timer-throttling","--disable-backgrounding-occluded-windows","--disable-breakpad","--disable-client-side-phishing-detection","--disable-component-extensions-with-background-pages","--disable-default-apps","--disable-dev-shm-usage","--disable-extensions","--disable-features=TranslateUI","--disable-hang-monitor","--disable-ipc-flooding-protection","--disable-popup-blocking","--disable-prompt-on-repost","--disable-renderer-backgrounding","--disable-sync","--force-color-profile=srgb","--metrics-recording-only","--no-first-run","--enable-automation","--password-store=basic","--use-mock-keychain","--enable-blink-features=IdleDetection"],{devtools:r=!1,headless:n=!r,args:a=[],userDataDir:o=null}=e;return o&&t.push(`--user-data-dir=${l.resolve(o)}`),r&&t.push("--auto-open-devtools-for-tabs"),n&&t.push("--headless","--hide-scrollbars","--mute-audio"),a.every(e=>e.startsWith("-"))&&t.push("about:blank"),t.push(...a),t}executablePath(){return n(this).executablePath}get product(){return"chrome"}}class y{constructor(e,t,r){this._projectRoot=e,this._preferredRevision=t,this._isLine truncated
If you think this is a bug, please report it on the Puppeteer issue tracker.`}\nError cause: ${e.stack}`)}u.helper.removeEventListeners(this._listeners)}async setupConnection(e){const{usePipe:t,timeout:r,slowMo:a,preferredRevision:o}=e;if(!t){const e=await n(this.proc,r,o),t=await g.NodeWebSocketTransport.create(e);this.connection=new m.Connection(e,t,a)}else{const{3:e,4:t}=this.proc.stdio,r=new h.PipeTransport(e,t);this.connection=new m.Connection("",r,a)}return this.connection}}},93935:function(e,t,r){"use strict";function n(e){let t;if(!e._isPuppeteerCore){const e=process.env.PUPPETEER_EXECUTABLE_PATH||process.env.npm_config_puppeteer_executable_path||process.env.npm_package_config_puppeteer_executable_path;if(e){const t=d.existsSync(e)?null:"Tried to use PUPPETEER_EXECUTABLE_PATH env variable to launch browser but did not find any executable at: "+e;return{executablePath:e,missingText:t}}t=process.env.PUPPETEER_DOWNLOAD_PATH||process.env.npm_config_puppeteer_download_path||process.env.npm_package_config_puppeteer_download_path}const r=new p.BrowserFetcher(e._projectRoot,{product:e.product,path:t});if(!e._isPuppeteerCore&&"chrome"===e.product){const e=process.env.PUPPETEER_CHROMIUM_REVISION;if(e){const t=r.revisionInfo(e),n=t.local?null:"Tried to use PUPPETEER_CHROMIUM_REVISION env variable to launch browser but did not find executable at: "+t.executablePath;return{executablePath:t.executablePath,missingText:n}}}const n=r.revisionInfo(e._preferredRevision),a=n.local?null:`Could not find browser revision ${e._preferredRevision}. Run "PUPPETEER_PRODUCT=firefox npm install" or "PUPPETEER_PRODUCT=firefox yarn install" to download a supported Firefox browser binary.`;return{executablePath:n.executablePath,missingText:a}}var a=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r),Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e["default"]=t}),i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)"default"!=r&&Object.hasOwnProperty.call(e,r)&&a(t,e,r);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0});const s=i(r(12087)),l=i(r(85622)),d=i(r(35747)),p=r(77463),c=r(10487),u=r(15228),m=r(31669),g=m.promisify(d.mkdtemp),h=m.promisify(d.writeFile);class f{constructor(e,t,r){this._projectRoot=e,this._preferredRevision=t,this._isPuppeteerCore=r}async launch(e={}){const{ignoreDefaultArgs:t=!1,args:r=[],dumpio:a=!1,executablePath:o=null,pipe:i=!1,env:d=process.env,handleSIGINT:p=!0,handleSIGTERM:m=!0,handleSIGHUP:h=!0,ignoreHTTPSErrors:f=!1,defaultViewport:y={width:800,height:600},slowMo:b=0,timeout:S=3e4}=e,x=l.join(s.tmpdir(),"puppeteer_dev_chrome_profile-"),v=[];t?Array.isArray(t)?v.push(...this.defaultArgs(e).filter(e=>!t.includes(e))):v.push(...r):v.push(...this.defaultArgs(e));let k=null;v.some(e=>e.startsWith("--remote-debugging-"))||v.push(i?"--remote-debugging-pipe":"--remote-debugging-port=0"),v.some(e=>e.startsWith("--user-data-dir"))||(k=await g(x),v.push(`--user-data-dir=${k}`));let C=o;if("arm64"===s.arch())C="/usr/bin/chromium-browser";else if(!o){const{missingText:e,executablePath:t}=n(this);if(e)throw new Error(e);C=t}const _=v.includes("--remote-debugging-pipe"),w=new u.BrowserRunner(C,v,k);w.start({handleSIGHUP:h,handleSIGTERM:m,handleSIGINT:p,dumpio:a,env:d,pipe:_});try{const e=await w.setupConnection({usePipe:_,timeout:S,slowMo:b,preferredRevision:this._preferredRevision}),t=await c.Browser.create(e,[],f,y,w.proc,w.close.bind(w));return await t.waitForTarget(e=>"page"===e.type()),t}catch(e){throw w.kill(),e}}defaultArgs(e={}){const t=["--disable-background-networking","--enable-features=NetworkService,NetworkServiceInProcess","--disable-background-timer-throttling","--disable-backgrounding-occluded-windows","--disable-breakpad","--disable-client-side-phishing-detection","--disable-component-extensions-with-background-pages","--disable-default-apps","--disable-dev-shm-usage","--disable-extensions","--disable-features=TranslateUI","--disable-hang-monitor","--disable-ipc-flooding-protection","--disable-popup-blocking","--disable-prompt-on-repost","--disable-renderer-backgrounding","--disable-sync","--force-color-profile=srgb","--metrics-recording-only","--no-first-run","--enable-automation","--password-store=basic","--use-mock-keychain","--enable-blink-features=IdleDetection"],{devtools:r=!1,headless:n=!r,args:a=[],userDataDir:o=null}=e;return o&&t.push(`--user-data-dir=${l.resolve(o)}`),r&&t.push("--auto-open-devtools-for-tabs"),n&&t.push("--headless","--hide-scrollbars","--mute-audio"),a.every(e=>e.startsWith("-"))&&t.push("about:blank"),t.push(...a),t}executablePath(){return n(this).executablePath}get product(){return"chrome"}}class y{constructor(e,t,r){this._projectRoot=e,this._preferredRevision=t,this._isLine truncated
* SVGO is a Nodejs-based tool for optimizing SVG vector graphics files.
*
* @see https://github.com/svg/svgo
@@ -96,7 +96,7 @@ If you think this is a bug, please report it on the Puppeteer issue tracker.`}\n
* @author Kir Belevich <kir@soulshine.in> (https://github.com/deepsweet)
* @copyright © 2012 Kir Belevich
* @license MIT https://raw.githubusercontent.com/svg/svgo/master/LICENSE
*/var n=r(42342),a=r(3717),o=r(65994),i=r(71921),s=r(79736).By,l=r(58529),d=function(e){this.config=n(e)};d.prototype.optimize=function(e,t){return t=t||{},new Promise((r,n)=>{if(this.config.error)return void n(this.config.error);var a=this.config,o=a.multipass?10:1,i=0,l=_NumberPOSITIVE_INFINITY,d=e=>e.error?void n(e.error):void(t.multipassCount=i,++i<o&&e.data.length<l?(l=e.data.length,this._optimizeOnce(e.data,t,d)):(a.datauri&&(e.data=s(e.data,a.datauri)),t&&t.path&&(e.path=t.path),r(e)));this._optimizeOnce(e,t,d)})},d.prototype._optimizeOnce=function(e,t,r){var n=this.config;a(e,function(e){return e.error?void r(e):void(e=o(e,t,n.plugins),r(l(e,n.js2svg)))})},d.prototype.createContentItem=function(e){return new i(e)},d.Config=n,e.exports=d,e.exports.default=d},42342:(e,t,r)=>{function n(e){return"_collections.js"===e||"_collections"===e?r(76344):"_path.js"===e||"_path"===e?r(54870):"_transforms.js"===e||"_transforms"===e?r(22527):"addAttributesToSVGElement.js"===e||"addAttributesToSVGElement"===e?r(5519):"addClassesToSVGElement.js"===e||"addClassesToSVGElement"===e?r(75118):"cleanupAttrs.js"===e||"cleanupAttrs"===e?r(4106):"cleanupEnableBackground.js"===e||"cleanupEnableBackground"===e?r(26483):"cleanupIDs.js"===e||"cleanupIDs"===e?r(37762):"cleanupListOfValues.js"===e||"cleanupListOfValues"===e?r(92331):"cleanupNumericValues.js"===e||"cleanupNumericValues"===e?r(36296):"collapseGroups.js"===e||"collapseGroups"===e?r(59616):"convertColors.js"===e||"convertColors"===e?r(83254):"convertEllipseToCircle.js"===e||"convertEllipseToCircle"===e?r(56061):"convertPathData.js"===e||"convertPathData"===e?r(76307):"convertShapeToPath.js"===e||"convertShapeToPath"===e?r(24199):"convertStyleToAttrs.js"===e||"convertStyleToAttrs"===e?r(72446):"convertTransform.js"===e||"convertTransform"===e?r(72234):"inlineStyles.js"===e||"inlineStyles"===e?r(81862):"mergePaths.js"===e||"mergePaths"===e?r(46123):"minifyStyles.js"===e||"minifyStyles"===e?r(77686):"moveElemsAttrsToGroup.js"===e||"moveElemsAttrsToGroup"===e?r(42778):"moveGroupAttrsToElems.js"===e||"moveGroupAttrsToElems"===e?r(69078):"prefixIds.js"===e||"prefixIds"===e?r(33099):"removeAttributesBySelector.js"===e||"removeAttributesBySelector"===e?r(65731):"removeAttrs.js"===e||"removeAttrs"===e?r(91585):"removeComments.js"===e||"removeComments"===e?r(13383):"removeDesc.js"===e||"removeDesc"===e?r(81668):"removeDimensions.js"===e||"removeDimensions"===e?r(41690):"removeDoctype.js"===e||"removeDoctype"===e?r(42114):"removeEditorsNSData.js"===e||"removeEditorsNSData"===e?r(70325):"removeElementsByAttr.js"===e||"removeElementsByAttr"===e?r(70535):"removeEmptyAttrs.js"===e||"removeEmptyAttrs"===e?r(63151):"removeEmptyContainers.js"===e||"removeEmptyContainers"===e?r(41059):"removeEmptyText.js"===e||"removeEmptyText"===e?r(14156):"removeHiddenElems.js"===e||"removeHiddenElems"===e?r(1378):"removeMetadata.js"===e||"removeMetadata"===e?r(28873):"removeNonInheritableGroupAttrs.js"===e||"removeNonInheritableGroupAttrs"===e?r(67662):"removeOffCanvasPaths.js"===e||"removeOffCanvasPaths"===e?r(58267):"removeRasterImages.js"===e||"removeRasterImages"===e?r(99062):"removeScriptElement.js"===e||"removeScriptElement"===e?r(64186):"removeStyleElement.js"===e||"removeStyleElement"===e?r(99681):"removeTitle.js"===e||"removeTitle"===e?r(76087):"removeUnknownsAndDefaults.js"===e||"removeUnknownsAndDefaults"===e?r(8316):"removeUnusedNS.js"===e||"removeUnusedNS"===e?r(77926):"removeUselessDefs.js"===e||"removeUselessDefs"===e?r(1820):"removeUselessStrokeAndFill.js"===e||"removeUselessStrokeAndFill"===e?r(7519):"removeViewBox.js"===e||"removeViewBox"===e?r(81306):"removeXMLNS.js"===e||"removeXMLNS"===e?r(44987):"removeXMLProcInst.js"===e||"removeXMLProcInst"===e?r(97427):"reusePaths.js"===e||"reusePaths"===e?r(86607):"sortAttrs.js"===e||"sortAttrs"===e?r(17549):"sortDefsChildren.js"===e||"sortDefsChildren"===e?r(5681):void 0}function a(e,t){var r,n;return t.map(function(t){return"object"==typeof t?(n=Object.keys(t)[0],"object"==typeof t[n]&&t[n].fn&&"function"==typeof t[n].fn?r=i(n,t[n]):(r=l(d(e,n,t[n].path),t,n),r.name=n)):(r=d(e,t),r.name=t,"object"==typeof r.params&&(r.params=Object.assign({},r.params))),r})}function o(e,t){var r;return t.plugins&&t.plugins.forEach(function(n){"object"==typeof n&&(r=Object.keys(n)[0],null==n[r]&&console.error(`Error: '${r}' plugin is misconfigured! Have you padded its content in YML properly?\n`),"object"==typeof n[r]&&n[r].fn&&"function"==typeof n[r].fn?e.plugins.push(i(r,n[r])):"object"==typeof n[r]&&n[r].path?e.plugins.push(l(d(t,void 0,n[r].path),n,r)):e.plugins.forEach(function(e){e.name===r&&(e=l(e,n,r))}))}),e.multipass=t.multipass,t.svg2js&&(e.svg2js=t.svg2js),t.js2svg&&(e.js2svg=t.js2svg),e}function i(e,t){return t.active=!0,t.params=Object.assign({},t.params||{}),t.name=e,t}function s(e){var t;return e.reduce(function(e,r){return t&&r.type==t[0].type?t.push(r):e.push(t=[r]),e},[])}function l(e,t,r){return"object"==typeof t[r]?(e.params=Object.asLine truncated
*/var n=r(42342),a=r(3717),o=r(65994),i=r(71921),s=r(79736).By,l=r(58529),d=function(e){this.config=n(e)};d.prototype.optimize=function(e,t){return t=t||{},new Promise((r,n)=>{if(this.config.error)return void n(this.config.error);var a=this.config,o=a.multipass?10:1,i=0,l=_NumberPOSITIVE_INFINITY,d=e=>e.error?void n(e.error):void(t.multipassCount=i,++i<o&&e.data.length<l?(l=e.data.length,this._optimizeOnce(e.data,t,d)):(a.datauri&&(e.data=s(e.data,a.datauri)),t&&t.path&&(e.path=t.path),r(e)));this._optimizeOnce(e,t,d)})},d.prototype._optimizeOnce=function(e,t,r){var n=this.config;a(e,function(e){return e.error?void r(e):void(e=o(e,t,n.plugins),r(l(e,n.js2svg)))})},d.prototype.createContentItem=function(e){return new i(e)},d.Config=n,e.exports=d,e.exports.default=d},42342:(e,t,r)=>{function n(e){return"_collections.js"===e||"_collections"===e?r(76344):"_path.js"===e||"_path"===e?r(54870):"_transforms.js"===e||"_transforms"===e?r(22527):"addAttributesToSVGElement.js"===e||"addAttributesToSVGElement"===e?r(5519):"addClassesToSVGElement.js"===e||"addClassesToSVGElement"===e?r(75118):"cleanupAttrs.js"===e||"cleanupAttrs"===e?r(4106):"cleanupEnableBackground.js"===e||"cleanupEnableBackground"===e?r(26483):"cleanupIDs.js"===e||"cleanupIDs"===e?r(37762):"cleanupListOfValues.js"===e||"cleanupListOfValues"===e?r(92331):"cleanupNumericValues.js"===e||"cleanupNumericValues"===e?r(36296):"collapseGroups.js"===e||"collapseGroups"===e?r(59616):"convertColors.js"===e||"convertColors"===e?r(83254):"convertEllipseToCircle.js"===e||"convertEllipseToCircle"===e?r(56061):"convertPathData.js"===e||"convertPathData"===e?r(76307):"convertShapeToPath.js"===e||"convertShapeToPath"===e?r(24199):"convertStyleToAttrs.js"===e||"convertStyleToAttrs"===e?r(72446):"convertTransform.js"===e||"convertTransform"===e?r(72234):"inlineStyles.js"===e||"inlineStyles"===e?r(81862):"mergePaths.js"===e||"mergePaths"===e?r(46123):"minifyStyles.js"===e||"minifyStyles"===e?r(77686):"moveElemsAttrsToGroup.js"===e||"moveElemsAttrsToGroup"===e?r(42778):"moveGroupAttrsToElems.js"===e||"moveGroupAttrsToElems"===e?r(69078):"prefixIds.js"===e||"prefixIds"===e?r(33099):"removeAttributesBySelector.js"===e||"removeAttributesBySelector"===e?r(65731):"removeAttrs.js"===e||"removeAttrs"===e?r(91585):"removeComments.js"===e||"removeComments"===e?r(13383):"removeDesc.js"===e||"removeDesc"===e?r(81668):"removeDimensions.js"===e||"removeDimensions"===e?r(41690):"removeDoctype.js"===e||"removeDoctype"===e?r(42114):"removeEditorsNSData.js"===e||"removeEditorsNSData"===e?r(70325):"removeElementsByAttr.js"===e||"removeElementsByAttr"===e?r(70535):"removeEmptyAttrs.js"===e||"removeEmptyAttrs"===e?r(63151):"removeEmptyContainers.js"===e||"removeEmptyContainers"===e?r(41059):"removeEmptyText.js"===e||"removeEmptyText"===e?r(14156):"removeHiddenElems.js"===e||"removeHiddenElems"===e?r(1378):"removeMetadata.js"===e||"removeMetadata"===e?r(28873):"removeNonInheritableGroupAttrs.js"===e||"removeNonInheritableGroupAttrs"===e?r(67662):"removeOffCanvasPaths.js"===e||"removeOffCanvasPaths"===e?r(58267):"removeRasterImages.js"===e||"removeRasterImages"===e?r(99062):"removeScriptElement.js"===e||"removeScriptElement"===e?r(64186):"removeStyleElement.js"===e||"removeStyleElement"===e?r(99681):"removeTitle.js"===e||"removeTitle"===e?r(76087):"removeUnknownsAndDefaults.js"===e||"removeUnknownsAndDefaults"===e?r(8316):"removeUnusedNS.js"===e||"removeUnusedNS"===e?r(77926):"removeUselessDefs.js"===e||"removeUselessDefs"===e?r(1820):"removeUselessStrokeAndFill.js"===e||"removeUselessStrokeAndFill"===e?r(7519):"removeViewBox.js"===e||"removeViewBox"===e?r(81306):"removeXMLNS.js"===e||"removeXMLNS"===e?r(44987):"removeXMLProcInst.js"===e||"removeXMLProcInst"===e?r(97427):"reusePaths.js"===e||"reusePaths"===e?r(86607):"sortAttrs.js"===e||"sortAttrs"===e?r(17549):"sortDefsChildren.js"===e||"sortDefsChildren"===e?r(5681):void 0}function a(e,t){var r,n;return t.map(function(t){return"object"==typeof t?(n=Object.keys(t)[0],"object"==typeof t[n]&&t[n].fn&&"function"==typeof t[n].fn?r=i(n,t[n]):(r=l(d(e,n,t[n].path),t,n),r.name=n)):(r=d(e,t),r.name=t,"object"==typeof r.params&&(r.params=Object.assign({},r.params))),r})}function o(e,t){var r;return t.plugins&&t.plugins.forEach(function(n){"object"==typeof n&&(r=Object.keys(n)[0],null==n[r]&&console.error(`Error: '${r}' plugin is misconfigured! Have you padded its content in YML properly?\n`),"object"==typeof n[r]&&n[r].fn&&"function"==typeof n[r].fn?e.plugins.push(i(r,n[r])):"object"==typeof n[r]&&n[r].path?e.plugins.push(l(d(t,void 0,n[r].path),n,r)):e.plugins.forEach(function(e){e.name===r&&(e=l(e,n,r))}))}),e.multipass=t.multipass,t.svg2js&&(e.svg2js=t.svg2js),t.js2svg&&(e.js2svg=t.js2svg),e}function i(e,t){return t.active=!0,t.params=Object.assign({},t.params||{}),t.name=e,t}function s(e){var t;return e.reduce(function(e,r){return t&&r.type==t[0].type?t.push(r):e.push(t=[r]),e},[])}function l(e,t,r){return"object"==typeof t[r]?(e.params=Object.asLine truncated
* @license
* The MIT License
*
@@ -172,4 +172,4 @@ If you think this is a bug, please report it on the Puppeteer issue tracker.`}\n
* ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ПРОГРАММНОГО
* ОБЕСПЕЧЕНИЯ
* ИЛИ ИНЫМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
*/function n(e,t){return e.renameElem("use"),e.removeAttr("d"),e.removeAttr("stroke"),e.removeAttr("fill"),e.addAttr({name:"xlink:href",local:"xlink:href",prefix:"none",value:"#"+t}),delete e.pathJS,e}function a(e,t){if(!e.isEmpty())for(let r of e.content)t(r),a(r,t)}var o=r(71921);t.type="full",t.active=!1,t.description="Finds <path> elements with the same d, fill, and stroke, and converts them to <use> elements referencing a single <path> def.",t.fn=function(e){const t=new Map;let r=0;const i=[];a(e,e=>{if(!e.isElem("path")||!e.hasAttr("d"))return;const a=e.attr("d").value,o=e.hasAttr("fill")&&e.attr("fill").value||"",s=e.hasAttr("stroke")&&e.attr("stroke").value||"",l=a+";s:"+s+";f:"+o,d=t.get(l);return d?void(!d.reused&&(d.reused=!0,!d.elem.hasAttr("id")&&d.elem.addAttr({name:"id",local:"id",prefix:"",value:"reuse-"+r++}),i.push(d.elem)),e=n(e,d.elem.attr("id").value)):void t.set(l,{elem:e,reused:!1})});const s=new o({elem:"defs",prefix:"",local:"defs",content:[],attrs:[]},e);e.content[0].spliceContent(0,0,s);for(let t of i){const e=t.style,r=t.class;delete t.style,delete t.class;const a=t.clone();t.style=e,t.class=r,a.removeAttr("transform"),s.spliceContent(0,0,a),t=n(t,a.attr("id").value),t.removeAttr("id")}return e}},17549:(e,t)=>{"use strict";t.type="perItem",t.active=!1,t.description="sorts element attributes (disabled by default)",t.params={order:["id","width","height","x","x1","x2","y","y1","y2","cx","cy","r","fill","stroke","marker","d","points"]},t.fn=function(e,t){var r=[],n={},o=t.order.length+1,i=t.xmlnsOrder||"front";e.elem&&(e.eachAttr(function(e){r.push(e)}),r.sort(function(e,r){if(e.prefix!=r.prefix){if("front"==i){if("xmlns"==e.prefix)return-1;if("xmlns"==r.prefix)return 1}return e.prefix<r.prefix?-1:1}for(var n=o,a=o,s=0;s<t.order.length;s++)e.name==t.order[s]?n=s:0===e.name.indexOf(t.order[s]+"-")&&(n=s+.5),r.name==t.order[s]?a=s:0===r.name.indexOf(t.order[s]+"-")&&(a=s+.5);return n==a?e.name<r.name?-1:1:n-a}),r.forEach(function(e){n[e.name]=e}),e.attrs=n)}},5681:(e,t)=>{"use strict";t.type="perItem",t.active=!0,t.description="Sorts children of <defs> to improve compression",t.fn=function(e){if(e.isElem("defs")){if(e.content){var t=e.content.reduce(function(e,t){return t.elem in e?e[t.elem]++:e[t.elem]=1,e},{});e.content.sort(function(e,r){var n=t[r.elem]-t[e.elem];if(0!=n)return n;var a=r.elem.length-e.elem.length;return 0==a?e.elem==r.elem?0:e.elem>r.elem?-1:1:a})}return!0}}},16974:(e,t,r)=>{function n(e,t,r,a){return t===r?a(null,!0):void e.lstat(t,function(o,i){return o&&"ENOENT"!==o.code?a(o):o||i.isDirectory()?n(e,p.join(t,".."),r,a):void a(null,!1)})}function a(e,t,r){l(e,{fs:t.fs},function(e,n){!e&&n&&t.own?o(n,t.uid,t.gid,r):r(e)})}var o=r(28729),i=r(15283),s=r(537),l=r(23607),d=r(35747),p=r(85622),c=r(12087),u="win32"===c.platform(),m=function(){},g=function(e){return e},h=u?function(e){return e.replace(/\\/g,"/").replace(/[:?<>|]/g,"_")}:g,f=function(e,t,r,n,a,o){var s=a||["."];return function(a){if(!s.length)return a();var l=s.shift(),d=p.join(r,l);t.call(e,d,function(t,c){return t?a(t):c.isDirectory()?void e.readdir(d,function(e,t){if(e)return a(e);o&&t.sort();for(var d=0;d<t.length;d++)n(p.join(r,l,t[d]))||s.push(p.join(l,t[d]));a(null,l,c)}):a(null,l,c)})}},y=function(e,t){return function(r){r.name=r.name.split("/").slice(t).join("/");var n=r.linkname;return n&&("link"===r.type||p.isAbsolute(n))&&(r.linkname=n.split("/").slice(t).join("/")),e(r)}};t.pack=function(e,t){e||(e="."),t||(t={});var r=t.fs||d,n=t.ignore||t.filter||m,a=t.map||m,o=t.mapStream||g,l=f(r,t.dereference?r.stat:r.lstat,e,n,t.entries,t.sort),c=!1!==t.strict,u="number"==typeof t.umask?~t.umask:~x(),b="number"==typeof t.dmode?t.dmode:0,S="number"==typeof t.fmode?t.fmode:0,v=t.pack||i.pack(),k=t.finish||m;t.strip&&(a=y(a,t.strip)),t.readable&&(b|=parseInt(555,8),S|=parseInt(444,8)),t.writable&&(b|=parseInt(333,8),S|=parseInt(222,8));var C=function(t,n){r.readlink(p.join(e,t),function(e,t){return e?v.destroy(e):void(n.linkname=h(t),v.entry(n,w))})},_=function(n,i,l){if(n)return v.destroy(n);if(!i)return!1!==t.finalize&&v.finalize(),k(v);if(l.isSocket())return w();var d={name:h(i),mode:(l.mode|(l.isDirectory()?b:S))&u,mtime:l.mtime,size:l.size,type:"file",uid:l.uid,gid:l.gid};if(l.isDirectory())return d.size=0,d.type="directory",d=a(d)||d,v.entry(d,w);if(l.isSymbolicLink())return d.size=0,d.type="symlink",d=a(d)||d,C(i,d);if(d=a(d)||d,!l.isFile())return c?v.destroy(new Error("unsupported type for "+i)):w();var m=v.entry(d,w);if(m){var g=o(r.createReadStream(p.join(e,i),{start:0,end:0<d.size?d.size-1:d.size}),d);g.on("error",function(e){m.destroy(e)}),s(g,m)}},w=function(e){return e?v.destroy(e):void l(_)};return w(),v};var b=function(e){return e.length?e[e.length-1]:null},S=function(){return process.getuid?process.getuid():-1},x=function(){return process.umask?process.umask():0};t.extract=function(e,t){e||(e="."),t||(t={});var r=t.fs||d,o=t.ignore||t.filter||m,l=t.map||m,c=t.mapStream||g,f=!1!==t.chown&&!Line truncated
*/function n(e,t){return e.renameElem("use"),e.removeAttr("d"),e.removeAttr("stroke"),e.removeAttr("fill"),e.addAttr({name:"xlink:href",local:"xlink:href",prefix:"none",value:"#"+t}),delete e.pathJS,e}function a(e,t){if(!e.isEmpty())for(let r of e.content)t(r),a(r,t)}var o=r(71921);t.type="full",t.active=!1,t.description="Finds <path> elements with the same d, fill, and stroke, and converts them to <use> elements referencing a single <path> def.",t.fn=function(e){const t=new Map;let r=0;const i=[];a(e,e=>{if(!e.isElem("path")||!e.hasAttr("d"))return;const a=e.attr("d").value,o=e.hasAttr("fill")&&e.attr("fill").value||"",s=e.hasAttr("stroke")&&e.attr("stroke").value||"",l=a+";s:"+s+";f:"+o,d=t.get(l);return d?void(!d.reused&&(d.reused=!0,!d.elem.hasAttr("id")&&d.elem.addAttr({name:"id",local:"id",prefix:"",value:"reuse-"+r++}),i.push(d.elem)),e=n(e,d.elem.attr("id").value)):void t.set(l,{elem:e,reused:!1})});const s=new o({elem:"defs",prefix:"",local:"defs",content:[],attrs:[]},e);e.content[0].spliceContent(0,0,s);for(let t of i){const e=t.style,r=t.class;delete t.style,delete t.class;const a=t.clone();t.style=e,t.class=r,a.removeAttr("transform"),s.spliceContent(0,0,a),t=n(t,a.attr("id").value),t.removeAttr("id")}return e}},17549:(e,t)=>{"use strict";t.type="perItem",t.active=!1,t.description="sorts element attributes (disabled by default)",t.params={order:["id","width","height","x","x1","x2","y","y1","y2","cx","cy","r","fill","stroke","marker","d","points"]},t.fn=function(e,t){var r=[],n={},o=t.order.length+1,i=t.xmlnsOrder||"front";e.elem&&(e.eachAttr(function(e){r.push(e)}),r.sort(function(e,r){if(e.prefix!=r.prefix){if("front"==i){if("xmlns"==e.prefix)return-1;if("xmlns"==r.prefix)return 1}return e.prefix<r.prefix?-1:1}for(var n=o,a=o,s=0;s<t.order.length;s++)e.name==t.order[s]?n=s:0===e.name.indexOf(t.order[s]+"-")&&(n=s+.5),r.name==t.order[s]?a=s:0===r.name.indexOf(t.order[s]+"-")&&(a=s+.5);return n==a?e.name<r.name?-1:1:n-a}),r.forEach(function(e){n[e.name]=e}),e.attrs=n)}},5681:(e,t)=>{"use strict";t.type="perItem",t.active=!0,t.description="Sorts children of <defs> to improve compression",t.fn=function(e){if(e.isElem("defs")){if(e.content){var t=e.content.reduce(function(e,t){return t.elem in e?e[t.elem]++:e[t.elem]=1,e},{});e.content.sort(function(e,r){var n=t[r.elem]-t[e.elem];if(0!=n)return n;var a=r.elem.length-e.elem.length;return 0==a?e.elem==r.elem?0:e.elem>r.elem?-1:1:a})}return!0}}},16974:(e,t,r)=>{function n(e,t,r,a){return t===r?a(null,!0):void e.lstat(t,function(o,i){return o&&"ENOENT"!==o.code?a(o):o||i.isDirectory()?n(e,p.join(t,".."),r,a):void a(null,!1)})}function a(e,t,r){l(e,{fs:t.fs},function(e,n){!e&&n&&t.own?o(n,t.uid,t.gid,r):r(e)})}var o=r(28729),i=r(15283),s=r(537),l=r(23607),d=r(35747),p=r(85622),c=r(12087),u="win32"===c.platform(),m=function(){},g=function(e){return e},h=u?function(e){return e.replace(/\\/g,"/").replace(/[:?<>|]/g,"_")}:g,f=function(e,t,r,n,a,o){var s=a||["."];return function(a){if(!s.length)return a();var l=s.shift(),d=p.join(r,l);t.call(e,d,function(t,c){return t?a(t):c.isDirectory()?void e.readdir(d,function(e,t){if(e)return a(e);o&&t.sort();for(var d=0;d<t.length;d++)n(p.join(r,l,t[d]))||s.push(p.join(l,t[d]));a(null,l,c)}):a(null,l,c)})}},y=function(e,t){return function(r){r.name=r.name.split("/").slice(t).join("/");var n=r.linkname;return n&&("link"===r.type||p.isAbsolute(n))&&(r.linkname=n.split("/").slice(t).join("/")),e(r)}};t.pack=function(e,t){e||(e="."),t||(t={});var r=t.fs||d,n=t.ignore||t.filter||m,a=t.map||m,o=t.mapStream||g,l=f(r,t.dereference?r.stat:r.lstat,e,n,t.entries,t.sort),c=!1!==t.strict,u="number"==typeof t.umask?~t.umask:~x(),b="number"==typeof t.dmode?t.dmode:0,S="number"==typeof t.fmode?t.fmode:0,v=t.pack||i.pack(),k=t.finish||m;t.strip&&(a=y(a,t.strip)),t.readable&&(b|=parseInt(555,8),S|=parseInt(444,8)),t.writable&&(b|=parseInt(333,8),S|=parseInt(222,8));var C=function(t,n){r.readlink(p.join(e,t),function(e,t){return e?v.destroy(e):void(n.linkname=h(t),v.entry(n,w))})},_=function(n,i,l){if(n)return v.destroy(n);if(!i)return!1!==t.finalize&&v.finalize(),k(v);if(l.isSocket())return w();var d={name:h(i),mode:(l.mode|(l.isDirectory()?b:S))&u,mtime:l.mtime,size:l.size,type:"file",uid:l.uid,gid:l.gid};if(l.isDirectory())return d.size=0,d.type="directory",d=a(d)||d,v.entry(d,w);if(l.isSymbolicLink())return d.size=0,d.type="symlink",d=a(d)||d,C(i,d);if(d=a(d)||d,!l.isFile())return c?v.destroy(new Error("unsupported type for "+i)):w();var m=v.entry(d,w);if(m){var g=o(r.createReadStream(p.join(e,i),{start:0,end:0<d.size?d.size-1:d.size}),d);g.on("error",function(e){m.destroy(e)}),s(g,m)}},w=function(e){return e?v.destroy(e):void l(_)};return w(),v};var b=function(e){return e.length?e[e.length-1]:null},S=function(){return process.getuid?process.getuid():-1},x=function(){return process.umask?process.umask():0};t.extract=function(e,t){e||(e="."),t||(t={});var r=t.fs||d,o=t.ignore||t.filter||m,l=t.map||m,c=t.mapStream||g,f=!1!==t.chown&&!Line truncated
+16 -9
View File
@@ -37,7 +37,7 @@
console.log(`Template to use | ${template}`)
//Token for data gathering
const token = core.getInput("token")
const token = core.getInput("token") || ""
console.log(`Github token | ${token ? "provided" : "missing"}`)
if (!token)
throw new Error("You must provide a valid GitHub token to gather your metrics")
@@ -71,16 +71,22 @@
if (!debug)
console.debug = message => debugged.push(message)
console.log(`Debug mode | ${debug}`)
const dflags = (core.getInput("debug_flags") ?? "").split(" ").filter(flag => flag)
const dflags = (core.getInput("debug_flags") || "").split(" ").filter(flag => flag)
console.log(`Debug flags | ${dflags.join(" ")}`)
//Base elements
const base = {}
let parts = (core.getInput("base")||"").split(",").map(part => part.trim())
let parts = (core.getInput("base") || "").split(",").map(part => part.trim())
for (const part of conf.settings.plugins.base.parts)
base[`base.${part}`] = parts.includes(part)
console.log(`Base parts | ${parts.join(", ") || "(none)"}`)
//Config
const config = {
"config.timezone":core.getInput("config_timezone") || ""
}
console.log(`Timezone | ${config.timezone || "(none)"}`)
//Additional plugins
const plugins = {
lines:{enabled:bool(core.getInput("plugin_lines"))},
@@ -102,7 +108,7 @@
//Additional plugins options
//Pagespeed
if (plugins.pagespeed.enabled) {
plugins.pagespeed.token = core.getInput("plugin_pagespeed_token")
plugins.pagespeed.token = core.getInput("plugin_pagespeed_token") || ""
q[`pagespeed.detailed`] = bool(core.getInput(`plugin_pagespeed_detailed`))
console.log(`Pagespeed token | ${plugins.pagespeed.token ? "provided" : "missing"}`)
console.log(`Pagespeed detailed | ${q["pagespeed.detailed"]}`)
@@ -145,7 +151,7 @@
}
//Isocalendar
if (plugins.isocalendar.enabled) {
q["isocalendar.duration"] = core.getInput("plugin_isocalendar_duration") ?? "half-year"
q["isocalendar.duration"] = core.getInput("plugin_isocalendar_duration") || "half-year"
console.log(`Isocalendar duration | ${q["isocalendar.duration"]}`)
}
//Topics
@@ -179,7 +185,7 @@
console.log(`Plugin errors | ${die ? "die" : "ignore"}`)
//Built query
q = {...q, base:false, ...base, repositories, template}
q = {...q, base:false, ...base, ...config, repositories, template}
//Render metrics
const rendered = await metrics({login:user, q, dflags}, {graphql, rest, plugins, conf, die})
@@ -206,7 +212,7 @@
console.log(`Repository | ${github.context.repo.owner}/${github.context.repo.repo}`)
console.log(`Branch | ${branch}`)
//Committer token
const token = core.getInput("committer_token") || core.getInput("token")
const token = core.getInput("committer_token") || core.getInput("token") || ""
console.log(`Committer token | ${token ? "provided" : "missing"}`)
if (!token)
throw new Error("You must provide a valid GitHub token to commit your metrics")
@@ -231,7 +237,7 @@
)
sha = oid
} catch (error) { console.debug(error) }
console.log(`Previous render sha | ${sha || "none"}`)
console.log(`Previous render sha | ${sha ?? "none"}`)
//Update file content through API
await rest.repos.createOrUpdateFileContents({
...github.context.repo, path:filename, message:`Update ${filename} - [Skip GitHub Action]`,
@@ -245,8 +251,9 @@
console.log(`Success !`)
process.exit(0)
}
//Errors
} catch (error) {
catch (error) {
console.error(error)
if (!bool(core.getInput("debug")))
for (const log of ["_".repeat(64), "An error occured, logging debug message :", ...debugged])
+31 -31
View File
@@ -211,26 +211,26 @@
}
},
"@babel/traverse": {
"version": "7.12.10",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.10.tgz",
"integrity": "sha512-6aEtf0IeRgbYWzta29lePeYSk+YAFIC3kyqESeft8o5CkFlYIMX+EQDDWEiAQ9LHOA3d0oHdgrSsID/CKqXJlg==",
"version": "7.12.12",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz",
"integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
"@babel/generator": "^7.12.10",
"@babel/helper-function-name": "^7.10.4",
"@babel/helper-split-export-declaration": "^7.11.0",
"@babel/parser": "^7.12.10",
"@babel/types": "^7.12.10",
"@babel/code-frame": "^7.12.11",
"@babel/generator": "^7.12.11",
"@babel/helper-function-name": "^7.12.11",
"@babel/helper-split-export-declaration": "^7.12.11",
"@babel/parser": "^7.12.11",
"@babel/types": "^7.12.12",
"debug": "^4.1.0",
"globals": "^11.1.0",
"lodash": "^4.17.19"
}
},
"@babel/types": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.11.tgz",
"integrity": "sha512-ukA9SQtKThINm++CX1CwmliMrE54J6nIYB5XTwL5f/CLFW9owfls+YSU8tVW15RQ2w+a3fSbPjC6HdQNtWZkiA==",
"version": "7.12.12",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz",
"integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.12.11",
@@ -280,9 +280,9 @@
}
},
"@octokit/openapi-types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-2.0.0.tgz",
"integrity": "sha512-J4bfM7lf8oZvEAdpS71oTvC1ofKxfEZgU5vKVwzZKi4QPiL82udjpseJwxPid9Pu2FNmyRQOX4iEj6W1iOSnPw=="
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-2.0.1.tgz",
"integrity": "sha512-9AuC04PUnZrjoLiw3uPtwGh9FE4Q3rTqs51oNlQ0rkwgE8ftYsOC+lsrQyvCvWm85smBbSc0FNRKKumvGyb44Q=="
},
"@octokit/plugin-paginate-rest": {
"version": "2.6.2",
@@ -343,18 +343,18 @@
}
},
"@octokit/types": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.1.1.tgz",
"integrity": "sha512-btm3D6S7VkRrgyYF31etUtVY/eQ1KzrNRqhFt25KSe2mKlXuLXJilglRC6eDA2P6ou94BUnk/Kz5MPEolXgoiw==",
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.1.2.tgz",
"integrity": "sha512-LPCpcLbcky7fWfHCTuc7tMiSHFpFlrThJqVdaHgowBTMS0ijlZFfonQC/C1PrZOjD4xRCYgBqH9yttEATGE/nw==",
"requires": {
"@octokit/openapi-types": "^2.0.0",
"@octokit/openapi-types": "^2.0.1",
"@types/node": ">= 8"
}
},
"@types/node": {
"version": "14.14.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.14.tgz",
"integrity": "sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ=="
"version": "14.14.16",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.16.tgz",
"integrity": "sha512-naXYePhweTi+BMv11TgioE2/FXU4fSl29HAH1ffxVciNsH3rYXjNP2yM8wqmSm7jS20gM8TIklKiTen+1iVncw=="
},
"@types/q": {
"version": "1.5.4",
@@ -371,9 +371,9 @@
}
},
"@vercel/ncc": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.25.1.tgz",
"integrity": "sha512-dGecC5+1wLof1MQpey4+6i2KZv4Sfs6WfXkl9KfO32GED4ZPiKxRfvtGPjbjZv0IbqMl6CxtcV1RotXYfd5SSA==",
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.26.1.tgz",
"integrity": "sha512-iVhYAL/rpHgjO88GkDHNVNrp7WTfMFBbeWXNgwaDPMv5rDI4hNOAM0u+Zhtbs42XBQE6EccNaY6UDb/tm1+dhg==",
"dev": true
},
"abbrev": {
@@ -445,9 +445,9 @@
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
},
"axios": {
"version": "0.21.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz",
"integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==",
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
@@ -1416,9 +1416,9 @@
"dev": true
},
"get-intrinsic": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz",
"integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz",
"integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "metrics",
"version": "2.9.0-beta",
"version": "2.9.0",
"description": "An image generator with 20+ metrics about your GitHub account such as activity, community, repositories, coding habits, website performances, music played, starred topics, etc. that you can put on your profile or elsewhere !",
"main": "index.mjs",
"scripts": {
@@ -24,7 +24,7 @@
"@actions/github": "^4.0.0",
"@octokit/graphql": "^4.5.8",
"@octokit/rest": "^18.0.12",
"axios": "^0.21.0",
"axios": "^0.21.1",
"colors": "^1.4.0",
"compression": "^1.7.4",
"ejs": "^3.1.5",
@@ -39,7 +39,7 @@
"vue-prism-component": "^1.2.0"
},
"devDependencies": {
"@vercel/ncc": "^0.25.1",
"@vercel/ncc": "^0.26.1",
"babel-minify": "^0.5.1",
"libxmljs": "^0.19.7"
}
+3 -2
View File
@@ -8,6 +8,7 @@
import setup from "./setup.mjs"
import metrics from "./metrics.mjs"
import Templates from "./templates/index.mjs"
import util from "util"
/** App */
export default async function () {
@@ -107,7 +108,7 @@
//Compute rendering
try {
//Render
console.debug(`metrics/app/${login} > ${JSON.stringify(req.query)}`)
console.debug(`metrics/app/${login} > ${util.inspect(req.query, {depth:Infinity, maxStringLength:256})}`)
const rendered = await metrics({login, q:parse(req.query)}, {graphql, rest, plugins, conf})
//Cache
if ((!debug)&&(cached)&&(login !== "placeholder"))
@@ -140,7 +141,7 @@
`Debug mode | ${debug}`,
`Restricted to users | ${restricted.size ? [...restricted].join(", ") : "(unrestricted)"}`,
`Cached time | ${cached} seconds`,
`Rate limiter | ${ratelimiter ? JSON.stringify(ratelimiter) : "(enabled)"}`,
`Rate limiter | ${ratelimiter ? util.inspect(req.query, {depth:Infinity, maxStringLength:256}) : "(enabled)"}`,
`Max simultaneous users | ${maxusers ? `${maxusers} users` : "(unrestricted)"}`,
`Plugins enabled | ${enabled.join(", ")}`
].join("\n")))
+4 -6
View File
@@ -11,6 +11,7 @@
import fs from "fs/promises"
import os from "os"
import paths from "path"
import util from "util"
//Setup
export default async function metrics({login, q, dflags = []}, {graphql, rest, plugins, conf, die = false}) {
@@ -19,7 +20,7 @@
//Init
console.debug(`metrics/compute/${login} > start`)
console.debug(JSON.stringify(q))
console.debug(util.inspect(q, {depth:Infinity, maxStringLength:256}))
const template = q.template || conf.settings.templates.default
const repositories = Math.max(0, Number(q.repositories)) || conf.settings.repositories || 100
const pending = []
@@ -27,7 +28,7 @@
if ((!(template in Templates))||(!(template in conf.templates))||((conf.settings.templates.enabled.length)&&(!conf.settings.templates.enabled.includes(template))))
throw new Error("unsupported template")
const {query, image, style, fonts} = conf.templates[template]
const data = {base:{}}
const data = {base:{}, config:{}}
//Base parts
{
@@ -53,13 +54,10 @@
//Compute metrics
console.debug(`metrics/compute/${login} > compute`)
const computer = Templates[template].default || Templates[template]
await computer({login, q, dflags}, {conf, data, rest, graphql, plugins}, {s, pending, imports:{plugins:Plugins, url, imgb64, axios, puppeteer, run, fs, os, paths, format, bytes, shuffle, htmlescape, urlexpand}})
await computer({login, q, dflags}, {conf, data, rest, graphql, plugins}, {s, pending, imports:{plugins:Plugins, url, imgb64, axios, puppeteer, run, fs, os, paths, util, format, bytes, shuffle, htmlescape, urlexpand}})
const promised = await Promise.all(pending)
//Check plugins errors
if (conf.settings.debug)
for (const {name, result = null} of promised)
console.debug(`plugin ${name} ${result ? result.error ? "failed" : "success" : "ignored"} : ${JSON.stringify(result).replace(/^(.{888}).+/, "$1...")}`)
if (die) {
const errors = promised.filter(({result = null}) => !!result?.error).length
if (errors)
+1 -2
View File
@@ -23,7 +23,6 @@
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
throw {error:{message:"An error occured", instance:error}}
}
}
+4 -3
View File
@@ -5,7 +5,8 @@
//Check if plugin is enabled and requirements are met
if ((!enabled)||(!q.gists))
return null
//Retrieve contribution calendar from graphql api
//Retrieve gists from graphql api
console.debug(`metrics/compute/${login}/plugins > gists > querying api`)
const {user:{gists}} = await graphql(`
query Gists {
user(login: "${login}") {
@@ -27,6 +28,7 @@
`
)
//Iterate through gists
console.debug(`metrics/compute/${login}/plugins > gists > processing ${gists.nodes.length} gists`)
let stargazers = 0, forks = 0, comments = 0
for (const gist of gists.nodes) {
//Skip forks
@@ -42,7 +44,6 @@
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
throw {error:{message:"An error occured", instance:error}}
}
}
+22 -15
View File
@@ -1,5 +1,5 @@
//Setup
export default async function ({login, rest, imports, q}, {enabled = false, from:defaults = 100} = {}) {
export default async function ({login, rest, imports, data, q}, {enabled = false, from:defaults = 100} = {}) {
//Plugin execution
try {
//Check if plugin is enabled and requirements are met
@@ -14,23 +14,25 @@
//Initialization
const habits = {facts, charts, commits:{hour:NaN, hours:{}, day:NaN, days:{}}, indents:{style:"", spaces:0, tabs:0}, linguist:{available:false, ordered:[], languages:{}}}
const pages = Math.ceil(from/100)
const offset = data.config.timezone?.offset ?? 0
//Get user recent activity
console.debug(`metrics/compute/${login}/plugins > habits > querying api`)
const events = []
try {
for (let page = 0; page < pages; page++) {
console.debug(`metrics/compute/${login}/plugins > habits > loaded page ${page}`)
console.debug(`metrics/compute/${login}/plugins > habits > loading page ${page}`)
events.push(...(await rest.activity.listEventsForAuthenticatedUser({username:login, per_page:100, page})).data)
}
} catch { console.debug(`metrics/compute/${login}/plugins > habits > no more events to load`) }
console.debug(`metrics/compute/${login}/plugins > habits > no more events to load (${events.length} loaded)`)
} catch { console.debug(`metrics/compute/${login}/plugins > habits > no more page to load`) }
console.debug(`metrics/compute/${login}/plugins > habits > ${events.length} events loaded`)
//Get user recent commits
const commits = events
.filter(({type}) => type === "PushEvent")
.filter(({actor}) => actor.login === login)
.filter(({created_at}) => new Date(created_at) > new Date(Date.now()-days*24*60*60*1000))
console.debug(`metrics/compute/${login}/plugins > habits > filtered out ${commits.length} commits`)
const actor = commits[0]?.actor?.id ?? 0
console.debug(`metrics/compute/${login}/plugins > habits > filtered out ${commits.length} push events over last ${days} days`)
//Retrieve edited files and filter edited lines (those starting with +/-) from patches
console.debug(`metrics/compute/${login}/plugins > habits > loading patches`)
const patches = [...await Promise.allSettled(commits
.flatMap(({payload}) => payload.commits).map(commit => commit.url)
.map(async commit => (await rest.request(commit)).data.files)
@@ -42,7 +44,8 @@
//Commit day
{
//Compute commit days
const days = commits.map(({created_at}) => (new Date(created_at)).getDay())
console.debug(`metrics/compute/${login}/plugins > habits > searching most active day of week`)
const days = commits.map(({created_at}) => (new Date(new Date(created_at).getTime() + offset)).getDay())
for (const day of days)
habits.commits.days[day] = (habits.commits.days[day] ?? 0) + 1
habits.commits.days.max = Math.max(...Object.values(habits.commits.days))
@@ -52,7 +55,8 @@
//Commit hour
{
//Compute commit hours
const hours = commits.map(({created_at}) => (new Date(created_at)).getHours())
console.debug(`metrics/compute/${login}/plugins > habits > searching most active time of day`)
const hours = commits.map(({created_at}) => (new Date(new Date(created_at).getTime() + offset)).getHours())
for (const hour of hours)
habits.commits.hours[hour] = (habits.commits.hours[hour] ?? 0) + 1
habits.commits.hours.max = Math.max(...Object.values(habits.commits.hours))
@@ -62,6 +66,7 @@
//Indent style
{
//Attempt to guess whether tabs or spaces are used in patches
console.debug(`metrics/compute/${login}/plugins > habits > searching indent style`)
patches
.map(({patch}) => patch.match(/((?:\t)|(?: )) /gm) ?? [])
.forEach(indent => habits.indents[/^\t/.test(indent) ? "tabs" : "spaces"]++)
@@ -70,36 +75,38 @@
//Linguist
if (charts) {
//Check if linguist exists
console.debug(`metrics/compute/${login}/plugins > habits > searching recently used languages using linguist`)
const prefix = {win32:"wsl"}[process.platform] ?? ""
if ((patches.length)&&(await imports.run(`${prefix} which github-linguist`))) {
//Setup for linguist
habits.linguist.available = true
const path = imports.paths.join(imports.os.tmpdir(), `${actor}`)
const path = imports.paths.join(imports.os.tmpdir(), `${commits[0]?.actor?.id ?? 0}`)
//Create temporary directory and save patches
console.debug(`metrics/compute/${login}/plugins > habits > creating temp dir ${path} with ${patches.length} files`)
await imports.fs.mkdir(path, {recursive:true})
await Promise.all(patches.map(async ({name, patch}, i) => await imports.fs.writeFile(imports.paths.join(path, `${i}${imports.paths.extname(name)}`), patch)))
console.debug(`metrics/compute/${login}/plugins > habits > created temp dir ${path} with ${patches.length} files`)
//Create temporary git repository
console.debug(`metrics/compute/${login}/plugins > habits > creating temp git repository`)
await imports.run(`git init && git add . && git config user.name "linguist" && git config user.email "null@github.com" && git commit -m "linguist"`, {cwd:path}).catch(console.debug)
await imports.run(`git status`, {cwd:path})
console.debug(`metrics/compute/${login}/plugins > habits > created temp git repository`)
//Spawn linguist process
console.debug(`metrics/compute/${login}/plugins > habits > running linguist`)
;(await imports.run(`${prefix} github-linguist`, {cwd:path}))
;(await imports.run(`${prefix} github-linguist --breakdown`, {cwd:path}))
//Parse linguist result
.split("\n").map(line => line.match(/(?<value>[\d.]+)%\s+(?<language>\w+)/)?.groups).filter(line => line)
.map(({value, language}) => habits.linguist.languages[language] = (habits.linguist.languages[language] ?? 0) + value/100)
habits.linguist.ordered = Object.entries(habits.linguist.languages).sort(([an, a], [bn, b]) => b - a)
}
else
console.debug(`metrics/compute/${login}/plugins > habits > linguist is not available`)
console.debug(`metrics/compute/${login}/plugins > habits > linguist not available`)
}
//Results
return habits
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
if (error.error?.message)
throw error
throw {error:{message:"An error occured", instance:error}}
}
}
+6 -3
View File
@@ -20,9 +20,10 @@
const padding = new Date(start)
padding.setHours(-14*24)
//Retrieve contribution calendar from graphql api
console.debug(`metrics/compute/${login}/plugins > isocalendar > querying api`)
const calendar = {}
for (const [name, from, to] of [["padding", padding, start], ["weeks", start, now]]) {
console.debug(`metrics/compute/${login}/plugins > isocalendar > loading "${name}" from "${from.toISOString()}" to "${to.toISOString()}"`)
console.debug(`metrics/compute/${login}/plugins > isocalendar > loading ${name} from "${from.toISOString()}" to "${to.toISOString()}"`)
const {user:{calendar:{contributionCalendar:{weeks}}}} = await graphql(`
query Calendar {
user(login: "${login}") {
@@ -44,11 +45,13 @@
calendar[name] = weeks
}
//Apply padding
console.debug(`metrics/compute/${login}/plugins > isocalendar > applying padding`)
const firstweek = calendar.weeks[0].contributionDays
const padded = calendar.padding.flatMap(({contributionDays}) => contributionDays).filter(({date}) => !firstweek.map(({date}) => date).includes(date))
while (firstweek.length < 7)
firstweek.unshift(padded.pop())
//Compute the highest contributions in a day, streaks and average commits per day
console.debug(`metrics/compute/${login}/plugins > isocalendar > computing stats`)
let max = 0, streak = {max:0, current:0}, values = [], average = 0
for (const week of calendar.weeks) {
for (const day of week.contributionDays) {
@@ -60,6 +63,7 @@
}
average = (values.reduce((a, b) => a + b, 0)/values.length).toFixed(2).replace(/[.]0+$/, "")
//Compute SVG
console.debug(`metrics/compute/${login}/plugins > isocalendar > computing svg render`)
const size = 6
let i = 0, j = 0
let svg = `
@@ -96,7 +100,6 @@
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
throw {error:{message:"An error occured", instance:error}}
}
}
+3 -2
View File
@@ -12,6 +12,7 @@
//Skipped repositories
skipped = decodeURIComponent(skipped).split(",").map(x => x.trim().toLocaleLowerCase()).filter(x => x)
//Iterate through user's repositories and retrieve languages data
console.debug(`metrics/compute/${login}/plugins > languages > processing ${data.user.repositories.nodes.length} repositories`)
const languages = {colors:{}, total:0, stats:{}}
for (const repository of data.user.repositories.nodes) {
//Skip repository if asked
@@ -33,6 +34,7 @@
}
}
//Compute languages stats
console.debug(`metrics/compute/${login}/plugins > languages > computing stats`)
Object.keys(languages.stats).map(name => languages.stats[name] /= languages.total)
languages.favorites = Object.entries(languages.stats).sort(([an, a], [bn, b]) => b - a).slice(0, 8).map(([name, value]) => ({name, value, color:languages.colors[name], x:0}))
for (let i = 1; i < languages.favorites.length; i++)
@@ -42,7 +44,6 @@
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
throw {error:{message:"An error occured", instance:error}}
}
}
+3 -2
View File
@@ -8,9 +8,11 @@
//Repositories
const repositories = data.user.repositories.nodes.map(({name}) => name) ?? []
//Get contributors stats from repositories
console.debug(`metrics/compute/${login}/plugins > lines > querying api`)
const lines = {added:0, deleted:0}
const response = await Promise.all(repositories.map(async repo => await rest.repos.getContributorsStats({owner:login, repo})))
//Compute changed lines
console.debug(`metrics/compute/${login}/plugins > lines > computing total diff`)
response.map(({data:repository}) => {
//Check if data are available
if (!Array.isArray(repository))
@@ -29,8 +31,7 @@
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
throw {error:{message:"An error occured", instance:error}}
}
}
+15 -10
View File
@@ -56,13 +56,14 @@
//Limit
limit = Math.max(1, Math.min(100, Number(limit)))
//Handle mode
console.debug(`metrics/compute/${login}/plugins > music > processing mode ${mode} with provider ${provider}`)
switch (mode) {
//Playlist mode
case "playlist":{
//Start puppeteer and navigate to playlist
console.debug(`metrics/compute/${login}/plugins > music > starting browser`)
const browser = await imports.puppeteer.launch({headless:true, executablePath:process.env.PUPPETEER_BROWSER_PATH, args:["--no-sandbox", "--disable-extensions", "--disable-setuid-sandbox", "--disable-dev-shm-usage"]})
console.debug(`metrics/compute/${login}/plugins > music > loaded ${await browser.version()}`)
console.debug(`metrics/compute/${login}/plugins > music > started ${await browser.version()}`)
const page = await browser.newPage()
console.debug(`metrics/compute/${login}/plugins > music > loading page`)
await page.goto(playlist)
@@ -103,7 +104,7 @@
if (Array.isArray(tracks)) {
//Tracks
console.debug(`metrics/compute/${login}/plugins > music > found ${tracks.length} tracks`)
console.debug(JSON.stringify(tracks))
console.debug(imports.util.inspect(tracks, {depth:Infinity, maxStringLength:256}))
//Shuffle tracks
tracks = imports.shuffle(tracks)
}
@@ -120,17 +121,18 @@
//Prepare credentials
const [client_id, client_secret, refresh_token] = token.split(",").map(part => part.trim())
if ((!client_id)||(!client_secret)||(!refresh_token))
throw {error:`Spotify token must contain client id/secret and refresh token`}
throw {error:{message:`Spotify token must contain client id/secret and refresh token`}}
//API call and parse tracklist
try {
//Request access token
console.debug(`metrics/compute/${login}/plugins > music > requesting access token with refresh token for spotify`)
console.debug(`metrics/compute/${login}/plugins > music > requesting access token with spotify refresh token`)
const {data:{access_token:access}} = await imports.axios.post("https://accounts.spotify.com/api/token",
`${new imports.url.URLSearchParams({grant_type:"refresh_token", refresh_token, client_id, client_secret})}`,
{headers:{"Content-Type":"application/x-www-form-urlencoded"}},
)
console.debug(`metrics/compute/${login}/plugins > music > got new access token`)
console.debug(`metrics/compute/${login}/plugins > music > got access token`)
//Retriev tracks
console.debug(`metrics/compute/${login}/plugins > music > querying spotify api`)
tracks = (await imports.axios(`https://api.spotify.com/v1/me/player/recently-played?limit=${limit}&after=${timestamp}`, {headers:{
"Accept":"application/json",
"Content-Type":"application/json",
@@ -143,8 +145,13 @@
}
//Handle errors
catch (error) {
if ((error.response?.status))
throw {error:{message:`API returned ${error.response.status}${error.response.data?.error_description ? ` (${error.response.data.error_description})` : ""}`}, ...raw}
if (error.isAxiosError) {
const status = error.response?.status
const description = error.response.data?.error_description ?? null
message = `API returned ${status}${description ? ` (${description})` : ""}`
error = error.response?.data ?? null
throw {error:{message, instance:error}, ...raw}
}
throw error
}
break
@@ -173,7 +180,6 @@
track.artwork = await imports.imgb64(track.artwork)
}
//Save results
console.debug(`metrics/compute/${login}/plugins > music > success`)
return {...raw, tracks}
}
//Unhandled error
@@ -183,7 +189,6 @@
catch (error) {
if (error.error?.message)
throw error
console.debug(error)
throw {error:{message:`An error occured`}}
throw {error:{message:"An error occured", instance:error}}
}
}
+21 -13
View File
@@ -15,29 +15,37 @@
url = `https://${url}`
const result = {url, detailed, scores:[], metrics:{}}
//Load scores from API
console.debug(`metrics/compute/${login}/plugins > pagespeed > querying api for ${url}`)
const scores = new Map()
await Promise.all(["performance", "accessibility", "best-practices", "seo"].map(async category => {
const {score, title} = (await imports.axios.get(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?category=${category}&url=${url}&key=${token}`)).data.lighthouseResult.categories[category]
console.debug(`metrics/compute/${login}/plugins > pagespeed > performing audit ${category}`)
const request = await imports.axios.get(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?category=${category}&url=${url}&key=${token}`)
console.debug(request.data)
const {score, title} = request.data.lighthouseResult.categories[category]
scores.set(category, {score, title})
console.debug(`metrics/compute/${login}/plugins > pagespeed > ${category} audit performed`)
console.debug(`metrics/compute/${login}/plugins > pagespeed > performed audit ${category} (status code ${request.status})`)
}))
result.scores = [scores.get("performance"), scores.get("accessibility"), scores.get("best-practices"), scores.get("seo")]
//Detailed metrics
if (detailed)
Object.assign(result.metrics, ...(await imports.axios.get(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?&url=${url}&key=${token}`)).data.lighthouseResult.audits.metrics.details.items)
//Integrity check
if (result.scores.filter(score => score).length < 4)
throw {error:{message:"Incomplete PageSpeed results"}, url}
if (detailed) {
console.debug(`metrics/compute/${login}/plugins > pagespeed > performing detailed audit`)
const request = await imports.axios.get(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?&url=${url}&key=${token}`)
console.debug(request.data)
Object.assign(result.metrics, ...request.data.lighthouseResult.audits.metrics.details.items)
console.debug(`metrics/compute/${login}/plugins > pagespeed > performed detailed audit (status code ${request.status})`)
}
//Results
return result
}
//Handle errors
catch (error) {
if (error.response?.status)
throw {error:{message:`PageSpeed token error (code ${error.response.status})`}, url}
if (error.error?.message)
throw error
console.debug(error)
throw {error:{message:`An error occured`}}
let message = "An error occured"
if (error.isAxiosError) {
const status = error.response?.status
const description = error.response?.data?.error?.message?.match(/Lighthouse returned error: (?<description>[A-Z_]+)/)?.groups?.description ?? null
message = `API returned ${status}${description ? ` (${description})` : ""}`
error = error.response?.data ?? null
}
throw {error:{message, instance:error}}
}
}
+3 -2
View File
@@ -11,10 +11,12 @@
//Limit
limit = Math.max(1, Math.min(30, Number(limit)))
//Retrieve posts
console.debug(`metrics/compute/${login}/plugins > posts > processing with source ${source}`)
let posts = null
switch (source) {
//Dev.to
case "dev.to":{
console.debug(`metrics/compute/${login}/plugins > posts > querying api`)
posts = (await imports.axios.get(`https://dev.to/api/articles?username=${login}&state=fresh`)).data.map(({title, readable_publish_date:date}) => ({title, date}))
break
}
@@ -37,7 +39,6 @@
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
throw {error:{message:"An error occured", instance:error}}
}
}
+6 -2
View File
@@ -10,6 +10,7 @@
//Limit
limit = Math.max(1, Math.min(100, Number(limit)))
//Retrieve contribution calendar from graphql api
console.debug(`metrics/compute/${login}/plugins > projects > querying api`)
const {user:{projects}} = await graphql(`
query Projects {
user(login: "${login}") {
@@ -31,6 +32,7 @@
`
)
//Iterate through projects and format them
console.debug(`metrics/compute/${login}/plugins > posts > processing ${projects.nodes.length} projects`)
const list = []
for (const project of projects.nodes) {
//Format date
@@ -52,7 +54,9 @@
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
let message = "An error occured"
if (error.errors?.map(({type}) => type)?.includes("INSUFFICIENT_SCOPES"))
message = "Insufficient token rights"
throw {error:{message, instance:error}}
}
}
+11 -5
View File
@@ -14,10 +14,11 @@
//Limit
limit = Math.max(1, Math.min(20, Number(limit)))
//Start puppeteer and navigate to topics
console.debug(`metrics/compute/${login}/plugins > topics > searching starred topics`)
let topics = []
console.debug(`metrics/compute/${login}/plugins > topics > starting browser`)
const browser = await imports.puppeteer.launch({headless:true, executablePath:process.env.PUPPETEER_BROWSER_PATH, args:["--no-sandbox", "--disable-extensions", "--disable-setuid-sandbox", "--disable-dev-shm-usage"]})
console.debug(`metrics/compute/${login}/plugins > topics > loaded ${await browser.version()}`)
console.debug(`metrics/compute/${login}/plugins > topics > started ${await browser.version()}`)
const page = await browser.newPage()
//Iterate through pages
for (let i = 1; i <= 100; i++) {
@@ -32,17 +33,22 @@
description:li.querySelector(".f5").innerText,
icon:li.querySelector("img")?.src ?? null,
})))
console.debug(`metrics/compute/${login}/plugins > topics > extracted ${starred.length} starred topics`)
//Check if next page exists
if (!starred.length)
if (!starred.length) {
console.debug(`metrics/compute/${login}/plugins > topics > no more page to load`)
break
}
topics.push(...starred)
}
//Close browser
console.debug(`metrics/compute/${login}/plugins > music > closing browser`)
await browser.close()
//Shuffle topics
if (shuffle)
if (shuffle) {
console.debug(`metrics/compute/${login}/plugins > topics > shuffling topics`)
topics = imports.shuffle(topics)
}
//Limit topics
if (limit > 0) {
console.debug(`metrics/compute/${login}/plugins > topics > keeping only ${limit} topics`)
@@ -51,6 +57,7 @@
topics.push({name:`And ${removed.length} more...`, description:removed.map(({name}) => name).join(", "), icon:null})
}
//Convert icons to base64
console.debug(`metrics/compute/${login}/plugins > topics > loading artworks`)
for (const topic of topics) {
if (topic.icon) {
console.debug(`metrics/compute/${login}/plugins > topics > processing ${topic.name}`)
@@ -64,7 +71,6 @@
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
throw {error:{message:"An error occured", instance:error}}
}
}
+5 -3
View File
@@ -8,9 +8,11 @@
//Repositories
const repositories = data.user.repositories.nodes.map(({name}) => name) ?? []
//Get views stats from repositories
console.debug(`metrics/compute/${login}/plugins > traffic > querying api`)
const views = {count:0, uniques:0}
const response = await Promise.all(repositories.map(async repo => await rest.repos.getViews({owner:login, repo})))
//Compute views
console.debug(`metrics/compute/${login}/plugins > traffic > computing stats`)
response.filter(({data}) => data).map(({data:{count, uniques}}) => (views.count += count, views.uniques += uniques))
//Format values
views.count = imports.format(views.count)
@@ -20,9 +22,9 @@
}
//Handle errors
catch (error) {
let message = "An error occured"
if (error.status === 403)
throw {error:{message:`Insufficient token rights`}}
console.debug(error)
throw {error:{message:`An error occured`}}
message = "Insufficient token rights"
throw {error:{message, instance:error}}
}
}
+9 -3
View File
@@ -14,7 +14,7 @@
console.debug(`metrics/compute/${login}/plugins > tweets > loading twitter profile (@${username})`)
const {data:{data:profile = null}} = await imports.axios.get(`https://api.twitter.com/2/users/by/username/${username}?user.fields=profile_image_url,verified`, {headers:{Authorization:`Bearer ${token}`}})
//Load tweets
console.debug(`metrics/compute/${login}/plugins > tweets > loading tweets`)
console.debug(`metrics/compute/${login}/plugins > tweets > querying api`)
const {data:{data:tweets = []}} = await imports.axios.get(`https://api.twitter.com/2/tweets/search/recent?query=from:${username}&tweet.fields=created_at&expansions=entities.mentions.username`, {headers:{Authorization:`Bearer ${token}`}})
//Load profile image
if (profile?.profile_image_url) {
@@ -50,7 +50,13 @@
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
let message = "An error occured"
if (error.isAxiosError) {
const status = error.response?.status
const description = error.response?.data?.errors?.[0]?.message ?? null
message = `API returned ${status}${description ? ` (${description})` : ""}`
error = error.response?.data ?? null
}
throw {error:{message, instance:error}}
}
}
+2 -1
View File
@@ -1,6 +1,7 @@
//Imports
import fs from "fs"
import path from "path"
import util from "util"
/** Setup */
export default async function ({log = true} = {}) {
@@ -30,7 +31,7 @@
conf.settings.plugins = {}
conf.settings.plugins.base = {parts:["header", "activity", "community", "repositories", "metadata"]}
if (conf.settings.debug)
logger(conf.settings)
logger(util.inspect(conf.settings, {depth:Infinity, maxStringLength:256}))
//Load package settings
logger(`metrics/setup > load package.json`)
+2 -2
View File
@@ -13,7 +13,7 @@
+ (!!plugins.isocalendar)*192 + (plugins.isocalendar?.duration === 'full-year')*100
+ (!!plugins.gists)*68
+ (!!plugins.topics)*160
+ (!!plugins.projects)*22 + (plugins.projects?.list?.length ?? 0)*60
+ (!!plugins.projects)*22 + (plugins.projects?.list?.length ?? 0)*60 + (!!plugins.projects?.error)*22
+ (!!plugins.tweets)*64 + (plugins.tweets?.list?.length ?? 0)*90
+ Math.max(0, (((!!base.metadata)+(!!base.header)+((!!base.activity)||(!!base.community))+(!!base.repositories)+((!!plugins.habits))+(!!plugins.pagespeed)+(!!plugins.languages)+(!!plugins.music)+(!!plugins.posts)+(!!plugins.isocalendar)+(!!plugins.gists)+(!!plugins.topics)+(!!plugins.projects))-1))*4
%>">
@@ -774,7 +774,7 @@
<% if (base.metadata) { %>
<footer>
<span>These metrics <%= !computed.token.scopes.includes("repo") ? "does not include" : "includes" %> private contributions</span>
<span>These metrics <%= !computed.token.scopes.includes("repo") ? "does not include all" : "includes" %> private contributions<% if ((config.timezone?.name)&&(!config.timezone?.error)) { %>, timezone <%= config.timezone.name %><% } %></span>
<span>Last updated <%= new Date().toGMTString() %> with lowlighter/metrics@<%= meta.version %></span>
</footer>
<% } %>

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

+23 -5
View File
@@ -5,18 +5,36 @@
const computed = data.computed = {commits:0, sponsorships:0, licenses:{favorite:"", used:{}}, token:{}, repositories:{watchers:0, stargazers:0, issues_open:0, issues_closed:0, pr_open:0, pr_merged:0, forks:0, releases:0}}
const avatar = imports.imgb64(data.user.avatarUrl)
data.plugins = {}
console.debug(`metrics/compute/${login} > formatting common metrics`)
//Timezone config
if (q["config.timezone"]) {
const timezone = data.config.timezone = {name:q["config.timezone"], offset:0}
try {
timezone.offset = Number(new Date().toLocaleString("fr", {timeZoneName:"short", timeZone:timezone.name}).match(/UTC[+](?<offset>\d+)/)?.groups?.offset*60*60*1000) || 0
console.debug(`metrics/compute/${login} > timezone set to ${timezone.name} (${timezone.offset > 0 ? "+" : ""}${Math.round(timezone.offset/(60*60*1000))} hours)`)
} catch {
timezone.error = `Failed to use timezone "${timezone.name}"`
console.debug(`metrics/compute/${login} > failed to use timezone "${timezone.name}"`)
}
}
//Plugins
for (const name of Object.keys(imports.plugins)) {
pending.push((async () => {
try {
console.debug(`metrics/compute/${login}/plugins > ${name} > started`)
data.plugins[name] = await imports.plugins[name]({login, q, imports, data, computed, rest, graphql}, plugins[name])
console.debug(`metrics/compute/${login}/plugins > ${name} > completed (${data.plugins[name] !== null ? "success" : "skipped"})`)
}
catch (error) {
console.debug(`metrics/compute/${login}/plugins > ${name} > completed (error)`)
data.plugins[name] = error
}
finally {
return {name, result:data.plugins[name]}
const result = {name, result:data.plugins[name]}
console.debug(imports.util.inspect(result, {depth:Infinity, maxStringLength:256}))
return result
}
})())
}
@@ -30,14 +48,14 @@
computed.repositories.forks += repository.forkCount
//License
if (repository.licenseInfo)
computed.licenses.used[repository.licenseInfo.spdxId] = (computed.licenses.used[repository.licenseInfo.spdxId] || 0) + 1
computed.licenses.used[repository.licenseInfo.spdxId] = (computed.licenses.used[repository.licenseInfo.spdxId] ?? 0) + 1
}
//Total disk usage
computed.diskUsage = `${imports.bytes(data.user.repositories.totalDiskUsage*1000)}`
//Compute licenses stats
computed.licenses.favorite = Object.entries(computed.licenses.used).sort(([an, a], [bn, b]) => b - a).slice(0, 1).map(([name, value]) => name) || ""
computed.licenses.favorite = Object.entries(computed.licenses.used).sort(([an, a], [bn, b]) => b - a).slice(0, 1).map(([name, value]) => name) ?? ""
//Compute total commits
computed.commits += data.user.contributionsCollection.totalCommitContributions + data.user.contributionsCollection.restrictedContributionsCount
@@ -62,11 +80,11 @@
data.meta = {version:conf.package.version, author:conf.package.author}
//Debug flags
if (dflags.includes("--cakeday")||q["dflag.cakeday"]) {
if ((dflags.includes("--cakeday"))||(q["dflag.cakeday"])) {
console.debug(`metrics/compute/${login} > applying dflag --cakeday`)
computed.cakeday = true
}
if (dflags.includes("--hireable")||q["dflag.hireable"]) {
if ((dflags.includes("--hireable"))||(q["dflag.hireable"])) {
console.debug(`metrics/compute/${login} > applying dflag --hireable`)
data.user.isHireable = true
}