ホームページ  >  記事  >  バックエンド開発  >  jsファイルを自動的に圧縮するために使用されるPHPコード

jsファイルを自動的に圧縮するために使用されるPHPコード

WBOY
WBOYオリジナル
2016-07-25 09:02:581118ブラウズ
  1. /* 2008 年 4 月 9 日。バージョン 1.1
  2. *
  3. * これは、Dean Edwards JavaScript の Packer の php バージョンです
  4. * ベース:
  5. *
  6. * ParseMaster、バージョン 1.0.2 ( 2005-08-19) Copyright 2005, Dean Edwards
  7. * マルチパターン パーサー。
  8. * 既知のバグ: 置換でescapeCharを使用すると誤った動作
  9. * 関数である値
  10. *
  11. * パッカー、バージョン 2.0.2 (2005-08-19) 著作権 2004-2005、Dean Edwards
  12. *
  13. * ライセンス: http://creativecommons.org/licenses/LGPL/2.1/
  14. *
  15. * Nicolas Martin によって PHP に移植されました。
  16. *
  17. * ---------------------------------------------- ------------------------
  18. * 変更履歴:
  19. * 1.1 : バグを修正。パックされた後にアンパックされた「/0」が「/」になる。
  20. * ------------------------------------------------ ----------------------
  21. *
  22. * 使用例:
  23. * $myPacker = new JavaScriptPacker($script, 62, true, false);
  24. * $packed = $myPacker->pack();
  25. *
  26. * または
  27. *
  28. * $myPacker = new JavaScriptPacker($script, 'Normal', true, false);
  29. * $packed = $myPacker->pack();
  30. *
  31. * または (デフォルト値)
  32. *
  33. * $myPacker = new JavaScriptPacker($script);
  34. * $packed = $myPacker->pack();
  35. *
  36. *
  37. * コンストラクターのパラメータ:
  38. * $script: パックする JavaScript、文字列。
  39. * $encoding: エンコーディングのレベル、int または string :
  40. * 0、10、62、95 または 'None'、'Numeric'、'Normal'、'High ASCII'。
  41. * デフォルト: 62。
  42. * $fastDecode: パックされた結果 (ブール値) に高速デコーダーを含めます。
  43. * デフォルト: true。
  44. * $specialChars: スクリプト内でプライベート変数とローカル変数にフラグが設定されている場合
  45. *、ブール値。
  46. * デフォルト: false。
  47. *
  48. * Pack() メソッドは、圧縮された JavaScript を文字列として返します。
  49. *
  50. * 詳細については、http://dean.edwards.name/packer/usage/ を参照してください。
  51. *
  52. * 注:
  53. * # PHP 5 が必要です。 PHP 5.1.2、5.1.3、5.1.4、5.2.3 でテスト済み
  54. *
  55. * # パックされた結果は Dean Edwards
  56. * バージョンとは異なる場合がありますが、長さは同じです。その理由は、配列をソートするための PHP
  57. * 関数 usort が
  58. * 2 つの等しいメンバーの元の順序を必ずしも保持しないためです。 Javascript の並べ替え関数
  59. * は実際にこの順序を保持します (ただし、これは
  60. * ECMAScript 標準では必須ではありません)。したがって、エンコードされたキーワードの順序は
  61. * 2 つの結果で異なる可能性があります。
  62. *
  63. * # ファイル内で
  64. * UTF-8 を使用する場合は、'High ASCII' レベルのエンコーディングに注意してください...
  65. */
  66. class JavaScriptPacker {
  67. // 定数
  68. const IGNORE = '$1';
  69. // パラメータを検証します
  70. private $_script = '';
  71. プライベート $_encoding = 62;
  72. プライベート $_fastDecode = true;
  73. プライベート $_specialChars = false;
  74. private $LITERAL_ENCODING = array(
  75. 'None' => 0,
  76. 'Numeric' => 10,
  77. 'Normal' => 62,
  78. 'High ASCII' => 95
  79. );
  80. パブリック関数 __construct($_script, $_encoding = 62, $_fastDecode = true, $_specialChars = false)
  81. {
  82. $this->_script = $_script 。 "/n";
  83. if (array_key_exists($_encoding, $this->LITERAL_ENCODING))
  84. $_encoding = $this->LITERAL_ENCODING[$_encoding];
  85. $this->_encoding = min((int)$_encoding, 95);
  86. $this->_fastDecode = $_fastDecode;
  87. $this->_specialChars = $_specialChars;
  88. }
  89. public function Pack() {
  90. $this->_addParser('_basicCompression');
  91. if ($this->_specialChars)
  92. $this->_addParser('_encodeSpecialChars');
  93. if ($this->_encoding)
  94. $this->_addParser('_encodeKeywords');
  95. // 行きます!
  96. return $this->_pack($this->_script);
  97. }
  98. // すべての解析ルーチンを適用します
  99. private function _pack($script) {
  100. for ($i = 0; isset($this->_parsers[$i]); $i++) {
  101. $script = call_user_func (array(&$this,$this->_parsers[$i]), $script);
  102. }
  103. $script を返します。
  104. }
  105. // 解析関数のリストを保持し、それらは一度にすべて実行されます
  106. private $_parsers = array();
  107. プライベート関数 _addParser($parser) {
  108. $this->_parsers[] = $parser;
  109. }
  110. // ゼロエンコーディング - 空白とコメントの削除のみ
  111. private function _basicCompression($script) {
  112. $parser = new ParseMaster();
  113. // 安全にする
  114. $parser->escapeChar = '//';
  115. // 文字列を保護する
  116. $parser->add('//'[^/'//n//r]*/'/', self::IGNORE);
  117. $parser->add('/"[^"//n//r]*"/', self::IGNORE);
  118. // コメントを削除します
  119. $parser->add('//// ///[^//n//r]*[//n//r]/', ' ')
  120. $parser->add('//////*[^*]*/ /*+([^///][^*]*//*+)*////', ' ');
  121. // 正規表現を保護する
  122. $parser->add('///s+ (///[^/////n//r//*][^/////n//r]*///g?i?)/', '$2');無視
  123. $parser->add('/[^//w//x24////'"*)//?:]///[^/////n//r//*] [^/////n//r]*///g?i?/', self::IGNORE);
  124. // 削除: ;;; doSomething();
  125. if ($this->_specialChars) $parser->add('/;;;[^//n//r]+[//n//r]/');
  126. // 冗長なセミコロンを削除します
  127. $parser->add('///(;;//)/', self::IGNORE); // (;;) ループを保護します
  128. $parser->add('/;+//s*([};])/', '$2');
  129. // 上記を適用します
  130. $script = $parser->exec($script);
  131. // 空白を削除します
  132. $parser->add('/(//b|//x24)//s+(//b|//x24)/', '$2 $3');
  133. $parser->add('/([+//-])//s+([+//-])/', '$2 $3');
  134. $parser->add('///s+/', '');
  135. // 完了
  136. return $parser->exec($script);
  137. }
  138. プライベート関数 _encodeSpecialChars($script) {
  139. $parser = new ParseMaster();
  140. // 置換: $name -> n, $$name -> na
  141. $parser->add('/((//x24+)([a-zA-Z$_]+))(//d*)/',
  142. array('fn' => '_replace_name】 ')
  143. );
  144. // 置換: _name -> _0、二重アンダースコア (__name) は無視されます
  145. $regexp = '///b_[A-Za-z//d]//w*/';
  146. // 単語リストを作成します
  147. $keywords = $this->_analyze($script, $regexp, '_encodePrivate');
  148. // 簡単な参照
  149. $encoded = $keywords['encoded'];
  150. $parser->add($regexp,
  151. array(
  152. 'fn' => '_replace_encoded',
  153. 'data' => $encoded
  154. )
  155. );
  156. return $parser->exec($script);
  157. }
  158. private function _encodeKeywords($script) {
  159. // すでにスクリプト内 (つまり文字列内) にある上位 ASCII 値をエスケープします
  160. if ($this->_encoding > 62)
  161. $script = $this-> ;_escape95($script);
  162. // パーサーを作成します
  163. $parser = new ParseMaster();
  164. $encode = $this->_getEncoder($this->_encoding);
  165. // 高 ASCII の場合、単一文字の低 ASCII をエンコードしません
  166. $regexp = ($this->_encoding > 62) ? '///w//w+/' : '///w+/';
  167. // 単語リストを作成します
  168. $keywords = $this->_analyze($script, $regexp, $encode);
  169. $encoded = $keywords['encoded'];
  170. // エンコード
  171. $parser->add($regexp,
  172. array(
  173. 'fn' => '_replace_encoded',
  174. 'data' => $encoded
  175. )
  176. );
  177. if (emptyempty($script)) $script を返します。
  178. else {
  179. //$res = $parser->exec($script);
  180. //$res = $this->_bootStrap($res, $keywords);
  181. // $res を返します;
  182. return $this->_bootStrap($parser->exec($script), $keywords);
  183. }
  184. }
  185. private function _analyze($script, $regexp, $encode) {
  186. // 分析
  187. // スクリプト内のすべての単語を取得します
  188. $all = array();
  189. preg_match_all($regexp, $script, $all);
  190. $_sorted = array(); // 頻度順にソートされた単語のリスト
  191. $_encoded = array(); // 単語の辞書 > エンコーディング
  192. $_protected = array(); // 「保護された」単語のインスタンス
  193. $all = $all[0]; // グローバル一致の JavaScript コンポーネントをシミュレートします
  194. if (!emptyempty($all)) {
  195. $unsorted = array(); // 同じリスト、ソートされていない
  196. $protected = array(); // 「保護された」単語 (単語の辞書->「単語」)
  197. $value = array(); // charCode->エンコーディングの辞書 (例: 256->ff)
  198. $this->_count = array(); // 単語->カウント
  199. $i = count($all); $j = 0; //$word = null;
  200. // 出現回数をカウントします - 後で並べ替えるために使用されます
  201. do {
  202. --$i;
  203. $word = '$' 。 $all[$i];
  204. if (!isset($this->_count[$word])) {
  205. $this->_count[$word] = 0;
  206. $unsorted[$j] = $word;
  207. // このスクリプト内のすべての保護された単語の辞書を作成します
  208. // これらはエンコードと間違われる可能性のある単語です
  209. //if (is_string($encode) && Method_exists($this, $encode))
  210. $values [$j] = call_user_func(array(&$this, $encode), $j);
  211. $protected['$' . $values[$j]] = $j++;
  212. }
  213. // 単語カウンターをインクリメントします
  214. $this->_count[$word]++;
  215. } while ($i > 0);
  216. // 単語リストを並べ替える準備をします。まず、コードとしても使用される単語を保護する必要があります。
  217. // 単語。単語自体に相当するコード
  218. // を割り当てます。
  219. // 例: "do" がエンコード範囲内にある場合
  220. // キーワードを格納します["do"] = "do";
  221. // これにより、デコード時の問題が回避されます
  222. $i = count($unsorted);
  223. do {
  224. $word = $unsorted[--$i];
  225. if (isset($protected[$word]) /*!= null*/) {
  226. $_sorted[$protected[$word]] = substr($word, 1);
  227. $_protected[$protected[$word]] = true;
  228. $this->_count[$word] = 0;
  229. }
  230. } while ($i);
  231. // 単語を頻度で並べ替えます
  232. // 注: javascript と php のバージョンの sort は異なる場合があります :
  233. // php マニュアルでは、usort :
  234. // " 2 つのメンバーが等しいと比較した場合、
  235. // それらの順序ソートされた配列内の値は未定義です。」
  236. // したがって、最終的にパックされたスクリプトは学部長の JavaScript バージョンとは異なります
  237. // しかし同等です。
  238. // ECMAscript 標準はこの動作を保証しません。
  239. // したがって、すべてのブラウザ (例:
  240. // 少なくとも 2003 年まで遡る Mozilla バージョン) がこれを尊重するわけではありません。
  241. usort($unsorted, array(&$this, '_sortWords'));
  242. $j = 0;
  243. // リストに「保護された」単語があるため
  244. // 並べ替えられた単語をその周囲に追加する必要があります
  245. do {
  246. if (!isset($_sorted[$i]))
  247. $_sorted[$i] = substr ($unsorted[$j++], 1);
  248. $_encoded[$_sorted[$i]] = $values[$i];
  249. } while (++$i }
  250. return array(
  251. 'sorted' => $_sorted,
  252. 'encoded' => $_encoded,
  253. 'protected' => $_protected);
  254. }
  255. プライベート $_count = array();
  256. プライベート関数 _sortWords($match1, $match2) {
  257. return $this->_count[$match2] - $this->_count[$match1];
  258. }
  259. // ロードとデコードに使用されるブート関数を構築します
  260. private function _bootStrap($packed, $keywords) {
  261. $ENCODE = $this->_safeRegExp('$encode//($count//)');
  262. // $packed: パックされたスクリプト
  263. $packed = "'" 。 $this->_escape($packed) 。 "";
  264. // $ascii: エンコードのベース
  265. $ascii = min(count($keywords['sorted']), $this->_encoding);
  266. if ($ascii == 0) $ascii = 1;
  267. // $count: スクリプトに含まれる単語の数
  268. $count = count($keywords['sorted']);
  269. // $keywords: スクリプトに含まれる単語のリスト
  270. foreach ($keywords['protected'] as $i=>$value) {
  271. $keywords['sorted'][$i] = '';
  272. }
  273. // 文字列から配列に変換します
  274. ksort($keywords['sorted']);
  275. $keywords = "'" 。 implode('|',$keywords['sorted']) 。 "'.split('|')";
  276. $encode = ($this->_encoding > 62) ? '_encode95' : $this->_getEncoder($ascii);
  277. $encode = $this->_getJSFunction($encode);
  278. $encode = preg_replace('/_encoding/','$ascii', $encode);
  279. $encode = preg_replace('/arguments//.callee/','$encode', $encode);
  280. $inline = '//$count' 。 ($ascii > 10 ? '.toString(//$ascii)' : '');
  281. // $decode: デコードを高速化するコード スニペット
  282. if ($this->_fastDecode) {
  283. // デコーダーを作成します
  284. $decode = $this->_getJSFunction('_decodeBody');
  285. if ($this->_encoding > 62)
  286. $decode = preg_replace('/////w/', '[//xa1-//xff]', $decode);
  287. // 下位 ASCII 値のエンコードをインラインで実行します
  288. elseif ($ascii < 36)
  289. $decode = preg_replace($ENCODE, $inline, $decode);
  290. // 特殊なケース: $count==0 の場合、キーワードはありません。
  291. // アンパック関数の基本的な形状を維持したいので、コードをフリグします...
  292. if ($count == 0)
  293. $decode = preg_replace($this->_safeRegExp('($count )//s*=//s*1'), '$1=0', $decode, 1);
  294. }
  295. // ブート関数
  296. $unpack = $this->_getJSFunction('_unpack');
  297. if ($this->_fastDecode) {
  298. // デコーダを挿入します
  299. $this->buffer = $decode;
  300. $unpack = preg_replace_callback('///{/', array(&$this, '_insertFastDecode'), $unpack, 1);
  301. }
  302. $unpack = preg_replace('/"/', "'", $unpack);
  303. if ($this->_encoding > 62) { // high-ascii
  304. // 単語を削除します-正規表現一致の境界
  305. $unpack = preg_replace('//'////////b/'/s*//+|//+/s*/'////////b/ '/', '', $unpack);
  306. }
  307. if ($ascii > 36 || $this->_encoding > 62 || $this->_fastDecode) {
  308. // エンコード関数を挿入します
  309. $this->buffer = $encode;
  310. $unpack = preg_replace_callback('///', array(&$this, '_insertFastEncode'), $unpack, 1); } else {
  311. //インラインエンコード
  312. $unpack = preg_replace($ENCODE, $inline, $unpack);
  313. }
  314. // ブート関数もパックします
  315. $unpackPacker = new JavaScriptPacker($unpack, 0, false, true); unpackPacker->pack();
  316. // 引数
  317. $params = array($packed, $ascii, $count, $keywords);
  318. if ($this->_fastDecode) {
  319. $params[] = 0;
  320. $params[] = '{}';
  321. }
  322. $params = implode(',', $params);
  323. // 全体
  324. return 'eval(' . $unpack . '(' . $params . "))/n";
  325. }
  326. プライベート $buffer;
  327. プライベート関数 _insertFastDecode($match) {
  328. '{' を返します。 $this->バッファ 。 ';';
  329. }
  330. プライベート関数 _insertFastEncode($match) {
  331. '{$encode=' を返します。 $this->バッファ 。 ';';
  332. }
  333. // うーん.. ..どれが必要ですか??
  334. プライベート関数 _getEncoder($ascii) {
  335. return $ascii > 10? $アスキー> 36? $アスキー> 62?
  336. '_encode95' : '_encode62' : '_encode36' : '_encode10';
  337. }
  338. // ゼロエンコーディング
  339. // 文字: 0123456789
  340. private function _encode10($charCode) {
  341. return $charCode;
  342. }
  343. // 固有のbase36サポート
  344. // 文字: 0123456789abcdefghijklmnopqrstuvwxyz
  345. private function _encode36($charCode) {
  346. returnbase_convert($charCode, 10, 36);
  347. }
  348. // Base36 に乗り、大文字の英字を追加します
  349. // 文字: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
  350. private function _encode62($charCode) {
  351. $res = '';
  352. if ($charCode >= $this->_encoding) {
  353. $res = $this->_encode62((int)($charCode / $this->_encoding));
  354. }
  355. $charCode = $charCode % $this->_encoding;
  356. if ($charCode > 35)
  357. $res を返します。 chr($charCode + 29);
  358. else
  359. return $res 。 Base_convert($charCode, 10, 36);
  360. }
  361. // high-ascii 値を使用します
  362. // 文字: ?¢£¤¥|§¨?a??-?ˉ°±23′μ?·?1o?????àá???? ??èéê?ìí??D?òó???×?ùú?üYT?àáa?????èéê?ìí??e?òó???÷?ùú?üyt
  363. プライベート関数 _encode95($charCode) {
  364. $res = '';
  365. if ($charCode >= $this->_encoding)
  366. $res = $this->_encode95($charCode / $this->_encoding);
  367. $res を返します。 chr(($charCode % $this->_encoding) + 161);
  368. }
  369. プライベート関数 _safeRegExp($string) {
  370. return '/'.preg_replace('//$/', '///$', $string).'/';
  371. }
  372. プライベート関数 _encodePrivate($charCode) {
  373. return "_" 。 $charCode;
  374. }
  375. // パーサーによって使用される文字を保護
  376. private function _escape($script) {
  377. return preg_replace('/([/////'])/', '///$1', $script) ;
  378. }
  379. // すでにスクリプト内にあるハイアスキー文字を保護します
  380. private function _escape95($script) {
  381. return preg_replace_callback(
  382. '/[//xa1-//xff]/',
  383. array(&$this, '_escape95Bis')、
  384. $script
  385. );
  386. }
  387. プライベート関数 _escape95Bis($match) {
  388. return '/x'.((string)dechex(ord($match)));
  389. }
  390. プライベート関数 _getJSFunction($aName) {
  391. if (define('self::JSFUNCTION'.$aName))
  392. return constant('self::JSFUNCTION'.$aName);
  393. else
  394. return '';
  395. }
  396. // JavaScript 関数が使用されます。
  397. // 注 : Dean のバージョンでは、これらの関数は
  398. // 'String(aFunctionName);' で変換されます。
  399. // この内部変換により元のコードが完成します。例:
  400. // 'while (aBool) anAction();'は
  401. // 'while (aBool) { anAction(); に変換されます。 }'。
  402. // 以下のJavaScript関数を修正しました。
  403. // アンパッキング関数 - これはブートストラップ関数です
  404. // このパッキング ルーチンから抽出されたデータは、
  405. // ターゲットでデコードされるときにこの関数に渡されます
  406. // 注意 ! : 「;」なし最後の。
  407. const JSFUNCTION_unpack =
  408. 'function($packed, $ascii, $count, $keywords, $encode, $decode) {
  409. while ($count--) {
  410. if ($keywords[$count]) {
  411. $packed = $packed.replace(new RegExp(/'////b/' + $encode($count) + /'////b/', /'g/'), $keywords[$count]) ;
  412. }
  413. }
  414. $packed を返します。
  415. }';
  416. /*
  417. 'function($packed, $ascii, $count, $keywords, $encode, $decode) {
  418. while ($count--)
  419. if ($keywords[$count])
  420. $packed = $packed .replace(new RegExp(/'////b/' + $encode($count) + /'////b/', /'g/'), $keywords[$count]);
  421. $packed を返す;
  422. }';
  423. */
  424. // デコードを高速化するためにアンパッカーにコード スニペットが挿入されます
  425. const JSFUNCTION_decodeBody =
  426. //_decode = function() {
  427. // ブラウザは String.replace をサポートしますか?
  428. // 置換値は関数?
  429. ' if (!/'/'.replace(/^/, String)) {
  430. // 必要な値をすべてデコードします
  431. while ($count--) {
  432. $decode[$encode($count)] = $keywords[$count] || $encode($count);
  433. }
  434. // グローバル置換関数
  435. $keywords = [function ($encoded) {return $decode[$encoded]}];
  436. // 一般的な一致
  437. $encode = function () {return /'////w+/'};
  438. // ループカウンターをリセットします - 今、グローバル置換を行っています
  439. $count = 1;
  440. }
  441. ';
  442. //};
  443. /*
  444. ' if (!/'/'.replace(/^/, String)) {
  445. // 必要な値をすべてデコードします
  446. while ($count--) $decode[$encode($count)] = $キーワード[$カウント] || $encode($count);
  447. // グローバル置換関数
  448. $keywords = [function ($encoded) {return $decode[$encoded]}];
  449. // 一般的な一致
  450. $encode = function () {return/'////w+/'};
  451. // ループカウンターをリセットします - 今、グローバル置換を行っています
  452. $count = 1;
  453. }';
  454. */
  455. // ゼロエンコーディング
  456. // 文字: 0123456789
  457. const JSFUNCTION_encode10 =
  458. 'function($charCode) {
  459. return $charCode;
  460. }';//;';
  461. // 固有の Base36 サポート
  462. // 文字: 0123456789abcdefghijklmnopqrstuvwxyz
  463. const JSFUNCTION_encode36 =
  464. 'function($charCode) {
  465. return $charCode.toString(36);
  466. }';//;';
  467. // Base36 に乗り、大文字の英字を追加します
  468. // 文字: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
  469. const JSFUNCTION_encode62 =
  470. 'function($charCode) {
  471. return ($charCode) < _encoding ? /'/' : 引数。 callee(parseInt($charCode / _encoding))) +
  472. (($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36));
  473. }';
  474. // high-ASCII 値を使用します
  475. // 文字: ?¢£¤¥|§¨?a??-?ˉ°±23'μ?·?1o?????àá?????? èéê?ìí??D?òó???×?ùú?üYT?àáa?????èéê?ìí??e?òó???÷?ùú?üyt
  476. const JSFUNCTION_encode95 =
  477. 'function($charCode) {
  478. return ($charCode < _encoding ? /'/' : argument.callee($charCode / _encoding)) +
  479. String.fromCharCode($charCode % _encoding + 161);
  480. }';
  481. }
  482. class ParseMaster {
  483. public $ignoreCase = false;
  484. public $escapeChar = '';
  485. // 定数
  486. const EXPRESSION = 0;
  487. const REPLACEMENT = 1;
  488. const LENGTH = 2;
  489. // ネストレベルの決定に使用されます
  490. private $GROUPS = '///(/';//g
  491. private $SUB_REPLACE = '///$//d/';
  492. private $INDEXED = '/^/ /$//d+$/';
  493. プライベート $TRIM = '/([/'"])//1//.(.*)//.//1//1$/';
  494. プライベート $ESCAPE = '////./';//g
  495. プライベート $QUOTE = '//'/';
  496. プライベート $DELETED = '///x01[^//x01]*//x01/';// g
  497. public function add($expression, $replacement = '') {
  498. // 部分式の数をカウントします
  499. // - 各パターン自体が部分式であるため、1 つ追加します
  500. $length = 1 + preg_match_all( $this->GROUPS, $this->internalEscape((string)$expression), $out);
  501. // 文字列のみを扱います $replacement
  502. if (is_string($replacement)) {
  503. // パターンを実行します部分式を処理しますか?
  504. if (preg_match($this->SUB_REPLACE, $replacement)) {
  505. // 単純な検索 (例: "$2")
  506. if (preg_match($this->INDEXED, $replacement) )) {
  507. // インデックスを保存します (一致した文字列を高速に取得するために使用されます)
  508. $replacement = (int)(substr($replacement, 1)) - 1;
  509. } else { // 複雑な検索 (例: "Hello $2 $1")
  510. // ルックアップを実行する関数を構築します
  511. $quote = preg_match($this->QUOTE, $this->_internalEscape($replacement) )
  512. ? '"' : "'";
  513. $replacement = array(
  514. 'fn' => '_backReferences',
  515. 'data' => array(
  516. 'replacement' => $replacement,
  517. 'length' => ; $length,
  518. 'quote' => $quote
  519. )
  520. );
  521. // 変更された引数を渡します
  522. if (!emptyempty($expression)) $this->_add($expression, $replacement, $length);
  523. else $this->_add('/^$/', $replacement, $length);
  524. }
  525. public function exec($string) {
  526. // グローバル置換を実行します
  527. $this->_escaped = array();
  528. // Dean の _patterns.toSTring をシミュレートします
  529. $regexp = '/';
  530. foreach ($this->_patterns as $reg) {
  531. $regexp .= '(' . substr($reg[self::EXPRESSION], 1, -1) . ')|';
  532. }
  533. $regexp = substr($regexp, 0, -1) 。 '/';
  534. $regexp .= ($this->ignoreCase) ? '私' : '';
  535. $string = $this->_escape($string, $this->escapeChar);
  536. $string = preg_replace_callback(
  537. $regexp,
  538. array(
  539. &$this,
  540. '_replacement'
  541. ),
  542. $string
  543. );
  544. $string = $this->_unescape($string, $this->escapeChar);
  545. return preg_replace($this->DELETED, '', $string);
  546. }
  547. public function restart() {
  548. // このオブジェクトが再利用できるようにパターン コレクションをクリアします
  549. $this->_patterns = array();
  550. }
  551. // プライベート
  552. プライベート $_escaped = array(); // エスケープ文字
  553. private $_patterns = array(); // インデックスによって保存されるパターン
  554. // 新しいパターンを作成してパターン コレクションに追加します
  555. private function _add() {
  556. $arguments = func_get_args();
  557. $this->_patterns[] = $arguments;
  558. }
  559. // これはグローバル置換関数です (非常に複雑です)
  560. private function _replacement($arguments) {
  561. if (emptyempty($arguments)) return '';
  562. $i = 1; $j = 0;
  563. // パターンをループします
  564. while (isset($this->_patterns[$j])) {
  565. $pattern = $this->_patterns[$j++];
  566. // 結果はありますか?
  567. if (isset($arguments[$i]) && ($arguments[$i] != '')) {
  568. $replacement = $pattern[self::REPLACEMENT];
  569. if (is_array($replacement) && isset($replacement['fn'])) {
  570. if (isset($replacement['data'])) $this->buffer = $replacement['data' ];
  571. return call_user_func(array(&$this, $replacement['fn']), $arguments, $i);
  572. } elseif (is_int($replacement)) {
  573. return $arguments[$replacement + $i];
  574. }
  575. $delete = ($this->escapeChar == '' ||
  576. strpos($arguments[$i], $this->escapeChar) === false)
  577. ? '' : "/x01" 。 $arguments[$i] 。 "/x01";
  578. $delete を返します。 $置換;
  579. // 部分式への参照をスキップします
  580. } else {
  581. $i += $pattern[self::LENGTH];
  582. }
  583. }
  584. }
  585. private function _backReferences($match, $offset) {
  586. $replacement = $this->buffer['replacement'];
  587. $quote = $this->buffer['quote'];
  588. $i = $this->buffer['length'];
  589. while ($i) {
  590. $replacement = str_replace('$'.$i--, $match[$offset + $i], $replacement);
  591. }
  592. $replacement を返します。
  593. }
  594. プライベート関数 _replace_name($match, $offset){
  595. $length = strlen($match[$offset + 2]);
  596. $start = $length - max($length - strlen($match[$offset + 3]), 0);
  597. substr($match[$offset + 1], $start, $length) を返します。 $match[$offset + 4];
  598. }
  599. private function _replace_encoded($match, $offset) {
  600. return $this->buffer[$match[$offset]];
  601. }
  602. // php : preg_replace_callback に追加データを渡すことはできません。
  603. // そして、create_function で &$this を使用することはできないので、下位レベルに行きましょう
  604. private $buffer;
  605. // エスケープ文字をエンコードします
  606. private function _escape($string, $escapeChar) {
  607. if ($escapeChar) {
  608. $this->buffer = $escapeChar;
  609. return preg_replace_callback(
  610. '///' . $escapeChar . '(.)' .'/',
  611. array(&$this, '_escapeBis'),
  612. $string
  613. );
  614. } else {
  615. $string を返します。
  616. }
  617. }
  618. プライベート関数 _escapeBis($match) {
  619. $this->_escaped[] = $match[1];
  620. $this->buffer を返す;
  621. }
  622. // エスケープされた文字をデコードする
  623. private function _unescape($string, $escapeChar) {
  624. if ($escapeChar) {
  625. $regexp = '/'.'//'.$escapeChar.'/';
  626. $this->buffer = array('escapeChar'=> $escapeChar, 'i' => 0);
  627. return preg_replace_callback
  628. (
  629. $regexp,
  630. array(&$this, '_unescapeBis'),
  631. $string
  632. );
  633. } else {
  634. $string を返します。
  635. }
  636. }
  637. プライベート関数 _unescapeBis() {
  638. if (isset($this->_escaped[$this->buffer['i']]])
  639. && $this->_escaped[$this->バッファ['i']] != '')
  640. {
  641. $temp = $this->_escaped[$this->buffer['i']];
  642. } else {
  643. $temp = '';
  644. }
  645. $this->buffer['i']++;
  646. $this->buffer['escapeChar'] を返します。 $temp;
  647. }
  648. プライベート関数 _internalEscape($string) {
  649. return preg_replace($this->ESCAPE, '', $string);
  650. }
  651. }
  652. ?>
复制代

2、実行圧縮のPHPファイルpack_js_file.php

  1. require 'tom-class.JavaScriptPacker.php';
  2. $t1 = マイクロタイム(true);
  3. $source_dir = realpath(dirname(__FILE__)."/..")."/common/script_unpacked";
  4. $out_dir = realpath(dirname(__FILE__)."/..")."/common/script";
  5. $d = dir( $source_dir );
  6. //エコー "ハンドル: " . $d->ハンドル 。 "/n";
  7. //エコー "パス: " . $d->パス 。 "/n";
  8. while (false !== ($entry = $d->read())) {
  9. if($entry=='.') continue;
  10. if($entry=='..') 続行;
  11. if($entry=='.svn') 続行;
  12. echo $entry."/n";
  13. $script = file_get_contents($source_dir. '/'. $entry);
  14. $packer = new JavaScriptPacker($script, 'Normal', true, false);
  15. $packed = $packer->pack();
  16. file_put_contents($out_dir. '/'. $entry, $packed);
  17. }
  18. $d->close();
  19. $t2 = マイクロタイム(true);
  20. $time = sprintf('%.4f', ($t2 - $t1) );
  21. echo 'script in ', $time, ' s.', "/n";
  22. 死ぬ;
  23. ?>
复制コード

3、自動実行のbatファイルを作成します。 文中に次のような内容を入力します: /usr/local/php/bin/php Pack_js_file.php

总结: 只要充填好相对路または绝对路、一键加密JS完了、那は相当な方便です!!

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。