UNPKG

eslint-plugin-mdx

Version:
511 lines (493 loc) 16.5 kB
import * as eslintMdx from 'eslint-mdx'; import { arrayify, last, DEFAULT_EXTENSIONS, MARKDOWN_EXTENSIONS, getPhysicalFilename, performSyncWork } from 'eslint-mdx'; import { processors as processors$1 } from 'eslint-plugin-markdown'; import path from 'node:path'; import { createRequire } from 'node:module'; var mdx = /*#__PURE__*/Object.freeze({ __proto__: null, get DEFAULT_LANGUAGE_MAPPER () { return DEFAULT_LANGUAGE_MAPPER; }, get base () { return base; }, get codeBlocks () { return codeBlocks; }, get configs () { return configs; }, get createRemarkProcessor () { return createRemarkProcessor; }, get flat () { return flat; }, get flatCodeBlocks () { return flatCodeBlocks; }, get getGlobals () { return getGlobals; }, get getShortLang () { return getShortLang; }, get meta () { return meta; }, get overrides () { return overrides$1; }, get processorOptions () { return processorOptions; }, get processors () { return processors; }, get recommended () { return recommended; }, get remark () { return remark; }, get rules () { return rules; } }); const base = { parser: "eslint-mdx", parserOptions: { sourceType: "module", ecmaVersion: "latest" }, plugins: ["mdx"], processor: "mdx/remark", rules: { "mdx/remark": "warn", "no-unused-expressions": "error" } }; const codeBlocks = { parserOptions: { ecmaFeatures: { // Adding a "use strict" directive at the top of // every code block is tedious and distracting, so // opt into strict mode parsing without the // directive. impliedStrict: true } }, rules: { // The Markdown parser automatically trims trailing // newlines from code blocks. "eol-last": "off", // In code snippets and examples, these rules are often // counterproductive to clarity and brevity. "no-undef": "off", "no-unused-expressions": "off", "no-unused-vars": "off", "padded-blocks": "off", // Adding a "use strict" directive at the top of every // code block is tedious and distracting. The config // opts into strict mode parsing without the directive. strict: "off", // The processor will not receive a Unicode Byte Order // Mark from the Markdown parser. "unicode-bom": "off" } }; var __defProp$5 = Object.defineProperty; var __getOwnPropSymbols$5 = Object.getOwnPropertySymbols; var __hasOwnProp$5 = Object.prototype.hasOwnProperty; var __propIsEnum$5 = Object.prototype.propertyIsEnumerable; var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$5 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$5.call(b, prop)) __defNormalProp$5(a, prop, b[prop]); if (__getOwnPropSymbols$5) for (var prop of __getOwnPropSymbols$5(b)) { if (__propIsEnum$5.call(b, prop)) __defNormalProp$5(a, prop, b[prop]); } return a; }; var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp$5.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols$5) for (var prop of __getOwnPropSymbols$5(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum$5.call(source, prop)) target[prop] = source[prop]; } return target; }; const flat = { files: ["**/*.{md,mdx}"], languageOptions: { sourceType: "module", ecmaVersion: "latest", parser: eslintMdx, globals: { React: false } }, plugins: { mdx }, rules: { "mdx/remark": "warn", "no-unused-expressions": "error", "react/react-in-jsx-scope": 0 } }; const _a = codeBlocks, { parserOptions } = _a, restConfig = __objRest(_a, ["parserOptions"]); const flatCodeBlocks = __spreadValues$5({ files: ["**/*.{md,mdx}/*"], languageOptions: { parserOptions } }, restConfig); var __defProp$4 = Object.defineProperty; var __defProps$2 = Object.defineProperties; var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$4 = Object.getOwnPropertySymbols; var __hasOwnProp$4 = Object.prototype.hasOwnProperty; var __propIsEnum$4 = Object.prototype.propertyIsEnumerable; var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$4 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$4.call(b, prop)) __defNormalProp$4(a, prop, b[prop]); if (__getOwnPropSymbols$4) for (var prop of __getOwnPropSymbols$4(b)) { if (__propIsEnum$4.call(b, prop)) __defNormalProp$4(a, prop, b[prop]); } return a; }; var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b)); let isReactPluginAvailable = false; try { require.resolve("eslint-plugin-react"); isReactPluginAvailable = true; } catch (e) { } const overrides$1 = __spreadProps$2(__spreadValues$4({}, base), { globals: { React: false }, plugins: arrayify( base.plugins, /* istanbul ignore next */ isReactPluginAvailable ? "react" : null ), rules: { "react/jsx-no-undef": ( /* istanbul ignore next */ isReactPluginAvailable ? [ 2, { allowGlobals: true } ] : 0 ), "react/react-in-jsx-scope": 0 } }); var __defProp$3 = Object.defineProperty; var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols; var __hasOwnProp$3 = Object.prototype.hasOwnProperty; var __propIsEnum$3 = Object.prototype.propertyIsEnumerable; var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$3 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$3.call(b, prop)) __defNormalProp$3(a, prop, b[prop]); if (__getOwnPropSymbols$3) for (var prop of __getOwnPropSymbols$3(b)) { if (__propIsEnum$3.call(b, prop)) __defNormalProp$3(a, prop, b[prop]); } return a; }; const overrides = [ __spreadValues$3({ files: ["*.md", "*.mdx"], extends: "plugin:mdx/overrides" }, base), { files: "**/*.{md,mdx}/**", extends: "plugin:mdx/code-blocks" } ]; const recommended = { overrides }; const getImportMetaUrl = () => { try { return new Function("return import.meta.url")(); } catch (e) { return path.resolve(process.cwd(), "__test__.js"); } }; const cjsRequire = typeof require === "undefined" ? createRequire(getImportMetaUrl()) : require; const addPrettierRules = () => { try { cjsRequire.resolve("prettier"); const { meta } = cjsRequire("eslint-plugin-prettier"); const version = (meta == null ? void 0 : meta.version) || ""; const [major, minor, patch] = version.split("."); if ( /* istanbul ignore next */ +major > 5 || +major === 5 && (+minor > 1 || +minor === 1 && Number.parseInt(patch) >= 2) ) { return; } overrides.push( { files: "*.md", rules: { "prettier/prettier": [ "error", { parser: "markdown" } ] } }, { files: "*.mdx", rules: { "prettier/prettier": [ "error", { parser: "mdx" } ] } } ); } catch (e) { } }; addPrettierRules(); const configs = { base, "code-blocks": codeBlocks, codeBlocks, flat, flatCodeBlocks, overrides: overrides$1, recommended }; const getGlobals = (sources, initialGlobals = {}) => (Array.isArray(sources) ? ( // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion sources ) : Object.keys(sources)).reduce( (globals, source) => Object.assign(globals, { [source]: false }), // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter initialGlobals ); var name = "eslint-plugin-mdx"; var version = "3.1.5"; const meta = { name, version }; var __defProp$2 = Object.defineProperty; var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols; var __hasOwnProp$2 = Object.prototype.hasOwnProperty; var __propIsEnum$2 = Object.prototype.propertyIsEnumerable; var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$2 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$2.call(b, prop)) __defNormalProp$2(a, prop, b[prop]); if (__getOwnPropSymbols$2) for (var prop of __getOwnPropSymbols$2(b)) { if (__propIsEnum$2.call(b, prop)) __defNormalProp$2(a, prop, b[prop]); } return a; }; const DEFAULT_LANGUAGE_MAPPER = { javascript: "js", javascriptreact: "jsx", typescript: "ts", typescriptreact: "tsx", markdown: "md", mdown: "md", mkdn: "md" }; function getShortLang(filename, languageMapper) { const language = last(filename.split(".")); if (languageMapper === false) { return language; } languageMapper = __spreadValues$2(__spreadValues$2({}, DEFAULT_LANGUAGE_MAPPER), languageMapper); const lang = language.toLowerCase(); return languageMapper[language] || languageMapper[lang] || lang; } const processorOptions = {}; const linterPath = Object.keys(require.cache).find( (path) => /([/\\])eslint\1lib(?:\1linter){2}\.js$/.test(path) ); if (!linterPath) { throw new Error("Could not find ESLint Linter in require cache"); } const ESLinter = require(linterPath).Linter; const { verify } = ESLinter.prototype; ESLinter.prototype.verify = function(code, config, options) { const settings = config && (typeof config.extractConfig === "function" ? config.extractConfig( /* istanbul ignore next */ // eslint-disable-next-line unicorn/no-typeof-undefined typeof options === "undefined" || typeof options === "string" ? options : options.filename ) : config).settings || {}; processorOptions.lintCodeBlocks = settings["mdx/code-blocks"] === true; processorOptions.languageMapper = settings["mdx/language-mapper"]; return verify.call(this, code, config, options); }; var __defProp$1 = Object.defineProperty; var __defProps$1 = Object.defineProperties; var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols; var __hasOwnProp$1 = Object.prototype.hasOwnProperty; var __propIsEnum$1 = Object.prototype.propertyIsEnumerable; var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$1 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]); if (__getOwnPropSymbols$1) for (var prop of __getOwnPropSymbols$1(b)) { if (__propIsEnum$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]); } return a; }; var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b)); const createRemarkProcessor = (processorOptions$1 = processorOptions) => ({ meta: { name: "mdx/remark", version: meta.version }, supportsAutofix: true, preprocess(text, filename) { if (!processorOptions$1.lintCodeBlocks) { return [text]; } return [ text, ...processors$1.markdown.preprocess(text, filename).map(({ text: text2, filename: filename2 }) => ({ text: text2, filename: filename2.slice(0, filename2.lastIndexOf(".")) + "." + getShortLang(filename2, processorOptions$1.languageMapper) })) ]; }, postprocess([mdxMessages, ...markdownMessages], filename) { return [ ...mdxMessages, ...processors$1.markdown.postprocess(markdownMessages, filename) ].sort((a, b) => a.line - b.line || a.column - b.column).map((lintMessage) => { const { message, ruleId: eslintRuleId, severity: eslintSeverity } = lintMessage; if (eslintRuleId !== "mdx/remark") { return lintMessage; } const { source, ruleId, reason, severity } = JSON.parse( message ); return __spreadProps$1(__spreadValues$1({}, lintMessage), { ruleId: `${source}-${ruleId}`, message: reason, severity: Math.max(eslintSeverity, severity) }); }); } }); const remark$1 = createRemarkProcessor(); const processors = { remark: remark$1 }; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); const remark = { meta: { type: "layout", docs: { description: "Linter integration with remark plugins", category: "Stylistic Issues", recommended: true }, fixable: "code" }, create(context) { const filename = context.getFilename(); const extname = path.extname(filename); const sourceCode = context.getSourceCode(); const options = context.parserOptions; const isMdx = [ ...DEFAULT_EXTENSIONS, ...options.extensions || [] ].includes(extname); const isMarkdown = [ ...MARKDOWN_EXTENSIONS, ...options.markdownExtensions || [] ].includes(extname); return { // eslint-disable-next-line sonarjs/cognitive-complexity Program(node) { if (!isMdx && !isMarkdown) { return; } const ignoreRemarkConfig = Boolean(options.ignoreRemarkConfig); const physicalFilename = getPhysicalFilename(filename); const sourceText = sourceCode.getText(node); const { messages, content: fixedText } = performSyncWork({ fileOptions: { path: physicalFilename, value: sourceText, // eslint-disable-next-line sonar/deprecation -- FIXME: ESLint 8.40+ required cwd: context.getCwd() }, physicalFilename, isMdx, process: true, ignoreRemarkConfig }); let fixed = 0; for (const { source, reason, ruleId, fatal, line, column, place } of messages) { const severity = fatal ? 2 : fatal == null ? 0 : 1; if (!severity) { continue; } const message = { reason, source, ruleId, severity }; const point = { line, // ! eslint ast column is 0-indexed, but unified is 1-indexed column: column - 1 }; context.report({ // related to https://github.com/eslint/eslint/issues/14198 message: JSON.stringify(message), loc: ( /* istanbul ignore next */ place && "start" in place ? __spreadProps(__spreadValues({}, point), { start: __spreadProps(__spreadValues({}, place.start), { column: place.start.column - 1 }), end: __spreadProps(__spreadValues({}, place.end), { column: place.end.column - 1 }) }) : point ), node, fix: fixedText === sourceText ? null : () => fixed++ ? null : { range: [0, sourceText.length], text: fixedText } }); } } }; } }; const rules = { remark }; export { DEFAULT_LANGUAGE_MAPPER, base, codeBlocks, configs, createRemarkProcessor, flat, flatCodeBlocks, getGlobals, getShortLang, meta, overrides$1 as overrides, processorOptions, processors, recommended, remark, rules };