markpage
Version:
Build and manage markdown-based content with distributed navigation - framework agnostic content management system
1 lines • 10.2 kB
Source Map (JSON)
{"version":3,"file":"builder.cjs","sources":["../../src/builder/builder.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { marked } from 'marked';\nimport { buildNavigationTree, validateContentStructure } from './parser.js';\nimport { BuildOptions, BuildResult, NavigationItem, ContentProcessor } from '../types.js';\n\nexport class BuilderError extends Error {\n constructor(message: string, public filePath?: string) {\n super(message);\n this.name = 'BuilderError';\n }\n}\n\nexport interface ContentBundle {\n [path: string]: string;\n}\n\nexport async function buildPages(\n contentPath: string,\n options: BuildOptions = {}\n): Promise<BuildResult> {\n try {\n // Validate content structure\n validateContentStructure(contentPath, { autoDiscover: options.autoDiscover });\n \n // Build navigation tree\n const navigation = buildNavigationTree(contentPath, { autoDiscover: options.autoDiscover });\n \n // Bundle markdown content if requested\n let content: ContentBundle | undefined;\n if (options.includeContent !== false) {\n content = bundleMarkdownContent(navigation, contentPath);\n }\n \n // Write outputs\n if (options.appOutput) {\n await writeAppOutput(navigation, content, options.appOutput);\n }\n \n if (options.websiteOutput) {\n await writeWebsiteOutput(navigation, options.websiteOutput);\n }\n \n return {\n navigation,\n content: content || undefined\n };\n } catch (error) {\n if (error instanceof BuilderError) {\n throw error;\n }\n \n throw new BuilderError(\n `Build failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n contentPath\n );\n }\n}\n\nfunction bundleMarkdownContent(\n navigation: NavigationItem[],\n basePath: string\n): ContentBundle {\n const content: ContentBundle = {};\n \n function processItems(items: NavigationItem[]): void {\n for (const item of items) {\n if (item.type === 'page' && item.path) {\n const filePath = join(basePath, item.path);\n try {\n const markdownContent = readFileSync(filePath, 'utf-8');\n content[item.path] = markdownContent;\n } catch (error) {\n throw new BuilderError(\n `Failed to read markdown file: ${error instanceof Error ? error.message : 'Unknown error'}`,\n filePath\n );\n }\n } else if (item.type === 'section' && item.path) {\n // Bundle content for sections that have a path (README/index.md files)\n const filePath = join(basePath, item.path);\n try {\n const markdownContent = readFileSync(filePath, 'utf-8');\n content[item.path] = markdownContent;\n } catch (error) {\n throw new BuilderError(\n `Failed to read section markdown file: ${error instanceof Error ? error.message : 'Unknown error'}`,\n filePath\n );\n }\n }\n \n if (item.items) {\n processItems(item.items);\n }\n }\n }\n \n processItems(navigation);\n return content;\n}\n\nasync function writeAppOutput(\n navigation: NavigationItem[],\n content: ContentBundle | undefined,\n outputPath: string\n): Promise<void> {\n try {\n mkdirSync(dirname(outputPath), { recursive: true });\n \n // Write navigation\n const navigationPath = join(outputPath, 'navigation.json');\n writeFileSync(navigationPath, JSON.stringify(navigation, null, 2));\n \n // Write content if available\n if (content) {\n const contentPath = join(outputPath, 'content.json');\n writeFileSync(contentPath, JSON.stringify(content, null, 2));\n }\n } catch (error) {\n throw new BuilderError(\n `Failed to write app output: ${error instanceof Error ? error.message : 'Unknown error'}`,\n outputPath\n );\n }\n}\n\nasync function writeWebsiteOutput(\n navigation: NavigationItem[],\n outputPath: string\n): Promise<void> {\n try {\n mkdirSync(dirname(outputPath), { recursive: true });\n \n const navigationPath = join(outputPath, 'navigation.json');\n writeFileSync(navigationPath, JSON.stringify(navigation, null, 2));\n } catch (error) {\n throw new BuilderError(\n `Failed to write website output: ${error instanceof Error ? error.message : 'Unknown error'}`,\n outputPath\n );\n }\n}\n\n// Deprecated: markdown rendering is handled at runtime by renderer packages\nexport function processMarkdown(content: string, processor?: ContentProcessor): string {\n return processor ? processor.process(content) : content;\n}\n\nexport function generateStaticPages(\n navigation: NavigationItem[],\n basePath: string,\n options: {\n processor?: ContentProcessor;\n pageOptions?: {\n title?: string;\n baseUrl?: string;\n css?: string;\n js?: string;\n };\n } = {}\n): Array<{\n path: string;\n content: string;\n html: string;\n}> {\n const pages: Array<{\n path: string;\n content: string;\n html: string;\n }> = [];\n \n function processItems(items: NavigationItem[]): void {\n for (const item of items) {\n if (item.type === 'page' && item.path) {\n const filePath = join(basePath, item.path);\n try {\n const markdownContent = readFileSync(filePath, 'utf-8');\n const processedMd = processMarkdown(markdownContent, options.processor);\n const fullHtml = generateHTMLPage(processedMd, item.label, options.pageOptions);\n \n pages.push({\n path: item.path.replace(/\\.md$/, '.html'),\n content: markdownContent,\n html: fullHtml\n });\n } catch (error) {\n throw new BuilderError(\n `Failed to process page ${item.path}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n filePath\n );\n }\n } else if (item.items) {\n processItems(item.items);\n }\n }\n }\n \n processItems(navigation);\n return pages;\n}\n\nfunction generateHTMLPage(\n content: string,\n title: string,\n options: {\n title?: string;\n baseUrl?: string;\n css?: string;\n js?: string;\n } = {}\n): string {\n const pageTitle = options.title || title;\n const baseUrl = options.baseUrl || '';\n const css = options.css || '';\n const js = options.js || '';\n \n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${pageTitle}</title>\n <base href=\"${baseUrl}\">\n ${css ? `<style>${css}</style>` : ''}\n</head>\n<body>\n <div class=\"content\">\n ${content}\n </div>\n ${js ? `<script>${js}</script>` : ''}\n</body>\n</html>`;\n}"],"names":["validateContentStructure","buildNavigationTree","join","readFileSync","mkdirSync","dirname","writeFileSync"],"mappings":"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"}