@rsvelte/vite-plugin-svelte 0.1.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/LICENSE +21 -0
- package/README.md +28 -0
- package/package.json +59 -0
- package/src/index.js +42 -0
- package/src/plugins/compile-module.js +130 -0
- package/src/plugins/compile.js +65 -0
- package/src/plugins/configure.js +97 -0
- package/src/plugins/hot-update.js +196 -0
- package/src/plugins/load-compiled-css.js +66 -0
- package/src/plugins/load-custom.js +42 -0
- package/src/plugins/preprocess.js +208 -0
- package/src/plugins/setup-optimizer.js +340 -0
- package/src/preprocess.js +166 -0
- package/src/public.d.ts +217 -0
- package/src/types/compile.d.ts +37 -0
- package/src/types/id.d.ts +46 -0
- package/src/types/log.d.ts +24 -0
- package/src/types/options.d.ts +21 -0
- package/src/types/plugin-api.d.ts +15 -0
- package/src/types/vite-plugin-svelte-stats.d.ts +30 -0
- package/src/utils/compile.js +152 -0
- package/src/utils/constants.js +36 -0
- package/src/utils/dependencies.js +60 -0
- package/src/utils/error.js +167 -0
- package/src/utils/hash.js +43 -0
- package/src/utils/id.js +274 -0
- package/src/utils/load-svelte-config.js +80 -0
- package/src/utils/log.js +256 -0
- package/src/utils/options.js +618 -0
- package/src/utils/preprocess.js +89 -0
- package/src/utils/sourcemaps.js +82 -0
- package/src/utils/svelte-version.js +46 -0
- package/src/utils/vite-plugin-svelte-stats.js +248 -0
- package/src/utils/watch.js +95 -0
- package/types/index.d.ts +228 -0
- package/types/index.d.ts.map +31 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
|
|
4
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {{
|
|
8
|
+
* file?: string;
|
|
9
|
+
* sources?: string[];
|
|
10
|
+
* sourceRoot?: string;
|
|
11
|
+
* }} SourceMapFileRefs
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* convert absolute paths in sourcemap file refs to their relative equivalents to avoid leaking fs info
|
|
16
|
+
*
|
|
17
|
+
* map is modified in place.
|
|
18
|
+
*
|
|
19
|
+
* @param {SourceMapFileRefs | undefined} map sourcemap
|
|
20
|
+
* @param {string} filename absolute path to file the sourcemap is for
|
|
21
|
+
*/
|
|
22
|
+
export function mapToRelative(map, filename) {
|
|
23
|
+
if (!map) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const sourceRoot = map.sourceRoot;
|
|
27
|
+
const dirname = path.dirname(filename);
|
|
28
|
+
|
|
29
|
+
/** @type {(s: string) => string} */
|
|
30
|
+
const toRelative = (s) => {
|
|
31
|
+
if (!s) {
|
|
32
|
+
return s;
|
|
33
|
+
}
|
|
34
|
+
/** @type {string} */
|
|
35
|
+
let sourcePath;
|
|
36
|
+
if (s.startsWith('file:///')) {
|
|
37
|
+
// windows has file:///C:/foo and posix has file:///foo, so we have to remove one extra on windows
|
|
38
|
+
sourcePath = s.slice(IS_WINDOWS ? 8 : 7);
|
|
39
|
+
} else if (sourceRoot) {
|
|
40
|
+
const sep = sourceRoot[sourceRoot.length - 1] === '/' || s[0] === '/' ? '' : '/';
|
|
41
|
+
sourcePath = `${sourceRoot}${sep}${s}`;
|
|
42
|
+
} else {
|
|
43
|
+
sourcePath = s;
|
|
44
|
+
}
|
|
45
|
+
return path.isAbsolute(sourcePath) ? path.relative(dirname, sourcePath) : sourcePath;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
if (map.file) {
|
|
49
|
+
map.file = path.basename(filename);
|
|
50
|
+
}
|
|
51
|
+
if (map.sources) {
|
|
52
|
+
map.sources = map.sources.map(toRelative);
|
|
53
|
+
}
|
|
54
|
+
if (map.sourceRoot) {
|
|
55
|
+
// we have prepended sourceRoot and computed relative paths from it
|
|
56
|
+
// remove it here to avoid downstream processing prepending it again
|
|
57
|
+
delete map.sourceRoot;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* vitePreprocess uses an extra lang extension to tell vite about the type of preprocessor to use
|
|
63
|
+
* This function removes it afterwards to get back working file refs
|
|
64
|
+
*
|
|
65
|
+
* map is modified in place.
|
|
66
|
+
*
|
|
67
|
+
* @param {SourceMapFileRefs | undefined} map the output sourcemap
|
|
68
|
+
* @param {string} suffix the suffix to remove
|
|
69
|
+
*/
|
|
70
|
+
export function removeLangSuffix(map, suffix) {
|
|
71
|
+
if (!map) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
/** @type {(s:string)=> string} */
|
|
75
|
+
const removeSuffix = (s) => (s?.endsWith(suffix) ? s.slice(0, -1 * suffix.length) : s);
|
|
76
|
+
if (map.file) {
|
|
77
|
+
map.file = removeSuffix(map.file);
|
|
78
|
+
}
|
|
79
|
+
if (map.sources) {
|
|
80
|
+
map.sources = map.sources.map(removeSuffix);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { VERSION } from '@rsvelte/compiler';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {boolean}
|
|
5
|
+
*/
|
|
6
|
+
export const isSvelteWithAsync = gte(VERSION, '5.36.0');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* split semver string and convert to number, ignores non digits in tag
|
|
10
|
+
* @param {string} semver
|
|
11
|
+
* @return {number[]} [major,minor,patch,tag]
|
|
12
|
+
*/
|
|
13
|
+
function splitToNumbers(semver) {
|
|
14
|
+
const num = semver
|
|
15
|
+
.replace(/[^\d.-]/g, '')
|
|
16
|
+
.split(/[.-]+/, 4)
|
|
17
|
+
.map(Number);
|
|
18
|
+
while (num.length < 3) {
|
|
19
|
+
num.push(0);
|
|
20
|
+
}
|
|
21
|
+
if (num.length < 4) {
|
|
22
|
+
num.push(Infinity);
|
|
23
|
+
}
|
|
24
|
+
return num;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* compare semver versions, tags are compared by their numeric part only
|
|
29
|
+
*
|
|
30
|
+
* @param {string} a semver version
|
|
31
|
+
* @param {string} b semver version
|
|
32
|
+
* @return {boolean} true if a is greater or equal to b
|
|
33
|
+
*/
|
|
34
|
+
export function gte(a, b) {
|
|
35
|
+
const aNum = splitToNumbers(a);
|
|
36
|
+
const bNum = splitToNumbers(b);
|
|
37
|
+
for (let i = 0; i < aNum.length; i++) {
|
|
38
|
+
if (aNum[i] < bNum[i]) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (aNum[i] > bNum[i]) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { log } from './log.js';
|
|
2
|
+
import { performance } from 'node:perf_hooks';
|
|
3
|
+
import { normalizePath } from 'vite';
|
|
4
|
+
import { findClosestPkgJsonPath } from 'vitefu';
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { dirname } from 'node:path';
|
|
7
|
+
|
|
8
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').CollectionOptions} */
|
|
9
|
+
const defaultCollectionOptions = {
|
|
10
|
+
// log after 500ms and more than one file processed
|
|
11
|
+
logInProgress: (c, now) => now - c.collectionStart > 500 && c.stats.length > 1,
|
|
12
|
+
// always log results
|
|
13
|
+
logResult: () => true
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {number} n
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
function humanDuration(n) {
|
|
21
|
+
// 99.9ms 0.10s
|
|
22
|
+
return n < 100 ? `${n.toFixed(1)}ms` : `${(n / 1000).toFixed(2)}s`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {import('../types/vite-plugin-svelte-stats.d.ts').PackageStats[]} pkgStats
|
|
27
|
+
* @returns {string}
|
|
28
|
+
*/
|
|
29
|
+
function formatPackageStats(pkgStats) {
|
|
30
|
+
const statLines = pkgStats.map((pkgStat) => {
|
|
31
|
+
const duration = pkgStat.duration;
|
|
32
|
+
const avg = duration / pkgStat.files;
|
|
33
|
+
return [pkgStat.pkg, `${pkgStat.files}`, humanDuration(duration), humanDuration(avg)];
|
|
34
|
+
});
|
|
35
|
+
statLines.unshift(['package', 'files', 'time', 'avg']);
|
|
36
|
+
const columnWidths = statLines.reduce(
|
|
37
|
+
(widths, row) => {
|
|
38
|
+
for (let i = 0; i < row.length; i++) {
|
|
39
|
+
const cell = row[i];
|
|
40
|
+
if (widths[i] < cell.length) {
|
|
41
|
+
widths[i] = cell.length;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return widths;
|
|
45
|
+
},
|
|
46
|
+
statLines[0].map(() => 0)
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const table = statLines
|
|
50
|
+
.map((row) =>
|
|
51
|
+
row
|
|
52
|
+
.map((cell, i) => {
|
|
53
|
+
if (i === 0) {
|
|
54
|
+
return cell.padEnd(columnWidths[i], ' ');
|
|
55
|
+
} else {
|
|
56
|
+
return cell.padStart(columnWidths[i], ' ');
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
.join('\t')
|
|
60
|
+
)
|
|
61
|
+
.join('\n');
|
|
62
|
+
return table;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @class
|
|
67
|
+
*/
|
|
68
|
+
export class VitePluginSvelteStats {
|
|
69
|
+
/** @type {PackageInfo[]} */
|
|
70
|
+
#packageInfos = [];
|
|
71
|
+
|
|
72
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection[]} */
|
|
73
|
+
#collections = [];
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {string} name
|
|
77
|
+
* @param {Partial<import('../types/vite-plugin-svelte-stats.d.ts').CollectionOptions>} [opts]
|
|
78
|
+
* @returns {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection}
|
|
79
|
+
*/
|
|
80
|
+
startCollection(name, opts) {
|
|
81
|
+
const options = {
|
|
82
|
+
...defaultCollectionOptions,
|
|
83
|
+
...opts
|
|
84
|
+
};
|
|
85
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').Stat[]} */
|
|
86
|
+
const stats = [];
|
|
87
|
+
const collectionStart = performance.now();
|
|
88
|
+
|
|
89
|
+
const _this = this;
|
|
90
|
+
let hasLoggedProgress = false;
|
|
91
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} */
|
|
92
|
+
const collection = {
|
|
93
|
+
name,
|
|
94
|
+
options,
|
|
95
|
+
stats,
|
|
96
|
+
collectionStart,
|
|
97
|
+
finished: false,
|
|
98
|
+
start(file) {
|
|
99
|
+
if (collection.finished) {
|
|
100
|
+
throw new Error('called after finish() has been used');
|
|
101
|
+
}
|
|
102
|
+
file = normalizePath(file);
|
|
103
|
+
const start = performance.now();
|
|
104
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').Stat} */
|
|
105
|
+
const stat = { file, start, end: start };
|
|
106
|
+
return () => {
|
|
107
|
+
const now = performance.now();
|
|
108
|
+
stat.end = now;
|
|
109
|
+
stats.push(stat);
|
|
110
|
+
if (!hasLoggedProgress && options.logInProgress(collection, now)) {
|
|
111
|
+
hasLoggedProgress = true;
|
|
112
|
+
log.debug(`${name} in progress ...`, undefined, 'stats');
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
async finish() {
|
|
117
|
+
await _this.#finish(collection);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
_this.#collections.push(collection);
|
|
121
|
+
return collection;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async finishAll() {
|
|
125
|
+
await Promise.all(this.#collections.map((c) => c.finish()));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @param {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} collection
|
|
130
|
+
*/
|
|
131
|
+
async #finish(collection) {
|
|
132
|
+
try {
|
|
133
|
+
collection.finished = true;
|
|
134
|
+
const now = performance.now();
|
|
135
|
+
collection.duration = now - collection.collectionStart;
|
|
136
|
+
const logResult = collection.options.logResult(collection);
|
|
137
|
+
if (logResult) {
|
|
138
|
+
await this.#aggregateStatsResult(collection);
|
|
139
|
+
log.debug(
|
|
140
|
+
`${collection.name} done.\n${formatPackageStats(
|
|
141
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').PackageStats[]}*/ (
|
|
142
|
+
collection.packageStats
|
|
143
|
+
)
|
|
144
|
+
)}`,
|
|
145
|
+
undefined,
|
|
146
|
+
'stats'
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
// cut some ties to free it for garbage collection
|
|
150
|
+
const index = this.#collections.indexOf(collection);
|
|
151
|
+
this.#collections.splice(index, 1);
|
|
152
|
+
collection.stats.length = 0;
|
|
153
|
+
collection.stats = [];
|
|
154
|
+
if (collection.packageStats) {
|
|
155
|
+
collection.packageStats.length = 0;
|
|
156
|
+
collection.packageStats = [];
|
|
157
|
+
}
|
|
158
|
+
collection.start = () => () => {};
|
|
159
|
+
collection.finish = () => {};
|
|
160
|
+
} catch (e) {
|
|
161
|
+
// this should not happen, but stats taking also should not break the process
|
|
162
|
+
log.debug.once(`failed to finish stats for ${collection.name}\n`, e, 'stats');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @param {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} collection
|
|
168
|
+
*/
|
|
169
|
+
async #aggregateStatsResult(collection) {
|
|
170
|
+
const stats = collection.stats;
|
|
171
|
+
for (const stat of stats) {
|
|
172
|
+
stat.pkg = (await this.#getPackageInfo(stat.file)).name;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// group stats
|
|
176
|
+
/** @type {Record<string, import('../types/vite-plugin-svelte-stats.d.ts').PackageStats>} */
|
|
177
|
+
const grouped = {};
|
|
178
|
+
stats.forEach((stat) => {
|
|
179
|
+
const pkg = /** @type {string} */ (stat.pkg);
|
|
180
|
+
let group = grouped[pkg];
|
|
181
|
+
if (!group) {
|
|
182
|
+
group = grouped[pkg] = {
|
|
183
|
+
files: 0,
|
|
184
|
+
duration: 0,
|
|
185
|
+
pkg
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
group.files += 1;
|
|
189
|
+
group.duration += stat.end - stat.start;
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const groups = Object.values(grouped);
|
|
193
|
+
groups.sort((a, b) => b.duration - a.duration);
|
|
194
|
+
collection.packageStats = groups;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* @param {string} file
|
|
198
|
+
* @returns {Promise<PackageInfo>}
|
|
199
|
+
*/
|
|
200
|
+
async #getPackageInfo(file) {
|
|
201
|
+
let info = this.#packageInfos.find((pi) => file.startsWith(pi.path));
|
|
202
|
+
if (!info) {
|
|
203
|
+
info = await findPackageInfo(file);
|
|
204
|
+
this.#packageInfos.push(info);
|
|
205
|
+
}
|
|
206
|
+
return info;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @typedef {{
|
|
212
|
+
* name: string;
|
|
213
|
+
* version: string;
|
|
214
|
+
* svelte?: string;
|
|
215
|
+
* path: string;
|
|
216
|
+
* }} PackageInfo
|
|
217
|
+
*/
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* utility to get some info from the closest package.json with a "name" set
|
|
221
|
+
*
|
|
222
|
+
* @param {string} file to find info for
|
|
223
|
+
* @returns {Promise<PackageInfo>}
|
|
224
|
+
*/
|
|
225
|
+
async function findPackageInfo(file) {
|
|
226
|
+
/** @type {PackageInfo} */
|
|
227
|
+
const info = {
|
|
228
|
+
name: '$unknown',
|
|
229
|
+
version: '0.0.0-unknown',
|
|
230
|
+
path: '$unknown'
|
|
231
|
+
};
|
|
232
|
+
let path = await findClosestPkgJsonPath(file, (pkgPath) => {
|
|
233
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
234
|
+
if (pkg.name != null) {
|
|
235
|
+
info.name = pkg.name;
|
|
236
|
+
if (pkg.version != null) {
|
|
237
|
+
info.version = pkg.version;
|
|
238
|
+
}
|
|
239
|
+
info.svelte = pkg.svelte;
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
return false;
|
|
243
|
+
});
|
|
244
|
+
// return normalized path with appended '/' so .startsWith works for future file checks
|
|
245
|
+
path = normalizePath(dirname(path ?? file)) + '/';
|
|
246
|
+
info.path = path;
|
|
247
|
+
return info;
|
|
248
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { log } from './log.js';
|
|
3
|
+
import { knownSvelteConfigNames } from './load-svelte-config.js';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {import('../types/options.d.ts').ResolvedOptions} options
|
|
8
|
+
* @returns {void}
|
|
9
|
+
*/
|
|
10
|
+
export function setupWatchers(options) {
|
|
11
|
+
const { server, configFile: svelteConfigFile } = options;
|
|
12
|
+
if (!server) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const { watcher, ws } = server;
|
|
16
|
+
const { root, server: serverConfig } = server.config;
|
|
17
|
+
|
|
18
|
+
/** @type {(filename: string) => void} */
|
|
19
|
+
const triggerViteRestart = (filename) => {
|
|
20
|
+
if (serverConfig.middlewareMode) {
|
|
21
|
+
// in middlewareMode we can't restart the server automatically
|
|
22
|
+
// show the user an overlay instead
|
|
23
|
+
const message =
|
|
24
|
+
'Svelte config change detected, restart your dev process to apply the changes.';
|
|
25
|
+
log.info(message, filename);
|
|
26
|
+
ws.send({
|
|
27
|
+
type: 'error',
|
|
28
|
+
err: { message, stack: '', plugin: 'vite-plugin-svelte', id: filename }
|
|
29
|
+
});
|
|
30
|
+
} else {
|
|
31
|
+
log.info(`svelte config changed: restarting vite server. - file: ${filename}`);
|
|
32
|
+
server.restart();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// collection of watcher listeners by event
|
|
37
|
+
/** @type {Record<string, Function[]>} */
|
|
38
|
+
const listenerCollection = {
|
|
39
|
+
add: [],
|
|
40
|
+
change: [],
|
|
41
|
+
unlink: []
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
if (svelteConfigFile !== false) {
|
|
45
|
+
// configFile false means we ignore the file and external process is responsible
|
|
46
|
+
const possibleSvelteConfigs = knownSvelteConfigNames.map((cfg) => path.join(root, cfg));
|
|
47
|
+
/** @type {(filename: string) => void} */
|
|
48
|
+
const restartOnConfigAdd = (filename) => {
|
|
49
|
+
if (possibleSvelteConfigs.includes(filename)) {
|
|
50
|
+
triggerViteRestart(filename);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/** @type {(filename: string) => void} */
|
|
55
|
+
const restartOnConfigChange = (filename) => {
|
|
56
|
+
if (filename === svelteConfigFile) {
|
|
57
|
+
triggerViteRestart(filename);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
if (svelteConfigFile) {
|
|
62
|
+
listenerCollection.change.push(restartOnConfigChange);
|
|
63
|
+
listenerCollection.unlink.push(restartOnConfigChange);
|
|
64
|
+
} else {
|
|
65
|
+
listenerCollection.add.push(restartOnConfigAdd);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
Object.entries(listenerCollection).forEach(([evt, listeners]) => {
|
|
70
|
+
if (listeners.length > 0) {
|
|
71
|
+
watcher.on(evt, (filename) => listeners.forEach((listener) => listener(filename)));
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* taken from vite utils
|
|
78
|
+
* @param {import('vite').FSWatcher} watcher
|
|
79
|
+
* @param {string | null} file
|
|
80
|
+
* @param {string} root
|
|
81
|
+
* @returns {void}
|
|
82
|
+
*/
|
|
83
|
+
export function ensureWatchedFile(watcher, file, root) {
|
|
84
|
+
if (
|
|
85
|
+
file &&
|
|
86
|
+
// only need to watch if out of root
|
|
87
|
+
!file.startsWith(root + '/') &&
|
|
88
|
+
// some rollup plugins use null bytes for private resolved Ids
|
|
89
|
+
!file.includes('\0') &&
|
|
90
|
+
fs.existsSync(file)
|
|
91
|
+
) {
|
|
92
|
+
// resolve file to normalized system path
|
|
93
|
+
watcher.add(path.resolve(file));
|
|
94
|
+
}
|
|
95
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
declare module '@rsvelte/vite-plugin-svelte' {
|
|
2
|
+
import type { InlineConfig, ResolvedConfig } from 'vite';
|
|
3
|
+
import type { CompileOptions, Warning, PreprocessorGroup } from '@rsvelte/compiler';
|
|
4
|
+
import type { Options as InspectorOptions } from '@sveltejs/vite-plugin-svelte-inspector';
|
|
5
|
+
export type Options = Omit<SvelteConfig, 'vitePlugin'> & PluginOptionsInline;
|
|
6
|
+
|
|
7
|
+
interface PluginOptionsInline extends PluginOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Path to a svelte config file, either absolute or relative to Vite root
|
|
10
|
+
*
|
|
11
|
+
* set to `false` to ignore the svelte config file
|
|
12
|
+
*
|
|
13
|
+
* @see https://vitejs.dev/config/#root
|
|
14
|
+
*/
|
|
15
|
+
configFile?: string | false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface PluginOptions {
|
|
19
|
+
/**
|
|
20
|
+
* A `picomatch` pattern, or array of patterns, which specifies the files the plugin should
|
|
21
|
+
* operate on. By default, all svelte files are included.
|
|
22
|
+
*
|
|
23
|
+
* @see https://github.com/micromatch/picomatch
|
|
24
|
+
*/
|
|
25
|
+
include?: Arrayable<string | RegExp>;
|
|
26
|
+
/**
|
|
27
|
+
* A `picomatch` pattern, or array of patterns, which specifies the files to be ignored by the
|
|
28
|
+
* plugin. By default, no files are ignored.
|
|
29
|
+
*
|
|
30
|
+
* @see https://github.com/micromatch/picomatch
|
|
31
|
+
*/
|
|
32
|
+
exclude?: Arrayable<string | RegExp>;
|
|
33
|
+
/**
|
|
34
|
+
* Emit Svelte styles as virtual CSS files for Vite and other plugins to process
|
|
35
|
+
*
|
|
36
|
+
* @default true
|
|
37
|
+
*/
|
|
38
|
+
emitCss?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Enable or disable Hot Module Replacement.
|
|
41
|
+
* Deprecated, use compilerOptions.hmr instead!
|
|
42
|
+
*
|
|
43
|
+
* @deprecated
|
|
44
|
+
* @default true for development, always false for production
|
|
45
|
+
*/
|
|
46
|
+
hot?: boolean;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Some Vite plugins can contribute additional preprocessors by defining `api.sveltePreprocess`.
|
|
50
|
+
* If you don't want to use them, set this to true to ignore them all or use an array of strings
|
|
51
|
+
* with plugin names to specify which.
|
|
52
|
+
*
|
|
53
|
+
* @default false
|
|
54
|
+
*/
|
|
55
|
+
ignorePluginPreprocessors?: boolean | string[];
|
|
56
|
+
/**
|
|
57
|
+
* vite-plugin-svelte automatically handles excluding svelte libraries and reinclusion of their dependencies
|
|
58
|
+
* in vite.optimizeDeps.
|
|
59
|
+
*
|
|
60
|
+
* `disableDependencyReinclusion: true` disables all reinclusions
|
|
61
|
+
* `disableDependencyReinclusion: ['foo','bar']` disables reinclusions for dependencies of foo and bar
|
|
62
|
+
*
|
|
63
|
+
* This should be used for hybrid packages that contain both node and browser dependencies, eg Routify
|
|
64
|
+
*
|
|
65
|
+
* @default false
|
|
66
|
+
*/
|
|
67
|
+
disableDependencyReinclusion?: boolean | string[];
|
|
68
|
+
/**
|
|
69
|
+
* Enable support for Vite's dependency optimization to prebundle Svelte libraries.
|
|
70
|
+
*
|
|
71
|
+
* To disable prebundling for a specific library, add it to `optimizeDeps.exclude`.
|
|
72
|
+
*
|
|
73
|
+
* @default true for dev, false for build
|
|
74
|
+
*/
|
|
75
|
+
prebundleSvelteLibraries?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* toggle/configure Svelte Inspector
|
|
78
|
+
*
|
|
79
|
+
* @default unset for dev, always false for build
|
|
80
|
+
*/
|
|
81
|
+
inspector?: InspectorOptions | boolean;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* A function to update `compilerOptions` before compilation
|
|
85
|
+
*
|
|
86
|
+
* `data.filename` - The file to be compiled
|
|
87
|
+
* `data.code` - The preprocessed Svelte code
|
|
88
|
+
* `data.compileOptions` - The current compiler options
|
|
89
|
+
*
|
|
90
|
+
* To change part of the compiler options, return an object with the changes you need.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```
|
|
94
|
+
* ({ filename, compileOptions }) => {
|
|
95
|
+
* // Dynamically set runes mode per Svelte file
|
|
96
|
+
* if (forceRunesMode(filename) && !compileOptions.runes) {
|
|
97
|
+
* return { runes: true };
|
|
98
|
+
* }
|
|
99
|
+
* }
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
dynamicCompileOptions?: (data: {
|
|
103
|
+
filename: string;
|
|
104
|
+
code: string;
|
|
105
|
+
compileOptions: Partial<CompileOptions>;
|
|
106
|
+
}) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* These options are considered experimental and breaking changes to them can occur in any release
|
|
110
|
+
*/
|
|
111
|
+
experimental?: ExperimentalOptions;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface SvelteConfig {
|
|
115
|
+
/**
|
|
116
|
+
* A list of file extensions to be compiled by Svelte
|
|
117
|
+
*
|
|
118
|
+
* @default ['.svelte']
|
|
119
|
+
*/
|
|
120
|
+
extensions?: string[];
|
|
121
|
+
/**
|
|
122
|
+
* An array of preprocessors to transform the Svelte source code before compilation
|
|
123
|
+
*
|
|
124
|
+
* @see https://svelte.dev/docs/svelte/svelte-compiler#PreprocessorGroup
|
|
125
|
+
*/
|
|
126
|
+
preprocess?: Arrayable<PreprocessorGroup>;
|
|
127
|
+
/**
|
|
128
|
+
* The options to be passed to the Svelte compiler. A few options are set by default,
|
|
129
|
+
* including `dev` and `css`. However, some options are non-configurable, like
|
|
130
|
+
* `filename`, `format`, `generate`, and `cssHash` (in dev).
|
|
131
|
+
*
|
|
132
|
+
* @see https://svelte.dev/docs/svelte/svelte-compiler#CompileOptions
|
|
133
|
+
*/
|
|
134
|
+
compilerOptions?: Omit<CompileOptions, 'filename' | 'format' | 'generate'>;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Handles warning emitted from the Svelte compiler
|
|
138
|
+
*
|
|
139
|
+
* warnings emitted for files in node_modules are logged at the debug level, to see them run
|
|
140
|
+
* `DEBUG=vite-plugin-svelte:node-modules-onwarn pnpm build`
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```
|
|
144
|
+
* (warning, defaultHandler) => {
|
|
145
|
+
* // ignore some warnings
|
|
146
|
+
* if (!['foo','bar'].includes(warning.code)) {
|
|
147
|
+
* defaultHandler(warning);
|
|
148
|
+
* }
|
|
149
|
+
* }
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
*/
|
|
153
|
+
onwarn?: (warning: Warning, defaultHandler: (warning: Warning) => void) => void;
|
|
154
|
+
/**
|
|
155
|
+
* Options for vite-plugin-svelte
|
|
156
|
+
*/
|
|
157
|
+
vitePlugin?: PluginOptions;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* These options are considered experimental and breaking changes to them can occur in any release
|
|
162
|
+
*/
|
|
163
|
+
interface ExperimentalOptions {
|
|
164
|
+
/**
|
|
165
|
+
* send a websocket message with svelte compiler warnings during dev
|
|
166
|
+
*
|
|
167
|
+
*/
|
|
168
|
+
sendWarningsToBrowser?: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* disable svelte field resolve warnings
|
|
171
|
+
*
|
|
172
|
+
* @default false
|
|
173
|
+
*/
|
|
174
|
+
disableSvelteResolveWarnings?: boolean;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* disable api.sveltePreprocess deprecation warnings
|
|
178
|
+
*
|
|
179
|
+
* @default false
|
|
180
|
+
*/
|
|
181
|
+
disableApiSveltePreprocessWarnings?: boolean;
|
|
182
|
+
|
|
183
|
+
compileModule?: CompileModuleOptions;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
interface CompileModuleOptions {
|
|
187
|
+
/**
|
|
188
|
+
* infix that must be present in filename
|
|
189
|
+
* @default ['.svelte.']
|
|
190
|
+
*/
|
|
191
|
+
infixes?: string[];
|
|
192
|
+
/**
|
|
193
|
+
* module extensions
|
|
194
|
+
* @default ['.ts','.js']
|
|
195
|
+
*/
|
|
196
|
+
extensions?: string[];
|
|
197
|
+
include?: Arrayable<string | RegExp>;
|
|
198
|
+
exclude?: Arrayable<string | RegExp>;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
type Arrayable<T> = T | T[];
|
|
202
|
+
|
|
203
|
+
export interface VitePreprocessOptions {
|
|
204
|
+
/**
|
|
205
|
+
* preprocess script block with vite pipeline.
|
|
206
|
+
* Since svelte5 this is not needed for typescript anymore
|
|
207
|
+
*
|
|
208
|
+
* @default false
|
|
209
|
+
*/
|
|
210
|
+
script?: boolean;
|
|
211
|
+
/**
|
|
212
|
+
* preprocess style blocks with vite pipeline
|
|
213
|
+
*/
|
|
214
|
+
style?: boolean | InlineConfig | ResolvedConfig;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* returns a list of plugins to handle svelte files
|
|
218
|
+
* plugins are named `vite-plugin-svelte:<task>`
|
|
219
|
+
*
|
|
220
|
+
* */
|
|
221
|
+
export function svelte(inlineOptions?: Partial<Options>): import("vite").Plugin[];
|
|
222
|
+
export function vitePreprocess(opts?: VitePreprocessOptions): import("@rsvelte/compiler").PreprocessorGroup;
|
|
223
|
+
export function loadSvelteConfig(viteConfig?: import("vite").UserConfig, inlineOptions?: Partial<Options>): Promise<Partial<SvelteConfig> | undefined>;
|
|
224
|
+
|
|
225
|
+
export {};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
//# sourceMappingURL=index.d.ts.map
|