Skip to content

Commit 20d5537

Browse files
authored
Merge branch 'main' into bugfix/issue-11549
2 parents c61b247 + 83a3b5a commit 20d5537

File tree

84 files changed

+2309
-1862
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2309
-1862
lines changed

.github/workflows/test-smokes.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ jobs:
130130
renv::restore()
131131
# Install dev versions for our testing
132132
# Use r-universe to avoid github api calls
133-
try(install.packages('knitr', repos = 'https://yihui.r-universe.dev'))
134-
try(install.packages('rmarkdown', repos = 'https://rstudio.r-universe.dev'))
133+
try(install.packages('rmarkdown', repos = c('https://rstudio.r-universe.dev', getOption('repos'))))
134+
try(install.packages('knitr', repos = c('https://yihui.r-universe.dev', getOption('repos'))))
135135
if ('${{ inputs.extra-r-packages }}' != '') {
136136
cat(sprintf("::notice::Running with the following extra R packages for pak: %s\n", "${{ inputs.extra-r-packages }}"))
137137
renv::install(strsplit("${{ inputs.extra-r-packages }}", split = ",")[[1]])
@@ -143,7 +143,7 @@ jobs:
143143
- name: Install uv for Python
144144
uses: astral-sh/setup-uv@v3
145145
with:
146-
version: "0.4.30"
146+
version: "0.5.6"
147147
enable-cache: true
148148
cache-dependency-glob: "tests/uv.lock"
149149

@@ -183,7 +183,7 @@ jobs:
183183
export JUPYTER=$(find $(dirname $(uv run --frozen which jupyter))/ -type f -name "jupyter.exe" -o -name "jupyter")
184184
uv run --frozen julia --color=yes --project=. -e "import Pkg; Pkg.instantiate(); Pkg.build(\"IJulia\"); Pkg.precompile()"
185185
echo "Julia Jupyter:"
186-
julia --project=. -e "import IJulia;println(IJulia.JUPYTER);println(IJulia.find_jupyter_subcommand(\"notebook\"))"
186+
uv run julia --project=. -e "import IJulia;println(IJulia.JUPYTER);println(IJulia.find_jupyter_subcommand(\"notebook\"))"
187187
188188
- name: Setup timing file for timed test
189189
if: ${{ matrix.time-test == true }}

news/changelog-1.7.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,32 @@ All changes included in 1.7:
22

33
## Regression fixes
44

5-
- ([#11532](https://github.com/quarto-dev/quarto-cli/issues/11532)): Fix regression for [#660](https://github.com/quarto-dev/quarto-cli/issues/660), which causes files to have incorrect permissions when Quarto is installed in a location not writable by the current user.
65
- ([#11509](https://github.com/quarto-dev/quarto-cli/issues/11509)): Fix link-decoration regression in HTML formats.
6+
- ([#11532](https://github.com/quarto-dev/quarto-cli/issues/11532)): Fix regression for [#660](https://github.com/quarto-dev/quarto-cli/issues/660), which causes files to have incorrect permissions when Quarto is installed in a location not writable by the current user.
77
- ([#11549](https://github.com/quarto-dev/quarto-cli/issues/11549)): Fix regression in rendering `dashboard` tabsets into cards without titles.
8+
- ([#11580](https://github.com/quarto-dev/quarto-cli/issues/11580)): Fix regression with documents containing `categories` fields that are not strings.
9+
10+
## YAML validation
11+
12+
- ([#11654](https://github.com/quarto-dev/quarto-cli/issues/11654)): Allow `page-inset` as value in `column` key for code cells.
13+
14+
## `quarto check`
15+
16+
- ([#11608](https://github.com/quarto-dev/quarto-cli/pull/11608)): Do not issue error message when calling `quarto check info`.
17+
18+
## `typst` Format
19+
20+
- ([#11578](https://github.com/quarto-dev/quarto-cli/issues/11578)): Typst column layout widths use fractional `fr` units instead of percent `%` units for unitless and default widths in order to fill the enclosing block and not spill outside it.
21+
22+
## Lua Filters and extensions
23+
24+
- ([#11526](https://github.com/quarto-dev/quarto-cli/pull/11526)):
25+
General improvements to the style and robustness of Quarto's Lua code.
26+
This also provides a new public function `quarto.utils.is_empty_node`
27+
that allows to check whether a node is empty, i.e., whether it's an
28+
empty list, has no child nodes, and contains no text.
29+
30+
## Other Fixes and Improvements
31+
32+
- ([#11441](https://github.com/quarto-dev/quarto-cli/issues/11441)): Don't add newlines around shortcodes during processing.
33+
- ([#11643](https://github.com/quarto-dev/quarto-cli/issues/11643)): Improve highlighting of nested code block inside markdown code block, i.e. using ` ```{{python}} ` or ` ```python ` inside ` ````markdown` fenced code block.

package/src/util/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export async function download(src: string, dest: string): Promise<void> {
2525

2626
const file = await Deno.create(dest);
2727
await writeAll(file, contents);
28-
Deno.close(file.rid);
28+
file.close();
2929
}
3030

3131
export async function unzip(

src/command/check/check.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,20 @@ import { notebookContext } from "../../render/notebook/notebook-context.ts";
4747
import { typstBinaryPath } from "../../core/typst.ts";
4848
import { quartoCacheDir } from "../../core/appdirs.ts";
4949
import { isWindows } from "../../deno_ral/platform.ts";
50+
import { makeStringEnumTypeEnforcer } from "../../typing/dynamic.ts";
5051

51-
const kIndent = " ";
52+
export const kTargets = [
53+
"install",
54+
"info",
55+
"jupyter",
56+
"knitr",
57+
"versions",
58+
"all",
59+
] as const;
60+
export type Target = typeof kTargets[number];
61+
export const enforceTargetType = makeStringEnumTypeEnforcer(...kTargets);
5262

53-
export type Target =
54-
| "install"
55-
| "jupyter"
56-
| "knitr"
57-
| "versions"
58-
| "info"
59-
| "all";
63+
const kIndent = " ";
6064

6165
export async function check(target: Target): Promise<void> {
6266
const services = renderServices(notebookContext());
@@ -82,7 +86,9 @@ export async function check(target: Target): Promise<void> {
8286
}
8387
}
8488

85-
// Currently this doesn't check anything, but
89+
// Currently this doesn't check anything
90+
// but it's a placeholder for future checks
91+
// and the message is useful for troubleshooting
8692
async function checkInfo(_services: RenderServices) {
8793
const cacheDir = quartoCacheDir();
8894
completeMessage("Checking environment information...");

src/command/check/cmd.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,8 @@
44
* Copyright (C) 2021-2022 Posit Software, PBC
55
*/
66

7-
import { error } from "../../deno_ral/log.ts";
8-
97
import { Command } from "cliffy/command/mod.ts";
10-
import { check, Target } from "./check.ts";
11-
12-
const kTargets = ["install", "jupyter", "knitr", "versions", "all"];
8+
import { check, enforceTargetType } from "./check.ts";
139

1410
export const checkCommand = new Command()
1511
.name("check")
@@ -22,13 +18,7 @@ export const checkCommand = new Command()
2218
.example("Check Jupyter engine", "quarto check jupyter")
2319
.example("Check Knitr engine", "quarto check knitr")
2420
.example("Check installation and all engines", "quarto check all")
25-
.action(async (_options: unknown, target?: string) => {
26-
target = target || "all";
27-
if (!kTargets.includes(target)) {
28-
error(
29-
"Invalid target '" + target + "' (valid targets are " +
30-
kTargets.join(", ") + ").",
31-
);
32-
}
33-
await check(target as Target);
21+
.action(async (_options: unknown, targetStr?: string) => {
22+
targetStr = targetStr || "all";
23+
await check(enforceTargetType(targetStr));
3424
});

src/command/create/editor.ts

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ import {
1616
import { basename, dirname, join } from "../../deno_ral/path.ts";
1717
import { existsSync } from "../../deno_ral/fs.ts";
1818
import { isMac, isWindows } from "../../deno_ral/platform.ts";
19+
import {
20+
enforcer,
21+
makeStringEnumTypeFunctions,
22+
objectPredicate,
23+
stringTypePredicate,
24+
} from "../../typing/dynamic.ts";
1925

2026
export interface Editor {
2127
// A short, command line friendly id
@@ -77,11 +83,14 @@ interface EditorInfo {
7783
open: (path: string, createResult: CreateResult) => () => Promise<void>;
7884
}
7985

80-
interface ScanAction {
81-
action: "path" | "which" | "env";
86+
const scanActionActions = ["path", "which", "env"] as const;
87+
type ScanActionAction = typeof scanActionActions[number];
88+
89+
type ScanAction = {
90+
action: ScanActionAction;
8291
arg: string;
8392
filter?: (path: string) => string;
84-
}
93+
};
8594

8695
function vscodeEditorInfo(): EditorInfo {
8796
const editorInfo: EditorInfo = {
@@ -110,29 +119,26 @@ function vscodeEditorInfo(): EditorInfo {
110119
action: "which",
111120
arg: "code.exe",
112121
});
113-
const pathActions = windowsAppPaths("Microsoft VS Code", "code.exe").map(
114-
(path) => {
115-
return {
116-
action: "path",
117-
arg: path,
118-
} as ScanAction;
119-
},
120-
);
122+
const pathActions: ScanAction[] = windowsAppPaths(
123+
"Microsoft VS Code",
124+
"code.exe",
125+
).map((path) => ({
126+
action: "path",
127+
arg: path,
128+
}));
121129
editorInfo.actions.push(...pathActions);
122130
} else if (isMac) {
123131
editorInfo.actions.push({
124132
action: "which",
125133
arg: "code",
126134
});
127135

128-
const pathActions = macosAppPaths(
136+
const pathActions: ScanAction[] = macosAppPaths(
129137
"Visual Studio Code.app/Contents/Resources/app/bin/code",
130-
).map((path) => {
131-
return {
132-
action: "path",
133-
arg: path,
134-
} as ScanAction;
135-
});
138+
).map((path) => ({
139+
action: "path",
140+
arg: path,
141+
}));
136142
editorInfo.actions.push(...pathActions);
137143
} else {
138144
editorInfo.actions.push({
@@ -174,13 +180,14 @@ function positronEditorInfo(): EditorInfo {
174180
action: "which",
175181
arg: "Positron.exe",
176182
});
177-
const pathActions = windowsAppPaths("Positron", "Positron.exe").map(
178-
(path) => {
179-
return {
180-
action: "path",
181-
arg: path,
182-
} as ScanAction;
183-
},
183+
const pathActions: ScanAction[] = windowsAppPaths(
184+
"Positron",
185+
"Positron.exe",
186+
).map(
187+
(path) => ({
188+
action: "path",
189+
arg: path,
190+
}),
184191
);
185192
editorInfo.actions.push(...pathActions);
186193
} else if (isMac) {
@@ -189,13 +196,13 @@ function positronEditorInfo(): EditorInfo {
189196
arg: "positron",
190197
});
191198

192-
const pathActions = macosAppPaths(
199+
const pathActions: ScanAction[] = macosAppPaths(
193200
"Positron.app/Contents/Resources/app/bin/code",
194201
).map((path) => {
195202
return {
196203
action: "path",
197204
arg: path,
198-
} as ScanAction;
205+
};
199206
});
200207
editorInfo.actions.push(...pathActions);
201208
} else {
@@ -249,22 +256,19 @@ function rstudioEditorInfo(): EditorInfo {
249256
},
250257
});
251258

252-
const paths = windowsAppPaths(join("RStudio", "bin"), rstudioExe).map(
253-
(path) => {
254-
return {
255-
action: "path",
256-
arg: path,
257-
} as ScanAction;
258-
},
259-
);
259+
const paths: ScanAction[] = windowsAppPaths(
260+
join("RStudio", "bin"),
261+
rstudioExe,
262+
).map((path) => ({
263+
action: "path",
264+
arg: path,
265+
}));
260266
editorInfo.actions.push(...paths);
261267
} else if (isMac) {
262-
const paths = macosAppPaths("RStudio.app").map((path) => {
263-
return {
264-
action: "path",
265-
arg: path,
266-
} as ScanAction;
267-
});
268+
const paths: ScanAction[] = macosAppPaths("RStudio.app").map((path) => ({
269+
action: "path",
270+
arg: path,
271+
}));
268272
editorInfo.actions.push(...paths);
269273
} else {
270274
editorInfo.actions.push({

src/command/render/pandoc.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ import {
201201
MarkdownPipelineHandler,
202202
} from "../../core/markdown-pipeline.ts";
203203
import { getEnv } from "../../../package/src/util/utils.ts";
204-
import { canonicalizeTitlePostprocessor } from "../../format/html/format-html-title.ts";
205204
import {
206205
BrandFontBunny,
207206
BrandFontFile,
@@ -439,11 +438,6 @@ export async function runPandoc(
439438
// record postprocessors
440439
postprocessors.push(...(extras.postprocessors || []));
441440

442-
// Fix H1 title inconsistency
443-
if (isHtmlFileOutput(options.format.pandoc)) {
444-
htmlPostprocessors.push(canonicalizeTitlePostprocessor);
445-
}
446-
447441
// add a keep-source post processor if we need one
448442
if (
449443
options.format?.render[kKeepSource] || formatHasCodeTools(options.format)

src/core/console.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ export function writeFileToStdout(file: string) {
174174
const df = Deno.openSync(file, { read: true });
175175
const contents = readAllSync(df);
176176
writeAllSync(Deno.stdout, contents);
177-
Deno.close(df.rid);
177+
df.close();
178178
}
179179

180180
export function clearLine() {

src/core/handlers/base.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,7 @@ export async function expandIncludes(
405405
const newCells: MappedString[] = [];
406406
for (let i = 0; i < mdCells.length; ++i) {
407407
const cell = mdCells[i];
408-
newCells.push(
409-
i === 0 ? cell.sourceVerbatim : mappedConcat(["\n", cell.sourceVerbatim]),
410-
);
408+
newCells.push(cell.sourceVerbatim);
411409
}
412410

413411
await processMarkdownIncludes(newCells, options, filename);
@@ -437,9 +435,7 @@ export async function handleLanguageCells(
437435

438436
for (let i = 0; i < mdCells.length; ++i) {
439437
const cell = mdCells[i];
440-
newCells.push(
441-
i === 0 ? cell.sourceVerbatim : mappedConcat(["\n", cell.sourceVerbatim]),
442-
);
438+
newCells.push(cell.sourceVerbatim);
443439
if (
444440
cell.cell_type === "raw" ||
445441
cell.cell_type === "markdown"
@@ -483,7 +479,6 @@ export async function handleLanguageCells(
483479
(innerLanguageHandler.stage !== "any" &&
484480
innerLanguageHandler.stage !== options.stage)
485481
) { // we're in the wrong stage, so we don't actually do anything
486-
newCells[cell.index] = mappedConcat([newCells[cell.index], "\n"]);
487482
continue;
488483
}
489484
if (
@@ -492,7 +487,6 @@ export async function handleLanguageCells(
492487
) {
493488
// if no handler is present (or a directive was included for something
494489
// that responds to cells instead), we're a no-op
495-
newCells[cell.index] = mappedConcat([newCells[cell.index], "\n"]);
496490
continue;
497491
}
498492
if (innerLanguageHandler.directive === undefined) {

0 commit comments

Comments
 (0)