markdown-to-jsx
Version:
A very fast and versatile markdown toolchain. AST, React, and HTML output available with full customization.
347 lines (346 loc) • 11 kB
TypeScript
import * as React2 from "react";
import * as React from "react";
/**
* Analogous to `node.type`. Please note that the values here may change at any time,
* so do not hard code against the value directly.
*/
declare const RuleTypeConst: {
readonly blockQuote: 0;
readonly breakLine: 1;
readonly breakThematic: 2;
readonly codeBlock: 3;
readonly codeInline: 4;
readonly footnote: 5;
readonly footnoteReference: 6;
readonly frontmatter: 7;
readonly gfmTask: 8;
readonly heading: 9;
readonly htmlBlock: 10;
readonly htmlComment: 11;
readonly htmlSelfClosing: 12;
readonly image: 13;
readonly link: 14;
readonly orderedList: 15;
readonly paragraph: 16;
readonly ref: 17;
readonly refCollection: 18;
readonly table: 19;
readonly text: 20;
readonly textFormatted: 21;
readonly unorderedList: 22;
};
type RuleTypeValue = (typeof RuleTypeConst)[keyof typeof RuleTypeConst];
/**
* markdown-to-jsx types and interfaces
*/
declare namespace MarkdownToJSX {
/**
* RequireAtLeastOne<{ ... }> <- only requires at least one key
*/
type RequireAtLeastOne<
T,
Keys extends keyof T = keyof T
> = Pick<T, Exclude<keyof T, Keys>> & { [K in Keys]-? : Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>> }[Keys];
export type CreateElement = typeof React.createElement;
export type HTMLTags = keyof React.JSX.IntrinsicElements & (string & {});
export type State = {
/** true if the current content is inside anchor link grammar */
inAnchor?: boolean;
/** true if inside a blockquote */
inBlockQuote?: boolean;
/** true if parsing in an HTML context */
inHTML?: boolean;
/** true if in a list */
inList?: boolean;
/** true if parsing in an inline context (subset of rules around formatting and links) */
inline?: boolean;
/** use this for the `key` prop */
key?: React.Key;
/** reference definitions (footnotes are stored with '^' prefix) */
refs?: {
[key: string]: {
target: string;
title: string | undefined;
};
};
/** current recursion depth during rendering */
renderDepth?: number;
};
export interface BlockQuoteNode {
alert?: string;
children: MarkdownToJSX.ASTNode[];
type: typeof RuleType2.blockQuote;
}
export interface BreakLineNode {
type: typeof RuleType2.breakLine;
}
export interface BreakThematicNode {
type: typeof RuleType2.breakThematic;
}
export interface CodeBlockNode {
type: typeof RuleType2.codeBlock;
attrs?: React.JSX.IntrinsicAttributes;
lang?: string;
text: string;
}
export interface CodeInlineNode {
type: typeof RuleType2.codeInline;
text: string;
}
export interface FootnoteNode {
type: typeof RuleType2.footnote;
}
export interface FootnoteReferenceNode {
type: typeof RuleType2.footnoteReference;
target: string;
text: string;
}
export interface FrontmatterNode {
type: typeof RuleType2.frontmatter;
text: string;
}
export interface GFMTaskNode {
type: typeof RuleType2.gfmTask;
completed: boolean;
}
export interface HeadingNode {
type: typeof RuleType2.heading;
children: MarkdownToJSX.ASTNode[];
id: string;
level: 1 | 2 | 3 | 4 | 5 | 6;
}
export interface HTMLCommentNode {
type: typeof RuleType2.htmlComment;
text: string;
}
export interface ImageNode {
type: typeof RuleType2.image;
alt?: string;
target: string;
title?: string;
}
export interface LinkNode {
type: typeof RuleType2.link;
children: MarkdownToJSX.ASTNode[];
target: string | null;
title?: string;
}
export interface OrderedListNode {
type: typeof RuleType2.orderedList;
items: MarkdownToJSX.ASTNode[][];
start?: number;
}
export interface UnorderedListNode {
type: typeof RuleType2.unorderedList;
items: MarkdownToJSX.ASTNode[][];
}
export interface ParagraphNode {
type: typeof RuleType2.paragraph;
children: MarkdownToJSX.ASTNode[];
}
export interface ReferenceNode {
type: typeof RuleType2.ref;
}
export interface ReferenceCollectionNode {
type: typeof RuleType2.refCollection;
refs: {
[key: string]: {
target: string;
title: string | undefined;
};
};
}
export interface TableNode {
type: typeof RuleType2.table;
/**
* alignment for each table column
*/
align: ("left" | "right" | "center")[];
cells: MarkdownToJSX.ASTNode[][][];
header: MarkdownToJSX.ASTNode[][];
}
export interface TextNode {
type: typeof RuleType2.text;
text: string;
}
export interface FormattedTextNode {
type: typeof RuleType2.textFormatted;
/**
* the corresponding html tag
*/
tag: string;
children: MarkdownToJSX.ASTNode[];
}
export interface HTMLNode {
type: typeof RuleType2.htmlBlock;
attrs?: Record<string, any>;
children?: ASTNode[] | undefined;
noInnerParse?: Boolean;
tag: string;
text?: string | undefined;
}
export interface HTMLSelfClosingNode {
type: typeof RuleType2.htmlSelfClosing;
attrs?: Record<string, any>;
isClosingTag?: boolean;
tag: string;
}
export type ASTNode = BlockQuoteNode | BreakLineNode | BreakThematicNode | CodeBlockNode | CodeInlineNode | FootnoteNode | FootnoteReferenceNode | FrontmatterNode | GFMTaskNode | HeadingNode | HTMLCommentNode | ImageNode | LinkNode | OrderedListNode | UnorderedListNode | ParagraphNode | ReferenceNode | ReferenceCollectionNode | TableNode | TextNode | FormattedTextNode | HTMLNode | HTMLSelfClosingNode;
export type ASTRender = (ast: MarkdownToJSX.ASTNode | MarkdownToJSX.ASTNode[], state: MarkdownToJSX.State) => React.ReactNode;
export type Override = RequireAtLeastOne<{
component: React.ElementType;
props: Object;
}> | React.ElementType;
export type Overrides = { [tag in HTMLTags]? : Override } & {
[customComponent: string]: Override;
};
export type Options = Partial<{
/**
* Ultimate control over the output of all rendered JSX.
*/
createElement: (tag: Parameters<CreateElement>[0], props: React.JSX.IntrinsicAttributes, ...children: React.ReactNode[]) => React.ReactNode;
/**
* The library automatically generates an anchor tag for bare URLs included in the markdown
* document, but this behavior can be disabled if desired.
*/
disableAutoLink: boolean;
/**
* Disable the compiler's best-effort transcription of provided raw HTML
* into JSX-equivalent. This is the functionality that prevents the need to
* use `dangerouslySetInnerHTML` in React.
*/
disableParsingRawHTML: boolean;
/**
* Enable GFM tagfilter extension to filter potentially dangerous HTML tags.
* When enabled, the following tags are escaped: title, textarea, style, xmp,
* iframe, noembed, noframes, script, plaintext.
* https://github.github.com/gfm/#disallowed-raw-html-extension-
* @default true
*/
tagfilter?: boolean;
/**
* Forces the compiler to have space between hash sign and the header text which
* is explicitly stated in the most of the markdown specs.
* https://github.github.com/gfm/#atx-heading
* `The opening sequence of # characters must be followed by a space or by the end of line.`
*/
enforceAtxHeadings: boolean;
/**
* Forces the compiler to always output content with a block-level wrapper
* (`<p>` or any block-level syntax your markdown already contains.)
*/
forceBlock: boolean;
/**
* Forces the compiler to always output content with an inline wrapper (`<span>`)
*/
forceInline: boolean;
/**
* Forces the compiler to wrap results, even if there is only a single
* child or no children.
*/
forceWrapper: boolean;
/**
* Selectively control the output of particular HTML tags as they would be
* emitted by the compiler.
*/
overrides: Overrides;
/**
* Allows for full control over rendering of particular rules.
* For example, to implement a LaTeX renderer such as `react-katex`:
*
* ```
* renderRule(next, node, renderChildren, state) {
* if (node.type === RuleType.codeBlock && node.lang === 'latex') {
* return (
* <TeX as="div" key={state.key}>
* {String.raw`${node.text}`}
* </TeX>
* )
* }
*
* return next();
* }
* ```
*
* Thar be dragons obviously, but you can do a lot with this
* (have fun!) To see how things work internally, check the `render`
* method in source for a particular rule.
*/
renderRule: (next: () => React.ReactNode, node: ASTNode, renderChildren: ASTRender, state: State) => React.ReactNode;
/**
* Override the built-in sanitizer function for URLs, etc if desired. The built-in version is available as a library
export called `sanitizer`.
*/
sanitizer: (value: string, tag: HTMLTags, attribute: string) => string | null;
/**
* Override normalization of non-URI-safe characters for use in generating
* HTML IDs for anchor linking purposes.
*/
slugify: (input: string, defaultFn: (input: string) => string) => string;
/**
* Declare the type of the wrapper to be used when there are multiple
* children to render. Set to `null` to get an array of children back
* without any wrapper, or use `React.Fragment` to get a React element
* that won't show up in the DOM.
*/
wrapper: React.ElementType | null;
/**
* Props to apply to the wrapper element.
*/
wrapperProps?: React.JSX.IntrinsicAttributes;
/**
* Preserve frontmatter in the output by rendering it as a <pre> element.
* By default, frontmatter is parsed but not rendered.
* @default false
*/
preserveFrontmatter?: boolean;
}>;
}
declare const RuleType2: typeof RuleTypeConst;
type RuleType2 = RuleTypeValue;
declare global {
var parseMetrics: {
blockParsers: {
[key: string]: {
attempts: number;
hits: number;
hitTimings: number[];
};
};
inlineParsers: {
[key: string]: {
attempts: number;
hits: number;
hitTimings: number[];
};
};
totalOperations: number;
blockParseIterations: number;
inlineParseIterations: number;
} | null;
var parseMetricsStartTimes: Map<string, number> | null;
}
/**
* Given a markdown string, return an abstract syntax tree (AST) of the markdown.
*
* The first node in the AST is a reference collection node. This node contains all the
* reference definitions found in the markdown. These reference definitions are used to
* resolve reference links and images in the markdown.
*
* @param source - The markdown string to parse.
* @param options - The options for the parser.
* @returns The AST of the markdown.
*/
declare function parser(source: string, options?: MarkdownToJSX.Options): MarkdownToJSX.ASTNode[];
declare function sanitizer(input: string): string | null;
declare function slugify(str: string): string;
declare function compiler(markdown?: string, options?: MarkdownToJSX.Options): React2.ReactNode;
/**
* A simple HOC for easy React use. Feed the markdown content as a direct child
* and the rest is taken care of automatically.
*/
declare const Markdown: React2.FC<Omit<React2.HTMLAttributes<Element>, "children"> & {
children?: string | null;
options?: MarkdownToJSX.Options;
}>;
export { slugify, sanitizer, parser, Markdown as default, compiler, RuleType2 as RuleType, MarkdownToJSX, Markdown };