Projects
A py-doc project is a folder with a py-doc.yml that lists its documents. py-doc build, py-doc lint, py-doc c4 and py-doc site find the nearest py-doc.yml above the current folder, or take --config.
Starting a project
py-doc init makes a project in the current folder, or in the folder it is given:
py-doc init # asks for the name and the options, in a terminal
py-doc init docs-project --name "Pump Controller" --c4 --site mkdocs -y
| Option | What it adds |
|---|---|
--name NAME |
The project name (default: the folder name) |
--c4 |
architecture/workspace.dsl, a C4 model, and a document generated from it |
--templates |
templates/reference.docx and reference.pptx: pandoc’s own, with py-doc’s callout styles in the Word one. They need the tool container |
--site mkdocs or --site starlight |
A site section in py-doc.yml and the site project in site/ |
-y, --yes |
Ask nothing: what is not given is left out |
It always writes py-doc.yml, with a comment on every setting, and docs/overview.md, a first document with YAML front matter, and adds build/, .py-doc/ and .structurizr/ to .gitignore. In a terminal, init asks for what the options do not say, and with --yes or in a script it asks nothing. A folder that already has a py-doc.yml is refused and left as it is. A file that is already there is kept and named, never replaced. The new project lints clean and builds at once, and init ends with the commands to run next.
The configuration file
One file describes documents, outputs, lint policy, C4 settings and the site. Paths are relative to the file. Every key is checked when the file loads, so a typo is an error that names its place, such as documents.guide.sources[1].page_brek.
project:
name: Technical documentation
outputs: # defaults for every document
docx:
template: templates/Template.docx
dir: build # where documents go unless they set a path
pptx:
split_level: 2
documents:
c4-guide:
title: C4 Architecture Modelling
author: Mark Bacon
version: "1.0.4"
document_number: GD-001
status: Proposed
keywords: [architecture, C4]
sources:
- index.md
- file: 01-foundations.md
heading_offset: 0 # shift every heading level (kept within 1 to 6)
page_break: true # start on a new page, or a new slide
title: Foundations # replaces the first heading, or adds one
site_path: basics/foundations # its page on a site (default: its place below the sources' folder)
- {file: draft.md, include: false}
variables: {version: "1.0"}
conditions: {internal: false}
outputs:
docx: {path: build/guides/c4-guide.docx}
pptx: {} # also build a deck
api:
sources:
- api/index.md
- {collection: endpoints, page_break: true} # every file of a collection, in order
collections: # named sets of source files, for any document to take in
endpoints: [api/endpoints/*.md] # a pattern adds its files sorted by path
bundles: # several documents in one output, each starting on a new page
handbook:
title: Sensor handbook
documents: [c4-guide, api]
outputs: {pdf: {}}
site: # a web site of the documents: see the web sites chapter
engine: mkdocs
dir: site
diagrams:
mermaid: # Mermaid configuration of every Mermaid diagram
look: classic
theme: neutral
theme: print # the theme of poster blocks (cards, chart...) in documents
poster: # settings for every poster: see the posters chapter
theme: brand/poster-theme.yml
logo: brand/logo.svg
posters: # HTML posters that `py-doc poster` builds
launch:
source: posters/launch.md
orientation: landscape
footer: {qr: "https://example.com/launch"}
lint:
exclude: [drafts]
rules:
DOC001: error # error, warning, info or off
DOC002: off
glossary:
Kubernetes: [k8s]
phrases:
utilise: use
acronyms:
min_length: 3
allowed: [SBOM]
scope: document # a definition in an earlier file of the same document counts
limits:
sentence_words: 40
- Documents join their sources in order. Properties come from the configuration, then from the first source’s front matter, then from its first heading. A document builds the formats listed under
outputs, or Word if none is listed. - Output options per format:
template,allow_missing_template,name,placeholder_prefix,markerandtocfor Word,split_levelandfooterfor PowerPoint,template,toc,nameandnumber_sectionsfor PDF and HTML, andheading_numbersfor every format. A document’s value overrides the default. The outputs chapter has the details. - Lint settings extend the built-in glossary, phrases and allowed acronyms. The linting chapter has every setting.
- C4:
c4.cli,c4.imageandc4.portsay how Structurizr runs. See the C4 chapter. - Diagrams:
diagrams.mermaidis Mermaid configuration for every Mermaid diagram, in documents, sites and posters, such aslook,theme,layoutorflowchart: {curve: linear}. A diagram’s own front matter wins, key by key. See Diagrams.diagrams.themeis the theme poster blocks are drawn in when a document uses them,printunless set. See Poster blocks in documents. - Reports:
reports.pathwrites the JSON build report of every build. - Posters:
posterslists the posterspy-doc posterbuilds, each with itssource,outputand settings, andposterholds settings for every poster, such as the company colours and logo. See the posters chapter. - Collections name sets of source files: a list of files and patterns such as
docs/guide/*.mdordocs/**/*.md. A document takes one in with{collection: name}, which can carryheading_offsetandpage_break. The same file can be in several collections and documents. - Bundles build several documents as one output, beside their own outputs. A bundle lists its
documentsand can set the same properties,outputs,variablesandconditionsas a document. Its own properties come first, then the first document’s front matter. Each document after the first starts on a new page.py-doc build handbookbuilds one bundle. A bundle is not on the site unlesssite.documentsnames it. - Content generators (
content.generators) write Markdown files from other sources before the build, and build settings (build.lint,build.lint_report,build.site,build.generate) say whatpy-doc builddoes around the documents. Both are in Generators, the build pipeline and analysis.
Building
py-doc build # every document, then every poster
py-doc build c4-guide -f pptx # one document, one format
py-doc build launch # one poster, by its name under posters:
py-doc build -f poster # only the posters
py-doc build --var version=2.1 --condition internal=true
py-doc build --keep-going # list every broken diagram, not just the first
py-doc build --lint --site # generate, lint, build the documents, then the site
--var and --condition win over the values in the file. A document that fails does not stop the others: each failure is named, a summary follows, and the exit status is 1. The generators, lint and site steps around the documents are described in the build pipeline.
Converting single files
py-doc docx and py-doc slides convert files without a py-doc.yml:
py-doc docx Technical_Specification.md -o Technical_Specification.docx
py-doc docx Technical_Specification.md -t Template.docx
py-doc docx docs/ -o dist/docx/ # a whole folder, structure kept
py-doc slides talk.md -o talk.pptx
py-doc slides talk.md -t Corporate.pptx --split-level 1
py-doc docx Technical_Specification.md --watch # build on every save, with a live HTML preview
| Option | Commands | Description |
|---|---|---|
input |
both | A Markdown file, or a folder searched for .md and .markdown files in any capitalisation |
-o, --output |
both | The output file, or a folder. A folder (an existing one, or a path ending in /) gets <name>.docx or <name>.pptx inside it |
-t, --template |
both | A reference .docx or .dotx (Word), or .pptx or .potx (PowerPoint). -r, --reference is the old slides name |
--allow-missing-template |
both | Warn and use a blank document if the template file is missing (default: fail) |
--split-level N |
slides | Start a new slide at each heading up to level N (default 2) |
--watch |
both | Build again on every save, and serve an HTML preview of each file that reloads itself (Ctrl+C stops) |
--port N |
both | With --watch, the local port to serve the preview on (default: a free one) |
--no-open |
both | With --watch, do not open the browser |
-q, -v |
both | Only warnings and errors, or debug detail |
--version |
both | Print the version |
A file that uses [[IF:]] needs its conditions defined, and only py-doc build can set them, so build such a file as a document of a py-doc.yml. For a folder of files:
- Hidden folders and
node_modules,venv,env,site-packages,__pycache__,dist,buildandvendorare skipped, and so is an output folder inside the input. - One bad file does not stop the rest. Each failure is printed on stderr, a summary follows, and the exit status is
1if anything failed. - Two sources that would write the same output (
a.mdanda.markdown) are refused before anything is converted. - The input is checked before any folder is created, so a typo leaves nothing behind.
Live preview
--watch builds the files, then builds them again whenever a source below their folder changes. A source is the Markdown, an included file, a picture, a diagram source or the template. For each .docx or .pptx it also writes an HTML twin of the same Markdown, to .py-doc/preview/ below the input’s folder. It serves the twins on this computer only. The page in the browser reloads after each build, and a build that fails shows its error over the last good page.
- A document open in Word or PowerPoint cannot be written, so it is left as it is, with a warning, and its preview is still updated.
- The twin shows page breaks as dashed lines, speaker notes in boxes and columns side by side. The twin of a deck shows each slide as a numbered 16:9 box, split as PowerPoint splits it.
- The twin is a preview, not an output. Build HTML with
py-doc buildandoutputs: html.
The VS Code extension starts --watch for the open file and shows the preview beside it.
The old commands py-doc2docx, py-doc2slides and py-doclint still work and print a one-line note naming their replacement. -q hides the note.
File names and versions
- File names: the default is exactly the path given.
name: "{name}-{version_safe}"on any output makesguide-1_2_3.docx. The fields are{name}(the file name it would have had),{version}(an error when there is no version) and{version_safe}(dots become underscores, no version givesx_x_x). - Version from Git:
version: git, in the configuration or the front matter, isgit describe --tags --alwaysof the project folder. Outside a repository, or without a commit, the build fails instead of inventing a version. - Status templates: with
status: Draftandtemplate: Template.docx,Template_Draft.docx(thenTemplate_draft.docx) is used when it exists, else the base template, and the log says which. The same rule applies to PowerPoint, LaTeX and HTML templates.
Build report
py-doc build --report build.json, or reports: {path: build.json} in py-doc.yml, writes a JSON report of the build:
- the py-doc version, the image tag and id, and the version of each tool used;
- each document with its sources (words, sentences, paragraphs) and its outputs (size and SHA-256);
- the icons each poster uses, with their pack and licence;
- every diagram: type, file, line, and whether the cache served it;
- template problems, and every warning with file and line. Keys are in a fixed order and there are no times unless you pass
--timestamps, which also adds the render time of each diagram. The report is written when the build fails too, withstatus: failedand the error. Word and PowerPoint files contain the time they were written, so their checksums differ between builds. The schema ispy_doc/report.schema.json.