Skip to content

Commit

Permalink
Update for micromark in remark
Browse files Browse the repository at this point in the history
* Update to a micromark parser
* The markdown parser is now CommonMark compliant
* Several rules work on GFM features (literal autolinks, tables,
  strikethrough, tasklist).
  Make sure to install `remark-gfm` if you’re using GFM
* A couple of positions in messages moved a tad bit to make more sense

Most plugins are fine, but some received majors.

The following plugins are made for the new parser and do not work on
the old.
While you’re still on remark 12, use their previous version.
Use the new versions for remark 13+.

* `remark-lint-checkbox-character-style`
* `remark-lint-checkbox-content-indent`
* `remark-lint-list-item-bullet-indent`
* `remark-lint-list-item-spacing`
* `remark-lint-no-blockquote-without-marker`
* `remark-lint-no-heading-indent`
* `remark-lint-no-paragraph-content-indent`
* `remark-lint-no-table-indentation`
* `remark-lint-table-cell-padding`
* `remark-lint-table-pipes`

These plugins generally work on old and new remark, but might miss some
messages in the old one now:

* `remark-lint-no-consecutive-blank-lines` (extra blank lines can no
  longer break out of lists)
* `remark-lint-no-heading-content-indent` (pedantic mode no longer
  supported)
* `remark-lint-no-inline-padding` (emphasis, strong, strikethrough
  can’t be padded anymore)
* `remark-lint-no-undefined-references` (undefined references are no
  longer parsed, so we have to do magic to find them)
  • Loading branch information
wooorm committed Oct 12, 2020
1 parent d60518b commit 7791db9
Show file tree
Hide file tree
Showing 75 changed files with 906 additions and 565 deletions.
3 changes: 1 addition & 2 deletions .remarkrc.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
exports.settings = {bullet: '*', tablePipeAlign: false}

exports.plugins = [
require('./packages/remark-preset-lint-recommended'),
require('./packages/remark-preset-lint-consistent'),
[require('remark-toc'), {tight: true, maxDepth: 2, heading: 'contents'}],
require('remark-comment-config'),
[require('remark-gfm'), {tablePipeAlign: false}],
require('remark-github'),
require('remark-validate-links'),
require('./script/plugin/list-of-presets'),
Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@
"nyc": "^15.0.0",
"parse-author": "^2.0.0",
"prettier": "^2.0.0",
"remark": "^12.0.0",
"remark-cli": "^8.0.0",
"remark-comment-config": "^5.0.0",
"remark-github": "^9.0.0",
"remark": "^13.0.0-alpha.1",
"remark-cli": "^9.0.0-alpha.1",
"remark-comment-config": "^6.0.0",
"remark-gfm": "^1.0.0",
"remark-github": "^10.0.0",
"remark-toc": "^7.0.0",
"remark-validate-links": "^10.0.0",
"strip-indent": "^3.0.0",
Expand Down Expand Up @@ -92,6 +93,7 @@
"unicorn/prefer-optional-catch-binding": "off",
"unicorn/string-content": "off",
"guard-for-in": "off",
"max-depth": "off",
"no-eq-null": "off",
"eqeqeq": [
"error",
Expand Down
13 changes: 2 additions & 11 deletions packages/remark-lint-blockquote-indentation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
*
* @example {"name": "not-ok.md", "label": "output"}
*
* 5:3: Remove 1 space between block quote and content
* 5:5: Remove 1 space between block quote and content
* 9:3: Add 1 space between block quote and content
*/

Expand All @@ -52,7 +52,6 @@ var plural = require('pluralize')
var visit = require('unist-util-visit')
var position = require('unist-util-position')
var generated = require('unist-util-generated')
var toString = require('mdast-util-to-string')

module.exports = rule(
'remark-lint:blockquote-indentation',
Expand Down Expand Up @@ -95,13 +94,5 @@ function blockquoteIndentation(tree, file, option) {
}

function check(node) {
var head = node.children[0]
var indentation = position.start(head).column - position.start(node).column
var padding = toString(head).match(/^ +/)

if (padding) {
indentation += padding[0].length
}

return indentation
return position.start(node.children[0]).column - position.start(node).column
}
1 change: 0 additions & 1 deletion packages/remark-lint-blockquote-indentation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"index.js"
],
"dependencies": {
"mdast-util-to-string": "^1.0.2",
"pluralize": "^8.0.0",
"unified-lint-rule": "^1.0.0",
"unist-util-generated": "^1.1.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/remark-lint-blockquote-indentation/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Paragraph.
###### Out

```text
5:3: Remove 1 space between block quote and content
5:5: Remove 1 space between block quote and content
9:3: Add 1 space between block quote and content
```

Expand Down
58 changes: 30 additions & 28 deletions packages/remark-lint-checkbox-character-style/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,53 +26,52 @@
* See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown)
* on how to automatically fix warnings for this rule.
*
* @example {"name": "ok.md", "setting": {"checked": "x"}}
* @example {"name": "ok.md", "setting": {"checked": "x"}, "gfm": true}
*
* - [x] List item
* - [x] List item
*
* @example {"name": "ok.md", "setting": {"checked": "X"}}
* @example {"name": "ok.md", "setting": {"checked": "X"}, "gfm": true}
*
* - [X] List item
* - [X] List item
*
* @example {"name": "ok.md", "setting": {"unchecked": " "}}
* @example {"name": "ok.md", "setting": {"unchecked": " "}, "gfm": true}
*
* - [ ] List item
* - [ ] List item
* - [ ]··
* - [ ]
*
* @example {"name": "ok.md", "setting": {"unchecked": "\t"}}
* @example {"name": "ok.md", "setting": {"unchecked": "\t"}, "gfm": true}
*
* - [»] List item
* - [»] List item
*
* @example {"name": "not-ok.md", "label": "input"}
* @example {"name": "not-ok.md", "label": "input", "gfm": true}
*
* - [x] List item
* - [X] List item
* - [ ] List item
* - [»] List item
*
* @example {"name": "not-ok.md", "label": "output"}
* @example {"name": "not-ok.md", "label": "output", "gfm": true}
*
* 2:4-2:5: Checked checkboxes should use `x` as a marker
* 4:4-4:5: Unchecked checkboxes should use ` ` as a marker
* 2:5: Checked checkboxes should use `x` as a marker
* 4:5: Unchecked checkboxes should use ` ` as a marker
*
* @example {"setting": {"unchecked": "💩"}, "name": "not-ok.md", "label": "output", "config": {"positionless": true}}
* @example {"setting": {"unchecked": "💩"}, "name": "not-ok.md", "label": "output", "positionless": true, "gfm": true}
*
* 1:1: Incorrect unchecked checkbox marker `💩`: use either `'\t'`, or `' '`
*
* @example {"setting": {"checked": "💩"}, "name": "not-ok.md", "label": "output", "config": {"positionless": true}}
* @example {"setting": {"checked": "💩"}, "name": "not-ok.md", "label": "output", "positionless": true, "gfm": true}
*
* 1:1: Incorrect checked checkbox marker `💩`: use either `'x'`, or `'X'`
*/

'use strict'

var rule = require('unified-lint-rule')
var vfileLocation = require('vfile-location')
var visit = require('unist-util-visit')
var position = require('unist-util-position')
var generated = require('unist-util-generated')
Expand All @@ -91,7 +90,6 @@ var types = {true: 'checked', false: 'unchecked'}

function checkboxCharacterStyle(tree, file, option) {
var contents = String(file)
var location = vfileLocation(file)
var preferred = typeof option === 'object' ? option : {}

if (preferred.unchecked && unchecked[preferred.unchecked] !== true) {
Expand All @@ -114,11 +112,9 @@ function checkboxCharacterStyle(tree, file, option) {

function visitor(node) {
var type
var initial
var final
var point
var value
var style
var character
var reason

// Exit early for items without checkbox.
Expand All @@ -127,33 +123,39 @@ function checkboxCharacterStyle(tree, file, option) {
}

type = types[node.checked]
initial = start(node).offset
final = (node.children.length === 0 ? end(node) : start(node.children[0]))
.offset

// For a checkbox to be parsed, it must be followed by a whitespace.
value = contents.slice(initial, final).replace(/\s+$/, '').slice(0, -1)
/* istanbul ignore next - a list item cannot be checked and empty, according
* to GFM, but theoretically it makes sense to get the end if that were
* possible. */
point = node.children.length === 0 ? end(node) : start(node.children[0])
// Move back to before `] `.
point.offset -= 2
point.column -= 2

// Assume we start with a checkbox, because well, `checked` is set.
value = /\[([\t Xx])]/.exec(
contents.slice(point.offset - 2, point.offset + 1)
)

/* istanbul ignore if - failsafe to make sure we don‘t crash if there
* actually isn’t a checkbox. */
if (!value) return

// The checkbox character is behind a square bracket.
character = value.charAt(value.length - 1)
style = preferred[type]

if (style) {
if (character !== style) {
if (value[1] !== style) {
reason =
type.charAt(0).toUpperCase() +
type.slice(1) +
' checkboxes should use `' +
style +
'` as a marker'

file.message(reason, {
start: location.toPosition(initial + value.length - 1),
end: location.toPosition(initial + value.length)
})
file.message(reason, point)
}
} else {
preferred[type] = character
preferred[type] = value[1]
}
}
}
3 changes: 1 addition & 2 deletions packages/remark-lint-checkbox-character-style/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
"unified-lint-rule": "^1.0.0",
"unist-util-generated": "^1.1.0",
"unist-util-position": "^3.0.0",
"unist-util-visit": "^2.0.0",
"vfile-location": "^3.0.0"
"unist-util-visit": "^2.0.0"
},
"xo": false
}
16 changes: 14 additions & 2 deletions packages/remark-lint-checkbox-character-style/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ When configured with `{ checked: 'x' }`.

###### In

Note: this example uses [GFM][].

```markdown
- [x] List item
- [x] List item
Expand All @@ -63,6 +65,8 @@ When configured with `{ checked: 'X' }`.

###### In

Note: this example uses [GFM][].

```markdown
- [X] List item
- [X] List item
Expand All @@ -78,6 +82,8 @@ When configured with `{ unchecked: ' ' }`.

###### In

Note: this example uses [GFM][].

Note: `·` represents a space.

```markdown
Expand All @@ -97,6 +103,8 @@ When configured with `{ unchecked: '\t' }`.

###### In

Note: this example uses [GFM][].

Note: `»` represents a tab.

```markdown
Expand All @@ -112,6 +120,8 @@ No messages.

###### In

Note: this example uses [GFM][].

Note: `»` represents a tab.

```markdown
Expand All @@ -124,8 +134,8 @@ Note: `»` represents a tab.
###### Out

```text
2:4-2:5: Checked checkboxes should use `x` as a marker
4:4-4:5: Unchecked checkboxes should use ` ` as a marker
2:5: Checked checkboxes should use `x` as a marker
4:5: Unchecked checkboxes should use ` ` as a marker
```

##### `not-ok.md`
Expand Down Expand Up @@ -246,3 +256,5 @@ abide by its terms.
[license]: https://github.com/remarkjs/remark-lint/blob/main/license

[author]: https://wooorm.com

[gfm]: https://github.com/remarkjs/remark-gfm
38 changes: 23 additions & 15 deletions packages/remark-lint-checkbox-content-indent/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
* @fileoverview
* Warn when list item checkboxes are followed by too much whitespace.
*
* @example {"name": "ok.md"}
* @example {"name": "ok.md", "gfm": true}
*
* - [ ] List item
* + [x] List Item
* * [X] List item
* - [ ] List item
*
* @example {"name": "not-ok.md", "label": "input"}
* @example {"name": "not-ok.md", "label": "input", "gfm": true}
*
* - [ ] List item
* + [x] List item
* * [X] List item
* - [ ] List item
*
* @example {"name": "not-ok.md", "label": "output"}
* @example {"name": "not-ok.md", "label": "output", "gfm": true}
*
* 2:7-2:8: Checkboxes should be followed by a single character
* 3:7-3:9: Checkboxes should be followed by a single character
Expand Down Expand Up @@ -55,28 +55,36 @@ function checkboxContentIndent(tree, file) {
var initial
var final
var value
var point

// Exit early for items without checkbox.
if (typeof node.checked !== 'boolean' || generated(node)) {
return
}

initial = start(node).offset
/* istanbul ignore next - hard to test, couldn’t find a case. */
final = (node.children.length === 0 ? end(node) : start(node.children[0]))
.offset
/* istanbul ignore next - a list item cannot be checked and empty, according
* to GFM, but theoretically it makes sense to get the end if that were
* possible. */
point = node.children.length === 0 ? end(node) : start(node.children[0])

while (/[^\S\n]/.test(contents.charAt(final))) {
final++
}
// Assume we start with a checkbox, because well, `checked` is set.
value = /\[([\t xX])]/.exec(
contents.slice(point.offset - 4, point.offset + 1)
)

/* istanbul ignore if - failsafe to make sure we don‘t crash if there
* actually isn’t a checkbox. */
if (!value) return

// Move past checkbox.
initial = point.offset
final = initial

// For a checkbox to be parsed, it must be followed by a whitespace.
value = contents.slice(initial, final)
value = value.slice(value.indexOf(']') + 1)
while (/[\t ]/.test(contents.charAt(final))) final++

if (value.length !== 1) {
if (final - initial > 0) {
file.message(reason, {
start: location.toPosition(final - value.length + 1),
start: location.toPosition(initial),
end: location.toPosition(final)
})
}
Expand Down
6 changes: 6 additions & 0 deletions packages/remark-lint-checkbox-content-indent/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ This rule is not included in any default preset

###### In

Note: this example uses [GFM][].

```markdown
- [ ] List item
+ [x] List Item
Expand All @@ -37,6 +39,8 @@ No messages.

###### In

Note: this example uses [GFM][].

```markdown
- [ ] List item
+ [x] List item
Expand Down Expand Up @@ -150,3 +154,5 @@ abide by its terms.
[license]: https://github.com/remarkjs/remark-lint/blob/main/license

[author]: https://wooorm.com

[gfm]: https://github.com/remarkjs/remark-gfm
Loading

0 comments on commit 7791db9

Please sign in to comment.