eslint-plugin-mdx
Version:
ESLint Plugin for MDX
104 lines • 4.04 kB
JavaScript
import path from 'node:path';
import { DEFAULT_EXTENSIONS, MARKDOWN_EXTENSIONS, getPhysicalFilename, performSyncWork, } from 'eslint-mdx';
import { generateDifferences } from 'prettier-linter-helpers';
const normalizeDifference = (difference) => ({
deleteText: '',
insertText: '',
...difference,
});
const getDifferences = (sourceText, fixedText) => fixedText == null || fixedText === sourceText
? []
: generateDifferences(sourceText, fixedText).map(normalizeDifference);
const getFixesForPlace = (differences, place) => {
if (place == null) {
return null;
}
const start = 'start' in place ? place.start : place;
const end = 'start' in place ? place.end : place;
if (start.offset == null || end.offset == null) {
return null;
}
const fixes = differences
.filter(({ deleteText, offset }) => offset <= end.offset && offset + deleteText.length >= start.offset)
.map(({ deleteText, insertText, offset }) => ({
range: [offset, offset + deleteText.length],
text: insertText,
}));
return fixes.length > 0 ? fixes : null;
};
export const remark = {
meta: {
type: 'layout',
docs: {
description: 'Linter integration with remark plugins',
category: 'Stylistic Issues',
recommended: true,
},
fixable: 'code',
},
create(context) {
const filename = context.filename ??
context.getFilename();
const extname = path.extname(filename);
const sourceCode = context.sourceCode ??
context.getSourceCode();
const { extensions, markdownExtensions, ignoreRemarkConfig, remarkConfigPath, } = {
...context.parserOptions,
...context.languageOptions?.parserOptions,
};
const isMdx = [...DEFAULT_EXTENSIONS, ...(extensions || [])].includes(extname);
const isMarkdown = [
...MARKDOWN_EXTENSIONS,
...(markdownExtensions || []),
].includes(extname);
return {
Program(node) {
if (!isMdx && !isMarkdown) {
return;
}
const sourceText = sourceCode.getText(node);
const { messages, content: fixedText } = performSyncWork({
filePath: getPhysicalFilename(filename),
code: sourceText,
cwd: context.cwd ??
context.getCwd(),
isMdx,
process: true,
ignoreRemarkConfig,
remarkConfigPath,
});
const differences = getDifferences(sourceText, fixedText);
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,
column: column - 1,
};
const fixes = getFixesForPlace(differences, place);
context.report({
message: JSON.stringify(message),
loc: place && 'start' in place
? {
...point,
start: { ...place.start, column: place.start.column - 1 },
end: { ...place.end, column: place.end.column - 1 },
}
: point,
node,
fix: () => fixes,
});
}
},
};
},
};
//# sourceMappingURL=remark.js.map