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.
Files changed (62) hide show
  1. package/README.md +10 -1
  2. package/codegen/elm-pages-codegen.js +39026 -0
  3. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  5. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmi +0 -0
  6. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  12. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  13. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock +0 -0
  14. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  15. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -0
  16. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
  17. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25835 -0
  18. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
  19. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
  20. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/package.json +1 -0
  21. package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
  22. package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
  23. package/generator/dead-code-review/elm.json +35 -0
  24. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +304 -0
  25. package/generator/dead-code-review/src/ReviewConfig.elm +9 -0
  26. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +673 -0
  27. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  28. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  29. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  30. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  31. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +1 -1
  32. package/generator/src/SharedTemplate.elm +1 -1
  33. package/generator/src/build.js +75 -42
  34. package/generator/src/compatibility-key.js +1 -0
  35. package/generator/src/config.js +41 -0
  36. package/generator/src/dev-server.js +36 -56
  37. package/generator/src/generate-template-module-connector.js +2 -28
  38. package/generator/src/pre-render-html.js +31 -17
  39. package/generator/src/render.js +2 -0
  40. package/generator/src/seo-renderer.js +11 -4
  41. package/generator/src/vite-utils.js +78 -0
  42. package/generator/template/app/Api.elm +1 -1
  43. package/generator/template/app/Site.elm +6 -1
  44. package/package.json +5 -3
  45. package/src/ApiRoute.elm +0 -3
  46. package/src/DataSource/File.elm +1 -1
  47. package/src/DataSource/Internal/Request.elm +0 -5
  48. package/src/DataSource.elm +39 -31
  49. package/src/Form/Field.elm +1 -1
  50. package/src/Form.elm +1 -1
  51. package/src/Head/Seo.elm +16 -27
  52. package/src/Head.elm +126 -0
  53. package/src/HtmlPrinter.elm +7 -3
  54. package/src/Pages/Generate.elm +544 -102
  55. package/src/Pages/Internal/NotFoundReason.elm +3 -2
  56. package/src/Pages/Internal/Platform/Cli.elm +91 -27
  57. package/src/Pages/Internal/Platform/Cli.elm.bak +1276 -0
  58. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  59. package/src/Pages/Internal/Platform.elm +34 -27
  60. package/src/Pages/ProgramConfig.elm +6 -3
  61. package/src/Server/Session.elm +149 -83
  62. package/src/Server/SetCookie.elm +89 -31
@@ -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
- const config = await import(
84
- path.join(process.cwd(), "elm-pages.config.mjs")
85
- )
86
- .then(async (elmPagesConfig) => {
87
- return elmPagesConfig.default || {};
88
- })
89
- .catch((error) => {
90
- console.warn(
91
- "No `elm-pages.config.mjs` file found. Using default config."
92
- );
93
- return {};
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
- ...viteConfig,
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 preloads = `<link rel="modulepreload" href="/${manifest["elm-stuff/elm-pages/index.html"]["file"]}" />`;
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 -->", 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: "error",
158
+ logLevel: "silent",
150
159
  })
151
160
  .then((result) => {
152
- global.portsFilePath = Object.keys(result.metafile.outputs)[0];
161
+ try {
162
+ global.portsFilePath = Object.keys(result.metafile.outputs)[0];
163
+ } catch (e) {}
153
164
  })
154
165
  .catch((error) => {
155
- if (
156
- error.errors.length === 1 &&
157
- error.errors[0].text.includes(
158
- `Could not resolve "./port-data-source"`
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 viteConfig = await import(
121
- path.join(process.cwd(), "elm-pages.config.mjs")
122
- )
123
- .then(async (elmPagesConfig) => {
124
- return elmPagesConfig.default.vite || {};
125
- })
126
- .catch((error) => {
127
- console.warn(
128
- kleur.yellow(
129
- "No `elm-pages.config.mjs` file found. Using default config."
130
- )
131
- );
132
- return {};
133
- });
134
- const vite = await createViteServer({
135
- server: { middlewareMode: "ssr", base: options.base, port: options.port },
136
- configFile: false,
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: "error",
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
- global.portsFilePath = Object.keys(result.metafile.outputs)[0];
161
+ try {
162
+ global.portsFilePath = Object.keys(result.metafile.outputs)[0];
162
163
 
163
- clients.forEach((client) => {
164
- client.response.write(`data: content.dat\n\n`);
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
- console.error("Failed to start port-data-source watcher", error);
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
- // await runElmCodegenInstall();
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(path.join(
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
- function templateHtml() {
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
- <meta name="generator" content="elm-pages v${cliVersion}" />
35
- <meta name="mobile-web-app-capable" content="yes" />
36
- <meta name="theme-color" content="#ffffff" />
37
- <meta name="apple-mobile-web-app-capable" content="yes" />
38
- <meta
39
- name="apple-mobile-web-app-status-bar-style"
40
- content="black-translucent"
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
  */
@@ -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
- .map((headTag) => {
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 };
@@ -9,7 +9,7 @@ import Route exposing (Route)
9
9
 
10
10
  routes :
11
11
  DataSource (List Route)
12
- -> (Html Never -> String)
12
+ -> (Maybe { indent : Int, newLines : Bool } -> Html Never -> String)
13
13
  -> List (ApiRoute ApiRoute.Response)
14
14
  routes getStaticRoutes htmlToString =
15
15
  []
@@ -14,6 +14,11 @@ config =
14
14
 
15
15
  head : DataSource (List Head.Tag)
16
16
  head =
17
- [ Head.sitemapLink "/sitemap.xml"
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.0",
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
- "prepare": "elm-codegen install",
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.0.9",
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
  ],