From ba04fc8181a73a616e53364c33855d27f3ec240d Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 6 Jan 2026 13:58:39 +0100 Subject: [PATCH 1/3] use npm: prefix in import map for lodash (#13850) * dev: use npm: prefix in import map for lodash as skypack CDN is failing with error 500 * fix: add type annotations for lodash npm: import compatibility The npm: prefix for lodash doesn't preserve generic type inference, causing TypeScript to infer `any` for callback parameters. Added explicit type annotations and type assertions where needed. (cherry picked from commit d341f2a70fe365b7ca66e4cbd179ec07dc892722) --- src/command/render/cleanup.ts | 3 +-- src/command/render/project.ts | 2 +- src/core/jupyter/venv.ts | 8 ++++---- src/format/html/format-html-notebook-preview.ts | 13 ++++++++++--- src/format/html/format-html-notebook.ts | 2 +- src/import_map.json | 4 ++-- src/project/types/book/book-bibliography.ts | 2 +- src/project/types/manuscript/manuscript-meca.ts | 2 +- .../types/website/listing/website-listing.ts | 2 +- src/project/types/website/website-navigation.ts | 2 +- 10 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/command/render/cleanup.ts b/src/command/render/cleanup.ts index d2fdc1c8547..40390e594b7 100644 --- a/src/command/render/cleanup.ts +++ b/src/command/render/cleanup.ts @@ -13,7 +13,6 @@ import { normalizePath, removeIfEmptyDir, removeIfExists, - safeRemoveSync, } from "../../core/path.ts"; import { figuresDir, inputFilesDir } from "../../core/render.ts"; @@ -90,7 +89,7 @@ export function renderCleanup( } // clean supporting - ld.uniq(supporting).forEach((path) => { + ld.uniq(supporting).forEach((path: string) => { if (existsSync(path)) { safeRemoveDirSync(path, project.dir); } diff --git a/src/command/render/project.ts b/src/command/render/project.ts index 6156e9b8508..2c5669e668e 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -599,7 +599,7 @@ export async function renderProject( // as an example case) const uniqOps = ld.uniqBy(fileOperations, (op: FileOperation) => { return op.key; - }); + }) as FileOperation[]; const sortedOperations = uniqOps.sort((a, b) => { if (a.src === b.src) { diff --git a/src/core/jupyter/venv.ts b/src/core/jupyter/venv.ts index b250010179b..6c98d6eb4a7 100644 --- a/src/core/jupyter/venv.ts +++ b/src/core/jupyter/venv.ts @@ -35,10 +35,10 @@ export async function jupyterCreateVenv(dir: string, packages?: string[]) { kEnvDir, isWindows ? "Scripts\\pip.exe" : "bin/pip3", ); - packages = ld.uniq(["jupyter"].concat(packages || [])); + const pkgList = ld.uniq(["jupyter"].concat(packages || [])) as string[]; const installResult = await execProcess({ cmd: pip3, - args: ["install", ...packages], + args: ["install", ...pkgList], cwd: dir, }); if (!installResult.success) { @@ -55,10 +55,10 @@ export async function jupyterCreateCondaenv(dir: string, packages?: string[]) { const conda = await which("conda"); if (conda) { info(`Using conda at ${conda}`); - packages = ld.uniq(["jupyter"].concat(packages || [])); + const pkgList = ld.uniq(["jupyter"].concat(packages || [])) as string[]; const installResult = await execProcess({ cmd: "conda", - args: ["create", "--yes", "--prefix", "env", ...packages], + args: ["create", "--yes", "--prefix", "env", ...pkgList], cwd: dir, }); if (!installResult.success) { diff --git a/src/format/html/format-html-notebook-preview.ts b/src/format/html/format-html-notebook-preview.ts index 02518739c88..ea8363887fd 100644 --- a/src/format/html/format-html-notebook-preview.ts +++ b/src/format/html/format-html-notebook-preview.ts @@ -14,7 +14,13 @@ import { Format, NotebookPreviewDescriptor } from "../../config/types.ts"; import { RenderServices } from "../../command/render/types.ts"; -import { basename, dirname, isAbsolute, join, relative } from "../../deno_ral/path.ts"; +import { + basename, + dirname, + isAbsolute, + join, + relative, +} from "../../deno_ral/path.ts"; import { pathWithForwardSlashes } from "../../core/path.ts"; import { ProjectContext } from "../../project/types.ts"; import { projectIsBook } from "../../project/project-shared.ts"; @@ -102,7 +108,7 @@ export const notebookPreviewer = ( .metadata[kNotebookPreviewOptions] as NotebookPreviewOptions; const notebookPaths = previewQueue.map((work) => (work.nbPath)); - const uniquePaths = ld.uniq(notebookPaths); + const uniquePaths = ld.uniq(notebookPaths) as string[]; const toRenderPaths = uniquePaths.filter((nbPath) => { return services.notebook.get(nbPath, project) === undefined; }); @@ -252,7 +258,8 @@ export const notebookPreviewer = ( // to form links to this notebook const nbPreview = { title: resolvedTitle, - href: descriptor?.url || relative(inputDir, renderedNotebook[kHtmlPreview].hrefPath), + href: descriptor?.url || + relative(inputDir, renderedNotebook[kHtmlPreview].hrefPath), supporting, resources, order: work.order, diff --git a/src/format/html/format-html-notebook.ts b/src/format/html/format-html-notebook.ts index 63d0d043ca3..87ffcee54f6 100644 --- a/src/format/html/format-html-notebook.ts +++ b/src/format/html/format-html-notebook.ts @@ -254,7 +254,7 @@ export async function emplaceNotebookPreviews( (nbPath: { href: string; title?: string }) => { return nbPath.href; }, - ).forEach((nbPath) => { + ).forEach((nbPath: NotebookPreview) => { const li = doc.createElement("li"); const link = doc.createElement("a"); diff --git a/src/import_map.json b/src/import_map.json index 23c5fb371b2..4e10858ca63 100644 --- a/src/import_map.json +++ b/src/import_map.json @@ -15,7 +15,7 @@ "uuid/": "jsr:/@std/uuid@1.0.6/", "https://deno.land/std@0.91.0/path/mod.ts": "jsr:/@std/path@1.0.8", "https://deno.land/std@0.91.0/path/": "jsr:/@std/path@1.0.8/", - + "testing/": "jsr:/@std/testing@0.224.0/", "flags": "jsr:/@std/flags@0.224.0", "datetime/": "jsr:/@std/datetime@0.225.4/", @@ -41,7 +41,7 @@ "dayjs/": "https://cdn.skypack.dev/dayjs@1.8.21/", "moment-guess": "https://cdn.skypack.dev/moment-guess@1.2.4", "ansi_up": "https://cdn.skypack.dev/ansi_up@v6.0.2", - "lodash/": "https://cdn.skypack.dev/lodash@4.17.21/", + "lodash/": "npm:/lodash@4.17.21/", "acorn-class-fields": "https://cdn.skypack.dev/acorn-class-fields@1.0.0", "acorn/acorn": "https://cdn.skypack.dev/acorn@8.4.0", "acorn/walk": "https://cdn.skypack.dev/acorn-walk@8.2.0", diff --git a/src/project/types/book/book-bibliography.ts b/src/project/types/book/book-bibliography.ts index 9bc851f4e03..780cd154e8b 100644 --- a/src/project/types/book/book-bibliography.ts +++ b/src/project/types/book/book-bibliography.ts @@ -269,7 +269,7 @@ export async function generateBibliography( // make the aggregated bibliography const yaml: Metadata = { [kBibliography]: biblioPaths.map(pathWithForwardSlashes), - [kNoCite]: ld.uniq(citeIds).map((id) => "@" + id).join(", "), + [kNoCite]: ld.uniq(citeIds).map((id: string) => "@" + id).join(", "), }; if (csl) { yaml[kCsl] = isAbsolute(csl) diff --git a/src/project/types/manuscript/manuscript-meca.ts b/src/project/types/manuscript/manuscript-meca.ts index 8492c47fc6b..f67fb7b34f0 100644 --- a/src/project/types/manuscript/manuscript-meca.ts +++ b/src/project/types/manuscript/manuscript-meca.ts @@ -264,7 +264,7 @@ export const createMecaBundle = async ( const manuscriptResources: MecaItem[] = []; const manuscriptZipFiles: string[] = []; if (jatsArticle.supporting) { - ld.uniq(jatsArticle.supporting).forEach((file) => { + ld.uniq(jatsArticle.supporting).forEach((file: string) => { const relPath = isAbsolute(file) ? relative(outputDir, file) : file; const absPath = isAbsolute(file) ? file : join(outputDir, file); const workingPath = toWorkingDir(absPath, relPath, false); diff --git a/src/project/types/website/listing/website-listing.ts b/src/project/types/website/listing/website-listing.ts index f202e6897e5..3f6e7a1e34a 100644 --- a/src/project/types/website/listing/website-listing.ts +++ b/src/project/types/website/listing/website-listing.ts @@ -110,7 +110,7 @@ export function listingSupplementalFiles( return !inputs.find((inp) => { return inp.path === file; }) && existsSync(file); - })); + })) as string[]; const onRenderComplete = async ( project: ProjectContext, diff --git a/src/project/types/website/website-navigation.ts b/src/project/types/website/website-navigation.ts index 2cc30015166..30ed38da25f 100644 --- a/src/project/types/website/website-navigation.ts +++ b/src/project/types/website/website-navigation.ts @@ -1204,7 +1204,7 @@ function nextAndPrevious( (sidebarItem: SidebarItem) => { return sidebarItem.href || Math.random().toString(); }, - ); + ) as SidebarItem[]; const index = sidebarItemsUniq.findIndex((item) => item.href === href); const nextPage = index > -1 && index < sidebarItemsUniq.length - 1 && From 64920d8dd93a044810e275c5a2af2ecfa78d6202 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Fri, 5 Dec 2025 13:49:20 +0100 Subject: [PATCH 2/3] Render this test without koma script This avoid failing test while still testing the feature (cherry picked from commit 98a0a0fded90c4ad190c006c15945bed6226e912) --- .../docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es.qmd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es.qmd b/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es.qmd index ce1b6b66703..2583442b381 100644 --- a/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es.qmd +++ b/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es.qmd @@ -1,5 +1,7 @@ --- -format: pdf +format: + pdf: + documentclass: article lang: es _quarto: tests: From 2c06c5bd2c55814a8ccb345d85f41a717d3035d4 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 10 Nov 2025 18:14:36 +0100 Subject: [PATCH 3/3] test - temporary opt out some article layout test due to latex update issues Something in recent LaTeX updates appears to have broken some of the article layout tests. Rendering them make them hangs. To temporarily opt out these tests until we can investigate and fix the underlying issue, https://github.com/quarto-dev/quarto-cli/issues/13663 (cherry picked from commit dd8d1417a78804fe9d6fa520f1a68c0cf751937f) --- tests/docs/smoke-all/article-layout/tables/tufte.qmd | 2 ++ tests/smoke/render/render-page-layout.test.ts | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/docs/smoke-all/article-layout/tables/tufte.qmd b/tests/docs/smoke-all/article-layout/tables/tufte.qmd index d145ae41a6b..6d17a76f1e5 100644 --- a/tests/docs/smoke-all/article-layout/tables/tufte.qmd +++ b/tests/docs/smoke-all/article-layout/tables/tufte.qmd @@ -14,6 +14,8 @@ execute: reference-location: margin citation-location: margin bibliography: skeleton.bib +_quarto: + tests-on-ci: false --- # Introduction diff --git a/tests/smoke/render/render-page-layout.test.ts b/tests/smoke/render/render-page-layout.test.ts index 0ccb3ba52a7..ff41e402a05 100644 --- a/tests/smoke/render/render-page-layout.test.ts +++ b/tests/smoke/render/render-page-layout.test.ts @@ -9,5 +9,7 @@ import { docs } from "../../utils.ts"; import { testRender } from "./render.ts"; // Simple rendering tests -testRender(docs("page-layout/tufte-pdf.qmd"), "pdf", true); +// TODO: 10/11/2025 - SKIPPED FOR NOW DUE TO LATEX UPDATE PROBLEMS +// See https://github.com/quarto-dev/quarto-cli/issues/13647 +// testRender(docs("page-layout/tufte-pdf.qmd"), "pdf", true); testRender(docs("page-layout/tufte-html.qmd"), "html", false);