@nuxt/scripts 1.0.0-beta.30 → 1.0.0-beta.31
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/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/{CYlYSSNW.js → 6CwTUC2b.js} +1 -1
- package/dist/client/_nuxt/{D5FIkDae.js → B71AlSZ1.js} +1 -1
- package/dist/client/_nuxt/{AwAKM0sG.js → BYGJV5dd.js} +1 -1
- package/dist/client/_nuxt/{Bl23o3st.js → V4W-T8W6.js} +4 -4
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/70b59a3e-a025-4a77-a25a-dfadf5b1749d.json +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +2 -2
- package/dist/module.d.ts +2 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +43 -70
- package/dist/registry.mjs +9 -9
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.d.vue.ts +5 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +11 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +5 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.d.vue.ts +14 -0
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.vue +50 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.vue.d.ts +14 -0
- package/dist/runtime/server/proxy-handler.js +25 -35
- package/dist/shared/scripts.D7e2ENu6.mjs +211 -0
- package/dist/stats.mjs +6 -14
- package/dist/types-source.mjs +15 -1
- package/package.json +2 -2
- package/dist/client/_nuxt/builds/meta/f0b4dd20-8496-4003-b7a3-05cbae515923.json +0 -1
- package/dist/shared/scripts.ViOoYQXH.mjs +0 -381
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"70b59a3e-a025-4a77-a25a-dfadf5b1749d","timestamp":1774072124960}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"70b59a3e-a025-4a77-a25a-dfadf5b1749d","timestamp":1774072124960,"prerendered":[]}
|
package/dist/client/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-scripts/_nuxt/entry.C5SUNdim.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-scripts/_nuxt/entry.C5SUNdim.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/V4W-T8W6.js"><script type="module" src="/__nuxt-scripts/_nuxt/V4W-T8W6.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{"nuxt-scripts":{version:"",defaultScriptOptions:{trigger:"onNuxtReady"},googleStaticMapsProxy:"",endpoints:{}}},app:{baseURL:"/__nuxt-scripts",buildId:"70b59a3e-a025-4a77-a25a-dfadf5b1749d",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1774072130545,false]</script></body></html>
|
package/dist/module.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
2
|
import { FetchOptions } from 'ofetch';
|
|
3
|
-
import { ProxyPrivacyInput } from '../dist/runtime/server/utils/privacy.js';
|
|
4
3
|
import { RegistryScripts, NuxtConfigScriptRegistry, NuxtUseScriptOptionsSerializable, NuxtUseScriptInput } from '../dist/runtime/types.js';
|
|
4
|
+
import { ProxyPrivacyInput } from '../dist/runtime/server/utils/privacy.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Global privacy override for all first-party proxy requests.
|
|
@@ -24,7 +24,7 @@ interface FirstPartyOptions {
|
|
|
24
24
|
* Path prefix for proxy endpoints.
|
|
25
25
|
*
|
|
26
26
|
* Analytics collection requests are proxied through these paths.
|
|
27
|
-
* For example, Google Analytics collection goes to `/_scripts/p/
|
|
27
|
+
* For example, Google Analytics collection goes to `/_scripts/p/www.google-analytics.com/g/collect`.
|
|
28
28
|
* @default '/_scripts/p'
|
|
29
29
|
* @example '/_tracking'
|
|
30
30
|
*/
|
package/dist/module.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
2
|
import { FetchOptions } from 'ofetch';
|
|
3
|
-
import { ProxyPrivacyInput } from '../dist/runtime/server/utils/privacy.js';
|
|
4
3
|
import { RegistryScripts, NuxtConfigScriptRegistry, NuxtUseScriptOptionsSerializable, NuxtUseScriptInput } from '../dist/runtime/types.js';
|
|
4
|
+
import { ProxyPrivacyInput } from '../dist/runtime/server/utils/privacy.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Global privacy override for all first-party proxy requests.
|
|
@@ -24,7 +24,7 @@ interface FirstPartyOptions {
|
|
|
24
24
|
* Path prefix for proxy endpoints.
|
|
25
25
|
*
|
|
26
26
|
* Analytics collection requests are proxied through these paths.
|
|
27
|
-
* For example, Google Analytics collection goes to `/_scripts/p/
|
|
27
|
+
* For example, Google Analytics collection goes to `/_scripts/p/www.google-analytics.com/g/collect`.
|
|
28
28
|
* @default '/_scripts/p'
|
|
29
29
|
* @example '/_tracking'
|
|
30
30
|
*/
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -19,48 +19,34 @@ import { colors } from 'consola/utils';
|
|
|
19
19
|
import MagicString from 'magic-string';
|
|
20
20
|
import { hash } from 'ohash';
|
|
21
21
|
import { registry } from './registry.mjs';
|
|
22
|
-
import { g as getAllProxyConfigs
|
|
22
|
+
import { g as getAllProxyConfigs } from './shared/scripts.D7e2ENu6.mjs';
|
|
23
23
|
|
|
24
|
-
function generatePartytownResolveUrl(
|
|
25
|
-
const rulesJson = JSON.stringify(interceptRules);
|
|
24
|
+
function generatePartytownResolveUrl(proxyPrefix) {
|
|
26
25
|
return `function(url, location, type) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
var rule = rules[i];
|
|
30
|
-
if (url.hostname === rule.pattern || url.hostname.endsWith('.' + rule.pattern)) {
|
|
31
|
-
if (rule.pathPrefix && !url.pathname.startsWith(rule.pathPrefix)) continue;
|
|
32
|
-
var path = rule.pathPrefix ? url.pathname.slice(rule.pathPrefix.length) : url.pathname;
|
|
33
|
-
var newPath = rule.target + (path.startsWith('/') ? '' : '/') + path + url.search;
|
|
34
|
-
return new URL(newPath, location.origin);
|
|
35
|
-
}
|
|
26
|
+
if (url.origin !== location.origin) {
|
|
27
|
+
return new URL(${JSON.stringify(proxyPrefix)} + '/' + url.host + url.pathname + url.search, location.origin);
|
|
36
28
|
}
|
|
37
29
|
}`;
|
|
38
30
|
}
|
|
39
31
|
|
|
40
32
|
const logger = useLogger("@nuxt/scripts");
|
|
41
33
|
|
|
42
|
-
function generateInterceptPluginContents(
|
|
43
|
-
const rulesJson = JSON.stringify(interceptRules);
|
|
34
|
+
function generateInterceptPluginContents(proxyPrefix) {
|
|
44
35
|
return `export default defineNuxtPlugin({
|
|
45
36
|
name: 'nuxt-scripts:intercept',
|
|
46
37
|
enforce: 'pre',
|
|
47
38
|
setup() {
|
|
48
|
-
const
|
|
39
|
+
const proxyPrefix = ${JSON.stringify(proxyPrefix)};
|
|
49
40
|
const origBeacon = typeof navigator !== 'undefined' && navigator.sendBeacon
|
|
50
41
|
? navigator.sendBeacon.bind(navigator)
|
|
51
42
|
: () => false;
|
|
52
43
|
const origFetch = globalThis.fetch.bind(globalThis);
|
|
53
44
|
|
|
54
|
-
function
|
|
45
|
+
function proxyUrl(url) {
|
|
55
46
|
try {
|
|
56
47
|
const parsed = new URL(url, location.origin);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (rule.pathPrefix && !parsed.pathname.startsWith(rule.pathPrefix)) continue;
|
|
60
|
-
const path = rule.pathPrefix ? parsed.pathname.slice(rule.pathPrefix.length) : parsed.pathname;
|
|
61
|
-
return location.origin + rule.target + (path.startsWith('/') ? '' : '/') + path + parsed.search;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
48
|
+
if (parsed.origin !== location.origin)
|
|
49
|
+
return location.origin + proxyPrefix + '/' + parsed.host + parsed.pathname + parsed.search;
|
|
64
50
|
} catch {}
|
|
65
51
|
return url;
|
|
66
52
|
}
|
|
@@ -70,7 +56,7 @@ function generateInterceptPluginContents(interceptRules) {
|
|
|
70
56
|
class ProxiedXHR extends OrigXHR {
|
|
71
57
|
open() {
|
|
72
58
|
const args = Array.from(arguments);
|
|
73
|
-
if (typeof args[1] === 'string') args[1] =
|
|
59
|
+
if (typeof args[1] === 'string') args[1] = proxyUrl(args[1]);
|
|
74
60
|
return super.open.apply(this, args);
|
|
75
61
|
}
|
|
76
62
|
}
|
|
@@ -83,7 +69,7 @@ function generateInterceptPluginContents(interceptRules) {
|
|
|
83
69
|
if (origSrcDesc && origSrcDesc.set) {
|
|
84
70
|
Object.defineProperty(img, 'src', {
|
|
85
71
|
get() { return origSrcDesc.get.call(this); },
|
|
86
|
-
set(v) { origSrcDesc.set.call(this, typeof v === 'string' ?
|
|
72
|
+
set(v) { origSrcDesc.set.call(this, typeof v === 'string' ? proxyUrl(v) : v); },
|
|
87
73
|
configurable: true,
|
|
88
74
|
});
|
|
89
75
|
}
|
|
@@ -91,8 +77,8 @@ function generateInterceptPluginContents(interceptRules) {
|
|
|
91
77
|
}
|
|
92
78
|
|
|
93
79
|
globalThis.__nuxtScripts = {
|
|
94
|
-
sendBeacon: (url, data) => origBeacon(
|
|
95
|
-
fetch: (url, opts) => origFetch(typeof url === 'string' ?
|
|
80
|
+
sendBeacon: (url, data) => origBeacon(proxyUrl(url), data),
|
|
81
|
+
fetch: (url, opts) => origFetch(typeof url === 'string' ? proxyUrl(url) : url, opts),
|
|
96
82
|
XMLHttpRequest: ProxiedXHR,
|
|
97
83
|
Image: ProxiedImage,
|
|
98
84
|
};
|
|
@@ -106,7 +92,7 @@ async function setupFirstParty(config, resolvePath) {
|
|
|
106
92
|
const proxyPrefix = typeof config.firstParty === "object" ? config.firstParty.proxyPrefix || "/_scripts/p" : "/_scripts/p";
|
|
107
93
|
const privacy = typeof config.firstParty === "object" ? config.firstParty.privacy : void 0;
|
|
108
94
|
const assetsPrefix = config.assets?.prefix || "/_scripts/assets";
|
|
109
|
-
const proxyConfigs = enabled ? getAllProxyConfigs(
|
|
95
|
+
const proxyConfigs = enabled ? getAllProxyConfigs() : {};
|
|
110
96
|
const firstParty = { enabled, proxyPrefix, privacy, assetsPrefix, proxyConfigs };
|
|
111
97
|
if (enabled) {
|
|
112
98
|
const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
|
|
@@ -123,6 +109,9 @@ function applyAutoInject(registry, runtimeConfig, proxyPrefix, registryKey, auto
|
|
|
123
109
|
if (!entry)
|
|
124
110
|
return;
|
|
125
111
|
const input = entry[0];
|
|
112
|
+
const scriptOptions = entry[1];
|
|
113
|
+
if (input?.firstParty === false || scriptOptions?.firstParty === false)
|
|
114
|
+
return;
|
|
126
115
|
const rtScripts = runtimeConfig.public?.scripts;
|
|
127
116
|
const rtEntry = rtScripts?.[registryKey];
|
|
128
117
|
const config = rtEntry && typeof rtEntry === "object" ? rtEntry : input;
|
|
@@ -133,16 +122,6 @@ function applyAutoInject(registry, runtimeConfig, proxyPrefix, registryKey, auto
|
|
|
133
122
|
if (rtEntry && typeof rtEntry === "object" && rtEntry !== input)
|
|
134
123
|
rtEntry[autoInject.configField] = value;
|
|
135
124
|
}
|
|
136
|
-
const DOMAIN_RE = /^https?:\/\/([^/]+)/;
|
|
137
|
-
function extractDomains(routes) {
|
|
138
|
-
const domains = /* @__PURE__ */ new Set();
|
|
139
|
-
for (const { proxy } of Object.values(routes)) {
|
|
140
|
-
const match = proxy.match(DOMAIN_RE);
|
|
141
|
-
if (match?.[1])
|
|
142
|
-
domains.add(match[1]);
|
|
143
|
-
}
|
|
144
|
-
return [...domains].sort();
|
|
145
|
-
}
|
|
146
125
|
function computePrivacyLevel(privacy) {
|
|
147
126
|
const flags = Object.values(privacy);
|
|
148
127
|
if (flags.every(Boolean))
|
|
@@ -160,10 +139,10 @@ function finalizeFirstParty(opts) {
|
|
|
160
139
|
if (script.registryKey)
|
|
161
140
|
scriptByKey.set(script.registryKey, script);
|
|
162
141
|
}
|
|
163
|
-
const
|
|
164
|
-
const routePrivacyOverrides = {};
|
|
142
|
+
const domainPrivacy = {};
|
|
165
143
|
const unsupportedScripts = [];
|
|
166
144
|
const unmatchedScripts = [];
|
|
145
|
+
let totalDomains = 0;
|
|
167
146
|
const devtoolsScripts = [];
|
|
168
147
|
for (const key of registryKeys) {
|
|
169
148
|
const script = scriptByKey.get(key);
|
|
@@ -173,6 +152,11 @@ function finalizeFirstParty(opts) {
|
|
|
173
152
|
}
|
|
174
153
|
if (script.proxy === false)
|
|
175
154
|
continue;
|
|
155
|
+
const registryEntry = opts.registry?.[key];
|
|
156
|
+
const entryScriptOptions = registryEntry?.[1];
|
|
157
|
+
const entryInput = registryEntry?.[0];
|
|
158
|
+
if (entryScriptOptions?.firstParty === false || entryInput?.firstParty === false)
|
|
159
|
+
continue;
|
|
176
160
|
const configKey = script.proxy || key;
|
|
177
161
|
const proxyConfig = proxyConfigs[configKey];
|
|
178
162
|
if (!proxyConfig) {
|
|
@@ -180,11 +164,9 @@ function finalizeFirstParty(opts) {
|
|
|
180
164
|
unsupportedScripts.push(key);
|
|
181
165
|
continue;
|
|
182
166
|
}
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
for (const routePath of Object.keys(proxyConfig.routes))
|
|
187
|
-
routePrivacyOverrides[routePath] = proxyConfig.privacy;
|
|
167
|
+
for (const domain of proxyConfig.domains) {
|
|
168
|
+
domainPrivacy[domain] = proxyConfig.privacy;
|
|
169
|
+
totalDomains++;
|
|
188
170
|
}
|
|
189
171
|
if (proxyConfig.autoInject && opts.registry)
|
|
190
172
|
applyAutoInject(opts.registry, nuxtOptions.runtimeConfig, proxyPrefix, key, proxyConfig.autoInject);
|
|
@@ -200,7 +182,6 @@ function finalizeFirstParty(opts) {
|
|
|
200
182
|
};
|
|
201
183
|
const logo = script.logo;
|
|
202
184
|
const logoStr = typeof logo === "object" ? logo.dark || logo.light : logo || "";
|
|
203
|
-
const interceptRules2 = routesToInterceptRules(scriptRoutes);
|
|
204
185
|
devtoolsScripts.push({
|
|
205
186
|
registryKey: key,
|
|
206
187
|
label: script.label || key,
|
|
@@ -213,9 +194,7 @@ function finalizeFirstParty(opts) {
|
|
|
213
194
|
hasPostProcess: !!proxyConfig.postProcess,
|
|
214
195
|
privacy: normalizedPrivacy,
|
|
215
196
|
privacyLevel: computePrivacyLevel(normalizedPrivacy),
|
|
216
|
-
domains:
|
|
217
|
-
routes: Object.entries(scriptRoutes).map(([local, { proxy }]) => ({ local, target: proxy })),
|
|
218
|
-
interceptRules: interceptRules2
|
|
197
|
+
domains: [...proxyConfig.domains]
|
|
219
198
|
});
|
|
220
199
|
}
|
|
221
200
|
}
|
|
@@ -231,30 +210,21 @@ These scripts will not have proxy routes registered. Check that the registry key
|
|
|
231
210
|
They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
|
|
232
211
|
);
|
|
233
212
|
}
|
|
234
|
-
const interceptRules = routesToInterceptRules(neededRoutes);
|
|
235
213
|
addPluginTemplate({
|
|
236
214
|
filename: "nuxt-scripts-intercept.client.mjs",
|
|
237
215
|
getContents() {
|
|
238
|
-
return generateInterceptPluginContents(
|
|
216
|
+
return generateInterceptPluginContents(proxyPrefix);
|
|
239
217
|
}
|
|
240
218
|
});
|
|
241
|
-
const flatRoutes = {};
|
|
242
|
-
for (const [path, config] of Object.entries(neededRoutes))
|
|
243
|
-
flatRoutes[path] = config.proxy;
|
|
244
219
|
nuxtOptions.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
220
|
+
proxyPrefix,
|
|
221
|
+
domainPrivacy,
|
|
222
|
+
privacy: firstParty.privacy
|
|
248
223
|
};
|
|
249
224
|
const privacyLabel = firstParty.privacy === void 0 ? "per-script" : typeof firstParty.privacy === "boolean" ? firstParty.privacy ? "anonymize" : "passthrough" : "custom";
|
|
250
|
-
if (
|
|
251
|
-
const routeCount = Object.keys(neededRoutes).length;
|
|
225
|
+
if (totalDomains > 0 && nuxtOptions.dev) {
|
|
252
226
|
const scriptsCount = registryKeys.length;
|
|
253
|
-
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${
|
|
254
|
-
if (logger.level >= 4) {
|
|
255
|
-
for (const [path, config] of Object.entries(neededRoutes))
|
|
256
|
-
logger.debug(` ${path} \u2192 ${config.proxy}`);
|
|
257
|
-
}
|
|
227
|
+
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${totalDomains} domain(s) proxied (privacy: ${privacyLabel})`);
|
|
258
228
|
}
|
|
259
229
|
const staticPresets = ["static", "github-pages", "cloudflare-pages-static", "netlify-static", "azure-static", "firebase-static"];
|
|
260
230
|
const preset = process.env.NITRO_PRESET || "";
|
|
@@ -283,11 +253,10 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
|
283
253
|
proxyPrefix,
|
|
284
254
|
privacyMode: privacyLabel,
|
|
285
255
|
scripts: devtoolsScripts,
|
|
286
|
-
totalRoutes: Object.keys(neededRoutes).length,
|
|
287
256
|
totalDomains: allDomains.size
|
|
288
257
|
};
|
|
289
258
|
}
|
|
290
|
-
return {
|
|
259
|
+
return { proxyPrefix, devtools };
|
|
291
260
|
}
|
|
292
261
|
|
|
293
262
|
const renderedScript = /* @__PURE__ */ new Map();
|
|
@@ -1056,7 +1025,10 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
1056
1025
|
const script = options.scripts?.find((s2) => s2.import.name === fnName);
|
|
1057
1026
|
const proxyConfigKey = script?.proxy !== false ? script?.proxy || registryKey : void 0;
|
|
1058
1027
|
const proxyConfig = !firstPartyOptOut && proxyConfigKey ? options.proxyConfigs?.[proxyConfigKey] : void 0;
|
|
1059
|
-
const proxyRewrites = proxyConfig?.
|
|
1028
|
+
const proxyRewrites = proxyConfig?.domains?.map((domain) => ({
|
|
1029
|
+
from: domain,
|
|
1030
|
+
to: `${options.proxyPrefix}/${domain}`
|
|
1031
|
+
}));
|
|
1060
1032
|
const postProcess = proxyConfig?.postProcess;
|
|
1061
1033
|
const skipApiRewrites = !!(registryKey && options.partytownScripts?.has(registryKey));
|
|
1062
1034
|
deferredOps.push(async () => {
|
|
@@ -1601,7 +1573,7 @@ const module$1 = defineNuxtModule({
|
|
|
1601
1573
|
}
|
|
1602
1574
|
const { renderedScript } = setupPublicAssetStrategy(config.assets);
|
|
1603
1575
|
if (firstParty.enabled) {
|
|
1604
|
-
const {
|
|
1576
|
+
const { proxyPrefix, devtools: devtoolsData } = finalizeFirstParty({
|
|
1605
1577
|
firstParty,
|
|
1606
1578
|
registry: config.registry,
|
|
1607
1579
|
registryScripts,
|
|
@@ -1610,10 +1582,10 @@ const module$1 = defineNuxtModule({
|
|
|
1610
1582
|
if (devtoolsData) {
|
|
1611
1583
|
nuxt.options.runtimeConfig.public["nuxt-scripts-devtools"] = devtoolsData;
|
|
1612
1584
|
}
|
|
1613
|
-
if (config.partytown?.length && hasNuxtModule("@nuxtjs/partytown")
|
|
1585
|
+
if (config.partytown?.length && hasNuxtModule("@nuxtjs/partytown")) {
|
|
1614
1586
|
const partytownConfig = nuxt.options.partytown || {};
|
|
1615
1587
|
if (!partytownConfig.resolveUrl) {
|
|
1616
|
-
partytownConfig.resolveUrl = generatePartytownResolveUrl(
|
|
1588
|
+
partytownConfig.resolveUrl = generatePartytownResolveUrl(proxyPrefix);
|
|
1617
1589
|
nuxt.options.partytown = partytownConfig;
|
|
1618
1590
|
logger.info("[partytown] Auto-configured resolveUrl for first-party proxy");
|
|
1619
1591
|
} else {
|
|
@@ -1630,6 +1602,7 @@ const module$1 = defineNuxtModule({
|
|
|
1630
1602
|
registryConfig: nuxt.options.runtimeConfig.public.scripts,
|
|
1631
1603
|
defaultBundle: firstParty.enabled || config.defaultScriptOptions?.bundle,
|
|
1632
1604
|
proxyConfigs: firstParty.proxyConfigs,
|
|
1605
|
+
proxyPrefix: firstParty.proxyPrefix,
|
|
1633
1606
|
partytownScripts: new Set(config.partytown || []),
|
|
1634
1607
|
moduleDetected(module) {
|
|
1635
1608
|
if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
|
package/dist/registry.mjs
CHANGED
|
@@ -340,6 +340,8 @@ async function registry(resolve) {
|
|
|
340
340
|
registryKey: "stripe",
|
|
341
341
|
label: "Stripe",
|
|
342
342
|
scriptBundling: false,
|
|
343
|
+
// needs fingerprinting for fraud detection
|
|
344
|
+
proxy: false,
|
|
343
345
|
category: "payments",
|
|
344
346
|
logo: LOGOS.stripe,
|
|
345
347
|
import: {
|
|
@@ -363,7 +365,8 @@ async function registry(resolve) {
|
|
|
363
365
|
registryKey: "paypal",
|
|
364
366
|
label: "PayPal",
|
|
365
367
|
src: false,
|
|
366
|
-
//
|
|
368
|
+
// needs fingerprinting for fraud detection
|
|
369
|
+
proxy: false,
|
|
367
370
|
category: "payments",
|
|
368
371
|
logo: LOGOS.paypal,
|
|
369
372
|
import: {
|
|
@@ -466,18 +469,14 @@ async function registry(resolve) {
|
|
|
466
469
|
{
|
|
467
470
|
registryKey: "googleRecaptcha",
|
|
468
471
|
label: "Google reCAPTCHA",
|
|
472
|
+
scriptBundling: false,
|
|
473
|
+
// needs fingerprinting for bot detection
|
|
474
|
+
proxy: false,
|
|
469
475
|
category: "utility",
|
|
470
476
|
logo: LOGOS.googleRecaptcha,
|
|
471
477
|
import: {
|
|
472
478
|
name: "useScriptGoogleRecaptcha",
|
|
473
479
|
from: await resolve("./runtime/registry/google-recaptcha")
|
|
474
|
-
},
|
|
475
|
-
scriptBundling(options) {
|
|
476
|
-
if (!options?.siteKey) {
|
|
477
|
-
return false;
|
|
478
|
-
}
|
|
479
|
-
const baseUrl = options?.recaptchaNet ? "https://www.recaptcha.net/recaptcha" : "https://www.google.com/recaptcha";
|
|
480
|
-
return `${baseUrl}/${options?.enterprise ? "enterprise.js" : "api.js"}`;
|
|
481
480
|
}
|
|
482
481
|
},
|
|
483
482
|
{
|
|
@@ -485,7 +484,8 @@ async function registry(resolve) {
|
|
|
485
484
|
label: "Google Sign-In",
|
|
486
485
|
src: "https://accounts.google.com/gsi/client",
|
|
487
486
|
scriptBundling: false,
|
|
488
|
-
// CORS prevents bundling
|
|
487
|
+
// CORS prevents bundling, needs fingerprinting for auth
|
|
488
|
+
proxy: false,
|
|
489
489
|
category: "utility",
|
|
490
490
|
logo: LOGOS.googleSignIn,
|
|
491
491
|
import: {
|
|
@@ -12,10 +12,13 @@ export interface MarkerClustererOptions {
|
|
|
12
12
|
renderer?: unknown;
|
|
13
13
|
onClusterClick?: unknown;
|
|
14
14
|
}
|
|
15
|
-
export
|
|
15
|
+
export interface MarkerClustererContext {
|
|
16
16
|
markerClusterer: ShallowRef<MarkerClustererInstance | undefined>;
|
|
17
17
|
requestRerender: () => void;
|
|
18
|
-
|
|
18
|
+
/** Increments after each clustering cycle; watch to detect cluster membership changes */
|
|
19
|
+
clusteringVersion: ShallowRef<number>;
|
|
20
|
+
}
|
|
21
|
+
export declare const MARKER_CLUSTERER_INJECTION_KEY: InjectionKey<MarkerClustererContext>;
|
|
19
22
|
declare const _default: typeof __VLS_export;
|
|
20
23
|
export default _default;
|
|
21
24
|
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { provide, shallowRef, watch } from "vue";
|
|
2
|
+
import { inject, provide, shallowRef, watch } from "vue";
|
|
3
3
|
import { bindGoogleMapsEvents } from "./bindGoogleMapsEvents";
|
|
4
|
+
import { MAP_INJECTION_KEY } from "./injectionKeys";
|
|
4
5
|
import { useGoogleMapsResource } from "./useGoogleMapsResource";
|
|
5
6
|
export const MARKER_CLUSTERER_INJECTION_KEY = /* @__PURE__ */ Symbol("marker-clusterer");
|
|
6
7
|
</script>
|
|
@@ -15,6 +16,8 @@ const markerClustererEvents = [
|
|
|
15
16
|
"clusteringbegin",
|
|
16
17
|
"clusteringend"
|
|
17
18
|
];
|
|
19
|
+
const mapContext = inject(MAP_INJECTION_KEY, void 0);
|
|
20
|
+
const clusteringVersion = shallowRef(0);
|
|
18
21
|
const markerClusterer = useGoogleMapsResource({
|
|
19
22
|
async create({ map }) {
|
|
20
23
|
const { MarkerClusterer } = await import("@googlemaps/markerclusterer");
|
|
@@ -23,6 +26,9 @@ const markerClusterer = useGoogleMapsResource({
|
|
|
23
26
|
...props.options
|
|
24
27
|
});
|
|
25
28
|
bindGoogleMapsEvents(clusterer, emit, { withPayload: markerClustererEvents });
|
|
29
|
+
clusterer.addListener("clusteringend", () => {
|
|
30
|
+
clusteringVersion.value++;
|
|
31
|
+
});
|
|
26
32
|
return clusterer;
|
|
27
33
|
},
|
|
28
34
|
cleanup(clusterer, { mapsApi }) {
|
|
@@ -39,6 +45,8 @@ watch(
|
|
|
39
45
|
(ready) => {
|
|
40
46
|
if (!ready)
|
|
41
47
|
return;
|
|
48
|
+
if (!mapContext?.map.value?.getProjection())
|
|
49
|
+
return;
|
|
42
50
|
rerenderPending.value = false;
|
|
43
51
|
try {
|
|
44
52
|
markerClusterer.value.render();
|
|
@@ -53,7 +61,8 @@ provide(
|
|
|
53
61
|
MARKER_CLUSTERER_INJECTION_KEY,
|
|
54
62
|
{
|
|
55
63
|
markerClusterer,
|
|
56
|
-
requestRerender
|
|
64
|
+
requestRerender,
|
|
65
|
+
clusteringVersion
|
|
57
66
|
}
|
|
58
67
|
);
|
|
59
68
|
</script>
|
|
@@ -12,10 +12,13 @@ export interface MarkerClustererOptions {
|
|
|
12
12
|
renderer?: unknown;
|
|
13
13
|
onClusterClick?: unknown;
|
|
14
14
|
}
|
|
15
|
-
export
|
|
15
|
+
export interface MarkerClustererContext {
|
|
16
16
|
markerClusterer: ShallowRef<MarkerClustererInstance | undefined>;
|
|
17
17
|
requestRerender: () => void;
|
|
18
|
-
|
|
18
|
+
/** Increments after each clustering cycle; watch to detect cluster membership changes */
|
|
19
|
+
clusteringVersion: ShallowRef<number>;
|
|
20
|
+
}
|
|
21
|
+
export declare const MARKER_CLUSTERER_INJECTION_KEY: InjectionKey<MarkerClustererContext>;
|
|
19
22
|
declare const _default: typeof __VLS_export;
|
|
20
23
|
export default _default;
|
|
21
24
|
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
@@ -33,6 +33,18 @@ type __VLS_Props = {
|
|
|
33
33
|
* @default true
|
|
34
34
|
*/
|
|
35
35
|
blockMapInteraction?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Pan the map so the overlay is fully visible when opened, similar to InfoWindow behavior.
|
|
38
|
+
* Set to `true` for default 40px padding, or a number for custom padding.
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
panOnOpen?: boolean | number;
|
|
42
|
+
/**
|
|
43
|
+
* Automatically hide the overlay when its parent marker joins a cluster (on zoom out).
|
|
44
|
+
* Only applies when nested inside a ScriptGoogleMapsMarkerClusterer.
|
|
45
|
+
* @default true
|
|
46
|
+
*/
|
|
47
|
+
hideWhenClustered?: boolean;
|
|
36
48
|
};
|
|
37
49
|
type __VLS_ModelProps = {
|
|
38
50
|
'open'?: boolean;
|
|
@@ -52,6 +64,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
52
64
|
anchor: OverlayAnchor;
|
|
53
65
|
pane: OverlayPane;
|
|
54
66
|
blockMapInteraction: boolean;
|
|
67
|
+
panOnOpen: boolean | number;
|
|
68
|
+
hideWhenClustered: boolean;
|
|
55
69
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
56
70
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
57
71
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { inject, useTemplateRef, watch } from "vue";
|
|
3
3
|
import { ADVANCED_MARKER_ELEMENT_INJECTION_KEY, MARKER_INJECTION_KEY } from "./injectionKeys";
|
|
4
|
+
import { MARKER_CLUSTERER_INJECTION_KEY } from "./ScriptGoogleMapsMarkerClusterer.vue";
|
|
4
5
|
import { useGoogleMapsResource } from "./useGoogleMapsResource";
|
|
5
6
|
const props = defineProps({
|
|
6
7
|
position: { type: null, required: false },
|
|
@@ -8,11 +9,14 @@ const props = defineProps({
|
|
|
8
9
|
offset: { type: Object, required: false },
|
|
9
10
|
pane: { type: String, required: false, default: "floatPane" },
|
|
10
11
|
zIndex: { type: Number, required: false },
|
|
11
|
-
blockMapInteraction: { type: Boolean, required: false, default: true }
|
|
12
|
+
blockMapInteraction: { type: Boolean, required: false, default: true },
|
|
13
|
+
panOnOpen: { type: [Boolean, Number], required: false, default: true },
|
|
14
|
+
hideWhenClustered: { type: Boolean, required: false, default: true }
|
|
12
15
|
});
|
|
13
16
|
const open = defineModel("open", { type: Boolean, ...{ default: void 0 } });
|
|
14
17
|
const markerContext = inject(MARKER_INJECTION_KEY, void 0);
|
|
15
18
|
const advancedMarkerElementContext = inject(ADVANCED_MARKER_ELEMENT_INJECTION_KEY, void 0);
|
|
19
|
+
const markerClustererContext = inject(MARKER_CLUSTERER_INJECTION_KEY, void 0);
|
|
16
20
|
function getResolvedPosition() {
|
|
17
21
|
if (props.position)
|
|
18
22
|
return props.position;
|
|
@@ -44,6 +48,25 @@ const ANCHOR_TRANSFORMS = {
|
|
|
44
48
|
};
|
|
45
49
|
const overlayContent = useTemplateRef("overlay-content");
|
|
46
50
|
const listeners = [];
|
|
51
|
+
function panMapToFitOverlay(el, map, padding) {
|
|
52
|
+
const child = el.firstElementChild;
|
|
53
|
+
if (!child)
|
|
54
|
+
return;
|
|
55
|
+
const overlayRect = child.getBoundingClientRect();
|
|
56
|
+
const mapRect = map.getDiv().getBoundingClientRect();
|
|
57
|
+
let panX = 0;
|
|
58
|
+
let panY = 0;
|
|
59
|
+
if (overlayRect.top - padding < mapRect.top)
|
|
60
|
+
panY = overlayRect.top - mapRect.top - padding;
|
|
61
|
+
if (overlayRect.bottom + padding > mapRect.bottom)
|
|
62
|
+
panY = overlayRect.bottom - mapRect.bottom + padding;
|
|
63
|
+
if (overlayRect.left - padding < mapRect.left)
|
|
64
|
+
panX = overlayRect.left - mapRect.left - padding;
|
|
65
|
+
else if (overlayRect.right + padding > mapRect.right)
|
|
66
|
+
panX = overlayRect.right - mapRect.right + padding;
|
|
67
|
+
if (panX !== 0 || panY !== 0)
|
|
68
|
+
map.panBy(panX, panY);
|
|
69
|
+
}
|
|
47
70
|
const overlay = useGoogleMapsResource({
|
|
48
71
|
// ready condition accesses .value on ShallowRefs — tracked by whenever() in useGoogleMapsResource
|
|
49
72
|
ready: () => !!overlayContent.value && !!(props.position || markerContext?.marker.value || advancedMarkerElementContext?.advancedMarkerElement.value),
|
|
@@ -57,6 +80,12 @@ const overlay = useGoogleMapsResource({
|
|
|
57
80
|
if (props.blockMapInteraction)
|
|
58
81
|
mapsApi.OverlayView.preventMapHitsAndGesturesFrom(el);
|
|
59
82
|
}
|
|
83
|
+
if (props.panOnOpen) {
|
|
84
|
+
const padding = typeof props.panOnOpen === "number" ? props.panOnOpen : 40;
|
|
85
|
+
requestAnimationFrame(() => {
|
|
86
|
+
panMapToFitOverlay(el, map, padding);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
60
89
|
}
|
|
61
90
|
draw() {
|
|
62
91
|
if (open.value === false) {
|
|
@@ -148,6 +177,26 @@ watch([() => props.pane, () => props.blockMapInteraction], () => {
|
|
|
148
177
|
overlay.value.setMap(map);
|
|
149
178
|
}
|
|
150
179
|
});
|
|
180
|
+
if (markerClustererContext && (markerContext || advancedMarkerElementContext)) {
|
|
181
|
+
watch(
|
|
182
|
+
() => markerClustererContext.clusteringVersion.value,
|
|
183
|
+
() => {
|
|
184
|
+
if (!props.hideWhenClustered || open.value === false)
|
|
185
|
+
return;
|
|
186
|
+
const clusterer = markerClustererContext.markerClusterer.value;
|
|
187
|
+
if (!clusterer?.clusters)
|
|
188
|
+
return;
|
|
189
|
+
const parentMarker = advancedMarkerElementContext?.advancedMarkerElement.value ?? markerContext?.marker.value;
|
|
190
|
+
if (!parentMarker)
|
|
191
|
+
return;
|
|
192
|
+
const isClustered = clusterer.clusters.some(
|
|
193
|
+
(cluster) => cluster.count > 1 && cluster.markers?.includes(parentMarker)
|
|
194
|
+
);
|
|
195
|
+
if (isClustered)
|
|
196
|
+
open.value = false;
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
}
|
|
151
200
|
defineExpose({ overlay });
|
|
152
201
|
</script>
|
|
153
202
|
|
|
@@ -33,6 +33,18 @@ type __VLS_Props = {
|
|
|
33
33
|
* @default true
|
|
34
34
|
*/
|
|
35
35
|
blockMapInteraction?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Pan the map so the overlay is fully visible when opened, similar to InfoWindow behavior.
|
|
38
|
+
* Set to `true` for default 40px padding, or a number for custom padding.
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
panOnOpen?: boolean | number;
|
|
42
|
+
/**
|
|
43
|
+
* Automatically hide the overlay when its parent marker joins a cluster (on zoom out).
|
|
44
|
+
* Only applies when nested inside a ScriptGoogleMapsMarkerClusterer.
|
|
45
|
+
* @default true
|
|
46
|
+
*/
|
|
47
|
+
hideWhenClustered?: boolean;
|
|
36
48
|
};
|
|
37
49
|
type __VLS_ModelProps = {
|
|
38
50
|
'open'?: boolean;
|
|
@@ -52,6 +64,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
52
64
|
anchor: OverlayAnchor;
|
|
53
65
|
pane: OverlayPane;
|
|
54
66
|
blockMapInteraction: boolean;
|
|
67
|
+
panOnOpen: boolean | number;
|
|
68
|
+
hideWhenClustered: boolean;
|
|
55
69
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
56
70
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
57
71
|
declare const _default: typeof __VLS_export;
|