Skip to content

Commit c3105d9

Browse files
committed
Generate scripts and styles dynamically
1 parent 83667e2 commit c3105d9

File tree

4 files changed

+54
-37
lines changed

4 files changed

+54
-37
lines changed

.eslintignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# unconventional js
22
/blueprints/*/files/
3-
/vendor/
43

54
# compiled output
65
/dist/

.prettierignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# unconventional js
22
/blueprints/*/files/
3-
/vendor/
43

54
# compiled output
65
/dist/

lib/process-html.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ const { JSDOM } = require('jsdom');
77

88
const INDEX_FILE = 'index.html';
99

10+
// convert https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap to simple serializable pojo
11+
function convertAttributesToObject(attributes) {
12+
return [...attributes].reduce(
13+
(hash, { name, value }) => ({ [name]: value, ...hash }),
14+
{}
15+
);
16+
}
17+
1018
class ProcessHtmlPlugin extends Plugin {
1119
constructor(input, { appName, rootURL, ui }) {
1220
super([input], {
@@ -45,12 +53,12 @@ class ProcessHtmlPlugin extends Plugin {
4553
return false;
4654
}
4755

48-
const scripts = document.querySelectorAll('script');
49-
const styles = document.querySelectorAll('link[rel="stylesheet"]');
50-
this.references = [...scripts, ...styles];
56+
this.scripts = document.querySelectorAll('script');
57+
this.styles = document.querySelectorAll('link[rel="stylesheet"]');
5158

5259
// Remove all scripts and styles from the final index.html, as those will be loaded form our embed.js script
53-
this.references.forEach((ref) => ref.remove());
60+
this.scripts.forEach((ref) => ref.remove());
61+
this.styles.forEach((ref) => ref.remove());
5462

5563
// insert embed.js
5664
const embedScript = document.createElement('script');
@@ -70,16 +78,26 @@ class ProcessHtmlPlugin extends Plugin {
7078
});
7179

7280
for (const [key, value] of Object.entries(this._dynamicReplacements)) {
81+
js = js.replace(new RegExp(`/${key}/`, 'g'), value);
7382
js = js.replace(new RegExp(key, 'g'), value);
7483
}
7584

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

7988
get _dynamicReplacements() {
89+
const styles = Array.from(this.styles).map((node) =>
90+
convertAttributesToObject(node.attributes)
91+
);
92+
const scripts = Array.from(this.scripts).map((node) =>
93+
convertAttributesToObject(node.attributes)
94+
);
95+
8096
return {
8197
'###APPNAME###': this.appName,
8298
'###CENAME###': this.customElementName,
99+
'###STYLES###': JSON.stringify(styles),
100+
'###SCRIPTS###': JSON.stringify(scripts),
83101
};
84102
}
85103
}

vendor/embed.js

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,45 @@
55
console.debug('[ember-embedded-snippet] %s', msg);
66
}
77

8-
function injectScript(src, head) {
8+
function injectScript(script, head, host) {
99
return new Promise((resolve) => {
1010
let scriptTag = document.createElement('script');
11-
scriptTag.type = 'text/javascript';
12-
scriptTag.src = src;
11+
for (let [name, value] of Object.entries(script)) {
12+
if (name === 'src') {
13+
value = prependHostIfRequired(value, host);
14+
debug('Injecting script: ' + value);
15+
}
16+
scriptTag.setAttribute(name, value);
17+
}
1318
scriptTag.onload = resolve;
14-
debug('Injecting script: ' + src);
1519
head.appendChild(scriptTag);
1620
});
1721
}
1822

19-
async function injectScripts(jsUrls, head) {
20-
for (let src of jsUrls) {
21-
await injectScript(src, head);
23+
async function injectScripts(scripts, head, host) {
24+
for (let script of scripts) {
25+
await injectScript(script, head, host);
2226
}
2327
}
2428

25-
function injectStyles(cssUrls, head) {
26-
cssUrls.forEach((src) => {
27-
let cssSelector = "link[href='" + src + "']";
28-
29-
if (head.querySelector(cssSelector) === null) {
30-
let cssLink = document.createElement('link');
31-
cssLink.setAttribute('rel', 'stylesheet');
32-
cssLink.setAttribute('type', 'text/css');
33-
cssLink.setAttribute('href', src);
34-
debug('Injecting style: ' + src);
35-
head.appendChild(cssLink);
29+
function injectStyles(styles, head, host) {
30+
for (const style of styles) {
31+
let cssSelector = `link[href="${style.href}"]`;
32+
33+
if (head.querySelector(cssSelector) !== null) {
34+
return;
3635
}
37-
});
36+
37+
let cssLink = document.createElement('link');
38+
for (let [name, value] of Object.entries(style)) {
39+
if (name === 'href') {
40+
value = prependHostIfRequired(value, host);
41+
debug('Injecting style: ' + value);
42+
}
43+
cssLink.setAttribute(name, value);
44+
}
45+
head.appendChild(cssLink);
46+
}
3847
}
3948

4049
async function setup(head, host) {
@@ -49,19 +58,11 @@
4958

5059
host = host.replace(/\/$/, '');
5160

52-
let cssUrls = [
53-
prependHostIfRequired('/assets/vendor.css', host),
54-
prependHostIfRequired('/assets/###APPNAME###.css', host),
55-
];
56-
57-
injectStyles(cssUrls, head);
58-
59-
let jsUrls = [
60-
prependHostIfRequired('/assets/vendor.js', host),
61-
prependHostIfRequired('/assets/###APPNAME###.js', host),
62-
];
61+
const styles = /###STYLES###/;
62+
const scripts = /###SCRIPTS###/;
6363

64-
await injectScripts(jsUrls, head);
64+
injectStyles(styles, head, host);
65+
await injectScripts(scripts, head, host);
6566
}
6667

6768
function prependHostIfRequired(url, host) {

0 commit comments

Comments
 (0)