@qwik.dev/router 2.0.0-beta.13 → 2.0.0-beta.14

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.
Files changed (66) hide show
  1. package/lib/adapters/azure-swa/vite/index.mjs +7 -7
  2. package/lib/adapters/bun-server/vite/index.mjs +7 -7
  3. package/lib/adapters/cloud-run/vite/index.mjs +7 -7
  4. package/lib/adapters/cloudflare-pages/vite/index.mjs +8 -8
  5. package/lib/adapters/deno-server/vite/index.mjs +7 -7
  6. package/lib/adapters/netlify-edge/vite/index.mjs +7 -7
  7. package/lib/adapters/node-server/vite/index.mjs +7 -7
  8. package/lib/adapters/shared/vite/index.mjs +8 -8
  9. package/lib/adapters/ssg/vite/index.mjs +7 -8
  10. package/lib/adapters/vercel-edge/vite/index.mjs +7 -7
  11. package/lib/chunks/error-handler.mjs +2 -4
  12. package/lib/chunks/format-error.mjs +6 -6
  13. package/lib/chunks/fs.mjs +6 -27
  14. package/lib/chunks/index.mjs +39 -31
  15. package/lib/chunks/mime-types.mjs +2 -3
  16. package/lib/chunks/routing.qwik.mjs +23 -47
  17. package/lib/chunks/types.qwik.mjs +2 -5
  18. package/lib/index.d.ts +2 -1
  19. package/lib/index.qwik.mjs +48 -68
  20. package/lib/middleware/aws-lambda/index.mjs +4 -5
  21. package/lib/middleware/azure-swa/index.mjs +6 -7
  22. package/lib/middleware/bun/index.mjs +8 -9
  23. package/lib/middleware/cloudflare-pages/index.mjs +5 -6
  24. package/lib/middleware/deno/index.mjs +7 -8
  25. package/lib/middleware/firebase/index.mjs +4 -5
  26. package/lib/middleware/netlify-edge/index.mjs +5 -6
  27. package/lib/middleware/node/index.mjs +15 -11
  28. package/lib/middleware/request-handler/index.d.ts +2 -2
  29. package/lib/middleware/request-handler/index.mjs +64 -79
  30. package/lib/middleware/vercel-edge/index.mjs +5 -6
  31. package/lib/service-worker/index.mjs +2 -3
  32. package/lib/ssg/index.mjs +3 -4
  33. package/lib/vite/index.d.ts +7 -1
  34. package/lib/vite/index.mjs +91 -68
  35. package/package.json +21 -39
  36. package/lib/adapters/azure-swa/vite/index.cjs +0 -61
  37. package/lib/adapters/bun-server/vite/index.cjs +0 -27
  38. package/lib/adapters/cloud-run/vite/index.cjs +0 -24
  39. package/lib/adapters/cloudflare-pages/vite/index.cjs +0 -65
  40. package/lib/adapters/deno-server/vite/index.cjs +0 -39
  41. package/lib/adapters/netlify-edge/vite/index.cjs +0 -88
  42. package/lib/adapters/node-server/vite/index.cjs +0 -27
  43. package/lib/adapters/shared/vite/index.cjs +0 -306
  44. package/lib/adapters/ssg/vite/index.cjs +0 -19
  45. package/lib/adapters/vercel-edge/vite/index.cjs +0 -81
  46. package/lib/chunks/error-handler.cjs +0 -58
  47. package/lib/chunks/format-error.cjs +0 -136
  48. package/lib/chunks/fs.cjs +0 -274
  49. package/lib/chunks/index.cjs +0 -877
  50. package/lib/chunks/mime-types.cjs +0 -52
  51. package/lib/chunks/routing.qwik.cjs +0 -452
  52. package/lib/chunks/types.qwik.cjs +0 -24
  53. package/lib/index.qwik.cjs +0 -1662
  54. package/lib/middleware/aws-lambda/index.cjs +0 -52
  55. package/lib/middleware/azure-swa/index.cjs +0 -92
  56. package/lib/middleware/bun/index.cjs +0 -143
  57. package/lib/middleware/cloudflare-pages/index.cjs +0 -96
  58. package/lib/middleware/deno/index.cjs +0 -130
  59. package/lib/middleware/firebase/index.cjs +0 -33
  60. package/lib/middleware/netlify-edge/index.cjs +0 -71
  61. package/lib/middleware/node/index.cjs +0 -219
  62. package/lib/middleware/request-handler/index.cjs +0 -1488
  63. package/lib/middleware/vercel-edge/index.cjs +0 -98
  64. package/lib/service-worker/index.cjs +0 -5
  65. package/lib/ssg/index.cjs +0 -15
  66. package/lib/vite/index.cjs +0 -2021
@@ -1,2021 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
- // If the importer is in node compatibility mode or this is not an ESM
19
- // file that has been converted to a CommonJS file using a Babel-
20
- // compatible transform (i.e. "__esModule" has not been set), then set
21
- // "default" to the CommonJS "module.exports" for node compatibility.
22
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
- mod
24
- ));
25
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
26
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
27
- const vite = require("vite");
28
- const fs$1 = require("node:fs");
29
- const path = require("node:path");
30
- const fs = require("../chunks/fs.cjs");
31
- const marked = require("marked");
32
- const sourceMap = require("source-map");
33
- const unistUtilVisit = require("unist-util-visit");
34
- const yaml = require("yaml");
35
- const Slugger = require("github-slugger");
36
- const estreeUtilValueToEstree = require("estree-util-value-to-estree");
37
- const hastUtilHeadingRank = require("hast-util-heading-rank");
38
- const hastUtilToString = require("hast-util-to-string");
39
- const refractor = require("refractor");
40
- const tsxLang = require("refractor/lang/tsx.js");
41
- const svgo = require("svgo");
42
- const formatError = require("../chunks/format-error.cjs");
43
- function extendConfig(baseConfigExport, serverConfigExport) {
44
- return async (env) => {
45
- let resolvedBase = await baseConfigExport;
46
- if (typeof resolvedBase === "function") {
47
- resolvedBase = await resolvedBase(env);
48
- }
49
- let resolvedServer = await serverConfigExport;
50
- if (typeof resolvedServer === "function") {
51
- resolvedServer = await resolvedServer(env);
52
- }
53
- return vite.mergeConfig(resolvedBase, resolvedServer);
54
- };
55
- }
56
- const swRegister = 'export default""';
57
- function getSourceFile(fileName) {
58
- const ext = fs.getExtension(fileName);
59
- const extlessName = fs.removeExtension(fileName);
60
- const isPageModule = fs.isPageModuleExt(ext);
61
- const isModule = fs.isModuleExt(ext);
62
- const isMarkdown = fs.isMarkdownExt(ext);
63
- let type = null;
64
- if ((fs.isIndexModule(extlessName) || fs.isErrorName(extlessName)) && (isPageModule || isModule || isMarkdown)) {
65
- type = "route";
66
- } else if (fs.isLayoutModule(extlessName) && (isPageModule || isModule)) {
67
- type = "layout";
68
- } else if (fs.isEntryName(extlessName) && isModule) {
69
- type = "entry";
70
- } else if (fs.isMenuFileName(fileName)) {
71
- type = "menu";
72
- } else if (isModule && fs.isServiceWorkerName(extlessName)) {
73
- type = "service-worker";
74
- }
75
- if (type !== null) {
76
- const sourceFileName = {
77
- type,
78
- extlessName,
79
- ext
80
- };
81
- return sourceFileName;
82
- }
83
- return null;
84
- }
85
- function getMarkdownRelativeUrl(opts, containingFilePath, url, checkFileExists) {
86
- if (typeof url !== "string" || !fs.isSameOriginUrl(url)) {
87
- return url;
88
- }
89
- const querySplit = url.split("?");
90
- const hashSplit = url.split("#");
91
- const strippedUrl = url.split("?")[0].split("#")[0];
92
- const extension = fs.getExtension(strippedUrl);
93
- if (fs.isMarkdownExt(extension)) {
94
- const isAbsolute = strippedUrl.startsWith("/");
95
- const parts = fs.normalizePath(strippedUrl).split("/").filter((p) => p.length > 0);
96
- const filePath = isAbsolute ? path.join(opts.routesDir, ...parts) : path.join(path.dirname(containingFilePath), ...parts);
97
- if (checkFileExists && !fs$1.existsSync(filePath)) {
98
- console.warn(
99
- `
100
- The link "${url}", found within "${containingFilePath}" does not have a matching source file.
101
- `
102
- );
103
- }
104
- const fileName = path.basename(filePath);
105
- const sourceFileName = getSourceFile(fileName);
106
- if (sourceFileName) {
107
- const mdDirPath = path.dirname(filePath);
108
- let pathname = fs.getPathnameFromDirPath(opts, mdDirPath);
109
- if (querySplit.length > 1) {
110
- pathname += "?" + querySplit[1];
111
- } else if (hashSplit.length > 1) {
112
- pathname += "#" + hashSplit[1];
113
- }
114
- return pathname;
115
- }
116
- } else if (extension === "") {
117
- if (url.endsWith("/")) {
118
- if (globalThis.__NO_TRAILING_SLASH__) {
119
- url = url.slice(0, -1);
120
- }
121
- } else if (!globalThis.__NO_TRAILING_SLASH__) {
122
- url += "/";
123
- }
124
- }
125
- return url;
126
- }
127
- function createMenu(opts, filePath) {
128
- const menu = {
129
- pathname: fs.getMenuPathname(opts, filePath),
130
- filePath
131
- };
132
- return menu;
133
- }
134
- function resolveMenu(opts, menuSourceFile) {
135
- return createMenu(opts, menuSourceFile.filePath);
136
- }
137
- async function transformMenu(opts, filePath, content) {
138
- const parsedMenu = parseMenu(opts, filePath, content);
139
- const id = fs.createFileId(opts.routesDir, filePath);
140
- const code = `const ${id} = ${JSON.stringify(parsedMenu, null, 2)};`;
141
- return `${code} export default ${id}`;
142
- }
143
- function parseMenu(opts, filePath, content, checkFileExists = true) {
144
- const tokens = marked.marked.lexer(content, {});
145
- let currentDepth = 0;
146
- const stack = [];
147
- for (const t of tokens) {
148
- if (t.type === "heading") {
149
- const diff = currentDepth - t.depth;
150
- if (diff >= 0) {
151
- stack.length -= diff + 1;
152
- }
153
- if (diff < -1) {
154
- throw new Error(
155
- `Menu hierarchy skipped a level, went from <h${"#".repeat(
156
- currentDepth
157
- )}> to <h${"#".repeat(t.depth)}>, in menu: ${filePath}`
158
- );
159
- }
160
- currentDepth = t.depth;
161
- const parentNode = stack[stack.length - 1];
162
- for (const h2Token of t.tokens || []) {
163
- const lastNode = {
164
- text: ""
165
- };
166
- if (h2Token.type === "text") {
167
- lastNode.text = h2Token.text;
168
- } else if (h2Token.type === "link") {
169
- lastNode.text = h2Token.text;
170
- lastNode.href = getMarkdownRelativeUrl(opts, filePath, h2Token.href, checkFileExists);
171
- } else {
172
- throw new Error(
173
- `Headings can only be a text or link. Received "${h2Token.type}", value "${h2Token.raw}", in menu: ${filePath}`
174
- );
175
- }
176
- if (parentNode) {
177
- parentNode.items = parentNode.items || [];
178
- parentNode.items.push(lastNode);
179
- }
180
- stack.push(lastNode);
181
- }
182
- } else if (t.type === "list") {
183
- const parentNode = stack[stack.length - 1];
184
- parentNode.items = parentNode.items || [];
185
- for (const li of t.items) {
186
- if (li.type === "list_item") {
187
- for (const liToken of li.tokens) {
188
- if (liToken.type === "text") {
189
- for (const liItem of liToken.tokens) {
190
- if (liItem.type === "text") {
191
- parentNode.items.push({ text: liItem.text });
192
- } else if (liItem.type === "link") {
193
- parentNode.items.push({
194
- text: liItem.text,
195
- href: getMarkdownRelativeUrl(opts, filePath, liItem.href, checkFileExists)
196
- });
197
- } else {
198
- throw new Error(
199
- `List items can only be a text or link. Received "${liItem.type}", value "${liItem.raw}", in menu: ${filePath}`
200
- );
201
- }
202
- }
203
- } else if (liToken.type === "link") {
204
- parentNode.items.push({
205
- text: liToken.text,
206
- href: getMarkdownRelativeUrl(opts, filePath, liToken.href, checkFileExists)
207
- });
208
- } else {
209
- throw new Error(
210
- `List items can only be a text or link. Received "${liToken.type}", value "${liToken.raw}", in menu: ${filePath}`
211
- );
212
- }
213
- }
214
- } else {
215
- throw new Error(
216
- `Only list items can be used in lists. Received "${li.type}", value "${li.raw}", in menu: ${filePath}`
217
- );
218
- }
219
- }
220
- } else if (t.type === "space") {
221
- continue;
222
- } else {
223
- throw new Error(
224
- `Menu has a "${t.type}" with the value "${t.raw}". However, only headings and lists can be used in the menu: ${filePath}`
225
- );
226
- }
227
- }
228
- if (stack.length === 0) {
229
- throw new Error(`Menu must start with an h1 in the index: ${filePath}`);
230
- }
231
- return stack[0];
232
- }
233
- function parseRoutePathname(basePathname, pathname) {
234
- if (pathname === basePathname) {
235
- return {
236
- pattern: new RegExp("^" + pathname.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "$"),
237
- routeName: pathname,
238
- paramNames: [],
239
- segments: [[{ content: "", dynamic: false, rest: false }]]
240
- };
241
- }
242
- pathname = pathname.slice(1);
243
- const segments = pathname.split("/");
244
- const paramNames = [];
245
- const pattern = new RegExp(
246
- `^${segments.filter((segment) => segment.length > 0).map((s) => {
247
- const segment = decodeURI(s);
248
- const catchAll = /^\[\.\.\.(\w+)?\]$/.exec(segment);
249
- if (catchAll) {
250
- paramNames.push(catchAll[1]);
251
- return "(?:/(.*))?";
252
- }
253
- return "/" + segment.split(DYNAMIC_SEGMENT).map((content, i) => {
254
- if (i % 2) {
255
- const rg = PARAM_PATTERN.exec(content);
256
- if (rg) {
257
- const [, rest, name] = rg;
258
- paramNames.push(name);
259
- return rest ? "(.*?)" : "([^/]+?)";
260
- }
261
- }
262
- return encodeURI(content).normalize().replace(/%5[Bb]/g, "[").replace(/%5[Dd]/g, "]").replace(/#/g, "%23").replace(/\?/g, "%3F").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
263
- }).join("");
264
- }).join("")}/?$`
265
- // always match with and without a trailing slash
266
- );
267
- return {
268
- pattern,
269
- routeName: pathname,
270
- paramNames,
271
- segments: segments.map((segment) => {
272
- const parts = [];
273
- segment.split(/\[(.+?)\]/).map((content, i) => {
274
- if (content) {
275
- const dynamic = !!(i % 2);
276
- parts.push({
277
- content,
278
- dynamic,
279
- rest: dynamic && content.startsWith("...")
280
- });
281
- }
282
- });
283
- return parts;
284
- })
285
- };
286
- }
287
- const PARAM_PATTERN = /^(\.\.\.)?(\w+)?$/;
288
- const DYNAMIC_SEGMENT = /\[(.+?)\]/;
289
- function routeSortCompare(a, b) {
290
- const maxSegments = Math.max(a.segments.length, b.segments.length);
291
- for (let i = 0; i < maxSegments; i += 1) {
292
- const sa = a.segments[i];
293
- const sb = b.segments[i];
294
- if (!sa) {
295
- return a.pathname.includes("[...") ? 1 : -1;
296
- }
297
- if (!sb) {
298
- return b.pathname.includes("[...") ? -1 : 1;
299
- }
300
- const maxParts = Math.max(sa.length, sb.length);
301
- for (let i2 = 0; i2 < maxParts; i2 += 1) {
302
- const pa = sa[i2];
303
- const pb = sb[i2];
304
- if (pa === void 0) {
305
- return pb.dynamic ? -1 : 1;
306
- }
307
- if (pb === void 0) {
308
- return pa.dynamic ? 1 : -1;
309
- }
310
- if (pa.dynamic !== pb.dynamic) {
311
- return pa.dynamic ? 1 : -1;
312
- }
313
- if (pa.dynamic) {
314
- if (pa.rest !== pb.rest) {
315
- return pa.rest ? 1 : -1;
316
- }
317
- }
318
- }
319
- }
320
- if (a.pathname === b.pathname) {
321
- return a.ext > b.ext ? -1 : 1;
322
- }
323
- return a.pathname < b.pathname ? -1 : 1;
324
- }
325
- function resolveSourceFiles(opts, sourceFiles) {
326
- const layouts = sourceFiles.filter((s) => s.type === "layout").map((s) => resolveLayout(opts, s)).sort((a, b) => {
327
- return a.id < b.id ? -1 : 1;
328
- });
329
- const routes = sourceFiles.filter((s) => s.type === "route").map((s) => resolveRoute(opts, layouts, s)).sort(routeSortCompare);
330
- const entries = sourceFiles.filter((s) => s.type === "entry").map((s) => resolveEntry(opts, s)).sort((a, b) => {
331
- return a.chunkFileName < b.chunkFileName ? -1 : 1;
332
- });
333
- const serviceWorkers = sourceFiles.filter((s) => s.type === "service-worker").map((p) => resolveServiceWorkerEntry(opts, p)).sort((a, b) => {
334
- return a.chunkFileName < b.chunkFileName ? -1 : 1;
335
- });
336
- const menus = sourceFiles.filter((s) => s.type === "menu").map((p) => resolveMenu(opts, p)).sort((a, b) => {
337
- return a.pathname < b.pathname ? -1 : 1;
338
- });
339
- let inc = 0;
340
- const ids = /* @__PURE__ */ new Set();
341
- const uniqueIds = (b) => {
342
- for (const r of b) {
343
- let id = r.id;
344
- while (ids.has(id)) {
345
- id = `${r.id}_${inc++}`;
346
- }
347
- r.id = id;
348
- ids.add(id);
349
- }
350
- };
351
- uniqueIds(layouts);
352
- uniqueIds(routes);
353
- uniqueIds(entries);
354
- uniqueIds(serviceWorkers);
355
- return { layouts, routes, entries, menus, serviceWorkers };
356
- }
357
- function resolveLayout(opts, layoutSourceFile) {
358
- let extlessName = layoutSourceFile.extlessName;
359
- const filePath = layoutSourceFile.filePath;
360
- const dirPath = layoutSourceFile.dirPath;
361
- let layoutName;
362
- let layoutType;
363
- if (extlessName.endsWith(LAYOUT_TOP_SUFFIX)) {
364
- layoutType = "top";
365
- extlessName = extlessName.slice(0, extlessName.length - 1);
366
- } else {
367
- layoutType = "nested";
368
- }
369
- if (extlessName.startsWith(LAYOUT_NAMED_PREFIX)) {
370
- layoutName = extlessName.slice(LAYOUT_NAMED_PREFIX.length);
371
- } else {
372
- layoutName = "";
373
- }
374
- const layout = {
375
- id: fs.createFileId(opts.routesDir, filePath),
376
- filePath,
377
- dirPath,
378
- layoutType,
379
- layoutName
380
- };
381
- return layout;
382
- }
383
- const LAYOUT_ID = "layout";
384
- const LAYOUT_NAMED_PREFIX = LAYOUT_ID + "-";
385
- const LAYOUT_TOP_SUFFIX = "!";
386
- function resolveRoute(opts, appLayouts, sourceFile) {
387
- const filePath = sourceFile.filePath;
388
- const layouts = [];
389
- const routesDir = opts.routesDir;
390
- const { layoutName, layoutStop } = fs.parseRouteIndexName(sourceFile.extlessName);
391
- let pathname = fs.getPathnameFromDirPath(opts, sourceFile.dirPath);
392
- if (sourceFile.extlessName === "404") {
393
- pathname += sourceFile.extlessName + ".html";
394
- }
395
- if (!layoutStop) {
396
- let currentDir = fs.normalizePath(path.dirname(filePath));
397
- let hasFoundNamedLayout = false;
398
- const hasNamedLayout = layoutName !== "";
399
- for (let i = 0; i < 20; i++) {
400
- let layout = void 0;
401
- if (hasNamedLayout && !hasFoundNamedLayout) {
402
- layout = appLayouts.find((l) => l.dirPath === currentDir && l.layoutName === layoutName);
403
- if (layout) {
404
- hasFoundNamedLayout = true;
405
- }
406
- } else {
407
- layout = appLayouts.find((l) => l.dirPath === currentDir && l.layoutName === "");
408
- }
409
- if (layout) {
410
- layouts.push(layout);
411
- if (layout.layoutType === "top") {
412
- break;
413
- }
414
- }
415
- if (currentDir === routesDir) {
416
- break;
417
- }
418
- currentDir = fs.normalizePath(path.dirname(currentDir));
419
- }
420
- }
421
- const buildRoute = {
422
- id: fs.createFileId(opts.routesDir, filePath, "Route"),
423
- filePath,
424
- pathname,
425
- layouts: layouts.reverse(),
426
- ext: sourceFile.ext,
427
- ...parseRoutePathname(opts.basePathname, pathname)
428
- };
429
- return buildRoute;
430
- }
431
- function resolveEntry(opts, sourceFile) {
432
- const pathname = fs.getPathnameFromDirPath(opts, sourceFile.dirPath);
433
- const chunkFileName = pathname.slice(opts.basePathname.length);
434
- const buildEntry = {
435
- id: fs.createFileId(opts.routesDir, sourceFile.filePath, "Route"),
436
- filePath: sourceFile.filePath,
437
- chunkFileName,
438
- ...parseRoutePathname(opts.basePathname, pathname)
439
- };
440
- return buildEntry;
441
- }
442
- function resolveServiceWorkerEntry(opts, sourceFile) {
443
- const dirPathname = fs.getPathnameFromDirPath(opts, sourceFile.dirPath);
444
- const pathname = dirPathname + sourceFile.extlessName + ".js";
445
- const chunkFileName = pathname.slice(opts.basePathname.length);
446
- const buildEntry = {
447
- id: fs.createFileId(opts.routesDir, sourceFile.filePath, "ServiceWorker"),
448
- filePath: sourceFile.filePath,
449
- chunkFileName,
450
- ...parseRoutePathname(opts.basePathname, pathname)
451
- };
452
- return buildEntry;
453
- }
454
- async function walkRoutes(routesDir) {
455
- const sourceFiles = [];
456
- await walkRouteDir(sourceFiles, fs.normalizePath(routesDir), path.basename(routesDir));
457
- return sourceFiles;
458
- }
459
- async function walkRouteDir(sourceFiles, dirPath, dirName) {
460
- const dirItemNames = await fs$1.promises.readdir(dirPath);
461
- await Promise.all(
462
- dirItemNames.map(async (itemName) => {
463
- const itemPath = fs.normalizePath(path.join(dirPath, itemName));
464
- const stat = await fs$1.promises.stat(itemPath);
465
- if (stat.isDirectory()) {
466
- await walkRouteDir(sourceFiles, itemPath, itemName);
467
- } else {
468
- const sourceFileName = getSourceFile(itemName);
469
- if (sourceFileName !== null) {
470
- sourceFiles.push({
471
- ...sourceFileName,
472
- fileName: itemName,
473
- filePath: itemPath,
474
- dirName,
475
- dirPath
476
- });
477
- }
478
- }
479
- })
480
- );
481
- }
482
- async function walkServerPlugins(opts) {
483
- const dirPath = opts.serverPluginsDir;
484
- const dirItemNames = await fs$1.promises.readdir(dirPath);
485
- const sourceFiles = [];
486
- await Promise.all(
487
- dirItemNames.map(async (itemName) => {
488
- const itemPath = fs.normalizePath(path.join(dirPath, itemName));
489
- const ext = fs.getExtension(itemName);
490
- const extlessName = fs.removeExtension(itemName);
491
- if ((fs.isModuleExt(ext) || fs.isPageModuleExt(ext)) && fs.isPluginModule(extlessName)) {
492
- sourceFiles.push({
493
- id: fs.createFileId(opts.serverPluginsDir, itemPath, "Plugin"),
494
- filePath: itemPath,
495
- ext
496
- });
497
- }
498
- })
499
- );
500
- return sourceFiles;
501
- }
502
- async function parseRoutesDir(ctx) {
503
- try {
504
- await updateRoutingContext(ctx);
505
- validateBuild(ctx);
506
- } catch (e) {
507
- fs.addError(ctx, e);
508
- }
509
- for (const d of ctx.diagnostics) {
510
- if (d.type === "error") {
511
- throw new Error(d.message);
512
- } else {
513
- console.warn(d.message);
514
- }
515
- }
516
- }
517
- function updateRoutingContext(ctx) {
518
- ctx.activeBuild || (ctx.activeBuild = _updateRoutingContext(ctx).finally(() => {
519
- ctx.activeBuild = null;
520
- }));
521
- return ctx.activeBuild;
522
- }
523
- async function _updateRoutingContext(ctx) {
524
- const serverPlugins = await walkServerPlugins(ctx.opts);
525
- const sourceFiles = await walkRoutes(ctx.opts.routesDir);
526
- const resolved = resolveSourceFiles(ctx.opts, sourceFiles);
527
- resolved.routes = rewriteRoutes(ctx, resolved.routes);
528
- ctx.serverPlugins = serverPlugins;
529
- ctx.layouts = resolved.layouts;
530
- ctx.routes = resolved.routes;
531
- ctx.entries = resolved.entries;
532
- ctx.serviceWorkers = resolved.serviceWorkers;
533
- ctx.menus = resolved.menus;
534
- }
535
- function rewriteRoutes(ctx, routes) {
536
- if (!ctx.opts.rewriteRoutes) {
537
- return routes;
538
- }
539
- const translatedRoutes = [];
540
- let segmentsToTranslate = ctx.opts.rewriteRoutes.flatMap((rewriteConfig) => {
541
- return Object.keys(rewriteConfig.paths || {});
542
- });
543
- segmentsToTranslate = Array.from(new Set(segmentsToTranslate));
544
- routes.forEach((route) => {
545
- translatedRoutes.push(route);
546
- const currentRouteSegments = route.pathname.split("/");
547
- const foundSegmentToTranslate = currentRouteSegments.some(
548
- (segment) => segmentsToTranslate.includes(segment)
549
- );
550
- if (foundSegmentToTranslate || route.pathname === "/") {
551
- ctx.opts.rewriteRoutes.forEach((config, configIndex) => {
552
- if (route.pathname === "/" && !config.prefix) {
553
- return;
554
- }
555
- const routeToPush = translateRoute(route, config, configIndex);
556
- if (!translatedRoutes.some(
557
- (item) => item.pathname === routeToPush.pathname && item.routeName === routeToPush.routeName
558
- )) {
559
- translatedRoutes.push(routeToPush);
560
- }
561
- });
562
- }
563
- });
564
- return translatedRoutes.sort(routeSortCompare);
565
- }
566
- function translateRoute(route, config, configIndex) {
567
- const replacePath = (part) => (config.paths || {})[part] ?? part;
568
- const pathnamePrefix = config.prefix ? "/" + config.prefix : "";
569
- const routeNamePrefix = config.prefix ? config.prefix + "/" : "";
570
- const idSuffix = config.prefix?.toUpperCase().replace(/-/g, "");
571
- const patternInfix = config.prefix ? [config.prefix] : [];
572
- const splittedPathName = route.pathname.split("/");
573
- const translatedPathParts = splittedPathName.map(replacePath);
574
- const splittedRouteName = route.routeName.split("/");
575
- const translatedRouteParts = splittedRouteName.map(replacePath);
576
- const splittedPattern = route.pattern.toString().split("\\/");
577
- const [translatedPatternFirst, ...translatedPatternOthers] = splittedPattern.map(replacePath);
578
- const translatedPatternParts = [
579
- translatedPatternFirst,
580
- ...patternInfix,
581
- ...translatedPatternOthers
582
- ];
583
- const translatedPatternString = translatedPatternParts.join("\\/");
584
- const translatedRegExp = translatedPatternString.substring(
585
- 1,
586
- route.pathname === "/" ? translatedPatternString.length - 1 : translatedPatternString.length - 2
587
- );
588
- const translatedSegments = route.segments.map(
589
- (segment) => segment.map((item) => ({ ...item, content: replacePath(item.content) }))
590
- );
591
- if (config.prefix) {
592
- translatedSegments.splice(0, 0, [
593
- {
594
- content: config.prefix,
595
- dynamic: false,
596
- rest: false
597
- }
598
- ]);
599
- }
600
- const translatedPath = translatedPathParts.join("/");
601
- const translatedRoute = translatedRouteParts.join("/");
602
- const routeToPush = {
603
- ...route,
604
- id: route.id + (idSuffix || configIndex),
605
- pathname: pathnamePrefix + translatedPath,
606
- routeName: routeNamePrefix + (translatedRoute !== "/" ? translatedRoute : ""),
607
- pattern: new RegExp(translatedRegExp),
608
- segments: translatedSegments
609
- };
610
- return routeToPush;
611
- }
612
- function validateBuild(ctx) {
613
- const pathnames = Array.from(new Set(ctx.routes.map((r) => r.pathname))).sort();
614
- for (const pathname of pathnames) {
615
- const foundRoutes = ctx.routes.filter((r) => r.pathname === pathname);
616
- if (foundRoutes.length > 1) {
617
- fs.addError(
618
- ctx,
619
- `More than one route has been found for pathname "${pathname}". Please narrow it down to only one of these:
620
- ${foundRoutes.map((r) => ` - ${r.filePath}`).join("\n")}`
621
- );
622
- }
623
- }
624
- ctx.layouts.filter((l) => l.layoutType === "top").forEach((l) => {
625
- fs.addWarning(
626
- ctx,
627
- `The "top" layout feature, which is used by "${l.filePath}" has been deprecated and will be removed from future versions. In most cases the "group" layout feature can be used in its place: https://qwik.dev/docs/advanced/routing/`
628
- );
629
- });
630
- }
631
- function createBuildContext(rootDir, viteBasePath, userOpts, target, dynamicImports) {
632
- const ctx = {
633
- rootDir: fs.normalizePath(rootDir),
634
- opts: normalizeOptions(rootDir, viteBasePath, userOpts),
635
- routes: [],
636
- serverPlugins: [],
637
- layouts: [],
638
- entries: [],
639
- serviceWorkers: [],
640
- menus: [],
641
- diagnostics: [],
642
- frontmatter: /* @__PURE__ */ new Map(),
643
- target: target || "ssr",
644
- dynamicImports: target === "client" || !!dynamicImports,
645
- isDirty: true,
646
- activeBuild: null
647
- };
648
- return ctx;
649
- }
650
- function resetBuildContext(ctx) {
651
- if (ctx) {
652
- ctx.routes.length = 0;
653
- ctx.layouts.length = 0;
654
- ctx.entries.length = 0;
655
- ctx.menus.length = 0;
656
- ctx.diagnostics.length = 0;
657
- ctx.frontmatter.clear();
658
- ctx.isDirty = true;
659
- }
660
- }
661
- function normalizeOptions(rootDir, viteBasePath, userOpts) {
662
- if (!(viteBasePath.startsWith("/") && viteBasePath.endsWith("/"))) {
663
- console.error(
664
- `warning: vite's config.base must begin and end with /. This will be an error in v2. If you have a valid use case, please open an issue.`
665
- );
666
- if (!viteBasePath.endsWith("/")) {
667
- viteBasePath += "/";
668
- }
669
- }
670
- const opts = { ...userOpts };
671
- if (typeof opts.routesDir !== "string") {
672
- opts.routesDir = path.resolve(rootDir, "src", "routes");
673
- } else if (!path.isAbsolute(opts.routesDir)) {
674
- opts.routesDir = path.resolve(rootDir, opts.routesDir);
675
- }
676
- opts.routesDir = fs.normalizePath(opts.routesDir);
677
- if (typeof opts.serverPluginsDir !== "string") {
678
- opts.serverPluginsDir = opts.routesDir;
679
- } else if (!path.isAbsolute(opts.serverPluginsDir)) {
680
- opts.serverPluginsDir = path.resolve(rootDir, opts.serverPluginsDir);
681
- }
682
- opts.serverPluginsDir = fs.normalizePath(opts.serverPluginsDir);
683
- if (typeof opts.baseUrl === "string") {
684
- opts.basePathname = opts.baseUrl;
685
- }
686
- if (typeof opts.basePathname !== "string") {
687
- opts.basePathname = viteBasePath;
688
- }
689
- if (!opts.basePathname.endsWith("/")) {
690
- console.error(
691
- `Warning: qwik-router plugin basePathname must end with /. This will be an error in v2`
692
- );
693
- opts.basePathname += "/";
694
- }
695
- const url = new URL(opts.basePathname, "https://qwik.dev/");
696
- opts.basePathname = url.pathname;
697
- opts.mdx = opts.mdx || {};
698
- opts.platform = opts.platform || {};
699
- return opts;
700
- }
701
- function parseFrontmatter(ctx) {
702
- return (mdast, vfile) => {
703
- const attrs = {};
704
- unistUtilVisit.visit(mdast, "yaml", (node) => {
705
- const parsedAttrs = parseFrontmatterAttrs(node.value);
706
- for (const k in parsedAttrs) {
707
- attrs[k] = parsedAttrs[k];
708
- }
709
- });
710
- if (Object.keys(attrs).length > 0) {
711
- ctx.frontmatter.set(fs.normalizePath(vfile.path), attrs);
712
- }
713
- };
714
- }
715
- function parseFrontmatterAttrs(yaml$1) {
716
- if (typeof yaml$1 === "string") {
717
- yaml$1 = yaml$1.trim();
718
- if (yaml$1 !== "") {
719
- return yaml.parse(yaml$1);
720
- }
721
- }
722
- return null;
723
- }
724
- const metaNames = {
725
- author: true,
726
- creator: true,
727
- "color-scheme": true,
728
- description: true,
729
- generator: true,
730
- keywords: true,
731
- publisher: true,
732
- referrer: true,
733
- robots: true,
734
- "theme-color": true,
735
- viewport: true
736
- };
737
- function frontmatterAttrsToDocumentHead(attrs) {
738
- if (attrs != null && typeof attrs === "object") {
739
- const attrNames = Object.keys(attrs);
740
- if (attrNames.length > 0) {
741
- const head = {
742
- title: "",
743
- meta: [],
744
- styles: [],
745
- links: [],
746
- scripts: [],
747
- frontmatter: {}
748
- };
749
- for (const attrName of attrNames) {
750
- const attrValue = attrs[attrName];
751
- if (attrValue != null) {
752
- if (attrName === "title") {
753
- head.title = attrValue.toString();
754
- head.title = head.title.replace(/\\@/g, "@");
755
- } else if (attrName === "og" || attrName === "opengraph") {
756
- if (typeof attrValue === "object") {
757
- for (const opengraph of Array.isArray(attrValue) ? attrValue : [attrValue]) {
758
- if (opengraph != null && typeof opengraph === "object" && !Array.isArray(opengraph)) {
759
- for (const [property, content] of Object.entries(opengraph)) {
760
- if ((property === "title" || property === "description") && content === true) {
761
- if (attrNames.includes(property)) {
762
- head.meta.push({
763
- property: `og:${property}`,
764
- content: attrs[property]?.toString()
765
- });
766
- }
767
- } else {
768
- head.meta.push({
769
- property: `og:${property}`,
770
- content: content?.toString()
771
- });
772
- }
773
- }
774
- }
775
- }
776
- }
777
- } else if (metaNames[attrName]) {
778
- head.meta.push({
779
- name: attrName,
780
- content: attrValue.toString()
781
- });
782
- } else {
783
- head.frontmatter[attrName] = attrValue;
784
- }
785
- }
786
- }
787
- return head;
788
- }
789
- }
790
- return null;
791
- }
792
- function rehypeSlug() {
793
- return (ast) => {
794
- const mdast = ast;
795
- const slugs = new Slugger();
796
- unistUtilVisit.visit(mdast, "element", (node) => {
797
- const level = hastUtilHeadingRank.headingRank(node);
798
- if (level && node.properties) {
799
- const text = hastUtilToString.toString(node);
800
- if (!hasProperty(node, "id")) {
801
- node.properties.id = slugs.slug(text);
802
- }
803
- }
804
- });
805
- };
806
- }
807
- function rehypePage(ctx) {
808
- return (ast, vfile) => {
809
- const mdast = ast;
810
- const sourcePath = fs.normalizePath(vfile.path);
811
- updateContentLinks(mdast, ctx.opts, sourcePath);
812
- exportFrontmatter(ctx, mdast, sourcePath);
813
- exportContentHead(ctx, mdast, sourcePath);
814
- exportContentHeadings(mdast);
815
- };
816
- }
817
- function renameClassname() {
818
- return (ast) => {
819
- const mdast = ast;
820
- unistUtilVisit.visit(mdast, "element", (node) => {
821
- if (node.properties) {
822
- if (node.properties.className) {
823
- node.properties.class = node.properties.className;
824
- node.properties.className = void 0;
825
- }
826
- }
827
- });
828
- };
829
- }
830
- function wrapTableWithDiv() {
831
- return (ast) => {
832
- const mdast = ast;
833
- unistUtilVisit.visit(mdast, "element", (node) => {
834
- if (node.tagName === "table" && !node.done) {
835
- const table = { ...node };
836
- table.done = true;
837
- node.tagName = "div";
838
- node.properties = { className: "table-wrapper" };
839
- node.children = [table];
840
- }
841
- });
842
- };
843
- }
844
- function updateContentLinks(mdast, opts, sourcePath) {
845
- unistUtilVisit.visit(mdast, "element", (node) => {
846
- const tagName = node && node.type === "element" && node.tagName.toLowerCase();
847
- if (tagName === "a") {
848
- const href = (node.properties && node.properties.href || "").trim();
849
- if (fs.isSameOriginUrl(href)) {
850
- const ext = fs.getExtension(href);
851
- if (fs.isMarkdownExt(ext)) {
852
- node.properties.href = getMarkdownRelativeUrl(
853
- opts,
854
- sourcePath,
855
- node.properties.href,
856
- true
857
- );
858
- }
859
- }
860
- }
861
- });
862
- }
863
- function exportFrontmatter(ctx, mdast, sourcePath) {
864
- const attrs = ctx.frontmatter.get(sourcePath);
865
- createExport(mdast, "frontmatter", attrs);
866
- }
867
- function exportContentHead(ctx, mdast, sourcePath) {
868
- const attrs = ctx.frontmatter.get(sourcePath);
869
- const head = frontmatterAttrsToDocumentHead(attrs);
870
- if (head) {
871
- createExport(mdast, "head", head);
872
- }
873
- }
874
- function exportContentHeadings(mdast) {
875
- const headings = [];
876
- unistUtilVisit.visit(mdast, "element", (node) => {
877
- const level = hastUtilHeadingRank.headingRank(node);
878
- if (level && node.properties) {
879
- if (hasProperty(node, "id")) {
880
- const text = hastUtilToString.toString(node);
881
- headings.push({
882
- text,
883
- id: node.properties.id,
884
- level
885
- });
886
- }
887
- }
888
- });
889
- if (headings.length > 0) {
890
- createExport(mdast, "headings", headings);
891
- }
892
- }
893
- function createExport(mdast, identifierName, val) {
894
- const mdxjsEsm = {
895
- type: "mdxjsEsm",
896
- value: "",
897
- data: {
898
- estree: {
899
- type: "Program",
900
- sourceType: "module",
901
- body: [
902
- {
903
- type: "ExportNamedDeclaration",
904
- source: null,
905
- specifiers: [],
906
- attributes: [],
907
- declaration: {
908
- type: "VariableDeclaration",
909
- kind: "const",
910
- declarations: [
911
- {
912
- type: "VariableDeclarator",
913
- id: { type: "Identifier", name: identifierName },
914
- init: estreeUtilValueToEstree.valueToEstree(val)
915
- }
916
- ]
917
- }
918
- }
919
- ]
920
- }
921
- }
922
- };
923
- mdast.children.unshift(mdxjsEsm);
924
- }
925
- const own = {}.hasOwnProperty;
926
- function hasProperty(node, propName) {
927
- const value = node && typeof node === "object" && node.type === "element" && node.properties && own.call(node.properties, propName) && node.properties[propName];
928
- return value != null && value !== false;
929
- }
930
- function rehypeSyntaxHighlight() {
931
- refractor.refractor.register(tsxLang);
932
- return async (ast) => {
933
- unistUtilVisit.visit(ast, "element", (node, _index, parent) => {
934
- if (!parent || parent.tagName !== "pre" || node.tagName !== "code" || !Array.isArray(node.properties.className)) {
935
- return;
936
- }
937
- for (let i = 0; i < node.properties.className.length; i++) {
938
- const className = node.properties.className[i];
939
- const lang = getLanguage(className);
940
- if (lang && refractor.refractor.registered(lang)) {
941
- node.properties.className[i] = "language-" + lang;
942
- syntaxHighlight(node, lang);
943
- return;
944
- }
945
- }
946
- });
947
- };
948
- }
949
- function syntaxHighlight(node, lang) {
950
- const code = hastUtilToString.toString(node);
951
- const result = refractor.refractor.highlight(code, lang);
952
- if (result && Array.isArray(node.children)) {
953
- node.children = result.children;
954
- }
955
- }
956
- function getLanguage(className) {
957
- if (typeof className === "string") {
958
- className = className.toLowerCase();
959
- if (className.startsWith("language-")) {
960
- return className.slice(9);
961
- }
962
- }
963
- return null;
964
- }
965
- async function createMdxTransformer(ctx) {
966
- const { compile } = await import("@mdx-js/mdx");
967
- const { default: remarkFrontmatter } = await import("remark-frontmatter");
968
- const { default: remarkGfm } = await import("remark-gfm");
969
- const { default: rehypeAutolinkHeadings } = await import("rehype-autolink-headings");
970
- const { VFile } = await import("vfile");
971
- const userMdxOpts = ctx.opts.mdx;
972
- const userRemarkPlugins = userMdxOpts.remarkPlugins || [];
973
- const userRehypePlugins = userMdxOpts.rehypePlugins || [];
974
- const coreMdxPlugins = ctx.opts.mdxPlugins;
975
- const coreRemarkPlugins = [];
976
- if (typeof coreMdxPlugins?.remarkGfm === "undefined" || coreMdxPlugins.remarkGfm) {
977
- coreRemarkPlugins.push(remarkGfm);
978
- }
979
- const coreRehypePlugins = [];
980
- if (typeof coreMdxPlugins?.rehypeSyntaxHighlight === "undefined" || coreMdxPlugins.rehypeSyntaxHighlight) {
981
- coreRehypePlugins.push(rehypeSyntaxHighlight);
982
- }
983
- if (typeof coreMdxPlugins?.rehypeAutolinkHeadings === "undefined" || coreMdxPlugins.rehypeAutolinkHeadings) {
984
- coreRehypePlugins.push(rehypeAutolinkHeadings);
985
- }
986
- const options = {
987
- SourceMapGenerator: sourceMap.SourceMapGenerator,
988
- jsxImportSource: "@qwik.dev/core",
989
- ...userMdxOpts,
990
- elementAttributeNameCase: "html",
991
- remarkPlugins: [
992
- ...userRemarkPlugins,
993
- ...coreRemarkPlugins,
994
- remarkFrontmatter,
995
- [parseFrontmatter, ctx]
996
- ],
997
- rehypePlugins: [
998
- rehypeSlug,
999
- ...userRehypePlugins,
1000
- ...coreRehypePlugins,
1001
- [rehypePage, ctx],
1002
- renameClassname,
1003
- wrapTableWithDiv
1004
- ]
1005
- };
1006
- return async function(code, id) {
1007
- const ext = fs.getExtension(id);
1008
- if ([".mdx", ".md", ".markdown"].includes(ext)) {
1009
- const file = new VFile({ value: code, path: id });
1010
- const compiled = await compile(file, options);
1011
- const output = String(compiled.value);
1012
- const addImport = `import { jsx } from '@qwik.dev/core';
1013
- `;
1014
- const newDefault = `
1015
- function _missingMdxReference(id, component, place) {
1016
- throw new Error("${id}: Expected " + (component ? "component" : "object") + " \`" + id + "\` to be defined: you likely forgot to import, pass, or provide it." + (place ? "\\nIt’s referenced in your code at \`" + place + "\`" : ""));
1017
- }
1018
- const WrappedMdxContent = () => {
1019
- const content = _createMdxContent({});
1020
- return typeof MDXLayout === 'function' ? jsx(MDXLayout, {children: content}) : content;
1021
- };
1022
- export default WrappedMdxContent;
1023
- `;
1024
- const exportIndex = output.lastIndexOf("export default ");
1025
- if (exportIndex === -1) {
1026
- throw new Error("Could not find default export in mdx output");
1027
- }
1028
- const wrappedOutput = addImport + output.slice(0, exportIndex) + newDefault;
1029
- return {
1030
- code: wrappedOutput,
1031
- map: compiled.map
1032
- };
1033
- }
1034
- };
1035
- }
1036
- function createEntries(ctx, c) {
1037
- const isClient = ctx.target === "client";
1038
- const entries = [...ctx.entries, ...ctx.serviceWorkers];
1039
- if (isClient && entries.length > 0) {
1040
- c.push(`
1041
- /** Qwik Router Entries Entry */`);
1042
- c.push(`export const e = () => import("@qwik-router-entries");
1043
- `);
1044
- }
1045
- }
1046
- function generateQwikRouterEntries(ctx) {
1047
- const c = [];
1048
- const entries = [...ctx.entries, ...ctx.serviceWorkers];
1049
- c.push(`
1050
- /** Qwik Router Entries (${entries.length}) */`);
1051
- for (let i = 0; i < entries.length; i++) {
1052
- const entry = entries[i];
1053
- c.push(`export const ${entry.id} = () => import(${JSON.stringify(entry.filePath)});`);
1054
- }
1055
- return c.join("\n") + "\n";
1056
- }
1057
- function getImportPath(importPath) {
1058
- const lowerCasePath = importPath.toLowerCase();
1059
- if (lowerCasePath.endsWith(".tsx") || lowerCasePath.endsWith(".jsx")) {
1060
- return importPath.slice(0, importPath.length - 4);
1061
- }
1062
- if (lowerCasePath.endsWith(".ts")) {
1063
- return importPath.slice(0, importPath.length - 3);
1064
- }
1065
- return importPath;
1066
- }
1067
- function createMenus(ctx, c, esmImports, isSSR) {
1068
- c.push(`
1069
- /** Qwik Router Menus (${ctx.menus.length}) */`);
1070
- c.push(`export const menus = [`);
1071
- const dynamicImports = !isSSR;
1072
- const routesDir = ctx.opts.routesDir;
1073
- for (const m of ctx.menus) {
1074
- const importPath = JSON.stringify(getImportPath(m.filePath));
1075
- if (dynamicImports) {
1076
- c.push(` [${JSON.stringify(m.pathname)}, ()=>import(${importPath})],`);
1077
- } else {
1078
- const id = fs.createFileId(routesDir, m.filePath);
1079
- esmImports.push(`import * as ${id} from ${importPath};`);
1080
- c.push(` [${JSON.stringify(m.pathname)}, ()=>${id}],`);
1081
- }
1082
- }
1083
- c.push(`];`);
1084
- }
1085
- function createRoutes(ctx, qwikPlugin, c, esmImports, isSSR) {
1086
- const includeEndpoints = isSSR;
1087
- const dynamicImports = ctx.dynamicImports;
1088
- if (ctx.layouts.length > 0) {
1089
- c.push(`
1090
- /** Qwik Router Layouts (${ctx.layouts.length}) */`);
1091
- for (const layout of ctx.layouts) {
1092
- const importPath = JSON.stringify(getImportPath(layout.filePath));
1093
- if (dynamicImports) {
1094
- c.push(`const ${layout.id} = ()=>import(${importPath});`);
1095
- } else {
1096
- esmImports.push(`import * as ${layout.id}_ from ${importPath};`);
1097
- c.push(`const ${layout.id} = ()=>${layout.id}_;`);
1098
- }
1099
- }
1100
- }
1101
- c.push(`
1102
- /** Qwik Router Routes (${ctx.routes.length}) */`);
1103
- c.push(`export const routes = [`);
1104
- for (const route of ctx.routes) {
1105
- const layouts = [];
1106
- if (fs.isPageExt(route.ext)) {
1107
- for (const layout of route.layouts) {
1108
- layouts.push(layout.id);
1109
- }
1110
- const importPath = getImportPath(route.filePath);
1111
- if (dynamicImports) {
1112
- layouts.push(`()=>import(${JSON.stringify(importPath)})`);
1113
- } else {
1114
- esmImports.push(`import * as ${route.id} from ${JSON.stringify(importPath)};`);
1115
- layouts.push(`()=>${route.id}`);
1116
- }
1117
- } else if (includeEndpoints && fs.isModuleExt(route.ext)) {
1118
- const importPath = getImportPath(route.filePath);
1119
- esmImports.push(`import * as ${route.id} from ${JSON.stringify(importPath)};`);
1120
- for (const layout of route.layouts) {
1121
- layouts.push(layout.id);
1122
- }
1123
- layouts.push(`()=>${route.id}`);
1124
- }
1125
- if (layouts.length > 0) {
1126
- c.push(` ${createRouteData(qwikPlugin, route, layouts, isSSR)},`);
1127
- }
1128
- }
1129
- c.push(`];`);
1130
- }
1131
- function createRouteData(qwikPlugin, r, layouts, isSsr) {
1132
- const routeName = JSON.stringify(r.routeName);
1133
- const moduleLayouts = `[ ${layouts.join(", ")} ]`;
1134
- if (isSsr) {
1135
- const originalPathname = JSON.stringify(r.pathname);
1136
- const clientBundleNames = JSON.stringify(getClientRouteBundleNames(qwikPlugin, r));
1137
- return `[ ${routeName}, ${moduleLayouts}, ${originalPathname}, ${clientBundleNames} ]`;
1138
- }
1139
- return `[ ${routeName}, ${moduleLayouts} ]`;
1140
- }
1141
- function getClientRouteBundleNames(qwikPlugin, r) {
1142
- const bundlesNames = [];
1143
- const manifest = qwikPlugin.api.getManifest();
1144
- if (manifest) {
1145
- const manifestBundleNames = Object.keys(manifest.bundles);
1146
- const addRouteFile = (filePath) => {
1147
- filePath = fs.removeExtension(filePath);
1148
- for (const bundleName of manifestBundleNames) {
1149
- const bundle = manifest.bundles[bundleName];
1150
- if (bundle.origins) {
1151
- for (const bundleOrigin of bundle.origins) {
1152
- const originPath = fs.removeExtension(bundleOrigin);
1153
- if (filePath.endsWith(originPath)) {
1154
- if (!bundlesNames.includes(bundleName)) {
1155
- bundlesNames.push(bundleName);
1156
- }
1157
- }
1158
- }
1159
- }
1160
- }
1161
- };
1162
- for (const layout of r.layouts) {
1163
- addRouteFile(layout.filePath);
1164
- }
1165
- addRouteFile(r.filePath);
1166
- }
1167
- return bundlesNames;
1168
- }
1169
- function createServerPlugins(ctx, _qwikPlugin, c, esmImports, isSSR) {
1170
- c.push(`
1171
- /** Qwik Router ServerPlugins (${ctx.serverPlugins.length}) */`);
1172
- c.push(`export const serverPlugins = [`);
1173
- if (isSSR) {
1174
- for (const file of ctx.serverPlugins) {
1175
- const importPath = JSON.stringify(getImportPath(file.filePath));
1176
- esmImports.push(`import * as ${file.id} from ${importPath};`);
1177
- }
1178
- for (const file of ctx.serverPlugins) {
1179
- c.push(` ${file.id},`);
1180
- }
1181
- }
1182
- c.push(`];`);
1183
- }
1184
- function generateQwikRouterConfig(ctx, qwikPlugin, isSSR) {
1185
- const esmImports = [];
1186
- const c = [];
1187
- c.push(`
1188
- /** Qwik Router Config */`);
1189
- c.push(`
1190
- import { isDev } from '@qwik.dev/core/build';`);
1191
- createServerPlugins(ctx, qwikPlugin, c, esmImports, isSSR);
1192
- createRoutes(ctx, qwikPlugin, c, esmImports, isSSR);
1193
- createMenus(ctx, c, esmImports, isSSR);
1194
- createEntries(ctx, c);
1195
- c.push(`export const trailingSlash = ${JSON.stringify(!globalThis.__NO_TRAILING_SLASH__)};`);
1196
- c.push(`export const basePathname = ${JSON.stringify(ctx.opts.basePathname)};`);
1197
- c.push(`export const cacheModules = !isDev;`);
1198
- c.push(
1199
- `export default { routes, serverPlugins, menus, trailingSlash, basePathname, cacheModules };`
1200
- );
1201
- return esmImports.join("\n") + c.join("\n");
1202
- }
1203
- function generateServiceWorkerRegister(ctx, swRegister2) {
1204
- let swReg;
1205
- let swUrl = "/service-worker.js";
1206
- if (ctx.serviceWorkers.length === 0) {
1207
- swReg = SW_UNREGISTER;
1208
- } else {
1209
- swReg = swRegister2;
1210
- const sw = ctx.serviceWorkers.sort(
1211
- (a, b) => a.chunkFileName.length < b.chunkFileName.length ? -1 : 1
1212
- )[0];
1213
- swUrl = ctx.opts.basePathname + sw.chunkFileName;
1214
- }
1215
- swReg = swReg.replace("__url", swUrl);
1216
- return `export default ${JSON.stringify(swReg)};`;
1217
- }
1218
- const SW_UNREGISTER = `
1219
- "serviceWorker"in navigator&&navigator.serviceWorker.getRegistrations().then(r=>{for(const e of r){const c='__url'.split("/").pop();e.active?.scriptURL.endsWith(c||"service-worker.js")&&e.unregister().catch(console.error)}}),"caches"in window&&caches.keys().then(r=>{const e=r.find(c=>c.startsWith("QwikBuild"));e&&caches.delete(e).catch(console.error)}).catch(console.error)
1220
- `;
1221
- function getRouteImports(routes, manifest) {
1222
- const result = {};
1223
- routes.forEach((route) => {
1224
- const routePath = fs.removeExtension(route.filePath);
1225
- const layoutPaths = route.layouts ? route.layouts.map((layout) => fs.removeExtension(layout.filePath)) : [];
1226
- const routeAndLayoutPaths = [routePath, ...layoutPaths];
1227
- const bundles = [];
1228
- for (const [bundleName, bundle] of Object.entries(manifest.bundles)) {
1229
- if (isBundlePartOfRoute(bundle, routeAndLayoutPaths)) {
1230
- bundles.push(bundleName);
1231
- }
1232
- }
1233
- if (bundles.length > 0) {
1234
- result[route.routeName] = { dynamicImports: bundles };
1235
- }
1236
- });
1237
- for (const bundleName of Object.keys(manifest.bundles)) {
1238
- const bundle = manifest.bundles[bundleName];
1239
- if (bundle.origins?.some((s) => s.endsWith(QWIK_ROUTER_CONFIG_ID))) {
1240
- result[bundleName] = {
1241
- ...bundle,
1242
- dynamicImports: bundle.dynamicImports?.filter(
1243
- (d) => manifest.bundles[d].origins?.some((s) => s.endsWith("menu.md"))
1244
- )
1245
- };
1246
- break;
1247
- }
1248
- }
1249
- return result;
1250
- }
1251
- function isBundlePartOfRoute(bundle, routeAndLayoutPaths) {
1252
- if (!bundle.origins) {
1253
- return false;
1254
- }
1255
- for (const bundleOrigin of bundle.origins) {
1256
- const originPath = fs.removeExtension(bundleOrigin);
1257
- return routeAndLayoutPaths.some((path2) => path2.endsWith(originPath));
1258
- }
1259
- }
1260
- function imagePlugin(userOpts) {
1261
- const supportedExtensions = [".jpg", ".jpeg", ".png", ".webp", ".gif", ".avif", ".tiff"];
1262
- return [
1263
- import("vite-imagetools").then(
1264
- ({ imagetools }) => imagetools({
1265
- exclude: [],
1266
- extendOutputFormats(builtins) {
1267
- const jsx = () => (metadatas) => {
1268
- const srcSet = metadatas.map((meta) => `${meta.src} ${meta.width}w`).join(", ");
1269
- let largestImage;
1270
- let largestImageSize = 0;
1271
- for (let i = 0; i < metadatas.length; i++) {
1272
- const m = metadatas[i];
1273
- if (m.width > largestImageSize) {
1274
- largestImage = m;
1275
- largestImageSize = m.width;
1276
- }
1277
- }
1278
- return {
1279
- srcSet,
1280
- width: largestImage === null || largestImage === void 0 ? void 0 : largestImage.width,
1281
- height: largestImage === null || largestImage === void 0 ? void 0 : largestImage.height
1282
- };
1283
- };
1284
- return {
1285
- ...builtins,
1286
- jsx
1287
- };
1288
- },
1289
- defaultDirectives: (url) => {
1290
- if (url.searchParams.has("jsx")) {
1291
- const { jsx: _, ...params } = Object.fromEntries(url.searchParams.entries());
1292
- return new URLSearchParams({
1293
- format: "webp",
1294
- quality: "75",
1295
- w: "200;400;600;800;1200",
1296
- withoutEnlargement: "",
1297
- ...userOpts?.imageOptimization?.jsxDirectives,
1298
- ...params,
1299
- as: "jsx"
1300
- });
1301
- }
1302
- return new URLSearchParams();
1303
- }
1304
- })
1305
- ).catch((err) => {
1306
- console.error("Error loading vite-imagetools, image imports are not available", err);
1307
- return null;
1308
- }),
1309
- {
1310
- name: "qwik-router-image-jsx",
1311
- load: {
1312
- order: "pre",
1313
- handler: async (id) => {
1314
- const { params, pathId } = formatError.parseId(id);
1315
- const extension = path.extname(pathId).toLowerCase();
1316
- if (extension === ".svg" && params.has("jsx")) {
1317
- const code = await fs$1.promises.readFile(pathId, "utf-8");
1318
- return {
1319
- code,
1320
- moduleSideEffects: false
1321
- };
1322
- }
1323
- }
1324
- },
1325
- transform(code, id) {
1326
- id = id.toLowerCase();
1327
- const { params, pathId } = formatError.parseId(id);
1328
- if (params.has("jsx")) {
1329
- const extension = path.extname(pathId).toLowerCase();
1330
- if (supportedExtensions.includes(extension)) {
1331
- if (!code.includes("srcSet")) {
1332
- this.error(`Image '${id}' could not be optimized to JSX`);
1333
- }
1334
- const index = code.indexOf("export default");
1335
- return {
1336
- code: code.slice(0, index) + `
1337
- import { _jsxSorted } from '@qwik.dev/core';
1338
- const PROPS = {srcSet, width, height};
1339
- export default function (props, key, _, dev) {
1340
- return _jsxSorted('img', {...{decoding: 'async', loading: 'lazy'}, ...props}, PROPS, undefined, 3, key, dev);
1341
- }`,
1342
- map: null
1343
- };
1344
- } else if (extension === ".svg") {
1345
- const { svgAttributes } = optimizeSvg({ code, path: pathId }, userOpts);
1346
- return {
1347
- code: `
1348
- import { _jsxSorted } from '@qwik.dev/core';
1349
- const PROPS = ${JSON.stringify(svgAttributes)};
1350
- export default function (props, key, _, dev) {
1351
- return _jsxSorted('svg', props, PROPS, undefined, 3, key, dev);
1352
- }`,
1353
- map: null
1354
- };
1355
- }
1356
- }
1357
- return null;
1358
- }
1359
- }
1360
- ];
1361
- }
1362
- function optimizeSvg({ code, path: path2 }, userOpts) {
1363
- const svgAttributes = {};
1364
- const prefixIdsConfiguration = userOpts?.imageOptimization?.svgo?.prefixIds;
1365
- const maybePrefixIdsPlugin = prefixIdsConfiguration !== false ? [{ name: "prefixIds", params: prefixIdsConfiguration }] : [];
1366
- const userPlugins = userOpts?.imageOptimization?.svgo?.plugins?.filter((plugin) => {
1367
- if (plugin === "preset-default" || typeof plugin === "object" && plugin.name === "preset-default") {
1368
- console.warn(
1369
- `You are trying to use the preset-default SVGO plugin. This plugin is already included by default, you can customize it through the defaultPresetOverrides option.`
1370
- );
1371
- return false;
1372
- }
1373
- if (plugin === "prefixIds" || typeof plugin === "object" && plugin.name === "prefixIds") {
1374
- console.warn(
1375
- `You are trying to use the preset-default SVGO plugin. This plugin is already included by default, you can customize it through the prefixIds option.`
1376
- );
1377
- return false;
1378
- }
1379
- return true;
1380
- }) || [];
1381
- const data = svgo.optimize(code, {
1382
- floatPrecision: userOpts?.imageOptimization?.svgo?.floatPrecision,
1383
- multipass: userOpts?.imageOptimization?.svgo?.multipass,
1384
- path: path2,
1385
- plugins: [
1386
- {
1387
- name: "preset-default",
1388
- params: {
1389
- overrides: {
1390
- removeViewBox: false,
1391
- ...userOpts?.imageOptimization?.svgo?.defaultPresetOverrides
1392
- }
1393
- }
1394
- },
1395
- {
1396
- name: "customPluginName",
1397
- fn: () => {
1398
- return {
1399
- element: {
1400
- exit: (node) => {
1401
- if (node.name === "svg") {
1402
- node.name = "g";
1403
- Object.assign(svgAttributes, node.attributes);
1404
- node.attributes = {};
1405
- }
1406
- }
1407
- }
1408
- };
1409
- }
1410
- },
1411
- ...maybePrefixIdsPlugin,
1412
- ...userPlugins
1413
- ]
1414
- }).data;
1415
- svgAttributes.dangerouslySetInnerHTML = data.slice(3, -4);
1416
- return {
1417
- data,
1418
- svgAttributes
1419
- };
1420
- }
1421
- async function validatePlugin(opts) {
1422
- if (typeof opts.routesDir !== "string") {
1423
- throw new Error(`qwikRouter plugin "routesDir" option missing`);
1424
- }
1425
- if (!path.isAbsolute(opts.routesDir)) {
1426
- throw new Error(
1427
- `qwikRouter plugin "routesDir" option must be an absolute path: ${opts.routesDir}`
1428
- );
1429
- }
1430
- try {
1431
- const s = await fs$1.promises.stat(opts.routesDir);
1432
- if (!s.isDirectory()) {
1433
- throw new Error(
1434
- `qwikRouter plugin "routesDir" option must be a directory: ${opts.routesDir}`
1435
- );
1436
- }
1437
- } catch (e) {
1438
- throw new Error(`qwikRouter plugin "routesDir" not found: ${e}`);
1439
- }
1440
- }
1441
- class HtmlTransformPatcher {
1442
- constructor(req, res, server) {
1443
- __publicField(this, "state", 0);
1444
- __publicField(this, "buffer", "");
1445
- __publicField(this, "headInnerIndex", -1);
1446
- __publicField(this, "bodyInnerIndex", -1);
1447
- __publicField(this, "isHtmlResponse", false);
1448
- __publicField(this, "bodyPostContent", "");
1449
- __publicField(this, "response");
1450
- __publicField(this, "server");
1451
- __publicField(this, "request");
1452
- __publicField(this, "origWrite");
1453
- __publicField(this, "origEnd");
1454
- __publicField(this, "origSetHeader");
1455
- __publicField(this, "origWriteHead");
1456
- __publicField(this, "processingPromise", null);
1457
- this.request = req;
1458
- this.response = res;
1459
- this.server = server;
1460
- this.origWrite = this.response.write.bind(this.response);
1461
- this.origEnd = this.response.end.bind(this.response);
1462
- this.origSetHeader = this.response.setHeader.bind(this.response);
1463
- this.origWriteHead = this.response.writeHead.bind(this.response);
1464
- this.response.setHeader = (name, value) => {
1465
- if (name.toLowerCase() === "content-type") {
1466
- const contentType = String(value).toLowerCase();
1467
- this.isHtmlResponse = contentType.includes("text/html");
1468
- }
1469
- return this.origSetHeader(name, value);
1470
- };
1471
- this.response.writeHead = (statusCode, statusMessage, headers) => {
1472
- if (typeof statusMessage === "object" && statusMessage !== null) {
1473
- headers = statusMessage;
1474
- statusMessage = void 0;
1475
- }
1476
- if (headers && typeof headers === "object") {
1477
- for (const [key, value] of Object.entries(headers)) {
1478
- if (key.toLowerCase() === "content-type") {
1479
- const contentType = String(value).toLowerCase();
1480
- this.isHtmlResponse = contentType.includes("text/html");
1481
- }
1482
- }
1483
- }
1484
- return this.origWriteHead(statusCode, statusMessage, headers);
1485
- };
1486
- this.response.write = this.handleWrite.bind(this);
1487
- this.response.end = (chunk, encoding, callback) => {
1488
- this.handleEnd(chunk, encoding, callback).catch((error) => {
1489
- console.error("Error in handleEnd:", error);
1490
- this.transitionToPassthrough();
1491
- this.origEnd(chunk, encoding, callback);
1492
- });
1493
- return this.response;
1494
- };
1495
- }
1496
- handleWrite(chunk, encoding, callback) {
1497
- if (!this.isHtmlResponse || this.state === 3) {
1498
- return this.origWrite(chunk, encoding, callback);
1499
- }
1500
- if (typeof encoding === "function") {
1501
- callback = encoding;
1502
- encoding = void 0;
1503
- }
1504
- let data;
1505
- if (chunk instanceof ArrayBuffer || chunk instanceof Uint8Array || chunk instanceof Uint16Array || chunk instanceof Uint32Array) {
1506
- data = new TextDecoder().decode(chunk);
1507
- } else if (Buffer.isBuffer(chunk)) {
1508
- data = chunk.toString(encoding || "utf8");
1509
- } else if (typeof chunk === "string") {
1510
- data = chunk;
1511
- } else {
1512
- data = chunk?.toString() || "";
1513
- }
1514
- this.buffer += data;
1515
- switch (this.state) {
1516
- case 0:
1517
- if (this.headInnerIndex === -1) {
1518
- const headMatch = this.buffer.match(/<head[^>]*>/i);
1519
- if (headMatch) {
1520
- const headOuterIndex = this.buffer.indexOf(headMatch[0]);
1521
- this.headInnerIndex = headOuterIndex + headMatch[0].length;
1522
- }
1523
- }
1524
- if (this.headInnerIndex !== -1) {
1525
- const bodyMatch = this.buffer.slice(this.headInnerIndex).match(/<body[^>]*>/i);
1526
- if (bodyMatch) {
1527
- this.state = 1;
1528
- const bodyOuterIndex = this.buffer.indexOf(bodyMatch[0]);
1529
- this.bodyInnerIndex = bodyOuterIndex + bodyMatch[0].length;
1530
- this.processingPromise = this.processHead();
1531
- }
1532
- }
1533
- break;
1534
- case 1:
1535
- break;
1536
- case 2:
1537
- this.handleStreamingBodyState();
1538
- break;
1539
- default:
1540
- throw new Error(`Invalid state: ${this.state}`);
1541
- }
1542
- callback?.();
1543
- return true;
1544
- }
1545
- async processHead() {
1546
- try {
1547
- const fakeHtml = "<html><head>[FAKE_HEAD]</head><body>[FAKE_BODY]</body></html>";
1548
- const transformedHtml = await this.server.transformIndexHtml(
1549
- this.request.url || "/",
1550
- fakeHtml
1551
- );
1552
- const fakeHeadIndex = transformedHtml.indexOf("[FAKE_HEAD]");
1553
- const fakeHeadCloseIndex = transformedHtml.indexOf("</head>", fakeHeadIndex);
1554
- if (fakeHeadIndex === -1 || fakeHeadCloseIndex === -1) {
1555
- throw new Error("Transformed HTML does not contain [FAKE_HEAD]...</head>");
1556
- }
1557
- const headPreContent = transformedHtml.slice("<html><head>".length, fakeHeadIndex).trim();
1558
- const headPostContent = transformedHtml.slice(
1559
- fakeHeadIndex + "[FAKE_HEAD]".length,
1560
- fakeHeadCloseIndex
1561
- );
1562
- const fakeBodyStartIndex = transformedHtml.indexOf("<body>", fakeHeadCloseIndex);
1563
- const fakeBodyIndex = transformedHtml.indexOf("[FAKE_BODY]", fakeBodyStartIndex);
1564
- const fakeBodyEndIndex = transformedHtml.indexOf("</body>", fakeBodyIndex);
1565
- if (fakeBodyIndex === -1 || fakeBodyEndIndex === -1) {
1566
- throw new Error("Transformed HTML does not contain [FAKE_BODY]...</body>");
1567
- }
1568
- const bodyPreContent = transformedHtml.slice(
1569
- fakeBodyStartIndex + "<body>".length,
1570
- fakeBodyIndex
1571
- );
1572
- this.bodyPostContent = transformedHtml.slice(
1573
- fakeBodyIndex + "[FAKE_BODY]".length,
1574
- fakeBodyEndIndex
1575
- );
1576
- const headCloseIndex = this.buffer.indexOf("</head>", this.headInnerIndex);
1577
- if (headCloseIndex === -1) {
1578
- throw new Error("Buffered HTML does not contain </head>");
1579
- }
1580
- this.buffer = this.buffer.slice(0, this.headInnerIndex) + headPreContent + this.buffer.slice(this.headInnerIndex, headCloseIndex) + headPostContent + this.buffer.slice(headCloseIndex, this.bodyInnerIndex) + bodyPreContent + this.buffer.slice(this.bodyInnerIndex);
1581
- if (this.bodyPostContent.length > 0) {
1582
- this.state = 2;
1583
- this.handleStreamingBodyState();
1584
- return;
1585
- }
1586
- this.transitionToPassthrough();
1587
- return;
1588
- } catch (error) {
1589
- console.error("Error transforming HTML:", error);
1590
- this.transitionToPassthrough();
1591
- return;
1592
- }
1593
- }
1594
- handleStreamingBodyState() {
1595
- const bodyEndMatch = this.buffer.match(/<\/body>/i);
1596
- if (bodyEndMatch) {
1597
- const bodyEndPos = this.buffer.indexOf(bodyEndMatch[0]);
1598
- this.buffer = this.buffer.slice(0, bodyEndPos) + this.bodyPostContent + this.buffer.slice(bodyEndPos);
1599
- this.transitionToPassthrough();
1600
- return;
1601
- }
1602
- this.flushBuffer(6);
1603
- }
1604
- transitionToPassthrough() {
1605
- this.state = 3;
1606
- this.flushBuffer();
1607
- }
1608
- flushBuffer(keep = 0) {
1609
- if (this.buffer.length > keep) {
1610
- if (keep > 0) {
1611
- this.origWrite(this.buffer.slice(0, -keep));
1612
- this.buffer = this.buffer.slice(-keep);
1613
- } else {
1614
- this.origWrite(this.buffer);
1615
- this.buffer = "";
1616
- }
1617
- }
1618
- }
1619
- async handleEnd(chunk, encoding, callback) {
1620
- if (typeof encoding === "function") {
1621
- callback = encoding;
1622
- encoding = void 0;
1623
- }
1624
- if (chunk) {
1625
- this.handleWrite(chunk, encoding);
1626
- }
1627
- await this.processingPromise;
1628
- this.flushBuffer();
1629
- this.origEnd(callback);
1630
- }
1631
- }
1632
- function wrapResponseForHtmlTransform(request, response, server) {
1633
- new HtmlTransformPatcher(request, response, server);
1634
- return response;
1635
- }
1636
- const makeRouterDevMiddleware = (server, ctx) => async (req, res, next) => {
1637
- const mod = await server.ssrLoadModule("src/entry.ssr");
1638
- if (!mod.default) {
1639
- console.error("No default export found in src/entry.ssr");
1640
- return next();
1641
- }
1642
- const renderer = mod.default;
1643
- if (ctx.isDirty) {
1644
- await updateRoutingContext(ctx);
1645
- ctx.isDirty = false;
1646
- }
1647
- const entry = ctx.entries.find((e) => req.url === `${server.config.base}${e.chunkFileName}`);
1648
- if (entry) {
1649
- const entryContents = await server.transformRequest(
1650
- `/@fs${entry.filePath.startsWith("/") ? "" : "/"}${entry.filePath}`
1651
- );
1652
- if (entryContents) {
1653
- res.setHeader("Content-Type", "text/javascript");
1654
- res.end(entryContents.code);
1655
- } else {
1656
- next();
1657
- }
1658
- return;
1659
- }
1660
- if (req.url === `${server.config.base}service-worker.js`) {
1661
- res.setHeader("Content-Type", "text/javascript");
1662
- res.end(
1663
- `/* Qwik Router Dev Service Worker */self.addEventListener('install', () => self.skipWaiting());self.addEventListener('activate', (ev) => ev.waitUntil(self.clients.claim()));`
1664
- );
1665
- return;
1666
- }
1667
- globalThis.__qwik = void 0;
1668
- const { createQwikRouter } = await server.ssrLoadModule(
1669
- "@qwik.dev/router/middleware/node"
1670
- );
1671
- try {
1672
- const render = (async (opts) => {
1673
- return await renderer(opts);
1674
- });
1675
- const { router, staticFile, notFound } = createQwikRouter({ render });
1676
- const wrappedRes = wrapResponseForHtmlTransform(req, res, server);
1677
- staticFile(req, wrappedRes, () => {
1678
- router(req, wrappedRes, () => {
1679
- notFound(req, wrappedRes, next);
1680
- });
1681
- });
1682
- } catch (e) {
1683
- if (e instanceof Error) {
1684
- server.ssrFixStacktrace(e);
1685
- formatError.formatError(e);
1686
- }
1687
- next(e);
1688
- return;
1689
- }
1690
- };
1691
- const CSS_EXTENSIONS = [".css", ".scss", ".sass", ".less", ".styl", ".stylus"];
1692
- const JS_EXTENSIONS = /\.[mc]?[tj]sx?$/;
1693
- const isCssPath = (url) => CSS_EXTENSIONS.some((ext) => url.endsWith(ext));
1694
- const getCssUrls = (server) => {
1695
- const cssModules = /* @__PURE__ */ new Set();
1696
- const cssImportedByCSS = /* @__PURE__ */ new Set();
1697
- Array.from(server.moduleGraph.fileToModulesMap.entries()).forEach(([_name, modules]) => {
1698
- modules.forEach((mod) => {
1699
- const [pathId, query] = mod.url.split("?");
1700
- if (!query && isCssPath(pathId)) {
1701
- const isEntryCSS = mod.importers.size === 0;
1702
- const hasCSSImporter = Array.from(mod.importers).some((importer) => {
1703
- const importerPath = importer.url || importer.file;
1704
- const isCSS = importerPath && isCssPath(importerPath);
1705
- if (isCSS && mod.url) {
1706
- cssImportedByCSS.add(mod.url);
1707
- }
1708
- return isCSS;
1709
- });
1710
- const hasJSImporter = Array.from(mod.importers).some((importer) => {
1711
- const importerPath = importer.url || importer.file;
1712
- return importerPath && JS_EXTENSIONS.test(importerPath);
1713
- });
1714
- if ((isEntryCSS || hasJSImporter) && !hasCSSImporter && !cssImportedByCSS.has(mod.url)) {
1715
- cssModules.add(mod);
1716
- }
1717
- }
1718
- });
1719
- });
1720
- return [...cssModules].map(
1721
- ({ url, lastHMRTimestamp }) => `${url}${lastHMRTimestamp ? `?t=${lastHMRTimestamp}` : ""}`
1722
- );
1723
- };
1724
- const getRouterIndexTags = (server) => {
1725
- const cssUrls = getCssUrls(server);
1726
- return cssUrls.map((url) => ({
1727
- tag: "link",
1728
- attrs: { rel: "stylesheet", href: url }
1729
- }));
1730
- };
1731
- const QWIK_ROUTER_CONFIG_ID = "@qwik-router-config";
1732
- const QWIK_ROUTER_ENTRIES_ID = "@qwik-router-entries";
1733
- const QWIK_ROUTER = "@qwik.dev/router";
1734
- const QWIK_ROUTER_SW_REGISTER = "@qwik-router-sw-register";
1735
- function qwikCity(userOpts) {
1736
- return qwikRouter(userOpts);
1737
- }
1738
- function qwikRouter(userOpts) {
1739
- return [qwikRouterPlugin(userOpts), ...imagePlugin(userOpts)];
1740
- }
1741
- function qwikRouterPlugin(userOpts) {
1742
- let ctx = null;
1743
- let mdxTransform = null;
1744
- let rootDir = null;
1745
- let qwikPlugin;
1746
- let ssrFormat = "esm";
1747
- let outDir = null;
1748
- let viteCommand;
1749
- let devServer = null;
1750
- let devSsrServer = userOpts?.devSsrServer;
1751
- const routesDir = userOpts?.routesDir ?? "src/routes";
1752
- const serverPluginsDir = userOpts?.serverPluginsDir ?? routesDir;
1753
- const api = {
1754
- getBasePathname: () => ctx?.opts.basePathname ?? "/",
1755
- getRoutes: () => {
1756
- return ctx?.routes.slice() ?? [];
1757
- },
1758
- getServiceWorkers: () => {
1759
- return ctx?.serviceWorkers.slice() ?? [];
1760
- }
1761
- };
1762
- const plugin = {
1763
- name: "vite-plugin-qwik-router",
1764
- enforce: "pre",
1765
- api,
1766
- async config(_viteConfig, viteEnv) {
1767
- viteCommand = viteEnv.command;
1768
- const updatedViteConfig = {
1769
- define: {
1770
- "globalThis.__DEFAULT_LOADERS_SERIALIZATION_STRATEGY__": JSON.stringify(
1771
- userOpts?.defaultLoadersSerializationStrategy || "never"
1772
- ),
1773
- "globalThis.__NO_TRAILING_SLASH__": JSON.stringify(userOpts?.trailingSlash === false)
1774
- },
1775
- appType: "custom",
1776
- resolve: {
1777
- dedupe: [QWIK_ROUTER, "@builder.io/qwik-city"],
1778
- alias: [
1779
- { find: "@builder.io/qwik-city", replacement: "@qwik.dev/router" },
1780
- { find: /^@builder\.io\/qwik-city\/(.*)/, replacement: "@qwik.dev/router/$1" },
1781
- { find: "@qwik-city-plan", replacement: QWIK_ROUTER_CONFIG_ID },
1782
- { find: "@qwik-city-entries", replacement: QWIK_ROUTER_ENTRIES_ID },
1783
- { find: "@qwik-city-sw-register", replacement: QWIK_ROUTER_SW_REGISTER }
1784
- ]
1785
- },
1786
- optimizeDeps: {
1787
- // Let Vite find all app deps, these are not part of the static imports from `src/root`
1788
- entries: [
1789
- `${routesDir}/**/index*`,
1790
- `${routesDir}/**/layout*`,
1791
- `${serverPluginsDir}/plugin@*`
1792
- ],
1793
- // These need processing by the optimizer during dev
1794
- exclude: [
1795
- QWIK_ROUTER,
1796
- QWIK_ROUTER_CONFIG_ID,
1797
- QWIK_ROUTER_ENTRIES_ID,
1798
- QWIK_ROUTER_SW_REGISTER
1799
- ]
1800
- },
1801
- ssr: {
1802
- external: ["node:async_hooks"],
1803
- noExternal: [
1804
- QWIK_ROUTER,
1805
- QWIK_ROUTER_CONFIG_ID,
1806
- QWIK_ROUTER_ENTRIES_ID,
1807
- QWIK_ROUTER_SW_REGISTER,
1808
- // We've had reports of bundling issues with zod
1809
- "zod"
1810
- ]
1811
- },
1812
- server: {
1813
- watch: {
1814
- // needed for recursive watching of index and layout files in the src/routes directory
1815
- disableGlobbing: false
1816
- }
1817
- }
1818
- };
1819
- return updatedViteConfig;
1820
- },
1821
- async configResolved(config) {
1822
- Object.assign(process.env, vite.loadEnv(config.mode, process.cwd(), ""));
1823
- rootDir = path.resolve(config.root);
1824
- const target = config.build?.ssr || config.mode === "ssr" ? "ssr" : "client";
1825
- ctx = createBuildContext(
1826
- rootDir,
1827
- config.base,
1828
- userOpts,
1829
- target,
1830
- !userOpts?.staticImportRoutes
1831
- );
1832
- await validatePlugin(ctx.opts);
1833
- mdxTransform = await createMdxTransformer(ctx);
1834
- qwikPlugin = config.plugins.find(
1835
- (p) => p.name === "vite-plugin-qwik"
1836
- );
1837
- if (!qwikPlugin) {
1838
- throw new Error("Missing vite-plugin-qwik");
1839
- }
1840
- if (typeof devSsrServer !== "boolean") {
1841
- devSsrServer = qwikPlugin.api._oldDevSsrServer();
1842
- }
1843
- qwikPlugin.api.registerBundleGraphAdder?.((manifest) => {
1844
- return getRouteImports(ctx.routes, manifest);
1845
- });
1846
- if (config.ssr?.format === "cjs") {
1847
- ssrFormat = "cjs";
1848
- }
1849
- outDir = config.build?.outDir;
1850
- },
1851
- async configureServer(server) {
1852
- devServer = server;
1853
- const toWatch = path.resolve(
1854
- rootDir,
1855
- "src/routes/**/{index,layout,entry,service-worker}{.,@,-}*"
1856
- );
1857
- server.watcher.add(toWatch);
1858
- await new Promise((resolve2) => setTimeout(resolve2, 1e3));
1859
- server.watcher.on("change", (path2) => {
1860
- if (!/\/(index[.@]|layout[.-]|entry\.|service-worker\.)[^/]*$/.test(path2)) {
1861
- return;
1862
- }
1863
- ctx.isDirty = true;
1864
- const graph = server.environments?.ssr?.moduleGraph;
1865
- if (graph) {
1866
- const mod = graph.getModuleById("@qwik-router-config");
1867
- if (mod) {
1868
- graph.invalidateModule(mod);
1869
- }
1870
- }
1871
- });
1872
- if (userOpts?.devSsrServer !== false) {
1873
- return () => {
1874
- server.middlewares.use(makeRouterDevMiddleware(server, ctx));
1875
- };
1876
- }
1877
- },
1878
- transformIndexHtml() {
1879
- if (viteCommand !== "serve") {
1880
- return;
1881
- }
1882
- return getRouterIndexTags(devServer);
1883
- },
1884
- buildStart() {
1885
- resetBuildContext(ctx);
1886
- },
1887
- resolveId(id) {
1888
- if (id === QWIK_ROUTER_CONFIG_ID || id === QWIK_ROUTER_ENTRIES_ID) {
1889
- return {
1890
- id,
1891
- // user entries added in the routes, like src/routes/service-worker.ts
1892
- // are added as dynamic imports to the qwik-router-config as a way to create
1893
- // a new entry point for the build. Ensure these are not treeshaken.
1894
- moduleSideEffects: "no-treeshake"
1895
- };
1896
- }
1897
- if (id === QWIK_ROUTER_SW_REGISTER) {
1898
- return id;
1899
- }
1900
- return null;
1901
- },
1902
- async load(id, opts) {
1903
- if (ctx) {
1904
- if (id.endsWith(QWIK_ROUTER_ENTRIES_ID)) {
1905
- return generateQwikRouterEntries(ctx);
1906
- }
1907
- const isRouterConfig = id.endsWith(QWIK_ROUTER_CONFIG_ID);
1908
- const isSwRegister = id.endsWith(QWIK_ROUTER_SW_REGISTER);
1909
- if (isRouterConfig || isSwRegister) {
1910
- if (ctx.isDirty) {
1911
- await parseRoutesDir(ctx);
1912
- ctx.isDirty = false;
1913
- ctx.diagnostics.forEach((d) => {
1914
- this.warn(d.message);
1915
- });
1916
- }
1917
- if (isRouterConfig) {
1918
- return generateQwikRouterConfig(ctx, qwikPlugin, opts?.ssr ?? false);
1919
- }
1920
- if (isSwRegister) {
1921
- return generateServiceWorkerRegister(ctx, swRegister);
1922
- }
1923
- }
1924
- }
1925
- return null;
1926
- },
1927
- async transform(code, id) {
1928
- const isVirtualId = id.startsWith("\0");
1929
- if (isVirtualId) {
1930
- return;
1931
- }
1932
- const ext = path.extname(id).toLowerCase();
1933
- const isMD = ext === ".md" || ext === ".mdx";
1934
- if (ctx && isMD) {
1935
- const fileName = path.basename(id);
1936
- if (fs.isMenuFileName(fileName)) {
1937
- const menuCode = await transformMenu(ctx.opts, id, code);
1938
- return { code: menuCode, map: null };
1939
- }
1940
- if (mdxTransform) {
1941
- try {
1942
- const mdxResult = await mdxTransform(code, id);
1943
- return mdxResult;
1944
- } catch (e) {
1945
- if (e && typeof e == "object" && "position" in e && "reason" in e) {
1946
- const column = e.position?.start.column;
1947
- const line = e.position?.start.line;
1948
- const err = Object.assign(new Error(e.reason), {
1949
- id,
1950
- plugin: "qwik-router-mdx",
1951
- loc: {
1952
- column,
1953
- line
1954
- },
1955
- stack: ""
1956
- });
1957
- this.error(err);
1958
- } else if (e instanceof Error) {
1959
- this.error(e);
1960
- } else {
1961
- this.error(String(e));
1962
- }
1963
- }
1964
- }
1965
- }
1966
- return null;
1967
- },
1968
- generateBundle(_, bundles) {
1969
- if (ctx?.target === "client") {
1970
- const entries = [...ctx.entries, ...ctx.serviceWorkers].map((entry) => {
1971
- return {
1972
- chunkFileName: entry.chunkFileName,
1973
- extensionlessFilePath: fs.removeExtension(entry.filePath)
1974
- };
1975
- });
1976
- for (const entry of entries) {
1977
- for (const fileName in bundles) {
1978
- const c = bundles[fileName];
1979
- if (c.type === "chunk" && c.isDynamicEntry && c.facadeModuleId) {
1980
- const extensionlessFilePath = fs.removeExtension(fs.normalizePath(c.facadeModuleId));
1981
- if (entry.extensionlessFilePath === extensionlessFilePath) {
1982
- c.fileName = entry.chunkFileName;
1983
- continue;
1984
- }
1985
- }
1986
- }
1987
- }
1988
- }
1989
- },
1990
- closeBundle: {
1991
- sequential: true,
1992
- async handler() {
1993
- if (ctx?.target === "ssr" && outDir) {
1994
- await generateServerPackageJson(outDir, ssrFormat);
1995
- }
1996
- }
1997
- }
1998
- };
1999
- return plugin;
2000
- }
2001
- async function generateServerPackageJson(outDir, ssrFormat) {
2002
- await fs$1.promises.mkdir(outDir, { recursive: true });
2003
- const serverPackageJsonPath = path.join(outDir, "package.json");
2004
- let packageJson = {};
2005
- if (fs$1.existsSync(serverPackageJsonPath)) {
2006
- const content = await fs$1.promises.readFile(serverPackageJsonPath, "utf-8");
2007
- const contentAsJson = JSON.parse(content);
2008
- packageJson = {
2009
- ...contentAsJson
2010
- };
2011
- }
2012
- packageJson = {
2013
- ...packageJson,
2014
- type: ssrFormat == "cjs" ? "commonjs" : "module"
2015
- };
2016
- const serverPackageJsonCode = JSON.stringify(packageJson, null, 2);
2017
- await fs$1.promises.writeFile(serverPackageJsonPath, serverPackageJsonCode);
2018
- }
2019
- exports.extendConfig = extendConfig;
2020
- exports.qwikCity = qwikCity;
2021
- exports.qwikRouter = qwikRouter;