UNPKG

@getgreenspark/widgets

Version:

An SDK design to help the use of Greenspark's widget API in the browser

66 lines (56 loc) 2.13 kB
import { DEFAULT_CONTAINER_CSS_SELECTOR } from '@/constants' export class DOMInjector { containerSelector: string useShadowDom?: boolean constructor({ containerSelector, useShadowDom = true, }: { containerSelector: string useShadowDom?: boolean }) { this.containerSelector = containerSelector this.useShadowDom = useShadowDom } getWrapper(container: Element): ShadowRoot | Element { if (!this.useShadowDom) { return container } return container.shadowRoot ?? container.attachShadow({ mode: 'open' }) } inject(widget: HTMLElement, containerSelector?: string) { if (!widget) return this.containerSelector = containerSelector ?? this.containerSelector const container = document.querySelector(this.containerSelector) if (!container) { throw new Error( `Greenspark - The document.querySelector('${this.containerSelector}') does not return an Element. Are you sure that you input the correct 'containerSelector'? The default selector is ${DEFAULT_CONTAINER_CSS_SELECTOR}`, ) } container.setAttribute('data-greenspark-shadow-dom-container', 'true') const scripts = [...widget.children].filter((el) => el.tagName === 'SCRIPT') const nonScripts = [...widget.children].filter((el) => el.tagName !== 'SCRIPT') const wrapper = this.getWrapper(container) while (wrapper.firstChild) { wrapper.removeChild(wrapper.firstChild) } wrapper.append(...nonScripts) if (document.readyState === 'complete' || document.readyState === 'interactive') { scripts.forEach((s) => eval(s.innerHTML)) } else { document.addEventListener('DOMContentLoaded', function () { scripts.forEach((s) => eval(s.innerHTML)) }) } } parseHtml(html: string): HTMLElement { const parser = new DOMParser() const parsedWidget = parser.parseFromString(html, 'text/html') if (parsedWidget.body === null) { throw new Error( `Greenspark - An error occurred when trying to execute 'renderToElement'. Failed to render ${html} `, ) } return parsedWidget.body } }