react-markdown
Advanced tools
Comparing version 8.0.7 to 9.0.0
@@ -1,4 +0,6 @@ | ||
export {uriTransformer} from './lib/uri-transformer.js' | ||
export {ReactMarkdown as default} from './lib/react-markdown.js' | ||
export type Options = import('./lib/react-markdown.js').ReactMarkdownOptions | ||
export type Components = import('./lib/ast-to-react.js').Components | ||
export type ExtraProps = import('hast-util-to-jsx-runtime').ExtraProps; | ||
export type AllowElement = import('./lib/index.js').AllowElement; | ||
export type Components = import('./lib/index.js').Components; | ||
export type Options = import('./lib/index.js').Options; | ||
export type UrlTransform = import('./lib/index.js').UrlTransform; | ||
export { Markdown as default, defaultUrlTransform } from "./lib/index.js"; |
11
index.js
/** | ||
* @typedef {import('./lib/react-markdown.js').ReactMarkdownOptions} Options | ||
* @typedef {import('./lib/ast-to-react.js').Components} Components | ||
* @typedef {import('hast-util-to-jsx-runtime').ExtraProps} ExtraProps | ||
* @typedef {import('./lib/index.js').AllowElement} AllowElement | ||
* @typedef {import('./lib/index.js').Components} Components | ||
* @typedef {import('./lib/index.js').Options} Options | ||
* @typedef {import('./lib/index.js').UrlTransform} UrlTransform | ||
*/ | ||
export {uriTransformer} from './lib/uri-transformer.js' | ||
export {ReactMarkdown as default} from './lib/react-markdown.js' | ||
export {Markdown as default, defaultUrlTransform} from './lib/index.js' |
134
package.json
{ | ||
"name": "react-markdown", | ||
"version": "8.0.7", | ||
"version": "9.0.0", | ||
"description": "React component to render markdown", | ||
"license": "MIT", | ||
"keywords": [ | ||
"remark", | ||
"unified", | ||
"markdown", | ||
"ast", | ||
"commonmark", | ||
"component", | ||
"gfm", | ||
"ast", | ||
"markdown", | ||
"react", | ||
"react-component", | ||
"component" | ||
"remark", | ||
"unified" | ||
], | ||
@@ -72,64 +72,60 @@ "repository": "remarkjs/react-markdown", | ||
"type": "module", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"unpkg": "react-markdown.min.js", | ||
"exports": "./index.js", | ||
"files": [ | ||
"lib/", | ||
"index.d.ts", | ||
"index.js", | ||
"react-markdown.min.js" | ||
"index.js" | ||
], | ||
"dependencies": { | ||
"@types/hast": "^2.0.0", | ||
"@types/prop-types": "^15.0.0", | ||
"@types/unist": "^2.0.0", | ||
"comma-separated-tokens": "^2.0.0", | ||
"hast-util-whitespace": "^2.0.0", | ||
"prop-types": "^15.0.0", | ||
"property-information": "^6.0.0", | ||
"react-is": "^18.0.0", | ||
"remark-parse": "^10.0.0", | ||
"remark-rehype": "^10.0.0", | ||
"space-separated-tokens": "^2.0.0", | ||
"style-to-object": "^0.4.0", | ||
"unified": "^10.0.0", | ||
"unist-util-visit": "^4.0.0", | ||
"vfile": "^5.0.0" | ||
"@types/hast": "^3.0.0", | ||
"devlop": "^1.0.0", | ||
"hast-util-to-jsx-runtime": "^2.0.0", | ||
"html-url-attributes": "^3.0.0", | ||
"mdast-util-to-hast": "^13.0.0", | ||
"micromark-util-sanitize-uri": "^2.0.0", | ||
"remark-parse": "^11.0.0", | ||
"remark-rehype": "^11.0.0", | ||
"unified": "^11.0.0", | ||
"unist-util-visit": "^5.0.0", | ||
"vfile": "^6.0.0" | ||
}, | ||
"peerDependencies": { | ||
"@types/react": ">=16", | ||
"react": ">=16" | ||
"@types/react": ">=18", | ||
"react": ">=18" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^18.0.0", | ||
"@types/node": "^20.0.0", | ||
"@types/react": "^18.0.0", | ||
"@types/react-dom": "^18.0.0", | ||
"@types/react-is": "^17.0.0", | ||
"c8": "^7.0.0", | ||
"esbuild": "^0.17.0", | ||
"eslint-config-xo-react": "^0.27.0", | ||
"eslint-plugin-es": "^4.0.0", | ||
"c8": "^8.0.0", | ||
"esbuild": "^0.19.0", | ||
"eslint-plugin-react": "^7.0.0", | ||
"eslint-plugin-react-hooks": "^4.0.0", | ||
"eslint-plugin-security": "^1.0.0", | ||
"prettier": "^2.0.0", | ||
"prettier": "^3.0.0", | ||
"react": "^18.0.0", | ||
"react-dom": "^18.0.0", | ||
"rehype-raw": "^6.0.0", | ||
"rehype-raw": "^7.0.0", | ||
"remark-cli": "^11.0.0", | ||
"remark-gfm": "^3.0.0", | ||
"remark-gfm": "^4.0.0", | ||
"remark-preset-wooorm": "^9.0.0", | ||
"remark-toc": "^8.0.0", | ||
"remark-toc": "^9.0.0", | ||
"type-coverage": "^2.0.0", | ||
"typescript": "^5.0.0", | ||
"xo": "^0.54.0" | ||
"xo": "^0.56.0" | ||
}, | ||
"scripts": { | ||
"build": "tsc --build --clean && tsc --build && type-coverage", | ||
"format": "remark . --frail --output --quiet && prettier . --log-level warn --write && xo --fix", | ||
"prepack": "npm run build && npm run format", | ||
"build": "tsc --build --clean && tsc --build && type-coverage && esbuild index.js --bundle --minify --target=es2015 --outfile=react-markdown.min.js --global-name=ReactMarkdown --banner:js=\"(function (g, f) {typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = f() : typeof define === 'function' && define.amd ? define([], f) : (g = typeof globalThis !== 'undefined' ? globalThis : g || self, g.ReactMarkdown = f()); }(this, (function () { 'use strict';\" --footer:js=\"return ReactMarkdown;})));\"", | ||
"format": "remark . -qfo --ignore-pattern test/ && prettier . -w --loglevel warn && xo --fix", | ||
"test-api": "node --no-warnings --experimental-loader=./test/loader.js --conditions development test/test.jsx", | ||
"test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api", | ||
"test": "npm run build && npm run format && npm run test-coverage" | ||
"test": "npm run build && npm run format && npm run test-coverage", | ||
"test-api": "node --conditions development --experimental-loader=./script/load-jsx.js --no-warnings test.jsx", | ||
"test-coverage": "c8 --100 --exclude script/ --reporter lcov npm run test-api" | ||
}, | ||
"prettier": { | ||
"bracketSpacing": false, | ||
"singleQuote": true, | ||
"semi": false, | ||
"tabWidth": 2, | ||
"trailingComma": "none", | ||
"useTabs": false | ||
}, | ||
"remarkConfig": { | ||
@@ -139,3 +135,3 @@ "plugins": [ | ||
[ | ||
"remark-gfm", | ||
"./node_modules/remark-preset-wooorm/node_modules/remark-gfm/index.js", | ||
{ | ||
@@ -158,50 +154,26 @@ "tablePipeAlign": false | ||
"detail": true, | ||
"strict": true, | ||
"ignoreCatch": true, | ||
"#": "below is ignored because some proptypes will `any`", | ||
"ignoreFiles": [ | ||
"lib/react-markdown.d.ts", | ||
"index.d.ts" | ||
] | ||
"strict": true | ||
}, | ||
"prettier": { | ||
"tabWidth": 2, | ||
"useTabs": false, | ||
"singleQuote": true, | ||
"bracketSpacing": false, | ||
"semi": false, | ||
"trailingComma": "none" | ||
}, | ||
"xo": { | ||
"prettier": true, | ||
"extends": "xo-react", | ||
"envs": [ | ||
"shared-node-browser" | ||
], | ||
"extends": "plugin:react/jsx-runtime", | ||
"overrides": [ | ||
{ | ||
"files": [ | ||
"lib/**/*.js" | ||
"**/*.jsx" | ||
], | ||
"extends": [ | ||
"plugin:es/restrict-to-es2019", | ||
"plugin:security/recommended" | ||
], | ||
"rules": { | ||
"complexity": "off", | ||
"security/detect-object-injection": "off" | ||
"no-unused-vars": "off" | ||
} | ||
}, | ||
{ | ||
"files": [ | ||
"test/**/*.jsx" | ||
], | ||
"rules": { | ||
"n/file-extension-in-import": "off", | ||
"react/no-children-prop": "off", | ||
"react/prop-types": "off" | ||
} | ||
} | ||
] | ||
], | ||
"prettier": true, | ||
"rules": { | ||
"complexity": "off", | ||
"n/file-extension-in-import": "off" | ||
} | ||
} | ||
} |
586
readme.md
@@ -21,9 +21,9 @@ <!-- | ||
* [x] **[safe][security] by default** | ||
* [x] **[safe][section-security] by default** | ||
(no `dangerouslySetInnerHTML` or XSS attacks) | ||
* [x] **[components][]** | ||
* [x] **[components][section-components]** | ||
(pass your own component to use instead of `<h2>` for `## hi`) | ||
* [x] **[plugins][]** | ||
* [x] **[plugins][section-plugins]** | ||
(many plugins you can pick and choose from) | ||
* [x] **[compliant][syntax]** | ||
* [x] **[compliant][section-syntax]** | ||
(100% to CommonMark, 100% to GFM with a plugin) | ||
@@ -38,4 +38,9 @@ | ||
* [API](#api) | ||
* [`props`](#props) | ||
* [`uriTransformer`](#uritransformer) | ||
* [`Markdown`](#markdown) | ||
* [`defaultUrlTransform(url)`](#defaulturltransformurl) | ||
* [`AllowElement`](#allowelement) | ||
* [`Components`](#components) | ||
* [`ExtraProps`](#extraprops) | ||
* [`Options`](#options) | ||
* [`UrlTransform`](#urltransform) | ||
* [Examples](#examples) | ||
@@ -53,2 +58,3 @@ * [Use a plugin](#use-a-plugin) | ||
* [Appendix B: Components](#appendix-b-components) | ||
* [Appendix C: line endings in markdown (and JSX)](#appendix-c-line-endings-in-markdown-and-jsx) | ||
* [Security](#security) | ||
@@ -63,6 +69,6 @@ * [Related](#related) | ||
that it’ll safely render to React elements. | ||
You can pass plugins to change how markdown is transformed to React elements and | ||
pass components that will be used instead of normal HTML elements. | ||
You can pass plugins to change how markdown is transformed and pass components | ||
that will be used instead of normal HTML elements. | ||
* to learn markdown, see this [cheatsheet and tutorial][cheat] | ||
* to learn markdown, see this [cheatsheet and tutorial][commonmark-help] | ||
* to try out `react-markdown`, see [our demo][demo] | ||
@@ -73,13 +79,11 @@ | ||
There are other ways to use markdown in React out there so why use this one? | ||
The two main reasons are that they often rely on `dangerouslySetInnerHTML` or | ||
have bugs with how they handle markdown. | ||
`react-markdown` uses a syntax tree to build the virtual dom which allows for | ||
updating only the changing DOM instead of completely overwriting. | ||
`react-markdown` is 100% CommonMark compliant and has plugins to support other | ||
syntax extensions (such as GFM). | ||
The three main reasons are that they often rely on `dangerouslySetInnerHTML`, | ||
have bugs with how they handle markdown, or don’t let you swap elements for | ||
components. | ||
`react-markdown` builds a virtual DOM, so React only replaces what changed, | ||
from a syntax tree. | ||
That’s supported because we use [unified][], specifically [remark][] for | ||
markdown and [rehype][] for HTML, which are popular tools to transform content | ||
with plugins. | ||
These features are supported because we use [unified][], specifically [remark][] | ||
for markdown and [rehype][] for HTML, which are popular tools to transform | ||
content with plugins. | ||
This package focusses on making it easy for beginners to safely use markdown in | ||
@@ -95,3 +99,3 @@ React. | ||
This package is [ESM only][esm]. | ||
In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]: | ||
In Node.js (version 16+), install with [npm][]: | ||
@@ -105,3 +109,3 @@ ```sh | ||
```js | ||
import ReactMarkdown from 'https://esm.sh/react-markdown@7' | ||
import Markdown from 'https://esm.sh/react-markdown@9' | ||
``` | ||
@@ -113,3 +117,3 @@ | ||
<script type="module"> | ||
import ReactMarkdown from 'https://esm.sh/react-markdown@7?bundle' | ||
import Markdown from 'https://esm.sh/react-markdown@9?bundle' | ||
</script> | ||
@@ -124,6 +128,8 @@ ``` | ||
import React from 'react' | ||
import ReactMarkdown from 'react-markdown' | ||
import ReactDom from 'react-dom' | ||
import Markdown from 'react-markdown' | ||
ReactDom.render(<ReactMarkdown># Hello, *world*!</ReactMarkdown>, document.body) | ||
const markdown = '# Hi, *Pluto*!' | ||
ReactDom.render(<Markdown>{markdown}</Markdown>, document.body) | ||
``` | ||
@@ -136,3 +142,3 @@ | ||
<h1> | ||
Hello, <em>world</em>! | ||
Hi, <em>Pluto</em>! | ||
</h1> | ||
@@ -144,4 +150,4 @@ ``` | ||
Here is an example that shows passing the markdown as a string and how | ||
to use a plugin ([`remark-gfm`][gfm], which adds support for strikethrough, | ||
tables, tasklists and URLs directly): | ||
to use a plugin ([`remark-gfm`][remark-gfm], which adds support for | ||
footnotes, strikethrough, tables, tasklists and URLs directly): | ||
@@ -151,9 +157,9 @@ ```jsx | ||
import ReactDom from 'react-dom' | ||
import ReactMarkdown from 'react-markdown' | ||
import Markdown from 'react-markdown' | ||
import remarkGfm from 'remark-gfm' | ||
const markdown = `Just a link: https://reactjs.com.` | ||
const markdown = `Just a link: www.nasa.gov.` | ||
ReactDom.render( | ||
<ReactMarkdown children={markdown} remarkPlugins={[remarkGfm]} />, | ||
<Markdown remarkPlugins={[remarkGfm]}>{markdown}</Markdown>, | ||
document.body | ||
@@ -168,3 +174,3 @@ ) | ||
<p> | ||
Just a link: <a href="https://reactjs.com">https://reactjs.com</a>. | ||
Just a link: <a href="http://www.nasa.gov">www.nasa.gov</a>. | ||
</p> | ||
@@ -178,60 +184,132 @@ ``` | ||
This package exports the following identifier: | ||
[`uriTransformer`][uri-transformer]. | ||
The default export is `ReactMarkdown`. | ||
[`defaultUrlTransform`][api-default-url-transform]. | ||
The default export is [`Markdown`][api-markdown]. | ||
### `props` | ||
### `Markdown` | ||
* `children` (`string`, default: `''`)\ | ||
markdown to parse | ||
* `components` (`Record<string, Component>`, default: `{}`)\ | ||
object mapping tag names to React components | ||
* `remarkPlugins` (`Array<Plugin>`, default: `[]`)\ | ||
list of [remark plugins][remark-plugins] to use | ||
* `rehypePlugins` (`Array<Plugin>`, default: `[]`)\ | ||
list of [rehype plugins][rehype-plugins] to use | ||
* `remarkRehypeOptions` (`Object?`, default: `undefined`)\ | ||
options to pass through to [`remark-rehype`][remark-rehype] | ||
* `className` (`string?`)\ | ||
wrap the markdown in a `div` with this class name | ||
* `skipHtml` (`boolean`, default: `false`)\ | ||
ignore HTML in markdown completely | ||
* `sourcePos` (`boolean`, default: `false`)\ | ||
pass a prop to all components with a serialized position | ||
(`data-sourcepos="3:1-3:13"`) | ||
* `rawSourcePos` (`boolean`, default: `false`)\ | ||
pass a prop to all components with their [position][] | ||
(`sourcePosition: {start: {line: 3, column: 1}, end:…}`) | ||
* `includeElementIndex` (`boolean`, default: `false`)\ | ||
pass the `index` (number of elements before it) and `siblingCount` (number | ||
of elements in parent) as props to all components | ||
* `allowedElements` (`Array<string>`, default: `undefined`)\ | ||
tag names to allow (can’t combine w/ `disallowedElements`), all tag names | ||
are allowed by default | ||
* `disallowedElements` (`Array<string>`, default: `undefined`)\ | ||
tag names to disallow (can’t combine w/ `allowedElements`), all tag names | ||
are allowed by default | ||
* `allowElement` (`(element, index, parent) => boolean?`, optional)\ | ||
function called to check if an element is allowed (when truthy) or not, | ||
`allowedElements` or `disallowedElements` is used first! | ||
* `unwrapDisallowed` (`boolean`, default: `false`)\ | ||
extract (unwrap) the children of not allowed elements, by default, when | ||
`strong` is disallowed, it and it’s children are dropped, but with | ||
`unwrapDisallowed` the element itself is replaced by its children | ||
* `linkTarget` (`string` or `(href, children, title) => string`, optional)\ | ||
target to use on links (such as `_blank` for `<a target="_blank"…`) | ||
* `transformLinkUri` (`(href, children, title) => string`, default: | ||
[`uriTransformer`][uri-transformer], optional)\ | ||
change URLs on links, pass `null` to allow all URLs, see [security][] | ||
* `transformImageUri` (`(src, alt, title) => string`, default: | ||
[`uriTransformer`][uri-transformer], optional)\ | ||
change URLs on images, pass `null` to allow all URLs, see [security][] | ||
Component to render markdown. | ||
### `uriTransformer` | ||
###### Parameters | ||
Our default URL transform, which you can overwrite (see props above). | ||
It’s given a URL and cleans it, by allowing only `http:`, `https:`, `mailto:`, | ||
and `tel:` URLs, absolute paths (`/example.png`), and hashes (`#some-place`). | ||
* `options` ([`Options`][api-options]) | ||
— props | ||
See the [source code here][uri]. | ||
###### Returns | ||
React element (`JSX.Element`). | ||
### `defaultUrlTransform(url)` | ||
Make a URL safe. | ||
###### Parameters | ||
* `url` (`string`) | ||
— URL | ||
###### Returns | ||
Safe URL (`string`). | ||
### `AllowElement` | ||
Filter elements (TypeScript type). | ||
###### Parameters | ||
* `node` ([`Element` from `hast`][hast-element]) | ||
— element to check | ||
* `index` (`number | undefined`) | ||
— index of `element` in `parent` | ||
* `parent` ([`Node` from `hast`][hast-node]) | ||
— parent of `element` | ||
###### Returns | ||
Whether to allow `element` (`boolean`, optional). | ||
### `Components` | ||
Map tag names to components (TypeScript type). | ||
###### Type | ||
```ts | ||
import type {Element} from 'hast' | ||
type Components = Partial<{ | ||
[TagName in keyof JSX.IntrinsicElements]: | ||
// Class component: | ||
| (new (props: JSX.IntrinsicElements[TagName] & ExtraProps) => JSX.ElementClass) | ||
// Function component: | ||
| ((props: JSX.IntrinsicElements[TagName] & ExtraProps) => JSX.Element | string | null | undefined) | ||
// Tag name: | ||
| keyof JSX.IntrinsicElements | ||
}> | ||
``` | ||
### `ExtraProps` | ||
Extra fields we pass to components (TypeScript type). | ||
###### Fields | ||
* `node` ([`Element` from `hast`][hast-element], optional) | ||
— original node | ||
### `Options` | ||
Configuration (TypeScript type). | ||
###### Fields | ||
* `allowElement` ([`AllowElement`][api-allow-element], optional) | ||
— filter elements; | ||
`allowedElements` / `disallowedElements` is used first | ||
* `allowedElements` (`Array<string>`, default: all tag names) | ||
— tag names to allow; | ||
cannot combine w/ `disallowedElements` | ||
* `children` (`string`, optional) | ||
— markdown | ||
* `className` (`string`, optional) | ||
— wrap in a `div` with this class name | ||
* `components` ([`Components`][api-components], optional) | ||
— map tag names to components | ||
* `disallowedElements` (`Array<string>`, default: `[]`) | ||
— tag names to disallow; | ||
cannot combine w/ `allowedElements` | ||
* `rehypePlugins` (`Array<Plugin>`, optional) | ||
— list of [rehype plugins][rehype-plugins] to use | ||
* `remarkPlugins` (`Array<Plugin>`, optional) | ||
— list of [remark plugins][remark-plugins] to use | ||
* `remarkRehypeOptions` ([`Options` from | ||
`remark-rehype`][remark-rehype-options], optional) | ||
— options to pass through to `remark-rehype` | ||
* `skipHtml` (`boolean`, default: `false`) | ||
— ignore HTML in markdown completely | ||
* `unwrapDisallowed` (`boolean`, default: `false`) | ||
— extract (unwrap) what’s in disallowed elements; | ||
normally when say `strong` is not allowed, it and it’s children are dropped, | ||
with `unwrapDisallowed` the element itself is replaced by its children | ||
* `urlTransform` ([`UrlTransform`][api-url-transform], default: | ||
[`defaultUrlTransform`][api-default-url-transform]) | ||
— change URLs | ||
### `UrlTransform` | ||
Transform URLs (TypeScript type). | ||
###### Parameters | ||
* `url` (`string`) | ||
— URL | ||
* `key` (`string`, example: `'href'`) | ||
— property name | ||
* `node` ([`Element` from `hast`][hast-element]) | ||
— element to check | ||
###### Returns | ||
Transformed URL (`string`, optional). | ||
## Examples | ||
@@ -242,9 +320,9 @@ | ||
This example shows how to use a remark plugin. | ||
In this case, [`remark-gfm`][gfm], which adds support for strikethrough, tables, | ||
tasklists and URLs directly: | ||
In this case, [`remark-gfm`][remark-gfm], which adds support for strikethrough, | ||
tables, tasklists and URLs directly: | ||
```jsx | ||
import React from 'react' | ||
import ReactMarkdown from 'react-markdown' | ||
import ReactDom from 'react-dom' | ||
import Markdown from 'react-markdown' | ||
import remarkGfm from 'remark-gfm' | ||
@@ -267,3 +345,3 @@ | ||
ReactDom.render( | ||
<ReactMarkdown children={markdown} remarkPlugins={[remarkGfm]} />, | ||
<Markdown remarkPlugins={[remarkGfm]}>{markdown}</Markdown>, | ||
document.body | ||
@@ -287,9 +365,9 @@ ) | ||
</blockquote> | ||
<ul> | ||
<ul className="contains-task-list"> | ||
<li>Lists</li> | ||
<li> | ||
<input checked={false} readOnly={true} type="checkbox" /> todo | ||
<li className="task-list-item"> | ||
<input type="checkbox" disabled /> todo | ||
</li> | ||
<li> | ||
<input checked={true} readOnly={true} type="checkbox" /> done | ||
<li className="task-list-item"> | ||
<input type="checkbox" disabled checked /> done | ||
</li> | ||
@@ -301,4 +379,4 @@ </ul> | ||
<tr> | ||
<td>a</td> | ||
<td>b</td> | ||
<th>a</th> | ||
<th>b</th> | ||
</tr> | ||
@@ -317,14 +395,17 @@ </thead> | ||
second. | ||
[`remark-gfm`][gfm] has an option to allow only double tildes for strikethrough: | ||
[`remark-gfm`][remark-gfm] has an option to allow only double tildes for | ||
strikethrough: | ||
```jsx | ||
import React from 'react' | ||
import ReactMarkdown from 'react-markdown' | ||
import ReactDom from 'react-dom' | ||
import Markdown from 'react-markdown' | ||
import remarkGfm from 'remark-gfm' | ||
const markdown = 'This ~is not~ strikethrough, but ~~this is~~!' | ||
ReactDom.render( | ||
<ReactMarkdown remarkPlugins={[[remarkGfm, {singleTilde: false}]]}> | ||
This ~is not~ strikethrough, but ~~this is~~! | ||
</ReactMarkdown>, | ||
<Markdown remarkPlugins={[[remarkGfm, {singleTilde: false}]]}> | ||
{markdown} | ||
</Markdown>, | ||
document.body | ||
@@ -353,6 +434,8 @@ ) | ||
<!-- To do: currently broken on actual ESM; let’s find an alternative? --> | ||
```jsx | ||
import React from 'react' | ||
import ReactDom from 'react-dom' | ||
import ReactMarkdown from 'react-markdown' | ||
import Markdown from 'react-markdown' | ||
import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter' | ||
@@ -370,10 +453,11 @@ import {dark} from 'react-syntax-highlighter/dist/esm/styles/prism' | ||
ReactDom.render( | ||
<ReactMarkdown | ||
<Markdown | ||
children={markdown} | ||
components={{ | ||
code({node, inline, className, children, ...props}) { | ||
code(props) { | ||
const {children, className, node, ...rest} = props | ||
const match = /language-(\w+)/.exec(className || '') | ||
return !inline && match ? ( | ||
return match ? ( | ||
<SyntaxHighlighter | ||
{...props} | ||
{...rest} | ||
children={String(children).replace(/\n$/, '')} | ||
@@ -385,3 +469,3 @@ style={dark} | ||
) : ( | ||
<code {...props} className={className}> | ||
<code {...rest} className={className}> | ||
{children} | ||
@@ -413,5 +497,5 @@ </code> | ||
This example shows how a syntax extension (through [`remark-math`][math]) | ||
This example shows how a syntax extension (through [`remark-math`][remark-math]) | ||
is used to support math in markdown, and a transform plugin | ||
([`rehype-katex`][katex]) to render that math. | ||
([`rehype-katex`][rehype-katex]) to render that math. | ||
@@ -421,14 +505,13 @@ ```jsx | ||
import ReactDom from 'react-dom' | ||
import ReactMarkdown from 'react-markdown' | ||
import Markdown from 'react-markdown' | ||
import rehypeKatex from 'rehype-katex' | ||
import remarkMath from 'remark-math' | ||
import rehypeKatex from 'rehype-katex' | ||
import 'katex/dist/katex.min.css' // `rehype-katex` does not import the CSS for you | ||
const markdown = `The lift coefficient ($C_L$) is a dimensionless coefficient.` | ||
ReactDom.render( | ||
<ReactMarkdown | ||
children={`The lift coefficient ($C_L$) is a dimensionless coefficient.`} | ||
remarkPlugins={[remarkMath]} | ||
rehypePlugins={[rehypeKatex]} | ||
/>, | ||
<Markdown remarkPlugins={[remarkMath]} rehypePlugins={[rehypeKatex]}> | ||
{markdown} | ||
</Markdown>, | ||
document.body | ||
@@ -444,11 +527,9 @@ ) | ||
The lift coefficient ( | ||
<span className="math math-inline"> | ||
<span className="katex"> | ||
<span className="katex-mathml"> | ||
<math xmlns="http://www.w3.org/1998/Math/MathML">{/* … */}</math> | ||
</span> | ||
<span className="katex-html" aria-hidden="true"> | ||
{/* … */} | ||
</span> | ||
<span className="katex"> | ||
<span className="katex-mathml"> | ||
<math xmlns="http://www.w3.org/1998/Math/MathML">{/* … */}</math> | ||
</span> | ||
<span className="katex-html" aria-hidden="true"> | ||
{/* … */} | ||
</span> | ||
</span> | ||
@@ -488,11 +569,19 @@ ) is a dimensionless coefficient. | ||
This package is fully typed with [TypeScript][]. | ||
It exports `Options` and `Components` types, which specify the interface of the | ||
accepted props and components. | ||
It exports the additional types | ||
[`AllowElement`][api-allow-element], | ||
[`ExtraProps`][api-extra-props], | ||
[`Components`][api-components], | ||
[`Options`][api-options], and | ||
[`UrlTransform`][api-url-transform]. | ||
## Compatibility | ||
Projects maintained by the unified collective are compatible with all maintained | ||
Projects maintained by the unified collective are compatible with maintained | ||
versions of Node.js. | ||
As of now, that is Node.js 12.20+, 14.14+, and 16.0+. | ||
Our projects sometimes work with older versions, but this is not guaranteed. | ||
When we cut a new major release, we drop support for unmaintained versions of | ||
Node. | ||
This means we try to keep the current release line, `react-markdown@^9`, | ||
compatible with Node.js 16. | ||
They work in all modern browsers (essentially: everything not IE 11). | ||
@@ -538,3 +627,3 @@ You can use a bundler (such as esbuild, webpack, or Rollup) to use this package | ||
can spare the bundle size (±60kb minzipped), then you can use | ||
[`rehype-raw`][raw]: | ||
[`rehype-raw`][rehype-raw]: | ||
@@ -544,6 +633,6 @@ ```jsx | ||
import ReactDom from 'react-dom' | ||
import ReactMarkdown from 'react-markdown' | ||
import Markdown from 'react-markdown' | ||
import rehypeRaw from 'rehype-raw' | ||
const input = `<div class="note"> | ||
const markdown = `<div class="note"> | ||
@@ -555,3 +644,3 @@ Some *emphasis* and <strong>strong</strong>! | ||
ReactDom.render( | ||
<ReactMarkdown rehypePlugins={[rehypeRaw]} children={input} />, | ||
<Markdown rehypePlugins={[rehypeRaw]}>{markdown}</Markdown>, | ||
document.body | ||
@@ -565,4 +654,6 @@ ) | ||
```jsx | ||
<div class="note"> | ||
<p>Some <em>emphasis</em> and <strong>strong</strong>!</p> | ||
<div className="note"> | ||
<p> | ||
Some <em>emphasis</em> and <strong>strong</strong>! | ||
</p> | ||
</div> | ||
@@ -574,3 +665,3 @@ ``` | ||
**Note**: HTML in markdown is still bound by how [HTML works in | ||
CommonMark][cm-html]. | ||
CommonMark][commonmark-html]. | ||
Make sure to use blank lines around block-level HTML that again contains | ||
@@ -584,3 +675,3 @@ markdown! | ||
```jsx | ||
<ReactMarkdown | ||
<Markdown | ||
components={{ | ||
@@ -590,3 +681,6 @@ // Map `h1` (`# heading`) to use `h2`s. | ||
// Rewrite `em`s (`*like so*`) to `i` with a red foreground color. | ||
em: ({node, ...props}) => <i style={{color: 'red'}} {...props} /> | ||
em(props) { | ||
const {node, ...rest} = props | ||
return <i style={{color: 'red'}} {...rest} /> | ||
} | ||
}} | ||
@@ -601,4 +695,4 @@ /> | ||
`ul`. | ||
With [`remark-gfm`][gfm], you can also use: `del`, `input`, `table`, `tbody`, | ||
`td`, `th`, `thead`, and `tr`. | ||
With [`remark-gfm`][remark-gfm], you can also use `del`, `input`, `table`, | ||
`tbody`, `td`, `th`, `thead`, and `tr`. | ||
Other remark or rehype plugins that add support for new constructs will also | ||
@@ -610,69 +704,71 @@ work with `react-markdown`. | ||
etc. | ||
There are some extra props passed. | ||
* `code` | ||
* `inline` (`boolean?`) | ||
— set to `true` for inline code | ||
* `className` (`string?`) | ||
— set to `language-js` or so when using ` ```js ` | ||
* `h1`, `h2`, `h3`, `h4`, `h5`, `h6` | ||
* `level` (`number` between 1 and 6) | ||
— heading rank | ||
* `input` (when using [`remark-gfm`][gfm]) | ||
* `checked` (`boolean`) | ||
— whether the item is checked | ||
* `disabled` (`true`) | ||
* `type` (`'checkbox'`) | ||
* `li` | ||
* `index` (`number`) | ||
— number of preceding items (so first gets `0`, etc.) | ||
* `ordered` (`boolean`) | ||
— whether the parent is an `ol` or not | ||
* `checked` (`boolean?`) | ||
— `null` normally, `boolean` when using [`remark-gfm`][gfm]’s tasklists | ||
* `className` (`string?`) | ||
— set to `task-list-item` when using [`remark-gfm`][gfm] and the | ||
item1 is a tasklist | ||
* `ol`, `ul` | ||
* `depth` (`number`) | ||
— number of ancestral lists (so first gets `0`, etc.) | ||
* `ordered` (`boolean`) | ||
— whether it’s an `ol` or not | ||
* `className` (`string?`) | ||
— set to `contains-task-list` when using [`remark-gfm`][gfm] and the | ||
list contains one or more tasklists | ||
* `td`, `th` (when using [`remark-gfm`][gfm]) | ||
* `style` (`Object?`) | ||
— something like `{textAlign: 'left'}` depending on how the cell is | ||
aligned | ||
* `isHeader` (`boolean`) | ||
— whether it’s a `th` or not | ||
* `tr` (when using [`remark-gfm`][gfm]) | ||
* `isHeader` (`boolean`) | ||
— whether it’s in the `thead` or not | ||
Every component will receive a `node`. | ||
This is the original [`Element` from `hast`][hast-element] element being turned | ||
into a React element. | ||
Every component will receive a `node` (`Object`). | ||
This is the original [hast](https://github.com/syntax-tree/hast) element being | ||
turned into a React element. | ||
## Appendix C: line endings in markdown (and JSX) | ||
Every element will receive a `key` (`string`). | ||
See [React’s docs](https://reactjs.org/docs/lists-and-keys.html#keys) for more | ||
info. | ||
You might have trouble with how line endings work in markdown and JSX. | ||
We recommend the following, which solves all line ending problems: | ||
Optionally, components will also receive: | ||
```jsx | ||
// If you write actual markdown in your code, put your markdown in a variable; | ||
// **do not indent markdown**: | ||
const markdown = ` | ||
# This is perfect! | ||
` | ||
* `data-sourcepos` (`string`) | ||
— see `sourcePos` option | ||
* `sourcePosition` (`Object`) | ||
— see `rawSourcePos` option | ||
* `index` and `siblingCount` (`number`) | ||
— see `includeElementIndex` option | ||
* `target` on `a` (`string`) | ||
— see `linkTarget` option | ||
// Pass the value as an expresion as an only child: | ||
<Markdown>{markdown}</Markdown> | ||
``` | ||
👆 That works. | ||
Read on for what doesn’t and why that is. | ||
You might try to write markdown directly in your JSX and find that it **does | ||
not** work: | ||
```jsx | ||
<Markdown> | ||
# Hi | ||
This is **not** a paragraph. | ||
</Markdown> | ||
``` | ||
The is because in JSX the whitespace (including line endings) is collapsed to | ||
a single space. | ||
So the above example is equivalent to: | ||
```jsx | ||
<Markdown> # Hi This is **not** a paragraph. </Markdown> | ||
``` | ||
Instead, to pass markdown to `Markdown`, you can use an expression: | ||
with a template literal: | ||
```jsx | ||
<Markdown>{` | ||
# Hi | ||
This is a paragraph. | ||
`}</Markdown> | ||
``` | ||
Template literals have another potential problem, because they keep whitespace | ||
(including indentation) inside them. | ||
That means that the following **does not** turn into a heading: | ||
```jsx | ||
<Markdown>{` | ||
# This is **not** a heading, it’s an indented code block | ||
`}</Markdown> | ||
``` | ||
## Security | ||
Use of `react-markdown` is secure by default. | ||
Overwriting `transformLinkUri` or `transformImageUri` to something insecure will | ||
open you up to XSS vectors. | ||
Overwriting `urlTransform` to something insecure will open you up to XSS | ||
vectors. | ||
Furthermore, the `remarkPlugins`, `rehypePlugins`, and `components` you use may | ||
@@ -682,3 +778,3 @@ be insecure. | ||
To make sure the content is completely safe, even after what plugins do, | ||
use [`rehype-sanitize`][sanitize]. | ||
use [`rehype-sanitize`][rehype-sanitize]. | ||
It lets you define your own schema of what is and isn’t allowed. | ||
@@ -688,8 +784,8 @@ | ||
* [`MDX`](https://github.com/mdx-js/mdx) | ||
* [`MDX`][mdx] | ||
— JSX *in* markdown | ||
* [`remark-gfm`](https://github.com/remarkjs/remark-gfm) | ||
* [`remark-gfm`][remark-gfm] | ||
— add support for GitHub flavored markdown support | ||
* [`react-remark`][react-remark] | ||
— modern hook based alternative | ||
— hook based alternative | ||
* [`rehype-react`][rehype-react] | ||
@@ -724,5 +820,5 @@ — turn HTML into React elements | ||
[size-badge]: https://img.shields.io/bundlephobia/minzip/react-markdown.svg | ||
[size-badge]: https://img.shields.io/bundlejs/size/react-markdown | ||
[size]: https://bundlephobia.com/result?p=react-markdown | ||
[size]: https://bundlejs.com/?q=react-markdown | ||
@@ -741,2 +837,4 @@ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg | ||
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c | ||
[esmsh]: https://esm.sh | ||
@@ -746,7 +844,7 @@ | ||
[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md | ||
[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md | ||
[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md | ||
[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md | ||
[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md | ||
[support]: https://github.com/remarkjs/.github/blob/main/support.md | ||
@@ -757,68 +855,78 @@ [license]: license | ||
[micromark]: https://github.com/micromark/micromark | ||
[awesome-remark]: https://github.com/remarkjs/awesome-remark | ||
[remark]: https://github.com/remarkjs/remark | ||
[awesome-rehype]: https://github.com/rehypejs/awesome-rehype | ||
[demo]: https://remarkjs.github.io/react-markdown/ | ||
[commonmark-help]: https://commonmark.org/help/ | ||
[position]: https://github.com/syntax-tree/unist#position | ||
[commonmark-html]: https://spec.commonmark.org/0.30/#html-blocks | ||
[gfm]: https://github.com/remarkjs/remark-gfm | ||
[hast-element]: https://github.com/syntax-tree/hast#element | ||
[math]: https://github.com/remarkjs/remark-math | ||
[hast-node]: https://github.com/syntax-tree/hast#nodes | ||
[katex]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex | ||
[mdx]: https://github.com/mdx-js/mdx/ | ||
[raw]: https://github.com/rehypejs/rehype-raw | ||
[micromark]: https://github.com/micromark/micromark | ||
[sanitize]: https://github.com/rehypejs/rehype-sanitize | ||
[react]: http://reactjs.org | ||
[remark-plugins]: https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins | ||
[react-remark]: https://github.com/remarkjs/react-remark | ||
[react-syntax-highlighter]: https://github.com/react-syntax-highlighter/react-syntax-highlighter | ||
[rehype]: https://github.com/rehypejs/rehype | ||
[rehype-katex]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex | ||
[rehype-plugin]: https://github.com/topics/rehype-plugin | ||
[rehype-plugins]: https://github.com/rehypejs/rehype/blob/main/doc/plugins.md#list-of-plugins | ||
[remark-rehype]: https://github.com/remarkjs/remark-rehype | ||
[rehype-react]: https://github.com/rehypejs/rehype-react | ||
[awesome-remark]: https://github.com/remarkjs/awesome-remark | ||
[rehype-raw]: https://github.com/rehypejs/rehype-raw | ||
[awesome-rehype]: https://github.com/rehypejs/awesome-rehype | ||
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize | ||
[remark-plugin]: https://github.com/topics/remark-plugin | ||
[remark]: https://github.com/remarkjs/remark | ||
[rehype-plugin]: https://github.com/topics/rehype-plugin | ||
[remark-gfm]: https://github.com/remarkjs/remark-gfm | ||
[cm-html]: https://spec.commonmark.org/0.30/#html-blocks | ||
[remark-math]: https://github.com/remarkjs/remark-math | ||
[uri]: https://github.com/remarkjs/react-markdown/blob/main/lib/uri-transformer.js | ||
[remark-plugin]: https://github.com/topics/remark-plugin | ||
[uri-transformer]: #uritransformer | ||
[remark-plugins]: https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins | ||
[react]: http://reactjs.org | ||
[remark-rehype-options]: https://github.com/remarkjs/remark-rehype#options | ||
[cheat]: https://commonmark.org/help/ | ||
[unified]: https://github.com/unifiedjs/unified | ||
[rehype]: https://github.com/rehypejs/rehype | ||
[typescript]: https://www.typescriptlang.org | ||
[react-remark]: https://github.com/remarkjs/react-remark | ||
[conor]: https://github.com/conorhastings | ||
[rehype-react]: https://github.com/rehypejs/rehype-react | ||
[demo]: https://remarkjs.github.io/react-markdown/ | ||
[mdx]: https://github.com/mdx-js/mdx/ | ||
[section-components]: #appendix-b-components | ||
[typescript]: https://www.typescriptlang.org | ||
[section-plugins]: #plugins | ||
[security]: #security | ||
[section-security]: #security | ||
[components]: #appendix-b-components | ||
[section-syntax]: #syntax | ||
[plugins]: #plugins | ||
[api-allow-element]: #allowelement | ||
[syntax]: #syntax | ||
[api-components]: #components | ||
[react-syntax-highlighter]: https://github.com/react-syntax-highlighter/react-syntax-highlighter | ||
[api-default-url-transform]: #defaulturltransformurl | ||
[conor]: https://github.com/conorhastings | ||
[api-extra-props]: #extraprops | ||
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c | ||
[api-markdown]: #markdown | ||
[api-options]: #options | ||
[api-url-transform]: #urltransform |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
13
17
892
44755
7
403
1
+ Addeddevlop@^1.0.0
+ Addedhtml-url-attributes@^3.0.0
+ Addedmdast-util-to-hast@^13.0.0
+ Added@types/estree@1.0.6(transitive)
+ Added@types/estree-jsx@1.0.5(transitive)
+ Added@types/hast@3.0.4(transitive)
+ Added@types/mdast@4.0.4(transitive)
+ Added@types/unist@3.0.3(transitive)
+ Added@ungap/structured-clone@1.2.0(transitive)
+ Addedccount@2.0.1(transitive)
+ Addedcharacter-entities-html4@2.1.0(transitive)
+ Addedcharacter-entities-legacy@3.0.0(transitive)
+ Addedcharacter-reference-invalid@2.0.1(transitive)
+ Addeddevlop@1.1.0(transitive)
+ Addedestree-util-is-identifier-name@3.0.0(transitive)
+ Addedhast-util-to-jsx-runtime@2.3.2(transitive)
+ Addedhast-util-whitespace@3.0.0(transitive)
+ Addedhtml-url-attributes@3.0.1(transitive)
+ Addedinline-style-parser@0.2.4(transitive)
+ Addedis-alphabetical@2.0.1(transitive)
+ Addedis-alphanumerical@2.0.1(transitive)
+ Addedis-decimal@2.0.1(transitive)
+ Addedis-hexadecimal@2.0.1(transitive)
+ Addedlongest-streak@3.1.0(transitive)
+ Addedmdast-util-from-markdown@2.0.2(transitive)
+ Addedmdast-util-mdx-expression@2.0.1(transitive)
+ Addedmdast-util-mdx-jsx@3.1.3(transitive)
+ Addedmdast-util-mdxjs-esm@2.0.1(transitive)
+ Addedmdast-util-phrasing@4.1.0(transitive)
+ Addedmdast-util-to-hast@13.2.0(transitive)
+ Addedmdast-util-to-markdown@2.1.2(transitive)
+ Addedmdast-util-to-string@4.0.0(transitive)
+ Addedmicromark@4.0.1(transitive)
+ Addedmicromark-core-commonmark@2.0.2(transitive)
+ Addedmicromark-factory-destination@2.0.1(transitive)
+ Addedmicromark-factory-label@2.0.1(transitive)
+ Addedmicromark-factory-space@2.0.1(transitive)
+ Addedmicromark-factory-title@2.0.1(transitive)
+ Addedmicromark-factory-whitespace@2.0.1(transitive)
+ Addedmicromark-util-character@2.1.1(transitive)
+ Addedmicromark-util-chunked@2.0.1(transitive)
+ Addedmicromark-util-classify-character@2.0.1(transitive)
+ Addedmicromark-util-combine-extensions@2.0.1(transitive)
+ Addedmicromark-util-decode-numeric-character-reference@2.0.2(transitive)
+ Addedmicromark-util-decode-string@2.0.1(transitive)
+ Addedmicromark-util-encode@2.0.1(transitive)
+ Addedmicromark-util-html-tag-name@2.0.1(transitive)
+ Addedmicromark-util-normalize-identifier@2.0.1(transitive)
+ Addedmicromark-util-resolve-all@2.0.1(transitive)
+ Addedmicromark-util-sanitize-uri@2.0.1(transitive)
+ Addedmicromark-util-subtokenize@2.0.3(transitive)
+ Addedmicromark-util-symbol@2.0.1(transitive)
+ Addedmicromark-util-types@2.0.1(transitive)
+ Addedparse-entities@4.0.1(transitive)
+ Addedremark-parse@11.0.0(transitive)
+ Addedremark-rehype@11.1.1(transitive)
+ Addedstringify-entities@4.0.4(transitive)
+ Addedstyle-to-object@1.0.8(transitive)
+ Addedunified@11.0.5(transitive)
+ Addedunist-util-is@6.0.0(transitive)
+ Addedunist-util-position@5.0.0(transitive)
+ Addedunist-util-stringify-position@4.0.0(transitive)
+ Addedunist-util-visit@5.0.0(transitive)
+ Addedunist-util-visit-parents@6.0.1(transitive)
+ Addedvfile@6.0.3(transitive)
+ Addedvfile-message@4.0.2(transitive)
+ Addedzwitch@2.0.4(transitive)
- Removed@types/prop-types@^15.0.0
- Removed@types/unist@^2.0.0
- Removedcomma-separated-tokens@^2.0.0
- Removedhast-util-whitespace@^2.0.0
- Removedprop-types@^15.0.0
- Removedproperty-information@^6.0.0
- Removedreact-is@^18.0.0
- Removedspace-separated-tokens@^2.0.0
- Removedstyle-to-object@^0.4.0
- Removed@types/hast@2.3.10(transitive)
- Removed@types/mdast@3.0.15(transitive)
- Removeddiff@5.2.0(transitive)
- Removedhast-util-whitespace@2.0.1(transitive)
- Removedinline-style-parser@0.1.1(transitive)
- Removedis-buffer@2.0.5(transitive)
- Removedkleur@4.1.5(transitive)
- Removedmdast-util-definitions@5.1.2(transitive)
- Removedmdast-util-from-markdown@1.3.1(transitive)
- Removedmdast-util-to-hast@12.3.0(transitive)
- Removedmdast-util-to-string@3.2.0(transitive)
- Removedmicromark@3.2.0(transitive)
- Removedmicromark-core-commonmark@1.1.0(transitive)
- Removedmicromark-factory-destination@1.1.0(transitive)
- Removedmicromark-factory-label@1.1.0(transitive)
- Removedmicromark-factory-space@1.1.0(transitive)
- Removedmicromark-factory-title@1.1.0(transitive)
- Removedmicromark-factory-whitespace@1.1.0(transitive)
- Removedmicromark-util-character@1.2.0(transitive)
- Removedmicromark-util-chunked@1.1.0(transitive)
- Removedmicromark-util-classify-character@1.1.0(transitive)
- Removedmicromark-util-combine-extensions@1.1.0(transitive)
- Removedmicromark-util-decode-numeric-character-reference@1.1.0(transitive)
- Removedmicromark-util-decode-string@1.1.0(transitive)
- Removedmicromark-util-encode@1.1.0(transitive)
- Removedmicromark-util-html-tag-name@1.2.0(transitive)
- Removedmicromark-util-normalize-identifier@1.1.0(transitive)
- Removedmicromark-util-resolve-all@1.1.0(transitive)
- Removedmicromark-util-sanitize-uri@1.2.0(transitive)
- Removedmicromark-util-subtokenize@1.1.0(transitive)
- Removedmicromark-util-symbol@1.1.0(transitive)
- Removedmicromark-util-types@1.1.0(transitive)
- Removedmri@1.2.0(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedprop-types@15.8.1(transitive)
- Removedreact-is@16.13.118.3.1(transitive)
- Removedremark-parse@10.0.2(transitive)
- Removedremark-rehype@10.1.0(transitive)
- Removedsade@1.8.1(transitive)
- Removedstyle-to-object@0.4.4(transitive)
- Removedunified@10.1.2(transitive)
- Removedunist-util-generated@2.0.1(transitive)
- Removedunist-util-is@5.2.1(transitive)
- Removedunist-util-position@4.0.4(transitive)
- Removedunist-util-stringify-position@3.0.3(transitive)
- Removedunist-util-visit@4.1.2(transitive)
- Removedunist-util-visit-parents@5.1.3(transitive)
- Removeduvu@0.5.6(transitive)
- Removedvfile@5.3.7(transitive)
- Removedvfile-message@3.1.4(transitive)
Updated@types/hast@^3.0.0
Updatedremark-parse@^11.0.0
Updatedremark-rehype@^11.0.0
Updatedunified@^11.0.0
Updatedunist-util-visit@^5.0.0
Updatedvfile@^6.0.0