diff --git a/.eslintignore b/.eslintignore index 701947e..1a24a64 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,5 @@ # unconventional js /blueprints/*/files/ -/vendor/ # compiled output /dist/ diff --git a/.prettierignore b/.prettierignore index 9221655..c4c3f7e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,5 @@ # unconventional js /blueprints/*/files/ -/vendor/ # compiled output /dist/ diff --git a/lib/process-html.js b/lib/process-html.js index 6506b36..a672832 100644 --- a/lib/process-html.js +++ b/lib/process-html.js @@ -7,6 +7,14 @@ const { JSDOM } = require('jsdom'); const INDEX_FILE = 'index.html'; +// convert https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap to simple serializable pojo +function convertAttributesToObject(attributes) { + return [...attributes].reduce( + (hash, { name, value }) => ({ [name]: value, ...hash }), + {} + ); +} + class ProcessHtmlPlugin extends Plugin { constructor(input, { appName, rootURL, ui }) { super([input], { @@ -45,12 +53,12 @@ class ProcessHtmlPlugin extends Plugin { return false; } - const scripts = document.querySelectorAll('script'); - const styles = document.querySelectorAll('link[rel="stylesheet"]'); - this.references = [...scripts, ...styles]; + this.scripts = document.querySelectorAll('script'); + this.styles = document.querySelectorAll('link[rel="stylesheet"]'); // Remove all scripts and styles from the final index.html, as those will be loaded form our embed.js script - this.references.forEach((ref) => ref.remove()); + this.scripts.forEach((ref) => ref.remove()); + this.styles.forEach((ref) => ref.remove()); // insert embed.js const embedScript = document.createElement('script'); @@ -70,6 +78,7 @@ class ProcessHtmlPlugin extends Plugin { }); for (const [key, value] of Object.entries(this._dynamicReplacements)) { + js = js.replace(new RegExp(`/${key}/`, 'g'), value); js = js.replace(new RegExp(key, 'g'), value); } @@ -77,9 +86,18 @@ class ProcessHtmlPlugin extends Plugin { } get _dynamicReplacements() { + const styles = Array.from(this.styles).map((node) => + convertAttributesToObject(node.attributes) + ); + const scripts = Array.from(this.scripts).map((node) => + convertAttributesToObject(node.attributes) + ); + return { '###APPNAME###': this.appName, '###CENAME###': this.customElementName, + '###STYLES###': JSON.stringify(styles), + '###SCRIPTS###': JSON.stringify(scripts), }; } } diff --git a/vendor/embed.js b/vendor/embed.js index 5df7f22..486da87 100644 --- a/vendor/embed.js +++ b/vendor/embed.js @@ -5,36 +5,45 @@ console.debug('[ember-embedded-snippet] %s', msg); } - function injectScript(src, head) { + function injectScript(script, head, host) { return new Promise((resolve) => { let scriptTag = document.createElement('script'); - scriptTag.type = 'text/javascript'; - scriptTag.src = src; + for (let [name, value] of Object.entries(script)) { + if (name === 'src') { + value = prependHostIfRequired(value, host); + debug('Injecting script: ' + value); + } + scriptTag.setAttribute(name, value); + } scriptTag.onload = resolve; - debug('Injecting script: ' + src); head.appendChild(scriptTag); }); } - async function injectScripts(jsUrls, head) { - for (let src of jsUrls) { - await injectScript(src, head); + async function injectScripts(scripts, head, host) { + for (let script of scripts) { + await injectScript(script, head, host); } } - function injectStyles(cssUrls, head) { - cssUrls.forEach((src) => { - let cssSelector = "link[href='" + src + "']"; - - if (head.querySelector(cssSelector) === null) { - let cssLink = document.createElement('link'); - cssLink.setAttribute('rel', 'stylesheet'); - cssLink.setAttribute('type', 'text/css'); - cssLink.setAttribute('href', src); - debug('Injecting style: ' + src); - head.appendChild(cssLink); + function injectStyles(styles, head, host) { + for (const style of styles) { + let cssSelector = `link[href="${style.href}"]`; + + if (head.querySelector(cssSelector) !== null) { + return; } - }); + + let cssLink = document.createElement('link'); + for (let [name, value] of Object.entries(style)) { + if (name === 'href') { + value = prependHostIfRequired(value, host); + debug('Injecting style: ' + value); + } + cssLink.setAttribute(name, value); + } + head.appendChild(cssLink); + } } async function setup(head, host) { @@ -49,19 +58,11 @@ host = host.replace(/\/$/, ''); - let cssUrls = [ - prependHostIfRequired('/assets/vendor.css', host), - prependHostIfRequired('/assets/###APPNAME###.css', host), - ]; - - injectStyles(cssUrls, head); - - let jsUrls = [ - prependHostIfRequired('/assets/vendor.js', host), - prependHostIfRequired('/assets/###APPNAME###.js', host), - ]; + const styles = /###STYLES###/; + const scripts = /###SCRIPTS###/; - await injectScripts(jsUrls, head); + injectStyles(styles, head, host); + await injectScripts(scripts, head, host); } function prependHostIfRequired(url, host) {