Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions news/changelog-1.10.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
All changes included in 1.10:

## Engines

### `julia`

- Update `julia` engine extension from 0.1.0 to 0.2.0 and QuartoNotebookRunner from 0.17.4 to 0.18.1.
- Add `keep-ipynb` support. When `keep-ipynb: true` is set in document YAML, the executed notebook is written alongside the source file.
- Add shared worker processes. Multiple notebooks sharing the same config can reuse a single worker process via `julia: share_worker_process: true`.
- Add support for `execute-dir: project` to set working directory to project root.
- Add diagnostic file logging via `QUARTONOTEBOOKRUNNER_LOG` environment variable.
- Cache worker package environments across sessions, skipping environment setup on subsequent runs when Julia and QNR versions haven't changed.
- Relax manifest version checking to major.minor by default, matching Julia's Pkg behavior. Opt into strict checking via `julia: strict_manifest_versions: true`.
- Fix `fig-format: retina` by normalizing to `png` with doubled `fig-dpi`, matching Jupyter and knitr backends.
- Fix cache invalidation to hash full `Manifest.toml` content so dependency version changes correctly invalidate the cache.
- Fix duplicate YAML keys when Python/R cells have cell options like `echo`.

## Formats

### `typst`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: "Enforce changelog"
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]

jobs:
changelog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dangoslen/changelog-enforcer@204e7d3ef26579f4cd0fd759c57032656fdf23c7 # v3.6.1
with:
changeLogPath: 'CHANGELOG.md'
skipLabels: 'skip-changelog'
4 changes: 4 additions & 0 deletions src/resources/extension-subtrees/julia-engine/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ CI runs on all three platforms (Linux, macOS, Windows) against a pinned quarto-c
3. Runs the full test suite

When bumping `QUARTO_CLI_REV`, use the full commit hash annotated with the version tag for clarity (e.g. `abc123 # v1.9.35`).

## Changelog

Every PR with user-facing or otherwise meaningful changes must include an update to `CHANGELOG.md` (enforced by CI). Add entries under the `## Unreleased` section. Use the `skip-changelog` label to bypass the check for PRs that don't need an entry (e.g. internal cleanups, CI, or docs changes).
28 changes: 28 additions & 0 deletions src/resources/extension-subtrees/julia-engine/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Quarto Julia Engine changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

## [0.2.0](https://github.com/PumasAI/quarto-julia-engine/releases/tag/v0.2.0) - 2026-03-24

- Added `keep-ipynb` support. When `keep-ipynb: true` is set in document YAML, the executed notebook is written to `<stem>.ipynb` alongside the source file [#8](https://github.com/PumasAI/quarto-julia-engine/pull/8).
- Updated to QuartoNotebookRunner 0.18.1 [#11](https://github.com/PumasAI/quarto-julia-engine/pull/11):
- **`fig-format: retina` support**: Normalized to `png` with doubled `fig-dpi`, matching Quarto's Jupyter and knitr backends. Fixes blurry plots with default HTML settings.
- **Improved cache invalidation**: Cache key now hashes full `Manifest.toml` content (SHA-224) so dependency version changes correctly invalidate the cache.
- Updated to QuartoNotebookRunner 0.18.0 [#7](https://github.com/PumasAI/quarto-julia-engine/pull/7):
- **Shared worker processes**: Multiple notebooks can share a single worker process when their configs match. Enable with `share_worker_process: true`.
- **`execute-dir` support**: Quarto's `execute-dir` option (e.g. `execute-dir: project`) is now passed through correctly.
- **Cached worker environments**: Worker envs persist across sessions, skipping environment setup on subsequent runs when Julia and QNR versions haven't changed.
- **Relaxed manifest version checking**: Only major.minor is checked by default, matching Julia's Pkg behavior. Opt into strict major.minor.patch via `julia: strict_manifest_versions: true`.
- **Diagnostic file logging**: Set `QUARTONOTEBOOKRUNNER_LOG` to a directory path to enable timestamped log files.
- **Echo handling for Python/R cells**: Fixed duplicate YAML keys and added proper support for `echo: false` and `echo: fenced`.

## [0.1.0](https://github.com/PumasAI/quarto-julia-engine/releases/tag/v0.1.0) - 2026-03-19

- Initial release as a standalone Quarto extension, extracted from [quarto-cli](https://github.com/quarto-dev/quarto-cli).
- Bundled Julia resource files (`Project.toml`, `ensure_environment.jl`, `quartonotebookrunner.jl`, `start_quartonotebookrunner_detached.jl`) into the extension, making it fully self-contained [#6](https://github.com/PumasAI/quarto-julia-engine/pull/6).
- Added CI workflow with tests on Linux, macOS, and Windows [#6](https://github.com/PumasAI/quarto-julia-engine/pull/6).
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
QuartoNotebookRunner = "4c0109c6-14e9-4c88-93f0-2b974d3468f4"

[compat]
QuartoNotebookRunner = "=0.17.4"
QuartoNotebookRunner = "=0.18.1"
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
title: Quarto Julia Engine Extension
version: 0.1.0
version: 0.2.0
quarto-required: ">=1.9.0"
contributes:
engines:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ var kFigFormat = "fig-format";
var kFigPos = "fig-pos";
var kIpynbProduceSourceNotebook = "produce-source-notebook";
var kKeepHidden = "keep-hidden";
var kKeepIpynb = "keep-ipynb";

// src/julia-engine.ts
var isWindows2 = Deno.build.os === "windows";
Expand Down Expand Up @@ -749,6 +750,11 @@ var juliaEngineDiscovery = {
language: "julia"
};
const assets = quarto.jupyter.assets(options.target.input, options.format.pandoc.to);
if (options.format.execute[kKeepIpynb]) {
const stem = options.target.source.replace(/\.[^.]+$/, "");
const ipynbPath = stem + ".ipynb";
Deno.writeTextFileSync(ipynbPath, JSON.stringify(nb, null, 2));
}
const result = await quarto.jupyter.toMarkdown(nb, {
executeOptions: options,
language: nb.metadata.kernelspec.language.toLowerCase(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export const kFigFormat = "fig-format";
export const kFigPos = "fig-pos";
export const kIpynbProduceSourceNotebook = "produce-source-notebook";
export const kKeepHidden = "keep-hidden";
export const kKeepIpynb = "keep-ipynb";
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
kIpynbProduceSourceNotebook,
kJuliaEngine,
kKeepHidden,
kKeepIpynb,
} from "./constants.ts";

// Platform detection
Expand Down Expand Up @@ -220,6 +221,14 @@ export const juliaEngineDiscovery: ExecutionEngineDiscovery = {
options.format.pandoc.to,
);

// Write notebook to file if keep-ipynb is set (must happen before
// toMarkdown which mutates nb in place)
if (options.format.execute[kKeepIpynb]) {
const stem = options.target.source.replace(/\.[^.]+$/, "");
const ipynbPath = stem + ".ipynb";
Deno.writeTextFileSync(ipynbPath, JSON.stringify(nb, null, 2));
}

// NOTE: for perforance reasons the 'nb' is mutated in place
// by jupyterToMarkdown (we don't want to make a copy of a
// potentially very large notebook) so should not be relied
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
# Allow only source files
!*/*.qmd
!*/_quarto.yml
!*/_metadata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engines: ["julia"]

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: keep-ipynb test
engine: julia
format: html
keep-ipynb: true
---

```{julia}
1 + 1
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: no keep-ipynb test
engine: julia
format: html
---

```{julia}
1 + 1
```

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,40 @@ Deno.test("source ranges with includes", async () => {
try { Deno.removeSync(outputFile); } catch { /* ok */ }
});

Deno.test("keep-ipynb", async () => {
const dir = docs("julia-engine/keep-ipynb");
const input = join(dir, "keep-ipynb.qmd");
renderQmd(input, ["--to", "html"]);

const outputHtml = join(dir, "keep-ipynb.html");
assert(existsSync(outputHtml), `Output file ${outputHtml} should exist`);

const ipynbFile = join(dir, "keep-ipynb.ipynb");
assert(existsSync(ipynbFile), `keep-ipynb file ${ipynbFile} should exist`);

const content = await Deno.readTextFile(ipynbFile);
const nb = JSON.parse(content);
assert(nb.cells, "Notebook should have cells");
assert(nb.metadata, "Notebook should have metadata");

try { Deno.removeSync(outputHtml); } catch { /* ok */ }
try { Deno.removeSync(ipynbFile); } catch { /* ok */ }
});

Deno.test("no keep-ipynb by default", () => {
const dir = docs("julia-engine/keep-ipynb");
const input = join(dir, "no-keep-ipynb.qmd");
renderQmd(input, ["--to", "html"]);

const outputHtml = join(dir, "no-keep-ipynb.html");
assert(existsSync(outputHtml), `Output file ${outputHtml} should exist`);

const ipynbFile = join(dir, "no-keep-ipynb.ipynb");
assert(!existsSync(ipynbFile), `ipynb file ${ipynbFile} should NOT exist without keep-ipynb`);

try { Deno.removeSync(outputHtml); } catch { /* ok */ }
});

Deno.test("engine reordering", () => {
const dir = docs("julia-engine/engine-reordering");
renderQmd("notebook.qmd", ["--to", "html"], dir);
Expand Down
Loading