sdk/editor: improve legacy import sizing + add editor typecheck
This commit is contained in:
parent
704e29a6d8
commit
4ca9f59737
@ -6,6 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
|
"typecheck": "tsc -b --noEmit",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -338,25 +338,53 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt
|
|||||||
for (const raw of componentList) {
|
for (const raw of componentList) {
|
||||||
const c = unwrapComponent(raw);
|
const c = unwrapComponent(raw);
|
||||||
const option = optionOf(c);
|
const option = optionOf(c);
|
||||||
|
|
||||||
|
// We try to infer the widget kind early so we can pick better default sizes
|
||||||
|
// when exports omit sizing information.
|
||||||
|
const inferredType: 'text' | 'image' | 'iframe' | 'video' | undefined = isTextCommon(c)
|
||||||
|
? 'text'
|
||||||
|
: isImage(c) || looksLikeImageOption(option)
|
||||||
|
? 'image'
|
||||||
|
: // Important: run video checks before iframe checks; iframe URL detection is broader.
|
||||||
|
isVideo(c) || looksLikeVideoOption(option)
|
||||||
|
? 'video'
|
||||||
|
: isIframe(c) || looksLikeIframeOption(option)
|
||||||
|
? 'iframe'
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const defaults =
|
||||||
|
inferredType === 'text'
|
||||||
|
? { w: 320, h: 60 }
|
||||||
|
: inferredType === 'image'
|
||||||
|
? { w: 320, h: 180 }
|
||||||
|
: inferredType === 'iframe'
|
||||||
|
? { w: 480, h: 270 }
|
||||||
|
: inferredType === 'video'
|
||||||
|
? { w: 480, h: 270 }
|
||||||
|
: { w: 320, h: 60 };
|
||||||
|
|
||||||
const optSize = pickSizeLike(option);
|
const optSize = pickSizeLike(option);
|
||||||
|
|
||||||
const rect = c.attr
|
const attr = c.attr as unknown as Record<string, unknown> | undefined;
|
||||||
|
const rect = attr
|
||||||
? {
|
? {
|
||||||
x: toNumber((c.attr as unknown as Record<string, unknown>).x, 0),
|
x: toNumber(attr.x, 0),
|
||||||
y: toNumber((c.attr as unknown as Record<string, unknown>).y, 0),
|
y: toNumber(attr.y, 0),
|
||||||
// Prefer explicit attr sizing, but fall back to option sizing when missing.
|
// Prefer explicit attr sizing, but fall back to option sizing when missing.
|
||||||
w: toNumber((c.attr as unknown as Record<string, unknown>).w, optSize.w ?? 320),
|
w: toNumber(attr.w, optSize.w ?? defaults.w),
|
||||||
h: toNumber((c.attr as unknown as Record<string, unknown>).h, optSize.h ?? 60),
|
h: toNumber(attr.h, optSize.h ?? defaults.h),
|
||||||
}
|
}
|
||||||
: { x: 0, y: 0, w: optSize.w ?? 320, h: optSize.h ?? 60 };
|
: { x: 0, y: 0, w: optSize.w ?? defaults.w, h: optSize.h ?? defaults.h };
|
||||||
|
|
||||||
if (isTextCommon(c)) {
|
const zIndex = attr?.zIndex === undefined ? undefined : toNumber(attr.zIndex, 0);
|
||||||
|
|
||||||
|
if (inferredType === 'text') {
|
||||||
const props = convertGoViewTextOptionToNodeProps(option as GoViewTextOption);
|
const props = convertGoViewTextOptionToNodeProps(option as GoViewTextOption);
|
||||||
nodes.push({
|
nodes.push({
|
||||||
id: c.id ?? `import_text_${Math.random().toString(16).slice(2)}`,
|
id: c.id ?? `import_text_${Math.random().toString(16).slice(2)}`,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
rect,
|
rect,
|
||||||
zIndex: c.attr?.zIndex === undefined ? undefined : toNumber((c.attr as unknown as Record<string, unknown>).zIndex, 0),
|
zIndex,
|
||||||
locked: c.status?.lock ?? false,
|
locked: c.status?.lock ?? false,
|
||||||
hidden: c.status?.hide ?? false,
|
hidden: c.status?.hide ?? false,
|
||||||
props,
|
props,
|
||||||
@ -364,13 +392,13 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isImage(c) || looksLikeImageOption(option)) {
|
if (inferredType === 'image') {
|
||||||
const props = convertGoViewImageOptionToNodeProps(option as GoViewImageOption);
|
const props = convertGoViewImageOptionToNodeProps(option as GoViewImageOption);
|
||||||
nodes.push({
|
nodes.push({
|
||||||
id: c.id ?? `import_image_${Math.random().toString(16).slice(2)}`,
|
id: c.id ?? `import_image_${Math.random().toString(16).slice(2)}`,
|
||||||
type: 'image',
|
type: 'image',
|
||||||
rect,
|
rect,
|
||||||
zIndex: c.attr?.zIndex === undefined ? undefined : toNumber((c.attr as unknown as Record<string, unknown>).zIndex, 0),
|
zIndex,
|
||||||
locked: c.status?.lock ?? false,
|
locked: c.status?.lock ?? false,
|
||||||
hidden: c.status?.hide ?? false,
|
hidden: c.status?.hide ?? false,
|
||||||
props,
|
props,
|
||||||
@ -378,14 +406,13 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefer explicit component keys over heuristics.
|
if (inferredType === 'iframe') {
|
||||||
if (isIframe(c)) {
|
|
||||||
const props = convertGoViewIframeOptionToNodeProps(option as GoViewIframeOption);
|
const props = convertGoViewIframeOptionToNodeProps(option as GoViewIframeOption);
|
||||||
nodes.push({
|
nodes.push({
|
||||||
id: c.id ?? `import_iframe_${Math.random().toString(16).slice(2)}`,
|
id: c.id ?? `import_iframe_${Math.random().toString(16).slice(2)}`,
|
||||||
type: 'iframe',
|
type: 'iframe',
|
||||||
rect,
|
rect,
|
||||||
zIndex: c.attr?.zIndex === undefined ? undefined : toNumber((c.attr as unknown as Record<string, unknown>).zIndex, 0),
|
zIndex,
|
||||||
locked: c.status?.lock ?? false,
|
locked: c.status?.lock ?? false,
|
||||||
hidden: c.status?.hide ?? false,
|
hidden: c.status?.hide ?? false,
|
||||||
props,
|
props,
|
||||||
@ -393,43 +420,13 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isVideo(c)) {
|
if (inferredType === 'video') {
|
||||||
const props = convertGoViewVideoOptionToNodeProps(option as GoViewVideoOption);
|
const props = convertGoViewVideoOptionToNodeProps(option as GoViewVideoOption);
|
||||||
nodes.push({
|
nodes.push({
|
||||||
id: c.id ?? `import_video_${Math.random().toString(16).slice(2)}`,
|
id: c.id ?? `import_video_${Math.random().toString(16).slice(2)}`,
|
||||||
type: 'video',
|
type: 'video',
|
||||||
rect,
|
rect,
|
||||||
zIndex: c.attr?.zIndex === undefined ? undefined : toNumber((c.attr as unknown as Record<string, unknown>).zIndex, 0),
|
zIndex,
|
||||||
locked: c.status?.lock ?? false,
|
|
||||||
hidden: c.status?.hide ?? false,
|
|
||||||
props,
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Heuristic fallback: distinguish common URL patterns.
|
|
||||||
// Important: run video checks before iframe checks; iframe URL detection is broader.
|
|
||||||
if (looksLikeVideoOption(option)) {
|
|
||||||
const props = convertGoViewVideoOptionToNodeProps(option as GoViewVideoOption);
|
|
||||||
nodes.push({
|
|
||||||
id: c.id ?? `import_video_${Math.random().toString(16).slice(2)}`,
|
|
||||||
type: 'video',
|
|
||||||
rect,
|
|
||||||
zIndex: c.attr?.zIndex === undefined ? undefined : toNumber((c.attr as unknown as Record<string, unknown>).zIndex, 0),
|
|
||||||
locked: c.status?.lock ?? false,
|
|
||||||
hidden: c.status?.hide ?? false,
|
|
||||||
props,
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (looksLikeIframeOption(option)) {
|
|
||||||
const props = convertGoViewIframeOptionToNodeProps(option as GoViewIframeOption);
|
|
||||||
nodes.push({
|
|
||||||
id: c.id ?? `import_iframe_${Math.random().toString(16).slice(2)}`,
|
|
||||||
type: 'iframe',
|
|
||||||
rect,
|
|
||||||
zIndex: c.attr?.zIndex === undefined ? undefined : toNumber((c.attr as unknown as Record<string, unknown>).zIndex, 0),
|
|
||||||
locked: c.status?.lock ?? false,
|
locked: c.status?.lock ?? false,
|
||||||
hidden: c.status?.hide ?? false,
|
hidden: c.status?.hide ?? false,
|
||||||
props,
|
props,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user