feat(sdk): improve goView iframe/video import
This commit is contained in:
parent
97a2eccc92
commit
b67d6be00f
@ -9,6 +9,17 @@ export interface GoViewIframeOption {
|
||||
dataset?: unknown;
|
||||
src?: unknown;
|
||||
url?: unknown;
|
||||
|
||||
// common alternative shapes
|
||||
iframeUrl?: unknown;
|
||||
iframeSrc?: unknown;
|
||||
embedUrl?: unknown;
|
||||
|
||||
// list-ish shapes (some low-code editors model embeds as a list even for a single item)
|
||||
sources?: unknown;
|
||||
sourceList?: unknown;
|
||||
urlList?: unknown;
|
||||
|
||||
borderRadius?: number;
|
||||
}
|
||||
|
||||
@ -29,24 +40,6 @@ function looksLikeHtml(input: string): boolean {
|
||||
return trimmed.startsWith('<') && trimmed.includes('>');
|
||||
}
|
||||
|
||||
function pickSrc(option: GoViewIframeOption): string {
|
||||
// Prefer the whole option first (covers iframeUrl/embedUrl variants directly on the object).
|
||||
const url = pickUrlLike(option) || pickUrlLike(option.dataset) || pickUrlLike(option.src) || pickUrlLike(option.url);
|
||||
if (url) return looksLikeHtml(url) ? toDataHtmlUrl(url) : url;
|
||||
|
||||
// Some goView / low-code exports store raw HTML instead of a URL.
|
||||
const html = pickFromNested(
|
||||
option,
|
||||
(obj) => {
|
||||
const v = obj.srcdoc ?? obj.srcDoc ?? 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 {
|
||||
if (typeof v === 'number' && Number.isFinite(v)) return v;
|
||||
if (typeof v === 'string') {
|
||||
@ -56,7 +49,11 @@ function toMaybeNumber(v: unknown): number | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function pickFromNested<T>(input: unknown, picker: (obj: Record<string, unknown>) => T | undefined, depth: number): T | undefined {
|
||||
function pickFromNested<T>(
|
||||
input: unknown,
|
||||
picker: (obj: Record<string, unknown>) => T | undefined,
|
||||
depth: number,
|
||||
): T | undefined {
|
||||
if (!input || typeof input !== 'object') return undefined;
|
||||
const obj = input as Record<string, unknown>;
|
||||
|
||||
@ -72,6 +69,60 @@ function pickFromNested<T>(input: unknown, picker: (obj: Record<string, unknown>
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function pickFirstUrlFromList(input: unknown): string {
|
||||
if (!input) return '';
|
||||
if (typeof input === 'string') return input;
|
||||
|
||||
if (Array.isArray(input)) {
|
||||
for (const item of input) {
|
||||
const v = pickFirstUrlFromList(item);
|
||||
if (v) return v;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
if (typeof input !== 'object') return '';
|
||||
return pickUrlLike(input, 2);
|
||||
}
|
||||
|
||||
function pickSrc(option: GoViewIframeOption): string {
|
||||
// 1) Prefer explicit iframe-ish URL fields.
|
||||
const url =
|
||||
pickUrlLike({ iframeUrl: option.iframeUrl, iframeSrc: option.iframeSrc, embedUrl: option.embedUrl }) ||
|
||||
pickUrlLike(option) ||
|
||||
pickUrlLike(option.dataset) ||
|
||||
pickUrlLike(option.src) ||
|
||||
pickUrlLike(option.url);
|
||||
|
||||
if (url) return looksLikeHtml(url) ? toDataHtmlUrl(url) : url;
|
||||
|
||||
// 2) Some exports store raw HTML instead of a URL.
|
||||
const html = pickFromNested(
|
||||
option,
|
||||
(obj) => {
|
||||
const v = obj.srcdoc ?? obj.srcDoc ?? obj.html ?? obj.htmlContent ?? obj.content ?? obj.template;
|
||||
return typeof v === 'string' ? v : undefined;
|
||||
},
|
||||
2,
|
||||
);
|
||||
if (html) return toDataHtmlUrl(html);
|
||||
|
||||
// 3) List-ish shapes.
|
||||
const listUrl = pickFromNested(
|
||||
option,
|
||||
(obj) => {
|
||||
for (const key of ['sources', 'sourceList', 'urlList']) {
|
||||
const v = pickFirstUrlFromList(obj[key]);
|
||||
if (v) return v;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
2,
|
||||
);
|
||||
|
||||
return listUrl ? (looksLikeHtml(listUrl) ? toDataHtmlUrl(listUrl) : listUrl) : '';
|
||||
}
|
||||
|
||||
function pickBorderRadius(option: GoViewIframeOption): number | undefined {
|
||||
const direct = toMaybeNumber(option.borderRadius);
|
||||
if (direct !== undefined) return direct;
|
||||
|
||||
@ -10,6 +10,14 @@ export interface GoViewVideoOption {
|
||||
src?: unknown;
|
||||
url?: unknown;
|
||||
|
||||
// common alternative shapes
|
||||
sources?: unknown;
|
||||
sourceList?: unknown;
|
||||
urlList?: unknown;
|
||||
srcList?: unknown;
|
||||
playList?: unknown;
|
||||
playlist?: unknown;
|
||||
|
||||
autoplay?: boolean;
|
||||
autoPlay?: boolean;
|
||||
isAutoPlay?: boolean;
|
||||
@ -28,11 +36,6 @@ export interface GoViewVideoOption {
|
||||
*/
|
||||
export type LegacyVideoOption = GoViewVideoOption;
|
||||
|
||||
function pickSrc(option: GoViewVideoOption): string {
|
||||
// Prefer the whole option first (covers videoUrl/mp4/m3u8/flv/etc directly on the object).
|
||||
return pickUrlLike(option) || pickUrlLike(option.dataset) || pickUrlLike(option.src) || pickUrlLike(option.url);
|
||||
}
|
||||
|
||||
function asString(v: unknown): string {
|
||||
if (typeof v === 'string') return v;
|
||||
if (!v) return '';
|
||||
@ -59,7 +62,11 @@ function toMaybeNumber(v: unknown): number | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function pickFromNested<T>(input: unknown, picker: (obj: Record<string, unknown>) => T | undefined, depth: number): T | undefined {
|
||||
function pickFromNested<T>(
|
||||
input: unknown,
|
||||
picker: (obj: Record<string, unknown>) => T | undefined,
|
||||
depth: number,
|
||||
): T | undefined {
|
||||
if (!input || typeof input !== 'object') return undefined;
|
||||
const obj = input as Record<string, unknown>;
|
||||
|
||||
@ -75,6 +82,88 @@ function pickFromNested<T>(input: unknown, picker: (obj: Record<string, unknown>
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function pickFirstUrlFromList(input: unknown): string {
|
||||
if (!input) return '';
|
||||
|
||||
// strings, objects, or nested list wrappers are all accepted.
|
||||
if (typeof input === 'string') return input;
|
||||
|
||||
if (Array.isArray(input)) {
|
||||
for (const item of input) {
|
||||
const v = pickFirstUrlFromList(item);
|
||||
if (v) return v;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
if (typeof input !== 'object') return '';
|
||||
|
||||
const obj = input as Record<string, unknown>;
|
||||
|
||||
// common media list item shapes
|
||||
// - { src/url/value }
|
||||
// - { playUrl }
|
||||
// - { mp4/m3u8/flv/hls/rtsp/rtmp }
|
||||
for (const key of ['mp4', 'm3u8', 'flv', 'hls', 'rtsp', 'rtmp', 'videoUrl', 'videoSrc', 'playUrl', 'src', 'url', 'value']) {
|
||||
const v = obj[key];
|
||||
if (typeof v === 'string' && v) return v;
|
||||
}
|
||||
|
||||
// nested wrappers like { source: { url } } or { data: {...} }
|
||||
return pickUrlLike(obj, 2);
|
||||
}
|
||||
|
||||
function pickSrc(option: GoViewVideoOption): string {
|
||||
// Prefer explicit video-ish keys in a stable order, then fall back to permissive URL picking.
|
||||
const fromDirect = pickFromNested(
|
||||
option,
|
||||
(obj) => {
|
||||
for (const key of [
|
||||
// common explicit keys
|
||||
'videoUrl',
|
||||
'videoSrc',
|
||||
// format-specific keys
|
||||
'm3u8',
|
||||
'hls',
|
||||
'mp4',
|
||||
'flv',
|
||||
// streaming/camera keys
|
||||
'rtsp',
|
||||
'rtmp',
|
||||
'stream',
|
||||
'streamUrl',
|
||||
// generic fallbacks
|
||||
'src',
|
||||
'url',
|
||||
'value',
|
||||
]) {
|
||||
const v = obj[key];
|
||||
if (typeof v === 'string' && v) return v;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
2,
|
||||
);
|
||||
if (fromDirect) return fromDirect;
|
||||
|
||||
// Many exports use list-ish shapes: sources/sourceList/urlList/etc.
|
||||
const fromList = pickFromNested(
|
||||
option,
|
||||
(obj) => {
|
||||
for (const key of ['sources', 'sourceList', 'urlList', 'srcList', 'playList', 'playlist']) {
|
||||
const v = pickFirstUrlFromList(obj[key]);
|
||||
if (v) return v;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
2,
|
||||
);
|
||||
if (fromList) return fromList;
|
||||
|
||||
// Last resort: permissive URL-like picking across option/dataset/src/url.
|
||||
return pickUrlLike(option) || pickUrlLike(option.dataset) || pickUrlLike(option.src) || pickUrlLike(option.url);
|
||||
}
|
||||
|
||||
function pickBorderRadius(option: GoViewVideoOption): number | undefined {
|
||||
const direct = toMaybeNumber(option.borderRadius);
|
||||
if (direct !== undefined) return direct;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user