svelte-markdown-pages
v0.3.1
Published
Build and render markdown-based content with distributed navigation for Svelte projects
Maintainers
Readme
Svelte Markdown Pages
A standalone npm package for building and rendering markdown-based content with distributed navigation structure for Svelte projects.
Project Structure
This is a monorepo with the following packages:
packages/svelte-markdown-pages- The main package that gets published to npmpackages/tests- Comprehensive test suite for the packagepackages/examples- Example SvelteKit project demonstrating usage
Features
- Distributed Navigation: Each folder defines its own structure with
.index.jsonfiles - Multiple Output Formats: App bundles, website navigation, and static HTML sites
- Type-Safe: Full TypeScript support with Zod validation
- Framework Agnostic: Svelte 5 components that work in any Svelte project
- Flexible: Point to any directory with markdown and
.index.jsonfiles - Comprehensive Testing: >90% test coverage with comprehensive test suite
Development
Prerequisites
- Node.js 18+
- npm
Setup
# Install dependencies for all packages
npm install
# Build the main package
npm run build
# Run tests
npm test
# Build examples
npm run build:examples
# Start examples in development mode
npm run dev:examplesPackage Scripts
npm run build- Build the main svelte-markdown-pages packagenpm run dev- Watch mode for the main packagenpm test- Run all testsnpm run test:watch- Run tests in watch modenpm run test:coverage- Run tests with coverage reportnpm run build:examples- Build the example SvelteKit projectnpm run dev:examples- Start the example project in development mode
Installation
npm install svelte-markdown-pagesQuick Start
1. Create Content Structure
Create a directory with your markdown content and .index.json files:
my-content/
├── .index.json
├── getting-started.md
└── guides/
├── .index.json
└── installation.md2. Define Navigation
Root level (my-content/.index.json):
{
"items": [
{ "name": "getting-started", "type": "page", "label": "Getting Started" },
{ "name": "guides", "type": "section", "label": "Guides" }
]
}Section level (my-content/guides/.index.json):
{
"items": [
{ "name": "installation", "type": "page", "label": "Installation" }
]
}3. Build Documentation
import { buildPages } from 'svelte-markdown-pages/builder';
await buildPages('./my-content', {
appOutput: './src/lib/content',
websiteOutput: './src/lib/content',
includeContent: true
});4. Use in Your App
import { NavigationTree, loadContent } from 'svelte-markdown-pages/renderer';
import navigationData from './src/lib/content/navigation.json';
import contentBundle from './src/lib/content/content.json';
const navigation = new NavigationTree(navigationData);
const content = await loadContent('getting-started.md', contentBundle);CLI Usage
Build for App/Website
npx svelte-markdown-pages build ./my-content --output ./src/lib/contentGenerate Static Site
npx svelte-markdown-pages static ./my-content --output ./distAPI Reference
Builder Module
buildPages(contentPath, options?)
Builds documentation from a content directory.
import { buildPages } from 'svelte-markdown-pages/builder';
const result = await buildPages('./content', {
appOutput: './src/lib/content',
websiteOutput: './src/lib/content',
includeContent: true
});generateStaticSite(contentPath, outputPath, options?)
Generates a complete static HTML site.
import { generateStaticSite } from 'svelte-markdown-pages/builder';
const result = await generateStaticSite('./content', './dist', {
title: 'My Documentation',
baseUrl: 'https://example.com',
includeIndex: true
});Renderer Module
NavigationTree
Manages navigation structure and provides navigation utilities.
import { NavigationTree } from 'svelte-markdown-pages/renderer';
const navigation = new NavigationTree(navigationData);
// Find items
const item = navigation.findItemByPath('guides/installation.md');
// Get breadcrumbs
const breadcrumbs = navigation.getBreadcrumbs('guides/installation.md');
// Get siblings
const siblings = navigation.getSiblings('guides/installation.md');
const nextSibling = navigation.getNextSibling('guides/installation.md');
const prevSibling = navigation.getPreviousSibling('guides/installation.md');ContentLoader
Manages content loading and processing.
import { ContentLoader } from 'svelte-markdown-pages/renderer';
const loader = new ContentLoader(contentBundle);
// Load content
const content = loader.loadAndProcess('getting-started.md');
// Check availability
const hasContent = loader.hasContent('guides/installation.md');
const paths = loader.getAvailablePaths();loadContent(path, contentBundle, processor?)
Loads and processes content for a specific path.
import { loadContent } from 'svelte-markdown-pages/renderer';
const content = await loadContent('getting-started.md', contentBundle);Content Processing
Custom Processors
You can provide custom content processors for advanced transformations:
const processor = {
process(content: string): string {
// Add table of contents
return addTableOfContents(content);
}
};
const content = await loadContent('page.md', contentBundle, processor);Utility Functions
import {
extractHeadings,
extractTableOfContents,
addTableOfContents
} from 'svelte-markdown-pages/renderer';
// Extract headings from markdown
const headings = extractHeadings(content);
// Generate table of contents
const toc = extractTableOfContents(content);
// Add table of contents to content
const contentWithToc = addTableOfContents(content);Content Structure
Index.json Format
Each directory can contain a .index.json file that defines the navigation structure:
{
"items": [
{ "name": "page-name", "type": "page", "label": "Page Label" },
{ "name": "section-name", "type": "section", "label": "Section Label" }
]
}Item Properties
name: File/directory name (without extension)type: Either"page"or"section"label: Display label for navigationcollapsed: Optional boolean to collapse sections by defaulturl: Optional external URL
File Structure
- Pages:
{name}.mdfiles - Sections:
{name}/directories with their own.index.json
Use Cases
Documentation Sites
npx svelte-markdown-pages build ./docs --output ./src/lib/docsBlog Systems
npx svelte-markdown-pages build ./blog --output ./src/lib/blogKnowledge Bases
npx svelte-markdown-pages build ./kb --output ./src/lib/kbStatic Sites
npx svelte-markdown-pages static ./content --output ./distIntegration Examples
SvelteKit Integration
<!-- src/routes/docs/[...slug]/+page.svelte -->
<script lang="ts">
import { NavigationTree } from 'svelte-markdown-pages/renderer';
import { DocsSidebar, DocsContent } from 'svelte-markdown-pages/components';
import navigationData from '$lib/content/navigation.json';
export let data;
let { content, slug } = data;
let navigation = $state(new NavigationTree(navigationData));
</script>
<div class="docs-layout">
<DocsSidebar {navigation} currentPage={slug} />
<DocsContent {content} />
</div>App Integration
<!-- src/lib/components/ContentPopover.svelte -->
<script lang="ts">
import { NavigationTree, loadContent } from 'svelte-markdown-pages/renderer';
import { DocsSidebar, DocsContent } from 'svelte-markdown-pages/components';
import navigationData from '$lib/content/navigation.json';
import contentBundle from '$lib/content/content.json';
let navigation = $state(new NavigationTree(navigationData));
let currentPage = $state<string | null>(null);
let pageContent = $state<string | null>(null);
$effect(() => {
if (currentPage) {
loadContent(currentPage, contentBundle).then(content => {
pageContent = content;
});
}
});
</script>
<div class="content-popover">
<DocsSidebar {navigation} bind:currentPage />
<DocsContent {pageContent} />
</div>Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
License
MIT License - see LICENSE file for details.
