
Security News
Crates.io Users Targeted by Phishing Emails
The Rust Security Response WG is warning of phishing emails from rustfoundation.dev targeting crates.io users.
Build and render markdown-based content with distributed navigation for any framework
A standalone npm package for building and rendering markdown-based content with distributed navigation structure for any framework.
This is a monorepo with the following packages:
packages/markpage
- The main package that gets published to npmpackages/tests
- Comprehensive test suite for the packagepackages/examples
- Example SvelteKit project demonstrating usage.index.json
files.index.json
files# 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:examples
npm run build
- Build the main markpage 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 modenpm install markpage
Create a directory with your markdown content and .index.json
files:
my-content/
├── .index.json
├── getting-started.md
└── guides/
├── .index.json
└── installation.md
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" }
]
}
import { buildPages } from 'markpage/builder';
await buildPages('./my-content', {
appOutput: './src/lib/content',
websiteOutput: './src/lib/content',
includeContent: true
});
import { NavigationTree, loadContent } from 'markpage/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);
npx markpage build ./my-content --output ./src/lib/content
npx markpage static ./my-content --output ./dist
buildPages(contentPath, options?)
Builds documentation from a content directory.
import { buildPages } from 'markpage/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 'markpage/builder';
const result = await generateStaticSite('./content', './dist', {
title: 'My Documentation',
baseUrl: 'https://example.com',
includeIndex: true
});
NavigationTree
Manages navigation structure and provides navigation utilities.
import { NavigationTree } from 'markpage/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 'markpage/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 'markpage/renderer';
const content = await loadContent('getting-started.md', contentBundle);
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);
import {
extractHeadings,
extractTableOfContents,
addTableOfContents
} from 'markpage/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);
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" }
]
}
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{name}.md
files{name}/
directories with their own .index.json
npx markpage build ./docs --output ./src/lib/docs
npx markpage build ./blog --output ./src/lib/blog
npx markpage build ./kb --output ./src/lib/kb
npx markpage static ./content --output ./dist
<!-- src/routes/docs/[...slug]/+page.svelte -->
<script lang="ts">
import { NavigationTree } from 'markpage/renderer';
import { DocsSidebar, DocsContent } from 'markpage/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>
<!-- src/lib/components/ContentPopover.svelte -->
<script lang="ts">
import { NavigationTree, loadContent } from 'markpage/renderer';
import { DocsSidebar, DocsContent } from 'markpage/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>
MIT License - see LICENSE file for details.
FAQs
Build and manage markdown-based content with distributed navigation - framework agnostic content management system
The npm package markpage receives a total of 355 weekly downloads. As such, markpage popularity was classified as not popular.
We found that markpage demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The Rust Security Response WG is warning of phishing emails from rustfoundation.dev targeting crates.io users.
Product
Socket now lets you customize pull request alert headers, helping security teams share clear guidance right in PRs to speed reviews and reduce back-and-forth.
Product
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.