License detector for UglifyJS that identifies and preserves license comments during minification
npx @tessl/cli install tessl/npm-uglify-save-license@0.4.0uglify-save-license is a license detector that identifies and preserves license comments during UglifyJS minification. It analyzes JavaScript comment tokens to intelligently determine which comments contain license information that should be preserved during code compression.
npm install uglify-save-licenseconst saveLicense = require('uglify-save-license');ES modules (if supported by your environment):
import saveLicense from 'uglify-save-license';const UglifyJS = require('uglify-js');
const saveLicense = require('uglify-save-license');
// Use with UglifyJS2
const result = UglifyJS.minify('file.js', {
output: {
comments: saveLicense
}
});
// Use with grunt-contrib-uglify
grunt.initConfig({
uglify: {
my_target: {
options: {
preserveComments: saveLicense
},
src: ['src/app.js'],
dest: 'dest/app.min.js'
}
}
});The main export function that determines whether a comment should be preserved during minification based on license detection heuristics.
/**
* Determines whether a comment should be preserved as a license comment
* @param {Object} node - UglifyJS AST node (currently unused but part of callback signature)
* @param {Object} comment - UglifyJS comment token with the following properties:
* @param {string} comment.file - Name of the file being processed
* @param {string} comment.value - Content of the comment
* @param {string} comment.type - Comment type ('comment1' for //, 'comment2' for /* */)
* @param {number} comment.line - Line number where comment appears
* @returns {boolean} - Returns true if comment should be preserved, false otherwise
*/
function saveLicense(node, comment)The function identifies license comments using these detection criteria:
Pattern Matching: Comments matching the license detection regex /@preserve|@cc_on|\bMIT\b|\bMPL\b|\bGPL\b|\bBSD\b|\bISCL\b|\(c\)|License|Copyright/mi:
@preserve, @cc_onMIT, MPL, GPL, BSD, ISCL(c), Copyright, LicenseSpecial Comment Formats:
! (e.g., /*! ... */)Position-Based Detection:
Note on Stateful Behavior: The function maintains internal state to track the line number of the last preserved comment (prevCommentLine) and the current file being processed (prevFile). This allows it to identify consecutive license comment blocks that should be preserved together, even if only the first comment in the block matches the license patterns.
Usage Examples:
const UglifyJS = require('uglify-js');
const saveLicense = require('uglify-save-license');
// CLI tool example
const minified = UglifyJS.minify(process.argv[2], {
output: {
comments: saveLicense
}
}).code;
console.log(minified);Detection Examples:
Given this input file:
// First line comment - preserved (position-based: line 1)
// (c) 2024 Company Name - preserved (pattern match: contains "(c)")
// This line is also preserved (consecutive: follows preserved comment)
// This comment won't be preserved (no match, not consecutive)
function myFunction() {
/*! Important license notice */ // preserved (special format: starts with !)
return 'Hello World';
}The function will preserve the first three comments and the /*! comment while removing the regular comment. The consecutive behavior ensures that multi-line license headers stay together even if only the first line contains recognizable license patterns.