Refactor web instance to add missing supported plugins options, rename routes and display remaining GitHub requests (#20)
This commit is contained in:
2
action/dist/index.js
vendored
2
action/dist/index.js
vendored
File diff suppressed because one or more lines are too long
42
src/app.mjs
42
src/app.mjs
@@ -47,31 +47,25 @@
|
|||||||
const actions = {flush:new Map()}
|
const actions = {flush:new Map()}
|
||||||
app.get("/", limiter, (req, res) => res.sendFile(`${conf.statics}/index.html`))
|
app.get("/", limiter, (req, res) => res.sendFile(`${conf.statics}/index.html`))
|
||||||
app.get("/index.html", limiter, (req, res) => res.sendFile(`${conf.statics}/index.html`))
|
app.get("/index.html", limiter, (req, res) => res.sendFile(`${conf.statics}/index.html`))
|
||||||
app.get("/app.js", limiter, (req, res) => res.sendFile(`${conf.statics}/app.js`))
|
|
||||||
app.get("/style.css", limiter, (req, res) => res.sendFile(`${conf.statics}/style.css`))
|
|
||||||
app.get("/.version", limiter, (req, res) => res.status(200).send(conf.package.version))
|
|
||||||
app.get("/favicon.ico", limiter, (req, res) => res.sendStatus(204))
|
app.get("/favicon.ico", limiter, (req, res) => res.sendStatus(204))
|
||||||
app.get("/plugins.list", limiter, (req, res) => res.status(200).json(enabled))
|
app.get("/.version", limiter, (req, res) => res.status(200).send(conf.package.version))
|
||||||
app.get("/templates.list", limiter, (req, res) => res.status(200).json(templates))
|
app.get("/.requests", limiter, async (req, res) => res.status(200).json((await rest.rateLimit.get()).data.rate))
|
||||||
app.get("/plugins.base.parts.list", limiter, (req, res) => res.status(200).json(conf.settings.plugins.base.parts))
|
app.get("/.templates", limiter, (req, res) => res.status(200).json(templates))
|
||||||
app.get("/ejs.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/ejs/ejs.min.js`))
|
app.get("/.plugins", limiter, (req, res) => res.status(200).json(enabled))
|
||||||
app.get("/axios.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/axios/dist/axios.min.js`))
|
app.get("/.plugins.base", limiter, (req, res) => res.status(200).json(conf.settings.plugins.base.parts))
|
||||||
app.get("/axios.min.map", limiter, (req, res) => res.sendFile(`${conf.node_modules}/axios/dist/axios.min.map`))
|
app.get("/.css/style.css", limiter, (req, res) => res.sendFile(`${conf.statics}/style.css`))
|
||||||
app.get("/vue.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/vue/dist/vue.min.js`))
|
app.get("/.css/style.prism.css", limiter, (req, res) => res.sendFile(`${conf.node_modules}/prismjs/themes/prism-tomorrow.css`))
|
||||||
app.get("/vue.prism.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/vue-prism-component/dist/vue-prism-component.min.js`))
|
app.get("/.js/app.js", limiter, (req, res) => res.sendFile(`${conf.statics}/app.js`))
|
||||||
app.get("/vue-prism-component.min.js.map", limiter, (req, res) => res.sendFile(`${conf.node_modules}/vue-prism-component/dist/vue-prism-component.min.js.map`))
|
app.get("/.js/ejs.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/ejs/ejs.min.js`))
|
||||||
app.get("/prism.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/prismjs/prism.js`))
|
app.get("/.js/axios.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/axios/dist/axios.min.js`))
|
||||||
app.get("/prism.yaml.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/prismjs/components/prism-yaml.min.js`))
|
app.get("/.js/axios.min.map", limiter, (req, res) => res.sendFile(`${conf.node_modules}/axios/dist/axios.min.map`))
|
||||||
app.get("/prism.markdown.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/prismjs/components/prism-markdown.min.js`))
|
app.get("/.js/vue.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/vue/dist/vue.min.js`))
|
||||||
app.get("/style.prism.css", limiter, (req, res) => res.sendFile(`${conf.node_modules}/prismjs/themes/prism-tomorrow.css`))
|
app.get("/.js/vue.prism.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/vue-prism-component/dist/vue-prism-component.min.js`))
|
||||||
app.get("/placeholder.json", limiter, async (req, res) => {
|
app.get("/.js/vue-prism-component.min.js.map", limiter, (req, res) => res.sendFile(`${conf.node_modules}/vue-prism-component/dist/vue-prism-component.min.js.map`))
|
||||||
const template = req.query.template || conf.settings.templates.default
|
app.get("/.js/prism.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/prismjs/prism.js`))
|
||||||
if (!(template in Templates))
|
app.get("/.js/prism.yaml.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/prismjs/components/prism-yaml.min.js`))
|
||||||
return res.sendStatus(404)
|
app.get("/.js/prism.markdown.min.js", limiter, (req, res) => res.sendFile(`${conf.node_modules}/prismjs/components/prism-markdown.min.js`))
|
||||||
const {style, image, fonts} = conf.templates[template]
|
app.get("/.uncache", limiter, async (req, res) => {
|
||||||
res.status(200).json({style, image, fonts})
|
|
||||||
})
|
|
||||||
app.get("/action.flush", limiter, async (req, res) => {
|
|
||||||
const {token, user} = req.query
|
const {token, user} = req.query
|
||||||
if (token) {
|
if (token) {
|
||||||
if (actions.flush.has(token)) {
|
if (actions.flush.has(token)) {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
;(async function() {
|
;(async function() {
|
||||||
//Init
|
//Init
|
||||||
const url = new URLSearchParams(window.location.search)
|
const url = new URLSearchParams(window.location.search)
|
||||||
const {data:templates} = await axios.get("/templates.list")
|
const {data:templates} = await axios.get("/.templates")
|
||||||
const {data:plugins} = await axios.get("/plugins.list")
|
const {data:plugins} = await axios.get("/.plugins")
|
||||||
const {data:base} = await axios.get("/plugins.base.parts.list")
|
const {data:base} = await axios.get("/.plugins.base")
|
||||||
const {data:version} = await axios.get("/.version")
|
const {data:version} = await axios.get("/.version")
|
||||||
//App
|
//App
|
||||||
return new Vue({
|
return new Vue({
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
version,
|
version,
|
||||||
user:url.get("user") || "",
|
user:url.get("user") || "",
|
||||||
palette:url.get("palette") || (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light") || "light",
|
palette:url.get("palette") || (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light") || "light",
|
||||||
|
requests:{limit:0, used:0, remaining:0, reset:0},
|
||||||
plugins:{
|
plugins:{
|
||||||
base,
|
base,
|
||||||
list:plugins,
|
list:plugins,
|
||||||
@@ -45,10 +46,13 @@
|
|||||||
"pagespeed.detailed":false,
|
"pagespeed.detailed":false,
|
||||||
"habits.from":100,
|
"habits.from":100,
|
||||||
"music.playlist":"",
|
"music.playlist":"",
|
||||||
"music.mode":"playlist",
|
|
||||||
"music.limit":4,
|
"music.limit":4,
|
||||||
"posts.limit":4,
|
"posts.limit":4,
|
||||||
"posts.source":"dev.to",
|
"posts.source":"dev.to",
|
||||||
|
"isocalendar.duration":"half-year",
|
||||||
|
"projects.limit":4,
|
||||||
|
"topics.sort":"stars",
|
||||||
|
"topics.limit":12,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
templates:{
|
templates:{
|
||||||
@@ -130,6 +134,8 @@
|
|||||||
const url = this.url.replace(new RegExp(`${this.user}(\\?|$)`), "placeholder$1")
|
const url = this.url.replace(new RegExp(`${this.user}(\\?|$)`), "placeholder$1")
|
||||||
this.templates.placeholder = this.serialize((await axios.get(url)).data)
|
this.templates.placeholder = this.serialize((await axios.get(url)).data)
|
||||||
this.generated.content = ""
|
this.generated.content = ""
|
||||||
|
//Start GitHub rate limiter tracker
|
||||||
|
this.ghlimit()
|
||||||
},
|
},
|
||||||
//Generate metrics and flush cache
|
//Generate metrics and flush cache
|
||||||
async generate() {
|
async generate() {
|
||||||
@@ -139,7 +145,7 @@
|
|||||||
this.generated.pending = true
|
this.generated.pending = true
|
||||||
//Compute metrics
|
//Compute metrics
|
||||||
try {
|
try {
|
||||||
await axios.get(`/action.flush?&token=${(await axios.get(`/action.flush?user=${this.user}`)).data.token}`)
|
await axios.get(`/.uncache?&token=${(await axios.get(`/.uncache?user=${this.user}`)).data.token}`)
|
||||||
this.generated.content = this.serialize((await axios.get(this.url)).data)
|
this.generated.content = this.serialize((await axios.get(this.url)).data)
|
||||||
} catch {
|
} catch {
|
||||||
this.generated.error = true
|
this.generated.error = true
|
||||||
@@ -152,6 +158,13 @@
|
|||||||
serialize(svg) {
|
serialize(svg) {
|
||||||
return `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svg)))}`
|
return `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svg)))}`
|
||||||
},
|
},
|
||||||
|
//Update reate limit requests
|
||||||
|
async ghlimit() {
|
||||||
|
const {data:requests} = await axios.get("/.requests")
|
||||||
|
this.requests = requests
|
||||||
|
setTimeout(() => this.ghlimit(), 30*1000)
|
||||||
|
console.log("yeh")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})()
|
})()
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
<meta name="description" content="A SVG image generator which includes activity, community and repositories metrics about your GitHub account that you can includes on your profile">
|
<meta name="description" content="A SVG image generator which includes activity, community and repositories metrics about your GitHub account that you can includes on your profile">
|
||||||
<meta name="author" content="lowlighter">
|
<meta name="author" content="lowlighter">
|
||||||
<link rel="icon" href="data:,">
|
<link rel="icon" href="data:,">
|
||||||
<link rel="stylesheet" href="/style.css">
|
<link rel="stylesheet" href="/.css/style.css">
|
||||||
<link rel="stylesheet" href="/style.prism.css" />
|
<link rel="stylesheet" href="/.css/style.prism.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- Vue app -->
|
<!-- Vue app -->
|
||||||
@@ -51,25 +51,80 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<i>*Additional plugins may be available when used as GitHub Action</i>
|
<i>*Additional plugins may be available when used as GitHub Action</i>
|
||||||
<template v-if="(plugins.enabled.pagespeed)||(plugins.enabled.habits)||(plugins.enabled.music)||(plugins.enabled.posts)">
|
<template v-if="(plugins.enabled.music)||(plugins.enabled.pagespeed)||(plugins.enabled.habits)||(plugins.enabled.posts)||(plugins.enabled.isocalendar)||(plugins.enabled.projects)||(plugins.enabled.topics)">
|
||||||
<h3>2.3 Configure additional plugins</h3>
|
<h3>2.3 Configure additional plugins</h3>
|
||||||
<div class="options">
|
<div class="options">
|
||||||
<label v-if="plugins.enabled.pagespeed">
|
<div class="options-group" v-if="plugins.enabled.music">
|
||||||
Detailed PageSpeed report
|
<h4>{{ plugins.descriptions.music }}</h4>
|
||||||
<input type="checkbox" v-model="plugins.options['pagespeed.detailed']" @change="load">
|
<label>
|
||||||
</label>
|
Playlist embed link
|
||||||
<label v-if="(plugins.enabled.music)&&(plugins.options['music.mode'] === 'playlist')">
|
<input type="text" v-model="plugins.options['music.playlist']" placeholder="https://embed.music.apple.com/en/playlist/">
|
||||||
Playlist embed link
|
</label>
|
||||||
<input type="text" v-model="plugins.options['music.playlist']" placeholder="https://embed.music.apple.com/en/playlist/">
|
<label>
|
||||||
</label>
|
Number of tracks to display
|
||||||
<label v-if="plugins.enabled.habits">
|
<input type="number" v-model="plugins.options['music.limit']" min="1" @change="load">
|
||||||
Number of events for habits
|
</label>
|
||||||
<input type="number" v-model="plugins.options['habits.from']" min="1" max="100">
|
</div>
|
||||||
</label>
|
<div class="options-group" v-if="plugins.enabled.pagespeed">
|
||||||
<label v-if="plugins.enabled.posts">
|
<h4>{{ plugins.descriptions.pagespeed }}</h4>
|
||||||
Posts source
|
<label>
|
||||||
<input type="text" v-model="plugins.options['posts.source']" disabled>
|
Detailed PageSpeed report
|
||||||
</label>
|
<input type="checkbox" v-model="plugins.options['pagespeed.detailed']" @change="load">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="options-group" v-if="plugins.enabled.habits">
|
||||||
|
<h4>{{ plugins.descriptions.habits }}</h4>
|
||||||
|
<label>
|
||||||
|
Number of events for habits
|
||||||
|
<input type="number" v-model="plugins.options['habits.from']" min="1" max="100">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="options-group" v-if="plugins.enabled.posts">
|
||||||
|
<h4>{{ plugins.descriptions.posts }}</h4>
|
||||||
|
<label>
|
||||||
|
Posts source
|
||||||
|
<select v-model="plugins.options['posts.source']" disabled>
|
||||||
|
<option value="dev.to">dev.to</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Number of posts to display
|
||||||
|
<input type="number" v-model="plugins.options['posts.limit']" min="1" @change="load">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="options-group" v-if="plugins.enabled.isocalendar">
|
||||||
|
<h4>{{ plugins.descriptions.isocalendar }}</h4>
|
||||||
|
<label>
|
||||||
|
Isocalendar duration
|
||||||
|
<select v-model="plugins.options['isocalendar.duration']">
|
||||||
|
<option value="half-year">Half year</option>
|
||||||
|
<option value="full-year">Full year</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="options-group" v-if="plugins.enabled.topics">
|
||||||
|
<h4>{{ plugins.descriptions.topics }}</h4>
|
||||||
|
<label>
|
||||||
|
Topics sorting
|
||||||
|
<select v-model="plugins.options['topics.sort']">
|
||||||
|
<option value="starred">Recently starred by you</option>
|
||||||
|
<option value="stars">Most stars</option>
|
||||||
|
<option value="activity">Recent actity</option>
|
||||||
|
<option value="random">Random</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Number of topics to display
|
||||||
|
<input type="number" v-model="plugins.options['topics.limit']" @change="load">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="options-group" v-if="plugins.enabled.projects">
|
||||||
|
<h4>{{ plugins.descriptions.projects }}</h4>
|
||||||
|
<label>
|
||||||
|
Number of projects to display
|
||||||
|
<input type="number" v-model="plugins.options['projects.limit']" min="1" max="100" @change="load">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
@@ -128,15 +183,19 @@
|
|||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
<!-- GitHub requests tracker -->
|
||||||
|
<template>
|
||||||
|
<div class="gh-requests">{{ requests.remaining }} GitHub request{{ requests.remaining > 1 ? "s" : "" }} remaining</div>
|
||||||
|
</template>
|
||||||
</main>
|
</main>
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
<script src="/axios.min.js"></script>
|
<script src="/.js/axios.min.js"></script>
|
||||||
<script src="/prism.min.js"></script>
|
<script src="/.js/prism.min.js"></script>
|
||||||
<script src="/prism.markdown.min.js"></script>
|
<script src="/.js/prism.markdown.min.js"></script>
|
||||||
<script src="/prism.yaml.min.js"></script>
|
<script src="/.js/prism.yaml.min.js"></script>
|
||||||
<script src="/ejs.min.js"></script>
|
<script src="/.js/ejs.min.js"></script>
|
||||||
<script src="/vue.min.js"></script>
|
<script src="/.js/vue.min.js"></script>
|
||||||
<script src="/vue.prism.min.js"></script>
|
<script src="/.js/vue.prism.min.js"></script>
|
||||||
<script src="/app.js"></script>
|
<script src="/.js/app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -142,6 +142,16 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
.options-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.options-group label {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.options-group h4 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
/* Code snippets */
|
/* Code snippets */
|
||||||
.code {
|
.code {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -194,3 +204,10 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
/* Github requests */
|
||||||
|
.gh-requests {
|
||||||
|
position: fixed;
|
||||||
|
right: .25rem;
|
||||||
|
bottom: .25rem;
|
||||||
|
font-size: .8rem;
|
||||||
|
}
|
||||||
@@ -167,8 +167,8 @@
|
|||||||
followup:{issues:{count:0}, pr:{count:0}},
|
followup:{issues:{count:0}, pr:{count:0}},
|
||||||
habits:{indents:{style:`########`}},
|
habits:{indents:{style:`########`}},
|
||||||
languages:{favorites:new Array(7).fill(null).map((_, x) => ({x, name:"######", color:"#ebedf0", value:1/(x+1)}))},
|
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:"", icon:null})), {name:`And ## more...`, description:"", icon:null}]},
|
topics:{list:[...new Array("topics.limit" in q ? Math.max(Number(q["topics.limit"])||0, 0) : 12).fill(null).map(() => ({name:"######", description:"", icon:null})), {name:`And ## more...`, description:"", icon:null}]},
|
||||||
projects:{list:[...new Array(4).fill(null).map(() => ({name:"########", updated:"########", progress:{enabled:true, todo:"##", doing:"##", done:"##", total:"##"}}))]},
|
projects:{list:[...new Array("projects.limit" in q ? Math.max(Number(q["projects.limit"])||0, 0) : 4).fill(null).map(() => ({name:"########", updated:"########", progress:{enabled:true, todo:"##", doing:"##", done:"##", total:"##"}}))]},
|
||||||
}[key]??{})]
|
}[key]??{})]
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user