Compare commits

..

No commits in common. "62b1d60ff2430663b43e83dbf34b638715ec5fd2" and "a10a5eb66176d180673d24aa0b844466ab57481f" have entirely different histories.

4 changed files with 11 additions and 74 deletions

View File

@ -1,10 +1,8 @@
#root { #root {
width: 100vw; max-width: 1280px;
height: 100vh; margin: 0 auto;
max-width: none; padding: 2rem;
margin: 0; text-align: center;
padding: 0;
text-align: initial;
} }
.logo { .logo {

View File

@ -24,16 +24,12 @@ a:hover {
body { body {
margin: 0; margin: 0;
display: flex;
place-items: center;
min-width: 320px; min-width: 320px;
min-height: 100vh; min-height: 100vh;
} }
/* Editor app should occupy the full viewport; Vite template centering breaks layout */
#root {
width: 100vw;
height: 100vh;
}
h1 { h1 {
font-size: 3.2em; font-size: 3.2em;
line-height: 1.1; line-height: 1.1;

View File

@ -40,21 +40,6 @@ function looksLikeHtml(input: string): boolean {
return trimmed.startsWith('<') && trimmed.includes('>'); return trimmed.startsWith('<') && trimmed.includes('>');
} }
function extractSrcFromEmbedHtml(html: string): string {
// Many low-code editors store iframe widgets as an embed code string.
// Prefer extracting the actual src to keep the resulting screen portable.
// Examples:
// - <iframe src="https://example.com" ...></iframe>
// - <iframe src='//example.com' ...>
// - <embed src="...">
const s = html.trim();
if (!s) return '';
const match = /\b(?:iframe|embed)\b[^>]*\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+))/i.exec(s);
const src = match?.[1] ?? match?.[2] ?? match?.[3] ?? '';
return typeof src === 'string' ? src.trim() : '';
}
function toMaybeNumber(v: unknown): number | undefined { function toMaybeNumber(v: unknown): number | undefined {
if (typeof v === 'number' && Number.isFinite(v)) return v; if (typeof v === 'number' && Number.isFinite(v)) return v;
if (typeof v === 'string') { if (typeof v === 'string') {
@ -109,13 +94,7 @@ function pickSrc(option: GoViewIframeOption): string {
pickUrlLike(option.src) || pickUrlLike(option.src) ||
pickUrlLike(option.url); pickUrlLike(option.url);
if (url) { if (url) return looksLikeHtml(url) ? toDataHtmlUrl(url) : url;
if (looksLikeHtml(url)) {
const extracted = extractSrcFromEmbedHtml(url);
return extracted || toDataHtmlUrl(url);
}
return url;
}
// 2) Some exports store raw HTML instead of a URL. // 2) Some exports store raw HTML instead of a URL.
const html = pickFromNested( const html = pickFromNested(
@ -141,12 +120,7 @@ function pickSrc(option: GoViewIframeOption): string {
2, 2,
); );
if (!listUrl) return ''; return listUrl ? (looksLikeHtml(listUrl) ? toDataHtmlUrl(listUrl) : listUrl) : '';
if (looksLikeHtml(listUrl)) {
const extracted = extractSrcFromEmbedHtml(listUrl);
return extracted || toDataHtmlUrl(listUrl);
}
return listUrl;
} }
function pickBorderRadius(option: GoViewIframeOption): number | undefined { function pickBorderRadius(option: GoViewIframeOption): number | undefined {

View File

@ -42,29 +42,6 @@ function asString(v: unknown): string {
return ''; return '';
} }
function looksLikeHtml(input: string): boolean {
const trimmed = input.trim();
return trimmed.startsWith('<') && trimmed.includes('>');
}
function extractSrcFromVideoHtml(html: string): string {
// Some low-code exports store a whole <video> or <source> tag string.
// Examples:
// - <video src="..." />
// - <video><source src="..." /></video>
const s = html.trim();
if (!s) return '';
// Prefer <source src="..."> if present.
const sourceMatch = /\bsource\b[^>]*\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+))/i.exec(s);
const sourceSrc = sourceMatch?.[1] ?? sourceMatch?.[2] ?? sourceMatch?.[3] ?? '';
if (sourceSrc) return sourceSrc.trim();
const videoMatch = /\bvideo\b[^>]*\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+))/i.exec(s);
const videoSrc = videoMatch?.[1] ?? videoMatch?.[2] ?? videoMatch?.[3] ?? '';
return typeof videoSrc === 'string' ? videoSrc.trim() : '';
}
function toMaybeBoolean(v: unknown): boolean | undefined { function toMaybeBoolean(v: unknown): boolean | undefined {
if (typeof v === 'boolean') return v; if (typeof v === 'boolean') return v;
if (typeof v === 'number') return v !== 0; if (typeof v === 'number') return v !== 0;
@ -136,13 +113,6 @@ function pickFirstUrlFromList(input: unknown): string {
return pickUrlLike(obj, 2); return pickUrlLike(obj, 2);
} }
function normalizeSrcMaybeFromHtml(raw: string): string {
if (!raw) return '';
if (!looksLikeHtml(raw)) return raw;
const extracted = extractSrcFromVideoHtml(raw);
return extracted || raw;
}
function pickSrc(option: GoViewVideoOption): string { function pickSrc(option: GoViewVideoOption): string {
// Prefer explicit video-ish keys in a stable order, then fall back to permissive URL picking. // Prefer explicit video-ish keys in a stable order, then fall back to permissive URL picking.
const fromDirect = pickFromNested( const fromDirect = pickFromNested(
@ -174,7 +144,7 @@ function pickSrc(option: GoViewVideoOption): string {
}, },
2, 2,
); );
if (fromDirect) return normalizeSrcMaybeFromHtml(fromDirect); if (fromDirect) return fromDirect;
// Many exports use list-ish shapes: sources/sourceList/urlList/etc. // Many exports use list-ish shapes: sources/sourceList/urlList/etc.
const fromList = pickFromNested( const fromList = pickFromNested(
@ -188,11 +158,10 @@ function pickSrc(option: GoViewVideoOption): string {
}, },
2, 2,
); );
if (fromList) return normalizeSrcMaybeFromHtml(fromList); if (fromList) return fromList;
// Last resort: permissive URL-like picking across option/dataset/src/url. // Last resort: permissive URL-like picking across option/dataset/src/url.
const raw = pickUrlLike(option) || pickUrlLike(option.dataset) || pickUrlLike(option.src) || pickUrlLike(option.url); return pickUrlLike(option) || pickUrlLike(option.dataset) || pickUrlLike(option.src) || pickUrlLike(option.url);
return normalizeSrcMaybeFromHtml(raw);
} }
function pickBorderRadius(option: GoViewVideoOption): number | undefined { function pickBorderRadius(option: GoViewVideoOption): number | undefined {