-
-
Notifications
You must be signed in to change notification settings - Fork 196
/
TokenValueRetriever.ts
125 lines (103 loc) · 4.75 KB
/
TokenValueRetriever.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { ApplyVariablesStylesOrRawValues } from '@/constants/ApplyVariablesStyleOrder';
import { RawVariableReferenceMap } from '@/types/RawVariableReferenceMap';
import { AnyTokenList } from '@/types/tokens';
export class TokenValueRetriever {
public tokens;
public variableReferences;
public cachedVariableReferences;
private styleReferences;
private stylePathPrefix;
private ignoreFirstPartForStyles;
public applyVariablesStylesOrRawValue;
public createStylesWithVariableReferences;
private getAdjustedTokenName(tokenName: string): [string, string] {
const withIgnoredFirstPart = this.ignoreFirstPartForStyles && tokenName.split('.').length > 1
? tokenName.split('.').slice(1).join('.')
: tokenName;
const adjustedTokenName = [this.stylePathPrefix, tokenName].filter((n) => n).join('.');
const adjustedTokenNameWithIgnoreFirstPart = [this.stylePathPrefix, withIgnoredFirstPart].filter((n) => n).join('.');
return [adjustedTokenName, adjustedTokenNameWithIgnoreFirstPart];
}
public initiate({
tokens,
variableReferences,
styleReferences,
stylePathPrefix,
ignoreFirstPartForStyles = false,
createStylesWithVariableReferences = false,
applyVariablesStylesOrRawValue = ApplyVariablesStylesOrRawValues.VARIABLES_STYLES,
}: { tokens: AnyTokenList,
variableReferences?: RawVariableReferenceMap,
styleReferences?: Map<string,
string>,
stylePathPrefix?: string,
ignoreFirstPartForStyles?: boolean,
createStylesWithVariableReferences?: boolean,
applyVariablesStylesOrRawValue?: ApplyVariablesStylesOrRawValues,
}) {
this.stylePathPrefix = typeof stylePathPrefix !== 'undefined' ? stylePathPrefix : null;
this.ignoreFirstPartForStyles = ignoreFirstPartForStyles;
this.createStylesWithVariableReferences = createStylesWithVariableReferences;
this.styleReferences = styleReferences || new Map();
this.variableReferences = variableReferences || new Map();
this.cachedVariableReferences = new Map();
this.applyVariablesStylesOrRawValue = applyVariablesStylesOrRawValue;
this.tokens = new Map<string, any>(tokens.map((token) => {
const variableId = variableReferences?.get(token.name);
// For styles, we need to ignore the first part of the token name as well as consider theme prefix
const [adjustedTokenName, adjustedTokenNameWithIgnoreFirstPart] = this.getAdjustedTokenName(token.name);
const styleId = styleReferences?.get(adjustedTokenName) || styleReferences?.get(adjustedTokenNameWithIgnoreFirstPart) || styleReferences?.get(token.name);
const finalAdjustedTokenName = styleReferences?.has(adjustedTokenName) ? adjustedTokenName : adjustedTokenNameWithIgnoreFirstPart;
return [token.name, {
...token,
variableId,
styleId,
adjustedTokenName: styleId ? finalAdjustedTokenName : adjustedTokenName,
}];
}));
}
public get(tokenName: string) {
return this.tokens.get(tokenName);
}
public async getVariableReference(tokenName: string) {
let variable;
const storedToken = this.tokens.get(tokenName);
const isUsingReference = storedToken?.rawValue?.startsWith?.('{') && storedToken?.rawValue?.endsWith?.('}');
const hasCachedVariable = this.cachedVariableReferences.has(tokenName);
if (hasCachedVariable) {
variable = this.cachedVariableReferences.get(tokenName);
return variable;
}
const variableMapped = this.variableReferences.get(tokenName) || (isUsingReference ? this.variableReferences.get(storedToken.rawValue.slice(1, -1)) : null);
if (!variableMapped) return false;
if (!hasCachedVariable && typeof variableMapped === 'string') {
try {
const foundVariable = await figma.variables.importVariableByKeyAsync(variableMapped);
if (foundVariable) {
this.cachedVariableReferences.set(tokenName, foundVariable);
variable = foundVariable;
return variable;
}
} catch (e) {
console.log('error importing variable', e);
Promise.reject(e);
}
}
if (variable === undefined) return null;
return null;
}
public getTokens() {
return this.tokens;
}
public clearCache() {
if (this.cachedVariableReferences) this.cachedVariableReferences.clear();
if (this.tokens) this.tokens.clear();
if (this.variableReferences) this.variableReferences.clear();
if (this.styleReferences) this.styleReferences.clear();
if (this.stylePathPrefix) this.stylePathPrefix = undefined;
if (this.ignoreFirstPartForStyles) this.ignoreFirstPartForStyles = undefined;
if (this.createStylesWithVariableReferences) this.createStylesWithVariableReferences = undefined;
}
}
const defaultTokenValueRetriever = new TokenValueRetriever();
export { defaultTokenValueRetriever };