mdxlayer
Version:
Transform your MDX content into typed, JSON-powered data with flexible schema validation.
85 lines (82 loc) • 2.68 kB
JavaScript
import fs from 'node:fs';
import path from 'node:path';
import fg from 'fast-glob';
import matter from 'gray-matter';
import { cache } from '../cache/index.js';
import { getUserConfig } from '../config/index.js';
import { processMDX } from '../plugin/index.js';
import { transformFile } from '../utils/transform.js';
import { toIndexMjs } from './docs/index-js.js';
import { toPackageJson } from './docs/package.js';
import { toTypesDts } from './docs/types-d.js';
const builder = async () => {
const {
changed,
contentDir = "content",
docType = "Content",
resolvedFields,
frontmatterSchema,
options
} = await getUserConfig();
const cwd = process.cwd();
const dir = path.resolve(cwd, contentDir.replace(/^(\.\/|\/)+/, ""));
const files = await fg(["**/*.mdx"], { cwd: dir });
let processedCount = 0;
let errorCount = 0;
const processingPromises = files.map(async (file) => {
const fullPath = path.join(dir, file);
const isChanged = cache.mtime(fullPath);
if (!isChanged && !changed) {
return;
}
try {
const raw = fs.readFileSync(fullPath, "utf8");
const { data, content } = matter(raw);
const parsed = frontmatterSchema.safeValidate(data);
if (!parsed.success) {
throw new Error(
`Invalid ${docType} frontmatter in ${file}: ${!parsed.error}`
);
}
const code = await processMDX(options, content);
const filename = file.replace(/\.mdx$/, "");
const doc = {
_id: path.basename(filename),
...data,
_body: { code, raw: content },
_filePath: fullPath
};
if (resolvedFields) {
const promises = Object.entries(resolvedFields).map(
([, { resolve }]) => resolve(doc)
);
const results = await Promise.all(promises);
results.forEach((value, i) => {
const key = Object.keys(resolvedFields)[i];
doc[key] = value;
});
}
transformFile({
doc,
filename: `${filename}.json`,
subpath: `generated/${docType}`
});
processedCount += 1;
} catch (err) {
console.error(`❌ Error processing ${file}:`, err);
errorCount += 1;
}
});
await Promise.all(processingPromises);
toTypesDts({ docType, frontmatterSchema, resolvedFields });
toIndexMjs(files, docType);
toPackageJson();
if (errorCount > 0) {
console.error(`❌ MDXLayout completed with ${errorCount} errors`);
} else if (processedCount > 0) {
console.log(`✅ MDXLayout built: ${processedCount} items updated`);
} else {
console.log("✅ MDXLayout: No changes detected");
}
};
export { builder };