@nuxt/scripts 1.0.0-rc.9 → 1.0.1
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/dist/devtools-client/200.html +1 -1
- package/dist/devtools-client/404.html +1 -1
- package/dist/devtools-client/_nuxt/{Cxq4HLPL.js → BjIIVRlr.js} +1 -1
- package/dist/devtools-client/_nuxt/{BBS9G2Kb.js → C3h_qg0j.js} +1 -1
- package/dist/devtools-client/_nuxt/{DCBsJT4N.js → CKrGhxlH.js} +1 -1
- package/dist/devtools-client/_nuxt/DD1eKorn.js +1 -0
- package/dist/devtools-client/_nuxt/{B4uHpJPz.js → DTVoxnk-.js} +1 -1
- package/dist/devtools-client/_nuxt/{DvZScWzI.js → TnW0ti1s.js} +1 -1
- package/dist/devtools-client/_nuxt/UTyLw2F_.js +188 -0
- package/dist/devtools-client/_nuxt/builds/latest.json +1 -1
- package/dist/devtools-client/_nuxt/builds/meta/8eda1fb3-23bc-456f-8373-7e503f9580ec.json +1 -0
- package/dist/devtools-client/_nuxt/{entry.BwpOBArY.css → entry.BKkVrcJj.css} +1 -1
- package/dist/devtools-client/_nuxt/error-404.Rdq9GpXu.css +1 -0
- package/dist/devtools-client/_nuxt/error-500.BPHNCR4E.css +1 -0
- package/dist/devtools-client/_nuxt/index.DZD1lwyI.css +1 -0
- package/dist/devtools-client/docs/index.html +1 -1
- package/dist/devtools-client/first-party/index.html +1 -1
- package/dist/devtools-client/index.html +1 -1
- package/dist/devtools-client/registry/index.html +1 -1
- package/dist/module.d.mts +18 -2
- package/dist/module.d.ts +18 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +81 -9
- package/dist/registry.mjs +10 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +1 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue +3 -0
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue +6 -2
- package/dist/runtime/components/ScriptBlueskyEmbed.d.vue.ts +0 -1
- package/dist/runtime/components/ScriptBlueskyEmbed.vue +12 -10
- package/dist/runtime/components/ScriptBlueskyEmbed.vue.d.ts +0 -1
- package/dist/runtime/components/ScriptInstagramEmbed.vue +3 -1
- package/dist/runtime/components/ScriptXEmbed.d.vue.ts +0 -1
- package/dist/runtime/components/ScriptXEmbed.vue +11 -9
- package/dist/runtime/components/ScriptXEmbed.vue.d.ts +0 -1
- package/dist/runtime/composables/useScript.js +17 -6
- package/dist/runtime/composables/useScriptProxyToken.d.ts +12 -0
- package/dist/runtime/composables/useScriptProxyToken.js +4 -0
- package/dist/runtime/composables/useScriptProxyUrl.d.ts +12 -0
- package/dist/runtime/composables/useScriptProxyUrl.js +27 -0
- package/dist/runtime/plugins/proxy-token.server.d.ts +10 -0
- package/dist/runtime/plugins/proxy-token.server.js +17 -0
- package/dist/runtime/registry/bing-uet.d.ts +6 -2
- package/dist/runtime/registry/bing-uet.js +13 -1
- package/dist/runtime/registry/bluesky-embed.d.ts +0 -4
- package/dist/runtime/registry/bluesky-embed.js +0 -4
- package/dist/runtime/registry/clarity.d.ts +6 -2
- package/dist/runtime/registry/clarity.js +12 -1
- package/dist/runtime/registry/google-analytics.d.ts +6 -2
- package/dist/runtime/registry/google-analytics.js +12 -1
- package/dist/runtime/registry/google-tag-manager.d.ts +6 -2
- package/dist/runtime/registry/google-tag-manager.js +10 -1
- package/dist/runtime/registry/gravatar.js +10 -13
- package/dist/runtime/registry/matomo-analytics.d.ts +9 -3
- package/dist/runtime/registry/matomo-analytics.js +28 -1
- package/dist/runtime/registry/meta-pixel.d.ts +8 -2
- package/dist/runtime/registry/meta-pixel.js +10 -1
- package/dist/runtime/registry/mixpanel-analytics.d.ts +12 -2
- package/dist/runtime/registry/mixpanel-analytics.js +16 -4
- package/dist/runtime/registry/posthog.d.ts +8 -2
- package/dist/runtime/registry/posthog.js +15 -4
- package/dist/runtime/registry/schemas.d.ts +65 -0
- package/dist/runtime/registry/schemas.js +75 -8
- package/dist/runtime/registry/tiktok-pixel.d.ts +16 -2
- package/dist/runtime/registry/tiktok-pixel.js +22 -1
- package/dist/runtime/registry/x-embed.d.ts +0 -4
- package/dist/runtime/registry/x-embed.js +0 -4
- package/dist/runtime/server/bluesky-embed-image.d.ts +1 -1
- package/dist/runtime/server/bluesky-embed.d.ts +1 -15
- package/dist/runtime/server/bluesky-embed.js +22 -4
- package/dist/runtime/server/google-maps-geocode-proxy.js +8 -5
- package/dist/runtime/server/google-static-maps-proxy.d.ts +1 -1
- package/dist/runtime/server/google-static-maps-proxy.js +13 -8
- package/dist/runtime/server/gravatar-proxy.d.ts +1 -1
- package/dist/runtime/server/gravatar-proxy.js +6 -7
- package/dist/runtime/server/instagram-embed-asset.d.ts +1 -1
- package/dist/runtime/server/instagram-embed-image.d.ts +1 -1
- package/dist/runtime/server/instagram-embed.js +22 -10
- package/dist/runtime/server/utils/cached-upstream.d.ts +55 -0
- package/dist/runtime/server/utils/cached-upstream.js +65 -0
- package/dist/runtime/server/utils/embed-rewriters.d.ts +19 -0
- package/dist/runtime/server/utils/embed-rewriters.js +41 -0
- package/dist/runtime/server/utils/image-proxy.d.ts +3 -1
- package/dist/runtime/server/utils/image-proxy.js +8 -6
- package/dist/runtime/server/utils/instagram-embed.d.ts +4 -4
- package/dist/runtime/server/utils/instagram-embed.js +10 -9
- package/dist/runtime/server/utils/proxy-url.d.ts +9 -0
- package/dist/runtime/server/utils/proxy-url.js +21 -0
- package/dist/runtime/server/utils/sign-constants.d.ts +16 -0
- package/dist/runtime/server/utils/sign-constants.js +5 -0
- package/dist/runtime/server/utils/sign.d.ts +2 -10
- package/dist/runtime/server/utils/sign.js +8 -5
- package/dist/runtime/server/utils/withSigning.js +3 -2
- package/dist/runtime/server/vercel-insights-sink.d.ts +2 -0
- package/dist/runtime/server/vercel-insights-sink.js +5 -0
- package/dist/runtime/server/x-embed-image.d.ts +1 -1
- package/dist/runtime/server/x-embed.js +20 -2
- package/dist/runtime/types.d.ts +28 -1
- package/dist/types-source.mjs +104 -11
- package/dist/types.d.mts +1 -1
- package/package.json +3 -3
- package/dist/devtools-client/_nuxt/CQR4zIAm.js +0 -1
- package/dist/devtools-client/_nuxt/DTxy5P8N.js +0 -188
- package/dist/devtools-client/_nuxt/builds/meta/bd58b869-1eb5-4c50-871c-707f9b71e8f9.json +0 -1
- package/dist/devtools-client/_nuxt/error-404.d44aGwWI.css +0 -1
- package/dist/devtools-client/_nuxt/error-500.NthMfIEt.css +0 -1
- package/dist/devtools-client/_nuxt/index.CA-OpSj0.css +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { useAsyncData } from "nuxt/app";
|
|
3
3
|
import { computed } from "vue";
|
|
4
|
-
import {
|
|
4
|
+
import { useScriptProxyUrl } from "../composables/useScriptProxyUrl";
|
|
5
|
+
import { formatCount, formatTweetDate } from "../registry/x-embed";
|
|
5
6
|
import { requireRegistryEndpoint, scriptsPrefix } from "../utils";
|
|
6
7
|
const props = defineProps({
|
|
7
8
|
tweetId: { type: String, required: true },
|
|
@@ -15,10 +16,11 @@ const apiEndpoint = computed(() => props.apiEndpoint || `${prefix}/embed/x`);
|
|
|
15
16
|
const resolvedImageProxyEndpoint = computed(() => props.imageProxyEndpoint || `${prefix}/embed/x-image`);
|
|
16
17
|
if (!props.apiEndpoint)
|
|
17
18
|
requireRegistryEndpoint("ScriptXEmbed", "xEmbed");
|
|
19
|
+
const proxyUrl = useScriptProxyUrl();
|
|
18
20
|
const cacheKey = computed(() => `x-embed-${props.tweetId}`);
|
|
19
21
|
const { data: tweet, status, error } = useAsyncData(
|
|
20
22
|
cacheKey,
|
|
21
|
-
() => $fetch(
|
|
23
|
+
() => $fetch(proxyUrl(apiEndpoint.value, { id: props.tweetId }))
|
|
22
24
|
);
|
|
23
25
|
const slotProps = computed(() => {
|
|
24
26
|
if (!tweet.value)
|
|
@@ -30,8 +32,7 @@ const slotProps = computed(() => {
|
|
|
30
32
|
// User info
|
|
31
33
|
userName: t.user.name,
|
|
32
34
|
userHandle: t.user.screen_name,
|
|
33
|
-
userAvatar:
|
|
34
|
-
userAvatarOriginal: t.user.profile_image_url_https,
|
|
35
|
+
userAvatar: t.user.profile_image_url_https,
|
|
35
36
|
isVerified: t.user.verified || t.user.is_blue_verified,
|
|
36
37
|
// Tweet content
|
|
37
38
|
text: t.text,
|
|
@@ -42,14 +43,14 @@ const slotProps = computed(() => {
|
|
|
42
43
|
likesFormatted: formatCount(t.favorite_count),
|
|
43
44
|
replies: t.conversation_count,
|
|
44
45
|
repliesFormatted: formatCount(t.conversation_count),
|
|
45
|
-
// Media
|
|
46
|
+
// Media (already proxied)
|
|
46
47
|
photos: t.photos?.map((p) => ({
|
|
47
48
|
...p,
|
|
48
|
-
proxiedUrl:
|
|
49
|
+
proxiedUrl: p.url
|
|
49
50
|
})),
|
|
50
51
|
video: t.video ? {
|
|
51
52
|
...t.video,
|
|
52
|
-
posterProxied:
|
|
53
|
+
posterProxied: t.video.poster
|
|
53
54
|
} : null,
|
|
54
55
|
// Links
|
|
55
56
|
tweetUrl: `https://x.com/${t.user.screen_name}/status/${t.id_str}`,
|
|
@@ -59,8 +60,9 @@ const slotProps = computed(() => {
|
|
|
59
60
|
// Reply context
|
|
60
61
|
isReply: !!t.parent,
|
|
61
62
|
replyToUser: t.parent?.user.screen_name,
|
|
62
|
-
// Helpers
|
|
63
|
-
|
|
63
|
+
// Helpers — proxy an arbitrary URL through the image endpoint at runtime.
|
|
64
|
+
// Uses the page token emitted during SSR so client-generated URLs validate.
|
|
65
|
+
proxyImage: (url) => proxyUrl(resolvedImageProxyEndpoint.value, { url })
|
|
64
66
|
};
|
|
65
67
|
});
|
|
66
68
|
defineExpose({
|
|
@@ -26,11 +26,22 @@ function toNetworkRequest(entry, proxyPrefix) {
|
|
|
26
26
|
isProxied
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
-
function createDomainMatcher(domains, proxyPrefix) {
|
|
29
|
+
function createDomainMatcher(domains, proxyPrefix, scriptSrc) {
|
|
30
30
|
const localHostname = window.location.hostname;
|
|
31
|
+
const scriptUrl = (() => {
|
|
32
|
+
if (!scriptSrc)
|
|
33
|
+
return "";
|
|
34
|
+
try {
|
|
35
|
+
return new URL(scriptSrc, window.location.origin).href;
|
|
36
|
+
} catch {
|
|
37
|
+
return "";
|
|
38
|
+
}
|
|
39
|
+
})();
|
|
31
40
|
return function matchesScript(entry) {
|
|
32
41
|
try {
|
|
33
42
|
const entryUrl = new URL(entry.name, window.location.origin);
|
|
43
|
+
if (scriptUrl && entryUrl.href === scriptUrl)
|
|
44
|
+
return true;
|
|
34
45
|
if (entryUrl.hostname !== localHostname && domains.has(entryUrl.hostname))
|
|
35
46
|
return true;
|
|
36
47
|
const proxyPath = `${proxyPrefix}/`;
|
|
@@ -46,12 +57,12 @@ function createDomainMatcher(domains, proxyPrefix) {
|
|
|
46
57
|
return false;
|
|
47
58
|
};
|
|
48
59
|
}
|
|
49
|
-
function observeNetworkRequests(payload, domains, onUpdate) {
|
|
60
|
+
function observeNetworkRequests(payload, domains, onUpdate, scriptSrc) {
|
|
50
61
|
if (typeof PerformanceObserver === "undefined")
|
|
51
62
|
return () => {
|
|
52
63
|
};
|
|
53
64
|
const proxyPrefix = resolveProxyPrefix();
|
|
54
|
-
const matchesScript = createDomainMatcher(domains, proxyPrefix);
|
|
65
|
+
const matchesScript = createDomainMatcher(domains, proxyPrefix, scriptSrc);
|
|
55
66
|
const seen = /* @__PURE__ */ new Set();
|
|
56
67
|
function entryKey(entry) {
|
|
57
68
|
return `${entry.name}@${entry.startTime}`;
|
|
@@ -148,7 +159,7 @@ export function useScript(input, options) {
|
|
|
148
159
|
],
|
|
149
160
|
networkRequests: []
|
|
150
161
|
};
|
|
151
|
-
disconnectObserver = observeNetworkRequests(payload, domains, syncScripts);
|
|
162
|
+
disconnectObserver = observeNetworkRequests(payload, domains, syncScripts, src);
|
|
152
163
|
syncScripts();
|
|
153
164
|
}
|
|
154
165
|
return stub;
|
|
@@ -274,7 +285,7 @@ export function useScript(input, options) {
|
|
|
274
285
|
...scriptHostname ? [scriptHostname] : [],
|
|
275
286
|
...options.devtools?.domains || []
|
|
276
287
|
]);
|
|
277
|
-
let disconnectObserver = observeNetworkRequests(payload, domains, syncScripts);
|
|
288
|
+
let disconnectObserver = observeNetworkRequests(payload, domains, syncScripts, input.src);
|
|
278
289
|
const _origRemove = instance.remove;
|
|
279
290
|
const _origReload = instance.reload;
|
|
280
291
|
instance.remove = () => {
|
|
@@ -284,7 +295,7 @@ export function useScript(input, options) {
|
|
|
284
295
|
instance.reload = async () => {
|
|
285
296
|
disconnectObserver();
|
|
286
297
|
const result = await _origReload();
|
|
287
|
-
disconnectObserver = observeNetworkRequests(payload, domains, syncScripts);
|
|
298
|
+
disconnectObserver = observeNetworkRequests(payload, domains, syncScripts, input.src);
|
|
288
299
|
return result;
|
|
289
300
|
};
|
|
290
301
|
syncScripts();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ScriptProxyToken {
|
|
2
|
+
token: string;
|
|
3
|
+
ts: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Shared `useState` holding the proxy page token emitted during SSR.
|
|
7
|
+
*
|
|
8
|
+
* Populated by the `nuxt-scripts:proxy-token` server plugin when
|
|
9
|
+
* `runtimeConfig['nuxt-scripts'].proxySecret` is set, and hydrated to the
|
|
10
|
+
* client via the Nuxt payload. Stays null when signing is disabled.
|
|
11
|
+
*/
|
|
12
|
+
export declare function useScriptProxyToken(): import("vue").Ref<ScriptProxyToken | null, ScriptProxyToken | null>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build proxy URLs that the server's `withSigning` middleware accepts.
|
|
3
|
+
*
|
|
4
|
+
* Attaches the page token emitted during SSR (`_pt` + `_ts`) when one is
|
|
5
|
+
* available, so client-driven proxy calls (e.g. reactive fetches, dynamic
|
|
6
|
+
* image helpers exposed in slot props) authenticate without needing a
|
|
7
|
+
* server round-trip to sign each URL.
|
|
8
|
+
*
|
|
9
|
+
* When no token is present (signing disabled or no secret), emits plain
|
|
10
|
+
* `?url=...` URLs, matching the pre-signing behavior.
|
|
11
|
+
*/
|
|
12
|
+
export declare function useScriptProxyUrl(): (path: string, query?: Record<string, unknown>) => string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PAGE_TOKEN_PARAM, PAGE_TOKEN_TS_PARAM } from "../server/utils/sign-constants.js";
|
|
2
|
+
import { useScriptProxyToken } from "./useScriptProxyToken.js";
|
|
3
|
+
export function useScriptProxyUrl() {
|
|
4
|
+
const token = useScriptProxyToken();
|
|
5
|
+
return (path, query = {}) => {
|
|
6
|
+
const parts = [];
|
|
7
|
+
for (const [key, value] of Object.entries(query)) {
|
|
8
|
+
if (value === void 0 || value === null)
|
|
9
|
+
continue;
|
|
10
|
+
const encodedKey = encodeURIComponent(key);
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
for (const item of value) {
|
|
13
|
+
if (item === void 0 || item === null)
|
|
14
|
+
continue;
|
|
15
|
+
parts.push(`${encodedKey}=${encodeURIComponent(String(item))}`);
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
parts.push(`${encodedKey}=${encodeURIComponent(String(value))}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (token.value) {
|
|
22
|
+
parts.push(`${PAGE_TOKEN_PARAM}=${encodeURIComponent(token.value.token)}`);
|
|
23
|
+
parts.push(`${PAGE_TOKEN_TS_PARAM}=${token.value.ts}`);
|
|
24
|
+
}
|
|
25
|
+
return parts.length ? `${path}?${parts.join("&")}` : path;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emit a per-request proxy page token into the SSR payload.
|
|
3
|
+
*
|
|
4
|
+
* The token authorizes client-side proxy calls (`/embed/x-image?url=...`,
|
|
5
|
+
* `/embed/bluesky?url=...`, etc.) without needing each URL to be signed
|
|
6
|
+
* ahead of time. It stays null when no proxy secret is configured, in
|
|
7
|
+
* which case `withSigning` passes requests through unchecked.
|
|
8
|
+
*/
|
|
9
|
+
declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineNuxtPlugin, useRuntimeConfig } from "nuxt/app";
|
|
2
|
+
import { useScriptProxyToken } from "../composables/useScriptProxyToken.js";
|
|
3
|
+
import { generateProxyToken } from "../server/utils/sign.js";
|
|
4
|
+
export default defineNuxtPlugin({
|
|
5
|
+
name: "nuxt-scripts:proxy-token",
|
|
6
|
+
enforce: "pre",
|
|
7
|
+
setup() {
|
|
8
|
+
const secret = useRuntimeConfig()["nuxt-scripts"]?.proxySecret;
|
|
9
|
+
if (!secret)
|
|
10
|
+
return;
|
|
11
|
+
const ts = Math.floor(Date.now() / 1e3);
|
|
12
|
+
useScriptProxyToken().value = {
|
|
13
|
+
token: generateProxyToken(secret, ts),
|
|
14
|
+
ts
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
1
|
+
import type { RegistryScriptInput, UseScriptContext } from '#nuxt-scripts/types';
|
|
2
2
|
import { BingUetOptions } from './schemas.js';
|
|
3
3
|
export { BingUetOptions };
|
|
4
4
|
export type BingUetInput = RegistryScriptInput<typeof BingUetOptions, true, false>;
|
|
@@ -189,6 +189,10 @@ declare global {
|
|
|
189
189
|
uetq: any[] | BingUetQueue;
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
|
+
export interface BingUetConsent {
|
|
193
|
+
/** Push `['consent','update', state]` with the `ad_storage` signal. */
|
|
194
|
+
update: (state: BingUetConsentOptions) => void;
|
|
195
|
+
}
|
|
192
196
|
export declare function useScriptBingUet<T extends BingUetApi>(_options?: BingUetInput & {
|
|
193
197
|
onBeforeUetStart?: (uetq: BingUetQueue) => void;
|
|
194
|
-
}):
|
|
198
|
+
}): UseScriptContext<T, BingUetConsent>;
|
|
@@ -2,7 +2,7 @@ import { useRegistryScript } from "../utils.js";
|
|
|
2
2
|
import { BingUetOptions } from "./schemas.js";
|
|
3
3
|
export { BingUetOptions };
|
|
4
4
|
export function useScriptBingUet(_options) {
|
|
5
|
-
|
|
5
|
+
const instance = useRegistryScript("bingUet", (options) => ({
|
|
6
6
|
scriptInput: {
|
|
7
7
|
src: "https://bat.bing.com/bat.js",
|
|
8
8
|
crossorigin: false
|
|
@@ -25,7 +25,19 @@ export function useScriptBingUet(_options) {
|
|
|
25
25
|
clientInit: import.meta.server ? void 0 : () => {
|
|
26
26
|
const uetq = window.uetq || [];
|
|
27
27
|
window.uetq = uetq;
|
|
28
|
+
if (options?.defaultConsent) {
|
|
29
|
+
uetq.push("consent", "default", options.defaultConsent);
|
|
30
|
+
}
|
|
28
31
|
_options?.onBeforeUetStart?.(uetq);
|
|
29
32
|
}
|
|
30
33
|
}), _options);
|
|
34
|
+
if (import.meta.client && !instance.consent) {
|
|
35
|
+
instance.consent = {
|
|
36
|
+
update: (state) => {
|
|
37
|
+
;
|
|
38
|
+
instance.proxy.uetq.push("consent", "update", state);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return instance;
|
|
31
43
|
}
|
|
@@ -98,10 +98,6 @@ export declare function extractBlueskyPostId(url: string): {
|
|
|
98
98
|
actor: string;
|
|
99
99
|
rkey: string;
|
|
100
100
|
} | undefined;
|
|
101
|
-
/**
|
|
102
|
-
* Proxy a Bluesky image URL through the server
|
|
103
|
-
*/
|
|
104
|
-
export declare function proxyBlueskyImageUrl(url: string, proxyEndpoint?: string): string;
|
|
105
101
|
/**
|
|
106
102
|
* Format a Bluesky post date for display
|
|
107
103
|
*/
|
|
@@ -7,10 +7,6 @@ export function extractBlueskyPostId(url) {
|
|
|
7
7
|
return void 0;
|
|
8
8
|
return { actor: match[1], rkey: match[2] };
|
|
9
9
|
}
|
|
10
|
-
export function proxyBlueskyImageUrl(url, proxyEndpoint = "/_scripts/embed/bluesky-image") {
|
|
11
|
-
const separator = proxyEndpoint.includes("?") ? "&" : "?";
|
|
12
|
-
return `${proxyEndpoint}${separator}url=${encodeURIComponent(url)}`;
|
|
13
|
-
}
|
|
14
10
|
export function formatBlueskyDate(dateString) {
|
|
15
11
|
const date = new Date(dateString);
|
|
16
12
|
const time = date.toLocaleString("en-US", {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
1
|
+
import type { RegistryScriptInput, UseScriptContext } from '#nuxt-scripts/types';
|
|
2
2
|
import { ClarityOptions } from './schemas.js';
|
|
3
3
|
export { ClarityOptions };
|
|
4
4
|
type ClarityFunctions = ((fn: 'start', options?: {
|
|
@@ -25,4 +25,8 @@ declare global {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
export type ClarityInput = RegistryScriptInput<typeof ClarityOptions>;
|
|
28
|
-
export
|
|
28
|
+
export interface ClarityConsent {
|
|
29
|
+
/** Call `clarity('consent', value)` with either a boolean (default) or Clarity's advanced vector. */
|
|
30
|
+
set: (value: boolean | Record<string, string>) => void;
|
|
31
|
+
}
|
|
32
|
+
export declare function useScriptClarity<T extends ClarityApi>(_options?: ClarityInput): UseScriptContext<T, ClarityConsent>;
|
|
@@ -2,7 +2,7 @@ import { useRegistryScript } from "../utils.js";
|
|
|
2
2
|
import { ClarityOptions } from "./schemas.js";
|
|
3
3
|
export { ClarityOptions };
|
|
4
4
|
export function useScriptClarity(_options) {
|
|
5
|
-
|
|
5
|
+
const instance = useRegistryScript("clarity", (options) => ({
|
|
6
6
|
scriptInput: {
|
|
7
7
|
src: `https://www.clarity.ms/tag/${options.id}`
|
|
8
8
|
},
|
|
@@ -22,6 +22,17 @@ export function useScriptClarity(_options) {
|
|
|
22
22
|
window.clarity = window.clarity || function(...params) {
|
|
23
23
|
(window.clarity.q = window.clarity.q || []).push(params);
|
|
24
24
|
};
|
|
25
|
+
if (options?.defaultConsent !== void 0)
|
|
26
|
+
window.clarity("consent", options.defaultConsent);
|
|
25
27
|
}
|
|
26
28
|
}), _options);
|
|
29
|
+
if (import.meta.client && !instance.consent) {
|
|
30
|
+
instance.consent = {
|
|
31
|
+
set: (value) => {
|
|
32
|
+
;
|
|
33
|
+
instance.proxy.clarity("consent", value);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return instance;
|
|
27
38
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
1
|
+
import type { ConsentState, RegistryScriptInput, UseScriptContext } from '#nuxt-scripts/types';
|
|
2
2
|
import { GoogleAnalyticsOptions } from './schemas.js';
|
|
3
3
|
export type GtagCustomParams = Record<string, any>;
|
|
4
4
|
export type ConsentStatus = 'granted' | 'denied';
|
|
@@ -58,6 +58,10 @@ export interface GoogleAnalyticsApi {
|
|
|
58
58
|
}
|
|
59
59
|
export { GoogleAnalyticsOptions };
|
|
60
60
|
export type GoogleAnalyticsInput = RegistryScriptInput<typeof GoogleAnalyticsOptions>;
|
|
61
|
+
export interface GoogleAnalyticsConsent {
|
|
62
|
+
/** Send `gtag('consent','update', state)` with GCMv2 partial state. */
|
|
63
|
+
update: (state: ConsentState) => void;
|
|
64
|
+
}
|
|
61
65
|
export declare function useScriptGoogleAnalytics<T extends GoogleAnalyticsApi>(_options?: GoogleAnalyticsInput & {
|
|
62
66
|
onBeforeGtagStart?: (gtag: GTag) => void;
|
|
63
|
-
}):
|
|
67
|
+
}): UseScriptContext<T, GoogleAnalyticsConsent>;
|
|
@@ -3,7 +3,7 @@ import { withQuery } from "ufo";
|
|
|
3
3
|
import { GoogleAnalyticsOptions } from "./schemas.js";
|
|
4
4
|
export { GoogleAnalyticsOptions };
|
|
5
5
|
export function useScriptGoogleAnalytics(_options) {
|
|
6
|
-
|
|
6
|
+
const instance = useRegistryScript(_options?.key || "googleAnalytics", (options) => {
|
|
7
7
|
const dataLayerName = options?.l ?? "dataLayer";
|
|
8
8
|
const w = import.meta.client ? window : {};
|
|
9
9
|
return {
|
|
@@ -24,6 +24,8 @@ export function useScriptGoogleAnalytics(_options) {
|
|
|
24
24
|
w.gtag = function() {
|
|
25
25
|
w[dataLayerName].push(arguments);
|
|
26
26
|
};
|
|
27
|
+
if (options?.defaultConsent)
|
|
28
|
+
w.gtag("consent", "default", options.defaultConsent);
|
|
27
29
|
_options?.onBeforeGtagStart?.(w.gtag);
|
|
28
30
|
w.gtag("js", /* @__PURE__ */ new Date());
|
|
29
31
|
if (options?.id) {
|
|
@@ -32,4 +34,13 @@ export function useScriptGoogleAnalytics(_options) {
|
|
|
32
34
|
}
|
|
33
35
|
};
|
|
34
36
|
}, _options);
|
|
37
|
+
if (import.meta.client && !instance.consent) {
|
|
38
|
+
instance.consent = {
|
|
39
|
+
update: (state) => {
|
|
40
|
+
;
|
|
41
|
+
instance.proxy.gtag("consent", "update", state);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return instance;
|
|
35
46
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NuxtUseScriptOptions, RegistryScriptInput, UseFunctionType, UseScriptContext } from '#nuxt-scripts/types';
|
|
1
|
+
import type { ConsentState, NuxtUseScriptOptions, RegistryScriptInput, UseFunctionType, UseScriptContext } from '#nuxt-scripts/types';
|
|
2
2
|
import type { GTag } from './google-analytics.js';
|
|
3
3
|
import { GoogleTagManagerOptions } from './schemas.js';
|
|
4
4
|
/**
|
|
@@ -68,6 +68,10 @@ declare global {
|
|
|
68
68
|
}
|
|
69
69
|
export { GoogleTagManagerOptions };
|
|
70
70
|
export type GoogleTagManagerInput = RegistryScriptInput<typeof GoogleTagManagerOptions>;
|
|
71
|
+
export interface GoogleTagManagerConsent {
|
|
72
|
+
/** Push `['consent','update', state]` onto dataLayer with GCMv2 partial state. */
|
|
73
|
+
update: (state: ConsentState) => void;
|
|
74
|
+
}
|
|
71
75
|
/**
|
|
72
76
|
* Hook to use Google Tag Manager in Nuxt applications
|
|
73
77
|
*/
|
|
@@ -77,4 +81,4 @@ export declare function useScriptGoogleTagManager<T extends GoogleTagManagerApi>
|
|
|
77
81
|
* Allows for custom initialization or configuration
|
|
78
82
|
*/
|
|
79
83
|
onBeforeGtmStart?: (gtag: DataLayerPush) => void;
|
|
80
|
-
}): UseScriptContext<UseFunctionType<NuxtUseScriptOptions<T>, T
|
|
84
|
+
}): UseScriptContext<UseFunctionType<NuxtUseScriptOptions<T>, T>, GoogleTagManagerConsent>;
|
|
@@ -54,5 +54,14 @@ export function useScriptGoogleTagManager(options) {
|
|
|
54
54
|
if (gtag)
|
|
55
55
|
options.onBeforeGtmStart(gtag);
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
const typed = instance;
|
|
58
|
+
if (import.meta.client && !typed.consent) {
|
|
59
|
+
typed.consent = {
|
|
60
|
+
update: (state) => {
|
|
61
|
+
;
|
|
62
|
+
typed.proxy.dataLayer.push(["consent", "update", state]);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return typed;
|
|
58
67
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { scriptsPrefix, useRegistryScript } from "#nuxt-scripts/utils";
|
|
2
|
+
import { useScriptProxyUrl } from "../composables/useScriptProxyUrl.js";
|
|
2
3
|
import { GravatarOptions } from "./schemas.js";
|
|
3
4
|
export { GravatarOptions } from "./schemas.js";
|
|
4
5
|
export function useScriptGravatar(_options) {
|
|
@@ -6,13 +7,11 @@ export function useScriptGravatar(_options) {
|
|
|
6
7
|
const size = options?.size ?? 80;
|
|
7
8
|
const defaultImg = options?.default ?? "mp";
|
|
8
9
|
const rating = options?.rating ?? "g";
|
|
9
|
-
const buildQuery = (overrides) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return params.toString();
|
|
15
|
-
};
|
|
10
|
+
const buildQuery = (overrides) => ({
|
|
11
|
+
s: overrides?.size ?? size,
|
|
12
|
+
d: overrides?.default ?? defaultImg,
|
|
13
|
+
r: overrides?.rating ?? rating
|
|
14
|
+
});
|
|
16
15
|
return {
|
|
17
16
|
scriptInput: {
|
|
18
17
|
src: "https://secure.gravatar.com/js/gprofiles.js"
|
|
@@ -21,13 +20,11 @@ export function useScriptGravatar(_options) {
|
|
|
21
20
|
scriptOptions: {
|
|
22
21
|
use: () => {
|
|
23
22
|
const prefix = scriptsPrefix();
|
|
23
|
+
const proxyUrl = useScriptProxyUrl();
|
|
24
|
+
const path = `${prefix}/proxy/gravatar`;
|
|
24
25
|
return {
|
|
25
|
-
getAvatarUrl: (hash, overrides) => {
|
|
26
|
-
|
|
27
|
-
},
|
|
28
|
-
getAvatarUrlFromEmail: (email, overrides) => {
|
|
29
|
-
return `${prefix}/proxy/gravatar?email=${encodeURIComponent(email)}&${buildQuery(overrides)}`;
|
|
30
|
-
}
|
|
26
|
+
getAvatarUrl: (hash, overrides) => proxyUrl(path, { hash, ...buildQuery(overrides) }),
|
|
27
|
+
getAvatarUrlFromEmail: (email, overrides) => proxyUrl(path, { email, ...buildQuery(overrides) })
|
|
31
28
|
};
|
|
32
29
|
}
|
|
33
30
|
}
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
1
|
+
import type { RegistryScriptInput, UseScriptContext } from '#nuxt-scripts/types';
|
|
2
2
|
import { MatomoAnalyticsOptions } from './schemas.js';
|
|
3
3
|
export { MatomoAnalyticsOptions };
|
|
4
4
|
export type MatomoAnalyticsInput = RegistryScriptInput<typeof MatomoAnalyticsOptions, false, false>;
|
|
5
|
-
interface MatomoAnalyticsApi {
|
|
5
|
+
export interface MatomoAnalyticsApi {
|
|
6
6
|
_paq: unknown[];
|
|
7
7
|
}
|
|
8
8
|
declare global {
|
|
9
9
|
interface Window extends MatomoAnalyticsApi {
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
export
|
|
12
|
+
export interface MatomoConsent {
|
|
13
|
+
/** Push `setConsentGiven`. Requires `defaultConsent: 'required' | 'given'` at registration to have an effect. */
|
|
14
|
+
give: () => void;
|
|
15
|
+
/** Push `forgetConsentGiven`. Requires `defaultConsent: 'required' | 'given'` at registration to have an effect. */
|
|
16
|
+
forget: () => void;
|
|
17
|
+
}
|
|
18
|
+
export declare function useScriptMatomoAnalytics<T extends MatomoAnalyticsApi>(_options?: MatomoAnalyticsInput): UseScriptContext<T, MatomoConsent>;
|
|
@@ -5,7 +5,7 @@ import { useRegistryScript } from "../utils.js";
|
|
|
5
5
|
import { MatomoAnalyticsOptions } from "./schemas.js";
|
|
6
6
|
export { MatomoAnalyticsOptions };
|
|
7
7
|
export function useScriptMatomoAnalytics(_options) {
|
|
8
|
-
|
|
8
|
+
const instance = useRegistryScript("matomoAnalytics", (options) => {
|
|
9
9
|
const normalizedCloudId = options?.cloudId ? withoutTrailingSlash(withoutProtocol(options.cloudId)) : void 0;
|
|
10
10
|
const origin = options?.matomoUrl ? options.matomoUrl : `https://cdn.matomo.cloud/${normalizedCloudId}/`;
|
|
11
11
|
const _paq = import.meta.client ? window._paq = window._paq || [] : [];
|
|
@@ -30,6 +30,12 @@ export function useScriptMatomoAnalytics(_options) {
|
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
clientInit: import.meta.server ? void 0 : () => {
|
|
33
|
+
if (options?.defaultConsent === "required") {
|
|
34
|
+
_paq.push(["requireConsent"]);
|
|
35
|
+
} else if (options?.defaultConsent === "given") {
|
|
36
|
+
_paq.push(["requireConsent"]);
|
|
37
|
+
_paq.push(["setConsentGiven"]);
|
|
38
|
+
}
|
|
33
39
|
if (options?.enableLinkTracking) {
|
|
34
40
|
_paq.push(["enableLinkTracking"]);
|
|
35
41
|
}
|
|
@@ -59,4 +65,25 @@ export function useScriptMatomoAnalytics(_options) {
|
|
|
59
65
|
}
|
|
60
66
|
};
|
|
61
67
|
}, _options);
|
|
68
|
+
if (import.meta.client && !instance.consent) {
|
|
69
|
+
const requiresConsent = _options?.defaultConsent === "required" || _options?.defaultConsent === "given";
|
|
70
|
+
const warnIfUnsafe = import.meta.dev ? (method) => {
|
|
71
|
+
if (!requiresConsent) {
|
|
72
|
+
logger.warn(`matomo consent.${method}() is a no-op unless \`defaultConsent: 'required'\` or \`'given'\` is set at registration.`);
|
|
73
|
+
}
|
|
74
|
+
} : () => {
|
|
75
|
+
};
|
|
76
|
+
const paq = instance.proxy._paq;
|
|
77
|
+
instance.consent = {
|
|
78
|
+
give: () => {
|
|
79
|
+
warnIfUnsafe("give");
|
|
80
|
+
paq.push(["setConsentGiven"]);
|
|
81
|
+
},
|
|
82
|
+
forget: () => {
|
|
83
|
+
warnIfUnsafe("forget");
|
|
84
|
+
paq.push(["forgetConsentGiven"]);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return instance;
|
|
62
89
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
1
|
+
import type { RegistryScriptInput, UseScriptContext } from '#nuxt-scripts/types';
|
|
2
2
|
import { MetaPixelOptions } from './schemas.js';
|
|
3
3
|
type StandardEvents = 'AddPaymentInfo' | 'AddToCart' | 'AddToWishlist' | 'CompleteRegistration' | 'Contact' | 'CustomizeProduct' | 'Donate' | 'FindLocation' | 'InitiateCheckout' | 'Lead' | 'Purchase' | 'Schedule' | 'Search' | 'StartTrial' | 'SubmitApplication' | 'Subscribe' | 'ViewContent';
|
|
4
4
|
interface EventObjectProperties {
|
|
@@ -38,4 +38,10 @@ declare global {
|
|
|
38
38
|
}
|
|
39
39
|
export { MetaPixelOptions };
|
|
40
40
|
export type MetaPixelInput = RegistryScriptInput<typeof MetaPixelOptions, true, false>;
|
|
41
|
-
export
|
|
41
|
+
export interface MetaPixelConsent {
|
|
42
|
+
/** Call `fbq('consent','grant')`. */
|
|
43
|
+
grant: () => void;
|
|
44
|
+
/** Call `fbq('consent','revoke')`. */
|
|
45
|
+
revoke: () => void;
|
|
46
|
+
}
|
|
47
|
+
export declare function useScriptMetaPixel<T extends MetaPixelApi>(_options?: MetaPixelInput): UseScriptContext<T, MetaPixelConsent>;
|
|
@@ -2,7 +2,7 @@ import { useRegistryScript } from "../utils.js";
|
|
|
2
2
|
import { MetaPixelOptions } from "./schemas.js";
|
|
3
3
|
export { MetaPixelOptions };
|
|
4
4
|
export function useScriptMetaPixel(_options) {
|
|
5
|
-
|
|
5
|
+
const instance = useRegistryScript("metaPixel", (options) => ({
|
|
6
6
|
scriptInput: {
|
|
7
7
|
src: "https://connect.facebook.net/en_US/fbevents.js",
|
|
8
8
|
crossorigin: false
|
|
@@ -27,8 +27,17 @@ export function useScriptMetaPixel(_options) {
|
|
|
27
27
|
fbq.loaded = true;
|
|
28
28
|
fbq.version = "2.0";
|
|
29
29
|
fbq.queue = [];
|
|
30
|
+
if (options?.defaultConsent)
|
|
31
|
+
fbq("consent", options.defaultConsent === "granted" ? "grant" : "revoke");
|
|
30
32
|
fbq("init", options?.id);
|
|
31
33
|
fbq("track", "PageView");
|
|
32
34
|
}
|
|
33
35
|
}), _options);
|
|
36
|
+
if (import.meta.client && !instance.consent) {
|
|
37
|
+
instance.consent = {
|
|
38
|
+
grant: () => instance.proxy.fbq("consent", "grant"),
|
|
39
|
+
revoke: () => instance.proxy.fbq("consent", "revoke")
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return instance;
|
|
34
43
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
1
|
+
import type { RegistryScriptInput, UseScriptContext } from '#nuxt-scripts/types';
|
|
2
2
|
import { MixpanelAnalyticsOptions } from './schemas.js';
|
|
3
3
|
export { MixpanelAnalyticsOptions };
|
|
4
4
|
export type MixpanelAnalyticsInput = RegistryScriptInput<typeof MixpanelAnalyticsOptions>;
|
|
@@ -12,6 +12,10 @@ export interface MixpanelAnalyticsApi {
|
|
|
12
12
|
};
|
|
13
13
|
register: (properties: Record<string, any>) => void;
|
|
14
14
|
init: (token: string, config?: Record<string, any>) => void;
|
|
15
|
+
/** Opt the user in to tracking. Available after the real SDK loads. */
|
|
16
|
+
opt_in_tracking?: () => void;
|
|
17
|
+
/** Opt the user out of tracking. Available after the real SDK loads. */
|
|
18
|
+
opt_out_tracking?: () => void;
|
|
15
19
|
};
|
|
16
20
|
}
|
|
17
21
|
declare global {
|
|
@@ -19,4 +23,10 @@ declare global {
|
|
|
19
23
|
mixpanel: MixpanelAnalyticsApi['mixpanel'];
|
|
20
24
|
}
|
|
21
25
|
}
|
|
22
|
-
export
|
|
26
|
+
export interface MixpanelConsent {
|
|
27
|
+
/** Call `mixpanel.opt_in_tracking()`. */
|
|
28
|
+
optIn: () => void;
|
|
29
|
+
/** Call `mixpanel.opt_out_tracking()`. For boot-time opt-out, use `defaultConsent: 'opt-out'` instead. */
|
|
30
|
+
optOut: () => void;
|
|
31
|
+
}
|
|
32
|
+
export declare function useScriptMixpanelAnalytics<T extends MixpanelAnalyticsApi>(_options?: MixpanelAnalyticsInput): UseScriptContext<T, MixpanelConsent>;
|