diff --git a/package.json b/package.json index 0e6a2ec38..6b96fc21c 100644 --- a/package.json +++ b/package.json @@ -425,6 +425,7 @@ "check:poster-section:self-test": "node plugin-designs/country-posters/scripts/check-poster-section.mjs --self-test", "check:poster-sections": "node plugin-designs/poster-sections/scripts/check-poster-sections.mjs", "check:poster-sections:self-test": "node plugin-designs/poster-sections/scripts/check-poster-sections.mjs --self-test", + "gen:poster-sections-presets": "node plugin-designs/poster-sections/scripts/gen-presets.mjs", "check:side-lane-photo-pixels": "node plugin-designs/country-posters/scripts/check-side-lane-photo-pixels.mjs", "check:side-lane-photo-pixels:self-test": "node plugin-designs/country-posters/scripts/check-side-lane-photo-pixels.mjs --self-test", "check:poster-type-registry": "node internal/check-poster-type-registry.mjs", @@ -702,6 +703,7 @@ "check:poster-section:self-test": "a registry without 'country', a region key without \"&\" → \"and\", and a section that uses a name it does not inject must each make check:poster-section fail.", "check:poster-sections": "the Poster Sections page (plugin-designs/poster-sections): every panel choice (each region or All regions, each language, open or collapsed, 1-5 per row) builds tags that the element's own attribute reader turns back into exactly those choices; All regions is one section per region; Copy embed is the bundle script plus those same tags. The presets file holds, per poster type, exactly an all-regions preset plus one per region its adapter's scopes() returns, so a region the data drops (or gains) cannot drift from the presets.", "check:poster-sections:self-test": "a tag builder that drops columns, one that drops collapsed, one that repeats a region under All regions, and a preset for a region the type does not have must each make check:poster-sections fail.", + "gen:poster-sections-presets": "writes plugin-designs/poster-sections/poster-sections.instances.json from each poster type's own scopes() (all regions + one preset per region, titled by the type's own section title, then configure); the list check:poster-sections holds the file to.", "check:side-lane-photo-pixels": "BROWSER gate (browser seat; elsewhere 75 NOT MEASURED): the 60x96 side-lane sheet rasterised by poster-raster.js, measured in pixels at every photo slot. A data: photo draws; every photo on its own host stays flat, never the broken-image glyph an external rasterises as.", "check:side-lane-photo-pixels:self-test": "the same raster WITHOUT stripExternalImages must leave the external photo slots NOT flat (the glyph), else the gate proves nothing.", "check:poster-type-registry": "the poster type registry is ONE per page: every bundle inlines its own copy of posterTypes.js and is defined by whichever bundle loads first, so with two independent copies loaded side by side a type registered through one is found through the other; the built-in country is listed once; a name registered twice keeps the first; every registration is announced on window (dxm-poster-type-registered) and PosterSectionView re-resolves on it. Run the `check:poster-type-registry:self-test` script for the NEGATIVE test (a per-bundle registry fails)." diff --git a/plugin-designs/poster-sections/poster-sections.instances.json b/plugin-designs/poster-sections/poster-sections.instances.json index 38be95915..8f5b58f7a 100644 --- a/plugin-designs/poster-sections/poster-sections.instances.json +++ b/plugin-designs/poster-sections/poster-sections.instances.json @@ -10,14 +10,6 @@ "scope": "all" } }, - { - "id": "countries-africa", - "title": "Country posters — Africa", - "props": { - "type": "country", - "scope": "africa" - } - }, { "id": "countries-asia", "title": "Country posters — Asia", @@ -27,11 +19,11 @@ } }, { - "id": "countries-europe", - "title": "Country posters — Europe", + "id": "countries-middle-east", + "title": "Country posters — Middle East", "props": { "type": "country", - "scope": "europe" + "scope": "middle-east" } }, { @@ -43,11 +35,27 @@ } }, { - "id": "countries-middle-east", - "title": "Country posters — Middle East", + "id": "countries-africa", + "title": "Country posters — Africa", "props": { "type": "country", - "scope": "middle-east" + "scope": "africa" + } + }, + { + "id": "countries-europe", + "title": "Country posters — Europe", + "props": { + "type": "country", + "scope": "europe" + } + }, + { + "id": "countries-other", + "title": "Country posters — Other", + "props": { + "type": "country", + "scope": "other" } }, { @@ -66,14 +74,6 @@ "scope": "oceania" } }, - { - "id": "countries-other", - "title": "Country posters — Other", - "props": { - "type": "country", - "scope": "other" - } - }, { "id": "upg100-all", "title": "UPG 100 posters — all regions", diff --git a/plugin-designs/poster-sections/scripts/gen-presets.mjs b/plugin-designs/poster-sections/scripts/gen-presets.mjs new file mode 100644 index 000000000..944b79906 --- /dev/null +++ b/plugin-designs/poster-sections/scripts/gen-presets.mjs @@ -0,0 +1,42 @@ +#!/usr/bin/env node +// gen-presets.mjs (bun run gen:poster-sections-presets) — writes poster-sections.instances.json from each poster type's +// OWN regions: "-all" plus one preset per scope its adapter's scopes() returns, titled by the type's own +// (English) section title, then "configure". The same source check:poster-sections holds the file to, so when the +// data's regions change, running this is the whole fix. A type whose file is not on the tree yet keeps the presets it +// already has. +import { readFileSync, writeFileSync, existsSync } from 'node:fs' +import { join, dirname } from 'node:path' +import { fileURLToPath } from 'node:url' + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), '../../..') +const FILE = join(ROOT, 'plugin-designs/poster-sections/poster-sections.instances.json') +const TYPES = [ + { type: 'country', prefix: 'countries', noun: 'Country posters', file: 'library/components/poster/types/countryPosterType.js' }, + { type: 'upg100-list', prefix: 'upg100', noun: 'UPG 100 posters', file: 'plugin-designs/my-upg-100-list/data/upg100-poster-type.js' }, +] +const old = JSON.parse(readFileSync(FILE, 'utf8')) +const { createServer } = await import('vite') +const server = await createServer({ root: ROOT, configFile: false, logLevel: 'error', appType: 'custom', server: { middlewareMode: true, hmr: false, ws: false }, resolve: { alias: { '@map': join(ROOT, 'library') } } }) +// English from the real catalogue (library/i18n/locales/en/.json), so a title the type translates reads as the +// site's English; a key the catalogue lacks comes back as itself, which every adapter treats as "use the region name". +const english = (key) => { + const [area, ...parts] = String(key).split('.') + const f = join(ROOT, `library/i18n/locales/en/${area}.json`) + if (!parts.length || !existsSync(f)) return key + let o = JSON.parse(readFileSync(f, 'utf8')) + for (const p of parts) { if (!o || typeof o !== 'object' || !(p in o)) return key; o = o[p] } + return typeof o === 'string' ? o : key +} +const instances = [] +try { + for (const { type, prefix, noun, file } of TYPES) { + if (!existsSync(join(ROOT, file))) { instances.push(...old.instances.filter((i) => i.props && i.props.type === type)); continue } + const a = (await server.ssrLoadModule(join(ROOT, file))).default + instances.push({ id: `${prefix}-all`, title: `${noun} — all regions`, props: { type, scope: 'all' } }) + for (const scope of a.scopes()) instances.push({ id: `${prefix}-${scope}`, title: `${noun} — ${a.title(scope, english)}`, props: { type, scope } }) + } +} finally { await server.close() } +instances.push({ id: 'configure', title: 'Configure — make a new preset', props: { configure: true } }) +writeFileSync(FILE, JSON.stringify({ ...old, instances }, null, 2) + '\n') +const before = new Set(old.instances.map((i) => i.id)), after = new Set(instances.map((i) => i.id)) +console.log(`poster-sections presets: ${instances.length} (removed: ${[...before].filter((x) => !after.has(x)).join(', ') || 'none'}; added: ${[...after].filter((x) => !before.has(x)).join(', ') || 'none'})`) diff --git a/public/dx-maps/doxa-maps-spa/manifest.json b/public/dx-maps/doxa-maps-spa/manifest.json index 26b3f8f38..4d806c7dc 100644 --- a/public/dx-maps/doxa-maps-spa/manifest.json +++ b/public/dx-maps/doxa-maps-spa/manifest.json @@ -1218,21 +1218,6 @@ "iframe": "" } }, - { - "id": "countries-africa", - "title": "Country posters — Africa", - "apiBaseUrl": "", - "props": { - "profile": "poster-sections", - "type": "country", - "scope": "africa" - }, - "element": "poster-sections", - "iframeUrl": "./poster-sections/poster-sections/countries-africa/index.html", - "embed": { - "iframe": "" - } - }, { "id": "countries-asia", "title": "Country posters — Asia", @@ -1249,18 +1234,18 @@ } }, { - "id": "countries-europe", - "title": "Country posters — Europe", + "id": "countries-middle-east", + "title": "Country posters — Middle East", "apiBaseUrl": "", "props": { "profile": "poster-sections", "type": "country", - "scope": "europe" + "scope": "middle-east" }, "element": "poster-sections", - "iframeUrl": "./poster-sections/poster-sections/countries-europe/index.html", + "iframeUrl": "./poster-sections/poster-sections/countries-middle-east/index.html", "embed": { - "iframe": "" + "iframe": "" } }, { @@ -1279,18 +1264,48 @@ } }, { - "id": "countries-middle-east", - "title": "Country posters — Middle East", + "id": "countries-africa", + "title": "Country posters — Africa", "apiBaseUrl": "", "props": { "profile": "poster-sections", "type": "country", - "scope": "middle-east" + "scope": "africa" }, "element": "poster-sections", - "iframeUrl": "./poster-sections/poster-sections/countries-middle-east/index.html", + "iframeUrl": "./poster-sections/poster-sections/countries-africa/index.html", "embed": { - "iframe": "" + "iframe": "" + } + }, + { + "id": "countries-europe", + "title": "Country posters — Europe", + "apiBaseUrl": "", + "props": { + "profile": "poster-sections", + "type": "country", + "scope": "europe" + }, + "element": "poster-sections", + "iframeUrl": "./poster-sections/poster-sections/countries-europe/index.html", + "embed": { + "iframe": "" + } + }, + { + "id": "countries-other", + "title": "Country posters — Other", + "apiBaseUrl": "", + "props": { + "profile": "poster-sections", + "type": "country", + "scope": "other" + }, + "element": "poster-sections", + "iframeUrl": "./poster-sections/poster-sections/countries-other/index.html", + "embed": { + "iframe": "" } }, { @@ -1323,21 +1338,6 @@ "iframe": "" } }, - { - "id": "countries-other", - "title": "Country posters — Other", - "apiBaseUrl": "", - "props": { - "profile": "poster-sections", - "type": "country", - "scope": "other" - }, - "element": "poster-sections", - "iframeUrl": "./poster-sections/poster-sections/countries-other/index.html", - "embed": { - "iframe": "" - } - }, { "id": "upg100-all", "title": "UPG 100 posters — all regions", diff --git a/public/dx-maps/manifest.json b/public/dx-maps/manifest.json index 26b3f8f38..4d806c7dc 100644 --- a/public/dx-maps/manifest.json +++ b/public/dx-maps/manifest.json @@ -1218,21 +1218,6 @@ "iframe": "" } }, - { - "id": "countries-africa", - "title": "Country posters — Africa", - "apiBaseUrl": "", - "props": { - "profile": "poster-sections", - "type": "country", - "scope": "africa" - }, - "element": "poster-sections", - "iframeUrl": "./poster-sections/poster-sections/countries-africa/index.html", - "embed": { - "iframe": "" - } - }, { "id": "countries-asia", "title": "Country posters — Asia", @@ -1249,18 +1234,18 @@ } }, { - "id": "countries-europe", - "title": "Country posters — Europe", + "id": "countries-middle-east", + "title": "Country posters — Middle East", "apiBaseUrl": "", "props": { "profile": "poster-sections", "type": "country", - "scope": "europe" + "scope": "middle-east" }, "element": "poster-sections", - "iframeUrl": "./poster-sections/poster-sections/countries-europe/index.html", + "iframeUrl": "./poster-sections/poster-sections/countries-middle-east/index.html", "embed": { - "iframe": "" + "iframe": "" } }, { @@ -1279,18 +1264,48 @@ } }, { - "id": "countries-middle-east", - "title": "Country posters — Middle East", + "id": "countries-africa", + "title": "Country posters — Africa", "apiBaseUrl": "", "props": { "profile": "poster-sections", "type": "country", - "scope": "middle-east" + "scope": "africa" }, "element": "poster-sections", - "iframeUrl": "./poster-sections/poster-sections/countries-middle-east/index.html", + "iframeUrl": "./poster-sections/poster-sections/countries-africa/index.html", "embed": { - "iframe": "" + "iframe": "" + } + }, + { + "id": "countries-europe", + "title": "Country posters — Europe", + "apiBaseUrl": "", + "props": { + "profile": "poster-sections", + "type": "country", + "scope": "europe" + }, + "element": "poster-sections", + "iframeUrl": "./poster-sections/poster-sections/countries-europe/index.html", + "embed": { + "iframe": "" + } + }, + { + "id": "countries-other", + "title": "Country posters — Other", + "apiBaseUrl": "", + "props": { + "profile": "poster-sections", + "type": "country", + "scope": "other" + }, + "element": "poster-sections", + "iframeUrl": "./poster-sections/poster-sections/countries-other/index.html", + "embed": { + "iframe": "" } }, { @@ -1323,21 +1338,6 @@ "iframe": "" } }, - { - "id": "countries-other", - "title": "Country posters — Other", - "apiBaseUrl": "", - "props": { - "profile": "poster-sections", - "type": "country", - "scope": "other" - }, - "element": "poster-sections", - "iframeUrl": "./poster-sections/poster-sections/countries-other/index.html", - "embed": { - "iframe": "" - } - }, { "id": "upg100-all", "title": "UPG 100 posters — all regions",