UPG-100 packet page 1 is the full UPG-100 poster: the letter sheet with its title, scripture banner, three-column header and footer, generated at the click

generateSheet gains `sparse` (default: every format but 'packet', so every existing caller is unchanged);
the UPG-100 zone sheet answers the packet's 'packet' request with the full letter poster, the same
1500x1941 page. check:poster-browser-equiv compares that sheet with Node's letter format without SPARSE.
This commit is contained in:
Doxa Maps 2026-10-02 19:44:34 +00:00
parent 381abd0623
commit 75e581019e
3 changed files with 15 additions and 5 deletions

View file

@ -11,7 +11,7 @@
* ★ IT CALLS WHAT THE BROWSER CALLS. The first version rebuilt the feed itself and so could not see a * ★ IT CALLS WHAT THE BROWSER CALLS. The first version rebuilt the feed itself and so could not see a
* defect in the real entry points: generateCountrySheet passed no province boundaries, and a country * defect in the real entry points: generateCountrySheet passed no province boundaries, and a country
* beside India or China printed without them — while this gate, feeding them by hand, stayed green. So: * beside India or China printed without them — while this gate, feeding them by hand, stayed green. So:
* · a UPG-100 zone through makeZoneSheet (data/zone-sheet-print.js), the map-only packet sheet, an India * · a UPG-100 zone through makeZoneSheet (data/zone-sheet-print.js), the packet's page 1 (the full letter poster), an India
* zone so the ADM1 path runs; * zone so the ADM1 path runs;
* · a country through generateCountrySheet, NEPAL, which sits between India and China; * · a country through generateCountrySheet, NEPAL, which sits between India and China;
* both fetching the served boundaries exactly as the page does (file:// here, the asset URL there). * both fetching the served boundaries exactly as the page does (file:// here, the asset URL there).
@ -110,7 +110,9 @@ const results = []
const { makeZoneSheet } = await import(join(REPO, 'plugin-designs/my-upg-100-list/data/zone-sheet-print.js')) const { makeZoneSheet } = await import(join(REPO, 'plugin-designs/my-upg-100-list/data/zone-sheet-print.js'))
const zoneSheet = makeZoneSheet({ allRecords: async () => records, assetsBase: () => assetsBase, profileConfig: null, date: DATE }) const zoneSheet = makeZoneSheet({ allRecords: async () => records, assetsBase: () => assetsBase, profileConfig: null, date: DATE })
const id = 'asia-india-gujarat' const id = 'asia-india-gujarat'
results.push({ what: `${id} (packet sheet, makeZoneSheet)`, browser: await zoneSheet({ id }, 'packet'), node: nodeSheet({ FORMAT: 'packet', ONLY: id }, `${id}.packet.html`) }) // The UPG-100 packet's page 1 is the FULL letter poster (zone-sheet-print answers 'packet' with it), so the
// Node side is the letter format without SPARSE.
results.push({ what: `${id} (packet page 1 = the full letter poster, makeZoneSheet)`, browser: await zoneSheet({ id }, 'packet'), node: nodeSheet({ FORMAT: 'letter', ONLY: id }, `${id}.letter.html`) })
} }
{ // a country, through the function the country wall calls — Nepal, between India and China { // a country, through the function the country wall calls — Nepal, between India and China
const { generateCountrySheet } = await import(join(REPO, 'library/packet/posterSheets.js')) const { generateCountrySheet } = await import(join(REPO, 'library/packet/posterSheets.js'))

View file

@ -117,13 +117,15 @@ function loadPlaces(assetsBase) {
/** /**
* @returns {Promise<string>} the sheet's full HTML document ('' when the zone cannot be drawn). * @returns {Promise<string>} the sheet's full HTML document ('' when the zone cannot be drawn).
* format '3x4' | '3x3' | 'letter' | 'packet' (map-only, for a packet's page 1) * format '3x4' | '3x3' | 'letter' | 'packet' (map-only, for a packet's page 1)
* sparse the poster's thumbnail layout (default: every format but 'packet'); false asks for the FULL
* poster — the facts, the two explainers and the networks — in any format
* seriesId a key of series.json ('upg100', 'country'); decides the poster's text and networks * seriesId a key of series.json ('upg100', 'country'); decides the poster's text and networks
* date the stamp printed on the sheet (default today) — pass one to reproduce a sheet exactly * date the stamp printed on the sheet (default today) — pass one to reproduce a sheet exactly
*/ */
export async function generateSheet({ export async function generateSheet({
zone, pins = [], zoneFC = null, format = '3x4', seriesId = 'upg100', ISO3_NAME = {}, zone, pins = [], zoneFC = null, format = '3x4', seriesId = 'upg100', ISO3_NAME = {},
adm0 = null, adm1Ind = null, adm1Chn = null, series = { totalGroups: 0, totalLists: 0, index: 1 }, date = null, adm0 = null, adm1Ind = null, adm1Chn = null, series = { totalGroups: 0, totalLists: 0, index: 1 }, date = null,
assetsBase = null, nePlaces = null, assetsBase = null, nePlaces = null, sparse = format !== 'packet',
} = {}) { } = {}) {
if (!zone || !zone.zoneKey) return '' if (!zone || !zone.zoneKey) return ''
const [{ seriesAll }, places, createPosterGenerator] = await Promise.all([ const [{ seriesAll }, places, createPosterGenerator] = await Promise.all([
@ -142,7 +144,9 @@ export async function generateSheet({
// stored UPG-100 thumbnails showed the bold row. A reader saw one header on the card and got // stored UPG-100 thumbnails showed the bold row. A reader saw one header on the card and got
// another on the print. 'packet' is the one packet format (FORMATS: 3x4, 3x3, letter, packet), // another on the print. 'packet' is the one packet format (FORMATS: 3x4, 3x3, letter, packet),
// so it alone keeps the full layout its packet pages were designed around. // so it alone keeps the full layout its packet pages were designed around.
env: { FORMAT: format, ...(format !== 'packet' ? { SPARSE: '1' } : {}), ...(date ? { POSTER_DATE: date } : {}) }, // `sparse` defaults to exactly that split; a caller may ask for the full poster in a poster format (the
// UPG-100 packet's page 1 is its full letter poster).
env: { FORMAT: format, ...(sparse ? { SPARSE: '1' } : {}), ...(date ? { POSTER_DATE: date } : {}) },
SERIES_DEF, ISO3_NAME, adm0, adm1Ind, adm1Chn, nePlaces: places, series: { totalGroups: 0, totalLists: 0, index: 1, ...series }, SERIES_DEF, ISO3_NAME, adm0, adm1Ind, adm1Chn, nePlaces: places, series: { totalGroups: 0, totalLists: 0, index: 1, ...series },
}) })
const fc = zoneFC || { type: 'FeatureCollection', features: [] } const fc = zoneFC || { type: 'FeatureCollection', features: [] }

View file

@ -29,8 +29,12 @@ export function makeZoneSheet({ allRecords, assetsBase, profileConfig, date = nu
if (!zone) return '' // a selection or an unknown id has no zone sheet; the caller falls through if (!zone) return '' // a selection or an unknown id has no zone sheet; the caller falls through
const pins = assignPins(zones, records).get(zone.zoneKey) || [] const pins = assignPins(zones, records).get(zone.zoneKey) || []
const zoneFC = resolveZoneGeometry(zone, { records, ...bounds }) const zoneFC = resolveZoneGeometry(zone, { records, ...bounds })
// ★ THE PACKET'S PAGE 1 IS THE FULL UPG-100 POSTER (2026-10-02), not the map-only sheet: the letter-size
// poster with its title, the scripture banner, the three-column header and the footer. The packet asks
// for 'packet'; this series answers with the full letter sheet, which is the same 1500x1941 page.
const page1 = format === 'packet'
return generateSheet({ return generateSheet({
zone, pins, zoneFC, format, seriesId: 'upg100', ISO3_NAME, adm0: bounds.adm0, adm1Ind: bounds.adm1Ind, adm1Chn: bounds.adm1Chn, zone, pins, zoneFC, format: page1 ? 'letter' : format, ...(page1 ? { sparse: false } : {}), seriesId: 'upg100', ISO3_NAME, adm0: bounds.adm0, adm1Ind: bounds.adm1Ind, adm1Chn: bounds.adm1Chn,
series: { ...seriesFacts(zones), index: zones.indexOf(zone) + 1 }, date, assetsBase: assetsBase(), series: { ...seriesFacts(zones), index: zones.indexOf(zone) + 1 }, date, assetsBase: assetsBase(),
}) })
} }