Files
2025-07-24 17:21:45 +08:00

160 lines
4.4 KiB
JavaScript

/*
* grunt-contrib-uglify
* https://gruntjs.com/
*
* Copyright (c) 2017 "Cowboy" Ben Alman, contributors
* Licensed under the MIT license.
*/
'use strict';
// External libs.
var path = require('path');
var UglifyJS = require('uglify-js');
var uriPath = require('uri-path');
var domprops = require('uglify-js/tools/domprops');
// Converts \r\n to \n
function normalizeLf(string) {
return string.replace(/\r\n/g, '\n');
}
function toCache(cache, key) {
if (cache[key]) {
cache[key].props = UglifyJS.Dictionary.fromObject(cache[key].props);
} else {
cache[key] = {
cname: -1,
props: new UglifyJS.Dictionary()
};
}
return cache[key];
}
exports.init = function(grunt) {
var exports = {};
// Minify with UglifyJS.
// From https://github.com/mishoo/UglifyJS2
exports.minify = function(files, dest, options) {
options = options || {};
grunt.verbose.write('Minifying with UglifyJS...');
var totalCode = '';
var minifyOptions = {
compress: options.compress,
ie8: options.ie8,
keep_fnames: options.keep_fnames,
mangle: options.mangle,
output: options.output || {},
parse: options.parse || {},
sourceMap: options.sourceMap,
toplevel: options.toplevel,
wrap: options.wrap
};
if (options.banner) {
minifyOptions.output.preamble = normalizeLf(options.banner);
}
if (options.beautify) {
minifyOptions.output.beautify = true;
for (var key in options.beautify) {
minifyOptions.output[key] = options.beautify[key];
}
}
var cache;
if (options.nameCache) {
try {
cache = JSON.parse(grunt.file.read(options.nameCache));
} catch (ex) {
cache = {};
}
}
if (minifyOptions.mangle) {
if (typeof minifyOptions.mangle !== 'object') {
minifyOptions.mangle = {};
}
if (cache) {
minifyOptions.mangle.cache = toCache(cache, 'vars');
}
if (!Array.isArray(minifyOptions.mangle.reserved)) {
minifyOptions.mangle.reserved = [];
}
if (minifyOptions.mangle.properties) {
if (typeof minifyOptions.mangle.properties !== 'object') {
minifyOptions.mangle.properties = {};
}
if (cache) {
minifyOptions.mangle.properties.cache = toCache(cache, 'props');
}
if (!Array.isArray(minifyOptions.mangle.properties.reserved)) {
minifyOptions.mangle.properties.reserved = [];
}
if (options.reserveDOMProperties) {
domprops.forEach(function(name) {
UglifyJS.push_uniq(minifyOptions.mangle.properties.reserved, name);
});
}
}
if (options.exceptionsFiles) {
options.exceptionsFiles.forEach(function(file) {
try {
var obj = JSON.parse(grunt.file.read(file));
if (minifyOptions.mangle && obj.vars) {
obj.vars.forEach(function(name) {
UglifyJS.push_uniq(minifyOptions.mangle.reserved, name);
});
}
if (minifyOptions.mangle.properties && obj.props) {
obj.props.forEach(function(name) {
UglifyJS.push_uniq(minifyOptions.mangle.properties.reserved, name);
});
}
} catch (ex) {
grunt.warn(ex);
}
});
}
}
var result = UglifyJS.minify(files.reduce(function(o, file) {
var code = grunt.file.read(file);
totalCode += code;
// The src file name must be relative to the source map for things to work
var basename = path.basename(file);
var fileDir = path.dirname(file);
var sourceMapDir = path.dirname(options.generatedSourceMapName);
var relativePath = path.relative(sourceMapDir, fileDir);
var pathPrefix = relativePath ? relativePath + path.sep : '';
// Convert paths to use forward slashes for sourcemap use in the browser
o[uriPath(pathPrefix + basename)] = code;
return o;
}, {}), minifyOptions);
if (result.error) {
throw result.error;
}
if (options.nameCache) {
grunt.file.write(options.nameCache, JSON.stringify(cache, function(key, value) {
return value instanceof UglifyJS.Dictionary ? value.toObject() : value;
}));
}
grunt.verbose.ok();
return {
max: totalCode,
min: result.code,
sourceMap: result.map
};
};
return exports;
};