Skip to content

Commit ffafa54

Browse files
authored
Merge branch 'main' into fix/chromium-deprecation-arm64
2 parents 7c8cdb8 + 4b3bf72 commit ffafa54

20 files changed

Lines changed: 267 additions & 34 deletions

File tree

.github/workflows/test-ff-matrix.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ on:
2020
- ".github/workflows/stale-needs-repro.yml"
2121
- ".github/workflows/test-bundle.yml"
2222
- ".github/workflows/test-smokes-parallel.yml"
23+
- ".github/workflows/test-install.yml"
2324
- ".github/workflows/test-quarto-latexmk.yml"
2425
- ".github/workflows/update-test-timing.yml"
2526
pull_request:
@@ -31,6 +32,7 @@ on:
3132
- ".github/workflows/performance-check.yml"
3233
- ".github/workflows/stale-needs-repro.yml"
3334
- ".github/workflows/test-bundle.yml"
35+
- ".github/workflows/test-install.yml"
3436
- ".github/workflows/test-smokes-parallel.yml"
3537
- ".github/workflows/test-quarto-latexmk.yml"
3638
- ".github/workflows/update-test-timing.yml"

.github/workflows/test-smokes-parallel.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ on:
2929
- ".github/workflows/stale-needs-repro.yml"
3030
- ".github/workflows/test-bundle.yml"
3131
- ".github/workflows/test-ff-matrix.yml"
32+
- ".github/workflows/test-install.yml"
3233
- ".github/workflows/test-quarto-latexmk.yml"
3334
- ".github/workflows/update-test-timing.yml"
3435
push:

news/changelog-1.10.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ All changes included in 1.10:
55
- ([#14267](https://github.com/quarto-dev/quarto-cli/issues/14267)): Fix Windows paths with accented characters (e.g., `C:\Users\Sébastien\`) breaking dart-sass compilation.
66
- ([#14281](https://github.com/quarto-dev/quarto-cli/issues/14281)): Fix transient `.quarto_ipynb` files accumulating during `quarto preview` with Jupyter engine.
77
- ([#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.
8+
- ([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.
89

910
## Formats
1011

@@ -27,6 +28,10 @@ All changes included in 1.10:
2728

2829
- ([#14250](https://github.com/quarto-dev/quarto-cli/issues/14250)): Fix `quarto create` producing read-only files when Quarto is installed via system packages (e.g., `.deb`). Files copied from installed resources now have user-write permission ensured.
2930

31+
## Lua API
32+
33+
- ([#14297](https://github.com/quarto-dev/quarto-cli/pull/14297)): Fix `quarto.utils.is_empty_node()` returning inverted results for text nodes (`Str`, `Code`, `RawInline`).
34+
3035
## Other fixes and improvements
3136

3237
- ([#6651](https://github.com/quarto-dev/quarto-cli/issues/6651)): Fix dart-sass compilation failing in enterprise environments where `.bat` files are blocked by group policy.

news/changelog-1.9.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,13 @@ All changes included in 1.9:
7979
- ([#13775](https://github.com/quarto-dev/quarto-cli/issues/13775)): Fix brand fonts not being applied when using `citeproc: true` with Typst format. Format detection now properly handles Pandoc format variants like `typst-citations`.
8080
- ([#13868](https://github.com/quarto-dev/quarto-cli/issues/13868)): Add image alt text support for PDF/UA accessibility. Alt text from markdown captions and explicit `alt` attributes is now passed to Typst's `image()` function. (Temporary workaround until [jgm/pandoc#11394](https://github.com/jgm/pandoc/pull/11394) is merged.)
8181
- ([#13870](https://github.com/quarto-dev/quarto-cli/issues/13870)): Add support for `alt` attribute on cross-referenced equations for improved accessibility. (author: @mcanouil)
82+
- ([#13878](https://github.com/quarto-dev/quarto-cli/issues/13878)): Typst now uses Pandoc's skylighting for syntax highlighting by default (consistent with other formats). Use `syntax-highlighting: idiomatic` to opt-in to Typst's native syntax highlighting instead.
83+
- ([#13879](https://github.com/quarto-dev/quarto-cli/pull/13879)): Add Tufte-style margin layout for Typst using the marginalia package. Supports `.column-margin` for margin notes, figures, tables, and captions; `.column-screen` and `.column-page` for full-width content; `citation-location: margin`; `reference-location: margin` for sidenotes; `suppress-bibliography`; `cap-location: margin`, `fig-cap-location: margin`, and `tbl-cap-location: margin`; `grid` options (`margin-width`, `body-width`, `gutter-width`); and `margin-geometry` for fine-grained layout control.
8284
- ([#13917](https://github.com/quarto-dev/quarto-cli/issues/13917)): Fix brand logo paths not resolving correctly for Typst documents in project subdirectories. Brand logo paths are now converted to project-absolute paths before merging with document metadata, replacing the fragile `projectOffset()` workaround.
8385
- ([#13942](https://github.com/quarto-dev/quarto-cli/issues/13942)): Fix Typst compilation errors showing confusing internal stack traces. Users now see only the relevant Typst error message.
8486
- ([#13950](https://github.com/quarto-dev/quarto-cli/pull/13950)): Replace ctheorems with theorion package for theorem environments. Add `theorem-appearance` option to control styling: `simple` (default, classic LaTeX style), `fancy` (colored boxes with brand colors), `clouds` (rounded backgrounds), or `rainbow` (colored start border and colored title).
8587
- ([#13954](https://github.com/quarto-dev/quarto-cli/issues/13954)): Add support for Typst book projects via format extensions. Quarto now bundles the `orange-book` extension which provides a textbook-style format with chapter numbering, cross-references, and professional styling. Book projects with `format: typst` automatically use this extension.
8688
- ([#13978](https://github.com/quarto-dev/quarto-cli/pull/13978)): Keep term and description together in definition lists to avoid breaking across pages. (author: @mcanouil)
87-
- ([#13878](https://github.com/quarto-dev/quarto-cli/issues/13878)): Typst now uses Pandoc's skylighting for syntax highlighting by default (consistent with other formats). Use `syntax-highlighting: idiomatic` to opt-in to Typst's native syntax highlighting instead.
8889
- ([#14126](https://github.com/quarto-dev/quarto-cli/issues/14126)): Fix Skylighting code blocks in Typst lacking full-width background, padding, and border radius. A postprocessor patches the Pandoc-generated Skylighting function to add `width: 100%`, `inset: 8pt`, and `radius: 2pt` to the block call, matching the styling of native code blocks. Brand `monospace-block.background-color` also now correctly applies to Skylighting output. This workaround will be removed once the fix is upstreamed to Skylighting.
8990
- ([#14202](https://github.com/quarto-dev/quarto-cli/issues/14202)): Fix CSS inlining (`juice`) failing on Windows when Quarto is installed in a path with spaces (e.g., `C:\Program Files\Quarto\`).
9091

src/command/render/render-contexts.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -678,15 +678,20 @@ const readExtensionFormat = async (
678678
) => {
679679
// Determine effective extension - use default for certain project/format combinations
680680
let effectiveExtension = formatDesc.extension;
681+
let preferLocal = false;
681682

682-
// For book projects with typst format and no explicit extension,
683-
// use orange-book as the default typst book template
684683
if (
685-
!effectiveExtension &&
686684
formatDesc.baseFormat === "typst" &&
687685
project?.config?.project?.[kProjectType] === "book"
688686
) {
689-
effectiveExtension = "orange-book";
687+
if (effectiveExtension) {
688+
// User explicitly named a typst book extension (e.g. format: orange-book-typst),
689+
// prefer a locally installed copy over the built-in so customizations take effect
690+
preferLocal = true;
691+
} else {
692+
// No explicit extension - use orange-book as the default typst book template
693+
effectiveExtension = "orange-book";
694+
}
690695
}
691696

692697
// Read the format file and populate this
@@ -697,6 +702,7 @@ const readExtensionFormat = async (
697702
file,
698703
project?.config,
699704
project?.dir,
705+
preferLocal,
700706
);
701707

702708
// Read the yaml file and resolve / bucketize

src/core/platform.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ export function isWSL() {
1414
return !!Deno.env.get("WSL_DISTRO_NAME");
1515
}
1616

17+
// Test override for isRStudio — avoids Deno.env.set() race conditions
18+
// in parallel tests. See quarto-dev/quarto-cli#14218 and PR #12621.
19+
let _isRStudioOverride: boolean | undefined;
20+
export function _setIsRStudioForTest(value: boolean | undefined) {
21+
_isRStudioOverride = value;
22+
}
23+
1724
export function isRStudio() {
25+
if (_isRStudioOverride !== undefined) return _isRStudioOverride;
1826
return !!Deno.env.get("RSTUDIO");
1927
}
2028

src/extension/extension.ts

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,15 @@ export function createExtensionContext(): ExtensionContext {
119119
input: string,
120120
config?: ProjectConfig,
121121
projectDir?: string,
122+
preferLocal = false,
122123
): Promise<Extension | undefined> => {
123124
// Load the extension and resolve any paths
124-
const unresolved = await loadExtension(name, input, projectDir);
125+
const unresolved = await loadExtension(
126+
name,
127+
input,
128+
projectDir,
129+
preferLocal,
130+
);
125131
return resolveExtensionPaths(unresolved, input, config);
126132
};
127133

@@ -342,9 +348,15 @@ const loadExtension = async (
342348
extension: string,
343349
input: string,
344350
projectDir?: string,
351+
preferLocal = false,
345352
): Promise<Extension> => {
346353
const extensionId = toExtensionId(extension);
347-
const extensionPath = discoverExtensionPath(input, extensionId, projectDir);
354+
const extensionPath = discoverExtensionPath(
355+
input,
356+
extensionId,
357+
projectDir,
358+
preferLocal,
359+
);
348360

349361
if (extensionPath) {
350362
// Find the metadata file, if any
@@ -585,8 +597,9 @@ export function discoverExtensionPath(
585597
input: string,
586598
extensionId: ExtensionId,
587599
projectDir?: string,
600+
preferLocal = false,
588601
) {
589-
const extensionDirGlobs = [];
602+
const extensionDirGlobs: string[] = [];
590603
if (extensionId.organization) {
591604
// If there is an organization, always match that exactly
592605
extensionDirGlobs.push(
@@ -619,6 +632,41 @@ export function discoverExtensionPath(
619632
}
620633
};
621634

635+
const findLocalExtensionDir = () => {
636+
const sourceDir = Deno.statSync(input).isDirectory ? input : dirname(input);
637+
const sourceDirAbs = normalizePath(sourceDir);
638+
639+
if (projectDir && isSubdir(projectDir, sourceDirAbs)) {
640+
let extensionDir;
641+
let currentDir = normalize(sourceDirAbs);
642+
const projDir = normalize(projectDir);
643+
while (!extensionDir) {
644+
extensionDir = findExtensionDir(
645+
join(currentDir, kExtensionDir),
646+
extensionDirGlobs,
647+
);
648+
if (currentDir == projDir) {
649+
break;
650+
}
651+
currentDir = dirname(currentDir);
652+
}
653+
return extensionDir;
654+
} else {
655+
return findExtensionDir(
656+
join(sourceDirAbs, kExtensionDir),
657+
extensionDirGlobs,
658+
);
659+
}
660+
};
661+
662+
// When preferLocal is set, check local project extensions first
663+
if (preferLocal) {
664+
const localDir = findLocalExtensionDir();
665+
if (localDir) {
666+
return localDir;
667+
}
668+
}
669+
622670
// check for built-in
623671
const builtinExtensionDir = findExtensionDir(
624672
builtinExtensions(),
@@ -646,30 +694,9 @@ export function discoverExtensionPath(
646694
}
647695
}
648696

649-
// Start in the source directory
650-
const sourceDir = Deno.statSync(input).isDirectory ? input : dirname(input);
651-
const sourceDirAbs = normalizePath(sourceDir);
652-
653-
if (projectDir && isSubdir(projectDir, sourceDirAbs)) {
654-
let extensionDir;
655-
let currentDir = normalize(sourceDirAbs);
656-
const projDir = normalize(projectDir);
657-
while (!extensionDir) {
658-
extensionDir = findExtensionDir(
659-
join(currentDir, kExtensionDir),
660-
extensionDirGlobs,
661-
);
662-
if (currentDir == projDir) {
663-
break;
664-
}
665-
currentDir = dirname(currentDir);
666-
}
667-
return extensionDir;
668-
} else {
669-
return findExtensionDir(
670-
join(sourceDirAbs, kExtensionDir),
671-
extensionDirGlobs,
672-
);
697+
// Check local project extensions (when not already checked via preferLocal)
698+
if (!preferLocal) {
699+
return findLocalExtensionDir();
673700
}
674701
}
675702

src/extension/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export interface ExtensionContext {
7171
input: string,
7272
config?: ProjectConfig,
7373
projectDir?: string,
74+
preferLocal?: boolean,
7475
): Promise<Extension | undefined>;
7576
find(
7677
name: string,

src/inspect/inspect.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import {
4949
import { validateDocumentFromSource } from "../core/schema/validate-document.ts";
5050
import { error } from "../deno_ral/log.ts";
5151
import { ProjectContext } from "../project/types.ts";
52+
import { isRStudio } from "../core/platform.ts";
5253

5354
export function isProjectConfig(
5455
config: InspectedConfig,
@@ -238,7 +239,9 @@ const inspectDocumentConfig = async (path: string) => {
238239
};
239240

240241
// if there is a project then add it
241-
if (context?.config) {
242+
// Suppress project for standalone files in RStudio: current releases
243+
// assume project.dir implies _quarto.yml exists (rstudio/rstudio#17333)
244+
if (context?.config && !(context.isSingleFile && isRStudio())) {
242245
config.project = await inspectProjectConfig(context);
243246
}
244247
return config;

src/resources/pandoc/datadir/_utils.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ local function is_empty_node (node)
592592
return not next(node.caption)
593593
elseif node.text then
594594
-- looks like a code node or text node
595-
return node.text ~= ''
595+
return node.text == ''
596596
else
597597
-- Not sure what this is, but it's probably not empty.
598598
return false

0 commit comments

Comments
 (0)