Skip to content

Commit

Permalink
Add new plugin topics (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
lowlighter committed Dec 8, 2020
1 parent 7f77d33 commit 9a3f05d
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 10 deletions.
44 changes: 44 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,47 @@ jobs:
plugin_gists: yes
plugins_errors_fatal: yes
dryrun: yes

- name: Topics plugin (stars)
uses: lowlighter/metrics@master
with:
token: ${{ secrets.METRICS_TOKEN }}
base: ""
repositories: 1
plugin_topics: yes
plugin_topics_sort: stars
plugins_errors_fatal: yes
dryrun: yes

- name: Topics plugin (activity)
uses: lowlighter/metrics@master
with:
token: ${{ secrets.METRICS_TOKEN }}
base: ""
repositories: 1
plugin_topics: yes
plugin_topics_sort: activity
plugins_errors_fatal: yes
dryrun: yes

- name: Topics plugin (starred)
uses: lowlighter/metrics@master
with:
token: ${{ secrets.METRICS_TOKEN }}
base: ""
repositories: 1
plugin_topics: yes
plugin_topics_sort: starred
plugins_errors_fatal: yes
dryrun: yes

- name: Topics plugin (random)
uses: lowlighter/metrics@master
with:
token: ${{ secrets.METRICS_TOKEN }}
base: ""
repositories: 1
plugin_topics: yes
plugin_topics_sort: random
plugins_errors_fatal: yes
dryrun: yes
23 changes: 23 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,29 @@ inputs:
description: Display gists metrics
default: no

# Topics plugins
# Display starred topics
plugin_topics:
description: Display starred topics
default: no

# Sorting method of topics
# Supported values are :
# - "stars" to sort them from most starred to least starred
# - "activity" to sort them from most recent activity to least recent activity
# - "starred" to sort them from your most recently starred to your least recently starred
# - "random" to sort them randomly
plugin_topics_sort:
description: Sorting method of starred topics
default: "stars"

# Limit the number of topics displayed
# Between 1 and 20
# If more topics must be displayed, they will be grouped in an ellipsis
plugin_topics_limit:
description: Number of starred topics to display
default: 15

# Enable debug mode
# Be sure to put all secrets in your repository secrets before to avoid any leaks !
debug:
Expand Down
16 changes: 8 additions & 8 deletions action/dist/index.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions action/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
posts:{enabled:bool(core.getInput("plugin_posts"))},
isocalendar:{enabled:bool(core.getInput("plugin_isocalendar"))},
gists:{enabled:bool(core.getInput("plugin_gists"))},
topics:{enabled:bool(core.getInput("plugin_topics"))},
}
let q = Object.fromEntries(Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => [key, true]))
console.log(`Plugins enabled | ${Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => key).join(", ")}`)
Expand Down Expand Up @@ -115,6 +116,13 @@
q["isocalendar.duration"] = core.getInput("plugin_isocalendar_duration") ?? "half-year"
console.log(`Isocalendar duration| ${q["isocalendar.duration"]}`)
}
//Topics
if (plugins.topics.enabled) {
for (const option of ["sort", "limit"])
q[`topics.${option}`] = core.getInput(`plugin_topics_${option}`) || null
console.log(`Topics sort mode | ${q["topics.sort"]}`)
console.log(`Topics limit | ${q["topics.limit"]}`)
}

//Repositories to use
const repositories = Number(core.getInput("repositories")) || 100
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metrics",
"version": "2.5.0",
"version": "2.6.0",
"description": "Generate an user's GitHub metrics as SVG image format to embed somewhere else",
"main": "index.mjs",
"scripts": {
Expand Down
3 changes: 3 additions & 0 deletions settings.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
},
"gists":{ "//":"Gists plugin",
"enabled":false, "//":"Enable or disable gists metrics"
},
"topics":{ "//":"Topics plugin",
"enabled":false, "//":"Enable or disable starred topics display"
}
}
}
1 change: 1 addition & 0 deletions src/html/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
posts:"Recent posts",
isocalendar:"Isometric commit calendar",
gists:"Gists metrics",
topics:"Starred topics",
"base.header":"Header",
"base.activity":"Account activity",
"base.community":"Community stats",
Expand Down
13 changes: 12 additions & 1 deletion src/metrics.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
//Compute metrics
console.debug(`metrics/compute/${login} > compute`)
const computer = Templates[template].default || Templates[template]
await computer({login, q}, {conf, data, rest, graphql, plugins}, {s, pending, imports:{plugins:Plugins, url, imgb64, axios, puppeteer, format, bytes, shuffle}})
await computer({login, q}, {conf, data, rest, graphql, plugins}, {s, pending, imports:{plugins:Plugins, url, imgb64, axios, puppeteer, format, bytes, shuffle, htmlescape}})
const promised = await Promise.all(pending)

//Check plugins errors
Expand Down Expand Up @@ -113,6 +113,16 @@
return array
}

/** Escape html */
function htmlescape(string) {
return string
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;")
}

/** Placeholder generator */
function placeholder({data, conf, q}) {
//Proxifier
Expand Down Expand Up @@ -154,6 +164,7 @@
followup:{issues:{count:0}, pr:{count:0}},
habits:{indents:{style:`########`}},
languages:{favorites:new Array(7).fill(null).map((_, x) => ({x, name:`######`, color:"#ebedf0", value:1/(x+1)}))},
topics:{list:[...new Array(12).fill(null).map(() => ({name:`######`, description:`Lorem ipsum dolor sit amet, consectetur adipiscing elit.`, icon:null})), {name:`And ## more...`, description:"", icon:null}]},
}[key]??{})]
)),
token:{scopes:[]},
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import pagespeed from "./pagespeed/index.mjs"
import posts from "./posts/index.mjs"
import selfskip from "./selfskip/index.mjs"
import topics from "./topics/index.mjs"
import traffic from "./traffic/index.mjs"

//Exports
Expand All @@ -25,5 +26,6 @@
pagespeed,
posts,
selfskip,
topics,
traffic,
}
67 changes: 67 additions & 0 deletions src/plugins/topics/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//Setup
export default async function ({login, imports, q}, {enabled = false} = {}) {
//Plugin execution
try {
//Check if plugin is enabled and requirements are met
if ((!enabled)||(!q.topics))
return null
//Parameters override
let {"topics.sort":sort = "stars", "topics.limit":limit = 15} = q
//Shuffle
const shuffle = (sort === "random")
//Sort method
sort = {starred:"created", activity:"updated", stars:"stars", random:"created"}[sort] ?? "starred"
//Limit
limit = Math.max(1, Math.min(20, Number(limit)))
//Start puppeteer and navigate to 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()}`)
const page = await browser.newPage()
//Iterate through pages
for (let i = 1; i <= 100; i++) {
//Load page
console.debug(`metrics/compute/${login}/plugins > topics > loading page ${i}`)
await page.goto(`https://github.com/stars/${login}/topics?direction=desc&page=${i}&sort=${sort}`)
const frame = page.mainFrame()
//Extract topics
await Promise.race([frame.waitForSelector("ul.repo-list"), frame.waitForSelector(".blankslate")])
const starred = await frame.evaluate(() => [...document.querySelectorAll("ul.repo-list li")].map(li => ({
name:li.querySelector(".f3").innerText,
description:li.querySelector(".f5").innerText,
icon:li.querySelector("img")?.src ?? null,
})))
//Check if next page exists
if (!starred.length)
break
topics.push(...starred)
}
//Shuffle topics
if (shuffle)
topics = imports.shuffle(topics)
//Limit topics
if (limit > 0) {
console.debug(`metrics/compute/${login}/plugins > topics > keeping only ${limit} topics`)
const removed = topics.slice(limit)
topics = topics.slice(0, limit)
topics.push({name:`And ${removed.length} more...`, description:removed.map(({name}) => name).join(", "), icon:null})
}
//Convert icons to base64
for (const topic of topics) {
if (topic.icon) {
console.debug(`metrics/compute/${login}/plugins > topics > processing ${topic.name}`)
topic.icon = await imports.imgb64(topic.icon)
}
//Escape HTML description
topic.description = imports.htmlescape(topic.description)
}
//Results
return {list:topics}
}
//Handle errors
catch (error) {
console.debug(error)
throw {error:{message:`An error occured`}}
}
}
28 changes: 28 additions & 0 deletions src/templates/classic/image.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions src/templates/classic/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,24 @@
opacity: .7;
}

/* Labels */
.label {
background-color: #F1F8FF;
color: #0366D6;
padding: 0 10px;
font-weight: 500;
line-height: 22px;
margin: 2px 5px;
white-space: nowrap;
border-radius: 32px;
font-size: 12px;
}

.label:hover {
background-color: #DDEEFF;
cursor: pointer;
}

/* Habits */
.habits {
margin: 0;
Expand Down Expand Up @@ -242,6 +260,12 @@
padding-top: 1px;
}

/* Topics */
.topics {
display: flex;
flex-wrap: wrap;
}

/* Fade animation */
.af {
opacity: 0;
Expand Down

0 comments on commit 9a3f05d

Please sign in to comment.