var createTypeScriptPreprocessor = function(args, config, logger, helper) { config = config || {}; var log = logger.create('preprocessor.typescript'); var defaultOptions = {}; var transformPath = args.transformPath || config.transformPath || function(filepath) { return filepath.replace(/\.ts$/, '.js'); }; // compiler options var options = helper.merge(defaultOptions, args.options || {}, config.options || {}); var compiler = new tss.TypeScriptSimple(options, false); return function(content, file, done) { log.debug('Processing "%s".', file.originalPath); file.path = transformPath(file.originalPath); try { var output = compiler.compile(content, file.originalPath); done(null, output); } catch(e) { log.error('%s\n at %s\n%s', e.message, file.originalPath, e.stack); return done(e, null); } }; };
;(function(){ 'use strict' const fs = require('fs') const ts = require('typescript') const { TypeScriptSimple } = require('typescript-simple') const DEFAULT_COMPILER_OPTIONS = { declaration: false // , emitDecoratorMetadata: true // , experimentalDecorators: true , module: ts.ModuleKind.CommonJS , moduleResolution: ts.ModuleResolutionKind.NodeJs , noEmitOnError: true , noEmit: false , noImplicitAny: false , target: ts.ScriptTarget.ES6 , sourceMap: true , inlineSources: true // , inlineSourceMap: true } const compilerOptions = Object.assign({} , DEFAULT_COMPILER_OPTIONS , { // TODO: --dev & --prod settings switcher }) delete compilerOptions.outDir const tss = new TypeScriptSimple(compilerOptions) function pureTypeScript(module, fileName) { const ts = fs.readFileSync(fileName, 'utf8') let js try { js = tss.compile(ts, fileName) } catch (e) { throw new Error(`Syntax error in ${fileName}: ${e.message}`) } // console.log(js) module._compile(js, fileName) } // require('source-map-support').install({ // environment: 'node' // , hookRequire: true // }) require.extensions['.ts'] = pureTypeScript module.exports = pureTypeScript.default = pureTypeScript.pureTypeScript = pureTypeScript })()
function pureTypeScript(module, fileName) { const ts = fs.readFileSync(fileName, 'utf8') let js try { js = tss.compile(ts, fileName) } catch (e) { throw new Error(`Syntax error in ${fileName}: ${e.message}`) } // console.log(js) module._compile(js, fileName) }
return function(content, file, done) { log.debug('Processing "%s".', file.originalPath); file.path = transformPath(file.originalPath); try { var output = compiler.compile(content, file.originalPath); done(null, output); } catch(e) { log.error('%s\n at %s\n%s', e.message, file.originalPath, e.stack); return done(e, null); } };
//通用文件处理 /* * file_paths 目录或者目录列表 * res_pathname 真正要返回的文件 * pathname URL请求的文件,不代表最后要返回的文件 */ function _route_to_file(file_paths, res_pathname, type, pathname, params, req, res) { //有大量异步操作,所以要把options缓存起来 var jhs_options = jhs.getOptions(req); //统一用数组 Array.isArray(file_paths) || (file_paths = [file_paths]); console.log(("[ " + type.placeholder(5) + "]").colorsHead(), "=>", pathname.placeholder(60, "\n\t"), "=>", file_paths, res_pathname, "\n") //如果是取MAP,直接取出 var map_md5 = req.query._MAP_MD5_; var map_from = req.query._MAP_FROM_; if (map_md5 && map_from) { res.body = temp.get(map_from, map_md5); return } if (!fss.existsFileInPathsSync(file_paths, pathname)) { res.status(404); var _404file_name = jhs_options["404"] || "404.html"; if (!fss.existsFileInPathsSync(file_paths, _404file_name)) { res.set('Content-Type', mime.contentType("html")); res.body = _get_404_file(); return; } res_pathname = _404file_name; } var file_path = file_paths.map(function(folder_path) { return folder_path + "/" + res_pathname; }); var content_type = mime.contentType(type); res.set('Content-Type', content_type); var fileInfo = cache.getFileCache(file_path, cache.options.file_cache_time, jhs_options); res.body = fileInfo.source_content; if (fileInfo.is_text) { var _path_info = path.parse(res_pathname); var _extname = _path_info.ext; var _filename = _path_info.base; var _basename = _path_info.name; res.is_text = true; res.text_file_info = { filename: _filename, basename: _basename, extname: _extname, }; } (jhs_options.common_filter_handle instanceof Function) && jhs_options.common_filter_handle(pathname, params, req, res); jhs.emit("*." + type, pathname, params, req, res); /* * 用户自定义的处理完成后再做最后的处理,避免nunjucks的include、import指令导入的内容没有处理 */ if (fileInfo.is_text) { res.body = res.body.replaceAll("__pathname__", pathname) .replaceAll("__res_pathname__", res_pathname) .replaceAll("__filename__", _filename) .replaceAll("__basename__", _basename) .replaceAll("__extname__", _extname); var _lower_case_extname = _extname.toLowerCase(); var _lower_case_compile_to = req.query.compile_to; _lower_case_compile_to = (_lower_case_compile_to || "").toLowerCase(); var _temp_body; /* TYPESCRIPT编译 */ if (_lower_case_extname === ".ts" && /js|\.js/.test(_lower_case_compile_to)) { if (fileInfo.compile_tsc_content) { res.body = fileInfo.compile_tsc_content; } else { if (_temp_body = temp.get("typescript", fileInfo.source_md5)) { res.body = fileInfo.compile_tsc_content = _temp_body.toString(); //Buffer to String } else { var tss = new TypeScriptSimple({ sourceMap: jhs_options.tsc_sourceMap }); res.type('js'); try { var tsc_compile_resule = tss.compile(res.body, path.parse(fileInfo.filepath).dir); res.body = tsc_compile_resule; temp.set("typescript", fileInfo.source_md5, res.body); } catch (e) { console.log(e.stack) // res.status(500); res.body = '((window.console&&console.error)||alert).call(window.console,' + JSON.stringify(e.message) + ')'; } } } } /* Babel编译 */ if (((_lower_case_extname === ".bb" || _filename.endWith(".bb.js")) && /js|\.js/.test(_lower_case_compile_to)) || /bb_to_\.js/.test(_lower_case_compile_to)) { if (fileInfo.compile_bb_content) { res.body = fileInfo.compile_bb_content; } else { if (_temp_body = temp.get("babel-core", fileInfo.source_md5)) { res.body = fileInfo.compile_bb_content = _temp_body.toString(); //Buffer to String } else { res.type('js'); try { console.time("Babel:" + _filename); console.log(req.query); var sourceMaps = $$.boolean_parse(req.query.debug) var bb_compile_resule = BabelCore.transform(res.body, { filename: __dirname + "/babel/" + _filename, ast: false, sourceMaps: sourceMaps, babelrc: false, code: true, presets: ['es2015'], ignore: ["node_modules/**/*.js"], // plugins: ["syntax-async-generators"] }); var code = bb_compile_resule.code; if (sourceMaps) { code += "\n//# sourceMappingURL=" + res_pathname + "?_MAP_MD5_=" + fileInfo.source_md5 + "&_MAP_FROM_=babel-core-map"; fileInfo.compile_bb_content_map = JSON.stringify(bb_compile_resule.map); temp.set("babel-core-map", fileInfo.source_md5, fileInfo.compile_bb_content_map); } console.timeEnd("Babel:" + _filename); res.body = fileInfo.compile_bb_content = code; temp.set("babel-core", fileInfo.source_md5, res.body); } catch (e) { console.log(e.stack) // res.status(500); res.body = '((window.console&&console.error)||alert).call(window.console,' + JSON.stringify(e.message) + ')'; } } } } /* SASS编译 */ if (_lower_case_extname === ".scss" && /css|\.css/.test(_lower_case_compile_to)) { if (fileInfo.compile_sass_content) { res.body = fileInfo.compile_sass_content; } else { if (_temp_body = temp.get("sass", fileInfo.source_md5)) { // console.log("使用缓存,无需编译!!") res.body = fileInfo.compile_sass_content = _temp_body.toString(); //Buffer to String } else { var fiber = Fiber.current; sass.render({ data: res.body, includePaths: [path.parse(fileInfo.filepath).dir] }, function(e, result) { process.nextTick(function() { if (e) { res.status(500); fiber.run({ css: (e && e.stack) || String(e) }) return } fiber.run(result) }); }); var sass_compile_result = Fiber.yield(); res.body = fileInfo.compile_sass_content = sass_compile_result.css.toString(); temp.set("sass", fileInfo.source_md5, res.body); } } //文件内容变为CSS了,所以可以参与CSS文件类型的处理 extname = ".css"; } /* LESS编译 */ if (_lower_case_extname === ".less" && /css|\.css/.test(_lower_case_compile_to)) { if (fileInfo.compile_less_content) { res.body = fileInfo.compile_less_content; } else { if (_temp_body = temp.get("less", fileInfo.source_md5)) { // console.log("使用缓存,无需编译!!") res.body = fileInfo.compile_less_content = _temp_body.toString(); //Buffer to String } else { var fiber = Fiber.current; less.render(res.body, { paths: [path.parse(fileInfo.filepath).dir], filename: _filename }, function(e, output) { process.nextTick(function() { if (e) { // console.error(e instanceof Error) // fiber.throwInto(e); res.status(500); fiber.run({ css: (e && e.stack) || String(e) }) return } console.log("output:::::", output) fiber.run(output) }); }); var less_compile_result = Fiber.yield(); res.body = fileInfo.compile_less_content = less_compile_result.css.toString(); temp.set("less", fileInfo.source_md5, res.body); } } //文件内容变为CSS了,所以可以参与CSS文件类型的处理 extname = ".css"; } /* CSS压缩 */ if (jhs_options.css_minify && _lower_case_extname === ".css") { if (fileInfo.minified_css_content) { res.body = fileInfo.minified_css_content; } else { if (_temp_body = temp.get("css_minify", fileInfo.source_md5)) { res.body = fileInfo.minified_css_content = _temp_body.toString(); //Buffer to String } else { var fiber = Fiber.current; new CleanCSS().minify(res.body, function(err, minified) { if (err) { console.log("[CleanCSS Minify Error]".colorsHead(), "=>", err); } res.body = fileInfo.minified_css_content = minified.styles; if (minified.errors.length + minified.warnings.length) { minified.errors.forEach(function(err) { console.log("[CSS Error]".colorsHead(), "=>", err); }); minified.warnings.forEach(function(war) { console.log("[CSS Warn]".colorsHead(), "=>", war); }); } fiber.run(); }); Fiber.yield(); temp.set("css_minify", fileInfo.source_md5, res.body); } } } /* JS压缩 */ if (jhs_options.js_minify && _lower_case_extname === ".js" || $$.boolean_parse(req.query.min)) { if (fileInfo.minified_js_content) { res.body = fileInfo.minified_js_content; } else { if (_temp_body = temp.get("js_minify", fileInfo.source_md5)) { res.body = fileInfo.minified_js_content = _temp_body.toString(); //Buffer to String } else { var js_minify_result = UglifyJS.minify(res.body, { fromString: true }); res.body = fileInfo.minified_js_content = js_minify_result.code; temp.set("js_minify", fileInfo.source_md5, res.body); } } } /* HTML压缩 */ if (jhs_options.html_minify && _lower_case_extname === ".html") { } } };