From 3894be8ba1733fb134f096a7b1d51029d3aa3bfa Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Sun, 23 Aug 2020 13:54:59 +0200 Subject: [PATCH] Add MDX support Closes GH-270. Closes GH-271. --- cli.js | 16 +++++++++++++- index.js | 11 ++++++++++ package.json | 1 + readme.md | 50 ++++++++++++++++++++++++++++++++++++++++-- test/api.js | 20 +++++++++++++++++ test/cli.js | 16 ++++++++++++++ test/fixtures/four.mdx | 4 ++++ 7 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/four.mdx diff --git a/cli.js b/cli.js index 7829859..e5039ed 100755 --- a/cli.js +++ b/cli.js @@ -9,6 +9,7 @@ var unified = require('unified') var markdown = require('remark-parse') var html = require('rehype-parse') var frontmatter = require('remark-frontmatter') +var mdx = require('remark-mdx') var english = require('retext-english') var remark2retext = require('remark-retext') var rehype2retext = require('rehype-retext') @@ -30,6 +31,7 @@ var textExtensions = [ 'ron' ] var htmlExtensions = ['htm', 'html'] +var mdxExtensions = ['mdx'] // Update messages. notifier({pkg: pack}).notify() @@ -45,6 +47,7 @@ var cli = meow( ' -q, --quiet output only warnings and errors', ' -t, --text treat input as plain-text (not markdown)', ' -l, --html treat input as html (not markdown)', + ' --mdx treat input as mdx (not markdown)', ' -d, --diff ignore unchanged lines (affects Travis only)', ' --stdin read from stdin', '', @@ -62,6 +65,7 @@ var cli = meow( help: {type: 'boolean', alias: 'h'}, stdin: {type: 'boolean'}, text: {type: 'boolean', alias: 't'}, + mdx: {type: 'boolean'}, html: {type: 'boolean', alias: 'l'}, diff: {type: 'boolean', alias: 'd'}, quiet: {type: 'boolean', alias: 'q'}, @@ -71,7 +75,11 @@ var cli = meow( ) // Set-up. -var extensions = cli.flags.html ? htmlExtensions : textExtensions +var extensions = cli.flags.html + ? htmlExtensions + : cli.flags.mdx + ? mdxExtensions + : textExtensions var defaultGlobs = ['{docs/**/,doc/**/,}*.{' + extensions.join(',') + '}'] var silentlyIgnore var globs @@ -127,6 +135,12 @@ function transform(options) { if (cli.flags.html) { plugins = [html, [rehype2retext, unified().use({plugins: plugins})]] + } else if (cli.flags.mdx) { + plugins = [ + markdown, + mdx, + [remark2retext, unified().use({plugins: plugins})] + ] } else if (!cli.flags.text) { plugins = [ markdown, diff --git a/index.js b/index.js index 29e1880..547f412 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,7 @@ var VFile = require('vfile') var unified = require('unified') var markdown = require('remark-parse') var frontmatter = require('remark-frontmatter') +var mdx = require('remark-mdx') var html = require('rehype-parse') var english = require('retext-english') var equality = require('retext-equality') @@ -16,6 +17,7 @@ var filter = require('./filter') module.exports = alex alex.text = noMarkdown alex.markdown = alex +alex.mdx = mdxParse alex.html = htmlParse function makeText(config) { @@ -63,6 +65,15 @@ function alex(value, config) { ) } +// Alex, for MDX. +function mdxParse(value, config) { + return core( + value, + config, + unified().use(markdown).use(mdx).use(remark2retext, makeText(config)) + ) +} + // Alex, for HTML. function htmlParse(value, config) { return core( diff --git a/package.json b/package.json index 668458b..8d71aba 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "rehype-parse": "^7.0.0", "rehype-retext": "^2.0.1", "remark-frontmatter": "^2.0.0", + "remark-mdx": "^2.0.0-next.7", "remark-message-control": "^6.0.0", "remark-parse": "^8.0.0", "remark-retext": "^4.0.0", diff --git a/readme.md b/readme.md index 9b9c182..d9ee378 100644 --- a/readme.md +++ b/readme.md @@ -26,7 +26,7 @@ Give **alex** a spin on the [Online demo »][demo]. * [x] Helps to get better at considerate writing * [x] Catches many possible offences * [x] Suggests helpful alternatives -* [x] Reads plain text, HTML, and markdown as input +* [x] Reads plain text, HTML, MDX, or markdown as input * [x] Stylish ## Install @@ -60,6 +60,7 @@ Or you can follow this step-by-step tutorial: * [API](#api) * [`alex(value, config)`](#alexvalue-config) * [`alex.markdown(value, config)`](#alexmarkdownvalue-config) + * [`alex.mdx(value, config)`](#alexmdxvalue-config) * [`alex.html(value, config)`](#alexhtmlvalue-config) * [`alex.text(value, config)`](#alextextvalue-config) * [Workflow](#workflow) @@ -107,7 +108,7 @@ like][literals] are not warned about. * Ember — [`yohanmishkin/ember-cli-alex`](https://github.com/yohanmishkin/ember-cli-alex) * Probot — [`swinton/linter-alex`](https://github.com/swinton/linter-alex) * GitHub Actions — [`brown-ccv/alex-recommends`](https://github.com/marketplace/actions/alex-recommends) -* GitHub Actions (reviewdog) — [`reviewdog/action-alex`](https://github.com/marketplace/actions/run-alex-with-reviewdog) +* GitHub Actions (reviewdog) — [`reviewdog/action-alex`](https://github.com/marketplace/actions/run-alex-with-reviewdog) * Vim — [`w0rp/ale`](https://github.com/w0rp/ale) * Browser extension — [`skn0tt/alex-browser-extension`](https://github.com/skn0tt/alex-browser-extension) * Contentful - [`stefanjudis/alex-js-contentful-ui-extension`](https://github.com/stefanjudis/alex-js-contentful-ui-extension) @@ -309,6 +310,7 @@ See `$ alex --help` for more information. > When no input files are given to **alex**, it searches for files in the > current directory, `doc`, and `docs`. +> If `--mdx` is given, it searches for `mdx` extensions. > If `--html` is given, it searches for `htm` and `html` extensions. > Otherwise, it searches for `txt`, `text`, `md`, `mkd`, `mkdn`, `mkdown`, > `ron`, and `markdown` extensions. @@ -369,6 +371,46 @@ Yields: ] ``` +### `alex.mdx(value, config)` + +Check [MDX][] (ignoring syntax). + +> Note: the syntax for [MDX@2][mdx-next], while currently in beta, is used in +> alex. + +###### Parameters + +* `value` ([`VFile`][vfile] or `string`) — MDX document +* `config` (`Object`, optional) — See the [Configuration][] section + +###### Returns + +[`VFile`][vfile]. + +###### Example + +```js +alex.mdx('He walked to class.').messages +``` + +Yields: + +```js +[ + [1:12-1:14: `He` may be insensitive, use `They`, `It` instead] { + reason: '`He` may be insensitive, use `They`, `It` instead', + line: 1, + column: 12, + location: { start: [Object], end: [Object] }, + source: 'retext-equality', + ruleId: 'he-she', + fatal: false, + actual: 'He', + expected: [ 'They', 'It' ] + } +] +``` + ### `alex.html(value, config)` Check HTML (ignoring syntax). @@ -635,3 +677,7 @@ Lots of [people helped since][contributors]! [ignoring-files]: #ignoring-files [alexignore]: #alexignore + +[mdx]: https://mdxjs.com + +[mdx-next]: https://github.com/mdx-js/mdx/issues/1041 diff --git a/test/api.js b/test/api.js index 3a9a5f0..f6d741f 100644 --- a/test/api.js +++ b/test/api.js @@ -6,6 +6,7 @@ var test = require('tape') var alex = require('..') var html = fs.readFileSync(path.join(__dirname, 'fixtures', 'three.html')) +var mdx = fs.readFileSync(path.join(__dirname, 'fixtures', 'four.mdx')) // Tests. Note that these are small because alex is in fact // just a collection of well-tested modules. @@ -318,5 +319,24 @@ test('alex()', function (t) { 'alex.html() with deny and profanity config' ) + t.deepEqual( + alex.mdx(mdx).messages.map(String), + [ + '3:1-3:4: `She` may be insensitive, use `They`, `It` instead', + '3:32-3:38: Don’t use `asshat`, it’s profane', + '3:70-3:74: Be careful with `butt`, it’s profane in some cases' + ], + 'alex.mdx()' + ) + + t.deepEqual( + alex.mdx(mdx, ['butt']).messages.map(String), + [ + '3:1-3:4: `She` may be insensitive, use `They`, `It` instead', + '3:32-3:38: Don’t use `asshat`, it’s profane' + ], + 'alex.mdx() with options' + ) + t.end() }) diff --git a/test/cli.js b/test/cli.js index 890c71c..eedf00d 100644 --- a/test/cli.js +++ b/test/cli.js @@ -145,6 +145,22 @@ test('alex-cli', function (t) { } }) + t.test('mdx', function (t) { + var fp = path.join('test', 'fixtures') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp + ' --mdx', onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err.code, /2 warnings/.test(stderr), stdout], + [1, true, ''], + 'should work' + ) + } + }) + t.test('successful', function (t) { var fp = path.join('test', 'fixtures', 'ok.txt') diff --git a/test/fixtures/four.mdx b/test/fixtures/four.mdx new file mode 100644 index 0000000..e320915 --- /dev/null +++ b/test/fixtures/four.mdx @@ -0,0 +1,4 @@ +We’ve confirmed `his` identity. + +She walked to class. Eric, the asshat, is pretty set on beating your butt +for the sheriff.