From 1e0c67db9eb7c93b9156d69e3f74cb4de34e94aa Mon Sep 17 00:00:00 2001 From: Titus Date: Fri, 5 Nov 2021 15:10:23 +0100 Subject: [PATCH] Add improved docs Closes GH-22. Reviewed-by: with-heart Reviewed-by: Christian Murphy --- index.js | 61 +----- lib/index.js | 71 +++++++ package.json | 10 +- readme.md | 504 ++++++++++++++++++++++++++++++++++++++++++++------ tsconfig.json | 2 +- 5 files changed, 525 insertions(+), 123 deletions(-) create mode 100644 lib/index.js diff --git a/index.js b/index.js index 444a59cc..fc14ef04 100644 --- a/index.js +++ b/index.js @@ -1,63 +1,8 @@ /** - * @typedef {import('unist').Node} Node - * @typedef {import('hast').Root} HastRoot - * @typedef {import('mdast').Root} MdastRoot - * @typedef {import('mdast-util-to-hast').Options} Options - * @typedef {import('unified').Processor} Processor - * - * @typedef {import('mdast-util-to-hast')} DoNotTouchAsThisImportIncludesRawInTree + * @typedef {import('./lib/index.js').Options} Options + * @typedef {import('./lib/index.js').Processor} Processor */ -import {toHast} from 'mdast-util-to-hast' - -// Note: the `` overload doesn’t seem to work :'( - -/** - * Plugin to bridge or mutate to rehype. - * - * If a destination is given, runs the destination with the new hast tree - * (bridge-mode). - * Without destination, returns the hast tree: further plugins run on that tree - * (mutate-mode). - * - * @param destination - * Optional unified processor. - * @param options - * Options passed to `mdast-util-to-hast`. - */ -const remarkRehype = - /** @type {(import('unified').Plugin<[Processor, Options?]|[null|undefined, Options?]|[Options]|[], MdastRoot>)} */ - ( - function (destination, options) { - return destination && 'run' in destination - ? bridge(destination, options) - : mutate(destination || options) - } - ) +import remarkRehype from './lib/index.js' export default remarkRehype - -/** - * Bridge-mode. - * Runs the destination with the new hast tree. - * - * @type {import('unified').Plugin<[Processor, Options?], MdastRoot>} - */ -function bridge(destination, options) { - return (node, file, next) => { - destination.run(toHast(node, options), file, (error) => { - next(error) - }) - } -} - -/** - * Mutate-mode. - * Further transformers run on the nlcst tree. - * - * @type {import('unified').Plugin<[Options?]|void[], MdastRoot, HastRoot>} - */ -function mutate(options) { - // @ts-expect-error: assume a corresponding node is returned for `toHast`. - return (node) => toHast(node, options) -} diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 00000000..431b7d97 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,71 @@ +/** + * @typedef {import('hast').Root} HastRoot + * @typedef {import('mdast').Root} MdastRoot + * @typedef {import('mdast-util-to-hast').Options} Options + * @typedef {import('unified').Processor} Processor + * + * @typedef {import('mdast-util-to-hast')} DoNotTouchAsThisImportIncludesRawInTree + */ + +import {toHast} from 'mdast-util-to-hast' + +// Note: the `` overload doesn’t seem to work :'( + +/** + * Plugin that turns markdown into HTML to support rehype. + * + * * If a destination processor is given, that processor runs with a new HTML + * (hast) tree (bridge-mode). + * As the given processor runs with a hast tree, and rehype plugins support + * hast, that means rehype plugins can be used with the given processor. + * The hast tree is discarded in the end. + * It’s highly unlikely that you want to do this. + * * The common case is to not pass a destination processor, in which case the + * current processor continues running with a new HTML (hast) tree + * (mutate-mode). + * As the current processor continues with a hast tree, and rehype plugins + * support hast, that means rehype plugins can be used after + * `remark-rehype`. + * It’s likely that this is what you want to do. + * + * @param destination + * Optional unified processor. + * @param options + * Options passed to `mdast-util-to-hast`. + */ +const remarkRehype = + /** @type {(import('unified').Plugin<[Processor, Options?]|[null|undefined, Options?]|[Options]|[], MdastRoot>)} */ + ( + function (destination, options) { + return destination && 'run' in destination + ? bridge(destination, options) + : mutate(destination || options) + } + ) + +export default remarkRehype + +/** + * Bridge-mode. + * Runs the destination with the new hast tree. + * + * @type {import('unified').Plugin<[Processor, Options?], MdastRoot>} + */ +function bridge(destination, options) { + return (node, file, next) => { + destination.run(toHast(node, options), file, (error) => { + next(error) + }) + } +} + +/** + * Mutate-mode. + * Further plugins run on the hast tree. + * + * @type {import('unified').Plugin<[Options?]|void[], MdastRoot, HastRoot>} + */ +function mutate(options) { + // @ts-expect-error: assume a corresponding node is returned by `toHast`. + return (node) => toHast(node, options) +} diff --git a/package.json b/package.json index cd863875..efd453ec 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "remark-rehype", "version": "10.0.0", - "description": "remark plugin to transform to rehype", + "description": "remark plugin that turns markdown into HTML to support rehype", "license": "MIT", "keywords": [ "unified", @@ -31,6 +31,7 @@ "main": "index.js", "types": "index.d.ts", "files": [ + "lib/", "index.d.ts", "index.js" ], @@ -56,7 +57,7 @@ "xo": "^0.46.0" }, "scripts": { - "build": "rimraf \"*.d.ts\" && tsc && type-coverage", + "build": "rimraf \"lib/**/*.d.ts\" \"*.d.ts\" && tsc && type-coverage", "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", "test-api": "node --conditions development test.js", "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov npm run test-api", @@ -86,8 +87,9 @@ "ignoreCatch": true, "#": "needed `any`s", "ignoreFiles": [ - "index.d.ts", - "index.js" + "lib/index.d.ts", + "lib/index.js", + "index.d.ts" ] } } diff --git a/readme.md b/readme.md index d4ba17e1..e8f0debb 100644 --- a/readme.md +++ b/readme.md @@ -8,32 +8,108 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -[**remark**][remark] plugin to bridge or mutate to [**rehype**][rehype]. +**[remark][]** plugin that turns markdown into HTML to support **[rehype][]**. + +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [API](#api) + * [`unified().use(remarkRehype[, destination][, options])`](#unifieduseremarkrehype-destination-options) +* [Examples](#examples) + * [Example: supporting HTML in markdown naïvely](#example-supporting-html-in-markdown-naïvely) + * [Example: supporting HTML in markdown properly](#example-supporting-html-in-markdown-properly) + * [Example: footnotes in languages other than English](#example-footnotes-in-languages-other-than-english) +* [Syntax tree](#syntax-tree) +* [CSS](#css) +* [Types](#types) +* [Compatibility](#compatibility) +* [Security](#security) +* [Related](#related) +* [Contribute](#contribute) +* [License](#license) + +## What is this? + +This package is a [unified][] ([remark][]) plugin that switches from remark (the +markdown ecosystem) to rehype (the HTML ecosystem). +It does this by transforming the current markdown (mdast) syntax tree into an +HTML (hast) syntax tree. +remark plugins deal with mdast and rehype plugins deal with hast, so plugins +used after `remark-rehype` have to be rehype plugins. + +The reason that there are different ecosystems for markdown and HTML is that +turning markdown into HTML is, while frequently needed, not the only purpose of +markdown. +Checking (linting) and formatting markdown are also common use cases for +remark and markdown. +There are several aspects of markdown that do not translate 1-to-1 to HTML. +In some cases markdown contains more information than HTML: for example, there +are several ways to add a link in markdown (as in, autolinks: ``, +resource links: `[label](url)`, and reference links with definitions: +`[label][id]` and `[id]: url`). +In other cases HTML contains more information than markdown: there are many +tags, which add new meaning (semantics), available in HTML that aren’t available +in markdown. +If there was just one AST, it would be quite hard to perform the tasks that +several remark and rehype plugins currently do. + +**unified** is a project that transforms content with abstract syntax trees +(ASTs). +**remark** adds support for markdown to unified. +**rehype** adds support for HTML to unified. +**mdast** is the markdown AST that remark uses. +**hast** is the markdown AST that rehype uses. +This is a remark plugin that transforms mdast into hast to support rehype. + +## When should I use this? + +This project is useful when you want to turn markdown to HTML. +It opens up a whole new ecosystem with tons of plugins to do all kinds of +things. +You can [minify HTML][rehype-minify], [format HTML][rehype-format], +[make sure it’s safe][rehype-sanitize], [highlight code][rehype-highlight], +[add metadata][rehype-meta], and a lot more. + +A different plugin, [`rehype-raw`][rehype-raw], adds support for raw HTML +written inside markdown. +This is a separate plugin because supporting HTML inside markdown is a heavy +task and not always needed. +To use both together, you also have to configure `remark-rehype` with +`allowDangerousHtml: true`. + +The rehype plugin [`rehype-remark`][rehype-remark] does the inverse of this +plugin. +It turns HTML into markdown. -> Note: `remark-rehype` doesn’t deal with HTML inside the Markdown. -> You’ll need [`rehype-raw`][raw] if you’re planning on doing that. +## Install -## Note! +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 plugin is ready for the new parser in remark -([`remarkjs/remark#536`](https://github.com/remarkjs/remark/pull/536)). -The current and previous versions of the plugin work with the current and -previous versions of remark. +```sh +npm install remark-rehype +``` -## Install +In Deno with [Skypack][]: -This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): -Node 12+ is needed to use it and it must be `import`ed instead of `require`d. +```js +import remarkRehype from 'https://cdn.skypack.dev/remark-rehype@10?dts' +``` -[npm][]: +In browsers with [Skypack][]: -```sh -npm install remark-rehype +```html + ``` ## Use -Say we have the following file, `example.md`: +Say we have the following file `example.md`: ```markdown # Hello world @@ -43,10 +119,10 @@ Say we have the following file, `example.md`: Some _emphasis_, **importance**, and `code`. ``` -And our module, `example.js`, looks as follows: +And our module `example.js` looks as follows: ```js -import {readSync} from 'to-vfile' +import {read} from 'to-vfile' import {reporter} from 'vfile-reporter' import {unified} from 'unified' import remarkParse from 'remark-parse' @@ -55,25 +131,29 @@ import rehypeDocument from 'rehype-document' import rehypeFormat from 'rehype-format' import rehypeStringify from 'rehype-stringify' -const file = readSync('example.md') +main() -unified() - .use(remarkParse) - .use(remarkRehype) - .use(rehypeDocument) - .use(rehypeFormat) - .use(rehypeStringify) - .process(file) - .then((file) => { - console.error(reporter(file)) - console.log(String(file)) - }) +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkRehype) + .use(rehypeDocument) + .use(rehypeFormat) + .use(rehypeStringify) + .process(await read('example.md')) + + console.error(reporter(file)) + console.log(String(file)) +} ``` -Now, running `node example` yields: +Now, running `node example.js` yields: -```html +```txt example.md: no issues found +``` + +```html @@ -96,42 +176,326 @@ example.md: no issues found This package exports no identifiers. The default export is `remarkRehype`. -### `origin.use(remarkRehype[, destination][, options])` +### `unified().use(remarkRehype[, destination][, options])` + +Plugin that turns markdown into HTML to support rehype. + +##### `destination` + +If a [`Unified`][processor] destination processor is given, that processor runs +with a new HTML (hast) tree (bridge-mode). +As the given processor runs with a hast tree, and rehype plugins support +hast, that means rehype plugins can be used with the given processor. +The hast tree is discarded in the end. + +> 👉 **Note**: It’s highly unlikely that you want to do this. + +##### `options` + +Configuration (optional). + +###### `options.allowDangerousHtml` + +Whether to persist raw HTML in markdown in the hast tree (`boolean`, default: +`false`). +Raw HTML is available in the markdown (mdast) tree as [`html`][mdast-html] nodes +and can be embedded in the HTML (hast) tree as semistandard `raw` nodes. +Most rehype plugins ignore `raw` nodes, but two notable plugins don’t: + +* [`rehype-stringify`][rehype-stringify] also has an option + `allowDangerousHtml` which will output the raw HTML. + This is typically discouraged as noted by the option name but is useful if + you completely trust who authors the markdown +* [`rehype-raw`][rehype-raw] can handle the raw embedded HTML strings in hast + trees by parsing them into standard hast nodes (element, text, etc). + This is a heavy task as it needs a full HTML parser, but it is the only way + to support untrusted content + +###### `options.clobberPrefix` + +Prefix to use before the `id` attribute on footnotes to prevent it from +*clobbering* (`string`, default: `'user-content-'`). +DOM clobbering is this: + +```html +

+ +``` + +Elements by their ID are made available by browsers on the `window` object, +which is a security risk. +Using a prefix solves this problem. + +> 👉 **Note**: this option affects footnotes. +> Footnotes are not specified by CommonMark so they’re not supported in remark +> by default. +> They are supported by GitHub, so they can be enabled by using the remark +> plugin [`remark-gfm`][remark-gfm]. + +###### `options.footnoteLabel` + +Label to use for the footnotes section (`string`, default: `'Footnotes'`). +Affects screen readers. +Change it when the markdown is not in English. + +> 👉 **Note**: this option affects footnotes. +> Footnotes are not specified by CommonMark so they’re not supported in remark +> by default. +> They are supported by GitHub, so they can be enabled by using the remark +> plugin [`remark-gfm`][remark-gfm]. + +###### `options.footnoteBackLabel` + +Label to use from backreferences back to their footnote call (`string`, default: +`'Back to content'`). +Affects screen readers. +Change it when the markdown is not in English. + +> 👉 **Note**: this option affects footnotes. +> Footnotes are not specified by CommonMark so they’re not supported in remark +> by default. +> They are supported by GitHub, so they can be enabled by using the remark +> plugin [`remark-gfm`][remark-gfm]. + +###### `options.handlers` + +This option is a bit advanced as it requires knowledge of ASTs, so we defer +to the documentation available in [`mdast-util-to-hast`][mdast-util-to-hast]. + +###### `options.passThrough` + +This option is a bit advanced as it requires knowledge of ASTs, so we defer +to the documentation available in [`mdast-util-to-hast`][mdast-util-to-hast]. + +###### `options.unknownHandler` + +This option is a bit advanced as it requires knowledge of ASTs, so we defer +to the documentation available in [`mdast-util-to-hast`][mdast-util-to-hast]. + +## Examples + +### Example: supporting HTML in markdown naïvely + +If you completely trust the authors of the input markdown and want to allow them +to write HTML inside markdown, you can pass `allowDangerousHtml` to this plugin +(`remark-rehype`) and `rehype-stringify`: + +```js +import {unified} from 'unified' +import remarkParse from 'remark-parse' +import remarkRehype from 'remark-rehype' +import rehypeStringify from 'rehype-stringify' + +main() + +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkRehype, {allowDangerousHtml: true}) + .use(rehypeStringify, {allowDangerousHtml: true}) + .process('It works! ') + + console.log(String(file)) +} +``` + +Running that code yields: + +```html +

It works!

+``` + +> ⚠️ **Danger**: Observe that the XSS attack through the `onerror` attribute +> is still present. + +### Example: supporting HTML in markdown properly -[**remark**][remark] ([**mdast**][mdast]) plugin to bridge or mutate to -[**rehype**][rehype] ([**hast**][hast]). +If you do not trust the authors of the input markdown, or if you want to make +sure that rehype plugins can see HTML embedded in markdown, use +[`rehype-raw`][rehype-raw]. +The following example passes `allowDangerousHtml` to this plugin +(`remark-rehype`), then turns the raw embedded HTML into proper HTML nodes +(`rehype-raw`), and finally sanitizes the HTML by only allowing safe things +(`rehype-sanitize`): -###### `destination` +```js +import {unified} from 'unified' +import remarkParse from 'remark-parse' +import remarkRehype from 'remark-rehype' +import rehypeRaw from 'rehype-raw' +import rehypeSanitize from 'rehype-sanitize' +import rehypeStringify from 'rehype-stringify' + +main() + +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkRehype, {allowDangerousHtml: true}) + .use(rehypeRaw) + .use(rehypeSanitize) + .use(rehypeStringify) + .process('It works! ') + + console.log(String(file)) +} +``` + +Running that code yields: + +```html +

It works!

+``` + +> 👉 **Note**: Observe that the XSS attack through the `onerror` attribute +> is no longer present. + +### Example: footnotes in languages other than English + +If you know that the markdown is authored in a language other than English, +and you’re using `remark-gfm` to match how GitHub renders markdown, and you know +that footnotes are (or can?) be used, you should translate the labels associated +with them. + +Let’s first set the stage: + +```js +import {unified} from 'unified' +import remarkParse from 'remark-parse' +import remarkGfm from 'remark-gfm' +import remarkRehype from 'remark-rehype' +import rehypeStringify from 'rehype-stringify' + +main() + +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkGfm) + .use(remarkRehype) + .use(rehypeStringify) + .process('Hallo[^1]\n\n[^1]: Wereld!') + + console.log(String(file)) +} +``` + +Running that code yields: + +```html +

Hallo1

+

Footnotes

+
    +
  1. +

    Wereld!

    +
  2. +
+
+``` -If a [`Unified`][processor] processor is given, runs the destination processor -with the new hast tree, then, after running discards that tree and continues on -running the origin processor with the original tree ([*bridge mode*][bridge]). -Otherwise, passes the tree to further plugins (*mutate mode*). +This is a mix of English and Dutch that screen readers can’t handle nicely. +Let’s say our program does know that the markdown is in Dutch. +In that case, it’s important to translate and define the labels relating to +footnotes so that screen reader users can properly pronounce the page: + +```diff +@@ -10,7 +10,7 @@ async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkGfm) +- .use(remarkRehype) ++ .use(remarkRehype, {footnoteLabel: 'Voetnoten', footnoteBackLabel: 'Terug'}) + .use(rehypeStringify) + .process('Hallo[^1]\n\n[^1]: Wereld!') +``` + +Running the code with the above patch applied, yields: + +```diff +@@ -1,8 +1,8 @@ +

Hallo1

+-

Footnotes

++

Voetnoten

+
    +
  1. +-

    Wereld!

    ++

    Wereld!

    +
  2. +
+
+``` + +## Syntax tree + +A frequent problem arises when having to turn one syntax tree into another. +As the original tree (in this case, mdast for markdown) is in some cases +limited compared to the destination (in this case, hast for HTML) tree, +is it possible to provide more info in the original to define what the +result will be in the destination? +This is possible by defining data on mdast nodes, which this plugin will read +as instructions on what hast nodes to create. + +An example is `remark-math`, which defines semistandard math nodes that this +plugin doesn’t understand. +To solve this, `remark-math` defines instructions on mdast nodes that this +plugin does understand because they define a certain hast structure. + +As these instructions are somewhat advanced in that they requires knowledge of +ASTs, we defer to the documentation available in the low level utility we use: +[`mdast-util-to-hast`][mdast-util-to-hast]. + +## CSS -###### `options` +Assuming you know how to use (semantic) HTML and CSS, then it should generally +be straight forward to style the HTML produced by this plugin. +With CSS, you can get creative and style the results as you please. -Passed to [`mdast-util-to-hast`][to-hast]. +Some semistandard features, notably [`remark-gfm`][remark-gfm]s tasklists and +footnotes, generate HTML that be unintuitive, as it matches exactly what GitHub +produces for their website. +There is a project, [`sindresorhus/github-markdown-css`][github-markdown-css], +that exposes the stylesheet that GitHub uses for rendered markdown, which might +either be inspirational for more complex features, or can be used as-is to +exactly match how GitHub styles rendered markdown. + +## Types + +This package is fully typed with [TypeScript][]. +It exports `Options` and `Processor` types, which specify the interfaces of the +accepted options. + +## Compatibility + +Projects maintained by the unified collective are compatible with all 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. + +This plugin works with `unified` version 6+, `remark-parse` version 3+ (used in +`remark` version 7), and `rehype-stringify` version 3+ (used in `rehype` +version 5). ## Security Use of `remark-rehype` can open you up to a [cross-site scripting (XSS)][xss] attack. -Embedded [**hast**][hast] properties (`hName`, `hProperties`, `hChildren`), -custom handlers, and the `allowDangerousHtml` option all provide openings. -Use [`rehype-sanitize`][sanitize] to make the tree safe. +Embedded **[hast][]** properties (`hName`, `hProperties`, `hChildren`) in +[mdast][], custom handlers, and the `allowDangerousHtml` option all provide +openings. +Use [`rehype-sanitize`][rehype-sanitize] to make the tree safe. ## Related -* [`rehype-raw`][raw] - — Properly deal with HTML in Markdown (used after `remark-rehype`) -* [`rehype-sanitize`][sanitize] - — Sanitize HTML +* [`rehype-raw`][rehype-raw] + — rehype plugin to parse the tree again and support `raw` nodes +* [`rehype-sanitize`][rehype-sanitize] + — rehype plugin to sanitize HTML * [`rehype-remark`](https://github.com/rehypejs/rehype-remark) - — Transform HTML ([hast][]) to Markdown ([mdast][]) + — rehype plugin to turn HTML into markdown * [`rehype-retext`](https://github.com/rehypejs/rehype-retext) - — Transform HTML ([hast][]) to natural language ([nlcst][]) + — rehype plugin to support retext * [`remark-retext`](https://github.com/remarkjs/remark-retext) - — Transform Markdown ([mdast][]) to natural language ([nlcst][]) + — remark plugin to support retext ## Contribute @@ -177,6 +541,8 @@ abide by its terms. [npm]: https://docs.npmjs.com/cli/install +[skypack]: https://www.skypack.dev + [health]: https://github.com/remarkjs/.github [contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md @@ -191,22 +557,40 @@ abide by its terms. [processor]: https://github.com/unifiedjs/unified#processor -[bridge]: https://github.com/unifiedjs/unified#processing-between-syntaxes - [remark]: https://github.com/remarkjs/remark [rehype]: https://github.com/rehypejs/rehype -[raw]: https://github.com/rehypejs/rehype-raw +[unified]: https://github.com/unifiedjs/unified -[sanitize]: https://github.com/rehypejs/rehype-sanitize +[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting -[mdast]: https://github.com/syntax-tree/mdast +[typescript]: https://www.typescriptlang.org -[hast]: https://github.com/syntax-tree/hast +[rehype-minify]: https://github.com/rehypejs/rehype-minify -[nlcst]: https://github.com/syntax-tree/nlcst +[rehype-format]: https://github.com/rehypejs/rehype-format -[to-hast]: https://github.com/syntax-tree/mdast-util-to-hast#tohastnode-options +[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize -[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting +[rehype-highlight]: https://github.com/rehypejs/rehype-highlight + +[rehype-meta]: https://github.com/rehypejs/rehype-meta + +[rehype-raw]: https://github.com/rehypejs/rehype-raw + +[rehype-remark]: https://github.com/rehypejs/rehype-remark + +[rehype-stringify]: https://github.com/rehypejs/rehype/tree/main/packages/rehype-stringify + +[mdast-html]: https://github.com/syntax-tree/mdast#html + +[remark-gfm]: https://github.com/remarkjs/remark-gfm + +[mdast-util-to-hast]: https://github.com/syntax-tree/mdast-util-to-hast + +[mdast]: https://github.com/syntax-tree/mdast + +[hast]: https://github.com/syntax-tree/hast + +[github-markdown-css]: https://github.com/sindresorhus/github-markdown-css diff --git a/tsconfig.json b/tsconfig.json index e31adf83..d377f01c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "include": ["*.js"], + "include": ["lib/**/*.js", "*.js"], "compilerOptions": { "target": "ES2020", "lib": ["ES2020"],