@atlaskit/codemod-cli 0.8.0 → 0.8.4

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +12 -2
  3. package/dist/cjs/cli.js +3 -2
  4. package/dist/cjs/index.js +4 -4
  5. package/dist/cjs/main.js +6 -4
  6. package/dist/cjs/presets/index.js +4 -2
  7. package/dist/cjs/presets/theme-to-design-tokens/theme-to-design-tokens.js +181 -0
  8. package/dist/cjs/presets/theme-to-design-tokens/types.js +5 -0
  9. package/dist/cjs/presets/theme-to-design-tokens/utils/ast-meta.js +104 -0
  10. package/dist/cjs/presets/theme-to-design-tokens/utils/ast.js +19 -0
  11. package/dist/cjs/presets/theme-to-design-tokens/utils/color-difference.js +174 -0
  12. package/dist/cjs/presets/theme-to-design-tokens/utils/color-palette-tokens-map.js +129 -0
  13. package/dist/cjs/presets/theme-to-design-tokens/utils/color-to-token.js +88 -0
  14. package/dist/cjs/presets/theme-to-design-tokens/utils/color.js +59 -0
  15. package/dist/cjs/presets/theme-to-design-tokens/utils/fuzzy-search.js +348 -0
  16. package/dist/cjs/presets/theme-to-design-tokens/utils/legacy-colors.js +81 -0
  17. package/dist/cjs/presets/theme-to-design-tokens/utils/named-colors.js +8 -0
  18. package/dist/cjs/transforms.js +1 -1
  19. package/dist/cjs/types.js +5 -3
  20. package/dist/cjs/version.json +1 -1
  21. package/dist/es2019/cli.js +3 -2
  22. package/dist/es2019/main.js +3 -1
  23. package/dist/es2019/presets/index.js +2 -1
  24. package/dist/es2019/presets/theme-to-design-tokens/theme-to-design-tokens.js +137 -0
  25. package/dist/es2019/presets/theme-to-design-tokens/types.js +1 -0
  26. package/dist/es2019/presets/theme-to-design-tokens/utils/ast-meta.js +70 -0
  27. package/dist/es2019/presets/theme-to-design-tokens/utils/ast.js +10 -0
  28. package/dist/es2019/presets/theme-to-design-tokens/utils/color-difference.js +150 -0
  29. package/dist/es2019/presets/theme-to-design-tokens/utils/color-palette-tokens-map.js +122 -0
  30. package/dist/es2019/presets/theme-to-design-tokens/utils/color-to-token.js +75 -0
  31. package/dist/es2019/presets/theme-to-design-tokens/utils/color.js +35 -0
  32. package/dist/es2019/presets/theme-to-design-tokens/utils/fuzzy-search.js +336 -0
  33. package/dist/es2019/presets/theme-to-design-tokens/utils/legacy-colors.js +72 -0
  34. package/dist/es2019/presets/theme-to-design-tokens/utils/named-colors.js +1 -0
  35. package/dist/es2019/version.json +1 -1
  36. package/dist/esm/cli.js +3 -2
  37. package/dist/esm/main.js +6 -4
  38. package/dist/esm/presets/index.js +3 -2
  39. package/dist/esm/presets/theme-to-design-tokens/theme-to-design-tokens.js +165 -0
  40. package/dist/esm/presets/theme-to-design-tokens/types.js +1 -0
  41. package/dist/esm/presets/theme-to-design-tokens/utils/ast-meta.js +88 -0
  42. package/dist/esm/presets/theme-to-design-tokens/utils/ast.js +10 -0
  43. package/dist/esm/presets/theme-to-design-tokens/utils/color-difference.js +160 -0
  44. package/dist/esm/presets/theme-to-design-tokens/utils/color-palette-tokens-map.js +122 -0
  45. package/dist/esm/presets/theme-to-design-tokens/utils/color-to-token.js +78 -0
  46. package/dist/esm/presets/theme-to-design-tokens/utils/color.js +39 -0
  47. package/dist/esm/presets/theme-to-design-tokens/utils/fuzzy-search.js +340 -0
  48. package/dist/esm/presets/theme-to-design-tokens/utils/legacy-colors.js +72 -0
  49. package/dist/esm/presets/theme-to-design-tokens/utils/named-colors.js +1 -0
  50. package/dist/esm/types.js +3 -2
  51. package/dist/esm/version.json +1 -1
  52. package/dist/types/presets/index.d.ts +1 -0
  53. package/dist/types/presets/theme-to-design-tokens/theme-to-design-tokens.d.ts +2 -0
  54. package/dist/types/presets/theme-to-design-tokens/types.d.ts +2 -0
  55. package/dist/types/presets/theme-to-design-tokens/utils/ast-meta.d.ts +4 -0
  56. package/dist/types/presets/theme-to-design-tokens/utils/ast.d.ts +3 -0
  57. package/dist/types/presets/theme-to-design-tokens/utils/color-difference.d.ts +66 -0
  58. package/dist/types/presets/theme-to-design-tokens/utils/color-palette-tokens-map.d.ts +21 -0
  59. package/dist/types/presets/theme-to-design-tokens/utils/color-to-token.d.ts +12 -0
  60. package/dist/types/presets/theme-to-design-tokens/utils/color.d.ts +4 -0
  61. package/dist/types/presets/theme-to-design-tokens/utils/fuzzy-search.d.ts +5 -0
  62. package/dist/types/presets/theme-to-design-tokens/utils/legacy-colors.d.ts +3 -0
  63. package/dist/types/presets/theme-to-design-tokens/utils/named-colors.d.ts +1 -0
  64. package/package.json +4 -2
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.namedColors = void 0;
7
+ var namedColors = ['black', 'silver', 'gray', 'white', 'maroon', 'red', 'purple', 'fuchsia', 'green', 'lime', 'olive', 'yellow', 'navy', 'blue', 'teal', 'aqua', 'orange', 'aliceblue', 'antiquewhite', 'aquamarine', 'azure', 'beige', 'bisque', 'blanchedalmond', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'greenyellow', 'grey', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow', 'limegreen', 'linen', 'magenta', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'oldlace', 'olivedrab', 'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'skyblue', 'slateblue', 'slategray', 'slategrey', 'snow', 'springgreen', 'steelblue', 'tan', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'whitesmoke', 'yellowgreen', 'rebeccapurple'];
8
+ exports.namedColors = namedColors;
@@ -5,7 +5,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.getTransformVersion = exports.getTransformModule = exports.getTransformPath = exports.parseTransformPath = exports.getTransforms = exports.hasTransform = void 0;
8
+ exports.parseTransformPath = exports.hasTransform = exports.getTransforms = exports.getTransformVersion = exports.getTransformPath = exports.getTransformModule = void 0;
9
9
 
10
10
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
11
 
package/dist/cjs/types.js CHANGED
@@ -5,7 +5,9 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.NoTransformsExistError = exports.ValidationError = void 0;
8
+ exports.ValidationError = exports.NoTransformsExistError = void 0;
9
+
10
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
9
11
 
10
12
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
11
13
 
@@ -34,7 +36,7 @@ var ValidationError = /*#__PURE__*/function (_Error) {
34
36
  return _super.apply(this, arguments);
35
37
  }
36
38
 
37
- return ValidationError;
39
+ return (0, _createClass2.default)(ValidationError);
38
40
  }( /*#__PURE__*/(0, _wrapNativeSuper2.default)(Error));
39
41
 
40
42
  exports.ValidationError = ValidationError;
@@ -49,7 +51,7 @@ var NoTransformsExistError = /*#__PURE__*/function (_Error2) {
49
51
  return _super2.apply(this, arguments);
50
52
  }
51
53
 
52
- return NoTransformsExistError;
54
+ return (0, _createClass2.default)(NoTransformsExistError);
53
55
  }( /*#__PURE__*/(0, _wrapNativeSuper2.default)(Error));
54
56
 
55
57
  exports.NoTransformsExistError = NoTransformsExistError;
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "@atlaskit/codemod-cli",
3
- "version": "0.8.0"
3
+ "version": "0.8.4"
4
4
  }
@@ -16,7 +16,7 @@ Options
16
16
  --ignore-pattern, ignore files that match a provided glob expression
17
17
  --fail-on-error, return a 1 exit code when errors were found during execution of codemods
18
18
  --version, -v version number
19
- --filterPaths filters source paths to package directories that declare a dependency on the package being upgraded
19
+ --no-filter-paths disables dependant package file path filtering logic
20
20
  --help Help me 😱
21
21
 
22
22
  Examples
@@ -55,7 +55,8 @@ Examples
55
55
  type: 'boolean'
56
56
  },
57
57
  filterPaths: {
58
- type: 'boolean'
58
+ type: 'boolean',
59
+ default: true
59
60
  }
60
61
  }
61
62
  });
@@ -78,7 +78,9 @@ const runTransform = async (filePaths, transform, flags) => {
78
78
  codemodDirs = await findDependentPackagePaths(filePaths, transform.module);
79
79
 
80
80
  if (codemodDirs.length === 0) {
81
- logger.log(chalk.yellow(`Filtering for module ${transform.module} returned no directories, please validate specified paths.`));
81
+ // Fallback to non-filter logic if filtering returns no directories
82
+ logger.log(chalk.yellow(`Could not filter source paths for ${transform.module}, falling back to running over all specified paths. (See --no-filter-paths flag)`));
83
+ codemodDirs = filePaths;
82
84
  } else {
83
85
  logger.log(chalk.green(`Running transform '${chalk.bold(transform.name)}' over filtered dirs ${chalk.bold(codemodDirs.join(', '))}...`));
84
86
  }
@@ -5,5 +5,6 @@ import path from 'path';
5
5
  */
6
6
 
7
7
  import './styled-to-emotion/styled-to-emotion';
8
- const presets = ['styled-to-emotion'].map(preset => path.join(__dirname, preset, `${preset}.@(ts|js)`));
8
+ import './theme-to-design-tokens/theme-to-design-tokens';
9
+ const presets = ['styled-to-emotion', 'theme-to-design-tokens'].map(preset => path.join(__dirname, preset, `${preset}.@(ts|js|tsx)`));
9
10
  export default presets;
@@ -0,0 +1,137 @@
1
+ /* eslint-disable no-console */
2
+ import colorToToken from './utils/color-to-token';
3
+ import { isDecendantOfToken, isDecendantOfType } from './utils/ast';
4
+ import { cleanMeta, getMetaFromAncestors } from './utils/ast-meta';
5
+ import { includesHardCodedColor, isHardCodedColor, isLegacyColor, isLegacyNamedColor } from './utils/color';
6
+ import Search from './utils/fuzzy-search';
7
+ import { legacyColorMetaMap } from './utils/legacy-colors';
8
+ import designTokens from '@atlaskit/tokens/token-names';
9
+ const tokens = Object.keys(designTokens);
10
+ const search = Search(tokens, false);
11
+
12
+ function hasImportDeclaration(j, source, sourcePath) {
13
+ return !!source.find(j.ImportDeclaration).filter(path => path.node.source.value === sourcePath).length;
14
+ }
15
+
16
+ function hasImportSpecifier(j, source, specifier, sourcePath) {
17
+ return !!source.find(j.ImportDeclaration).filter(path => path.node.source.value === sourcePath).find(j.ImportSpecifier, {
18
+ local: {
19
+ name: specifier
20
+ }
21
+ }).length;
22
+ }
23
+
24
+ function insertTokenImport(j, source) {
25
+ if (hasImportDeclaration(j, source, '@atlaskit/tokens')) {
26
+ return;
27
+ }
28
+
29
+ const newImport = j.importDeclaration([j.importSpecifier(j.identifier('token'))], j.stringLiteral('@atlaskit/tokens'));
30
+ source.get().node.program.body.unshift(newImport);
31
+ }
32
+
33
+ function buildToken(j, tokenResult, node) {
34
+ const callExpr = j.callExpression(j.identifier('token'), [j.stringLiteral(tokenResult.suggestion[0] || 'util.UNSAFE_MISSING_TOKEN'), tokenResult.fallbackNeeded && node].filter(Boolean));
35
+ callExpr.comments = [j.commentBlock(` [token-confidence: ${tokenResult.confidence}] `)];
36
+ return callExpr;
37
+ }
38
+
39
+ function getTokenFromNode(j, path, debug, paletteColor, baseMeta = []) {
40
+ const foundMeta = getMetaFromAncestors(j, path);
41
+ const propertyName = foundMeta.find(name => {
42
+ if (!name) {
43
+ return false;
44
+ }
45
+
46
+ return name.toLowerCase().match(/(.*color|image|fill|stroke|shadow|border(?!-)|background(?!-)|outline(?!-)|column-rule-color)/);
47
+ });
48
+ let state = 'resting';
49
+ foundMeta.find(name => {
50
+ if (!name) {
51
+ return false;
52
+ }
53
+
54
+ const result = /(hover|active|disabled)/.exec(name.toLowerCase());
55
+
56
+ if (result) {
57
+ if (result[0] === 'active') {
58
+ state = 'pressed';
59
+ } else {
60
+ state = result[0];
61
+ }
62
+
63
+ return true;
64
+ }
65
+
66
+ return false;
67
+ });
68
+ const tokenResult = colorToToken(paletteColor || '', {
69
+ state,
70
+ propertyName
71
+ }, () => {
72
+ const searchTerm = cleanMeta([...foundMeta, ...baseMeta]).join(' ');
73
+ const results = search.get(searchTerm);
74
+
75
+ if (results) {
76
+ return results.map(result => result[1]);
77
+ }
78
+
79
+ return [];
80
+ });
81
+ return tokenResult;
82
+ }
83
+
84
+ export default function transformer(file, api, debug = false) {
85
+ const j = api.jscodeshift;
86
+ const source = j(file.source);
87
+ let transformed = false;
88
+ source // Handle colors.N100
89
+ .find(j.MemberExpression).filter(path => {
90
+ return path.value.object.type === 'Identifier' && path.value.object.name === 'colors' && path.value.property.type === 'Identifier' && isLegacyColor(path.value.property.name);
91
+ }).filter(path => !isDecendantOfToken(j, path)).forEach(path => {
92
+ debug && console.log('file:', file.path);
93
+ insertTokenImport(j, source);
94
+ const key = path.value.property.type === 'Identifier' ? path.value.property.name : undefined;
95
+ const colorMeta = legacyColorMetaMap[key] || [];
96
+ const tokenId = getTokenFromNode(j, path, debug, key, colorMeta);
97
+ j(path).replaceWith(buildToken(j, tokenId, path.value));
98
+ transformed = true;
99
+ });
100
+ source.find(j.ObjectProperty).filter(path => {
101
+ return path.value.value.type === 'Identifier' && (isLegacyColor(path.value.value.name) || isLegacyNamedColor(path.value.value.name));
102
+ }).filter(path => hasImportSpecifier(j, source, path.value.value.type === 'Identifier' ? path.value.value.name : '', '@atlaskit/theme') || hasImportSpecifier(j, source, path.value.value.type === 'Identifier' ? path.value.value.name : '', '@atlaskit/theme/colors')).filter(path => !isDecendantOfToken(j, path.value.value)).forEach(path => {
103
+ const valuePath = path.get('value');
104
+ debug && console.log('file:', file.path);
105
+ insertTokenImport(j, source);
106
+ const colorMeta = legacyColorMetaMap[valuePath.name] || [];
107
+ const tokenId = getTokenFromNode(j, valuePath, debug, valuePath.name, colorMeta);
108
+ j(path).replaceWith(j.objectProperty(path.value.key, buildToken(j, tokenId, valuePath.value)));
109
+ transformed = true;
110
+ });
111
+ source.find(j.Identifier).filter(path => isLegacyColor(path.value.name) || isLegacyNamedColor(path.value.name)).filter(path => hasImportSpecifier(j, source, path.value.name, '@atlaskit/theme') || hasImportSpecifier(j, source, path.value.name, '@atlaskit/theme/colors')).filter(path => !['ImportSpecifier', 'MemberExpression', 'ObjectProperty'].includes(path.parentPath.value.type)).filter(path => !isDecendantOfToken(j, path)).forEach(path => {
112
+ debug && console.log('file:', file.path);
113
+ insertTokenImport(j, source);
114
+ const colorMeta = legacyColorMetaMap[path.value.name] || [];
115
+ const tokenId = getTokenFromNode(j, path, debug, path.value.name, colorMeta);
116
+ j(path).replaceWith(buildToken(j, tokenId, path.value));
117
+ transformed = true;
118
+ });
119
+ source.find(j.Literal).filter(path => typeof path.value.value === 'string' && (includesHardCodedColor(path.value.value) || isHardCodedColor(path.value.value))).filter(path => !isDecendantOfToken(j, path)).forEach(path => {
120
+ var _path$value, _path$value$value;
121
+
122
+ debug && console.log('file:', file.path);
123
+ insertTokenImport(j, source);
124
+ const value = path === null || path === void 0 ? void 0 : (_path$value = path.value) === null || _path$value === void 0 ? void 0 : (_path$value$value = _path$value.value) === null || _path$value$value === void 0 ? void 0 : _path$value$value.toString();
125
+ const colorMeta = legacyColorMetaMap[value] || [];
126
+ const tokenId = getTokenFromNode(j, path, debug, value, colorMeta);
127
+ const tokenNode = buildToken(j, tokenId, path.value);
128
+ j(path).replaceWith(isDecendantOfType(j, path, j.JSXAttribute) ? j.jsxExpressionContainer(tokenNode) : tokenNode);
129
+ transformed = true;
130
+ });
131
+
132
+ if (transformed) {
133
+ return source.toSource();
134
+ }
135
+
136
+ return file.source;
137
+ }
@@ -0,0 +1,70 @@
1
+ import designTokens from '@atlaskit/tokens/token-names';
2
+ const tokens = Object.keys(designTokens);
3
+ export const getUniqueWordsFromTokens = tokens.reduce((accum, val) => [...accum, ...val.split('.')], []).reduce((accum, val) => [...accum, ...val.split(/(?=[A-Z])/g).map(e => e.toLowerCase())], []).reduce((accum, val) => {
4
+ if (!accum.includes(val)) {
5
+ accum.push(val);
6
+ }
7
+
8
+ return accum;
9
+ }, []);
10
+ export function getMetaFromAncestors(j, path, meta = []) {
11
+ const parent = path.parentPath;
12
+ const grandParent = parent && parent.parentPath;
13
+
14
+ if (parent && parent.value.type === 'ObjectProperty') {
15
+ let value = '';
16
+
17
+ if (parent.value.key.type === 'Literal' || parent.value.key.type === 'StringLiteral' || parent.value.key.type === 'NumericLiteral') {
18
+ value = parent.value.key.value.toString();
19
+ } else {
20
+ value = parent.value.key.name;
21
+ }
22
+
23
+ meta.push(value);
24
+ }
25
+
26
+ if (parent && grandParent && grandParent.value.type === 'TemplateLiteral') {
27
+ const expressionIndex = grandParent.value.expressions.findIndex(exp => exp.name === path.value.name);
28
+ const quasi = grandParent.value.quasis[expressionIndex];
29
+ const propertyName = (quasi.value.cooked || quasi.value.raw || '').replace(/\n/g, '').split(/;|{|}/).filter(el => !el.match(/\.|\@|\(|\)/)).pop().replace(/:/g, '').trim();
30
+ grandParent.value.quasis.slice(0, expressionIndex + 1).map(q => q.value.cooked) // We reverse so the most nested one is first which we're more likely than not interested in
31
+ .reverse().forEach(str => {
32
+ const result = /(hover|active|disabled|focus)/.exec(str.toLowerCase());
33
+
34
+ if (result) {
35
+ meta.push(result[0]);
36
+ }
37
+ });
38
+ meta.push(propertyName);
39
+ }
40
+
41
+ if (parent && parent.value.type === 'JSXAttribute') {
42
+ if (!['css', 'styles', 'style'].includes(parent.value.name.name)) {
43
+ meta.push(parent.value.name.name);
44
+ }
45
+ }
46
+
47
+ if (parent && parent.value.type === 'VariableDeclarator') {
48
+ meta.push(parent.value.id.name);
49
+ }
50
+
51
+ if (parent) {
52
+ return getMetaFromAncestors(j, parent, meta);
53
+ }
54
+
55
+ return meta;
56
+ }
57
+ export function cleanMeta(meta) {
58
+ return meta.reduce((accum, val) => [...accum, ...(typeof val === 'string' ? val.split(/(?=[A-Z])/g).map(e => e.toLowerCase()) : [])], []).reduce((accum, val) => {
59
+ accum.push(val.replace(/:/g, '').replace(/,/g, '').replace('grey', 'neutral').replace('texts', 'text').replace('error', 'danger').replace('invalid', 'danger').replace('removed', 'danger').replace('removal', 'danger').replace('remove', 'danger').replace('valid', 'success').replace('successful', 'success').replace('risk', 'warning').replace('primary', 'bold').replace('info', 'bold').replace('secondary', 'subtle').replace('hyperlink', 'link').replace('focused', 'focus').replace('active', 'pressed').replace('hovered', 'hover').replace('background-color', 'background').replace('color', 'text').replace('stroke', 'border').replace('border-left', 'border').replace('border-right', 'border').replace('box-shadow', 'shadow'));
60
+ return accum;
61
+ }, []).filter(val => {
62
+ return getUniqueWordsFromTokens.includes(val);
63
+ }).reduce((accum, val) => {
64
+ if (!accum.includes(val)) {
65
+ accum.push(val);
66
+ }
67
+
68
+ return accum;
69
+ }, []);
70
+ }
@@ -0,0 +1,10 @@
1
+ export function isDecendantOfToken(j, path) {
2
+ return j(path).closest(j.CallExpression, {
3
+ callee: {
4
+ name: 'token'
5
+ }
6
+ }).length > 0;
7
+ }
8
+ export function isDecendantOfType(j, path, type) {
9
+ return j(path).closest(type).length > 0;
10
+ }
@@ -0,0 +1,150 @@
1
+ /* eslint-disable @atlassian/tangerine/import/entry-points */
2
+ import { convert } from 'chromatism'; // Design token values are not currently exposed from @atlaskit/tokens
3
+ // In a follow up ticket we will expose them again via another entrypoint.
4
+
5
+ import defaultTokenValues from '@atlaskit/tokens/token-names';
6
+ export const legacyColorPalette = {
7
+ R50: '#FFEBE6',
8
+ R75: '#FFBDAD',
9
+ R100: '#FF8F73',
10
+ R200: '#FF7452',
11
+ R300: '#FF5630',
12
+ R400: '#DE350B',
13
+ R500: '#BF2600',
14
+ Y50: '#FFFAE6',
15
+ Y75: '#FFF0B3',
16
+ Y100: '#FFE380',
17
+ Y200: '#FFC400',
18
+ Y300: '#FFAB00',
19
+ Y400: '#FF991F',
20
+ Y500: '#FF8B00',
21
+ G50: '#E3FCEF',
22
+ G75: '#ABF5D1',
23
+ G100: '#79F2C0',
24
+ G200: '#57D9A3',
25
+ G300: '#36B37E',
26
+ G400: '#00875A',
27
+ G500: '#006644',
28
+ B50: '#DEEBFF',
29
+ B75: '#B3D4FF',
30
+ B100: '#4C9AFF',
31
+ B200: '#2684FF',
32
+ B300: '#0065FF',
33
+ B400: '#0052CC',
34
+ B500: '#0747A6',
35
+ P50: '#EAE6FF',
36
+ P75: '#C0B6F2',
37
+ P100: '#998DD9',
38
+ P200: '#8777D9',
39
+ P300: '#6554C0',
40
+ P400: '#5243AA',
41
+ P500: '#403294',
42
+ T50: '#E6FCFF',
43
+ T75: '#B3F5FF',
44
+ T100: '#79E2F2',
45
+ T200: '#00C7E6',
46
+ T300: '#00B8D9',
47
+ T400: '#00A3BF',
48
+ T500: '#008DA6',
49
+ N0: '#FFFFFF',
50
+ N10: '#FAFBFC',
51
+ N20: '#F4F5F7',
52
+ N30: '#EBECF0',
53
+ N40: '#DFE1E6',
54
+ N50: '#C1C7D0',
55
+ N60: '#B3BAC5',
56
+ N70: '#A5ADBA',
57
+ N80: '#97A0AF',
58
+ N90: '#8993A4',
59
+ N100: '#7A869A',
60
+ N200: '#6B778C',
61
+ N300: '#5E6C84',
62
+ N400: '#505F79',
63
+ N500: '#42526E',
64
+ N600: '#344563',
65
+ N700: '#253858',
66
+ N800: '#172B4D',
67
+ N900: '#091E42'
68
+ };
69
+ export function findClosetMatchingToken(paletteName) {
70
+ const paletteColor = legacyColorPalette[paletteName];
71
+
72
+ if (!paletteColor) {
73
+ return undefined;
74
+ }
75
+
76
+ const tokens = Object.entries(defaultTokenValues).map(([key, value]) => {
77
+ try {
78
+ const diff = deltaE(paletteColor, value);
79
+ return [key, diff];
80
+ } catch (e) {
81
+ return [key, 99999];
82
+ }
83
+ }).sort((a, b) => {
84
+ const left = a[1];
85
+ const right = b[1];
86
+ return left - right;
87
+ });
88
+ const [token, diff] = tokens[0];
89
+
90
+ if (diff < 10) {
91
+ return token;
92
+ }
93
+
94
+ return undefined;
95
+ }
96
+
97
+ function toRgbArray(color) {
98
+ const colr = convert(color);
99
+ return [colr.rgb.r, colr.rgb.g, colr.rgb.b];
100
+ }
101
+ /**
102
+ * Color difference function ripped from https://stackoverflow.com/a/52453462
103
+ *
104
+ * **Color difference**
105
+ * - <= 1.0 not perceptible by human eyes
106
+ * - 1-2 Perceptible through close observation
107
+ * - 2-10 Perceptible at a glance
108
+ * - 11-49 Colors are more similar than opposite
109
+ * - 100 Colors are opposite
110
+ */
111
+
112
+
113
+ function deltaE(rgbA, rgbB) {
114
+ let labA = rgb2lab(toRgbArray(rgbA));
115
+ let labB = rgb2lab(toRgbArray(rgbB));
116
+ let deltaL = labA[0] - labB[0];
117
+ let deltaA = labA[1] - labB[1];
118
+ let deltaB = labA[2] - labB[2];
119
+ let c1 = Math.sqrt(labA[1] * labA[1] + labA[2] * labA[2]);
120
+ let c2 = Math.sqrt(labB[1] * labB[1] + labB[2] * labB[2]);
121
+ let deltaC = c1 - c2;
122
+ let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
123
+ deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
124
+ let sc = 1.0 + 0.045 * c1;
125
+ let sh = 1.0 + 0.015 * c1;
126
+ let deltaLKlsl = deltaL / 1.0;
127
+ let deltaCkcsc = deltaC / sc;
128
+ let deltaHkhsh = deltaH / sh;
129
+ let i = deltaLKlsl * deltaLKlsl + deltaCkcsc * deltaCkcsc + deltaHkhsh * deltaHkhsh;
130
+ return i < 0 ? 0 : Math.sqrt(i);
131
+ }
132
+
133
+ function rgb2lab(rgb) {
134
+ let r = rgb[0] / 255,
135
+ g = rgb[1] / 255,
136
+ b = rgb[2] / 255,
137
+ x,
138
+ y,
139
+ z;
140
+ r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
141
+ g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
142
+ b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
143
+ x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
144
+ y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.0;
145
+ z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
146
+ x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;
147
+ y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
148
+ z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;
149
+ return [116 * y - 16, 500 * (x - y), 200 * (y - z)];
150
+ }
@@ -0,0 +1,122 @@
1
+ const colorMap = {
2
+ resting: {
3
+ text: {
4
+ B300: ['color.text.selected', 'color.text.link.resting', 'color.iconBorder.brand'],
5
+ B400: ['color.text.selected', 'color.text.link.resting', 'color.iconBorder.brand'],
6
+ R300: ['color.text.danger', 'color.iconBorder.danger'],
7
+ R400: ['color.text.danger', 'color.iconBorder.danger'],
8
+ Y300: ['color.text.warning', 'color.iconBorder.warning'],
9
+ Y400: ['color.text.warning', 'color.iconBorder.warning'],
10
+ P300: ['color.text.discovery', 'color.iconBorder.discovery'],
11
+ P400: ['color.text.discovery', 'color.iconBorder.discovery'],
12
+ G300: ['color.text.success', 'color.iconBorder.success'],
13
+ G400: ['color.text.success', 'color.iconBorder.success'],
14
+ N0: ['color.text.onBold'],
15
+ N70: ['color.text.lowEmphasis'],
16
+ N80: ['color.text.lowEmphasis'],
17
+ N90: ['color.text.lowEmphasis'],
18
+ N100: ['color.text.lowEmphasis'],
19
+ N200: ['color.text.lowEmphasis'],
20
+ N300: ['color.text.lowEmphasis'],
21
+ N400: ['color.text.mediumEmphasis'],
22
+ N500: ['color.text.mediumEmphasis'],
23
+ N600: ['color.text.mediumEmphasis'],
24
+ N700: ['color.text.highEmphasis'],
25
+ N800: ['color.text.highEmphasis'],
26
+ N900: ['color.text.highEmphasis']
27
+ },
28
+ background: {
29
+ B75: ['color.background.selected.resting'],
30
+ N40: ['color.background.subtleNeutral.resting', 'color.background.sunken'],
31
+ B50: ['color.background.subtleBrand.resting', 'color.background.selected.resting'],
32
+ Y75: ['color.background.subtleWarning.resting'],
33
+ P50: ['color.background.subtleDiscovery.resting'],
34
+ R50: ['color.background.subtleDanger.resting'],
35
+ G50: ['color.background.subtleSuccess.resting'],
36
+ P300: ['color.background.boldDiscovery.resting'],
37
+ P400: ['color.background.boldDiscovery.resting'],
38
+ G300: ['color.background.boldSuccess.resting'],
39
+ Y300: ['color.background.boldWarning.resting'],
40
+ Y500: ['color.background.boldWarning.resting'],
41
+ R400: ['color.background.boldDanger.resting'],
42
+ B400: ['color.background.boldBrand.resting'],
43
+ N0: ['color.background.default', 'color.background.overlay', 'color.background.card']
44
+ },
45
+ border: {
46
+ N10: ['color.border.neutral'],
47
+ N20: ['color.border.neutral'],
48
+ N30: ['color.border.neutral'],
49
+ N40: ['color.border.neutral'],
50
+ N50: ['color.border.neutral'],
51
+ N60: ['color.border.neutral'],
52
+ N70: ['color.border.neutral'],
53
+ B100: ['color.border.focus'],
54
+ B300: ['color.iconBorder.brand', 'color.text.selected'],
55
+ B400: ['color.iconBorder.brand', 'color.text.selected'],
56
+ R300: ['color.iconBorder.danger'],
57
+ R400: ['color.iconBorder.danger'],
58
+ Y300: ['color.iconBorder.warning'],
59
+ Y400: ['color.iconBorder.warning'],
60
+ P300: ['color.iconBorder.discovery'],
61
+ P400: ['color.iconBorder.discovery'],
62
+ G300: ['color.iconBorder.success'],
63
+ G400: ['color.iconBorder.success']
64
+ }
65
+ },
66
+ hover: {
67
+ text: {
68
+ B300: ['color.text.link.resting'],
69
+ B400: ['color.text.link.resting']
70
+ },
71
+ background: {
72
+ B50: ['color.background.selected.hover'],
73
+ B75: ['color.background.selected.hover'],
74
+ P200: ['color.background.boldDiscovery.hover'],
75
+ P300: ['color.background.boldDiscovery.hover'],
76
+ G200: ['color.background.boldSuccess.hover'],
77
+ R300: ['color.background.boldDanger.hover'],
78
+ Y200: ['color.background.boldWarning.hover'],
79
+ B300: ['color.background.boldBrand.hover']
80
+ },
81
+ border: {}
82
+ },
83
+ pressed: {
84
+ text: {
85
+ B300: ['color.text.link.pressed'],
86
+ B400: ['color.text.link.pressed']
87
+ },
88
+ background: {
89
+ B50: ['color.background.selected.pressed'],
90
+ B75: ['color.background.selected.pressed'],
91
+ P400: ['color.background.boldDiscovery.pressed'],
92
+ P500: ['color.background.boldDiscovery.pressed'],
93
+ G400: ['color.background.boldSuccess.pressed'],
94
+ R500: ['color.background.boldDanger.pressed'],
95
+ Y400: ['color.background.boldWarning.pressed'],
96
+ B500: ['color.background.boldBrand.pressed']
97
+ },
98
+ border: {}
99
+ },
100
+ disabled: {
101
+ text: {
102
+ N60: ['color.text.disabled'],
103
+ N70: ['color.text.disabled'],
104
+ N80: ['color.text.disabled'],
105
+ N90: ['color.text.disabled'],
106
+ N100: ['color.text.disabled']
107
+ },
108
+ background: {
109
+ N10: ['color.background.disabled'],
110
+ N20: ['color.background.disabled'],
111
+ N30: ['color.background.disabled'],
112
+ N40: ['color.background.disabled']
113
+ },
114
+ border: {
115
+ N10: ['color.background.disabled'],
116
+ N20: ['color.background.disabled'],
117
+ N30: ['color.background.disabled'],
118
+ N40: ['color.background.disabled']
119
+ }
120
+ }
121
+ };
122
+ export default colorMap;
@@ -0,0 +1,75 @@
1
+ import { findClosetMatchingToken } from './color-difference';
2
+ import colorTokensMap from './color-palette-tokens-map';
3
+
4
+ function normalizeName(name) {
5
+ if (!name) {
6
+ return 'unknown';
7
+ }
8
+
9
+ if (name.startsWith('background')) {
10
+ return 'background';
11
+ }
12
+
13
+ if (name.toLowerCase().includes('color') || name === 'color' || name === 'fill' || name === 'stroke') {
14
+ return 'text';
15
+ }
16
+
17
+ if (name.startsWith('border') || name.toLowerCase().replace('-', '') === 'boxshadow') {
18
+ return 'border';
19
+ }
20
+
21
+ return 'unknown';
22
+ }
23
+
24
+ export default function colorToToken(paletteName, {
25
+ state = 'resting',
26
+ propertyName
27
+ }, getLowConfidenceFuzzyResult = () => []) {
28
+ const normalizedPropertyName = normalizeName(propertyName);
29
+ const value = paletteName.toUpperCase();
30
+ const tokenSuggestionProperties = colorTokensMap[state];
31
+ const tokenSuggestionProperty = tokenSuggestionProperties && normalizedPropertyName !== 'unknown' && tokenSuggestionProperties[normalizedPropertyName];
32
+ const tokenSuggestionValue = tokenSuggestionProperty && tokenSuggestionProperty[value];
33
+
34
+ if (tokenSuggestionValue && tokenSuggestionValue.length === 1) {
35
+ return {
36
+ confidence: 'high',
37
+ suggestion: tokenSuggestionValue,
38
+ fallbackNeeded: true
39
+ };
40
+ }
41
+
42
+ if (tokenSuggestionValue && tokenSuggestionValue.length > 2) {
43
+ return {
44
+ confidence: 'medium',
45
+ suggestion: tokenSuggestionValue,
46
+ fallbackNeeded: true
47
+ };
48
+ }
49
+
50
+ const closestTokenName = findClosetMatchingToken(value);
51
+
52
+ if (closestTokenName) {
53
+ return {
54
+ confidence: 'low',
55
+ suggestion: [closestTokenName],
56
+ fallbackNeeded: true
57
+ };
58
+ }
59
+
60
+ const fuzzyResult = getLowConfidenceFuzzyResult();
61
+
62
+ if (fuzzyResult.length) {
63
+ return {
64
+ confidence: 'low',
65
+ suggestion: fuzzyResult,
66
+ fallbackNeeded: true
67
+ };
68
+ }
69
+
70
+ return {
71
+ confidence: 'unknown',
72
+ suggestion: [],
73
+ fallbackNeeded: true
74
+ };
75
+ }