refactor(core): avoid record casts for dynamic writes
- Use KiwiNodeChange index signature for raw Figma field assignment - Type preserved raw NodeChange keys with keyof NodeChange - Replace scene graph property write casts with a typed setter
This commit is contained in:
parent
22280cc758
commit
7f2c21bb23
|
|
@ -823,7 +823,7 @@ export const FIGMA_RAW_NODE_FIELD_KEYS = [
|
|||
'vectorData',
|
||||
'fillGeometry',
|
||||
'strokeGeometry'
|
||||
]
|
||||
] as const satisfies readonly (keyof NodeChange)[]
|
||||
|
||||
function extractFigmaRawGeometry(
|
||||
nc: NodeChange,
|
||||
|
|
@ -831,7 +831,7 @@ function extractFigmaRawGeometry(
|
|||
): Pick<SceneNode['source']['fig'], 'rawSize' | 'rawTransform' | 'rawNodeFields'> {
|
||||
const rawNodeFields: Record<string, unknown> = {}
|
||||
for (const key of FIGMA_RAW_NODE_FIELD_KEYS) {
|
||||
const value = (nc as Record<string, unknown>)[key]
|
||||
const value = nc[key]
|
||||
if (value !== undefined) rawNodeFields[key] = preserveFigmaPayloadBlobs(value, blobs)
|
||||
}
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -309,9 +309,9 @@ function applyRawFigmaNodeFields(
|
|||
blobIndexByHex: context.blobIndexByHex,
|
||||
includePaintVariables: true,
|
||||
includeVariableMaps: true
|
||||
}) as Record<string, unknown>
|
||||
for (const key of Object.keys(materialized)) {
|
||||
if (RAW_FIELDS_OVERRIDE_BLOCKLIST.has(key)) continue
|
||||
}) as Partial<KiwiNodeChange>
|
||||
for (const key of Object.keys(materialized) as (keyof KiwiNodeChange)[]) {
|
||||
if (RAW_FIELDS_OVERRIDE_BLOCKLIST.has(String(key))) continue
|
||||
// For paint arrays on imported nodes, the raw NC data preserves the
|
||||
// original opacity/color.a split (e.g. opacity=0 for invisible strokes).
|
||||
// The scene model may lose this distinction for instance children whose
|
||||
|
|
@ -328,7 +328,7 @@ function applyRawFigmaNodeFields(
|
|||
if (context.assetRefToVarGuid && context.assetRefToVarGuid.size > 0) {
|
||||
paints = convertColorVarAssetRefs(paints, context.assetRefToVarGuid)
|
||||
}
|
||||
;(nc as Record<string, unknown>)[key] = paints
|
||||
nc[key] = paints
|
||||
continue
|
||||
}
|
||||
// Also convert colorVar.assetRef in raw effects (e.g. shadow color variables)
|
||||
|
|
@ -339,16 +339,16 @@ function applyRawFigmaNodeFields(
|
|||
context.assetRefToVarGuid.size > 0
|
||||
) {
|
||||
const converted = convertColorVarAssetRefs(materialized[key], context.assetRefToVarGuid)
|
||||
;(nc as Record<string, unknown>)[key] = converted
|
||||
nc[key] = converted
|
||||
continue
|
||||
}
|
||||
if (key === 'derivedTextData' && node.source.id) {
|
||||
;(nc as Record<string, unknown>)[key] = materialized[key]
|
||||
nc[key] = materialized[key]
|
||||
continue
|
||||
}
|
||||
// Skip any key already set on nc — explicit serialization takes priority
|
||||
if (key in (nc as Record<string, unknown>)) continue
|
||||
;(nc as Record<string, unknown>)[key] = materialized[key]
|
||||
if (key in nc) continue
|
||||
nc[key] = materialized[key]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ function applyRawFigmaNodeFields(
|
|||
* reference resolvable regardless of whether key/version is present on the
|
||||
* VARIABLE NodeChange.
|
||||
*/
|
||||
function convertColorVarAssetRefs(paints: unknown, assetRefToVarGuid: Map<string, GUID>): unknown {
|
||||
function convertColorVarAssetRefs<T>(paints: T, assetRefToVarGuid: Map<string, GUID>): T {
|
||||
if (!Array.isArray(paints)) return paints
|
||||
const result = paints.map((paint: Record<string, unknown>) => {
|
||||
const colorVar = paint.colorVar as Record<string, unknown> | undefined
|
||||
|
|
@ -390,7 +390,7 @@ function convertColorVarAssetRefs(paints: unknown, assetRefToVarGuid: Map<string
|
|||
})
|
||||
// Check if any paint was actually changed (skip expensive JSON comparison)
|
||||
for (let i = 0; i < paints.length; i++) {
|
||||
if (result[i] !== paints[i]) return result
|
||||
if (result[i] !== paints[i]) return result as T
|
||||
}
|
||||
return paints
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { SceneGraph, SceneNode, Fill, Stroke, Effect, StyleRun } from './'
|
||||
import type { SceneGraph, SceneNode } from './'
|
||||
import { copyEffects, copyFills, copyStrokes, copyStyleRuns } from './copy'
|
||||
|
||||
const INSTANCE_SYNC_PROPS: (keyof SceneNode)[] = [
|
||||
|
|
@ -40,22 +40,30 @@ const INSTANCE_SYNC_PROPS: (keyof SceneNode)[] = [
|
|||
'borderLeftWeight'
|
||||
]
|
||||
|
||||
function setSceneProp<K extends keyof SceneNode>(
|
||||
target: Partial<SceneNode>,
|
||||
key: K,
|
||||
value: SceneNode[K]
|
||||
): void {
|
||||
target[key] = value
|
||||
}
|
||||
|
||||
function copyProp(
|
||||
target: Partial<SceneNode> | SceneNode,
|
||||
source: SceneNode,
|
||||
key: keyof SceneNode
|
||||
): void {
|
||||
const val = source[key]
|
||||
if (key === 'fills') {
|
||||
;(target as Record<string, unknown>)[key] = copyFills(val as Fill[])
|
||||
setSceneProp(target, key, copyFills(source.fills))
|
||||
} else if (key === 'strokes') {
|
||||
;(target as Record<string, unknown>)[key] = copyStrokes(val as Stroke[])
|
||||
setSceneProp(target, key, copyStrokes(source.strokes))
|
||||
} else if (key === 'effects') {
|
||||
;(target as Record<string, unknown>)[key] = copyEffects(val as Effect[])
|
||||
setSceneProp(target, key, copyEffects(source.effects))
|
||||
} else if (key === 'styleRuns') {
|
||||
;(target as Record<string, unknown>)[key] = copyStyleRuns(val as StyleRun[])
|
||||
setSceneProp(target, key, copyStyleRuns(source.styleRuns))
|
||||
} else {
|
||||
;(target as Record<string, unknown>)[key] = Array.isArray(val) ? structuredClone(val) : val
|
||||
const value = source[key]
|
||||
setSceneProp(target, key, Array.isArray(value) ? structuredClone(value) : value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue