html-minifier-terser
Advanced tools
Comparing version 7.0.0-alpha.0 to 7.0.0-alpha.1
16
cli.js
@@ -28,13 +28,13 @@ #!/usr/bin/env node | ||
'use strict'; | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
import { createRequire } from 'module'; | ||
import { camelCase } from 'camel-case'; | ||
import { paramCase } from 'param-case'; | ||
import { Command } from 'commander'; | ||
import { minify } from './src/htmlminifier.js'; | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const require = createRequire(import.meta.url); | ||
const { camelCase } = require('camel-case'); | ||
const { paramCase } = require('param-case'); | ||
const { Command } = require('commander'); | ||
const pkg = require('./package.json'); | ||
const minify = require('./' + pkg.main).minify; | ||
@@ -41,0 +41,0 @@ const program = new Command(); |
{ | ||
"name": "html-minifier-terser", | ||
"description": "Highly configurable, well-tested, JavaScript-based HTML minifier.", | ||
"version": "7.0.0-alpha.0", | ||
"version": "7.0.0-alpha.1", | ||
"license": "MIT", | ||
@@ -44,13 +44,11 @@ "repository": "https://github.com/terser/html-minifier-terser.git", | ||
"engines": { | ||
"node": ">=12" | ||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0" | ||
}, | ||
"bin": { | ||
"html-minifier-terser": "./cli.js" | ||
}, | ||
"main": "./src/htmlminifier.js", | ||
"module": "./dist/htmlminifier.js", | ||
"type": "module", | ||
"main": "./dist/htmlminifier.cjs", | ||
"module": "./src/htmlminifier.js", | ||
"exports": { | ||
".": { | ||
"require": "./src/htmlminifier.js", | ||
"imports": "./dist/htmlminifier.js" | ||
"require": "./dist/htmlminifier.cjs", | ||
"import": "./src/htmlminifier.js" | ||
}, | ||
@@ -60,2 +58,5 @@ "./dist/*": "./dist/*.js", | ||
}, | ||
"bin": { | ||
"html-minifier-terser": "./cli.js" | ||
}, | ||
"files": [ | ||
@@ -68,5 +69,5 @@ "dist/", | ||
"build": "rollup -c", | ||
"test:node": "jest --verbose", | ||
"test:web": "jest --verbose --environment=jsdom", | ||
"test:watch": "jest verbose --watch", | ||
"test:node": "NODE_OPTIONS=--experimental-vm-modules jest --verbose", | ||
"test:web": "NODE_OPTIONS=--experimental-vm-modules jest --verbose --environment=jsdom", | ||
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest verbose --watch", | ||
"test": "npm run test:node", | ||
@@ -89,8 +90,8 @@ "serve": "vite", | ||
"@commitlint/cli": "^15.0.0", | ||
"@jest/globals": "^27.4.2", | ||
"@jest/globals": "^27.4.4", | ||
"@rollup/plugin-commonjs": "^21.0.1", | ||
"@rollup/plugin-json": "^4.1.0", | ||
"@rollup/plugin-node-resolve": "^13.0.6", | ||
"@rollup/plugin-node-resolve": "^13.1.1", | ||
"alpinejs": "^3.7.0", | ||
"commitlint-config-non-conventional": "^1.0.0", | ||
"commitlint-config-non-conventional": "^1.0.1", | ||
"eslint": "^7.32.0", | ||
@@ -103,8 +104,8 @@ "eslint-config-standard": "^16.0.3", | ||
"is-ci": "^3.0.1", | ||
"jest": "^27.4.3", | ||
"jest": "^27.4.4", | ||
"lint-staged": "^12.1.2", | ||
"rollup": "^2.60.2", | ||
"rollup": "^2.61.1", | ||
"rollup-plugin-polyfill-node": "^0.8.0", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"vite": "^2.6.14" | ||
"vite": "^2.7.2" | ||
}, | ||
@@ -111,0 +112,0 @@ "benchmarkDependencies": { |
@@ -8,4 +8,41 @@ # HTMLMinifier | ||
See [corresponding blog post](http://perfectionkills.com/experimenting-with-html-minifier/) for all the gory details of [how it works](http://perfectionkills.com/experimenting-with-html-minifier/#how_it_works), [description of each option](http://perfectionkills.com/experimenting-with-html-minifier/#options), [testing results](http://perfectionkills.com/experimenting-with-html-minifier/#field_testing) and [conclusions](http://perfectionkills.com/experimenting-with-html-minifier/#cost_and_benefits). | ||
## Installation | ||
From NPM for use as a command line app: | ||
```shell | ||
npm install html-minifier-terser -g | ||
``` | ||
From NPM for programmatic use: | ||
```shell | ||
npm install html-minifier-terser | ||
``` | ||
## Usage | ||
**Note** that almost all options are disabled by default. Experiment and find what works best for you and your project. | ||
For command line usage please see `html-minifier-terser --help` for a list of available options. | ||
**Sample command line:** | ||
```bash | ||
html-minifier-terser --collapse-whitespace --remove-comments --minify-js true | ||
``` | ||
### Node.js | ||
```js | ||
const { minify } = require('html-minifier-terser'); | ||
const result = await minify('<p title="blah" id="moo">foo</p>', { | ||
removeAttributeQuotes: true, | ||
}); | ||
result; // '<p title=blah id=moo>foo</p>' | ||
``` | ||
See [corresponding blog post](http://perfectionkills.com/experimenting-with-html-minifier) for all the gory details of [how it works](http://perfectionkills.com/experimenting-with-html-minifier#how_it_works), [description of each option](http://perfectionkills.com/experimenting-with-html-minifier#options), [testing results](http://perfectionkills.com/experimenting-with-html-minifier#field_testing) and [conclusions](http://perfectionkills.com/experimenting-with-html-minifier#cost_and_benefits). | ||
Also see corresponding [Ruby wrapper](https://github.com/stereobooster/html_minifier), and for Node.js, [Grunt plugin](https://github.com/gruntjs/grunt-contrib-htmlmin), [Gulp module](https://github.com/jonschlinkert/gulp-htmlmin), [Koa middleware wrapper](https://github.com/koajs/html-minifier) and [Express middleware wrapper](https://github.com/melonmanchan/express-minify-html). | ||
@@ -114,45 +151,2 @@ | ||
## Installation Instructions | ||
From NPM for use as a command line app: | ||
```shell | ||
npm install html-minifier-terser -g | ||
``` | ||
From NPM for programmatic use: | ||
```shell | ||
npm install html-minifier-terser | ||
``` | ||
From Git: | ||
```shell | ||
git clone git://github.com/terser/html-minifier-terser.git | ||
cd html-minifier-terser | ||
npm link . | ||
``` | ||
## Usage | ||
Note that almost all options are disabled by default. For command line usage please see `html-minifier-terser --help` for a list of available options. Experiment and find what works best for you and your project. | ||
**Sample command line:** | ||
```bash | ||
html-minifier-terser --collapse-whitespace --remove-comments --remove-optional-tags --remove-redundant-attributes --remove-script-type-attributes --remove-tag-whitespace --use-short-doctype --minify-css true --minify-js true | ||
``` | ||
### Node.js | ||
```js | ||
const { minify } = require('html-minifier-terser'); | ||
const result = await minify('<p title="blah" id="moo">foo</p>', { | ||
removeAttributeQuotes: true | ||
}); | ||
result; // '<p title=blah id=moo>foo</p>' | ||
``` | ||
## Running benchmarks | ||
@@ -159,0 +153,0 @@ |
@@ -1,12 +0,10 @@ | ||
'use strict'; | ||
import CleanCSS from 'clean-css'; | ||
import { decodeHTMLStrict, decodeHTML } from 'entities'; | ||
import RelateURL from 'relateurl'; | ||
import { minify as terser } from 'terser'; | ||
const CleanCSS = require('clean-css'); | ||
const { decodeHTMLStrict, decodeHTML } = require('entities'); | ||
const RelateUrl = require('relateurl'); | ||
const Terser = require('terser'); | ||
import { HTMLParser, endTag } from './htmlparser.js'; | ||
import TokenChain from './tokenchain.js'; | ||
import { createMapFromString, createMap, replaceAsync } from './utils.js'; | ||
const { HTMLParser, endTag } = require('./htmlparser'); | ||
const TokenChain = require('./tokenchain'); | ||
const utils = require('./utils'); | ||
function trimWhitespace(str) { | ||
@@ -66,3 +64,2 @@ return str && str.replace(/^[ \n\r\t\f]+/, '').replace(/[ \n\r\t\f]+$/, ''); | ||
const createMapFromString = utils.createMapFromString; | ||
// non-empty tags that will maintain whitespace around them | ||
@@ -159,3 +156,3 @@ const inlineTags = createMapFromString('a,abbr,acronym,b,bdi,bdo,big,button,cite,code,del,dfn,em,font,i,ins,kbd,label,mark,math,nobr,object,q,rp,rt,rtc,ruby,s,samp,select,small,span,strike,strong,sub,sup,svg,textarea,time,tt,u,var'); | ||
// https://developer.mozilla.org/en/docs/Web/HTML/Element/script#attr-type | ||
const executableScriptsMimetypes = utils.createMap([ | ||
const executableScriptsMimetypes = createMap([ | ||
'text/javascript', | ||
@@ -170,3 +167,3 @@ 'text/ecmascript', | ||
const keepScriptsMimetypes = utils.createMap([ | ||
const keepScriptsMimetypes = createMap([ | ||
'module' | ||
@@ -387,4 +384,4 @@ ]); | ||
return options.processConditionalComments | ||
? await utils.replaceAsync(comment, /^(\[if\s[^\]]+]>)([\s\S]*?)(<!\[endif])$/, async function (match, prefix, text, suffix) { | ||
return prefix + await minify(text, options, true) + suffix; | ||
? await replaceAsync(comment, /^(\[if\s[^\]]+]>)([\s\S]*?)(<!\[endif])$/, async function (match, prefix, text, suffix) { | ||
return prefix + await minifyHTML(text, options, true) + suffix; | ||
}) | ||
@@ -398,3 +395,3 @@ : comment; | ||
options.processScripts.indexOf(currentAttrs[i].value) > -1) { | ||
return await minify(text, options); | ||
return await minifyHTML(text, options); | ||
} | ||
@@ -704,3 +701,3 @@ } | ||
try { | ||
const result = await Terser.minify(code, value); | ||
const result = await terser(code, value); | ||
return result.code.replace(/;$/, ''); | ||
@@ -723,3 +720,3 @@ } catch (error) { | ||
try { | ||
return RelateUrl.relate(text, value); | ||
return RelateURL.relate(text, value); | ||
} catch (err) { | ||
@@ -803,3 +800,3 @@ options.log(err); | ||
options.sortClassName = false; | ||
await scan(await minify(value, options)); | ||
await scan(await minifyHTML(value, options)); | ||
options.log = log; | ||
@@ -833,3 +830,3 @@ if (attrChains) { | ||
async function minify(value, options, partialMarkup) { | ||
async function minifyHTML(value, options, partialMarkup) { | ||
if (options.collapseWhitespace) { | ||
@@ -1339,8 +1336,10 @@ value = collapseWhitespace(value, options, true, true); | ||
exports.minify = async function (value, options) { | ||
export const minify = async function (value, options) { | ||
const start = Date.now(); | ||
options = processOptions(options || {}); | ||
const result = await minify(value, options); | ||
const result = await minifyHTML(value, options); | ||
options.log('minified in: ' + (Date.now() - start) + 'ms'); | ||
return result; | ||
}; | ||
export default { minify }; |
@@ -31,6 +31,4 @@ /*! | ||
'use strict'; | ||
import { createMapFromString, replaceAsync } from './utils.js'; | ||
const { createMapFromString, replaceAsync } = require('./utils'); | ||
function makeMap(values) { | ||
@@ -63,3 +61,3 @@ return createMapFromString(values, true); | ||
const startTagClose = /^\s*(\/?)>/; | ||
const endTag = new RegExp('^<\\/' + qnameCapture + '[^>]*>'); | ||
export const endTag = new RegExp('^<\\/' + qnameCapture + '[^>]*>'); | ||
const doctype = /^<!DOCTYPE\s?[^>]+>/i; | ||
@@ -121,3 +119,3 @@ | ||
class HTMLParser { | ||
export class HTMLParser { | ||
constructor(html, handler) { | ||
@@ -438,4 +436,3 @@ this.html = html; | ||
exports.HTMLParser = HTMLParser; | ||
exports.HTMLtoXML = function (html) { | ||
export const HTMLtoXML = (html) => { | ||
let results = ''; | ||
@@ -472,3 +469,3 @@ | ||
exports.HTMLtoDOM = function (html, doc) { | ||
export const HTMLtoDOM = (html, doc) => { | ||
// There can be only one of these elements | ||
@@ -572,3 +569,1 @@ const one = { | ||
}; | ||
exports.endTag = endTag; |
@@ -1,3 +0,1 @@ | ||
'use strict'; | ||
class Sorter { | ||
@@ -70,2 +68,2 @@ sort(tokens, fromIndex = 0) { | ||
module.exports = TokenChain; | ||
export default TokenChain; |
@@ -1,8 +0,8 @@ | ||
'use strict'; | ||
export function createMap(values, ignoreCase) { | ||
const map = {}; | ||
function createMap(values, ignoreCase) { | ||
const map = {}; | ||
values.forEach(function (value) { | ||
map[value] = 1; | ||
}); | ||
return ignoreCase | ||
@@ -17,4 +17,5 @@ ? function (value) { | ||
async function replaceAsync(str, regex, asyncFn) { | ||
export async function replaceAsync(str, regex, asyncFn) { | ||
const promises = []; | ||
str.replace(regex, (match, ...args) => { | ||
@@ -24,2 +25,3 @@ const promise = asyncFn(match, ...args); | ||
}); | ||
const data = await Promise.all(promises); | ||
@@ -29,7 +31,4 @@ return str.replace(regex, () => data.shift()); | ||
exports.createMap = createMap; | ||
exports.createMapFromString = function (values, ignoreCase) { | ||
export function createMapFromString(values, ignoreCase) { | ||
return createMap(values.split(/,/), ignoreCase); | ||
}; | ||
exports.replaceAsync = replaceAsync; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses eval() which is a dangerous function. This prevents the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
1
5
2
Yes
4953270
12
119159
163