feat: manually generate ogi to speed up builds

This commit is contained in:
Cory Dransfeldt 2024-05-02 14:49:04 -07:00
parent 25cc2f9d77
commit 7b7ce22aad
No known key found for this signature in database
303 changed files with 87 additions and 114 deletions

View file

@ -0,0 +1,74 @@
import { promises as fs } from 'fs'
import path from 'path'
import sharp from 'sharp'
import matter from 'gray-matter'
import slugify from 'slugify'
import { Liquid } from 'liquidjs'
import { DateTime } from 'luxon'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const baseDir = path.join(__dirname, '../../src/posts')
const outputDir = path.join(__dirname, '../../src/assets/img/ogi/')
const engine = new Liquid({ extname: '.liquid' })
engine.registerFilter('date', (isoDateString, formatString = 'MMMM d, yyyy') => {
const date = DateTime.fromISO(isoDateString)
return date.isValid ? date.toFormat(formatString) : isoDateString
})
engine.registerFilter('splitLines', (input, maxCharLength) => {
return input.split(' ').reduce((acc, cur) => {
if (!acc.length || acc[acc.length - 1].length + cur.length + 1 > maxCharLength) {
acc.push(cur)
} else {
acc[acc.length - 1] += ' ' + cur
}
return acc
}, [])
})
engine.registerFilter('slugify', (input) => slugify(input, { lower: true, strict: true, remove: /[*+~.()'"!:@]/g }))
const generateSVGAndConvertToPNG = async (filePath) => {
try {
const fileContent = await fs.readFile(filePath, 'utf8')
const { data } = matter(fileContent)
const svgTemplatePath = path.resolve(__dirname, 'index.liquid')
const templateContent = await fs.readFile(svgTemplatePath, 'utf8')
const svgContent = await engine.parseAndRender(templateContent, { preview: { data: data, date: data.date }})
const outputFile = path.join(outputDir, `${engine.filters.slugify(data.title)}-preview.png`)
await fs.mkdir(outputDir, { recursive: true })
await sharp(Buffer.from(svgContent)).png().toFile(outputFile)
console.log(`Generated png at ${outputFile}`)
} catch (error) {
console.error('Error processing file:', error)
}
}
const processYearDirectories = async (baseDir) => {
try {
const yearDirs = await fs.readdir(baseDir, { withFileTypes: true })
for (const dirent of yearDirs) {
if (dirent.isDirectory()) {
const yearPath = path.join(baseDir, dirent.name)
const markdownFiles = await fs.readdir(yearPath, { withFileTypes: true })
for (const file of markdownFiles) {
if (file.isFile() && file.name.endsWith('.md')) {
const filePath = path.join(yearPath, file.name)
await generateSVGAndConvertToPNG(filePath)
}
}
}
}
} catch (error) {
console.error('Failed to process directories:', error)
}
}
const generateOgImages = async () => await processYearDirectories(baseDir)
generateOgImages()

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="1200" height="630" viewBox="0 0 1200 630" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
{% assign titleInLines = preview.data.title | splitLines: 40 %}
{% assign numberOfLines = titleInLines.length %}
{% if numberOfLines == 1 %}
{% assign verticalStartingPoint = 340 %}
{% elsif numberOfLines == 2 %}
{% assign verticalStartingPoint = 290 %}
{% elsif numberOfLines == 3 %}
{% assign verticalStartingPoint = 250 %}
{% elsif numberOfLines == 4 %}
{% assign verticalStartingPoint = 210 %}
{% elsif numberOfLines == 5 %}
{% assign verticalStartingPoint = 170 %}
{% endif %}
<svg id="visual" viewBox="0 0 1200 630" width="1200" height="630" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><rect x="0" y="0" width="1200" height="630" fill="#000"></rect></svg>
<!-- date -->
<text
font-family="MonoLisa, Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, ui-monospace, monospace"
font-size="24"
font-weight="800"
fill="#fff"
>
<tspan x="80" y="{{ verticalStartingPoint | minus: 120 }}">
{{ preview.data.date | date: "MMMM d, yyyy" }}
</tspan>
</text>
<!-- title -->
<text
id="text"
font-family="MonoLisa, Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, ui-monospace, monospace"
font-size="40"
font-weight="800"
fill="#fff"
>
{% for line in titleInLines %}
{% capture spacing %}{{ forloop.index0 | times: 50 }}{% endcapture %}
<tspan x="80" y="{{ verticalStartingPoint | plus: spacing }}">
{{ line }}
</tspan>
{% endfor %}
</text>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB