Utilities Reference
Helper functions and utilities for EmberDocs development.
Content Parsing
parseMarkdown()
Parse markdown file content with YAML frontmatter.
function parseMarkdown(
input: string,
options?: ParseOptions
): ContentData
interface ParseOptions {
generateToc?: boolean; // Default: true
strictFrontmatter?: boolean; // Default: false
}
interface ContentData {
frontmatter: Record<string, any>;
body: string;
toc: TocEntry[];
}Example:
import { parseMarkdown } from '@/lib/content';
const markdown = `---
title: "My Doc"
slug: "my-doc"
---
# Hello
This is content.`;
const parsed = parseMarkdown(markdown);
console.log(parsed.frontmatter.title); // "My Doc"
console.log(parsed.body); // "# Hello\n\nThis is content."
console.log(parsed.toc); // Array of headings
// Parse without TOC generation
const parsedNoToc = parseMarkdown(markdown, { generateToc: false });generateSlug()
Generate URL-safe slug from text (used internally for heading IDs).
function generateSlug(text: string): stringExample:
import { generateSlug } from '@/lib/content';
generateSlug('Getting Started'); // "getting-started"
generateSlug('API & Reference'); // "api-and-reference"
generateSlug('Hello World!'); // "hello-world"Behavior:
- Converts to lowercase
- Replaces
&withand - Removes special characters
- Replaces spaces with hyphens
- Trims leading/trailing hyphens
Search Functions
buildSearchIndex()
Generate full-text search index from document directory.
async function buildSearchIndex(docsPath: string): Promise<SearchIndex>Example:
import { buildSearchIndex, saveIndexToFile } from '@/lib/search';
const index = await buildSearchIndex('./docs');
await saveIndexToFile('./public/search-index.json', index);Returns:
interface SearchIndex {
documents: Record<string, SearchDocument>;
index?: any; // FlexSearch index (built client-side)
metadata: {
buildTime: number;
documentCount: number;
indexedWords: number;
};
}querySearchIndex()
Search pre-built index with natural language query. Note: This is a server-side fallback. Client-side search uses FlexSearch directly.
function querySearchIndex(
index: SearchIndex,
documents: Record<string, SearchDocument>,
query: string,
limit?: number
): SearchResult[]Example:
import { querySearchIndex, buildSearchIndex } from '@/lib/search';
// Build index
const searchIndex = await buildSearchIndex('./docs');
// Search
const results = querySearchIndex(searchIndex, searchIndex.documents, "authentication", 10);
results.forEach(result => {
console.log(result.title); // Document title
console.log(result.excerpt); // Preview text
console.log(result.path); // URL path
console.log(result.score); // Relevance score
});serializeIndex()
Serialize search index to JSON string.
function serializeIndex(index: SearchIndex): stringdeserializeIndex()
Convert JSON serialized index back to SearchIndex format.
function deserializeIndex(serialized: string): SearchIndexExample:
import { serializeIndex, deserializeIndex, buildSearchIndex } from '@/lib/search';
// Build and serialize
const index = await buildSearchIndex('./docs');
const json = serializeIndex(index);
// Later, deserialize
const restored = deserializeIndex(json);saveIndexToFile()
Write search index to JSON file.
async function saveIndexToFile(
filePath: string,
index: SearchIndex
): Promise<void>Navigation Functions
discoverDocuments()
Discover all markdown documents from a directory structure.
function discoverDocuments(
rootPath: string,
currentPath?: string,
parentId?: string | null
): NavigationNode[]Example:
import { discoverDocuments, buildNavigationTree } from '@/lib/navigation';
// Discover all documents
const nodes = discoverDocuments('./docs/examples');
// Build hierarchical tree
const { roots, nodeMap } = buildNavigationTree(nodes);
// Access nested document
const deepDoc = nodeMap['deep/nesting/many/levels/deep-doc'];
console.log(deepDoc.title); // Document title from frontmatterbuildNavigationTree()
Build hierarchical tree structure from flat node list.
function buildNavigationTree(nodes: NavigationNode[]): NavigationStructureReturns:
interface NavigationStructure {
roots: NavigationNode[];
nodeMap: Record<string, NavigationNode>;
versions: Version[];
currentVersion?: string;
}getBreadcrumbs()
Generate breadcrumb trail for current path.
function getBreadcrumbs(
structure: NavigationStructure,
pathname: string
): BreadcrumbItem[]Example:
import { discoverDocuments, buildNavigationTree, getBreadcrumbs } from '@/lib/navigation';
const nodes = discoverDocuments('./docs');
const nav = buildNavigationTree(nodes);
const breadcrumbs = getBreadcrumbs(nav, '/docs/guides/advanced-features');
// Returns:
// [
// { href: '/docs', label: 'Docs' },
// { href: '/docs/guides', label: 'Guides' },
// { href: '/docs/guides/advanced-features', label: 'Advanced Features' }
// ]findNodeByPath()
Find navigation node by pathname.
function findNodeByPath(
structure: NavigationStructure,
pathname: string
): NavigationNode | undefineddetectVersions()
Detect Git tag versions for documentation versioning.
function detectVersions(baseDir?: string): Version[]Returns:
interface Version {
tag: string;
label: string;
isCurrent: boolean;
}Example:
import { detectVersions } from '@/lib/navigation';
const versions = detectVersions();
// Returns array of Git tag versions
// Example: [{ tag: 'v1.0.0', label: 'v1.0.0', isCurrent: true }]
// Falls back to [{ tag: 'main', label: 'Latest', isCurrent: true }] if no tagsgenerateNavigation()
Complete navigation generation (discovers documents, builds tree, detects versions).
function generateNavigation(
docsPath?: string,
baseDir?: string
): NavigationStructureExample:
import { generateNavigation } from '@/lib/navigation';
const nav = generateNavigation('./docs/examples');
console.log(nav.roots); // Root navigation nodes
console.log(nav.nodeMap); // All nodes by ID
console.log(nav.versions); // Git tag versionsflattenNavigation()
Convert navigation tree to flat list of all documents.
function flattenNavigation(nodes: NavigationNode[]): NavDocument[]Returns:
interface NavDocument {
title: string;
path: string;
}Example:
import { flattenNavigation } from '@/lib/nav-helpers';
const flat = flattenNavigation(nav.roots);
flat.forEach(doc => {
console.log(`${doc.title} -> ${doc.path}`);
});Type Definitions
Document Types
interface DocumentMetadata {
title: string;
slug: string;
author?: string;
date?: string;
tags?: string[];
published?: boolean;
order?: number;
}
interface ContentData {
frontmatter: Record<string, any>;
body: string;
toc: TocEntry[];
}Search Types
interface SearchDocument {
id: string;
title: string;
path: string;
body: string;
excerpt?: string;
tags?: string[];
headings?: string[];
}
interface SearchResult {
id: string;
title: string;
path: string;
excerpt: string;
score: number;
tags?: string[];
}
interface SearchIndex {
documents: Record<string, SearchDocument>;
index?: any; // FlexSearch index (built client-side)
metadata: {
buildTime: number;
documentCount: number;
indexedWords?: number;
};
}Navigation Types
interface NavigationNode {
id: string;
title: string;
path: string;
type?: 'folder' | 'doc';
parentId?: string | null;
children?: NavigationNode[];
frontmatter?: DocumentMetadata;
}
interface NavigationStructure {
roots: NavigationNode[];
nodeMap: Record<string, NavigationNode>;
versions: Version[];
currentVersion?: string;
}
interface Version {
tag: string;
label: string;
isCurrent: boolean;
}
interface BreadcrumbItem {
href: string;
label: string;
}getPrevNextDocs()
Get previous and next documents in navigation order.
function getPrevNextDocs(
currentPath: string,
navNodes: NavigationNode[]
): { prev?: NavDocument; next?: NavDocument }Example:
import { getPrevNextDocs } from '@/lib/nav-helpers';
const { prev, next } = getPrevNextDocs('/docs/guides/advanced', nav.roots);
if (prev) console.log('Previous:', prev.title);
if (next) console.log('Next:', next.title);Markdown Utilities
highlightCode()
Syntax highlight code block using Shiki.
async function highlightCode(code: string, language: string): Promise<string>Example:
import { highlightCode } from '@/lib/highlight';
const html = await highlightCode('const x = 5;', 'typescript');
// Returns HTML with syntax highlightingNote: This is used internally by the CodeBlock component. For most use cases, you'll use the CodeBlock component directly.
extractExcerpt()
Extract excerpt from text with query highlighting.
function extractExcerpt(
text: string,
query?: string,
contextWords?: number
): stringExample:
import { extractExcerpt } from '@/lib/search';
const excerpt = extractExcerpt(longText, 'authentication', 2);
// Returns excerpt with query highlightedflattenToc()
Flatten nested TOC structure to flat array.
function flattenToc(toc: TocEntry[]): TocEntry[]Example:
import { parseMarkdown, flattenToc } from '@/lib/content';
const parsed = parseMarkdown(markdown);
const flatToc = flattenToc(parsed.toc);
// Returns all headings in flat array (no nesting)Next Steps
- See Components for UI component API
- Review Configuration for setup options
- Check Advanced Features for integration patterns