customElements.define( 'x-frame-bypass', class extends HTMLIFrameElement { static get observedAttributes() { return ['src']; } constructor() { super(); } attributeChangedCallback() { this.load(this.src); } connectedCallback() { this.sandbox = '' + this.sandbox || 'allow-forms allow-modals allow-pointer-lock allow-same-origin allow-scripts allow-top-navigation-by-user-activation'; // all except allow-top-navigation } load(url, options) { if (!url || !url.startsWith('http')) throw new Error(`Unable to load src ${url} does not start with http(s)://`); this.srcdoc = `
`; this.fetchProxy(url, options, 0) .then((res) => res.text()) .then((data) => { if (data) this.srcdoc = data.replace( /]*)>/i, ` `, ); }) .catch((e) => console.error('Unable to load proxy iframe service', e)); } fetchProxy(url, options, i) { const proxies = (options || {}).proxies || [ 'https://cors-anywhere.herokuapp.com/', 'https://api.codetabs.com/v1/proxy/?quest=', ]; return fetch(proxies[i] + url, options) .then((res) => { if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); return res; }) .catch((error) => { if (i === proxies.length - 1) throw error; return this.fetchProxy(url, options, i + 1); }); } }, { extends: 'iframe' }, );