diff --git a/packages/sdk/src/core/goview/convert.ts b/packages/sdk/src/core/goview/convert.ts index 9be5eb0..6408f00 100644 --- a/packages/sdk/src/core/goview/convert.ts +++ b/packages/sdk/src/core/goview/convert.ts @@ -158,6 +158,9 @@ function looksLikeIframeOption(option: unknown): boolean { if (typeof option === 'object') { const o = option as Record; if ('iframeUrl' in o || 'iframeSrc' in o || 'embedUrl' in o) return true; + + // Some exports store raw HTML instead of a URL. + if ('html' in o || 'htmlContent' in o || 'content' in o || 'template' in o) return true; } const url = pickUrlLike(option); @@ -181,7 +184,19 @@ function looksLikeVideoOption(option: unknown): boolean { // Prefer explicit video-ish keys when option is an object. if (typeof option === 'object') { const o = option as Record; - if ('videoUrl' in o || 'videoSrc' in o || 'mp4' in o || 'm3u8' in o || 'flv' in o || 'hls' in o || 'rtsp' in o) { + if ( + 'videoUrl' in o || + 'videoSrc' in o || + 'mp4' in o || + 'm3u8' in o || + 'flv' in o || + 'hls' in o || + 'rtsp' in o || + // list-ish shapes + 'sources' in o || + 'sourceList' in o || + 'urlList' in o + ) { return true; } } diff --git a/packages/sdk/src/core/widgets/iframe.ts b/packages/sdk/src/core/widgets/iframe.ts index d00eddb..d3e2e34 100644 --- a/packages/sdk/src/core/widgets/iframe.ts +++ b/packages/sdk/src/core/widgets/iframe.ts @@ -17,9 +17,29 @@ export interface GoViewIframeOption { */ export type LegacyIframeOption = GoViewIframeOption; +function toDataHtmlUrl(html: string): string { + // Keep this simple and safe: use a data URL so we can render the provided HTML + // without needing an external host. + // NOTE: encodeURIComponent is important to preserve characters + avoid breaking the URL. + return `data:text/html;charset=utf-8,${encodeURIComponent(html)}`; +} + function pickSrc(option: GoViewIframeOption): string { // Prefer the whole option first (covers iframeUrl/embedUrl variants directly on the object). - return pickUrlLike(option) || pickUrlLike(option.dataset) || pickUrlLike(option.src) || pickUrlLike(option.url); + const url = pickUrlLike(option) || pickUrlLike(option.dataset) || pickUrlLike(option.src) || pickUrlLike(option.url); + if (url) return url; + + // Some goView / low-code exports store raw HTML instead of a URL. + const html = pickFromNested( + option, + (obj) => { + const v = obj.html ?? obj.htmlContent ?? obj.content ?? obj.template; + return typeof v === 'string' ? v : undefined; + }, + 2, + ); + + return html ? toDataHtmlUrl(html) : ''; } function toMaybeNumber(v: unknown): number | undefined { diff --git a/packages/sdk/src/core/widgets/urlLike.ts b/packages/sdk/src/core/widgets/urlLike.ts index dbe1f54..56d50db 100644 --- a/packages/sdk/src/core/widgets/urlLike.ts +++ b/packages/sdk/src/core/widgets/urlLike.ts @@ -34,6 +34,7 @@ function pickUrlLikeInner(input: unknown, depth: number): string { for (const key of [ 'value', 'url', + 'uri', 'src', 'href', 'link', @@ -86,6 +87,10 @@ function pickUrlLikeInner(input: unknown, depth: number): string { 'props', 'source', 'media', + // common list-ish wrappers for media sources + 'sources', + 'sourceList', + 'urlList', // widget-ish wrappers seen in exports 'iframe', 'video',