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
14 changes: 14 additions & 0 deletions news/changelog-1.10.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ All changes included in 1.10:
- ([#14298](https://github.com/quarto-dev/quarto-cli/issues/14298)): Fix `quarto preview` browse URL including output filename (e.g., `hello.html`) for single-file documents, breaking Posit Workbench proxied server access.
- ([rstudio/rstudio#17333](https://github.com/rstudio/rstudio/issues/17333)): Fix `quarto inspect` on standalone files emitting project metadata that breaks RStudio's publishing wizard.

## 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
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).
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
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
10 changes: 10 additions & 0 deletions tests/docs/julia-engine/keep-ipynb/keep-ipynb.qmd
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
```
9 changes: 9 additions & 0 deletions tests/docs/julia-engine/keep-ipynb/no-keep-ipynb.qmd
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
```
Loading