Reference the chevron once, the way their markup references it

Their chevron is a single <use href="/assets/icons/arrow-chevron.svg#chevron-up">.
We had copied its path into three call sites and never vendored the file.

I assumed the platform forced that, and it does not: an external
<use href="file.svg#id"> renders in Chromium, renders inside a shadow root,
and a local <symbol> plus <use href="#id"> renders too — 410x234 in all
three. What is forced is the external href, not the mechanism. A dropped
bundle resolves assets against whatever tree it sits in and the tree
generator stages an allowlist with no icons directory, so an external
reference would 404 in silence and the chevron would simply be absent. That
is the same reason worldmap.svg arrives through a prop. So: their path,
verbatim, as one <symbol>, referenced the way they reference it.

The first attempt blanked all 21 chevrons — the regex rewrote the path inside
the sprite it had just inserted, so the symbol referenced itself. Worth
recording how that was caught, because the CSS fingerprint called the broken
page identical: a <use> resolving nothing keeps exactly the same computed
styles. Geometry caught it, and so did looking at the page. The fingerprint
now says so in its own header, along with the fact that its keys are
ordinal-sensitive for unclassed elements.
This commit is contained in:
doxa-maps-88655c70 2026-09-24 13:48:54 +00:00
parent c4a6d628b4
commit 5000355237
7 changed files with 67 additions and 47 deletions

View file

@ -476,6 +476,26 @@ useShadowStyles(
<template>
<div class="rl-root" :dir="isRTL ? 'rtl' : 'ltr'">
<!-- THEIR ICON, DELIVERED THE WAY THEIR MARKUP DELIVERS IT. Theirs is
<svg class="icon | rotate-90 right"><use href="/assets/icons/arrow-chevron.svg#chevron-up"/></svg>
— one <use> reference, not a path repeated per call site.
MEASURED BEFORE CHOOSING, because I assumed the platform forced the inline copy and it
does not: an external <use href="file.svg#id"> renders in Chromium, renders INSIDE a
shadow root, and a local <symbol> + <use href="#id"> renders too — bbox 410x234 in all
three cases.
WHAT IS ACTUALLY FORCED IS THE EXTERNAL HREF, not the mechanism. A dropped bundle
resolves assets against whatever tree it sits in, and generate-tree stages an allowlist
with no icons/ dir, so an external href would 404 SILENTLY and the chevron would simply
vanish. Same reason worldmap.svg arrives through an imagesBase prop instead of their bare
`const imagesUrl = '/assets/images'`.
So: their 454-byte file's path verbatim, as a <symbol> declared ONCE, referenced by
<use href="#chevron-up"> exactly as their markup does. No external fetch, and the path is
no longer copied three times. -->
<svg width="0" height="0" aria-hidden="true" focusable="false" style="position:absolute">
<symbol id="chevron-up" viewBox="0 0 489.67 289.877">
<path d="M439.017,211.678L263.258,35.919c-3.9-3.9-8.635-6.454-13.63-7.665-9.539-2.376-20.051.161-27.509,7.619L46.361,211.632c-11.311,11.311-11.311,29.65,0,40.961h0c11.311,11.311,29.65,11.311,40.961,0L242.667,97.248l155.39,155.39c11.311,11.311,29.65,11.311,40.961,0h0c11.311-11.311,11.311-29.65,0-40.961Z" />
</symbol>
</svg>
<div class="rl-scroll">
<!-- pages/regions/index.vue:47-58 — their centred head: the title with its last word
in brand primary, and the strapline underneath. -->
@ -507,7 +527,7 @@ useShadowStyles(
>
{{ region.label || 'Other' }}
<svg class="region-card__icon" viewBox="0 0 489.67 289.877" aria-hidden="true">
<path d="M439.017,211.678L263.258,35.919c-3.9-3.9-8.635-6.454-13.63-7.665-9.539-2.376-20.051.161-27.509,7.619L46.361,211.632c-11.311,11.311-11.311,29.65,0,40.961h0c11.311,11.311,29.65,11.311,40.961,0L242.667,97.248l155.39,155.39c11.311,11.311,29.65,11.311,40.961,0h0c11.311-11.311,11.311-29.65,0-40.961Z" />
<use href="#chevron-up" />
</svg>
</button>
</h2>
@ -534,7 +554,7 @@ useShadowStyles(
>
{{ dashboardLink(region) }}
<svg class="region-card__icon" viewBox="0 0 489.67 289.877" aria-hidden="true">
<path d="M439.017,211.678L263.258,35.919c-3.9-3.9-8.635-6.454-13.63-7.665-9.539-2.376-20.051.161-27.509,7.619L46.361,211.632c-11.311,11.311-11.311,29.65,0,40.961h0c11.311,11.311,29.65,11.311,40.961,0L242.667,97.248l155.39,155.39c11.311,11.311,29.65,11.311,40.961,0h0c11.311-11.311,11.311-29.65,0-40.961Z" />
<use href="#chevron-up" />
</svg>
</button>
</p>
@ -560,7 +580,7 @@ useShadowStyles(
viewBox="0 0 489.67 289.877"
aria-hidden="true"
>
<path d="M439.017,211.678L263.258,35.919c-3.9-3.9-8.635-6.454-13.63-7.665-9.539-2.376-20.051.161-27.509,7.619L46.361,211.632c-11.311,11.311-11.311,29.65,0,40.961h0c11.311,11.311,29.65,11.311,40.961,0L242.667,97.248l155.39,155.39c11.311,11.311,29.65,11.311,40.961,0h0c11.311-11.311,11.311-29.65,0-40.961Z" />
<use href="#chevron-up" />
</svg>
</button>
</p>

File diff suppressed because one or more lines are too long

View file

@ -856,7 +856,7 @@
"bundle": "regions-dashboard",
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"output": "doxa-maps/regions-dashboard/regions-dashboard.js",
"integrity": "sha384-ytQtETEeE4XyDOiMQwksdiiRD6dD55yw+8DO3Xqk0fCfQkpjjNPvA0DTdtMMIFQo",
"integrity": "sha384-gdsNwbs4RZH3pLoW4Q7VYk3IzEL0BOAzNqmjVCQY1WfgvXCx6oPhZBs3nnE9bXQ/",
"elements": [
"regions-dashboard"
],
@ -876,7 +876,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./regions-dashboard/region-dashboards/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-ytQtETEeE4XyDOiMQwksdiiRD6dD55yw+8DO3Xqk0fCfQkpjjNPvA0DTdtMMIFQo\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-gdsNwbs4RZH3pLoW4Q7VYk3IzEL0BOAzNqmjVCQY1WfgvXCx6oPhZBs3nnE9bXQ/\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
}
},
{
@ -890,7 +890,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./regions-dashboard/regions-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-ytQtETEeE4XyDOiMQwksdiiRD6dD55yw+8DO3Xqk0fCfQkpjjNPvA0DTdtMMIFQo\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-gdsNwbs4RZH3pLoW4Q7VYk3IzEL0BOAzNqmjVCQY1WfgvXCx6oPhZBs3nnE9bXQ/\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
}
},
{
@ -904,7 +904,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./regions-dashboard/regions-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-ytQtETEeE4XyDOiMQwksdiiRD6dD55yw+8DO3Xqk0fCfQkpjjNPvA0DTdtMMIFQo\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-gdsNwbs4RZH3pLoW4Q7VYk3IzEL0BOAzNqmjVCQY1WfgvXCx6oPhZBs3nnE9bXQ/\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
}
}
]

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
<script src="../regions-dashboard.js" integrity="sha384-ytQtETEeE4XyDOiMQwksdiiRD6dD55yw+8DO3Xqk0fCfQkpjjNPvA0DTdtMMIFQo" crossorigin="anonymous"></script>
<script src="../regions-dashboard.js" integrity="sha384-gdsNwbs4RZH3pLoW4Q7VYk3IzEL0BOAzNqmjVCQY1WfgvXCx6oPhZBs3nnE9bXQ/" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
<script src="../regions-dashboard.js" integrity="sha384-ytQtETEeE4XyDOiMQwksdiiRD6dD55yw+8DO3Xqk0fCfQkpjjNPvA0DTdtMMIFQo" crossorigin="anonymous"></script>
<script src="../regions-dashboard.js" integrity="sha384-gdsNwbs4RZH3pLoW4Q7VYk3IzEL0BOAzNqmjVCQY1WfgvXCx6oPhZBs3nnE9bXQ/" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -40,7 +40,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
<script src="../regions-dashboard.js" integrity="sha384-ytQtETEeE4XyDOiMQwksdiiRD6dD55yw+8DO3Xqk0fCfQkpjjNPvA0DTdtMMIFQo" crossorigin="anonymous"></script>
<script src="../regions-dashboard.js" integrity="sha384-gdsNwbs4RZH3pLoW4Q7VYk3IzEL0BOAzNqmjVCQY1WfgvXCx6oPhZBs3nnE9bXQ/" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order: