UNPKG

svelte-markdown-pages

Version:

Build and render markdown-based content with distributed navigation for Svelte projects

287 lines (284 loc) 7.97 kB
import { marked } from 'marked'; // src/renderer/navigation.ts var NavigationTree = class { constructor(data) { this._flatItems = []; this._pathMap = /* @__PURE__ */ new Map(); this._items = data.items; this._buildIndexes(); } get items() { return this._items; } get flatItems() { return this._flatItems; } findItemByPath(path) { return this._pathMap.get(path); } findItemByName(name) { return this._findItemByNameRecursive(this._items, name); } getBreadcrumbs(path) { const item = this.findItemByPath(path); if (!item) { return []; } const breadcrumbs = []; let current = item; while (current) { breadcrumbs.unshift(current); current = current.parent; } return breadcrumbs; } getSiblings(path) { const item = this.findItemByPath(path); if (!item || !item.parent) { return this._items; } return item.parent.items || []; } getNextSibling(path) { const siblings = this.getSiblings(path); const currentIndex = siblings.findIndex((item) => item.path === path); if (currentIndex === -1 || currentIndex === siblings.length - 1) { return void 0; } return siblings[currentIndex + 1]; } getPreviousSibling(path) { const siblings = this.getSiblings(path); const currentIndex = siblings.findIndex((item) => item.path === path); if (currentIndex <= 0) { return void 0; } return siblings[currentIndex - 1]; } getChildren(path) { let item = this.findItemByName(path); if (!item) { item = this.findItemByPath(path); } if (!item && path.includes("/")) { const pathParts = path.split("/"); const sectionName = pathParts[pathParts.length - 1]; if (sectionName) { item = this.findItemByName(sectionName); } } return item?.items || []; } isExpanded(path) { const item = this.findItemByName(path) || this.findItemByPath(path); return item ? !item.collapsed : false; } toggleExpanded(path) { const item = this.findItemByName(path) || this.findItemByPath(path); if (item) { item.collapsed = !item.collapsed; } } _buildIndexes() { this._flatItems = []; this._pathMap.clear(); this._buildIndexesRecursive(this._items, void 0); } _buildIndexesRecursive(items, parent) { for (const item of items) { item.parent = parent || void 0; this._flatItems.push(item); if (item.path) { this._pathMap.set(item.path, item); } if (item.items) { this._buildIndexesRecursive(item.items, item); } } } _findItemByNameRecursive(items, name) { for (const item of items) { if (item.name === name) { return item; } if (item.items) { const found = this._findItemByNameRecursive(item.items, name); if (found) { return found; } } } return void 0; } }; function createNavigationTree(data) { return new NavigationTree(data); } var ContentLoader = class { constructor(content, processor) { this.content = content; this.processor = processor; } loadContent(path) { return this.content[path]; } loadAndProcess(path) { const content = this.loadContent(path); if (!content) { return void 0; } return this.processContent(content); } processContent(content) { if (this.processor) { content = this.processor.process(content); } return marked(content); } hasContent(path) { return path in this.content; } getAvailablePaths() { return Object.keys(this.content); } getContentSize(path) { const content = this.loadContent(path); return content ? content.length : 0; } getTotalContentSize() { return Object.values(this.content).reduce((total, content) => total + content.length, 0); } }; async function loadContent(path, contentBundle, processor) { const loader = new ContentLoader(contentBundle, processor); return loader.loadAndProcess(path); } function createContentLoader(contentBundle, processor) { return new ContentLoader(contentBundle, processor); } function extractHeadings(content) { const headings = []; const lines = content.split("\n"); for (const line of lines) { const match = line.match(/^(#{1,6})\s+(.+)$/); if (match && match[1] && match[2]) { const level = match[1].length; const text = match[2].trim(); const id = text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""); headings.push({ level, text, id }); } } return headings; } function extractTableOfContents(content) { const headings = extractHeadings(content); if (headings.length === 0) { return ""; } const toc = ["## Table of Contents", ""]; for (const heading of headings) { const indent = " ".repeat(heading.level - 1); toc.push(`${indent}- [${heading.text}](#${heading.id})`); } return toc.join("\n"); } function addTableOfContents(content) { const toc = extractTableOfContents(content); if (!toc) { return content; } const lines = content.split("\n"); const firstHeadingIndex = lines.findIndex((line) => line.match(/^#{1,6}\s+/)); if (firstHeadingIndex === -1) { return content; } lines.splice(firstHeadingIndex + 1, 0, toc, ""); return lines.join("\n"); } // src/renderer/components.ts var DocsSidebarClass = class { constructor(props) { this.props = props; } render() { return ` <nav class="docs-sidebar ${this.props.collapsed ? "collapsed" : ""}"> ${this.renderNavigationItems(this.props.navigation.items)} </nav> `; } renderNavigationItems(items) { return items.map((item) => { if (item.type === "section") { return ` <div class="nav-section"> <div class="nav-section-header">${item.label}</div> ${item.items ? this.renderNavigationItems(item.items) : ""} </div> `; } else { const isActive = this.props.currentPage === item.path; return ` <a href="#" class="nav-link ${isActive ? "active" : ""}" data-path="${item.path}" onclick="this.dispatchEvent(new CustomEvent('pageSelect', {detail: '${item.path}'}))"> ${item.label} </a> `; } }).join(""); } }; var DocsContentClass = class { constructor(props) { this.props = props; } render() { if (this.props.loading) { return '<div class="docs-content loading">Loading...</div>'; } if (this.props.error) { return `<div class="docs-content error">Error: ${this.props.error}</div>`; } if (!this.props.content) { return '<div class="docs-content empty">No content selected</div>'; } return ` <div class="docs-content"> ${this.props.title ? `<h1>${this.props.title}</h1>` : ""} <div class="content-body"> ${this.props.content} </div> </div> `; } }; function createDocsSidebar(props) { return new DocsSidebarClass(props); } function createDocsContent(props) { return new DocsContentClass(props); } function createDocsLayout(props) { const sidebar = new DocsSidebarClass({ navigation: props.navigation, currentPage: props.currentPage, onPageSelect: props.onPageSelect, collapsed: props.sidebarCollapsed }); const content = new DocsContentClass({ content: props.content, loading: false, error: null }); return ` <div class="docs-layout"> ${sidebar.render()} ${content.render()} </div> `; } export { ContentLoader, DocsContentClass as DocsContent, DocsSidebarClass as DocsSidebar, NavigationTree, addTableOfContents, createContentLoader, createDocsContent, createDocsLayout, createDocsSidebar, createNavigationTree, extractHeadings, extractTableOfContents, loadContent }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map