From f6911fbcca934bfd77ac5364d7a80e08410d4c49 Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Sat, 30 May 2026 18:31:56 +0300 Subject: [PATCH 01/67] feature: add sv-router, page structure and redirect to home from any other page --- package.json | 3 ++- src/app/App.svelte | 9 +++++---- src/routes/{Page.svelte => Home.svelte} | 4 ++-- src/routes/Redirect.svelte | 10 ++++++++++ src/routes/index.ts | 7 +++++++ src/routes/router.ts | 23 +++++++++++++++++++++++ yarn.lock | 16 +++++++++++++++- 7 files changed, 64 insertions(+), 8 deletions(-) rename src/routes/{Page.svelte => Home.svelte} (81%) create mode 100644 src/routes/Redirect.svelte create mode 100644 src/routes/index.ts create mode 100644 src/routes/router.ts diff --git a/package.json b/package.json index 8ff3064..ef02d67 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ }, "dependencies": { "@chenglou/pretext": "0.0.6", - "@tanstack/svelte-query": "6.1.28" + "@tanstack/svelte-query": "6.1.28", + "sv-router": "^0.16.3" } } diff --git a/src/app/App.svelte b/src/app/App.svelte index 38a8bce..6f9fccc 100644 --- a/src/app/App.svelte +++ b/src/app/App.svelte @@ -6,21 +6,22 @@ /** * App Component * - * Application entry point component. Wraps the main page route within the shared + * Application entry point component. Wraps the active route within the shared * layout shell. This is the root component mounted by the application. * * Structure: * - QueryProvider provides TanStack Query client for data fetching * - Layout provides sidebar, header/footer, and page container - * - Page renders the current route content + * - Router renders the matched route component */ -import Page from '$routes/Page.svelte'; +import '$routes/router'; +import { Router } from 'sv-router'; import { QueryProvider } from './providers'; import Layout from './ui/Layout.svelte'; - + diff --git a/src/routes/Page.svelte b/src/routes/Home.svelte similarity index 81% rename from src/routes/Page.svelte rename to src/routes/Home.svelte index 00481d6..dfd42ef 100644 --- a/src/routes/Page.svelte +++ b/src/routes/Home.svelte @@ -1,6 +1,6 @@ diff --git a/src/routes/index.ts b/src/routes/index.ts new file mode 100644 index 0000000..1cfa066 --- /dev/null +++ b/src/routes/index.ts @@ -0,0 +1,7 @@ +export { + isActive, + navigate, + p, + preload, + route, +} from './router'; diff --git a/src/routes/router.ts b/src/routes/router.ts new file mode 100644 index 0000000..49e21cd --- /dev/null +++ b/src/routes/router.ts @@ -0,0 +1,23 @@ +import { createRouter } from 'sv-router'; +import Home from './Home.svelte'; +import Redirect from './Redirect.svelte'; + +/** + * Single-page router for glyphdiff. + * + * Currently exposes one route; structure exists so additional routes can be + * added without touching the app shell. + */ +export const { + isActive, + navigate, + p, + preload, + route, +} = createRouter({ + '/': Home, + /** + * Any unmatched path redirects to home until additional routes exist. + */ + '*notfound': Redirect, +}); diff --git a/yarn.lock b/yarn.lock index 992f596..be38bb9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2382,7 +2382,7 @@ __metadata: languageName: node linkType: hard -"esm-env@npm:^1.0.0, esm-env@npm:^1.1.2, esm-env@npm:^1.2.1": +"esm-env@npm:^1.0.0, esm-env@npm:^1.1.2, esm-env@npm:^1.2.1, esm-env@npm:^1.2.2": version: 1.2.2 resolution: "esm-env@npm:1.2.2" checksum: 10c0/3d25c973f2fd69c25ffff29c964399cea573fe10795ecc1d26f6f957ce0483d3254e1cceddb34bf3296a0d7b0f1d53a28992f064ba509dfe6366751e752c4166 @@ -2577,6 +2577,7 @@ __metadata: oxlint: "npm:1.62.0" playwright: "npm:1.59.1" storybook: "npm:10.3.6" + sv-router: "npm:^0.16.3" svelte: "npm:5.55.5" svelte-check: "npm:4.4.8" svelte-language-server: "npm:0.18.0" @@ -3966,6 +3967,19 @@ __metadata: languageName: node linkType: hard +"sv-router@npm:^0.16.3": + version: 0.16.3 + resolution: "sv-router@npm:0.16.3" + dependencies: + esm-env: "npm:^1.2.2" + peerDependencies: + svelte: ^5 + bin: + sv-router: ./src/cli/index.js + checksum: 10c0/809263498b38828f869b613919946fd4ac899435cbb32396fdab43fba53aec612383f05f6661c1bfd0f5f78c395dc4fcf0b88b8bcd5da0e55a5280138ad884fb + languageName: node + linkType: hard + "svelte-ast-print@npm:^0.4.0": version: 0.4.2 resolution: "svelte-ast-print@npm:0.4.2" -- 2.52.0 From ddadac86863e1c63ff0ee57be0ef354499a78c37 Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Sat, 30 May 2026 18:48:53 +0300 Subject: [PATCH 02/67] reafactor: move CharacterComparisonEngine into Font entity --- .../CharacterComparisonEngine.svelte.ts | 2 -- .../CharacterComparisonEngine.test.ts | 2 +- src/entities/Font/lib/index.ts | 6 ++++++ src/shared/lib/helpers/index.ts | 19 ------------------- src/shared/lib/index.ts | 3 --- .../ui/SliderArea/SliderArea.svelte | 4 +--- 6 files changed, 8 insertions(+), 28 deletions(-) rename src/{shared/lib/helpers => entities/Font/lib}/CharacterComparisonEngine/CharacterComparisonEngine.svelte.ts (99%) rename src/{shared/lib/helpers => entities/Font/lib}/CharacterComparisonEngine/CharacterComparisonEngine.test.ts (98%) diff --git a/src/shared/lib/helpers/CharacterComparisonEngine/CharacterComparisonEngine.svelte.ts b/src/entities/Font/lib/CharacterComparisonEngine/CharacterComparisonEngine.svelte.ts similarity index 99% rename from src/shared/lib/helpers/CharacterComparisonEngine/CharacterComparisonEngine.svelte.ts rename to src/entities/Font/lib/CharacterComparisonEngine/CharacterComparisonEngine.svelte.ts index 1816218..232b621 100644 --- a/src/shared/lib/helpers/CharacterComparisonEngine/CharacterComparisonEngine.svelte.ts +++ b/src/entities/Font/lib/CharacterComparisonEngine/CharacterComparisonEngine.svelte.ts @@ -13,8 +13,6 @@ const CHAR_PROXIMITY_RANGE_PCT = 5; /** * Default render size in px when callers omit the `size` arg on `layout()`. - * Kept as a local constant to avoid pulling `$entities/Font` into - * `$shared/lib` (would create an FSD-illegal upward import cycle). */ const DEFAULT_RENDER_SIZE_PX = 16; diff --git a/src/shared/lib/helpers/CharacterComparisonEngine/CharacterComparisonEngine.test.ts b/src/entities/Font/lib/CharacterComparisonEngine/CharacterComparisonEngine.test.ts similarity index 98% rename from src/shared/lib/helpers/CharacterComparisonEngine/CharacterComparisonEngine.test.ts rename to src/entities/Font/lib/CharacterComparisonEngine/CharacterComparisonEngine.test.ts index 09a4f5f..43ed97d 100644 --- a/src/shared/lib/helpers/CharacterComparisonEngine/CharacterComparisonEngine.test.ts +++ b/src/entities/Font/lib/CharacterComparisonEngine/CharacterComparisonEngine.test.ts @@ -1,4 +1,5 @@ // @vitest-environment jsdom +import { installCanvasMock } from '$shared/lib/helpers/__mocks__/canvas'; import { clearCache } from '@chenglou/pretext'; import { beforeEach, @@ -6,7 +7,6 @@ import { expect, it, } from 'vitest'; -import { installCanvasMock } from '../__mocks__/canvas'; import { CharacterComparisonEngine } from './CharacterComparisonEngine.svelte'; // FontA: 10px per character. FontB: 15px per character. diff --git a/src/entities/Font/lib/index.ts b/src/entities/Font/lib/index.ts index 161c396..436676c 100644 --- a/src/entities/Font/lib/index.ts +++ b/src/entities/Font/lib/index.ts @@ -1,3 +1,9 @@ +export { + CharacterComparisonEngine, + type ComparisonLine, + type ComparisonResult, +} from './CharacterComparisonEngine/CharacterComparisonEngine.svelte'; + export { getFontUrl } from './getFontUrl/getFontUrl'; // Mock data helpers for Storybook and testing diff --git a/src/shared/lib/helpers/index.ts b/src/shared/lib/helpers/index.ts index ba2bb77..56a185c 100644 --- a/src/shared/lib/helpers/index.ts +++ b/src/shared/lib/helpers/index.ts @@ -7,7 +7,6 @@ * - Virtual scrolling for large lists * - Debounced state for search inputs * - Entity stores with O(1) lookups - * - Character-by-character font comparison * - Persistent localStorage-backed state * - Responsive breakpoint tracking * - 3D perspective animations @@ -116,24 +115,6 @@ export { type EntityStore, } from './createEntityStore/createEntityStore.svelte'; -/** - * Comparison logic - */ -export { - /** - * Character-by-character comparison utility - */ - CharacterComparisonEngine, - /** - * Single line of comparison results - */ - type ComparisonLine, - /** - * Full comparison output - */ - type ComparisonResult, -} from './CharacterComparisonEngine/CharacterComparisonEngine.svelte'; - /** * Text layout */ diff --git a/src/shared/lib/index.ts b/src/shared/lib/index.ts index 42fccfb..81cd249 100644 --- a/src/shared/lib/index.ts +++ b/src/shared/lib/index.ts @@ -5,9 +5,6 @@ */ export { - CharacterComparisonEngine, - type ComparisonLine, - type ComparisonResult, type ControlDataModel, type ControlModel, createDebouncedState, diff --git a/src/widgets/ComparisonView/ui/SliderArea/SliderArea.svelte b/src/widgets/ComparisonView/ui/SliderArea/SliderArea.svelte index a5ae2de..9e3708f 100644 --- a/src/widgets/ComparisonView/ui/SliderArea/SliderArea.svelte +++ b/src/widgets/ComparisonView/ui/SliderArea/SliderArea.svelte @@ -9,6 +9,7 @@ --> {#if fontA && fontB} - 0 ? 'transform' : 'auto'} - > + {#each [0, 1] as s (s)} { : 'text-neutral-950 dark:text-white', )} style:font-family={slotFonts[s]} - style:font-weight={typography.weight} style:opacity={slot === s ? '1' : '0'} style:position={slot === s ? 'relative' : 'absolute'} aria-hidden={slot !== s ? true : undefined} @@ -89,7 +77,6 @@ $effect(() => { font-optical-sizing: auto; transition: opacity 0.1s ease-out, - color 0.2s ease-out, - transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1); + color 0.2s ease-out; } diff --git a/src/widgets/ComparisonView/ui/Line/Line.svelte b/src/widgets/ComparisonView/ui/Line/Line.svelte index d8cb81f..69c5e08 100644 --- a/src/widgets/ComparisonView/ui/Line/Line.svelte +++ b/src/widgets/ComparisonView/ui/Line/Line.svelte @@ -1,42 +1,46 @@
- {#each chars as c, index} - {@render character?.({ char: c.char, index })} + {#if model.leftText} + {model.leftText} + {/if} + {#each model.windowChars as wc (wc.key)} + {/each} + {#if model.rightText} + {model.rightText} + {/if}
diff --git a/src/widgets/ComparisonView/ui/SliderArea/SliderArea.svelte b/src/widgets/ComparisonView/ui/SliderArea/SliderArea.svelte index 9e3708f..1a513b4 100644 --- a/src/widgets/ComparisonView/ui/SliderArea/SliderArea.svelte +++ b/src/widgets/ComparisonView/ui/SliderArea/SliderArea.svelte @@ -9,10 +9,12 @@ --> {#if fontA && fontB} - + {#each [0, 1] as s (s)} {