fix(fig): preserve marker-based instance text edits on export (#648)
This commit is contained in:
parent
6e74ad2a51
commit
9d4fe4e421
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
### Fixed
|
||||
|
||||
- Preserve edited instance text, including cleared labels, when saving and reopening `.fig` files.
|
||||
- Honor `.pen` frame layout defaults and sizing and padding shorthands so imported auto-layout frames keep their computed dimensions and child positions. (#564)
|
||||
- Avoid macOS Keychain prompts during credential status checks and pause repeated credential access after failures until explicitly retried from Settings.
|
||||
|
||||
|
|
|
|||
|
|
@ -401,12 +401,15 @@ function serializeTextOverrides(
|
|||
): KiwiSymbolOverridePayload[] {
|
||||
const result: KiwiSymbolOverridePayload[] = []
|
||||
forEachInstanceOverride(instance.instanceOverrides, (nodeId, field, value) => {
|
||||
if (field !== 'text' || typeof value !== 'string' || !nodeId) return
|
||||
if (field !== 'text' || !nodeId) return
|
||||
const target = context.graph.getNode(nodeId)
|
||||
if (!target || !isDescendantOf(context, nodeId, instance.id)) return
|
||||
const targetGuid = resolveOverrideTargetGuid(context, target, localIdCounter)
|
||||
if (targetGuid)
|
||||
result.push({ guidPath: { guids: [targetGuid] }, textData: { characters: value } })
|
||||
result.push({
|
||||
guidPath: { guids: [targetGuid] },
|
||||
textData: { characters: typeof value === 'string' ? value : target.text }
|
||||
})
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
|
|
|||
45
tests/engine/io/fig/instance/text-marker-roundtrip.test.ts
Normal file
45
tests/engine/io/fig/instance/text-marker-roundtrip.test.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import { expect, test } from 'bun:test'
|
||||
|
||||
import { FigmaAPI } from '@open-pencil/core'
|
||||
import { exportFigFile, parseFigFile } from '@open-pencil/core/io'
|
||||
import { initCodec } from '@open-pencil/core/kiwi'
|
||||
import { SceneGraph, getInstanceOverride } from '@open-pencil/scene-graph'
|
||||
|
||||
for (const text of ['User edit', '']) {
|
||||
test(`preserves API instance text edit ${JSON.stringify(text)} across save/reload`, async () => {
|
||||
await initCodec()
|
||||
const graph = new SceneGraph()
|
||||
const api = new FigmaAPI(graph)
|
||||
const component = api.createComponent()
|
||||
const label = api.createText()
|
||||
label.characters = 'Default'
|
||||
component.appendChild(label)
|
||||
const edited = component.createInstance()
|
||||
edited.name = 'Edited'
|
||||
const inherited = component.createInstance()
|
||||
inherited.name = 'Inherited'
|
||||
edited.children[0].characters = text
|
||||
const raw = graph.getNode(edited.id)
|
||||
if (!raw) throw new Error('Missing instance')
|
||||
expect(
|
||||
getInstanceOverride(raw.instanceOverrides, edited.id, edited.children[0].id, 'text')
|
||||
).toBe(true)
|
||||
label.characters = 'Component edit'
|
||||
graph.syncInstances(component.id)
|
||||
expect(edited.children[0].characters).toBe(text)
|
||||
expect(inherited.children[0].characters).toBe('Component edit')
|
||||
|
||||
const bytes = await exportFigFile(graph)
|
||||
const restored = await parseFigFile(bytes.buffer as ArrayBuffer)
|
||||
for (const [name, expected] of [
|
||||
['Edited', text],
|
||||
['Inherited', 'Component edit']
|
||||
]) {
|
||||
const instance = [...restored.getAllNodes()].find(
|
||||
(node) => node.type === 'INSTANCE' && node.name === name
|
||||
)
|
||||
if (!instance) throw new Error(`Missing ${name}`)
|
||||
expect(restored.getChildren(instance.id)[0]?.text).toBe(expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
Reference in a new issue