Files
memind/plaza-embed.mjs
T
John 25d9c8c364 Add MindSpace visual page editor and Plaza local Tunnel deployment.
In-preview HTML editing with undo/redo sync replaces Agent patch auto-save; Plaza runs on local Mac via Cloudflare Tunnel with embed height and CSP fixes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 22:57:22 -07:00

131 lines
4.5 KiB
JavaScript

/**
* Plaza iframe embed helpers — full-page iframe height sync for publication pages.
*/
export const PLAZA_EMBED_QUERY = 'embed=plaza';
export function isPlazaEmbedRequest(query = {}) {
return String(query?.embed ?? '').toLowerCase() === 'plaza';
}
export function publishedPageCspForEmbed(isFullHtml) {
if (isFullHtml) {
return "default-src 'none'; style-src 'unsafe-inline' https:; img-src data: https:; font-src https: data:; base-uri 'none'; form-action 'self'; frame-ancestors *; script-src 'unsafe-inline'";
}
return "default-src 'none'; style-src 'unsafe-inline'; img-src data:; font-src 'none'; base-uri 'none'; form-action 'self'; frame-ancestors *; script-src 'unsafe-inline'";
}
const EMBED_BOOTSTRAP = `<script id="plaza-embed-bootstrap">(function(){
if(window.parent===window)return;
var d=document;
function blocks(){
var out=[],hero=d.querySelector('.hero');
if(hero)out.push(hero);
d.querySelectorAll('.section,.quote-section').forEach(function(el){out.push(el);});
var foot=d.querySelector('.footer');
if(foot)out.push(foot);
return out.length?out:[d.body];
}
function fullHeight(){
var body=d.body;
var measured=0;
var els=blocks();
for(var i=0;i<els.length;i++){
var el=els[i];
measured=Math.max(measured,el.offsetTop+el.offsetHeight);
}
if(body&&body.lastElementChild){
var last=body.lastElementChild;
measured=Math.max(measured,last.offsetTop+last.offsetHeight);
}
measured=Math.max(measured,d.documentElement.scrollHeight,body?body.scrollHeight:0,420);
return Math.min(measured,16000);
}
function restoreBlock(block){
if(!block)return;
block.querySelectorAll('[data-plaza-defer-bg]').forEach(function(el){
el.style.backgroundImage=el.dataset.plazaDeferBg;
delete el.dataset.plazaDeferBg;
});
block.querySelectorAll('[data-plaza-defer-hero-bg]').forEach(function(el){
var bg=el.dataset.plazaDeferHeroBg;
if(!bg)return;
if(bg.indexOf('url(')>=0)el.style.backgroundImage=bg;
else el.style.background=bg;
delete el.dataset.plazaDeferHeroBg;
});
}
function reportHeight(){
var b=blocks();
window.parent.postMessage({
type:'plaza:embed-section',
count:b.length,
height:fullHeight(),
total:b.length
},'*');
}
function showAll(){
var b=blocks();
for(var i=0;i<b.length;i++){
b[i].style.display='';
b[i].style.visibility='';
restoreBlock(b[i]);
}
reportHeight();
}
var style=d.createElement('style');
style.textContent='html,body{overflow:hidden!important;margin:0}';
d.head.appendChild(style);
function scheduleReport(){
showAll();
requestAnimationFrame(function(){
requestAnimationFrame(function(){
reportHeight();
});
});
}
if(d.readyState==='loading'){
d.addEventListener('DOMContentLoaded',scheduleReport);
}else{
scheduleReport();
}
window.addEventListener('load',function(){scheduleReport();});
new ResizeObserver(function(){reportHeight();}).observe(d.documentElement);
})();</script>`;
const EMBED_LAYOUT_OVERRIDES =
'<style id="plaza-embed-overrides">.section,.quote-section,.footer{content-visibility:visible!important;contain-intrinsic-size:auto!important}</style>';
/** Remove inline CSP meta tags that block plaza-embed-bootstrap (HTTP CSP header applies instead). */
export function stripPublicationHtmlCspMeta(html) {
return String(html ?? '').replace(
/<meta\s+http-equiv\s*=\s*["']Content-Security-Policy["'][^>]*>/gi,
'',
);
}
/** Prepare stored publication HTML for Plaza iframe embed. */
export function preparePublicationHtmlForEmbed(html) {
let source = stripPublicationHtmlCspMeta(html);
if (!source.includes('id="plaza-embed-overrides"') && /<head[^>]*>/i.test(source)) {
source = source.replace(/<head([^>]*)>/i, `<head$1>${EMBED_LAYOUT_OVERRIDES}`);
}
return injectPlazaEmbedBootstrap(source);
}
export function injectPlazaEmbedBootstrap(html) {
const source = String(html ?? '');
if (source.includes('id="plaza-embed-bootstrap"')) return source;
if (/<\/body>/i.test(source)) {
return source.replace(/<\/body>/i, `${EMBED_BOOTSTRAP}</body>`);
}
return `${source}${EMBED_BOOTSTRAP}`;
}
export function appendPlazaEmbedQuery(url) {
const value = String(url ?? '').trim();
if (!value) return value;
if (value.includes(PLAZA_EMBED_QUERY)) return value;
return value.includes('?') ? `${value}&${PLAZA_EMBED_QUERY}` : `${value}?${PLAZA_EMBED_QUERY}`;
}