Files
SnowLuma/.pnpm-store/v11/files/ad/e3a14075bebdfb39560f9c59cf6d07259b5fb701ff329c271deb4b6147f0716c1d9012dff56d667d8fbdc60645099926b8f3de240cccca8698ae99b177ea75
T
TanTan 2a69b23b47
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

254 lines
9.9 KiB
Plaintext

import { f as createRule, g as import_ast_utils, m as AST_NODE_TYPES } from "../utils.js";
var object_curly_spacing_default = createRule({
name: "object-curly-spacing",
meta: {
type: "layout",
docs: { description: "Enforce consistent spacing inside braces" },
fixable: "whitespace",
schema: [{
type: "string",
enum: ["always", "never"]
}, {
type: "object",
properties: {
arraysInObjects: { type: "boolean" },
objectsInObjects: { type: "boolean" },
overrides: {
type: "object",
properties: Object.fromEntries([
"ObjectPattern",
"ObjectExpression",
"ImportDeclaration",
"ImportAttributes",
"ExportNamedDeclaration",
"ExportAllDeclaration",
"TSMappedType",
"TSTypeLiteral",
"TSInterfaceBody",
"TSEnumBody"
].map((node) => [node, {
type: "string",
enum: ["always", "never"]
}])),
additionalProperties: false
},
emptyObjects: {
type: "string",
enum: [
"ignore",
"always",
"never"
]
}
},
additionalProperties: false
}],
defaultOptions: ["never"],
messages: {
requireSpaceBefore: "A space is required before '{{token}}'.",
requireSpaceAfter: "A space is required after '{{token}}'.",
unexpectedSpaceBefore: "There should be no space before '{{token}}'.",
unexpectedSpaceAfter: "There should be no space after '{{token}}'.",
requiredSpaceInEmptyObject: "A space is required in empty '{{node}}'.",
unexpectedSpaceInEmptyObject: "There should be no space in empty '{{node}}'."
}
},
create(context, [firstOption, secondOption]) {
const spaced = firstOption === "always";
const sourceCode = context.sourceCode;
function isOptionSet(option) {
return secondOption ? secondOption[option] === !spaced : false;
}
const options = {
spaced,
arraysInObjectsException: isOptionSet("arraysInObjects"),
objectsInObjectsException: isOptionSet("objectsInObjects"),
overrides: secondOption?.overrides ?? {},
emptyObjects: secondOption?.emptyObjects ?? "ignore"
};
function reportNoBeginningSpace(node, token) {
const nextToken = sourceCode.getTokenAfter(token, { includeComments: true });
context.report({
node,
loc: {
start: token.loc.end,
end: nextToken.loc.start
},
messageId: "unexpectedSpaceAfter",
data: { token: token.value },
fix(fixer) {
return fixer.removeRange([token.range[1], nextToken.range[0]]);
}
});
}
function reportNoEndingSpace(node, token) {
const previousToken = sourceCode.getTokenBefore(token, { includeComments: true });
context.report({
node,
loc: {
start: previousToken.loc.end,
end: token.loc.start
},
messageId: "unexpectedSpaceBefore",
data: { token: token.value },
fix(fixer) {
return fixer.removeRange([previousToken.range[1], token.range[0]]);
}
});
}
function reportRequiredBeginningSpace(node, token) {
context.report({
node,
loc: token.loc,
messageId: "requireSpaceAfter",
data: { token: token.value },
fix(fixer) {
return fixer.insertTextAfter(token, " ");
}
});
}
function reportRequiredEndingSpace(node, token) {
context.report({
node,
loc: token.loc,
messageId: "requireSpaceBefore",
data: { token: token.value },
fix(fixer) {
return fixer.insertTextBefore(token, " ");
}
});
}
function validateBraceSpacing(node, openingToken, closingToken, nodeType = node.type) {
const tokenAfterOpening = sourceCode.getTokenAfter(openingToken, { includeComments: true });
const spaced = options.overrides[nodeType] ? options.overrides[nodeType] === "always" : options.spaced;
if ((0, import_ast_utils.isTokenOnSameLine)(openingToken, tokenAfterOpening)) {
const firstSpaced = sourceCode.isSpaceBetween(openingToken, tokenAfterOpening);
const secondType = sourceCode.getNodeByRangeIndex(tokenAfterOpening.range[0]).type;
const openingCurlyBraceMustBeSpaced = options.arraysInObjectsException && [AST_NODE_TYPES.TSMappedType, AST_NODE_TYPES.TSIndexSignature].includes(secondType) ? !spaced : spaced;
if (openingCurlyBraceMustBeSpaced && !firstSpaced) reportRequiredBeginningSpace(node, openingToken);
if (!openingCurlyBraceMustBeSpaced && firstSpaced && !((0, import_ast_utils.isCommentToken)(tokenAfterOpening) && !(0, import_ast_utils.isTokenOnSameLine)(openingToken, closingToken))) reportNoBeginningSpace(node, openingToken);
}
const tokenBeforeClosing = sourceCode.getTokenBefore(closingToken, { includeComments: true });
if ((0, import_ast_utils.isTokenOnSameLine)(tokenBeforeClosing, closingToken)) {
const penultimateType = options.arraysInObjectsException && (0, import_ast_utils.isClosingBracketToken)(tokenBeforeClosing) || options.objectsInObjectsException && (0, import_ast_utils.isClosingBraceToken)(tokenBeforeClosing) ? sourceCode.getNodeByRangeIndex(tokenBeforeClosing.range[0]).type : void 0;
const closingCurlyBraceMustBeSpaced = options.arraysInObjectsException && [AST_NODE_TYPES.ArrayExpression, AST_NODE_TYPES.TSTupleType].includes(penultimateType) || options.objectsInObjectsException && penultimateType !== void 0 && [
AST_NODE_TYPES.ObjectExpression,
AST_NODE_TYPES.ObjectPattern,
AST_NODE_TYPES.TSMappedType,
AST_NODE_TYPES.TSTypeLiteral
].includes(penultimateType) ? !spaced : spaced;
const lastSpaced = sourceCode.isSpaceBetween(tokenBeforeClosing, closingToken);
if (closingCurlyBraceMustBeSpaced && !lastSpaced) reportRequiredEndingSpace(node, closingToken);
if (!closingCurlyBraceMustBeSpaced && lastSpaced) reportNoEndingSpace(node, closingToken);
}
}
function checkSpaceInEmptyObjectLike(node, openingToken, closingToken, nodeType = node.type) {
if (options.emptyObjects === "ignore" || !(0, import_ast_utils.isTokenOnSameLine)(openingToken, closingToken) || sourceCode.commentsExistBetween(openingToken, closingToken)) return;
const sourceBetween = sourceCode.getText().slice(openingToken.range[0] + 1, closingToken.range[1] - 1);
if (sourceBetween.trim() !== "") return;
if (options.emptyObjects === "always") {
if (sourceBetween === " ") return;
context.report({
node,
loc: {
start: openingToken.loc.end,
end: closingToken.loc.start
},
messageId: "requiredSpaceInEmptyObject",
data: { node: nodeType },
fix(fixer) {
return fixer.replaceTextRange([openingToken.range[1], closingToken.range[0]], " ");
}
});
} else if (options.emptyObjects === "never") {
if (sourceBetween === "") return;
context.report({
node,
loc: {
start: openingToken.loc.end,
end: closingToken.loc.start
},
messageId: "unexpectedSpaceInEmptyObject",
data: { node: nodeType },
fix(fixer) {
return fixer.removeRange([openingToken.range[1], closingToken.range[0]]);
}
});
}
}
function getBraceToken(node, nodeType = node.type) {
switch (nodeType) {
case "ImportDeclaration":
case "ExportNamedDeclaration":
case "ExportAllDeclaration": {
const attrTokens = sourceCode.getTokens(node);
return [attrTokens.find((token) => (0, import_ast_utils.isOpeningBraceToken)(token)), attrTokens.find((token) => (0, import_ast_utils.isClosingBraceToken)(token))];
}
case "ImportAttributes": {
const attrTokens = sourceCode.getTokens(node);
const openingAttrToken = attrTokens.findLast((token) => (0, import_ast_utils.isOpeningBraceToken)(token));
const closingAttrToken = attrTokens.findLast((token) => (0, import_ast_utils.isClosingBraceToken)(token));
if (!openingAttrToken || !closingAttrToken || !node.source || openingAttrToken.range[0] < node.source.range[0]) return [null, null];
return [openingAttrToken, closingAttrToken];
}
case "ObjectPattern":
case "ObjectExpression":
case "TSMappedType":
case "TSTypeLiteral":
case "TSInterfaceBody":
case "TSEnumBody": {
const allTokens = sourceCode.getTokens(node);
return [allTokens.find((token) => (0, import_ast_utils.isOpeningBraceToken)(token)), node.type === "ObjectPattern" && node.typeAnnotation ? sourceCode.getTokenBefore(node.typeAnnotation) : allTokens.findLast((token) => (0, import_ast_utils.isClosingBraceToken)(token))];
}
default: throw new Error(`Unsupported node type: ${nodeType}`);
}
}
function checkForObjectLike(node, properties, nodeType = node.type) {
const [openingToken, closingToken] = getBraceToken(node, nodeType);
if (!openingToken || !closingToken) return;
if (properties.length === 0) {
checkSpaceInEmptyObjectLike(node, openingToken, closingToken, nodeType);
return;
}
validateBraceSpacing(node, openingToken, closingToken, nodeType);
}
return {
ObjectPattern(node) {
checkForObjectLike(node, node.properties);
},
ObjectExpression(node) {
checkForObjectLike(node, node.properties);
},
ImportDeclaration(node) {
if (node.attributes) checkForObjectLike(node, node.attributes, "ImportAttributes");
const firstSpecifierIndex = node.specifiers.findIndex((specifier) => specifier.type === "ImportSpecifier");
if (firstSpecifierIndex === -1) {
checkForObjectLike(node, []);
return;
}
checkForObjectLike(node, node.specifiers.slice(firstSpecifierIndex));
},
ExportNamedDeclaration(node) {
checkForObjectLike(node, node.specifiers);
if (node.attributes) checkForObjectLike(node, node.attributes, "ImportAttributes");
},
ExportAllDeclaration(node) {
if (node.attributes) checkForObjectLike(node, node.attributes, "ImportAttributes");
},
TSMappedType(node) {
validateBraceSpacing(node, sourceCode.getFirstToken(node), sourceCode.getLastToken(node));
},
TSTypeLiteral(node) {
checkForObjectLike(node, node.members);
},
TSInterfaceBody(node) {
checkForObjectLike(node, node.body);
},
TSEnumBody(node) {
checkForObjectLike(node, node.members);
}
};
}
});
export { object_curly_spacing_default as t };