@marko/vite 5.0.6 → 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,166 +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";
11
-
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;"}
10
+ // src/babel-plugin-cjs-interop.ts
11
+ import * as t from "@babel/types";
18
12
 
19
- export function getPrepend(g) {
20
- return (
21
- g.___viteRenderAssets("head-prepend") +
22
- g.___viteRenderAssets("head") +
23
- g.___viteRenderAssets("body-prepend")
24
- );
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;
36
+ }
37
+ return false;
25
38
  }
26
- export function getAppend(g) {
27
- return (
28
- g.___viteRenderAssets("body-prepend")
29
- );
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];
57
+ }
58
+ return relativePath;
59
+ }
30
60
  }
31
- export function addAssets(g, newEntries) {
32
- const entries = g.___viteEntries;
33
- if (entries) {
34
- g.___viteEntries = entries.concat(newEntries);
35
- return true;
61
+ function packageFilter(pkg) {
62
+ if (pkg.exports) {
63
+ pkg.main = exportsMainFile;
36
64
  }
37
- g.___viteEntries = newEntries;
38
- g.___viteRenderAssets = renderAssets;
39
- g.___viteInjectAttrs = g.cspNonce
40
- ? \` nonce="\${g.cspNonce.replace(/"/g, "&#39;")}"\`
41
- : "";
42
- g.___viteSeenIds = new Set();
43
- ${opts.runtimeId ? `g.runtimeId = ${JSON.stringify(opts.runtimeId)};` : ""}
65
+ return pkg;
44
66
  }
45
67
 
46
- function renderAssets(slot) {
47
- const entries = this.___viteEntries;
48
- let html = "";
49
-
50
- if (entries) {
51
- const seenIds = this.___viteSeenIds;
52
- const slotWrittenEntriesKey = \`___viteWrittenEntries-\${slot}\`;
53
- const lastWrittenEntry = this[slotWrittenEntriesKey] || 0;
54
- const writtenEntries = (this[slotWrittenEntriesKey] = entries.length);
55
-
56
- if(!this.___flushedMBP && slot !== "head-prepend") {
57
- this.___flushedMBP = true;
58
-
59
- html += \`<script\${this.___viteInjectAttrs}>${opts.runtimeId ? `$mbp_${opts.runtimeId}` : "$mbp"}=\${JSON.stringify(base)}</script>\`
60
- }
61
-
62
- for (let i = lastWrittenEntry; i < writtenEntries; i++) {
63
- let entry = entries[i];
64
-
65
- if (typeof entry === "string") {
66
- entry = __MARKO_MANIFEST__[entry] || {};
67
- }${opts.isBuild ? "" : ` else if (slot === "head") {
68
- // In dev mode we have is a list entries of the top level modules that need to be imported.
69
- // To avoid FOUC we will hide the page until all of these modules are loaded.
70
- const { preload } = entry;
71
- if (preload) {
72
- html += \`<script class=marko-vite-preload async blocking=render type=module\${this.___viteInjectAttrs}>\`;
73
- for (const id of preload) {
74
- 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;
75
86
  }
76
-
77
- html += "document.querySelectorAll('.marko-vite-preload').forEach((el) => el.remove());";
78
- html += "document.documentElement.style.visibility='';";
79
- html +=
80
- "if(document.documentElement.getAttribute('style')==='')document.documentElement.removeAttribute('style');";
81
- html += \`</script><script class=marko-vite-preload\${this.___viteInjectAttrs}>document.documentElement.style.visibility='hidden'</script>\`;
87
+ } catch (_) {
88
+ return;
82
89
  }
83
- }`}
84
-
85
- const parts = entry[slot];
86
-
87
- if (parts) {
88
- for (let i = 0; i < parts.length; i++) {
89
- const part = parts[i];
90
- switch (part) {
91
- case 0: /** InjectType.AssetAttrs */
92
- html += this.___viteInjectAttrs;
93
- break;
94
- case 1: /** InjectType.PublicPath */
95
- html += base;
96
- break;
97
- case 2: /** InjectType.Dedupe */ {
98
- const id = parts[++i];
99
- const skipParts = parts[++i];
100
- if (seenIds.has(id)) {
101
- i += skipParts;
102
- } else {
103
- seenIds.add(id);
104
- }
105
- break;
106
- }
107
- default:
108
- html += part;
109
- 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;
110
103
  }
111
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
+ }
112
177
  }
113
178
  }
114
- }
115
-
116
- return html;
117
- }
118
- `;
179
+ };
119
180
  }
120
181
 
121
- // src/server-entry-template.ts
122
- var server_entry_template_default = async (opts) => {
123
- const fileNameStr = JSON.stringify(`./${path.basename(opts.fileName)}`);
124
- if (opts.tagsAPI) {
125
- return `import Template from ${fileNameStr};
126
- export * from ${fileNameStr};
127
- import { addAssets, getPrepend, getAppend } from "${renderAssetsRuntimeId}";
128
- static function flush($global, html) {
129
- return getPrepend($global) + html + getAppend($global);
130
- }
131
- static function setFlush($global) {
132
- $global.__flush__ = flush;
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
+ });
264
+ }
265
+ };
133
266
  }
134
- static const assets = [${opts.entryData.join(",")}];
135
- <const/writeSync=addAssets($global, assets) || setFlush($global)/>
136
- -- $!{writeSync && getPrepend($global)}
137
- <Template ...input/>
138
- -- $!{writeSync && getAppend($global)}
139
- `;
267
+
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
+ }
140
317
  }
141
- return `import template from ${fileNameStr};
142
- export * from ${fileNameStr};
143
- import { addAssets, getPrepend, getAppend } from "${renderAssetsRuntimeId}";
144
- static const assets = [${opts.entryData.join(",")}];
145
- <if(addAssets($global, assets))>
146
- $!{getPrepend($global)}
147
- <\${template} ...input/>
148
- $!{getAppend($global)}
149
- </>
150
- <else>
151
- <__flush_here_and_after__>$!{getPrepend($global)}</>
152
- <\${template} ...input/>
153
- <init-components/>
154
- <await-reorderer/>
155
- <__flush_here_and_after__>$!{getAppend($global)}</>
156
- </>
157
- `;
158
318
  };
159
319
 
160
320
  // src/manifest-generator.ts
161
- import { Parser } from "htmlparser2";
162
321
  import { ElementType as ElementType2 } from "domelementtype";
163
322
  import { DomHandler } from "domhandler";
323
+ import { Parser } from "htmlparser2";
164
324
 
165
325
  // src/serializer.ts
166
326
  import { ElementType } from "domelementtype";
@@ -364,285 +524,51 @@ function isElement(node) {
364
524
  return node.type === ElementType2.Tag;
365
525
  }
366
526
 
367
- // src/esbuild-plugin.ts
368
- import fs from "fs";
369
- import path2 from "path";
370
- import * as compiler from "@marko/compiler";
371
- var markoErrorRegExp = /^(.+?)(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
372
- function esbuildPlugin(config) {
373
- return {
374
- name: "marko",
375
- async setup(build) {
376
- const { platform = "browser" } = build.initialOptions;
377
- const isScan = build.initialOptions.plugins?.some(
378
- (v) => v.name === "vite:dep-scan"
379
- );
380
- const virtualFiles2 = /* @__PURE__ */ new Map();
381
- const finalConfig = {
382
- ...config,
383
- output: platform === "browser" ? "dom" : "html",
384
- resolveVirtualDependency(from, dep) {
385
- virtualFiles2.set(path2.join(from, "..", dep.virtualPath), dep);
386
- return dep.virtualPath;
387
- }
388
- };
389
- const scanConfig = {
390
- ...finalConfig,
391
- output: "hydrate"
392
- };
393
- build.onResolve({ filter: /\.marko\./ }, (args) => {
394
- return {
395
- namespace: "marko:virtual",
396
- path: path2.resolve(args.resolveDir, args.path),
397
- external: isScan
398
- };
399
- });
400
- build.onLoad(
401
- { filter: /\.marko\./, namespace: "marko:virtual" },
402
- (args) => ({
403
- contents: virtualFiles2.get(args.path).code,
404
- loader: path2.extname(args.path).slice(1)
405
- })
406
- );
407
- build.onLoad({ filter: /\.marko$/ }, async (args) => {
408
- try {
409
- const { code, meta } = await compiler.compileFile(
410
- args.path,
411
- isScan && args.namespace === "" ? scanConfig : finalConfig
412
- );
413
- return {
414
- loader: "js",
415
- contents: code,
416
- watchFiles: meta.watchFiles,
417
- resolveDir: path2.dirname(args.path)
418
- };
419
- } catch (e) {
420
- const text = e.message;
421
- const errors = [];
422
- let match;
423
- let lines;
424
- while (match = markoErrorRegExp.exec(text)) {
425
- const [, file, rawLine, rawCol, text2] = match;
426
- const line = parseInt(rawLine, 10) || 1;
427
- const column = parseInt(rawCol, 10) || 1;
428
- lines ||= (await fs.promises.readFile(args.path, "utf-8")).split(
429
- /\n/g
430
- );
431
- errors.push({
432
- text: text2,
433
- location: {
434
- file,
435
- line,
436
- column,
437
- lineText: ` ${lines[line - 1]}`
438
- }
439
- });
440
- }
441
- if (!errors.length) {
442
- errors.push({ text });
443
- }
444
- return {
445
- errors
446
- };
447
- }
448
- });
449
- }
450
- };
451
- }
452
-
453
- // src/babel-plugin-cjs-interop.ts
454
- import * as t from "@babel/types";
455
-
456
- // src/resolve.ts
457
- import { exports } from "resolve.exports";
458
- import Resolve from "resolve";
459
- import path3 from "path";
460
- import fs2 from "fs";
461
- var exportsMainFile = `__package_exports__`;
462
- var modulePathReg = /^.*[/\\]node_modules[/\\](?:@[^/\\]+[/\\])?[^/\\]+[/\\]/;
463
- var cjsModuleLookup = /* @__PURE__ */ new Map();
464
- function isCJSModule(id) {
465
- const modulePath = modulePathReg.exec(id)?.[0];
466
- if (modulePath) {
467
- const pkgPath = modulePath + "package.json";
468
- let isCJS = cjsModuleLookup.get(pkgPath);
469
- if (isCJS === void 0) {
470
- try {
471
- const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
472
- isCJS = pkg.type !== "module" && !pkg.exports;
473
- } catch {
474
- isCJS = false;
475
- }
476
- cjsModuleLookup.set(pkgPath, isCJS);
477
- }
478
- return isCJS;
479
- }
480
- return false;
481
- }
482
- function resolve(id, from, extensions, conditions) {
483
- return Resolve.sync(id, {
484
- basedir: path3.dirname(from),
485
- filename: from,
486
- pathFilter,
487
- packageFilter,
488
- extensions
489
- });
490
- function pathFilter(pkg, pkgFile, relativePath) {
491
- cjsModuleLookup.set(pkgFile, pkg.type !== "module" && !pkg.exports);
492
- if (pkg.exports) {
493
- return exports(
494
- pkg,
495
- relativePath === exportsMainFile ? "." : relativePath,
496
- {
497
- conditions
498
- }
499
- )?.[0];
500
- }
501
- 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;
502
539
  }
503
- }
504
- function packageFilter(pkg) {
505
- if (pkg.exports) {
506
- pkg.main = exportsMainFile;
540
+ write(value) {
541
+ values.set(this.uid, value);
507
542
  }
508
- return pkg;
509
- }
510
-
511
- // src/babel-plugin-cjs-interop.ts
512
- function plugin(options) {
513
- return {
514
- name: "marko-import-interop",
515
- visitor: {
516
- ImportDeclaration(path7) {
517
- if (!path7.node.specifiers.length || /\.(?:mjs|marko)$|\?/.test(path7.node.source.value) || options.filter?.(path7.node.source.value) === false) {
518
- return;
519
- }
520
- try {
521
- const resolved = resolve(
522
- path7.node.source.value,
523
- path7.hub.file.opts.filename,
524
- options.extensions,
525
- options.conditions
526
- );
527
- if (!/\.c?js$/.test(resolved) || !isCJSModule(resolved)) {
528
- return;
529
- }
530
- } catch (_) {
531
- return;
532
- }
533
- let namespaceId;
534
- let defaultImportId;
535
- let imports;
536
- for (const s of path7.node.specifiers) {
537
- if (t.isImportSpecifier(s)) {
538
- (imports ||= []).push({
539
- name: t.isStringLiteral(s.imported) ? s.imported.value : s.imported.name,
540
- alias: s.local.name
541
- });
542
- } else if (t.isImportDefaultSpecifier(s)) {
543
- defaultImportId = s.local;
544
- } else if (t.isImportNamespaceSpecifier(s)) {
545
- namespaceId = s.local;
546
- }
547
- }
548
- const rawImport = path7.scope.generateUidIdentifier(
549
- namespaceId?.name || defaultImportId?.name || path7.node.source.value
550
- );
551
- path7.node.specifiers = [t.importNamespaceSpecifier(rawImport)];
552
- if (defaultImportId) {
553
- path7.insertAfter(
554
- t.variableDeclaration("const", [
555
- t.variableDeclarator(
556
- t.objectPattern([
557
- t.objectProperty(t.identifier("default"), defaultImportId)
558
- ]),
559
- t.conditionalExpression(
560
- t.optionalMemberExpression(
561
- t.memberExpression(rawImport, t.identifier("default")),
562
- t.identifier("__esModule"),
563
- false,
564
- true
565
- ),
566
- t.memberExpression(rawImport, t.identifier("default")),
567
- rawImport
568
- )
569
- )
570
- ])
571
- );
572
- }
573
- if (namespaceId) {
574
- path7.insertAfter(
575
- t.variableDeclaration("const", [
576
- t.variableDeclarator(
577
- namespaceId,
578
- t.conditionalExpression(
579
- t.optionalMemberExpression(
580
- rawImport,
581
- t.identifier("__esModule"),
582
- false,
583
- true
584
- ),
585
- rawImport,
586
- t.memberExpression(rawImport, t.identifier("default"))
587
- )
588
- )
589
- ])
590
- );
591
- }
592
- if (imports) {
593
- path7.insertAfter(
594
- t.variableDeclaration("const", [
595
- t.variableDeclarator(
596
- t.objectPattern(
597
- imports.map(
598
- ({ name, alias }) => t.objectProperty(
599
- t.identifier(name),
600
- t.identifier(alias),
601
- false,
602
- name === alias
603
- )
604
- )
605
- ),
606
- t.conditionalExpression(
607
- t.optionalMemberExpression(
608
- rawImport,
609
- t.identifier("__esModule"),
610
- false,
611
- true
612
- ),
613
- rawImport,
614
- t.memberExpression(rawImport, t.identifier("default"))
615
- )
616
- )
617
- ])
618
- );
619
- }
620
- }
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;
621
549
  }
622
- };
623
- }
624
-
625
- // src/render-assets-transform.ts
626
- var render_assets_transform_default = (tag, t3) => {
627
- if (tag.hub.file.markoOpts.markoViteLinked) {
628
- const body = tag.get("body");
629
- const tagName = tag.get("name").node.value;
630
- body.unshiftContainer("body", renderAssetsCall(t3, `${tagName}-prepend`));
631
- body.pushContainer("body", renderAssetsCall(t3, tagName));
550
+ if (loadedFromDisk === true) {
551
+ throw new Error(`Value for ${uid} could not be loaded.`);
552
+ }
553
+ await (loadedFromDisk ||= fs3.readFile(tmpFile, "utf-8").then(syncDataFromDisk).catch(finishLoadFromDisk));
554
+ return this.read();
632
555
  }
633
556
  };
634
- function renderAssetsCall(t3, slot) {
635
- return t3.markoPlaceholder(
636
- t3.callExpression(
637
- t3.memberExpression(
638
- t3.identifier("$global"),
639
- t3.identifier("___viteRenderAssets")
640
- ),
641
- [t3.stringLiteral(slot)]
642
- ),
643
- false
644
- );
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;
645
566
  }
567
+ process.once("beforeExit", (code) => {
568
+ if (code === 0 && values.size) {
569
+ fs3.writeFile(tmpFile, JSON.stringify([...values])).catch(noop);
570
+ }
571
+ });
646
572
 
647
573
  // src/relative-assets-transform.ts
648
574
  var attrSrc = /* @__PURE__ */ new Set(["src"]);
@@ -691,103 +617,176 @@ function transform(tag, t3) {
691
617
  }
692
618
  }
693
619
 
694
- // src/glob-import-transform.ts
695
- import { types as t2 } from "@marko/compiler";
696
- import glob from "fast-glob";
697
- import path4 from "path";
698
- var programGlobImports = /* @__PURE__ */ new WeakMap();
699
- var glob_import_transform_default = {
700
- MetaProperty(tag) {
701
- const memberExpression2 = tag.parentPath;
702
- if (memberExpression2.node.type === "MemberExpression" && memberExpression2.node.property.type === "Identifier" && memberExpression2.node.property.name === "glob") {
703
- const callExpression = memberExpression2.parentPath;
704
- if (callExpression?.node.type === "CallExpression") {
705
- const args = callExpression.get("arguments").map((arg) => arg.evaluate().value);
706
- if (args[1]?.eager) {
707
- const program = tag.hub.file.path;
708
- const existing = programGlobImports.get(program);
709
- if (!existing) {
710
- programGlobImports.set(program, [args]);
711
- } else {
712
- 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)};\`;
713
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>\`;
714
690
  }
715
- }
716
- }
717
- },
718
- Program: {
719
- exit(tag) {
720
- const globImports = programGlobImports.get(tag);
721
- if (!globImports) {
722
- return;
723
- }
724
- const { cwd, filename } = tag.hub.file.opts;
725
- const dir = path4.dirname(filename);
726
- const seen = /* @__PURE__ */ new Set();
727
- for (const [patterns, options] of globImports) {
728
- const resolvedPatterns = Array.isArray(patterns) ? patterns.map((p) => path4.resolve(dir, p)) : path4.resolve(dir, patterns);
729
- const results = glob.globSync(resolvedPatterns, {
730
- cwd,
731
- absolute: true,
732
- dot: !!options.exhaustive,
733
- ignore: options.exhaustive ? [] : [path4.join(cwd, "**/node_modules/**")]
734
- });
735
- for (const file of results) {
736
- if (file.endsWith(".marko") && file !== filename && !seen.has(file)) {
737
- seen.add(file);
738
- 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;
739
718
  }
740
719
  }
741
720
  }
742
721
  }
743
722
  }
744
- };
745
723
 
746
- // src/read-once-persisted-store.ts
747
- import os from "os";
748
- import path5 from "path";
749
- import { promises as fs3 } from "fs";
750
- var noop = () => {
751
- };
752
- var tmpFile = path5.join(os.tmpdir(), "marko-vite-storage.json");
753
- var values = /* @__PURE__ */ new Map();
754
- var loadedFromDisk;
755
- var ReadOncePersistedStore = class {
756
- constructor(uid) {
757
- this.uid = uid;
758
- }
759
- write(value) {
760
- values.set(this.uid, value);
761
- }
762
- async read() {
763
- const { uid } = this;
764
- if (values.has(uid)) {
765
- const value = values.get(uid);
766
- values.delete(uid);
767
- return value;
768
- }
769
- if (loadedFromDisk === true) {
770
- throw new Error(`Value for ${uid} could not be loaded.`);
771
- }
772
- await (loadedFromDisk ||= fs3.readFile(tmpFile, "utf-8").then(syncDataFromDisk).catch(finishLoadFromDisk));
773
- 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));
774
736
  }
775
737
  };
776
- function syncDataFromDisk(data) {
777
- finishLoadFromDisk();
778
- fs3.unlink(tmpFile).catch(noop);
779
- for (const [k, v] of JSON.parse(data)) {
780
- values.set(k, v);
781
- }
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
+ );
782
749
  }
783
- function finishLoadFromDisk() {
784
- 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);
785
761
  }
786
- process.once("beforeExit", (code) => {
787
- if (code === 0 && values.size) {
788
- 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
+ `;
789
771
  }
790
- });
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
+ };
791
790
 
792
791
  // src/index.ts
793
792
  var POSIX_SEP = "/";
@@ -812,6 +811,7 @@ var babelCaller = {
812
811
  supportsTopLevelAwait: true,
813
812
  supportsExportNamespaceFrom: true
814
813
  };
814
+ var optimizeKnownTemplatesForRoot = /* @__PURE__ */ new Map();
815
815
  var registeredTagLib = false;
816
816
  var cjsToEsm;
817
817
  function noop2() {
@@ -854,7 +854,6 @@ function markoPlugin(opts = {}) {
854
854
  );
855
855
  const entryIds = /* @__PURE__ */ new Set();
856
856
  const cachedSources = /* @__PURE__ */ new Map();
857
- const optimizedRegisistyIdMap = /* @__PURE__ */ new Map();
858
857
  const transformWatchFiles = /* @__PURE__ */ new Map();
859
858
  const transformOptionalFiles = /* @__PURE__ */ new Map();
860
859
  const store = new ReadOncePersistedStore(
@@ -884,16 +883,7 @@ function markoPlugin(opts = {}) {
884
883
  runtimeId,
885
884
  sourceMaps: true,
886
885
  writeVersionComment: false,
887
- optimizeRegistryId(id) {
888
- let registryId = optimizedRegisistyIdMap.get(id);
889
- if (registryId === void 0) {
890
- optimizedRegisistyIdMap.set(
891
- id,
892
- registryId = optimizedRegisistyIdMap.size
893
- );
894
- }
895
- return registryId;
896
- },
886
+ optimizeKnownTemplates: optimize && linked ? getKnownTemplates(root) : void 0,
897
887
  babelConfig: opts.babelConfig ? {
898
888
  ...opts.babelConfig,
899
889
  caller: opts.babelConfig.caller ? {
@@ -1098,6 +1088,7 @@ function markoPlugin(opts = {}) {
1098
1088
  handleHotUpdate(ctx) {
1099
1089
  compiler2.taglib.clearCaches();
1100
1090
  baseConfig.cache.clear();
1091
+ optimizeKnownTemplatesForRoot.clear();
1101
1092
  for (const [, cache2] of configsByFileSystem) {
1102
1093
  cache2.clear();
1103
1094
  }
@@ -1112,11 +1103,6 @@ function markoPlugin(opts = {}) {
1112
1103
  try {
1113
1104
  serverManifest = await store.read();
1114
1105
  inputOptions.input = toHTMLEntries(root, serverManifest.entries);
1115
- if (serverManifest.registered) {
1116
- for (let i = 0; i < serverManifest.registered.length; i++) {
1117
- optimizedRegisistyIdMap.set(serverManifest.registered[i], i);
1118
- }
1119
- }
1120
1106
  for (const entry in serverManifest.entrySources) {
1121
1107
  const id = normalizePath(path6.resolve(root, entry));
1122
1108
  entryIds.add(id);
@@ -1381,9 +1367,6 @@ if (import.meta.hot) import.meta.hot.accept(() => {});`;
1381
1367
  }
1382
1368
  }
1383
1369
  }
1384
- if (optimizedRegisistyIdMap.size) {
1385
- serverManifest.registered = [...optimizedRegisistyIdMap.keys()];
1386
- }
1387
1370
  store.write(serverManifest);
1388
1371
  } else {
1389
1372
  const browserManifest = {};
@@ -1512,6 +1495,33 @@ function getConfigForFileSystem(info, config) {
1512
1495
  }
1513
1496
  return configForFileSystem;
1514
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
+ }
1515
1525
  export {
1516
1526
  markoPlugin as default
1517
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.6",
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\"",