# tw
One command for a Markdoc corpus: lint it, format it, serve it to an editor,
preview the site and build the PDFs, with the same tools at the same versions
on every writer's machine and in CI.
`tw` links the rules — [markdoc-lint](https://github.com/markdoc-rs/markdoc-lint)
for structure, [markdoc-prose](https://github.com/markdoc-rs/markdoc-prose) for
prose — and launches the rest at the versions the corpus pins:
[markdoc-ls](https://github.com/markdoc-rs/markdoc-ls), markdoc-pdf and the
corpus's site generator.
## Install
Download the binary for your platform from the
[latest release](https://github.com/markdoc-rs/tw/releases/latest), each with a
`.sha256` beside it, and put it on your `PATH`:
| Linux (x86-64) | `tw-linux-x86_64` |
| Windows (x86-64) | `tw-windows-x86_64.exe` |
| macOS (Apple Silicon) | `tw-macos-aarch64` |
| macOS (Intel) | `tw-macos-x86_64` |
After that, `tw update` replaces it with the newest release. To build it from
source instead:
```
cargo install --git https://github.com/markdoc-rs/tw
```
## Getting started
In a corpus, a directory with `.tooling/` at its root:
```
tw setup # install the git hooks and fetch the pinned tools
tw check # lint the whole corpus, structure and prose
```
## Commands
| `tw check [PATH]...` | Lint the structure and the prose, and report both together. The whole corpus when no path is given. `--no-prose` for structure only, `--staged` for what git has staged, `--json` for CI and editors, `--list-rules` for what the corpus has turned on. Exits 1 when it finds something. |
| `tw setup` | Install the git hooks and fetch the pinned tools. Safe to re-run; `--no-tools` downloads nothing. |
| `tw update` | Replace this binary with the newest release, then re-pin the tools. |
| `tw fmt [ARGS]...` | Format the tags, with the pinned markdoc-ls. |
| `tw lsp` | Run the language server, the pinned markdoc-ls. |
| `tw preview` | Build and serve the site locally, with the generator `tw.toml` names under `[preview]`. |
| `tw build` | Render the manuals, with the pinned markdoc-pdf. |
| `tw completions <SHELL>` | Print a completion script for bash, zsh, fish, elvish or PowerShell. |
| `tw <name>` | Run `tw-<name>`, from `PATH` or the corpus's pinned tools, as git runs `git-<name>`. |
`tw help` lists them, and `tw <command> --help` says more about each.
The hooks `tw setup` installs, in `.githooks/` through `core.hooksPath`, run
`tw check --no-prose --staged` before a commit and `tw check --no-prose`
before a push. The prose pass is left to CI: it is too slow for a hook.
## The corpus
`tw` works from the corpus root: the nearest directory at or above where it
runs that holds `.tooling/`, or else `tw.toml` or `markdoc-lint.toml`. There
it reads:
- `.tooling/tooling-versions.json`: the version pinned for each tool `tw`
launches, and the forges they are released on. Downloads go to
`.tooling/bin/` and are checked against their `.sha256`.
- `tw.toml`: what the corpus adds. `[preview]` names its site generator,
`[tools.<name>]` other pinned programs, and `[[check.external]]` checks that
`tw check` runs and reports with its own.
- `markdoc-lint.toml` and `markdoc-prose.toml`: the rules' configuration.
- `.env`: a writer's own credentials, such as a token for a private forge. It
is used only when git ignores it.
A tool `tw` launches is looked for in this order: the path in its environment
variable (`MARKDOC_LS`, `MARKDOC_PDF`, or `<NAME>_BIN` for one from
`tw.toml`), `.tooling/tools/`, a sibling checkout's `target/release` (such as
`../markdoc-ls`), the pinned release, and last `PATH`.
## Building
```
cargo build --release
bash .github/scripts/check.sh # the gate CI runs: fmt, clippy, tests, a release build
```
## Licence
MIT