sdk: harden goView import (iframe/video/image)
This commit is contained in:
parent
c574d4e323
commit
d00544b0a7
@ -1,13 +1,16 @@
|
||||
import type { Screen } from './schema';
|
||||
import { convertGoViewProjectToScreen } from './goview/convert';
|
||||
|
||||
/**
|
||||
* goView JSON converter (stub).
|
||||
* goView JSON converter.
|
||||
*
|
||||
* The legacy goView format isn't implemented yet; this is a placeholder so we can
|
||||
* start wiring UI + migration flows without committing to the full mapping.
|
||||
* We keep this permissive because goView exports / storage snapshots vary across
|
||||
* versions and forks. The heavy lifting lives in `goview/convert.ts`.
|
||||
*/
|
||||
export function convertGoViewJSONToScreen(input: unknown): Screen {
|
||||
// keep reference to avoid unused-vars lint until implemented
|
||||
void input;
|
||||
throw new Error('convertGoViewJSONToScreen: not implemented yet');
|
||||
if (!input || typeof input !== 'object') {
|
||||
throw new Error('convertGoViewJSONToScreen: expected object');
|
||||
}
|
||||
|
||||
return convertGoViewProjectToScreen(input as unknown as object);
|
||||
}
|
||||
|
||||
@ -85,13 +85,40 @@ function isVideo(c: GoViewComponentLike): boolean {
|
||||
return k.includes('mp4') || k.includes('media') || k.includes('player');
|
||||
}
|
||||
|
||||
function pick<T>(...values: Array<T | undefined | null>): T | undefined {
|
||||
for (const v of values) {
|
||||
if (v !== undefined && v !== null) return v as T;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewStorageLike): Screen {
|
||||
const editCanvasConfig = (input as GoViewStorageLike).editCanvasConfig;
|
||||
// goView exports vary a lot; attempt a few common nesting shapes.
|
||||
const root = input as unknown as Record<string, unknown>;
|
||||
const data = (root.data as Record<string, unknown> | undefined) ?? undefined;
|
||||
const state = (root.state as Record<string, unknown> | undefined) ?? undefined;
|
||||
const project = (root.project as Record<string, unknown> | undefined) ?? undefined;
|
||||
|
||||
const editCanvasConfig = pick<GoViewEditCanvasConfigLike>(
|
||||
(input as GoViewStorageLike).editCanvasConfig,
|
||||
data?.editCanvasConfig as GoViewEditCanvasConfigLike | undefined,
|
||||
state?.editCanvasConfig as GoViewEditCanvasConfigLike | undefined,
|
||||
project?.editCanvasConfig as GoViewEditCanvasConfigLike | undefined,
|
||||
);
|
||||
|
||||
const width =
|
||||
editCanvasConfig?.width ?? (input as GoViewProjectLike).canvas?.width ?? (input as GoViewProjectLike).width ?? 1920;
|
||||
editCanvasConfig?.width ??
|
||||
(input as GoViewProjectLike).canvas?.width ??
|
||||
(input as GoViewProjectLike).width ??
|
||||
(data?.width as number | undefined) ??
|
||||
1920;
|
||||
|
||||
const height =
|
||||
editCanvasConfig?.height ?? (input as GoViewProjectLike).canvas?.height ?? (input as GoViewProjectLike).height ?? 1080;
|
||||
editCanvasConfig?.height ??
|
||||
(input as GoViewProjectLike).canvas?.height ??
|
||||
(input as GoViewProjectLike).height ??
|
||||
(data?.height as number | undefined) ??
|
||||
1080;
|
||||
|
||||
const name = editCanvasConfig?.projectName ?? 'Imported Project';
|
||||
const background = editCanvasConfig?.background;
|
||||
@ -105,7 +132,13 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt
|
||||
nodes: [],
|
||||
});
|
||||
|
||||
const componentList = (input as GoViewStorageLike).componentList ?? (input as GoViewProjectLike).componentList ?? [];
|
||||
const componentList =
|
||||
(input as GoViewStorageLike).componentList ??
|
||||
(input as GoViewProjectLike).componentList ??
|
||||
(data?.componentList as GoViewComponentLike[] | undefined) ??
|
||||
(state?.componentList as GoViewComponentLike[] | undefined) ??
|
||||
(project?.componentList as GoViewComponentLike[] | undefined) ??
|
||||
[];
|
||||
|
||||
const nodes: Array<TextWidgetNode | ImageWidgetNode | IframeWidgetNode | VideoWidgetNode> = [];
|
||||
|
||||
|
||||
@ -5,9 +5,9 @@ import type { IframeWidgetNode } from '../schema';
|
||||
* Keep it permissive and normalize the common fields.
|
||||
*/
|
||||
export interface GoViewIframeOption {
|
||||
dataset?: string;
|
||||
src?: string;
|
||||
url?: string;
|
||||
dataset?: unknown;
|
||||
src?: unknown;
|
||||
url?: unknown;
|
||||
borderRadius?: number;
|
||||
}
|
||||
|
||||
@ -16,8 +16,23 @@ export interface GoViewIframeOption {
|
||||
*/
|
||||
export type LegacyIframeOption = GoViewIframeOption;
|
||||
|
||||
function asString(v: unknown): string {
|
||||
if (typeof v === 'string') return v;
|
||||
if (!v) return '';
|
||||
|
||||
// Some goView widgets store data as { value: '...' } or { url: '...' }.
|
||||
if (typeof v === 'object') {
|
||||
const obj = v as Record<string, unknown>;
|
||||
if (typeof obj.value === 'string') return obj.value;
|
||||
if (typeof obj.url === 'string') return obj.url;
|
||||
if (typeof obj.src === 'string') return obj.src;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function pickSrc(option: GoViewIframeOption): string {
|
||||
return option.dataset ?? option.src ?? option.url ?? '';
|
||||
return asString(option.dataset) || asString(option.src) || asString(option.url);
|
||||
}
|
||||
|
||||
export function convertGoViewIframeOptionToNodeProps(option: GoViewIframeOption): IframeWidgetNode['props'] {
|
||||
|
||||
@ -8,28 +8,51 @@ export interface GoViewImageOption {
|
||||
/**
|
||||
* Common in existing legacy widgets (same as iframe/video).
|
||||
*/
|
||||
dataset?: string;
|
||||
dataset?: unknown;
|
||||
|
||||
/**
|
||||
* Other variants seen in the wild.
|
||||
*/
|
||||
src?: string;
|
||||
url?: string;
|
||||
src?: unknown;
|
||||
url?: unknown;
|
||||
|
||||
/**
|
||||
* Styling.
|
||||
*/
|
||||
fit?: ImageWidgetNode['props']['fit'];
|
||||
objectFit?: ImageWidgetNode['props']['fit'];
|
||||
fit?: unknown;
|
||||
objectFit?: unknown;
|
||||
borderRadius?: number;
|
||||
}
|
||||
|
||||
function asString(v: unknown): string {
|
||||
if (typeof v === 'string') return v;
|
||||
if (!v) return '';
|
||||
|
||||
// Some goView widgets store data as { value: '...' } or { url: '...' }.
|
||||
if (typeof v === 'object') {
|
||||
const obj = v as Record<string, unknown>;
|
||||
if (typeof obj.value === 'string') return obj.value;
|
||||
if (typeof obj.url === 'string') return obj.url;
|
||||
if (typeof obj.src === 'string') return obj.src;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function pickSrc(option: GoViewImageOption): string {
|
||||
return option.dataset ?? option.src ?? option.url ?? '';
|
||||
return asString(option.dataset) || asString(option.src) || asString(option.url);
|
||||
}
|
||||
|
||||
function pickFit(option: GoViewImageOption): ImageWidgetNode['props']['fit'] | undefined {
|
||||
return option.fit ?? option.objectFit;
|
||||
const raw = asString(option.fit) || asString(option.objectFit);
|
||||
if (!raw) return undefined;
|
||||
|
||||
const v = raw.toLowerCase();
|
||||
if (v === 'contain' || v === 'cover' || v === 'fill' || v === 'none' || v === 'scale-down') {
|
||||
return v as ImageWidgetNode['props']['fit'];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function convertGoViewImageOptionToNodeProps(option: GoViewImageOption): ImageWidgetNode['props'] {
|
||||
|
||||
@ -5,15 +5,15 @@ import type { VideoWidgetNode } from '../schema';
|
||||
* Keep it permissive and normalize the common fields.
|
||||
*/
|
||||
export interface GoViewVideoOption {
|
||||
dataset?: string;
|
||||
src?: string;
|
||||
url?: string;
|
||||
dataset?: unknown;
|
||||
src?: unknown;
|
||||
url?: unknown;
|
||||
|
||||
loop?: boolean;
|
||||
muted?: boolean;
|
||||
|
||||
fit?: VideoWidgetNode['props']['fit'];
|
||||
objectFit?: VideoWidgetNode['props']['fit'];
|
||||
fit?: unknown;
|
||||
objectFit?: unknown;
|
||||
|
||||
borderRadius?: number;
|
||||
}
|
||||
@ -23,12 +23,35 @@ export interface GoViewVideoOption {
|
||||
*/
|
||||
export type LegacyVideoOption = GoViewVideoOption;
|
||||
|
||||
function asString(v: unknown): string {
|
||||
if (typeof v === 'string') return v;
|
||||
if (!v) return '';
|
||||
|
||||
if (typeof v === 'object') {
|
||||
const obj = v as Record<string, unknown>;
|
||||
if (typeof obj.value === 'string') return obj.value;
|
||||
if (typeof obj.url === 'string') return obj.url;
|
||||
if (typeof obj.src === 'string') return obj.src;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function pickSrc(option: GoViewVideoOption): string {
|
||||
return option.dataset ?? option.src ?? option.url ?? '';
|
||||
return asString(option.dataset) || asString(option.src) || asString(option.url);
|
||||
}
|
||||
|
||||
function pickFit(option: GoViewVideoOption): VideoWidgetNode['props']['fit'] | undefined {
|
||||
return option.fit ?? option.objectFit;
|
||||
const raw = asString(option.fit) || asString(option.objectFit);
|
||||
if (!raw) return undefined;
|
||||
|
||||
// normalize common variants
|
||||
const v = raw.toLowerCase();
|
||||
if (v === 'contain' || v === 'cover' || v === 'fill' || v === 'none' || v === 'scale-down') {
|
||||
return v as VideoWidgetNode['props']['fit'];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function convertGoViewVideoOptionToNodeProps(option: GoViewVideoOption): VideoWidgetNode['props'] {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user