Update utils.mjs
This commit is contained in:
@@ -56,8 +56,8 @@
|
|||||||
console.debug(`metrics/compute/${login} > render`)
|
console.debug(`metrics/compute/${login} > render`)
|
||||||
let rendered = await ejs.render(image, {...data, s:imports.s, f:imports.format, style, fonts}, {views, async:true})
|
let rendered = await ejs.render(image, {...data, s:imports.s, f:imports.format, style, fonts}, {views, async:true})
|
||||||
if (q["config.twemoji"])
|
if (q["config.twemoji"])
|
||||||
rendered = await imports.svgemojis(rendered)
|
rendered = await imports.svg.twemojis(rendered)
|
||||||
const {resized, mime} = await imports.svgresize(rendered, {paddings:q["config.padding"] || conf.settings.padding, convert})
|
const {resized, mime} = await imports.svg.resize(rendered, {paddings:q["config.padding"] || conf.settings.padding, convert})
|
||||||
rendered = resized
|
rendered = resized
|
||||||
|
|
||||||
//Additional SVG transformations
|
//Additional SVG transformations
|
||||||
|
|||||||
@@ -86,16 +86,6 @@
|
|||||||
.replace(/'/g, u["'"] ? "'" : "'")
|
.replace(/'/g, u["'"] ? "'" : "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Expand url */
|
|
||||||
export async function urlexpand(url) {
|
|
||||||
try {
|
|
||||||
return (await axios.get(url)).request.res.responseUrl
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Run command */
|
/**Run command */
|
||||||
export async function run(command, options, {prefixed = true} = {}) {
|
export async function run(command, options, {prefixed = true} = {}) {
|
||||||
const prefix = {win32:"wsl"}[process.platform] ?? ""
|
const prefix = {win32:"wsl"}[process.platform] ?? ""
|
||||||
@@ -128,63 +118,65 @@
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Render svg */
|
/**SVG utils */
|
||||||
export async function svgresize(svg, {paddings, convert}) {
|
export const svg = {
|
||||||
//Instantiate browser if needed
|
/**Render and resize svg */
|
||||||
if (!svgresize.browser) {
|
async resize(rendered, {paddings, convert}) {
|
||||||
svgresize.browser = await puppeteer.launch({headless:true, executablePath:process.env.PUPPETEER_BROWSER_PATH, args:["--no-sandbox", "--disable-extensions", "--disable-setuid-sandbox", "--disable-dev-shm-usage"]})
|
//Instantiate browser if needed
|
||||||
console.debug(`metrics/svgresize > started ${await svgresize.browser.version()}`)
|
if (!svg.resize.browser) {
|
||||||
}
|
svg.resize.browser = await puppeteer.launch({headless:true, executablePath:process.env.PUPPETEER_BROWSER_PATH, args:["--no-sandbox", "--disable-extensions", "--disable-setuid-sandbox", "--disable-dev-shm-usage"]})
|
||||||
//Format padding
|
console.debug(`metrics/svg/resize > started ${await svg.resize.browser.version()}`)
|
||||||
const [pw = 1, ph] = (Array.isArray(paddings) ? paddings : `${paddings}`.split(",").map(x => x.trim())).map(padding => `${padding}`.substring(0, padding.length-1)).map(value => 1+Number(value)/100)
|
}
|
||||||
const padding = {width:pw, height:ph ?? pw}
|
//Format padding
|
||||||
console.debug(`metrics/svgresize > padding width*${padding.width}, height*${padding.height}`)
|
const [pw = 1, ph] = (Array.isArray(paddings) ? paddings : `${paddings}`.split(",").map(x => x.trim())).map(padding => `${padding}`.substring(0, padding.length-1)).map(value => 1+Number(value)/100)
|
||||||
//Render through browser and resize height
|
const padding = {width:pw, height:ph ?? pw}
|
||||||
const page = await svgresize.browser.newPage()
|
console.debug(`metrics/svg/resize > padding width*${padding.width}, height*${padding.height}`)
|
||||||
await page.setContent(svg, {waitUntil:["load", "domcontentloaded", "networkidle2"]})
|
//Render through browser and resize height
|
||||||
await page.addStyleTag({content:"body { margin: 0; padding: 0; }"})
|
const page = await svg.resize.browser.newPage()
|
||||||
await wait(1)
|
await page.setContent(rendered, {waitUntil:["load", "domcontentloaded", "networkidle2"]})
|
||||||
let mime = "image/svg+xml"
|
await page.addStyleTag({content:"body { margin: 0; padding: 0; }"})
|
||||||
let {resized, width, height} = await page.evaluate(async padding => {
|
await wait(1)
|
||||||
//Disable animations
|
let mime = "image/svg+xml"
|
||||||
const animated = !document.querySelector("svg").classList.contains("no-animations")
|
let {resized, width, height} = await page.evaluate(async padding => {
|
||||||
if (animated)
|
//Disable animations
|
||||||
document.querySelector("svg").classList.add("no-animations")
|
const animated = !document.querySelector("svg").classList.contains("no-animations")
|
||||||
//Get bounds and resize
|
if (animated)
|
||||||
let {y:height, width} = document.querySelector("svg #metrics-end").getBoundingClientRect()
|
document.querySelector("svg").classList.add("no-animations")
|
||||||
height = Math.ceil(height*padding.height)
|
//Get bounds and resize
|
||||||
width = Math.ceil(width*padding.width)
|
let {y:height, width} = document.querySelector("svg #metrics-end").getBoundingClientRect()
|
||||||
//Resize svg
|
height = Math.ceil(height*padding.height)
|
||||||
document.querySelector("svg").setAttribute("height", height)
|
width = Math.ceil(width*padding.width)
|
||||||
//Enable animations
|
//Resize svg
|
||||||
if (animated)
|
document.querySelector("svg").setAttribute("height", height)
|
||||||
document.querySelector("svg").classList.remove("no-animations")
|
//Enable animations
|
||||||
|
if (animated)
|
||||||
|
document.querySelector("svg").classList.remove("no-animations")
|
||||||
|
//Result
|
||||||
|
return {resized:new XMLSerializer().serializeToString(document.querySelector("svg")), height, width}
|
||||||
|
}, padding)
|
||||||
|
//Convert if required
|
||||||
|
if (convert) {
|
||||||
|
console.debug(`metrics/svg/resize > convert to ${convert}`)
|
||||||
|
resized = await page.screenshot({type:convert, clip:{x:0, y:0, width, height}, omitBackground:true})
|
||||||
|
mime = `image/${convert}`
|
||||||
|
}
|
||||||
//Result
|
//Result
|
||||||
return {resized:new XMLSerializer().serializeToString(document.querySelector("svg")), height, width}
|
await page.close()
|
||||||
}, padding)
|
return {resized, mime}
|
||||||
//Convert if required
|
},
|
||||||
if (convert) {
|
/**Render twemojis */
|
||||||
console.debug(`metrics/svgresize > convert to ${convert}`)
|
async twemojis(rendered) {
|
||||||
resized = await page.screenshot({type:convert, clip:{x:0, y:0, width, height}, omitBackground:true})
|
//Load emojis
|
||||||
mime = `image/${convert}`
|
const emojis = new Map()
|
||||||
}
|
for (const {text:emoji, url} of twemojis.parse(rendered)) {
|
||||||
//Result
|
if (!emojis.has(emoji))
|
||||||
await page.close()
|
emojis.set(emoji, (await axios.get(url)).data.replace(/^<svg /, '<svg class="twemoji" '))
|
||||||
return {resized, mime}
|
}
|
||||||
}
|
//Apply replacements
|
||||||
|
for (const [emoji, twemoji] of emojis)
|
||||||
/**Render twemojis */
|
rendered = rendered.replace(new RegExp(emoji, "g"), twemoji)
|
||||||
export async function svgemojis(svg) {
|
return rendered
|
||||||
//Load emojis
|
},
|
||||||
const emojis = new Map()
|
|
||||||
for (const {text:emoji, url} of twemojis.parse(svg)) {
|
|
||||||
if (!emojis.has(emoji))
|
|
||||||
emojis.set(emoji, (await axios.get(url)).data.replace(/^<svg /, '<svg class="twemoji" '))
|
|
||||||
}
|
|
||||||
//Apply replacements
|
|
||||||
for (const [emoji, twemoji] of emojis)
|
|
||||||
svg = svg.replace(new RegExp(emoji, "g"), twemoji)
|
|
||||||
return svg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Wait */
|
/**Wait */
|
||||||
@@ -193,17 +185,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**Create gif from puppeteer browser */
|
/**Create gif from puppeteer browser */
|
||||||
export async function puppeteergif({page, width, height, frames, scale = 1, quality = 80, x = 0, y = 0, delay = 150}) {
|
export async function record({page, width, height, frames, scale = 1, quality = 80, x = 0, y = 0, delay = 150}) {
|
||||||
//Register images frames
|
//Register images frames
|
||||||
const images = []
|
const images = []
|
||||||
for (let i = 0; i < frames; i++) {
|
for (let i = 0; i < frames; i++) {
|
||||||
images.push(await page.screenshot({type:"png", clip:{width, height, x, y}}))
|
images.push(await page.screenshot({type:"png", clip:{width, height, x, y}}))
|
||||||
await wait(delay/1000)
|
await wait(delay/1000)
|
||||||
if (i%10 === 0)
|
if (i%10 === 0)
|
||||||
console.debug(`metrics/puppeteergif > processed ${i}/${frames} frames`)
|
console.debug(`metrics/record > processed ${i}/${frames} frames`)
|
||||||
}
|
}
|
||||||
console.debug(`metrics/puppeteergif > processed ${frames}/${frames} frames`)
|
console.debug(`metrics/record > processed ${frames}/${frames} frames`)
|
||||||
//Post-processing
|
//Post-processing
|
||||||
console.debug("metrics/puppeteergif > applying post-processing")
|
console.debug("metrics/record > applying post-processing")
|
||||||
return Promise.all(images.map(async buffer => (await jimp.read(buffer)).scale(scale).quality(quality).getBase64Async("image/png")))
|
return Promise.all(images.map(async buffer => (await jimp.read(buffer)).scale(scale).quality(quality).getBase64Async("image/png")))
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
//Generate gif
|
//Generate gif
|
||||||
console.debug(`metrics/compute/${login}/plugins > skyline > generating frames`)
|
console.debug(`metrics/compute/${login}/plugins > skyline > generating frames`)
|
||||||
const framed = await imports.puppeteergif({page, width, height, frames, scale:quality})
|
const framed = await imports.record({page, width, height, frames, scale:quality})
|
||||||
|
|
||||||
//Close puppeteer
|
//Close puppeteer
|
||||||
await browser.close()
|
await browser.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user