However, the generated HTML uses inline styles. There are articles, and tools like Firefox Page Speed, that warn against inline styles because they slow down browser rendering; the reality is that the impact is often miniscule. Of more concern with highlight_file is that its inline styles could significantly increase the size of your page and have a noticeable impact on download times. Can we use CSS classes instead?
A quick search showed that other people had posed this question without answer, and someone had even written their own equivalent PHP function with classes. After putting my thinking cap on I realised that using a technique similar to SQL injection provides a dead simple, and in hindsight, obvious solution:
001<?php
002# Author: Andy Wrigley webstuff.inblighty.com
003ini_set('highlight.default', '"class="aw_default');
004ini_set('highlight.keyword','"class="aw_keyword');
005ini_set('highlight.string', '"class="aw_string');
006ini_set('highlight.html', '"class="aw_htmlsrc');
007ini_set('highlight.comment', '"class="aw_comment');
008$aw_source = highlight_file('your_sourcefile.ext', TRUE);
009echo str_replace('style="color: "', '' , $aw_source );
010?>
This post extends the above script to add line numbers.
This example uses highlight_file; I assume it will also work for highlight_string, but I have not tested it.
Explanation by example
1. Normal usage, default colors, no classes:
Source of mydemo.php:
<p>Some HTML</p>
<?php
# A php comment
?>
By using <?php highlight_file(mydemo.php); ?>
your visitors will see:
<p>Some HTML</p>
<?php
# A php comment
?>
If you “view source” in the browser window you will see that the highlight_file has generated the following syntax colored encoded HTML. I have highlighted the comment to demonstrate how the syntax highlighter inserts spans with inline color styles:
<code><span style="color: #000000">
<p>Some HTML</p>
<br /><span style="color: #0000BB"><?php
<br /></span><span style="color: #FF8000"># A php comment
<br /></span><span style="color: #0000BB">?></span>
</span>
</code>
2. Changing default colors:
The colors used by the syntax highlighter are the values set for highlight.comment, highlight.default, highlight.html, highlight.keyword and highlight.string. You can change the default color values by using ini_set e.g. to make comments green ini_set('highlight.comment', '#00FF00')
.
3. Adding classes:
The syntax highlighter uses concatenation. For a comment span, simplistically something like this: outputstring .= '<span style="color: '
. ini_get(‘highlight.comment’) . '" >;'
The ini_set function does not validate the “color” value so we can set it to any string we want; and it will be inserted by the syntax highlighter between style=”color : and a closing double quote and >. So if we wanted bold red keywords: ini_set('highlight.keyword', 'red; font-weight:bold')
and keyword spans would look like this: <span style="color: red; font-weight:bold">
I’ve not seen it suggested elsewhere, but we can use this same technique to add a class. All we have to do is start our string with a double quote to close the inline style and follow it by class="class_name
. Do not add a closing double quote, as the syntax highlighter adds this to “close the inline style”.
003ini_set('highlight.default', '"class="aw_default');
004ini_set('highlight.keyword','"class="aw_keyword');
005ini_set('highlight.string', '"class="aw_string');
006ini_set('highlight.html', '"class="aw_htmlsrc');
007ini_set('highlight.comment', '"class="aw_comment');
Although this will work, all our spans will contain a superfluous style="color: "
. The highlight_file function has an optional boolean parameter, if this is set to true, instead of “printing” it will return the encoded HTML as a string. We can strip out the empty inline styles before echoing.
008$aw_source = highlight_file('your_sourcefile.ext', TRUE);
009echo str_replace('style="color: "', '' , $aw_source );
A final word
This trick relies on the absence of parameter validation by ini_set. I suspect this will continue to be the case, but it is possible that by the time you read this you may be using a brand spanking new release of PHP that prevents this ‘hack’.
Shameless plug: If you find this article interesting or useful then a “+1” at the top of the page would really be appreciated.
Thanks!