UNPKG

@loomhq/loom-embed

Version:

SDK for easily embedding videos

154 lines (148 loc) 5.88 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); // src/common.ts var LOOM_BASE_REGEX_STR = "(?:https?://)?((?:stage.loom.com|loom.com|www.loom.com|loomlocal.com:4444)/share/([a-zA-Z0-9-]*-)?[a-f0-9]+)(\\?[a-zA-Z0-9=&-_]+)?"; var LOOM_URL_REGEX = new RegExp(`^${LOOM_BASE_REGEX_STR}$`); var LOOM_URL_MATCH_REGEX = new RegExp(`${LOOM_BASE_REGEX_STR}`, "g"); var LOOM_HOSTNAME_CAPTURE = /(www\.loom\.com|loom\.com|stage\.loom\.com|loomlocal\.com:4444)/i; var LINK_REPLACED_CLASS = "lo-link-replaced"; // src/validate.ts var isLoomUrl = (url) => LOOM_URL_REGEX.test(url); var isValidEmbedUrl = (url) => isLoomUrl(url); var isValidLinkNode = (node) => !node.className.includes(LINK_REPLACED_CLASS) && isValidEmbedUrl(node.href); var validate_default = { isLoomUrl }; // src/oembed.ts var SRC_URL_REGEX = /src=["']+(https?:\/\/[a-zA-z\d:./?&]+)/; var getResponsiveEmbedCode = (embedURL, heightAspectRatio) => { const padding = `${heightAspectRatio * 100}%`; const wrapperStyles = `position: relative; padding-bottom: ${padding}; height: 0;`; const iframeStyles = "position: absolute; top: 0; left: 0; width: 100%; height: 100%;"; const staticAttributes = 'frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen'; return ` <div class="lo-emb-vid" style="${wrapperStyles}"> <iframe src="${embedURL}" style="${iframeStyles}" ${staticAttributes}></iframe> </div>`.split("\n").map((s) => s.trim()).join(""); }; var chooseAspectRatio = (data) => { const { width, height } = data; if (width == null || height == null) { return 1080 / 1920; } return height / width; }; var enhanceEmbedCode = (videoData, options) => { const { width, height } = options; if (!width && !height) { const [, embedUrl] = videoData.html.match(SRC_URL_REGEX); const aspectRatio = chooseAspectRatio(videoData); return __spreadProps(__spreadValues({}, videoData), { html: getResponsiveEmbedCode(embedUrl, aspectRatio) }); } return videoData; }; var buildLoomOembedUrl = (url, options) => { const { width, height, gifThumbnail, hideOwner } = options; const maxWidth = width ? `&maxwidth=${width}` : ""; const maxHeight = height ? `&maxheight=${height}` : ""; const gifParam = gifThumbnail ? `&gif=${gifThumbnail}` : ""; const ownerParam = hideOwner ? `&hide_owner=${hideOwner}` : ""; const [loomDomain] = url.match(LOOM_HOSTNAME_CAPTURE); let loomBaseDomain = loomDomain; if (loomDomain === "loom.com") { loomBaseDomain = `www.${loomDomain}`; } return `https://${loomBaseDomain}/v1/oembed?url=${url}${maxWidth}${maxHeight}${gifParam}${ownerParam}`; }; var oembed = (linkUrl, options = {}) => { const isSupportedUrl = isValidEmbedUrl(linkUrl); if (isSupportedUrl) { return fetch(buildLoomOembedUrl(linkUrl, options)).then((resp) => resp.json()).then((videoData) => enhanceEmbedCode(videoData, options)).catch((e) => { throw new Error("Unable to fetch oembed data:" + e); }); } throw new Error("URL is not from a supported video provider"); }; var gifEmbed = async (linkUrl) => { const oEmbed = await oembed(linkUrl, { gifThumbnail: true }); return `<a href="${linkUrl}"> <img style="max-width:300px;" src="${oEmbed.thumbnail_url}"> </a>`; }; // src/linkReplace.ts var createNodeFromString = (htmlString) => { const containerNode = document.createElement("div"); containerNode.innerHTML = htmlString; return containerNode.firstChild; }; var injectVideo = (linkNode, embedString) => { const embedNode = createNodeFromString(embedString); if (embedNode && linkNode.parentNode) { linkNode.parentNode.insertBefore(embedNode, linkNode); } }; var linkReplace = (selector = "a", options = {}, target = document) => { const linkNodes = [ ...Array.from(target.querySelectorAll(selector)) ]; linkNodes.filter((item) => isValidLinkNode(item)).forEach(async (node) => { const { html } = await oembed(node.href, options); injectVideo(node, html); node.className = `${node.className} ${LINK_REPLACED_CLASS}`; return true; }); }; // src/textReplace.ts var normalizeUrls = (url) => { const [, loomBaseUrl] = url.match(LOOM_URL_REGEX); return { originalUrl: url, requestUrl: `https://${loomBaseUrl}` }; }; var textReplace = async (textString, options = {}) => { const textInput = textString || ""; const loomMatches = textInput.match(LOOM_URL_MATCH_REGEX); if (!loomMatches) { return textInput; } const embedPromises = loomMatches.map(normalizeUrls).map(async (urls) => { const { html } = await oembed(urls.requestUrl, options); return __spreadProps(__spreadValues({}, urls), { embedCode: html }); }); const embedData = await Promise.all(embedPromises); return embedData.reduce((acc, curr) => { const { originalUrl, embedCode } = curr; const urlReplaceRegex = new RegExp(originalUrl, "g"); return acc.replace(urlReplaceRegex, embedCode); }, textInput); }; export { gifEmbed, linkReplace, oembed, textReplace, validate_default as validate }; //# sourceMappingURL=index.js.map