Automated Slate documentation builds
scripting a template into an automated documentation builder- 5 mins
Recently at work, I came across a documentation website recently set up for one of our APIs. I thought it looked great, and slick, and super nice, and wanted to adopt it for anther project. I was told the documentation was generated using a project called Slate, and after taking a look I knew I had to try it out. It’s very pretty.
First step: read some docs. “Getting Started with Slate” seemed like a good place to get started.
Mhm, looking good so far. I’ve got all those things.
Hold up. What? Is this telling me that I can’t just “use” this thing to build documentation as a tool? I need to fork it and change it?
Okay great. Well, I don’t want to do that. I want my documentation to be part of my repository, so it can be versioned alongside our code, and I don’t want to carry around the baggage of an entire repository alongside my documentation. So let’s not do that, and try to hack Slate into a proper doc builder.
# Making the Script
mkdir -p docs_build cd docs_build if [ ! -d slate ]; then git clone [https://github.com/lord/slate.git](https://github.com/lord/slate.git) fi
To start off, I want my script to grab the repo (I’ll need it one way or another) and chuck it into a temporary directory. I called it
docs_build and chucked it into my
.gitignore where it belongs.
Next, I’ll go ahead and symlink everything that I’m supposed to change in my “fork” from where I want my actual documentation to be — I decided to call it
docs_src — into the cloned Slate repo.
# in /docs_build # documentation ln -fs "$(dirname "$(pwd)")"/docs_src/index.html.md \ slate/source/index.html.md # CSS variables (colours, etc.) ln -fs "$(dirname "$(pwd)")"/docs_src/stylesheets/_variables.scss \ slate/source/stylesheets/_variables.scss # cute logo! ln -fs "$(dirname "$(pwd)")"/.static/inertia.png \ slate/source/images/logo.png
Note that when creating a symlink with
ln -s, you should use the full directory path as your source, or the link could point to something nonexistent. In this case, I opted to use pwd and join it to the file I’m trying to link from.
Next, I’ll need to install Slate’s dependencies:
# in /docs_build cd slate bundle install
And hypothetically I should be good to go!
# in /docs_build/slate # build docs into the /docs directory bundle exec middleman build --clean --build-dir=../../docs
The build works, and all seems well. Let’s check out live reload:
# in /docs_build/slate bundle exec middleman server --verbose
If you’re following along, you’ll probably notice that this step tragically does not work properly — editing a file in my /docs_src directory does not trigger a reload.
This probably happens because a symlink doesn’t usually play well with file watchers, and poking around the Middleman repository issues reveals a few (such as this one) that reveals this is likely the problem. Some more digging surfaces a files.watch feature that seems to do what I want: add my symlink source directories as a trigger for rebuilds.
The problem is, I need to add this to
config.rb, which is in the Slate repository, and I want to maintain my Slate-as-a-doc-builder feature, which means any configuration changes I make must be scripted and perfectly reproducible.
TEMPLATE_FILES_WATCH= \ "files.watch :source, path: File.join(root, '../../docs_src')" if ! grep -q "$TEMPLATE_FILES_WATCH" slate/config.rb ; then echo "$TEMPLATE_FILES_WATCH" \ >> slate/config.rb fi
Nice! This script checks for if my custom files.watch directive is already in Slate’s config.rb , and if not, append it to the end. Now running the Middleman server successfully live-reloads my changes to http://localhost:4567 !
I’m not quite done though — I also want my site to have a favicon. I figured this might be a configuration option in index.html.md , but it’s not:
Well that’s just great. Time to whip out some
LAYOUT="slate/source/layouts/layout.erb" if ! grep -q "<%= favicon_tag 'favicon.ico' %>" "$LAYOUT" ; then sed -i '' '/<head>/a\ <%= favicon_tag '\''favicon\.ico'\'' %> ' slate/source/layouts/layout.erb fi
This checks the layout for the favicon tag, and if it’s not there, insert it right after the <head> tag.
Then I had to add the favicon to my list of things to symlink:
ln -fs "$(dirname "$(pwd)")"/.static/favicon.ico \ slate/source/images/favicon.ico
And it worked! bundle exec middleman server kindly updated my local deployment to show my shiny new favicon:
# Finishing Touches
- I tied everything up together into a tidy (I hope), documented (I think) script.
- I also added a some Makefile targets to run the build script and the live-reload server.
- Of course, writing and building documentation needs documentation as well.
- I forked Slate (and opened a PR upstream) to add some more customization features (mostly in the CSS variables), and am currently using this fork in my script.
- I deployed the documentation to https://inertia.ubclaunchpad.com/
Here’s what the documentation site looks like now: