eslint-plugin-mdx
Version:
ESLint Plugin for MDX
511 lines (493 loc) • 16.5 kB
JavaScript
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 };