mirror of
https://github.com/remarkjs/remark-lint.git
synced 2024-10-27 03:37:50 +03:00
Add better external rule support, and refactor module
* Remove requirement for synchronous rules to accept, and invoke, a `done` handler; * Add support for returning promises, generators, from rules. * Add `doc/external.md`, with a description on how to use and create external rule packages; * Add structural fixtures per-rule inline, which are now shown in (improved) `doc/rules.md`, and used in testing each rule; * Add contributors to `package.json`; * Remove history before stable from changelog; * Refactor tests to use `tape` instead of `mocha`; * Add automated generation of `rules.js` index; * Fix incorrect badges.
This commit is contained in:
parent
60907ad17e
commit
8dedd190c1
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
.DS_Store
|
||||
*.log
|
||||
coverage/
|
||||
.nyc_output/
|
||||
node_modules/
|
||||
remark-lint.js
|
||||
remark-lint.min.js
|
||||
|
@ -1 +0,0 @@
|
||||
test
|
@ -5,7 +5,6 @@ node_js:
|
||||
- '4.0'
|
||||
- '5.0'
|
||||
- '6.0'
|
||||
sudo: false
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
deploy:
|
||||
|
207
doc/external.md
Normal file
207
doc/external.md
Normal file
@ -0,0 +1,207 @@
|
||||
# External rules
|
||||
|
||||
External rules make it easy to develop and publish small linting rules
|
||||
for markdown.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Using external rules](#using-external-rules)
|
||||
* [Creating external rules](#creating-external-rules)
|
||||
|
||||
## Using external rules
|
||||
|
||||
External rules can be used by passing their file-path or their name,
|
||||
in which case `remark-lint-` can be omitted, in an `external` array
|
||||
to **remark-lint**. This only works in Node.js.
|
||||
|
||||
Alternatively, load modules yourself and pass them in the `external` array too.
|
||||
|
||||
### CLI
|
||||
|
||||
Say we are in the following directory: `~/projects/things`.
|
||||
|
||||
Create a `.remarkrc` file and add the following JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugins": {
|
||||
"lint": {
|
||||
"external": [
|
||||
"no-empty-sections"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Add a markdown file, such as `readme.md` file, which looks as follows:
|
||||
|
||||
```md
|
||||
# A
|
||||
|
||||
## B (this section is empty!)
|
||||
|
||||
## C
|
||||
```
|
||||
|
||||
Then, install the required dependencies:
|
||||
|
||||
```sh
|
||||
npm install -g remark-cli remark-lint remark-lint-no-empty-sections
|
||||
```
|
||||
|
||||
Now, run the following in your shell, from the same directory:
|
||||
|
||||
```sh
|
||||
# This will process all markdown files in the current
|
||||
# directory, and pass the through the specified plugins.
|
||||
remark .
|
||||
```
|
||||
|
||||
That should show a report like:
|
||||
|
||||
```sh
|
||||
readme.md
|
||||
5:1-5:5 warning Remove empty section: "B (this section is empty!)" empty-sections
|
||||
|
||||
⚠ 1 warning
|
||||
```
|
||||
|
||||
### Programmatic
|
||||
|
||||
Say we have a file, `example.md`, which looks as follows:
|
||||
|
||||
```md
|
||||
[link](http://example.com/);
|
||||
```
|
||||
|
||||
And `example.js` next to it:
|
||||
|
||||
```js
|
||||
var fs = require('fs');
|
||||
var remark = require('remark');
|
||||
var lint = require('remark-lint');
|
||||
var report = require('vfile-reporter');
|
||||
var doc = fs.readFileSync('example.md', 'utf8');
|
||||
|
||||
remark()
|
||||
.use(lint, {external: ['no-url-trailing-slash']})
|
||||
.process(doc, function (err, file) {
|
||||
console.log(report(err || file));
|
||||
});
|
||||
```
|
||||
|
||||
Then, install the required dependencies:
|
||||
|
||||
```sh
|
||||
npm install remark remark-lint remark-lint-no-url-trailing-slash
|
||||
```
|
||||
|
||||
Finally, run `example.js` with Node:
|
||||
|
||||
```sh
|
||||
node example.js
|
||||
```
|
||||
|
||||
Yields:
|
||||
|
||||
```txt
|
||||
1:1-1:28 warning Remove trailing slash (http://example.com) trailing-slash
|
||||
|
||||
⚠ 1 warning
|
||||
```
|
||||
|
||||
## Creating external rules
|
||||
|
||||
External rule packages expose an object of dash-cased rule id’s to
|
||||
functions.
|
||||
|
||||
`index.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
'code-js-flag': require('./rules/code-js-flag.js')
|
||||
};
|
||||
```
|
||||
|
||||
### Synchronous
|
||||
|
||||
Each rule is a function which gets passed a [`root`][root] node,
|
||||
a [virtual file][vfile], and a setting.
|
||||
|
||||
The setting is never `true` or `false`, those are used later to filter
|
||||
messages. Rules always run, even when they’re turned off, as they can
|
||||
be turned on from within markdown code through [comments][]
|
||||
|
||||
An example, `./rules/code-js-flag.js`, is as follows:
|
||||
|
||||
```js
|
||||
var visit = require('unist-util-visit');
|
||||
|
||||
module.exports = rule;
|
||||
|
||||
var valid = ['js', 'javascript', 'es', 'es6', 'javascript'];
|
||||
var def = valid[0];
|
||||
|
||||
function rule(ast, file, setting) {
|
||||
pref = setting == null ? def : setting;
|
||||
|
||||
if (valid.indexOf(pref) === -1) {
|
||||
/* `file.fail` is for invalid, unrecoverable things, **not** for
|
||||
* linting messages. */
|
||||
file.fail(pref + ' is not a valid JavaScript extension');
|
||||
return
|
||||
}
|
||||
|
||||
visit(ast, 'code', function (node) {
|
||||
/* Emit a linting message, only for JS code though. */
|
||||
if (valid.indexOf(node.lang) !== -1 && node.lang !== pref) {
|
||||
file.warn(
|
||||
'JavaScript code blocks should use `' + pref + '` as a ' +
|
||||
'language flag, not `' + node.lang + '`',
|
||||
node
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Promises
|
||||
|
||||
A rule can return a promise, this will automatically switch everything
|
||||
to asynchronous and wait for the rule to resolve or reject before
|
||||
continuing on. Note: Do not resolve a value. Rejecting an error is OK.
|
||||
|
||||
```js
|
||||
function rule(ast, file, setting) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
// ...do async things.
|
||||
setImmediate(function () {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Callbacks
|
||||
|
||||
If a rule has a fourth parameters, `next`, it must be invoked, and it
|
||||
may be invoked asynchronously. An error may be given to `next` to stop
|
||||
all processing.
|
||||
|
||||
```js
|
||||
function rule(ast, file, setting, next) {
|
||||
/* ...do async things. */
|
||||
setImmediate(function () {
|
||||
next();
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
<!--Definitions:-->
|
||||
|
||||
[root]: https://github.com/wooorm/mdast#root
|
||||
|
||||
[vfile]: https://github.com/wooorm/vfile
|
||||
|
||||
[comments]: https://github.com/wooorm/remark-lint#configuring-remark-lint
|
3271
doc/rules.md
3271
doc/rules.md
File diff suppressed because it is too large
Load Diff
65
history.md
65
history.md
@ -124,68 +124,3 @@
|
||||
|
||||
1.0.0 / 2015-08-17
|
||||
==================
|
||||
|
||||
* Update dependencies ([`4936d35`](https://github.com/wooorm/remark-lint/commit/4936d35))
|
||||
|
||||
0.4.5 / 2015-08-08
|
||||
==================
|
||||
|
||||
* Fix typo in definition-case warning ([`490ac16`](https://github.com/wooorm/remark-lint/commit/490ac16))
|
||||
|
||||
0.4.4 / 2015-08-05
|
||||
==================
|
||||
|
||||
* Remove maximum-line-length warnings on definitions ([`1119ca8`](https://github.com/wooorm/remark-lint/commit/1119ca8))
|
||||
* Add `linter-markdown` to `readme.md` ([`7de8847`](https://github.com/wooorm/remark-lint/commit/7de8847))
|
||||
|
||||
0.4.3 / 2015-08-04
|
||||
==================
|
||||
|
||||
* Fix block-quotes without children ([`a9aaff7`](https://github.com/wooorm/remark-lint/commit/a9aaff7))
|
||||
* Update mdast dev-dependency ([`34df79c`](https://github.com/wooorm/remark-lint/commit/34df79c))
|
||||
* Add vfile as a dev-dependency ([`84d1ce3`](https://github.com/wooorm/remark-lint/commit/84d1ce3))
|
||||
|
||||
0.4.2 / 2015-07-12
|
||||
==================
|
||||
|
||||
* Remove peer-dependencies ([`8d70fcf`](https://github.com/wooorm/remark-lint/commit/8d70fcf))
|
||||
|
||||
0.4.1 / 2015-07-05
|
||||
==================
|
||||
|
||||
* Remove component support ([`58d7e6b`](https://github.com/wooorm/remark-lint/commit/58d7e6b))
|
||||
* Refactor to externalise `lib/utilities/` ([`eb78529`](https://github.com/wooorm/remark-lint/commit/eb78529))
|
||||
|
||||
0.4.0 / 2015-06-29
|
||||
==================
|
||||
|
||||
* Add gap support ([`136e760`](https://github.com/wooorm/remark-lint/commit/136e760))
|
||||
* Update mdast ([`2d122e4`](https://github.com/wooorm/remark-lint/commit/2d122e4))
|
||||
|
||||
0.3.0 / 2015-06-20
|
||||
==================
|
||||
|
||||
* Add checkbox-content-indent rule ([`7b55519`](https://github.com/wooorm/remark-lint/commit/7b55519))
|
||||
* Fix dot-files from being read as fixtures ([`ecbec2c`](https://github.com/wooorm/remark-lint/commit/ecbec2c))
|
||||
* Add checkbox-character-style rule ([`7ed4579`](https://github.com/wooorm/remark-lint/commit/7ed4579))
|
||||
* Fix tests for invalid position given my mdast-range ([`55d1128`](https://github.com/wooorm/remark-lint/commit/55d1128))
|
||||
* Add missing jsdoc comment ([`63b83b9`](https://github.com/wooorm/remark-lint/commit/63b83b9))
|
||||
* Update eslint ([`a3b0829`](https://github.com/wooorm/remark-lint/commit/a3b0829))
|
||||
* Update mdast, mdast-yaml-config ([`52bac04`](https://github.com/wooorm/remark-lint/commit/52bac04))
|
||||
|
||||
0.2.0 / 2015-06-13
|
||||
==================
|
||||
|
||||
* Remove mdast-usage, add mdast-yaml-config as dependencies ([`053674f`](https://github.com/wooorm/remark-lint/commit/053674f))
|
||||
* Add images to blacklist for maximum-line-length ([`ba6d270`](https://github.com/wooorm/remark-lint/commit/ba6d270))
|
||||
* Refactor to use rawgit references to images in `readme.md` ([`3f6344c`](https://github.com/wooorm/remark-lint/commit/3f6344c))
|
||||
* Add support for external rules ([`5162a09`](https://github.com/wooorm/remark-lint/commit/5162a09))
|
||||
* Refactor additional, fileless, rules support ([`6d2ba65`](https://github.com/wooorm/remark-lint/commit/6d2ba65))
|
||||
* Adds support for automatic doc generation for file-less rules ([`29965a3`](https://github.com/wooorm/remark-lint/commit/29965a3))
|
||||
* Add `reset` docs to rule generation script ([`77b8bfd`](https://github.com/wooorm/remark-lint/commit/77b8bfd))
|
||||
* Adds `reset` rule to docs ([`90a5f8a`](https://github.com/wooorm/remark-lint/commit/90a5f8a))
|
||||
* Update wording re rules in `readme.md` ([`00d9ba4`](https://github.com/wooorm/remark-lint/commit/00d9ba4))
|
||||
* Update rule count in `readme.md` ([`f937cf4`](https://github.com/wooorm/remark-lint/commit/f937cf4))
|
||||
|
||||
0.1.0 / 2015-06-11
|
||||
==================
|
||||
|
@ -165,9 +165,7 @@ function ruleFactory(id, rule, options) {
|
||||
var scope = file.namespace('remark-lint');
|
||||
|
||||
/* Track new messages per file. */
|
||||
if (scope.index === undefined || scope.index === null) {
|
||||
scope.index = file.messages.length;
|
||||
}
|
||||
scope.index = file.messages.length;
|
||||
|
||||
fn(ast, file, options, function (err) {
|
||||
var messages = file.messages;
|
||||
|
61
lib/rules.js
Normal file
61
lib/rules.js
Normal file
@ -0,0 +1,61 @@
|
||||
/* This file is generated. */
|
||||
'use strict';
|
||||
module.exports = {
|
||||
'blockquote-indentation': require('./rules/blockquote-indentation.js'),
|
||||
'checkbox-character-style': require('./rules/checkbox-character-style.js'),
|
||||
'checkbox-content-indent': require('./rules/checkbox-content-indent.js'),
|
||||
'code-block-style': require('./rules/code-block-style.js'),
|
||||
'definition-case': require('./rules/definition-case.js'),
|
||||
'definition-spacing': require('./rules/definition-spacing.js'),
|
||||
'emphasis-marker': require('./rules/emphasis-marker.js'),
|
||||
'fenced-code-flag': require('./rules/fenced-code-flag.js'),
|
||||
'fenced-code-marker': require('./rules/fenced-code-marker.js'),
|
||||
'file-extension': require('./rules/file-extension.js'),
|
||||
'final-definition': require('./rules/final-definition.js'),
|
||||
'final-newline': require('./rules/final-newline.js'),
|
||||
'first-heading-level': require('./rules/first-heading-level.js'),
|
||||
'hard-break-spaces': require('./rules/hard-break-spaces.js'),
|
||||
'heading-increment': require('./rules/heading-increment.js'),
|
||||
'heading-style': require('./rules/heading-style.js'),
|
||||
'link-title-style': require('./rules/link-title-style.js'),
|
||||
'list-item-bullet-indent': require('./rules/list-item-bullet-indent.js'),
|
||||
'list-item-content-indent': require('./rules/list-item-content-indent.js'),
|
||||
'list-item-indent': require('./rules/list-item-indent.js'),
|
||||
'list-item-spacing': require('./rules/list-item-spacing.js'),
|
||||
'maximum-heading-length': require('./rules/maximum-heading-length.js'),
|
||||
'maximum-line-length': require('./rules/maximum-line-length.js'),
|
||||
'no-auto-link-without-protocol': require('./rules/no-auto-link-without-protocol.js'),
|
||||
'no-blockquote-without-caret': require('./rules/no-blockquote-without-caret.js'),
|
||||
'no-consecutive-blank-lines': require('./rules/no-consecutive-blank-lines.js'),
|
||||
'no-duplicate-definitions': require('./rules/no-duplicate-definitions.js'),
|
||||
'no-duplicate-headings': require('./rules/no-duplicate-headings.js'),
|
||||
'no-emphasis-as-heading': require('./rules/no-emphasis-as-heading.js'),
|
||||
'no-file-name-articles': require('./rules/no-file-name-articles.js'),
|
||||
'no-file-name-consecutive-dashes': require('./rules/no-file-name-consecutive-dashes.js'),
|
||||
'no-file-name-irregular-characters': require('./rules/no-file-name-irregular-characters.js'),
|
||||
'no-file-name-mixed-case': require('./rules/no-file-name-mixed-case.js'),
|
||||
'no-file-name-outer-dashes': require('./rules/no-file-name-outer-dashes.js'),
|
||||
'no-heading-content-indent': require('./rules/no-heading-content-indent.js'),
|
||||
'no-heading-indent': require('./rules/no-heading-indent.js'),
|
||||
'no-heading-punctuation': require('./rules/no-heading-punctuation.js'),
|
||||
'no-html': require('./rules/no-html.js'),
|
||||
'no-inline-padding': require('./rules/no-inline-padding.js'),
|
||||
'no-literal-urls': require('./rules/no-literal-urls.js'),
|
||||
'no-missing-blank-lines': require('./rules/no-missing-blank-lines.js'),
|
||||
'no-multiple-toplevel-headings': require('./rules/no-multiple-toplevel-headings.js'),
|
||||
'no-shell-dollars': require('./rules/no-shell-dollars.js'),
|
||||
'no-shortcut-reference-image': require('./rules/no-shortcut-reference-image.js'),
|
||||
'no-shortcut-reference-link': require('./rules/no-shortcut-reference-link.js'),
|
||||
'no-table-indentation': require('./rules/no-table-indentation.js'),
|
||||
'no-tabs': require('./rules/no-tabs.js'),
|
||||
'no-undefined-references': require('./rules/no-undefined-references.js'),
|
||||
'no-unused-definitions': require('./rules/no-unused-definitions.js'),
|
||||
'ordered-list-marker-style': require('./rules/ordered-list-marker-style.js'),
|
||||
'ordered-list-marker-value': require('./rules/ordered-list-marker-value.js'),
|
||||
'rule-style': require('./rules/rule-style.js'),
|
||||
'strong-marker': require('./rules/strong-marker.js'),
|
||||
'table-cell-padding': require('./rules/table-cell-padding.js'),
|
||||
'table-pipe-alignment': require('./rules/table-pipe-alignment.js'),
|
||||
'table-pipes': require('./rules/table-pipes.js'),
|
||||
'unordered-list-marker-style': require('./rules/unordered-list-marker-style.js')
|
||||
};
|
@ -10,21 +10,43 @@
|
||||
*
|
||||
* The default value, `consistent`, detects the first used indentation
|
||||
* and will warn when other blockquotes use a different indentation.
|
||||
* @example
|
||||
* <!-- Valid, when set to `4`, invalid when set to `2` -->
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": 4}
|
||||
*
|
||||
* <!--This file is also valid by default-->
|
||||
*
|
||||
* > Hello
|
||||
* ...
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* > World
|
||||
*
|
||||
* <!-- Valid, when set to `2`, invalid when set to `4` -->
|
||||
* @example {"name": "valid.md", "setting": 2}
|
||||
*
|
||||
* <!--This file is also valid by default-->
|
||||
*
|
||||
* > Hello
|
||||
* ...
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* > World
|
||||
*
|
||||
* <!-- Always invalid -->
|
||||
* > Hello
|
||||
* ...
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* > Hello
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* > World
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* > World
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 5:3: Remove 1 space between blockquote and content
|
||||
* 9:3: Add 1 space between blockquote and content
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -12,36 +12,61 @@
|
||||
*
|
||||
* These values can also be passed in as an object, such as:
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "checked": "x",
|
||||
* "unchecked": " "
|
||||
* }
|
||||
* ```js
|
||||
* {checked: 'x', unchecked: ' '}
|
||||
* ```
|
||||
* @example
|
||||
* <!-- Note: the double guillemet (`»`) and middle-dots represent a tab -->
|
||||
*
|
||||
* <!-- Valid by default, `'consistent'`, or `{checked: 'x'}` -->
|
||||
* @example {"name": "valid.md", "setting": {"checked": "x"}}
|
||||
*
|
||||
* <!--This file is also valid by default-->
|
||||
*
|
||||
* - [x] List item
|
||||
* - [x] List item
|
||||
*
|
||||
* <!-- Valid by default, `'consistent'`, or `{checked: 'X'}` -->
|
||||
* @example {"name": "valid.md", "setting": {"checked": "X"}}
|
||||
*
|
||||
* <!--This file is also valid by default-->
|
||||
*
|
||||
* - [X] List item
|
||||
* - [X] List item
|
||||
*
|
||||
* <!-- Valid by default, `'consistent'`, or `{unchecked: ' '}` -->
|
||||
* @example {"name": "valid.md", "setting": {"unchecked": " "}}
|
||||
*
|
||||
* <!--This file is also valid by default-->
|
||||
*
|
||||
* - [ ] List item
|
||||
* - [ ] List item
|
||||
* - [ ]··
|
||||
* - [ ]
|
||||
*
|
||||
* <!-- Valid by default, `'consistent'`, or `{unchecked: '»'}` -->
|
||||
* - [»···] List item
|
||||
* - [»···] List item
|
||||
* @example {"name": "valid.md", "setting": {"unchecked": "\t"}}
|
||||
*
|
||||
* <!--Also valid by default (note: `»` represents `\t`)-->
|
||||
*
|
||||
* - [»] List item
|
||||
* - [»] List item
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!--Note: `»` represents `\t`-->
|
||||
*
|
||||
* <!-- Always invalid -->
|
||||
* - [x] List item
|
||||
* - [X] List item
|
||||
* - [ ] List item
|
||||
* - [»···] List item
|
||||
* - [»] List item
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 4:4-4:5: Checked checkboxes should use `x` as a marker
|
||||
* 6:4-6:5: Unchecked checkboxes should use ` ` as a marker
|
||||
*
|
||||
* @example {"setting": {"unchecked": "!"}, "name": "invalid.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid unchecked checkbox marker `!`: use either `'\t'`, or `' '`
|
||||
*
|
||||
* @example {"setting": {"checked": "!"}, "name": "invalid.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid checked checkbox marker `!`: use either `'x'`, or `'X'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,18 +5,26 @@
|
||||
* @module checkbox-content-indent
|
||||
* @fileoverview
|
||||
* Warn when list item checkboxes are followed by too much white-space.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* - [ ] List item
|
||||
* + [x] List item
|
||||
* * [X] List item
|
||||
* - [ ] List item
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* - [ ] List item
|
||||
* + [x] List item
|
||||
* * [X] List item
|
||||
* - [ ] List item
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 2:7-2:8: Checkboxes should be followed by a single character
|
||||
* 3:7-3:9: Checkboxes should be followed by a single character
|
||||
* 4:7-4:10: Checkboxes should be followed by a single character
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -12,29 +12,80 @@
|
||||
* The default value, `consistent`, detects the first used code-block
|
||||
* style, and will warn when a subsequent code-block uses a different
|
||||
* style.
|
||||
* @example
|
||||
* <!-- Valid, when set to `indented` or `consistent`, invalid when set to `fenced` -->
|
||||
* Hello
|
||||
*
|
||||
* ...
|
||||
* @example {"setting": "indented", "name": "valid.md"}
|
||||
*
|
||||
* World
|
||||
* <!-- This is also valid when `'consistent'` -->
|
||||
*
|
||||
* alpha();
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* bravo();
|
||||
*
|
||||
* @example {"setting": "indented", "name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!-- Valid, when set to `fenced` or `consistent`, invalid when set to `indented` -->
|
||||
* ```
|
||||
* Hello
|
||||
* ```
|
||||
* ...
|
||||
* ```bar
|
||||
* World
|
||||
* alpha();
|
||||
* ```
|
||||
*
|
||||
* <!-- Always invalid -->
|
||||
* Hello
|
||||
* ...
|
||||
* Paragraph.
|
||||
*
|
||||
* ```
|
||||
* World
|
||||
* ```
|
||||
* bravo();
|
||||
* ```
|
||||
*
|
||||
* @example {"setting": "indented", "name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-3:4: Code blocks should be indented
|
||||
* 7:1-9:4: Code blocks should be indented
|
||||
*
|
||||
* @example {"setting": "fenced", "name": "valid.md"}
|
||||
*
|
||||
* <!-- This is also valid when `'consistent'` -->
|
||||
*
|
||||
* ```
|
||||
* alpha();
|
||||
* ```
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* ```
|
||||
* bravo();
|
||||
* ```
|
||||
*
|
||||
* @example {"setting": "fenced", "name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* alpha();
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* bravo();
|
||||
*
|
||||
* @example {"setting": "fenced", "name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:13: Code blocks should be fenced
|
||||
* 5:1-5:13: Code blocks should be fenced
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!-- This is always invalid -->
|
||||
*
|
||||
* alpha();
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* ```
|
||||
* bravo();
|
||||
* ```
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 7:1-9:4: Code blocks should be indented
|
||||
*
|
||||
* @example {"setting": "invalid", "name": "invalid.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid code block style `invalid`: use either `'consistent'`, `'fenced'`, or `'indented'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,12 +5,18 @@
|
||||
* @module definition-case
|
||||
* @fileoverview
|
||||
* Warn when definition labels are not lower-case.
|
||||
* @example
|
||||
* <!-- Valid -->
|
||||
* [example] http://example.com "Example Domain"
|
||||
*
|
||||
* <!-- Invalid -->
|
||||
* ![Example] http://example.com/favicon.ico "Example image"
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* [example]: http://example.com "Example Domain"
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* [Example]: http://example.com "Example Domain"
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:47: Do not use upper-case characters in definition labels
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,12 +5,18 @@
|
||||
* @module definition-spacing
|
||||
* @fileoverview
|
||||
* Warn when consecutive white space is used in a definition.
|
||||
* @example
|
||||
* <!-- Valid -->
|
||||
* [example domain] http://example.com "Example Domain"
|
||||
*
|
||||
* <!-- Invalid -->
|
||||
* ![example image] http://example.com/favicon.ico "Example image"
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* [example domain]: http://example.com "Example Domain"
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* [example domain]: http://example.com "Example Domain"
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:57: Do not use consecutive white-space in definition labels
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -12,14 +12,45 @@
|
||||
* The default value, `consistent`, detects the first used emphasis
|
||||
* style, and will warn when a subsequent emphasis uses a different
|
||||
* style.
|
||||
* @example
|
||||
* <!-- Valid when set to `consistent` or `*` -->
|
||||
* *foo*
|
||||
* *bar*
|
||||
*
|
||||
* <!-- Valid when set to `consistent` or `_` -->
|
||||
* @example {"setting": "*", "name": "valid.md"}
|
||||
*
|
||||
* *foo*
|
||||
*
|
||||
* @example {"setting": "*", "name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* _foo_
|
||||
*
|
||||
* @example {"setting": "*", "name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:6: Emphasis should use `*` as a marker
|
||||
*
|
||||
* @example {"setting": "_", "name": "valid.md"}
|
||||
*
|
||||
* _foo_
|
||||
*
|
||||
* @example {"setting": "_", "name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* *foo*
|
||||
*
|
||||
* @example {"setting": "_", "name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:6: Emphasis should use `_` as a marker
|
||||
*
|
||||
* @example {"setting": "consistent", "name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!-- This is never valid -->
|
||||
*
|
||||
* *foo*
|
||||
* _bar_
|
||||
*
|
||||
* @example {"setting": "consistent", "name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 4:1-4:6: Emphasis should use `*` as a marker
|
||||
*
|
||||
* @example {"setting": "invalid", "name": "invalid.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid emphasis marker `invalid`: use either `'consistent'`, `'*'`, or `'_'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -15,29 +15,54 @@
|
||||
* In addition it can have the property `allowEmpty` (`boolean`)
|
||||
* which signifies whether or not to warn for fenced code-blocks without
|
||||
* languge flags.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
* ```hello
|
||||
* world();
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* ```alpha
|
||||
* bravo();
|
||||
* ```
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* Hello
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* ```
|
||||
* world();
|
||||
* alpha();
|
||||
* ```
|
||||
*
|
||||
* <!-- Valid when given `{allowEmpty: true}`: -->
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-3:4: Missing code-language flag
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": {"allowEmpty": true}}
|
||||
*
|
||||
* ```
|
||||
* world();
|
||||
* alpha();
|
||||
* ```
|
||||
*
|
||||
* <!-- Invalid when given `["world"]`: -->
|
||||
* ```hello
|
||||
* world();
|
||||
* @example {"name": "invalid.md", "setting": {"allowEmpty": false}, "label": "input"}
|
||||
*
|
||||
* ```
|
||||
* alpha();
|
||||
* ```
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": {"allowEmpty": false}, "label": "output"}
|
||||
*
|
||||
* 1:1-3:4: Missing code-language flag
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": ["alpha"]}
|
||||
*
|
||||
* ```alpha
|
||||
* bravo();
|
||||
* ```
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": ["charlie"], "label": "input"}
|
||||
*
|
||||
* ```alpha
|
||||
* bravo();
|
||||
* ```
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": ["charlie"], "label": "output"}
|
||||
*
|
||||
* 1:1-3:4: Invalid code-language flag
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -11,33 +11,50 @@
|
||||
* The default value, `consistent`, detects the first used fenced code
|
||||
* marker style, and will warn when a subsequent fenced code uses a
|
||||
* different style.
|
||||
* @example
|
||||
* <!-- Valid by default and `` '`' ``: -->
|
||||
* ```foo
|
||||
* bar();
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "`"}
|
||||
*
|
||||
* <!-- This is also valid by default. -->
|
||||
*
|
||||
* ```alpha
|
||||
* bravo();
|
||||
* ```
|
||||
*
|
||||
* ```
|
||||
* baz();
|
||||
* charlie();
|
||||
* ```
|
||||
*
|
||||
* <!-- Valid by default and `'~'`: -->
|
||||
* ~~~foo
|
||||
* bar();
|
||||
* @example {"name": "valid.md", "setting": "~"}
|
||||
*
|
||||
* <!-- This is also valid by default. -->
|
||||
*
|
||||
* ~~~alpha
|
||||
* bravo();
|
||||
* ~~~
|
||||
*
|
||||
* ~~~
|
||||
* baz();
|
||||
* charlie();
|
||||
* ~~~
|
||||
*
|
||||
* <!-- Always invalid: -->
|
||||
* ~~~foo
|
||||
* bar();
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!-- This is always invalid. -->
|
||||
*
|
||||
* ```alpha
|
||||
* bravo();
|
||||
* ```
|
||||
*
|
||||
* ~~~
|
||||
* charlie();
|
||||
* ~~~
|
||||
*
|
||||
* ```
|
||||
* baz();
|
||||
* ```
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 7:1-9:4: Fenced code should use ` as a marker
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": "!", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid fenced code marker `!`: use either `'consistent'`, `` '`' ``, or `'~'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -11,9 +11,16 @@
|
||||
* `AUTHORS` or `LICENSE`).
|
||||
*
|
||||
* Options: `string`, default: `'md'` — Expected file extension.
|
||||
* @example
|
||||
* Invalid (when `'md'`): readme.mkd, readme.markdown, etc.
|
||||
* Valid (when `'md'`): readme, readme.md
|
||||
*
|
||||
* @example {"name": "readme.md"}
|
||||
*
|
||||
* @example {"name": "readme"}
|
||||
*
|
||||
* @example {"name": "readme.mkd", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid extension: use `md`
|
||||
*
|
||||
* @example {"name": "readme.mkd", "setting": "mkd"}
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,18 +5,24 @@
|
||||
* @module final-definition
|
||||
* @fileoverview
|
||||
* Warn when definitions are not placed at the end of the file.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
* ...
|
||||
*
|
||||
* [example] http://example.com "Example Domain"
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* ...
|
||||
* Paragraph.
|
||||
*
|
||||
* [example] http://example.com "Example Domain"
|
||||
* [example]: http://example.com "Example Domain"
|
||||
*
|
||||
* A trailing paragraph.
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* [example]: http://example.com "Example Domain"
|
||||
*
|
||||
* Another paragraph.
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:1-3:47: Move definitions to the end of the file (after the node at line `5`)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -26,7 +26,7 @@ function finalNewline(ast, file) {
|
||||
var contents = file.toString();
|
||||
var last = contents.length - 1;
|
||||
|
||||
if (last > 0 && contents.charAt(last) !== '\n') {
|
||||
if (last > -1 && contents.charAt(last) !== '\n') {
|
||||
file.warn('Missing newline character at end of file');
|
||||
}
|
||||
}
|
||||
|
@ -7,16 +7,42 @@
|
||||
* Warn when the first heading has a level other than a specified value.
|
||||
*
|
||||
* Options: `number`, default: `1`.
|
||||
* @example
|
||||
* <!-- Valid, when set to `1` -->
|
||||
* # Foo
|
||||
*
|
||||
* ## Bar
|
||||
* @example {"name": "valid.md", "setting": 1}
|
||||
*
|
||||
* <!-- Invalid, when set to `1` -->
|
||||
* ## Foo
|
||||
* <!-- Also valid by default. -->
|
||||
*
|
||||
* # Bar
|
||||
* # Alpha
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": 1, "label": "input"}
|
||||
*
|
||||
* <!-- Also invalid by default. -->
|
||||
*
|
||||
* ## Bravo
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": 1, "label": "output"}
|
||||
*
|
||||
* 3:1-3:9: First heading level should be `1`
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": 2}
|
||||
*
|
||||
* ## Bravo
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": 2, "label": "input"}
|
||||
*
|
||||
* # Bravo
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": 2, "label": "output"}
|
||||
*
|
||||
* 1:1-1:8: First heading level should be `2`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,16 +5,24 @@
|
||||
* @module hard-break-spaces
|
||||
* @fileoverview
|
||||
* Warn when too many spaces are used to create a hard break.
|
||||
* @example
|
||||
* <!-- Note: the middle-dots represent spaces -->
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* <!--Note: `·` represents ` `-->
|
||||
*
|
||||
* Lorem ipsum··
|
||||
* dolor sit amet
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!--Note: `·` represents ` `-->
|
||||
*
|
||||
* Lorem ipsum···
|
||||
* dolor sit amet.
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:12-4:1: Use two spaces for hard line breaks
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,16 +5,22 @@
|
||||
* @module heading-increment
|
||||
* @fileoverview
|
||||
* Warn when headings increment with more than 1 level at a time.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
* # Foo
|
||||
*
|
||||
* ## Bar
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* # Foo
|
||||
* # Alpha
|
||||
*
|
||||
* ### Bar
|
||||
* ## Bravo
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* # Charlie
|
||||
*
|
||||
* ### Delta
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:1-3:10: Heading levels should increment by one level at a time
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -12,37 +12,54 @@
|
||||
* The default value, `consistent`, detects the first used heading
|
||||
* style, and will warn when a subsequent heading uses a different
|
||||
* style.
|
||||
* @example
|
||||
* <!-- Valid when `consistent` or `atx` -->
|
||||
* # Foo
|
||||
*
|
||||
* ## Bar
|
||||
* @example {"name": "valid.md", "setting": "atx"}
|
||||
*
|
||||
* ### Baz
|
||||
* <!--Also valid when `consistent`-->
|
||||
*
|
||||
* <!-- Valid when `consistent` or `atx-closed` -->
|
||||
* # Foo #
|
||||
* # Alpha
|
||||
*
|
||||
* ## Bar #
|
||||
* ## Bravo
|
||||
*
|
||||
* ### Baz ###
|
||||
* ### Charlie
|
||||
*
|
||||
* <!-- Valid when `consistent` or `setext` -->
|
||||
* Foo
|
||||
* ===
|
||||
* @example {"name": "valid.md", "setting": "atx-closed"}
|
||||
*
|
||||
* Bar
|
||||
* ---
|
||||
* <!--Also valid when `consistent`-->
|
||||
*
|
||||
* ### Baz
|
||||
* # Delta ##
|
||||
*
|
||||
* <!-- Invalid -->
|
||||
* Foo
|
||||
* ===
|
||||
* ## Echo ##
|
||||
*
|
||||
* ## Bar
|
||||
* ### Foxtrot ###
|
||||
*
|
||||
* ### Baz ###
|
||||
* @example {"name": "valid.md", "setting": "setext"}
|
||||
*
|
||||
* <!--Also valid when `consistent`-->
|
||||
*
|
||||
* Golf
|
||||
* ====
|
||||
*
|
||||
* Hotel
|
||||
* -----
|
||||
*
|
||||
* ### India
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!--Always invalid.-->
|
||||
*
|
||||
* Juliett
|
||||
* =======
|
||||
*
|
||||
* ## Kilo
|
||||
*
|
||||
* ### Lima ###
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 6:1-6:8: Headings should use setext
|
||||
* 8:1-8:13: Headings should use setext
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -1,70 +0,0 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module Rules
|
||||
* @fileoverview Map of rule id’s to rules.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* Expose. */
|
||||
module.exports = {
|
||||
'no-auto-link-without-protocol': require('./no-auto-link-without-protocol'),
|
||||
'no-literal-urls': require('./no-literal-urls'),
|
||||
'no-consecutive-blank-lines': require('./no-consecutive-blank-lines'),
|
||||
'no-missing-blank-lines': require('./no-missing-blank-lines'),
|
||||
'blockquote-indentation': require('./blockquote-indentation'),
|
||||
'no-blockquote-without-caret': require('./no-blockquote-without-caret'),
|
||||
'code-block-style': require('./code-block-style'),
|
||||
'checkbox-content-indent': require('./checkbox-content-indent'),
|
||||
'checkbox-character-style': require('./checkbox-character-style'),
|
||||
'definition-case': require('./definition-case'),
|
||||
'definition-spacing': require('./definition-spacing'),
|
||||
'no-emphasis-as-heading': require('./no-emphasis-as-heading'),
|
||||
'emphasis-marker': require('./emphasis-marker'),
|
||||
'fenced-code-flag': require('./fenced-code-flag'),
|
||||
'fenced-code-marker': require('./fenced-code-marker'),
|
||||
'file-extension': require('./file-extension'),
|
||||
'final-newline': require('./final-newline'),
|
||||
'no-file-name-articles': require('./no-file-name-articles'),
|
||||
'no-file-name-consecutive-dashes': require('./no-file-name-consecutive-dashes'),
|
||||
'no-file-name-irregular-characters': require('./no-file-name-irregular-characters'),
|
||||
'no-file-name-mixed-case': require('./no-file-name-mixed-case'),
|
||||
'no-file-name-outer-dashes': require('./no-file-name-outer-dashes'),
|
||||
'final-definition': require('./final-definition'),
|
||||
'hard-break-spaces': require('./hard-break-spaces'),
|
||||
'heading-increment': require('./heading-increment'),
|
||||
'no-heading-content-indent': require('./no-heading-content-indent'),
|
||||
'no-heading-indent': require('./no-heading-indent'),
|
||||
'first-heading-level': require('./first-heading-level'),
|
||||
'maximum-heading-length': require('./maximum-heading-length'),
|
||||
'no-heading-punctuation': require('./no-heading-punctuation'),
|
||||
'heading-style': require('./heading-style'),
|
||||
'no-multiple-toplevel-headings': require('./no-multiple-toplevel-headings'),
|
||||
'no-duplicate-headings': require('./no-duplicate-headings'),
|
||||
'no-duplicate-definitions': require('./no-duplicate-definitions'),
|
||||
'no-html': require('./no-html'),
|
||||
'no-inline-padding': require('./no-inline-padding'),
|
||||
'maximum-line-length': require('./maximum-line-length'),
|
||||
'link-title-style': require('./link-title-style'),
|
||||
'list-item-bullet-indent': require('./list-item-bullet-indent'),
|
||||
'list-item-content-indent': require('./list-item-content-indent'),
|
||||
'list-item-indent': require('./list-item-indent'),
|
||||
'list-item-spacing': require('./list-item-spacing'),
|
||||
'ordered-list-marker-style': require('./ordered-list-marker-style'),
|
||||
'ordered-list-marker-value': require('./ordered-list-marker-value'),
|
||||
'no-shortcut-reference-image': require('./no-shortcut-reference-image'),
|
||||
'no-shortcut-reference-link': require('./no-shortcut-reference-link'),
|
||||
'rule-style': require('./rule-style'),
|
||||
'no-shell-dollars': require('./no-shell-dollars'),
|
||||
'strong-marker': require('./strong-marker'),
|
||||
'no-table-indentation': require('./no-table-indentation'),
|
||||
'table-pipe-alignment': require('./table-pipe-alignment'),
|
||||
'table-cell-padding': require('./table-cell-padding'),
|
||||
'table-pipes': require('./table-pipes'),
|
||||
'no-tabs': require('./no-tabs'),
|
||||
'unordered-list-marker-style': require('./unordered-list-marker-style'),
|
||||
'no-undefined-references': require('./no-undefined-references.js'),
|
||||
'no-unused-definitions': require('./no-unused-definitions.js')
|
||||
};
|
@ -12,23 +12,54 @@
|
||||
* The default value, `consistent`, detects the first used quote
|
||||
* style, and will warn when a subsequent titles use a different
|
||||
* style.
|
||||
* @example
|
||||
* <!-- Valid when `consistent` or `"` -->
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "\""}
|
||||
*
|
||||
* <!--Also valid when `consistent`-->
|
||||
*
|
||||
* [Example](http://example.com "Example Domain")
|
||||
* [Example](http://example.com "Example Domain")
|
||||
*
|
||||
* <!-- Valid when `consistent` or `'` -->
|
||||
* @example {"name": "valid.md", "setting": "'"}
|
||||
*
|
||||
* <!--Also valid when `consistent`-->
|
||||
*
|
||||
* [Example](http://example.com 'Example Domain')
|
||||
* [Example](http://example.com 'Example Domain')
|
||||
*
|
||||
* <!-- Valid when `consistent` or `()` -->
|
||||
* [Example](http://example.com (Example Domain))
|
||||
* [Example](http://example.com (Example Domain))
|
||||
* @example {"name": "valid.md", "setting": "()"}
|
||||
*
|
||||
* <!--Also valid when `consistent`-->
|
||||
*
|
||||
* [Example](http://example.com (Example Domain) )
|
||||
* [Example](http://example.com (Example Domain) )
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!--Always invalid-->
|
||||
*
|
||||
* <!-- Always invalid -->
|
||||
* [Example](http://example.com "Example Domain")
|
||||
* [Example](http://example.com#without-title)
|
||||
* [Example](http://example.com 'Example Domain')
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 5:46: Titles should use `"` as a quote
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input", "setting": "()"}
|
||||
*
|
||||
* <!--Always invalid-->
|
||||
*
|
||||
* [Example](http://example.com (Example Domain))
|
||||
* [Example](http://example.com 'Example Domain')
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output", "setting": "()"}
|
||||
*
|
||||
* 4:46: Titles should use `()` as a quote
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": ".", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid link title style marker `.`: use either `'consistent'`, `'"'`, `'\''`, or `'()'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,14 +5,25 @@
|
||||
* @module list-item-bullet-indent
|
||||
* @fileoverview
|
||||
* Warn when list item bullets are indented.
|
||||
* @example
|
||||
* <!-- Valid -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* * List item
|
||||
* * List item
|
||||
*
|
||||
* <!-- Invalid -->
|
||||
* * List item
|
||||
* * List item
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* * List item
|
||||
* * List item
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:3: Incorrect indentation before bullet: remove 1 space
|
||||
* 4:3: Incorrect indentation before bullet: remove 1 space
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,16 +5,20 @@
|
||||
* @module list-item-content-indent
|
||||
* @fileoverview
|
||||
* Warn when the content of a list item has mixed indentation.
|
||||
* @example
|
||||
* <!-- Valid -->
|
||||
* * List item
|
||||
*
|
||||
* * Nested list item indented by 4 spaces
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* <!-- Invalid -->
|
||||
* * List item
|
||||
* 1. [x] Alpha
|
||||
* 1. Bravo
|
||||
*
|
||||
* * Nested list item indented by 3 spaces
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* 1. [x] Charlie
|
||||
* 1. Delta
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 2:5: Don’t use mixed indentation for children, remove 1 space
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -9,35 +9,60 @@
|
||||
*
|
||||
* Options: `string`, either `'tab-size'`, `'mixed'`, or `'space'`,
|
||||
* default: `'tab-size'`.
|
||||
* @example
|
||||
* <!-- Valid when `tab-size` -->
|
||||
* * List
|
||||
* item.
|
||||
*
|
||||
* 11. List
|
||||
* item.
|
||||
*
|
||||
* <!-- Valid when `mixed` -->
|
||||
* * List item.
|
||||
*
|
||||
* 11. List item
|
||||
* @example {"name": "valid.md", "setting": "tab-size"}
|
||||
*
|
||||
* * List
|
||||
* item.
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* 11. List
|
||||
* item.
|
||||
*
|
||||
* <!-- Valid when `space` -->
|
||||
* Paragraph.
|
||||
*
|
||||
* * List
|
||||
* item.
|
||||
*
|
||||
* * List
|
||||
* item.
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "mixed"}
|
||||
*
|
||||
* * List item.
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* 11. List item
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* * List
|
||||
* item.
|
||||
*
|
||||
* * List
|
||||
* item.
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "space"}
|
||||
*
|
||||
* * List item.
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* 11. List item
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* * List
|
||||
* item.
|
||||
*
|
||||
* 11. List
|
||||
* item.
|
||||
* * List
|
||||
* item.
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": "invalid", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid list-item indent style `invalid`: use either `'tab-size'`, `'space'`, or `'mixed'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -6,8 +6,17 @@
|
||||
* @fileoverview
|
||||
* Warn when list looseness is incorrect, such as being tight
|
||||
* when it should be loose, and vice versa.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* A tight list:
|
||||
*
|
||||
* - item 1
|
||||
* - item 2
|
||||
* - item 3
|
||||
*
|
||||
* A loose list:
|
||||
*
|
||||
* - Wrapped
|
||||
* item
|
||||
*
|
||||
@ -15,23 +24,29 @@
|
||||
*
|
||||
* - item 3
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* - item 1
|
||||
* - item 2
|
||||
* - item 3
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* A tight list:
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* - Wrapped
|
||||
* item
|
||||
* - item 2
|
||||
* - item 3
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* A loose list:
|
||||
*
|
||||
* - item 1
|
||||
*
|
||||
* - item 2
|
||||
*
|
||||
* - item 3
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 4:9-5:1: Missing new line after list item
|
||||
* 5:11-6:1: Missing new line after list item
|
||||
* 11:1-12:1: Extraneous new line after list item
|
||||
* 13:1-14:1: Extraneous new line after list item
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -9,13 +9,20 @@
|
||||
* Options: `number`, default: `60`.
|
||||
*
|
||||
* Ignores markdown syntax, only checks the plain text content.
|
||||
* @example
|
||||
* <!-- Valid, when set to `40` -->
|
||||
* # Alpha bravo charlie delta echo
|
||||
* # ![Alpha bravo charlie delta echo](http://example.com/nato.png)
|
||||
*
|
||||
* <!-- Invalid, when set to `40` -->
|
||||
* # Alpha bravo charlie delta echo foxtrot
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* # Alpha bravo charlie delta echo foxtrot golf hotel
|
||||
*
|
||||
* # ![Alpha bravo charlie delta echo foxtrot golf hotel](http://example.com/nato.png)
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": 40, "label": "input"}
|
||||
*
|
||||
* # Alpha bravo charlie delta echo foxtrot golf hotel
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": 40, "label": "output"}
|
||||
*
|
||||
* 1:1-1:52: Use headings shorter than `40`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -10,24 +10,50 @@
|
||||
*
|
||||
* Ignores nodes which cannot be wrapped, such as heasings, tables,
|
||||
* code, link, images, and definitions.
|
||||
* @example
|
||||
* <!-- Valid, when set to `40` -->
|
||||
* Alpha bravo charlie delta echo.
|
||||
*
|
||||
* Alpha bravo charlie delta echo [foxtrot](./foxtrot.html).
|
||||
* @example {"name": "valid.md", "setting": 80, "config": {"positionless": true}}
|
||||
*
|
||||
* # Alpha bravo charlie delta echo foxtrot golf hotel.
|
||||
* This line is simply not toooooooooooooooooooooooooooooooooooooooooooo
|
||||
* long.
|
||||
*
|
||||
* # Alpha bravo charlie delta echo foxtrot golf hotel.
|
||||
* This is also fine: <http://this-long-url-with-a-long-domain.co.uk/a-long-path?query=variables>
|
||||
*
|
||||
* | A | B | C | D | E | F | F | H |
|
||||
* | ----- | ----- | ------- | ----- | ---- | ------- | ---- | ----- |
|
||||
* | Alpha | bravo | charlie | delta | echo | foxtrot | golf | hotel |
|
||||
* <http://this-link-is-fine.com>
|
||||
*
|
||||
* <!-- Invalid, when set to `40` -->
|
||||
* Alpha bravo charlie delta echo foxtrot golf.
|
||||
* [foo](http://this-long-url-with-a-long-domain-is-valid.co.uk/a-long-path?query=variables)
|
||||
*
|
||||
* Alpha bravo charlie delta echo [foxtrot](./foxtrot.html) golf.
|
||||
* <http://this-long-url-with-a-long-domain-is-valid.co.uk/a-long-path?query=variables>
|
||||
*
|
||||
* ![foo](http://this-long-url-with-a-long-domain-is-valid.co.uk/a-long-path?query=variables)
|
||||
*
|
||||
* | An | exception | is | line | length | in | long | tables | because | those | can’t | just |
|
||||
* | -- | --------- | -- | ---- | ------ | -- | ---- | ------ | ------- | ----- | ----- | ---- |
|
||||
* | be | helped | | | | | | | | | | . |
|
||||
*
|
||||
* The following is also fine, because there is no white-space.
|
||||
*
|
||||
* <http://this-long-url-with-a-long-domain-is-invalid.co.uk/a-long-path?query=variables>.
|
||||
*
|
||||
* In addition, definitions are also fine:
|
||||
*
|
||||
* [foo]: <http://this-long-url-with-a-long-domain-is-invalid.co.uk/a-long-path?query=variables>
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": 80, "label": "input", "config": {"positionless": true}}
|
||||
*
|
||||
* This line is simply not tooooooooooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
* long.
|
||||
*
|
||||
* Just like thiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis one.
|
||||
*
|
||||
* And this one is also very wrong: because the link starts aaaaaaafter the column: <http://line.com>
|
||||
*
|
||||
* <http://this-long-url-with-a-long-domain-is-invalid.co.uk/a-long-path?query=variables> and such.
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": 80, "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 4:86: Line must be at most 80 characters
|
||||
* 6:99: Line must be at most 80 characters
|
||||
* 8:97: Line must be at most 80 characters
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,14 +5,20 @@
|
||||
* @module no-auto-link-without-protocol
|
||||
* @fileoverview
|
||||
* Warn for angle-bracketed links without protocol.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* <http://www.example.com>
|
||||
* <mailto:foo@bar.com>
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <www.example.com>
|
||||
* <foo@bar.com>
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 2:1-2:14: All automatic links must start with a protocol
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,16 +5,22 @@
|
||||
* @module no-blockquote-without-caret
|
||||
* @fileoverview
|
||||
* Warn when blank lines without carets are found in a blockquote.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* > Foo...
|
||||
* >
|
||||
* > ...Bar.
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* > Foo...
|
||||
*
|
||||
* > ...Bar.
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 2:1: Missing caret in blockquote
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -6,17 +6,32 @@
|
||||
* @fileoverview
|
||||
* Warn for too many consecutive blank lines. Knows about the extra line
|
||||
* needed between a list and indented code, and two lists.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* Foo...
|
||||
*
|
||||
* ...Bar.
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "valid-for-code.md"}
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* * List
|
||||
*
|
||||
*
|
||||
* bravo();
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* Foo...
|
||||
*
|
||||
*
|
||||
* ...Bar.
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 4:1: Remove 1 line before node
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,14 +5,20 @@
|
||||
* @module no-duplicate-definitions
|
||||
* @fileoverview
|
||||
* Warn when duplicate definitions are found.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* [foo]: bar
|
||||
* [baz]: qux
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* [foo]: bar
|
||||
* [foo]: qux
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 2:1-2:11: Do not use definitions with the same identifier (1:1)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,18 +5,25 @@
|
||||
* @module no-duplicate-headings
|
||||
* @fileoverview
|
||||
* Warn when duplicate headings are found.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* # Foo
|
||||
*
|
||||
* ## Bar
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* # Foo
|
||||
*
|
||||
* ## Foo
|
||||
*
|
||||
* ## [Foo](http://foo.com/bar)
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:1-3:7: Do not use headings with similar content (1:1)
|
||||
* 5:1-5:29: Do not use headings with similar content (3:1)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -6,16 +6,22 @@
|
||||
* @fileoverview
|
||||
* Warn when emphasis (including strong), instead of a heading, introduces
|
||||
* a paragraph.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* # Foo
|
||||
*
|
||||
* Bar.
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* *Foo*
|
||||
*
|
||||
* Bar.
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:6: Don’t use emphasis to introduce a section, use a heading
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,9 +5,20 @@
|
||||
* @module no-file-name-articles
|
||||
* @fileoverview
|
||||
* Warn when file name start with an article.
|
||||
* @example
|
||||
* Valid: article.md
|
||||
* Invalid: an-article.md, a-article.md, , the-article.md
|
||||
*
|
||||
* @example {"name": "title.md"}
|
||||
*
|
||||
* @example {"name": "a-title.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not start file names with `a`
|
||||
*
|
||||
* @example {"name": "the-title.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not start file names with `the`
|
||||
*
|
||||
* @example {"name": "an-article.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not start file names with `an`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,9 +5,12 @@
|
||||
* @module no-file-name-consecutive-dashes
|
||||
* @fileoverview
|
||||
* Warn when file names contain consecutive dashes.
|
||||
* @example
|
||||
* Invalid: docs/plug--ins.md
|
||||
* Valid: docs/plug-ins.md
|
||||
*
|
||||
* @example {"name": "plug-ins.md"}
|
||||
*
|
||||
* @example {"name": "plug--ins.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not use consecutive dashes in a file name
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -14,9 +14,22 @@
|
||||
*
|
||||
* Any match by the wrapped or given expressions triggers a
|
||||
* warning.
|
||||
* @example
|
||||
* Invalid: plug_ins.md, plug ins.md.
|
||||
* Valid: plug-ins.md, plugins.md.
|
||||
*
|
||||
* @example {"name": "plug-ins.md"}
|
||||
*
|
||||
* @example {"name": "plugins.md"}
|
||||
*
|
||||
* @example {"name": "plug_ins.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not use `_` in a file name
|
||||
*
|
||||
* @example {"name": "README.md", "label": "output", "setting": "\\.a-z0-9", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not use `R` in a file name
|
||||
*
|
||||
* @example {"name": "plug ins.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not use ` ` in a file name
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@ -36,7 +49,7 @@ module.exports = noFileNameIrregularCharacters;
|
||||
* characters which should not be allowed.
|
||||
*/
|
||||
function noFileNameIrregularCharacters(ast, file, preferred) {
|
||||
var expression = preferred || /[^\\.a-zA-Z0-9-]/;
|
||||
var expression = preferred || /[^\\\.a-zA-Z0-9-]/;
|
||||
var match;
|
||||
|
||||
if (typeof expression === 'string') {
|
||||
|
@ -6,9 +6,14 @@
|
||||
* @fileoverview
|
||||
* Warn when a file name uses mixed case: both upper- and lower case
|
||||
* characters.
|
||||
* @example
|
||||
* Invalid: Readme.md
|
||||
* Valid: README.md, readme.md
|
||||
*
|
||||
* @example {"name": "README.md"}
|
||||
*
|
||||
* @example {"name": "readme.md"}
|
||||
*
|
||||
* @example {"name": "Readme.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not mix casing in file names
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,9 +5,16 @@
|
||||
* @module no-file-name-outer-dashes
|
||||
* @fileoverview
|
||||
* Warn when file names contain initial or final dashes.
|
||||
* @example
|
||||
* Invalid: -readme.md, readme-.md
|
||||
* Valid: readme.md
|
||||
*
|
||||
* @example {"name": "readme.md"}
|
||||
*
|
||||
* @example {"name": "-readme.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not use initial or final dashes in a file name
|
||||
*
|
||||
* @example {"name": "readme-.md", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Do not use initial or final dashes in a file name
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,21 +5,47 @@
|
||||
* @module no-heading-content-indent
|
||||
* @fileoverview
|
||||
* Warn when a heading’s content is indented.
|
||||
* @example
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* <!-- Note: the middle-dots represent spaces -->
|
||||
* <!-- Invalid: -->
|
||||
*
|
||||
* #·Foo
|
||||
*
|
||||
* ## Bar·##
|
||||
*
|
||||
* ##·Baz
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!-- Note: the middle-dots represent spaces -->
|
||||
*
|
||||
* #··Foo
|
||||
*
|
||||
* ## Bar··##
|
||||
*
|
||||
* ##··Baz
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* #·Foo
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* ## Bar·##
|
||||
* 3:4: Remove 1 space before this heading’s content
|
||||
* 5:7: Remove 1 space after this heading’s content
|
||||
* 7:7: Remove 1 space before this heading’s content
|
||||
*
|
||||
* ##·Baz
|
||||
* @example {"name": "empty-heading.md"}
|
||||
*
|
||||
* #··
|
||||
*
|
||||
* @example {"name": "tight.md", "config":{"pedantic":true}, "label": "input"}
|
||||
*
|
||||
* In pedantic mode, headings without spacing can also be detected:
|
||||
*
|
||||
* ##No spacing left, too much right··##
|
||||
*
|
||||
* @example {"name": "tight.md", "label": "output"}
|
||||
*
|
||||
* 3:3: Add 1 space before this heading’s content
|
||||
* 3:34: Remove 1 space after this heading’s content
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@ -74,7 +100,7 @@ function noHeadingContentIndent(ast, file) {
|
||||
char = contents.charAt(index);
|
||||
}
|
||||
|
||||
/* CR/LF bug: wooorm/remark#195. */
|
||||
/* istanbul ignore if - CR/LF bug: wooorm/remark#195. */
|
||||
if (!char) {
|
||||
return;
|
||||
}
|
||||
|
@ -5,9 +5,25 @@
|
||||
* @module no-heading-indent
|
||||
* @fileoverview
|
||||
* Warn when a heading is indented.
|
||||
* @example
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* <!-- Note: the middle-dots represent spaces -->
|
||||
* <!-- Invalid: -->
|
||||
*
|
||||
* #·Hello world
|
||||
*
|
||||
* Foo
|
||||
* -----
|
||||
*
|
||||
* #·Hello world·#
|
||||
*
|
||||
* Bar
|
||||
* =====
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!-- Note: the middle-dots represent spaces -->
|
||||
*
|
||||
* ···# Hello world
|
||||
*
|
||||
* ·Foo
|
||||
@ -18,16 +34,12 @@
|
||||
* ···Bar
|
||||
* =====
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* # Hello world
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* Foo
|
||||
* -----
|
||||
*
|
||||
* # Hello world #
|
||||
*
|
||||
* Bar
|
||||
* =====
|
||||
* 3:4: Remove 3 spaces before this heading
|
||||
* 5:2: Remove 1 space before this heading
|
||||
* 8:2: Remove 1 space before this heading
|
||||
* 10:4: Remove 3 spaces before this heading
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -11,8 +11,17 @@
|
||||
*
|
||||
* Note that these are added to a regex, in a group (`'[' + char + ']'`),
|
||||
* be careful for escapes and dashes.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* # Hello
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": ",;:!?"}
|
||||
*
|
||||
* # Hello...
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* # Hello:
|
||||
*
|
||||
* # Hello?
|
||||
@ -23,8 +32,13 @@
|
||||
*
|
||||
* # Hello;
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* # Hello
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:9: Don’t add a trailing `:` to headings
|
||||
* 3:1-3:9: Don’t add a trailing `?` to headings
|
||||
* 5:1-5:9: Don’t add a trailing `!` to headings
|
||||
* 7:1-7:9: Don’t add a trailing `,` to headings
|
||||
* 9:1-9:9: Don’t add a trailing `;` to headings
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -8,12 +8,20 @@
|
||||
*
|
||||
* Ignores comments, because they are used by this tool, remark, and
|
||||
* because markdown doesn’t have native comments.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* # Hello
|
||||
*
|
||||
* <!--Comments are also OK-->
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <h1>Hello</h1>
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* # Hello
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:15: Do not use HTML in markdown
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -8,12 +8,20 @@
|
||||
* content.
|
||||
*
|
||||
* Warns for emphasis, strong, delete, image, and link.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
* * Hello *, [ world ](http://foo.bar/baz)
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* *Hello*, [world](http://foo.bar/baz)
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* Alpha, *bravo*, _charlie_, [delta](http://echo.fox/trot)
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* Alpha, * bravo *, _ charlie _, [ delta ](http://echo.fox/trot)
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:8-1:17: Don’t pad `emphasis` with inner spaces
|
||||
* 1:19-1:30: Don’t pad `emphasis` with inner spaces
|
||||
* 1:32-1:63: Don’t pad `link` with inner spaces
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,12 +5,21 @@
|
||||
* @module no-literal-urls
|
||||
* @fileoverview
|
||||
* Warn when URLs without angle-brackets are used.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* <http://foo.bar/baz>
|
||||
* <mailto:qux@quux.com>
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* http://foo.bar/baz
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* <http://foo.bar/baz>
|
||||
* mailto:qux@quux.com
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:19: Don’t use literal URLs without angle brackets
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@ -51,7 +60,7 @@ function noLiteralURLs(ast, file) {
|
||||
if (
|
||||
initial === head &&
|
||||
final === tail &&
|
||||
(value === node.url || value == MAILTO + node.url)
|
||||
(node.url === MAILTO + value || node.url === value)
|
||||
) {
|
||||
file.warn('Don’t use literal URLs without angle brackets', node);
|
||||
}
|
||||
|
@ -5,15 +5,21 @@
|
||||
* @module no-missing-blank-lines
|
||||
* @fileoverview
|
||||
* Warn for missing blank lines before a block node.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
* # Foo
|
||||
* ## Bar
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* # Foo
|
||||
*
|
||||
* ## Bar
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* # Foo
|
||||
* ## Bar
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 2:1-2:7: Missing blank line before block node
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -7,16 +7,22 @@
|
||||
* Warn when multiple top-level headings are used.
|
||||
*
|
||||
* Options: `number`, default: `1`.
|
||||
* @example
|
||||
* <!-- Invalid, when set to `1` -->
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": 1}
|
||||
*
|
||||
* # Foo
|
||||
*
|
||||
* ## Bar
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": 1, "label": "input"}
|
||||
*
|
||||
* # Foo
|
||||
*
|
||||
* # Bar
|
||||
*
|
||||
* <!-- Valid, when set to `1` -->
|
||||
* # Foo
|
||||
* @example {"name": "invalid.md", "setting": 1, "label": "output"}
|
||||
*
|
||||
* ## Bar
|
||||
* 3:1-3:6: Don’t use multiple top level headings (3:1)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -8,25 +8,30 @@
|
||||
*
|
||||
* Ignored indented code blocks and fenced code blocks without language
|
||||
* flag.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
* ```bash
|
||||
* $ echo a
|
||||
* $ echo a > file
|
||||
* ```
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* ```sh
|
||||
* echo a
|
||||
* echo a > file
|
||||
* ```
|
||||
*
|
||||
* <!-- Also valid: -->
|
||||
* ```zsh
|
||||
* $ echo a
|
||||
* a
|
||||
* $ echo a > file
|
||||
* ```
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* ```bash
|
||||
* $ echo a
|
||||
* $ echo a > file
|
||||
* ```
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-4:4: Do not use dollar signs before shell-commands
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,16 +5,22 @@
|
||||
* @module no-shortcut-reference-image
|
||||
* @fileoverview
|
||||
* Warn when shortcut reference images are used.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* ![foo][]
|
||||
*
|
||||
* [foo]: http://foo.bar/baz.png
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* ![foo]
|
||||
*
|
||||
* [foo]: http://foo.bar/baz.png
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* ![foo][]
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* [foo]: http://foo.bar/baz.png
|
||||
* 1:1-1:7: Use the trailing [] on reference images
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,16 +5,22 @@
|
||||
* @module no-shortcut-reference-link
|
||||
* @fileoverview
|
||||
* Warn when shortcut reference links are used.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* [foo][]
|
||||
*
|
||||
* [foo]: http://foo.bar/baz
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* [foo]
|
||||
*
|
||||
* [foo]: http://foo.bar/baz
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* [foo][]
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* [foo]: http://foo.bar/baz
|
||||
* 1:1-1:6: Use the trailing [] on reference links
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,16 +5,27 @@
|
||||
* @module no-table-indentation
|
||||
* @fileoverview
|
||||
* Warn when tables are indented.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
* | A | B |
|
||||
* | ----- | ----- |
|
||||
* | Alpha | Bravo |
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* | A | B |
|
||||
* | ----- | ----- |
|
||||
* | Alpha | Bravo |
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* | A | B |
|
||||
* | ----- | ----- |
|
||||
* | Alpha | Bravo |
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:1-3:21: Do not indent table rows
|
||||
* 5:1-5:21: Do not indent table rows
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,17 +5,42 @@
|
||||
* @module no-tabs
|
||||
* @fileoverview
|
||||
* Warn when hard-tabs instead of spaces
|
||||
* @example
|
||||
* <!-- Note: the double guillemet (`»`) and middle-dots represent a tab -->
|
||||
* <!-- Invalid: -->
|
||||
* Foo»Bar
|
||||
*
|
||||
* »···Foo
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* Foo Bar
|
||||
*
|
||||
* Foo
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input", "config": {"positionless": true}}
|
||||
*
|
||||
* <!-- Note: the guillemets represent tabs -->
|
||||
*
|
||||
* »Here's one before a code block.
|
||||
*
|
||||
* Here's a tab:», and here is another:».
|
||||
*
|
||||
* And this is in `inline»code`.
|
||||
*
|
||||
* >»This is in a block quote.
|
||||
*
|
||||
* *»And...
|
||||
*
|
||||
* »1.»in a list.
|
||||
*
|
||||
* And this is a tab as the last character.»
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:1: Use spaces instead of hard-tabs
|
||||
* 5:14: Use spaces instead of hard-tabs
|
||||
* 5:37: Use spaces instead of hard-tabs
|
||||
* 7:23: Use spaces instead of hard-tabs
|
||||
* 9:2: Use spaces instead of hard-tabs
|
||||
* 11:2: Use spaces instead of hard-tabs
|
||||
* 13:1: Use spaces instead of hard-tabs
|
||||
* 13:4: Use spaces instead of hard-tabs
|
||||
* 15:41: Use spaces instead of hard-tabs
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -2,17 +2,23 @@
|
||||
* @author Titus Wormer
|
||||
* @copyright 2016 Titus Wormer
|
||||
* @license MIT
|
||||
* @module no-unused-definitions
|
||||
* @module no-undefined-references
|
||||
* @fileoverview
|
||||
* Warn when references to undefined definitions are found.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* [foo][]
|
||||
*
|
||||
* [foo]: https://example.com
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* [bar][]
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:8: Found reference to undefined definition
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,14 +5,20 @@
|
||||
* @module no-unused-definitions
|
||||
* @fileoverview
|
||||
* Warn when unused definitions are found.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* [foo][]
|
||||
*
|
||||
* [foo]: https://example.com
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* [bar]: https://example.com
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1-1:27: Found unused definition
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -15,16 +15,37 @@
|
||||
* The default value, `consistent`, detects the first used list
|
||||
* style, and will warn when a subsequent list uses a different
|
||||
* style.
|
||||
* @example
|
||||
* <!-- Valid when set to `consistent` or `.` -->
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "."}
|
||||
*
|
||||
* <!-- This is also valid when `consistent`. -->
|
||||
*
|
||||
* 1. Foo
|
||||
*
|
||||
* 2. Bar
|
||||
*
|
||||
* <!-- Valid when set to `consistent` or `)` -->
|
||||
* @example {"name": "valid.md", "setting": ")", "config": {"commonmark": true}}
|
||||
*
|
||||
* <!-- This is also valid when `consistent`.
|
||||
* But it does require commonmark. -->
|
||||
*
|
||||
* 1) Foo
|
||||
*
|
||||
* 2) Bar
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input", "config": {"commonmark": true}}
|
||||
*
|
||||
* 1. Foo
|
||||
*
|
||||
* 2) Bar
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:1-3:8: Marker style should be `.`
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output", "setting": "!", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid ordered list-item marker style `!`: use either `'.'` or `')'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -14,33 +14,64 @@
|
||||
* relative to the starting point. When set to `'single'`, bullets should
|
||||
* be the same as the relative starting point. When set to `'one'`, bullets
|
||||
* should always be `1`.
|
||||
* @example
|
||||
* <!-- Valid when set to `one`: -->
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "one"}
|
||||
*
|
||||
* 1. Foo
|
||||
* 1. Bar
|
||||
* 1. Baz
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* 1. Alpha
|
||||
* 1. Bravo
|
||||
* 1. Charlie
|
||||
*
|
||||
* <!-- Valid when set to `single`: -->
|
||||
* @example {"name": "valid.md", "setting": "single"}
|
||||
*
|
||||
* 1. Foo
|
||||
* 1. Bar
|
||||
* 1. Baz
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* 3. Alpha
|
||||
* 3. Bravo
|
||||
* 3. Charlie
|
||||
*
|
||||
* <!-- Valid when set to `ordered`: -->
|
||||
* @example {"name": "valid.md", "setting": "ordered"}
|
||||
*
|
||||
* 1. Foo
|
||||
* 2. Bar
|
||||
* 3. Baz
|
||||
*
|
||||
* Paragraph.
|
||||
*
|
||||
* 3. Alpha
|
||||
* 4. Bravo
|
||||
* 5. Charlie
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": "one", "label": "input"}
|
||||
*
|
||||
* 1. Foo
|
||||
* 2. Bar
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": "one", "label": "output"}
|
||||
*
|
||||
* 2:1-2:8: Marker should be `1`, was `2`
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": "ordered", "label": "input"}
|
||||
*
|
||||
* 1. Foo
|
||||
* 1. Bar
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": "ordered", "label": "output"}
|
||||
*
|
||||
* 2:1-2:8: Marker should be `2`, was `1`
|
||||
*
|
||||
* @example {"name": "invalid.md", "setting": "invalid", "label": "output", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid ordered list-item marker value `invalid`: use either `'ordered'` or `'one'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -10,16 +10,38 @@
|
||||
*
|
||||
* Options: `string`, either a valid markdown rule, or `consistent`,
|
||||
* default: `'consistent'`.
|
||||
* @example
|
||||
* <!-- Valid when set to `consistent` or `* * *`: -->
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "* * *"}
|
||||
*
|
||||
* <!-- This is also valid when `consistent`. -->
|
||||
*
|
||||
* * * *
|
||||
*
|
||||
* * * *
|
||||
*
|
||||
* <!-- Valid when set to `consistent` or `_______`: -->
|
||||
* @example {"name": "valid.md", "setting": "_______"}
|
||||
*
|
||||
* <!-- This is also valid when `consistent`. -->
|
||||
*
|
||||
* _______
|
||||
*
|
||||
* _______
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!-- Always invalid. -->
|
||||
*
|
||||
* ***
|
||||
*
|
||||
* * * *
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 5:1-5:6: Rules should use `***`
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output", "setting": "!!!", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid preferred rule-style: provide a valid markdown rule, or `'consistent'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module blockquote-indentation
|
||||
* @module strong-marker
|
||||
* @fileoverview
|
||||
* Warn for violating strong markers.
|
||||
*
|
||||
@ -12,14 +12,34 @@
|
||||
* The default value, `consistent`, detects the first used strong
|
||||
* style, and will warn when a subsequent strong uses a different
|
||||
* style.
|
||||
* @example
|
||||
* <!-- Valid when set to `consistent` or `*` -->
|
||||
* **foo**
|
||||
* **bar**
|
||||
*
|
||||
* <!-- Valid when set to `consistent` or `_` -->
|
||||
* __foo__
|
||||
* __bar__
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* **foo** and **bar**.
|
||||
*
|
||||
* @example {"name": "also-valid.md"}
|
||||
*
|
||||
* __foo__ and __bar__.
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "*"}
|
||||
*
|
||||
* **foo**.
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "_"}
|
||||
*
|
||||
* __foo__.
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* **foo** and __bar__.
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:13-1:20: Strong should use `*` as a marker
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output", "setting": "!", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid strong marker `!`: use either `'consistent'`, `'*'`, or `'_'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -12,21 +12,40 @@
|
||||
* The default value, `consistent`, detects the first used cell padding
|
||||
* style, and will warn when a subsequent cells uses a different
|
||||
* style.
|
||||
* @example
|
||||
* <!-- Valid when set to `consistent` or `padded` -->
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "padded"}
|
||||
*
|
||||
* <!--Also valid when `consistent`-->
|
||||
*
|
||||
* | A | B |
|
||||
* | ----- | ----- |
|
||||
* | Alpha | Bravo |
|
||||
*
|
||||
* <!-- Valid when set to `consistent` or `compact` -->
|
||||
* @example {"name": "valid.md", "setting": "compact"}
|
||||
*
|
||||
* <!--Also valid when `consistent`-->
|
||||
*
|
||||
* |A |B |
|
||||
* |-----|-----|
|
||||
* |Alpha|Bravo|
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* <!--Always invalid-->
|
||||
*
|
||||
* | A | B |
|
||||
* | -----| -----|
|
||||
* | Alpha| Bravo|
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:5: Cell should be padded, isn’t
|
||||
* 3:9: Cell should be padded, isn’t
|
||||
* 3:16: Cell should be padded, isn’t
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output", "setting": "invalid", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid table-cell-padding style `invalid`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,16 +5,23 @@
|
||||
* @module table-pipe-alignment
|
||||
* @fileoverview
|
||||
* Warn when table pipes are not aligned.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* | A | B |
|
||||
* | ----- | ----- |
|
||||
* | Alpha | Bravo |
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* | A | B |
|
||||
* | -- | -- |
|
||||
* | Alpha | Bravo |
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 3:9-3:10: Misaligned table fence
|
||||
* 3:17-3:18: Misaligned table fence
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -5,16 +5,25 @@
|
||||
* @module table-pipes
|
||||
* @fileoverview
|
||||
* Warn when table rows are not fenced with pipes.
|
||||
* @example
|
||||
* <!-- Valid: -->
|
||||
*
|
||||
* @example {"name": "valid.md"}
|
||||
*
|
||||
* | A | B |
|
||||
* | ----- | ----- |
|
||||
* | Alpha | Bravo |
|
||||
*
|
||||
* <!-- Invalid: -->
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* A | B
|
||||
* ----- | -----
|
||||
* Alpha | Bravo
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 1:1: Missing initial pipe in table fence
|
||||
* 1:10: Missing final pipe in table fence
|
||||
* 3:1: Missing initial pipe in table fence
|
||||
* 3:14: Missing final pipe in table fence
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -13,22 +13,33 @@
|
||||
* The default value, `consistent`, detects the first used list
|
||||
* style, and will warn when a subsequent list uses a different
|
||||
* style.
|
||||
* @example
|
||||
* <!-- Valid when set to `consistent` or `-` -->
|
||||
* - Foo
|
||||
* - Bar
|
||||
*
|
||||
* <!-- Valid when set to `consistent` or `*` -->
|
||||
* * Foo
|
||||
* * Bar
|
||||
* @example {"name": "valid.md", "setting": "*"}
|
||||
*
|
||||
* <!-- Valid when set to `consistent` or `+` -->
|
||||
* + Foo
|
||||
* + Bar
|
||||
* * Foo
|
||||
*
|
||||
* <!-- Never valid: -->
|
||||
* + Foo
|
||||
* - Bar
|
||||
* @example {"name": "valid.md", "setting": "-"}
|
||||
*
|
||||
* - Foo
|
||||
*
|
||||
* @example {"name": "valid.md", "setting": "+"}
|
||||
*
|
||||
* + Foo
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "input"}
|
||||
*
|
||||
* * Foo
|
||||
* - Bar
|
||||
* + Baz
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output"}
|
||||
*
|
||||
* 2:1-2:6: Marker style should be `*`
|
||||
* 3:1-3:6: Marker style should be `*`
|
||||
*
|
||||
* @example {"name": "invalid.md", "label": "output", "setting": "!", "config": {"positionless": true}}
|
||||
*
|
||||
* 1:1: Invalid unordered list-item marker style `!`: use either `'-'`, `'*'`, or `'+'`
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
46
package.json
46
package.json
@ -9,21 +9,26 @@
|
||||
"validate",
|
||||
"remark"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wooorm/remark-lint.git"
|
||||
},
|
||||
"repository": "https://github.com/wooorm/remark-lint",
|
||||
"bugs": "https://github.com/wooorm/remark-lint/issues",
|
||||
"author": "Titus Wormer <tituswormer@gmail.com> (http://wooorm.com)",
|
||||
"contributors": [
|
||||
"Titus Wormer <tituswormer@gmail.com> (http://wooorm.com)"
|
||||
"Titus Wormer <tituswormer@gmail.com> (http://wooorm.com)",
|
||||
"Stephan Schneider <stephanschndr@gmail.com>",
|
||||
"Ben Balter <ben.balter@github.com>",
|
||||
"Danny Arnold <despair.blue@gmail.com>",
|
||||
"Tony Brix <tony@brix.ninja>",
|
||||
"Michael Mior <michael.mior@gmail.com>",
|
||||
"Patrick Gilday <pcgilday@gmail.com>",
|
||||
"Yoshua Wuyts <yoshuawuyts@gmail.com>",
|
||||
"YJ Yang <chcokr@gmail.com>",
|
||||
"Burak Yiğit Kaya <ben@byk.im>"
|
||||
],
|
||||
"dependencies": {
|
||||
"decamelize": "^1.0.0",
|
||||
"load-plugin": "^1.1.1",
|
||||
"mdast-util-heading-style": "^1.0.0",
|
||||
"mdast-util-to-string": "^1.0.0",
|
||||
"npm-prefix": "^1.1.1",
|
||||
"plur": "^2.0.0",
|
||||
"remark-message-control": "^2.0.0",
|
||||
"trough": "^1.0.0",
|
||||
@ -39,28 +44,35 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"browserify": "^13.0.0",
|
||||
"chalk": "^1.1.3",
|
||||
"dox": "^0.8.0",
|
||||
"esmangle": "^1.0.0",
|
||||
"istanbul": "^0.4.0",
|
||||
"mocha": "^2.0.0",
|
||||
"nyc": "^7.1.0",
|
||||
"remark": "^5.0.0",
|
||||
"remark-cli": "^1.0.0",
|
||||
"remark-comment-config": "^4.0.0",
|
||||
"remark-github": "^5.0.0",
|
||||
"remark-lint-no-url-trailing-slash": "^2.0.0",
|
||||
"remark-toc": "^3.0.0",
|
||||
"remark-validate-links": "^4.0.0",
|
||||
"mocha": "^2.0.0",
|
||||
"vfile": "^1.0.0"
|
||||
"strip-indent": "^1.0.0",
|
||||
"tape": "^4.6.0",
|
||||
"to-vfile": "^1.0.0",
|
||||
"trim": "0.0.1",
|
||||
"unist-builder": "^1.0.2",
|
||||
"unist-util-remove-position": "^1.1.0",
|
||||
"xo": "^0.16.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build-rules": "node script/build-rule-documentation.js",
|
||||
"build-index": "node script/build-index.js",
|
||||
"build-rules": "node script/build-docs.js",
|
||||
"build-md": "remark . --quiet --frail",
|
||||
"build-bundle": "browserify index.js --bare -s remarkLint > remark-lint.js",
|
||||
"build-mangle": "esmangle remark-lint.js > remark-lint.min.js",
|
||||
"build": "npm run build-rules && npm run build-md && npm run build-bundle && npm run build-mangle",
|
||||
"build": "npm run build-md && npm run build-index && npm run build-rules && npm run build-bundle && npm run build-mangle",
|
||||
"lint": "xo",
|
||||
"test-api": "mocha --check-leaks test/index.js",
|
||||
"test-coverage": "istanbul cover _mocha -- test/index.js",
|
||||
"test-api": "tape test/index.js",
|
||||
"test-coverage": "nyc --reporter lcov tape test/index.js",
|
||||
"test": "npm run build && npm run lint && npm run test-coverage"
|
||||
},
|
||||
"nyc": {
|
||||
@ -87,10 +99,12 @@
|
||||
"comment-config": null,
|
||||
"github": null,
|
||||
"toc": {
|
||||
"tight": true
|
||||
"tight": true,
|
||||
"maxDepth": 2
|
||||
},
|
||||
"./": {
|
||||
"no-missing-blank-lines": false
|
||||
"no-missing-blank-lines": false,
|
||||
"list-item-spacing": false
|
||||
},
|
||||
"validate-links": null
|
||||
},
|
||||
|
44
readme.md
44
readme.md
@ -4,8 +4,6 @@
|
||||
[![Coverage Status][coverage-badge]][coverage-status]
|
||||
[![Chat][chat-badge]][chat]
|
||||
|
||||
<!--lint disable list-item-spacing-->
|
||||
|
||||
**remark-lint** is a markdown code style linter. Another linter? Yes.
|
||||
Ensuring the markdown you (and contributors) write is of great quality will
|
||||
provide better rendering in all the different markdown parsers, and makes
|
||||
@ -20,7 +18,6 @@ processor powered by [plugins][remark-plugins] (such as this one).
|
||||
* [Installation](#installation)
|
||||
* [Command line](#command-line)
|
||||
* [Programmatic](#programmatic)
|
||||
* [remark.use(lint\[, options\])](#remarkuselint-options)
|
||||
* [Rules](#rules)
|
||||
* [Configuring remark-lint](#configuring-remark-lint)
|
||||
* [Using remark to fix your markdown](#using-remark-to-fix-your-markdown)
|
||||
@ -93,7 +90,6 @@ console.log(report(file));
|
||||
Now, running `node example.js` yields:
|
||||
|
||||
```txt
|
||||
<stdin>
|
||||
1:1 warning Missing newline character at end of file final-newline
|
||||
1:1-1:16 warning First heading level should be `1` first-heading-level
|
||||
1:1-1:16 warning Don’t add a trailing `!` to headings no-heading-punctuation
|
||||
@ -109,14 +105,18 @@ When processing a file, these warnings are available at `file.messages`, and
|
||||
look as follows:
|
||||
|
||||
```js
|
||||
{
|
||||
file: '~/example.md',
|
||||
{ [1:1-1:16: First heading level should be `1`]
|
||||
message: 'First heading level should be `1`',
|
||||
name: '1:1-1:16',
|
||||
file: '',
|
||||
reason: 'First heading level should be `1`',
|
||||
line: 1,
|
||||
column: 1,
|
||||
location: Position { start: [Object], end: [Object] },
|
||||
ruleId: 'first-heading-level',
|
||||
location: {
|
||||
start: { line: 1, column: 1, offset: 0 },
|
||||
end: { line: 1, column: 16, offset: 15 } },
|
||||
fatal: false,
|
||||
ruleId: 'first-heading-level',
|
||||
source: 'remark-lint' }
|
||||
```
|
||||
|
||||
@ -213,10 +213,20 @@ and I strongly suggest checking out how it can make your life easier :+1:
|
||||
Currently, **remark-lint** is integrated with Atom through
|
||||
[**linter-markdown**][linter-markdown].
|
||||
|
||||
If you want to run all of **remark** from **Atom**, use
|
||||
[**linter-remark**][linter-remark].
|
||||
|
||||
To run **remark**, optionally with **remark-lint** from **Gulp**, use
|
||||
[**gulp-remark**][gulp-remark].
|
||||
|
||||
I’m very interested in more integrations. Let me know if I can help.
|
||||
|
||||
## List of External Rules
|
||||
|
||||
External rules can be loaded through the [`external` setting][external].
|
||||
|
||||
Learn how to create and use external rules in [`doc/external.md`][doc-external].
|
||||
|
||||
<!--
|
||||
This list is ordered based on the name without prefix, so
|
||||
excluding `remark-lint-no-` or `remark-lint-`
|
||||
@ -249,19 +259,19 @@ excluding `remark-lint-no-` or `remark-lint-`
|
||||
|
||||
<!-- Definitions -->
|
||||
|
||||
[build-badge]: https://img.shields.io/travis/wooorm/remark-inline-links.svg
|
||||
[build-badge]: https://img.shields.io/travis/wooorm/remark-lint.svg
|
||||
|
||||
[build-status]: https://travis-ci.org/wooorm/remark-inline-links
|
||||
[build-status]: https://travis-ci.org/wooorm/remark-lint
|
||||
|
||||
[coverage-badge]: https://img.shields.io/codecov/c/github/wooorm/remark-inline-links.svg
|
||||
[coverage-badge]: https://img.shields.io/codecov/c/github/wooorm/remark-lint.svg
|
||||
|
||||
[coverage-status]: https://codecov.io/github/wooorm/remark-inline-links
|
||||
[coverage-status]: https://codecov.io/github/wooorm/remark-lint
|
||||
|
||||
[chat-badge]: https://img.shields.io/gitter/room/wooorm/remark.svg
|
||||
|
||||
[chat]: https://gitter.im/wooorm/remark
|
||||
|
||||
[releases]: https://github.com/wooorm/remark-inline-links/releases
|
||||
[releases]: https://github.com/wooorm/remark-lint/releases
|
||||
|
||||
[license]: LICENSE
|
||||
|
||||
@ -290,3 +300,11 @@ excluding `remark-lint-no-` or `remark-lint-`
|
||||
[vfile]: https://github.com/wooorm/vfile
|
||||
|
||||
[vfile-message]: https://github.com/wooorm/vfile#vfilemessage
|
||||
|
||||
[linter-remark]: https://github.com/wooorm/linter-remark
|
||||
|
||||
[gulp-remark]: https://github.com/denysdovhan/gulp-remark
|
||||
|
||||
[external]: doc/rules.md#external
|
||||
|
||||
[doc-external]: doc/external.md
|
||||
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"reset": {
|
||||
"description": "By default, all rules are turned on unless explicitly set to `false`.\nWhen `reset: true`, the opposite is true: all rules are turned off,\nunless when given a non-nully and non-false value.\n\nOptions: `boolean`, default: `false`.",
|
||||
"example": "<!-- Explicitly activate rules: -->\n```json\n{\n \"reset\": true,\n \"final-newline\": true\n}\n```\n"
|
||||
},
|
||||
"external": {
|
||||
"description": "External contains a list of extra rules to load.\nThese are, or refer to, an object mapping `ruleId`s to rules.\n\nNote that in node.js, a string can be given (a module\nname or a file), but in the browser an object must be passed in.\n\nWhen using a globally installed remark-lint, globally installed external\nrules are also loaded.\n\nThe prefix `remark-lint-` can be omitted.",
|
||||
"example": "<!-- Load more rules -->\n```json\n{\n \"external\": [\"foo\", \"bar\", \"baz\"]\n}\n```\n"
|
||||
}
|
||||
}
|
184
script/build-docs.js
Normal file
184
script/build-docs.js
Normal file
@ -0,0 +1,184 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2016 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:lint:script:build-docs
|
||||
* @fileoverview Creates `rules.md` files.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* Dependencies. */
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var inspect = require('util').inspect;
|
||||
var chalk = require('chalk');
|
||||
var remark = require('remark');
|
||||
var toc = require('remark-toc');
|
||||
var u = require('unist-builder');
|
||||
var rules = require('./util/rules');
|
||||
var rule = require('./util/rule');
|
||||
|
||||
/* Processor. */
|
||||
var markdown = remark().use(toc);
|
||||
|
||||
/* Generate. */
|
||||
[path.join(process.cwd())].forEach(function (filePath) {
|
||||
var children = [];
|
||||
var all = rules(filePath);
|
||||
var root;
|
||||
|
||||
rules(filePath).forEach(function (rulePath) {
|
||||
var info = rule(rulePath);
|
||||
var tests = info.tests;
|
||||
|
||||
children = children.concat(
|
||||
u('heading', {depth: 2}, [
|
||||
u('inlineCode', info.ruleId)
|
||||
]),
|
||||
markdown.parse(info.description).children
|
||||
);
|
||||
|
||||
Object.keys(tests).forEach(function (setting) {
|
||||
var fixtures = tests[setting];
|
||||
|
||||
Object.keys(fixtures).forEach(function (fileName) {
|
||||
var fixture = fixtures[fileName];
|
||||
var label = inspect(JSON.parse(setting));
|
||||
var sentence;
|
||||
|
||||
if (label === 'true') {
|
||||
label = u('text', 'turned on');
|
||||
} else {
|
||||
label = u('inlineCode', label);
|
||||
}
|
||||
|
||||
sentence = [
|
||||
u('text', 'When this rule is '),
|
||||
label,
|
||||
u('text', ', the following file\n'),
|
||||
u('inlineCode', fileName),
|
||||
u('text', ' is ')
|
||||
];
|
||||
|
||||
if (fixture.output.length) {
|
||||
sentence.push(
|
||||
u('strong', [u('text', 'not')]),
|
||||
u('text', ' ')
|
||||
);
|
||||
}
|
||||
|
||||
sentence.push(u('text', 'ok:'));
|
||||
|
||||
if (fixture.input == null) {
|
||||
children.push(
|
||||
u('paragraph', [
|
||||
u('text', 'When '),
|
||||
label,
|
||||
u('text', ' is passed in, the following error is given:')
|
||||
])
|
||||
);
|
||||
} else {
|
||||
children.push(
|
||||
u('paragraph', sentence),
|
||||
u('code', {lang: 'markdown'}, fixture.input)
|
||||
);
|
||||
}
|
||||
|
||||
if (fixture.output.length) {
|
||||
children.push(
|
||||
u('code', {lang: 'text'}, fixture.output.join('\n'))
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
root = u('root', [].concat(
|
||||
markdown.parse([
|
||||
'<!-- This file is generated -->',
|
||||
'',
|
||||
'# List of Rules',
|
||||
'',
|
||||
'This document describes all (' + all.length + ')',
|
||||
'available rules, what they check for, examples of',
|
||||
'what they warn for, and how to fix their warnings.',
|
||||
'',
|
||||
'Note: both camel-cased and dash-cases versions of rule id’s',
|
||||
'are supported in configuration objects:',
|
||||
'',
|
||||
'```json',
|
||||
'{',
|
||||
' "final-newline": false',
|
||||
'}',
|
||||
'```',
|
||||
'',
|
||||
'...is treated the same as:',
|
||||
'',
|
||||
'```json',
|
||||
'{',
|
||||
' "finalNewline": false',
|
||||
'}',
|
||||
'```',
|
||||
'',
|
||||
'## Table of Contents',
|
||||
'',
|
||||
'## `reset`',
|
||||
'',
|
||||
'By default, all rules are turned on unless explicitly',
|
||||
'set to `false`. When `reset: true`, the opposite is',
|
||||
'`true`: all rules are turned off, unless when given a',
|
||||
'non-nully and non-false value.',
|
||||
'',
|
||||
'Options: `boolean`, default: `false`.',
|
||||
'',
|
||||
'Explicitly activate rules:',
|
||||
'',
|
||||
'```json',
|
||||
'{',
|
||||
' "reset": true,',
|
||||
' "final-newline": true',
|
||||
'}',
|
||||
'```',
|
||||
'',
|
||||
'## `external`',
|
||||
'',
|
||||
'External contains a list of extra rules to load. These are,',
|
||||
'or refer to, an object mapping `ruleId`s to rules.',
|
||||
'',
|
||||
'Note that in Node.js, a `string` can be given (a module name',
|
||||
'or a file path), but in the browser an object must be passed',
|
||||
'in.',
|
||||
'',
|
||||
'When using a globally installed remark-lint, globally installed',
|
||||
'external rules are also loaded.',
|
||||
'',
|
||||
'The prefix `remark-lint-` can be omitted.',
|
||||
'',
|
||||
'```js',
|
||||
'{',
|
||||
' external: [\'no-empty-sections\', \'./a-local-file.js\']',
|
||||
'}',
|
||||
'```',
|
||||
'',
|
||||
'Read more about external rules in',
|
||||
'[`doc/external.md`](./external.md).',
|
||||
'',
|
||||
''
|
||||
].join('\n')).children,
|
||||
children
|
||||
));
|
||||
|
||||
markdown.run(root);
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(filePath, 'doc', 'rules.md'),
|
||||
markdown.stringify(root)
|
||||
);
|
||||
|
||||
console.log(
|
||||
chalk.green('✓') +
|
||||
' wrote docs for ' + all.length + ' rules in ' +
|
||||
path.basename(filePath)
|
||||
);
|
||||
});
|
52
script/build-index.js
Normal file
52
script/build-index.js
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2016 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:lint:script:build-indices
|
||||
* @fileoverview Creates `index.js` files for rules.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* Dependencies. */
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var chalk = require('chalk');
|
||||
var rules = require('./util/rules');
|
||||
|
||||
/* Generate. */
|
||||
[path.join(process.cwd())].forEach(function (filePath) {
|
||||
var base = path.resolve(filePath, 'lib', 'rules.js');
|
||||
var doc = [];
|
||||
|
||||
rules(filePath).forEach(function (rulePath) {
|
||||
var name = path.basename(rulePath);
|
||||
var relative = './' + path.relative(path.dirname(base), rulePath);
|
||||
|
||||
name = name.slice(0, name.indexOf('.'));
|
||||
|
||||
doc.push(
|
||||
' \'' + name + '\': require(\'' + relative + '\')'
|
||||
);
|
||||
});
|
||||
|
||||
doc = [].concat(
|
||||
[
|
||||
'/* This file is generated. */',
|
||||
'\'use strict\';',
|
||||
'module.exports = {'
|
||||
],
|
||||
doc.join(',\n'),
|
||||
[
|
||||
'};',
|
||||
''
|
||||
]
|
||||
).join('\n');
|
||||
|
||||
fs.writeFileSync(path.join(base), doc);
|
||||
|
||||
console.log(
|
||||
chalk.green('✓') +
|
||||
' wrote `index.js` in ' + path.basename(filePath)
|
||||
);
|
||||
});
|
@ -1,181 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:lint:script:build-rule-documentation
|
||||
* @fileoverview Creates documentation for all exposed
|
||||
* rules.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* Dependencies. */
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var dox = require('dox');
|
||||
var remark = require('remark');
|
||||
var toc = require('remark-toc');
|
||||
var rules = require('../lib/rules');
|
||||
var additional = require('./additional.json');
|
||||
|
||||
/* Methods. */
|
||||
var exists = fs.existsSync;
|
||||
|
||||
var children = [];
|
||||
|
||||
/* Add main heading. */
|
||||
children.push({
|
||||
type: 'heading',
|
||||
depth: 1,
|
||||
children: [{
|
||||
type: 'text',
|
||||
value: 'List of Rules'
|
||||
}]
|
||||
});
|
||||
|
||||
/* Add main description. */
|
||||
children.push(
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [{
|
||||
type: 'text',
|
||||
value: 'This document describes all available rules, what they\n' +
|
||||
'check for, examples of what they warn for, and how to\n' +
|
||||
'fix their warnings.'
|
||||
}]
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'See the readme for a '
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
url: 'https://github.com/wooorm/remark-lint#list-of-external-rules',
|
||||
children: [{
|
||||
type: 'text',
|
||||
value: 'list of external rules'
|
||||
}]
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: '.'
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
/* Add the rules heading. */
|
||||
children.push({
|
||||
type: 'heading',
|
||||
depth: 2,
|
||||
children: [{
|
||||
type: 'text',
|
||||
value: 'Rules'
|
||||
}]
|
||||
});
|
||||
|
||||
/* Add a section on how to turn of rules. */
|
||||
children.push({
|
||||
type: 'paragraph',
|
||||
children: [{
|
||||
type: 'text',
|
||||
value: 'Remember that rules can always be turned off by\n' +
|
||||
'passing false. In addition, when reset is given, values can\n' +
|
||||
'be null or undefined in order to be ignored.'
|
||||
}]
|
||||
});
|
||||
|
||||
/* Add the table-of-contents heading. */
|
||||
children.push({
|
||||
type: 'heading',
|
||||
depth: 3,
|
||||
children: [{
|
||||
type: 'text',
|
||||
value: 'Table of Contents'
|
||||
}]
|
||||
});
|
||||
|
||||
/* Add rules. */
|
||||
Object.keys(additional).sort()
|
||||
.concat(Object.keys(rules).sort())
|
||||
.forEach(function (ruleId) {
|
||||
var description;
|
||||
var filePath;
|
||||
var example;
|
||||
var code;
|
||||
var tags;
|
||||
|
||||
filePath = path.join('lib', 'rules', ruleId + '.js');
|
||||
|
||||
if (exists(filePath)) {
|
||||
code = fs.readFileSync(filePath, 'utf-8');
|
||||
tags = dox.parseComments(code)[0].tags;
|
||||
description = find(tags, 'fileoverview');
|
||||
example = find(tags, 'example');
|
||||
|
||||
if (!description) {
|
||||
throw new Error(ruleId + ' is missing a `@fileoverview`');
|
||||
}
|
||||
|
||||
description = description.string;
|
||||
example = example && example.string;
|
||||
} else {
|
||||
description = additional[ruleId].description;
|
||||
example = additional[ruleId].example;
|
||||
}
|
||||
|
||||
children.push({
|
||||
type: 'heading',
|
||||
depth: 3,
|
||||
children: [{
|
||||
type: 'text',
|
||||
value: ruleId
|
||||
}]
|
||||
});
|
||||
|
||||
if (example) {
|
||||
children.push({
|
||||
type: 'code',
|
||||
lang: 'md',
|
||||
value: example
|
||||
});
|
||||
}
|
||||
|
||||
children = children.concat(remark().parse(description).children);
|
||||
});
|
||||
|
||||
/* Node. */
|
||||
var node = {type: 'root', children: children};
|
||||
|
||||
/* Add toc. */
|
||||
remark().use(toc).run(node);
|
||||
|
||||
/* Write. */
|
||||
fs.writeFileSync('doc/rules.md', remark().stringify(node));
|
||||
|
||||
/**
|
||||
* Find the first tag in `tags` with a type set to `key`.
|
||||
*
|
||||
* @param {Array.<Object>} tags - List of tags.
|
||||
* @param {string} key - Type of tag.
|
||||
* @return {Object?} - Tag, when found.
|
||||
*/
|
||||
function find(tags, key) {
|
||||
var value = null;
|
||||
|
||||
tags.some(function (tag) {
|
||||
if (tag && tag.type === key) {
|
||||
value = tag;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
159
script/util/rule.js
Executable file
159
script/util/rule.js
Executable file
@ -0,0 +1,159 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2016 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:lint:script:rule
|
||||
* @fileoverview Get information for a rule.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* Dependencies. */
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var dox = require('dox');
|
||||
var strip = require('strip-indent');
|
||||
var trim = require('trim');
|
||||
|
||||
/* Expose. */
|
||||
module.exports = ruleSync;
|
||||
|
||||
/**
|
||||
* Get information for a rule at `filePath`.
|
||||
*
|
||||
* @param {string} filePath - Path to rule.
|
||||
*/
|
||||
function ruleSync(filePath) {
|
||||
var ruleId = path.basename(filePath);
|
||||
var result = {};
|
||||
var tests = {};
|
||||
var description;
|
||||
var code;
|
||||
var tags;
|
||||
var name;
|
||||
|
||||
ruleId = ruleId.slice(0, ruleId.indexOf('.'));
|
||||
|
||||
code = fs.readFileSync(filePath, 'utf-8');
|
||||
tags = dox.parseComments(code)[0].tags;
|
||||
description = find(tags, 'fileoverview');
|
||||
name = find(tags, 'module');
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (name !== ruleId) {
|
||||
throw new Error(
|
||||
ruleId + ' has an invalid `@module`: ' + name
|
||||
);
|
||||
}
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (!description) {
|
||||
throw new Error(ruleId + ' is missing a `@fileoverview`');
|
||||
}
|
||||
|
||||
description = strip(description);
|
||||
|
||||
result.ruleId = ruleId;
|
||||
result.description = trim(description);
|
||||
result.tests = tests;
|
||||
result.filePath = filePath;
|
||||
|
||||
findAll(tags, 'example').map(strip).forEach(function (example) {
|
||||
var lines = example.split('\n');
|
||||
var value = strip(lines.slice(1).join('\n'));
|
||||
var info;
|
||||
var setting;
|
||||
var context;
|
||||
var name;
|
||||
|
||||
try {
|
||||
info = JSON.parse(lines[0]);
|
||||
} catch (err) {
|
||||
/* istanbul ignore next */
|
||||
throw new Error(
|
||||
'Could not parse example in ' + ruleId + ':\n' + err.stack
|
||||
);
|
||||
}
|
||||
|
||||
setting = JSON.stringify(info.setting || true);
|
||||
context = tests[setting];
|
||||
name = info.name;
|
||||
|
||||
if (!context) {
|
||||
context = tests[setting] = [];
|
||||
}
|
||||
|
||||
if (!info.label) {
|
||||
context[name] = {
|
||||
config: info.config || {},
|
||||
setting: setting,
|
||||
input: value,
|
||||
output: []
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (info.label !== 'input' && info.label !== 'output') {
|
||||
throw new Error(
|
||||
'Expected `input` or `ouput` for `label` in ' +
|
||||
ruleId + ', not `' + info.label + '`'
|
||||
);
|
||||
}
|
||||
|
||||
if (!context[name]) {
|
||||
context[name] = {config: info.config || {}};
|
||||
}
|
||||
|
||||
context[name].setting = setting;
|
||||
|
||||
if (info.label === 'output') {
|
||||
value = value.split('\n');
|
||||
}
|
||||
|
||||
context[name][info.label] = value;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first tag in `tags` with a type set to `key`.
|
||||
*
|
||||
* @param {Array.<Object>} tags - List of tags.
|
||||
* @param {string} key - Type of tag.
|
||||
* @return {Object?} - Tag, when found.
|
||||
*/
|
||||
function find(tags, key) {
|
||||
var value = null;
|
||||
|
||||
tags.some(function (tag) {
|
||||
if (tag && tag.type === key) {
|
||||
value = tag;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return value && value.string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first tag in `tags` with a type set to `key`.
|
||||
*
|
||||
* @param {Array.<Object>} tags - List of tags.
|
||||
* @param {string} key - Type of tag.
|
||||
* @return {Object?} - Tag, when found.
|
||||
*/
|
||||
function findAll(tags, key) {
|
||||
return tags
|
||||
.filter(function (tag) {
|
||||
return tag && tag.type === key;
|
||||
})
|
||||
.map(function (tag) {
|
||||
return tag.string;
|
||||
});
|
||||
}
|
33
script/util/rules.js
Normal file
33
script/util/rules.js
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2016 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:lint:script:util:rules
|
||||
* @fileoverview Get a list of rules.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* Dependencies. */
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
/* Expose. */
|
||||
module.exports = rulesSync;
|
||||
|
||||
/**
|
||||
* Get a list of rules in a package.
|
||||
*
|
||||
* @param {string} filePath - Package to look into.
|
||||
*/
|
||||
function rulesSync(filePath) {
|
||||
var basePath = path.join(filePath, 'lib', 'rules');
|
||||
|
||||
return fs.readdirSync(basePath)
|
||||
.filter(function (basename) {
|
||||
return path.extname(basename) === '.js';
|
||||
})
|
||||
.map(function (basename) {
|
||||
return path.join(basePath, basename);
|
||||
});
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:lint:test:clean
|
||||
* @fileoverview remark plug-in used to remove positional
|
||||
* information from remark’s syntax tree.
|
||||
* @todo Externalise into its own repository.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* Dependencies. */
|
||||
var visit = require('unist-util-visit');
|
||||
|
||||
/**
|
||||
* Delete the `position` key for each node.
|
||||
*
|
||||
* @param {Node} ast - Root node.
|
||||
*/
|
||||
function transformer(ast) {
|
||||
visit(ast, function (node) {
|
||||
node.position = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `transformer`.
|
||||
*
|
||||
* @return {Function} - See `transformer`.
|
||||
*/
|
||||
function attacher() {
|
||||
return transformer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose.
|
||||
*/
|
||||
|
||||
module.exports = attacher;
|
19
test/external/index.js
vendored
19
test/external/index.js
vendored
@ -1,19 +0,0 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:lint:test:external
|
||||
* @fileoverview Map of example external rules.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-env commonjs */
|
||||
|
||||
/*
|
||||
* Expose.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
'no-lorem': require('./no-lorem')
|
||||
};
|
50
test/external/no-lorem.js
vendored
50
test/external/no-lorem.js
vendored
@ -1,50 +0,0 @@
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer
|
||||
* @license MIT
|
||||
* @module remark:lint:test:no-lorem
|
||||
* @fileoverview
|
||||
* Warn when `lorem` is used in a document.
|
||||
* @example
|
||||
* <!-- Invalid: -->
|
||||
* lorem
|
||||
*
|
||||
* <!-- Valid: -->
|
||||
* ipsum
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-env commonjs */
|
||||
|
||||
/*
|
||||
* Dependencies.
|
||||
*/
|
||||
|
||||
var vfileLocation = require('vfile-location');
|
||||
|
||||
/**
|
||||
* Warn when `lorem` is used in a document.
|
||||
*
|
||||
* @param {Node} ast - Root node.
|
||||
* @param {File} file - Virtual file.
|
||||
* @param {*} preferred - Ignored.
|
||||
* @param {Function} done - Callback.
|
||||
*/
|
||||
function noLorem(ast, file, preferred, done) {
|
||||
var content = file.toString();
|
||||
var expression = /\blorem\b/gi;
|
||||
var location = vfileLocation(file);
|
||||
|
||||
while (expression.exec(content)) {
|
||||
file.warn('Do not use lorem', location.toPosition(expression.lastIndex));
|
||||
}
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose.
|
||||
*/
|
||||
|
||||
module.exports = noLorem;
|
13
test/fixtures/blockquote-indentation-2.md
vendored
13
test/fixtures/blockquote-indentation-2.md
vendored
@ -1,13 +0,0 @@
|
||||
> Foo
|
||||
|
||||
<!-- -->
|
||||
|
||||
> Bar
|
||||
|
||||
<!-- -->
|
||||
|
||||
> Baz
|
||||
|
||||
<!-- -->
|
||||
|
||||
>
|
13
test/fixtures/blockquote-indentation-4.md
vendored
13
test/fixtures/blockquote-indentation-4.md
vendored
@ -1,13 +0,0 @@
|
||||
> Foo
|
||||
|
||||
<!-- -->
|
||||
|
||||
> Bar
|
||||
|
||||
<!-- -->
|
||||
|
||||
> Baz
|
||||
|
||||
<!-- -->
|
||||
|
||||
>
|
6
test/fixtures/carriage-returns.md
vendored
6
test/fixtures/carriage-returns.md
vendored
@ -1,6 +0,0 @@
|
||||
---
|
||||
title: "Example #
"
|
||||
---
|
||||
# Establishing an example #
|
||||
|
||||
Description.
|
@ -1,7 +0,0 @@
|
||||
* [x] Foo;
|
||||
|
||||
- [x] Bar;
|
||||
|
||||
+ [x] Baz;
|
||||
|
||||
* [x]
|
@ -1,7 +0,0 @@
|
||||
* [ ] Foo;
|
||||
|
||||
- [ ] Bar;
|
||||
|
||||
+ [ ] Baz;
|
||||
|
||||
* [ ]
|
@ -1,7 +0,0 @@
|
||||
* [ ] Foo;
|
||||
|
||||
- [ ] Bar;
|
||||
|
||||
+ [ ] Baz;
|
||||
|
||||
* [ ]
|
@ -1,7 +0,0 @@
|
||||
* [X] Foo;
|
||||
|
||||
- [X] Bar;
|
||||
|
||||
+ [X] Baz;
|
||||
|
||||
* [X]
|
11
test/fixtures/checkbox-content-indent-invalid.md
vendored
11
test/fixtures/checkbox-content-indent-invalid.md
vendored
@ -1,11 +0,0 @@
|
||||
* [x] This starts with two spaces;
|
||||
|
||||
- [ ] This with three;
|
||||
|
||||
- [ ] This with a space and a tab;
|
||||
|
||||
+ [X] Below is trailing white space;
|
||||
|
||||
* [x]
|
||||
|
||||
Foo.
|
15
test/fixtures/checkbox-content-indent-valid.md
vendored
15
test/fixtures/checkbox-content-indent-valid.md
vendored
@ -1,15 +0,0 @@
|
||||
- [x] One;
|
||||
|
||||
+ [X] Two;
|
||||
|
||||
* [ ] Three;
|
||||
|
||||
- [ ] Four;
|
||||
|
||||
- [x] Five (code);
|
||||
|
||||
+ [X] Below is a single white space;
|
||||
|
||||
* [x]
|
||||
|
||||
Foo.
|
11
test/fixtures/code-style-fenced.md
vendored
11
test/fixtures/code-style-fenced.md
vendored
@ -1,11 +0,0 @@
|
||||
Some fenced code block:
|
||||
|
||||
```
|
||||
foo
|
||||
```
|
||||
|
||||
And one with language flag:
|
||||
|
||||
```barscript
|
||||
bar
|
||||
```
|
7
test/fixtures/code-style-indented.md
vendored
7
test/fixtures/code-style-indented.md
vendored
@ -1,7 +0,0 @@
|
||||
Some indented code block:
|
||||
|
||||
foo
|
||||
|
||||
And another:
|
||||
|
||||
bar
|
13
test/fixtures/comments-disable-multiple.md
vendored
13
test/fixtures/comments-disable-multiple.md
vendored
@ -1,13 +0,0 @@
|
||||
# Hello
|
||||
|
||||
<!--lint disable no-duplicate-headings maximum-line-length-->
|
||||
|
||||
## Hello
|
||||
|
||||
Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello.
|
||||
|
||||
<!--lint enable no-duplicate-headings-->
|
||||
|
||||
### Hello
|
||||
|
||||
Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello.
|
7
test/fixtures/comments-disable.md
vendored
7
test/fixtures/comments-disable.md
vendored
@ -1,7 +0,0 @@
|
||||
<!--lint disable maximum-line-length-->
|
||||
|
||||
alpha bravo charlie delta echo foxtrot golf hotel india julliet kilo lima mike november.
|
||||
|
||||
<!--lint enable maximum-line-length-->
|
||||
|
||||
alpha bravo charlie delta echo foxtrot golf hotel india julliet kilo lima mike november.
|
7
test/fixtures/comments-duplicates.md
vendored
7
test/fixtures/comments-duplicates.md
vendored
@ -1,7 +0,0 @@
|
||||
<!--lint enable maximum-line-length-->
|
||||
|
||||
alpha bravo charlie delta echo foxtrot golf hotel india julliet kilo lima mike november.
|
||||
|
||||
<!--lint enable maximum-line-length-->
|
||||
|
||||
alpha bravo charlie delta echo foxtrot golf hotel india julliet kilo lima mike november.
|
7
test/fixtures/comments-enable.md
vendored
7
test/fixtures/comments-enable.md
vendored
@ -1,7 +0,0 @@
|
||||
<!--lint enable maximum-line-length-->
|
||||
|
||||
alpha bravo charlie delta echo foxtrot golf hotel india julliet kilo lima mike november.
|
||||
|
||||
<!--lint disable maximum-line-length-->
|
||||
|
||||
alpha bravo charlie delta echo foxtrot golf hotel india julliet kilo lima mike november.
|
1
test/fixtures/comments-inline.md
vendored
1
test/fixtures/comments-inline.md
vendored
@ -1 +0,0 @@
|
||||
Foo <!--lint enable no-html--> <span>This is HTML</span>.
|
5
test/fixtures/comments-invalid-keyword.md
vendored
5
test/fixtures/comments-invalid-keyword.md
vendored
@ -1,5 +0,0 @@
|
||||
Intro.
|
||||
|
||||
<!--lint foo bar-->
|
||||
|
||||
Outro.
|
5
test/fixtures/comments-invalid-rule-id.md
vendored
5
test/fixtures/comments-invalid-rule-id.md
vendored
@ -1,5 +0,0 @@
|
||||
Intro.
|
||||
|
||||
<!--lint enable bar-->
|
||||
|
||||
Outro.
|
1
test/fixtures/comments-none.md
vendored
1
test/fixtures/comments-none.md
vendored
@ -1 +0,0 @@
|
||||
Things should not fail without warnings, nor comments. Alpha bravo charlie delta echo foxtrot.
|
3
test/fixtures/definition-case-invalid.md
vendored
3
test/fixtures/definition-case-invalid.md
vendored
@ -1,3 +0,0 @@
|
||||
This document has definitions with improper spacing and casing.
|
||||
|
||||
[Invalid]: http://example.com/favicon.ico "Example Domain"
|
3
test/fixtures/definition-case-valid.md
vendored
3
test/fixtures/definition-case-valid.md
vendored
@ -1,3 +0,0 @@
|
||||
This document has definitions with proper spacing and casing.
|
||||
|
||||
[valid]: http://example.com/favicon.ico "Example Domain"
|
3
test/fixtures/definition-spacing-invalid.md
vendored
3
test/fixtures/definition-spacing-invalid.md
vendored
@ -1,3 +0,0 @@
|
||||
This document has definitions with improper spacing and casing.
|
||||
|
||||
[another invalid]: http://example.org/favicon.ico "Example Domain"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user