comrak
Version:
Comrak is an efficient, extensible, and highly configurable Markdown parser and renderer, written in Rust and compiled to WebAssembly. Portable and agnostic, it works seamlessly in any WebAssembly-friendly JS runtime.
1,113 lines (1,112 loc) • 37.1 kB
TypeScript
/**
* This module exposes the various configuration options and plugins available
* in the Comrak library, allowing you to customize the parsing and rendering
* behavior to suit your specific needs.
*
* @module options
*/
import type { HeadingAdapter, SyntaxHighlighterAdapter } from "./adapters.js";
import { type RequiredDeep } from "./_internal.js";
/**
* Represents an optional value that can be of type `T`, or `null | undefined`.
*
* @remarks
* This type corresponds to the `Option<T>` type in Rust, and is used to type
* values that may or may not be present. In the context of this library, this
* is used to represent optional parameters in various function signatures.
*
* @category Types
*/
export type Maybe<T> = T | null | undefined;
/**
* Represents an undefined link reference encountered during parsing.
*
* @category Options
* @tags parse
*/
export interface BrokenLinkReference {
/** The normalized URL of the link that was broken. */
normalized: string;
/** The original URL of the link that was broken. */
original: string;
}
/**
* The result of resolving a broken link reference.
*
* @category Options
* @tags parse
*/
export interface ResolvedReference {
/** The title of the resolved reference. */
title: string;
/** The destination URL of the resolved reference. */
url: string;
}
/**
* When the Comrak parser encounters an image or link reference that does not
* have a corresponding definition, the {@linkcode BrokenLinkCallback} will be
* invoked (if provided) to allow custom handling of the broken reference.
*
* The callback receives a {@linkcode BrokenLinkReference} object containing
* details about the broken link. It can return a {@linkcode ResolvedReference}
* object (or `null` or `undefined`) to provide a fallback title / URL to use
* for the broken link. If the callback returns `null` or `undefined`, the
* original link will be preserved.
*
* @category Options
* @tags parse
*/
export interface BrokenLinkCallbackFunction {
(this: BrokenLinkReference, ref: BrokenLinkReference): Maybe<ResolvedReference>;
}
/**
* Similar to the {@linkcode BrokenLinkCallbackFunction}, but implemented as an
* object with a `resolve` method.
*
* @category Options
* @tags parse
*/
export interface BrokenLinkCallbackImpl {
resolve(ref: BrokenLinkReference): Maybe<ResolvedReference>;
}
/**
* A type that represents either a function or an object for handling broken
* link references.
*
* @see {@linkcode BrokenLinkCallbackFunction} for function-based handling.
* @see {@linkcode BrokenLinkCallbackImpl} for object-based handling.
* @category Options
* @tags parse
*/
export type BrokenLinkCallback = BrokenLinkCallbackFunction | BrokenLinkCallbackImpl;
/**
* A function that rewrites URLs for images or links during rendering.
*
* @category Options
* @tags extension
*/
export interface URLRewriterFunction {
(url: string): string;
}
/**
* An object that rewrites URLs for images or links during rendering.
*
* @category Options
* @tags extension
*/
export interface URLRewriterImpl {
toHTML(url: string): string;
}
/**
* A type that represents either a function or an object for rewriting URLs.
*
* @see {@linkcode URLRewriterFunction} for function-based URL rewriting.
* @see {@linkcode URLRewriterImpl} for object-based URL rewriting.
* @category Options
* @tags extension
*/
export type URLRewriter = URLRewriterFunction | URLRewriterImpl;
/**
* Comrak's capabilities really shine through its highly configurable APIs. The
* `Options` interface allows you to fine-tune each stage of the Markdown
* processing pipeline, from parsing to rendering.
*
* Comrak also supports numerous extensions to the CommonMark specification,
* enabling features like tables, footnotes, autolinks, task lists, description
* lists, HTML tag filtering, and much more. You can also customize Comrak's
* behavior further through its extensible {@linkcode Plugins} API, allowing
* for integration with external syntax highlighters, heading ID slugifiers,
* and other capabilities.
*
* These options can be passed to any of Comrak's main functions:
*
* - {@link markdownToHTML}
* - {@link markdownToXML}
* - {@link markdownToCommonMark}
* - {@link parseMarkdown}
* - {@link renderHTML}
* - {@link renderXML}
* - {@link renderCommonMark}
*
* See the documentation for each individual option for detailed information on
* their behavior and usage, as well as functional code examples.
*
* @category Options
*/
export interface Options {
/** Configure extensions to the CommonMark specification. */
extension?: ExtensionOptions;
/** Configure parse-time options. */
parse?: ParseOptions;
/** Configure render-time options. */
render?: RenderOptions;
/** Configure {@linkcode Plugins} to customize Comrak's behavior. */
plugins?: Plugins;
}
/**
* Options to select extensions.
*
* @category Options
* @tags extension
*/
export interface ExtensionOptions {
/**
* Enables the [autolink extension] from the GFM spec.
*
* [autolink extension]: https://github.github.com/gfm/#autolinks-extension-
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("Hello www.github.com.\n", {
* extension: { autolink: true },
* });
* assert.equal(html, '<p>Hello <a href="http://www.github.com">www.github.com</a>.</p>\n');
* ```
* @default {false}
*/
autolink?: boolean;
/**
* Enables the description lists extension.
*
* Each term must be defined in one paragraph, followed by a blank line, and
* then by the details. Details begins with a colon.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("Term\n\n: Definition", {
* extension: { descriptionLists: true },
* });
* assert.equal(html, "<dl>\n<dt>Term</dt>\n<dd>\n<p>Definition</p>\n</dd>\n</dl>\n");
* ```
* @default {false}
*/
descriptionLists?: boolean;
/**
* Enables the footnotes extension per cmark-gfm.
*
* The extension is modelled after [Kramdown].
*
* [Kramdown]: https://kramdown.gettalong.org/syntax.html#footnotes
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("Hi[^x].\n\n[^x]: A greeting.\n", {
* extension: { footnotes: true },
* });
* assert.equal(html, '<p>Hi<sup class="footnote-ref"><a href="#fn-x" id="fnref-x" data-footnote-ref>1</a></sup>.</p>\n<section class="footnotes" data-footnotes>\n<ol>\n<li id="fn-x">\n<p>A greeting. <a href="#fnref-x" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>\n</li>\n</ol>\n</section>\n');
* ```
* @default {false}
*/
footnotes?: boolean;
/**
* Enables the inline footnotes extension.
*
* Allows inline footnote syntax `^[content]` where the content can include
* inline markup. Inline footnotes are automatically converted to regular
* footnotes with auto-generated names and share the same numbering sequence.
*
* Requires `footnotes` to be enabled as well.
*
* @example
* ```ts
* import { markdownToHTML, Options } from "@nick/comrak";
* import assert from "node:assert";
*
* const options = Options.default();
* options.extension.footnotes = true;
* options.extension.inlineFootnotes = true;
*
* const md = "Hi^[An inline note].\n";
* const html = markdownToHTML(md, options);
* assert.equal(html, "<p>Hi<sup class=\"footnote-ref\"><a href=\"#fn-__inline_1\" id=\"fnref-__inline_1\" data-footnote-ref>1</a></sup>.</p>\n<section class=\"footnotes\" data-footnotes>\n<ol>\n<li id=\"fn-__inline_1\">\n<p>An inline note <a href=\"#fnref-__inline_1\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"1\" aria-label=\"Back to reference 1\">↩</a></p>\n</li>\n</ol>\n</section>\n");
* ```
*/
inlineFootnotes?: boolean;
/**
* Enables the front matter extension.
*
* Front matter, which begins with the delimiter string at the beginning of
* the file and ends at the end of the next line that contains only the
* delimiter, is passed through unchanged in markdown output and omitted
* from HTML output.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("---\nlayout: post\n---\nText\n", {
* extension: { frontMatterDelimiter: "---" },
* });
* assert.equal(html, "<p>Text</p>\n");
* ```
* @default {null}
*/
frontMatterDelimiter?: string | null;
/**
* Enables the header IDs Comrak extension.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("# README\n", {
* extension: { headerIDs: "user-content-" },
* });
* assert.equal(html, "<h1><a href=\"#readme\" aria-hidden=\"true\" class=\"anchor\" id=\"user-content-readme\"></a>README</h1>\n");
* ```
* @default {null}
*/
headerIDs?: string | null;
/**
* Enables the [table extension] from the GFM spec.
*
* [table extension]: https://github.github.com/gfm/#tables-extension-
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("| a | b |\n|---|---|\n| c | d |\n", {
* extension: { table: true },
* });
* assert.equal(html, "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n");
* ```
* @default {false}
*/
table?: boolean;
/**
* Enables the [tagfilter extension] per the GFM spec.
*
* [tagfilter extension]: https://github.github.com/gfm/#disallowed-raw-html-extension-
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("Hello <xmp>.\n\n<xmp>", {
* extension: { tagfilter: true },
* render: { unsafe: true },
* });
* assert.equal(html, "<p>Hello <xmp>.</p>\n<xmp>\n");
* ```
* @default {false}
*/
tagfilter?: boolean;
/**
* Enables the [task list items extension] from the GFM spec.
*
* Note that the spec does not define the precise output, so only the bare
* essentials are rendered.
*
* [task list items extension]: https://github.github.com/gfm/#task-list-items-extension-
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("* [x] Done\n* [ ] Not done\n", { extension: { tasklist: true } });
* assert.equal(html, "<ul>\n<li><input type=\"checkbox\" checked=\"\" disabled=\"\" /> Done</li>\n<li><input type=\"checkbox\" disabled=\"\" /> Not done</li>\n</ul>\n");
* ```
* @default {false}
*/
tasklist?: boolean;
/**
* Enables the multiline block quote extension.
*
* Place `>>>` before and after text to make it into a block quote.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML(">>>\nparagraph\n>>>", {
* extension: { multilineBlockQuotes: true },
* });
* assert.equal(html, "<blockquote>\n<p>paragraph</p>\n</blockquote>\n");
* ```
* @default {false}
*/
multilineBlockQuotes?: boolean;
/**
* Enables GitHub-style alerts.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("> [!note]\n> Something of note", {
* extension: { alerts: true },
* });
* assert.equal(html, "<div class=\"markdown-alert markdown-alert-note\">\n<p class=\"markdown-alert-title\">Note</p>\n<p>Something of note</p>\n</div>\n");
* ```
*
* @default {false}
*/
alerts?: boolean;
/**
* Enables math using dollar syntax.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("$1 + 2$ and $$x = y$$", {
* extension: { mathDollars: true },
* });
* assert.equal(html, "<p><span data-math-style=\"inline\">1 + 2</span> and <span data-math-style=\"display\">x = y</span></p>\n");
* ```
* @default {false}
*/
mathDollars?: boolean;
/**
* Enables math using code syntax.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("$`1 + 2`$", {
* extension: { mathCode: true },
* });
* assert.equal(html, "<p><code data-math-style=\"inline\">1 + 2</code></p>\n");
* ```
* @default {false}
*/
mathCode?: boolean;
/**
* Enables wikilinks extension.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* // Title before pipe: [[title|url]]
* const html = markdownToHTML("[[link label|url]]", {
* extension: { wikilinksTitleBeforePipe: true },
* });
* assert.equal(html, "<p><a href=\"url\" data-wikilink=\"true\">link label</a></p>\n");
* ```
* @default {false}
*/
wikilinksTitleBeforePipe?: boolean;
/**
* Enables wikilinks extension.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* // Title after pipe: [[url|title]]
* const html = markdownToHTML("[[url|link label]]", {
* extension: { wikilinksTitleAfterPipe: true },
* });
* assert.equal(html, "<p><a href=\"url\" data-wikilink=\"true\">link label</a></p>\n");
* ```
* @default {false}
*/
wikilinksTitleAfterPipe?: boolean;
/**
* Enables underlines using double underscores.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("__underlined text__", {
* extension: { underline: true },
* });
* assert.equal(html, "<p><u>underlined text</u></p>\n");
* ```
* @default {false}
*/
underline?: boolean;
/**
* Enables the [strikethrough extension] from the GFM spec.
*
* [strikethrough extension]: https://github.github.com/gfm/#strikethrough-extension-
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("Hello ~world~ there.\n", {
* extension: { strikethrough: true },
* });
* assert.equal(html, "<p>Hello <del>world</del> there.</p>\n");
* ```
* @default {false}
*/
strikethrough?: boolean;
/**
* Enables the superscript Comrak extension.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("e = mc^2^.\n", { extension: { superscript: true } });
* assert.equal(html, "<p>e = mc<sup>2</sup>.</p>\n");
* ```
* @default {false}
*/
superscript?: boolean;
/**
* Enables subscript text using single tildes.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("H~2~O", {
* extension: { subscript: true },
* });
* assert.equal(html, "<p>H<sub>2</sub>O</p>\n");
* ```
* @default {false}
*/
subscript?: boolean;
/**
* Enables spoilers using double vertical bars.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("Darth Vader is ||Luke's father||", {
* extension: { spoiler: true },
* });
* assert.equal(html, "<p>Darth Vader is <span class=\"spoiler\">Luke's father</span></p>\n");
* ```
* @default {false}
*/
spoiler?: boolean;
/**
* Requires at least one space after a `>` character to generate a blockquote.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML(">implying implications", {
* extension: { greentext: true },
* });
* assert.equal(html, "<p>>implying implications</p>\n");
* ```
* @default {false}
*/
greentext?: boolean;
/**
* Phrases wrapped inside of ':' blocks will be replaced with emojis.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("Happy Friday! :smile:", {
* extension: { shortcodes: true },
* });
* assert.equal(html, "<p>Happy Friday! 😄</p>\n");
* ```
* @default {false}
*/
shortcodes?: boolean;
/**
* Wraps image URLs using a custom {@linkcode URLRewriter}.
*
* @example
* ```ts
* import { markdownToHTML, Options } from "@nick/comrak";
* import assert from "node:assert";
*
* const options = Options.default();
* options.extension.imageURLRewriter = (url: string) =>
* `https://cdn.example.com/images/${encodeURIComponent(url)}`;
*
* const html = markdownToHTML("", options);
* assert.equal(html, '<p><img src="https://cdn.example.com/images/image.png" alt="alt text" /></p>\n');
* ```
* @default {null}
*/
imageURLRewriter?: URLRewriter | null;
/**
* Wraps link URLs using a function or custom trait object.
*
* @example
* ```ts
* import { markdownToHTML, Options } from "@nick/comrak";
* import assert from "node:assert";
*
* const options = Options.default();
* options.extension.linkURLRewriter = (url: string) =>
* `https://safe.example.com/norefer?url=${encodeURIComponent(url)}`;
*
* const html = markdownToHTML("[my link](http://unsafe.example.com/bad)", options);
* assert.equal(html,
* '<p><a href="https://safe.example.com/norefer?url=http%3A%2F%2Funsafe.example.com%2Fbad">my link</a></p>\n'
* );
* ```
* @default {null}
*/
linkURLRewriter?: URLRewriter | null;
/**
* Recognizes many emphasis that appear in CJK contexts.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("**この文は重要です。**但这句话并不重要。", {
* extension: { cjkFriendlyEmphasis: true },
* });
* assert.equal(html, "<p><strong>この文は重要です。</strong>但这句话并不重要。</p>\n");
* ```
* @default {false}
*/
cjkFriendlyEmphasis?: boolean;
/**
* Enables block scoped subscript that acts similar to a header.
*
* ```md
* -# subtext
* ```
*
* @example
* ```ts
* import { markdownToHTML, Options } from "@nick/comrak";
* import assert from "node:assert";
*
* const options = Options.default();
* options.extension.subtext = true;
*
* assert.equal(markdownToHTML("-# subtext", options),
* "<p><sub>subtext</sub></p>\n");
* ```
* @default {false}
*/
subtext?: boolean;
/**
* Enables highlighting (mark) using `==`.
*
* ```md
* Hey, ==this is important==!
* ```
* @example
* ```ts
* import { markdownToHTML, Options } from "@nick/comrak";
* import assert from "node:assert";
*
* const options = Options.default();
* options.extension.highlight = true;
*
* const html = markdownToHTML("Hey, ==this is important==!", options);
* assert.equal(html, "<p>Hey, <mark>this is important</mark>!</p>\n");
* ```
*/
highlight?: boolean;
}
/**
* Options for parser functions.
*
* @category Options
* @tags parse
*/
export interface ParseOptions {
/**
* The default info string for fenced code blocks.
*
* @example
* ````ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* let html = markdownToHTML("```\nfn hello();\n```\n");
* assert.equal(html, "<pre><code>fn hello();\n</code></pre>\n");
*
* html = markdownToHTML("```\nfn hello();\n```\n", {
* parse: { defaultInfoString: "rust" },
* });
* assert.equal(html, "<pre><code class=\"language-rust\">fn hello();\n</code></pre>\n");
* ````
* @default {null}
*/
defaultInfoString?: string | null;
/**
* When enabled, converts all quotes, full-stops, hyphens, ellipsis, and
* other punctuation into their ‘smart’ equivalents. Also commonly known as
* "smartypants" conversion.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* let html = markdownToHTML("'Hello,' \"world\" ...");
* assert.equal(html, "<p>'Hello,' "world" ...</p>\n");
*
* html = markdownToHTML("'Hello,' \"world\" ...", {
* parse: { smart: true },
* });
* assert.equal(html, "<p>‘Hello,’ “world” …</p>\n");
* ```
*
* @default {false}
*/
smart?: boolean;
/**
* Whether or not a simple `x` or `X` is used for tasklist or any other
* symbol is allowed.
*
* @default {false}
*/
relaxedTasklistMatching?: boolean;
/**
* Whether tasklist items can be parsed in table cells. At present, the
* tasklist item must be the only content in the cell. Both tables and
* tasklists much be enabled for this to work.
*
* @example
* ```ts
* import { markdownToHTML, Options } from "@nick/comrak";
* import assert from "node:assert";
*
* const options = Options.default();
* options.extension.table = true;
* options.extension.tasklist = true;
* assert.equal(markdownToHTML("| val |\n| - |\n| [ ] |\n", options),
* "<table>\n<thead>\n<tr>\n<th>val</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>[ ]</td>\n</tr>\n</tbody>\n</table>\n");
*
* options.parse.tasklistInTable = true;
* assert.equal(markdownToHTML("| val |\n| - |\n| [ ] |\n", options),
* "<table>\n<thead>\n<tr>\n<th>val</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>\n<input type=\"checkbox\" disabled=\"\" /> </td>\n</tr>\n</tbody>\n</table>\n");
* ```
* @default {false}
*/
tasklistInTable?: boolean;
/**
* Relax parsing of autolinks, allow links to be detected inside brackets
* and allow all url schemes.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("[https://foo.com]", {
* extension: { autolink: true },
* parse: { relaxedAutolinks: true },
* });
* assert.equal(html, "<p>[<a href=\"https://foo.com\">https://foo.com</a>]</p>\n");
* ```
* @default {false}
*/
relaxedAutolinks?: boolean;
/**
* Ignore setext headings in input.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("setext heading\n---", {
* parse: { ignoreSetext: true },
* });
* assert.equal(html, "<p>setext heading</p>\n<hr />\n");
* ```
* @default {false}
*/
ignoreSetext?: boolean;
/**
* Callback for broken link resolution. When the parser encounters a link or
* image reference that does not have a corresponding definition, this option
* determines how to handle it.
*
* You can specify the callback either as a function, or an object that
* implements the {@linkcode BrokenLinkCallbackImpl} interface.
*
* In either case, the callback will be invoked with a
* {@linkcode BrokenLinkReference} object containing the normalized and
* original URLs of the broken link. The callback should return a
* {@linkcode ResolvedReference} object, which contains a `url` and `title`
* to replace the broken link with, or `null` or `undefined` to leave the
* link unchanged.
*
* @example
* ```ts
* import { markdownToHTML, Options } from "@nick/comrak";
* import assert from "node:assert";
*
* const options = Options.default();
*
* options.parse.brokenLinkCallback = (ref) => {
* if (ref.normalized.includes("badge")) {
* return {
* url: "https://img.shields.io/badge/placeholder-lightgrey.svg",
* title: `Placeholder Badge (original: ${ref.original})`,
* };
* }
* return null;
* };
*
* const html = markdownToHTML("![Build Status][undefined-badge]\n", options);
* assert.equal(html, '<p><img src="https://img.shields.io/badge/placeholder-lightgrey.svg" alt="Build Status" title="Placeholder Badge (original: undefined-badge)" /></p>\n');
* ```
* @default {null}
*/
brokenLinkCallback?: BrokenLinkCallback | null;
/**
* Leave footnote definitions in place in the document tree, rather than
* reordering them to the end. This will also cause unreferenced footnote
* definitions to remain in the tree, rather than being removed.
*
* Comrak's default formatters expect this option to be turned **off**, so
* use this with care if you use the default formatters.
*
* @default {false}
*/
leaveFootnoteDefinitions?: boolean;
/**
* Leave escaped characters in an `Escaped` node in the document tree.
*
* **Note**: enabling the {@linkcode RenderOptions.escapedCharSpans} will
* cause this option to be enabled automatically.
*
* @default {false}
*/
escapedCharSpans?: boolean;
}
/**
* Options for the renderer functions.
*
* @category Options
* @tags render
*/
export interface RenderOptions {
/**
* Escape raw HTML instead of clobbering it.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* let html = markdownToHTML("<i>italic text</i>");
* assert.equal(html, "<p><!-- raw HTML omitted -->italic text<!-- raw HTML omitted --></p>\n");
*
* html = markdownToHTML("<i>italic text</i>", {
* render: { escape: true },
* });
* assert.equal(html, "<p><i>italic text</i></p>\n");
* ```
* @default {false}
*/
escape?: boolean;
/**
* GitHub-style `<pre lang="xyz">` is used for fenced code blocks with info
* tags, instead of `<pre><code class="language-xyz">`.
*
* @example
* ````ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* let html = markdownToHTML("```rust\nfn hello();\n```\n");
* assert.equal(html, "<pre><code class=\"language-rust\">fn hello();\n</code></pre>\n");
*
* html = markdownToHTML("```rust\nfn hello();\n```\n", {
* render: { githubPreLang: true },
* });
* assert.equal(html, "<pre lang=\"rust\"><code>fn hello();\n</code></pre>\n");
* ````
* @default {false}
*/
githubPreLang?: boolean;
/**
* [Soft line breaks](https://spec.commonmark.org/0.27/#soft-line-breaks) in
* the input translate into hard line breaks in the output.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* let html = markdownToHTML("Hello.\nWorld.\n");
* assert.equal(html, "<p>Hello.\nWorld.</p>\n");
*
* html = markdownToHTML("Hello.\nWorld.\n", { render: { hardbreaks: true } });
* assert.equal(html, "<p>Hello.<br />\nWorld.</p>\n");
* ```
* @default {false}
*/
hardbreaks?: boolean;
/**
* Allow rendering of raw HTML and potentially dangerous links.
*
* @example
* ```ts
* import { markdownToHTML, Options } from "@nick/comrak";
* import assert from "node:assert";
*
* const options = Options.default();
*
* const dangerousMarkdown = "<script>\nalert('xyz');\n</script>\n\nPossibly <marquee>annoying</marquee>.\n\n[Dangerous](javascript:alert(document.cookie)).\n\n[Safe](http://commonmark.org).\n";
*
* const safeHTML = markdownToHTML(dangerousMarkdown, options);
* assert.equal(safeHTML, "<!-- raw HTML omitted -->\n<p>Possibly <!-- raw HTML omitted -->annoying<!-- raw HTML omitted -->.</p>\n<p><a href=\"\">Dangerous</a>.</p>\n<p><a href=\"http://commonmark.org\">Safe</a>.</p>\n");
*
* options.render.unsafe = true;
* const unsafeHTML = markdownToHTML(dangerousMarkdown, options);
* assert.equal(unsafeHTML, "<script>\nalert(\'xyz\');\n</script>\n<p>Possibly <marquee>annoying</marquee>.</p>\n<p><a href=\"javascript:alert(document.cookie)\">Dangerous</a>.</p>\n<p><a href=\"http://commonmark.org\">Safe</a>.</p>\n");
* ```
* @default {false}
*/
unsafe?: boolean;
/**
* The wrap column when outputting CommonMark.
*
* @default {0}
*/
width?: number;
/**
* Whether to use the full info string for fenced code blocks.
*
* @example
* ````ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* let html = markdownToHTML("```rust extra info\nfn hello();\n```\n");
* assert.equal(html, '<pre><code class="language-rust">fn hello();\n</code></pre>\n');
*
* html = markdownToHTML("```rust extra info\nfn hello();\n```\n", {
* render: { fullInfoString: true },
* });
* assert.equal(html, '<pre><code class="language-rust" data-meta="extra info">fn hello();\n</code></pre>\n');
* ````
*
* @default {false}
*/
fullInfoString?: boolean;
/**
* The style for list items.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("* Item\n* Item\n", { render: { listStyle: "star" } });
* assert.equal(html, "<ul>\n<li>Item</li>\n<li>Item</li>\n</ul>\n");
* ```
* @default {"dash"}
*/
listStyle?: "dash" | "plus" | "star";
/**
* Include source position attributes in HTML and XML output.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("Hello *world*!", {
* render: { sourcepos: true },
* });
* assert.equal(html, "<p data-sourcepos=\"1:1-1:14\">Hello <em data-sourcepos=\"1:7-1:13\">world</em>!</p>\n");
* ```
*
* @default {false}
*/
sourcepos?: boolean;
/**
* Wrap escaped characters in a `<span>` to allow any post-processing to recognize them.
*
* **Note**: enabling this will also enable {@linkcode ParseOptions.escapedCharSpans}.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("Notify user \\@example", {
* render: { escapedCharSpans: true },
* });
* assert.equal(html, "<p>Notify user <span data-escaped-char>@</span>example</p>\n");
* ```
* @default {false}
*/
escapedCharSpans?: boolean;
/**
* Ignore empty links in input.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("[]()", {
* render: { ignoreEmptyLinks: true },
* });
* assert.equal(html, "<p>[]()</p>\n");
* ```
* @default {false}
*/
ignoreEmptyLinks?: boolean;
/**
* Enables GFM quirks in HTML output which break CommonMark compatibility.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("****abcd****", {
* render: { gfmQuirks: true },
* });
* assert.equal(html, "<p><strong>abcd</strong></p>\n");
* ```
* @default {false}
*/
gfmQuirks?: boolean;
/**
* Prefer fenced code blocks when outputting CommonMark.
*
* @default {false}
*/
preferFenced?: boolean;
/**
* Render the image as a figure element with the title as its caption.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("", { render: { figureWithCaption: true } });
* assert.equal(html, "<p><figure><img src=\"https://example.com/image.png\" alt=\"image\" title=\"this is an image\" /><figcaption>this is an image</figcaption></figure></p>\n");
* ```
* @default {false}
*/
figureWithCaption?: boolean;
/**
* Add classes to the output of the tasklist extension.
*
* @example
* ```ts
* import { markdownToHTML } from "@nick/comrak";
* import assert from "node:assert";
*
* const html = markdownToHTML("- [ ] Foo", {
* extension: { tasklist: true },
* render: { tasklistClasses: true },
* });
* assert.equal(html, "<ul class=\"contains-task-list\">\n<li class=\"task-list-item\"><input type=\"checkbox\" class=\"task-list-item-checkbox\" disabled=\"\" /> Foo</li>\n</ul>\n");
* ```
* @default {false}
*/
tasklistClasses?: boolean;
/**
* Render ordered list with a minimum marker width.
*
* @default {0}
*/
olWidth?: number;
/**
* Minimise escapes used in CommonMark output.
*
* @default {false}
*/
experimentalMinimizeCommonmark?: boolean;
}
/**
* Plugins to customize rendering behavior.
*
* @category Options
* @tags render, plugins
*/
export interface RenderPlugins {
/** Adapter for syntax highlighting codefences. */
codefenceSyntaxHighlighter?: SyntaxHighlighterAdapter | null;
/** Adapter for customizing heading rendering. */
headingAdapter?: HeadingAdapter | null;
}
/**
* Plugins to customize rendering behavior.
*
* @category Options
* @tags plugins
*/
export interface Plugins {
/**
* Plugins to customize rendering behavior.
*/
render?: RenderPlugins;
}
/**
* Default options for the various parsing, rendering, and conversion functions
* in the Comrak library.
*
* @category Options
*/
export declare const defaultOptions: DefaultOptions;
/**
* Default options with all fields specified.
*
* @category Options
* @tags defaults
*/
export type DefaultOptions = RequiredDeep<Options, URLRewriter | HeadingAdapter | SyntaxHighlighterAdapter>;
/**
* Options with defaults applied, and a `default` method to obtain a fresh copy
* of the default options object, for use when constructing new options.
*
* @category Options
* @tags defaults
*/
export interface OptionsWithDefaults extends DefaultOptions {
/**
* Returns a fresh copy of the {@linkcode defaultOptions} object,
* as a deeply-cloned (immutable) copy of the original.
*/
default(): DefaultOptions;
}
/**
* The `Options` object contains the default options for Comrak, as well as a
* `default` helper method to obtain a fresh copy of those defaults.
*
* This is useful when constructing new options objects to pass to Comrak's
* parsing, rendering, and conversion functions, as it ensures that all fields
* are set and avoids any issues with mutation-related side-effects.
*
* @category Options
* @tags defaults
*/
export declare const Options: OptionsWithDefaults;