oaktree-sapling 0.0.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.
Files changed (37) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +66 -0
  3. package/ci/run.sh +64 -0
  4. package/dist/cli.cjs +1230 -0
  5. package/package.json +50 -0
  6. package/paper-base.yml +29 -0
  7. package/plugins/gallery.mjs +224 -0
  8. package/templates/instance/brand/brand.yml +15 -0
  9. package/templates/instance/brand/logo.svg +4 -0
  10. package/templates/instance/editions/edition.yml +14 -0
  11. package/templates/instance/journal.yml +58 -0
  12. package/templates/instance/registry/papers.yml +20 -0
  13. package/templates/paper/.github/actions/engine/action.yml +59 -0
  14. package/templates/paper/.github/actions/engine/pins.yml +16 -0
  15. package/templates/paper/.github/workflows/check-post.yml +79 -0
  16. package/templates/paper/.github/workflows/check.yml +72 -0
  17. package/templates/paper/.github/workflows/ci.yml +64 -0
  18. package/templates/paper/.github/workflows/prepare.yml +34 -0
  19. package/templates/paper/.github/workflows/preview-deploy.yml +52 -0
  20. package/templates/paper/.github/workflows/publish.yml +33 -0
  21. package/templates/paper/.github/workflows/version-bump.yml +29 -0
  22. package/templates/paper/CODEOWNERS +9 -0
  23. package/templates/paper/bib.bib +6 -0
  24. package/templates/paper/gitignore +8 -0
  25. package/templates/paper/index.md +12 -0
  26. package/templates/paper/myst.yml +37 -0
  27. package/templates/site/.github/workflows/site.yml +73 -0
  28. package/templates/site/gitignore +5 -0
  29. package/templates/site/myst.yml +32 -0
  30. package/templates/site/package.json +9 -0
  31. package/templates/site/pages/index.md +25 -0
  32. package/templates/typst/LICENSE +21 -0
  33. package/templates/typst/frontmatter.typ +244 -0
  34. package/templates/typst/lapreprint.typ +310 -0
  35. package/templates/typst/template.typ +112 -0
  36. package/templates/typst/template.yml +82 -0
  37. package/typst.version +1 -0
package/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Neuromatch, Inc.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # oaktree-sapling
2
+
3
+ A journal engine for small publications built on [MyST](https://mystmd.org), GitHub and Zenodo.
4
+
5
+ One repo holds the journal: its settings, branding, editions and the list of published papers.
6
+ Each paper gets a repo of its own, with CI that builds a website and a PDF, runs the journal's checks on every pull request, publishes a preview, and deposits the final version to Zenodo for a DOI. `oak` is the command line tool that sets those repos up and does the work inside them.
7
+
8
+ Papers refer to the engine by a single version coordinate, so a journal upgrades by changing one line rather than by copying workflow files around.
9
+
10
+ ## Status
11
+
12
+ Pre-1.0 and in active development. Every command is implemented and the CI is being tested end to end against real GitHub, Cloudflare and Zenodo, but interfaces may still change between 0.x versions and the documentation is incomplete. Its original design served Neuromatch Impact Scholars Program 2025, but is being heavily revised to become suitable to more tenants.
13
+
14
+ ## Install
15
+
16
+ ```
17
+ npm install -g oaktree-sapling
18
+ oak
19
+ ```
20
+
21
+ `oak` with no arguments prints the full usage.
22
+
23
+ ## Commands
24
+
25
+ Setting up repos:
26
+
27
+ - `oak bootstrap journal` — create the journal repo (settings, branding, paper list)
28
+ - `oak bootstrap paper` — create a paper repo pointing at a journal
29
+ - `oak upgrade` — move a paper repo to a newer engine version, as a pull request
30
+
31
+ Working on a paper:
32
+
33
+ - `oak validate` — run the journal's checks over a manuscript
34
+ - `oak build` — build the paper's website and PDF into `_build/`
35
+ - `oak start` — preview it in a browser with the journal's settings applied
36
+
37
+ The rest (`check-post`, `deploy-preview`, `deposit`, `release`, `notify`, `conformance`) are run by the generated workflows and are rarely typed by hand.
38
+
39
+ ## Known limitations of the npm package
40
+
41
+ The engine is normally run from a checked-out release tag, which carries two things the npm package does not:
42
+
43
+ - **No PDF export.** A pinned `typst` binary ships with each release tag; the package has none, so `oak build` produces a PDF only if `typst` is already on your `PATH`.
44
+ - **`oak deposit` does not work.** It archives the engine with `git archive` to record what built the paper, which needs a git checkout rather than an installed package.
45
+
46
+ Both are being worked on. Until then, CI uses release tags.
47
+
48
+ ## Editorial checks
49
+
50
+ `oak validate` runs two kinds of check. The engine's own invariants are built in. The editorial checks a journal selects — authors exist, have ORCIDs, have valid CRediT roles, abstract exists, keywords defined — come from the MIT-licensed [`@curvenote/check-implementations`](https://www.npmjs.com/package/@curvenote/check-implementations) and [`@curvenote/check-definitions`](https://www.npmjs.com/package/@curvenote/check-definitions). The engine supplies the runner and the GitHub Check Run reporter.
51
+
52
+ ## Development
53
+
54
+ ```
55
+ npm install
56
+ npm test
57
+ npm run typecheck
58
+ ```
59
+
60
+ `NOTES.md` has the module map and the build internals. `RELEASING.md` explains how releases are cut and why the built bundle is committed at the tag.
61
+
62
+ ## License
63
+
64
+ BSD 3-Clause, copyright Neuromatch, Inc. See `LICENSE`.
65
+
66
+ One subtree is not covered by it: `templates/typst/` is the [LaPreprint](https://github.com/curvenote/lapreprint) typst template, MIT-licensed and copyright Rowan Cockett. It keeps its own `LICENSE` alongside it, which ships with the package and with every release tag.
package/ci/run.sh ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env bash
2
+ # The ONLY bash in the engine (design §12). The composite action has already checked out
3
+ # the engine at the pinned ref into ./.engine and set INSTANCE_REPO from pins.yml. This
4
+ # does the CI-specific *materialization* §1b assigns it — typst on PATH, instance-config
5
+ # cloned, BASE_URL by event — then dispatches to dist/cli.cjs, where all LOGIC lives.
6
+ # (Resolves the §12 "5 lines" aspiration toward §1b: setup here, logic in the bundle.)
7
+ set -euo pipefail
8
+
9
+ here="$(cd "$(dirname "$0")" && pwd)"
10
+ engine="$(cd "$here/.." && pwd)"
11
+ verb="${1:-}"
12
+
13
+ # A runnable engine ⟺ a release ([R57]): dist/cli.cjs is committed ONLY onto release-tag
14
+ # leaves, never a branch tip. If it's absent the pinned ref is a branch (or a bad tag) —
15
+ # fail loud with the fix, not a raw "Cannot find module". This guard IS the enforcement of
16
+ # "CI runs released tags only"; nothing else rejects a branch pin.
17
+ if [ ! -f "$engine/dist/cli.cjs" ]; then
18
+ echo "::error::engine ref carries no dist/cli.cjs — pin a released tag, not a branch tip (a runnable engine ⟺ a release, [R57]; see RELEASING.md)"
19
+ exit 1
20
+ fi
21
+
22
+ # typst — prefer a binary shipped with the engine tag ([R34]); else rely on PATH.
23
+ if [ -x "$engine/bin/typst" ]; then export PATH="$engine/bin:$PATH"; fi
24
+
25
+ extra=()
26
+
27
+ # build + release run a real myst build → pick BASE_URL. deploy-preview only reads the
28
+ # journal.yml preview: fields ([R27]), so it needs the instance but never a base_url.
29
+ if [ "$verb" = "build" ] || [ "$verb" = "release" ]; then
30
+ # BASE_URL: '' for PR previews (served at the Cloudflare root), '/<repo>' for Pages/prod.
31
+ if [ "${GITHUB_EVENT_NAME:-}" = "pull_request" ]; then
32
+ base_url=""
33
+ else
34
+ base_url="/${GITHUB_REPOSITORY##*/}"
35
+ fi
36
+ extra+=(--base-url "$base_url")
37
+ fi
38
+
39
+ # instance-config: public, depth-1, default branch (dec. 16/19). '.' = co-located
40
+ # (repo=journal, deferred) — leave to the CLI's root resolution. build/release need it for
41
+ # the extends chain; deploy-preview needs it for the preview: knobs ([R27]/[R69]); validate
42
+ # needs it for journal.yml `checks:` + the registry (id-uniqueness).
43
+ if [ "$verb" = "build" ] || [ "$verb" = "release" ] || [ "$verb" = "deploy-preview" ] || [ "$verb" = "validate" ]; then
44
+ if [ -n "${INSTANCE_REPO:-}" ] && [ "${INSTANCE_REPO}" != "." ]; then
45
+ inst_dir="$(mktemp -d)"
46
+ git clone --depth 1 "https://github.com/${INSTANCE_REPO}.git" "$inst_dir"
47
+ extra+=(--instance "$inst_dir")
48
+ fi
49
+ fi
50
+
51
+ echo "::group::engine context"
52
+ echo "engine dir : $engine"
53
+ echo "verb : $verb"
54
+ echo "instance : ${INSTANCE_REPO:-<co-located>}"
55
+ echo "extra args : ${extra[*]:-<none>}"
56
+ # Secret PRESENCE only — never the value (design §1a: echo what we resolved; aids a
57
+ # tenant's first broken run, and lets the [R18] step-env-propagation spike be observed
58
+ # on prepare/publish/preview-deploy without leaking anything). `:+present` is set -u safe.
59
+ echo "GH_TOKEN : ${GH_TOKEN:+present}"
60
+ echo "ZENODO_TOKEN : ${ZENODO_TOKEN:+present}"
61
+ echo "CLOUDFLARE : ${CLOUDFLARE_API_TOKEN:+present}"
62
+ echo "::endgroup::"
63
+
64
+ exec node "$engine/dist/cli.cjs" "$@" "${extra[@]}"