@hkdigital/lib-core 0.5.62 → 0.5.65
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/dist/browser/navigation/navigation.svelte.js +1 -1
- package/dist/generic/data/classes/IterableTree.js +1 -1
- package/dist/generic/promises/classes/HkPromise.js +1 -1
- package/dist/logging/client.d.ts +1 -1
- package/dist/logging/client.js +1 -1
- package/dist/logging/common.d.ts +1 -1
- package/dist/logging/common.js +1 -1
- package/dist/logging/internal/factories/client.d.ts +1 -1
- package/dist/logging/internal/factories/client.js +1 -1
- package/dist/logging/internal/factories/server.d.ts +1 -1
- package/dist/logging/internal/factories/server.js +1 -1
- package/dist/logging/internal/logger.d.ts +1 -0
- package/dist/logging/internal/logger.js +1 -0
- package/dist/logging/server.d.ts +1 -1
- package/dist/logging/server.js +1 -1
- package/dist/ui/components/presenter/ImageSlide.svelte +1 -1
- package/dist/ui/components/rows/panel-row-2/PanelRow2.svelte +1 -1
- package/dist/ui/components/tab-bar/HkTabBar.svelte +1 -1
- package/dist/ui/primitives/area.d.ts +2 -0
- package/dist/ui/primitives/area.js +2 -0
- package/dist/ui/primitives/icons/HkTabIcon.svelte +1 -1
- package/dist/ui/primitives/icons/index.d.ts +0 -1
- package/dist/ui/primitives/icons/index.js +0 -2
- package/dist/util/array/index.js +2 -2
- package/dist/util/compare/index.js +1 -1
- package/dist/util/expect/compounds.js +1 -1
- package/dist/util/expect/objects.js +1 -1
- package/dist/util/iterate/index.js +1 -1
- package/dist/util/object/index.js +4 -4
- package/dist/util/string/interpolate.js +1 -1
- package/package.json +5 -1
- package/scripts/README.md +279 -0
- package/scripts/import-fixes.txt +60 -0
- package/scripts/validate-imports.mjs +375 -0
- package/dist/logging/internal/logger/index.d.ts +0 -1
- package/dist/logging/internal/logger/index.js +0 -1
- package/dist/ui/components/index.d.ts +0 -11
- package/dist/ui/components/index.js +0 -23
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as expect from '../../../util/expect.js';
|
|
4
4
|
|
|
5
|
-
import { PATH_SEPARATOR } from '../../../util/object
|
|
5
|
+
import { PATH_SEPARATOR } from '../../../util/object.js';
|
|
6
6
|
|
|
7
7
|
/* ------------------------------------------------------------------ Typedef */
|
|
8
8
|
|
package/dist/logging/client.d.ts
CHANGED
package/dist/logging/client.js
CHANGED
package/dist/logging/common.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./levels.js";
|
|
2
|
-
export { Logger } from "./internal/logger/
|
|
2
|
+
export { default as Logger } from "./internal/logger/Logger.js";
|
package/dist/logging/common.js
CHANGED
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
* @returns {Logger} Configured logger instance
|
|
12
12
|
*/
|
|
13
13
|
export function createClientLogger(name: string, level: import("../../typedef.js").LogLevel, consoleOptions?: Object): Logger;
|
|
14
|
-
import { Logger } from '../logger
|
|
14
|
+
import { Logger } from '../logger.js';
|
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
* @returns {Logger} Configured logger instance
|
|
12
12
|
*/
|
|
13
13
|
export function createServerLogger(name: string, level: import("../../typedef.js").LogLevel, pinoOptions?: Object): Logger;
|
|
14
|
-
import { Logger } from '../logger
|
|
14
|
+
import { Logger } from '../logger.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Logger } from "./logger/Logger.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Logger } from './logger/Logger.js';
|
package/dist/logging/server.d.ts
CHANGED
package/dist/logging/server.js
CHANGED
package/dist/util/array/index.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import * as expect from '../expect.js';
|
|
4
4
|
|
|
5
|
-
import { smallestFirst, largestFirst } from '../compare
|
|
5
|
+
import { smallestFirst, largestFirst } from '../compare.js';
|
|
6
6
|
|
|
7
|
-
import { objectGet, PATH_SEPARATOR } from '../object
|
|
7
|
+
import { objectGet, PATH_SEPARATOR } from '../object.js';
|
|
8
8
|
|
|
9
9
|
import { Selector } from '../../generic/data.js';
|
|
10
10
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* ------------------------------------------------------------------ Imports */
|
|
2
2
|
|
|
3
3
|
import * as expect from '../expect.js';
|
|
4
|
-
import { smallestFirst, largestFirst } from '../compare
|
|
4
|
+
import { smallestFirst, largestFirst } from '../compare.js';
|
|
5
5
|
|
|
6
6
|
import { IterableTree } from '../../generic/data.js';
|
|
7
7
|
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import * as expect from '../expect.js';
|
|
4
4
|
|
|
5
|
-
import { equals } from '../compare
|
|
5
|
+
import { equals } from '../compare.js';
|
|
6
6
|
|
|
7
|
-
import { toArrayPath } from '../array
|
|
7
|
+
import { toArrayPath } from '../array.js';
|
|
8
8
|
|
|
9
9
|
import { toStringPath } from '../string.js';
|
|
10
10
|
|
|
11
|
-
import * as is from '../is
|
|
11
|
+
import * as is from '../is.js';
|
|
12
12
|
|
|
13
|
-
import { iterateObjectPaths, iterateObjectEntries } from '../iterate
|
|
13
|
+
import { iterateObjectPaths, iterateObjectEntries } from '../iterate.js';
|
|
14
14
|
|
|
15
15
|
// ------------------------------------------------------------------- Internals
|
|
16
16
|
|
|
@@ -2,7 +2,7 @@ import * as expect from '../expect.js';
|
|
|
2
2
|
|
|
3
3
|
import { toArrayPath } from '../array/index.js';
|
|
4
4
|
|
|
5
|
-
import { objectGet, PATH_SEPARATOR } from '../object
|
|
5
|
+
import { objectGet, PATH_SEPARATOR } from '../object.js';
|
|
6
6
|
|
|
7
7
|
export const RE_JS_EXPRESSION = /\$\{([^${}]*)\}/g;
|
|
8
8
|
export const RE_MUSTACHE = /\{\{([^{}]*)\}\}/g;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hkdigital/lib-core",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.65",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "HKdigital",
|
|
6
6
|
"url": "https://hkdigital.nl"
|
|
@@ -41,11 +41,13 @@
|
|
|
41
41
|
"cache:clear": "rm -rf node_modules/.cache/imagetools",
|
|
42
42
|
"lint:prettier": "prettier --check .",
|
|
43
43
|
"lint:eslint": "eslint .",
|
|
44
|
+
"lint:imports": "node scripts/validate-imports.mjs",
|
|
44
45
|
"test:unit": "vitest",
|
|
45
46
|
"test:unit-run": "pnpm run test:unit -- --run",
|
|
46
47
|
"prepack:sync": "svelte-kit sync",
|
|
47
48
|
"prepack:build": "svelte-package",
|
|
48
49
|
"prepack:lint": "publint",
|
|
50
|
+
"prepack:imports": "node scripts/validate-imports.mjs",
|
|
49
51
|
"publish:npm:version": "npm version patch",
|
|
50
52
|
"publish:npm:publish": "npm publish --access public",
|
|
51
53
|
"upgrade:hk:update": "ncu --dep dev,optional,peer,prod '@hkdigital/*' -u",
|
|
@@ -54,6 +56,7 @@
|
|
|
54
56
|
},
|
|
55
57
|
"files": [
|
|
56
58
|
"dist",
|
|
59
|
+
"scripts",
|
|
57
60
|
"CLAUDE.md",
|
|
58
61
|
"!dist/**/*.test.*",
|
|
59
62
|
"!dist/**/*.spec.*",
|
|
@@ -102,6 +105,7 @@
|
|
|
102
105
|
"@skeletonlabs/skeleton-svelte": "1.3.1",
|
|
103
106
|
"@steeze-ui/heroicons": "^2.4.2",
|
|
104
107
|
"@sveltejs/adapter-auto": "^6.1.1",
|
|
108
|
+
"@sveltejs/adapter-node": "^5.4.0",
|
|
105
109
|
"@sveltejs/kit": "^2.47.0",
|
|
106
110
|
"@sveltejs/package": "^2.5.4",
|
|
107
111
|
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# Import Path Validation
|
|
2
|
+
|
|
3
|
+
This directory contains validation scripts for enforcing consistent
|
|
4
|
+
import path conventions across the project.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
The `validate-imports.mjs` script checks all JavaScript and Svelte
|
|
9
|
+
files to ensure imports follow project conventions. These rules align
|
|
10
|
+
with how Node.js and Vite resolve modules, ensuring code works both
|
|
11
|
+
during development and when published as a package.
|
|
12
|
+
|
|
13
|
+
## Running the Linter
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Run validation
|
|
17
|
+
node scripts/validate-imports.mjs
|
|
18
|
+
|
|
19
|
+
# Add to package.json scripts
|
|
20
|
+
{
|
|
21
|
+
"scripts": {
|
|
22
|
+
"lint:imports": "node scripts/validate-imports.mjs"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Import Rules Summary
|
|
28
|
+
|
|
29
|
+
1. **No cross-domain relative imports** - Use `$lib/` for 3+ levels up
|
|
30
|
+
2. **Write index.js explicitly** - Don't rely on implicit directory
|
|
31
|
+
resolution (except in test files)
|
|
32
|
+
3. **Standard extensions optional** - `.js` and `.svelte` can be
|
|
33
|
+
omitted
|
|
34
|
+
4. **Non-standard extensions required** - `.svelte.js`, `.test.js`,
|
|
35
|
+
etc. must be explicit
|
|
36
|
+
5. **Import paths must exist** - All imports must resolve to actual
|
|
37
|
+
files
|
|
38
|
+
|
|
39
|
+
## Import Rules
|
|
40
|
+
|
|
41
|
+
### Rule 1: No cross-domain relative imports
|
|
42
|
+
|
|
43
|
+
**Don't navigate up 3+ levels with relative paths**
|
|
44
|
+
|
|
45
|
+
When importing from a different domain (different main folder under
|
|
46
|
+
`src/lib/`), use `$lib/` imports instead of long relative paths.
|
|
47
|
+
|
|
48
|
+
❌ Bad:
|
|
49
|
+
```javascript
|
|
50
|
+
// In src/lib/ui/components/MyComponent.svelte
|
|
51
|
+
import { http } from '../../../network/http.js';
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
✅ Good:
|
|
55
|
+
```javascript
|
|
56
|
+
// In src/lib/ui/components/MyComponent.svelte
|
|
57
|
+
import { http } from '$lib/network/http.js';
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Why:** Makes imports clearer, easier to refactor, and independent of
|
|
61
|
+
file location.
|
|
62
|
+
|
|
63
|
+
### Rule 2: Write index.js explicitly (except same-directory)
|
|
64
|
+
|
|
65
|
+
**If importing from a directory, write the index.js explicitly**
|
|
66
|
+
|
|
67
|
+
When a directory contains an `index.js` file, don't rely on implicit
|
|
68
|
+
resolution - write it explicitly.
|
|
69
|
+
|
|
70
|
+
❌ Bad:
|
|
71
|
+
```javascript
|
|
72
|
+
// When src/lib/ui/primitives/ has index.js
|
|
73
|
+
import { Button } from '$lib/ui/primitives';
|
|
74
|
+
import { Card } from '../components/cards';
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
✅ Good:
|
|
78
|
+
```javascript
|
|
79
|
+
import { Button } from '$lib/ui/primitives/index.js';
|
|
80
|
+
import { Card } from '../components/cards/index.js';
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
✅ Exception - same-directory imports allowed:
|
|
84
|
+
```javascript
|
|
85
|
+
// In drag-drop/DropZoneArea.svelte
|
|
86
|
+
import { DropZone } from './index.js'; // OK - sibling file
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
✅ Exception - test files can import from index.js:
|
|
90
|
+
```javascript
|
|
91
|
+
// In *.test.js or *.spec.js files
|
|
92
|
+
import { helper } from './index.js'; // OK in tests
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Why:**
|
|
96
|
+
- Makes it explicit that you're importing from a re-export file
|
|
97
|
+
- Same-directory imports are allowed for module cohesion (files
|
|
98
|
+
within the same module can use their local index.js)
|
|
99
|
+
- Parent navigation (`../index.js`) should use cross-domain imports
|
|
100
|
+
or specific files instead
|
|
101
|
+
|
|
102
|
+
### Rule 3: Standard extensions are optional
|
|
103
|
+
|
|
104
|
+
**Standard extensions (.js, .svelte) can be omitted**
|
|
105
|
+
|
|
106
|
+
Both `$lib/` and relative imports can omit `.js` and `.svelte`
|
|
107
|
+
extensions. Vite and Node.js will resolve them correctly.
|
|
108
|
+
|
|
109
|
+
✅ All valid:
|
|
110
|
+
```javascript
|
|
111
|
+
// File exists at src/lib/util/array.js
|
|
112
|
+
import { arraySlice } from '$lib/util/array';
|
|
113
|
+
import { arraySlice } from '$lib/util/array.js';
|
|
114
|
+
|
|
115
|
+
// File exists at ./components/Button.svelte
|
|
116
|
+
import Button from './components/Button';
|
|
117
|
+
import Button from './components/Button.svelte';
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Why:** Vite and Node.js automatically resolve extensions, so
|
|
121
|
+
requiring them is unnecessary for internal code.
|
|
122
|
+
|
|
123
|
+
### Rule 4: Non-standard extensions must be explicit
|
|
124
|
+
|
|
125
|
+
**Files with non-standard extensions require the full extension**
|
|
126
|
+
|
|
127
|
+
Non-standard extensions like `.svelte.js`, `.test.js`, or `.spec.js`
|
|
128
|
+
are not automatically resolved by module loaders, so they must be
|
|
129
|
+
written explicitly in imports.
|
|
130
|
+
|
|
131
|
+
❌ Bad:
|
|
132
|
+
```javascript
|
|
133
|
+
// File is MyComponent.state.svelte.js
|
|
134
|
+
import { state } from './MyComponent.state.svelte';
|
|
135
|
+
import { state } from './MyComponent.state';
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
✅ Good:
|
|
139
|
+
```javascript
|
|
140
|
+
// File is MyComponent.state.svelte.js
|
|
141
|
+
import { state } from './MyComponent.state.svelte.js';
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Why:** Module resolution only tries standard extensions (.js,
|
|
145
|
+
.svelte). Non-standard compound extensions won't be found
|
|
146
|
+
automatically and will cause import errors.
|
|
147
|
+
|
|
148
|
+
### Rule 5: Import paths must exist
|
|
149
|
+
|
|
150
|
+
**All import paths must resolve to actual files**
|
|
151
|
+
|
|
152
|
+
The linter verifies that every internal import (`$lib/`, `./`, `../`)
|
|
153
|
+
points to a file that exists on the filesystem. This catches typos,
|
|
154
|
+
moved/deleted files, and incorrect paths early.
|
|
155
|
+
|
|
156
|
+
❌ Bad:
|
|
157
|
+
```javascript
|
|
158
|
+
// File doesn't exist
|
|
159
|
+
import { helper } from './utlis.js'; // Typo: should be "utils"
|
|
160
|
+
import Button from '$lib/ui/Buttton.svelte'; // Typo in filename
|
|
161
|
+
import { old } from './deleted-file.js'; // File was removed
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
✅ Good:
|
|
165
|
+
```javascript
|
|
166
|
+
// All files exist
|
|
167
|
+
import { helper } from './utils.js';
|
|
168
|
+
import Button from '$lib/ui/Button.svelte';
|
|
169
|
+
import { current } from './existing-file.js';
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Special handling:**
|
|
173
|
+
- **Query parameters**: Vite asset imports with query strings (e.g.,
|
|
174
|
+
`'./image.jpg?preset=render'`) are supported - the query string is
|
|
175
|
+
stripped before checking file existence
|
|
176
|
+
- **Resolution order**: Follows Node.js/Vite resolution (tries `.js`,
|
|
177
|
+
`.svelte`, `.svelte.js`, `/index.js` for extensionless imports)
|
|
178
|
+
|
|
179
|
+
**Why:** Catches broken imports immediately instead of discovering
|
|
180
|
+
them at build time or runtime. Helps prevent errors when refactoring
|
|
181
|
+
or moving files.
|
|
182
|
+
|
|
183
|
+
## How Module Resolution Works
|
|
184
|
+
|
|
185
|
+
Understanding how Node.js and Vite resolve imports helps explain
|
|
186
|
+
these rules:
|
|
187
|
+
|
|
188
|
+
### Resolution order for `import { x } from './foo'`
|
|
189
|
+
|
|
190
|
+
1. Try `./foo` (exact match)
|
|
191
|
+
2. Try `./foo.js`
|
|
192
|
+
3. Try `./foo.svelte`
|
|
193
|
+
4. Try `./foo/index.js`
|
|
194
|
+
5. Try `./foo/index.svelte`
|
|
195
|
+
|
|
196
|
+
### Examples
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
// Import: from './components/things'
|
|
200
|
+
// Resolution:
|
|
201
|
+
// 1. ./components/things (not found)
|
|
202
|
+
// 2. ./components/things.js (✓ found!) → uses this file
|
|
203
|
+
// 3. Never checks ./components/things/index.js
|
|
204
|
+
|
|
205
|
+
// Import: from './components/cards'
|
|
206
|
+
// Resolution:
|
|
207
|
+
// 1. ./components/cards (not found)
|
|
208
|
+
// 2. ./components/cards.js (not found)
|
|
209
|
+
// 3. ./components/cards.svelte (not found)
|
|
210
|
+
// 4. ./components/cards/index.js (✓ found!) → uses this file
|
|
211
|
+
// → Should write './components/cards/index.js' explicitly
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Directory imports vs file imports
|
|
215
|
+
|
|
216
|
+
The linter follows Node.js/Vite resolution order and only flags
|
|
217
|
+
directory imports when they actually resolve to a directory's
|
|
218
|
+
index.js:
|
|
219
|
+
|
|
220
|
+
✅ No warning - imports a file:
|
|
221
|
+
```javascript
|
|
222
|
+
// src/lib/util/array.js exists (file)
|
|
223
|
+
import { arraySlice } from '$lib/util/array';
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
⚠️ Warning - imports a directory's index.js:
|
|
227
|
+
```javascript
|
|
228
|
+
// src/lib/ui/primitives/ directory with index.js
|
|
229
|
+
import { Button } from '$lib/ui/primitives';
|
|
230
|
+
// Should be: from '$lib/ui/primitives/index.js'
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Edge case: file and directory with same name
|
|
234
|
+
|
|
235
|
+
When both a file and directory exist with the same base name, the
|
|
236
|
+
file is always resolved first:
|
|
237
|
+
|
|
238
|
+
```javascript
|
|
239
|
+
// src/lib/util/env.js (file) exists
|
|
240
|
+
// src/lib/util/env/index.js (directory) also exists
|
|
241
|
+
import { isTestEnv } from '$lib/util/env';
|
|
242
|
+
// ✅ Resolves to env.js, no warning
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The linter correctly follows this resolution order.
|
|
246
|
+
|
|
247
|
+
## Test file exceptions
|
|
248
|
+
|
|
249
|
+
Test files (*.test.js, *.spec.js) are exempt from Rule 2 because
|
|
250
|
+
they test the public API. It's natural for tests to import from
|
|
251
|
+
`./index.js` alongside the code being tested.
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
// In Button.test.js
|
|
255
|
+
import { Button } from './index.js'; // ✅ OK in test files
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## External package imports
|
|
259
|
+
|
|
260
|
+
The linter only checks internal imports (`$lib/`, `./`, `../`).
|
|
261
|
+
External package imports are not validated:
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
import { derived } from 'svelte/store'; // Not checked
|
|
265
|
+
import { v } from 'valibot'; // Not checked
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Implementation details
|
|
269
|
+
|
|
270
|
+
The validator:
|
|
271
|
+
1. Scans all `.js` and `.svelte` files in `src/`
|
|
272
|
+
2. Parses import statements using regex
|
|
273
|
+
3. Resolves paths to filesystem locations
|
|
274
|
+
4. Checks if directories contain `index.js` files
|
|
275
|
+
5. Reports violations with file:line references
|
|
276
|
+
|
|
277
|
+
Exit codes:
|
|
278
|
+
- `0` - All imports valid
|
|
279
|
+
- `1` - Violations found or script error
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
src/lib/ui/components/rows/panel-row-2/PanelRow2.svelte:2 - Parent index.js import (use $lib/ or import specific file)
|
|
2
|
+
import { PanelGridRow } from '../index.js';
|
|
3
|
+
import { PanelGridRow } from '../index.js'; // TODO: Import specific file or refactor
|
|
4
|
+
|
|
5
|
+
src/lib/ui/components/tab-bar/HkTabBar.svelte:9 - Missing non-standard extension (use './HkTabBar.state.svelte.js')
|
|
6
|
+
import { createOrGetState } from './HkTabBar.state.svelte';
|
|
7
|
+
import { createOrGetState } from './HkTabBar.state.svelte.js';
|
|
8
|
+
|
|
9
|
+
src/lib/ui/primitives/icons/HkTabIcon.svelte:13 - Directory import (write explicitly: '../area/index.js')
|
|
10
|
+
import { HkGridArea } from '../area';
|
|
11
|
+
import { HkGridArea } from '../area/index.js';
|
|
12
|
+
|
|
13
|
+
src/lib/util/array/index.js:5 - Parent index.js import (use $lib/ or import specific file)
|
|
14
|
+
import { smallestFirst, largestFirst } from '../compare/index.js';
|
|
15
|
+
import { smallestFirst, largestFirst } from '../compare.js';
|
|
16
|
+
|
|
17
|
+
src/lib/util/array/index.js:7 - Parent index.js import (use $lib/ or import specific file)
|
|
18
|
+
import { objectGet, PATH_SEPARATOR } from '../object/index.js';
|
|
19
|
+
import { objectGet, PATH_SEPARATOR } from '../object.js';
|
|
20
|
+
|
|
21
|
+
src/lib/util/compare/index.js:3 - Parent index.js import (use $lib/ or import specific file)
|
|
22
|
+
import { objectGet } from '../object/index.js';
|
|
23
|
+
import { objectGet } from '../object.js';
|
|
24
|
+
|
|
25
|
+
src/lib/util/expect/compounds.js:2 - Parent index.js import (use $lib/ or import specific file)
|
|
26
|
+
import * as is from '../is/index.js';
|
|
27
|
+
import * as is from '../is.js';
|
|
28
|
+
|
|
29
|
+
src/lib/util/expect/objects.js:2 - Parent index.js import (use $lib/ or import specific file)
|
|
30
|
+
import * as is from '../is/index.js';
|
|
31
|
+
import * as is from '../is.js';
|
|
32
|
+
|
|
33
|
+
src/lib/util/iterate/index.js:4 - Parent index.js import (use $lib/ or import specific file)
|
|
34
|
+
import { smallestFirst, largestFirst } from '../compare/index.js';
|
|
35
|
+
import { smallestFirst, largestFirst } from '../compare.js';
|
|
36
|
+
|
|
37
|
+
src/lib/util/object/index.js:5 - Parent index.js import (use $lib/ or import specific file)
|
|
38
|
+
import { equals } from '../compare/index.js';
|
|
39
|
+
import { equals } from '../compare.js';
|
|
40
|
+
|
|
41
|
+
src/lib/util/object/index.js:7 - Parent index.js import (use $lib/ or import specific file)
|
|
42
|
+
import { toArrayPath } from '../array/index.js';
|
|
43
|
+
import { toArrayPath } from '../array.js';
|
|
44
|
+
|
|
45
|
+
src/lib/util/object/index.js:11 - Parent index.js import (use $lib/ or import specific file)
|
|
46
|
+
import * as is from '../is/index.js';
|
|
47
|
+
import * as is from '../is.js';
|
|
48
|
+
|
|
49
|
+
src/lib/util/object/index.js:13 - Parent index.js import (use $lib/ or import specific file)
|
|
50
|
+
import { iterateObjectPaths, iterateObjectEntries } from '../iterate/index.js';
|
|
51
|
+
import { iterateObjectPaths, iterateObjectEntries } from '../iterate.js';
|
|
52
|
+
|
|
53
|
+
src/lib/util/string/interpolate.js:5 - Parent index.js import (use $lib/ or import specific file)
|
|
54
|
+
import { objectGet, PATH_SEPARATOR } from '../object/index.js';
|
|
55
|
+
import { objectGet, PATH_SEPARATOR } from '../object.js';
|
|
56
|
+
|
|
57
|
+
src/routes/explorer/[...path]/+page.svelte:4 - Parent index.js import (use $lib/ or import specific file)
|
|
58
|
+
import { TopBar, Explorer } from '../components/index.js';
|
|
59
|
+
import { TopBar, Explorer } from '../components.js';
|
|
60
|
+
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
4
|
+
import { join, relative, resolve, dirname } from 'node:path';
|
|
5
|
+
|
|
6
|
+
const PROJECT_ROOT = process.cwd();
|
|
7
|
+
const SRC_DIR = join(PROJECT_ROOT, 'src');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Find all JS and Svelte files recursively
|
|
11
|
+
*
|
|
12
|
+
* @param {string} dir - Directory to search
|
|
13
|
+
*
|
|
14
|
+
* @returns {Promise<string[]>} Array of file paths
|
|
15
|
+
*/
|
|
16
|
+
async function findFiles(dir) {
|
|
17
|
+
const files = [];
|
|
18
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
19
|
+
|
|
20
|
+
for (const entry of entries) {
|
|
21
|
+
const fullPath = join(dir, entry.name);
|
|
22
|
+
if (entry.isDirectory()) {
|
|
23
|
+
if (entry.name !== 'node_modules' && entry.name !== '.svelte-kit') {
|
|
24
|
+
files.push(...await findFiles(fullPath));
|
|
25
|
+
}
|
|
26
|
+
} else if (entry.name.endsWith('.js') || entry.name.endsWith('.svelte')) {
|
|
27
|
+
files.push(fullPath);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return files;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check if import path resolves to directory with index.js
|
|
36
|
+
*
|
|
37
|
+
* Follows Node.js/Vite resolution order:
|
|
38
|
+
* 1. Check for file with .js extension
|
|
39
|
+
* 2. Check for file with .svelte extension
|
|
40
|
+
* 3. Check for directory with index.js
|
|
41
|
+
*
|
|
42
|
+
* @param {string} fsPath - Filesystem path to check (without extension)
|
|
43
|
+
*
|
|
44
|
+
* @returns {Promise<boolean>} True if resolves to directory with index.js
|
|
45
|
+
*/
|
|
46
|
+
async function isDirectoryWithIndex(fsPath) {
|
|
47
|
+
// First check if a file exists (files resolve before directories)
|
|
48
|
+
try {
|
|
49
|
+
const jsStats = await stat(fsPath + '.js');
|
|
50
|
+
if (jsStats.isFile()) {
|
|
51
|
+
return false; // Resolves to file, not directory
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
// .js file doesn't exist, continue checking
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const svelteStats = await stat(fsPath + '.svelte');
|
|
59
|
+
if (svelteStats.isFile()) {
|
|
60
|
+
return false; // Resolves to file, not directory
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
// .svelte file doesn't exist, continue checking
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Now check if it's a directory with index.js
|
|
67
|
+
try {
|
|
68
|
+
const dirStats = await stat(fsPath);
|
|
69
|
+
if (dirStats.isDirectory()) {
|
|
70
|
+
try {
|
|
71
|
+
await stat(join(fsPath, 'index.js'));
|
|
72
|
+
return true; // Directory with index.js
|
|
73
|
+
} catch {
|
|
74
|
+
return false; // Directory but no index.js
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} catch {
|
|
78
|
+
// Path doesn't exist at all
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Validate import paths in a file
|
|
86
|
+
*
|
|
87
|
+
* @param {string} filePath - Path to the file
|
|
88
|
+
*
|
|
89
|
+
* @returns {Promise<string[]>} Array of error messages
|
|
90
|
+
*/
|
|
91
|
+
async function validateFile(filePath) {
|
|
92
|
+
const content = await readFile(filePath, 'utf-8');
|
|
93
|
+
const errors = [];
|
|
94
|
+
const relativePath = relative(PROJECT_ROOT, filePath);
|
|
95
|
+
const isTestFile = filePath.endsWith('.test.js') ||
|
|
96
|
+
filePath.endsWith('.spec.js');
|
|
97
|
+
|
|
98
|
+
// Check each line for import statements
|
|
99
|
+
const lines = content.split('\n');
|
|
100
|
+
for (let index = 0; index < lines.length; index++) {
|
|
101
|
+
const line = lines[index];
|
|
102
|
+
const lineNum = index + 1;
|
|
103
|
+
|
|
104
|
+
// Skip if not an import line
|
|
105
|
+
if (!line.trim().startsWith('import ')) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Extract import path from line
|
|
110
|
+
const importMatch = line.match(/from ['"]([^'"]+)['"]/);
|
|
111
|
+
if (!importMatch) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const importPathRaw = importMatch[1];
|
|
116
|
+
|
|
117
|
+
// Strip query parameters (Vite asset imports like ?preset=render)
|
|
118
|
+
const importPath = importPathRaw.split('?')[0];
|
|
119
|
+
|
|
120
|
+
// Skip external packages (no ./ or $lib prefix)
|
|
121
|
+
if (!importPath.startsWith('./') &&
|
|
122
|
+
!importPath.startsWith('../') &&
|
|
123
|
+
!importPath.startsWith('$lib/')) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Check 1: Cross-domain relative imports (3+ levels up)
|
|
128
|
+
if (importPath.match(/^\.\.\/\.\.\/\.\.\//)) {
|
|
129
|
+
errors.push(
|
|
130
|
+
`${relativePath}:${lineNum} - Cross-domain relative import ` +
|
|
131
|
+
`(use $lib/ instead)`
|
|
132
|
+
);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Check 2: Local index.js imports (skip for test files)
|
|
137
|
+
// Allow ./index.js and ./subfolder/index.js but flag parent navigation
|
|
138
|
+
if (!isTestFile && importPath.match(/\/index\.js$/)) {
|
|
139
|
+
// Allow same-directory and child directory imports
|
|
140
|
+
// Examples: ./index.js, ./subfolder/index.js, ./(meta)/index.js
|
|
141
|
+
// Flag parent navigation: ../index.js, ../../index.js
|
|
142
|
+
const isParentNavigation = importPath.match(/^\.\..*\/index\.js$/);
|
|
143
|
+
|
|
144
|
+
if (isParentNavigation) {
|
|
145
|
+
errors.push(
|
|
146
|
+
`${relativePath}:${lineNum} - Parent index.js import ` +
|
|
147
|
+
`(use $lib/ or import specific file)`
|
|
148
|
+
);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Resolve to filesystem path
|
|
154
|
+
let fsPath;
|
|
155
|
+
if (importPath.startsWith('$lib/')) {
|
|
156
|
+
fsPath = join(PROJECT_ROOT, importPath.replace('$lib/', 'src/lib/'));
|
|
157
|
+
} else {
|
|
158
|
+
fsPath = resolve(dirname(filePath), importPath);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Check 3: Non-standard extensions (must be explicit)
|
|
162
|
+
// Files like .svelte.js need full extension in import
|
|
163
|
+
// Examples:
|
|
164
|
+
// import './Button.svelte' when Button.svelte.js exists → error
|
|
165
|
+
// import './Button' when Button.svelte.js exists → error
|
|
166
|
+
// import './Button.svelte.js' → correct!
|
|
167
|
+
|
|
168
|
+
const hasFullNonStandardExt = importPath.match(/\.(svelte\.js|test\.js|spec\.js)$/);
|
|
169
|
+
|
|
170
|
+
if (!hasFullNonStandardExt) {
|
|
171
|
+
// First check if file resolves with standard extension
|
|
172
|
+
let fileExistsWithStandardExt = false;
|
|
173
|
+
|
|
174
|
+
// Check .js
|
|
175
|
+
if (importPath.endsWith('.js')) {
|
|
176
|
+
try {
|
|
177
|
+
const stats = await stat(fsPath);
|
|
178
|
+
if (stats.isFile()) {
|
|
179
|
+
fileExistsWithStandardExt = true;
|
|
180
|
+
}
|
|
181
|
+
} catch {
|
|
182
|
+
// Doesn't exist
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Check .svelte
|
|
187
|
+
if (!fileExistsWithStandardExt && importPath.endsWith('.svelte')) {
|
|
188
|
+
try {
|
|
189
|
+
const stats = await stat(fsPath);
|
|
190
|
+
if (stats.isFile()) {
|
|
191
|
+
fileExistsWithStandardExt = true;
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
// Doesn't exist
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Check implicit .js (no extension in import)
|
|
199
|
+
if (!fileExistsWithStandardExt &&
|
|
200
|
+
!importPath.endsWith('.js') &&
|
|
201
|
+
!importPath.endsWith('.svelte')) {
|
|
202
|
+
try {
|
|
203
|
+
const stats = await stat(fsPath + '.js');
|
|
204
|
+
if (stats.isFile()) {
|
|
205
|
+
fileExistsWithStandardExt = true;
|
|
206
|
+
}
|
|
207
|
+
} catch {
|
|
208
|
+
// Doesn't exist
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Check implicit .svelte (no extension in import)
|
|
213
|
+
if (!fileExistsWithStandardExt &&
|
|
214
|
+
!importPath.endsWith('.js') &&
|
|
215
|
+
!importPath.endsWith('.svelte')) {
|
|
216
|
+
try {
|
|
217
|
+
const stats = await stat(fsPath + '.svelte');
|
|
218
|
+
if (stats.isFile()) {
|
|
219
|
+
fileExistsWithStandardExt = true;
|
|
220
|
+
}
|
|
221
|
+
} catch {
|
|
222
|
+
// Doesn't exist
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Only check for non-standard extensions if standard doesn't exist
|
|
227
|
+
if (!fileExistsWithStandardExt) {
|
|
228
|
+
// Remove any standard extension from import path
|
|
229
|
+
const baseImportPath = importPath
|
|
230
|
+
.replace(/\.js$/, '')
|
|
231
|
+
.replace(/\.svelte$/, '');
|
|
232
|
+
|
|
233
|
+
let baseFsPath;
|
|
234
|
+
if (baseImportPath.startsWith('$lib/')) {
|
|
235
|
+
baseFsPath = join(
|
|
236
|
+
PROJECT_ROOT,
|
|
237
|
+
baseImportPath.replace('$lib/', 'src/lib/')
|
|
238
|
+
);
|
|
239
|
+
} else if (baseImportPath.startsWith('./') ||
|
|
240
|
+
baseImportPath.startsWith('../')) {
|
|
241
|
+
baseFsPath = resolve(dirname(filePath), baseImportPath);
|
|
242
|
+
} else {
|
|
243
|
+
baseFsPath = fsPath;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Check for files with non-standard extensions
|
|
247
|
+
const nonStandardExts = ['.svelte.js', '.test.js', '.spec.js'];
|
|
248
|
+
let foundNonStandard = false;
|
|
249
|
+
|
|
250
|
+
for (const ext of nonStandardExts) {
|
|
251
|
+
try {
|
|
252
|
+
const testPath = baseFsPath + ext;
|
|
253
|
+
const stats = await stat(testPath);
|
|
254
|
+
if (stats.isFile()) {
|
|
255
|
+
const correctImport = baseImportPath + ext;
|
|
256
|
+
errors.push(
|
|
257
|
+
`${relativePath}:${lineNum} - Missing non-standard ` +
|
|
258
|
+
`extension (use '${correctImport}')`
|
|
259
|
+
);
|
|
260
|
+
foundNonStandard = true;
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
} catch {
|
|
264
|
+
// File doesn't exist with this extension, continue checking
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Skip remaining checks if we found a non-standard extension issue
|
|
269
|
+
if (foundNonStandard) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Check 4: Directory imports (when directory has index.js)
|
|
276
|
+
// Only check if import doesn't have extension (extensionless imports)
|
|
277
|
+
const hasAnyExtension = importPath.match(/\.(js|svelte)$/) ||
|
|
278
|
+
importPath.match(/\.(svelte\.js|test\.js|spec\.js)$/);
|
|
279
|
+
|
|
280
|
+
if (!hasAnyExtension) {
|
|
281
|
+
// Check if it's a directory with index.js
|
|
282
|
+
if (await isDirectoryWithIndex(fsPath)) {
|
|
283
|
+
// Don't suggest ../path/index.js (parent navigation)
|
|
284
|
+
// Suggest creating export file instead
|
|
285
|
+
const wouldBeParentNavigation = importPath.match(/^\.\.\//);
|
|
286
|
+
|
|
287
|
+
if (wouldBeParentNavigation) {
|
|
288
|
+
errors.push(
|
|
289
|
+
`${relativePath}:${lineNum} - Directory import requires ` +
|
|
290
|
+
`parent navigation (create export file like '${importPath}.js' ` +
|
|
291
|
+
`or import specific file)`
|
|
292
|
+
);
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const suggestion = importPath.endsWith('/') ?
|
|
297
|
+
`${importPath}index.js` : `${importPath}/index.js`;
|
|
298
|
+
errors.push(
|
|
299
|
+
`${relativePath}:${lineNum} - Directory import ` +
|
|
300
|
+
`(write explicitly: '${suggestion}')`
|
|
301
|
+
);
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Check 5: File existence (after all other checks)
|
|
307
|
+
// Verify that the import path resolves to an existing file
|
|
308
|
+
// Follow Node.js/Vite resolution order
|
|
309
|
+
let fileExists = false;
|
|
310
|
+
const possiblePaths = [];
|
|
311
|
+
|
|
312
|
+
// If import has extension, check exact path
|
|
313
|
+
if (importPath.match(/\.(js|svelte|svelte\.js|test\.js|spec\.js)$/)) {
|
|
314
|
+
possiblePaths.push(fsPath);
|
|
315
|
+
} else {
|
|
316
|
+
// No extension, try in resolution order
|
|
317
|
+
possiblePaths.push(fsPath); // Exact match
|
|
318
|
+
possiblePaths.push(fsPath + '.js');
|
|
319
|
+
possiblePaths.push(fsPath + '.svelte');
|
|
320
|
+
possiblePaths.push(fsPath + '.svelte.js');
|
|
321
|
+
possiblePaths.push(fsPath + '/index.js');
|
|
322
|
+
possiblePaths.push(fsPath + '/index.svelte');
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
for (const testPath of possiblePaths) {
|
|
326
|
+
try {
|
|
327
|
+
const stats = await stat(testPath);
|
|
328
|
+
if (stats.isFile()) {
|
|
329
|
+
fileExists = true;
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
} catch {
|
|
333
|
+
// File doesn't exist, continue checking
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (!fileExists) {
|
|
338
|
+
errors.push(
|
|
339
|
+
`${relativePath}:${lineNum} - Import path does not exist: ` +
|
|
340
|
+
`'${importPath}'`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return errors;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Main validation function
|
|
350
|
+
*/
|
|
351
|
+
async function main() {
|
|
352
|
+
console.log('Validating import paths...\n');
|
|
353
|
+
|
|
354
|
+
const files = await findFiles(SRC_DIR);
|
|
355
|
+
const allErrors = [];
|
|
356
|
+
|
|
357
|
+
for (const file of files) {
|
|
358
|
+
const errors = await validateFile(file);
|
|
359
|
+
allErrors.push(...errors);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (allErrors.length > 0) {
|
|
363
|
+
console.error('❌ Found import path violations:\n');
|
|
364
|
+
allErrors.forEach(error => console.error(` ${error}`));
|
|
365
|
+
console.error(`\n${allErrors.length} error(s) found.`);
|
|
366
|
+
process.exit(1);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
console.log('✅ All import paths are valid!');
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
main().catch(error => {
|
|
373
|
+
console.error('Validation script error:', error);
|
|
374
|
+
process.exit(1);
|
|
375
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as Logger } from "./Logger.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as Logger } from './Logger.js';
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { default as ButtonGroup } from "./button-group/ButtonGroup.svelte";
|
|
2
|
-
export { default as CompareLeftRight } from "./compare-left-right/CompareLeftRight.svelte";
|
|
3
|
-
export { default as GameBox } from "./game-box/GameBox.svelte";
|
|
4
|
-
export { default as HkAppLayout } from "./hk-app-layout/HkAppLayout.svelte";
|
|
5
|
-
export { default as ImageBox } from "./image-box/ImageBox.svelte";
|
|
6
|
-
export { default as Presenter } from "./presenter/Presenter.svelte";
|
|
7
|
-
export { default as ImageSlide } from "./presenter/ImageSlide.svelte";
|
|
8
|
-
export { default as VirtualViewport } from "./virtual-viewport/VirtualViewport.svelte";
|
|
9
|
-
export * from "./button-group/typedef.js";
|
|
10
|
-
export * from "./presenter/typedef.js";
|
|
11
|
-
export { createOrGetState as createOrGetAppLayoutState, createState as createAppLayoutState, getState as getAppLayoutState } from "./hk-app-layout/HkAppLayout.state.svelte.js";
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export { default as ButtonGroup } from './button-group/ButtonGroup.svelte';
|
|
2
|
-
export { default as CompareLeftRight } from './compare-left-right/CompareLeftRight.svelte';
|
|
3
|
-
export { default as GameBox } from './game-box/GameBox.svelte';
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
createOrGetState as createOrGetAppLayoutState,
|
|
7
|
-
createState as createAppLayoutState,
|
|
8
|
-
getState as getAppLayoutState
|
|
9
|
-
} from './hk-app-layout/HkAppLayout.state.svelte.js';
|
|
10
|
-
|
|
11
|
-
export { default as HkAppLayout } from './hk-app-layout/HkAppLayout.svelte';
|
|
12
|
-
|
|
13
|
-
export { default as ImageBox } from './image-box/ImageBox.svelte';
|
|
14
|
-
|
|
15
|
-
export { default as Presenter } from './presenter/Presenter.svelte';
|
|
16
|
-
export { default as ImageSlide } from './presenter/ImageSlide.svelte';
|
|
17
|
-
|
|
18
|
-
export { default as VirtualViewport } from './virtual-viewport/VirtualViewport.svelte';
|
|
19
|
-
|
|
20
|
-
// > Types
|
|
21
|
-
|
|
22
|
-
export * from './button-group/typedef.js';
|
|
23
|
-
export * from './presenter/typedef.js';
|