elm-pages 2.1.11 → 3.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/{template/public/style.css → review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock} +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +27617 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/package.json +1 -0
- package/generator/review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
- package/generator/review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
- package/generator/review/elm.json +13 -4
- package/{src → generator/review/src}/Pages/Review/NoContractViolations.elm +148 -148
- package/generator/review/tests/Pages/Review/NoContractViolationsTest.elm +331 -0
- package/generator/src/RouteBuilder.elm +420 -0
- package/generator/src/SharedTemplate.elm +4 -5
- package/generator/src/SiteConfig.elm +3 -9
- package/generator/src/build.js +308 -95
- package/generator/src/cli.js +103 -8
- package/generator/src/codegen.js +192 -35
- package/generator/src/compile-elm.js +183 -31
- package/generator/src/dev-server.js +353 -96
- package/generator/src/elm-application.json +3 -1
- package/generator/src/elm-codegen.js +34 -0
- package/generator/src/elm-file-constants.js +2 -0
- package/generator/src/error-formatter.js +20 -1
- package/generator/src/generate-template-module-connector.js +120 -924
- package/generator/src/hello.ts +5 -0
- package/generator/src/pre-render-html.js +58 -104
- package/generator/src/render-worker.js +27 -13
- package/generator/src/render.js +252 -197
- package/generator/src/request-cache-fs.js +18 -0
- package/generator/src/request-cache.js +128 -56
- package/generator/src/rewrite-client-elm-json.js +49 -0
- package/generator/src/route-codegen-helpers.js +62 -1
- package/generator/static-code/dev-style.css +22 -0
- package/generator/static-code/elm-pages.js +43 -39
- package/generator/static-code/hmr.js +98 -88
- package/generator/template/app/Api.elm +25 -0
- package/generator/template/app/ErrorPage.elm +38 -0
- package/generator/template/app/Route/Index.elm +87 -0
- package/generator/template/{src → app}/Shared.elm +34 -13
- package/generator/template/app/Site.elm +19 -0
- package/generator/template/{src → app}/View.elm +0 -0
- package/generator/template/elm-pages.config.mjs +5 -0
- package/generator/template/elm.json +1 -0
- package/generator/template/{public/index.js → index.ts} +7 -3
- package/generator/template/package.json +4 -4
- package/generator/template/public/favicon.ico +0 -0
- package/generator/template/public/images/icon-png.png +0 -0
- package/generator/template/src/.gitkeep +0 -0
- package/generator/template/style.css +4 -0
- package/package.json +30 -23
- package/src/ApiRoute.elm +176 -43
- package/src/BuildError.elm +10 -1
- package/src/CookieParser.elm +84 -0
- package/src/DataSource/Env.elm +38 -0
- package/src/DataSource/File.elm +27 -16
- package/src/DataSource/Glob.elm +126 -80
- package/src/DataSource/Http.elm +283 -304
- package/src/DataSource/Internal/Glob.elm +5 -21
- package/src/DataSource/Internal/Request.elm +25 -0
- package/src/DataSource/Port.elm +17 -14
- package/src/DataSource.elm +55 -318
- package/src/Form/Field.elm +717 -0
- package/src/Form/FieldStatus.elm +36 -0
- package/src/Form/FieldView.elm +417 -0
- package/src/Form/FormData.elm +22 -0
- package/src/Form/Validation.elm +391 -0
- package/src/Form/Value.elm +118 -0
- package/src/Form.elm +1683 -0
- package/src/FormData.elm +58 -0
- package/src/FormDecoder.elm +102 -0
- package/src/Head/Seo.elm +12 -4
- package/src/Head.elm +12 -2
- package/src/HtmlPrinter.elm +1 -1
- package/src/Internal/ApiRoute.elm +17 -4
- package/src/Internal/Request.elm +7 -0
- package/src/PageServerResponse.elm +68 -0
- package/src/Pages/ContentCache.elm +1 -229
- package/src/Pages/Fetcher.elm +58 -0
- package/src/Pages/FormState.elm +256 -0
- package/src/Pages/Generate.elm +800 -0
- package/src/Pages/Internal/Form.elm +17 -0
- package/src/Pages/Internal/NotFoundReason.elm +3 -55
- package/src/Pages/Internal/Platform/Cli.elm +777 -579
- package/src/Pages/Internal/Platform/Effect.elm +5 -5
- package/src/Pages/Internal/Platform/StaticResponses.elm +178 -394
- package/src/Pages/Internal/Platform/ToJsPayload.elm +24 -23
- package/src/Pages/Internal/Platform.elm +1244 -504
- package/src/Pages/Internal/ResponseSketch.elm +19 -0
- package/src/Pages/Internal/RoutePattern.elm +596 -45
- package/src/Pages/Manifest.elm +26 -0
- package/src/Pages/Msg.elm +79 -0
- package/src/Pages/ProgramConfig.elm +67 -14
- package/src/Pages/SiteConfig.elm +3 -6
- package/src/Pages/StaticHttp/Request.elm +4 -2
- package/src/Pages/StaticHttpRequest.elm +50 -215
- package/src/Pages/Transition.elm +70 -0
- package/src/Path.elm +1 -0
- package/src/Pattern.elm +98 -0
- package/src/RenderRequest.elm +2 -2
- package/src/RequestsAndPending.elm +111 -9
- package/src/Server/Request.elm +1253 -0
- package/src/Server/Response.elm +292 -0
- package/src/Server/Session.elm +316 -0
- package/src/Server/SetCookie.elm +169 -0
- package/src/TerminalText.elm +1 -1
- package/src/Test/Html/Internal/ElmHtml/Markdown.elm +0 -1
- package/src/Test/Html/Internal/ElmHtml/ToString.elm +1 -1
- package/generator/src/Page.elm +0 -359
- package/generator/src/codegen-template-module.js +0 -183
- package/generator/src/elm-pages-js-minified.js +0 -1
- package/generator/template/src/Api.elm +0 -14
- package/generator/template/src/Page/Index.elm +0 -69
- package/generator/template/src/Site.elm +0 -41
- package/src/DataSource/ServerRequest.elm +0 -60
- package/src/Internal/OptimizedDecoder.elm +0 -18
- package/src/KeepOrDiscard.elm +0 -6
- package/src/OptimizedDecoder/Pipeline.elm +0 -335
- package/src/OptimizedDecoder.elm +0 -818
- package/src/Pages/Internal/ApplicationType.elm +0 -6
- package/src/Pages/Secrets.elm +0 -83
- package/src/Secrets.elm +0 -111
- package/src/SecretsDict.elm +0 -45
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
-
const
|
|
3
|
-
const fs = require("fs");
|
|
2
|
+
const fetch = require("node-fetch");
|
|
4
3
|
const objectHash = require("object-hash");
|
|
5
4
|
const kleur = require("kleur");
|
|
6
5
|
|
|
@@ -17,61 +16,76 @@ function requestToString(request) {
|
|
|
17
16
|
/**
|
|
18
17
|
* @param {Object} request
|
|
19
18
|
*/
|
|
20
|
-
function fullPath(request) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
function fullPath(portsHash, request, hasFsAccess) {
|
|
20
|
+
const requestWithPortHash =
|
|
21
|
+
request.url === "elm-pages-internal://port"
|
|
22
|
+
? { portsHash, ...request }
|
|
23
|
+
: request;
|
|
24
|
+
if (hasFsAccess) {
|
|
25
|
+
return path.join(
|
|
26
|
+
process.cwd(),
|
|
27
|
+
".elm-pages",
|
|
28
|
+
"http-response-cache",
|
|
29
|
+
requestToString(requestWithPortHash)
|
|
30
|
+
);
|
|
31
|
+
} else {
|
|
32
|
+
return path.join("/", requestToString(requestWithPortHash));
|
|
33
|
+
}
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
/**
|
|
30
37
|
* @param {string} mode
|
|
31
|
-
* @param {{url: string;
|
|
38
|
+
* @param {{url: string;headers: {[x: string]: string;};method: string;body: Body;}} rawRequest
|
|
32
39
|
* @returns {Promise<string>}
|
|
40
|
+
* @param {string} portsFile
|
|
41
|
+
* @param {boolean} hasFsAccess
|
|
33
42
|
*/
|
|
34
|
-
function lookupOrPerform(mode, rawRequest) {
|
|
43
|
+
function lookupOrPerform(portsFile, mode, rawRequest, hasFsAccess, useCache) {
|
|
44
|
+
const { fs } = require("./request-cache-fs.js")(hasFsAccess);
|
|
35
45
|
return new Promise(async (resolve, reject) => {
|
|
36
46
|
const request = toRequest(rawRequest);
|
|
37
|
-
const
|
|
47
|
+
const portsHash = (portsFile && portsFile.match(/-([^-]+)\.js$/)[1]) || "";
|
|
48
|
+
const responsePath = fullPath(portsHash, request, hasFsAccess);
|
|
38
49
|
|
|
39
|
-
if
|
|
50
|
+
// TODO check cache expiration time and delete and go to else if expired
|
|
51
|
+
if (useCache && (await checkFileExists(fs, responsePath))) {
|
|
40
52
|
// console.log("Skipping request, found file.");
|
|
41
53
|
resolve(responsePath);
|
|
42
54
|
} else {
|
|
43
55
|
let portDataSource = {};
|
|
44
|
-
let
|
|
56
|
+
let portDataSourceImportError = null;
|
|
45
57
|
try {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
if (portsFile === undefined) {
|
|
59
|
+
throw "missing";
|
|
60
|
+
}
|
|
61
|
+
const portDataSourcePath = path.resolve(portsFile);
|
|
62
|
+
// On Windows, we need cannot use paths directly and instead must use a file:// URL.
|
|
63
|
+
// portDataSource = await require(url.pathToFileURL(portDataSourcePath).href);
|
|
64
|
+
portDataSource = require(portDataSourcePath);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
portDataSourceImportError = e;
|
|
67
|
+
}
|
|
52
68
|
|
|
53
|
-
if (request.url
|
|
69
|
+
if (request.url === "elm-pages-internal://port") {
|
|
54
70
|
try {
|
|
55
|
-
const portName =
|
|
56
|
-
|
|
71
|
+
const { input, portName } = rawRequest.body.args[0];
|
|
72
|
+
|
|
57
73
|
if (!portDataSource[portName]) {
|
|
58
|
-
if (
|
|
59
|
-
throw `DataSource.Port.send "${portName}"
|
|
74
|
+
if (portDataSourceImportError === null) {
|
|
75
|
+
throw `DataSource.Port.send "${portName}" was called, but I couldn't find a function with that name in the port definitions file. Is it exported correctly?`;
|
|
76
|
+
} else if (portDataSourceImportError === "missing") {
|
|
77
|
+
throw `DataSource.Port.send "${portName}" was called, but I couldn't find the port definitions file. Be sure to create a 'port-data-source.ts' or 'port-data-source.js' file and maybe restart the dev server.`;
|
|
60
78
|
} else {
|
|
61
|
-
throw `DataSource.Port.send "${portName}" was called, but I couldn't
|
|
79
|
+
throw `DataSource.Port.send "${portName}" was called, but I couldn't import the port definitions file, because of this exception: \`${portDataSourceImportError}\` Are there syntax errors or expections thrown during import?`;
|
|
62
80
|
}
|
|
63
81
|
} else if (typeof portDataSource[portName] !== "function") {
|
|
64
|
-
throw `DataSource.Port.send "${portName}" is not a function. Be sure to export a function with that name from port-data-source.js`;
|
|
82
|
+
throw `DataSource.Port.send "${portName}" was called, but it is not a function. Be sure to export a function with that name from port-data-source.js`;
|
|
65
83
|
}
|
|
66
84
|
await fs.promises.writeFile(
|
|
67
85
|
responsePath,
|
|
68
|
-
JSON.stringify(
|
|
69
|
-
await portDataSource[portName](rawRequest.body.args[0])
|
|
70
|
-
)
|
|
86
|
+
JSON.stringify(jsonResponse(await portDataSource[portName](input)))
|
|
71
87
|
);
|
|
72
88
|
resolve(responsePath);
|
|
73
|
-
|
|
74
|
-
// console.timeEnd(JSON.stringify(requestToPerform.masked));
|
|
75
89
|
} catch (error) {
|
|
76
90
|
console.trace(error);
|
|
77
91
|
reject({
|
|
@@ -80,38 +94,81 @@ function lookupOrPerform(mode, rawRequest) {
|
|
|
80
94
|
});
|
|
81
95
|
}
|
|
82
96
|
} else {
|
|
83
|
-
|
|
84
|
-
.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
...request.headers,
|
|
92
|
-
},
|
|
97
|
+
try {
|
|
98
|
+
console.time(`fetch ${request.url}`);
|
|
99
|
+
const response = await fetch(request.url, {
|
|
100
|
+
method: request.method,
|
|
101
|
+
body: request.body,
|
|
102
|
+
headers: {
|
|
103
|
+
"User-Agent": "request",
|
|
104
|
+
...request.headers,
|
|
93
105
|
},
|
|
94
|
-
|
|
95
|
-
const writeStream = fs.createWriteStream(responsePath);
|
|
96
|
-
writeStream.on("finish", async () => {
|
|
97
|
-
resolve(responsePath);
|
|
98
|
-
});
|
|
106
|
+
});
|
|
99
107
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
.
|
|
104
|
-
let
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
console.timeEnd(`fetch ${request.url}`);
|
|
109
|
+
const expectString = request.headers["elm-pages-internal"];
|
|
110
|
+
|
|
111
|
+
if (response.ok || expectString === "ExpectResponse") {
|
|
112
|
+
let body;
|
|
113
|
+
let bodyKind;
|
|
114
|
+
if (expectString === "ExpectJson") {
|
|
115
|
+
body = await response.json();
|
|
116
|
+
bodyKind = "json";
|
|
117
|
+
} else if (
|
|
118
|
+
expectString === "ExpectBytes" ||
|
|
119
|
+
expectString === "ExpectBytesResponse"
|
|
120
|
+
) {
|
|
121
|
+
bodyKind = "bytes";
|
|
122
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
123
|
+
body = Buffer.from(arrayBuffer).toString("base64");
|
|
124
|
+
} else if (expectString === "ExpectWhatever") {
|
|
125
|
+
bodyKind = "whatever";
|
|
126
|
+
body = null;
|
|
127
|
+
} else if (
|
|
128
|
+
expectString === "ExpectResponse" ||
|
|
129
|
+
expectString === "ExpectString"
|
|
130
|
+
) {
|
|
131
|
+
bodyKind = "string";
|
|
132
|
+
body = await response.text();
|
|
133
|
+
} else {
|
|
134
|
+
throw `Unexpected expectString ${expectString}`;
|
|
107
135
|
}
|
|
136
|
+
|
|
137
|
+
await fs.promises.writeFile(
|
|
138
|
+
responsePath,
|
|
139
|
+
JSON.stringify({
|
|
140
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
141
|
+
statusCode: response.status,
|
|
142
|
+
body: body,
|
|
143
|
+
bodyKind,
|
|
144
|
+
url: response.url,
|
|
145
|
+
statusText: response.statusText,
|
|
146
|
+
})
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
resolve(responsePath);
|
|
150
|
+
} else {
|
|
151
|
+
console.log("@@@ request-cache1 bad HTTP response");
|
|
108
152
|
reject({
|
|
109
153
|
title: "DataSource.Http Error",
|
|
110
154
|
message: `${kleur
|
|
111
155
|
.yellow()
|
|
112
|
-
.underline(request.url)} ${
|
|
156
|
+
.underline(request.url)} Bad HTTP response ${response.status} ${
|
|
157
|
+
response.statusText
|
|
158
|
+
}
|
|
159
|
+
`,
|
|
113
160
|
});
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.trace("@@@ request-cache2 HTTP error", error);
|
|
164
|
+
reject({
|
|
165
|
+
title: "DataSource.Http Error",
|
|
166
|
+
message: `${kleur
|
|
167
|
+
.yellow()
|
|
168
|
+
.underline(request.url)} ${error.toString()}
|
|
169
|
+
`,
|
|
114
170
|
});
|
|
171
|
+
}
|
|
115
172
|
}
|
|
116
173
|
}
|
|
117
174
|
});
|
|
@@ -131,7 +188,15 @@ function toRequest(elmRequest) {
|
|
|
131
188
|
body: toBody(elmRequest.body),
|
|
132
189
|
};
|
|
133
190
|
}
|
|
134
|
-
|
|
191
|
+
/**
|
|
192
|
+
* @param {string} file
|
|
193
|
+
*/
|
|
194
|
+
function checkFileExists(fs, file) {
|
|
195
|
+
return fs.promises
|
|
196
|
+
.access(file, fs.constants.F_OK)
|
|
197
|
+
.then(() => true)
|
|
198
|
+
.catch(() => false);
|
|
199
|
+
}
|
|
135
200
|
/**
|
|
136
201
|
* @param {Body} body
|
|
137
202
|
*/
|
|
@@ -177,4 +242,11 @@ function requireUncached(mode, filePath) {
|
|
|
177
242
|
return require(filePath);
|
|
178
243
|
}
|
|
179
244
|
|
|
245
|
+
/**
|
|
246
|
+
* @param {unknown} json
|
|
247
|
+
*/
|
|
248
|
+
function jsonResponse(json) {
|
|
249
|
+
return { bodyKind: "json", body: json };
|
|
250
|
+
}
|
|
251
|
+
|
|
180
252
|
module.exports = { lookupOrPerform };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
|
|
3
|
+
module.exports = async function () {
|
|
4
|
+
var elmJson = JSON.parse(
|
|
5
|
+
(await fs.promises.readFile("./elm.json")).toString()
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
// write new elm.json
|
|
9
|
+
|
|
10
|
+
await writeFileIfChanged(
|
|
11
|
+
"./elm-stuff/elm-pages/client/elm.json",
|
|
12
|
+
JSON.stringify(rewriteElmJson(elmJson))
|
|
13
|
+
);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function rewriteElmJson(elmJson) {
|
|
17
|
+
// The internal generated file will be at:
|
|
18
|
+
// ./elm-stuff/elm-pages/
|
|
19
|
+
// So, we need to take the existing elmJson and
|
|
20
|
+
// 1. remove existing path that looks at `Pages.elm`
|
|
21
|
+
elmJson["source-directories"] = elmJson["source-directories"].filter(
|
|
22
|
+
(item) => {
|
|
23
|
+
return item != ".elm-pages" && item != "app";
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
// 2. prepend ../../../ to remaining
|
|
27
|
+
elmJson["source-directories"] = elmJson["source-directories"].map((item) => {
|
|
28
|
+
return "../../../" + item;
|
|
29
|
+
});
|
|
30
|
+
// 3. add our own secret My.elm module 😈
|
|
31
|
+
elmJson["source-directories"].push(".elm-pages");
|
|
32
|
+
elmJson["source-directories"].push("app");
|
|
33
|
+
return elmJson;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function writeFileIfChanged(filePath, content) {
|
|
37
|
+
if (
|
|
38
|
+
!(await fileExists(filePath)) ||
|
|
39
|
+
(await fs.promises.readFile(filePath, "utf8")) !== content
|
|
40
|
+
) {
|
|
41
|
+
await fs.promises.writeFile(filePath, content);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function fileExists(file) {
|
|
45
|
+
return fs.promises
|
|
46
|
+
.access(file, fs.constants.F_OK)
|
|
47
|
+
.then(() => true)
|
|
48
|
+
.catch(() => false);
|
|
49
|
+
}
|
|
@@ -177,6 +177,62 @@ function toPathPattern(name) {
|
|
|
177
177
|
.join("/")
|
|
178
178
|
);
|
|
179
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* @param {string[]} name
|
|
182
|
+
* @returns {string[]}
|
|
183
|
+
*/
|
|
184
|
+
function toPathPatterns(name) {
|
|
185
|
+
const segments = parseRouteParamsWithStatic(name);
|
|
186
|
+
|
|
187
|
+
const lastSegment = segments[segments.length - 1];
|
|
188
|
+
const allButLast = segments.slice(0, segments.length - 1);
|
|
189
|
+
if (lastSegment && lastSegment.kind === "optional") {
|
|
190
|
+
return [
|
|
191
|
+
joinPath(newHelper(allButLast)),
|
|
192
|
+
joinPath(newHelper(allButLast).concat(`:${lastSegment.name}`)),
|
|
193
|
+
];
|
|
194
|
+
} else {
|
|
195
|
+
return [joinPath(newHelper(segments))];
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @param {string[]} segments
|
|
201
|
+
*/
|
|
202
|
+
function joinPath(segments) {
|
|
203
|
+
const joined = segments.join("/");
|
|
204
|
+
if (joined.startsWith("/")) {
|
|
205
|
+
return joined;
|
|
206
|
+
} else {
|
|
207
|
+
return "/" + joined;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @return {string[]}
|
|
213
|
+
*/
|
|
214
|
+
function newHelper(segments) {
|
|
215
|
+
return segments.map((param) => {
|
|
216
|
+
switch (param.kind) {
|
|
217
|
+
case "static": {
|
|
218
|
+
return camelToKebab(param.name);
|
|
219
|
+
}
|
|
220
|
+
case "dynamic": {
|
|
221
|
+
return `:${param.name}`;
|
|
222
|
+
}
|
|
223
|
+
case "optional": {
|
|
224
|
+
return `[:${param.name}]`;
|
|
225
|
+
}
|
|
226
|
+
case "required-splat": {
|
|
227
|
+
return `*`;
|
|
228
|
+
}
|
|
229
|
+
case "optional-splat": {
|
|
230
|
+
return `*`;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
// .join("/");
|
|
235
|
+
}
|
|
180
236
|
|
|
181
237
|
/**
|
|
182
238
|
* @param {string[]} name
|
|
@@ -211,7 +267,11 @@ function toElmPathPattern(name) {
|
|
|
211
267
|
.flatMap((param) => {
|
|
212
268
|
switch (param.kind) {
|
|
213
269
|
case "static": {
|
|
214
|
-
return [
|
|
270
|
+
return [
|
|
271
|
+
`Pages.Internal.RoutePattern.StaticSegment "${camelToKebab(
|
|
272
|
+
param.name
|
|
273
|
+
)}"`,
|
|
274
|
+
];
|
|
215
275
|
}
|
|
216
276
|
case "dynamic": {
|
|
217
277
|
return [`Pages.Internal.RoutePattern.DynamicSegment "${param.name}"`];
|
|
@@ -308,6 +368,7 @@ module.exports = {
|
|
|
308
368
|
toFieldName,
|
|
309
369
|
paramsRecord,
|
|
310
370
|
toPathPattern,
|
|
371
|
+
toPathPatterns,
|
|
311
372
|
parseRouteParams,
|
|
312
373
|
parseRouteParamsWithStatic,
|
|
313
374
|
toElmPathPattern,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
@keyframes lds-default {
|
|
2
|
+
0%,
|
|
3
|
+
20%,
|
|
4
|
+
80%,
|
|
5
|
+
100% {
|
|
6
|
+
transform: scale(1);
|
|
7
|
+
}
|
|
8
|
+
50% {
|
|
9
|
+
transform: scale(1.5);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
#not-found-reason code {
|
|
13
|
+
color: rgb(226, 0, 124);
|
|
14
|
+
}
|
|
15
|
+
#not-found-reason h1 {
|
|
16
|
+
font-size: 26px;
|
|
17
|
+
font-weight: bold;
|
|
18
|
+
padding-bottom: 15px;
|
|
19
|
+
}
|
|
20
|
+
#not-found-reason a:hover {
|
|
21
|
+
text-decoration: underline;
|
|
22
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import userInit from "/index
|
|
2
|
-
|
|
3
|
-
let prefetchedPages = [window.location.pathname];
|
|
4
|
-
let initialLocationHash = document.location.hash.replace(/^#/, "");
|
|
1
|
+
import userInit from "/index";
|
|
5
2
|
|
|
3
|
+
let prefetchedPages;
|
|
4
|
+
let initialLocationHash;
|
|
6
5
|
/**
|
|
7
6
|
* @returns
|
|
8
7
|
*/
|
|
@@ -11,15 +10,15 @@ function loadContentAndInitializeApp() {
|
|
|
11
10
|
if (!path.endsWith("/")) {
|
|
12
11
|
path = path + "/";
|
|
13
12
|
}
|
|
14
|
-
const app = Elm.
|
|
13
|
+
const app = Elm.Main.init({
|
|
15
14
|
flags: {
|
|
16
15
|
secrets: null,
|
|
17
16
|
isPrerendering: false,
|
|
18
17
|
isDevServer: false,
|
|
19
18
|
isElmDebugMode: false,
|
|
20
|
-
contentJson:
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
contentJson: {},
|
|
20
|
+
pageDataBase64: document.getElementById("__ELM_PAGES_BYTES_DATA__")
|
|
21
|
+
.innerHTML,
|
|
23
22
|
userFlags: userInit.flags(),
|
|
24
23
|
},
|
|
25
24
|
});
|
|
@@ -48,48 +47,51 @@ function prefetchIfNeeded(/** @type {HTMLAnchorElement} */ target) {
|
|
|
48
47
|
link.setAttribute("as", "fetch");
|
|
49
48
|
|
|
50
49
|
link.setAttribute("rel", "prefetch");
|
|
51
|
-
link.setAttribute("href", origin + target.pathname + "/content.
|
|
50
|
+
link.setAttribute("href", origin + target.pathname + "/content.dat");
|
|
52
51
|
document.head.appendChild(link);
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
userInit.load(appPromise);
|
|
63
|
-
|
|
64
|
-
if (typeof connect === "function") {
|
|
65
|
-
connect(function (newContentJson) {
|
|
66
|
-
appPromise.then((app) => {
|
|
67
|
-
app.ports.fromJsPort.send({ contentJson: newContentJson });
|
|
55
|
+
export function setup() {
|
|
56
|
+
prefetchedPages = [window.location.pathname];
|
|
57
|
+
initialLocationHash = document.location.hash.replace(/^#/, "");
|
|
58
|
+
const appPromise = new Promise(function (resolve, reject) {
|
|
59
|
+
document.addEventListener("DOMContentLoaded", (_) => {
|
|
60
|
+
resolve(loadContentAndInitializeApp());
|
|
68
61
|
});
|
|
69
62
|
});
|
|
70
|
-
|
|
63
|
+
userInit.load(appPromise);
|
|
71
64
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
if (typeof connect === "function") {
|
|
66
|
+
connect(function (bytesData) {
|
|
67
|
+
appPromise.then((app) => {
|
|
68
|
+
app.ports.hotReloadData.send(bytesData);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
77
71
|
}
|
|
78
|
-
};
|
|
79
72
|
|
|
80
|
-
/** @
|
|
81
|
-
|
|
73
|
+
/** @param {MouseEvent} event */
|
|
74
|
+
const trigger_prefetch = (event) => {
|
|
75
|
+
const a = find_anchor(/** @type {Node} */ (event.target));
|
|
76
|
+
if (a && a.href && a.hasAttribute("elm-pages:prefetch")) {
|
|
77
|
+
prefetchIfNeeded(a);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** @type {NodeJS.Timeout} */
|
|
82
|
+
let mousemove_timeout;
|
|
82
83
|
|
|
83
|
-
/** @param {MouseEvent} event */
|
|
84
|
-
const handle_mousemove = (event) => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
};
|
|
84
|
+
/** @param {MouseEvent} event */
|
|
85
|
+
const handle_mousemove = (event) => {
|
|
86
|
+
clearTimeout(mousemove_timeout);
|
|
87
|
+
mousemove_timeout = setTimeout(() => {
|
|
88
|
+
trigger_prefetch(event);
|
|
89
|
+
}, 20);
|
|
90
|
+
};
|
|
90
91
|
|
|
91
|
-
addEventListener("touchstart", trigger_prefetch);
|
|
92
|
-
addEventListener("mousemove", handle_mousemove);
|
|
92
|
+
addEventListener("touchstart", trigger_prefetch);
|
|
93
|
+
addEventListener("mousemove", handle_mousemove);
|
|
94
|
+
}
|
|
93
95
|
|
|
94
96
|
/**
|
|
95
97
|
* @param {Node} node
|
|
@@ -100,3 +102,5 @@ function find_anchor(node) {
|
|
|
100
102
|
while (node && node.nodeName.toUpperCase() !== "A") node = node.parentNode; // SVG <a> elements have a lowercase name
|
|
101
103
|
return /** @type {HTMLAnchorElement} */ (node);
|
|
102
104
|
}
|
|
105
|
+
|
|
106
|
+
setup();
|