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