Last active
August 29, 2015 13:59
-
-
Save jgoz/10501188 to your computer and use it in GitHub Desktop.
Typescript loader for webpack (WIP)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var fs = require("fs"); | |
var loaderUtils = require("loader-utils"); | |
var path = require("path"); | |
var ts = require("typescript-api"); | |
function buildSettings(options, debug, outFile) { | |
var settings = new ts.CompilationSettings(); | |
if (options) { | |
var target = (options.target || "es3").toLowerCase(); | |
settings.codeGenTarget = (target === "es3" ? 0 : (target === "es5" ? 1 : options.target)); | |
var module = (options.module || "").toLowerCase(); | |
settings.moduleGenTarget = (module === "commonjs" ? 1 : (module === "amd" ? 2 : 0)); | |
settings.noResolve = options.noResolve === true; | |
settings.noImplicitAny = options.warnImplicitAny !== true; | |
} | |
settings.mapSourceFiles = debug; | |
settings.outFileOption = outFile; | |
//settings.syntacticErrors = true; | |
//settings.semanticErrors = true; | |
return ts.ImmutableCompilationSettings.fromCompilationSettings(settings); | |
} | |
function compile(batchCompiler, settings) { | |
var compiler = new ts.TypeScriptCompiler(new ts.NullLogger(), settings); | |
batchCompiler.resolvedFiles.forEach(function (resolvedFile) { | |
var sourceFile = this.getSourceFile(resolvedFile.path); | |
compiler.addFile(resolvedFile.path, sourceFile.scriptSnapshot, sourceFile.byteOrderMark, 0, false, resolvedFile.referencedFiles); | |
}, batchCompiler); | |
var it = compiler.compile(function (path) { | |
return batchCompiler.resolvePath(path); | |
}); | |
var output = []; | |
while (it.moveNext()) { | |
var current = it.current(); | |
var result = {}; | |
for (var i = 0; i < current.outputFiles.length; i++) { | |
var outputFile = current.outputFiles[i]; | |
if (!outputFile) { continue; } | |
if (outputFile.fileType === 1) { // SourceMap | |
result.map = outputFile.text; | |
} else { | |
// HACK: strip inline sourcemap info, as this will be included | |
// at the bottom of the output bundle | |
result.content = outputFile.text.replace(/\/\/# sourceMappingURL=.+\.map/, ""); | |
result.name = outputFile.name; | |
} | |
} | |
if (result.content) { | |
output.push(result); | |
} | |
} | |
var errors = []; | |
batchCompiler.resolvedFiles.forEach(function (resolvedFile) { | |
var diagnostics = compiler.getSyntacticDiagnostics(resolvedFile.path) | |
.concat(compiler.getSemanticDiagnostics(resolvedFile.path)); | |
diagnostics.forEach(function (d) { | |
errors.push({ path: resolvedFile.path, message: d.text(), line: d.line() + 1, character: d.character() + 1 }); | |
}); | |
}); | |
return { output: output, errors: errors }; | |
} | |
function resolve(batchCompiler, filePath) { | |
var result = []; | |
var content, output; | |
batchCompiler.resolvedFiles = []; | |
batchCompiler.inputFiles = [filePath]; | |
batchCompiler.resolve(); | |
batchCompiler.resolvedFiles.forEach(function (rf) { | |
if (!/\.d\.ts$/.test(rf.path)) { | |
content = fs.readFileSync(rf.path, {encoding: 'utf8'}); | |
result.push({ path: rf.path, source: content }); | |
} | |
}); | |
return result; | |
} | |
function getBasename(filePath) { | |
return path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath))); | |
} | |
module.exports = function typescriptLoader(source) { | |
if (this.cacheable) { this.cacheable(); } | |
var tsRequest = loaderUtils.getRemainingRequest(this); | |
var jsRequest = loaderUtils.getCurrentRequest(this); | |
var query = loaderUtils.parseQuery(this.query); | |
var settings = buildSettings(query, this.debug, jsRequest); | |
var inputFiles = [{ path: tsRequest, source: source }]; | |
var batchCompiler = new ts.BatchCompiler(ts.IO); | |
batchCompiler.logger = new ts.NullLogger(); | |
batchCompiler.compilationSettings = settings; | |
resolve(batchCompiler, tsRequest); | |
var result = compile(batchCompiler, settings); | |
result.errors.forEach(function(error) { | |
this.emitError( | |
error.message.replace(/\.$/, "") + " in " + | |
path.relative(this.options.context, error.path) + " " + | |
error.line + ":" + error.character | |
); | |
}, this); | |
var expectedBasename = getBasename(tsRequest); | |
result.output.forEach(function(output) { | |
var outputBasename = getBasename(output.name); | |
if (outputBasename === expectedBasename) { | |
var map = JSON.parse(output.map); | |
map.sourcesContent = [source]; | |
map.sourceRoot = "ts/" + path.relative(this.options.context, path.dirname(tsRequest)); | |
this.callback(null, output.content, map); | |
} else { | |
this.addDependency(getBasename(output.name) + ".ts"); | |
} | |
}, this); | |
}; | |
module.exports.seperable = true; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment