@marko/vite 5.0.5 → 5.0.7

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.
@@ -1,5 +1,5 @@
1
- import type * as vite from "vite";
2
1
  import * as compiler from "@marko/compiler";
2
+ import type * as vite from "vite";
3
3
  type ESBuildOptions = Exclude<vite.DepOptimizationConfig["esbuildOptions"], undefined>;
4
4
  type ESBuildPlugin = Exclude<ESBuildOptions["plugins"], undefined>[number];
5
5
  export default function esbuildPlugin(config: compiler.Config): ESBuildPlugin;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type * as vite from "vite";
2
1
  import * as compiler from "@marko/compiler";
2
+ import type * as vite from "vite";
3
3
  export declare namespace API {
4
4
  type getMarkoAssetCodeForEntry = (id: string) => string | void;
5
5
  }
package/dist/index.mjs CHANGED
@@ -1,156 +1,326 @@
1
1
  // src/index.ts
2
2
  import * as compiler2 from "@marko/compiler";
3
+ import anyMatch from "anymatch";
4
+ import crypto from "crypto";
5
+ import glob2 from "fast-glob";
3
6
  import fs4 from "fs";
4
7
  import path6 from "path";
5
- import crypto from "crypto";
6
- import anyMatch from "anymatch";
7
8
  import { pathToFileURL } from "url";
8
9
 
9
- // src/server-entry-template.ts
10
- import path from "path";
10
+ // src/babel-plugin-cjs-interop.ts
11
+ import * as t from "@babel/types";
11
12
 
12
- // src/render-assets-runtime.ts
13
- var renderAssetsRuntimeId = "\0marko-render-assets.mjs";
14
- function getRenderAssetsRuntime(opts) {
15
- return `${opts.basePathVar && opts.isBuild ? `const base = globalThis.${opts.basePathVar};
16
- if (typeof base !== "string") throw new Error("${opts.basePathVar} must be defined when using basePathVar.");
17
- if (!base.endsWith("/")) throw new Error("${opts.basePathVar} must end with a '/' when using basePathVar.");` : "const base = import.meta.env.BASE_URL;"}
18
- export function addAssets(g, newEntries) {
19
- const entries = g.___viteEntries;
20
- if (entries) {
21
- g.___viteEntries = entries.concat(newEntries);
22
- return true;
13
+ // src/resolve.ts
14
+ import fs from "fs";
15
+ import path from "path";
16
+ import Resolve from "resolve";
17
+ import { exports } from "resolve.exports";
18
+ var exportsMainFile = `__package_exports__`;
19
+ var modulePathReg = /^.*[/\\]node_modules[/\\](?:@[^/\\]+[/\\])?[^/\\]+[/\\]/;
20
+ var cjsModuleLookup = /* @__PURE__ */ new Map();
21
+ function isCJSModule(id) {
22
+ const modulePath = modulePathReg.exec(id)?.[0];
23
+ if (modulePath) {
24
+ const pkgPath = modulePath + "package.json";
25
+ let isCJS = cjsModuleLookup.get(pkgPath);
26
+ if (isCJS === void 0) {
27
+ try {
28
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
29
+ isCJS = pkg.type !== "module" && !pkg.exports;
30
+ } catch {
31
+ isCJS = false;
32
+ }
33
+ cjsModuleLookup.set(pkgPath, isCJS);
34
+ }
35
+ return isCJS;
23
36
  }
24
- g.___viteEntries = newEntries;
25
- g.___viteRenderAssets = renderAssets;
26
- g.___viteInjectAttrs = g.cspNonce
27
- ? \` nonce="\${g.cspNonce.replace(/"/g, "&#39;")}"\`
28
- : "";
29
- g.___viteSeenIds = new Set();
30
- ${opts.runtimeId ? `g.runtimeId = ${JSON.stringify(opts.runtimeId)};` : ""}
37
+ return false;
31
38
  }
32
-
33
- function renderAssets(slot) {
34
- const entries = this.___viteEntries;
35
- let html = "";
36
-
37
- if (entries) {
38
- const seenIds = this.___viteSeenIds;
39
- const slotWrittenEntriesKey = \`___viteWrittenEntries-\${slot}\`;
40
- const lastWrittenEntry = this[slotWrittenEntriesKey] || 0;
41
- const writtenEntries = (this[slotWrittenEntriesKey] = entries.length);
42
-
43
- if(!this.___flushedMBP && slot !== "head-prepend") {
44
- this.___flushedMBP = true;
45
-
46
- html += \`<script\${this.___viteInjectAttrs}>${opts.runtimeId ? `$mbp_${opts.runtimeId}` : "$mbp"}=\${JSON.stringify(base)}</script>\`
39
+ function resolve(id, from, extensions, conditions) {
40
+ return Resolve.sync(id, {
41
+ basedir: path.dirname(from),
42
+ filename: from,
43
+ pathFilter,
44
+ packageFilter,
45
+ extensions
46
+ });
47
+ function pathFilter(pkg, pkgFile, relativePath) {
48
+ cjsModuleLookup.set(pkgFile, pkg.type !== "module" && !pkg.exports);
49
+ if (pkg.exports) {
50
+ return exports(
51
+ pkg,
52
+ relativePath === exportsMainFile ? "." : relativePath,
53
+ {
54
+ conditions
55
+ }
56
+ )?.[0];
47
57
  }
58
+ return relativePath;
59
+ }
60
+ }
61
+ function packageFilter(pkg) {
62
+ if (pkg.exports) {
63
+ pkg.main = exportsMainFile;
64
+ }
65
+ return pkg;
66
+ }
48
67
 
49
- for (let i = lastWrittenEntry; i < writtenEntries; i++) {
50
- let entry = entries[i];
51
-
52
- if (typeof entry === "string") {
53
- entry = __MARKO_MANIFEST__[entry] || {};
54
- }${opts.isBuild ? "" : ` else if (slot === "head") {
55
- // In dev mode we have is a list entries of the top level modules that need to be imported.
56
- // To avoid FOUC we will hide the page until all of these modules are loaded.
57
- const { preload } = entry;
58
- if (preload) {
59
- html += \`<script class=marko-vite-preload async blocking=render type=module\${this.___viteInjectAttrs}>\`;
60
- for (const id of preload) {
61
- html += \`import \${JSON.stringify(base + id)};\`;
68
+ // src/babel-plugin-cjs-interop.ts
69
+ function plugin(options) {
70
+ return {
71
+ name: "marko-import-interop",
72
+ visitor: {
73
+ ImportDeclaration(path7) {
74
+ if (!path7.node.specifiers.length || /\.(?:mjs|marko)$|\?/.test(path7.node.source.value) || options.filter?.(path7.node.source.value) === false) {
75
+ return;
76
+ }
77
+ try {
78
+ const resolved = resolve(
79
+ path7.node.source.value,
80
+ path7.hub.file.opts.filename,
81
+ options.extensions,
82
+ options.conditions
83
+ );
84
+ if (!/\.c?js$/.test(resolved) || !isCJSModule(resolved)) {
85
+ return;
62
86
  }
63
-
64
- html += "document.querySelectorAll('.marko-vite-preload').forEach((el) => el.remove());";
65
- html += "document.documentElement.style.visibility='';";
66
- html +=
67
- "if(document.documentElement.getAttribute('style')==='')document.documentElement.removeAttribute('style');";
68
- html += \`</script><script class=marko-vite-preload\${this.___viteInjectAttrs}>document.documentElement.style.visibility='hidden'</script>\`;
87
+ } catch (_) {
88
+ return;
69
89
  }
70
- }`}
71
-
72
- const parts = entry[slot];
73
-
74
- if (parts) {
75
- for (let i = 0; i < parts.length; i++) {
76
- const part = parts[i];
77
- switch (part) {
78
- case 0: /** InjectType.AssetAttrs */
79
- html += this.___viteInjectAttrs;
80
- break;
81
- case 1: /** InjectType.PublicPath */
82
- html += base;
83
- break;
84
- case 2: /** InjectType.Dedupe */ {
85
- const id = parts[++i];
86
- const skipParts = parts[++i];
87
- if (seenIds.has(id)) {
88
- i += skipParts;
89
- } else {
90
- seenIds.add(id);
91
- }
92
- break;
93
- }
94
- default:
95
- html += part;
96
- break;
90
+ let namespaceId;
91
+ let defaultImportId;
92
+ let imports;
93
+ for (const s of path7.node.specifiers) {
94
+ if (t.isImportSpecifier(s)) {
95
+ (imports ||= []).push({
96
+ name: t.isStringLiteral(s.imported) ? s.imported.value : s.imported.name,
97
+ alias: s.local.name
98
+ });
99
+ } else if (t.isImportDefaultSpecifier(s)) {
100
+ defaultImportId = s.local;
101
+ } else if (t.isImportNamespaceSpecifier(s)) {
102
+ namespaceId = s.local;
97
103
  }
98
104
  }
105
+ const rawImport = path7.scope.generateUidIdentifier(
106
+ namespaceId?.name || defaultImportId?.name || path7.node.source.value
107
+ );
108
+ path7.node.specifiers = [t.importNamespaceSpecifier(rawImport)];
109
+ if (defaultImportId) {
110
+ path7.insertAfter(
111
+ t.variableDeclaration("const", [
112
+ t.variableDeclarator(
113
+ t.objectPattern([
114
+ t.objectProperty(t.identifier("default"), defaultImportId)
115
+ ]),
116
+ t.conditionalExpression(
117
+ t.optionalMemberExpression(
118
+ t.memberExpression(rawImport, t.identifier("default")),
119
+ t.identifier("__esModule"),
120
+ false,
121
+ true
122
+ ),
123
+ t.memberExpression(rawImport, t.identifier("default")),
124
+ rawImport
125
+ )
126
+ )
127
+ ])
128
+ );
129
+ }
130
+ if (namespaceId) {
131
+ path7.insertAfter(
132
+ t.variableDeclaration("const", [
133
+ t.variableDeclarator(
134
+ namespaceId,
135
+ t.conditionalExpression(
136
+ t.optionalMemberExpression(
137
+ rawImport,
138
+ t.identifier("__esModule"),
139
+ false,
140
+ true
141
+ ),
142
+ rawImport,
143
+ t.memberExpression(rawImport, t.identifier("default"))
144
+ )
145
+ )
146
+ ])
147
+ );
148
+ }
149
+ if (imports) {
150
+ path7.insertAfter(
151
+ t.variableDeclaration("const", [
152
+ t.variableDeclarator(
153
+ t.objectPattern(
154
+ imports.map(
155
+ ({ name, alias }) => t.objectProperty(
156
+ t.identifier(name),
157
+ t.identifier(alias),
158
+ false,
159
+ name === alias
160
+ )
161
+ )
162
+ ),
163
+ t.conditionalExpression(
164
+ t.optionalMemberExpression(
165
+ rawImport,
166
+ t.identifier("__esModule"),
167
+ false,
168
+ true
169
+ ),
170
+ rawImport,
171
+ t.memberExpression(rawImport, t.identifier("default"))
172
+ )
173
+ )
174
+ ])
175
+ );
176
+ }
99
177
  }
100
178
  }
101
- }
102
-
103
- return html;
104
- }
105
- `;
179
+ };
106
180
  }
107
181
 
108
- // src/server-entry-template.ts
109
- var server_entry_template_default = async (opts) => {
110
- const addAssetsCall = `addAssets($global, [${opts.entryData.join(",")}])`;
111
- const fileNameStr = JSON.stringify(`./${path.basename(opts.fileName)}`);
112
- return `import template from ${fileNameStr};
113
- export * from ${fileNameStr};
114
- import { addAssets } from "${renderAssetsRuntimeId}";
115
-
116
- ${opts.tagsAPI ? `<const/writeSync=${addAssetsCall}/>` : `$ const writeSync = ${addAssetsCall};`}
117
-
118
- ${opts.tagsAPI ? "<if=writeSync>" : "<if(writeSync)>"}
119
- $!{
120
- $global.___viteRenderAssets("head-prepend") +
121
- $global.___viteRenderAssets("head") +
122
- $global.___viteRenderAssets("body-prepend")
123
- }
124
- </>
125
- <else>
126
- <__flush_here_and_after__>
127
- $!{
128
- $global.___viteRenderAssets("head-prepend") +
129
- $global.___viteRenderAssets("head") +
130
- $global.___viteRenderAssets("body-prepend")
182
+ // src/esbuild-plugin.ts
183
+ import * as compiler from "@marko/compiler";
184
+ import fs2 from "fs";
185
+ import path2 from "path";
186
+ var markoErrorRegExp = /^(.+?)(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
187
+ function esbuildPlugin(config) {
188
+ return {
189
+ name: "marko",
190
+ async setup(build) {
191
+ const { platform = "browser" } = build.initialOptions;
192
+ const isScan = build.initialOptions.plugins?.some(
193
+ (v) => v.name === "vite:dep-scan"
194
+ );
195
+ const virtualFiles2 = /* @__PURE__ */ new Map();
196
+ const finalConfig = {
197
+ ...config,
198
+ output: platform === "browser" ? "dom" : "html",
199
+ resolveVirtualDependency(from, dep) {
200
+ virtualFiles2.set(path2.join(from, "..", dep.virtualPath), dep);
201
+ return dep.virtualPath;
202
+ }
203
+ };
204
+ const scanConfig = {
205
+ ...finalConfig,
206
+ output: "hydrate"
207
+ };
208
+ build.onResolve({ filter: /\.marko\./ }, (args) => {
209
+ return {
210
+ namespace: "marko:virtual",
211
+ path: path2.resolve(args.resolveDir, args.path),
212
+ external: isScan
213
+ };
214
+ });
215
+ build.onLoad(
216
+ { filter: /\.marko\./, namespace: "marko:virtual" },
217
+ (args) => ({
218
+ contents: virtualFiles2.get(args.path).code,
219
+ loader: path2.extname(args.path).slice(1)
220
+ })
221
+ );
222
+ build.onLoad({ filter: /\.marko$/ }, async (args) => {
223
+ try {
224
+ const { code, meta } = await compiler.compileFile(
225
+ args.path,
226
+ isScan && args.namespace === "" ? scanConfig : finalConfig
227
+ );
228
+ return {
229
+ loader: "js",
230
+ contents: code,
231
+ watchFiles: meta.watchFiles,
232
+ resolveDir: path2.dirname(args.path)
233
+ };
234
+ } catch (e) {
235
+ const text = e.message;
236
+ const errors = [];
237
+ let match;
238
+ let lines;
239
+ while (match = markoErrorRegExp.exec(text)) {
240
+ const [, file, rawLine, rawCol, text2] = match;
241
+ const line = parseInt(rawLine, 10) || 1;
242
+ const column = parseInt(rawCol, 10) || 1;
243
+ lines ||= (await fs2.promises.readFile(args.path, "utf-8")).split(
244
+ /\n/g
245
+ );
246
+ errors.push({
247
+ text: text2,
248
+ location: {
249
+ file,
250
+ line,
251
+ column,
252
+ lineText: ` ${lines[line - 1]}`
253
+ }
254
+ });
255
+ }
256
+ if (!errors.length) {
257
+ errors.push({ text });
258
+ }
259
+ return {
260
+ errors
261
+ };
262
+ }
263
+ });
131
264
  }
132
- </__flush_here_and_after__>
133
- </>
134
-
135
- <\${template} ...input/>${opts.tagsAPI ? "" : `
136
- <init-components/>
137
- <await-reorderer/>`}
265
+ };
266
+ }
138
267
 
139
- ${opts.tagsAPI ? "<if=writeSync>" : "<if(writeSync)>"}
140
- $!{$global.___viteRenderAssets("body")}
141
- </>
142
- <else>
143
- <__flush_here_and_after__>
144
- $!{$global.___viteRenderAssets("body")}
145
- </__flush_here_and_after__>
146
- </>
147
- `;
268
+ // src/glob-import-transform.ts
269
+ import { types as t2 } from "@marko/compiler";
270
+ import glob from "fast-glob";
271
+ import path3 from "path";
272
+ var programGlobImports = /* @__PURE__ */ new WeakMap();
273
+ var glob_import_transform_default = {
274
+ MetaProperty(tag) {
275
+ const memberExpression2 = tag.parentPath;
276
+ if (memberExpression2.node.type === "MemberExpression" && memberExpression2.node.property.type === "Identifier" && memberExpression2.node.property.name === "glob") {
277
+ const callExpression = memberExpression2.parentPath;
278
+ if (callExpression?.node.type === "CallExpression") {
279
+ const args = callExpression.get("arguments").map((arg) => arg.evaluate().value);
280
+ if (args[1]?.eager) {
281
+ const program = tag.hub.file.path;
282
+ const existing = programGlobImports.get(program);
283
+ if (!existing) {
284
+ programGlobImports.set(program, [args]);
285
+ } else {
286
+ existing.push(args);
287
+ }
288
+ }
289
+ }
290
+ }
291
+ },
292
+ Program: {
293
+ exit(tag) {
294
+ const globImports = programGlobImports.get(tag);
295
+ if (!globImports) {
296
+ return;
297
+ }
298
+ const { cwd, filename } = tag.hub.file.opts;
299
+ const dir = path3.dirname(filename);
300
+ const seen = /* @__PURE__ */ new Set();
301
+ for (const [patterns, options] of globImports) {
302
+ const resolvedPatterns = Array.isArray(patterns) ? patterns.map((p) => path3.resolve(dir, p)) : path3.resolve(dir, patterns);
303
+ const results = glob.globSync(resolvedPatterns, {
304
+ cwd,
305
+ absolute: true,
306
+ dot: !!options.exhaustive,
307
+ ignore: options.exhaustive ? [] : [path3.join(cwd, "**/node_modules/**")]
308
+ });
309
+ for (const file of results) {
310
+ if (file.endsWith(".marko") && file !== filename && !seen.has(file)) {
311
+ seen.add(file);
312
+ tag.node.body.push(t2.importDeclaration([], t2.stringLiteral(file)));
313
+ }
314
+ }
315
+ }
316
+ }
317
+ }
148
318
  };
149
319
 
150
320
  // src/manifest-generator.ts
151
- import { Parser } from "htmlparser2";
152
321
  import { ElementType as ElementType2 } from "domelementtype";
153
322
  import { DomHandler } from "domhandler";
323
+ import { Parser } from "htmlparser2";
154
324
 
155
325
  // src/serializer.ts
156
326
  import { ElementType } from "domelementtype";
@@ -354,285 +524,51 @@ function isElement(node) {
354
524
  return node.type === ElementType2.Tag;
355
525
  }
356
526
 
357
- // src/esbuild-plugin.ts
358
- import fs from "fs";
359
- import path2 from "path";
360
- import * as compiler from "@marko/compiler";
361
- var markoErrorRegExp = /^(.+?)(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
362
- function esbuildPlugin(config) {
363
- return {
364
- name: "marko",
365
- async setup(build) {
366
- const { platform = "browser" } = build.initialOptions;
367
- const isScan = build.initialOptions.plugins?.some(
368
- (v) => v.name === "vite:dep-scan"
369
- );
370
- const virtualFiles2 = /* @__PURE__ */ new Map();
371
- const finalConfig = {
372
- ...config,
373
- output: platform === "browser" ? "dom" : "html",
374
- resolveVirtualDependency(from, dep) {
375
- virtualFiles2.set(path2.join(from, "..", dep.virtualPath), dep);
376
- return dep.virtualPath;
377
- }
378
- };
379
- const scanConfig = {
380
- ...finalConfig,
381
- output: "hydrate"
382
- };
383
- build.onResolve({ filter: /\.marko\./ }, (args) => {
384
- return {
385
- namespace: "marko:virtual",
386
- path: path2.resolve(args.resolveDir, args.path),
387
- external: isScan
388
- };
389
- });
390
- build.onLoad(
391
- { filter: /\.marko\./, namespace: "marko:virtual" },
392
- (args) => ({
393
- contents: virtualFiles2.get(args.path).code,
394
- loader: path2.extname(args.path).slice(1)
395
- })
396
- );
397
- build.onLoad({ filter: /\.marko$/ }, async (args) => {
398
- try {
399
- const { code, meta } = await compiler.compileFile(
400
- args.path,
401
- isScan && args.namespace === "" ? scanConfig : finalConfig
402
- );
403
- return {
404
- loader: "js",
405
- contents: code,
406
- watchFiles: meta.watchFiles,
407
- resolveDir: path2.dirname(args.path)
408
- };
409
- } catch (e) {
410
- const text = e.message;
411
- const errors = [];
412
- let match;
413
- let lines;
414
- while (match = markoErrorRegExp.exec(text)) {
415
- const [, file, rawLine, rawCol, text2] = match;
416
- const line = parseInt(rawLine, 10) || 1;
417
- const column = parseInt(rawCol, 10) || 1;
418
- lines ||= (await fs.promises.readFile(args.path, "utf-8")).split(
419
- /\n/g
420
- );
421
- errors.push({
422
- text: text2,
423
- location: {
424
- file,
425
- line,
426
- column,
427
- lineText: ` ${lines[line - 1]}`
428
- }
429
- });
430
- }
431
- if (!errors.length) {
432
- errors.push({ text });
433
- }
434
- return {
435
- errors
436
- };
437
- }
438
- });
439
- }
440
- };
441
- }
442
-
443
- // src/babel-plugin-cjs-interop.ts
444
- import * as t from "@babel/types";
445
-
446
- // src/resolve.ts
447
- import { exports } from "resolve.exports";
448
- import Resolve from "resolve";
449
- import path3 from "path";
450
- import fs2 from "fs";
451
- var exportsMainFile = `__package_exports__`;
452
- var modulePathReg = /^.*[/\\]node_modules[/\\](?:@[^/\\]+[/\\])?[^/\\]+[/\\]/;
453
- var cjsModuleLookup = /* @__PURE__ */ new Map();
454
- function isCJSModule(id) {
455
- const modulePath = modulePathReg.exec(id)?.[0];
456
- if (modulePath) {
457
- const pkgPath = modulePath + "package.json";
458
- let isCJS = cjsModuleLookup.get(pkgPath);
459
- if (isCJS === void 0) {
460
- try {
461
- const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
462
- isCJS = pkg.type !== "module" && !pkg.exports;
463
- } catch {
464
- isCJS = false;
465
- }
466
- cjsModuleLookup.set(pkgPath, isCJS);
467
- }
468
- return isCJS;
469
- }
470
- return false;
471
- }
472
- function resolve(id, from, extensions, conditions) {
473
- return Resolve.sync(id, {
474
- basedir: path3.dirname(from),
475
- filename: from,
476
- pathFilter,
477
- packageFilter,
478
- extensions
479
- });
480
- function pathFilter(pkg, pkgFile, relativePath) {
481
- cjsModuleLookup.set(pkgFile, pkg.type !== "module" && !pkg.exports);
482
- if (pkg.exports) {
483
- return exports(
484
- pkg,
485
- relativePath === exportsMainFile ? "." : relativePath,
486
- {
487
- conditions
488
- }
489
- )?.[0];
490
- }
491
- return relativePath;
527
+ // src/read-once-persisted-store.ts
528
+ import { promises as fs3 } from "fs";
529
+ import os from "os";
530
+ import path4 from "path";
531
+ var noop = () => {
532
+ };
533
+ var tmpFile = path4.join(os.tmpdir(), "marko-vite-storage.json");
534
+ var values = /* @__PURE__ */ new Map();
535
+ var loadedFromDisk;
536
+ var ReadOncePersistedStore = class {
537
+ constructor(uid) {
538
+ this.uid = uid;
492
539
  }
493
- }
494
- function packageFilter(pkg) {
495
- if (pkg.exports) {
496
- pkg.main = exportsMainFile;
540
+ write(value) {
541
+ values.set(this.uid, value);
497
542
  }
498
- return pkg;
499
- }
500
-
501
- // src/babel-plugin-cjs-interop.ts
502
- function plugin(options) {
503
- return {
504
- name: "marko-import-interop",
505
- visitor: {
506
- ImportDeclaration(path7) {
507
- if (!path7.node.specifiers.length || /\.(?:mjs|marko)$|\?/.test(path7.node.source.value) || options.filter?.(path7.node.source.value) === false) {
508
- return;
509
- }
510
- try {
511
- const resolved = resolve(
512
- path7.node.source.value,
513
- path7.hub.file.opts.filename,
514
- options.extensions,
515
- options.conditions
516
- );
517
- if (!/\.c?js$/.test(resolved) || !isCJSModule(resolved)) {
518
- return;
519
- }
520
- } catch (_) {
521
- return;
522
- }
523
- let namespaceId;
524
- let defaultImportId;
525
- let imports;
526
- for (const s of path7.node.specifiers) {
527
- if (t.isImportSpecifier(s)) {
528
- (imports ||= []).push({
529
- name: t.isStringLiteral(s.imported) ? s.imported.value : s.imported.name,
530
- alias: s.local.name
531
- });
532
- } else if (t.isImportDefaultSpecifier(s)) {
533
- defaultImportId = s.local;
534
- } else if (t.isImportNamespaceSpecifier(s)) {
535
- namespaceId = s.local;
536
- }
537
- }
538
- const rawImport = path7.scope.generateUidIdentifier(
539
- namespaceId?.name || defaultImportId?.name || path7.node.source.value
540
- );
541
- path7.node.specifiers = [t.importNamespaceSpecifier(rawImport)];
542
- if (defaultImportId) {
543
- path7.insertAfter(
544
- t.variableDeclaration("const", [
545
- t.variableDeclarator(
546
- t.objectPattern([
547
- t.objectProperty(t.identifier("default"), defaultImportId)
548
- ]),
549
- t.conditionalExpression(
550
- t.optionalMemberExpression(
551
- t.memberExpression(rawImport, t.identifier("default")),
552
- t.identifier("__esModule"),
553
- false,
554
- true
555
- ),
556
- t.memberExpression(rawImport, t.identifier("default")),
557
- rawImport
558
- )
559
- )
560
- ])
561
- );
562
- }
563
- if (namespaceId) {
564
- path7.insertAfter(
565
- t.variableDeclaration("const", [
566
- t.variableDeclarator(
567
- namespaceId,
568
- t.conditionalExpression(
569
- t.optionalMemberExpression(
570
- rawImport,
571
- t.identifier("__esModule"),
572
- false,
573
- true
574
- ),
575
- rawImport,
576
- t.memberExpression(rawImport, t.identifier("default"))
577
- )
578
- )
579
- ])
580
- );
581
- }
582
- if (imports) {
583
- path7.insertAfter(
584
- t.variableDeclaration("const", [
585
- t.variableDeclarator(
586
- t.objectPattern(
587
- imports.map(
588
- ({ name, alias }) => t.objectProperty(
589
- t.identifier(name),
590
- t.identifier(alias),
591
- false,
592
- name === alias
593
- )
594
- )
595
- ),
596
- t.conditionalExpression(
597
- t.optionalMemberExpression(
598
- rawImport,
599
- t.identifier("__esModule"),
600
- false,
601
- true
602
- ),
603
- rawImport,
604
- t.memberExpression(rawImport, t.identifier("default"))
605
- )
606
- )
607
- ])
608
- );
609
- }
610
- }
543
+ async read() {
544
+ const { uid } = this;
545
+ if (values.has(uid)) {
546
+ const value = values.get(uid);
547
+ values.delete(uid);
548
+ return value;
549
+ }
550
+ if (loadedFromDisk === true) {
551
+ throw new Error(`Value for ${uid} could not be loaded.`);
611
552
  }
612
- };
613
- }
614
-
615
- // src/render-assets-transform.ts
616
- var render_assets_transform_default = (tag, t3) => {
617
- if (tag.hub.file.markoOpts.markoViteLinked) {
618
- const body = tag.get("body");
619
- const tagName = tag.get("name").node.value;
620
- body.unshiftContainer("body", renderAssetsCall(t3, `${tagName}-prepend`));
621
- body.pushContainer("body", renderAssetsCall(t3, tagName));
553
+ await (loadedFromDisk ||= fs3.readFile(tmpFile, "utf-8").then(syncDataFromDisk).catch(finishLoadFromDisk));
554
+ return this.read();
622
555
  }
623
556
  };
624
- function renderAssetsCall(t3, slot) {
625
- return t3.markoPlaceholder(
626
- t3.callExpression(
627
- t3.memberExpression(
628
- t3.identifier("$global"),
629
- t3.identifier("___viteRenderAssets")
630
- ),
631
- [t3.stringLiteral(slot)]
632
- ),
633
- false
634
- );
557
+ function syncDataFromDisk(data) {
558
+ finishLoadFromDisk();
559
+ fs3.unlink(tmpFile).catch(noop);
560
+ for (const [k, v] of JSON.parse(data)) {
561
+ values.set(k, v);
562
+ }
563
+ }
564
+ function finishLoadFromDisk() {
565
+ loadedFromDisk = true;
635
566
  }
567
+ process.once("beforeExit", (code) => {
568
+ if (code === 0 && values.size) {
569
+ fs3.writeFile(tmpFile, JSON.stringify([...values])).catch(noop);
570
+ }
571
+ });
636
572
 
637
573
  // src/relative-assets-transform.ts
638
574
  var attrSrc = /* @__PURE__ */ new Set(["src"]);
@@ -681,103 +617,176 @@ function transform(tag, t3) {
681
617
  }
682
618
  }
683
619
 
684
- // src/glob-import-transform.ts
685
- import { types as t2 } from "@marko/compiler";
686
- import glob from "fast-glob";
687
- import path4 from "path";
688
- var programGlobImports = /* @__PURE__ */ new WeakMap();
689
- var glob_import_transform_default = {
690
- MetaProperty(tag) {
691
- const memberExpression2 = tag.parentPath;
692
- if (memberExpression2.node.type === "MemberExpression" && memberExpression2.node.property.type === "Identifier" && memberExpression2.node.property.name === "glob") {
693
- const callExpression = memberExpression2.parentPath;
694
- if (callExpression?.node.type === "CallExpression") {
695
- const args = callExpression.get("arguments").map((arg) => arg.evaluate().value);
696
- if (args[1]?.eager) {
697
- const program = tag.hub.file.path;
698
- const existing = programGlobImports.get(program);
699
- if (!existing) {
700
- programGlobImports.set(program, [args]);
701
- } else {
702
- existing.push(args);
620
+ // src/render-assets-runtime.ts
621
+ var renderAssetsRuntimeId = "\0marko-render-assets.mjs";
622
+ function getRenderAssetsRuntime(opts) {
623
+ return `${opts.basePathVar && opts.isBuild ? `const base = globalThis.${opts.basePathVar};
624
+ if (typeof base !== "string") throw new Error("${opts.basePathVar} must be defined when using basePathVar.");
625
+ if (!base.endsWith("/")) throw new Error("${opts.basePathVar} must end with a '/' when using basePathVar.");` : "const base = import.meta.env.BASE_URL;"}
626
+
627
+ export function getPrepend(g) {
628
+ return (
629
+ g.___viteRenderAssets("head-prepend") +
630
+ g.___viteRenderAssets("head") +
631
+ g.___viteRenderAssets("body-prepend")
632
+ );
633
+ }
634
+ export function getAppend(g) {
635
+ return (
636
+ g.___viteRenderAssets("body-prepend")
637
+ );
638
+ }
639
+ export function addAssets(g, newEntries) {
640
+ const entries = g.___viteEntries;
641
+ if (entries) {
642
+ g.___viteEntries = entries.concat(newEntries);
643
+ return true;
644
+ }
645
+ g.___viteEntries = newEntries;
646
+ g.___viteRenderAssets = renderAssets;
647
+ g.___viteInjectAttrs = g.cspNonce
648
+ ? \` nonce="\${g.cspNonce.replace(/"/g, "&#39;")}"\`
649
+ : "";
650
+ g.___viteSeenIds = new Set();
651
+ ${opts.runtimeId ? `g.runtimeId = ${JSON.stringify(opts.runtimeId)};` : ""}
652
+ }
653
+
654
+ function renderAssets(slot) {
655
+ const entries = this.___viteEntries;
656
+ let html = "";
657
+
658
+ if (entries) {
659
+ const seenIds = this.___viteSeenIds;
660
+ const slotWrittenEntriesKey = \`___viteWrittenEntries-\${slot}\`;
661
+ const lastWrittenEntry = this[slotWrittenEntriesKey] || 0;
662
+ const writtenEntries = (this[slotWrittenEntriesKey] = entries.length);
663
+
664
+ if(!this.___flushedMBP && slot !== "head-prepend") {
665
+ this.___flushedMBP = true;
666
+
667
+ html += \`<script\${this.___viteInjectAttrs}>${opts.runtimeId ? `$mbp_${opts.runtimeId}` : "$mbp"}=\${JSON.stringify(base)}</script>\`
668
+ }
669
+
670
+ for (let i = lastWrittenEntry; i < writtenEntries; i++) {
671
+ let entry = entries[i];
672
+
673
+ if (typeof entry === "string") {
674
+ entry = __MARKO_MANIFEST__[entry] || {};
675
+ }${opts.isBuild ? "" : ` else if (slot === "head") {
676
+ // In dev mode we have is a list entries of the top level modules that need to be imported.
677
+ // To avoid FOUC we will hide the page until all of these modules are loaded.
678
+ const { preload } = entry;
679
+ if (preload) {
680
+ html += \`<script class=marko-vite-preload async blocking=render type=module\${this.___viteInjectAttrs}>\`;
681
+ for (const id of preload) {
682
+ html += \`import \${JSON.stringify(base + id)};\`;
703
683
  }
684
+
685
+ html += "document.querySelectorAll('.marko-vite-preload').forEach((el) => el.remove());";
686
+ html += "document.documentElement.style.visibility='';";
687
+ html +=
688
+ "if(document.documentElement.getAttribute('style')==='')document.documentElement.removeAttribute('style');";
689
+ html += \`</script><script class=marko-vite-preload\${this.___viteInjectAttrs}>document.documentElement.style.visibility='hidden'</script>\`;
704
690
  }
705
- }
706
- }
707
- },
708
- Program: {
709
- exit(tag) {
710
- const globImports = programGlobImports.get(tag);
711
- if (!globImports) {
712
- return;
713
- }
714
- const { cwd, filename } = tag.hub.file.opts;
715
- const dir = path4.dirname(filename);
716
- const seen = /* @__PURE__ */ new Set();
717
- for (const [patterns, options] of globImports) {
718
- const resolvedPatterns = Array.isArray(patterns) ? patterns.map((p) => path4.resolve(dir, p)) : path4.resolve(dir, patterns);
719
- const results = glob.globSync(resolvedPatterns, {
720
- cwd,
721
- absolute: true,
722
- dot: !!options.exhaustive,
723
- ignore: options.exhaustive ? [] : [path4.join(cwd, "**/node_modules/**")]
724
- });
725
- for (const file of results) {
726
- if (file.endsWith(".marko") && file !== filename && !seen.has(file)) {
727
- seen.add(file);
728
- tag.node.body.push(t2.importDeclaration([], t2.stringLiteral(file)));
691
+ }`}
692
+
693
+ const parts = entry[slot];
694
+
695
+ if (parts) {
696
+ for (let i = 0; i < parts.length; i++) {
697
+ const part = parts[i];
698
+ switch (part) {
699
+ case 0: /** InjectType.AssetAttrs */
700
+ html += this.___viteInjectAttrs;
701
+ break;
702
+ case 1: /** InjectType.PublicPath */
703
+ html += base;
704
+ break;
705
+ case 2: /** InjectType.Dedupe */ {
706
+ const id = parts[++i];
707
+ const skipParts = parts[++i];
708
+ if (seenIds.has(id)) {
709
+ i += skipParts;
710
+ } else {
711
+ seenIds.add(id);
712
+ }
713
+ break;
714
+ }
715
+ default:
716
+ html += part;
717
+ break;
729
718
  }
730
719
  }
731
720
  }
732
721
  }
733
722
  }
734
- };
735
723
 
736
- // src/read-once-persisted-store.ts
737
- import os from "os";
738
- import path5 from "path";
739
- import { promises as fs3 } from "fs";
740
- var noop = () => {
741
- };
742
- var tmpFile = path5.join(os.tmpdir(), "marko-vite-storage.json");
743
- var values = /* @__PURE__ */ new Map();
744
- var loadedFromDisk;
745
- var ReadOncePersistedStore = class {
746
- constructor(uid) {
747
- this.uid = uid;
748
- }
749
- write(value) {
750
- values.set(this.uid, value);
751
- }
752
- async read() {
753
- const { uid } = this;
754
- if (values.has(uid)) {
755
- const value = values.get(uid);
756
- values.delete(uid);
757
- return value;
758
- }
759
- if (loadedFromDisk === true) {
760
- throw new Error(`Value for ${uid} could not be loaded.`);
761
- }
762
- await (loadedFromDisk ||= fs3.readFile(tmpFile, "utf-8").then(syncDataFromDisk).catch(finishLoadFromDisk));
763
- return this.read();
724
+ return html;
725
+ }
726
+ `;
727
+ }
728
+
729
+ // src/render-assets-transform.ts
730
+ var render_assets_transform_default = (tag, t3) => {
731
+ if (tag.hub.file.markoOpts.markoViteLinked) {
732
+ const body = tag.get("body");
733
+ const tagName = tag.get("name").node.value;
734
+ body.unshiftContainer("body", renderAssetsCall(t3, `${tagName}-prepend`));
735
+ body.pushContainer("body", renderAssetsCall(t3, tagName));
764
736
  }
765
737
  };
766
- function syncDataFromDisk(data) {
767
- finishLoadFromDisk();
768
- fs3.unlink(tmpFile).catch(noop);
769
- for (const [k, v] of JSON.parse(data)) {
770
- values.set(k, v);
771
- }
738
+ function renderAssetsCall(t3, slot) {
739
+ return t3.markoPlaceholder(
740
+ t3.callExpression(
741
+ t3.memberExpression(
742
+ t3.identifier("$global"),
743
+ t3.identifier("___viteRenderAssets")
744
+ ),
745
+ [t3.stringLiteral(slot)]
746
+ ),
747
+ false
748
+ );
772
749
  }
773
- function finishLoadFromDisk() {
774
- loadedFromDisk = true;
750
+
751
+ // src/server-entry-template.ts
752
+ import path5 from "path";
753
+ var server_entry_template_default = async (opts) => {
754
+ const fileNameStr = JSON.stringify(`./${path5.basename(opts.fileName)}`);
755
+ if (opts.tagsAPI) {
756
+ return `import Template from ${fileNameStr};
757
+ export * from ${fileNameStr};
758
+ import { addAssets, getPrepend, getAppend } from "${renderAssetsRuntimeId}";
759
+ static function flush($global, html) {
760
+ return getPrepend($global) + html + getAppend($global);
775
761
  }
776
- process.once("beforeExit", (code) => {
777
- if (code === 0 && values.size) {
778
- fs3.writeFile(tmpFile, JSON.stringify([...values])).catch(noop);
762
+ static function setFlush($global) {
763
+ $global.__flush__ = flush;
764
+ }
765
+ static const assets = [${opts.entryData.join(",")}];
766
+ <const/writeSync=addAssets($global, assets) || setFlush($global)/>
767
+ -- $!{writeSync && getPrepend($global)}
768
+ <Template ...input/>
769
+ -- $!{writeSync && getAppend($global)}
770
+ `;
779
771
  }
780
- });
772
+ return `import template from ${fileNameStr};
773
+ export * from ${fileNameStr};
774
+ import { addAssets, getPrepend, getAppend } from "${renderAssetsRuntimeId}";
775
+ static const assets = [${opts.entryData.join(",")}];
776
+ <if(addAssets($global, assets))>
777
+ $!{getPrepend($global)}
778
+ <\${template} ...input/>
779
+ $!{getAppend($global)}
780
+ </>
781
+ <else>
782
+ <__flush_here_and_after__>$!{getPrepend($global)}</>
783
+ <\${template} ...input/>
784
+ <init-components/>
785
+ <await-reorderer/>
786
+ <__flush_here_and_after__>$!{getAppend($global)}</>
787
+ </>
788
+ `;
789
+ };
781
790
 
782
791
  // src/index.ts
783
792
  var POSIX_SEP = "/";
@@ -802,6 +811,7 @@ var babelCaller = {
802
811
  supportsTopLevelAwait: true,
803
812
  supportsExportNamespaceFrom: true
804
813
  };
814
+ var optimizeKnownTemplatesForRoot = /* @__PURE__ */ new Map();
805
815
  var registeredTagLib = false;
806
816
  var cjsToEsm;
807
817
  function noop2() {
@@ -844,7 +854,6 @@ function markoPlugin(opts = {}) {
844
854
  );
845
855
  const entryIds = /* @__PURE__ */ new Set();
846
856
  const cachedSources = /* @__PURE__ */ new Map();
847
- const optimizedRegisistyIdMap = /* @__PURE__ */ new Map();
848
857
  const transformWatchFiles = /* @__PURE__ */ new Map();
849
858
  const transformOptionalFiles = /* @__PURE__ */ new Map();
850
859
  const store = new ReadOncePersistedStore(
@@ -874,16 +883,7 @@ function markoPlugin(opts = {}) {
874
883
  runtimeId,
875
884
  sourceMaps: true,
876
885
  writeVersionComment: false,
877
- optimizeRegistryId(id) {
878
- let registryId = optimizedRegisistyIdMap.get(id);
879
- if (registryId === void 0) {
880
- optimizedRegisistyIdMap.set(
881
- id,
882
- registryId = optimizedRegisistyIdMap.size
883
- );
884
- }
885
- return registryId;
886
- },
886
+ optimizeKnownTemplates: optimize && linked ? getKnownTemplates(root) : void 0,
887
887
  babelConfig: opts.babelConfig ? {
888
888
  ...opts.babelConfig,
889
889
  caller: opts.babelConfig.caller ? {
@@ -1088,6 +1088,7 @@ function markoPlugin(opts = {}) {
1088
1088
  handleHotUpdate(ctx) {
1089
1089
  compiler2.taglib.clearCaches();
1090
1090
  baseConfig.cache.clear();
1091
+ optimizeKnownTemplatesForRoot.clear();
1091
1092
  for (const [, cache2] of configsByFileSystem) {
1092
1093
  cache2.clear();
1093
1094
  }
@@ -1102,11 +1103,6 @@ function markoPlugin(opts = {}) {
1102
1103
  try {
1103
1104
  serverManifest = await store.read();
1104
1105
  inputOptions.input = toHTMLEntries(root, serverManifest.entries);
1105
- if (serverManifest.registered) {
1106
- for (let i = 0; i < serverManifest.registered.length; i++) {
1107
- optimizedRegisistyIdMap.set(serverManifest.registered[i], i);
1108
- }
1109
- }
1110
1106
  for (const entry in serverManifest.entrySources) {
1111
1107
  const id = normalizePath(path6.resolve(root, entry));
1112
1108
  entryIds.add(id);
@@ -1371,9 +1367,6 @@ if (import.meta.hot) import.meta.hot.accept(() => {});`;
1371
1367
  }
1372
1368
  }
1373
1369
  }
1374
- if (optimizedRegisistyIdMap.size) {
1375
- serverManifest.registered = [...optimizedRegisistyIdMap.keys()];
1376
- }
1377
1370
  store.write(serverManifest);
1378
1371
  } else {
1379
1372
  const browserManifest = {};
@@ -1502,6 +1495,33 @@ function getConfigForFileSystem(info, config) {
1502
1495
  }
1503
1496
  return configForFileSystem;
1504
1497
  }
1498
+ function getKnownTemplates(cwd) {
1499
+ let knownTemplates = optimizeKnownTemplatesForRoot.get(cwd);
1500
+ if (!knownTemplates) {
1501
+ optimizeKnownTemplatesForRoot.set(
1502
+ cwd,
1503
+ knownTemplates = glob2.globSync(
1504
+ ["**/*.marko", "**/node_modules/.marko/**/*.marko"],
1505
+ {
1506
+ cwd,
1507
+ absolute: true,
1508
+ ignore: [
1509
+ "**/*.d.marko",
1510
+ "**/*build*/**",
1511
+ "**/*coverage*/**",
1512
+ "**/*dist*/**",
1513
+ "**/*example*/**",
1514
+ "**/*fixture*/**",
1515
+ "**/*snapshot*/**",
1516
+ "**/*stories*/**",
1517
+ "**/*test*/**"
1518
+ ]
1519
+ }
1520
+ )
1521
+ );
1522
+ }
1523
+ return knownTemplates;
1524
+ }
1505
1525
  export {
1506
1526
  markoPlugin as default
1507
1527
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@marko/vite",
3
3
  "description": "A Marko plugin for Vite",
4
- "version": "5.0.5",
4
+ "version": "5.0.7",
5
5
  "author": "Dylan Piercey <dpiercey@ebay.com>",
6
6
  "bugs": "https://github.com/marko-js/vite/issues",
7
7
  "dependencies": {
@@ -17,29 +17,30 @@
17
17
  "devDependencies": {
18
18
  "@changesets/changelog-github": "^0.5.0",
19
19
  "@changesets/cli": "^2.27.10",
20
- "@marko/compiler": "^5.38.0",
20
+ "@eslint/js": "^9.15.0",
21
+ "@marko/compiler": "^5.38.1",
21
22
  "@marko/fixture-snapshots": "^2.2.1",
22
23
  "@marko/testing-library": "^6.2.0",
23
24
  "@types/babel__core": "^7.20.5",
24
25
  "@types/diff": "^6.0.0",
25
26
  "@types/jsdom": "^21.1.7",
26
27
  "@types/mocha": "^10.0.10",
27
- "@types/node": "^22.9.1",
28
+ "@types/node": "^22.9.3",
28
29
  "@types/resolve": "^1.20.6",
29
30
  "@types/serve-handler": "^6.1.4",
30
- "@typescript-eslint/eslint-plugin": "^7.11.0",
31
- "@typescript-eslint/parser": "^7.11.0",
32
31
  "cross-env": "^7.0.3",
33
32
  "diff": "^7.0.0",
34
33
  "esbuild": "^0.24.0",
35
- "eslint": "^8.57.0",
36
- "eslint-config-prettier": "^9.1.0",
34
+ "eslint": "^9.15.0",
35
+ "eslint-formatter-unix": "^8.40.0",
36
+ "eslint-plugin-simple-import-sort": "^12.1.1",
37
37
  "fixpack": "^4.0.0",
38
+ "globals": "^15.12.0",
38
39
  "husky": "^9.1.7",
39
40
  "jsdom": "^25.0.1",
40
- "less": "^4.2.0",
41
+ "less": "^4.2.1",
41
42
  "lint-staged": "^15.2.10",
42
- "marko": "^5.36.0",
43
+ "marko": "^5.36.1",
43
44
  "mocha": "^10.8.2",
44
45
  "mocha-snap": "^5.0.0",
45
46
  "nyc": "^17.1.0",
@@ -48,6 +49,7 @@
48
49
  "serve-handler": "^6.1.6",
49
50
  "tsx": "^4.19.2",
50
51
  "typescript": "^5.7.2",
52
+ "typescript-eslint": "^8.16.0",
51
53
  "vite": "^5.4.11"
52
54
  },
53
55
  "files": [
@@ -79,9 +81,9 @@
79
81
  "ci:test": "nyc npm test -- --forbid-only",
80
82
  "format": "npm run lint:eslint -- --fix && npm run lint:prettier -- --write && (fixpack || true)",
81
83
  "lint": "tsc -b && npm run lint:eslint && npm run lint:prettier -- -l && fixpack",
82
- "lint:eslint": "eslint -f visualstudio .",
84
+ "lint:eslint": "eslint -f unix .",
83
85
  "lint:prettier": "prettier \"./**/*{.ts,.js,.json,.md,.yml,rc}\"",
84
- "prepare": "husky install",
86
+ "prepare": "husky",
85
87
  "release": "npm run build && changeset publish",
86
88
  "report": "open ./coverage/lcov-report/index.html",
87
89
  "test": "cross-env NODE_ENV=test mocha \"./src/**/__tests__/*.test.ts\"",