eslint-plugin-markdown
Advanced tools
Comparing version 2.0.0 to 2.0.1
@@ -0,1 +1,8 @@ | ||
v2.0.1 - April 5, 2021 | ||
* [`d23d5f7`](https://github.com/eslint/eslint-plugin-markdown/commit/d23d5f739943d136669aac945ef25528f31cd7db) Fix: use blocksCache instead of single blocks instance (fixes #181) (#183) (JounQin) | ||
* [`a09a645`](https://github.com/eslint/eslint-plugin-markdown/commit/a09a6452c1031b029efb17fe606cc5f56cfa0d23) Chore: add yarn.lock and package-lock.json into .gitignore (#184) (JounQin) | ||
* [`1280ac1`](https://github.com/eslint/eslint-plugin-markdown/commit/1280ac1f4998e8ab2030742fe510cc02d200aea2) Docs: improve jsdoc, better for typings (#182) (JounQin) | ||
* [`79be776`](https://github.com/eslint/eslint-plugin-markdown/commit/79be776331cf2bb4db2f265ee6cf7260e90e3d5e) Fix: More reliable comment attachment (fixes #76) (#177) (Brandon Mills) | ||
v2.0.0 - February 14, 2021 | ||
@@ -2,0 +9,0 @@ |
@@ -6,2 +6,21 @@ /** | ||
/** | ||
* @typedef {import('eslint/lib/shared/types').LintMessage} Message | ||
* | ||
* @typedef {Object} ASTNode | ||
* @property {string} type | ||
* @property {string} [lang] | ||
* | ||
* @typedef {Object} RangeMap | ||
* @property {number} js | ||
* @property {number} md | ||
* | ||
* @typedef {Object} BlockBase | ||
* @property {string} baseIndentText | ||
* @property {string[]} comments | ||
* @property {RangeMap[]} rangeMap | ||
* | ||
* @typedef {ASTNode & BlockBase} Block | ||
*/ | ||
"use strict"; | ||
@@ -20,3 +39,6 @@ | ||
let blocks = []; | ||
/** | ||
* @type {Map<string, Block[]>} | ||
*/ | ||
const blocksCache = new Map(); | ||
@@ -26,9 +48,10 @@ /** | ||
* @param {ASTNode} node A Markdown AST node. | ||
* @param {Object} callbacks A map of node types to callbacks. | ||
* @param {Object} [parent] The node's parent AST node. | ||
* @param {{[key: string]: (node: ASTNode) => void}} callbacks A map of node types to callbacks. | ||
* @returns {void} | ||
*/ | ||
function traverse(node, callbacks, parent) { | ||
function traverse(node, callbacks) { | ||
if (callbacks[node.type]) { | ||
callbacks[node.type](node, parent); | ||
callbacks[node.type](node); | ||
} else { | ||
callbacks["*"](); | ||
} | ||
@@ -38,3 +61,3 @@ | ||
for (let i = 0; i < node.children.length; i++) { | ||
traverse(node.children[i], callbacks, node); | ||
traverse(node.children[i], callbacks); | ||
} | ||
@@ -45,5 +68,6 @@ } | ||
/** | ||
* Converts leading HTML comments to JS block comments. | ||
* Extracts `eslint-*` or `global` comments from HTML comments if present. | ||
* @param {string} html The text content of an HTML AST node. | ||
* @returns {string[]} An array of JS block comments. | ||
* @returns {string} The comment's text without the opening and closing tags or | ||
* an empty string if the text is not an ESLint HTML comment. | ||
*/ | ||
@@ -124,5 +148,5 @@ function getComment(html) { | ||
* @param {ASTNode} node A Markdown code block AST node. | ||
* @param {comments} comments List of configuration comment strings that will be | ||
* @param {string[]} 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 | ||
* @returns {RangeMap[]} A list of offset-based adjustments, where lookups are | ||
* done based on the `js` key, which represents the range in the linted JS, | ||
@@ -218,34 +242,42 @@ * and the `md` key is the offset delta that, when added to the JS range, | ||
/** | ||
* Extracts lintable JavaScript code blocks from Markdown text. | ||
* Extracts lintable code blocks from Markdown text. | ||
* @param {string} text The text of the file. | ||
* @returns {string[]} Source code strings to lint. | ||
* @param {string} filename The filename of the file | ||
* @returns {Array<{ filename: string, text: string }>} Source code blocks to lint. | ||
*/ | ||
function preprocess(text) { | ||
function preprocess(text, filename) { | ||
const ast = markdown.parse(text); | ||
const blocks = []; | ||
blocks = []; | ||
blocksCache.set(filename, blocks); | ||
/** | ||
* During the depth-first traversal, keep track of any sequences of HTML | ||
* comment nodes containing `eslint-*` or `global` comments. If a code | ||
* block immediately follows such a sequence, insert the comments at the | ||
* top of the code block. Any non-ESLint comment or other node type breaks | ||
* and empties the sequence. | ||
* @type {string[]} | ||
*/ | ||
let htmlComments = []; | ||
traverse(ast, { | ||
code(node, parent) { | ||
const comments = []; | ||
"*"() { | ||
htmlComments = []; | ||
}, | ||
code(node) { | ||
if (node.lang) { | ||
let index = parent.children.indexOf(node) - 1; | ||
let previousNode = parent.children[index]; | ||
const comments = []; | ||
while (previousNode && previousNode.type === "html") { | ||
const comment = getComment(previousNode.value); | ||
if (!comment) { | ||
break; | ||
} | ||
for (const comment of htmlComments) { | ||
if (comment.trim() === "eslint-skip") { | ||
htmlComments = []; | ||
return; | ||
} | ||
comments.unshift(`/*${comment}*/`); | ||
index--; | ||
previousNode = parent.children[index]; | ||
comments.push(`/*${comment}*/`); | ||
} | ||
htmlComments = []; | ||
blocks.push({ | ||
@@ -258,2 +290,11 @@ ...node, | ||
} | ||
}, | ||
html(node) { | ||
const comment = getComment(node.value); | ||
if (comment) { | ||
htmlComments.push(comment); | ||
} else { | ||
htmlComments = []; | ||
} | ||
} | ||
@@ -275,3 +316,3 @@ }); | ||
* @param {Block} block A code block. | ||
* @returns {Function} A function that adjusts messages in a code block. | ||
* @returns {(message: Message) => Message} A function that adjusts messages in a code block. | ||
*/ | ||
@@ -344,5 +385,10 @@ function adjustBlock(block) { | ||
* for each code block returned from `preprocess`. | ||
* @param {string} filename The filename of the file | ||
* @returns {Message[]} A flattened array of messages with mapped locations. | ||
*/ | ||
function postprocess(messages) { | ||
function postprocess(messages, filename) { | ||
const blocks = blocksCache.get(filename); | ||
blocksCache.delete(filename); | ||
return [].concat(...messages.map((group, i) => { | ||
@@ -349,0 +395,0 @@ const adjust = adjustBlock(blocks[i]); |
{ | ||
"name": "eslint-plugin-markdown", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"description": "An ESLint plugin to lint JavaScript in Markdown code fences.", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
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
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
45740
394