UNPKG

aubade

Version:

filesystem-based content processor

59 lines (58 loc) 2.08 kB
import * as fs from 'fs/promises'; import { marker } from '../artisan/index.js'; import { parse } from '../core/index.js'; import { catenate } from './utils.js'; export async function traverse(entry, inspect = ({ path }) => { if (!path.endsWith('.md')) return; return async ({ buffer, parse }) => { const { body, frontmatter } = parse(buffer.toString('utf-8')); if (!frontmatter) return; const result = { ...frontmatter, content: marker.render(body).trim() }; return result; }; }) { const results = []; const pending = []; async function scan(current, { depth = 0 } = {}) { const tree = await fs.readdir(current, { withFileTypes: true }); const files = tree.flatMap((i) => { if (i.isDirectory()) return []; return { filename: i.name, get buffer() { return fs.readFile(catenate(current, i.name)); }, }; }); for (const item of tree) { const path = catenate(current, item.name); if (item.isDirectory()) { pending.push(scan(path, { depth: depth + 1 })); continue; } const hydrate = inspect({ breadcrumb: path.split(/[/\\]/).reverse(), depth, path, parent: current, }); if (hydrate) { const transformed = hydrate({ buffer: await fs.readFile(path), marker, parse: parse, siblings: files.filter(({ filename }) => filename !== item.name), task: (fn) => pending.push(fn({ fs })), }); results.push(transformed); } } } await scan(entry); // await for the initial scan to complete while (pending.length) await Promise.all(pending.splice(0)); return (await Promise.all(results)).filter((i) => !!i); }