Skip to content

Commit 50e7e04

Browse files
author
o10n-x
committed
core update
1 parent 4daa36a commit 50e7e04

File tree

6 files changed

+301
-10
lines changed

6 files changed

+301
-10
lines changed

README.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Tags: css, critical css, async, minify, editor, concat, minifier, concatenation,
55
Requires at least: 4.0
66
Requires PHP: 5.4
77
Tested up to: 4.9.4
8-
Stable tag: 0.0.49
8+
Stable tag: 0.0.50
99
License: GPLv2 or later
1010
License URI: http://www.gnu.org/licenses/gpl-2.0.html
1111

@@ -50,6 +50,9 @@ Documentation is available on [Github](https://github.com/o10n-x/wordpress-css-o
5050

5151
== Changelog ==
5252

53+
= 0.0.50 =
54+
* Added: Regular Expression [Compressor.php from Minify](https://github.com/mrclay/minify) (mrclay)
55+
5356
= 0.0.49 =
5457
* Added: support for multiple CSS minifiers.
5558
* Added: Yahoo [YUI CSS Compressor PHP Port](https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port) v4.1.1

admin/css.inc.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
<select name="o10n[css.minify.minifier]" data-ns-change="css.minify" data-json-default="<?php print esc_attr(json_encode('cssmin')); ?>">
3838
<option value="cssmin"<?php $selected('css.minify.minifier', 'cssmin'); ?>>CssMin.php (Joe Scylla)</option>
3939
<option value="yui"<?php $selected('css.minify.minifier', 'yui'); ?>>Yahoo YUI Compressor PHP Port v4.1.1</option>
40-
<!--option value="regex"<?php $selected('css.minify.minifier', 'regex'); ?>>Regular Expression Compressor.php from Minify (mrclay)</option-->
40+
<option value="regex"<?php $selected('css.minify.minifier', 'regex'); ?>>Regular Expression Compressor.php from Minify (mrclay)</option>
4141
</select>
4242
<p class="description">Choose a minifier that provides the best performance for your CSS code.</p>
4343
</div>
@@ -49,7 +49,7 @@
4949
<p class="info_yellow" style="margin-bottom:1em;" data-ns="css.minify.ignore_errors"<?php $visible('css.minify.ignore_errors'); ?>><strong><span class="dashicons dashicons-lightbulb"></span></strong> It is advised to use the CSS editor's CSS Lint feature to repair invalid CSS code.</p>
5050
</div>
5151

52-
<div class="suboption" data-ns="css.minify"<?php $visible('css.minify', ($get('css.minify.minifier') === 'yui')); ?> data-ns-condition="css.minify.minifier==yui">
52+
<div class="suboption" data-ns="css.minify"<?php $visible('css.minify', ($get('css.minify.minifier') === 'yui' || $get('css.minify.minifier') === 'regex')); ?> data-ns-condition="css.minify.minifier==yui||css.minify.minifier==regex">
5353

5454
<p class="poweredby" data-ns="css.minify.rebase"<?php $visible('css.minify.rebase'); ?>>Powered by <a href="https://github.com/pear/Net_URL2/" target="_blank">Net_URL2</a><span class="star">
5555
<a class="github-button" data-manual="1" href="https://github.com/pear/Net_URL2" data-icon="octicon-star" data-show-count="true" aria-label="Star pear/Net_URL2 on GitHub">Star</a></span></p>
@@ -69,12 +69,12 @@
6969
</div>
7070

7171
<div style="margin-top:0.5em;" data-ns="css.minify.import.filter"<?php $visible('css.minify.import.filter', ($get('css.minify.import.filter.type') === 'include')); ?> data-ns-condition="css.minify.import.filter.type==include">
72-
<h5 class="h">&nbsp;Minify Include List</h5>
72+
<h5 class="h">&nbsp;Import Include List</h5>
7373
<textarea class="json-array-lines" name="o10n[css.minify.import.filter.include]" data-json-type="json-array-lines" placeholder="Exclude stylesheets by default. Import stylesheets on this list."><?php $line_array('css.minify.import.filter.include'); ?></textarea>
7474
<p class="description">Enter (parts of) stylesheet URLs to import, e.g. <code>bootstrap.min.css</code>. One match string per line.</p>
7575
</div>
7676
<div style="margin-top:0.5em;" data-ns="css.minify.import.filter"<?php $visible('css.minify.import.filter', ($get('css.minify.import.filter.type') === 'exclude')); ?> data-ns-condition="css.minify.import.filter.type==exclude">
77-
<h5 class="h">&nbsp;Minify Exclude List</h5>
77+
<h5 class="h">&nbsp;Import Exclude List</h5>
7878
<textarea class="json-array-lines" name="o10n[css.minify.import.filter.exclude]" data-json-type="json-array-lines" placeholder="Import stylesheets by default. Exclude stylesheets on this list."><?php $line_array('css.minify.import.filter.exclude'); ?></textarea>
7979
<p class="description">Enter (parts of) stylesheet URLs to exclude from import. One match string per line.</p>
8080
</div>

changelog.txt

-2
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,3 @@ Added: minify critical CSS using [PHP CssMin](https://code.google.com/archive/p/
153153

154154
Beta release. Please provide feedback on [Github forum](https://github.com/o10n-x/wordpress-css-optimization/issues).
155155

156-
157-
* Added: Regular Expression [Compressor.php from Minify](https://github.com/mrclay/minify) (mrclay)

controllers/css.class.php

+26-1
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,12 @@ class Css extends Controller implements Controller_Interface
5757
private $cssmin_minify_filters = null;
5858
private $cssmin_minify_plugins = null;
5959

60-
// YUI settings
60+
// YUI instance
6161
private $YUI;
6262

63+
// Compressor.php instance
64+
private $Compressor;
65+
6366
/**
6467
* Load controller
6568
*
@@ -1956,6 +1959,28 @@ final private function minify($sources, $base_href, $minifier)
19561959
case "regex":
19571960
default:
19581961

1962+
// load library
1963+
if (!class_exists('O10n\Minify_CSS_Compressor')) {
1964+
try {
1965+
require_once $this->core->modules('css')->dir_path() . 'lib/Compressor.php';
1966+
1967+
$this->Compressor = new Minify_CSS_Compressor(null);
1968+
} catch (\Exception $err) {
1969+
throw new Exception('CSS Compressor.php failed to load: ' . $err->getMessage(), 'css');
1970+
}
1971+
}
1972+
1973+
// minify
1974+
try {
1975+
$minified = $this->Compressor->process($CSS);
1976+
} catch (\Exception $err) {
1977+
throw new Exception('CSS Compressor.php failed: ' . $err->getMessage(), 'css');
1978+
}
1979+
1980+
if (!$minified && $minified !== '') {
1981+
throw new Exception('CSS Compressor.php failed: unknown error', 'css');
1982+
}
1983+
19591984
$this->last_used_minifier = 'regex';
19601985
break;
19611986
}

css-optimization.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* @wordpress-plugin
1313
* Plugin Name: CSS Optimization
1414
* Description: Advanced CSS optimization toolkit. Critical CSS, minification, concatenation, async loading, advanced editor, CSS Lint, Clean CSS (professional), beautifier and more.
15-
* Version: 0.0.49
15+
* Version: 0.0.50
1616
* Author: Optimization.Team
1717
* Author URI: https://optimization.team/
1818
* Text Domain: o10n
@@ -29,7 +29,7 @@
2929
}
3030

3131
// settings
32-
$module_version = '0.0.49';
32+
$module_version = '0.0.50';
3333
$minimum_core_version = '0.0.36';
3434
$plugin_path = dirname(__FILE__);
3535

lib/Compressor.php

+265
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
<?php
2+
namespace O10n;
3+
4+
/**
5+
* Class Minify_CSS_Compressor
6+
* @package Minify
7+
*/
8+
9+
/**
10+
* Compress CSS
11+
*
12+
* This is a heavy regex-based removal of whitespace, unnecessary
13+
* comments and tokens, and some CSS value minimization, where practical.
14+
* Many steps have been taken to avoid breaking comment-based hacks,
15+
* including the ie5/mac filter (and its inversion), but expect tricky
16+
* hacks involving comment tokens in 'content' value strings to break
17+
* minimization badly. A test suite is available.
18+
*
19+
* Note: This replaces a lot of spaces with line breaks. It's rumored
20+
* (https://github.com/yui/yuicompressor/blob/master/README.md#global-options)
21+
* that some source control tools and old browsers don't like very long lines.
22+
* Compressed files with shorter lines are also easier to diff. If this is
23+
* unacceptable please use CSSmin instead.
24+
*
25+
* @package Minify
26+
* @author Stephen Clay <[email protected]>
27+
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
28+
*
29+
* @deprecated Use CSSmin (tubalmartin/cssmin)
30+
*/
31+
class Minify_CSS_Compressor
32+
{
33+
34+
/**
35+
* @var array
36+
*/
37+
protected $_options = null;
38+
39+
/**
40+
* Are we "in" a hack? I.e. are some browsers targetted until the next comment?
41+
*
42+
* @var bool
43+
*/
44+
protected $_inHack = false;
45+
46+
/**
47+
* Constructor
48+
*
49+
* @param array $options (currently ignored)
50+
*/
51+
public function __construct($options)
52+
{
53+
$this->_options = $options;
54+
}
55+
56+
/**
57+
* Minify a CSS string
58+
*
59+
* @param string $css
60+
*
61+
* @return string
62+
*/
63+
public function process($css)
64+
{
65+
66+
// reset
67+
$this->_inHack = false;
68+
69+
$css = str_replace("\r\n", "\n", $css);
70+
71+
// preserve empty comment after '>'
72+
// http://www.webdevout.net/css-hacks#in_css-selectors
73+
$css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
74+
75+
// preserve empty comment between property and value
76+
// http://css-discuss.incutio.com/?page=BoxModelHack
77+
$css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
78+
$css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
79+
80+
// apply callback to all valid comments (and strip out surrounding ws
81+
$pattern = '@\\s*/\\*([\\s\\S]*?)\\*/\\s*@';
82+
$css = preg_replace_callback($pattern, array($this, '_commentCB'), $css);
83+
84+
// remove ws around { } and last semicolon in declaration block
85+
$css = preg_replace('/\\s*{\\s*/', '{', $css);
86+
$css = preg_replace('/;?\\s*}\\s*/', '}', $css);
87+
88+
// remove ws surrounding semicolons
89+
$css = preg_replace('/\\s*;\\s*/', ';', $css);
90+
91+
// remove ws around urls
92+
$pattern = '/
93+
url\\( # url(
94+
\\s*
95+
([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
96+
\\s*
97+
\\) # )
98+
/x';
99+
$css = preg_replace($pattern, 'url($1)', $css);
100+
101+
// remove ws between rules and colons
102+
$pattern = '/
103+
\\s*
104+
([{;]) # 1 = beginning of block or rule separator
105+
\\s*
106+
([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
107+
\\s*
108+
:
109+
\\s*
110+
(\\b|[#\'"-]) # 3 = first character of a value
111+
/x';
112+
$css = preg_replace($pattern, '$1$2:$3', $css);
113+
114+
// remove ws in selectors
115+
$pattern = '/
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+
$css = preg_replace_callback($pattern, array($this, '_selectorsCB'), $css);
127+
128+
// minimize hex colors
129+
$pattern = '/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i';
130+
$css = preg_replace($pattern, '$1#$2$3$4$5', $css);
131+
132+
// remove spaces between font families
133+
$pattern = '/font-family:([^;}]+)([;}])/';
134+
$css = preg_replace_callback($pattern, 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+
$pattern = '/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/';
143+
$css = preg_replace($pattern, "$1\n$2{", $css);
144+
145+
// Use newline after 1st numeric value (to limit line lengths).
146+
$pattern = '/
147+
((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
148+
\\s+
149+
/x';
150+
$css = preg_replace($pattern, "$1\n", $css);
151+
152+
// prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
153+
$css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css);
154+
155+
return trim($css);
156+
}
157+
158+
/**
159+
* Replace what looks like a set of selectors
160+
*
161+
* @param array $m regex matches
162+
*
163+
* @return string
164+
*/
165+
protected function _selectorsCB($m)
166+
{
167+
// remove ws around the combinators
168+
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
169+
}
170+
171+
/**
172+
* Process a comment and return a replacement
173+
*
174+
* @param array $m regex matches
175+
*
176+
* @return string
177+
*/
178+
protected function _commentCB($m)
179+
{
180+
$hasSurroundingWs = (trim($m[0]) !== $m[1]);
181+
$m = $m[1];
182+
// $m is the comment content w/o the surrounding tokens,
183+
// but the return value will replace the entire comment.
184+
if ($m === 'keep') {
185+
return '/**/';
186+
}
187+
188+
if ($m === '" "') {
189+
// component of http://tantek.com/CSS/Examples/midpass.html
190+
return '/*" "*/';
191+
}
192+
193+
if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
194+
// component of http://tantek.com/CSS/Examples/midpass.html
195+
return '/*";}}/* */';
196+
}
197+
198+
if ($this->_inHack) {
199+
// inversion: feeding only to one browser
200+
$pattern = '@
201+
^/ # comment started like /*/
202+
\\s*
203+
(\\S[\\s\\S]+?) # has at least some non-ws content
204+
\\s*
205+
/\\* # ends like /*/ or /**/
206+
@x';
207+
if (preg_match($pattern, $m, $n)) {
208+
// end hack mode after this comment, but preserve the hack and comment content
209+
$this->_inHack = false;
210+
211+
return "/*/{$n[1]}/**/";
212+
}
213+
}
214+
215+
if (substr($m, -1) === '\\') { // comment ends like \*/
216+
// begin hack mode and preserve hack
217+
$this->_inHack = true;
218+
219+
return '/*\\*/';
220+
}
221+
222+
if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
223+
// begin hack mode and preserve hack
224+
$this->_inHack = true;
225+
226+
return '/*/*/';
227+
}
228+
229+
if ($this->_inHack) {
230+
// a regular comment ends hack mode but should be preserved
231+
$this->_inHack = false;
232+
233+
return '/**/';
234+
}
235+
236+
// Issue 107: if there's any surrounding whitespace, it may be important, so
237+
// replace the comment with a single space
238+
return $hasSurroundingWs ? ' ' : ''; // remove all other comments
239+
}
240+
241+
/**
242+
* Process a font-family listing and return a replacement
243+
*
244+
* @param array $m regex matches
245+
*
246+
* @return string
247+
*/
248+
protected function _fontFamilyCB($m)
249+
{
250+
// Issue 210: must not eliminate WS between words in unquoted families
251+
$flags = PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY;
252+
$pieces = preg_split('/(\'[^\']+\'|"[^"]+")/', $m[1], null, $flags);
253+
$out = 'font-family:';
254+
255+
while (null !== ($piece = array_shift($pieces))) {
256+
if ($piece[0] !== '"' && $piece[0] !== "'") {
257+
$piece = preg_replace('/\\s+/', ' ', $piece);
258+
$piece = preg_replace('/\\s?,\\s?/', ',', $piece);
259+
}
260+
$out .= $piece;
261+
}
262+
263+
return $out . $m[2];
264+
}
265+
}

0 commit comments

Comments
 (0)