style-dictionary 4.0.0-prerelease.1 → 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/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
|
},
|
|
@@ -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
|
},
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
|
|
5
|
+
* the License. A copy of the License is located at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
10
|
+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
|
|
11
|
+
* and limitations under the License.
|
|
12
|
+
*/
|
|
13
|
+
import { isPlainObject } from 'is-plain-object';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Takes a nested object of tokens and filters them using the provided
|
|
17
|
+
* function.
|
|
18
|
+
*
|
|
19
|
+
* @param {Object|undefined|null} tokens
|
|
20
|
+
* @param {Function} filter - A function that receives a property object and
|
|
21
|
+
* returns `true` if the property should be included in the output or `false`
|
|
22
|
+
* if the property should be excluded from the output.
|
|
23
|
+
* @returns {Object[]} tokens - A new object containing only the tokens
|
|
24
|
+
* that matched the filter.
|
|
25
|
+
*/
|
|
26
|
+
function filterTokenObject(tokens, filter) {
|
|
27
|
+
// Use reduce to generate a new object with the unwanted tokens filtered
|
|
28
|
+
// out
|
|
29
|
+
return Object.entries(tokens ?? []).reduce((acc, [key, value]) => {
|
|
30
|
+
// If the value is not an object, we don't know what it is. We return it as-is.
|
|
31
|
+
if (!isPlainObject(value)) {
|
|
32
|
+
return acc;
|
|
33
|
+
// If the value has a `value` member we know it's a property, pass it to
|
|
34
|
+
// the filter function and either include it in the final `acc` object or
|
|
35
|
+
// exclude it (by returning the `acc` object without it added).
|
|
36
|
+
} else if (typeof value.value !== 'undefined') {
|
|
37
|
+
return filter(value) ? { ...acc, [key]: value } : acc;
|
|
38
|
+
// If we got here we have an object that is not a property. We'll assume
|
|
39
|
+
// it's an object containing multiple tokens and recursively filter it
|
|
40
|
+
// using the `filterTokenObject` function.
|
|
41
|
+
} else {
|
|
42
|
+
const filtered = filterTokenObject(value, filter);
|
|
43
|
+
// If the filtered object is not empty then add it to the final `acc`
|
|
44
|
+
// object. If it is empty then every property inside of it was filtered
|
|
45
|
+
// out, then exclude it entirely from the final `acc` object.
|
|
46
|
+
return Object.entries(filtered || {}).length < 1 ? acc : { ...acc, [key]: filtered };
|
|
47
|
+
}
|
|
48
|
+
}, {});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Takes a dictionary and filters the `allTokens` array and the `tokens`
|
|
53
|
+
* object using a function provided by the user.
|
|
54
|
+
*
|
|
55
|
+
* @param {Object} dictionary
|
|
56
|
+
* @param {Function} filter - A function that receives a token object
|
|
57
|
+
* and returns `true` if the token should be included in the output
|
|
58
|
+
* or `false` if the token should be excluded from the output
|
|
59
|
+
* @returns {Object} dictionary - A new dictionary containing only the
|
|
60
|
+
* tokens that matched the filter (or the original dictionary if no filter
|
|
61
|
+
* function was provided).
|
|
62
|
+
*/
|
|
63
|
+
export default function filterTokens(dictionary, filter) {
|
|
64
|
+
if (!filter) {
|
|
65
|
+
return dictionary;
|
|
66
|
+
} else {
|
|
67
|
+
if (typeof filter !== 'function') {
|
|
68
|
+
throw new Error('filter is not a function');
|
|
69
|
+
} else {
|
|
70
|
+
return {
|
|
71
|
+
allTokens: (dictionary.allTokens ?? []).filter(filter),
|
|
72
|
+
tokens: filterTokenObject(dictionary.tokens, filter),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
|
|
5
|
+
* the License. A copy of the License is located at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
10
|
+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
|
|
11
|
+
* and limitations under the License.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {import('../../types/Preprocessor').Preprocessor} Preprocessor
|
|
16
|
+
* Adds a custom preprocessor to preprocess the parsed dictionary, before transforming individual tokens.
|
|
17
|
+
* @static
|
|
18
|
+
* @memberof module:style-dictionary
|
|
19
|
+
* @param {Object} Preprocessor - Preprocessor object
|
|
20
|
+
* @param {String} Preprocessor.name - Name of the format to be referenced in your config.json
|
|
21
|
+
* @param {function} Preprocessor.preprocessor - Function to preprocess the dictionary. The function should return a plain Javascript object.
|
|
22
|
+
* @returns {module:style-dictionary}
|
|
23
|
+
* @example
|
|
24
|
+
* ```js
|
|
25
|
+
* StyleDictionary.registerPreprocessor((dictionary) => {
|
|
26
|
+
* return dictionary;
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export default function registerPreprocessor(cfg) {
|
|
31
|
+
const errorPrefix = 'Cannot register preprocessor;';
|
|
32
|
+
if (typeof cfg.name !== 'string')
|
|
33
|
+
throw new Error(`${errorPrefix} Preprocessor.name must be a string`);
|
|
34
|
+
if (!(cfg.preprocessor instanceof Function)) {
|
|
35
|
+
throw new Error(`${errorPrefix} Preprocessor.preprocessor must be a function`);
|
|
36
|
+
}
|
|
37
|
+
this.preprocessors[cfg.name] = cfg.preprocessor;
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
@@ -54,12 +54,13 @@ export default function registerTransform(options) {
|
|
|
54
54
|
throw new Error('matcher must be a function');
|
|
55
55
|
if (typeof options.transformer !== 'function') throw new Error('transformer must be a function');
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
const transform = {
|
|
58
58
|
type: options.type,
|
|
59
59
|
matcher: options.matcher,
|
|
60
60
|
transitive: !!options.transitive,
|
|
61
61
|
transformer: options.transformer,
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
+
this.transform[options.name] = transform;
|
|
64
65
|
return this;
|
|
65
66
|
}
|
|
@@ -11,8 +11,6 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { isArray } from '../utils/es6_.js';
|
|
15
|
-
|
|
16
14
|
/**
|
|
17
15
|
* Add a custom transformGroup to the Style Dictionary, which is a
|
|
18
16
|
* group of transforms.
|
|
@@ -36,7 +34,7 @@ import { isArray } from '../utils/es6_.js';
|
|
|
36
34
|
*/
|
|
37
35
|
export default function registerTransformGroup(options) {
|
|
38
36
|
if (typeof options.name !== 'string') throw new Error('transform name must be a string');
|
|
39
|
-
if (!isArray(options.transforms))
|
|
37
|
+
if (!Array.isArray(options.transforms))
|
|
40
38
|
throw new Error('transforms must be an array of registered value transforms');
|
|
41
39
|
|
|
42
40
|
options.transforms.forEach(
|