Rust comes with a built-in documentation system, rustdoc
. It's great, use it.
Github comes with a built-in web hosting service, Github Pages. It's great, use it.
To use Github Pages, you can either create a directory in your repository to host your deployed web content or a separate branch and then activate the feature in the "Pages" section of your repository settings:
Great!
You get a directory located at <project>/target/doc
when you run cargo doc
to generate your Rust documentation. It contains the complete web content ready to publish. If you execute cargo doc --open
, your default browser will open up and show you what it generated.
Unfortunately, this folder can't be copied strictly as-is. If you try, you'll get a 404. This is because Github Pages is looking for an index.html
file in the root directory of wherever it's pointed. However, cargo doc
created a subdirectory for your crate specifically, where index.html
lives. Here's my example for a Rust package called build_wheel
:
$ tree target/doc/
target/doc
├── ayu.css
├── brush.svg
├── build_wheel
│ ├── all.html
│ ├── fn.build_wheel.html
│ ├── index.html <-- RIGHT HERE
│ ├── sidebar-items.js
│ ├── struct.Config.html
│ └── struct.Tag.html
├── clipboard.svg
/* ... etc, etc... */
Uh-oh, it's nested. Github can't find it. You can't just make a symbolic link to an index.html
in the root directory because all the relative links inside will break.
Luckily, the fix is easy. You simply need to create an index.html
that reroutes where you want. This file only consists of one line:
<meta http-equiv="refresh" content="0; url=build_wheel">
This file uses the http-equiv
meta attribute to point immediately to the build_wheel
subdirectory and load the index.html
file found there. Just replace the directory name with the name of your package.
You can easily automate this in a simple script:
cargo doc --no-deps
rm -rf ./docs
echo "<meta http-equiv=\"refresh\" content=\"0; url=build_wheel\">" > target/doc/index.html
cp -r target/doc ./docs
Feel free to get as fancy as you want for pulling the actual name. I've just hardcoded it ¯\(ツ)/¯.
When Github Pages tries to build your content, now it will find this root index page. Users will load this page and immediately refresh the page you intended to display, and all the internal links generated by rustdoc
will work as expected.
Neat.
Cover photo by Kelly Sikkema on Unsplash
Top comments (5)
I translated the script (and reordered it slightly) for a Windows bat file. Use as you please
This is quite cunning. I like it.
It's also how I ensured no broken links when I was migrating the root ssokolow.com site to Jekyll.
Just have a bunch of folders containing redirecting index.html files named after the old non-HTML routes from when I was using MoinMoin. (eg. ssokolow.com/ContactMe )
This is interesting but why not using docs.rs where all documentations are available as soon as you publish your crate ?
I'm using this for a crate that's part of a build process specific to one project. It's not likely to end up published, but I still want to provide accessible documentation. You're definitely right for most public packages, just use the existing infrastructure!