From 40f55afa6ffd42dc5910bbd68310c216a3500b4e Mon Sep 17 00:00:00 2001
From: Sachin Kumar <69066918+sachin9058@users.noreply.github.com>
Date: Thu, 8 Oct 2026 21:32:36 +0530
Subject: [PATCH] Fetch Wikidata preview thumbnails at a fixed height (#7433)
---
.../javascripts/index_modules/element.js | 61 +++++++++++++++----
app/controllers/application_controller.rb | 5 +-
config/settings.yml | 2 +-
3 files changed, 52 insertions(+), 16 deletions(-)
diff --git a/app/assets/javascripts/index_modules/element.js b/app/assets/javascripts/index_modules/element.js
index 777a1cab0..79f75e18e 100644
--- a/app/assets/javascripts/index_modules/element.js
+++ b/app/assets/javascripts/index_modules/element.js
@@ -62,6 +62,10 @@ function previewWikidataValue($btn) {
const items = $btn.data("qids");
if (!items?.length) return;
$btn.prop("disabled", true);
+ const fetchOptions = {
+ headers: { "Api-User-Agent": "OSM-TagPreview (https://github.com/openstreetmap/openstreetmap-website)" },
+ signal: abortController?.signal
+ };
fetch(OSM.WIKIDATA_API_URL + "?" + new URLSearchParams({
action: "wbgetentities",
format: "json",
@@ -71,10 +75,7 @@ function previewWikidataValue($btn) {
languages: languagesToRequest.join("|"),
languagefallback: 1,
sitefilter: wikisToRequest.join("|")
- }), {
- headers: { "Api-User-Agent": "OSM-TagPreview (https://github.com/openstreetmap/openstreetmap-website)" },
- signal: abortController?.signal
- })
+ }), fetchOptions)
.then(response => response.ok ? response.json() : Promise.reject(response))
.then(({ entities }) => {
if (!entities) return Promise.reject(entities);
@@ -85,7 +86,7 @@ function previewWikidataValue($btn) {
.filter(qid => entities[qid])
.map(qid => getLocalizedResponse(entities[qid]))
.filter(data => data.label || data.icon || data.description || data.article)
- .map(data => renderWikidataResponse(data, $btn.siblings(`a[href*="wikidata.org/entity/${data.qid}"]`)))
+ .map(data => renderWikidataResponse(data, $btn.siblings(`a[href*="wikidata.org/entity/${data.qid}"]`), fetchOptions))
);
})
.catch(() => $btn.prop("disabled", false));
@@ -112,20 +113,22 @@ function getLocalizedResponse(entity) {
return data;
}
-function renderWikidataResponse({ icon, label, article, description }, $link) {
+function renderWikidataResponse({ icon, label, article, description }, $link, fetchOptions) {
const localeName = new Intl.DisplayNames(OSM.preferred_languages, { type: "language" });
const cell = $("
")
.attr("colspan", 2)
.addClass("bg-body-tertiary");
if (icon && OSM.WIKIMEDIA_COMMONS_URL) {
- let src = OSM.WIKIMEDIA_COMMONS_URL + "Special:Redirect/file/" + encodeURIComponent(icon) + "?mobileaction=toggle_view_desktop";
- if (!icon.endsWith(".svg")) src += "&width=128";
- $("")
- .attr("href", OSM.WIKIMEDIA_COMMONS_URL + "File:" + encodeURIComponent(icon) + `?uselang=${OSM.i18n.locale}`)
- .append($(" ").attr({ src, height: "32" }))
- .addClass("float-end mb-1 ms-2")
- .appendTo(cell);
+ fetchCommonsThumbnail(icon, fetchOptions)
+ .then(imageAttributes => {
+ $("")
+ .attr("href", OSM.WIKIMEDIA_COMMONS_URL + "/wiki/File:" + encodeURIComponent(icon) + `?uselang=${OSM.i18n.locale}`)
+ .append($(" ").attr(imageAttributes))
+ .addClass("float-end mb-1 ms-2")
+ .prependTo(cell);
+ })
+ .catch(() => {});
}
if (label) {
const link = $link.clone()
@@ -164,3 +167,35 @@ function renderWikidataResponse({ icon, label, article, description }, $link) {
}
return $("").append(cell);
}
+
+function fetchCommonsThumbnail(filename, fetchOptions) {
+ const isVectorImage = filename.toLowerCase().endsWith(".svg");
+ return fetch(OSM.WIKIMEDIA_COMMONS_URL + "/w/api.php?" + new URLSearchParams({
+ action: "query",
+ format: "json",
+ origin: "*",
+ prop: "imageinfo",
+ titles: "File:" + filename,
+ iiprop: "url|thumburls",
+ iiurlheight: "32"
+ }), fetchOptions)
+ .then(response => response.ok ? response.json() : Promise.reject(response))
+ .then(({ query }) => {
+ const page = Object.values(query.pages)[0];
+ const imageInfo = page.imageinfo?.[0];
+ const imageUrl = isVectorImage ? imageInfo?.url : imageInfo?.thumburl;
+ if (!imageUrl) return Promise.reject(page);
+
+ const imageAttributes = { src: imageUrl, height: "32", alt: filename };
+ if (!isVectorImage) {
+ const thumbUrls = Object.entries(imageInfo.thumburls ?? {});
+ if (thumbUrls.length) {
+ imageAttributes.srcset = thumbUrls
+ .map(([width, thumbnail]) => `${thumbnail.url} ${width}w`)
+ .join(", ");
+ imageAttributes.sizes = `${imageInfo.thumbwidth}px`;
+ }
+ }
+ return imageAttributes;
+ });
+}
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 3e6fa3a0a..784c6c14d 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -253,9 +253,10 @@ class ApplicationController < ActionController::Base
policy = request.content_security_policy.clone
policy.connect_src(*policy.connect_src, "http://127.0.0.1:8111", "https://vector.openstreetmap.org", "https://api.maptiler.com",
"https://tile.thunderforest.com", "https://render.openstreetmap.org", Settings.nominatim_url, Settings.overpass_url,
- Settings.fossgis_osrm_url, Settings.graphhopper_url, Settings.fossgis_valhalla_url, Settings.wikidata_api_url)
+ Settings.fossgis_osrm_url, Settings.graphhopper_url, Settings.fossgis_valhalla_url, Settings.wikidata_api_url,
+ Settings.wikimedia_commons_url)
policy.form_action(*policy.form_action, "render.openstreetmap.org", "tile.thunderforest.com")
- policy.img_src(*policy.img_src, Settings.wikimedia_commons_url, "upload.wikimedia.org")
+ policy.img_src(*policy.img_src, Settings.wikimedia_commons_url, "upload.wikimedia.org", "thumb.wikimedia.org")
policy.script_src(*policy.script_src, :wasm_unsafe_eval)
policy.style_src(*policy.style_src, :unsafe_inline)
diff --git a/config/settings.yml b/config/settings.yml
index 34f36d086..4d04dd948 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -140,7 +140,7 @@ fossgis_osrm_url: "https://routing.openstreetmap.de/"
fossgis_valhalla_url: "https://valhalla1.openstreetmap.de/route"
# Endpoints for Wikimedia integration
wikidata_api_url: "https://www.wikidata.org/w/api.php"
-wikimedia_commons_url: "https://commons.wikimedia.org/wiki/"
+wikimedia_commons_url: "https://commons.wikimedia.org"
# URL to donation form
donation_url: "https://supporting.openstreetmap.org/donate/"
# Linkification rules
--
2.47.3
|