style-dictionary 4.0.0-prerelease.0 → 4.0.0-prerelease.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/{style-dictionary → style-dictionary.js} +13 -13
- package/examples/advanced/auto-rebuild-watcher/package.json +1 -1
- package/examples/advanced/create-react-app/package.json +2 -1
- package/examples/advanced/create-react-native-app/package.json +5 -1
- package/examples/advanced/s3/upload.js +1 -1
- package/examples/advanced/yaml-tokens/sd.config.js +1 -1
- package/lib/StyleDictionary.js +451 -0
- package/lib/buildFile.js +46 -40
- package/lib/cleanDir.js +1 -1
- package/lib/cleanDirs.js +2 -2
- package/lib/cleanFile.js +1 -1
- package/lib/common/actions.js +12 -7
- package/lib/common/formatHelpers/createPropertyFormatter.js +116 -59
- package/lib/common/formatHelpers/getTypeScriptType.js +8 -7
- package/lib/common/formats.js +6 -6
- package/lib/common/templates/compose/object.kt.template.js +1 -1
- package/lib/common/templates/css/fonts.css.template.js +1 -1
- package/lib/common/templates/ios/singleton.m.template.js +10 -10
- package/lib/common/templates/scss/map-deep.template.js +3 -3
- package/lib/common/transforms.js +11 -1
- package/lib/filterTokens.js +76 -0
- package/lib/register/preprocessor.js +39 -0
- package/lib/register/transform.js +2 -1
- package/lib/register/transformGroup.js +1 -3
- package/lib/transform/config.js +26 -21
- package/lib/transform/object.js +18 -12
- package/lib/transform/{property.js → token.js} +1 -2
- package/lib/transform/{propertySetup.js → tokenSetup.js} +17 -17
- package/lib/utils/combineJSON.js +22 -12
- package/lib/utils/convertToBase64.js +3 -3
- package/lib/utils/createDictionary.js +10 -14
- package/lib/utils/createFormatArgs.js +1 -5
- package/lib/utils/deepExtend.js +15 -18
- package/lib/utils/deepmerge.js +14 -0
- package/lib/utils/{flattenProperties.js → flattenTokens.js} +10 -10
- package/lib/utils/preprocess.js +35 -0
- package/lib/utils/references/getName.js +2 -2
- package/lib/utils/references/getReferences.js +7 -7
- package/lib/utils/resolveObject.js +4 -5
- package/package.json +33 -20
- package/types/Config.d.ts +3 -2
- package/types/Dictionary.d.ts +0 -2
- package/types/FormatHelpers.d.ts +12 -23
- package/{lib/cleanAllPlatforms.js → types/Preprocessor.d.ts} +6 -17
- package/types/index.d.ts +23 -2
- package/types/index.test-d.ts +7 -0
- package/index-node.js +0 -7
- package/index.js +0 -84
- package/lib/buildAllPlatforms.js +0 -37
- package/lib/buildPlatform.js +0 -67
- package/lib/cleanPlatform.js +0 -59
- package/lib/exportPlatform.js +0 -131
- package/lib/extend.js +0 -162
- package/lib/filterProperties.js +0 -92
- package/lib/utils/es6_.js +0 -151
package/lib/buildFile.js
CHANGED
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
import path from '@bundled-es-modules/path-browserify';
|
|
15
15
|
import chalk from 'chalk';
|
|
16
|
-
import { fs } from '
|
|
17
|
-
import
|
|
16
|
+
import { fs } from 'style-dictionary/fs';
|
|
17
|
+
import filterTokens from './filterTokens.js';
|
|
18
18
|
import GroupMessages from './utils/groupMessages.js';
|
|
19
19
|
|
|
20
20
|
import createFormatArgs from './utils/createFormatArgs.js';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* Takes the style
|
|
23
|
+
* Takes the style token object and a format and returns a
|
|
24
24
|
* string that can be written to a file.
|
|
25
25
|
* @memberOf StyleDictionary
|
|
26
26
|
* @param {Object} file
|
|
@@ -50,60 +50,58 @@ export default function buildFile(file = {}, platform = {}, dictionary = {}) {
|
|
|
50
50
|
const dirname = path.dirname(fullDestination);
|
|
51
51
|
if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true });
|
|
52
52
|
|
|
53
|
-
const
|
|
53
|
+
const filteredTokens = filterTokens(dictionary, filter);
|
|
54
54
|
const filteredDictionary = Object.assign({}, dictionary, {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
tokens
|
|
58
|
-
|
|
59
|
-
// keep the unfiltered properties object for reference resolution
|
|
60
|
-
_properties: dictionary.properties,
|
|
55
|
+
tokens: filteredTokens.tokens,
|
|
56
|
+
allTokens: filteredTokens.allTokens,
|
|
57
|
+
// keep the unfiltered tokens object for reference resolution
|
|
58
|
+
_tokens: dictionary.tokens,
|
|
61
59
|
});
|
|
62
60
|
|
|
63
|
-
// if
|
|
61
|
+
// if tokens object is empty, return without creating a file
|
|
64
62
|
if (
|
|
65
|
-
|
|
66
|
-
Object.keys(
|
|
67
|
-
|
|
63
|
+
filteredTokens.hasOwnProperty('tokens') &&
|
|
64
|
+
Object.keys(filteredTokens.tokens).length === 0 &&
|
|
65
|
+
filteredTokens.tokens.constructor === Object
|
|
68
66
|
) {
|
|
69
|
-
let warnNoFile = `No
|
|
67
|
+
let warnNoFile = `No tokens for ${destination}. File not created.`;
|
|
70
68
|
console.log(chalk.rgb(255, 140, 0)(warnNoFile));
|
|
71
69
|
return null;
|
|
72
70
|
}
|
|
73
71
|
|
|
74
|
-
// Check for
|
|
72
|
+
// Check for token name Collisions
|
|
75
73
|
const nameCollisionObj = {};
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
let
|
|
79
|
-
if (!nameCollisionObj[
|
|
80
|
-
nameCollisionObj[
|
|
74
|
+
filteredTokens.allTokens &&
|
|
75
|
+
filteredTokens.allTokens.forEach((tokenData) => {
|
|
76
|
+
let tokenName = tokenData.name;
|
|
77
|
+
if (!nameCollisionObj[tokenName]) {
|
|
78
|
+
nameCollisionObj[tokenName] = [];
|
|
81
79
|
}
|
|
82
|
-
nameCollisionObj[
|
|
80
|
+
nameCollisionObj[tokenName].push(tokenData);
|
|
83
81
|
});
|
|
84
82
|
|
|
85
83
|
const PROPERTY_NAME_COLLISION_WARNINGS =
|
|
86
84
|
GroupMessages.GROUP.PropertyNameCollisionWarnings + ':' + destination;
|
|
87
85
|
GroupMessages.clear(PROPERTY_NAME_COLLISION_WARNINGS);
|
|
88
|
-
Object.keys(nameCollisionObj).forEach((
|
|
89
|
-
if (nameCollisionObj[
|
|
90
|
-
let collisions = nameCollisionObj[
|
|
91
|
-
.map((
|
|
92
|
-
let
|
|
93
|
-
let valueText = chalk.rgb(255, 140, 0)(
|
|
94
|
-
return
|
|
86
|
+
Object.keys(nameCollisionObj).forEach((tokenName) => {
|
|
87
|
+
if (nameCollisionObj[tokenName].length > 1) {
|
|
88
|
+
let collisions = nameCollisionObj[tokenName]
|
|
89
|
+
.map((tokens) => {
|
|
90
|
+
let tokenPathText = chalk.rgb(255, 69, 0)(tokens.path.join('.'));
|
|
91
|
+
let valueText = chalk.rgb(255, 140, 0)(tokens.value);
|
|
92
|
+
return tokenPathText + ' ' + valueText;
|
|
95
93
|
})
|
|
96
94
|
.join('\n ');
|
|
97
95
|
GroupMessages.add(
|
|
98
96
|
PROPERTY_NAME_COLLISION_WARNINGS,
|
|
99
97
|
`Output name ${chalk
|
|
100
98
|
.rgb(255, 69, 0)
|
|
101
|
-
.bold(
|
|
99
|
+
.bold(tokenName)} was generated by:\n ${collisions}`,
|
|
102
100
|
);
|
|
103
101
|
}
|
|
104
102
|
});
|
|
105
103
|
|
|
106
|
-
let
|
|
104
|
+
let tokenNamesCollisionCount = GroupMessages.count(PROPERTY_NAME_COLLISION_WARNINGS);
|
|
107
105
|
fs.writeFileSync(
|
|
108
106
|
fullDestination,
|
|
109
107
|
format(
|
|
@@ -121,12 +119,12 @@ export default function buildFile(file = {}, platform = {}, dictionary = {}) {
|
|
|
121
119
|
|
|
122
120
|
// don't show name collision warnings for nested type formats
|
|
123
121
|
// because they are not relevant.
|
|
124
|
-
if ((nested ||
|
|
122
|
+
if ((nested || tokenNamesCollisionCount === 0) && filteredReferencesCount === 0) {
|
|
125
123
|
console.log(chalk.bold.green(`✔︎ ${fullDestination}`));
|
|
126
124
|
} else {
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
let
|
|
125
|
+
const warnHeader = `⚠️ ${fullDestination}`;
|
|
126
|
+
if (tokenNamesCollisionCount > 0) {
|
|
127
|
+
let tokenNamesCollisionWarnings = GroupMessages.fetchMessages(
|
|
130
128
|
PROPERTY_NAME_COLLISION_WARNINGS,
|
|
131
129
|
).join('\n ');
|
|
132
130
|
let title = `While building ${chalk
|
|
@@ -139,13 +137,17 @@ export default function buildFile(file = {}, platform = {}, dictionary = {}) {
|
|
|
139
137
|
)(
|
|
140
138
|
[
|
|
141
139
|
'This many-to-one issue is usually caused by some combination of:',
|
|
142
|
-
'* conflicting or similar paths/names in
|
|
140
|
+
'* conflicting or similar paths/names in token definitions',
|
|
143
141
|
'* platform transforms/transformGroups affecting names, especially when removing specificity',
|
|
144
142
|
'* overly inclusive file filters',
|
|
145
143
|
].join('\n '),
|
|
146
144
|
);
|
|
147
|
-
let warn = `${title}\n ${
|
|
148
|
-
|
|
145
|
+
let warn = `${warnHeader}\n${title}\n ${tokenNamesCollisionWarnings}\n${help}`;
|
|
146
|
+
if (platform?.log === 'error') {
|
|
147
|
+
throw new Error(warn);
|
|
148
|
+
} else {
|
|
149
|
+
console.log(chalk.rgb(255, 140, 0).bold(warn));
|
|
150
|
+
}
|
|
149
151
|
}
|
|
150
152
|
|
|
151
153
|
if (filteredReferencesCount > 0) {
|
|
@@ -162,8 +164,12 @@ export default function buildFile(file = {}, platform = {}, dictionary = {}) {
|
|
|
162
164
|
165,
|
|
163
165
|
0,
|
|
164
166
|
)(['This is caused when combining a filter and `outputReferences`.'].join('\n '));
|
|
165
|
-
let warn = `${title}\n ${filteredReferencesWarnings}\n${help}`;
|
|
166
|
-
|
|
167
|
+
let warn = `${warnHeader}\n${title}\n ${filteredReferencesWarnings}\n${help}`;
|
|
168
|
+
if (platform?.log === 'error') {
|
|
169
|
+
throw new Error(warn);
|
|
170
|
+
} else {
|
|
171
|
+
console.log(chalk.rgb(255, 140, 0).bold(warn));
|
|
172
|
+
}
|
|
167
173
|
}
|
|
168
174
|
}
|
|
169
175
|
}
|
package/lib/cleanDir.js
CHANGED
package/lib/cleanDirs.js
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
import cleanDir from './cleanDir.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Takes a platform config object and a
|
|
18
|
-
* object and cleans all the files.
|
|
17
|
+
* Takes a platform config object and a tokens
|
|
18
|
+
* object and cleans all the files. Tokens object
|
|
19
19
|
* should have been transformed and resolved before this
|
|
20
20
|
* point.
|
|
21
21
|
* @memberOf StyleDictionary
|
package/lib/cleanFile.js
CHANGED
package/lib/common/actions.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { fs } from '
|
|
14
|
+
import { fs } from 'style-dictionary/fs';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* @namespace Actions
|
|
@@ -25,20 +25,25 @@ export default {
|
|
|
25
25
|
*/
|
|
26
26
|
'android/copyImages': {
|
|
27
27
|
do: function (dictionary, config) {
|
|
28
|
-
|
|
28
|
+
const imagesDir = `${config.buildPath}android/main/res/drawable-`;
|
|
29
29
|
dictionary.allTokens.forEach(function (token) {
|
|
30
30
|
if (token.attributes.category === 'asset' && token.attributes.type === 'image') {
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
const name = token.path.slice(2, 4).join('_');
|
|
32
|
+
const dir = `${imagesDir}${token.attributes.state}`;
|
|
33
|
+
const path = `${dir}/${name}.png`;
|
|
34
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
35
|
+
fs.copyFileSync(token.value, path);
|
|
33
36
|
}
|
|
34
37
|
});
|
|
35
38
|
},
|
|
36
39
|
undo: function (dictionary, config) {
|
|
37
|
-
|
|
40
|
+
const imagesDir = `${config.buildPath}android/main/res/drawable-`;
|
|
38
41
|
dictionary.allTokens.forEach(function (token) {
|
|
39
42
|
if (token.attributes.category === 'asset' && token.attributes.type === 'image') {
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
const name = token.path.slice(2, 4).join('_');
|
|
44
|
+
const dir = `${imagesDir}${token.attributes.state}`;
|
|
45
|
+
const path = `${dir}/${name}.png`;
|
|
46
|
+
fs.unlinkSync(path);
|
|
42
47
|
}
|
|
43
48
|
});
|
|
44
49
|
},
|
|
@@ -14,11 +14,65 @@
|
|
|
14
14
|
const defaultFormatting = {
|
|
15
15
|
prefix: '',
|
|
16
16
|
commentStyle: 'long',
|
|
17
|
+
commentPosition: 'inline',
|
|
17
18
|
indentation: '',
|
|
18
19
|
separator: ' =',
|
|
19
20
|
suffix: ';',
|
|
20
21
|
};
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Split a string comment by newlines and
|
|
25
|
+
* convert to multi-line comment if necessary
|
|
26
|
+
* @param {string} to_ret_prop
|
|
27
|
+
* @param {{comment: string; style: 'short' | 'long'; position: 'above' | 'inline'; indentation: string}} options
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
function addComment(to_ret_prop, options) {
|
|
31
|
+
const { comment, style, indentation } = options;
|
|
32
|
+
let { position } = options;
|
|
33
|
+
|
|
34
|
+
const commentsByNewLine = comment.split('\n');
|
|
35
|
+
if (commentsByNewLine.length > 1) {
|
|
36
|
+
position = 'above';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let processedComment;
|
|
40
|
+
switch (style) {
|
|
41
|
+
case 'short':
|
|
42
|
+
if (position === 'inline') {
|
|
43
|
+
processedComment = `// ${comment}`;
|
|
44
|
+
} else {
|
|
45
|
+
processedComment = commentsByNewLine.reduce(
|
|
46
|
+
(acc, curr) => `${acc}${indentation}// ${curr}\n`,
|
|
47
|
+
'',
|
|
48
|
+
);
|
|
49
|
+
// remove trailing newline
|
|
50
|
+
processedComment = processedComment.replace(/\n$/g, '');
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
case 'long':
|
|
54
|
+
if (commentsByNewLine.length > 1) {
|
|
55
|
+
processedComment = commentsByNewLine.reduce(
|
|
56
|
+
(acc, curr) => `${acc}${indentation} * ${curr}\n`,
|
|
57
|
+
`${indentation}/**\n`,
|
|
58
|
+
);
|
|
59
|
+
processedComment += `${indentation} */`;
|
|
60
|
+
} else {
|
|
61
|
+
processedComment = `${position === 'above' ? indentation : ''}/* ${comment} */`;
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (position === 'above') {
|
|
67
|
+
// put the comment above the prop if it's multi-line or if commentStyle ended with -above
|
|
68
|
+
to_ret_prop = `${processedComment}\n${to_ret_prop}`;
|
|
69
|
+
} else {
|
|
70
|
+
to_ret_prop = `${to_ret_prop} ${processedComment}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return to_ret_prop;
|
|
74
|
+
}
|
|
75
|
+
|
|
22
76
|
/**
|
|
23
77
|
* Creates a function that can be used to format a property. This can be useful
|
|
24
78
|
* to use as the function on `dictionary.allTokens.map`. The formatting
|
|
@@ -57,37 +111,37 @@ export default function createPropertyFormatter({
|
|
|
57
111
|
formatting = {},
|
|
58
112
|
themeable = false,
|
|
59
113
|
}) {
|
|
60
|
-
|
|
61
|
-
{},
|
|
62
|
-
defaultFormatting,
|
|
63
|
-
formatting,
|
|
64
|
-
);
|
|
65
|
-
|
|
114
|
+
const formatDefaults = {};
|
|
66
115
|
switch (format) {
|
|
67
116
|
case 'css':
|
|
68
|
-
prefix = '--';
|
|
69
|
-
indentation = ' ';
|
|
70
|
-
separator = ':';
|
|
117
|
+
formatDefaults.prefix = '--';
|
|
118
|
+
formatDefaults.indentation = ' ';
|
|
119
|
+
formatDefaults.separator = ':';
|
|
71
120
|
break;
|
|
72
121
|
case 'sass':
|
|
73
|
-
prefix = '$';
|
|
74
|
-
commentStyle = 'short';
|
|
75
|
-
indentation = '';
|
|
76
|
-
separator = ':';
|
|
122
|
+
formatDefaults.prefix = '$';
|
|
123
|
+
formatDefaults.commentStyle = 'short';
|
|
124
|
+
formatDefaults.indentation = '';
|
|
125
|
+
formatDefaults.separator = ':';
|
|
77
126
|
break;
|
|
78
127
|
case 'less':
|
|
79
|
-
prefix = '@';
|
|
80
|
-
commentStyle = 'short';
|
|
81
|
-
indentation = '';
|
|
82
|
-
separator = ':';
|
|
128
|
+
formatDefaults.prefix = '@';
|
|
129
|
+
formatDefaults.commentStyle = 'short';
|
|
130
|
+
formatDefaults.indentation = '';
|
|
131
|
+
formatDefaults.separator = ':';
|
|
83
132
|
break;
|
|
84
133
|
case 'stylus':
|
|
85
|
-
prefix = '$';
|
|
86
|
-
commentStyle = 'short';
|
|
87
|
-
indentation = '';
|
|
88
|
-
separator = '=';
|
|
134
|
+
formatDefaults.prefix = '$';
|
|
135
|
+
formatDefaults.commentStyle = 'short';
|
|
136
|
+
formatDefaults.indentation = '';
|
|
137
|
+
formatDefaults.separator = '=';
|
|
89
138
|
break;
|
|
90
139
|
}
|
|
140
|
+
let { prefix, commentStyle, commentPosition, indentation, separator, suffix } = {
|
|
141
|
+
...defaultFormatting,
|
|
142
|
+
...formatDefaults,
|
|
143
|
+
...formatting,
|
|
144
|
+
};
|
|
91
145
|
|
|
92
146
|
return function (prop) {
|
|
93
147
|
let to_ret_prop = `${indentation}${prefix}${prop.name}${separator} `;
|
|
@@ -108,44 +162,46 @@ export default function createPropertyFormatter({
|
|
|
108
162
|
if (outputReferences && dictionary.usesReference(prop.original.value)) {
|
|
109
163
|
// Formats that use this function expect `value` to be a string
|
|
110
164
|
// or else you will get '[object Object]' in the output
|
|
111
|
-
|
|
112
|
-
const refs = dictionary.getReferences(prop.original.value);
|
|
165
|
+
const refs = dictionary.getReferences(prop.original.value);
|
|
113
166
|
|
|
114
|
-
|
|
115
|
-
|
|
167
|
+
// original can either be an object value, which requires transitive value transformation in web CSS formats
|
|
168
|
+
// or a different (primitive) type, meaning it can be stringified.
|
|
169
|
+
const originalIsObject =
|
|
170
|
+
typeof prop.original.value === 'object' && prop.original.value !== null;
|
|
116
171
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
172
|
+
if (!originalIsObject) {
|
|
173
|
+
// when original is object value, we replace value by matching ref.value and putting a var instead.
|
|
174
|
+
// Due to the original.value being an object, it requires transformation, so undoing the transformation
|
|
175
|
+
// by replacing value with original.value is not possible.
|
|
121
176
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
177
|
+
// when original is string value, we replace value by matching original.value and putting a var instead
|
|
178
|
+
// this is more friendly to transitive transforms that transform the string values
|
|
179
|
+
value = prop.original.value;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
refs.forEach((ref) => {
|
|
183
|
+
// value should be a string that contains the resolved reference
|
|
184
|
+
// because Style Dictionary resolved this in the resolution step.
|
|
185
|
+
// Here we are undoing that by replacing the value with
|
|
186
|
+
// the reference's name
|
|
187
|
+
if (Object.hasOwn(ref, 'value') && Object.hasOwn(ref, 'name')) {
|
|
188
|
+
const replaceFunc = function () {
|
|
189
|
+
if (format === 'css') {
|
|
190
|
+
if (outputReferenceFallbacks) {
|
|
191
|
+
return `var(${prefix}${ref.name}, ${ref.value})`;
|
|
135
192
|
} else {
|
|
136
|
-
return
|
|
193
|
+
return `var(${prefix}${ref.name})`;
|
|
137
194
|
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
195
|
+
} else {
|
|
196
|
+
return `${prefix}${ref.name}`;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
value = value.replace(
|
|
200
|
+
originalIsObject ? ref.value : new RegExp(`{${ref.path.join('.')}(.value)?}`, 'g'),
|
|
201
|
+
replaceFunc,
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
149
205
|
}
|
|
150
206
|
|
|
151
207
|
to_ret_prop += prop.attributes.category === 'asset' ? `"${value}"` : value;
|
|
@@ -158,11 +214,12 @@ export default function createPropertyFormatter({
|
|
|
158
214
|
to_ret_prop += suffix;
|
|
159
215
|
|
|
160
216
|
if (prop.comment && commentStyle !== 'none') {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
217
|
+
to_ret_prop = addComment(to_ret_prop, {
|
|
218
|
+
comment: prop.comment,
|
|
219
|
+
style: commentStyle,
|
|
220
|
+
position: commentPosition,
|
|
221
|
+
indentation,
|
|
222
|
+
});
|
|
166
223
|
}
|
|
167
224
|
|
|
168
225
|
return to_ret_prop;
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
|
-
import { unique } from '../../utils/es6_.js';
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
15
|
* Given some value, returns a basic valid TypeScript type for that value.
|
|
@@ -22,7 +21,7 @@ import { unique } from '../../utils/es6_.js';
|
|
|
22
21
|
* StyleDictionary.registerFormat({
|
|
23
22
|
* name: 'myCustomFormat',
|
|
24
23
|
* formatter: function({ dictionary, options }) {
|
|
25
|
-
* return dictionary.
|
|
24
|
+
* return dictionary.allTokens.map(function(prop) {
|
|
26
25
|
* var to_ret_prop = 'export const ' + prop.name + ' : ' + getTypeScriptType(prop.value) + ';';
|
|
27
26
|
* if (prop.comment)
|
|
28
27
|
* to_ret_prop = to_ret_prop.concat(' // ' + prop.comment);
|
|
@@ -72,11 +71,13 @@ function getArrayType(passedArray) {
|
|
|
72
71
|
if (passedArray.every((v) => getTypeScriptType(v) === firstValueType)) {
|
|
73
72
|
return firstValueType + '[]';
|
|
74
73
|
} else {
|
|
75
|
-
return `(${
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
return `(${Array.from(
|
|
75
|
+
new Set(
|
|
76
|
+
passedArray.map((item, index) => {
|
|
77
|
+
const isLast = passedArray.length === index + 1;
|
|
78
|
+
return `${getTypeScriptType(item)}${!isLast ? ' | ' : ''}`;
|
|
79
|
+
}),
|
|
80
|
+
),
|
|
80
81
|
).join('')})[]`;
|
|
81
82
|
}
|
|
82
83
|
}
|
package/lib/common/formats.js
CHANGED
|
@@ -468,7 +468,7 @@ const formats = {
|
|
|
468
468
|
'typescript/es6-declarations': function ({ dictionary, file, options }) {
|
|
469
469
|
return (
|
|
470
470
|
fileHeader({ file }) +
|
|
471
|
-
dictionary.
|
|
471
|
+
dictionary.allTokens
|
|
472
472
|
.map(function (prop) {
|
|
473
473
|
let to_ret_prop = '';
|
|
474
474
|
if (prop.comment) to_ret_prop += '/** ' + prop.comment + ' */\n';
|
|
@@ -529,7 +529,7 @@ const formats = {
|
|
|
529
529
|
* formatter: function({ dictionary }) {
|
|
530
530
|
* return 'declare const root: RootObject\n' +
|
|
531
531
|
* 'export default root\n' +
|
|
532
|
-
* JsonToTS(dictionary.
|
|
532
|
+
* JsonToTS(dictionary.tokens).join('\n');
|
|
533
533
|
* },
|
|
534
534
|
* });
|
|
535
535
|
* ```
|
|
@@ -788,7 +788,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
|
|
|
788
788
|
*/
|
|
789
789
|
'compose/object': function ({ dictionary, options, file }) {
|
|
790
790
|
const template = _template(composeObject);
|
|
791
|
-
let
|
|
791
|
+
let allTokens;
|
|
792
792
|
const { outputReferences } = options;
|
|
793
793
|
const formatProperty = createPropertyFormatter({
|
|
794
794
|
outputReferences,
|
|
@@ -800,14 +800,14 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul
|
|
|
800
800
|
});
|
|
801
801
|
|
|
802
802
|
if (outputReferences) {
|
|
803
|
-
|
|
803
|
+
allTokens = [...dictionary.allTokens].sort(sortByReference(dictionary));
|
|
804
804
|
} else {
|
|
805
|
-
|
|
805
|
+
allTokens = [...dictionary.allTokens].sort(sortByName);
|
|
806
806
|
}
|
|
807
807
|
|
|
808
808
|
options = setComposeObjectProperties(options);
|
|
809
809
|
|
|
810
|
-
return template({
|
|
810
|
+
return template({ allTokens, file, options, formatProperty, fileHeader });
|
|
811
811
|
},
|
|
812
812
|
|
|
813
813
|
// iOS templates
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export default `<% Object.values(
|
|
1
|
+
export default `<% Object.values(tokens && tokens.asset && tokens.asset.font || {}).forEach(function(font) {
|
|
2
2
|
var fileFormatArr = [];
|
|
3
3
|
if (font.eot) {
|
|
4
4
|
fileFormatArr.push("url('../" + font.eot.value + "');\\n\\tsrc: url('../" + font.eot.value + "?#iefix') format('embedded-opentype')");
|
|
@@ -34,7 +34,7 @@ export default `<%
|
|
|
34
34
|
static dispatch_once_t onceToken;
|
|
35
35
|
|
|
36
36
|
dispatch_once(&onceToken, ^{
|
|
37
|
-
dictionary = <%= buildDictionary(dictionary.
|
|
37
|
+
dictionary = <%= buildDictionary(dictionary.tokens) %>;
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
return dictionary;
|
|
@@ -42,25 +42,25 @@ export default `<%
|
|
|
42
42
|
|
|
43
43
|
@end
|
|
44
44
|
|
|
45
|
-
<% function buildDictionary(
|
|
45
|
+
<% function buildDictionary(tokens, indent) {
|
|
46
46
|
indent = indent || ' ';
|
|
47
47
|
var to_ret = '@{\\n';
|
|
48
|
-
if (
|
|
49
|
-
var value =
|
|
48
|
+
if (tokens.hasOwnProperty('value')) {
|
|
49
|
+
var value = tokens.attributes.category === 'size' || tokens.attributes.category === 'time' ? '@' + tokens.value : tokens.value;
|
|
50
50
|
to_ret += indent + '@"value": ' + value + ',\\n';
|
|
51
|
-
to_ret += indent + '@"name": @"' +
|
|
51
|
+
to_ret += indent + '@"name": @"' + tokens.name + '",\\n';
|
|
52
52
|
|
|
53
|
-
for(var name in
|
|
54
|
-
if (
|
|
55
|
-
to_ret += indent + '@"' + name + '": @"' +
|
|
53
|
+
for(var name in tokens.attributes) {
|
|
54
|
+
if (tokens.attributes[name]) {
|
|
55
|
+
to_ret += indent + '@"' + name + '": @"' + tokens.attributes[name] + '",\\n';
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// remove last comma
|
|
60
60
|
return to_ret.slice(0, -2) + '\\n' + indent + '}';
|
|
61
61
|
} else {
|
|
62
|
-
for(var name in
|
|
63
|
-
to_ret += indent + '@"' + name + '": ' + buildDictionary(
|
|
62
|
+
for(var name in tokens) {
|
|
63
|
+
to_ret += indent + '@"' + name + '": ' + buildDictionary(tokens[name], indent + ' ') + ',\\n';
|
|
64
64
|
}
|
|
65
65
|
// remove last comma
|
|
66
66
|
return to_ret.slice(0, -2) + '\\n' + indent + '}';
|
|
@@ -17,9 +17,9 @@ export default `<%
|
|
|
17
17
|
// output the list of tokens as a Sass nested map
|
|
18
18
|
// (the values are pointing to the variables)
|
|
19
19
|
//
|
|
20
|
-
print(\`$\${file.mapName||'tokens'}: \${processJsonNode(dictionary.
|
|
20
|
+
print(\`$\${file.mapName||'tokens'}: \${processJsonNode(dictionary.tokens, 0)};\\n\`);
|
|
21
21
|
|
|
22
|
-
// recursive function to process a
|
|
22
|
+
// recursive function to process a tokens JSON node
|
|
23
23
|
//
|
|
24
24
|
function processJsonNode(obj, depth) {
|
|
25
25
|
var output = '';
|
|
@@ -31,7 +31,7 @@ export default `<%
|
|
|
31
31
|
// if we have found a leaf (a property with a value) append the value
|
|
32
32
|
output += \`$\${obj.name}\`;
|
|
33
33
|
} else {
|
|
34
|
-
// if we have found a group of
|
|
34
|
+
// if we have found a group of tokens, use the Sass group "(...)" syntax and loop -recursively- on the children
|
|
35
35
|
output += '(\\n'
|
|
36
36
|
output += Object.keys(obj).map(function(newKey) {
|
|
37
37
|
var newProp = obj[newKey];
|
package/lib/common/transforms.js
CHANGED
|
@@ -13,9 +13,16 @@
|
|
|
13
13
|
|
|
14
14
|
import Color from 'tinycolor2';
|
|
15
15
|
import path from '@bundled-es-modules/path-browserify';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
camelCaseTransformMerge,
|
|
18
|
+
snakeCase,
|
|
19
|
+
paramCase as kebabCase,
|
|
20
|
+
camelCase as _camelCase,
|
|
21
|
+
} from 'change-case';
|
|
17
22
|
import convertToBase64 from '../utils/convertToBase64.js';
|
|
18
23
|
|
|
24
|
+
const camelCase = (str) => _camelCase(str, { transform: camelCaseTransformMerge });
|
|
25
|
+
|
|
19
26
|
const UNICODE_PATTERN = /&#x([^;]+);/g;
|
|
20
27
|
|
|
21
28
|
function isColor(token) {
|
|
@@ -281,6 +288,9 @@ export default {
|
|
|
281
288
|
'name/cti/pascal': {
|
|
282
289
|
type: 'name',
|
|
283
290
|
transformer: function (token, options) {
|
|
291
|
+
const upperFirst = function (str) {
|
|
292
|
+
return str ? str[0].toUpperCase() + str.substr(1) : '';
|
|
293
|
+
};
|
|
284
294
|
return upperFirst(camelCase([options.prefix].concat(token.path).join(' ')));
|
|
285
295
|
},
|
|
286
296
|
},
|