Add support for fonts

This commit is contained in:
lowlighter
2020-10-25 00:19:57 +02:00
parent cdbb0e5b87
commit a4e15807ad
11 changed files with 116 additions and 48 deletions

View File

@@ -66,8 +66,8 @@
const template = req.query.template || conf.settings.templates.default const template = req.query.template || conf.settings.templates.default
if (!(template in Templates)) if (!(template in Templates))
return res.sendStatus(404) return res.sendStatus(404)
const {style, image} = conf.templates[template] const {style, image, fonts} = conf.templates[template]
res.status(200).json({style, image}) res.status(200).json({style, image, fonts})
}) })
app.get("/action.flush", limiter, async (req, res) => { app.get("/action.flush", limiter, async (req, res) => {
const {token, user} = req.query const {token, user} = req.query

View File

@@ -104,10 +104,10 @@
//Load template //Load template
const template = this.templates.selected const template = this.templates.selected
if (!this.templates.loaded[template]) { if (!this.templates.loaded[template]) {
const {data:{image, style}} = await axios.get(`/placeholder.svg?template=${template}`) const {data:{image, style, fonts}} = await axios.get(`/placeholder.svg?template=${template}`)
this.templates.loaded[template] = {image, style} this.templates.loaded[template] = {image, style, fonts}
} }
const {image = "", style = {}} = this.templates.loaded[this.templates.selected] || {} const {image = "", style = "", fonts = ""} = this.templates.loaded[this.templates.selected] || {}
if (!image) if (!image)
return this.templates.placeholder = "#" return this.templates.placeholder = "#"
//Proxifier //Proxifier
@@ -115,7 +115,7 @@
get(target, property) { get(target, property) {
//Primitive conversion //Primitive conversion
if (property === Symbol.toPrimitive) if (property === Symbol.toPrimitive)
return () => "" return () => "##"
//Iterables //Iterables
if (property === Symbol.iterator) if (property === Symbol.iterator)
return Reflect.get(target, property) return Reflect.get(target, property)
@@ -132,27 +132,29 @@
//Placeholder data //Placeholder data
const data = { const data = {
style, style,
fonts,
s(_, letter) { return letter === "y" ? "ies" : "s" }, s(_, letter) { return letter === "y" ? "ies" : "s" },
base:this.plugins.enabled.base, base:this.plugins.enabled.base,
meta:{version:"0.0.0", author:"lowlighter", placeholder:true}, meta:{version:"0.0.0", author:"lowlighter", placeholder:true},
user:proxify({name:`▇▇▇▇`, websiteUrl:`▇▇▇▇▇▇▇▇▇▇▇▇`}), user:proxify({name:`############`, websiteUrl:`########################`}),
computed:proxify({ computed:proxify({
avatar:"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOcOnfpfwAGfgLYttYINwAAAABJRU5ErkJggg==", avatar:"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOcOnfpfwAGfgLYttYINwAAAABJRU5ErkJggg==",
registration:" years ago", registration:"## years ago",
calendar:new Array(14).fill({color:"#ebedf0"}), calendar:new Array(14).fill({color:"#ebedf0"}),
licenses:{favorite:`▇▇▇▇`}, licenses:{favorite:`########`},
plugins:Object.fromEntries(Object.entries(this.plugins.enabled).filter(([key, enabled]) => (key !== "base")&&(enabled)).map(([key]) => { plugins:Object.fromEntries(Object.entries(this.plugins.enabled).filter(([key, enabled]) => (key !== "base")&&(enabled)).map(([key]) => {
return [key, proxify({ return [key, proxify({
pagespeed:{scores:["Performance", "Accessibility", "Best Practices", "SEO"].map(title => ({title, score:NaN}))}, pagespeed:{scores:["Performance", "Accessibility", "Best Practices", "SEO"].map(title => ({title, score:NaN}))},
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)}))},
}[key]||{})] }[key]||{})]
})), })),
token:{scopes:[]}, token:{scopes:[]},
}), }),
} }
//Render placeholder //Render placeholder
console.log(new Set([...ejs.render(image, data)]))
this.templates.placeholder = this.serialize(ejs.render(image, data)) this.templates.placeholder = this.serialize(ejs.render(image, data))
this.generated.content = "" this.generated.content = ""
}, },

View File

@@ -19,7 +19,7 @@
const s = (value, end = "") => value > 1 ? {y:"ies", "":"s"}[end] : end const s = (value, end = "") => value > 1 ? {y:"ies", "":"s"}[end] : end
if ((!(template in Templates))||(!(template in conf.templates))||((conf.settings.templates.enabled.length)&&(!conf.settings.templates.enabled.includes(template)))) if ((!(template in Templates))||(!(template in conf.templates))||((conf.settings.templates.enabled.length)&&(!conf.settings.templates.enabled.includes(template))))
throw new Error("unsupported template") throw new Error("unsupported template")
const {query, image, style} = conf.templates[template] const {query, image, style, fonts} = conf.templates[template]
//Query data from GitHub API //Query data from GitHub API
console.debug(`metrics/compute/${login} > query`) console.debug(`metrics/compute/${login} > query`)
@@ -45,7 +45,7 @@
//Eval rendering //Eval rendering
console.debug(`metrics/compute/${login} > render`) console.debug(`metrics/compute/${login} > render`)
let rendered = await ejs.render(image, {...data, s, style}, {async:true}) let rendered = await ejs.render(image, {...data, s, style, fonts}, {async:true})
console.debug(`metrics/compute/${login} > render > success`) console.debug(`metrics/compute/${login} > render > success`)
//Optimize rendering //Optimize rendering

View File

@@ -54,18 +54,19 @@
`${templates}/${name}/query.graphql`, `${templates}/${name}/query.graphql`,
`${templates}/${name}/image.svg`, `${templates}/${name}/image.svg`,
`${templates}/${name}/style.css`, `${templates}/${name}/style.css`,
`${templates}/${name}/fonts.css`,
] ]
const [query, image, style] = await Promise.all(files.map(async file => `${await fs.promises.readFile(path.resolve(file))}`)) const [query, image, style, fonts] = await Promise.all(files.map(async file => `${await fs.promises.readFile(path.resolve(file))}`))
conf.templates[name] = {query, image, style} conf.templates[name] = {query, image, style, fonts}
logger(`metrics/setup > load template [${name}] > success`) logger(`metrics/setup > load template [${name}] > success`)
//Debug //Debug
if (conf.settings.debug) { if (conf.settings.debug) {
Object.defineProperty(conf.templates, name, { Object.defineProperty(conf.templates, name, {
get() { get() {
logger(`metrics/setup > reload template [${name}]`) logger(`metrics/setup > reload template [${name}]`)
const [query, image, style] = files.map(file => `${fs.readFileSync(path.resolve(file))}`) const [query, image, style, fonts] = files.map(file => `${fs.readFileSync(path.resolve(file))}`)
logger(`metrics/setup > reload template [${name}] > success`) logger(`metrics/setup > reload template [${name}] > success`)
return {query, image, style} return {query, image, style, fonts}
} }
}) })
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,14 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="480" height="<%= 0 <svg xmlns="http://www.w3.org/2000/svg" width="480" height="<%= 0
+ (!!base.header)*86 + (!!base.header)*80
+ (!!base.metadata)*42 + (!!base.metadata)*38
+ ((!!base.activity)||(!!base.community))*150 + ((!!base.activity)||(!!base.community))*128
+ (!!base.repositories)*100 + (!!base.repositories)*92
+ ((!!computed.plugins.traffic)||(!!computed.plugins.lines))*18 + ((!!base.repositories)*((!!computed.plugins.traffic)||(!!computed.plugins.lines)))*16
+ (!!computed.plugins.followup)*72 + (!!computed.plugins.followup)*68
+ (!!computed.plugins.pagespeed)*128 + (!!computed.plugins.pagespeed)*126
+ (!!computed.plugins.habits)*72 + (!!computed.plugins.habits)*68
+ (!!computed.plugins.languages)*96 + (!!computed.plugins.languages)*96
%>"> %>">
<defs><style><%= fonts %></style></defs>
<style> <style>
<%= style %> <%= style %>
</style> </style>

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -1,6 +1,6 @@
/* SVG global context */ /* SVG global context */
svg { svg {
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji; font-family: 'Roboto';
font-size: 14px; font-size: 14px;
color: #777777; color: #777777;
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,23 +1,23 @@
<svg xmlns="http://www.w3.org/2000/svg" width="480" height="<%= 48 <svg xmlns="http://www.w3.org/2000/svg" width="480" height="<%= 48
+ (!!base.header)*64 + (!!base.header)*62
+ (!!base.metadata)*122 + (!!base.metadata)*108
+ (!!base.activity)*146 + (!!base.activity)*108
+ (!!base.community)*120 + (!!base.community)*94
+ (!!base.repositories)*188 + (!!base.repositories)*142
+ (Object.entries(base).filter(([key, value]) => value).length)*8 + ((!!base.repositories)*(!!computed.plugins.traffic))*18
+ (!!computed.plugins.traffic)*18 + ((!!base.repositories)*(!!computed.plugins.followup))*102
+ (!!computed.plugins.followup)*112 + ((!!base.repositories)*(!!computed.plugins.lines))*34
+ (!!computed.plugins.lines)*36 + (!!computed.plugins.pagespeed)*110
+ ((!!computed.plugins.traffic)+(!!computed.plugins.followup)+(!!computed.plugins.lines))*4 + (!!computed.plugins.languages)*124
+ (!!computed.plugins.pagespeed)*132 + Math.max(0, (((!!base.metadata)+(!!base.header)+((!!base.activity)||(!!base.community))+(!!base.repositories)+(!!computed.plugins.pagespeed)+(!!computed.plugins.languages))-1))*20
+ (!!computed.plugins.languages)*172
+ (Object.entries(computed.plugins).filter(([key, value]) => value).length)*4
%>"> %>">
<% <%
meta.$ = `<span class="ps1-path">${user.login}@metrics</span>:<span class="ps1-location">~</span>${computed.token.scopes.includes("repo") ? "#" : "$"}` meta.$ = `<span class="ps1-path">${user.login}@metrics</span>:<span class="ps1-location">~</span>${computed.token.scopes.includes("repo") ? "#" : "$"}`
meta.animations = !meta.placeholder ? {stdin:.16, stdout:.28, length:(2+Object.keys(base).length+Object.keys(computed.plugins).length)} : {stdin:0, stdout:0, length:0} meta.animations = !meta.placeholder ? {stdin:.16, stdout:.28, length:(2+Object.keys(base).length+Object.keys(computed.plugins).length)} : {stdin:0, stdout:0, length:0}
%> %>
<defs><style><%= fonts %></style></defs>
<style> <style>
<%= style %> <%= style %>
.stdin, .stdout { .stdin, .stdout {
@@ -57,8 +57,7 @@
<% if (base.metadata) { %> <% if (base.metadata) { %>
<div class="banner"><%# -%> <div class="banner"><%# -%>
GitHub metrics generator <%= meta.version %> GitHub metrics generator <%= meta.version %>
These generated metrics comes with ABSOLUTELY NO WARRANTY, These generated metrics comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law.
to the extent permitted by applicable law.
Last generated: <%= new Date().toGMTString() %> Last generated: <%= new Date().toGMTString() %>
</div><% } -%> </div><% } -%>
@@ -66,8 +65,9 @@ Last generated: <%= new Date().toGMTString() %>
<% if (base.header) { %> <% if (base.header) { %>
<div class="stdin"><%- meta.$ %> whoami</div><%# -%> <div class="stdin"><%- meta.$ %> whoami</div><%# -%>
<div class="stdout"><%# -%> <div class="stdout"><%# -%>
<b><%= user.name || user.login %></b> registered=<%= computed.registration.match(/^.+? [ym]/)[0].replace(/ /g, "") %>, uid=<%= `${user.databaseId}`.substr(-4) %>, gid=<%= user.organizations.totalCount %>, followers=<%= user.followers.totalCount %> <b><%= user.name || user.login %></b> registered=<%= computed.registration.match(/^.+? [ym]/)[0].replace(/ /g, "") %>, uid=<%= `${user.databaseId}`.substr(-4) %>, gid=<%= user.organizations.totalCount %>
contributed to <%= user.repositoriesContributedTo.totalCount %> repositor<%= s(user.repositoriesContributedTo.totalCount, "y") %> <b><% for (const [x, {color}] of Object.entries(computed.calendar)) { -%><span style="color:<%= color %>">#</span><% } %></b> contributed to <%= user.repositoriesContributedTo.totalCount %> repositor<%= s(user.repositoriesContributedTo.totalCount, "y") %> <b><% for (const [x, {color}] of Object.entries(computed.calendar)) { -%><span style="color:<%= color %>">#</span><% } %></b>
followed by <b><%= user.followers.totalCount %></b> user<%= s(user.followers.totalCount) %>
</div><% } -%> </div><% } -%>
<%# ============================================================= -%> <%# ============================================================= -%>
<% if ((base.activity)||(base.community)) { %> <% if ((base.activity)||(base.community)) { %>
@@ -152,7 +152,7 @@ dr-x LICENSE
<%# ============================================================= -%> <%# ============================================================= -%>
<% if (base.metadata) { -%> <% if (base.metadata) { -%>
<footer>Connection reset by 127.0.0.1</footer><%# -%> <footer>Connection reset by <%= Math.floor(256*Math.random()) %>.<%= Math.floor(256*Math.random()) %>.<%= Math.floor(256*Math.random()) %>.<%= Math.floor(256*Math.random()) %></footer><%# -%>
<% } -%></pre> <% } -%></pre>
</div> </div>

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -1,6 +1,6 @@
/* SVG global context */ /* SVG global context */
svg { svg {
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji; font-family: 'Courier Prime';
font-size: 14px; font-size: 14px;
color: #777777; color: #777777;
} }
@@ -49,7 +49,7 @@
/* Terminal */ /* Terminal */
pre, .banner, .footer { pre, .banner, .footer {
margin: 0; margin: 0;
font-family: monospace; font-family: 'Courier Prime';
color: #DDDDDD; color: #DDDDDD;
white-space: break-spaces; white-space: break-spaces;
} }
@@ -61,7 +61,6 @@
} }
.banner, footer { .banner, footer {
opacity: .7; opacity: .7;
font-family: monospace;
} }
/* Prompt */ /* Prompt */

View File

@@ -28,9 +28,10 @@
`${templates}/${name}/query.graphql`, `${templates}/${name}/query.graphql`,
`${templates}/${name}/image.svg`, `${templates}/${name}/image.svg`,
`${templates}/${name}/style.css`, `${templates}/${name}/style.css`,
`${templates}/${name}/fonts.css`,
] ]
const [query, image, style] = await Promise.all(files.map(async file => `${await fs.promises.readFile(path.resolve(file))}`)) const [query, image, style, fonts] = await Promise.all(files.map(async file => `${await fs.promises.readFile(path.resolve(file))}`))
assets[name] = {query, image, style} assets[name] = {query, image, style, fonts}
} }
code = code.replace(/<#assets>/g, Buffer.from(JSON.stringify(assets)).toString("base64")) code = code.replace(/<#assets>/g, Buffer.from(JSON.stringify(assets)).toString("base64"))