pax_global_header00006660000000000000000000000064143227550750014524gustar00rootroot0000000000000052 comment=34ffc809e0264067554214c528d8c4db9468a8e2 uglifyify-6.0.0/000077500000000000000000000000001432275507500135365ustar00rootroot00000000000000uglifyify-6.0.0/.github/000077500000000000000000000000001432275507500150765ustar00rootroot00000000000000uglifyify-6.0.0/.github/dependabot.yml000066400000000000000000000002171432275507500177260ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: npm directory: "/" schedule: interval: daily time: "04:00" open-pull-requests-limit: 10 uglifyify-6.0.0/.github/workflows/000077500000000000000000000000001432275507500171335ustar00rootroot00000000000000uglifyify-6.0.0/.github/workflows/ci.yml000066400000000000000000000013441432275507500202530ustar00rootroot00000000000000name: Node CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [6.x, 8.x, 10.x, 12.x, 14.x, 16.x, 18.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: npm install run: npm install - name: npm test run: npm run tests-only lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Use Node.js LTS uses: actions/setup-node@v3 with: node-version: lts/* - name: npm install run: npm install - name: npm run lint run: npm run lint uglifyify-6.0.0/.gitignore000066400000000000000000000000161432275507500155230ustar00rootroot00000000000000node_modules/ uglifyify-6.0.0/.npmrc000066400000000000000000000000231432275507500146510ustar00rootroot00000000000000package-lock=false uglifyify-6.0.0/LICENSE.md000066400000000000000000000020611432275507500151410ustar00rootroot00000000000000This software is released under the MIT license: 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. uglifyify-6.0.0/README.md000066400000000000000000000117341432275507500150230ustar00rootroot00000000000000# @browserify/uglifyify A [Browserify](http://browserify.org) transform which minifies your code using [terser](https://github.com/fabiosantoscode/terser). ## Installation ``` bash npm install @browserify/uglifyify ``` ## Motivation/Usage Ordinarily you'd be fine doing this: ``` bash browserify index.js | terser -c > bundle.js ``` But uglifyify is able to yield smaller output by processing files individually instead of just the entire bundle. When using uglifyify you should generally **also** use Uglify, to achieve the smallest output. Uglifyify provides an additional optimization when used with Uglify, but does not provide all of the optimization that using Uglify on its own does, so it's not a replacement. Uglifyify gives you the benefit of applying Uglify's "squeeze" transform on each file *before* it's included in the bundle, meaning you can remove dead code paths for conditional requires. Here's a contrived example: ``` javascript if (true) { module.exports = require('./browser') } else { module.exports = require('./node') } ``` `module.exports = require('./node')` will be excluded by Uglify, meaning that only `./browser` will be bundled and required. If you combine uglifyify with [envify](http://github.com/hughsk/envify), you can make this a little more accessible. Take this code: ``` javascript if (process.env.NODE_ENV === 'development') { module.exports = require('./development') } else { module.exports = require('./production') } ``` And use this to compile: ``` bash NODE_ENV=development browserify -t envify -t @browserify/uglifyify index.js -o dev.js && NODE_ENV=production browserify -t envify -t @browserify/uglifyify index.js -o prod.js ``` It should go without saying that you should be hesitant using environment variables in a Browserify module - this is best suited to your own applications or modules built with Browserify's `--standalone` tag. ## File Extensions Sometimes, you don't want uglifyify to minify all of your files – for example, if you're using a transform to `require` CSS or HTML, you might get an error as uglify expects JavaScript and will throw if it can't parse what it's given. This is done using the `-x` or `--exts` transform options, e.g. from the command-line: ``` bash browserify \ -t coffeeify \ -t [ @browserify/uglifyify -x .js -x .coffee ] ``` The above example will only minify `.js` and `.coffee` files, ignoring the rest. ## Global Transforms You might also want to take advantage of uglifyify's pre-bundle minification to produce slightly leaner files across your entire browserify bundle. By default, transforms only alter your application code, but you can use global transforms to minify module code too. From your terminal: ``` bash browserify -g @browserify/uglifyify ./index.js > bundle.js ``` Or programatically: ``` javascript var browserify = require('browserify') var fs = require('fs') var bundler = browserify(__dirname + '/index.js') bundler.transform('@browserify/uglifyify', { global: true }) bundler.bundle() .pipe(fs.createWriteStream(__dirname + '/bundle.js')) ``` Note that this is fine for uglifyify as it shouldn't modify the behavior of your code unexpectedly, but transforms such as envify should almost always stay local – otherwise you'll run into unexpected side-effects within modules that weren't expecting to be modified as such. ## Ignoring Files Sometimes uglifyjs will break specific files under specific settings – it's rare, but does happen – and to work around that, you can use the `ignore` option. Given one or more glob patterns, you can filter out specific files this way: ``` bash browserify -g [ @browserify/uglifyify --ignore '**/node_modules/weakmap/*' ] ./index.js ``` ``` javascript var bundler = browserify('index.js') bundler.transform('@browserify/uglifyify', { global: true, ignore: [ '**/node_modules/weakmap/*' , '**/node_modules/async/*' ] }) bundler.bundle().pipe(process.stdout) ``` ## Source Maps Uglifyify supports source maps, so you can minify your code and still see the original source – this works especially well with a tool such as [exorcist](https://github.com/thlorenz/exorcist) when creating production builds. Source maps are enabled when: * You're using another transform, such as [coffeeify](https://github.com/jnordberg/coffeeify), that inlines source maps. * You've passed the `--debug` flag (or `debug` option) to your browserify bundle. Enabling `--debug` with browserify is easy: ``` bash browserify -t @browserify/uglifyify --debug index.js ``` ``` javascript var bundler = browserify({ debug: true }) bundler .add('index.js') .transform('@browserify/uglifyify') .bundle() .pipe(process.stdout) ``` If you'd prefer them not to be included regardless, you can opt out using the `sourcemap` option: ``` bash browserify -t [ @browserify/uglifyify --no-sourcemap ] app.js ``` ``` javascript var bundler = browserify('index.js') bundler.transform('@browserify/uglifyify', { sourceMap: false }) .bundle() .pipe(process.stdout) ``` uglifyify-6.0.0/index.js000066400000000000000000000066201432275507500152070ustar00rootroot00000000000000const minimatch = require('minimatch').Minimatch const convert = require('convert-source-map') const through = require('through2') const path = require('path') const xtend = require('xtend') module.exports = uglifyify function uglifyify (file, opts) { opts = xtend(opts || {}) let debug = opts._flags && opts._flags.debug // lazy require `terser` so uglifyify can be loaded on very old node.js versions const ujs = opts.uglify || require('terser') if (ignore(file, opts.ignore)) { return through() } let buffer = '' const exts = [] .concat(opts.exts || []) .concat(opts.x || []) .map(function (d) { if (d.charAt(0) === '.') return d return '.' + d }) if ( /\.json$/.test(file) || (exts.length && exts.indexOf(path.extname(file)) === -1) ) { return through() } // remove exts before passing opts to uglify delete opts.global delete opts.exts delete opts.x delete opts.uglify return through(function write (chunk, _enc, callback) { buffer += chunk callback() }, capture(function ready (callback) { const stream = this debug = opts.sourceMap !== false && debug opts = xtend({ compress: true, mangle: true, sourceMap: { filename: file } }, opts) // map out command line options to uglify compatible ones mapArgv(opts) if (typeof opts.compress === 'object') { opts.compress = xtend(opts.compress || {}) delete opts.compress._ } if (debug) opts.sourceMap.url = 'out.js.map' // Check if incoming source code already has source map comment. // If so, send it in to ujs.minify as the inSourceMap parameter if (debug) { opts.sourceMap.content = 'inline' } return Promise.resolve(ujs.minify(buffer, opts)).then(function (min) { // we should catch the min error if it comes back and end the stream if (min.error) throw min.error // Uglify leaves a source map comment pointing back to "out.js.map", // which we want to get rid of because it confuses browserify. min.code = min.code.replace(/\/\/[#@] ?sourceMappingURL=out.js.map$/, '') stream.push(min.code) if (min.map && min.map !== 'null') { const map = convert.fromJSON(min.map) map.setProperty('sources', [path.basename(file)]) stream.push('\n') stream.push(map.toComment()) } callback() }) })) function capture (fn) { return function (callback) { const stream = this try { fn.apply(stream, arguments).catch(function (err) { callback(err) }) } catch (err) { callback(err) } } } } function ignore (file, list) { if (!list) return list = Array.isArray(list) ? list : [list] return list.some(function (pattern) { const match = minimatch(pattern) return match.match(file) }) } // uglify-es doesn't allow for command line options in javascript api, this // remaps it function mapArgv (opts) { if (opts._flags) { delete opts._flags } if (opts.c) { opts.compress = opts.c delete opts.c } if (opts.m) { opts.mangle = opts.m delete opts.m } if (opts.p) { opts.parse = opts.p delete opts.p } if (opts.b) { opts.beautify = opts.b delete opts.b } if (opts.o) { opts.output = opts.o delete opts.o } if (opts.d) { opts.define = opts.d delete opts.d } delete opts._ } uglifyify-6.0.0/package.json000066400000000000000000000020371432275507500160260ustar00rootroot00000000000000{ "name": "@browserify/uglifyify", "version": "6.0.0", "description": "A browserify transform which minifies your code using Terser", "main": "index.js", "dependencies": { "convert-source-map": "^1.9.0", "minimatch": "^3.0.2", "terser": "^5.15.1", "through2": "^4.0.2", "xtend": "^4.0.1" }, "devDependencies": { "bl": "^5.0.0", "browserify": "^17.0.0", "from2-string": "^1.1.0", "standard": "^17.0.0", "tap-spec": "^5.0.0", "tape": "^5.6.1", "uglify-js": "^3.17.3", "wrap-stream": "^2.0.0" }, "scripts": { "tests-only": "node test | tap-spec", "lint": "standard", "test": "npm run lint && npm run tests-only" }, "repository": { "type": "git", "url": "git://github.com/browserify/uglifyify.git" }, "keywords": [ "uglify", "minify", "compress", "compile", "browserify", "transform", "stream" ], "author": "Hugh Kennedy (http://hughskennedy.com/)", "license": "MIT", "readmeFilename": "README.md" } uglifyify-6.0.0/test/000077500000000000000000000000001432275507500145155ustar00rootroot00000000000000uglifyify-6.0.0/test/fixture.js000066400000000000000000000001301432275507500165330ustar00rootroot00000000000000/* eslint-disable */ var hello = 'world' if (hello !== 'world') { throw new Error() } uglifyify-6.0.0/test/index.js000066400000000000000000000132341432275507500161650ustar00rootroot00000000000000const convert = require('convert-source-map') const wrap = require('wrap-stream') const browserify = require('browserify') const from2 = require('from2-string') const test = require('tape') const path = require('path') const uglifyify = require('../') const fs = require('fs') const bl = require('bl').BufferListStream let uglify try { uglify = require('terser') } catch (_err) { // The terser version we use by default requires Node.js 10+ uglify = require('uglify-js') } test('uglifyify: sanity check', function (t) { const src = path.join(__dirname, 'fixture.js') const orig = fs.readFileSync(src, 'utf8') fs.createReadStream(src) .pipe(uglifyify(src, { uglify })) .pipe(bl(function (err, data) { if (err) return t.ifError(err) data = String(data) t.notEqual(data.indexOf('var hello'), -1, 'var hello') t.notEqual(data.indexOf('"world"'), -1, '"world"') t.notEqual(data, orig, 'should be minified') t.end() })) }) test('uglifyify: ignores json', function (t) { const src = path.join(__dirname, 'fixture.js') const json = path.join(__dirname, 'fixture.json') const orig = fs.readFileSync(src, 'utf8') fs.createReadStream(src) .pipe(uglifyify(json, { uglify })) .pipe(bl(buffered)) function buffered (err, data) { if (err) return t.ifError(err) data = String(data) t.equal(data, orig, 'should not be minified') t.end() } }) test('uglifyify: -t [ uglifyify --exts ]', function (t) { const src = path.join(__dirname, 'fixture.js') const orig = fs.readFileSync(src, 'utf8') t.plan(5) check(path.join(__dirname, 'fixture.json'), true) check(path.join(__dirname, 'fixture.obj2'), false) check(path.join(__dirname, 'fixture.mkdn'), false) check(path.join(__dirname, 'fixture.fbla'), true) check(src, true) function check (name, ignored) { fs.createReadStream(src) .pipe(uglifyify(name, { exts: ['mkdn'], x: ['.obj2'], uglify })) .pipe(bl(buffered)) function buffered (err, data) { if (err) return t.ifError(err) data = String(data) t.ok(ignored ? data === orig : data !== orig , path.extname(name) + ' handled as expected') } } }) test('uglifyify: passes options to uglify', function (t) { const src = path.join(__dirname, 'fixture.js') const orig = fs.readFileSync(src, 'utf8') let buf1 = null fs.createReadStream(src) .pipe(closure()) .pipe(uglifyify(src, { compress: { conditionals: false }, uglify })) .pipe(bl(buffered1)) function buffered1 (err, _buf1) { if (err) return t.ifError(err) buf1 = String(_buf1) t.notEqual(buf1, orig, 'should be minified') fs.createReadStream(src) .pipe(closure()) .pipe(uglifyify(src, { uglify })) .pipe(bl(buffered2)) } function buffered2 (err, buf2) { if (err) return buf2 = String(buf2) t.notEqual(buf2, orig, 'should be minified') t.notEqual(buf1, buf2, 'options altered output') t.end() } }) function closure () { return wrap('(function(){', '})()') } test('uglifyify: sourcemaps', function (t) { t.plan(10) const src = path.join(__dirname, 'fixture.js') const json = path.join(__dirname, 'fixture.json') const orig = fs.readFileSync(src, 'utf8') Promise.resolve(uglify.minify(orig, { sourceMap: { url: 'out.js.map' } })).then(function (min) { const map = convert.fromJSON(min.map) map.setProperty('sources', [src]) map.setProperty('sourcesContent', [orig]) const mapped = [orig, map.toComment()].join('\n') from2(mapped) .pipe(uglifyify(json, { uglify })) .pipe(bl(doneWithMap)) from2(orig) .pipe(uglifyify(json, { uglify })) .pipe(bl(doneWithoutMap)) browserify({ entries: [src], debug: true }) .transform(uglifyify, { uglify }) .bundle() .pipe(bl(doneWithMap)) browserify({ entries: [src], debug: false }) .transform(uglifyify, { uglify }) .bundle() .pipe(bl(doneWithoutDebug)) from2(mapped) .pipe(uglifyify(json, { _flags: { debug: false }, uglify })) .pipe(bl(doneWithMapAndNoDebug)) function doneWithMap (err, data) { if (err) return t.ifError(err) data = String(data) t.notEqual(data, orig, 'should have changed') t.equal(data.match(/\/\/[@#]/g).length, 1, 'should have sourcemap') } function doneWithoutMap (err, data) { if (err) return t.ifError(err) data = String(data) t.equal(data, orig, 'should not have changed') t.equal(data.indexOf(/\/\/[@#]/g), -1, 'should not have sourcemap') } function doneWithoutDebug (err, data) { if (err) return t.ifError(err) data = String(data) t.notEqual(data, orig, 'should have changed') t.equal(data.indexOf(/\/\/[@#]/g), -1, 'should not have sourcemap') } function doneWithMapAndNoDebug (err, data) { if (err) return t.ifError(err) data = String(data) t.notEqual(data, orig, 'should have changed') t.equal(data.match(/\/\/[@#]/g).length, 1, 'should have sourcemap') } }, function (err) { t.ifError(err) }) }) test('uglifyify: transform is stable', function (t) { t.plan(1) const src = path.join(__dirname, 'fixture.js') const opts = { uglify, _flags: { debug: false } } const tr1 = fs.createReadStream(src).pipe(uglifyify(src, opts)) const tr2 = fs.createReadStream(src).pipe(uglifyify(src, opts)) tr1.pipe(bl(function (err, data) { if (err) return t.ifError(err) const data1 = String(data) tr2.pipe(bl(function (err, data) { if (err) return t.ifError(err) const data2 = String(data) t.equal(data2, data1, 'repeated runs should be the same') t.end() })) })) })