diff --git a/client/src/components/Studio/bookFontWarm.ts b/client/src/components/Studio/bookFontWarm.ts index 33fa18345..f727b7482 100644 --- a/client/src/components/Studio/bookFontWarm.ts +++ b/client/src/components/Studio/bookFontWarm.ts @@ -53,9 +53,12 @@ export async function warmBookFaces( * Warms the faces of the book the Studio holds whenever the set of faces it * uses changes; typing into a text does not, so an edit costs nothing here. */ +/** A key compares by code units: the same faces give the same key whatever the locale. */ +const byCodeUnits = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0); + export function useWarmBookFaces(): void { const doc = useStudioStore((s) => s.doc); - const key = useMemo(() => (doc ? bookFacesUsed(doc).map(faceSpec).sort().join('|') : ''), [doc]); + const key = useMemo(() => (doc ? bookFacesUsed(doc).map(faceSpec).sort(byCodeUnits).join('|') : ''), [doc]); useEffect(() => { const current = useStudioStore.getState().doc; // A face that will not load is drawn in its fallback, which the picker already shows; nothing to tell anyone. diff --git a/client/src/components/Studio/snapshotFonts.ts b/client/src/components/Studio/snapshotFonts.ts index f2c67ccd4..56adc020f 100644 --- a/client/src/components/Studio/snapshotFonts.ts +++ b/client/src/components/Studio/snapshotFonts.ts @@ -120,8 +120,9 @@ export function pickFaceRules(rules: readonly FaceRule[], uses: FaceUses): FaceR const slanted = ofFamily.filter((r) => r.italic === (italicText === 'true')); const styled = slanted.length ? slanted : ofFamily.filter((r) => !r.italic); if (!styled.length) continue; - const nearest = styled.reduce((best, r) => - Math.abs(r.weight - weight) < Math.abs(best.weight - weight) ? r : best + const nearest = styled.reduce( + (best, r) => (Math.abs(r.weight - weight) < Math.abs(best.weight - weight) ? r : best), + styled[0] ).weight; for (const rule of styled) { if (rule.weight === nearest && coversAny(rule.unicodeRange, chars)) picked.set(rule.url, rule); diff --git a/client/src/components/Tours/planner/roundHikeRouting.ts b/client/src/components/Tours/planner/roundHikeRouting.ts index b2a1cdad3..39b2fea4a 100644 --- a/client/src/components/Tours/planner/roundHikeRouting.ts +++ b/client/src/components/Tours/planner/roundHikeRouting.ts @@ -64,14 +64,15 @@ export async function findRoundHikes( ): Promise { const state = await searchRoundLoops(request.start, request.targetM, (spots) => askLoop(request, spots, signal), { signal, - onStep: ({ found, asked }) => report({ phase: 'searching', candidates: found.map(candidateOf), asked }), + onStep: ({ found, asked }) => + report({ phase: 'searching', candidates: found.map((loop, i) => candidateOf(loop, i)), asked }), }); if (signal.aborted) return; if (state.answered === 0) { report({ phase: 'failed', candidates: [], asked: state.asked }); return; } - const found = state.found.map(candidateOf); + const found = state.found.map((loop, i) => candidateOf(loop, i)); let candidates = [...found]; report({ phase: 'done', candidates, asked: state.asked }); for (const round of found) {