@pyreon/compiler 0.22.0 → 0.24.0
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/README.md +138 -54
- package/lib/analysis/index.js.html +1 -1
- package/lib/index.js +414 -9
- package/lib/types/index.d.ts +94 -1
- package/package.json +12 -12
- package/src/index.ts +2 -0
- package/src/jsx.ts +425 -5
- package/src/lpih.ts +270 -0
- package/src/pyreon-intercept.ts +19 -8
- package/src/ssg-audit.ts +3 -3
- package/src/tests/collapse-bail-census.test.ts +101 -16
- package/src/tests/component-child-no-wrap.test.ts +204 -0
- package/src/tests/dynamic-collapse-detector.test.ts +164 -0
- package/src/tests/dynamic-collapse-emit.test.ts +192 -0
- package/src/tests/dynamic-collapse-scan.test.ts +111 -0
- package/src/tests/lpih.test.ts +404 -0
- package/src/tests/native-equivalence.test.ts +92 -0
package/README.md
CHANGED
|
@@ -1,96 +1,180 @@
|
|
|
1
1
|
# @pyreon/compiler
|
|
2
2
|
|
|
3
|
-
JSX reactive transform
|
|
3
|
+
JSX reactive transform (Rust native + JS fallback) plus authoring-time analysis tools.
|
|
4
|
+
|
|
5
|
+
`@pyreon/compiler` is the build-time toolchain Pyreon ships. It transforms JSX into `_tpl()` + `_bind()` cloneNode templates against `@pyreon/runtime-dom`, auto-wraps dynamic expressions in reactive getters, hoists fully-static subtrees to module scope, inlines `const`-from-`props` for end-to-end reactivity, and auto-calls bare signal references in JSX. The reactive transform ships as a Rust native binary (napi-rs, 3.7-8.9× faster) with a per-call JS fallback — cross-backend equivalence is asserted by 180+ tests. The package also exports authoring-time tools: a Reactivity-Lens sidecar, React-pattern detection + one-shot migration, a Pyreon anti-pattern detector (the MCP `validate` engine), and three project audits (`auditTestEnvironment`, `auditIslands`, `auditSsg`) consumed by `pyreon doctor`.
|
|
6
|
+
|
|
7
|
+
Most users never call this package directly — `@pyreon/vite-plugin` wires it into Vite for you.
|
|
4
8
|
|
|
5
9
|
## Install
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
|
-
bun add @pyreon/compiler
|
|
12
|
+
bun add -D @pyreon/compiler
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## What it does
|
|
16
|
+
|
|
17
|
+
The compiler transforms JSX expression containers and props so the runtime receives reactive getters instead of eagerly-evaluated values.
|
|
18
|
+
|
|
19
|
+
| Input | Output | Reason |
|
|
20
|
+
| ------------------------- | ---------------------------- | ----------------- |
|
|
21
|
+
| `<div>{expr}</div>` | `<div>{() => expr}</div>` | Dynamic child |
|
|
22
|
+
| `<div class={expr}>` | `<div class={() => expr}>` | Dynamic prop |
|
|
23
|
+
| `<div>{count}</div>` * | `<div>{() => count()}</div>` | Signal auto-call |
|
|
24
|
+
| `<button onClick={fn}>` | unchanged | Event handler |
|
|
25
|
+
| `<div>{() => expr}</div>` | unchanged | Already wrapped |
|
|
26
|
+
| `<div>{"literal"}</div>` | unchanged | Static value |
|
|
27
|
+
| `<Comp {...src}>` | `<Comp {..._wrapSpread(src)}>` | Reactive-safe spread |
|
|
28
|
+
|
|
29
|
+
\* When `count` is declared as `const count = signal(...)` in the same module, or passed via the `knownSignals` option (the `@pyreon/vite-plugin` does this for cross-module signal exports automatically).
|
|
30
|
+
|
|
31
|
+
### Static hoisting
|
|
32
|
+
|
|
33
|
+
Fully static JSX subtrees are hoisted to module-level constants, so they're created once at module initialization:
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
// Before
|
|
37
|
+
const App = () => <div>{<span>Hello</span>}</div>
|
|
38
|
+
|
|
39
|
+
// After
|
|
40
|
+
const _$h0 = <span>Hello</span>
|
|
41
|
+
const App = () => <div>{_$h0}</div>
|
|
9
42
|
```
|
|
10
43
|
|
|
11
|
-
|
|
44
|
+
### Template-based mount
|
|
45
|
+
|
|
46
|
+
Element trees with ≥1 DOM tag emit `_tpl()` + `_bind()` instead of nested `h()` calls — cloneNode for the static skeleton, per-text-node `_bind()` for surgical updates. Zero VNode allocations on the static parts.
|
|
47
|
+
|
|
48
|
+
## Reactive transform — Quick start
|
|
12
49
|
|
|
13
50
|
```ts
|
|
14
51
|
import { transformJSX } from '@pyreon/compiler'
|
|
15
52
|
|
|
16
|
-
const
|
|
17
|
-
`
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
53
|
+
const { code, warnings, usesTemplates } = transformJSX(
|
|
54
|
+
`const App = () => <div class={color()}>{count()}</div>`,
|
|
55
|
+
'App.tsx',
|
|
56
|
+
{
|
|
57
|
+
ssr: false, // Skip template emission for SSR
|
|
58
|
+
knownSignals: ['count', 'color'], // Cross-module signal names → auto-call
|
|
59
|
+
reactivityLens: false, // Opt-in sidecar
|
|
60
|
+
collapseRocketstyle: false, // Advanced — see "Rocketstyle collapse" below
|
|
61
|
+
},
|
|
21
62
|
)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`transformJSX_JS(...)` is the forced JS-backend variant — deterministic, used by `analyzeReactivity` and useful for debugging the native path.
|
|
22
66
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
67
|
+
## Authoring-time tools (editor-side)
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { analyzeReactivity, formatReactivityLens } from '@pyreon/compiler'
|
|
71
|
+
|
|
72
|
+
// Surface the compiler's reactive/static decisions back to the editor
|
|
73
|
+
const { findings, spans } = analyzeReactivity(
|
|
74
|
+
`const A = (props) => <div>{props.name}</div>`,
|
|
75
|
+
'A.tsx',
|
|
76
|
+
)
|
|
77
|
+
// findings: ReactivityFinding[] — merged footgun + structural taxonomy
|
|
78
|
+
// spans: ReactivitySpan[] — { kind: 'reactive' | 'static-text' | 'hoisted-static' | ... }
|
|
79
|
+
|
|
80
|
+
console.log(formatReactivityLens(source, { findings, spans }))
|
|
26
81
|
```
|
|
27
82
|
|
|
28
|
-
|
|
83
|
+
The Lens is **additive** — `TransformResult.code` is byte-identical with or without `reactivityLens: true`. Spans are RECORDS of a codegen branch; absence is "not asserted", never an implicit static claim.
|
|
29
84
|
|
|
30
|
-
|
|
85
|
+
## React migration
|
|
31
86
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
| `<div>{() => expr}</div>` | unchanged | Already wrapped |
|
|
38
|
-
| `<div>{"literal"}</div>` | unchanged | Static value |
|
|
87
|
+
```ts
|
|
88
|
+
import { detectReactPatterns, migrateReactCode, diagnoseError } from '@pyreon/compiler'
|
|
89
|
+
|
|
90
|
+
const diagnostics = detectReactPatterns(reactSource, 'App.tsx')
|
|
91
|
+
// diagnostics: ReactDiagnostic[] with codes like 'use-state', 'use-effect', 'class-name'
|
|
39
92
|
|
|
40
|
-
|
|
93
|
+
const { code, changes } = migrateReactCode(reactSource, 'App.tsx')
|
|
94
|
+
// One-shot codemod: useState → signal, useEffect → effect, className → class, etc.
|
|
41
95
|
|
|
42
|
-
|
|
96
|
+
const err = new Error('useState is not defined')
|
|
97
|
+
diagnoseError(err, source) // ErrorDiagnosis — points users at the migration step
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The migration is a one-shot codemod, **not** a runtime adapter. For runtime compat layers, see `@pyreon/react-compat`.
|
|
101
|
+
|
|
102
|
+
## Pyreon anti-pattern detector
|
|
43
103
|
|
|
44
104
|
```ts
|
|
45
|
-
|
|
46
|
-
const App = () => <div>{<span>Hello</span>}</div>
|
|
105
|
+
import { detectPyreonPatterns, hasPyreonPatterns } from '@pyreon/compiler'
|
|
47
106
|
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
107
|
+
const diags = detectPyreonPatterns(
|
|
108
|
+
`const C = ({ state }) => <div>{state}</div>`,
|
|
109
|
+
'C.tsx',
|
|
110
|
+
)
|
|
111
|
+
// PyreonDiagnostic[] — 15 codes today: 'for-missing-by', 'for-with-key',
|
|
112
|
+
// 'props-destructured', 'props-destructured-body', 'process-dev-gate',
|
|
113
|
+
// 'empty-theme', 'raw-add-event-listener', 'raw-remove-event-listener',
|
|
114
|
+
// 'date-math-random-id', 'on-click-undefined', 'signal-write-as-call',
|
|
115
|
+
// 'static-return-null-conditional', 'as-unknown-as-vnodechild',
|
|
116
|
+
// 'island-never-with-registry-entry', 'query-options-as-function'
|
|
51
117
|
```
|
|
52
118
|
|
|
53
|
-
|
|
119
|
+
This is what the MCP `validate({ code })` tool runs. Some shapes are caught syntactically here AND also as lint rules in `@pyreon/lint` (proactive + reactive — the agent sees the fix before commit; CI catches it post-commit).
|
|
120
|
+
|
|
121
|
+
## Project audits
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { auditIslands, auditSsg, auditTestEnvironment } from '@pyreon/compiler'
|
|
125
|
+
|
|
126
|
+
const islandResult = auditIslands(projectRoot)
|
|
127
|
+
const ssgResult = auditSsg(projectRoot)
|
|
128
|
+
const testResult = auditTestEnvironment(projectRoot, { minRisk: 'high' })
|
|
129
|
+
```
|
|
54
130
|
|
|
55
|
-
-
|
|
56
|
-
- **`transformJSX_JS(code, filename?, options?): TransformResult`** -- JS-only transform (bypasses native binary). Useful for debugging or cross-backend testing.
|
|
57
|
-
- **`loadNativeBinding(): NativeBinding | null`** -- Resolve the native `.node` binding via two paths: (1) in-tree at `packages/core/compiler/native/` (workspace-internal), (2) per-platform npm package (`@pyreon/compiler-<platform>-<arch>[-<libc>]`). Returns `null` when neither path resolves; `transformJSX()` then falls through to the JS path silently.
|
|
131
|
+
Three syntactic project-wide audits consumed by `pyreon doctor --check-islands` / `--check-ssg` / `--audit-tests`. Pure-AST, no type-check pass — designed for CI speed.
|
|
58
132
|
|
|
59
|
-
|
|
133
|
+
## Compiler-emitted runtime helpers
|
|
60
134
|
|
|
61
|
-
|
|
62
|
-
- **`TransformOptions`** -- `{ ssr?: boolean }` -- Set `ssr: true` to skip `_tpl()` template emission for server-side rendering.
|
|
135
|
+
The transform emits calls to symbols exported by `@pyreon/runtime-dom` and `@pyreon/core`:
|
|
63
136
|
|
|
64
|
-
|
|
137
|
+
| Helper | Where exported | Purpose |
|
|
138
|
+
|------------------|-------------------------|---------|
|
|
139
|
+
| `_tpl(html)` | `@pyreon/runtime-dom` | Parse + clone an HTML template once per template literal |
|
|
140
|
+
| `_bind(fn, …)` | `@pyreon/runtime-dom` | Per-binding reactive update wired to a template node |
|
|
141
|
+
| `_bindText(…)` | `@pyreon/runtime-dom` | Fast path for reactive text nodes |
|
|
142
|
+
| `_bindDirect(…)` | `@pyreon/runtime-dom` | Fast path for reactive attributes |
|
|
143
|
+
| `_applyProps(…)` | `@pyreon/runtime-dom` | Spread props on a template element |
|
|
144
|
+
| `_rp(thunk)` | `@pyreon/core` | Brand a reactive prop wrapper |
|
|
145
|
+
| `_wrapSpread(s)` | `@pyreon/core` | Preserve reactivity through `<Comp {...source}>` |
|
|
65
146
|
|
|
66
|
-
|
|
147
|
+
## Architecture — dual backend
|
|
67
148
|
|
|
68
|
-
|
|
69
|
-
- **JS fallback** (`src/jsx.ts`): uses `oxc-parser` (Rust NAPI binding) for parsing + JS reactive pass. Activated automatically when the native binary isn't available.
|
|
70
|
-
- **Auto-detection**: `transformJSX()` loads the native binary via `createRequire` (ESM-safe), falls back per-call with try/catch.
|
|
149
|
+
**Rust native binary** (`native/`): full reactive pass via `oxc_parser`/`oxc_ast`. Zero JSON serialization, single-pass recursive walk with `FxHashMap`-cached `isDynamic` analysis. ~2,800 lines of Rust, compiled to a ~1MB `.node` binary.
|
|
71
150
|
|
|
72
|
-
|
|
151
|
+
**JS fallback** (`src/jsx.ts`): uses `oxc-parser` (Rust NAPI binding) for parsing + a JS reactive pass. Activated automatically when the native binary isn't available (CI without the per-platform package, WASM, unsupported platform). The fallback path is silent — no error, just a slower transform.
|
|
73
152
|
|
|
74
|
-
|
|
153
|
+
**Per-platform packages**: the native binary ships as separate optional dependencies, one per platform. npm / bun install only the matching one via `os` / `cpu` fields:
|
|
75
154
|
|
|
76
|
-
| Platform | Arch
|
|
77
|
-
|
|
78
|
-
| darwin | arm64
|
|
79
|
-
| darwin | x64
|
|
80
|
-
| linux | x64
|
|
81
|
-
| linux | x64
|
|
82
|
-
| linux | arm64
|
|
83
|
-
| linux | arm64
|
|
84
|
-
| win32 | x64
|
|
155
|
+
| Platform | Arch | libc | Package |
|
|
156
|
+
|----------|------|------|--------------------------------------|
|
|
157
|
+
| darwin | arm64 | — | `@pyreon/compiler-darwin-arm64` |
|
|
158
|
+
| darwin | x64 | — | `@pyreon/compiler-darwin-x64` |
|
|
159
|
+
| linux | x64 | gnu | `@pyreon/compiler-linux-x64-gnu` |
|
|
160
|
+
| linux | x64 | musl | `@pyreon/compiler-linux-x64-musl` |
|
|
161
|
+
| linux | arm64 | gnu | `@pyreon/compiler-linux-arm64-gnu` |
|
|
162
|
+
| linux | arm64 | musl | `@pyreon/compiler-linux-arm64-musl` |
|
|
163
|
+
| win32 | x64 | — | `@pyreon/compiler-win32-x64-msvc` |
|
|
85
164
|
|
|
86
|
-
`detectLibc()` distinguishes glibc vs musl on Linux at load time
|
|
165
|
+
A `detectLibc()` step distinguishes glibc vs musl on Linux at load time.
|
|
87
166
|
|
|
88
|
-
## Implementation
|
|
167
|
+
## Implementation notes
|
|
89
168
|
|
|
90
169
|
- Props named `key` and `ref` are never wrapped.
|
|
91
170
|
- Props matching `on[A-Z]*` (event handlers) are never wrapped.
|
|
92
|
-
- Prop-derived variable resolution is fully AST-based — walks `IdentifierReference` nodes, never scans source text.
|
|
93
|
-
- 527 tests: 347 original + 180 cross-backend equivalence
|
|
171
|
+
- Prop-derived variable resolution is fully AST-based — walks `IdentifierReference` nodes, never scans source text. Cycle detection via a `resolving` set prevents infinite recursion.
|
|
172
|
+
- 527+ tests: 347 original + 180 cross-backend equivalence (Unicode, TypeScript syntax, control flow, string collision resistance).
|
|
173
|
+
- `analyzeReactivity` always uses the JS backend — it's the deterministic oracle for the merged footgun + structural taxonomy.
|
|
174
|
+
|
|
175
|
+
## Documentation
|
|
176
|
+
|
|
177
|
+
Full docs: [docs.pyreon.dev/docs/compiler](https://docs.pyreon.dev/docs/compiler) (or `docs/docs/compiler.md` in this repo).
|
|
94
178
|
|
|
95
179
|
## License
|
|
96
180
|
|
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"6eb92b25-1","name":"defer-inline.ts"},{"uid":"6eb92b25-3","name":"event-names.ts"},{"uid":"6eb92b25-5","name":"load-native.ts"},{"uid":"6eb92b25-7","name":"jsx.ts"},{"uid":"6eb92b25-9","name":"pyreon-intercept.ts"},{"uid":"6eb92b25-11","name":"reactivity-lens.ts"},{"uid":"6eb92b25-13","name":"lpih.ts"},{"uid":"6eb92b25-15","name":"project-scanner.ts"},{"uid":"6eb92b25-17","name":"react-intercept.ts"},{"uid":"6eb92b25-19","name":"test-audit.ts"},{"uid":"6eb92b25-21","name":"island-audit.ts"},{"uid":"6eb92b25-23","name":"ssg-audit.ts"},{"uid":"6eb92b25-25","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"6eb92b25-1":{"renderedLength":15789,"gzipLength":5000,"brotliLength":0,"metaUid":"6eb92b25-0"},"6eb92b25-3":{"renderedLength":2941,"gzipLength":1335,"brotliLength":0,"metaUid":"6eb92b25-2"},"6eb92b25-5":{"renderedLength":3959,"gzipLength":1744,"brotliLength":0,"metaUid":"6eb92b25-4"},"6eb92b25-7":{"renderedLength":75616,"gzipLength":18800,"brotliLength":0,"metaUid":"6eb92b25-6"},"6eb92b25-9":{"renderedLength":29341,"gzipLength":9289,"brotliLength":0,"metaUid":"6eb92b25-8"},"6eb92b25-11":{"renderedLength":4373,"gzipLength":2130,"brotliLength":0,"metaUid":"6eb92b25-10"},"6eb92b25-13":{"renderedLength":5266,"gzipLength":2166,"brotliLength":0,"metaUid":"6eb92b25-12"},"6eb92b25-15":{"renderedLength":4762,"gzipLength":1730,"brotliLength":0,"metaUid":"6eb92b25-14"},"6eb92b25-17":{"renderedLength":28896,"gzipLength":7322,"brotliLength":0,"metaUid":"6eb92b25-16"},"6eb92b25-19":{"renderedLength":13167,"gzipLength":5060,"brotliLength":0,"metaUid":"6eb92b25-18"},"6eb92b25-21":{"renderedLength":18208,"gzipLength":6051,"brotliLength":0,"metaUid":"6eb92b25-20"},"6eb92b25-23":{"renderedLength":12773,"gzipLength":4183,"brotliLength":0,"metaUid":"6eb92b25-22"},"6eb92b25-25":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"6eb92b25-24"}},"nodeMetas":{"6eb92b25-0":{"id":"/src/defer-inline.ts","moduleParts":{"index.js":"6eb92b25-1"},"imported":[{"uid":"6eb92b25-26"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-2":{"id":"/src/event-names.ts","moduleParts":{"index.js":"6eb92b25-3"},"imported":[],"importedBy":[{"uid":"6eb92b25-6"}]},"6eb92b25-4":{"id":"/src/load-native.ts","moduleParts":{"index.js":"6eb92b25-5"},"imported":[{"uid":"6eb92b25-31"},{"uid":"6eb92b25-32"},{"uid":"6eb92b25-29"}],"importedBy":[{"uid":"6eb92b25-6"}]},"6eb92b25-6":{"id":"/src/jsx.ts","moduleParts":{"index.js":"6eb92b25-7"},"imported":[{"uid":"6eb92b25-27"},{"uid":"6eb92b25-26"},{"uid":"6eb92b25-2"},{"uid":"6eb92b25-4"}],"importedBy":[{"uid":"6eb92b25-24"},{"uid":"6eb92b25-10"}]},"6eb92b25-8":{"id":"/src/pyreon-intercept.ts","moduleParts":{"index.js":"6eb92b25-9"},"imported":[{"uid":"6eb92b25-30"}],"importedBy":[{"uid":"6eb92b25-24"},{"uid":"6eb92b25-10"}]},"6eb92b25-10":{"id":"/src/reactivity-lens.ts","moduleParts":{"index.js":"6eb92b25-11"},"imported":[{"uid":"6eb92b25-6"},{"uid":"6eb92b25-8"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-12":{"id":"/src/lpih.ts","moduleParts":{"index.js":"6eb92b25-13"},"imported":[],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-14":{"id":"/src/project-scanner.ts","moduleParts":{"index.js":"6eb92b25-15"},"imported":[{"uid":"6eb92b25-28"},{"uid":"6eb92b25-29"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-16":{"id":"/src/react-intercept.ts","moduleParts":{"index.js":"6eb92b25-17"},"imported":[{"uid":"6eb92b25-30"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-18":{"id":"/src/test-audit.ts","moduleParts":{"index.js":"6eb92b25-19"},"imported":[{"uid":"6eb92b25-28"},{"uid":"6eb92b25-29"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-20":{"id":"/src/island-audit.ts","moduleParts":{"index.js":"6eb92b25-21"},"imported":[{"uid":"6eb92b25-28"},{"uid":"6eb92b25-29"},{"uid":"6eb92b25-30"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-22":{"id":"/src/ssg-audit.ts","moduleParts":{"index.js":"6eb92b25-23"},"imported":[{"uid":"6eb92b25-28"},{"uid":"6eb92b25-29"},{"uid":"6eb92b25-30"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-24":{"id":"/src/index.ts","moduleParts":{"index.js":"6eb92b25-25"},"imported":[{"uid":"6eb92b25-0"},{"uid":"6eb92b25-6"},{"uid":"6eb92b25-10"},{"uid":"6eb92b25-12"},{"uid":"6eb92b25-14"},{"uid":"6eb92b25-16"},{"uid":"6eb92b25-8"},{"uid":"6eb92b25-18"},{"uid":"6eb92b25-20"},{"uid":"6eb92b25-22"}],"importedBy":[],"isEntry":true},"6eb92b25-26":{"id":"oxc-parser","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-0"},{"uid":"6eb92b25-6"}]},"6eb92b25-27":{"id":"magic-string","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-6"}]},"6eb92b25-28":{"id":"node:fs","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-14"},{"uid":"6eb92b25-18"},{"uid":"6eb92b25-20"},{"uid":"6eb92b25-22"}]},"6eb92b25-29":{"id":"node:path","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-14"},{"uid":"6eb92b25-18"},{"uid":"6eb92b25-20"},{"uid":"6eb92b25-22"},{"uid":"6eb92b25-4"}]},"6eb92b25-30":{"id":"typescript","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-16"},{"uid":"6eb92b25-8"},{"uid":"6eb92b25-20"},{"uid":"6eb92b25-22"}]},"6eb92b25-31":{"id":"node:module","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-4"}]},"6eb92b25-32":{"id":"node:url","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-4"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|