source: branches/0.4/web/addons/job_monarch/dwoo/plugins/builtin/filters/html_format.php @ 755

Last change on this file since 755 was 755, checked in by ramonb, 11 years ago
  • add Dwoo
File size: 5.9 KB
Line 
1<?php
2
3/**
4 * Formats any html output (must be valid xml where every tag opened is closed)
5 * using a single tab for indenting. 'pre' and other whitespace sensitive
6 * tags should not be affected.
7 *
8 * It is not recommended to use this on every template if you render multiple
9 * templates per page, you should only use it once on the main page template so that
10 * everything is formatted in one pass.
11 *
12 * This software is provided 'as-is', without any express or implied warranty.
13 * In no event will the authors be held liable for any damages arising from the use of this software.
14 *
15 * @author     Jordi Boggiano <j.boggiano@seld.be>
16 * @copyright  Copyright (c) 2008, Jordi Boggiano
17 * @license    http://dwoo.org/LICENSE   Modified BSD License
18 * @link       http://dwoo.org/
19 * @version    1.0.0
20 * @date       2008-10-23
21 * @package    Dwoo
22 */
23class Dwoo_Filter_html_format extends Dwoo_Filter
24{
25        /**
26         * tab count to auto-indent the source
27         *
28         * @var int
29         */
30        protected static $tabCount = -1;
31
32        /**
33         * stores the additional data (following a tag) of the last call to open/close/singleTag
34         *
35         * @var string
36         */
37        protected static $lastCallAdd = '';
38
39        /**
40         * formats the input using the singleTag/closeTag/openTag functions
41         *
42         * It is auto indenting the whole code, excluding <textarea>, <code> and <pre> tags that must be kept intact.
43         * Those tags must however contain only htmlentities-escaped text for everything to work properly.
44         * Inline tags are presented on a single line with their content
45         *
46         * @param Dwoo_Core $dwoo the dwoo instance rendering this
47         * @param string $input the xhtml to format
48         * @return string formatted xhtml
49         */
50        public function process($input)
51        {
52                self::$tabCount = -1;
53
54                // auto indent all but textareas & pre (or we have weird tabs inside)
55                $input = preg_replace_callback("#(<[^>]+>)(\s*)([^<]*)#", array('self', 'tagDispatcher'), $input);
56
57                return $input;
58        }
59
60        /**
61         * helper function for format()'s preg_replace call
62         *
63         * @param array $input  array of matches (1=>tag, 2=>whitespace(optional), 3=>additional non-html content)
64         * @return string the indented tag
65         */
66        protected static function tagDispatcher($input)
67        {
68                // textarea, pre, code tags and comments are to be left alone to avoid any non-wanted whitespace inside them so it just outputs them as they were
69                if (substr($input[1],0,9) == "<textarea" || substr($input[1],0,4) == "<pre" || substr($input[1],0,5) == "<code" || substr($input[1],0,4) == "<!--" || substr($input[1],0,9) == "<![CDATA[") {
70                        return $input[1] . $input[3];
71                }
72                // closing textarea, code and pre tags and self-closed tags (i.e. <br />) are printed as singleTags because we didn't use openTag for the formers and the latter is a single tag
73                if (substr($input[1],0,10) == "</textarea" || substr($input[1],0,5) == "</pre" || substr($input[1],0,6) == "</code" || substr($input[1],-2) == "/>") {
74                        return self::singleTag($input[1],$input[3],$input[2]);
75                }
76                // it's the closing tag
77                if ($input[0][1]=="/"){
78                        return self::closeTag($input[1],$input[3],$input[2]);
79                }
80                // opening tag
81                return self::openTag($input[1],$input[3],$input[2]);
82        }
83
84        /**
85         * returns an open tag and adds a tab into the auto indenting
86         *
87         * @param string $tag content of the tag
88         * @param string $add additional data (anything before the following tag)
89         * @param string $whitespace white space between the tag and the additional data
90         * @return string
91         */
92        protected static function openTag($tag,$add,$whitespace)
93        {
94                $tabs = str_pad('',self::$tabCount++,"\t");
95
96                if (preg_match('#^<(a|label|option|textarea|h1|h2|h3|h4|h5|h6|strong|b|em|i|abbr|acronym|cite|span|sub|sup|u|s|title)(?: [^>]*|)>#', $tag)) {
97                        // if it's one of those tag it's inline so it does not require a leading line break
98                        $result = $tag . $whitespace . str_replace("\n","\n".$tabs,$add);
99                } elseif (substr($tag,0,9) == '<!DOCTYPE') {
100                        // it's the doctype declaration so no line break here either
101                        $result = $tabs . $tag;
102                } else {
103                        // normal block tag
104                        $result = "\n".$tabs . $tag;
105
106                        if (!empty($add)) {
107                                $result .= "\n".$tabs."\t".str_replace("\n","\n\t".$tabs,$add);
108                        }
109                }
110
111                self::$lastCallAdd = $add;
112
113                return $result;
114        }
115
116        /**
117         * returns a closing tag and removes a tab from the auto indenting
118         *
119         * @param string $tag content of the tag
120         * @param string $add additional data (anything before the following tag)
121         * @param string $whitespace white space between the tag and the additional data
122         * @return string
123         */
124        protected static function closeTag($tag,$add,$whitespace)
125        {
126                $tabs = str_pad('',--self::$tabCount,"\t");
127
128                // if it's one of those tag it's inline so it does not require a leading line break
129                if (preg_match('#^</(a|label|option|textarea|h1|h2|h3|h4|h5|h6|strong|b|em|i|abbr|acronym|cite|span|sub|sup|u|s|title)>#', $tag)) {
130                        $result = $tag . $whitespace . str_replace("\n","\n".$tabs,$add);
131                } else {
132                        $result = "\n".$tabs.$tag;
133
134                        if (!empty($add)) {
135                                $result .= "\n".$tabs."\t".str_replace("\n","\n\t".$tabs,$add);
136                        }
137                }
138
139                self::$lastCallAdd = $add;
140
141                return $result;
142        }
143
144        /**
145         * returns a single tag with auto indenting
146         *
147         * @param string $tag content of the tag
148         * @param string $add additional data (anything before the following tag)
149         * @return string
150         */
151        protected static function singleTag($tag,$add,$whitespace)
152        {
153                $tabs = str_pad('',self::$tabCount,"\t");
154
155                // if it's img, br it's inline so it does not require a leading line break
156                // if it's a closing textarea, code or pre tag, it does not require a leading line break either or it creates whitespace at the end of those blocks
157                if (preg_match('#^<(img|br|/textarea|/pre|/code)(?: [^>]*|)>#', $tag)) {
158                        $result = $tag.$whitespace;
159
160                        if (!empty($add)) {
161                                $result .= str_replace("\n","\n".$tabs,$add);
162                        }
163                } else {
164                        $result = "\n".$tabs.$tag;
165
166                        if (!empty($add)) {
167                                $result .= "\n".$tabs.str_replace("\n","\n".$tabs,$add);
168                        }
169                }
170
171                self::$lastCallAdd = $add;
172
173                return $result;
174        }
175}
Note: See TracBrowser for help on using the repository browser.