const style = `:host { display: block; width: 300px; height: 150px; background-color: #ddd;}iframe { width: 100%; height: 100%; border: none;}.download-link { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center;}.download-link a { background-color: royalblue; color: white; border-radius: 0.5em; padding: 1em; text-decoration: none; line-height: 100%;}.download-link a:hover { background-color: dodgerblue;}.download-link a::after { content: "💾"; font-size: 1.2em; mergin: 0.2em; filter: brightness(2);}`;
const viewerHtmlCache = {};
async function render({ src: fileSrc }) { const iframe = document.createElement("iframe");
if (!fileSrc) { throw new Error("plese set `src` attribute to <embed-pdf> element."); }
if (globalThis.navigator?.pdfViewerEnabled) { iframe.src = fileSrc; return iframe; }
try { const fileUrl = new URL(fileSrc, location.href);
viewerHtmlCache[EmbedPdf.viewerUrl] ??= (async () => { const res = await fetch(EmbedPdf.viewerUrl); return await res.text(); })(); const text = await viewerHtmlCache[EmbedPdf.viewerUrl];
const html = text .replace( '<meta charset="utf-8">', `<meta charset="utf-8"><base href="${EmbedPdf.viewerUrl}">`, ) .replace( '<script src="viewer.js"></script>', `<script src="viewer.js"></script> <script>PDFViewerApplicationOptions.set("defaultUrl", "${fileUrl}");</script>`, );
const blob = new Blob([html], { type: "text/html" }); iframe.src = URL.createObjectURL(blob);
iframe.addEventListener("load", () => { iframe.contentWindow?.addEventListener("unhandledrejection", () => { iframe.parentNode?.append(renderDownloadLink(fileSrc)); iframe.remove(); }); });
return iframe; } catch (error) { console.error(error);
return renderDownloadLink(fileSrc); }}
function renderDownloadLink(fileSrc) { const wrapper = document.createElement("div"); const downloadLink = document.createElement("a"); downloadLink.href = fileSrc; downloadLink.target = "_brank"; downloadLink.textContent = "Download PDF "; wrapper.append(downloadLink); wrapper.classList.add("download-link"); return wrapper;}
export class EmbedPdf extends HTMLElement { static viewerUrl = new URL("./vendor/pdfjs/web/viewer.html", import.meta.url) .toString(); static observedAttributes = ["src"]; #shadowRoot; #isConnected = false; constructor() { super(); this.#shadowRoot = this.attachShadow({ mode: "closed" }); const styleSheet = new CSSStyleSheet(); styleSheet.replace(style); this.#shadowRoot.adoptedStyleSheets = [styleSheet]; } async connectedCallback() { this.#shadowRoot.replaceChildren( await render({ src: this.getAttribute("src") }), ); this.#isConnected = true; } disconnectedCallback() { this.#isConnected = false; this.#shadowRoot.replaceChildren(); } async attributeChangedCallback(name, _oldValue, newValue) { if (!this.#isConnected) { return; } if (name === "src") { this.#shadowRoot.replaceChildren(await render({ src: newValue })); } }}customElements.define("embed-pdf", EmbedPdf);