UNPKG

sourcemint-loader-js

Version:

277 lines (234 loc) 8.52 kB
var CONNECT = require("connect"), FS = require("fs"), PATH = require("path"), CRYPTO = require("crypto"), QUERYSTRING = require("querystring"); HTTP = require("http"), FS = require("fs"), ZLIB = require("zlib"); const ROOT_PATH = PATH.dirname(__dirname); const PORT = 8080; exports.main = function() { var server = CONNECT(); server.use(CONNECT.router(function(app) { app.get(/^\/$/, function(req, res) { res.writeHead(302, { "Location": "http://127.0.0.1:" + PORT + "/workspace/www/" }); res.end(); }); app.get(/^\/loader.js$/, function(req, res) { res.setHeader("Content-Type", "text/javascript"); res.end(getRawSource()); }); app.get(/^\/loader.stripped.js$/, function(req, res) { res.setHeader("Content-Type", "text/plain"); res.end(getStrippedSource()); }); app.get(/^\/loader.min.js/, function(req, res) { res.setHeader("Content-Type", "text/plain"); getMinifiedSource(function(source) { res.end(source); }); }); app.get(/^\/loader.crush.js/, function(req, res) { res.setHeader("Content-Type", "text/plain"); getCrushedSource(function(source) { res.end(source); }); }); app.get(/^\/loader.min.js.gz/, function(req, res) { res.setHeader("Content-Type", "application/x-javascript"); res.setHeader("Content-Encoding", "gzip"); getMinifiedSource(function() { var raw = FS.createReadStream(ROOT_PATH + "/loader.min.js.gz"); res.writeHead(200, { "content-encoding": "gzip" }); raw.pipe(res); }); }); app.get(/^\/loader.crush.js.gz/, function(req, res) { res.setHeader("Content-Type", "application/x-javascript"); res.setHeader("Content-Encoding", "gzip"); getCrushedSource(function() { var raw = FS.createReadStream(ROOT_PATH + "/loader.crush.js.gz"); res.writeHead(200, { "content-encoding": "gzip" }); raw.pipe(res); }); }); app.get(/^\/.*/, CONNECT.static(ROOT_PATH)); })); server.listen(PORT, "127.0.0.1"); console.log("Workspace running. Open browser to: http://127.0.0.1:" + PORT + "/"); } if (require.main === module) { exports.main(); } function getRawSource() { return FS.readFileSync(ROOT_PATH + "/loader.js").toString(); } function getStrippedSource() { var source = getRawSource(); source = source.split("\n").filter(function(line) { return !(/\/\*DEBUG\*\//.test(line)); }).join("\n"); source = "\n\n// WARNING: DO NOT EDIT THIS FILE! IT IS AUTO-GENERATED FROM ./loader.js BY STRIPPING '/*DEBUG*/' LINES.\n\n\n" + source; FS.writeFileSync(ROOT_PATH + "/loader.stripped.js", source); return source; } var minifying = false; function getMinifiedSource(callback) { var source = getStrippedSource(), sourceHash = md5Hash(source), fileHash = false; function done() { callback(FS.readFileSync(ROOT_PATH + "/loader.min.js").toString()); } if (PATH.existsSync(ROOT_PATH + "/workspace/www/loader.stripped.js.md5")) { fileHash = FS.readFileSync(ROOT_PATH + "/workspace/www/loader.stripped.js.md5").toString(); } if (sourceHash != fileHash && minifying === false) { minifying = true; console.log("Minifying loader.js using Google Closure ..."); compileSource(source, function(compiledSource) { FS.writeFileSync(ROOT_PATH + "/loader.min.js", compiledSource); FS.writeFileSync(ROOT_PATH + "/workspace/www/loader.min.js-size", ""+compiledSource.length); writeZip(compiledSource, ROOT_PATH + "/loader.min.js.gz", function(result) { FS.writeFileSync(ROOT_PATH + "/workspace/www/loader.min.js.gz-size", ""+result.length); var readme = FS.readFileSync(ROOT_PATH + "/README.md").toString(); readme = readme.replace(/\*\*\d* bytes\*\* \*\(minified and zipped\)\*/, "**" + result.length + " bytes** *(minified and zipped)*"); FS.writeFileSync(ROOT_PATH + "/README.md", readme); console.log("... OK"); // TMP: Bypass for now cos it is so slow. /* console.log("Crushing loader.min.js using JSCrush ..."); crushSource(compiledSource, function(crushedSource) { FS.writeFileSync(ROOT_PATH + "/loader.crush.js", crushedSource); FS.writeFileSync(ROOT_PATH + "/workspace/www/loader.crush.js-size", ""+crushedSource.length); writeZip(crushedSource, ROOT_PATH + "/loader.crush.js.gz", function(result) { FS.writeFileSync(ROOT_PATH + "/workspace/www/loader.crush.js.gz-size", ""+result.length); FS.writeFileSync(ROOT_PATH + "/workspace/www/loader.stripped.js.md5", sourceHash); console.log("... OK"); */ minifying = false; done(); /* }); }); */ }); }); } else { done(); } } function getCrushedSource(callback) { getMinifiedSource(function() { callback(FS.readFileSync(ROOT_PATH + "/loader.crush.js").toString()); }); } function md5Hash(data) { var shasum = CRYPTO.createHash("md5"); shasum.update(data); return shasum.digest("hex"); } function writeZip(source, zipPath, callback) { ZLIB.gzip(new Buffer(source), function(err, result) { FS.writeFileSync(zipPath, result.toString("binary")); var out = FS.createWriteStream(zipPath); out.on("close", function() { callback(result); }); out.end(result); }); } function compileSource(codestring, callback) { // @credit http://stackoverflow.com/questions/6158933/http-post-request-in-node-js var post_data = QUERYSTRING.stringify({ 'compilation_level' : 'SIMPLE_OPTIMIZATIONS', 'output_format': 'json', 'output_info': 'compiled_code', 'js_code' : codestring }); // An object of options to indicate where to post to var post_options = { host: 'closure-compiler.appspot.com', port: '80', path: '/compile', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': post_data.length } }; // Set up the request var post_req = HTTP.request(post_options, function(res) { res.setEncoding('utf8'); var data = []; res.on('data', function(chunk) { data.push(chunk); }); res.on('end', function() { callback(JSON.parse(data.join("")).compiledCode); }); }); // post the data post_req.write(post_data); post_req.end(); } /* @source http://www.iteral.com/jscrush/ */ function crushSource(codestring, callback) { // b.innerHTML="Javascript source<br><textarea rows=12 cols=80></textarea><br><button>CRUSH</button> <b></b><br><textarea rows=12 cols=80></textarea>"+b.innerHTML; Q=[]; for(i=127;--i;i-10&&i-13&&i-34&&i-39&&i-92&&Q.push(String.fromCharCode(i))); // setTimeout("b.children[1].value=eval(b.children[9].innerHTML.replace(/eval\\(_\\)/,'_'));L()"); // b.children[3].onclick=L= callback(function(s) { i=s=s.replace(/([\r\n]|^)\s*\/\/.*|[\r\n]+\s*/g,'').replace(/\\/g,'\\\\'),B=s.length/2,m=''; for(S=encodeURI(i).replace(/%../g,'i').length;;m=c+m){for(c=0,i=122;!c&&--i;!~s.indexOf(Q[i])&&(c=Q[i]));if(!c)break; for(o={},M=N=e=Z=t=0;++t<=B;)for(i=0;++i<s.length-t;)if(!o[x=s.substr(j=i,t)]) if(~(j=s.indexOf(x,j+t)))for(Z=t,o[x]=1;~j;o[x]++)j=s.indexOf(x,j+t);B=Z; for(i in o){j=encodeURI(i).replace(/%../g,'i').length;if(j=(R=o[i])*j-R-j-1)if(j>M||j==M&&R>N)M=j,N=R,e=i}if(!e)break; s=s.split(e).join(c)+c+e}c=s.split('"').length<s.split("'").length?(B='"',/"/g):(B="'",/'/g); return '_='+B+s.replace(c,'\\'+B)+B+';for(Y=0;$='+B+m+B+'[Y++];)with(_.split($))_=join(pop());eval(_)'; // i=encodeURI(i).replace(/%../g,'i').length; // b.children[4].innerHTML=S+'B to '+i+'B ('+(i=i-S)+'B, '+((i/S*1e4|0)/100)+'%)' }(codestring)); }