|
// Some imports |
|
const fs = require('fs'); |
|
const matter = require('gray-matter'); |
|
const nodeHtmlToImage = require('node-html-to-image'); |
|
const path = require('path'); |
|
|
|
// Defining some constants, such as the content folder, image folder, etc. |
|
const articlesDir = path.join(process.cwd(), 'content/articles'); |
|
const imagesDir = path.join(process.cwd(), 'assets/imgs/social'); |
|
const articleExt = '.md'; |
|
const imageExt = '.png'; |
|
// Customize this part |
|
// I recommend setting the body size to 1200 x 628 px. |
|
const htmlTemplate: `<html><head> |
|
<style> |
|
body { |
|
position: relative; |
|
width: 1200px; |
|
height: 628px; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<h1>{{ title }}</h1> |
|
{{#if tags}} |
|
<ul id="tags"> |
|
{{#each tags}} |
|
<li class="tag">#{{this}}</li> |
|
{{/each}} |
|
</ul> |
|
{{/if}} |
|
</body></html>`; |
|
|
|
// Find all articles |
|
function walk(dir: string): string[] { |
|
const files: string[] = []; |
|
|
|
fs.readdirSync(dir).forEach((file: string) => { |
|
const filePath = path.join(dir, file); |
|
const stats = fs.statSync(filePath); |
|
|
|
if (stats.isDirectory()) { |
|
files.push(...walk(filePath)); |
|
} else if (stats.isFile()) { |
|
files.push(filePath); |
|
} |
|
}); |
|
|
|
return files; |
|
} |
|
|
|
// Retrieve the front matter from an article |
|
function getFrontMatter(filePath: string): Record<string, any> { |
|
return matter(fs.readFileSync(filePath)).data; |
|
} |
|
|
|
// Return the complete image path from an article path |
|
// E.g. 'content/articles/2020/hello-world.md' will return |
|
// 'assets/imgs/social/2020/hello-world.png'. |
|
function getImagePath( |
|
origDir: string, destDir: string, |
|
origExt: string, destExt: string, |
|
filePath: string, |
|
): string { |
|
return filePath |
|
.replace(origDir, destDir) |
|
.replace(origExt, destExt); |
|
} |
|
|
|
// Generate an image from metadata |
|
function genImage(imageData: Array<Record<string, any>>) { |
|
nodeHtmlToImage({ |
|
html: htmlTemplate, |
|
// In this case, this contains an array with information from all the |
|
// articles |
|
content: imageData, |
|
// This is needed to run the script in AWS Amplify Console |
|
puppeteerArgs: ['--no-sandbox'], |
|
}); |
|
} |
|
|
|
// Let's put everything together |
|
const files = walk(articlesDir); |
|
const fileData = files.map((filePath: string) => { |
|
const data = getFrontMatter(filePath); |
|
|
|
data.output = getImagePath(articlesDir, imagesDir, articleExt, imageExt, filePath); |
|
|
|
return data; |
|
}); |
|
genImage(fileData); |