Numerals: Eastern (۱۲۳) or Western (123) in the display settings; the server sends pages with the chosen digits (scripts and styles untouched) and script-drawn numbers follow. Settings button lines up with the other icons
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e04ed0d4af
commit
3305a514ba
@ -29,6 +29,7 @@ import Icon from '../components/Icon.astro';
|
||||
if (t) document.documentElement.dataset.theme = t;
|
||||
const pal = localStorage.getItem('divan-palette'); // sepia when unset
|
||||
if (pal) document.documentElement.dataset.palette = pal;
|
||||
if (document.cookie.includes('divan-digits=latn')) document.documentElement.dataset.digits = 'latn'; // Western numerals
|
||||
} catch (e) {}
|
||||
</script>
|
||||
</head>
|
||||
@ -66,6 +67,8 @@ import Icon from '../components/Icon.astro';
|
||||
<button type="button" data-palette={v} title={name} aria-label={name} style={`--a: ${a}; --b: ${b}`}><span></span>{name}</button>
|
||||
))}
|
||||
</div>
|
||||
<p>ہندسے</p>
|
||||
<div class="seg"><button type="button" data-digits="">۱۲۳ مشرقی</button><button type="button" data-digits="latn">123 مغربی</button></div>
|
||||
<p>روشنی</p>
|
||||
<div class="seg">
|
||||
<button type="button" data-theme-pick="light"><Icon name="sun" size={16} /> روشن</button>
|
||||
@ -122,15 +125,32 @@ import Icon from '../components/Icon.astro';
|
||||
panel.querySelectorAll('[data-font]').forEach((b) => b.setAttribute('aria-pressed', String(b.dataset.font === on.font)));
|
||||
panel.querySelectorAll('[data-palette]').forEach((b) => b.setAttribute('aria-pressed', String(b.dataset.palette === on.palette)));
|
||||
panel.querySelectorAll('[data-theme-pick]').forEach((b) => b.setAttribute('aria-pressed', String(b.dataset.themePick === on.theme)));
|
||||
panel.querySelectorAll('[data-digits]').forEach((b) => b.setAttribute('aria-pressed', String(b.dataset.digits === (root.dataset.digits ?? ''))));
|
||||
};
|
||||
panel.addEventListener('click', (e) => {
|
||||
const b = e.target.closest('button'); if (!b) return;
|
||||
if (b.dataset.font) { root.classList.toggle('nastaliq', b.dataset.font === 'nastaliq'); store('divan-font', b.dataset.font); }
|
||||
if (b.dataset.palette != null) { if (b.dataset.palette) root.dataset.palette = b.dataset.palette; else delete root.dataset.palette; store('divan-palette', b.dataset.palette); }
|
||||
if (b.dataset.digits != null) {
|
||||
// numerals: a cookie, so the server sends pages with them; switching back to Eastern reloads the page
|
||||
document.cookie = `divan-digits=${b.dataset.digits}; path=/; max-age=${b.dataset.digits ? 31536000 : 0}; samesite=lax`;
|
||||
if (!b.dataset.digits) { delete root.dataset.digits; location.reload(); return; }
|
||||
root.dataset.digits = 'latn'; westernDigits(document.body);
|
||||
}
|
||||
if (b.dataset.themePick != null) { if (b.dataset.themePick) root.dataset.theme = b.dataset.themePick; else delete root.dataset.theme; store('divan-theme', b.dataset.themePick); }
|
||||
marks();
|
||||
|
||||
});
|
||||
document.addEventListener('click', (e) => { if (panel.open && !panel.contains(e.target)) panel.open = false; }); // close when clicking elsewhere
|
||||
// Western numerals also in what scripts add later (word sidebar, page numbers, suggestions)
|
||||
function westernDigits(node) {
|
||||
const walk = document.createTreeWalker(node, NodeFilter.SHOW_TEXT);
|
||||
for (let t = walk.nextNode(); t; t = walk.nextNode()) if (/[۰-۹]/.test(t.data)) t.data = t.data.replace(/[۰-۹]/g, (d) => String(d.charCodeAt(0) - 0x6f0));
|
||||
}
|
||||
new MutationObserver((list) => {
|
||||
if (root.dataset.digits !== 'latn') return;
|
||||
for (const m of list) for (const n of m.addedNodes) n.nodeType === 3 ? westernDigits(n.parentNode) : n.nodeType === 1 && westernDigits(n);
|
||||
}).observe(document.body, { childList: true, subtree: true });
|
||||
marks();
|
||||
// Urdu on-screen keyboard, Gboard/Windows Urdu layout
|
||||
const BASE = [[...'طصھدٹپتبجح'], [...'مورنلہاکی'], [...'قفےسشغع']];
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
// The signed-in reader (or null) for every page, from the session cookie
|
||||
// The signed-in reader (or null) for every page, from the session cookie; and the reader's numerals: pages are
|
||||
// written with Eastern Arabic (Urdu) digits, and a reader who chose Western digits (cookie divan-digits=latn, set in
|
||||
// the display settings) gets them in the page as sent, so nothing flashes
|
||||
import { defineMiddleware } from 'astro:middleware';
|
||||
import { auth, COOKIE } from './lib/auth';
|
||||
|
||||
@ -10,5 +12,11 @@ export const onRequest = defineMiddleware(async (ctx, next) => {
|
||||
if (r.ok) ctx.locals.user = r.data.user;
|
||||
else if (r.status === 401) ctx.cookies.delete(COOKIE, { path: '/' }); // expired or signed out elsewhere
|
||||
}
|
||||
return next();
|
||||
const res = await next();
|
||||
if (ctx.cookies.get('divan-digits')?.value !== 'latn' || !res.headers.get('content-type')?.includes('text/html')) return res;
|
||||
// text only: scripts and styles are left alone (the page's own scripts look for Eastern digits)
|
||||
const html = (await res.text()).split(/(<script[\s\S]*?<\/script>|<style[\s\S]*?<\/style>)/)
|
||||
.map((part, i) => (i % 2 ? part : part.replace(/[۰-۹]/g, (d) => String(d.charCodeAt(0) - 0x6f0)))).join('');
|
||||
const headers = new Headers(res.headers); headers.delete('content-length');
|
||||
return new Response(html, { status: res.status, statusText: res.statusText, headers });
|
||||
});
|
||||
|
||||
@ -496,7 +496,7 @@ h1 + .muted { text-align: center; margin-top: 0; }
|
||||
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
||||
.icon-btn.small { width: 30px; height: 30px; }
|
||||
/* display settings in the header: a button and its panel (font, palette swatches, light/dark/automatic) */
|
||||
.display-menu { position: relative; }
|
||||
.display-menu { position: relative; display: flex; } /* no line box: lines up with the other header icons */
|
||||
.display-menu > summary { list-style: none; }
|
||||
.display-menu > summary::-webkit-details-marker { display: none; }
|
||||
.display-menu[open] > summary { border-color: var(--brand); color: var(--brand); }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user