<?php
-// @codingStandardsIgnoreFile File external to MediaWiki. Ignore coding conventions checks.
+// phpcs:ignoreFile -- File external to MediaWiki. Ignore coding conventions checks.
/**
* JavaScript Minifier
*
*/
class JavaScriptMinifier {
- /* Class constants */
/* Parsing states.
* The state machine is only necessary to decide whether to parse a slash as division
* operator or as regexp literal.
// Sanity limit to avoid excessive memory usage
const STACK_LIMIT = 1000;
- /* Static functions */
-
/**
* Returns minified JavaScript code.
*
* or when required to guard against semicolon insertion.
*
* @param string $s JavaScript code to minify
- * @param bool $statementsOnOwnLine Whether to put each statement on its own line
* @param int $maxLineLength Maximum length of a single line, or -1 for no maximum.
* @return String Minified code
*/
- public static function minify( $s, $statementsOnOwnLine = false, $maxLineLength = 1000 ) {
+ public static function minify( $s, $maxLineLength = 1000 ) {
// First we declare a few tables that contain our parsing rules
// $opChars : characters, which can be combined without whitespace in between them
)
);
- // Rules for when newlines should be inserted if
- // $statementsOnOwnLine is enabled.
- // $newlineBefore is checked before switching state,
- // $newlineAfter is checked after
- $newlineBefore = array(
- self::STATEMENT => array(
- self::TYPE_BRACE_CLOSE => true,
- ),
- );
- $newlineAfter = array(
- self::STATEMENT => array(
- self::TYPE_BRACE_OPEN => true,
- self::TYPE_PAREN_CLOSE => true,
- self::TYPE_SEMICOLON => true,
- ),
- );
-
// $divStates : Contains all states that can be followed by a division operator
$divStates = array(
self::EXPRESSION_OP => true,
// We have to distinguish between regexp literals and division operators
// A division operator is only possible in certain states
} elseif( $ch === '/' && !isset( $divStates[$state] ) ) {
- // Regexp literal, search to the end, skipping over backslash escapes and
- // character classes
+ // Regexp literal
for( ; ; ) {
do{
+ // Skip until we find "/" (end of regexp), "\" (backslash escapes),
+ // or "[" (start of character classes).
$end += strcspn( $s, '/[\\', $end ) + 2;
+ // If backslash escape, keep searching...
} while( $end - 2 < $length && $s[$end - 2] === '\\' );
$end--;
+ // If the end, stop here.
if( $end - 1 >= $length || $s[$end - 1] === '/' ) {
break;
}
+ // (Implicit else), we must've found the start of a char class,
+ // skip until we find "]" (end of char class), or "\" (backslash escape)
do{
$end += strcspn( $s, ']\\', $end ) + 2;
+ // If backslash escape, keep searching...
} while( $end - 2 < $length && $s[$end - 2] === '\\' );
$end--;
};
$pos = $end;
$newlineFound = false;
- // Output a newline after the token if required
- // This is checked before AND after switching state
- $newlineAdded = false;
- if ( $statementsOnOwnLine && !$newlineAdded && isset( $newlineBefore[$state][$type] ) ) {
- $out .= "\n";
- $lineLength = 0;
- $newlineAdded = true;
- }
-
// Now that we have output our token, transition into the new state.
if( isset( $push[$state][$type] ) && count( $stack ) < self::STACK_LIMIT ) {
$stack[] = $push[$state][$type];
} elseif( isset( $goto[$state][$type] ) ) {
$state = $goto[$state][$type];
}
-
- // Check for newline insertion again
- if ( $statementsOnOwnLine && !$newlineAdded && isset( $newlineAfter[$state][$type] ) ) {
- $out .= "\n";
- $lineLength = 0;
- }
}
return $out;
}