Public Member Functions | Data Fields

JSMin Class Reference

Main JSMin application class. More...

Public Member Functions

 isAlphaNum ($c)
 Indicates whether a character is alphanumeric or _, $, \ or non-ASCII.
 get ()
 Get the next character from the input stream.
 peek ()
 Get the next character from the input stream, without gettng it.
 put ($c)
 Adds a char to the output steram / string.
 next ()
 Get the next character from the input stream, excluding comments.
 action ($action)
 Do something !
 minify ()
 Run the JSMin application : minify some JS code.
 JSMin ($inFileName= '-', $outFileName= '-', $comments=NULL)
 Prepare a new JSMin application.
 JSMin_File ($inFileName= '-', $outFileName= '-', $comments=NULL)
 JSMin_String ($inString, $comments=NULL)

Data Fields

 $in
 $out
 $theA
 $theB
 $inLength = 0
 variables used for string-based parsing
 $inPos = 0
 $isString = false

Detailed Description

Main JSMin application class.

Example of use :

$jsMin = new JSMin(...input..., ...output...); $jsMin->minify();

Do not specify input and/or output (or default to '-') to use stdin and/or stdout.

Definition at line 175 of file JSMin_lib.php.


Member Function Documentation

JSMin::action ( action  ) 

Do something !

The action to perform is determined by the argument :

JSMin::ACT_FULL : Output A. Copy B to A. Get the next B. JSMin::ACT_BUF : Copy B to A. Get the next B. (Delete A). JSMin::ACT_IMM : Get the next B. (Delete B).

A string is treated as a single character. Also, regular expressions are recognized if preceded by '(', ',' or '='.

Parameters:
int $action The action to perform : one of the JSMin::ACT_* constants.

Definition at line 418 of file JSMin_lib.php.

References next(), and put().

Referenced by minify().

                             {

        // Choice of possible actions
        // Note the frequent fallthroughs : the actions are decrementally "long"

        switch ($action) {

            case JSMIN_ACT_FULL :

                // Write A to output, then fall through

                $this->put($this->theA);

            case JSMIN_ACT_BUF : // N.B. possible fallthrough from above

                // Copy B to A

                $tmpA = $this->theA = $this->theB;

                // Treating a string as a single char : outputting it whole
                // Note that the string-opening char (" or ') is memorized in B

                if ($tmpA == '\'' || $tmpA == '"') {

                    while (true) {

                        // Output string contents

                        $this->put($tmpA);

                        // Get next character, watching out for termination of the current string,
                        // new line & co (then the string is not terminated !), or a backslash
                        // (upon which the following char is directly output to serve the escape mechanism)

                        $tmpA = $this->theA = $this->get();

                        if ($tmpA == $this->theB) {

                            // String terminated

                            break; // from while(true)
                        }

                        // else

                        if (ord($tmpA) <= ORD_NL) {

                            // Whoopsie

                            //throw new UnterminatedStringLiteralJSMinException();
                            trigger_error('UnterminatedStringLiteral', E_USER_ERROR);
                        }

                        // else

                        if ($tmpA == '\\') {

                            // Escape next char immediately

                            $this->put($tmpA);
                            $tmpA = $this->theA = $this->get();
                        }
                    }
                }

            case JSMIN_ACT_IMM : // N.B. possible fallthrough from above

                // Get the next B

                $this->theB = $this->next();

                // Special case of recognising regular expressions (beginning with /) that are
                // preceded by '(', ',' or '='

                $tmpA = $this->theA;

                if ($this->theB == '/' && ($tmpA == '(' || $tmpA == ',' || $tmpA == '=')) {

                    // Output the two successive chars

                    $this->put($tmpA);
                    $this->put($this->theB);

                    // Look for the end of the RE literal, watching out for escaped chars or a control /
                    // end of line char (the RE literal then being unterminated !)

                    while (true) {

                        $tmpA = $this->theA = $this->get();

                        if ($tmpA == '/') {

                            // RE literal terminated

                            break; // from while(true)
                        }

                        // else

                        if ($tmpA == '\\') {

                            // Escape next char immediately

                            $this->put($tmpA);
                            $tmpA = $this->theA = $this->get();
                        }
                        else if (ord($tmpA) <= ORD_NL) {

                            // Whoopsie

                            //throw new UnterminatedRegExpLiteralJSMinException();
                            trigger_error('UnterminatedRegExpLiteral', E_USER_ERROR);
                        }

                        // Output RE characters

                        $this->put($tmpA);
                    }

                    // Move forward after the RE literal

                    $this->theB = $this->next();
                }

            break;
            default :
                                //throw new JSMinException('Expected a JSMin::ACT_* constant in action().');
                                trigger_error('Expected a JSMin::ACT_* constant in action()', E_USER_ERROR);
        }
    }

Here is the call graph for this function:

Here is the caller graph for this function:

JSMin::get (  ) 

Get the next character from the input stream.

If said character is a control character, translate it to a space or linefeed.

Returns:
string The next character from the specified input stream.
See also:
$in
peek()

Definition at line 240 of file JSMin_lib.php.

                   {

        // Get next input character and advance position in file

                if ($this->isString) {
                        if ($this->inPos < $this->inLength) {
                                $c = $this->in[$this->inPos];
                                ++$this->inPos;
                        }
                        else {
                                return EOF;
                        }
                }
                else
                $c = $this->in->fgetc();

        // Test for non-problematic characters

        if ($c === "\n" || $c === EOF || ord($c) >= ORD_space) {
            return $c;
        }

        // else
        // Make linefeeds into newlines

        if ($c === "\r") {
            return "\n";
        }

        // else
        // Consider space

        return ' ';
    }

JSMin::isAlphaNum ( c  ) 

Indicates whether a character is alphanumeric or _, $, \ or non-ASCII.

Parameters:
string $c The single character to test.
Returns:
boolean Whether the char is a letter, digit, underscore, dollar, backslash, or non-ASCII.

Definition at line 214 of file JSMin_lib.php.

Referenced by minify().

                            {

        // Get ASCII value of character for C-like comparisons

        $a = ord($c);

        // Compare using defined character ordinals, or between PHP strings
        // Note : === is micro-faster than == when types are known to be the same

        return
            ($a >= ORD_a && $a <= ORD_z) ||
            ($a >= ORD_0 && $a <= ORD_9) ||
            ($a >= ORD_cA && $a <= ORD_cZ) ||
            $c === '_' || $c === '$' || $c === '\\' || $a > 126
        ;
    }

Here is the caller graph for this function:

JSMin::JSMin ( inFileName = '-',
outFileName = '-',
comments = NULL 
)

Prepare a new JSMin application.

The next step is to minify() the input into the output.

Parameters:
string $inFileName The pathname of the input (unminified JS) file. STDIN if '-' or absent.
string $outFileName The pathname of the output (minified JS) file. STDOUT if '-' or absent. If outFileName === FALSE, we assume that inFileName is in fact the string to be minified!!!
array $comments Optional lines to present as comments at the beginning of the output.

Definition at line 682 of file JSMin_lib.php.

References JSMin_File(), and JSMin_String().

                                                                                {
                if ($outFileName === FALSE) {
                        $this->JSMin_String($inFileName, $comments);
                }
                else {
                        $this->JSMin_File($inFileName, $outFileName, $comments);
                }
        }

Here is the call graph for this function:

JSMin::JSMin_File ( inFileName = '-',
outFileName = '-',
comments = NULL 
)

Definition at line 691 of file JSMin_lib.php.

Referenced by JSMin().

                                                                                 {

        // Recuperate input and output streams.
        // Use STDIN and STDOUT by default, if they are defined (CLI mode) and no file names are provided

            if ($inFileName == '-')  $inFileName  = 'php://stdin';
            if ($outFileName == '-') $outFileName = 'php://stdout';

            /*try {

                $this->in = new SplFileObject($inFileName, 'rb', TRUE);
            }
            catch (Exception $e) {

                throw new FileOpenFailedJSMinException(
                    'Failed to open "'.$inFileName.'" for reading only.'
                );
            }

            try {

                $this->out = new SplFileObject($outFileName, 'wb', TRUE);
            }
            catch (Exception $e) {

                throw new FileOpenFailedJSMinException(
                    'Failed to open "'.$outFileName.'" for writing only.'
                );
            }
                        */
                        $this->in = fopen($inFileName, 'rb');
                        if (!$this->in) {
                                trigger_error('Failed to open "'.$inFileName, E_USER_ERROR);
                        }
                        $this->out = fopen($outFileName, 'wb');
                        if (!$this->out) {
                                trigger_error('Failed to open "'.$outFileName, E_USER_ERROR);
                        }

            // Present possible initial comments

            if ($comments !== NULL) {
                foreach ($comments as $comm) {
                    $this->out->fwrite('// '.str_replace("\n", " ", $comm)."\n");
                }
            }

    }

Here is the caller graph for this function:

JSMin::JSMin_String ( inString,
comments = NULL 
)

Definition at line 740 of file JSMin_lib.php.

Referenced by JSMin().

                                                       {
        $this->in = $inString;
        $this->out = '';
                $this->inLength = strlen($inString);
                $this->inPos = 0;
                $this->isString = true;

        if ($comments !== NULL) {
            foreach ($comments as $comm) {
                $this->out .= '// '.str_replace("\n", " ", $comm)."\n";
            }
        }
        }

Here is the caller graph for this function:

JSMin::minify (  ) 

Run the JSMin application : minify some JS code.

The code is read from the input stream, and its minified version is written to the output one. In case input is a string, minified vesrions is also returned by this function as string. That is : characters which are insignificant to JavaScript are removed, as well as comments ; tabs are replaced with spaces ; carriage returns are replaced with linefeeds, and finally most spaces and linefeeds are deleted.

Note : name was changed from jsmin() because PHP identifiers are case-insensitive, and it is already the name of this class.

See also:
JSMin()
Returns:
null | string

Definition at line 564 of file JSMin_lib.php.

References action(), and isAlphaNum().

                      {

        // Initialize A and run the first (minimal) action

        $this->theA = "\n";
        $this->action(JSMIN_ACT_IMM);

        // Proceed all the way to the end of the input file

        while ($this->theA !== EOF) {

            switch ($this->theA) {

                case ' ' :

                    if (JSMin::isAlphaNum($this->theB)) {
                        $this->action(JSMIN_ACT_FULL);
                    }
                    else {
                        $this->action(JSMIN_ACT_BUF);
                    }

                break;
                case "\n" :

                    switch ($this->theB) {

                        case '{' : case '[' : case '(' :
                        case '+' : case '-' :

                            $this->action(JSMIN_ACT_FULL);

                        break;
                        case ' ' :

                            $this->action(JSMIN_ACT_IMM);

                        break;
                        default :

                            if (JSMin::isAlphaNum($this->theB)) {
                                $this->action(JSMIN_ACT_FULL);
                            }
                            else {
                                $this->action(JSMIN_ACT_BUF);
                            }

                        break;
                    }

                break;
                default :

                    switch ($this->theB) {

                        case ' ' :

                            if (JSMin::isAlphaNum($this->theA)) {

                                $this->action(JSMIN_ACT_FULL);
                                break;
                            }

                            // else

                            $this->action(JSMIN_ACT_IMM);

                        break;
                        case "\n" :

                            switch ($this->theA) {

                                case '}' : case ']' : case ')' : case '+' :
                                case '-' : case '"' : case '\'' :

                                    $this->action(JSMIN_ACT_FULL);

                                break;
                                default :

                                    if (JSMin::isAlphaNum($this->theA)) {
                                        $this->action(JSMIN_ACT_FULL);
                                    }
                                    else {
                                        $this->action(JSMIN_ACT_IMM);
                                    }

                                break;
                            }

                        break;
                        default :

                            $this->action(JSMIN_ACT_FULL);

                        break;
                    }

                break;
            }
        }

            if ($this->isString) {
                    return $this->out;

            }
    }

Here is the call graph for this function:

JSMin::next (  ) 

Get the next character from the input stream, excluding comments.

peek() is used to see if a '/' is followed by a '*' or '/'. Multiline comments are actually returned as a single space.

Returns:
string The next character from the specified input stream, skipping comments.
See also:
$in

Definition at line 331 of file JSMin_lib.php.

References peek().

Referenced by action().

                    {

        // Get next char from input, translated if necessary

        $c = $this->get();

        // Check comment possibility

        if ($c == '/') {

            // Look ahead : a comment is two slashes or slashes followed by asterisk (to be closed)

            switch ($this->peek()) {

                case '/' :

                    // Comment is up to the end of the line
                    // TOTEST : simple $this->in->fgets()

                    while (true) {

                        $c = $this->get();

                        if (ord($c) <= ORD_NL) {
                            return $c;
                        }
                    }

                case '*' :

                    // Comment is up to comment close.
                    // Might not be terminated, if we hit the end of file.

                    while (true) {

                        // N.B. not using switch() because of having to test EOF with ===

                        $c = $this->get();

                        if ($c == '*') {

                            // Comment termination if the char ahead is a slash

                            if ($this->peek() == '/') {

                                // Advance again and make into a single space

                                $this->get();
                                return ' ';
                            }
                        }
                        else if ($c === EOF) {

                            // Whoopsie

                            //throw new UnterminatedCommentJSMinException();
                            trigger_error('UnterminatedComment', E_USER_ERROR);
                        }
                    }

                default :

                    // Not a comment after all

                    return $c;
            }
        }

        // No risk of a comment

        return $c;
    }

Here is the call graph for this function:

Here is the caller graph for this function:

JSMin::peek (  ) 

Get the next character from the input stream, without gettng it.

Returns:
string The next character from the specified input stream, without advancing the position in the underlying file.
See also:
$in
get()

Definition at line 283 of file JSMin_lib.php.

Referenced by next().

                    {

                if ($this->isString) {
                        if ($this->inPos < $this->inLength) {
                                $c = $this->in[$this->inPos];
                        }
                        else {
                                return EOF;
                        }
                }
                else {
                // Get next input character

                $c = $this->in->fgetc();

                // Regress position in file

                $this->in->fseek(-1, SEEK_CUR);

                // Return character obtained
            }

        return $c;
    }

Here is the caller graph for this function:

JSMin::put ( c  ) 

Adds a char to the output steram / string.

See also:
$out

Definition at line 312 of file JSMin_lib.php.

Referenced by action().

        {
                if ($this->isString) {
                        $this->out .= $c;
                }
                else {
                        $this->out->fwrite($c);
                }
        }

Here is the caller graph for this function:


Field Documentation

JSMin::$in

Definition at line 182 of file JSMin_lib.php.

JSMin::$inLength = 0

variables used for string-based parsing

Definition at line 204 of file JSMin_lib.php.

JSMin::$inPos = 0

Definition at line 205 of file JSMin_lib.php.

JSMin::$isString = false

Definition at line 206 of file JSMin_lib.php.

JSMin::$out

Definition at line 189 of file JSMin_lib.php.

JSMin::$theA

Definition at line 195 of file JSMin_lib.php.

JSMin::$theB

Definition at line 201 of file JSMin_lib.php.


The documentation for this class was generated from the following file: