Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
/**
4
 * HTML renderer
5
 *
6
 * PHP versions 4 and 5
7
 *
8
 * LICENSE: This source file is subject to version 3.0 of the PHP license
9
 * that is available through the world-wide-web at the following URI:
10
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
11
 * the PHP License and are unable to obtain it through the web, please
12
 * send a note to license@php.net so we can mail you a copy immediately.
13
 *
14
 * @category   Text
15
 * @package    Text_Highlighter
16
 * @author     Andrey Demenev <demenev@gmail.com>
17
 * @copyright  2004-2006 Andrey Demenev
18
 * @license    http://www.php.net/license/3_0.txt  PHP License
19
 * @version    CVS: $Id: Html.php,v 1.1 2007/06/03 02:37:09 ssttoo Exp $
20
 * @link       http://pear.php.net/package/Text_Highlighter
21
 */
22
 
23
/**
24
 * @ignore
25
 */
26
 
27
require_once dirname(__FILE__).'/../Renderer.php';
28
require_once dirname(__FILE__).'/../Renderer/Array.php';
29
 
30
// BC trick : only define constants if Text/Highlighter.php
31
// is not yet included
32
if (!defined('HL_NUMBERS_LI')) {
33
    /**#@+
34
     * Constant for use with $options['numbers']
35
     */
36
    /**
37
     * use numbered list, deprecated, use HL_NUMBERS_OL instaed
38
     * @deprecated
39
     */
40
    define ('HL_NUMBERS_LI'    ,    1);
41
    /**
42
     * Use 2-column table with line numbers in left column and code in  right column.
43
     */
44
    define ('HL_NUMBERS_TABLE'    , 2);
45
    /**#@-*/
46
}
47
 
48
 
49
/**#@+
50
 * Constant for use with $options['numbers']
51
 */
52
/**
53
 * Use numbered list
54
 */
55
define ('HL_NUMBERS_OL',    1);
56
/**
57
 * Use non-numbered list
58
 */
59
define ('HL_NUMBERS_UL',    3);
60
/**#@-*/
61
 
62
 
63
/**
64
 * HTML renderer
65
 *
66
 * Elements of $options argument of constructor (each being optional):
67
 *
68
 * - 'numbers' - Line numbering style 0 or {@link HL_NUMBERS_TABLE}
69
 *               or {@link HL_NUMBERS_UL} or {@link HL_NUMBERS_OL}
70
 * - 'numbers_start' - starting number for numbered lines
71
 * - 'tabsize' - Tab size
72
 * - 'style_map' - Mapping of keywords to formatting rules using inline styles
73
 * - 'class_map' - Mapping of keywords to formatting rules using class names
74
 * - 'doclinks' - array that has keys "url", "target" and "elements", used for
75
 *                generating links to online documentation
76
 * - 'use_language' - class names will be prefixed with language, like "php-reserved" or "css-code"
77
 *
78
 * Example of setting documentation links:
79
 * $options['doclinks'] = array(
80
 *   'url' => 'http://php.net/%s',
81
 *   'target' => '_blank',
82
 *   'elements' => array('reserved', 'identifier')
83
 * );
84
 *
85
 * Example of setting class names map:
86
 * $options['class_map'] = array(
87
 *       'main'       => 'my-main',
88
 *       'table'      => 'my-table',
89
 *       'gutter'     => 'my-gutter',
90
 *       'brackets'   => 'my-brackets',
91
 *       'builtin'    => 'my-builtin',
92
 *       'code'       => 'my-code',
93
 *       'comment'    => 'my-comment',
94
 *       'default'    => 'my-default',
95
 *       'identifier' => 'my-identifier',
96
 *       'inlinedoc'  => 'my-inlinedoc',
97
 *       'inlinetags' => 'my-inlinetags',
98
 *       'mlcomment'  => 'my-mlcomment',
99
 *       'number'     => 'my-number',
100
 *       'quotes'     => 'my-quotes',
101
 *       'reserved'   => 'my-reserved',
102
 *       'special'    => 'my-special',
103
 *       'string'     => 'my-string',
104
 *       'url'        => 'my-url',
105
 *       'var'        => 'my-var',
106
 * );
107
 *
108
 * Example of setting styles mapping:
109
 * $options['style_map'] = array(
110
 *       'main'       => 'color: black',
111
 *       'table'      => 'border: 1px solid black',
112
 *       'gutter'     => 'background-color: yellow',
113
 *       'brackets'   => 'color: blue',
114
 *       'builtin'    => 'color: red',
115
 *       'code'       => 'color: green',
116
 *       'comment'    => 'color: orange',
117
 *       // ....
118
 * );
119
 *
120
 *
121
 * @author Andrey Demenev <demenev@gmail.com>
122
 * @category   Text
123
 * @package    Text_Highlighter
124
 * @copyright  2004-2006 Andrey Demenev
125
 * @license    http://www.php.net/license/3_0.txt  PHP License
126
 * @version    Release: 0.7.0
127
 * @link       http://pear.php.net/package/Text_Highlighter
128
 */
129
 
130
class Text_Highlighter_Renderer_Html extends Text_Highlighter_Renderer_Array
131
{
132
 
133
    /**#@+
134
     * @access private
135
     */
136
 
137
    /**
138
     * Line numbering style
139
     *
140
     * @var integer
141
     */
142
    var $_numbers = 0;
143
 
144
    /**
145
     * For numberered lines - where to start
146
     *
147
     * @var integer
148
     */
149
    var $_numbers_start = 0;
150
 
151
    /**
152
     * Tab size
153
     *
154
     * @var integer
155
     */
156
    var $_tabsize = 4;
157
 
158
    /**
159
     * Highlighted code
160
     *
161
     * @var string
162
     */
163
    var $_output = '';
164
 
165
    /**
166
     * Mapping of keywords to formatting rules using inline styles
167
     *
168
     * @var array
169
     */
170
    var $_style_map = array();
171
 
172
    /**
173
     * Mapping of keywords to formatting rules using class names
174
     *
175
     * @var array
176
     */
177
    var $_class_map = array(
178
        'main'       => 'hl-main',
179
        'table'      => 'hl-table',
180
        'gutter'     => 'hl-gutter',
181
        'brackets'   => 'hl-brackets',
182
        'builtin'    => 'hl-builtin',
183
        'code'       => 'hl-code',
184
        'comment'    => 'hl-comment',
185
        'default'    => 'hl-default',
186
        'identifier' => 'hl-identifier',
187
        'inlinedoc'  => 'hl-inlinedoc',
188
        'inlinetags' => 'hl-inlinetags',
189
        'mlcomment'  => 'hl-mlcomment',
190
        'number'     => 'hl-number',
191
        'quotes'     => 'hl-quotes',
192
        'reserved'   => 'hl-reserved',
193
        'special'    => 'hl-special',
194
        'string'     => 'hl-string',
195
        'url'        => 'hl-url',
196
        'var'        => 'hl-var',
197
    );
198
 
199
    /**
200
     * Setup for links to online documentation
201
     *
202
     * This is an array with keys:
203
     * - url, ex. http://php.net/%s
204
     * - target, ex. _blank, default - no target
205
     * - elements, default is <code>array('reserved', 'identifier')</code>
206
     *
207
     * @var array
208
     */
209
    var $_doclinks = array();
210
 
211
    /**#@-*/
212
 
213
    /**
214
     * Resets renderer state
215
     *
216
     * @access protected
217
     *
218
     *
219
     * Descendents of Text_Highlighter call this method from the constructor,
220
     * passing $options they get as parameter.
221
     */
222
    function reset()
223
    {
224
        $this->_output = '';
225
        if (isset($this->_options['numbers'])) {
226
            $this->_numbers = (int)$this->_options['numbers'];
227
            if ($this->_numbers != HL_NUMBERS_LI
228
             && $this->_numbers != HL_NUMBERS_UL
229
             && $this->_numbers != HL_NUMBERS_OL
230
             && $this->_numbers != HL_NUMBERS_TABLE
231
             ) {
232
                $this->_numbers = 0;
233
            }
234
        }
235
        if (isset($this->_options['tabsize'])) {
236
            $this->_tabsize = $this->_options['tabsize'];
237
        }
238
        if (isset($this->_options['numbers_start'])) {
239
            $this->_numbers_start = intval($this->_options['numbers_start']);
240
        }
241
        if (isset($this->_options['doclinks']) &&
242
            is_array($this->_options['doclinks']) &&
243
            !empty($this->_options['doclinks']['url'])
244
        ) {
245
 
246
            $this->_doclinks = $this->_options['doclinks']; // keys: url, target, elements array
247
 
248
            if (empty($this->_options['doclinks']['elements'])) {
249
                $this->_doclinks['elements'] = array('reserved', 'identifier');
250
            }
251
        }
252
        if (isset($this->_options['style_map'])) {
253
            $this->_style_map = $this->_options['style_map'];
254
        }
255
        if (isset($this->_options['class_map'])) {
256
            $this->_class_map = array_merge($this->_class_map, $this->_options['class_map']);
257
        }
258
        $this->_htmlspecialchars = true;
259
 
260
    }
261
 
262
 
263
    /**
264
     * Given a CSS class name, returns the class name
265
     * with language name prepended, if necessary
266
     *
267
     * @access private
268
     *
269
     * @param  string $class   Token class
270
     */
271
    function _getFullClassName($class)
272
    {
273
        if (!empty($this->_options['use_language'])) {
274
            $the_class = $this->_language . '-' . $class;
275
        } else {
276
            $the_class = $class;
277
        }
278
        return $the_class;
279
    }
280
 
281
    /**
282
     * Signals that no more tokens are available
283
     *
284
     * @access public
285
     */
286
    function finalize()
287
    {
288
 
289
        // get parent's output
290
        parent::finalize();
291
        $output = parent::getOutput();
292
        if(empty($output))
293
        	return;
294
 
295
		$html_output = '';
296
        // loop through each class=>content pair
297
        foreach ($output AS $token) {
298
 
299
            if ($this->_enumerated) {
300
                $the_class = $token[0];
301
                $content = $token[1];
302
            } else {
303
                $key = key($token);
304
                $the_class = $key;
305
                $content = $token[$key];
306
            }
307
 
308
            $span = $this->_getStyling($the_class);
309
            $decorated_output = $this->_decorate($content, $key);
310
			//print "<pre> token = ".var_export($token, true)." -- span = " . htmlentities($span). "-- deco = ".$decorated_output."</pre>\n";
311
            $html_output .= sprintf($span, $decorated_output);
312
        }
313
 
314
        // format lists
315
        if (!empty($this->_numbers) &&
316
            (
317
            $this->_numbers == HL_NUMBERS_LI ||
318
            $this->_numbers == HL_NUMBERS_UL ||
319
            $this->_numbers == HL_NUMBERS_OL
320
            )
321
        ) {
322
			//$html_output = "<pre>".$html_output."</pre>";
323
            // additional whitespace for browsers that do not display
324
            // empty list items correctly
325
            $this->_output = '<li><pre>&nbsp;' . str_replace("\n", "</pre></li>\n<li><pre>&nbsp;", $html_output) . '</pre></li>';
326
 
327
 
328
            $start = '';
329
            if ($this->_numbers == HL_NUMBERS_OL && intval($this->_numbers_start) > 0)  {
330
                $start = ' start="' . $this->_numbers_start . '"';
331
            }
332
 
333
            $list_tag = 'ol';
334
            if ($this->_numbers == HL_NUMBERS_UL)  {
335
                $list_tag = 'ul';
336
            }
337
 
338
 
339
            $this->_output = '<' . $list_tag . $start
340
                             . ' ' . $this->_getStyling('main', false) . '>'
341
                             . $this->_output . '</'. $list_tag .'>';
342
 
343
        // render a table
344
        } else if ($this->_numbers == HL_NUMBERS_TABLE) {
345
 
346
 
347
            $start_number = 0;
348
            if (intval($this->_numbers_start)) {
349
                $start_number = $this->_numbers_start - 1;
350
            }
351
 
352
            $numbers = '';
353
 
354
            $nlines = substr_count($html_output,"\n")+1;
355
            for ($i=1; $i <= $nlines; $i++) {
356
                $numbers .= ($start_number + $i) . "\n";
357
            }
358
            $this->_output = '<table ' . $this->_getStyling('table', false) . ' width="100%"><tr>' .
359
                             '<td '. $this->_getStyling('gutter', false) .' align="right" valign="top">' .
360
                             '<pre>' . $numbers . '</pre></td><td '. $this->_getStyling('main', false) .
361
                             ' valign="top"><pre>' .
362
                             $html_output . '</pre></td></tr></table>';
363
        }
364
        if (!$this->_numbers) {
365
            $this->_output = '<pre>' . $html_output . '</pre>';
366
        }
367
        $this->_output = '<div ' . $this->_getStyling('main', false) . '>' . $this->_output . '</div>';
368
    }
369
 
370
 
371
    /**
372
     * Provides additional formatting to a keyword
373
     *
374
     * @param string $content Keyword
375
     * @return string Keyword with additional formatting
376
     * @access public
377
     *
378
     */
379
    function _decorate($content, $key)
380
    {
381
        // links to online documentation
382
        if (!empty($this->_doclinks) &&
383
            !empty($this->_doclinks['url']) &&
384
            in_array($key, $this->_doclinks['elements'])
385
        ) {
386
 
387
            $link = '<a href="'. sprintf($this->_doclinks['url'], $content) . '"';
388
            if (!empty($this->_doclinks['target'])) {
389
                $link.= ' target="' . $this->_doclinks['target'] . '"';
390
            }
391
            $link .= '>';
392
            $link.= $content;
393
            $link.= '</a>';
394
 
395
            $content = $link;
396
 
397
        }
398
 
399
        return $content;
400
    }
401
 
402
    /**
403
     * Returns <code>class</code> and/or <code>style</code> attribute,
404
     * optionally enclosed in a <code>span</code> tag
405
     *
406
     * @param string $class Class name
407
     * @paran boolean $span_tag Whether or not to return styling attributes in a <code>&gt;span&lt;</code> tag
408
     * @return string <code>span</code> tag or just a <code>class</code> and/or <code>style</code> attributes
409
     * @access private
410
     */
411
    function _getStyling($class, $span_tag = true)
412
    {
413
        $attrib = '';
414
        if (!empty($this->_style_map) &&
415
            !empty($this->_style_map[$class])
416
        ) {
417
            $attrib = 'style="'. $this->_style_map[$class] .'"';
418
        }
419
        if (!empty($this->_class_map) &&
420
            !empty($this->_class_map[$class])
421
        ) {
422
            if ($attrib) {
423
                $attrib .= ' ';
424
            }
425
            $attrib .= 'class="'. $this->_getFullClassName($this->_class_map[$class]) .'"';
426
        }
427
 
428
        if ($span_tag) {
429
            $span = '<span ' . $attrib . '>%s</span>';
430
            return $span;
431
        } else {
432
            return $attrib;
433
        }
434
 
435
    }
436
}
437
 
438
/*
439
 * Local variables:
440
 * tab-width: 4
441
 * c-basic-offset: 4
442
 * c-hanging-comment-ender-p: nil
443
 * End:
444
 */
445
 
446
?>