Jekyll Gulp HAML SASS BrowserSync

My custom flavour of Jekyll site template.

Whilst using Github's Jekyll framework to build a static website, I noticed a lack of built-in HAML support.

I am a big fan of using HAML to produce HTML. Whilst I think we should be careful about adding yet more tools into the build chain, for personal projects at least it can be fun to play around with them with. HAML is used within the Ruby on Rails community, as it is supported by Ruby on Rails along with ERB as alternate HTML template engines. I even write my CV in HAML.

Apart from this lack of built-in support for HAML, I really enjoy using Jekyll, so I persisted with integrating a HAML build step into my Jekyll build.

Since I was using Gulp to manage the build process, I needed a Gulp task to handle the conversion from HAML to HTML. I initially tried using the Gulp-Haml NPM packagegulp-haml module in my HAML task, but it produced incorrect results a few times. I then came across the node module Gulp-Ruby-Haml NPM packagegulp-ruby-haml, which is a wrapper on the Ruby gem HAML ruby packagehaml, and which gives accurate results.

HAML Processing

HAML files reside inside a _haml folder which sits at the location of the resultant HTML files. For example:

project-root/
    index/
        _haml/
                index.haml
        index.html
    _includes/
        _haml/
            footer.haml
            head.haml
            nav.haml
        footer.html
        head.html
        nav.html

The HAML build task is actually fairly slow compared to the CSS or Javascript processing tasks. It can take up to 10 seconds to process all of the HAML in the project. This is unacceptable when rebuilding on-the-fly while making changes.

To avoid slow build times, I wrote a separate haml-watch task that watches the HAML files for changes, then only processes the files that changed. The stream is then piped into the code for compiling the HAML, which is contained in the function hamlBuild(). This stream-piping step makes use of Stream Combiner 2 NPM packagestream-combiner2. Below is the code for both HAML tasks:

var haml = require('gulp-ruby-haml')
var combiner = require('stream-combiner2')

...

var config = {
    paths: {
        ...
        haml: {
            src: ['**/_haml/*.haml']
        },
        ...
    }
}

...

/* hamlBuild() contains the shared build logic used by haml-watch and haml-build */
function hamlBuild() {
    return combiner(
        haml(),
        rename(function (path) {
            path.dirname += '/../'
        })
    )
}

/* Watch and compile only changed HAML files to HTML.
 * haml-watch has its own task to avoid doing a full HAML build on each .haml file change, since a full HAML build
 * can be quite slow.
 */
gulp.task('haml-watch', function () {
    gulp.src(config.paths.haml.src, {read: false})
        .pipe(watch(config.paths.haml.src))
        .pipe(hamlBuild())
        .pipe(gulp.dest('./'))
})

/* Compile all HAML files to HTML. */
gulp.task('haml-build', function () {
    return gulp.src(config.paths.haml.src)
        .pipe(hamlBuild())
        .pipe(gulp.dest('./'))
})

Full Site Template

Whilst researching Jekyll, I noticed a few other people sharing their Jekyll setups as site templates. Here is my own Source repository for Jekyll-Gulp-Haml-Sass-BrowserSync projectjekyll-gulp-haml-sass-browsersync template which includes my full Gulpfile for Jekyll-Gulp-Haml-Sass-BrowserSync project on source repository pageGulpfile.