Automated Slate documentation builds
scripting a template into an automated documentation builder
- 5 minsRecently 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 sed
:
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:
Feel free to check out the commit or pull request that added all this stuff to Inertia, a UBC Launch Pad project!