├── .prettierignore ├── config.civet ├── .gitignore ├── .vscode └── extensions.json ├── .prettierrc ├── test ├── __template.civet ├── interface.civet ├── comments.civet ├── instanceof.civet ├── property.civet ├── objects.civet ├── numbers.civet ├── _run.civet ├── required.civet ├── variables.civet ├── _utils.civet ├── import.civet ├── control-flow.civet └── function.civet ├── tsconfig.json ├── rollup.config.civet ├── scripts └── ts-ast.civet ├── src ├── utils.civet ├── transform.civet ├── cli.civet └── emitter.civet ├── readme.md ├── package.json └── pnpm-lock.yaml /.prettierignore: -------------------------------------------------------------------------------- 1 | test/test.tsx -------------------------------------------------------------------------------- /config.civet: -------------------------------------------------------------------------------- 1 | export default 2 | parseOptions: {} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | dist 3 | node_modules 4 | verify/*json* -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["danielx.civet"] 3 | } 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "trailingComma": "es5", 4 | "arrowParens": "avoid", 5 | "semi": false, 6 | "printWidth": 100 7 | } 8 | -------------------------------------------------------------------------------- /test/__template.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | Dummy_Test: => "" becomes "" -------------------------------------------------------------------------------- /test/interface.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | Index_Signature: => "interface X { [indexSignature: string]: number }" becomes "interface X\n\t[indexSignature: string]: number" -------------------------------------------------------------------------------- /test/comments.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | Inline_Around: => "/* 1 */hey/* 2 */" becomes " /* 1 */\nhey /* 2 */\n" 7 | Line_Around: => "// 1\nhey\n// 2" becomes " // 1\nhey\n// 2" -------------------------------------------------------------------------------- /test/instanceof.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | Instanceof: => "a instanceof b" becomes "a "!(a instanceof b)" becomes "a ! "typeof a === 'b'" becomes "a "typeof a !== 'b'" becomes "a ! "ns.thing" becomes "ns.thing" 8 | PropertyAccessQuestionDot: => "ns?.thing" becomes "ns?.thing" 9 | ThisAccess: => "this.thing" becomes "@thing" 10 | ThisAccessQuestionDot: => "this?.thing" becomes "@?.thing" -------------------------------------------------------------------------------- /rollup.config.civet: -------------------------------------------------------------------------------- 1 | civetRollupPlugin from @danielx/civet/dist/rollup.mjs 2 | type { RollupOptions } from rollup 3 | pkg from ./package.json assert type: "json" 4 | 5 | export default { 6 | input: 7 | transform: "src/transform.civet" 8 | cli: "src/cli.civet" 9 | output: 10 | dir: "dist" 11 | format: "es" 12 | plugins: [ 13 | civetRollupPlugin 14 | emitDeclaration: true 15 | ts: "tsc" 16 | typecheck: true 17 | implicitExtension: true 18 | 19 | ] 20 | external: [/^node\:/, ...Object.keys pkg.dependencies] 21 | } satisfies RollupOptions -------------------------------------------------------------------------------- /test/objects.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator exprBecomes, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | Empty: => "{}" exprBecomes "{}" 7 | Unbrace: => "{ number: 3 }" exprBecomes "number: 3" 8 | Brace: => "{ number }" exprBecomes "{ number }" 9 | Multiline: => "{\n\tnumber: 3\n}" exprBecomes "\n\tnumber: 3" 10 | InArray: => 11 | "[{ a: 1 }]" exprBecomes "[{ a: 1 }]" 12 | "[{ a: 1 }, { b: 2 }]" exprBecomes "[{ a: 1 }, { b: 2 }]" 13 | "[\n\t{ a: 1 },\n\t{ b: 2 }\n]" exprBecomes "[\n\ta: 1\n,\n\tb: 2\n]" -------------------------------------------------------------------------------- /test/numbers.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | Basic: => "10" becomes "10" 7 | Binary: => "0b10" becomes "0b10" 8 | Octal: => "0o10" becomes "0o10" 9 | Hex: => "0x10" becomes "0x10" 10 | Float: => 11 | "10.0" becomes "10.0", 12 | "10.0e10" becomes "10.0e10" 13 | Seperator: => 14 | "10_000" becomes "10_000", 15 | "10_000.0" becomes "10_000.0", 16 | "10_000.0e10" becomes "10_000.0e10" 17 | BigInt: => 18 | "10n" becomes "10n", 19 | "10_000n" becomes "10_000n" -------------------------------------------------------------------------------- /test/_run.civet: -------------------------------------------------------------------------------- 1 | { glob } from glob 2 | { dirname, parse } from node:path 3 | { fileURLToPath } from node:url 4 | { describe, it } from node:test 5 | { setOptions } from ./_utils.civet 6 | 7 | files := await glob "./**/*.civet", dotRelative: true, cwd: dirname fileURLToPath import.meta.url 8 | 9 | for file of files 10 | console.log `Importing ${file}` 11 | parsed := parse file 12 | continue if parsed.base.startsWith '_' 13 | { tests, options } := await import file 14 | describe file, => 15 | for name in tests 16 | it name.replaceAll("_", " "), => 17 | if name.startsWith "TODO" 18 | return 19 | setOptions options 20 | await tests[name]() 21 | return -------------------------------------------------------------------------------- /scripts/ts-ast.civet: -------------------------------------------------------------------------------- 1 | ts from typescript 2 | { createSourceFile } := ts 3 | { readFile, writeFile } from node:fs/promises 4 | * as prettier from prettier 5 | [runner, script, ...inputs] := process.argv 6 | if inputs.length is 0 7 | console.error `Usage: ${runner} ${script} [...input.ts]` 8 | process.exit 1 9 | await.all inputs.map (input) => 10 | tscode .= await readFile input, 'utf8' 11 | tscode = prettier.format tscode, parser: 'typescript', semi: false 12 | output := `${input}.json` 13 | sourceFile := createSourceFile input, tscode, ts.ScriptTarget.Latest, false 14 | delete sourceFile.text // don't compare this 15 | delete sourceFile.fileName // don't compare this 16 | await writeFile output, JSON.stringify sourceFile, (key, value) => if key is in ["pos", "end", "jsDoc"] then undefined else value, 2 17 | console.log `Wrote ${output}` -------------------------------------------------------------------------------- /src/utils.civet: -------------------------------------------------------------------------------- 1 | export enum StringLiteralType 2 | SingleQuote 3 | DoubleQuote 4 | Template 5 | 6 | regexes: Record := 7 | [StringLiteralType.SingleQuote]: /'/g 8 | [StringLiteralType.DoubleQuote]: /"/g 9 | [StringLiteralType.Template]: /`/g 10 | 11 | regexReplaces: Record string> := { 12 | [StringLiteralType.SingleQuote](match: string) 13 | `\\${match}` 14 | [StringLiteralType.DoubleQuote](match: string) 15 | `\\${match}` 16 | [StringLiteralType.Template](match: string) 17 | `\\${match}` 18 | } 19 | 20 | 21 | /** Converts a string to something that can be used in that kind of string. */ 22 | export function stringLiteral(text: string, literalType: StringLiteralType): string 23 | text.replaceAll regexes[literalType], regexReplaces[literalType] -------------------------------------------------------------------------------- /test/required.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | Labels: => 7 | "label: hello" becomes ":label \nhello\n" 8 | "$: hello" becomes ":$ \nhello\n" 9 | 10 | Arrow_Functions: => 11 | "a => a" contains "(a) => a" 12 | "(a) => a" contains "(a) => a" 13 | "a => { return a }" contains "(a) =>\n\treturn a" 14 | "(a) => { return a }" contains "(a) =>\n\treturn a" 15 | 16 | Decorators: => 17 | """ 18 | @Object.seal 19 | class Civet { 20 | @stuff 21 | drink() {} 22 | } 23 | """ contains """ 24 | \n@@Object.seal 25 | class Civet 26 | \t@@stuff 27 | \tdrink(): void 28 | """ 29 | 30 | Ternary: => "a ? b : c" contains "if a then b else c" -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ts2civet 2 | 3 | Converts [TypeScript](https://www.typescriptlang.org/) code to _concise_ [civet](https://civet.dev/). Demo at [ts2civet.esthe.win](https://ts2civet.esthe.win/) 4 | 5 | ***WIP! Use carefully and double-check output.*** 6 | 7 | ## CLI 8 | 9 | ```bash 10 | npx ts2civet --help 11 | ``` 12 | 13 | Examples: 14 | 15 | ```bash 16 | $ ts2civet src/**/*.ts 17 | > Transformed src/a.ts to src/a.civet 18 | > Transformed src/b.ts to src/b.civet 19 | > Transformed src/folder/file.ts to src/folder/file.civet 20 | 21 | $ ts2civet src/index.ts -o- 22 | > console.log "Hello, world!" 23 | 24 | $ ts2civet src/a.ts -o src/civety-a.civet src/b.ts -o. src/import.ts -o- 25 | > Transformed src/a.ts to src/civety-a.civet 26 | > Transformed src/b.ts to src/b.civet 27 | > console.log "Hello, world!" 28 | ``` 29 | 30 | ## API 31 | 32 | ```ts 33 | import { transform } from "ts2civet" 34 | const code = transform('console.log("Hello, world!")', "./code.ts") // console.log "Hello, world!" 35 | ``` 36 | -------------------------------------------------------------------------------- /test/variables.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | Basic: => 7 | "const a = 1" becomes "a := 1" 8 | "let a = 1" becomes "a .= 1" 9 | "var a = 1" becomes "var a = 1" 10 | Typed: => 11 | "const a: number = 1" becomes "a: number := 1" 12 | "let a: number = 1" becomes "a: number .= 1" 13 | "var a: number = 1" becomes "var a: number = 1" 14 | Multiple: => 15 | "const a = 1, b = 2" becomes "const a = 1, \n\tb = 2" 16 | "let a = 1, b = 2" becomes "let a = 1, \n\tb = 2" 17 | "var a = 1, b = 2" becomes "var a = 1, \n\tb = 2" 18 | Multiple_Typed: => 19 | "const a: number = 1, b: string = 'b'" becomes "const a: number = 1, \n\tb: string = 'b'" 20 | "let a: number = 1, b: string = 'b'" becomes "let a: number = 1, \n\tb: string = 'b'" 21 | "var a: number = 1, b: string = 'b'" becomes "var a: number = 1, \n\tb: string = 'b'" -------------------------------------------------------------------------------- /src/transform.civet: -------------------------------------------------------------------------------- 1 | ts from typescript 2 | { SyntaxKind, createSourceFile } := ts 3 | { Emitter } from ./emitter.civet 4 | 5 | export interface Options 6 | /** 7 | * If false, don't add a header to the generated file. 8 | * @default true 9 | */ 10 | header?: boolean 11 | 12 | 13 | export function transform( 14 | tscode: string 15 | path: string 16 | options: Options = {} 17 | ): string 18 | { header } := options 19 | // a bit of a hack to fix issue #6 20 | tscode += '\n0' 21 | parsed .= createSourceFile `${path}.tsx`, tscode, ts.ScriptTarget.Latest, true 22 | 23 | writer := new Emitter parsed 24 | 25 | if header !== false 26 | writer.write `// Generated by ts2civet: ${new Date()}\n\n` 27 | 28 | writer.node parsed 29 | result .= writer.toString() 30 | // cont: a bit of a hack to fix issue #6 31 | result |>= .replace(/\s*0\s*$/, '') + '\n' 32 | if writer.jsxUsed 33 | result = '"civet coffeeJSX" // ts2civet does not implement JSX civetifying yet. Feel free to move this flag to your civet config, or manually rewrite the JSX.\n' + result // TODO FIX! this is like . bad ! 34 | result -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts2civet", 3 | "version": "1.0.0-beta.10", 4 | "description": "Converts typescript code to civet code", 5 | "main": "dist/cli.js", 6 | "bin": { 7 | "ts2civet": "dist/cli.js" 8 | }, 9 | "repository": "github:esthedebeste/ts2civet", 10 | "exports": { 11 | "import": "./dist/transform.js", 12 | "types": "./dist/transform.civet.d.ts" 13 | }, 14 | "types": "./dist/transform.civet.d.ts", 15 | "scripts": { 16 | "build": "rollup --config rollup.config.civet --configPlugin @danielx/civet/rollup", 17 | "prepare": "pnpm build", 18 | "start": "node --loader @danielx/civet/esm ./src/cli.civet", 19 | "test": "c8 node --loader @danielx/civet/esm --test test/_run.civet" 20 | }, 21 | "keywords": [ 22 | "typescript", 23 | "civet" 24 | ], 25 | "author": "esthedebeste", 26 | "license": "MIT", 27 | "dependencies": { 28 | "code-block-writer": "^12.0.0", 29 | "glob": "^10.3.10", 30 | "meow": "^13.2.0", 31 | "typescript": "^5.3.3" 32 | }, 33 | "devDependencies": { 34 | "@danielx/civet": "^0.6.83", 35 | "@types/node": "^20.11.24", 36 | "@types/prettier": "^3.0.0", 37 | "c8": "^9.1.0", 38 | "prettier": "^3.2.5", 39 | "rollup": "^4.12.0" 40 | }, 41 | "files": [ 42 | "dist" 43 | ], 44 | "c8": { 45 | "all": true, 46 | "reporter": [ 47 | "lcov", 48 | "text" 49 | ], 50 | "extension": [ 51 | ".civet" 52 | ], 53 | "include": [ 54 | "src" 55 | ] 56 | }, 57 | "type": "module" 58 | } 59 | -------------------------------------------------------------------------------- /test/_utils.civet: -------------------------------------------------------------------------------- 1 | /// 2 | { transform, type Options as OrigOptions } from ../src/transform.civet 3 | { operator equal, ok: assert, doesNotThrow } from node:assert/strict 4 | * as civet from @danielx/civet 5 | 6 | export interface Options extends OrigOptions 7 | filename?: string 8 | 9 | defaultOpts := { filename: "./code.tsx" } as const 10 | export options: Options .= { ...defaultOpts } 11 | 12 | function transforms(source: string) 13 | transform source, options.filename ?? "./code.tsx", { -header, ...options } 14 | 15 | export operator becomesUnchecked(source: string, output: string) 16 | transforms source |> &.trim() equal output.trim() 17 | 18 | export operator becomes(source: string, output: string) 19 | try 20 | civet.parse output 21 | catch e 22 | equal output, "any valid civet code", "TEST FAULT: Expected output is not valid civet code" 23 | source becomesUnchecked output 24 | 25 | export operator exprBecomes(source: string, output: string) 26 | ("_ = " + source) becomes ("_ = " + output) 27 | 28 | export operator contains(source: string, output: string) 29 | transformed := transforms source 30 | assert output.trim() is in transformed, `Expected ${output} to be in ${transformed} - (${JSON.stringify output} in ${JSON.stringify transformed})` 31 | 32 | export function setOptions(opts: Partial) 33 | options = { ...defaultOpts, ...opts } 34 | 35 | export type Tests = Record> -------------------------------------------------------------------------------- /test/import.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator becomesUnchecked, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | export tests: Tests := 5 | ImportBald: => "import './stuff'" becomes "import ./stuff\n" 6 | ImportDefault: => "import s from './stuff'" becomes "s from ./stuff\n" 7 | ImportNamed: => "import { s } from './stuff'" becomes "{ s } from ./stuff\n" 8 | ImportNamedAs: => "import { s as t } from './stuff'" becomes "{ s: t } from ./stuff\n" 9 | ImportNamespace: => "import * as s from './stuff'" becomes "* as s from ./stuff\n" 10 | ImportTypeGroup: => "import type { s } from './stuff'" becomes "type { s } from ./stuff\n" 11 | ImportTypeGroupAs: => "import type { s as t } from './stuff'" becomes "type { s: t } from ./stuff\n" 12 | ImportMixed: => "import s, { t as u, type f as k } from './stuff'" becomes "s, { t: u, type f: k } from ./stuff\n" 13 | ImportWith: => "import { s } from './stuff' with { type: 'json' }" becomes "{ s } from ./stuff with type: 'json'\n" 14 | 15 | ExportFrom: => "export { s } from './stuff'" becomes "export s from ./stuff\n" 16 | ExportAll: => "export * from './stuff'" becomes "export * from ./stuff\n" 17 | ExportAs: => "export { s as t }" becomes "export s as t\n" 18 | // TODO: replace this `becomesUnchecked` once this issue is solved https://github.com/DanielXMoore/Civet/issues/1092 19 | ExportFromAs: => "export { s as t } from './stuff'" becomesUnchecked "export s: t from ./stuff\n" 20 | ExportFromType: => "export type { s } from './stuff'" becomes "export type s from ./stuff\n" 21 | // TODO: replace this `becomesUnchecked` once this issue is solved https://github.com/DanielXMoore/Civet/issues/1091 22 | ExportFromWith: => "export { s } from './stuff' with { type: 'json' }" becomesUnchecked "export s from ./stuff with type: 'json'\n" -------------------------------------------------------------------------------- /src/cli.civet: -------------------------------------------------------------------------------- 1 | meow from meow 2 | { transform, type Options } from ./transform.civet 3 | { readFileSync, writeFileSync } from node:fs 4 | { glob } from glob 5 | 6 | cli := meow """ 7 | Usage 8 | $ ts2civet [input] 9 | 10 | Options 11 | --help Show this help message 12 | --version Show version 13 | --(no-)header Add a ts2civet header to the output (default: true) 14 | --output, -o Output file. '-' for stdout, '.' to replace the extension with .civet (default) 15 | 16 | Examples 17 | $ ts2civet src/**/*.ts 18 | > Transformed src/a.ts to src/a.civet 19 | > Transformed src/b.ts to src/b.civet 20 | > Transformed src/folder/file.ts to src/folder/file.civet 21 | 22 | $ ts2civet src/index.ts -o- 23 | > console.log "Hello, world!" 24 | 25 | $ ts2civet src/a.ts -o src/civety-a.civet src/b.ts -o. src/import.ts -o- 26 | > Transformed src/a.ts to src/civety-a.civet 27 | > Transformed src/b.ts to src/b.civet 28 | > console.log "Hello, world!" 29 | """, 30 | importMeta: import.meta, 31 | flags: 32 | help: 33 | type: "boolean" 34 | default: false 35 | version: 36 | type: "boolean" 37 | default: false 38 | header: 39 | type: "boolean" 40 | default: true 41 | output: 42 | type: "string" 43 | shortFlag: "o" 44 | default: [] 45 | isMultiple: true 46 | isRequired: false 47 | 48 | if cli.flags.version then cli.showVersion() 49 | if cli.flags.help or cli.input.length is 0 then cli.showHelp() 50 | 51 | cli.input = (await.all cli.input.map (pattern) => glob pattern).flat() 52 | 53 | if cli.flags.output.length is not 0 and cli.flags.output.length is not cli.input.length 54 | console.error "Number of output files must match number of input files, or be omitted." 55 | cli.showHelp() 56 | 57 | for [i, input] of cli.input.entries() 58 | out := 59 | if cli.flags.output.length is 0 or cli.flags.output[i] is "." 60 | input.replace /\.\w+?$/, ".civet" 61 | else 62 | cli.flags.output[i] 63 | source := readFileSync input, "utf8" 64 | transformed := transform source, input, cli.flags as Options 65 | if out is "-" 66 | console.log transformed 67 | else 68 | writeFileSync out, transformed 69 | console.log `Transformed ${input} to ${out}` 70 | 71 | -------------------------------------------------------------------------------- /test/control-flow.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator becomesUnchecked, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | Indexed: => 7 | "for(let i = 0; i < 10; i++) { 123 }" becomes "for i .= 0; i < 10; i++\n\t123" 8 | Indexed_Multiple: => 9 | "for(let i = 0, j = 0; i < 10; i++) { 123 }" becomes "for let i = 0, j = 0; i < 10; i++\n\t123" 10 | ForIn: => 11 | "for(const key in object) { 123 }" becomes "for key in object\n\t123" 12 | ForOf: => 13 | "for(const value of array) { 123 }" becomes "for value of array\n\t123" 14 | ForOf_Async: => 15 | "for await(const value of array) { 123 }" becomes "for await value of array\n\t123" 16 | 17 | While: => 18 | "while(condition) { 123 }" becomes "while condition\n\t123" 19 | DoWhile: => 20 | "do { 123 } while(condition)" becomes "do\n\t123\nwhile condition" 21 | 22 | SwitchWhen: => 23 | "switch(value) { case 1: 123; break; default: break; }" becomes "switch value\n\twhen 1\n\t\t123\n\telse" 24 | "switch(value) { case 1: { break; } default: break; }" becomes "switch value\n\twhen 1\n\telse" 25 | 26 | SwitchNoWhen: => 27 | "switch(value) { case 1: default: break; }" becomes "switch value\n\tcase 1:\n\telse" 28 | 29 | SwitchElse: => 30 | "switch(value) { default: break; }" becomes "switch value\n\telse" 31 | 32 | SwitchNoElse: => 33 | "switch(value) { default: }" becomes "switch value\n\tdefault:" 34 | 35 | Break: => 36 | "break" becomes "break" 37 | "break label" becomes "break label" 38 | 39 | Continue: => 40 | "continue" becomes "continue" 41 | "continue label" becomes "continue label" 42 | 43 | If: => 44 | "if(condition) { 123 }" becomes "if condition\n\t123" 45 | If_Else: => 46 | "if(condition) { 123 } else { 321 }" becomes "if condition\n\t123\nelse\n\t321" 47 | If_ElseIf: => 48 | "if(a) { 123 } else if(b) { 321 } else { 132 }" becomes "if a\n\t123\nelse if b\n\t321\nelse\n\t132" 49 | 50 | With: => 51 | "with(object) { 123 }" becomesUnchecked "with object\n\t123" // https://github.com/DanielXMoore/Civet/issues/881 52 | 53 | Try: => 54 | "try { 123 }" becomes "try\n\t123" 55 | Try_Catch: => 56 | "try { 123 } catch(error) { 321 }" becomes "try\n\t123\ncatch error\n\t321" 57 | "try { 123 } catch { 321 }" becomes "try\n\t123\ncatch\n\t321" 58 | Try_Finally: => 59 | "try { 123 } finally { 321 }" becomes "try\n\t123\nfinally\n\t321" 60 | Try_Catch_Finally: => 61 | "try { 123 } catch(error) { 321 } finally { 213 }" becomes "try\n\t123\ncatch error\n\t321\nfinally\n\t213" 62 | "try { 123 } catch { 321 } finally { 213 }" becomes "try\n\t123\ncatch\n\t321\nfinally\n\t213" 63 | 64 | Throw: => 65 | "throw error" becomes "throw error" 66 | -------------------------------------------------------------------------------- /test/function.civet: -------------------------------------------------------------------------------- 1 | { operator becomes, operator contains, type Tests, type Options } from ./_utils.civet 2 | 3 | export options: Options := {} 4 | 5 | export tests: Tests := 6 | FunctionStatementNoop: => "function hi() {}" becomes "function hi: void" 7 | FunctionStatement: => "function hi() { return 3 }" becomes "function hi\n\treturn 3" 8 | GeneratorFunctionStatement: => "function* hi() { yield 3 }" becomes "function* hi\n\tyield 3" 9 | AsyncFunctionStatement: => "async function hi() { return 3 }" becomes "async function hi\n\treturn 3" 10 | AsyncGeneratorFunctionStatement: => "async function* hi() { yield 3 }" becomes "async function* hi\n\tyield 3" 11 | TemplateFunctionStatement: => "function hi(): T { return 1 as T }" becomes "function hi: T\n\treturn 1 as T" 12 | 13 | FunctionExpressionNoop: => "const x = function(){}" becomes "x := function: void" 14 | FunctionExpression: => "const x = function() { return 3 }" becomes "x := function\n\treturn 3" 15 | GeneratorFunctionExpression: => "const x = function*() { yield 3 }" becomes "x := function*\n\tyield 3" 16 | AsyncFunctionExpression: => "const x = async function() { return 3 }" becomes "x := async function\n\treturn 3" 17 | AsyncGeneratorFunctionExpression: => "const x = async function*() { yield 3 }" becomes "x := async function*\n\tyield 3" 18 | 19 | ConstructorDeclaration: => "class X { constructor() {} }" becomes "class X\n\t@()" 20 | MethodDeclaration: => "class X { method() {} }" becomes "class X\n\tmethod(): void" 21 | GeneratorMethodDeclaration: => "class X { *method() {} }" becomes "class X\n\t*method()" 22 | OptionalMethodDeclaration: => "class X { method?() {} }" becomes "class X\n\tmethod?(): void" 23 | MethodSignatureClass: => "class X { method(): void }" becomes "class X\n\tmethod(): void" 24 | MethodSignature: => "interface X { method(): void }" becomes "interface X\n\tmethod(): void" 25 | GetAccessor: => "class X { get getter() {} }" becomes "class X\n\tget getter(): void" 26 | SetAccessor: => "class X { set setter() {} }" becomes "class X\n\tset setter(): void" 27 | LambdaExpression: => "const x = () => 3" becomes "x := => 3" 28 | FunctionType: => 29 | "const x: () => void" becomes "const x: => void" 30 | "const x: (a: number) => void" becomes "const x: (a: number) => void" 31 | "const x: (a: T) => void" becomes "const x: (a: T) => void" 32 | ConstructorType: => "const x: new () => void" becomes "const x: new => void" 33 | InterfaceCallSignature: => "interface X { (): void }" becomes "interface X\n\t(): void" 34 | InterfaceConstructSignature: => "interface X { new (): void }" becomes "interface X\n\tnew (): void" 35 | 36 | AutoVoid: => "function hi() { 123 }" becomes "function hi: void\n\t123" 37 | AutoVoidEmptyReturn: => "function hi() { return }" becomes "function hi: void\n\treturn" 38 | AutoVoidNotTriggeredByChildren: => "function hi() { function child(){ return 123 } }" becomes "function hi: void\n\tfunction child\n\t\treturn 123" 39 | 40 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | code-block-writer: 9 | specifier: ^12.0.0 10 | version: 12.0.0 11 | glob: 12 | specifier: ^10.3.10 13 | version: 10.3.10 14 | meow: 15 | specifier: ^13.2.0 16 | version: 13.2.0 17 | typescript: 18 | specifier: ^5.3.3 19 | version: 5.3.3 20 | 21 | devDependencies: 22 | '@danielx/civet': 23 | specifier: ^0.6.83 24 | version: 0.6.83(typescript@5.3.3) 25 | '@types/node': 26 | specifier: ^20.11.24 27 | version: 20.11.24 28 | '@types/prettier': 29 | specifier: ^3.0.0 30 | version: 3.0.0 31 | c8: 32 | specifier: ^9.1.0 33 | version: 9.1.0 34 | prettier: 35 | specifier: ^3.2.5 36 | version: 3.2.5 37 | rollup: 38 | specifier: ^4.12.0 39 | version: 4.12.0 40 | 41 | packages: 42 | 43 | /@bcoe/v8-coverage@0.2.3: 44 | resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} 45 | dev: true 46 | 47 | /@cspotcode/source-map-support@0.8.1: 48 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} 49 | engines: {node: '>=12'} 50 | dependencies: 51 | '@jridgewell/trace-mapping': 0.3.9 52 | dev: true 53 | 54 | /@danielx/civet@0.6.83(typescript@5.3.3): 55 | resolution: {integrity: sha512-QtrR8oiMOa4Eia5Ef1o9FcmWM5JOAxS/+1M/sKk8tVmgzfngv3sPIitUgLblXph4pvB7wz6Vha+gEihRJpIYBA==} 56 | engines: {node: '>=19 || ^18.6.0 || ^16.17.0'} 57 | hasBin: true 58 | peerDependencies: 59 | typescript: ^4.5 || ^5.0 60 | dependencies: 61 | '@cspotcode/source-map-support': 0.8.1 62 | '@typescript/vfs': 1.5.0 63 | typescript: 5.3.3 64 | unplugin: 1.8.1 65 | transitivePeerDependencies: 66 | - supports-color 67 | dev: true 68 | 69 | /@isaacs/cliui@8.0.2: 70 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 71 | engines: {node: '>=12'} 72 | dependencies: 73 | string-width: 5.1.2 74 | string-width-cjs: /string-width@4.2.3 75 | strip-ansi: 7.1.0 76 | strip-ansi-cjs: /strip-ansi@6.0.1 77 | wrap-ansi: 8.1.0 78 | wrap-ansi-cjs: /wrap-ansi@7.0.0 79 | dev: false 80 | 81 | /@istanbuljs/schema@0.1.3: 82 | resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} 83 | engines: {node: '>=8'} 84 | dev: true 85 | 86 | /@jridgewell/resolve-uri@3.1.1: 87 | resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} 88 | engines: {node: '>=6.0.0'} 89 | dev: true 90 | 91 | /@jridgewell/sourcemap-codec@1.4.15: 92 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 93 | dev: true 94 | 95 | /@jridgewell/trace-mapping@0.3.20: 96 | resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} 97 | dependencies: 98 | '@jridgewell/resolve-uri': 3.1.1 99 | '@jridgewell/sourcemap-codec': 1.4.15 100 | dev: true 101 | 102 | /@jridgewell/trace-mapping@0.3.9: 103 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} 104 | dependencies: 105 | '@jridgewell/resolve-uri': 3.1.1 106 | '@jridgewell/sourcemap-codec': 1.4.15 107 | dev: true 108 | 109 | /@pkgjs/parseargs@0.11.0: 110 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 111 | engines: {node: '>=14'} 112 | requiresBuild: true 113 | dev: false 114 | optional: true 115 | 116 | /@rollup/rollup-android-arm-eabi@4.12.0: 117 | resolution: {integrity: sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==} 118 | cpu: [arm] 119 | os: [android] 120 | requiresBuild: true 121 | dev: true 122 | optional: true 123 | 124 | /@rollup/rollup-android-arm64@4.12.0: 125 | resolution: {integrity: sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==} 126 | cpu: [arm64] 127 | os: [android] 128 | requiresBuild: true 129 | dev: true 130 | optional: true 131 | 132 | /@rollup/rollup-darwin-arm64@4.12.0: 133 | resolution: {integrity: sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==} 134 | cpu: [arm64] 135 | os: [darwin] 136 | requiresBuild: true 137 | dev: true 138 | optional: true 139 | 140 | /@rollup/rollup-darwin-x64@4.12.0: 141 | resolution: {integrity: sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==} 142 | cpu: [x64] 143 | os: [darwin] 144 | requiresBuild: true 145 | dev: true 146 | optional: true 147 | 148 | /@rollup/rollup-linux-arm-gnueabihf@4.12.0: 149 | resolution: {integrity: sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==} 150 | cpu: [arm] 151 | os: [linux] 152 | requiresBuild: true 153 | dev: true 154 | optional: true 155 | 156 | /@rollup/rollup-linux-arm64-gnu@4.12.0: 157 | resolution: {integrity: sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==} 158 | cpu: [arm64] 159 | os: [linux] 160 | requiresBuild: true 161 | dev: true 162 | optional: true 163 | 164 | /@rollup/rollup-linux-arm64-musl@4.12.0: 165 | resolution: {integrity: sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==} 166 | cpu: [arm64] 167 | os: [linux] 168 | requiresBuild: true 169 | dev: true 170 | optional: true 171 | 172 | /@rollup/rollup-linux-riscv64-gnu@4.12.0: 173 | resolution: {integrity: sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==} 174 | cpu: [riscv64] 175 | os: [linux] 176 | requiresBuild: true 177 | dev: true 178 | optional: true 179 | 180 | /@rollup/rollup-linux-x64-gnu@4.12.0: 181 | resolution: {integrity: sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==} 182 | cpu: [x64] 183 | os: [linux] 184 | requiresBuild: true 185 | dev: true 186 | optional: true 187 | 188 | /@rollup/rollup-linux-x64-musl@4.12.0: 189 | resolution: {integrity: sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==} 190 | cpu: [x64] 191 | os: [linux] 192 | requiresBuild: true 193 | dev: true 194 | optional: true 195 | 196 | /@rollup/rollup-win32-arm64-msvc@4.12.0: 197 | resolution: {integrity: sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==} 198 | cpu: [arm64] 199 | os: [win32] 200 | requiresBuild: true 201 | dev: true 202 | optional: true 203 | 204 | /@rollup/rollup-win32-ia32-msvc@4.12.0: 205 | resolution: {integrity: sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==} 206 | cpu: [ia32] 207 | os: [win32] 208 | requiresBuild: true 209 | dev: true 210 | optional: true 211 | 212 | /@rollup/rollup-win32-x64-msvc@4.12.0: 213 | resolution: {integrity: sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==} 214 | cpu: [x64] 215 | os: [win32] 216 | requiresBuild: true 217 | dev: true 218 | optional: true 219 | 220 | /@types/estree@1.0.5: 221 | resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} 222 | dev: true 223 | 224 | /@types/istanbul-lib-coverage@2.0.6: 225 | resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} 226 | dev: true 227 | 228 | /@types/node@20.11.24: 229 | resolution: {integrity: sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==} 230 | dependencies: 231 | undici-types: 5.26.5 232 | dev: true 233 | 234 | /@types/prettier@3.0.0: 235 | resolution: {integrity: sha512-mFMBfMOz8QxhYVbuINtswBp9VL2b4Y0QqYHwqLz3YbgtfAcat2Dl6Y1o4e22S/OVE6Ebl9m7wWiMT2lSbAs1wA==} 236 | deprecated: This is a stub types definition. prettier provides its own type definitions, so you do not need this installed. 237 | dependencies: 238 | prettier: 3.2.5 239 | dev: true 240 | 241 | /@typescript/vfs@1.5.0: 242 | resolution: {integrity: sha512-AJS307bPgbsZZ9ggCT3wwpg3VbTKMFNHfaY/uF0ahSkYYrPF2dSSKDNIDIQAHm9qJqbLvCsSJH7yN4Vs/CsMMg==} 243 | dependencies: 244 | debug: 4.3.4 245 | transitivePeerDependencies: 246 | - supports-color 247 | dev: true 248 | 249 | /acorn@8.11.3: 250 | resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} 251 | engines: {node: '>=0.4.0'} 252 | hasBin: true 253 | dev: true 254 | 255 | /ansi-regex@5.0.1: 256 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 257 | engines: {node: '>=8'} 258 | 259 | /ansi-regex@6.0.1: 260 | resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} 261 | engines: {node: '>=12'} 262 | dev: false 263 | 264 | /ansi-styles@4.3.0: 265 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 266 | engines: {node: '>=8'} 267 | dependencies: 268 | color-convert: 2.0.1 269 | 270 | /ansi-styles@6.2.1: 271 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 272 | engines: {node: '>=12'} 273 | dev: false 274 | 275 | /anymatch@3.1.3: 276 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 277 | engines: {node: '>= 8'} 278 | dependencies: 279 | normalize-path: 3.0.0 280 | picomatch: 2.3.1 281 | dev: true 282 | 283 | /balanced-match@1.0.2: 284 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 285 | 286 | /binary-extensions@2.2.0: 287 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 288 | engines: {node: '>=8'} 289 | dev: true 290 | 291 | /brace-expansion@1.1.11: 292 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 293 | dependencies: 294 | balanced-match: 1.0.2 295 | concat-map: 0.0.1 296 | dev: true 297 | 298 | /brace-expansion@2.0.1: 299 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 300 | dependencies: 301 | balanced-match: 1.0.2 302 | dev: false 303 | 304 | /braces@3.0.2: 305 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 306 | engines: {node: '>=8'} 307 | dependencies: 308 | fill-range: 7.0.1 309 | dev: true 310 | 311 | /c8@9.1.0: 312 | resolution: {integrity: sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==} 313 | engines: {node: '>=14.14.0'} 314 | hasBin: true 315 | dependencies: 316 | '@bcoe/v8-coverage': 0.2.3 317 | '@istanbuljs/schema': 0.1.3 318 | find-up: 5.0.0 319 | foreground-child: 3.1.1 320 | istanbul-lib-coverage: 3.2.2 321 | istanbul-lib-report: 3.0.1 322 | istanbul-reports: 3.1.6 323 | test-exclude: 6.0.0 324 | v8-to-istanbul: 9.2.0 325 | yargs: 17.7.2 326 | yargs-parser: 21.1.1 327 | dev: true 328 | 329 | /chokidar@3.6.0: 330 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} 331 | engines: {node: '>= 8.10.0'} 332 | dependencies: 333 | anymatch: 3.1.3 334 | braces: 3.0.2 335 | glob-parent: 5.1.2 336 | is-binary-path: 2.1.0 337 | is-glob: 4.0.3 338 | normalize-path: 3.0.0 339 | readdirp: 3.6.0 340 | optionalDependencies: 341 | fsevents: 2.3.3 342 | dev: true 343 | 344 | /cliui@8.0.1: 345 | resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} 346 | engines: {node: '>=12'} 347 | dependencies: 348 | string-width: 4.2.3 349 | strip-ansi: 6.0.1 350 | wrap-ansi: 7.0.0 351 | dev: true 352 | 353 | /code-block-writer@12.0.0: 354 | resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} 355 | dev: false 356 | 357 | /color-convert@2.0.1: 358 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 359 | engines: {node: '>=7.0.0'} 360 | dependencies: 361 | color-name: 1.1.4 362 | 363 | /color-name@1.1.4: 364 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 365 | 366 | /concat-map@0.0.1: 367 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 368 | dev: true 369 | 370 | /convert-source-map@2.0.0: 371 | resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} 372 | dev: true 373 | 374 | /cross-spawn@7.0.3: 375 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 376 | engines: {node: '>= 8'} 377 | dependencies: 378 | path-key: 3.1.1 379 | shebang-command: 2.0.0 380 | which: 2.0.2 381 | 382 | /debug@4.3.4: 383 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 384 | engines: {node: '>=6.0'} 385 | peerDependencies: 386 | supports-color: '*' 387 | peerDependenciesMeta: 388 | supports-color: 389 | optional: true 390 | dependencies: 391 | ms: 2.1.2 392 | dev: true 393 | 394 | /eastasianwidth@0.2.0: 395 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 396 | dev: false 397 | 398 | /emoji-regex@8.0.0: 399 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 400 | 401 | /emoji-regex@9.2.2: 402 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 403 | dev: false 404 | 405 | /escalade@3.1.1: 406 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 407 | engines: {node: '>=6'} 408 | dev: true 409 | 410 | /fill-range@7.0.1: 411 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 412 | engines: {node: '>=8'} 413 | dependencies: 414 | to-regex-range: 5.0.1 415 | dev: true 416 | 417 | /find-up@5.0.0: 418 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 419 | engines: {node: '>=10'} 420 | dependencies: 421 | locate-path: 6.0.0 422 | path-exists: 4.0.0 423 | dev: true 424 | 425 | /foreground-child@3.1.1: 426 | resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} 427 | engines: {node: '>=14'} 428 | dependencies: 429 | cross-spawn: 7.0.3 430 | signal-exit: 4.1.0 431 | 432 | /fs.realpath@1.0.0: 433 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 434 | dev: true 435 | 436 | /fsevents@2.3.3: 437 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 438 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 439 | os: [darwin] 440 | requiresBuild: true 441 | dev: true 442 | optional: true 443 | 444 | /get-caller-file@2.0.5: 445 | resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 446 | engines: {node: 6.* || 8.* || >= 10.*} 447 | dev: true 448 | 449 | /glob-parent@5.1.2: 450 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 451 | engines: {node: '>= 6'} 452 | dependencies: 453 | is-glob: 4.0.3 454 | dev: true 455 | 456 | /glob@10.3.10: 457 | resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} 458 | engines: {node: '>=16 || 14 >=14.17'} 459 | hasBin: true 460 | dependencies: 461 | foreground-child: 3.1.1 462 | jackspeak: 2.3.6 463 | minimatch: 9.0.3 464 | minipass: 7.0.4 465 | path-scurry: 1.10.1 466 | dev: false 467 | 468 | /glob@7.2.3: 469 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 470 | dependencies: 471 | fs.realpath: 1.0.0 472 | inflight: 1.0.6 473 | inherits: 2.0.4 474 | minimatch: 3.1.2 475 | once: 1.4.0 476 | path-is-absolute: 1.0.1 477 | dev: true 478 | 479 | /has-flag@4.0.0: 480 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 481 | engines: {node: '>=8'} 482 | dev: true 483 | 484 | /html-escaper@2.0.2: 485 | resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} 486 | dev: true 487 | 488 | /inflight@1.0.6: 489 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 490 | dependencies: 491 | once: 1.4.0 492 | wrappy: 1.0.2 493 | dev: true 494 | 495 | /inherits@2.0.4: 496 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 497 | dev: true 498 | 499 | /is-binary-path@2.1.0: 500 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 501 | engines: {node: '>=8'} 502 | dependencies: 503 | binary-extensions: 2.2.0 504 | dev: true 505 | 506 | /is-extglob@2.1.1: 507 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 508 | engines: {node: '>=0.10.0'} 509 | dev: true 510 | 511 | /is-fullwidth-code-point@3.0.0: 512 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 513 | engines: {node: '>=8'} 514 | 515 | /is-glob@4.0.3: 516 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 517 | engines: {node: '>=0.10.0'} 518 | dependencies: 519 | is-extglob: 2.1.1 520 | dev: true 521 | 522 | /is-number@7.0.0: 523 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 524 | engines: {node: '>=0.12.0'} 525 | dev: true 526 | 527 | /isexe@2.0.0: 528 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 529 | 530 | /istanbul-lib-coverage@3.2.2: 531 | resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} 532 | engines: {node: '>=8'} 533 | dev: true 534 | 535 | /istanbul-lib-report@3.0.1: 536 | resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} 537 | engines: {node: '>=10'} 538 | dependencies: 539 | istanbul-lib-coverage: 3.2.2 540 | make-dir: 4.0.0 541 | supports-color: 7.2.0 542 | dev: true 543 | 544 | /istanbul-reports@3.1.6: 545 | resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} 546 | engines: {node: '>=8'} 547 | dependencies: 548 | html-escaper: 2.0.2 549 | istanbul-lib-report: 3.0.1 550 | dev: true 551 | 552 | /jackspeak@2.3.6: 553 | resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} 554 | engines: {node: '>=14'} 555 | dependencies: 556 | '@isaacs/cliui': 8.0.2 557 | optionalDependencies: 558 | '@pkgjs/parseargs': 0.11.0 559 | dev: false 560 | 561 | /locate-path@6.0.0: 562 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 563 | engines: {node: '>=10'} 564 | dependencies: 565 | p-locate: 5.0.0 566 | dev: true 567 | 568 | /lru-cache@10.1.0: 569 | resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==} 570 | engines: {node: 14 || >=16.14} 571 | dev: false 572 | 573 | /lru-cache@6.0.0: 574 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 575 | engines: {node: '>=10'} 576 | dependencies: 577 | yallist: 4.0.0 578 | dev: true 579 | 580 | /make-dir@4.0.0: 581 | resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} 582 | engines: {node: '>=10'} 583 | dependencies: 584 | semver: 7.5.4 585 | dev: true 586 | 587 | /meow@13.2.0: 588 | resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} 589 | engines: {node: '>=18'} 590 | dev: false 591 | 592 | /minimatch@3.1.2: 593 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 594 | dependencies: 595 | brace-expansion: 1.1.11 596 | dev: true 597 | 598 | /minimatch@9.0.3: 599 | resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} 600 | engines: {node: '>=16 || 14 >=14.17'} 601 | dependencies: 602 | brace-expansion: 2.0.1 603 | dev: false 604 | 605 | /minipass@7.0.4: 606 | resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} 607 | engines: {node: '>=16 || 14 >=14.17'} 608 | dev: false 609 | 610 | /ms@2.1.2: 611 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 612 | dev: true 613 | 614 | /normalize-path@3.0.0: 615 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 616 | engines: {node: '>=0.10.0'} 617 | dev: true 618 | 619 | /once@1.4.0: 620 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 621 | dependencies: 622 | wrappy: 1.0.2 623 | dev: true 624 | 625 | /p-limit@3.1.0: 626 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 627 | engines: {node: '>=10'} 628 | dependencies: 629 | yocto-queue: 0.1.0 630 | dev: true 631 | 632 | /p-locate@5.0.0: 633 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 634 | engines: {node: '>=10'} 635 | dependencies: 636 | p-limit: 3.1.0 637 | dev: true 638 | 639 | /path-exists@4.0.0: 640 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 641 | engines: {node: '>=8'} 642 | dev: true 643 | 644 | /path-is-absolute@1.0.1: 645 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 646 | engines: {node: '>=0.10.0'} 647 | dev: true 648 | 649 | /path-key@3.1.1: 650 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 651 | engines: {node: '>=8'} 652 | 653 | /path-scurry@1.10.1: 654 | resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} 655 | engines: {node: '>=16 || 14 >=14.17'} 656 | dependencies: 657 | lru-cache: 10.1.0 658 | minipass: 7.0.4 659 | dev: false 660 | 661 | /picomatch@2.3.1: 662 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 663 | engines: {node: '>=8.6'} 664 | dev: true 665 | 666 | /prettier@3.2.5: 667 | resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} 668 | engines: {node: '>=14'} 669 | hasBin: true 670 | dev: true 671 | 672 | /readdirp@3.6.0: 673 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 674 | engines: {node: '>=8.10.0'} 675 | dependencies: 676 | picomatch: 2.3.1 677 | dev: true 678 | 679 | /require-directory@2.1.1: 680 | resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} 681 | engines: {node: '>=0.10.0'} 682 | dev: true 683 | 684 | /rollup@4.12.0: 685 | resolution: {integrity: sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==} 686 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 687 | hasBin: true 688 | dependencies: 689 | '@types/estree': 1.0.5 690 | optionalDependencies: 691 | '@rollup/rollup-android-arm-eabi': 4.12.0 692 | '@rollup/rollup-android-arm64': 4.12.0 693 | '@rollup/rollup-darwin-arm64': 4.12.0 694 | '@rollup/rollup-darwin-x64': 4.12.0 695 | '@rollup/rollup-linux-arm-gnueabihf': 4.12.0 696 | '@rollup/rollup-linux-arm64-gnu': 4.12.0 697 | '@rollup/rollup-linux-arm64-musl': 4.12.0 698 | '@rollup/rollup-linux-riscv64-gnu': 4.12.0 699 | '@rollup/rollup-linux-x64-gnu': 4.12.0 700 | '@rollup/rollup-linux-x64-musl': 4.12.0 701 | '@rollup/rollup-win32-arm64-msvc': 4.12.0 702 | '@rollup/rollup-win32-ia32-msvc': 4.12.0 703 | '@rollup/rollup-win32-x64-msvc': 4.12.0 704 | fsevents: 2.3.3 705 | dev: true 706 | 707 | /semver@7.5.4: 708 | resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} 709 | engines: {node: '>=10'} 710 | hasBin: true 711 | dependencies: 712 | lru-cache: 6.0.0 713 | dev: true 714 | 715 | /shebang-command@2.0.0: 716 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 717 | engines: {node: '>=8'} 718 | dependencies: 719 | shebang-regex: 3.0.0 720 | 721 | /shebang-regex@3.0.0: 722 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 723 | engines: {node: '>=8'} 724 | 725 | /signal-exit@4.1.0: 726 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 727 | engines: {node: '>=14'} 728 | 729 | /string-width@4.2.3: 730 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 731 | engines: {node: '>=8'} 732 | dependencies: 733 | emoji-regex: 8.0.0 734 | is-fullwidth-code-point: 3.0.0 735 | strip-ansi: 6.0.1 736 | 737 | /string-width@5.1.2: 738 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 739 | engines: {node: '>=12'} 740 | dependencies: 741 | eastasianwidth: 0.2.0 742 | emoji-regex: 9.2.2 743 | strip-ansi: 7.1.0 744 | dev: false 745 | 746 | /strip-ansi@6.0.1: 747 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 748 | engines: {node: '>=8'} 749 | dependencies: 750 | ansi-regex: 5.0.1 751 | 752 | /strip-ansi@7.1.0: 753 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 754 | engines: {node: '>=12'} 755 | dependencies: 756 | ansi-regex: 6.0.1 757 | dev: false 758 | 759 | /supports-color@7.2.0: 760 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 761 | engines: {node: '>=8'} 762 | dependencies: 763 | has-flag: 4.0.0 764 | dev: true 765 | 766 | /test-exclude@6.0.0: 767 | resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} 768 | engines: {node: '>=8'} 769 | dependencies: 770 | '@istanbuljs/schema': 0.1.3 771 | glob: 7.2.3 772 | minimatch: 3.1.2 773 | dev: true 774 | 775 | /to-regex-range@5.0.1: 776 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 777 | engines: {node: '>=8.0'} 778 | dependencies: 779 | is-number: 7.0.0 780 | dev: true 781 | 782 | /typescript@5.3.3: 783 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} 784 | engines: {node: '>=14.17'} 785 | hasBin: true 786 | 787 | /undici-types@5.26.5: 788 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} 789 | dev: true 790 | 791 | /unplugin@1.8.1: 792 | resolution: {integrity: sha512-NDAvOEnZmeSRRmjfD0FoLzfve2/9lqceO5bR4J/2V72zphnFdq7UYo3fg6F1y1HfZEaSHa+7bZgbEN+z5x8ZDQ==} 793 | dependencies: 794 | acorn: 8.11.3 795 | chokidar: 3.6.0 796 | webpack-sources: 3.2.3 797 | webpack-virtual-modules: 0.6.1 798 | dev: true 799 | 800 | /v8-to-istanbul@9.2.0: 801 | resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} 802 | engines: {node: '>=10.12.0'} 803 | dependencies: 804 | '@jridgewell/trace-mapping': 0.3.20 805 | '@types/istanbul-lib-coverage': 2.0.6 806 | convert-source-map: 2.0.0 807 | dev: true 808 | 809 | /webpack-sources@3.2.3: 810 | resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} 811 | engines: {node: '>=10.13.0'} 812 | dev: true 813 | 814 | /webpack-virtual-modules@0.6.1: 815 | resolution: {integrity: sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==} 816 | dev: true 817 | 818 | /which@2.0.2: 819 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 820 | engines: {node: '>= 8'} 821 | hasBin: true 822 | dependencies: 823 | isexe: 2.0.0 824 | 825 | /wrap-ansi@7.0.0: 826 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 827 | engines: {node: '>=10'} 828 | dependencies: 829 | ansi-styles: 4.3.0 830 | string-width: 4.2.3 831 | strip-ansi: 6.0.1 832 | 833 | /wrap-ansi@8.1.0: 834 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 835 | engines: {node: '>=12'} 836 | dependencies: 837 | ansi-styles: 6.2.1 838 | string-width: 5.1.2 839 | strip-ansi: 7.1.0 840 | dev: false 841 | 842 | /wrappy@1.0.2: 843 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 844 | dev: true 845 | 846 | /y18n@5.0.8: 847 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} 848 | engines: {node: '>=10'} 849 | dev: true 850 | 851 | /yallist@4.0.0: 852 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 853 | dev: true 854 | 855 | /yargs-parser@21.1.1: 856 | resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} 857 | engines: {node: '>=12'} 858 | dev: true 859 | 860 | /yargs@17.7.2: 861 | resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} 862 | engines: {node: '>=12'} 863 | dependencies: 864 | cliui: 8.0.1 865 | escalade: 3.1.1 866 | get-caller-file: 2.0.5 867 | require-directory: 2.1.1 868 | string-width: 4.2.3 869 | y18n: 5.0.8 870 | yargs-parser: 21.1.1 871 | dev: true 872 | 873 | /yocto-queue@0.1.0: 874 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 875 | engines: {node: '>=10'} 876 | dev: true 877 | -------------------------------------------------------------------------------- /src/emitter.civet: -------------------------------------------------------------------------------- 1 | * as cbw from code-block-writer 2 | type { Options } from code-block-writer 3 | CodeBlockWriter := cbw.default as never as typeof import("code-block-writer").default 4 | ts from typescript 5 | { isParenthesizedExpression, isTypeOfExpression, SyntaxKind, NodeFlags, idText, tokenToString, forEachLeadingCommentRange, forEachTrailingCommentRange, isArrayLiteralExpression, isCallExpression, isExpression, isToken, isDefaultClause, isBlock, isFunctionLike, isBinaryExpression, isObjectLiteralExpression } := ts 6 | type { ModifierLike, Node, Statement, NodeArray, Identifier, QualifiedName, ComputedPropertyName, PrivateIdentifier, Decorator, TypeParameterDeclaration, SignatureDeclaration, CallSignatureDeclaration, ConstructSignatureDeclaration, VariableDeclaration, VariableDeclarationList, ParameterDeclaration, BindingElement, PropertySignature, PropertyDeclaration, PropertyAssignment, ShorthandPropertyAssignment, SpreadAssignment, ObjectBindingPattern, ArrayBindingPattern, FunctionLikeDeclaration, FunctionDeclaration, MethodSignature, MethodDeclaration, ConstructorDeclaration, SemicolonClassElement, GetAccessorDeclaration, SetAccessorDeclaration, IndexSignatureDeclaration, ClassStaticBlockDeclaration, ImportTypeAssertionContainer, ImportTypeNode, ThisTypeNode, FunctionOrConstructorTypeNodeBase, FunctionTypeNode, ConstructorTypeNode, TypeReferenceNode, TypePredicateNode, TypeQueryNode, TypeLiteralNode, ArrayTypeNode, TupleTypeNode, NamedTupleMember, OptionalTypeNode, RestTypeNode, UnionTypeNode, IntersectionTypeNode, ConditionalTypeNode, InferTypeNode, ParenthesizedTypeNode, TypeOperatorNode, IndexedAccessTypeNode, MappedTypeNode, LiteralTypeNode, StringLiteral, TemplateLiteralTypeNode, TemplateLiteralTypeSpan, OmittedExpression, PartiallyEmittedExpression, PrefixUnaryExpression, PostfixUnaryExpression, NullLiteral, TrueLiteral, FalseLiteral, ThisExpression, SuperExpression, ImportExpression, DeleteExpression, TypeOfExpression, VoidExpression, AwaitExpression, YieldExpression, SyntheticExpression, BinaryExpression, ConditionalExpression, FunctionExpression, ArrowFunction, RegularExpressionLiteral, NoSubstitutionTemplateLiteral, NumericLiteral, BigIntLiteral, TemplateHead, TemplateMiddle, TemplateTail, TemplateExpression, TemplateSpan, ParenthesizedExpression, ArrayLiteralExpression, SpreadElement, ObjectLiteralExpression, PropertyAccessExpression, ElementAccessExpression, CallExpression, ExpressionWithTypeArguments, NewExpression, TaggedTemplateExpression, AsExpression, TypeAssertion, SatisfiesExpression, NonNullExpression, MetaProperty, JsxElement, JsxAttributes, JsxNamespacedName, JsxOpeningElement, JsxSelfClosingElement, JsxFragment, JsxOpeningFragment, JsxClosingFragment, JsxAttribute, JsxSpreadAttribute, JsxClosingElement, JsxExpression, JsxText, NotEmittedStatement, CommaListExpression, EmptyStatement, DebuggerStatement, MissingDeclaration, Block, VariableStatement, ExpressionStatement, IfStatement, DoStatement, WhileStatement, ForStatement, ForInStatement, ForOfStatement, BreakStatement, ContinueStatement, ReturnStatement, WithStatement, SwitchStatement, CaseBlock, CaseClause, DefaultClause, LabeledStatement, ThrowStatement, TryStatement, CatchClause, ClassLikeDeclaration, ClassDeclaration, ClassExpression, InterfaceDeclaration, HeritageClause, TypeAliasDeclaration, EnumMember, EnumDeclaration, ModuleDeclaration, ModuleBlock, ImportEqualsDeclaration, ExternalModuleReference, ImportDeclaration, ImportClause, AssertEntry, AssertClause, NamespaceImport, NamespaceExport, NamespaceExportDeclaration, ExportDeclaration, NamedImports, NamedExports, ImportSpecifier, ExportSpecifier, ExportAssignment, JSDocTypeExpression, JSDocNameReference, JSDocMemberName, JSDocAllType, JSDocUnknownType, JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, JSDocFunctionType, JSDocVariadicType, JSDocNamepathType, JSDoc, JSDocLink, JSDocLinkCode, JSDocLinkPlain, JSDocText, JSDocUnknownTag, JSDocAugmentsTag, JSDocImplementsTag, JSDocAuthorTag, JSDocDeprecatedTag, JSDocClassTag, JSDocPublicTag, JSDocPrivateTag, JSDocProtectedTag, JSDocReadonlyTag, JSDocOverrideTag, JSDocEnumTag, JSDocThisTag, JSDocTemplateTag, JSDocSeeTag, JSDocReturnTag, JSDocTypeTag, JSDocTypedefTag, JSDocCallbackTag, JSDocOverloadTag, JSDocThrowsTag, JSDocSignature, JSDocPropertyTag, JSDocParameterTag, JSDocTypeLiteral, JSDocSatisfiesTag, SourceFile, Bundle, InputFiles, UnparsedSource, UnparsedPrologue, UnparsedPrepend, UnparsedTextLike, UnparsedSyntheticReference, JsonMinusNumericLiteral, SyntaxList } from typescript 7 | { StringLiteralType, stringLiteral } from ./utils.civet 8 | 9 | function TODO(node: { kind: ts.SyntaxKind }): never 10 | throw new Error `TODO: Unhandled node type: ${SyntaxKind[node.kind]}` 11 | 12 | function keyword(kind: ts.SyntaxKind): string 13 | str := tokenToString kind 14 | if str? 15 | return str 16 | else 17 | TODO { kind } 18 | 19 | function shouldInsertDo(parent: Node, child: Block): boolean 20 | parent.kind is in [SyntaxKind.SourceFile, SyntaxKind.Block, SyntaxKind.ModuleBlock, SyntaxKind.CaseBlock] or (isDefaultClause(parent) and parent.statements.indexOf(child) > 0) 21 | 22 | function isMultiline(node: any) 23 | Boolean(node.multiLine) 24 | 25 | type NodeOptions = Parameters]> extends [any, ...infer U] ? U : never 26 | export class Emitter < CodeBlockWriter 27 | ast: SourceFile 28 | @(ast: SourceFile) 29 | super 30 | useTabs: true 31 | useSingleQuote: true 32 | @ast = ast 33 | 34 | nl(): void 35 | @newLineIfLastNot() if @getLength() > 0 // dont need to start with a newline 36 | 37 | controlFlowBlock(statement: Statement, ...options: NodeOptions): void 38 | if isBlock(statement) 39 | @[SyntaxKind.Block] statement, ...options 40 | else 41 | @indent : void => 42 | @node statement, ...options 43 | 44 | modifiers(modifiers: NodeArray): void 45 | for modifier of modifiers 46 | if modifier.kind is SyntaxKind.Decorator 47 | @[SyntaxKind.Decorator] modifier 48 | @nl() 49 | else 50 | @write modifier.getText @ast 51 | @write " " 52 | 53 | private emittedComments = new Set() 54 | 55 | /** 56 | * Always use this function to emit nodes, do not directly emit through `@[SyntaxKind.___]`! This function currently also handles comments. 57 | */ 58 | node(node: Node, ...options: NodeOptions): void 59 | forEachLeadingCommentRange @ast.text, node.pos, (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean): void => 60 | if @emittedComments.has end then return 61 | @emittedComments.add end 62 | unless @isLastNewLine() 63 | @write " " 64 | @write @ast.text[pos...end].trimEnd() 65 | if hasTrailingNewLine then @nl() 66 | 67 | { kind } := node 68 | if Object.hasOwn Emitter.prototype, kind 69 | @[kind as Extract] node as any, ...options 70 | else if node.kind >= SyntaxKind.FirstKeyword and node.kind <= SyntaxKind.LastKeyword 71 | @write node.getText @ast 72 | else if isToken node 73 | @write keyword node.kind 74 | else 75 | TODO node 76 | 77 | forEachTrailingCommentRange @ast.text, node.end, (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean): void => 78 | if @emittedComments.has end then return 79 | @emittedComments.add end 80 | unless @isLastNewLine() 81 | @write " " 82 | @write @ast.text[pos...end].trimEnd() 83 | if hasTrailingNewLine then @nl() 84 | 85 | [SyntaxKind.Identifier](node: Identifier): void 86 | text := idText node 87 | @write if text is "this" then "@" else text // TODO: is this `if` necessary? (SyntaxKind.ThisKeyword) 88 | 89 | [SyntaxKind.QualifiedName](node: QualifiedName): void 90 | { left, right } := node 91 | @node left 92 | @write "." 93 | @node right 94 | 95 | [SyntaxKind.ComputedPropertyName](node: ComputedPropertyName): void 96 | if node.expression.kind is SyntaxKind.TemplateExpression 97 | @node node.expression 98 | return 99 | @write "[" 100 | @node node.expression 101 | @write "]" 102 | 103 | [SyntaxKind.PrivateIdentifier](node: PrivateIdentifier): void 104 | @write idText node 105 | 106 | [SyntaxKind.Decorator](node: Decorator): void 107 | @write "@@" // `@@` cause civet uses `@` for `this` 108 | @node node.expression 109 | 110 | [SyntaxKind.TypeParameter](node: TypeParameterDeclaration): void 111 | if node.modifiers? 112 | @modifiers node.modifiers 113 | @node node.name 114 | if node.constraint? 115 | @write " extends " 116 | @node node.constraint 117 | if node.default? 118 | @write " = " 119 | @node node.default 120 | 121 | nodeArray(nodes: NodeArray, separator: string = ", "): void 122 | for node, index of nodes 123 | if index > 0 124 | @write separator 125 | @node node 126 | 127 | // callable types - used for CallSignature, ConstructSignature, MethodSignature, FunctionType, and ConstructorType 128 | signatureDeclaration(node: SignatureDeclaration): void 129 | if "modifiers" in node and node.modifiers? 130 | @modifiers node.modifiers 131 | 132 | if node.kind is in [SyntaxKind.ConstructorType, SyntaxKind.ConstructSignature] 133 | @write "new " 134 | 135 | if node.name? 136 | @node node.name 137 | 138 | if node.typeParameters? 139 | @write "<" 140 | @nodeArray node.typeParameters 141 | @write ">" 142 | 143 | if node.parameters.length > 0 144 | @write "(" 145 | @nodeArray node.parameters 146 | @write ")" 147 | else if node.kind is not in [SyntaxKind.FunctionType, SyntaxKind.ConstructorType] 148 | @write "()" 149 | 150 | if node.kind is SyntaxKind.FunctionType or node.kind is SyntaxKind.ConstructorType 151 | @write " " if node.parameters.length > 0 152 | @write "=> " 153 | @node node.type 154 | else if node.type? 155 | @write ": " 156 | @node node.type 157 | 158 | [SyntaxKind.CallSignature](node: CallSignatureDeclaration): void 159 | @signatureDeclaration node 160 | 161 | [SyntaxKind.ConstructSignature](node: ConstructSignatureDeclaration): void 162 | @signatureDeclaration node 163 | 164 | [SyntaxKind.VariableDeclaration](node: VariableDeclaration): void 165 | decl := if node.parent.flags & NodeFlags.Const then "const" else if node.parent.flags & NodeFlags.Let then "let" else "var" 166 | if node.initializer? and decl is not "var" 167 | @node node.name 168 | if node.type? 169 | @write ": " 170 | @node node.type 171 | @write " " 172 | @write switch 173 | when node.parent.flags & NodeFlags.Const then ":" 174 | when node.parent.flags & NodeFlags.Let then "." 175 | else throw new Error "unreachable" 176 | @write "= " 177 | @node node.initializer 178 | return 179 | 180 | unless node.parent.kind is SyntaxKind.CatchClause or (node.parent.parent.kind is in [SyntaxKind.ForInStatement, SyntaxKind.ForOfStatement] and decl is "const") 181 | @write decl 182 | @write " " 183 | @node node.name 184 | if node.exclamationToken? 185 | @write "!" 186 | if node.type? 187 | @write ": " 188 | @node node.type 189 | if node.initializer? 190 | @write " = " 191 | @node node.initializer 192 | 193 | [SyntaxKind.VariableDeclarationList](node: VariableDeclarationList): void 194 | newlines := node.parent.kind is not in [SyntaxKind.ForOfStatement, SyntaxKind.ForInStatement, SyntaxKind.ForStatement] 195 | 196 | if node.declarations.length is 0 197 | return // typescript parses like this if the input file is simply "const;" 198 | 199 | if node.declarations.length is 1 200 | @nl() if newlines 201 | @node node.declarations[0] 202 | @nl() if newlines 203 | return 204 | 205 | @nl() if newlines 206 | decl := if node.flags & NodeFlags.Const then "const" else if node.flags & NodeFlags.Let then "let" else "var" 207 | @write decl 208 | @write " " 209 | for declaration, index of node.declarations 210 | if index > 0 211 | @write ", " 212 | if newlines 213 | @nl() 214 | @indent(1) 215 | @node declaration.name 216 | if declaration.type? 217 | @write ": " 218 | @node declaration.type 219 | if declaration.initializer? 220 | @write " = " 221 | @node declaration.initializer 222 | @nl() if newlines 223 | 224 | [SyntaxKind.Parameter](node: ParameterDeclaration): void 225 | if node.modifiers? 226 | @modifiers node.modifiers 227 | if node.dotDotDotToken? 228 | @write "..." 229 | @node node.name 230 | if node.questionToken? 231 | @write "?" 232 | if node.type? 233 | @write ": " 234 | @node node.type 235 | if node.initializer? 236 | @write " = " 237 | @node node.initializer 238 | 239 | [SyntaxKind.BindingElement](node: BindingElement): void 240 | if node.dotDotDotToken? 241 | @write "..." 242 | if node.propertyName? 243 | @node node.propertyName 244 | @write ": " 245 | @node node.name 246 | if node.initializer? 247 | @write " = " 248 | @node node.initializer 249 | 250 | [SyntaxKind.PropertySignature](node: PropertySignature): void 251 | if node.modifiers? 252 | @modifiers node.modifiers 253 | @node node.name 254 | if node.questionToken? 255 | @write "?" 256 | if node.type? 257 | @write ": " 258 | @node node.type 259 | 260 | [SyntaxKind.PropertyDeclaration](node: PropertyDeclaration): void 261 | @nl() 262 | if node.modifiers? 263 | @modifiers node.modifiers 264 | @node node.name 265 | if node.questionToken? 266 | @write "?" 267 | if node.type? 268 | @write ": " 269 | @node node.type 270 | if node.initializer? 271 | @write " = " 272 | @node node.initializer 273 | @nl() 274 | 275 | [SyntaxKind.PropertyAssignment](node: PropertyAssignment): void 276 | @node node.name 277 | @write ": " 278 | @node node.initializer 279 | 280 | [SyntaxKind.ShorthandPropertyAssignment](node: ShorthandPropertyAssignment): void 281 | @node node.name 282 | 283 | [SyntaxKind.SpreadAssignment](node: SpreadAssignment): void 284 | @write "..." 285 | @node node.expression 286 | 287 | [SyntaxKind.ObjectBindingPattern](node: ObjectBindingPattern): void 288 | @write "{" 289 | @nodeArray node.elements 290 | @write "}" 291 | 292 | [SyntaxKind.ArrayBindingPattern](node: ArrayBindingPattern): void 293 | @write "[" 294 | @nodeArray node.elements // TODO: multiline doesn't need commas 295 | @write "]" 296 | 297 | functionLikeDeclaration(node: FunctionLikeDeclaration): void 298 | if node.modifiers? 299 | @modifiers node.modifiers 300 | 301 | if node.kind is SyntaxKind.FunctionDeclaration or node.kind is SyntaxKind.FunctionExpression 302 | @write "function" 303 | if node.asteriskToken? 304 | @write "*" 305 | @write " " if node.name? 306 | else if node.asteriskToken? 307 | @write "*" 308 | 309 | 310 | if node.kind is SyntaxKind.Constructor 311 | @write "@" 312 | else if node.name? 313 | @node node.name 314 | 315 | if node.questionToken? 316 | @write "?" // for example: `foo?() {}` method 317 | if node.typeParameters? 318 | @write "<" 319 | @nodeArray node.typeParameters 320 | @write ">" 321 | if node.parameters.length > 0 322 | @write "(" 323 | @nodeArray node.parameters 324 | @write ")" 325 | else if node.kind is not in [SyntaxKind.ArrowFunction, SyntaxKind.FunctionDeclaration, SyntaxKind.FunctionExpression] 326 | @write "()" 327 | 328 | if node.type? 329 | @write ": " 330 | @node node.type 331 | else if node.kind is not SyntaxKind.Constructor and !node.asteriskToken? 332 | // constructors and generators never return void 333 | hasReturnValue .= node.kind is SyntaxKind.ArrowFunction and node.body.kind is not SyntaxKind.Block 334 | // TODO: is this the correct function to use? does it recurse? will it recurse into arrow functions? etc. 335 | if node.body and not hasReturnValue 336 | ts.forEachChild node.body, (child) => 337 | return true if isFunctionLike child // break - do not recurse into nested functions 338 | return false if hasReturnValue or child.kind is not SyntaxKind.ReturnStatement 339 | return hasReturnValue = true if (child as ReturnStatement).expression? 340 | @write ": void" unless hasReturnValue 341 | 342 | if node.kind is SyntaxKind.ArrowFunction 343 | @spaceIfLastNot() 344 | @write "=>" 345 | if node.body and node.body.kind is not SyntaxKind.Block 346 | @write " " 347 | 348 | if node.body? 349 | @node node.body 350 | else 351 | @nl() 352 | 353 | [SyntaxKind.FunctionDeclaration](node: FunctionDeclaration): void 354 | @functionLikeDeclaration node 355 | 356 | [SyntaxKind.MethodSignature](node: MethodSignature): void 357 | @signatureDeclaration node 358 | 359 | [SyntaxKind.MethodDeclaration](node: MethodDeclaration): void 360 | @functionLikeDeclaration node 361 | 362 | [SyntaxKind.Constructor](node: ConstructorDeclaration): void 363 | @functionLikeDeclaration node 364 | 365 | [SyntaxKind.SemicolonClassElement](node: SemicolonClassElement): void 366 | @nl() 367 | 368 | [SyntaxKind.GetAccessor](node: GetAccessorDeclaration): void 369 | @write "get " 370 | @functionLikeDeclaration node 371 | 372 | [SyntaxKind.SetAccessor](node: SetAccessorDeclaration): void 373 | @write "set " 374 | @functionLikeDeclaration node 375 | 376 | [SyntaxKind.IndexSignature](node: IndexSignatureDeclaration): void 377 | @write "[" 378 | @nodeArray node.parameters 379 | @write "]: " 380 | @node node.type 381 | 382 | [SyntaxKind.ClassStaticBlockDeclaration](node: ClassStaticBlockDeclaration): void 383 | @write "static " 384 | @node node.body 385 | 386 | [SyntaxKind.ImportTypeAssertionContainer](node: ImportTypeAssertionContainer): void 387 | TODO node // ??? 388 | 389 | [SyntaxKind.ImportType](node: ImportTypeNode): void 390 | if node.isTypeOf 391 | @write "typeof " 392 | @write "import(" 393 | @node node.argument 394 | @write ")" 395 | 396 | 397 | [SyntaxKind.ThisType](node: ThisTypeNode): void 398 | @write "this" // ??? 399 | 400 | [SyntaxKind.FunctionType](node: FunctionTypeNode): void 401 | @signatureDeclaration node 402 | 403 | [SyntaxKind.ConstructorType](node: ConstructorTypeNode): void 404 | @signatureDeclaration node 405 | 406 | [SyntaxKind.TypeReference](node: TypeReferenceNode): void 407 | @node node.typeName 408 | if node.typeArguments? 409 | @write "<" 410 | @nodeArray node.typeArguments 411 | @write ">" 412 | 413 | [SyntaxKind.TypePredicate](node: TypePredicateNode): void 414 | if node.assertsModifier? 415 | @write "asserts " 416 | @node node.parameterName 417 | if node.type? 418 | @write " is " 419 | @node node.type 420 | 421 | [SyntaxKind.TypeQuery](node: TypeQueryNode): void 422 | @write "typeof " 423 | @node node.exprName 424 | 425 | [SyntaxKind.TypeLiteral](node: TypeLiteralNode): void 426 | @nl() 427 | @indent : void => 428 | for member of node.members 429 | @node member 430 | @nl() 431 | 432 | [SyntaxKind.ArrayType](node: ArrayTypeNode): void 433 | @node node.elementType 434 | @write "[]" 435 | 436 | [SyntaxKind.TupleType](node: TupleTypeNode): void 437 | @write "[" 438 | @nodeArray node.elements 439 | @write "]" 440 | 441 | [SyntaxKind.NamedTupleMember](node: NamedTupleMember): void 442 | if node.dotDotDotToken? 443 | @write "..." 444 | @node node.name 445 | if node.questionToken? 446 | @write "?" 447 | @write ": " 448 | @node node.type 449 | 450 | [SyntaxKind.OptionalType](node: OptionalTypeNode): void 451 | @node node.type 452 | @write "?" 453 | 454 | [SyntaxKind.RestType](node: RestTypeNode): void 455 | @write "..." 456 | @node node.type 457 | 458 | [SyntaxKind.UnionType](node: UnionTypeNode): void 459 | @node node.types[0] 460 | for type of node.types[1..] 461 | @write " | " 462 | @node type 463 | 464 | [SyntaxKind.IntersectionType](node: IntersectionTypeNode): void 465 | @node node.types[0] 466 | for type of node.types[1..] 467 | @write " & " 468 | @node type 469 | 470 | [SyntaxKind.ConditionalType](node: ConditionalTypeNode): void 471 | @node node.checkType 472 | @write " extends " 473 | @node node.extendsType 474 | @write " ? " 475 | @node node.trueType 476 | @write " : " 477 | @node node.falseType 478 | 479 | [SyntaxKind.InferType](node: InferTypeNode): void 480 | @write "infer " 481 | @node node.typeParameter 482 | 483 | [SyntaxKind.ParenthesizedType](node: ParenthesizedTypeNode): void 484 | @write "(" 485 | @node node.type 486 | @write ")" 487 | 488 | [SyntaxKind.TypeOperator](node: TypeOperatorNode): void 489 | @write keyword node.operator 490 | @write " " 491 | @node node.type 492 | 493 | [SyntaxKind.IndexedAccessType](node: IndexedAccessTypeNode): void 494 | @node node.objectType 495 | @write "[" 496 | @node node.indexType 497 | @write "]" 498 | 499 | [SyntaxKind.MappedType](node: MappedTypeNode): void 500 | if node.readonlyToken? 501 | @write keyword node.readonlyToken.kind 502 | @write " " 503 | TODO node 504 | 505 | [SyntaxKind.LiteralType](node: LiteralTypeNode): void 506 | @node node.literal 507 | 508 | [SyntaxKind.StringLiteral](node: StringLiteral): void 509 | @write node.getText(@ast) // just insert original source text 510 | 511 | [SyntaxKind.TemplateLiteralType](node: TemplateLiteralTypeNode): void 512 | TODO node 513 | 514 | [SyntaxKind.TemplateLiteralTypeSpan](node: TemplateLiteralTypeSpan): void 515 | TODO node 516 | 517 | [SyntaxKind.OmittedExpression](node: OmittedExpression): void 518 | // the spaces in `[ , , , ]` 519 | @write " " 520 | 521 | [SyntaxKind.PartiallyEmittedExpression](node: PartiallyEmittedExpression): void 522 | TODO node 523 | 524 | [SyntaxKind.PrefixUnaryExpression](node: PrefixUnaryExpression): void 525 | // !(a instanceof b) => a ! 668 | @node element 669 | @nl() 670 | if index < node.elements.length - 1 and isObjectLiteralExpression(element) and @braceless element 671 | @write "," 672 | @write "]" 673 | else 674 | @write "[" 675 | @nodeArray node.elements 676 | @write "]" 677 | 678 | [SyntaxKind.SpreadElement](node: SpreadElement): void 679 | @write "..." 680 | @node node.expression 681 | 682 | braceless(node: ObjectLiteralExpression) 683 | (!isBinaryExpression(node.parent) or node.parent.operatorToken.kind is SyntaxKind.EqualsToken) 684 | and !(isArrayLiteralExpression(node.parent) and !isMultiline(node.parent)) 685 | and node.properties.length > 0 686 | and node.properties.every (prop) => prop.kind is SyntaxKind.PropertyAssignment 687 | and prop.name.kind is SyntaxKind.Identifier 688 | 689 | [SyntaxKind.ObjectLiteralExpression](node: ObjectLiteralExpression): void 690 | multiline := isMultiline node 691 | braceless := @braceless node 692 | unless braceless 693 | @write if multiline or node.properties.length is 0 then "{" else "{ " 694 | if multiline 695 | @indent : void => 696 | for property of node.properties 697 | @node property 698 | @nl() 699 | else 700 | @nodeArray node.properties 701 | unless braceless 702 | @write if multiline or node.properties.length is 0 then "}" else " }" 703 | 704 | [SyntaxKind.PropertyAccessExpression](node: PropertyAccessExpression): void 705 | if node.expression.kind is SyntaxKind.ThisKeyword and node.questionDotToken == null 706 | @write "@" // 707 | else 708 | @node node.expression 709 | if node.questionDotToken? 710 | @write "?" 711 | @write "." 712 | @node node.name 713 | 714 | [SyntaxKind.ElementAccessExpression](node: ElementAccessExpression): void 715 | @node node.expression 716 | if node.questionDotToken? 717 | @write "?" 718 | @write "[" 719 | @node node.argumentExpression 720 | @write "]" 721 | 722 | [SyntaxKind.CallExpression](node: CallExpression): void 723 | { expression, typeArguments, arguments: args, parent } := node 724 | @node expression 725 | if typeArguments? 726 | @write "<" 727 | @nodeArray typeArguments 728 | @write ">" 729 | 730 | explicit := args.length is 0 or ( 731 | isCallExpression(parent) and (parent.expression is node or parent.arguments.length is not 1) 732 | or (parent.kind is not in [SyntaxKind.CallExpression, SyntaxKind.ExpressionStatement, SyntaxKind.ReturnStatement, SyntaxKind.ArrowFunction, SyntaxKind.AwaitExpression, SyntaxKind.VariableDeclaration]) 733 | // TODO: more cases 734 | ) 735 | if node.questionDotToken 736 | @write "?" 737 | 738 | @write if explicit then "(" else " " 739 | @nodeArray args 740 | if explicit then @write ")" 741 | 742 | [SyntaxKind.ExpressionWithTypeArguments](node: ExpressionWithTypeArguments): void 743 | @node node.expression 744 | if node.typeArguments? 745 | @write "<" 746 | @nodeArray node.typeArguments 747 | @write ">" 748 | 749 | [SyntaxKind.NewExpression](node: NewExpression): void 750 | @write "new " 751 | @node node.expression 752 | if node.typeArguments? 753 | @write "<" 754 | @nodeArray node.typeArguments 755 | @write ">" 756 | @write "(" 757 | if node.arguments? 758 | @nodeArray node.arguments 759 | @write ")" 760 | 761 | [SyntaxKind.TaggedTemplateExpression](node: TaggedTemplateExpression): void 762 | @node node.tag 763 | if node.typeArguments? 764 | @write "<" 765 | @nodeArray node.typeArguments 766 | @write ">" 767 | @node node.template 768 | 769 | [SyntaxKind.AsExpression](node: AsExpression): void 770 | @node node.expression 771 | @write " as " 772 | @node node.type 773 | 774 | [SyntaxKind.TypeAssertionExpression](node: TypeAssertion): void 775 | throw new Error `Type assertions ('123') are not supported in civet and get parsed as JSX instead. Use '123 as number' instead.` 776 | @write "<" 777 | @node node.type 778 | @write ">" 779 | @node node.expression 780 | 781 | [SyntaxKind.SatisfiesExpression](node: SatisfiesExpression): void 782 | @node node.expression 783 | @write " satisfies " 784 | @node node.type 785 | 786 | [SyntaxKind.NonNullExpression](node: NonNullExpression): void 787 | @node node.expression 788 | @write "!" 789 | 790 | [SyntaxKind.MetaProperty](node: MetaProperty): void // `new.target`, `import.meta` 791 | @write keyword node.keywordToken 792 | @write "." 793 | @node node.name 794 | 795 | [SyntaxKind.JsxElement](node: JsxElement): void 796 | if @isLastNewLine() and !isExpression(node.parent) 797 | @write ";" 798 | @node node.openingElement 799 | for child of node.children 800 | @node child 801 | @node node.closingElement 802 | 803 | [SyntaxKind.JsxNamespacedName](node: JsxNamespacedName): void 804 | @node node.namespace 805 | @write ":" 806 | @node node.name 807 | 808 | [SyntaxKind.JsxOpeningElement](node: JsxOpeningElement): void 809 | @write "<" 810 | @node node.tagName 811 | if node.typeArguments? 812 | @write "<" 813 | @nodeArray node.typeArguments 814 | @write ">" 815 | @jsxAttributes node.attributes 816 | @write ">" 817 | 818 | [SyntaxKind.JsxSelfClosingElement](node: JsxSelfClosingElement): void 819 | @write "<" 820 | @node node.tagName 821 | if node.typeArguments? 822 | @write "<" 823 | @nodeArray node.typeArguments 824 | @write ">" 825 | @jsxAttributes node.attributes 826 | @write "/>" 827 | 828 | [SyntaxKind.JsxFragment](node: JsxFragment): void 829 | @node node.openingFragment 830 | for child of node.children 831 | @node child 832 | @node node.closingFragment 833 | 834 | [SyntaxKind.JsxOpeningFragment](node: JsxOpeningFragment): void 835 | @write "<>" 836 | 837 | [SyntaxKind.JsxClosingFragment](node: JsxClosingFragment): void 838 | @write "" 839 | 840 | [SyntaxKind.JsxAttribute](node: JsxAttribute): void 841 | if node.name.kind is SyntaxKind.Identifier 842 | if node.name.text is "id" 843 | @write "#" 844 | if node.initializer? 845 | @node node.initializer 846 | return 847 | else if node.name.text is "class" 848 | @write "." 849 | if node.initializer? 850 | @node node.initializer 851 | return 852 | if node.initializer == null 853 | @node node.name 854 | return 855 | if node.initializer.kind is SyntaxKind.JsxExpression and node.initializer.expression? 856 | expression := node.initializer.expression 857 | if expression.kind is SyntaxKind.TrueKeyword 858 | @write "+" 859 | @node node.name 860 | return 861 | else if expression.kind is SyntaxKind.FalseKeyword 862 | @write "-" 863 | @node node.name 864 | return 865 | @node node.name 866 | @write "=" 867 | @node node.initializer 868 | 869 | [SyntaxKind.JsxSpreadAttribute](node: JsxSpreadAttribute): void 870 | @write "..." 871 | @node node.expression 872 | 873 | [SyntaxKind.JsxClosingElement](node: JsxClosingElement): void 874 | @write "" 877 | 878 | jsxUsed = false; 879 | [SyntaxKind.JsxExpression](node: JsxExpression): void 880 | @jsxUsed = true // TODO FIX! this is like . bad ! 881 | @write "{" 882 | if node.dotDotDotToken? 883 | @write "..." 884 | if node.expression? 885 | @node node.expression 886 | @write "}" 887 | 888 | [SyntaxKind.JsxText](node: JsxText): void 889 | @write node.text 890 | 891 | jsxAttributes(attributes: JsxAttributes): void 892 | for attribute of attributes.properties 893 | @write " " 894 | @node attribute 895 | 896 | [SyntaxKind.NotEmittedStatement](node: NotEmittedStatement): void 897 | TODO node 898 | 899 | [SyntaxKind.CommaListExpression](node: CommaListExpression): void 900 | TODO node 901 | 902 | [SyntaxKind.EmptyStatement](node: EmptyStatement): void 903 | // nothing 904 | 905 | [SyntaxKind.DebuggerStatement](node: DebuggerStatement): void 906 | @nl() 907 | @write "debugger" 908 | @nl() 909 | 910 | [SyntaxKind.MissingDeclaration](node: MissingDeclaration): void 911 | TODO node 912 | 913 | [SyntaxKind.Block](node: Block, flags: Partial<{ breakBreak: true }> = {}): void 914 | if shouldInsertDo node.parent, node 915 | @write "do" 916 | @nl() 917 | @indent : void => 918 | for let index = 0; index < node.statements.length; index++ 919 | statement := node.statements[index] 920 | if flags.breakBreak and statement.kind is SyntaxKind.BreakStatement 921 | break 922 | @node statement 923 | 924 | [SyntaxKind.VariableStatement](node: VariableStatement): void 925 | @nl() 926 | if node.modifiers? 927 | @modifiers node.modifiers 928 | @node node.declarationList 929 | @nl() 930 | 931 | [SyntaxKind.ExpressionStatement](node: ExpressionStatement): void 932 | @nl() 933 | @write ";" if node.expression.kind is in [SyntaxKind.ParenthesizedExpression, SyntaxKind.ArrayLiteralExpression] 934 | @node node.expression 935 | @nl() 936 | 937 | [SyntaxKind.IfStatement](node: IfStatement): void 938 | @write "if " 939 | @node node.expression 940 | @nl() 941 | @controlFlowBlock node.thenStatement 942 | if elseStatement := node.elseStatement 943 | @write "else" 944 | if elseStatement.kind is SyntaxKind.IfStatement 945 | @write " " 946 | @node elseStatement 947 | else 948 | @nl() 949 | @controlFlowBlock elseStatement 950 | 951 | [SyntaxKind.DoStatement](node: DoStatement): void 952 | @writeLine "do" 953 | @controlFlowBlock node.statement 954 | @write "while " 955 | @node node.expression 956 | 957 | [SyntaxKind.WhileStatement](node: WhileStatement): void 958 | @write "while " 959 | @node node.expression 960 | @nl() 961 | @controlFlowBlock node.statement 962 | 963 | [SyntaxKind.ForStatement](node: ForStatement): void 964 | @write "for " 965 | if node.initializer? 966 | @node node.initializer 967 | @write ";" 968 | if node.condition? 969 | @write " " 970 | @node node.condition 971 | @write ";" 972 | if node.incrementor? 973 | @write " " 974 | @node node.incrementor 975 | @nl() 976 | @controlFlowBlock node.statement 977 | 978 | [SyntaxKind.ForInStatement](node: ForInStatement): void 979 | @write "for " 980 | @node node.initializer 981 | @write " in " 982 | @node node.expression 983 | @nl() 984 | @controlFlowBlock node.statement 985 | 986 | [SyntaxKind.ForOfStatement](node: ForOfStatement): void 987 | @write "for " 988 | if node.awaitModifier? 989 | @write "await " 990 | @node node.initializer 991 | @write " of " 992 | @node node.expression 993 | @nl() 994 | @controlFlowBlock node.statement 995 | 996 | [SyntaxKind.BreakStatement](node: BreakStatement): void 997 | @nl() 998 | @write "break" 999 | if node.label? 1000 | @write " " // TODO: civet also supports `break :label` 1001 | @node node.label 1002 | @nl() 1003 | 1004 | [SyntaxKind.ContinueStatement](node: ContinueStatement): void 1005 | @nl() 1006 | @write "continue" 1007 | if node.label? 1008 | @write " " // TODO: civet also supports `continue :label` 1009 | @node node.label 1010 | @nl() 1011 | 1012 | [SyntaxKind.ReturnStatement](node: ReturnStatement): void 1013 | @nl() 1014 | @write "return" // TODO: implicit return at the end of a function/block 1015 | if node.expression? 1016 | @write " " 1017 | @node node.expression 1018 | @nl() 1019 | 1020 | [SyntaxKind.WithStatement](node: WithStatement): void 1021 | // https://github.com/DanielXMoore/Civet/issues/881 1022 | @nl() 1023 | @write "with " 1024 | @node node.expression 1025 | @nl() 1026 | @controlFlowBlock node.statement 1027 | @nl() 1028 | 1029 | [SyntaxKind.SwitchStatement](node: SwitchStatement): void 1030 | @nl() 1031 | @write "switch " 1032 | @node node.expression 1033 | @nl() 1034 | @indent : void => 1035 | @node node.caseBlock 1036 | @nl() 1037 | 1038 | [SyntaxKind.CaseBlock](node: CaseBlock): void 1039 | @nl() 1040 | for clause of node.clauses 1041 | @node clause 1042 | @nl() 1043 | 1044 | [SyntaxKind.CaseClause](node: CaseClause): void 1045 | @nl() 1046 | firstStatement := node.statements[0] 1047 | useWhen := node.statements.length is 1 and isBlock(firstStatement) and firstStatement.statements.-1?.kind is SyntaxKind.BreakStatement or node.statements.-1?.kind is SyntaxKind.BreakStatement // this last one is a pretty aggressive transform, it doesn't 1:1 transform the code. maybe feature flag? 1048 | @write if useWhen then "when " else "case " 1049 | @node node.expression 1050 | @write ":" unless useWhen 1051 | if node.statements.length > 0 1052 | @nl() 1053 | for statement, index of node.statements 1054 | if useWhen and statement.kind is SyntaxKind.BreakStatement 1055 | break 1056 | @controlFlowBlock statement, breakBreak: true 1057 | 1058 | [SyntaxKind.DefaultClause](node: DefaultClause): void 1059 | firstStatement := node.statements.0 1060 | useElse := node.statements.length is 1 and isBlock(firstStatement) and firstStatement.statements.-1?.kind is SyntaxKind.BreakStatement or node.statements.-1?.kind is SyntaxKind.BreakStatement 1061 | @write if useElse then "else" else "default:" 1062 | if node.statements.length > 0 1063 | @nl() 1064 | for statement, index of node.statements 1065 | if useElse and statement.kind is SyntaxKind.BreakStatement 1066 | break 1067 | @controlFlowBlock statement, breakBreak: true 1068 | 1069 | [SyntaxKind.LabeledStatement](node: LabeledStatement): void 1070 | @nl() 1071 | @write ":" 1072 | @node node.label 1073 | @write " " 1074 | @node node.statement 1075 | @nl() 1076 | 1077 | [SyntaxKind.ThrowStatement](node: ThrowStatement): void 1078 | @nl() 1079 | @write "throw " 1080 | @node node.expression 1081 | @nl() 1082 | 1083 | [SyntaxKind.TryStatement](node: TryStatement): void 1084 | @nl() 1085 | @write "try" 1086 | @node node.tryBlock 1087 | if node.catchClause? 1088 | @node node.catchClause 1089 | if node.finallyBlock? and node.finallyBlock.statements.length > 0 1090 | @nl() 1091 | @write "finally" 1092 | @node node.finallyBlock 1093 | 1094 | [SyntaxKind.CatchClause](node: CatchClause): void 1095 | if node.block.statements.length is 0 1096 | return // do not print if empty, civet allows `try { }` without catch/finally 1097 | @nl() 1098 | @write "catch" 1099 | if node.variableDeclaration? 1100 | @write " " 1101 | @node node.variableDeclaration 1102 | @nl() 1103 | @node node.block 1104 | 1105 | classLikeDeclaration(node: ClassLikeDeclaration): void 1106 | if node.modifiers? 1107 | @modifiers node.modifiers 1108 | @write "class " 1109 | if node.name? 1110 | @node node.name 1111 | if node.typeParameters? 1112 | @write "<" 1113 | @nodeArray node.typeParameters 1114 | @write ">" 1115 | if node.heritageClauses? 1116 | for heritageClause of node.heritageClauses 1117 | @node heritageClause 1118 | 1119 | @indent : void => 1120 | for member of node.members 1121 | @node member 1122 | 1123 | [SyntaxKind.ClassDeclaration](node: ClassDeclaration): void 1124 | @nl() 1125 | @classLikeDeclaration node 1126 | @nl() 1127 | 1128 | [SyntaxKind.ClassExpression](node: ClassExpression): void 1129 | @classLikeDeclaration node 1130 | 1131 | [SyntaxKind.InterfaceDeclaration](node: InterfaceDeclaration): void 1132 | @nl() 1133 | if node.modifiers? 1134 | @modifiers node.modifiers 1135 | @write "interface " 1136 | @node node.name 1137 | if node.typeParameters? 1138 | @write "<" 1139 | @nodeArray node.typeParameters 1140 | @write ">" 1141 | if node.heritageClauses? 1142 | for heritageClause of node.heritageClauses 1143 | @node heritageClause 1144 | @nl() 1145 | @indent : void => 1146 | for member of node.members 1147 | @node member 1148 | @nl() 1149 | 1150 | [SyntaxKind.HeritageClause](node: HeritageClause): void 1151 | switch node.token 1152 | when SyntaxKind.ExtendsKeyword 1153 | @write " < " 1154 | when SyntaxKind.ImplementsKeyword 1155 | @write " <: " 1156 | else 1157 | throw new Error "Unknown heritage clause token: #{node.token}" 1158 | @nodeArray node.types 1159 | 1160 | [SyntaxKind.TypeAliasDeclaration](node: TypeAliasDeclaration): void 1161 | if node.modifiers? 1162 | @modifiers node.modifiers 1163 | @node node.name 1164 | if node.typeParameters? 1165 | @write "<" 1166 | @nodeArray node.typeParameters 1167 | @write ">" 1168 | @write " ::= " 1169 | @node node.type 1170 | @nl() 1171 | 1172 | [SyntaxKind.EnumMember](node: EnumMember): void 1173 | @node node.name 1174 | if node.initializer? 1175 | @write " = " 1176 | @node node.initializer 1177 | @nl() 1178 | 1179 | [SyntaxKind.EnumDeclaration](node: EnumDeclaration): void 1180 | if node.modifiers? 1181 | @modifiers node.modifiers 1182 | @write "enum " 1183 | @node node.name 1184 | @nl() 1185 | @indent : void => 1186 | for member of node.members 1187 | @node member 1188 | 1189 | [SyntaxKind.ModuleDeclaration](node: ModuleDeclaration): void 1190 | @nl() 1191 | if node.modifiers? 1192 | @modifiers node.modifiers 1193 | @write "module " 1194 | @node node.name 1195 | if node.body? 1196 | @nl() 1197 | @node node.body 1198 | @nl() 1199 | 1200 | [SyntaxKind.ModuleBlock](node: ModuleBlock): void 1201 | @indent : void => 1202 | for statement of node.statements 1203 | @node statement 1204 | 1205 | [SyntaxKind.ImportEqualsDeclaration](node: ImportEqualsDeclaration): void 1206 | @nl() 1207 | if node.modifiers? 1208 | @modifiers node.modifiers 1209 | @write "import " 1210 | @node node.name 1211 | @write " = " 1212 | @node node.moduleReference 1213 | @nl() 1214 | 1215 | [SyntaxKind.ExternalModuleReference](node: ExternalModuleReference): void 1216 | @write "require(" // TODO: check if this is correct. i have never seen this syntax before. 1217 | @node node.expression 1218 | @write ")" 1219 | 1220 | moduleSpecifier(node: Node): void 1221 | if node.kind is SyntaxKind.StringLiteral 1222 | // write string literal without quotes 1223 | @write (node as StringLiteral).text 1224 | else 1225 | @node node 1226 | 1227 | [SyntaxKind.ImportDeclaration](node: ImportDeclaration): void 1228 | @nl() 1229 | if node.modifiers? 1230 | @modifiers node.modifiers 1231 | 1232 | if node.importClause? 1233 | @node node.importClause 1234 | @write " from " 1235 | else 1236 | @write "import " 1237 | 1238 | @moduleSpecifier node.moduleSpecifier 1239 | if node.attributes? 1240 | @write " " 1241 | @node node.attributes 1242 | @nl() 1243 | 1244 | [SyntaxKind.ImportClause](node: ImportClause): void 1245 | if node.isTypeOnly 1246 | @write "type " 1247 | if node.name? 1248 | @node node.name 1249 | if node.name? and node.namedBindings? 1250 | @write ", " 1251 | if node.namedBindings? 1252 | @node node.namedBindings 1253 | 1254 | [SyntaxKind.ImportAttribute](node: AssertEntry): void 1255 | @node node.name 1256 | @write ": " 1257 | @node node.value 1258 | 1259 | [SyntaxKind.ImportAttributes](node: AssertClause): void 1260 | @write "with" 1261 | if node.multiLine 1262 | @nl() 1263 | @indent() 1264 | @indent : void => 1265 | for entry of node.elements 1266 | @node entry 1267 | @nl() 1268 | else 1269 | @write " " 1270 | @nodeArray node.elements 1271 | 1272 | [SyntaxKind.NamespaceImport](node: NamespaceImport): void 1273 | @write "* as " 1274 | @node node.name 1275 | 1276 | [SyntaxKind.NamespaceExport](node: NamespaceExport): void 1277 | @write "* as " 1278 | @node node.name 1279 | 1280 | [SyntaxKind.NamespaceExportDeclaration](node: NamespaceExportDeclaration): void 1281 | @write "export as namespace " 1282 | @node node.name 1283 | 1284 | [SyntaxKind.ExportDeclaration](node: ExportDeclaration): void 1285 | @nl() 1286 | if node.modifiers? 1287 | @modifiers node.modifiers 1288 | @write "export " 1289 | if node.isTypeOnly 1290 | @write "type " 1291 | if node.exportClause? 1292 | @node node.exportClause 1293 | else 1294 | @write "*" 1295 | if node.moduleSpecifier? 1296 | @write " from " 1297 | @moduleSpecifier node.moduleSpecifier 1298 | 1299 | if node.attributes? 1300 | @write " " 1301 | @node node.attributes 1302 | @nl() 1303 | 1304 | [SyntaxKind.NamedImports](node: NamedImports): void 1305 | @write "{ " 1306 | @nodeArray node.elements 1307 | @write " }" 1308 | 1309 | [SyntaxKind.NamedExports](node: NamedExports): void 1310 | @nodeArray node.elements 1311 | 1312 | [SyntaxKind.ImportSpecifier](node: ImportSpecifier): void 1313 | if node.isTypeOnly 1314 | @write "type " 1315 | if node.propertyName? 1316 | @node node.propertyName 1317 | @write ": " // TODO: option to keep this as `as` 1318 | @node node.name 1319 | 1320 | [SyntaxKind.ExportSpecifier](node: ExportSpecifier): void 1321 | if node.propertyName? 1322 | @node node.propertyName 1323 | if node.parent.parent.moduleSpecifier? 1324 | @write ": " 1325 | else 1326 | @write " as " // can't be :, `export x: b` => `export var x: b` 1327 | @node node.name 1328 | 1329 | [SyntaxKind.ExportAssignment](node: ExportAssignment): void 1330 | @write "export " 1331 | @write if node.isExportEquals then "= " else "default " 1332 | 1333 | [SyntaxKind.JSDocTypeExpression](node: JSDocTypeExpression): void TODO node 1334 | [SyntaxKind.JSDocNameReference](node: JSDocNameReference): void TODO node 1335 | [SyntaxKind.JSDocMemberName](node: JSDocMemberName): void TODO node 1336 | [SyntaxKind.JSDocAllType](node: JSDocAllType): void TODO node 1337 | [SyntaxKind.JSDocUnknownType](node: JSDocUnknownType): void TODO node 1338 | [SyntaxKind.JSDocNonNullableType](node: JSDocNonNullableType): void TODO node 1339 | [SyntaxKind.JSDocNullableType](node: JSDocNullableType): void TODO node 1340 | [SyntaxKind.JSDocOptionalType](node: JSDocOptionalType): void TODO node 1341 | [SyntaxKind.JSDocFunctionType](node: JSDocFunctionType): void TODO node 1342 | [SyntaxKind.JSDocVariadicType](node: JSDocVariadicType): void TODO node 1343 | [SyntaxKind.JSDocNamepathType](node: JSDocNamepathType): void TODO node 1344 | [SyntaxKind.JSDoc](node: JSDoc): void TODO node 1345 | [SyntaxKind.JSDocLink](node: JSDocLink): void TODO node 1346 | [SyntaxKind.JSDocLinkCode](node: JSDocLinkCode): void TODO node 1347 | [SyntaxKind.JSDocLinkPlain](node: JSDocLinkPlain): void TODO node 1348 | [SyntaxKind.JSDocText](node: JSDocText): void TODO node 1349 | [SyntaxKind.JSDocTag](node: JSDocUnknownTag): void TODO node 1350 | [SyntaxKind.JSDocAugmentsTag](node: JSDocAugmentsTag): void TODO node 1351 | [SyntaxKind.JSDocImplementsTag](node: JSDocImplementsTag): void TODO node 1352 | [SyntaxKind.JSDocAuthorTag](node: JSDocAuthorTag): void TODO node 1353 | [SyntaxKind.JSDocDeprecatedTag](node: JSDocDeprecatedTag): void TODO node 1354 | [SyntaxKind.JSDocClassTag](node: JSDocClassTag): void TODO node 1355 | [SyntaxKind.JSDocPublicTag](node: JSDocPublicTag): void TODO node 1356 | [SyntaxKind.JSDocPrivateTag](node: JSDocPrivateTag): void TODO node 1357 | [SyntaxKind.JSDocProtectedTag](node: JSDocProtectedTag): void TODO node 1358 | [SyntaxKind.JSDocReadonlyTag](node: JSDocReadonlyTag): void TODO node 1359 | [SyntaxKind.JSDocOverrideTag](node: JSDocOverrideTag): void TODO node 1360 | [SyntaxKind.JSDocEnumTag](node: JSDocEnumTag): void TODO node 1361 | [SyntaxKind.JSDocThisTag](node: JSDocThisTag): void TODO node 1362 | [SyntaxKind.JSDocTemplateTag](node: JSDocTemplateTag): void TODO node 1363 | [SyntaxKind.JSDocSeeTag](node: JSDocSeeTag): void TODO node 1364 | [SyntaxKind.JSDocReturnTag](node: JSDocReturnTag): void TODO node 1365 | [SyntaxKind.JSDocTypeTag](node: JSDocTypeTag): void TODO node 1366 | [SyntaxKind.JSDocTypedefTag](node: JSDocTypedefTag): void TODO node 1367 | [SyntaxKind.JSDocCallbackTag](node: JSDocCallbackTag): void TODO node 1368 | [SyntaxKind.JSDocOverloadTag](node: JSDocOverloadTag): void TODO node 1369 | [SyntaxKind.JSDocThrowsTag](node: JSDocThrowsTag): void TODO node 1370 | [SyntaxKind.JSDocSignature](node: JSDocSignature): void TODO node 1371 | [SyntaxKind.JSDocPropertyTag](node: JSDocPropertyTag): void TODO node 1372 | [SyntaxKind.JSDocParameterTag](node: JSDocParameterTag): void TODO node 1373 | [SyntaxKind.JSDocTypeLiteral](node: JSDocTypeLiteral): void TODO node 1374 | [SyntaxKind.JSDocSatisfiesTag](node: JSDocSatisfiesTag): void TODO node 1375 | [SyntaxKind.SourceFile](node: SourceFile): void 1376 | for statement of node.statements 1377 | @node statement 1378 | 1379 | [SyntaxKind.Bundle](node: Bundle): void 1380 | for sourceFile of node.sourceFiles 1381 | @node sourceFile 1382 | 1383 | [SyntaxKind.InputFiles](node: InputFiles): void 1384 | TODO node // deprecated 1385 | 1386 | [SyntaxKind.UnparsedSource](node: UnparsedSource): void TODO node 1387 | [SyntaxKind.UnparsedPrologue](node: UnparsedPrologue): void TODO node 1388 | [SyntaxKind.UnparsedPrepend](node: UnparsedPrepend): void TODO node 1389 | [SyntaxKind.UnparsedText](node: UnparsedTextLike): void TODO node 1390 | [SyntaxKind.UnparsedSyntheticReference](node: UnparsedSyntheticReference): void TODO node 1391 | [SyntaxKind.SyntaxList](node: SyntaxList): void TODO node --------------------------------------------------------------------------------