7

How to Add Line Highlight Support to WP-Syntax

Posted June 5th, 2011 (Updated 22 May 2014) in PHP

Update 06 June 2011: I’ve contacted the current developer and he’s accepted the patch. It should be appearing in a WP-Syntax near you shortly!
Update 16 July 2011: I’ve merged Chimo’s excellent patch which adds page range support. See the updated tutorial below for usage instructions. Thanks Chimo!
Update 27 July 2011: We have liftoff! This patch is finally part of the official plugin!

I’ve used a few different WordPress syntax highlighters in my day but WP-Syntax is easily the best of them. One issue that’s bothered me with WP-Syntax for a while now, however, is lack of line highlighting support so I decided to look into adding it myself. At the time of writing I’m using WP-Syntax 0.9.9.

To add highlighting support, open up /wp-content/plugins/wp-syntax/wp-syntax.php. You’ll need to modify two functions - wp_syntax_highlight and wp_syntax_before_filter. Here’s wp_syntax_highlight:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function wp_syntax_highlight($match)
{
    global $wp_syntax_matches;
 
    $i = intval($match[1]);
    $match = $wp_syntax_matches[$i];
 
    $language = strtolower(trim($match[1]));
    $line = trim($match[2]);
    $escaped = trim($match[3]);
 
    $code = wp_syntax_code_trim($match[5]);    if ($escaped == "true") $code = htmlspecialchars_decode($code);
 
    $geshi = new GeSHi($code, $language);
    $geshi->enable_keyword_links(false);
    do_action_ref_array('wp_syntax_init_geshi', array(&$geshi));
 
    //START LINE HIGHLIGHT SUPPORT    $highlight = array();    if ( !empty($match[4]) )    {        $highlight = strpos($match[4],',') == false ? array($match[4]) : explode(',', $match[4]); 	$h_lines = array();	for( $i=0; $i<sizeof($highlight); $i++ )	{		$h_range = explode('-', $highlight[$i]); 		if( sizeof($h_range) == 2 )			$h_lines = array_merge( $h_lines, range($h_range[0], $h_range[1]) );		else			array_push($h_lines, $highlight[$i]);	}         $geshi->highlight_lines_extra( $h_lines );    }    //END LINE HIGHLIGHT SUPPORT 
    $output = "n<div class="wp_syntax">";
 
    if ($line)
    {
        $output .= "<table><tr><td class="line_numbers">";
        $output .= wp_syntax_line_numbers($code, $line);
        $output .= "</td><td class="code">";
        $output .= $geshi->parse_code();
        $output .= "</td></tr></table>";
    }
    else
    {
        $output .= "<div class="code">";
        $output .= $geshi->parse_code();
        $output .= "</div>";
    }
    return
 
    $output .= "</div>n";
 
    return $output;
}

and here’s wp_syntax_before_filter:

1
2
3
4
5
6
7
8
function wp_syntax_before_filter($content)
{
    return preg_replace_callback(
        "/s*<pre(?:lang=["']([w-]+)["']|line=["'](d*)["']|escaped=["'](true|false)?["']|highlight=["']((?:d+[,-])*d+)["']|s)+>(.*)</pre>s*/siU",        "wp_syntax_substitute",
        $content
    );
}

Updated/added lines are, of course, highlighted :)

Below is an example of the new functionality:

<pre lang=”php” highlight=”2″>
$foo = ‘foo’;
$bar = ‘bar’;
$foobar = ‘foobar’;
</pre>

    $foo = 'foo';
    $bar = 'bar';    $foobar = 'foobar';

<pre lang=”php” highlight=”1,2,5-7″>
$foo = ‘foo’;
$bar = ‘bar’;
$foobar = ‘foobar’;

$foo = ‘foo’;
$bar = ‘bar’;
$foobar = ‘foobar’;

$foo = ‘foo’;
$bar = ‘bar’;
$foobar = ‘foobar’;
</pre>

    $foo = 'foo';    $bar = 'bar';    $foobar = 'foobar';
 
    $foo = 'foo';    $bar = 'bar';    $foobar = 'foobar'; 
    $foo = 'foo';
    $bar = 'bar';
    $foobar = 'foobar';

Remember to add highlight to the list of allowed <PRE> tag arguments in your themes functions.php file. Details on doing so can be found here.

  • Chimo

    Hi, this is great.

    I modified your code so it accept ranges as well as single lines (ex: highlight=”3,7,12-32,36″):

    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    
    //START LINE HIGHLIGHT SUPPORT
    $highlight = array();
    if ( !empty($match[4]) )
    {
        $highlight = strpos($match[4],',') == false ? array($match[4]) : explode(',', $match[4]);
     
        $h_lines = array();
        for($i = 0; $i highlight_lines_extra( $h_lines );
    }
    //END LINE HIGHLIGHT SUPPORT

    Of course, the regex needs to be changed so it accepts dashes:

    169
    170
    171
    172
    173
    174
    175
    176
    
    function wp_syntax_before_filter($content)
    {
        return preg_replace_callback(
            "/s*<pre>(.*)s*/siU",
            "wp_syntax_substitute",
            $content
        );
    }

    Thought I’d share.

    Cheers

    • Flynsarmy

      Thanks Chimo!

      I was planning on adding this in myself but it looks like you’ve done all the hard work for me. I’ll update my code shortly to include it.

      Great work
      Flynsarmy

  • Chimo

    Sorry, that didn’t show up properly…
    See here instead: http://pastebin.com/z4YJuT2D

  • Steve

    I copied the code verbatim and the range doesn’t seem to work correctly. It will not highlight the range. It seems the fix should be

    36
    
            $geshi-&gt;highlight_lines_extra( $highlight );

    this:

    36
    
            $geshi-&gt;highlight_lines_extra( $h_lines );

    At least that what makes it work after some debugging. Can you please check and I push the updated code out. Thanks!

    • Flynsarmy

      Hey Steve,

      Sorry about that you’re correct – it should have been $h_lines. I’ve updated the code above.

  • Jessica

    For the plugin I’ve changed all my colors for php highlighting to match the Solarized color theme. I can’t figure out where to change this highlight color. Any tips?

    • Jessica

      And of course as soon as I posted this I looked one last time and found it.
      wp-syntax/geshi/geshi.php

      Line 428

      /**
      * Styles of extra-highlighted lines
      * @var string
      */
      var $highlight_extra_lines_style = ‘background-color: #ffc;’;