├── test ├── fixture │ ├── tsconfig.json │ ├── tsfmt │ │ ├── g │ │ │ ├── tsfmt.json │ │ │ └── main.ts │ │ ├── e │ │ │ ├── tsfmt.json │ │ │ └── main.ts │ │ ├── k │ │ │ ├── tsfmt.json │ │ │ └── main.ts │ │ ├── d │ │ │ ├── main.ts │ │ │ └── tsfmt.json │ │ ├── a │ │ │ ├── tsfmt.json │ │ │ └── main.ts │ │ ├── h │ │ │ ├── tsfmt.json │ │ │ └── main.tsx │ │ ├── j │ │ │ ├── tsfmt.json │ │ │ └── main.ts │ │ ├── f │ │ │ ├── main.ts │ │ │ └── tsfmt.json │ │ ├── i │ │ │ └── main.tsx │ │ ├── b │ │ │ ├── tsfmt.json │ │ │ └── main.ts │ │ └── c │ │ │ ├── tsfmt.json │ │ │ └── main.ts │ ├── tslint │ │ ├── whitespace-check-typecast │ │ │ ├── main.ts │ │ │ ├── tslint.json │ │ │ └── tsfmt.json │ │ ├── indent │ │ │ ├── tslint.json │ │ │ ├── main.ts │ │ │ └── tsfmt.json │ │ ├── indent-tabs │ │ │ ├── tslint.json │ │ │ └── main.ts │ │ ├── no-trailing-whitespace │ │ │ ├── main.ts │ │ │ └── tslint.json │ │ ├── no-consecutive-blank-lines │ │ │ ├── tslint.json │ │ │ └── main.ts │ │ ├── whitespace-check-branch │ │ │ ├── tslint.json │ │ │ ├── main.ts │ │ │ └── tsfmt.json │ │ ├── whitespace-check-operator │ │ │ ├── tslint.json │ │ │ ├── main.ts │ │ │ └── tsfmt.json │ │ ├── whitespace-check-separator │ │ │ ├── tslint.json │ │ │ ├── main.ts │ │ │ └── tsfmt.json │ │ ├── a │ │ │ ├── main.ts │ │ │ └── tslint.json │ │ └── b │ │ │ ├── main.ts │ │ │ └── tslint.json │ ├── editorconfig │ │ ├── insert_final_newline │ │ │ ├── main.ts │ │ │ └── .editorconfig │ │ ├── a │ │ │ ├── main.ts │ │ │ └── .editorconfig │ │ ├── tab │ │ │ ├── main.ts │ │ │ └── .editorconfig │ │ ├── space │ │ │ ├── main.ts │ │ │ └── .editorconfig │ │ ├── newline-cr │ │ │ ├── main.ts │ │ │ └── .editorconfig │ │ ├── newline-crlf │ │ │ ├── main.ts │ │ │ └── .editorconfig │ │ └── newline-lf │ │ │ ├── main.ts │ │ │ └── .editorconfig │ ├── tsconfig │ │ ├── extends │ │ │ ├── tsconfig.json │ │ │ ├── child │ │ │ │ └── tsconfig.json │ │ │ ├── tsconfig.other.json │ │ │ └── main.ts │ │ ├── a │ │ │ ├── tsconfig.json │ │ │ └── main.ts │ │ ├── lf │ │ │ ├── tsconfig.json │ │ │ └── main.ts │ │ └── crlf │ │ │ ├── tsconfig.json │ │ │ └── main.ts │ ├── specified-config │ │ ├── vscode │ │ │ ├── main.ts │ │ │ ├── .vscode │ │ │ │ └── settings.json │ │ │ └── alt-vscode-settings.json │ │ ├── tsconfig │ │ │ ├── tsconfig.json │ │ │ ├── alt-tsconfig.json │ │ │ └── main.ts │ │ ├── tslint │ │ │ ├── tslint.json │ │ │ ├── alt-tslint.json │ │ │ └── main.ts │ │ └── tsfmt │ │ │ ├── main.ts │ │ │ ├── alt-tsfmt.json │ │ │ └── tsfmt.json │ ├── vscode │ │ ├── a │ │ │ ├── main.ts │ │ │ └── .vscode │ │ │ │ └── settings.json │ │ └── b │ │ │ ├── main.ts │ │ │ └── .vscode │ │ │ └── settings.json │ ├── schemats │ │ └── main.ts │ ├── tsc-version │ │ └── decorators │ │ │ └── main.ts │ └── default │ │ └── main.ts ├── expected │ ├── tslint │ │ ├── whitespace-check-typecast │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── no-trailing-whitespace │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── no-consecutive-blank-lines │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── indent │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── indent-tabs │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── whitespace-check-branch │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── whitespace-check-separator │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── a │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── b │ │ │ ├── main.ts │ │ │ └── main.json │ │ └── whitespace-check-operator │ │ │ ├── main.ts │ │ │ └── main.json │ ├── editorconfig │ │ ├── insert_final_newline │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── newline-cr │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── a │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── tab │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── newline-lf │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── newline-crlf │ │ │ ├── main.ts │ │ │ └── main.json │ │ └── space │ │ │ ├── main.ts │ │ │ └── main.json │ ├── specified-config │ │ ├── vscode │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── tsconfig │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── tslint │ │ │ ├── main.ts │ │ │ └── main.json │ │ └── tsfmt │ │ │ ├── main.ts │ │ │ └── main.json │ ├── tsfmt │ │ ├── d │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── e │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── g │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── k │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── a │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── h │ │ │ ├── main.tsx │ │ │ └── main.json │ │ ├── f │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── i │ │ │ ├── main.tsx │ │ │ └── main.json │ │ ├── c │ │ │ ├── main.json │ │ │ └── main.ts │ │ ├── j │ │ │ └── main.json │ │ └── b │ │ │ └── main.json │ ├── vscode │ │ ├── b │ │ │ ├── main.ts │ │ │ └── main.json │ │ └── a │ │ │ ├── main.ts │ │ │ └── main.json │ ├── tsconfig │ │ ├── lf │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── a │ │ │ ├── main.ts │ │ │ └── main.json │ │ ├── extends │ │ │ ├── main.ts │ │ │ └── main.json │ │ └── crlf │ │ │ ├── main.ts │ │ │ └── main.json │ ├── schemats │ │ ├── main.ts │ │ └── main.json │ ├── default │ │ └── main.json │ └── tsc-version │ │ └── decorators │ │ ├── main.json │ │ └── main.ts └── cli │ ├── files │ ├── main.ts │ └── tsconfig.json │ ├── includeExclude │ ├── exclude.ts │ ├── include.ts │ └── tsconfig.json │ └── useTsconfig │ ├── exclude.ts │ ├── include.ts │ └── tsconfig.main.json ├── index.d.ts ├── index.js ├── bin └── tsfmt ├── .travis.yml ├── .vscode └── settings.json ├── .gitignore ├── .github └── ISSUE_TEMPLATE.md ├── example ├── index.ts ├── package.json └── tsconfig.json ├── .npmignore ├── lib ├── typings │ └── editorconfig.d.ts ├── provider │ ├── tsconfigjson.ts │ ├── editorconfig.ts │ ├── tslintjson.ts │ ├── vscodesettings.ts │ └── base.ts ├── formatter.ts ├── utils.ts ├── index.ts └── cli.ts ├── LICENSE.txt ├── tsconfig.json ├── package.json ├── _tslint.json └── README.md /test/fixture/tsconfig.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./lib"; 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./lib/"); 2 | -------------------------------------------------------------------------------- /bin/tsfmt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require("../lib/cli"); 4 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/g/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 2 3 | } 4 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-typecast/main.ts: -------------------------------------------------------------------------------- 1 | const a=5 2 | -------------------------------------------------------------------------------- /test/expected/tslint/whitespace-check-typecast/main.ts: -------------------------------------------------------------------------------- 1 | const a= 5 2 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/insert_final_newline/main.ts: -------------------------------------------------------------------------------- 1 | console.log("test"); -------------------------------------------------------------------------------- /test/expected/editorconfig/insert_final_newline/main.ts: -------------------------------------------------------------------------------- 1 | console.log("test"); 2 | -------------------------------------------------------------------------------- /test/cli/files/main.ts: -------------------------------------------------------------------------------- 1 | class TestCLI { 2 | method() { 3 | 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/extends/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./child/tsconfig" 3 | } -------------------------------------------------------------------------------- /test/fixture/tsfmt/e/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | // comment 3 | /* comment */ 4 | } 5 | -------------------------------------------------------------------------------- /test/cli/includeExclude/exclude.ts: -------------------------------------------------------------------------------- 1 | export class TestCLI { 2 | method() { 3 | } 4 | } 5 | -------------------------------------------------------------------------------- /test/cli/includeExclude/include.ts: -------------------------------------------------------------------------------- 1 | export class TestCLI { 2 | method() { 3 | } 4 | } 5 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/a/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // comment 3 | /* comment */ 4 | } 5 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/k/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "insertSpaceBeforeTypeAnnotation": true 3 | } 4 | -------------------------------------------------------------------------------- /test/fixture/specified-config/vscode/main.ts: -------------------------------------------------------------------------------- 1 | if(true===false){console.log('Hello world');} 2 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/extends/child/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.other" 3 | } -------------------------------------------------------------------------------- /test/fixture/tsfmt/g/main.ts: -------------------------------------------------------------------------------- 1 | function hello(name: string) { 2 | let str = `Hi! ${name}`; 3 | } 4 | -------------------------------------------------------------------------------- /test/expected/specified-config/vscode/main.ts: -------------------------------------------------------------------------------- 1 | if(true === false) { console.log('Hello world'); } 2 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/d/main.ts: -------------------------------------------------------------------------------- 1 | function hello(name: string) { 2 | let str = `Hi! ${name}`; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/e/main.ts: -------------------------------------------------------------------------------- 1 | function hello(name: string) { 2 | let str = `Hi! ${name}`; 3 | } 4 | -------------------------------------------------------------------------------- /test/expected/tsfmt/d/main.ts: -------------------------------------------------------------------------------- 1 | function hello(name: string) { 2 | let str = `Hi! ${ name }`; 3 | } 4 | -------------------------------------------------------------------------------- /test/expected/tsfmt/e/main.ts: -------------------------------------------------------------------------------- 1 | function hello(name: string) { 2 | let str = `Hi! ${name}`; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/a/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "indentSize": 1, 3 | "convertTabsToSpaces": true 4 | } 5 | -------------------------------------------------------------------------------- /test/expected/tsfmt/g/main.ts: -------------------------------------------------------------------------------- 1 | function hello(name: string) { 2 | let str = `Hi! ${name}`; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixture/tslint/indent/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [true, 6] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/cli/useTsconfig/exclude.ts: -------------------------------------------------------------------------------- 1 | export class Sample {hello(){console.log("Hello world");}} 2 | new Sample().hello(); -------------------------------------------------------------------------------- /test/cli/useTsconfig/include.ts: -------------------------------------------------------------------------------- 1 | export class Sample {hello(){console.log("Hello world");}} 2 | new Sample().hello(); -------------------------------------------------------------------------------- /test/fixture/tsfmt/h/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": true 3 | } 4 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/k/main.ts: -------------------------------------------------------------------------------- 1 | type Int = number; 2 | function RGBtoHSB( param1: Int, param2: Int, param3: Int ){} 3 | -------------------------------------------------------------------------------- /test/expected/tsfmt/k/main.ts: -------------------------------------------------------------------------------- 1 | type Int = number; 2 | function RGBtoHSB(param1 : Int, param2 : Int, param3 : Int) { } 3 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/extends/tsconfig.other.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "newLine": "LF" 4 | } 5 | } -------------------------------------------------------------------------------- /test/fixture/tsfmt/d/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": true 3 | } 4 | -------------------------------------------------------------------------------- /test/fixture/tslint/indent-tabs/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [true, "tabs"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixture/tslint/no-trailing-whitespace/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | test() { 3 | return ""; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 6 4 | - 8 5 | sudo: false 6 | 7 | notifications: 8 | email: true 9 | -------------------------------------------------------------------------------- /test/fixture/specified-config/tsconfig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "newLine": "CRLF" 4 | } 5 | } -------------------------------------------------------------------------------- /test/fixture/specified-config/tslint/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [true, "spaces"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/j/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "indentSize": 6, 3 | "tabSize": 8, 4 | "convertTabsToSpaces": true 5 | } 6 | -------------------------------------------------------------------------------- /test/expected/tslint/no-trailing-whitespace/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | test() { 3 | return ""; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixture/specified-config/tsconfig/alt-tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "newLine": "LF" 4 | } 5 | } -------------------------------------------------------------------------------- /test/fixture/specified-config/tslint/alt-tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [true, "tabs"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/tslint/no-trailing-whitespace/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-trailing-whitespace": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/expected/editorconfig/newline-cr/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { hello(word = "world") { return "Hello, " + word; } } var s = new Sample(); -------------------------------------------------------------------------------- /test/expected/tslint/no-consecutive-blank-lines/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | 3 | test() { 4 | return ""; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/tab/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | -------------------------------------------------------------------------------- /test/expected/editorconfig/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word = "world") { return "Hello, " + word; } 3 | } 4 | 5 | var s = new Sample(); 6 | -------------------------------------------------------------------------------- /test/expected/tsfmt/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word = "world") { return "Hello, " + word; } 3 | } 4 | 5 | var s = new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/space/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/lf/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "newLine": "LF" 4 | }, 5 | "files": [ 6 | "main.ts" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixture/tslint/no-consecutive-blank-lines/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-consecutive-blank-lines": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/newline-cr/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/newline-crlf/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/newline-lf/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/specified-config/vscode/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": true 3 | } 4 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/crlf/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "newLine": "CRLF" 4 | }, 5 | "files": [ 6 | "main.ts" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/expected/editorconfig/tab/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word = "world") { return "Hello, " + word; } 3 | } 4 | 5 | var s = new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/specified-config/vscode/alt-vscode-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": false 3 | } 4 | -------------------------------------------------------------------------------- /test/expected/editorconfig/newline-lf/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word = "world") { return "Hello, " + word; } 3 | } 4 | 5 | var s = new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/h/main.tsx: -------------------------------------------------------------------------------- 1 | class MyComponent { 2 | props: { 3 | foo?: string; 4 | } 5 | } 6 | 7 | let str = "str"; 8 | ; 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "typescript.tsdk": "./node_modules/typescript/lib/" 4 | } -------------------------------------------------------------------------------- /test/expected/editorconfig/newline-crlf/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word = "world") { return "Hello, " + word; } 3 | } 4 | 5 | var s = new Sample(); 6 | -------------------------------------------------------------------------------- /test/expected/editorconfig/space/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word = "world") { return "Hello, " + word; } 3 | } 4 | 5 | var s = new Sample(); 6 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-branch/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "whitespace": [true, 4 | "check-branch" 5 | ] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-operator/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "whitespace": [true, 4 | "check-operator" 5 | ] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-typecast/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "whitespace": [true, 4 | "check-typecast" 5 | ] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/expected/tsfmt/h/main.tsx: -------------------------------------------------------------------------------- 1 | class MyComponent { 2 | props: { 3 | foo?: string; 4 | } 5 | } 6 | 7 | let str = "str"; 8 | ; 9 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-separator/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "whitespace": [true, 4 | "check-separator" 5 | ] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/expected/tslint/indent/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world") { return "Hello, "+word; } 3 | } 4 | 5 | var s=new Sample(); 6 | if(s===s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/fixture/tslint/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tslint/b/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tslint/indent/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tslint/no-consecutive-blank-lines/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | 3 | 4 | 5 | 6 | test() { 7 | return ""; 8 | } 9 | } 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/fixture/vscode/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/vscode/b/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/crlf/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/lf/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tslint/indent-tabs/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-branch/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-operator/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-separator/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world"){return "Hello, " + word;} 3 | } 4 | 5 | var s=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/expected/tslint/indent-tabs/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word = "world") { return "Hello, " + word; } 3 | } 4 | 5 | var s = new Sample(); 6 | if (s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/fixture/tsconfig/extends/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/expected/vscode/b/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word: string="world"): string {return "Hello, "+word;} 3 | } 4 | 5 | var s: Sample=new Sample(); 6 | if(s===s) {console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/specified-config/tsfmt/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/fixture/specified-config/tslint/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/expected/tslint/whitespace-check-branch/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world") { return "Hello, "+word; } 3 | } 4 | 5 | var s=new Sample(); 6 | if (s===s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/tslint/whitespace-check-separator/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word="world") { return "Hello, "+word; } 3 | } 4 | 5 | var s=new Sample(); 6 | if(s===s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/insert_final_newline/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | insert_final_newline=true 8 | -------------------------------------------------------------------------------- /test/fixture/specified-config/tsconfig/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word:string="world"):string{return "Hello, " + word;} 3 | } 4 | 5 | var s:Sample=new Sample(); 6 | if(s===s){console.log(s.hello());} 7 | -------------------------------------------------------------------------------- /test/expected/tsconfig/lf/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word: string = "world"): string { return "Hello, " + word; } 3 | } 4 | 5 | var s: Sample = new Sample(); 6 | if (s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/tsconfig/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word: string = "world"): string { return "Hello, " + word; } 3 | } 4 | 5 | var s: Sample = new Sample(); 6 | if (s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/tsconfig/extends/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word: string = "world"): string { return "Hello, " + word; } 3 | } 4 | 5 | var s: Sample = new Sample(); 6 | if (s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/tslint/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word: string = "world"): string { return "Hello, " + word; } 3 | } 4 | 5 | var s: Sample = new Sample(); 6 | if (s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/tslint/b/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word: string = "world"): string { return "Hello, " + word; } 3 | } 4 | 5 | var s: Sample = new Sample(); 6 | if (s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/tslint/whitespace-check-operator/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word = "world") { return "Hello, " + word; } 3 | } 4 | 5 | var s = new Sample(); 6 | if(s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/tsconfig/crlf/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word: string = "world"): string { return "Hello, " + word; } 3 | } 4 | 5 | var s: Sample = new Sample(); 6 | if (s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/specified-config/tsconfig/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word: string = "world"): string { return "Hello, " + word; } 3 | } 4 | 5 | var s: Sample = new Sample(); 6 | if (s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/specified-config/tslint/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | hello(word: string = "world"): string { return "Hello, " + word; } 3 | } 4 | 5 | var s: Sample = new Sample(); 6 | if (s === s) { console.log(s.hello()); } 7 | -------------------------------------------------------------------------------- /test/expected/vscode/a/main.ts: -------------------------------------------------------------------------------- 1 | class Sample 2 | { 3 | hello ( word: string = "world" ): string { return "Hello, " + word; } 4 | } 5 | 6 | var s: Sample = new Sample(); 7 | if ( s === s ) { console.log( s.hello() ); } 8 | -------------------------------------------------------------------------------- /test/expected/specified-config/tsfmt/main.ts: -------------------------------------------------------------------------------- 1 | class Sample 2 | { 3 | hello( word: string = "world" ): string { return "Hello, " + word; } 4 | } 5 | 6 | var s: Sample = new Sample(); 7 | if ( s === s ) { console.log( s.hello() ); } 8 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/f/main.ts: -------------------------------------------------------------------------------- 1 | class Sample{ 2 | constructor(){} 3 | } 4 | 5 | if(true){} 6 | if(true){console.log("test");} 7 | 8 | let a:string|null=null as any; 9 | let b:string|null=null; 10 | 11 | function(){} 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | 3 | node_modules/ 4 | typings/ 5 | .tscache/ 6 | 7 | npm-debug.log 8 | 9 | lib/**/*.js 10 | lib/**/*.js.map 11 | lib/**/*.d.ts 12 | test/**/*.js 13 | test/**/*.js.map 14 | test/**/*.d.ts 15 | example/*.js 16 | 17 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/f/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "insertSpaceAfterConstructor": true, 3 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false, 4 | "insertSpaceAfterTypeAssertion": true, 5 | "insertSpaceBeforeFunctionParenthesis": true 6 | } 7 | -------------------------------------------------------------------------------- /test/expected/tsfmt/f/main.ts: -------------------------------------------------------------------------------- 1 | class Sample { 2 | constructor () {} 3 | } 4 | 5 | if (true) {} 6 | if (true) {console.log("test");} 7 | 8 | let a: string | null = null as any; 9 | let b: string | null = null; 10 | 11 | function() {} 12 | -------------------------------------------------------------------------------- /test/expected/tsfmt/i/main.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | I am a lightbox! 4 | 5 | 6 | Close Me! 7 | 8 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/tab/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | indent_style = tab 9 | tab_width = 8 10 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/newline-cr/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = cr 9 | charset = utf-8 10 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/newline-lf/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | charset = utf-8 10 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/space/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | indent_style = space 9 | indent_size = 8 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /test/cli/useTsconfig/tsconfig.main.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "noImplicitAny": false, 6 | "sourceMap": false 7 | }, 8 | "files": [ 9 | "include.ts" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/newline-crlf/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = crlf 9 | charset = utf-8 10 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/i/main.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | I am a lightbox! 4 | 5 | 6 | Close Me! 7 | 8 | -------------------------------------------------------------------------------- /test/cli/files/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": false, 6 | "noImplicitAny": true, 7 | "removeComments": false, 8 | "noLib": false 9 | }, 10 | "files": [ 11 | "./main.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /example/index.ts: -------------------------------------------------------------------------------- 1 | import * as tsfmt from "typescript-formatter"; 2 | 3 | tsfmt 4 | .processFiles(["./index.ts"], { 5 | dryRun: true, 6 | replace: false, 7 | verify: false, 8 | tsconfig: true, 9 | tslint: true, 10 | editorconfig: true, 11 | tsfmt: true 12 | }) 13 | .then(result =>{ 14 | console.log(result["./index.ts"].dest); 15 | }); 16 | -------------------------------------------------------------------------------- /test/fixture/editorconfig/a/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | indent_style = tab 9 | tab_width = 2 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .github/ 3 | 4 | # for npm 5 | node_modules/ 6 | npm-shrinkwrap.json 7 | yarn.lock 8 | 9 | # codes 10 | test/ 11 | 12 | # for https://github.com/Microsoft/TypeScript/issues/4667 13 | lib/**/*.ts 14 | !lib/**/*.d.ts 15 | 16 | # misc 17 | .vscode/ 18 | .gitignore 19 | .editorconfig 20 | .travis.yml 21 | circle.yml 22 | Gruntfile.js 23 | _tslint.json 24 | 25 | test-results.xml 26 | npm-debug.log 27 | -------------------------------------------------------------------------------- /test/cli/includeExclude/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": false, 6 | "noImplicitAny": true, 7 | "removeComments": false, 8 | "noLib": false 9 | }, 10 | "include": [ 11 | "./*.ts" 12 | ], 13 | "exclude": [ 14 | "./exclude.ts", 15 | "./*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "use-typescript-formatter-api-sample", 3 | "private": true, 4 | "version": "0.0.1", 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": { 8 | "build": "tsc -p ./", 9 | "exec": "node index", 10 | "test": "npm run build && npm run exec" 11 | }, 12 | "author": "vvakame+dev@gmail.com", 13 | "license": "MIT", 14 | "dependencies": { 15 | "typescript-formatter": "^3.0.0", 16 | "typescript": "^2.0.0" 17 | }, 18 | "devDependencies": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/fixture/tslint/indent/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "insertSpaceAfterCommaDelimiter": false, 3 | "insertSpaceAfterSemicolonInForStatements": false, 4 | "insertSpaceBeforeAndAfterBinaryOperators": false, 5 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 6 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 7 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 8 | "placeOpenBraceOnNewLineForFunctions": false, 9 | "placeOpenBraceOnNewLineForControlBlocks": false 10 | } 11 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-branch/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "insertSpaceAfterCommaDelimiter": false, 3 | "insertSpaceAfterSemicolonInForStatements": false, 4 | "insertSpaceBeforeAndAfterBinaryOperators": false, 5 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 6 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 7 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 8 | "placeOpenBraceOnNewLineForFunctions": false, 9 | "placeOpenBraceOnNewLineForControlBlocks": false 10 | } 11 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-operator/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "insertSpaceAfterCommaDelimiter": false, 3 | "insertSpaceAfterSemicolonInForStatements": false, 4 | "insertSpaceBeforeAndAfterBinaryOperators": false, 5 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 6 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 7 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 8 | "placeOpenBraceOnNewLineForFunctions": false, 9 | "placeOpenBraceOnNewLineForControlBlocks": false 10 | } 11 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-separator/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "insertSpaceAfterCommaDelimiter": false, 3 | "insertSpaceAfterSemicolonInForStatements": false, 4 | "insertSpaceBeforeAndAfterBinaryOperators": false, 5 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 6 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 7 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 8 | "placeOpenBraceOnNewLineForFunctions": false, 9 | "placeOpenBraceOnNewLineForControlBlocks": false 10 | } 11 | -------------------------------------------------------------------------------- /test/fixture/tslint/whitespace-check-typecast/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "insertSpaceAfterCommaDelimiter": false, 3 | "insertSpaceAfterSemicolonInForStatements": false, 4 | "insertSpaceBeforeAndAfterBinaryOperators": false, 5 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 6 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 7 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 8 | "placeOpenBraceOnNewLineForFunctions": false, 9 | "placeOpenBraceOnNewLineForControlBlocks": false 10 | } 11 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "lib": [ 6 | "es2015" 7 | ], 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noEmitOnError": true, 11 | "noImplicitReturns": true, 12 | "noImplicitThis": true, 13 | "noUnusedLocals": true, 14 | "noUnusedParameters": true, 15 | "sourceMap": false, 16 | "listFiles": true 17 | }, 18 | "exclude": [ 19 | "node_modules" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /test/expected/schemats/main.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * AUTO-GENERATED FILE @ 2016-12-07 13:17:46 - DO NOT EDIT! 3 | * 4 | * This file was generated with schemats node package: 5 | * $ schemats generate -c postgres://username:password@localhost/test -t users -o ./test/osm.ts 6 | * 7 | * Re-run the command above. 8 | */ 9 | 10 | 11 | export namespace cta_situationcompte_scoFields { 12 | export type sco_id = number; 13 | export type sco_total_debit = number; 14 | export type sco_total_credit = number; 15 | export type sco_nb_ecritures = number; 16 | export type pst_id = number; 17 | export type cpt_id = number; 18 | 19 | } -------------------------------------------------------------------------------- /test/fixture/tsfmt/b/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "indentSize": 8, 3 | "tabSize": 8, 4 | "newLineCharacter": "/* \n */", 5 | "convertTabsToSpaces": false, 6 | "insertSpaceAfterCommaDelimiter": false, 7 | "insertSpaceAfterSemicolonInForStatements": false, 8 | "insertSpaceBeforeAndAfterBinaryOperators": false, 9 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 10 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": true, 11 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true, 12 | "placeOpenBraceOnNewLineForFunctions": true, 13 | "placeOpenBraceOnNewLineForControlBlocks": true 14 | } 15 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/c/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "indentSize": 4, 3 | "indentStyle": "None", 4 | "tabSize": 4, 5 | "newLineCharacter": "\n", 6 | "convertTabsToSpaces": false, 7 | "insertSpaceAfterCommaDelimiter": false, 8 | "insertSpaceAfterSemicolonInForStatements": false, 9 | "insertSpaceBeforeAndAfterBinaryOperators": false, 10 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 11 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": true, 12 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true, 13 | "placeOpenBraceOnNewLineForFunctions": true, 14 | "placeOpenBraceOnNewLineForControlBlocks": true 15 | } 16 | -------------------------------------------------------------------------------- /test/fixture/schemats/main.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * AUTO-GENERATED FILE @ 2016-12-07 13:17:46 - DO NOT EDIT! 3 | * 4 | * This file was generated with schemats node package: 5 | * $ schemats generate -c postgres://username:password@localhost/test -t users -o ./test/osm.ts 6 | * 7 | * Re-run the command above. 8 | */ 9 | 10 | 11 | export namespace cta_situationcompte_scoFields { 12 | export type sco_id = number; 13 | export type sco_total_debit = number; 14 | export type sco_total_credit = number; 15 | export type sco_nb_ecritures = number; 16 | export type pst_id = number; 17 | export type cpt_id = number; 18 | 19 | } -------------------------------------------------------------------------------- /test/fixture/specified-config/tsfmt/alt-tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "indentSize": 4, 3 | "tabSize": 4, 4 | "indentStyle": 2, 5 | "newLineCharacter": "\n", 6 | "convertTabsToSpaces": true, 7 | "insertSpaceAfterCommaDelimiter": true, 8 | "insertSpaceAfterSemicolonInForStatements": true, 9 | "insertSpaceBeforeAndAfterBinaryOperators": true, 10 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 11 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": true, 12 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true, 13 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true, 14 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": true, 15 | "placeOpenBraceOnNewLineForFunctions": true, 16 | "placeOpenBraceOnNewLineForControlBlocks": true 17 | } -------------------------------------------------------------------------------- /lib/typings/editorconfig.d.ts: -------------------------------------------------------------------------------- 1 | declare module "editorconfig" { 2 | export interface FileInfo { 3 | indent_style?: string; 4 | indent_size?: number; 5 | tab_width?: number; 6 | end_of_line?: string; 7 | charset?: string; 8 | trim_trailing_whitespace?: boolean; 9 | insert_final_newline?: boolean; 10 | root?: string; 11 | } 12 | 13 | export interface ParseOptions { 14 | /* config file name. default: .editorconfig */ 15 | config: string; 16 | version: any; // string or Version 17 | } 18 | 19 | export function parseFromFiles(filepath: string, files: any[], options?: ParseOptions): Promise; 20 | 21 | export function parse(filepath: string, options?: ParseOptions): Promise; 22 | } 23 | -------------------------------------------------------------------------------- /test/fixture/specified-config/tsfmt/tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "indentSize": 4, 3 | "tabSize": 4, 4 | "indentStyle": 2, 5 | "newLineCharacter": "\r\n", 6 | "convertTabsToSpaces": false, 7 | "insertSpaceAfterCommaDelimiter": false, 8 | "insertSpaceAfterSemicolonInForStatements": false, 9 | "insertSpaceBeforeAndAfterBinaryOperators": false, 10 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 11 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 12 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 13 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 15 | "placeOpenBraceOnNewLineForFunctions": false, 16 | "placeOpenBraceOnNewLineForControlBlocks": false 17 | } -------------------------------------------------------------------------------- /test/expected/vscode/a/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": true, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": true, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": true, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": true, 19 | "insertSpaceAfterTypeAssertion": true, 20 | "insertSpaceBeforeFunctionParenthesis": true, 21 | "placeOpenBraceOnNewLineForFunctions": true, 22 | "placeOpenBraceOnNewLineForControlBlocks": true, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/f/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": true, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": true, 20 | "insertSpaceBeforeFunctionParenthesis": true, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/default/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/schemats/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsconfig/a/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsconfig/lf/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/a/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 1, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/c/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 0, 6 | "newLineCharacter": "\n", 7 | "convertTabsToSpaces": false, 8 | "insertSpaceAfterCommaDelimiter": false, 9 | "insertSpaceAfterSemicolonInForStatements": false, 10 | "insertSpaceBeforeAndAfterBinaryOperators": false, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": true, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": true, 22 | "placeOpenBraceOnNewLineForControlBlocks": true, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/d/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": true, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/e/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/g/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 2, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/h/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": true, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/i/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/j/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 6, 4 | "tabSize": 8, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/k/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": true 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/a/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/b/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/editorconfig/a/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\n", 7 | "convertTabsToSpaces": false, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/specified-config/tsfmt/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": true, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": true, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": true, 22 | "placeOpenBraceOnNewLineForControlBlocks": true, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsconfig/crlf/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsconfig/extends/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsfmt/b/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 8, 4 | "tabSize": 8, 5 | "indentStyle": 2, 6 | "newLineCharacter": "/* \n */", 7 | "convertTabsToSpaces": false, 8 | "insertSpaceAfterCommaDelimiter": false, 9 | "insertSpaceAfterSemicolonInForStatements": false, 10 | "insertSpaceBeforeAndAfterBinaryOperators": false, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": true, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": true, 22 | "placeOpenBraceOnNewLineForControlBlocks": true, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/vscode/b/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": false, 9 | "insertSpaceAfterSemicolonInForStatements": false, 10 | "insertSpaceBeforeAndAfterBinaryOperators": false, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright © 2015 Masahiro Wakame 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the “Software”), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/expected/editorconfig/space/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 8, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/editorconfig/tab/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": false, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/indent-tabs/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": false, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/indent/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": false, 9 | "insertSpaceAfterSemicolonInForStatements": false, 10 | "insertSpaceBeforeAndAfterBinaryOperators": false, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/editorconfig/newline-cr/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/editorconfig/newline-crlf/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/editorconfig/newline-lf/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/specified-config/tsconfig/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/specified-config/tslint/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": false, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/specified-config/vscode/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tsc-version/decorators/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/no-trailing-whitespace/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/editorconfig/insert_final_newline/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/no-consecutive-blank-lines/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/whitespace-check-branch/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": false, 9 | "insertSpaceAfterSemicolonInForStatements": false, 10 | "insertSpaceBeforeAndAfterBinaryOperators": false, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/whitespace-check-operator/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": false, 9 | "insertSpaceAfterSemicolonInForStatements": false, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/whitespace-check-separator/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": false, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /test/expected/tslint/whitespace-check-typecast/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\r\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": false, 9 | "insertSpaceAfterSemicolonInForStatements": false, 10 | "insertSpaceBeforeAndAfterBinaryOperators": false, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": false, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": true, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "placeOpenBraceOnNewLineForFunctions": false, 22 | "placeOpenBraceOnNewLineForControlBlocks": false, 23 | "insertSpaceBeforeTypeAnnotation": false 24 | } -------------------------------------------------------------------------------- /lib/provider/tsconfigjson.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "typescript"; 2 | 3 | import * as path from "path"; 4 | 5 | import { Options } from "../"; 6 | import { getConfigFileName, readTsconfig } from "../utils"; 7 | 8 | export function makeFormatCodeOptions(fileName: string, opts: Options, formatSettings: ts.FormatCodeSettings): ts.FormatCodeSettings { 9 | 10 | let baseDir = opts.baseDir ? path.resolve(opts.baseDir) : path.dirname(path.resolve(fileName)); 11 | let configFileName: string | null; 12 | if (opts.tsconfigFile && path.isAbsolute(opts.tsconfigFile)) { 13 | configFileName = opts.tsconfigFile; 14 | } else { 15 | configFileName = getConfigFileName(baseDir, opts.tsconfigFile || "tsconfig.json"); 16 | } 17 | if (!configFileName) { 18 | return formatSettings; 19 | } 20 | if (opts.verbose) { 21 | console.log(`read ${configFileName} for ${fileName}`); 22 | } 23 | 24 | let parsed = readTsconfig(configFileName); 25 | if (parsed.options.newLine === ts.NewLineKind.CarriageReturnLineFeed) { 26 | formatSettings.newLineCharacter = "\r\n"; 27 | } else if (parsed.options.newLine === ts.NewLineKind.LineFeed) { 28 | formatSettings.newLineCharacter = "\n"; 29 | } 30 | 31 | return formatSettings; 32 | } 33 | -------------------------------------------------------------------------------- /test/fixture/vscode/a/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // comment 3 | "typescript.format.enable": true, 4 | "typescript.format.insertSpaceAfterCommaDelimiter": true, 5 | "typescript.format.insertSpaceAfterConstructor": true, 6 | "typescript.format.insertSpaceAfterSemicolonInForStatements": true, 7 | "typescript.format.insertSpaceBeforeAndAfterBinaryOperators": true, 8 | "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": true, 9 | "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": true, 10 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true, 11 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true, 12 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 13 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": true, 14 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": true, 15 | "typescript.format.insertSpaceAfterTypeAssertion": true, 16 | "typescript.format.insertSpaceBeforeFunctionParenthesis": true, 17 | "typescript.format.placeOpenBraceOnNewLineForFunctions": true, 18 | "typescript.format.placeOpenBraceOnNewLineForControlBlocks": true 19 | } -------------------------------------------------------------------------------- /test/fixture/vscode/b/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // comment 3 | "typescript.format.enable": false, 4 | "typescript.format.insertSpaceAfterCommaDelimiter": false, 5 | "typescript.format.insertSpaceAfterConstructor": false, 6 | "typescript.format.insertSpaceAfterSemicolonInForStatements": false, 7 | "typescript.format.insertSpaceBeforeAndAfterBinaryOperators": false, 8 | "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": false, 9 | "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 10 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 11 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 12 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false, 13 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 14 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 15 | "typescript.format.insertSpaceAfterTypeAssertion": false, 16 | "typescript.format.insertSpaceBeforeFunctionParenthesis": false, 17 | "typescript.format.placeOpenBraceOnNewLineForFunctions": false, 18 | "typescript.format.placeOpenBraceOnNewLineForControlBlocks": false 19 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "moduleResolution": "node", 5 | "target": "es5", 6 | "lib": [ 7 | "dom", 8 | "es2017" 9 | ], 10 | "types": [ 11 | "node", 12 | "mocha" 13 | ], 14 | "noImplicitAny": true, 15 | "strictNullChecks": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "noImplicitReturns": true, 18 | "noImplicitThis": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "experimentalDecorators": true, 22 | "forceConsistentCasingInFileNames": true, 23 | "stripInternal": true, 24 | "skipDefaultLibCheck": true, 25 | "skipLibCheck": false, 26 | "rootDir": ".", 27 | "sourceMap": true, 28 | "declaration": true, 29 | "listFiles": false, 30 | "traceResolution": false, 31 | "newLine": "LF", 32 | "noEmitOnError": true, 33 | "inlineSources": true, 34 | "listEmittedFiles": false 35 | }, 36 | "include": [ 37 | "lib/**/*.ts", 38 | "test/**/*.ts" 39 | ], 40 | "exclude": [ 41 | "node_modules", 42 | "lib/*.d.ts", 43 | "lib/provider/*.d.ts", 44 | "test/cli", 45 | "test/expected", 46 | "test/fixture", 47 | "example" 48 | ] 49 | } -------------------------------------------------------------------------------- /lib/formatter.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "typescript"; 2 | 3 | import { createDefaultFormatCodeSettings } from "./utils"; 4 | 5 | class LanguageServiceHost implements ts.LanguageServiceHost { 6 | files: ts.MapLike = {}; 7 | addFile(fileName: string, text: string) { 8 | this.files[fileName] = ts.ScriptSnapshot.fromString(text); 9 | } 10 | 11 | // for ts.LanguageServiceHost 12 | 13 | getCompilationSettings = () => ts.getDefaultCompilerOptions(); 14 | getScriptFileNames = () => Object.keys(this.files); 15 | getScriptVersion = (_fileName: string) => "0"; 16 | getScriptSnapshot = (fileName: string) => this.files[fileName]; 17 | getCurrentDirectory = () => process.cwd(); 18 | getDefaultLibFileName = (options: ts.CompilerOptions) => ts.getDefaultLibFilePath(options); 19 | } 20 | 21 | export function format(fileName: string, text: string, options = createDefaultFormatCodeSettings()) { 22 | const host = new LanguageServiceHost(); 23 | host.addFile(fileName, text); 24 | 25 | const languageService = ts.createLanguageService(host); 26 | const edits = languageService.getFormattingEditsForDocument(fileName, options); 27 | edits 28 | .sort((a, b) => a.span.start - b.span.start) 29 | .reverse() 30 | .forEach(edit => { 31 | const head = text.slice(0, edit.span.start); 32 | const tail = text.slice(edit.span.start + edit.span.length); 33 | text = `${head}${edit.newText}${tail}`; 34 | }); 35 | 36 | return text; 37 | } 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-formatter", 3 | "version": "7.2.2", 4 | "description": "Formatter of TypeScript code", 5 | "main": "./index", 6 | "bin": { 7 | "tsfmt": "./bin/tsfmt" 8 | }, 9 | "scripts": { 10 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", 11 | "build": "tslint --fix -c _tslint.json -p tsconfig.json && tsfmt -r && tsc", 12 | "test": "npm run build && mocha --reporter spec --timeout 20000 --require intelli-espower-loader" 13 | }, 14 | "keywords": [ 15 | "TypeScript" 16 | ], 17 | "author": "vvakame+dev@gmail.com", 18 | "license": "MIT", 19 | "homepage": "https://github.com/vvakame/typescript-formatter", 20 | "repository": { 21 | "type": "git", 22 | "url": "git@github.com:vvakame/typescript-formatter.git" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/vvakame/typescript-formatter/issues" 26 | }, 27 | "engines": { 28 | "node": ">= 4.2.0" 29 | }, 30 | "directories": { 31 | "example": "example", 32 | "test": "test" 33 | }, 34 | "dependencies": { 35 | "commandpost": "^1.0.0", 36 | "editorconfig": "^0.15.0" 37 | }, 38 | "peerDependencies": { 39 | "typescript": "^2.1.6 || ^3.0.0 || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev" 40 | }, 41 | "devDependencies": { 42 | "@types/mkdirp": "^0.5.0", 43 | "@types/mocha": "^5.0.0", 44 | "@types/node": "^10.3.0", 45 | "@types/power-assert": "^1.5.0", 46 | "conventional-changelog-cli": "^2.0.0", 47 | "intelli-espower-loader": "^1.0.1", 48 | "mkdirp": "^0.5.1", 49 | "mocha": "^5.1.0", 50 | "power-assert": "^1.5.0", 51 | "tslint": "^5.1.0", 52 | "typescript": ">=3.0.0-rc", 53 | "typescript-formatter": "^7.2.2" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /test/fixture/tsc-version/decorators/main.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | @classDecorator 4 | class Sample { 5 | a(): string { 6 | return ""; 7 | } 8 | 9 | @methodDecorator 10 | b(): string { 11 | return ""; 12 | } 13 | 14 | @staticMethodDecorator 15 | static c(): string { 16 | return ""; 17 | } 18 | 19 | @propertyDecorator 20 | d = ""; 21 | 22 | 23 | @accessorDecorator 24 | get e(): string { 25 | return ""; 26 | } 27 | 28 | f( @parameterDecorator str: string): string { 29 | return `Hello, ${str}`; 30 | } 31 | } 32 | 33 | console.log("------"); 34 | 35 | let obj = new Sample(); 36 | console.log(obj.a()); 37 | console.log(obj.b()); 38 | console.log(Sample.c()); 39 | console.log(obj.d); 40 | console.log(obj.e); 41 | console.log(obj.f("parameter")); 42 | 43 | function classDecorator(sampleClazz: typeof Sample): typeof Sample { 44 | console.log("classDecorator", arguments); 45 | sampleClazz.prototype.a = function() { 46 | return "Hello from classDecorator!"; 47 | } 48 | return null; 49 | } 50 | 51 | function methodDecorator(prototypeOfSample: any, key: string, propertyDescription: PropertyDescriptor): PropertyDescriptor { 52 | console.log("methodDecorator", arguments); 53 | return null; 54 | } 55 | 56 | function staticMethodDecorator(sampleClazz: typeof Sample, key: string, propertyDescription: PropertyDescriptor): PropertyDescriptor { 57 | console.log("staticMethodDecorator", arguments); 58 | return null; 59 | } 60 | 61 | function propertyDecorator(prototypeOfSample: any, key: string): void { 62 | console.log("propertyDecorator", arguments); 63 | } 64 | 65 | function accessorDecorator(prototypeOfSample: any, key: string, propertyDescription: PropertyDescriptor): PropertyDescriptor { 66 | console.log("accessorDecorator", arguments); 67 | return null; 68 | } 69 | 70 | function parameterDecorator(prototypeOfSample: any, methodName: string, parameterIndex: number): void { 71 | console.log("parameterDecorator", arguments); 72 | } 73 | -------------------------------------------------------------------------------- /test/expected/tsc-version/decorators/main.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | @classDecorator 4 | class Sample { 5 | a(): string { 6 | return ""; 7 | } 8 | 9 | @methodDecorator 10 | b(): string { 11 | return ""; 12 | } 13 | 14 | @staticMethodDecorator 15 | static c(): string { 16 | return ""; 17 | } 18 | 19 | @propertyDecorator 20 | d = ""; 21 | 22 | 23 | @accessorDecorator 24 | get e(): string { 25 | return ""; 26 | } 27 | 28 | f(@parameterDecorator str: string): string { 29 | return `Hello, ${str}`; 30 | } 31 | } 32 | 33 | console.log("------"); 34 | 35 | let obj = new Sample(); 36 | console.log(obj.a()); 37 | console.log(obj.b()); 38 | console.log(Sample.c()); 39 | console.log(obj.d); 40 | console.log(obj.e); 41 | console.log(obj.f("parameter")); 42 | 43 | function classDecorator(sampleClazz: typeof Sample): typeof Sample { 44 | console.log("classDecorator", arguments); 45 | sampleClazz.prototype.a = function() { 46 | return "Hello from classDecorator!"; 47 | } 48 | return null; 49 | } 50 | 51 | function methodDecorator(prototypeOfSample: any, key: string, propertyDescription: PropertyDescriptor): PropertyDescriptor { 52 | console.log("methodDecorator", arguments); 53 | return null; 54 | } 55 | 56 | function staticMethodDecorator(sampleClazz: typeof Sample, key: string, propertyDescription: PropertyDescriptor): PropertyDescriptor { 57 | console.log("staticMethodDecorator", arguments); 58 | return null; 59 | } 60 | 61 | function propertyDecorator(prototypeOfSample: any, key: string): void { 62 | console.log("propertyDecorator", arguments); 63 | } 64 | 65 | function accessorDecorator(prototypeOfSample: any, key: string, propertyDescription: PropertyDescriptor): PropertyDescriptor { 66 | console.log("accessorDecorator", arguments); 67 | return null; 68 | } 69 | 70 | function parameterDecorator(prototypeOfSample: any, methodName: string, parameterIndex: number): void { 71 | console.log("parameterDecorator", arguments); 72 | } 73 | -------------------------------------------------------------------------------- /lib/provider/editorconfig.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "typescript"; 2 | 3 | import * as editorconfig from "editorconfig"; 4 | 5 | import { Options } from "../"; 6 | 7 | let emitBaseDirWarning = false; 8 | 9 | export function makeFormatCodeOptions(fileName: string, opts: Options, formatSettings: ts.FormatCodeSettings): Promise { 10 | 11 | if (opts.verbose && opts.baseDir && !emitBaseDirWarning) { 12 | console.log("editorconfig is not supported baseDir options"); 13 | emitBaseDirWarning = true; 14 | } 15 | 16 | return editorconfig 17 | .parse(fileName) 18 | .then(config => { 19 | if (Object.keys(config).length === 0) { 20 | return formatSettings; 21 | } 22 | if (opts.verbose) { 23 | console.log("editorconfig: \n" + "file: " + fileName + "\n" + JSON.stringify(config, null, 2)); 24 | } 25 | 26 | if (config.indent_style === "tab") { 27 | formatSettings.convertTabsToSpaces = false; 28 | // if (typeof config.tab_width === "number") { 29 | // options.TabSize = config.tab_width; 30 | // } 31 | } else if (typeof config.indent_size === "number") { 32 | formatSettings.convertTabsToSpaces = true; 33 | formatSettings.indentSize = config.indent_size; 34 | } 35 | if (config.end_of_line === "lf") { 36 | formatSettings.newLineCharacter = "\n"; 37 | } else if (config.end_of_line === "cr") { 38 | formatSettings.newLineCharacter = "\r"; 39 | } else if (config.end_of_line === "crlf") { 40 | formatSettings.newLineCharacter = "\r\n"; 41 | } 42 | 43 | return formatSettings; 44 | }); 45 | } 46 | 47 | 48 | export function postProcess(fileName: string, formattedCode: string, opts: Options, _formatSettings: ts.FormatCodeSettings): Promise { 49 | 50 | if (opts.verbose && opts.baseDir && !emitBaseDirWarning) { 51 | console.log("editorconfig is not supported baseDir options"); 52 | emitBaseDirWarning = true; 53 | } 54 | 55 | return editorconfig 56 | .parse(fileName) 57 | .then(config => { 58 | if (config.insert_final_newline && !/\n$/.test(formattedCode)) { 59 | formattedCode += "\n"; 60 | } 61 | return formattedCode; 62 | }); 63 | } 64 | -------------------------------------------------------------------------------- /test/fixture/tslint/a/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "ban": [true, 4 | ["_", "extend"], 5 | ["_", "isNull"], 6 | ["_", "isDefined"] 7 | ], 8 | "class-name": true, 9 | "comment-format": [true, 10 | "check-space", 11 | "check-lowercase" 12 | ], 13 | "curly": true, 14 | "eofline": true, 15 | "forin": true, 16 | "indent": [true, 4], 17 | "interface-name": true, 18 | "jsdoc-format": true, 19 | "label-position": true, 20 | "label-undefined": true, 21 | "max-line-length": [true, 140], 22 | "no-arg": true, 23 | "no-bitwise": true, 24 | "no-console": [true, 25 | "debug", 26 | "info", 27 | "time", 28 | "timeEnd", 29 | "trace" 30 | ], 31 | "no-construct": true, 32 | "no-debugger": true, 33 | "no-duplicate-key": true, 34 | "no-duplicate-variable": true, 35 | "no-empty": true, 36 | "no-eval": true, 37 | "no-string-literal": true, 38 | "trailing-comma": [true, { 39 | "singleline": "never", 40 | "multiline": "always" 41 | }], 42 | "no-trailing-whitespace": true, 43 | "no-unused-expression": true, 44 | "no-unused-variable": true, 45 | "no-unreachable": true, 46 | "no-use-before-declare": true, 47 | "one-line": [true, 48 | "check-open-brace", 49 | "check-catch", 50 | "check-else", 51 | "check-whitespace" 52 | ], 53 | "quotemark": [true, "double"], 54 | "radix": true, 55 | "semicolon": true, 56 | "triple-equals": [true, "allow-null-check"], 57 | "typedef": [true, 58 | "callSignature", 59 | "catchClause", 60 | "indexSignature", 61 | "parameter", 62 | "propertySignature", 63 | "variableDeclarator" 64 | ], 65 | "typedef-whitespace": [true, 66 | ["callSignature", "noSpace"], 67 | ["catchClause", "noSpace"], 68 | ["indexSignature", "space"] 69 | ], 70 | "use-strict": [true, 71 | "check-module", 72 | "check-function" 73 | ], 74 | "variable-name": false, 75 | "whitespace": [true, 76 | "check-branch", 77 | "check-decl", 78 | "check-operator", 79 | "check-separator", 80 | "check-type" 81 | ] 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /test/fixture/tslint/b/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | // comment 3 | /* comment */ 4 | "rules": { 5 | "ban": [true, 6 | ["_", "extend"], 7 | ["_", "isNull"], 8 | ["_", "isDefined"] 9 | ], 10 | "class-name": true, 11 | "comment-format": [true, 12 | "check-space", 13 | "check-lowercase" 14 | ], 15 | "curly": true, 16 | "eofline": true, 17 | "forin": true, 18 | "indent": [true, 4], 19 | "interface-name": true, 20 | "jsdoc-format": true, 21 | "label-position": true, 22 | "label-undefined": true, 23 | "max-line-length": [true, 140], 24 | "no-arg": true, 25 | "no-bitwise": true, 26 | "no-console": [true, 27 | "debug", 28 | "info", 29 | "time", 30 | "timeEnd", 31 | "trace" 32 | ], 33 | "no-construct": true, 34 | "no-debugger": true, 35 | "no-duplicate-key": true, 36 | "no-duplicate-variable": true, 37 | "no-empty": true, 38 | "no-eval": true, 39 | "no-string-literal": true, 40 | "trailing-comma": [true, { 41 | "singleline": "never", 42 | "multiline": "always" 43 | }], 44 | "no-trailing-whitespace": true, 45 | "no-unused-expression": true, 46 | "no-unused-variable": true, 47 | "no-unreachable": true, 48 | "no-use-before-declare": true, 49 | "one-line": [true, 50 | "check-open-brace", 51 | "check-catch", 52 | "check-else", 53 | "check-whitespace" 54 | ], 55 | "quotemark": [true, "double"], 56 | "radix": true, 57 | "semicolon": true, 58 | "triple-equals": [true, "allow-null-check"], 59 | "typedef": [true, 60 | "callSignature", 61 | "catchClause", 62 | "indexSignature", 63 | "parameter", 64 | "propertySignature", 65 | "variableDeclarator" 66 | ], 67 | "typedef-whitespace": [true, 68 | ["callSignature", "noSpace"], 69 | ["catchClause", "noSpace"], 70 | ["indexSignature", "space"] 71 | ], 72 | "use-strict": [true, 73 | "check-module", 74 | "check-function" 75 | ], 76 | "variable-name": false, 77 | "whitespace": [true, 78 | "check-branch", 79 | "check-decl", 80 | "check-operator", 81 | "check-separator", 82 | "check-type" 83 | ] 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lib/utils.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "typescript"; 2 | 3 | import * as fs from "fs"; 4 | import * as path from "path"; 5 | 6 | const TSCONFIG_CACHE: { [filePath: string]: ts.ParsedCommandLine; } = {}; 7 | 8 | export function createDefaultFormatCodeSettings(): ts.FormatCodeSettings { 9 | 10 | return { 11 | baseIndentSize: 0, 12 | indentSize: 4, 13 | tabSize: 4, 14 | indentStyle: ts.IndentStyle.Smart, 15 | newLineCharacter: "\r\n", 16 | convertTabsToSpaces: true, 17 | insertSpaceAfterCommaDelimiter: true, 18 | insertSpaceAfterSemicolonInForStatements: true, 19 | insertSpaceBeforeAndAfterBinaryOperators: true, 20 | insertSpaceAfterConstructor: false, 21 | insertSpaceAfterKeywordsInControlFlowStatements: true, 22 | insertSpaceAfterFunctionKeywordForAnonymousFunctions: false, 23 | insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, 24 | insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, 25 | insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, 26 | insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, 27 | insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, 28 | insertSpaceAfterTypeAssertion: false, 29 | insertSpaceBeforeFunctionParenthesis: false, 30 | placeOpenBraceOnNewLineForFunctions: false, 31 | placeOpenBraceOnNewLineForControlBlocks: false, 32 | insertSpaceBeforeTypeAnnotation: false, 33 | }; 34 | } 35 | 36 | export function getConfigFileName(baseDir: string, configFileName: string): string | null { 37 | 38 | let configFilePath = path.resolve(baseDir, configFileName); 39 | if (fs.existsSync(configFilePath)) { 40 | return configFilePath; 41 | } 42 | 43 | if (baseDir.length === path.dirname(baseDir).length) { 44 | return null; 45 | } 46 | 47 | return getConfigFileName(path.resolve(baseDir, "../"), configFileName); 48 | } 49 | 50 | export function readFilesFromTsconfig(configPath: string): string[] { 51 | return readTsconfig(configPath).fileNames; 52 | } 53 | 54 | export function readTsconfig(configPath: string): ts.ParsedCommandLine { 55 | if (TSCONFIG_CACHE[configPath]) { 56 | return TSCONFIG_CACHE[configPath]; 57 | } 58 | 59 | // for `extends` support. It supported from TypeScript 2.1.1. 60 | // `& { readFile(path: string): string; }` is backword compat for TypeScript compiler 2.0.3 support. 61 | const host: ts.ParseConfigHost & { readFile(path: string): string; } = { 62 | useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames, 63 | readDirectory: ts.sys.readDirectory, 64 | fileExists: path => fs.existsSync(path), 65 | readFile: (path: string) => fs.readFileSync(path, "utf-8"), 66 | }; 67 | let rootConfig = parseJSON(fs.readFileSync(configPath, "utf-8")); 68 | let parsed = ts.parseJsonConfigFileContent(rootConfig, host, path.dirname(configPath)); 69 | if (parsed.errors && parsed.errors.length !== 0) { 70 | throw new Error(parsed.errors.map(e => e.messageText).join("\n")); 71 | } 72 | 73 | TSCONFIG_CACHE[configPath] = parsed; 74 | 75 | return parsed; 76 | } 77 | 78 | export function parseJSON(jsonText: string): any { 79 | let result = ts.parseConfigFileTextToJson("tmp.json", jsonText); 80 | if (result.error) { 81 | throw new Error("JSON parse error"); 82 | } 83 | 84 | return result.config; 85 | } 86 | -------------------------------------------------------------------------------- /lib/provider/tslintjson.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "typescript"; 2 | import { IOptions as TslintOptions } from "tslint"; 3 | import * as path from "path"; 4 | 5 | import { Options } from "../"; 6 | import { getConfigFileName } from "../utils"; 7 | 8 | 9 | export interface AdditionalFormatSettings { 10 | $noConsecutiveBlankLines: boolean; 11 | } 12 | 13 | export async function makeFormatCodeOptions(fileName: string, opts: Options, formatSettings: ts.FormatCodeSettings): Promise { 14 | 15 | const rules = await getRules(fileName, opts); 16 | 17 | if (!rules) { 18 | return formatSettings; 19 | } 20 | 21 | const indent = rules.get("indent"); 22 | const whitespace = rules.get("whitespace"); 23 | 24 | if (indent && indent.ruleArguments) { 25 | switch (indent.ruleArguments[0]) { 26 | case "spaces": 27 | formatSettings.convertTabsToSpaces = true; 28 | break; 29 | case "tabs": 30 | formatSettings.convertTabsToSpaces = false; 31 | break; 32 | default: 33 | break; 34 | } 35 | } 36 | if (whitespace && whitespace.ruleArguments) { 37 | for (let p in whitespace.ruleArguments) { 38 | switch (whitespace.ruleArguments[p]) { 39 | case "check-branch": 40 | formatSettings.insertSpaceAfterKeywordsInControlFlowStatements = true; 41 | break; 42 | case "check-operator": 43 | formatSettings.insertSpaceBeforeAndAfterBinaryOperators = true; 44 | break; 45 | case "check-separator": 46 | formatSettings.insertSpaceAfterCommaDelimiter = true; 47 | formatSettings.insertSpaceAfterSemicolonInForStatements = true; 48 | break; 49 | case "check-typecast": 50 | formatSettings.insertSpaceAfterTypeAssertion = true; 51 | break; 52 | default: 53 | break; 54 | } 55 | } 56 | } 57 | 58 | return formatSettings; 59 | } 60 | 61 | export async function postProcess(fileName: string, formattedCode: string, opts: Options, _formatSettings: ts.FormatCodeSettings): Promise { 62 | 63 | const rules = await getRules(fileName, opts); 64 | 65 | if (!rules) { 66 | return formattedCode; 67 | } 68 | 69 | if (rules.has("no-consecutive-blank-lines")) { 70 | formattedCode = formattedCode.replace(/\n+^$/mg, "\n"); 71 | } 72 | 73 | return formattedCode; 74 | } 75 | 76 | async function getRules(fileName: string, opts: Options): Promise> | undefined> { 77 | const baseDir = opts.baseDir ? path.resolve(opts.baseDir) : path.dirname(path.resolve(fileName)); 78 | 79 | let configFileName: string | null; 80 | if (opts.tslintFile && path.isAbsolute(opts.tslintFile)) { 81 | configFileName = opts.tslintFile; 82 | } else { 83 | configFileName = getConfigFileName(baseDir, opts.tslintFile || "tslint.json"); 84 | } 85 | 86 | if (!configFileName) { 87 | return undefined; 88 | } 89 | 90 | if (opts.verbose) { 91 | console.log(`read ${configFileName} for ${fileName}`); 92 | } 93 | 94 | const { Configuration } = await import("tslint"); 95 | const { rules } = Configuration.loadConfigurationFromPath(configFileName); 96 | return rules; 97 | } 98 | -------------------------------------------------------------------------------- /_tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "align": [ 4 | false, 5 | "parameters", 6 | "arguments", 7 | "statements" 8 | ], 9 | "ban": false, 10 | "class-name": true, 11 | "comment-format": [ 12 | true, 13 | "check-space" 14 | ], 15 | "curly": true, 16 | "eofline": true, 17 | "forin": false, 18 | "indent": [ 19 | false, 20 | "spaces" 21 | ], 22 | "interface-name": [ 23 | true, 24 | "never-prefix" 25 | ], 26 | "jsdoc-format": false, 27 | "label-position": true, 28 | "max-line-length": [ 29 | false, 30 | 140 31 | ], 32 | "member-access": false, 33 | "member-ordering": [ 34 | false, 35 | "public-before-private", 36 | "static-before-instance" 37 | ], 38 | "new-parens": true, 39 | "no-angle-bracket-type-assertion": false, 40 | "no-any": false, 41 | "no-arg": true, 42 | "no-bitwise": true, 43 | "no-conditional-assignment": true, 44 | "no-consecutive-blank-lines": false, 45 | "no-console": [ 46 | true, 47 | "debug", 48 | "info", 49 | "time", 50 | "timeEnd", 51 | "trace" 52 | ], 53 | "no-construct": true, 54 | "no-debugger": true, 55 | "no-duplicate-variable": true, 56 | "no-empty": false, 57 | "no-eval": true, 58 | "no-inferrable-types": false, 59 | "no-internal-module": true, 60 | "no-invalid-this": false, 61 | "no-mergeable-namespace": false, 62 | "no-namespace": [ 63 | true, 64 | "allow-declarations" 65 | ], 66 | "no-null-keyword": false, 67 | "no-reference": true, 68 | "no-require-imports": false, 69 | "no-shadowed-variable": false, 70 | "no-string-literal": false, 71 | "no-switch-case-fall-through": false, 72 | "no-trailing-whitespace": false, 73 | "no-unused-expression": false, 74 | "no-use-before-declare": true, 75 | "no-var-keyword": true, 76 | "no-var-requires": false, 77 | "object-literal-sort-keys": false, 78 | "one-line": [ 79 | true, 80 | "check-open-brace", 81 | "check-catch", 82 | "check-else", 83 | "check-finally", 84 | "check-whitespace" 85 | ], 86 | "quotemark": [ 87 | true, 88 | "double", 89 | "avoid-escape" 90 | ], 91 | "radix": true, 92 | "semicolon": [true, "always"], 93 | "switch-default": true, 94 | "trailing-comma": [ 95 | true, 96 | { 97 | "multiline": "always", 98 | "singleline": "never" 99 | } 100 | ], 101 | "triple-equals": [ 102 | true, 103 | "allow-null-check" 104 | ], 105 | "typedef": [ 106 | false, 107 | "call-signature", 108 | "parameter", 109 | "property-declaration", 110 | "variable-declaration", 111 | "member-variable-declaration" 112 | ], 113 | "typedef-whitespace": [ 114 | false, 115 | { 116 | "call-signature": "nospace", 117 | "index-signature": "nospace", 118 | "parameter": "nospace", 119 | "property-declaration": "nospace", 120 | "variable-declaration": "nospace" 121 | }, 122 | { 123 | "call-signature": "space", 124 | "index-signature": "space", 125 | "parameter": "space", 126 | "property-declaration": "space", 127 | "variable-declaration": "space" 128 | } 129 | ], 130 | "use-isnan": true, 131 | "variable-name": [ 132 | true, 133 | "check-format", 134 | "allow-leading-underscore", 135 | "ban-keywords" 136 | ], 137 | "whitespace": [ 138 | true, 139 | "check-branch", 140 | "check-decl", 141 | "check-operator", 142 | "check-separator", 143 | "check-type" 144 | ] 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /lib/provider/vscodesettings.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "typescript"; 2 | 3 | import * as path from "path"; 4 | import * as fs from "fs"; 5 | 6 | import { Options } from "../"; 7 | import { getConfigFileName, parseJSON } from "../utils"; 8 | 9 | // https://code.visualstudio.com/Docs/customization/userandworkspace 10 | interface VSCodeSettings { 11 | "typescript.format.insertSpaceAfterCommaDelimiter": boolean; 12 | "typescript.format.insertSpaceAfterConstructor": boolean; 13 | "typescript.format.insertSpaceAfterSemicolonInForStatements": boolean; 14 | "typescript.format.insertSpaceBeforeAndAfterBinaryOperators": boolean; 15 | "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": boolean; 16 | "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": boolean; 17 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": boolean; 18 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": boolean; 19 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": boolean; 20 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": boolean; 21 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": boolean; 22 | "typescript.format.insertSpaceAfterTypeAssertion": boolean; 23 | "typescript.format.insertSpaceBeforeFunctionParenthesis": boolean; 24 | "typescript.format.placeOpenBraceOnNewLineForFunctions": boolean; 25 | "typescript.format.placeOpenBraceOnNewLineForControlBlocks": boolean; 26 | 27 | // NOTE https://github.com/Microsoft/vscode/issues/10296 28 | // baseIndentSize 29 | } 30 | 31 | export function makeFormatCodeOptions(fileName: string, opts: Options, formatSettings: ts.FormatCodeSettings): ts.FormatCodeSettings { 32 | 33 | let baseDir = opts.baseDir ? path.resolve(opts.baseDir) : path.dirname(path.resolve(fileName)); 34 | let configFileName: string | null; 35 | if (opts.vscodeFile && path.isAbsolute(opts.vscodeFile)) { 36 | configFileName = opts.vscodeFile; 37 | } else { 38 | configFileName = getConfigFileName(baseDir, opts.vscodeFile || ".vscode/settings.json"); 39 | } 40 | if (!configFileName) { 41 | return formatSettings; 42 | } 43 | if (opts.verbose) { 44 | console.log(`read ${configFileName} for ${fileName}`); 45 | } 46 | 47 | let config: VSCodeSettings = parseJSON(fs.readFileSync(configFileName, "utf-8")); 48 | if (config["typescript.format.insertSpaceAfterCommaDelimiter"] != null) { 49 | formatSettings.insertSpaceAfterCommaDelimiter = config["typescript.format.insertSpaceAfterCommaDelimiter"]; 50 | } 51 | if (config["typescript.format.insertSpaceAfterConstructor"] != null) { 52 | formatSettings.insertSpaceAfterConstructor = config["typescript.format.insertSpaceAfterConstructor"]; 53 | } 54 | if (config["typescript.format.insertSpaceAfterSemicolonInForStatements"] != null) { 55 | formatSettings.insertSpaceAfterSemicolonInForStatements = config["typescript.format.insertSpaceAfterSemicolonInForStatements"]; 56 | } 57 | if (config["typescript.format.insertSpaceBeforeAndAfterBinaryOperators"] != null) { 58 | formatSettings.insertSpaceBeforeAndAfterBinaryOperators = config["typescript.format.insertSpaceBeforeAndAfterBinaryOperators"]; 59 | } 60 | if (config["typescript.format.insertSpaceAfterKeywordsInControlFlowStatements"] != null) { 61 | formatSettings.insertSpaceAfterKeywordsInControlFlowStatements = config["typescript.format.insertSpaceAfterKeywordsInControlFlowStatements"]; 62 | } 63 | if (config["typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions"] != null) { 64 | formatSettings.insertSpaceAfterFunctionKeywordForAnonymousFunctions = config["typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions"]; 65 | } 66 | if (config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"] != null) { 67 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis = config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"]; 68 | } 69 | if (config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"] != null) { 70 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets = config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"]; 71 | } 72 | if (config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"] != null) { 73 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces = config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"]; 74 | } 75 | if (config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"] != null) { 76 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces = config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"]; 77 | } 78 | if (config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"] != null) { 79 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces = config["typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"]; 80 | } 81 | if (config["typescript.format.insertSpaceAfterTypeAssertion"] != null) { 82 | formatSettings.insertSpaceAfterTypeAssertion = config["typescript.format.insertSpaceAfterTypeAssertion"]; 83 | } 84 | if (config["typescript.format.insertSpaceBeforeFunctionParenthesis"] != null) { 85 | formatSettings.insertSpaceBeforeFunctionParenthesis = config["typescript.format.insertSpaceBeforeFunctionParenthesis"]; 86 | } 87 | if (config["typescript.format.placeOpenBraceOnNewLineForFunctions"] != null) { 88 | formatSettings.placeOpenBraceOnNewLineForFunctions = config["typescript.format.placeOpenBraceOnNewLineForFunctions"]; 89 | } 90 | if (config["typescript.format.placeOpenBraceOnNewLineForControlBlocks"] != null) { 91 | formatSettings.placeOpenBraceOnNewLineForControlBlocks = config["typescript.format.placeOpenBraceOnNewLineForControlBlocks"]; 92 | } 93 | 94 | return formatSettings; 95 | } 96 | -------------------------------------------------------------------------------- /lib/provider/base.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "typescript"; 2 | 3 | import * as path from "path"; 4 | import * as fs from "fs"; 5 | 6 | import { Options } from "../"; 7 | import { getConfigFileName, parseJSON } from "../utils"; 8 | 9 | interface TsfmtSettings { 10 | insertSpaceAfterCommaDelimiter?: boolean; 11 | insertSpaceAfterSemicolonInForStatements?: boolean; 12 | insertSpaceBeforeAndAfterBinaryOperators?: boolean; 13 | insertSpaceAfterConstructor?: boolean; 14 | insertSpaceAfterKeywordsInControlFlowStatements?: boolean; 15 | insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean; 16 | insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean; 17 | insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean; 18 | insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean; 19 | insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean; 20 | insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean; 21 | insertSpaceAfterTypeAssertion?: boolean; 22 | insertSpaceBeforeFunctionParenthesis?: boolean; 23 | placeOpenBraceOnNewLineForFunctions?: boolean; 24 | placeOpenBraceOnNewLineForControlBlocks?: boolean; 25 | insertSpaceBeforeTypeAnnotation?: boolean; 26 | baseIndentSize?: number; 27 | indentSize?: number; 28 | // 0, 1, 2 or None, Block, Smart 29 | indentStyle?: number | string; 30 | tabSize?: number; 31 | newLineCharacter?: string; 32 | convertTabsToSpaces?: boolean; 33 | } 34 | 35 | export function makeFormatCodeOptions(fileName: string, opts: Options, formatSettings: ts.FormatCodeSettings): ts.FormatCodeSettings { 36 | let baseDir = opts.baseDir ? path.resolve(opts.baseDir) : path.dirname(path.resolve(fileName)); 37 | let configFileName: string | null; 38 | if (opts.tsfmtFile && path.isAbsolute(opts.tsfmtFile)) { 39 | configFileName = opts.tsfmtFile; 40 | } else { 41 | configFileName = getConfigFileName(baseDir, opts.tsfmtFile || "tsfmt.json"); 42 | } 43 | if (!configFileName) { 44 | return formatSettings; 45 | } 46 | 47 | if (opts.verbose) { 48 | console.log(`read ${configFileName} for ${fileName}`); 49 | } 50 | 51 | let config: TsfmtSettings = parseJSON(fs.readFileSync(configFileName, "utf-8")); 52 | if (typeof config.insertSpaceAfterCommaDelimiter === "boolean") { 53 | formatSettings.insertSpaceAfterCommaDelimiter = config.insertSpaceAfterCommaDelimiter; 54 | } 55 | if (typeof config.insertSpaceAfterSemicolonInForStatements === "boolean") { 56 | formatSettings.insertSpaceAfterSemicolonInForStatements = config.insertSpaceAfterSemicolonInForStatements; 57 | } 58 | if (typeof config.insertSpaceBeforeAndAfterBinaryOperators === "boolean") { 59 | formatSettings.insertSpaceBeforeAndAfterBinaryOperators = config.insertSpaceBeforeAndAfterBinaryOperators; 60 | } 61 | if (typeof config.insertSpaceAfterConstructor === "boolean") { 62 | formatSettings.insertSpaceAfterConstructor = config.insertSpaceAfterConstructor; 63 | } 64 | if (typeof config.insertSpaceAfterKeywordsInControlFlowStatements === "boolean") { 65 | formatSettings.insertSpaceAfterKeywordsInControlFlowStatements = config.insertSpaceAfterKeywordsInControlFlowStatements; 66 | } 67 | if (typeof config.insertSpaceAfterFunctionKeywordForAnonymousFunctions === "boolean") { 68 | formatSettings.insertSpaceAfterFunctionKeywordForAnonymousFunctions = config.insertSpaceAfterFunctionKeywordForAnonymousFunctions; 69 | } 70 | if (typeof config.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis === "boolean") { 71 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis = config.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis; 72 | } 73 | if (typeof config.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces === "boolean") { 74 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces = config.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces; 75 | } 76 | if (typeof config.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets === "boolean") { 77 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets = config.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets; 78 | } 79 | if (typeof config.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces === "boolean") { 80 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces = config.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces; 81 | } 82 | if (typeof config.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces === "boolean") { 83 | formatSettings.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces = config.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces; 84 | } 85 | if (typeof config.insertSpaceAfterTypeAssertion === "boolean") { 86 | formatSettings.insertSpaceAfterTypeAssertion = config.insertSpaceAfterTypeAssertion; 87 | } 88 | if (typeof config.insertSpaceBeforeFunctionParenthesis === "boolean") { 89 | formatSettings.insertSpaceBeforeFunctionParenthesis = config.insertSpaceBeforeFunctionParenthesis; 90 | } 91 | if (typeof config.placeOpenBraceOnNewLineForFunctions === "boolean") { 92 | formatSettings.placeOpenBraceOnNewLineForFunctions = config.placeOpenBraceOnNewLineForFunctions; 93 | } 94 | if (typeof config.placeOpenBraceOnNewLineForControlBlocks === "boolean") { 95 | formatSettings.placeOpenBraceOnNewLineForControlBlocks = config.placeOpenBraceOnNewLineForControlBlocks; 96 | } 97 | if (typeof config.insertSpaceBeforeTypeAnnotation === "boolean") { 98 | formatSettings.insertSpaceBeforeTypeAnnotation = config.insertSpaceBeforeTypeAnnotation; 99 | } 100 | if (typeof config.baseIndentSize === "number") { 101 | formatSettings.baseIndentSize = config.baseIndentSize; 102 | } 103 | if (typeof config.indentSize === "number") { 104 | formatSettings.indentSize = config.indentSize; 105 | } 106 | if (typeof config.indentStyle === "number") { 107 | formatSettings.indentStyle = config.indentStyle as number; 108 | } else if (typeof config.indentStyle === "string") { 109 | formatSettings.indentStyle = (ts.IndentStyle as any)[config.indentStyle] as number; 110 | } 111 | if (typeof config.tabSize === "number") { 112 | formatSettings.tabSize = config.tabSize; 113 | } 114 | if (typeof config.newLineCharacter === "string") { 115 | formatSettings.newLineCharacter = config.newLineCharacter; 116 | } 117 | if (typeof config.convertTabsToSpaces === "boolean") { 118 | formatSettings.convertTabsToSpaces = config.convertTabsToSpaces; 119 | } 120 | 121 | return formatSettings; 122 | } 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Formatter (tsfmt) 2 | 3 | [![npm](https://img.shields.io/npm/v/typescript-formatter.svg)](https://www.npmjs.com/package/typescript-formatter) 4 | [![Build Status](https://travis-ci.org/vvakame/typescript-formatter.svg)](https://travis-ci.org/vvakame/typescript-formatter) 5 | [![Dependency Status](https://david-dm.org/vvakame/typescript-formatter.svg?theme=shields.io)](https://david-dm.org/vvakame/typescript-formatter) 6 | [![npm](https://img.shields.io/npm/dm/typescript-formatter.svg)](https://www.npmjs.com/package/typescript-formatter) 7 | [![GitHub stars](https://img.shields.io/github/stars/vvakame/typescript-formatter.svg?style=social&label=Star)](https://github.com/vvakame/typescript-formatter/stargazers) 8 | 9 | A TypeScript code formatter powered by [TypeScript Compiler Service](https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#pretty-printer-using-the-ls-formatter). 10 | 11 | ```bash 12 | $ tsfmt --help 13 | Usage: tsfmt [options] [--] [files...] 14 | 15 | Options: 16 | 17 | -r, --replace replace .ts file 18 | --verify checking file format 19 | --baseDir config file lookup from 20 | --stdin get formatting content from stdin 21 | --no-tsconfig don't read a tsconfig.json 22 | --no-tslint don't read a tslint.json 23 | --no-editorconfig don't read a .editorconfig 24 | --no-vscode don't read a .vscode/settings.json 25 | --no-tsfmt don't read a tsfmt.json 26 | --useTsconfig using specified config file instead of tsconfig.json 27 | --useTslint using specified config file instead of tslint.json 28 | --useTsfmt using specified config file instead of tsfmt.json 29 | --verbose makes output more verbose 30 | ``` 31 | 32 | ## Installation 33 | 34 | ```npm install -g typescript-formatter``` 35 | 36 | ## Usage 37 | 38 | ### Format or verify specific TypeScript files 39 | 40 | ```bash 41 | $ cat sample.ts 42 | class Sample {hello(word="world"){return "Hello, "+word;}} 43 | new Sample().hello("TypeScript"); 44 | ``` 45 | 46 | ```bash 47 | # basic. read file, output to stdout. 48 | $ tsfmt sample.ts 49 | class Sample { hello(word = "world") { return "Hello, " + word; } } 50 | new Sample().hello("TypeScript"); 51 | ``` 52 | 53 | ```bash 54 | # from stdin. read from stdin, output to stdout. 55 | $ cat sample.ts | tsfmt --stdin 56 | class Sample { hello(word = "world") { return "Hello, " + word; } } 57 | new Sample().hello("TypeScript"); 58 | ``` 59 | 60 | ```bash 61 | # replace. read file, and replace file. 62 | $ tsfmt -r sample.ts 63 | replaced sample.ts 64 | $ cat sample.ts 65 | class Sample { hello(word = "world") { return "Hello, " + word; } } 66 | new Sample().hello("TypeScript"); 67 | ``` 68 | 69 | ```bash 70 | # verify. checking file format. 71 | $ tsfmt --verify sample.ts 72 | sample.ts is not formatted 73 | $ echo $? 74 | 1 75 | ``` 76 | 77 | ### Reformat all files in a TypeScript project 78 | 79 | If no files are specified on the command line but 80 | a TypeScript project file (tsconfig.json) exists, 81 | the list of files will be read from the project file. 82 | 83 | ```bash 84 | # reads list of files to format from tsconfig.json 85 | tsfmt -r 86 | ``` 87 | 88 | ## Read Settings From Files 89 | 90 | 1st. Read settings from tsfmt.json. Below is the example with [default values](https://github.com/vvakame/typescript-formatter/blob/master/lib/utils.ts): 91 | 92 | ```json 93 | { 94 | "baseIndentSize": 0, 95 | "indentSize": 4, 96 | "tabSize": 4, 97 | "indentStyle": 2, 98 | "newLineCharacter": "\r\n", 99 | "convertTabsToSpaces": true, 100 | "insertSpaceAfterCommaDelimiter": true, 101 | "insertSpaceAfterSemicolonInForStatements": true, 102 | "insertSpaceBeforeAndAfterBinaryOperators": true, 103 | "insertSpaceAfterConstructor": false, 104 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 105 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 106 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 107 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 108 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 109 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 110 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 111 | "insertSpaceAfterTypeAssertion": false, 112 | "insertSpaceBeforeFunctionParenthesis": false, 113 | "insertSpaceBeforeTypeAnnotation": true, 114 | "placeOpenBraceOnNewLineForFunctions": false, 115 | "placeOpenBraceOnNewLineForControlBlocks": false 116 | } 117 | ``` 118 | 119 | 2nd. Read settings from tsconfig.json ([tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)) 120 | 121 | ```text 122 | { 123 | "compilerOptions": { 124 | "newLine": "LF" 125 | } 126 | } 127 | ``` 128 | 129 | 3rd. Read settings from .editorconfig ([editorconfig](http://editorconfig.org/)) 130 | 131 | ```text 132 | # EditorConfig is awesome: http://EditorConfig.org 133 | 134 | # top-most EditorConfig file 135 | root = true 136 | 137 | # Unix-style newlines with a newline ending every file 138 | [*] 139 | indent_style = tab 140 | tab_width = 2 141 | end_of_line = lf 142 | charset = utf-8 143 | trim_trailing_whitespace = true 144 | insert_final_newline = true 145 | ``` 146 | 147 | 4th. Read settings from tslint.json ([tslint](https://www.npmjs.org/package/tslint)) 148 | 149 | ```json 150 | { 151 | "rules": { 152 | "indent": [true, 4], 153 | "whitespace": [true, 154 | "check-branch", 155 | "check-operator", 156 | "check-separator", 157 | "check-typecast" 158 | ] 159 | } 160 | } 161 | ``` 162 | 163 | 5th. Read settings from .vscode/settings.json ([VisualStudio Code](https://code.visualstudio.com/Docs/customization/userandworkspace)) 164 | 165 | ```json 166 | { 167 | // Place your settings in this file to overwrite default and user settings. 168 | "typescript.format.enable": true, 169 | "typescript.format.insertSpaceAfterCommaDelimiter": true, 170 | "typescript.format.insertSpaceAfterSemicolonInForStatements": true, 171 | "typescript.format.insertSpaceBeforeAndAfterBinaryOperators": true, 172 | "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": true, 173 | "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 174 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 175 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 176 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 177 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 178 | "typescript.format.placeOpenBraceOnNewLineForFunctions": false, 179 | "typescript.format.placeOpenBraceOnNewLineForControlBlocks": false 180 | } 181 | ``` 182 | 183 | ### Read Settings Rules 184 | 185 | ``` 186 | $ tree -a 187 | . 188 | ├── .vscode 189 | │   └── settings.json 190 | ├── foo 191 | │   ├── bar 192 | │   │   ├── .editorconfig 193 | │   │   └── buzz.ts 194 | │   ├── fuga 195 | │   │   ├── piyo.ts 196 | │   │   └── tsfmt.json 197 | │   └── tsfmt.json 198 | └── tslint.json 199 | 200 | 4 directories, 7 files 201 | ``` 202 | 203 | 1. exec `$ tsfmt -r foo/bar/buzz.ts foo/fuga/piyo.ts` 204 | 2. for foo/bar/buzz.ts, read foo/tsfmt.json and foo/bar/.editorconfig and ./tslint.json and .vscode/settings.json 205 | 3. for foo/fuga/piyo.ts, read foo/fuga/tsfmt.json and ./tslint.json and .vscode/settings.json 206 | 207 | ## Change Log 208 | 209 | See [CHANGELOG](https://github.com/vvakame/typescript-formatter/blob/master/CHANGELOG.md) 210 | -------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "typescript"; 2 | import { format } from "./formatter"; 3 | import { createDefaultFormatCodeSettings, parseJSON } from "./utils"; 4 | 5 | export { parseJSON }; 6 | 7 | import * as fs from "fs"; 8 | import * as path from "path"; 9 | 10 | import * as base from "./provider/base"; 11 | import * as tsconfigjson from "./provider/tsconfigjson"; 12 | import * as editorconfig from "./provider/editorconfig"; 13 | import * as tslintjson from "./provider/tslintjson"; 14 | import * as vscodesettings from "./provider/vscodesettings"; 15 | import { EOL } from "os"; 16 | 17 | const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json")).toString()); 18 | export const version = packageJson.version; 19 | 20 | export interface Options { 21 | dryRun?: boolean; 22 | verbose?: boolean; 23 | baseDir?: string; 24 | replace: boolean; 25 | verify: boolean; 26 | tsconfig: boolean; 27 | tsconfigFile: string | null; 28 | tslint: boolean; 29 | tslintFile: string | null; 30 | editorconfig: boolean; 31 | vscode: boolean; 32 | vscodeFile: string | null; 33 | tsfmt: boolean; 34 | tsfmtFile: string | null; 35 | } 36 | 37 | export interface OptionModifier { 38 | (fileName: string, opts: Options, formatSettings: ts.FormatCodeSettings): ts.FormatCodeSettings | Promise; 39 | } 40 | 41 | export interface PostProcessor { 42 | (fileName: string, formattedCode: string, opts: Options, formatSettings: ts.FormatCodeSettings): string | Promise; 43 | } 44 | 45 | class Processor { 46 | optionModifiers: OptionModifier[] = []; 47 | postProcessors: PostProcessor[] = []; 48 | 49 | addOptionModify(modifier: OptionModifier) { 50 | this.optionModifiers.push(modifier); 51 | } 52 | 53 | processFormatCodeOptions(fileName: string, opts: Options, formatSettings: ts.FormatCodeSettings): Promise { 54 | let optionModifiers = [...this.optionModifiers]; 55 | 56 | let next = (formatSettings: ts.FormatCodeSettings): Promise => { 57 | if (optionModifiers.length === 0) { 58 | return Promise.resolve(formatSettings); 59 | } 60 | let modifier = optionModifiers.shift()!; 61 | let ret = modifier(fileName, opts, formatSettings); 62 | return Promise.resolve(ret).then(formatSettings => next(formatSettings)); 63 | }; 64 | 65 | return next(formatSettings); 66 | } 67 | 68 | addPostProcess(postProcessor: PostProcessor) { 69 | this.postProcessors.push(postProcessor); 70 | } 71 | 72 | postProcess(fileName: string, formattedCode: string, opts: Options, formatSettings: ts.FormatCodeSettings): Promise { 73 | let postProcessors = [...this.postProcessors]; 74 | 75 | let next = (formattedCode: string): Promise => { 76 | if (postProcessors.length === 0) { 77 | return Promise.resolve(formattedCode); 78 | } 79 | let processor = postProcessors.shift()!; 80 | let ret = processor(fileName, formattedCode, opts, formatSettings); 81 | return Promise.resolve(ret).then(formattedCode => next(formattedCode)); 82 | }; 83 | 84 | return next(formattedCode); 85 | } 86 | } 87 | 88 | export interface ResultMap { 89 | [fileName: string]: Result; 90 | } 91 | 92 | export interface Result { 93 | fileName: string; 94 | settings: ts.FormatCodeSettings | null; 95 | message: string; 96 | error: boolean; 97 | src: string; 98 | dest: string; 99 | } 100 | 101 | export function processFiles(files: string[], opts: Options): Promise { 102 | 103 | let resultMap: ResultMap = {}; 104 | let promises = files.map(fileName => { 105 | if (!fs.existsSync(fileName)) { 106 | let result: Result = { 107 | fileName: fileName, 108 | settings: null, 109 | message: `${fileName} does not exist. process abort.\n`, 110 | error: true, 111 | src: "", 112 | dest: "", 113 | }; 114 | return Promise.resolve(result); 115 | } 116 | 117 | let content = fs.readFileSync(fileName).toString(); 118 | return processString(fileName, content, opts); 119 | }); 120 | return Promise.all(promises).then(resultList => { 121 | resultList.forEach(result => { 122 | resultMap[result.fileName] = result; 123 | }); 124 | return resultMap; 125 | }); 126 | } 127 | 128 | export function processStream(fileName: string, input: NodeJS.ReadableStream, opts: Options): Promise { 129 | 130 | input.setEncoding("utf8"); 131 | 132 | let promise = new Promise((resolve, _reject) => { 133 | let fragment = ""; 134 | input.on("data", (chunk: string) => { 135 | fragment += chunk; 136 | }); 137 | 138 | input.on("end", () => { 139 | resolve(fragment); 140 | }); 141 | }); 142 | return promise.then(content => processString(fileName, content, opts)); 143 | } 144 | 145 | export function processString(fileName: string, content: string, opts: Options): Promise { 146 | 147 | let processor = new Processor(); 148 | if (opts.tsfmt) { 149 | processor.addOptionModify(base.makeFormatCodeOptions); 150 | } 151 | if (opts.tsconfig) { 152 | processor.addOptionModify(tsconfigjson.makeFormatCodeOptions); 153 | } 154 | if (opts.editorconfig) { 155 | processor.addOptionModify(editorconfig.makeFormatCodeOptions); 156 | processor.addPostProcess(editorconfig.postProcess); 157 | } 158 | if (opts.tslint) { 159 | processor.addOptionModify(tslintjson.makeFormatCodeOptions); 160 | processor.addPostProcess(tslintjson.postProcess); 161 | } 162 | if (opts.vscode) { 163 | processor.addOptionModify(vscodesettings.makeFormatCodeOptions); 164 | } 165 | processor.addPostProcess((_fileName: string, formattedCode: string, _opts: Options, formatSettings: ts.FormatCodeSettings) => { 166 | // replace newline code. maybe NewLineCharacter params affect to only "new" newline by language service. 167 | formattedCode = formattedCode.replace(/\r?\n/g, formatSettings.newLineCharacter || EOL); 168 | return Promise.resolve(formattedCode); 169 | }); 170 | 171 | let formatSettings = createDefaultFormatCodeSettings(); 172 | return processor.processFormatCodeOptions(fileName, opts, formatSettings) 173 | .then(formatSettings => { 174 | let formattedCode = format(fileName, content, formatSettings); 175 | 176 | // apply post process logic 177 | return processor.postProcess(fileName, formattedCode, opts, formatSettings); 178 | 179 | }).then(formattedCode => { 180 | let message = ""; 181 | let error = false; 182 | if (opts && opts.verify) { 183 | if (content !== formattedCode) { 184 | message = `${fileName} is not formatted\n`; 185 | error = true; 186 | } 187 | } else if (opts && opts.replace) { 188 | if (content !== formattedCode) { 189 | fs.writeFileSync(fileName, formattedCode); 190 | message = `replaced ${fileName}\n`; 191 | } 192 | } else if (opts && !opts.dryRun) { 193 | message = formattedCode; 194 | } 195 | 196 | let result: Result = { 197 | fileName: fileName, 198 | settings: formatSettings, 199 | message: message, 200 | error: error, 201 | src: content, 202 | dest: formattedCode, 203 | }; 204 | return Promise.resolve(result); 205 | }); 206 | } 207 | -------------------------------------------------------------------------------- /lib/cli.ts: -------------------------------------------------------------------------------- 1 | try { 2 | require("typescript"); 3 | } catch (e) { 4 | console.error("typescript is required. please try 'npm install -g typescript'\n"); 5 | } 6 | 7 | import * as ts from "typescript"; 8 | 9 | import * as fs from "fs"; 10 | import * as path from "path"; 11 | import * as commandpost from "commandpost"; 12 | 13 | import * as lib from "./"; 14 | import { getConfigFileName, readFilesFromTsconfig } from "./utils"; 15 | 16 | const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json")).toString()); 17 | 18 | interface RootOptions { 19 | replace: boolean; 20 | verify: boolean; 21 | baseDir: string[]; 22 | stdin: boolean; 23 | tsconfig: boolean; 24 | tslint: boolean; 25 | editorconfig: boolean; 26 | vscode: boolean; 27 | tsfmt: boolean; 28 | useTsconfig: string[]; 29 | useTslint: string[]; 30 | useTsfmt: string[]; 31 | useVscode: string[]; 32 | verbose: boolean; 33 | version: boolean; 34 | } 35 | 36 | interface RootArguments { 37 | files: string[]; 38 | } 39 | 40 | let root = commandpost 41 | .create("tsfmt [files...]") 42 | .option("-r, --replace", "replace .ts file") 43 | .option("--verify", "checking file format") 44 | .option("--baseDir ", "config file lookup from ") 45 | .option("--stdin", "get formatting content from stdin") 46 | .option("--no-tsconfig", "don't read a tsconfig.json") 47 | .option("--no-tslint", "don't read a tslint.json") 48 | .option("--no-editorconfig", "don't read a .editorconfig") 49 | .option("--no-vscode", "don't read a .vscode/settings.json") 50 | .option("--no-tsfmt", "don't read a tsfmt.json") 51 | .option("--useTsconfig ", "using specified config file instead of tsconfig.json") 52 | .option("--useTslint ", "using specified config file instead of tslint.json") 53 | .option("--useTsfmt ", "using specified config file instead of tsfmt.json") 54 | .option("--useVscode ", "using specified config file instead of .vscode/settings.json") 55 | .option("--verbose", "makes output more verbose") 56 | .option("-v, --version", "output the version number") 57 | .action((opts, args) => { 58 | let replace = !!opts.replace; 59 | let verify = !!opts.verify; 60 | let baseDir = opts.baseDir ? opts.baseDir[0] : void 0; 61 | let stdin = !!opts.stdin; 62 | let tsconfig = !!opts.tsconfig; 63 | let tslint = !!opts.tslint; 64 | let editorconfig = !!opts.editorconfig; 65 | let vscode = !!opts.vscode; 66 | let tsfmt = !!opts.tsfmt; 67 | let tsconfigFile = opts.useTsconfig[0] ? path.join(process.cwd(), opts.useTsconfig[0]) : null; 68 | let tslintFile = opts.useTslint[0] ? path.join(process.cwd(), opts.useTslint[0]) : null; 69 | let vscodeFile = opts.useVscode[0] ? path.join(process.cwd(), opts.useVscode[0]) : null; 70 | let tsfmtFile = opts.useTsfmt[0] ? path.join(process.cwd(), opts.useTsfmt[0]) : null; 71 | let verbose = !!opts.verbose; 72 | let version = !!opts.version; 73 | 74 | if (version) { 75 | console.log(`tsfmt : ${packageJson.version}`); 76 | console.log(`tsc : ${ts.version}`); 77 | return; 78 | } 79 | 80 | let files = args.files; 81 | let useTsconfig = false; 82 | if (files.length === 0) { 83 | let configFileName = tsconfigFile || getConfigFileName(baseDir || process.cwd(), "tsconfig.json"); 84 | if (configFileName) { 85 | files = readFilesFromTsconfig(configFileName); 86 | if (verbose) { 87 | console.log(`read: ${configFileName}`); 88 | } 89 | useTsconfig = true; 90 | } 91 | } 92 | 93 | if (files.length === 0 && !opts.stdin) { 94 | process.stdout.write(root.helpText() + "\n"); 95 | return; 96 | } 97 | 98 | if (verbose) { 99 | const printPool: { [name: string]: string; } = {}; 100 | const printSetting = (name: string, value: string | boolean) => { 101 | if (typeof value === "boolean") { 102 | printPool[name] = value ? "ON" : "OFF"; 103 | } else { 104 | printPool[name] = value; 105 | } 106 | }; 107 | const doPrint = () => { 108 | const maxLength = Object.keys(printPool).reduce((p, c) => Math.max(p, c.length), 0); 109 | Object.keys(printPool).forEach(key => { 110 | const value = printPool[key]; 111 | console.log(`${padSpaces(key, maxLength + 1)}: ${value}`); 112 | }); 113 | 114 | function padSpaces(str: string, len: number) { 115 | let result = str; 116 | while (result.length < len) { 117 | result += " "; 118 | } 119 | return result; 120 | } 121 | }; 122 | 123 | printSetting("replace", replace); 124 | printSetting("verify", verify); 125 | printSetting("baseDir", baseDir ? baseDir : process.cwd()); 126 | printSetting("stdin", stdin); 127 | printSetting("files from tsconfig", useTsconfig); 128 | printSetting("tsconfig", tsconfig); 129 | if (tsconfigFile) { 130 | printSetting("specified tsconfig.json", tsconfigFile); 131 | } 132 | printSetting("tslint", tslint); 133 | if (tslintFile) { 134 | printSetting("specified tslint.json", tslintFile); 135 | } 136 | printSetting("editorconfig", editorconfig); 137 | printSetting("vscode", vscode); 138 | if (vscodeFile) { 139 | printSetting("specified vscode settings.json", vscodeFile); 140 | } 141 | printSetting("tsfmt", tsfmt); 142 | if (tsfmtFile) { 143 | printSetting("specified tsfmt.json", tsfmtFile); 144 | } 145 | 146 | doPrint(); 147 | } 148 | 149 | if (stdin) { 150 | if (replace) { 151 | errorHandler("--stdin option can not use with --replace option"); 152 | return; 153 | } 154 | lib 155 | .processStream(files[0] || "temp.ts", process.stdin, { 156 | replace: replace, 157 | verify: verify, 158 | baseDir: baseDir, 159 | tsconfig: tsconfig, 160 | tsconfigFile: tsconfigFile, 161 | tslint: tslint, 162 | tslintFile: tslintFile, 163 | editorconfig: editorconfig, 164 | vscode: vscode, 165 | vscodeFile: vscodeFile, 166 | tsfmt: tsfmt, 167 | tsfmtFile: tsfmtFile, 168 | verbose: verbose, 169 | }) 170 | .then(result => { 171 | let resultMap: lib.ResultMap = {}; 172 | resultMap[result.fileName] = result; 173 | return resultMap; 174 | }) 175 | .then(showResultHandler) 176 | .catch(errorHandler); 177 | } else { 178 | lib 179 | .processFiles(files, { 180 | replace: replace, 181 | verify: verify, 182 | baseDir: baseDir, 183 | tsconfig: tsconfig, 184 | tsconfigFile: tsconfigFile, 185 | tslint: tslint, 186 | tslintFile: tslintFile, 187 | editorconfig: editorconfig, 188 | vscode: vscode, 189 | vscodeFile: vscodeFile, 190 | tsfmt: tsfmt, 191 | tsfmtFile: tsfmtFile, 192 | verbose: verbose, 193 | }) 194 | .then(showResultHandler) 195 | .catch(errorHandler); 196 | } 197 | }); 198 | 199 | commandpost 200 | .exec(root, process.argv) 201 | .catch(errorHandler); 202 | 203 | function showResultHandler(resultMap: lib.ResultMap): Promise { 204 | 205 | let hasError = Object.keys(resultMap).filter(fileName => resultMap[fileName].error).length !== 0; 206 | if (hasError) { 207 | Object.keys(resultMap) 208 | .map(fileName => resultMap[fileName]) 209 | .filter(result => result.error) 210 | .forEach(result => process.stderr.write(result.message)); 211 | process.exit(1); 212 | } else { 213 | Object.keys(resultMap) 214 | .map(fileName => resultMap[fileName]) 215 | .forEach(result => { 216 | if (result.message) { 217 | process.stdout.write(result.message); 218 | } 219 | }); 220 | } 221 | return Promise.resolve(null); 222 | } 223 | 224 | function errorHandler(err: any): Promise { 225 | 226 | if (err instanceof Error) { 227 | console.error(err.stack); 228 | } else { 229 | console.error(err); 230 | } 231 | return Promise.resolve(null).then(() => { 232 | process.exit(1); 233 | return null; 234 | }); 235 | } 236 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/c/main.ts: -------------------------------------------------------------------------------- 1 | class Vector { 2 | 3 | constructor(public x: number, public y: number, public z: number) { } 4 | 5 | static times(k: number, v: Vector) { 6 | return new Vector(k * v.x, k * v.y, k * v.z); 7 | } 8 | 9 | static minus(v1: Vector, v2: Vector) { 10 | return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); 11 | } 12 | 13 | static plus(v1: Vector, v2: Vector) { 14 | return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); 15 | } 16 | 17 | static dot(v1: Vector, v2: Vector) { 18 | return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; 19 | } 20 | 21 | static mag(v: Vector) { 22 | return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); 23 | } 24 | 25 | static norm(v: Vector) { 26 | var mag = Vector.mag(v); 27 | var div = (mag === 0) ? Infinity : 1.0 / mag; 28 | return Vector.times(div, v); 29 | } 30 | 31 | static cross(v1: Vector, v2: Vector) { 32 | return new Vector(v1.y * v2.z - v1.z * v2.y, 33 | v1.z * v2.x - v1.x * v2.z, 34 | v1.x * v2.y - v1.y * v2.x); 35 | } 36 | 37 | } 38 | 39 | class Color { 40 | 41 | constructor(public r: number, public g: number, public b: number) { } 42 | 43 | static scale(k: number, v: Color) { 44 | return new Color(k * v.r, k * v.g, k * v.b); 45 | } 46 | 47 | static plus(v1: Color, v2: Color) { 48 | return new Color(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b); 49 | } 50 | 51 | static times(v1: Color, v2: Color) { 52 | return new Color(v1.r * v2.r, v1.g * v2.g, v1.b * v2.b); 53 | } 54 | 55 | static white = new Color(1.0, 1.0, 1.0); 56 | static grey = new Color(0.5, 0.5, 0.5); 57 | static black = new Color(0.0, 0.0, 0.0); 58 | static background = Color.black; 59 | static defaultColor = Color.black; 60 | 61 | static toDrawingColor(c: Color) { 62 | var legalize = d => d > 1 ? 1 : d; 63 | return { 64 | r: Math.floor(legalize(c.r) * 255), 65 | g: Math.floor(legalize(c.g) * 255), 66 | b: Math.floor(legalize(c.b) * 255) 67 | } 68 | } 69 | 70 | } 71 | 72 | class Camera { 73 | 74 | forward: Vector; 75 | right: Vector; 76 | up: Vector; 77 | 78 | constructor(public pos: Vector, lookAt: Vector) { 79 | var down = new Vector(0.0, -1.0, 0.0); 80 | this.forward = Vector.norm(Vector.minus(lookAt, this.pos)); 81 | this.right = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, down))); 82 | this.up = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, this.right))); 83 | } 84 | 85 | } 86 | 87 | interface Ray { 88 | start: Vector; 89 | dir: Vector; 90 | } 91 | 92 | interface Intersection { 93 | thing: Thing; 94 | ray: Ray; 95 | dist: number; 96 | } 97 | 98 | interface Surface { 99 | diffuse: (pos: Vector) => Color; 100 | specular: (pos: Vector) => Color; 101 | reflect: (pos: Vector) => number; 102 | roughness: number; 103 | } 104 | 105 | interface Thing { 106 | intersect: (ray: Ray) => Intersection; 107 | normal: (pos: Vector) => Vector; 108 | surface: Surface; 109 | } 110 | 111 | interface Light { 112 | pos: Vector; 113 | color: Color; 114 | } 115 | 116 | interface Scene { 117 | things: Thing[]; 118 | lights: Light[]; 119 | camera: Camera; 120 | } 121 | 122 | class Sphere implements Thing { 123 | 124 | radius2: number; 125 | 126 | constructor(public center: Vector, radius: number, public surface: Surface) { 127 | this.radius2 = radius * radius; 128 | } 129 | 130 | normal(pos: Vector): Vector { 131 | return Vector.norm(Vector.minus(pos, this.center)); 132 | } 133 | 134 | intersect(ray: Ray) { 135 | var eo = Vector.minus(this.center, ray.start); 136 | var v = Vector.dot(eo, ray.dir); 137 | var dist = 0; 138 | if (v >= 0) { 139 | var disc = this.radius2 - (Vector.dot(eo, eo) - v * v); 140 | if (disc >= 0) { 141 | dist = v - Math.sqrt(disc); 142 | } 143 | } 144 | if (dist === 0) { 145 | return null; 146 | } else { 147 | return { thing: this, ray: ray, dist: dist }; 148 | } 149 | } 150 | 151 | } 152 | 153 | class Plane implements Thing { 154 | 155 | normal: (pos: Vector) => Vector; 156 | intersect: (ray: Ray) => Intersection; 157 | 158 | constructor(norm: Vector, offset: number, public surface: Surface) { 159 | this.normal = function(pos: Vector) { return norm; } 160 | this.intersect = function(ray: Ray): Intersection { 161 | var denom = Vector.dot(norm, ray.dir); 162 | if (denom > 0) { 163 | return null; 164 | } else { 165 | var dist = (Vector.dot(norm, ray.start) + offset) / (-denom); 166 | return { thing: this, ray: ray, dist: dist }; 167 | } 168 | } 169 | } 170 | 171 | } 172 | 173 | module Surfaces { 174 | 175 | export var shiny: Surface = { 176 | diffuse: function(pos) { return Color.white; }, 177 | specular: function(pos) { return Color.grey; }, 178 | reflect: function(pos) { return 0.7; }, 179 | roughness: 250 180 | } 181 | 182 | export var checkerboard: Surface = { 183 | diffuse: function(pos) { 184 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 185 | return Color.white; 186 | } else { 187 | return Color.black; 188 | } 189 | }, 190 | specular: function(pos) { return Color.white; }, 191 | reflect: function(pos) { 192 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 193 | return 0.1; 194 | } else { 195 | return 0.7; 196 | } 197 | }, 198 | roughness: 150 199 | } 200 | 201 | } 202 | 203 | 204 | class RayTracer { 205 | 206 | private maxDepth = 5; 207 | 208 | private intersections(ray: Ray, scene: Scene) { 209 | var closest = +Infinity; 210 | var closestInter: Intersection = undefined; 211 | for (var i in scene.things) { 212 | var inter = scene.things[i].intersect(ray); 213 | if (inter != null && inter.dist < closest) { 214 | closestInter = inter; 215 | closest = inter.dist; 216 | } 217 | } 218 | return closestInter; 219 | } 220 | 221 | private testRay(ray: Ray, scene: Scene) { 222 | var isect = this.intersections(ray, scene); 223 | if (isect != null) { 224 | return isect.dist; 225 | } else { 226 | return undefined; 227 | } 228 | } 229 | 230 | private traceRay(ray: Ray, scene: Scene, depth: number): Color { 231 | var isect = this.intersections(ray, scene); 232 | if (isect === undefined) { 233 | return Color.background; 234 | } else { 235 | return this.shade(isect, scene, depth); 236 | } 237 | } 238 | 239 | private shade(isect: Intersection, scene: Scene, depth: number) { 240 | var d = isect.ray.dir; 241 | var pos = Vector.plus(Vector.times(isect.dist, d), isect.ray.start); 242 | var normal = isect.thing.normal(pos); 243 | var reflectDir = Vector.minus(d, Vector.times(2, Vector.times(Vector.dot(normal, d), normal))); 244 | var naturalColor = Color.plus(Color.background, 245 | this.getNaturalColor(isect.thing, pos, normal, reflectDir, scene)); 246 | var reflectedColor = (depth >= this.maxDepth) ? Color.grey : this.getReflectionColor(isect.thing, pos, normal, reflectDir, scene, depth); 247 | return Color.plus(naturalColor, reflectedColor); 248 | } 249 | 250 | private getReflectionColor(thing: Thing, pos: Vector, normal: Vector, rd: Vector, scene: Scene, depth: number) { 251 | return Color.scale(thing.surface.reflect(pos), this.traceRay({ start: pos, dir: rd }, scene, depth + 1)); 252 | } 253 | 254 | private getNaturalColor(thing: Thing, pos: Vector, norm: Vector, rd: Vector, scene: Scene) { 255 | var addLight = (col, light) => { 256 | var ldis = Vector.minus(light.pos, pos); 257 | var livec = Vector.norm(ldis); 258 | var neatIsect = this.testRay({ start: pos, dir: livec }, scene); 259 | var isInShadow = (neatIsect === undefined) ? false : (neatIsect <= Vector.mag(ldis)); 260 | if (isInShadow) { 261 | return col; 262 | } else { 263 | var illum = Vector.dot(livec, norm); 264 | var lcolor = (illum > 0) ? Color.scale(illum, light.color) 265 | : Color.defaultColor; 266 | var specular = Vector.dot(livec, Vector.norm(rd)); 267 | var scolor = (specular > 0) ? Color.scale(Math.pow(specular, thing.surface.roughness), light.color) 268 | : Color.defaultColor; 269 | return Color.plus(col, Color.plus(Color.times(thing.surface.diffuse(pos), lcolor), 270 | Color.times(thing.surface.specular(pos), scolor))); 271 | } 272 | } 273 | return scene.lights.reduce(addLight, Color.defaultColor); 274 | } 275 | 276 | render(scene, ctx, screenWidth, screenHeight) { 277 | var getPoint = (x, y, camera) => { 278 | var recenterX = x => (x - (screenWidth / 2.0)) / 2.0 / screenWidth; 279 | var recenterY = y => -(y - (screenHeight / 2.0)) / 2.0 / screenHeight; 280 | return Vector.norm(Vector.plus(camera.forward, Vector.plus(Vector.times(recenterX(x), camera.right), Vector.times(recenterY(y), camera.up)))); 281 | } 282 | for (var y = 0; y < screenHeight; y++) { 283 | for (var x = 0; x < screenWidth; x++) { 284 | var color = this.traceRay({ start: scene.camera.pos, dir: getPoint(x, y, scene.camera) }, scene, 0); 285 | var c = Color.toDrawingColor(color); 286 | ctx.fillStyle = "rgb(" + String(c.r) + ", " + String(c.g) + ", " + String(c.b) + ")"; 287 | ctx.fillRect(x, y, x + 1, y + 1); 288 | } 289 | } 290 | } 291 | 292 | } 293 | 294 | 295 | function defaultScene(): Scene { 296 | return { 297 | things: [new Plane(new Vector(0.0, 1.0, 0.0), 0.0, Surfaces.checkerboard), 298 | new Sphere(new Vector(0.0, 1.0, -0.25), 1.0, Surfaces.shiny), 299 | new Sphere(new Vector(-1.0, 0.5, 1.5), 0.5, Surfaces.shiny)], 300 | lights: [{ pos: new Vector(-2.0, 2.5, 0.0), color: new Color(0.49, 0.07, 0.07) }, 301 | { pos: new Vector(1.5, 2.5, 1.5), color: new Color(0.07, 0.07, 0.49) }, 302 | { pos: new Vector(1.5, 2.5, -1.5), color: new Color(0.07, 0.49, 0.071) }, 303 | { pos: new Vector(0.0, 3.5, 0.0), color: new Color(0.21, 0.21, 0.35) }], 304 | camera: new Camera(new Vector(3.0, 2.0, 4.0), new Vector(-1.0, 0.5, 0.0)) 305 | }; 306 | } 307 | 308 | function exec() { 309 | var canv = document.createElement("canvas"); 310 | canv.width = 256; 311 | canv.height = 256; 312 | document.body.appendChild(canv); 313 | var ctx = canv.getContext("2d"); 314 | var rayTracer = new RayTracer(); 315 | return rayTracer.render(defaultScene(), ctx, 256, 256); 316 | } 317 | 318 | exec(); 319 | -------------------------------------------------------------------------------- /test/fixture/default/main.ts: -------------------------------------------------------------------------------- 1 | class Vector { 2 | 3 | constructor(public x: number, public y: number, public z: number) { } 4 | 5 | static times(k: number, v: Vector) { 6 | return new Vector(k * v.x, k * v.y, k * v.z); 7 | } 8 | 9 | static minus(v1: Vector, v2: Vector) { 10 | return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); 11 | } 12 | 13 | static plus(v1: Vector, v2: Vector) { 14 | return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); 15 | } 16 | 17 | static dot(v1: Vector, v2: Vector) { 18 | return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; 19 | } 20 | 21 | static mag(v: Vector) { 22 | return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); 23 | } 24 | 25 | static norm(v: Vector) { 26 | var mag = Vector.mag(v); 27 | var div = (mag === 0) ? Infinity : 1.0 / mag; 28 | return Vector.times(div, v); 29 | } 30 | 31 | static cross(v1: Vector, v2: Vector) { 32 | return new Vector(v1.y * v2.z - v1.z * v2.y, 33 | v1.z * v2.x - v1.x * v2.z, 34 | v1.x * v2.y - v1.y * v2.x); 35 | } 36 | 37 | } 38 | 39 | class Color { 40 | 41 | constructor(public r: number, public g: number, public b: number) { } 42 | 43 | static scale(k: number, v: Color) { 44 | return new Color(k * v.r, k * v.g, k * v.b); 45 | } 46 | 47 | static plus(v1: Color, v2: Color) { 48 | return new Color(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b); 49 | } 50 | 51 | static times(v1: Color, v2: Color) { 52 | return new Color(v1.r * v2.r, v1.g * v2.g, v1.b * v2.b); 53 | } 54 | 55 | static white = new Color(1.0, 1.0, 1.0); 56 | static grey = new Color(0.5, 0.5, 0.5); 57 | static black = new Color(0.0, 0.0, 0.0); 58 | static background = Color.black; 59 | static defaultColor = Color.black; 60 | 61 | static toDrawingColor(c: Color) { 62 | var legalize = d => d > 1 ? 1 : d; 63 | return { 64 | r: Math.floor(legalize(c.r) * 255), 65 | g: Math.floor(legalize(c.g) * 255), 66 | b: Math.floor(legalize(c.b) * 255) 67 | } 68 | } 69 | 70 | } 71 | 72 | class Camera { 73 | 74 | forward: Vector; 75 | right: Vector; 76 | up: Vector; 77 | 78 | constructor(public pos: Vector, lookAt: Vector) { 79 | var down = new Vector(0.0, -1.0, 0.0); 80 | this.forward = Vector.norm(Vector.minus(lookAt, this.pos)); 81 | this.right = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, down))); 82 | this.up = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, this.right))); 83 | } 84 | 85 | } 86 | 87 | interface Ray { 88 | start: Vector; 89 | dir: Vector; 90 | } 91 | 92 | interface Intersection { 93 | thing: Thing; 94 | ray: Ray; 95 | dist: number; 96 | } 97 | 98 | interface Surface { 99 | diffuse: (pos: Vector) => Color; 100 | specular: (pos: Vector) => Color; 101 | reflect: (pos: Vector) => number; 102 | roughness: number; 103 | } 104 | 105 | interface Thing { 106 | intersect: (ray: Ray) => Intersection; 107 | normal: (pos: Vector) => Vector; 108 | surface: Surface; 109 | } 110 | 111 | interface Light { 112 | pos: Vector; 113 | color: Color; 114 | } 115 | 116 | interface Scene { 117 | things: Thing[]; 118 | lights: Light[]; 119 | camera: Camera; 120 | } 121 | 122 | class Sphere implements Thing { 123 | 124 | radius2: number; 125 | 126 | constructor(public center: Vector, radius: number, public surface: Surface) { 127 | this.radius2 = radius * radius; 128 | } 129 | 130 | normal(pos: Vector): Vector { 131 | return Vector.norm(Vector.minus(pos, this.center)); 132 | } 133 | 134 | intersect(ray: Ray) { 135 | var eo = Vector.minus(this.center, ray.start); 136 | var v = Vector.dot(eo, ray.dir); 137 | var dist = 0; 138 | if (v >= 0) { 139 | var disc = this.radius2 - (Vector.dot(eo, eo) - v * v); 140 | if (disc >= 0) { 141 | dist = v - Math.sqrt(disc); 142 | } 143 | } 144 | if (dist === 0) { 145 | return null; 146 | } else { 147 | return { thing: this, ray: ray, dist: dist }; 148 | } 149 | } 150 | 151 | } 152 | 153 | class Plane implements Thing { 154 | 155 | normal: (pos: Vector) => Vector; 156 | intersect: (ray: Ray) => Intersection; 157 | 158 | constructor(norm: Vector, offset: number, public surface: Surface) { 159 | this.normal = function(pos: Vector) { return norm; } 160 | this.intersect = function(ray: Ray): Intersection { 161 | var denom = Vector.dot(norm, ray.dir); 162 | if (denom > 0) { 163 | return null; 164 | } else { 165 | var dist = (Vector.dot(norm, ray.start) + offset) / (-denom); 166 | return { thing: this, ray: ray, dist: dist }; 167 | } 168 | } 169 | } 170 | 171 | } 172 | 173 | module Surfaces { 174 | 175 | export var shiny: Surface = { 176 | diffuse: function(pos) { return Color.white; }, 177 | specular: function(pos) { return Color.grey; }, 178 | reflect: function(pos) { return 0.7; }, 179 | roughness: 250 180 | } 181 | 182 | export var checkerboard: Surface = { 183 | diffuse: function(pos) { 184 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 185 | return Color.white; 186 | } else { 187 | return Color.black; 188 | } 189 | }, 190 | specular: function(pos) { return Color.white; }, 191 | reflect: function(pos) { 192 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 193 | return 0.1; 194 | } else { 195 | return 0.7; 196 | } 197 | }, 198 | roughness: 150 199 | } 200 | 201 | } 202 | 203 | 204 | class RayTracer { 205 | 206 | private maxDepth = 5; 207 | 208 | private intersections(ray: Ray, scene: Scene) { 209 | var closest = +Infinity; 210 | var closestInter: Intersection = undefined; 211 | for (var i in scene.things) { 212 | var inter = scene.things[i].intersect(ray); 213 | if (inter != null && inter.dist < closest) { 214 | closestInter = inter; 215 | closest = inter.dist; 216 | } 217 | } 218 | return closestInter; 219 | } 220 | 221 | private testRay(ray: Ray, scene: Scene) { 222 | var isect = this.intersections(ray, scene); 223 | if (isect != null) { 224 | return isect.dist; 225 | } else { 226 | return undefined; 227 | } 228 | } 229 | 230 | private traceRay(ray: Ray, scene: Scene, depth: number): Color { 231 | var isect = this.intersections(ray, scene); 232 | if (isect === undefined) { 233 | return Color.background; 234 | } else { 235 | return this.shade(isect, scene, depth); 236 | } 237 | } 238 | 239 | private shade(isect: Intersection, scene: Scene, depth: number) { 240 | var d = isect.ray.dir; 241 | var pos = Vector.plus(Vector.times(isect.dist, d), isect.ray.start); 242 | var normal = isect.thing.normal(pos); 243 | var reflectDir = Vector.minus(d, Vector.times(2, Vector.times(Vector.dot(normal, d), normal))); 244 | var naturalColor = Color.plus(Color.background, 245 | this.getNaturalColor(isect.thing, pos, normal, reflectDir, scene)); 246 | var reflectedColor = (depth >= this.maxDepth) ? Color.grey : this.getReflectionColor(isect.thing, pos, normal, reflectDir, scene, depth); 247 | return Color.plus(naturalColor, reflectedColor); 248 | } 249 | 250 | private getReflectionColor(thing: Thing, pos: Vector, normal: Vector, rd: Vector, scene: Scene, depth: number) { 251 | return Color.scale(thing.surface.reflect(pos), this.traceRay({ start: pos, dir: rd }, scene, depth + 1)); 252 | } 253 | 254 | private getNaturalColor(thing: Thing, pos: Vector, norm: Vector, rd: Vector, scene: Scene) { 255 | var addLight = (col, light) => { 256 | var ldis = Vector.minus(light.pos, pos); 257 | var livec = Vector.norm(ldis); 258 | var neatIsect = this.testRay({ start: pos, dir: livec }, scene); 259 | var isInShadow = (neatIsect === undefined) ? false : (neatIsect <= Vector.mag(ldis)); 260 | if (isInShadow) { 261 | return col; 262 | } else { 263 | var illum = Vector.dot(livec, norm); 264 | var lcolor = (illum > 0) ? Color.scale(illum, light.color) 265 | : Color.defaultColor; 266 | var specular = Vector.dot(livec, Vector.norm(rd)); 267 | var scolor = (specular > 0) ? Color.scale(Math.pow(specular, thing.surface.roughness), light.color) 268 | : Color.defaultColor; 269 | return Color.plus(col, Color.plus(Color.times(thing.surface.diffuse(pos), lcolor), 270 | Color.times(thing.surface.specular(pos), scolor))); 271 | } 272 | } 273 | return scene.lights.reduce(addLight, Color.defaultColor); 274 | } 275 | 276 | render(scene, ctx, screenWidth, screenHeight) { 277 | var getPoint = (x, y, camera) => { 278 | var recenterX = x => (x - (screenWidth / 2.0)) / 2.0 / screenWidth; 279 | var recenterY = y => -(y - (screenHeight / 2.0)) / 2.0 / screenHeight; 280 | return Vector.norm(Vector.plus(camera.forward, Vector.plus(Vector.times(recenterX(x), camera.right), Vector.times(recenterY(y), camera.up)))); 281 | } 282 | for (var y = 0; y < screenHeight; y++) { 283 | for (var x = 0; x < screenWidth; x++) { 284 | var color = this.traceRay({ start: scene.camera.pos, dir: getPoint(x, y, scene.camera) }, scene, 0); 285 | var c = Color.toDrawingColor(color); 286 | ctx.fillStyle = "rgb(" + String(c.r) + ", " + String(c.g) + ", " + String(c.b) + ")"; 287 | ctx.fillRect(x, y, x + 1, y + 1); 288 | } 289 | } 290 | } 291 | 292 | } 293 | 294 | 295 | function defaultScene(): Scene { 296 | return { 297 | things: [new Plane(new Vector(0.0, 1.0, 0.0), 0.0, Surfaces.checkerboard), 298 | new Sphere(new Vector(0.0, 1.0, -0.25), 1.0, Surfaces.shiny), 299 | new Sphere(new Vector(-1.0, 0.5, 1.5), 0.5, Surfaces.shiny)], 300 | lights: [{ pos: new Vector(-2.0, 2.5, 0.0), color: new Color(0.49, 0.07, 0.07) }, 301 | { pos: new Vector(1.5, 2.5, 1.5), color: new Color(0.07, 0.07, 0.49) }, 302 | { pos: new Vector(1.5, 2.5, -1.5), color: new Color(0.07, 0.49, 0.071) }, 303 | { pos: new Vector(0.0, 3.5, 0.0), color: new Color(0.21, 0.21, 0.35) }], 304 | camera: new Camera(new Vector(3.0, 2.0, 4.0), new Vector(-1.0, 0.5, 0.0)) 305 | }; 306 | } 307 | 308 | function exec() { 309 | var canv = document.createElement("canvas"); 310 | canv.width = 256; 311 | canv.height = 256; 312 | document.body.appendChild(canv); 313 | var ctx = canv.getContext("2d"); 314 | var rayTracer = new RayTracer(); 315 | return rayTracer.render(defaultScene(), ctx, 256, 256); 316 | } 317 | 318 | exec(); 319 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/b/main.ts: -------------------------------------------------------------------------------- 1 | class Vector { 2 | 3 | constructor(public x: number, public y: number, public z: number) { } 4 | 5 | static times(k: number, v: Vector) { 6 | return new Vector(k * v.x, k * v.y, k * v.z); 7 | } 8 | 9 | static minus(v1: Vector, v2: Vector) { 10 | return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); 11 | } 12 | 13 | static plus(v1: Vector, v2: Vector) { 14 | return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); 15 | } 16 | 17 | static dot(v1: Vector, v2: Vector) { 18 | return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; 19 | } 20 | 21 | static mag(v: Vector) { 22 | return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); 23 | } 24 | 25 | static norm(v: Vector) { 26 | var mag = Vector.mag(v); 27 | var div = (mag === 0) ? Infinity : 1.0 / mag; 28 | return Vector.times(div, v); 29 | } 30 | 31 | static cross(v1: Vector, v2: Vector) { 32 | return new Vector(v1.y * v2.z - v1.z * v2.y, 33 | v1.z * v2.x - v1.x * v2.z, 34 | v1.x * v2.y - v1.y * v2.x); 35 | } 36 | 37 | } 38 | 39 | class Color { 40 | 41 | constructor(public r: number, public g: number, public b: number) { } 42 | 43 | static scale(k: number, v: Color) { 44 | return new Color(k * v.r, k * v.g, k * v.b); 45 | } 46 | 47 | static plus(v1: Color, v2: Color) { 48 | return new Color(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b); 49 | } 50 | 51 | static times(v1: Color, v2: Color) { 52 | return new Color(v1.r * v2.r, v1.g * v2.g, v1.b * v2.b); 53 | } 54 | 55 | static white = new Color(1.0, 1.0, 1.0); 56 | static grey = new Color(0.5, 0.5, 0.5); 57 | static black = new Color(0.0, 0.0, 0.0); 58 | static background = Color.black; 59 | static defaultColor = Color.black; 60 | 61 | static toDrawingColor(c: Color) { 62 | var legalize = d => d > 1 ? 1 : d; 63 | return { 64 | r: Math.floor(legalize(c.r) * 255), 65 | g: Math.floor(legalize(c.g) * 255), 66 | b: Math.floor(legalize(c.b) * 255) 67 | } 68 | } 69 | 70 | } 71 | 72 | class Camera { 73 | 74 | forward: Vector; 75 | right: Vector; 76 | up: Vector; 77 | 78 | constructor(public pos: Vector, lookAt: Vector) { 79 | var down = new Vector(0.0, -1.0, 0.0); 80 | this.forward = Vector.norm(Vector.minus(lookAt, this.pos)); 81 | this.right = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, down))); 82 | this.up = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, this.right))); 83 | } 84 | 85 | } 86 | 87 | interface Ray { 88 | start: Vector; 89 | dir: Vector; 90 | } 91 | 92 | interface Intersection { 93 | thing: Thing; 94 | ray: Ray; 95 | dist: number; 96 | } 97 | 98 | interface Surface { 99 | diffuse: (pos: Vector) => Color; 100 | specular: (pos: Vector) => Color; 101 | reflect: (pos: Vector) => number; 102 | roughness: number; 103 | } 104 | 105 | interface Thing { 106 | intersect: (ray: Ray) => Intersection; 107 | normal: (pos: Vector) => Vector; 108 | surface: Surface; 109 | } 110 | 111 | interface Light { 112 | pos: Vector; 113 | color: Color; 114 | } 115 | 116 | interface Scene { 117 | things: Thing[]; 118 | lights: Light[]; 119 | camera: Camera; 120 | } 121 | 122 | class Sphere implements Thing { 123 | 124 | radius2: number; 125 | 126 | constructor(public center: Vector, radius: number, public surface: Surface) { 127 | this.radius2 = radius * radius; 128 | } 129 | 130 | normal(pos: Vector): Vector { 131 | return Vector.norm(Vector.minus(pos, this.center)); 132 | } 133 | 134 | intersect(ray: Ray) { 135 | var eo = Vector.minus(this.center, ray.start); 136 | var v = Vector.dot(eo, ray.dir); 137 | var dist = 0; 138 | if (v >= 0) { 139 | var disc = this.radius2 - (Vector.dot(eo, eo) - v * v); 140 | if (disc >= 0) { 141 | dist = v - Math.sqrt(disc); 142 | } 143 | } 144 | if (dist === 0) { 145 | return null; 146 | } else { 147 | return { thing: this, ray: ray, dist: dist }; 148 | } 149 | } 150 | 151 | } 152 | 153 | class Plane implements Thing { 154 | 155 | normal: (pos: Vector) => Vector; 156 | intersect: (ray: Ray) => Intersection; 157 | 158 | constructor(norm: Vector, offset: number, public surface: Surface) { 159 | this.normal = function(pos: Vector) { return norm; } 160 | this.intersect = function(ray: Ray): Intersection { 161 | var denom = Vector.dot(norm, ray.dir); 162 | if (denom > 0) { 163 | return null; 164 | } else { 165 | var dist = (Vector.dot(norm, ray.start) + offset) / (-denom); 166 | return { thing: this, ray: ray, dist: dist }; 167 | } 168 | } 169 | } 170 | 171 | } 172 | 173 | module Surfaces { 174 | 175 | export var shiny: Surface = { 176 | diffuse: function(pos) { return Color.white; }, 177 | specular: function(pos) { return Color.grey; }, 178 | reflect: function(pos) { return 0.7; }, 179 | roughness: 250 180 | } 181 | 182 | export var checkerboard: Surface = { 183 | diffuse: function(pos) { 184 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 185 | return Color.white; 186 | } else { 187 | return Color.black; 188 | } 189 | }, 190 | specular: function(pos) { return Color.white; }, 191 | reflect: function(pos) { 192 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 193 | return 0.1; 194 | } else { 195 | return 0.7; 196 | } 197 | }, 198 | roughness: 150 199 | } 200 | 201 | } 202 | 203 | 204 | class RayTracer { 205 | 206 | private maxDepth = 5; 207 | 208 | private intersections(ray: Ray, scene: Scene) { 209 | var closest = +Infinity; 210 | var closestInter: Intersection = undefined; 211 | for (var i in scene.things) { 212 | var inter = scene.things[i].intersect(ray); 213 | if (inter != null && inter.dist < closest) { 214 | closestInter = inter; 215 | closest = inter.dist; 216 | } 217 | } 218 | return closestInter; 219 | } 220 | 221 | private testRay(ray: Ray, scene: Scene) { 222 | var isect = this.intersections(ray, scene); 223 | if (isect != null) { 224 | return isect.dist; 225 | } else { 226 | return undefined; 227 | } 228 | } 229 | 230 | private traceRay(ray: Ray, scene: Scene, depth: number): Color { 231 | var isect = this.intersections(ray, scene); 232 | if (isect === undefined) { 233 | return Color.background; 234 | } else { 235 | return this.shade(isect, scene, depth); 236 | } 237 | } 238 | 239 | private shade(isect: Intersection, scene: Scene, depth: number) { 240 | var d = isect.ray.dir; 241 | var pos = Vector.plus(Vector.times(isect.dist, d), isect.ray.start); 242 | var normal = isect.thing.normal(pos); 243 | var reflectDir = Vector.minus(d, Vector.times(2, Vector.times(Vector.dot(normal, d), normal))); 244 | var naturalColor = Color.plus(Color.background, 245 | this.getNaturalColor(isect.thing, pos, normal, reflectDir, scene)); 246 | var reflectedColor = (depth >= this.maxDepth) ? Color.grey : this.getReflectionColor(isect.thing, pos, normal, reflectDir, scene, depth); 247 | return Color.plus(naturalColor, reflectedColor); 248 | } 249 | 250 | private getReflectionColor(thing: Thing, pos: Vector, normal: Vector, rd: Vector, scene: Scene, depth: number) { 251 | return Color.scale(thing.surface.reflect(pos), this.traceRay({ start: pos, dir: rd }, scene, depth + 1)); 252 | } 253 | 254 | private getNaturalColor(thing: Thing, pos: Vector, norm: Vector, rd: Vector, scene: Scene) { 255 | var addLight = (col, light) => { 256 | var ldis = Vector.minus(light.pos, pos); 257 | var livec = Vector.norm(ldis); 258 | var neatIsect = this.testRay({ start: pos, dir: livec }, scene); 259 | var isInShadow = (neatIsect === undefined) ? false : (neatIsect <= Vector.mag(ldis)); 260 | if (isInShadow) { 261 | return col; 262 | } else { 263 | var illum = Vector.dot(livec, norm); 264 | var lcolor = (illum > 0) ? Color.scale(illum, light.color) 265 | : Color.defaultColor; 266 | var specular = Vector.dot(livec, Vector.norm(rd)); 267 | var scolor = (specular > 0) ? Color.scale(Math.pow(specular, thing.surface.roughness), light.color) 268 | : Color.defaultColor; 269 | return Color.plus(col, Color.plus(Color.times(thing.surface.diffuse(pos), lcolor), 270 | Color.times(thing.surface.specular(pos), scolor))); 271 | } 272 | } 273 | return scene.lights.reduce(addLight, Color.defaultColor); 274 | } 275 | 276 | render(scene, ctx, screenWidth, screenHeight) { 277 | var getPoint = (x, y, camera) => { 278 | var recenterX = x => (x - (screenWidth / 2.0)) / 2.0 / screenWidth; 279 | var recenterY = y => -(y - (screenHeight / 2.0)) / 2.0 / screenHeight; 280 | return Vector.norm(Vector.plus(camera.forward, Vector.plus(Vector.times(recenterX(x), camera.right), Vector.times(recenterY(y), camera.up)))); 281 | } 282 | for (var y = 0; y < screenHeight; y++) { 283 | for (var x = 0; x < screenWidth; x++) { 284 | var color = this.traceRay({ start: scene.camera.pos, dir: getPoint(x, y, scene.camera) }, scene, 0); 285 | var c = Color.toDrawingColor(color); 286 | ctx.fillStyle = "rgb(" + String(c.r) + ", " + String(c.g) + ", " + String(c.b) + ")"; 287 | ctx.fillRect(x, y, x + 1, y + 1); 288 | } 289 | } 290 | } 291 | 292 | } 293 | 294 | 295 | function defaultScene(): Scene { 296 | return { 297 | things: [new Plane(new Vector(0.0, 1.0, 0.0), 0.0, Surfaces.checkerboard), 298 | new Sphere(new Vector(0.0, 1.0, -0.25), 1.0, Surfaces.shiny), 299 | new Sphere(new Vector(-1.0, 0.5, 1.5), 0.5, Surfaces.shiny)], 300 | lights: [{ pos: new Vector(-2.0, 2.5, 0.0), color: new Color(0.49, 0.07, 0.07) }, 301 | { pos: new Vector(1.5, 2.5, 1.5), color: new Color(0.07, 0.07, 0.49) }, 302 | { pos: new Vector(1.5, 2.5, -1.5), color: new Color(0.07, 0.49, 0.071) }, 303 | { pos: new Vector(0.0, 3.5, 0.0), color: new Color(0.21, 0.21, 0.35) }], 304 | camera: new Camera(new Vector(3.0, 2.0, 4.0), new Vector(-1.0, 0.5, 0.0)) 305 | }; 306 | } 307 | 308 | function exec() { 309 | var canv = document.createElement("canvas"); 310 | canv.width = 256; 311 | canv.height = 256; 312 | document.body.appendChild(canv); 313 | var ctx = canv.getContext("2d"); 314 | var rayTracer = new RayTracer(); 315 | return rayTracer.render(defaultScene(), ctx, 256, 256); 316 | } 317 | 318 | exec(); 319 | -------------------------------------------------------------------------------- /test/fixture/tsfmt/j/main.ts: -------------------------------------------------------------------------------- 1 | class Vector { 2 | 3 | constructor(public x: number, public y: number, public z: number) { } 4 | 5 | static times(k: number, v: Vector) { 6 | return new Vector(k * v.x, k * v.y, k * v.z); 7 | } 8 | 9 | static minus(v1: Vector, v2: Vector) { 10 | return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); 11 | } 12 | 13 | static plus(v1: Vector, v2: Vector) { 14 | return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); 15 | } 16 | 17 | static dot(v1: Vector, v2: Vector) { 18 | return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; 19 | } 20 | 21 | static mag(v: Vector) { 22 | return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); 23 | } 24 | 25 | static norm(v: Vector) { 26 | var mag = Vector.mag(v); 27 | var div = (mag === 0) ? Infinity : 1.0 / mag; 28 | return Vector.times(div, v); 29 | } 30 | 31 | static cross(v1: Vector, v2: Vector) { 32 | return new Vector(v1.y * v2.z - v1.z * v2.y, 33 | v1.z * v2.x - v1.x * v2.z, 34 | v1.x * v2.y - v1.y * v2.x); 35 | } 36 | 37 | } 38 | 39 | class Color { 40 | 41 | constructor(public r: number, public g: number, public b: number) { } 42 | 43 | static scale(k: number, v: Color) { 44 | return new Color(k * v.r, k * v.g, k * v.b); 45 | } 46 | 47 | static plus(v1: Color, v2: Color) { 48 | return new Color(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b); 49 | } 50 | 51 | static times(v1: Color, v2: Color) { 52 | return new Color(v1.r * v2.r, v1.g * v2.g, v1.b * v2.b); 53 | } 54 | 55 | static white = new Color(1.0, 1.0, 1.0); 56 | static grey = new Color(0.5, 0.5, 0.5); 57 | static black = new Color(0.0, 0.0, 0.0); 58 | static background = Color.black; 59 | static defaultColor = Color.black; 60 | 61 | static toDrawingColor(c: Color) { 62 | var legalize = d => d > 1 ? 1 : d; 63 | return { 64 | r: Math.floor(legalize(c.r) * 255), 65 | g: Math.floor(legalize(c.g) * 255), 66 | b: Math.floor(legalize(c.b) * 255) 67 | } 68 | } 69 | 70 | } 71 | 72 | class Camera { 73 | 74 | forward: Vector; 75 | right: Vector; 76 | up: Vector; 77 | 78 | constructor(public pos: Vector, lookAt: Vector) { 79 | var down = new Vector(0.0, -1.0, 0.0); 80 | this.forward = Vector.norm(Vector.minus(lookAt, this.pos)); 81 | this.right = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, down))); 82 | this.up = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, this.right))); 83 | } 84 | 85 | } 86 | 87 | interface Ray { 88 | start: Vector; 89 | dir: Vector; 90 | } 91 | 92 | interface Intersection { 93 | thing: Thing; 94 | ray: Ray; 95 | dist: number; 96 | } 97 | 98 | interface Surface { 99 | diffuse: (pos: Vector) => Color; 100 | specular: (pos: Vector) => Color; 101 | reflect: (pos: Vector) => number; 102 | roughness: number; 103 | } 104 | 105 | interface Thing { 106 | intersect: (ray: Ray) => Intersection; 107 | normal: (pos: Vector) => Vector; 108 | surface: Surface; 109 | } 110 | 111 | interface Light { 112 | pos: Vector; 113 | color: Color; 114 | } 115 | 116 | interface Scene { 117 | things: Thing[]; 118 | lights: Light[]; 119 | camera: Camera; 120 | } 121 | 122 | class Sphere implements Thing { 123 | 124 | radius2: number; 125 | 126 | constructor(public center: Vector, radius: number, public surface: Surface) { 127 | this.radius2 = radius * radius; 128 | } 129 | 130 | normal(pos: Vector): Vector { 131 | return Vector.norm(Vector.minus(pos, this.center)); 132 | } 133 | 134 | intersect(ray: Ray) { 135 | var eo = Vector.minus(this.center, ray.start); 136 | var v = Vector.dot(eo, ray.dir); 137 | var dist = 0; 138 | if (v >= 0) { 139 | var disc = this.radius2 - (Vector.dot(eo, eo) - v * v); 140 | if (disc >= 0) { 141 | dist = v - Math.sqrt(disc); 142 | } 143 | } 144 | if (dist === 0) { 145 | return null; 146 | } else { 147 | return { thing: this, ray: ray, dist: dist }; 148 | } 149 | } 150 | 151 | } 152 | 153 | class Plane implements Thing { 154 | 155 | normal: (pos: Vector) => Vector; 156 | intersect: (ray: Ray) => Intersection; 157 | 158 | constructor(norm: Vector, offset: number, public surface: Surface) { 159 | this.normal = function(pos: Vector) { return norm; } 160 | this.intersect = function(ray: Ray): Intersection { 161 | var denom = Vector.dot(norm, ray.dir); 162 | if (denom > 0) { 163 | return null; 164 | } else { 165 | var dist = (Vector.dot(norm, ray.start) + offset) / (-denom); 166 | return { thing: this, ray: ray, dist: dist }; 167 | } 168 | } 169 | } 170 | 171 | } 172 | 173 | module Surfaces { 174 | 175 | export var shiny: Surface = { 176 | diffuse: function(pos) { return Color.white; }, 177 | specular: function(pos) { return Color.grey; }, 178 | reflect: function(pos) { return 0.7; }, 179 | roughness: 250 180 | } 181 | 182 | export var checkerboard: Surface = { 183 | diffuse: function(pos) { 184 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 185 | return Color.white; 186 | } else { 187 | return Color.black; 188 | } 189 | }, 190 | specular: function(pos) { return Color.white; }, 191 | reflect: function(pos) { 192 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 193 | return 0.1; 194 | } else { 195 | return 0.7; 196 | } 197 | }, 198 | roughness: 150 199 | } 200 | 201 | } 202 | 203 | 204 | class RayTracer { 205 | 206 | private maxDepth = 5; 207 | 208 | private intersections(ray: Ray, scene: Scene) { 209 | var closest = +Infinity; 210 | var closestInter: Intersection = undefined; 211 | for (var i in scene.things) { 212 | var inter = scene.things[i].intersect(ray); 213 | if (inter != null && inter.dist < closest) { 214 | closestInter = inter; 215 | closest = inter.dist; 216 | } 217 | } 218 | return closestInter; 219 | } 220 | 221 | private testRay(ray: Ray, scene: Scene) { 222 | var isect = this.intersections(ray, scene); 223 | if (isect != null) { 224 | return isect.dist; 225 | } else { 226 | return undefined; 227 | } 228 | } 229 | 230 | private traceRay(ray: Ray, scene: Scene, depth: number): Color { 231 | var isect = this.intersections(ray, scene); 232 | if (isect === undefined) { 233 | return Color.background; 234 | } else { 235 | return this.shade(isect, scene, depth); 236 | } 237 | } 238 | 239 | private shade(isect: Intersection, scene: Scene, depth: number) { 240 | var d = isect.ray.dir; 241 | var pos = Vector.plus(Vector.times(isect.dist, d), isect.ray.start); 242 | var normal = isect.thing.normal(pos); 243 | var reflectDir = Vector.minus(d, Vector.times(2, Vector.times(Vector.dot(normal, d), normal))); 244 | var naturalColor = Color.plus(Color.background, 245 | this.getNaturalColor(isect.thing, pos, normal, reflectDir, scene)); 246 | var reflectedColor = (depth >= this.maxDepth) ? Color.grey : this.getReflectionColor(isect.thing, pos, normal, reflectDir, scene, depth); 247 | return Color.plus(naturalColor, reflectedColor); 248 | } 249 | 250 | private getReflectionColor(thing: Thing, pos: Vector, normal: Vector, rd: Vector, scene: Scene, depth: number) { 251 | return Color.scale(thing.surface.reflect(pos), this.traceRay({ start: pos, dir: rd }, scene, depth + 1)); 252 | } 253 | 254 | private getNaturalColor(thing: Thing, pos: Vector, norm: Vector, rd: Vector, scene: Scene) { 255 | var addLight = (col, light) => { 256 | var ldis = Vector.minus(light.pos, pos); 257 | var livec = Vector.norm(ldis); 258 | var neatIsect = this.testRay({ start: pos, dir: livec }, scene); 259 | var isInShadow = (neatIsect === undefined) ? false : (neatIsect <= Vector.mag(ldis)); 260 | if (isInShadow) { 261 | return col; 262 | } else { 263 | var illum = Vector.dot(livec, norm); 264 | var lcolor = (illum > 0) ? Color.scale(illum, light.color) 265 | : Color.defaultColor; 266 | var specular = Vector.dot(livec, Vector.norm(rd)); 267 | var scolor = (specular > 0) ? Color.scale(Math.pow(specular, thing.surface.roughness), light.color) 268 | : Color.defaultColor; 269 | return Color.plus(col, Color.plus(Color.times(thing.surface.diffuse(pos), lcolor), 270 | Color.times(thing.surface.specular(pos), scolor))); 271 | } 272 | } 273 | return scene.lights.reduce(addLight, Color.defaultColor); 274 | } 275 | 276 | render(scene, ctx, screenWidth, screenHeight) { 277 | var getPoint = (x, y, camera) => { 278 | var recenterX = x => (x - (screenWidth / 2.0)) / 2.0 / screenWidth; 279 | var recenterY = y => -(y - (screenHeight / 2.0)) / 2.0 / screenHeight; 280 | return Vector.norm(Vector.plus(camera.forward, Vector.plus(Vector.times(recenterX(x), camera.right), Vector.times(recenterY(y), camera.up)))); 281 | } 282 | for (var y = 0; y < screenHeight; y++) { 283 | for (var x = 0; x < screenWidth; x++) { 284 | var color = this.traceRay({ start: scene.camera.pos, dir: getPoint(x, y, scene.camera) }, scene, 0); 285 | var c = Color.toDrawingColor(color); 286 | ctx.fillStyle = "rgb(" + String(c.r) + ", " + String(c.g) + ", " + String(c.b) + ")"; 287 | ctx.fillRect(x, y, x + 1, y + 1); 288 | } 289 | } 290 | } 291 | 292 | } 293 | 294 | 295 | function defaultScene(): Scene { 296 | return { 297 | things: [new Plane(new Vector(0.0, 1.0, 0.0), 0.0, Surfaces.checkerboard), 298 | new Sphere(new Vector(0.0, 1.0, -0.25), 1.0, Surfaces.shiny), 299 | new Sphere(new Vector(-1.0, 0.5, 1.5), 0.5, Surfaces.shiny)], 300 | lights: [{ pos: new Vector(-2.0, 2.5, 0.0), color: new Color(0.49, 0.07, 0.07) }, 301 | { pos: new Vector(1.5, 2.5, 1.5), color: new Color(0.07, 0.07, 0.49) }, 302 | { pos: new Vector(1.5, 2.5, -1.5), color: new Color(0.07, 0.49, 0.071) }, 303 | { pos: new Vector(0.0, 3.5, 0.0), color: new Color(0.21, 0.21, 0.35) }], 304 | camera: new Camera(new Vector(3.0, 2.0, 4.0), new Vector(-1.0, 0.5, 0.0)) 305 | }; 306 | } 307 | 308 | function exec() { 309 | var canv = document.createElement("canvas"); 310 | canv.width = 256; 311 | canv.height = 256; 312 | document.body.appendChild(canv); 313 | var ctx = canv.getContext("2d"); 314 | var rayTracer = new RayTracer(); 315 | return rayTracer.render(defaultScene(), ctx, 256, 256); 316 | } 317 | 318 | exec(); 319 | -------------------------------------------------------------------------------- /test/expected/tsfmt/c/main.ts: -------------------------------------------------------------------------------- 1 | class Vector 2 | { 3 | 4 | constructor( public x: number,public y: number,public z: number ) { } 5 | 6 | static times( k: number,v: Vector ) 7 | { 8 | return new Vector( k*v.x,k*v.y,k*v.z ); 9 | } 10 | 11 | static minus( v1: Vector,v2: Vector ) 12 | { 13 | return new Vector( v1.x-v2.x,v1.y-v2.y,v1.z-v2.z ); 14 | } 15 | 16 | static plus( v1: Vector,v2: Vector ) 17 | { 18 | return new Vector( v1.x+v2.x,v1.y+v2.y,v1.z+v2.z ); 19 | } 20 | 21 | static dot( v1: Vector,v2: Vector ) 22 | { 23 | return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z; 24 | } 25 | 26 | static mag( v: Vector ) 27 | { 28 | return Math.sqrt( v.x*v.x+v.y*v.y+v.z*v.z ); 29 | } 30 | 31 | static norm( v: Vector ) 32 | { 33 | var mag=Vector.mag( v ); 34 | var div=( mag===0 )? Infinity:1.0/mag; 35 | return Vector.times( div,v ); 36 | } 37 | 38 | static cross( v1: Vector,v2: Vector ) 39 | { 40 | return new Vector( v1.y*v2.z-v1.z*v2.y, 41 | v1.z*v2.x-v1.x*v2.z, 42 | v1.x*v2.y-v1.y*v2.x ); 43 | } 44 | 45 | } 46 | 47 | class Color 48 | { 49 | 50 | constructor( public r: number,public g: number,public b: number ) { } 51 | 52 | static scale( k: number,v: Color ) 53 | { 54 | return new Color( k*v.r,k*v.g,k*v.b ); 55 | } 56 | 57 | static plus( v1: Color,v2: Color ) 58 | { 59 | return new Color( v1.r+v2.r,v1.g+v2.g,v1.b+v2.b ); 60 | } 61 | 62 | static times( v1: Color,v2: Color ) 63 | { 64 | return new Color( v1.r*v2.r,v1.g*v2.g,v1.b*v2.b ); 65 | } 66 | 67 | static white=new Color( 1.0,1.0,1.0 ); 68 | static grey=new Color( 0.5,0.5,0.5 ); 69 | static black=new Color( 0.0,0.0,0.0 ); 70 | static background=Color.black; 71 | static defaultColor=Color.black; 72 | 73 | static toDrawingColor( c: Color ) 74 | { 75 | var legalize=d => d>1? 1:d; 76 | return { 77 | r: Math.floor( legalize( c.r )*255 ), 78 | g: Math.floor( legalize( c.g )*255 ), 79 | b: Math.floor( legalize( c.b )*255 ) 80 | } 81 | } 82 | 83 | } 84 | 85 | class Camera 86 | { 87 | 88 | forward: Vector; 89 | right: Vector; 90 | up: Vector; 91 | 92 | constructor( public pos: Vector,lookAt: Vector ) 93 | { 94 | var down=new Vector( 0.0,-1.0,0.0 ); 95 | this.forward=Vector.norm( Vector.minus( lookAt,this.pos ) ); 96 | this.right=Vector.times( 1.5,Vector.norm( Vector.cross( this.forward,down ) ) ); 97 | this.up=Vector.times( 1.5,Vector.norm( Vector.cross( this.forward,this.right ) ) ); 98 | } 99 | 100 | } 101 | 102 | interface Ray 103 | { 104 | start: Vector; 105 | dir: Vector; 106 | } 107 | 108 | interface Intersection 109 | { 110 | thing: Thing; 111 | ray: Ray; 112 | dist: number; 113 | } 114 | 115 | interface Surface 116 | { 117 | diffuse: ( pos: Vector ) => Color; 118 | specular: ( pos: Vector ) => Color; 119 | reflect: ( pos: Vector ) => number; 120 | roughness: number; 121 | } 122 | 123 | interface Thing 124 | { 125 | intersect: ( ray: Ray ) => Intersection; 126 | normal: ( pos: Vector ) => Vector; 127 | surface: Surface; 128 | } 129 | 130 | interface Light 131 | { 132 | pos: Vector; 133 | color: Color; 134 | } 135 | 136 | interface Scene 137 | { 138 | things: Thing[]; 139 | lights: Light[]; 140 | camera: Camera; 141 | } 142 | 143 | class Sphere implements Thing 144 | { 145 | 146 | radius2: number; 147 | 148 | constructor( public center: Vector,radius: number,public surface: Surface ) 149 | { 150 | this.radius2=radius*radius; 151 | } 152 | 153 | normal( pos: Vector ): Vector 154 | { 155 | return Vector.norm( Vector.minus( pos,this.center ) ); 156 | } 157 | 158 | intersect( ray: Ray ) 159 | { 160 | var eo=Vector.minus( this.center,ray.start ); 161 | var v=Vector.dot( eo,ray.dir ); 162 | var dist=0; 163 | if( v>=0 ) 164 | { 165 | var disc=this.radius2-( Vector.dot( eo,eo )-v*v ); 166 | if( disc>=0 ) 167 | { 168 | dist=v-Math.sqrt( disc ); 169 | } 170 | } 171 | if( dist===0 ) 172 | { 173 | return null; 174 | } else 175 | { 176 | return { thing: this,ray: ray,dist: dist }; 177 | } 178 | } 179 | 180 | } 181 | 182 | class Plane implements Thing 183 | { 184 | 185 | normal: ( pos: Vector ) => Vector; 186 | intersect: ( ray: Ray ) => Intersection; 187 | 188 | constructor( norm: Vector,offset: number,public surface: Surface ) 189 | { 190 | this.normal=function ( pos: Vector ) { return norm; } 191 | this.intersect=function ( ray: Ray ): Intersection 192 | { 193 | var denom=Vector.dot( norm,ray.dir ); 194 | if( denom>0 ) 195 | { 196 | return null; 197 | } else 198 | { 199 | var dist=( Vector.dot( norm,ray.start )+offset )/( -denom ); 200 | return { thing: this,ray: ray,dist: dist }; 201 | } 202 | } 203 | } 204 | 205 | } 206 | 207 | module Surfaces 208 | { 209 | 210 | export var shiny: Surface={ 211 | diffuse: function ( pos ) { return Color.white; }, 212 | specular: function ( pos ) { return Color.grey; }, 213 | reflect: function ( pos ) { return 0.7; }, 214 | roughness: 250 215 | } 216 | 217 | export var checkerboard: Surface={ 218 | diffuse: function ( pos ) 219 | { 220 | if( ( Math.floor( pos.z )+Math.floor( pos.x ) )%2!==0 ) 221 | { 222 | return Color.white; 223 | } else 224 | { 225 | return Color.black; 226 | } 227 | }, 228 | specular: function ( pos ) { return Color.white; }, 229 | reflect: function ( pos ) 230 | { 231 | if( ( Math.floor( pos.z )+Math.floor( pos.x ) )%2!==0 ) 232 | { 233 | return 0.1; 234 | } else 235 | { 236 | return 0.7; 237 | } 238 | }, 239 | roughness: 150 240 | } 241 | 242 | } 243 | 244 | 245 | class RayTracer 246 | { 247 | 248 | private maxDepth=5; 249 | 250 | private intersections( ray: Ray,scene: Scene ) 251 | { 252 | var closest=+Infinity; 253 | var closestInter: Intersection=undefined; 254 | for( var i in scene.things ) 255 | { 256 | var inter=scene.things[i].intersect( ray ); 257 | if( inter!=null&&inter.dist=this.maxDepth )? Color.grey:this.getReflectionColor( isect.thing,pos,normal,reflectDir,scene,depth ); 299 | return Color.plus( naturalColor,reflectedColor ); 300 | } 301 | 302 | private getReflectionColor( thing: Thing,pos: Vector,normal: Vector,rd: Vector,scene: Scene,depth: number ) 303 | { 304 | return Color.scale( thing.surface.reflect( pos ),this.traceRay( { start: pos,dir: rd },scene,depth+1 ) ); 305 | } 306 | 307 | private getNaturalColor( thing: Thing,pos: Vector,norm: Vector,rd: Vector,scene: Scene ) 308 | { 309 | var addLight=( col,light ) => 310 | { 311 | var ldis=Vector.minus( light.pos,pos ); 312 | var livec=Vector.norm( ldis ); 313 | var neatIsect=this.testRay( { start: pos,dir: livec },scene ); 314 | var isInShadow=( neatIsect===undefined )? false:( neatIsect<=Vector.mag( ldis ) ); 315 | if( isInShadow ) 316 | { 317 | return col; 318 | } else 319 | { 320 | var illum=Vector.dot( livec,norm ); 321 | var lcolor=( illum>0 )? Color.scale( illum,light.color ) 322 | :Color.defaultColor; 323 | var specular=Vector.dot( livec,Vector.norm( rd ) ); 324 | var scolor=( specular>0 )? Color.scale( Math.pow( specular,thing.surface.roughness ),light.color ) 325 | :Color.defaultColor; 326 | return Color.plus( col,Color.plus( Color.times( thing.surface.diffuse( pos ),lcolor ), 327 | Color.times( thing.surface.specular( pos ),scolor ) ) ); 328 | } 329 | } 330 | return scene.lights.reduce( addLight,Color.defaultColor ); 331 | } 332 | 333 | render( scene,ctx,screenWidth,screenHeight ) 334 | { 335 | var getPoint=( x,y,camera ) => 336 | { 337 | var recenterX=x => ( x-( screenWidth/2.0 ) )/2.0/screenWidth; 338 | var recenterY=y => -( y-( screenHeight/2.0 ) )/2.0/screenHeight; 339 | return Vector.norm( Vector.plus( camera.forward,Vector.plus( Vector.times( recenterX( x ),camera.right ),Vector.times( recenterY( y ),camera.up ) ) ) ); 340 | } 341 | for( var y=0;y