Markdown
LiteNode provides built-in methods for parsing Markdown files, extracting frontmatter, generating table of contents, and paginating content — making it a solid foundation for blogs, documentation sites, and content-driven apps.
parseMarkdownFile
Signature:
parseMarkdownFile(filePath: string): Promise<{
frontmatter: object
content: string
filePath: string
fileDir: string
fileName: string
fileBaseName: string
}>
Parses a single Markdown file. File paths are relative to your template directory.
app.get("/post/:slug", async (req, res) => {
const file = await app.parseMarkdownFile(`posts/${req.params.slug}.md`)
const { frontmatter, content } = file
const html = marked.parse(content)
res.render("layouts/post.html", { title: frontmatter.title, html_content: html })
})
parseMarkdownFileS
Signature:
parseMarkdownFileS(dirPath: string): Promise<Array<{
frontmatter: object
content: string
filePath: string
fileDir: string
fileName: string
fileBaseName: string
}>>
Parses all Markdown files in a directory. Useful for blog listings, doc indexes, and sitemaps.
app.get("/blog", async (req, res) => {
const posts = await app.parseMarkdownFileS("posts")
posts.sort((a, b) => new Date(b.frontmatter.date) - new Date(a.frontmatter.date))
res.render("layouts/blog.html", { posts })
})
extractMarkdownProperties
Signature:
extractMarkdownProperties(
files: ParsedFile[],
properties: string[]
): Promise<object[]>
Extracts specific frontmatter properties from an array of parsed files. Useful for building navigation menus or index pages.
const pages = await app.parseMarkdownFileS("pages")
const nav = await app.extractMarkdownProperties(pages, ["title", "href"])
// → [{ title: "Usage", href: "usage" }, { title: "Routing", href: "routing" }, ...]
groupByMarkdownProperty
Signature:
groupByMarkdownProperty(
dirPath: string,
properties: string[],
groupKey: string
): Promise<object>
Parses a directory and groups files by a frontmatter property.
app.get("/by-category", async (req, res) => {
const grouped = await app.groupByMarkdownProperty("posts", ["title", "href", "category"], "category")
res.json(grouped)
})
paginateMarkdownFiles
Signature:
paginateMarkdownFiles(
input: string | ParsedFile[],
page?: number,
perPage?: number
): Promise<{
page: number
per_page: number
prev_page: number | null
next_page: number | null
total_files: number
total_pages: number
data: object[]
}>
Paginates markdown files from a directory path or a pre-parsed array.
app.get("/blog", async (req, res) => {
const page = parseInt(req.queryParams.get("page")) || 1
const pagination = await app.paginateMarkdownFiles("posts", page, 10)
res.render("layouts/blog.html", {
posts: pagination.data,
currentPage: pagination.page,
totalPages: pagination.total_pages,
prevPage: pagination.prev_page,
nextPage: pagination.next_page,
})
})
generateTOC
Signature:
generateTOC(input: string): string
Generates a nested HTML <ul> table of contents from heading elements (h2–h6) in an HTML string. Headings must have id attributes — see Add IDs to Headings below.
const html = marked.parse(content)
const toc = app.generateTOC(html)
res.render("layouts/docs.html", { html_content: html, html_toc: toc })
Add IDs to Headings
generateTOC relies on heading id attributes. Many Markdown parsers (including Marked with extensions) generate them automatically. Alternatively, you can add them manually in your Markdown:
## My Section {#my-section}
The {#id} syntax is stripped from the rendered heading text and used as the element's id.
Custom Directory
All methods accept paths relative to the template directory. If you initialise LiteNode with a custom views directory, the same root applies:
const app = new LiteNode("public", "templates")
// Reads from templates/posts/...
const posts = await app.parseMarkdownFileS("posts")
See the Examples page for a complete blog and documentation setup.