Unified markdown processor powered by plugins with parsing, transformation, and stringification capabilities
npx @tessl/cli install tessl/npm-remark@15.0.0Remark is a unified markdown processor powered by plugins that provides parsing, transformation, and stringification capabilities for markdown documents. It exports a single pre-configured unified processor that combines remark-parse and remark-stringify into a ready-to-use markdown processing pipeline.
npm install remarkimport { remark } from "remark";For CommonJS:
const { remark } = require("remark");import { remark } from "remark";
// Process markdown through complete pipeline
const file = await remark.process("# Hello World\n\nThis is **markdown**.");
console.log(String(file)); // "# Hello World\n\nThis is **markdown**.\n"
// Parse markdown to AST
const tree = remark.parse("# Hello World");
console.log(tree.type); // "root"
// Add plugins for extended functionality
const processor = remark
.use(remarkGfm) // Add GitHub Flavored Markdown support
.use(remarkToc, { heading: "Contents" }); // Add table of contents
const result = await processor.process(markdownContent);Remark is built on the unified ecosystem and provides:
The remark package exports a single pre-configured unified processor.
/**
* Pre-configured unified processor with remark-parse and remark-stringify
* This is a frozen processor instance, not a function
*/
const remark: Processor<Root, undefined, undefined, Root, string>;All processing methods are inherited from the unified processor interface:
Process markdown through the complete pipeline (parse → transform → stringify).
/**
* Process markdown input through complete pipeline
* @param file - Markdown string or VFile to process
* @returns Promise resolving to processed VFile
*/
remark.process(file: string | VFile): Promise<VFile>;
/**
* Synchronous version of process()
* @param file - Markdown string or VFile to process
* @returns Processed VFile
*/
remark.processSync(file: string | VFile): VFile;Parse markdown to MDAST abstract syntax tree.
/**
* Parse markdown to MDAST AST
* @param file - Markdown string or VFile to parse
* @returns MDAST Root node
*/
remark.parse(file: string | VFile): Root;Convert MDAST abstract syntax tree to markdown string.
/**
* Convert MDAST AST to markdown string
* @param tree - MDAST Root node to stringify
* @param file - Optional VFile for context
* @returns Markdown string
*/
remark.stringify(tree: Root, file?: VFile): string;Run transformation plugins on MDAST abstract syntax tree.
/**
* Run transformation plugins on AST
* @param tree - MDAST Root node to transform
* @param file - Optional VFile for context
* @returns Promise resolving to transformed Root node
*/
remark.run(tree: Root, file?: VFile): Promise<Root>;
/**
* Synchronous version of run()
* @param tree - MDAST Root node to transform
* @param file - Optional VFile for context
* @returns Transformed Root node
*/
remark.runSync(tree: Root, file?: VFile): Root;Add plugins or presets to extend processor capabilities.
/**
* Add plugin to processor
* @param plugin - Plugin function to add
* @param options - Optional plugin configuration
* @returns New processor instance with plugin added
*/
remark.use(plugin: Plugin, options?: any): Processor<Root, undefined, undefined, Root, string>;
/**
* Add preset to processor
* @param preset - Plugin preset to add
* @returns New processor instance with preset added
*/
remark.use(preset: Preset): Processor<Root, undefined, undefined, Root, string>;
/**
* Add list of plugins to processor
* @param list - Array of plugins/presets to add
* @returns New processor instance with plugins added
*/
remark.use(list: PluggableList): Processor<Root, undefined, undefined, Root, string>;Get or set processor configuration data and settings.
/**
* Get configuration value
* @param key - Configuration key to retrieve
* @returns Configuration value
*/
remark.data(key: string): any;
/**
* Set configuration value
* @param key - Configuration key to set
* @param value - Configuration value to set
* @returns Processor instance for chaining
*/
remark.data(key: string, value: any): Processor<Root, undefined, undefined, Root, string>;
/**
* Set multiple configuration values
* @param dataset - Object containing configuration key-value pairs
* @returns Processor instance for chaining
*/
remark.data(dataset: Record<string, any>): Processor<Root, undefined, undefined, Root, string>;Configure remark-parse and remark-stringify extensions via data.
/**
* Configure micromark extensions for parsing
* Used by remark-parse to extend markdown syntax
*/
remark.data("micromarkExtensions", extensions: MicromarkExtension[]): Processor;
/**
* Configure fromMarkdown extensions for parsing
* Used by remark-parse to handle extended syntax nodes
*/
remark.data("fromMarkdownExtensions", extensions: FromMarkdownExtension[]): Processor;
/**
* Configure toMarkdown extensions for stringification
* Used by remark-stringify to output extended syntax
*/
remark.data("toMarkdownExtensions", extensions: ToMarkdownExtension[]): Processor;
/**
* Configure stringify settings
* Used by remark-stringify for output formatting
*/
remark.data("settings", settings: StringifySettings): Processor;/**
* Create frozen processor instance (prevents further .use() calls)
* @returns Frozen processor instance
*/
remark.freeze(): Processor<Root, undefined, undefined, Root, string>;
/**
* Whether processor is frozen (always true for remark export)
*/
readonly remark.frozen: boolean;Remark works with types from its dependencies:
/**
* MDAST root node representing markdown document
* From @types/mdast package
*/
interface Root {
type: "root";
children: Array<RootContent>;
position?: Position;
}
/**
* Virtual file with path, content, and metadata
* From vfile package
*/
interface VFile {
readonly path?: string;
value: string;
readonly data: Record<string, unknown>;
readonly messages: Array<VFileMessage>;
readonly history: Array<string>;
readonly cwd: string;
}
/**
* Unified processor interface
* From unified package
*/
interface Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult> {
parse(file: string | VFile): ParseTree;
stringify(tree: CompileTree, file?: VFile): CompileResult;
run(tree: HeadTree, file?: VFile): Promise<TailTree>;
runSync(tree: HeadTree, file?: VFile): TailTree;
process(file: string | VFile): Promise<VFile>;
processSync(file: string | VFile): VFile;
use(plugin: Plugin, options?: any): Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>;
data(key: string): any;
data(key: string, value: any): Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>;
freeze(): Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>;
readonly frozen: boolean;
}
/**
* Plugin function type
* From unified package
*/
type Plugin = (this: Processor, options?: any) => void | Transformer;
/**
* Transformation function type
* From unified package
*/
type Transformer = (tree: Node, file?: VFile) => void | Node | Promise<void | Node>;
/**
* Plugin or plugin tuple type
* From unified package
*/
type Pluggable = Plugin | [Plugin, any] | Preset;
/**
* List of pluggables
* From unified package
*/
type PluggableList = Array<Pluggable>;
/**
* Plugin preset configuration
* From unified package
*/
interface Preset {
settings?: Record<string, any>;
plugins?: PluggableList;
}/**
* Micromark extension for parsing
* From micromark package
*/
interface MicromarkExtension {
document?: Record<string, any>;
contentInitial?: Record<string, any>;
flowInitial?: Record<string, any>;
flow?: Record<string, any>;
string?: Record<string, any>;
text?: Record<string, any>;
}
/**
* FromMarkdown extension for AST construction
* From mdast-util-from-markdown package
*/
interface FromMarkdownExtension {
canContainEols?: Array<string>;
enter?: Record<string, any>;
exit?: Record<string, any>;
}
/**
* ToMarkdown extension for stringification
* From mdast-util-to-markdown package
*/
interface ToMarkdownExtension {
extensions?: Array<any>;
}Configure markdown output formatting via the settings data key:
remark.data("settings", {
bullet: "*", // Bullet list marker ("-", "*", "+")
bulletOrdered: ".", // Ordered list marker (".", ")")
closeAtx: false, // Close ATX headings with #
emphasis: "*", // Emphasis marker ("*", "_")
fence: "`", // Code fence marker ("`", "~")
fences: true, // Use fences for code blocks
incrementListMarker: true, // Increment ordered list markers
listItemIndent: "one", // List indentation ("tab", "one", "mixed")
quote: '"', // Quote marker for titles ('"', "'")
rule: "*", // Horizontal rule marker ("-", "*", "_")
ruleRepetition: 3, // HR marker repetition count
ruleSpaces: false, // Spaces around HR markers
setext: false, // Use setext headings (underlined)
strong: "*", // Strong emphasis marker ("*", "_")
tightDefinitions: false // Tight definition formatting
});// Add micromark extensions for parsing
remark.data("micromarkExtensions", [gfmExtension]);
// Add fromMarkdown extensions for AST handling
remark.data("fromMarkdownExtensions", [gfmFromMarkdown]);
// Add toMarkdown extensions for stringification
remark.data("toMarkdownExtensions", [gfmToMarkdown]);import { remark } from "remark";
// Simple processing
const file = await remark.process("# Hello\n\nWorld!");
console.log(String(file)); // "# Hello\n\nWorld!\n"import { remark } from "remark";
import remarkGfm from "remark-gfm";
import remarkToc from "remark-toc";
const processor = remark
.use(remarkGfm)
.use(remarkToc, { heading: "contents", tight: true });
const result = await processor.process(markdownWithTables);import { remark } from "remark";
const processor = remark
.data("settings", {
bulletOrdered: ")",
incrementListMarker: false,
setext: true,
emphasis: "_"
});
const formatted = await processor.process(inputMarkdown);import { remark } from "remark";
import type { Root } from "mdast";
// Parse to AST
const tree = remark.parse("# Hello World") as Root;
// Modify AST
tree.children.push({
type: "paragraph",
children: [{ type: "text", value: "Added content" }]
});
// Convert back to markdown
const markdown = remark.stringify(tree);import { remark } from "remark";
import { gfm } from "micromark-extension-gfm";
import { gfmFromMarkdown, gfmToMarkdown } from "mdast-util-gfm";
const processor = remark
.data("micromarkExtensions", [gfm()])
.data("fromMarkdownExtensions", [gfmFromMarkdown()])
.data("toMarkdownExtensions", [gfmToMarkdown()]);
const result = await processor.process("| Column 1 | Column 2 |\n|----------|----------|\n| Cell 1 | Cell 2 |");