tfrere HF Staff commited on
Commit
23cc404
·
1 Parent(s): a90f930

update htmlembed

Browse files
Files changed (1) hide show
  1. app/src/components/HtmlEmbed.astro +88 -86
app/src/components/HtmlEmbed.astro CHANGED
@@ -105,104 +105,106 @@ const htmlWithId =
105
  <script>
106
  // Re-execute <script> tags inside the injected fragment (innerHTML doesn't run scripts)
107
  // Uses IntersectionObserver for lazy loading - only executes when embed is visible
108
- const scriptEl = document.currentScript;
109
- const figure = scriptEl?.previousElementSibling?.closest(".html-embed");
110
- const mount = scriptEl ? scriptEl.previousElementSibling : null;
 
111
 
112
- if (!mount || !figure) return;
113
 
114
- let executed = false;
115
- const execute = () => {
116
- if (executed || !mount) return;
117
- executed = true;
118
 
119
- const scripts = mount.querySelectorAll("script");
120
- scripts.forEach((old) => {
121
- // ignore non-executable types (e.g., application/json)
122
- if (
123
- old.type &&
124
- old.type !== "text/javascript" &&
125
- old.type !== "module" &&
126
- old.type !== ""
127
- )
128
- return;
129
- if (old.dataset.executed === "true") return;
130
- old.dataset.executed = "true";
131
- if (old.src) {
132
- const s = document.createElement("script");
133
- Array.from(old.attributes).forEach((attr) =>
134
- s.setAttribute(attr.name, attr.value),
135
- );
136
- document.body.appendChild(s);
137
- } else {
138
- try {
139
- // run inline
140
- (0, eval)(old.text || "");
141
- } catch (e) {
142
- console.error("HtmlEmbed inline script error:", e);
 
143
  }
144
- }
145
- });
146
 
147
- // Mark as loaded
148
- figure.classList.add("html-embed--loaded");
149
- };
150
 
151
- // Check if IntersectionObserver is supported
152
- if ("IntersectionObserver" in window) {
153
- const observer = new IntersectionObserver(
154
- (entries) => {
155
- entries.forEach((entry) => {
156
- if (entry.isIntersecting && !executed) {
157
- observer.disconnect();
158
- // Small delay to ensure DOM is ready
159
- if (document.readyState === "loading") {
160
- document.addEventListener("DOMContentLoaded", execute, {
161
- once: true,
162
- });
163
- } else {
164
- // Use requestAnimationFrame to ensure execution after DOM is fully ready
165
- requestAnimationFrame(() => {
166
- setTimeout(execute, 0);
167
- });
 
168
  }
169
- }
170
- });
171
- },
172
- {
173
- // Start loading when element is 100px away from viewport
174
- rootMargin: "100px",
175
- threshold: 0.01,
176
- },
177
- );
178
 
179
- observer.observe(figure);
180
 
181
- // Fallback: if still not loaded after 3 seconds, load anyway (for edge cases)
182
- setTimeout(() => {
183
- if (!executed) {
184
- observer.disconnect();
185
- if (document.readyState === "loading") {
186
- document.addEventListener("DOMContentLoaded", execute, {
187
- once: true,
188
- });
189
- } else {
190
- requestAnimationFrame(() => {
191
- setTimeout(execute, 0);
192
- });
 
193
  }
194
- }
195
- }, 3000);
196
- } else {
197
- // Fallback for browsers without IntersectionObserver support
198
- if (document.readyState === "loading") {
199
- document.addEventListener("DOMContentLoaded", execute, { once: true });
200
  } else {
201
- requestAnimationFrame(() => {
202
- setTimeout(execute, 0);
203
- });
 
 
 
 
 
204
  }
205
- }
206
  </script>
207
 
208
  <style is:global>
 
105
  <script>
106
  // Re-execute <script> tags inside the injected fragment (innerHTML doesn't run scripts)
107
  // Uses IntersectionObserver for lazy loading - only executes when embed is visible
108
+ (() => {
109
+ const scriptEl = document.currentScript;
110
+ const figure = scriptEl?.previousElementSibling?.closest(".html-embed");
111
+ const mount = scriptEl ? scriptEl.previousElementSibling : null;
112
 
113
+ if (!mount || !figure) return;
114
 
115
+ let executed = false;
116
+ const execute = () => {
117
+ if (executed || !mount) return;
118
+ executed = true;
119
 
120
+ const scripts = mount.querySelectorAll("script");
121
+ scripts.forEach((old) => {
122
+ // ignore non-executable types (e.g., application/json)
123
+ if (
124
+ old.type &&
125
+ old.type !== "text/javascript" &&
126
+ old.type !== "module" &&
127
+ old.type !== ""
128
+ )
129
+ return;
130
+ if (old.dataset.executed === "true") return;
131
+ old.dataset.executed = "true";
132
+ if (old.src) {
133
+ const s = document.createElement("script");
134
+ Array.from(old.attributes).forEach((attr) =>
135
+ s.setAttribute(attr.name, attr.value),
136
+ );
137
+ document.body.appendChild(s);
138
+ } else {
139
+ try {
140
+ // run inline
141
+ (0, eval)(old.text || "");
142
+ } catch (e) {
143
+ console.error("HtmlEmbed inline script error:", e);
144
+ }
145
  }
146
+ });
 
147
 
148
+ // Mark as loaded
149
+ figure.classList.add("html-embed--loaded");
150
+ };
151
 
152
+ // Check if IntersectionObserver is supported
153
+ if ("IntersectionObserver" in window) {
154
+ const observer = new IntersectionObserver(
155
+ (entries) => {
156
+ entries.forEach((entry) => {
157
+ if (entry.isIntersecting && !executed) {
158
+ observer.disconnect();
159
+ // Small delay to ensure DOM is ready
160
+ if (document.readyState === "loading") {
161
+ document.addEventListener("DOMContentLoaded", execute, {
162
+ once: true,
163
+ });
164
+ } else {
165
+ // Use requestAnimationFrame to ensure execution after DOM is fully ready
166
+ requestAnimationFrame(() => {
167
+ setTimeout(execute, 0);
168
+ });
169
+ }
170
  }
171
+ });
172
+ },
173
+ {
174
+ // Start loading when element is 100px away from viewport
175
+ rootMargin: "100px",
176
+ threshold: 0.01,
177
+ },
178
+ );
 
179
 
180
+ observer.observe(figure);
181
 
182
+ // Fallback: if still not loaded after 3 seconds, load anyway (for edge cases)
183
+ setTimeout(() => {
184
+ if (!executed) {
185
+ observer.disconnect();
186
+ if (document.readyState === "loading") {
187
+ document.addEventListener("DOMContentLoaded", execute, {
188
+ once: true,
189
+ });
190
+ } else {
191
+ requestAnimationFrame(() => {
192
+ setTimeout(execute, 0);
193
+ });
194
+ }
195
  }
196
+ }, 3000);
 
 
 
 
 
197
  } else {
198
+ // Fallback for browsers without IntersectionObserver support
199
+ if (document.readyState === "loading") {
200
+ document.addEventListener("DOMContentLoaded", execute, { once: true });
201
+ } else {
202
+ requestAnimationFrame(() => {
203
+ setTimeout(execute, 0);
204
+ });
205
+ }
206
  }
207
+ })();
208
  </script>
209
 
210
  <style is:global>