markpage
Version:
Build and manage markdown-based content with distributed navigation - framework agnostic content management system
163 lines (162 loc) • 5.25 kB
JavaScript
import { mkdirSync, writeFileSync, readFileSync } from "fs";
import { dirname, join } from "path";
import { validateContentStructure, buildNavigationTree } from "./parser.js";
class BuilderError extends Error {
constructor(message, filePath) {
super(message);
this.filePath = filePath;
this.name = "BuilderError";
}
}
async function buildPages(contentPath, options = {}) {
try {
validateContentStructure(contentPath, { autoDiscover: options.autoDiscover });
const navigation = buildNavigationTree(contentPath, { autoDiscover: options.autoDiscover });
let content;
if (options.includeContent !== false) {
content = bundleMarkdownContent(navigation, contentPath);
}
if (options.appOutput) {
await writeAppOutput(navigation, content, options.appOutput);
}
if (options.websiteOutput) {
await writeWebsiteOutput(navigation, options.websiteOutput);
}
return {
navigation,
content: content || void 0
};
} catch (error) {
if (error instanceof BuilderError) {
throw error;
}
throw new BuilderError(
`Build failed: ${error instanceof Error ? error.message : "Unknown error"}`,
contentPath
);
}
}
function bundleMarkdownContent(navigation, basePath) {
const content = {};
function processItems(items) {
for (const item of items) {
if (item.type === "page" && item.path) {
const filePath = join(basePath, item.path);
try {
const markdownContent = readFileSync(filePath, "utf-8");
content[item.path] = markdownContent;
} catch (error) {
throw new BuilderError(
`Failed to read markdown file: ${error instanceof Error ? error.message : "Unknown error"}`,
filePath
);
}
} else if (item.type === "section" && item.path) {
const filePath = join(basePath, item.path);
try {
const markdownContent = readFileSync(filePath, "utf-8");
content[item.path] = markdownContent;
} catch (error) {
throw new BuilderError(
`Failed to read section markdown file: ${error instanceof Error ? error.message : "Unknown error"}`,
filePath
);
}
}
if (item.items) {
processItems(item.items);
}
}
}
processItems(navigation);
return content;
}
async function writeAppOutput(navigation, content, outputPath) {
try {
mkdirSync(dirname(outputPath), { recursive: true });
const navigationPath = join(outputPath, "navigation.json");
writeFileSync(navigationPath, JSON.stringify(navigation, null, 2));
if (content) {
const contentPath = join(outputPath, "content.json");
writeFileSync(contentPath, JSON.stringify(content, null, 2));
}
} catch (error) {
throw new BuilderError(
`Failed to write app output: ${error instanceof Error ? error.message : "Unknown error"}`,
outputPath
);
}
}
async function writeWebsiteOutput(navigation, outputPath) {
try {
mkdirSync(dirname(outputPath), { recursive: true });
const navigationPath = join(outputPath, "navigation.json");
writeFileSync(navigationPath, JSON.stringify(navigation, null, 2));
} catch (error) {
throw new BuilderError(
`Failed to write website output: ${error instanceof Error ? error.message : "Unknown error"}`,
outputPath
);
}
}
function processMarkdown(content, processor) {
return processor ? processor.process(content) : content;
}
function generateStaticPages(navigation, basePath, options = {}) {
const pages = [];
function processItems(items) {
for (const item of items) {
if (item.type === "page" && item.path) {
const filePath = join(basePath, item.path);
try {
const markdownContent = readFileSync(filePath, "utf-8");
const processedMd = processMarkdown(markdownContent, options.processor);
const fullHtml = generateHTMLPage(processedMd, item.label, options.pageOptions);
pages.push({
path: item.path.replace(/\.md$/, ".html"),
content: markdownContent,
html: fullHtml
});
} catch (error) {
throw new BuilderError(
`Failed to process page ${item.path}: ${error instanceof Error ? error.message : "Unknown error"}`,
filePath
);
}
} else if (item.items) {
processItems(item.items);
}
}
}
processItems(navigation);
return pages;
}
function generateHTMLPage(content, title, options = {}) {
const pageTitle = options.title || title;
const baseUrl = options.baseUrl || "";
const css = options.css || "";
const js = options.js || "";
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${pageTitle}</title>
<base href="${baseUrl}">
${css ? `<style>${css}</style>` : ""}
</head>
<body>
<div class="content">
${content}
</div>
${js ? `<script>${js}<\/script>` : ""}
</body>
</html>`;
}
export {
BuilderError,
buildPages,
generateStaticPages,
processMarkdown
};
//# sourceMappingURL=builder.js.map