Flexible Markdown to HTML conversion library.
| Package | npm |
|---|---|
mark-deco |
|
mark-deco-cli |
(Japanese language is here/ζ₯ζ¬θͺγ―γγ‘γ)
Flexible Markdown to HTML conversion library written in TypeScript. It interprets GitHub Flavored Markdown (GFM) and outputs HTML. Supports frontmatter parsing, heading analysis, source code formatting, oEmbed/card/Mermaid diagram rendering (mermaid.js or beautiful-mermaid), and custom code block processing through plugin extensions.
- Can be used to render HTML from Markdown input.
- Simple interface makes it very easy to use.
- Highly independent with minimal runtime requirements. Works in both Node.js and browser environments.
- Built-in plugins support oEmbed, cards, Mermaid.js, and Beautiful Mermaid.
npm install mark-decoHere's the simplest usage example:
import { createMarkdownProcessor, createCachedFetcher } from 'mark-deco';
// Create a memory-cached fetcher
const fetcher = createCachedFetcher('MyApp/1.0');
// Create mark-deco processor
const processor = createMarkdownProcessor({
fetcher
});
// Markdown to convert
const markdown = `---
title: Sample Article
author: John Doe
---
# Hello World
This is a test article.`;
// Render HTML from Markdown input
const result = await processor.process(
markdown,
"id"); // ID prefix for HTML elements (described later)
// Generated HTML
console.log(result.html);
// Extracted frontmatter information (described later)
console.log(result.frontmatter);
// Extracted heading information (described later)
console.log(result.headingTree);This will render HTML like this:
<h1 id="id-1">Hello World</h1>
<p>This is a test article.</p>A "fetcher" is an abstraction for external server access. It's primarily used by oEmbed and card plugins for external API calls and page scraping. See details below. The argument passed to the fetcher is a user agent string, which is applied to HTTP request headers when accessing external servers.
HTML converted by the mark-deco processor is formatted in a readable manner. Advanced options allow fine-tuning of formatting conditions (described later).
While the mark-deco processor engine itself doesn't access external servers, plugins may access external servers as needed (e.g., when using oEmbed APIs or performing page scraping).
To enable operation cancellation in such cases, pass an ECMAScript standard AbortSignal instance to notify cancellation signals:
// Abort controller
const abortController = new AbortController();
// ...
// Convert Markdown to HTML
const result = await processor.process(
markdown, "id",
{ // Specify processor options
signal: abortController.signal, // Cancellation support
});For usage of AbortController and AbortSignal, refer to ECMAScript documentation.
By default, mark-deco copies the first base-level heading into frontmatter.title and removes that heading from the content. Adjust this with headerTitleTransform:
await processor.process(markdown, 'id', { headerTitleTransform: 'extract' });Use extract to keep the heading while copying the title, extractAndRemove (default) to remove it, or none to skip the behaviour entirely.
You can assign a default CSS class to the parent paragraph (<p>) of Markdown images with defaultImageOuterClassName.
// Add the .content-image and .shadow classes to the parent <p> tags
await processor.process(markdown, 'id', {
defaultImageOuterClassName: 'content-image shadow',
});You can add loading="lazy" to all generated <img> tags with applyLazyLoadingToImg (default: false).
Explicit loading attributes in Markdown are preserved.
await processor.process(markdown, 'id', {
applyLazyLoadingToImg: true,
});resolveUrl lets you rewrite URLs generated from Markdown before HTML output.
It is called for Markdown links, images, reference definitions, and raw HTML attributes such as href, src, srcset, poster, data, action, formaction, cite, and xlink:href.
The hook always runs, so return the original URL when no change is needed.
For raw HTML, context.tagName and context.attrName identify the source attribute.
// Prefix relative URLs
await processor.process(markdown, 'id', {
resolveUrl: (url, context) => {
if (/^(https?:)?\/\//.test(url) || url.startsWith('#')) {
return url;
}
return `/docs/${url}`;
},
});Although mark-deco is a library, a CLI interface is also available in the package that allows you to easily try out mark-deco. This allows you to try out conversions without having to write code in TypeScript, or call it as an independent application from another code.
# Take Markdown from standard input and output HTML
$ echo "# Hello World" | mark-decoFor more information, see CLI documentation.
mark-deco has many useful features. For further details, please see below.
- Frontmatter Information Extraction - Parse YAML frontmatter from Markdown files to extract metadata like title, author, tags, and publication date
- Heading ID Generation and Heading Information Extraction - Automatically generate unique IDs for headings with hierarchical or content-based naming strategies
- Fetcher and Cache System - External HTTP request management with configurable caching strategies for oEmbed APIs and page scraping
- Built-in Processing - oEmbed/card/Mermaid plugins and built-in code highlighting
- Creating Custom Plugins - Develop custom plugins to extend Markdown processing with code block interceptors and unified ecosystem integration
- CLI Application - Command-line interface for batch processing Markdown files with configuration support and plugin control
This library was born when we determined during the development of a-terra-forge that it would be better to separate the conversion engine into a standalone component.
The project includes a demonstration page that can be run with npm run dev.
Additionally, using a-terra-forge allows you to verify the implementation of a site generator utilizing mark-deco.
Under MIT.