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;
|
dataset?: unknown;
|
||||||
src?: unknown;
|
src?: unknown;
|
||||||
url?: 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;
|
borderRadius?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,24 +40,6 @@ function looksLikeHtml(input: string): boolean {
|
|||||||
return trimmed.startsWith('<') && trimmed.includes('>');
|
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 {
|
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') {
|
||||||
@ -56,7 +49,11 @@ function toMaybeNumber(v: unknown): number | undefined {
|
|||||||
return 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;
|
if (!input || typeof input !== 'object') return undefined;
|
||||||
const obj = input as Record<string, unknown>;
|
const obj = input as Record<string, unknown>;
|
||||||
|
|
||||||
@ -72,6 +69,60 @@ function pickFromNested<T>(input: unknown, picker: (obj: Record<string, unknown>
|
|||||||
return undefined;
|
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 {
|
function pickBorderRadius(option: GoViewIframeOption): number | undefined {
|
||||||
const direct = toMaybeNumber(option.borderRadius);
|
const direct = toMaybeNumber(option.borderRadius);
|
||||||
if (direct !== undefined) return direct;
|
if (direct !== undefined) return direct;
|
||||||
|
|||||||
@ -10,6 +10,14 @@ export interface GoViewVideoOption {
|
|||||||
src?: unknown;
|
src?: unknown;
|
||||||
url?: unknown;
|
url?: unknown;
|
||||||
|
|
||||||
|
// common alternative shapes
|
||||||
|
sources?: unknown;
|
||||||
|
sourceList?: unknown;
|
||||||
|
urlList?: unknown;
|
||||||
|
srcList?: unknown;
|
||||||
|
playList?: unknown;
|
||||||
|
playlist?: unknown;
|
||||||
|
|
||||||
autoplay?: boolean;
|
autoplay?: boolean;
|
||||||
autoPlay?: boolean;
|
autoPlay?: boolean;
|
||||||
isAutoPlay?: boolean;
|
isAutoPlay?: boolean;
|
||||||
@ -28,11 +36,6 @@ export interface GoViewVideoOption {
|
|||||||
*/
|
*/
|
||||||
export type LegacyVideoOption = 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 {
|
function asString(v: unknown): string {
|
||||||
if (typeof v === 'string') return v;
|
if (typeof v === 'string') return v;
|
||||||
if (!v) return '';
|
if (!v) return '';
|
||||||
@ -59,7 +62,11 @@ function toMaybeNumber(v: unknown): number | undefined {
|
|||||||
return 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;
|
if (!input || typeof input !== 'object') return undefined;
|
||||||
const obj = input as Record<string, unknown>;
|
const obj = input as Record<string, unknown>;
|
||||||
|
|
||||||
@ -75,6 +82,88 @@ function pickFromNested<T>(input: unknown, picker: (obj: Record<string, unknown>
|
|||||||
return undefined;
|
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 {
|
function pickBorderRadius(option: GoViewVideoOption): number | undefined {
|
||||||
const direct = toMaybeNumber(option.borderRadius);
|
const direct = toMaybeNumber(option.borderRadius);
|
||||||
if (direct !== undefined) return direct;
|
if (direct !== undefined) return direct;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user