Share this page never copies a token; neutral wording in the P3 comments

pageLink() drops ?tk= from the page's address: a leaf page reads a token from
there and leaves it in place, so pressing Share would have sent it. The URL is
rewritten only when tk is present; every other link is the address as it stands.
The comments name the page, not who measured it, and no longer cite a request.
check:map-menu-anchor strips a same-line comment before testing each return, so
a fallback named only in a comment no longer passes.
This commit is contained in:
Doxa Maps 2026-10-03 06:18:57 +00:00
parent ac71afaf55
commit c21bcd2e13
4 changed files with 18 additions and 8 deletions

View file

@ -68,9 +68,9 @@ const areas = readdirSync(join(ROOT, 'en')).filter((f) => f.endsWith('.json'))
// translations, add the locale here with its count and lower it as they arrive. // translations, add the locale here with its count and lower it as they arrive.
// Never raise a number; never add a locale that is already complete. // Never raise a number; never add a locale that is already complete.
const DEBT = { const DEBT = {
// 2026-10-03, the Share menu's 10 new share.json keys (shareable pages P3), English only for now: the Driver // 2026-10-03, the Share menu's 10 new share.json keys (shareable pages P3): localization is English-only for now.
// parked localization ("just English for now"). tStatic falls back to the English text, so these locales show // tStatic falls back to the English text, so these locales show English until the translations arrive;
// English until the translations arrive; lower each to 0 then, and empty the map again. // lower each to 0 then, and empty the map again.
ar: 10, de: 10, es: 10, fr: 10, hi: 10, it: 10, pt: 10, ro: 10, ru: 10, zh: 10, ar: 10, de: 10, es: 10, fr: 10, hi: 10, it: 10, pt: 10, ro: 10, ru: 10, zh: 10,
} }

View file

@ -46,7 +46,8 @@ if (!m) {
if (fn) { if (fn) {
const body = code.match(new RegExp('function\\s+' + fn[1] + '\\s*\\(\\)\\s*\\{([\\s\\S]*?)\\n\\}')) const body = code.match(new RegExp('function\\s+' + fn[1] + '\\s*\\(\\)\\s*\\{([\\s\\S]*?)\\n\\}'))
// every return that resolves a named area must carry its structural fallback on the SAME expression // every return that resolves a named area must carry its structural fallback on the SAME expression
const rets = body ? [...body[1].matchAll(/return\s+([^\n]*closest\([^\n]*)/g)].map((r) => r[1]) : [] // a same-line comment is not a fallback: strip `//…` before testing each return
const rets = body ? [...body[1].matchAll(/return\s+([^\n]*closest\([^\n]*)/g)].map((r) => r[1].replace(/\s*\/\/.*$/, '')) : []
expr = rets.length && rets.every((r) => /offsetParent|parentElement|document\.body/.test(r)) ? rets.join(' ;; ') : (rets.find((r) => !/offsetParent|parentElement|document\.body/.test(r)) || '') expr = rets.length && rets.every((r) => /offsetParent|parentElement|document\.body/.test(r)) ? rets.join(' ;; ') : (rets.find((r) => !/offsetParent|parentElement|document\.body/.test(r)) || '')
if (!body) fails.push(`the area resolution calls ${fn[1]}(), and this gate cannot find that function to read it.`) if (!body) fails.push(`the area resolution calls ${fn[1]}(), and this gate cannot find that function to read it.`)
else if (!rets.length) fails.push(`${fn[1]}() returns no named-area resolution, so this gate would pass blind.`) else if (!rets.length) fails.push(`${fn[1]}() returns no named-area resolution, so this gate would pass blind.`)

View file

@ -129,7 +129,7 @@ function place() {
// ★ THE BLOCK THAT CONTAINS IT IS MEASURED, NOT ASSUMED. The menu is position:absolute, so its coordinates are // ★ THE BLOCK THAT CONTAINS IT IS MEASURED, NOT ASSUMED. The menu is position:absolute, so its coordinates are
// relative to its containing block, which the HOST's markup decides: an unpositioned wrapper hands it to the // relative to its containing block, which the HOST's markup decides: an unpositioned wrapper hands it to the
// header above. Measuring against one element and positioning against another is what sent the header menu far // header above. Measuring against one element and positioning against another is what sent the header menu far
// to the left (upg100, 2026-10-03). So the target point is computed in viewport coordinates and converted into // to the left (the UPG-100 list page, 2026-10-03). So the target point is computed in viewport coordinates and converted into
// the containing block's own (its padding edge, scrolled), whatever element that turns out to be. // the containing block's own (its padding edge, scrolled), whatever element that turns out to be.
function placeBeside(tb) { function placeBeside(tb) {
const vw = document.documentElement.clientWidth || window.innerWidth || 1024 const vw = document.documentElement.clientWidth || window.innerWidth || 1024

View file

@ -411,8 +411,17 @@ function pageOwner() {
} }
return false return false
} }
// A leaf page reads a token from ?tk= and leaves it in its address, so the page link drops it: a reader must
// never send a credential by pressing Share. The URL is rewritten only when tk is there, so every other link is
// the address exactly as it stands.
function pageLink() { function pageLink() {
try { if (pageOwner() && window.location.href) return window.location.href } catch { /* no window */ } try {
if (pageOwner() && window.location.href) {
const u = new URL(window.location.href)
if (u.searchParams.has('tk')) { u.searchParams.delete('tk'); return u.href }
return window.location.href
}
} catch { /* no window */ }
return shareUrl.value return shareUrl.value
} }
@ -518,9 +527,9 @@ const hasOwnAnchor = !providedToolbar
★ THE ANCHOR IS THE BUTTON, AND NOTHING IS DECIDED AT RENDER TIME (shareable pages P3). This used to tag ★ THE ANCHOR IS THE BUTTON, AND NOTHING IS DECIDED AT RENDER TIME (shareable pages P3). This used to tag
`el.offsetParent || el.parentElement` as the menu's area DURING RENDER (a function ref, so it ran before `el.offsetParent || el.parentElement` as the menu's area DURING RENDER (a function ref, so it ran before
MapControlMenu latched its area). Before layout offsetParent is null, so the tag fell on the button's MapControlMenu latched its area). Before layout offsetParent is null, so the tag fell on the button's
immediate parent: in a header with a narrow, unpositioned wrapper (upg100 measured .hdr-btns) the menu immediate parent: in a header with a narrow, unpositioned wrapper (measured on the UPG-100 list page: .hdr-btns) the menu
measured against that wrapper, clamped to its 200px floor, and was positioned against the header above measured against that wrapper, clamped to its 200px floor, and was positioned against the header above
it: far to the left, and narrow (the Driver's report, 2026-10-03). Now the button only names itself; it: far to the left, and narrow (reported 2026-10-03). Now the button only names itself;
MapControlMenu resolves where the menu lives and where it goes when it OPENS, with layout known. MapControlMenu resolves where the menu lives and where it goes when it OPENS, with layout known.
*/ */
function bindAnchor(el) { function bindAnchor(el) {