All checks were successful
Deploy Docusaurus Site / deploy (push) Successful in 29s
78 lines
2.6 KiB
JavaScript
78 lines
2.6 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const ROOT = path.resolve(__dirname, '..');
|
|
|
|
function parseFrontmatter(content) {
|
|
const m = content.match(/^---\n([\s\S]*?)\n---/);
|
|
if (!m) return {};
|
|
const fm = {};
|
|
for (const line of m[1].split('\n')) {
|
|
const idx = line.indexOf(':');
|
|
if (idx === -1) continue;
|
|
const key = line.slice(0, idx).trim();
|
|
let val = line.slice(idx + 1).trim();
|
|
// Remove quotes
|
|
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'")))
|
|
val = val.slice(1, -1);
|
|
fm[key] = val;
|
|
}
|
|
return fm;
|
|
}
|
|
|
|
function guessTag(folderName) {
|
|
if (folderName.startsWith('dgx-spark')) return 'DGX Spark';
|
|
if (folderName.startsWith('gitea')) return 'Gitea';
|
|
if (folderName.startsWith('searxng')) return 'SearXNG';
|
|
if (folderName.startsWith('ollama')) return 'Ollama';
|
|
if (folderName.startsWith('browser')) return 'Browser';
|
|
if (folderName.startsWith('game')) return 'Game';
|
|
return 'Tech';
|
|
}
|
|
|
|
function getTag(fm, folderName, defaultTag) {
|
|
if (fm.tag) return fm.tag;
|
|
if (fm.tags) return fm.tags.replace(/[\[\]]/g, '').split(',')[0].trim();
|
|
if (defaultTag === 'blog') return 'AI';
|
|
return guessTag(folderName);
|
|
}
|
|
|
|
function scanDir(dir, urlPrefix, isBlog) {
|
|
if (!fs.existsSync(dir)) return [];
|
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
const posts = [];
|
|
for (const e of entries) {
|
|
if (!e.isDirectory()) continue;
|
|
const indexPath = path.join(dir, e.name, 'index.md');
|
|
if (!fs.existsSync(indexPath)) continue;
|
|
const content = fs.readFileSync(indexPath, 'utf8');
|
|
const fm = parseFrontmatter(content);
|
|
const title = fm.title || e.name;
|
|
const tag = getTag(fm, e.name, isBlog ? 'blog' : 'tech');
|
|
|
|
// Extract date
|
|
let date = null;
|
|
const dateMatch = e.name.match(/^(\d{4}-\d{2}-\d{2})/);
|
|
if (dateMatch) {
|
|
date = dateMatch[1];
|
|
} else if (fm.date) {
|
|
date = fm.date.slice(0, 10);
|
|
} else {
|
|
// Use file mtime
|
|
const stat = fs.statSync(indexPath);
|
|
date = stat.mtime.toISOString().slice(0, 10);
|
|
}
|
|
|
|
posts.push({ title, date, tag, url: `${urlPrefix}${e.name}` });
|
|
}
|
|
posts.sort((a, b) => b.date.localeCompare(a.date));
|
|
return posts.slice(0, 5);
|
|
}
|
|
|
|
const tech = scanDir(path.join(ROOT, 'docs-tech'), '/tech/', false);
|
|
const blog = scanDir(path.join(ROOT, 'docs'), '/blog/', true);
|
|
|
|
const outPath = path.join(ROOT, 'src', 'data', 'recent-posts.json');
|
|
fs.writeFileSync(outPath, JSON.stringify({ tech, blog }, null, 2));
|
|
console.log(`Generated ${outPath} (tech: ${tech.length}, blog: ${blog.length})`);
|