@ts-svg/svelte 0.0.1-beta.0 → 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/README.md +226 -0
- package/package.json +2 -2
- package/src/index.js +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# ts-svg
|
|
2
|
+
|
|
3
|
+
Type-safe SVG bundling for Vite. `ts-svg` scans a directory (including subdirectories), generates **typed virtual modules**, and lets you import SVGs as framework components with great DX (autocomplete + type checking) and proper bundling/tree-shaking.
|
|
4
|
+
|
|
5
|
+
## Why ts-svg?
|
|
6
|
+
|
|
7
|
+
- **Type-safe imports**: virtual modules are generated with types, so importing from `virtual:ts-svg/...` is typed.
|
|
8
|
+
- **Great DX**: namespace import + `<Icon.` gives instant autocomplete for every icon in that folder.
|
|
9
|
+
- **Optimized output**: SVGs are optimized (SVGO) and transformed into **Svelte components**.
|
|
10
|
+
- **Tree-shakable**: only the SVGs you actually use end up bundled.
|
|
11
|
+
|
|
12
|
+
## Packages
|
|
13
|
+
|
|
14
|
+
- **Svelte / SvelteKit:** `@ts-svg/svelte`
|
|
15
|
+
- (Other framework adapters will be available soon)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## SvelteKit Setup (`@ts-svg/svelte`)
|
|
20
|
+
|
|
21
|
+
### 1) Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm i -D @ts-svg/svelte
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 2) Add the Vite plugin
|
|
28
|
+
|
|
29
|
+
Add `tsSvg()` to `vite.config.ts`. The `path` option is required.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { sveltekit } from '@sveltejs/kit/vite';
|
|
33
|
+
import { defineConfig } from 'vite';
|
|
34
|
+
import { tsSvg } from '@ts-svg/svelte';
|
|
35
|
+
|
|
36
|
+
export default defineConfig({
|
|
37
|
+
plugins: [
|
|
38
|
+
sveltekit(),
|
|
39
|
+
// Step 1: Add the vite plugin
|
|
40
|
+
tsSvg({
|
|
41
|
+
path: './src/lib/svgs',
|
|
42
|
+
// svgoConfig: {...} // optional: override default SVGO config
|
|
43
|
+
}),
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`path` is the folder to scan. All `.svg` files inside it (and subfolders) become typed virtual modules.
|
|
49
|
+
|
|
50
|
+
### 3) Reference the generated ambient types
|
|
51
|
+
|
|
52
|
+
In `src/app.d.ts`, add a reference to the generated `ambient.d.ts`:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// Step 2: Import the generated types
|
|
56
|
+
/// <reference types="../.ts-svg/ambient.d.ts" />
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 4) Ignore the generated directory
|
|
60
|
+
|
|
61
|
+
Add `.ts-svg` to both `.gitignore` and `.prettierignore`:
|
|
62
|
+
|
|
63
|
+
```gitignore
|
|
64
|
+
.ts-svg
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 5) Generate types in CI (recommended)
|
|
68
|
+
|
|
69
|
+
In CI (or any non-dev environment), you may not want to rely on the dev server to trigger generation.
|
|
70
|
+
Prepend the CLI `ts-svg` in `package.json` scripts that run in CI:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"scripts": {
|
|
75
|
+
"prepare": "ts-svg && svelte-kit sync || echo ''",
|
|
76
|
+
"check": "ts-svg && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
77
|
+
"check:watch": "ts-svg && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
Put SVGs under the directory you configured (e.g. `./src/lib/svgs`).
|
|
87
|
+
|
|
88
|
+
Then import from `virtual:ts-svg`:
|
|
89
|
+
|
|
90
|
+
- Root folder: `virtual:ts-svg`
|
|
91
|
+
- Subfolder: `virtual:ts-svg/<subfolder>`
|
|
92
|
+
|
|
93
|
+
### Recommended: namespace import for icon folders
|
|
94
|
+
|
|
95
|
+
If you have `./src/lib/svgs/icons/*.svg`:
|
|
96
|
+
|
|
97
|
+
```svelte
|
|
98
|
+
<script lang="ts">
|
|
99
|
+
import * as Icon from 'virtual:ts-svg/icons'; // recommended
|
|
100
|
+
// or import one-by-one:
|
|
101
|
+
import { Home } from 'virtual:ts-svg/icons';
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<Icon.Book class="size-200" />
|
|
105
|
+
<Home />
|
|
106
|
+
|
|
107
|
+
<style>
|
|
108
|
+
:global(.size-200) {
|
|
109
|
+
width: 200px;
|
|
110
|
+
height: 200px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
:global(svg) {
|
|
114
|
+
width: 150px;
|
|
115
|
+
height: 150px;
|
|
116
|
+
}
|
|
117
|
+
</style>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Typing `<Icon.` will show all icons in autocomplete.
|
|
121
|
+
|
|
122
|
+
### Props
|
|
123
|
+
|
|
124
|
+
Imported SVGs are Svelte components and accept normal props (e.g. `class`, `style`, etc.).
|
|
125
|
+
|
|
126
|
+
For a complete SvelteKit example (config, generated types, and usage), see the sample setup here: [examples/sveltekit](https://github.com/chunnamwong/ts-svg/tree/main/examples/svelte).
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Tip: Create a local re-export for nicer imports
|
|
131
|
+
|
|
132
|
+
If it’s hard to remember import paths like `virtual:ts-svg/icons`, you can create a local module and re-export your namespace.
|
|
133
|
+
|
|
134
|
+
Create `src/lib/Icon.ts`:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
export * as Icon from 'virtual:ts-svg/icons';
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Then import from your app code:
|
|
141
|
+
|
|
142
|
+
```svelte
|
|
143
|
+
<script lang="ts">
|
|
144
|
+
import { Icon } from '$lib/Icon';
|
|
145
|
+
</script>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
You can do the same pattern for other subdirectories (e.g. `brand`, `images`, etc.):
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Configuration
|
|
153
|
+
|
|
154
|
+
### `path` (required)
|
|
155
|
+
|
|
156
|
+
The directory to scan for `.svg` files.
|
|
157
|
+
|
|
158
|
+
### `svgoConfig` (optional)
|
|
159
|
+
|
|
160
|
+
Override the default SVGO configuration used during optimization.
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
tsSvg({
|
|
164
|
+
path: './src/lib/svgs',
|
|
165
|
+
svgoConfig: {
|
|
166
|
+
// your custom svgo config
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Generated output
|
|
174
|
+
|
|
175
|
+
`ts-svg` generates this file:
|
|
176
|
+
|
|
177
|
+
- `.ts-svg/ambient.d.ts` (referenced from `src/app.d.ts`)
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## FAQ
|
|
182
|
+
|
|
183
|
+
### Do I need to commit `.ts-svg`?
|
|
184
|
+
|
|
185
|
+
No. It’s generated output. Add it to `.gitignore` and regenerate it in CI using `ts-svg` in your scripts.
|
|
186
|
+
|
|
187
|
+
### How do subfolders map to imports?
|
|
188
|
+
|
|
189
|
+
A subfolder becomes an import path segment.
|
|
190
|
+
|
|
191
|
+
Example:
|
|
192
|
+
|
|
193
|
+
- `src/lib/svgs/icons/Home.svg` → `import { Home } from 'virtual:ts-svg/icons'`
|
|
194
|
+
|
|
195
|
+
### How do I stay safe with tree shaking?
|
|
196
|
+
|
|
197
|
+
Tree-shaking works best when the bundler can see **exactly which exports you use**.
|
|
198
|
+
|
|
199
|
+
If you use a namespace import:
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import * as Icon from 'virtual:ts-svg/icons';
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
✅ **Do** access **specific exports**:
|
|
206
|
+
|
|
207
|
+
```svelte
|
|
208
|
+
<Icon.Home />
|
|
209
|
+
<Icon.Book />
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
⚠️ **Don’t** pass around or “touch” the whole namespace object (e.g. iterating keys, spreading, or indexing dynamically). If the bundler detects the namespace object itself is used as a value, it may conservatively treat **all exports as used**, which can cause **all icons to be bundled**, even if you only use a few.
|
|
213
|
+
|
|
214
|
+
Examples to avoid:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
Object.keys(Icon); // iterating namespace
|
|
218
|
+
const Comp = Icon[name]; // dynamic access
|
|
219
|
+
const list = { ...Icon }; // spreading namespace
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ts-svg/svelte",
|
|
3
|
-
"version": "0.0.1
|
|
3
|
+
"version": "0.0.1",
|
|
4
4
|
"description": "Vite Plugin for loading all svg files inside a folder with types.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vite-plugin",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"svgo": "^4.0.0",
|
|
36
|
-
"@ts-svg/core": "^0.0.1
|
|
36
|
+
"@ts-svg/core": "^0.0.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^24.6.0"
|
package/src/index.js
CHANGED
|
@@ -45,7 +45,7 @@ declare module '*.svg?svelte' {
|
|
|
45
45
|
export default component;
|
|
46
46
|
}
|
|
47
47
|
`,
|
|
48
|
-
async transform(_code, id) {
|
|
48
|
+
async transform(_code, id, options) {
|
|
49
49
|
if (!id.endsWith('.svg?svelte')) {
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
@@ -57,7 +57,7 @@ declare module '*.svg?svelte' {
|
|
|
57
57
|
);
|
|
58
58
|
const componentCode = optimizedSvgSource.replace(/<svg([^>]*)>/, '<svg$1 {...$$$$props}>');
|
|
59
59
|
const component = compile(componentCode, {
|
|
60
|
-
generate:
|
|
60
|
+
generate: options?.ssr ? 'server' : undefined,
|
|
61
61
|
});
|
|
62
62
|
return {
|
|
63
63
|
code: component.js.code,
|