diff --git a/data/posters/country-ind.webp b/data/posters/country-ind.webp new file mode 100644 index 000000000..ddd04d40b Binary files /dev/null and b/data/posters/country-ind.webp differ diff --git a/library/packet/countrySheet.js b/library/packet/countrySheet.js index dacab7b5f..594d72e57 100644 --- a/library/packet/countrySheet.js +++ b/library/packet/countrySheet.js @@ -72,6 +72,34 @@ export function seriesFor(countries, item) { return { totalGroups: tier.reduce((a, x) => a + (x.count || 0), 0), totalLists: tier.length, index } } +/** + * ★ COUNTRIES TOO LARGE FOR ANY PAPER SHEET print as ONE LARGE side-lane sheet instead (poster-render's 60x96 / + * 66x66 / 36x60: every group named beside the map, crossing-free leaders). ONE source of truth for every caller (the + * Country Posters wall, the Regions list), so one country never gets two answers. `desktopOnly`: its poster, list, + * packet and cards are offered on a desktop or laptop only (a phone cannot draw a sheet that big). + * The data (country-posters.json) still records why no PAPER sheet fits; this table is what prints instead. + */ +export const LARGE_SHEETS = { IND: { format: '60x96', formats: ['60x96', '66x66', '36x60'], desktopOnly: true } } +export function largeSheet(item) { return (item && LARGE_SHEETS[String(item.iso3 || '').toUpperCase()]) || null } +// The sheet format a request gets: a large-sheet country prints at the large size ASKED FOR when it has one (66x66, +// 36x60), else at its default (60x96); a packet's page 1 stays a page; every other country gets exactly what it asked. +export function sheetFormatFor(item, format) { + const big = largeSheet(item) + if (!big || format === 'packet') return format + return big.formats.includes(format) ? format : big.format +} + +// The facts row's "Administrative Areas" cell for a large-sheet country whose divisions we know (India: its states and +// union territories, counted from the shared state table). English, like the rest of the sheet. +async function adminAreasFor(iso3, base) { + if (iso3 !== 'IND') return undefined + try { + const { loadIndiaStates } = await import('@map/data/indiaStates.js') + const n = ((await loadIndiaStates(base)).states || []).length + return n ? `${n} states and union territories` : undefined + } catch (_) { return undefined } // the cell falls back to the country's name +} + export function makeCountrySheet({ records, assetsBase, countries = null }) { return async function countrySheet(item, format) { const iso3 = item && item.iso3 @@ -84,14 +112,16 @@ export function makeCountrySheet({ records, assetsBase, countries = null }) { records({ type: 'country', values: [iso3] }), ]) if (!rows || !rows.length) return '' // nothing to pin: fall through rather than draw an empty country + const big = largeSheet(item) + const adminAreas = item.adminAreas || (big ? await adminAreasFor(String(iso3).toUpperCase(), assetsBase()) : undefined) return generateCountrySheet({ // region travels: countryZone colours the sheet from it, and a country arriving without one // silently falls back to the old flat teal for that poster alone. - country: { id: item.id, iso3, label: item.label, count: item.count, region: item.region }, + country: { id: item.id, iso3, label: item.label, count: item.count, region: item.region, adminAreas }, records: rows, assetsBase: assetsBase(), ISO3_NAME, - format, + format: sheetFormatFor(item, format), series: seriesFor(countries, item), }) } diff --git a/library/packet/poster-render.integrity.js b/library/packet/poster-render.integrity.js index e99664730..62ef50af3 100644 --- a/library/packet/poster-render.integrity.js +++ b/library/packet/poster-render.integrity.js @@ -2,13 +2,13 @@ // The sha384 of library/packet/poster-render.js. The browser fetches the served copy of that file // (/lib/poster-render.js), hashes it, and runs it only when it matches this pin: code loaded at // print time is integrity-pinned like every embed, because it executes on partner pages. -export const POSTER_RENDER_SHA384 = 'sha384-G47HkYq8eBHUsabdbIppQnCHHlYH6wMYwDH0JjOD++43LdHQugVItepj2arJ1ONR' +export const POSTER_RENDER_SHA384 = 'sha384-eiiTZts7LtjX2hiisXAI4WuoxPQJk9uPEeN5yLHiYXmxsyw+Y+KmJkred53w1ioC' // The sha384 of library/scripts/posters/data/ne-places.json, served at /boundaries/ne-places.json. // Data, not code, but pinned the same way: a sheet uses the places only when they are the pinned ones. export const NE_PLACES_SHA384 = 'sha384-Qtz2q8mcnA9Ei8Kwa2MRMyX95hSbSnUXjXdtsy8rHTX++mgSCih4LO4Rdrb2MIQy' // The sha384 of the classic-script copy (/lib/poster-render.global.js, globalVariant of the file above), // loaded with