PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.3
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.3
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / vendor / mrclay / minify / lib / Minify / HTML.php

HTML.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.3, at vendor/mrclay/minify/lib/Minify/HTML.php

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