@atlaskit/tokens 1.49.0 → 1.50.0

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 (125) hide show
  1. package/CHANGELOG.md +1589 -1591
  2. package/README.md +14 -8
  3. package/codemods/css-to-design-tokens/lib/colors.tsx +47 -49
  4. package/codemods/css-to-design-tokens/lib/declaration.tsx +26 -26
  5. package/codemods/css-to-design-tokens/lib/legacy-colors.tsx +326 -326
  6. package/codemods/css-to-design-tokens/lib/meta.tsx +116 -122
  7. package/codemods/css-to-design-tokens/lib/tokens.tsx +28 -35
  8. package/codemods/css-to-design-tokens/lib/value.tsx +70 -72
  9. package/codemods/css-to-design-tokens/transform.tsx +68 -72
  10. package/codemods/hypermod.config.tsx +5 -5
  11. package/codemods/remove-fallbacks-color/transform.tsx +16 -18
  12. package/codemods/theme-to-design-tokens/transform.tsx +505 -588
  13. package/codemods/theme-to-design-tokens/utils/ast-meta.tsx +139 -147
  14. package/codemods/theme-to-design-tokens/utils/ast.tsx +23 -34
  15. package/codemods/theme-to-design-tokens/utils/color.tsx +25 -26
  16. package/codemods/theme-to-design-tokens/utils/css-utils.tsx +27 -30
  17. package/codemods/theme-to-design-tokens/utils/fuzzy-search.tsx +272 -290
  18. package/codemods/theme-to-design-tokens/utils/legacy-colors.tsx +224 -224
  19. package/codemods/theme-to-design-tokens/utils/named-colors.tsx +148 -148
  20. package/codemods/theme-to-design-tokens/utils/string-utils.tsx +10 -16
  21. package/codemods/utils/tokens.tsx +371 -371
  22. package/dist/cjs/artifacts/atlassian-dark-token-value-for-contrast-check.js +1 -1
  23. package/dist/cjs/artifacts/atlassian-light-token-value-for-contrast-check.js +1 -1
  24. package/dist/cjs/artifacts/generated-pairs.js +1 -1
  25. package/dist/cjs/artifacts/palettes-raw/typography-palette.js +45 -30
  26. package/dist/cjs/artifacts/theme-import-map.js +1 -1
  27. package/dist/cjs/artifacts/themes/atlassian-typography-minor3.js +2 -2
  28. package/dist/cjs/artifacts/token-default-values.js +1 -1
  29. package/dist/cjs/artifacts/token-names.js +1 -1
  30. package/dist/cjs/artifacts/tokens-raw/atlassian-typography-adg3.js +20 -20
  31. package/dist/cjs/artifacts/tokens-raw/atlassian-typography-minor3.js +13 -13
  32. package/dist/es2019/artifacts/atlassian-dark-token-value-for-contrast-check.js +1 -1
  33. package/dist/es2019/artifacts/atlassian-light-token-value-for-contrast-check.js +1 -1
  34. package/dist/es2019/artifacts/generated-pairs.js +1 -1
  35. package/dist/es2019/artifacts/palettes-raw/typography-palette.js +45 -30
  36. package/dist/es2019/artifacts/theme-import-map.js +1 -1
  37. package/dist/es2019/artifacts/themes/atlassian-typography-minor3.js +2 -2
  38. package/dist/es2019/artifacts/token-default-values.js +1 -1
  39. package/dist/es2019/artifacts/token-names.js +1 -1
  40. package/dist/es2019/artifacts/tokens-raw/atlassian-typography-adg3.js +20 -20
  41. package/dist/es2019/artifacts/tokens-raw/atlassian-typography-minor3.js +13 -13
  42. package/dist/esm/artifacts/atlassian-dark-token-value-for-contrast-check.js +1 -1
  43. package/dist/esm/artifacts/atlassian-light-token-value-for-contrast-check.js +1 -1
  44. package/dist/esm/artifacts/generated-pairs.js +1 -1
  45. package/dist/esm/artifacts/palettes-raw/typography-palette.js +45 -30
  46. package/dist/esm/artifacts/theme-import-map.js +1 -1
  47. package/dist/esm/artifacts/themes/atlassian-typography-minor3.js +2 -2
  48. package/dist/esm/artifacts/token-default-values.js +1 -1
  49. package/dist/esm/artifacts/token-names.js +1 -1
  50. package/dist/esm/artifacts/tokens-raw/atlassian-typography-adg3.js +20 -20
  51. package/dist/esm/artifacts/tokens-raw/atlassian-typography-minor3.js +13 -13
  52. package/dist/types/artifacts/atlassian-dark-token-value-for-contrast-check.d.ts +1 -1
  53. package/dist/types/artifacts/atlassian-light-token-value-for-contrast-check.d.ts +1 -1
  54. package/dist/types/artifacts/generated-pairs.d.ts +1 -1
  55. package/dist/types/artifacts/palettes-raw/typography-palette.d.ts +1 -1
  56. package/dist/types/artifacts/theme-import-map.d.ts +2 -2
  57. package/dist/types/artifacts/themes/atlassian-typography-minor3.d.ts +2 -2
  58. package/dist/types/artifacts/token-default-values.d.ts +1 -1
  59. package/dist/types/artifacts/token-names.d.ts +1 -1
  60. package/dist/types/artifacts/tokens-raw/atlassian-typography-adg3.d.ts +1 -1
  61. package/dist/types/artifacts/tokens-raw/atlassian-typography-minor3.d.ts +1 -1
  62. package/dist/types/artifacts/types-internal.d.ts +1 -1
  63. package/dist/types/artifacts/types.d.ts +1 -1
  64. package/dist/types/babel-plugin/plugin.d.ts +1 -1
  65. package/dist/types/custom-theme.d.ts +2 -2
  66. package/dist/types/enable-global-theme.d.ts +2 -2
  67. package/dist/types/entry-points/css-type-schema.codegen.d.ts +1 -1
  68. package/dist/types/entry-points/token-ids.d.ts +1 -1
  69. package/dist/types/get-global-theme.d.ts +1 -1
  70. package/dist/types/get-ssr-auto-script.d.ts +1 -1
  71. package/dist/types/get-theme-html-attrs.d.ts +1 -1
  72. package/dist/types/get-theme-styles.d.ts +1 -1
  73. package/dist/types/get-token.d.ts +1 -1
  74. package/dist/types/index.d.ts +1 -1
  75. package/dist/types/load-custom-theme-styles.d.ts +1 -1
  76. package/dist/types/set-global-theme.d.ts +2 -2
  77. package/dist/types/theme-state-transformer.d.ts +1 -1
  78. package/dist/types/utils/color-detection.d.ts +1 -1
  79. package/dist/types/utils/color-mode-listeners.d.ts +1 -1
  80. package/dist/types/utils/configure-page.d.ts +1 -1
  81. package/dist/types/utils/contrast-mode-listeners.d.ts +1 -1
  82. package/dist/types/utils/custom-theme-loading-utils.d.ts +1 -1
  83. package/dist/types/utils/custom-theme-token-contrast-check.d.ts +1 -1
  84. package/dist/types/utils/generate-custom-color-ramp.d.ts +2 -2
  85. package/dist/types/utils/get-increased-contrast-theme.d.ts +1 -1
  86. package/dist/types/utils/get-theme-preferences.d.ts +1 -1
  87. package/dist/types/utils/theme-loading.d.ts +1 -1
  88. package/dist/types-ts4.5/artifacts/atlassian-dark-token-value-for-contrast-check.d.ts +1 -1
  89. package/dist/types-ts4.5/artifacts/atlassian-light-token-value-for-contrast-check.d.ts +1 -1
  90. package/dist/types-ts4.5/artifacts/generated-pairs.d.ts +1 -1
  91. package/dist/types-ts4.5/artifacts/palettes-raw/typography-palette.d.ts +1 -1
  92. package/dist/types-ts4.5/artifacts/theme-import-map.d.ts +2 -2
  93. package/dist/types-ts4.5/artifacts/themes/atlassian-typography-minor3.d.ts +2 -2
  94. package/dist/types-ts4.5/artifacts/token-default-values.d.ts +1 -1
  95. package/dist/types-ts4.5/artifacts/token-names.d.ts +1 -1
  96. package/dist/types-ts4.5/artifacts/tokens-raw/atlassian-typography-adg3.d.ts +1 -1
  97. package/dist/types-ts4.5/artifacts/tokens-raw/atlassian-typography-minor3.d.ts +1 -1
  98. package/dist/types-ts4.5/artifacts/types-internal.d.ts +1 -1
  99. package/dist/types-ts4.5/artifacts/types.d.ts +1 -1
  100. package/dist/types-ts4.5/babel-plugin/plugin.d.ts +1 -1
  101. package/dist/types-ts4.5/custom-theme.d.ts +2 -2
  102. package/dist/types-ts4.5/enable-global-theme.d.ts +2 -2
  103. package/dist/types-ts4.5/entry-points/css-type-schema.codegen.d.ts +1 -1
  104. package/dist/types-ts4.5/entry-points/token-ids.d.ts +1 -1
  105. package/dist/types-ts4.5/get-global-theme.d.ts +1 -1
  106. package/dist/types-ts4.5/get-ssr-auto-script.d.ts +1 -1
  107. package/dist/types-ts4.5/get-theme-html-attrs.d.ts +1 -1
  108. package/dist/types-ts4.5/get-theme-styles.d.ts +1 -1
  109. package/dist/types-ts4.5/get-token.d.ts +1 -1
  110. package/dist/types-ts4.5/index.d.ts +1 -1
  111. package/dist/types-ts4.5/load-custom-theme-styles.d.ts +1 -1
  112. package/dist/types-ts4.5/set-global-theme.d.ts +2 -2
  113. package/dist/types-ts4.5/theme-state-transformer.d.ts +1 -1
  114. package/dist/types-ts4.5/utils/color-detection.d.ts +1 -1
  115. package/dist/types-ts4.5/utils/color-mode-listeners.d.ts +1 -1
  116. package/dist/types-ts4.5/utils/configure-page.d.ts +1 -1
  117. package/dist/types-ts4.5/utils/contrast-mode-listeners.d.ts +1 -1
  118. package/dist/types-ts4.5/utils/custom-theme-loading-utils.d.ts +1 -1
  119. package/dist/types-ts4.5/utils/custom-theme-token-contrast-check.d.ts +1 -1
  120. package/dist/types-ts4.5/utils/generate-custom-color-ramp.d.ts +2 -2
  121. package/dist/types-ts4.5/utils/get-increased-contrast-theme.d.ts +1 -1
  122. package/dist/types-ts4.5/utils/get-theme-preferences.d.ts +1 -1
  123. package/dist/types-ts4.5/utils/theme-loading.d.ts +1 -1
  124. package/package.json +3 -5
  125. package/report.api.md +2071 -2090
@@ -1,12 +1,6 @@
1
1
  /* eslint-disable no-console */
2
2
  import { hasImportDeclaration, isDecendantOfType } from '@hypermod/utils';
3
- import type {
4
- API,
5
- Collection,
6
- FileInfo,
7
- JSCodeshift,
8
- TemplateElement,
9
- } from 'jscodeshift';
3
+ import type { API, Collection, FileInfo, JSCodeshift, TemplateElement } from 'jscodeshift';
10
4
 
11
5
  import CSSTransformer from '../css-to-design-tokens/transform';
12
6
  import { activeTokens } from '../utils/tokens';
@@ -14,615 +8,538 @@ import { activeTokens } from '../utils/tokens';
14
8
  import { isDecendantOfToken, isParentOfToken } from './utils/ast';
15
9
  import { cleanMeta, getMetaFromAncestors } from './utils/ast-meta';
16
10
  import {
17
- includesHardCodedColor,
18
- isBoldColor,
19
- isHardCodedColor,
20
- isLegacyColor,
21
- isLegacyNamedColor,
11
+ includesHardCodedColor,
12
+ isBoldColor,
13
+ isHardCodedColor,
14
+ isLegacyColor,
15
+ isLegacyNamedColor,
22
16
  } from './utils/color';
23
- import {
24
- containsReplaceableCSSDeclarations,
25
- findEndIndexOfCSSExpression,
26
- } from './utils/css-utils';
17
+ import { containsReplaceableCSSDeclarations, findEndIndexOfCSSExpression } from './utils/css-utils';
27
18
  import Search from './utils/fuzzy-search';
28
19
  import { legacyColorMetaMap } from './utils/legacy-colors';
29
- import {
30
- findFirstNonspaceIndexAfter,
31
- kebabize,
32
- splitAtIndex,
33
- } from './utils/string-utils';
20
+ import { findFirstNonspaceIndexAfter, kebabize, splitAtIndex } from './utils/string-utils';
34
21
 
35
22
  function insertTokenImport(j: JSCodeshift, source: Collection<any>) {
36
- if (hasImportDeclaration(j, source, '@atlaskit/tokens')) {
37
- return;
38
- }
23
+ if (hasImportDeclaration(j, source, '@atlaskit/tokens')) {
24
+ return;
25
+ }
39
26
 
40
- const newImport = j.importDeclaration(
41
- [j.importSpecifier(j.identifier('token'))],
42
- j.stringLiteral('@atlaskit/tokens'),
43
- );
27
+ const newImport = j.importDeclaration(
28
+ [j.importSpecifier(j.identifier('token'))],
29
+ j.stringLiteral('@atlaskit/tokens'),
30
+ );
44
31
 
45
- source.get().node.program.body.unshift(newImport);
32
+ source.get().node.program.body.unshift(newImport);
46
33
  }
47
34
 
48
35
  function buildToken(j: JSCodeshift, tokenId: string, node: any) {
49
- const callExpr = j.callExpression(
50
- j.identifier('token'),
51
- [j.stringLiteral(tokenId), node].filter(Boolean),
52
- );
36
+ const callExpr = j.callExpression(
37
+ j.identifier('token'),
38
+ [j.stringLiteral(tokenId), node].filter(Boolean),
39
+ );
53
40
 
54
- return callExpr;
41
+ return callExpr;
55
42
  }
56
43
 
57
44
  // Wrap over the j.templateElement builder to provide a more convenient API.
58
45
  function buildTemplateElement(
59
- j: JSCodeshift,
60
- text: string,
61
- options: { tail?: boolean; fromNode?: TemplateElement | null } = {
62
- tail: false,
63
- fromNode: null,
64
- },
46
+ j: JSCodeshift,
47
+ text: string,
48
+ options: { tail?: boolean; fromNode?: TemplateElement | null } = {
49
+ tail: false,
50
+ fromNode: null,
51
+ },
65
52
  ) {
66
- let tail;
67
- if (options.fromNode) {
68
- tail = options.fromNode.tail;
69
- } else {
70
- tail = !!options.tail;
71
- }
72
-
73
- return j.templateElement({ raw: text, cooked: null }, tail);
53
+ let tail;
54
+ if (options.fromNode) {
55
+ tail = options.fromNode.tail;
56
+ } else {
57
+ tail = !!options.tail;
58
+ }
59
+
60
+ return j.templateElement({ raw: text, cooked: null }, tail);
74
61
  }
75
62
 
76
63
  function getColorFromIdentifier(expression: any) {
77
- let value = '';
64
+ let value = '';
78
65
 
79
- if (expression.type === 'Identifier') {
80
- value = expression.name;
81
- }
66
+ if (expression.type === 'Identifier') {
67
+ value = expression.name;
68
+ }
82
69
 
83
- if (expression.type === 'StringLiteral') {
84
- value = expression.value;
85
- }
70
+ if (expression.type === 'StringLiteral') {
71
+ value = expression.value;
72
+ }
86
73
 
87
- if (
88
- expression.type === 'MemberExpression' &&
89
- expression.object.name === 'colors' &&
90
- isLegacyColor(expression.property.name)
91
- ) {
92
- value = expression.property.name;
93
- }
74
+ if (
75
+ expression.type === 'MemberExpression' &&
76
+ expression.object.name === 'colors' &&
77
+ isLegacyColor(expression.property.name)
78
+ ) {
79
+ value = expression.property.name;
80
+ }
94
81
 
95
- return value;
82
+ return value;
96
83
  }
97
84
 
98
- function getTokenFromNode(
99
- j: JSCodeshift,
100
- path: any,
101
- value: string,
102
- propertyName: string,
103
- ): string {
104
- const valueMeta = cleanMeta(legacyColorMetaMap[value!] || []);
105
- const ancestorMeta = cleanMeta(
106
- [...getMetaFromAncestors(j, path), ...kebabize(propertyName).split('-')] ||
107
- [],
108
- );
109
-
110
- let property = cleanMeta([kebabize(propertyName)])[0];
111
-
112
- // Attempt to find a property from ancestors if one is not found
113
- if (
114
- !property ||
115
- !['border', 'icon', 'background', 'text'].includes(property)
116
- ) {
117
- if (ancestorMeta.includes('border')) {
118
- property = 'border';
119
- }
120
-
121
- if (ancestorMeta.includes('icon')) {
122
- property = 'icon';
123
- }
124
-
125
- if (ancestorMeta.includes('background')) {
126
- property = 'background';
127
- }
128
-
129
- if (ancestorMeta.includes('color')) {
130
- property = 'text';
131
- }
132
- }
133
-
134
- let meta: string[] = [];
135
- let possibleTokens = activeTokens;
136
-
137
- if (property === 'text') {
138
- possibleTokens = activeTokens.filter((token) => token.includes('.text'));
139
-
140
- if (valueMeta.includes('neutral')) {
141
- meta.push('color', 'text');
142
- }
143
-
144
- if (
145
- valueMeta.includes('neutral') &&
146
- (value === 'N400' || value === 'N500')
147
- ) {
148
- meta.push('color', 'text', 'subtle');
149
- }
150
-
151
- if (
152
- valueMeta.includes('neutral') &&
153
- (value === 'N80' ||
154
- value === 'N100' ||
155
- value === 'N200' ||
156
- value === 'N300' ||
157
- value === 'N400')
158
- ) {
159
- meta.push('color', 'text', 'subtlest');
160
- }
161
-
162
- // handle non-neutrals
163
- if (!valueMeta.includes('neutral')) {
164
- meta.push('color', ...ancestorMeta, ...valueMeta);
165
- }
166
- }
167
-
168
- if (property === 'background' || property === 'background-color') {
169
- if (ancestorMeta.includes('disabled')) {
170
- // disabled backgrounds
171
- meta.push(property, ...ancestorMeta);
172
- } else if (
173
- // Surfaces
174
- valueMeta.includes('neutral') &&
175
- value !== 'N100' &&
176
- value !== 'N200' &&
177
- value !== 'N300' &&
178
- value !== 'N400' &&
179
- value !== 'N500' &&
180
- value !== 'N600' &&
181
- value !== 'N700' &&
182
- value !== 'N800'
183
- ) {
184
- meta.push('surface', ...ancestorMeta);
185
- } else if (value.includes('N0')) {
186
- // default surface
187
- meta.push('elevation', 'surface');
188
- } else if (valueMeta.includes('neutral') && isBoldColor(value)) {
189
- // bold netural backgrounds
190
- meta.push('background', 'neutral', 'bold');
191
- } else if (valueMeta.includes('neutral')) {
192
- // netural backgrounds
193
- meta.push('background', 'neutral');
194
- }
195
- }
196
-
197
- if (
198
- property === 'border' ||
199
- property === 'border-color' ||
200
- property === 'border-left' ||
201
- property === 'border-right' ||
202
- property === 'border-top' ||
203
- property === 'border-bottom' ||
204
- property === 'outline' ||
205
- property === 'outline-color'
206
- ) {
207
- possibleTokens = activeTokens.filter(
208
- (token) => token.includes('.border') || token.includes('.focus'),
209
- );
210
-
211
- if (valueMeta.includes('neutral')) {
212
- // standard netural boarder
213
- meta.push('color', 'border', ...ancestorMeta);
214
- } else {
215
- meta.push('border', ...valueMeta, ...ancestorMeta);
216
- }
217
- }
218
-
219
- if (ancestorMeta.includes('icon')) {
220
- possibleTokens = activeTokens.filter((token) => token.includes('.icon'));
221
-
222
- if (ancestorMeta.includes('disabled')) {
223
- // disabled backgrounds
224
- meta.push('disabled');
225
- }
226
-
227
- meta.push('color', 'icon', ...valueMeta);
228
- }
229
-
230
- // Fallback if guided behavior yields nothing
231
- if (meta.length === 0) {
232
- meta.push(property, ...valueMeta, ...ancestorMeta);
233
- }
234
-
235
- const search = Search(possibleTokens, false);
236
- const results: [number, string][] = search.get(meta.join(' '));
237
-
238
- let tokenId = ['MISSING_TOKEN'];
239
-
240
- if (results) {
241
- tokenId = results.map((result) => result[1]) as any;
242
- }
243
-
244
- return tokenId[0];
85
+ function getTokenFromNode(j: JSCodeshift, path: any, value: string, propertyName: string): string {
86
+ const valueMeta = cleanMeta(legacyColorMetaMap[value!] || []);
87
+ const ancestorMeta = cleanMeta(
88
+ [...getMetaFromAncestors(j, path), ...kebabize(propertyName).split('-')] || [],
89
+ );
90
+
91
+ let property = cleanMeta([kebabize(propertyName)])[0];
92
+
93
+ // Attempt to find a property from ancestors if one is not found
94
+ if (!property || !['border', 'icon', 'background', 'text'].includes(property)) {
95
+ if (ancestorMeta.includes('border')) {
96
+ property = 'border';
97
+ }
98
+
99
+ if (ancestorMeta.includes('icon')) {
100
+ property = 'icon';
101
+ }
102
+
103
+ if (ancestorMeta.includes('background')) {
104
+ property = 'background';
105
+ }
106
+
107
+ if (ancestorMeta.includes('color')) {
108
+ property = 'text';
109
+ }
110
+ }
111
+
112
+ let meta: string[] = [];
113
+ let possibleTokens = activeTokens;
114
+
115
+ if (property === 'text') {
116
+ possibleTokens = activeTokens.filter((token) => token.includes('.text'));
117
+
118
+ if (valueMeta.includes('neutral')) {
119
+ meta.push('color', 'text');
120
+ }
121
+
122
+ if (valueMeta.includes('neutral') && (value === 'N400' || value === 'N500')) {
123
+ meta.push('color', 'text', 'subtle');
124
+ }
125
+
126
+ if (
127
+ valueMeta.includes('neutral') &&
128
+ (value === 'N80' ||
129
+ value === 'N100' ||
130
+ value === 'N200' ||
131
+ value === 'N300' ||
132
+ value === 'N400')
133
+ ) {
134
+ meta.push('color', 'text', 'subtlest');
135
+ }
136
+
137
+ // handle non-neutrals
138
+ if (!valueMeta.includes('neutral')) {
139
+ meta.push('color', ...ancestorMeta, ...valueMeta);
140
+ }
141
+ }
142
+
143
+ if (property === 'background' || property === 'background-color') {
144
+ if (ancestorMeta.includes('disabled')) {
145
+ // disabled backgrounds
146
+ meta.push(property, ...ancestorMeta);
147
+ } else if (
148
+ // Surfaces
149
+ valueMeta.includes('neutral') &&
150
+ value !== 'N100' &&
151
+ value !== 'N200' &&
152
+ value !== 'N300' &&
153
+ value !== 'N400' &&
154
+ value !== 'N500' &&
155
+ value !== 'N600' &&
156
+ value !== 'N700' &&
157
+ value !== 'N800'
158
+ ) {
159
+ meta.push('surface', ...ancestorMeta);
160
+ } else if (value.includes('N0')) {
161
+ // default surface
162
+ meta.push('elevation', 'surface');
163
+ } else if (valueMeta.includes('neutral') && isBoldColor(value)) {
164
+ // bold netural backgrounds
165
+ meta.push('background', 'neutral', 'bold');
166
+ } else if (valueMeta.includes('neutral')) {
167
+ // netural backgrounds
168
+ meta.push('background', 'neutral');
169
+ }
170
+ }
171
+
172
+ if (
173
+ property === 'border' ||
174
+ property === 'border-color' ||
175
+ property === 'border-left' ||
176
+ property === 'border-right' ||
177
+ property === 'border-top' ||
178
+ property === 'border-bottom' ||
179
+ property === 'outline' ||
180
+ property === 'outline-color'
181
+ ) {
182
+ possibleTokens = activeTokens.filter(
183
+ (token) => token.includes('.border') || token.includes('.focus'),
184
+ );
185
+
186
+ if (valueMeta.includes('neutral')) {
187
+ // standard netural boarder
188
+ meta.push('color', 'border', ...ancestorMeta);
189
+ } else {
190
+ meta.push('border', ...valueMeta, ...ancestorMeta);
191
+ }
192
+ }
193
+
194
+ if (ancestorMeta.includes('icon')) {
195
+ possibleTokens = activeTokens.filter((token) => token.includes('.icon'));
196
+
197
+ if (ancestorMeta.includes('disabled')) {
198
+ // disabled backgrounds
199
+ meta.push('disabled');
200
+ }
201
+
202
+ meta.push('color', 'icon', ...valueMeta);
203
+ }
204
+
205
+ // Fallback if guided behavior yields nothing
206
+ if (meta.length === 0) {
207
+ meta.push(property, ...valueMeta, ...ancestorMeta);
208
+ }
209
+
210
+ const search = Search(possibleTokens, false);
211
+ const results: [number, string][] = search.get(meta.join(' '));
212
+
213
+ let tokenId = ['MISSING_TOKEN'];
214
+
215
+ if (results) {
216
+ tokenId = results.map((result) => result[1]) as any;
217
+ }
218
+
219
+ return tokenId[0];
245
220
  }
246
221
 
247
222
  function parseCSSPropertyName(cssString: string) {
248
- const lastColonIndex = cssString.lastIndexOf(':');
249
- if (lastColonIndex === -1) {
250
- return { colonIndex: null, cssPropertyName: null };
251
- }
252
-
253
- const propertyNameEndIndex = Math.max(
254
- cssString.lastIndexOf(';', lastColonIndex),
255
- cssString.lastIndexOf(' ', lastColonIndex),
256
- -1,
257
- );
258
-
259
- const startIndex = propertyNameEndIndex + 1;
260
- return {
261
- cssPropertyName: cssString.slice(startIndex, lastColonIndex).trim(),
262
- colonIndex: lastColonIndex,
263
- };
223
+ const lastColonIndex = cssString.lastIndexOf(':');
224
+ if (lastColonIndex === -1) {
225
+ return { colonIndex: null, cssPropertyName: null };
226
+ }
227
+
228
+ const propertyNameEndIndex = Math.max(
229
+ cssString.lastIndexOf(';', lastColonIndex),
230
+ cssString.lastIndexOf(' ', lastColonIndex),
231
+ -1,
232
+ );
233
+
234
+ const startIndex = propertyNameEndIndex + 1;
235
+ return {
236
+ cssPropertyName: cssString.slice(startIndex, lastColonIndex).trim(),
237
+ colonIndex: lastColonIndex,
238
+ };
264
239
  }
265
240
 
266
- export default async function transformer(
267
- file: FileInfo,
268
- api: API,
269
- debug = false,
270
- ) {
271
- const j = api.jscodeshift;
272
- const source = j(file.source);
273
- let transformed = false;
274
-
275
- // Objects
276
- source.find(j.ObjectProperty).forEach((path) => {
277
- if (path.value.value.type === 'ObjectExpression') {
278
- return;
279
- }
280
-
281
- // Avoid transforming objects that are default arguments
282
- if (
283
- path.parent.parent.value.type === 'ArrowFunctionExpression' ||
284
- path.parent.parent.value.type === 'FunctionDeclaration'
285
- ) {
286
- return;
287
- }
288
-
289
- if (isParentOfToken(j, path.value.value)) {
290
- return;
291
- }
292
-
293
- const value = getColorFromIdentifier(path.value.value);
294
-
295
- if (
296
- !value ||
297
- (!includesHardCodedColor(value) &&
298
- !isHardCodedColor(value) &&
299
- !isLegacyColor(value) &&
300
- !isLegacyNamedColor(value))
301
- ) {
302
- return;
303
- }
304
-
305
- let key;
306
-
307
- if (
308
- path.value.key.type === 'NumericLiteral' ||
309
- path.value.key.type === 'StringLiteral'
310
- ) {
311
- key = path.value.key.value.toString();
312
- }
313
-
314
- if (path.value.key.type === 'Identifier') {
315
- key = path.value.key.name;
316
- }
317
-
318
- // Key is a node type we do not support
319
- if (!key) {
320
- return;
321
- }
322
-
323
- const tokenId = getTokenFromNode(j, path, value, key);
324
-
325
- insertTokenImport(j, source);
326
-
327
- j(path).replaceWith(
328
- j.objectProperty(
329
- path.value.key,
330
- buildToken(j, tokenId, path.value.value),
331
- ),
332
- );
333
-
334
- transformed = true;
335
- });
336
-
337
- // JSX props
338
- source.find(j.JSXAttribute).forEach((path) => {
339
- if (path.value?.value?.type !== 'JSXExpressionContainer') {
340
- return;
341
- }
342
-
343
- if (isParentOfToken(j, path)) {
344
- return;
345
- }
346
-
347
- const expression = path.value.value.expression;
348
- const value = getColorFromIdentifier(expression);
349
-
350
- if (
351
- !value ||
352
- (!includesHardCodedColor(value) &&
353
- !isHardCodedColor(value) &&
354
- !isLegacyColor(value) &&
355
- !isLegacyNamedColor(value))
356
- ) {
357
- return;
358
- }
359
-
360
- const tokenId = getTokenFromNode(
361
- j,
362
- path,
363
- value,
364
- path.value.name.name as string,
365
- );
366
- insertTokenImport(j, source);
367
-
368
- j(path)
369
- .find(j.JSXExpressionContainer)
370
- .forEach((path) => {
371
- const tokenNode = buildToken(j, tokenId, path.value.expression);
372
- j(path).replaceWith(j.jsxExpressionContainer(tokenNode));
373
- });
374
-
375
- transformed = true;
376
- });
377
-
378
- // Strings
379
- source.find(j.StringLiteral).forEach((path) => {
380
- j(path)
381
- .filter(
382
- (expression) => !isDecendantOfType(j, expression, j.ObjectExpression),
383
- )
384
- .forEach((path) => {
385
- const value = path.value.value;
386
-
387
- if (replaceStringLiteralIfItConsistsOnlyOfColor(j, path, value)) {
388
- transformed = true;
389
- }
390
- });
391
- });
392
-
393
- const templateLiteralPaths = source.find(j.TemplateLiteral).paths();
394
-
395
- for (const path of templateLiteralPaths) {
396
- // Background: a 'type: TemplateLiteral' Node has quasis and expressions
397
- // (see ast-types/src/gen/namedTypes.ts), and invariant holds that
398
- // quasis.length === expression.length + 1.
399
- //
400
- // eg `${foo}bar` has quasis [Node(''), Node('bar')] and expressions
401
- // [Node('foo')]. Each quasi has type: 'TemplateElement'; expressions are
402
- // probably safe to treat as subtypes of Expression, though ast-types
403
- // codebase has a more involved definition.
404
- if (path.value.expressions.length === 0) {
405
- // A single-quasi (equivalently, no-expression) template literal is
406
- // basically just a string literal, possibly multi-line. We handle the
407
- // simple `#ababab` case here, and the multi-line case after.
408
- const text = path.value.quasis[0].value.raw;
409
-
410
- if (replaceStringLiteralIfItConsistsOnlyOfColor(j, path, text)) {
411
- transformed = true;
412
- }
413
- } else {
414
- j(path)
415
- .find(j.Expression)
416
- .filter((expressionPath) => {
417
- // jscodeshift walks over the whole tree; we are interested only in
418
- // the direct children: i.e. top-level expressions appearing in ${}.
419
- return expressionPath.parent === path;
420
- })
421
- .forEach((expressionPath, expressionIndex) => {
422
- if (
423
- replaceTemplateLiteralExpression(
424
- j,
425
- path,
426
- expressionPath,
427
- expressionIndex,
428
- )
429
- ) {
430
- transformed = true;
431
- }
432
- });
433
- }
434
-
435
- // No matter if we have one big quasi or many small chunks between
436
- // expressions (which potentially have been transformed), try to pass them
437
- // through the CSS transformer; it's robust enough to understand malformed
438
- // CSS that would result if we split e.g. this template:
439
- //
440
- // `${gridSize}px; color: red;`, giving `px; color: red;` as input; or
441
- // `@media ${mobile} { color: red }`, giving `{ color: red }`.
442
- const quasiPaths = j(path)
443
- .find(j.TemplateElement)
444
- .filter((quasiPath) => {
445
- return quasiPath.parent === path;
446
- })
447
- .paths();
448
-
449
- for (const quasiPath of quasiPaths) {
450
- const text = quasiPath.value.value.raw;
451
- if (
452
- includesHardCodedColor(text) &&
453
- containsReplaceableCSSDeclarations(text)
454
- ) {
455
- const newCSS = await CSSTransformer(text);
456
-
457
- j(quasiPath).replaceWith(buildTemplateElement(j, newCSS));
458
- transformed = true;
459
- }
460
- }
461
- }
462
-
463
- function replaceStringLiteralIfItConsistsOnlyOfColor(
464
- j: any,
465
- path: any,
466
- value: string,
467
- ) {
468
- if (isDecendantOfToken(j, path)) {
469
- return false;
470
- }
471
-
472
- if (
473
- isHardCodedColor(value) &&
474
- !isLegacyColor(value) &&
475
- !isLegacyNamedColor(value)
476
- ) {
477
- const parent = path.parent.value;
478
- let key = '';
479
-
480
- if (parent.type === 'VariableDeclarator') {
481
- key = parent.id.name;
482
- }
483
-
484
- const tokenId = getTokenFromNode(j, path, value, key);
485
-
486
- insertTokenImport(j, source);
487
-
488
- j(path).replaceWith(buildToken(j, tokenId, path.value));
489
-
490
- return true;
491
- }
492
-
493
- return false;
494
- }
495
-
496
- function replaceTemplateLiteralExpression(
497
- j: any,
498
- mainPath: any,
499
- expressionPath: any,
500
- expressionIndex: any,
501
- ) {
502
- const expression = expressionPath.value;
503
- if (
504
- !(
505
- expression.type === 'MemberExpression' ||
506
- expression.type === 'Identifier'
507
- )
508
- ) {
509
- return false;
510
- }
511
-
512
- if (isDecendantOfToken(j, expressionPath)) {
513
- return false;
514
- }
515
-
516
- const value = getColorFromIdentifier(expression);
517
-
518
- if (
519
- !value ||
520
- (!includesHardCodedColor(value) &&
521
- !isHardCodedColor(value) &&
522
- !isLegacyColor(value) &&
523
- !isLegacyNamedColor(value))
524
- ) {
525
- return false;
526
- }
527
-
528
- const precedingQuasi = mainPath.value.quasis[expressionIndex];
529
- const precedingQuasiText = precedingQuasi.value.raw;
530
- const { cssPropertyName, colonIndex } =
531
- parseCSSPropertyName(precedingQuasiText);
532
-
533
- if (!cssPropertyName) {
534
- return false;
535
- }
536
-
537
- const tokenId = getTokenFromNode(j, expressionPath, value, cssPropertyName);
538
-
539
- insertTokenImport(j, source);
540
-
541
- const newQuasis = [...mainPath.value.quasis];
542
- const newExpressions = [...mainPath.value.expressions];
543
-
544
- if (cssPropertyName !== 'box-shadow') {
545
- const tokenExpression = buildToken(j, tokenId, expressionPath.value);
546
-
547
- newExpressions[expressionIndex] = tokenExpression;
548
- } else {
549
- // box-shadow is a multi-part property where the color can appear at any
550
- // part position (even though the standard suggests that color comes
551
- // last, browsers' CSS parsers are more lax). If we get here, then the
552
- // color part is replaceable. Textually, it's something like:
553
- //
554
- // <rules before>; box-shadow: 0 1px ${colors.N50} 2rem; <rules after>
555
- //
556
- // the fallback value will be multipart, i.e. the token call is
557
- //
558
- // token(<replacedValue>, `0 1px ${colors.N50} 2rem`)
559
- //
560
- // and it's wrapped in a substitution like this:
561
- //
562
- // <rules before>; box-shadow: ${token(<...>)}; <rules after>
563
- //
564
- // We stich the fallback from the last part of preceding quasi (after
565
- // colon) and the first part of the following quasi (before ';' or '}').
566
- //
567
- // If multiple box-shadows are comma-separated but only one of them has a
568
- // replaceable color and others are hard-coded, this logic would still
569
- // work. When multiple shadows have expressions, it's unfortunately not
570
- // possible to proceed because we cannot find where the value ends from a
571
- // single following quasi.
572
- const valueStartIndex = findFirstNonspaceIndexAfter(
573
- precedingQuasiText,
574
- colonIndex,
575
- );
576
-
577
- const [newPrecedingQuasiText, partialValueBeginning] = splitAtIndex(
578
- precedingQuasiText,
579
- valueStartIndex,
580
- );
581
-
582
- const followingQuasi = mainPath.value.quasis[expressionIndex + 1];
583
- const followingQuasiText = followingQuasi.value.raw;
584
-
585
- const valueEndIndex = findEndIndexOfCSSExpression(
586
- followingQuasiText,
587
- followingQuasi.tail,
588
- );
589
- if (!valueEndIndex) {
590
- console.warn(
591
- 'cannot find end of box-shadow value, please check manually',
592
- );
593
- return false;
594
- }
595
- const [partialValueEnd, newFollowingQuasiText] = splitAtIndex(
596
- followingQuasiText,
597
- valueEndIndex + 1,
598
- );
599
-
600
- const internalQuasis = [
601
- buildTemplateElement(j, partialValueBeginning, { tail: false }),
602
- buildTemplateElement(j, partialValueEnd, { tail: true }),
603
- ];
604
- const internalExpressions = [expressionPath.value];
605
- const newFallback = j.templateLiteral(
606
- internalQuasis,
607
- internalExpressions,
608
- );
609
- const newExpression = buildToken(j, tokenId, newFallback);
610
-
611
- newQuasis[expressionIndex] = buildTemplateElement(
612
- j,
613
- newPrecedingQuasiText,
614
- { fromNode: newQuasis[expressionIndex] },
615
- );
616
- newExpressions[expressionIndex] = newExpression;
617
- newQuasis[expressionIndex + 1] = buildTemplateElement(
618
- j,
619
- newFollowingQuasiText,
620
- { fromNode: newQuasis[expressionIndex] },
621
- );
622
- }
623
- mainPath.replace(j.templateLiteral(newQuasis, newExpressions));
624
- return true;
625
- }
626
-
627
- return transformed ? source.toSource() : file.source;
241
+ export default async function transformer(file: FileInfo, api: API, debug = false) {
242
+ const j = api.jscodeshift;
243
+ const source = j(file.source);
244
+ let transformed = false;
245
+
246
+ // Objects
247
+ source.find(j.ObjectProperty).forEach((path) => {
248
+ if (path.value.value.type === 'ObjectExpression') {
249
+ return;
250
+ }
251
+
252
+ // Avoid transforming objects that are default arguments
253
+ if (
254
+ path.parent.parent.value.type === 'ArrowFunctionExpression' ||
255
+ path.parent.parent.value.type === 'FunctionDeclaration'
256
+ ) {
257
+ return;
258
+ }
259
+
260
+ if (isParentOfToken(j, path.value.value)) {
261
+ return;
262
+ }
263
+
264
+ const value = getColorFromIdentifier(path.value.value);
265
+
266
+ if (
267
+ !value ||
268
+ (!includesHardCodedColor(value) &&
269
+ !isHardCodedColor(value) &&
270
+ !isLegacyColor(value) &&
271
+ !isLegacyNamedColor(value))
272
+ ) {
273
+ return;
274
+ }
275
+
276
+ let key;
277
+
278
+ if (path.value.key.type === 'NumericLiteral' || path.value.key.type === 'StringLiteral') {
279
+ key = path.value.key.value.toString();
280
+ }
281
+
282
+ if (path.value.key.type === 'Identifier') {
283
+ key = path.value.key.name;
284
+ }
285
+
286
+ // Key is a node type we do not support
287
+ if (!key) {
288
+ return;
289
+ }
290
+
291
+ const tokenId = getTokenFromNode(j, path, value, key);
292
+
293
+ insertTokenImport(j, source);
294
+
295
+ j(path).replaceWith(j.objectProperty(path.value.key, buildToken(j, tokenId, path.value.value)));
296
+
297
+ transformed = true;
298
+ });
299
+
300
+ // JSX props
301
+ source.find(j.JSXAttribute).forEach((path) => {
302
+ if (path.value?.value?.type !== 'JSXExpressionContainer') {
303
+ return;
304
+ }
305
+
306
+ if (isParentOfToken(j, path)) {
307
+ return;
308
+ }
309
+
310
+ const expression = path.value.value.expression;
311
+ const value = getColorFromIdentifier(expression);
312
+
313
+ if (
314
+ !value ||
315
+ (!includesHardCodedColor(value) &&
316
+ !isHardCodedColor(value) &&
317
+ !isLegacyColor(value) &&
318
+ !isLegacyNamedColor(value))
319
+ ) {
320
+ return;
321
+ }
322
+
323
+ const tokenId = getTokenFromNode(j, path, value, path.value.name.name as string);
324
+ insertTokenImport(j, source);
325
+
326
+ j(path)
327
+ .find(j.JSXExpressionContainer)
328
+ .forEach((path) => {
329
+ const tokenNode = buildToken(j, tokenId, path.value.expression);
330
+ j(path).replaceWith(j.jsxExpressionContainer(tokenNode));
331
+ });
332
+
333
+ transformed = true;
334
+ });
335
+
336
+ // Strings
337
+ source.find(j.StringLiteral).forEach((path) => {
338
+ j(path)
339
+ .filter((expression) => !isDecendantOfType(j, expression, j.ObjectExpression))
340
+ .forEach((path) => {
341
+ const value = path.value.value;
342
+
343
+ if (replaceStringLiteralIfItConsistsOnlyOfColor(j, path, value)) {
344
+ transformed = true;
345
+ }
346
+ });
347
+ });
348
+
349
+ const templateLiteralPaths = source.find(j.TemplateLiteral).paths();
350
+
351
+ for (const path of templateLiteralPaths) {
352
+ // Background: a 'type: TemplateLiteral' Node has quasis and expressions
353
+ // (see ast-types/src/gen/namedTypes.ts), and invariant holds that
354
+ // quasis.length === expression.length + 1.
355
+ //
356
+ // eg `${foo}bar` has quasis [Node(''), Node('bar')] and expressions
357
+ // [Node('foo')]. Each quasi has type: 'TemplateElement'; expressions are
358
+ // probably safe to treat as subtypes of Expression, though ast-types
359
+ // codebase has a more involved definition.
360
+ if (path.value.expressions.length === 0) {
361
+ // A single-quasi (equivalently, no-expression) template literal is
362
+ // basically just a string literal, possibly multi-line. We handle the
363
+ // simple `#ababab` case here, and the multi-line case after.
364
+ const text = path.value.quasis[0].value.raw;
365
+
366
+ if (replaceStringLiteralIfItConsistsOnlyOfColor(j, path, text)) {
367
+ transformed = true;
368
+ }
369
+ } else {
370
+ j(path)
371
+ .find(j.Expression)
372
+ .filter((expressionPath) => {
373
+ // jscodeshift walks over the whole tree; we are interested only in
374
+ // the direct children: i.e. top-level expressions appearing in ${}.
375
+ return expressionPath.parent === path;
376
+ })
377
+ .forEach((expressionPath, expressionIndex) => {
378
+ if (replaceTemplateLiteralExpression(j, path, expressionPath, expressionIndex)) {
379
+ transformed = true;
380
+ }
381
+ });
382
+ }
383
+
384
+ // No matter if we have one big quasi or many small chunks between
385
+ // expressions (which potentially have been transformed), try to pass them
386
+ // through the CSS transformer; it's robust enough to understand malformed
387
+ // CSS that would result if we split e.g. this template:
388
+ //
389
+ // `${gridSize}px; color: red;`, giving `px; color: red;` as input; or
390
+ // `@media ${mobile} { color: red }`, giving `{ color: red }`.
391
+ const quasiPaths = j(path)
392
+ .find(j.TemplateElement)
393
+ .filter((quasiPath) => {
394
+ return quasiPath.parent === path;
395
+ })
396
+ .paths();
397
+
398
+ for (const quasiPath of quasiPaths) {
399
+ const text = quasiPath.value.value.raw;
400
+ if (includesHardCodedColor(text) && containsReplaceableCSSDeclarations(text)) {
401
+ const newCSS = await CSSTransformer(text);
402
+
403
+ j(quasiPath).replaceWith(buildTemplateElement(j, newCSS));
404
+ transformed = true;
405
+ }
406
+ }
407
+ }
408
+
409
+ function replaceStringLiteralIfItConsistsOnlyOfColor(j: any, path: any, value: string) {
410
+ if (isDecendantOfToken(j, path)) {
411
+ return false;
412
+ }
413
+
414
+ if (isHardCodedColor(value) && !isLegacyColor(value) && !isLegacyNamedColor(value)) {
415
+ const parent = path.parent.value;
416
+ let key = '';
417
+
418
+ if (parent.type === 'VariableDeclarator') {
419
+ key = parent.id.name;
420
+ }
421
+
422
+ const tokenId = getTokenFromNode(j, path, value, key);
423
+
424
+ insertTokenImport(j, source);
425
+
426
+ j(path).replaceWith(buildToken(j, tokenId, path.value));
427
+
428
+ return true;
429
+ }
430
+
431
+ return false;
432
+ }
433
+
434
+ function replaceTemplateLiteralExpression(
435
+ j: any,
436
+ mainPath: any,
437
+ expressionPath: any,
438
+ expressionIndex: any,
439
+ ) {
440
+ const expression = expressionPath.value;
441
+ if (!(expression.type === 'MemberExpression' || expression.type === 'Identifier')) {
442
+ return false;
443
+ }
444
+
445
+ if (isDecendantOfToken(j, expressionPath)) {
446
+ return false;
447
+ }
448
+
449
+ const value = getColorFromIdentifier(expression);
450
+
451
+ if (
452
+ !value ||
453
+ (!includesHardCodedColor(value) &&
454
+ !isHardCodedColor(value) &&
455
+ !isLegacyColor(value) &&
456
+ !isLegacyNamedColor(value))
457
+ ) {
458
+ return false;
459
+ }
460
+
461
+ const precedingQuasi = mainPath.value.quasis[expressionIndex];
462
+ const precedingQuasiText = precedingQuasi.value.raw;
463
+ const { cssPropertyName, colonIndex } = parseCSSPropertyName(precedingQuasiText);
464
+
465
+ if (!cssPropertyName) {
466
+ return false;
467
+ }
468
+
469
+ const tokenId = getTokenFromNode(j, expressionPath, value, cssPropertyName);
470
+
471
+ insertTokenImport(j, source);
472
+
473
+ const newQuasis = [...mainPath.value.quasis];
474
+ const newExpressions = [...mainPath.value.expressions];
475
+
476
+ if (cssPropertyName !== 'box-shadow') {
477
+ const tokenExpression = buildToken(j, tokenId, expressionPath.value);
478
+
479
+ newExpressions[expressionIndex] = tokenExpression;
480
+ } else {
481
+ // box-shadow is a multi-part property where the color can appear at any
482
+ // part position (even though the standard suggests that color comes
483
+ // last, browsers' CSS parsers are more lax). If we get here, then the
484
+ // color part is replaceable. Textually, it's something like:
485
+ //
486
+ // <rules before>; box-shadow: 0 1px ${colors.N50} 2rem; <rules after>
487
+ //
488
+ // the fallback value will be multipart, i.e. the token call is
489
+ //
490
+ // token(<replacedValue>, `0 1px ${colors.N50} 2rem`)
491
+ //
492
+ // and it's wrapped in a substitution like this:
493
+ //
494
+ // <rules before>; box-shadow: ${token(<...>)}; <rules after>
495
+ //
496
+ // We stich the fallback from the last part of preceding quasi (after
497
+ // colon) and the first part of the following quasi (before ';' or '}').
498
+ //
499
+ // If multiple box-shadows are comma-separated but only one of them has a
500
+ // replaceable color and others are hard-coded, this logic would still
501
+ // work. When multiple shadows have expressions, it's unfortunately not
502
+ // possible to proceed because we cannot find where the value ends from a
503
+ // single following quasi.
504
+ const valueStartIndex = findFirstNonspaceIndexAfter(precedingQuasiText, colonIndex);
505
+
506
+ const [newPrecedingQuasiText, partialValueBeginning] = splitAtIndex(
507
+ precedingQuasiText,
508
+ valueStartIndex,
509
+ );
510
+
511
+ const followingQuasi = mainPath.value.quasis[expressionIndex + 1];
512
+ const followingQuasiText = followingQuasi.value.raw;
513
+
514
+ const valueEndIndex = findEndIndexOfCSSExpression(followingQuasiText, followingQuasi.tail);
515
+ if (!valueEndIndex) {
516
+ console.warn('cannot find end of box-shadow value, please check manually');
517
+ return false;
518
+ }
519
+ const [partialValueEnd, newFollowingQuasiText] = splitAtIndex(
520
+ followingQuasiText,
521
+ valueEndIndex + 1,
522
+ );
523
+
524
+ const internalQuasis = [
525
+ buildTemplateElement(j, partialValueBeginning, { tail: false }),
526
+ buildTemplateElement(j, partialValueEnd, { tail: true }),
527
+ ];
528
+ const internalExpressions = [expressionPath.value];
529
+ const newFallback = j.templateLiteral(internalQuasis, internalExpressions);
530
+ const newExpression = buildToken(j, tokenId, newFallback);
531
+
532
+ newQuasis[expressionIndex] = buildTemplateElement(j, newPrecedingQuasiText, {
533
+ fromNode: newQuasis[expressionIndex],
534
+ });
535
+ newExpressions[expressionIndex] = newExpression;
536
+ newQuasis[expressionIndex + 1] = buildTemplateElement(j, newFollowingQuasiText, {
537
+ fromNode: newQuasis[expressionIndex],
538
+ });
539
+ }
540
+ mainPath.replace(j.templateLiteral(newQuasis, newExpressions));
541
+ return true;
542
+ }
543
+
544
+ return transformed ? source.toSource() : file.source;
628
545
  }