import{readFileSync,writeFileSync,mkdirSync,cpSync,readdirSync,existsSync,statSync}from'fs' import{join,extname}from'path' import matter from'gray-matter' import{marked}from'marked' const ARTICLES='articles',DIST='dist',TEMPLATES='templates',STATIC='static' const template=n=>readFileSync(join(TEMPLATES,n),'utf-8') const articleTmpl=template('article.html') const homeTmpl=template('home.html') mkdirSync(DIST,{recursive:true}) if(existsSync(STATIC)) cpSync(STATIC,DIST,{recursive:true}) const articles=[] for(const slug of readdirSync(ARTICLES)){ const dir=join(ARTICLES,slug) if(!statSync(dir).isDirectory()) continue const mdPath=join(dir,'index.md') if(!existsSync(mdPath)) continue const{data,content}=matter(readFileSync(mdPath,'utf-8')) const html=marked(content) const outDir=join(DIST,slug) mkdirSync(outDir,{recursive:true}) // copy co-located assets for(const f of readdirSync(dir)){ if(f==='index.md') continue cpSync(join(dir,f),join(outDir,f)) } const page=articleTmpl .replace('{{title}}',data.title||slug) .replace('{{date}}',data.date?new Date(data.date).toLocaleDateString('en-US',{month:'long',day:'numeric',year:'numeric'}):'') .replace('{{date_iso}}',data.date?new Date(data.date).toISOString().split('T')[0]:'') .replace('{{tags}}', (data.tags||[]).map(t=>`${t}`).join(' ')) .replace('{{excerpt}}',data.excerpt||'') .replace('{{slug}}',slug) .replace('{{body}}',html) writeFileSync(join(outDir,'index.html'),page) articles.push({slug,...data}) console.log(`ā ${slug}`) } articles.sort((a,b)=>new Date(b.date)-new Date(a.date)) const articleListHtml=articles.map(a=>` ${a.title} ${new Date(a.date).toLocaleDateString('en-US',{month:'short',day:'numeric'})} ${a.excerpt?`${a.excerpt}`:''} ${(a.tags||[]).map(t=>`${t}`).join('')} `).join('\n') const home=homeTmpl.replace('{{articles}}',articleListHtml) writeFileSync(join(DIST,'index.html'),home) console.log(`\nš index.html ā ${articles.length} article(s)`)
${a.excerpt}