{"id":13403871,"url":"https://github.com/remarkjs/react-markdown","last_synced_at":"2025-05-12T18:20:59.365Z","repository":{"id":32274259,"uuid":"35848897","full_name":"remarkjs/react-markdown","owner":"remarkjs","description":"Markdown component for React","archived":false,"fork":false,"pushed_at":"2025-04-21T10:10:50.000Z","size":2071,"stargazers_count":14227,"open_issues_count":2,"forks_count":907,"subscribers_count":56,"default_branch":"main","last_synced_at":"2025-05-05T15:48:04.472Z","etag":null,"topics":["commonmark","gfm","markdown","react","remark"],"latest_commit_sha":null,"homepage":"https://remarkjs.github.io/react-markdown/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/remarkjs.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"unifiedjs","open_collective":"unified"}},"created_at":"2015-05-18T23:59:17.000Z","updated_at":"2025-05-05T10:00:29.000Z","dependencies_parsed_at":"2023-02-10T11:32:46.017Z","dependency_job_id":"2f8cd69f-efc5-4429-9b13-693caf52afbd","html_url":"https://github.com/remarkjs/react-markdown","commit_stats":{"total_commits":534,"total_committers":72,"mean_commits":7.416666666666667,"dds":0.5149812734082397,"last_synced_commit":"aed001070aae99bc6d1f3bdd8e71974f5c0d5f10"},"previous_names":["rexxars/react-markdown"],"tags_count":82,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkjs%2Freact-markdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkjs%2Freact-markdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkjs%2Freact-markdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkjs%2Freact-markdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/remarkjs","download_url":"https://codeload.github.com/remarkjs/react-markdown/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253655898,"owners_count":21943069,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commonmark","gfm","markdown","react","remark"],"created_at":"2024-07-30T19:01:35.721Z","updated_at":"2025-05-12T18:20:59.335Z","avatar_url":"https://github.com/remarkjs.png","language":"JavaScript","readme":"\u003c!--\n  Notes for maintaining this document:\n\n  * update the version of the link for `commonmark-html` once in a while\n--\u003e\n\n# react-markdown\n\n[![Build][badge-build-image]][badge-build-url]\n[![Coverage][badge-coverage-image]][badge-coverage-url]\n[![Downloads][badge-downloads-image]][badge-downloads-url]\n[![Size][badge-size-image]][badge-size-url]\n\nReact component to render markdown.\n\n## Feature highlights\n\n* [x] **[safe][section-security] by default**\n  (no `dangerouslySetInnerHTML` or XSS attacks)\n* [x] **[components][section-components]**\n  (pass your own component to use instead of `\u003ch2\u003e` for `## hi`)\n* [x] **[plugins][section-plugins]**\n  (many plugins you can pick and choose from)\n* [x] **[compliant][section-syntax]**\n  (100% to CommonMark, 100% to GFM with a plugin)\n\n## Contents\n\n* [What is this?](#what-is-this)\n* [When should I use this?](#when-should-i-use-this)\n* [Install](#install)\n* [Use](#use)\n* [API](#api)\n  * [`Markdown`](#markdown)\n  * [`MarkdownAsync`](#markdownasync)\n  * [`MarkdownHooks`](#markdownhooks)\n  * [`defaultUrlTransform(url)`](#defaulturltransformurl)\n  * [`AllowElement`](#allowelement)\n  * [`Components`](#components)\n  * [`ExtraProps`](#extraprops)\n  * [`HooksOptions`](#hooksoptions)\n  * [`Options`](#options)\n  * [`UrlTransform`](#urltransform)\n* [Examples](#examples)\n  * [Use a plugin](#use-a-plugin)\n  * [Use a plugin with options](#use-a-plugin-with-options)\n  * [Use custom components (syntax highlight)](#use-custom-components-syntax-highlight)\n  * [Use remark and rehype plugins (math)](#use-remark-and-rehype-plugins-math)\n* [Plugins](#plugins)\n* [Syntax](#syntax)\n* [Compatibility](#compatibility)\n* [Architecture](#architecture)\n* [Appendix A: HTML in markdown](#appendix-a-html-in-markdown)\n* [Appendix B: Components](#appendix-b-components)\n* [Appendix C: line endings in markdown (and JSX)](#appendix-c-line-endings-in-markdown-and-jsx)\n* [Security](#security)\n* [Related](#related)\n* [Contribute](#contribute)\n* [License](#license)\n\n## What is this?\n\nThis package is a [React][] component that can be given a string of markdown\nthat it’ll safely render to React elements.\nYou can pass plugins to change how markdown is transformed and pass components\nthat will be used instead of normal HTML elements.\n\n* to learn markdown, see this [cheatsheet and tutorial][commonmark-help]\n* to try out `react-markdown`, see [our demo][github-io-react-markdown]\n\n## When should I use this?\n\nThere are other ways to use markdown in React out there so why use this one?\nThe three main reasons are that they often rely on `dangerouslySetInnerHTML`,\nhave bugs with how they handle markdown, or don’t let you swap elements for\ncomponents.\n`react-markdown` builds a virtual DOM, so React only replaces what changed,\nfrom a syntax tree.\nThat’s supported because we use [unified][github-unified],\nspecifically [remark][github-remark] for markdown and [rehype][github-rehype]\nfor HTML,\nwhich are popular tools to transform content with plugins.\n\nThis package focusses on making it easy for beginners to safely use markdown in\nReact.\nWhen you’re familiar with unified, you can use a modern hooks based alternative\n[`react-remark`][github-react-remark] or [`rehype-react`][github-rehype-react]\nmanually.\nIf you instead want to use JavaScript and JSX *inside* markdown files, use\n[MDX][github-mdx].\n\n## Install\n\nThis package is [ESM only][esm].\nIn Node.js (version 16+), install with [npm][npm-install]:\n\n```sh\nnpm install react-markdown\n```\n\nIn Deno with [`esm.sh`][esmsh]:\n\n```js\nimport Markdown from 'https://esm.sh/react-markdown@10'\n```\n\nIn browsers with [`esm.sh`][esmsh]:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import Markdown from 'https://esm.sh/react-markdown@10?bundle'\n\u003c/script\u003e\n```\n\n## Use\n\nA basic hello world:\n\n```js\nimport React from 'react'\nimport {createRoot} from 'react-dom/client'\nimport Markdown from 'react-markdown'\n\nconst markdown = '# Hi, *Pluto*!'\n\ncreateRoot(document.body).render(\u003cMarkdown\u003e{markdown}\u003c/Markdown\u003e)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eShow equivalent JSX\u003c/summary\u003e\n\n```js\n\u003ch1\u003e\n  Hi, \u003cem\u003ePluto\u003c/em\u003e!\n\u003c/h1\u003e\n```\n\n\u003c/details\u003e\n\nHere is an example that shows how to use a plugin\n([`remark-gfm`][github-remark-gfm],\nwhich adds support for footnotes, strikethrough, tables, tasklists and\nURLs directly):\n\n```js\nimport React from 'react'\nimport {createRoot} from 'react-dom/client'\nimport Markdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nconst markdown = `Just a link: www.nasa.gov.`\n\ncreateRoot(document.body).render(\n  \u003cMarkdown remarkPlugins={[remarkGfm]}\u003e{markdown}\u003c/Markdown\u003e\n)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eShow equivalent JSX\u003c/summary\u003e\n\n```js\n\u003cp\u003e\n  Just a link: \u003ca href=\"http://www.nasa.gov\"\u003ewww.nasa.gov\u003c/a\u003e.\n\u003c/p\u003e\n```\n\n\u003c/details\u003e\n\n## API\n\nThis package exports the identifiers\n[`MarkdownAsync`][api-markdown-async],\n[`MarkdownHooks`][api-markdown-hooks],\nand\n[`defaultUrlTransform`][api-default-url-transform].\nThe default export is [`Markdown`][api-markdown].\n\nIt also exports the additional [TypeScript][] types\n[`AllowElement`][api-allow-element],\n[`Components`][api-components],\n[`ExtraProps`][api-extra-props],\n[`HooksOptions`][api-hooks-options],\n[`Options`][api-options],\nand\n[`UrlTransform`][api-url-transform].\n\n### `Markdown`\n\nComponent to render markdown.\n\nThis is a synchronous component.\nWhen using async plugins,\nsee [`MarkdownAsync`][api-markdown-async] or\n[`MarkdownHooks`][api-markdown-hooks].\n\n###### Parameters\n\n* `options` ([`Options`][api-options])\n  — props\n\n###### Returns\n\nReact element (`ReactElement`).\n\n### `MarkdownAsync`\n\nComponent to render markdown with support for async plugins\nthrough async/await.\n\nComponents returning promises are supported on the server.\nFor async support on the client,\nsee [`MarkdownHooks`][api-markdown-hooks].\n\n###### Parameters\n\n* `options` ([`Options`][api-options])\n  — props\n\n###### Returns\n\nPromise to a React element (`Promise\u003cReactElement\u003e`).\n\n### `MarkdownHooks`\n\nComponent to render markdown with support for async plugins through hooks.\n\nThis uses `useEffect` and `useState` hooks.\nHooks run on the client and do not immediately render something.\nFor async support on the server,\nsee [`MarkdownAsync`][api-markdown-async].\n\n###### Parameters\n\n* `options` ([`Options`][api-options])\n  — props\n\n###### Returns\n\nReact node (`ReactNode`).\n\n### `defaultUrlTransform(url)`\n\nMake a URL safe.\n\nThis follows how GitHub works.\nIt allows the protocols `http`, `https`, `irc`, `ircs`, `mailto`, and `xmpp`,\nand URLs relative to the current protocol (such as `/something`).\n\n###### Parameters\n\n* `url` (`string`)\n  — URL\n\n###### Returns\n\nSafe URL (`string`).\n\n### `AllowElement`\n\nFilter elements (TypeScript type).\n\n###### Parameters\n\n* `node` ([`Element` from `hast`][github-hast-element])\n  — element to check\n* `index` (`number | undefined`)\n  — index of `element` in `parent`\n* `parent` ([`Node` from `hast`][github-hast-nodes])\n  — parent of `element`\n\n###### Returns\n\nWhether to allow `element` (`boolean`, optional).\n\n### `Components`\n\nMap tag names to components (TypeScript type).\n\n###### Type\n\n```ts\nimport type {ExtraProps} from 'react-markdown'\nimport type {ComponentProps, ElementType} from 'react'\n\ntype Components = {\n  [Key in Extract\u003cElementType, string\u003e]?: ElementType\u003cComponentProps\u003cKey\u003e \u0026 ExtraProps\u003e\n}\n```\n\n### `ExtraProps`\n\nExtra fields we pass to components (TypeScript type).\n\n###### Fields\n\n* `node` ([`Element` from `hast`][github-hast-element], optional)\n  — original node\n\n### `HooksOptions`\n\nConfiguration for [`MarkdownHooks`][api-markdown-hooks] (TypeScript type);\nextends the regular [`Options`][api-options] with a `fallback` prop.\n\n###### Extends\n\n[`Options`][api-options].\n\n###### Fields\n\n* `fallback` (`ReactNode`, optional)\n  — content to render while the processor processing the markdown\n\n### `Options`\n\nConfiguration (TypeScript type).\n\n###### Fields\n\n* `allowElement` ([`AllowElement`][api-allow-element], optional)\n  — filter elements;\n  `allowedElements` / `disallowedElements` is used first\n* `allowedElements` (`Array\u003cstring\u003e`, default: all tag names)\n  — tag names to allow;\n  cannot combine w/ `disallowedElements`\n* `children` (`string`, optional)\n  — markdown\n* `components` ([`Components`][api-components], optional)\n  — map tag names to components\n* `disallowedElements` (`Array\u003cstring\u003e`, default: `[]`)\n  — tag names to disallow;\n  cannot combine w/ `allowedElements`\n* `rehypePlugins` (`Array\u003cPlugin\u003e`, optional)\n  — list of [rehype plugins][github-rehype-plugins] to use\n* `remarkPlugins` (`Array\u003cPlugin\u003e`, optional)\n  — list of [remark plugins][github-remark-plugins] to use\n* `remarkRehypeOptions`\n  ([`Options` from `remark-rehype`][github-remark-rehype-options],\n  optional)\n  — options to pass through to `remark-rehype`\n* `skipHtml` (`boolean`, default: `false`)\n  — ignore HTML in markdown completely\n* `unwrapDisallowed` (`boolean`, default: `false`)\n  — extract (unwrap) what’s in disallowed elements;\n  normally when say `strong` is not allowed, it and it’s children are dropped,\n  with `unwrapDisallowed` the element itself is replaced by its children\n* `urlTransform` ([`UrlTransform`][api-url-transform], default:\n  [`defaultUrlTransform`][api-default-url-transform])\n  — change URLs\n\n### `UrlTransform`\n\nTransform URLs (TypeScript type).\n\n###### Parameters\n\n* `url` (`string`)\n  — URL\n* `key` (`string`, example: `'href'`)\n  — property name\n* `node` ([`Element` from `hast`][github-hast-element])\n  — element to check\n\n###### Returns\n\nTransformed URL (`string`, optional).\n\n## Examples\n\n### Use a plugin\n\nThis example shows how to use a remark plugin.\nIn this case, [`remark-gfm`][github-remark-gfm],\nwhich adds support for strikethrough, tables, tasklists and URLs directly:\n\n```js\nimport React from 'react'\nimport {createRoot} from 'react-dom/client'\nimport Markdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nconst markdown = `A paragraph with *emphasis* and **strong importance**.\n\n\u003e A block quote with ~strikethrough~ and a URL: https://reactjs.org.\n\n* Lists\n* [ ] todo\n* [x] done\n\nA table:\n\n| a | b |\n| - | - |\n`\n\ncreateRoot(document.body).render(\n  \u003cMarkdown remarkPlugins={[remarkGfm]}\u003e{markdown}\u003c/Markdown\u003e\n)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eShow equivalent JSX\u003c/summary\u003e\n\n```js\n\u003c\u003e\n  \u003cp\u003e\n    A paragraph with \u003cem\u003eemphasis\u003c/em\u003e and \u003cstrong\u003estrong importance\u003c/strong\u003e.\n  \u003c/p\u003e\n  \u003cblockquote\u003e\n    \u003cp\u003e\n      A block quote with \u003cdel\u003estrikethrough\u003c/del\u003e and a URL:{' '}\n      \u003ca href=\"https://reactjs.org\"\u003ehttps://reactjs.org\u003c/a\u003e.\n    \u003c/p\u003e\n  \u003c/blockquote\u003e\n  \u003cul className=\"contains-task-list\"\u003e\n    \u003cli\u003eLists\u003c/li\u003e\n    \u003cli className=\"task-list-item\"\u003e\n      \u003cinput type=\"checkbox\" disabled /\u003e todo\n    \u003c/li\u003e\n    \u003cli className=\"task-list-item\"\u003e\n      \u003cinput type=\"checkbox\" disabled checked /\u003e done\n    \u003c/li\u003e\n  \u003c/ul\u003e\n  \u003cp\u003eA table:\u003c/p\u003e\n  \u003ctable\u003e\n    \u003cthead\u003e\n      \u003ctr\u003e\n        \u003cth\u003ea\u003c/th\u003e\n        \u003cth\u003eb\u003c/th\u003e\n      \u003c/tr\u003e\n    \u003c/thead\u003e\n  \u003c/table\u003e\n\u003c/\u003e\n```\n\n\u003c/details\u003e\n\n### Use a plugin with options\n\nThis example shows how to use a plugin and give it options.\nTo do that, use an array with the plugin at the first place, and the options\nsecond.\n[`remark-gfm`][github-remark-gfm] has an option to allow only double tildes for\nstrikethrough:\n\n```js\nimport React from 'react'\nimport {createRoot} from 'react-dom/client'\nimport Markdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nconst markdown = 'This ~is not~ strikethrough, but ~~this is~~!'\n\ncreateRoot(document.body).render(\n  \u003cMarkdown remarkPlugins={[[remarkGfm, {singleTilde: false}]]}\u003e\n    {markdown}\n  \u003c/Markdown\u003e\n)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eShow equivalent JSX\u003c/summary\u003e\n\n```js\n\u003cp\u003e\n  This ~is not~ strikethrough, but \u003cdel\u003ethis is\u003c/del\u003e!\n\u003c/p\u003e\n```\n\n\u003c/details\u003e\n\n### Use custom components (syntax highlight)\n\nThis example shows how you can overwrite the normal handling of an element by\npassing a component.\nIn this case, we apply syntax highlighting with the seriously super amazing\n[`react-syntax-highlighter`][github-react-syntax-highlighter] by\n[**@conorhastings**][github-conorhastings]:\n\n\u003c!-- To do: currently broken on actual ESM; let’s find an alternative? --\u003e\n\n```js\nimport React from 'react'\nimport {createRoot} from 'react-dom/client'\nimport Markdown from 'react-markdown'\nimport {Prism as SyntaxHighlighter} from 'react-syntax-highlighter'\nimport {dark} from 'react-syntax-highlighter/dist/esm/styles/prism'\n\n// Did you know you can use tildes instead of backticks for code in markdown? ✨\nconst markdown = `Here is some JavaScript code:\n\n~~~js\nconsole.log('It works!')\n~~~\n`\n\ncreateRoot(document.body).render(\n  \u003cMarkdown\n    children={markdown}\n    components={{\n      code(props) {\n        const {children, className, node, ...rest} = props\n        const match = /language-(\\w+)/.exec(className || '')\n        return match ? (\n          \u003cSyntaxHighlighter\n            {...rest}\n            PreTag=\"div\"\n            children={String(children).replace(/\\n$/, '')}\n            language={match[1]}\n            style={dark}\n          /\u003e\n        ) : (\n          \u003ccode {...rest} className={className}\u003e\n            {children}\n          \u003c/code\u003e\n        )\n      }\n    }}\n  /\u003e\n)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eShow equivalent JSX\u003c/summary\u003e\n\n```js\n\u003c\u003e\n  \u003cp\u003eHere is some JavaScript code:\u003c/p\u003e\n  \u003cpre\u003e\n    \u003cSyntaxHighlighter language=\"js\" style={dark} PreTag=\"div\" children=\"console.log('It works!')\" /\u003e\n  \u003c/pre\u003e\n\u003c/\u003e\n```\n\n\u003c/details\u003e\n\n### Use remark and rehype plugins (math)\n\nThis example shows how a syntax extension\n(through [`remark-math`][github-remark-math])\nis used to support math in markdown, and a transform plugin\n([`rehype-katex`][github-rehype-katex]) to render that math.\n\n```js\nimport React from 'react'\nimport {createRoot} from 'react-dom/client'\nimport Markdown from 'react-markdown'\nimport rehypeKatex from 'rehype-katex'\nimport remarkMath from 'remark-math'\nimport 'katex/dist/katex.min.css' // `rehype-katex` does not import the CSS for you\n\nconst markdown = `The lift coefficient ($C_L$) is a dimensionless coefficient.`\n\ncreateRoot(document.body).render(\n  \u003cMarkdown remarkPlugins={[remarkMath]} rehypePlugins={[rehypeKatex]}\u003e\n    {markdown}\n  \u003c/Markdown\u003e\n)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eShow equivalent JSX\u003c/summary\u003e\n\n```js\n\u003cp\u003e\n  The lift coefficient (\n  \u003cspan className=\"katex\"\u003e\n    \u003cspan className=\"katex-mathml\"\u003e\n      \u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e{/* … */}\u003c/math\u003e\n    \u003c/span\u003e\n    \u003cspan className=\"katex-html\" aria-hidden=\"true\"\u003e\n      {/* … */}\n    \u003c/span\u003e\n  \u003c/span\u003e\n  ) is a dimensionless coefficient.\n\u003c/p\u003e\n```\n\n\u003c/details\u003e\n\n## Plugins\n\nWe use [unified][github-unified],\nspecifically [remark][github-remark] for markdown and\n[rehype][github-rehype] for HTML,\nwhich are tools to transform content with plugins.\nHere are three good ways to find plugins:\n\n* [`awesome-remark`][github-awesome-remark] and\n  [`awesome-rehype`][github-awesome-rehype]\n  — selection of the most awesome projects\n* [List of remark plugins][github-remark-plugins] and\n  [list of rehype plugins][github-rehype-plugins]\n  — list of all plugins\n* [`remark-plugin`][github-topic-remark-plugin] and\n  [`rehype-plugin`][github-topic-rehype-plugin] topics\n  — any tagged repo on GitHub\n\n## Syntax\n\n`react-markdown` follows CommonMark, which standardizes the differences between\nmarkdown implementations, by default.\nSome syntax extensions are supported through plugins.\n\nWe use [`micromark`][github-micromark] under the hood for our parsing.\nSee its documentation for more information on markdown, CommonMark, and\nextensions.\n\n## Compatibility\n\nProjects maintained by the unified collective are compatible with maintained\nversions of Node.js.\n\nWhen we cut a new major release, we drop support for unmaintained versions of\nNode.\nThis means we try to keep the current release line, `react-markdown@10`,\ncompatible with Node.js 16.\n\nThey work in all modern browsers (essentially: everything not IE 11).\nYou can use a bundler (such as esbuild, webpack, or Rollup) to use this package\nin your project, and use its options (or plugins) to add support for legacy\nbrowsers.\n\n## Architecture\n\n\u003cpre\u003e\u003ccode\u003e                                                           react-markdown\n         +----------------------------------------------------------------------------------------------------------------+\n         |                                                                                                                |\n         |  +----------+        +----------------+        +---------------+       +----------------+       +------------+ |\n         |  |          |        |                |        |               |       |                |       |            | |\n\u003ca href=\"https://commonmark.org\"\u003emarkdown\u003c/a\u003e-+-\u003e+  \u003ca href=\"https://github.com/remarkjs/remark\"\u003eremark\u003c/a\u003e  +-\u003ca href=\"https://github.com/syntax-tree/mdast\"\u003emdast\u003c/a\u003e-\u003e+ \u003ca href=\"https://github.com/remarkjs/remark/blob/main/doc/plugins.md\"\u003eremark plugins\u003c/a\u003e +-\u003ca href=\"https://github.com/syntax-tree/mdast\"\u003emdast\u003c/a\u003e-\u003e+ \u003ca href=\"https://github.com/remarkjs/remark-rehype\"\u003eremark-rehype\u003c/a\u003e +-\u003ca href=\"https://github.com/syntax-tree/hast\"\u003ehast\u003c/a\u003e-\u003e+ \u003ca href=\"https://github.com/rehypejs/rehype/blob/main/doc/plugins.md\"\u003erehype plugins\u003c/a\u003e +-\u003ca href=\"https://github.com/syntax-tree/hast\"\u003ehast\u003c/a\u003e-\u003e+ \u003ca href=\"#appendix-b-components\"\u003ecomponents\u003c/a\u003e +-+-\u003ereact elements\n         |  |          |        |                |        |               |       |                |       |            | |\n         |  +----------+        +----------------+        +---------------+       +----------------+       +------------+ |\n         |                                                                                                                |\n         +----------------------------------------------------------------------------------------------------------------+\n\u003c/code\u003e\u003c/pre\u003e\n\nTo understand what this project does, it’s important to first understand what\nunified does: please read through the [`unifiedjs/unified`][github-unified]\nreadme\n(the part until you hit the API section is required reading).\n\n`react-markdown` is a unified pipeline — wrapped so that most folks don’t need\nto directly interact with unified.\nThe processor goes through these steps:\n\n* parse markdown to mdast (markdown syntax tree)\n* transform through remark (markdown ecosystem)\n* transform mdast to hast (HTML syntax tree)\n* transform through rehype (HTML ecosystem)\n* render hast to React with components\n\n## Appendix A: HTML in markdown\n\n`react-markdown` typically escapes HTML (or ignores it, with `skipHtml`)\nbecause it is dangerous and defeats the purpose of this library.\n\nHowever, if you are in a trusted environment (you trust the markdown), and\ncan spare the bundle size (±60kb minzipped), then you can use\n[`rehype-raw`][github-rehype-raw]:\n\n```js\nimport React from 'react'\nimport {createRoot} from 'react-dom/client'\nimport Markdown from 'react-markdown'\nimport rehypeRaw from 'rehype-raw'\n\nconst markdown = `\u003cdiv class=\"note\"\u003e\n\nSome *emphasis* and \u003cstrong\u003estrong\u003c/strong\u003e!\n\n\u003c/div\u003e`\n\ncreateRoot(document.body).render(\n  \u003cMarkdown rehypePlugins={[rehypeRaw]}\u003e{markdown}\u003c/Markdown\u003e\n)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eShow equivalent JSX\u003c/summary\u003e\n\n```js\n\u003cdiv className=\"note\"\u003e\n  \u003cp\u003e\n    Some \u003cem\u003eemphasis\u003c/em\u003e and \u003cstrong\u003estrong\u003c/strong\u003e!\n  \u003c/p\u003e\n\u003c/div\u003e\n```\n\n\u003c/details\u003e\n\n**Note**: HTML in markdown is still bound by how [HTML works in\nCommonMark][commonmark-html].\nMake sure to use blank lines around block-level HTML that again contains\nmarkdown!\n\n## Appendix B: Components\n\nYou can also change the things that come from markdown:\n\n```js\n\u003cMarkdown\n  components={{\n    // Map `h1` (`# heading`) to use `h2`s.\n    h1: 'h2',\n    // Rewrite `em`s (`*like so*`) to `i` with a red foreground color.\n    em(props) {\n      const {node, ...rest} = props\n      return \u003ci style={{color: 'red'}} {...rest} /\u003e\n    }\n  }}\n/\u003e\n```\n\nThe keys in components are HTML equivalents for the things you write with\nmarkdown (such as `h1` for `# heading`).\nNormally, in markdown, those are: `a`, `blockquote`, `br`, `code`, `em`, `h1`,\n`h2`, `h3`, `h4`, `h5`, `h6`, `hr`, `img`, `li`, `ol`, `p`, `pre`, `strong`, and\n`ul`.\nWith [`remark-gfm`][github-remark-gfm],\nyou can also use `del`, `input`, `table`, `tbody`, `td`, `th`, `thead`, and `tr`.\nOther remark or rehype plugins that add support for new constructs will also\nwork with `react-markdown`.\n\nThe props that are passed are what you probably would expect: an `a` (link) will\nget `href` (and `title`) props, and `img` (image) an `src`, `alt` and `title`,\netc.\n\nEvery component will receive a `node`.\nThis is the original [`Element` from `hast`][github-hast-element] element being\nturned into a React element.\n\n## Appendix C: line endings in markdown (and JSX)\n\nYou might have trouble with how line endings work in markdown and JSX.\nWe recommend the following, which solves all line ending problems:\n\n```js\n// If you write actual markdown in your code, put your markdown in a variable;\n// **do not indent markdown**:\nconst markdown = `\n# This is perfect!\n`\n\n// Pass the value as an expression as an only child:\nconst result = \u003cMarkdown\u003e{markdown}\u003c/Markdown\u003e\n```\n\n👆 That works.\nRead on for what doesn’t and why that is.\n\nYou might try to write markdown directly in your JSX and find that it **does\nnot** work:\n\n```js\n\u003cMarkdown\u003e\n  # Hi\n\n  This is **not** a paragraph.\n\u003c/Markdown\u003e\n```\n\nThe is because in JSX the whitespace (including line endings) is collapsed to\na single space.\nSo the above example is equivalent to:\n\n```js\n\u003cMarkdown\u003e # Hi This is **not** a paragraph. \u003c/Markdown\u003e\n```\n\nInstead, to pass markdown to `Markdown`, you can use an expression:\nwith a template literal:\n\n```js\n\u003cMarkdown\u003e{`\n# Hi\n\nThis is a paragraph.\n`}\u003c/Markdown\u003e\n```\n\nTemplate literals have another potential problem, because they keep whitespace\n(including indentation) inside them.\nThat means that the following **does not** turn into a heading:\n\n```js\n\u003cMarkdown\u003e{`\n    # This is **not** a heading, it’s an indented code block\n`}\u003c/Markdown\u003e\n```\n\n## Security\n\nUse of `react-markdown` is secure by default.\nOverwriting `urlTransform` to something insecure will open you up to XSS\nvectors.\nFurthermore, the `remarkPlugins`, `rehypePlugins`, and `components` you use may\nbe insecure.\n\nTo make sure the content is completely safe, even after what plugins do,\nuse [`rehype-sanitize`][github-rehype-sanitize].\nIt lets you define your own schema of what is and isn’t allowed.\n\n## Related\n\n* [`MDX`][github-mdx]\n  — JSX *in* markdown\n* [`remark-gfm`][github-remark-gfm]\n  — add support for GitHub flavored markdown support\n* [`react-remark`][github-react-remark]\n  — hook based alternative\n* [`rehype-react`][github-rehype-react]\n  — turn HTML into React elements\n\n## Contribute\n\nSee [`contributing.md`][health-contributing] in [`remarkjs/.github`][health]\nfor ways to get started.\nSee [`support.md`][health-support] for ways to get help.\n\nThis project has a [code of conduct][health-coc].\nBy interacting with this repository, organization, or community you agree to\nabide by its terms.\n\n## License\n\n[MIT][file-license] © [Espen Hovlandsdal][author]\n\n[api-allow-element]: #allowelement\n\n[api-components]: #components\n\n[api-default-url-transform]: #defaulturltransformurl\n\n[api-extra-props]: #extraprops\n\n[api-hooks-options]: #hooksoptions\n\n[api-markdown]: #markdown\n\n[api-markdown-async]: #markdownasync\n\n[api-markdown-hooks]: #markdownhooks\n\n[api-options]: #options\n\n[api-url-transform]: #urltransform\n\n[author]: https://espen.codes/\n\n[badge-build-image]: https://github.com/remarkjs/react-markdown/workflows/main/badge.svg\n\n[badge-build-url]: https://github.com/remarkjs/react-markdown/actions\n\n[badge-coverage-image]: https://img.shields.io/codecov/c/github/remarkjs/react-markdown.svg\n\n[badge-coverage-url]: https://codecov.io/github/remarkjs/react-markdown\n\n[badge-downloads-image]: https://img.shields.io/npm/dm/react-markdown.svg\n\n[badge-downloads-url]: https://www.npmjs.com/package/react-markdown\n\n[badge-size-image]: https://img.shields.io/bundlejs/size/react-markdown\n\n[badge-size-url]: https://bundlejs.com/?q=react-markdown\n\n[commonmark-help]: https://commonmark.org/help/\n\n[commonmark-html]: https://spec.commonmark.org/0.31.2/#html-blocks\n\n[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n\n[esmsh]: https://esm.sh\n\n[file-license]: license\n\n[github-awesome-rehype]: https://github.com/rehypejs/awesome-rehype\n\n[github-awesome-remark]: https://github.com/remarkjs/awesome-remark\n\n[github-conorhastings]: https://github.com/conorhastings\n\n[github-hast-element]: https://github.com/syntax-tree/hast#element\n\n[github-hast-nodes]: https://github.com/syntax-tree/hast#nodes\n\n[github-io-react-markdown]: https://remarkjs.github.io/react-markdown/\n\n[github-mdx]: https://github.com/mdx-js/mdx/\n\n[github-micromark]: https://github.com/micromark/micromark\n\n[github-react-remark]: https://github.com/remarkjs/react-remark\n\n[github-react-syntax-highlighter]: https://github.com/react-syntax-highlighter/react-syntax-highlighter\n\n[github-rehype]: https://github.com/rehypejs/rehype\n\n[github-rehype-katex]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex\n\n[github-rehype-plugins]: https://github.com/rehypejs/rehype/blob/main/doc/plugins.md#list-of-plugins\n\n[github-rehype-raw]: https://github.com/rehypejs/rehype-raw\n\n[github-rehype-react]: https://github.com/rehypejs/rehype-react\n\n[github-rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize\n\n[github-remark]: https://github.com/remarkjs/remark\n\n[github-remark-gfm]: https://github.com/remarkjs/remark-gfm\n\n[github-remark-math]: https://github.com/remarkjs/remark-math\n\n[github-remark-plugins]: https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins\n\n[github-remark-rehype-options]: https://github.com/remarkjs/remark-rehype#options\n\n[github-topic-rehype-plugin]: https://github.com/topics/rehype-plugin\n\n[github-topic-remark-plugin]: https://github.com/topics/remark-plugin\n\n[github-unified]: https://github.com/unifiedjs/unified\n\n[health]: https://github.com/remarkjs/.github\n\n[health-coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md\n\n[health-contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md\n\n[health-support]: https://github.com/remarkjs/.github/blob/main/support.md\n\n[npm-install]: https://docs.npmjs.com/cli/install\n\n[react]: http://reactjs.org\n\n[section-components]: #appendix-b-components\n\n[section-plugins]: #plugins\n\n[section-security]: #security\n\n[section-syntax]: #syntax\n\n[typescript]: https://www.typescriptlang.org\n","funding_links":["https://github.com/sponsors/unifiedjs","https://opencollective.com/unified"],"categories":["Other Components","JavaScript","Markdown editor","前端常见效果库","语言资源库","前端开发框架及项目","markdown","react","Built on remark","UI Components / UI Tools"],"sub_categories":["代码高亮","JavaScript","其他_文本生成、文本对话"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremarkjs%2Freact-markdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fremarkjs%2Freact-markdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremarkjs%2Freact-markdown/lists"}