From 933cb5569d7d5dabf8d3dc45762b0aafec38b0c0 Mon Sep 17 00:00:00 2001 From: Bart Veneman Date: Fri, 28 Aug 2026 21:27:37 +0200 Subject: [PATCH 1/2] fix: store svelte element binding in $state() --- src/routes/(public)/specificity-calculator/+page.svelte | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/routes/(public)/specificity-calculator/+page.svelte b/src/routes/(public)/specificity-calculator/+page.svelte index 961e94d..00bec71 100644 --- a/src/routes/(public)/specificity-calculator/+page.svelte +++ b/src/routes/(public)/specificity-calculator/+page.svelte @@ -15,7 +15,7 @@ // @ts-expect-error No type definitions for importing images import Image from './og-image.png?w=1200' - let input_ref: HTMLInputElement + let input_ref: HTMLInputElement | undefined = $state() let has_error = $state(false) let result: { selector: string; specificity: Specificity }[] | undefined = $state() @@ -70,7 +70,7 @@ } async function on_input() { - let input = input_ref.value + let input = input_ref!.value calculate(input) await update_url(input) @@ -79,6 +79,8 @@ onMount(async () => { let param_input = new URLSearchParams(page.url.searchParams.toString()).get(PARAM) + if (!input_ref) return + if (param_input) { input_ref.value = param_input } else { From bac1bbbc6a78c97bebdf710c1b0808eb147b5341 Mon Sep 17 00:00:00 2001 From: Bart Veneman Date: Fri, 28 Aug 2026 21:40:01 +0200 Subject: [PATCH 2/2] feat: render a deep link to Polypane specificity calculator --- .../(public)/specificity-calculator/+page.svelte | 16 ++++++++++++++-- .../(public)/specificity-calculator/spec.ts | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/routes/(public)/specificity-calculator/+page.svelte b/src/routes/(public)/specificity-calculator/+page.svelte index 00bec71..874d549 100644 --- a/src/routes/(public)/specificity-calculator/+page.svelte +++ b/src/routes/(public)/specificity-calculator/+page.svelte @@ -16,8 +16,18 @@ import Image from './og-image.png?w=1200' let input_ref: HTMLInputElement | undefined = $state() + let input_value = $state('') let has_error = $state(false) let result: { selector: string; specificity: Specificity }[] | undefined = $state() + let polypane_url = $derived.by(() => { + let base_url = new URL('https://polypane.app/css-specificity-calculator/') + + if (input_value) { + base_url.searchParams.set('selector', encodeURIComponent(input_value)) + } + + return base_url.toString() + }) const DEFAULT_INPUT = '.kid :has(.friend) ~ :where(.treehouse) :is(#gross)' const PARAM = 'selectors' @@ -71,6 +81,7 @@ async function on_input() { let input = input_ref!.value + input_value = input calculate(input) await update_url(input) @@ -87,6 +98,7 @@ input_ref.value = DEFAULT_INPUT } + input_value = input_ref.value calculate(input_ref.value) await update_url(input_ref.value) }) @@ -152,8 +164,8 @@ This analyzer is powered by @bramus/specificity. There are other specificity calculators available that offer explanations, like - the one from Polypane. You - should use that one if you want to know more about how + the one from Polypane. You should use that one if you want to know + more about how specificity is calculated.

diff --git a/src/routes/(public)/specificity-calculator/spec.ts b/src/routes/(public)/specificity-calculator/spec.ts index d352da8..6085ae4 100644 --- a/src/routes/(public)/specificity-calculator/spec.ts +++ b/src/routes/(public)/specificity-calculator/spec.ts @@ -65,6 +65,7 @@ test.describe('without preloading', () => { index++ } }) + test('shows an error message for invalid selectors', async ({ page }) => { await expect(page).toBeHydrated() await input.fill(`1234`) @@ -89,6 +90,20 @@ test.describe('without preloading', () => { await input.fill(`#my-selector .myClass, :is(second)`) await expect(page).toHaveURL('/specificity-calculator?selectors=%23my-selector+.myClass%2C+%3Ais%28second%29') }) + + test('deep links to Polypane when selector is filled', async ({ page }) => { + await expect(page).toBeHydrated() + await input.fill(`#my-selector .myClass, :is(second)`) + const link = page.getByRole('link', { name: 'the one from Polypane' }) + await expect(link).toHaveAttribute( + 'href', + 'https://polypane.app/css-specificity-calculator/?selector=%2523my-selector%2520.myClass%252C%2520%253Ais%28second%29' + ) + + // and updates after changing selector + await input.fill(`a`) + await expect(link).toHaveAttribute('href', 'https://polypane.app/css-specificity-calculator/?selector=a') + }) }) test.describe('with preloading', () => {