elm-pages 3.0.0-beta.0 → 3.0.0-beta.10
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/README.md +10 -1
- package/codegen/elm-pages-codegen.js +39026 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25835 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/package.json +1 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
- package/generator/dead-code-review/elm.json +35 -0
- package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +304 -0
- package/generator/dead-code-review/src/ReviewConfig.elm +9 -0
- package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +673 -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/o.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +1 -1
- package/generator/src/SharedTemplate.elm +1 -1
- package/generator/src/build.js +75 -42
- package/generator/src/compatibility-key.js +1 -0
- package/generator/src/config.js +41 -0
- package/generator/src/dev-server.js +36 -56
- package/generator/src/generate-template-module-connector.js +2 -28
- package/generator/src/pre-render-html.js +31 -17
- package/generator/src/render.js +2 -0
- package/generator/src/seo-renderer.js +11 -4
- package/generator/src/vite-utils.js +78 -0
- package/generator/template/app/Api.elm +1 -1
- package/generator/template/app/Site.elm +6 -1
- package/package.json +5 -3
- package/src/ApiRoute.elm +0 -3
- package/src/DataSource/File.elm +1 -1
- package/src/DataSource/Internal/Request.elm +0 -5
- package/src/DataSource.elm +39 -31
- package/src/Form/Field.elm +1 -1
- package/src/Form.elm +1 -1
- package/src/Head/Seo.elm +16 -27
- package/src/Head.elm +126 -0
- package/src/HtmlPrinter.elm +7 -3
- package/src/Pages/Generate.elm +544 -102
- package/src/Pages/Internal/NotFoundReason.elm +3 -2
- package/src/Pages/Internal/Platform/Cli.elm +91 -27
- package/src/Pages/Internal/Platform/Cli.elm.bak +1276 -0
- package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
- package/src/Pages/Internal/Platform.elm +34 -27
- package/src/Pages/ProgramConfig.elm +6 -3
- package/src/Server/Session.elm +149 -83
- package/src/Server/SetCookie.elm +89 -31
package/generator/src/build.js
CHANGED
|
@@ -16,6 +16,9 @@ const { build } = require("vite");
|
|
|
16
16
|
const preRenderHtml = require("./pre-render-html.js");
|
|
17
17
|
const esbuild = require("esbuild");
|
|
18
18
|
const { createHash } = require("crypto");
|
|
19
|
+
const { merge_vite_configs } = require("./vite-utils.js");
|
|
20
|
+
const { resolveConfig } = require("./config.js");
|
|
21
|
+
const globby = require("globby");
|
|
19
22
|
|
|
20
23
|
let pool = [];
|
|
21
24
|
let pagesReady;
|
|
@@ -75,40 +78,31 @@ async function run(options) {
|
|
|
75
78
|
const generateCode = codegen.generate(options.base);
|
|
76
79
|
|
|
77
80
|
await generateCode;
|
|
81
|
+
|
|
82
|
+
const config = await resolveConfig();
|
|
78
83
|
await fsPromises.writeFile(
|
|
79
84
|
"elm-stuff/elm-pages/index.html",
|
|
80
|
-
preRenderHtml.templateHtml()
|
|
85
|
+
preRenderHtml.templateHtml(false, config.headTagsTemplate)
|
|
81
86
|
);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const viteConfig = config.vite || {};
|
|
96
|
-
|
|
97
|
-
const buildComplete = build({
|
|
98
|
-
configFile: false,
|
|
99
|
-
root: process.cwd(),
|
|
100
|
-
base: options.base,
|
|
101
|
-
ssr: false,
|
|
102
|
-
|
|
103
|
-
build: {
|
|
104
|
-
manifest: true,
|
|
105
|
-
outDir: "dist",
|
|
106
|
-
rollupOptions: {
|
|
107
|
-
input: "elm-stuff/elm-pages/index.html",
|
|
87
|
+
const viteConfig = merge_vite_configs(
|
|
88
|
+
{
|
|
89
|
+
configFile: false,
|
|
90
|
+
root: process.cwd(),
|
|
91
|
+
base: options.base,
|
|
92
|
+
ssr: false,
|
|
93
|
+
|
|
94
|
+
build: {
|
|
95
|
+
manifest: true,
|
|
96
|
+
outDir: "dist",
|
|
97
|
+
rollupOptions: {
|
|
98
|
+
input: "elm-stuff/elm-pages/index.html",
|
|
99
|
+
},
|
|
108
100
|
},
|
|
109
101
|
},
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
config.vite || {}
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const buildComplete = build(viteConfig);
|
|
112
106
|
const compileClientDone = compileElm(options);
|
|
113
107
|
await buildComplete;
|
|
114
108
|
await compileClientDone;
|
|
@@ -124,10 +118,25 @@ async function run(options) {
|
|
|
124
118
|
"dist/elm-stuff/elm-pages/index.html",
|
|
125
119
|
"utf-8"
|
|
126
120
|
);
|
|
127
|
-
const
|
|
121
|
+
const preloadFiles = [
|
|
122
|
+
`elm.${browserElmHash}.js`,
|
|
123
|
+
...Object.entries(manifest).map((entry) => entry[1].file),
|
|
124
|
+
].map((file) => path.join(options.base, file));
|
|
125
|
+
const userProcessedPreloads = preloadFiles.flatMap((file) => {
|
|
126
|
+
const userPreloadForFile = config.preloadTagForFile(file);
|
|
127
|
+
if (userPreloadForFile === true) {
|
|
128
|
+
return [defaultPreloadForFile(file)];
|
|
129
|
+
} else if (userPreloadForFile === false) {
|
|
130
|
+
return [];
|
|
131
|
+
} else if (typeof userPreloadForFile === "string") {
|
|
132
|
+
return [userPreloadForFile];
|
|
133
|
+
} else {
|
|
134
|
+
throw `I expected preloadTagForFile in elm-pages.config.mjs to return a string or boolean, but instead it returned: ${userPreloadForFile}`;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
128
137
|
|
|
129
138
|
const processedIndexTemplate = indexTemplate
|
|
130
|
-
.replace("<!-- PLACEHOLDER_PRELOADS -->",
|
|
139
|
+
.replace("<!-- PLACEHOLDER_PRELOADS -->", userProcessedPreloads.join(""))
|
|
131
140
|
.replace(
|
|
132
141
|
'<script defer src="/elm.js" type="text/javascript"></script>',
|
|
133
142
|
`<script defer src="/elm.${browserElmHash}.js" type="text/javascript"></script>`
|
|
@@ -146,21 +155,20 @@ async function run(options) {
|
|
|
146
155
|
metafile: true,
|
|
147
156
|
bundle: true,
|
|
148
157
|
watch: false,
|
|
149
|
-
logLevel: "
|
|
158
|
+
logLevel: "silent",
|
|
150
159
|
})
|
|
151
160
|
.then((result) => {
|
|
152
|
-
|
|
161
|
+
try {
|
|
162
|
+
global.portsFilePath = Object.keys(result.metafile.outputs)[0];
|
|
163
|
+
} catch (e) {}
|
|
153
164
|
})
|
|
154
165
|
.catch((error) => {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
console.warn("No port-data-source file found.");
|
|
162
|
-
} else {
|
|
163
|
-
console.error("Failed to load port-data-source file", error);
|
|
166
|
+
const portDataSourceFileFound =
|
|
167
|
+
globby.sync("./port-data-source.*").length > 0;
|
|
168
|
+
if (portDataSourceFileFound) {
|
|
169
|
+
// don't present error if there are no files matching port-data-source
|
|
170
|
+
// if there are files matching port-data-source, warn the user in case something went wrong loading it
|
|
171
|
+
console.error("Failed to start port-data-source watcher", error);
|
|
164
172
|
}
|
|
165
173
|
});
|
|
166
174
|
// TODO extract common code for compiling ports file?
|
|
@@ -627,6 +635,31 @@ async function runAdapter(adaptFn, processedIndexTemplate) {
|
|
|
627
635
|
}
|
|
628
636
|
}
|
|
629
637
|
|
|
638
|
+
// Source: https://github.com/vitejs/vite/blob/c53ffec3465d2d28d08d29ca61313469e03f5dd6/playground/ssr-vue/src/entry-server.js#L50-L68
|
|
639
|
+
/**
|
|
640
|
+
* @param {string} file
|
|
641
|
+
*/
|
|
642
|
+
function defaultPreloadForFile(file) {
|
|
643
|
+
if (file.endsWith(".js")) {
|
|
644
|
+
return `<link rel="modulepreload" crossorigin href="${file}">`;
|
|
645
|
+
} else if (file.endsWith(".css")) {
|
|
646
|
+
return `<link rel="preload" href="${file}" as="style">`;
|
|
647
|
+
} else if (file.endsWith(".woff")) {
|
|
648
|
+
return ` <link rel="preload" href="${file}" as="font" type="font/woff" crossorigin>`;
|
|
649
|
+
} else if (file.endsWith(".woff2")) {
|
|
650
|
+
return ` <link rel="preload" href="${file}" as="font" type="font/woff2" crossorigin>`;
|
|
651
|
+
} else if (file.endsWith(".gif")) {
|
|
652
|
+
return ` <link rel="preload" href="${file}" as="image" type="image/gif">`;
|
|
653
|
+
} else if (file.endsWith(".jpg") || file.endsWith(".jpeg")) {
|
|
654
|
+
return ` <link rel="preload" href="${file}" as="image" type="image/jpeg">`;
|
|
655
|
+
} else if (file.endsWith(".png")) {
|
|
656
|
+
return ` <link rel="preload" href="${file}" as="image" type="image/png">`;
|
|
657
|
+
} else {
|
|
658
|
+
// TODO
|
|
659
|
+
return "";
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
630
663
|
/** @typedef { { route : string; contentJson : string; head : SeoTag[]; html: string; body: string; } } FromElm */
|
|
631
664
|
/** @typedef {HeadTag | JsonLdTag} SeoTag */
|
|
632
665
|
/** @typedef {{ name: string; attributes: string[][]; type: 'head' }} HeadTag */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = { compatibilityKey: 1 };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
|
|
3
|
+
async function resolveConfig() {
|
|
4
|
+
const initialConfig = await await import(
|
|
5
|
+
path.join(process.cwd(), "elm-pages.config.mjs")
|
|
6
|
+
)
|
|
7
|
+
.then(async (elmPagesConfig) => {
|
|
8
|
+
return (
|
|
9
|
+
elmPagesConfig.default || {
|
|
10
|
+
headTagsTemplate: defaultHeadTagsTemplate,
|
|
11
|
+
}
|
|
12
|
+
);
|
|
13
|
+
})
|
|
14
|
+
.catch((error) => {
|
|
15
|
+
console.warn(
|
|
16
|
+
"No `elm-pages.config.mjs` file found. Using default config."
|
|
17
|
+
);
|
|
18
|
+
return {
|
|
19
|
+
headTagsTemplate: defaultHeadTagsTemplate,
|
|
20
|
+
vite: {},
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
preloadTagForFile: function () {
|
|
26
|
+
return true;
|
|
27
|
+
},
|
|
28
|
+
headTagsTemplate: defaultHeadTagsTemplate,
|
|
29
|
+
vite: {},
|
|
30
|
+
...initialConfig,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function defaultHeadTagsTemplate(context) {
|
|
35
|
+
return `
|
|
36
|
+
<link rel="stylesheet" href="/style.css" />
|
|
37
|
+
<meta name="generator" content="elm-pages v${context.cliVersion}" />
|
|
38
|
+
`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = { resolveConfig };
|
|
@@ -24,6 +24,10 @@ const busboy = require("busboy");
|
|
|
24
24
|
const { createServer: createViteServer } = require("vite");
|
|
25
25
|
const cliVersion = require("../../package.json").version;
|
|
26
26
|
const esbuild = require("esbuild");
|
|
27
|
+
const { merge_vite_configs } = require("./vite-utils.js");
|
|
28
|
+
const { templateHtml } = require("./pre-render-html.js");
|
|
29
|
+
const { resolveConfig } = require("./config.js");
|
|
30
|
+
const globby = require("globby");
|
|
27
31
|
|
|
28
32
|
/**
|
|
29
33
|
* @param {{ port: string; base: string; https: boolean; debug: boolean; }} options
|
|
@@ -117,27 +121,23 @@ async function start(options) {
|
|
|
117
121
|
watcher.add(sourceDirs);
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
root: process.cwd(),
|
|
138
|
-
base: options.base,
|
|
139
|
-
...viteConfig,
|
|
140
|
-
});
|
|
124
|
+
const config = await resolveConfig();
|
|
125
|
+
const vite = await createViteServer(
|
|
126
|
+
merge_vite_configs(
|
|
127
|
+
{
|
|
128
|
+
server: {
|
|
129
|
+
middlewareMode: "ssr",
|
|
130
|
+
base: options.base,
|
|
131
|
+
port: options.port,
|
|
132
|
+
},
|
|
133
|
+
configFile: false,
|
|
134
|
+
root: process.cwd(),
|
|
135
|
+
base: options.base,
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
config.vite
|
|
139
|
+
)
|
|
140
|
+
);
|
|
141
141
|
esbuild
|
|
142
142
|
.build({
|
|
143
143
|
entryPoints: ["./port-data-source"],
|
|
@@ -148,7 +148,7 @@ async function start(options) {
|
|
|
148
148
|
metafile: true,
|
|
149
149
|
bundle: true,
|
|
150
150
|
watch: true,
|
|
151
|
-
logLevel: "
|
|
151
|
+
logLevel: "silent",
|
|
152
152
|
|
|
153
153
|
outdir: ".elm-pages/compiled-ports",
|
|
154
154
|
entryNames: "[dir]/[name]-[hash]",
|
|
@@ -158,11 +158,13 @@ async function start(options) {
|
|
|
158
158
|
name: "example",
|
|
159
159
|
setup(build) {
|
|
160
160
|
build.onEnd((result) => {
|
|
161
|
-
|
|
161
|
+
try {
|
|
162
|
+
global.portsFilePath = Object.keys(result.metafile.outputs)[0];
|
|
162
163
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
clients.forEach((client) => {
|
|
165
|
+
client.response.write(`data: content.dat\n\n`);
|
|
166
|
+
});
|
|
167
|
+
} catch (e) {}
|
|
166
168
|
});
|
|
167
169
|
},
|
|
168
170
|
},
|
|
@@ -172,7 +174,13 @@ async function start(options) {
|
|
|
172
174
|
console.log("Watching port-data-source...");
|
|
173
175
|
})
|
|
174
176
|
.catch((error) => {
|
|
175
|
-
|
|
177
|
+
const portDataSourceFileFound =
|
|
178
|
+
globby.sync("./port-data-source.*").length > 0;
|
|
179
|
+
if (portDataSourceFileFound) {
|
|
180
|
+
// don't present error if there are no files matching port-data-source
|
|
181
|
+
// if there are files matching port-data-source, warn the user in case something went wrong loading it
|
|
182
|
+
console.error("Failed to start port-data-source watcher", error);
|
|
183
|
+
}
|
|
176
184
|
});
|
|
177
185
|
|
|
178
186
|
const app = connect()
|
|
@@ -459,35 +467,7 @@ async function start(options) {
|
|
|
459
467
|
}
|
|
460
468
|
case "html": {
|
|
461
469
|
try {
|
|
462
|
-
const template =
|
|
463
|
-
/*html*/
|
|
464
|
-
`<!DOCTYPE html>
|
|
465
|
-
<!-- ROOT --><html lang="en">
|
|
466
|
-
<head>
|
|
467
|
-
<script src="/hmr.js" type="text/javascript"></script>
|
|
468
|
-
<script src="/elm.js" type="text/javascript"></script>
|
|
469
|
-
<link rel="stylesheet" href="/style.css">
|
|
470
|
-
<link rel="stylesheet" href="/dev-style.css">
|
|
471
|
-
<script src="/elm-pages.js" type="module"></script>
|
|
472
|
-
<meta charset="UTF-8" />
|
|
473
|
-
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
474
|
-
<title><!-- PLACEHOLDER_TITLE --></title>
|
|
475
|
-
<meta name="generator" content="elm-pages v${cliVersion}" />
|
|
476
|
-
<meta name="mobile-web-app-capable" content="yes" />
|
|
477
|
-
<meta name="theme-color" content="#ffffff" />
|
|
478
|
-
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
479
|
-
<meta
|
|
480
|
-
name="apple-mobile-web-app-status-bar-style"
|
|
481
|
-
content="black-translucent"
|
|
482
|
-
/>
|
|
483
|
-
<!-- PLACEHOLDER_HEAD_AND_DATA -->
|
|
484
|
-
</head>
|
|
485
|
-
<body>
|
|
486
|
-
<div data-url="" display="none"></div>
|
|
487
|
-
<!-- PLACEHOLDER_HTML -->
|
|
488
|
-
</body>
|
|
489
|
-
</html>
|
|
490
|
-
`;
|
|
470
|
+
const template = templateHtml(true, config.headTagsTemplate);
|
|
491
471
|
const processedTemplate = await vite.transformIndexHtml(
|
|
492
472
|
req.originalUrl,
|
|
493
473
|
template
|
|
@@ -63,30 +63,10 @@ async function generateTemplateModuleConnector(basePath, phase) {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
async function runElmCodegenCli(templates, basePath, phase) {
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
await compileCliApp(
|
|
69
|
-
// { debug: true },
|
|
70
|
-
{},
|
|
71
|
-
`Generate.elm`,
|
|
72
|
-
path.join(process.cwd(), "elm-stuff/elm-pages-codegen.js"),
|
|
73
|
-
path.join(__dirname, "../../codegen"),
|
|
74
|
-
|
|
75
|
-
path.join(process.cwd(), "elm-stuff/elm-pages-codegen.js")
|
|
76
|
-
);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
console.log(restoreColorSafe(error));
|
|
79
|
-
process.exit(1);
|
|
80
|
-
// throw error;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// TODO use uncached require here to prevent stale code from running
|
|
66
|
+
const filePath = path.join(__dirname, `../../codegen/elm-pages-codegen.js`);
|
|
84
67
|
|
|
85
68
|
const promise = new Promise((resolve, reject) => {
|
|
86
|
-
const elmPagesCodegen = require(
|
|
87
|
-
process.cwd(),
|
|
88
|
-
"./elm-stuff/elm-pages-codegen.js"
|
|
89
|
-
)).Elm.Generate;
|
|
69
|
+
const elmPagesCodegen = require(filePath).Elm.Generate;
|
|
90
70
|
|
|
91
71
|
const app = elmPagesCodegen.init({
|
|
92
72
|
flags: { templates: templates, basePath, phase },
|
|
@@ -102,12 +82,10 @@ async function runElmCodegenCli(templates, basePath, phase) {
|
|
|
102
82
|
}
|
|
103
83
|
});
|
|
104
84
|
const filesToGenerate = await promise;
|
|
105
|
-
console.dir(filesToGenerate.map((file) => file.path));
|
|
106
85
|
|
|
107
86
|
return filesToGenerate;
|
|
108
87
|
}
|
|
109
88
|
|
|
110
|
-
|
|
111
89
|
/**
|
|
112
90
|
*
|
|
113
91
|
* @param {string[][]} templates
|
|
@@ -173,8 +151,6 @@ function sortScore(name) {
|
|
|
173
151
|
);
|
|
174
152
|
}
|
|
175
153
|
|
|
176
|
-
|
|
177
|
-
|
|
178
154
|
function fetcherModule(name) {
|
|
179
155
|
let moduleName = name.join(".");
|
|
180
156
|
// TODO need to account for splat routes/etc.
|
|
@@ -246,7 +222,6 @@ submit toMsg options =
|
|
|
246
222
|
`;
|
|
247
223
|
}
|
|
248
224
|
|
|
249
|
-
|
|
250
225
|
/**
|
|
251
226
|
* Convert Strings from camelCase to kebab-case
|
|
252
227
|
* @param {string} input
|
|
@@ -256,5 +231,4 @@ function camelToKebab(input) {
|
|
|
256
231
|
return input.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
257
232
|
}
|
|
258
233
|
|
|
259
|
-
|
|
260
234
|
module.exports = { generateTemplateModuleConnector, sortTemplates };
|
|
@@ -17,28 +17,32 @@ function wrapHtml(basePath, fromElm, contentDatPayload) {
|
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* @param {boolean} devMode
|
|
22
|
+
* @param {(context: {cliVersion: string;}) => string} userHeadTagsTemplate
|
|
23
|
+
*/
|
|
24
|
+
function templateHtml(devMode, userHeadTagsTemplate) {
|
|
21
25
|
return /* html */ `<!DOCTYPE html>
|
|
22
26
|
<!-- ROOT --><html lang="en">
|
|
23
27
|
<head>
|
|
24
|
-
<!-- PLACEHOLDER_PRELOADS -->
|
|
25
|
-
<script defer src="/elm.js" type="text/javascript"></script>
|
|
26
|
-
<script defer src="${path.join(
|
|
27
|
-
__dirname,
|
|
28
|
-
"../static-code/elm-pages.js"
|
|
29
|
-
)}" type="module"></script>
|
|
30
|
-
<link rel="stylesheet" href="/style.css" />
|
|
31
28
|
<meta charset="UTF-8" />
|
|
32
|
-
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
33
29
|
<title><!-- PLACEHOLDER_TITLE --></title>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
${
|
|
31
|
+
devMode
|
|
32
|
+
? `<script src="/hmr.js" type="text/javascript"></script>
|
|
33
|
+
<link rel="stylesheet" href="/dev-style.css">`
|
|
34
|
+
: `<!-- PLACEHOLDER_PRELOADS -->`
|
|
35
|
+
}
|
|
36
|
+
<script defer src="/elm.js" type="text/javascript"></script>
|
|
37
|
+
${
|
|
38
|
+
devMode
|
|
39
|
+
? `<script src="/elm-pages.js" type="module"></script>`
|
|
40
|
+
: `<script defer src="${path.join(
|
|
41
|
+
__dirname,
|
|
42
|
+
"../static-code/elm-pages.js"
|
|
43
|
+
)}" type="module"></script>`
|
|
44
|
+
}
|
|
45
|
+
${indent(userHeadTagsTemplate({ cliVersion }))}
|
|
42
46
|
<!-- PLACEHOLDER_HEAD_AND_DATA -->
|
|
43
47
|
</head>
|
|
44
48
|
<body>
|
|
@@ -48,6 +52,16 @@ function templateHtml() {
|
|
|
48
52
|
</html>`;
|
|
49
53
|
}
|
|
50
54
|
|
|
55
|
+
/**
|
|
56
|
+
* @param {string} snippet
|
|
57
|
+
*/
|
|
58
|
+
function indent(snippet) {
|
|
59
|
+
return snippet
|
|
60
|
+
.split("\n")
|
|
61
|
+
.map((line) => ` ${line}`)
|
|
62
|
+
.join("\n");
|
|
63
|
+
}
|
|
64
|
+
|
|
51
65
|
/**
|
|
52
66
|
* @param {string} processedTemplate
|
|
53
67
|
*/
|
package/generator/src/render.js
CHANGED
|
@@ -9,6 +9,7 @@ const preRenderHtml = require("./pre-render-html.js");
|
|
|
9
9
|
const { lookupOrPerform } = require("./request-cache.js");
|
|
10
10
|
const kleur = require("kleur");
|
|
11
11
|
const cookie = require("cookie-signature");
|
|
12
|
+
const { compatibilityKey } = require("./compatibility-key.js");
|
|
12
13
|
kleur.enabled = true;
|
|
13
14
|
|
|
14
15
|
process.on("unhandledRejection", (error) => {
|
|
@@ -98,6 +99,7 @@ function runElmApp(
|
|
|
98
99
|
app = elmModule.Elm.Main.init({
|
|
99
100
|
flags: {
|
|
100
101
|
mode,
|
|
102
|
+
compatibilityKey,
|
|
101
103
|
request: {
|
|
102
104
|
payload: modifiedRequest,
|
|
103
105
|
kind: "single-page",
|
|
@@ -43,11 +43,16 @@ function headTag(rootModifiers) {
|
|
|
43
43
|
|
|
44
44
|
function toString(/** @type { SeoTag[] } */ tags) {
|
|
45
45
|
return tags
|
|
46
|
-
.
|
|
46
|
+
.flatMap((headTag) => {
|
|
47
47
|
if (headTag.type === "head") {
|
|
48
|
-
return appendTag(headTag);
|
|
48
|
+
return [appendTag(headTag)];
|
|
49
49
|
} else if (headTag.type === "json-ld") {
|
|
50
|
-
return appendJsonLdTag(headTag);
|
|
50
|
+
return [appendJsonLdTag(headTag)];
|
|
51
|
+
} else if (headTag.type === "stripped") {
|
|
52
|
+
console.warn(
|
|
53
|
+
`WARNING: Head.nonLoadingTag value ignored because it used a loading tag: ${headTag.message}`
|
|
54
|
+
);
|
|
55
|
+
return [];
|
|
51
56
|
} else {
|
|
52
57
|
throw new Error(`Unknown tag type ${JSON.stringify(headTag)}`);
|
|
53
58
|
}
|
|
@@ -55,7 +60,7 @@ function toString(/** @type { SeoTag[] } */ tags) {
|
|
|
55
60
|
.join("");
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
/** @typedef {HeadTag | JsonLdTag} SeoTag */
|
|
63
|
+
/** @typedef {HeadTag | JsonLdTag | StrippedTag} SeoTag */
|
|
59
64
|
|
|
60
65
|
/** @typedef {{ name: string; attributes: string[][]; type: 'head' }} HeadTag */
|
|
61
66
|
function appendTag(/** @type {HeadTag} */ tagDetails) {
|
|
@@ -66,6 +71,8 @@ function appendTag(/** @type {HeadTag} */ tagDetails) {
|
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
/** @typedef {{ contents: Object; type: 'json-ld' }} JsonLdTag */
|
|
74
|
+
/** @typedef {{ message: string; type: 'stripped' }} StrippedTag */
|
|
75
|
+
|
|
69
76
|
function appendJsonLdTag(/** @type {JsonLdTag} */ tagDetails) {
|
|
70
77
|
return `<script type="application/ld+json">
|
|
71
78
|
${JSON.stringify(tagDetails.contents)}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** This code is from https://github.com/sveltejs/kit/blob/3b457f67d4d7c59fc63bb3f600a490e4dacc2e62/packages/kit/src/exports/vite/utils.js */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {...import('vite').UserConfig} configs
|
|
5
|
+
* @returns {import('vite').UserConfig}
|
|
6
|
+
*/
|
|
7
|
+
function merge_vite_configs(...configs) {
|
|
8
|
+
return deep_merge(
|
|
9
|
+
...configs.map((config) => ({
|
|
10
|
+
...config,
|
|
11
|
+
resolve: {
|
|
12
|
+
...config.resolve,
|
|
13
|
+
alias: normalize_alias(config.resolve?.alias || {}),
|
|
14
|
+
},
|
|
15
|
+
}))
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Takes zero or more objects and returns a new object that has all the values
|
|
21
|
+
* deeply merged together. None of the original objects will be mutated at any
|
|
22
|
+
* level, and the returned object will have no references to the original
|
|
23
|
+
* objects at any depth. If there's a conflict the last one wins, except for
|
|
24
|
+
* arrays which will be combined.
|
|
25
|
+
* @param {...Object} objects
|
|
26
|
+
* @returns {Record<string, any>} the merged object
|
|
27
|
+
*/
|
|
28
|
+
function deep_merge(...objects) {
|
|
29
|
+
const result = {};
|
|
30
|
+
/** @type {string[]} */
|
|
31
|
+
objects.forEach((o) => merge_into(result, o));
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* normalize kit.vite.resolve.alias as an array
|
|
37
|
+
* @param {import('vite').AliasOptions} o
|
|
38
|
+
* @returns {import('vite').Alias[]}
|
|
39
|
+
*/
|
|
40
|
+
function normalize_alias(o) {
|
|
41
|
+
if (Array.isArray(o)) return o;
|
|
42
|
+
return Object.entries(o).map(([find, replacement]) => ({
|
|
43
|
+
find,
|
|
44
|
+
replacement,
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Merges b into a, recursively, mutating a.
|
|
50
|
+
* @param {Record<string, any>} a
|
|
51
|
+
* @param {Record<string, any>} b
|
|
52
|
+
*/
|
|
53
|
+
function merge_into(a, b) {
|
|
54
|
+
/**
|
|
55
|
+
* Checks for "plain old Javascript object", typically made as an object
|
|
56
|
+
* literal. Excludes Arrays and built-in types like Buffer.
|
|
57
|
+
* @param {any} x
|
|
58
|
+
*/
|
|
59
|
+
const is_plain_object = (x) =>
|
|
60
|
+
typeof x === "object" && x.constructor === Object;
|
|
61
|
+
|
|
62
|
+
for (const prop in b) {
|
|
63
|
+
if (is_plain_object(b[prop])) {
|
|
64
|
+
if (!is_plain_object(a[prop])) {
|
|
65
|
+
a[prop] = {};
|
|
66
|
+
}
|
|
67
|
+
merge_into(a[prop], b[prop]);
|
|
68
|
+
} else if (Array.isArray(b[prop])) {
|
|
69
|
+
if (!Array.isArray(a[prop])) {
|
|
70
|
+
a[prop] = [];
|
|
71
|
+
}
|
|
72
|
+
a[prop].push(...b[prop]);
|
|
73
|
+
} else {
|
|
74
|
+
a[prop] = b[prop];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
module.exports = { merge_vite_configs };
|
|
@@ -14,6 +14,11 @@ config =
|
|
|
14
14
|
|
|
15
15
|
head : DataSource (List Head.Tag)
|
|
16
16
|
head =
|
|
17
|
-
[ Head.
|
|
17
|
+
[ Head.metaName "viewport" (Head.raw "width=device-width,initial-scale=1")
|
|
18
|
+
, Head.metaName "mobile-web-app-capable" (Head.raw "yes")
|
|
19
|
+
, Head.metaName "theme-color" (Head.raw "#ffffff")
|
|
20
|
+
, Head.metaName "apple-mobile-web-app-capable" (Head.raw "yes")
|
|
21
|
+
, Head.metaName "apple-mobile-web-app-status-bar-style" (Head.raw "black-translucent")
|
|
22
|
+
, Head.sitemapLink "/sitemap.xml"
|
|
18
23
|
]
|
|
19
24
|
|> DataSource.succeed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elm-pages",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.10",
|
|
4
4
|
"homepage": "https://elm-pages.com",
|
|
5
5
|
"moduleResolution": "node",
|
|
6
6
|
"description": "Type-safe static sites, written in pure elm with your own custom elm-markup syntax.",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"test": "./test.sh",
|
|
11
11
|
"test:snapshot": "(cd examples/escaping && npm install && npm test) && (cd examples/base-path && npm install && npm test)",
|
|
12
12
|
"cypress": "npm start & cypress run",
|
|
13
|
-
"
|
|
13
|
+
"build:generator": "elm-codegen install && (cd codegen && lamdera make Generate.elm --output elm-pages-codegen.js)",
|
|
14
14
|
"review": "elm-review"
|
|
15
15
|
},
|
|
16
16
|
"repository": "https://github.com/dillonkearns/elm-pages",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"object-hash": "^2.2.0",
|
|
46
46
|
"serve-static": "^1.15.0",
|
|
47
47
|
"terser": "^5.14.2",
|
|
48
|
-
"vite": "^3.
|
|
48
|
+
"vite": "^3.1.8",
|
|
49
49
|
"which": "^2.0.2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
@@ -68,7 +68,9 @@
|
|
|
68
68
|
"files": [
|
|
69
69
|
"generator/src/",
|
|
70
70
|
"generator/review/",
|
|
71
|
+
"generator/dead-code-review/",
|
|
71
72
|
"src/",
|
|
73
|
+
"codegen/elm-pages-codegen.js",
|
|
72
74
|
"generator/template/",
|
|
73
75
|
"generator/static-code/"
|
|
74
76
|
],
|