svelte-shaker 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Yuichiro Yamashita
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,198 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/baseballyama/svelte-shaker/main/assets/logo.png" alt="svelte-shaker" width="190" />
3
+ </p>
4
+
5
+ <h1 align="center">svelte-shaker</h1>
6
+
7
+ <p align="center">A <strong>sound, source-level tree-shaker for Svelte&nbsp;5 (runes) components.</strong></p>
8
+
9
+ **▶ Try it in the browser: https://baseballyama.github.io/svelte-shaker/** — an
10
+ interactive playground that runs the engine entirely client-side (and is itself
11
+ built with rsvelte + dogfooded through svelte-shaker).
12
+
13
+ It runs in your app's production build, _before_ the Svelte compiler, and slims
14
+ each `.svelte` file by partially evaluating it against how the **whole app**
15
+ actually uses it: props that are never passed (or always passed the same value)
16
+ are folded to their constant, the dead `{#if}` arms behind them are deleted,
17
+ those props are dropped from the `$props()` signature, and the now-pointless
18
+ attributes are removed at every call site. The Svelte compiler then only sees the
19
+ code your app can actually reach.
20
+
21
+ It is **sound first**: it never changes what the user sees. When it cannot prove
22
+ a transform is safe, it leaves the code untouched (bails).
23
+
24
+ See [`docs/ARCHITECTURE.md`](https://github.com/baseballyama/svelte-shaker/blob/main/docs/ARCHITECTURE.md) for the full design.
25
+
26
+ ## Why this exists (and why a JS bundler can't do it)
27
+
28
+ Design-system components carry lots of props (`Button` with
29
+ `variant / size / loading / icon / iconPosition / fullWidth / rounded / href …`),
30
+ but any one app uses only a few. The code behind the unused props — template
31
+ branches, class computation, reactive statements, imports, CSS — is effectively
32
+ dead for that app, yet it ships anyway.
33
+
34
+ It cannot be removed _after_ Svelte compiles, because Svelte emits **one generic
35
+ JS module per component**, shared by every caller. In that JS the prop values
36
+ flow through the runtime (`$.prop(...)`), so `loading` / `variant` are not static
37
+ JS constants — terser/esbuild/Rollup cannot fold `if (loading)` to `if (false)`,
38
+ and the single module has no whole-program information to know which props this
39
+ particular app never uses.
40
+
41
+ svelte-shaker works **one step earlier**, on the pre-compile Svelte source, where
42
+ the prop's value (its default, or the literal at the call site) is still visible
43
+ and the template structure is intact. It is essentially a **whole-program partial
44
+ evaluator + dead-code eliminator that understands Svelte**, driven by every call
45
+ site in the app.
46
+
47
+ ### The CSS differentiator (what a bundler genuinely can't reach)
48
+
49
+ Given `class="btn btn-{variant}"` where the app only ever passes
50
+ `variant ∈ {primary, secondary}`, the class `btn-danger` can never exist at
51
+ runtime. But the class only appears as a runtime string, so:
52
+
53
+ - Svelte's own unused-CSS pruning keeps `.btn-danger` (it can't see inside the
54
+ interpolation), and
55
+ - Rollup/terser can't touch it either (the class isn't in the JS at all).
56
+
57
+ svelte-shaker computes the reachable value set of `variant`, proves the
58
+ `.btn-danger` / `.btn-ghost` rules can never match any element this component
59
+ renders, and **removes those `<style>` rules** — while keeping `.btn`,
60
+ `.btn-primary`, `.btn-secondary`. This is verified end-to-end in
61
+ `packages/svelte-shaker/tests/css.test.ts`.
62
+
63
+ ## Install
64
+
65
+ ```sh
66
+ pnpm add -D svelte-shaker
67
+ # or: npm i -D svelte-shaker / yarn add -D svelte-shaker
68
+ ```
69
+
70
+ Requires `svelte@^5`.
71
+
72
+ ## Usage (Vite)
73
+
74
+ Add the plugin **before** `svelte()` so it hands already-slimmed source to the
75
+ Svelte compiler. It is **build-only by design** — dev is a pass-through (see
76
+ [Soundness](#soundness) / [Limitations](#limitations)).
77
+
78
+ ```ts
79
+ // vite.config.ts
80
+ import { defineConfig } from 'vite';
81
+ import { svelte } from '@sveltejs/vite-plugin-svelte';
82
+ import { shaker } from 'svelte-shaker/vite';
83
+
84
+ export default defineConfig({
85
+ plugins: [
86
+ // `include` must cover EVERY call site in the app, or prop elimination
87
+ // would be unsound. Defaults to the Vite root.
88
+ shaker({ include: ['src'] }),
89
+ svelte(),
90
+ ],
91
+ });
92
+ ```
93
+
94
+ There is also a plain-Rollup plugin (`rollup-plugin-svelte-shaker`) for non-Vite
95
+ pipelines; the Vite plugin is preferred for apps.
96
+
97
+ ### Options
98
+
99
+ ```ts
100
+ shaker({
101
+ include: ['src'], // dirs (relative to root) holding every .svelte call site
102
+ level: 1, // 0 | 1 | 2 — default 1 (L0/L1/L1.5 always on). 2 = opt-in L2.
103
+ monomorphize: false, // L2 tuning; only consulted when level: 2.
104
+ });
105
+
106
+ // Opt into L2 per-call-site monomorphization:
107
+ shaker({ include: ['src'], level: 2, monomorphize: true });
108
+ shaker({ include: ['src'], level: 2, monomorphize: { maxVariants: 16 } });
109
+ ```
110
+
111
+ ## What it does
112
+
113
+ | Level | What it removes | Default |
114
+ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
115
+ | **L0** | Props no call site ever passes → fold to the default, drop from `$props()`, strip the attribute at call sites | on |
116
+ | **L1** | Props that collapse to one constant app-wide → fold + drop + strip every call site's attribute | on |
117
+ | **L1.5** | Value-set **narrowing**: with `variant ∈ {primary, secondary}`, delete provably-dead `{#if}`/`{:else if}` arms (prop stays in the signature) | on |
118
+ | **CSS** | `<style>` rules whose class can never be produced given the value sets — the bundler-can't differentiator | on |
119
+ | **L2** | Per-call-site monomorphization: specialize a component per prop shape (deduped by residual, capped by `maxVariants`) | **opt-in** |
120
+
121
+ Folding also reaches template ternaries (`{cond ? a : b}`) and class-string
122
+ interpolation when the condition/parts are provable constants.
123
+
124
+ ## Soundness
125
+
126
+ The whole point is to **never change observable behavior**.
127
+
128
+ - **Differential-SSR verified.** Tests server-render the original and the shaken
129
+ component (comments stripped, whitespace normalized) and assert the HTML is
130
+ identical for every value the app actually passes
131
+ (`packages/svelte-shaker/tests/diff.ts`).
132
+ - **Conservative bail.** When a transform can't be _proven_ safe, the code is
133
+ left as-is. Whole-component bails: `<svelte:options accessors />` /
134
+ `customElement`, and any component that **escapes** as a value
135
+ (`<svelte:component this={X}>`, assigned/passed/stored), or is rendered through
136
+ a barrel/named import (its call sites aren't enumerable). Per-prop bails:
137
+ spread that could overwrite it, callee `...rest`, `bind:`, a name shadowed by
138
+ `{#each as}` / snippet params / `{#await then}` / `let:` / `{@const}`, or used
139
+ in `{@debug}`.
140
+ - **Side effects preserved.** A call-site attribute is only stripped if its value
141
+ has no side effects; a value's code is removed only when it is provably pure
142
+ and unused.
143
+ - **Whole-program fixpoint.** Call sites inside a folded-away `{#if}` don't count
144
+ toward a child's prop profile; analysis iterates to a fixpoint so cascades are
145
+ consistent with what the transform actually deletes.
146
+
147
+ ## Limitations
148
+
149
+ - **Svelte 5 runes only** (`$props()` / `$derived` / `$effect`). Svelte 4
150
+ (`export let` / `$:` / `$$props`) is out of scope.
151
+ - **Needs `.svelte` source.** Libraries shipping compiled JS can't be shaken (the
152
+ source has to be visible — that's the whole premise). Distribute via
153
+ `svelte-package`. Anything it can't resolve is silently passed through.
154
+ - **Build only.** It runs in `vite build`, not in dev/HMR — whole-program
155
+ analysis is fundamentally incompatible with HMR's locality, and L1.5/CSS depend
156
+ on negative information ("this value never occurs") that a lazily-loaded dev
157
+ server can't guarantee. Dev is always a pass-through (and is unoptimized but
158
+ always correct). A `dev: 'coarse'` mode is a future opt-in.
159
+ - **`include` must cover the whole app.** A call site outside the scanned dirs is
160
+ invisible, so soundness requires every consumer of a prop to be in scope.
161
+ - **Partial-bail boundaries.** Spread/rest/`bind:`/shadowing limit how much can be
162
+ folded (by design — the engine errs toward keeping code). L2's `minSavings`,
163
+ and `exclude` / `unsafe` / `report` options, are reserved but not yet
164
+ implemented.
165
+
166
+ ## Running the tests
167
+
168
+ ```sh
169
+ pnpm --filter svelte-shaker test # vitest: eval / basic / shadow / probes2 / css / vite / mono
170
+ pnpm format:fix && pnpm all:check # type-check + lint + format
171
+ ```
172
+
173
+ ### Bench
174
+
175
+ `packages/svelte-shaker/tests/css.test.ts` builds a tiny app
176
+ (`App` passes `variant="primary"` and `variant="secondary"` to `Btn`, whose
177
+ `<style>` defines `.btn-{primary,secondary,danger,ghost}`) two ways:
178
+
179
+ - **control** (Svelte + Rollup, no shaker): keeps `.btn-danger` and `.btn-ghost`
180
+ in the emitted CSS — the toolchain cannot prove them dead.
181
+ - **shaken**: removes `.btn-danger` / `.btn-ghost`, keeps `.btn` /
182
+ `.btn-primary` / `.btn-secondary`, and the rendered HTML is identical for both
183
+ variants the app passes.
184
+
185
+ That's the headline result: the same source produces strictly smaller CSS with no
186
+ behavior change.
187
+
188
+ ## Architecture & status
189
+
190
+ The engine is split into an environment-free **Engine** (Svelte-aware analysis +
191
+ transform) behind a stable IR, and a thin **Shell** (the Vite/Rollup plugin) that
192
+ owns file IO and module resolution — so the core can later be ported to Rust
193
+ (rsvelte / OXC). The current implementation status (what's done vs. remaining) is
194
+ tracked in [`docs/ARCHITECTURE.md` §11](https://github.com/baseballyama/svelte-shaker/blob/main/docs/ARCHITECTURE.md#11-実装状況implementation-status).
195
+
196
+ ## License
197
+
198
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";var e=require("svelte/compiler"),n=require("zimmerframe"),t=require("magic-string");function o(n,t){return e.parse(n,{modern:!0,filename:t})}function r(e,t,o){n.walk(e,t,o)}const s={known:!1};function a(e,n){if(!e)return s;switch(e.type){case"Literal":return{known:!0,value:e.value};case"Identifier":{const t=e.name??"";return"undefined"===t?{known:!0,value:void 0}:n.has(t)?{known:!0,value:n.get(t)}:s}case"UnaryExpression":{const t=a(e.argument,n);if(!t.known)return s;const o=t.value;switch(e.operator){case"!":return{known:!0,value:!o};case"-":return{known:!0,value:-o};case"+":return{known:!0,value:+o};case"typeof":return{known:!0,value:typeof o};case"void":return{known:!0,value:void 0};default:return s}}case"LogicalExpression":{const t=a(e.left,n);if(!t.known)return s;switch(e.operator){case"&&":return t.value?a(e.right,n):t;case"||":return t.value?t:a(e.right,n);case"??":return null===t.value||void 0===t.value?a(e.right,n):t;default:return s}}case"BinaryExpression":{const t=a(e.left,n),o=a(e.right,n);if(!t.known||!o.known)return s;const r=t.value,i=o.value;switch(e.operator){case"===":return{known:!0,value:r===i};case"!==":return{known:!0,value:r!==i};case"==":return{known:!0,value:r==i};case"!=":return{known:!0,value:r!=i};case"<":return{known:!0,value:r<i};case">":return{known:!0,value:r>i};case"<=":return{known:!0,value:r<=i};case">=":return{known:!0,value:r>=i};case"+":return{known:!0,value:r+i};case"-":return{known:!0,value:r-i};case"*":return{known:!0,value:r*i};case"/":return{known:!0,value:r/i};case"%":return{known:!0,value:r%i};default:return s}}default:return s}}function i(e,n,t){const o=a(e,n);if(o.known)return o;const r=c(e,n,t);return"unknown"===r?s:{known:!0,value:r}}function c(e,n,t){if(!e)return"unknown";switch(e.type){case"UnaryExpression":return"!"===e.operator?l(c(e.argument,n,t)):"unknown";case"LogicalExpression":{const s=c(e.left,n,t),a=()=>c(e.right,n,t);return"&&"===e.operator?!1!==s&&(o=s,r=a(),!1!==o&&!1!==r&&(!0===o&&!0===r||"unknown")):"||"===e.operator?!0===s||function(e,n){return!0===e||!0===n||(!1!==e||!1!==n)&&"unknown"}(s,a()):"unknown"}case"BinaryExpression":{const o=e.operator;if("==="===o||"=="===o||"!=="===o||"!="===o){const r="=="===o||"!="===o,s=function(e,n,t,o,r){const s=u(e,o),i=a(n,t);if(s&&i.known)return f(s,i.value,r);const c=u(n,o),l=a(e,t);return c&&l.known?f(c,l.value,r):l.known&&i.known?r?l.value==i.value:l.value===i.value:"unknown"}(e.left,e.right,n,t,r);return"!=="===o||"!="===o?l(s):s}return"unknown"}default:return"unknown"}var o,r}function u(e,n){return"Identifier"===e?.type&&e.name&&n.has(e.name)?n.get(e.name):null}function f(e,n,t){const o=t?e=>e==n:e=>e===n;return!!e.some(o)&&(!!e.every(o)||"unknown")}function l(e){return!0!==e&&(!1===e||"unknown")}function p(e,n,t){const{arms:o,elseFrag:r}=function(e){const n=[];let t,o=e;for(;o;){n.push({block:o,test:o.test,consequent:o.consequent});const e=o.alternate,r="Fragment"===e?.type&&1===e.nodes?.length&&"IfBlock"===e.nodes[0]?.type&&!0===e.nodes[0].elseif?e.nodes[0]:void 0;r?o=r:("Fragment"===e?.type&&(t=e),o=void 0)}return t?{arms:n,elseFrag:t}:{arms:n}}(e),s=[e.start,e.end],a=o.map((e=>i(e.test,n,t))),c=e=>e.known&&Boolean(e.value),u=e=>e.known&&!e.value;let f=!0;for(let e=0;e<o.length;e++){const n=a[e];if(c(n)&&f){const n=o[e].consequent;return{span:s,kept:n,removed:d(s,m(n)),recurse:!1}}u(n)||(f=!1)}const l=a.findIndex((e=>!u(e)));if(-1===l)return r?{span:s,kept:r,removed:d(s,m(r)),recurse:!1}:{span:s,kept:void 0,removed:[s],recurse:!1};if(0===l)return{span:s,kept:void 0,removed:v(o,a,l),recurse:!0};const p=o[l].block;return{span:s,kept:void 0,removed:[[s[0],p.start],...v(o,a,l)],recurse:!1,headerRewrite:{from:p.start,to:p.test.start,text:"{#if "}}}function d(e,n){if(!n)return[e];const t=[];return e[0]<n[0]&&t.push([e[0],n[0]]),n[1]<e[1]&&t.push([n[1],e[1]]),t}function m(e){const n=e?.nodes??[];return 0===n.length?null:[n[0].start,n[n.length-1].end]}function v(e,n,t){const o=[];for(let r=t+1;r<e.length;r++){const t=n[r];if(!t.known||t.value)continue;const s=e[r],a=e[r+1]?.block,i=a?a.start:h(s.consequent,s.block.end);o.push([s.block.start,i])}return o}function h(e,n){const t=e?.nodes??[];return t.length?t[t.length-1].end:n}function w(e,n){return n.some((([n,t])=>e.start>=n&&e.end<=t))}function g(e,n,t){if(0===n.size&&0===t.size)return[];const o=[];return r(e,null,{IfBlock(e,{next:r}){if(e.elseif||w(e,o))return;const s=p(e,n,t);for(const e of s.removed)o.push(e);s.recurse&&r()}}),o}const y=e=>e.endsWith(".svelte"),k=10,x="escapes as value (e.g. <svelte:component this={X}>)",S="rendered through a barrel/named import (call sites unobservable)";async function b(e,n,t){const o=await async function(e,n,t){const o=new Map,r=Array.isArray(e)?[...e]:[e],s=new Set(r);for(;r.length>0;){const e=r.shift(),a=await t(e),i=await D(e,a,n,t);o.set(e,i);for(const e of[...i.imports.values(),...i.barrelChildIds])s.has(e)||(s.add(e),r.push(e))}return o}(e,n,t),r=new Set;for(const e of o.values())for(const n of e.escapedComponents)r.add(n);for(const e of r){const n=o.get(e);n&&!n.bailReasons.includes(x)&&n.bailReasons.push(x)}const s=new Set;for(const e of o.values())for(const n of e.barrelChildIds)s.add(n);for(const e of s){const n=o.get(e);n&&!n.bailReasons.includes(S)&&n.bailReasons.push(S)}let a=M(o,I(o,new Map));for(let e=0;e<k;e++){const e=M(o,I(o,C(o,a)));if(E(a,e)){a=e;break}a=e}return{models:o,plans:a}}function I(e,n){const t=new Map,o=e=>{let n=t.get(e);return n||(n={sites:[]},t.set(e,n)),n};for(const t of e.values()){const e=n.get(t.id)??[];for(const n of t.childCalls)e.length>0&&w(n.node,e)||o(n.childId).sites.push(R(n.node))}return t}function M(e,n){const t=new Map;for(const o of e.values())t.set(o.id,T(o,n.get(o.id)));return t}function E(e,n){if(e.size!==n.size)return!1;for(const[t,o]of e){const e=n.get(t);if(!e)return!1;if(o.bail!==e.bail)return!1;if(!A(o.constFold,e.constFold))return!1;if(!P(o.narrow,e.narrow))return!1}return!0}function A(e,n){if(e.size!==n.size)return!1;for(const[t,o]of e)if(!n.has(t)||!Object.is(n.get(t),o))return!1;return!0}function P(e,n){if(e.size!==n.size)return!1;for(const[t,o]of e){const e=n.get(t);if(!e||o.length!==e.length)return!1;for(let n=0;n<o.length;n++)if(!Object.is(o[n],e[n]))return!1}return!0}function C(e,n){const t=new Map;for(const o of e.values()){const e=n.get(o.id);if(e.bail)continue;const r=g(o.ast.fragment,e.constFold,e.narrow);r.length>0&&t.set(o.id,r)}return t}async function D(e,n,t,s){const a=o(n,e),i=new Map,c=new Map,u=[];r(a.fragment,null,{SvelteOptions(e,{next:n}){for(const n of e.attributes??[])"Attribute"!==n.type||"accessors"!==n.name&&"customElement"!==n.name||u.push(`<svelte:options ${n.name}>`);n()}});let f,l,p=null,d=!1;const m=new Set,v=a.instance;if(v){for(const n of function*(e){const n=e.content;for(const e of n?.body??[]){if("ImportDeclaration"!==e.type)continue;const n=e.source?.value;if("string"==typeof n)for(const t of e.specifiers??[]){const e=t.local?.name;e&&("ImportDefaultSpecifier"===t.type?yield{value:n,local:e,imported:"default"}:"ImportNamespaceSpecifier"===t.type?yield{value:n,local:e,imported:"*"}:"ImportSpecifier"===t.type&&(yield{value:n,local:e,imported:q(t)??e}))}}}(v)){if(m.add(n.local),"default"===n.imported&&y(n.value)){const o=await t(n.value,e);o&&i.set(n.local,o);continue}const o=await W(n.value,n.imported,e,t,s);o&&c.set(n.local,o)}const n=function(e){const n=e.content;for(const e of n?.body??[])if("VariableDeclaration"===e.type)for(const n of e.declarations??[]){const t=n.init,o=n.id;if("CallExpression"===t?.type&&"Identifier"===t.callee?.type&&"$props"===t.callee.name&&"ObjectPattern"===o?.type)return{declaration:e,pattern:o,sharesStatement:(e.declarations?.length??1)>1}}return null}(v);if(n){f=n.declaration,l=n.pattern,n.sharesStatement&&u.push("$props() shares a multi-declarator statement"),p=[];for(const e of n.pattern.properties??[]){if("RestElement"===e.type){d=!0;continue}if("Property"!==e.type)continue;const n=e.key;if("Identifier"!==n?.type||!n.name)continue;const t=e.value,o="AssignmentPattern"===t?.type?t.right:void 0;p.push({name:n.name,property:e,defaultExpr:o})}}}const h=function(e,n){const t=[];return r(e.fragment,null,{Component(e,{next:o}){const r=e.name?n.get(e.name):void 0;r&&t.push({childId:r,node:e}),o()}}),t}(a,i),w=function(e,n){const t=new Set;return 0===n.size||r(e.fragment,null,{Component(e,{next:o}){const r=e.name?n.get(e.name):void 0;r&&t.add(r),o()}}),t}(a,c),{shadowedNames:g,debugNames:k}=function(e,n,t){const o=new Set,s=new Set;n&&r(n,null,{_(e,{next:n}){if("VariableDeclarator"!==e.type&&"FunctionDeclaration"!==e.type||e===t||"Identifier"!==e.id?.type||!e.id.name||o.add(e.id.name),"FunctionDeclaration"===e.type||"FunctionExpression"===e.type||"ArrowFunctionExpression"===e.type)for(const n of e.params??[])F(n,o);n()}});return r(e.fragment,null,{EachBlock(e,{next:n}){F(e.context,o),"string"==typeof e.index&&o.add(e.index),n()},SnippetBlock(e,{next:n}){"Identifier"===e.expression?.type&&e.expression.name&&o.add(e.expression.name);for(const n of e.parameters??[])F(n,o);n()},AwaitBlock(e,{next:n}){F(e.value,o),F(e.error,o),n()},LetDirective(e,{next:n}){e.name&&o.add(e.name),n()},ConstTag(e,{next:n}){for(const n of e.declaration?.declarations??[])F(n.id,o);n()},DebugTag(e,{next:n}){for(const n of e.identifiers??[])"Identifier"===n.type&&n.name&&s.add(n.name);n()}}),{shadowedNames:o,debugNames:s}}(a,v,f),x=function(e,n,t){const o=new Set,s=e=>{if(!e)return;const t=n.get(e);t&&o.add(t)};r(e.fragment,{parent:null},{_(e,{state:n,next:o}){"Identifier"===e.type&&e.name&&t.has(e.name)&&z(e,n.parent)&&s(e.name),o({parent:e})}}),e.instance&&r(e.instance,{parent:null},{_(e,{state:t,next:o}){"Identifier"===e.type&&e.name&&n.has(e.name)&&z(e,t.parent)&&!N(t.parent)&&s(e.name),o({parent:e})}});return o}(a,i,m);return{id:e,code:n,ast:a,imports:i,props:p,propsDeclaration:f,propsPattern:l,hasRestProp:d,childCalls:h,shadowedNames:g,debugNames:k,escapedComponents:x,barrelChildIds:w,bailReasons:u}}function F(e,n){if(e)switch(e.type){case"Identifier":return void(e.name&&n.add(e.name));case"ObjectPattern":for(const t of e.properties??[])"RestElement"===t.type?F(t.argument,n):"Property"===t.type&&F(t.value??t.key,n);return;case"ArrayPattern":for(const t of e.elements??[])F(t,n);return;case"AssignmentPattern":return void F(e.left,n);case"RestElement":return void F(e.argument,n);default:return}}function z(e,n){return!!n&&(!("MemberExpression"===n.type&&n.property===e&&!n.computed)&&(!("Property"===n.type&&n.key===e&&!n.computed&&!0!==n.shorthand)&&!N(n)))}function N(e){return null!=e&&("ImportSpecifier"===e.type||"ImportDefaultSpecifier"===e.type||"ImportNamespaceSpecifier"===e.type||"ExportSpecifier"===e.type)}function R(e){const n=e.attributes??[];let t=-1;for(let e=0;e<n.length;e++)"SpreadAttribute"===n[e].type&&(t=e);const o=new Map;for(let e=0;e<n.length;e++){const r=n[e],s=r.name;if("BindDirective"===r.type){s&&o.set(s,L(e,t));continue}if("Attribute"!==r.type||!s)continue;const a=$(r.value);o.set(s,a.known?{value:a.value,dynamic:!1,afterLastSpread:e>t}:L(e,t))}for(const r of function(e){const n=e.fragment?.nodes??[],t=[];let o=!1;for(const e of n)if("SnippetBlock"!==e.type){if("Comment"!==e.type){if("Text"===e.type){if(""===(e.data??e.raw??"").trim())continue}o=!0}}else"Identifier"===e.expression?.type&&e.expression.name&&t.push(e.expression.name);o&&t.push("children");return t}(e))o.set(r,L(n.length,t));return{hadSpread:t>=0,explicit:o}}function L(e,n){return{value:void 0,dynamic:!0,afterLastSpread:e>n}}function $(e){if(!0===e)return{known:!0,value:!0};if(null==e)return{known:!1};const n=Array.isArray(e)?e:[e];if(1===n.length){const e=n[0];return"Text"===e.type?{known:!0,value:e.data??e.raw??""}:"ExpressionTag"===e.type&&"Literal"===e.expression?.type?{known:!0,value:e.expression.value}:{known:!1}}let t="";for(const e of n){if("Text"!==e.type)return{known:!1};t+=e.data??e.raw??""}return{known:!0,value:t}}function O(e,n){return e.shadowedNames.has(n)||e.debugNames.has(n)}function T(e,n){const t={id:e.id,bail:!1,reasons:[],constFold:new Map,narrow:new Map,valueSets:new Map};if(e.bailReasons.length>0)return t.bail=!0,t.reasons.push(...e.bailReasons),t;if(!e.props||0===e.props.length)return t;const o=n?.sites??[];if(0===o.length)return t;for(const n of e.props){if(O(e,n.name))continue;const r=_(n,o);t.valueSets.set(n.name,r),r.top||r.dynamic||(1!==r.values.length?r.values.length>=2&&t.narrow.set(n.name,r.values):t.constFold.set(n.name,r.values[0]))}return t}function _(e,n){const t=[];let o=!1,r=!1;const s=e=>{t.some((n=>Object.is(n,e)))||t.push(e)};for(const t of n){const n=t.explicit.get(e.name);if(n?.afterLastSpread){n.dynamic?o=!0:s(n.value);continue}if(t.hadSpread){r=!0;continue}const a=B(e.defaultExpr);a.known?s(a.value):o=!0}return{values:t,dynamic:o,top:r}}function B(e){return e?"Literal"===e.type?{known:!0,value:e.value}:"Identifier"===e.type&&"undefined"===e.name?{known:!0,value:void 0}:{known:!1}:{known:!0,value:void 0}}function q(e){const n=e.imported;return"Identifier"===n?.type&&n.name?n.name:"Literal"===n?.type&&"string"==typeof n.value?n.value:void 0}function j(e){return"Identifier"===e?.type&&e.name?e.name:"Literal"===e?.type&&"string"==typeof e.value?e.value:void 0}const V=8;async function W(e,n,t,r,s,a=0){if(a>V)return null;const i=await r(e,t);if(!i)return null;if(y(e)||y(i))return"default"===n||"*"===n?i:null;let c;try{c=await s(i)}catch{return null}const u=function(e,n){try{const t=o(`<script module>\n${e}\n<\/script>`,n);return t.module?.content?.body??null}catch{return null}}(c,i);if(!u)return null;for(const e of u)if("ExportNamedDeclaration"===e.type&&e.source?.value){for(const t of e.specifiers??[])if(j(t.exported)===n)return W(String(e.source.value),j(t.local)??"default",i,r,s,a+1)}else if("ExportNamedDeclaration"!==e.type||e.source){if("ExportAllDeclaration"===e.type&&e.source?.value){const t=await W(String(e.source.value),n,i,r,s,a+1);if(t)return t}}else for(const t of e.specifiers??[]){if(j(t.exported)!==n)continue;const e=j(t.local);if(!e)continue;const o=U(u,e);return o?W(o.value,o.imported,i,r,s,a+1):null}return null}function U(e,n){for(const t of e){if("ImportDeclaration"!==t.type)continue;const e=t.source?.value;if("string"==typeof e)for(const o of t.specifiers??[])if(o.local?.name===n){if("ImportDefaultSpecifier"===o.type)return{value:e,imported:"default"};if("ImportNamespaceSpecifier"===o.type)return{value:e,imported:"*"};if("ImportSpecifier"===o.type)return{value:e,imported:q(o)??n}}}return null}const J=64;const X=Symbol("unbounded-class-source");function G(e,n,t){if(!0===e)return X;if(null==e)return new Set;const o=Array.isArray(e)?e:[e];let r=[""];for(const e of o){const o=H(e,n,t);if(o===X)return X;const s=[];for(const e of r)for(const n of o)if(s.push(e+n),s.length>J)return X;r=s}const s=new Set;for(const e of r)for(const n of e.split(/\s+/))n&&s.add(n);return s}function H(e,n,t){return"Text"===e.type?new Set([e.data??e.raw??""]):"ExpressionTag"===e.type?function(e,n,t){if(!e)return X;if("Identifier"===e.type&&e.name&&t.has(e.name)){const n=new Set;for(const o of t.get(e.name))n.add(K(o));return n}const o=a(e,n);return o.known?new Set([K(o.value)]):X}(e.expression,n,t):X}function K(e){return String(e)}function Q(e,n,t){const o=e.ast.css;if(!o||!o.children)return 0;const s=function(e,n){const t=new Set;let o=!1;const s=n.constFold,a=n.narrow;return r(e.ast.fragment,null,{_(e,{next:n}){if("RegularElement"===(r=e.type)||"SvelteElement"===r||"Component"===r||"SvelteComponent"===r||"SvelteSelf"===r){var r;for(const n of e.attributes??[]){if("SpreadAttribute"===n.type){o=!0;continue}if("ClassDirective"===n.type){n.name&&t.add(n.name);continue}if("Attribute"!==n.type||"class"!==n.name)continue;const e=G(n.value,s,a);if(e===X)o=!0;else for(const n of e)t.add(n)}n()}else n()}}),{classes:t,unbounded:o}}(e,n);if(s.unbounded)return 0;let a=0;for(const n of o.children)"Rule"===n.type&&Y(n,s.classes)&&(Z(e.code,n,o.children,t),a+=1);return a}function Y(e,n){if(function(e){let n=!1;return r(e,null,{_(e,{next:t}){"PseudoClassSelector"===e.type&&"global"===e.name&&(n=!0),t()}}),n}(e))return!1;const t=e.prelude?.children??[];return 0!==t.length&&t.every((e=>function(e,n){let t=!1;for(const o of e.children??[])for(const e of o.selectors??[])"ClassSelector"===e.type&&e.name&&!n.has(e.name)&&(t=!0);return t}(e,n)))}function Z(e,n,t,o){const r=t.indexOf(n),s=t[r-1];let a=n.start;const i=s?s.end:0;for(;a>i&&/\s/.test(e[a-1]);)a-=1;o.remove(a,n.end)}function ee(e,n){return te(e,ne(e,n))}function ne(e,n){const o=new Map,r=new Map;for(const s of e.values()){const e=new t(s.code);o.set(s.id,e);const a=n.get(s.id);r.set(s.id,a.bail?new Set:ie(s,a,e))}for(const n of e.values())de(n,r,o.get(n.id));return o}function te(e,n){const t={};for(const o of e.values())t[o.id]=n.get(o.id).toString();return t}function oe(e,n,t,o){const r=ne(e,n);return function(e,n,t,o){const r=new Map;for(const e of n){const n=r.get(e.owner);n?n.push(e):r.set(e.owner,[e])}for(const[n,s]of r){const r=e.get(n),a=o.get(n);if(!r||!a)continue;const i=new Map,c=[];let u=0;for(const e of s){const n=e.node.name??"Cmp";let o=i.get(e.variantId);void 0===o&&(o=`${n}__shaker_v${u++}`,i.set(e.variantId,o),c.push({local:o,spec:t(e.variantId)})),re(r.code,e.node,o,e.foldedProps,a)}c.length>0&&ae(r,c,a)}}(e,t,o,r),te(e,r)}function re(e,n,t,o,r){const s=n.name;if(!s)return;const a=n.start+1;e.slice(a,a+s.length)===s&&r.overwrite(a,a+s.length,t);const i=`</${s}`,c=e.lastIndexOf(i,n.end);if(c>=n.start){const e=c+2;r.overwrite(e,e+s.length,t)}for(const t of n.attributes??[])"Attribute"===t.type&&t.name&&o.has(t.name)&&se(e,t,r)}function se(e,n,t){let o=n.start;" "!==e[o-1]&&"\t"!==e[o-1]||(o-=1),t.remove(o,n.end)}function ae(e,n,t){const o=n.map((e=>` import ${e.local} from ${JSON.stringify(e.spec)};`)).join("\n"),r=e.ast.instance,s=r?.content?.body??[];if(r&&s.length>0){const e=s[s.length-1];t.appendLeft(e.end,`\n${o}`)}else r&&r.content?t.appendLeft(r.content.start,`\n${o}\n`):t.prepend(`<script>\n${o}\n<\/script>\n`)}function ie(e,n,t){return ce(e,n.constFold,n.narrow,n,t)}function ce(e,n,t,o,s){if(0===n.size&&0===t.size)return new Set;const i=e.code,c=[];!function(e,n,t,o,s,a){r(e,null,{IfBlock(e,{next:r}){if(e.elseif||w(e,a))return;const i=p(e,n,t);if(function(e,n,t,o){if(e.kept)return void o.overwrite(e.span[0],e.span[1],function(e,n,t){const o=e?.nodes??[];return 0===o.length?"":ue(o[0].start,o[o.length-1].end,o,n,t)}(e.kept,n,t));for(const[n,t]of e.removed)o.remove(n,t);if(e.headerRewrite){const{from:n,to:t,text:r}=e.headerRewrite;o.overwrite(n,t,r)}}(i,n,o,s),i.kept)a.push(i.span);else for(const e of i.removed)a.push(e);i.recurse&&r()}})}(e.ast.fragment,n,t,i,s,c),function(e,n,t,o,s){if(0===n.size)return;r(e,null,{ConditionalExpression(e,{next:r}){if(w(e,s))return;const i=a(e.test,n);if(!i.known)return void r();const c=i.value?e.consequent:e.alternate;c?(o.overwrite(e.start,e.end,ue(c.start,c.end,[c],n,t)),s.push([e.start,e.end])):r()}})}(e.ast.fragment,n,i,s,c);const u=function(e,n,t){const o=new Map,s=s=>{s&&r(s,{parent:null},{_(r,{state:s,next:a}){"Identifier"===r.type&&r.name&&n.has(r.name)&&!w(r,t)&&r!==e.propsPattern&&!fe(r,s.parent)&&(o.get(r.name)??function(e,n){const t=[];return e.set(n,t),t}(o,r.name)).push([r.start,r.end]),a({parent:r})}})};return s(e.ast.instance),s(e.ast.fragment),o}(e,n,c);for(const[e,t]of n)for(const n of u.get(e)??[])s.overwrite(n[0],n[1],ve(t));const f=new Set(n.keys());!function(e,n,t){if(!e.props||0===n.size)return;const o=e.props.filter((e=>!n.has(e.name)));if(0===o.length&&!e.hasRestProp&&e.propsDeclaration)return void function(e,n,t){let o=n.start;for(;o>0&&"\n"!==e[o-1];)o-=1;let r=n.end;for(;r<e.length&&"\n"!==e[r];)r+=1;const s=e.slice(o,n.start),a=e.slice(n.end,r);/^\s*$/.test(s)&&/^\s*;?\s*$/.test(a)?t.remove(o,r<e.length?r+1:r):t.remove(n.start,";"===e[n.end]?n.end+1:n.end)}(e.code,e.propsDeclaration,t);const r=e.propsPattern?.properties??[];for(const o of e.props)n.has(o.name)&&(le(r,o.property,t),e.propsPattern&&pe(e.propsPattern,o.name,t))}(e,f,s);return Q(e,{...o,constFold:n,narrow:t},s),f}function ue(e,n,t,o,s){if(0===o.size)return s.slice(e,n);const a=[];for(const e of t)r(e,{parent:null},{_(e,{state:n,next:t}){"Identifier"===e.type&&e.name&&o.has(e.name)&&!fe(e,n.parent)&&a.push({start:e.start,end:e.end,name:e.name}),t({parent:e})}});if(0===a.length)return s.slice(e,n);a.sort(((e,n)=>e.start-n.start));let i="",c=e;for(const e of a)i+=s.slice(c,e.start),i+=ve(o.get(e.name)),c=e.end;return i+=s.slice(c,n),i}function fe(e,n){return!!n&&("MemberExpression"===n.type&&n.property===e&&!n.computed||("Property"===n.type&&n.key===e&&!n.computed&&!0!==n.shorthand||("ImportSpecifier"===n.type||"ImportDefaultSpecifier"===n.type||"ImportNamespaceSpecifier"===n.type||"ExportSpecifier"===n.type)))}function le(e,n,t){const o=e.indexOf(n),r=e[o+1],s=e[o-1];r?t.remove(n.start,r.start):s?t.remove(s.end,n.end):t.remove(n.start,n.end)}function pe(e,n,t){const o=e.typeAnnotation?.typeAnnotation?.members??[],r=o.findIndex((e=>"Identifier"===e.key?.type&&e.key.name===n));if(-1===r)return;const s=o[r],a=o[r+1],i=o[r-1];a?t.remove(s.start,a.start):i?t.remove(i.end,s.end):t.remove(s.start,s.end)}function de(e,n,t){r(e.ast.fragment,null,{Component(o,{next:r}){const s=o.name?e.imports.get(o.name):void 0,a=s?n.get(s):void 0;if(a&&a.size>0)for(const n of o.attributes??[])"Attribute"===n.type&&n.name&&a.has(n.name)&&me(n.value)&&se(e.code,n,t);r()}})}function me(e){if(!0===e||null==e)return!0;return(Array.isArray(e)?e:[e]).every((e=>"Text"===e.type||"ExpressionTag"===e.type&&"Literal"===e.expression?.type))}function ve(e){return void 0===e?"undefined":JSON.stringify(e)}const he={enabled:!1,maxVariants:8,minSavings:0};function we(n,t,o=he,r=[]){const s=new Map,a=[];if(!o.enabled)return{variants:s,bindings:a};const i=C(n,t),c=new Map,u=new Set;for(const e of n.values()){const o=i.get(e.id)??[];for(const r of e.childCalls){if(o.length>0&&w(r.node,o))continue;const s=n.get(r.childId),a=t.get(r.childId);if(!s||!a)continue;if(a.bail||!s.props||0===s.props.length){u.add(r.childId);continue}const i=ke(r.node,s,a);if(0===i.size){u.add(r.childId);continue}const f=xe(s,a,i);if(f===be(s,a)){u.add(r.childId);continue}const l=c.get(r.childId);l?l.push({owner:e.id,node:r.node,shape:i,code:f}):c.set(r.childId,[{owner:e.id,node:r.node,shape:i,code:f}])}}const f=function(e,n){const t=new Map;for(const o of e.values()){const e=n.get(o.id);t.set(o.id,e.bail?o.code:be(o,e))}return t}(n,t),l=new Map;for(const e of n.values())l.set(e.id,ye(f.get(e.id),e));const p=new Set;for(const e of l.values())for(const n of e)p.add(n);const d=(Array.isArray(r)?r:[r]).filter((e=>n.has(e))).filter((e=>!p.has(e))),m=new Map,v=(n,t)=>{const o=m.get(t);if(void 0!==o)return o;let r;try{const{js:o}=e.compile(t,{generate:"client",dev:!1,filename:n});r=o.code.length}catch{r=null}return null!==r&&m.set(t,r),r},h=new Set;for(const e of c.keys())u.has(e)||h.add(e);for(const[e,t]of c){if(u.has(e))continue;if(t.some((n=>n.owner!==e&&h.has(n.owner))))continue;const r=new Map,i=[];let c=!1;for(const n of t){if(r.has(n.code))continue;if(i.length>=o.maxVariants){c=!0;break}const t=`${e}::v${i.length}`;r.set(n.code,t),i.push({id:t,code:n.code})}if(!c&&ge(e,i,n,f,l,d,v,o.minSavings)){for(const n of i){const o=t.find((e=>e.code===n.code));s.set(n.id,{id:n.id,childId:e,code:n.code,foldedProps:o.shape})}for(const n of t)a.push({owner:n.owner,childId:e,node:n.node,variantId:r.get(n.code),foldedProps:n.shape})}}return{variants:s,bindings:a}}function ge(e,n,t,o,r,s,a,i){const c=t.get(e),u=new Map;for(const e of n)u.set(e.id,ye(e.code,c));const f=new Set,l=[...s];for(;l.length>0;){const e=l.pop();if(!f.has(e)){f.add(e);for(const n of r.get(e)??[])l.push(n)}}let p=0;for(const e of f){const n=a(e,o.get(e));if(null===n)return!1;p+=n}const d=n.map((e=>e.id)),m=new Set,v=new Set,h=n=>n===e?{comps:[],vars:d}:{comps:[n],vars:[]},w=[],g=[];for(const e of s){const n=h(e);w.push(...n.comps),g.push(...n.vars)}for(;w.length>0||g.length>0;){if(w.length>0){const e=w.pop();if(m.has(e))continue;m.add(e);for(const n of r.get(e)??[]){const e=h(n);w.push(...e.comps),g.push(...e.vars)}continue}const e=g.pop();if(!v.has(e)){v.add(e);for(const n of u.get(e)??[]){const e=h(n);w.push(...e.comps),g.push(...e.vars)}}}let y=0;for(const e of m){const n=a(e,o.get(e));if(null===n)return!1;y+=n}for(const e of v){const t=n.find((n=>n.id===e)).code,o=a(e,t);if(null===o)return!1;y+=o}return y<p*(1-i)}function ye(e,n){let t;try{t=o(e,n.id)}catch{return[]}const s=[];return r(t.fragment,null,{Component(e,{next:t}){const o=e.name?n.imports.get(e.name):void 0;o&&s.push(o),t()}}),s}function ke(e,n,t){const o=R(e),r=new Map;for(const e of n.props??[])r.set(e.name,e);const s=new Map;for(const[e,a]of o.explicit)r.has(e)&&(t.constFold.has(e)||O(n,e)||!a.dynamic&&a.afterLastSpread&&s.set(e,a.value));return s}function xe(e,n,o){const r=new Map(n.constFold);for(const[e,n]of o)r.set(e,n);const s=new Map;for(const[e,t]of n.narrow)r.has(e)||s.set(e,t);const a=new t(e.code);return ce(e,r,s,n,a),a.toString()}const Se=new WeakMap;function be(e,n){const o=Se.get(e);if(void 0!==o)return o;const r=new t(e.code);ce(e,n.constFold,n.narrow,n,r);const s=r.toString();return Se.set(e,s),s}exports.DEFAULT_MONO_OPTIONS=he,exports.analyze=b,exports.monomorphize=we,exports.svelteShaker=async function(e,n,t){const{models:o,plans:r}=await b(e,n,t);return ee(o,r)},exports.svelteShakerWithMono=async function(e,n,t,o=he,r=(e=>e)){const{models:s,plans:a}=await b(e,n,t),i=we(s,a,o,e);return{files:0===i.bindings.length?ee(s,a):oe(s,a,i.bindings.map((e=>({owner:e.owner,node:e.node,variantId:e.variantId,foldedProps:e.foldedProps}))),r),mono:i}},exports.transformAll=ee,exports.transformAllWithMono=oe;
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{parse as e,compile as n}from"svelte/compiler";import{walk as t}from"zimmerframe";import o from"magic-string";function r(n,t){return e(n,{modern:!0,filename:t})}function s(e,n,o){t(e,n,o)}const a={known:!1};function i(e,n){if(!e)return a;switch(e.type){case"Literal":return{known:!0,value:e.value};case"Identifier":{const t=e.name??"";return"undefined"===t?{known:!0,value:void 0}:n.has(t)?{known:!0,value:n.get(t)}:a}case"UnaryExpression":{const t=i(e.argument,n);if(!t.known)return a;const o=t.value;switch(e.operator){case"!":return{known:!0,value:!o};case"-":return{known:!0,value:-o};case"+":return{known:!0,value:+o};case"typeof":return{known:!0,value:typeof o};case"void":return{known:!0,value:void 0};default:return a}}case"LogicalExpression":{const t=i(e.left,n);if(!t.known)return a;switch(e.operator){case"&&":return t.value?i(e.right,n):t;case"||":return t.value?t:i(e.right,n);case"??":return null===t.value||void 0===t.value?i(e.right,n):t;default:return a}}case"BinaryExpression":{const t=i(e.left,n),o=i(e.right,n);if(!t.known||!o.known)return a;const r=t.value,s=o.value;switch(e.operator){case"===":return{known:!0,value:r===s};case"!==":return{known:!0,value:r!==s};case"==":return{known:!0,value:r==s};case"!=":return{known:!0,value:r!=s};case"<":return{known:!0,value:r<s};case">":return{known:!0,value:r>s};case"<=":return{known:!0,value:r<=s};case">=":return{known:!0,value:r>=s};case"+":return{known:!0,value:r+s};case"-":return{known:!0,value:r-s};case"*":return{known:!0,value:r*s};case"/":return{known:!0,value:r/s};case"%":return{known:!0,value:r%s};default:return a}}default:return a}}function c(e,n,t){const o=i(e,n);if(o.known)return o;const r=u(e,n,t);return"unknown"===r?a:{known:!0,value:r}}function u(e,n,t){if(!e)return"unknown";switch(e.type){case"UnaryExpression":return"!"===e.operator?p(u(e.argument,n,t)):"unknown";case"LogicalExpression":{const s=u(e.left,n,t),a=()=>u(e.right,n,t);return"&&"===e.operator?!1!==s&&(o=s,r=a(),!1!==o&&!1!==r&&(!0===o&&!0===r||"unknown")):"||"===e.operator?!0===s||function(e,n){return!0===e||!0===n||(!1!==e||!1!==n)&&"unknown"}(s,a()):"unknown"}case"BinaryExpression":{const o=e.operator;if("==="===o||"=="===o||"!=="===o||"!="===o){const r="=="===o||"!="===o,s=function(e,n,t,o,r){const s=f(e,o),a=i(n,t);if(s&&a.known)return l(s,a.value,r);const c=f(n,o),u=i(e,t);return c&&u.known?l(c,u.value,r):u.known&&a.known?r?u.value==a.value:u.value===a.value:"unknown"}(e.left,e.right,n,t,r);return"!=="===o||"!="===o?p(s):s}return"unknown"}default:return"unknown"}var o,r}function f(e,n){return"Identifier"===e?.type&&e.name&&n.has(e.name)?n.get(e.name):null}function l(e,n,t){const o=t?e=>e==n:e=>e===n;return!!e.some(o)&&(!!e.every(o)||"unknown")}function p(e){return!0!==e&&(!1===e||"unknown")}function d(e,n,t){const{arms:o,elseFrag:r}=function(e){const n=[];let t,o=e;for(;o;){n.push({block:o,test:o.test,consequent:o.consequent});const e=o.alternate,r="Fragment"===e?.type&&1===e.nodes?.length&&"IfBlock"===e.nodes[0]?.type&&!0===e.nodes[0].elseif?e.nodes[0]:void 0;r?o=r:("Fragment"===e?.type&&(t=e),o=void 0)}return t?{arms:n,elseFrag:t}:{arms:n}}(e),s=[e.start,e.end],a=o.map((e=>c(e.test,n,t))),i=e=>e.known&&Boolean(e.value),u=e=>e.known&&!e.value;let f=!0;for(let e=0;e<o.length;e++){const n=a[e];if(i(n)&&f){const n=o[e].consequent;return{span:s,kept:n,removed:m(s,v(n)),recurse:!1}}u(n)||(f=!1)}const l=a.findIndex((e=>!u(e)));if(-1===l)return r?{span:s,kept:r,removed:m(s,v(r)),recurse:!1}:{span:s,kept:void 0,removed:[s],recurse:!1};if(0===l)return{span:s,kept:void 0,removed:h(o,a,l),recurse:!0};const p=o[l].block;return{span:s,kept:void 0,removed:[[s[0],p.start],...h(o,a,l)],recurse:!1,headerRewrite:{from:p.start,to:p.test.start,text:"{#if "}}}function m(e,n){if(!n)return[e];const t=[];return e[0]<n[0]&&t.push([e[0],n[0]]),n[1]<e[1]&&t.push([n[1],e[1]]),t}function v(e){const n=e?.nodes??[];return 0===n.length?null:[n[0].start,n[n.length-1].end]}function h(e,n,t){const o=[];for(let r=t+1;r<e.length;r++){const t=n[r];if(!t.known||t.value)continue;const s=e[r],a=e[r+1]?.block,i=a?a.start:w(s.consequent,s.block.end);o.push([s.block.start,i])}return o}function w(e,n){const t=e?.nodes??[];return t.length?t[t.length-1].end:n}function g(e,n){return n.some((([n,t])=>e.start>=n&&e.end<=t))}function y(e,n,t){if(0===n.size&&0===t.size)return[];const o=[];return s(e,null,{IfBlock(e,{next:r}){if(e.elseif||g(e,o))return;const s=d(e,n,t);for(const e of s.removed)o.push(e);s.recurse&&r()}}),o}const k=e=>e.endsWith(".svelte"),x=10,b="escapes as value (e.g. <svelte:component this={X}>)",S="rendered through a barrel/named import (call sites unobservable)";async function I(e,n,t){const o=await async function(e,n,t){const o=new Map,r=Array.isArray(e)?[...e]:[e],s=new Set(r);for(;r.length>0;){const e=r.shift(),a=await t(e),i=await F(e,a,n,t);o.set(e,i);for(const e of[...i.imports.values(),...i.barrelChildIds])s.has(e)||(s.add(e),r.push(e))}return o}(e,n,t),r=new Set;for(const e of o.values())for(const n of e.escapedComponents)r.add(n);for(const e of r){const n=o.get(e);n&&!n.bailReasons.includes(b)&&n.bailReasons.push(b)}const s=new Set;for(const e of o.values())for(const n of e.barrelChildIds)s.add(n);for(const e of s){const n=o.get(e);n&&!n.bailReasons.includes(S)&&n.bailReasons.push(S)}let a=E(o,M(o,new Map));for(let e=0;e<x;e++){const e=E(o,M(o,D(o,a)));if(A(a,e)){a=e;break}a=e}return{models:o,plans:a}}function M(e,n){const t=new Map,o=e=>{let n=t.get(e);return n||(n={sites:[]},t.set(e,n)),n};for(const t of e.values()){const e=n.get(t.id)??[];for(const n of t.childCalls)e.length>0&&g(n.node,e)||o(n.childId).sites.push($(n.node))}return t}function E(e,n){const t=new Map;for(const o of e.values())t.set(o.id,T(o,n.get(o.id)));return t}function A(e,n){if(e.size!==n.size)return!1;for(const[t,o]of e){const e=n.get(t);if(!e)return!1;if(o.bail!==e.bail)return!1;if(!C(o.constFold,e.constFold))return!1;if(!P(o.narrow,e.narrow))return!1}return!0}function C(e,n){if(e.size!==n.size)return!1;for(const[t,o]of e)if(!n.has(t)||!Object.is(n.get(t),o))return!1;return!0}function P(e,n){if(e.size!==n.size)return!1;for(const[t,o]of e){const e=n.get(t);if(!e||o.length!==e.length)return!1;for(let n=0;n<o.length;n++)if(!Object.is(o[n],e[n]))return!1}return!0}function D(e,n){const t=new Map;for(const o of e.values()){const e=n.get(o.id);if(e.bail)continue;const r=y(o.ast.fragment,e.constFold,e.narrow);r.length>0&&t.set(o.id,r)}return t}async function F(e,n,t,o){const a=r(n,e),i=new Map,c=new Map,u=[];s(a.fragment,null,{SvelteOptions(e,{next:n}){for(const n of e.attributes??[])"Attribute"!==n.type||"accessors"!==n.name&&"customElement"!==n.name||u.push(`<svelte:options ${n.name}>`);n()}});let f,l,p=null,d=!1;const m=new Set,v=a.instance;if(v){for(const n of function*(e){const n=e.content;for(const e of n?.body??[]){if("ImportDeclaration"!==e.type)continue;const n=e.source?.value;if("string"==typeof n)for(const t of e.specifiers??[]){const e=t.local?.name;e&&("ImportDefaultSpecifier"===t.type?yield{value:n,local:e,imported:"default"}:"ImportNamespaceSpecifier"===t.type?yield{value:n,local:e,imported:"*"}:"ImportSpecifier"===t.type&&(yield{value:n,local:e,imported:q(t)??e}))}}}(v)){if(m.add(n.local),"default"===n.imported&&k(n.value)){const o=await t(n.value,e);o&&i.set(n.local,o);continue}const r=await U(n.value,n.imported,e,t,o);r&&c.set(n.local,r)}const n=function(e){const n=e.content;for(const e of n?.body??[])if("VariableDeclaration"===e.type)for(const n of e.declarations??[]){const t=n.init,o=n.id;if("CallExpression"===t?.type&&"Identifier"===t.callee?.type&&"$props"===t.callee.name&&"ObjectPattern"===o?.type)return{declaration:e,pattern:o,sharesStatement:(e.declarations?.length??1)>1}}return null}(v);if(n){f=n.declaration,l=n.pattern,n.sharesStatement&&u.push("$props() shares a multi-declarator statement"),p=[];for(const e of n.pattern.properties??[]){if("RestElement"===e.type){d=!0;continue}if("Property"!==e.type)continue;const n=e.key;if("Identifier"!==n?.type||!n.name)continue;const t=e.value,o="AssignmentPattern"===t?.type?t.right:void 0;p.push({name:n.name,property:e,defaultExpr:o})}}}const h=function(e,n){const t=[];return s(e.fragment,null,{Component(e,{next:o}){const r=e.name?n.get(e.name):void 0;r&&t.push({childId:r,node:e}),o()}}),t}(a,i),w=function(e,n){const t=new Set;return 0===n.size||s(e.fragment,null,{Component(e,{next:o}){const r=e.name?n.get(e.name):void 0;r&&t.add(r),o()}}),t}(a,c),{shadowedNames:g,debugNames:y}=function(e,n,t){const o=new Set,r=new Set;n&&s(n,null,{_(e,{next:n}){if("VariableDeclarator"!==e.type&&"FunctionDeclaration"!==e.type||e===t||"Identifier"!==e.id?.type||!e.id.name||o.add(e.id.name),"FunctionDeclaration"===e.type||"FunctionExpression"===e.type||"ArrowFunctionExpression"===e.type)for(const n of e.params??[])z(n,o);n()}});return s(e.fragment,null,{EachBlock(e,{next:n}){z(e.context,o),"string"==typeof e.index&&o.add(e.index),n()},SnippetBlock(e,{next:n}){"Identifier"===e.expression?.type&&e.expression.name&&o.add(e.expression.name);for(const n of e.parameters??[])z(n,o);n()},AwaitBlock(e,{next:n}){z(e.value,o),z(e.error,o),n()},LetDirective(e,{next:n}){e.name&&o.add(e.name),n()},ConstTag(e,{next:n}){for(const n of e.declaration?.declarations??[])z(n.id,o);n()},DebugTag(e,{next:n}){for(const n of e.identifiers??[])"Identifier"===n.type&&n.name&&r.add(n.name);n()}}),{shadowedNames:o,debugNames:r}}(a,v,f),x=function(e,n,t){const o=new Set,r=e=>{if(!e)return;const t=n.get(e);t&&o.add(t)};s(e.fragment,{parent:null},{_(e,{state:n,next:o}){"Identifier"===e.type&&e.name&&t.has(e.name)&&R(e,n.parent)&&r(e.name),o({parent:e})}}),e.instance&&s(e.instance,{parent:null},{_(e,{state:t,next:o}){"Identifier"===e.type&&e.name&&n.has(e.name)&&R(e,t.parent)&&!N(t.parent)&&r(e.name),o({parent:e})}});return o}(a,i,m);return{id:e,code:n,ast:a,imports:i,props:p,propsDeclaration:f,propsPattern:l,hasRestProp:d,childCalls:h,shadowedNames:g,debugNames:y,escapedComponents:x,barrelChildIds:w,bailReasons:u}}function z(e,n){if(e)switch(e.type){case"Identifier":return void(e.name&&n.add(e.name));case"ObjectPattern":for(const t of e.properties??[])"RestElement"===t.type?z(t.argument,n):"Property"===t.type&&z(t.value??t.key,n);return;case"ArrayPattern":for(const t of e.elements??[])z(t,n);return;case"AssignmentPattern":return void z(e.left,n);case"RestElement":return void z(e.argument,n);default:return}}function R(e,n){return!!n&&(!("MemberExpression"===n.type&&n.property===e&&!n.computed)&&(!("Property"===n.type&&n.key===e&&!n.computed&&!0!==n.shorthand)&&!N(n)))}function N(e){return null!=e&&("ImportSpecifier"===e.type||"ImportDefaultSpecifier"===e.type||"ImportNamespaceSpecifier"===e.type||"ExportSpecifier"===e.type)}function $(e){const n=e.attributes??[];let t=-1;for(let e=0;e<n.length;e++)"SpreadAttribute"===n[e].type&&(t=e);const o=new Map;for(let e=0;e<n.length;e++){const r=n[e],s=r.name;if("BindDirective"===r.type){s&&o.set(s,L(e,t));continue}if("Attribute"!==r.type||!s)continue;const a=B(r.value);o.set(s,a.known?{value:a.value,dynamic:!1,afterLastSpread:e>t}:L(e,t))}for(const r of function(e){const n=e.fragment?.nodes??[],t=[];let o=!1;for(const e of n)if("SnippetBlock"!==e.type){if("Comment"!==e.type){if("Text"===e.type){if(""===(e.data??e.raw??"").trim())continue}o=!0}}else"Identifier"===e.expression?.type&&e.expression.name&&t.push(e.expression.name);o&&t.push("children");return t}(e))o.set(r,L(n.length,t));return{hadSpread:t>=0,explicit:o}}function L(e,n){return{value:void 0,dynamic:!0,afterLastSpread:e>n}}function B(e){if(!0===e)return{known:!0,value:!0};if(null==e)return{known:!1};const n=Array.isArray(e)?e:[e];if(1===n.length){const e=n[0];return"Text"===e.type?{known:!0,value:e.data??e.raw??""}:"ExpressionTag"===e.type&&"Literal"===e.expression?.type?{known:!0,value:e.expression.value}:{known:!1}}let t="";for(const e of n){if("Text"!==e.type)return{known:!1};t+=e.data??e.raw??""}return{known:!0,value:t}}function O(e,n){return e.shadowedNames.has(n)||e.debugNames.has(n)}function T(e,n){const t={id:e.id,bail:!1,reasons:[],constFold:new Map,narrow:new Map,valueSets:new Map};if(e.bailReasons.length>0)return t.bail=!0,t.reasons.push(...e.bailReasons),t;if(!e.props||0===e.props.length)return t;const o=n?.sites??[];if(0===o.length)return t;for(const n of e.props){if(O(e,n.name))continue;const r=_(n,o);t.valueSets.set(n.name,r),r.top||r.dynamic||(1!==r.values.length?r.values.length>=2&&t.narrow.set(n.name,r.values):t.constFold.set(n.name,r.values[0]))}return t}function _(e,n){const t=[];let o=!1,r=!1;const s=e=>{t.some((n=>Object.is(n,e)))||t.push(e)};for(const t of n){const n=t.explicit.get(e.name);if(n?.afterLastSpread){n.dynamic?o=!0:s(n.value);continue}if(t.hadSpread){r=!0;continue}const a=j(e.defaultExpr);a.known?s(a.value):o=!0}return{values:t,dynamic:o,top:r}}function j(e){return e?"Literal"===e.type?{known:!0,value:e.value}:"Identifier"===e.type&&"undefined"===e.name?{known:!0,value:void 0}:{known:!1}:{known:!0,value:void 0}}function q(e){const n=e.imported;return"Identifier"===n?.type&&n.name?n.name:"Literal"===n?.type&&"string"==typeof n.value?n.value:void 0}function V(e){return"Identifier"===e?.type&&e.name?e.name:"Literal"===e?.type&&"string"==typeof e.value?e.value:void 0}const J=8;async function U(e,n,t,o,s,a=0){if(a>J)return null;const i=await o(e,t);if(!i)return null;if(k(e)||k(i))return"default"===n||"*"===n?i:null;let c;try{c=await s(i)}catch{return null}const u=function(e,n){try{const t=r(`<script module>\n${e}\n<\/script>`,n);return t.module?.content?.body??null}catch{return null}}(c,i);if(!u)return null;for(const e of u)if("ExportNamedDeclaration"===e.type&&e.source?.value){for(const t of e.specifiers??[])if(V(t.exported)===n)return U(String(e.source.value),V(t.local)??"default",i,o,s,a+1)}else if("ExportNamedDeclaration"!==e.type||e.source){if("ExportAllDeclaration"===e.type&&e.source?.value){const t=await U(String(e.source.value),n,i,o,s,a+1);if(t)return t}}else for(const t of e.specifiers??[]){if(V(t.exported)!==n)continue;const e=V(t.local);if(!e)continue;const r=W(u,e);return r?U(r.value,r.imported,i,o,s,a+1):null}return null}function W(e,n){for(const t of e){if("ImportDeclaration"!==t.type)continue;const e=t.source?.value;if("string"==typeof e)for(const o of t.specifiers??[])if(o.local?.name===n){if("ImportDefaultSpecifier"===o.type)return{value:e,imported:"default"};if("ImportNamespaceSpecifier"===o.type)return{value:e,imported:"*"};if("ImportSpecifier"===o.type)return{value:e,imported:q(o)??n}}}return null}const X=64;const G=Symbol("unbounded-class-source");function H(e,n,t){if(!0===e)return G;if(null==e)return new Set;const o=Array.isArray(e)?e:[e];let r=[""];for(const e of o){const o=K(e,n,t);if(o===G)return G;const s=[];for(const e of r)for(const n of o)if(s.push(e+n),s.length>X)return G;r=s}const s=new Set;for(const e of r)for(const n of e.split(/\s+/))n&&s.add(n);return s}function K(e,n,t){return"Text"===e.type?new Set([e.data??e.raw??""]):"ExpressionTag"===e.type?function(e,n,t){if(!e)return G;if("Identifier"===e.type&&e.name&&t.has(e.name)){const n=new Set;for(const o of t.get(e.name))n.add(Q(o));return n}const o=i(e,n);return o.known?new Set([Q(o.value)]):G}(e.expression,n,t):G}function Q(e){return String(e)}function Y(e,n,t){const o=e.ast.css;if(!o||!o.children)return 0;const r=function(e,n){const t=new Set;let o=!1;const r=n.constFold,a=n.narrow;return s(e.ast.fragment,null,{_(e,{next:n}){if("RegularElement"===(s=e.type)||"SvelteElement"===s||"Component"===s||"SvelteComponent"===s||"SvelteSelf"===s){var s;for(const n of e.attributes??[]){if("SpreadAttribute"===n.type){o=!0;continue}if("ClassDirective"===n.type){n.name&&t.add(n.name);continue}if("Attribute"!==n.type||"class"!==n.name)continue;const e=H(n.value,r,a);if(e===G)o=!0;else for(const n of e)t.add(n)}n()}else n()}}),{classes:t,unbounded:o}}(e,n);if(r.unbounded)return 0;let a=0;for(const n of o.children)"Rule"===n.type&&Z(n,r.classes)&&(ee(e.code,n,o.children,t),a+=1);return a}function Z(e,n){if(function(e){let n=!1;return s(e,null,{_(e,{next:t}){"PseudoClassSelector"===e.type&&"global"===e.name&&(n=!0),t()}}),n}(e))return!1;const t=e.prelude?.children??[];return 0!==t.length&&t.every((e=>function(e,n){let t=!1;for(const o of e.children??[])for(const e of o.selectors??[])"ClassSelector"===e.type&&e.name&&!n.has(e.name)&&(t=!0);return t}(e,n)))}function ee(e,n,t,o){const r=t.indexOf(n),s=t[r-1];let a=n.start;const i=s?s.end:0;for(;a>i&&/\s/.test(e[a-1]);)a-=1;o.remove(a,n.end)}function ne(e,n){return oe(e,te(e,n))}function te(e,n){const t=new Map,r=new Map;for(const s of e.values()){const e=new o(s.code);t.set(s.id,e);const a=n.get(s.id);r.set(s.id,a.bail?new Set:ce(s,a,e))}for(const n of e.values())me(n,r,t.get(n.id));return t}function oe(e,n){const t={};for(const o of e.values())t[o.id]=n.get(o.id).toString();return t}function re(e,n,t,o){const r=te(e,n);return function(e,n,t,o){const r=new Map;for(const e of n){const n=r.get(e.owner);n?n.push(e):r.set(e.owner,[e])}for(const[n,s]of r){const r=e.get(n),a=o.get(n);if(!r||!a)continue;const i=new Map,c=[];let u=0;for(const e of s){const n=e.node.name??"Cmp";let o=i.get(e.variantId);void 0===o&&(o=`${n}__shaker_v${u++}`,i.set(e.variantId,o),c.push({local:o,spec:t(e.variantId)})),se(r.code,e.node,o,e.foldedProps,a)}c.length>0&&ie(r,c,a)}}(e,t,o,r),oe(e,r)}function se(e,n,t,o,r){const s=n.name;if(!s)return;const a=n.start+1;e.slice(a,a+s.length)===s&&r.overwrite(a,a+s.length,t);const i=`</${s}`,c=e.lastIndexOf(i,n.end);if(c>=n.start){const e=c+2;r.overwrite(e,e+s.length,t)}for(const t of n.attributes??[])"Attribute"===t.type&&t.name&&o.has(t.name)&&ae(e,t,r)}function ae(e,n,t){let o=n.start;" "!==e[o-1]&&"\t"!==e[o-1]||(o-=1),t.remove(o,n.end)}function ie(e,n,t){const o=n.map((e=>` import ${e.local} from ${JSON.stringify(e.spec)};`)).join("\n"),r=e.ast.instance,s=r?.content?.body??[];if(r&&s.length>0){const e=s[s.length-1];t.appendLeft(e.end,`\n${o}`)}else r&&r.content?t.appendLeft(r.content.start,`\n${o}\n`):t.prepend(`<script>\n${o}\n<\/script>\n`)}function ce(e,n,t){return ue(e,n.constFold,n.narrow,n,t)}function ue(e,n,t,o,r){if(0===n.size&&0===t.size)return new Set;const a=e.code,c=[];!function(e,n,t,o,r,a){s(e,null,{IfBlock(e,{next:s}){if(e.elseif||g(e,a))return;const i=d(e,n,t);if(function(e,n,t,o){if(e.kept)return void o.overwrite(e.span[0],e.span[1],function(e,n,t){const o=e?.nodes??[];return 0===o.length?"":fe(o[0].start,o[o.length-1].end,o,n,t)}(e.kept,n,t));for(const[n,t]of e.removed)o.remove(n,t);if(e.headerRewrite){const{from:n,to:t,text:r}=e.headerRewrite;o.overwrite(n,t,r)}}(i,n,o,r),i.kept)a.push(i.span);else for(const e of i.removed)a.push(e);i.recurse&&s()}})}(e.ast.fragment,n,t,a,r,c),function(e,n,t,o,r){if(0===n.size)return;s(e,null,{ConditionalExpression(e,{next:s}){if(g(e,r))return;const a=i(e.test,n);if(!a.known)return void s();const c=a.value?e.consequent:e.alternate;c?(o.overwrite(e.start,e.end,fe(c.start,c.end,[c],n,t)),r.push([e.start,e.end])):s()}})}(e.ast.fragment,n,a,r,c);const u=function(e,n,t){const o=new Map,r=r=>{r&&s(r,{parent:null},{_(r,{state:s,next:a}){"Identifier"===r.type&&r.name&&n.has(r.name)&&!g(r,t)&&r!==e.propsPattern&&!le(r,s.parent)&&(o.get(r.name)??function(e,n){const t=[];return e.set(n,t),t}(o,r.name)).push([r.start,r.end]),a({parent:r})}})};return r(e.ast.instance),r(e.ast.fragment),o}(e,n,c);for(const[e,t]of n)for(const n of u.get(e)??[])r.overwrite(n[0],n[1],he(t));const f=new Set(n.keys());!function(e,n,t){if(!e.props||0===n.size)return;const o=e.props.filter((e=>!n.has(e.name)));if(0===o.length&&!e.hasRestProp&&e.propsDeclaration)return void function(e,n,t){let o=n.start;for(;o>0&&"\n"!==e[o-1];)o-=1;let r=n.end;for(;r<e.length&&"\n"!==e[r];)r+=1;const s=e.slice(o,n.start),a=e.slice(n.end,r);/^\s*$/.test(s)&&/^\s*;?\s*$/.test(a)?t.remove(o,r<e.length?r+1:r):t.remove(n.start,";"===e[n.end]?n.end+1:n.end)}(e.code,e.propsDeclaration,t);const r=e.propsPattern?.properties??[];for(const o of e.props)n.has(o.name)&&(pe(r,o.property,t),e.propsPattern&&de(e.propsPattern,o.name,t))}(e,f,r);return Y(e,{...o,constFold:n,narrow:t},r),f}function fe(e,n,t,o,r){if(0===o.size)return r.slice(e,n);const a=[];for(const e of t)s(e,{parent:null},{_(e,{state:n,next:t}){"Identifier"===e.type&&e.name&&o.has(e.name)&&!le(e,n.parent)&&a.push({start:e.start,end:e.end,name:e.name}),t({parent:e})}});if(0===a.length)return r.slice(e,n);a.sort(((e,n)=>e.start-n.start));let i="",c=e;for(const e of a)i+=r.slice(c,e.start),i+=he(o.get(e.name)),c=e.end;return i+=r.slice(c,n),i}function le(e,n){return!!n&&("MemberExpression"===n.type&&n.property===e&&!n.computed||("Property"===n.type&&n.key===e&&!n.computed&&!0!==n.shorthand||("ImportSpecifier"===n.type||"ImportDefaultSpecifier"===n.type||"ImportNamespaceSpecifier"===n.type||"ExportSpecifier"===n.type)))}function pe(e,n,t){const o=e.indexOf(n),r=e[o+1],s=e[o-1];r?t.remove(n.start,r.start):s?t.remove(s.end,n.end):t.remove(n.start,n.end)}function de(e,n,t){const o=e.typeAnnotation?.typeAnnotation?.members??[],r=o.findIndex((e=>"Identifier"===e.key?.type&&e.key.name===n));if(-1===r)return;const s=o[r],a=o[r+1],i=o[r-1];a?t.remove(s.start,a.start):i?t.remove(i.end,s.end):t.remove(s.start,s.end)}function me(e,n,t){s(e.ast.fragment,null,{Component(o,{next:r}){const s=o.name?e.imports.get(o.name):void 0,a=s?n.get(s):void 0;if(a&&a.size>0)for(const n of o.attributes??[])"Attribute"===n.type&&n.name&&a.has(n.name)&&ve(n.value)&&ae(e.code,n,t);r()}})}function ve(e){if(!0===e||null==e)return!0;return(Array.isArray(e)?e:[e]).every((e=>"Text"===e.type||"ExpressionTag"===e.type&&"Literal"===e.expression?.type))}function he(e){return void 0===e?"undefined":JSON.stringify(e)}const we={enabled:!1,maxVariants:8,minSavings:0};function ge(e,t,o=we,r=[]){const s=new Map,a=[];if(!o.enabled)return{variants:s,bindings:a};const i=D(e,t),c=new Map,u=new Set;for(const n of e.values()){const o=i.get(n.id)??[];for(const r of n.childCalls){if(o.length>0&&g(r.node,o))continue;const s=e.get(r.childId),a=t.get(r.childId);if(!s||!a)continue;if(a.bail||!s.props||0===s.props.length){u.add(r.childId);continue}const i=xe(r.node,s,a);if(0===i.size){u.add(r.childId);continue}const f=be(s,a,i);if(f===Ie(s,a)){u.add(r.childId);continue}const l=c.get(r.childId);l?l.push({owner:n.id,node:r.node,shape:i,code:f}):c.set(r.childId,[{owner:n.id,node:r.node,shape:i,code:f}])}}const f=function(e,n){const t=new Map;for(const o of e.values()){const e=n.get(o.id);t.set(o.id,e.bail?o.code:Ie(o,e))}return t}(e,t),l=new Map;for(const n of e.values())l.set(n.id,ke(f.get(n.id),n));const p=new Set;for(const e of l.values())for(const n of e)p.add(n);const d=(Array.isArray(r)?r:[r]).filter((n=>e.has(n))).filter((e=>!p.has(e))),m=new Map,v=(e,t)=>{const o=m.get(t);if(void 0!==o)return o;let r;try{const{js:o}=n(t,{generate:"client",dev:!1,filename:e});r=o.code.length}catch{r=null}return null!==r&&m.set(t,r),r},h=new Set;for(const e of c.keys())u.has(e)||h.add(e);for(const[n,t]of c){if(u.has(n))continue;if(t.some((e=>e.owner!==n&&h.has(e.owner))))continue;const r=new Map,i=[];let c=!1;for(const e of t){if(r.has(e.code))continue;if(i.length>=o.maxVariants){c=!0;break}const t=`${n}::v${i.length}`;r.set(e.code,t),i.push({id:t,code:e.code})}if(!c&&ye(n,i,e,f,l,d,v,o.minSavings)){for(const e of i){const o=t.find((n=>n.code===e.code));s.set(e.id,{id:e.id,childId:n,code:e.code,foldedProps:o.shape})}for(const e of t)a.push({owner:e.owner,childId:n,node:e.node,variantId:r.get(e.code),foldedProps:e.shape})}}return{variants:s,bindings:a}}function ye(e,n,t,o,r,s,a,i){const c=t.get(e),u=new Map;for(const e of n)u.set(e.id,ke(e.code,c));const f=new Set,l=[...s];for(;l.length>0;){const e=l.pop();if(!f.has(e)){f.add(e);for(const n of r.get(e)??[])l.push(n)}}let p=0;for(const e of f){const n=a(e,o.get(e));if(null===n)return!1;p+=n}const d=n.map((e=>e.id)),m=new Set,v=new Set,h=n=>n===e?{comps:[],vars:d}:{comps:[n],vars:[]},w=[],g=[];for(const e of s){const n=h(e);w.push(...n.comps),g.push(...n.vars)}for(;w.length>0||g.length>0;){if(w.length>0){const e=w.pop();if(m.has(e))continue;m.add(e);for(const n of r.get(e)??[]){const e=h(n);w.push(...e.comps),g.push(...e.vars)}continue}const e=g.pop();if(!v.has(e)){v.add(e);for(const n of u.get(e)??[]){const e=h(n);w.push(...e.comps),g.push(...e.vars)}}}let y=0;for(const e of m){const n=a(e,o.get(e));if(null===n)return!1;y+=n}for(const e of v){const t=n.find((n=>n.id===e)).code,o=a(e,t);if(null===o)return!1;y+=o}return y<p*(1-i)}function ke(e,n){let t;try{t=r(e,n.id)}catch{return[]}const o=[];return s(t.fragment,null,{Component(e,{next:t}){const r=e.name?n.imports.get(e.name):void 0;r&&o.push(r),t()}}),o}function xe(e,n,t){const o=$(e),r=new Map;for(const e of n.props??[])r.set(e.name,e);const s=new Map;for(const[e,a]of o.explicit)r.has(e)&&(t.constFold.has(e)||O(n,e)||!a.dynamic&&a.afterLastSpread&&s.set(e,a.value));return s}function be(e,n,t){const r=new Map(n.constFold);for(const[e,n]of t)r.set(e,n);const s=new Map;for(const[e,t]of n.narrow)r.has(e)||s.set(e,t);const a=new o(e.code);return ue(e,r,s,n,a),a.toString()}const Se=new WeakMap;function Ie(e,n){const t=Se.get(e);if(void 0!==t)return t;const r=new o(e.code);ue(e,n.constFold,n.narrow,n,r);const s=r.toString();return Se.set(e,s),s}async function Me(e,n,t){const{models:o,plans:r}=await I(e,n,t);return ne(o,r)}async function Ee(e,n,t,o=we,r=(e=>e)){const{models:s,plans:a}=await I(e,n,t),i=ge(s,a,o,e);return{files:0===i.bindings.length?ne(s,a):re(s,a,i.bindings.map((e=>({owner:e.owner,node:e.node,variantId:e.variantId,foldedProps:e.foldedProps}))),r),mono:i}}export{we as DEFAULT_MONO_OPTIONS,I as analyze,ge as monomorphize,Me as svelteShaker,Ee as svelteShakerWithMono,ne as transformAll,re as transformAllWithMono};
package/dist/scan.js ADDED
@@ -0,0 +1 @@
1
+ import*as e from"node:fs";import*as t from"node:path";const n=(e,n)=>e.startsWith(".")?t.resolve(t.dirname(n),e):null,o=t=>e.readFileSync(t,"utf-8");function r(n){const o=[];let s;try{s=e.readdirSync(n,{withFileTypes:!0})}catch{return o}for(const e of s){if("node_modules"===e.name||e.name.startsWith("."))continue;const s=t.join(n,e.name);e.isDirectory()?o.push(...r(s)):e.isFile()&&e.name.endsWith(".svelte")&&o.push(s)}return o}export{r as collectSvelteFiles,o as fsReadFile,n as fsResolve};
@@ -0,0 +1,135 @@
1
+ import { type AnyNode, type Root } from './parse';
2
+ import { type ComponentId, type ComponentPlan, type Literal } from './ir';
3
+ import { type Span } from './dead';
4
+ export type Resolve = (source: string, importer: ComponentId) => Promise<ComponentId | null> | ComponentId | null;
5
+ export type ReadFile = (id: ComponentId) => Promise<string> | string;
6
+ /** One declared prop in a `$props()` destructuring. */
7
+ export interface PropDecl {
8
+ name: string;
9
+ /** The `Property` node inside the `ObjectPattern` (for surgical removal). */
10
+ property: AnyNode;
11
+ /** Default value expression, if `name = <default>`. */
12
+ defaultExpr?: AnyNode | undefined;
13
+ }
14
+ /** Everything we learn from parsing one component, reused by the transform. */
15
+ export interface FileModel {
16
+ id: ComponentId;
17
+ code: string;
18
+ ast: Root;
19
+ /** local import name (`Sub`) -> resolved child component id. */
20
+ imports: Map<string, ComponentId>;
21
+ /** Declared props, or `null` if the component has no `$props()` pattern. */
22
+ props: PropDecl[] | null;
23
+ /** The `let { ... } = $props()` declaration + its pattern, for editing. */
24
+ propsDeclaration?: AnyNode | undefined;
25
+ propsPattern?: AnyNode | undefined;
26
+ hasRestProp: boolean;
27
+ /**
28
+ * Every `<Child .../>` instance THIS component renders, with the child it
29
+ * resolves to and the AST node (so the fixpoint can test whether the site
30
+ * falls inside a dead `{#if}` span of this component — docs §2.1).
31
+ */
32
+ childCalls: ChildCall[];
33
+ /**
34
+ * Names this component binds OUTSIDE the `$props()` pattern — local `let` /
35
+ * `function` declarations in the instance script, and every template-scope
36
+ * binder (`{#each … as ctx, i}`, destructure patterns, `{#snippet name(p)}`,
37
+ * `{#await … then v}` / `{:catch e}`, `let:` directives). A declared prop
38
+ * whose name collides with any of these is a DIFFERENT entity inside that
39
+ * scope, so folding/substituting/dropping it would corrupt the binding (and
40
+ * often produce invalid Svelte). We therefore never fold such a prop.
41
+ */
42
+ shadowedNames: Set<string>;
43
+ /**
44
+ * Names that appear as a `{@debug …}` argument. Svelte requires those to be
45
+ * bare identifiers, so substituting a folded literal there is invalid and
46
+ * dropping the prop dangles the reference — we never fold a prop named here.
47
+ */
48
+ debugNames: Set<string>;
49
+ /**
50
+ * Resolved ids of CHILD components this file leaks as a value (escape, docs
51
+ * §4.1) — e.g. `<svelte:component this={Child}>`. `analyze` unions these
52
+ * across the program and bails every escaped component completely, since its
53
+ * prop profile can no longer be observed from `<Child .../>` sites alone.
54
+ */
55
+ escapedComponents: Set<ComponentId>;
56
+ /**
57
+ * Resolved ids of CHILD components this file renders through an import we do
58
+ * NOT treat as a direct `.svelte` default (a named/namespace import, or a
59
+ * `.js`/`.ts` barrel re-exporting a `.svelte` default). These `<Comp .../>`
60
+ * sites are invisible to {@link collectChildCalls} (whose attribution keys off
61
+ * the default-import `imports` map only), so the child's value set would omit
62
+ * them — folding/narrowing on a partial set is unsound (docs §4.2: every
63
+ * consumer must be enumerated). `analyze` unions these across the program and
64
+ * bails every such child completely, just like an escape.
65
+ */
66
+ barrelChildIds: Set<ComponentId>;
67
+ /** Reasons this whole component must be left untouched. */
68
+ bailReasons: string[];
69
+ }
70
+ /** One `<Child .../>` instance rendered by a component. */
71
+ export interface ChildCall {
72
+ childId: ComponentId;
73
+ node: AnyNode;
74
+ }
75
+ /**
76
+ * One value passed explicitly to a prop at one call site, after last-write-wins
77
+ * has been resolved (`{...obj}` aside). `dynamic` means the attribute had a
78
+ * non-literal value (`bind:`, dynamic expression): used, value not statically
79
+ * known. `afterLastSpread` records whether this explicit write happened after
80
+ * the site's last `{...spread}` — only then can a spread not silently override
81
+ * it (docs §4.1, "後勝ち順序で救う").
82
+ */
83
+ export interface ExplicitProp {
84
+ value: Literal;
85
+ dynamic: boolean;
86
+ afterLastSpread: boolean;
87
+ }
88
+ /** How a child component is called at one `<Child .../>` site. */
89
+ export interface CallSite {
90
+ /** Did this site have at least one `{...spread}` attribute? */
91
+ hadSpread: boolean;
92
+ /** Last-write-wins explicit props at this site, keyed by prop name. */
93
+ explicit: Map<string, ExplicitProp>;
94
+ }
95
+ export interface AnalyzeResult {
96
+ models: Map<ComponentId, FileModel>;
97
+ plans: Map<ComponentId, ComponentPlan>;
98
+ }
99
+ /**
100
+ * Crawl the component graph from `entries` and compute a plan per component,
101
+ * iterating to a whole-program fixpoint (docs §2.1).
102
+ *
103
+ * The crucial cascade: a `<Child/>` that lives inside a branch we fold away must
104
+ * NOT count toward the child's prop profile. Excluding it can shrink the
105
+ * child's value sets and enable more folding, which can fold away yet more
106
+ * branches. So we parse every component once, then alternate between
107
+ * (a) collecting call sites that are NOT inside a current dead span, and
108
+ * (b) recomputing plans (and hence dead spans) from that usage,
109
+ * until the plans stop changing.
110
+ */
111
+ export declare function analyze(entries: ComponentId | ComponentId[], resolve: Resolve, readFile: ReadFile): Promise<AnalyzeResult>;
112
+ /**
113
+ * Dead `{#if}` spans per component implied by `plans`, via the SAME shared
114
+ * predicate the transform uses ({@link computeDeadSpans}). A bailed component
115
+ * folds nothing, so it has no dead spans.
116
+ */
117
+ export declare function deadSpansForPlans(models: Map<ComponentId, FileModel>, plans: Map<ComponentId, ComponentPlan>): Map<ComponentId, Span[]>;
118
+ /**
119
+ * Read one `<Child .../>` into a {@link CallSite}. Attributes are in source
120
+ * order, so we resolve last-write-wins (a later `a={…}` overrides an earlier
121
+ * one) and record, per prop, whether its winning write came *after* the last
122
+ * spread — the only case a spread cannot silently override it (docs §4.1).
123
+ */
124
+ export declare function readCallSite(component: AnyNode): CallSite;
125
+ /** Decide what to fold for one component from its global usage. */
126
+ /**
127
+ * Whether a declared prop name is unsafe to fold/narrow/drop because it is also
128
+ * bound elsewhere: shadowed by a local `let`/`function` or a template binder
129
+ * (`{#each as}`, snippet params, `{#await then}`, `let:`, `{@const}`), or used as
130
+ * a `{@debug}` argument (Svelte forbids a literal there). In those scopes the
131
+ * name is a different entity, so folding it would corrupt the binding (often
132
+ * invalid Svelte). Both L1 planning ({@link buildPlan}) and L2 specialization
133
+ * (mono.ts) must honor this identically.
134
+ */
135
+ export declare function isFoldBlockedName(model: FileModel, name: string): boolean;
@@ -0,0 +1,32 @@
1
+ import type MagicString from 'magic-string';
2
+ import type { ComponentPlan } from './ir';
3
+ import type { FileModel } from './analyze';
4
+ /**
5
+ * The set of class names any element this component renders could carry.
6
+ * `unbounded` means at least one element has a class source we cannot enumerate
7
+ * (a non-foldable `class={x}`, or a spread that could carry `class`), so the
8
+ * "possible class set" is really "all class names" and NO rule may be removed.
9
+ */
10
+ export interface PossibleClasses {
11
+ classes: Set<string>;
12
+ unbounded: boolean;
13
+ }
14
+ /**
15
+ * Compute the component's possible class set (docs §3, step 1). Sources:
16
+ * - static `class="a b"` -> the literal tokens,
17
+ * - `class:foo` directive -> `foo` is always possible (regardless of its cond),
18
+ * - `class="x-{expr}"` / `class={expr}` where every interpolated `expr` is
19
+ * foldable (constFold) or narrowable (narrow set) -> enumerate the tokens,
20
+ * - ANY unbounded source (`class={nonFoldable}`, or a `{...spread}` that could
21
+ * carry `class`) -> the whole set is unbounded.
22
+ */
23
+ export declare function computePossibleClasses(model: FileModel, plan: ComponentPlan): PossibleClasses;
24
+ /**
25
+ * Remove provably-dead top-level `<style>` rules via MagicString span removal
26
+ * (docs §3, step 2/3). A rule is removed ONLY when the possible class set is
27
+ * bounded, the rule contains no `:global(...)` anywhere, and EVERY selector in
28
+ * the rule's selector list contains at least one class `.C` with `C` absent from
29
+ * the possible set (so no selector in the list can match any element this
30
+ * component can render). Anything else is KEPT. Returns the number removed.
31
+ */
32
+ export declare function shakeCss(model: FileModel, plan: ComponentPlan, s: MagicString): number;
@@ -0,0 +1,71 @@
1
+ import { type AnyNode } from './parse';
2
+ import type { Literal } from './ir';
3
+ export type Span = [number, number];
4
+ /** One arm of an `{#if}` / `{:else if}` chain in source order. */
5
+ interface ChainArm {
6
+ block: AnyNode;
7
+ test: AnyNode | undefined;
8
+ consequent: AnyNode | undefined;
9
+ }
10
+ /**
11
+ * The outcome of folding one chain against the known environments.
12
+ *
13
+ * `removed` are source ranges that do NOT appear in the output (deleted branch
14
+ * markup, dead headers). `kept` is the single arm consequent that survives
15
+ * verbatim when the chain collapses to it (case (a)/(b1-else)), or `undefined`
16
+ * when the chain keeps its `{#if}` structure. `recurse` says whether the
17
+ * surviving subtree still contains live `{#if}` blocks that must be folded
18
+ * (true only when the original head arm is kept in place).
19
+ *
20
+ * `headerRewrite`, when present, promotes a surviving `{:else if …}` arm to a
21
+ * fresh `{#if …}` head: `[from, to]` is replaced by `text`. It carries no call
22
+ * site, so the dead-span view simply treats `[from, to]` as removed.
23
+ */
24
+ export interface ChainDecision {
25
+ span: Span;
26
+ removed: Span[];
27
+ kept: AnyNode | undefined;
28
+ recurse: boolean;
29
+ headerRewrite?: {
30
+ from: number;
31
+ to: number;
32
+ text: string;
33
+ } | undefined;
34
+ }
35
+ /**
36
+ * Collect the arms of an `{#if}` / `{:else if}` chain in source order, plus the
37
+ * trailing `{:else}` fragment if present. Each arm carries its own IfBlock node
38
+ * (the head, or an `elseif` continuation).
39
+ */
40
+ export declare function collectChain(top: AnyNode): {
41
+ arms: ChainArm[];
42
+ elseFrag?: AnyNode;
43
+ };
44
+ /**
45
+ * Decide how one if/else-if chain folds against `env` (constFold) and `setEnv`
46
+ * (value sets). Soundness: an arm is dropped only when its test is provably
47
+ * FALSE for every reachable value; the chain collapses to a consequent only when
48
+ * an arm is provably TRUE and every earlier arm is provably FALSE. Otherwise
49
+ * the head is kept and callers recurse for nested blocks.
50
+ *
51
+ * This is the single source of truth used by BOTH the transform and the
52
+ * analysis fixpoint, so they can never disagree on what folds.
53
+ */
54
+ export declare function decideChain(top: AnyNode, env: Map<string, Literal>, setEnv: Map<string, Literal[]>): ChainDecision;
55
+ /** End offset of a consequent fragment (its last node), or a fallback. */
56
+ export declare function consequentEnd(fragment: AnyNode | undefined, fallback: number): number;
57
+ /** Is `node` fully contained in any of the given spans? */
58
+ export declare function inSpans(node: AnyNode, spans: Span[]): boolean;
59
+ /**
60
+ * Compute the source spans that genuinely vanish from a component's output when
61
+ * its plan is applied — i.e. the markup deleted by dead-`{#if}` folding. This
62
+ * is the SAME predicate the transform uses (both go through {@link decideChain}),
63
+ * so a call site is excluded from a child's prop profile iff the transform would
64
+ * actually delete it (docs §2.1 cascade).
65
+ *
66
+ * We mirror the transform's walk: a chain whose head we keep is recursed into
67
+ * (nested blocks can still fold); a chain we rewrote/collapsed is not, and its
68
+ * span is skipped on later visits via `inSpans`.
69
+ */
70
+ export declare function computeDeadSpans(fragment: AnyNode, env: Map<string, Literal>, setEnv: Map<string, Literal[]>): Span[];
71
+ export {};
@@ -0,0 +1,26 @@
1
+ import type { AnyNode } from './parse';
2
+ import type { Literal } from './ir';
3
+ export type EvalResult = {
4
+ known: true;
5
+ value: Literal;
6
+ } | {
7
+ known: false;
8
+ };
9
+ /**
10
+ * A deliberately tiny, total constant evaluator over an ESTree expression,
11
+ * given an environment of statically-known identifiers. It never throws and
12
+ * never guesses: anything it cannot prove is `{ known: false }`.
13
+ *
14
+ * This is the M0 stand-in for the abstract-interpretation engine described in
15
+ * docs/ARCHITECTURE.md §13 — same contract (sound over-approximation, falls to
16
+ * unknown on non-distributive ops), just without the interprocedural lattice.
17
+ */
18
+ export declare function evaluate(node: AnyNode | null | undefined, env: Map<string, Literal>): EvalResult;
19
+ /**
20
+ * Sound set-aware predicate. `constEnv` holds props collapsed to a single
21
+ * literal (`constFold`); `setEnv` holds props whose reachable value set is known
22
+ * (`narrow`, >= 2 literals). Returns `{ known:true }` ONLY when the boolean is
23
+ * provable for the whole reachable set — a value reachable through the set keeps
24
+ * the branch. Anything outside the small supported fragment is `{ known:false }`.
25
+ */
26
+ export declare function evaluateWithSets(node: AnyNode | null | undefined, constEnv: Map<string, Literal>, setEnv: Map<string, Literal[]>): EvalResult;
@@ -0,0 +1,44 @@
1
+ import { type ReadFile, type Resolve } from './analyze';
2
+ import { type MonomorphizeOptions, type MonomorphizeResult } from './mono';
3
+ import type { ComponentId } from './ir';
4
+ export type { ComponentId } from './ir';
5
+ export type { Resolve, ReadFile } from './analyze';
6
+ export { analyze } from './analyze';
7
+ export { transformAll, transformAllWithMono } from './transform';
8
+ export { monomorphize, DEFAULT_MONO_OPTIONS, type MonomorphizeOptions, type MonomorphizeResult, type Variant, type CallSiteBinding, } from './mono';
9
+ /**
10
+ * Whole-program shake: crawl the component graph from `entry`, decide what to
11
+ * fold, and return the shaken source for every reachable `.svelte` file.
12
+ *
13
+ * `resolve` / `readFile` are injected so the engine stays environment-free —
14
+ * it has NO `node:*` imports, so it runs unchanged in the browser (the
15
+ * playground passes an in-memory file map). A Vite plugin passes `this.resolve`;
16
+ * Node callers use `fsResolve` / `fs.readFileSync` from `svelte-shaker/node`.
17
+ * See docs/ARCHITECTURE.md §5 — this is the Engine; the Shell owns resolution.
18
+ */
19
+ export declare function svelteShaker(entries: ComponentId | ComponentId[], resolve: Resolve, readFile: ReadFile): Promise<Record<ComponentId, string>>;
20
+ /** The full output of a shake including L2 specialization. */
21
+ export interface ShakeResult {
22
+ /**
23
+ * Whole-program output: shaken source per `.svelte` file. With L2 OFF this is
24
+ * byte-for-byte identical to {@link svelteShaker}; with L2 ON, owner files
25
+ * whose call sites were specialized have those sites rewritten to import a
26
+ * variant via `variantSpecifier(variantId)`.
27
+ */
28
+ files: Record<ComponentId, string>;
29
+ /** L2 specialized variants + call-site bindings (empty when L2 is off). */
30
+ mono: MonomorphizeResult;
31
+ }
32
+ /** Build the module specifier a rewritten call site imports a variant from. */
33
+ export type VariantSpecifier = (variantId: string) => string;
34
+ /**
35
+ * Whole-program shake WITH optional L2 monomorphization (docs §3 "L2").
36
+ *
37
+ * `mono` carries the specialized variants (id -> residual source) and the call
38
+ * sites bound to them; `files` is the wired owner source. The Shell resolves
39
+ * `variantSpecifier(id)` to a virtual module whose source is
40
+ * `mono.variants.get(id)!.code`. With `mono.enabled` false (default) nothing is
41
+ * specialized and `files` equals the L0/L1/L1.5 output exactly — a strict
42
+ * superset of the default behavior, so existing consumers are unaffected.
43
+ */
44
+ export declare function svelteShakerWithMono(entries: ComponentId | ComponentId[], resolve: Resolve, readFile: ReadFile, mono?: MonomorphizeOptions, variantSpecifier?: VariantSpecifier): Promise<ShakeResult>;
@@ -0,0 +1,75 @@
1
+ /** Resolved absolute path of a `.svelte` file. */
2
+ export type ComponentId = string;
3
+ /** A statically-known literal value a prop can take. */
4
+ export type Literal = string | number | boolean | null | undefined;
5
+ /**
6
+ * The join, over every call site in the program, of the value passed to a
7
+ * single prop. See the lattice in docs/ARCHITECTURE.md §2.2.
8
+ *
9
+ * M0 only ever produces `const` (single literal across all sites) and `top`
10
+ * (something we cannot reason about — never fold). `multi` / `dynamic` are
11
+ * declared now so L1.5 narrowing can be added without reshaping callers.
12
+ */
13
+ export type PropAbstraction = {
14
+ kind: 'bottom';
15
+ } | {
16
+ kind: 'const';
17
+ value: Literal;
18
+ } | {
19
+ kind: 'multi';
20
+ values: Literal[];
21
+ } | {
22
+ kind: 'dynamic';
23
+ } | {
24
+ kind: 'top';
25
+ reason: string;
26
+ };
27
+ /**
28
+ * The set of literal values one declared prop is seen to take across the whole
29
+ * program (default included for sites that omit it), plus the two ways it can
30
+ * escape the lattice. This is the value-set foundation later levels narrow on
31
+ * (docs §2.2 `multi`, §3 L1.5): `constFold` is just the `size === 1 && !dynamic
32
+ * && !top` projection of it. Kept on the plan as groundwork — no level yet
33
+ * consumes the multi-element / `dynamic` cases.
34
+ */
35
+ export interface PropValueSet {
36
+ /** Distinct literals observed (dedup'd; `undefined`/`null` are distinct). */
37
+ values: Literal[];
38
+ /** A non-literal value was passed somewhere (used, value not statically known). */
39
+ dynamic: boolean;
40
+ /**
41
+ * ⊤: a call-site spread may set this prop (docs §4.1 partial bail), so the
42
+ * value set is really "all values" and the prop must not be folded.
43
+ */
44
+ top: boolean;
45
+ }
46
+ /** What the analysis decides to do to one component. */
47
+ export interface ComponentPlan {
48
+ id: ComponentId;
49
+ /** Whole-component bail (accessors / customElement / escape). */
50
+ bail: boolean;
51
+ reasons: string[];
52
+ /**
53
+ * L0/L1: props that collapse to a single constant. Under the "攻め"
54
+ * default (docs §12-2) these are folded in the body, dropped from the
55
+ * `$props()` signature, and their attributes are removed at every call site.
56
+ */
57
+ constFold: Map<string, Literal>;
58
+ /**
59
+ * L1.5 value-set narrowing (docs §3): props whose reachable value set is a
60
+ * known set of >= 2 distinct literals (no `dynamic`/`top` contribution). We
61
+ * delete branches the prop can provably never reach (e.g. a `variant ===
62
+ * 'danger'` arm when `variant ∈ {'primary','secondary'}`), but — unlike
63
+ * `constFold` — the prop is still genuinely used/dynamic, so it is NOT
64
+ * substituted and NOT dropped from the `$props()` signature. Singletons stay
65
+ * in `constFold`; these two maps are disjoint.
66
+ */
67
+ narrow: Map<string, Literal[]>;
68
+ /**
69
+ * Per-declared-prop value-set foundation (see {@link PropValueSet}). Present
70
+ * for every declared prop the analysis reasoned about; `constFold` is its
71
+ * singleton projection and `narrow` is its multi-element projection.
72
+ */
73
+ valueSets: Map<string, PropValueSet>;
74
+ }
75
+ export declare function emptyPlan(id: ComponentId): ComponentPlan;
@@ -0,0 +1,82 @@
1
+ import { type FileModel } from './analyze';
2
+ import { type AnyNode } from './parse';
3
+ import type { ComponentId, ComponentPlan, Literal } from './ir';
4
+ /** Tuning knobs for L2 (docs §8.1, §13.2). All have sound defaults. */
5
+ export interface MonomorphizeOptions {
6
+ /** Master switch. Default OFF — every existing behavior is unchanged. */
7
+ enabled: boolean;
8
+ /**
9
+ * Cap on distinct specialized variants generated per component (docs §13.2
10
+ * "maxVariants"). Dedup by residual means this counts *distinct residuals*,
11
+ * not call sites; if a child's distinct residuals exceed the cap it cannot be
12
+ * specialized all-sites, so it keeps the base entirely. Default 8.
13
+ */
14
+ maxVariants: number;
15
+ /**
16
+ * Minimum FRACTION of the base-scenario module bytes the specialization must
17
+ * save before we apply it (docs §13.2 "measured net-win"). `0` (default) means
18
+ * specialize on ANY strict net reduction (`Sigma_spec < Sigma_base`); `0.15`
19
+ * would require a >=15% reduction. Higher is more conservative; it can never
20
+ * make L2 bloat, only decline more.
21
+ */
22
+ minSavings: number;
23
+ }
24
+ export declare const DEFAULT_MONO_OPTIONS: MonomorphizeOptions;
25
+ /**
26
+ * One generated specialized module for a component shape.
27
+ *
28
+ * `key` is the dedup key — the residual SOURCE itself, so two shapes with
29
+ * identical residuals collapse to one variant (docs §13.2). `code` is the
30
+ * slimmed `.svelte` source; `foldedProps` records which props this variant
31
+ * folded to which literal (the call-site shape), so the Shell can strip those
32
+ * attributes from the rewritten call site.
33
+ */
34
+ export interface Variant {
35
+ /** Stable id `<childId>::v<n>` — used as the virtual module specifier. */
36
+ id: string;
37
+ /** The component this is a specialization of. */
38
+ childId: ComponentId;
39
+ /** Slimmed `.svelte` source (the residual). */
40
+ code: string;
41
+ /** Props this variant froze to a literal (name -> value). */
42
+ foldedProps: Map<string, Literal>;
43
+ }
44
+ /** One call site that was assigned to a specialized variant. */
45
+ export interface CallSiteBinding {
46
+ /** The component that renders this `<Child .../>`. */
47
+ owner: ComponentId;
48
+ /** The component being called. */
49
+ childId: ComponentId;
50
+ /** The `<Child .../>` AST node (so the Shell can rewrite this exact site). */
51
+ node: AnyNode;
52
+ /** The variant this site resolves to. */
53
+ variantId: string;
54
+ /**
55
+ * The props THIS site froze to a literal. May differ from the resolved
56
+ * variant's `foldedProps` when two shapes dedup to one residual (a frozen prop
57
+ * that the residual ignores); the rewrite must strip THIS site's frozen attrs,
58
+ * so the binding carries its own shape rather than the dedup target's.
59
+ */
60
+ foldedProps: Map<string, Literal>;
61
+ }
62
+ /** The complete L2 result the Shell consumes. */
63
+ export interface MonomorphizeResult {
64
+ /** Every generated variant, keyed by its id. */
65
+ variants: Map<string, Variant>;
66
+ /** Per (owner, node) the variant a call site was specialized to. */
67
+ bindings: CallSiteBinding[];
68
+ }
69
+ /**
70
+ * Compute per-call-site specialized residuals and the dedup'd variant set under
71
+ * a MEASURED, never-bloat net-win gate (docs §3 L2, §13.2).
72
+ *
73
+ * Pure over `models`/`plans`: it reads the already-computed plans, finds the
74
+ * live call sites whose extra literal props fold, groups them per child, and —
75
+ * for each child — only specializes when (a) EVERY live site of that child gets
76
+ * a non-base residual (all-sites-or-nothing, so the base module becomes
77
+ * unreferenced) and (b) replacing the child with its variants strictly shrinks
78
+ * the whole-program module bytes reachable from `entries`. It never mutates the
79
+ * inputs and never touches the base transform, so with L2 off (or when no child
80
+ * passes the gate) the default whole-program output is byte-for-byte unchanged.
81
+ */
82
+ export declare function monomorphize(models: Map<ComponentId, FileModel>, plans: Map<ComponentId, ComponentPlan>, options?: MonomorphizeOptions, entries?: ComponentId | ComponentId[]): MonomorphizeResult;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * A deliberately loose view of the Svelte + ESTree AST: only the fields this
3
+ * engine reads, each optional. Avoiding an index signature keeps named access
4
+ * compatible with `noPropertyAccessFromIndexSignature` while still letting us
5
+ * walk an untyped tree. `value` is `unknown` because it means different things
6
+ * on `Literal` (a literal) vs `Attribute` (true | node | node[]).
7
+ */
8
+ export interface AnyNode {
9
+ type: string;
10
+ start: number;
11
+ end: number;
12
+ test?: AnyNode | undefined;
13
+ consequent?: AnyNode | undefined;
14
+ alternate?: AnyNode | null | undefined;
15
+ expression?: AnyNode | undefined;
16
+ argument?: AnyNode | undefined;
17
+ left?: AnyNode | undefined;
18
+ right?: AnyNode | undefined;
19
+ callee?: AnyNode | undefined;
20
+ id?: AnyNode | undefined;
21
+ init?: AnyNode | undefined;
22
+ key?: AnyNode | undefined;
23
+ property?: AnyNode | undefined;
24
+ source?: AnyNode | undefined;
25
+ local?: AnyNode | undefined;
26
+ /** ImportSpecifier / ExportSpecifier exported-name slot. */
27
+ imported?: AnyNode | undefined;
28
+ exported?: AnyNode | undefined;
29
+ typeAnnotation?: AnyNode | undefined;
30
+ content?: AnyNode | undefined;
31
+ fragment?: AnyNode | null | undefined;
32
+ instance?: AnyNode | null | undefined;
33
+ module?: AnyNode | null | undefined;
34
+ css?: AnyNode | null | undefined;
35
+ context?: AnyNode | undefined;
36
+ error?: AnyNode | null | undefined;
37
+ then?: AnyNode | null | undefined;
38
+ catch?: AnyNode | null | undefined;
39
+ declaration?: AnyNode | undefined;
40
+ prelude?: AnyNode | undefined;
41
+ block?: AnyNode | null | undefined;
42
+ combinator?: AnyNode | null | undefined;
43
+ args?: AnyNode | null | undefined;
44
+ attributes?: AnyNode[] | undefined;
45
+ properties?: AnyNode[] | undefined;
46
+ members?: AnyNode[] | undefined;
47
+ body?: AnyNode[] | undefined;
48
+ declarations?: AnyNode[] | undefined;
49
+ specifiers?: AnyNode[] | undefined;
50
+ nodes?: AnyNode[] | undefined;
51
+ /** SnippetBlock parameters; ArrayPattern elements; DebugTag identifiers. */
52
+ parameters?: AnyNode[] | undefined;
53
+ /** Function / arrow ESTree parameters (`function f(a, b)`, `(a) => …`). */
54
+ params?: AnyNode[] | undefined;
55
+ elements?: (AnyNode | null)[] | undefined;
56
+ identifiers?: AnyNode[] | undefined;
57
+ /** CSS StyleSheet/SelectorList/ComplexSelector children, Block children. */
58
+ children?: AnyNode[] | undefined;
59
+ /** RelativeSelector simple selectors (ClassSelector, TypeSelector, …). */
60
+ selectors?: AnyNode[] | undefined;
61
+ name?: string | undefined;
62
+ /** EachBlock loop index variable name (a bare string, e.g. `i`). */
63
+ index?: string | undefined;
64
+ operator?: string | undefined;
65
+ raw?: string | undefined;
66
+ data?: string | undefined;
67
+ computed?: boolean | undefined;
68
+ shorthand?: boolean | undefined;
69
+ elseif?: boolean | undefined;
70
+ value?: unknown;
71
+ }
72
+ export interface Root extends AnyNode {
73
+ fragment: AnyNode;
74
+ }
75
+ export declare function parseSvelte(code: string, filename: string): Root;
76
+ export interface WalkCtx<S> {
77
+ state: S;
78
+ next: (state?: S) => void;
79
+ stop: () => void;
80
+ }
81
+ export type Visitors<S> = Record<string, (node: AnyNode, ctx: WalkCtx<S>) => void>;
82
+ /** `zimmerframe.walk`, narrowed to our loose node type. */
83
+ export declare function walk<S>(root: AnyNode, state: S, visitors: Visitors<S>): void;
@@ -0,0 +1,12 @@
1
+ import type { ComponentId } from './ir';
2
+ import type { Resolve, ReadFile } from './analyze';
3
+ /** Default filesystem resolver: resolve `source` relative to its importer. */
4
+ export declare const fsResolve: Resolve;
5
+ /** Default filesystem reader. */
6
+ export declare const fsReadFile: ReadFile;
7
+ /**
8
+ * Recursively collect every `.svelte` file under `dir` (skipping `node_modules`
9
+ * and dot-directories). A Shell helper, kept out of the env-free engine core
10
+ * (docs/ARCHITECTURE.md §5): plugins use it to seed the whole-program crawl.
11
+ */
12
+ export declare function collectSvelteFiles(dir: string): ComponentId[];
@@ -0,0 +1,45 @@
1
+ import MagicString from 'magic-string';
2
+ import { type AnyNode } from './parse';
3
+ import type { ComponentId, ComponentPlan, Literal } from './ir';
4
+ import type { FileModel } from './analyze';
5
+ /**
6
+ * Apply every plan to every component and return the shaken source per file.
7
+ *
8
+ * Two phases over a shared set of MagicStrings so that a parent's call-site
9
+ * attributes are removed using each child's *actually dropped* props (not just
10
+ * what the plan proposed): a prop only leaves the public signature when every
11
+ * reference to it could be folded or substituted away.
12
+ */
13
+ export declare function transformAll(models: Map<ComponentId, FileModel>, plans: Map<ComponentId, ComponentPlan>): Record<ComponentId, string>;
14
+ /**
15
+ * Like {@link transformAll}, but additionally rewrites the L2-bound call sites in
16
+ * each owner to import a specialized variant from a virtual module. The base
17
+ * phases are unchanged (so files with no binding are byte-identical to
18
+ * {@link transformAll}); phase 3 only edits regions phase 2 never touches — a
19
+ * bound `<Child …>` tag's NAME, and the frozen-prop attributes (which are
20
+ * disjoint from the dropped-prop attributes phase 2 removes, because a frozen
21
+ * prop is by construction NOT in the child's app-wide `constFold`).
22
+ *
23
+ * `variantImport(variantId)` maps a variant id to the module specifier the
24
+ * rewritten `import` should reference (the Shell supplies the virtual id).
25
+ */
26
+ export declare function transformAllWithMono(models: Map<ComponentId, FileModel>, plans: Map<ComponentId, ComponentPlan>, bindings: MonoBinding[], variantImport: (variantId: string) => string): Record<ComponentId, string>;
27
+ /** Minimal binding shape the rewrite needs (matches `mono.ts` CallSiteBinding). */
28
+ export interface MonoBinding {
29
+ owner: ComponentId;
30
+ node: AnyNode;
31
+ variantId: string;
32
+ /** Props the variant froze — their attributes are removed from the site. */
33
+ foldedProps: Map<string, Literal>;
34
+ }
35
+ /**
36
+ * Slim one component's body against the given fold (`env`) and narrow (`setEnv`)
37
+ * environments, editing `s` in place, and return the set of props that left the
38
+ * `$props()` signature. Factored out of {@link transformBody} so L2
39
+ * monomorphization (see `mono.ts`) can re-run the SAME pipeline with an augmented
40
+ * `env` (a call site's extra literal props) on a fresh MagicString — guaranteeing
41
+ * a specialized residual is produced by exactly the audited L0/L1/L1.5 machinery,
42
+ * never a parallel code path. `cssPlan` carries the value sets CSS removal reads
43
+ * (its `constFold`/`narrow` are overridden by `env`/`setEnv` before use).
44
+ */
45
+ export declare function shakeBody(model: FileModel, env: Map<string, Literal>, setEnv: Map<string, Literal[]>, cssPlan: ComponentPlan, s: MagicString): Set<string>;
@@ -0,0 +1,40 @@
1
+ import type { Plugin } from 'vite';
2
+ import { type MonomorphizeOptions } from './mono';
3
+ export interface ShakerOptions {
4
+ /**
5
+ * Directories (relative to the Vite root) to scan for `.svelte` components.
6
+ * Defaults to the Vite root itself. Every `.svelte` file found is treated as
7
+ * a call-site source, so the union of these dirs must contain the whole app
8
+ * for prop elimination to be sound (docs/ARCHITECTURE.md §4.2).
9
+ */
10
+ include?: string[];
11
+ /**
12
+ * Optimization level (docs §3). L0/L1/L1.5 are always on (`level >= 1`); only
13
+ * `level: 2` additionally enables L2 per-call-site monomorphization, which is
14
+ * OPT-IN. Default `1` — behavior with the level unset is unchanged.
15
+ */
16
+ level?: 0 | 1 | 2;
17
+ /**
18
+ * L2 monomorphization tuning (docs §13.2). Only consulted when `level: 2`.
19
+ * `true` enables it with defaults; an object overrides `maxVariants`. Defaults
20
+ * to OFF.
21
+ */
22
+ monomorphize?: boolean | Partial<Omit<MonomorphizeOptions, 'enabled'>>;
23
+ }
24
+ /**
25
+ * Source-level Svelte tree-shaking as a Vite plugin (docs/ARCHITECTURE.md §6).
26
+ *
27
+ * Build-only by design: `apply: 'build'` makes dev a pass-through, because the
28
+ * whole-program analysis is incompatible with HMR's locality (§6.2).
29
+ * `enforce: 'pre'` runs us before `@sveltejs/vite-plugin-svelte`, so we hand it
30
+ * already-slimmed `.svelte` source and stay decoupled from Svelte's codegen.
31
+ *
32
+ * L2 wiring (opt-in, `level: 2`): a specialized variant is exposed as a request
33
+ * for the ORIGINAL child file with a `?shaker_variant=<id>` query. Keeping the
34
+ * real `.svelte` path means the variant's own relative imports (`./Icon.svelte`)
35
+ * resolve exactly as they would in the unspecialized child, and vite-plugin-svelte
36
+ * still compiles it as a normal component; our `transform` swaps in the variant
37
+ * residual for that id. Two call sites with byte-identical residuals share one
38
+ * variant id (dedup), so they share one compiled module.
39
+ */
40
+ export declare function shaker(options?: ShakerOptions): Plugin;
package/dist/vite.js ADDED
@@ -0,0 +1 @@
1
+ import*as e from"node:fs";import*as n from"node:path";import{parse as t,compile as o}from"svelte/compiler";import{walk as r}from"zimmerframe";import s from"magic-string";function a(e,n){return t(e,{modern:!0,filename:n})}function i(e,n,t){r(e,n,t)}const c={known:!1};function u(e,n){if(!e)return c;switch(e.type){case"Literal":return{known:!0,value:e.value};case"Identifier":{const t=e.name??"";return"undefined"===t?{known:!0,value:void 0}:n.has(t)?{known:!0,value:n.get(t)}:c}case"UnaryExpression":{const t=u(e.argument,n);if(!t.known)return c;const o=t.value;switch(e.operator){case"!":return{known:!0,value:!o};case"-":return{known:!0,value:-o};case"+":return{known:!0,value:+o};case"typeof":return{known:!0,value:typeof o};case"void":return{known:!0,value:void 0};default:return c}}case"LogicalExpression":{const t=u(e.left,n);if(!t.known)return c;switch(e.operator){case"&&":return t.value?u(e.right,n):t;case"||":return t.value?t:u(e.right,n);case"??":return null===t.value||void 0===t.value?u(e.right,n):t;default:return c}}case"BinaryExpression":{const t=u(e.left,n),o=u(e.right,n);if(!t.known||!o.known)return c;const r=t.value,s=o.value;switch(e.operator){case"===":return{known:!0,value:r===s};case"!==":return{known:!0,value:r!==s};case"==":return{known:!0,value:r==s};case"!=":return{known:!0,value:r!=s};case"<":return{known:!0,value:r<s};case">":return{known:!0,value:r>s};case"<=":return{known:!0,value:r<=s};case">=":return{known:!0,value:r>=s};case"+":return{known:!0,value:r+s};case"-":return{known:!0,value:r-s};case"*":return{known:!0,value:r*s};case"/":return{known:!0,value:r/s};case"%":return{known:!0,value:r%s};default:return c}}default:return c}}function l(e,n,t){const o=u(e,n);if(o.known)return o;const r=f(e,n,t);return"unknown"===r?c:{known:!0,value:r}}function f(e,n,t){if(!e)return"unknown";switch(e.type){case"UnaryExpression":return"!"===e.operator?m(f(e.argument,n,t)):"unknown";case"LogicalExpression":{const s=f(e.left,n,t),a=()=>f(e.right,n,t);return"&&"===e.operator?!1!==s&&(o=s,r=a(),!1!==o&&!1!==r&&(!0===o&&!0===r||"unknown")):"||"===e.operator?!0===s||function(e,n){return!0===e||!0===n||(!1!==e||!1!==n)&&"unknown"}(s,a()):"unknown"}case"BinaryExpression":{const o=e.operator;if("==="===o||"=="===o||"!=="===o||"!="===o){const r="=="===o||"!="===o,s=function(e,n,t,o,r){const s=p(e,o),a=u(n,t);if(s&&a.known)return d(s,a.value,r);const i=p(n,o),c=u(e,t);return i&&c.known?d(i,c.value,r):c.known&&a.known?r?c.value==a.value:c.value===a.value:"unknown"}(e.left,e.right,n,t,r);return"!=="===o||"!="===o?m(s):s}return"unknown"}default:return"unknown"}var o,r}function p(e,n){return"Identifier"===e?.type&&e.name&&n.has(e.name)?n.get(e.name):null}function d(e,n,t){const o=t?e=>e==n:e=>e===n;return!!e.some(o)&&(!!e.every(o)||"unknown")}function m(e){return!0!==e&&(!1===e||"unknown")}function v(e,n,t){const{arms:o,elseFrag:r}=function(e){const n=[];let t,o=e;for(;o;){n.push({block:o,test:o.test,consequent:o.consequent});const e=o.alternate,r="Fragment"===e?.type&&1===e.nodes?.length&&"IfBlock"===e.nodes[0]?.type&&!0===e.nodes[0].elseif?e.nodes[0]:void 0;r?o=r:("Fragment"===e?.type&&(t=e),o=void 0)}return t?{arms:n,elseFrag:t}:{arms:n}}(e),s=[e.start,e.end],a=o.map((e=>l(e.test,n,t))),i=e=>e.known&&Boolean(e.value),c=e=>e.known&&!e.value;let u=!0;for(let e=0;e<o.length;e++){const n=a[e];if(i(n)&&u){const n=o[e].consequent;return{span:s,kept:n,removed:h(s,w(n)),recurse:!1}}c(n)||(u=!1)}const f=a.findIndex((e=>!c(e)));if(-1===f)return r?{span:s,kept:r,removed:h(s,w(r)),recurse:!1}:{span:s,kept:void 0,removed:[s],recurse:!1};if(0===f)return{span:s,kept:void 0,removed:y(o,a,f),recurse:!0};const p=o[f].block;return{span:s,kept:void 0,removed:[[s[0],p.start],...y(o,a,f)],recurse:!1,headerRewrite:{from:p.start,to:p.test.start,text:"{#if "}}}function h(e,n){if(!n)return[e];const t=[];return e[0]<n[0]&&t.push([e[0],n[0]]),n[1]<e[1]&&t.push([n[1],e[1]]),t}function w(e){const n=e?.nodes??[];return 0===n.length?null:[n[0].start,n[n.length-1].end]}function y(e,n,t){const o=[];for(let r=t+1;r<e.length;r++){const t=n[r];if(!t.known||t.value)continue;const s=e[r],a=e[r+1]?.block,i=a?a.start:g(s.consequent,s.block.end);o.push([s.block.start,i])}return o}function g(e,n){const t=e?.nodes??[];return t.length?t[t.length-1].end:n}function k(e,n){return n.some((([n,t])=>e.start>=n&&e.end<=t))}function x(e,n,t){if(0===n.size&&0===t.size)return[];const o=[];return i(e,null,{IfBlock(e,{next:r}){if(e.elseif||k(e,o))return;const s=v(e,n,t);for(const e of s.removed)o.push(e);s.recurse&&r()}}),o}const b=e=>e.endsWith(".svelte"),S=10,I="escapes as value (e.g. <svelte:component this={X}>)",M="rendered through a barrel/named import (call sites unobservable)";async function E(e,n,t){const o=await async function(e,n,t){const o=new Map,r=Array.isArray(e)?[...e]:[e],s=new Set(r);for(;r.length>0;){const e=r.shift(),a=await t(e),i=await z(e,a,n,t);o.set(e,i);for(const e of[...i.imports.values(),...i.barrelChildIds])s.has(e)||(s.add(e),r.push(e))}return o}(e,n,t),r=new Set;for(const e of o.values())for(const n of e.escapedComponents)r.add(n);for(const e of r){const n=o.get(e);n&&!n.bailReasons.includes(I)&&n.bailReasons.push(I)}const s=new Set;for(const e of o.values())for(const n of e.barrelChildIds)s.add(n);for(const e of s){const n=o.get(e);n&&!n.bailReasons.includes(M)&&n.bailReasons.push(M)}let a=$(o,A(o,new Map));for(let e=0;e<S;e++){const e=$(o,A(o,D(o,a)));if(C(a,e)){a=e;break}a=e}return{models:o,plans:a}}function A(e,n){const t=new Map,o=e=>{let n=t.get(e);return n||(n={sites:[]},t.set(e,n)),n};for(const t of e.values()){const e=n.get(t.id)??[];for(const n of t.childCalls)e.length>0&&k(n.node,e)||o(n.childId).sites.push(O(n.node))}return t}function $(e,n){const t=new Map;for(const o of e.values())t.set(o.id,j(o,n.get(o.id)));return t}function C(e,n){if(e.size!==n.size)return!1;for(const[t,o]of e){const e=n.get(t);if(!e)return!1;if(o.bail!==e.bail)return!1;if(!F(o.constFold,e.constFold))return!1;if(!P(o.narrow,e.narrow))return!1}return!0}function F(e,n){if(e.size!==n.size)return!1;for(const[t,o]of e)if(!n.has(t)||!Object.is(n.get(t),o))return!1;return!0}function P(e,n){if(e.size!==n.size)return!1;for(const[t,o]of e){const e=n.get(t);if(!e||o.length!==e.length)return!1;for(let n=0;n<o.length;n++)if(!Object.is(o[n],e[n]))return!1}return!0}function D(e,n){const t=new Map;for(const o of e.values()){const e=n.get(o.id);if(e.bail)continue;const r=x(o.ast.fragment,e.constFold,e.narrow);r.length>0&&t.set(o.id,r)}return t}async function z(e,n,t,o){const r=a(n,e),s=new Map,c=new Map,u=[];i(r.fragment,null,{SvelteOptions(e,{next:n}){for(const n of e.attributes??[])"Attribute"!==n.type||"accessors"!==n.name&&"customElement"!==n.name||u.push(`<svelte:options ${n.name}>`);n()}});let l,f,p=null,d=!1;const m=new Set,v=r.instance;if(v){for(const n of function*(e){const n=e.content;for(const e of n?.body??[]){if("ImportDeclaration"!==e.type)continue;const n=e.source?.value;if("string"==typeof n)for(const t of e.specifiers??[]){const e=t.local?.name;e&&("ImportDefaultSpecifier"===t.type?yield{value:n,local:e,imported:"default"}:"ImportNamespaceSpecifier"===t.type?yield{value:n,local:e,imported:"*"}:"ImportSpecifier"===t.type&&(yield{value:n,local:e,imported:V(t)??e}))}}}(v)){if(m.add(n.local),"default"===n.imported&&b(n.value)){const o=await t(n.value,e);o&&s.set(n.local,o);continue}const r=await X(n.value,n.imported,e,t,o);r&&c.set(n.local,r)}const n=function(e){const n=e.content;for(const e of n?.body??[])if("VariableDeclaration"===e.type)for(const n of e.declarations??[]){const t=n.init,o=n.id;if("CallExpression"===t?.type&&"Identifier"===t.callee?.type&&"$props"===t.callee.name&&"ObjectPattern"===o?.type)return{declaration:e,pattern:o,sharesStatement:(e.declarations?.length??1)>1}}return null}(v);if(n){l=n.declaration,f=n.pattern,n.sharesStatement&&u.push("$props() shares a multi-declarator statement"),p=[];for(const e of n.pattern.properties??[]){if("RestElement"===e.type){d=!0;continue}if("Property"!==e.type)continue;const n=e.key;if("Identifier"!==n?.type||!n.name)continue;const t=e.value,o="AssignmentPattern"===t?.type?t.right:void 0;p.push({name:n.name,property:e,defaultExpr:o})}}}const h=function(e,n){const t=[];return i(e.fragment,null,{Component(e,{next:o}){const r=e.name?n.get(e.name):void 0;r&&t.push({childId:r,node:e}),o()}}),t}(r,s),w=function(e,n){const t=new Set;return 0===n.size||i(e.fragment,null,{Component(e,{next:o}){const r=e.name?n.get(e.name):void 0;r&&t.add(r),o()}}),t}(r,c),{shadowedNames:y,debugNames:g}=function(e,n,t){const o=new Set,r=new Set;n&&i(n,null,{_(e,{next:n}){if("VariableDeclarator"!==e.type&&"FunctionDeclaration"!==e.type||e===t||"Identifier"!==e.id?.type||!e.id.name||o.add(e.id.name),"FunctionDeclaration"===e.type||"FunctionExpression"===e.type||"ArrowFunctionExpression"===e.type)for(const n of e.params??[])R(n,o);n()}});return i(e.fragment,null,{EachBlock(e,{next:n}){R(e.context,o),"string"==typeof e.index&&o.add(e.index),n()},SnippetBlock(e,{next:n}){"Identifier"===e.expression?.type&&e.expression.name&&o.add(e.expression.name);for(const n of e.parameters??[])R(n,o);n()},AwaitBlock(e,{next:n}){R(e.value,o),R(e.error,o),n()},LetDirective(e,{next:n}){e.name&&o.add(e.name),n()},ConstTag(e,{next:n}){for(const n of e.declaration?.declarations??[])R(n.id,o);n()},DebugTag(e,{next:n}){for(const n of e.identifiers??[])"Identifier"===n.type&&n.name&&r.add(n.name);n()}}),{shadowedNames:o,debugNames:r}}(r,v,l),k=function(e,n,t){const o=new Set,r=e=>{if(!e)return;const t=n.get(e);t&&o.add(t)};i(e.fragment,{parent:null},{_(e,{state:n,next:o}){"Identifier"===e.type&&e.name&&t.has(e.name)&&N(e,n.parent)&&r(e.name),o({parent:e})}}),e.instance&&i(e.instance,{parent:null},{_(e,{state:t,next:o}){"Identifier"===e.type&&e.name&&n.has(e.name)&&N(e,t.parent)&&!L(t.parent)&&r(e.name),o({parent:e})}});return o}(r,s,m);return{id:e,code:n,ast:r,imports:s,props:p,propsDeclaration:l,propsPattern:f,hasRestProp:d,childCalls:h,shadowedNames:y,debugNames:g,escapedComponents:k,barrelChildIds:w,bailReasons:u}}function R(e,n){if(e)switch(e.type){case"Identifier":return void(e.name&&n.add(e.name));case"ObjectPattern":for(const t of e.properties??[])"RestElement"===t.type?R(t.argument,n):"Property"===t.type&&R(t.value??t.key,n);return;case"ArrayPattern":for(const t of e.elements??[])R(t,n);return;case"AssignmentPattern":return void R(e.left,n);case"RestElement":return void R(e.argument,n);default:return}}function N(e,n){return!!n&&(!("MemberExpression"===n.type&&n.property===e&&!n.computed)&&(!("Property"===n.type&&n.key===e&&!n.computed&&!0!==n.shorthand)&&!L(n)))}function L(e){return null!=e&&("ImportSpecifier"===e.type||"ImportDefaultSpecifier"===e.type||"ImportNamespaceSpecifier"===e.type||"ExportSpecifier"===e.type)}function O(e){const n=e.attributes??[];let t=-1;for(let e=0;e<n.length;e++)"SpreadAttribute"===n[e].type&&(t=e);const o=new Map;for(let e=0;e<n.length;e++){const r=n[e],s=r.name;if("BindDirective"===r.type){s&&o.set(s,_(e,t));continue}if("Attribute"!==r.type||!s)continue;const a=B(r.value);o.set(s,a.known?{value:a.value,dynamic:!1,afterLastSpread:e>t}:_(e,t))}for(const r of function(e){const n=e.fragment?.nodes??[],t=[];let o=!1;for(const e of n)if("SnippetBlock"!==e.type){if("Comment"!==e.type){if("Text"===e.type){if(""===(e.data??e.raw??"").trim())continue}o=!0}}else"Identifier"===e.expression?.type&&e.expression.name&&t.push(e.expression.name);o&&t.push("children");return t}(e))o.set(r,_(n.length,t));return{hadSpread:t>=0,explicit:o}}function _(e,n){return{value:void 0,dynamic:!0,afterLastSpread:e>n}}function B(e){if(!0===e)return{known:!0,value:!0};if(null==e)return{known:!1};const n=Array.isArray(e)?e:[e];if(1===n.length){const e=n[0];return"Text"===e.type?{known:!0,value:e.data??e.raw??""}:"ExpressionTag"===e.type&&"Literal"===e.expression?.type?{known:!0,value:e.expression.value}:{known:!1}}let t="";for(const e of n){if("Text"!==e.type)return{known:!1};t+=e.data??e.raw??""}return{known:!0,value:t}}function T(e,n){return e.shadowedNames.has(n)||e.debugNames.has(n)}function j(e,n){const t={id:e.id,bail:!1,reasons:[],constFold:new Map,narrow:new Map,valueSets:new Map};if(e.bailReasons.length>0)return t.bail=!0,t.reasons.push(...e.bailReasons),t;if(!e.props||0===e.props.length)return t;const o=n?.sites??[];if(0===o.length)return t;for(const n of e.props){if(T(e,n.name))continue;const r=W(n,o);t.valueSets.set(n.name,r),r.top||r.dynamic||(1!==r.values.length?r.values.length>=2&&t.narrow.set(n.name,r.values):t.constFold.set(n.name,r.values[0]))}return t}function W(e,n){const t=[];let o=!1,r=!1;const s=e=>{t.some((n=>Object.is(n,e)))||t.push(e)};for(const t of n){const n=t.explicit.get(e.name);if(n?.afterLastSpread){n.dynamic?o=!0:s(n.value);continue}if(t.hadSpread){r=!0;continue}const a=q(e.defaultExpr);a.known?s(a.value):o=!0}return{values:t,dynamic:o,top:r}}function q(e){return e?"Literal"===e.type?{known:!0,value:e.value}:"Identifier"===e.type&&"undefined"===e.name?{known:!0,value:void 0}:{known:!1}:{known:!0,value:void 0}}function V(e){const n=e.imported;return"Identifier"===n?.type&&n.name?n.name:"Literal"===n?.type&&"string"==typeof n.value?n.value:void 0}function J(e){return"Identifier"===e?.type&&e.name?e.name:"Literal"===e?.type&&"string"==typeof e.value?e.value:void 0}const U=8;async function X(e,n,t,o,r,s=0){if(s>U)return null;const i=await o(e,t);if(!i)return null;if(b(e)||b(i))return"default"===n||"*"===n?i:null;let c;try{c=await r(i)}catch{return null}const u=function(e,n){try{const t=a(`<script module>\n${e}\n<\/script>`,n);return t.module?.content?.body??null}catch{return null}}(c,i);if(!u)return null;for(const e of u)if("ExportNamedDeclaration"===e.type&&e.source?.value){for(const t of e.specifiers??[])if(J(t.exported)===n)return X(String(e.source.value),J(t.local)??"default",i,o,r,s+1)}else if("ExportNamedDeclaration"!==e.type||e.source){if("ExportAllDeclaration"===e.type&&e.source?.value){const t=await X(String(e.source.value),n,i,o,r,s+1);if(t)return t}}else for(const t of e.specifiers??[]){if(J(t.exported)!==n)continue;const e=J(t.local);if(!e)continue;const a=G(u,e);return a?X(a.value,a.imported,i,o,r,s+1):null}return null}function G(e,n){for(const t of e){if("ImportDeclaration"!==t.type)continue;const e=t.source?.value;if("string"==typeof e)for(const o of t.specifiers??[])if(o.local?.name===n){if("ImportDefaultSpecifier"===o.type)return{value:e,imported:"default"};if("ImportNamespaceSpecifier"===o.type)return{value:e,imported:"*"};if("ImportSpecifier"===o.type)return{value:e,imported:V(o)??n}}}return null}const H=64;const K=Symbol("unbounded-class-source");function Q(e,n,t){if(!0===e)return K;if(null==e)return new Set;const o=Array.isArray(e)?e:[e];let r=[""];for(const e of o){const o=Y(e,n,t);if(o===K)return K;const s=[];for(const e of r)for(const n of o)if(s.push(e+n),s.length>H)return K;r=s}const s=new Set;for(const e of r)for(const n of e.split(/\s+/))n&&s.add(n);return s}function Y(e,n,t){return"Text"===e.type?new Set([e.data??e.raw??""]):"ExpressionTag"===e.type?function(e,n,t){if(!e)return K;if("Identifier"===e.type&&e.name&&t.has(e.name)){const n=new Set;for(const o of t.get(e.name))n.add(Z(o));return n}const o=u(e,n);return o.known?new Set([Z(o.value)]):K}(e.expression,n,t):K}function Z(e){return String(e)}function ee(e,n,t){const o=e.ast.css;if(!o||!o.children)return 0;const r=function(e,n){const t=new Set;let o=!1;const r=n.constFold,s=n.narrow;return i(e.ast.fragment,null,{_(e,{next:n}){if("RegularElement"===(a=e.type)||"SvelteElement"===a||"Component"===a||"SvelteComponent"===a||"SvelteSelf"===a){var a;for(const n of e.attributes??[]){if("SpreadAttribute"===n.type){o=!0;continue}if("ClassDirective"===n.type){n.name&&t.add(n.name);continue}if("Attribute"!==n.type||"class"!==n.name)continue;const e=Q(n.value,r,s);if(e===K)o=!0;else for(const n of e)t.add(n)}n()}else n()}}),{classes:t,unbounded:o}}(e,n);if(r.unbounded)return 0;let s=0;for(const n of o.children)"Rule"===n.type&&ne(n,r.classes)&&(te(e.code,n,o.children,t),s+=1);return s}function ne(e,n){if(function(e){let n=!1;return i(e,null,{_(e,{next:t}){"PseudoClassSelector"===e.type&&"global"===e.name&&(n=!0),t()}}),n}(e))return!1;const t=e.prelude?.children??[];return 0!==t.length&&t.every((e=>function(e,n){let t=!1;for(const o of e.children??[])for(const e of o.selectors??[])"ClassSelector"===e.type&&e.name&&!n.has(e.name)&&(t=!0);return t}(e,n)))}function te(e,n,t,o){const r=t.indexOf(n),s=t[r-1];let a=n.start;const i=s?s.end:0;for(;a>i&&/\s/.test(e[a-1]);)a-=1;o.remove(a,n.end)}function oe(e,n){return se(e,re(e,n))}function re(e,n){const t=new Map,o=new Map;for(const r of e.values()){const e=new s(r.code);t.set(r.id,e);const a=n.get(r.id);o.set(r.id,a.bail?new Set:le(r,a,e))}for(const n of e.values())he(n,o,t.get(n.id));return t}function se(e,n){const t={};for(const o of e.values())t[o.id]=n.get(o.id).toString();return t}function ae(e,n,t,o){const r=re(e,n);return function(e,n,t,o){const r=new Map;for(const e of n){const n=r.get(e.owner);n?n.push(e):r.set(e.owner,[e])}for(const[n,s]of r){const r=e.get(n),a=o.get(n);if(!r||!a)continue;const i=new Map,c=[];let u=0;for(const e of s){const n=e.node.name??"Cmp";let o=i.get(e.variantId);void 0===o&&(o=`${n}__shaker_v${u++}`,i.set(e.variantId,o),c.push({local:o,spec:t(e.variantId)})),ie(r.code,e.node,o,e.foldedProps,a)}c.length>0&&ue(r,c,a)}}(e,t,o,r),se(e,r)}function ie(e,n,t,o,r){const s=n.name;if(!s)return;const a=n.start+1;e.slice(a,a+s.length)===s&&r.overwrite(a,a+s.length,t);const i=`</${s}`,c=e.lastIndexOf(i,n.end);if(c>=n.start){const e=c+2;r.overwrite(e,e+s.length,t)}for(const t of n.attributes??[])"Attribute"===t.type&&t.name&&o.has(t.name)&&ce(e,t,r)}function ce(e,n,t){let o=n.start;" "!==e[o-1]&&"\t"!==e[o-1]||(o-=1),t.remove(o,n.end)}function ue(e,n,t){const o=n.map((e=>` import ${e.local} from ${JSON.stringify(e.spec)};`)).join("\n"),r=e.ast.instance,s=r?.content?.body??[];if(r&&s.length>0){const e=s[s.length-1];t.appendLeft(e.end,`\n${o}`)}else r&&r.content?t.appendLeft(r.content.start,`\n${o}\n`):t.prepend(`<script>\n${o}\n<\/script>\n`)}function le(e,n,t){return fe(e,n.constFold,n.narrow,n,t)}function fe(e,n,t,o,r){if(0===n.size&&0===t.size)return new Set;const s=e.code,a=[];!function(e,n,t,o,r,s){i(e,null,{IfBlock(e,{next:a}){if(e.elseif||k(e,s))return;const i=v(e,n,t);if(function(e,n,t,o){if(e.kept)return void o.overwrite(e.span[0],e.span[1],function(e,n,t){const o=e?.nodes??[];return 0===o.length?"":pe(o[0].start,o[o.length-1].end,o,n,t)}(e.kept,n,t));for(const[n,t]of e.removed)o.remove(n,t);if(e.headerRewrite){const{from:n,to:t,text:r}=e.headerRewrite;o.overwrite(n,t,r)}}(i,n,o,r),i.kept)s.push(i.span);else for(const e of i.removed)s.push(e);i.recurse&&a()}})}(e.ast.fragment,n,t,s,r,a),function(e,n,t,o,r){if(0===n.size)return;i(e,null,{ConditionalExpression(e,{next:s}){if(k(e,r))return;const a=u(e.test,n);if(!a.known)return void s();const i=a.value?e.consequent:e.alternate;i?(o.overwrite(e.start,e.end,pe(i.start,i.end,[i],n,t)),r.push([e.start,e.end])):s()}})}(e.ast.fragment,n,s,r,a);const c=function(e,n,t){const o=new Map,r=r=>{r&&i(r,{parent:null},{_(r,{state:s,next:a}){"Identifier"===r.type&&r.name&&n.has(r.name)&&!k(r,t)&&r!==e.propsPattern&&!de(r,s.parent)&&(o.get(r.name)??function(e,n){const t=[];return e.set(n,t),t}(o,r.name)).push([r.start,r.end]),a({parent:r})}})};return r(e.ast.instance),r(e.ast.fragment),o}(e,n,a);for(const[e,t]of n)for(const n of c.get(e)??[])r.overwrite(n[0],n[1],ye(t));const l=new Set(n.keys());!function(e,n,t){if(!e.props||0===n.size)return;const o=e.props.filter((e=>!n.has(e.name)));if(0===o.length&&!e.hasRestProp&&e.propsDeclaration)return void function(e,n,t){let o=n.start;for(;o>0&&"\n"!==e[o-1];)o-=1;let r=n.end;for(;r<e.length&&"\n"!==e[r];)r+=1;const s=e.slice(o,n.start),a=e.slice(n.end,r);/^\s*$/.test(s)&&/^\s*;?\s*$/.test(a)?t.remove(o,r<e.length?r+1:r):t.remove(n.start,";"===e[n.end]?n.end+1:n.end)}(e.code,e.propsDeclaration,t);const r=e.propsPattern?.properties??[];for(const o of e.props)n.has(o.name)&&(me(r,o.property,t),e.propsPattern&&ve(e.propsPattern,o.name,t))}(e,l,r);return ee(e,{...o,constFold:n,narrow:t},r),l}function pe(e,n,t,o,r){if(0===o.size)return r.slice(e,n);const s=[];for(const e of t)i(e,{parent:null},{_(e,{state:n,next:t}){"Identifier"===e.type&&e.name&&o.has(e.name)&&!de(e,n.parent)&&s.push({start:e.start,end:e.end,name:e.name}),t({parent:e})}});if(0===s.length)return r.slice(e,n);s.sort(((e,n)=>e.start-n.start));let a="",c=e;for(const e of s)a+=r.slice(c,e.start),a+=ye(o.get(e.name)),c=e.end;return a+=r.slice(c,n),a}function de(e,n){return!!n&&("MemberExpression"===n.type&&n.property===e&&!n.computed||("Property"===n.type&&n.key===e&&!n.computed&&!0!==n.shorthand||("ImportSpecifier"===n.type||"ImportDefaultSpecifier"===n.type||"ImportNamespaceSpecifier"===n.type||"ExportSpecifier"===n.type)))}function me(e,n,t){const o=e.indexOf(n),r=e[o+1],s=e[o-1];r?t.remove(n.start,r.start):s?t.remove(s.end,n.end):t.remove(n.start,n.end)}function ve(e,n,t){const o=e.typeAnnotation?.typeAnnotation?.members??[],r=o.findIndex((e=>"Identifier"===e.key?.type&&e.key.name===n));if(-1===r)return;const s=o[r],a=o[r+1],i=o[r-1];a?t.remove(s.start,a.start):i?t.remove(i.end,s.end):t.remove(s.start,s.end)}function he(e,n,t){i(e.ast.fragment,null,{Component(o,{next:r}){const s=o.name?e.imports.get(o.name):void 0,a=s?n.get(s):void 0;if(a&&a.size>0)for(const n of o.attributes??[])"Attribute"===n.type&&n.name&&a.has(n.name)&&we(n.value)&&ce(e.code,n,t);r()}})}function we(e){if(!0===e||null==e)return!0;return(Array.isArray(e)?e:[e]).every((e=>"Text"===e.type||"ExpressionTag"===e.type&&"Literal"===e.expression?.type))}function ye(e){return void 0===e?"undefined":JSON.stringify(e)}const ge={enabled:!1,maxVariants:8,minSavings:0};function ke(e,n,t=ge,r=[]){const s=new Map,a=[];if(!t.enabled)return{variants:s,bindings:a};const i=D(e,n),c=new Map,u=new Set;for(const t of e.values()){const o=i.get(t.id)??[];for(const r of t.childCalls){if(o.length>0&&k(r.node,o))continue;const s=e.get(r.childId),a=n.get(r.childId);if(!s||!a)continue;if(a.bail||!s.props||0===s.props.length){u.add(r.childId);continue}const i=Se(r.node,s,a);if(0===i.size){u.add(r.childId);continue}const l=Ie(s,a,i);if(l===Ee(s,a)){u.add(r.childId);continue}const f=c.get(r.childId);f?f.push({owner:t.id,node:r.node,shape:i,code:l}):c.set(r.childId,[{owner:t.id,node:r.node,shape:i,code:l}])}}const l=function(e,n){const t=new Map;for(const o of e.values()){const e=n.get(o.id);t.set(o.id,e.bail?o.code:Ee(o,e))}return t}(e,n),f=new Map;for(const n of e.values())f.set(n.id,be(l.get(n.id),n));const p=new Set;for(const e of f.values())for(const n of e)p.add(n);const d=(Array.isArray(r)?r:[r]).filter((n=>e.has(n))).filter((e=>!p.has(e))),m=new Map,v=(e,n)=>{const t=m.get(n);if(void 0!==t)return t;let r;try{const{js:t}=o(n,{generate:"client",dev:!1,filename:e});r=t.code.length}catch{r=null}return null!==r&&m.set(n,r),r},h=new Set;for(const e of c.keys())u.has(e)||h.add(e);for(const[n,o]of c){if(u.has(n))continue;if(o.some((e=>e.owner!==n&&h.has(e.owner))))continue;const r=new Map,i=[];let c=!1;for(const e of o){if(r.has(e.code))continue;if(i.length>=t.maxVariants){c=!0;break}const o=`${n}::v${i.length}`;r.set(e.code,o),i.push({id:o,code:e.code})}if(!c&&xe(n,i,e,l,f,d,v,t.minSavings)){for(const e of i){const t=o.find((n=>n.code===e.code));s.set(e.id,{id:e.id,childId:n,code:e.code,foldedProps:t.shape})}for(const e of o)a.push({owner:e.owner,childId:n,node:e.node,variantId:r.get(e.code),foldedProps:e.shape})}}return{variants:s,bindings:a}}function xe(e,n,t,o,r,s,a,i){const c=t.get(e),u=new Map;for(const e of n)u.set(e.id,be(e.code,c));const l=new Set,f=[...s];for(;f.length>0;){const e=f.pop();if(!l.has(e)){l.add(e);for(const n of r.get(e)??[])f.push(n)}}let p=0;for(const e of l){const n=a(e,o.get(e));if(null===n)return!1;p+=n}const d=n.map((e=>e.id)),m=new Set,v=new Set,h=n=>n===e?{comps:[],vars:d}:{comps:[n],vars:[]},w=[],y=[];for(const e of s){const n=h(e);w.push(...n.comps),y.push(...n.vars)}for(;w.length>0||y.length>0;){if(w.length>0){const e=w.pop();if(m.has(e))continue;m.add(e);for(const n of r.get(e)??[]){const e=h(n);w.push(...e.comps),y.push(...e.vars)}continue}const e=y.pop();if(!v.has(e)){v.add(e);for(const n of u.get(e)??[]){const e=h(n);w.push(...e.comps),y.push(...e.vars)}}}let g=0;for(const e of m){const n=a(e,o.get(e));if(null===n)return!1;g+=n}for(const e of v){const t=n.find((n=>n.id===e)).code,o=a(e,t);if(null===o)return!1;g+=o}return g<p*(1-i)}function be(e,n){let t;try{t=a(e,n.id)}catch{return[]}const o=[];return i(t.fragment,null,{Component(e,{next:t}){const r=e.name?n.imports.get(e.name):void 0;r&&o.push(r),t()}}),o}function Se(e,n,t){const o=O(e),r=new Map;for(const e of n.props??[])r.set(e.name,e);const s=new Map;for(const[e,a]of o.explicit)r.has(e)&&(t.constFold.has(e)||T(n,e)||!a.dynamic&&a.afterLastSpread&&s.set(e,a.value));return s}function Ie(e,n,t){const o=new Map(n.constFold);for(const[e,n]of t)o.set(e,n);const r=new Map;for(const[e,t]of n.narrow)o.has(e)||r.set(e,t);const a=new s(e.code);return fe(e,o,r,n,a),a.toString()}const Me=new WeakMap;function Ee(e,n){const t=Me.get(e);if(void 0!==t)return t;const o=new s(e.code);fe(e,n.constFold,n.narrow,n,o);const r=o.toString();return Me.set(e,r),r}const Ae=(e,t)=>e.startsWith(".")?n.resolve(n.dirname(t),e):null;function $e(t){const o=[];let r;try{r=e.readdirSync(t,{withFileTypes:!0})}catch{return o}for(const e of r){if("node_modules"===e.name||e.name.startsWith("."))continue;const r=n.join(t,e.name);e.isDirectory()?o.push(...$e(r)):e.isFile()&&e.name.endsWith(".svelte")&&o.push(r)}return o}const Ce="shaker_variant";function Fe(t={}){const o=function(e){if(2!==e.level||!e.monomorphize)return ge;const n="object"==typeof e.monomorphize?e.monomorphize:{};return{...ge,enabled:!0,...n}}(t);let r={},s=new Map,a=process.cwd();const i=e=>{const n=e.lastIndexOf("::v"),t=e.slice(0,n),o=e.slice(n+3);return`${t}?${Ce}=${o}`};return{name:"vite-plugin-svelte-shaker",enforce:"pre",apply:"build",configResolved(e){a=e.root},async buildStart(){const c=(t.include??["."]).map((e=>n.resolve(a,e))).flatMap($e);if(0===c.length)return r={},void(s=new Map);const u=n=>e.readFileSync(n,"utf-8");if(!o.enabled)return r=await async function(e,n,t){const{models:o,plans:r}=await E(e,n,t);return oe(o,r)}(c,Ae,u),void(s=new Map);const l=await async function(e,n,t,o=ge,r=(e=>e)){const{models:s,plans:a}=await E(e,n,t),i=ke(s,a,o,e);return{files:0===i.bindings.length?oe(s,a):ae(s,a,i.bindings.map((e=>({owner:e.owner,node:e.node,variantId:e.variantId,foldedProps:e.foldedProps}))),r),mono:i}}(c,Ae,u,o,i);r=l.files,s=new Map;for(const e of l.mono.variants.values())s.set(i(e.id),e.code)},resolveId(e,t){if(!e.includes(`${Ce}=`))return null;const[o,r]=e.split("?");if(!o||!o.endsWith(".svelte"))return null;const s=t?n.dirname(t.split("?")[0]):a;return`${o.startsWith(".")?n.resolve(s,o):o}?${r}`},load:e=>e.includes(`${Ce}=`)?s.get(e)??null:null,transform(e,n){if(n.includes(`${Ce}=`))return null;if(n.includes("svelte&type="))return null;const t=n.split("?")[0];if(!t.endsWith(".svelte"))return null;const o=r[t];return null==o||o===e?null:o}}}export{Fe as shaker};
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "svelte-shaker",
3
+ "version": "0.0.1",
4
+ "description": "Tree shaking for Svelte components",
5
+ "author": "baseballyama",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "svelte",
9
+ "tree-shaking",
10
+ "tree-shaker",
11
+ "vite-plugin",
12
+ "rollup-plugin",
13
+ "dead-code-elimination"
14
+ ],
15
+ "homepage": "https://github.com/baseballyama/svelte-shaker#readme",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/baseballyama/svelte-shaker.git",
19
+ "directory": "packages/svelte-shaker"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/baseballyama/svelte-shaker/issues"
23
+ },
24
+ "type": "module",
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/types/src/index.d.ts",
27
+ "files": [
28
+ "dist/*.js",
29
+ "dist/*.cjs",
30
+ "dist/types/src"
31
+ ],
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/types/src/index.d.ts",
38
+ "import": "./dist/index.js",
39
+ "require": "./dist/index.cjs"
40
+ },
41
+ "./vite": {
42
+ "types": "./dist/types/src/vite.d.ts",
43
+ "import": "./dist/vite.js"
44
+ },
45
+ "./node": {
46
+ "types": "./dist/types/src/scan.d.ts",
47
+ "import": "./dist/scan.js"
48
+ },
49
+ "./package.json": "./package.json"
50
+ },
51
+ "scripts": {
52
+ "build": "rollup -c",
53
+ "prepack": "rollup -c",
54
+ "dev": "rollup -cw",
55
+ "test:watch": "vitest",
56
+ "test": "vitest run"
57
+ },
58
+ "dependencies": {
59
+ "magic-string": "0.30.10",
60
+ "zimmerframe": "1.1.2"
61
+ },
62
+ "peerDependencies": {
63
+ "svelte": "^5"
64
+ },
65
+ "devDependencies": {
66
+ "@rollup/plugin-commonjs": "25.0.8",
67
+ "@rollup/plugin-node-resolve": "15.2.3",
68
+ "@rollup/plugin-terser": "0.4.4",
69
+ "@rollup/plugin-typescript": "11.1.6",
70
+ "@sveltejs/vite-plugin-svelte": "^4",
71
+ "rollup": "4.18.0",
72
+ "svelte": "^5",
73
+ "tslib": "2.6.2",
74
+ "vite": "^5"
75
+ }
76
+ }