fix: default TEXT nodes to solid black fill
TEXT nodes created via SceneGraph.createNode() defaulted to empty fills, causing text to be invisible when .fig files are opened in Figma. Now defaults to a solid black fill matching Figma's behavior. Closes #133
This commit is contained in:
parent
2efd63ea09
commit
5139836816
|
|
@ -17,6 +17,7 @@
|
|||
- Fix browser/headless rendering mismatch for imported toolbar/instance content by correcting runtime imported layout recomputation instead of diverging browser rendering behavior
|
||||
- Fix `set_layout` tool not defaulting to HUG sizing when enabling auto-layout — frames now shrink/grow to fit children instead of keeping fixed dimensions
|
||||
- Normalize font family names on `.fig` export — strip optical size suffixes (e.g. "DM Sans 9pt" → "DM Sans") so Figma recognizes the font
|
||||
- TEXT nodes now default to a solid black fill — previously exported with no fill, making text invisible when opened in Figma
|
||||
- Fix save crash when COLOR variable is missing alpha channel
|
||||
- Fix console error spam on deployed web app from automation WebSocket reconnect loop
|
||||
- Fix headless CLI font fallback — bundled Inter font now ships with `@open-pencil/core` and loads without a web server
|
||||
|
|
|
|||
|
|
@ -371,7 +371,9 @@ function createDefaultNode(type: NodeType, overrides: Partial<SceneNode> = {}):
|
|||
width: 100,
|
||||
height: 100,
|
||||
rotation: 0,
|
||||
fills: [],
|
||||
fills: type === 'TEXT'
|
||||
? [{ type: 'SOLID' as const, color: { r: 0, g: 0, b: 0, a: 1 }, opacity: 1, visible: true }]
|
||||
: [],
|
||||
strokes: [],
|
||||
effects: [],
|
||||
opacity: 1,
|
||||
|
|
|
|||
|
|
@ -82,3 +82,70 @@ describe('Font family normalization on .fig export', () => {
|
|||
expect(textNode.fontFamily).toBe('Roboto')
|
||||
})
|
||||
})
|
||||
|
||||
describe('TEXT node default fill', () => {
|
||||
test('TEXT node without explicit fills exports with solid black fill', async () => {
|
||||
const graph = new SceneGraph()
|
||||
graph.createNode('TEXT', pageId(graph), {
|
||||
name: 'No Fill Specified',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
height: 20,
|
||||
text: 'Hello',
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: 400,
|
||||
fontSize: 14,
|
||||
})
|
||||
|
||||
const exported = await exportFigFile(graph)
|
||||
const reimported = await parseFigFile(exported.buffer as ArrayBuffer)
|
||||
|
||||
const nodes = [...reimported.nodes.values()]
|
||||
const textNode = nodes.find((n) => n.type === 'TEXT')!
|
||||
expect(textNode.fills.length).toBe(1)
|
||||
expect(textNode.fills[0].type).toBe('SOLID')
|
||||
expect(textNode.fills[0].color.r).toBe(0)
|
||||
expect(textNode.fills[0].color.g).toBe(0)
|
||||
expect(textNode.fills[0].color.b).toBe(0)
|
||||
expect(textNode.fills[0].color.a).toBe(1)
|
||||
})
|
||||
|
||||
test('TEXT node with explicit fill preserves it', async () => {
|
||||
const graph = new SceneGraph()
|
||||
graph.createNode('TEXT', pageId(graph), {
|
||||
name: 'Gold Text',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
height: 20,
|
||||
text: 'Hello',
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: 400,
|
||||
fontSize: 14,
|
||||
fills: [{ type: 'SOLID', color: { r: 0.96, g: 0.72, b: 0, a: 1 }, opacity: 1, visible: true }],
|
||||
})
|
||||
|
||||
const exported = await exportFigFile(graph)
|
||||
const reimported = await parseFigFile(exported.buffer as ArrayBuffer)
|
||||
|
||||
const nodes = [...reimported.nodes.values()]
|
||||
const textNode = nodes.find((n) => n.type === 'TEXT')!
|
||||
expect(textNode.fills.length).toBe(1)
|
||||
expect(textNode.fills[0].color.r).toBeCloseTo(0.96, 1)
|
||||
expect(textNode.fills[0].color.g).toBeCloseTo(0.72, 1)
|
||||
expect(textNode.fills[0].color.b).toBeCloseTo(0, 1)
|
||||
})
|
||||
|
||||
test('non-TEXT node still defaults to empty fills', async () => {
|
||||
const graph = new SceneGraph()
|
||||
const node = graph.createNode('RECTANGLE', pageId(graph), {
|
||||
name: 'Rect',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
})
|
||||
expect(graph.getNode(node.id)!.fills.length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue