Version Description
Download this release
Release Info
Developer | wokamoto |
Plugin | Head Cleaner |
Version | 1.3.8 |
Comparing to | |
See all releases |
Code changes from version 1.3.7 to 1.3.8
- head-cleaner.php +58 -33
- includes/CSS/Compressor.php +250 -0
- includes/CSS/UriRewriter.php +270 -0
- includes/CSSMin.php +83 -0
- includes/CommentPreserver.php +90 -0
- includes/ImportProcessor.php +157 -0
- includes/JSMin.php +314 -0
- includes/common-controller.php +19 -1
- includes/jsmin-1.1.1.php +0 -291
- languages/head-cleaner-nl_NL.mo +0 -0
- languages/head-cleaner-nl_NL.po +213 -0
- readme.txt +6 -5
- readme_ja.txt +6 -5
head-cleaner.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Head Cleaner
|
4 |
-
Version: 1.3.
|
5 |
Plugin URI: http://wppluginsj.sourceforge.jp/head-cleaner/
|
6 |
Description: Cleaning tags from your WordPress header and footer.
|
7 |
Author: wokamoto
|
@@ -134,7 +134,7 @@ if (!class_exists('wokController') || !class_exists('wokScriptManager'))
|
|
134 |
//**************************************************************************************
|
135 |
class HeadCleaner extends wokController {
|
136 |
public $plugin_name = 'head-cleaner';
|
137 |
-
public $plugin_ver = '1.3.
|
138 |
|
139 |
// Deafault Options
|
140 |
private $options_default = array(
|
@@ -296,15 +296,19 @@ class HeadCleaner extends wokController {
|
|
296 |
require($includes . 'simple_html_dom.php' );
|
297 |
|
298 |
// jsmin.php - PHP implementation of Douglas Crockford's JSMin.
|
299 |
-
if ($this->options['js_minify']) {
|
300 |
-
require($includes . '
|
301 |
$this->options['js_minify'] = class_exists('JSMin') && $this->options['js_minify'];
|
302 |
}
|
303 |
|
304 |
-
// CSSTidy - CSS Parser and Optimiser
|
305 |
-
if ($this->options['css_optimise']) {
|
306 |
-
require($includes . 'csstidy-1.3/class.csstidy.php');
|
307 |
-
$this->options['css_optimise'] = class_exists('csstidy') && $this->options['css_optimise'];
|
|
|
|
|
|
|
|
|
308 |
}
|
309 |
|
310 |
// Use Google Ajax Libraries
|
@@ -332,7 +336,7 @@ class HeadCleaner extends wokController {
|
|
332 |
// ob_start for Header
|
333 |
//**************************************************************************************
|
334 |
public function head_start(){
|
335 |
-
if (! $this->
|
336 |
$ob_handlers = (array) ob_list_handlers();
|
337 |
if ( count($ob_handlers) > 0 ) {
|
338 |
foreach ( $ob_handlers as $ob_handler ) {
|
@@ -362,7 +366,7 @@ class HeadCleaner extends wokController {
|
|
362 |
// ob_start for footer
|
363 |
//**************************************************************************************
|
364 |
public function footer_start(){
|
365 |
-
if (! $this->
|
366 |
$ob_handlers = (array) ob_list_handlers();
|
367 |
if ( count($ob_handlers) > 0 ) {
|
368 |
foreach ( $ob_handlers as $ob_handler ) {
|
@@ -887,8 +891,21 @@ class HeadCleaner extends wokController {
|
|
887 |
//**************************************************************************************
|
888 |
// Is mobile ?
|
889 |
//**************************************************************************************
|
890 |
-
private function
|
891 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
892 |
}
|
893 |
|
894 |
//**************************************************************************************
|
@@ -1379,8 +1396,7 @@ class HeadCleaner extends wokController {
|
|
1379 |
|
1380 |
switch ($type) {
|
1381 |
case 'css': // inline CSS
|
1382 |
-
$text =
|
1383 |
-
. trim(preg_replace(
|
1384 |
array($comment_pattern, '/^[ \t]+/m', '/[ \t]+$/m') ,
|
1385 |
array('', '', '') ,
|
1386 |
$text)
|
@@ -1388,8 +1404,7 @@ class HeadCleaner extends wokController {
|
|
1388 |
break;
|
1389 |
|
1390 |
case 'js': // inline JavaScript
|
1391 |
-
$text =
|
1392 |
-
. trim(preg_replace(
|
1393 |
array($comment_pattern, '/^[ \t]+/m', '/[ \t]+$/m', '/^<\!\-+/', '/-+>$/') ,
|
1394 |
array('', '', '', '', '') ,
|
1395 |
$text)
|
@@ -1426,7 +1441,11 @@ class HeadCleaner extends wokController {
|
|
1426 |
private function _js_minify($buffer) {
|
1427 |
$js = trim($buffer . "\n");
|
1428 |
if ($this->options['js_minify']) {
|
1429 |
-
|
|
|
|
|
|
|
|
|
1430 |
}
|
1431 |
$js = trim($js);
|
1432 |
|
@@ -1462,15 +1481,19 @@ class HeadCleaner extends wokController {
|
|
1462 |
$css = trim($buffer . "\n");
|
1463 |
|
1464 |
if ($this->options['css_optimise']) {
|
1465 |
-
|
1466 |
-
|
1467 |
-
|
1468 |
-
|
1469 |
-
|
1470 |
-
|
1471 |
-
|
1472 |
-
|
1473 |
-
|
|
|
|
|
|
|
|
|
1474 |
}
|
1475 |
if ( $merge )
|
1476 |
$css = str_replace("\n\n", "\n", $this->_css_import($css));
|
@@ -1786,15 +1809,19 @@ class HeadCleaner extends wokController {
|
|
1786 |
$out .= "</tr>\n";
|
1787 |
}
|
1788 |
$out .= "<tr>";
|
1789 |
-
$out .= "<td>";
|
1790 |
-
$out .= "<input type=\"checkbox\" name=\"gzip_on\" id=\"gzip_on\" value=\"on\" style=\"margin-right:0.5em;\"".($this->options['gzip_on'] === true ? " checked=\"true\"" : "")." />";
|
1791 |
-
$out .= __('gzip compress to CSS and JS.', $this->textdomain_name);
|
1792 |
-
$out .= "</td>";
|
1793 |
$out .= "<td>";
|
1794 |
$out .= "<input type=\"checkbox\" name=\"use_ajax_libs\" id=\"use_ajax_libs\" value=\"on\" style=\"margin-right:0.5em;\"".($this->options['use_ajax_libs'] === true ? " checked=\"true\"" : "")." />";
|
1795 |
$out .= __('Use Google Ajax Libraries.', $this->textdomain_name);
|
1796 |
$out .= "</td>";
|
1797 |
$out .= "<td>";
|
|
|
|
|
|
|
|
|
1798 |
$out .= "</td>";
|
1799 |
$out .= "</tr>\n";
|
1800 |
|
@@ -1808,8 +1835,6 @@ class HeadCleaner extends wokController {
|
|
1808 |
$out .= __('Add canonical tag.', $this->textdomain_name);
|
1809 |
$out .= "</td>";
|
1810 |
$out .= "<td>";
|
1811 |
-
$out .= "<input type=\"checkbox\" name=\"ie_conditional\" id=\"ie_conditional\" value=\"on\" style=\"margin-right:0.5em;\"".($this->options['ie_conditional'] === true ? " checked=\"true\"" : "")." />";
|
1812 |
-
$out .= __('Remove IE Conditional Tag.', $this->textdomain_name);
|
1813 |
$out .= "</td>";
|
1814 |
$out .= "</tr>\n";
|
1815 |
|
@@ -1842,7 +1867,7 @@ class HeadCleaner extends wokController {
|
|
1842 |
$out .= "</tbody></table>";
|
1843 |
|
1844 |
// CSS Tidy Options
|
1845 |
-
if ($this->options['css_optimise']) {
|
1846 |
$out .= "<div style=\"margin-top:2em;\" id=\"csstidy_option\">\n";
|
1847 |
$out .= "<h3>" . __('The CSS optimization settings', $this->textdomain_name) . "</h3>" ;
|
1848 |
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Head Cleaner
|
4 |
+
Version: 1.3.8
|
5 |
Plugin URI: http://wppluginsj.sourceforge.jp/head-cleaner/
|
6 |
Description: Cleaning tags from your WordPress header and footer.
|
7 |
Author: wokamoto
|
134 |
//**************************************************************************************
|
135 |
class HeadCleaner extends wokController {
|
136 |
public $plugin_name = 'head-cleaner';
|
137 |
+
public $plugin_ver = '1.3.8';
|
138 |
|
139 |
// Deafault Options
|
140 |
private $options_default = array(
|
296 |
require($includes . 'simple_html_dom.php' );
|
297 |
|
298 |
// jsmin.php - PHP implementation of Douglas Crockford's JSMin.
|
299 |
+
if ($this->options['js_minify'] && !class_exists('JSMin')) {
|
300 |
+
require($includes . 'JSMin.php');
|
301 |
$this->options['js_minify'] = class_exists('JSMin') && $this->options['js_minify'];
|
302 |
}
|
303 |
|
304 |
+
// // CSSTidy - CSS Parser and Optimiser
|
305 |
+
// if ($this->options['css_optimise'] && !class_exists('csstidy')) {
|
306 |
+
// require($includes . 'csstidy-1.3/class.csstidy.php');
|
307 |
+
// $this->options['css_optimise'] = class_exists('csstidy') && $this->options['css_optimise'];
|
308 |
+
// }
|
309 |
+
if ($this->options['css_optimise'] && !class_exists('Minify_CSS')) {
|
310 |
+
require($includes . 'CSSMin.php');
|
311 |
+
$this->options['css_optimise'] = class_exists('Minify_CSS') && $this->options['css_optimise'];
|
312 |
}
|
313 |
|
314 |
// Use Google Ajax Libraries
|
336 |
// ob_start for Header
|
337 |
//**************************************************************************************
|
338 |
public function head_start(){
|
339 |
+
if (! $this->_is_mobile() ) {
|
340 |
$ob_handlers = (array) ob_list_handlers();
|
341 |
if ( count($ob_handlers) > 0 ) {
|
342 |
foreach ( $ob_handlers as $ob_handler ) {
|
366 |
// ob_start for footer
|
367 |
//**************************************************************************************
|
368 |
public function footer_start(){
|
369 |
+
if (! $this->_is_mobile() && $this->options['foot_js'] ) {
|
370 |
$ob_handlers = (array) ob_list_handlers();
|
371 |
if ( count($ob_handlers) > 0 ) {
|
372 |
foreach ( $ob_handlers as $ob_handler ) {
|
891 |
//**************************************************************************************
|
892 |
// Is mobile ?
|
893 |
//**************************************************************************************
|
894 |
+
private function _is_mobile() {
|
895 |
+
$is_mobile = $this->isKtai();
|
896 |
+
|
897 |
+
if ( !$is_mobile && function_exists('bnc_is_iphone') ) {
|
898 |
+
global $wptouch_plugin;
|
899 |
+
|
900 |
+
$is_mobile = bnc_is_iphone();
|
901 |
+
if ( $is_mobile && isset($wptouch_plugin) ) {
|
902 |
+
$is_mobile = isset($wptouch_plugin->desired_view)
|
903 |
+
? $wptouch_plugin->desired_view == 'mobile'
|
904 |
+
: true;
|
905 |
+
}
|
906 |
+
}
|
907 |
+
|
908 |
+
return ($is_mobile);
|
909 |
}
|
910 |
|
911 |
//**************************************************************************************
|
1396 |
|
1397 |
switch ($type) {
|
1398 |
case 'css': // inline CSS
|
1399 |
+
$text = trim(preg_replace(
|
|
|
1400 |
array($comment_pattern, '/^[ \t]+/m', '/[ \t]+$/m') ,
|
1401 |
array('', '', '') ,
|
1402 |
$text)
|
1404 |
break;
|
1405 |
|
1406 |
case 'js': // inline JavaScript
|
1407 |
+
$text = trim(preg_replace(
|
|
|
1408 |
array($comment_pattern, '/^[ \t]+/m', '/[ \t]+$/m', '/^<\!\-+/', '/-+>$/') ,
|
1409 |
array('', '', '', '', '') ,
|
1410 |
$text)
|
1441 |
private function _js_minify($buffer) {
|
1442 |
$js = trim($buffer . "\n");
|
1443 |
if ($this->options['js_minify']) {
|
1444 |
+
if ( class_exists('JSMin') ) {
|
1445 |
+
$js = JSMin::minify($js);
|
1446 |
+
} else if( class_exists('JSMinPlus') ) {
|
1447 |
+
$js = JSMinPlus::minify($js);
|
1448 |
+
}
|
1449 |
}
|
1450 |
$js = trim($js);
|
1451 |
|
1481 |
$css = trim($buffer . "\n");
|
1482 |
|
1483 |
if ($this->options['css_optimise']) {
|
1484 |
+
if ( class_exists('Minify_CSS') ) {
|
1485 |
+
$css = Minify_CSS::minify($css);
|
1486 |
+
} else if ( class_exists('csstidy') ) {
|
1487 |
+
$csstidy = new csstidy();
|
1488 |
+
$csstidy->set_cfg('optimise_shorthands', $this->options['csstidy_option']['optimise_shorthands']);
|
1489 |
+
$csstidy->set_cfg('compress_colors', $this->options['csstidy_option']['compress_colors']);
|
1490 |
+
$csstidy->set_cfg('compress_font-weight', $this->options['csstidy_option']['compress_font_weight']);
|
1491 |
+
$csstidy->set_cfg('remove_bslash', $this->options['csstidy_option']['remove_bslash']);
|
1492 |
+
$csstidy->load_template($this->csstidy_template[$this->options['csstidy_option']['template']]);
|
1493 |
+
$csstidy->parse($css);
|
1494 |
+
$css = $csstidy->print->plain();
|
1495 |
+
unset($csstidy);
|
1496 |
+
}
|
1497 |
}
|
1498 |
if ( $merge )
|
1499 |
$css = str_replace("\n\n", "\n", $this->_css_import($css));
|
1809 |
$out .= "</tr>\n";
|
1810 |
}
|
1811 |
$out .= "<tr>";
|
1812 |
+
// $out .= "<td>";
|
1813 |
+
// $out .= "<input type=\"checkbox\" name=\"gzip_on\" id=\"gzip_on\" value=\"on\" style=\"margin-right:0.5em;\"".($this->options['gzip_on'] === true ? " checked=\"true\"" : "")." />";
|
1814 |
+
// $out .= __('gzip compress to CSS and JS.', $this->textdomain_name);
|
1815 |
+
// $out .= "</td>";
|
1816 |
$out .= "<td>";
|
1817 |
$out .= "<input type=\"checkbox\" name=\"use_ajax_libs\" id=\"use_ajax_libs\" value=\"on\" style=\"margin-right:0.5em;\"".($this->options['use_ajax_libs'] === true ? " checked=\"true\"" : "")." />";
|
1818 |
$out .= __('Use Google Ajax Libraries.', $this->textdomain_name);
|
1819 |
$out .= "</td>";
|
1820 |
$out .= "<td>";
|
1821 |
+
$out .= "<input type=\"checkbox\" name=\"ie_conditional\" id=\"ie_conditional\" value=\"on\" style=\"margin-right:0.5em;\"".($this->options['ie_conditional'] === true ? " checked=\"true\"" : "")." />";
|
1822 |
+
$out .= __('Remove IE Conditional Tag.', $this->textdomain_name);
|
1823 |
+
$out .= "</td>";
|
1824 |
+
$out .= "<td>";
|
1825 |
$out .= "</td>";
|
1826 |
$out .= "</tr>\n";
|
1827 |
|
1835 |
$out .= __('Add canonical tag.', $this->textdomain_name);
|
1836 |
$out .= "</td>";
|
1837 |
$out .= "<td>";
|
|
|
|
|
1838 |
$out .= "</td>";
|
1839 |
$out .= "</tr>\n";
|
1840 |
|
1867 |
$out .= "</tbody></table>";
|
1868 |
|
1869 |
// CSS Tidy Options
|
1870 |
+
if ($this->options['css_optimise'] && class_exists('csstidy')) {
|
1871 |
$out .= "<div style=\"margin-top:2em;\" id=\"csstidy_option\">\n";
|
1872 |
$out .= "<h3>" . __('The CSS optimization settings', $this->textdomain_name) . "</h3>" ;
|
1873 |
|
includes/CSS/Compressor.php
ADDED
@@ -0,0 +1,250 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Minify_CSS_Compressor
|
4 |
+
* @package Minify
|
5 |
+
*/
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Compress CSS
|
9 |
+
*
|
10 |
+
* This is a heavy regex-based removal of whitespace, unnecessary
|
11 |
+
* comments and tokens, and some CSS value minimization, where practical.
|
12 |
+
* Many steps have been taken to avoid breaking comment-based hacks,
|
13 |
+
* including the ie5/mac filter (and its inversion), but expect tricky
|
14 |
+
* hacks involving comment tokens in 'content' value strings to break
|
15 |
+
* minimization badly. A test suite is available.
|
16 |
+
*
|
17 |
+
* @package Minify
|
18 |
+
* @author Stephen Clay <steve@mrclay.org>
|
19 |
+
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
|
20 |
+
*/
|
21 |
+
class Minify_CSS_Compressor {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Minify a CSS string
|
25 |
+
*
|
26 |
+
* @param string $css
|
27 |
+
*
|
28 |
+
* @param array $options (currently ignored)
|
29 |
+
*
|
30 |
+
* @return string
|
31 |
+
*/
|
32 |
+
public static function process($css, $options = array())
|
33 |
+
{
|
34 |
+
$obj = new Minify_CSS_Compressor($options);
|
35 |
+
return $obj->_process($css);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @var array options
|
40 |
+
*/
|
41 |
+
protected $_options = null;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @var bool Are we "in" a hack?
|
45 |
+
*
|
46 |
+
* I.e. are some browsers targetted until the next comment?
|
47 |
+
*/
|
48 |
+
protected $_inHack = false;
|
49 |
+
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Constructor
|
53 |
+
*
|
54 |
+
* @param array $options (currently ignored)
|
55 |
+
*
|
56 |
+
* @return null
|
57 |
+
*/
|
58 |
+
private function __construct($options) {
|
59 |
+
$this->_options = $options;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Minify a CSS string
|
64 |
+
*
|
65 |
+
* @param string $css
|
66 |
+
*
|
67 |
+
* @return string
|
68 |
+
*/
|
69 |
+
protected function _process($css)
|
70 |
+
{
|
71 |
+
$css = str_replace("\r\n", "\n", $css);
|
72 |
+
|
73 |
+
// preserve empty comment after '>'
|
74 |
+
// http://www.webdevout.net/css-hacks#in_css-selectors
|
75 |
+
$css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
|
76 |
+
|
77 |
+
// preserve empty comment between property and value
|
78 |
+
// http://css-discuss.incutio.com/?page=BoxModelHack
|
79 |
+
$css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
|
80 |
+
$css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
|
81 |
+
|
82 |
+
// apply callback to all valid comments (and strip out surrounding ws
|
83 |
+
$css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@'
|
84 |
+
,array($this, '_commentCB'), $css);
|
85 |
+
|
86 |
+
// remove ws around { } and last semicolon in declaration block
|
87 |
+
$css = preg_replace('/\\s*{\\s*/', '{', $css);
|
88 |
+
$css = preg_replace('/;?\\s*}\\s*/', '}', $css);
|
89 |
+
|
90 |
+
// remove ws surrounding semicolons
|
91 |
+
$css = preg_replace('/\\s*;\\s*/', ';', $css);
|
92 |
+
|
93 |
+
// remove ws around urls
|
94 |
+
$css = preg_replace('/
|
95 |
+
url\\( # url(
|
96 |
+
\\s*
|
97 |
+
([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
|
98 |
+
\\s*
|
99 |
+
\\) # )
|
100 |
+
/x', 'url($1)', $css);
|
101 |
+
|
102 |
+
// remove ws between rules and colons
|
103 |
+
$css = preg_replace('/
|
104 |
+
\\s*
|
105 |
+
([{;]) # 1 = beginning of block or rule separator
|
106 |
+
\\s*
|
107 |
+
([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
|
108 |
+
\\s*
|
109 |
+
:
|
110 |
+
\\s*
|
111 |
+
(\\b|[#\'"]) # 3 = first character of a value
|
112 |
+
/x', '$1$2:$3', $css);
|
113 |
+
|
114 |
+
// remove ws in selectors
|
115 |
+
$css = preg_replace_callback('/
|
116 |
+
(?: # non-capture
|
117 |
+
\\s*
|
118 |
+
[^~>+,\\s]+ # selector part
|
119 |
+
\\s*
|
120 |
+
[,>+~] # combinators
|
121 |
+
)+
|
122 |
+
\\s*
|
123 |
+
[^~>+,\\s]+ # selector part
|
124 |
+
{ # open declaration block
|
125 |
+
/x'
|
126 |
+
,array($this, '_selectorsCB'), $css);
|
127 |
+
|
128 |
+
// minimize hex colors
|
129 |
+
$css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i'
|
130 |
+
, '$1#$2$3$4$5', $css);
|
131 |
+
|
132 |
+
// remove spaces between font families
|
133 |
+
$css = preg_replace_callback('/font-family:([^;}]+)([;}])/'
|
134 |
+
,array($this, '_fontFamilyCB'), $css);
|
135 |
+
|
136 |
+
$css = preg_replace('/@import\\s+url/', '@import url', $css);
|
137 |
+
|
138 |
+
// replace any ws involving newlines with a single newline
|
139 |
+
$css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css);
|
140 |
+
|
141 |
+
// separate common descendent selectors w/ newlines (to limit line lengths)
|
142 |
+
$css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css);
|
143 |
+
|
144 |
+
// Use newline after 1st numeric value (to limit line lengths).
|
145 |
+
$css = preg_replace('/
|
146 |
+
((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
|
147 |
+
\\s+
|
148 |
+
/x'
|
149 |
+
,"$1\n", $css);
|
150 |
+
|
151 |
+
// prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
|
152 |
+
$css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css);
|
153 |
+
|
154 |
+
return trim($css);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Replace what looks like a set of selectors
|
159 |
+
*
|
160 |
+
* @param array $m regex matches
|
161 |
+
*
|
162 |
+
* @return string
|
163 |
+
*/
|
164 |
+
protected function _selectorsCB($m)
|
165 |
+
{
|
166 |
+
// remove ws around the combinators
|
167 |
+
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Process a comment and return a replacement
|
172 |
+
*
|
173 |
+
* @param array $m regex matches
|
174 |
+
*
|
175 |
+
* @return string
|
176 |
+
*/
|
177 |
+
protected function _commentCB($m)
|
178 |
+
{
|
179 |
+
$hasSurroundingWs = (trim($m[0]) !== $m[1]);
|
180 |
+
$m = $m[1];
|
181 |
+
// $m is the comment content w/o the surrounding tokens,
|
182 |
+
// but the return value will replace the entire comment.
|
183 |
+
if ($m === 'keep') {
|
184 |
+
return '/**/';
|
185 |
+
}
|
186 |
+
if ($m === '" "') {
|
187 |
+
// component of http://tantek.com/CSS/Examples/midpass.html
|
188 |
+
return '/*" "*/';
|
189 |
+
}
|
190 |
+
if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
|
191 |
+
// component of http://tantek.com/CSS/Examples/midpass.html
|
192 |
+
return '/*";}}/* */';
|
193 |
+
}
|
194 |
+
if ($this->_inHack) {
|
195 |
+
// inversion: feeding only to one browser
|
196 |
+
if (preg_match('@
|
197 |
+
^/ # comment started like /*/
|
198 |
+
\\s*
|
199 |
+
(\\S[\\s\\S]+?) # has at least some non-ws content
|
200 |
+
\\s*
|
201 |
+
/\\* # ends like /*/ or /**/
|
202 |
+
@x', $m, $n)) {
|
203 |
+
// end hack mode after this comment, but preserve the hack and comment content
|
204 |
+
$this->_inHack = false;
|
205 |
+
return "/*/{$n[1]}/**/";
|
206 |
+
}
|
207 |
+
}
|
208 |
+
if (substr($m, -1) === '\\') { // comment ends like \*/
|
209 |
+
// begin hack mode and preserve hack
|
210 |
+
$this->_inHack = true;
|
211 |
+
return '/*\\*/';
|
212 |
+
}
|
213 |
+
if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
|
214 |
+
// begin hack mode and preserve hack
|
215 |
+
$this->_inHack = true;
|
216 |
+
return '/*/*/';
|
217 |
+
}
|
218 |
+
if ($this->_inHack) {
|
219 |
+
// a regular comment ends hack mode but should be preserved
|
220 |
+
$this->_inHack = false;
|
221 |
+
return '/**/';
|
222 |
+
}
|
223 |
+
// Issue 107: if there's any surrounding whitespace, it may be important, so
|
224 |
+
// replace the comment with a single space
|
225 |
+
return $hasSurroundingWs // remove all other comments
|
226 |
+
? ' '
|
227 |
+
: '';
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Process a font-family listing and return a replacement
|
232 |
+
*
|
233 |
+
* @param array $m regex matches
|
234 |
+
*
|
235 |
+
* @return string
|
236 |
+
*/
|
237 |
+
protected function _fontFamilyCB($m)
|
238 |
+
{
|
239 |
+
$m[1] = preg_replace('/
|
240 |
+
\\s*
|
241 |
+
(
|
242 |
+
"[^"]+" # 1 = family in double qutoes
|
243 |
+
|\'[^\']+\' # or 1 = family in single quotes
|
244 |
+
|[\\w\\-]+ # or 1 = unquoted family
|
245 |
+
)
|
246 |
+
\\s*
|
247 |
+
/x', '$1', $m[1]);
|
248 |
+
return 'font-family:' . $m[1] . $m[2];
|
249 |
+
}
|
250 |
+
}
|
includes/CSS/UriRewriter.php
ADDED
@@ -0,0 +1,270 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Minify_CSS_UriRewriter
|
4 |
+
* @package Minify
|
5 |
+
*/
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Rewrite file-relative URIs as root-relative in CSS files
|
9 |
+
*
|
10 |
+
* @package Minify
|
11 |
+
* @author Stephen Clay <steve@mrclay.org>
|
12 |
+
*/
|
13 |
+
class Minify_CSS_UriRewriter {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Defines which class to call as part of callbacks, change this
|
17 |
+
* if you extend Minify_CSS_UriRewriter
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
protected static $className = 'Minify_CSS_UriRewriter';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* rewrite() and rewriteRelative() append debugging information here
|
24 |
+
* @var string
|
25 |
+
*/
|
26 |
+
public static $debugText = '';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Rewrite file relative URIs as root relative in CSS files
|
30 |
+
*
|
31 |
+
* @param string $css
|
32 |
+
*
|
33 |
+
* @param string $currentDir The directory of the current CSS file.
|
34 |
+
*
|
35 |
+
* @param string $docRoot The document root of the web site in which
|
36 |
+
* the CSS file resides (default = $_SERVER['DOCUMENT_ROOT']).
|
37 |
+
*
|
38 |
+
* @param array $symlinks (default = array()) If the CSS file is stored in
|
39 |
+
* a symlink-ed directory, provide an array of link paths to
|
40 |
+
* target paths, where the link paths are within the document root. Because
|
41 |
+
* paths need to be normalized for this to work, use "//" to substitute
|
42 |
+
* the doc root in the link paths (the array keys). E.g.:
|
43 |
+
* <code>
|
44 |
+
* array('//symlink' => '/real/target/path') // unix
|
45 |
+
* array('//static' => 'D:\\staticStorage') // Windows
|
46 |
+
* </code>
|
47 |
+
*
|
48 |
+
* @return string
|
49 |
+
*/
|
50 |
+
public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = array())
|
51 |
+
{
|
52 |
+
self::$_docRoot = self::_realpath(
|
53 |
+
$docRoot ? $docRoot : $_SERVER['DOCUMENT_ROOT']
|
54 |
+
);
|
55 |
+
self::$_currentDir = self::_realpath($currentDir);
|
56 |
+
self::$_symlinks = array();
|
57 |
+
|
58 |
+
// normalize symlinks
|
59 |
+
foreach ($symlinks as $link => $target) {
|
60 |
+
$link = ($link === '//')
|
61 |
+
? self::$_docRoot
|
62 |
+
: str_replace('//', self::$_docRoot . '/', $link);
|
63 |
+
$link = strtr($link, '/', DIRECTORY_SEPARATOR);
|
64 |
+
self::$_symlinks[$link] = self::_realpath($target);
|
65 |
+
}
|
66 |
+
|
67 |
+
self::$debugText .= "docRoot : " . self::$_docRoot . "\n"
|
68 |
+
. "currentDir : " . self::$_currentDir . "\n";
|
69 |
+
if (self::$_symlinks) {
|
70 |
+
self::$debugText .= "symlinks : " . var_export(self::$_symlinks, 1) . "\n";
|
71 |
+
}
|
72 |
+
self::$debugText .= "\n";
|
73 |
+
|
74 |
+
$css = self::_trimUrls($css);
|
75 |
+
|
76 |
+
// rewrite
|
77 |
+
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
78 |
+
,array(self::$className, '_processUriCB'), $css);
|
79 |
+
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
80 |
+
,array(self::$className, '_processUriCB'), $css);
|
81 |
+
|
82 |
+
return $css;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Prepend a path to relative URIs in CSS files
|
87 |
+
*
|
88 |
+
* @param string $css
|
89 |
+
*
|
90 |
+
* @param string $path The path to prepend.
|
91 |
+
*
|
92 |
+
* @return string
|
93 |
+
*/
|
94 |
+
public static function prepend($css, $path)
|
95 |
+
{
|
96 |
+
self::$_prependPath = $path;
|
97 |
+
|
98 |
+
$css = self::_trimUrls($css);
|
99 |
+
|
100 |
+
// append
|
101 |
+
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
102 |
+
,array(self::$className, '_processUriCB'), $css);
|
103 |
+
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
104 |
+
,array(self::$className, '_processUriCB'), $css);
|
105 |
+
|
106 |
+
self::$_prependPath = null;
|
107 |
+
return $css;
|
108 |
+
}
|
109 |
+
|
110 |
+
|
111 |
+
/**
|
112 |
+
* @var string directory of this stylesheet
|
113 |
+
*/
|
114 |
+
private static $_currentDir = '';
|
115 |
+
|
116 |
+
/**
|
117 |
+
* @var string DOC_ROOT
|
118 |
+
*/
|
119 |
+
private static $_docRoot = '';
|
120 |
+
|
121 |
+
/**
|
122 |
+
* @var array directory replacements to map symlink targets back to their
|
123 |
+
* source (within the document root) E.g. '/var/www/symlink' => '/var/realpath'
|
124 |
+
*/
|
125 |
+
private static $_symlinks = array();
|
126 |
+
|
127 |
+
/**
|
128 |
+
* @var string path to prepend
|
129 |
+
*/
|
130 |
+
private static $_prependPath = null;
|
131 |
+
|
132 |
+
private static function _trimUrls($css)
|
133 |
+
{
|
134 |
+
return preg_replace('/
|
135 |
+
url\\( # url(
|
136 |
+
\\s*
|
137 |
+
([^\\)]+?) # 1 = URI (assuming does not contain ")")
|
138 |
+
\\s*
|
139 |
+
\\) # )
|
140 |
+
/x', 'url($1)', $css);
|
141 |
+
}
|
142 |
+
|
143 |
+
private static function _processUriCB($m)
|
144 |
+
{
|
145 |
+
// $m matched either '/@import\\s+([\'"])(.*?)[\'"]/' or '/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
146 |
+
$isImport = ($m[0][0] === '@');
|
147 |
+
// determine URI and the quote character (if any)
|
148 |
+
if ($isImport) {
|
149 |
+
$quoteChar = $m[1];
|
150 |
+
$uri = $m[2];
|
151 |
+
} else {
|
152 |
+
// $m[1] is either quoted or not
|
153 |
+
$quoteChar = ($m[1][0] === "'" || $m[1][0] === '"')
|
154 |
+
? $m[1][0]
|
155 |
+
: '';
|
156 |
+
$uri = ($quoteChar === '')
|
157 |
+
? $m[1]
|
158 |
+
: substr($m[1], 1, strlen($m[1]) - 2);
|
159 |
+
}
|
160 |
+
// analyze URI
|
161 |
+
if ('/' !== $uri[0] // root-relative
|
162 |
+
&& false === strpos($uri, '//') // protocol (non-data)
|
163 |
+
&& 0 !== strpos($uri, 'data:') // data protocol
|
164 |
+
) {
|
165 |
+
// URI is file-relative: rewrite depending on options
|
166 |
+
$uri = (self::$_prependPath !== null)
|
167 |
+
? (self::$_prependPath . $uri)
|
168 |
+
: self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks);
|
169 |
+
}
|
170 |
+
return $isImport
|
171 |
+
? "@import {$quoteChar}{$uri}{$quoteChar}"
|
172 |
+
: "url({$quoteChar}{$uri}{$quoteChar})";
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Rewrite a file relative URI as root relative
|
177 |
+
*
|
178 |
+
* <code>
|
179 |
+
* Minify_CSS_UriRewriter::rewriteRelative(
|
180 |
+
* '../img/hello.gif'
|
181 |
+
* , '/home/user/www/css' // path of CSS file
|
182 |
+
* , '/home/user/www' // doc root
|
183 |
+
* );
|
184 |
+
* // returns '/img/hello.gif'
|
185 |
+
*
|
186 |
+
* // example where static files are stored in a symlinked directory
|
187 |
+
* Minify_CSS_UriRewriter::rewriteRelative(
|
188 |
+
* 'hello.gif'
|
189 |
+
* , '/var/staticFiles/theme'
|
190 |
+
* , '/home/user/www'
|
191 |
+
* , array('/home/user/www/static' => '/var/staticFiles')
|
192 |
+
* );
|
193 |
+
* // returns '/static/theme/hello.gif'
|
194 |
+
* </code>
|
195 |
+
*
|
196 |
+
* @param string $uri file relative URI
|
197 |
+
*
|
198 |
+
* @param string $realCurrentDir realpath of the current file's directory.
|
199 |
+
*
|
200 |
+
* @param string $realDocRoot realpath of the site document root.
|
201 |
+
*
|
202 |
+
* @param array $symlinks (default = array()) If the file is stored in
|
203 |
+
* a symlink-ed directory, provide an array of link paths to
|
204 |
+
* real target paths, where the link paths "appear" to be within the document
|
205 |
+
* root. E.g.:
|
206 |
+
* <code>
|
207 |
+
* array('/home/foo/www/not/real/path' => '/real/target/path') // unix
|
208 |
+
* array('C:\\htdocs\\not\\real' => 'D:\\real\\target\\path') // Windows
|
209 |
+
* </code>
|
210 |
+
*
|
211 |
+
* @return string
|
212 |
+
*/
|
213 |
+
public static function rewriteRelative($uri, $realCurrentDir, $realDocRoot, $symlinks = array())
|
214 |
+
{
|
215 |
+
// prepend path with current dir separator (OS-independent)
|
216 |
+
$path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR)
|
217 |
+
. DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR);
|
218 |
+
|
219 |
+
self::$debugText .= "file-relative URI : {$uri}\n"
|
220 |
+
. "path prepended : {$path}\n";
|
221 |
+
|
222 |
+
// "unresolve" a symlink back to doc root
|
223 |
+
foreach ($symlinks as $link => $target) {
|
224 |
+
if (0 === strpos($path, $target)) {
|
225 |
+
// replace $target with $link
|
226 |
+
$path = $link . substr($path, strlen($target));
|
227 |
+
|
228 |
+
self::$debugText .= "symlink unresolved : {$path}\n";
|
229 |
+
|
230 |
+
break;
|
231 |
+
}
|
232 |
+
}
|
233 |
+
// strip doc root
|
234 |
+
$path = substr($path, strlen($realDocRoot));
|
235 |
+
|
236 |
+
self::$debugText .= "docroot stripped : {$path}\n";
|
237 |
+
|
238 |
+
// fix to root-relative URI
|
239 |
+
|
240 |
+
$uri = strtr($path, '/\\', '//');
|
241 |
+
|
242 |
+
// remove /./ and /../ where possible
|
243 |
+
$uri = str_replace('/./', '/', $uri);
|
244 |
+
// inspired by patch from Oleg Cherniy
|
245 |
+
do {
|
246 |
+
$uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, 1, $changed);
|
247 |
+
} while ($changed);
|
248 |
+
|
249 |
+
self::$debugText .= "traversals removed : {$uri}\n\n";
|
250 |
+
|
251 |
+
return $uri;
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Get realpath with any trailing slash removed. If realpath() fails,
|
256 |
+
* just remove the trailing slash.
|
257 |
+
*
|
258 |
+
* @param string $path
|
259 |
+
*
|
260 |
+
* @return mixed path with no trailing slash
|
261 |
+
*/
|
262 |
+
protected static function _realpath($path)
|
263 |
+
{
|
264 |
+
$realPath = realpath($path);
|
265 |
+
if ($realPath !== false) {
|
266 |
+
$path = $realPath;
|
267 |
+
}
|
268 |
+
return rtrim($path, '/\\');
|
269 |
+
}
|
270 |
+
}
|
includes/CSSMin.php
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Minify_CSS
|
4 |
+
* @package Minify
|
5 |
+
*/
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Minify CSS
|
9 |
+
*
|
10 |
+
* This class uses Minify_CSS_Compressor and Minify_CSS_UriRewriter to
|
11 |
+
* minify CSS and rewrite relative URIs.
|
12 |
+
*
|
13 |
+
* @package Minify
|
14 |
+
* @author Stephen Clay <steve@mrclay.org>
|
15 |
+
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
|
16 |
+
*/
|
17 |
+
class Minify_CSS {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Minify a CSS string
|
21 |
+
*
|
22 |
+
* @param string $css
|
23 |
+
*
|
24 |
+
* @param array $options available options:
|
25 |
+
*
|
26 |
+
* 'preserveComments': (default true) multi-line comments that begin
|
27 |
+
* with "/*!" will be preserved with newlines before and after to
|
28 |
+
* enhance readability.
|
29 |
+
*
|
30 |
+
* 'prependRelativePath': (default null) if given, this string will be
|
31 |
+
* prepended to all relative URIs in import/url declarations
|
32 |
+
*
|
33 |
+
* 'currentDir': (default null) if given, this is assumed to be the
|
34 |
+
* directory of the current CSS file. Using this, minify will rewrite
|
35 |
+
* all relative URIs in import/url declarations to correctly point to
|
36 |
+
* the desired files. For this to work, the files *must* exist and be
|
37 |
+
* visible by the PHP process.
|
38 |
+
*
|
39 |
+
* 'symlinks': (default = array()) If the CSS file is stored in
|
40 |
+
* a symlink-ed directory, provide an array of link paths to
|
41 |
+
* target paths, where the link paths are within the document root. Because
|
42 |
+
* paths need to be normalized for this to work, use "//" to substitute
|
43 |
+
* the doc root in the link paths (the array keys). E.g.:
|
44 |
+
* <code>
|
45 |
+
* array('//symlink' => '/real/target/path') // unix
|
46 |
+
* array('//static' => 'D:\\staticStorage') // Windows
|
47 |
+
* </code>
|
48 |
+
*
|
49 |
+
* @return string
|
50 |
+
*/
|
51 |
+
public static function minify($css, $options = array())
|
52 |
+
{
|
53 |
+
require_once dirname(__FILE__).'/CSS/Compressor.php';
|
54 |
+
if (isset($options['preserveComments'])
|
55 |
+
&& !$options['preserveComments']) {
|
56 |
+
$css = Minify_CSS_Compressor::process($css, $options);
|
57 |
+
} else {
|
58 |
+
require_once dirname(__FILE__).'/CommentPreserver.php';
|
59 |
+
$css = Minify_CommentPreserver::process(
|
60 |
+
$css
|
61 |
+
,array('Minify_CSS_Compressor', 'process')
|
62 |
+
,array($options)
|
63 |
+
);
|
64 |
+
}
|
65 |
+
if (! isset($options['currentDir']) && ! isset($options['prependRelativePath'])) {
|
66 |
+
return $css;
|
67 |
+
}
|
68 |
+
require_once dirname(__FILE__).'/CSS/UriRewriter.php';
|
69 |
+
if (isset($options['currentDir'])) {
|
70 |
+
return Minify_CSS_UriRewriter::rewrite(
|
71 |
+
$css
|
72 |
+
,$options['currentDir']
|
73 |
+
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
74 |
+
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
75 |
+
);
|
76 |
+
} else {
|
77 |
+
return Minify_CSS_UriRewriter::prepend(
|
78 |
+
$css
|
79 |
+
,$options['prependRelativePath']
|
80 |
+
);
|
81 |
+
}
|
82 |
+
}
|
83 |
+
}
|
includes/CommentPreserver.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Minify_CommentPreserver
|
4 |
+
* @package Minify
|
5 |
+
*/
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Process a string in pieces preserving C-style comments that begin with "/*!"
|
9 |
+
*
|
10 |
+
* @package Minify
|
11 |
+
* @author Stephen Clay <steve@mrclay.org>
|
12 |
+
*/
|
13 |
+
class Minify_CommentPreserver {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* String to be prepended to each preserved comment
|
17 |
+
*
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
public static $prepend = "\n";
|
21 |
+
|
22 |
+
/**
|
23 |
+
* String to be appended to each preserved comment
|
24 |
+
*
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
public static $append = "\n";
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Process a string outside of C-style comments that begin with "/*!"
|
31 |
+
*
|
32 |
+
* On each non-empty string outside these comments, the given processor
|
33 |
+
* function will be called. The first "!" will be removed from the
|
34 |
+
* preserved comments, and the comments will be surrounded by
|
35 |
+
* Minify_CommentPreserver::$preprend and Minify_CommentPreserver::$append.
|
36 |
+
*
|
37 |
+
* @param string $content
|
38 |
+
* @param callback $processor function
|
39 |
+
* @param array $args array of extra arguments to pass to the processor
|
40 |
+
* function (default = array())
|
41 |
+
* @return string
|
42 |
+
*/
|
43 |
+
public static function process($content, $processor, $args = array())
|
44 |
+
{
|
45 |
+
$ret = '';
|
46 |
+
while (true) {
|
47 |
+
list($beforeComment, $comment, $afterComment) = self::_nextComment($content);
|
48 |
+
if ('' !== $beforeComment) {
|
49 |
+
$callArgs = $args;
|
50 |
+
array_unshift($callArgs, $beforeComment);
|
51 |
+
$ret .= call_user_func_array($processor, $callArgs);
|
52 |
+
}
|
53 |
+
if (false === $comment) {
|
54 |
+
break;
|
55 |
+
}
|
56 |
+
$ret .= $comment;
|
57 |
+
$content = $afterComment;
|
58 |
+
}
|
59 |
+
return $ret;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Extract comments that YUI Compressor preserves.
|
64 |
+
*
|
65 |
+
* @param string $in input
|
66 |
+
*
|
67 |
+
* @return array 3 elements are returned. If a YUI comment is found, the
|
68 |
+
* 2nd element is the comment and the 1st and 2nd are the surrounding
|
69 |
+
* strings. If no comment is found, the entire string is returned as the
|
70 |
+
* 1st element and the other two are false.
|
71 |
+
*/
|
72 |
+
private static function _nextComment($in)
|
73 |
+
{
|
74 |
+
if (
|
75 |
+
false === ($start = strpos($in, '/*!'))
|
76 |
+
|| false === ($end = strpos($in, '*/', $start + 3))
|
77 |
+
) {
|
78 |
+
return array($in, false, false);
|
79 |
+
}
|
80 |
+
$ret = array(
|
81 |
+
substr($in, 0, $start)
|
82 |
+
,self::$prepend . '/*' . substr($in, $start + 3, $end - $start - 1) . self::$append
|
83 |
+
);
|
84 |
+
$endChars = (strlen($in) - $end - 2);
|
85 |
+
$ret[] = (0 === $endChars)
|
86 |
+
? ''
|
87 |
+
: substr($in, -$endChars);
|
88 |
+
return $ret;
|
89 |
+
}
|
90 |
+
}
|
includes/ImportProcessor.php
ADDED
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Minify_ImportProcessor
|
4 |
+
* @package Minify
|
5 |
+
*/
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Linearize a CSS/JS file by including content specified by CSS import
|
9 |
+
* declarations. In CSS files, relative URIs are fixed.
|
10 |
+
*
|
11 |
+
* @imports will be processed regardless of where they appear in the source
|
12 |
+
* files; i.e. @imports commented out or in string content will still be
|
13 |
+
* processed!
|
14 |
+
*
|
15 |
+
* This has a unit test but should be considered "experimental".
|
16 |
+
*
|
17 |
+
* @package Minify
|
18 |
+
* @author Stephen Clay <steve@mrclay.org>
|
19 |
+
*/
|
20 |
+
class Minify_ImportProcessor {
|
21 |
+
|
22 |
+
public static $filesIncluded = array();
|
23 |
+
|
24 |
+
public static function process($file)
|
25 |
+
{
|
26 |
+
self::$filesIncluded = array();
|
27 |
+
self::$_isCss = (strtolower(substr($file, -4)) === '.css');
|
28 |
+
$obj = new Minify_ImportProcessor(dirname($file));
|
29 |
+
return $obj->_getContent($file);
|
30 |
+
}
|
31 |
+
|
32 |
+
// allows callback funcs to know the current directory
|
33 |
+
private $_currentDir = null;
|
34 |
+
|
35 |
+
// allows _importCB to write the fetched content back to the obj
|
36 |
+
private $_importedContent = '';
|
37 |
+
|
38 |
+
private static $_isCss = null;
|
39 |
+
|
40 |
+
private function __construct($currentDir)
|
41 |
+
{
|
42 |
+
$this->_currentDir = $currentDir;
|
43 |
+
}
|
44 |
+
|
45 |
+
private function _getContent($file)
|
46 |
+
{
|
47 |
+
$file = realpath($file);
|
48 |
+
if (! $file
|
49 |
+
|| in_array($file, self::$filesIncluded)
|
50 |
+
|| false === ($content = @file_get_contents($file))
|
51 |
+
) {
|
52 |
+
// file missing, already included, or failed read
|
53 |
+
return '';
|
54 |
+
}
|
55 |
+
self::$filesIncluded[] = realpath($file);
|
56 |
+
$this->_currentDir = dirname($file);
|
57 |
+
|
58 |
+
// remove UTF-8 BOM if present
|
59 |
+
if (pack("CCC",0xef,0xbb,0xbf) === substr($content, 0, 3)) {
|
60 |
+
$content = substr($content, 3);
|
61 |
+
}
|
62 |
+
// ensure uniform EOLs
|
63 |
+
$content = str_replace("\r\n", "\n", $content);
|
64 |
+
|
65 |
+
// process @imports
|
66 |
+
$content = preg_replace_callback(
|
67 |
+
'/
|
68 |
+
@import\\s+
|
69 |
+
(?:url\\(\\s*)? # maybe url(
|
70 |
+
[\'"]? # maybe quote
|
71 |
+
(.*?) # 1 = URI
|
72 |
+
[\'"]? # maybe end quote
|
73 |
+
(?:\\s*\\))? # maybe )
|
74 |
+
([a-zA-Z,\\s]*)? # 2 = media list
|
75 |
+
; # end token
|
76 |
+
/x'
|
77 |
+
,array($this, '_importCB')
|
78 |
+
,$content
|
79 |
+
);
|
80 |
+
|
81 |
+
if (self::$_isCss) {
|
82 |
+
// rewrite remaining relative URIs
|
83 |
+
$content = preg_replace_callback(
|
84 |
+
'/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
85 |
+
,array($this, '_urlCB')
|
86 |
+
,$content
|
87 |
+
);
|
88 |
+
}
|
89 |
+
|
90 |
+
return $this->_importedContent . $content;
|
91 |
+
}
|
92 |
+
|
93 |
+
private function _importCB($m)
|
94 |
+
{
|
95 |
+
$url = $m[1];
|
96 |
+
$mediaList = preg_replace('/\\s+/', '', $m[2]);
|
97 |
+
|
98 |
+
if (strpos($url, '://') > 0) {
|
99 |
+
// protocol, leave in place for CSS, comment for JS
|
100 |
+
return self::$_isCss
|
101 |
+
? $m[0]
|
102 |
+
: "/* Minify_ImportProcessor will not include remote content */";
|
103 |
+
}
|
104 |
+
if ('/' === $url[0]) {
|
105 |
+
// protocol-relative or root path
|
106 |
+
$url = ltrim($url, '/');
|
107 |
+
$file = realpath($_SERVER['DOCUMENT_ROOT']) . DIRECTORY_SEPARATOR
|
108 |
+
. strtr($url, '/', DIRECTORY_SEPARATOR);
|
109 |
+
} else {
|
110 |
+
// relative to current path
|
111 |
+
$file = $this->_currentDir . DIRECTORY_SEPARATOR
|
112 |
+
. strtr($url, '/', DIRECTORY_SEPARATOR);
|
113 |
+
}
|
114 |
+
$obj = new Minify_ImportProcessor(dirname($file));
|
115 |
+
$content = $obj->_getContent($file);
|
116 |
+
if ('' === $content) {
|
117 |
+
// failed. leave in place for CSS, comment for JS
|
118 |
+
return self::$_isCss
|
119 |
+
? $m[0]
|
120 |
+
: "/* Minify_ImportProcessor could not fetch '{$file}' */";;
|
121 |
+
}
|
122 |
+
return (!self::$_isCss || preg_match('@(?:^$|\\ball\\b)@', $mediaList))
|
123 |
+
? $content
|
124 |
+
: "@media {$mediaList} {\n{$content}\n}\n";
|
125 |
+
}
|
126 |
+
|
127 |
+
private function _urlCB($m)
|
128 |
+
{
|
129 |
+
// $m[1] is either quoted or not
|
130 |
+
$quote = ($m[1][0] === "'" || $m[1][0] === '"')
|
131 |
+
? $m[1][0]
|
132 |
+
: '';
|
133 |
+
$url = ($quote === '')
|
134 |
+
? $m[1]
|
135 |
+
: substr($m[1], 1, strlen($m[1]) - 2);
|
136 |
+
if ('/' !== $url[0]) {
|
137 |
+
if (strpos($url, '//') > 0) {
|
138 |
+
// probably starts with protocol, do not alter
|
139 |
+
} else {
|
140 |
+
// prepend path with current dir separator (OS-independent)
|
141 |
+
$path = $this->_currentDir
|
142 |
+
. DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR);
|
143 |
+
// strip doc root
|
144 |
+
$path = substr($path, strlen(realpath($_SERVER['DOCUMENT_ROOT'])));
|
145 |
+
// fix to absolute URL
|
146 |
+
$url = strtr($path, '/\\', '//');
|
147 |
+
// remove /./ and /../ where possible
|
148 |
+
$url = str_replace('/./', '/', $url);
|
149 |
+
// inspired by patch from Oleg Cherniy
|
150 |
+
do {
|
151 |
+
$url = preg_replace('@/[^/]+/\\.\\./@', '/', $url, 1, $changed);
|
152 |
+
} while ($changed);
|
153 |
+
}
|
154 |
+
}
|
155 |
+
return "url({$quote}{$url}{$quote})";
|
156 |
+
}
|
157 |
+
}
|
includes/JSMin.php
ADDED
@@ -0,0 +1,314 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* jsmin.php - PHP implementation of Douglas Crockford's JSMin.
|
4 |
+
*
|
5 |
+
* This is a direct port of jsmin.c to PHP with a few PHP performance tweaks and
|
6 |
+
* modifications to preserve some comments (see below). Also, rather than using
|
7 |
+
* stdin/stdout, JSMin::minify() accepts a string as input and returns another
|
8 |
+
* string as output.
|
9 |
+
*
|
10 |
+
* Comments containing IE conditional compilation are preserved, as are multi-line
|
11 |
+
* comments that begin with "/*!" (for documentation purposes). In the latter case
|
12 |
+
* newlines are inserted around the comment to enhance readability.
|
13 |
+
*
|
14 |
+
* PHP 5 or higher is required.
|
15 |
+
*
|
16 |
+
* Permission is hereby granted to use this version of the library under the
|
17 |
+
* same terms as jsmin.c, which has the following license:
|
18 |
+
*
|
19 |
+
* --
|
20 |
+
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
21 |
+
*
|
22 |
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
23 |
+
* this software and associated documentation files (the "Software"), to deal in
|
24 |
+
* the Software without restriction, including without limitation the rights to
|
25 |
+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
26 |
+
* of the Software, and to permit persons to whom the Software is furnished to do
|
27 |
+
* so, subject to the following conditions:
|
28 |
+
*
|
29 |
+
* The above copyright notice and this permission notice shall be included in all
|
30 |
+
* copies or substantial portions of the Software.
|
31 |
+
*
|
32 |
+
* The Software shall be used for Good, not Evil.
|
33 |
+
*
|
34 |
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
35 |
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
36 |
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
37 |
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
38 |
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
39 |
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
40 |
+
* SOFTWARE.
|
41 |
+
* --
|
42 |
+
*
|
43 |
+
* @package JSMin
|
44 |
+
* @author Ryan Grove <ryan@wonko.com> (PHP port)
|
45 |
+
* @author Steve Clay <steve@mrclay.org> (modifications + cleanup)
|
46 |
+
* @author Andrea Giammarchi <http://www.3site.eu> (spaceBeforeRegExp)
|
47 |
+
* @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
|
48 |
+
* @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
|
49 |
+
* @license http://opensource.org/licenses/mit-license.php MIT License
|
50 |
+
* @link http://code.google.com/p/jsmin-php/
|
51 |
+
*/
|
52 |
+
|
53 |
+
class JSMin {
|
54 |
+
const ORD_LF = 10;
|
55 |
+
const ORD_SPACE = 32;
|
56 |
+
const ACTION_KEEP_A = 1;
|
57 |
+
const ACTION_DELETE_A = 2;
|
58 |
+
const ACTION_DELETE_A_B = 3;
|
59 |
+
|
60 |
+
protected $a = "\n";
|
61 |
+
protected $b = '';
|
62 |
+
protected $input = '';
|
63 |
+
protected $inputIndex = 0;
|
64 |
+
protected $inputLength = 0;
|
65 |
+
protected $lookAhead = null;
|
66 |
+
protected $output = '';
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Minify Javascript
|
70 |
+
*
|
71 |
+
* @param string $js Javascript to be minified
|
72 |
+
* @return string
|
73 |
+
*/
|
74 |
+
public static function minify($js)
|
75 |
+
{
|
76 |
+
$jsmin = new JSMin($js);
|
77 |
+
return $jsmin->min();
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Setup process
|
82 |
+
*/
|
83 |
+
public function __construct($input)
|
84 |
+
{
|
85 |
+
$this->input = str_replace("\r\n", "\n", $input);
|
86 |
+
$this->inputLength = strlen($this->input);
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Perform minification, return result
|
91 |
+
*/
|
92 |
+
public function min()
|
93 |
+
{
|
94 |
+
if ($this->output !== '') { // min already run
|
95 |
+
return $this->output;
|
96 |
+
}
|
97 |
+
$this->action(self::ACTION_DELETE_A_B);
|
98 |
+
|
99 |
+
while ($this->a !== null) {
|
100 |
+
// determine next command
|
101 |
+
$command = self::ACTION_KEEP_A; // default
|
102 |
+
if ($this->a === ' ') {
|
103 |
+
if (! $this->isAlphaNum($this->b)) {
|
104 |
+
$command = self::ACTION_DELETE_A;
|
105 |
+
}
|
106 |
+
} elseif ($this->a === "\n") {
|
107 |
+
if ($this->b === ' ') {
|
108 |
+
$command = self::ACTION_DELETE_A_B;
|
109 |
+
} elseif (false === strpos('{[(+-', $this->b)
|
110 |
+
&& ! $this->isAlphaNum($this->b)) {
|
111 |
+
$command = self::ACTION_DELETE_A;
|
112 |
+
}
|
113 |
+
} elseif (! $this->isAlphaNum($this->a)) {
|
114 |
+
if ($this->b === ' '
|
115 |
+
|| ($this->b === "\n"
|
116 |
+
&& (false === strpos('}])+-"\'', $this->a)))) {
|
117 |
+
$command = self::ACTION_DELETE_A_B;
|
118 |
+
}
|
119 |
+
}
|
120 |
+
$this->action($command);
|
121 |
+
}
|
122 |
+
$this->output = trim($this->output);
|
123 |
+
return $this->output;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* ACTION_KEEP_A = Output A. Copy B to A. Get the next B.
|
128 |
+
* ACTION_DELETE_A = Copy B to A. Get the next B.
|
129 |
+
* ACTION_DELETE_A_B = Get the next B.
|
130 |
+
*/
|
131 |
+
protected function action($command)
|
132 |
+
{
|
133 |
+
switch ($command) {
|
134 |
+
case self::ACTION_KEEP_A:
|
135 |
+
$this->output .= $this->a;
|
136 |
+
// fallthrough
|
137 |
+
case self::ACTION_DELETE_A:
|
138 |
+
$this->a = $this->b;
|
139 |
+
if ($this->a === "'" || $this->a === '"') { // string literal
|
140 |
+
$str = $this->a; // in case needed for exception
|
141 |
+
while (true) {
|
142 |
+
$this->output .= $this->a;
|
143 |
+
$this->a = $this->get();
|
144 |
+
if ($this->a === $this->b) { // end quote
|
145 |
+
break;
|
146 |
+
}
|
147 |
+
if (ord($this->a) <= self::ORD_LF) {
|
148 |
+
throw new JSMin_UnterminatedStringException(
|
149 |
+
'Unterminated String: ' . var_export($str, true));
|
150 |
+
}
|
151 |
+
$str .= $this->a;
|
152 |
+
if ($this->a === '\\') {
|
153 |
+
$this->output .= $this->a;
|
154 |
+
$this->a = $this->get();
|
155 |
+
$str .= $this->a;
|
156 |
+
}
|
157 |
+
}
|
158 |
+
}
|
159 |
+
// fallthrough
|
160 |
+
case self::ACTION_DELETE_A_B:
|
161 |
+
$this->b = $this->next();
|
162 |
+
if ($this->b === '/' && $this->isRegexpLiteral()) { // RegExp literal
|
163 |
+
$this->output .= $this->a . $this->b;
|
164 |
+
$pattern = '/'; // in case needed for exception
|
165 |
+
while (true) {
|
166 |
+
$this->a = $this->get();
|
167 |
+
$pattern .= $this->a;
|
168 |
+
if ($this->a === '/') { // end pattern
|
169 |
+
break; // while (true)
|
170 |
+
} elseif ($this->a === '\\') {
|
171 |
+
$this->output .= $this->a;
|
172 |
+
$this->a = $this->get();
|
173 |
+
$pattern .= $this->a;
|
174 |
+
} elseif (ord($this->a) <= self::ORD_LF) {
|
175 |
+
throw new JSMin_UnterminatedRegExpException(
|
176 |
+
'Unterminated RegExp: '. var_export($pattern, true));
|
177 |
+
}
|
178 |
+
$this->output .= $this->a;
|
179 |
+
}
|
180 |
+
$this->b = $this->next();
|
181 |
+
}
|
182 |
+
// end case ACTION_DELETE_A_B
|
183 |
+
}
|
184 |
+
}
|
185 |
+
|
186 |
+
protected function isRegexpLiteral()
|
187 |
+
{
|
188 |
+
if (false !== strpos("\n{;(,=:[!&|?", $this->a)) { // we aren't dividing
|
189 |
+
return true;
|
190 |
+
}
|
191 |
+
if (' ' === $this->a) {
|
192 |
+
$length = strlen($this->output);
|
193 |
+
if ($length < 2) { // weird edge case
|
194 |
+
return true;
|
195 |
+
}
|
196 |
+
// you can't divide a keyword
|
197 |
+
if (preg_match('/(?:case|else|in|return|typeof)$/', $this->output, $m)) {
|
198 |
+
if ($this->output === $m[0]) { // odd but could happen
|
199 |
+
return true;
|
200 |
+
}
|
201 |
+
// make sure it's a keyword, not end of an identifier
|
202 |
+
$charBeforeKeyword = substr($this->output, $length - strlen($m[0]) - 1, 1);
|
203 |
+
if (! $this->isAlphaNum($charBeforeKeyword)) {
|
204 |
+
return true;
|
205 |
+
}
|
206 |
+
}
|
207 |
+
}
|
208 |
+
return false;
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Get next char. Convert ctrl char to space.
|
213 |
+
*/
|
214 |
+
protected function get()
|
215 |
+
{
|
216 |
+
$c = $this->lookAhead;
|
217 |
+
$this->lookAhead = null;
|
218 |
+
if ($c === null) {
|
219 |
+
if ($this->inputIndex < $this->inputLength) {
|
220 |
+
$c = $this->input[$this->inputIndex];
|
221 |
+
$this->inputIndex += 1;
|
222 |
+
} else {
|
223 |
+
return null;
|
224 |
+
}
|
225 |
+
}
|
226 |
+
if ($c === "\r" || $c === "\n") {
|
227 |
+
return "\n";
|
228 |
+
}
|
229 |
+
if (ord($c) < self::ORD_SPACE) { // control char
|
230 |
+
return ' ';
|
231 |
+
}
|
232 |
+
return $c;
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Get next char. If is ctrl character, translate to a space or newline.
|
237 |
+
*/
|
238 |
+
protected function peek()
|
239 |
+
{
|
240 |
+
$this->lookAhead = $this->get();
|
241 |
+
return $this->lookAhead;
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Is $c a letter, digit, underscore, dollar sign, escape, or non-ASCII?
|
246 |
+
*/
|
247 |
+
protected function isAlphaNum($c)
|
248 |
+
{
|
249 |
+
return (preg_match('/^[0-9a-zA-Z_\\$\\\\]$/', $c) || ord($c) > 126);
|
250 |
+
}
|
251 |
+
|
252 |
+
protected function singleLineComment()
|
253 |
+
{
|
254 |
+
$comment = '';
|
255 |
+
while (true) {
|
256 |
+
$get = $this->get();
|
257 |
+
$comment .= $get;
|
258 |
+
if (ord($get) <= self::ORD_LF) { // EOL reached
|
259 |
+
// if IE conditional comment
|
260 |
+
if (preg_match('/^\\/@(?:cc_on|if|elif|else|end)\\b/', $comment)) {
|
261 |
+
return "/{$comment}";
|
262 |
+
}
|
263 |
+
return $get;
|
264 |
+
}
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
+
protected function multipleLineComment()
|
269 |
+
{
|
270 |
+
$this->get();
|
271 |
+
$comment = '';
|
272 |
+
while (true) {
|
273 |
+
$get = $this->get();
|
274 |
+
if ($get === '*') {
|
275 |
+
if ($this->peek() === '/') { // end of comment reached
|
276 |
+
$this->get();
|
277 |
+
// if comment preserved by YUI Compressor
|
278 |
+
if (0 === strpos($comment, '!')) {
|
279 |
+
return "\n/*" . substr($comment, 1) . "*/\n";
|
280 |
+
}
|
281 |
+
// if IE conditional comment
|
282 |
+
if (preg_match('/^@(?:cc_on|if|elif|else|end)\\b/', $comment)) {
|
283 |
+
return "/*{$comment}*/";
|
284 |
+
}
|
285 |
+
return ' ';
|
286 |
+
}
|
287 |
+
} elseif ($get === null) {
|
288 |
+
throw new JSMin_UnterminatedCommentException('Unterminated Comment: ' . var_export('/*' . $comment, true));
|
289 |
+
}
|
290 |
+
$comment .= $get;
|
291 |
+
}
|
292 |
+
}
|
293 |
+
|
294 |
+
/**
|
295 |
+
* Get the next character, skipping over comments.
|
296 |
+
* Some comments may be preserved.
|
297 |
+
*/
|
298 |
+
protected function next()
|
299 |
+
{
|
300 |
+
$get = $this->get();
|
301 |
+
if ($get !== '/') {
|
302 |
+
return $get;
|
303 |
+
}
|
304 |
+
switch ($this->peek()) {
|
305 |
+
case '/': return $this->singleLineComment();
|
306 |
+
case '*': return $this->multipleLineComment();
|
307 |
+
default: return $get;
|
308 |
+
}
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
+
class JSMin_UnterminatedStringException extends Exception {}
|
313 |
+
class JSMin_UnterminatedCommentException extends Exception {}
|
314 |
+
class JSMin_UnterminatedRegExpException extends Exception {}
|
includes/common-controller.php
CHANGED
@@ -195,7 +195,7 @@ class wokController {
|
|
195 |
return $is_active;
|
196 |
}
|
197 |
|
198 |
-
//
|
199 |
function isKtai(){
|
200 |
return (
|
201 |
(function_exists('is_mobile') && is_mobile()) ||
|
@@ -203,6 +203,24 @@ class wokController {
|
|
203 |
);
|
204 |
}
|
205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
// Output Javascript
|
207 |
function writeScript($out = '', $place = 'head') {
|
208 |
global $wok_script_manager;
|
195 |
return $is_active;
|
196 |
}
|
197 |
|
198 |
+
// Is Ktai Access ?
|
199 |
function isKtai(){
|
200 |
return (
|
201 |
(function_exists('is_mobile') && is_mobile()) ||
|
203 |
);
|
204 |
}
|
205 |
|
206 |
+
// Is mobile access?
|
207 |
+
function isMobile() {
|
208 |
+
$is_mobile = $this->isKtai();
|
209 |
+
|
210 |
+
if ( !$is_mobile && function_exists('bnc_is_iphone') ) {
|
211 |
+
global $wptouch_plugin;
|
212 |
+
|
213 |
+
$is_mobile = bnc_is_iphone();
|
214 |
+
if ( $is_mobile && isset($wptouch_plugin) ) {
|
215 |
+
$is_mobile = isset($wptouch_plugin->desired_view)
|
216 |
+
? $wptouch_plugin->desired_view == 'mobile'
|
217 |
+
: true;
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
return ($is_mobile);
|
222 |
+
}
|
223 |
+
|
224 |
// Output Javascript
|
225 |
function writeScript($out = '', $place = 'head') {
|
226 |
global $wok_script_manager;
|
includes/jsmin-1.1.1.php
DELETED
@@ -1,291 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* jsmin.php - PHP implementation of Douglas Crockford's JSMin.
|
4 |
-
*
|
5 |
-
* This is pretty much a direct port of jsmin.c to PHP with just a few
|
6 |
-
* PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
|
7 |
-
* outputs to stdout, this library accepts a string as input and returns another
|
8 |
-
* string as output.
|
9 |
-
*
|
10 |
-
* PHP 5 or higher is required.
|
11 |
-
*
|
12 |
-
* Permission is hereby granted to use this version of the library under the
|
13 |
-
* same terms as jsmin.c, which has the following license:
|
14 |
-
*
|
15 |
-
* --
|
16 |
-
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
17 |
-
*
|
18 |
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
19 |
-
* this software and associated documentation files (the "Software"), to deal in
|
20 |
-
* the Software without restriction, including without limitation the rights to
|
21 |
-
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
22 |
-
* of the Software, and to permit persons to whom the Software is furnished to do
|
23 |
-
* so, subject to the following conditions:
|
24 |
-
*
|
25 |
-
* The above copyright notice and this permission notice shall be included in all
|
26 |
-
* copies or substantial portions of the Software.
|
27 |
-
*
|
28 |
-
* The Software shall be used for Good, not Evil.
|
29 |
-
*
|
30 |
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
31 |
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
32 |
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
33 |
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
34 |
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
35 |
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
36 |
-
* SOFTWARE.
|
37 |
-
* --
|
38 |
-
*
|
39 |
-
* @package JSMin
|
40 |
-
* @author Ryan Grove <ryan@wonko.com>
|
41 |
-
* @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
|
42 |
-
* @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
|
43 |
-
* @license http://opensource.org/licenses/mit-license.php MIT License
|
44 |
-
* @version 1.1.1 (2008-03-02)
|
45 |
-
* @link http://code.google.com/p/jsmin-php/
|
46 |
-
*/
|
47 |
-
|
48 |
-
class JSMin {
|
49 |
-
const ORD_LF = 10;
|
50 |
-
const ORD_SPACE = 32;
|
51 |
-
|
52 |
-
protected $a = '';
|
53 |
-
protected $b = '';
|
54 |
-
protected $input = '';
|
55 |
-
protected $inputIndex = 0;
|
56 |
-
protected $inputLength = 0;
|
57 |
-
protected $lookAhead = null;
|
58 |
-
protected $output = '';
|
59 |
-
|
60 |
-
// -- Public Static Methods --------------------------------------------------
|
61 |
-
|
62 |
-
public static function minify($js) {
|
63 |
-
$jsmin = new JSMin($js);
|
64 |
-
return $jsmin->min();
|
65 |
-
}
|
66 |
-
|
67 |
-
// -- Public Instance Methods ------------------------------------------------
|
68 |
-
|
69 |
-
public function __construct($input) {
|
70 |
-
$this->input = str_replace("\r\n", "\n", $input);
|
71 |
-
$this->inputLength = strlen($this->input);
|
72 |
-
}
|
73 |
-
|
74 |
-
// -- Protected Instance Methods ---------------------------------------------
|
75 |
-
|
76 |
-
protected function action($d) {
|
77 |
-
switch($d) {
|
78 |
-
case 1:
|
79 |
-
$this->output .= $this->a;
|
80 |
-
|
81 |
-
case 2:
|
82 |
-
$this->a = $this->b;
|
83 |
-
|
84 |
-
if ($this->a === "'" || $this->a === '"') {
|
85 |
-
for (;;) {
|
86 |
-
$this->output .= $this->a;
|
87 |
-
$this->a = $this->get();
|
88 |
-
|
89 |
-
if ($this->a === $this->b) {
|
90 |
-
break;
|
91 |
-
}
|
92 |
-
|
93 |
-
if (ord($this->a) <= self::ORD_LF) {
|
94 |
-
throw new JSMinException('Unterminated string literal.');
|
95 |
-
}
|
96 |
-
|
97 |
-
if ($this->a === '\\') {
|
98 |
-
$this->output .= $this->a;
|
99 |
-
$this->a = $this->get();
|
100 |
-
}
|
101 |
-
}
|
102 |
-
}
|
103 |
-
|
104 |
-
case 3:
|
105 |
-
$this->b = $this->next();
|
106 |
-
|
107 |
-
if ($this->b === '/' && (
|
108 |
-
$this->a === '(' || $this->a === ',' || $this->a === '=' ||
|
109 |
-
$this->a === ':' || $this->a === '[' || $this->a === '!' ||
|
110 |
-
$this->a === '&' || $this->a === '|' || $this->a === '?')) {
|
111 |
-
|
112 |
-
$this->output .= $this->a . $this->b;
|
113 |
-
|
114 |
-
for (;;) {
|
115 |
-
$this->a = $this->get();
|
116 |
-
|
117 |
-
if ($this->a === '/') {
|
118 |
-
break;
|
119 |
-
} elseif ($this->a === '\\') {
|
120 |
-
$this->output .= $this->a;
|
121 |
-
$this->a = $this->get();
|
122 |
-
} elseif (ord($this->a) <= self::ORD_LF) {
|
123 |
-
throw new JSMinException('Unterminated regular expression '.
|
124 |
-
'literal.');
|
125 |
-
}
|
126 |
-
|
127 |
-
$this->output .= $this->a;
|
128 |
-
}
|
129 |
-
|
130 |
-
$this->b = $this->next();
|
131 |
-
}
|
132 |
-
}
|
133 |
-
}
|
134 |
-
|
135 |
-
protected function get() {
|
136 |
-
$c = $this->lookAhead;
|
137 |
-
$this->lookAhead = null;
|
138 |
-
|
139 |
-
if ($c === null) {
|
140 |
-
if ($this->inputIndex < $this->inputLength) {
|
141 |
-
$c = $this->input[$this->inputIndex];
|
142 |
-
$this->inputIndex += 1;
|
143 |
-
} else {
|
144 |
-
$c = null;
|
145 |
-
}
|
146 |
-
}
|
147 |
-
|
148 |
-
if ($c === "\r") {
|
149 |
-
return "\n";
|
150 |
-
}
|
151 |
-
|
152 |
-
if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
|
153 |
-
return $c;
|
154 |
-
}
|
155 |
-
|
156 |
-
return ' ';
|
157 |
-
}
|
158 |
-
|
159 |
-
protected function isAlphaNum($c) {
|
160 |
-
return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
|
161 |
-
}
|
162 |
-
|
163 |
-
protected function min() {
|
164 |
-
$this->a = "\n";
|
165 |
-
$this->action(3);
|
166 |
-
|
167 |
-
while ($this->a !== null) {
|
168 |
-
switch ($this->a) {
|
169 |
-
case ' ':
|
170 |
-
if ($this->isAlphaNum($this->b)) {
|
171 |
-
$this->action(1);
|
172 |
-
} else {
|
173 |
-
$this->action(2);
|
174 |
-
}
|
175 |
-
break;
|
176 |
-
|
177 |
-
case "\n":
|
178 |
-
switch ($this->b) {
|
179 |
-
case '{':
|
180 |
-
case '[':
|
181 |
-
case '(':
|
182 |
-
case '+':
|
183 |
-
case '-':
|
184 |
-
$this->action(1);
|
185 |
-
break;
|
186 |
-
|
187 |
-
case ' ':
|
188 |
-
$this->action(3);
|
189 |
-
break;
|
190 |
-
|
191 |
-
default:
|
192 |
-
if ($this->isAlphaNum($this->b)) {
|
193 |
-
$this->action(1);
|
194 |
-
}
|
195 |
-
else {
|
196 |
-
$this->action(2);
|
197 |
-
}
|
198 |
-
}
|
199 |
-
break;
|
200 |
-
|
201 |
-
default:
|
202 |
-
switch ($this->b) {
|
203 |
-
case ' ':
|
204 |
-
if ($this->isAlphaNum($this->a)) {
|
205 |
-
$this->action(1);
|
206 |
-
break;
|
207 |
-
}
|
208 |
-
|
209 |
-
$this->action(3);
|
210 |
-
break;
|
211 |
-
|
212 |
-
case "\n":
|
213 |
-
switch ($this->a) {
|
214 |
-
case '}':
|
215 |
-
case ']':
|
216 |
-
case ')':
|
217 |
-
case '+':
|
218 |
-
case '-':
|
219 |
-
case '"':
|
220 |
-
case "'":
|
221 |
-
$this->action(1);
|
222 |
-
break;
|
223 |
-
|
224 |
-
default:
|
225 |
-
if ($this->isAlphaNum($this->a)) {
|
226 |
-
$this->action(1);
|
227 |
-
}
|
228 |
-
else {
|
229 |
-
$this->action(3);
|
230 |
-
}
|
231 |
-
}
|
232 |
-
break;
|
233 |
-
|
234 |
-
default:
|
235 |
-
$this->action(1);
|
236 |
-
break;
|
237 |
-
}
|
238 |
-
}
|
239 |
-
}
|
240 |
-
|
241 |
-
return $this->output;
|
242 |
-
}
|
243 |
-
|
244 |
-
protected function next() {
|
245 |
-
$c = $this->get();
|
246 |
-
|
247 |
-
if ($c === '/') {
|
248 |
-
switch($this->peek()) {
|
249 |
-
case '/':
|
250 |
-
for (;;) {
|
251 |
-
$c = $this->get();
|
252 |
-
|
253 |
-
if (ord($c) <= self::ORD_LF) {
|
254 |
-
return $c;
|
255 |
-
}
|
256 |
-
}
|
257 |
-
|
258 |
-
case '*':
|
259 |
-
$this->get();
|
260 |
-
|
261 |
-
for (;;) {
|
262 |
-
switch($this->get()) {
|
263 |
-
case '*':
|
264 |
-
if ($this->peek() === '/') {
|
265 |
-
$this->get();
|
266 |
-
return ' ';
|
267 |
-
}
|
268 |
-
break;
|
269 |
-
|
270 |
-
case null:
|
271 |
-
throw new JSMinException('Unterminated comment.');
|
272 |
-
}
|
273 |
-
}
|
274 |
-
|
275 |
-
default:
|
276 |
-
return $c;
|
277 |
-
}
|
278 |
-
}
|
279 |
-
|
280 |
-
return $c;
|
281 |
-
}
|
282 |
-
|
283 |
-
protected function peek() {
|
284 |
-
$this->lookAhead = $this->get();
|
285 |
-
return $this->lookAhead;
|
286 |
-
}
|
287 |
-
}
|
288 |
-
|
289 |
-
// -- Exceptions ---------------------------------------------------------------
|
290 |
-
class JSMinException extends Exception {}
|
291 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
languages/head-cleaner-nl_NL.mo
ADDED
Binary file
|
languages/head-cleaner-nl_NL.po
ADDED
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
msgid ""
|
2 |
+
msgstr ""
|
3 |
+
"Project-Id-Version: Head Cleaner\n"
|
4 |
+
"Report-Msgid-Bugs-To: \n"
|
5 |
+
"POT-Creation-Date: 2009-03-09 17:56+0900\n"
|
6 |
+
"PO-Revision-Date: 2010-04-29 21:07+0100\n"
|
7 |
+
"Last-Translator: WordPressPluginGuide.com <info@wppg.me>\n"
|
8 |
+
"Language-Team: http://WPPG.me <info@wppg.me>\n"
|
9 |
+
"MIME-Version: 1.0\n"
|
10 |
+
"Content-Type: text/plain; charset=utf-8\n"
|
11 |
+
"Content-Transfer-Encoding: 8bit\n"
|
12 |
+
"X-Poedit-Language: Dutch\n"
|
13 |
+
"X-Poedit-Country: NETHERLANDS\n"
|
14 |
+
"X-Poedit-SourceCharset: utf-8\n"
|
15 |
+
"X-Poedit-KeywordsList: __;_e\n"
|
16 |
+
"X-Poedit-Basepath: .\n"
|
17 |
+
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
18 |
+
"X-Poedit-SearchPath-0: ..\n"
|
19 |
+
|
20 |
+
# description
|
21 |
+
msgid "Cleaning tags from your WordPress header and footer."
|
22 |
+
msgstr "Verwijderen van tags van je WordPress kop- en voettekst."
|
23 |
+
|
24 |
+
#: ../head-cleaner.php:1405
|
25 |
+
msgid "Head Cleaner"
|
26 |
+
msgstr "Head Cleaner"
|
27 |
+
|
28 |
+
#: ../head-cleaner.php:1414
|
29 |
+
#: ../includes/common-controller.php:166
|
30 |
+
msgid "Settings"
|
31 |
+
msgstr "Instellingen"
|
32 |
+
|
33 |
+
#: ../head-cleaner.php:1501
|
34 |
+
#: ../head-cleaner.php:1511
|
35 |
+
#: ../head-cleaner.php:1521
|
36 |
+
msgid "Done!"
|
37 |
+
msgstr "Klaar!"
|
38 |
+
|
39 |
+
#: ../head-cleaner.php:1533
|
40 |
+
msgid "Head Cleaner Options"
|
41 |
+
msgstr "Head Cleaner Opties"
|
42 |
+
|
43 |
+
#: ../head-cleaner.php:1541
|
44 |
+
msgid "CSS and JavaScript are cached on the server."
|
45 |
+
msgstr "CSS en JavaScript worden gecached van de server."
|
46 |
+
|
47 |
+
#: ../head-cleaner.php:1545
|
48 |
+
msgid "Put JavaScripts at the Bottom."
|
49 |
+
msgstr "Plaats JavaScripts aan de onderkant."
|
50 |
+
|
51 |
+
#: ../head-cleaner.php:1549
|
52 |
+
msgid "CSS and JS are dynamically generated."
|
53 |
+
msgstr "CSS en JS worden dynamisch gegenereerd."
|
54 |
+
|
55 |
+
#: ../head-cleaner.php:1557
|
56 |
+
msgid "Two or more CSS is combined."
|
57 |
+
msgstr "Twee of meer CSS worden gecombineerd."
|
58 |
+
|
59 |
+
#: ../head-cleaner.php:1561
|
60 |
+
msgid "CSS is optimized."
|
61 |
+
msgstr "CSS is geoptimaliseerd."
|
62 |
+
|
63 |
+
#: ../head-cleaner.php:1564
|
64 |
+
msgid "Default media attribute applied to CSS."
|
65 |
+
msgstr "Standaard media attributen toegepast op CSS."
|
66 |
+
|
67 |
+
#: ../head-cleaner.php:1573
|
68 |
+
msgid "Two or more JavaScript is combined."
|
69 |
+
msgstr "Twee of meer JavaScripts zijn gecombineerd."
|
70 |
+
|
71 |
+
#: ../head-cleaner.php:1577
|
72 |
+
msgid "JavaScript is minified."
|
73 |
+
msgstr "JavaScript is geminimaliseerd."
|
74 |
+
|
75 |
+
#: ../head-cleaner.php:1581
|
76 |
+
msgid "Bottom JavaScript is combined, too."
|
77 |
+
msgstr "Het JavaScript aan de onderkant is ook gecombineerd."
|
78 |
+
|
79 |
+
#: ../head-cleaner.php:1589
|
80 |
+
msgid "Remove generator tag."
|
81 |
+
msgstr "Verwijder generator tag."
|
82 |
+
|
83 |
+
#: ../head-cleaner.php:1593
|
84 |
+
msgid "Remove RSD link tag."
|
85 |
+
msgstr "Verwijder RSD link tag."
|
86 |
+
|
87 |
+
#: ../head-cleaner.php:1597
|
88 |
+
msgid "Remove wlwmanifest link tag."
|
89 |
+
msgstr "Verwijder wlwmanifest link tag."
|
90 |
+
|
91 |
+
#: ../head-cleaner.php:1604
|
92 |
+
msgid "Debug mode"
|
93 |
+
msgstr "Debug modus"
|
94 |
+
|
95 |
+
#: ../head-cleaner.php:1617
|
96 |
+
msgid "The CSS optimization settings"
|
97 |
+
msgstr "De CSS optimalisatie instellingen"
|
98 |
+
|
99 |
+
#: ../head-cleaner.php:1619
|
100 |
+
msgid "Compression (code layout):"
|
101 |
+
msgstr "Compressie (code lay-out):"
|
102 |
+
|
103 |
+
#: ../head-cleaner.php:1621
|
104 |
+
msgid "Highest (no readability, smallest size)"
|
105 |
+
msgstr "Hoogste (geen leesbaarheid, kleinste maat)"
|
106 |
+
|
107 |
+
#: ../head-cleaner.php:1622
|
108 |
+
msgid "High (moderate readability, smaller size)"
|
109 |
+
msgstr "Hoog (matige leesbaarheid, kleiner formaat)"
|
110 |
+
|
111 |
+
#: ../head-cleaner.php:1623
|
112 |
+
msgid "Standard (balance between readability and size)"
|
113 |
+
msgstr "Standaard (evenwicht tussen leesbaarheid en grootte)"
|
114 |
+
|
115 |
+
#: ../head-cleaner.php:1624
|
116 |
+
msgid "Low (higher readability)"
|
117 |
+
msgstr "Laag (hogere leesbaarheid)"
|
118 |
+
|
119 |
+
#: ../head-cleaner.php:1627
|
120 |
+
msgid "Optimise shorthands"
|
121 |
+
msgstr "Optimaliseren van snelkoppelingen"
|
122 |
+
|
123 |
+
#: ../head-cleaner.php:1629
|
124 |
+
msgid "All optimisations"
|
125 |
+
msgstr "Alle optimalisaties"
|
126 |
+
|
127 |
+
#: ../head-cleaner.php:1630
|
128 |
+
msgid "Safe optimisations"
|
129 |
+
msgstr "Opslaan optimalisaties"
|
130 |
+
|
131 |
+
#: ../head-cleaner.php:1631
|
132 |
+
msgid "Don't optimise"
|
133 |
+
msgstr "Niet optimaliseren"
|
134 |
+
|
135 |
+
#: ../head-cleaner.php:1636
|
136 |
+
msgid "Compress colors"
|
137 |
+
msgstr "Comprimeren kleuren"
|
138 |
+
|
139 |
+
#: ../head-cleaner.php:1639
|
140 |
+
msgid "Compress font-weight"
|
141 |
+
msgstr "Comprimeren font-weight"
|
142 |
+
|
143 |
+
#: ../head-cleaner.php:1642
|
144 |
+
msgid "Remove unnecessary backslashes"
|
145 |
+
msgstr "Verwijder onnodige backslashes"
|
146 |
+
|
147 |
+
#: ../head-cleaner.php:1650
|
148 |
+
msgid "Active JavaScripts"
|
149 |
+
msgstr "Aktieve Javascripts"
|
150 |
+
|
151 |
+
#: ../head-cleaner.php:1653
|
152 |
+
msgid "Move to footer"
|
153 |
+
msgstr "Ga naar voettekst"
|
154 |
+
|
155 |
+
#: ../head-cleaner.php:1654
|
156 |
+
msgid "JavaScripts"
|
157 |
+
msgstr "JavaScripts"
|
158 |
+
|
159 |
+
#: ../head-cleaner.php:1666
|
160 |
+
msgid "Active Filters"
|
161 |
+
msgstr "Actieve Filters"
|
162 |
+
|
163 |
+
#: ../head-cleaner.php:1669
|
164 |
+
#: ../head-cleaner.php:1706
|
165 |
+
msgid "Don't process!"
|
166 |
+
msgstr "Niet verwerken!"
|
167 |
+
|
168 |
+
#: ../head-cleaner.php:1670
|
169 |
+
#: ../head-cleaner.php:1707
|
170 |
+
msgid "Remove"
|
171 |
+
msgstr "Verwijderen"
|
172 |
+
|
173 |
+
#: ../head-cleaner.php:1671
|
174 |
+
msgid "Head filters"
|
175 |
+
msgstr "Filter bovenkant"
|
176 |
+
|
177 |
+
#: ../head-cleaner.php:1673
|
178 |
+
#: ../head-cleaner.php:1710
|
179 |
+
msgid "Priority"
|
180 |
+
msgstr "Prioriteit"
|
181 |
+
|
182 |
+
#: ../head-cleaner.php:1708
|
183 |
+
msgid "Bottom filters"
|
184 |
+
msgstr "Filters onderkant"
|
185 |
+
|
186 |
+
#: ../head-cleaner.php:1744
|
187 |
+
msgid "Update Options"
|
188 |
+
msgstr "Opties Opslaan"
|
189 |
+
|
190 |
+
#: ../head-cleaner.php:1749
|
191 |
+
msgid "Remove all cache files"
|
192 |
+
msgstr "Verwijder alle cache bestanden"
|
193 |
+
|
194 |
+
#: ../head-cleaner.php:1752
|
195 |
+
msgid "All cache files are removed."
|
196 |
+
msgstr "All cache bestanden zijn verwijderd."
|
197 |
+
|
198 |
+
#: ../head-cleaner.php:1753
|
199 |
+
msgid "Remove All Cache Files"
|
200 |
+
msgstr "Verwijder Alle Cache Bestanden"
|
201 |
+
|
202 |
+
#: ../head-cleaner.php:1758
|
203 |
+
msgid "Uninstall"
|
204 |
+
msgstr "Deinstalleren"
|
205 |
+
|
206 |
+
#: ../head-cleaner.php:1761
|
207 |
+
msgid "All the settings of "Head Cleaner" are deleted."
|
208 |
+
msgstr "Alle instellingen van "Head Cleaner" worden verwijderd."
|
209 |
+
|
210 |
+
#: ../head-cleaner.php:1762
|
211 |
+
msgid "Delete Options"
|
212 |
+
msgstr "Opties Verwijderen"
|
213 |
+
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=9S8AJ
|
|
4 |
Tags: head, header, footer, javascript, css, optimization, minified, performance
|
5 |
Requires at least: 2.5
|
6 |
Tested up to: 2.9.2
|
7 |
-
Stable tag: 1.3.
|
8 |
|
9 |
Cleaning tags from your WordPress header and footer.
|
10 |
|
@@ -39,11 +39,12 @@ To speed up the loading of JavaScript and CSS.
|
|
39 |
= Localization =
|
40 |
"Head Cleaner" has been translated into languages. Our thanks and appreciation must go to the following for their contributions:
|
41 |
|
42 |
-
* Belorussian (by) -
|
|
|
43 |
* German (de) - Carsten
|
44 |
-
* Japanese (ja) -
|
45 |
-
* Spanish (es) -
|
46 |
-
* Russian (ru) -
|
47 |
|
48 |
If you have translated into your language, please let me know.
|
49 |
|
4 |
Tags: head, header, footer, javascript, css, optimization, minified, performance
|
5 |
Requires at least: 2.5
|
6 |
Tested up to: 2.9.2
|
7 |
+
Stable tag: 1.3.8
|
8 |
|
9 |
Cleaning tags from your WordPress header and footer.
|
10 |
|
39 |
= Localization =
|
40 |
"Head Cleaner" has been translated into languages. Our thanks and appreciation must go to the following for their contributions:
|
41 |
|
42 |
+
* Belorussian (by) - [Marcis Gasuns](http://www.comfi.com/ "Marcis Gasuns")
|
43 |
+
* Dutch (nl_NL) - [Rene](http://wpwebshop.com/blog "WPWebshop Blog")
|
44 |
* German (de) - Carsten
|
45 |
+
* Japanese (ja) - [OKAMOTO Wataru](http://dogmap.jp/ "dogmap.jp") (plugin author)
|
46 |
+
* Spanish (es) - [Franz Hartmann](http://tolingo.com/ "tolingo.com - Franz Hartmann")
|
47 |
+
* Russian (ru) - [ilyuha](http://antsar.info/ "ilyuha")
|
48 |
|
49 |
If you have translated into your language, please let me know.
|
50 |
|
readme_ja.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=9S8AJ
|
|
4 |
Tags: head optimization, javascript, css, optimization, minified, performance
|
5 |
Requires at least: 2.5
|
6 |
Tested up to: 2.9.2
|
7 |
-
Stable tag: 1.3.
|
8 |
|
9 |
Head �� footer �����|�����܂��B
|
10 |
|
@@ -37,11 +37,12 @@ WordPress
|
|
37 |
= Localization =
|
38 |
"Head Cleaner" ���e����ɖ|�Ă������������X�Ɋ��ӂ����߂āB
|
39 |
|
40 |
-
* Belorussian (by) -
|
|
|
41 |
* German (de) - Carsten
|
42 |
-
* Japanese (ja) -
|
43 |
-
* Spanish (es) -
|
44 |
-
* Russian (ru) -
|
45 |
|
46 |
|
47 |
== Installation ==
|
4 |
Tags: head optimization, javascript, css, optimization, minified, performance
|
5 |
Requires at least: 2.5
|
6 |
Tested up to: 2.9.2
|
7 |
+
Stable tag: 1.3.8
|
8 |
|
9 |
Head �� footer �����|�����܂��B
|
10 |
|
37 |
= Localization =
|
38 |
"Head Cleaner" ���e����ɖ|�Ă������������X�Ɋ��ӂ����߂āB
|
39 |
|
40 |
+
* Belorussian (by) - [Marcis Gasuns](http://www.comfi.com/ "Marcis Gasuns")
|
41 |
+
* Dutch (nl_NL) - [Rene](http://wpwebshop.com/blog "WPWebshop Blog")
|
42 |
* German (de) - Carsten
|
43 |
+
* Japanese (ja) - [OKAMOTO Wataru](http://dogmap.jp/ "dogmap.jp") (plugin author)
|
44 |
+
* Spanish (es) - [Franz Hartmann](http://tolingo.com/ "tolingo.com - Franz Hartmann")
|
45 |
+
* Russian (ru) - [ilyuha](http://antsar.info/ "ilyuha")
|
46 |
|
47 |
|
48 |
== Installation ==
|