@openpresentation/cli 0.15.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @openpresentation/cli
2
2
 
3
- A local CLI for agents and people working with `.opf.json` presentations. Create documents, validate them, apply precise edits, paginate content, embed the catalog records a deck uses for offline use (`opf embed`), inspect the bundled schemas and the default catalog, and render, export (PPTX, PDF, PNG, SVG) and import (PPTX) files. Node 22 or later on macOS, Linux, or Windows is required (`engines.node` `>=22` from the release after 0.10.0; 0.10.0 and earlier 24.x-only releases make npm on Node 22 or 26 silently install the 0.7.0 CLI, which has no `export` or `render` command).
3
+ The `opf` command, for agents and people working with OPF presentations. Create documents, validate them, apply precise edits, paginate content, embed the catalog records a deck uses for offline use (`opf embed`), inspect the bundled schemas and the default catalog, render, export (PPTX, PDF, PNG, SVG), convert and import (PPTX) files. Node 22 or later on macOS, Linux, or Windows is required (`engines.node` `>=22` from the release after 0.10.0; 0.10.0 and earlier 24.x-only releases make npm on Node 22 or 26 silently install the 0.7.0 CLI, which has no `export` or `render` command).
4
4
 
5
- The CLI bundles its OPF schema, catalogs, and validator. It needs no separate core package, API key, or network connection at runtime. `opf --version` reports the CLI and bundled core versions. Validation and editing never render; successful validation is not visual verification. `opf render`, `opf export` and `opf import` use the optional peers `@openpresentation/opf-render` and `@openpresentation/opf-pptx` (see [Render, export and import](#render-export-and-import)).
5
+ The CLI depends on `@openpresentation/opf` (core), which holds the OPF schema, catalogs and validator and reads and writes the text formats, and whose `@openpresentation/opf/node` engine reads and writes files; the CLI is the command over it. It needs no API key or network connection at runtime. `opf --version` reports the CLI and the installed core versions. Validation and editing never render; successful validation is not visual verification. `opf render`, `opf export`, `opf convert` and `opf import` use the optional peers `@openpresentation/opf-render` and `@openpresentation/opf-pptx` (see [Render, export and import](#render-export-and-import)).
6
6
 
7
7
  ## Install
8
8
 
@@ -13,9 +13,9 @@ npm install -g @openpresentation/cli
13
13
  opf --version
14
14
  ```
15
15
 
16
- Or install it as a development dependency and use `npx --no-install opf`. CLI 0.11.0 bundles OPF 0.13.0 (chart and table data: number formats, datasets and `chart.mapping`; plus templates and variables, numbered lists, footnotes and captions, chart options, the 0.01 pt font grid, the design fields, the 100-layout catalog and the pinned gallery default catalog), including the reference layer (`variables`, ColorRef, payload ids, and the command then named `opf bundle`, which is `opf embed` from OPF 0.15), complete code and quote composition, source-preserving pagination and readability floors, styled/merged table cells, shared headers/footers, `opf lint`, and the six OPF agent skills. Browser rendering and editable PowerPoint export require the coordinated library releases documented in [the compatibility matrix](../../docs/compatibility-matrix.md).
16
+ Or install it as a development dependency and use `npx --no-install opf`. The command covers creating, validating, editing, paginating, embedding, linting, filling, rendering, exporting, converting and importing; `opf --help` lists it, and [the compatibility matrix](../../docs/compatibility-matrix.md) names the library releases that go with each CLI. Applications use core's file API instead of the command: see [From code](#from-code).
17
17
 
18
- To verify the standalone package from source, run `pnpm install` and `pnpm test:cli:packed`. This creates `artifacts/cli/openpresentation-cli-0.11.0.tgz`, which can be installed using its absolute path. For source development, run `pnpm --filter @openpresentation/cli build` and `node packages/cli/dist/index.js --help`.
18
+ To verify the standalone package from source, run `pnpm install` and `pnpm test:cli:packed`. This creates `artifacts/cli/openpresentation-cli-<version>.tgz` (with the core tarball it depends on), which can be installed using its absolute path. For source development, run `pnpm --filter @openpresentation/cli build` and `node packages/cli/dist/index.js --help`.
19
19
 
20
20
  ## Install agent skills
21
21
 
@@ -48,7 +48,7 @@ opf create - --title "Launch decision" | opf validate -
48
48
  opf create imported.opf.json --from - < authored.opf.json
49
49
  ```
50
50
 
51
- `opf validate` is the one checker: it reads the file as strict JSON text (or as YAML, for a name ending `.yaml`/`.yml` or `--input-format yaml`) and prints the report (`valid`, `schemaValid`, `findings`, `counts`, `checks`), the input's SHA-256 digest and the bundled core version. Each finding has a stable `opf/<rule>` id, a severity, a category (`format`, `references`, `policy`, `accessibility`, `layout`, `content`), a JSON Pointer path, the source line and column, a hint and sometimes suggested fixes. Only format, references and policy findings are errors by default, so `valid` keeps meaning "correct OPF"; accessibility, layout and content findings are warnings and info. A content reference that resolves nowhere is the warning `opf/unresolved-reference`; a `name:id` prefix that names no catalog group is the error `opf/undeclared-catalog`.
51
+ `opf validate` is the one checker: it reads the file as strict JSON text (or as YAML for a name ending `.yaml`/`.yml` or `--input-format yaml`, or as a Markdown deck for a name ending `.opf.md` or `--input-format markdown`) and prints the report (`valid`, `schemaValid`, `findings`, `counts`, `checks`), the input's SHA-256 digest and the core version. Each finding has a stable `opf/<rule>` id, a severity, a category (`format`, `references`, `policy`, `accessibility`, `layout`, `content`), a JSON Pointer path, the source line and column, a hint and sometimes suggested fixes. Only format, references and policy findings are errors by default, so `valid` keeps meaning "correct OPF"; accessibility, layout and content findings are warnings and info. A content reference that resolves nowhere is the warning `opf/unresolved-reference`; a `name:id` prefix that names no catalog group is the error `opf/undeclared-catalog`.
52
52
 
53
53
  ```sh
54
54
  opf validate deck.opf.json # everything, JSON report
@@ -129,6 +129,8 @@ opf import-data revenue.csv --as chart --category Quarter --series '["Revenue","
129
129
 
130
130
  Data can come from a file or stdin (`-`). JSON accepts arrays of records, row matrices, or `{columns, rows}`. `--path /slides/0/table` replaces or adds a table field inside an existing parent; use `/chart` for charts. With `--into` and no path, a new slide is appended. Other options include `--format csv|tsv|json`, `--delimiter`, `--no-header`, `--columns` (a JSON array), and `--title`. Preview on stdout by omitting an output destination. All file writes validate the complete document. CSV table strings are preserved; chart measures must be numeric (strict decimal syntax: `12%` or `$5` is rejected). `--dataset <id>` writes the data into the deck's top-level `datasets` map (replacing that dataset's columns and rows, keeping the format of each column whose name is unchanged, and recording the file as its `source`) and references it from the table or chart, so several tables and charts can share it. Data is embedded, not linked to the source file.
131
131
 
132
+ Import is deterministic. A new slide is named `data-` plus eight hex digits of a SHA-256 over the data and the import options (`data-xxxxxxxx-2`, `-3` if the deck already has the id); `--id <slideId>` names it instead and fails if the id is taken. With `--dataset`, `source.src` is the data file relative to the deck's folder with `/` separators, and `source.retrieved` is set only by `--date YYYY-MM-DD` (the command never reads the clock).
133
+
132
134
  ## Fill a template
133
135
 
134
136
  A template is an OPF file with `"template": true` and variables (`{{id}}` tokens and `var:id` references, see [templates and variables](../../docs/templates-and-variables.md)). `opf fill` resolves them from data:
@@ -152,7 +154,7 @@ opf catalog layouts
152
154
  opf catalog fontSchemes roboto
153
155
  ```
154
156
 
155
- `schemas` and `catalogs` list available names/kinds. `schema` returns the whole schema or a branch addressed by a pointer into the schema. `catalog` returns the records in a kind, keyed by id, or one exact ID. They inspect the default catalog the CLI bundles (the full pptx.gallery catalog of its core) and do not fetch galleries.
157
+ `schemas` and `catalogs` list available names/kinds. `schema` returns the whole schema or a branch addressed by a pointer into the schema. `catalog` returns the records in a kind, keyed by id, or one exact ID. They inspect the default catalog of the core it runs on (the full pptx.gallery catalog) and do not fetch galleries.
156
158
 
157
159
  ```sh
158
160
  opf paginate decision.opf.json paginated.opf.json
@@ -179,27 +181,52 @@ Embed copies every catalog record the document references — including transiti
179
181
  ## Markdown and outlines
180
182
 
181
183
  `opf from-md <deck.md|-> [output.opf.json|output.opf.yaml|-] [--split <rules|headings>] [--title <text>] [--force] [--fail-on <level>]` converts Markdown in the OPF dialect (YAML front matter, `---` between slides, `#` title, lists, quotes, tables, `chart`, `metric` and `timeline` fences, `Note:` notes, `<!-- slide: ... -->` options) to a validated deck, and `opf to-md <deck.opf.json|-> [output.md|-] [--drop-unsupported] [--force] [--fail-on <level>]` writes a deck as that Markdown, which `from-md` reads back unchanged. Both print JSON reports and follow the exit codes above; Markdown findings carry `line` and `column`. Not in releases before the one that lists it in the changelog. See the [Markdown guide](../../docs/markdown.md).
184
+
185
+ ### Markdown decks in every command
186
+
187
+ JSON stays the canonical form of a deck; YAML and Markdown are authoring forms of the same data, and every command that reads or writes a deck reads and writes all three. A file ending `.opf.md` (any case) is a Markdown deck: `opf validate deck.opf.md`, `opf render deck.opf.md`, `opf export deck.opf.md --format pptx`, `opf edit deck.opf.md --patch changes.json --in-place`, `opf format deck.opf.md` (canonical Markdown; `--check` works), `opf paginate`, `opf fill`, `opf merge`, `opf diff`, `opf stats`. Only `.opf.md` counts: a plain `.md` file is never taken for a deck. Stdin and other names are JSON unless `--input-format markdown` (alias `md`) says otherwise. A Markdown syntax error exits 2 with `line:column` in the message and located findings under `markdown` in the error report, except in `opf validate`, which reports it as a `markdown/<rule>` finding (exit 1); `validate`, `render` and `export` report their findings at Markdown lines. A deck is written as Markdown when the output name ends `.opf.md` or with `--format markdown` (`md`); without either, a command writes the format it read (`create`, `import` and `from-md` have no deck input and default to JSON), and a rewrite that has to put content into an `opf-slide`/`opf-block` fence prints a warning on stderr. `from-md` and `to-md` stay explicit conversions with any file names. See [Markdown decks in every command](../../docs/markdown.md#markdown-decks-in-every-command).
182
188
  ## OPF as YAML
183
189
 
184
- A deck can be written as YAML (`deck.opf.yaml`) and every command that reads a deck or a JSON Patch reads it: a file ending `.yaml` or `.yml` is YAML (strict JSON-compatible YAML 1.2, no anchors, tags or duplicate keys); stdin and other names are JSON unless `--input-format yaml` says otherwise. A YAML syntax error exits 2 with the line and column in the message, like invalid JSON, except in `opf validate`, which reports it as a `yaml/<rule>` finding (exit 1); `validate`, `render` and `export` report their findings at YAML lines. A deck is written as YAML when the output name ends `.yaml`/`.yml` or with `--format yaml` (`create`, `edit`, `merge`, `format`, `paginate`, `embed`, `fill`, `import-data`, `from-md`, `import`); without either, a command writes the format it read, and JSON when it read none.
190
+ A deck can be written as YAML (`deck.opf.yaml`) and every command that reads a deck or a JSON Patch reads it: a file ending `.yaml` or `.yml` is YAML (strict JSON-compatible YAML 1.2, no anchors, tags or duplicate keys); stdin and other names are JSON unless `--input-format yaml` (or `markdown`) says otherwise. A YAML syntax error exits 2 with the line and column in the message, like invalid JSON, except in `opf validate`, which reports it as a `yaml/<rule>` finding (exit 1); `validate`, `render` and `export` report their findings at YAML lines. A deck is written as YAML when the output name ends `.yaml`/`.yml` or with `--format yaml` (`create`, `edit`, `merge`, `format`, `paginate`, `embed`, `fill`, `import-data`, `from-md`, `import`); without either, a command writes the format it read, and JSON when it read none.
185
191
 
186
192
  `opf from-yaml <deck.yaml|-> [output.opf.json|-] [--aliases] [--force] [--fail-on <level>]` converts YAML to a validated JSON deck (`--aliases` expands anchors, aliases and merge keys, capped at 100 aliases), and `opf to-yaml <deck.opf.json|-> [output.opf.yaml|-] [--schema-comment] [--force]` writes canonical YAML that `from-yaml` reads back unchanged; `--schema-comment` adds the `# yaml-language-server: $schema=...` line that gives editors validation and completion. Both print JSON reports and follow the exit codes above; YAML findings carry `line` and `column`. Commands that rewrite a YAML file do not preserve its comments and print a warning on stderr. Settings files (`--config`), `fill --data` and `import-data` sources stay JSON, CSV or TSV. See the [YAML guide](../../docs/yaml.md).
187
193
 
194
+ ## From code
195
+
196
+ The CLI is the command. An application reads, writes, converts and exports files with core's `@openpresentation/opf/node`, the engine the `convert`, `render`, `export` and `import` commands run, so the command and the code give the same bytes:
197
+
198
+ ```ts
199
+ import * as opf from "@openpresentation/opf/node";
200
+
201
+ await opf.convert("deck.opf.md", "deck.pdf");
202
+ const deck = await opf.open("deck.opf.md");
203
+ deck.slides.push({ title: "Q4" });
204
+ await opf.save(deck, "deck.opf.md");
205
+ const { files } = await opf.convert(deck, { format: "pptx" }); // bytes, nothing written
206
+ ```
207
+
208
+ Install `@openpresentation/opf` and the engines your outputs use (the same packages as for the command, below). See [OPF files in Node](https://github.com/OpenPresentation/opf/blob/main/docs/node.md) for the options, the file naming and the errors.
209
+
188
210
  ## Render, export and import
189
211
 
190
212
  ```sh
191
- npm install -g @openpresentation/cli @openpresentation/opf-render @openpresentation/opf-pptx
213
+ npm install -g @openpresentation/cli @openpresentation/opf-render @openpresentation/opf-pptx @resvg/resvg-js sharp pdf-lib @expo-google-fonts/roboto@0.4.3 @expo-google-fonts/roboto-mono@0.4.2 @expo-google-fonts/caladea@0.4.2 @expo-google-fonts/arimo@0.4.3 @expo-google-fonts/tinos@0.4.2 @expo-google-fonts/cousine@0.4.3 @expo-google-fonts/gelasio@0.4.1 @expo-google-fonts/noto-sans@0.4.2
192
214
  opf render deck.opf.json --slides 1,3-5 --format png --scale 2 --out slides
193
215
  opf export deck.opf.json --format pptx # deck.pptx
194
216
  opf export deck.opf.json --format pdf --pdf-mode vector
195
217
  opf export deck.opf.json --format svg --out slides.zip
196
218
  opf import deck.pptx --out deck.opf.json --signals signals.json
219
+ opf convert deck.opf.md deck.pdf # the formats come from the names
220
+ opf convert deck.opf.md slides/deck.png # slides/deck-001.png, -002, ...
221
+ opf convert deck.pptx deck.opf.yaml
197
222
  ```
198
223
 
199
- These commands write files; every other command only prints JSON. They check the document's format and references first and print the `opf validate` report (`findings`, `counts`, exit 1 on errors, or on findings at or above `--fail-on`, in which case nothing is written) plus an `outputs` list with each file's SHA-256. Output is deterministic: no network, no system fonts, no clock (`--date` supplies the date for `date: true` fields). Fonts are the renderer's bundled open pack plus the `.ttf`/`.otf` files in each `--font-dir`; relative images are read only from the document's folder (`--asset-dir`); URLs are never fetched. Existing outputs need `--force`.
224
+ These commands write files; every other command only prints JSON. They check the document's format and references first and print the `opf validate` report (`findings`, `counts`, exit 1 on errors, or on findings at or above `--fail-on`, in which case nothing is written) plus an `outputs` list with each file's SHA-256. Output is deterministic: no network, no system fonts, no clock (`--date` supplies the date for `date: true` fields). Fonts are the renderer's bundled open pack plus the `.ttf`/`.otf` files in each `--font-dir`; relative images are read only from the document's folder (`--asset-dir`); URLs are never fetched. Existing outputs need `--force`. `render` and `export` take the format from `--out`'s extension (`--out deck.png` is PNG) and refuse an `--out` with another file extension.
225
+
226
+ `opf convert <input> <output>` turns a `.pptx`, `.opf.md`, `.yaml`/`.yml` or `.json` file into a `.pdf`, `.pptx`, `.png`, `.svg`, `.zip`, `.opf.md`, `.yaml`/`.yml` or `.json` file, the formats named by the extensions, with the flags, report and exit codes of `opf export`. PNG and SVG give one file per slide beside the output (`slides/deck.png` writes `slides/deck-001.png`, ...; one selected slide is written to the output itself), a `.zip` holds the slides (`--format png`, the default, or `svg`), and a deck output writes the deck in that form. Images resolve next to the input file unless `--asset-dir`. It is `convert` of `@openpresentation/opf/node`.
200
227
 
201
- opf-render and opf-pptx are **optional peer dependencies**, loaded the first time a command needs them (beside the CLI first, then in the working directory), so the CLI stays small and dependency-free; a missing peer, or one that lacks `loadFonts`, `renderSlideSvg` or the other names of its API, exits 2 (the declared range is `^0.15.0`) with the install command. Scripts beyond Latin, Greek and Cyrillic need the renderer's optional Noto script packages (the report names them). The full reference, the report fields and the decisions are in [docs/cli.md](https://github.com/OpenPresentation/opf/blob/main/docs/cli.md).
228
+ opf-render and opf-pptx are **optional peer dependencies**, loaded the first time a command needs them (beside the CLI first, then in the working directory), so the CLI stays small and dependency-free; a missing peer, or one that lacks `loadFonts`, `renderSlideSvg` or the other names of its API, exits 2 (the declared range is `^0.16.0`) with the install command. Scripts beyond Latin, Greek and Cyrillic need the renderer's optional Noto script packages (the report names them). From code, the same engine is `@openpresentation/opf/node` ([From code](#from-code)). The full reference, the report fields and the decisions are in [docs/cli.md](https://github.com/OpenPresentation/opf/blob/main/docs/cli.md).
202
229
 
203
230
  ## Development checks
204
231
 
205
- `pnpm test:cli` runs command-level regression checks, including `test/files.mjs` for render, export and import against the workspace's pinned opf-render and opf-pptx (set `UPDATE_GOLDEN=1` to refresh the pinned SVG digests after a renderer or core bump). `pnpm test:cli:packed:peers` installs the packed CLI with both peers from the npm registry and repeats those checks against the installed binary and through `npm exec`. `pnpm test:cli:packed` builds and packs the CLI, installs the tarball offline into an isolated global prefix, exercises the actual executable, and reruns the same checks against the installation. It does not change your global installation. Package builds bundle their current core dependency; rebuild after schema/catalog changes.
232
+ `pnpm test:cli` runs command-level regression checks, including `test/files.mjs` for render, export and import against the workspace's pinned opf-render and opf-pptx (set `UPDATE_GOLDEN=1` to refresh the pinned SVG digests after a renderer or core bump). `pnpm test:cli:packed:peers` installs the packed CLI with both peers from the npm registry and repeats those checks against the installed binary and through `npm exec`. `pnpm test:cli:packed` builds and packs the CLI, installs the tarball and the core tarball it depends on into an isolated global prefix, exercises the actual executable, asserts that the installation holds one core, and reruns the same checks against the installation. It does not change your global installation. `test/convert.test.mjs` covers `opf convert` and the `--out` rule; core's `test/node.test.mjs` covers the engine. Rebuild the CLI after a core change; the workspace links the CLI to the core in `packages/javascript`.