- Index component property definitions and variable asset references once per export or override context\n- Skip converged instance fill and text propagation and use native binary hex encoding\n- Add a non-populating parse mode for raw fixture validation\n- Reduce the Material 3 round trip from minutes to about twenty seconds
93 lines
2.6 KiB
TypeScript
93 lines
2.6 KiB
TypeScript
import { describe, expect, test } from 'bun:test'
|
|
|
|
import { SceneGraph } from '@open-pencil/scene-graph'
|
|
|
|
import {
|
|
buildComponentPropIndex,
|
|
fractionalPosition,
|
|
mapToFigmaType,
|
|
sceneNodeToKiwi,
|
|
type FigNodeChangeExportRuntime
|
|
} from '../src/node-change'
|
|
|
|
describe('@open-pencil/fig SceneGraph export policy', () => {
|
|
test('maps node types and sibling positions deterministically', () => {
|
|
expect(mapToFigmaType('COMPONENT')).toBe('SYMBOL')
|
|
expect([0, 93, 94, 188].map(fractionalPosition)).toEqual(['!', '~', '~!', '~~!'])
|
|
})
|
|
|
|
test('reuses an export-scoped component property definition index', () => {
|
|
const graph = new SceneGraph()
|
|
const page = graph.getPages()[0]
|
|
const component = graph.createNode('COMPONENT', page.id, {
|
|
componentPropertyDefinitions: [
|
|
{ id: '1:100', name: 'Label', type: 'TEXT', defaultValue: 'Default' }
|
|
]
|
|
})
|
|
const instance = graph.createNode('INSTANCE', page.id, {
|
|
componentId: component.id,
|
|
componentPropertyAssignments: { '1:100': 'Override' }
|
|
})
|
|
const serialize = (definitions?: ReturnType<typeof buildComponentPropIndex>) =>
|
|
sceneNodeToKiwi(
|
|
instance,
|
|
{ sessionID: 1, localID: 1 },
|
|
0,
|
|
{ value: 2 },
|
|
graph,
|
|
[],
|
|
new Map(),
|
|
undefined,
|
|
undefined,
|
|
undefined,
|
|
undefined,
|
|
new Set(),
|
|
undefined,
|
|
definitions
|
|
)[0].componentPropAssignments
|
|
|
|
const definitions = buildComponentPropIndex(graph)
|
|
expect(definitions.get('1:100')).toBe(component.componentPropertyDefinitions[0])
|
|
expect(serialize(definitions)).toEqual(serialize())
|
|
})
|
|
|
|
test('injects runtime glyph outlines into derived text data', () => {
|
|
const graph = new SceneGraph()
|
|
const text = graph.createNode('TEXT', graph.getPages()[0].id, {
|
|
text: 'A',
|
|
width: 20,
|
|
height: 20,
|
|
fontSize: 16
|
|
})
|
|
const blobs: Uint8Array[] = []
|
|
const runtime: FigNodeChangeExportRuntime = {
|
|
getGlyphOutlineMetrics: () => [
|
|
{
|
|
commands: [{ type: 'M', x: 0, y: 0 }, { type: 'L', x: 8, y: 16 }, { type: 'Z' }],
|
|
x: 0,
|
|
advance: 10
|
|
}
|
|
]
|
|
}
|
|
|
|
const [change] = sceneNodeToKiwi(
|
|
text,
|
|
{ sessionID: 1, localID: 1 },
|
|
0,
|
|
{ value: 2 },
|
|
graph,
|
|
blobs,
|
|
undefined,
|
|
new Map([['Inter|Regular', new Uint8Array([1, 2, 3])]]),
|
|
undefined,
|
|
new Map(),
|
|
undefined,
|
|
undefined,
|
|
runtime
|
|
)
|
|
|
|
expect(change.derivedTextData?.glyphs).toHaveLength(1)
|
|
expect(blobs).toHaveLength(1)
|
|
})
|
|
})
|