PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
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 4.7.0, at vendor/mrclay/minify/lib/Minify/HTML.php

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