Skip to content

Commit ef3cc62

Browse files
committed
Merge branch 'main' into bugfix/issue-11596
2 parents 5f071f2 + 13b55fc commit ef3cc62

File tree

37 files changed

+1415
-1190
lines changed

37 files changed

+1415
-1190
lines changed

.github/workflows/test-smokes.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

news/changelog-1.7.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,18 @@ 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.
7+
- ([#11580](https://github.com/quarto-dev/quarto-cli/issues/11580)): Fix regression with documents containing `categories` fields that are not strings.
8+
9+
## `quarto check`
10+
11+
- ([#11608](https://github.com/quarto-dev/quarto-cli/pull/11608)): Do not issue error message when calling `quarto check info`.
12+
13+
## Lua Filters and extensions
14+
15+
- ([#11526](https://github.com/quarto-dev/quarto-cli/pull/11526)):
16+
General improvements to the style and robustness of Quarto's Lua code.
17+
This also provides a new public function `quarto.utils.is_empty_node`
18+
that allows to check whether a node is empty, i.e., whether it's an
19+
empty list, has no child nodes, and contains no text.

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/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/lib/error.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
* Copyright (C) 2020-2022 Posit Software, PBC
66
*/
77

8+
export class DynamicTypeCheckError extends Error {
9+
constructor(
10+
message: string,
11+
printName = true,
12+
printStack = true,
13+
) {
14+
super(message);
15+
this.name = "Dynamic Type-Checking Error";
16+
this.printName = printName;
17+
this.printStack = printStack;
18+
}
19+
20+
public readonly printName: boolean;
21+
public readonly printStack: boolean;
22+
}
23+
824
export class InternalError extends Error {
925
constructor(
1026
message: string,

src/core/performance/metrics.ts

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -41,37 +41,4 @@ export function reportPeformanceMetrics() {
4141
console.log("Performance metrics");
4242
console.log("Quarto:");
4343
console.log(JSON.stringify(quartoPerformanceMetrics(), null, 2));
44-
console.log();
45-
// denoMetrics is some kind of fancy object that doesn't respond
46-
// to a bunch of the normal methods. So we have to do this
47-
// the JSON-round-trip way.
48-
console.log("Deno:");
49-
const denoMetrics = JSON.parse(JSON.stringify(Deno.metrics() as any));
50-
denoMetrics.ops = Object.fromEntries(
51-
Object.entries(denoMetrics.ops).map(
52-
([key, opMetrics]: any) => {
53-
for (const key of Object.keys(opMetrics)) {
54-
if (opMetrics[key] === 0) {
55-
delete opMetrics[key];
56-
}
57-
}
58-
return [key, opMetrics];
59-
},
60-
).filter(([_key, opMetrics]: any) => Object.keys(opMetrics).length > 0)
61-
.map(([key, opMetrics]: any) => {
62-
if (
63-
(opMetrics.opsDispatched === opMetrics.opsDispatchedSync &&
64-
opMetrics.opsDispatched === opMetrics.opsCompleted &&
65-
opMetrics.opsDispatched === opMetrics.opsCompletedSync) ||
66-
(opMetrics.opsDispatched === opMetrics.opsDispatchedAsync &&
67-
opMetrics.opsDispatched === opMetrics.opsCompleted &&
68-
opMetrics.opsDispatched === opMetrics.opsCompletedAsync)
69-
) {
70-
return [key, opMetrics.opsDispatched];
71-
} else {
72-
return [key, opMetrics];
73-
}
74-
}),
75-
);
76-
console.log(JSON.stringify(denoMetrics, null, 2));
7744
}

src/core/platform.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export function jupyterHubServicePrefix() {
8787
}
8888

8989
export function isInteractiveTerminal() {
90-
return Deno.isatty(Deno.stderr.rid);
90+
return Deno.stderr.isTerminal();
9191
}
9292

9393
export function isInteractiveSession() {

0 commit comments

Comments
 (0)