diff --git a/news/changelog-1.7.md b/news/changelog-1.7.md index 4394506da36..7ae57de4d9a 100644 --- a/news/changelog-1.7.md +++ b/news/changelog-1.7.md @@ -68,3 +68,4 @@ All changes included in 1.7: - ([#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. - ([fb38eb5](https://github.com/quarto-dev/quarto-cli/commit/fb38eb56c11e09f44cef58fd3b697ff24bb5a3f3)) Use the `latest` parser for Acorn when analyzing JS code imported from OJS blocks. - ([#10532](https://github.com/quarto-dev/quarto-cli/issues/10532)): Quarto changed default of `--headless=old` to `--headless` as [Chrome 132 has removed old headless mode](https://developer.chrome.com/blog/removing-headless-old-from-chrome) and only support new mode. For using old mode, `QUARTO_CHROMIUM` could be set to a [new `chrome-headless-shell` binary](https://developer.chrome.com/blog/chrome-headless-shell) or too an older chrome version (between 128 and 132) and `QUARTO_CHROMIUM_HEADLESS_MODE` set to `old` for using old headless mode with that compatabitle version. +- ([#10961](https://github.com/quarto-dev/quarto-cli/issues/10961)): Add more information on which Chrome Headless will be used in `quarto check install`. This is helpful to help debug mermaid issues. diff --git a/src/command/check/check.ts b/src/command/check/check.ts index be8419ab422..7d96933097c 100644 --- a/src/command/check/check.ts +++ b/src/command/check/check.ts @@ -48,6 +48,7 @@ import { typstBinaryPath } from "../../core/typst.ts"; import { quartoCacheDir } from "../../core/appdirs.ts"; import { isWindows } from "../../deno_ral/platform.ts"; import { makeStringEnumTypeEnforcer } from "../../typing/dynamic.ts"; +import { findChrome } from "../../core/puppeteer.ts"; export const kTargets = [ "install", @@ -212,11 +213,12 @@ async function checkInstall(services: RenderServices) { info(""); const toolsMessage = "Checking tools...................."; const toolsOutput: string[] = []; + let tools: Awaited>; await withSpinner({ message: toolsMessage, doneMessage: toolsMessage + "OK", }, async () => { - const tools = await allTools(); + tools = await allTools(); for (const tool of tools.installed) { const version = await tool.installedVersion() || "(external install)"; @@ -260,6 +262,43 @@ async function checkInstall(services: RenderServices) { latexOutput.forEach((out) => info(out)); info(""); + const chromeHeadlessMessage = "Checking Chrome Headless...................."; + const chromeHeadlessOutput: string[] = []; + await withSpinner({ + message: chromeHeadlessMessage, + doneMessage: chromeHeadlessMessage + "OK", + }, async () => { + const chromeDetected = await findChrome(); + const chromiumQuarto = tools.installed.find((tool) => + tool.name === "chromium" + ); + if (chromeDetected.path !== undefined) { + chromeHeadlessOutput.push(`${kIndent}Using: Chrome found on system`); + chromeHeadlessOutput.push( + `${kIndent}Path: ${chromeDetected.path}`, + ); + if (chromeDetected.source) { + chromeHeadlessOutput.push(`${kIndent}Source: ${chromeDetected.source}`); + } + } else if (chromiumQuarto !== undefined) { + chromeHeadlessOutput.push( + `${kIndent}Using: Chromium installed by Quarto`, + ); + if (chromiumQuarto?.binDir) { + chromeHeadlessOutput.push( + `${kIndent}Path: ${chromiumQuarto?.binDir}`, + ); + } + chromeHeadlessOutput.push( + `${kIndent}Version: ${chromiumQuarto.installedVersion}`, + ); + } else { + chromeHeadlessOutput.push(`${kIndent}Chrome: (not detected)`); + } + }); + chromeHeadlessOutput.forEach((out) => info(out)); + info(""); + const kMessage = "Checking basic markdown render...."; await withSpinner({ message: kMessage, diff --git a/src/core/puppeteer.ts b/src/core/puppeteer.ts index 7e341852e21..891e6a968e9 100644 --- a/src/core/puppeteer.ts +++ b/src/core/puppeteer.ts @@ -200,15 +200,21 @@ export async function withHeadlessBrowser( } } -async function findChrome(): Promise { +interface ChromeInfo { + path: string | undefined; + source: string | undefined; +} + +export async function findChrome(): Promise { let path; + let source; // First check env var and use this path if specified const envPath = Deno.env.get("QUARTO_CHROMIUM"); if (envPath) { debug("[CHROMIUM] Using path specified in QUARTO_CHROMIUM"); if (safeExistsSync(envPath)) { debug(`[CHROMIUM] Found at ${envPath}, and will be used.`); - return envPath; + return { path: envPath, source: "QUARTO_CHROMIUM" }; } else { debug( `[CHROMIUM] Not found at ${envPath}. Check your environment variable valye. Searching now for another binary.`, @@ -222,6 +228,7 @@ async function findChrome(): Promise { "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge", ]; path = programs.find(safeExistsSync); + source = "MacOS known location"; } else if (isWindows) { // Try the HKLM key const programs = ["chrome.exe", "msedge.exe"]; @@ -231,7 +238,10 @@ async function findChrome(): Promise { programs[i], "(Default)", ); - if (path && safeExistsSync(path)) break; + if (path && safeExistsSync(path)) { + source = "Windows Registry"; + break; + } } // Try the HKCR key @@ -244,7 +254,10 @@ async function findChrome(): Promise { ); path = path?.match(/"(.*)"/); path = path ? path[1] : undefined; - if (path && existsSync(path)) break; + if (path && existsSync(path)) { + source = "Windows Registry"; + break; + } } } } else { @@ -254,6 +267,9 @@ async function findChrome(): Promise { if (!path) { path = await which("chromium-browser"); } + if (path && existsSync(path)) { + source = "PATH"; + } } if (path) { debug("[CHROMIUM] Found Chromium on OS known location"); @@ -261,7 +277,7 @@ async function findChrome(): Promise { } else { debug("[CHROMIUM] Chromium not found on OS known location"); } - return path; + return { path: path, source: source }; } export async function getBrowserExecutablePath() { @@ -272,7 +288,7 @@ export async function getBrowserExecutablePath() { let executablePath: string | undefined = undefined; if (executablePath === undefined) { - executablePath = await findChrome(); + executablePath = (await findChrome()).path; } if (executablePath === undefined && availableRevisions.length > 0) {