rehype-sanitize
Advanced tools
Comparing version 5.0.1 to 6.0.0
@@ -1,18 +0,3 @@ | ||
/** | ||
* Plugin to sanitize HTML. | ||
* | ||
* @type {import('unified').Plugin<[Options?] | Array<void>, Root, Root>} | ||
*/ | ||
export default function rehypeSanitize( | ||
options?: void | import('hast-util-sanitize/lib').Schema | undefined | ||
): | ||
| void | ||
| import('unified').Transformer<import('hast').Root, import('hast').Root> | ||
export {defaultSchema} from 'hast-util-sanitize' | ||
export type Root = import('hast').Root | ||
/** | ||
* The sanitation schema defines how and if nodes and properties should be cleaned. | ||
* See `hast-util-sanitize`. | ||
* The default schema is exported as `defaultSchema`. | ||
*/ | ||
export type Options = import('hast-util-sanitize').Schema | ||
export { defaultSchema } from "hast-util-sanitize"; | ||
export { default } from "./lib/index.js"; | ||
export type Options = import('hast-util-sanitize').Schema; |
18
index.js
/** | ||
* @typedef {import('hast').Root} Root | ||
* | ||
* @typedef {import('hast-util-sanitize').Schema} Options | ||
* The sanitation schema defines how and if nodes and properties should be cleaned. | ||
* See `hast-util-sanitize`. | ||
* The default schema is exported as `defaultSchema`. | ||
*/ | ||
import {sanitize as hastUtilSanitize, defaultSchema} from 'hast-util-sanitize' | ||
/** | ||
* Plugin to sanitize HTML. | ||
* | ||
* @type {import('unified').Plugin<[Options?] | Array<void>, Root, Root>} | ||
*/ | ||
export default function rehypeSanitize(options = defaultSchema) { | ||
// @ts-expect-error: assume input `root` matches output root. | ||
return (tree) => hastUtilSanitize(tree, options) | ||
} | ||
export {defaultSchema} from 'hast-util-sanitize' | ||
export {default} from './lib/index.js' |
{ | ||
"name": "rehype-sanitize", | ||
"version": "5.0.1", | ||
"version": "6.0.0", | ||
"description": "rehype plugin to sanitize HTML", | ||
"license": "MIT", | ||
"keywords": [ | ||
"unified", | ||
"clean", | ||
"html", | ||
"plugin", | ||
"rehype", | ||
"rehype-plugin", | ||
"plugin", | ||
"xss", | ||
"sanitize", | ||
"clean", | ||
"html" | ||
"unified", | ||
"xss" | ||
], | ||
@@ -28,5 +28,5 @@ "repository": "rehypejs/rehype-sanitize", | ||
"type": "module", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"exports": "./index.js", | ||
"files": [ | ||
"lib/", | ||
"index.d.ts", | ||
@@ -36,46 +36,36 @@ "index.js" | ||
"dependencies": { | ||
"@types/hast": "^2.0.0", | ||
"hast-util-sanitize": "^4.0.0", | ||
"unified": "^10.0.0" | ||
"@types/hast": "^3.0.0", | ||
"hast-util-sanitize": "^5.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/tape": "^4.0.0", | ||
"browserify": "^17.0.0", | ||
"c8": "^7.0.0", | ||
"@types/node": "^20.0.0", | ||
"c8": "^8.0.0", | ||
"deepmerge": "^4.0.0", | ||
"prettier": "^2.0.0", | ||
"rehype": "^12.0.0", | ||
"remark-cli": "^10.0.0", | ||
"prettier": "^3.0.0", | ||
"rehype": "^13.0.0", | ||
"remark-cli": "^11.0.0", | ||
"remark-preset-wooorm": "^9.0.0", | ||
"rimraf": "^3.0.0", | ||
"tape": "^5.0.0", | ||
"tinyify": "^3.0.0", | ||
"type-coverage": "^2.0.0", | ||
"typescript": "^4.0.0", | ||
"xo": "^0.47.0" | ||
"typescript": "^5.0.0", | ||
"xo": "^0.56.0" | ||
}, | ||
"scripts": { | ||
"build": "rimraf \"*.d.ts\" && tsc && type-coverage", | ||
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", | ||
"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", | ||
"test": "npm run build && npm run format && npm run test-coverage", | ||
"test-api": "node --conditions development test.js", | ||
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node --conditions development test.js", | ||
"test": "npm run build && npm run format && npm run test-coverage" | ||
"test-coverage": "c8 --100 --check-coverage --reporter lcov npm run test-api" | ||
}, | ||
"prettier": { | ||
"tabWidth": 2, | ||
"useTabs": false, | ||
"bracketSpacing": false, | ||
"singleQuote": true, | ||
"bracketSpacing": false, | ||
"semi": false, | ||
"trailingComma": "none" | ||
"tabWidth": 2, | ||
"trailingComma": "none", | ||
"useTabs": false | ||
}, | ||
"xo": { | ||
"prettier": true, | ||
"ignores": [ | ||
"types/" | ||
] | ||
}, | ||
"remarkConfig": { | ||
"plugins": [ | ||
"preset-wooorm" | ||
"remark-preset-wooorm" | ||
] | ||
@@ -86,5 +76,8 @@ }, | ||
"detail": true, | ||
"strict": true, | ||
"ignoreCatch": true | ||
"ignoreCatch": true, | ||
"strict": true | ||
}, | ||
"xo": { | ||
"prettier": true | ||
} | ||
} |
318
readme.md
@@ -20,3 +20,5 @@ # rehype-sanitize | ||
* [API](#api) | ||
* [`defaultSchema`](#defaultschema) | ||
* [`unified().use(rehypeSanitize[, schema])`](#unifieduserehypesanitize-schema) | ||
* [`Options`](#options) | ||
* [Example](#example) | ||
@@ -57,4 +59,4 @@ * [Example: headings (DOM clobbering)](#example-headings-dom-clobbering) | ||
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). | ||
In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]: | ||
This package is [ESM only][esm]. | ||
In Node.js (version 16+), install with [npm][]: | ||
@@ -65,13 +67,13 @@ ```sh | ||
In Deno with [Skypack][]: | ||
In Deno with [`esm.sh`][esmsh]: | ||
```js | ||
import rehypeSanitize from 'https://cdn.skypack.dev/rehype-sanitize@5?dts' | ||
import rehypeSanitize from 'https://esm.sh/rehype-sanitize@6' | ||
``` | ||
In browsers with [Skypack][]: | ||
In browsers with [`esm.sh`][esmsh]: | ||
```html | ||
<script type="module"> | ||
import rehypeSanitize from 'https://cdn.skypack.dev/rehype-sanitize@5?min' | ||
import rehypeSanitize from 'https://esm.sh/rehype-sanitize@6?bundle' | ||
</script> | ||
@@ -98,22 +100,18 @@ ``` | ||
And our module `example.js` looks as follows: | ||
…and our module `example.js` looks as follows: | ||
```js | ||
import {read} from 'to-vfile' | ||
import {unified} from 'unified' | ||
import rehypeParse from 'rehype-parse' | ||
import rehypeSanitize from 'rehype-sanitize' | ||
import rehypeStringify from 'rehype-stringify' | ||
import {read} from 'to-vfile' | ||
import {unified} from 'unified' | ||
main() | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
.use(rehypeSanitize) | ||
.use(rehypeStringify) | ||
.process(await read('index.html')) | ||
async function main() { | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
.use(rehypeSanitize) | ||
.use(rehypeStringify) | ||
.process(await read('index.html')) | ||
console.log(String(file)) | ||
} | ||
console.log(String(file)) | ||
``` | ||
@@ -136,5 +134,11 @@ | ||
This package exports the following identifiers: `defaultSchema`. | ||
The default export is `rehypeSanitize`. | ||
This package exports the identifier [`defaultSchema`][api-default-schema]. | ||
The default export is [`rehypeSanitize`][api-rehype-sanitize]. | ||
### `defaultSchema` | ||
Default schema ([`Options`][api-options]). | ||
Follows GitHub style sanitation. | ||
### `unified().use(rehypeSanitize[, schema])` | ||
@@ -144,11 +148,18 @@ | ||
###### `schema` | ||
###### Parameters | ||
Sanitation schema that defines if and how nodes and properties should be | ||
cleaned. | ||
The default schema is exported as `defaultSchema`. | ||
* `options` ([`Options`][api-options], optional) | ||
— configuration | ||
This option is a bit advanced as it requires knowledge of ASTs, so we defer | ||
to the documentation available for [`Schema` in `hast-util-sanitize`][schema]. | ||
###### Returns | ||
Transform ([`Transformer`][unified-transformer]). | ||
### `Options` | ||
Schema that defines what nodes and properties are allowed (TypeScript type). | ||
This option is a bit advanced as it requires knowledge of syntax trees, so see | ||
the docs for [`Schema` in `hast-util-sanitize`][hast-util-sanitize-schema]. | ||
## Example | ||
@@ -171,12 +182,13 @@ | ||
```js | ||
import {promises as fs} from 'node:fs' | ||
import {unified} from 'unified' | ||
/** | ||
* @typedef {import('hast').Root} Root | ||
*/ | ||
import fs from 'node:fs/promises' | ||
import rehypeParse from 'rehype-parse' | ||
import rehypeStringify from 'rehype-stringify' | ||
import {unified} from 'unified' | ||
main() | ||
async function main() { | ||
const browser = String(await fs.readFile('browser.js')) | ||
const document = `<a name="old"></a> | ||
const browser = String(await fs.readFile('browser.js')) | ||
const document = `<a name="old"></a> | ||
<h1 id="current">Current</h1> | ||
@@ -186,5 +198,9 @@ ${`<p>${'Lorem ipsum dolor sit amet. '.repeat(20)}</p>\n`.repeat(20)} | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
.use(() => (tree) => { | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
.use(function () { | ||
/** | ||
* @param {Root} tree | ||
*/ | ||
return function (tree) { | ||
tree.children.push({ | ||
@@ -196,8 +212,8 @@ type: 'element', | ||
}) | ||
}) | ||
.use(rehypeStringify) | ||
.process(document) | ||
} | ||
}) | ||
.use(rehypeStringify) | ||
.process(document) | ||
await fs.writeFile('output.html', file.value) | ||
} | ||
await fs.writeFile('output.html', String(file)) | ||
``` | ||
@@ -220,6 +236,7 @@ | ||
When you run this code locally, open the generated `output.html`, you can | ||
When you run this code locally and open the generated `output.html`, you can | ||
observe that the links at the bottom work, but also that the `<h1>` element | ||
is printed to the console (the clobbering). | ||
`rehype-sanitize` solved the clobbering by prefixing every `id` and `name` | ||
`rehype-sanitize` solves the clobbering by prefixing every `id` and `name` | ||
attribute with `'user-content-'`. | ||
@@ -234,5 +251,5 @@ Changing `example.js`: | ||
+ .use(rehypeSanitize) | ||
.use(() => (tree) => { | ||
tree.children.push({ | ||
type: 'element', | ||
.use(function () { | ||
/** | ||
* @param {Root} tree | ||
``` | ||
@@ -249,3 +266,3 @@ | ||
But this introduces another problem as the links are now broken. | ||
This introduces another problem as the links are now broken. | ||
It could perhaps be solved by changing all links, but that would make the links | ||
@@ -260,2 +277,5 @@ rather ugly, and we’d need to track what IDs we have outside of the user content | ||
```js | ||
/// <reference lib="dom" /> | ||
/* eslint-env browser */ | ||
// Page load (you could wrap this in a DOM ready if the script is loaded early). | ||
@@ -271,3 +291,3 @@ hashchange() | ||
'click', | ||
(event) => { | ||
function (event) { | ||
if ( | ||
@@ -279,3 +299,3 @@ event.target && | ||
) { | ||
setTimeout(() => { | ||
setImmediate(function () { | ||
if (!event.defaultPrevented) { | ||
@@ -291,3 +311,3 @@ hashchange() | ||
function hashchange() { | ||
/** @type {string|undefined} */ | ||
/** @type {string | undefined} */ | ||
let hash | ||
@@ -306,5 +326,5 @@ | ||
if (target) { | ||
setTimeout(() => { | ||
setImmediate(function () { | ||
target.scrollIntoView() | ||
}, 0) | ||
}) | ||
} | ||
@@ -323,20 +343,16 @@ } | ||
```js | ||
import {unified} from 'unified' | ||
import rehypeKatex from 'rehype-katex' | ||
import rehypeParse from 'rehype-parse' | ||
import rehypeKatex from 'rehype-katex' | ||
import rehypeSanitize from 'rehype-sanitize' | ||
import rehypeStringify from 'rehype-stringify' | ||
import {unified} from 'unified' | ||
main() | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
.use(rehypeKatex) | ||
.use(rehypeSanitize) | ||
.use(rehypeStringify) | ||
.process('<span class="math math-inline">L</span>') | ||
async function main() { | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
.use(rehypeKatex) | ||
.use(rehypeSanitize) | ||
.use(rehypeStringify) | ||
.process('<span class="math math-inline">L</span>') | ||
console.log(String(file)) | ||
} | ||
console.log(String(file)) | ||
``` | ||
@@ -358,32 +374,31 @@ | ||
@@ -1,7 +1,7 @@ | ||
import {unified} from 'unified' | ||
import rehypeKatex from 'rehype-katex' | ||
import rehypeParse from 'rehype-parse' | ||
import rehypeKatex from 'rehype-katex' | ||
-import rehypeSanitize from 'rehype-sanitize' | ||
+import rehypeSanitize, {defaultSchema} from 'rehype-sanitize' | ||
import rehypeStringify from 'rehype-stringify' | ||
import {unified} from 'unified' | ||
main() | ||
@@ -9,8 +9,21 @@ main() | ||
async function main() { | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
+ .use(rehypeSanitize, { | ||
+ ...defaultSchema, | ||
+ attributes: { | ||
+ ...defaultSchema.attributes, | ||
+ div: [ | ||
+ ...(defaultSchema.attributes.div || []), | ||
+ ['className', 'math', 'math-display'] | ||
+ ], | ||
+ span: [ | ||
+ ...(defaultSchema.attributes.span || []), | ||
+ ['className', 'math', 'math-inline'] | ||
+ ] | ||
+ } | ||
+ }) | ||
.use(rehypeKatex) | ||
- .use(rehypeSanitize) | ||
.use(rehypeStringify) | ||
.process('<span class="math math-inline">L</span>') | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
+ .use(rehypeSanitize, { | ||
+ ...defaultSchema, | ||
+ attributes: { | ||
+ ...defaultSchema.attributes, | ||
+ div: [ | ||
+ ...(defaultSchema.attributes.div || []), | ||
+ ['className', 'math', 'math-display'] | ||
+ ], | ||
+ span: [ | ||
+ ...(defaultSchema.attributes.span || []), | ||
+ ['className', 'math', 'math-inline'] | ||
+ ] | ||
+ } | ||
+ }) | ||
.use(rehypeKatex) | ||
- .use(rehypeSanitize) | ||
.use(rehypeStringify) | ||
.process('<span class="math math-inline">L</span>') | ||
``` | ||
@@ -399,30 +414,26 @@ | ||
```js | ||
import {unified} from 'unified' | ||
import rehypeHighlight from 'rehype-highlight' | ||
import rehypeParse from 'rehype-parse' | ||
import rehypeHighlight from 'rehype-highlight' | ||
import rehypeSanitize, {defaultSchema} from './index.js' | ||
import rehypeSanitize, {defaultSchema} from 'rehype-sanitize' | ||
import rehypeStringify from 'rehype-stringify' | ||
import {unified} from 'unified' | ||
main() | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
.use(rehypeSanitize, { | ||
...defaultSchema, | ||
attributes: { | ||
...defaultSchema.attributes, | ||
code: [ | ||
...(defaultSchema.attributes.code || []), | ||
// List of all allowed languages: | ||
['className', 'language-js', 'language-css', 'language-md'] | ||
] | ||
} | ||
}) | ||
.use(rehypeHighlight, {subset: false}) | ||
.use(rehypeStringify) | ||
.process('<pre><code className="language-js">console.log(1)</code></pre>') | ||
async function main() { | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
.use(rehypeSanitize, { | ||
...defaultSchema, | ||
attributes: { | ||
...defaultSchema.attributes, | ||
code: [ | ||
...(defaultSchema.attributes.code || []), | ||
// List of all allowed languages: | ||
['className', 'language-js', 'language-css', 'language-md'] | ||
] | ||
} | ||
}) | ||
.use(rehypeHighlight, {subset: false}) | ||
.use(rehypeStringify) | ||
.process('<pre><code className="language-js">console.log(1)</code></pre>') | ||
console.log(String(file)) | ||
} | ||
console.log(String(file)) | ||
``` | ||
@@ -435,25 +446,24 @@ | ||
```diff | ||
async function main() { | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
+ .use(rehypeHighlight, {subset: false}) | ||
.use(rehypeSanitize, { | ||
...defaultSchema, | ||
attributes: { | ||
...defaultSchema.attributes, | ||
- code: [ | ||
- ...(defaultSchema.attributes.code || []), | ||
- // List of all allowed languages: | ||
- ['className', 'hljs', 'language-js', 'language-css', 'language-md'] | ||
+ span: [ | ||
+ ...(defaultSchema.attributes.span || []), | ||
+ // List of all allowed tokens: | ||
+ ['className', 'hljs-addition', 'hljs-attr', 'hljs-attribute', 'hljs-built_in', 'hljs-bullet', 'hljs-char', 'hljs-code', 'hljs-comment', 'hljs-deletion', 'hljs-doctag', 'hljs-emphasis', 'hljs-formula', 'hljs-keyword', 'hljs-link', 'hljs-literal', 'hljs-meta', 'hljs-name', 'hljs-number', 'hljs-operator', 'hljs-params', 'hljs-property', 'hljs-punctuation', 'hljs-quote', 'hljs-regexp', 'hljs-section', 'hljs-selector-attr', 'hljs-selector-class', 'hljs-selector-id', 'hljs-selector-pseudo', 'hljs-selector-tag', 'hljs-string', 'hljs-strong', 'hljs-subst', 'hljs-symbol', 'hljs-tag', 'hljs-template-tag', 'hljs-template-variable', 'hljs-title', 'hljs-type', 'hljs-variable' | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
+ .use(rehypeHighlight, {subset: false}) | ||
.use(rehypeSanitize, { | ||
...defaultSchema, | ||
attributes: { | ||
...defaultSchema.attributes, | ||
- code: [ | ||
- ...(defaultSchema.attributes.code || []), | ||
- // List of all allowed languages: | ||
- ['className', 'hljs', 'language-js', 'language-css', 'language-md'] | ||
+ span: [ | ||
+ ...(defaultSchema.attributes.span || []), | ||
+ // List of all allowed tokens: | ||
+ ['className', 'hljs-addition', 'hljs-attr', 'hljs-attribute', 'hljs-built_in', 'hljs-bullet', 'hljs-char', 'hljs-code', 'hljs-comment', 'hljs-deletion', 'hljs-doctag', 'hljs-emphasis', 'hljs-formula', 'hljs-keyword', 'hljs-link', 'hljs-literal', 'hljs-meta', 'hljs-name', 'hljs-number', 'hljs-operator', 'hljs-params', 'hljs-property', 'hljs-punctuation', 'hljs-quote', 'hljs-regexp', 'hljs-section', 'hljs-selector-attr', 'hljs-selector-class', 'hljs-selector-id', 'hljs-selector-pseudo', 'hljs-selector-tag', 'hljs-string', 'hljs-strong', 'hljs-subst', 'hljs-symbol', 'hljs-tag', 'hljs-template-tag', 'hljs-template-variable', 'hljs-title', 'hljs-type', 'hljs-variable' | ||
+ ] | ||
] | ||
} | ||
}) | ||
- .use(rehypeHighlight, {subset: false}) | ||
.use(rehypeStringify) | ||
.process('<pre><code className="language-js">console.log(1)</code></pre>') | ||
] | ||
} | ||
}) | ||
- .use(rehypeHighlight, {subset: false}) | ||
.use(rehypeStringify) | ||
.process('<pre><code className="language-js">console.log(1)</code></pre>') | ||
``` | ||
@@ -464,12 +474,14 @@ | ||
This package is fully typed with [TypeScript][]. | ||
It exports an `Options` type, which specifies the interface of the accepted | ||
options. | ||
It exports the additional type [`Options`][api-options]. | ||
## 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, `rehype-sanitize@^6`, | ||
compatible with Node.js 16. | ||
This plugin works with `rehype-parse` version 3+, `rehype-stringify` version 3+, | ||
@@ -523,5 +535,5 @@ `rehype` version 5+, and `unified` version 6+. | ||
[size-badge]: https://img.shields.io/bundlephobia/minzip/rehype-sanitize.svg | ||
[size-badge]: https://img.shields.io/bundlejs/size/rehype-sanitize | ||
[size]: https://bundlephobia.com/result?p=rehype-sanitize | ||
[size]: https://bundlejs.com/?q=rehype-sanitize | ||
@@ -538,4 +550,6 @@ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg | ||
[skypack]: https://www.skypack.dev | ||
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c | ||
[esmsh]: https://esm.sh | ||
[npm]: https://docs.npmjs.com/cli/install | ||
@@ -555,6 +569,2 @@ | ||
[unified]: https://github.com/unifiedjs/unified | ||
[rehype]: https://github.com/rehypejs/rehype | ||
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting | ||
@@ -568,4 +578,6 @@ | ||
[schema]: https://github.com/syntax-tree/hast-util-sanitize#schema | ||
[hast-util-sanitize-schema]: https://github.com/syntax-tree/hast-util-sanitize#schema | ||
[rehype]: https://github.com/rehypejs/rehype | ||
[rehype-katex]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex | ||
@@ -576,1 +588,11 @@ | ||
[rehype-highlight]: https://github.com/rehypejs/rehype-highlight | ||
[unified]: https://github.com/unifiedjs/unified | ||
[unified-transformer]: https://github.com/unifiedjs/unified?tab=readme-ov-file#transformer | ||
[api-default-schema]: #defaultschema | ||
[api-options]: #options | ||
[api-rehype-sanitize]: #unifieduserehypesanitize-schema |
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
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
20789
2
10
7
45
572
+ Added@types/hast@3.0.4(transitive)
+ Added@types/unist@3.0.3(transitive)
+ Added@ungap/structured-clone@1.2.0(transitive)
+ Addedhast-util-sanitize@5.0.1(transitive)
+ Addedunist-util-position@5.0.0(transitive)
- Removedunified@^10.0.0
- Removed@types/hast@2.3.10(transitive)
- Removed@types/unist@2.0.11(transitive)
- Removedbail@2.0.2(transitive)
- Removedextend@3.0.2(transitive)
- Removedhast-util-sanitize@4.1.0(transitive)
- Removedis-buffer@2.0.5(transitive)
- Removedis-plain-obj@4.1.0(transitive)
- Removedtrough@2.2.0(transitive)
- Removedunified@10.1.2(transitive)
- Removedunist-util-stringify-position@3.0.3(transitive)
- Removedvfile@5.3.7(transitive)
- Removedvfile-message@3.1.4(transitive)
Updated@types/hast@^3.0.0
Updatedhast-util-sanitize@^5.0.0