Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit ecaf9a43635bdcbb0e7ae1b645f9cdfb0a0185e7 1 parent 938d6e8
@yukinying authored
View
38 README.md
@@ -1,2 +1,38 @@
connect-strictenjs
-==================
+==================
+
+overview
+--------
+
+This is a connect middelware that adds ECMAScript 5 (ES5) strict mode by prepending "use strict" to all javascript blocks.
+As developers do not need to modify the html or JS code that the server is serving, one could quickly test if their
+code are compatible with the ES5 strict mode.
+
+The package also comes with a code beautifier (based on UglifyJS2), which allows easier troubleshooting when syntax errors
+are reported on minified code.
+
+recommended usage
+-----------------
+
+Use it with the javascript testing framework that use connect. To enable the middleware, one should simply patch the
+code with
+
+```javascript
+var strict = require('connect-strictenjs');
+
+app = express();
+
+app.use(strict.stricten() );
+app.use(strict.beautifier());
+
+// ... other logics that render the pages
+```
+
+Then install the package via
+
+```shell
+npm link
+```
+
+Sample code could be found in the example directory.
+
View
1  examples/html/helloworld.html
@@ -0,0 +1 @@
+<script src=helloworld.js></script>
View
4 examples/html/helloworld.js
@@ -0,0 +1,4 @@
+(function(){ console.log('hello world!'); document.write('hello world'); /* this is a quick and dirty... */ })();
+var b = 2;
+(function(){ b = 3; console.log("b ="+ b);})();
+(function(){ a = 1; console.log("a ="+ a);})();
View
9 examples/html/inline.html
@@ -0,0 +1,9 @@
+
+
+
+ <script>
+(function(){var k=13,d=4,j=0,a=document.documentElement,b=[a.className],f,c=navigator.plugins,g=k;if(c&&c.length){f=c["Shockwave Flash"];if(f&&f.description){j=parseInt(f.description.match(/\b(\d+)\.\d+\b/)[1],10)||0}}else{while(g--){try{new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+g);j=g;break}catch(h){}}}b.push("flash-"+j);while(j-->d){b.push("flash-gt"+j)}a.className=b.join(" ")})();
+</script>
+
+ <script type="text/javascript">
+ rtTop = Number(new Date()); document.documentElement.className += ' jsenabled'; </script>
View
29 examples/proxy.js
@@ -0,0 +1,29 @@
+var express = require('express');
+var connect = require('connect');
+
+var httpProxy = require('http-proxy')
+var url = require('url');
+
+// for development, use npm link to create symlink based installation.
+var strict = require('connect-strictenjs');
+
+var proxy = new httpProxy.RoutingProxy();
+
+app = express();
+
+var proxyware = function( req, res ) {
+ var uri = url.parse(req.url);
+ req.headers["Accept-Encoding"] = '';
+ proxy.proxyRequest(req, res, {
+ host: uri.hostname,
+ port: uri.port || 80
+ });
+};
+
+// app.use(express.logger());
+app.use(connect.responseTime());
+app.use(strict.stricten() );
+app.use(strict.beautifier());
+app.all('/*',proxyware);
+
+app.listen(8080);
View
18 examples/static.js
@@ -0,0 +1,18 @@
+var express = require('express');
+var connect = require('connect');
+
+var url = require('url');
+
+// for development, use npm link to create symlink based installation.
+var strict = require('connect-strictenjs');
+
+app = express();
+
+// app.use(express.logger());
+app.use(connect.responseTime());
+app.use(strict.stricten() );
+app.use(strict.beautifier());
+
+app.use(express.static(__dirname + '/html'));
+
+app.listen(8080);
View
206 lib/connect-stricten.js
@@ -0,0 +1,206 @@
+exports.filterJS = function( req, res ) {
+
+// TODO don't test url.
+ return (
+ /\.js/.test(req.url)
+ && req.accepts('json') == 'json'
+ && res.statusCode == 200
+ ) ;
+}
+
+exports.filterHTML = function( req, res ) {
+ return (
+ req.accepts('html') == 'html'
+ && res.statusCode == 200
+ ) ;
+}
+
+exports.beautify = function( body, p1, p2, p3 ) {
+ if( p3 ) body = p2;
+ try {
+ var U = require("uglify-js2");
+ var ostream = U.OutputStream({beautify: true, source_map: null} );
+ var toplevel = U.parse(body);
+ toplevel.print(ostream);
+ if( p3 )
+ return p1 + "\n" + ostream.toString() + "\n" + p3 ;
+ else
+ return ostream.toString();
+ } catch (e) {
+ console.log(body);
+ console.log(e)
+ }
+ return body;
+}
+
+exports.strictening = function( body, p1, p2, p3 ) {
+ if( p3 )
+ return p1 + "\n" + '"use strict";' + "\n" + p2 + "\n" + p3 ;
+ else
+ return '"use strict";' + "\n" + body;
+}
+
+exports.beautifier = function(options) {
+
+ var options = options || {} ;
+
+ return function (req, res, next) {
+
+ var
+ write = res.write
+ , writeHead = res.writeHead
+ , end = res.end
+ , url = req.originalUrl
+ , body = ''
+ , isJS = exports.filterJS(req,res)
+ , isHTML = exports.filterHTML(req,res)
+ ;
+
+
+
+ res.on('header', function( ) {
+ if( isJS || isHTML ) {
+ console.log('Url is ' + req.url );
+ console.log('Content Length is ' + res.get('Content-Length'));
+ console.log('Content Type is ' + res.get('Content-Type'));
+
+ res.removeHeader('Content-Length');
+ res.removeHeader('last-modified');
+ }
+ if( res.get('Content-Type') ) {
+ isJS = isJS && /javascript|json/.test(res.get('Content-Type'));
+ }
+ });
+
+ // From https://github.com/nateps/connect/blob/4025c2fbd2f53d4a8fe5608055514eee0d696ca1/lib/patch.js
+ // Until connect has taken the patch, we could only patch it here.
+ res.writeHead = function(statusCode){
+ var reasonPhrase, headers, headerIndex;
+ if (typeof arguments[1] == 'string') {
+ reasonPhrase = arguments[1];
+ headerIndex = 2;
+ } else {
+ headerIndex = 1;
+ }
+ headers = arguments[headerIndex];
+ if (headers) {
+ for (var name in headers) {
+ this.setHeader(name, headers[name]);
+ }
+ }
+ if (!this._emittedHeader) this.emit('header');
+ this._emittedHeader = true;
+ return writeHead.call(this, statusCode, reasonPhrase);
+ };
+
+ res.write = function( chunk, encoding ) {
+ if( isJS || isHTML ) {
+ body += chunk; }
+ else {
+ write.apply(res,arguments);
+ }
+ }
+
+ res.end = function(chunk,encoding) {
+ if( isJS ) {
+ if (chunk) body += chunk;
+ console.log('beautifying ' + url);
+ var ubody = exports.beautify( body ) ;
+ write.call(res,ubody,encoding);
+ end.call(res);
+ } else if ( isHTML ) {
+ if (chunk) body += chunk;
+ console.log('beautifying ' + url);
+ body = body.replace(/(<script[^>]*>)((?:.|\s)*?)(<\/script>)/mig, exports.beautify ) ;
+ write.call(res,body,encoding);
+ end.call(res);
+
+ } else {
+ end.apply(res,arguments)
+ }
+ }
+
+ next();
+
+ };
+}
+
+exports.stricten = function(options) {
+
+ var options = options || {} ;
+
+ return function (req, res, next) {
+
+ var
+ called = false
+ , write = res.write
+ , writeHead = res.writeHead
+ , body = ''
+ , end = res.end
+ , url = req.originalUrl
+ , isJS = exports.filterJS( req, res)
+ , isHTML = exports.filterHTML( req, res)
+ ;
+
+ // Normal case
+ res.on('header', function( ) {
+ if( isJS ) {
+ res.removeHeader('Content-Length');
+ res.removeHeader('last-modified'); // do not cache modification on-the-fly
+ }
+ if( res.get('Content-Type') ) {
+ isJS = isJS && /javascript|json/.test(res.get('Content-Type'));
+ }
+ });
+
+ // From https://github.com/nateps/connect/blob/4025c2fbd2f53d4a8fe5608055514eee0d696ca1/lib/patch.js
+ // Until connect has taken the patch, we could only patch it here.
+ res.writeHead = function(statusCode){
+ var reasonPhrase, headers, headerIndex;
+ if (typeof arguments[1] == 'string') {
+ reasonPhrase = arguments[1];
+ headerIndex = 2;
+ } else {
+ headerIndex = 1;
+ }
+ headers = arguments[headerIndex];
+ if (headers) {
+ for (var name in headers) {
+ this.setHeader(name, headers[name]);
+ }
+ }
+ if (!this._emittedHeader) this.emit('header');
+ this._emittedHeader = true;
+ return writeHead.call(this, statusCode, reasonPhrase);
+ };
+
+ res.write = function( chunk, encoding ) {
+
+ if( isJS ) {
+ called = true;
+ console.log('strictening ' + url);
+ write.call(res, exports.strictening(chunk), encoding);
+ } else if ( isHTML ) {
+ if (chunk) body += chunk;
+ } else {
+ write.apply(res,arguments);
+ }
+ }
+
+
+ res.end = function(chunk,encoding) {
+ if ( isHTML ) {
+ if (chunk) body += chunk;
+ console.log('strictening ' + url);
+ body = body.replace(/(<script[^>]*>)((?:.|\s)*?)(<\/script>)/mig, exports.strictening ) ;
+ write.call(res,body,encoding);
+ end.call(res);
+ } else {
+ end.apply(res,arguments)
+ }
+ }
+
+ next();
+
+ };
+}
View
24 package.json
@@ -0,0 +1,24 @@
+{
+ "name": "connect-strictenjs",
+ "version": "0.0.1",
+ "description": "a Strict mode (ES5) enforcer via connect middleware",
+ "main": "lib/connect-stricten.js",
+ "directories": {
+ "example": "examples",
+ "test": "test"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:yukinying/connect-strictenjs.git"
+ },
+ "keywords": [
+ "ES5",
+ "connect",
+ "strict"
+ ],
+ "author": "Albert Yu",
+ "license": "BSD"
+}
Please sign in to comment.
Something went wrong with that request. Please try again.