elearning/Frontend-Learner/node_modules/eslint-plugin-import-lite/dist/rules/first.mjs
2026-01-13 10:48:02 +07:00

101 lines
No EOL
4 KiB
JavaScript

import { a as createRule } from "../utils.mjs";
//#region src/rules/first/first.ts
function getImportValue(node) {
return node.type === "ImportDeclaration" ? node.source.value : "moduleReference" in node && "expression" in node.moduleReference && "value" in node.moduleReference.expression && node.moduleReference.expression.value;
}
function isPossibleDirective(node) {
return node.type === "ExpressionStatement" && node.expression.type === "Literal" && typeof node.expression.value === "string";
}
var first_default = createRule({
name: "first",
meta: {
type: "suggestion",
docs: { description: "Ensure all imports appear before other statements." },
fixable: "code",
schema: [{
type: "string",
enum: ["absolute-first", "disable-absolute-first"]
}],
messages: {
absolute: "Absolute imports should come before relative imports.",
order: "Import in body of module; reorder to top."
}
},
defaultOptions: [],
create(context, options) {
return { Program(n) {
const body = n.body;
if (!body?.length) return;
const absoluteFirst = options[0] === "absolute-first";
const { sourceCode } = context;
const originSourceCode = sourceCode.getText();
let nonImportCount = 0;
let anyExpressions = false;
let anyRelative = false;
let lastLegalImp = null;
const errorInfos = [];
let shouldSort = true;
let lastSortNodesIndex = 0;
for (const [index, node] of body.entries()) {
if (!anyExpressions && isPossibleDirective(node)) continue;
anyExpressions = true;
if (node.type === "ImportDeclaration" || node.type === "TSImportEqualsDeclaration") {
if (absoluteFirst) {
const importValue = getImportValue(node);
if (typeof importValue === "string" && /^\./.test(importValue)) anyRelative = true;
else if (anyRelative) context.report({
node: node.type === "ImportDeclaration" ? node.source : node.moduleReference,
messageId: "absolute"
});
}
if (nonImportCount > 0) {
/** @see https://eslint.org/docs/next/use/migrate-to-9.0.0#-removed-multiple-context-methods */
for (const variable of sourceCode.getDeclaredVariables(node)) {
if (!shouldSort) break;
for (const reference of variable.references) if (reference.identifier.range[0] < node.range[1]) {
shouldSort = false;
break;
}
}
if (shouldSort) lastSortNodesIndex = errorInfos.length;
errorInfos.push({
node,
range: [body[index - 1].range[1], node.range[1]]
});
} else lastLegalImp = node;
} else nonImportCount++;
}
if (errorInfos.length === 0) return;
for (const [index, { node }] of errorInfos.entries()) {
let fix;
if (index < lastSortNodesIndex) fix = (fixer) => fixer.insertTextAfter(node, "");
else if (index === lastSortNodesIndex) {
const sortNodes = errorInfos.slice(0, lastSortNodesIndex + 1);
fix = (fixer) => {
const removeFixers = sortNodes.map(({ range: range$1 }) => fixer.removeRange(range$1));
const range = [0, removeFixers[removeFixers.length - 1].range[1]];
let insertSourceCode = sortNodes.map(({ range: range$1 }) => {
const nodeSourceCode = originSourceCode.slice(...range$1);
if (/\S/.test(nodeSourceCode[0])) return `\n${nodeSourceCode}`;
return nodeSourceCode;
}).join("");
let replaceSourceCode = "";
if (!lastLegalImp) insertSourceCode = insertSourceCode.trim() + insertSourceCode.match(/^(\s+)/)[0];
const fixers = [lastLegalImp ? fixer.insertTextAfter(lastLegalImp, insertSourceCode) : fixer.insertTextBefore(body[0], insertSourceCode), ...removeFixers];
for (const [i, computedFixer] of fixers.entries()) replaceSourceCode += originSourceCode.slice(fixers[i - 1] ? fixers[i - 1].range[1] : 0, computedFixer.range[0]) + computedFixer.text;
return fixer.replaceTextRange(range, replaceSourceCode);
};
}
context.report({
node,
messageId: "order",
fix
});
}
} };
}
});
//#endregion
export { first_default as t };