mirror of https://github.com/docusealco/docuseal
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
3.6 KiB
92 lines
3.6 KiB
// Self-hosted embed shim for the <docuseal-builder> web component.
|
|
// Upstream `EmbedScriptsController#show` returns an "Upgrade to Pro" stub;
|
|
// the Rails static middleware serves this file ahead of that route, so the
|
|
// real shim wins without touching the controller.
|
|
//
|
|
// What this does:
|
|
// 1. Reads the JWT minted by the embedding app from `data-token`.
|
|
// 2. Iframes the token-authenticated entry point `/embed/builder?token=…`.
|
|
// That endpoint verifies the JWT against the account API key, signs the
|
|
// owner in (a first-party DocuSeal session, scoped to one template), and
|
|
// redirects into the builder — `/templates/:id/edit` for an existing
|
|
// template, or `/new?url=…` for a fresh upload. The token is the only
|
|
// credential; no cross-origin cookies are involved.
|
|
// 3. Relays the inner builder's `save` postMessage up as a DOM
|
|
// `CustomEvent('save')` so `@docuseal/react`'s `onSave` callback fires.
|
|
(function () {
|
|
// Discover the DocuSeal host from this script's own src so embedders don't
|
|
// have to set data-host on every element.
|
|
var SCRIPT_HOST = (function () {
|
|
try {
|
|
var current = document.currentScript
|
|
var src = current ? current.src : ''
|
|
if (!src) {
|
|
var all = document.getElementsByTagName('script')
|
|
for (var i = 0; i < all.length; i++) {
|
|
if (/\/js\/(builder|form)\.js/.test(all[i].src)) {
|
|
src = all[i].src
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return src ? new URL(src).host : ''
|
|
} catch (e) {
|
|
return ''
|
|
}
|
|
})()
|
|
|
|
// Relay `save` postMessage from the iframe (the builder fires it after a
|
|
// successful manual SAVE) up as a DOM `save` CustomEvent on the outer
|
|
// <docuseal-builder> element so React listeners can close the embedding sheet.
|
|
if (!window.__docusealEmbedListenerInstalled) {
|
|
window.__docusealEmbedListenerInstalled = true
|
|
window.addEventListener('message', function (ev) {
|
|
var d = ev && ev.data
|
|
if (!d || d.source !== 'docuseal-embed' || d.type !== 'save') return
|
|
document.querySelectorAll('docuseal-builder, docuseal-form').forEach(function (el) {
|
|
el.dispatchEvent(new CustomEvent('save', { detail: { template_id: d.template_id } }))
|
|
})
|
|
})
|
|
}
|
|
|
|
var EmbedBuilder = class extends HTMLElement {
|
|
static get observedAttributes() {
|
|
return ['data-token', 'data-host']
|
|
}
|
|
connectedCallback() {
|
|
this._maybeMount()
|
|
}
|
|
attributeChangedCallback() {
|
|
this._maybeMount()
|
|
}
|
|
_maybeMount() {
|
|
if (this._mounted) return
|
|
var token = this.getAttribute('data-token') || ''
|
|
if (!token) return
|
|
this._mounted = true
|
|
var host = this.getAttribute('data-host') || SCRIPT_HOST || window.location.host
|
|
|
|
// Match parent page scheme. Both ends run TLS, so https parent -> https
|
|
// iframe with no mixed-content blocking.
|
|
var origin = window.location.protocol + '//' + host
|
|
var src = origin + '/embed/builder?token=' + encodeURIComponent(token)
|
|
|
|
var iframe = document.createElement('iframe')
|
|
iframe.src = src
|
|
iframe.style.cssText = 'width:100%;height:100%;min-height:600px;border:0;display:block'
|
|
iframe.setAttribute('allow', 'clipboard-write')
|
|
this.style.display = 'block'
|
|
this.style.height = this.style.height || '100%'
|
|
this.appendChild(iframe)
|
|
}
|
|
}
|
|
|
|
if (!window.customElements.get('docuseal-builder')) {
|
|
window.customElements.define('docuseal-builder', EmbedBuilder)
|
|
}
|
|
|
|
if (!window.customElements.get('docuseal-form')) {
|
|
window.customElements.define('docuseal-form', class extends EmbedBuilder {})
|
|
}
|
|
})()
|