fix(goview): extract src from embed html for iframe/video
This commit is contained in:
parent
c4c50b9e89
commit
62b1d60ff2
@ -40,6 +40,21 @@ 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') {
|
||||||
@ -94,7 +109,13 @@ function pickSrc(option: GoViewIframeOption): string {
|
|||||||
pickUrlLike(option.src) ||
|
pickUrlLike(option.src) ||
|
||||||
pickUrlLike(option.url);
|
pickUrlLike(option.url);
|
||||||
|
|
||||||
if (url) return looksLikeHtml(url) ? toDataHtmlUrl(url) : url;
|
if (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(
|
||||||
@ -120,7 +141,12 @@ function pickSrc(option: GoViewIframeOption): string {
|
|||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
|
|
||||||
return listUrl ? (looksLikeHtml(listUrl) ? toDataHtmlUrl(listUrl) : listUrl) : '';
|
if (!listUrl) return '';
|
||||||
|
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 {
|
||||||
|
|||||||
@ -42,6 +42,29 @@ 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;
|
||||||
@ -113,6 +136,13 @@ 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(
|
||||||
@ -144,7 +174,7 @@ function pickSrc(option: GoViewVideoOption): string {
|
|||||||
},
|
},
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
if (fromDirect) return fromDirect;
|
if (fromDirect) return normalizeSrcMaybeFromHtml(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(
|
||||||
@ -158,10 +188,11 @@ function pickSrc(option: GoViewVideoOption): string {
|
|||||||
},
|
},
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
if (fromList) return fromList;
|
if (fromList) return normalizeSrcMaybeFromHtml(fromList);
|
||||||
|
|
||||||
// Last resort: permissive URL-like picking across option/dataset/src/url.
|
// Last resort: permissive URL-like picking across option/dataset/src/url.
|
||||||
return pickUrlLike(option) || pickUrlLike(option.dataset) || pickUrlLike(option.src) || pickUrlLike(option.url);
|
const raw = 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 {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user