Hi all!
This post discusses an enhancement to Swift-DocC and Swift-DocC-Render that will allow developers to build DocC archives that can be hosted without custom routing. This is specifically designed to enable DocC to be used in additional static hosting environments, most notably GitHub Pages.
This change is meant as a quick solution to address a pressing need, and provides general goodness. But please know that we’ve heard the community’s feedback that they would love for Swift-DocC to directly emit static HTML, and this feature is high on the priority list.
The proposed implementation put together by Steve Scott (Scotty) and Dobromir Hristov is available here:
- Swift-DocC: https://github.com/apple/swift-docc/pull/44
- Swift-DocC-Render: Add static-hostable support, by allowing changing the baseUrl at runtime by dobromir-hristov · Pull Request #24 · apple/swift-docc-render · GitHub
Proposed Solution
To produce a new DocC archive that does not require custom routing rules for hosting on a simple Python HTTP server, you run the following:
docc convert MyFramework.docc --transform-for-static-hosting \
--output-path MyFramework.doccarchive
# Start a local Python server
cd MyFramework.doccarchive
python3 -m http.server
You can also now produce a DocC archive for hosting on the GitHub Pages environment at your my-framework-repo
repository.
Assuming, you’ve configured the GitHub Pages site at my-username.github.io/my-framework-repo
to render the documentation from the docs
directory at the root of the repository, you would run the following from the repository root to publish documentation:
docc convert MyFramework.docc --transform-for-static-hosting \
--static-hosting-base-path /my-framework-repo \
--output-path docs
git add docs
git commit -m "Update documentation."
git push
Background
A DocC archive is a static, single-page web application. As a web app, it contains just a single html
file and requires some configuration on the server in order to route all incoming requests to this html
file.
For example, when trying to access the “Formatting Your Documentation Content Page” in DocC’s documentation on Swift.org, the server accepts a request at the documentation/docc/formatting-your-documentation-content
path and routes it the base index.html
file at the root of DocC’s own archive.
For more information on the custom routing rules required to host a DocC archive on a server, please see the documentation on Swift.org.
However, if a you are hosting a DocC archive on a server where you don’t have the ability to customize routing rules, the request to documentation/docc/formatting-your-documentation-content
would fail because there is no file at that path.
Solution
The proposed solution will copy the index.html
file at the root of a DocC archive to all of the documentation paths in the given archive. This removes the requirement for custom routing rules but, in all other ways, Swift-DocC-Render will continue to behave the same way.
For example, when transformed for a static hosting environment, DocC’s own archive would look something like this:
DocC.doccarchive
├ data
│ │ formatting-your-documentation-content.json
│ │ distributing-documentation-to-other-developers.json
│ └ ...
├ documentation
│ ├ formatting-your-documentation-content
│ │ └ index.html
│ ├ distributing-documentation-to-other-developers
│ │ └ index.html
│ └ ...
├ js
├ css
└ ...
Because the DocC archive now contains an index.html
file at all documentation paths, the archive can be hosted without custom routing rules. This enables out-of-the-box support for simple file servers like Python’s HTTP server (python3 -m http.server
), and hosts that don’t expose custom routing, like GitHub Pages.
This a less-than-optimal solution because of the duplication of the index.html
file that is required. However, we feel that as we work towards emitting static HTML directly, this duplication is acceptable in the meantime as it supports a simpler hosting solution.
By default, Swift-DocC will continue emitting a single index.html
file for space efficiency in server environments that support custom routing. To get the new GitHub Pages-compatible behavior you will need to pass the --transform-for-static-hosting
flag, for now.
Base Path Configuration
This solution addresses the needs of developers who are hosting their documentation content at the root of their website (i.e. www.my-website.com/documentation/my-framework
). However, many developers may wish to host their documentation at a specific sub-path on their website. This is also a requirement for many hosting their documentation on GitHub Pages where developers will likely be hosting their documentation at my-username.github.io/my-repository/documentation/my-framework
. To support these scenarios, Swift-DocC-Render will add support for a configurable BASE_PATH
argument. This path will be configurable by Swift-DocC when producing a DocC archive for static hosting environments.
Implementation
The docc convert
command will add an additional flag and option:
--transform-for-static-hosting
: Produce a DocC archive that supports a static hosting environment.--static-hosting-base-path <static-hosting-base-path>
: The base path your documentation website will be hosted at.- For example, to deploy your site to
example.com/my_name/my_project/documentation
instead ofexample.com/documentation
, pass/my_name/my_project
as the base path.
- For example, to deploy your site to
When the --transform-for-static-hosting
flag is passed to a docc convert
invocation, the produced DocC archive will include an index.html
file at all documentation paths, making it compatible with static hosting environments.
In order to support base path customization, Swift-DocC-Render will vend a new file named template-index.html
. This file will include {{BASE_PATH}}
template placeholder tags that Swift-DocC will be able to replace with a user-provided path.
When a static hosting base path is provided to docc convert
via the --static-hosting-base-path
option, docc will replace all instances of {{BASE_PATH}}
in the new template-index.html
file vended by Swift-DocC-Render. Then it will copy this customized version of the index.html
file to all documentation paths. The produced archive will be compatible with static hosting environments at the given base path.
In addition, a new command will be added to docc
that allows for updating an existing DocC archive to make it compatible with a static hosting environment.
The usage for this command will be as follows:
OVERVIEW: Transform an existing DocC Archive into one that supports a static hosting environment.
USAGE: docc process-archive transform-for-static-hosting <source-archive-path> [--output-path <output-path>] [--static-hosting-base-path <static-hosting-base-path>]
ARGUMENTS:
<source-archive-path> `Path to the DocC Archive that should be processed.`
OPTIONS:
--output-path <output-path>
The location where docc writes the transformed archive.
If no output-path is provided, docc will perform an in-place transformation of the provided DocC Archive.
--static-hosting-base-path <static-hosting-base-path>
The base path your documentation website will be hosted at.
For example, to deploy your site to 'example.com/my_name/my_project/documentation' instead of 'example.com/documentation', pass '/my_name/my_project' as the base path.
-h, --help Show help information.
Alternatives Considered
We considered using Node.js to pre-render the content in the DocC archive out to static HTML. This format would inherently remove the requirement for custom routing rules. However, because this would add a run-time dependency on Node and have performance impacts on producing a compatible DocC archive, we decided to not take this route. When we do add support for static HTML in Swift-DocC, we’ll want to enhance the documentation compiler to emit HTML directly.