Awesome
yodoc
Keep document including commands and their results up to date.
yodoc is a CLI to maintain documents including commands and their results. When you write commands and their results in documents, it's hard to keep them up to date. They would become outdated soon.
yodoc resolves this issue. It executes commands, tests results, and generates documents based on template files.
:warning: Security
yodoc executes commands based on template files, so you shouldn't run yodoc if they are untrusted.
How to install
yodoc
is a single binary written in Go.
So you only need to put the executable binary into $PATH
.
brew install suzuki-shunsuke/yodoc/yodoc
scoop bucket add suzuki-shunsuke https://github.com/suzuki-shunsuke/scoop-bucket
scoop install yodoc
aqua g -i suzuki-shunsuke/yodoc
-
Download a prebuilt binary from GitHub Releases and install it into
$PATH
-
Go
go install github.com/suzuki-shunsuke/yodoc/cmd/yodoc@latest
How to use
- Scaffold a configuration file by
yodoc init
.
yodoc init # Scaffold a configuration file
- Edit the configuration file.
- Write templates in the source directory.
- Generate documents by
yodoc run
.
yodoc run # Update document
By default, yodoc searches template files and process all template files, but you can also process only specific template files.
yodoc run README_yodoc.md # [...<file>]
Usage
Environment variables
YODOC_CONFIG
: a configuration file pathYODOC_LOG_COLOR
: log color mode:auto
,always
,never
YODOC_LOG_LEVEL
: trace, debug, info, warn, error, fatal, panic
Configuration file paths
yodoc
searches a configuration according to the following order.
If no configuration file is found, yodoc
fails.
--config
YODOC_CONFIG
yodoc.yaml
,.yodoc.yaml
in the current directory :warning:yodoc.yml
and.yodoc.yml
are ignored
Configuration file
yodoc.yaml
# File paths are relative paths from the configuration file.
src: src # source directory where templates files are located
dest: . # destination directory where files are generated
delim:
# delim is a pair of delimiters in templates.
# This is optional.
left: "{{" # The default value is "{{"
right: "}}" # The default value is "}}"
src
and dest
are required.
yodoc searches template files from src
, and generates documents in dest
.
The file extension must be either .md
or .mdx
.
yodoc ignores directories .git
and node_modules
.
If src
and dest
are same, template file names must end with _yodoc.md
or _yodoc.mdx
, then yodoc generates .md
or .mdx
.
README_yodoc.md
=>README.md
README_yodoc.mdx
=>README.mdx
Template
Template files are rendered by Go's text/template.
Front matter
You can write YAML Front matter in the top of templates.
---
dir: "{{.SourceDir}}"
dest: README.md
delim:
left: "[["
right: "]]"
---
Front matters are removed from generated document. Front matter supports the following fields.
dir
dest
delim
dir
is rendered by Go's text/template.
The following variables are available.
SourceDir
: a directory where a template file existsDestDir
: a directory where a file is generatedConfigDir
: a directory where a configuration file exists
Annotation
yodoc supports the following annotations.
#-yodoc hidden
: Executes a script and check if it succeeds but doesn't show the script and the output#-yodoc run
: Executes a script and show the script. The command must succeed#!yodoc run
: Executes a script and show the script. The command must fail#-yodoc #
: Code comment. This isn't outputted#-yodoc check
: Checks the result of the previous#-yodoc run
#-yodoc dir <dir>
: Change the directory where a command is executed
#-yodoc run
, #!yodoc run
Executes a script and show the script. This annotation must use at the top of a code block surrounded by <code>```</code>. You can use the result in templates.
e.g.
<pre> ```sh #-yodoc run npm test ``` ``` {{.CombinedOutput -}} ``` </pre>#-yodoc hidden
Executes a script and check if it succeeds but doesn't show the script and the output. This annotation must use at the top of a code block surrounded by <code>```</code>. This annotation is used for preprocess, test, and clean up.
e.g.
<pre> ```sh #-yodoc hidden rm foo.json # Delete foo.json before `make init` ``` ```sh #-yodoc run make init ``` ```sh #-yodoc hidden test -f foo.json # Test if `make init` creates foo.json ``` # ... ```sh #-yodoc hidden rm foo.json # Clean up ``` </pre>#-yodoc dir <dir>
Change the directory where a command is executed. This annotation must use in a code block.
e.g.
#-yodoc hidden
#-yodoc dir foo
rm foo.json # Clean up
Checks
e.g.
<pre> ```sh #-yodoc run npm test ``` ```yaml #-yodoc check checks: - expr: ExitCode == 0 ``` </pre>The annotation #-yodoc check
is available at the top of a code block surrounded by <code>```</code>.
The content of the code block must be YAML.
checks
is a list of checks.
All checks must be true, otherwise it fails to generate document.
check has the following fields.
expr
: An expression of expr-lang/expr.
The expression must return a boolean. The following variables are passed.
Command
: Executed commandExitCode
: Exit codeStdout
: Standard outputStderr
: Standard error outputCombinedOutput
: Output combined Stdout and StderrRunError
: Error string if it fails to execute the command
The annotation #-yodoc check
can be also used in #-yodoc run
and #!yodoc run
blocks.
#-yodoc check <expr>
<pre>
```sh
#-yodoc run
#-yodoc check Stdout contains "foo"
npm test
```
</pre>
Template variables
In templates, the result of #-yodoc run
is available.
Command
: Executed commandExitCode
: Exit codeStdout
: Standard outputStderr
: Standard error outputCombinedOutput
: Output combined Stdout and StderrRunError
: Error string if it fails to execute the command
e.g.
<pre> ```sh #-yodoc run npm test ``` ``` {{.CombinedOutput}} ``` </pre>Template functions
sprig functions are available. But the following functions are unavailable for security reason.
env
expandenv
getHostByName
Furthermore, some custom functions are available.
Read
: Read a file
Read
{{Read "foo.yaml"}}
Read
takes one argument, which is a file path to read.
The file path is a relative path from the template file.
Read
returns a string which is the file content.
Automatic update by CI
You can update documents by CI automatically, but you need to be care about the security.
We recommend executing yodoc by push
event on the default branch and creating a pull request to update documents.
- https://github.com/suzuki-shunsuke/yodoc-workflow - Reusable workflow to update documents
- https://github.com/suzuki-shunsuke/poc-yodoc - Example of automation