Wolfmans Howlings

A programmers Blog about Programming solutions and a few other issues

How to setup SyntaxHighlighter in Rails 3.1.1

Posted by Jim Morris on Sat Nov 12 01:36:29 -0800 2011

Or how to get Rails 3.1.1 assets in vendor/assets to work in production.

I find the new Assets stuff very tricky to make work in production, they seem to work fine in development, but after they have been precompiled and deployed all sorts of stuff goes wrong, eve though it works fine in development.

This Blog Engine uses SyntaxHighlighter to highlight the code snippets. Porting to Rails 3.1(.1) turned out to be tricky.

I initially put all the SyntaxHighlighter files in /vendor/assets/syntaxhighlighter as that is the recommended place to put it. Then I used javascript_include_tag to include the various files I needed, and that worked fine in development, but in production it doesn't work as vendor/assets do not automatically get precompiled into public/assets/application.js nor do the subdirectories under vendor/assets get copied to public/assets when precompiled.

As these scripts are needed for virtually all pages they can just as well get put in application.js, and that is how I got it to work.

The vendor tree looks like this...

vendor/
├── assets
│   └── syntaxhighlighter
│       ├── shAutoloader.js
│       ├── shBrushAppleScript.js
│       ├── shBrushAS3.js
│       ├── shBrushBash.js
│       ├── shBrushColdFusion.js
│       ├── shBrushCpp.js
│       ├── shBrushCSharp.js
│       ├── shBrushCss.js
│       ├── shBrushDelphi.js
│       ├── shBrushDiff.js
│       ├── shBrushErlang.js
│       ├── shBrushGroovy.js
│       ├── shBrushJavaFX.js
│       ├── shBrushJava.js
│       ├── shBrushJScript.js
│       ├── shBrushPerl.js
│       ├── shBrushPhp.js
│       ├── shBrushPlain.js
│       ├── shBrushPowerShell.js
│       ├── shBrushPython.js
│       ├── shBrushRuby.js
│       ├── shBrushSass.js
│       ├── shBrushScala.js
│       ├── shBrushSql.js
│       ├── shBrushVb.js
│       ├── shBrushXml.js
│       ├── shCore.css
│       ├── shCore.js
│       ├── shLegacy.js
│       ├── shThemeDefault.css
│       ├── shThemeDjango.css
│       ├── shThemeEclipse.css
│       ├── shThemeEmacs.css
│       ├── shThemeFadeToGrey.css
│       ├── shThemeMDUltra.css
│       ├── shThemeMidnight.css
│       ├── shThemeRDark.css
│       └── syntaxhighlighter.js
└── plugins

I added syntaxhighlighter.js to the tree which contains this...

//= require ./shCore.js
//= require ./shBrushBash.js
//= require ./shBrushCpp.js
//= require ./shBrushCss.js
//= require ./shBrushDiff.js
//= require ./shBrushErlang.js
//= require ./shBrushGroovy.js
//= require ./shBrushJava.js
//= require ./shBrushJScript.js
//= require ./shBrushPerl.js
//= require ./shBrushPhp.js
//= require ./shBrushPlain.js
//= require ./shBrushPython.js
//= require ./shBrushRuby.js
//= require ./shBrushSass.js
//= require ./shBrushScala.js
//= require ./shBrushSql.js
//= require ./shBrushXml.js

Basically I include only the .js files I need.

Then I added the line //= require syntaxhighlighter to app/assets/javascripts/application.js and it gets precompiled into application.js when deployed to production.

//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require syntaxhighlighter
//= require_tree .

This now works both in development and production.

The final pieces to get this to work are to add

   :javascript
      SyntaxHighlighter.all();

To the head (if you are using HAML) and add...

*= require shCore
*= require shThemeDefault

to app/assets/stylesheets/application.css.

Obviously you can specify whatever theme you want.

I would still like to know the best way to include the syntax highlighter files only in specific pages, I know how to do it in the pre-assets era, but now it seems everything needs to be precompiled somewhere, and I don't see a way to get a syntaxhighlighter.js precompiled and copied into public/assets so I can just do a javascript_include_tag 'syntaxhighlighter' in specific view pages.

One way I guess is to modify config/environments/production.rb by adding

config.assets.precompile += %w( syntaxhighlighter.js )

but it seems a little ugly.

Posted in Rails  |  Tags rails,syntaxhighlighter,assets  |  2 comments

Comments

  1. DGM said on Sat Nov 12 13:19:05 -0800 2011
    The point of including it all the time is that the file gets downloaded once and cached in the web browser for subsequent calls. If you had it compile and download a different subset for different pages, you would force the browser to constantly download new js every time, making it slower.
  2. wolfman said on Sat Nov 12 13:49:25 -0800 2011
    Yes true, if the javascript and css is needed on every page it is an advantage, and in this case that is true, which is why the above method is probably the best solution. However there are cases where you only want some javascript loaded (or css) with a specific page. It is briefly mentioned in the rails guides on assets, but with no examples or details. An example is in my post on authentication, where I only want to load the auth.js and sha1.js when the login page is loaded. I show a solution there.

    This post is more to show how to get js and css in vendor/assets to work in production, which is not documented anywhere I can find.

(leave email »)