Skip to content

Commit

Permalink
Generate scripts and styles dynamically
Browse files Browse the repository at this point in the history
  • Loading branch information
simonihmig committed Oct 22, 2021
1 parent 83667e2 commit c3105d9
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 37 deletions.
1 change: 0 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# unconventional js
/blueprints/*/files/
/vendor/

# compiled output
/dist/
Expand Down
1 change: 0 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# unconventional js
/blueprints/*/files/
/vendor/

# compiled output
/dist/
Expand Down
26 changes: 22 additions & 4 deletions lib/process-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -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], {
Expand Down Expand Up @@ -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');
Expand All @@ -70,16 +78,26 @@ 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);
}

fs.writeFileSync(path.join(this.outputPath, 'embed.js'), js);
}

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),
};
}
}
Expand Down
63 changes: 32 additions & 31 deletions vendor/embed.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down

0 comments on commit c3105d9

Please sign in to comment.