Skip to content

Commit 3bce33e

Browse files
committed
docs: fix html-includes patch
1 parent 70bfd93 commit 3bce33e

File tree

1 file changed

+87
-86
lines changed

1 file changed

+87
-86
lines changed

docs/demo/demo.ts

Lines changed: 87 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,4 @@
11
import { HTMLIncludeElement } from 'html-include-element';
2-
3-
/* eslint-disable no-console */
4-
/**
5-
* quick hack to avoid page load errors if subresources are missing from demo files
6-
* @see https://github.com/justinfagnani/html-include-element/pull/21
7-
*/
8-
if (!HTMLIncludeElement.prototype.attributeChangedCallback.toString().includes('await Promise.all([...this.shadowRoot.querySelectorAll')) {
9-
console.info('No need to patch <html-include>');
10-
} else {
11-
console.info('Patching <html-include>');
12-
// @ts-expect-error: tla is available
13-
await customElements.whenDefined('html-include');
14-
const isLinkAlreadyLoaded = (link: HTMLLinkElement) => {
15-
try {
16-
return !!(link.sheet && link.sheet.cssRules);
17-
} catch (error) {
18-
if (error.name === 'InvalidAccessError' || error.name === 'SecurityError') {
19-
return false;
20-
} else {
21-
throw error;
22-
}
23-
}
24-
};
25-
26-
const linkLoaded = async function linkLoaded(link: HTMLLinkElement) {
27-
return new Promise((resolve, reject) => {
28-
if (!('onload' in HTMLLinkElement.prototype)) {
29-
resolve(null);
30-
} else if (isLinkAlreadyLoaded(link)) {
31-
resolve(link.sheet);
32-
} else {
33-
link.addEventListener('load', () => resolve(link.sheet), { once: true });
34-
link.addEventListener('error', () => reject({ link }), { once: true });
35-
}
36-
});
37-
};
38-
39-
HTMLIncludeElement.prototype.attributeChangedCallback = async function attributeChangedCallback(name: string, _: string, newValue: string) {
40-
if (name === 'src') {
41-
let text = '';
42-
try {
43-
const mode = this.mode || 'cors';
44-
const response = await fetch(newValue, { mode });
45-
if (!response.ok) {
46-
throw new Error(`html-include fetch failed: ${response.statusText}`);
47-
}
48-
text = await response.text();
49-
if (this.src !== newValue) {
50-
// the src attribute was changed before we got the response, so bail
51-
return;
52-
}
53-
} catch (e) {
54-
console.error(e);
55-
}
56-
// Don't destroy the light DOM if we're using shadow DOM, so that slotted content is respected
57-
if (this.noShadow) {
58-
this.innerHTML = text;
59-
}
60-
this.shadowRoot.innerHTML = `
61-
<style>
62-
:host {
63-
display: block;
64-
}
65-
</style>
66-
${this.noShadow ? '<slot></slot>' : text}
67-
`;
68-
69-
// If we're not using shadow DOM, then the consuming root
70-
// is responsible to load its own resources
71-
if (!this.noShadow) {
72-
const results = await Promise.allSettled([...this.shadowRoot.querySelectorAll('link')].map(linkLoaded));
73-
for (const result of results) {
74-
if (result.status === 'rejected') {
75-
const { link } = result.reason;
76-
const message = `Could not load ${link.href}`;
77-
console.error(message);
78-
}
79-
}
80-
}
81-
82-
this.dispatchEvent(new Event('load'));
83-
}
84-
};
85-
}
86-
/* eslint-enable no-console */
87-
882
import 'api-viewer-element';
893
import '@vaadin/split-layout';
904

@@ -135,8 +49,95 @@ async function onLoad(element: string, base: 'core' | 'elements', location: Loca
13549
onContextChange();
13650
}
13751

52+
async function patchHTMLIncludes() {
53+
/* eslint-disable no-console */
54+
/**
55+
* quick hack to avoid page load errors if subresources are missing from demo files
56+
* @see https://github.com/justinfagnani/html-include-element/pull/21
57+
*/
58+
if (!HTMLIncludeElement.prototype.attributeChangedCallback.toString().includes('await Promise.all([...this.shadowRoot.querySelectorAll')) {
59+
console.info('No need to patch <html-include>');
60+
} else {
61+
console.info('Patching <html-include>');
62+
await customElements.whenDefined('html-include');
63+
const isLinkAlreadyLoaded = (link: HTMLLinkElement) => {
64+
try {
65+
return !!(link.sheet && link.sheet.cssRules);
66+
} catch (error) {
67+
if (error.name === 'InvalidAccessError' || error.name === 'SecurityError') {
68+
return false;
69+
} else {
70+
throw error;
71+
}
72+
}
73+
};
74+
75+
const linkLoaded = async function linkLoaded(link: HTMLLinkElement) {
76+
return new Promise((resolve, reject) => {
77+
if (!('onload' in HTMLLinkElement.prototype)) {
78+
resolve(null);
79+
} else if (isLinkAlreadyLoaded(link)) {
80+
resolve(link.sheet);
81+
} else {
82+
link.addEventListener('load', () => resolve(link.sheet), { once: true });
83+
link.addEventListener('error', () => reject({ link }), { once: true });
84+
}
85+
});
86+
};
87+
88+
HTMLIncludeElement.prototype.attributeChangedCallback = async function attributeChangedCallback(name: string, _: string, newValue: string) {
89+
if (name === 'src') {
90+
let text = '';
91+
try {
92+
const mode = this.mode || 'cors';
93+
const response = await fetch(newValue, { mode });
94+
if (!response.ok) {
95+
throw new Error(`html-include fetch failed: ${response.statusText}`);
96+
}
97+
text = await response.text();
98+
if (this.src !== newValue) {
99+
// the src attribute was changed before we got the response, so bail
100+
return;
101+
}
102+
} catch (e) {
103+
console.error(e);
104+
}
105+
// Don't destroy the light DOM if we're using shadow DOM, so that slotted content is respected
106+
if (this.noShadow) {
107+
this.innerHTML = text;
108+
}
109+
this.shadowRoot.innerHTML = `
110+
<style>
111+
:host {
112+
display: block;
113+
}
114+
</style>
115+
${this.noShadow ? '<slot></slot>' : text}
116+
`;
117+
118+
// If we're not using shadow DOM, then the consuming root
119+
// is responsible to load its own resources
120+
if (!this.noShadow) {
121+
const results = await Promise.allSettled([...this.shadowRoot.querySelectorAll('link')].map(linkLoaded));
122+
for (const result of results) {
123+
if (result.status === 'rejected') {
124+
const { link } = result.reason;
125+
const message = `Could not load ${link.href}`;
126+
console.error(message);
127+
}
128+
}
129+
}
130+
131+
this.dispatchEvent(new Event('load'));
132+
}
133+
};
134+
}
135+
/* eslint-enable no-console */
136+
}
137+
138138
/** Load up the requested element's demo in a separate shadow root */
139139
async function go(location = window.location) {
140+
await patchHTMLIncludes();
140141
const { element } = pattern.exec(location.href)?.pathname?.groups ?? {};
141142

142143
if (element) {

0 commit comments

Comments
 (0)