twoslash-eslint
Version:
ESLint-backed twoslash runner
85 lines (80 loc) • 2.5 kB
JavaScript
const eslint = require('eslint');
const twoslashProtocol = require('twoslash-protocol');
function createTwoslasher(options) {
const {
includeDocs = true,
mergeMessages = true
} = options;
const linter = new eslint.Linter({
cwd: options.cwd,
configType: "flat"
});
let docsMap;
function getDocsMap() {
if (!docsMap) {
docsMap = /* @__PURE__ */ new Map();
for (const config of options.eslintConfig) {
Object.entries(config.plugins || {}).forEach(([pluginName, plugin]) => {
Object.entries(plugin?.rules || {}).forEach(([ruleName, rule]) => {
if ("meta" in rule) {
const docs = rule.meta?.docs?.url;
if (docs)
docsMap.set(`${pluginName}/${ruleName}`, docs);
}
});
});
}
}
return docsMap;
}
return (code, file) => {
const filename = file?.includes(".") ? file : `index.${file ?? "ts"}`;
const messages = linter.verify(
options.eslintCodePreprocess?.(code) || code,
options.eslintConfig,
{ filename }
);
const pc = twoslashProtocol.createPositionConverter(code);
const raws = messages.map((message) => {
const start = pc.posToIndex(message.line - 1, message.column - 1);
const end = message.endLine != null && message.endColumn != null ? pc.posToIndex(message.endLine - 1, message.endColumn - 1) : start + 1;
let text = message.message;
if (message.ruleId) {
const link = includeDocs && getDocsMap().get(message.ruleId);
text += link ? ` ([${message.ruleId}](${link}))` : ` (${message.ruleId})`;
}
return {
type: "error",
id: message.ruleId || "",
code: 0,
text,
start,
length: end - start,
level: message.severity === 2 ? "error" : "warning",
filename
};
});
let merged = [];
if (mergeMessages) {
for (const current of raws) {
const existing = merged.find((r) => r.start === current.start && r.length === current.length);
if (existing) {
existing.text += `
${current.text}`;
continue;
}
merged.push(current);
}
} else {
merged = raws;
}
const nodes = twoslashProtocol.resolveNodePositions(merged, code).filter((i) => i.line < pc.lines.length);
const results = {
code,
nodes
};
return results;
};
}
exports.createTwoslasher = createTwoslasher;
;