@uniweb/unipress 0.2.2
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/CHANGELOG.md +137 -0
- package/LICENSE +201 -0
- package/README.md +213 -0
- package/RELEASING.md +101 -0
- package/docs/parity-report.md +153 -0
- package/docs/templates/book.md +55 -0
- package/docs/templates/data-report.md +85 -0
- package/docs/templates/directory.md +73 -0
- package/docs/templates/monograph.md +50 -0
- package/docs/templates/report.md +55 -0
- package/docs/troubleshooting.md +159 -0
- package/package.json +62 -0
- package/src/catalog.js +23 -0
- package/src/cli.js +193 -0
- package/src/commands/compile.js +37 -0
- package/src/commands/create.js +165 -0
- package/src/commands/inspect.js +182 -0
- package/src/compile.js +165 -0
- package/src/config.js +128 -0
- package/src/content-loader.js +56 -0
- package/src/document-yml.js +20 -0
- package/src/errors.js +78 -0
- package/src/foundation-fetch.js +202 -0
- package/src/foundation-loader.js +229 -0
- package/src/foundations-data.js +122 -0
- package/src/index.js +8 -0
- package/src/orchestrator.js +150 -0
- package/src/scaffold.js +66 -0
- package/src/sinks/blob.js +25 -0
- package/src/sinks/typst.js +101 -0
- package/src/templates-data.js +63 -0
- package/src/typst/binary-manager.js +228 -0
- package/src/typst/versions.js +65 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
The credibility-shifting release. Two production-shaped foundations
|
|
6
|
+
(`@uniweb/book`, `@uniweb/data`), five templates (`book`, `monograph`,
|
|
7
|
+
`report`, `data-report`, `directory`), and a vocabulary cleanup that
|
|
8
|
+
separates create-time templates from runtime foundations.
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`@uniweb/book`** foundation. Long-form prose with chapters; outputs
|
|
13
|
+
Typst/PDF, Paged.js HTML, EPUB. Default section type `Chapter` plus
|
|
14
|
+
`Cover`, `BackCover`, `BackMatter`, `Contents`. Inlines parameterised
|
|
15
|
+
Typst defaults (trim, typography, structure, localized labels) and a
|
|
16
|
+
CSS Paged Media stylesheet.
|
|
17
|
+
- **`@uniweb/data`** foundation. Aggregates structured records and
|
|
18
|
+
emits Excel workbooks + Word reports. Eight section types
|
|
19
|
+
(`Cover`, `Members`, `Publications*` ×4, `Funding`, `Supervisions`)
|
|
20
|
+
with Loom-driven aggregate stats and a queryable filter surface.
|
|
21
|
+
- **Five templates** under `documents/`:
|
|
22
|
+
- `book` — trade-6x9 prose (3 chapters).
|
|
23
|
+
- `monograph` — royal-octavo, EB Garamond, `tocDepth: 3`.
|
|
24
|
+
- `report` — trade-7x10, block paragraphs, code-margin relief.
|
|
25
|
+
- `data-report` — migrated from the v0.1 `academic-metrics`
|
|
26
|
+
placeholder; aggregate metrics across sample naturalists.
|
|
27
|
+
- `directory` — flat records listing with filterable surface.
|
|
28
|
+
- **Per-template docs** at `docs/templates/<name>.md` covering the
|
|
29
|
+
`document.yml` fields that matter, common customizations, and
|
|
30
|
+
links to the foundation README.
|
|
31
|
+
- **Registry-ref resolver** in `foundation-loader.js`. The fifth ref
|
|
32
|
+
form `@<namespace>/<name>@<version>` constructs a URL from
|
|
33
|
+
`UNIWEB_REGISTRY_URL` (or the production default at
|
|
34
|
+
`site-router.uniweb-edge.workers.dev`) and fetches via the existing
|
|
35
|
+
cache. Catalog entries pin registry refs; scaffolded `document.yml`
|
|
36
|
+
files inherit them.
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- **Vocabulary**: `unipress create` now takes `--template <id>`
|
|
41
|
+
instead of `--foundation <id>`, and `list-foundations` is renamed
|
|
42
|
+
to `list-templates`. Catalog ids are templates — starter content
|
|
43
|
+
pinning a foundation. Runtime concepts keep the foundation name
|
|
44
|
+
(`compile --foundation`, `document.yml`'s `foundation:`).
|
|
45
|
+
- **Catalog entry shape**: `{ source: { url } }` →
|
|
46
|
+
`{ foundation: { ref, source: { url } } }`. The new `foundation.ref`
|
|
47
|
+
is the registry ref scaffolded `document.yml` files pin; the
|
|
48
|
+
`foundation.source.url` is the human-readable "where this lives"
|
|
49
|
+
pointer shown in `list-templates` output.
|
|
50
|
+
- **Repo layout**: `framework/unipress/` is now a nested pnpm
|
|
51
|
+
workspace. Foundations developed for unipress live under
|
|
52
|
+
`foundations/<name>/`; documents (foundation-dev test harnesses
|
|
53
|
+
AND bundled template starter content) live under `documents/<name>/`.
|
|
54
|
+
The `scripts/generate-templates-data.js` generator reads from
|
|
55
|
+
`documents/` and rewrites path-ref `foundation:` values to registry
|
|
56
|
+
refs at bundle time so the on-disk file stays dev-friendly while
|
|
57
|
+
the bundled file is end-user-friendly.
|
|
58
|
+
|
|
59
|
+
### Removed
|
|
60
|
+
|
|
61
|
+
- `--foundation` flag on `create`. Errors with a pointer to
|
|
62
|
+
`--template` (no deprecation alias — pre-1.0).
|
|
63
|
+
- `list-foundations` command. Errors with a pointer to `list-templates`.
|
|
64
|
+
- `templates/` directory; `package.json`'s `files:` array now ships
|
|
65
|
+
`documents/`.
|
|
66
|
+
|
|
67
|
+
### Caveat
|
|
68
|
+
|
|
69
|
+
Catalog entries currently point at the **local registry**
|
|
70
|
+
(`http://localhost:4001/registry/packages/<ns>/<name>/<ver>/foundation.js`).
|
|
71
|
+
Scaffolded documents will fail to fetch the foundation unless the
|
|
72
|
+
foundations are published locally via `uniweb publish --local` against
|
|
73
|
+
a running unicloud, OR the user passes `--foundation <path>` explicitly.
|
|
74
|
+
A follow-up release switches the catalog URLs to the production
|
|
75
|
+
registry once `@uniweb/book` and `@uniweb/data` publish there.
|
|
76
|
+
|
|
77
|
+
## 0.1.0 (unreleased)
|
|
78
|
+
|
|
79
|
+
First working release, published as `@uniweb/unipress` after the
|
|
80
|
+
unscoped `unipress` name was abandoned (npm Levenshtein-policy
|
|
81
|
+
conflict with `unirest`). The CLI binary is still `unipress`; only the
|
|
82
|
+
package specifier is scoped. All functionality below is in the working
|
|
83
|
+
tree and exercised end-to-end against the v0.1 reference foundation
|
|
84
|
+
(198-page PDF via Typst 0.14.2).
|
|
85
|
+
|
|
86
|
+
### Added
|
|
87
|
+
|
|
88
|
+
- `unipress compile <dir>` — compile a content directory into a
|
|
89
|
+
document. Calls `foundation.compileDocument(website, { format,
|
|
90
|
+
foundation, ...hostHints })` and sinks the resulting Blob.
|
|
91
|
+
- Format support: whatever the foundation declares in its `outputs:`
|
|
92
|
+
map. Today that's PDF / Typst source zip / Paged.js HTML / EPUB via
|
|
93
|
+
`@proximify/press-book`; other formats land when their foundations do.
|
|
94
|
+
- Typst binary manager: pinned to `0.14.2`, SHA-256-verified, cached
|
|
95
|
+
under `$UNIPRESS_CACHE_DIR` or the platform default (XDG /
|
|
96
|
+
`~/Library/Caches/unipress` / `~/.cache/unipress`). Override with
|
|
97
|
+
`--typst-binary <path>`.
|
|
98
|
+
- `unipress.config.js` + `--config <path>`. Precedence: CLI > config >
|
|
99
|
+
`document.yml` > defaults. Fields: `format`, `foundation`, `out`,
|
|
100
|
+
`typst.binary`, `typst.version`. Relative paths resolve against the
|
|
101
|
+
config file's directory.
|
|
102
|
+
- `unipress inspect <dir>` — JSON dump of the resolved Website graph,
|
|
103
|
+
with filtering knobs (`--full`, `--summary`, `--page <route>`,
|
|
104
|
+
`--depth <n>`, `--foundation <ref>`, `--no-orchestrate`).
|
|
105
|
+
- Foundation resolver: npm package name (walks `node_modules/`, picks
|
|
106
|
+
`exports['./dist']`) or local path. URL-based resolution is planned.
|
|
107
|
+
- Named error catalog (`ContentDirectoryError`, `DocumentYmlError`,
|
|
108
|
+
`ConfigValidationError`, `FoundationResolutionError`, `CompileError`,
|
|
109
|
+
`OutputWriteError`, `TypstBinaryError`, plus three reserved for
|
|
110
|
+
later milestones). `UnipressError.format()` produces structured
|
|
111
|
+
multi-line output. Top-level handler splits exit codes: `1` for
|
|
112
|
+
user-addressable errors, `2` for internal bugs.
|
|
113
|
+
- `--verbose` flag — step-by-step progress to stderr + stack traces on
|
|
114
|
+
errors.
|
|
115
|
+
- `--keep-temp` flag — preserves the typst temp directory on compile
|
|
116
|
+
failure so the generated source bundle can be inspected.
|
|
117
|
+
|
|
118
|
+
### Framework-side changes that shipped alongside
|
|
119
|
+
|
|
120
|
+
- [`@uniweb/press`] `compileDocument(websiteOrTree, options)` — the
|
|
121
|
+
high-level compile entry point. Tree mode passes through to
|
|
122
|
+
`compileSubtree`; website mode reads `foundation.outputs[format]`,
|
|
123
|
+
assembles adapter options, gathers blocks, dispatches.
|
|
124
|
+
- [`@uniweb/build`] Host-shareable re-export extended — the generated
|
|
125
|
+
entry now re-exports both `compileSubtree` and `compileDocument`
|
|
126
|
+
when the foundation depends on `@uniweb/press`.
|
|
127
|
+
- [docs] New "Document Outputs" section in `foundation-config.md`
|
|
128
|
+
covering the `outputs: { <format>: { getOptions, via?, extension? } }`
|
|
129
|
+
contract.
|
|
130
|
+
|
|
131
|
+
(0.1.0 was never tagged; its content shipped under the 0.0.1 working
|
|
132
|
+
tree and was superseded by 0.2.0 directly.)
|
|
133
|
+
|
|
134
|
+
## 0.0.1
|
|
135
|
+
|
|
136
|
+
- Name-reservation release. CLI prints help and version; no commands
|
|
137
|
+
are implemented yet.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# unipress
|
|
2
|
+
|
|
3
|
+
**Compile a directory of markdown into a document — typeset PDF, EPUB, Word, Excel, Paged.js HTML, Typst source — using a foundation that knows the conventions of the kind of document you're writing.**
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
unipress create my-book
|
|
7
|
+
unipress compile my-book
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Two commands. The first scaffolds a starter project; the second produces the file.
|
|
11
|
+
|
|
12
|
+
## What it makes
|
|
13
|
+
|
|
14
|
+
| Format | What it's for |
|
|
15
|
+
|---|---|
|
|
16
|
+
| **PDF** | The finished, typeset document. Real typography, real pagination, ready to print or share. Built on [Typst](https://typst.app), the modern typesetting system. |
|
|
17
|
+
| **EPUB** | The format Kindles and other ebook readers use. |
|
|
18
|
+
| **Word (`.docx`)** | When a journal, committee, or collaborator needs a Word file. |
|
|
19
|
+
| **Excel (`.xlsx`)** | When the document is structured data — a directory, a dataset, a registry — rather than prose. |
|
|
20
|
+
| **Paged.js HTML** | Browser-paginated HTML you can print to PDF or post on the web. |
|
|
21
|
+
| **Typst source** | The `.typ` files unipress feeds the compiler. Useful if you want to take the typesetting further yourself, or hand off to a designer. |
|
|
22
|
+
|
|
23
|
+
Equations work in the standard LaTeX style — `$E = mc^2$` for inline, `$$...$$` for displayed. Tables, lists, footnotes, code blocks, and images all behave the way you'd expect from markdown.
|
|
24
|
+
|
|
25
|
+
## Two ways to use it
|
|
26
|
+
|
|
27
|
+
**For authors.** unipress is a tool. Pick a template, write markdown, compile. The template knows the conventions for its kind of document — typography, structure, the bits that make a book look like a book and a directory look like a directory. You handle the content; the template handles everything else.
|
|
28
|
+
|
|
29
|
+
**For developers.** unipress is an engine. A *foundation* is a component system that declares what section types exist (`type: Chapter`, `type: Bibliography`), where data comes from (`data:` declarations), and what output formats it can emit (`outputs: { docx, xlsx, pdf, custom-format }`). Authors write markdown against your vocabulary; unipress runs your foundation against their content. Same content directory, multiple outputs your foundation chooses to support — typeset book, accessible EPUB, regulatory report, structured data feed. The same foundation can also drive a [Uniweb](https://uniweb.io) website, so the work is never single-purpose.
|
|
30
|
+
|
|
31
|
+
Foundations consume [`@uniweb/press`](https://github.com/uniweb/press) for the bytes-emitting work. Press is the output layer (Word, Excel, Typst today; more formats shipping); the foundation is your vocabulary.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
**Standalone binary (recommended for most users).** No Node, no npm. Download the asset for your platform from [the releases page](https://github.com/uniweb/unipress/releases), make it executable, and put it somewhere on your `PATH` — `/usr/local/bin/unipress` is a common choice on macOS and Linux. Then you can run `unipress` from any directory.
|
|
36
|
+
|
|
37
|
+
**npm.** If you already have Node:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm i -g @uniweb/unipress
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Pick a template
|
|
44
|
+
|
|
45
|
+
Five built-in templates ship with the binary. Run `unipress list-templates` for the picker.
|
|
46
|
+
|
|
47
|
+
| Template | Foundation | Outputs | Use case |
|
|
48
|
+
|---|---|---|---|
|
|
49
|
+
| `book` | `@uniweb/book` | pdf, typst, pagedjs, epub | Trade book, long-form prose |
|
|
50
|
+
| `monograph` | `@uniweb/book` | pdf, typst, pagedjs, epub | Scholarly monograph (royal-octavo, classical typography) |
|
|
51
|
+
| `report` | `@uniweb/book` | pdf, typst, pagedjs, epub | Technical report (trade-7x10, block paragraphs) |
|
|
52
|
+
| `data-report` | `@uniweb/data` | xlsx, docx | Aggregate metrics across structured records |
|
|
53
|
+
| `directory` | `@uniweb/data` | xlsx, docx | Flat records listing with a filterable surface |
|
|
54
|
+
|
|
55
|
+
Per-template guides: [`docs/templates/`](./docs/templates/).
|
|
56
|
+
|
|
57
|
+
More templates land as more foundations ship — `cv`, `resume`, `paper`, `thesis` are on the roadmap for upcoming releases.
|
|
58
|
+
|
|
59
|
+
## Write your first document
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
unipress create my-book --template book --title "My Book" --author "Your Name"
|
|
63
|
+
cd my-book
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The result is a content-only directory — markdown pages, a `document.yml`, optional `theme.yml` and `assets/`. **No `package.json`, no `node_modules`.** Edit the markdown — that's your content. Numbered filenames (`01-intro.md`, `02-chapter-one.md`) keep chapter order predictable.
|
|
67
|
+
|
|
68
|
+
When you're ready to produce the document:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
unipress compile . --format pdf
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or any of the formats the foundation declares (`--format epub`, `--format pagedjs`). Write, compile, look at the result, revise, compile again — that's the loop.
|
|
75
|
+
|
|
76
|
+
The first PDF run downloads Typst 0.14.2 to `~/Library/Caches/unipress/typst/0.14.2/` (or the XDG cache dir on Linux). Subsequent runs reuse the cached binary.
|
|
77
|
+
|
|
78
|
+
## Custom foundations
|
|
79
|
+
|
|
80
|
+
Any foundation that declares an `outputs: { … }` map on its default export can drive unipress. Point `document.yml`'s `foundation:` at:
|
|
81
|
+
|
|
82
|
+
- a registry ref: `@<namespace>/<name>@<version>` — fetched from the Uniweb registry, cached locally,
|
|
83
|
+
- a URL: `https://…/foundation.js`,
|
|
84
|
+
- a local filesystem path: `./foundation`, `/abs/path`, etc.
|
|
85
|
+
|
|
86
|
+
The local-path form is the everyday dev loop — point unipress at a foundation directory you're iterating on, no publish step needed:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
unipress compile my-doc --foundation ../my-foundation
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
For the foundation contract — the `outputs:` map, the `getOptions(website, hostHints)` function, what bytes a foundation can emit — see the [foundation authors' guide](https://github.com/uniweb/docs/blob/main/reference/foundation-config.md#document-outputs). Foundations are distributed via the [Uniweb registry](https://uniweb.io), not npm.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
Below this point is reference material — useful when you want to do something beyond the basics, or when something doesn't behave as expected.
|
|
97
|
+
|
|
98
|
+
## CLI reference
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
unipress compile <dir> [options]
|
|
102
|
+
--format <fmt> Output format (pdf | typst | docx | xlsx | pagedjs | epub).
|
|
103
|
+
Overrides the format: field in document.yml.
|
|
104
|
+
--foundation <ref> Override document.yml's foundation. Accepts:
|
|
105
|
+
- registry ref: @<namespace>/<name>@<version>
|
|
106
|
+
- URL: https://…/foundation.js
|
|
107
|
+
- path: ./foundation, /abs/path, …
|
|
108
|
+
--out <path> Output file (default: ./<dir-basename>.<ext>).
|
|
109
|
+
--config <path> Explicit config file (default: <dir>/unipress.config.js).
|
|
110
|
+
--typst-binary <p> Path to a typst binary (skips the managed download).
|
|
111
|
+
--keep-temp On typst-compile failure, keep the temp dir for inspection.
|
|
112
|
+
--verbose Per-step progress to stderr + stack traces on errors.
|
|
113
|
+
|
|
114
|
+
unipress create <dir> [options]
|
|
115
|
+
--template <id> Template to scaffold (interactive picker if omitted).
|
|
116
|
+
Run `unipress list-templates` to see available ids.
|
|
117
|
+
--title <str> Document title (prompts if omitted).
|
|
118
|
+
--author <str> Document author (prompts if omitted).
|
|
119
|
+
--force Overwrite non-empty <dir>.
|
|
120
|
+
--yes Skip prompts (requires --template).
|
|
121
|
+
|
|
122
|
+
unipress list-templates
|
|
123
|
+
List the templates available, one per line, with description, outputs,
|
|
124
|
+
the foundation each pins, and the source URL where the foundation lives.
|
|
125
|
+
|
|
126
|
+
unipress inspect <dir> [options]
|
|
127
|
+
Dump the parsed content as JSON (debugging aid).
|
|
128
|
+
--full Include web-only fields (assets, icons, etc.).
|
|
129
|
+
--summary Replace pages[] with route strings only.
|
|
130
|
+
--page <route> Keep only the page matching <route>.
|
|
131
|
+
--depth <n> Truncate nested values beyond depth n.
|
|
132
|
+
--foundation <ref> Override document.yml's foundation.
|
|
133
|
+
--no-orchestrate Skip running the foundation; show only the parsed content.
|
|
134
|
+
|
|
135
|
+
unipress --help
|
|
136
|
+
unipress --version
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Exit codes: `0` success, `1` user-addressable error, `2` internal error (re-run with `--verbose` for a stack trace).
|
|
140
|
+
|
|
141
|
+
## Configuration
|
|
142
|
+
|
|
143
|
+
### `document.yml`
|
|
144
|
+
|
|
145
|
+
The content-directory-level config. Fields unipress reads:
|
|
146
|
+
|
|
147
|
+
| Field | Purpose |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `name` | Document name (used as a title fallback). |
|
|
150
|
+
| `foundation` | Registry ref (`@ns/name@ver`), URL, or local path to the foundation. |
|
|
151
|
+
| `format` | Default output format. Overridable by CLI `--format` or `unipress.config.js`. |
|
|
152
|
+
| `pages:` | Reading order (same semantics as a Uniweb site's `site.yml`). |
|
|
153
|
+
| `book:`, `report:`, `collections:` … | Foundation-specific config blocks. The foundation's `getOptions` reads these. |
|
|
154
|
+
|
|
155
|
+
`site.yml` is also accepted as a fallback for compatibility with existing Uniweb site directories.
|
|
156
|
+
|
|
157
|
+
### `unipress.config.js`
|
|
158
|
+
|
|
159
|
+
Optional ESM file for things awkward in YAML — imports, computed values, format-specific overrides. Auto-discovered at `<dir>/unipress.config.js` or explicit via `--config <path>`.
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
import { defineUnipressConfig } from '@uniweb/unipress'
|
|
163
|
+
|
|
164
|
+
export default defineUnipressConfig({
|
|
165
|
+
out: './dist/my-book.pdf', // overrides --out default
|
|
166
|
+
format: 'pdf', // overrides document.yml format
|
|
167
|
+
|
|
168
|
+
typst: {
|
|
169
|
+
version: '0.14.2', // override the pinned Typst version
|
|
170
|
+
binary: '/usr/local/bin/typst', // skip the managed download
|
|
171
|
+
},
|
|
172
|
+
})
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Plain `export default { … }` works equally well; `defineUnipressConfig` is an identity wrapper for editor autocomplete.
|
|
176
|
+
|
|
177
|
+
Relative paths in the config (`out`, `foundation`, `typst.binary`) resolve against the **config file's directory** — matching Vite / Astro convention.
|
|
178
|
+
|
|
179
|
+
### Precedence chain
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
CLI flags > unipress.config.js > document.yml > defaults
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Applied per-field.
|
|
186
|
+
|
|
187
|
+
## Typst binary
|
|
188
|
+
|
|
189
|
+
`--format pdf` requires a Typst binary. unipress pins `0.14.2` and manages the download:
|
|
190
|
+
|
|
191
|
+
- **Cache location:** `$UNIPRESS_CACHE_DIR` > `$XDG_CACHE_HOME/unipress` > `~/Library/Caches/unipress` (macOS) > `~/.cache/unipress` (fallback). Binary path: `<cache>/typst/<version>/typst`.
|
|
192
|
+
- **Override:** pass `--typst-binary <path>` or set `typst.binary` in `unipress.config.js`.
|
|
193
|
+
- **Checksum verified:** each download is SHA-256-checked against the digest pinned in `src/typst/versions.js`.
|
|
194
|
+
|
|
195
|
+
## Where things stand
|
|
196
|
+
|
|
197
|
+
unipress is **pre-1.0**. The CLI is stable enough to write real documents with — the `book` template, in particular, is well-tested. Future versions may change small things, but `document.yml` files and project folders from today should keep working: scaffolded projects pin a specific foundation version, and registry artifacts are immutable.
|
|
198
|
+
|
|
199
|
+
**Heads-up for v0.2:** the bundled catalog points at a local registry (`http://localhost:4001/...`) until the foundations publish to the production Uniweb registry. To compile against a bundled template today, either pass `--foundation <path>` pointing at a built foundation directory, or run a local foundation registry (publish a built foundation with `uniweb publish --local` and serve `.unicloud/registry/` on port 4001). A follow-up release switches the catalog to production URLs once `@uniweb/book` and `@uniweb/data` ship there.
|
|
200
|
+
|
|
201
|
+
## Troubleshooting
|
|
202
|
+
|
|
203
|
+
See [`docs/troubleshooting.md`](./docs/troubleshooting.md) for common errors and fixes — every named error class maps to a cause and a concrete next step.
|
|
204
|
+
|
|
205
|
+
## See also
|
|
206
|
+
|
|
207
|
+
- [`@uniweb/press`](https://github.com/uniweb/press) — the output layer foundations consume to produce Word/Excel/Typst/EPUB. Foundation authors interact with it directly.
|
|
208
|
+
- [`@uniweb/build`](https://github.com/uniweb/build) — the framework's content-collection pipeline. unipress consumes the sharp-free `/content` entry.
|
|
209
|
+
- [Uniweb](https://uniweb.io) — the larger framework. Foundations originate here; unipress brings them to the command line.
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
Apache-2.0 — see [LICENSE](./LICENSE).
|
package/RELEASING.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Releasing unipress
|
|
2
|
+
|
|
3
|
+
Notes for cutting a release tag (`unipress@<version>`). The release workflow at `.github/workflows/release.yml` watches for tag pushes matching that pattern, builds three binaries (darwin-arm64, linux-x64, windows-x64), and creates a GitHub Release with the binaries and SHA-256 sidecars attached.
|
|
4
|
+
|
|
5
|
+
This file mostly exists to flag one thing the release workflow currently can't handle on its own.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The CI install tension
|
|
10
|
+
|
|
11
|
+
unipress's runtime depends on five `@uniweb/*` framework packages (`@uniweb/build`, `@uniweb/content-reader`, `@uniweb/core`, `@uniweb/runtime`, `@uniweb/semantic-parser`). The CLI is developed inside a larger monorepo where these are sibling packages and resolve via `workspace:*`. That works for local dev — pnpm symlinks the local sources directly — but the release workflow checks out only this repo, with no monorepo around it.
|
|
12
|
+
|
|
13
|
+
Two strategies have been tried, and each has a failure mode:
|
|
14
|
+
|
|
15
|
+
- **`^X.Y.Z` (npm version specs).** Lets CI install standalone from npm. Failure mode: when framework changes ship in unpublished workspace versions, dev machines pnpm-resolve to the npm-published copy instead of the local sibling — meaning `pnpm install` from inside the monorepo silently picks up an older framework. This bit us once; the developer-side breakage is silent and hard to spot.
|
|
16
|
+
|
|
17
|
+
- **`workspace:*` (current).** Dev machines always get the local siblings. Failure mode: CI's `pnpm install --ignore-workspace --no-frozen-lockfile` has no way to resolve `workspace:*` outside a workspace — it will error.
|
|
18
|
+
|
|
19
|
+
Both strategies are correct for one audience and broken for the other. The current state is `workspace:*`, which means **the next release tag will fail at the CI install step until one of the two fixes below lands.**
|
|
20
|
+
|
|
21
|
+
## Two ways out
|
|
22
|
+
|
|
23
|
+
### (a) Publish all `@uniweb/*` framework packages to npm at the release version, then flip the specs back to npm ranges at release time
|
|
24
|
+
|
|
25
|
+
The `pnpm framework:publish:*` shortcuts in the outer monorepo handle the framework publish. Workflow:
|
|
26
|
+
|
|
27
|
+
1. From the outer monorepo, bump + publish all framework packages: `pnpm framework:publish:patch` (or `:minor`).
|
|
28
|
+
2. Wait for the publish to settle on npm.
|
|
29
|
+
3. In the unipress repo, change the five `@uniweb/*` deps in `package.json` from `workspace:*` back to `^<published-version>` matching what just shipped.
|
|
30
|
+
4. Commit, tag `unipress@<version>`, push.
|
|
31
|
+
5. After the release CI succeeds and the binary is out, switch the deps back to `workspace:*` so dev resolution stays correct.
|
|
32
|
+
|
|
33
|
+
Pros: keeps the CI workflow simple — `pnpm install --ignore-workspace --no-frozen-lockfile` continues to work standalone. The release artifact is reproducible from npm with no monorepo context.
|
|
34
|
+
|
|
35
|
+
Cons: requires a framework publish before every unipress release. Adds a step. The flip-back-to-`workspace:*` after release is easy to forget; if you skip it, the next dev `pnpm install` quietly downgrades the framework deps to the npm-published versions. Worth automating the flip with a script if this becomes the standard path.
|
|
36
|
+
|
|
37
|
+
### (b) Build the unipress binary inside the outer monorepo's CI
|
|
38
|
+
|
|
39
|
+
Add a release workflow at the **outer monorepo** that:
|
|
40
|
+
|
|
41
|
+
1. Watches for tag pushes matching `unipress@*`.
|
|
42
|
+
2. Checks out the outer monorepo (which has the workspace + all `@uniweb/*` siblings cloned via `pnpm clone`).
|
|
43
|
+
3. Runs `pnpm install` at the outer root (resolves `workspace:*` correctly).
|
|
44
|
+
4. Runs `node scripts/build-binaries.js` from inside `framework/unipress/`.
|
|
45
|
+
5. Uploads the resulting binaries to a GitHub Release in the **unipress** repo (cross-repo release via `gh release` with a PAT).
|
|
46
|
+
|
|
47
|
+
Pros: matches the dev environment exactly — workspace:* always resolves the same way locally and in CI. No extra publish step. No flip-back dance.
|
|
48
|
+
|
|
49
|
+
Cons: more workflow complexity. Cross-repo release upload requires a PAT (the workflow's default `GITHUB_TOKEN` is scoped to its own repo). The outer monorepo is private, so the workflow runs there and can't be inspected by anyone outside the org — fine for our purposes but worth noting if unipress ever gets external contributors who want to understand how releases are produced.
|
|
50
|
+
|
|
51
|
+
## Recommendation
|
|
52
|
+
|
|
53
|
+
**Go with (a) for v0.x releases. Move to (b) once unipress's release cadence outpaces the framework's**, or once the outer monorepo's CI matures enough that adding a cross-repo build step is cheap.
|
|
54
|
+
|
|
55
|
+
Why (a) first:
|
|
56
|
+
|
|
57
|
+
- The framework already publishes to npm on its own cadence. Tagging unipress *after* a framework publish settles is a normal sequencing — every framework feature unipress depends on is on npm anyway by the time a release ships.
|
|
58
|
+
- The flip-back-to-`workspace:*` step is the only friction, and it's a one-line change. Easy to script.
|
|
59
|
+
- (b) is strictly more invasive and ties the unipress release pipeline to the outer monorepo's existence — a coupling worth deferring.
|
|
60
|
+
|
|
61
|
+
When (b) starts to make sense:
|
|
62
|
+
|
|
63
|
+
- If unipress needs to release patches against unpublished framework changes (rare, but possible).
|
|
64
|
+
- If the framework publish cadence becomes the bottleneck on shipping unipress fixes.
|
|
65
|
+
- If cross-repo release infrastructure is already in place for other reasons (e.g., other tools in `framework/` shipping binaries).
|
|
66
|
+
|
|
67
|
+
## Concrete checklist for the next release
|
|
68
|
+
|
|
69
|
+
Until (b) lands, every release goes through this:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# 1. From the outer monorepo: bump + publish framework
|
|
73
|
+
pnpm framework:publish:patch # or :minor
|
|
74
|
+
|
|
75
|
+
# 2. Note the new versions: check `framework/<pkg>/package.json` for each.
|
|
76
|
+
|
|
77
|
+
# 3. In framework/unipress/, edit package.json:
|
|
78
|
+
# - "@uniweb/build": "workspace:*" → "^<new-version>"
|
|
79
|
+
# - (repeat for content-reader, core, runtime, semantic-parser)
|
|
80
|
+
|
|
81
|
+
# 4. Bump unipress version + update CHANGELOG (this file's git history
|
|
82
|
+
# should make the pattern obvious).
|
|
83
|
+
|
|
84
|
+
# 5. Commit + tag + push:
|
|
85
|
+
git add package.json CHANGELOG.md
|
|
86
|
+
git commit -m "release: <version>"
|
|
87
|
+
git tag -a unipress@<version> -m "..."
|
|
88
|
+
git push origin main
|
|
89
|
+
git push origin unipress@<version>
|
|
90
|
+
|
|
91
|
+
# 6. Wait for the release workflow. Confirm artifacts uploaded.
|
|
92
|
+
# The release is created as a draft — review and publish it via
|
|
93
|
+
# `gh release edit unipress@<version> --draft=false`.
|
|
94
|
+
|
|
95
|
+
# 7. Flip framework deps back to workspace:* so dev resolution stays
|
|
96
|
+
# correct against unpublished framework changes:
|
|
97
|
+
git revert <step-3-commit> # or hand-edit + commit
|
|
98
|
+
git push origin main
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Step 7 is the easy-to-forget one. If a dev pulls and runs `pnpm install` while the package.json still has the npm specs from step 3, they'll silently get the npm-published framework copies — which means any unpublished framework features won't be available locally. Don't skip step 7.
|