openvibers/openvibe.tours Commits

A picture's credit reads "Ramir Borja", not "Ramir Borja ." (#48)

OP OpenVibers committed 11 days ago · e2fa0c1d5a · 4 files, +10 −6

Commons' Artist field is HTML; each tag became a space, so Singapore's credit read "Ramir Borja .
· CC BY-SA 3.0". The space before punctuation and a trailing full stop go, and the common entities
are decoded. The cities job's version (credits-1) rewrites the stored credits at the next boot,
which also brings {{unesco}} into Suzhou's summary today rather than at tomorrow's run.

Changes

ddiff --git a/server/jobs/cities.js b/server/jobs/cities.js
iindex 0a1eb26..554e400 100644
---- a/server/jobs/cities.js
++++ b/server/jobs/cities.js
@@@ -30,9 +30,9 @@ function fileTitle(name) {
return /^File:/i.test(s) ? s : `File:${s}`;
}
--// A run under older rules is not fresh (jobs/index.js): inline-templates-2 keeps {{convert}}, the unit templates ({{km2}}), {{lang}} and the like
--// in the summaries, so the first boot with it rewrites them.
--const CITIES_VERSION = 'inline-templates-2';
++// A run under older rules is not fresh (jobs/index.js): credits-1 also cleans picture credits (and {{unesco}}, rail badges); inline-templates-2 kept
++// {{convert}}, the unit templates ({{km2}}), {{lang}} and the like in the summaries, so the first boot with it rewrites them.
++const CITIES_VERSION = 'credits-1';
function createCitiesJob({ config, s, store, fetchImpl, log = console }) {
const wikivoyage = createWikivoyage({ config, fetchImpl, pace: s.pace });
ddiff --git a/server/sources/wikidata.js b/server/sources/wikidata.js
iindex 15a4840..5a88761 100644
---- a/server/sources/wikidata.js
++++ b/server/sources/wikidata.js
@@@ -132,7 +132,11 @@ function createWikidata({ config, fetchImpl, pace, log = console }) {
if (!info) continue;
const meta = info.extmetadata || {};
const val = (k) => (meta[k] && meta[k].value ? String(meta[k].value) : null);
-- const strip = (s) => (s ? s.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim() : null);
++ // Commons' Artist is HTML: a tag becomes a space, then the space before punctuation and a trailing full
++ // stop go ("Ramir Borja</a>." read "Ramir Borja ." beside the licence, 2026-11-02).
++ const ENT = { '&amp;': '&', '&quot;': '"', '&#39;': "'", '&lt;': '<', '&gt;': '>', '&nbsp;': ' ' };
++ const strip = (s) => (s ? s.replace(/<[^>]*>/g, ' ').replace(/&(amp|quot|#39|lt|gt|nbsp);/g, (e) => ENT[e]).replace(/\s+/g, ' ')
++ .replace(/\s+([.,;:!?])/g, '$1').replace(/[\s.]+$/, '').trim() || null : null);
out.set(String(page.title), {
url: info.thumburl || info.url || null,
credit: strip(val('Artist')) || strip(val('Credit')) || 'Wikimedia Commons',
ddiff --git a/test/helpers/upstreams.js b/test/helpers/upstreams.js
iindex 1cce6b4..4c94506 100644
---- a/test/helpers/upstreams.js
++++ b/test/helpers/upstreams.js
@@@ -182,7 +182,7 @@ async function startUpstreams() {
}
if (action === 'query' && url.searchParams.get('prop') === 'imageinfo') {
const titles = String(url.searchParams.get('titles') || '').split('|');
-- const pages = titles.map((t) => ({ title: t, imageinfo: [{ thumburl: 'https://upload.wikimedia.org/tours-test.jpg', url: 'https://upload.wikimedia.org/tours-test.jpg', extmetadata: { Artist: { value: 'A photographer' }, LicenseShortName: { value: 'CC BY-SA 4.0' }, LicenseUrl: { value: 'https://creativecommons.org/licenses/by-sa/4.0/' } } }] }));
++ const pages = titles.map((t) => ({ title: t, imageinfo: [{ thumburl: 'https://upload.wikimedia.org/tours-test.jpg', url: 'https://upload.wikimedia.org/tours-test.jpg', extmetadata: { Artist: { value: '<a href="https://commons.wikimedia.org/wiki/User:A">A photographer</a> &amp; friends.' }, LicenseShortName: { value: 'CC BY-SA 4.0' }, LicenseUrl: { value: 'https://creativecommons.org/licenses/by-sa/4.0/' } } }] }));
return json(200, { query: { pages } });
}
return json(400, { error: 'unknown action' });
ddiff --git a/test/jobs.test.js b/test/jobs.test.js
iindex 6330469..808cc63 100644
---- a/test/jobs.test.js
++++ b/test/jobs.test.js
@@@ -18,7 +18,7 @@ const { boot, check, done } = require('./helpers/boot');
const tokyo = await t.ctx.s.db.maybe("SELECT * FROM tours_cities WHERE slug = 'tokyo'");
assert.strictEqual(tokyo.wikidata_id, 'Q1490');
assert.strictEqual(tokyo.image_license, 'CC BY-SA 4.0');
-- assert.match(tokyo.image_credit, /photographer/i);
++ assert.strictEqual(tokyo.image_credit, 'A photographer & friends', 'Commons HTML: no space before punctuation, no trailing stop, entities decoded');
assert.strictEqual(tokyo.country, 'Japan');
assert.strictEqual(tokyo.country_code, 'JP');
assert.match(tokyo.summary, /capital of Japan/);