import type * as AST from 'estree'; import type * as ESTreeJSX from 'estree-jsx'; import type { TSESTree } from '@typescript-eslint/types'; import type { Parse } from './parse.js'; import type * as ESRap from 'esrap'; import type { Position } from 'acorn'; import type { RequireAllOrNone } from './helpers'; import type { JsxPlatform, JsxPlatformHooks, JsxTransformContext, JsxTransformOptions, JsxTransformResult, createJsxTransform, } from './jsx-platform'; export type { Parse, JsxPlatform, JsxPlatformHooks, JsxTransformContext, JsxTransformOptions, JsxTransformResult, }; export { createJsxTransform }; export function collectStyleRefAttributes(node: any, refs?: any[]): any[]; export function createStyleClassMap(component: any, css: any): AST.ObjectExpression; export function createStyleClassMapFromStylesheet(css: any): AST.ObjectExpression; export function createStyleRefSetupStatements( refAttributes: any[], styleMap: AST.Expression, options?: { allowMutableRefTarget?: boolean; createTempIdentifier?: () => AST.Identifier; visitExpression?: (expression: AST.Expression) => AST.Expression; }, ): AST.Statement[]; export function getStyleElementStylesheet(styleElement: any): any | null; /** * Compile error interface */ export interface CompileError extends Error { code: string | undefined; pos: number | undefined; raisedAt: number | undefined; end: number | undefined; loc: AST.SourceLocation | undefined; fileName: string | null; type: 'fatal' | 'usage'; } /** * Compilation options */ export interface CompileOptions { mode?: 'client' | 'server'; minify_css?: boolean; dev?: boolean; hmr?: boolean; /** * When true, non-fatal errors are collected on the result's `errors` * array instead of being thrown. Defaults to false (strict mode: throws). */ collect?: boolean; /** * Enables editor-oriented parser recovery such as incomplete markup. * Also collects non-fatal errors as `collect`. */ loose?: boolean; } export type NameSpace = 'html' | 'svg' | 'mathml'; interface BaseNodeMetaData { scoped?: boolean; path: AST.Node[]; has_template?: boolean; source_name?: string; source_length?: number; module_keyword?: 'module' | 'namespace'; is_capitalized?: boolean; commentContainerId?: number; parenthesized?: boolean; native_tsrx?: boolean; native_tsrx_template_block?: boolean; dynamicElement?: boolean; templateMode?: 'script' | 'template'; script_only?: boolean; tsrxDirective?: 'if' | 'for' | 'switch' | 'try'; ts_name?: string; delegated?: any; returned_tsrx_return?: AST.ReturnStatement; styleScopeHash?: string; css?: { scopedClasses: Map; hash: string; }; elementLeadingComments?: AST.Comment[]; returns?: AST.ReturnStatement[]; has_return?: boolean; has_throw?: boolean; has_continue?: boolean; is_reactive?: boolean; lone_return?: boolean; regular_js?: boolean; returned_tsrx_child?: boolean; forceMapping?: boolean; generated_loop_skip_if?: boolean; lazy_id?: string; disable_verification?: boolean; lazy_param_binding_mappings?: Array<{ source: AST.Identifier; generated: AST.Identifier | AST.Literal; }>; } interface FunctionMetaData extends BaseNodeMetaData { native_tsrx?: boolean; native_tsrx_function?: boolean; is_method?: boolean; tracked?: boolean; has_lazy_descendants?: boolean; synthetic_children?: boolean; generated_helpers?: any[]; generated_statics?: any[]; } // Strip parent, loc, and range from TSESTree nodes to match @sveltejs/acorn-typescript output // acorn-typescript uses start/end instead of range, and loc is optional type AcornTSNode = Omit & { start?: number; end?: number; loc?: AST.SourceLocation; range?: AST.BaseNode['range']; metadata: BaseNodeMetaData; leadingComments?: AST.Comment[] | undefined; trailingComments?: AST.Comment[] | undefined; }; interface FunctionLikeTS { returnType?: AST.TSTypeAnnotation; typeParameters?: AST.TSTypeParameterDeclaration; typeAnnotation?: AST.TSTypeAnnotation; } // TSRX augmentation for ESTree function nodes declare module 'estree' { interface Program { innerComments?: Comment[] | undefined; } interface FunctionDeclaration extends FunctionLikeTS { metadata: FunctionMetaData; } interface FunctionExpression extends FunctionLikeTS { metadata: FunctionMetaData; } interface ArrowFunctionExpression extends FunctionLikeTS { metadata: FunctionMetaData; } interface NewExpression { metadata: BaseNodeMetaData & { skipNewMapping?: boolean; }; } interface SimpleCallExpression { metadata: BaseNodeMetaData & { hash?: string; /** * A generated `(() => @{ … })()` inline-component IIFE for a code * block; collapsible once the block's statements lower into the * component callback. */ tsrx_code_block_component?: boolean; /** * A generated zero-argument scope IIFE for a `@{ … }` code-block * chain level; runs synchronously inside its `with_scope` wrapper. */ tsrx_code_block_scope?: boolean; }; } interface ReturnStatement { metadata: BaseNodeMetaData & { invalid_tsrx_template_return?: boolean; generated_loop_continue_return?: boolean; }; } interface BlockStatement { metadata: BaseNodeMetaData & { native_return_block?: boolean; native_tsrx_template_block?: boolean; allows_native_return?: boolean; }; } type Accessibility = 'public' | 'protected' | 'private'; // missing in acorn-typescript types interface MethodDefinition { typeParameters?: TSTypeParameterDeclaration; accessibility?: Accessibility; } interface PropertyDefinition { accessibility?: Accessibility; readonly?: boolean; optional?: boolean; } interface ClassDeclaration { typeParameters?: AST.TSTypeParameterDeclaration; superTypeParameters?: AST.TSTypeParameterInstantiation; implements?: AST.TSClassImplements[]; } interface ClassExpression { typeParameters?: AST.TSTypeParameterDeclaration; superTypeParameters?: AST.TSTypeParameterInstantiation; implements?: AST.TSClassImplements[]; } interface Identifier extends AST.TrackedNode { metadata: BaseNodeMetaData & { // needed for volar tokens to recognize component functions is_component?: boolean; }; typeAnnotation?: TSTypeAnnotation | undefined; decorators: TSESTree.Decorator[]; optional: boolean; } // Lazy destructuring patterns (&{...} and &[...]) interface ObjectPattern { lazy?: boolean; } interface ArrayPattern { lazy?: boolean; } // Ripple analysis may mark a whole member expression as tracked metadata. interface MemberExpression { tracked?: boolean; } interface SimpleLiteral extends AST.LiteralNode {} interface RegExpLiteral extends AST.LiteralNode {} interface BigIntLiteral extends AST.LiteralNode {} interface TrackedNode { tracked?: boolean; } interface LiteralNode { was_expression?: boolean; } // Include TypeScript node types and TSRX-specific nodes in NodeMap interface NodeMap { Element: Element; TsrxFragment: TsrxFragment; Text: Text; TSRXJSXElement: TSRXJSXElement; TSRXJSXFragment: TSRXJSXFragment; TSRXJSXOpeningElement: ESTreeJSX.TSRXJSXOpeningElement; TSRXJSXClosingElement: ESTreeJSX.TSRXJSXClosingElement; TSRXExpression: TSRXExpression; Attribute: Attribute; SpreadAttribute: SpreadAttribute; JSXCodeBlock: JSXCodeBlock; JSXStyleElement: JSXStyleElement; JSXIfExpression: JSXIfExpression; JSXForExpression: JSXForExpression; JSXSwitchExpression: JSXSwitchExpression; JSXTryExpression: JSXTryExpression; ParenthesizedExpression: ParenthesizedExpression; } interface ExpressionMap { Element: Element; TsrxFragment: TsrxFragment; Text: Text; TSRXExpression: TSRXExpression; JSXCodeBlock: JSXCodeBlock; JSXStyleElement: JSXStyleElement; JSXIfExpression: JSXIfExpression; JSXForExpression: JSXForExpression; JSXSwitchExpression: JSXSwitchExpression; JSXTryExpression: JSXTryExpression; JSXEmptyExpression: ESTreeJSX.JSXEmptyExpression; ParenthesizedExpression: ParenthesizedExpression; TSAsExpression: TSAsExpression; } // Ripple-normalized template node shapes. The core parser emits JSX-shaped // TSRX nodes; @tsrx/ripple creates these during its normalization pass. interface Attribute extends AST.BaseNode { type: 'Attribute'; name: AST.Identifier; value: any; shorthand?: boolean; metadata: BaseNodeMetaData; } interface SpreadAttribute extends AST.BaseNode { type: 'SpreadAttribute'; argument: AST.Expression; metadata: BaseNodeMetaData; } interface Element extends AST.BaseExpression { type: 'Element'; id: AST.Expression; attributes: Array; children: AST.Node[]; openingElement: ESTreeJSX.JSXOpeningElement; closingElement: ESTreeJSX.JSXClosingElement | null; selfClosing?: boolean; unclosed?: boolean; isDynamic?: boolean; css?: string; metadata: BaseNodeMetaData; start: number; end: number; } interface TsrxFragment extends AST.BaseExpression { type: 'TsrxFragment'; children: AST.Node[]; openingElement?: ESTreeJSX.JSXOpeningFragment; closingElement?: ESTreeJSX.JSXClosingFragment | null; selfClosing?: boolean; attributes?: Array; metadata: BaseNodeMetaData & { /** * A synthetic wrapper for a nested code-block render chain * (`@{ @{ … } }`), so render-slot consumers see a template node; * template-children lowering unwraps it. */ tsrx_code_block_chain?: boolean; }; start: number; end: number; } interface Text extends AST.BaseExpression { type: 'Text'; expression: AST.Expression; metadata: BaseNodeMetaData; } interface TSRXExpression extends AST.BaseExpression { type: 'TSRXExpression'; expression: AST.Expression; metadata: BaseNodeMetaData; } type TSRXJSXChild = | ESTreeJSX.JSXText | ESTreeJSX.JSXExpressionContainer | ESTreeJSX.JSXSpreadChild | TSRXJSXElement | TSRXJSXFragment | AST.JSXCodeBlock; interface TSRXJSXElement extends Omit, AST.NodeWithMaybeComments { openingElement: ESTreeJSX.TSRXJSXOpeningElement; closingElement: ESTreeJSX.TSRXJSXClosingElement | null; children: TSRXJSXChild[]; metadata: BaseNodeMetaData & { ts_name?: string; }; } interface TSRXJSXFragment extends Omit, AST.NodeWithMaybeComments { children: TSRXJSXChild[]; } interface JSXCodeBlock extends AST.BaseExpression { type: 'JSXCodeBlock'; body: AST.Statement[]; render: AST.Node | null; metadata: BaseNodeMetaData; innerComments?: AST.Comment[] | undefined; } interface JSXStyleElement extends Omit { type: 'JSXStyleElement'; children: AST.CSS.StyleSheet[]; css?: string; unclosed?: boolean; } interface JSXIfExpression extends AST.BaseExpression { type: 'JSXIfExpression'; statementType: 'IfStatement'; test: AST.Expression; consequent: AST.Statement; alternate: AST.Statement | null; metadata: BaseNodeMetaData; } interface JSXForExpression extends AST.BaseExpression { type: 'JSXForExpression'; statementType: 'ForStatement' | 'ForInStatement' | 'ForOfStatement'; body: AST.Statement; init?: AST.VariableDeclaration | AST.Expression | null; test?: AST.Expression | null; update?: AST.Expression | null; left?: AST.VariableDeclaration | AST.Pattern; right?: AST.Expression; await?: boolean; index?: AST.Identifier | null; key?: AST.Expression | null; empty?: AST.BlockStatement | null; metadata: BaseNodeMetaData; } interface JSXSwitchExpression extends AST.BaseExpression { type: 'JSXSwitchExpression'; statementType: 'SwitchStatement'; discriminant: AST.Expression; cases: AST.SwitchCase[]; metadata: BaseNodeMetaData; } interface JSXTryExpression extends AST.BaseExpression { type: 'JSXTryExpression'; statementType: 'TryStatement'; block: AST.BlockStatement; handler: AST.CatchClause | null; finalizer: AST.BlockStatement | null; pending?: AST.BlockStatement | null; metadata: BaseNodeMetaData; } interface ParenthesizedExpression extends AST.BaseNode { type: 'ParenthesizedExpression'; expression: AST.Expression; metadata: BaseNodeMetaData & { skipParenthesisMapping?: boolean; }; } interface Comment { context?: Parse.CommentMetaData | null; } // For now only ObjectExpression needs printInline // Needed to avoid ts pragma comments being on the wrong line that // does not affect the next line as in the source code interface ObjectExpression { metadata: BaseNodeMetaData & { printInline?: boolean; }; } /** * Custom Comment interface with location information */ type CommentWithLocation = AST.Comment & NodeWithLocation; interface TryStatement { pending?: AST.BlockStatement | null; } interface CatchClause { resetParam?: AST.Pattern | null; } interface ForOfStatement { index?: AST.Identifier | null; key?: AST.Expression | null; empty?: AST.BlockStatement | null; } interface ImportDeclaration { importKind: TSESTree.ImportDeclaration['importKind']; } interface ImportSpecifier { importKind: TSESTree.ImportSpecifier['importKind']; } interface ExportNamedDeclaration { exportKind: TSESTree.ExportNamedDeclaration['exportKind']; } interface BaseNodeWithoutComments { // Adding start, end for now as always there // later might change to optional // And only define on certain nodes // BaseNode inherits from this interface start?: number; end?: number; } interface BaseNode { is_controlled?: boolean; // This is for Pattern but it's a type alias // So it's just easy to extend BaseNode even though // typeAnnotation, typeArguments do not apply to all nodes typeAnnotation?: TSTypeAnnotation; typeArguments?: TSTypeParameterInstantiation; // even though technically metadata starts out as undefined // metadata is always populated by the `_` visitor // which runs for every node before other visitors // so taking a practical approach and making it required // to avoid lots of typecasting or checking for undefined metadata: BaseNodeMetaData; comments?: Comment[]; } interface NodeWithLocation { start: number; end: number; loc: AST.SourceLocation; } interface NodeWithMaybeComments { innerComments?: AST.Comment[] | undefined; leadingComments?: AST.Comment[] | undefined; trailingComments?: AST.Comment[] | undefined; } type TSRXDeclaration = AST.Declaration | AST.TSDeclareFunction; interface TSRXExportNamedDeclaration extends Omit { declaration?: TSRXDeclaration | null | undefined; } interface TSRXProgram extends Omit { body: (Program['body'][number] | FunctionExpression)[]; } type TSRXStatement = AST.Statement | TSESTree.Statement; type NodeWithChildren = TSRXJSXElement | TSRXJSXFragment | JSXStyleElement | ESTreeJSX.JSXElement; export namespace CSS { export interface BaseNode extends AST.NodeWithMaybeComments { start: number; end: number; loc?: AST.SourceLocation; } export interface StyleSheet extends BaseNode { type: 'StyleSheet'; children: Array; source: string; hash: string; } export interface Atrule extends BaseNode { type: 'Atrule'; name: string; prelude: string; block: Block | null; } export interface Rule extends BaseNode { type: 'Rule'; prelude: SelectorList; block: Block; metadata: { parent_rule: Rule | null; has_local_selectors: boolean; is_global_block: boolean; }; } /** * A list of selectors, e.g. `a, b, c {}` */ export interface SelectorList extends BaseNode { type: 'SelectorList'; /** * The `a`, `b` and `c` in `a, b, c {}` */ children: ComplexSelector[]; } /** * A complex selector, e.g. `a b c {}` */ export interface ComplexSelector extends BaseNode { type: 'ComplexSelector'; /** * The `a`, `b` and `c` in `a b c {}` */ children: RelativeSelector[]; metadata: { rule: Rule | null; used: boolean; is_global?: boolean; }; } /** * A relative selector, e.g the `a` and `> b` in `a > b {}` */ export interface RelativeSelector extends BaseNode { type: 'RelativeSelector'; /** * In `a > b`, `> b` forms one relative selector, and `>` is the combinator. `null` for the first selector. */ combinator: null | Combinator; /** * The `b:is(...)` in `> b:is(...)` */ selectors: SimpleSelector[]; metadata: { is_global: boolean; is_global_like: boolean; scoped: boolean; }; } export interface TypeSelector extends BaseNode { type: 'TypeSelector'; name: string; } export interface IdSelector extends BaseNode { type: 'IdSelector'; name: string; } export interface ClassSelector extends BaseNode { type: 'ClassSelector'; name: string; } export interface AttributeSelector extends BaseNode { type: 'AttributeSelector'; name: string; matcher: string | null; value: string | null; flags: string | null; } export interface PseudoElementSelector extends BaseNode { type: 'PseudoElementSelector'; name: string; } export interface PseudoClassSelector extends BaseNode { type: 'PseudoClassSelector'; name: string; args: SelectorList | null; } export interface Percentage extends BaseNode { type: 'Percentage'; value: string; } export interface NestingSelector extends BaseNode { type: 'NestingSelector'; name: '&'; } export interface Nth extends BaseNode { type: 'Nth'; value: string; } export type SimpleSelector = | TypeSelector | IdSelector | ClassSelector | AttributeSelector | PseudoElementSelector | PseudoClassSelector | Percentage | Nth | NestingSelector; export interface Combinator extends BaseNode { type: 'Combinator'; name: string; } export interface Block extends BaseNode { type: 'Block'; children: Array; } export interface Declaration extends BaseNode { type: 'Declaration'; property: string; value: string; } // for zimmerframe export type Node = | StyleSheet | Rule | Atrule | SelectorList | Block | ComplexSelector | RelativeSelector | Combinator | SimpleSelector | Declaration; } } declare module 'estree-jsx' { interface JSXAttribute { shorthand: boolean; } interface JSXIdentifier { metadata: BaseNodeMetaData & { is_component?: boolean; }; } interface JSXEmptyExpression { loc: AST.SourceLocation; innerComments?: AST.Comment[]; } interface JSXOpeningFragment { attributes: Array; } interface JSXElement { metadata: BaseNodeMetaData & { ts_name?: string; }; } interface JSXOpeningElement { metadata: BaseNodeMetaData & { native_tsrx_pretransformed?: boolean; }; } interface JSXExpressionContainer { text?: boolean; style?: boolean; isDynamic?: boolean; } interface JSXMemberExpression { computed?: boolean; } interface TSRXJSXOpeningElement extends Omit { name: AST.MemberExpression | JSXIdentifier | JSXNamespacedName | JSXExpressionContainer; } interface TSRXJSXClosingElement extends Omit { name: AST.MemberExpression | JSXIdentifier | JSXNamespacedName | JSXExpressionContainer; } interface ExpressionMap { JSXIdentifier: JSXIdentifier; } } declare module 'estree' { // Helper map for creating our own TypeNode // and to be used to extend estree's NodeMap interface TSNodeMap { // TypeScript nodes TSAnyKeyword: TSAnyKeyword; TSArrayType: TSArrayType; TSAsExpression: TSAsExpression; TSBigIntKeyword: TSBigIntKeyword; TSBooleanKeyword: TSBooleanKeyword; TSCallSignatureDeclaration: TSCallSignatureDeclaration; TSConditionalType: TSConditionalType; TSConstructorType: TSConstructorType; TSConstructSignatureDeclaration: TSConstructSignatureDeclaration; TSDeclareFunction: TSDeclareFunction; TSEnumDeclaration: TSEnumDeclaration; TSEnumMember: TSEnumMember; TSExportAssignment: TSExportAssignment; TSExternalModuleReference: TSExternalModuleReference; TSFunctionType: TSFunctionType; TSImportEqualsDeclaration: TSImportEqualsDeclaration; TSImportType: TSImportType; TSIndexedAccessType: TSIndexedAccessType; TSIndexSignature: TSIndexSignature; TSInferType: TSInferType; TSInstantiationExpression: TSInstantiationExpression; TSInterfaceBody: TSInterfaceBody; TSInterfaceDeclaration: TSInterfaceDeclaration; TSIntersectionType: TSIntersectionType; TSIntrinsicKeyword: TSIntrinsicKeyword; TSLiteralType: TSLiteralType; TSMappedType: TSMappedType; TSMethodSignature: TSMethodSignature; TSModuleBlock: TSModuleBlock; TSModuleDeclaration: TSModuleDeclaration; TSNamedTupleMember: TSNamedTupleMember; TSNamespaceExportDeclaration: TSNamespaceExportDeclaration; TSNeverKeyword: TSNeverKeyword; TSNonNullExpression: TSNonNullExpression; TSNullKeyword: TSNullKeyword; TSNumberKeyword: TSNumberKeyword; TSObjectKeyword: TSObjectKeyword; TSOptionalType: TSOptionalType; TSParameterProperty: TSParameterProperty; TSPropertySignature: TSPropertySignature; TSQualifiedName: TSQualifiedName; TSRestType: TSRestType; TSSatisfiesExpression: TSSatisfiesExpression; TSStringKeyword: TSStringKeyword; TSSymbolKeyword: TSSymbolKeyword; TSThisType: TSThisType; TSTupleType: TSTupleType; TSTypeAliasDeclaration: TSTypeAliasDeclaration; TSTypeAnnotation: TSTypeAnnotation; TSTypeAssertion: TSTypeAssertion; TSTypeLiteral: TSTypeLiteral; TSTypeOperator: TSTypeOperator; TSTypeParameter: TSTypeParameter; TSTypeParameterDeclaration: TSTypeParameterDeclaration; TSTypeParameterInstantiation: TSTypeParameterInstantiation; TSTypePredicate: TSTypePredicate; TSTypeQuery: TSTypeQuery; TSTypeReference: TSTypeReference; TSUndefinedKeyword: TSUndefinedKeyword; TSUnionType: TSUnionType; TSUnknownKeyword: TSUnknownKeyword; TSVoidKeyword: TSVoidKeyword; TSParenthesizedType: TSParenthesizedType; TSExpressionWithTypeArguments: TSExpressionWithTypeArguments; TSClassImplements: TSClassImplements; } // Create our version of TypeNode with modified types to be used in replacements type TypeNode = TSNodeMap[keyof TSNodeMap]; // Extend NodeMap to include TypeScript nodes interface NodeMap extends TSNodeMap { TypeNode: TypeNode; } type EntityName = AST.Identifier | AST.ThisExpression | TSQualifiedName; type Parameter = | AST.ArrayPattern | AST.AssignmentPattern | AST.Identifier | AST.ObjectPattern | AST.RestElement | TSParameterProperty; type TypeElement = | TSCallSignatureDeclaration | TSConstructSignatureDeclaration | TSIndexSignature | TSMethodSignature | TSPropertySignature; type TSPropertySignature = TSPropertySignatureComputedName | TSPropertySignatureNonComputedName; type PropertyNameComputed = AST.Expression; type PropertyNameNonComputed = AST.Identifier | NumberLiteral | StringLiteral; // TypeScript AST node interfaces from @sveltejs/acorn-typescript // Based on TSESTree types but adapted for acorn's output format interface TSAnyKeyword extends AcornTSNode {} interface TSArrayType extends Omit, 'elementType'> { elementType: TypeNode; } interface TSAsExpression extends Omit, 'typeAnnotation'> { // Have to override it to use our Expression for required properties like metadata expression: AST.Expression; typeAnnotation: TypeNode; } interface TSBigIntKeyword extends AcornTSNode {} interface TSBooleanKeyword extends AcornTSNode {} interface TSCallSignatureDeclaration extends Omit< AcornTSNode, 'typeParameters' | 'params' | 'returnType' > { parameters: Parameter[]; typeParameters: TSTypeParameterDeclaration | undefined; typeAnnotation: TSTypeAnnotation | undefined; } interface TSConditionalType extends Omit< AcornTSNode, 'checkType' | 'extendsType' | 'falseType' | 'trueType' > { checkType: TypeNode; extendsType: TypeNode; falseType: TypeNode; trueType: TypeNode; } interface TSConstructorType extends Omit< AcornTSNode, 'typeParameters' | 'params' | 'returnType' > { typeAnnotation: TSTypeAnnotation | undefined; typeParameters: TSTypeParameterDeclaration | undefined; parameters: AST.Parameter[]; } interface TSConstructSignatureDeclaration extends Omit< AcornTSNode, 'typeParameters' | 'params' | 'returnType' > { parameters: Parameter[]; typeParameters: TSTypeParameterDeclaration | undefined; typeAnnotation: TSTypeAnnotation | undefined; } interface TSDeclareFunction extends Omit< AcornTSNode, 'id' | 'params' | 'typeParameters' | 'returnType' > { id: AST.Identifier; params: Parameter[]; typeParameters: TSTypeParameterDeclaration | undefined; returnType: TSTypeAnnotation | undefined; } interface TSEnumDeclaration extends Omit< AcornTSNode, 'id' | 'members' > { id: AST.Identifier; members: TSEnumMember[]; } interface TSEnumMember extends Omit, 'id' | 'initializer'> { id: AST.Identifier | StringLiteral; initializer: AST.Expression | undefined; } interface TSExportAssignment extends Omit< AcornTSNode, 'expression' > { expression: AST.Expression; } interface TSExternalModuleReference extends Omit< AcornTSNode, 'expression' > { expression: StringLiteral; } interface TSFunctionType extends Omit< AcornTSNode, 'typeParameters' | 'params' | 'returnType' > { typeAnnotation: TSTypeAnnotation | undefined; typeParameters: TSTypeParameterDeclaration | undefined; parameters: Parameter[]; } interface TSImportEqualsDeclaration extends AcornTSNode {} interface TSImportType extends Omit< AcornTSNode, 'argument' | 'qualifier' | 'typeParameters' > { argument: TypeNode; qualifier: EntityName | null; // looks like acorn-typescript has typeParameters typeParameters: TSTypeParameterDeclaration | undefined | undefined; } interface TSIndexedAccessType extends Omit< AcornTSNode, 'indexType' | 'objectType' > { indexType: TypeNode; objectType: TypeNode; } interface TSIndexSignature extends Omit< AcornTSNode, 'parameters' | 'typeAnnotation' > { parameters: AST.Parameter[]; typeAnnotation: TSTypeAnnotation | undefined; } interface TSInferType extends Omit, 'typeParameter'> { typeParameter: TSTypeParameter; } interface TSInstantiationExpression extends Omit< AcornTSNode, 'typeArguments' | 'expression' > { expression: AST.Expression; typeArguments: TSTypeParameterInstantiation; } interface TSInterfaceBody extends Omit, 'body'> { body: TypeElement[]; } interface TSInterfaceDeclaration extends Omit< AcornTSNode, 'id' | 'typeParameters' | 'body' | 'extends' > { id: AST.Identifier; typeParameters: TSTypeParameterDeclaration | undefined; body: TSInterfaceBody; extends: TSExpressionWithTypeArguments[]; } interface TSIntersectionType extends Omit, 'types'> { types: TypeNode[]; } interface TSIntrinsicKeyword extends AcornTSNode {} interface TSLiteralType extends Omit, 'literal'> { literal: AST.Literal | AST.TemplateLiteral; } interface TSMappedType extends Omit< AcornTSNode, 'typeParameter' | 'typeAnnotation' | 'nameType' > { typeAnnotation: TypeNode | undefined; typeParameter: TSTypeParameter; nameType: TypeNode | null; } interface TSMethodSignature extends Omit< AcornTSNode, 'key' | 'typeParameters' | 'params' | 'returnType' > { key: PropertyNameComputed | PropertyNameNonComputed; typeParameters: TSTypeParameterDeclaration | undefined; parameters: Parameter[]; // doesn't actually exist in the spec but acorn-typescript adds it typeAnnotation: TSTypeAnnotation | undefined; } interface TSModuleBlock extends Omit, 'body'> { body: AST.Statement[]; } interface TSModuleDeclaration extends Omit< AcornTSNode, 'body' | 'id' > { body: TSModuleBlock; id: AST.Identifier; metadata: BaseNodeMetaData & { exports?: Set; }; } interface TSNamedTupleMember extends Omit< AcornTSNode, 'elementType' | 'label' > { elementType: TypeNode; label: AST.Identifier; } interface TSNamespaceExportDeclaration extends Omit< AcornTSNode, 'id' > { id: AST.Identifier; } interface TSNeverKeyword extends AcornTSNode {} interface TSNonNullExpression extends AcornTSNode { expression: AST.Expression; } interface TSNullKeyword extends AcornTSNode {} interface TSNumberKeyword extends AcornTSNode {} interface TSObjectKeyword extends AcornTSNode {} interface TSOptionalType extends Omit, 'typeAnnotation'> { typeAnnotation: TypeNode; } interface TSParameterProperty extends AcornTSNode {} interface TSPropertySignatureComputedName extends Omit< AcornTSNode, 'key' | 'typeAnnotation' > { key: PropertyNameComputed; typeAnnotation: TSTypeAnnotation | undefined; } interface TSPropertySignatureNonComputedName extends Omit< AcornTSNode, 'key' | 'typeAnnotation' > { key: PropertyNameNonComputed; typeAnnotation: TSTypeAnnotation | undefined; } interface TSQualifiedName extends Omit, 'left' | 'right'> { left: EntityName; right: AST.Identifier; } interface TSRestType extends Omit, 'typeAnnotation'> { typeAnnotation: TypeNode; } interface TSSatisfiesExpression extends Omit< AcornTSNode, 'typeAnnotation' > { expression: AST.Expression; typeAnnotation: TypeNode; } interface TSStringKeyword extends AcornTSNode {} interface TSSymbolKeyword extends AcornTSNode {} interface TSThisType extends AcornTSNode {} interface TSTupleType extends Omit, 'elementTypes'> { elementTypes: TypeNode[]; } interface TSTypeAliasDeclaration extends Omit< AcornTSNode, 'id' | 'typeParameters' | 'typeAnnotation' > { id: AST.Identifier; typeAnnotation: TypeNode; typeParameters: TSTypeParameterDeclaration | undefined; } interface TSTypeAnnotation extends Omit< AcornTSNode, 'typeAnnotation' > { typeAnnotation: TypeNode; } interface TSTypeAssertion extends AcornTSNode { expression: AST.Expression; } interface TSTypeLiteral extends Omit, 'members'> { members: TypeElement[]; } interface TSTypeOperator extends Omit, 'typeAnnotation'> { typeAnnotation: TypeNode | undefined; } interface TSTypeParameter extends Omit< AcornTSNode, 'name' | 'constraint' | 'default' > { constraint: TypeNode | undefined; default: TypeNode | undefined; name: string; // for some reason acorn-typescript uses string instead of Identifier } interface TSTypeParameterDeclaration extends Omit< AcornTSNode, 'params' > { params: TSTypeParameter[]; extra?: { trailingComma: number; }; } interface TSTypeParameterInstantiation extends Omit< AcornTSNode, 'params' > { params: TypeNode[]; } interface TSTypePredicate extends Omit< AcornTSNode, 'parameterName' | 'typeAnnotation' > { parameterName: AST.Identifier | AST.TSThisType; typeAnnotation: AST.TSTypeAnnotation | null; } interface TSTypeQuery extends Omit< AcornTSNode, 'exprName' | 'typeArguments' > { exprName: EntityName | TSImportType; typeArguments: TSTypeParameterInstantiation | undefined; } interface TSTypeReference extends Omit< AcornTSNode, 'typeName' | 'typeArguments' > { typeArguments: TSTypeParameterInstantiation | undefined; typeName: EntityName; } interface TSUndefinedKeyword extends AcornTSNode {} interface TSUnionType extends Omit, 'types'> { types: TypeNode[]; } // TSInterfaceHeritage doesn't exist in acorn-typescript which uses TSExpressionWithTypeArguments interface TSInterfaceHeritage extends Omit< AcornTSNode, 'expression' | 'typeParameters' > { expression: AST.Expression; // acorn-typescript uses typeParameters instead of typeArguments typeParameters: TSTypeParameterInstantiation | undefined; } // Extends TSInterfaceHeritage as it's the semantically the same as used by acorn-typescript interface TSExpressionWithTypeArguments extends Omit { type: 'TSExpressionWithTypeArguments'; } interface TSClassImplements extends AcornTSNode {} interface TSUnknownKeyword extends AcornTSNode {} interface TSVoidKeyword extends AcornTSNode {} interface NumberLiteral extends AcornTSNode {} interface StringLiteral extends AcornTSNode {} // acorn-typescript specific nodes (not in @typescript-eslint/types) interface TSParenthesizedType extends AST.BaseNode { type: 'TSParenthesizedType'; } // Extend ExpressionMap for TypeScript expressions interface ExpressionMap { TSAsExpression: TSAsExpression; TSInstantiationExpression: TSInstantiationExpression; TSNonNullExpression: TSNonNullExpression; TSSatisfiesExpression: TSSatisfiesExpression; TSTypeAssertion: TSTypeAssertion; } } /** * Parse error information */ export interface ParseError { message: string; pos: number; loc: Position; } /** * Parse options */ export interface ParseOptions { collect?: boolean; loose?: boolean; errors?: CompileError[]; comments?: AST.CommentWithLocation[]; } /** * Analyze options */ export interface AnalyzeOptions extends ParseOptions, Pick { errors?: CompileError[]; to_ts?: boolean; } /** * Result of parsing operation */ export interface ParseResult { ast: AST.Program; errors: ParseError[]; } export interface AnalysisResult { ast: AST.Program; scopes: Map; scope: ScopeInterface; component_metadata: Array<{ id: string }>; metadata: { serverImportsPresent: boolean; serverImportDeclarations: AST.ImportDeclaration[]; serverModule: AST.TSModuleDeclaration | null; }; errors: CompileError[]; comments: AST.CommentWithLocation[]; } /** * Configuration for the TSRX parser plugin */ export interface TSRXPluginConfig { allowSatisfies?: boolean; } /** * Types of declarations in scope */ export type DeclarationKind = | 'var' | 'let' | 'const' | 'function' | 'param' | 'rest_param' | 'import' | 'module' | 'using' | 'await using'; /** * Binding kinds */ export type BindingKind = | 'normal' | 'for_pattern' | 'rest_prop' | 'prop' | 'prop_fallback' | 'lazy' | 'lazy_fallback' | 'index'; /** * A variable binding in a scope */ export interface Binding { /** The identifier node that declares this binding */ node: AST.Identifier; /** References to this binding */ references: Array<{ node: AST.Identifier; path: AST.Node[] }>; /** Initial value/declaration */ initial: | null | AST.Expression | AST.FunctionDeclaration | AST.ClassDeclaration | AST.ImportDeclaration | AST.TSModuleDeclaration | ESTreeJSX.JSXFragment; /** Whether this binding has been reassigned */ reassigned: boolean; /** Whether this binding has been mutated (property access) */ mutated: boolean; /** Whether this binding has been updated (reassigned or mutated) */ updated: boolean; /** Whether this binding represents a called function */ is_called: boolean; /** Additional metadata for this binding */ metadata: { pattern?: AST.Identifier; is_ripple_object?: boolean; is_template_value?: boolean; lazy_array_source?: string; lazy_array_index?: number; lazy_array_source_tracked?: boolean; lazy_array_rest?: boolean; typeAnnotation?: AST.TypeNode; } | null; /** Kind of binding */ kind: BindingKind; /** Declaration kind */ declaration_kind?: DeclarationKind; /** The scope that contains this binding */ scope: ScopeInterface; /** Transform functions for reading, assigning, and updating this binding */ transform?: { read: (node?: AST.Identifier) => AST.Expression; assign?: (node: AST.Identifier, value: AST.Expression) => AST.Expression; update?: (node: AST.UpdateExpression) => AST.Expression; }; /** Whether the read transform already produces an unwrapped value (calls get() internally) */ read_unwraps?: boolean; } /** * Root scope manager */ export interface ScopeRootInterface { /** Set of conflicting/reserved names */ conflicts: Set; /** Generate unique identifier name */ unique(preferred_name: string): AST.Identifier; } export interface ScopeConstructorInterface { root: ScopeRootInterface; parent: ScopeInterface | null; porous: boolean; error_options: { collect: boolean; errors: CompileError[]; filename: string; comments?: AST.CommentWithLocation[]; }; } export type ScopeConstructorParameters = [ root: ScopeConstructorInterface['root'], parent: ScopeConstructorInterface['parent'], porous: ScopeConstructorInterface['porous'], error_options: ScopeConstructorInterface['error_options'], ]; /** * Lexical scope for variable bindings */ export interface ScopeInterface { /** Root scope manager */ root: ScopeRootInterface; /** Parent scope */ parent: ScopeInterface | null; /** Map of declared bindings */ declarations: Map; /** Map of declarators to their bindings */ declarators: Map; /** Map of references in this scope */ references: Map>; /** Function nesting depth */ function_depth: number; /** Whether reactive tracing is enabled */ tracing: null | AST.Expression; server_block?: boolean; /** Create child scope */ child(porous?: boolean): ScopeInterface; /** Declare a binding */ declare( node: AST.Identifier, kind: BindingKind, declaration_kind: DeclarationKind, initial?: | null | AST.Expression | AST.FunctionDeclaration | AST.ClassDeclaration | AST.ImportDeclaration | AST.TSModuleDeclaration | ESTreeJSX.JSXFragment, ): Binding; /** Get binding by name */ get(name: string): Binding | null; /** Get bindings for a declarator */ get_bindings(node: AST.VariableDeclarator): Binding[]; /** Find the scope that owns a name */ owner(name: string): ScopeInterface | null; /** Add a reference */ reference(node: AST.Identifier, path: AST.Node[]): void; /** Generate unique identifier name */ generate(preferred_name: string): string; } /** * Compiler state object */ interface BaseStateMetaData { tracking?: boolean | null; } export interface BaseState { /** For utils */ scope: ScopeInterface; scopes: Map; ancestor_server_block: AST.TSModuleDeclaration | undefined; inside_head?: boolean; keep_component_style?: boolean; regular_js?: boolean; /** Common For All */ to_ts: boolean; component?: AST.Function; } export interface AnalysisState extends BaseState { analysis: AnalysisResult & { module: { ast: AnalysisResult['ast']; scope: AnalysisResult['scope']; scopes: AnalysisResult['scopes']; filename: string; }; }; elements?: Array; function_depth?: number; collect?: boolean; metadata: BaseStateMetaData & { styleClasses?: StyleClasses; }; mode: CompileOptions['mode']; // keep this as an object as we destructure module: { // Incremented counter for generating unique track/trackAsync hashes track_id: number; }; } export interface TransformServerState extends BaseState { imports: Set; init: Array | null; stylesheets: AST.CSS.StyleSheet[]; component_metadata: AnalysisResult['component_metadata']; filename: string; metadata: BaseStateMetaData; namespace: NameSpace; server_block_locals: AST.VariableDeclaration[]; server_exported_names: string[]; applyParentCssScope?: AST.CSS.StyleSheet['hash']; dev?: boolean; return_flags?: Map; template_child?: boolean; skip_regular_blocks?: boolean; in_regular_block?: boolean; is_tsrx_element?: boolean; jsx_to_tsrx_element?: boolean; } export type UpdateList = Array< RequireAllOrNone< { identity?: AST.Identifier | AST.Expression; initial?: AST.Expression; operation: (expr?: AST.Expression, prev?: AST.Expression) => AST.ExpressionStatement; expression?: AST.Expression; needsPrevTracking?: boolean; }, 'initial' | 'identity' | 'expression' > >; export interface TransformClientState extends BaseState { events: Set; filename: string; final: Array | null; flush_node: ((is_text?: boolean, is_controlled?: boolean) => AST.Identifier) | null; hoisted: Array; imports: Set; server_block_locals: AST.VariableDeclaration[]; init: Array | null; metadata: BaseStateMetaData; namespace: NameSpace; stylesheets: Array; template: Array | null; update: UpdateList | null; errors: CompileError[]; applyParentCssScope?: AST.CSS.StyleSheet['hash']; skip_children_traversal: boolean; return_flags?: Map; is_tsrx_element?: boolean; jsx_to_tsrx_element?: boolean; template_child?: boolean; ref_target_type?: AST.TypeNode; } /** Override zimmerframe types and provide our own */ type NodeOf = X extends { type: T } ? X : never; type SpecializedVisitors = { [K in T['type']]?: Visitor, U, T>; }; type VisitFn = (node: V) => void; export type CatchAllVisitor = ( node: T, context: Context, visit: VisitFn, ) => V | void; export type Visitor = (node: T, context: Context) => V | void; export type Visitors = T['type'] extends '_' ? never : SpecializedVisitors & { _?: CatchAllVisitor; }; export interface Context extends Omit< ESRap.Context, 'path' | 'state' | 'visit' | 'next' | 'stop' > { next: (state?: U) => T | void; path: T[]; state: U; stop: () => void; visit: (node: T, state?: U) => T; } /** * Transform context object */ export type TransformClientContext = Context; export type TransformServerContext = Context; export type AnalysisContext = Context; export type CommonContext = TransformClientContext | TransformServerContext | AnalysisContext; export type VisitorClientContext = TransformClientContext & { root?: boolean }; /** * Delegated event result */ export interface DelegatedEventResult { function?: AST.FunctionExpression | AST.FunctionDeclaration | AST.ArrowFunctionExpression; } export type TopScopedClasses = Map< string, { start: number; end: number; selector: AST.CSS.ClassSelector; } >; export type StyleClasses = Map; /** * Event handling types */ export interface AddEventOptions extends ExtendedEventOptions { customName?: string; } export interface AddEventObject extends AddEventOptions { handleEvent(object: Event): void; } export interface ExtendedEventOptions { capture?: boolean; once?: boolean; passive?: boolean; signal?: AbortSignal; delegated?: boolean; } /** * Volar integration types */ import type { CodeInformation as VolarCodeInformation, Mapping as VolarMapping, } from '@volar/language-core'; import type { DocumentHighlightKind } from 'vscode-languageserver-types'; import type { RawSourceMap } from 'source-map'; export interface DefinitionLocation { embeddedId: string; start: number; end: number; } export interface PluginActionOverrides { wordHighlight?: { kind: DocumentHighlightKind; }; suppressedDiagnostics?: number[]; hover?: string | false | ((content: string) => string); definition?: | { description?: string; location?: DefinitionLocation; typeReplace?: { name: string; path: string; }; } | false; } export interface CustomMappingData extends PluginActionOverrides { embeddedId?: string; content?: string; } export interface MappingData extends VolarCodeInformation { customData: CustomMappingData; } export interface CodeMapping extends Omit, 'generatedLengths'> { generatedLengths: number[]; data: MappingData; } export interface VolarMappingsResult { code: string; mappings: CodeMapping[]; cssMappings: CodeMapping[]; errors: CompileError[]; sourceAst: AST.Program; } /** * Result of compilation operation */ export interface CompileResult { /** The generated JavaScript code */ code: string; /** Source map for the generated code */ map: import('source-map').RawSourceMap; /** Rendered CSS for the module, or `''` when the module emits no styles. */ css: string; /** * Space-separated scope hashes for the rendered CSS, or `null` when the * module emits no styles. */ cssHash: string | null; /** * Non-fatal errors collected during compilation. Populated only when the * caller passes `collect: true` or `loose: true`; empty otherwise. */ errors: CompileError[]; } /** * Volar-specific compile options */ export interface VolarCompileOptions extends Omit { minify_css?: boolean; dev?: boolean; } /** * Common base options accepted by every TSRX target's `compile` entry point. * Targets that need extra knobs (e.g. ripple's `mode`/`dev`/`hmr`, preact's * `suspenseSource`) intersect their own option type with this base when * declaring their `compile` export. */ export interface BaseCompileOptions { collect?: boolean; loose?: boolean; } /** * Shared `compile` signature for every TSRX target package. Per-target * `compile` declarations should be `CompileFn` so any * drift in the shared contract becomes a typecheck error in every package. * * @template TOptions Per-target options accepted as the third argument. * Defaults to {@link BaseCompileOptions}. * @template TResult Per-target result type. Must extend {@link CompileResult}; * targets may add fields (e.g. ripple's deprecated `js` back-compat field) * via intersection. */ export type CompileFn< TOptions = BaseCompileOptions, TResult extends CompileResult = CompileResult, > = (source: string, filename?: string, options?: TOptions) => TResult; /** * Shared `compile_to_volar_mappings` signature for every TSRX target package. * * @template TOptions Per-target options accepted as the third argument. * Defaults to {@link ParseOptions}; targets may intersect their own option * type to add e.g. `suspenseSource`. */ export type VolarCompileFn = ( source: string, filename?: string, options?: TOptions, ) => VolarMappingsResult; /** * Source map transformation types */ export type PostProcessingChanges = Map; export type LineOffsets = number[];