@accelerated-agency/visual-editor 0.4.2 → 0.4.3
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/index.js +23 -3
- package/dist/vite.cjs +51 -11
- package/dist/vite.js +51 -11
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -4657,7 +4657,6 @@ function PlatformVisualEditor({
|
|
|
4657
4657
|
}),
|
|
4658
4658
|
[experiment]
|
|
4659
4659
|
);
|
|
4660
|
-
console.log("loadPayload", loadPayload);
|
|
4661
4660
|
useEffect(() => {
|
|
4662
4661
|
if (!editorReady) return;
|
|
4663
4662
|
const payloadKey = JSON.stringify(loadPayload);
|
|
@@ -4807,6 +4806,7 @@ function PlatformVisualEditorV2({
|
|
|
4807
4806
|
// channel kept for API compatibility; VvvebJs uses its own internal channel
|
|
4808
4807
|
embeddedGlobalKey = "__CONVERSION_EMBEDDED__",
|
|
4809
4808
|
proxyBaseUrl = "",
|
|
4809
|
+
conversionProxyBaseUrl = "",
|
|
4810
4810
|
strictObserverFreeze = false,
|
|
4811
4811
|
trackingMarkers = [],
|
|
4812
4812
|
className = "fixed inset-0 z-[9999] flex flex-col bg-white",
|
|
@@ -4839,6 +4839,7 @@ function PlatformVisualEditorV2({
|
|
|
4839
4839
|
}) {
|
|
4840
4840
|
const iframeRef = useRef(null);
|
|
4841
4841
|
const [editorReady, setEditorReady] = useState(false);
|
|
4842
|
+
const [iframeLoaded, setIframeLoaded] = useState(false);
|
|
4842
4843
|
const [isSaving, setIsSaving] = useState(false);
|
|
4843
4844
|
const [dirty, setDirty] = useState(false);
|
|
4844
4845
|
const dirtyRef = useRef(false);
|
|
@@ -4870,11 +4871,12 @@ function PlatformVisualEditorV2({
|
|
|
4870
4871
|
status: experiment?.status,
|
|
4871
4872
|
pageUrl: experiment?.pageUrl,
|
|
4872
4873
|
editorPassword: experiment?.editorPassword,
|
|
4874
|
+
conversionProxyBaseUrl: typeof conversionProxyBaseUrl === "string" ? conversionProxyBaseUrl.trim().replace(/\/+$/, "") : "",
|
|
4873
4875
|
strictObserverFreeze: !!strictObserverFreeze,
|
|
4874
4876
|
trackingMarkers: Array.isArray(trackingMarkers) ? trackingMarkers.filter((m) => typeof m === "string" && m.trim().length > 0) : [],
|
|
4875
4877
|
variations: experiment?.variations ?? []
|
|
4876
4878
|
}),
|
|
4877
|
-
[experiment, strictObserverFreeze, trackingMarkers]
|
|
4879
|
+
[conversionProxyBaseUrl, experiment, strictObserverFreeze, trackingMarkers]
|
|
4878
4880
|
);
|
|
4879
4881
|
const editorSrc = useMemo(() => {
|
|
4880
4882
|
const safeBaseUrl = normalizeProxyBaseUrl(proxyBaseUrl);
|
|
@@ -4968,6 +4970,23 @@ function PlatformVisualEditorV2({
|
|
|
4968
4970
|
window.addEventListener("message", listener);
|
|
4969
4971
|
return () => window.removeEventListener("message", listener);
|
|
4970
4972
|
}, [handleMessage]);
|
|
4973
|
+
useEffect(() => {
|
|
4974
|
+
if (!iframeLoaded || editorReady) return;
|
|
4975
|
+
let attempts = 0;
|
|
4976
|
+
const maxAttempts = 12;
|
|
4977
|
+
const tickMs = 500;
|
|
4978
|
+
const tryBootstrap = () => {
|
|
4979
|
+
if (editorReady) return;
|
|
4980
|
+
attempts += 1;
|
|
4981
|
+
sendToVvveb("load-experiment", loadPayload);
|
|
4982
|
+
if (attempts >= maxAttempts) {
|
|
4983
|
+
clearInterval(timer);
|
|
4984
|
+
}
|
|
4985
|
+
};
|
|
4986
|
+
tryBootstrap();
|
|
4987
|
+
const timer = window.setInterval(tryBootstrap, tickMs);
|
|
4988
|
+
return () => window.clearInterval(timer);
|
|
4989
|
+
}, [iframeLoaded, editorReady, loadPayload, sendToVvveb]);
|
|
4971
4990
|
useCallback(
|
|
4972
4991
|
(tab) => onTabChange?.(tab),
|
|
4973
4992
|
[onTabChange]
|
|
@@ -4987,7 +5006,8 @@ function PlatformVisualEditorV2({
|
|
|
4987
5006
|
src: editorSrc,
|
|
4988
5007
|
className: "w-full h-full border-0",
|
|
4989
5008
|
title: "Vvveb Visual Editor",
|
|
4990
|
-
allow: "same-origin"
|
|
5009
|
+
allow: "same-origin",
|
|
5010
|
+
onLoad: () => setIframeLoaded(true)
|
|
4991
5011
|
}
|
|
4992
5012
|
) }) });
|
|
4993
5013
|
}
|
package/dist/vite.cjs
CHANGED
|
@@ -1140,6 +1140,8 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
1140
1140
|
</div>
|
|
1141
1141
|
|
|
1142
1142
|
<!-- CDN scripts -->
|
|
1143
|
+
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
|
|
1144
|
+
<script src="https://cdn.jsdelivr.net/npm/jquery-ui-dist@1.13.3/jquery-ui.min.js"></script>
|
|
1143
1145
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
1144
1146
|
<script>
|
|
1145
1147
|
window.__veLoadFallback = function(el, candidates){
|
|
@@ -1167,10 +1169,6 @@ window.__veLoadFallback = function(el, candidates){
|
|
|
1167
1169
|
onerror="window.__veLoadFallback(this,'https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/inputs.js||https://unpkg.com/vvvebjs@latest/libs/builder/inputs.js')"
|
|
1168
1170
|
></script>
|
|
1169
1171
|
<!-- components.js removed (frequently missing on npm CDN); safety stubs below prevent bootstrap/widgets loader errors -->
|
|
1170
|
-
// <script
|
|
1171
|
-
// src="https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-widgets.js"
|
|
1172
|
-
// onerror="window.__veLoadFallback(this,'https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-widgets.js||https://unpkg.com/vvvebjs@latest/libs/builder/components-widgets.js')"
|
|
1173
|
-
// ></script>
|
|
1174
1172
|
<script>
|
|
1175
1173
|
/* Safety stub: if components.js didn't define these, create empty arrays so
|
|
1176
1174
|
components-bootstrap5.js doesn't throw ReferenceError on load. */
|
|
@@ -1199,7 +1197,7 @@ if (window.Vvveb && window.Vvveb.Components) {
|
|
|
1199
1197
|
</script>
|
|
1200
1198
|
<script
|
|
1201
1199
|
src="https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-bootstrap4.js"
|
|
1202
|
-
onerror="window.__veLoadFallback(this,'https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-bootstrap4.js||https://unpkg.com/vvvebjs@latest/libs/builder/components-bootstrap4.js')"
|
|
1200
|
+
onerror="window.__veLoadFallback(this,'https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-bootstrap5.js||https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-bootstrap4.js||https://unpkg.com/vvvebjs@latest/libs/builder/components-bootstrap5.js||https://unpkg.com/vvvebjs@latest/libs/builder/components-bootstrap4.js')"
|
|
1203
1201
|
></script>
|
|
1204
1202
|
<script
|
|
1205
1203
|
src="https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-widgets.js"
|
|
@@ -2432,12 +2430,24 @@ function handleLoadExperiment(data) {
|
|
|
2432
2430
|
var extraTrackingMarkers = Array.isArray(data && data.trackingMarkers)
|
|
2433
2431
|
? data.trackingMarkers.filter(function(m){return typeof m === 'string' && m.trim().length > 0;})
|
|
2434
2432
|
: [];
|
|
2433
|
+
var conversionProxyBaseUrl = (typeof (data && data.conversionProxyBaseUrl) === 'string'
|
|
2434
|
+
? data.conversionProxyBaseUrl
|
|
2435
|
+
: '').trim().replace(/\\/+$/, '');
|
|
2436
|
+
var proxyPath = '/api/conversion-proxy';
|
|
2437
|
+
// Keep iframe navigation same-origin for DOM access (selection/editing).
|
|
2438
|
+
// If conversionProxyBaseUrl is provided, middleware delegates upstream fetches
|
|
2439
|
+
// server-side while browser URLs stay local.
|
|
2440
|
+
var proxyRoot = proxyPath;
|
|
2435
2441
|
var trackingMarkersParam = extraTrackingMarkers.length
|
|
2436
2442
|
? '&trackingMarkers=' + encodeURIComponent(JSON.stringify(extraTrackingMarkers))
|
|
2437
2443
|
: '';
|
|
2438
|
-
var
|
|
2444
|
+
var conversionProxyBaseUrlParam = conversionProxyBaseUrl
|
|
2445
|
+
? '&conversionProxyBaseUrl=' + encodeURIComponent(conversionProxyBaseUrl)
|
|
2446
|
+
: '';
|
|
2447
|
+
var proxyUrl = proxyRoot + '?password=' + encodeURIComponent(data.editorPassword || '') +
|
|
2439
2448
|
'&url=' + encodeURIComponent(pageUrl) +
|
|
2440
2449
|
'&strictObserverFreeze=' + encodeURIComponent(data && data.strictObserverFreeze ? '1' : '0') +
|
|
2450
|
+
conversionProxyBaseUrlParam +
|
|
2441
2451
|
trackingMarkersParam;
|
|
2442
2452
|
|
|
2443
2453
|
// Parent often re-posts load-experiment when React re-renders (new object identity) or
|
|
@@ -5523,6 +5533,8 @@ function createVisualEditorMiddleware(options) {
|
|
|
5523
5533
|
const url = new URL(req.url || "", "http://localhost");
|
|
5524
5534
|
const targetUrl = url.searchParams.get("url");
|
|
5525
5535
|
const password = url.searchParams.get("password") || "";
|
|
5536
|
+
const conversionProxyBaseUrlForRequest = (url.searchParams.get("conversionProxyBaseUrl") || "").trim().replace(/\/+$/, "");
|
|
5537
|
+
const proxyRootForRequest = "/api/conversion-proxy";
|
|
5526
5538
|
const extraTrackingMarkersForRequest = parseTrackingMarkersParam(
|
|
5527
5539
|
url.searchParams.get("trackingMarkers")
|
|
5528
5540
|
);
|
|
@@ -5575,7 +5587,34 @@ function createVisualEditorMiddleware(options) {
|
|
|
5575
5587
|
return false;
|
|
5576
5588
|
}
|
|
5577
5589
|
};
|
|
5590
|
+
const workerRawFetch = (input, init = {}) => {
|
|
5591
|
+
const workerUrl = new URL("/api/conversion-proxy", conversionProxyBaseUrlForRequest);
|
|
5592
|
+
workerUrl.searchParams.set("url", input);
|
|
5593
|
+
workerUrl.searchParams.set("raw", "1");
|
|
5594
|
+
const method2 = (init?.method || "GET").toUpperCase();
|
|
5595
|
+
const nextHeaders = {};
|
|
5596
|
+
const h = init?.headers;
|
|
5597
|
+
if (h && typeof h.forEach === "function") {
|
|
5598
|
+
h.forEach((v, k) => {
|
|
5599
|
+
if (!v) return;
|
|
5600
|
+
nextHeaders[k] = String(v);
|
|
5601
|
+
});
|
|
5602
|
+
} else {
|
|
5603
|
+
Object.entries(h || {}).forEach(([k, v]) => {
|
|
5604
|
+
if (!v) return;
|
|
5605
|
+
nextHeaders[k] = Array.isArray(v) ? v.join(",") : String(v);
|
|
5606
|
+
});
|
|
5607
|
+
}
|
|
5608
|
+
return fetch(workerUrl.toString(), {
|
|
5609
|
+
...init,
|
|
5610
|
+
method: method2,
|
|
5611
|
+
headers: nextHeaders
|
|
5612
|
+
});
|
|
5613
|
+
};
|
|
5578
5614
|
const upstreamFetch = async (input, init = {}) => {
|
|
5615
|
+
if (conversionProxyBaseUrlForRequest) {
|
|
5616
|
+
return workerRawFetch(input, init);
|
|
5617
|
+
}
|
|
5579
5618
|
const primary = await scraperFetch(input, init);
|
|
5580
5619
|
if (!await shouldFallbackFromScraper(primary)) {
|
|
5581
5620
|
return primary;
|
|
@@ -5606,7 +5645,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
5606
5645
|
)}`,
|
|
5607
5646
|
redirect: "manual"
|
|
5608
5647
|
});
|
|
5609
|
-
const setCookies = passResp.headers.getSetCookie?.() || [];
|
|
5648
|
+
const setCookies = passResp.headers.getSetCookie?.() || (passResp.headers.get("set-cookie") ? [String(passResp.headers.get("set-cookie"))] : []);
|
|
5610
5649
|
cookieHeader = setCookies.map((c) => c.split(";")[0]).join("; ");
|
|
5611
5650
|
}
|
|
5612
5651
|
const fetchHeaders = { ...headers };
|
|
@@ -5704,7 +5743,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
5704
5743
|
html = stripTrackingScriptsFromScrapedHtml(html, trackingMarkersForRequest);
|
|
5705
5744
|
html = html.replace(/(href|src|action)="\/(?!\/)/g, `$1="${origin}/`);
|
|
5706
5745
|
const escapedOrigin = origin.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5707
|
-
const proxyBase =
|
|
5746
|
+
const proxyBase = `${proxyRootForRequest}?password=${encodeURIComponent(password)}&url=`;
|
|
5708
5747
|
html = html.replace(
|
|
5709
5748
|
new RegExp(`(href|action)="${escapedOrigin}(/[^"]*)"`, "g"),
|
|
5710
5749
|
(match, attr, urlPath) => {
|
|
@@ -5717,7 +5756,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
5717
5756
|
);
|
|
5718
5757
|
html = html.replace(
|
|
5719
5758
|
/data-link="\/(?!\/)([^"]*)"/g,
|
|
5720
|
-
(_match, pathPart) => `data-link="
|
|
5759
|
+
(_match, pathPart) => `data-link="${proxyRootForRequest}?password=${encodeURIComponent(password)}&url=${encodeURIComponent(
|
|
5721
5760
|
`${origin}/${pathPart}`
|
|
5722
5761
|
)}"`
|
|
5723
5762
|
);
|
|
@@ -5741,6 +5780,7 @@ ${iframeAlwaysShowCssGuardScript}
|
|
|
5741
5780
|
var TARGET_ORIGIN=${JSON.stringify(origin)};
|
|
5742
5781
|
var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};
|
|
5743
5782
|
var PROXY_PASSWORD=${JSON.stringify(password)};
|
|
5783
|
+
var PROXY_BASE_URL="";
|
|
5744
5784
|
var STRICT_OBSERVER_FREEZE=${JSON.stringify(strictObserverFreezeForRequest)};
|
|
5745
5785
|
var PARENT_URL_CHANNEL="vvveb-proxy-url";
|
|
5746
5786
|
window.__CONVERSION_EDITOR_ACTIVE__=true;
|
|
@@ -5791,7 +5831,7 @@ function shouldBlockEditorTracking(rawUrl){
|
|
|
5791
5831
|
var looksLikeHeartbeatPayload=hasViewportPing&&hasSessionIds;
|
|
5792
5832
|
var isCrossOriginCollector=host!==TARGET_HOSTNAME&&hasMarker(host,TRACKING_HOST_MARKERS)&&hasMarker(path,TRACKING_PATH_MARKERS);
|
|
5793
5833
|
var isSnowplowStylePath=path==="/i"||path.indexOf("/com.snowplowanalytics.snowplow/")!==-1||path.indexOf("/tp2")!==-1;
|
|
5794
|
-
var isTaboolaUnip=host==="trc-events.taboola.com"
|
|
5834
|
+
var isTaboolaUnip=host==="trc-events.taboola.com"&&/\\/log\\/\\d+\\/unip(?:\\/|$)/.test(path);
|
|
5795
5835
|
var isCollectApiPath=path==="/api/collect"||path.indexOf("/api/collect/")===0;
|
|
5796
5836
|
var isNbCollectorPath=path==="/nb-collector"||path.indexOf("/nb-collector/")===0;
|
|
5797
5837
|
return isCrossOriginCollector||(looksLikeHeartbeatPayload&&isSnowplowStylePath)||isCollectApiPath||isTaboolaUnip||isNbCollectorPath;
|
|
@@ -5861,7 +5901,7 @@ try{window.addEventListener("popstate",notifyEditorUrlChanged,true);}catch(_){}
|
|
|
5861
5901
|
try{window.addEventListener("hashchange",notifyEditorUrlChanged,true);}catch(_){}
|
|
5862
5902
|
function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#");}
|
|
5863
5903
|
function toAbsolute(raw){if(isSkippable(raw))return raw;try{var base=raw.startsWith("/")||raw.startsWith("//")?TARGET_ORIGIN:TARGET_PAGE_URL;return new URL(raw,base).toString();}catch(_){return raw;}}
|
|
5864
|
-
function toProxy(raw){if(isSkippable(raw))return null;var abs=toAbsolute(raw);if(!abs||typeof abs!=="string")return null;try{var parsed=new URL(abs);if(parsed.origin!==TARGET_ORIGIN)return null;
|
|
5904
|
+
function toProxy(raw){if(isSkippable(raw))return null;var abs=toAbsolute(raw);if(!abs||typeof abs!=="string")return null;try{var parsed=new URL(abs);if(parsed.origin!==TARGET_ORIGIN)return null;var root="/api/conversion-proxy";return root+"?password="+encodeURIComponent(PROXY_PASSWORD||"")+"&url="+encodeURIComponent(parsed.toString());}catch(_){return null;}}
|
|
5865
5905
|
var nativeAssign=window.location.assign?window.location.assign.bind(window.location):null;
|
|
5866
5906
|
var nativeReplace=window.location.replace?window.location.replace.bind(window.location):null;
|
|
5867
5907
|
function safeNavigate(raw,mode){var abs=toAbsolute(raw);var prox=toProxy(raw);if(!prox){try{console.warn("[conversion-proxy] redirect blocked",{mode:mode,requested:raw,resolved:abs,origin:TARGET_ORIGIN});}catch(_){}return false;}try{console.info("[conversion-proxy] redirect intercepted",{mode:mode,requested:raw,resolved:abs,proxied:prox});if(mode==="replace"&&nativeReplace){nativeReplace(prox);return true;}if(nativeAssign){nativeAssign(prox);return true;}window.location.href=prox;return true;}catch(err){try{console.warn("[conversion-proxy] redirect interception failed",{mode:mode,requested:raw,resolved:abs,proxied:prox,error:err&&err.message?err.message:String(err)});}catch(_){}return false;}}
|
package/dist/vite.js
CHANGED
|
@@ -1132,6 +1132,8 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
1132
1132
|
</div>
|
|
1133
1133
|
|
|
1134
1134
|
<!-- CDN scripts -->
|
|
1135
|
+
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
|
|
1136
|
+
<script src="https://cdn.jsdelivr.net/npm/jquery-ui-dist@1.13.3/jquery-ui.min.js"></script>
|
|
1135
1137
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
1136
1138
|
<script>
|
|
1137
1139
|
window.__veLoadFallback = function(el, candidates){
|
|
@@ -1159,10 +1161,6 @@ window.__veLoadFallback = function(el, candidates){
|
|
|
1159
1161
|
onerror="window.__veLoadFallback(this,'https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/inputs.js||https://unpkg.com/vvvebjs@latest/libs/builder/inputs.js')"
|
|
1160
1162
|
></script>
|
|
1161
1163
|
<!-- components.js removed (frequently missing on npm CDN); safety stubs below prevent bootstrap/widgets loader errors -->
|
|
1162
|
-
// <script
|
|
1163
|
-
// src="https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-widgets.js"
|
|
1164
|
-
// onerror="window.__veLoadFallback(this,'https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-widgets.js||https://unpkg.com/vvvebjs@latest/libs/builder/components-widgets.js')"
|
|
1165
|
-
// ></script>
|
|
1166
1164
|
<script>
|
|
1167
1165
|
/* Safety stub: if components.js didn't define these, create empty arrays so
|
|
1168
1166
|
components-bootstrap5.js doesn't throw ReferenceError on load. */
|
|
@@ -1191,7 +1189,7 @@ if (window.Vvveb && window.Vvveb.Components) {
|
|
|
1191
1189
|
</script>
|
|
1192
1190
|
<script
|
|
1193
1191
|
src="https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-bootstrap4.js"
|
|
1194
|
-
onerror="window.__veLoadFallback(this,'https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-bootstrap4.js||https://unpkg.com/vvvebjs@latest/libs/builder/components-bootstrap4.js')"
|
|
1192
|
+
onerror="window.__veLoadFallback(this,'https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-bootstrap5.js||https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-bootstrap4.js||https://unpkg.com/vvvebjs@latest/libs/builder/components-bootstrap5.js||https://unpkg.com/vvvebjs@latest/libs/builder/components-bootstrap4.js')"
|
|
1195
1193
|
></script>
|
|
1196
1194
|
<script
|
|
1197
1195
|
src="https://cdn.jsdelivr.net/npm/vvvebjs@latest/libs/builder/components-widgets.js"
|
|
@@ -2424,12 +2422,24 @@ function handleLoadExperiment(data) {
|
|
|
2424
2422
|
var extraTrackingMarkers = Array.isArray(data && data.trackingMarkers)
|
|
2425
2423
|
? data.trackingMarkers.filter(function(m){return typeof m === 'string' && m.trim().length > 0;})
|
|
2426
2424
|
: [];
|
|
2425
|
+
var conversionProxyBaseUrl = (typeof (data && data.conversionProxyBaseUrl) === 'string'
|
|
2426
|
+
? data.conversionProxyBaseUrl
|
|
2427
|
+
: '').trim().replace(/\\/+$/, '');
|
|
2428
|
+
var proxyPath = '/api/conversion-proxy';
|
|
2429
|
+
// Keep iframe navigation same-origin for DOM access (selection/editing).
|
|
2430
|
+
// If conversionProxyBaseUrl is provided, middleware delegates upstream fetches
|
|
2431
|
+
// server-side while browser URLs stay local.
|
|
2432
|
+
var proxyRoot = proxyPath;
|
|
2427
2433
|
var trackingMarkersParam = extraTrackingMarkers.length
|
|
2428
2434
|
? '&trackingMarkers=' + encodeURIComponent(JSON.stringify(extraTrackingMarkers))
|
|
2429
2435
|
: '';
|
|
2430
|
-
var
|
|
2436
|
+
var conversionProxyBaseUrlParam = conversionProxyBaseUrl
|
|
2437
|
+
? '&conversionProxyBaseUrl=' + encodeURIComponent(conversionProxyBaseUrl)
|
|
2438
|
+
: '';
|
|
2439
|
+
var proxyUrl = proxyRoot + '?password=' + encodeURIComponent(data.editorPassword || '') +
|
|
2431
2440
|
'&url=' + encodeURIComponent(pageUrl) +
|
|
2432
2441
|
'&strictObserverFreeze=' + encodeURIComponent(data && data.strictObserverFreeze ? '1' : '0') +
|
|
2442
|
+
conversionProxyBaseUrlParam +
|
|
2433
2443
|
trackingMarkersParam;
|
|
2434
2444
|
|
|
2435
2445
|
// Parent often re-posts load-experiment when React re-renders (new object identity) or
|
|
@@ -5515,6 +5525,8 @@ function createVisualEditorMiddleware(options) {
|
|
|
5515
5525
|
const url = new URL(req.url || "", "http://localhost");
|
|
5516
5526
|
const targetUrl = url.searchParams.get("url");
|
|
5517
5527
|
const password = url.searchParams.get("password") || "";
|
|
5528
|
+
const conversionProxyBaseUrlForRequest = (url.searchParams.get("conversionProxyBaseUrl") || "").trim().replace(/\/+$/, "");
|
|
5529
|
+
const proxyRootForRequest = "/api/conversion-proxy";
|
|
5518
5530
|
const extraTrackingMarkersForRequest = parseTrackingMarkersParam(
|
|
5519
5531
|
url.searchParams.get("trackingMarkers")
|
|
5520
5532
|
);
|
|
@@ -5567,7 +5579,34 @@ function createVisualEditorMiddleware(options) {
|
|
|
5567
5579
|
return false;
|
|
5568
5580
|
}
|
|
5569
5581
|
};
|
|
5582
|
+
const workerRawFetch = (input, init = {}) => {
|
|
5583
|
+
const workerUrl = new URL("/api/conversion-proxy", conversionProxyBaseUrlForRequest);
|
|
5584
|
+
workerUrl.searchParams.set("url", input);
|
|
5585
|
+
workerUrl.searchParams.set("raw", "1");
|
|
5586
|
+
const method2 = (init?.method || "GET").toUpperCase();
|
|
5587
|
+
const nextHeaders = {};
|
|
5588
|
+
const h = init?.headers;
|
|
5589
|
+
if (h && typeof h.forEach === "function") {
|
|
5590
|
+
h.forEach((v, k) => {
|
|
5591
|
+
if (!v) return;
|
|
5592
|
+
nextHeaders[k] = String(v);
|
|
5593
|
+
});
|
|
5594
|
+
} else {
|
|
5595
|
+
Object.entries(h || {}).forEach(([k, v]) => {
|
|
5596
|
+
if (!v) return;
|
|
5597
|
+
nextHeaders[k] = Array.isArray(v) ? v.join(",") : String(v);
|
|
5598
|
+
});
|
|
5599
|
+
}
|
|
5600
|
+
return fetch(workerUrl.toString(), {
|
|
5601
|
+
...init,
|
|
5602
|
+
method: method2,
|
|
5603
|
+
headers: nextHeaders
|
|
5604
|
+
});
|
|
5605
|
+
};
|
|
5570
5606
|
const upstreamFetch = async (input, init = {}) => {
|
|
5607
|
+
if (conversionProxyBaseUrlForRequest) {
|
|
5608
|
+
return workerRawFetch(input, init);
|
|
5609
|
+
}
|
|
5571
5610
|
const primary = await scraperFetch(input, init);
|
|
5572
5611
|
if (!await shouldFallbackFromScraper(primary)) {
|
|
5573
5612
|
return primary;
|
|
@@ -5598,7 +5637,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
5598
5637
|
)}`,
|
|
5599
5638
|
redirect: "manual"
|
|
5600
5639
|
});
|
|
5601
|
-
const setCookies = passResp.headers.getSetCookie?.() || [];
|
|
5640
|
+
const setCookies = passResp.headers.getSetCookie?.() || (passResp.headers.get("set-cookie") ? [String(passResp.headers.get("set-cookie"))] : []);
|
|
5602
5641
|
cookieHeader = setCookies.map((c) => c.split(";")[0]).join("; ");
|
|
5603
5642
|
}
|
|
5604
5643
|
const fetchHeaders = { ...headers };
|
|
@@ -5696,7 +5735,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
5696
5735
|
html = stripTrackingScriptsFromScrapedHtml(html, trackingMarkersForRequest);
|
|
5697
5736
|
html = html.replace(/(href|src|action)="\/(?!\/)/g, `$1="${origin}/`);
|
|
5698
5737
|
const escapedOrigin = origin.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5699
|
-
const proxyBase =
|
|
5738
|
+
const proxyBase = `${proxyRootForRequest}?password=${encodeURIComponent(password)}&url=`;
|
|
5700
5739
|
html = html.replace(
|
|
5701
5740
|
new RegExp(`(href|action)="${escapedOrigin}(/[^"]*)"`, "g"),
|
|
5702
5741
|
(match, attr, urlPath) => {
|
|
@@ -5709,7 +5748,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
5709
5748
|
);
|
|
5710
5749
|
html = html.replace(
|
|
5711
5750
|
/data-link="\/(?!\/)([^"]*)"/g,
|
|
5712
|
-
(_match, pathPart) => `data-link="
|
|
5751
|
+
(_match, pathPart) => `data-link="${proxyRootForRequest}?password=${encodeURIComponent(password)}&url=${encodeURIComponent(
|
|
5713
5752
|
`${origin}/${pathPart}`
|
|
5714
5753
|
)}"`
|
|
5715
5754
|
);
|
|
@@ -5733,6 +5772,7 @@ ${iframeAlwaysShowCssGuardScript}
|
|
|
5733
5772
|
var TARGET_ORIGIN=${JSON.stringify(origin)};
|
|
5734
5773
|
var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};
|
|
5735
5774
|
var PROXY_PASSWORD=${JSON.stringify(password)};
|
|
5775
|
+
var PROXY_BASE_URL="";
|
|
5736
5776
|
var STRICT_OBSERVER_FREEZE=${JSON.stringify(strictObserverFreezeForRequest)};
|
|
5737
5777
|
var PARENT_URL_CHANNEL="vvveb-proxy-url";
|
|
5738
5778
|
window.__CONVERSION_EDITOR_ACTIVE__=true;
|
|
@@ -5783,7 +5823,7 @@ function shouldBlockEditorTracking(rawUrl){
|
|
|
5783
5823
|
var looksLikeHeartbeatPayload=hasViewportPing&&hasSessionIds;
|
|
5784
5824
|
var isCrossOriginCollector=host!==TARGET_HOSTNAME&&hasMarker(host,TRACKING_HOST_MARKERS)&&hasMarker(path,TRACKING_PATH_MARKERS);
|
|
5785
5825
|
var isSnowplowStylePath=path==="/i"||path.indexOf("/com.snowplowanalytics.snowplow/")!==-1||path.indexOf("/tp2")!==-1;
|
|
5786
|
-
var isTaboolaUnip=host==="trc-events.taboola.com"
|
|
5826
|
+
var isTaboolaUnip=host==="trc-events.taboola.com"&&/\\/log\\/\\d+\\/unip(?:\\/|$)/.test(path);
|
|
5787
5827
|
var isCollectApiPath=path==="/api/collect"||path.indexOf("/api/collect/")===0;
|
|
5788
5828
|
var isNbCollectorPath=path==="/nb-collector"||path.indexOf("/nb-collector/")===0;
|
|
5789
5829
|
return isCrossOriginCollector||(looksLikeHeartbeatPayload&&isSnowplowStylePath)||isCollectApiPath||isTaboolaUnip||isNbCollectorPath;
|
|
@@ -5853,7 +5893,7 @@ try{window.addEventListener("popstate",notifyEditorUrlChanged,true);}catch(_){}
|
|
|
5853
5893
|
try{window.addEventListener("hashchange",notifyEditorUrlChanged,true);}catch(_){}
|
|
5854
5894
|
function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#");}
|
|
5855
5895
|
function toAbsolute(raw){if(isSkippable(raw))return raw;try{var base=raw.startsWith("/")||raw.startsWith("//")?TARGET_ORIGIN:TARGET_PAGE_URL;return new URL(raw,base).toString();}catch(_){return raw;}}
|
|
5856
|
-
function toProxy(raw){if(isSkippable(raw))return null;var abs=toAbsolute(raw);if(!abs||typeof abs!=="string")return null;try{var parsed=new URL(abs);if(parsed.origin!==TARGET_ORIGIN)return null;
|
|
5896
|
+
function toProxy(raw){if(isSkippable(raw))return null;var abs=toAbsolute(raw);if(!abs||typeof abs!=="string")return null;try{var parsed=new URL(abs);if(parsed.origin!==TARGET_ORIGIN)return null;var root="/api/conversion-proxy";return root+"?password="+encodeURIComponent(PROXY_PASSWORD||"")+"&url="+encodeURIComponent(parsed.toString());}catch(_){return null;}}
|
|
5857
5897
|
var nativeAssign=window.location.assign?window.location.assign.bind(window.location):null;
|
|
5858
5898
|
var nativeReplace=window.location.replace?window.location.replace.bind(window.location):null;
|
|
5859
5899
|
function safeNavigate(raw,mode){var abs=toAbsolute(raw);var prox=toProxy(raw);if(!prox){try{console.warn("[conversion-proxy] redirect blocked",{mode:mode,requested:raw,resolved:abs,origin:TARGET_ORIGIN});}catch(_){}return false;}try{console.info("[conversion-proxy] redirect intercepted",{mode:mode,requested:raw,resolved:abs,proxied:prox});if(mode==="replace"&&nativeReplace){nativeReplace(prox);return true;}if(nativeAssign){nativeAssign(prox);return true;}window.location.href=prox;return true;}catch(err){try{console.warn("[conversion-proxy] redirect interception failed",{mode:mode,requested:raw,resolved:abs,proxied:prox,error:err&&err.message?err.message:String(err)});}catch(_){}return false;}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@accelerated-agency/visual-editor",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Conversion visual editor as a reusable React package",
|
|
6
6
|
"type": "module",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"clean": "rm -rf dist",
|
|
27
27
|
"build": "tsup",
|
|
28
28
|
"local:build": "tsup && yarn --cwd ../codebase-server clean && yarn --cwd ../codebase-server dev",
|
|
29
|
-
"watch": "tsup --watch"
|
|
29
|
+
"watch": "tsup --watch",
|
|
30
|
+
"deploy:worker": "wrangler deploy"
|
|
30
31
|
},
|
|
31
32
|
"peerDependencies": {
|
|
32
33
|
"react": ">=18",
|