eslint-plugin-mdx
Advanced tools
Comparing version
@@ -1,2 +0,3 @@ | ||
import type { fromMarkdown as fromMarkdown_ } from 'mdast-util-from-markdown'; | ||
export declare const fromMarkdown: import("synckit").Syncify<typeof fromMarkdown_>; | ||
import type { Root } from 'mdast'; | ||
import type { Value } from 'mdast-util-from-markdown'; | ||
export declare const fromMarkdown: import("synckit").Syncify<(value: Value, isMdx: boolean) => Root>; |
@@ -1,2 +0,13 @@ | ||
export declare const DEFAULT_LANGUAGE_MAPPER: Record<string, string>; | ||
export declare const DEFAULT_LANGUAGE_MAPPER: { | ||
readonly ecmascript: "js"; | ||
readonly javascript: "js"; | ||
readonly javascriptreact: "jsx"; | ||
readonly typescript: "ts"; | ||
readonly typescriptreact: "tsx"; | ||
readonly markdown: "md"; | ||
readonly markdownjsx: "mdx"; | ||
readonly markdownreact: "mdx"; | ||
readonly mdown: "md"; | ||
readonly mkdn: "md"; | ||
}; | ||
export declare function getShortLang(filename: string, languageMapper?: Record<string, string> | false): string; |
@@ -1,3 +0,3 @@ | ||
import { last } from 'eslint-mdx'; | ||
export const DEFAULT_LANGUAGE_MAPPER = { | ||
ecmascript: 'js', | ||
javascript: 'js', | ||
@@ -8,2 +8,4 @@ javascriptreact: 'jsx', | ||
markdown: 'md', | ||
markdownjsx: 'mdx', | ||
markdownreact: 'mdx', | ||
mdown: 'md', | ||
@@ -13,10 +15,16 @@ mkdn: 'md', | ||
export function getShortLang(filename, languageMapper) { | ||
const language = last(filename.split('.')); | ||
const language = filename.split('.').at(-1); | ||
if (languageMapper === false) { | ||
return language; | ||
} | ||
languageMapper = { ...DEFAULT_LANGUAGE_MAPPER, ...languageMapper }; | ||
languageMapper = languageMapper | ||
? { ...DEFAULT_LANGUAGE_MAPPER, ...languageMapper } | ||
: DEFAULT_LANGUAGE_MAPPER; | ||
const mapped = languageMapper[language]; | ||
if (mapped) { | ||
return mapped; | ||
} | ||
const lang = language.toLowerCase(); | ||
return languageMapper[language] || languageMapper[lang] || lang; | ||
return languageMapper[lang] || lang; | ||
} | ||
//# sourceMappingURL=helpers.js.map |
import type { Linter } from 'eslint'; | ||
declare function preprocess(sourceText: string, filename: string): Array<{ | ||
declare function preprocess(sourceText: string, filename: string): { | ||
filename: string; | ||
text: string; | ||
}>; | ||
}[]; | ||
declare function postprocess(messages: Linter.LintMessage[][], filename: string): Linter.LintMessage[]; | ||
@@ -7,0 +7,0 @@ export declare const markdownProcessor: { |
@@ -1,2 +0,3 @@ | ||
import { fromMarkdown } from "../from-markdown.js"; | ||
import { fromMarkdown } from '../from-markdown.js'; | ||
import { meta } from '../meta.js'; | ||
const UNSATISFIABLE_RULES = new Set([ | ||
@@ -23,11 +24,24 @@ 'eol-last', | ||
} | ||
function getComment(html) { | ||
const commentStart = '<!--'; | ||
const commentEnd = '-->'; | ||
const regex = /^(?:eslint\b|global\s)/u; | ||
if (!html.startsWith(commentStart) || !html.endsWith(commentEnd)) { | ||
const COMMENTS = [ | ||
[ | ||
/^<!-{2,}/, | ||
/-{2,}>$/, | ||
], | ||
[ | ||
/^\/\*+/, | ||
/\*+\/$/, | ||
], | ||
]; | ||
const eslintCommentRegex = /^(?:eslint\b|global\s)/u; | ||
function getComment(value, isMdx = false) { | ||
const [commentStart, commentEnd] = COMMENTS[+isMdx]; | ||
const commentStartMatched = commentStart.exec(value); | ||
const commentEndMatched = commentEnd.exec(value); | ||
if (commentStartMatched == null || commentEndMatched == null) { | ||
return ''; | ||
} | ||
const comment = html.slice(commentStart.length, -commentEnd.length); | ||
if (!regex.test(comment.trim())) { | ||
const comment = value | ||
.slice(commentStartMatched[0].length, -commentEndMatched[0].length) | ||
.trim(); | ||
if (!eslintCommentRegex.test(comment)) { | ||
return ''; | ||
@@ -73,3 +87,3 @@ } | ||
} | ||
const codeBlockFileNameRegex = /filename=(["']).*?\1/u; | ||
const codeBlockFileNameRegex = /filename=(?<quote>["'])(?<filename>.*?)\1/u; | ||
function fileNameFromMeta(block) { | ||
@@ -80,36 +94,40 @@ return codeBlockFileNameRegex | ||
} | ||
const languageToFileExtension = { | ||
javascript: 'js', | ||
ecmascript: 'js', | ||
typescript: 'ts', | ||
markdown: 'md', | ||
}; | ||
function preprocess(sourceText, filename) { | ||
const text = sourceText.startsWith(BOM) ? sourceText.slice(1) : sourceText; | ||
const ast = fromMarkdown(text); | ||
const ast = fromMarkdown(text, filename.endsWith('.mdx')); | ||
const blocks = []; | ||
blocksCache.set(filename, blocks); | ||
let htmlComments = []; | ||
let allComments = []; | ||
function mdxExpression(node) { | ||
const comment = getComment(node.value, true); | ||
if (comment) { | ||
allComments.push(comment); | ||
} | ||
else { | ||
allComments = []; | ||
} | ||
} | ||
traverse(ast, { | ||
'*'() { | ||
htmlComments = []; | ||
allComments = []; | ||
}, | ||
code(node) { | ||
if (node.lang) { | ||
const comments = []; | ||
for (const comment of htmlComments) { | ||
if (comment.trim() === 'eslint-skip') { | ||
htmlComments = []; | ||
return; | ||
} | ||
comments.push(`/*${comment}*/`); | ||
if (!node.lang) { | ||
return; | ||
} | ||
const comments = []; | ||
for (const comment of allComments) { | ||
if (comment === 'eslint-skip') { | ||
allComments = []; | ||
return; | ||
} | ||
htmlComments = []; | ||
blocks.push({ | ||
...node, | ||
baseIndentText: getIndentText(text, node), | ||
comments, | ||
rangeMap: getBlockRangeMap(text, node, comments), | ||
}); | ||
comments.push(`/* ${comment} */`); | ||
} | ||
allComments = []; | ||
blocks.push({ | ||
...node, | ||
baseIndentText: getIndentText(text, node), | ||
comments, | ||
rangeMap: getBlockRangeMap(text, node, comments), | ||
}); | ||
}, | ||
@@ -119,16 +137,15 @@ html(node) { | ||
if (comment) { | ||
htmlComments.push(comment); | ||
allComments.push(comment); | ||
} | ||
else { | ||
htmlComments = []; | ||
allComments = []; | ||
} | ||
}, | ||
mdxFlowExpression: mdxExpression, | ||
mdxTextExpression: mdxExpression, | ||
}); | ||
return blocks.map((block, index) => { | ||
const [language] = block.lang.trim().split(' '); | ||
const fileExtension = Object.hasOwn(languageToFileExtension, language) | ||
? languageToFileExtension[language] | ||
: language; | ||
return { | ||
filename: fileNameFromMeta(block) ?? `${index}.${fileExtension}`, | ||
filename: fileNameFromMeta(block) ?? `${index}.${language}`, | ||
text: [...block.comments, block.value, ''].join('\n'), | ||
@@ -198,4 +215,4 @@ }; | ||
meta: { | ||
name: '@eslint/markdown/markdown', | ||
version: '6.3.0', | ||
name: 'mdx/markdown', | ||
version: meta.version, | ||
}, | ||
@@ -202,0 +219,0 @@ preprocess, |
@@ -15,3 +15,3 @@ import type { Code } from 'mdast'; | ||
} | ||
export interface BlockBase { | ||
export interface CodeBlock extends Code { | ||
baseIndentText: string; | ||
@@ -21,3 +21,1 @@ comments: string[]; | ||
} | ||
export interface Block extends Code, BlockBase { | ||
} |
@@ -32,11 +32,7 @@ import path from 'node:path'; | ||
const ignoreRemarkConfig = Boolean(options.ignoreRemarkConfig); | ||
const physicalFilename = getPhysicalFilename(filename); | ||
const sourceText = sourceCode.getText(node); | ||
const { messages, content: fixedText } = performSyncWork({ | ||
fileOptions: { | ||
path: physicalFilename, | ||
value: sourceText, | ||
cwd: context.getCwd(), | ||
}, | ||
physicalFilename, | ||
filePath: getPhysicalFilename(filename), | ||
code: sourceText, | ||
cwd: context.getCwd(), | ||
isMdx, | ||
@@ -72,3 +68,3 @@ process: true, | ||
node, | ||
fix: fixedText === sourceText | ||
fix: fixedText == null || fixedText === sourceText | ||
? null | ||
@@ -75,0 +71,0 @@ : () => fixed++ |
import { fromMarkdown } from 'mdast-util-from-markdown'; | ||
import { mdxFromMarkdown } from 'mdast-util-mdx'; | ||
import { mdxjs } from 'micromark-extension-mdxjs'; | ||
import { runAsWorker } from 'synckit'; | ||
runAsWorker(fromMarkdown); | ||
runAsWorker((value, isMdx) => isMdx | ||
? fromMarkdown(value, { | ||
extensions: [mdxjs()], | ||
mdastExtensions: [mdxFromMarkdown()], | ||
}) | ||
: fromMarkdown(value)); | ||
//# sourceMappingURL=worker.js.map |
{ | ||
"name": "eslint-plugin-mdx", | ||
"version": "3.3.2", | ||
"version": "3.4.0", | ||
"type": "module", | ||
@@ -52,4 +52,6 @@ "description": "ESLint Plugin for MDX", | ||
"dependencies": { | ||
"eslint-mdx": "^3.3.2", | ||
"eslint-mdx": "^3.4.0", | ||
"mdast-util-from-markdown": "^2.0.2", | ||
"mdast-util-mdx": "^3.0.0", | ||
"micromark-extension-mdxjs": "^3.0.0", | ||
"remark-mdx": "^3.1.0", | ||
@@ -56,0 +58,0 @@ "remark-parse": "^11.0.0", |
@@ -13,3 +13,3 @@ <p align="center"> | ||
[](https://github.com/mdx-js/eslint-mdx/actions/workflows/ci.yml) | ||
[](https://github.com/mdx-js/eslint-mdx/actions/workflows/ci.yml?query=branch%3Amaster) | ||
[](https://codecov.io/gh/mdx-js/eslint-mdx) | ||
@@ -36,3 +36,3 @@ [](https://github.com/plantain-00/type-coverage) | ||
- [Usage](#usage) | ||
- [Classic](#classic) | ||
- [Classic Config](#classic-config) | ||
- [Flat Config](#flat-config) | ||
@@ -79,9 +79,21 @@ - [Parser Options](#parser-options) | ||
If you're using multi languages, `js/jsx/ts/tsx/vue`, etc for example, you'd better to always use [`overrides`](https://eslint.org/docs/user-guide/configuring/configuration-files#how-do-overrides-work) feature of ESLint, because configs may be overridden by following configs. | ||
1. If you're using multi languages, `js/jsx/ts/tsx/vue`, etc for example, you'd better to always use [`overrides`](https://eslint.org/docs/user-guide/configuring/configuration-files#how-do-overrides-work) ([Classic Config](#classic-config)) or [`files`](https://eslint.org/docs/latest/use/configure/configuration-files#specifying-files-and-ignores) ([Flag Config](#flat-config)) feature of ESLint, because configs may be overridden by following configs. | ||
See [#251](https://github.com/mdx-js/eslint-mdx/issues/251#issuecomment-736139224) for more details. | ||
See [#251](https://github.com/mdx-js/eslint-mdx/issues/251#issuecomment-736139224) for more details. | ||
2. If you're using `{/* eslint-disable-line mdx/remark */}` with `prettier`, this won't work because `prettier` will add a blank line after the comment, which makes it invalid. You can use `{/* eslint-disable mdx/remark */}` paired with `{/* eslint-enable mdx/remark */}` instead: | ||
<!-- eslint-skip --> | ||
```mdx | ||
{/* eslint-disable mdx/remark */} | ||
# Heading | ||
{/* eslint-enable mdx/remark */} | ||
``` | ||
## Usage | ||
### Classic | ||
### Classic Config | ||
@@ -241,7 +253,9 @@ `.eslintrc` file: | ||
[](https://github.com/sponsors/JounQin) | ||
## Sponsors | ||
| 1stG | RxTS | UnTS | | ||
| ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | ||
| [](https://opencollective.com/1stG) | [](https://opencollective.com/rxts) | [](https://opencollective.com/unts) | | ||
| 1stG | RxTS | UnTS | | ||
| ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | ||
| [](https://opencollective.com/1stG) | [](https://opencollective.com/rxts) | [](https://opencollective.com/unts) | | ||
@@ -252,8 +266,6 @@ [](https://opencollective.com/unified) | ||
[](https://github.com/sponsors/JounQin) | ||
| 1stG | RxTS | UnTS | | ||
| ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | | ||
| [](https://opencollective.com/1stG) | [](https://opencollective.com/rxts) | [](https://opencollective.com/unts) | | ||
| 1stG | RxTS | UnTS | | ||
| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | ||
| [](https://opencollective.com/1stG) | [](https://opencollective.com/rxts) | [](https://opencollective.com/unts) | | ||
[](https://opencollective.com/unified) | ||
@@ -260,0 +272,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
84522
3.23%1537
3.92%288
4.35%12
20%+ Added
Updated