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