Fixing Ghost's Casper theme

As you've most likely guessed, I'm running Ghost as a blogging platform here on timofejew.com.

I'm really liking it so far. The post editor is really nice, and I'm digging that it's using Markdown as it's markup language. All the cool kids use Markdown. And the default "theme" for Ghost, Casper v1.1.7 is pretty slick as well. I tried out a few of the free Ghost themes that people have created, and I'm not that crazy about them. Casper feels a lot like the theme that Medium uses (minus a few goodies), and the Ghost team have done a great job creating a responsive web design.

However... there is one major thing screwed up with it. The <pre> blocks. I'm planning on putting a fair bit of code snippets on here, and the style for <pre> has one inexcusable flaw: it hyphenates code(!)

Basic fix

Thankfully, the fix is easy. Ghost (at least in v0.5.10) provides a mechanism for injecting code into the <head> of each page. It's a trivial matter of adding some CSS styles to override the default by adding a <style> tag in the header. All that's needed to enable this is to go to the 'Labs' section of the settings tab to enable this feature.

Code injection

To fix this paste the following HTML into the 'Blog Header' section:

<style>  
  pre {
    word-wrap: normal;
    -moz-hyphens: none;
    -ms-hyphens: none;
    -webkit-hyphens: none;
    hyphens: none;
  }
  pre code, pre tt {
    white-space: pre;
  }
</style>  

This will nuke the hyphenation, and as a bonus, will turn the code box into a side-scroller. Job done! You can actually cut-n-paste code from here, and it won't be incorrect.

But wait! There's more!

Only $19.95!

C'mon, it's 2015 already

Syntax highlighting. Sure, it adds a bit to the "weight" of a web page, but not nearly as much as all the #@$%^!! ad saturated web sites that we all go to. So let's just use it, take the 20ms page load hit, and everyone will appreciate how much easier it is to read code.

I took a look at two popular packages: highlight.js and Prism. Both do roughly the same thing, but I ended up choosing highlight.js for the following reasons:

  • Hosted on a CDN
  • Understands YAML and NGINX formats
  • Can also be turned off on a per code block basis
  • Has my current favourite syntax colour scheme - the same one used by GitHub

That said, Prism is very nice looking as well. Try 'em both out!

highlight.js

Paste the following into the code injection box:

<!-- http://highlightjs.readthedocs.org/en/latest/css-classes-reference.html -->  
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.5/styles/github.min.css">  
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.5/highlight.min.js"></script>  
<script>hljs.initHighlightingOnLoad();</script>  
<style>  
  pre {
    word-wrap: normal;
    -moz-hyphens: none;
    -ms-hyphens: none;
    -webkit-hyphens: none;
    hyphens: none;
    font-size: 0.7em;
    line-height: 1.3em;
  }
    pre code, pre tt {
    white-space: pre;
  }
</style>  

And that's it - you're totally stylin' now.

Prism

As Prism isn't hosted on a CDN, you'll need to download the JavaScript/CSS code and host it locally. Then, paste the following into you-know-where (changing the href locations as appropriate):

<!-- http://prismjs.com/index.html#languages-list -->  
<link href="//example.com/assets/prism.css" rel="stylesheet" />  
<script src="//example.com/assets/prism-min.js"></script>  
<style>  
  pre {
    word-wrap: normal;
    -moz-hyphens: none;
    -ms-hyphens: none;
    -webkit-hyphens: none;
    hyphens: none;
    font-size: 0.7em;
    line-height: 1.3em;
}
pre code, pre tt {  
    white-space: pre;
}
code[class*="language-"], pre[class*="language-"] {  
    line-height: 1.2em;
}
:not(pre) > code[class*="language-"], pre[class*="language-"] {
    background: #F7FAFB;
}
</style>  

Ta-da!

Usage

If you reload a post that has a code block in it, you'll notice that it's probably highlighted. Maybe not exactly as you'd want, though...

Both packages attempt, with varying degrees of success, to automatically determine what the language of the block is, and colour the syntax appropriately. However, this can easily go wrong.

There is thankfully a mechanism in the extended Markdown syntax that will allow passing the language to both highlighting packages. If you use the triple backtick mechanism to specify a code block (rather than the 4 space indent format), you can pass the language name. For example,

  ```css
  :not(pre) > code[class*="language-"], pre[class*="language-"] {
      background: #F7FAFB;
  }
  ```

will instruct the highlighter to chose the CSS syntax. Which languages are supported, and what their name is, is dependent on which languages you chose to include when you downloaded the packages1.

And for highlight.js, you can also use nohighlight as a "language" to turn off auto detection.

Now you're in the 21st century again. You're welcome.


  1. highlight.js can be customized here, and the language names are here. Prism is customized here, and languages are here.