fix(pen-core/variables): resolveNodeForCanvas — fontWeight + empty-vars fallback
GAP-1: add 'fontWeight' to the text-node key list in resolveNodeForCanvas so
$type-*-weight refs resolve to a number before reaching the renderer.
GAP-2: replace the early-exit `if (!variables || Object.keys(variables).length === 0)
return node` with `if (!variables) variables = {}` so DEFAULT_PALETTE_FALLBACK
fires even when the document has an empty variables map (un-seeded v1 docs).
Adds 2 new tests to fallback-equivalence.test.ts covering both gaps.
This commit is contained in:
parent
aa2658fcd1
commit
dc656be409
|
|
@ -1,5 +1,7 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import { resolveVariableRef } from '../variables/resolve.js';
|
||||
import { resolveVariableRef, resolveNodeForCanvas } from '../variables/resolve.js';
|
||||
import { createEmptyDocument } from '../tree-utils.js';
|
||||
import type { PenNode } from '@zseven-w/pen-types';
|
||||
|
||||
describe('resolver-side fallback (un-seeded doc, P1.6)', () => {
|
||||
const emptyVars = {};
|
||||
|
|
@ -75,3 +77,44 @@ describe('resolver-side fallback (un-seeded doc, P1.6)', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GAP fixes — resolveNodeForCanvas covers all numeric refs', () => {
|
||||
it('resolves fontWeight ref via fallback', () => {
|
||||
const doc = createEmptyDocument();
|
||||
const textNode: PenNode = {
|
||||
id: 'h',
|
||||
type: 'text',
|
||||
name: 'H1',
|
||||
content: 'Hello',
|
||||
fontSize: '$type-h1-size' as unknown as number,
|
||||
fontWeight: '$type-h1-weight' as unknown as number,
|
||||
fill: [{ type: 'solid', color: '$color-text-primary' }],
|
||||
};
|
||||
const resolved = resolveNodeForCanvas(
|
||||
textNode,
|
||||
doc.variables ?? {},
|
||||
undefined,
|
||||
) as unknown as Record<string, unknown>;
|
||||
expect(typeof resolved.fontWeight).toBe('number');
|
||||
expect(resolved.fontWeight).toBe(600);
|
||||
});
|
||||
|
||||
it('resolves refs in empty-vars doc (fallback fires past early-exit)', () => {
|
||||
// createEmptyDocument() returns doc.variables = undefined; passing undefined as vars
|
||||
// exercises the GAP-2 fix (the early-exit was `if (!variables || Object.keys...)`).
|
||||
const textNode: PenNode = {
|
||||
id: 't',
|
||||
type: 'text',
|
||||
name: 'T',
|
||||
content: 'Hi',
|
||||
fill: [{ type: 'solid', color: '$color-text-primary' }],
|
||||
};
|
||||
const resolved = resolveNodeForCanvas(
|
||||
textNode,
|
||||
undefined as unknown as Record<string, import('@zseven-w/pen-types').VariableDefinition>,
|
||||
undefined,
|
||||
) as unknown as Record<string, unknown>;
|
||||
const fill = (resolved.fill as Array<{ type: string; color: string }>)[0];
|
||||
expect(fill.color).toBe('#0F172A');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ function resolveEffectsForCanvas(
|
|||
* Returns the same object reference when no variables are present.
|
||||
*/
|
||||
export function resolveNodeForCanvas(node: PenNode, variables: Vars, activeTheme?: Theme): PenNode {
|
||||
if (!variables || Object.keys(variables).length === 0) return node;
|
||||
if (!variables) variables = {};
|
||||
|
||||
let changed = false;
|
||||
const out: Record<string, unknown> = { ...node };
|
||||
|
|
@ -278,7 +278,7 @@ export function resolveNodeForCanvas(node: PenNode, variables: Vars, activeTheme
|
|||
// since both paths use `node.fontSize ?? 16` (not type-guarded for strings).
|
||||
if (node.type === 'text') {
|
||||
const n = node as unknown as Record<string, unknown>;
|
||||
for (const key of ['fontSize', 'lineHeight', 'letterSpacing'] as const) {
|
||||
for (const key of ['fontSize', 'fontWeight', 'lineHeight', 'letterSpacing'] as const) {
|
||||
if (typeof n[key] === 'string' && isVariableRef(n[key] as string)) {
|
||||
const resolved = resolveNumericRef(n[key] as string, variables, activeTheme);
|
||||
if (resolved !== undefined) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue