From 742b3e35b12636fcb8f2821c9487121dae10a353 Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Tue, 19 May 2026 16:29:19 -0400 Subject: [PATCH 1/2] Add renderMethodReady() using postMessage(). The implementation uses an object passed to `renderMethodReady()`. It currently supports values of `{ready: true}` or `{error: {message: ...}}`. Obviously additional data could be passed through on that object making this a risk if the renderer is not meant to know of the results or if the JS in the sandbox could surface JS (perhaps embedded in an SVG or PDF) if that were sent back through the `postMessage()`. So...we should proceed with caution. --- app.js | 20 ++++++++++++++++++++ index.html | 8 +++++++- viewers/html.js | 20 ++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index b6243a7..4851f63 100644 --- a/app.js +++ b/app.js @@ -99,5 +99,25 @@ window.app = createApp({ }, loadExampleCredential(event) { this.loadCredential(event.target.value); + }, + setupMessaging(el) { + const iframe = el; + const loader = el.nextElementSibling; + // create a MessageChannel; transfer one port to the iframe + const channel = new MessageChannel(); + // start message queue so messages won't be lost while iframe loads + channel.port1.start(); + // handle `ready` message + channel.port1.onmessage = function(event) { + if(event.data?.ready) { + iframe.removeAttribute('hidden'); + loader.setAttribute('hidden', 'hidden'); + } else { + new Error(event.data?.error?.message); + } + channel.port1.onmessage = undefined; + }; + // send "start" message; send `port2` to iframe for return communication + iframe.contentWindow.postMessage('start', '*', [channel.port2]); } }).mount(); diff --git a/index.html b/index.html index c8d149a..dcd4f8a 100644 --- a/index.html +++ b/index.html @@ -57,7 +57,13 @@ @click="currentTab = 'credential'">Filtered Credential
- + + +
diff --git a/viewers/html.js b/viewers/html.js index ae01a50..a24d660 100644 --- a/viewers/html.js +++ b/viewers/html.js @@ -36,6 +36,26 @@ export function HTMLViewer({template, credential, pointers}) { + ${store.code} From 62a35f64158fdc070f1bed041862dd68059ea3a4 Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Tue, 19 May 2026 16:37:24 -0400 Subject: [PATCH 2/2] Add Download PDF after iframe if provided. It is now possible to supply an `application/pdf` value to the parent page (for better or worse) via `renderMethodReady({ready: true, pdf: ...data URL of application/pdf...})`. --- app.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app.js b/app.js index 4851f63..82c77c7 100644 --- a/app.js +++ b/app.js @@ -112,6 +112,15 @@ window.app = createApp({ if(event.data?.ready) { iframe.removeAttribute('hidden'); loader.setAttribute('hidden', 'hidden'); + if(event.data?.pdf) { + // append another iframe after the current one with the PDF data URL + const pdfDownloadLink = document.createElement('a'); + pdfDownloadLink.href = event.data.pdf; + pdfDownloadLink.download = 'credential.pdf'; + pdfDownloadLink.textContent = 'Download PDF'; + pdfDownloadLink.type = 'application/pdf'; + iframe.insertAdjacentElement('afterend', pdfDownloadLink); + } } else { new Error(event.data?.error?.message); }