Frontend iframe renderer framework: 3D models, OpenAPI (#37233)

Introduces a frontend external-render framework that runs renderer
plugins inside an `iframe` (loaded via `srcdoc` to keep the CSP
`sandbox` directive working without origin-related console noise), and
migrates the 3D viewer and OpenAPI/Swagger renderers onto it. PDF and
asciicast paths are refactored to share the same `data-render-name`
mechanism.

Adds e2e coverage for 3D, PDF, asciicast and OpenAPI render paths, plus
a regression for the `RefTypeNameSubURL` double-escape on non-ASCII
branch names.

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind
2026-04-18 00:30:17 +02:00
committed by GitHub
parent 0161f3019b
commit d5831b9385
32 changed files with 540 additions and 293 deletions

View File

@@ -1,5 +1,6 @@
import {generateElemId, queryElemChildren} from '../utils/dom.ts';
import {generateElemId} from '../utils/dom.ts';
import {isDarkTheme} from '../utils.ts';
import {GET} from '../modules/fetch.ts';
function safeRenderIframeLink(link: any): string | null {
try {
@@ -41,7 +42,7 @@ function getRealBackgroundColor(el: HTMLElement) {
return '';
}
async function loadRenderIframeContent(iframe: HTMLIFrameElement) {
export async function initExternalRenderIframe(iframe: HTMLIFrameElement) {
const iframeSrcUrl = iframe.getAttribute('data-src')!;
if (!iframe.id) iframe.id = generateElemId('gitea-iframe-');
@@ -62,9 +63,10 @@ async function loadRenderIframeContent(iframe: HTMLIFrameElement) {
u.searchParams.set('gitea-is-dark-theme', String(isDarkTheme()));
u.searchParams.set('gitea-iframe-id', iframe.id);
u.searchParams.set('gitea-iframe-bgcolor', getRealBackgroundColor(iframe));
iframe.src = u.href;
}
export function initMarkupRenderIframe(el: HTMLElement) {
queryElemChildren(el, 'iframe.external-render-iframe', loadRenderIframeContent);
// It must use "srcdoc" here, because our backend always sends CSP sandbox directive for the rendered content
// (to protect from XSS risks), so we can't use "src" to load the content directly, otherwise there will be console errors like:
// Unsafe attempt to load URL http://localhost:3000/test from frame with URL http://localhost:3000/test
const resp = await GET(u.href);
iframe.srcdoc = await resp.text();
}