UEA-Prodem

This commit is contained in:
2026-06-10 12:38:42 -03:00
parent 3f33154e16
commit c41625e542
9352 changed files with 1128292 additions and 14752 deletions
@@ -0,0 +1,10 @@
type Options = [
{
allowReturnAny?: boolean;
}
];
type MessageId = `asyncFunc` | `nonVoidFunc` | `nonVoidReturn`;
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageId, Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
name: string;
};
export default _default;
@@ -0,0 +1,377 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const tsutils = __importStar(require("ts-api-utils"));
const ts = __importStar(require("typescript"));
const util = __importStar(require("../util"));
exports.default = util.createRule({
name: 'strict-void-return',
meta: {
type: 'problem',
docs: {
description: 'Disallow passing a value-returning function in a position accepting a void function',
requiresTypeChecking: true,
},
messages: {
asyncFunc: 'Async function used in a context where a void function is expected.',
nonVoidFunc: 'Value-returning function used in a context where a void function is expected.',
nonVoidReturn: 'Value returned in a context where a void return is expected.',
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
allowReturnAny: {
type: 'boolean',
description: 'Whether to allow functions returning `any` to be used in place expecting a `void` function.',
},
},
},
],
},
defaultOptions: [
{
allowReturnAny: false,
},
],
create(context, [options]) {
const sourceCode = context.sourceCode;
const parserServices = util.getParserServices(context);
const checker = parserServices.program.getTypeChecker();
return {
ArrayExpression: (node) => {
for (const elemNode of node.elements) {
if (elemNode != null &&
elemNode.type !== utils_1.AST_NODE_TYPES.SpreadElement) {
checkExpressionNode(elemNode);
}
}
},
ArrowFunctionExpression: (node) => {
if (node.body.type !== utils_1.AST_NODE_TYPES.BlockStatement) {
checkExpressionNode(node.body);
}
},
AssignmentExpression: (node) => {
checkExpressionNode(node.right); // should ignore operators like `+=` or `-=` automatically
},
'CallExpression, NewExpression': checkFunctionCallNode,
JSXAttribute: (node) => {
if (node.value?.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer &&
node.value.expression.type !== utils_1.AST_NODE_TYPES.JSXEmptyExpression) {
checkExpressionNode(node.value.expression);
}
},
MethodDefinition: checkClassMethodNode,
ObjectExpression: (node) => {
for (const propNode of node.properties) {
if (propNode.type !== utils_1.AST_NODE_TYPES.SpreadElement) {
checkObjectPropertyNode(propNode);
}
}
},
PropertyDefinition: checkClassPropertyNode,
ReturnStatement: (node) => {
if (node.argument != null) {
checkExpressionNode(node.argument);
}
},
VariableDeclarator: (node) => {
if (node.init != null) {
checkExpressionNode(node.init);
}
},
};
function isVoidReturningFunctionType(type) {
const returnTypes = tsutils
.getCallSignaturesOfType(type)
.flatMap(signature => tsutils.unionConstituents(signature.getReturnType()));
return (returnTypes.length > 0 &&
returnTypes.every(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.Void)));
}
/**
* Finds errors in any expression node.
*
* Compares the type of the node against the contextual (expected) type.
*
* @returns `true` if the expected type was void function.
*/
function checkExpressionNode(node) {
const expectedType = parserServices.getContextualType(node);
if (expectedType != null && isVoidReturningFunctionType(expectedType)) {
reportIfNonVoidFunction(node);
return true;
}
return false;
}
/**
* Finds errors in function calls.
*
* When checking arguments, we also manually figure out the argument types
* by iterating over all the function signatures.
* Thanks to this, we can find arguments like `(() => void) | (() => any)`
* and treat them as void too.
* This is done to also support checking functions like `addEventListener`
* which have overloads where one callback returns any.
*
* Implementation mostly based on no-misused-promises,
* which does this to find `(() => void) | (() => NotThenable)`
* and report them too.
*/
function checkFunctionCallNode(callNode) {
if (callNode.arguments.length === 0) {
return;
}
const callTsNode = parserServices.esTreeNodeToTSNodeMap.get(callNode);
const funcType = checker.getTypeAtLocation(callTsNode.expression);
const funcSignatures = tsutils
.unionConstituents(funcType)
.flatMap(type => ts.isCallExpression(callTsNode)
? type.getCallSignatures()
: type.getConstructSignatures());
for (const [argIdx, argNode] of callNode.arguments.entries()) {
if (argNode.type === utils_1.AST_NODE_TYPES.SpreadElement) {
continue;
}
// Collect the types from all of the call signatures
const argExpectedReturnTypes = funcSignatures
.map(s => s.parameters[argIdx])
.filter(Boolean)
.map(param => checker.getTypeOfSymbolAtLocation(param, callTsNode.expression))
.flatMap(paramType => tsutils.unionConstituents(paramType))
.flatMap(paramType => paramType.getCallSignatures())
.map(paramSignature => paramSignature.getReturnType());
const hasSingleSignature = funcSignatures.length === 1;
const allSignaturesReturnVoid = argExpectedReturnTypes.every(type => isVoid(type) ||
// Treat as void even though it might be technically any.
isNullishOrAny(type) ||
// `getTypeOfSymbolAtLocation` returns unresolved type parameters
// (e.g. `T`), even for overloads that match the call.
//
// Since we can't tell whether a generic overload currently matches,
// we treat TypeParameters similar to void.
tsutils.isTypeParameter(type));
// Check against the contextual type first, but only when there is a
// single signature or when all signatures return void, because
// `getContextualType` resolves to the first overload's return type even
// though there may be another one that matches the call.
if ((hasSingleSignature || allSignaturesReturnVoid) &&
checkExpressionNode(argNode)) {
continue;
}
if (
// At least one return type is void
argExpectedReturnTypes.some(isVoid) &&
// The rest are nullish or any
argExpectedReturnTypes.every(isNullishOrAny)) {
// We treat this argument as void even though it might be technically any.
reportIfNonVoidFunction(argNode);
}
}
}
function isNullishOrAny(type) {
return tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike |
ts.TypeFlags.Undefined |
ts.TypeFlags.Null |
ts.TypeFlags.Any |
ts.TypeFlags.Never);
}
function isVoid(type) {
return tsutils.isTypeFlagSet(type, ts.TypeFlags.Void);
}
/**
* Finds errors in an object property.
*
* Object properties require different logic
* when the property is a method shorthand.
*/
function checkObjectPropertyNode(propNode) {
const valueNode = propNode.value;
const propTsNode = parserServices.esTreeNodeToTSNodeMap.get(propNode);
if (propTsNode.kind === ts.SyntaxKind.MethodDeclaration) {
// Object property is a method shorthand.
if (propTsNode.name.kind === ts.SyntaxKind.ComputedPropertyName) {
// Don't check object methods with computed name.
return;
}
const objType = parserServices.getContextualType(propNode.parent);
if (objType == null) {
// Expected object type is unknown.
return;
}
const propSymbol = checker.getPropertyOfType(objType, propTsNode.name.text);
if (propSymbol == null) {
// Expected object type is known, but it doesn't have this method.
return;
}
const propExpectedType = checker.getTypeOfSymbolAtLocation(propSymbol, propTsNode);
if (isVoidReturningFunctionType(propExpectedType)) {
reportIfNonVoidFunction(valueNode);
}
return;
}
// Object property is a regular property.
checkExpressionNode(valueNode);
}
/**
* Finds errors in a class property.
*
* In addition to the regular check against the contextual type,
* we also check against the base class property (when the class extends another class)
* and the implemented interfaces (when the class implements an interface).
*/
function checkClassPropertyNode(propNode) {
if (propNode.value == null) {
return;
}
// Check in comparison to the base types.
for (const { baseMemberType } of util.getBaseTypesOfClassMember(parserServices, propNode)) {
if (isVoidReturningFunctionType(baseMemberType)) {
reportIfNonVoidFunction(propNode.value);
return; // Report at most one error.
}
}
// Check in comparison to the contextual type.
checkExpressionNode(propNode.value);
}
/**
* Finds errors in a class method.
*
* We check against the base class method (when the class extends another class)
* and the implemented interfaces (when the class implements an interface).
*/
function checkClassMethodNode(methodNode) {
if (methodNode.value.type === utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression) {
return;
}
// Check in comparison to the base types.
for (const { baseMemberType } of util.getBaseTypesOfClassMember(parserServices, methodNode)) {
if (isVoidReturningFunctionType(baseMemberType)) {
reportIfNonVoidFunction(methodNode.value);
return; // Report at most one error.
}
}
}
/**
* Reports an error if the provided node is not allowed in a void function context.
*/
function reportIfNonVoidFunction(funcNode) {
const allowedReturnType = ts.TypeFlags.Void |
ts.TypeFlags.Never |
ts.TypeFlags.Undefined |
(options.allowReturnAny ? ts.TypeFlags.Any : 0);
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(funcNode);
const actualType = checker.getApparentType(checker.getTypeAtLocation(tsNode));
if (tsutils
.getCallSignaturesOfType(actualType)
.map(signature => signature.getReturnType())
.flatMap(returnType => tsutils.unionConstituents(returnType))
.every(type => tsutils.isTypeFlagSet(type, allowedReturnType))) {
// The function is already void.
return;
}
if (funcNode.type !== utils_1.AST_NODE_TYPES.ArrowFunctionExpression &&
funcNode.type !== utils_1.AST_NODE_TYPES.FunctionExpression) {
// The provided function is not a function literal.
// Report a generic error.
return context.report({
node: funcNode,
messageId: `nonVoidFunc`,
});
}
// The provided function is a function literal.
if (funcNode.generator) {
// The provided function is a generator function.
// Generator functions are not allowed.
return context.report({
loc: util.getFunctionHeadLoc(funcNode, sourceCode),
messageId: `nonVoidFunc`,
});
}
if (funcNode.async) {
// The provided function is an async function.
// Async functions aren't allowed.
return context.report({
loc: util.getFunctionHeadLoc(funcNode, sourceCode),
messageId: `asyncFunc`,
});
}
if (funcNode.body.type !== utils_1.AST_NODE_TYPES.BlockStatement) {
// The provided function is an arrow function shorthand without braces.
return context.report({
node: funcNode.body,
messageId: `nonVoidReturn`,
});
}
// The function is a regular or arrow function with a block body.
// Check return type annotation.
if (funcNode.returnType != null) {
// The provided function has an explicit return type annotation.
const typeAnnotationNode = funcNode.returnType.typeAnnotation;
if (typeAnnotationNode.type !== utils_1.AST_NODE_TYPES.TSVoidKeyword) {
// The explicit return type is not `void`.
return context.report({
node: typeAnnotationNode,
messageId: `nonVoidFunc`,
});
}
}
// Iterate over all function's return statements.
for (const statement of util.walkStatements(funcNode.body.body)) {
if (statement.type !== utils_1.AST_NODE_TYPES.ReturnStatement ||
statement.argument == null) {
// We only care about return statements with a value.
continue;
}
const returnType = checker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(statement.argument));
if (tsutils.isTypeFlagSet(returnType, allowedReturnType)) {
// Only visit return statements with invalid type.
continue;
}
// This return statement causes the non-void return type.
const returnKeyword = util.nullThrows(sourceCode.getFirstToken(statement, {
filter: token => token.value === 'return',
}), util.NullThrowsReasons.MissingToken('return keyword', statement.type));
context.report({
node: returnKeyword,
messageId: `nonVoidReturn`,
});
}
// No invalid returns found. The function is allowed.
}
},
});
@@ -0,0 +1,11 @@
import type { TSESTree, ParserServicesWithTypeInformation } from '@typescript-eslint/utils';
import type * as ts from 'typescript';
/**
* Given a member of a class which extends another class or implements an interface,
* yields the corresponding member type for each of the base class/interfaces.
*/
export declare function getBaseTypesOfClassMember(services: ParserServicesWithTypeInformation, memberNode: TSESTree.MethodDefinition | TSESTree.PropertyDefinition): Generator<{
baseType: ts.Type;
baseMemberType: ts.Type;
heritageToken: ts.SyntaxKind.ExtendsKeyword | ts.SyntaxKind.ImplementsKeyword;
}>;
@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBaseTypesOfClassMember = getBaseTypesOfClassMember;
/**
* Given a member of a class which extends another class or implements an interface,
* yields the corresponding member type for each of the base class/interfaces.
*/
function* getBaseTypesOfClassMember(services, memberNode) {
const memberTsNode = services.esTreeNodeToTSNodeMap.get(memberNode);
if (memberTsNode.name == null) {
return;
}
const checker = services.program.getTypeChecker();
const memberSymbol = checker.getSymbolAtLocation(memberTsNode.name);
if (memberSymbol == null) {
return;
}
const classNode = memberTsNode.parent;
for (const clauseNode of classNode.heritageClauses ?? []) {
for (const baseTypeNode of clauseNode.types) {
const baseType = checker.getTypeAtLocation(baseTypeNode);
const baseMemberSymbol = checker.getPropertyOfType(baseType, memberSymbol.name);
if (baseMemberSymbol == null) {
continue;
}
const baseMemberType = checker.getTypeOfSymbolAtLocation(baseMemberSymbol, memberTsNode);
const heritageToken = clauseNode.token;
yield { baseMemberType, baseType, heritageToken };
}
}
}
@@ -0,0 +1,5 @@
import type { TSESTree } from '@typescript-eslint/utils';
/**
* Recursively checks whether a given reference is used in a type predicate (e.g., `arg is string`)
*/
export declare function referenceContainsTypePredicate(node: TSESTree.Node): boolean;
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.referenceContainsTypePredicate = referenceContainsTypePredicate;
const utils_1 = require("@typescript-eslint/utils");
/**
* Recursively checks whether a given reference is used in a type predicate (e.g., `arg is string`)
*/
function referenceContainsTypePredicate(node) {
switch (node.type) {
case utils_1.AST_NODE_TYPES.TSTypePredicate:
return true;
case utils_1.AST_NODE_TYPES.TSQualifiedName:
case utils_1.AST_NODE_TYPES.Identifier:
return referenceContainsTypePredicate(node.parent);
default:
return false;
}
}
@@ -0,0 +1,7 @@
import type { TSESTree } from '@typescript-eslint/utils';
/**
* Yields all statement nodes in a block, including nested blocks.
*
* You can use it to find all return statements in a function body.
*/
export declare function walkStatements(body: readonly TSESTree.Statement[]): Generator<TSESTree.Statement>;
@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.walkStatements = walkStatements;
const utils_1 = require("@typescript-eslint/utils");
/**
* Yields all statement nodes in a block, including nested blocks.
*
* You can use it to find all return statements in a function body.
*/
function* walkStatements(body) {
for (const statement of body) {
switch (statement.type) {
case utils_1.AST_NODE_TYPES.BlockStatement: {
yield* walkStatements(statement.body);
continue;
}
case utils_1.AST_NODE_TYPES.SwitchStatement: {
for (const switchCase of statement.cases) {
yield* walkStatements(switchCase.consequent);
}
continue;
}
case utils_1.AST_NODE_TYPES.IfStatement: {
yield* walkStatements([statement.consequent]);
if (statement.alternate) {
yield* walkStatements([statement.alternate]);
}
continue;
}
case utils_1.AST_NODE_TYPES.WhileStatement:
case utils_1.AST_NODE_TYPES.DoWhileStatement:
case utils_1.AST_NODE_TYPES.ForStatement:
case utils_1.AST_NODE_TYPES.ForInStatement:
case utils_1.AST_NODE_TYPES.ForOfStatement:
case utils_1.AST_NODE_TYPES.WithStatement:
case utils_1.AST_NODE_TYPES.LabeledStatement: {
yield* walkStatements([statement.body]);
continue;
}
case utils_1.AST_NODE_TYPES.TryStatement: {
yield* walkStatements([statement.block]);
if (statement.handler) {
yield* walkStatements([statement.handler.body]);
}
if (statement.finalizer) {
yield* walkStatements([statement.finalizer]);
}
continue;
}
default: {
yield statement;
continue;
}
}
}
}
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2025_collection: LibDefinition;
@@ -0,0 +1,17 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.es2025_collection = void 0;
const base_config_1 = require("./base-config");
const es2024_collection_1 = require("./es2024.collection");
exports.es2025_collection = {
libs: [es2024_collection_1.es2024_collection],
variables: [
['ReadonlySetLike', base_config_1.TYPE],
['Set', base_config_1.TYPE],
['ReadonlySet', base_config_1.TYPE],
],
};
+2
View File
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2025: LibDefinition;
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2025_float16: LibDefinition;
@@ -0,0 +1,19 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.es2025_float16 = void 0;
const base_config_1 = require("./base-config");
const es2015_iterable_1 = require("./es2015.iterable");
const es2015_symbol_1 = require("./es2015.symbol");
exports.es2025_float16 = {
libs: [es2015_symbol_1.es2015_symbol, es2015_iterable_1.es2015_iterable],
variables: [
['Float16Array', base_config_1.TYPE_VALUE],
['Float16ArrayConstructor', base_config_1.TYPE],
['Math', base_config_1.TYPE],
['DataView', base_config_1.TYPE],
],
};
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2025_full: LibDefinition;
+24
View File
@@ -0,0 +1,24 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.es2025_full = void 0;
const dom_1 = require("./dom");
const dom_asynciterable_1 = require("./dom.asynciterable");
const dom_iterable_1 = require("./dom.iterable");
const es2025_1 = require("./es2025");
const scripthost_1 = require("./scripthost");
const webworker_importscripts_1 = require("./webworker.importscripts");
exports.es2025_full = {
libs: [
es2025_1.es2025,
dom_1.dom,
webworker_importscripts_1.webworker_importscripts,
scripthost_1.scripthost,
dom_iterable_1.dom_iterable,
dom_asynciterable_1.dom_asynciterable,
],
variables: [],
};
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2025_intl: LibDefinition;
+13
View File
@@ -0,0 +1,13 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.es2025_intl = void 0;
const base_config_1 = require("./base-config");
const es2018_intl_1 = require("./es2018.intl");
exports.es2025_intl = {
libs: [es2018_intl_1.es2018_intl],
variables: [['Intl', base_config_1.TYPE_VALUE]],
};
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2025_iterator: LibDefinition;
@@ -0,0 +1,16 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.es2025_iterator = void 0;
const base_config_1 = require("./base-config");
const es2015_iterable_1 = require("./es2015.iterable");
exports.es2025_iterator = {
libs: [es2015_iterable_1.es2015_iterable],
variables: [
['Iterator', base_config_1.TYPE_VALUE],
['IteratorObjectConstructor', base_config_1.TYPE],
],
};
+26
View File
@@ -0,0 +1,26 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.es2025 = void 0;
const es2024_1 = require("./es2024");
const es2025_collection_1 = require("./es2025.collection");
const es2025_float16_1 = require("./es2025.float16");
const es2025_intl_1 = require("./es2025.intl");
const es2025_iterator_1 = require("./es2025.iterator");
const es2025_promise_1 = require("./es2025.promise");
const es2025_regexp_1 = require("./es2025.regexp");
exports.es2025 = {
libs: [
es2024_1.es2024,
es2025_collection_1.es2025_collection,
es2025_float16_1.es2025_float16,
es2025_intl_1.es2025_intl,
es2025_iterator_1.es2025_iterator,
es2025_promise_1.es2025_promise,
es2025_regexp_1.es2025_regexp,
],
variables: [],
};
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2025_promise: LibDefinition;
@@ -0,0 +1,12 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.es2025_promise = void 0;
const base_config_1 = require("./base-config");
exports.es2025_promise = {
libs: [],
variables: [['PromiseConstructor', base_config_1.TYPE]],
};
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2025_regexp: LibDefinition;
@@ -0,0 +1,12 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.es2025_regexp = void 0;
const base_config_1 = require("./base-config");
exports.es2025_regexp = {
libs: [],
variables: [['RegExpConstructor', base_config_1.TYPE]],
};
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const esnext_date: LibDefinition;
+13
View File
@@ -0,0 +1,13 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.esnext_date = void 0;
const base_config_1 = require("./base-config");
const esnext_temporal_1 = require("./esnext.temporal");
exports.esnext_date = {
libs: [esnext_temporal_1.esnext_temporal],
variables: [['Date', base_config_1.TYPE]],
};
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const esnext_temporal: LibDefinition;
@@ -0,0 +1,15 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.esnext_temporal = void 0;
const base_config_1 = require("./base-config");
const es2015_symbol_wellknown_1 = require("./es2015.symbol.wellknown");
const es2020_intl_1 = require("./es2020.intl");
const es2025_intl_1 = require("./es2025.intl");
exports.esnext_temporal = {
libs: [es2015_symbol_wellknown_1.es2015_symbol_wellknown, es2020_intl_1.es2020_intl, es2025_intl_1.es2025_intl],
variables: [['Temporal', base_config_1.TYPE_VALUE]],
};
@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const esnext_typedarrays: LibDefinition;
@@ -0,0 +1,15 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
// npx nx generate-lib repo
Object.defineProperty(exports, "__esModule", { value: true });
exports.esnext_typedarrays = void 0;
const base_config_1 = require("./base-config");
exports.esnext_typedarrays = {
libs: [],
variables: [
['Uint8Array', base_config_1.TYPE],
['Uint8ArrayConstructor', base_config_1.TYPE],
],
};
@@ -0,0 +1,23 @@
(MIT)
Original code Copyright Julian Gruber <julian@juliangruber.com>
Port to TypeScript Copyright Isaac Z. Schlueter <i@izs.me>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,57 @@
# balanced-match
Match balanced string pairs, like `{` and `}` or `<b>` and
`</b>`. Supports regular expressions as well!
## Example
Get the first matching pair of braces:
```js
import { balanced } from 'balanced-match'
console.log(balanced('{', '}', 'pre{in{nested}}post'))
console.log(balanced('{', '}', 'pre{first}between{second}post'))
console.log(
balanced(/\s+\{\s+/, /\s+\}\s+/, 'pre { in{nest} } post'),
)
```
The matches are:
```bash
$ node example.js
{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' }
{ start: 3,
end: 9,
pre: 'pre',
body: 'first',
post: 'between{second}post' }
{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' }
```
## API
### const m = balanced(a, b, str)
For the first non-nested matching pair of `a` and `b` in `str`, return an
object with those keys:
- **start** the index of the first match of `a`
- **end** the index of the matching `b`
- **pre** the preamble, `a` and `b` not included
- **body** the match, `a` and `b` not included
- **post** the postscript, `a` and `b` not included
If there's no match, `undefined` will be returned.
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`.
### const r = balanced.range(a, b, str)
For the first non-nested matching pair of `a` and `b` in `str`, return an
array with indexes: `[ <a index>, <b index> ]`.
If there's no match, `undefined` will be returned.
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`.
@@ -0,0 +1,9 @@
export declare const balanced: (a: string | RegExp, b: string | RegExp, str: string) => false | {
start: number;
end: number;
pre: string;
body: string;
post: string;
} | undefined;
export declare const range: (a: string, b: string, str: string) => undefined | [number, number];
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,GACnB,GAAG,MAAM,GAAG,MAAM,EAClB,GAAG,MAAM,GAAG,MAAM,EAClB,KAAK,MAAM;;;;;;aAgBZ,CAAA;AAOD,eAAO,MAAM,KAAK,GAChB,GAAG,MAAM,EACT,GAAG,MAAM,EACT,KAAK,MAAM,KACV,SAAS,GAAG,CAAC,MAAM,EAAE,MAAM,CA2C7B,CAAA"}
@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.range = exports.balanced = void 0;
const balanced = (a, b, str) => {
const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
const mb = b instanceof RegExp ? maybeMatch(b, str) : b;
const r = ma !== null && mb != null && (0, exports.range)(ma, mb, str);
return (r && {
start: r[0],
end: r[1],
pre: str.slice(0, r[0]),
body: str.slice(r[0] + ma.length, r[1]),
post: str.slice(r[1] + mb.length),
});
};
exports.balanced = balanced;
const maybeMatch = (reg, str) => {
const m = str.match(reg);
return m ? m[0] : null;
};
const range = (a, b, str) => {
let begs, beg, left, right = undefined, result;
let ai = str.indexOf(a);
let bi = str.indexOf(b, ai + 1);
let i = ai;
if (ai >= 0 && bi > 0) {
if (a === b) {
return [ai, bi];
}
begs = [];
left = str.length;
while (i >= 0 && !result) {
if (i === ai) {
begs.push(i);
ai = str.indexOf(a, i + 1);
}
else if (begs.length === 1) {
const r = begs.pop();
if (r !== undefined)
result = [r, bi];
}
else {
beg = begs.pop();
if (beg !== undefined && beg < left) {
left = beg;
right = bi;
}
bi = str.indexOf(b, i + 1);
}
i = ai < bi && ai >= 0 ? ai : bi;
}
if (begs.length && right !== undefined) {
result = [left, right];
}
}
return result;
};
exports.range = range;
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export const balanced = (\n a: string | RegExp,\n b: string | RegExp,\n str: string,\n) => {\n const ma = a instanceof RegExp ? maybeMatch(a, str) : a\n const mb = b instanceof RegExp ? maybeMatch(b, str) : b\n\n const r = ma !== null && mb != null && range(ma, mb, str)\n\n return (\n r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + ma.length, r[1]),\n post: str.slice(r[1] + mb.length),\n }\n )\n}\n\nconst maybeMatch = (reg: RegExp, str: string) => {\n const m = str.match(reg)\n return m ? m[0] : null\n}\n\nexport const range = (\n a: string,\n b: string,\n str: string,\n): undefined | [number, number] => {\n let begs: number[],\n beg: number | undefined,\n left: number,\n right: number | undefined = undefined,\n result: undefined | [number, number]\n let ai = str.indexOf(a)\n let bi = str.indexOf(b, ai + 1)\n let i = ai\n\n if (ai >= 0 && bi > 0) {\n if (a === b) {\n return [ai, bi]\n }\n begs = []\n left = str.length\n\n while (i >= 0 && !result) {\n if (i === ai) {\n begs.push(i)\n ai = str.indexOf(a, i + 1)\n } else if (begs.length === 1) {\n const r = begs.pop()\n if (r !== undefined) result = [r, bi]\n } else {\n beg = begs.pop()\n if (beg !== undefined && beg < left) {\n left = beg\n right = bi\n }\n\n bi = str.indexOf(b, i + 1)\n }\n\n i = ai < bi && ai >= 0 ? ai : bi\n }\n\n if (begs.length && right !== undefined) {\n result = [left, right]\n }\n }\n\n return result\n}\n"]}
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
@@ -0,0 +1,9 @@
export declare const balanced: (a: string | RegExp, b: string | RegExp, str: string) => false | {
start: number;
end: number;
pre: string;
body: string;
post: string;
} | undefined;
export declare const range: (a: string, b: string, str: string) => undefined | [number, number];
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,GACnB,GAAG,MAAM,GAAG,MAAM,EAClB,GAAG,MAAM,GAAG,MAAM,EAClB,KAAK,MAAM;;;;;;aAgBZ,CAAA;AAOD,eAAO,MAAM,KAAK,GAChB,GAAG,MAAM,EACT,GAAG,MAAM,EACT,KAAK,MAAM,KACV,SAAS,GAAG,CAAC,MAAM,EAAE,MAAM,CA2C7B,CAAA"}
@@ -0,0 +1,54 @@
export const balanced = (a, b, str) => {
const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
const mb = b instanceof RegExp ? maybeMatch(b, str) : b;
const r = ma !== null && mb != null && range(ma, mb, str);
return (r && {
start: r[0],
end: r[1],
pre: str.slice(0, r[0]),
body: str.slice(r[0] + ma.length, r[1]),
post: str.slice(r[1] + mb.length),
});
};
const maybeMatch = (reg, str) => {
const m = str.match(reg);
return m ? m[0] : null;
};
export const range = (a, b, str) => {
let begs, beg, left, right = undefined, result;
let ai = str.indexOf(a);
let bi = str.indexOf(b, ai + 1);
let i = ai;
if (ai >= 0 && bi > 0) {
if (a === b) {
return [ai, bi];
}
begs = [];
left = str.length;
while (i >= 0 && !result) {
if (i === ai) {
begs.push(i);
ai = str.indexOf(a, i + 1);
}
else if (begs.length === 1) {
const r = begs.pop();
if (r !== undefined)
result = [r, bi];
}
else {
beg = begs.pop();
if (beg !== undefined && beg < left) {
left = beg;
right = bi;
}
bi = str.indexOf(b, i + 1);
}
i = ai < bi && ai >= 0 ? ai : bi;
}
if (begs.length && right !== undefined) {
result = [left, right];
}
}
return result;
};
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export const balanced = (\n a: string | RegExp,\n b: string | RegExp,\n str: string,\n) => {\n const ma = a instanceof RegExp ? maybeMatch(a, str) : a\n const mb = b instanceof RegExp ? maybeMatch(b, str) : b\n\n const r = ma !== null && mb != null && range(ma, mb, str)\n\n return (\n r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + ma.length, r[1]),\n post: str.slice(r[1] + mb.length),\n }\n )\n}\n\nconst maybeMatch = (reg: RegExp, str: string) => {\n const m = str.match(reg)\n return m ? m[0] : null\n}\n\nexport const range = (\n a: string,\n b: string,\n str: string,\n): undefined | [number, number] => {\n let begs: number[],\n beg: number | undefined,\n left: number,\n right: number | undefined = undefined,\n result: undefined | [number, number]\n let ai = str.indexOf(a)\n let bi = str.indexOf(b, ai + 1)\n let i = ai\n\n if (ai >= 0 && bi > 0) {\n if (a === b) {\n return [ai, bi]\n }\n begs = []\n left = str.length\n\n while (i >= 0 && !result) {\n if (i === ai) {\n begs.push(i)\n ai = str.indexOf(a, i + 1)\n } else if (begs.length === 1) {\n const r = begs.pop()\n if (r !== undefined) result = [r, bi]\n } else {\n beg = begs.pop()\n if (beg !== undefined && beg < left) {\n left = beg\n right = bi\n }\n\n bi = str.indexOf(b, i + 1)\n }\n\n i = ai < bi && ai >= 0 ? ai : bi\n }\n\n if (begs.length && right !== undefined) {\n result = [left, right]\n }\n }\n\n return result\n}\n"]}
@@ -0,0 +1,3 @@
{
"type": "module"
}
@@ -0,0 +1,68 @@
{
"name": "balanced-match",
"description": "Match balanced character pairs, like \"{\" and \"}\"",
"version": "4.0.4",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/balanced-match.git"
},
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/commonjs/index.d.ts",
"default": "./dist/commonjs/index.js"
}
}
},
"type": "module",
"scripts": {
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"prepare": "tshy",
"pretest": "npm run prepare",
"presnap": "npm run prepare",
"test": "tap",
"snap": "tap",
"format": "prettier --write .",
"benchmark": "node benchmark/index.js",
"typedoc": "typedoc --tsconfig .tshy/esm.json ./src/*.ts"
},
"devDependencies": {
"@types/brace-expansion": "^1.1.2",
"@types/node": "^25.2.1",
"mkdirp": "^3.0.1",
"prettier": "^3.3.2",
"tap": "^21.6.2",
"tshy": "^3.0.2",
"typedoc": "^0.28.5"
},
"keywords": [
"match",
"regexp",
"test",
"balanced",
"parse"
],
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
},
"tshy": {
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
}
},
"main": "./dist/commonjs/index.js",
"types": "./dist/commonjs/index.d.ts",
"module": "./dist/esm/index.js"
}
@@ -0,0 +1,6 @@
export declare const EXPANSION_MAX = 100000;
export type BraceExpansionOptions = {
max?: number;
};
export declare function expand(str: string, options?: BraceExpansionOptions): string[];
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,aAAa,SAAU,CAAA;AAwDpC,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,YAkBtE"}
@@ -0,0 +1,201 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EXPANSION_MAX = void 0;
exports.expand = expand;
const balanced_match_1 = require("balanced-match");
const escSlash = '\0SLASH' + Math.random() + '\0';
const escOpen = '\0OPEN' + Math.random() + '\0';
const escClose = '\0CLOSE' + Math.random() + '\0';
const escComma = '\0COMMA' + Math.random() + '\0';
const escPeriod = '\0PERIOD' + Math.random() + '\0';
const escSlashPattern = new RegExp(escSlash, 'g');
const escOpenPattern = new RegExp(escOpen, 'g');
const escClosePattern = new RegExp(escClose, 'g');
const escCommaPattern = new RegExp(escComma, 'g');
const escPeriodPattern = new RegExp(escPeriod, 'g');
const slashPattern = /\\\\/g;
const openPattern = /\\{/g;
const closePattern = /\\}/g;
const commaPattern = /\\,/g;
const periodPattern = /\\\./g;
exports.EXPANSION_MAX = 100_000;
function numeric(str) {
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
}
function escapeBraces(str) {
return str
.replace(slashPattern, escSlash)
.replace(openPattern, escOpen)
.replace(closePattern, escClose)
.replace(commaPattern, escComma)
.replace(periodPattern, escPeriod);
}
function unescapeBraces(str) {
return str
.replace(escSlashPattern, '\\')
.replace(escOpenPattern, '{')
.replace(escClosePattern, '}')
.replace(escCommaPattern, ',')
.replace(escPeriodPattern, '.');
}
/**
* Basically just str.split(","), but handling cases
* where we have nested braced sections, which should be
* treated as individual members, like {a,{b,c},d}
*/
function parseCommaParts(str) {
if (!str) {
return [''];
}
const parts = [];
const m = (0, balanced_match_1.balanced)('{', '}', str);
if (!m) {
return str.split(',');
}
const { pre, body, post } = m;
const p = pre.split(',');
p[p.length - 1] += '{' + body + '}';
const postParts = parseCommaParts(post);
if (post.length) {
;
p[p.length - 1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expand(str, options = {}) {
if (!str) {
return [];
}
const { max = exports.EXPANSION_MAX } = options;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.slice(0, 2) === '{}') {
str = '\\{\\}' + str.slice(2);
}
return expand_(escapeBraces(str), max, true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand_(str, max, isTop) {
/** @type {string[]} */
const expansions = [];
const m = (0, balanced_match_1.balanced)('{', '}', str);
if (!m)
return [str];
// no need to expand pre, since it is guaranteed to be free of brace-sets
const pre = m.pre;
const post = m.post.length ? expand_(m.post, max, false) : [''];
if (/\$$/.test(m.pre)) {
for (let k = 0; k < post.length && k < max; k++) {
const expansion = pre + '{' + m.body + '}' + post[k];
expansions.push(expansion);
}
}
else {
const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
const isSequence = isNumericSequence || isAlphaSequence;
const isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand_(str, max, true);
}
return [str];
}
let n;
if (isSequence) {
n = m.body.split(/\.\./);
}
else {
n = parseCommaParts(m.body);
if (n.length === 1 && n[0] !== undefined) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand_(n[0], max, false).map(embrace);
//XXX is this necessary? Can't seem to hit it in tests.
/* c8 ignore start */
if (n.length === 1) {
return post.map(p => m.pre + n[0] + p);
}
/* c8 ignore stop */
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
let N;
if (isSequence && n[0] !== undefined && n[1] !== undefined) {
const x = numeric(n[0]);
const y = numeric(n[1]);
const width = Math.max(n[0].length, n[1].length);
let incr = n.length === 3 && n[2] !== undefined ?
Math.max(Math.abs(numeric(n[2])), 1)
: 1;
let test = lte;
const reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
const pad = n.some(isPadded);
N = [];
for (let i = x; test(i, y) && N.length < max; i += incr) {
let c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\') {
c = '';
}
}
else {
c = String(i);
if (pad) {
const need = width - c.length;
if (need > 0) {
const z = new Array(need + 1).join('0');
if (i < 0) {
c = '-' + z + c.slice(1);
}
else {
c = z + c;
}
}
}
}
N.push(c);
}
}
else {
N = [];
for (let j = 0; j < n.length; j++) {
N.push.apply(N, expand_(n[j], max, false));
}
}
for (let j = 0; j < N.length; j++) {
for (let k = 0; k < post.length && expansions.length < max; k++) {
const expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion) {
expansions.push(expansion);
}
}
}
}
return expansions;
}
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
@@ -0,0 +1,6 @@
export declare const EXPANSION_MAX = 100000;
export type BraceExpansionOptions = {
max?: number;
};
export declare function expand(str: string, options?: BraceExpansionOptions): string[];
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,aAAa,SAAU,CAAA;AAwDpC,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,YAkBtE"}
@@ -0,0 +1,197 @@
import { balanced } from 'balanced-match';
const escSlash = '\0SLASH' + Math.random() + '\0';
const escOpen = '\0OPEN' + Math.random() + '\0';
const escClose = '\0CLOSE' + Math.random() + '\0';
const escComma = '\0COMMA' + Math.random() + '\0';
const escPeriod = '\0PERIOD' + Math.random() + '\0';
const escSlashPattern = new RegExp(escSlash, 'g');
const escOpenPattern = new RegExp(escOpen, 'g');
const escClosePattern = new RegExp(escClose, 'g');
const escCommaPattern = new RegExp(escComma, 'g');
const escPeriodPattern = new RegExp(escPeriod, 'g');
const slashPattern = /\\\\/g;
const openPattern = /\\{/g;
const closePattern = /\\}/g;
const commaPattern = /\\,/g;
const periodPattern = /\\\./g;
export const EXPANSION_MAX = 100_000;
function numeric(str) {
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
}
function escapeBraces(str) {
return str
.replace(slashPattern, escSlash)
.replace(openPattern, escOpen)
.replace(closePattern, escClose)
.replace(commaPattern, escComma)
.replace(periodPattern, escPeriod);
}
function unescapeBraces(str) {
return str
.replace(escSlashPattern, '\\')
.replace(escOpenPattern, '{')
.replace(escClosePattern, '}')
.replace(escCommaPattern, ',')
.replace(escPeriodPattern, '.');
}
/**
* Basically just str.split(","), but handling cases
* where we have nested braced sections, which should be
* treated as individual members, like {a,{b,c},d}
*/
function parseCommaParts(str) {
if (!str) {
return [''];
}
const parts = [];
const m = balanced('{', '}', str);
if (!m) {
return str.split(',');
}
const { pre, body, post } = m;
const p = pre.split(',');
p[p.length - 1] += '{' + body + '}';
const postParts = parseCommaParts(post);
if (post.length) {
;
p[p.length - 1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
export function expand(str, options = {}) {
if (!str) {
return [];
}
const { max = EXPANSION_MAX } = options;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.slice(0, 2) === '{}') {
str = '\\{\\}' + str.slice(2);
}
return expand_(escapeBraces(str), max, true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand_(str, max, isTop) {
/** @type {string[]} */
const expansions = [];
const m = balanced('{', '}', str);
if (!m)
return [str];
// no need to expand pre, since it is guaranteed to be free of brace-sets
const pre = m.pre;
const post = m.post.length ? expand_(m.post, max, false) : [''];
if (/\$$/.test(m.pre)) {
for (let k = 0; k < post.length && k < max; k++) {
const expansion = pre + '{' + m.body + '}' + post[k];
expansions.push(expansion);
}
}
else {
const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
const isSequence = isNumericSequence || isAlphaSequence;
const isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand_(str, max, true);
}
return [str];
}
let n;
if (isSequence) {
n = m.body.split(/\.\./);
}
else {
n = parseCommaParts(m.body);
if (n.length === 1 && n[0] !== undefined) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand_(n[0], max, false).map(embrace);
//XXX is this necessary? Can't seem to hit it in tests.
/* c8 ignore start */
if (n.length === 1) {
return post.map(p => m.pre + n[0] + p);
}
/* c8 ignore stop */
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
let N;
if (isSequence && n[0] !== undefined && n[1] !== undefined) {
const x = numeric(n[0]);
const y = numeric(n[1]);
const width = Math.max(n[0].length, n[1].length);
let incr = n.length === 3 && n[2] !== undefined ?
Math.max(Math.abs(numeric(n[2])), 1)
: 1;
let test = lte;
const reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
const pad = n.some(isPadded);
N = [];
for (let i = x; test(i, y) && N.length < max; i += incr) {
let c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\') {
c = '';
}
}
else {
c = String(i);
if (pad) {
const need = width - c.length;
if (need > 0) {
const z = new Array(need + 1).join('0');
if (i < 0) {
c = '-' + z + c.slice(1);
}
else {
c = z + c;
}
}
}
}
N.push(c);
}
}
else {
N = [];
for (let j = 0; j < n.length; j++) {
N.push.apply(N, expand_(n[j], max, false));
}
}
for (let j = 0; j < N.length; j++) {
for (let k = 0; k < post.length && expansions.length < max; k++) {
const expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion) {
expansions.push(expansion);
}
}
}
}
return expansions;
}
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
{
"type": "module"
}
@@ -0,0 +1,55 @@
# Blue Oak Model License
Version 1.0.0
## Purpose
This license gives everyone as much permission to work with
this software as possible, while protecting contributors
from liability.
## Acceptance
In order to receive this license, you must agree to its
rules. The rules of this license are both obligations
under that agreement and conditions to your license.
You must not do anything with this software that triggers
a rule that you cannot or will not follow.
## Copyright
Each contributor licenses you to do everything with this
software that would otherwise infringe that contributor's
copyright in it.
## Notices
You must ensure that everyone who gets a copy of
any part of this software from you, with or without
changes, also gets the text of this license or a link to
<https://blueoakcouncil.org/license/1.0.0>.
## Excuse
If anyone notifies you in writing that you have not
complied with [Notices](#notices), you can keep your
license by taking all practical steps to comply within 30
days after the notice. If you do not do so, your license
ends immediately.
## Patent
Each contributor licenses you to do everything with this
software that would otherwise infringe any patent claims
they can license or become able to license.
## Reliability
No contributor can revoke this license.
## No Liability
**_As far as the law allows, this software comes as is,
without any warranty or condition, and no contributor
will be liable to anyone for any damages related to this
software or this license, under any kind of legal claim._**
@@ -0,0 +1,48 @@
'use strict'
const parse = require('./parse')
const constants = require('../internal/constants')
const SemVer = require('../classes/semver')
const truncate = (version, truncation, options) => {
if (!constants.RELEASE_TYPES.includes(truncation)) {
return null
}
const clonedVersion = cloneInputVersion(version, options)
return clonedVersion && doTruncation(clonedVersion, truncation)
}
const cloneInputVersion = (version, options) => {
const versionStringToParse = (
version instanceof SemVer ? version.version : version
)
return parse(versionStringToParse, options)
}
const doTruncation = (version, truncation) => {
if (isPrerelease(truncation)) {
return version.version
}
version.prerelease = []
switch (truncation) {
case 'major':
version.minor = 0
version.patch = 0
break
case 'minor':
version.patch = 0
break
}
return version.format()
}
const isPrerelease = (type) => {
return type.startsWith('pre')
}
module.exports = truncate
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1,123 @@
# eslint-visitor-keys
[![npm version](https://img.shields.io/npm/v/eslint-visitor-keys.svg)](https://www.npmjs.com/package/eslint-visitor-keys)
[![Downloads/month](https://img.shields.io/npm/dm/eslint-visitor-keys.svg)](http://www.npmtrends.com/eslint-visitor-keys)
[![Build Status](https://github.com/eslint/js/workflows/CI/badge.svg)](https://github.com/eslint/js/actions)
Constants and utilities about visitor keys to traverse AST.
## 💿 Installation
Use [npm] to install.
```bash
$ npm install eslint-visitor-keys
```
### Requirements
- [Node.js] `^20.19.0`, `^22.13.0`, or `>=24`
## 📖 Usage
To use in an ESM file:
```js
import * as evk from "eslint-visitor-keys";
```
To use in a CommonJS file:
```js
const evk = require("eslint-visitor-keys");
```
### evk.KEYS
> type: `{ [type: string]: string[] | undefined }`
Visitor keys. This keys are frozen.
This is an object. Keys are the type of [ESTree] nodes. Their values are an array of property names which have child nodes.
For example:
```
console.log(evk.KEYS.AssignmentExpression) // → ["left", "right"]
```
### evk.getKeys(node)
> type: `(node: object) => string[]`
Get the visitor keys of a given AST node.
This is similar to `Object.keys(node)` of ES Standard, but some keys are excluded: `parent`, `leadingComments`, `trailingComments`, and names which start with `_`.
This will be used to traverse unknown nodes.
For example:
```js
const node = {
type: "AssignmentExpression",
left: { type: "Identifier", name: "foo" },
right: { type: "Literal", value: 0 },
};
console.log(evk.getKeys(node)); // → ["type", "left", "right"]
```
### evk.unionWith(additionalKeys)
> type: `(additionalKeys: object) => { [type: string]: string[] | undefined }`
Make the union set with `evk.KEYS` and the given keys.
- The order of keys is, `additionalKeys` is at first, then `evk.KEYS` is concatenated after that.
- It removes duplicated keys as keeping the first one.
For example:
```js
console.log(
evk.unionWith({
MethodDefinition: ["decorators"],
}),
); // → { ..., MethodDefinition: ["decorators", "key", "value"], ... }
```
## 📰 Change log
See [GitHub releases](https://github.com/eslint/js/releases).
## 🍻 Contributing
Welcome. See [ESLint contribution guidelines](https://eslint.org/docs/developer-guide/contributing/).
### Development commands
- `npm test` runs tests and measures code coverage.
- `npm run lint` checks source codes with ESLint.
- `npm run test:open-coverage` opens the code coverage report of the previous test with your default browser.
[npm]: https://www.npmjs.com/
[Node.js]: https://nodejs.org/
[ESTree]: https://github.com/estree/estree
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
<!--sponsorsstart-->
## Sponsors
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate)
to get your logo on our READMEs and [website](https://eslint.org/sponsors).
<h3>Platinum Sponsors</h3>
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a></p><h3>Gold Sponsors</h3>
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/d472863/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/2d6c3b6/logo.png" alt="Liftoff" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://opensource.sap.com"><img src="https://avatars.githubusercontent.com/u/2531208" alt="SAP" height="32"></a> <a href="https://www.crawljobs.com/"><img src="https://images.opencollective.com/crawljobs-poland/fa43a17/logo.png" alt="CrawlJobs" height="32"></a> <a href="https://depot.dev"><img src="https://images.opencollective.com/depot/39125a1/logo.png" alt="Depot" height="32"></a> <a href="https://www.n-ix.com/"><img src="https://images.opencollective.com/n-ix-ltd/575a7a5/logo.png" alt="N-iX Ltd" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="TestMu AI Open Source Office (Formerly LambdaTest)" height="32"></a></p>
<h3>Technology Sponsors</h3>
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
<!--sponsorsend-->
@@ -0,0 +1,187 @@
'use strict';
/* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`.
TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed
*/
/**
* @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
*/
/* eslint-enable jsdoc/valid-types -- doesn't allow `readonly string[]`. TODO: check why */
/**
* @type {VisitorKeys}
*/
const KEYS = {
ArrayExpression: ["elements"],
ArrayPattern: ["elements"],
ArrowFunctionExpression: ["params", "body"],
AssignmentExpression: ["left", "right"],
AssignmentPattern: ["left", "right"],
AwaitExpression: ["argument"],
BinaryExpression: ["left", "right"],
BlockStatement: ["body"],
BreakStatement: ["label"],
CallExpression: ["callee", "arguments"],
CatchClause: ["param", "body"],
ChainExpression: ["expression"],
ClassBody: ["body"],
ClassDeclaration: ["id", "superClass", "body"],
ClassExpression: ["id", "superClass", "body"],
ConditionalExpression: ["test", "consequent", "alternate"],
ContinueStatement: ["label"],
DebuggerStatement: [],
DoWhileStatement: ["body", "test"],
EmptyStatement: [],
ExperimentalRestProperty: ["argument"],
ExperimentalSpreadProperty: ["argument"],
ExportAllDeclaration: ["exported", "source", "attributes"],
ExportDefaultDeclaration: ["declaration"],
ExportNamedDeclaration: [
"declaration",
"specifiers",
"source",
"attributes",
],
ExportSpecifier: ["local", "exported"],
ExpressionStatement: ["expression"],
ForInStatement: ["left", "right", "body"],
ForOfStatement: ["left", "right", "body"],
ForStatement: ["init", "test", "update", "body"],
FunctionDeclaration: ["id", "params", "body"],
FunctionExpression: ["id", "params", "body"],
Identifier: [],
IfStatement: ["test", "consequent", "alternate"],
ImportAttribute: ["key", "value"],
ImportDeclaration: ["specifiers", "source", "attributes"],
ImportDefaultSpecifier: ["local"],
ImportExpression: ["source", "options"],
ImportNamespaceSpecifier: ["local"],
ImportSpecifier: ["imported", "local"],
JSXAttribute: ["name", "value"],
JSXClosingElement: ["name"],
JSXClosingFragment: [],
JSXElement: ["openingElement", "children", "closingElement"],
JSXEmptyExpression: [],
JSXExpressionContainer: ["expression"],
JSXFragment: ["openingFragment", "children", "closingFragment"],
JSXIdentifier: [],
JSXMemberExpression: ["object", "property"],
JSXNamespacedName: ["namespace", "name"],
JSXOpeningElement: ["name", "attributes"],
JSXOpeningFragment: [],
JSXSpreadAttribute: ["argument"],
JSXSpreadChild: ["expression"],
JSXText: [],
LabeledStatement: ["label", "body"],
Literal: [],
LogicalExpression: ["left", "right"],
MemberExpression: ["object", "property"],
MetaProperty: ["meta", "property"],
MethodDefinition: ["key", "value"],
NewExpression: ["callee", "arguments"],
ObjectExpression: ["properties"],
ObjectPattern: ["properties"],
PrivateIdentifier: [],
Program: ["body"],
Property: ["key", "value"],
PropertyDefinition: ["key", "value"],
RestElement: ["argument"],
ReturnStatement: ["argument"],
SequenceExpression: ["expressions"],
SpreadElement: ["argument"],
StaticBlock: ["body"],
Super: [],
SwitchCase: ["test", "consequent"],
SwitchStatement: ["discriminant", "cases"],
TaggedTemplateExpression: ["tag", "quasi"],
TemplateElement: [],
TemplateLiteral: ["quasis", "expressions"],
ThisExpression: [],
ThrowStatement: ["argument"],
TryStatement: ["block", "handler", "finalizer"],
UnaryExpression: ["argument"],
UpdateExpression: ["argument"],
VariableDeclaration: ["declarations"],
VariableDeclarator: ["id", "init"],
WhileStatement: ["test", "body"],
WithStatement: ["object", "body"],
YieldExpression: ["argument"],
};
// Types.
const NODE_TYPES = Object.keys(KEYS);
// Freeze the keys.
for (const type of NODE_TYPES) {
Object.freeze(KEYS[type]);
}
Object.freeze(KEYS);
/**
* @author Toru Nagashima <https://github.com/mysticatea>
* See LICENSE file in root directory for full license.
*/
/**
* @typedef {import('./visitor-keys.js').VisitorKeys} VisitorKeys
*/
// List to ignore keys.
const KEY_BLACKLIST = new Set([
"parent",
"leadingComments",
"trailingComments",
]);
/**
* Check whether a given key should be used or not.
* @param {string} key The key to check.
* @returns {boolean} `true` if the key should be used.
*/
function filterKey(key) {
return !KEY_BLACKLIST.has(key) && key[0] !== "_";
}
/* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`.
TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed
*/
/**
* Get visitor keys of a given node.
* @param {Object} node The AST node to get keys.
* @returns {readonly string[]} Visitor keys of the node.
*/
function getKeys(node) {
return Object.keys(node).filter(filterKey);
}
/* eslint-enable jsdoc/valid-types -- doesn't allow `readonly` */
/**
* Make the union set with `KEYS` and given keys.
* @param {VisitorKeys} additionalKeys The additional keys.
* @returns {VisitorKeys} The union set.
*/
function unionWith(additionalKeys) {
const retv =
/** @type {{ [type: string]: ReadonlyArray<string> }} */
(Object.assign({}, KEYS));
for (const type of Object.keys(additionalKeys)) {
if (Object.hasOwn(retv, type)) {
const keys = new Set(additionalKeys[type]);
for (const key of retv[type]) {
keys.add(key);
}
retv[type] = Object.freeze(Array.from(keys));
} else {
retv[type] = Object.freeze(Array.from(additionalKeys[type]));
}
}
return Object.freeze(retv);
}
exports.KEYS = KEYS;
exports.getKeys = getKeys;
exports.unionWith = unionWith;
@@ -0,0 +1,28 @@
type VisitorKeys$1 = {
readonly [type: string]: ReadonlyArray<string>;
};
/**
* @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
*/
/**
* @type {VisitorKeys}
*/
declare const KEYS: VisitorKeys$1;
/**
* Get visitor keys of a given node.
* @param {Object} node The AST node to get keys.
* @returns {readonly string[]} Visitor keys of the node.
*/
declare function getKeys(node: Object): readonly string[];
/**
* Make the union set with `KEYS` and given keys.
* @param {VisitorKeys} additionalKeys The additional keys.
* @returns {VisitorKeys} The union set.
*/
declare function unionWith(additionalKeys: VisitorKeys): VisitorKeys;
type VisitorKeys = VisitorKeys$1;
export { KEYS, getKeys, unionWith };
export type { VisitorKeys };
@@ -0,0 +1,16 @@
/**
* Get visitor keys of a given node.
* @param {Object} node The AST node to get keys.
* @returns {readonly string[]} Visitor keys of the node.
*/
export function getKeys(node: Object): readonly string[];
/**
* Make the union set with `KEYS` and given keys.
* @param {VisitorKeys} additionalKeys The additional keys.
* @returns {VisitorKeys} The union set.
*/
export function unionWith(additionalKeys: VisitorKeys): VisitorKeys;
export { KEYS };
export type VisitorKeys = import("./visitor-keys.js").VisitorKeys;
import KEYS from "./visitor-keys.js";
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
export default KEYS;
export type VisitorKeys = {
readonly [type: string]: ReadonlyArray<string>;
};
/**
* @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
*/
/**
* @type {VisitorKeys}
*/
declare const KEYS: VisitorKeys;
//# sourceMappingURL=visitor-keys.d.ts.map
@@ -0,0 +1,67 @@
/**
* @author Toru Nagashima <https://github.com/mysticatea>
* See LICENSE file in root directory for full license.
*/
import KEYS from "./visitor-keys.js";
/**
* @typedef {import('./visitor-keys.js').VisitorKeys} VisitorKeys
*/
// List to ignore keys.
const KEY_BLACKLIST = new Set([
"parent",
"leadingComments",
"trailingComments",
]);
/**
* Check whether a given key should be used or not.
* @param {string} key The key to check.
* @returns {boolean} `true` if the key should be used.
*/
function filterKey(key) {
return !KEY_BLACKLIST.has(key) && key[0] !== "_";
}
/* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`.
TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed
*/
/**
* Get visitor keys of a given node.
* @param {Object} node The AST node to get keys.
* @returns {readonly string[]} Visitor keys of the node.
*/
export function getKeys(node) {
return Object.keys(node).filter(filterKey);
}
/* eslint-enable jsdoc/valid-types -- doesn't allow `readonly` */
/**
* Make the union set with `KEYS` and given keys.
* @param {VisitorKeys} additionalKeys The additional keys.
* @returns {VisitorKeys} The union set.
*/
export function unionWith(additionalKeys) {
const retv =
/** @type {{ [type: string]: ReadonlyArray<string> }} */
(Object.assign({}, KEYS));
for (const type of Object.keys(additionalKeys)) {
if (Object.hasOwn(retv, type)) {
const keys = new Set(additionalKeys[type]);
for (const key of retv[type]) {
keys.add(key);
}
retv[type] = Object.freeze(Array.from(keys));
} else {
retv[type] = Object.freeze(Array.from(additionalKeys[type]));
}
}
return Object.freeze(retv);
}
export { KEYS };
@@ -0,0 +1,118 @@
/* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`.
TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed
*/
/**
* @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
*/
/* eslint-enable jsdoc/valid-types -- doesn't allow `readonly string[]`. TODO: check why */
/**
* @type {VisitorKeys}
*/
const KEYS = {
ArrayExpression: ["elements"],
ArrayPattern: ["elements"],
ArrowFunctionExpression: ["params", "body"],
AssignmentExpression: ["left", "right"],
AssignmentPattern: ["left", "right"],
AwaitExpression: ["argument"],
BinaryExpression: ["left", "right"],
BlockStatement: ["body"],
BreakStatement: ["label"],
CallExpression: ["callee", "arguments"],
CatchClause: ["param", "body"],
ChainExpression: ["expression"],
ClassBody: ["body"],
ClassDeclaration: ["id", "superClass", "body"],
ClassExpression: ["id", "superClass", "body"],
ConditionalExpression: ["test", "consequent", "alternate"],
ContinueStatement: ["label"],
DebuggerStatement: [],
DoWhileStatement: ["body", "test"],
EmptyStatement: [],
ExperimentalRestProperty: ["argument"],
ExperimentalSpreadProperty: ["argument"],
ExportAllDeclaration: ["exported", "source", "attributes"],
ExportDefaultDeclaration: ["declaration"],
ExportNamedDeclaration: [
"declaration",
"specifiers",
"source",
"attributes",
],
ExportSpecifier: ["local", "exported"],
ExpressionStatement: ["expression"],
ForInStatement: ["left", "right", "body"],
ForOfStatement: ["left", "right", "body"],
ForStatement: ["init", "test", "update", "body"],
FunctionDeclaration: ["id", "params", "body"],
FunctionExpression: ["id", "params", "body"],
Identifier: [],
IfStatement: ["test", "consequent", "alternate"],
ImportAttribute: ["key", "value"],
ImportDeclaration: ["specifiers", "source", "attributes"],
ImportDefaultSpecifier: ["local"],
ImportExpression: ["source", "options"],
ImportNamespaceSpecifier: ["local"],
ImportSpecifier: ["imported", "local"],
JSXAttribute: ["name", "value"],
JSXClosingElement: ["name"],
JSXClosingFragment: [],
JSXElement: ["openingElement", "children", "closingElement"],
JSXEmptyExpression: [],
JSXExpressionContainer: ["expression"],
JSXFragment: ["openingFragment", "children", "closingFragment"],
JSXIdentifier: [],
JSXMemberExpression: ["object", "property"],
JSXNamespacedName: ["namespace", "name"],
JSXOpeningElement: ["name", "attributes"],
JSXOpeningFragment: [],
JSXSpreadAttribute: ["argument"],
JSXSpreadChild: ["expression"],
JSXText: [],
LabeledStatement: ["label", "body"],
Literal: [],
LogicalExpression: ["left", "right"],
MemberExpression: ["object", "property"],
MetaProperty: ["meta", "property"],
MethodDefinition: ["key", "value"],
NewExpression: ["callee", "arguments"],
ObjectExpression: ["properties"],
ObjectPattern: ["properties"],
PrivateIdentifier: [],
Program: ["body"],
Property: ["key", "value"],
PropertyDefinition: ["key", "value"],
RestElement: ["argument"],
ReturnStatement: ["argument"],
SequenceExpression: ["expressions"],
SpreadElement: ["argument"],
StaticBlock: ["body"],
Super: [],
SwitchCase: ["test", "consequent"],
SwitchStatement: ["discriminant", "cases"],
TaggedTemplateExpression: ["tag", "quasi"],
TemplateElement: [],
TemplateLiteral: ["quasis", "expressions"],
ThisExpression: [],
ThrowStatement: ["argument"],
TryStatement: ["block", "handler", "finalizer"],
UnaryExpression: ["argument"],
UpdateExpression: ["argument"],
VariableDeclaration: ["declarations"],
VariableDeclarator: ["id", "init"],
WhileStatement: ["test", "body"],
WithStatement: ["object", "body"],
YieldExpression: ["argument"],
};
// Types.
const NODE_TYPES = Object.keys(KEYS);
// Freeze the keys.
for (const type of NODE_TYPES) {
Object.freeze(KEYS[type]);
}
Object.freeze(KEYS);
export default KEYS;
@@ -0,0 +1,57 @@
{
"name": "eslint-visitor-keys",
"version": "5.0.1",
"description": "Constants and utilities about visitor keys to traverse AST.",
"type": "module",
"main": "dist/eslint-visitor-keys.cjs",
"types": "./dist/index.d.ts",
"exports": {
".": [
{
"import": "./lib/index.js",
"require": "./dist/eslint-visitor-keys.cjs"
},
"./dist/eslint-visitor-keys.cjs"
],
"./package.json": "./package.json"
},
"files": [
"dist/index.d.ts",
"dist/visitor-keys.d.ts",
"dist/eslint-visitor-keys.cjs",
"dist/eslint-visitor-keys.d.cts",
"lib"
],
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
},
"devDependencies": {
"rollup-plugin-dts": "^6.2.3",
"tsd": "^0.33.0"
},
"scripts": {
"build": "npm run build:cjs && npm run build:types",
"build:cjs": "rollup -c",
"build:debug": "npm run build:cjs -- -m && npm run build:types",
"build:types": "tsc -v && tsc",
"test": "mocha \"tests/**/*.test.cjs\" && mocha \"tests/**/*.test.js\" && npm run test:types",
"test:coverage": "c8 npm test",
"test:types": "tsd"
},
"repository": {
"type": "git",
"url": "https://github.com/eslint/js.git",
"directory": "packages/eslint-visitor-keys"
},
"funding": "https://opencollective.com/eslint",
"keywords": [
"eslint"
],
"author": "Toru Nagashima (https://github.com/mysticatea)",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/eslint/js/issues"
},
"homepage": "https://github.com/eslint/js/blob/main/packages/eslint-visitor-keys/README.md",
"sideEffects": false
}