diff --git a/package-lock.json b/package-lock.json index fbbc8e7..8afd0dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@melt-ui/pp": "^0.3.2", "@melt-ui/svelte": "^0.86.6", "@oddbird/popover-polyfill": "^0.6.1", - "@projectwallace/css-analyzer": "^9.2.0", + "@projectwallace/css-analyzer": "^9.3.0", "@projectwallace/css-code-coverage": "^0.9.0", "@projectwallace/css-code-quality": "^3.1.0", "@projectwallace/css-design-tokens": "^0.11.0", @@ -95,6 +95,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -118,6 +119,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -1164,6 +1166,7 @@ "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.86.6.tgz", "integrity": "sha512-Jer+M7DgIwT5IHfTayb4Iw/fkkxWNmC/mqn/nMh9JrbPbkxmyabfLQnhJ+JDn5HK77f84j34lubO3iqFtYAfMg==", "license": "MIT", + "peer": true, "dependencies": { "@floating-ui/core": "^1.3.1", "@floating-ui/dom": "^1.4.5", @@ -1385,12 +1388,12 @@ "license": "MIT" }, "node_modules/@projectwallace/css-analyzer": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@projectwallace/css-analyzer/-/css-analyzer-9.2.0.tgz", - "integrity": "sha512-UQTDXs5UZMU6HYTyJ2Qo0ElS1zCDBqNp9/Roi6lQBYE5yr7dIF6ZU0Qw2Tj76KipUDLsoo2ex1kEiC0dXL9bFw==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@projectwallace/css-analyzer/-/css-analyzer-9.3.0.tgz", + "integrity": "sha512-1a6YLRi2GQASvs1i2lk9G33I/RtL3Avf1PpaiqFTw/vO59hBhX0rIrdU767rJZ0CYDZustHLN/ZsQ/5vftASjA==", "license": "MIT", "dependencies": { - "@projectwallace/css-parser": "^0.13.0" + "@projectwallace/css-parser": "^0.13.3" }, "engines": { "node": ">=18.0.0" @@ -2186,6 +2189,7 @@ "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.50.0.tgz", "integrity": "sha512-Hj8sR8O27p2zshFEIJzsvfhLzxga/hWw6tRLnBjMYw70m1aS9BSYCqAUtzDBjRREtX1EvLMYgaC0mYE3Hz4KWA==", "license": "MIT", + "peer": true, "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", @@ -2236,6 +2240,7 @@ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.1.tgz", "integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==", "license": "MIT", + "peer": true, "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", @@ -2339,10 +2344,17 @@ "integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, "node_modules/@types/unist": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", @@ -2500,6 +2512,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2508,9 +2521,9 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", "dependencies": { @@ -2547,9 +2560,9 @@ "license": "Python-2.0" }, "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", + "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -2885,9 +2898,9 @@ } }, "node_modules/devalue": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.2.tgz", - "integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.3.tgz", + "integrity": "sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==", "license": "MIT" }, "node_modules/devlop": { @@ -4342,6 +4355,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -4451,6 +4465,7 @@ "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -4490,6 +4505,7 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -4925,6 +4941,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", @@ -5151,20 +5168,22 @@ } }, "node_modules/svelte": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.50.0.tgz", - "integrity": "sha512-FR9kTLmX5i0oyeQ5j/+w8DuagIkQ7MWMuPpPVioW2zx9Dw77q+1ufLzF1IqNtcTXPRnIIio4PlasliVn43OnbQ==", + "version": "5.53.5", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.5.tgz", + "integrity": "sha512-YkqERnF05g8KLdDZwZrF8/i1eSbj6Eoat8Jjr2IfruZz9StLuBqo8sfCSzjosNKd+ZrQ8DkKZDjpO5y3ht1Pow==", "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", + "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", - "aria-query": "^5.3.1", + "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", - "devalue": "^5.6.2", + "devalue": "^5.6.3", "esm-env": "^1.2.1", "esrap": "^2.2.2", "is-reference": "^3.0.3", @@ -5408,6 +5427,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -5467,6 +5487,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5642,6 +5663,7 @@ "resolved": "https://registry.npmjs.org/rolldown-vite/-/rolldown-vite-7.2.2.tgz", "integrity": "sha512-Fl3ZdmJhDMJGcqrr342pPVrhugXdOcuNBRBauz4S7QGSRXbQy7y8q5QYJtgkcrG8XjY0EENSZeTk58c3m20FxA==", "license": "MIT", + "peer": true, "dependencies": { "@oxc-project/runtime": "0.96.0", "fdir": "^6.5.0", @@ -5761,6 +5783,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, diff --git a/package.json b/package.json index fb0c3f9..4205742 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@melt-ui/pp": "^0.3.2", "@melt-ui/svelte": "^0.86.6", "@oddbird/popover-polyfill": "^0.6.1", - "@projectwallace/css-analyzer": "^9.2.0", + "@projectwallace/css-analyzer": "^9.3.0", "@projectwallace/css-code-coverage": "^0.9.0", "@projectwallace/css-code-quality": "^3.1.0", "@projectwallace/css-design-tokens": "^0.11.0", diff --git a/src/lib/components/stats/Selectors.svelte b/src/lib/components/stats/Selectors.svelte index e517bde..a050349 100644 --- a/src/lib/components/stats/Selectors.svelte +++ b/src/lib/components/stats/Selectors.svelte @@ -18,6 +18,15 @@ selectors?: CssAnalysis['selectors'] } + interface ValueCountPanelProps { + panel_id: string + title: string + data: { total: number; totalUnique: number; uniquenessRatio: number; uniqueWithLocations: Record } + list_id: string + empty_message: string + sort_options?: (typeof alphabetical_sorting)[] + } + let { selectors = Object.create(null) }: Props = $props() let { @@ -29,7 +38,8 @@ combinators, pseudoClasses, pseudoElements, - attributes + attributes, + customElements } = $derived(selectors) let alphabetical_sorting = { @@ -93,6 +103,30 @@ } +{#snippet value_count_panel({ panel_id, title, data, list_id, empty_message, sort_options = [alphabetical_sorting] }: ValueCountPanelProps)} + +
+ {title} + +
+ {#if data.total > 0} + + {:else} + {empty_message} + {/if} +
+{/snippet} +
Selectors @@ -184,49 +218,20 @@ {/if} - -
- Pseudo classes - -
- {#if pseudoClasses.total > 0} - - {:else} - No pseudo classes found. - {/if} -
- - -
- Pseudo elements - -
- {#if pseudoElements.total > 0} - - {:else} - No pseudo elements found. - {/if} -
+ {@render value_count_panel({ + panel_id: 'pseudo-classes', + title: 'Pseudo classes', + data: pseudoClasses, + list_id: 'pseudo-classes-list', + empty_message: 'No pseudo classes found.' + })} + {@render value_count_panel({ + panel_id: 'pseudo-elements', + title: 'Pseudo elements', + data: pseudoElements, + list_id: 'pseudo-elements-list', + empty_message: 'No pseudo elements found.' + })}
@@ -250,107 +255,42 @@ {/if} - -
- Vendor-prefixed selectors - -
- {#if prefixed.total > 0} - - {:else} - No vendor prefixed selectors found. - {/if} -
- - -
- Attribute selectors - -
- {#if attributes.total > 0} - - {:else} - No attribute selectors found. - {/if} -
- - -
- Accessibility selectors - -
- {#if accessibility.total > 0} - - {:else} - No accessibility selectors found. - {/if} -
- - -
- Keyframes selectors - -
- {#if keyframes.total > 0} - - {:else} - No keyframe selectors found. - {/if} -
+ {@render value_count_panel({ + panel_id: 'attribute-selectors', + title: 'Attribute selectors', + data: attributes, + list_id: 'attribute-selectors-list', + empty_message: 'No attribute selectors found.' + })} + {@render value_count_panel({ + panel_id: 'accessibility-selectors', + title: 'Accessibility selectors', + data: accessibility, + list_id: 'accessibility-selectors-list', + empty_message: 'No accessibility selectors found.' + })} + {@render value_count_panel({ + panel_id: 'keyframes-selectors', + title: 'Keyframes selectors', + data: keyframes, + list_id: 'keyframes-selectors-list', + empty_message: 'No keyframe selectors found.', + sort_options: [{ label: 'Sort by %', fn: sort_keyframes, id: 'keyframes-selectors' }] + })} + {@render value_count_panel({ + panel_id: 'custom-element-selectors', + title: 'Custom element selectors', + data: customElements, + list_id: 'custom-element-selectors-list', + empty_message: 'No custom element selectors found.' + })} + {@render value_count_panel({ + panel_id: 'prefixed-selectors', + title: 'Vendor-prefixed selectors', + data: prefixed, + list_id: 'prefixed-selectors-list', + empty_message: 'No vendor prefixed selectors found.' + })}
diff --git a/src/lib/components/stats/nav.ts b/src/lib/components/stats/nav.ts index 10bf37a..c389a50 100644 --- a/src/lib/components/stats/nav.ts +++ b/src/lib/components/stats/nav.ts @@ -28,10 +28,11 @@ export const nav = [ { id: 'pseudo-classes', title: 'Pseudo classes' }, { id: 'pseudo-elements', title: 'Pseudo elements' }, { id: 'selector-combinators', title: 'Combinators' }, - { id: 'prefixed-selectors', title: 'Vendor Prefixed' }, { id: 'attribute-selectors', title: 'Attributes' }, { id: 'accessibility-selectors', title: 'Accessibility' }, - { id: 'keyframes-selectors', title: 'Keyframes' } + { id: 'keyframes-selectors', title: 'Keyframes' }, + { id: 'custom-element-selectors', title: 'Custom elements' }, + { id: 'prefixed-selectors', title: 'Vendor Prefixed' } ] }, {