fis3-parser-typescript
Version:
A parser plugin for fis3 to compile typescript(ts) file.
187 lines (154 loc) • 5.73 kB
JavaScript
/**
* fis.baidu.com
*/
var ts = require('typescript');
var util = require('util');
var ModuleKind = ts.ModuleKind;
var JsxEmit = ts.JsxEmit;
var ScriptTarget = ts.ScriptTarget;
function transpileModule(content, transpileOptions, file) {
var options = transpileOptions.compilerOptions;
options.isolatedModules = true;
options.allowNonTsExtensions = true;
options.noLib = true;
options.noResolve = true;
var newLine = ts.getNewLineCharacter(options);
var inputFileName = file.isJsXLike ? file.realpath.replace(/\.[^\.]+$/, '.tsx') : file.realpath.replace(/\.jsx$/, '.tsx');
var sourceFile = ts.createSourceFile(inputFileName, content, options.target);
var sourceMapText, outputText;
if (file.isMod) {
sourceFile.moduleName = file.moduleId || file.id;
}
var compilerHost = {
getSourceFile: function (fileName) {
if (fileName === ts.normalizeSlashes(inputFileName)) {
return sourceFile;
}
var info = fis.uri(fileName, file.dirname);
if (info.file) {
var f = info.file;
var sf = ts.createSourceFile(f.isJsXLike ? f.realpath.replace(/\.[^\.]+$/, '.tsx') : f.realpath.replace(/\.jsx$/, '.tsx'), f.getContent(), options.target);
if (f.isMod) {
sf.moduleName = f.moduleId || f.id;
}
return sf;
}
return undefined;
},
writeFile: function (name, text, writeByteOrderMark) {
if (ts.fileExtensionIs(name, ".map")) {
ts.Debug.assert(sourceMapText === undefined, "Unexpected multiple source map outputs for the file '" + name + "'");
sourceMapText = text;
}
else {
ts.Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: " + name);
outputText = text;
}
},
getDefaultLibFileName: function () { return "lib.d.ts"; },
useCaseSensitiveFileNames: function () { return false; },
getCanonicalFileName: function (fileName) { return fileName; },
getCurrentDirectory: function () { return ""; },
getNewLine: function () { return newLine; },
fileExists: function (fileName) {
return fis.util.exists(fileName);
},
readFile: function (fileName) { return ""; }
};
var program = ts.createProgram([inputFileName], options, compilerHost);
var diagnostics;
var noticeDiagnostics;
if (transpileOptions.reportDiagnostics) {
diagnostics = [];
ts.addRange(diagnostics, program.getSyntacticDiagnostics(sourceFile));
ts.addRange(diagnostics, program.getOptionsDiagnostics());
noticeDiagnostics = [];
options.showNotices && ts.addRange(noticeDiagnostics, program.getSemanticDiagnostics(sourceFile));
}
program.emit();
return {
outputText: outputText,
diagnostics: diagnostics,
noticeDiagnostics: noticeDiagnostics,
sourceMapText: sourceMapText
};
}
module.exports = function (content, file, opts) {
// 用 html 语言处理一遍。
if (fis.compile.partial && file.ext === '.tsx' || file.ext === '.jsx' || file.isJsXLike) {
content = fis.compile.partial(content, file, {
ext: '.html',
isHtmlLike: true
});
}
var conf = fis.util.clone(opts);
if (!conf.sourceMap) {
conf.inlineSources = false;
}
var result = transpileModule(content, {
compilerOptions: conf,
fileName: file.realpath,
reportDiagnostics: true,
moduleName: undefined
}, file);
result.diagnostics.forEach(function(e) {
if(!e.file){
return;
}
var lineAndCharacterObj = e.file.getLineAndCharacterOfPosition(e.start);
var line = lineAndCharacterObj.line;
var character = lineAndCharacterObj.character;
var message = ts.flattenDiagnosticMessageText(e.messageText, '\n');
var msg = util.format('Syntax Error: %s in [%s:%s]', message, line+1, character+1);
throw new Error(msg);
});
result.noticeDiagnostics.forEach(function(e) {
if(!e.file){
return;
}
var lineAndCharacterObj = e.file.getLineAndCharacterOfPosition(e.start);
var line = lineAndCharacterObj.line;
var character = lineAndCharacterObj.character;
var message = ts.flattenDiagnosticMessageText(e.messageText, '\n');
var msg = util.format('Notice Syntax Error: %s in [%s:%s]', message, line+1, character+1);
fis.log[conf.noticeType] && fis.log[conf.noticeType](msg);
});
if (result.sourceMapText) {
var mapping = fis.file.wrap(file.dirname + '/' + file.filename + file.rExt + '.map');
// 修改 source 文件名。
var sourceMapObj = JSON.parse(result.sourceMapText);
sourceMapObj.sources = [file.subpath];
result.sourceMapText = JSON.stringify(sourceMapObj, null, 4);
mapping.setContent(result.sourceMapText);
var url = mapping.getUrl(fis.compile.settings.hash, fis.compile.settings.domain);
result.outputText = result.outputText.replace(/\n?\s*\/\/#\ssourceMappingURL=.*?(?:\n|$)/g, '');
result.outputText += '\n//# sourceMappingURL=' + url + '\n';
file.extras = file.extras || {};
file.extras.derived = file.extras.derived || [];
file.extras.derived.push(mapping);
}
return result.outputText || '';
};
module.exports.defaultOptions = {
// 1: JsxEmit.Preserve
// 2: JsxEmit.React
jsx: JsxEmit.React,
// 1: ModuleKind.CommonJS
// 2: ModuleKind.AMD
// 3: ModuleKind.UMD
// 4: ModuleKind.System
module: ModuleKind.CommonJS,
// 0: ScriptTarget.ES3
// 1: ScriptTarget.ES5
// 2: ScriptTarget.ES6
target: ScriptTarget.ES5,
noImplicitAny: false,
outDir: "built",
rootDir: fis.project.getProjectPath(),
sourceMap: false,
inlineSources: true,
emitDecoratorMetadata: true,
experimentalDecorators: true,
showNotices: false,
noticeType: 'warn' // warn|error
};