Notes on Jekyll

Published on

Here I describe a couple of Jekyll issues that I had to debug recently.

I have many relative symlinks in my jekyll directory that point outside of it. For instance, docs/2010-10-22-posix.pdf is a symlink to ../../kpi/POSIX/2010-10-22-posix.pdf.

Recently I noticed that these symlinks are broken in jekyll’s generated directory, _site. It appears that jekyll copies the link as is, that is as a relative link to ../../kpi/POSIX/2010-10-22-posix.pdf, but because the location of the link changed from $JEKYLL_ROOT to $JEKYLL_ROOT/_site, it no longer pointed into the right place.

So I dug into the source code and found this in lib/jekyll/static_file.rb:

def copy_file(dest_path)
  if @site.safe || Jekyll.env == "production"
    FileUtils.cp(path, dest_path)
  else
    FileUtils.copy_entry(path, dest_path)
  end

  unless File.symlink?(dest_path)
    File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path)
  end
end

As described in the docs for FileUtils, cp copies the file content, similarly to cp -L, while copy_entry copies a link as a link, like cp -d.

As the code implies, the behavior we want (FileUtils.cp) can be triggered by setting the environment to production:

JEKYLL_ENV=production

I don’t see why this shouldn’t be the default behavior, so I opened an issue.

Interestingly, I’m pretty sure it used to work properly before. When I discovered the issue, I rushed to check whether my site has been broken all this time, but the files were in the right places on the server. I thought that maybe this is a recent regression, but git blame says that this piece of code hasn’t changed in years. I still have not solved this mystery.

A case of a missing file

I needed to publish the files of a research project I’m working on. The main code for the project is in an R markdown notebook (“Rmd”). I was going to publish the raw code.Rmd file, so that others could run it, as well as its rendered version, code.html.

When I looked into the _site directory, code.html was there, but code.Rmd was mysteriously missing.

It took me a while to find the problem, but it is a simple one: Rmd is a markdown file with a YAML front matter — just like the markdown files jekyll has to process. So the code.html I was seeing was not the original code.html (which contains the output of the R code) but the Rmd file rendered by jekyll. And like all the other jekyll’s input files, code.Rmd was not copied into the output directory.

This problem was discussed before (here and here), and the advice was to make jekyll ignore the problematic files/directories and then use something else (like Gulp) to copy them into the _site directory.

This seemed too complicated to me, so I made a small patch to support “verbatim” directories, which are copied as is even if some of the files contain the YAML front matter. To enable this, simply add

verbatim:
  - files

to your _config.yml, where files is the name of the directory to copy verbatim.

I submitted this feature as a pull request, which I hope will be accepted, but for the time being you can get it from my fork of the jekyll repo.