Repository navigation
Support JPEG image sizes for feed and open-graph metadata - #15050
Merged
Merged
Conversation
Collaborator
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
imageSize only measured files whose name ended in ".png", so a JPEG (the usual format for blog thumbnails and the preview images Quarto auto-discovers) gave listing feeds and og:image/twitter:image no height or width. The extension check was also case-sensitive, so "feed.PNG" was skipped. imageSize now picks the reader from the file's header bytes: PNG as before, JPEG via a small marker scan to the first start-of-frame segment (baseline, progressive and lossless alike), no dependency. Other formats (SVG, GIF, WebP) still return no size; SVG often has no pixel size and social platforms reject it as og:image anyway. Sniffing content also means a WebP saved as ".jpg" is no longer misread, and a non-PNG file named ".png" now gets no size instead of an error. Checked against Pillow on every PNG and JPEG tracked in the repo (298 files): identical sizes.
cderv
force-pushed
the
fix/image-size-non-png
branch
from
October 14, 2026 09:48
b53fec0 to
16cf14c
Compare
cderv
added a commit
to quarto-dev/quarto-web
that referenced
this pull request
Oct 14, 2026
The image row described only PNG measurement and suggested JPEG as a case for declared sizes. Since quarto-dev/quarto-cli#15050, Quarto also measures JPEG, so declared sizes only matter for remote images and formats like WebP or GIF. quarto-dev/quarto-cli#15040 also stops a page image from inheriting the sizes declared in website: open-graph. The check is whether the page supplies an image, not whether it differs from the site image, and only the page's open-graph block is read, not top-level image-width/height. Sites without site-url that used the site sizes as defaults lose those tags, so document the migration through page or _metadata.yml open-graph metadata, and note that directory sizes also apply to the site image on pages without their own image. All statements checked by rendering test sites with a 1.11 dev build and with 1.10.19.
cderv
added a commit
that referenced
this pull request
Oct 14, 2026
Since #15050, Quarto measures JPEG images for open-graph metadata, and a measured size wins over a declared one. The site's mark.jpg is 34x52, so the fixtures that use it as the site image now emit 34 and 52 instead of the declared 1200 and 892. The declared-size cases that Quarto cannot measure keep their expectations in post-svg-declared.qmd.
cderv
added a commit
that referenced
this pull request
Oct 14, 2026
Since #15050 measures JPEG files, the fixtures using the local mark.jpg site image no longer exercise the declared-size fallback at the site level. A remote image is never measured, so with site-url its declared image-width and image-height must still reach og:image:width and og:image:height. This fails on main, where the size is replaced by the undefined measurement.
cderv
added a commit
that referenced
this pull request
Oct 14, 2026
#15050 now measures JPEG images, so the original JPEG case from #12016 no longer depends on this change. What remains is keeping a declared size for images Quarto cannot measure, such as remote ones, and limiting a site-declared size to the site image. The second part changes output for sites without site-url that declared a global size because all their page images share it: a page that sets its own image, even the site image again, no longer gets the site size. The entry names where to move the declaration.
4 of 5 tasks
cderv
added a commit
that referenced
this pull request
Oct 14, 2026
…15040) With `site-url` set, `og:image:width` and `og:image:height` were dropped for an open-graph image Quarto cannot measure, even when `image-width` and `image-height` were declared. The measured size replaced the declared one with undefined, because imageSize only reads PNG. #15050 now measures JPEG; this change covers the remaining cases, such as remote images, SVG, GIF and WebP. The measured size is still used when Quarto can read the file, so the tags describe the actual pixels. Otherwise the declared size is kept. A size declared in the site open-graph options describes the site image. It no longer applies when a page supplies its own image (an `image`, a page open-graph image, or a preview image found in the page content). That image only gets the dimensions the page declares under open-graph, each dimension separately. `image: false` and the website.image fallback keep the site image and its size. This changes output for sites without site-url: a site-declared size is no longer emitted on pages that set their own image. To keep the tags, declare image-width and image-height under open-graph in the page front matter or in shared metadata such as _metadata.yml. Top-level image-width and image-height are not read for open-graph. - Use the measured size when Quarto can read the image, else the declared one - Scope a site-declared size to the site image only - Treat an empty page open-graph entry as no page block Fixes #12016
cderv
added a commit
to quarto-dev/quarto-web
that referenced
this pull request
Oct 14, 2026
* Document how open-graph image-width and image-height apply The image rows of both social metadata tables said a declared image-width/image-height improves "your Twitter Card". Twitter Card metadata never reads a declared size; only Open Graph does. With site-url set, Quarto measures PNG images and uses that size over a declared one. From Quarto 1.11 (quarto-dev/quarto-cli#15040), a declared size is kept for images Quarto can't measure (JPEG, SVG, ...), and a page that brings its own image no longer inherits the size declared for the site image. Explain both in the Open Graph table, and point the Twitter Card row there instead. * Explain open-graph image size behaviour in its own section The image row described only PNG measurement and suggested JPEG as a case for declared sizes. Since quarto-dev/quarto-cli#15050, Quarto also measures JPEG, so declared sizes only matter for remote images and formats like WebP or GIF. quarto-dev/quarto-cli#15040 also stops a page image from inheriting the sizes declared in website: open-graph. The check is whether the page supplies an image, not whether it differs from the site image, and only the page's open-graph block is read, not top-level image-width/height. Sites without site-url that used the site sizes as defaults lose those tags, so document the migration through page or _metadata.yml open-graph metadata, and note that directory sizes also apply to the site image on pages without their own image. All statements checked by rendering test sites with a 1.11 dev build and with 1.10.19.
3 tasks done
3 of 5 tasks
cderv
added a commit
that referenced
this pull request
Oct 15, 2026
Pages without an `image` could pick a data URI as their preview image, such as the ORCID badge, and join it to `site-url`. Since #15050 the image size is read from any path, so the render then failed with a `stat` error. Crawlers and feed readers fetch images by URL, so a data URI is never usable there, so social metadata and listing feeds skip it and use the next candidate. - Preview image discovery skips data URIs and tries every marked image before the site image. - A data URI set as a page, site, listing item or feed image is ignored with a warning for social metadata and listing feeds, and the next candidate is used. - `projectRelativeHref` leaves data URIs unchanged, so listing cards keep displaying them instead of a broken project path. Fixes #15055
cderv
added a commit
that referenced
this pull request
Oct 16, 2026
The #15050 entry no longer claims twitter:image gets a height and width, as the measured size now goes to og:image only.
3 of 5 tasks
cderv
added a commit
that referenced
this pull request
Oct 16, 2026
) With site-url set, the size measured from a local PNG or JPEG image was written to every social metadata provider. The twitter provider passed it through as twitter:image-height and twitter:image-width, which Twitter Cards do not define: they only have twitter:image and twitter:image:alt for images. Crawlers ignore unknown meta names, so the effect is cosmetic, but the tags are wrong. The measured size now goes to og:image:height and og:image:width only. The same mix-up reached the options: twitter-card shared its option set with open-graph, so image-width and image-height showed in its reference although nothing read them (#12014). Removing them from twitter-card outright would fail the render of any config that sets them, since the object is closed, so they stay accepted there as hidden options that warn they are ignored and point to open-graph. - Send the measured size to Open Graph tags only - Move the image-width and image-height options to open-graph - Keep them accepted on twitter-card as hidden, ignored options The PNG case dates back to 2021; #15050 extended it to JPEG. This follows up on #15083. Fixes #12014
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
imageSize()only measured PNG files, and only when the path ended in a lowercase.png. A JPEG feed image, listing item image orog:imagetherefore never got a height or width: no<height>/<width>in the feed<image>, no size on itemmedia:content, noog:image:width/og:image:height. JPEG is the common format for photo thumbnails, and #12016 showed users do need the open-graph sizes for them.imageSize()now picks the parser from the file's header bytes instead of its extension. This also fixesfeed.PNG,.jpegand.jfifpaths, which the extension check skipped. JPEG sizes come from a newsrc/core/jpeg.tsthat scans markers up to the first start-of-frame segment, with no new dependency. Baseline and progressive JPEGs are both read. Callers are unchanged.Only PNG and JPEG are measured. SVG often has no pixel size, and Facebook and X reject SVG
og:imageanyway. GIF, WebP and AVIF can be added the same way if there is demand. Unknown formats still returnundefined, as before.png.tsnow exportsisPng(), which checks the 8-byte signature from the PNG spec. It replaces the old check that compared the bytes joined as decimal digits against the string"13780787113102610".Related to #15040, which fixes the same open-graph size behaviour for declared sizes with
site-url.Checklist
I have (if applicable):
AI-assisted PR
Note: autonomous AI agents submitting PRs without human oversight are not permitted — see the Code of Conduct.