Skip to content
This repository was archived by the owner on Jun 27, 2018. It is now read-only.

Support for TypeScript v1.5 #4

Merged
merged 17 commits into from
May 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dtsm.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"bundle": "typings/bundle.d.ts",
"dependencies": {
"node/node.d.ts": {
"ref": "6425747807265d7640d73234334aa6ae56b89e87"
"ref": "fbb8c672d56d1cfe677b81c300f8506a31e0404c"
}
}
}
}
18 changes: 10 additions & 8 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/// <reference path="typings/node/node.d.ts" />
/// <reference path="node_modules/typescript/bin/typescript.d.ts" />
import ts = require('typescript');
declare function tss(code: string, options: ts.CompilerOptions): string;
Expand All @@ -17,21 +16,24 @@ declare module tss {
constructor(options?: ts.CompilerOptions, doSemanticChecks?: boolean);
/**
* @param {string} code TypeScript source code to compile
* @param {string=} filename Only needed if you plan to use sourceMaps. Provide the complete filePath relevant to you
* @param {string=} fileName Only needed if you plan to use sourceMaps.
* Provide the complete filePath relevant to you
* @return {string} The JavaScript with inline sourceMaps if sourceMaps were enabled
* @throw {Error} A syntactic error or a semantic error (if doSemanticChecks is true)
*/
compile(code: string, filename?: string): string;
compile(code: string, fileName?: string): string;
private createService();
private getTypeScriptBinDir();
private getDefaultLibFilename(options);
private getDefaultLibFileName(options);
/**
* converts {"version":3,"file":"file.js","sourceRoot":"","sources":["file.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,MAAM,CAAC"}
* to {"version":3,"sources":["foo/test.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,MAAM,CAAC","file":"foo/test.ts","sourcesContent":["var x = 'test';"]}
* converts {"version":3,"file":"file.js","sourceRoot":"","sources":["file.ts"],"names":[],
* "mappings":"AAAA,IAAI,CAAC,GAAG,MAAM,CAAC"}
* to {"version":3,"sources":["foo/test.ts"],"names":[],
* "mappings":"AAAA,IAAI,CAAC,GAAG,MAAM,CAAC","file":"foo/test.ts","sourcesContent":["var x = 'test';"]}
* derived from : https://github.com/thlorenz/convert-source-map
*/
private getInlineSourceMap(mapText, filename);
private toJavaScript(service, filename?);
private getInlineSourceMap(mapText, fileName);
private toJavaScript(service, fileName?);
private formatDiagnostics(diagnostics);
}
}
Expand Down
105 changes: 56 additions & 49 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/// <reference path="typings/node/node.d.ts" />
/// <reference path="node_modules/typescript/bin/typescript.d.ts" />

import fs = require('fs');
Expand Down Expand Up @@ -41,11 +40,12 @@ module tss {

/**
* @param {string} code TypeScript source code to compile
* @param {string=} filename Only needed if you plan to use sourceMaps. Provide the complete filePath relevant to you
* @param {string=} fileName Only needed if you plan to use sourceMaps.
* Provide the complete filePath relevant to you
* @return {string} The JavaScript with inline sourceMaps if sourceMaps were enabled
* @throw {Error} A syntactic error or a semantic error (if doSemanticChecks is true)
*/
compile(code: string, filename = FILENAME_TS): string {
compile(code: string, fileName = FILENAME_TS): string {
if (!this.service) {
this.service = this.createService();
}
Expand All @@ -54,44 +54,57 @@ module tss {
file.text = code;
file.version++;

return this.toJavaScript(this.service, filename);
return this.toJavaScript(this.service, fileName);
}

private createService(): ts.LanguageService {
var defaultLib = this.getDefaultLibFilename(this.options);
var defaultLib = this.getDefaultLibFileName(this.options);
var defaultLibPath = path.join(this.getTypeScriptBinDir(), defaultLib);
this.files[defaultLib] = { version: 0, text: fs.readFileSync(defaultLibPath).toString() };
this.files[FILENAME_TS] = { version: 0, text: '' };

var servicesHost: ts.LanguageServiceHost = {
getScriptFileNames: () => [this.getDefaultLibFilename(this.options), FILENAME_TS],
getScriptVersion: (filename) => this.files[filename] && this.files[filename].version.toString(),
getScriptSnapshot: (filename) => {
var file = this.files[filename];
return {
getText: (start, end) => file.text.substring(start, end),
getLength: () => file.text.length,
getLineStartPositions: () => [],
getChangeRange: (oldSnapshot) => undefined
};
var serviceHost: ts.LanguageServiceHost = {
getScriptFileNames: () => [this.getDefaultLibFileName(this.options), FILENAME_TS],
getScriptVersion: (fileName) => this.files[fileName] && this.files[fileName].version.toString(),
getScriptSnapshot: (fileName) => {
var file = this.files[fileName];
if (file) {
return {
getText: (start, end) => file.text.substring(start, end),
getLength: () => file.text.length,
getLineStartPositions: (): number[]=> [],
getChangeRange: (oldSnapshot) => undefined
};
}
else { // This is some reference import
return {
getText: (start, end) => '',
getLength: () => 0,
getLineStartPositions: (): number[]=> [],
getChangeRange: (oldSnapshot) => undefined
};
}
},
getCurrentDirectory: () => process.cwd(),
getScriptIsOpen: () => true,
getCompilationSettings: () => this.options,
getDefaultLibFilename: (options: ts.CompilerOptions) => {
return this.getDefaultLibFilename(options);
getDefaultLibFileName: (options: ts.CompilerOptions) => {
return this.getDefaultLibFileName(options);
},
log: (message) => console.log(message)
getNewLine: () => os.EOL,
log: (message: string) => console.log(message),
trace: (message: string) => console.debug(message),
error: (message: string) => console.error(message)
};

return ts.createLanguageService(servicesHost, ts.createDocumentRegistry())
return ts.createLanguageService(serviceHost, ts.createDocumentRegistry())
}

private getTypeScriptBinDir(): string {
return path.dirname(require.resolve('typescript'));
}

private getDefaultLibFilename(options: ts.CompilerOptions): string {
private getDefaultLibFileName(options: ts.CompilerOptions): string {
if (options.target === ts.ScriptTarget.ES6) {
return 'lib.es6.d.ts';
} else {
Expand All @@ -100,56 +113,50 @@ module tss {
}

/**
* converts {"version":3,"file":"file.js","sourceRoot":"","sources":["file.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,MAAM,CAAC"}
* to {"version":3,"sources":["foo/test.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,MAAM,CAAC","file":"foo/test.ts","sourcesContent":["var x = 'test';"]}
* converts {"version":3,"file":"file.js","sourceRoot":"","sources":["file.ts"],"names":[],
* "mappings":"AAAA,IAAI,CAAC,GAAG,MAAM,CAAC"}
* to {"version":3,"sources":["foo/test.ts"],"names":[],
* "mappings":"AAAA,IAAI,CAAC,GAAG,MAAM,CAAC","file":"foo/test.ts","sourcesContent":["var x = 'test';"]}
* derived from : https://github.com/thlorenz/convert-source-map
*/
private getInlineSourceMap(mapText: string, filename: string): string {
private getInlineSourceMap(mapText: string, fileName: string): string {
var sourceMap = JSON.parse(mapText);
sourceMap.file = filename;
sourceMap.sources = [filename];
sourceMap.file = fileName;
sourceMap.sources = [fileName];
sourceMap.sourcesContent = [this.files[FILENAME_TS].text];
delete sourceMap.sourceRoot;
return JSON.stringify(sourceMap);
}

private toJavaScript(service: ts.LanguageService, filename = FILENAME_TS): string {
private toJavaScript(service: ts.LanguageService, fileName = FILENAME_TS): string {
var output = service.getEmitOutput(FILENAME_TS);

// Meaning of succeeded is driven by whether we need to check for semantic errors or not
var succeeded = output.emitOutputStatus === ts.EmitReturnStatus.Succeeded;
if (!this.doSemanticChecks && !succeeded) {
// We have an output. It implies syntactic success
succeeded = !!output.outputFiles.length;
}

if (!succeeded) {
var allDiagnostics = service.getCompilerOptionsDiagnostics()
.concat(service.getSyntacticDiagnostics(FILENAME_TS));
var allDiagnostics = service.getCompilerOptionsDiagnostics()
.concat(service.getSyntacticDiagnostics(FILENAME_TS));

if (this.doSemanticChecks) {
allDiagnostics = allDiagnostics.concat(service.getSemanticDiagnostics(FILENAME_TS));
}
if (this.doSemanticChecks) {
allDiagnostics = allDiagnostics.concat(service.getSemanticDiagnostics(FILENAME_TS));
}

if (allDiagnostics.length) {
throw new Error(this.formatDiagnostics(allDiagnostics));
}

var outputFilename = FILENAME_TS.replace(/ts$/, 'js');
var file = output.outputFiles.filter((file) => file.name === outputFilename)[0];
// TODO: Fixed in v1.5 https://github.com/Microsoft/TypeScript/issues/1653
var text = file.text.replace(/\r\n/g, os.EOL);
var outputFileName = FILENAME_TS.replace(/ts$/, 'js');
var file = output.outputFiles.filter((file) => file.name === outputFileName)[0];
var text = file.text;

// If we have sourceMaps convert them to inline sourceMaps
if (this.options.sourceMap) {
var sourceMapFilename = FILENAME_TS.replace(/ts$/, 'js.map');
var sourceMapFile = output.outputFiles.filter((file) => file.name === sourceMapFilename)[0];
var sourceMapFileName = FILENAME_TS.replace(/ts$/, 'js.map');
var sourceMapFile = output.outputFiles.filter((file) => file.name === sourceMapFileName)[0];

// Transform sourcemap
var sourceMapText = sourceMapFile.text;
sourceMapText = this.getInlineSourceMap(sourceMapText, filename);
sourceMapText = this.getInlineSourceMap(sourceMapText, fileName);
var base64SourceMapText = new Buffer(sourceMapText).toString('base64');
var sourceMapComment = '//# sourceMappingURL=data:application/json;base64,' + base64SourceMapText;
text = text.replace('//# sourceMappingURL=' + sourceMapFilename, sourceMapComment);
text = text.replace('//# sourceMappingURL=' + sourceMapFileName, sourceMapComment);
}

return text;
Expand All @@ -158,7 +165,7 @@ module tss {
private formatDiagnostics(diagnostics: ts.Diagnostic[]): string {
return diagnostics.map((d) => {
if (d.file) {
return 'L' + d.file.getLineAndCharacterFromPosition(d.start).line + ': ' + d.messageText;
return 'L' + d.file.getLineAndCharacterOfPosition(d.start).line + ': ' + d.messageText;
} else {
return d.messageText;
}
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "typescript-simple",
"version": "1.0.3",
"version": "2.0.0-beta.1",
"description": "Simple API to compile TypeScript code string to JavaScript. That's all!",
"main": "index.js",
"scripts": {
"test": "npm run build && mocha",
"build": "tsc -d --target ES5 --module commonjs --noImplicitAny index.ts",
"build": "tsc",
"prepublish": "npm test"
},
"repository": {
Expand All @@ -22,7 +22,7 @@
},
"homepage": "https://github.com/teppeis/typescript-simple",
"dependencies": {
"typescript": "~1.4.1"
"typescript": "~1.5.0-beta"
},
"devDependencies": {
"mocha": "^2.1.0"
Expand Down
27 changes: 17 additions & 10 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,20 @@ describe('typescript-update', function() {
var src = "var x: number = 'str';";
assert.throws(function() {
tss(src);
}, /^Error: L1: Type 'string' is not assignable to type 'number'./);
}, /^Error: L0: Type 'string' is not assignable to type 'number'./);
});

it('throws an error for ES6 "let"', function() {
var src = "let x: number = 1;";
assert.throws(function() {
tss(src);
}, /^Error: L1: 'let' declarations are only available when targeting ECMAScript 6 and higher./);
it('compiles ES6 "let" to "var"', function() {
var src = 'let x: number = 1;';
var expected = 'var x = 1;' + eol;
assert.equal(tss(src), expected);
});

it('throws an error for ES6 Promise', function() {
var src = "var x = new Promise(function (resolve, reject) {\n});";
assert.throws(function() {
tss(src);
}, /^Error: L1: Cannot find name 'Promise'./);
}, /^Error: L0: Cannot find name 'Promise'./);
});
});

Expand All @@ -63,13 +62,13 @@ describe('typescript-update', function() {
tss = new TypeScriptSimple({target: ts.ScriptTarget.ES6});
});

it('compiles ES6 "let"', function() {
it('compiles ES6 "let" to "let"', function() {
var src = "let x: number = 1;";
var expected = 'let x = 1;' + eol;
assert.equal(tss.compile(src), expected);
});

it('compiles ES6 Promise', function() {
it('does not throw for ES6 Promise', function() {
var src = "var x = new Promise(function (resolve, reject) {" + eol + "});";
var expected = src + eol;
assert.equal(tss.compile(src), expected);
Expand All @@ -87,12 +86,20 @@ describe('typescript-update', function() {
var expected = "var x = 'some string';" + eol;
assert.equal(tss.compile(src), expected);
});

it('reference imports are ignored', function() {
var src = "/// <reference path='./typings/tsd'/>" + eol
+ "var x: number = 'some string';";
var expected = "/// <reference path='./typings/tsd'/>" + eol
+ "var x = 'some string';" + eol;
assert.equal(tss.compile(src), expected);
});

it('syntactic errors are not ignored', function() {
var src = "var x = 123 123;";
assert.throws(function() {
tss.compile(src);
}, /^Error: L1: ',' expected./);
}, /^Error: L0: ',' expected./);
});
});

Expand Down
6 changes: 3 additions & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.4.1",
"version": "1.5.0",
"compilerOptions": {
"target": "es5",
"module": "commonjs",
Expand All @@ -10,12 +10,12 @@
},
"filesGlob": [
"./**/*.ts",
"!./index.d.ts",
"!./node_modules/**/*.ts"
],
"files": [
"./index.d.ts",
"./index.ts",
"./typings/bundle.d.ts",
"./typings/node/node.d.ts"
]
}
}
Loading