PluginProbe
Autoptimize / 1.8.2
Autoptimize v1.8.2
2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 All 107 releases
← All changes | classes/external/php/minify-html.php +65 -73 2.7.81.8.2 View file →
@@ -1,7 +1,7 @@
1 1 <?php
2 2 /**
3 - * Class Minify_HTML
3 + * Class Minify_HTML
4 4 * @package Minify
5 5 */
6 6
7 7 /**
@@ -6,22 +6,19 @@
6 6
7 7 /**
8 8 * Compress HTML
9 9 *
10 - * This is a heavy regex-based removal of whitespace, unnecessary comments and
10 + * This is a heavy regex-based removal of whitespace, unnecessary comments and
11 11 * tokens. IE conditional comments are preserved. There are also options to have
12 - * STYLE and SCRIPT blocks compressed by callback functions.
13 - *
12 + * STYLE and SCRIPT blocks compressed by callback functions.
13 + *
14 14 * A test suite is available.
15 - *
15 + *
16 16 * @package Minify
17 17 * @author Stephen Clay <steve@mrclay.org>
18 18 */
19 19 class Minify_HTML {
20 20
21 - /** @var string */
22 - private $_html;
23 -
24 21 /**
25 22 * "Minify" an HTML page
26 23 *
27 24 * @param string $html
@@ -29,18 +26,18 @@
29 26 * @param array $options
30 27 *
31 28 * 'cssMinifier' : (optional) callback function to process content of STYLE
32 29 * elements.
33 - *
30 + *
34 31 * 'jsMinifier' : (optional) callback function to process content of SCRIPT
35 32 * elements. Note: the type attribute is ignored.
36 - *
33 + *
37 34 * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
38 35 * unset, minify will sniff for an XHTML doctype.
39 - *
36 + *
40 37 * 'keepComments' : (optional boolean) should the HTML comments be kept
41 38 * in the HTML Code?
42 - *
39 + *
43 40 * @return string
44 41 */
45 42 public static function minify($html, $options = array()) {
46 43 $min = new Minify_HTML($html, $options);
@@ -45,10 +42,10 @@
45 42 public static function minify($html, $options = array()) {
46 43 $min = new Minify_HTML($html, $options);
47 44 return $min->process();
48 45 }
49 -
50 -
46 +
47 +
51 48 /**
52 49 * Create a minifier object
53 50 *
54 51 * @param string $html
@@ -56,18 +53,18 @@
56 53 * @param array $options
57 54 *
58 55 * 'cssMinifier' : (optional) callback function to process content of STYLE
59 56 * elements.
60 - *
57 + *
61 58 * 'jsMinifier' : (optional) callback function to process content of SCRIPT
62 59 * elements. Note: the type attribute is ignored.
63 - *
60 + *
64 61 * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
65 62 * unset, minify will sniff for an XHTML doctype.
66 - *
63 + *
67 64 * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
68 65 * unset, minify will sniff for an XHTML doctype.
69 - *
66 + *
70 67 * @return null
71 68 */
72 69 public function __construct($html, $options = array())
73 70 {
@@ -84,13 +81,13 @@
84 81 if (isset($options['keepComments'])) {
85 82 $this->_keepComments = $options['keepComments'];
86 83 }
87 84 }
88 -
89 -
85 +
86 +
90 87 /**
91 88 * Minify the markeup given in the constructor
92 - *
89 + *
93 90 * @return string
94 91 */
95 92 public function process()
96 93 {
@@ -96,72 +93,69 @@
96 93 {
97 94 if ($this->_isXhtml === null) {
98 95 $this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
99 96 }
100 -
97 +
101 98 $this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
102 99 $this->_placeholders = array();
103 -
100 +
104 101 // replace SCRIPTs (and minify) with placeholders
105 102 $this->_html = preg_replace_callback(
106 103 '/(\\s*)(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
107 104 ,array($this, '_removeScriptCB')
108 105 ,$this->_html);
109 -
106 +
110 107 // replace STYLEs (and minify) with placeholders
111 108 $this->_html = preg_replace_callback(
112 109 '/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i'
113 110 ,array($this, '_removeStyleCB')
114 111 ,$this->_html);
115 -
112 +
116 113 // remove HTML comments (not containing IE conditional comments).
117 - if ($this->_keepComments == false) {
118 - $this->_html = preg_replace_callback(
119 - '/<!--([\\s\\S]*?)-->/'
120 - ,array($this, '_commentCB')
121 - ,$this->_html);
114 + if ($this->_keepComments == false) {
115 + $this->_html = preg_replace_callback(
116 + '/<!--([\\s\\S]*?)-->/'
117 + ,array($this, '_commentCB')
118 + ,$this->_html);
122 119 }
123 -
120 +
124 121 // replace PREs with placeholders
125 122 $this->_html = preg_replace_callback('/\\s*(<pre\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
126 123 ,array($this, '_removePreCB')
127 124 ,$this->_html);
128 -
125 +
129 126 // replace TEXTAREAs with placeholders
130 127 $this->_html = preg_replace_callback(
131 128 '/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
132 129 ,array($this, '_removeTextareaCB')
133 130 ,$this->_html);
134 -
135 - // replace data: URIs with placeholders
131 +
132 + // replace data: URIs with placeholders
136 133 $this->_html = preg_replace_callback(
137 134 '/(=("|\')data:.*\\2)/Ui'
138 135 ,array($this, '_removeDataURICB')
139 136 ,$this->_html);
140 -
137 +
141 138 // trim each line.
142 - // replace by space instead of '' to avoid newline after opening tag getting zapped
143 - $this->_html = preg_replace('/^\s+|\s+$/m', ' ', $this->_html);
144 -
139 + // @todo take into account attribute values that span multiple lines.
140 + $this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
141 +
145 142 // remove ws around block/undisplayed elements
146 - $this->_html = preg_replace('/\\s+(<\\/?(?:area|article|aside|base(?:font)?|blockquote|body'
147 - .'|canvas|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|figcaption|figure|footer|form'
148 - .'|frame(?:set)?|h[1-6]|head|header|hgroup|hr|html|legend|li|link|main|map|menu|meta|nav'
149 - .'|ol|opt(?:group|ion)|output|p|param|section|t(?:able|body|head|d|h||r|foot|itle)'
150 - .'|ul|video)\\b[^>]*>)/i', '$1', $this->_html);
151 -
143 + $this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
144 + .'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
145 + .'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
146 + .'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
147 + .'|ul)\\b[^>]*>)/i', '$1', $this->_html);
148 +
152 149 // remove ws outside of all elements
153 150 $this->_html = preg_replace_callback(
154 151 '/>([^<]+)</'
155 152 ,array($this, '_outsideTagCB')
156 153 ,$this->_html);
157 -
154 +
158 155 // use newlines before 1st attribute in open tags (to limit line lengths)
159 156 //$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
160 -
161 - // reverse order while preserving keys to ensure the last replacement is done first, etc ...
162 - $this->_placeholders = array_reverse( $this->_placeholders, true );
163 -
157 +
164 158 // fill placeholders
165 159 $this->_html = str_replace(
166 160 array_keys($this->_placeholders)
167 161 ,array_values($this->_placeholders)
@@ -168,9 +162,9 @@
168 162 ,$this->_html
169 163 );
170 164 return $this->_html;
171 165 }
172 -
166 +
173 167 protected function _commentCB($m)
174 168 {
175 169 return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
176 170 ? $m[0]
@@ -175,9 +169,9 @@
175 169 return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
176 170 ? $m[0]
177 171 : '';
178 172 }
179 -
173 +
180 174 protected function _reservePlace($content)
181 175 {
182 176 $placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
183 177 $this->_placeholders[$placeholder] = $content;
@@ -188,26 +182,26 @@
188 182 protected $_replacementHash = null;
189 183 protected $_placeholders = array();
190 184 protected $_cssMinifier = null;
191 185 protected $_jsMinifier = null;
192 - protected $_keepComments = false;
186 + protected $_keepComments = false;
193 187
194 188 protected function _outsideTagCB($m)
195 189 {
196 190 return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
197 191 }
198 -
192 +
199 193 protected function _removePreCB($m)
200 194 {
201 195 return $this->_reservePlace($m[1]);
202 196 }
203 -
197 +
204 198 protected function _removeTextareaCB($m)
205 199 {
206 200 return $this->_reservePlace($m[1]);
207 201 }
208 -
209 - protected function _removeDataURICB($m)
202 +
203 + protected function _removeDataURICB($m)
210 204 {
211 205 return $this->_reservePlace($m[1]);
212 206 }
213 207
@@ -216,18 +210,18 @@
216 210 $openStyle = $m[1];
217 211 $css = $m[2];
218 212 // remove HTML comments
219 213 $css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
220 -
214 +
221 215 // remove CDATA section markers
222 216 $css = $this->_removeCdata($css);
223 -
217 +
224 218 // minify
225 219 $minifier = $this->_cssMinifier
226 220 ? $this->_cssMinifier
227 221 : 'trim';
228 222 $css = call_user_func($minifier, $css);
229 -
223 +
230 224 return $this->_reservePlace($this->_needsCdata($css)
231 225 ? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
232 226 : "{$openStyle}{$css}</style>"
233 227 );
@@ -236,27 +230,25 @@
236 230 protected function _removeScriptCB($m)
237 231 {
238 232 $openScript = $m[2];
239 233 $js = $m[3];
240 -
234 +
241 235 // whitespace surrounding? preserve at least one space
242 236 $ws1 = ($m[1] === '') ? '' : ' ';
243 237 $ws2 = ($m[4] === '') ? '' : ' ';
244 -
245 - if ($this->_keepComments == false) {
246 - // remove HTML comments (and ending "//" if present)
247 - $js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
248 -
249 - // remove CDATA section markers
250 - $js = $this->_removeCdata($js);
251 - }
252 -
238 +
239 + // remove HTML comments (and ending "//" if present)
240 + $js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
241 +
242 + // remove CDATA section markers
243 + $js = $this->_removeCdata($js);
244 +
253 245 // minify
254 246 $minifier = $this->_jsMinifier
255 247 ? $this->_jsMinifier
256 - : 'trim';
248 + : 'trim';
257 249 $js = call_user_func($minifier, $js);
258 -
250 +
259 251 return $this->_reservePlace($this->_needsCdata($js)
260 252 ? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
261 253 : "{$ws1}{$openScript}{$js}</script>{$ws2}"
262 254 );
@@ -264,12 +256,12 @@
264 256
265 257 protected function _removeCdata($str)
266 258 {
267 259 return (false !== strpos($str, '<![CDATA['))
268 - ? str_replace(array('/* <![CDATA[ */','/* ]]> */','/*<![CDATA[*/','/*]]>*/','<![CDATA[', ']]>'), '', $str)
260 + ? str_replace(array('<![CDATA[', ']]>'), '', $str)
269 261 : $str;
270 262 }
271 -
263 +
272 264 protected function _needsCdata($str)
273 265 {
274 266 return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
275 267 }