PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/upload/libraries/jsmin.class.php

https://github.com/sahilbabu/phpb2b
PHP | 946 lines | 532 code | 155 blank | 259 comment | 57 complexity | b65e4c79531df00141ee25d404426ddd MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * JSMin_lib.php (for PHP 4, 5)
  4. *
  5. * PHP adaptation of JSMin, published by Douglas Crockford as jsmin.c, also based
  6. * on its Java translation by John Reilly.
  7. *
  8. * Permission is hereby granted to use the PHP version under the same conditions
  9. * as jsmin.c, which has the following notice :
  10. *
  11. * ----------------------------------------------------------------------------
  12. *
  13. * Copyright (c) 2002 Douglas Crockford (www.crockford.com)
  14. *
  15. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  16. * this software and associated documentation files (the "Software"), to deal in
  17. * the Software without restriction, including without limitation the rights to
  18. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  19. * of the Software, and to permit persons to whom the Software is furnished to do
  20. * so, subject to the following conditions:
  21. *
  22. * The above copyright notice and this permission notice shall be included in all
  23. * copies or substantial portions of the Software.
  24. *
  25. * The Software shall be used for Good, not Evil.
  26. *
  27. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  28. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  30. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  31. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  32. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  33. * SOFTWARE.
  34. *
  35. * ----------------------------------------------------------------------------
  36. *
  37. * @copyright No new copyright ; please keep above and following information.
  38. * @author David Holmes <dholmes@cfdsoftware.net> of CFD Labs, France
  39. * @author Gaetano Giunta
  40. *
  41. * Please note, this is a brutal and simple conversion : it could undoubtedly be
  42. * improved, as a PHP implementation, by applying more PHP-specific programming
  43. * features.
  44. *
  45. * Exceptions and all PHP 5 - only features ahve been removed for compat with PHP 4
  46. *
  47. * Note : whereas jsmin.c works specifically with the standard input and output
  48. * streams, this implementation only falls back on them if file pathnames are
  49. * not provided to the JSMin() constructor.
  50. *
  51. * Examples comparing with the application compiled from jsmin.c :
  52. *
  53. * jsmin < orig.js > mini.js JSMin.php orig.js mini.js
  54. * JSMin.php orig.js > mini.js
  55. * JSMin.php - mini.js < orig.js
  56. * jsmin < orig.js JSMin.php orig.js
  57. * JSMin.php orig.js -
  58. * jsmin > mini.js JSMin.php - mini.js
  59. * JSMin.php > mini.js
  60. * jsmin comm1 comm2 < a.js > b.js JSMin.php a.js b.js comm1 comm2
  61. * JSMin.php a.js b.js -c comm1 comm2
  62. * JSMin.php a.js --comm comm1 comm2 > b.js
  63. * JSMin.php -c comm1 comm2 < a.js > b.js
  64. * (etc...)
  65. *
  66. * See JSMin.php -h (or --help) for command-line documentation.
  67. *
  68. * NEW AND IMPROVED in version 0.2:
  69. * to take advantage of this file in your own code, you can do the following:
  70. *
  71. * define('JSMIN_AS_LIB', true); // prevents auto-run on include
  72. * include('jsmin.php');
  73. * // the JSMin class now works on php strings, too
  74. * $jsMin = new JSMin(file_get_contents('e:/htdocs/awstats_misc_tracker.js'), false);
  75. * // in that case, the modifies string is returned by minify():
  76. * $out = $jsMin->minify();
  77. *
  78. */
  79. /**
  80. * Version of this PHP translation.
  81. */
  82. define('JSMIN_VERSION', '0.2');
  83. /**
  84. * How fgetc() reports an End Of File.
  85. * N.B. : use === and not == to test the result of fgetc() ! (see manual)
  86. */
  87. define('EOF', FALSE);
  88. /**
  89. * Some ASCII character ordinals.
  90. * N.B. : PHP identifiers are case-insensitive !
  91. */
  92. define('ORD_NL', ord("\n"));
  93. define('ORD_space', ord(' '));
  94. define('ORD_cA', ord('A'));
  95. define('ORD_cZ', ord('Z'));
  96. define('ORD_a', ord('a'));
  97. define('ORD_z', ord('z'));
  98. define('ORD_0', ord('0'));
  99. define('ORD_9', ord('9'));
  100. /**
  101. * Generic exception class related to JSMin.
  102. */
  103. /*
  104. class JSMinException extends Exception {
  105. }
  106. */
  107. class JSMinException {
  108. }
  109. /**
  110. * A JSMin exception indicating that a file provided for input or output could not be properly opened.
  111. */
  112. class FileOpenFailedJSMinException extends JSMinException {
  113. }
  114. /**
  115. * A JSMin exception indicating that an unterminated comment was encountered in input.
  116. */
  117. class UnterminatedCommentJSMinException extends JSMinException {
  118. }
  119. /**
  120. * A JSMin exception indicatig that an unterminated string literal was encountered in input.
  121. */
  122. class UnterminatedStringLiteralJSMinException extends JSMinException {
  123. }
  124. /**
  125. * A JSMin exception indicatig that an unterminated regular expression lieteral was encountered in input.
  126. */
  127. class UnterminatedRegExpLiteralJSMinException extends JSMinException {
  128. }
  129. /**
  130. * Constant describing an {@link action()} : Output A. Copy B to A. Get the next B.
  131. */
  132. define ('JSMIN_ACT_FULL', 1);
  133. /**
  134. * Constant describing an {@link action()} : Copy B to A. Get the next B. (Delete A).
  135. */
  136. define ('JSMIN_ACT_BUF', 2);
  137. /**
  138. * Constant describing an {@link action()} : Get the next B. (Delete B).
  139. */
  140. define ('JSMIN_ACT_IMM', 3);
  141. /**
  142. * Main JSMin application class.
  143. *
  144. * Example of use :
  145. *
  146. * $jsMin = new JSMin(...input..., ...output...);
  147. * $jsMin->minify();
  148. *
  149. * Do not specify input and/or output (or default to '-') to use stdin and/or stdout.
  150. */
  151. class JSMin {
  152. /**
  153. * The input stream, from which to read a JS file to minimize. Obtained by fopen().
  154. * NB: might be a string instead of a stream
  155. * @var SplFileObject | string
  156. */
  157. var $in;
  158. /**
  159. * The output stream, in which to write the minimized JS file. Obtained by fopen().
  160. * NB: might be a string instead of a stream
  161. * @var SplFileObject | string
  162. */
  163. var $out;
  164. /**
  165. * Temporary I/O character (A).
  166. * @var string
  167. */
  168. var $theA;
  169. /**
  170. * Temporary I/O character (B).
  171. * @var string
  172. */
  173. var $theB;
  174. /** variables used for string-based parsing **/
  175. var $inLength = 0;
  176. var $inPos = 0;
  177. var $isString = false;
  178. /**
  179. * Indicates whether a character is alphanumeric or _, $, \ or non-ASCII.
  180. *
  181. * @param string $c The single character to test.
  182. * @return boolean Whether the char is a letter, digit, underscore, dollar, backslash, or non-ASCII.
  183. */
  184. function isAlphaNum($c) {
  185. // Get ASCII value of character for C-like comparisons
  186. $a = ord($c);
  187. // Compare using defined character ordinals, or between PHP strings
  188. // Note : === is micro-faster than == when types are known to be the same
  189. return
  190. ($a >= ORD_a && $a <= ORD_z) ||
  191. ($a >= ORD_0 && $a <= ORD_9) ||
  192. ($a >= ORD_cA && $a <= ORD_cZ) ||
  193. $c === '_' || $c === '$' || $c === '\\' || $a > 126
  194. ;
  195. }
  196. /**
  197. * Get the next character from the input stream.
  198. *
  199. * If said character is a control character, translate it to a space or linefeed.
  200. *
  201. * @return string The next character from the specified input stream.
  202. * @see $in
  203. * @see peek()
  204. */
  205. function get() {
  206. // Get next input character and advance position in file
  207. if ($this->isString) {
  208. if ($this->inPos < $this->inLength) {
  209. $c = $this->in[$this->inPos];
  210. ++$this->inPos;
  211. }
  212. else {
  213. return EOF;
  214. }
  215. }
  216. else
  217. // $c = $this->in->fgetc();
  218. $c = fgetc($this->in);
  219. // Test for non-problematic characters
  220. if ($c === "\n" || $c === EOF || ord($c) >= ORD_space) {
  221. return $c;
  222. }
  223. // else
  224. // Make linefeeds into newlines
  225. if ($c === "\r") {
  226. return "\n";
  227. }
  228. // else
  229. // Consider space
  230. return ' ';
  231. }
  232. /**
  233. * Get the next character from the input stream, without gettng it.
  234. *
  235. * @return string The next character from the specified input stream, without advancing the position
  236. * in the underlying file.
  237. * @see $in
  238. * @see get()
  239. */
  240. function peek() {
  241. if ($this->isString) {
  242. if ($this->inPos < $this->inLength) {
  243. $c = $this->in[$this->inPos];
  244. }
  245. else {
  246. return EOF;
  247. }
  248. }
  249. else {
  250. // Get next input character
  251. // $c = $this->in->fgetc();
  252. $c = fgetc($this->in);
  253. // Regress position in file
  254. // $this->in->fseek(-1, SEEK_CUR);
  255. fseek($this->in,-1, SEEK_CUR);
  256. // Return character obtained
  257. }
  258. return $c;
  259. }
  260. /**
  261. * Adds a char to the output steram / string
  262. * @see $out
  263. */
  264. function put($c)
  265. {
  266. if ($this->isString) {
  267. $this->out .= $c;
  268. }
  269. else {
  270. // echo "<P>".get_resource_type($this->out)."<P>";
  271. // $this->out->fwrite($c);
  272. fwrite($this->out,$c);
  273. }
  274. }
  275. /**
  276. * Get the next character from the input stream, excluding comments.
  277. *
  278. * {@link peek()} is used to see if a '/' is followed by a '*' or '/'.
  279. * Multiline comments are actually returned as a single space.
  280. *
  281. * @return string The next character from the specified input stream, skipping comments.
  282. * @see $in
  283. */
  284. function next() {
  285. // Get next char from input, translated if necessary
  286. $c = $this->get();
  287. // Check comment possibility
  288. if ($c == '/') {
  289. // Look ahead : a comment is two slashes or slashes followed by asterisk (to be closed)
  290. switch ($this->peek()) {
  291. case '/' :
  292. // Comment is up to the end of the line
  293. // TOTEST : simple $this->in->fgets()
  294. while (true) {
  295. $c = $this->get();
  296. if (ord($c) <= ORD_NL) {
  297. return $c;
  298. }
  299. }
  300. case '*' :
  301. // Comment is up to comment close.
  302. // Might not be terminated, if we hit the end of file.
  303. while (true) {
  304. // N.B. not using switch() because of having to test EOF with ===
  305. $c = $this->get();
  306. if ($c == '*') {
  307. // Comment termination if the char ahead is a slash
  308. if ($this->peek() == '/') {
  309. // Advance again and make into a single space
  310. $this->get();
  311. return ' ';
  312. }
  313. }
  314. else if ($c === EOF) {
  315. // Whoopsie
  316. //throw new UnterminatedCommentJSMinException();
  317. trigger_error('UnterminatedComment', E_USER_ERROR);
  318. }
  319. }
  320. default :
  321. // Not a comment after all
  322. return $c;
  323. }
  324. }
  325. // No risk of a comment
  326. return $c;
  327. }
  328. /**
  329. * Do something !
  330. *
  331. * The action to perform is determined by the argument :
  332. *
  333. * JSMin::ACT_FULL : Output A. Copy B to A. Get the next B.
  334. * JSMin::ACT_BUF : Copy B to A. Get the next B. (Delete A).
  335. * JSMin::ACT_IMM : Get the next B. (Delete B).
  336. *
  337. * A string is treated as a single character. Also, regular expressions are recognized if preceded
  338. * by '(', ',' or '='.
  339. *
  340. * @param int $action The action to perform : one of the JSMin::ACT_* constants.
  341. */
  342. function action($action) {
  343. // Choice of possible actions
  344. // Note the frequent fallthroughs : the actions are decrementally "long"
  345. switch ($action) {
  346. case JSMIN_ACT_FULL :
  347. // Write A to output, then fall through
  348. $this->put($this->theA);
  349. case JSMIN_ACT_BUF : // N.B. possible fallthrough from above
  350. // Copy B to A
  351. $tmpA = $this->theA = $this->theB;
  352. // Treating a string as a single char : outputting it whole
  353. // Note that the string-opening char (" or ') is memorized in B
  354. if ($tmpA == '\'' || $tmpA == '"') {
  355. while (true) {
  356. // Output string contents
  357. $this->put($tmpA);
  358. // Get next character, watching out for termination of the current string,
  359. // new line & co (then the string is not terminated !), or a backslash
  360. // (upon which the following char is directly output to serve the escape mechanism)
  361. $tmpA = $this->theA = $this->get();
  362. if ($tmpA == $this->theB) {
  363. // String terminated
  364. break; // from while(true)
  365. }
  366. // else
  367. if (ord($tmpA) <= ORD_NL) {
  368. // Whoopsie
  369. //throw new UnterminatedStringLiteralJSMinException();
  370. //trigger_error('UnterminatedStringLiteral', E_USER_ERROR);
  371. }
  372. // else
  373. if ($tmpA == '\\') {
  374. // Escape next char immediately
  375. $this->put($tmpA);
  376. $tmpA = $this->theA = $this->get();
  377. }
  378. }
  379. }
  380. case JSMIN_ACT_IMM : // N.B. possible fallthrough from above
  381. // Get the next B
  382. $this->theB = $this->next();
  383. // Special case of recognising regular expressions (beginning with /) that are
  384. // preceded by '(', ',' or '='
  385. $tmpA = $this->theA;
  386. if ($this->theB == '/' && ($tmpA == '(' || $tmpA == ',' || $tmpA == '=')) {
  387. // Output the two successive chars
  388. $this->put($tmpA);
  389. $this->put($this->theB);
  390. // Look for the end of the RE literal, watching out for escaped chars or a control /
  391. // end of line char (the RE literal then being unterminated !)
  392. while (true) {
  393. $tmpA = $this->theA = $this->get();
  394. if ($tmpA == '/') {
  395. // RE literal terminated
  396. break; // from while(true)
  397. }
  398. // else
  399. if ($tmpA == '\\') {
  400. // Escape next char immediately
  401. $this->put($tmpA);
  402. $tmpA = $this->theA = $this->get();
  403. }
  404. else if (ord($tmpA) <= ORD_NL) {
  405. // Whoopsie
  406. //throw new UnterminatedRegExpLiteralJSMinException();
  407. trigger_error('UnterminatedRegExpLiteral', E_USER_ERROR);
  408. }
  409. // Output RE characters
  410. $this->put($tmpA);
  411. }
  412. // Move forward after the RE literal
  413. $this->theB = $this->next();
  414. }
  415. break;
  416. default :
  417. //throw new JSMinException('Expected a JSMin::ACT_* constant in action().');
  418. trigger_error('Expected a JSMin::ACT_* constant in action()', E_USER_ERROR);
  419. }
  420. }
  421. /**
  422. * Run the JSMin application : minify some JS code.
  423. *
  424. * The code is read from the input stream, and its minified version is written to the output one.
  425. * In case input is a string, minified vesrions is also returned by this function as string.
  426. * That is : characters which are insignificant to JavaScript are removed, as well as comments ;
  427. * tabs are replaced with spaces ; carriage returns are replaced with linefeeds, and finally most
  428. * spaces and linefeeds are deleted.
  429. *
  430. * Note : name was changed from jsmin() because PHP identifiers are case-insensitive, and it is already
  431. * the name of this class.
  432. *
  433. * @see JSMin()
  434. * @return null | string
  435. */
  436. function minify() {
  437. // Initialize A and run the first (minimal) action
  438. $this->theA = "\n";
  439. $this->action(JSMIN_ACT_IMM);
  440. // Proceed all the way to the end of the input file
  441. while ($this->theA !== EOF) {
  442. switch ($this->theA) {
  443. case ' ' :
  444. if (JSMin::isAlphaNum($this->theB)) {
  445. $this->action(JSMIN_ACT_FULL);
  446. }
  447. else {
  448. $this->action(JSMIN_ACT_BUF);
  449. }
  450. break;
  451. case "\n" :
  452. switch ($this->theB) {
  453. case '{' : case '[' : case '(' :
  454. case '+' : case '-' :
  455. $this->action(JSMIN_ACT_FULL);
  456. break;
  457. case ' ' :
  458. $this->action(JSMIN_ACT_IMM);
  459. break;
  460. default :
  461. if (JSMin::isAlphaNum($this->theB)) {
  462. $this->action(JSMIN_ACT_FULL);
  463. }
  464. else {
  465. $this->action(JSMIN_ACT_BUF);
  466. }
  467. break;
  468. }
  469. break;
  470. default :
  471. switch ($this->theB) {
  472. case ' ' :
  473. if (JSMin::isAlphaNum($this->theA)) {
  474. $this->action(JSMIN_ACT_FULL);
  475. break;
  476. }
  477. // else
  478. $this->action(JSMIN_ACT_IMM);
  479. break;
  480. case "\n" :
  481. switch ($this->theA) {
  482. case '}' : case ']' : case ')' : case '+' :
  483. case '-' : case '"' : case '\'' :
  484. $this->action(JSMIN_ACT_FULL);
  485. break;
  486. default :
  487. if (JSMin::isAlphaNum($this->theA)) {
  488. $this->action(JSMIN_ACT_FULL);
  489. }
  490. else {
  491. $this->action(JSMIN_ACT_IMM);
  492. }
  493. break;
  494. }
  495. break;
  496. default :
  497. $this->action(JSMIN_ACT_FULL);
  498. break;
  499. }
  500. break;
  501. }
  502. }
  503. if ($this->isString) {
  504. return $this->out;
  505. }
  506. }
  507. /**
  508. * Prepare a new JSMin application.
  509. *
  510. * The next step is to {@link minify()} the input into the output.
  511. *
  512. * @param string $inFileName The pathname of the input (unminified JS) file. STDIN if '-' or absent.
  513. * @param string $outFileName The pathname of the output (minified JS) file. STDOUT if '-' or absent.
  514. * If outFileName === FALSE, we assume that inFileName is in fact the string to be minified!!!
  515. * @param array $comments Optional lines to present as comments at the beginning of the output.
  516. */
  517. function JSMin($inFileName = '-', $outFileName = '-', $comments = NULL) {
  518. // echo"in file is ".$inFileName;
  519. if ($outFileName === FALSE) {
  520. $this->JSMin_String($inFileName, $comments);
  521. }
  522. else {
  523. $this->JSMin_File($inFileName, $outFileName, $comments);
  524. }
  525. }
  526. function JSMin_File($inFileName = '-', $outFileName = '-', $comments = NULL) {
  527. // Recuperate input and output streams.
  528. // Use STDIN and STDOUT by default, if they are defined (CLI mode) and no file names are provided
  529. if ($inFileName == '-') $inFileName = 'php://stdin';
  530. if ($outFileName == '-') $outFileName = 'php://stdout';
  531. /*try {
  532. $this->in = new SplFileObject($inFileName, 'rb', TRUE);
  533. }
  534. catch (Exception $e) {
  535. throw new FileOpenFailedJSMinException(
  536. 'Failed to open "'.$inFileName.'" for reading only.'
  537. );
  538. }
  539. try {
  540. $this->out = new SplFileObject($outFileName, 'wb', TRUE);
  541. }
  542. catch (Exception $e) {
  543. throw new FileOpenFailedJSMinException(
  544. 'Failed to open "'.$outFileName.'" for writing only.'
  545. );
  546. }
  547. */
  548. if(function_exists('sugar_fopen')){
  549. $this->in = sugar_fopen($inFileName, 'rb');
  550. }else{
  551. $this->in = fopen($inFileName, 'rb');
  552. }
  553. if (!$this->in) {
  554. trigger_error('Failed to open "'.$inFileName, E_USER_ERROR);
  555. }
  556. if(function_exists('sugar_fopen')){
  557. $this->out = sugar_fopen($outFileName, 'wb');
  558. }else{
  559. $this->out = fopen($outFileName, 'wb');
  560. }
  561. if (!$this->out) {
  562. trigger_error('Failed to open "'.$outFileName, E_USER_ERROR);
  563. }
  564. // Present possible initial comments
  565. if ($comments !== NULL) {
  566. foreach ($comments as $comm) {
  567. //$this->out->fwrite(str_replace("\n", " ", $comm)."\n");
  568. fwrite($this->out, $comm);
  569. }
  570. }
  571. }
  572. function JSMin_String($inString, $comments = NULL) {
  573. $this->in = $inString;
  574. $this->out = '';
  575. $this->inLength = strlen($inString);
  576. $this->inPos = 0;
  577. $this->isString = true;
  578. if ($comments !== NULL) {
  579. foreach ($comments as $comm) {
  580. $this->out .= '// '.str_replace("\n", " ", $comm)."\n";
  581. }
  582. }
  583. }
  584. }
  585. //
  586. // OTHER FUNCTIONS
  587. //
  588. /**
  589. * Displays inline help for the application.
  590. */
  591. function printHelp() {
  592. // All the inline help
  593. echo "\n";
  594. echo "Usage : JSMin.php [inputFile] [outputFile] [[-c] comm1 comm2 ...]\n";
  595. echo " JSMin.php [-v|-h]\n";
  596. echo "\n";
  597. echo "Minify JavaScript code using JSMin, the JavaScript Minifier.\n";
  598. echo "\n";
  599. echo "JSMin is a filter which removes comments and unnecessary whitespace\n";
  600. echo "from a script read in the inputFile (stdin by default), as well as\n";
  601. echo "omitting or modifying some characters, before writing the results to\n";
  602. echo "the outputFile (stdout by default).\n";
  603. echo "It does not change the behaviour of the program that is minifies.\n";
  604. echo "The result may be harder to debug. It will definitely be harder to\n";
  605. echo "read. It typically reduces filesize by half, resulting in faster\n";
  606. echo "downloads. It also encourages a more expressive programming style\n";
  607. echo "because it eliminates the download cost of clean, literate self-\n";
  608. echo "documentation.\n";
  609. echo "\n";
  610. echo "The '-' character can be used to explicitely specify a standard\n";
  611. echo "stream for input or output.\n";
  612. echo "\n";
  613. echo "With the optional -c (--comm) option, all following parameters will\n";
  614. echo "be listed at the beginning of the output as comments. This is a\n";
  615. echo "convenient way of replacing copyright messages and other info. The\n";
  616. echo "option is unnecessary if an input and output file are specified :\n";
  617. echo "following parameters will then automatically be treated thus.\n";
  618. echo "\n";
  619. echo "Options :\n";
  620. echo "\n";
  621. echo " -c, --comm Present following parameters as initial comments.\n";
  622. echo " -h, --help Display this information.\n";
  623. echo " -v, --version Display short version information.\n";
  624. echo "\n";
  625. echo "The JavaScript Minifier is copyright (c) 2002 by Douglas Crockford\n";
  626. echo "and available online at http://javascript.crockford.com/jsmin.html.\n";
  627. echo "This PHP translation is by David Holmes of CFD Labs, France, 2006.\n";
  628. echo "\n";
  629. }
  630. /**
  631. * Displays version information for the application.
  632. */
  633. function printVersion() {
  634. // Minimum info
  635. echo "JSMin, the JavaScript Minifier, copyright (c) 2002 by Douglas Crockford.\n";
  636. echo "PHP translation version ".JSMIN_VERSION." by David Holmes, CFD Labs.\n";
  637. }
  638. //
  639. // ENTRY POINT
  640. //
  641. // Allow user to include this file without having it run atomatically, ie. as if it was a lib
  642. if (!defined('JSMIN_AS_LIB')) {
  643. define('EXIT_SUCCESS', 0);
  644. define('EXIT_FAILURE', 1);
  645. // Examine command-line parameters
  646. // First shift off the first parameter, the executable's name
  647. if (!isset($argv)) {
  648. die("Please run this utility from a command line, or set php.ini setting 'register_argc_argv' to true.\nTo use this file in your own code, define 'JSMIN_AS_LIB' before inclusion.");
  649. }
  650. array_shift($argv);
  651. $inFileName = NULL;
  652. $outFileName = NULL;
  653. $haveCommentParams = FALSE;
  654. $comments = array();
  655. foreach ($argv as $arg) {
  656. // Bypass the rest if we are now considering initial comments
  657. if ($haveCommentParams) {
  658. $comments[] = $arg;
  659. continue;
  660. }
  661. // else
  662. // Look for an option (length > 1 because of '-' for indicating stdin or
  663. // stdout)
  664. if ($arg[0] == '-' && strlen($arg) > 1) {
  665. switch ($arg) {
  666. case '-c' : case '--comm' :
  667. // Following parameters will be initial comments
  668. $haveCommentParams = TRUE;
  669. break;
  670. case '-h' : case '--help' :
  671. // Display inline help and exit normally
  672. printHelp();
  673. exit(EXIT_SUCCESS);
  674. case '-v' : case '--version' :
  675. // Display short version information and exit normally
  676. printVersion();
  677. exit(EXIT_SUCCESS);
  678. default :
  679. // Reject any other (unknown) option
  680. echo "\n";
  681. echo "ERROR : unknown option \"$arg\", sorry.\n";
  682. printHelp();
  683. exit(EXIT_FAILURE);
  684. }
  685. continue;
  686. }
  687. // else
  688. // At this point, parameter is neither to be considered as an initial
  689. // comment, nor is it an option. It is an input or output file.
  690. if ($inFileName === NULL) {
  691. // No input file yet, this is it
  692. $inFileName = $arg;
  693. }
  694. else if ($outFileName === NULL) {
  695. // An input file but no output file yet, this is it
  696. $outFileName = $arg;
  697. }
  698. else {
  699. // Already have input and output file, this is a first initial comment
  700. $haveCommentParams = TRUE;
  701. $comments[] = $arg;
  702. }
  703. }
  704. if ($inFileName === NULL) $inFileName = '-';
  705. if ($outFileName === NULL) $outFileName = '-';
  706. // Prepare and run the JSMin application
  707. // If pathnames are not provided or '-', standard input/output streams are used
  708. $jsMin = new JSMin($inFileName, $outFileName, $comments);
  709. $jsMin->minify();
  710. }
  711. ?>