How to build these docs#
The documentation is a Sphinx project written in reStructuredText and rendered with
the Book theme. Sources are in docs/; the generated site goes to
docs/_build/html/ and is not committed.
Install#
The docs extra installs Sphinx and the Book theme into the active virtual
environment:
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[docs]"
Build and view#
python -m sphinx -b html -W -E docs docs/_build/html
start docs/_build/html/index.html
Option |
Effect |
|---|---|
|
Build the HTML site. |
|
Treat warnings as errors, so a broken link, a missing toctree entry or a bad heading reference fails the build instead of shipping. |
|
Ignore the cached environment and re-read every file. Use it to pick up the
version and the “last updated” time, which are computed when |
For a quicker edit loop, drop -E and -W and rebuild; Sphinx then rebuilds only
changed pages. Run the full strict command before committing.
Where the pieces live#
File |
Purpose |
|---|---|
|
Sphinx settings: the |
|
The landing page, with the version and build time, and the top-level
|
|
The page that lists a folder’s documents in its own |
|
Generated output; listed in |
The sources sit directly in docs/ rather than in a docs/source/ folder,
because the build output is already kept apart in docs/_build/.
Version and last updated#
The version shown in the browser title and on the landing page comes from the
versionline inpyproject.toml.Last updated appears in every page footer and on the landing page. It is the time of the build, not of the last edit to each page, because the project is not required to be a Git repository. Per-page edit dates would need a Git-aware extension such as
sphinx-last-updated-by-git.
Publishing the docs to GitHub Pages#
The built site is published from a separate repository,
samkhalilian/samkhalilian.github.io, which GitHub Pages serves from
the root of its main branch at https://samkhalilian.dev/ (the custom domain
comes from the CNAME file). That repository contains only the contents of
docs/_build/html, plus two Pages files that are not part of the Sphinx output:
CNAME: the custom domain. Deleting it breakssamkhalilian.dev..nojekyll: lets GitHub Pages serve the_staticand_sourcesfolders.
Publishing mirrors docs/_build/html into a clone of that repository, keeping those
two files and .git:
Remove-Item -Recurse -Force docs\_build
python -m sphinx -b html -W -E docs docs/_build/html
git clone https://github.com/samkhalilian/samkhalilian.github.io.git $env:TEMP\pages
robocopy docs\_build\html $env:TEMP\pages /MIR /XD .git .doctrees /XF CNAME .nojekyll
git -C $env:TEMP\pages add -A
git -C $env:TEMP\pages status
git -C $env:TEMP\pages commit -m "Publish trade-engine docs"
git -C $env:TEMP\pages push
Notes:
Start from a clean build. Sphinx does not delete pages that no longer exist, so removing
docs/_buildfirst stops renamed or deleted pages from being published.``robocopy /MIR`` deletes anything in the target that is not in the source, apart from what is excluded (
.git,CNAME,.nojekyll). Run it only against the temporary clone, and readgit statusbefore committing.Robocopy exit codes 0 to 7 mean success (for example 1 means files were copied); 8 or higher is a failure.
Copy ``html``, not all of ``_build``.
.doctreesis Sphinx’s build cache and is excluded.The previous site is kept on a branch. Before this repository was changed to hold only these docs, its earlier contents (a separate blog) were saved on the
backup-before-docs-replacebranch, and they also remain in the Git history ofmain. To restore them, check out that branch or revert the publishing commit.Anything else published to this repository replaces these docs. If the blog is built and copied into
samkhalilian.github.ioagain, run the commands above afterwards.The published site is public, even though both repositories are private. This includes the
_sourcesfolder with the reStructuredText sources. Review the docs before publishing.
Naming conventions#
reStructuredText file names use snake_case, for example
multi_asset.rstandbuild_docs.rst, notmulti-asset.rst. The name in atoctreeor a:doc:reference is the same name without the extension. Folder names are single lowercase words where possible (database,appendix).Repository names use kebab-case, for example
trade-engine, nottrade_engine(see How this repo was built).
Writing pages#
Put a page in the folder that matches its subject: storage and schemas in
docs/database/, calculations and process pages indocs/, project and tooling notes indocs/appendix/.Add every new page to a
toctree. A page that is in notoctreetriggers a warning, which fails the strict build.Link pages with
:doc:`/folder/page`and sections with:ref:rather than file paths, so Sphinx checks the links.Write formulas with the
mathdirective or the:math:role; they are rendered by MathJax. Usecode:: textblocks for architecture sketches.Use Implemented and Required as defined in Trade Engine — v1 Spec, and label planned designs as planned.
When code changes behaviour, update the page that describes it in the same commit.
Converting Markdown drafts#
The first drafts were Markdown. They were converted once with pandoc through the
pypandoc_binary package, which bundles pandoc so nothing else needs installing.
It is not in the docs extra because it was only needed for that one-off
conversion:
import pypandoc
rst = pypandoc.convert_file(
"page.md", "rst", format="gfm+tex_math_dollars", extra_args=["--list-tables"]
)
--list-tables produces list-table directives instead of grid tables that
break when text changes, and tex_math_dollars turns $...$ into :math:
roles. Links between documents must then be rewritten from page.md to :doc:
references by hand or with a small script.
Troubleshooting#
Symptom |
Cause and fix |
|---|---|
|
The |
|
Add the page to a |
|
A name in a |
|
A section reference such as |
The version or the build time looks stale |
Rebuild with |
|
The line of |