@accelerated-agency/visual-editor 0.1.9 → 0.2.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/index.js CHANGED
@@ -1832,8 +1832,10 @@ function ElementIcon({ tag }) {
1832
1832
  return /* @__PURE__ */ jsx("span", { className: "shrink-0 w-5 h-5 rounded flex items-center justify-center", style: { backgroundColor: bgColor }, children: /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx("rect", { x: "1.5", y: "1.5", width: "9", height: "9", rx: "1.5", stroke: iconColor, strokeWidth: "1.2" }) }) });
1833
1833
  }
1834
1834
  var CHANNEL = "conversion-editor";
1835
+ var IFRAME_LOAD_GUARD_MS = 13e4;
1835
1836
  function IframeCanvas({ url, password, proxyBaseUrl = "", onBridgeReady, onPong }) {
1836
1837
  const iframeElRef = useRef(null);
1838
+ const loadGuardRef = useRef(null);
1837
1839
  const setSelectedElement = useMutationsStore((s) => s.setSelectedElement);
1838
1840
  const addMutationToActive = useVariationsStore((s) => s.addMutationToActive);
1839
1841
  const [loading, setLoading] = useState(false);
@@ -1876,13 +1878,29 @@ function IframeCanvas({ url, password, proxyBaseUrl = "", onBridgeReady, onPong
1876
1878
  return () => window.removeEventListener("message", handleMessage);
1877
1879
  }, [handleMessage]);
1878
1880
  useEffect(() => {
1879
- if (url) setLoading(true);
1881
+ if (!url) return;
1882
+ setLoading(true);
1883
+ if (loadGuardRef.current) clearTimeout(loadGuardRef.current);
1884
+ loadGuardRef.current = setTimeout(() => {
1885
+ loadGuardRef.current = null;
1886
+ setLoading(false);
1887
+ }, IFRAME_LOAD_GUARD_MS);
1888
+ return () => {
1889
+ if (loadGuardRef.current) clearTimeout(loadGuardRef.current);
1890
+ };
1880
1891
  }, [url]);
1892
+ const clearLoadGuard = useCallback(() => {
1893
+ if (loadGuardRef.current) {
1894
+ clearTimeout(loadGuardRef.current);
1895
+ loadGuardRef.current = null;
1896
+ }
1897
+ setLoading(false);
1898
+ }, []);
1881
1899
  let resolvedUrl;
1882
1900
  if (url.toLowerCase() === "test") {
1883
1901
  resolvedUrl = "/test";
1884
1902
  } else if (url.startsWith("http")) {
1885
- resolvedUrl = `${proxyBaseUrl}/api/proxy?password=${encodeURIComponent(password || "")}&url=${encodeURIComponent(url)}`;
1903
+ resolvedUrl = `${proxyBaseUrl}/api/conversion-proxy?password=${encodeURIComponent(password || "")}&url=${encodeURIComponent(url)}`;
1886
1904
  } else {
1887
1905
  resolvedUrl = url;
1888
1906
  }
@@ -1908,7 +1926,8 @@ function IframeCanvas({ url, password, proxyBaseUrl = "", onBridgeReady, onPong
1908
1926
  src: resolvedUrl,
1909
1927
  className: "w-full h-full border-0",
1910
1928
  sandbox: "allow-scripts allow-same-origin allow-forms allow-popups",
1911
- onLoad: () => setLoading(false)
1929
+ onLoad: clearLoadGuard,
1930
+ onError: clearLoadGuard
1912
1931
  }
1913
1932
  )
1914
1933
  ] });
package/dist/vite.cjs CHANGED
@@ -1021,7 +1021,7 @@ function handleLoadExperiment(data) {
1021
1021
  var urlBar = document.getElementById('url-bar');
1022
1022
  urlBar.textContent = pageUrl;
1023
1023
  urlBar.title = pageUrl;
1024
- var proxyUrl = '/api/proxy?password=' + encodeURIComponent(data.editorPassword || '') +
1024
+ var proxyUrl = '/api/conversion-proxy?password=' + encodeURIComponent(data.editorPassword || '') +
1025
1025
  '&url=' + encodeURIComponent(pageUrl);
1026
1026
  loadPage(proxyUrl);
1027
1027
  }
@@ -1800,7 +1800,7 @@ function createVisualEditorMiddleware(options) {
1800
1800
  }
1801
1801
  }
1802
1802
  return async (req, res, next) => {
1803
- const pathname = (req.url || "").split("?")[0];
1803
+ let pathname = (req.url || "").split("?")[0];
1804
1804
  if (pathname === "/bridge.js") {
1805
1805
  res.removeHeader("X-Frame-Options");
1806
1806
  res.setHeader("Content-Type", "application/javascript; charset=utf-8");
@@ -1919,8 +1919,8 @@ function createVisualEditorMiddleware(options) {
1919
1919
  }
1920
1920
  return;
1921
1921
  }
1922
- const isRootProxyPath = pathname === "/api/proxy" || pathname.startsWith("/api/proxy/");
1923
- if (!isRootProxyPath && pathname.includes("api/proxy")) {
1922
+ const isRootProxyPath = pathname === "/api/conversion-proxy" || pathname.startsWith("/api/conversion-proxy/");
1923
+ if (!isRootProxyPath && pathname.includes("api/conversion-proxy")) {
1924
1924
  if ((req.method || "GET").toUpperCase() === "OPTIONS") {
1925
1925
  res.statusCode = 204;
1926
1926
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -1937,6 +1937,10 @@ function createVisualEditorMiddleware(options) {
1937
1937
  return;
1938
1938
  }
1939
1939
  if (pathname.startsWith("/api/proxy")) {
1940
+ req.url = (req.url || "").replace("/api/proxy", "/api/conversion-proxy");
1941
+ pathname = (req.url || "").split("?")[0];
1942
+ }
1943
+ if (pathname.startsWith("/api/conversion-proxy")) {
1940
1944
  try {
1941
1945
  const url = new URL(req.url || "", "http://localhost");
1942
1946
  const targetUrl = url.searchParams.get("url");
@@ -1997,17 +2001,39 @@ function createVisualEditorMiddleware(options) {
1997
2001
  }
1998
2002
  if (chunks.length > 0) requestBody = Buffer.concat(chunks);
1999
2003
  }
2000
- const upstream = await fetch(targetUrl, {
2001
- method,
2002
- headers: fetchHeaders,
2003
- body: requestBody ? Buffer.from(requestBody) : null,
2004
- redirect: "follow"
2005
- });
2004
+ const upstreamTimeoutMs = 12e4;
2005
+ const ac = new AbortController();
2006
+ const timeoutId = setTimeout(() => ac.abort(), upstreamTimeoutMs);
2007
+ let upstream;
2008
+ try {
2009
+ upstream = await fetch(targetUrl, {
2010
+ method,
2011
+ headers: fetchHeaders,
2012
+ body: requestBody ? Buffer.from(requestBody) : null,
2013
+ redirect: "follow",
2014
+ signal: ac.signal
2015
+ });
2016
+ } catch (fetchErr) {
2017
+ clearTimeout(timeoutId);
2018
+ const aborted = fetchErr?.name === "AbortError";
2019
+ res.statusCode = aborted ? 504 : 502;
2020
+ res.setHeader("Content-Type", "application/json");
2021
+ res.end(
2022
+ JSON.stringify({
2023
+ error: aborted ? `Upstream request timed out after ${upstreamTimeoutMs / 1e3}s` : fetchErr?.message || "Upstream fetch failed"
2024
+ })
2025
+ );
2026
+ return;
2027
+ }
2028
+ clearTimeout(timeoutId);
2006
2029
  const responseContentType = upstream.headers.get("content-type") || "";
2007
2030
  const isHtmlResponse = responseContentType.includes("text/html");
2031
+ const secFetchMode = (req.headers?.["sec-fetch-mode"] || "").toLowerCase();
2008
2032
  const secFetchDest = (req.headers?.["sec-fetch-dest"] || "").toLowerCase();
2009
- const isNavigationRequest = secFetchDest === "iframe" || secFetchDest === "document" || secFetchDest === "";
2010
- if (!isHtmlResponse || !isNavigationRequest) {
2033
+ const isLikelyDocumentNavigation = secFetchMode === "navigate" || secFetchDest === "iframe" || secFetchDest === "document" || secFetchDest === "nested-document" || secFetchDest === "frame";
2034
+ const isLikelyFetchOrXHR = secFetchDest === "empty" && (secFetchMode === "cors" || secFetchMode === "same-origin" || secFetchMode === "no-cors");
2035
+ const shouldInjectHtmlBridge = isHtmlResponse && (isLikelyDocumentNavigation || !isLikelyFetchOrXHR);
2036
+ if (!isHtmlResponse || !shouldInjectHtmlBridge) {
2011
2037
  const binary = Buffer.from(await upstream.arrayBuffer());
2012
2038
  res.statusCode = upstream.status;
2013
2039
  if (responseContentType) {
@@ -2025,7 +2051,7 @@ function createVisualEditorMiddleware(options) {
2025
2051
  }
2026
2052
  html = html.replace(/(href|src|action)="\/(?!\/)/g, `$1="${origin}/`);
2027
2053
  const escapedOrigin = origin.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2028
- const proxyBase = `/api/proxy?password=${encodeURIComponent(password)}&url=`;
2054
+ const proxyBase = `/api/conversion-proxy?password=${encodeURIComponent(password)}&url=`;
2029
2055
  html = html.replace(
2030
2056
  new RegExp(`(href|action)="${escapedOrigin}(/[^"]*)"`, "g"),
2031
2057
  (match, attr, urlPath) => {
@@ -2040,7 +2066,7 @@ function createVisualEditorMiddleware(options) {
2040
2066
  html = html.replace("</head>", `${popupHideCss}
2041
2067
  </head>`);
2042
2068
  }
2043
- const runtimeProxyScript = `<script>(function(){try{var TARGET_ORIGIN=${JSON.stringify(origin)};var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};var EMPTY_JSON_DATA="data:application/json;charset=utf-8,%7B%7D";function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#")||raw.startsWith("http")||raw.startsWith("//");}function toAbsoluteOriginUrl(raw){if(isSkippable(raw))return raw;try{var base=raw.startsWith("/")?TARGET_ORIGIN:TARGET_PAGE_URL;var abs=new URL(raw,base);if(abs.origin!==TARGET_ORIGIN)return raw;return abs.toString();}catch(_){return raw;}}function resolveUrl(s){try{return new URL(s,window.location.href);}catch(_){return null;}}function isNestedMalformedProxy(u){if(!u)return false;var p=u.pathname||"";if(p==="/api/proxy"||p.indexOf("/api/proxy/")===0)return false;return p.indexOf("api/proxy")!==-1;}function skipNestedProxyNetwork(s){var u=typeof s==="string"?resolveUrl(s):null;return u&&isNestedMalformedProxy(u);}function emptyJsonFetchResponse(){return Promise.resolve(new Response("{}",{status:200,headers:{"Content-Type":"application/json; charset=utf-8"}}));}if(window.fetch){var _fetch=window.fetch.bind(window);window.fetch=function(input,init){try{var rawUrl=typeof input==="string"?input:(input&&input.url?String(input.url):"");if(rawUrl&&skipNestedProxyNetwork(rawUrl))return emptyJsonFetchResponse();if(typeof input==="string"){input=toAbsoluteOriginUrl(input);}else if(input&&input.url){var next=toAbsoluteOriginUrl(input.url);if(next!==input.url){input=new Request(next,input);}}var after=typeof input==="string"?input:(input&&input.url?String(input.url):"");if(after&&skipNestedProxyNetwork(after))return emptyJsonFetchResponse();}catch(_){}return _fetch(input,init);};}if(window.XMLHttpRequest&&window.XMLHttpRequest.prototype&&window.XMLHttpRequest.prototype.open){var _open=window.XMLHttpRequest.prototype.open;window.XMLHttpRequest.prototype.open=function(method,url){try{var u=resolveUrl(String(url));if(u&&isNestedMalformedProxy(u)){arguments[1]=EMPTY_JSON_DATA;}else{arguments[1]=toAbsoluteOriginUrl(url);}}catch(_){}return _open.apply(this,arguments);};}if(window.navigator&&window.navigator.serviceWorker&&typeof window.navigator.serviceWorker.register==="function"){window.navigator.serviceWorker.register=function(){return Promise.resolve({scope:"disabled-in-editor-proxy"});};}}catch(_){}})();</script>`;
2069
+ const runtimeProxyScript = `<script>(function(){try{var TARGET_ORIGIN=${JSON.stringify(origin)};var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};var EMPTY_JSON_DATA="data:application/json;charset=utf-8,%7B%7D";function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#")||raw.startsWith("http")||raw.startsWith("//");}function toAbsoluteOriginUrl(raw){if(isSkippable(raw))return raw;try{var base=raw.startsWith("/")?TARGET_ORIGIN:TARGET_PAGE_URL;var abs=new URL(raw,base);if(abs.origin!==TARGET_ORIGIN)return raw;return abs.toString();}catch(_){return raw;}}function resolveUrl(s){try{return new URL(s,window.location.href);}catch(_){return null;}}function isNestedMalformedProxy(u){if(!u)return false;var p=u.pathname||"";if(p==="/api/conversion-proxy"||p.indexOf("/api/conversion-proxy/")===0)return false;return p.indexOf("api/conversion-proxy")!==-1;}function skipNestedProxyNetwork(s){var u=typeof s==="string"?resolveUrl(s):null;return u&&isNestedMalformedProxy(u);}function emptyJsonFetchResponse(){return Promise.resolve(new Response("{}",{status:200,headers:{"Content-Type":"application/json; charset=utf-8"}}));}if(window.fetch){var _fetch=window.fetch.bind(window);window.fetch=function(input,init){try{var rawUrl=typeof input==="string"?input:(input&&input.url?String(input.url):"");if(rawUrl&&skipNestedProxyNetwork(rawUrl))return emptyJsonFetchResponse();if(typeof input==="string"){input=toAbsoluteOriginUrl(input);}else if(input&&input.url){var next=toAbsoluteOriginUrl(input.url);if(next!==input.url){input=new Request(next,input);}}var after=typeof input==="string"?input:(input&&input.url?String(input.url):"");if(after&&skipNestedProxyNetwork(after))return emptyJsonFetchResponse();}catch(_){}return _fetch(input,init);};}if(window.XMLHttpRequest&&window.XMLHttpRequest.prototype&&window.XMLHttpRequest.prototype.open){var _open=window.XMLHttpRequest.prototype.open;window.XMLHttpRequest.prototype.open=function(method,url){try{var u=resolveUrl(String(url));if(u&&isNestedMalformedProxy(u)){arguments[1]=EMPTY_JSON_DATA;}else{arguments[1]=toAbsoluteOriginUrl(url);}}catch(_){}return _open.apply(this,arguments);};}if(window.navigator&&typeof window.navigator.sendBeacon==="function"){var _beacon=window.navigator.sendBeacon.bind(window.navigator);window.navigator.sendBeacon=function(url,data){try{if(skipNestedProxyNetwork(String(url)))return true;}catch(_){}return _beacon(url,data);};}if(window.navigator&&window.navigator.serviceWorker&&typeof window.navigator.serviceWorker.register==="function"){window.navigator.serviceWorker.register=function(){return Promise.resolve({scope:"disabled-in-editor-proxy"});};}}catch(_){}})();</script>`;
2044
2070
  if (html.includes("</head>")) {
2045
2071
  html = html.replace("</head>", `${runtimeProxyScript}
2046
2072
  </head>`);
package/dist/vite.js CHANGED
@@ -1013,7 +1013,7 @@ function handleLoadExperiment(data) {
1013
1013
  var urlBar = document.getElementById('url-bar');
1014
1014
  urlBar.textContent = pageUrl;
1015
1015
  urlBar.title = pageUrl;
1016
- var proxyUrl = '/api/proxy?password=' + encodeURIComponent(data.editorPassword || '') +
1016
+ var proxyUrl = '/api/conversion-proxy?password=' + encodeURIComponent(data.editorPassword || '') +
1017
1017
  '&url=' + encodeURIComponent(pageUrl);
1018
1018
  loadPage(proxyUrl);
1019
1019
  }
@@ -1792,7 +1792,7 @@ function createVisualEditorMiddleware(options) {
1792
1792
  }
1793
1793
  }
1794
1794
  return async (req, res, next) => {
1795
- const pathname = (req.url || "").split("?")[0];
1795
+ let pathname = (req.url || "").split("?")[0];
1796
1796
  if (pathname === "/bridge.js") {
1797
1797
  res.removeHeader("X-Frame-Options");
1798
1798
  res.setHeader("Content-Type", "application/javascript; charset=utf-8");
@@ -1911,8 +1911,8 @@ function createVisualEditorMiddleware(options) {
1911
1911
  }
1912
1912
  return;
1913
1913
  }
1914
- const isRootProxyPath = pathname === "/api/proxy" || pathname.startsWith("/api/proxy/");
1915
- if (!isRootProxyPath && pathname.includes("api/proxy")) {
1914
+ const isRootProxyPath = pathname === "/api/conversion-proxy" || pathname.startsWith("/api/conversion-proxy/");
1915
+ if (!isRootProxyPath && pathname.includes("api/conversion-proxy")) {
1916
1916
  if ((req.method || "GET").toUpperCase() === "OPTIONS") {
1917
1917
  res.statusCode = 204;
1918
1918
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -1929,6 +1929,10 @@ function createVisualEditorMiddleware(options) {
1929
1929
  return;
1930
1930
  }
1931
1931
  if (pathname.startsWith("/api/proxy")) {
1932
+ req.url = (req.url || "").replace("/api/proxy", "/api/conversion-proxy");
1933
+ pathname = (req.url || "").split("?")[0];
1934
+ }
1935
+ if (pathname.startsWith("/api/conversion-proxy")) {
1932
1936
  try {
1933
1937
  const url = new URL(req.url || "", "http://localhost");
1934
1938
  const targetUrl = url.searchParams.get("url");
@@ -1989,17 +1993,39 @@ function createVisualEditorMiddleware(options) {
1989
1993
  }
1990
1994
  if (chunks.length > 0) requestBody = Buffer.concat(chunks);
1991
1995
  }
1992
- const upstream = await fetch(targetUrl, {
1993
- method,
1994
- headers: fetchHeaders,
1995
- body: requestBody ? Buffer.from(requestBody) : null,
1996
- redirect: "follow"
1997
- });
1996
+ const upstreamTimeoutMs = 12e4;
1997
+ const ac = new AbortController();
1998
+ const timeoutId = setTimeout(() => ac.abort(), upstreamTimeoutMs);
1999
+ let upstream;
2000
+ try {
2001
+ upstream = await fetch(targetUrl, {
2002
+ method,
2003
+ headers: fetchHeaders,
2004
+ body: requestBody ? Buffer.from(requestBody) : null,
2005
+ redirect: "follow",
2006
+ signal: ac.signal
2007
+ });
2008
+ } catch (fetchErr) {
2009
+ clearTimeout(timeoutId);
2010
+ const aborted = fetchErr?.name === "AbortError";
2011
+ res.statusCode = aborted ? 504 : 502;
2012
+ res.setHeader("Content-Type", "application/json");
2013
+ res.end(
2014
+ JSON.stringify({
2015
+ error: aborted ? `Upstream request timed out after ${upstreamTimeoutMs / 1e3}s` : fetchErr?.message || "Upstream fetch failed"
2016
+ })
2017
+ );
2018
+ return;
2019
+ }
2020
+ clearTimeout(timeoutId);
1998
2021
  const responseContentType = upstream.headers.get("content-type") || "";
1999
2022
  const isHtmlResponse = responseContentType.includes("text/html");
2023
+ const secFetchMode = (req.headers?.["sec-fetch-mode"] || "").toLowerCase();
2000
2024
  const secFetchDest = (req.headers?.["sec-fetch-dest"] || "").toLowerCase();
2001
- const isNavigationRequest = secFetchDest === "iframe" || secFetchDest === "document" || secFetchDest === "";
2002
- if (!isHtmlResponse || !isNavigationRequest) {
2025
+ const isLikelyDocumentNavigation = secFetchMode === "navigate" || secFetchDest === "iframe" || secFetchDest === "document" || secFetchDest === "nested-document" || secFetchDest === "frame";
2026
+ const isLikelyFetchOrXHR = secFetchDest === "empty" && (secFetchMode === "cors" || secFetchMode === "same-origin" || secFetchMode === "no-cors");
2027
+ const shouldInjectHtmlBridge = isHtmlResponse && (isLikelyDocumentNavigation || !isLikelyFetchOrXHR);
2028
+ if (!isHtmlResponse || !shouldInjectHtmlBridge) {
2003
2029
  const binary = Buffer.from(await upstream.arrayBuffer());
2004
2030
  res.statusCode = upstream.status;
2005
2031
  if (responseContentType) {
@@ -2017,7 +2043,7 @@ function createVisualEditorMiddleware(options) {
2017
2043
  }
2018
2044
  html = html.replace(/(href|src|action)="\/(?!\/)/g, `$1="${origin}/`);
2019
2045
  const escapedOrigin = origin.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2020
- const proxyBase = `/api/proxy?password=${encodeURIComponent(password)}&url=`;
2046
+ const proxyBase = `/api/conversion-proxy?password=${encodeURIComponent(password)}&url=`;
2021
2047
  html = html.replace(
2022
2048
  new RegExp(`(href|action)="${escapedOrigin}(/[^"]*)"`, "g"),
2023
2049
  (match, attr, urlPath) => {
@@ -2032,7 +2058,7 @@ function createVisualEditorMiddleware(options) {
2032
2058
  html = html.replace("</head>", `${popupHideCss}
2033
2059
  </head>`);
2034
2060
  }
2035
- const runtimeProxyScript = `<script>(function(){try{var TARGET_ORIGIN=${JSON.stringify(origin)};var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};var EMPTY_JSON_DATA="data:application/json;charset=utf-8,%7B%7D";function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#")||raw.startsWith("http")||raw.startsWith("//");}function toAbsoluteOriginUrl(raw){if(isSkippable(raw))return raw;try{var base=raw.startsWith("/")?TARGET_ORIGIN:TARGET_PAGE_URL;var abs=new URL(raw,base);if(abs.origin!==TARGET_ORIGIN)return raw;return abs.toString();}catch(_){return raw;}}function resolveUrl(s){try{return new URL(s,window.location.href);}catch(_){return null;}}function isNestedMalformedProxy(u){if(!u)return false;var p=u.pathname||"";if(p==="/api/proxy"||p.indexOf("/api/proxy/")===0)return false;return p.indexOf("api/proxy")!==-1;}function skipNestedProxyNetwork(s){var u=typeof s==="string"?resolveUrl(s):null;return u&&isNestedMalformedProxy(u);}function emptyJsonFetchResponse(){return Promise.resolve(new Response("{}",{status:200,headers:{"Content-Type":"application/json; charset=utf-8"}}));}if(window.fetch){var _fetch=window.fetch.bind(window);window.fetch=function(input,init){try{var rawUrl=typeof input==="string"?input:(input&&input.url?String(input.url):"");if(rawUrl&&skipNestedProxyNetwork(rawUrl))return emptyJsonFetchResponse();if(typeof input==="string"){input=toAbsoluteOriginUrl(input);}else if(input&&input.url){var next=toAbsoluteOriginUrl(input.url);if(next!==input.url){input=new Request(next,input);}}var after=typeof input==="string"?input:(input&&input.url?String(input.url):"");if(after&&skipNestedProxyNetwork(after))return emptyJsonFetchResponse();}catch(_){}return _fetch(input,init);};}if(window.XMLHttpRequest&&window.XMLHttpRequest.prototype&&window.XMLHttpRequest.prototype.open){var _open=window.XMLHttpRequest.prototype.open;window.XMLHttpRequest.prototype.open=function(method,url){try{var u=resolveUrl(String(url));if(u&&isNestedMalformedProxy(u)){arguments[1]=EMPTY_JSON_DATA;}else{arguments[1]=toAbsoluteOriginUrl(url);}}catch(_){}return _open.apply(this,arguments);};}if(window.navigator&&window.navigator.serviceWorker&&typeof window.navigator.serviceWorker.register==="function"){window.navigator.serviceWorker.register=function(){return Promise.resolve({scope:"disabled-in-editor-proxy"});};}}catch(_){}})();</script>`;
2061
+ const runtimeProxyScript = `<script>(function(){try{var TARGET_ORIGIN=${JSON.stringify(origin)};var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};var EMPTY_JSON_DATA="data:application/json;charset=utf-8,%7B%7D";function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#")||raw.startsWith("http")||raw.startsWith("//");}function toAbsoluteOriginUrl(raw){if(isSkippable(raw))return raw;try{var base=raw.startsWith("/")?TARGET_ORIGIN:TARGET_PAGE_URL;var abs=new URL(raw,base);if(abs.origin!==TARGET_ORIGIN)return raw;return abs.toString();}catch(_){return raw;}}function resolveUrl(s){try{return new URL(s,window.location.href);}catch(_){return null;}}function isNestedMalformedProxy(u){if(!u)return false;var p=u.pathname||"";if(p==="/api/conversion-proxy"||p.indexOf("/api/conversion-proxy/")===0)return false;return p.indexOf("api/conversion-proxy")!==-1;}function skipNestedProxyNetwork(s){var u=typeof s==="string"?resolveUrl(s):null;return u&&isNestedMalformedProxy(u);}function emptyJsonFetchResponse(){return Promise.resolve(new Response("{}",{status:200,headers:{"Content-Type":"application/json; charset=utf-8"}}));}if(window.fetch){var _fetch=window.fetch.bind(window);window.fetch=function(input,init){try{var rawUrl=typeof input==="string"?input:(input&&input.url?String(input.url):"");if(rawUrl&&skipNestedProxyNetwork(rawUrl))return emptyJsonFetchResponse();if(typeof input==="string"){input=toAbsoluteOriginUrl(input);}else if(input&&input.url){var next=toAbsoluteOriginUrl(input.url);if(next!==input.url){input=new Request(next,input);}}var after=typeof input==="string"?input:(input&&input.url?String(input.url):"");if(after&&skipNestedProxyNetwork(after))return emptyJsonFetchResponse();}catch(_){}return _fetch(input,init);};}if(window.XMLHttpRequest&&window.XMLHttpRequest.prototype&&window.XMLHttpRequest.prototype.open){var _open=window.XMLHttpRequest.prototype.open;window.XMLHttpRequest.prototype.open=function(method,url){try{var u=resolveUrl(String(url));if(u&&isNestedMalformedProxy(u)){arguments[1]=EMPTY_JSON_DATA;}else{arguments[1]=toAbsoluteOriginUrl(url);}}catch(_){}return _open.apply(this,arguments);};}if(window.navigator&&typeof window.navigator.sendBeacon==="function"){var _beacon=window.navigator.sendBeacon.bind(window.navigator);window.navigator.sendBeacon=function(url,data){try{if(skipNestedProxyNetwork(String(url)))return true;}catch(_){}return _beacon(url,data);};}if(window.navigator&&window.navigator.serviceWorker&&typeof window.navigator.serviceWorker.register==="function"){window.navigator.serviceWorker.register=function(){return Promise.resolve({scope:"disabled-in-editor-proxy"});};}}catch(_){}})();</script>`;
2036
2062
  if (html.includes("</head>")) {
2037
2063
  html = html.replace("</head>", `${runtimeProxyScript}
2038
2064
  </head>`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@accelerated-agency/visual-editor",
3
- "version": "0.1.9",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
5
  "description": "Conversion visual editor as a reusable React package",
6
6
  "type": "module",