Skip to content

Move the OJS runtime and its Observable forks from quarto-dev/quarto - #15046

Merged
cderv merged 4 commits into
quarto-dev:mainfrom
nealrichardson:build/move-ojs-runtime
Oct 15, 2026
Merged

cderv merged 4 commits into
quarto-dev:mainfrom
nealrichardson:build/move-ojs-runtime

Conversation

@nealrichardson

Copy link
Copy Markdown
Contributor

Closes #15043.

This moves the OJS runtime and its vendored Observable forks from quarto-dev/quarto's packages/ojs/ into packages/ojs/ here, next to packages/quarto-types. It adds an npm build that regenerates the committed bundles, and a CI check that the committed bundles match the sources. quarto-dev/quarto#1180 deletes the copy there once this lands.

Commits

Each commit is reviewable separately:

  1. Copy packages/ojs from quarto-dev/quarto. A verbatim copy from quarto-dev/quarto@42177e13, the commit before Problem creating PDFs - 'No TeX installation was detected' (Windows 10) #1180's deletion, so Problem creating PDFs - 'No TeX installation was detected' (Windows 10) #1180's rollup tooling upgrade comes along. The only file left out is quarto-ojs-runtime/assets/quarto.css, because this repo's quarto-ojs.css is newer.
  2. Build with npm. The changes to the copied files:
    • packages/ojs/package.json is an npm workspace root that links the runtime and the five forks. It has a committed package-lock.json. npm run build writes quarto-ojs-runtime{,.min}.js straight into src/resources/formats/html/ojs/.
    • The forks' devDependencies and yarn.lock files are removed. They were only for each fork's own build and tests, which never ran in quarto-dev/quarto's CI either. Their old rollup plugins fail npm's peer dependency checks (rollup-plugin-terser 7 needs rollup 2, but the forks use rollup 3), and they would keep the dev-only Snyk advisories.
    • The compiler fork's package.json gets "module": "src/index.js". Its main was a UMD dist/ that had to be built first with rollup 1. Now the runtime's rollup bundles the compiler from its ES module source. This also makes @rollup/plugin-commonjs unnecessary: with it removed, the output is byte-identical.
    • The banner no longer includes new Date().getFullYear(), so a rebuild gives the same bytes in any year. The banner used to read "Copyright 2024 undefined"; now it reads // quarto-ojs-runtime v0.0.19 Copyright Posit Software, PBC. The runtime's version is bumped to 0.0.19.
    • notes.md is replaced with a README.md. The old notes' git subtree pull commands won't work on plain copies.
  3. Rebuild the bundles and check them in CI. This adds .github/workflows/test-ojs-runtime.yml, which runs when packages/ojs/** or the bundles change. It runs npm ci && npm run build, then fails if git diff shows the bundles changed.

Bundle changes

Compared with #1180's bundle, the new one differs only in how the compiler is included. The compiler's code is inlined as ES modules instead of as an embedded UMD blob, which also renumbers some identifiers (hasOwnProperty$2 → $3, and so on). The bundled library versions are the same: acorn 7.4.1 for the compiler's @observablehq/parser 4.2, and acorn 8.17.0 for the parser fork.

Compared with the bundle on main, which was last rebuilt in 2024-02, this also ships everything listed in #15043: acorn 8.8.1 → 8.17, the debugger removal, inspector 5.0.1, Inputs 0.10.6, and mime 4 (FileAttachment(…).mimeType is text/javascript for .js). @observablehq/inputs stays on 0.10, as the README notes.

Testing

  • npm ci && npm run build in packages/ojs on Node 24 / npm 11: clean install, 0 vulnerabilities, no peer warnings. Rebuilding from a fresh npm ci reproduces the committed bundles exactly.
  • I rendered all of tests/docs/playwright/ojs/*.qmd with the dev build and ran the 7 OJS spec files (9 tests) in Chromium, Firefox and WebKit: 27/27 pass. The rendered pages load the v0.0.19 bundle.

Notes for reviewers

  • I didn't preserve history (git subtree/filter-repo), because PRs here are squash-merged. The source commit is recorded in commit 1 and in the README.
  • The forks' nested .github/ and .circleci/ directories came along with the copy. They're inactive outside the repo root. I kept them so the forks stay close to upstream.
  • deno lint/fmt only include src/, so they don't check the vendored JS.

🤖 Generated with Claude Code

nealrichardson and others added 3 commits October 13, 2026 13:20
Copy the OJS runtime and its five vendored Observable forks verbatim
from packages/ojs in quarto-dev/quarto at 42177e13, which includes the
rollup tooling upgrade from quarto-dev/quarto#1180. The only omission is
quarto-ojs-runtime/assets/quarto.css, which is older than this repo's
src/resources/formats/html/ojs/quarto-ojs.css.

Part of quarto-dev#15043.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Add an npm workspace root in packages/ojs that links the runtime and
  the forks, with a package-lock.json. npm run build writes both bundles
  straight into src/resources/formats/html/ojs.
- Remove the forks' devDependencies and yarn.lock files. They were for
  each fork's own build and tests, which don't run here, and their old
  rollup plugins fail npm's peer dependency checks.
- Point the compiler fork's module field at its ES module source, so the
  runtime's rollup build bundles it directly. This removes the need for a
  rollup 1 build of its UMD dist and for @rollup/plugin-commonjs (the
  bundles are byte-identical without it).
- Drop the build year from the banner so the build is reproducible, and
  bump quarto-ojs-runtime to 0.0.19.
- Replace notes.md, whose git subtree commands no longer apply, with a
  README.

Part of quarto-dev#15043.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Rebuild quarto-ojs-runtime{,.min}.js from packages/ojs. Besides the
build tooling, this ships everything since the last bump in 2024-02:
acorn 8.17, the debugger removal, inspector 5.0.1, Inputs 0.10.6 and
mime 4.

Add a workflow that rebuilds the bundles when packages/ojs or the
bundles change, and fails if they differ from the committed ones.

Closes quarto-dev#15043.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Comment thread .github/workflows/test-ojs-runtime.yml
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- uses: actions/checkout@v1
- uses: actions/checkout@v7

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait do we even need this? this is just vendored?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, GitHub only runs workflows from the root .github/workflows, so this one never runs here. Same for the other CI files this PR adds under the forks:

packages/ojs/external-asg017-unofficial-observablehq-compiler/.circleci/config.yml
packages/ojs/external-asg017-unofficial-observablehq-compiler/.github/workflows/main.yml
packages/ojs/external-d3-d3-require/.github/eslint.json
packages/ojs/external-d3-d3-require/.github/workflows/node.js.yml
packages/ojs/external-observablehq-parser/.github/eslint.json
packages/ojs/external-observablehq-parser/.github/workflows/nodejs.yml
packages/ojs/external-observablehq-runtime/.github/workflows/nodejs.yml
packages/ojs/external-observablehq-stdlib/.github/workflows/nodejs.yml

The forks' devDependencies are already removed, so the test/build scripts these workflows call can't run anyway. I would remove the nested .github/ and .circleci/ directories before merging, so they don't end up in main and attract bump suggestions like the one on this file.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Removed all eight files listed (the nested .github/ and .circleci/ dirs in the forks) in 730faee, and noted the removal under "Changes from the copies in quarto-dev/quarto" in the README.

@vezwork
vezwork requested review from cderv and cscheid October 14, 2026 17:32
@vezwork

vezwork commented Oct 14, 2026

Copy link
Copy Markdown
Member

@cscheid @cderv please take a look. We would like to move the ojs runtime from the Quarto repo to this repo. It looks good to me from the extension side, how does it look on the cli side?

@cderv cderv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks good to me from the quarto-cli side.

What I checked in addition to your testing:

  • The rebuild also reproduces the bundles on Windows. The unminified one comes out with CRLF line endings there, but .gitattributes normalizes it, so git diff stays empty and the CI check holds for Windows contributors.
  • Only the bundle ships. Nothing under packages/ is picked up by prepare-dist, and deno lint/fmt don't see it.
  • For self-contained output we inline quarto-ojs-runtime.js into a <script type="module"> without any escaping. The new bundle still has no </script in it, so that path is fine.
  • The 14 smoke-all documents with {ojs} cells also pass with the new bundle.

A few small changes suggested inline, none blocking.

Comment thread packages/ojs/README.md Outdated
Comment thread packages/ojs/README.md Outdated
Comment thread news/changelog-1.11.md Outdated
Remove the forks' nested CI configs, note the escodegen and escape-html
licenses, and record the source commit in the README. Mention .mjs in
the changelog entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cderv
cderv merged commit 8ee034c into quarto-dev:main Oct 15, 2026
52 checks passed
@nealrichardson
nealrichardson deleted the build/move-ojs-runtime branch October 15, 2026 13:31
cderv added a commit that referenced this pull request Oct 15, 2026
The OJS runtime and its Observable forks now live in packages/ojs/,
but nothing in the repo explained how {ojs} cells reach that runtime or
what a runtime change must include to be complete. Add that
documentation so maintainers can work on the render path and the update
process without reverse-engineering it.

- llm-docs/ojs-architecture.md: the render path through ojsCompile(),
  linking or inlining the runtime for self-contained output, the Lua
  filter for inline ${...}, ojs_define per engine, resource extraction,
  and which files are generated versus hand-edited.
- dev-docs/update-ojs-runtime.md: the maintainer procedure for a runtime
  change, npm dependency bump, or fork change, including what to commit
  together and what to verify beyond the bundle CI check (self-contained
  render, Shiny inputs, FileAttachment MIME types after a mime upgrade).
  dev-docs/upgrade-dependencies.md links to it.
- .claude/rules/formats/ojs.md: a path-scoped rule pointing to both docs
  when editing OJS sources.
- vendored-html-dependencies.md excludes ojs/, since the vendored
  dependency updater does not manage it.

See #15046
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move the OJS runtime and its Observable forks from quarto-dev/quarto into quarto-cli

4 participants