An open API service indexing awesome lists of open source software.

https://github.com/zenor0/mdship

pack and ship your markdown
https://github.com/zenor0/mdship

cli go markdown md mermaid pandoc productivity typst

Last synced: 11 days ago
JSON representation

pack and ship your markdown

Awesome Lists containing this project

README

          

![mdship banner](assets/mdship-banner.png)

Deliver your Markdown content anywhere in one command. mdship is a CLI tool and Go library for packaging Markdown context and converting to various formats via Pandoc and other tools.

## Key features

- **Resource Discovery and Packaging**: Automatically discover local and remote resources (images, PDFs, etc.) linked in your Markdown, download remote assets, and package them into a structured workspace for conversion.
- **BibTex Citation Trimming**: Automatically extract and trim BibTeX entries for only the citations used in your document, keeping your bibliography lean and relevant.
- **Built-in neat Typst/Word templates**: Use mdship's built-in Typst templates for quick and beautiful PDF generation, or create your own templates for custom styling.
- **Mermaid Rendering**: Optionally render Mermaid diagrams to images before conversion, ensuring your diagrams look great in the final output.
- **Conversion Pipeline**: Convert your Markdown to various formats (PDF, HTML, Typst, etc.) using a configurable pipeline that can include pre-processing steps (like Mermaid rendering) and post-processing steps (like Typst compilation).

## Architecture

Two stages keep the system extensible:

1) **pack**: discover resources/citations, download remote assets, trim BibTeX,
and build a minimal workspace.
2) **convert**: run a conversion pipeline against packed markdown with predictable paths.

## Workspace layout (pack output)

```
/
document.md
manifest.json
bibliography.bib (optional)
assets/ (local files copied here)
remote/ (downloaded files)
```

## Installation

Install the CLI with Go:

```bash
go install github.com/zenor0/mdship/cmd/mdship@latest
```

For reproducible installs, prefer a tagged version instead of `latest`:

```bash
go install github.com/zenor0/mdship/cmd/mdship@v0.1.0
```

Make sure your Go bin directory is on `PATH`:

```bash
export PATH="$(go env GOPATH)/bin:$PATH"
```

Then verify the installation and check which external tools are still needed:

```bash
mdship --version
mdship check
```

## Requirements

- Go 1.24+ (only required for `go install` or local development)
- Pandoc on PATH
- Mermaid CLI (`mmdc`) when Mermaid rendering is enabled (pack defaults to enabled)
- Typst when compiling to PDF/PNG or using typst compile

## Local checks before commit

To catch the same Go formatting, vet, lint, and test failures before pushing, run:

```bash
make pre-commit
```

For a fuller local pass that also checks `go mod tidy` drift and race tests, run:

```bash
make ci-local
```

Install the repo-pinned `golangci-lint` version used by CI with (it is stored under `.tools/bin`):

```bash
make lint-install
```

`golangci-lint` is pinned in `.golangci-version`, and GitHub Actions reads that same file, so you only need to update one place when bumping the linter version. `make pre-commit` will auto-install or refresh that pinned version locally when missing or stale.

If you want Git to run the fast checks automatically before each commit, enable the repo hook once:

```bash
git config core.hooksPath .githooks
```

## Usage

Check external dependencies:

```bash
mdship check
mdship check --format json
```

`check` reports `pandoc`, `mmdc`, and `typst` so you can validate pack + convert toolchains up front.

### Structured error output for integrations

On command failure, mdship still prints a human-readable error line to `stderr`.
When `stderr` is non-interactive (pipe/file), mdship also appends one machine-readable line:

```text
MDSHIP_ERROR_JSON: {"error":{"source":"cli","code":"...","kind":"...","message":"...","suggestions":[...],"details":{...}}}
```

You can force this behavior with `MDSHIP_ERROR_JSON=1` or disable it with `MDSHIP_ERROR_JSON=0`.
Common codes include `CLI_FLAG_INVALID`, `CLI_DEPENDENCY_MISSING`, `CLI_CONFIG_INVALID`,
`CLI_PROFILE_INVALID`, `CLI_FILE_MISSING`, and `CLI_RESOURCE_MISSING`.

Pack a Markdown file:

```bash
mdship pack ./notes/example.md --out-dir ./mdship-out
```

By default, `pack` only searches the input directory for relative resources (`--parent-depth=0`). Increase `--parent-depth` (or add `--resource-path`) when you intentionally want parent-directory lookup.

Clean previously generated workspace artifacts before writing fresh outputs:

```bash
mdship pack ./notes/example.md --out-dir ./mdship-out --clean
```

Add resource paths and bibliography files:

```bash
mdship pack ./notes/example.md \
--resource-path ./attachments \
--bibliography ./refs/library.bib
```

Override Pandoc markdown output settings during pack:

```bash
mdship pack ./notes/example.md --pandoc-arg=--wrap=preserve
```

Convert the packaged document:

```bash
mdship convert --input ./mdship-out/document.md --to typst
```

Select a built-in conversion profile (e.g., Typst template preset):

```bash
mdship convert --input ./mdship-out/document.md --profile typst/default
```

Use Typst with a profile (embedded by default):

```bash
mdship convert --input ./mdship-out/document.md --to typst \
--profile typst/default
```

Use a custom profile on disk:

```bash
mdship convert --input ./mdship-out/document.md --to typst \
--profile /path/to/your/profile.yaml
```

Built-in profiles live under `modules//profiles`. You can also point `--profile` at a local `profile.yaml` (or a profile directory).

Release binaries and `go install` builds include built-in profiles from embedded assets. You can verify them with `mdship profiles` after installation.

List built-in profiles plus additional profile directories:

```bash
mdship profiles
mdship profiles --profile-dir ./modules --profile-dir /path/to/custom/modules
mdship profiles --profile-dir ./modules --verbose
mdship profiles --profile-dir ./modules --format json
```

`profile.yaml` defines pandoc CLI args plus template metadata. `args` can be raw strings or structured YAML (unset fields are skipped):

```yaml
meta:
name: Typst Default
alias: [default]
tags: [typst]
author: mdship
description: Default typst template profile.
args:
to: typst
standalone: true
template: profiles/default/template.typst
lua-filter:
- common/filters/html-br-linebreak.lua
- profiles/default/filters/callout-blocks.lua
metadata:
example: true
```

Rules of thumb: keys map to Pandoc flags, `true` adds a flag, lists repeat flags, and `metadata`/`variable` accept maps.

Render Mermaid blocks before conversion:

```bash
mdship convert --input ./mdship-out/document.md --to pdf --mermaid
```

Configure a conversion chain explicitly:

```bash
mdship convert --input ./mdship-out/document.md --to pdf \
--pipeline mermaid,pandoc:typst,typst-compile
```

Keep intermediate Typst output when compiling to PDF/PNG:

```bash
mdship convert --input ./mdship-out/document.md --to pdf --pipeline typst,typst-compile --typst-compile-keep
```

Pass extra Pandoc arguments after `--`:

```bash
mdship convert --input ./mdship-out/document.md --to typst -- --template template.typst
```

Ship a markdown file (pack + convert in a temp workspace):

```bash
mdship ship ./notes/example.md --to typst
```

When `ship` runs in default `file` mode and `--out` is omitted, output files are written to the current working directory (for example `./example.typ`).

When `ship` writes outputs in `file` mode, existing conflicting files are protected by default (primary output + sidecars). In an interactive terminal, mdship prompts before overwrite; in non-interactive runs it fails safely.

Use `--force` to overwrite without prompting:

```bash
mdship ship ./notes/example.md --to typst --force
```

When using `ship`, `--resource-path/-r` is also applied to the pack stage so external assets can be collected into the packaged workspace:

```bash
mdship ship ./notes/example.md --to typst --resource-path ./attachments
```

Ship into a directory or zip archive:

```bash
mdship ship ./notes/example.md --to typst --ship-package dir --out ./dist
mdship ship ./notes/example.md --to pdf --ship-package zip --out ./dist/example.zip
```

`ship` now preserves packaged sidecar resources (`assets/`, `remote/`) for text-like outputs (for example Typst/Markdown/HTML) so relative links keep working after export. It also writes a ship report with warnings/missing resources for downstream tooling:

- file mode: `.ship-manifest.json`
- dir/zip mode: `ship-manifest.json`

`ship-manifest.json` and preflight reports now share the same JSON envelope (`version: 0.2.0`) so external callers can parse one schema for both dry-run checks and real shipments.

Run a preflight check (pack-only) before full ship, and fail on any warnings/missing resources:

```bash
mdship ship ./notes/example.md --preflight --strict --report-out ./dist/preflight-report.json
```

Use `pack --strict` to fail when unresolved resources or warnings are detected:

```bash
mdship pack ./notes/example.md --strict --report-out ./mdship-out/preflight-report.json
```

Override a specific markdown resource target without moving files into resource paths:

```bash
mdship ship ./notes/example.md --preflight --strict \
--resource-map "images/logo.png=/tmp/uploads/new-logo.png"
```

Use a config file (YAML or JSON) to provide defaults:

```bash
mdship --config ./mdship.yaml pack ./notes/example.md
```

The default config lives at `internal/config/default.yaml` (copy it as a starting point). CLI flags override config values when provided. For module layout conventions, see `docs/modules.md`.

For an implementation-based CLI input/output/error contract, see `docs/cli-contract.md`.

Profiles can be declared in config and selected via `convert.profile` or `--profile`:

```yaml
convert:
profiles:
typst/default:
path: typst/default
profile: typst/default
```

Print the default or effective config:

```bash
mdship config
mdship --config ./mdship.yaml config --effective
```

## Example

See `examples/example.md` for a minimal Markdown + asset + bibliography setup.

## Contact
For questions, feedback, or contributions, please open an issue or reach out on GitHub Discussions.

## License
mdship is licensed under the MIT License. See [LICENSE](LICENSE) for details.