Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/changelog-1.11.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ All changes included in 1.11:
### Websites

- ([#10756](https://github.com/quarto-dev/quarto-cli/issues/10756)): Fix the notebook preview of an embedded `.qmd` file going missing from the output directory when a project is rendered again, which broke its source notebook link.
- ([#12016](https://github.com/quarto-dev/quarto-cli/issues/12016)): Fix `open-graph` `image-width` and `image-height` being dropped when `site-url` is set and Quarto cannot measure the image, such as a remote image. A size declared in the site `open-graph` options no longer applies when a page sets its own `image`, even the same file: declare `image-width` and `image-height` in the page `open-graph` options or in shared metadata such as `_metadata.yml`.
- ([#14972](https://github.com/quarto-dev/quarto-cli/issues/14972)): Fix the website navbar, sidebar toggle bar, or announcement covering the header of notebook preview pages, which hid the back link, notebook title, and download link. The notebook preview header now sits below the site header.
- ([#14974](https://github.com/quarto-dev/quarto-cli/issues/14974)): Fix math in `.llms.md` files from `llms-txt` coming out garbled with the default `mathjax` method, and with `katex` and `webtex`. Math is now written as `$...$` and `$$...$$` with the `mathjax`, `katex`, `webtex` and `mathml` methods.
- ([#15004](https://github.com/quarto-dev/quarto-cli/issues/15004)): Fix notebook preview pages and notebook sources missing from the output directory when a website with embedded notebooks is rendered from a directory other than the project directory.
Expand Down
33 changes: 29 additions & 4 deletions src/project/types/website/website-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,13 @@ export function metadataHtmlPostProcessor(

// find a preview image if one is not provided
if (metadata[kImage] === undefined && format.metadata[kImage] !== false) {
const previewImg = findPreviewImg(doc) || websiteImage(project.config);
const pagePreviewImg = findPreviewImg(doc);
const previewImg = pagePreviewImg || websiteImage(project.config);
metadata[kImage] = previewImg ? previewImg.src : undefined;
metadata[kImageAlt] = previewImg ? previewImg.alt : undefined;
if (pagePreviewImg && provider.key === kOpenGraph) {
usePageDeclaredImageSize(format, metadata);
}
}

// cook up a description if one is not provided
Expand Down Expand Up @@ -266,10 +270,30 @@ function opengraphMetadata(
metadata[key] = openGraph[key];
}
});

// Same predicate as mergedSiteAndDocumentData uses to replace the site image
const docOpenGraph = format.metadata[kOpenGraph];
const pageSetsImage = !!format.metadata[kImage] ||
(typeof docOpenGraph === "object" && docOpenGraph !== null &&
!!(docOpenGraph as Metadata)[kImage]);
if (pageSetsImage) {
usePageDeclaredImageSize(format, metadata);
}
}
return metadata;
}

// A size declared on the site describes the site image, so an image the page
// supplies only gets the dimensions the page itself declares
function usePageDeclaredImageSize(format: Format, metadata: Metadata) {
const docOpenGraph = format.metadata[kOpenGraph];
const docData = typeof docOpenGraph === "object" && docOpenGraph !== null
? docOpenGraph as Metadata
: {};
metadata[kImageHeight] = docData[kImageHeight];
metadata[kImageWidth] = docData[kImageWidth];
}

function twitterMetadata(format: Format) {
const metadata: Record<string, unknown> = {};

Expand Down Expand Up @@ -331,10 +355,11 @@ function resolveImageMetadata(
project,
);

// Update the image information
// Update the image information, preferring the size read from the file
// over a declared one
metadata[kImage] = imgMeta.href;
metadata[kImageHeight] = imgMeta.height;
metadata[kImageWidth] = imgMeta.width;
metadata[kImageHeight] = imgMeta.height ?? metadata[kImageHeight];
metadata[kImageWidth] = imgMeta.width ?? metadata[kImageWidth];

const altText = format.metadata[kImageAlt];
if (altText && !metadata[kImageAlt]) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.quarto/
_site/
**/*.quarto_ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
project:
type: website

website:
title: "issue-12016-no-site-url"
open-graph:
image: mark.jpg
image-width: 1200
image-height: 892
15 changes: 15 additions & 0 deletions tests/docs/smoke-all/2026/10/13/issue-12016-no-site-url/index.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: "Without site-url, the site image keeps its declared size"
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="mark.jpg">'
- '<meta property="og:image:height" content="892">'
- '<meta property="og:image:width" content="1200">'
- []
---

The declared size describes the site image used by this page.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: "A page with image false keeps the site image and its size"
image: false
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="mark.jpg">'
- '<meta property="og:image:height" content="892">'
- '<meta property="og:image:width" content="1200">'
- []
---

`image: false` does not replace the site image, so the size declared for it still applies.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: "Without site-url, a page image does not inherit the site's size"
image: square.svg
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="square.svg">'
-
- '<meta property="og:image:height"'
- '<meta property="og:image:width"'
---

The size the site declares for its own image does not describe this page's image.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.quarto/
_site/
**/*.quarto_ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
project:
type: website

website:
title: "issue-12016-preview-image"
site-url: https://example.com/
image: mark.jpg
open-graph:
image-width: 1200
image-height: 892
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: "The website image gets its measured size, not the size declared on the site"
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://example.com/mark.jpg">'
- '<meta property="og:image:height" content="52">'
- '<meta property="og:image:width" content="34">'
- []
---

The page has no image of its own, so the site's image is used with its measured size, not the declared one.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: "An empty page open-graph entry with a preview image gets no size"
open-graph:
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://example.com/square.svg">'
-
- '<meta property="og:image:height"'
- '<meta property="og:image:width"'
---

![A square](square.svg){.preview-image}

The page declares `open-graph:` with no value, so it declares no size for its preview image, and the size the site declares for its own image is not used either.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: "A discovered preview image does not inherit the site's size"
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://example.com/square.svg">'
-
- '<meta property="og:image:height"'
- '<meta property="og:image:width"'
---

![A square](square.svg){.preview-image}

The size the site declares describes the site image, not this page's preview image.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.quarto/
_site/
**/*.quarto_ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
project:
type: website

website:
title: "issue-12016-remote-site-image"
site-url: https://example.com/
open-graph:
image: https://images.example.com/social.jpg
image-width: 1200
image-height: 630
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: "A remote site image keeps the size declared on the site"
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://images\.example\.com/social\.jpg">'
- '<meta property="og:image:height" content="630">'
- '<meta property="og:image:width" content="1200">'
- []
---

With `site-url` set, Quarto cannot measure a remote image, so the `image-width` and `image-height` declared next to the site image are used.
3 changes: 3 additions & 0 deletions tests/docs/smoke-all/2026/10/13/issue-12016/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.quarto/
_site/
**/*.quarto_ipynb
10 changes: 10 additions & 0 deletions tests/docs/smoke-all/2026/10/13/issue-12016/_quarto.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
project:
type: website

website:
title: "issue-12016"
site-url: https://example.com/
open-graph:
image: mark.jpg
image-width: 1200
image-height: 892
15 changes: 15 additions & 0 deletions tests/docs/smoke-all/2026/10/13/issue-12016/index.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: "JPEG open-graph image gets its measured size, not the site's declared size"
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://example.com/mark.jpg">'
- '<meta property="og:image:height" content="52">'
- '<meta property="og:image:width" content="34">'
- []
---

With `site-url` set, Quarto measures the JPEG and the measured size wins over the site's declared `image-width` and `image-height`.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: "An empty page open-graph entry keeps the site's image and its measured size"
open-graph:
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://example.com/mark.jpg">'
- '<meta property="og:image:height" content="52">'
- '<meta property="og:image:width" content="34">'
- []
---

The page declares `open-graph:` with no value, so the site's open-graph image is used and its size is measured, not declared.
16 changes: 16 additions & 0 deletions tests/docs/smoke-all/2026/10/13/issue-12016/post-png.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: "A page image gets its own measured size, not the site's"
image: page.png
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://example.com/page.png">'
- '<meta property="og:image:height" content="160">'
- '<meta property="og:image:width" content="210">'
- []
---

The site declares a size for its own image; this page's PNG is measured instead.
19 changes: 19 additions & 0 deletions tests/docs/smoke-all/2026/10/13/issue-12016/post-svg-declared.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: "A page image keeps the size the page declares for it"
open-graph:
image: square.svg
image-width: 10
image-height: 10
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://example.com/square.svg">'
- '<meta property="og:image:height" content="10">'
- '<meta property="og:image:width" content="10">'
- []
---

Quarto cannot measure an SVG, so the size declared next to the page image is used.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: "A page image does not inherit a dimension the page leaves out"
open-graph:
image: square.svg
image-width: 10
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://example.com/square.svg">'
- '<meta property="og:image:width" content="10">'
-
- '<meta property="og:image:height"'
---

The page declares only the width of its image, so the site's height is not used for it.
16 changes: 16 additions & 0 deletions tests/docs/smoke-all/2026/10/13/issue-12016/post-svg.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: "A page image Quarto cannot measure gets no size"
image: square.svg
_quarto:
render-project: true
tests:
html:
ensureFileRegexMatches:
-
- '<meta property="og:image" content="https://example.com/square.svg">'
-
- '<meta property="og:image:height"'
- '<meta property="og:image:width"'
---

The size the site declares for its own image does not describe this page's image.
1 change: 1 addition & 0 deletions tests/docs/smoke-all/2026/10/13/issue-12016/square.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading