UNPKG

eslint-plugin-sort-export-all

Version:
195 lines (189 loc) 5.21 kB
import naturalCompare from 'natural-compare'; const name = "eslint-plugin-sort-export-all"; const version = "2.1.0"; const hasDocs = /* @__PURE__ */ new Set(["default-import-name"]); const blobUrl = "https://github.com/nirtamir2/eslint-plugin-sort-export-all/blob/main/src/rules/"; function RuleCreator(urlCreator) { return function createNamedRule({ name, meta, ...rule }) { return createRule({ meta: { ...meta, docs: { ...meta.docs, url: urlCreator(name) } }, ...rule }); }; } function createRule({ create, defaultOptions, meta }) { return { create: (context) => { const optionsWithDefault = context.options.map((options, index) => { return { ...defaultOptions[index], ...options }; }); return create(context, optionsWithDefault); }, defaultOptions, meta }; } const createEslintRule = RuleCreator( (ruleName) => hasDocs.has(ruleName) ? `${blobUrl}${ruleName}.md` : `${blobUrl}${ruleName}.test.ts` ); const isValidOrders = { asc(a, b) { return a <= b; }, ascI(a, b) { return a.toLowerCase() <= b.toLowerCase(); }, ascN(a, b) { return naturalCompare(a, b) <= 0; }, ascIN(a, b) { return naturalCompare(a.toLowerCase(), b.toLowerCase()) <= 0; }, desc(a, b) { return isValidOrders.asc(b, a); }, descI(a, b) { return isValidOrders.ascI(b, a); }, descN(a, b) { return isValidOrders.ascN(b, a); }, descIN(a, b) { return isValidOrders.ascIN(b, a); } }; const RULE_NAME = "sort-export-all"; const sortExportAll = createEslintRule({ name: RULE_NAME, defaultOptions: [], meta: { type: "suggestion", fixable: "code", docs: { description: "require export * to be sorted", url: "https://github.com/nirtamir2/eslint-plugin-sort-export-all" }, messages: { unorderedSortExportAll: `"export * from '{{beforeName}}'" should occur before "export * from '{{afterName}}'".` }, schema: [ { type: "string", enum: ["asc", "desc"] }, { type: "object", properties: { caseSensitive: { type: "boolean" }, natural: { type: "boolean" } }, additionalProperties: false } ] }, create: (context) => { const order = context.options[0] === "desc" ? "desc" : "asc"; const options = context.options[1]; const insensitive = (options && options.caseSensitive) === false; const natural = Boolean(options && options.natural); const functionName = order + (insensitive ? "I" : "") + (natural ? "N" : ""); const isValidOrder = isValidOrders[functionName]; if (isValidOrder === null) { throw new Error("Invalid options"); } const nodes = []; return { ExportAllDeclaration: (node) => { if (node.type !== "ExportAllDeclaration") { return; } if ("exportKind" in node && node.exportKind === "type") { return; } nodes.push(node); }, "Program:exit": () => { const sortedNodes = nodes.toSorted((a, b) => { return isValidOrder(a.source.value, b.source.value) ? -1 : 1; }); for (const [index, sortedNode] of sortedNodes.entries()) { const node = nodes[index]; if (node == null) { continue; } if (node.source.value === sortedNode.source.value) { continue; } const beforeName = sortedNode.source.value; const afterName = node.source.value; if (isValidOrder(beforeName, afterName)) { context.report({ messageId: "unorderedSortExportAll", node: sortedNode, ...sortedNode.loc === null ? null : { loc: sortedNode.loc }, data: { beforeName, afterName }, fix(fixer) { if (node == null) return null; const fixes = []; const { sourceCode } = context; const moveExportAllDeclaration = (fromNode, toNode) => { const prevText = sourceCode.getText(fromNode); const thisComments = sourceCode.getCommentsBefore(fromNode); for (const thisComment of thisComments) { fixes.push( fixer.insertTextBefore( toNode, `${sourceCode.getText(thisComment)} ` ) ); fixes.push(fixer.remove(thisComment)); } fixes.push(fixer.replaceText(toNode, prevText)); }; moveExportAllDeclaration(node, sortedNode); moveExportAllDeclaration(sortedNode, node); return fixes; } }); } } } }; } }); const plugin = { meta: { name, version }, // @keep-sorted rules: { "sort-export-all": sortExportAll } }; export { name as n, plugin as p };