Formatting Pygments linenos with Jekyll and Bootstrap

03 June 2015

This blog is generated by Jekyll and uses Pygments to highlight code syntax. This post describes the process I used to setup Pygments and style code snippets. [Update: For formatting code blocks with Jekyll version 3 please see formatting code with jekyll 3 and bootstrap] [Update 2: Github has updated to Jekyll 3, so this site now uses Jekyll 3 and the rouge highlighter.]

The first step is to install Pygments on your machine. The Pygments site has instructions for installation so I am not going to reproduce them here. Once Pygments is installed you need to configure Jekyll to use Pygments as the syntax highlighter. You do this by setting the following in the Jekyll _config.yml file:

highlighter: pygments

When Jekyll generates the site it will produce the HTML needed to display a code snippet. However, to style the syntax, a css stylesheet will need to be provided. Pygments provides a command line tool to do this. To generate a css file use the “pygmentize” command at the command line. For example:

pygmentize -f html -S friendly > syntax.css

The -S option indicates which style you wish to use, in this case the ‘friendly’ style. To see a preview of the various styles, go to the Pygments Demo pages page and click on one of the demo entries. You can then pick various syntax highlighting schemes in which to view the code.

The result of the above command will create a file named syntax.css. Copy this file to your site and reference it in your HTML. For example:

 <link rel="stylesheet" href="/css/syntax.css">

The syntax.css file only provides the css for the syntax highlighting. I also want to format how the code snippets are displayed on the page. I want to prevent long lines from word wrapping. The css to accomplish this depends on whether line numbers are to be displayed or not.

Line numbers

I chose to use the table option ( {% highlight python linenos=table %} ) for displaying line numbers because it allows for easy copying and pasting of the code. The HTML generated is dependent on whether line numbers are included or not. The HTML generated for a code snippet using “linenos=table” is the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<table class="highlighttable">
 <tbody>
  <tr>
   <td class="linenos">
    <div class="linenodiv">
     <pre>
      <code class="language-XXX" data-lang="XXX">line numbers</code>
     </pre>
    </div>
   </td>
   <td class="code">
    <div class="highlight">
     <pre>...snipped HTML for syntax highlighting...</pre>
    </div>
   </td>
  </tr>
 </tbody>
</table>

In the above snippet the XXX is the language of the code snippet (i.e. ruby, python, java etc.)

This site uses bootstrap, which requires tables to be wrapped in the .table-responsive class in order to make the table responsive. The .table-responsive class provides the styling to make the table scrollable. I do not want to have to manually add this class every time I create a code snippet. Fortunately, jQuery provides the wrap method that will automatically do this for me. I created the following function in my blog.js file:

$(document).ready(function () {
	$( ".highlighttable" ).wrap("<div class='table-responsive'></div>");
});

Next, I needed to style the table and line numbers. I added the following to my syntax.css file:

1
2
3
4
5
6
.table-responsive { color: #333; border: 1px solid #ccc; border-radius: 4px; margin-bottom: 10px; }
.linenodiv pre { margin: 6px 0px; color: #aaa; border-radius: 0; border: none; border-right: solid 1px; word-wrap: normal; }
.linenodiv pre code { white-space: pre; }
.code .highlight pre { margin: 6px 0px; border-radius: 0; border: none; word-wrap: normal; }
.highlighttable { width: 100%; background-color: #F5F5F5;  table-layout: fixed; }
.linenos { width: 40px; }
  • Line 1 - Styles the table-responsive class to have a rounded border.

  • Line 2 - The linenodiv pre tag styles the line numbers. I override some of the ‘pre’ tag settings as defined by bootstrap. I also provide a line between the line numbers and the code.

  • Line 3 - Styles the line numbers so they are vertical and the whitespace is preserved.

  • Line 4 - The ‘code’ class contains the actual code snippet. Again, I override some of the ‘pre’ tag settings as defined by bootstrap.

  • Line 5 - Sets the table width so it uses the full cell width. I also set background-color to that used by the ‘pre’ tag. The table-layout is set to fixed because there was an issue with being able to scroll properly on touch screens. It seems the combination of a ‘pre’ tag within a ‘td’ tag made scrolling difficult (at least on iOS). Changing the table-layout to fixed solved that issue.

  • Line 6 - Since the table-layout is fixed, I needed to set the width of the linenos. I set it to 40px which, I think, styles nicely for line numbers under 4 digits in length.

Here is an example of a code snippet using line numbers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Pojo {
    private long id;
    private String name;

    public void someMethod() {
        System.out.println("Some method"); //And here is a really long comment: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse egestas odio ligula, quis mollis libero condimentum et. Praesent urna purus, rutrum eu nibh eget, pharetra consectetur felis. Proin et massa purus. Pellentesque a elit eu dui fermentum vehicula. In rhoncus pharetra lacus. Sed maximus ut mi eget auctor. Fusce tempor, nibh sit amet aliquet gravida, nisl orci imperdiet ante, eget finibus tellus mauris sit amet ipsum.
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

No line numbers

The HTML generated for a code snippet that does not use line numbers is:

<div class="highlight">
 <pre>
  <code class="language-XXX" data-lang="XXX">...snipped HTML for syntax highlighting...</code>
 </pre>
</div>

In the above snippet the XXX is the language of the code snippet (i.e. ruby, python, java etc.)

I added the following to the syntax.css file:

.highlight pre code { display: block; white-space: pre; overflow-x: auto; word-wrap: normal; }

The above css will prevent the text from word wrapping, and will provide a horizontal scroll bar. Here is an example of a code snippet that does not use line numbers:

public class Pojo {
    private long id;
    private String name;

    public void someMethod() {
        System.out.println("Some method"); //And here is a really long comment: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse egestas odio ligula, quis mollis libero condimentum et. Praesent urna purus, rutrum eu nibh eget, pharetra consectetur felis. Proin et massa purus. Pellentesque a elit eu dui fermentum vehicula. In rhoncus pharetra lacus. Sed maximus ut mi eget auctor. Fusce tempor, nibh sit amet aliquet gravida, nisl orci imperdiet ante, eget finibus tellus mauris sit amet ipsum. 
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

You can see my full syntax.css and blog.js files on github:

Alternatives

I investigated using line numbers without the table option ( {% highlight python linenos %} ) and using the css user-select feature to prevent the line numbers from being selected when copying and pasting. However, these features are not standard and I found they did not work as expected across browsers. So, I opted for the table option instead.

The kofi logo of a coffee mugLike this? Please buy me a coffee!

Share