Metadata-Version: 2.4
Name: nide
Version: 2026.7.3
Summary: A bound volume (Finnish: nide) - assemble markdown text files into gfm-plus, html, and pdf channel outputs.
Author-email: Stefan Hagen <stefan@hagen.link>
Maintainer-email: Stefan Hagen <stefan@hagen.link>
License-Expression: MIT
Project-URL: Documentation, https://codes.dilettant.life/docs/nide
Keywords: developer-tools,documentation,markdown
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: jsonschema>=4.26.0
Requires-Dist: kaava>=2026.6.20
Requires-Dist: python-jsonpath>=2.0.2
Requires-Dist: PyYAML>=6.0.3
Requires-Dist: vyyhti>=2026.6.21
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# nide

A bound volume (Finnish: nide) — assemble Markdown source files into gfm-plus, html, and pdf channel outputs.

Requires Python 3.11 or later.

## Install

```
pip install nide
```

## Manual

The [man page](docs/nide.1) provides the CLI reference (`man nide` after placing the file on your `MANPATH`):

```sh
mkdir -p ~/.local/share/man/man1
cp docs/nide.1 ~/.local/share/man/man1/
```

## Quickstart

Run `nide` with no arguments for a usage summary, or `nide --version` to check the installed version.
For a dedicated feature walkthrough you can follow in minutes visit [quickstart](quickstart/README.md).
A step-by-step guided build of a document pipeline is provided in the [tutorial](tutorial/README.md).

## Pipeline

```
nide harvest              →  build/section-*.json, build/example-*.json

nide assemble -t html     →  build/tmp.md, build/toc-mint.json
pandoc                    →  build/tmp.html
nide inject               →  build/injected.html
tidy                      →  delivery HTML

nide assemble -t pdf      →  build/pdf.md
liitos                    →  delivery PDF
```

## Commands

`nide` has three subcommands.

**`nide assemble`** splices a list of Markdown source files into a single
assembled document, driving channel-specific transformations:

- Section headings are numbered and anchored for html and gfm-plus.
- Citation definition files are expanded into formatted inline citation entries.
- Glossary definition files are expanded into `<dl>` elements for the html channel.
- Cross-references (`[sec](#label)`, `[cite](#label)`, `[eg](#label)`) are resolved
  from JSON look-up tables produced by `nide harvest`.
- A table-of-contents data file (`build/toc-mint.json`) is written alongside the html output.

**`nide inject`** post-processes the HTML file that pandoc has produced from
nide's `build/tmp.md`, applying:

- Custom HTML table of contents (built from `build/toc-mint.json`).
- `<title>` element replaced with the value of `html-title` from config.
- Base and skin CSS inlined; `<link>` tags removed.
- Remote logo URL replaced with a local data URL.
- Image `src` attributes optionally replaced with base64 data URLs.

The result is written to `build/injected.html`.

**`nide harvest`** scans the Markdown sources and writes JSON look-up table (LUT)
files for section and example cross-references.  Run it before `nide assemble`
whenever source files change.

Three output channels are supported in assembly:

| Channel    | Output                                 | Intended consumer        |
|:-----------|:---------------------------------------|:-------------------------|
| `html`     | `build/tmp.md` + `build/toc-mint.json` | pandoc → `nide inject`   |
| `gfm-plus` | `build/tmp.md`                         | direct delivery          |
| `pdf`      | `build/pdf.md`                         | `liitos`                 |

## Configuration

All settings are read from `etc/assembly-config.yaml` (override with `-c`).
Every key is optional; the built-in defaults are listed below.

### Assembly keys

```yaml
binder: bind.txt
binder-ignores:
  gfm-plus: []
  html: []
  pdf: []
build-path: build
citation-skip-prefixes:
- '#'
citation-sources: []
cite-cosmetics-template: '**\[**<span id="$label$" class="anchor"></span>**$code$\]** $text$'
delete-when:
- contains: '<mark title="Ephemeral region marking">'
  delete:
  - '<mark title="Ephemeral region marking">'
  - '</mark>'
etc-path: etc
first-authored-section: '# Scope'
glossary-sources: []
html-title: No Title Given
logo-local-path: images/OASISLogo-v3.0.png
logo-url: https://docs.oasis-open.org/templates/OASISLogo-v3.0.png
sec-no-toc-postfix: '{.unnumbered .unlisted}'
section-display-to-label-db: section-display-to-label.json
section-display-to-text-db: section-display-to-text.json
section-label-to-display-db: section-label-to-display.json
section-reference-style: number
source-path: src
toc-template:
- '$sec_cnt_disp$ [$text$](#$label$)  '
- "\t$sec_cnt_disp$ [$text$](#$label$)  "
- "\t\t$sec_cnt_disp$ [$text$](#$label$)  "
- "\t\t\t$sec_cnt_disp$ [$text$](#$label$)  "
- "\t\t\t\t$sec_cnt_disp$ [$text$](#$label$)  "
tok-sec: "<a id='$thing$'></a>"
track-examples: false
```

The `section-*-db` files are look-up tables produced by `nide harvest` and must
be present before running `nide assemble` with cross-references.

### Inject keys

```yaml
html-inject-css-base: ''          # path to base CSS file (empty = skip)
html-inject-css-skin: ''          # path to skin CSS file
html-inject-logo-data-url: ''     # path to logo data URL .txt file (empty = skip)
html-inject-logo-remote-url: ''   # remote logo URL to replace
html-inject-toc-trigger: '<h1 id="table-of-contents'
html-inject-intro-trigger: ''     # HTML trigger for TOC end; both triggers required
html-inject-images: false         # inline image data URLs
html-inject-images-path: build/data-url
```

Both `html-inject-toc-trigger` and `html-inject-intro-trigger` must be non-empty for
TOC replacement to occur.
The trigger values are pandoc-generated HTML id attributes and depend on the heading text.

## Options

### Global options

```
nide [-V|--version]
nide version
```

| Option              | Description                  |
|:--------------------|:-----------------------------|
| `-V`, `--version`   | Print version string and exit |
| `version`           | Subcommand alias for `--version` |

### `nide assemble`

```
nide assemble [-d|--debug] [-c PATH|--config PATH] [-t CHANNEL|--target CHANNEL]
```

| Option       | Default                    | Description                                  |
|:-------------|:---------------------------|:---------------------------------------------|
| `-t CHANNEL` | `html`                     | Output channel: `gfm-plus`, `html`, or `pdf` |
| `-c PATH`    | `etc/assembly-config.yaml` | Path to the assembly configuration file      |
| `-d`         | off                        | Debug mode: write per-stage snapshot files   |

### `nide inject`

```
nide inject [-c PATH|--config PATH]
```

| Option    | Default                    | Description                             |
|:----------|:---------------------------|:----------------------------------------|
| `-c PATH` | `etc/assembly-config.yaml` | Path to the assembly configuration file |

### `nide harvest`

```
nide harvest [-c PATH|--config PATH]
```

| Option    | Default                    | Description                             |
|:----------|:---------------------------|:----------------------------------------|
| `-c PATH` | `etc/assembly-config.yaml` | Path to the assembly configuration file |

### Environment

| Variable       | Effect                                                       |
|:---------------|:-------------------------------------------------------------|
| `NIDE_CONFIG`  | Default config path when `-c` is not given (all subcommands) |
| `NIDE_DEBUG`   | Enable debug output; equivalent to `-d` (assemble mode)      |
| `DUMP_LUT`     | Write back section LUT files to `etc-path` after assembly    |

## Dependencies

- [jsonschema](https://pypi.org/project/jsonschema/) — JSON Schema validation
- [kaava](https://pypi.org/project/kaava/) — typed configuration from YAML
- [python-jsonpath](https://pypi.org/project/python-jsonpath/) — JSONPath expression scanning
- [PyYAML](https://pypi.org/project/PyYAML/) — YAML parsing
- [vyyhti](https://pypi.org/project/vyyhti/) — Markdown embedding scanner

## Design and requirements

| Document                            | Identifier  | File                                            |
|:------------------------------------|:------------|:------------------------------------------------|
| Software Requirements Specification | KOO-SRS-001 | [requirements/srs/](requirements/srs/README.md) |
| Software Design Description         | KOO-SDD-001 | [design/sdd/](design/sdd/README.md)             |

Both documents follow the MIL-STD-498 DID structure and are rendered into
the documentation site alongside the quickstart and tutorial.

## Bug Tracker

Any feature requests or bug reports shall go to the [todos of nide](https://todo.sr.ht/~sthagen/nide).

## Primary Source repository

The main source of `nide` is on a mountain in Central Switzerland under
configuration control ([fossil](https://fossil-scm.org/)).

## Contributions

If you like to share small changes under the repositories license please kindly
do so by sending a patchset.
You can send such a patchset per email using [git send-email](https://git-send-email.io).

## Support

Please kindly submit issues at https://todo.sr.ht/~sthagen/nide or write plain
text email to ~sthagen/nide@lists.sr.ht to support.
Thanks.

## Changes

See `docs/changes.md` for the release history.

## Coverage

The test suite maintains 100% branch coverage.
The HTML report (if generated) is in `site/coverage/`.

## SBOM

Runtime dependency information is published in `docs/sbom/` in SPDX 3.0 (JSON-LD)
and CycloneDX 1.6 (JSON) formats.
See `docs/sbom/README.md` for the component inventory and validation guide.
