Page MenuHomeWickedGov Phorge

Cli.php
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None
<?php declare( strict_types=1 );
/**
* Copyright 2021 Timo Tijhof
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @file
* @license Apache-2.0
*/
namespace Wikimedia\Minify;
/**
* Implementation of `minify` CLI.
*
* @internal For use by `bin/minify` only.
*/
final class Cli {
/** @var int $exitCode */
private $exitCode = 0;
/** @var resource $in */
private $in;
/** @var resource $out */
private $out;
/** @var string $self */
private $self;
/** @var string $command */
private $command;
/** @var string[] $params */
private $params;
/**
* @param resource $in An open stream for reading input with `fgets()`
* @param resource $out An open stream for writing output with `fwrite()`
* @param string[] $argv
*/
public function __construct( $in, $out, array $argv ) {
$this->in = $in;
$this->out = $out;
$this->self = basename( $argv[0] ?? '/minify' );
$this->command = $argv[1] ?? '';
$this->params = array_slice( $argv, 2 );
}
/** Perform the specified command. */
public function run(): void {
try {
switch ( $this->command ) {
case 'css':
$this->runCss( ...$this->params );
break;
case 'css-remap':
$this->runCssRemap( ...$this->params );
break;
case 'js':
$this->runJs( ...$this->params );
break;
case 'jsdebug':
$this->runJsDebug( ...$this->params );
break;
case 'jsmap-web':
$this->runJsMapWeb( ...$this->params );
break;
case 'jsmap-raw':
$this->runJsMapRaw( ...$this->params );
break;
case '':
case 'help':
$this->exitCode = 1;
$this->help();
break;
default:
$this->error( 'Unknown command' );
break;
}
} catch ( \Throwable $e ) {
$this->exitCode = 1;
$this->output( (string)$e );
}
}
private function runCss( ?string $file = null ): void {
$data = $file === null ? stream_get_contents( $this->in ) : file_get_contents( $file );
$this->output( CSSMin::minify( $data ) );
}
private function runCssRemap( ?string $file = null ): void {
if ( $file === null ) {
$this->error( 'Remapping requires a filepath' );
return;
}
$fulldir = dirname( realpath( $file ) );
$data = file_get_contents( $file );
$data = CSSMin::remap( $data, $fulldir, $fulldir );
$this->output( CSSMin::minify( $data ) );
}
private function runJs( ?string $file = null ): void {
$data = $file === null ? stream_get_contents( $this->in ) : file_get_contents( $file );
$onError = function ( ParseError $error ) {
$this->output( 'ParseError: ' . $error->getMessage() . ' at position ' . $error->getOffset() );
$this->exitCode = 1;
};
$ret = JavaScriptMinifier::minify( $data, $onError );
if ( !$this->exitCode ) {
$this->output( $ret );
}
}
private function runJsDebug( ?string $file = null ): void {
$data = $file === null ? stream_get_contents( $this->in ) : file_get_contents( $file );
$onError = function ( ParseError $error ) {
$this->output( 'ParseError: ' . $error->getMessage() . ' at position ' . $error->getOffset() );
$this->exitCode = 1;
};
$first = true;
$onDebug = static function ( array $frame ) use ( &$first ) {
if ( $first ) {
print sprintf( "| %-45s | %-4s | %-22s | %-17s | %-16s\n",
'stack', 'last', 'state', 'token', 'type' );
print sprintf( "| %'-45s | %'-4s | %'-22s | %'-17s | %'-16s\n",
'', '', '', '', '' );
$first = false;
}
$stackStrLen = 0;
$stackPieces = [];
$stackOverflow = 0;
foreach ( array_reverse( $frame['stack'] ) as $i => $state ) {
$stackStrLen += strlen( $state ) + 2;
if ( $stackStrLen < 40 ) {
$stackPieces[] = $state;
} else {
$stackOverflow++;
}
}
if ( $stackOverflow ) {
$stackPieces[] = "$stackOverflow ...";
}
$stack = implode( ', ', array_reverse( $stackPieces ) );
print sprintf( "| %-45s | %-4s | %-22s | @%-3s %-12s | %-16s\n",
$stack, $frame['last'], $frame['state'], $frame['pos'], $frame['token'], $frame['type'] );
};
$ret = JavaScriptMinifier::minifyInternal( $data, null, $onError, $onDebug );
if ( !$this->exitCode ) {
$this->output( $ret );
}
}
private function runJsMapWeb( ?string $file = null ): void {
$data = $file === null ? stream_get_contents( $this->in ) : file_get_contents( $file );
$sourceName = $file === null ? 'file.js' : basename( $file );
$mapper = JavaScriptMinifier::createSourceMapState();
$mapper->addSourceFile( $sourceName, $data, true );
$this->output( rtrim( $mapper->getSourceMap(), "\n" ) );
}
private function runJsMapRaw( ?string $file = null ): void {
$data = $file === null ? stream_get_contents( $this->in ) : file_get_contents( $file );
$sourceName = $file === null ? 'file.js' : basename( $file );
$mapper = JavaScriptMinifier::createSourceMapState();
$mapper->addSourceFile( $sourceName, $data, true );
$this->output( rtrim( $mapper->getRawSourceMap(), "\n" ) );
}
private function help(): void {
$this->output( <<<TEXT
usage: {$this->self} <command>
commands:
css [<file>] Minify input data as CSS code, and write to output.
Reads from stdin by default, or can read from a file.
css-remap <file> Remap and process any "@embed" comments in a CSS file,
and write the minified code to output.
js [<file>] Minify input data as JavaScript code, write to output.
Reads from stdin by default, or can read from a file.
jsmap-raw [<file>] Minify JavaScript code and write a raw source map to
output. Such a source map should not be delivered over
HTTP due to XSSI concerns.
jsmap-web [<file>] Minify JavaScript code and write a source map with XSSI
prefix.
TEXT
);
}
private function error( string $text ): void {
$this->exitCode = 1;
$this->output( "\n{$this->self} error: $text\n\n------\n" );
$this->help();
}
private function output( string $text ): void {
fwrite( $this->out, $text . "\n" );
}
/** @return int */
public function getExitCode(): int {
return $this->exitCode;
}
}

File Metadata

Mime Type
text/x-php
Expires
Aug 18 2026, 11:54 (5 w, 14 h ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
40/cc/3d4aafa3c20bc71c01c4d18ca5a5
Default Alt Text
Cli.php (6 KB)

Event Timeline