@nuxt/scripts 0.13.2 → 1.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/48AF9EJD.js +1 -0
- package/dist/client/_nuxt/Bk6ed9rg.js +1 -0
- package/dist/client/_nuxt/C4Cj8gBr.js +162 -0
- package/dist/client/_nuxt/{Bje-0OHL.js → DP0kj6Xn.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/919b81d8-ed3a-4222-8a40-df0031cc3b99.json +1 -0
- package/dist/client/_nuxt/entry.D45OuV0w.css +1 -0
- package/dist/client/_nuxt/error-404.B57D-jUQ.css +1 -0
- package/dist/client/_nuxt/error-500.DTHUW7BI.css +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +113 -4
- package/dist/module.d.ts +176 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +780 -299
- package/dist/registry.d.ts +6 -0
- package/dist/registry.mjs +94 -18
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +30 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +40 -15
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +30 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue +12 -12
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.d.vue.ts +21 -9
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +8 -8
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +21 -9
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue +11 -5
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.vue +7 -7
- package/dist/runtime/components/ScriptCrisp.d.vue.ts +1 -1
- package/dist/runtime/components/ScriptCrisp.vue +1 -1
- package/dist/runtime/components/ScriptCrisp.vue.d.ts +1 -1
- package/dist/runtime/components/ScriptGoogleAdsense.vue +1 -1
- package/dist/runtime/components/ScriptInstagramEmbed.d.vue.ts +53 -0
- package/dist/runtime/components/ScriptInstagramEmbed.vue +38 -0
- package/dist/runtime/components/ScriptInstagramEmbed.vue.d.ts +53 -0
- package/dist/runtime/components/ScriptIntercom.d.vue.ts +1 -1
- package/dist/runtime/components/ScriptIntercom.vue +4 -3
- package/dist/runtime/components/ScriptIntercom.vue.d.ts +1 -1
- package/dist/runtime/components/ScriptPayPalButtons.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptPayPalButtons.vue +13 -11
- package/dist/runtime/components/ScriptPayPalButtons.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptPayPalMarks.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptPayPalMarks.vue +10 -8
- package/dist/runtime/components/ScriptPayPalMarks.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptPayPalMessages.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptPayPalMessages.vue +11 -9
- package/dist/runtime/components/ScriptPayPalMessages.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptStripePricingTable.vue +2 -2
- package/dist/runtime/components/ScriptVimeoPlayer.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptVimeoPlayer.vue +1 -1
- package/dist/runtime/components/ScriptVimeoPlayer.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptXEmbed.d.vue.ts +82 -0
- package/dist/runtime/components/ScriptXEmbed.vue +76 -0
- package/dist/runtime/components/ScriptXEmbed.vue.d.ts +82 -0
- package/dist/runtime/components/ScriptYouTubePlayer.d.vue.ts +12 -1
- package/dist/runtime/components/ScriptYouTubePlayer.vue +44 -16
- package/dist/runtime/components/ScriptYouTubePlayer.vue.d.ts +12 -1
- package/dist/runtime/composables/useScript.js +36 -5
- package/dist/runtime/composables/useScriptEventPage.js +2 -2
- package/dist/runtime/composables/useScriptTriggerConsent.js +1 -1
- package/dist/runtime/composables/useScriptTriggerElement.js +1 -1
- package/dist/runtime/composables/useScriptTriggerIdleTimeout.js +1 -1
- package/dist/runtime/composables/useScriptTriggerServiceWorker.d.ts +7 -0
- package/dist/runtime/composables/useScriptTriggerServiceWorker.js +39 -0
- package/dist/runtime/npm-script-stub.d.ts +20 -0
- package/dist/runtime/npm-script-stub.js +73 -0
- package/dist/runtime/registry/clarity.js +21 -25
- package/dist/runtime/registry/cloudflare-web-analytics.js +1 -1
- package/dist/runtime/registry/crisp.js +1 -1
- package/dist/runtime/registry/databuddy-analytics.js +1 -1
- package/dist/runtime/registry/fathom-analytics.js +1 -1
- package/dist/runtime/registry/google-adsense.js +1 -1
- package/dist/runtime/registry/google-analytics.js +2 -2
- package/dist/runtime/registry/google-maps.d.ts +1 -1
- package/dist/runtime/registry/google-maps.js +1 -1
- package/dist/runtime/registry/google-recaptcha.d.ts +27 -0
- package/dist/runtime/registry/google-recaptcha.js +45 -0
- package/dist/runtime/registry/google-sign-in.d.ts +84 -0
- package/dist/runtime/registry/google-sign-in.js +50 -0
- package/dist/runtime/registry/google-tag-manager.d.ts +4 -2
- package/dist/runtime/registry/google-tag-manager.js +16 -6
- package/dist/runtime/registry/hotjar.js +1 -1
- package/dist/runtime/registry/instagram-embed.d.ts +23 -0
- package/dist/runtime/registry/instagram-embed.js +22 -0
- package/dist/runtime/registry/intercom.js +1 -1
- package/dist/runtime/registry/lemon-squeezy.d.ts +0 -1
- package/dist/runtime/registry/matomo-analytics.js +3 -3
- package/dist/runtime/registry/meta-pixel.js +1 -1
- package/dist/runtime/registry/npm.js +1 -1
- package/dist/runtime/registry/paypal.d.ts +1 -1
- package/dist/runtime/registry/paypal.js +2 -2
- package/dist/runtime/registry/plausible-analytics.js +21 -13
- package/dist/runtime/registry/posthog.d.ts +27 -0
- package/dist/runtime/registry/posthog.js +88 -0
- package/dist/runtime/registry/reddit-pixel.js +1 -1
- package/dist/runtime/registry/rybbit-analytics.js +41 -9
- package/dist/runtime/registry/segment.js +1 -1
- package/dist/runtime/registry/snapchat-pixel.js +1 -1
- package/dist/runtime/registry/stripe.d.ts +1 -1
- package/dist/runtime/registry/stripe.js +1 -1
- package/dist/runtime/registry/tiktok-pixel.d.ts +44 -0
- package/dist/runtime/registry/tiktok-pixel.js +44 -0
- package/dist/runtime/registry/umami-analytics.js +1 -1
- package/dist/runtime/registry/vimeo-player.d.ts +2 -2
- package/dist/runtime/registry/vimeo-player.js +1 -1
- package/dist/runtime/registry/x-embed.d.ts +77 -0
- package/dist/runtime/registry/x-embed.js +41 -0
- package/dist/runtime/registry/x-pixel.js +1 -1
- package/dist/runtime/registry/youtube-player.d.ts +7 -7
- package/dist/runtime/registry/youtube-player.js +1 -1
- package/dist/runtime/server/google-static-maps-proxy.d.ts +2 -0
- package/dist/runtime/server/google-static-maps-proxy.js +54 -0
- package/dist/runtime/server/instagram-embed-asset.d.ts +2 -0
- package/dist/runtime/server/instagram-embed-asset.js +42 -0
- package/dist/runtime/server/instagram-embed-image.d.ts +2 -0
- package/dist/runtime/server/instagram-embed-image.js +54 -0
- package/dist/runtime/server/instagram-embed.d.ts +2 -0
- package/dist/runtime/server/instagram-embed.js +91 -0
- package/dist/runtime/server/proxy-handler.d.ts +6 -0
- package/dist/runtime/server/proxy-handler.js +264 -0
- package/dist/runtime/server/utils/privacy.d.ts +141 -0
- package/dist/runtime/server/utils/privacy.js +324 -0
- package/dist/runtime/server/x-embed-image.d.ts +2 -0
- package/dist/runtime/server/x-embed-image.js +53 -0
- package/dist/runtime/server/x-embed.d.ts +49 -0
- package/dist/runtime/server/x-embed.js +31 -0
- package/dist/runtime/types.d.ts +61 -20
- package/dist/runtime/utils/pure.d.ts +9 -0
- package/dist/runtime/utils/pure.js +0 -0
- package/dist/runtime/utils.d.ts +5 -4
- package/dist/runtime/utils.js +12 -2
- package/dist/shared/scripts.DLRgvHQg.mjs +288 -0
- package/dist/stats.d.mts +39 -0
- package/dist/stats.d.ts +39 -0
- package/dist/stats.mjs +711 -0
- package/dist/types.d.mts +1 -1
- package/package.json +59 -46
- package/dist/client/_nuxt/DMut0W-e.js +0 -162
- package/dist/client/_nuxt/builds/meta/5e0206fe-a683-423c-8d59-2596d0b16fee.json +0 -1
- package/dist/client/_nuxt/entry.BjfcJo5q.css +0 -1
- package/dist/client/_nuxt/error-404.B0ZhSNwd.css +0 -1
- package/dist/client/_nuxt/error-500.D4MdgPaC.css +0 -1
- package/dist/client/_nuxt/iNmKC7TZ.js +0 -1
- package/dist/client/_nuxt/rttsH3SL.js +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { computed, onMounted, ref, watch } from "vue";
|
|
3
2
|
import { defu } from "defu";
|
|
4
3
|
import { useHead } from "nuxt/app";
|
|
4
|
+
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
5
5
|
import { useScriptTriggerElement } from "../composables/useScriptTriggerElement";
|
|
6
6
|
import { useScriptYouTubePlayer } from "../registry/youtube-player";
|
|
7
7
|
import ScriptAriaLoadingIndicator from "./ScriptAriaLoadingIndicator.vue";
|
|
@@ -14,12 +14,14 @@ const props = defineProps({
|
|
|
14
14
|
playerVars: { type: null, required: false, default: { autoplay: 0, playsinline: 1 } },
|
|
15
15
|
width: { type: Number, required: false, default: 640 },
|
|
16
16
|
height: { type: Number, required: false, default: 360 },
|
|
17
|
+
ratio: { type: String, required: false, default: "16/9" },
|
|
17
18
|
cookies: { type: Boolean, required: false, default: false },
|
|
18
19
|
playerOptions: { type: null, required: false },
|
|
19
20
|
thumbnailSize: { type: String, required: false, default: "hq720" },
|
|
20
|
-
webp: { type: Boolean, required: false, default: true }
|
|
21
|
+
webp: { type: Boolean, required: false, default: true },
|
|
22
|
+
placeholderObjectFit: { type: String, required: false, default: "cover" }
|
|
21
23
|
});
|
|
22
|
-
const emits = defineEmits(["ready", "state-change", "playback-quality-change", "playback-rate-change", "error"]);
|
|
24
|
+
const emits = defineEmits(["ready", "state-change", "playback-quality-change", "playback-rate-change", "error", "api-change"]);
|
|
23
25
|
const events = [
|
|
24
26
|
"onReady",
|
|
25
27
|
"onStateChange",
|
|
@@ -31,24 +33,48 @@ const events = [
|
|
|
31
33
|
const rootEl = ref();
|
|
32
34
|
const youtubeEl = ref();
|
|
33
35
|
const ready = ref(false);
|
|
36
|
+
const isTriggered = ref(false);
|
|
34
37
|
const trigger = useScriptTriggerElement({ trigger: props.trigger, el: rootEl });
|
|
35
38
|
const script = useScriptYouTubePlayer({
|
|
36
39
|
scriptOptions: {
|
|
40
|
+
// Use immediate trigger so script loads when ANY player needs it
|
|
41
|
+
// Each player will wait for its own trigger before creating iframe
|
|
37
42
|
trigger
|
|
38
43
|
}
|
|
39
44
|
});
|
|
40
45
|
const { onLoaded, status } = script;
|
|
41
46
|
const player = ref();
|
|
42
|
-
|
|
43
|
-
if (
|
|
47
|
+
const clickTriggered = ref(false);
|
|
48
|
+
if (trigger instanceof Promise) {
|
|
44
49
|
trigger.then((triggered) => {
|
|
45
50
|
if (triggered) {
|
|
46
|
-
|
|
51
|
+
isTriggered.value = true;
|
|
52
|
+
if (props.trigger === "mousedown") {
|
|
53
|
+
clickTriggered.value = true;
|
|
54
|
+
}
|
|
47
55
|
}
|
|
48
56
|
});
|
|
57
|
+
} else {
|
|
58
|
+
isTriggered.value = true;
|
|
49
59
|
}
|
|
60
|
+
const stopVideoIdWatch = watch(() => props.videoId, (newId) => {
|
|
61
|
+
if (ready.value && player.value) {
|
|
62
|
+
player.value.loadVideoById(newId);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
onBeforeUnmount(() => {
|
|
66
|
+
stopVideoIdWatch();
|
|
67
|
+
player.value?.destroy();
|
|
68
|
+
});
|
|
50
69
|
onMounted(() => {
|
|
51
70
|
onLoaded(async (instance) => {
|
|
71
|
+
if (!isTriggered.value && trigger instanceof Promise) {
|
|
72
|
+
const triggered = await trigger;
|
|
73
|
+
if (!triggered)
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (!youtubeEl.value)
|
|
77
|
+
return;
|
|
52
78
|
const YouTube = instance.YT instanceof Promise ? await instance.YT : instance.YT;
|
|
53
79
|
await new Promise((resolve) => {
|
|
54
80
|
if (typeof YT.Player === "undefined")
|
|
@@ -56,22 +82,24 @@ onMounted(() => {
|
|
|
56
82
|
else
|
|
57
83
|
resolve();
|
|
58
84
|
});
|
|
85
|
+
if (!youtubeEl.value)
|
|
86
|
+
return;
|
|
59
87
|
player.value = new YT.Player(youtubeEl.value, {
|
|
60
88
|
host: !props.cookies ? "https://www.youtube-nocookie.com" : "https://www.youtube.com",
|
|
61
|
-
|
|
89
|
+
videoId: props.videoId,
|
|
90
|
+
width: props.width,
|
|
91
|
+
height: props.height,
|
|
92
|
+
playerVars: props.playerVars,
|
|
62
93
|
...props.playerOptions,
|
|
63
94
|
events: Object.fromEntries(events.map((event) => [event, (e) => {
|
|
64
95
|
const emitEventName = event.replace(/([A-Z])/g, "-$1").replace("on-", "").toLowerCase();
|
|
65
96
|
emits(emitEventName, e);
|
|
66
97
|
if (event === "onReady") {
|
|
67
98
|
ready.value = true;
|
|
68
|
-
if (clickTriggered) {
|
|
99
|
+
if (clickTriggered.value) {
|
|
69
100
|
player.value?.playVideo();
|
|
70
|
-
clickTriggered = false;
|
|
101
|
+
clickTriggered.value = false;
|
|
71
102
|
}
|
|
72
|
-
watch(() => props.videoId, () => {
|
|
73
|
-
player.value?.loadVideoById(props.videoId);
|
|
74
|
-
});
|
|
75
103
|
}
|
|
76
104
|
}]))
|
|
77
105
|
});
|
|
@@ -96,7 +124,7 @@ const rootAttrs = computed(() => {
|
|
|
96
124
|
position: "relative",
|
|
97
125
|
backgroundColor: "black",
|
|
98
126
|
width: "100%",
|
|
99
|
-
aspectRatio:
|
|
127
|
+
aspectRatio: props.ratio
|
|
100
128
|
},
|
|
101
129
|
...trigger instanceof Promise ? trigger.ssrAttrs || {} : {}
|
|
102
130
|
});
|
|
@@ -108,12 +136,12 @@ if (import.meta.server) {
|
|
|
108
136
|
useHead({
|
|
109
137
|
link: [
|
|
110
138
|
{
|
|
111
|
-
key:
|
|
139
|
+
key: "nuxt-script-youtube-img-preconnect",
|
|
112
140
|
rel: props.aboveTheFold ? "preconnect" : "dns-prefetch",
|
|
113
141
|
href: "https://i.ytimg.com"
|
|
114
142
|
},
|
|
115
143
|
props.aboveTheFold ? {
|
|
116
|
-
key: `nuxt-script-youtube-img`,
|
|
144
|
+
key: `nuxt-script-youtube-img-preload-${props.videoId}`,
|
|
117
145
|
rel: "preload",
|
|
118
146
|
as: "image",
|
|
119
147
|
href: placeholder.value
|
|
@@ -128,7 +156,7 @@ const placeholderAttrs = computed(() => {
|
|
|
128
156
|
loading: props.aboveTheFold ? "eager" : "lazy",
|
|
129
157
|
style: {
|
|
130
158
|
width: "100%",
|
|
131
|
-
objectFit:
|
|
159
|
+
objectFit: props.placeholderObjectFit,
|
|
132
160
|
height: "100%"
|
|
133
161
|
},
|
|
134
162
|
onLoad(payload) {
|
|
@@ -10,6 +10,7 @@ type __VLS_Props = {
|
|
|
10
10
|
playerVars?: YT.PlayerVars;
|
|
11
11
|
width?: number;
|
|
12
12
|
height?: number;
|
|
13
|
+
ratio?: string;
|
|
13
14
|
/**
|
|
14
15
|
* Whether to use youtube-nocookie.com for embedding.
|
|
15
16
|
*
|
|
@@ -19,9 +20,15 @@ type __VLS_Props = {
|
|
|
19
20
|
playerOptions?: YT.PlayerOptions;
|
|
20
21
|
thumbnailSize?: YoutubeThumbnailSize;
|
|
21
22
|
webp?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Object-fit for the placeholder image.
|
|
25
|
+
*
|
|
26
|
+
* @default 'cover'
|
|
27
|
+
*/
|
|
28
|
+
placeholderObjectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
|
|
22
29
|
};
|
|
23
30
|
declare var __VLS_1: {
|
|
24
|
-
placeholder:
|
|
31
|
+
placeholder: string;
|
|
25
32
|
}, __VLS_3: {}, __VLS_10: {}, __VLS_12: {}, __VLS_14: {};
|
|
26
33
|
type __VLS_Slots = {} & {
|
|
27
34
|
placeholder?: (props: typeof __VLS_1) => any;
|
|
@@ -42,20 +49,24 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
|
42
49
|
"state-change": (e: YT.OnStateChangeEvent, target: YT.Player) => any;
|
|
43
50
|
"playback-quality-change": (e: YT.OnPlaybackQualityChangeEvent, target: YT.Player) => any;
|
|
44
51
|
"playback-rate-change": (e: YT.OnPlaybackRateChangeEvent, target: YT.Player) => any;
|
|
52
|
+
"api-change": (e: YT.PlayerEvent, target: YT.Player) => any;
|
|
45
53
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
46
54
|
onError?: ((e: YT.OnErrorEvent, target: YT.Player) => any) | undefined;
|
|
47
55
|
onReady?: ((e: YT.PlayerEvent) => any) | undefined;
|
|
48
56
|
"onState-change"?: ((e: YT.OnStateChangeEvent, target: YT.Player) => any) | undefined;
|
|
49
57
|
"onPlayback-quality-change"?: ((e: YT.OnPlaybackQualityChangeEvent, target: YT.Player) => any) | undefined;
|
|
50
58
|
"onPlayback-rate-change"?: ((e: YT.OnPlaybackRateChangeEvent, target: YT.Player) => any) | undefined;
|
|
59
|
+
"onApi-change"?: ((e: YT.PlayerEvent, target: YT.Player) => any) | undefined;
|
|
51
60
|
}>, {
|
|
52
61
|
trigger: ElementScriptTrigger;
|
|
53
62
|
width: number;
|
|
54
63
|
height: number;
|
|
55
64
|
playerVars: YT.PlayerVars;
|
|
65
|
+
ratio: string;
|
|
56
66
|
cookies: boolean;
|
|
57
67
|
thumbnailSize: YoutubeThumbnailSize;
|
|
58
68
|
webp: boolean;
|
|
69
|
+
placeholderObjectFit: "cover" | "contain" | "fill" | "none" | "scale-down";
|
|
59
70
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
60
71
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
61
72
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveTrigger } from "#build/nuxt-scripts-trigger-resolver";
|
|
2
2
|
import { useScript as _useScript } from "@unhead/vue/scripts";
|
|
3
|
-
import {
|
|
4
|
-
import { onNuxtReady, useNuxtApp, useRuntimeConfig
|
|
3
|
+
import { defu } from "defu";
|
|
4
|
+
import { injectHead, onNuxtReady, useHead, useNuxtApp, useRuntimeConfig } from "nuxt/app";
|
|
5
|
+
import { reactive, ref } from "vue";
|
|
5
6
|
import { logger } from "../logger.js";
|
|
6
|
-
import { resolveTrigger } from "#build/nuxt-scripts-trigger-resolver";
|
|
7
7
|
function useNuxtScriptRuntimeConfig() {
|
|
8
8
|
return useRuntimeConfig().public["nuxt-scripts"];
|
|
9
9
|
}
|
|
@@ -13,6 +13,27 @@ export function resolveScriptKey(input) {
|
|
|
13
13
|
export function useScript(input, options) {
|
|
14
14
|
input = typeof input === "string" ? { src: input } : input;
|
|
15
15
|
options = defu(options, useNuxtScriptRuntimeConfig()?.defaultScriptOptions);
|
|
16
|
+
if (options.partytown) {
|
|
17
|
+
const src = input.src;
|
|
18
|
+
if (!src) {
|
|
19
|
+
throw new Error("useScript with partytown requires a src");
|
|
20
|
+
}
|
|
21
|
+
useHead({
|
|
22
|
+
script: [{ src, type: "text/partytown" }]
|
|
23
|
+
});
|
|
24
|
+
const nuxtApp2 = useNuxtApp();
|
|
25
|
+
nuxtApp2.$scripts = nuxtApp2.$scripts || reactive({});
|
|
26
|
+
const status = ref("loaded");
|
|
27
|
+
const stub = {
|
|
28
|
+
id: src,
|
|
29
|
+
status,
|
|
30
|
+
load: () => Promise.resolve({}),
|
|
31
|
+
remove: () => false,
|
|
32
|
+
entry: void 0
|
|
33
|
+
};
|
|
34
|
+
nuxtApp2.$scripts[src] = stub;
|
|
35
|
+
return stub;
|
|
36
|
+
}
|
|
16
37
|
if (import.meta.dev && options.bundle === "unsupported") {
|
|
17
38
|
console.warn("[Nuxt Scripts] Bundling is not supported for dynamic script sources. Static URLs are required for bundling.");
|
|
18
39
|
options.bundle = false;
|
|
@@ -23,8 +44,8 @@ export function useScript(input, options) {
|
|
|
23
44
|
options.trigger = resolved;
|
|
24
45
|
}
|
|
25
46
|
}
|
|
26
|
-
const id = String(resolveScriptKey(input));
|
|
27
47
|
const nuxtApp = useNuxtApp();
|
|
48
|
+
const id = String(resolveScriptKey(input));
|
|
28
49
|
options.head = options.head || injectHead();
|
|
29
50
|
if (!options.head) {
|
|
30
51
|
throw new Error("useScript() has been called without Nuxt context.");
|
|
@@ -65,6 +86,16 @@ export function useScript(input, options) {
|
|
|
65
86
|
}
|
|
66
87
|
return _load();
|
|
67
88
|
};
|
|
89
|
+
instance.reload = async () => {
|
|
90
|
+
instance.remove();
|
|
91
|
+
const reloadInput = typeof input === "string" ? { src: input, key: `${id}-${Date.now()}` } : { ...input, key: `${id}-${Date.now()}` };
|
|
92
|
+
const reloaded = _useScript(reloadInput, { ...options, trigger: "client" });
|
|
93
|
+
Object.assign(instance, {
|
|
94
|
+
status: reloaded.status,
|
|
95
|
+
entry: reloaded.entry
|
|
96
|
+
});
|
|
97
|
+
return reloaded.load();
|
|
98
|
+
};
|
|
68
99
|
nuxtApp.$scripts[id] = instance;
|
|
69
100
|
if (import.meta.dev && import.meta.client) {
|
|
70
101
|
let syncScripts = function() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useNuxtApp, useRoute
|
|
2
|
-
import {
|
|
1
|
+
import { injectHead, useNuxtApp, useRoute } from "nuxt/app";
|
|
2
|
+
import { onScopeDispose, ref } from "vue";
|
|
3
3
|
export function useScriptEventPage(onChange) {
|
|
4
4
|
const nuxt = useNuxtApp();
|
|
5
5
|
const route = useRoute();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { onNuxtReady, requestIdleCallback, tryUseNuxtApp } from "nuxt/app";
|
|
1
2
|
import { isRef, ref, toValue, watch } from "vue";
|
|
2
|
-
import { tryUseNuxtApp, onNuxtReady, requestIdleCallback } from "nuxt/app";
|
|
3
3
|
export function useScriptTriggerConsent(options) {
|
|
4
4
|
if (import.meta.server)
|
|
5
5
|
return new Promise(() => {
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
useEventListener,
|
|
3
3
|
useIntersectionObserver
|
|
4
4
|
} from "@vueuse/core";
|
|
5
|
-
import {
|
|
5
|
+
import { tryOnMounted, tryOnScopeDispose } from "@vueuse/shared";
|
|
6
6
|
import { watch } from "vue";
|
|
7
7
|
function useElementVisibilityPromise(element) {
|
|
8
8
|
let observer;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { tryOnScopeDispose } from "@vueuse/shared";
|
|
2
1
|
import { useTimeoutFn } from "@vueuse/core";
|
|
2
|
+
import { tryOnScopeDispose } from "@vueuse/shared";
|
|
3
3
|
import { onNuxtReady } from "nuxt/app";
|
|
4
4
|
export function useScriptTriggerIdleTimeout(options) {
|
|
5
5
|
if (import.meta.server) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a trigger that loads a script after the service worker is controlling the page.
|
|
3
|
+
* Falls back to immediate loading if service workers are not supported or after timeout.
|
|
4
|
+
*/
|
|
5
|
+
export declare function useScriptTriggerServiceWorker(options?: {
|
|
6
|
+
timeout?: number;
|
|
7
|
+
}): Promise<boolean>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { tryOnScopeDispose } from "@vueuse/shared";
|
|
2
|
+
export function useScriptTriggerServiceWorker(options) {
|
|
3
|
+
if (import.meta.server)
|
|
4
|
+
return new Promise(() => {
|
|
5
|
+
});
|
|
6
|
+
const timeout = options?.timeout ?? 3e3;
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
if (!("serviceWorker" in navigator)) {
|
|
9
|
+
resolve(true);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
let resolved = false;
|
|
13
|
+
const done = () => {
|
|
14
|
+
if (resolved)
|
|
15
|
+
return;
|
|
16
|
+
resolved = true;
|
|
17
|
+
resolve(true);
|
|
18
|
+
};
|
|
19
|
+
if (navigator.serviceWorker.controller) {
|
|
20
|
+
done();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const onControllerChange = () => {
|
|
24
|
+
navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
|
|
25
|
+
done();
|
|
26
|
+
};
|
|
27
|
+
navigator.serviceWorker.addEventListener("controllerchange", onControllerChange);
|
|
28
|
+
const timer = setTimeout(() => {
|
|
29
|
+
navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
|
|
30
|
+
console.warn("[nuxt-scripts] Service worker not controlling after timeout, loading scripts anyway");
|
|
31
|
+
done();
|
|
32
|
+
}, timeout);
|
|
33
|
+
tryOnScopeDispose(() => {
|
|
34
|
+
navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
resolve(false);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import type { NuxtUseScriptOptions } from './types.js';
|
|
3
|
+
export interface NpmScriptStubOptions {
|
|
4
|
+
key: string;
|
|
5
|
+
use?: () => any;
|
|
6
|
+
clientInit?: () => void | Promise<any>;
|
|
7
|
+
trigger?: NuxtUseScriptOptions['trigger'];
|
|
8
|
+
}
|
|
9
|
+
export interface NpmScriptStub<T = any> {
|
|
10
|
+
status: Ref<'awaitingLoad' | 'loading' | 'loaded' | 'error'>;
|
|
11
|
+
load: () => Promise<void>;
|
|
12
|
+
onLoaded: (callback: (api: T) => void) => void;
|
|
13
|
+
proxy: T;
|
|
14
|
+
$script?: any;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Creates a script stub for NPM-only packages (no external script tag)
|
|
18
|
+
* Manages lifecycle and status without relying on script tag loading
|
|
19
|
+
*/
|
|
20
|
+
export declare function createNpmScriptStub<T = any>(options: NpmScriptStubOptions): NpmScriptStub<T>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
export function createNpmScriptStub(options) {
|
|
4
|
+
const status = ref("awaitingLoad");
|
|
5
|
+
const loadedCallbacks = [];
|
|
6
|
+
let initPromise = null;
|
|
7
|
+
let hasInitialized = false;
|
|
8
|
+
const proxy = options.use?.() || {};
|
|
9
|
+
const stub = {
|
|
10
|
+
status,
|
|
11
|
+
proxy,
|
|
12
|
+
async load() {
|
|
13
|
+
if (hasInitialized || status.value !== "awaitingLoad")
|
|
14
|
+
return;
|
|
15
|
+
hasInitialized = true;
|
|
16
|
+
status.value = "loading";
|
|
17
|
+
try {
|
|
18
|
+
if (options.clientInit) {
|
|
19
|
+
console.log(`[NpmScriptStub] Initializing ${options.key}...`);
|
|
20
|
+
initPromise = Promise.resolve(options.clientInit());
|
|
21
|
+
await initPromise;
|
|
22
|
+
console.log(`[NpmScriptStub] ${options.key} initialized successfully`);
|
|
23
|
+
}
|
|
24
|
+
status.value = "loaded";
|
|
25
|
+
loadedCallbacks.forEach((cb) => {
|
|
26
|
+
try {
|
|
27
|
+
cb(proxy);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
logger.error(`[NpmScriptStub] Error in onLoaded callback for ${options.key}:`, error);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
} catch (error) {
|
|
33
|
+
logger.error(`[NpmScriptStub] Failed to initialize ${options.key}:`, error);
|
|
34
|
+
status.value = "error";
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
onLoaded(callback) {
|
|
38
|
+
if (status.value === "loaded") {
|
|
39
|
+
callback(proxy);
|
|
40
|
+
} else {
|
|
41
|
+
loadedCallbacks.push(callback);
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
// Mock $script for compatibility with useScript API
|
|
45
|
+
get $script() {
|
|
46
|
+
return {
|
|
47
|
+
status: status.value,
|
|
48
|
+
load: stub.load
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
if (options.trigger) {
|
|
53
|
+
if (typeof options.trigger === "function") {
|
|
54
|
+
const res = options.trigger(() => stub.load());
|
|
55
|
+
if (res && typeof res === "object" && "then" in res)
|
|
56
|
+
res.then(() => stub.load());
|
|
57
|
+
} else if (options.trigger === "manual") {
|
|
58
|
+
} else if (options.trigger === "onNuxtReady") {
|
|
59
|
+
import("nuxt/app").then(({ onNuxtReady }) => {
|
|
60
|
+
onNuxtReady(() => stub.load());
|
|
61
|
+
});
|
|
62
|
+
} else if (options.trigger === "client") {
|
|
63
|
+
if (import.meta.client) {
|
|
64
|
+
stub.load();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
if (import.meta.client) {
|
|
69
|
+
stub.load();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return stub;
|
|
73
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { minLength, object, pipe, string } from "#nuxt-scripts-validator";
|
|
1
2
|
import { useRegistryScript } from "../utils.js";
|
|
2
|
-
import { minLength, object, string, pipe } from "#nuxt-scripts-validator";
|
|
3
3
|
export const ClarityOptions = object({
|
|
4
4
|
/**
|
|
5
5
|
* The Clarity token.
|
|
@@ -7,30 +7,26 @@ export const ClarityOptions = object({
|
|
|
7
7
|
id: pipe(string(), minLength(10))
|
|
8
8
|
});
|
|
9
9
|
export function useScriptClarity(_options) {
|
|
10
|
-
return useRegistryScript(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
clarity
|
|
22
|
-
|
|
23
|
-
return clarity.apply(this, params);
|
|
24
|
-
}, window.clarity)
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
clientInit: import.meta.server ? void 0 : () => {
|
|
29
|
-
window.clarity = window.clarity || function(...params) {
|
|
30
|
-
(window.clarity.q = window.clarity.q || []).push(params);
|
|
10
|
+
return useRegistryScript("clarity", (options) => ({
|
|
11
|
+
scriptInput: {
|
|
12
|
+
src: `https://www.clarity.ms/tag/${options.id}`
|
|
13
|
+
},
|
|
14
|
+
schema: import.meta.dev ? ClarityOptions : void 0,
|
|
15
|
+
scriptOptions: {
|
|
16
|
+
use() {
|
|
17
|
+
return {
|
|
18
|
+
// @ts-expect-error untyped
|
|
19
|
+
clarity: Object.assign(function(...params) {
|
|
20
|
+
const clarity = window.clarity;
|
|
21
|
+
return clarity.apply(this, params);
|
|
22
|
+
}, window.clarity)
|
|
31
23
|
};
|
|
32
24
|
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
},
|
|
26
|
+
clientInit: import.meta.server ? void 0 : () => {
|
|
27
|
+
window.clarity = window.clarity || function(...params) {
|
|
28
|
+
(window.clarity.q = window.clarity.q || []).push(params);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}), _options);
|
|
36
32
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useRegistryScript } from "../utils.js";
|
|
2
1
|
import { boolean, minLength, object, optional, pipe, string } from "#nuxt-scripts-validator";
|
|
2
|
+
import { useRegistryScript } from "../utils.js";
|
|
3
3
|
export const CloudflareWebAnalyticsOptions = object({
|
|
4
4
|
/**
|
|
5
5
|
* The Cloudflare Web Analytics token.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { boolean, number, object, optional, string } from "#nuxt-scripts-validator";
|
|
1
2
|
import { useRegistryScript } from "../utils.js";
|
|
2
|
-
import { object, optional, string, boolean, number } from "#nuxt-scripts-validator";
|
|
3
3
|
export const DatabuddyAnalyticsOptions = object({
|
|
4
4
|
// Required
|
|
5
5
|
clientId: string(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useRegistryScript } from "../utils.js";
|
|
2
1
|
import { boolean, literal, object, optional, string, union } from "#nuxt-scripts-validator";
|
|
2
|
+
import { useRegistryScript } from "../utils.js";
|
|
3
3
|
export const FathomAnalyticsOptions = object({
|
|
4
4
|
/**
|
|
5
5
|
* The Fathom Analytics site ID.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { boolean, object, optional, string } from "#nuxt-scripts-validator";
|
|
1
2
|
import { useHead } from "nuxt/app";
|
|
2
3
|
import { useRegistryScript } from "../utils.js";
|
|
3
|
-
import { object, string, optional, boolean } from "#nuxt-scripts-validator";
|
|
4
4
|
export const GoogleAdsenseOptions = object({
|
|
5
5
|
/**
|
|
6
6
|
* The Google Adsense ID.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { object, optional, string } from "#nuxt-scripts-validator";
|
|
2
2
|
import { useRegistryScript } from "#nuxt-scripts/utils";
|
|
3
|
-
import {
|
|
3
|
+
import { withQuery } from "ufo";
|
|
4
4
|
export const GoogleAnalyticsOptions = object({
|
|
5
5
|
id: optional(string()),
|
|
6
6
|
// The GA4 measurement ID (format: G-XXXXXXXX)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { array, literal, object, optional, string, union } from "#nuxt-scripts-validator";
|
|
1
2
|
import { withQuery } from "ufo";
|
|
2
3
|
import { useRegistryScript } from "../utils.js";
|
|
3
|
-
import { array, literal, object, optional, string, union } from "#nuxt-scripts-validator";
|
|
4
4
|
export const GoogleMapsOptions = object({
|
|
5
5
|
apiKey: string(),
|
|
6
6
|
libraries: optional(array(string())),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
2
|
+
export declare const GoogleRecaptchaOptions: import("valibot").ObjectSchema<{
|
|
3
|
+
readonly siteKey: import("valibot").StringSchema<undefined>;
|
|
4
|
+
readonly enterprise: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
5
|
+
readonly recaptchaNet: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
6
|
+
readonly hl: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
7
|
+
}, undefined>;
|
|
8
|
+
export type GoogleRecaptchaInput = RegistryScriptInput<typeof GoogleRecaptchaOptions>;
|
|
9
|
+
export interface GoogleRecaptchaApi {
|
|
10
|
+
grecaptcha: {
|
|
11
|
+
ready: (callback: () => void) => void;
|
|
12
|
+
execute: (siteKey: string, options: {
|
|
13
|
+
action: string;
|
|
14
|
+
}) => Promise<string>;
|
|
15
|
+
enterprise?: {
|
|
16
|
+
ready: (callback: () => void) => void;
|
|
17
|
+
execute: (siteKey: string, options: {
|
|
18
|
+
action: string;
|
|
19
|
+
}) => Promise<string>;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
declare global {
|
|
24
|
+
interface Window extends GoogleRecaptchaApi {
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export declare function useScriptGoogleRecaptcha<T extends GoogleRecaptchaApi>(_options?: GoogleRecaptchaInput): import("#nuxt-scripts/types").UseScriptContext<T>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { boolean, object, optional, string } from "#nuxt-scripts-validator";
|
|
2
|
+
import { useRegistryScript } from "#nuxt-scripts/utils";
|
|
3
|
+
import { withQuery } from "ufo";
|
|
4
|
+
export const GoogleRecaptchaOptions = object({
|
|
5
|
+
siteKey: string(),
|
|
6
|
+
// Use enterprise.js instead of api.js
|
|
7
|
+
enterprise: optional(boolean()),
|
|
8
|
+
// Use recaptcha.net (works in China)
|
|
9
|
+
recaptchaNet: optional(boolean()),
|
|
10
|
+
// Language code
|
|
11
|
+
hl: optional(string())
|
|
12
|
+
});
|
|
13
|
+
export function useScriptGoogleRecaptcha(_options) {
|
|
14
|
+
return useRegistryScript(_options?.key || "googleRecaptcha", (options) => {
|
|
15
|
+
const baseUrl = options?.recaptchaNet ? "https://www.recaptcha.net/recaptcha" : "https://www.google.com/recaptcha";
|
|
16
|
+
const scriptPath = options?.enterprise ? "enterprise.js" : "api.js";
|
|
17
|
+
return {
|
|
18
|
+
scriptInput: {
|
|
19
|
+
src: withQuery(`${baseUrl}/${scriptPath}`, {
|
|
20
|
+
render: options?.siteKey,
|
|
21
|
+
hl: options?.hl
|
|
22
|
+
}),
|
|
23
|
+
crossorigin: false
|
|
24
|
+
},
|
|
25
|
+
schema: import.meta.dev ? GoogleRecaptchaOptions : void 0,
|
|
26
|
+
scriptOptions: {
|
|
27
|
+
use() {
|
|
28
|
+
return { grecaptcha: window.grecaptcha };
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
clientInit: import.meta.server ? void 0 : () => {
|
|
32
|
+
const w = window;
|
|
33
|
+
w.grecaptcha = w.grecaptcha || {};
|
|
34
|
+
const readyFn = function(cb) {
|
|
35
|
+
(w.___grecaptcha_cfg = w.___grecaptcha_cfg || {}).fns = (w.___grecaptcha_cfg.fns || []).concat([cb]);
|
|
36
|
+
};
|
|
37
|
+
w.grecaptcha.ready = w.grecaptcha.ready || readyFn;
|
|
38
|
+
if (options?.enterprise) {
|
|
39
|
+
w.grecaptcha.enterprise = w.grecaptcha.enterprise || {};
|
|
40
|
+
w.grecaptcha.enterprise.ready = w.grecaptcha.enterprise.ready || readyFn;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}, _options);
|
|
45
|
+
}
|