diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..8c52ff9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintrc b/.eslintrc new file mode 100755 index 0000000..13e5d61 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,10 @@ +env: + browser: false + node: true +rules: + no-extra-parens: 2 + eqeqeq: 2 + block-scoped-var: 2 + quotes: + - 2 + - single diff --git a/.gitattributes b/.gitattributes new file mode 100755 index 0000000..176a458 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..ba2a97b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +coverage diff --git a/.travis.yml b/.travis.yml new file mode 100755 index 0000000..cfe68da --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: + - '0.10' + - '0.11' +after_script: + - npm run-script coveralls +notifications: + email: false diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..81395e4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Shinnosuke Watanabe + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100755 index 0000000..5cf7796 --- /dev/null +++ b/README.md @@ -0,0 +1,78 @@ +# script-equal + +[![Build Status](https://travis-ci.org/shinnn/script-equal.svg?branch=master)](https://travis-ci.org/shinnn/script-equal) +[![Build status](https://ci.appveyor.com/api/projects/status/ia3h5bcsy84vgfpc?svg=true)](https://ci.appveyor.com/project/ShinnosukeWatanabe/script-equal) +[![Coverage Status](https://img.shields.io/coveralls/shinnn/script-equal.svg)](https://coveralls.io/r/shinnn/script-equal) +[![Dependency Status](https://david-dm.org/shinnn/script-equal.svg)](https://david-dm.org/shinnn/script-equal) +[![devDependency Status](https://david-dm.org/shinnn/script-equal/dev-status.svg)](https://david-dm.org/shinnn/script-equal#info=devDependencies) + +Check if one JavaScript code is equivalent to another code, using [UglifyJS] + +```javascript +var scriptEqual = require('script-equal'); + +scriptEqual( + 'window.foo = {a: 0, b: 1};', + 'window["foo"]={\nb: 1,\rna: 0\n};' +); //=> true + +scriptEqual( + 'var foo = 12', + 'var foo = 1 + 1 * 14 - 3;;;;;;;;;;;;;;;;;;;' +); //=> true +``` + +## Installation + +[![NPM version](https://badge.fury.io/js/script-equal.svg)](https://www.npmjs.org/package/script-equal) + +[Use npm.](https://www.npmjs.org/doc/cli/npm-install.html) + +``` +npm install script-equal +``` + +## API + +```javascript +var scriptEqual = require('script-equal'); +``` + +### scriptEqual(*script0*, *script1* [, *options*]) + +*script0*:`String` (JavaScript code) +*script1*:`String` (JavaScript code) +*options*: `Object` ([UglifyJS][options] options) +Return: `Boolean` + +It compresses two JavaScript string with [UglifyJS]. If the results are the same string, it returns `true`. Otherwise it returns `false`. + +You can use all [UglifyJS][options] options. + +```javascript +var scriptEqual = require('script-equal'); + +var foo = 'a = {}; a.b = 0;'; +var bar = 'a = {}; a[\'b\'] = 0;'; + +scriptEqual(foo, bar); //=> true + +scriptEqual(foo, bar, { + compress: {properties: false} +}); //=> false +``` + +It throws an error when it fails to parse strings. + +```javascript +scriptEqual('a = 1', '1 = a'); // Error +``` + +## License + +Copyright (c) 2014 [Shinnosuke Watanabe](https://github.com/shinnn) + +Licensed under [the MIT License](./LICENSE). + +[UglifyJS]: https://github.com/mishoo/UglifyJS2 +[options]: https://github.com/mishoo/UglifyJS2#api-reference diff --git a/appveyor.yml b/appveyor.yml new file mode 100755 index 0000000..5c3c7d1 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,20 @@ +init: + - git config --global core.autocrlf input + +version: '{build}' + +environment: + matrix: + - nodejs_version: '0.10' + - nodejs_version: '0.11' + +install: + - ps: Install-Product node $env:nodejs_version + - npm install --production + - npm install tape + +build: off + +test_script: + - ps: 'node test.js #PowerShell' + - cmd: node test.js diff --git a/index.js b/index.js new file mode 100755 index 0000000..2b3acf2 --- /dev/null +++ b/index.js @@ -0,0 +1,22 @@ +/*! + * script-equal | MIT (c) Shinnosuke Watanabe + * https://github.com/shinnn/script-equal +*/ +'use strict'; + +var UglifyJS = require('uglify-js'); +var xtend = require('xtend'); + +module.exports = function scriptEqual(first, second, options) { + [first, second].forEach(function(arg, i) { + if (typeof arg !== 'string') { + throw new TypeError( + i === 0 ? 'First' : 'Second', + ' argument is not a string. Arguments must be: (string, string[, options])' + ); + } + }); + + options = xtend(options, {fromString: true}); + return UglifyJS.minify(first, options).code === UglifyJS.minify(second, options).code; +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..dbf241c --- /dev/null +++ b/package.json @@ -0,0 +1,56 @@ +{ + "name": "script-equal", + "version": "0.0.0", + "description": "Check if one JavaScript code is equivalent to another code", + "repository": "shinnn/script-equal", + "author": { + "name": "Shinnosuke Watanabe", + "url": "https://github.com/shinnn" + }, + "scripts": { + "pretest": "eslint *.js & jscs *.js", + "test": "node test.js | tap-spec", + "coverage": "istanbul cover test.js", + "coveralls": "${npm_package_scripts_coverage} && istanbul-coveralls" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/shinnn/script-equal/blob/master/LICENSE" + } + ], + "files": [ + "index.js", + "LICENSE" + ], + "keywords": [ + "code", + "parse", + "compare", + "comparison", + "equal", + "equivalent", + "script", + "js", + "javascript", + "uglify", + "uglifyjs", + "uglify-js" + ], + "dependencies": { + "uglify-js": "^2.4.15", + "xtend": "^4.0.0" + }, + "devDependencies": { + "eslint": "^0.9.2", + "istanbul": "^0.3.2", + "istanbul-coveralls": "^1.0.1", + "jscs": "^1.7.3", + "tap-spec": "^2.1.0", + "tape": "^3.0.3" + }, + "jscsConfig": { + "preset": "google", + "maximumLineLength": 98 + } +} diff --git a/test.js b/test.js new file mode 100755 index 0000000..7511310 --- /dev/null +++ b/test.js @@ -0,0 +1,58 @@ +'use strict'; + +var scriptEqual = require('./'); +var test = require('tape'); + +test('scriptEqual()', function(t) { + t.plan(7); + + t.strictEqual( + scriptEqual( + 'function w() {};\n(function() {\r\nvar d =2;var arr={e:0, f:[\'\', {}]}})();', + '(function() {\nvar w=1+ 1*"1",a = {f: ["", {}], e: 0};})(); function w() {}' + ), + true, + 'should return boolean if the first script is equivalent to the second.' + ); + + t.strictEqual( + scriptEqual( + 'a={};a[\'b\']=1;', + 'a={};a.b=1;', + {compress: {properties: false}} + ), + false, + 'should support `compress` option.' + ); + + t.strictEqual( + scriptEqual( + '(function(a) {a=1})(this)', + '(function(b) {b=1})(this)', + {mangle: false} + ), + false, + 'should support `mangle` option.' + ); + + t.strictEqual( + scriptEqual('', ' ', false), + true, + 'should run completely even if the third argument is falsy.' + ); + + t.throws( + scriptEqual.bind(null, [''], '', {}), /TypeError.*First/, + 'should throw a type error when the first argument is not a string.' + ); + + t.throws( + scriptEqual.bind(null, '', 1), /TypeError.*Second/, + 'should throw a type error when the second argument is not a string.' + ); + + t.throws( + scriptEqual.bind(null), /TypeError.*First/, + 'should throw a type error when it takes no arguments.' + ); +});