-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinclude.js
84 lines (66 loc) · 2.58 KB
/
include.js
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
// This Alpine plugin adds the x-include directive that enables
// including an Alpine "component" in an HTML file that uses Alpine.
// See the README file for details.
const { href } = location;
const lastSlashIndex = href.lastIndexOf("/");
const urlPrefix = href.substring(0, lastSlashIndex + 1);
const scriptStart = "<script>";
const scriptEnd = "</script>";
const _alpineIncludeCache = {};
function includeHTML() {
const attribute = "x-include";
// Find the first element that contains the include attribute.
const element = document.querySelector(`[${attribute}]`);
if (!element) return; // no more found
const componentName = element.getAttribute(attribute);
let content = _alpineIncludeCache[componentName] || "";
if (content) {
element.innerHTML = content;
element.removeAttribute(attribute);
// Make a recursive call to process remaining elements.
includeHTML();
} else {
const xhr = new XMLHttpRequest();
xhr.onload = () => {
// HTML5 does not dynamically add script tags using the innerHTML property!
let text = xhr.responseText;
let index = 0;
while (true) {
// Look for a script tag.
const startIndex = text.indexOf(scriptStart, index);
// TODO: Check for src attribute on script tag.
if (startIndex === -1) {
content += text.substring(index);
break;
} else {
const endIndex = text.indexOf(scriptEnd, startIndex);
if (endIndex !== -1) {
// Get the text before and in the script element.
const prefix = text.substring(0, startIndex);
const script = text.substring(
startIndex + scriptStart.length,
endIndex
);
// Create a script element and add it before the element.
const scriptElement = document.createElement("script");
scriptElement.appendChild(document.createTextNode(script));
element.parentElement.insertBefore(scriptElement, element);
content += prefix;
index = endIndex + scriptEnd.length;
} else {
throw new Error("found script start tag, but not end tag");
}
}
}
_alpineIncludeCache[componentName] = content;
// Replace the element text with all the non-script text.
element.innerHTML = content;
element.removeAttribute(attribute);
// Make a recursive call to process remaining elements.
includeHTML();
};
xhr.open("GET", `${urlPrefix}${componentName}.html`, true);
xhr.send();
}
}
window.onload = includeHTML;