From 91744b4daf245c734e99cd9bc7df534dc2234051 Mon Sep 17 00:00:00 2001 From: clawdbot Date: Thu, 29 Jan 2026 00:01:38 +0800 Subject: [PATCH] sdk: broaden goView iframe/video import heuristics --- packages/sdk/src/core/goview/convert.ts | 41 ++++++++++++++++++++++--- packages/sdk/src/core/widgets/iframe.ts | 13 +++++++- packages/sdk/src/core/widgets/video.ts | 17 ++++++++++ 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/packages/sdk/src/core/goview/convert.ts b/packages/sdk/src/core/goview/convert.ts index 64f26d9..5a68110 100644 --- a/packages/sdk/src/core/goview/convert.ts +++ b/packages/sdk/src/core/goview/convert.ts @@ -342,7 +342,29 @@ function looksLikeIframeOption(option: unknown): boolean { if (containsVideoHtmlDeep(option, 2)) return false; if ( - hasAnyKeyDeep(option, ['iframeUrl', 'iframeSrc', 'embedUrl', 'frameUrl', 'frameSrc'], 3) || + hasAnyKeyDeep( + option, + [ + 'iframeUrl', + 'iframeSrc', + 'embedUrl', + 'frameUrl', + 'frameSrc', + 'webUrl', + 'webpageUrl', + 'pageUrl', + 'h5Url', + 'link', + 'href', + // list-ish + 'sources', + 'sourceList', + 'urlList', + 'srcList', + 'iframeList', + ], + 3, + ) || // Some exports store raw HTML instead of a URL. hasAnyKeyDeep( option, @@ -385,7 +407,8 @@ function looksLikeIframeOption(option: unknown): boolean { // Avoid misclassifying video streams as iframes. !/\.(mp4|m3u8|flv|webm|mov|m4v|ogv)(\?|#|$)/i.test(url) && !/\bm3u8\b/i.test(url) && - !/^(rtsp|rtmp):\/\//i.test(url) + !/^(rtsp|rtmp|webrtc|srt):\/\//i.test(url) && + !/^wss?:\/\//i.test(url) ); } @@ -425,6 +448,11 @@ function looksLikeVideoOption(option: unknown): boolean { 'hlsUrl', 'flvUrl', 'm3u8Url', + 'webrtcUrl', + 'rtcUrl', + 'wsUrl', + 'srtUrl', + 'dashUrl', 'cameraUrl', 'cctvUrl', 'monitorUrl', @@ -471,7 +499,9 @@ function looksLikeVideoOption(option: unknown): boolean { if (/\bm3u8\b/i.test(url)) return true; // Streaming-ish protocols (seen in CCTV/camera widgets). - if (/^(rtsp|rtmp):\/\//i.test(url)) return true; + if (/^(rtsp|rtmp|webrtc|srt):\/\//i.test(url)) return true; + // WebSocket-based stream relays. + if (/^wss?:\/\//i.test(url)) return true; return false; } @@ -501,7 +531,7 @@ function looksLikeJsonString(input: string): boolean { const s = input.trim(); if (!s) return false; // Avoid parsing obvious URLs. - if (/^(https?:\/\/|\/\/|data:|rtsp:\/\/|rtmp:\/\/)/i.test(s)) return false; + if (/^(https?:\/\/|\/\/|data:|rtsp:\/\/|rtmp:\/\/|webrtc:\/\/|srt:\/\/|wss?:\/\/)/i.test(s)) return false; return ( (s.startsWith('{') && s.endsWith('}')) || (s.startsWith('[') && s.endsWith(']')) @@ -681,7 +711,8 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt // Keep actual media URLs as video. !/\.(mp4|m3u8|flv|webm|mov|m4v|ogv)(\?|#|$)/i.test(urlLike) && !/^data:video\//i.test(urlLike) && - !/^(rtsp|rtmp):\/\//i.test(urlLike); + !/^(rtsp|rtmp|webrtc|srt):\/\//i.test(urlLike) && + !/^wss?:\/\//i.test(urlLike); // Prefer evidence from the option payload over the widget key. // Many forks mislabel widget keys (e.g. "Text*" / "Image*"), but the option payload diff --git a/packages/sdk/src/core/widgets/iframe.ts b/packages/sdk/src/core/widgets/iframe.ts index bb6eaa5..7a94ff9 100644 --- a/packages/sdk/src/core/widgets/iframe.ts +++ b/packages/sdk/src/core/widgets/iframe.ts @@ -18,6 +18,11 @@ export interface GoViewIframeOption { frameSrc?: unknown; webUrl?: unknown; webpageUrl?: unknown; + pageUrl?: unknown; + h5Url?: unknown; + // generic link-ish fields seen in some exports + link?: unknown; + href?: unknown; // HTML/embed variants html?: unknown; @@ -32,6 +37,8 @@ export interface GoViewIframeOption { sources?: unknown; sourceList?: unknown; urlList?: unknown; + srcList?: unknown; + iframeList?: unknown; allow?: unknown; sandbox?: unknown; @@ -200,6 +207,10 @@ function pickSrc(option: GoViewIframeOption): string { frameSrc: option.frameSrc, webUrl: option.webUrl, webpageUrl: option.webpageUrl, + pageUrl: option.pageUrl, + h5Url: option.h5Url, + link: option.link, + href: option.href, }) || pickUrlLike(option) || pickUrlLike(option.dataset) || @@ -225,7 +236,7 @@ function pickSrc(option: GoViewIframeOption): string { const listUrl = pickFromNested( option, (obj) => { - for (const key of ['sources', 'sourceList', 'urlList']) { + for (const key of ['sources', 'sourceList', 'urlList', 'srcList', 'iframeList']) { const v = pickFirstUrlFromList(obj[key]); if (v) return v; } diff --git a/packages/sdk/src/core/widgets/video.ts b/packages/sdk/src/core/widgets/video.ts index 105b3bb..47552ba 100644 --- a/packages/sdk/src/core/widgets/video.ts +++ b/packages/sdk/src/core/widgets/video.ts @@ -14,6 +14,13 @@ export interface GoViewVideoOption { srcUrl?: unknown; sourceUrl?: unknown; + // streaming-ish aliases + webrtcUrl?: unknown; + rtcUrl?: unknown; + wsUrl?: unknown; + srtUrl?: unknown; + dashUrl?: unknown; + // common alternative shapes sources?: unknown; sourceList?: unknown; @@ -204,6 +211,11 @@ function pickFirstUrlFromList(input: unknown): string { 'hlsUrl', 'flvUrl', 'm3u8Url', + 'webrtcUrl', + 'rtcUrl', + 'wsUrl', + 'srtUrl', + 'dashUrl', 'cameraUrl', 'cctvUrl', 'monitorUrl', @@ -242,6 +254,11 @@ function pickSrc(option: GoViewVideoOption): string { 'hlsUrl', 'flvUrl', 'm3u8Url', + 'webrtcUrl', + 'rtcUrl', + 'wsUrl', + 'srtUrl', + 'dashUrl', 'cameraUrl', 'cctvUrl', 'monitorUrl',