mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
?embed=1 shows the globe alone: clean view with the HUD, panels, welcome and setup prompts hidden, and provider attribution kept. The page that frames it sends views with postMessage; the app applies each through its own actions and reports every step. Annotations in any link are drawn once it restores. Only embed-mode documents may be framed; every other page keeps X-Frame-Options DENY and frame-ancestors 'none', and GEV_EMBED_FRAME_ANCESTORS can restrict who frames them.
56 lines
2.0 KiB
JavaScript
56 lines
2.0 KiB
JavaScript
/**
|
|
* Lets other pages frame the app in embed mode (`?embed=1`). Every other
|
|
* document keeps the server's `X-Frame-Options: DENY` and
|
|
* `frame-ancestors 'none'`, which protect Provider Settings. Embed mode
|
|
* shows only the globe, so for those documents framing is limited to
|
|
* `ancestors` instead: `GEV_EMBED_FRAME_ANCESTORS`, or any frame by default.
|
|
* "Any" sends no framing restriction at all: `frame-ancestors *` would still
|
|
* refuse sandboxed frames with an opaque origin, which panel hosts use.
|
|
*/
|
|
|
|
const FRAMING_HEADERS = new Set(['x-frame-options', 'content-security-policy']);
|
|
|
|
/** Whether a request is for an embed-mode document. */
|
|
export function isEmbedDocumentRequest(url) {
|
|
let parsed;
|
|
try {
|
|
parsed = new URL(url || '/', 'http://localhost');
|
|
} catch {
|
|
return false;
|
|
}
|
|
return (
|
|
parsed.searchParams.get('embed') === '1' &&
|
|
(parsed.pathname === '/' || parsed.pathname.endsWith('.html'))
|
|
);
|
|
}
|
|
|
|
/** Vite plugin applying the embed framing policy on dev and preview servers. */
|
|
export function embedFramingPlugin({
|
|
ancestors = process.env.GEV_EMBED_FRAME_ANCESTORS || '*',
|
|
} = {}) {
|
|
const anywhere = ancestors.trim() === '*';
|
|
const policy = `frame-ancestors ${ancestors}`;
|
|
const install = (server) => {
|
|
server.middlewares.use((req, res, next) => {
|
|
if (!isEmbedDocumentRequest(req.url)) return next();
|
|
// The server's own headers are written when the response is sent, so
|
|
// intercept them rather than setting ours first.
|
|
const setHeader = res.setHeader.bind(res);
|
|
res.setHeader = (name, value) => {
|
|
const key = String(name).toLowerCase();
|
|
if (!FRAMING_HEADERS.has(key)) return setHeader(name, value);
|
|
if (key === 'content-security-policy' && !anywhere)
|
|
return setHeader(name, policy);
|
|
return res;
|
|
};
|
|
if (!anywhere) setHeader('Content-Security-Policy', policy);
|
|
next();
|
|
});
|
|
};
|
|
return {
|
|
name: 'embed-framing',
|
|
configureServer: install,
|
|
configurePreviewServer: install,
|
|
};
|
|
}
|