remark plugin to compile Markdown to HTML
npx @tessl/cli install tessl/npm-remark-html@16.0.0remark-html is a unified (remark) plugin that compiles Markdown to HTML. It provides a shortcut for converting markdown documents into sanitized HTML output, serving as an alternative to using the full remark-rehype-rehype-stringify pipeline.
npm install remark-htmlimport remarkHtml from 'remark-html';For CommonJS:
const remarkHtml = require('remark-html');With TypeScript types:
import remarkHtml from 'remark-html';
import type { Options } from 'remark-html';For advanced type usage:
import type { Schema } from 'hast-util-sanitize';
import type { Handlers } from 'mdast-util-to-hast';
import type { Root } from 'mdast';import remarkHtml from 'remark-html';
import remarkParse from 'remark-parse';
import { unified } from 'unified';
// Basic usage with default sanitization
const file = await unified()
.use(remarkParse)
.use(remarkHtml)
.process('# Hello\n\n**World**');
console.log(String(file));
// Output: <h1>Hello</h1>\n<p><strong>World</strong></p>\nremark-html works within the unified ecosystem by:
Compiles markdown to HTML with built-in sanitization.
/**
* Add support for serializing to HTML.
*
* @param options - Configuration options (optional)
* @returns Nothing (modifies processor)
*/
declare const remarkHtml: Plugin<
[(Readonly<Options> | null | undefined)?],
Root,
string
>;
interface Options {
/** How to turn mdast nodes into hast nodes */
handlers?: Readonly<Handlers> | null | undefined;
/** Sanitize the output, and how (default: true) */
sanitize?: Readonly<Schema> | boolean | null | undefined;
/** Control dangerous HTML elements */
allowDangerousHtml?: boolean | null | undefined;
/** Close self-closing elements */
closeSelfClosing?: boolean | null | undefined;
/** Omit optional closing tags */
omitOptionalTags?: boolean | null | undefined;
/** Character reference options */
characterReferences?: {
useShortestReferences?: boolean;
omitOptionalSemicolons?: boolean;
} | null | undefined;
/** Additional options from hast-util-to-html */
[key: string]: any;
}Usage Examples:
// Default usage with sanitization
const processor = unified()
.use(remarkParse)
.use(remarkHtml);
// Disable sanitization (DANGEROUS - allows XSS)
const unsafeProcessor = unified()
.use(remarkParse)
.use(remarkHtml, { sanitize: false });
// Custom sanitization schema
const customProcessor = unified()
.use(remarkParse)
.use(remarkHtml, {
sanitize: { tagNames: ['p', 'strong', 'em', 'a'] }
});
// Custom handlers for mdast to hast conversion
const handlerProcessor = unified()
.use(remarkParse)
.use(remarkHtml, {
handlers: {
paragraph(state, node) {
// Custom paragraph handling
return {
type: 'element',
tagName: 'div',
properties: { className: ['custom-paragraph'] },
children: state.all(node)
};
}
}
});Controls HTML sanitization to prevent XSS attacks.
/** Sanitization options */
sanitize?: Readonly<Schema> | boolean | null | undefined;true (default): Uses safe default schema from hast-util-sanitizefalse: DANGEROUS - Disables sanitization, allows arbitrary HTMLSchema: Custom sanitization schema objectExamples:
// Safe default (recommended)
.use(remarkHtml, { sanitize: true })
// Disable sanitization (dangerous)
.use(remarkHtml, { sanitize: false })
// Custom schema allowing only specific tags
.use(remarkHtml, {
sanitize: {
tagNames: ['p', 'strong', 'em', 'a', 'ul', 'ol', 'li'],
attributes: {
a: ['href'],
'*': ['className']
}
}
})Customize how specific markdown nodes are converted to HTML.
/** Custom node handlers */
handlers?: Readonly<Handlers> | null | undefined;Example:
.use(remarkHtml, {
handlers: {
// Custom link handler
link(state, node) {
return {
type: 'element',
tagName: 'a',
properties: {
href: node.url,
target: '_blank',
rel: 'noopener noreferrer'
},
children: state.all(node)
};
},
// Custom code block handler
code(state, node) {
return {
type: 'element',
tagName: 'pre',
properties: {
className: node.lang ? [`language-${node.lang}`] : undefined
},
children: [{
type: 'element',
tagName: 'code',
properties: {},
children: [{ type: 'text', value: node.value }]
}]
};
}
}
})Additional options from hast-util-to-html for controlling HTML output formatting. These are automatically available through the Options interface.
/** HTML output configuration options (subset of hast-util-to-html options) */
interface HtmlOutputOptions {
/** Allow dangerous HTML in output */
allowDangerousHtml?: boolean | null | undefined;
/** Close self-closing tags */
closeSelfClosing?: boolean | null | undefined;
/** Omit optional closing tags */
omitOptionalTags?: boolean | null | undefined;
/** Character encoding options */
characterReferences?: {
useShortestReferences?: boolean;
omitOptionalSemicolons?: boolean;
} | null | undefined;
/** Control quote usage in attributes */
quoteSmart?: boolean | null | undefined;
/** Collapse empty attributes */
collapseEmptyAttributes?: boolean | null | undefined;
/** Prefer unquoted attribute values */
preferUnquoted?: boolean | null | undefined;
}Examples:
// Control HTML output formatting
.use(remarkHtml, {
closeSelfClosing: true, // <br /> instead of <br>
omitOptionalTags: false, // Always include closing tags
characterReferences: {
useShortestReferences: true, // Use shortest HTML entities
omitOptionalSemicolons: false // Always include semicolons
}
})/** Unified plugin type */
type Plugin<PluginParameters, Input, Output> = (
...parameters: PluginParameters
) => void;
/** Markdown AST root node */
interface Root {
type: 'root';
children: any[];
}
/** Node handlers for mdast to hast conversion */
interface Handlers {
[nodeType: string]: (state: any, node: any) => any;
}
/** Sanitization schema from hast-util-sanitize */
interface Schema {
tagNames?: string[];
attributes?: Record<string, string[]>;
protocols?: Record<string, string[]>;
ancestors?: Record<string, string[]>;
clobber?: string[];
clobberPrefix?: string;
strip?: string[];
required?: Record<string, Record<string, any>>;
allowComments?: boolean;
allowDoctypes?: boolean;
}sanitize: truesanitize: false is dangerous and should only be used with trusted input// SAFE (recommended)
.use(remarkHtml) // sanitize: true by default
// DANGEROUS - only use with trusted input
.use(remarkHtml, { sanitize: false })
// SAFE with custom restrictions
.use(remarkHtml, {
sanitize: { tagNames: ['p', 'strong', 'em'] }
})mdast nodes can include data fields to customize HTML output:
interface NodeData {
/** Override the HTML tag name */
hName?: string;
/** Set HTML attributes/properties */
hProperties?: Record<string, any>;
/** Replace node children with custom HTML */
hChildren?: any[];
}Examples:
// Override tag name
node.data = { hName: 'section' }; // <p> becomes <section>
// Add attributes
node.data = {
hProperties: {
className: ['highlight'],
id: 'special'
}
};
// Replace content
node.data = {
hChildren: [
{ type: 'text', value: 'Custom content' }
]
};<div> elements.html