Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
parent
79795a6baa
commit
677dee5d13
342
js/com/minify.js
Normal file
342
js/com/minify.js
Normal file
|
@ -0,0 +1,342 @@
|
|||
/**
|
||||
** ==============================
|
||||
** O O O OOOO
|
||||
** O O O O O O
|
||||
** O O O O O O
|
||||
** OOOO OOOO O OOO OOOO
|
||||
** O O O O O O O
|
||||
** O O O O O O O
|
||||
** OOOO OOOO O O OOOO
|
||||
** ==============================
|
||||
** Dr. Stefan Bosse http://www.bsslab.de
|
||||
**
|
||||
** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED
|
||||
** BY THE AUTHOR(S).
|
||||
** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
|
||||
** MODIFIED, OR OTHERWISE USED IN A CONTEXT
|
||||
** OUTSIDE OF THE SOFTWARE SYSTEM.
|
||||
**
|
||||
** $AUTHORS: Stefan Bosse, Douglas Crockford (jsmin, C, 2002)
|
||||
** $INITIAL: (C) 2006-2020 bLAB
|
||||
** $CREATED: 09-06-20 by sbosse.
|
||||
** $RCS: $Id: minify.js,v 1.4 2020/02/03 09:45:01 sbosse Exp sbosse $
|
||||
** $VERSION: 1.1.1
|
||||
**
|
||||
** $INFO:
|
||||
**
|
||||
** Fast JavaScript Code Minifier (C-to-JS port)
|
||||
**
|
||||
** $ENDOFINFO
|
||||
*/
|
||||
|
||||
var EOF = null;
|
||||
var theA;
|
||||
var theB;
|
||||
var theLookahead = EOF;
|
||||
var theX = EOF;
|
||||
var theY = EOF;
|
||||
var theInbuf = null;
|
||||
var theOutbuf = null;
|
||||
var theInbufIndex = 0;
|
||||
var theOutbufIndex = 0;
|
||||
|
||||
/* isAlphanum -- return true if the character is a letter, digit, underscore,
|
||||
dollar sign, or non-ASCII character.
|
||||
*/
|
||||
function isAlphanum(c)
|
||||
{
|
||||
return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' ||
|
||||
c > String.fromCharCode(126));
|
||||
}
|
||||
|
||||
function get() {
|
||||
var c = theLookahead;
|
||||
theLookahead = EOF;
|
||||
if (c == EOF) {
|
||||
c = theInbuf[theInbufIndex++];
|
||||
}
|
||||
if (c >= ' ' || c == '\n' || c == EOF) {
|
||||
return c;
|
||||
}
|
||||
if (c == '\r') {
|
||||
return '\n';
|
||||
}
|
||||
return ' ';
|
||||
}
|
||||
|
||||
function put(c) {
|
||||
theOutbuf += c;
|
||||
}
|
||||
|
||||
function peek()
|
||||
{
|
||||
theLookahead = get();
|
||||
return theLookahead;
|
||||
}
|
||||
|
||||
function error(msg) { throw msg }
|
||||
|
||||
function next()
|
||||
{
|
||||
var c = get();
|
||||
if (c == '/') {
|
||||
switch (peek()) {
|
||||
case '/':
|
||||
for (;;) {
|
||||
c = get();
|
||||
if (c <= '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
get();
|
||||
while (c != ' ') {
|
||||
switch (get()) {
|
||||
case '*':
|
||||
if (peek() == '/') {
|
||||
get();
|
||||
c = ' ';
|
||||
}
|
||||
break;
|
||||
case EOF:
|
||||
error("Unterminated comment.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
theY = theX;
|
||||
theX = c;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* action -- do something! What you do is determined by the argument:
|
||||
1 Output A. Copy B to A. Get the next B.
|
||||
2 Copy B to A. Get the next B. (Delete A).
|
||||
3 Get the next B. (Delete B).
|
||||
action treats a string as a single character. Wow!
|
||||
action recognizes a regular expression if it is preceded by ( or , or =.
|
||||
*/
|
||||
|
||||
function action(d)
|
||||
{
|
||||
switch (d) {
|
||||
case 1:
|
||||
put(theA);
|
||||
if (
|
||||
(theY == '\n' || theY == ' ') &&
|
||||
(theA == '+' || theA == '-' || theA == '*' || theA == '/') &&
|
||||
(theB == '+' || theB == '-' || theB == '*' || theB == '/')
|
||||
) {
|
||||
put(theY);
|
||||
}
|
||||
case 2:
|
||||
theA = theB;
|
||||
if (theA == '\'' || theA == '"' || theA == '`') {
|
||||
for (;;) {
|
||||
put(theA);
|
||||
theA = get();
|
||||
if (theA == theB) {
|
||||
break;
|
||||
}
|
||||
if (theA == '\\') {
|
||||
put(theA);
|
||||
theA = get();
|
||||
}
|
||||
if (theA == EOF) {
|
||||
error("Unterminated string literal.");
|
||||
}
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
theB = next();
|
||||
if (theB == '/' && (
|
||||
theA == '(' || theA == ',' || theA == '=' || theA == ':' ||
|
||||
theA == '[' || theA == '!' || theA == '&' || theA == '|' ||
|
||||
theA == '?' || theA == '+' || theA == '-' || theA == '~' ||
|
||||
theA == '*' || theA == '/' || theA == '{' || theA == '\n'
|
||||
)) {
|
||||
put(theA);
|
||||
if (theA == '/' || theA == '*') {
|
||||
put(' ');
|
||||
}
|
||||
put(theB);
|
||||
for (;;) {
|
||||
theA = get();
|
||||
if (theA == '[') {
|
||||
for (;;) {
|
||||
put(theA);
|
||||
theA = get();
|
||||
if (theA == ']') {
|
||||
break;
|
||||
}
|
||||
if (theA == '\\') {
|
||||
put(theA);
|
||||
theA = get();
|
||||
}
|
||||
if (theA == EOF) {
|
||||
error("Unterminated set in Regular Expression literal.");
|
||||
}
|
||||
}
|
||||
} else if (theA == '/') {
|
||||
switch (peek()) {
|
||||
case '/':
|
||||
case '*':
|
||||
error("Unterminated set in Regular Expression literal.");
|
||||
break;
|
||||
case '\n':
|
||||
put(theA);
|
||||
theA='\n'; /* Newline required after end of regex */
|
||||
}
|
||||
break;
|
||||
} else if (theA =='\\') {
|
||||
put(theA);
|
||||
theA = get();
|
||||
}
|
||||
if (theA == EOF) {
|
||||
error("Unterminated Regular Expression literal.");
|
||||
}
|
||||
put(theA);
|
||||
}
|
||||
theB = next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function minify(text) {
|
||||
theA=0;
|
||||
theB=0;
|
||||
theLookahead = EOF;
|
||||
theX = EOF;
|
||||
theY = EOF;
|
||||
theInbuf=text;
|
||||
theInbufIndex=0;
|
||||
theOutbuf='';
|
||||
if (peek() == 0xEF) {
|
||||
get();
|
||||
get();
|
||||
get();
|
||||
}
|
||||
theA = get();
|
||||
action(3);
|
||||
while (theA != EOF) {
|
||||
switch (theA) {
|
||||
case ' ':
|
||||
action(isAlphanum(theB) ? 1 : 2);
|
||||
break;
|
||||
case '\n':
|
||||
switch (theB) {
|
||||
case '{':
|
||||
case '[':
|
||||
case '(':
|
||||
case '+':
|
||||
case '-':
|
||||
case '!':
|
||||
case '~':
|
||||
action(1);
|
||||
break;
|
||||
case ' ':
|
||||
action(3);
|
||||
break;
|
||||
default:
|
||||
action(isAlphanum(theB) ? 1 : 2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (theB) {
|
||||
case ' ':
|
||||
action(isAlphanum(theA) ? 1 : 3);
|
||||
break;
|
||||
case '\n':
|
||||
switch (theA) {
|
||||
case '}':
|
||||
case ']':
|
||||
case ')':
|
||||
case '+':
|
||||
case '-':
|
||||
case '"':
|
||||
case '\'':
|
||||
case '`':
|
||||
action(1);
|
||||
break;
|
||||
default:
|
||||
action(isAlphanum(theA) ? 1 : 3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
action(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return theOutbuf;
|
||||
}
|
||||
|
||||
// old faulty regex minimizer from Code module!!
|
||||
function minimize0 (code) {
|
||||
// Inline and multi-line comments
|
||||
var regex4= /\/\*([\S\s]*?)\*\//g;
|
||||
var regex5= /([^\\}])\\n/g;
|
||||
var regex6= /\/\/[^\n]+/g;
|
||||
// Newline after {},;
|
||||
var regex7= /[ ]*([{},; ]|else)[ ]*\n[\n]*/g;
|
||||
// Filter for string quotes
|
||||
var regex8= /([^\'"]+)|([\'"](?:[^\'"\\]|\\.)+[\'"])/g;
|
||||
// Multi-spaces reduction
|
||||
var regex9= / [ ]+/g;
|
||||
// relax } <identifier> syntax errors after newline removal; exclude keywords!
|
||||
var regex10= /}\s+(?!else|finally|catch)([a-zA-Z_]+)/g;
|
||||
// relax ) <identifier> syntax errors after newline removal
|
||||
var regex11= /\)\s+([a-zA-Z_]+)/g;
|
||||
|
||||
code=code.replace(regex4,"")
|
||||
.replace(regex5,'$1\n')
|
||||
.replace(regex5,'$1\n')
|
||||
.replace(regex6,"")
|
||||
.replace(regex7,"$1")
|
||||
.replace(regex8, function($0, $1, $2) {
|
||||
if ($1) {
|
||||
return $1.replace(regex9,' ').replace(regex10,'};$1').replace(regex11,')\n$1');
|
||||
} else {
|
||||
return $2;
|
||||
}
|
||||
});
|
||||
return code;
|
||||
}
|
||||
|
||||
// compare regex minimizer versa character state machine
|
||||
function test() {
|
||||
var n=1E4;
|
||||
var text=minify.toString();
|
||||
var t0=Date.now()
|
||||
for(var i=0;i<n;i++) {
|
||||
minify(text);
|
||||
}
|
||||
var t1=Date.now();
|
||||
console.log('minify: '+((t1-t0)/n/text.length*1000)+' us/char');
|
||||
var t0=Date.now()
|
||||
for(var i=0;i<n;i++) {
|
||||
minimize0(text);
|
||||
}
|
||||
var t1=Date.now();
|
||||
console.log('minimize0: '+((t1-t0)/n/text.length*1000)+' us/char');
|
||||
try {
|
||||
var M = process.binding('minify');
|
||||
var t0=Date.now()
|
||||
for(var i=0;i<n;i++) {
|
||||
M.minify(text);
|
||||
}
|
||||
var t1=Date.now();
|
||||
console.log('minifyC: '+((t1-t0)/n/text.length*1000)+' us/char');
|
||||
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
minify.test=test;
|
||||
|
||||
module.exports = minify;
|
||||
|
Loading…
Reference in New Issue
Block a user