@openpresentation/cli 0.16.0 → 0.18.0
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 +156 -141
- package/dist/index.js +2079 -1408
- package/dist/index.js.map +1 -1
- package/package.json +7 -11
- package/dist/api.d.ts +0 -191
- package/dist/api.js +0 -80
- package/dist/api.js.map +0 -1
- package/dist/chunk-Z2XWARO7.js +0 -1022
- package/dist/chunk-Z2XWARO7.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
# @openpresentation/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The `opf` command, for agents and people working with OPF presentations. Create decks, validate them, apply precise edits,
|
|
4
|
+
convert them between forms and formats (JSON, YAML, Markdown, PDF, PPTX, PNG, SVG), paginate content, embed the catalog records a
|
|
5
|
+
deck uses for offline use, fill templates, ingest data, and inspect the bundled schemas, the default catalog and the example
|
|
6
|
+
decks. Node 22 or later on macOS, Linux, or Windows is required.
|
|
4
7
|
|
|
5
|
-
The CLI depends on `@openpresentation/opf` (core), which holds the OPF schema, catalogs and validator and reads and writes the text
|
|
8
|
+
The CLI depends on `@openpresentation/opf` (core), which holds the OPF schema, catalogs and validator and reads and writes the text
|
|
9
|
+
formats, and whose Node build reads and writes files; the CLI is the command over it. It needs no API key or network connection at
|
|
10
|
+
runtime. `opf --version` reports the CLI and the installed core versions. Validation and editing never render; successful validation
|
|
11
|
+
is not visual verification. PDF, PPTX, PNG and SVG use the optional peers `@openpresentation/opf-render` and
|
|
12
|
+
`@openpresentation/opf-pptx` (see [Drawing and PowerPoint](#drawing-and-powerpoint)); `opf doctor` says what is installed.
|
|
6
13
|
|
|
7
14
|
## Install
|
|
8
15
|
|
|
9
|
-
The CLI is published on npm. Install the current release:
|
|
10
|
-
|
|
11
16
|
```sh
|
|
12
17
|
npm install -g @openpresentation/cli
|
|
13
18
|
opf --version
|
|
19
|
+
opf --help # every command; opf <command> --help (or -h) for one
|
|
14
20
|
```
|
|
15
21
|
|
|
16
|
-
Or install it as a development dependency and use `npx --no-install opf`. The
|
|
22
|
+
Or install it as a development dependency and use `npx --no-install opf`. [The compatibility matrix](../../docs/compatibility-matrix.md)
|
|
23
|
+
names the library releases that go with each CLI. Applications use core's functions instead of the command: see [From code](#from-code).
|
|
17
24
|
|
|
18
|
-
To verify the standalone package from source, run `pnpm install` and `pnpm test:cli:packed`. This creates
|
|
25
|
+
To verify the standalone package from source, run `pnpm install` and `pnpm test:cli:packed`. This creates
|
|
26
|
+
`artifacts/cli/openpresentation-cli-<version>.tgz` (with the core tarball it depends on), which can be installed using its absolute
|
|
27
|
+
path. For source development, run `pnpm --filter @openpresentation/cli build` and `node packages/cli/dist/index.js --help`.
|
|
19
28
|
|
|
20
29
|
## Install agent skills
|
|
21
30
|
|
|
@@ -25,40 +34,85 @@ npx @openpresentation/cli@latest skills status
|
|
|
25
34
|
npx @openpresentation/cli@latest skills update
|
|
26
35
|
```
|
|
27
36
|
|
|
28
|
-
CLI
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
The CLI installs all six bundled skill folders into the current project's `.agents/skills`, including references, examples and
|
|
38
|
+
inspection scripts. It requires no paid service, provider account or symlink privileges. Once the CLI is installed, these commands
|
|
39
|
+
work offline.
|
|
40
|
+
|
|
41
|
+
Use `--agent codex --global` for personal Codex skills, `--agent claude-code` or `--agent cursor` for those project skill
|
|
42
|
+
directories, or `--directory <path>` for another compatible agent. The default `universal` target uses `.agents/skills`; its global
|
|
43
|
+
target is `~/.agents/skills`. See [agent skill installation](https://github.com/OpenPresentation/opf/blob/main/docs/agent-skills.md)
|
|
44
|
+
for the complete target mapping and update behavior. The installer preserves AGENTS.md and unrelated configuration and refuses to
|
|
45
|
+
overwrite locally modified or unmanaged folders. `status` compares against the invoked CLI's bundled version without a network lookup.
|
|
46
|
+
|
|
47
|
+
## The conventions every command shares
|
|
48
|
+
|
|
49
|
+
- **One output convention.** A command that writes a deck takes an optional output after its inputs and writes stdout without one
|
|
50
|
+
(`-` says the same). `-i` (`--in-place`) rewrites the input. `format`, `embed` and `paginate` take `--check`: write nothing,
|
|
51
|
+
exit 1 when something would change. An existing output needs `--force`.
|
|
52
|
+
- **Fixed flag meanings.** `--format` is a report format only (`json`, `text`, `github` for validate, `patch` for diff). `--from` and
|
|
53
|
+
`--to` name deck forms (`json`, `yaml`, `md`); a name ending `.json`, `.opf.yaml`, `.yml` or `.opf.md` says the form, stdin that
|
|
54
|
+
starts with `{` or `[` is JSON, and anything else needs `--from`. `--data-format csv|tsv|json` names the data of `fill` and `ingest`.
|
|
55
|
+
- **One report.** `{ command, ok, input, outputs: [{ file, sha256, bytes, mediaType }], findings, counts, ... }`, on stdout, or on
|
|
56
|
+
stderr when stdout carries the deck. Errors are `{ command, ok: false, code, error, ... }` on stderr, and the message states the
|
|
57
|
+
fix (a missing argument, the nearest command or flag: "Did you mean --check?", a removed flag's replacement).
|
|
58
|
+
- **Exit codes.** `0` success, possibly with warnings. `1` an invalid document, a failed patch test, a finding at or above
|
|
59
|
+
`--fail-on <error|warning|info>` (default `error`), an existing output, a merge conflict, or a `--check` that found a change.
|
|
60
|
+
`2` usage, text that is not valid JSON, YAML or Markdown, I/O, or a missing optional peer.
|
|
61
|
+
- No telemetry, automatic uploads, or execution of instructions inside document text. Use `--` before file names that start with `-`.
|
|
33
62
|
|
|
34
63
|
## Create and validate
|
|
35
64
|
|
|
36
65
|
```sh
|
|
37
66
|
opf create decision.opf.json --title "Launch decision"
|
|
67
|
+
opf create brief.opf.md --example compliance-readiness-review # opf catalog examples lists them
|
|
68
|
+
opf create - --title "Launch decision" | opf validate -
|
|
38
69
|
opf validate decision.opf.json
|
|
39
|
-
opf create copy.opf.json --from decision.opf.json
|
|
40
70
|
```
|
|
41
71
|
|
|
42
|
-
Creation supplies a minimal deck with one stable slide ID, `slide-1
|
|
72
|
+
Creation supplies a minimal deck with one stable slide ID, `slide-1`; `--title` sets both deck name and visible slide title.
|
|
73
|
+
`--example <slug>` copies one of core's bundled example decks. To copy a deck into another form, use `opf convert`.
|
|
43
74
|
|
|
44
|
-
|
|
75
|
+
`opf validate` is the one checker. It reads each file as strict JSON text (or YAML, or a Markdown deck, by its name or `--from`) and
|
|
76
|
+
prints the report (`valid`, `schemaValid`, `findings`, `counts`, `checks`), the input's SHA-256 digest and the core version. Each
|
|
77
|
+
finding has a stable `opf/<rule>` id, a severity, a category (`format`, `references`, `policy`, `accessibility`, `layout`,
|
|
78
|
+
`content`), a JSON Pointer path, the source line and column, a hint and sometimes suggested fixes. Only format, references and
|
|
79
|
+
policy findings are errors by default, so `valid` keeps meaning "correct OPF".
|
|
45
80
|
|
|
46
81
|
```sh
|
|
47
|
-
opf
|
|
48
|
-
opf
|
|
82
|
+
opf validate deck.opf.json # everything, JSON report
|
|
83
|
+
opf validate deck.opf.json --format text # one line per finding
|
|
84
|
+
opf validate decks/ --format github --fail-on warning # every *.opf.* file in a folder, as CI annotations
|
|
85
|
+
opf validate a.opf.json b.opf.md - # several inputs: { command, ok, files, counts }
|
|
86
|
+
opf validate deck.opf.json --only format,references --ignore layout --config house-rules.json
|
|
87
|
+
opf validate --list-rules
|
|
49
88
|
```
|
|
50
89
|
|
|
51
|
-
|
|
90
|
+
A folder is searched for `*.opf.json`, `*.opf.yaml`, `*.opf.yml` and `*.opf.md` (sorted, skipping `node_modules` and dot folders).
|
|
91
|
+
The exit status is the worst over every file. `--only` and `--ignore` take comma-separated rule ids, bare names or category names,
|
|
92
|
+
and may be repeated. `--config` is an explicit local JSON file of `{ catalogs, contracts, severity, only, ignore, ignorePaths,
|
|
93
|
+
thresholds, chartPalette }`. Validation is read-only, fetches nothing and never rewrites the file. See [the validate guide](../../docs/validate.md).
|
|
94
|
+
|
|
95
|
+
## Convert
|
|
96
|
+
|
|
97
|
+
`opf convert <input> <output>` is every change of format, the formats named by the extensions or by `--from` and `--to`:
|
|
52
98
|
|
|
53
99
|
```sh
|
|
54
|
-
opf
|
|
55
|
-
opf
|
|
56
|
-
opf
|
|
57
|
-
opf
|
|
58
|
-
opf
|
|
100
|
+
opf convert deck.opf.md deck.pdf
|
|
101
|
+
opf convert deck.opf.md slides/deck.png --slides 1,3-5 --scale 2 # slides/deck-001.png, -003, -004, -005
|
|
102
|
+
opf convert deck.pptx deck.opf.md --signals signals.json
|
|
103
|
+
opf convert outline.md deck.opf.yaml # a plain .md input is OPF Markdown
|
|
104
|
+
opf convert deck.opf.json deck.opf.yaml --schema-comment
|
|
105
|
+
opf convert deck.opf.md - --to pdf > deck.pdf
|
|
59
106
|
```
|
|
60
107
|
|
|
61
|
-
|
|
108
|
+
Inputs: `.json`, `.opf.yaml`/`.yml`, `.opf.md` and a plain `.md`, `.pptx`, or `-`. Outputs: a deck form, `.pdf`, `.pptx`, `.png` or
|
|
109
|
+
`.svg` (one file per slide beside the output; one selected slide is written to the output itself), `.zip` (the slides as PNG, or
|
|
110
|
+
SVG with `--to svg`), or `-` with `--to`. A flag applies only where its format is involved, else it is a usage error: `--split` and
|
|
111
|
+
`--title` for a Markdown input, `--aliases` for YAML, `--signals` for a `.pptx` input, `--schema-comment` for a YAML output,
|
|
112
|
+
`--drop-unsupported` for a Markdown output, and `--slides`, `--include-hidden`, `--scale`, `--raster`, `--text`, `--charts`,
|
|
113
|
+
`--images`, `--provenance`, `--paginate`, `--date`, `--fonts` and `--asset-dir` for drawn and PowerPoint outputs. `opf convert --help`
|
|
114
|
+
lists which format each belongs to. Removed in 0.18: `render`, `export`, `import`, `from-md`, `to-md`, `from-yaml`, `to-yaml` and
|
|
115
|
+
`create --from`, all `opf convert` now. See [docs/cli.md](https://github.com/OpenPresentation/opf/blob/main/docs/cli.md).
|
|
62
116
|
|
|
63
117
|
## Edit with JSON Patch
|
|
64
118
|
|
|
@@ -68,7 +122,6 @@ Create `changes.json`:
|
|
|
68
122
|
[
|
|
69
123
|
{ "op": "test", "path": "/slides/0/id", "value": "slide-1" },
|
|
70
124
|
{ "op": "replace", "path": "/slides/0/title", "value": "Approve the next milestone" },
|
|
71
|
-
{ "op": "add", "path": "/slides/0/text", "value": "Describe the evidence and requested decision here." },
|
|
72
125
|
{ "op": "add", "path": "/slides/-", "value": { "id": "next-steps", "title": "Next steps" } }
|
|
73
126
|
]
|
|
74
127
|
```
|
|
@@ -76,71 +129,68 @@ Create `changes.json`:
|
|
|
76
129
|
Preview the result, save a separate file, or update the source:
|
|
77
130
|
|
|
78
131
|
```sh
|
|
79
|
-
opf edit decision.opf.json --patch changes.json
|
|
80
|
-
opf edit decision.opf.json
|
|
81
|
-
opf edit decision.opf.json --patch changes.json --
|
|
132
|
+
opf edit decision.opf.json --patch changes.json # stdout; nothing is written
|
|
133
|
+
opf edit decision.opf.json reviewed.opf.json --patch changes.json
|
|
134
|
+
opf edit decision.opf.json --patch changes.json -i --expect-sha256 "$EXPECTED_SHA256"
|
|
82
135
|
```
|
|
83
136
|
|
|
84
|
-
The editor implements [JSON Patch (RFC 6902)](https://www.rfc-editor.org/rfc/rfc6902): `add`, `remove`, `replace`, `move`, `copy`,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
```sh
|
|
91
|
-
opf edit decision.opf.json --patch changes.json --in-place --expect-sha256 "$EXPECTED_SHA256"
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
The digest compares the exact input bytes, including whitespace. The CLI also rechecks the input before replacing that same path. Writes use a temporary sibling file and atomic publication. Existing destinations require `--force`; `--in-place` explicitly authorizes replacing the input. Symlink and non-regular destinations are rejected. Coordinate concurrent writers externally: the hash check and rename are not a filesystem compare-and-swap or a collaboration lock. There is no persistent undo history; use version control or save a separate output when needed.
|
|
137
|
+
The editor implements [JSON Patch (RFC 6902)](https://www.rfc-editor.org/rfc/rfc6902): `add`, `remove`, `replace`, `move`, `copy`,
|
|
138
|
+
and `test`, applied whole or not at all; the patch is JSON or YAML. The result must pass the format and references check before it
|
|
139
|
+
is written, and the report carries `inverse`, the patch that undoes the edit. `--expect-sha256` takes the digest from an earlier
|
|
140
|
+
`opf validate` report and refuses an input that changed. Writes use a temporary sibling file and atomic publication; symlink and
|
|
141
|
+
non-regular destinations are rejected. There is no persistent undo history; use version control or save a separate output.
|
|
95
142
|
|
|
96
143
|
## Diff, merge and format
|
|
97
144
|
|
|
98
|
-
Added in CLI 0.10.0 (RR-31; not in 0.9.2 or earlier): check `opf --help`. These commands are local and deterministic. See [patch, diff, merge and format](../../docs/patch-diff-merge-format.md) for the matching rules, conflict objects and key order.
|
|
99
|
-
|
|
100
145
|
```sh
|
|
101
146
|
opf diff before.opf.json after.opf.json # readable report
|
|
102
147
|
opf diff before.opf.json after.opf.json --format patch # JSON Patch from before to after
|
|
103
148
|
opf diff a.opf.json b.opf.json --exit-code # exit 1 when they differ
|
|
104
|
-
opf merge base.opf.json ours.opf.json theirs.opf.json
|
|
105
|
-
opf merge base.opf.json ours.opf.json theirs.opf.json --prefer theirs --report conflicts.json
|
|
106
|
-
opf format deck.opf.json
|
|
107
|
-
opf format decks/*.opf.json
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
`diff` matches slides by `id`, then identical content, then content similarity, and reports additions, removals, moves and field, block, design and metadata changes; `--format json` adds the structured changes and `--format patch` prints only the patch, which `opf edit --patch` applies. `merge` combines two edits of a base: changes in different places merge, and conflicts are listed with the base, our and their values and **block the write** (exit 1, report on stderr) unless `--prefer ours|theirs` picks a side, in which case every conflict is still reported. The merged document is validated before it is written. `format` rewrites a file with canonical key order (the schema's property order), two-space indentation, LF endings (`--eol crlf|preserve`) and one trailing newline; it is idempotent and does not validate. `opf edit`, `diff` and `merge` share one RFC 6902 implementation with the editor.
|
|
111
|
-
|
|
112
|
-
## Facts about a deck
|
|
113
|
-
|
|
114
|
-
```sh
|
|
115
|
-
opf stats deck.opf.json # JSON
|
|
116
|
-
opf stats deck.opf.json --format text # a readable block per topic
|
|
117
|
-
opf stats - --per-slide < deck.opf.json # adds a row per slide
|
|
149
|
+
opf merge base.opf.json ours.opf.json theirs.opf.json merged.opf.json
|
|
150
|
+
opf merge base.opf.json ours.opf.json theirs.opf.json -i --prefer theirs --report conflicts.json
|
|
151
|
+
opf format deck.opf.json -i
|
|
152
|
+
opf format --check decks/*.opf.json # CI: exit 1 if any file would change
|
|
118
153
|
```
|
|
119
154
|
|
|
120
|
-
`
|
|
155
|
+
`diff` matches slides by `id`, then identical content, then content similarity. `merge` combines two edits of a base; conflicts block
|
|
156
|
+
the write (exit 1) unless `--prefer ours|theirs` picks a side, and every conflict is reported. `format` rewrites a deck in canonical
|
|
157
|
+
key order and layout, keeping its form (`opf convert` changes forms); it is idempotent. See
|
|
158
|
+
[patch, diff, merge and format](../../docs/patch-diff-merge-format.md).
|
|
121
159
|
|
|
122
|
-
##
|
|
160
|
+
## Facts, pagination and embedding
|
|
123
161
|
|
|
124
162
|
```sh
|
|
125
|
-
opf
|
|
126
|
-
opf
|
|
127
|
-
opf
|
|
163
|
+
opf stats deck.opf.json --format text --per-slide
|
|
164
|
+
opf paginate deck.opf.json paginated.opf.json
|
|
165
|
+
opf paginate deck.opf.json --check # CI: exit 1 when a slide overflows
|
|
166
|
+
opf embed deck.opf.json -i
|
|
167
|
+
opf embed deck.opf.json --check # CI: exit 1 when the deck is not self-contained
|
|
128
168
|
```
|
|
129
169
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
170
|
+
`stats` reports neutral facts (slides, sections, layouts, words, notes, images, charts, tables, datasets, citations, variables,
|
|
171
|
+
assets, fonts, an estimated speaking time) under `stats` in the report; it never validates, composes or rates anything. `paginate`
|
|
172
|
+
splits overflowing slides into continuation slides, measured with the fonts `opf convert` draws with when opf-render is installed
|
|
173
|
+
(`layout: "measured"`), else estimated (`layout: "estimated"`, with a `hint` that names the install command). `embed` copies every
|
|
174
|
+
catalog record the deck references, transitively, into it once, so the file renders the same with no catalog registered.
|
|
133
175
|
|
|
134
|
-
|
|
176
|
+
## Fill a template and ingest data
|
|
135
177
|
|
|
136
178
|
```sh
|
|
137
|
-
opf fill quarterly.opf.json
|
|
138
|
-
opf fill quarterly.opf.
|
|
139
|
-
opf fill quarterly.opf.json
|
|
140
|
-
opf fill quarterly.opf.json --examples
|
|
179
|
+
opf fill quarterly.opf.json globex.json globex.opf.json # one JSON object, one deck
|
|
180
|
+
opf fill quarterly.opf.md clients.csv decks/qbr-{client}.opf.md # one deck per row, named by a column
|
|
181
|
+
opf fill quarterly.opf.json clients.csv all.opf.json --combine # one deck, a slide group per row
|
|
182
|
+
opf fill quarterly.opf.json --examples > preview.opf.json # no data: fill from each variable's example
|
|
183
|
+
export-rows | opf fill quarterly.opf.json - decks/deck-{n}.opf.json # data from stdin
|
|
184
|
+
opf ingest revenue.csv table.opf.json --as table
|
|
185
|
+
opf ingest revenue.csv --as chart --category Quarter --series '["Revenue","Costs"]' --into decision.opf.json -i
|
|
141
186
|
```
|
|
142
187
|
|
|
143
|
-
|
|
188
|
+
`fill`'s second argument is always the data, whatever its name (`-` reads it from stdin), and the third is the output: a deck name,
|
|
189
|
+
or a file name pattern where `{n}` is the record number and `{column}` a slug of that column's value. A blank
|
|
190
|
+
cell keeps the declared value; an unfilled required variable fails unless `--partial`. `ingest` turns CSV, TSV or JSON rows into a
|
|
191
|
+
table or chart, alone or added `--into` a deck (`--path` replaces one); `--dataset <id>` stores the rows in the deck's datasets. The
|
|
192
|
+
same inputs give the same slide id and bytes. See [templates and variables](../../docs/templates-and-variables.md) and
|
|
193
|
+
[data import](../../docs/data-import.md).
|
|
144
194
|
|
|
145
195
|
## Discover format options
|
|
146
196
|
|
|
@@ -150,96 +200,61 @@ opf schema presentation '/$defs/Composition'
|
|
|
150
200
|
opf catalogs
|
|
151
201
|
opf catalog layouts
|
|
152
202
|
opf catalog fontSchemes roboto
|
|
203
|
+
opf catalog examples
|
|
153
204
|
```
|
|
154
205
|
|
|
155
|
-
|
|
206
|
+
They inspect the default catalog of the core the CLI runs on (the full pptx.gallery catalog) and the bundled example decks, and print
|
|
207
|
+
the data asked for. Nothing is fetched.
|
|
156
208
|
|
|
157
|
-
|
|
158
|
-
opf paginate decision.opf.json paginated.opf.json
|
|
159
|
-
```
|
|
209
|
+
## Drawing and PowerPoint
|
|
160
210
|
|
|
161
|
-
|
|
211
|
+
PDF, PNG and SVG need `@openpresentation/opf-render`; PPTX output and a `.pptx` input also need `@openpresentation/opf-pptx`. They
|
|
212
|
+
are **optional peer dependencies**, loaded the first time a command needs them (beside the CLI first, then in the working
|
|
213
|
+
directory), so the CLI stays small. `opf doctor` reports, per format, whether this install can write it and prints the one command
|
|
214
|
+
that installs what is missing, for the package manager in use (npm, pnpm, yarn or bun) and the way the CLI is installed (global, a
|
|
215
|
+
project, or npx):
|
|
162
216
|
|
|
163
217
|
```sh
|
|
164
|
-
opf
|
|
218
|
+
opf doctor --format text
|
|
219
|
+
opf doctor deck.opf.md # with a deck: a PDF needs sharp only when it has pictures
|
|
165
220
|
```
|
|
166
221
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
222
|
+
A conversion that misses a peer exits 2 with `code: "peer-not-installed"` and that one command in `install`. Output is
|
|
223
|
+
deterministic: no network, no system fonts, no clock (`--date` supplies the date for `date: true` fields). Fonts are the renderer's
|
|
224
|
+
bundled open pack plus the `.ttf`/`.otf` files in each `--fonts` folder; relative images are read only from the input's folder
|
|
225
|
+
(`--asset-dir`); URLs are never fetched. Scripts beyond Latin, Greek and Cyrillic need the renderer's optional Noto script packages
|
|
226
|
+
(the report names them). The full reference is in [docs/cli.md](https://github.com/OpenPresentation/opf/blob/main/docs/cli.md).
|
|
170
227
|
|
|
171
|
-
|
|
172
|
-
- `validate` reports to stdout, including for invalid documents.
|
|
173
|
-
- Commands emitting a document to stdout send their findings to stderr, so pipes remain valid JSON.
|
|
174
|
-
- File-writing commands report the absolute output path, output SHA-256, and `findings` (format and references only) to stdout.
|
|
175
|
-
- Exit `0`: success, possibly with warnings. Exit `1`: invalid document, failed patch/test, a finding at or above `--fail-on`, or file conflict. Exit `2`: usage, malformed JSON input to a command other than `validate`, or I/O failure.
|
|
176
|
-
- Commands that check a document before writing it take `--fail-on <error|warning|info>` (default `error`). Use `--` before positional filenames that start with `--`.
|
|
177
|
-
- No telemetry, automatic uploads, or execution of instructions inside document text.
|
|
228
|
+
## Markdown and YAML
|
|
178
229
|
|
|
179
|
-
|
|
230
|
+
JSON stays the canonical form of a deck; YAML (`deck.opf.yaml`) and Markdown (`deck.opf.md`) are authoring forms of the same data,
|
|
231
|
+
and every command that reads or writes a deck reads and writes all three. A syntax error exits 2 with `line:column` (`opf validate`
|
|
232
|
+
reports it as a finding, exit 1). A command that rewrites a YAML file does not keep its comments, and one that has to put content
|
|
233
|
+
into an `opf-slide`/`opf-block` fence, says so on stderr. See the [Markdown guide](../../docs/markdown.md) and the [YAML guide](../../docs/yaml.md).
|
|
180
234
|
|
|
181
|
-
|
|
235
|
+
## From code
|
|
182
236
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
## OPF as YAML
|
|
187
|
-
|
|
188
|
-
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.
|
|
189
|
-
|
|
190
|
-
`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).
|
|
191
|
-
|
|
192
|
-
## Library API
|
|
193
|
-
|
|
194
|
-
`@openpresentation/cli/api` is the CLI's code as a library: the format-oriented functions an application calls instead of spawning `opf`. Core reads and writes the text formats; this entry reads and writes files. It is one package with the command, so the command and the API give the same bytes.
|
|
195
|
-
|
|
196
|
-
```sh
|
|
197
|
-
npm install @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
|
|
198
|
-
```
|
|
237
|
+
The CLI is the command. An application calls core's `@openpresentation/opf` instead, the functions the commands run, so the command
|
|
238
|
+
and the code give the same result. In Node, `validate`, `stats`, `paginate`, `embed` and `edit` register the default catalog when a
|
|
239
|
+
call names none, as the commands do:
|
|
199
240
|
|
|
200
241
|
```ts
|
|
201
|
-
import
|
|
242
|
+
import * as opf from "@openpresentation/opf";
|
|
202
243
|
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
const {
|
|
244
|
+
await opf.convert("deck.opf.md", "deck.pdf");
|
|
245
|
+
const deck = await opf.open("deck.opf.md");
|
|
246
|
+
const { presentation } = opf.edit(deck, [{ op: "replace", path: "/name", value: "Q4" }]);
|
|
247
|
+
await opf.save(presentation, "deck.opf.md");
|
|
248
|
+
const { decks } = opf.fill(template, csvText);
|
|
208
249
|
```
|
|
209
250
|
|
|
210
|
-
|
|
211
|
-
| --- | --- |
|
|
212
|
-
| `readDeck(text, { format?, filename?, catalogs?, validate? })`, `writeDeck(presentation, { format? \| filename? })`, `validate`, `assertValid`, `OPFValidationError`, `defaultCatalog` | Core's own functions, re-exported: one import for an application that only has this package. They are the same functions and classes as `@openpresentation/opf` exports. |
|
|
213
|
-
| `exportDeck(presentation, options)` | Draws a presentation as `pdf`, `png`, `svg` or `pptx`. `png` and `svg` give one file per slide (named `<name>-001.png`), or one zip with `zip: true`; `pdf` and `pptx` give one file. Returns `{ files, findings, fonts, skippedHidden, renderer, pptx? }`. |
|
|
214
|
-
| `importDeck(bytes, { catalogs?, signals? })` | Reads a PowerPoint file into `{ presentation, findings, pptx, signals? }`. Import is a conversion, not a lossless round trip: what it cannot keep is in `findings`. |
|
|
215
|
-
|
|
216
|
-
`exportDeck` options: `format` (required), `slides` (`"1,3-5"` or `[1, 3]`; not for `pptx`), `includeHidden`, `paginate`, `scale` (`png`, raster `pdf`), `pdfMode` (`vector` or `raster`), `svgFonts` (`used` or `none`), `chartex`, `provenance`, `imageFormat` (`pptx`), `date` (`YYYY-MM-DD`), `zip`, `filename` (the source name, for naming files), `catalogs`, `fonts`, `fontDirs` and `assetDir`. They are the options of `opf export` and `opf render` in camel case.
|
|
217
|
-
|
|
218
|
-
- **Deterministic.** No network, no system fonts, no clock: a date field draws only the `date` you pass, and the same presentation gives the same bytes on every machine.
|
|
219
|
-
- **Fonts.** The renderer's bundled open pack plus the `.ttf` and `.otf` files in `fontDirs`. To reuse one prepared set across many calls, pass `fonts`: the handle `loadFonts()` of `@openpresentation/opf-render/fonts-node` returns.
|
|
220
|
-
- **Catalogs.** `catalogs` defaults to core's default catalog, as the command does. Pass your own list (for example `[defaultCatalog, myCatalog]`) to change how references resolve.
|
|
221
|
-
- **Images.** Local image paths are read only from `assetDir`; without it no local file is read. Data URIs work as they are, and URLs are never fetched.
|
|
222
|
-
- **The engines are peers.** `@openpresentation/opf-render` (PDF, PNG, SVG) and `@openpresentation/opf-pptx` (PPTX, import) are optional peer dependencies, loaded the first time a function needs them. Install what you call: from opf-render 0.16 its converters (`@resvg/resvg-js` and `sharp` for PNG, `pdf-lib` for raster PDF, `sharp` for pictures in a PDF) and font packages are optional peers too, listed per output in [docs/cli.md](https://github.com/OpenPresentation/opf/blob/main/docs/cli.md#install); a missing one throws the same `peer-not-installed` error with `details.package` (or `details.packages`) and the install command.
|
|
223
|
-
- **Errors.** `exportDeck` throws `OPFExportError` and `importDeck` `OPFImportError` (both extend `OPFApiError`), with a `code`, `details` and the located `findings`: `peer-not-installed` (the message carries the install command; `details` the package and its range), `peer-too-old`, `peer-load-failed`, `invalid-option`, `invalid-presentation`, `no-slides`, `all-slides-hidden`, `export-failed` and `import-failed`. A presentation that fails the format and references check is rejected with `invalid-presentation`; warnings come back in `findings`.
|
|
224
|
-
- **One core.** The package depends on `@openpresentation/opf` as a regular dependency and does not bundle a copy, so an application that also imports core runs a single core: `error instanceof OPFValidationError` holds across both imports.
|
|
225
|
-
|
|
226
|
-
The same engine runs `opf render`, `opf export` and `opf import`, whose reports are described in [docs/cli.md](https://github.com/OpenPresentation/opf/blob/main/docs/cli.md).
|
|
227
|
-
|
|
228
|
-
## Render, export and import
|
|
229
|
-
|
|
230
|
-
```sh
|
|
231
|
-
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
|
|
232
|
-
opf render deck.opf.json --slides 1,3-5 --format png --scale 2 --out slides
|
|
233
|
-
opf export deck.opf.json --format pptx # deck.pptx
|
|
234
|
-
opf export deck.opf.json --format pdf --pdf-mode vector
|
|
235
|
-
opf export deck.opf.json --format svg --out slides.zip
|
|
236
|
-
opf import deck.pptx --out deck.opf.json --signals signals.json
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
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`.
|
|
240
|
-
|
|
241
|
-
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). From code, the same engines are `exportDeck` and `importDeck` ([Library API](#library-api)). The full reference, the report fields and the decisions are in [docs/cli.md](https://github.com/OpenPresentation/opf/blob/main/docs/cli.md).
|
|
251
|
+
See [OPF files in Node](https://github.com/OpenPresentation/opf/blob/main/docs/node.md) for the options and the errors.
|
|
242
252
|
|
|
243
253
|
## Development checks
|
|
244
254
|
|
|
245
|
-
`pnpm test:cli` runs command
|
|
255
|
+
`pnpm test:cli` runs the command tests (`test/*.test.mjs` and `test/cli.mjs`), including `test/files.mjs` for drawing and
|
|
256
|
+
PowerPoint against the published opf-render and opf-pptx (set `UPDATE_GOLDEN=1` to refresh the pinned SVG digests after a renderer
|
|
257
|
+
or core bump). `pnpm test:cli:packed:peers` installs the packed CLI with both peers and repeats those checks against the installed
|
|
258
|
+
binary. `pnpm test:cli:packed` packs the CLI, installs the tarball and the core tarball it depends on into an isolated global prefix,
|
|
259
|
+
exercises the executable, asserts that the installation holds one core, and reruns `test/cli.mjs` against it. Rebuild the CLI after
|
|
260
|
+
a core change; the workspace links the CLI to the core in `packages/javascript`.
|