Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eslint-plugin-markdown

Package Overview
Dependencies
Maintainers
4
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-markdown - npm Package Compare versions

Comparing version 1.0.0-beta.8 to 1.0.0-rc.0

13

CHANGELOG.md

@@ -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 @@

175

lib/processor.js

@@ -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
};

26

package.json
{
"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 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc