@workday/canvas-kit-styling-transform 13.2.0 → 13.2.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.
Files changed (216) hide show
  1. package/dist/commonjs/index.d.ts +14 -0
  2. package/dist/commonjs/index.d.ts.map +1 -0
  3. package/dist/commonjs/index.js +28 -0
  4. package/dist/commonjs/lib/createObjectTransform.d.ts +10 -0
  5. package/dist/commonjs/lib/createObjectTransform.d.ts.map +1 -0
  6. package/dist/commonjs/lib/createObjectTransform.js +14 -0
  7. package/dist/commonjs/lib/createPropertyTransform.d.ts +7 -0
  8. package/dist/commonjs/lib/createPropertyTransform.d.ts.map +1 -0
  9. package/dist/commonjs/lib/createPropertyTransform.js +11 -0
  10. package/dist/commonjs/lib/createTypeScriptWatchProgram.d.ts +16 -0
  11. package/dist/commonjs/lib/createTypeScriptWatchProgram.d.ts.map +1 -0
  12. package/dist/commonjs/lib/createTypeScriptWatchProgram.js +45 -0
  13. package/dist/commonjs/lib/styleTransform.d.ts +23 -0
  14. package/dist/commonjs/lib/styleTransform.d.ts.map +1 -0
  15. package/dist/commonjs/lib/styleTransform.js +131 -0
  16. package/dist/commonjs/lib/utils/createStyleObjectNode.d.ts +35 -0
  17. package/dist/commonjs/lib/utils/createStyleObjectNode.d.ts.map +1 -0
  18. package/dist/commonjs/lib/utils/createStyleObjectNode.js +84 -0
  19. package/dist/commonjs/lib/utils/getCssVariables.d.ts +4 -0
  20. package/dist/commonjs/lib/utils/getCssVariables.d.ts.map +1 -0
  21. package/dist/commonjs/lib/utils/getCssVariables.js +31 -0
  22. package/dist/commonjs/lib/utils/getErrorMessage.d.ts +16 -0
  23. package/dist/commonjs/lib/utils/getErrorMessage.d.ts.map +1 -0
  24. package/dist/commonjs/lib/utils/getErrorMessage.js +45 -0
  25. package/dist/commonjs/lib/utils/getFallbackVariable.d.ts +9 -0
  26. package/dist/commonjs/lib/utils/getFallbackVariable.d.ts.map +1 -0
  27. package/dist/commonjs/lib/utils/getFallbackVariable.js +30 -0
  28. package/dist/commonjs/lib/utils/getHash.d.ts +4 -0
  29. package/dist/commonjs/lib/utils/getHash.d.ts.map +1 -0
  30. package/dist/commonjs/lib/utils/getHash.js +16 -0
  31. package/dist/commonjs/lib/utils/getVarName.d.ts +17 -0
  32. package/dist/commonjs/lib/utils/getVarName.d.ts.map +1 -0
  33. package/dist/commonjs/lib/utils/getVarName.js +34 -0
  34. package/dist/commonjs/lib/utils/handleCalc.d.ts +2 -0
  35. package/dist/commonjs/lib/utils/handleCalc.d.ts.map +1 -0
  36. package/dist/commonjs/lib/utils/handleCalc.js +33 -0
  37. package/dist/commonjs/lib/utils/handleCreateStencil.d.ts +7 -0
  38. package/dist/commonjs/lib/utils/handleCreateStencil.d.ts.map +1 -0
  39. package/dist/commonjs/lib/utils/handleCreateStencil.js +309 -0
  40. package/dist/commonjs/lib/utils/handleCreateStyles.d.ts +3 -0
  41. package/dist/commonjs/lib/utils/handleCreateStyles.d.ts.map +1 -0
  42. package/dist/commonjs/lib/utils/handleCreateStyles.js +86 -0
  43. package/dist/commonjs/lib/utils/handleCreateVars.d.ts +3 -0
  44. package/dist/commonjs/lib/utils/handleCreateVars.d.ts.map +1 -0
  45. package/dist/commonjs/lib/utils/handleCreateVars.js +65 -0
  46. package/dist/commonjs/lib/utils/handleCssVar.d.ts +2 -0
  47. package/dist/commonjs/lib/utils/handleCssVar.d.ts.map +1 -0
  48. package/dist/commonjs/lib/utils/handleCssVar.js +19 -0
  49. package/dist/commonjs/lib/utils/handleInjectGlobal.d.ts +3 -0
  50. package/dist/commonjs/lib/utils/handleInjectGlobal.d.ts.map +1 -0
  51. package/dist/commonjs/lib/utils/handleInjectGlobal.js +40 -0
  52. package/dist/commonjs/lib/utils/handleKeyframes.d.ts +3 -0
  53. package/dist/commonjs/lib/utils/handleKeyframes.d.ts.map +1 -0
  54. package/dist/commonjs/lib/utils/handleKeyframes.js +48 -0
  55. package/dist/commonjs/lib/utils/handleParentModifier.d.ts +2 -0
  56. package/dist/commonjs/lib/utils/handleParentModifier.d.ts.map +1 -0
  57. package/dist/commonjs/lib/utils/handleParentModifier.js +26 -0
  58. package/dist/commonjs/lib/utils/handlePx2Rem.d.ts +2 -0
  59. package/dist/commonjs/lib/utils/handlePx2Rem.d.ts.map +1 -0
  60. package/dist/commonjs/lib/utils/handlePx2Rem.js +19 -0
  61. package/dist/commonjs/lib/utils/injectStyles.d.ts +3 -0
  62. package/dist/commonjs/lib/utils/injectStyles.d.ts.map +1 -0
  63. package/dist/commonjs/lib/utils/injectStyles.js +11 -0
  64. package/dist/commonjs/lib/utils/isImportedFromStyling.d.ts +7 -0
  65. package/dist/commonjs/lib/utils/isImportedFromStyling.d.ts.map +1 -0
  66. package/dist/commonjs/lib/utils/isImportedFromStyling.js +24 -0
  67. package/dist/commonjs/lib/utils/parseNodeToStaticValue.d.ts +11 -0
  68. package/dist/commonjs/lib/utils/parseNodeToStaticValue.d.ts.map +1 -0
  69. package/dist/commonjs/lib/utils/parseNodeToStaticValue.js +217 -0
  70. package/dist/commonjs/lib/utils/parseObjectToStaticValue.d.ts +15 -0
  71. package/dist/commonjs/lib/utils/parseObjectToStaticValue.d.ts.map +1 -0
  72. package/dist/commonjs/lib/utils/parseObjectToStaticValue.js +168 -0
  73. package/dist/commonjs/lib/utils/stylisFns.d.ts +3 -0
  74. package/dist/commonjs/lib/utils/stylisFns.d.ts.map +1 -0
  75. package/dist/commonjs/lib/utils/stylisFns.js +45 -0
  76. package/dist/commonjs/lib/utils/types.d.ts +210 -0
  77. package/dist/commonjs/lib/utils/types.d.ts.map +1 -0
  78. package/dist/commonjs/lib/utils/types.js +2 -0
  79. package/dist/commonjs/lib/webpack-loader.d.ts +7 -0
  80. package/dist/commonjs/lib/webpack-loader.d.ts.map +1 -0
  81. package/dist/commonjs/lib/webpack-loader.js +21 -0
  82. package/dist/commonjs/lib/webpackPlugin.d.ts +31 -0
  83. package/dist/commonjs/lib/webpackPlugin.d.ts.map +1 -0
  84. package/dist/commonjs/lib/webpackPlugin.js +38 -0
  85. package/dist/commonjs/spec/createProgramFromSource.d.ts +8 -0
  86. package/dist/commonjs/spec/createProgramFromSource.d.ts.map +1 -0
  87. package/dist/commonjs/spec/createProgramFromSource.js +111 -0
  88. package/dist/commonjs/spec/findNodes.d.ts +3 -0
  89. package/dist/commonjs/spec/findNodes.d.ts.map +1 -0
  90. package/dist/commonjs/spec/findNodes.js +33 -0
  91. package/dist/commonjs/testing.d.ts +4 -0
  92. package/dist/commonjs/testing.d.ts.map +1 -0
  93. package/dist/commonjs/testing.js +11 -0
  94. package/dist/es6/index.d.ts +14 -0
  95. package/dist/es6/index.d.ts.map +1 -0
  96. package/dist/es6/index.js +14 -0
  97. package/dist/es6/lib/createObjectTransform.d.ts +10 -0
  98. package/dist/es6/lib/createObjectTransform.d.ts.map +1 -0
  99. package/dist/es6/lib/createObjectTransform.js +10 -0
  100. package/dist/es6/lib/createPropertyTransform.d.ts +7 -0
  101. package/dist/es6/lib/createPropertyTransform.d.ts.map +1 -0
  102. package/dist/es6/lib/createPropertyTransform.js +7 -0
  103. package/dist/es6/lib/createTypeScriptWatchProgram.d.ts +16 -0
  104. package/dist/es6/lib/createTypeScriptWatchProgram.d.ts.map +1 -0
  105. package/dist/es6/lib/createTypeScriptWatchProgram.js +36 -0
  106. package/dist/es6/lib/styleTransform.d.ts +23 -0
  107. package/dist/es6/lib/styleTransform.d.ts.map +1 -0
  108. package/dist/es6/lib/styleTransform.js +120 -0
  109. package/dist/es6/lib/utils/createStyleObjectNode.d.ts +35 -0
  110. package/dist/es6/lib/utils/createStyleObjectNode.d.ts.map +1 -0
  111. package/dist/es6/lib/utils/createStyleObjectNode.js +74 -0
  112. package/dist/es6/lib/utils/getCssVariables.d.ts +4 -0
  113. package/dist/es6/lib/utils/getCssVariables.d.ts.map +1 -0
  114. package/dist/es6/lib/utils/getCssVariables.js +26 -0
  115. package/dist/es6/lib/utils/getErrorMessage.d.ts +16 -0
  116. package/dist/es6/lib/utils/getErrorMessage.d.ts.map +1 -0
  117. package/dist/es6/lib/utils/getErrorMessage.js +41 -0
  118. package/dist/es6/lib/utils/getFallbackVariable.d.ts +9 -0
  119. package/dist/es6/lib/utils/getFallbackVariable.d.ts.map +1 -0
  120. package/dist/es6/lib/utils/getFallbackVariable.js +26 -0
  121. package/dist/es6/lib/utils/getHash.d.ts +4 -0
  122. package/dist/es6/lib/utils/getHash.d.ts.map +1 -0
  123. package/dist/es6/lib/utils/getHash.js +9 -0
  124. package/dist/es6/lib/utils/getVarName.d.ts +17 -0
  125. package/dist/es6/lib/utils/getVarName.d.ts.map +1 -0
  126. package/dist/es6/lib/utils/getVarName.js +27 -0
  127. package/dist/es6/lib/utils/handleCalc.d.ts +2 -0
  128. package/dist/es6/lib/utils/handleCalc.d.ts.map +1 -0
  129. package/dist/es6/lib/utils/handleCalc.js +27 -0
  130. package/dist/es6/lib/utils/handleCreateStencil.d.ts +7 -0
  131. package/dist/es6/lib/utils/handleCreateStencil.d.ts.map +1 -0
  132. package/dist/es6/lib/utils/handleCreateStencil.js +301 -0
  133. package/dist/es6/lib/utils/handleCreateStyles.d.ts +3 -0
  134. package/dist/es6/lib/utils/handleCreateStyles.d.ts.map +1 -0
  135. package/dist/es6/lib/utils/handleCreateStyles.js +79 -0
  136. package/dist/es6/lib/utils/handleCreateVars.d.ts +3 -0
  137. package/dist/es6/lib/utils/handleCreateVars.d.ts.map +1 -0
  138. package/dist/es6/lib/utils/handleCreateVars.js +58 -0
  139. package/dist/es6/lib/utils/handleCssVar.d.ts +2 -0
  140. package/dist/es6/lib/utils/handleCssVar.d.ts.map +1 -0
  141. package/dist/es6/lib/utils/handleCssVar.js +13 -0
  142. package/dist/es6/lib/utils/handleInjectGlobal.d.ts +3 -0
  143. package/dist/es6/lib/utils/handleInjectGlobal.d.ts.map +1 -0
  144. package/dist/es6/lib/utils/handleInjectGlobal.js +33 -0
  145. package/dist/es6/lib/utils/handleKeyframes.d.ts +3 -0
  146. package/dist/es6/lib/utils/handleKeyframes.d.ts.map +1 -0
  147. package/dist/es6/lib/utils/handleKeyframes.js +41 -0
  148. package/dist/es6/lib/utils/handleParentModifier.d.ts +2 -0
  149. package/dist/es6/lib/utils/handleParentModifier.d.ts.map +1 -0
  150. package/dist/es6/lib/utils/handleParentModifier.js +20 -0
  151. package/dist/es6/lib/utils/handlePx2Rem.d.ts +2 -0
  152. package/dist/es6/lib/utils/handlePx2Rem.d.ts.map +1 -0
  153. package/dist/es6/lib/utils/handlePx2Rem.js +13 -0
  154. package/dist/es6/lib/utils/injectStyles.d.ts +3 -0
  155. package/dist/es6/lib/utils/injectStyles.d.ts.map +1 -0
  156. package/dist/es6/lib/utils/injectStyles.js +7 -0
  157. package/dist/es6/lib/utils/isImportedFromStyling.d.ts +7 -0
  158. package/dist/es6/lib/utils/isImportedFromStyling.d.ts.map +1 -0
  159. package/dist/es6/lib/utils/isImportedFromStyling.js +17 -0
  160. package/dist/es6/lib/utils/parseNodeToStaticValue.d.ts +11 -0
  161. package/dist/es6/lib/utils/parseNodeToStaticValue.d.ts.map +1 -0
  162. package/dist/es6/lib/utils/parseNodeToStaticValue.js +209 -0
  163. package/dist/es6/lib/utils/parseObjectToStaticValue.d.ts +15 -0
  164. package/dist/es6/lib/utils/parseObjectToStaticValue.d.ts.map +1 -0
  165. package/dist/es6/lib/utils/parseObjectToStaticValue.js +159 -0
  166. package/dist/es6/lib/utils/stylisFns.d.ts +3 -0
  167. package/dist/es6/lib/utils/stylisFns.d.ts.map +1 -0
  168. package/dist/es6/lib/utils/stylisFns.js +41 -0
  169. package/dist/es6/lib/utils/types.d.ts +210 -0
  170. package/dist/es6/lib/utils/types.d.ts.map +1 -0
  171. package/dist/es6/lib/utils/types.js +1 -0
  172. package/dist/es6/lib/webpack-loader.d.ts +7 -0
  173. package/dist/es6/lib/webpack-loader.d.ts.map +1 -0
  174. package/dist/es6/lib/webpack-loader.js +15 -0
  175. package/dist/es6/lib/webpackPlugin.d.ts +31 -0
  176. package/dist/es6/lib/webpackPlugin.d.ts.map +1 -0
  177. package/dist/es6/lib/webpackPlugin.js +31 -0
  178. package/dist/es6/spec/createProgramFromSource.d.ts +8 -0
  179. package/dist/es6/spec/createProgramFromSource.d.ts.map +1 -0
  180. package/dist/es6/spec/createProgramFromSource.js +81 -0
  181. package/dist/es6/spec/findNodes.d.ts +3 -0
  182. package/dist/es6/spec/findNodes.d.ts.map +1 -0
  183. package/dist/es6/spec/findNodes.js +26 -0
  184. package/dist/es6/testing.d.ts +4 -0
  185. package/dist/es6/testing.d.ts.map +1 -0
  186. package/dist/es6/testing.js +3 -0
  187. package/index.ts +19 -0
  188. package/lib/createObjectTransform.ts +12 -0
  189. package/lib/createPropertyTransform.ts +9 -0
  190. package/lib/createTypeScriptWatchProgram.ts +52 -0
  191. package/lib/styleTransform.ts +169 -0
  192. package/lib/utils/createStyleObjectNode.ts +105 -0
  193. package/lib/utils/getCssVariables.ts +36 -0
  194. package/lib/utils/getErrorMessage.ts +57 -0
  195. package/lib/utils/getFallbackVariable.ts +34 -0
  196. package/lib/utils/getHash.ts +13 -0
  197. package/lib/utils/getVarName.ts +32 -0
  198. package/lib/utils/handleCalc.ts +33 -0
  199. package/lib/utils/handleCreateStencil.ts +442 -0
  200. package/lib/utils/handleCreateStyles.ts +97 -0
  201. package/lib/utils/handleCreateVars.ts +90 -0
  202. package/lib/utils/handleCssVar.ts +19 -0
  203. package/lib/utils/handleInjectGlobal.ts +51 -0
  204. package/lib/utils/handleKeyframes.ts +60 -0
  205. package/lib/utils/handleParentModifier.ts +29 -0
  206. package/lib/utils/handlePx2Rem.ts +22 -0
  207. package/lib/utils/injectStyles.ts +14 -0
  208. package/lib/utils/isImportedFromStyling.ts +21 -0
  209. package/lib/utils/parseNodeToStaticValue.ts +281 -0
  210. package/lib/utils/parseObjectToStaticValue.ts +201 -0
  211. package/lib/utils/stylisFns.ts +56 -0
  212. package/lib/utils/types.ts +223 -0
  213. package/lib/webpack-loader.ts +28 -0
  214. package/lib/webpackPlugin.ts +69 -0
  215. package/package.json +19 -14
  216. package/index.js +0 -22
@@ -0,0 +1,60 @@
1
+ import ts from 'typescript';
2
+
3
+ import {NestedStyleObject, NodeTransformer, TransformerContext} from './types';
4
+ import {parseNodeToStaticValue} from './parseNodeToStaticValue';
5
+ import {getVarName} from './getVarName';
6
+ import {createStyleObjectNode, serializeStyles} from './createStyleObjectNode';
7
+ import {isImportedFromStyling} from './isImportedFromStyling';
8
+ import {parseObjectToStaticValue} from './parseObjectToStaticValue';
9
+
10
+ export const handleKeyframes: NodeTransformer = (node, context) => {
11
+ const {checker} = context;
12
+ // keyframes`css`
13
+ if (
14
+ ts.isTaggedTemplateExpression(node) &&
15
+ ts.isIdentifier(node.tag) &&
16
+ node.tag.text === 'keyframes' &&
17
+ isImportedFromStyling(node.tag, checker)
18
+ ) {
19
+ // parseNodeToStaticValue can parse templates. Pass it through there to get a single static string
20
+ const styleObj = parseNodeToStaticValue(node.template, context).toString();
21
+ const identifierName = getVarName(node);
22
+
23
+ return ts.factory.createCallExpression(node.tag, undefined, [
24
+ createStyleReplacementNode(node, styleObj, identifierName, context),
25
+ ]);
26
+ }
27
+
28
+ // keyframes({})
29
+ if (
30
+ ts.isCallExpression(node) &&
31
+ ts.isIdentifier(node.expression) &&
32
+ node.expression.text === 'keyframes' &&
33
+ isImportedFromStyling(node.expression, checker)
34
+ ) {
35
+ if (ts.isObjectLiteralExpression(node.arguments[0])) {
36
+ const styleObj = parseObjectToStaticValue(node.arguments[0], context);
37
+ const identifierName = getVarName(node);
38
+
39
+ return ts.factory.updateCallExpression(node, node.expression, undefined, [
40
+ createStyleReplacementNode(node, styleObj, identifierName, context),
41
+ ]);
42
+ }
43
+ }
44
+
45
+ return;
46
+ };
47
+
48
+ function createStyleReplacementNode(
49
+ node: ts.Node,
50
+ styleObj: NestedStyleObject | string,
51
+ identifierName: string,
52
+ context: TransformerContext
53
+ ) {
54
+ const serialized = serializeStyles(node, styleObj, `@keyframes animation-%n{%s}`, context);
55
+ const animationName = `animation-${serialized.name}`;
56
+
57
+ context.names[identifierName] = animationName;
58
+
59
+ return createStyleObjectNode(serialized.styles, serialized.name);
60
+ }
@@ -0,0 +1,29 @@
1
+ import ts from 'typescript';
2
+
3
+ import {parentModifier} from '@workday/canvas-kit-styling';
4
+ import {createPropertyTransform} from '../createPropertyTransform';
5
+ import {parseNodeToStaticValue} from './parseNodeToStaticValue';
6
+
7
+ export const handleParentModifier = createPropertyTransform((node, context) => {
8
+ const {names, extractedNames} = context;
9
+
10
+ if (
11
+ ts.isComputedPropertyName(node) &&
12
+ ts.isCallExpression(node.expression) &&
13
+ ts.isIdentifier(node.expression.expression) &&
14
+ node.expression.expression.text === 'parentModifier'
15
+ ) {
16
+ const args = node.expression.arguments.map(arg => parseNodeToStaticValue(arg, context));
17
+ const hash = args[0].toString().replace('css-', 'm');
18
+
19
+ // add a mapping from `css-{hash}` to `{hash}` for extraction string replacement
20
+ names[args[0]] = hash;
21
+
22
+ // map the `{hash}` to the extracted CSS class name
23
+ extractedNames[hash] = extractedNames[args[0]];
24
+
25
+ return parentModifier(args[0].toString());
26
+ }
27
+
28
+ return;
29
+ });
@@ -0,0 +1,22 @@
1
+ import ts from 'typescript';
2
+
3
+ import {px2rem} from '@workday/canvas-kit-styling';
4
+ import {createPropertyTransform} from '../createPropertyTransform';
5
+ import {parseNodeToStaticValue} from './parseNodeToStaticValue';
6
+
7
+ export const handlePx2Rem = createPropertyTransform((node, context) => {
8
+ if (
9
+ ts.isCallExpression(node) &&
10
+ ts.isIdentifier(node.expression) &&
11
+ node.expression.text === 'px2rem'
12
+ ) {
13
+ const args = node.arguments.map(arg => parseNodeToStaticValue(arg, context));
14
+
15
+ return px2rem(
16
+ parseFloat(args[0] as string),
17
+ args[1] ? parseFloat(args[1] as string) : undefined
18
+ );
19
+ }
20
+
21
+ return;
22
+ });
@@ -0,0 +1,14 @@
1
+ import {TransformerContext} from './types';
2
+
3
+ export function injectStyles(
4
+ {styles, cache}: TransformerContext,
5
+ fileName: string,
6
+ hash: string,
7
+ styleOutput: string
8
+ ) {
9
+ if (!cache[hash]) {
10
+ styles[fileName] = styles[fileName] || [];
11
+ styles[fileName].push(styleOutput);
12
+ cache[hash] = styleOutput;
13
+ }
14
+ }
@@ -0,0 +1,21 @@
1
+ import ts from 'typescript';
2
+
3
+ /**
4
+ * Checks if the node was imported from '@workday/canvas-kit-styling'. This is useful if you want to
5
+ * limit transformation to only styling imports.
6
+ */
7
+ export function isImportedFromStyling(node: ts.Node, checker: ts.TypeChecker) {
8
+ const symbol = checker.getSymbolAtLocation(node);
9
+ const declaration = symbol?.valueDeclaration || symbol?.declarations?.[0];
10
+
11
+ if (
12
+ declaration &&
13
+ ts.isImportSpecifier(declaration) &&
14
+ ts.isStringLiteral(declaration.parent.parent.parent.moduleSpecifier) &&
15
+ declaration.parent.parent.parent.moduleSpecifier.text === '@workday/canvas-kit-styling'
16
+ ) {
17
+ return true;
18
+ }
19
+
20
+ return false;
21
+ }
@@ -0,0 +1,281 @@
1
+ import ts from 'typescript';
2
+
3
+ import {getErrorMessage} from './getErrorMessage';
4
+ import {TransformerContext} from './types';
5
+
6
+ function handlePropertyTransforms(node: ts.Node, context: TransformerContext): string | undefined {
7
+ return context.propertyTransforms.reduce((result, transformer) => {
8
+ return result || transformer(node, context) || undefined;
9
+ }, undefined as undefined | string);
10
+ }
11
+
12
+ /**
13
+ * This is the workhorse of statically analyzing style values
14
+ */
15
+ export function parseNodeToStaticValue(
16
+ node: ts.Node,
17
+ context: TransformerContext
18
+ ): string | number {
19
+ const {checker} = context;
20
+
21
+ const value = handlePropertyTransforms(node, context);
22
+ if (value) {
23
+ return value;
24
+ }
25
+
26
+ /**
27
+ * String literals like 'red' or empty Template Expressions like `red`
28
+ */
29
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
30
+ return node.text;
31
+ }
32
+
33
+ // 12
34
+ if (ts.isNumericLiteral(node)) {
35
+ return parseFloat(node.text);
36
+ }
37
+
38
+ // -12
39
+ if (
40
+ ts.isPrefixUnaryExpression(node) &&
41
+ node.operator === ts.SyntaxKind.MinusToken &&
42
+ ts.isNumericLiteral(node.operand)
43
+ ) {
44
+ return -parseFloat(node.operand.text);
45
+ }
46
+
47
+ // undefined
48
+ if (ts.isIdentifier(node) && node.text === 'undefined') {
49
+ return 'undefined';
50
+ }
51
+
52
+ // a.b
53
+ if (ts.isPropertyAccessExpression(node)) {
54
+ getPropertyAccessExpressionText(node);
55
+ const varName = getPropertyAccessExpressionText(node);
56
+
57
+ const value =
58
+ getValueFromProcessedNodes(varName, context) ||
59
+ getValueFromAliasedSymbol(node, varName, context);
60
+
61
+ if (value) {
62
+ return value;
63
+ }
64
+ }
65
+
66
+ if (ts.isComputedPropertyName(node) && ts.isIdentifier(node.expression)) {
67
+ const varName = node.expression.text;
68
+
69
+ const value =
70
+ getValueFromProcessedNodes(varName, context) ||
71
+ getValueFromAliasedSymbol(node, varName, context);
72
+
73
+ if (value) {
74
+ return value;
75
+ }
76
+ }
77
+
78
+ // [a.b]
79
+ if (ts.isComputedPropertyName(node) && ts.isPropertyAccessExpression(node.expression)) {
80
+ const varName = getPropertyAccessExpressionText(node.expression);
81
+
82
+ const value =
83
+ getValueFromProcessedNodes(varName, context) ||
84
+ getValueFromAliasedSymbol(node, varName, context);
85
+
86
+ if (value) {
87
+ return value;
88
+ }
89
+ }
90
+
91
+ // [`${a.b} &`]
92
+ if (ts.isComputedPropertyName(node) && ts.isTemplateExpression(node.expression)) {
93
+ return getStyleValueFromTemplateExpression(node.expression, context);
94
+ }
95
+
96
+ /**
97
+ * ```ts
98
+ * `border 1px ${myVars.colors.border}`
99
+ * ```
100
+ */
101
+ if (ts.isTemplateExpression(node)) {
102
+ return getStyleValueFromTemplateExpression(node, context);
103
+ }
104
+
105
+ /**
106
+ * An Identifier is a simple variable. It may represent a variable, so we'll check it before
107
+ * moving on. This typically happens in stencils.
108
+ */
109
+ if (ts.isIdentifier(node)) {
110
+ const value =
111
+ getValueFromProcessedNodes(node.text, context) ||
112
+ getValueFromAliasedSymbol(node, node.text, context);
113
+
114
+ if (value) {
115
+ return value;
116
+ }
117
+ }
118
+
119
+ if (ts.isElementAccessExpression(node)) {
120
+ const value = parseTypeToStaticValue(checker.getTypeAtLocation(node));
121
+
122
+ if (value) {
123
+ return value;
124
+ }
125
+ }
126
+
127
+ // If we got here, we cannot statically analyze by the AST alone. We have to check the type of the
128
+ // correct AST Node
129
+
130
+ if (ts.isIdentifier(node) || ts.isPropertyAccessExpression(node)) {
131
+ const value = parseTypeToStaticValue(checker.getTypeAtLocation(node));
132
+ if (value) {
133
+ return value;
134
+ }
135
+ }
136
+
137
+ if (ts.isComputedPropertyName(node)) {
138
+ const value = parseTypeToStaticValue(checker.getTypeAtLocation(node.expression));
139
+ if (value) {
140
+ return value;
141
+ }
142
+ }
143
+
144
+ // we don't know what this is, we need to throw an error
145
+ const type = checker.getTypeAtLocation(node);
146
+
147
+ const typeValue = checker.typeToString(type);
148
+
149
+ throw new Error(
150
+ `Unknown type at: "${node.getText()}". Received "${typeValue}"\n${getErrorMessage(
151
+ node,
152
+ context
153
+ )}\nFor static analysis of styles, please make sure all types resolve to string or numeric literals. Please use 'const' instead of 'let'. If using an object, cast using "as const" or use an interface with string or numeric literals.`
154
+ );
155
+ }
156
+
157
+ function parseTypeToStaticValue(type: ts.Type): string | number | void {
158
+ if (type.isStringLiteral()) {
159
+ return type.value;
160
+ }
161
+
162
+ if (type.isNumberLiteral()) {
163
+ return type.value;
164
+ }
165
+ }
166
+
167
+ /**
168
+ * A `PropertyExpression` is an expression with a dot in it. Like `a.b.c`. It may be nested. This
169
+ * function will walk the AST and create a string like `a.b.c` to be passed on to variable name
170
+ * generation. This will be used for CSS variable lookups.
171
+ */
172
+ function getPropertyAccessExpressionText(node: ts.PropertyAccessExpression): string {
173
+ if (ts.isIdentifier(node.name)) {
174
+ if (ts.isIdentifier(node.expression)) {
175
+ return `${node.expression.text}.${node.name.text}`;
176
+ }
177
+ if (ts.isPropertyAccessExpression(node.expression)) {
178
+ return `${getPropertyAccessExpressionText(node.expression)}.${node.name.text}`;
179
+ }
180
+ }
181
+ return '';
182
+ }
183
+
184
+ /**
185
+ * Gets a static string value from a template expression. It could recurse.
186
+ */
187
+ function getStyleValueFromTemplateExpression(
188
+ node: ts.Node | undefined,
189
+ context: TransformerContext
190
+ ): string {
191
+ if (!node) {
192
+ return '';
193
+ }
194
+ if (ts.isTemplateExpression(node)) {
195
+ return (
196
+ getStyleValueFromTemplateExpression(node.head, context) +
197
+ node.templateSpans.map(value => getStyleValueFromTemplateExpression(value, context)).join('')
198
+ );
199
+ }
200
+
201
+ if (ts.isTemplateHead(node) || ts.isTemplateTail(node) || ts.isTemplateMiddle(node)) {
202
+ return node.text;
203
+ }
204
+
205
+ if (ts.isTemplateSpan(node)) {
206
+ return (
207
+ parseNodeToStaticValue(node.expression, context) +
208
+ getStyleValueFromTemplateExpression(node.literal, context)
209
+ );
210
+ }
211
+
212
+ return '';
213
+ }
214
+
215
+ /**
216
+ * Get a value from an aliased symbol, if it exists. An aliased symbol comes from
217
+ */
218
+ export function getValueFromAliasedSymbol(
219
+ node: ts.Node,
220
+ varName: string,
221
+ context: TransformerContext
222
+ ): string | void {
223
+ const {checker, transform} = context;
224
+ let symbolNode: ts.Node | undefined;
225
+
226
+ if (ts.isIdentifier(node)) {
227
+ // base case is the node is an identifier
228
+ symbolNode = node;
229
+ }
230
+
231
+ if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name)) {
232
+ return getValueFromAliasedSymbol(node.expression, varName, context);
233
+ }
234
+
235
+ if (ts.isComputedPropertyName(node)) {
236
+ return getValueFromAliasedSymbol(node.expression, varName, context);
237
+ }
238
+
239
+ if (symbolNode) {
240
+ const symbol = checker.getSymbolAtLocation(symbolNode);
241
+ let declaration: ts.Declaration | undefined;
242
+
243
+ if (symbol?.valueDeclaration) {
244
+ // If the symbol has a value declaration, we'll use that declaration
245
+ declaration = symbol.valueDeclaration;
246
+ } else if (symbol && symbol.getFlags() & ts.SymbolFlags.Alias) {
247
+ // If the symbol does not have a value declaration, we'll check if there's a aliased symbol
248
+ // linking to the value declaration.
249
+ declaration = checker.getAliasedSymbol(symbol).valueDeclaration;
250
+ }
251
+ // If there is an aliased symbol and it is a variable declaration, try to resolve the
252
+ if (declaration && hasExpression(declaration)) {
253
+ if (declaration.initializer) {
254
+ // Update the `prefix` to the alias declaration's source file.
255
+ const aliasFileContext = {
256
+ ...context,
257
+ prefix: context.getPrefix(declaration.getSourceFile().fileName),
258
+ };
259
+ transform(declaration.initializer, aliasFileContext);
260
+
261
+ return getValueFromProcessedNodes(varName, aliasFileContext);
262
+ }
263
+ }
264
+ }
265
+ }
266
+
267
+ function getValueFromProcessedNodes(varName: string, context: TransformerContext): string | void {
268
+ const {names} = context;
269
+
270
+ if (context.nameScope && names[`${context.nameScope}${varName}`]) {
271
+ return names[`${context.nameScope}${varName}`];
272
+ }
273
+
274
+ if (names[varName]) {
275
+ return names[varName];
276
+ }
277
+ }
278
+
279
+ function hasExpression(node: ts.Node): node is ts.Node & {initializer: ts.Expression} {
280
+ return 'initializer' in node;
281
+ }
@@ -0,0 +1,201 @@
1
+ import ts from 'typescript';
2
+ import {getFallbackVariable} from './getFallbackVariable';
3
+
4
+ import {parseNodeToStaticValue} from './parseNodeToStaticValue';
5
+ import {NestedStyleObject, TransformerContext} from './types';
6
+
7
+ export function parseObjectToStaticValue(
8
+ node: ts.Node,
9
+ context: TransformerContext
10
+ ): NestedStyleObject {
11
+ let styleObj: NestedStyleObject = {};
12
+
13
+ if (ts.isObjectLiteralExpression(node)) {
14
+ node.properties.forEach(property => {
15
+ styleObj = {...styleObj, ...parsePropertyToStaticValue(property, context)};
16
+ });
17
+ }
18
+
19
+ return wrapStyleObj(styleObj, context);
20
+ }
21
+
22
+ /**
23
+ * Wrap all values and nested object values with a maybeWrapCSSVariables call
24
+ */
25
+ function wrapStyleObj(styleObj: NestedStyleObject, context: TransformerContext): NestedStyleObject {
26
+ for (const key in styleObj) {
27
+ if (styleObj.hasOwnProperty(key)) {
28
+ const value = styleObj[key];
29
+ if (typeof value === 'object') {
30
+ styleObj[key] = wrapStyleObj(value, context);
31
+ }
32
+ if (typeof value === 'string') {
33
+ styleObj[key] = maybeWrapCSSVariables(value, context.names);
34
+ }
35
+ }
36
+ }
37
+
38
+ return styleObj;
39
+ }
40
+
41
+ function handleObjectTransforms(
42
+ node: ts.Node,
43
+ context: TransformerContext
44
+ ): NestedStyleObject | undefined {
45
+ return context.objectTransforms.reduce((result, transformer) => {
46
+ return result || transformer(node, context) || undefined;
47
+ }, undefined as undefined | NestedStyleObject);
48
+ }
49
+
50
+ function parsePropertyToStaticValue(node: ts.Node, context: TransformerContext): NestedStyleObject {
51
+ const styleObj: NestedStyleObject = {};
52
+
53
+ // check to see if there's an object transform for this node
54
+ const obj = handleObjectTransforms(node, context);
55
+ if (obj) {
56
+ return obj;
57
+ }
58
+
59
+ // If there's a spread, we're expecting an object to be returned. We'll see if there's an object transform for this node
60
+ if (ts.isSpreadAssignment(node)) {
61
+ const obj = handleObjectTransforms(node.expression, context);
62
+
63
+ if (obj) {
64
+ return obj;
65
+ }
66
+ }
67
+
68
+ // {...{key: 'value'}}
69
+ if (ts.isSpreadAssignment(node) && ts.isObjectLiteralExpression(node.expression)) {
70
+ // recurse to parse a nested ObjectLiteralExpression
71
+ return parseObjectToStaticValue(node.expression, context);
72
+ }
73
+
74
+ // { name: value }
75
+ if (ts.isPropertyAssignment(node)) {
76
+ const key = ts.isIdentifier(node.name)
77
+ ? node.name.text
78
+ : parseNodeToStaticValue(node.name, context);
79
+ if (key) {
80
+ if (ts.isObjectLiteralExpression(node.initializer)) {
81
+ // nested
82
+ styleObj[key] = parseObjectToStaticValue(node.initializer, context);
83
+ } else {
84
+ styleObj[key] = parseNodeToStaticValue(node.initializer, context);
85
+ }
86
+
87
+ return styleObj;
88
+ }
89
+ }
90
+
91
+ // { name: value } (types)
92
+ if (ts.isPropertySignature(node)) {
93
+ const key = ts.isIdentifier(node.name)
94
+ ? node.name.text
95
+ : parseNodeToStaticValue(node.name, context).toString();
96
+ if (key) {
97
+ if (key.includes('&') || key.startsWith(':')) {
98
+ // nested
99
+ styleObj[key] = parseObjectToStaticValue(node.type!, context);
100
+ } else {
101
+ styleObj[key] = parseNodeToStaticValue(node.type!, context).toString() || '';
102
+ }
103
+
104
+ return styleObj;
105
+ }
106
+ }
107
+
108
+ // { name }
109
+ if (ts.isShorthandPropertyAssignment(node)) {
110
+ const key = node.name.text;
111
+
112
+ styleObj[key] = parseNodeToStaticValue(node.name, context).toString() || '';
113
+
114
+ return styleObj;
115
+ }
116
+
117
+ // { ...value }
118
+ if (ts.isSpreadAssignment(node)) {
119
+ // Spread assignments are a bit complicated to use the AST to figure out, so we'll ask the
120
+ // TypeScript type checker.
121
+ const type = context.checker.getTypeAtLocation(node.expression);
122
+ return parseStyleObjFromType(type, context);
123
+ }
124
+
125
+ return styleObj;
126
+ }
127
+
128
+ /**
129
+ * If we're here, we have a `ts.Type` that represents a style object. We try to parse a style object
130
+ * from the AST, but we might have something that is more complicated like a function call or an
131
+ * identifier that represents an object. It could be imported from another file.
132
+ */
133
+ export function parseStyleObjFromType(type: ts.Type, context: TransformerContext) {
134
+ const styleObj: Record<string, any> = {};
135
+
136
+ // Gets all the properties of the type object
137
+ return type.getProperties().reduce((result, property) => {
138
+ const declaration = property.valueDeclaration;
139
+
140
+ if (!declaration) {
141
+ return result;
142
+ }
143
+
144
+ // we might have generics, so we'll use the type of the symbol instead of the type at the
145
+ // declaration. This resolves generics like `T` into literal values if they exist.
146
+ const propType = context.checker.getTypeOfSymbolAtLocation(property, declaration);
147
+
148
+ if (propType.isStringLiteral()) {
149
+ // This isn't a component variable, it is a static CSS variable
150
+ result[property.name] = propType.value;
151
+ return result;
152
+ }
153
+
154
+ if (propType.isNumberLiteral()) {
155
+ result[property.name] = propType.value;
156
+ return result;
157
+ }
158
+
159
+ return {
160
+ ...result,
161
+ ...parsePropertyToStaticValue(declaration, context),
162
+ };
163
+ }, styleObj);
164
+ }
165
+
166
+ /**
167
+ * Wrap all unwrapped CSS Variables. For example, `{padding: '--foo'}` will be replaced with
168
+ * `{padding: 'var(--foo)'}`. It also works on variables in the middle of the property.
169
+ */
170
+ export function maybeWrapCSSVariables(
171
+ input: string | number,
172
+ names: Record<string, string>
173
+ ): string | number {
174
+ if (typeof input === 'number') {
175
+ return input;
176
+ }
177
+ // matches an string starting with `--` that isn't already wrapped in a `var()`. It tries to match
178
+ // any character that isn't a valid separator in CSS
179
+ return input.replace(
180
+ /([a-z]*[ (]*)(--[^\s;,'})]+)(\){0,1})/gi,
181
+ (match: string, prefix: string, variable: string, postfix: string) => {
182
+ // shortcut for var() wrappers that already have a fallback
183
+ if (prefix.startsWith('var(') && postfix !== ')') {
184
+ return match;
185
+ }
186
+
187
+ // find a possible fallback
188
+ const fallbackVariable = getFallbackVariable(variable, names);
189
+ const fallback = fallbackVariable
190
+ ? `, ${maybeWrapCSSVariables(fallbackVariable, names)}`
191
+ : '';
192
+
193
+ // if this a var wrapper without a fallback
194
+ if (prefix.startsWith('var(') && postfix === ')') {
195
+ return `${prefix}${variable}${fallback}${postfix}`;
196
+ }
197
+ // if this is not a var wrapper at all
198
+ return `${prefix}var(${variable}${fallback})${postfix}`;
199
+ }
200
+ );
201
+ }
@@ -0,0 +1,56 @@
1
+ /* eslint-disable no-param-reassign */
2
+ /* eslint-disable no-fallthrough */
3
+ /* eslint-disable default-case */
4
+ import {
5
+ COMMENT,
6
+ DECLARATION,
7
+ IMPORT,
8
+ KEYFRAMES,
9
+ LAYER,
10
+ Middleware,
11
+ RULESET,
12
+ serialize,
13
+ Element,
14
+ } from 'stylis';
15
+
16
+ function strlen(input: string): number {
17
+ return input.length;
18
+ }
19
+
20
+ export const prettyStringify: Middleware = (element, index, children, callback) => {
21
+ switch (element.type) {
22
+ case LAYER:
23
+ if (element.children.length) {
24
+ break;
25
+ }
26
+ case IMPORT:
27
+ case DECLARATION:
28
+ return (element.return =
29
+ element.return ||
30
+ ' ' + element.value.replace(':', ': ') + (index === children.length - 1 ? '' : '\n'));
31
+ case COMMENT:
32
+ return `${element.value}\n`;
33
+ case KEYFRAMES:
34
+ return (
35
+ (element.return =
36
+ element.value +
37
+ ' {\n' +
38
+ serialize(element.children as Element[], callback)
39
+ .split('\n')
40
+ .map(i => ` ${i}`)
41
+ .join('\n') +
42
+ '}').replace(/\s\s\}$/, '}') + '\n'
43
+ );
44
+ case RULESET:
45
+ if (!strlen((element.value = (element.props as string[]).join(', ')))) {
46
+ return '';
47
+ }
48
+ }
49
+
50
+ const childStr = serialize(element.children as Element[], callback);
51
+ if (childStr) {
52
+ element.return = `${element.value} {\n${childStr}\n}\n\n`;
53
+ return element.return;
54
+ }
55
+ return '';
56
+ };