eslint-plugin-markdown
Advanced tools
Comparing version 1.0.0-beta.8 to 1.0.0-rc.0
@@ -0,1 +1,14 @@ | ||
v1.0.0-rc.0 - October 27, 2018 | ||
* 8fe9a0e New: Enable autofix with --fix (fixes #58) (#97) (Bohdan Khodakivskyi) | ||
* a5d0cce Fix: Ignore anything after space in code fence's language (fixes #98) (#99) (Francisco Ryan Tolmasky I) | ||
* 6fd340d Upgrade: eslint-release@1.0.0 (#100) (Teddy Katz) | ||
* dff8e9c Fix: Emit correct endLine numbers (#88) (Paul Murray) | ||
* 83f00d0 Docs: Suggest disabling strict in .md files (fixes #94) (#95) (Brandon Mills) | ||
* 3b4ff95 Build: Test against Node v10 (#96) (Brandon Mills) | ||
* 6777977 Breaking: required node version 6+ (#89) (薛定谔的猫) | ||
* 5582fce Docs: Updating CLA link (#93) (Pablo Nevares) | ||
* 24070e6 Build: Upgrade to eslint-release@0.11.1 (#92) (Brandon Mills) | ||
* 6cfd1f0 Docs: Add unicode-bom to list of unsatisfiable rules (#91) (Brandon Mills) | ||
v1.0.0-beta.8 - April 8, 2018 | ||
@@ -2,0 +15,0 @@ |
@@ -17,2 +17,3 @@ /** | ||
]; | ||
var SUPPORTS_AUTOFIX = true; | ||
@@ -70,3 +71,135 @@ var markdown = unified().use(remarkParse); | ||
var leadingWhitespaceRegex = /^\s*/; | ||
/** | ||
* When applying fixes, the postprocess step needs to know how to map fix ranges | ||
* from their location in the linted JS to the original offset in the Markdown. | ||
* Configuration comments and indentation trimming both complicate this process. | ||
* | ||
* Configuration comments appear in the linted JS but not in the Markdown code | ||
* block. Fixes to configuration comments would cause undefined behavior and | ||
* should be ignored during postprocessing. Fixes to actual code after | ||
* configuration comments need to be mapped back to the code block after | ||
* removing any offset due to configuration comments. | ||
* | ||
* Fenced code blocks can be indented by up to three spaces at the opening | ||
* fence. Inside of a list, for example, this indent can be in addition to the | ||
* indent already required for list item children. Leading whitespace inside | ||
* indented code blocks is trimmed up to the level of the opening fence and does | ||
* not appear in the linted code. Further, lines can have less leading | ||
* whitespace than the opening fence, so not all lines are guaranteed to have | ||
* the same column offset as the opening fence. | ||
* | ||
* The source code of a non-configuration-comment line in the linted JS is a | ||
* suffix of the corresponding line in the Markdown code block. There are no | ||
* differences within the line, so the mapping need only provide the offset | ||
* delta at the beginning of each line. | ||
* | ||
* @param {string} text The text of the file. | ||
* @param {ASTNode} node A Markdown code block AST node. | ||
* @param {comments} comments List of configuration comment strings that will be | ||
* inserted at the beginning of the code block. | ||
* @returns {object[]} A list of offset-based adjustments, where lookups are | ||
* done based on the `js` key, which represents the range in the linted JS, | ||
* and the `md` key is the offset delta that, when added to the JS range, | ||
* returns the corresponding location in the original Markdown source. | ||
*/ | ||
function getBlockRangeMap(text, node, comments) { | ||
var baseIndent, | ||
code, | ||
commentLength, | ||
i, | ||
jsOffset, | ||
leadingWhitespaceLength, | ||
line, | ||
lines, | ||
mdOffset, | ||
rangeMap, | ||
startOffset, | ||
trimLength; | ||
/* | ||
* The parser sets the fenced code block's start offset to wherever content | ||
* should normally begin (typically the first column of the line, but more | ||
* inside a list item, for example). The code block's opening fance may be | ||
* further indented by up to three characters. If the code block has | ||
* additional indenting, the opening fence's first backtick may be up to | ||
* three whitespace characters after the start offset. | ||
*/ | ||
startOffset = node.position.start.offset; | ||
/* | ||
* Extract the Markdown source to determine the leading whitespace for each | ||
* line. | ||
*/ | ||
code = text.slice(startOffset, node.position.end.offset); | ||
lines = code.split("\n"); | ||
/* | ||
* The parser trims leading whitespace from each line of code within the | ||
* fenced code block up to the opening fence's first backtick. The first | ||
* backtick's column is the AST node's starting column plus any additional | ||
* indentation. | ||
*/ | ||
baseIndent = node.position.start.column - 1 | ||
+ leadingWhitespaceRegex.exec(lines[0])[0].length; | ||
/* | ||
* Track the length of any inserted configuration comments at the beginning | ||
* of the linted JS and start the JS offset lookup keys at this index. | ||
*/ | ||
commentLength = comments.reduce(function(len, comment) { | ||
return len + comment.length + 1; | ||
}, 0); | ||
/* | ||
* In case there are configuration comments, initialize the map so that the | ||
* first lookup index is always 0. If there are no configuration comments, | ||
* the lookup index will also be 0, and the lookup should always go to the | ||
* last range that matches, skipping this initialization entry. | ||
*/ | ||
rangeMap = [{ | ||
js: 0, | ||
md: 0 | ||
}]; | ||
// Start the JS offset after any configuration comments. | ||
jsOffset = commentLength; | ||
/* | ||
* Start the Markdown offset at the beginning of the block's first line of | ||
* actual code. The first line of the block is always the opening fence, so | ||
* the code begins on the second line. | ||
*/ | ||
mdOffset = startOffset + lines[0].length + 1; | ||
/* | ||
* For each line, determine how much leading whitespace was trimmed due to | ||
* indentation. Increase the JS lookup offset by the length of the line | ||
* post-trimming and the Markdown offset by the total line length. | ||
*/ | ||
for (i = 0; i + 1 < lines.length; i++) { | ||
line = lines[i + 1]; | ||
leadingWhitespaceLength = leadingWhitespaceRegex.exec(line)[0].length; | ||
// The parser trims leading whitespace up to the level of the opening | ||
// fence, so keep any additional indentation beyond that. | ||
trimLength = Math.min(baseIndent, leadingWhitespaceLength); | ||
rangeMap.push({ | ||
js: jsOffset, | ||
// Advance `trimLength` character from the beginning of the Markdown | ||
// line to the beginning of the equivalent JS line, then compute the | ||
// delta. | ||
md: mdOffset + trimLength - jsOffset | ||
}); | ||
// Accumulate the current line in the offsets, and don't forget the | ||
// newline. | ||
mdOffset += line.length + 1; | ||
jsOffset += line.length - trimLength + 1; | ||
} | ||
return rangeMap; | ||
} | ||
/** | ||
* Extracts lintable JavaScript code blocks from Markdown text. | ||
@@ -85,3 +218,3 @@ * @param {string} text The text of the file. | ||
if (node.lang && SUPPORTED_SYNTAXES.indexOf(node.lang.toLowerCase()) >= 0) { | ||
if (node.lang && SUPPORTED_SYNTAXES.indexOf(node.lang.split(" ")[0].toLowerCase()) >= 0) { | ||
index = parent.children.indexOf(node) - 1; | ||
@@ -105,3 +238,6 @@ previousNode = parent.children[index]; | ||
blocks.push(assign({}, node, { comments: comments })); | ||
blocks.push(assign({}, node, { | ||
comments: comments, | ||
rangeMap: getBlockRangeMap(text, node, comments) | ||
})); | ||
} | ||
@@ -126,2 +262,4 @@ } | ||
var blockStart = block.position.start.line; | ||
/** | ||
@@ -133,3 +271,5 @@ * Adjusts ESLint messages to point to the correct location in the Markdown. | ||
return function adjustMessage(message) { | ||
var lineInCode = message.line - leadingCommentLines; | ||
var endLine = message.endLine - leadingCommentLines; | ||
if (lineInCode < 1) { | ||
@@ -139,6 +279,28 @@ return null; | ||
return assign({}, message, { | ||
line: lineInCode + block.position.start.line, | ||
var out = { | ||
line: lineInCode + blockStart, | ||
endLine: endLine ? endLine + blockStart : endLine, | ||
column: message.column + block.position.indent[lineInCode - 1] - 1 | ||
}); | ||
}; | ||
var adjustedFix = {}; | ||
if (message.fix) { | ||
adjustedFix.fix = { | ||
range: message.fix.range.map(function(range) { | ||
// Advance through the block's range map to find the last | ||
// matching range by finding the first range too far and | ||
// then going back one. | ||
var i = 1; | ||
while (i < block.rangeMap.length && block.rangeMap[i].js < range) { | ||
i++; | ||
} | ||
// Apply the mapping delta for this range. | ||
return range + block.rangeMap[i - 1].md; | ||
}), | ||
text: message.fix.text | ||
}; | ||
} | ||
return assign({}, message, out, adjustedFix); | ||
}; | ||
@@ -171,3 +333,4 @@ } | ||
preprocess: preprocess, | ||
postprocess: postprocess | ||
postprocess: postprocess, | ||
supportsAutofix: SUPPORTS_AUTOFIX | ||
}; |
{ | ||
"name": "eslint-plugin-markdown", | ||
"version": "1.0.0-beta.8", | ||
"version": "1.0.0-rc.0", | ||
"description": "An ESLint plugin to lint JavaScript in Markdown code fences.", | ||
@@ -10,6 +10,3 @@ "license": "MIT", | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/eslint/eslint-plugin-markdown.git" | ||
}, | ||
"repository": "eslint/eslint-plugin-markdown", | ||
"bugs": { | ||
@@ -30,7 +27,7 @@ "url": "https://github.com/eslint/eslint-plugin-markdown/issues" | ||
"test-cov": "istanbul cover _mocha -- -c tests/lib/**/*.js", | ||
"release": "eslint-release", | ||
"ci-release": "eslint-ci-release", | ||
"gh-release": "eslint-gh-release", | ||
"alpharelease": "eslint-prerelease alpha", | ||
"betarelease": "eslint-prerelease beta" | ||
"generate-release": "eslint-generate-release", | ||
"generate-alpharelease": "eslint-generate-prerelease alpha", | ||
"generate-betarelease": "eslint-generate-prerelease beta", | ||
"generate-rcrelease": "eslint-generate-prerelease rc", | ||
"publish-release": "eslint-publish-release" | ||
}, | ||
@@ -45,5 +42,5 @@ "main": "index.js", | ||
"chai": "^3.0.0", | ||
"eslint": "^2.2.0", | ||
"eslint": "^4.19.1", | ||
"eslint-config-eslint": "^3.0.0", | ||
"eslint-release": "^0.10.2", | ||
"eslint-release": "^1.0.0", | ||
"istanbul": "^0.4.5", | ||
@@ -54,5 +51,8 @@ "mocha": "^2.2.5" | ||
"object-assign": "^4.0.1", | ||
"remark-parse": "^3.0.0", | ||
"remark-parse": "^5.0.0", | ||
"unified": "^6.1.2" | ||
}, | ||
"engines": { | ||
"node": "^6.14.0 || ^8.10.0 || >=9.10.0" | ||
} | ||
} |
@@ -125,2 +125,10 @@ # eslint-plugin-markdown | ||
## Fix issues automatically | ||
This plugin can attempt to fix some of the issues automatically using [`fix` ESLint option](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems). This option instructs ESLint to try to fix as many issues as possible. To enable this option you can add `--fix` to your ESLint call, for example: | ||
```bash | ||
eslint --fix --ext md . | ||
``` | ||
## Unsatisfiable Rules | ||
@@ -131,3 +139,26 @@ | ||
- `eol-last` | ||
- `unicode-bom` | ||
### Strict | ||
The `strict` rule is technically satisfiable inside of Markdown code blocks, but writing a `"use strict"` directive at the top of every code block is tedious and distracting. We recommend using a [glob pattern override](https://eslint.org/docs/user-guide/configuring#configuration-based-on-glob-patterns) for `.md` files to disable `strict` and enable the `impliedStrict` [parser option](https://eslint.org/docs/user-guide/configuring#specifying-parser-options) so the code blocks still parse in strict mode: | ||
```js | ||
// .eslintrc.json | ||
{ | ||
// ... | ||
"overrides": [{ | ||
"files": ["**/*.md"], | ||
"parserOptions": { | ||
"ecmaFeatures": { | ||
"impliedStrict": true | ||
} | ||
}, | ||
"rules": { | ||
"strict": "off" | ||
} | ||
}] | ||
} | ||
``` | ||
## Contributing | ||
@@ -134,0 +165,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
21744
304
172
1
+ Addedremark-parse@5.0.0(transitive)
- Removedhas@1.0.4(transitive)
- Removedremark-parse@3.0.1(transitive)
Updatedremark-parse@^5.0.0