mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-12-23 20:03:31 +03:00
150 lines
4.4 KiB
JavaScript
150 lines
4.4 KiB
JavaScript
|
export function setup() {
|
||
|
customElements.define(
|
||
|
"oembed-element",
|
||
|
class extends HTMLElement {
|
||
|
connectedCallback() {
|
||
|
let shadow = this.attachShadow({ mode: "closed" });
|
||
|
const urlAttr = this.getAttribute("url");
|
||
|
if (urlAttr) {
|
||
|
renderOembed(shadow, urlAttr, {
|
||
|
maxwidth: this.getAttribute("maxwidth"),
|
||
|
maxheight: this.getAttribute("maxheight"),
|
||
|
});
|
||
|
} else {
|
||
|
const discoverUrl = this.getAttribute("discover-url");
|
||
|
if (discoverUrl) {
|
||
|
getDiscoverUrl(discoverUrl, function (discoveredUrl) {
|
||
|
if (discoveredUrl) {
|
||
|
renderOembed(shadow, discoveredUrl, null);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {ShadowRoot} shadow
|
||
|
* @param {string} urlToEmbed
|
||
|
* @param {{maxwidth: string?; maxheight: string?}?} options
|
||
|
*/
|
||
|
function renderOembed(shadow, urlToEmbed, options) {
|
||
|
let apiUrlBuilder = new URL(
|
||
|
`https://cors-anywhere.herokuapp.com/${urlToEmbed}`
|
||
|
);
|
||
|
if (options && options.maxwidth) {
|
||
|
apiUrlBuilder.searchParams.set("maxwidth", options.maxwidth);
|
||
|
}
|
||
|
if (options && options.maxheight) {
|
||
|
apiUrlBuilder.searchParams.set("maxheight", options.maxheight);
|
||
|
}
|
||
|
const apiUrl = apiUrlBuilder.toString();
|
||
|
httpGetAsync(apiUrl, (rawResponse) => {
|
||
|
const response = JSON.parse(rawResponse);
|
||
|
|
||
|
switch (response.type) {
|
||
|
case "rich":
|
||
|
tryRenderingHtml(shadow, response);
|
||
|
break;
|
||
|
case "video":
|
||
|
tryRenderingHtml(shadow, response);
|
||
|
break;
|
||
|
case "photo":
|
||
|
let img = document.createElement("img");
|
||
|
img.setAttribute("src", response.url);
|
||
|
if (options) {
|
||
|
img.setAttribute(
|
||
|
"style",
|
||
|
`max-width: ${options.maxwidth}px; max-height: ${options.maxheight}px;`
|
||
|
);
|
||
|
}
|
||
|
shadow.appendChild(img);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {{
|
||
|
height: ?number;
|
||
|
width: ?number;
|
||
|
html: any;
|
||
|
}} response
|
||
|
* @param {ShadowRoot} shadow
|
||
|
*/
|
||
|
function tryRenderingHtml(shadow, response) {
|
||
|
if (response && typeof response.html) {
|
||
|
let iframe = createIframe(response);
|
||
|
shadow.appendChild(iframe);
|
||
|
setTimeout(() => {
|
||
|
let refetchedIframe = shadow.querySelector("iframe");
|
||
|
if (refetchedIframe && !response.height) {
|
||
|
refetchedIframe.setAttribute(
|
||
|
"height",
|
||
|
// @ts-ignore
|
||
|
(iframe.contentWindow.document.body.scrollHeight + 10).toString()
|
||
|
);
|
||
|
}
|
||
|
if (refetchedIframe && !response.width) {
|
||
|
refetchedIframe.setAttribute(
|
||
|
"width",
|
||
|
// @ts-ignore
|
||
|
(iframe.contentWindow.document.body.scrollWidth + 10).toString()
|
||
|
);
|
||
|
}
|
||
|
}, 1000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {{ height: number?; width: number?; html: string; }} response
|
||
|
* @returns {HTMLIFrameElement}
|
||
|
*/
|
||
|
function createIframe(response) {
|
||
|
let iframe = document.createElement("iframe");
|
||
|
iframe.setAttribute("border", "0");
|
||
|
iframe.setAttribute("frameborder", "0");
|
||
|
iframe.setAttribute("height", ((response.height || 500) + 20).toString());
|
||
|
iframe.setAttribute("width", ((response.width || 500) + 20).toString());
|
||
|
iframe.setAttribute("style", "max-width: 100%;");
|
||
|
iframe.srcdoc = response.html;
|
||
|
return iframe;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {string} url
|
||
|
* @param {{ (discoveredUrl: string?): void;}} callback
|
||
|
*/
|
||
|
function getDiscoverUrl(url, callback) {
|
||
|
let apiUrl = new URL(
|
||
|
`https://cors-anywhere.herokuapp.com/${url}`
|
||
|
).toString();
|
||
|
httpGetAsync(apiUrl, function (response) {
|
||
|
let dom = document.createElement("html");
|
||
|
dom.innerHTML = response;
|
||
|
/** @type {HTMLLinkElement | null} */ const oembedTag = dom.querySelector(
|
||
|
'link[type="application/json+oembed"]'
|
||
|
);
|
||
|
callback(oembedTag && oembedTag.href);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {string} theUrl
|
||
|
* @param {{ (rawResponse: string): void }} callback
|
||
|
*/
|
||
|
function httpGetAsync(theUrl, callback) {
|
||
|
var xmlHttp = new XMLHttpRequest();
|
||
|
xmlHttp.onreadystatechange = function () {
|
||
|
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
|
||
|
callback(xmlHttp.responseText);
|
||
|
};
|
||
|
xmlHttp.open("GET", theUrl, true); // true for asynchronous
|
||
|
xmlHttp.send(null);
|
||
|
}
|
||
|
}
|