6 * @subpackage PluginsFilter
10 * Smarty trimwhitespace outputfilter plugin
11 * Trim unnecessary whitespace from HTML markup.
15 * @param string $source input string
17 * @return string filtered output
18 * @todo substr_replace() is not overloaded by mbstring.func_overload - so this function might fail!
20 function smarty_outputfilter_trimwhitespace($source)
26 // Unify Line-Breaks to \n
27 $source = preg_replace("/\015\012|\015|\012/", "\n", $source);
29 // capture Internet Explorer and KnockoutJS Conditional Comments
30 if (preg_match_all('#<!--((\[[^\]]+\]>.*?<!\[[^\]]+\])|(\s*/?ko\s+.+))-->#is', $source, $matches,
31 PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
32 foreach ($matches as $match) {
33 $store[] = $match[ 0 ][ 0 ];
34 $_length = strlen($match[ 0 ][ 0 ]);
35 $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
36 $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] - $_offset, $_length);
38 $_offset += $_length - strlen($replace);
43 // Strip all HTML-Comments
44 // yes, even the ones in <script> - see http://stackoverflow.com/a/808850/515124
45 $source = preg_replace('#<!--.*?-->#ms', '', $source);
47 // capture html elements not to be messed with
49 if (preg_match_all('#(<script[^>]*>.*?</script[^>]*>)|(<textarea[^>]*>.*?</textarea[^>]*>)|(<pre[^>]*>.*?</pre[^>]*>)#is',
50 $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
51 foreach ($matches as $match) {
52 $store[] = $match[ 0 ][ 0 ];
53 $_length = strlen($match[ 0 ][ 0 ]);
54 $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
55 $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] - $_offset, $_length);
57 $_offset += $_length - strlen($replace);
62 $expressions = array(// replace multiple spaces between tags by a single space
63 // can't remove them entirely, becaue that might break poorly implemented CSS display:inline-block elements
64 '#(:SMARTY@!@|>)\s+(?=@!@SMARTY:|<)#s' => '\1 \2',
65 // remove spaces between attributes (but not in attribute values!)
66 '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5',
67 // note: for some very weird reason trim() seems to remove spaces inside attributes.
68 // maybe a \0 byte or something is interfering?
69 '#^\s+<#Ss' => '<', '#>\s+$#Ss' => '>',);
71 $source = preg_replace(array_keys($expressions), array_values($expressions), $source);
72 // note: for some very weird reason trim() seems to remove spaces inside attributes.
73 // maybe a \0 byte or something is interfering?
74 // $source = trim( $source );
77 if (preg_match_all('#@!@SMARTY:([0-9]+):SMARTY@!@#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
78 foreach ($matches as $match) {
79 $_length = strlen($match[ 0 ][ 0 ]);
80 $replace = $store[ $match[ 1 ][ 0 ] ];
81 $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] + $_offset, $_length);
83 $_offset += strlen($replace) - $_length;