@nuxt/scripts 0.6.2 → 0.6.4

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 (100) hide show
  1. package/dist/client/200.html +43 -43
  2. package/dist/client/404.html +43 -43
  3. package/dist/client/_nuxt/{G-Jz5hiA.js → 0ooBkv16.js} +1 -1
  4. package/dist/client/_nuxt/{CNkYXcD4.js → 1rqFXsGc.js} +2 -2
  5. package/dist/client/_nuxt/B8kiEHWd.js +31 -0
  6. package/dist/client/_nuxt/{BOnd8D4O.js → BB42E8aY.js} +3 -3
  7. package/dist/client/_nuxt/{GPY1wEXZ.js → BBBqETUW.js} +1 -1
  8. package/dist/client/_nuxt/{Buoqr_Oi.js → BMHPAh1U.js} +1 -1
  9. package/dist/client/_nuxt/BVLuctcA.js +1 -0
  10. package/dist/client/_nuxt/BVkeqZ59.js +1 -0
  11. package/dist/client/_nuxt/{DISxKEhY.js → Bdt_eLrj.js} +1 -1
  12. package/dist/client/_nuxt/{Dez-Qvcc.js → BeJnKnI_.js} +2 -2
  13. package/dist/client/_nuxt/{DG8tVHNj.js → Bi43K_FX.js} +1 -1
  14. package/dist/client/_nuxt/{BdfWgkoX.js → BnyYJeap.js} +1 -1
  15. package/dist/client/_nuxt/{wKgfcFVx.js → C1yTBzia.js} +1 -1
  16. package/dist/client/_nuxt/{o-cPXEvd.js → CBWrHyXe.js} +89 -84
  17. package/dist/client/_nuxt/CCqFro8U.js +3 -0
  18. package/dist/client/_nuxt/{C2pTd85Q.js → CE8XWCBP.js} +1 -1
  19. package/dist/client/_nuxt/CFF2d1j6.js +1 -0
  20. package/dist/client/_nuxt/{Lpdzc9s2.js → CJGKC1_q.js} +1 -1
  21. package/dist/client/_nuxt/{CcYwH0AH.js → CJIaz0BQ.js} +1 -1
  22. package/dist/client/_nuxt/CO7HdiM_.js +1 -0
  23. package/dist/client/_nuxt/Cb-F_BZP.js +1 -0
  24. package/dist/client/_nuxt/CgwOUXSn.js +1 -0
  25. package/dist/client/_nuxt/ChH25C4w.js +1 -0
  26. package/dist/client/_nuxt/{D4FSFK-1.js → D33OKbkv.js} +1 -1
  27. package/dist/client/_nuxt/{YdT6Gj0u.js → D7WeZTai.js} +1 -1
  28. package/dist/client/_nuxt/{DUdlC5k_.js → DJubGRtk.js} +1 -1
  29. package/dist/client/_nuxt/{C5gCGmDW.js → DK4oFTHQ.js} +1 -1
  30. package/dist/client/_nuxt/DM4HHECw.js +1 -0
  31. package/dist/client/_nuxt/DOqtC9FP.js +1 -0
  32. package/dist/client/_nuxt/{RyEv5ndP.js → DUCgB8kF.js} +1 -1
  33. package/dist/client/_nuxt/DV9JwLIa.js +1 -0
  34. package/dist/client/_nuxt/{BN0jYG70.js → DX8FDaDx.js} +1 -1
  35. package/dist/client/_nuxt/{zhgf4ixb.js → DrnZp123.js} +2 -2
  36. package/dist/client/_nuxt/{COIrKlfF.js → ECt0lbkd.js} +1 -1
  37. package/dist/client/_nuxt/builds/latest.json +1 -1
  38. package/dist/client/_nuxt/builds/meta/a56fe5f5-907d-4907-9967-836d6a0f3850.json +1 -0
  39. package/dist/client/_nuxt/cw46T5ID.js +61 -0
  40. package/dist/client/_nuxt/error-404.-RjlvToe.css +1 -0
  41. package/dist/client/_nuxt/error-500.Bz7LXgZy.css +1 -0
  42. package/dist/client/_nuxt/{D_T9yQUo.js → kuh6G-Sk.js} +2 -2
  43. package/dist/client/_nuxt/qxoleWdb.js +1 -0
  44. package/dist/client/_nuxt/{xtV5iK4E.js → yX2IItqj.js} +1 -1
  45. package/dist/client/index.html +43 -43
  46. package/dist/module.json +1 -1
  47. package/dist/module.mjs +84 -280
  48. package/dist/registry.mjs +33 -0
  49. package/dist/runtime/composables/useScript.js +1 -1
  50. package/dist/runtime/registry/clarity.js +1 -1
  51. package/dist/runtime/registry/cloudflare-web-analytics.js +1 -1
  52. package/dist/runtime/registry/crisp.d.ts +1 -1
  53. package/dist/runtime/registry/crisp.js +1 -1
  54. package/dist/runtime/registry/fathom-analytics.d.ts +1 -1
  55. package/dist/runtime/registry/fathom-analytics.js +1 -1
  56. package/dist/runtime/registry/google-adsense.d.ts +1 -1
  57. package/dist/runtime/registry/google-adsense.js +1 -1
  58. package/dist/runtime/registry/google-analytics.d.ts +13 -0
  59. package/dist/runtime/registry/google-analytics.js +31 -0
  60. package/dist/runtime/registry/google-maps.js +1 -1
  61. package/dist/runtime/registry/google-tag-manager.d.ts +13 -0
  62. package/dist/runtime/registry/google-tag-manager.js +27 -0
  63. package/dist/runtime/registry/hotjar.d.ts +1 -1
  64. package/dist/runtime/registry/hotjar.js +1 -1
  65. package/dist/runtime/registry/intercom.d.ts +1 -1
  66. package/dist/runtime/registry/intercom.js +1 -1
  67. package/dist/runtime/registry/lemon-squeezy.js +1 -1
  68. package/dist/runtime/registry/matomo-analytics.d.ts +1 -1
  69. package/dist/runtime/registry/matomo-analytics.js +1 -1
  70. package/dist/runtime/registry/meta-pixel.d.ts +1 -1
  71. package/dist/runtime/registry/meta-pixel.js +1 -1
  72. package/dist/runtime/registry/npm.d.ts +1 -1
  73. package/dist/runtime/registry/npm.js +1 -1
  74. package/dist/runtime/registry/plausible-analytics.js +1 -1
  75. package/dist/runtime/registry/segment.js +1 -1
  76. package/dist/runtime/registry/stripe.js +1 -1
  77. package/dist/runtime/registry/vimeo-player.js +1 -1
  78. package/dist/runtime/registry/x-pixel.d.ts +1 -1
  79. package/dist/runtime/registry/x-pixel.js +1 -1
  80. package/dist/runtime/registry/youtube-player.js +1 -1
  81. package/dist/runtime/types.d.ts +23 -7
  82. package/dist/runtime/utils.js +5 -1
  83. package/package.json +15 -14
  84. package/dist/client/_nuxt/B2BuIiKK.js +0 -1
  85. package/dist/client/_nuxt/B474tPdy.js +0 -66
  86. package/dist/client/_nuxt/BJn7Ek5W.js +0 -1
  87. package/dist/client/_nuxt/Bfj2ThZ4.js +0 -3
  88. package/dist/client/_nuxt/BmSZh3NL.js +0 -1
  89. package/dist/client/_nuxt/BrGg7AAd.js +0 -1
  90. package/dist/client/_nuxt/CBL0qBdF.js +0 -1
  91. package/dist/client/_nuxt/CHCTrc3a.js +0 -1
  92. package/dist/client/_nuxt/CIekO_uJ.js +0 -1
  93. package/dist/client/_nuxt/D7gg1Usp.js +0 -1
  94. package/dist/client/_nuxt/DDRuGeQH.js +0 -1
  95. package/dist/client/_nuxt/DKGhHdqV.js +0 -31
  96. package/dist/client/_nuxt/Djqq6n-7.js +0 -1
  97. package/dist/client/_nuxt/Dkb1Nx48.js +0 -1
  98. package/dist/client/_nuxt/builds/meta/45651e0f-66c7-4ff4-acab-e2f5a76c99b2.json +0 -1
  99. package/dist/client/_nuxt/error-404.DXyehy0d.css +0 -1
  100. package/dist/client/_nuxt/error-500.a_92Fvyl.css +0 -1
package/dist/module.mjs CHANGED
@@ -1,14 +1,14 @@
1
- import { useNuxt, useLogger, addDevServerHandler, createResolver, addTemplate, tryUseNuxt, logger as logger$1, addImports, defineNuxtModule, addBuildPlugin, addImportsDir, addComponentsDir, addPluginTemplate, hasNuxtModule } from '@nuxt/kit';
1
+ import { useNuxt, useLogger, addDevServerHandler, createResolver, addTemplate, tryUseNuxt, logger as logger$1, defineNuxtModule, addImportsDir, addComponentsDir, addImports, addPluginTemplate, addBuildPlugin, hasNuxtModule } from '@nuxt/kit';
2
2
  import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
3
3
  import { lt } from 'semver';
4
4
  import { resolvePath } from 'mlly';
5
- import { join, relative, extname } from 'pathe';
5
+ import { join, relative } from 'pathe';
6
6
  import { existsSync } from 'node:fs';
7
- import { pathToFileURL } from 'node:url';
8
7
  import { createUnplugin } from 'unplugin';
9
- import { parseURL, parseQuery, joinURL, hasProtocol } from 'ufo';
10
8
  import MagicString from 'magic-string';
11
9
  import { walk } from 'estree-walker';
10
+ import { pathToFileURL } from 'node:url';
11
+ import { parseURL, parseQuery, joinURL, hasProtocol } from 'ufo';
12
12
  import fsp from 'node:fs/promises';
13
13
  import { lazyEventHandler, eventHandler, createError } from 'h3';
14
14
  import { fetch } from 'ofetch';
@@ -19,10 +19,7 @@ import { createStorage } from 'unstorage';
19
19
  import fsDriver from 'unstorage/drivers/fs-lite';
20
20
  import { isCI, provider } from 'std-env';
21
21
  import { registry } from './registry.mjs';
22
- import { GooglaAnalyticsData, GoogleAnalytics, GoogleTagManagerData, GoogleTagManager } from 'third-party-capital';
23
- import { genTypeImport, genImport } from 'knitwork';
24
- import { parse } from 'acorn';
25
- import { transform } from 'esbuild';
22
+ import 'third-party-capital';
26
23
 
27
24
  const DEVTOOLS_UI_ROUTE = "/__nuxt-scripts";
28
25
  const DEVTOOLS_UI_LOCAL_PORT = 3300;
@@ -67,20 +64,39 @@ function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
67
64
  });
68
65
  }
69
66
 
67
+ function isVue(id, opts = {}) {
68
+ const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
69
+ if (id.endsWith(".vue") && !search) {
70
+ return true;
71
+ }
72
+ if (!search) {
73
+ return false;
74
+ }
75
+ const query = parseQuery(search);
76
+ if (query.nuxt_component) {
77
+ return false;
78
+ }
79
+ if (query.macro && (search === "?macro=true" || !opts.type || opts.type.includes("script"))) {
80
+ return true;
81
+ }
82
+ const type = "setup" in query ? "script" : query.type;
83
+ if (!("vue" in query) || opts.type && !opts.type.includes(type)) {
84
+ return false;
85
+ }
86
+ return true;
87
+ }
88
+ const JS_RE = /\.(?:[cm]?j|t)sx?$/;
89
+ function isJS(id) {
90
+ const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href));
91
+ return JS_RE.test(pathname);
92
+ }
93
+
70
94
  function NuxtScriptBundleTransformer(options) {
71
95
  return createUnplugin(() => {
72
96
  return {
73
97
  name: "nuxt:scripts:bundler-transformer",
74
98
  transformInclude(id) {
75
- const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
76
- const { type } = parseQuery(search);
77
- if (pathname.includes("node_modules/@unhead") || pathname.includes("node_modules/vueuse"))
78
- return false;
79
- if (pathname.endsWith(".vue") && (type === "script" || !search))
80
- return true;
81
- if (pathname.match(/\.((c|m)?j|t)sx?$/g))
82
- return true;
83
- return false;
99
+ return isVue(id, { type: ["template", "script"] }) || isJS(id);
84
100
  },
85
101
  async transform(code, id) {
86
102
  if (!code.includes("useScript"))
@@ -362,270 +378,58 @@ function installNuxtModule(name, options) {
362
378
  }, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
363
379
  }
364
380
 
365
- const HEAD_VAR = "__head";
366
- const INJECTHEAD_CODE = `const ${HEAD_VAR} = injectHead()`;
367
- function getTpcScriptContent(input) {
368
- const nuxt = useNuxt();
369
- if (!input.data.scripts)
370
- throw new Error("input.data has no scripts !");
371
- const mainScript = input.data.scripts?.find(({ key }) => key === input.tpcKey);
372
- if (!mainScript)
373
- throw new Error(`no main script found for ${input.tpcKey} in third-party-capital`);
374
- const mainScriptOptions = getScriptInputOption(mainScript);
375
- const imports = /* @__PURE__ */ new Set([
376
- "import { withQuery } from 'ufo'",
377
- "import { useRegistryScript } from '#nuxt-scripts-utils'",
378
- "import type { RegistryScriptInput } from '#nuxt-scripts'"
379
- ]);
380
- const chunks = [];
381
- const functionBody = [];
382
- const hasParams = mainScript.params?.length;
383
- if (input.tpcTypeImport) {
384
- imports.add(genTypeImport("third-party-capital", [input.tpcTypeImport]));
385
- }
386
- if (hasParams) {
387
- imports.add(genImport("#nuxt-scripts-validator", ["object", "any"]));
388
- chunks.push(`const OptionSchema = object({${mainScript.params?.map((p) => `${p}: any()`)}})`);
389
- }
390
- chunks.push(`
391
- declare global {
392
- interface Window extends ${input.tpcTypeImport} {}
393
- }`);
394
- const clientInitCode = [];
395
- if (input.data.stylesheets) {
396
- if (!functionBody.includes(INJECTHEAD_CODE)) {
397
- functionBody.unshift(INJECTHEAD_CODE);
398
- }
399
- functionBody.push(`${HEAD_VAR}.push({link: ${JSON.stringify(input.data.stylesheets.map((s) => ({ ref: "stylesheet", href: s })))}})`);
400
- }
401
- for (const script of input.data.scripts) {
402
- if ("code" in script)
403
- clientInitCode.push(replaceTokenToRuntime(script.code));
404
- if (script === mainScript)
405
- continue;
406
- if ("url" in script) {
407
- functionBody.push(`${HEAD_VAR}.push({scripts:{ async: true, src: ${script.url} }},${JSON.stringify(getScriptInputOption(script))})`);
408
- }
409
- }
410
- chunks.push(`export type Input = RegistryScriptInput${hasParams ? "<typeof OptionSchema>" : ""}`);
411
- chunks.push(`
412
- export function ${input.scriptFunctionName}<T extends ${input.tpcTypeImport}>(_options?: Input) {
413
- ${functionBody.join("\n")}
414
- return useRegistryScript${hasParams ? "<T, typeof OptionSchema>" : ""}('${input.tpcKey}', options => ({
415
- scriptInput: {
416
- src: withQuery('${mainScript.url}', {${mainScript.params?.map((p) => `${p}: options?.${p}`)}})
417
- },
418
- ${nuxt.options.dev ? "schema: OptionSchema," : ""}
419
- scriptOptions: {
420
- use: ${input.use.toString()},
421
- stub: import.meta.client ? undefined : ${input.stub.toString()},
422
- ${mainScriptOptions ? `...(${JSON.stringify(mainScriptOptions)})` : ""}
423
- },
424
- ${clientInitCode.length ? `clientInit: import.meta.server ? undefined : () => {${clientInitCode.join("\n")}},` : ""}
425
- }), _options)
426
- }`);
427
- chunks.unshift(...Array.from(imports));
428
- return chunks.join("\n");
429
- }
430
- function replaceTokenToRuntime(code) {
431
- return code.split(";").map((c) => c.replaceAll(/'?\{\{(.*?)\}\}'?/g, "options.$1")).join(";");
432
- }
433
- function getScriptInputOption(script) {
434
- if (script.location === "body") {
435
- if (script.action === "append") {
436
- return { tagPosition: "bodyClose" };
437
- }
438
- return { tagPosition: "bodyOpen" };
439
- }
440
- if (script.action === "append") {
441
- return { tagPriority: 1 };
442
- }
443
- }
444
-
445
- function googleAnalitycsRegistry() {
446
- const nuxt = useNuxt();
447
- const { dst } = addTemplate({
448
- getContents() {
449
- return getTpcScriptContent({
450
- data: GooglaAnalyticsData,
451
- scriptFunctionName: "useScriptGoogleAnalytics",
452
- use: () => {
453
- return { dataLayer: window.dataLayer, gtag: window.gtag };
454
- },
455
- // allow dataLayer to be accessed on the server
456
- stub: ({ fn }) => {
457
- return fn === "dataLayer" ? [] : void 0;
458
- },
459
- tpcKey: "gtag",
460
- tpcTypeImport: "GoogleAnalyticsApi"
461
- });
462
- },
463
- filename: "nuxt-scripts/tpc/google-analytics.ts",
464
- write: true
465
- });
466
- addImports({
467
- from: dst,
468
- name: "useScriptGoogleAnalytics"
469
- });
470
- const registry = {
471
- label: "Google Tag Manager",
472
- category: "tracking",
473
- logo: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="#8AB4F8" d="m150.262 245.516l-44.437-43.331l95.433-97.454l46.007 45.091z"/><path fill="#4285F4" d="M150.45 53.938L106.176 8.731L9.36 104.629c-12.48 12.48-12.48 32.713 0 45.207l95.36 95.986l45.09-42.182l-72.654-76.407z"/><path fill="#8AB4F8" d="m246.625 105.37l-96-96c-12.494-12.494-32.756-12.494-45.25 0c-12.495 12.495-12.495 32.757 0 45.252l96 96c12.494 12.494 32.756 12.494 45.25 0c12.495-12.495 12.495-32.757 0-45.251"/><circle cx="127.265" cy="224.731" r="31.273" fill="#246FDB"/></svg>`,
474
- import: {
475
- name: "useScriptGoogleAnalytics",
476
- from: dst
477
- },
478
- scriptBundling(options) {
479
- const data = GoogleAnalytics(options);
480
- const mainScript = data.scripts?.find(({ key }) => key === "gtag");
481
- if (mainScript && "url" in mainScript && mainScript.url)
482
- return mainScript.url;
483
- return false;
484
- }
485
- };
486
- nuxt.hook("scripts:registry", (scripts) => {
487
- scripts.push(registry);
488
- });
489
- }
490
-
491
- function googleTagManagerRegistry() {
492
- const nuxt = useNuxt();
493
- const { dst } = addTemplate({
494
- getContents() {
495
- return getTpcScriptContent({
496
- data: GoogleTagManagerData,
497
- scriptFunctionName: "useScriptGoogleTagManager",
498
- use: () => {
499
- return { dataLayer: window.dataLayer, google_tag_manager: window.google_tag_manager };
500
- },
501
- stub: ({ fn }) => {
502
- return fn === "dataLayer" ? [] : void 0;
503
- },
504
- tpcKey: "gtm",
505
- tpcTypeImport: "GoogleTagManagerApi"
506
- });
507
- },
508
- filename: "nuxt-scripts/tpc/google-tag-manager.ts",
509
- write: true
510
- });
511
- addImports({
512
- from: dst,
513
- name: "useScriptGoogleTagManager"
514
- });
515
- const registry = {
516
- label: "Google Tag Manager",
517
- category: "tracking",
518
- logo: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="#8AB4F8" d="m150.262 245.516l-44.437-43.331l95.433-97.454l46.007 45.091z"/><path fill="#4285F4" d="M150.45 53.938L106.176 8.731L9.36 104.629c-12.48 12.48-12.48 32.713 0 45.207l95.36 95.986l45.09-42.182l-72.654-76.407z"/><path fill="#8AB4F8" d="m246.625 105.37l-96-96c-12.494-12.494-32.756-12.494-45.25 0c-12.495 12.495-12.495 32.757 0 45.252l96 96c12.494 12.494 32.756 12.494 45.25 0c12.495-12.495 12.495-32.757 0-45.251"/><circle cx="127.265" cy="224.731" r="31.273" fill="#246FDB"/></svg>`,
519
- import: {
520
- name: "useScriptGoogleTagManager",
521
- from: dst
522
- },
523
- scriptBundling(options) {
524
- const data = GoogleTagManager(options);
525
- const mainScript = data.scripts?.find(({ key }) => key === "gtm");
526
- if (mainScript && "url" in mainScript && mainScript.url)
527
- return mainScript.url;
528
- return false;
529
- }
530
- };
531
- nuxt.hook("scripts:registry", (scripts) => {
532
- scripts.push(registry);
533
- });
534
- }
535
-
536
- const SCRIPT_RE = /<script[^>]*>([\s\S]*)<\/script>/;
537
- const checkScripts = () => createUnplugin(() => {
538
- return {
539
- name: "nuxt-scripts:check-scripts",
540
- enforce: "pre",
541
- async transform(code, id) {
542
- if (!code.includes("useScript"))
543
- return;
544
- const extName = extname(id);
545
- if (extName === ".vue") {
546
- const scriptAst = await extractScriptContentAst(code);
547
- if (scriptAst) {
548
- analyzeNodes(id, scriptAst);
549
- }
550
- } else if (extName === ".ts" || extName === ".js") {
551
- if (!code.includes("defineComponent"))
381
+ function NuxtScriptsCheckScripts() {
382
+ return createUnplugin(() => {
383
+ return {
384
+ name: "nuxt-scripts:check-scripts",
385
+ transformInclude(id) {
386
+ return isVue(id, { type: ["script"] });
387
+ },
388
+ async transform(code) {
389
+ if (!code.includes("useScript"))
552
390
  return;
553
- let result = code;
554
- if (extName === ".ts") {
555
- result = (await transform(code, { loader: "ts" })).code;
556
- }
557
- const setupFunction = extractSetupFunction(result);
558
- if (setupFunction) {
559
- analyzeNodes(id, setupFunction);
560
- }
561
- }
562
- return void 0;
563
- }
564
- };
565
- });
566
- function analyzeNodes(id, nodes) {
567
- let name;
568
- for (const node of nodes) {
569
- if (name) {
570
- if (isAwaitingLoad(name, node)) {
571
- throw new Error("Awaiting load should not be used at top level of a composable or <script>");
572
- }
573
- } else {
574
- if (node.type === "VariableDeclaration") {
575
- name = findScriptVar(node.declarations[0]);
576
- }
577
- }
578
- }
579
- }
580
- function findScriptVar(scriptDeclaration) {
581
- if (scriptDeclaration.id.type === "ObjectPattern") {
582
- for (const property of scriptDeclaration.id.properties) {
583
- if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
584
- return property.value.name;
585
- }
586
- }
587
- } else if (scriptDeclaration.id.type === "Identifier") {
588
- return scriptDeclaration.id.name;
589
- }
590
- }
591
- function isAwaitingLoad(name, node) {
592
- if (node.type === "ExpressionStatement" && node.expression.type === "AwaitExpression") {
593
- const arg = node.expression.argument;
594
- if (arg.type === "CallExpression") {
595
- const callee = arg.callee;
596
- if (callee.type === "MemberExpression" && callee.object.type === "Identifier" && callee.object.name === name) {
597
- if (callee.property.type === "Identifier" && callee.property.name === "load") {
598
- return true;
391
+ const ast = this.parse(code);
392
+ let nameNode;
393
+ let errorNode;
394
+ walk(ast, {
395
+ enter(_node) {
396
+ if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
397
+ const objPattern = _node.declarations[0]?.id;
398
+ for (const property of objPattern.properties) {
399
+ if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
400
+ nameNode = _node;
401
+ }
402
+ }
403
+ }
404
+ if (nameNode) {
405
+ let sequence = _node.type === "SequenceExpression" ? _node : null;
406
+ let assignmentExpression;
407
+ if (_node.type === "VariableDeclaration") {
408
+ if (_node.declarations[0]?.init?.type === "SequenceExpression") {
409
+ sequence = _node.declarations[0]?.init;
410
+ assignmentExpression = _node.declarations[0]?.init?.expressions?.[0];
411
+ }
412
+ }
413
+ if (sequence && !assignmentExpression) {
414
+ assignmentExpression = sequence.expressions[0]?.type === "AssignmentExpression" ? sequence.expressions[0] : null;
415
+ }
416
+ if (assignmentExpression) {
417
+ const right = assignmentExpression?.right;
418
+ if (right.callee?.name === "_withAsyncContext") {
419
+ if (right.arguments[0]?.body?.name === "$script" || right.arguments[0]?.body?.callee?.object?.name === "$script") {
420
+ errorNode = nameNode;
421
+ }
422
+ }
423
+ }
424
+ }
425
+ }
426
+ });
427
+ if (errorNode) {
428
+ return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
599
429
  }
600
430
  }
601
- }
602
- }
603
- }
604
- async function extractScriptContentAst(code) {
605
- const scriptCode = code.match(SCRIPT_RE);
606
- return scriptCode ? parse((await transform(scriptCode[1], { loader: "ts" })).code, {
607
- ecmaVersion: "latest",
608
- sourceType: "module"
609
- }).body : void 0;
610
- }
611
- function extractSetupFunction(code) {
612
- const ast = parse(code, {
613
- ecmaVersion: "latest",
614
- sourceType: "module"
431
+ };
615
432
  });
616
- const defaultExport = ast.body.find((node) => node.type === "ExportDefaultDeclaration");
617
- if (defaultExport && defaultExport.declaration.type === "CallExpression" && defaultExport.declaration.callee.type === "Identifier" && defaultExport.declaration.callee.name === "defineComponent") {
618
- const arg = defaultExport.declaration.arguments[0];
619
- if (arg && arg.type === "ObjectExpression") {
620
- const setupProperty = arg.properties.find((prop) => prop.type === "Property" && prop.key.type === "Identifier" && prop.key.name === "setup");
621
- if (setupProperty) {
622
- const setupValue = setupProperty.value;
623
- if (setupValue.type === "FunctionExpression") {
624
- return setupValue.body.body;
625
- }
626
- }
627
- }
628
- }
629
433
  }
630
434
 
631
435
  function templatePlugin(config, registry) {
@@ -700,7 +504,6 @@ const module = defineNuxtModule({
700
504
  return;
701
505
  }
702
506
  }
703
- addBuildPlugin(checkScripts());
704
507
  nuxt.options.alias["#nuxt-scripts-validator"] = resolve(`./runtime/validation/${nuxt.options.dev || nuxt.options._prepare ? "valibot" : "mock"}`);
705
508
  nuxt.options.alias["#nuxt-scripts"] = resolve("./runtime/types");
706
509
  nuxt.options.alias["#nuxt-scripts-utils"] = resolve("./runtime/utils");
@@ -720,8 +523,6 @@ const module = defineNuxtModule({
720
523
  path: resolve("./runtime/components")
721
524
  });
722
525
  const scripts = registry(resolve);
723
- googleAnalitycsRegistry();
724
- googleTagManagerRegistry();
725
526
  nuxt.hooks.hook("modules:done", async () => {
726
527
  const registryScripts = [...scripts];
727
528
  await nuxt.hooks.callHook("scripts:registry", registryScripts);
@@ -772,6 +573,9 @@ ${newScripts.map((i) => {
772
573
  const scriptMap = /* @__PURE__ */ new Map();
773
574
  const { normalizeScriptData } = setupPublicAssetStrategy(config.assets);
774
575
  const moduleInstallPromises = /* @__PURE__ */ new Map();
576
+ addBuildPlugin(NuxtScriptsCheckScripts(), {
577
+ dev: true
578
+ });
775
579
  addBuildPlugin(NuxtScriptBundleTransformer({
776
580
  scripts: registryScriptsWithImport,
777
581
  defaultBundle: config.defaultScriptOptions?.bundle,
package/dist/registry.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import { joinURL, withQuery, withBase } from 'ufo';
2
+ import { GoogleTagManager, GoogleAnalytics } from 'third-party-capital';
2
3
 
3
4
  const registry = (resolve) => {
4
5
  resolve = resolve || ((s) => s);
@@ -219,6 +220,38 @@ const registry = (resolve) => {
219
220
  // key is based on package name
220
221
  from: resolve("./runtime/registry/npm")
221
222
  }
223
+ },
224
+ {
225
+ label: "Google Tag Manager",
226
+ category: "tracking",
227
+ import: {
228
+ name: "useScriptGoogleTagManager",
229
+ from: resolve("./runtime/registry/google-tag-manager")
230
+ },
231
+ logo: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="#8AB4F8" d="m150.262 245.516l-44.437-43.331l95.433-97.454l46.007 45.091z"/><path fill="#4285F4" d="M150.45 53.938L106.176 8.731L9.36 104.629c-12.48 12.48-12.48 32.713 0 45.207l95.36 95.986l45.09-42.182l-72.654-76.407z"/><path fill="#8AB4F8" d="m246.625 105.37l-96-96c-12.494-12.494-32.756-12.494-45.25 0c-12.495 12.495-12.495 32.757 0 45.252l96 96c12.494 12.494 32.756 12.494 45.25 0c12.495-12.495 12.495-32.757 0-45.251"/><circle cx="127.265" cy="224.731" r="31.273" fill="#246FDB"/></svg>`,
232
+ scriptBundling(options) {
233
+ const data = GoogleTagManager(options);
234
+ const mainScript = data.scripts?.find(({ key }) => key === "gtag");
235
+ if (mainScript && "url" in mainScript && mainScript.url)
236
+ return mainScript.url;
237
+ return false;
238
+ }
239
+ },
240
+ {
241
+ label: "Google Analytics",
242
+ category: "tracking",
243
+ import: {
244
+ name: "useScriptGoogleAnalytics",
245
+ from: resolve("./runtime/registry/google-analytics")
246
+ },
247
+ logo: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="#8AB4F8" d="m150.262 245.516l-44.437-43.331l95.433-97.454l46.007 45.091z"/><path fill="#4285F4" d="M150.45 53.938L106.176 8.731L9.36 104.629c-12.48 12.48-12.48 32.713 0 45.207l95.36 95.986l45.09-42.182l-72.654-76.407z"/><path fill="#8AB4F8" d="m246.625 105.37l-96-96c-12.494-12.494-32.756-12.494-45.25 0c-12.495 12.495-12.495 32.757 0 45.252l96 96c12.494 12.494 32.756 12.494 45.25 0c12.495-12.495 12.495-32.757 0-45.251"/><circle cx="127.265" cy="224.731" r="31.273" fill="#246FDB"/></svg>`,
248
+ scriptBundling(options) {
249
+ const data = GoogleAnalytics(options);
250
+ const mainScript = data.scripts?.find(({ key }) => key === "gtag");
251
+ if (mainScript && "url" in mainScript && mainScript.url)
252
+ return mainScript.url;
253
+ return false;
254
+ }
222
255
  }
223
256
  ];
224
257
  };
@@ -20,7 +20,7 @@ export function useScript(input, options) {
20
20
  if (!nuxtApp._scripts?.[id]) {
21
21
  performance?.mark?.("mark_feature_usage", {
22
22
  detail: {
23
- feature: `nuxt-scripts:${id}`
23
+ feature: options.performanceMarkFeature ?? `nuxt-scripts:${id}`
24
24
  }
25
25
  });
26
26
  }
@@ -8,7 +8,7 @@ export const ClarityOptions = object({
8
8
  });
9
9
  export function useScriptClarity(_options) {
10
10
  return useRegistryScript(
11
- "clarity",
11
+ _options?.key || "clarity",
12
12
  (options) => ({
13
13
  scriptInput: {
14
14
  src: `https://www.clarity.ms/tag/${options.id}`
@@ -14,7 +14,7 @@ export const CloudflareWebAnalyticsOptions = object({
14
14
  spa: optional(boolean())
15
15
  });
16
16
  export function useScriptCloudflareWebAnalytics(_options) {
17
- return useRegistryScript("cloudflareWebAnalytics", (options) => ({
17
+ return useRegistryScript(_options?.key || "cloudflareWebAnalytics", (options) => ({
18
18
  scriptInput: {
19
19
  "src": "https://static.cloudflareinsights.com/beacon.min.js",
20
20
  "data-cf-beacon": JSON.stringify({ token: options.token, spa: options.spa || true }),
@@ -31,7 +31,7 @@ export declare const CrispOptions: import("valibot").ObjectSchema<{
31
31
  */
32
32
  readonly cookieExpiry: import("valibot").OptionalSchema<import("valibot").NumberSchema<undefined>, never>;
33
33
  }, undefined>;
34
- export type CrispInput = RegistryScriptInput<typeof CrispOptions, false>;
34
+ export type CrispInput = RegistryScriptInput<typeof CrispOptions, false, false, false>;
35
35
  export interface CrispApi {
36
36
  push: (...args: any[]) => void;
37
37
  is: (name: 'chat:opened' | 'chat:closed' | 'chat:visible' | 'chat:hidden' | 'chat:small' | 'chat:large' | 'session:ongoing' | 'website:available' | 'overlay:opened' | 'overlay:closed' | string) => boolean;
@@ -34,7 +34,7 @@ export const CrispOptions = object({
34
34
  });
35
35
  export function useScriptCrisp(_options) {
36
36
  let readyPromise = Promise.resolve();
37
- return useRegistryScript("crisp", (options) => ({
37
+ return useRegistryScript(_options?.key || "crisp", (options) => ({
38
38
  scriptInput: {
39
39
  src: "https://client.crisp.chat/l.js"
40
40
  // can't be bundled
@@ -21,7 +21,7 @@ export declare const FathomAnalyticsOptions: import("valibot").ObjectSchema<{
21
21
  */
22
22
  readonly honorDnt: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, never>;
23
23
  }, undefined>;
24
- export type FathomAnalyticsInput = RegistryScriptInput<typeof FathomAnalyticsOptions, false>;
24
+ export type FathomAnalyticsInput = RegistryScriptInput<typeof FathomAnalyticsOptions, false, false, false>;
25
25
  export interface FathomAnalyticsApi {
26
26
  beacon: (ctx: {
27
27
  url: string;
@@ -23,7 +23,7 @@ export const FathomAnalyticsOptions = object({
23
23
  honorDnt: optional(boolean())
24
24
  });
25
25
  export function useScriptFathomAnalytics(_options) {
26
- return useRegistryScript("fathomAnalytics", (options) => ({
26
+ return useRegistryScript(_options?.key || "fathomAnalytics", (options) => ({
27
27
  scriptInput: {
28
28
  src: "https://cdn.usefathom.com/script.js",
29
29
  // can't be bundled
@@ -5,7 +5,7 @@ export declare const GoogleAdsenseOptions: import("valibot").ObjectSchema<{
5
5
  */
6
6
  readonly client: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, never>;
7
7
  }, undefined>;
8
- export type GoogleAdsenseInput = RegistryScriptInput<typeof GoogleAdsenseOptions>;
8
+ export type GoogleAdsenseInput = RegistryScriptInput<typeof GoogleAdsenseOptions, true, false, false>;
9
9
  export interface GoogleAdsenseApi {
10
10
  /**
11
11
  * The Google Adsense API.
@@ -9,7 +9,7 @@ export const GoogleAdsenseOptions = object({
9
9
  client: optional(string())
10
10
  });
11
11
  export function useScriptGoogleAdsense(_options) {
12
- return useRegistryScript("googleAdsense", (options) => ({
12
+ return useRegistryScript(_options?.key || "googleAdsense", (options) => ({
13
13
  scriptInput: {
14
14
  src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
15
15
  },
@@ -0,0 +1,13 @@
1
+ import type { GoogleAnalyticsApi } from 'third-party-capital';
2
+ import type { RegistryScriptInput } from '#nuxt-scripts';
3
+ export declare const GoogleAnalyticsOptions: import("valibot").ObjectSchema<{
4
+ readonly id: import("valibot").StringSchema<undefined>;
5
+ }, undefined>;
6
+ declare global {
7
+ interface Window extends GoogleAnalyticsApi {
8
+ }
9
+ }
10
+ export type GoogleAnalyticsInput = RegistryScriptInput<typeof GoogleAnalyticsOptions>;
11
+ export declare function useScriptGoogleAnalytics<T extends GoogleAnalyticsApi>(_options?: GoogleAnalyticsInput): T & {
12
+ $script: Promise<T> & import("@unhead/vue").VueScriptInstance<T>;
13
+ };
@@ -0,0 +1,31 @@
1
+ import { withQuery } from "ufo";
2
+ import { useRegistryScript } from "#nuxt-scripts-utils";
3
+ import { object, string } from "#nuxt-scripts-validator";
4
+ export const GoogleAnalyticsOptions = object({ id: string() });
5
+ export function useScriptGoogleAnalytics(_options) {
6
+ return useRegistryScript(_options?.key || "google-analytics", (options) => ({
7
+ scriptInput: {
8
+ src: withQuery("https://www.googletagmanager.com/gtag/js", { id: options?.id })
9
+ },
10
+ schema: import.meta.dev ? void 0 : GoogleAnalyticsOptions,
11
+ scriptOptions: {
12
+ use: () => {
13
+ return { dataLayer: window.dataLayer, gtag: window.gtag };
14
+ },
15
+ stub: import.meta.client ? void 0 : ({ fn }) => {
16
+ return fn === "dataLayer" ? [] : void 0;
17
+ },
18
+ performanceMarkFeature: "nuxt-third-parties-ga",
19
+ ...{ tagPriority: 1 }
20
+ },
21
+ // eslint-disable-next-line
22
+ clientInit: import.meta.server ? void 0 : () => {
23
+ window.dataLayer = window.dataLayer || [];
24
+ window.gtag = function gtag() {
25
+ window.dataLayer.push(arguments);
26
+ };
27
+ window.gtag("js", /* @__PURE__ */ new Date());
28
+ window.gtag("config", options.id);
29
+ }
30
+ }), _options);
31
+ }
@@ -8,7 +8,7 @@ export const GoogleMapsOptions = object({
8
8
  });
9
9
  export function useScriptGoogleMaps(_options) {
10
10
  let readyPromise = Promise.resolve();
11
- return useRegistryScript("googleMaps", (options) => {
11
+ return useRegistryScript(_options?.key || "googleMaps", (options) => {
12
12
  const libraries = options?.libraries || ["places"];
13
13
  return {
14
14
  scriptInput: {
@@ -0,0 +1,13 @@
1
+ import type { GoogleTagManagerApi } from 'third-party-capital';
2
+ import type { RegistryScriptInput } from '#nuxt-scripts';
3
+ export declare const GoogleTagManagerOptions: import("valibot").ObjectSchema<{
4
+ readonly id: import("valibot").StringSchema<undefined>;
5
+ }, undefined>;
6
+ declare global {
7
+ interface Window extends GoogleTagManagerApi {
8
+ }
9
+ }
10
+ export type GoogleTagManagerInput = RegistryScriptInput<typeof GoogleTagManagerOptions>;
11
+ export declare function useScriptGoogleTagManager<T extends GoogleTagManagerApi>(_options?: GoogleTagManagerInput): T & {
12
+ $script: Promise<T> & import("@unhead/vue").VueScriptInstance<T>;
13
+ };