create fresh JS execution context on each render
Hunter
Thursday, July 24th, 2025 at 3:29 PM
182 }
183
184
- function createFullscreenToggle() {
- try {
- if (!preview.contentDocument) return;
-
- const doc = preview.contentDocument;
-
- // Remove existing button if it exists
- const existingButton = doc.getElementById('fullscreenToggle');
- if (existingButton) {
- existingButton.remove();
- }
-
- // Create button element
- const button = doc.createElement('button');
- button.id = 'fullscreenToggle';
- button.className = 'iframe-fullscreen-toggle';
- button.title = 'Toggle fullscreen';
- button.innerHTML = `<img src="resources/fullscreen.svg" width="20" height="20" alt="Fullscreen">`;
-
- // Add click handler
- button.addEventListener('click', toggleFullscreen);
-
- // Append to body
- if (doc.body) {
- doc.body.appendChild(button);
- }
- } catch (e) {
- // Ignore cross-origin errors
185 + // Listen for messages from iframe
186 + window.addEventListener('message', function(event) {
187 + if (event.data === 'toggleFullscreen') {
188 + toggleFullscreen();
189 }
- }
190 + });
191
192 function updatePreview() {
193 const code = editorView.state.doc.toString();
203 // Ignore cross-origin errors
204 }
205
- // Write HTML directly to iframe document
- const doc = preview.contentDocument || preview.contentWindow.document;
- doc.open();
-
- // Ensure we have a proper HTML document structure for the button
- const htmlContent = code.trim() || '<!DOCTYPE html><html><head></head><body></body></html>';
- doc.write(htmlContent);
206 + // Use srcdoc to create a completely fresh document context
207 + preview.srcdoc = code.trim() || '<!DOCTYPE html><html><head></head><body></body></html>';
208
- // Inject CSS to disable overscroll and add fullscreen toggle styles
- const style = doc.createElement('style');
- style.textContent = `
- * { overscroll-behavior: none !important; }
-
- .iframe-fullscreen-toggle {
- position: fixed;
- top: 5px;
- right: 5px;
- z-index: 10000;
- background: rgba(0, 0, 0, 0.2);
- color: white;
- border: none;
- border-radius: 4px;
- width: 32px;
- height: 32px;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- transition: background-color 0.2s;
- box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
- }
-
- .iframe-fullscreen-toggle img {
- filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
- opacity: 0.8;
- transition: opacity 0.2s;
- }
-
- @media (hover: hover) and (pointer: fine) {
- .iframe-fullscreen-toggle:hover {
- background: rgba(0, 0, 0, 0.35);
- }
-
- .iframe-fullscreen-toggle:hover img {
- opacity: 1;
- }
- }
- `;
- if (doc.head) {
- doc.head.appendChild(style);
- }
-
- // Create fullscreen toggle button immediately
- createFullscreenToggle();
-
- doc.close();
-
- // Restore scroll position after a short delay to ensure content is rendered
- setTimeout(() => {
209 + // Add our functionality after the iframe loads
210 + const onLoad = () => {
211 try {
- if (preview.contentWindow) {
- preview.contentWindow.scrollTo(scrollX, scrollY);
212 + const doc = preview.contentDocument;
213 + if (!doc) return;
214 +
215 + // Add CSS for overscroll and button
216 + const style = doc.createElement('style');
217 + style.textContent = '* { overscroll-behavior: none !important; } .iframe-fullscreen-toggle { position: fixed; top: 5px; right: 5px; z-index: 10000; background: rgba(0, 0, 0, 0.2); color: white; border: none; border-radius: 4px; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color 0.2s; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); } .iframe-fullscreen-toggle img { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3)); opacity: 0.8; transition: opacity 0.2s; } @media (hover: hover) and (pointer: fine) { .iframe-fullscreen-toggle:hover { background: rgba(0, 0, 0, 0.35); } .iframe-fullscreen-toggle:hover img { opacity: 1; } }';
218 + doc.head.appendChild(style);
219 +
220 + // Create fullscreen button
221 + const existingButton = doc.getElementById('fullscreenToggle');
222 + if (existingButton) existingButton.remove();
223 +
224 + const button = doc.createElement('button');
225 + button.id = 'fullscreenToggle';
226 + button.className = 'iframe-fullscreen-toggle';
227 + button.title = 'Toggle fullscreen';
228 +
229 + const img = doc.createElement('img');
230 + img.src = 'resources/fullscreen.svg';
231 + img.width = 20;
232 + img.height = 20;
233 + img.alt = 'Fullscreen';
234 + button.appendChild(img);
235 +
236 + button.addEventListener('click', function() {
237 + parent.postMessage('toggleFullscreen', '*');
238 + });
239 +
240 + if (doc.body) {
241 + doc.body.appendChild(button);
242 }
243 +
244 + // Restore scroll position
245 + setTimeout(() => {
246 + try {
247 + if (preview.contentWindow) {
248 + preview.contentWindow.scrollTo(scrollX, scrollY);
249 + }
250 + } catch (e) {
251 + // Ignore cross-origin errors
252 + }
253 + }, 10);
254 } catch (e) {
255 // Ignore cross-origin errors
256 }
- }, 10);
257 +
258 + preview.removeEventListener('load', onLoad);
259 + };
260 + preview.addEventListener('load', onLoad);
261 }
262
263 function saveToStorage() {