125 lines
2.7 KiB
JavaScript
125 lines
2.7 KiB
JavaScript
|
import html2png from '@besties/html2png'
|
||
|
import express from 'express'
|
||
|
import fs from 'node:fs'
|
||
|
|
||
|
const app = express();
|
||
|
|
||
|
const figtreeRegular = fs.readFileSync('./assets/Figtree-Regular.woff')
|
||
|
const figtreeMedium = fs.readFileSync('./assets/Figtree-Medium.woff')
|
||
|
const figtreeExtraBold = fs.readFileSync('./assets/Figtree-ExtraBold.woff')
|
||
|
const ATTR_REGEX = /["&]/g
|
||
|
const CONTENT_REGEX = /[&<]/g
|
||
|
|
||
|
|
||
|
|
||
|
function escape(value, is_attr = false) {
|
||
|
const str = String(value)
|
||
|
const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX
|
||
|
pattern.lastIndex = 0
|
||
|
let escaped = ''
|
||
|
let last = 0
|
||
|
while (pattern.test(str)) {
|
||
|
const i = pattern.lastIndex - 1
|
||
|
const ch = str[i]
|
||
|
escaped +=
|
||
|
// eslint-disable-next-line unicorn/prefer-string-slice
|
||
|
str.substring(last, i) +
|
||
|
(ch === '&' ? '&' : ch === '"' ? '"' : '<')
|
||
|
last = i + 1
|
||
|
}
|
||
|
return escaped + str.slice(Math.max(0, last))
|
||
|
}
|
||
|
|
||
|
app.get('/', function(req, res) {
|
||
|
res.redirect("https://git.gay/gitgay/og.git");
|
||
|
});
|
||
|
|
||
|
app.get('/:owner/:repo', async function(req, res) {
|
||
|
let repo = await (await fetch(`https://git.gay/api/v1/repos/${req.params.owner}/${req.params.repo}`)).json();
|
||
|
let infoHtml = `
|
||
|
<p style="font-size: 36px; color: #9A8FA7;">${escape(`@${repo.owner.login}`)}</p>
|
||
|
<p style="font-weight: 800; font-size: 4.5rem; line-height: 1.2em;">${escape(repo.name)}</p>
|
||
|
`;
|
||
|
|
||
|
if (repo.description) infoHtml = `${infoHtml}<p style="font-size: 42px; font-weight: 500; color: #9A8FA7;">${escape(repo.description)}</p>`;
|
||
|
|
||
|
let img = await html2png(
|
||
|
`<div class="main">
|
||
|
<div class="contents">
|
||
|
<div class="info">
|
||
|
${infoHtml}
|
||
|
</div>
|
||
|
<div class="graphics">
|
||
|
<img width="120" height="120" src="${escape(
|
||
|
repo.avatar_url || repo.owner.avatar_url,
|
||
|
true
|
||
|
)}"></img>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>`,
|
||
|
`p {
|
||
|
margin: 0;
|
||
|
}
|
||
|
|
||
|
.main {
|
||
|
color: #ffffff;
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
align-items: center;
|
||
|
background-color: #1B171F;
|
||
|
width: 1200px;
|
||
|
height: 600px;
|
||
|
}
|
||
|
|
||
|
.contents {
|
||
|
display: flex;
|
||
|
}
|
||
|
|
||
|
.info {
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
justify-content: center;
|
||
|
width: 800px;
|
||
|
gap: 10px;
|
||
|
}
|
||
|
|
||
|
.graphics {
|
||
|
display: flex;
|
||
|
justify-content: flex-end;
|
||
|
align-items: flex-start;
|
||
|
width: 240px;
|
||
|
}
|
||
|
|
||
|
.graphics > img {
|
||
|
border-radius: 100%;
|
||
|
width: 120px;
|
||
|
height: 120px;
|
||
|
}`,
|
||
|
{
|
||
|
fonts: [
|
||
|
{
|
||
|
name: 'Figtree',
|
||
|
data: figtreeRegular,
|
||
|
weight: 400,
|
||
|
style: 'normal'
|
||
|
},
|
||
|
{
|
||
|
name: 'Figtree',
|
||
|
data: figtreeMedium,
|
||
|
weight: 500,
|
||
|
style: 'normal'
|
||
|
},
|
||
|
{
|
||
|
name: 'Figtree',
|
||
|
data: figtreeExtraBold,
|
||
|
weight: 800,
|
||
|
style: 'normal'
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
);
|
||
|
|
||
|
res.send(img);
|
||
|
})
|
||
|
|
||
|
app.listen(8085);
|