import { promisify } from "util"; import fs from 'fs'; import path from 'path'; import parseFrontMatter, { GrayMatterFile } from 'gray-matter'; import { fileURLToPath } from "url"; const readdir = promisify(fs.readdir); const readfile = promisify(fs.readFile); const stat = promisify(fs.stat); export type Content = GrayMatterFile & { filename: string; data: Data }; export async function getContent(dir = 'content'): Promise>> { const dirContents = await deepReaddir(dir); const contentFiles = dirContents.filter(filename => filename.substring(filename.length - '.md'.length) === '.md'); const rawContent = await Promise.all(contentFiles.map((postFile) => readfile(postFile, 'utf-8'))); const content = rawContent .map((content) => parseFrontMatter(content)) .map((contentData, index) => ({ ...contentData, // We use `substring` to cut off the dir name and the consecutive directory separator (`/`) filename: contentFiles[index].substring(dir.length + 1), })) as Array>; return content; } async function deepReaddir(dir: string): Promise { const dirContents = await readdir(dir); const paths = await Promise.all( dirContents .map(async path => { const filePath = `${dir}/${path}`; const stats = await stat(filePath); // Mocking a recursive function would require implementing quite a bit of logic in tests, // creating surface area for bugs there. Therefore, we just test the top level and ignore // recursion: /* istanbul ignore else */ if (stats.isFile()) { return [ filePath ]; } else { return deepReaddir(filePath); } }) ); const flattenedPaths = paths.reduce( (soFar, current) => soFar.concat(current), [], ); return flattenedPaths; }