From d7e95efb68f66589fd65671746307d1009b689bb Mon Sep 17 00:00:00 2001 From: Titus Date: Thu, 20 Jun 2019 16:16:07 +0200 Subject: [PATCH] Add rules to prefer collapsed over full references Closes GH-192. Closes GH-212. Reviewed-by: Christian Murphy --- doc/rules.md | 2 + .../index.js | 65 +++++++ .../package.json | 31 ++++ .../readme.md | 154 +++++++++++++++++ .../index.js | 71 ++++++++ .../package.json | 31 ++++ .../readme.md | 158 ++++++++++++++++++ 7 files changed, 512 insertions(+) create mode 100644 packages/remark-lint-no-unneeded-full-reference-image/index.js create mode 100644 packages/remark-lint-no-unneeded-full-reference-image/package.json create mode 100644 packages/remark-lint-no-unneeded-full-reference-image/readme.md create mode 100644 packages/remark-lint-no-unneeded-full-reference-link/index.js create mode 100644 packages/remark-lint-no-unneeded-full-reference-link/package.json create mode 100644 packages/remark-lint-no-unneeded-full-reference-link/readme.md diff --git a/doc/rules.md b/doc/rules.md index 939a4440..839d3482 100644 --- a/doc/rules.md +++ b/doc/rules.md @@ -125,6 +125,8 @@ Rules][external]. * [`no-table-indentation`](https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-no-table-indentation) — warn when tables are indented * [`no-tabs`](https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-no-tabs) — warn when hard tabs are used instead of spaces * [`no-undefined-references`](https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-no-undefined-references) — warn when references to undefined definitions are found +* [`no-unneeded-full-reference-image`](https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-no-unneeded-full-reference-image) — warn when full reference images are used if they can be collapsed +* [`no-unneeded-full-reference-link`](https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-no-unneeded-full-reference-link) — warn when full reference links are used if they can be collapsed * [`no-unused-definitions`](https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-no-unused-definitions) — warn when unused definitions are found * [`ordered-list-marker-style`](https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-ordered-list-marker-style) — warn when the markers of ordered lists violate a given style * [`ordered-list-marker-value`](https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-ordered-list-marker-value) — warn when the marker value of ordered lists violates a given style diff --git a/packages/remark-lint-no-unneeded-full-reference-image/index.js b/packages/remark-lint-no-unneeded-full-reference-image/index.js new file mode 100644 index 00000000..83311099 --- /dev/null +++ b/packages/remark-lint-no-unneeded-full-reference-image/index.js @@ -0,0 +1,65 @@ +/** + * @author Titus Wormer + * @copyright 2019 Titus Wormer + * @license MIT + * @module no-unneeded-full-reference-image + * @fileoverview + * Warn when full reference images are used that could be collapsed. + * + * Full references (such as `[Remark][remark]`) can also be written as a + * collapsed reference (`[Remark][]`) if normalising the reference text yields + * the label. + * + * @example {"name": "valid.md"} + * + * ![alpha][] + * ![Bravo][] + * ![Charlie][delta] + * + * @example {"name": "invalid.md", "label": "input"} + * + * ![alpha][alpha] + * ![Bravo][bravo] + * ![charlie][Charlie] + * + * @example {"name": "invalid.md", "label": "output"} + * + * 1:1-1:16: Remove the image label as it matches the reference text + * 2:1-2:16: Remove the image label as it matches the reference text + * 3:1-3:20: Remove the image label as it matches the reference text + */ + +'use strict' + +var rule = require('unified-lint-rule') +var visit = require('unist-util-visit') +var generated = require('unist-util-generated') +var collapseWhiteSpace = require('collapse-white-space') + +module.exports = rule( + 'remark-lint:no-unneeded-full-reference-image', + noUnneededFullReferenceImage +) + +var reason = 'Remove the image label as it matches the reference text' + +function noUnneededFullReferenceImage(tree, file) { + visit(tree, 'imageReference', visitor) + + function visitor(node) { + if ( + generated(node) || + node.referenceType !== 'full' || + normalize(node.alt) !== node.identifier + ) { + return + } + + file.message(reason, node) + } +} + +// See: +function normalize(value) { + return collapseWhiteSpace(value).toLowerCase() +} diff --git a/packages/remark-lint-no-unneeded-full-reference-image/package.json b/packages/remark-lint-no-unneeded-full-reference-image/package.json new file mode 100644 index 00000000..4b61262f --- /dev/null +++ b/packages/remark-lint-no-unneeded-full-reference-image/package.json @@ -0,0 +1,31 @@ +{ + "name": "remark-lint-no-unneeded-full-reference-image", + "version": "0.0.0", + "description": "remark-lint rule to warn when full reference images are used if they can be collapsed", + "license": "MIT", + "keywords": [ + "remark", + "lint", + "rule", + "full", + "collapsed", + "reference", + "image" + ], + "repository": "https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-no-unneeded-full-reference-image", + "bugs": "https://github.com/remarkjs/remark-lint/issues", + "author": "Titus Wormer (https://wooorm.com)", + "contributors": [ + "Titus Wormer (https://wooorm.com)" + ], + "files": [ + "index.js" + ], + "dependencies": { + "collapse-white-space": "^1.0.0", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.4.0" + }, + "xo": false +} diff --git a/packages/remark-lint-no-unneeded-full-reference-image/readme.md b/packages/remark-lint-no-unneeded-full-reference-image/readme.md new file mode 100644 index 00000000..f7180233 --- /dev/null +++ b/packages/remark-lint-no-unneeded-full-reference-image/readme.md @@ -0,0 +1,154 @@ + + +# remark-lint-no-unneeded-full-reference-image + +[![Build][build-badge]][build] +[![Coverage][coverage-badge]][coverage] +[![Downloads][downloads-badge]][downloads] +[![Size][size-badge]][size] +[![Sponsors][sponsors-badge]][collective] +[![Backers][backers-badge]][collective] +[![Chat][chat-badge]][chat] + +Warn when full reference images are used that could be collapsed. + +Full references (such as `[Remark][remark]`) can also be written as a +collapsed reference (`[Remark][]`) if normalising the reference text yields +the label. + +## Presets + +This rule is not included in any default preset + +## Example + +##### `valid.md` + +###### In + +```markdown +![alpha][] +![Bravo][] +![Charlie][delta] +``` + +###### Out + +No messages. + +##### `invalid.md` + +###### In + +```markdown +![alpha][alpha] +![Bravo][bravo] +![charlie][Charlie] +``` + +###### Out + +```text +1:1-1:16: Remove the image label as it matches the reference text +2:1-2:16: Remove the image label as it matches the reference text +3:1-3:20: Remove the image label as it matches the reference text +``` + +## Install + +[npm][]: + +```sh +npm install remark-lint-no-unneeded-full-reference-image +``` + +## Use + +You probably want to use it on the CLI through a config file: + +```diff + ... + "remarkConfig": { + "plugins": [ + ... + "lint", ++ "lint-no-unneeded-full-reference-image", + ... + ] + } + ... +``` + +Or use it on the CLI directly + +```sh +remark -u lint -u lint-no-unneeded-full-reference-image readme.md +``` + +Or use this on the API: + +```diff + var remark = require('remark'); + var report = require('vfile-reporter'); + + remark() + .use(require('remark-lint')) ++ .use(require('remark-lint-no-unneeded-full-reference-image')) + .process('_Emphasis_ and **importance**', function (err, file) { + console.error(report(err || file)); + }); +``` + +## Contribute + +See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways +to get started. +See [`support.md`][support] for ways to get help. + +This project has a [Code of Conduct][coc]. +By interacting with this repository, organisation, or community you agree to +abide by its terms. + +## License + +[MIT][license] © [Titus Wormer][author] + +[build-badge]: https://img.shields.io/travis/remarkjs/remark-lint/master.svg + +[build]: https://travis-ci.org/remarkjs/remark-lint + +[coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-lint.svg + +[coverage]: https://codecov.io/github/remarkjs/remark-lint + +[downloads-badge]: https://img.shields.io/npm/dm/remark-lint-no-unneeded-full-reference-image.svg + +[downloads]: https://www.npmjs.com/package/remark-lint-no-unneeded-full-reference-image + +[size-badge]: https://img.shields.io/bundlephobia/minzip/remark-lint-no-unneeded-full-reference-image.svg + +[size]: https://bundlephobia.com/result?p=remark-lint-no-unneeded-full-reference-image + +[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg + +[backers-badge]: https://opencollective.com/unified/backers/badge.svg + +[collective]: https://opencollective.com/unified + +[chat-badge]: https://img.shields.io/badge/join%20the%20community-on%20spectrum-7b16ff.svg + +[chat]: https://spectrum.chat/unified/remark + +[npm]: https://docs.npmjs.com/cli/install + +[health]: https://github.com/remarkjs/.github + +[contributing]: https://github.com/remarkjs/.github/blob/master/contributing.md + +[support]: https://github.com/remarkjs/.github/blob/master/support.md + +[coc]: https://github.com/remarkjs/.github/blob/master/code-of-conduct.md + +[license]: https://github.com/remarkjs/remark-lint/blob/master/license + +[author]: https://wooorm.com diff --git a/packages/remark-lint-no-unneeded-full-reference-link/index.js b/packages/remark-lint-no-unneeded-full-reference-link/index.js new file mode 100644 index 00000000..d0d4125c --- /dev/null +++ b/packages/remark-lint-no-unneeded-full-reference-link/index.js @@ -0,0 +1,71 @@ +/** + * @author Titus Wormer + * @copyright 2019 Titus Wormer + * @license MIT + * @module no-unneeded-full-reference-link + * @fileoverview + * Warn when full reference links are used that could be collapsed. + * + * Full references (such as `[Remark][remark]`) can also be written as a + * collapsed reference (`[Remark][]`) if normalising the reference text yields + * the label. + * + * @example {"name": "valid.md"} + * + * [alpha][] + * [Bravo][] + * [Charlie][delta] + * + * This only works if the link text is a `text` node: + * [`echo`][] + * [*foxtrot*][] + * + * @example {"name": "invalid.md", "label": "input"} + * + * [alpha][alpha] + * [Bravo][bravo] + * [charlie][Charlie] + * + * @example {"name": "invalid.md", "label": "output"} + * + * 1:1-1:15: Remove the link label as it matches the reference text + * 2:1-2:15: Remove the link label as it matches the reference text + * 3:1-3:19: Remove the link label as it matches the reference text + */ + +'use strict' + +var rule = require('unified-lint-rule') +var visit = require('unist-util-visit') +var generated = require('unist-util-generated') +var collapseWhiteSpace = require('collapse-white-space') + +module.exports = rule( + 'remark-lint:no-unneeded-full-reference-link', + noUnneededFullReferenceLink +) + +var reason = 'Remove the link label as it matches the reference text' + +function noUnneededFullReferenceLink(tree, file) { + visit(tree, 'linkReference', visitor) + + function visitor(node) { + if ( + generated(node) || + node.referenceType !== 'full' || + node.children.length !== 1 || + node.children[0].type !== 'text' || + normalize(node.children[0].value) !== node.identifier + ) { + return + } + + file.message(reason, node) + } +} + +// See: +function normalize(value) { + return collapseWhiteSpace(value).toLowerCase() +} diff --git a/packages/remark-lint-no-unneeded-full-reference-link/package.json b/packages/remark-lint-no-unneeded-full-reference-link/package.json new file mode 100644 index 00000000..6caba5ad --- /dev/null +++ b/packages/remark-lint-no-unneeded-full-reference-link/package.json @@ -0,0 +1,31 @@ +{ + "name": "remark-lint-no-unneeded-full-reference-link", + "version": "0.0.0", + "description": "remark-lint rule to warn when full reference links are used if they can be collapsed", + "license": "MIT", + "keywords": [ + "remark", + "lint", + "rule", + "full", + "collapsed", + "reference", + "link" + ], + "repository": "https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-no-unneeded-full-reference-link", + "bugs": "https://github.com/remarkjs/remark-lint/issues", + "author": "Titus Wormer (https://wooorm.com)", + "contributors": [ + "Titus Wormer (https://wooorm.com)" + ], + "files": [ + "index.js" + ], + "dependencies": { + "collapse-white-space": "^1.0.0", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.4.0" + }, + "xo": false +} diff --git a/packages/remark-lint-no-unneeded-full-reference-link/readme.md b/packages/remark-lint-no-unneeded-full-reference-link/readme.md new file mode 100644 index 00000000..8607ed9c --- /dev/null +++ b/packages/remark-lint-no-unneeded-full-reference-link/readme.md @@ -0,0 +1,158 @@ + + +# remark-lint-no-unneeded-full-reference-link + +[![Build][build-badge]][build] +[![Coverage][coverage-badge]][coverage] +[![Downloads][downloads-badge]][downloads] +[![Size][size-badge]][size] +[![Sponsors][sponsors-badge]][collective] +[![Backers][backers-badge]][collective] +[![Chat][chat-badge]][chat] + +Warn when full reference links are used that could be collapsed. + +Full references (such as `[Remark][remark]`) can also be written as a +collapsed reference (`[Remark][]`) if normalising the reference text yields +the label. + +## Presets + +This rule is not included in any default preset + +## Example + +##### `valid.md` + +###### In + +```markdown +[alpha][] +[Bravo][] +[Charlie][delta] + +This only works if the link text is a `text` node: +[`echo`][] +[*foxtrot*][] +``` + +###### Out + +No messages. + +##### `invalid.md` + +###### In + +```markdown +[alpha][alpha] +[Bravo][bravo] +[charlie][Charlie] +``` + +###### Out + +```text +1:1-1:15: Remove the link label as it matches the reference text +2:1-2:15: Remove the link label as it matches the reference text +3:1-3:19: Remove the link label as it matches the reference text +``` + +## Install + +[npm][]: + +```sh +npm install remark-lint-no-unneeded-full-reference-link +``` + +## Use + +You probably want to use it on the CLI through a config file: + +```diff + ... + "remarkConfig": { + "plugins": [ + ... + "lint", ++ "lint-no-unneeded-full-reference-link", + ... + ] + } + ... +``` + +Or use it on the CLI directly + +```sh +remark -u lint -u lint-no-unneeded-full-reference-link readme.md +``` + +Or use this on the API: + +```diff + var remark = require('remark'); + var report = require('vfile-reporter'); + + remark() + .use(require('remark-lint')) ++ .use(require('remark-lint-no-unneeded-full-reference-link')) + .process('_Emphasis_ and **importance**', function (err, file) { + console.error(report(err || file)); + }); +``` + +## Contribute + +See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways +to get started. +See [`support.md`][support] for ways to get help. + +This project has a [Code of Conduct][coc]. +By interacting with this repository, organisation, or community you agree to +abide by its terms. + +## License + +[MIT][license] © [Titus Wormer][author] + +[build-badge]: https://img.shields.io/travis/remarkjs/remark-lint/master.svg + +[build]: https://travis-ci.org/remarkjs/remark-lint + +[coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-lint.svg + +[coverage]: https://codecov.io/github/remarkjs/remark-lint + +[downloads-badge]: https://img.shields.io/npm/dm/remark-lint-no-unneeded-full-reference-link.svg + +[downloads]: https://www.npmjs.com/package/remark-lint-no-unneeded-full-reference-link + +[size-badge]: https://img.shields.io/bundlephobia/minzip/remark-lint-no-unneeded-full-reference-link.svg + +[size]: https://bundlephobia.com/result?p=remark-lint-no-unneeded-full-reference-link + +[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg + +[backers-badge]: https://opencollective.com/unified/backers/badge.svg + +[collective]: https://opencollective.com/unified + +[chat-badge]: https://img.shields.io/badge/join%20the%20community-on%20spectrum-7b16ff.svg + +[chat]: https://spectrum.chat/unified/remark + +[npm]: https://docs.npmjs.com/cli/install + +[health]: https://github.com/remarkjs/.github + +[contributing]: https://github.com/remarkjs/.github/blob/master/contributing.md + +[support]: https://github.com/remarkjs/.github/blob/master/support.md + +[coc]: https://github.com/remarkjs/.github/blob/master/code-of-conduct.md + +[license]: https://github.com/remarkjs/remark-lint/blob/master/license + +[author]: https://wooorm.com