diff --git a/oxlint.json b/oxlint.json index ad197e7f4..7347fec94 100644 --- a/oxlint.json +++ b/oxlint.json @@ -91,11 +91,24 @@ } }, + { + "files": ["**/tools/ai-adapter.ts"], + "rules": { + "typescript/no-explicit-any": "off" + } + }, + { + "files": ["**/render/render-jsx.ts"], + "rules": { + "typescript/no-implied-eval": "off" + } + }, { "files": ["**/kiwi/kiwi-schema/**"], "rules": { "typescript/no-explicit-any": "off", "typescript/no-non-null-assertion": "off", + "typescript/no-implied-eval": "off", "typescript/prefer-for-of": "off", "typescript/prefer-optional-chain": "off", "typescript/consistent-type-imports": "off", diff --git a/packages/core/src/render/renderer.ts b/packages/core/src/render/renderer.ts index 811522aee..3506da64c 100644 --- a/packages/core/src/render/renderer.ts +++ b/packages/core/src/render/renderer.ts @@ -366,11 +366,7 @@ function applyLayoutOverrides( if (props.maxW !== undefined) o.width = Math.min(o.width ?? Infinity, props.maxW as number) } -function applyTextOverrides( - props: Record, - o: Partial, - parentLayout: SceneNode['layoutMode'] -): void { +function applyTextStyleOverrides(props: Record, o: Partial): void { const fontSize = props.size ?? props.fontSize if (typeof fontSize === 'number') o.fontSize = fontSize @@ -403,7 +399,13 @@ function applyTextOverrides( if (props.textAlign) { o.textAlignHorizontal = TEXT_ALIGN_MAP[props.textAlign as string] ?? 'LEFT' } +} +function applyTextAutoResize( + props: Record, + o: Partial, + parentLayout: SceneNode['layoutMode'] +): void { const w = props.w ?? props.width const hasExplicitWidth = w !== undefined const fillsParent = w === 'fill' || (props.grow as number) > 0 @@ -422,6 +424,15 @@ function applyTextOverrides( } } +function applyTextOverrides( + props: Record, + o: Partial, + parentLayout: SceneNode['layoutMode'] +): void { + applyTextStyleOverrides(props, o) + applyTextAutoResize(props, o, parentLayout) +} + function applyShapeAndEffectOverrides(props: Record, o: Partial): void { if (props.points !== undefined) o.pointCount = props.points as number if (props.innerRadius !== undefined) o.starInnerRadius = props.innerRadius as number diff --git a/packages/core/src/tools/create.ts b/packages/core/src/tools/create.ts index f1c0fc34b..441fe3d8e 100644 --- a/packages/core/src/tools/create.ts +++ b/packages/core/src/tools/create.ts @@ -1,12 +1,11 @@ import { parseColor } from '../color' import { fetchIcons, searchIconsBatch } from '../iconify' -import type { SceneNode } from '../scene-graph' import { defineTool, nodeSummary } from './schema' import type { FigmaAPI, FigmaNodeProxy } from '../figma-api' import type { Color } from '../types' -import type { Stroke, StrokeCap, StrokeJoin } from '../scene-graph' +import type { Stroke, StrokeCap, StrokeJoin, VectorNetwork } from '../scene-graph' export const createShape = defineTool({ name: 'create_shape', @@ -140,7 +139,7 @@ export const createVector = defineTool({ node.y = args.y if (args.name) node.name = args.name if (args.path) { - figma.graph.updateNode(node.id, { vectorNetwork: JSON.parse(args.path) as SceneNode['vectorNetwork'] }) + figma.graph.updateNode(node.id, { vectorNetwork: JSON.parse(args.path) as VectorNetwork }) } if (args.fill) { node.fills = [{ type: 'SOLID', color: parseColor(args.fill), opacity: 1, visible: true }] diff --git a/packages/core/src/tools/modify.ts b/packages/core/src/tools/modify.ts index bbfd9853f..325ad2ac8 100644 --- a/packages/core/src/tools/modify.ts +++ b/packages/core/src/tools/modify.ts @@ -1,7 +1,7 @@ /* eslint-disable max-lines -- property setters share common patterns, splitting would scatter related tools */ import { parseColor } from '../color' import { DEFAULT_SHADOW_COLOR } from '../constants' -import type { Effect, StyleRun } from '../scene-graph' +import type { CharacterStyleOverride, Effect, StyleRun } from '../scene-graph' import { defineTool } from './schema' @@ -81,14 +81,14 @@ export const setEffects = defineTool({ const isBlur = args.type === 'FOREGROUND_BLUR' || args.type === 'BACKGROUND_BLUR' const color = isBlur - ? { r: 0, g: 0, b: 0, a: 0 } + ? { r: 0, g: 0, b: 0, a: 1 } : (args.color ? parseColor(args.color) : { ...DEFAULT_SHADOW_COLOR }) const effect: Effect = { type: args.type as Effect['type'], visible: true, radius: args.radius ?? 4, color, - offset: isBlur ? { x: 0, y: 0 } : { x: args.offset_x ?? 0, y: args.offset_y ?? 4 }, + offset: { x: isBlur ? 0 : (args.offset_x ?? 0), y: isBlur ? 0 : (args.offset_y ?? 4) }, spread: isBlur ? 0 : (args.spread ?? 0) } @@ -385,11 +385,15 @@ export const setFontRange = defineTool({ execute: (figma, args) => { const node = figma.getNodeById(args.id) if (!node) return { error: `Node "${args.id}" not found` } - const style: StyleRun['style'] = {} + const style: CharacterStyleOverride = {} if (args.family) style.fontFamily = args.family if (args.size) style.fontSize = args.size - if (args.style) style.fontWeight = args.style === 'Bold' ? 700 : undefined - const run: StyleRun = { start: args.start, length: args.end - args.start, style } + if (args.style === 'italic' || args.style === 'Italic') style.italic = true + const run: StyleRun = { + start: args.start, + length: args.end - args.start, + style + } figma.graph.updateNode(node.id, { styleRuns: [...(figma.graph.getNode(node.id)?.styleRuns ?? []), run] }) diff --git a/packages/core/src/tools/variables.ts b/packages/core/src/tools/variables.ts index 48e513130..ab30ea31f 100644 --- a/packages/core/src/tools/variables.ts +++ b/packages/core/src/tools/variables.ts @@ -87,7 +87,7 @@ export const createVariable = defineTool({ args.name, args.type as VariableType, args.collection_id, - parsedValue as VariableValue | undefined + parsedValue as VariableValue ) return v } diff --git a/packages/core/src/tools/vector.ts b/packages/core/src/tools/vector.ts index c5dac4d42..2f333983d 100644 --- a/packages/core/src/tools/vector.ts +++ b/packages/core/src/tools/vector.ts @@ -1,5 +1,3 @@ -import type { SceneNode } from '../scene-graph' - import { defineTool, nodeSummary } from './schema' const CHUNK_SIZE = 0x8000 @@ -94,7 +92,7 @@ export const pathSet = defineTool({ const raw = figma.graph.getNode(args.id) if (!raw) return { error: `Node "${args.id}" not found` } const network = JSON.parse(args.path) - figma.graph.updateNode(args.id, { vectorNetwork: network } as Partial) + figma.graph.updateNode(args.id, { vectorNetwork: network }) return { id: args.id } } }) @@ -124,7 +122,8 @@ export const pathScale = defineTool({ s.tangentEnd.x *= factor s.tangentEnd.y *= factor } - figma.graph.updateNode(id, { vectorNetwork: vn } as Partial) + + figma.graph.updateNode(id, { vectorNetwork: vn }) return { id, factor } } }) @@ -159,7 +158,8 @@ export const pathFlip = defineTool({ if (axis === 'horizontal') s.tangentEnd.x = -s.tangentEnd.x else s.tangentEnd.y = -s.tangentEnd.y } - figma.graph.updateNode(id, { vectorNetwork: vn } as Partial) + + figma.graph.updateNode(id, { vectorNetwork: vn }) return { id, axis } } }) @@ -182,7 +182,8 @@ export const pathMove = defineTool({ v.x += dx v.y += dy } - figma.graph.updateNode(id, { vectorNetwork: vn } as Partial) + + figma.graph.updateNode(id, { vectorNetwork: vn }) return { id, dx, dy } } }) diff --git a/src/ai/chat-debug.ts b/src/ai/chat-debug.ts index 3b2f18ae8..afdb9ca60 100644 --- a/src/ai/chat-debug.ts +++ b/src/ai/chat-debug.ts @@ -248,7 +248,7 @@ export function serializeChatLog(messages: UIMessage[]): string { parts.push(` ${p.text as string}`) } else if (p.type === 'reasoning') { parts.push( - ` [reasoning] ${typeof p.text === 'string' ? p.text : typeof p.content === 'string' ? p.content : ''}` + ` [reasoning] ${typeof p.text === 'string' ? p.text : (typeof p.content === 'string' ? p.content : '')}` ) } else if ( p.type === 'tool-invocation' ||