Fix: Replace all template placeholders globally

This commit is contained in:
2026-02-24 19:05:19 -08:00
parent 17a8a82483
commit a308bf7ab1

View File

@@ -1,18 +1,28 @@
import { readFileSync, writeFileSync, mkdirSync, cpSync, readdirSync, existsSync, statSync } from 'fs' import { readFileSync, writeFileSync, mkdirSync, cpSync, readdirSync, existsSync, statSync } from 'fs'
import{join,extname}from'path' import { join } from 'path'
import matter from 'gray-matter' import matter from 'gray-matter'
import { marked } from 'marked' import { marked } from 'marked'
const ARTICLES='articles',DIST='dist',TEMPLATES='templates',STATIC='static' const ARTICLES = 'articles'
const DIST = 'dist'
const TEMPLATES = 'templates'
const STATIC = 'static'
const template = n => readFileSync(join(TEMPLATES, n), 'utf-8') const template = n => readFileSync(join(TEMPLATES, n), 'utf-8')
const articleTmpl = template('article.html') const articleTmpl = template('article.html')
const homeTmpl = template('home.html') const homeTmpl = template('home.html')
const render = (tpl, data) =>
tpl.replace(/{{\s*([a-zA-Z0-9_]+)\s*}}/g, (_, key) => `${data[key] ?? ''}`)
const fmtDateLong = d =>
d ? new Date(d).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }) : ''
const fmtDateIso = d => (d ? new Date(d).toISOString().split('T')[0] : '')
mkdirSync(DIST, { recursive: true }) mkdirSync(DIST, { recursive: true })
if(existsSync(STATIC)) if (existsSync(STATIC)) cpSync(STATIC, DIST, { recursive: true })
cpSync(STATIC,DIST,{recursive:true})
const articles = [] const articles = []
@@ -29,20 +39,25 @@ for(const slug of readdirSync(ARTICLES)){
const outDir = join(DIST, slug) const outDir = join(DIST, slug)
mkdirSync(outDir, { recursive: true }) mkdirSync(outDir, { recursive: true })
// copy co-located assets
for (const f of readdirSync(dir)) { for (const f of readdirSync(dir)) {
if (f === 'index.md') continue if (f === 'index.md') continue
cpSync(join(dir,f),join(outDir,f)) cpSync(join(dir, f), join(outDir, f), { recursive: true })
} }
const page=articleTmpl const page = render(articleTmpl, {
.replace('{{title}}',data.title||slug) title: data.title || slug,
.replace('{{date}}',data.date?new Date(data.date).toLocaleDateString('en-US',{month:'long',day:'numeric',year:'numeric'}):'') date: fmtDateLong(data.date),
.replace('{{date_iso}}',data.date?new Date(data.date).toISOString().split('T')[0]:'') date_iso: fmtDateIso(data.date),
.replace('{{tags}}', (data.tags||[]).map(t=>`<span class="inline-flex items-center rounded-full border border-gray-200 bg-gray-50 px-2 py-0.5 text-xs font-medium text-gray-600 mono">${t}</span>`).join(' ')) tags: (data.tags || [])
.replace('{{excerpt}}',data.excerpt||'') .map(
.replace('{{slug}}',slug) t =>
.replace('{{body}}',html) `<span class="inline-flex items-center rounded-full border border-gray-200 bg-gray-50 px-2 py-0.5 text-xs font-medium text-gray-600 mono">${t}</span>`
)
.join(' '),
excerpt: data.excerpt || '',
slug,
body: html
})
writeFileSync(join(outDir, 'index.html'), page) writeFileSync(join(outDir, 'index.html'), page)
articles.push({ slug, ...data }) articles.push({ slug, ...data })
@@ -51,7 +66,9 @@ for(const slug of readdirSync(ARTICLES)){
articles.sort((a, b) => new Date(b.date) - new Date(a.date)) articles.sort((a, b) => new Date(b.date) - new Date(a.date))
const articleListHtml=articles.map(a=>` const articleListHtml = articles
.map(
a => `
<a href="/${a.slug}/" class="block rounded-2xl border border-gray-200 bg-white shadow-sm hover:shadow-md transition-shadow overflow-hidden"> <a href="/${a.slug}/" class="block rounded-2xl border border-gray-200 bg-white shadow-sm hover:shadow-md transition-shadow overflow-hidden">
<div class="px-5 py-4"> <div class="px-5 py-4">
<div class="flex items-start justify-between gap-4"> <div class="flex items-start justify-between gap-4">
@@ -59,10 +76,17 @@ const articleListHtml=articles.map(a=>`
<time datetime="${new Date(a.date).toISOString().split('T')[0]}" class="mono text-xs text-gray-400 whitespace-nowrap mt-0.5">${new Date(a.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}</time> <time datetime="${new Date(a.date).toISOString().split('T')[0]}" class="mono text-xs text-gray-400 whitespace-nowrap mt-0.5">${new Date(a.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}</time>
</div> </div>
${a.excerpt ? `<p class="text-sm text-gray-500 mt-1.5">${a.excerpt}</p>` : ''} ${a.excerpt ? `<p class="text-sm text-gray-500 mt-1.5">${a.excerpt}</p>` : ''}
<div class="flex gap-1.5 mt-3">${(a.tags||[]).map(t=>`<span class="inline-flex items-center rounded-full border border-gray-200 bg-gray-50 px-2 py-0.5 text-xs font-medium text-gray-600 mono">${t}</span>`).join('')}</div> <div class="flex gap-1.5 mt-3">${(a.tags || [])
.map(
t =>
`<span class="inline-flex items-center rounded-full border border-gray-200 bg-gray-50 px-2 py-0.5 text-xs font-medium text-gray-600 mono">${t}</span>`
)
.join('')}</div>
</div> </div>
</a>`).join('\n') </a>`
)
.join('\n')
const home=homeTmpl.replace('{{articles}}',articleListHtml) const home = render(homeTmpl, { articles: articleListHtml })
writeFileSync(join(DIST, 'index.html'), home) writeFileSync(join(DIST, 'index.html'), home)
console.log(`\n🏠 index.html → ${articles.length} article(s)`) console.log(`\n🏠 index.html → ${articles.length} article(s)`)