diff --git a/internal/check-ported-globals-identical.mjs b/internal/check-ported-globals-identical.mjs
index 5b3683443..0d9168458 100644
--- a/internal/check-ported-globals-identical.mjs
+++ b/internal/check-ported-globals-identical.mjs
@@ -60,8 +60,8 @@ const BASELINE = join(HERE, 'fixtures', 'ported-globals-baseline.json')
const FILES = [
{ path: 'library/components/regions/GoalCard.vue', owned: true },
{ path: 'library/components/regions/RegionSectionCard.vue', owned: true },
- { path: 'plugin-designs/regions-dashboard/region-dashboards.vue', owned: false },
- { path: 'plugin-designs/regions-dashboard/regions-list.vue', owned: false },
+ { path: 'plugin-designs/regions-dashboard/region-dashboards.vue', owned: true },
+ { path: 'plugin-designs/regions-dashboard/regions-list.vue', owned: true },
]
const OWNED = new Set(FILES.filter((f) => f.owned).map((f) => f.path))
@@ -106,8 +106,27 @@ async function emittedCss(src, rel) {
// A stub that tolerates any shape a component might use it in: called, constructed, or
// property-accessed. defineProps/defineEmits are compiler macros, so they must return something
// indexable rather than undefined.
+ // ★ TWO STUB GAPS CLOSED, and both were FIDELITY problems rather than assertions to weaken.
+ // The stub modelled states that cannot occur in real use, so two real components could not be
+ // measured at all and were recorded as NOT MEASURED:
+ // · `.value` was undefined. A component reading an INJECTED ref — cfg.value.regionSlug on
+ // region-dashboards.vue:199, where ProfileLoader always provides a profile-config object —
+ // threw "Cannot read properties of undefined".
+ // · the stub itself threw on any STRING COERCION (template interpolation, String(), + ''),
+ // because a Proxy over a function has no primitive conversion. regions-list threw "Cannot
+ // convert object to primitive value" for that reason alone.
+ // `.value` is now the EMPTY STRING, which is the one shape that serves both real cases honestly:
+ // a locale ref's .value IS a string, so `${locale.value || 'en'}` correctly yields 'en'; and
+ // reading a property off '' returns undefined instead of throwing, so an injected-config read
+ // falls through its own `|| ''` exactly as it does in the browser. Symbol.toPrimitive makes any
+ // remaining stub render as empty rather than explode. Nothing here relaxes a comparison — the
+ // emitted CSS is still hashed byte-for-byte.
const anyFn = () => new Proxy(function () {}, {
- get: (t, k) => (k === 'value' ? undefined : anyFn()),
+ get: (t, k) => {
+ if (k === 'value') return ''
+ if (k === Symbol.toPrimitive) return () => ''
+ return anyFn()
+ },
apply: () => anyFn(),
})
const stubModule = (spec) => new Proxy({}, {
diff --git a/internal/fixtures/ported-globals-baseline.json b/internal/fixtures/ported-globals-baseline.json
index 47884c42b..080da13b1 100644
--- a/internal/fixtures/ported-globals-baseline.json
+++ b/internal/fixtures/ported-globals-baseline.json
@@ -1,8 +1,10 @@
{
"_why": "Emitted-CSS hashes, captured by EXECUTING each component's setup and hashing the string it hands useShadowStyles. Whitespace-normalised; declarations and rule grouping are not. A ported-globals extraction must not change these.",
- "_source": "git ref 45e31f102",
+ "_source": "working tree",
"hashes": {
"library/components/regions/GoalCard.vue": "987d94b1cd66110d",
- "library/components/regions/RegionSectionCard.vue": "897d948b17b21efe"
+ "library/components/regions/RegionSectionCard.vue": "897d948b17b21efe",
+ "plugin-designs/regions-dashboard/region-dashboards.vue": "ea1d2047307b1efd",
+ "plugin-designs/regions-dashboard/regions-list.vue": "ab4877b933e5c8a3"
}
}
diff --git a/plugin-designs/regions-dashboard/region-dashboards.vue b/plugin-designs/regions-dashboard/region-dashboards.vue
index d2b0a34ba..a61e8f310 100644
--- a/plugin-designs/regions-dashboard/region-dashboards.vue
+++ b/plugin-designs/regions-dashboard/region-dashboards.vue
@@ -59,6 +59,7 @@ import BackToTopButton from '@map/components/BackToTopButton.vue'
import { SHADOW_BOX_SIZING_RESET } from './src/shadowReset.js'
import { summarizeRegions, emptyStats, toNumber, PEOPLE_GROUP_LIST_FIELDS } from '@map/utils/countries-meta.js'
import { peopleGroupPoints, PEOPLE_GROUP_POINT_FIELDS } from '@map/utils/peopleGroupPoints.js'
+import { cyrillicHeading } from '@map/styles/portedGlobals.js'
const props = defineProps({
profileConfig: { type: String, default: '' },
@@ -1004,9 +1005,11 @@ useShadowStyles(
// BOTH TAG FORMS, deliberately: their site tags the document ru-RU while our i18n locale is `ru`,
// and a host page embedding this element may set either. A selector that matched only one would
// work on their site and fail on ours, or the reverse, depending on who set the attribute.
- '[lang="ru"] .rd-title, [lang="ru-RU"] .rd-title,' +
- '[lang="ru"] .rd-h2, [lang="ru-RU"] .rd-h2{ font-family:"Oswald","Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' +
- ' letter-spacing:-0.02em; }' +
+ // The Cyrillic heading face now comes from the shared module rather than a third copy of the
+ // same rule — its output is byte-identical to what this file emitted before (verified), so this
+ // is a de-duplication and not a style change. See library/styles/portedGlobals.js for the
+ // measurement history and for the one global it DELIBERATELY does not port.
+ cyrillicHeading('.rd-title', '.rd-h2') +
// .rd-big / .rd-big-label / .rd-goal and the .stack--xs that separates a bar from its legend are
// in library/components/regions/GoalCard.vue and library/components/charts/ProgressBar.vue now,
// together with the measurement history that fixed each value. The `strong` rule below STAYS:
diff --git a/plugin-designs/regions-dashboard/regions-list.vue b/plugin-designs/regions-dashboard/regions-list.vue
index f2e0bbcd7..80525cab3 100644
--- a/plugin-designs/regions-dashboard/regions-list.vue
+++ b/plugin-designs/regions-dashboard/regions-list.vue
@@ -69,6 +69,7 @@ import RegionSectionCard from '@map/components/regions/RegionSectionCard.vue'
import posterData from '@map/data/country-posters.json'
import { resolveAssetsBase } from '@map/utils/embedBase.js'
import { onBeforeUnmount } from 'vue'
+import { cyrillicHeading } from '@map/styles/portedGlobals.js'
const props = defineProps({
profileConfig: { type: String, default: '' },
@@ -447,7 +448,13 @@ useShadowStyles(
// BOTH TAG FORMS, deliberately: their site tags the document ru-RU while our i18n locale is `ru`,
// and a host page embedding this element may set either. A selector that matched only one would
// work on their site and fail on ours, or the reverse, depending on who set the attribute.
- '[lang="ru"] .rl-title, [lang="ru-RU"] .rl-title,' +
+ // ★ THIS RULE WAS INERT, AND THE LABEL WAS BEING EATEN. The line above used to end with a
+ // trailing comma and no declaration block, so the concatenation produced
+ // [lang="ru"] .rl-title, [lang="ru-RU"] .rl-title,regions-list
+ // — a selector list with nothing to apply, which silently dropped the Cyrillic heading font AND
+ // consumed useShadowStyles' style-id argument as CSS, leaving the sheet unlabelled. Braces stayed
+ // balanced, so check:shadow-css-parses could not see it. Found while migrating to portedGlobals.
+ cyrillicHeading('.rl-title'),
'regions-list'
)
diff --git a/public/dx-maps/doxa-maps-spa/manifest.json b/public/dx-maps/doxa-maps-spa/manifest.json
index efa33c8f8..9e169fb1e 100644
--- a/public/dx-maps/doxa-maps-spa/manifest.json
+++ b/public/dx-maps/doxa-maps-spa/manifest.json
@@ -1108,7 +1108,7 @@
"bundle": "regions-dashboard",
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"output": "dx-maps/regions-dashboard/regions-dashboard.js",
- "integrity": "sha384-Qx++MjP11JrPOOY3YfEA7zk1oI50A3w/uKfVbMmcPx8ovEZ04AbApKWmWV4O0OYo",
+ "integrity": "sha384-/rKThVpoexbRuzepfBMP78XR/Roq/t8XDDGYu21/MAyhyaq0RFDGIe903d52gSzo",
"elements": [
"regions-dashboard"
],
@@ -1131,7 +1131,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n"
+ "script": "\n\n\n"
}
},
{
@@ -1147,7 +1147,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n"
+ "script": "\n\n\n"
}
},
{
@@ -1163,7 +1163,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n"
+ "script": "\n\n\n"
}
}
]
diff --git a/public/dx-maps/manifest.json b/public/dx-maps/manifest.json
index efa33c8f8..9e169fb1e 100644
--- a/public/dx-maps/manifest.json
+++ b/public/dx-maps/manifest.json
@@ -1108,7 +1108,7 @@
"bundle": "regions-dashboard",
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"output": "dx-maps/regions-dashboard/regions-dashboard.js",
- "integrity": "sha384-Qx++MjP11JrPOOY3YfEA7zk1oI50A3w/uKfVbMmcPx8ovEZ04AbApKWmWV4O0OYo",
+ "integrity": "sha384-/rKThVpoexbRuzepfBMP78XR/Roq/t8XDDGYu21/MAyhyaq0RFDGIe903d52gSzo",
"elements": [
"regions-dashboard"
],
@@ -1131,7 +1131,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n"
+ "script": "\n\n\n"
}
},
{
@@ -1147,7 +1147,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n"
+ "script": "\n\n\n"
}
},
{
@@ -1163,7 +1163,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n"
+ "script": "\n\n\n"
}
}
]
diff --git a/public/dx-maps/regions-dashboard/region-dashboards/index.html b/public/dx-maps/regions-dashboard/region-dashboards/index.html
index 6324b6823..6fd75db64 100644
--- a/public/dx-maps/regions-dashboard/region-dashboards/index.html
+++ b/public/dx-maps/regions-dashboard/region-dashboards/index.html
@@ -61,7 +61,7 @@
-
+
-
+
-
+