Skip to content

Commit

Permalink
Basic TypeScript Support (#84)
Browse files Browse the repository at this point in the history
* Tiny gitignore cleanup

* firefox fix, #36

* ts support

* tsx added

* transpileoptions improvements and bugfix

* tsconfig.json support

* add basic typescript test

* Default to ES2015 to stay consistent with the js default

* remove custom transform, implement check in js transform for ts and put codegen back to commonjs

* keep ts transform addition within ts module

* ts testing and bugfix

* improve jsx parameter and default to preserve and let babel handle it

* improve jsx parameter and default to preserve and let babel handle it
  • Loading branch information
Jasper De Moor authored and devongovett committed Dec 8, 2017
1 parent 11d109b commit 757b673
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ coverage
dist
lib
!test/**/node_modules
.vscode/
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
"postcss-modules": "^0.8.0",
"posthtml-include": "^1.1.0",
"rimraf": "^2.6.1",
"stylus": "^0.54.5"
"stylus": "^0.54.5",
"typescript": "^2.6.2"
},
"scripts": {
"test": "cross-env NODE_ENV=test mocha",
Expand Down
3 changes: 2 additions & 1 deletion src/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class Parser {
this.registerExtension('js', './assets/JSAsset');
this.registerExtension('jsx', './assets/JSAsset');
this.registerExtension('es6', './assets/JSAsset');
this.registerExtension('ts', './assets/TypeScriptAsset');
this.registerExtension('tsx', './assets/TypeScriptAsset');
this.registerExtension('json', './assets/JSONAsset');
this.registerExtension('yaml', './assets/YAMLAsset');
this.registerExtension('yml', './assets/YAMLAsset');
Expand Down Expand Up @@ -46,7 +48,6 @@ class Parser {
if (typeof parser === 'string') {
parser = this.extensions[extension] = require(parser);
}

return parser;
}

Expand Down
35 changes: 35 additions & 0 deletions src/assets/TypeScriptAsset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const JSAsset = require('./JSAsset');
const config = require('../utils/config');
const localRequire = require('../utils/localRequire');

class TypeScriptAsset extends JSAsset {
async transform() {
super.transform();

await this.parseIfNeeded();
this.isAstDirty = true;
}

async parse(code) {
// require typescript, installed locally in the app
let typescript = localRequire('typescript', this.name);

let transpilerOptions = {
compilerOptions: {
module: typescript.ModuleKind.CommonJS,
jsx: typescript.JsxEmit.Preserve
},
fileName: this.basename
}

let tsconfig = await config.load(this.name, ['tsconfig.json']);
// Overwrite default if config is found
if (tsconfig) transpilerOptions.compilerOptions = tsconfig.compilerOptions;
transpilerOptions.compilerOptions.noEmit = false;

// Transpile Module using TypeScript and parse result as ast format through babylon
return await super.parse(typescript.transpileModule(code, transpilerOptions).outputText);
}
}

module.exports = TypeScriptAsset;
3 changes: 1 addition & 2 deletions src/builtins/prelude.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ require = (function (modules, cache, entry) {
if (previousRequire) {
return previousRequire(name, true);
}

var err = new Error('Cannot find module \'' + name + '\'');
err.code = 'MODULE_NOT_FOUND';
throw err;
Expand Down Expand Up @@ -58,7 +57,7 @@ require = (function (modules, cache, entry) {
newRequire.modules = modules;
newRequire.cache = cache;
newRequire.parent = previousRequire;

for (var i = 0; i < entry.length; i++) {
newRequire(entry[i]);
}
Expand Down
3 changes: 3 additions & 0 deletions test/integration/typescript-env/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function env() {
return process.env.NODE_ENV;
}
5 changes: 5 additions & 0 deletions test/integration/typescript-json/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const local = require('./local.json');

export function count() {
return local.a + local.b;
}
4 changes: 4 additions & 0 deletions test/integration/typescript-json/local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"a": 1,
"b": 2
}
5 changes: 5 additions & 0 deletions test/integration/typescript-raw/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const url = require('./test.txt');

export function getRaw() {
return url;
}
1 change: 1 addition & 0 deletions test/integration/typescript-raw/test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hi there
11 changes: 11 additions & 0 deletions test/integration/typescript-require/Local.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class Local {
a: number;
b: number;

constructor(a: number, b: number) {
this.a = a;
this.b = b;
}
}

module.exports = Local;
6 changes: 6 additions & 0 deletions test/integration/typescript-require/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const Local = require('./Local');

export function count() {
let local = new Local(1, 2);
return local.a + local.b;
}
9 changes: 9 additions & 0 deletions test/integration/typescript/Local.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export class Local {
a: number;
b: number;

constructor(a: number, b: number) {
this.a = a;
this.b = b;
}
}
6 changes: 6 additions & 0 deletions test/integration/typescript/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Local } from './Local';

export function count() {
let local = new Local(1, 2);
return local.a + local.b;
}
82 changes: 82 additions & 0 deletions test/typescript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const assert = require('assert');
const fs = require('fs');
const {bundle, run, assertBundleTree} = require('./utils');

describe('typescript', function () {
it('should produce a ts bundle using ES6 imports', async function () {
let b = await bundle(__dirname + '/integration/typescript/index.ts');

assert.equal(b.assets.size, 2);
assert.equal(b.childBundles.size, 0);

let output = run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
});

it('should produce a ts bundle using commonJS require', async function () {
let b = await bundle(__dirname + '/integration/typescript-require/index.ts');

assert.equal(b.assets.size, 2);
assert.equal(b.childBundles.size, 0);

let output = run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
});

it('should support json require', async function () {
let b = await bundle(__dirname + '/integration/typescript-json/index.ts');

assert.equal(b.assets.size, 2);
assert.equal(b.childBundles.size, 0);

let output = run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
});

it('should support env variables', async function () {
let b = await bundle(__dirname + '/integration/typescript-env/index.ts');

assert.equal(b.assets.size, 1);
assert.equal(b.childBundles.size, 0);

let output = run(b);
assert.equal(typeof output.env, 'function');
assert.equal(output.env(), 'test');
});

it('should support importing a URL to a raw asset', async function () {
let b = await bundle(__dirname + '/integration/typescript-raw/index.ts');

assertBundleTree(b, {
name: 'index.js',
assets: ['index.ts', 'test.txt'],
childBundles: [{
type: 'txt',
assets: ['test.txt'],
childBundles: []
}]
});

let output = run(b);
assert.equal(typeof output.getRaw, 'function');
assert(/^[0-9a-f]+\.txt$/.test(output.getRaw()));
assert(fs.existsSync(__dirname + '/dist/' + output.getRaw()));
});

/*it('should minify in production mode', async function () {
let b = await bundle(__dirname + '/integration/typescript-require/index.ts', { production: true });
assert.equal(b.assets.size, 2);
assert.equal(b.childBundles.size, 0);
let output = run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
let js = fs.readFileSync(__dirname + '/dist/index.js', 'utf8');
assert(!js.includes('local.a'));
});*/
});

0 comments on commit 757b673

Please sign in to comment.