From 376ce7586d8d7464b89f7373152c436158a38d1a Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 28 Oct 2021 14:01:22 +0200 Subject: [PATCH] Add improved docs --- index.js | 70 +---------------- lib/index.js | 78 +++++++++++++++++++ package.json | 9 ++- readme.md | 204 ++++++++++++++++++++++++++++++++++++++++---------- tsconfig.json | 2 +- 5 files changed, 252 insertions(+), 111 deletions(-) create mode 100644 lib/index.js diff --git a/index.js b/index.js index ad6fda2..0a2ccab 100644 --- a/index.js +++ b/index.js @@ -1,73 +1,7 @@ /** - * @typedef {import('unist').Node} Node - * @typedef {import('mdast').Root} MdastRoot - * @typedef {import('mdast-util-to-nlcst').ParserInstance} ParserInstance - * @typedef {import('mdast-util-to-nlcst').ParserConstructor} ParserConstructor - * @typedef {import('mdast-util-to-nlcst').Options} Options - * @typedef {import('unified').Processor} Processor - * @typedef {import('unified').Parser} Parser + * @typedef {import('./lib/index.js').Options} Options */ -import {toNlcst} from 'mdast-util-to-nlcst' - -/** - * Plugin to bridge or mutate to retext. - * - * If a destination processor is given, runs the destination with the new nlcst - * tree (bridge-mode). - * If a parser is given, returns the nlcst tree: further plugins run on that - * tree (mutate-mode). - * - * @param destination - * Either a processor (`unified().use(retextEnglish)…`) or a parser. - * @param options - * Configuration passed to `mdast-util-to-nlcst`. - */ -const remarkRetext = - /** - * @type {(import('unified').Plugin<[Processor, Options?]|[Processor], MdastRoot, MdastRoot> & import('unified').Plugin<[Parser, Options?]|[Parser], MdastRoot, Node>)} - */ - ( - /** - * @param {Processor|Parser} destination - * @param {Options|undefined} options - */ - function (destination, options) { - return destination && 'run' in destination - ? bridge(destination, options) - : mutate(destination, options) - } - ) +import remarkRetext from './lib/index.js' export default remarkRetext - -/** - * Mutate-mode. - * Further transformers run on the nlcst tree. - * - * @type {import('unified').Plugin<[Parser, Options?], MdastRoot, Node>} - */ -function mutate(parser, options) { - // Assume the parser is a retext parser. - const Parser = /** @type {ParserInstance|ParserConstructor} */ (parser) - return (node, file) => toNlcst(node, file, Parser, options) -} - -/** - * Bridge-mode. - * Runs the destination with the new nlcst tree. - * - * @type {import('unified').Plugin<[Processor, Options?], MdastRoot>} - */ -function bridge(destination, options) { - return (node, file, next) => { - // Assume the parser is a retext parser. - const Parser = /** @type {ParserConstructor|ParserInstance} */ ( - destination.freeze().Parser - ) - - destination.run(toNlcst(node, file, Parser, options), file, (error) => { - next(error) - }) - } -} diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..1d2e24c --- /dev/null +++ b/lib/index.js @@ -0,0 +1,78 @@ +/** + * @typedef {import('unist').Node} Node + * @typedef {import('mdast').Root} MdastRoot + * @typedef {import('mdast-util-to-nlcst').ParserInstance} ParserInstance + * @typedef {import('mdast-util-to-nlcst').ParserConstructor} ParserConstructor + * @typedef {import('mdast-util-to-nlcst').Options} Options + * @typedef {import('unified').Processor} Processor + * @typedef {import('unified').Parser} Parser + */ + +import {toNlcst} from 'mdast-util-to-nlcst' + +/** + * Plugin to support retext. + * + * * If a destination processor is given, runs the plugins attached to it with + * the new nlcst tree (bridge-mode). + * This given processor must have a parser attached (this can be done by + * using the plugin `retext-english` or similar) and should use other retext + * plugins. + * * If a parser is given, runs further plugins attached to the same processor + * with the new tree (mutate-mode). + * Such parsers are exported by packages like `retext-english` as `Parser`. + * You should use other retext plugins after `remark-retext`. + * + * @param destination + * Either a processor (`unified().use(retextEnglish)…`) or a parser. + * @param options + * Configuration passed to `mdast-util-to-nlcst`. + */ +const remarkRetext = + /** + * @type {(import('unified').Plugin<[Processor, Options?]|[Processor], MdastRoot, MdastRoot> & import('unified').Plugin<[Parser, Options?]|[Parser], MdastRoot, Node>)} + */ + ( + /** + * @param {Processor|Parser} destination + * @param {Options|undefined} options + */ + function (destination, options) { + return destination && 'run' in destination + ? bridge(destination, options) + : mutate(destination, options) + } + ) + +export default remarkRetext + +/** + * Mutate-mode. + * Further transformers run on the nlcst tree. + * + * @type {import('unified').Plugin<[Parser, Options?], MdastRoot, Node>} + */ +function mutate(parser, options) { + // Assume the parser is a retext parser. + const Parser = /** @type {ParserInstance|ParserConstructor} */ (parser) + return (node, file) => toNlcst(node, file, Parser, options) +} + +/** + * Bridge-mode. + * Runs the destination with the new nlcst tree. + * + * @type {import('unified').Plugin<[Processor, Options?], MdastRoot>} + */ +function bridge(destination, options) { + return (node, file, next) => { + // Assume the parser is a retext parser. + const Parser = /** @type {ParserConstructor|ParserInstance} */ ( + destination.freeze().Parser + ) + + destination.run(toNlcst(node, file, Parser, options), file, (error) => { + next(error) + }) + } +} diff --git a/package.json b/package.json index 835aedc..65ceb19 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "remark-retext", "version": "5.0.0", - "description": "remark plugin to transform to retext", + "description": "remark plugin to support retext", "license": "MIT", "keywords": [ "unified", @@ -30,6 +30,7 @@ "main": "index.js", "types": "index.d.ts", "files": [ + "lib/", "index.d.ts", "index.js" ], @@ -56,7 +57,7 @@ "xo": "^0.45.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", @@ -85,8 +86,8 @@ "ignoreCatch": true, "#": "needed `any`s", "ignoreFiles": [ - "index.d.ts", - "index.js" + "lib/index.d.ts", + "lib/index.js" ] } } diff --git a/readme.md b/readme.md index f3fe190..b60da9a 100644 --- a/readme.md +++ b/readme.md @@ -8,25 +8,72 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -[**remark**][remark] plugin to bridge or mutate to [**retext**][retext]. - -## Note! - -This plugin is ready for the new parser in remark -([`remarkjs/remark#536`](https://github.com/remarkjs/remark/pull/536)). -No change is needed: it works exactly the same now as it did previously! +**[remark][]** plugin to support **[retext][]**. + +## 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(remarkRetext, destination[, options])`](#unifieduseremarkretext-destination-options) +* [Examples](#examples) +* [Example: mutate mode](#example-mutate-mode) +* [Types](#types) +* [Compatibility](#compatibility) +* [Security](#security) +* [Related](#related) +* [Contribute](#contribute) +* [License](#license) + +## What is this? + +This package is a [unified][] ([remark][]) plugin to support [retext][]. + +**unified** is a project that transforms content with abstract syntax trees +(ASTs). +**remark** adds support for markdown to unified. +**retext** adds support for natural language to unified. +**mdast** is the markdown AST that remark uses. +**nlcst** is the natural language AST that retext uses. +This is a remark plugin that transforms mdast into nlcst to support retext. + +## When should I use this? + +This project is useful if you want to check natural language in markdown. +The retext ecosystem has many useful plugins to check prose, such as +[`retext-indefinite-article`][retext-indefinite-article] which checks that `a` +and `an` are used correctly, or [`retext-readability`][retext-readability] which +checks that sentences are not too complex. +This plugins lets you use them on markdown documents. + +This plugin is unfortunately not able to apply changes by retext plugins (such +as done by `retext-smartypants`) to the markdown content. ## Install -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. - -[npm][]: +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][]: ```sh npm install remark-retext ``` +In Deno with [Skypack][]: + +```js +import remarkRetext from 'https://cdn.skypack.dev/remark-retext@5?dts' +``` + +In browsers with [Skypack][]: + +```html + +``` + ## Use Say we have the following file, `example.md`: @@ -38,7 +85,7 @@ Say we have the following file, `example.md`: And our script, `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' @@ -47,16 +94,17 @@ import remarkRetext from 'remark-retext' import retextEnglish from 'retext-english' import retextEquality from 'retext-equality' -const file = readSync('example.md') +main() -unified() - .use(remarkParse) - .use(remarkRetext, unified().use(retextEnglish).use(retextEquality)) - .use(remarkStringify) - .process(file) - .then((file) => { - console.error(reporter(file)) - }) +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkRetext, unified().use(retextEnglish).use(retextEquality)) + .use(remarkStringify) + .process(await read('example.md')) + + console.error(reporter(file)) +} ``` Now, running `node example` yields: @@ -75,24 +123,100 @@ The default export is `remarkRetext`. ### `unified().use(remarkRetext, destination[, options])` -[**remark**][remark] ([**mdast**][mdast]) plugin to bridge or mutate to -[**retext**][retext] ([**nlcst**][nlcst]). +**[remark][]** plugin to support **[retext][]**. -###### `destination` +##### `destination` `destination` is either a parser or a processor. -If a [`Unified`][processor] processor is given, runs the destination processor -with the new nlcst tree, then, after running discards that tree and continues on -running the origin processor with the original tree ([*bridge mode*][bridge]). +* If a destination [processor][] is given, runs the plugins attached to it + with the new nlcst tree ([*bridge mode*][bridge]). + This given processor must have a parser attached (this can be done by using + the plugin `retext-english` or similar) and should use other retext plugins +* If a parser is given, runs further plugins attached to the same processor + with the new tree (*mutate mode*). + Such parsers are exported by packages like `retext-english` as `Parser`. + You should use other retext plugins after `remark-retext`. + +##### `options` + +Configuration (`Object`, optional). + +###### `options.ignore` + +List of [mdast][] node types to ignore (`Array.`). +The types `'table'`, `'tableRow'`, and `'tableCell'` are always ignored. + +###### `options.source` + +List of [mdast][] node types to mark as [nlcst][] source nodes +(`Array.`). +`'inlineCode'` is always marked as source. + +## Examples + +## Example: mutate mode + +The previous example was using *bridge* mode: the markdown AST remained for +other plugins after `remark-retext`. +This example uses *mutate* mode: the markdown AST is discarded and the natural +language AST. +This is not very useful: this is not a good way to get the plain text version +of a markdown document. + +```js +import {read} from 'to-vfile' +import {reporter} from 'vfile-reporter' +import {unified} from 'unified' +import remarkParse from 'remark-parse' +import remarkRetext from 'remark-retext' +import {Parser} from 'retext-english' +import retextEquality from 'retext-equality' +import retextStringify from 'retext-stringify' + +main() -If a parser (such as [`parse-latin`][latin], [`parse-english`][english], or -[`parse-dutch`][dutch]) is given, passes the tree to further plugins -(*mutate mode*). +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkRetext, Parser) + .use(retextEquality) + .use(retextStringify) + .process(await read('example.md')) -###### `options` + console.error(reporter(file)) + console.log(String(file)) +} +``` + +…yields: + +```txt +example.md + 1:10-1:14 warning `guys` may be insensitive, use `people`, `persons`, `folks` instead gals-man retext-equality + +⚠ 1 warning +``` + +```txt +Hello guys! +``` -Passed to [`mdast-util-to-nlcst`][to-nlcst]. +## Types + +This package is fully typed with [TypeScript][]. +It exports an `Options` type, which specifies the interface 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` version 3+, and `retext` +version 7+. ## Security @@ -155,6 +279,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 @@ -171,6 +297,8 @@ abide by its terms. [retext]: https://github.com/retextjs/retext +[unified]: https://github.com/unifiedjs/unified + [processor]: https://github.com/unifiedjs/unified#processor [bridge]: https://github.com/unifiedjs/unified#processing-between-syntaxes @@ -181,14 +309,14 @@ abide by its terms. [hast]: https://github.com/syntax-tree/hast -[latin]: https://github.com/wooorm/parse-latin - -[english]: https://github.com/wooorm/parse-english - -[dutch]: https://github.com/wooorm/parse-dutch - [to-nlcst]: https://github.com/syntax-tree/mdast-util-to-nlcst +[typescript]: https://www.typescriptlang.org + [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting [rehype]: https://github.com/rehypejs/rehype + +[retext-indefinite-article]: https://github.com/retextjs/retext-indefinite-article + +[retext-readability]: https://github.com/retextjs/retext-readability diff --git a/tsconfig.json b/tsconfig.json index e31adf8..d377f01 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "include": ["*.js"], + "include": ["lib/**/*.js", "*.js"], "compilerOptions": { "target": "ES2020", "lib": ["ES2020"],