diff --git a/news/changelog-1.9.md b/news/changelog-1.9.md
index f87a2552f86..6efe453fa69 100644
--- a/news/changelog-1.9.md
+++ b/news/changelog-1.9.md
@@ -63,6 +63,7 @@ All changes included in 1.9:
- ([#13745](https://github.com/quarto-dev/quarto-cli/issues/13745)): Fix relative `font-paths` from extensions or document metadata not resolving correctly for Typst compilation. Relative paths are now resolved against the document directory before being passed to the Typst CLI.
- ([#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`.
- ([#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.)
+- ([#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.
- ([#13249](https://github.com/quarto-dev/quarto-cli/pull/13249)): Update to Pandoc's Typst template following Pandoc 3.8.3 and Typst 0.14.2 support:
- Code syntax highlighting now uses Skylighting by default.
- New template variables `mathfont`, `codefont`, and `linestretch` for font and line spacing customization.
diff --git a/src/core/brand/brand.ts b/src/core/brand/brand.ts
index 80e76e2a297..4c107912423 100644
--- a/src/core/brand/brand.ts
+++ b/src/core/brand/brand.ts
@@ -425,6 +425,45 @@ export function logoAddLeadingSlashes(
};
}
+// Return a copy of the brand with logo paths converted from project-relative
+// to project-absolute (leading /). Typst resolves these via --root, which
+// points to the project directory. Call this before resolveLogo so that
+// brand-sourced paths get the / prefix while document-sourced paths are
+// left untouched.
+export function brandWithAbsoluteLogoPaths(
+ brand: LightDarkBrand | undefined,
+): LightDarkBrand | undefined {
+ if (!brand) {
+ return brand;
+ }
+ const transformBrand = (b: Brand | undefined): Brand | undefined => {
+ if (!b) return b;
+ const oldLogo = b.processedData.logo;
+ const logo: ProcessedBrandData["logo"] = { images: {} };
+ for (const size of Zod.BrandNamedLogo.options) {
+ if (oldLogo[size]) {
+ logo[size] = {
+ ...oldLogo[size],
+ path: ensureLeadingSlashIfNotExternal(oldLogo[size]!.path),
+ };
+ }
+ }
+ for (const [key, value] of Object.entries(oldLogo.images)) {
+ logo.images[key] = {
+ ...value,
+ path: ensureLeadingSlashIfNotExternal(value.path),
+ };
+ }
+ const copy = Object.create(b) as Brand;
+ copy.processedData = { ...b.processedData, logo };
+ return copy;
+ };
+ return {
+ light: transformBrand(brand.light),
+ dark: transformBrand(brand.dark),
+ };
+}
+
// this a typst workaround but might as well write it as a proper function
export function fillLogoPaths(
brand: LightDarkBrand | undefined,
diff --git a/src/format/typst/format-typst.ts b/src/format/typst/format-typst.ts
index ec7052256bc..3a2e018c3de 100644
--- a/src/format/typst/format-typst.ts
+++ b/src/format/typst/format-typst.ts
@@ -37,7 +37,11 @@ import {
BrandNamedLogo,
LogoLightDarkSpecifier,
} from "../../resources/types/schema-types.ts";
-import { fillLogoPaths, resolveLogo } from "../../core/brand/brand.ts";
+import {
+ brandWithAbsoluteLogoPaths,
+ fillLogoPaths,
+ resolveLogo,
+} from "../../core/brand/brand.ts";
import { LogoLightDarkSpecifierPathOptional } from "../../resources/types/zod/schema-types.ts";
const typstBookExtension: BookExtension = {
@@ -98,6 +102,10 @@ export function typstFormat(): Format {
}
const brand = format.render.brand;
+ // For Typst, convert brand logo paths to project-absolute (with /)
+ // before merging with document logo metadata. Typst resolves / paths
+ // via --root which points to the project directory.
+ const typstBrand = brandWithAbsoluteLogoPaths(brand);
const logoSpec = format
.metadata[kLogo] as LogoLightDarkSpecifierPathOptional;
const sizeOrder: BrandNamedLogo[] = [
@@ -108,8 +116,8 @@ export function typstFormat(): Format {
// temporary: if document logo has object or light/dark objects
// without path, do our own findLogo to add the path
// typst is the exception not needing path but we'll probably deprecate this
- const logo = fillLogoPaths(brand, logoSpec, sizeOrder);
- format.metadata[kLogo] = resolveLogo(brand, logo, sizeOrder);
+ const logo = fillLogoPaths(typstBrand, logoSpec, sizeOrder);
+ format.metadata[kLogo] = resolveLogo(typstBrand, logo, sizeOrder);
// force columns to wrap and move any 'columns' setting to metadata
const columns = format.pandoc[kColumns];
if (columns) {
diff --git a/src/resources/filters/quarto-post/typst-brand-yaml.lua b/src/resources/filters/quarto-post/typst-brand-yaml.lua
index e03ca02288e..e23639c86a2 100644
--- a/src/resources/filters/quarto-post/typst-brand-yaml.lua
+++ b/src/resources/filters/quarto-post/typst-brand-yaml.lua
@@ -328,10 +328,6 @@ function render_typst_brand_yaml()
imageFilename = imageFilename and imageFilename:gsub('\\_', '_')
else
-- backslashes need to be doubled for Windows
- if imageFilename[1] ~= "/" and _quarto.projectOffset() ~= "." then
- local offset = _quarto.projectOffset()
- imageFilename = pandoc.path.join({offset, imageFilename})
- end
imageFilename = string.gsub(imageFilename, '\\', '\\\\')
end
logoOptions.path = pandoc.RawInline('typst', imageFilename)
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt-override-dark.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt-override-dark.qmd
index 120d7dfe9f9..50ab1d61414 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt-override-dark.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt-override-dark.qmd
@@ -47,7 +47,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("moon-face\.png", width: 1\.5in, alt: "MOON"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/moon-face\.png", width: 1\.5in, alt: "MOON"\)\)'
-
- 'background.*sun-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt-override.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt-override.qmd
index 92659327349..ea7fbbf47a9 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt-override.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt-override.qmd
@@ -46,7 +46,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in, alt: "SUN"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in, alt: "SUN"\)\)'
-
- 'background.*moon-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt.qmd
index 456ef837e50..5915b972324 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-alt.qmd
@@ -39,7 +39,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in, alt: "sun face"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in, alt: "sun face"\)\)'
-
- 'background.*moon-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-dark.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-dark.qmd
index 69a75f2186b..320022bb449 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-dark.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-dark.qmd
@@ -39,7 +39,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("moon-face\.png", width: 1\.5in, alt: "moon face"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/moon-face\.png", width: 1\.5in, alt: "moon face"\)\)'
-
- 'background.*sun-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-image-path-alt.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-image-path-alt.qmd
index 793bd3530ed..92a4f86ae84 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-image-path-alt.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-image-path-alt.qmd
@@ -39,7 +39,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in, alt: "Sun face image"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in, alt: "Sun face image"\)\)'
-
- 'background.*moon-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-image-path-only.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-image-path-only.qmd
index 1b722b2b696..9d18f6cb0a9 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-image-path-only.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-image-path-only.qmd
@@ -35,7 +35,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in\)\)'
-
- 'background.*moon-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-large.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-large.qmd
index 23bc80aefc8..45d7094f523 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-large.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-large.qmd
@@ -32,7 +32,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in\)\)'
-
- 'background.*moon-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-light.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-light.qmd
index b62834327bd..51a59763a68 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-light.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-light.qmd
@@ -39,7 +39,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in, alt: "sun face"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in, alt: "sun face"\)\)'
-
- 'background.*moon-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-missing-mode.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-missing-mode.qmd
index cad81ca614b..acce956ae4f 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-missing-mode.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-missing-mode.qmd
@@ -30,7 +30,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in\)\)'
---
## Here we go
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-mixed-paths.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-mixed-paths.qmd
index 0ec5b2ea717..00f6d50e55a 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-mixed-paths.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-mixed-paths.qmd
@@ -35,7 +35,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in\)\)'
-
- 'background.*moon-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-reverse-dark.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-reverse-dark.qmd
index bc8edfcc73f..8160cc2f4e7 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-reverse-dark.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-reverse-dark.qmd
@@ -39,7 +39,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in\)\)'
-
- 'background.*moon-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-logo-reverse.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-logo-reverse.qmd
index 759b605117f..66bf44c6be7 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-logo-reverse.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-logo-reverse.qmd
@@ -38,7 +38,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("moon-face\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/moon-face\.png", width: 1\.5in\)\)'
-
- 'background.*sun-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-mode-dark.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-mode-dark.qmd
index 893778a0ae4..9445bb502b1 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-mode-dark.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-mode-dark.qmd
@@ -33,7 +33,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("moon-face\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/moon-face\.png", width: 1\.5in\)\)'
-
- 'background.*sun-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-mode-default.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-mode-default.qmd
index 95398c318cd..856233f18c8 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-mode-default.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-mode-default.qmd
@@ -32,7 +32,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in\)\)'
-
- 'background.*moon-face\.png'
diff --git a/tests/docs/smoke-all/brand/brand-mode/brand-mode-light.qmd b/tests/docs/smoke-all/brand/brand-mode/brand-mode-light.qmd
index 7d372974636..85e27219343 100644
--- a/tests/docs/smoke-all/brand/brand-mode/brand-mode-light.qmd
+++ b/tests/docs/smoke-all/brand/brand-mode/brand-mode-light.qmd
@@ -33,7 +33,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("sun-face\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/sun-face\.png", width: 1\.5in\)\)'
-
- 'background.*moon-face\.png'
---
diff --git a/tests/docs/smoke-all/brand/logo/choose-logo-resource.qmd b/tests/docs/smoke-all/brand/logo/choose-logo-resource.qmd
index 80ab3527e40..8ca915c57a1 100644
--- a/tests/docs/smoke-all/brand/logo/choose-logo-resource.qmd
+++ b/tests/docs/smoke-all/brand/logo/choose-logo-resource.qmd
@@ -32,7 +32,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("posit-logo-2024.svg", width: 1\.5in, alt: "posit logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/posit-logo-2024.svg", width: 1\.5in, alt: "posit logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/dark-logo.qmd b/tests/docs/smoke-all/brand/logo/dark-logo.qmd
index cf858b615f4..ea846c98450 100644
--- a/tests/docs/smoke-all/brand/logo/dark-logo.qmd
+++ b/tests/docs/smoke-all/brand/logo/dark-logo.qmd
@@ -42,7 +42,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("quarto.png", width: 1\.5in, alt: "quarto logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/quarto.png", width: 1\.5in, alt: "quarto logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/dark-mode-no-dark-logo.qmd b/tests/docs/smoke-all/brand/logo/dark-mode-no-dark-logo.qmd
index 9c940a9a08c..8614558e474 100644
--- a/tests/docs/smoke-all/brand/logo/dark-mode-no-dark-logo.qmd
+++ b/tests/docs/smoke-all/brand/logo/dark-mode-no-dark-logo.qmd
@@ -42,7 +42,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("quarto.png", width: 1\.5in, alt: "light logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/quarto.png", width: 1\.5in, alt: "light logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/dark-mode-no-light-logo.qmd b/tests/docs/smoke-all/brand/logo/dark-mode-no-light-logo.qmd
index 11aa072ea68..54727f5dfde 100644
--- a/tests/docs/smoke-all/brand/logo/dark-mode-no-light-logo.qmd
+++ b/tests/docs/smoke-all/brand/logo/dark-mode-no-light-logo.qmd
@@ -40,7 +40,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("posit-logo-2024.svg", width: 1\.5in, alt: "dark logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/posit-logo-2024.svg", width: 1\.5in, alt: "dark logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/dark-mode-search-priority.qmd b/tests/docs/smoke-all/brand/logo/dark-mode-search-priority.qmd
index a69d9ef750b..222a535e092 100644
--- a/tests/docs/smoke-all/brand/logo/dark-mode-search-priority.qmd
+++ b/tests/docs/smoke-all/brand/logo/dark-mode-search-priority.qmd
@@ -46,7 +46,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("dark-logo.png", width: 1\.5in, alt: "dark logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/dark-logo.png", width: 1\.5in, alt: "dark logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/default-logo.qmd b/tests/docs/smoke-all/brand/logo/default-logo.qmd
index 40f10348572..d2d2aef0e20 100644
--- a/tests/docs/smoke-all/brand/logo/default-logo.qmd
+++ b/tests/docs/smoke-all/brand/logo/default-logo.qmd
@@ -31,7 +31,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("quarto.png", width: 1\.5in, alt: "quarto logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/quarto.png", width: 1\.5in, alt: "quarto logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/logo-extension-github/logo-brand-extension.qmd b/tests/docs/smoke-all/brand/logo/logo-extension-github/logo-brand-extension.qmd
index 6d2d8051f61..29b03a792df 100644
--- a/tests/docs/smoke-all/brand/logo/logo-extension-github/logo-brand-extension.qmd
+++ b/tests/docs/smoke-all/brand/logo/logo-extension-github/logo-brand-extension.qmd
@@ -29,7 +29,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("_extensions(/|\\\\)my-org(/|\\\\)my-brand(/|\\\\)images(/|\\\\)sun-face.png", width: 1\.5in, alt: "sun face"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/_extensions(/|\\\\)my-org(/|\\\\)my-brand(/|\\\\)images(/|\\\\)sun-face.png", width: 1\.5in, alt: "sun face"\)\)'
-
- 'image\.*moon-face'
---
diff --git a/tests/docs/smoke-all/brand/logo/logo-extension/logo-brand-extension.qmd b/tests/docs/smoke-all/brand/logo/logo-extension/logo-brand-extension.qmd
index 1e00d390ad5..233ce8ed2a8 100644
--- a/tests/docs/smoke-all/brand/logo/logo-extension/logo-brand-extension.qmd
+++ b/tests/docs/smoke-all/brand/logo/logo-extension/logo-brand-extension.qmd
@@ -29,7 +29,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("_extensions(/|\\\\)my-brand(/|\\\\)sun-face.png", width: 1\.5in, alt: "sun face"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/_extensions(/|\\\\)my-brand(/|\\\\)sun-face.png", width: 1\.5in, alt: "sun face"\)\)'
-
- 'image.*moon-face'
---
diff --git a/tests/docs/smoke-all/brand/logo/missing-medium-dark-fallback.qmd b/tests/docs/smoke-all/brand/logo/missing-medium-dark-fallback.qmd
index d22cf154043..917775d2616 100644
--- a/tests/docs/smoke-all/brand/logo/missing-medium-dark-fallback.qmd
+++ b/tests/docs/smoke-all/brand/logo/missing-medium-dark-fallback.qmd
@@ -40,7 +40,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("quarto-dark.png", width: 1\.5in, alt: "quarto dark logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/quarto-dark.png", width: 1\.5in, alt: "quarto dark logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/mixed-resource-direct-path.qmd b/tests/docs/smoke-all/brand/logo/mixed-resource-direct-path.qmd
index d12d0da6b23..f8506473c6a 100644
--- a/tests/docs/smoke-all/brand/logo/mixed-resource-direct-path.qmd
+++ b/tests/docs/smoke-all/brand/logo/mixed-resource-direct-path.qmd
@@ -37,7 +37,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("custom-dark.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/custom-dark.png", width: 1\.5in\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/mode-first-search-algorithm.qmd b/tests/docs/smoke-all/brand/logo/mode-first-search-algorithm.qmd
index 6a25e548aa6..5b9da8f519b 100644
--- a/tests/docs/smoke-all/brand/logo/mode-first-search-algorithm.qmd
+++ b/tests/docs/smoke-all/brand/logo/mode-first-search-algorithm.qmd
@@ -42,7 +42,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("dark-large.png", width: 1\.5in, alt: "dark large logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/dark-large.png", width: 1\.5in, alt: "dark large logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/override-dark-logo.qmd b/tests/docs/smoke-all/brand/logo/override-dark-logo.qmd
index ada9e0cc07b..6ad05ab7f1c 100644
--- a/tests/docs/smoke-all/brand/logo/override-dark-logo.qmd
+++ b/tests/docs/smoke-all/brand/logo/override-dark-logo.qmd
@@ -46,7 +46,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("quarto-dark.png", width: 1\.5in, alt: "quarto dark logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/quarto-dark.png", width: 1\.5in, alt: "quarto dark logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/override-logo-resource-alt.qmd b/tests/docs/smoke-all/brand/logo/override-logo-resource-alt.qmd
index 4d21b79dc5e..2695d6559aa 100644
--- a/tests/docs/smoke-all/brand/logo/override-logo-resource-alt.qmd
+++ b/tests/docs/smoke-all/brand/logo/override-logo-resource-alt.qmd
@@ -34,7 +34,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("posit-logo-2024.svg", width: 1\.5in, alt: "logo of posit"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/posit-logo-2024.svg", width: 1\.5in, alt: "logo of posit"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/override-logo-resource.qmd b/tests/docs/smoke-all/brand/logo/override-logo-resource.qmd
index ed1ca1456a5..b079710edc1 100644
--- a/tests/docs/smoke-all/brand/logo/override-logo-resource.qmd
+++ b/tests/docs/smoke-all/brand/logo/override-logo-resource.qmd
@@ -33,7 +33,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("posit-logo-2024.svg", width: 1\.5in, alt: "posit logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/posit-logo-2024.svg", width: 1\.5in, alt: "posit logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/partial-document-override.qmd b/tests/docs/smoke-all/brand/logo/partial-document-override.qmd
index c2d3a9ff3fe..f2e94c47508 100644
--- a/tests/docs/smoke-all/brand/logo/partial-document-override.qmd
+++ b/tests/docs/smoke-all/brand/logo/partial-document-override.qmd
@@ -41,7 +41,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0.75in, image\("posit-logo-2024.svg", width: 1\.5in, alt: "posit logo"\)\)'
+ - 'background: align\(left\+top, box\(inset: 0.75in, image\("/posit-logo-2024.svg", width: 1\.5in, alt: "posit logo"\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/project-subdirs/typst/typst.qmd b/tests/docs/smoke-all/brand/logo/project-subdirs/typst/typst.qmd
index b5d5a07c210..df323207963 100644
--- a/tests/docs/smoke-all/brand/logo/project-subdirs/typst/typst.qmd
+++ b/tests/docs/smoke-all/brand/logo/project-subdirs/typst/typst.qmd
@@ -8,7 +8,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background:.*image\("\.\.(/|\\\\)brand(/|\\\\)images(/|\\\\)favicon\.png'
+ - '#set page\(background:.*image\("/brand(/|\\\\)images(/|\\\\)favicon\.png'
- '#box\(image\("\.\.(/|\\\\)brand(/|\\\\)images(/|\\\\)logo.png"\)\)'
- '#box\(image\("\.\.(/|\\\\)brand(/|\\\\)images(/|\\\\)header.png"\)\)'
- []
diff --git a/tests/docs/smoke-all/brand/logo/relative-logo-path-no-project/index.qmd b/tests/docs/smoke-all/brand/logo/relative-logo-path-no-project/index.qmd
index f6f90a866d6..b73980032d5 100644
--- a/tests/docs/smoke-all/brand/logo/relative-logo-path-no-project/index.qmd
+++ b/tests/docs/smoke-all/brand/logo/relative-logo-path-no-project/index.qmd
@@ -20,7 +20,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0\.75in, image\("logos(/|\\\\)logo\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0\.75in, image\("/logos(/|\\\\)logo\.png", width: 1\.5in\)\)'
- []
---
diff --git a/tests/docs/smoke-all/brand/logo/relative-logo-path-project/index.qmd b/tests/docs/smoke-all/brand/logo/relative-logo-path-project/index.qmd
index f6f90a866d6..b73980032d5 100644
--- a/tests/docs/smoke-all/brand/logo/relative-logo-path-project/index.qmd
+++ b/tests/docs/smoke-all/brand/logo/relative-logo-path-project/index.qmd
@@ -20,7 +20,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - 'background: align\(left\+top, box\(inset: 0\.75in, image\("logos(/|\\\\)logo\.png", width: 1\.5in\)\)'
+ - 'background: align\(left\+top, box\(inset: 0\.75in, image\("/logos(/|\\\\)logo\.png", width: 1\.5in\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/customize-without-path.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/customize-without-path.qmd
index 510878e3996..15ea04b70d8 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/customize-without-path.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/customize-without-path.qmd
@@ -16,7 +16,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background: align\(center\+top, box\(inset: 2em, image\("quarto(/|\\\\)quarto.png", width: 225pt\)\)\)\)'
+ - '#set page\(background: align\(center\+top, box\(inset: 2em, image\("/quarto(/|\\\\)quarto.png", width: 225pt\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/directional-padding.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/directional-padding.qmd
index b6620d0837d..4a8dd5c9091 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/directional-padding.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/directional-padding.qmd
@@ -18,7 +18,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background: align\(center\+horizon, box\(inset: \(bottom: 7.5pt, left: 15pt, right: 37.5pt, top: 22.5pt\), image\("quarto(/|\\\\)quarto.png", width: 135pt\)\)\)\)'
+ - '#set page\(background: align\(center\+horizon, box\(inset: \(bottom: 7.5pt, left: 15pt, right: 37.5pt, top: 22.5pt\), image\("/quarto(/|\\\\)quarto.png", width: 135pt\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-directional-padding-dark-mode.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-directional-padding-dark-mode.qmd
index bb716f4a9cd..784c7093440 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-directional-padding-dark-mode.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-directional-padding-dark-mode.qmd
@@ -36,7 +36,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background: align\(right\+horizon, box\(inset: \(bottom: 15pt, left: 7.5pt, right: 22.5pt, top: 30pt\), image\("quarto(/|\\\\)quarto.png", width: 120pt\)\)\)\)'
+ - '#set page\(background: align\(right\+horizon, box\(inset: \(bottom: 15pt, left: 7.5pt, right: 22.5pt, top: 30pt\), image\("/quarto(/|\\\\)quarto.png", width: 120pt\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-directional-padding.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-directional-padding.qmd
index 06af80338be..1b00a08de30 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-directional-padding.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-directional-padding.qmd
@@ -35,7 +35,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background: align\(left\+horizon, box\(inset: \(bottom: 18.75pt, left: 26.25pt, right: 11.25pt, top: 18.75pt\), image\("quarto(/|\\\\)quarto.png", width: 165pt\)\)\)\)'
+ - '#set page\(background: align\(left\+horizon, box\(inset: \(bottom: 18.75pt, left: 26.25pt, right: 11.25pt, top: 18.75pt\), image\("/quarto(/|\\\\)quarto.png", width: 165pt\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-variants-dark-mode.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-variants-dark-mode.qmd
index b341d49a2fb..ede2aa43316 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-variants-dark-mode.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-variants-dark-mode.qmd
@@ -30,7 +30,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background: align\(right\+bottom, box\(inset: 30pt, image\("quarto(/|\\\\)quarto.png", width: 150pt\)\)\)\)'
+ - '#set page\(background: align\(right\+bottom, box\(inset: 30pt, image\("/quarto(/|\\\\)quarto.png", width: 150pt\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-variants.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-variants.qmd
index 9f0150d75f1..493208b37be 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-variants.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/light-dark-variants.qmd
@@ -29,7 +29,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background: align\(left\+top, box\(inset: 18pt, image\("quarto(/|\\\\)quarto.png", width: 187.5pt\)\)\)\)'
+ - '#set page\(background: align\(left\+top, box\(inset: 18pt, image\("/quarto(/|\\\\)quarto.png", width: 187.5pt\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/padding-xy/brand-logo.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/padding-xy/brand-logo.qmd
index 46c8abf1b38..ab02ff014fd 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/padding-xy/brand-logo.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/padding-xy/brand-logo.qmd
@@ -10,7 +10,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background: align\(center\+top, box\(inset: \(x: 2in, y: 1\in\), image\("quarto.png", width: 225pt\)\)\)\)'
+ - '#set page\(background: align\(center\+top, box\(inset: \(x: 2in, y: 1\in\), image\("/quarto.png", width: 225pt\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/padding/brand-logo.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/padding/brand-logo.qmd
index 8db14e3bdd0..1d7999e3085 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/padding/brand-logo.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/padding/brand-logo.qmd
@@ -12,7 +12,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background: align\(center\+top, box\(inset: \(bottom: 3pt, left: 4pt, right: 2pt, top: 1pt\), image\("quarto.png", width: 225pt\)\)\)\)'
+ - '#set page\(background: align\(center\+top, box\(inset: \(bottom: 3pt, left: 4pt, right: 2pt, top: 1pt\), image\("/quarto.png", width: 225pt\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/posit/brand-logo.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/posit/brand-logo.qmd
index 07fff252977..7bf9f2d5b48 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/posit/brand-logo.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/posit/brand-logo.qmd
@@ -11,7 +11,7 @@ _quarto:
-
- '#let brand-logo-images = \(\s*brand-typst-with-good-padding: \(\s*path: "good-padding\.png"\s*\),\s*posit-logo-light-medium: \(\s*alt: "Posit Logo",\s*path: "posit-logo-2024.svg"\s*\)'
- '#let brand-logo = \(\s*medium: \(\s*alt: "Posit Logo",\s*path: "posit-logo-2024\.svg"\s*\)\s*\)'
- - '#set page\(background: align\(left\+top, box\(inset: 0.75in, image\("posit-logo-2024.svg", width: 1.5in, alt: "Posit Logo"\)\)\)\)'
+ - '#set page\(background: align\(left\+top, box\(inset: 0.75in, image\("/posit-logo-2024.svg", width: 1.5in, alt: "Posit Logo"\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/quarto/brand-logo.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/quarto/brand-logo.qmd
index 6eabcedfc79..f09bf25e502 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/quarto/brand-logo.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/quarto/brand-logo.qmd
@@ -10,7 +10,7 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- - '#set page\(background: align\(center\+top, box\(inset: 2em, image\("quarto.png", width: 225pt\)\)\)\)'
+ - '#set page\(background: align\(center\+top, box\(inset: 2em, image\("/quarto.png", width: 225pt\)\)\)\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/brand-yaml/logo/relative-path/brand-logo.qmd b/tests/docs/smoke-all/typst/brand-yaml/logo/relative-path/brand-logo.qmd
index f94302ae13f..e0fc147aaf5 100644
--- a/tests/docs/smoke-all/typst/brand-yaml/logo/relative-path/brand-logo.qmd
+++ b/tests/docs/smoke-all/typst/brand-yaml/logo/relative-path/brand-logo.qmd
@@ -13,7 +13,7 @@ _quarto:
-
- '#let brand-logo-images = \(\s*large-light: \(\s*path: "brand_yaml(/|\\\\)resources(/|\\\\)quarto.png"\s*\)\s*\)'
- '#let brand-logo = \(\s*large: \(\s*path: "brand_yaml(/|\\\\)resources(/|\\\\)quarto.png"\s*\)\s*\)'
- - '#set page\(background: align\(center\+top, box\(inset: 2em, image\("brand_yaml(/|\\\\)resources(/|\\\\)quarto.png", width: 225pt\)\)\)\)'
+ - '#set page\(background: align\(center\+top, box\(inset: 2em, image\("/brand_yaml(/|\\\\)resources(/|\\\\)quarto.png", width: 225pt\)\)\)\)'
- '#image\(brand-logo-images\.large-light\.path, alt:"from brand-logo-images"\)'
- []
---
diff --git a/tests/docs/smoke-all/typst/logo-path/from-brand/.gitignore b/tests/docs/smoke-all/typst/logo-path/from-brand/.gitignore
new file mode 100644
index 00000000000..b683cbac7c5
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-brand/.gitignore
@@ -0,0 +1,4 @@
+/.quarto/
+*.pdf
+
+**/*.quarto_ipynb
diff --git a/tests/docs/smoke-all/typst/logo-path/from-brand/_brand.yml b/tests/docs/smoke-all/typst/logo-path/from-brand/_brand.yml
new file mode 100644
index 00000000000..88a3b1a7674
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-brand/_brand.yml
@@ -0,0 +1,5 @@
+logo:
+ images:
+ main:
+ path: images/logo.svg
+ small: main
diff --git a/tests/docs/smoke-all/typst/logo-path/from-brand/_quarto.yml b/tests/docs/smoke-all/typst/logo-path/from-brand/_quarto.yml
new file mode 100644
index 00000000000..e63a3fa1026
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-brand/_quarto.yml
@@ -0,0 +1,4 @@
+project:
+ type: default
+format:
+ typst: default
diff --git a/tests/docs/smoke-all/typst/logo-path/from-brand/images/logo.svg b/tests/docs/smoke-all/typst/logo-path/from-brand/images/logo.svg
new file mode 100644
index 00000000000..5061a10d542
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-brand/images/logo.svg
@@ -0,0 +1 @@
+
diff --git a/tests/docs/smoke-all/typst/logo-path/from-brand/sub/doc.qmd b/tests/docs/smoke-all/typst/logo-path/from-brand/sub/doc.qmd
new file mode 100644
index 00000000000..8bac3219acc
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-brand/sub/doc.qmd
@@ -0,0 +1,16 @@
+---
+title: "Logo from _brand.yml in subdirectory"
+format:
+ typst:
+ keep-typ: true
+_quarto:
+ tests:
+ typst:
+ ensureTypstFileRegexMatches:
+ -
+ - 'image\("(/|\\\\)images(/|\\\\)logo\.svg"'
+ -
+ - 'image\("\.\.(/|\\\\)images(/|\\\\)logo\.svg"'
+---
+
+Hello world.
diff --git a/tests/docs/smoke-all/typst/logo-path/from-extension/.gitignore b/tests/docs/smoke-all/typst/logo-path/from-extension/.gitignore
new file mode 100644
index 00000000000..b683cbac7c5
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-extension/.gitignore
@@ -0,0 +1,4 @@
+/.quarto/
+*.pdf
+
+**/*.quarto_ipynb
diff --git a/tests/docs/smoke-all/typst/logo-path/from-extension/_extensions/testformat/_extension.yml b/tests/docs/smoke-all/typst/logo-path/from-extension/_extensions/testformat/_extension.yml
new file mode 100644
index 00000000000..3db81012866
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-extension/_extensions/testformat/_extension.yml
@@ -0,0 +1,7 @@
+title: Test Format
+author: Test
+version: 1.0.0
+contributes:
+ formats:
+ typst:
+ logo: logo.svg
diff --git a/tests/docs/smoke-all/typst/logo-path/from-extension/_extensions/testformat/logo.svg b/tests/docs/smoke-all/typst/logo-path/from-extension/_extensions/testformat/logo.svg
new file mode 100644
index 00000000000..5061a10d542
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-extension/_extensions/testformat/logo.svg
@@ -0,0 +1 @@
+
diff --git a/tests/docs/smoke-all/typst/logo-path/from-extension/_quarto.yml b/tests/docs/smoke-all/typst/logo-path/from-extension/_quarto.yml
new file mode 100644
index 00000000000..b8bae5830fa
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-extension/_quarto.yml
@@ -0,0 +1,2 @@
+project:
+ type: default
diff --git a/tests/docs/smoke-all/typst/logo-path/from-extension/sub/doc.qmd b/tests/docs/smoke-all/typst/logo-path/from-extension/sub/doc.qmd
new file mode 100644
index 00000000000..5f15e4aee3c
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-extension/sub/doc.qmd
@@ -0,0 +1,16 @@
+---
+title: "Logo from extension in subdirectory"
+keep-typ: true
+format:
+ testformat-typst: default
+_quarto:
+ tests:
+ testformat-typst:
+ ensureTypstFileRegexMatches:
+ -
+ - 'image\("\.\.(/|\\\\)_extensions(/|\\\\)testformat(/|\\\\)logo\.svg"'
+ -
+ - 'image\("\.\.(/|\\\\)\.\.(/|\\\\)_extensions(/|\\\\)testformat(/|\\\\)logo\.svg"'
+---
+
+Hello world.
diff --git a/tests/docs/smoke-all/typst/logo-path/from-frontmatter/.gitignore b/tests/docs/smoke-all/typst/logo-path/from-frontmatter/.gitignore
new file mode 100644
index 00000000000..b683cbac7c5
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-frontmatter/.gitignore
@@ -0,0 +1,4 @@
+/.quarto/
+*.pdf
+
+**/*.quarto_ipynb
diff --git a/tests/docs/smoke-all/typst/logo-path/from-frontmatter/_quarto.yml b/tests/docs/smoke-all/typst/logo-path/from-frontmatter/_quarto.yml
new file mode 100644
index 00000000000..e63a3fa1026
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-frontmatter/_quarto.yml
@@ -0,0 +1,4 @@
+project:
+ type: default
+format:
+ typst: default
diff --git a/tests/docs/smoke-all/typst/logo-path/from-frontmatter/images/logo.svg b/tests/docs/smoke-all/typst/logo-path/from-frontmatter/images/logo.svg
new file mode 100644
index 00000000000..5061a10d542
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-frontmatter/images/logo.svg
@@ -0,0 +1 @@
+
diff --git a/tests/docs/smoke-all/typst/logo-path/from-frontmatter/sub/doc.qmd b/tests/docs/smoke-all/typst/logo-path/from-frontmatter/sub/doc.qmd
new file mode 100644
index 00000000000..f2c12e14e1c
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-frontmatter/sub/doc.qmd
@@ -0,0 +1,17 @@
+---
+title: "Logo from front matter in subdirectory"
+logo: ../images/logo.svg
+format:
+ typst:
+ keep-typ: true
+_quarto:
+ tests:
+ typst:
+ ensureTypstFileRegexMatches:
+ -
+ - 'image\("\.\.(/|\\\\)images(/|\\\\)logo\.svg"'
+ -
+ - 'image\("\.\.(/|\\\\)\.\.(/|\\\\)images(/|\\\\)logo\.svg"'
+---
+
+Hello world.
diff --git a/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/.gitignore b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/.gitignore
new file mode 100644
index 00000000000..b683cbac7c5
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/.gitignore
@@ -0,0 +1,4 @@
+/.quarto/
+*.pdf
+
+**/*.quarto_ipynb
diff --git a/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/_quarto.yml b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/_quarto.yml
new file mode 100644
index 00000000000..7d63f6d1f9e
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/_quarto.yml
@@ -0,0 +1,5 @@
+project:
+ type: default
+format:
+ typst:
+ keep-typ: true
diff --git a/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/images/logo.svg b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/images/logo.svg
new file mode 100644
index 00000000000..5061a10d542
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/images/logo.svg
@@ -0,0 +1 @@
+
diff --git a/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/sub/_metadata.yml b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/sub/_metadata.yml
new file mode 100644
index 00000000000..0b73ffe9066
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/sub/_metadata.yml
@@ -0,0 +1 @@
+logo: ../images/logo.svg
diff --git a/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/sub/deep/doc.qmd b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/sub/deep/doc.qmd
new file mode 100644
index 00000000000..1847eb5f10e
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-metadata-yml/sub/deep/doc.qmd
@@ -0,0 +1,16 @@
+---
+title: "Logo from _metadata.yml in subdirectory"
+format:
+ typst:
+ keep-typ: true
+_quarto:
+ tests:
+ typst:
+ ensureTypstFileRegexMatches:
+ -
+ - 'image\("\.\.(/|\\\\)\.\.(/|\\\\)images(/|\\\\)logo\.svg"'
+ -
+ - 'image\("\.\.(/|\\\\)\.\.(/|\\\\)\.\.(/|\\\\)images(/|\\\\)logo\.svg"'
+---
+
+Hello world.
diff --git a/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/.gitignore b/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/.gitignore
new file mode 100644
index 00000000000..b683cbac7c5
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/.gitignore
@@ -0,0 +1,4 @@
+/.quarto/
+*.pdf
+
+**/*.quarto_ipynb
diff --git a/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/_quarto.yml b/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/_quarto.yml
new file mode 100644
index 00000000000..93b7d906ea0
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/_quarto.yml
@@ -0,0 +1,5 @@
+project:
+ type: default
+format:
+ typst:
+ logo: images/logo.svg
diff --git a/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/images/logo.svg b/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/images/logo.svg
new file mode 100644
index 00000000000..5061a10d542
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/images/logo.svg
@@ -0,0 +1 @@
+
diff --git a/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/sub/doc.qmd b/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/sub/doc.qmd
new file mode 100644
index 00000000000..3c4dc4ee2ec
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/from-quarto-yml/sub/doc.qmd
@@ -0,0 +1,16 @@
+---
+title: "Logo from _quarto.yml in subdirectory"
+format:
+ typst:
+ keep-typ: true
+_quarto:
+ tests:
+ typst:
+ ensureTypstFileRegexMatches:
+ -
+ - 'image\("\.\.(/|\\\\)images(/|\\\\)logo\.svg"'
+ -
+ - 'image\("\.\.(/|\\\\)\.\.(/|\\\\)images(/|\\\\)logo\.svg"'
+---
+
+Hello world.
diff --git a/tests/docs/smoke-all/typst/logo-path/logo.svg b/tests/docs/smoke-all/typst/logo-path/logo.svg
new file mode 100644
index 00000000000..5061a10d542
--- /dev/null
+++ b/tests/docs/smoke-all/typst/logo-path/logo.svg
@@ -0,0 +1 @@
+