-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
213 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@tokens-studio/graph-engine-nodes-figma": patch | ||
--- | ||
|
||
Add new node to add a variables scope by the token type. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,17 @@ | ||
import codeSyntax from "./codeSyntax.js"; | ||
import publish from "./publish.js"; | ||
import scopeAll from "./scopeAll.js"; | ||
import scopeByType from "./scopeByType.js"; | ||
import scopeColor from "./scopeColor.js"; | ||
import scopeNumber from "./scopeNumber.js"; | ||
import scopeString from "./scopeString.js"; | ||
|
||
export const nodes = [ | ||
codeSyntax, | ||
publish, | ||
scopeAll, | ||
scopeByType, | ||
scopeColor, | ||
scopeNumber, | ||
scopeString, | ||
codeSyntax, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { FigmaScope } from "../types/scopes.js"; | ||
import { | ||
INodeDefinition, | ||
Node, | ||
ToInput, | ||
ToOutput, | ||
} from "@tokens-studio/graph-engine"; | ||
import { SingleToken } from "@tokens-studio/types"; | ||
import { TokenSchema } from "@tokens-studio/graph-engine-nodes-design-tokens/schemas/index.js"; | ||
import { mergeTokenExtensions } from "../utils/tokenMerge.js"; | ||
|
||
export default class NodeDefinition extends Node { | ||
static title = "Scope By Type"; | ||
static type = "studio.tokens.figma.scopeByType"; | ||
static description = "Automatically sets Figma scopes based on token type"; | ||
|
||
declare inputs: ToInput<{ | ||
token: SingleToken; | ||
}>; | ||
declare outputs: ToOutput<{ | ||
token: SingleToken; | ||
}>; | ||
|
||
constructor(props: INodeDefinition) { | ||
super(props); | ||
|
||
this.addInput("token", { | ||
type: { | ||
...TokenSchema, | ||
description: "The design token to automatically scope", | ||
}, | ||
}); | ||
|
||
this.addOutput("token", { | ||
type: TokenSchema, | ||
}); | ||
} | ||
|
||
private getScopesByType(token: SingleToken): FigmaScope[] { | ||
switch (token.type) { | ||
case "color": | ||
return ["ALL_FILLS", "STROKE_COLOR", "EFFECT_COLOR"]; | ||
case "dimension": | ||
return [ | ||
"GAP", | ||
"WIDTH_HEIGHT", | ||
"CORNER_RADIUS", | ||
"STROKE_FLOAT", | ||
"EFFECT_FLOAT", | ||
"PARAGRAPH_INDENT", | ||
]; | ||
case "spacing": | ||
return ["GAP", "WIDTH_HEIGHT"]; | ||
case "borderRadius": | ||
return ["CORNER_RADIUS"]; | ||
case "fontFamilies": | ||
return ["FONT_FAMILY"]; | ||
case "fontWeights": | ||
return ["FONT_WEIGHT"]; | ||
case "fontSizes": | ||
return ["FONT_SIZE"]; | ||
case "lineHeights": | ||
return ["LINE_HEIGHT"]; | ||
case "letterSpacing": | ||
return ["LETTER_SPACING"]; | ||
case "paragraphSpacing": | ||
return ["PARAGRAPH_SPACING"]; | ||
case "opacity": | ||
return ["OPACITY"]; | ||
case "sizing": | ||
return ["WIDTH_HEIGHT"]; | ||
default: | ||
return []; | ||
} | ||
} | ||
|
||
execute(): void | Promise<void> { | ||
const { token } = this.getAllInputs(); | ||
const newScopes = this.getScopesByType(token); | ||
|
||
const modifiedToken = mergeTokenExtensions(token, { | ||
scopes: newScopes, | ||
}); | ||
|
||
this.outputs.token.set(modifiedToken); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import { Graph } from "@tokens-studio/graph-engine"; | ||
import { SingleToken } from "@tokens-studio/types"; | ||
import { describe, expect, test } from "vitest"; | ||
import Node from "../src/nodes/scopeByType.js"; | ||
|
||
describe("nodes/scopeByType", () => { | ||
test("adds color scopes to color token", async () => { | ||
const graph = new Graph(); | ||
const node = new Node({ graph }); | ||
|
||
const mockToken = { | ||
name: "test", | ||
value: "#ff0000", | ||
type: "color", | ||
} as SingleToken; | ||
|
||
node.inputs.token.setValue(mockToken); | ||
await node.execute(); | ||
|
||
expect(node.outputs.token.value).toEqual({ | ||
...mockToken, | ||
$extensions: { | ||
"com.figma": { | ||
scopes: ["ALL_FILLS", "STROKE_COLOR", "EFFECT_COLOR"], | ||
}, | ||
}, | ||
}); | ||
}); | ||
|
||
test("adds dimension scopes to dimension token", async () => { | ||
const graph = new Graph(); | ||
const node = new Node({ graph }); | ||
|
||
const mockToken = { | ||
name: "test", | ||
value: "16px", | ||
type: "dimension", | ||
} as SingleToken; | ||
|
||
node.inputs.token.setValue(mockToken); | ||
await node.execute(); | ||
|
||
expect(node.outputs.token.value).toEqual({ | ||
...mockToken, | ||
$extensions: { | ||
"com.figma": { | ||
scopes: [ | ||
"GAP", | ||
"WIDTH_HEIGHT", | ||
"CORNER_RADIUS", | ||
"STROKE_FLOAT", | ||
"EFFECT_FLOAT", | ||
"PARAGRAPH_INDENT", | ||
], | ||
}, | ||
}, | ||
}); | ||
}); | ||
|
||
test("adds font-related scopes to typography tokens", async () => { | ||
const graph = new Graph(); | ||
const node = new Node({ graph }); | ||
|
||
const mockToken = { | ||
name: "test", | ||
value: "Inter", | ||
type: "fontFamilies", | ||
} as SingleToken; | ||
|
||
node.inputs.token.setValue(mockToken); | ||
await node.execute(); | ||
|
||
expect(node.outputs.token.value).toEqual({ | ||
...mockToken, | ||
$extensions: { | ||
"com.figma": { | ||
scopes: ["FONT_FAMILY"], | ||
}, | ||
}, | ||
}); | ||
}); | ||
|
||
test("preserves existing extensions and merges scopes", async () => { | ||
const graph = new Graph(); | ||
const node = new Node({ graph }); | ||
|
||
const mockToken = { | ||
name: "test", | ||
value: "#ff0000", | ||
type: "color", | ||
$extensions: { | ||
"com.figma": { | ||
scopes: ["TEXT_FILL"], | ||
otherProp: true, | ||
}, | ||
"other.extension": { | ||
someProp: "value", | ||
}, | ||
}, | ||
} as unknown as SingleToken; | ||
|
||
node.inputs.token.setValue(mockToken); | ||
await node.execute(); | ||
|
||
expect(node.outputs.token.value).toEqual({ | ||
...mockToken, | ||
$extensions: { | ||
"com.figma": { | ||
scopes: ["TEXT_FILL", "ALL_FILLS", "STROKE_COLOR", "EFFECT_COLOR"], | ||
otherProp: true, | ||
}, | ||
"other.extension": { | ||
someProp: "value", | ||
}, | ||
}, | ||
}); | ||
}); | ||
}); |