@void/svelte 0.7.12 → 0.8.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/dist/plugin.d.mts +1 -1
- package/dist/plugin.mjs +66 -57
- package/package.json +3 -3
package/dist/plugin.d.mts
CHANGED
|
@@ -11,6 +11,6 @@ type VoidSvelteOptions = Readonly<{
|
|
|
11
11
|
viewTransitions?: boolean;
|
|
12
12
|
prefetch?: PrefetchConfig;
|
|
13
13
|
}>;
|
|
14
|
-
declare function voidSvelte(options?: VoidSvelteOptions):
|
|
14
|
+
declare function voidSvelte(options?: VoidSvelteOptions): Array<Plugin>;
|
|
15
15
|
//#endregion
|
|
16
16
|
export { VoidSvelteOptions, voidSvelte };
|
package/dist/plugin.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
|
2
|
+
import { generateComponentManifest, resolveEffectiveLayoutChain, resolvePagesDir, resolveStaticPageDataBuildOptions, scanPages } from "void/pages";
|
|
2
3
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
4
|
import { normalizePath } from "vite";
|
|
4
|
-
import { generateComponentManifest, resolveEffectiveLayoutChain, resolveStaticPageDataBuildOptions, scanPages } from "void/pages";
|
|
5
5
|
import { ISLANDS_CLIENT_ENTRY_ID, ISLANDS_RENDERER_ID, computePagesNeedingClientJS, extractCssImports, needsIslandClientBundle, resolveSpecifier, rewriteCssImportForVirtualModule, watchPagesForRescan } from "void/pages-islands-plugin";
|
|
6
6
|
//#region ../../node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs
|
|
7
7
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
@@ -9,42 +9,9 @@ function normalizeWindowsPath(input = "") {
|
|
|
9
9
|
if (!input) return input;
|
|
10
10
|
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
11
11
|
}
|
|
12
|
-
const _UNC_REGEX = /^[/\\]{2}/;
|
|
13
12
|
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
14
13
|
const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
15
14
|
const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
|
|
16
|
-
const normalize = function(path) {
|
|
17
|
-
if (path.length === 0) return ".";
|
|
18
|
-
path = normalizeWindowsPath(path);
|
|
19
|
-
const isUNCPath = path.match(_UNC_REGEX);
|
|
20
|
-
const isPathAbsolute = isAbsolute(path);
|
|
21
|
-
const trailingSeparator = path[path.length - 1] === "/";
|
|
22
|
-
path = normalizeString(path, !isPathAbsolute);
|
|
23
|
-
if (path.length === 0) {
|
|
24
|
-
if (isPathAbsolute) return "/";
|
|
25
|
-
return trailingSeparator ? "./" : ".";
|
|
26
|
-
}
|
|
27
|
-
if (trailingSeparator) path += "/";
|
|
28
|
-
if (_DRIVE_LETTER_RE.test(path)) path += "/";
|
|
29
|
-
if (isUNCPath) {
|
|
30
|
-
if (!isPathAbsolute) return `//./${path}`;
|
|
31
|
-
return `//${path}`;
|
|
32
|
-
}
|
|
33
|
-
return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
|
|
34
|
-
};
|
|
35
|
-
const join = function(...segments) {
|
|
36
|
-
let path = "";
|
|
37
|
-
for (const seg of segments) {
|
|
38
|
-
if (!seg) continue;
|
|
39
|
-
if (path.length > 0) {
|
|
40
|
-
const pathTrailing = path[path.length - 1] === "/";
|
|
41
|
-
const segLeading = seg[0] === "/";
|
|
42
|
-
if (pathTrailing && segLeading) path += seg.slice(1);
|
|
43
|
-
else path += pathTrailing || segLeading ? seg : `/${seg}`;
|
|
44
|
-
} else path += seg;
|
|
45
|
-
}
|
|
46
|
-
return normalize(path);
|
|
47
|
-
};
|
|
48
15
|
function cwd() {
|
|
49
16
|
if (typeof process !== "undefined" && typeof process.cwd === "function") return process.cwd().replace(/\\/g, "/");
|
|
50
17
|
return "/";
|
|
@@ -140,15 +107,31 @@ const COMPONENT_EXTENSIONS = [
|
|
|
140
107
|
".ts",
|
|
141
108
|
".js"
|
|
142
109
|
];
|
|
110
|
+
const ISLAND_IMPORT_RE = /import\s+([$_A-Za-z][$_\w]*)\s+from\s+("[^"]+"|'[^']+')\s+with\s*\{\s*island\s*:\s*("[^"]+"|'[^']+')\s*,?\s*\}/g;
|
|
111
|
+
function findIslandImports(code) {
|
|
112
|
+
const imports = [];
|
|
113
|
+
let match;
|
|
114
|
+
ISLAND_IMPORT_RE.lastIndex = 0;
|
|
115
|
+
while ((match = ISLAND_IMPORT_RE.exec(code)) !== null) {
|
|
116
|
+
const specifierRaw = match[2];
|
|
117
|
+
imports.push({
|
|
118
|
+
statement: match[0],
|
|
119
|
+
importName: match[1],
|
|
120
|
+
specifier: specifierRaw.slice(1, -1),
|
|
121
|
+
hydrate: match[3].slice(1, -1)
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return imports;
|
|
125
|
+
}
|
|
143
126
|
/**
|
|
144
127
|
* Prefix for virtual island wrapper modules. Must NOT use the `\0` prefix
|
|
145
128
|
* because `@sveltejs/vite-plugin-svelte` skips `\0`-prefixed modules in
|
|
146
129
|
* its transform filter.
|
|
147
130
|
*/
|
|
148
131
|
const WRAPPER_PREFIX = "/@void-island-wrap/";
|
|
149
|
-
function islandsPlugin(pagesDir) {
|
|
132
|
+
function islandsPlugin(pagesDir, options) {
|
|
150
133
|
let pageScan = null;
|
|
151
|
-
const root = dirname(pagesDir);
|
|
134
|
+
const root = options?.root ?? dirname(pagesDir);
|
|
152
135
|
const islandManifest = /* @__PURE__ */ new Map();
|
|
153
136
|
const islandCssFiles = /* @__PURE__ */ new Set();
|
|
154
137
|
let isDev = false;
|
|
@@ -173,8 +156,7 @@ function islandsPlugin(pagesDir) {
|
|
|
173
156
|
},
|
|
174
157
|
async buildStart() {
|
|
175
158
|
if (existsSync(pagesDir)) {
|
|
176
|
-
pageScan = await scanPages(root);
|
|
177
|
-
const importAttrRe = /import\s+\w+\s+from\s+("[^"]+"|'[^']+')\s+with\s*\{\s*island\s*:\s*("[^"]+"|'[^']+')\s*\}/g;
|
|
159
|
+
pageScan = await scanPages(root, { pagesDir });
|
|
178
160
|
const filesToScan = [
|
|
179
161
|
...pageScan.pages.map((page) => ({
|
|
180
162
|
filePath: page.componentPath,
|
|
@@ -194,11 +176,9 @@ function islandsPlugin(pagesDir) {
|
|
|
194
176
|
const filePath = resolve(pagesDir, entry.filePath);
|
|
195
177
|
const code = readFileSync(filePath, "utf-8");
|
|
196
178
|
const importerDir = dirname(filePath);
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const spec = importMatch[1].slice(1, -1);
|
|
201
|
-
const strategy = importMatch[2].slice(1, -1);
|
|
179
|
+
for (const islandImport of findIslandImports(code)) {
|
|
180
|
+
const spec = islandImport.specifier;
|
|
181
|
+
const strategy = islandImport.hydrate;
|
|
202
182
|
const absPath = resolveSpecifier(spec, importerDir, COMPONENT_EXTENSIONS);
|
|
203
183
|
if (absPath) {
|
|
204
184
|
const islandId = normalizePath(relative(root, absPath)).replace(/\.[^.]+$/, "");
|
|
@@ -258,16 +238,12 @@ function islandsPlugin(pagesDir) {
|
|
|
258
238
|
filter: { id: /\.island\.svelte$/ },
|
|
259
239
|
handler(code, id) {
|
|
260
240
|
if (/import\s+\{[^}]*\buseForm\b/.test(code)) this.warn(`islands: useForm cannot be imported in island page '${id}'. Use useIslandForm instead.`);
|
|
261
|
-
const importAttrRe = /import\s+(\w+)\s+from\s+("[^"]+"|'[^']+')\s+with\s*\{\s*island\s*:\s*("[^"]+"|'[^']+')\s*\}/g;
|
|
262
241
|
const importerDir = dirname(id);
|
|
263
242
|
let transformed = code;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
const strategyRaw = match[3];
|
|
269
|
-
const spec = specRaw.slice(1, -1);
|
|
270
|
-
const strategy = strategyRaw.slice(1, -1);
|
|
243
|
+
for (const islandImport of findIslandImports(code)) {
|
|
244
|
+
const name = islandImport.importName;
|
|
245
|
+
const spec = islandImport.specifier;
|
|
246
|
+
const strategy = islandImport.hydrate;
|
|
271
247
|
const absPath = resolveSpecifier(spec, importerDir, COMPONENT_EXTENSIONS);
|
|
272
248
|
if (absPath) {
|
|
273
249
|
const islandId = normalizePath(relative(root, absPath)).replace(/\.[^.]+$/, "");
|
|
@@ -280,7 +256,7 @@ function islandsPlugin(pagesDir) {
|
|
|
280
256
|
const islandId = absPath ? normalizePath(relative(root, absPath)).replace(/\.[^.]+$/, "") : spec;
|
|
281
257
|
const wrapperUrl = WRAPPER_PREFIX + encodeURIComponent(islandId) + ".svelte?src=" + encodeURIComponent(absPath || spec) + "&island=" + encodeURIComponent(islandId) + "&hydrate=" + encodeURIComponent(strategy);
|
|
282
258
|
const replacement = `import ${name} from ${JSON.stringify(wrapperUrl)}`;
|
|
283
|
-
transformed = transformed.replace(
|
|
259
|
+
transformed = transformed.replace(islandImport.statement, replacement);
|
|
284
260
|
}
|
|
285
261
|
if (transformed !== code) return {
|
|
286
262
|
code: transformed,
|
|
@@ -459,11 +435,28 @@ function pagesPlugin(pagesDir, options) {
|
|
|
459
435
|
let pageScan = null;
|
|
460
436
|
let isDev = false;
|
|
461
437
|
let viteConfig;
|
|
462
|
-
const root = dirname(pagesDir);
|
|
438
|
+
const root = options?.root ?? dirname(pagesDir);
|
|
439
|
+
const normalizedPagesDir = normalizePath(pagesDir);
|
|
440
|
+
let pendingRescan = null;
|
|
441
|
+
const rescanPages = async () => {
|
|
442
|
+
pageScan = existsSync(pagesDir) ? await scanPages(root, { pagesDir }) : null;
|
|
443
|
+
};
|
|
444
|
+
const runRescan = () => {
|
|
445
|
+
pendingRescan ??= rescanPages().finally(() => {
|
|
446
|
+
pendingRescan = null;
|
|
447
|
+
});
|
|
448
|
+
return pendingRescan;
|
|
449
|
+
};
|
|
450
|
+
const invalidatePageModules = (server) => {
|
|
451
|
+
for (const env of Object.values(server.environments)) for (const id of ["\0" + RENDERER_ID, "\0" + CLIENT_ENTRY_ID]) {
|
|
452
|
+
const mod = env.moduleGraph.getModuleById(id);
|
|
453
|
+
if (mod) env.moduleGraph.invalidateModule(mod);
|
|
454
|
+
}
|
|
455
|
+
};
|
|
463
456
|
return {
|
|
464
457
|
name: "void-svelte:pages",
|
|
465
458
|
async buildStart() {
|
|
466
|
-
|
|
459
|
+
await runRescan();
|
|
467
460
|
},
|
|
468
461
|
resolveId: {
|
|
469
462
|
filter: { id: /^virtual:void-pages-(renderer|client)$/ },
|
|
@@ -473,7 +466,9 @@ function pagesPlugin(pagesDir, options) {
|
|
|
473
466
|
},
|
|
474
467
|
load: {
|
|
475
468
|
filter: { id: /^\0virtual:void-pages-(renderer|client)$/ },
|
|
476
|
-
handler(id) {
|
|
469
|
+
async handler(id) {
|
|
470
|
+
if (isDev && pendingRescan) await pendingRescan;
|
|
471
|
+
if (!pageScan && existsSync(pagesDir)) await runRescan();
|
|
477
472
|
if (id === "\0" + RENDERER_ID) {
|
|
478
473
|
if (!pageScan) return "export function renderPage() { throw new Error('No pages found'); }";
|
|
479
474
|
return generateRendererModule(pageScan, pagesDir, isDev);
|
|
@@ -484,6 +479,18 @@ function pagesPlugin(pagesDir, options) {
|
|
|
484
479
|
}
|
|
485
480
|
}
|
|
486
481
|
},
|
|
482
|
+
configureServer(server) {
|
|
483
|
+
const handlePagesChange = async (path, event) => {
|
|
484
|
+
const normalizedPath = normalizePath(path);
|
|
485
|
+
if (normalizedPath !== normalizedPagesDir && !normalizedPath.startsWith(normalizedPagesDir + "/")) return;
|
|
486
|
+
if (event === "change" && !normalizedPath.endsWith(".md")) return;
|
|
487
|
+
await runRescan();
|
|
488
|
+
invalidatePageModules(server);
|
|
489
|
+
};
|
|
490
|
+
server.watcher.on("add", (path) => handlePagesChange(path, "add"));
|
|
491
|
+
server.watcher.on("change", (path) => handlePagesChange(path, "change"));
|
|
492
|
+
server.watcher.on("unlink", (path) => handlePagesChange(path, "unlink"));
|
|
493
|
+
},
|
|
487
494
|
configResolved(config) {
|
|
488
495
|
viteConfig = config;
|
|
489
496
|
},
|
|
@@ -661,14 +668,16 @@ start();
|
|
|
661
668
|
//#endregion
|
|
662
669
|
//#region src/plugin.ts
|
|
663
670
|
function voidSvelte(options) {
|
|
664
|
-
const
|
|
671
|
+
const root = process.cwd();
|
|
672
|
+
const pagesDir = resolvePagesDir(root);
|
|
665
673
|
return [
|
|
666
674
|
...svelte(options?.svelte),
|
|
667
675
|
pagesPlugin(pagesDir, {
|
|
676
|
+
root,
|
|
668
677
|
viewTransitions: options?.viewTransitions,
|
|
669
678
|
prefetch: options?.prefetch
|
|
670
679
|
}),
|
|
671
|
-
...islandsPlugin(pagesDir)
|
|
680
|
+
...islandsPlugin(pagesDir, { root })
|
|
672
681
|
];
|
|
673
682
|
}
|
|
674
683
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@void/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/voidzero-dev/void.git",
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
"svelte": "^5.55.5",
|
|
45
45
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.1.20",
|
|
46
46
|
"vite-plus": "^0.1.20",
|
|
47
|
-
"void": "0.
|
|
47
|
+
"void": "0.8.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"svelte": "^5.0.0",
|
|
51
51
|
"vite": "^8.0.0",
|
|
52
|
-
"void": "0.
|
|
52
|
+
"void": "0.8.0"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "vp pack",
|