sdk/editor: improve goView import sizing + add editor typecheck

This commit is contained in:
clawdbot 2026-01-28 00:09:18 +08:00
parent 102c4d67c6
commit c20e4796ae
2 changed files with 43 additions and 45 deletions

View File

@ -6,6 +6,7 @@
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"typecheck": "tsc -b --noEmit",
"lint": "eslint .",
"preview": "vite preview"
},

View File

@ -338,25 +338,53 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt
for (const raw of componentList) {
const c = unwrapComponent(raw);
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 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),
y: toNumber((c.attr as unknown as Record<string, unknown>).y, 0),
x: toNumber(attr.x, 0),
y: toNumber(attr.y, 0),
// 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),
h: toNumber((c.attr as unknown as Record<string, unknown>).h, optSize.h ?? 60),
w: toNumber(attr.w, optSize.w ?? defaults.w),
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);
nodes.push({
id: c.id ?? `import_text_${Math.random().toString(16).slice(2)}`,
type: 'text',
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,
@ -364,13 +392,13 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt
continue;
}
if (isImage(c) || looksLikeImageOption(option)) {
if (inferredType === 'image') {
const props = convertGoViewImageOptionToNodeProps(option as GoViewImageOption);
nodes.push({
id: c.id ?? `import_image_${Math.random().toString(16).slice(2)}`,
type: 'image',
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,
@ -378,14 +406,13 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt
continue;
}
// Prefer explicit component keys over heuristics.
if (isIframe(c)) {
if (inferredType === 'iframe') {
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),
zIndex,
locked: c.status?.lock ?? false,
hidden: c.status?.hide ?? false,
props,
@ -393,43 +420,13 @@ export function convertGoViewProjectToScreen(input: GoViewProjectLike | GoViewSt
continue;
}
if (isVideo(c)) {
if (inferredType === 'video') {
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;
}
// 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),
zIndex,
locked: c.status?.lock ?? false,
hidden: c.status?.hide ?? false,
props,