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/transform/config.js
CHANGED
|
@@ -11,25 +11,25 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { isPlainObject } from 'is-plain-object';
|
|
15
15
|
import deepExtend from '../utils/deepExtend.js';
|
|
16
16
|
import GroupMessages from '../utils/groupMessages.js';
|
|
17
17
|
|
|
18
|
-
const TEMPLATE_DEPRECATION_WARNINGS = GroupMessages.GROUP.TemplateDeprecationWarnings;
|
|
19
18
|
const MISSING_TRANSFORM_ERRORS = GroupMessages.GROUP.MissingRegisterTransformErrors;
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
|
-
* Takes a platform
|
|
21
|
+
* Takes a platform platformConfig object and returns a new one
|
|
23
22
|
* that has filters, transforms, formats, and actions
|
|
24
23
|
* mapped properly.
|
|
25
24
|
* @private
|
|
26
|
-
* @param {Object}
|
|
25
|
+
* @param {Object} platformConfig
|
|
27
26
|
* @param {Object} dictionary
|
|
28
27
|
* @param {Object} platformName (only used for error messaging)
|
|
29
28
|
* @returns {Object}
|
|
30
29
|
*/
|
|
31
|
-
export default function transformConfig(
|
|
32
|
-
const to_ret =
|
|
30
|
+
export default function transformConfig(platformConfig, dictionary, platformName) {
|
|
31
|
+
const to_ret = { ...platformConfig }; // structuredClone not suitable due to config being able to contain Function() etc.
|
|
32
|
+
to_ret.log = platformConfig.log ?? dictionary.log;
|
|
33
33
|
|
|
34
34
|
// The platform can define either a transformGroup or an array
|
|
35
35
|
// of transforms. If given a transformGroup that doesn't exist,
|
|
@@ -82,8 +82,8 @@ None of ${transform_warnings} match the name of a registered transform.
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// Apply registered fileHeaders onto the platform options
|
|
85
|
-
if (
|
|
86
|
-
const fileHeader =
|
|
85
|
+
if (platformConfig.options && platformConfig.options.fileHeader) {
|
|
86
|
+
const fileHeader = platformConfig.options.fileHeader;
|
|
87
87
|
if (typeof fileHeader === 'string') {
|
|
88
88
|
if (dictionary.fileHeader[fileHeader]) {
|
|
89
89
|
to_ret.options.fileHeader = dictionary.fileHeader[fileHeader];
|
|
@@ -97,7 +97,7 @@ None of ${transform_warnings} match the name of a registered transform.
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
to_ret.files = (
|
|
100
|
+
to_ret.files = (platformConfig.files || []).map(function (file) {
|
|
101
101
|
const ext = { options: {} };
|
|
102
102
|
if (file.options && file.options.fileHeader) {
|
|
103
103
|
const fileHeader = file.options.fileHeader;
|
|
@@ -122,6 +122,21 @@ None of ${transform_warnings} match the name of a registered transform.
|
|
|
122
122
|
throw new Error("Can't find filter: " + file.filter);
|
|
123
123
|
}
|
|
124
124
|
} else if (typeof file.filter === 'object') {
|
|
125
|
+
// Recursively go over the object keys of filter object and
|
|
126
|
+
// return a filter Function that filters tokens
|
|
127
|
+
// by the specified object keys.
|
|
128
|
+
const matchFn = function (inputObj, testObj) {
|
|
129
|
+
if (isPlainObject(testObj)) {
|
|
130
|
+
return Object.keys(testObj).every((key) => matchFn(inputObj[key], testObj[key]));
|
|
131
|
+
} else {
|
|
132
|
+
return inputObj == testObj;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const matches = function (matchObj) {
|
|
136
|
+
let cloneObj = { ...matchObj }; // shallow clone, structuredClone not suitable because obj can contain "Function()"
|
|
137
|
+
let matchesFn = (inputObj) => matchFn(inputObj, cloneObj);
|
|
138
|
+
return matchesFn;
|
|
139
|
+
};
|
|
125
140
|
ext.filter = matches(file.filter);
|
|
126
141
|
} else if (typeof file.filter === 'function') {
|
|
127
142
|
ext.filter = file.filter;
|
|
@@ -130,17 +145,7 @@ None of ${transform_warnings} match the name of a registered transform.
|
|
|
130
145
|
}
|
|
131
146
|
}
|
|
132
147
|
|
|
133
|
-
if (file.
|
|
134
|
-
if (dictionary.format[file.template]) {
|
|
135
|
-
GroupMessages.add(
|
|
136
|
-
TEMPLATE_DEPRECATION_WARNINGS,
|
|
137
|
-
`${file.destination} (template: ${file.template})`,
|
|
138
|
-
);
|
|
139
|
-
ext.format = dictionary.format[file.template];
|
|
140
|
-
} else {
|
|
141
|
-
throw new Error("Can't find template: " + file.template);
|
|
142
|
-
}
|
|
143
|
-
} else if (file.format) {
|
|
148
|
+
if (file.format) {
|
|
144
149
|
if (dictionary.format[file.format]) {
|
|
145
150
|
ext.format = dictionary.format[file.format];
|
|
146
151
|
} else {
|
|
@@ -152,7 +157,7 @@ None of ${transform_warnings} match the name of a registered transform.
|
|
|
152
157
|
return deepExtend([{}, file, ext]);
|
|
153
158
|
});
|
|
154
159
|
|
|
155
|
-
to_ret.actions = (
|
|
160
|
+
to_ret.actions = (platformConfig.actions || []).map(function (action) {
|
|
156
161
|
if (typeof dictionary.action[action].undo !== 'function') {
|
|
157
162
|
console.warn(action + ' action does not have a clean function!');
|
|
158
163
|
}
|
package/lib/transform/object.js
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { isPlainObject
|
|
14
|
+
import { isPlainObject } from 'is-plain-object';
|
|
15
15
|
import usesValueReference from '../utils/references/usesReference.js';
|
|
16
16
|
import getName from '../utils/references/getName.js';
|
|
17
|
-
import
|
|
18
|
-
import
|
|
17
|
+
import transformToken from './token.js';
|
|
18
|
+
import tokenSetup from './tokenSetup.js';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Applies transforms on all tokens. This
|
|
@@ -26,7 +26,7 @@ import propertySetup from './propertySetup.js';
|
|
|
26
26
|
* @private
|
|
27
27
|
* @param {Object} obj
|
|
28
28
|
* @param {Object} options
|
|
29
|
-
* @param {Object} [
|
|
29
|
+
* @param {Object} [ctx={}]
|
|
30
30
|
* @param {Array} [path=[]]
|
|
31
31
|
* @param {Object} [transformedObj={}]
|
|
32
32
|
* @returns {Object}
|
|
@@ -34,13 +34,12 @@ import propertySetup from './propertySetup.js';
|
|
|
34
34
|
export default function transformObject(
|
|
35
35
|
obj,
|
|
36
36
|
options,
|
|
37
|
-
|
|
37
|
+
{ transformedPropRefs = [], deferredPropValueTransforms = [] } = {},
|
|
38
38
|
path,
|
|
39
39
|
transformedObj,
|
|
40
40
|
) {
|
|
41
41
|
transformedObj = transformedObj || {};
|
|
42
42
|
path = path || [];
|
|
43
|
-
const { transformedPropRefs = [], deferredPropValueTransforms = [] } = transformationContext;
|
|
44
43
|
|
|
45
44
|
for (const name in obj) {
|
|
46
45
|
if (!obj.hasOwnProperty(name)) {
|
|
@@ -68,9 +67,9 @@ export default function transformObject(
|
|
|
68
67
|
continue;
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
// Note:
|
|
70
|
+
// Note: tokenSetup won't re-run if property has already been setup
|
|
72
71
|
// it is safe to run this multiple times on the same property.
|
|
73
|
-
const setupProperty =
|
|
72
|
+
const setupProperty = tokenSetup(objProp, name, path);
|
|
74
73
|
|
|
75
74
|
// If property has a reference, defer its transformations until later
|
|
76
75
|
if (usesValueReference(setupProperty.value, options)) {
|
|
@@ -86,9 +85,16 @@ export default function transformObject(
|
|
|
86
85
|
|
|
87
86
|
// If we got here, the property hasn't been transformed yet and
|
|
88
87
|
// does not use a value reference. Transform the property now and assign it.
|
|
89
|
-
transformedObj[name] =
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
transformedObj[name] = transformToken(setupProperty, options);
|
|
89
|
+
|
|
90
|
+
// Remove the property path from the deferred transform list, starting from end of array
|
|
91
|
+
for (let i = deferredPropValueTransforms.length - 1; i >= 0; i--) {
|
|
92
|
+
if (deferredPropValueTransforms[i] === pathName) {
|
|
93
|
+
// Important to use .splice and mutate the original array all the way up
|
|
94
|
+
deferredPropValueTransforms.splice(i, 1);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
// Add the property path to the transformed list so we don't transform it again.
|
|
93
99
|
transformedPropRefs.push(pathName);
|
|
94
100
|
} else if (isObj) {
|
|
@@ -96,7 +102,7 @@ export default function transformObject(
|
|
|
96
102
|
transformedObj[name] = transformObject(
|
|
97
103
|
objProp,
|
|
98
104
|
options,
|
|
99
|
-
|
|
105
|
+
{ transformedPropRefs, deferredPropValueTransforms },
|
|
100
106
|
path,
|
|
101
107
|
transformedObj[name],
|
|
102
108
|
);
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { clone } from '../utils/es6_.js';
|
|
15
14
|
import usesReference from '../utils/references/usesReference.js';
|
|
16
15
|
|
|
17
16
|
/**
|
|
@@ -23,7 +22,7 @@ import usesReference from '../utils/references/usesReference.js';
|
|
|
23
22
|
* @returns {Object} - A new property object with transforms applied.
|
|
24
23
|
*/
|
|
25
24
|
export default function transformProperty(property, options) {
|
|
26
|
-
const to_ret =
|
|
25
|
+
const to_ret = structuredClone(property);
|
|
27
26
|
const transforms = options.transforms;
|
|
28
27
|
|
|
29
28
|
for (let i = 0; i < transforms.length; i++) {
|
|
@@ -11,34 +11,34 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
import { isPlainObject } from 'is-plain-object';
|
|
14
15
|
import deepExtend from '../utils/deepExtend.js';
|
|
15
|
-
import { isPlainObject, isString, isArray, clone } from '../utils/es6_.js';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Takes a
|
|
19
|
-
* returns a new object that has some
|
|
18
|
+
* Takes a token object, a leaf node in a tokens object, and
|
|
19
|
+
* returns a new object that has some tokens set. It clones the
|
|
20
20
|
* original object for safekeeping, adds a name, adds an attributes object,
|
|
21
21
|
* and a path array.
|
|
22
22
|
* @private
|
|
23
|
-
* @param {Object}
|
|
24
|
-
* @param {String} name - The name of the
|
|
25
|
-
* @param {Array} path - The path of keys to get to the
|
|
23
|
+
* @param {Object} token - the token object to setup
|
|
24
|
+
* @param {String} name - The name of the token, which will should be its key in the object.
|
|
25
|
+
* @param {Array} path - The path of keys to get to the token from the top level of the tokens object.
|
|
26
26
|
* @returns {Object} - A new object that is setup and ready to go.
|
|
27
27
|
*/
|
|
28
|
-
export default function
|
|
29
|
-
if (!
|
|
30
|
-
if (!name || !
|
|
31
|
-
if (!path || !isArray(path)) throw new Error('Path must be an array');
|
|
28
|
+
export default function tokenSetup(token, name, path) {
|
|
29
|
+
if (!token && !isPlainObject(token)) throw new Error('Property object must be an object');
|
|
30
|
+
if (!name || !(typeof name === 'string')) throw new Error('Name must be a string');
|
|
31
|
+
if (!path || !Array.isArray(path)) throw new Error('Path must be an array');
|
|
32
32
|
|
|
33
|
-
let to_ret =
|
|
33
|
+
let to_ret = token;
|
|
34
34
|
|
|
35
35
|
// Only do this once
|
|
36
|
-
if (!
|
|
37
|
-
// Initial
|
|
38
|
-
// Keep the original object
|
|
36
|
+
if (!token.original) {
|
|
37
|
+
// Initial token setup
|
|
38
|
+
// Keep the original object tokens like it was in file (whitout additional data)
|
|
39
39
|
// so we can key off them in the transforms
|
|
40
|
-
to_ret = deepExtend([{},
|
|
41
|
-
let to_ret_original = deepExtend([{},
|
|
40
|
+
to_ret = deepExtend([{}, token]);
|
|
41
|
+
let to_ret_original = deepExtend([{}, token]);
|
|
42
42
|
delete to_ret_original.filePath;
|
|
43
43
|
delete to_ret_original.isSource;
|
|
44
44
|
|
|
@@ -49,7 +49,7 @@ export default function propertySetup(property, name, path) {
|
|
|
49
49
|
to_ret.attributes = to_ret.attributes || {};
|
|
50
50
|
// An array of the path down the object tree; we will use it to build readable names
|
|
51
51
|
// like color_font_base
|
|
52
|
-
to_ret.path =
|
|
52
|
+
to_ret.path = structuredClone(path);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
return to_ret;
|
package/lib/utils/combineJSON.js
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
import JSON5 from 'json5';
|
|
15
15
|
import glob from '@bundled-es-modules/glob';
|
|
16
16
|
import path from '@bundled-es-modules/path-browserify';
|
|
17
|
+
import { fs } from 'style-dictionary/fs';
|
|
17
18
|
import deepExtend from './deepExtend.js';
|
|
18
|
-
import { fs } from '../../fs.js';
|
|
19
19
|
|
|
20
20
|
function traverseObj(obj, fn) {
|
|
21
21
|
for (let key in obj) {
|
|
@@ -33,41 +33,51 @@ function traverseObj(obj, fn) {
|
|
|
33
33
|
* @param {String[]} arr - Array of paths to json (or node modules that export objects) files
|
|
34
34
|
* @param {Boolean} [deep=false] - If it should perform a deep merge
|
|
35
35
|
* @param {Function} collision - A function to be called when a name collision happens that isn't a normal deep merge of objects
|
|
36
|
-
* @param {Boolean} [source=true] - If json files are "sources", tag
|
|
36
|
+
* @param {Boolean} [source=true] - If json files are "sources", tag tokens
|
|
37
37
|
* @param {Object[]} [parsers=[]] - Custom file parsers
|
|
38
38
|
* @returns {Object}
|
|
39
39
|
*/
|
|
40
|
-
export default function combineJSON(arr, deep, collision, source, parsers = []) {
|
|
40
|
+
export default async function combineJSON(arr, deep, collision, source, parsers = []) {
|
|
41
41
|
const to_ret = {};
|
|
42
42
|
let files = [];
|
|
43
43
|
|
|
44
44
|
for (let i = 0; i < arr.length; i++) {
|
|
45
|
-
const new_files = glob.sync(arr[i], { fs });
|
|
45
|
+
const new_files = glob.sync(arr[i], { fs }).sort();
|
|
46
46
|
files = files.concat(new_files);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
// adjust for browser env glob results have leading slash
|
|
50
|
+
files = files.map((f) => f.replace(/^\//, ''));
|
|
51
|
+
|
|
49
52
|
for (let i = 0; i < files.length; i++) {
|
|
50
53
|
const filePath = files[i];
|
|
51
|
-
const resolvedPath = path.isAbsolute(files[i])
|
|
52
|
-
? files[i]
|
|
53
|
-
: path.resolve(process.cwd(), files[i]);
|
|
54
54
|
let file_content = null;
|
|
55
|
-
|
|
56
55
|
try {
|
|
57
56
|
// Iterate over custom parsers, if the file path matches the parser's
|
|
58
57
|
// pattern regex, use it's parse function to generate the object
|
|
59
58
|
parsers.forEach(({ pattern, parse }) => {
|
|
60
|
-
if (
|
|
59
|
+
if (filePath.match(pattern)) {
|
|
61
60
|
file_content = parse({
|
|
62
|
-
contents: fs.readFileSync(
|
|
63
|
-
filePath
|
|
61
|
+
contents: fs.readFileSync(filePath, { encoding: 'UTF-8' }),
|
|
62
|
+
filePath,
|
|
64
63
|
});
|
|
65
64
|
}
|
|
66
65
|
});
|
|
67
66
|
|
|
68
67
|
// If there is no file_content then no custom parser ran on that file
|
|
69
68
|
if (!file_content) {
|
|
70
|
-
|
|
69
|
+
let parsedFile;
|
|
70
|
+
if (['.js', '.mjs'].includes(path.extname(filePath))) {
|
|
71
|
+
const fileToImport = path.resolve(
|
|
72
|
+
typeof window === 'object' ? '' : process.cwd(),
|
|
73
|
+
filePath,
|
|
74
|
+
);
|
|
75
|
+
parsedFile = (await import(fileToImport)).default;
|
|
76
|
+
} else {
|
|
77
|
+
parsedFile = JSON5.parse(fs.readFileSync(filePath));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
file_content = deepExtend([file_content, parsedFile]);
|
|
71
81
|
}
|
|
72
82
|
} catch (e) {
|
|
73
83
|
e.message = 'Failed to load or parse JSON or JS Object: ' + e.message;
|
|
@@ -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
|
* Takes a file and converts it to a base64 string.
|
|
@@ -22,6 +22,6 @@ import { fs } from '../../fs.js';
|
|
|
22
22
|
export default function convertToBase64(filePath) {
|
|
23
23
|
if (typeof filePath !== 'string') throw new Error('filePath name must be a string');
|
|
24
24
|
|
|
25
|
-
const body = fs.readFileSync(filePath
|
|
26
|
-
return
|
|
25
|
+
const body = fs.readFileSync(filePath);
|
|
26
|
+
return btoa(body);
|
|
27
27
|
}
|
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import
|
|
14
|
+
import flattenTokens from './flattenTokens.js';
|
|
15
15
|
import getReferences from './references/getReferences.js';
|
|
16
16
|
import usesReference from './references/usesReference.js';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
*
|
|
20
20
|
* @typedef Dictionary
|
|
21
|
-
* @property {Object} tokens
|
|
22
|
-
* @property {Array} allTokens
|
|
21
|
+
* @property {Object} $tokens
|
|
22
|
+
* @property {Array} allTokens
|
|
23
23
|
* @property {Dictionary.getReferences} getReferences
|
|
24
24
|
* @property {Dictionary.usesReference} usesReference
|
|
25
25
|
*/
|
|
@@ -27,19 +27,15 @@ import usesReference from './references/usesReference.js';
|
|
|
27
27
|
/**
|
|
28
28
|
* Creates the dictionary object that is passed to formats and actions.
|
|
29
29
|
* @param {Object} args
|
|
30
|
-
* @param {Object} args.
|
|
30
|
+
* @param {Object} args.tokens
|
|
31
31
|
* @returns {Dictionary}
|
|
32
32
|
*/
|
|
33
|
-
export default function createDictionary({
|
|
34
|
-
const
|
|
33
|
+
export default function createDictionary({ tokens }) {
|
|
34
|
+
const allTokens = flattenTokens(tokens);
|
|
35
35
|
return {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
tokens: properties,
|
|
41
|
-
allTokens: allProperties,
|
|
42
|
-
getReferences: getReferences,
|
|
43
|
-
usesReference: usesReference,
|
|
36
|
+
tokens,
|
|
37
|
+
allTokens,
|
|
38
|
+
getReferences,
|
|
39
|
+
usesReference,
|
|
44
40
|
};
|
|
45
41
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import deepExtend from './deepExtend.js';
|
|
15
15
|
|
|
16
16
|
export default function createFormatArgs({ dictionary, platform, file = {} }) {
|
|
17
|
-
const {
|
|
17
|
+
const { allTokens, tokens, usesReference, getReferences } = dictionary;
|
|
18
18
|
// This will merge platform and file-level configuration
|
|
19
19
|
// where the file configuration takes precedence
|
|
20
20
|
const { options } = platform;
|
|
@@ -24,10 +24,6 @@ export default function createFormatArgs({ dictionary, platform, file = {} }) {
|
|
|
24
24
|
dictionary,
|
|
25
25
|
usesReference,
|
|
26
26
|
getReferences,
|
|
27
|
-
allProperties,
|
|
28
|
-
properties,
|
|
29
|
-
// adding tokens and allTokens as the new way starting in v3,
|
|
30
|
-
// keeping properties and allProperties around for backwards-compatibility
|
|
31
27
|
allTokens,
|
|
32
28
|
tokens,
|
|
33
29
|
platform,
|
package/lib/utils/deepExtend.js
CHANGED
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { isPlainObject
|
|
14
|
+
import { isPlainObject } from 'is-plain-object';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
+
* TODO: see if we can use deepmerge instead of maintaining our own utility
|
|
18
|
+
*
|
|
17
19
|
* Performs an deep extend on the objects, from right to left.
|
|
18
20
|
* @private
|
|
19
21
|
* @param {Object[]} objects - An array of JS objects
|
|
@@ -24,15 +26,7 @@ import { isPlainObject, isArray } from './es6_.js';
|
|
|
24
26
|
export default function deepExtend(objects, collision, path) {
|
|
25
27
|
if (objects == null) return {};
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
copyIsArray,
|
|
29
|
-
copy,
|
|
30
|
-
name,
|
|
31
|
-
options,
|
|
32
|
-
clone,
|
|
33
|
-
target = objects[0] || {},
|
|
34
|
-
i = 1,
|
|
35
|
-
length = objects.length;
|
|
29
|
+
let target = objects[0] || {};
|
|
36
30
|
|
|
37
31
|
path = path || [];
|
|
38
32
|
|
|
@@ -41,33 +35,36 @@ export default function deepExtend(objects, collision, path) {
|
|
|
41
35
|
target = {};
|
|
42
36
|
}
|
|
43
37
|
|
|
44
|
-
for (; i < length; i++) {
|
|
38
|
+
for (let i = 1; i < objects.length; i++) {
|
|
39
|
+
const options = objects[i];
|
|
45
40
|
// Only deal with non-null/undefined values
|
|
46
|
-
if (
|
|
41
|
+
if (options != null) {
|
|
47
42
|
// Extend the base object
|
|
48
|
-
for (name in options) {
|
|
43
|
+
for (const name in options) {
|
|
49
44
|
// Not everything extends from Object in browser context, so bind from Object just in case
|
|
50
45
|
if (!Object.hasOwnProperty.bind(options)(name)) continue;
|
|
51
46
|
if (name === '__proto__') continue;
|
|
52
47
|
|
|
53
|
-
src = target[name];
|
|
54
|
-
copy = options[name];
|
|
48
|
+
const src = target[name];
|
|
49
|
+
const copy = options[name];
|
|
55
50
|
|
|
56
51
|
// Prevent never-ending loop
|
|
57
52
|
if (target === copy) {
|
|
58
53
|
continue;
|
|
59
54
|
}
|
|
60
55
|
|
|
56
|
+
let copyIsArray = Array.isArray(copy);
|
|
61
57
|
// Recurse if we're merging plain objects or arrays
|
|
62
|
-
if (copy && (isPlainObject(copy) ||
|
|
58
|
+
if (copy && (isPlainObject(copy) || copyIsArray)) {
|
|
59
|
+
let clone;
|
|
63
60
|
if (copyIsArray) {
|
|
64
61
|
copyIsArray = false;
|
|
65
|
-
clone = src && isArray(src) ? src : [];
|
|
62
|
+
clone = src && Array.isArray(src) ? src : [];
|
|
66
63
|
} else {
|
|
67
64
|
clone = src && isPlainObject(src) ? src : {};
|
|
68
65
|
}
|
|
69
66
|
|
|
70
|
-
|
|
67
|
+
const nextPath = path.slice(0);
|
|
71
68
|
nextPath.push(name);
|
|
72
69
|
|
|
73
70
|
// Never move original objects, clone them
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import _deepmerge from '@bundled-es-modules/deepmerge';
|
|
2
|
+
import { isPlainObject } from 'is-plain-object';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Wrapper around deepmerge that merges only plain objects and arrays
|
|
6
|
+
* @param {Object} target
|
|
7
|
+
* @param {Object} source
|
|
8
|
+
*/
|
|
9
|
+
export const deepmerge = (target, source) => {
|
|
10
|
+
return _deepmerge(target, source, {
|
|
11
|
+
// Merge if object is array or a plain object (so not merging functions/class instances together)
|
|
12
|
+
isMergeableObject: (obj) => Array.isArray(obj) || isPlainObject(obj),
|
|
13
|
+
});
|
|
14
|
+
};
|
|
@@ -11,27 +11,27 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { isPlainObject } from '
|
|
14
|
+
import { isPlainObject } from 'is-plain-object';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Takes an plain javascript object and will make a flat array of all the leaf nodes.
|
|
18
18
|
* A leaf node in this context has a 'value' property. Potentially refactor this to
|
|
19
19
|
* be more generic.
|
|
20
20
|
* @private
|
|
21
|
-
* @param {Object}
|
|
22
|
-
* @param {Array} [to_ret=[]] -
|
|
21
|
+
* @param {Object} tokens - The plain object you want flattened into an array.
|
|
22
|
+
* @param {Array} [to_ret=[]] - Tokens array. This function is recursive therefore this is what gets passed along.
|
|
23
23
|
* @return {Array}
|
|
24
24
|
*/
|
|
25
|
-
export default function
|
|
25
|
+
export default function flattenTokens(tokens, to_ret) {
|
|
26
26
|
to_ret = to_ret || [];
|
|
27
27
|
|
|
28
|
-
for (var name in
|
|
29
|
-
if (
|
|
28
|
+
for (var name in tokens) {
|
|
29
|
+
if (tokens.hasOwnProperty(name)) {
|
|
30
30
|
// TODO: this is a bit fragile and arbitrary to stop when we get to a 'value' property.
|
|
31
|
-
if (isPlainObject(
|
|
32
|
-
to_ret.push(
|
|
33
|
-
} else if (isPlainObject(
|
|
34
|
-
|
|
31
|
+
if (isPlainObject(tokens[name]) && 'value' in tokens[name]) {
|
|
32
|
+
to_ret.push(tokens[name]);
|
|
33
|
+
} else if (isPlainObject(tokens[name])) {
|
|
34
|
+
flattenTokens(tokens[name], to_ret);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
* Run all registered preprocessors on the dictionary,
|
|
16
|
+
* returning the preprocessed dictionary in each step.
|
|
17
|
+
*
|
|
18
|
+
* @typedef {import('../../types/DesignToken').DesignTokens} DesignTokens
|
|
19
|
+
* @typedef {import('../../types/Preprocessor').Preprocessor} Preprocessor
|
|
20
|
+
*
|
|
21
|
+
* @param {DesignTokens} tokens
|
|
22
|
+
* @param {Preprocessor[]} preprocessorObj
|
|
23
|
+
* @returns {Promise<DesignTokens>}
|
|
24
|
+
*/
|
|
25
|
+
export async function preprocess(tokens, preprocessorObj = {}) {
|
|
26
|
+
let processedTokens = tokens;
|
|
27
|
+
|
|
28
|
+
const preprocessors = Object.values(preprocessorObj);
|
|
29
|
+
if (preprocessors.length > 0) {
|
|
30
|
+
for (const preprocessor of preprocessors) {
|
|
31
|
+
processedTokens = await preprocessor(processedTokens);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return processedTokens;
|
|
35
|
+
}
|
|
@@ -22,8 +22,8 @@ import defaults from './defaults.js';
|
|
|
22
22
|
* @returns {string} - The paths name
|
|
23
23
|
*/
|
|
24
24
|
export default function getName(path, opts = {}) {
|
|
25
|
-
const options =
|
|
26
|
-
if (!
|
|
25
|
+
const options = { ...defaults, ...opts };
|
|
26
|
+
if (!Array.isArray(path)) {
|
|
27
27
|
throw new Error('Getting name for path failed. Path must be an array');
|
|
28
28
|
}
|
|
29
29
|
return path.join(options.separator);
|
|
@@ -33,7 +33,6 @@ import GroupMessages from '../groupMessages.js';
|
|
|
33
33
|
*/
|
|
34
34
|
export default function getReferences(value, references = []) {
|
|
35
35
|
// `this` is the dictionary object passed to formats and actions
|
|
36
|
-
const self = this;
|
|
37
36
|
const regex = createReferenceRegex({});
|
|
38
37
|
|
|
39
38
|
// this will update the references array with the referenced tokens it finds.
|
|
@@ -44,10 +43,11 @@ export default function getReferences(value, references = []) {
|
|
|
44
43
|
// Find what the value is referencing
|
|
45
44
|
const pathName = getPath(variable);
|
|
46
45
|
|
|
47
|
-
let ref = resolveReference(pathName,
|
|
46
|
+
let ref = resolveReference(pathName, this.tokens);
|
|
47
|
+
|
|
48
48
|
if (!ref) {
|
|
49
|
-
// fall back on
|
|
50
|
-
ref = resolveReference(pathName,
|
|
49
|
+
// fall back on _tokens as it is unfiltered
|
|
50
|
+
ref = resolveReference(pathName, this._tokens);
|
|
51
51
|
// and warn the user about this
|
|
52
52
|
GroupMessages.add(GroupMessages.GROUP.FilteredOutputReferences, variable);
|
|
53
53
|
}
|
|
@@ -56,7 +56,7 @@ export default function getReferences(value, references = []) {
|
|
|
56
56
|
|
|
57
57
|
if (typeof value === 'string') {
|
|
58
58
|
// function inside .replace runs multiple times if there are multiple matches
|
|
59
|
-
value.replace(regex, findReference);
|
|
59
|
+
value.replace(regex, findReference.bind(this));
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// If the token's value is an object, run the replace reference
|
|
@@ -65,11 +65,11 @@ export default function getReferences(value, references = []) {
|
|
|
65
65
|
if (typeof value === 'object') {
|
|
66
66
|
for (const key in value) {
|
|
67
67
|
if (value.hasOwnProperty(key) && typeof value[key] === 'string') {
|
|
68
|
-
value[key].replace(regex, findReference);
|
|
68
|
+
value[key].replace(regex, findReference.bind(this));
|
|
69
69
|
}
|
|
70
70
|
// if it is an object, we go further down the rabbit hole
|
|
71
71
|
if (value.hasOwnProperty(key) && typeof value[key] === 'object') {
|
|
72
|
-
|
|
72
|
+
this.getReferences(value[key], references);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
}
|