From 020e6001cf4a34b7eb900586d77e767012d3570e Mon Sep 17 00:00:00 2001 From: Benny Powers Date: Thu, 24 Mar 2022 16:07:49 -0400 Subject: [PATCH] docs: patch html-includes if needed See https://github.com/justinfagnani/html-include-element/pull/21 --- docs/demo/demo.ts | 86 ++++++++++++++++++- .../pfe-jump-links/demo/pfe-jump-links.js | 4 +- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/docs/demo/demo.ts b/docs/demo/demo.ts index 0deecf1fcb..77ddb74dab 100644 --- a/docs/demo/demo.ts +++ b/docs/demo/demo.ts @@ -1,4 +1,88 @@ -import 'html-include-element'; +import { HTMLIncludeElement } from 'html-include-element'; + +/* eslint-disable no-console */ +/** + * quick hack to avoid page load errors if subresources are missing from demo files + * @see https://github.com/justinfagnani/html-include-element/pull/21 + */ +if (!HTMLIncludeElement.prototype.attributeChangedCallback.toString().includes('await Promise.all([...this.shadowRoot.querySelectorAll')) { + console.info('No need to patch '); +} else { + console.info('Patching '); + const isLinkAlreadyLoaded = (link: HTMLLinkElement) => { + try { + return !!(link.sheet && link.sheet.cssRules); + } catch (error) { + if (error.name === 'InvalidAccessError' || error.name === 'SecurityError') { + return false; + } else { + throw error; + } + } + }; + + const linkLoaded = async function linkLoaded(link: HTMLLinkElement) { + return new Promise((resolve, reject) => { + if (!('onload' in HTMLLinkElement.prototype)) { + resolve(null); + } else if (isLinkAlreadyLoaded(link)) { + resolve(link.sheet); + } else { + link.addEventListener('load', () => resolve(link.sheet), { once: true }); + link.addEventListener('error', () => reject({ link }), { once: true }); + } + }); + }; + + HTMLIncludeElement.prototype.attributeChangedCallback = async function attributeChangedCallback(name: string, _: string, newValue: string) { + if (name === 'src') { + let text = ''; + try { + const mode = this.mode || 'cors'; + const response = await fetch(newValue, { mode }); + if (!response.ok) { + throw new Error(`html-include fetch failed: ${response.statusText}`); + } + text = await response.text(); + if (this.src !== newValue) { + // the src attribute was changed before we got the response, so bail + return; + } + } catch (e) { + console.error(e); + } + // Don't destroy the light DOM if we're using shadow DOM, so that slotted content is respected + if (this.noShadow) { + this.innerHTML = text; + } + this.shadowRoot.innerHTML = ` + + ${this.noShadow ? '' : text} + `; + + // If we're not using shadow DOM, then the consuming root + // is responsible to load its own resources + if (!this.noShadow) { + const results = await Promise.allSettled([...this.shadowRoot.querySelectorAll('link')].map(linkLoaded)); + for (const result of results) { + if (result.status === 'rejected') { + const { link } = result.reason; + const message = `Could not load ${link.href}`; + console.error(message); + } + } + } + + this.dispatchEvent(new Event('load')); + } + }; +} +/* eslint-enable no-console */ + import 'api-viewer-element'; import '@vaadin/split-layout'; diff --git a/elements/pfe-jump-links/demo/pfe-jump-links.js b/elements/pfe-jump-links/demo/pfe-jump-links.js index d00bd1e26f..6a290446e6 100644 --- a/elements/pfe-jump-links/demo/pfe-jump-links.js +++ b/elements/pfe-jump-links/demo/pfe-jump-links.js @@ -10,8 +10,8 @@ import { installRouter } from 'pwa-helpers/router.js'; * @this {HTMLElement} */ async function route(location = window.location, event) { - event.preventDefault(); - event.stopPropagating(); + event?.preventDefault(); + event?.stopPropagating(); if (location.hash) { root?.querySelector(location.hash)?.scrollIntoView({ behavior: 'smooth' }); }