-
Notifications
You must be signed in to change notification settings - Fork 159
Expand file tree
/
Copy pathhtml-entrypoint.js
More file actions
93 lines (81 loc) · 2.93 KB
/
html-entrypoint.js
File metadata and controls
93 lines (81 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
'use strict';
const { JSDOM } = require('jsdom');
const fs = require('fs');
const path = require('path');
function htmlEntrypoint(appName, distPath, htmlPath) {
let html = fs.readFileSync(path.join(distPath, htmlPath), 'utf8');
let dom = new JSDOM(html);
let scripts = [];
let config = {};
for (let element of dom.window.document.querySelectorAll('meta')) {
let name = element.getAttribute('name');
if (name && name.endsWith('/config/environment')) {
let content = JSON.parse(decodeURIComponent(element.getAttribute('content')));
content.APP = Object.assign({ autoboot: false }, content.APP);
config[name.slice(0, -1 * '/config/environment'.length)] = content;
}
}
let rootURL = getRootURL(appName, config);
for (let element of dom.window.document.querySelectorAll('script,fastboot-script')) {
let src = extractSrc(element);
if (!extractIgnore(element)) {
let relativeSrc = urlWithin(src, rootURL);
if (relativeSrc) {
scripts.push(path.join(distPath, relativeSrc));
} else if (element.tagName === 'FASTBOOT-SCRIPT') {
scripts.push(path.join(distPath, src));
}
}
if (element.tagName === 'FASTBOOT-SCRIPT') {
removeWithWhitespaceTrim(element);
}
}
return { config, html: dom.serialize(), scripts };
}
function extractSrc(element) {
if (element.hasAttribute('data-fastboot-src')) {
let src = element.getAttribute('data-fastboot-src');
element.removeAttribute('data-fastboot-src');
return src;
} else {
return element.getAttribute('src');
}
}
function extractIgnore(element) {
if (element.hasAttribute('data-fastboot-ignore')) {
element.removeAttribute('data-fastboot-ignore');
return true;
}
return false;
}
function getRootURL(appName, config) {
let rootURL = (config[appName] && config[appName].rootURL) || '/';
if (!rootURL.endsWith('/')) {
rootURL = rootURL + '/';
}
return rootURL;
}
function urlWithin(candidate, root) {
let candidateURL = new URL(candidate, 'http://_the_current_origin_');
let rootURL = new URL(root, 'http://_the_current_origin_');
if (candidateURL.href.startsWith(rootURL.href)) {
return candidateURL.href.slice(rootURL.href.length);
}
}
// removes an element, and if that element was on a line by itself with nothing
// but whitespace, removes the whole line. The extra whitespace would otherwise
// be harmless but ugly.
function removeWithWhitespaceTrim(element) {
let prev = element.previousSibling;
let next = element.nextSibling;
if (prev && next && prev.nodeType == prev.TEXT_NODE && next.nodeType === next.TEXT_NODE) {
let prevMatch = prev.textContent.match(/\n\s*$/);
let nextMatch = next.textContent.match(/^(\s*\n)/);
if (prevMatch && nextMatch) {
prev.textContent = prev.textContent.slice(0, prevMatch.index + 1);
next.textContent = next.textContent.slice(nextMatch[0].length);
}
}
element.remove();
}
module.exports = htmlEntrypoint;