@workday/canvas-kit-styling-transform 10.2.5 → 10.3.0-646-next.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 (111) hide show
  1. package/dist/commonjs/lib/styleTransform.d.ts +12 -2
  2. package/dist/commonjs/lib/styleTransform.d.ts.map +1 -1
  3. package/dist/commonjs/lib/styleTransform.js +53 -517
  4. package/dist/commonjs/lib/utils/createStyleObjectNode.d.ts +10 -0
  5. package/dist/commonjs/lib/utils/createStyleObjectNode.d.ts.map +1 -0
  6. package/dist/commonjs/lib/utils/createStyleObjectNode.js +31 -0
  7. package/dist/commonjs/lib/{getCssVariables.d.ts → utils/getCssVariables.d.ts} +0 -1
  8. package/dist/commonjs/lib/utils/getCssVariables.d.ts.map +1 -0
  9. package/dist/commonjs/lib/{getCssVariables.js → utils/getCssVariables.js} +1 -21
  10. package/dist/commonjs/lib/utils/getErrorMessage.d.ts +15 -0
  11. package/dist/commonjs/lib/utils/getErrorMessage.d.ts.map +1 -0
  12. package/dist/commonjs/lib/utils/getErrorMessage.js +45 -0
  13. package/dist/commonjs/lib/utils/getFallbackVariable.d.ts +9 -0
  14. package/dist/commonjs/lib/utils/getFallbackVariable.d.ts.map +1 -0
  15. package/dist/commonjs/lib/utils/getFallbackVariable.js +30 -0
  16. package/dist/commonjs/lib/utils/getVarName.d.ts +17 -0
  17. package/dist/commonjs/lib/utils/getVarName.d.ts.map +1 -0
  18. package/dist/commonjs/lib/utils/getVarName.js +33 -0
  19. package/dist/commonjs/lib/utils/handleCalc.d.ts +19 -0
  20. package/dist/commonjs/lib/utils/handleCalc.d.ts.map +1 -0
  21. package/dist/commonjs/lib/utils/handleCalc.js +62 -0
  22. package/dist/commonjs/lib/utils/handleCreateStencil.d.ts +6 -0
  23. package/dist/commonjs/lib/utils/handleCreateStencil.d.ts.map +1 -0
  24. package/dist/commonjs/lib/utils/handleCreateStencil.js +202 -0
  25. package/dist/commonjs/lib/utils/handleCreateStyles.d.ts +3 -0
  26. package/dist/commonjs/lib/utils/handleCreateStyles.d.ts.map +1 -0
  27. package/dist/commonjs/lib/utils/handleCreateStyles.js +109 -0
  28. package/dist/commonjs/lib/utils/handleCreateVars.d.ts +3 -0
  29. package/dist/commonjs/lib/utils/handleCreateVars.d.ts.map +1 -0
  30. package/dist/commonjs/lib/utils/handleCreateVars.js +34 -0
  31. package/dist/commonjs/lib/utils/handleCssVar.d.ts +12 -0
  32. package/dist/commonjs/lib/utils/handleCssVar.d.ts.map +1 -0
  33. package/dist/commonjs/lib/utils/handleCssVar.js +33 -0
  34. package/dist/commonjs/lib/utils/handleFocusRing.d.ts +3 -0
  35. package/dist/commonjs/lib/utils/handleFocusRing.d.ts.map +1 -0
  36. package/dist/commonjs/lib/utils/handleFocusRing.js +83 -0
  37. package/dist/commonjs/lib/utils/handlePx2Rem.d.ts +6 -0
  38. package/dist/commonjs/lib/utils/handlePx2Rem.d.ts.map +1 -0
  39. package/dist/commonjs/lib/utils/handlePx2Rem.js +26 -0
  40. package/dist/commonjs/lib/utils/isImportedFromStyling.d.ts +7 -0
  41. package/dist/commonjs/lib/utils/isImportedFromStyling.d.ts.map +1 -0
  42. package/dist/commonjs/lib/utils/isImportedFromStyling.js +23 -0
  43. package/dist/commonjs/lib/utils/makeEmotionSafe.d.ts +7 -0
  44. package/dist/commonjs/lib/utils/makeEmotionSafe.d.ts.map +1 -0
  45. package/dist/commonjs/lib/utils/makeEmotionSafe.js +15 -0
  46. package/dist/commonjs/lib/utils/parseNodeToStaticValue.d.ts +6 -0
  47. package/dist/commonjs/lib/utils/parseNodeToStaticValue.d.ts.map +1 -0
  48. package/dist/commonjs/lib/utils/parseNodeToStaticValue.js +135 -0
  49. package/dist/commonjs/lib/utils/parseObjectToStaticValue.d.ts +12 -0
  50. package/dist/commonjs/lib/utils/parseObjectToStaticValue.d.ts.map +1 -0
  51. package/dist/commonjs/lib/utils/parseObjectToStaticValue.js +117 -0
  52. package/dist/commonjs/lib/utils/types.d.ts +10 -0
  53. package/dist/commonjs/lib/utils/types.d.ts.map +1 -0
  54. package/dist/commonjs/lib/utils/types.js +2 -0
  55. package/dist/es6/lib/styleTransform.d.ts +12 -2
  56. package/dist/es6/lib/styleTransform.d.ts.map +1 -1
  57. package/dist/es6/lib/styleTransform.js +51 -516
  58. package/dist/es6/lib/utils/createStyleObjectNode.d.ts +10 -0
  59. package/dist/es6/lib/utils/createStyleObjectNode.d.ts.map +1 -0
  60. package/dist/es6/lib/utils/createStyleObjectNode.js +24 -0
  61. package/dist/es6/lib/{getCssVariables.d.ts → utils/getCssVariables.d.ts} +0 -1
  62. package/dist/es6/lib/utils/getCssVariables.d.ts.map +1 -0
  63. package/dist/es6/lib/{getCssVariables.js → utils/getCssVariables.js} +0 -19
  64. package/dist/es6/lib/utils/getErrorMessage.d.ts +15 -0
  65. package/dist/es6/lib/utils/getErrorMessage.d.ts.map +1 -0
  66. package/dist/es6/lib/utils/getErrorMessage.js +41 -0
  67. package/dist/es6/lib/utils/getFallbackVariable.d.ts +9 -0
  68. package/dist/es6/lib/utils/getFallbackVariable.d.ts.map +1 -0
  69. package/dist/es6/lib/utils/getFallbackVariable.js +26 -0
  70. package/dist/es6/lib/utils/getVarName.d.ts +17 -0
  71. package/dist/es6/lib/utils/getVarName.d.ts.map +1 -0
  72. package/dist/es6/lib/utils/getVarName.js +26 -0
  73. package/dist/es6/lib/utils/handleCalc.d.ts +19 -0
  74. package/dist/es6/lib/utils/handleCalc.d.ts.map +1 -0
  75. package/dist/es6/lib/utils/handleCalc.js +55 -0
  76. package/dist/es6/lib/utils/handleCreateStencil.d.ts +6 -0
  77. package/dist/es6/lib/utils/handleCreateStencil.d.ts.map +1 -0
  78. package/dist/es6/lib/utils/handleCreateStencil.js +195 -0
  79. package/dist/es6/lib/utils/handleCreateStyles.d.ts +3 -0
  80. package/dist/es6/lib/utils/handleCreateStyles.d.ts.map +1 -0
  81. package/dist/es6/lib/utils/handleCreateStyles.js +102 -0
  82. package/dist/es6/lib/utils/handleCreateVars.d.ts +3 -0
  83. package/dist/es6/lib/utils/handleCreateVars.d.ts.map +1 -0
  84. package/dist/es6/lib/utils/handleCreateVars.js +27 -0
  85. package/dist/es6/lib/utils/handleCssVar.d.ts +12 -0
  86. package/dist/es6/lib/utils/handleCssVar.d.ts.map +1 -0
  87. package/dist/es6/lib/utils/handleCssVar.js +26 -0
  88. package/dist/es6/lib/utils/handleFocusRing.d.ts +3 -0
  89. package/dist/es6/lib/utils/handleFocusRing.d.ts.map +1 -0
  90. package/dist/es6/lib/utils/handleFocusRing.js +76 -0
  91. package/dist/es6/lib/utils/handlePx2Rem.d.ts +6 -0
  92. package/dist/es6/lib/utils/handlePx2Rem.d.ts.map +1 -0
  93. package/dist/es6/lib/utils/handlePx2Rem.js +19 -0
  94. package/dist/es6/lib/utils/isImportedFromStyling.d.ts +7 -0
  95. package/dist/es6/lib/utils/isImportedFromStyling.d.ts.map +1 -0
  96. package/dist/es6/lib/utils/isImportedFromStyling.js +16 -0
  97. package/dist/es6/lib/utils/makeEmotionSafe.d.ts +7 -0
  98. package/dist/es6/lib/utils/makeEmotionSafe.d.ts.map +1 -0
  99. package/dist/es6/lib/utils/makeEmotionSafe.js +11 -0
  100. package/dist/es6/lib/utils/parseNodeToStaticValue.d.ts +6 -0
  101. package/dist/es6/lib/utils/parseNodeToStaticValue.d.ts.map +1 -0
  102. package/dist/es6/lib/utils/parseNodeToStaticValue.js +128 -0
  103. package/dist/es6/lib/utils/parseObjectToStaticValue.d.ts +12 -0
  104. package/dist/es6/lib/utils/parseObjectToStaticValue.d.ts.map +1 -0
  105. package/dist/es6/lib/utils/parseObjectToStaticValue.js +109 -0
  106. package/dist/es6/lib/utils/types.d.ts +10 -0
  107. package/dist/es6/lib/utils/types.d.ts.map +1 -0
  108. package/dist/es6/lib/utils/types.js +1 -0
  109. package/package.json +6 -3
  110. package/dist/commonjs/lib/getCssVariables.d.ts.map +0 -1
  111. package/dist/es6/lib/getCssVariables.d.ts.map +0 -1
@@ -1,4 +1,5 @@
1
1
  import ts from 'typescript';
2
+ import { NodeTransformer } from './utils/types';
2
3
  export declare type NestedStyleObject = {
3
4
  [key: string]: string | NestedStyleObject;
4
5
  };
@@ -6,7 +7,16 @@ export interface StyleTransformerOptions {
6
7
  prefix: string;
7
8
  variables: Record<string, string>;
8
9
  fallbackFiles?: string[];
10
+ transformers?: NodeTransformer[];
9
11
  }
10
- export default function styleTransformer(program: ts.Program, { prefix, variables, fallbackFiles }?: Partial<StyleTransformerOptions>): ts.TransformerFactory<ts.SourceFile>;
11
- export declare function transform(program: ts.Program, fileName: string, options?: Partial<StyleTransformerOptions>): string;
12
+ /**
13
+ * The reset is used in tests and should not be called normally.
14
+ */
15
+ export declare function _reset(): void;
16
+ export default function styleTransformer(program: ts.Program, { prefix, variables, fallbackFiles, transformers, }?: Partial<StyleTransformerOptions>): ts.TransformerFactory<ts.SourceFile>;
17
+ /**
18
+ * This function is useful for tests or a custom build. The `styleTransformer` function is used by
19
+ * the https://www.npmjs.com/package/ttypescript package.
20
+ */
21
+ export declare function transform(program: ts.Program, fileName: string, options?: Partial<StyleTransformerOptions>, transformers?: NodeTransformer[]): string;
12
22
  //# sourceMappingURL=styleTransform.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"styleTransform.d.ts","sourceRoot":"","sources":["../../../lib/styleTransform.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,YAAY,CAAC;AAe5B,oBAAY,iBAAiB,GAAG;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAAA;CAAC,CAAC;AA+Z5E,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,EAAC,MAAc,EAAE,SAAc,EAAE,aAAa,EAAC,GAAE,OAAO,CAAC,uBAAuB,CAG/E,GACA,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,UAAU,CAAC,CAgLtC;AAGD,wBAAgB,SAAS,CACvB,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,UAY3C"}
1
+ {"version":3,"file":"styleTransform.d.ts","sourceRoot":"","sources":["../../../lib/styleTransform.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,YAAY,CAAC;AAW5B,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAE9C,oBAAY,iBAAiB,GAAG;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAAA;CAAC,CAAC;AAE5E,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;CAClC;AAKD;;GAEG;AACH,wBAAgB,MAAM,SAGrB;AAeD,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,EACE,MAAc,EACd,SAAc,EACd,aAAkB,EAClB,YAAkC,GACnC,GAAE,OAAO,CAAC,uBAAuB,CAIjC,GACA,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,UAAU,CAAC,CAgCtC;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,EAC1C,YAAY,CAAC,EAAE,eAAe,EAAE,UAYjC"}
@@ -3,554 +3,90 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.transform = void 0;
6
+ exports.transform = exports._reset = void 0;
7
7
  /// <reference types="node" />
8
8
  const typescript_1 = __importDefault(require("typescript"));
9
- const serialize_1 = require("@emotion/serialize");
10
- const canvas_tokens_web_1 = require("@workday/canvas-tokens-web");
11
9
  const node_path_1 = __importDefault(require("node:path"));
12
- const canvas_kit_styling_1 = require("@workday/canvas-kit-styling");
13
- const getCssVariables_1 = require("./getCssVariables");
14
- const styleExpressionName = 'createStyles';
15
- const cssVarExpressionName = 'cssVar';
16
- const createVarExpressionName = 'createVars';
17
- const styleImportString = '@workday/canvas-kit-styling';
18
- const vars = {};
19
- function getStyleValueFromType(node, type, checker) {
20
- const value = getCSSValueAtLocation(node, checker, type);
21
- if (value) {
22
- if (value.startsWith('--')) {
23
- return `var(${value})`;
24
- }
25
- return value;
26
- }
27
- const typeValue = checker.typeToString(type);
28
- throw new Error(`Unknown type at: "${node.getText()}". Received "${typeValue}"\n${getErrorMessage(node)}\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.`);
29
- }
30
- /**
31
- * Util function to fix an issue with Emotion by
32
- * appending `EmotionIssue#3066` to end of css variable
33
- * See issue: [#3066](https://github.com/emotion-js/emotion/issues/3066)
34
- */
35
- const makeEmotionSafe = (key) => {
36
- if (key.endsWith('label')) {
37
- return `${key}-emotion-safe`;
38
- }
39
- return key;
40
- };
41
- /**
42
- * A `PropertyExpression` is an expression with a dot in it. Like `a.b.c`. It may be nested. This
43
- * function will walk the AST and create a string like `a.b.c` to be passed on to variable name
44
- * generation. This will be used for CSS variable lookups.
45
- */
46
- function getPropertyAccessExpressionText(node) {
47
- if (typescript_1.default.isIdentifier(node.name)) {
48
- if (typescript_1.default.isIdentifier(node.expression)) {
49
- return `${node.expression.text}.${node.name.text}`;
50
- }
51
- if (typescript_1.default.isPropertyAccessExpression(node.expression)) {
52
- return `${getPropertyAccessExpressionText(node.expression)}.${node.name.text}`;
53
- }
54
- }
55
- return '';
56
- }
57
- function parseStyleObjValue(initializer, variables, checker) {
58
- /**
59
- * String literals like 'red' or empty Template Expressions like `red`
60
- */
61
- if (typescript_1.default.isStringLiteral(initializer) || typescript_1.default.isNoSubstitutionTemplateLiteral(initializer)) {
62
- return initializer.text;
63
- }
64
- // numeric literal values like `12`
65
- if (typescript_1.default.isNumericLiteral(initializer)) {
66
- return `${initializer.text}px`;
67
- }
68
- // The source file is using an identifier which will be known at runtime, we'll try to
69
- // determine the type
70
- if (typescript_1.default.isIdentifier(initializer)) {
71
- const type = checker.getTypeAtLocation(initializer);
72
- return getStyleValueFromType(initializer, type, checker);
73
- }
74
- /**
75
- * ```ts
76
- * PropertyAccessExpressions are dot-notation
77
- *
78
- * foo.bar.baz
79
- * ```
80
- */
81
- if (typescript_1.default.isPropertyAccessExpression(initializer)) {
82
- const type = checker.getTypeAtLocation(initializer);
83
- return getStyleValueFromType(initializer, type, checker);
84
- }
85
- /**
86
- * This will find patterns like:
87
- *
88
- * ```ts
89
- * cssVar(myVars.color);
90
- * cssVar(myVars.colors.background);
91
- * cssVar(myVars.colors.background, 'red')
92
- * ```
93
- */
94
- if (typescript_1.default.isCallExpression(initializer) &&
95
- typescript_1.default.isIdentifier(initializer.expression) &&
96
- initializer.expression.text === cssVarExpressionName) {
97
- const value = getCSSValueAtLocation(initializer.arguments[0], checker);
98
- const value2 = initializer.arguments[1]
99
- ? parseStyleObjValue(initializer.arguments[1], variables, checker)
100
- : undefined;
101
- // handle fallback variables
102
- const fallbackValue = getCssVariables_1.getFallbackVariable(value, variables);
103
- if (value && (value2 || fallbackValue)) {
104
- return `var(${value}, ${((value2 === null || value2 === void 0 ? void 0 : value2.startsWith('--')) ? `var(${value2})` : value2) || fallbackValue})`;
105
- }
106
- if (value) {
107
- return `var(${value})`;
108
- }
109
- }
110
- /**
111
- * ```ts
112
- * `border 1px ${myVars.colors.border}`
113
- * ```
114
- */
115
- if (typescript_1.default.isTemplateExpression(initializer)) {
116
- return getStyleValueFromTemplateExpression(initializer, variables, checker);
117
- }
118
- return '';
119
- }
120
- /**
121
- * Gets a static string value from a template expression. It could recurse.
122
- */
123
- function getStyleValueFromTemplateExpression(node, variables, checker) {
124
- if (!node) {
125
- return '';
126
- }
127
- if (typescript_1.default.isTemplateExpression(node)) {
128
- return (getStyleValueFromTemplateExpression(node.head, variables, checker) +
129
- node.templateSpans
130
- .map(value => getStyleValueFromTemplateExpression(value, variables, checker))
131
- .join(''));
132
- }
133
- if (typescript_1.default.isTemplateHead(node) || typescript_1.default.isTemplateTail(node) || typescript_1.default.isTemplateMiddle(node)) {
134
- return node.text;
135
- }
136
- if (typescript_1.default.isTemplateSpan(node)) {
137
- return (parseStyleObjValue(node.expression, variables, checker) +
138
- getStyleValueFromTemplateExpression(node.literal, variables, checker));
139
- }
140
- return '';
141
- }
142
- /**
143
- * Gets a CSS value from an AST node
144
- */
145
- function getCSSValueAtLocation(node, checker,
146
- /**
147
- * Optional type. This works for cases where the node is a TypeNode or TypeScript infers the Type
148
- * via a generic resolution. For example:
149
- * ```ts
150
- * function someFn<T extends string>(input: T): {fontSize: T} {
151
- * return { fontSize: input }
152
- * }
153
- *
154
- * // in styles
155
- * ...someFn('12px')
156
- * ```
157
- *
158
- * If we don't pass a type of the property given by `type.getProperties()`, TypeScript will
159
- * resolve the type at the value node as `T` instead of `12px`. Allowing for a type override is
160
- * useful when the caller may have more context about the type at a given node than we do.
161
- */
162
- type = checker.getTypeAtLocation(node)) {
163
- const varsKey = getVarsKeyFromNode(node);
164
- if (vars[varsKey]) {
165
- return vars[varsKey];
166
- }
167
- if (type.isStringLiteral()) {
168
- // This isn't a component variable, it is a static CSS variable
169
- return type.value;
170
- }
171
- if (type.isNumberLiteral()) {
172
- return `${type.value}px`;
173
- }
174
- if (node && typescript_1.default.isPropertyAccessExpression(node)) {
175
- return getPropertyAccessExpressionText(node);
176
- }
177
- return '';
178
- }
179
- function getModuleSpecifierFromDeclaration(node) {
180
- if (!node) {
181
- return undefined;
182
- }
183
- if (typescript_1.default.isImportSpecifier(node) && typescript_1.default.isStringLiteral(node.parent.parent.parent.moduleSpecifier)) {
184
- return node.parent.parent.parent.moduleSpecifier.text;
185
- }
186
- return undefined;
187
- }
188
- function getStyleFromProperty(property, prefix, variables, checker) {
189
- if (typescript_1.default.isPropertyAssignment(property)) {
190
- // All properties should be non-objects
191
- // {foo: 'bar'}
192
- if (typescript_1.default.isIdentifier(property.name)) {
193
- const value = parseStyleObjValue(property.initializer, variables, checker);
194
- if (value) {
195
- return { [property.name.text]: value };
196
- }
197
- }
198
- if (typescript_1.default.isComputedPropertyName(property.name)) {
199
- if (typescript_1.default.isPropertyAccessExpression(property.name.expression)) {
200
- const value = parseStyleObjValue(property.initializer, variables, checker);
201
- if (value) {
202
- // test if the property is a static value
203
- getPropertyAccessExpressionText(property.name.expression);
204
- const type = checker.getTypeAtLocation(property.name.expression);
205
- checker.typeToString(type);
206
- if (type.isStringLiteral()) {
207
- return { [type.value]: value };
208
- }
209
- else {
210
- const expressionText = getPropertyAccessExpressionText(property.name.expression);
211
- const [id, name] = getVariableNameParts(expressionText);
212
- return { [`--${prefix}-${canvas_kit_styling_1.slugify(id)}-${makeEmotionSafe(name)}`]: value };
213
- }
214
- }
215
- }
216
- }
217
- // String literal property names are special selectors with more styles
218
- // {'&:hover': {}}
219
- if (typescript_1.default.isStringLiteral(property.name)) {
220
- return {
221
- [property.name.text]: parseStyleObjFromNode(property.initializer, prefix, variables, checker),
222
- };
223
- }
224
- }
225
- /**
226
- * A spread assignment looks like:
227
- *
228
- * ```ts
229
- * {
230
- * ...styles
231
- * }
232
- * ```
233
- *
234
- * https://ts-ast-viewer.com/#code/MYewdgzgLgBFCmBbADjAvDA3gMxCAXDAOQBGAhgE5EC+AUKJLAigEzpYB0Xzy1QA
235
- */
236
- if (typescript_1.default.isSpreadAssignment(property)) {
237
- // Detect `focusRing` calls. This is temporary until we figure out a better way to do focus
238
- // rings that doesn't require a special entry in the transform function.
239
- //
240
- // TODO: implement a fully working type resolver for CSS variables or remove support for them an
241
- // remove all uses of `focusRing` from new styling code
242
- if (typescript_1.default.isCallExpression(property.expression) &&
243
- typescript_1.default.isIdentifier(property.expression.expression) &&
244
- property.expression.expression.text === 'focusRing') {
245
- const argumentObject = property.expression.arguments[0];
246
- // defaults
247
- const defaults = {
248
- width: '2px',
249
- separation: '0px',
250
- inset: undefined,
251
- innerColor: `var(${canvas_tokens_web_1.base.frenchVanilla100}, rgba(255,255,255,1))`,
252
- outerColor: `var(${canvas_tokens_web_1.brand.common.focusOutline}, rgba(8,117,225,1))`,
253
- };
254
- if (argumentObject && typescript_1.default.isObjectLiteralExpression(argumentObject)) {
255
- argumentObject.properties.forEach(property => {
256
- if (typescript_1.default.isPropertyAssignment(property) && typescript_1.default.isIdentifier(property.name)) {
257
- defaults[property.name.text] = parseStyleObjValue(property.initializer, variables, checker);
258
- }
259
- });
260
- let boxShadow;
261
- switch (defaults.inset) {
262
- case 'outer':
263
- boxShadow = `inset 0 0 0 ${defaults.separation} ${defaults.outerColor}, inset 0 0 0 calc(${defaults.width} + ${defaults.separation}) ${defaults.innerColor}`;
264
- break;
265
- case 'inner':
266
- boxShadow = `inset 0 0 0 ${defaults.separation} ${defaults.innerColor}, 0 0 0 ${defaults.width} ${defaults.outerColor}`;
267
- break;
268
- default:
269
- boxShadow = `0 0 0 ${defaults.separation} ${defaults.innerColor}, 0 0 0 calc(${defaults.width} + ${defaults.separation}) ${defaults.outerColor}`;
270
- break;
271
- }
272
- return { boxShadow };
273
- }
274
- }
275
- // Spread assignments are a bit complicated to use the AST to figure out, so we'll ask the
276
- // TypeScript type checker.
277
- const type = checker.getTypeAtLocation(property.expression);
278
- checker.typeToString(type); //?
279
- return parseStyleObjFromType(type, prefix, variables, checker);
280
- }
281
- return {};
282
- }
10
+ const getCssVariables_1 = require("./utils/getCssVariables");
11
+ const handleCreateVars_1 = require("./utils/handleCreateVars");
12
+ const handleCreateStyles_1 = require("./utils/handleCreateStyles");
13
+ const handleCreateStencil_1 = require("./utils/handleCreateStencil");
14
+ const handleCalc_1 = require("./utils/handleCalc");
15
+ const handlePx2Rem_1 = require("./utils/handlePx2Rem");
16
+ const handleFocusRing_1 = require("./utils/handleFocusRing");
17
+ const handleCssVar_1 = require("./utils/handleCssVar");
18
+ let vars = {};
19
+ let loadedFallbacks = false;
283
20
  /**
284
- * If we're here, we have a `ts.Type` that represents a style object. We try to parse a style object
285
- * from the AST, but we might have something that is more complicated like a function call or an
286
- * identifier that represents an object. It could be imported from another file.
21
+ * The reset is used in tests and should not be called normally.
287
22
  */
288
- function parseStyleObjFromType(type, prefix, variables, checker) {
289
- const styleObj = {};
290
- // Gets all the properties of the type object
291
- return type.getProperties().reduce((result, property) => {
292
- const declaration = property.declarations[0];
293
- if (declaration) {
294
- const propType = checker.getTypeOfSymbolAtLocation(property, declaration);
295
- return {
296
- ...result,
297
- [property.name]: getStyleValueFromType(declaration, propType, checker),
298
- };
299
- }
300
- return result;
301
- }, styleObj);
302
- }
303
- /**
304
- * If the node is an `ObjectLiteralExpression`, we'll walk the `properties` of the AST node and
305
- * create a style object for each property we find.
306
- */
307
- function parseStyleObjFromNode(node, prefix, variables, checker) {
308
- const styleObj = {};
309
- if (typescript_1.default.isObjectLiteralExpression(node)) {
310
- return node.properties.reduce((result, property) => {
311
- return { ...result, ...getStyleFromProperty(property, prefix, variables, checker) };
312
- }, styleObj);
313
- }
314
- return styleObj;
23
+ function _reset() {
24
+ vars = {};
25
+ loadedFallbacks = false;
315
26
  }
27
+ exports._reset = _reset;
316
28
  /**
317
- * Creates an AST node representation of the passed in `styleObj`, but in the format of `{name:
318
- * string, styles: serializedStyles}`. The `name` is hard-coded here to work with both server-side
319
- * and client-side style injection. This results in a stable style key for Emotion while also
320
- * optimizing style serialization.
29
+ * Optional list of transformers. Useful to override for tests
321
30
  */
322
- function createStyleObjectNode(styleObj) {
323
- const serialized = serialize_1.serializeStyles([styleObj]);
324
- const styleText = serialized.styles;
325
- const styleExpression = typescript_1.default.factory.createStringLiteral(styleText);
326
- // create an emotion-optimized object: https://github.com/emotion-js/emotion/blob/f3b268f7c52103979402da919c9c0dd3f9e0e189/packages/serialize/src/index.js#L315-L322
327
- // Looks like: `{name: $hash, styles: $styleText }`
328
- return typescript_1.default.factory.createObjectLiteralExpression([
329
- typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier('name'),
330
- // TODO - we may need this to be a static variable for the CSS package
331
- typescript_1.default.factory.createStringLiteral(canvas_kit_styling_1.generateUniqueId()) // We might be using values that are resolved at runtime, but should still be static. We're only supporting the `cs` function running once per file, so a stable id based on a hash is not necessary
332
- ),
333
- typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier('styles'), styleExpression // In the future we can extract CSS from here by running the `stylis` compiler directly. Emotion does this here: https://github.com/emotion-js/emotion/blob/f3b268f7c52103979402da919c9c0dd3f9e0e189/packages/cache/src/index.js#L188-L245
334
- ),
335
- ], false);
336
- }
337
- function styleTransformer(program, { prefix = 'css', variables = {}, fallbackFiles } = {
31
+ const defaultTransformers = [
32
+ handleCssVar_1.handleCssVar,
33
+ handleFocusRing_1.handleFocusRing,
34
+ handleCalc_1.handleCalc,
35
+ handlePx2Rem_1.handlePx2Rem,
36
+ handleCreateVars_1.handleCreateVars,
37
+ handleCreateStyles_1.handleCreateStyles,
38
+ handleCreateStencil_1.handleCreateStencil,
39
+ ];
40
+ function styleTransformer(program, { prefix = 'css', variables = {}, fallbackFiles = [], transformers = defaultTransformers, } = {
338
41
  prefix: 'css',
339
42
  variables: {},
43
+ transformers: defaultTransformers,
340
44
  }) {
341
- if (fallbackFiles) {
45
+ if (!loadedFallbacks) {
342
46
  const files = fallbackFiles
343
47
  .filter(file => file) // don't process empty files
344
48
  .map(file => {
345
49
  // Find the fully-qualified path name. This could error which should give "module not found" errors
346
50
  return file.startsWith('.') ? node_path_1.default.resolve(process.cwd(), file) : require.resolve(file);
347
51
  })
348
- .map(file => typescript_1.default.sys.readFile(file) || '');
52
+ .map(file => {
53
+ console.log(`Loading CSS variable fallback file: ${file}`);
54
+ return typescript_1.default.sys.readFile(file) || '';
55
+ });
56
+ const fallbackVars = getCssVariables_1.getVariablesFromFiles(files);
57
+ console.log(`Found ${Object.keys(fallbackVars).length} variables.`);
349
58
  // eslint-disable-next-line no-param-reassign
350
- variables = getCssVariables_1.getVariablesFromFiles(files);
59
+ vars = { ...variables, ...fallbackVars };
60
+ loadedFallbacks = true;
351
61
  }
352
62
  const checker = program.getTypeChecker();
353
63
  return context => {
354
64
  const visit = node => {
355
65
  // eslint-disable-next-line no-param-reassign
356
66
  node = typescript_1.default.visitEachChild(node, visit, context);
357
- /**
358
- * Check if the node is a call expression that looks like:
359
- *
360
- * ```ts
361
- * createStyles({
362
- * // properties
363
- * })
364
- * ```
365
- *
366
- * It will also make sure the `createStyles` function was imported from
367
- * `@workday/canvas-kit-styling` to ensure we don't rewrite the AST of code we don't own.
368
- *
369
- * This transformation will pre-serialize the style objects and turn them into strings for
370
- * faster runtime processing in Emotion. The following is an example of the transformation.
371
- *
372
- * ```ts
373
- * // before transformation
374
- * const myStyles = createStyles({
375
- * fontSize: '1rem'
376
- * })
377
- *
378
- * // after transformation
379
- * const myStyles = createStyles({
380
- * name: 'abc123',
381
- * styles: 'font-size: 1rem;'
382
- * })
383
- * ```
384
- *
385
- * The after transformation already serialized the styles and goes through a shortcut process
386
- * in `@emotion/css` where only the Emotion cache is checked and styles are inserted if the
387
- * cache key wasn't found.
388
- */
389
- if (typescript_1.default.isCallExpression(node) &&
390
- typescript_1.default.isIdentifier(node.expression) &&
391
- node.expression.text === styleExpressionName &&
392
- node.arguments.length > 0) {
393
- // get the declaration of the symbol of the styleExpression
394
- const symbol = checker.getSymbolAtLocation(node.expression);
395
- const declaration = symbol === null || symbol === void 0 ? void 0 : symbol.declarations[0];
396
- if (getModuleSpecifierFromDeclaration(declaration) === styleImportString) {
397
- const newArguments = [...node.arguments].map(arg => {
398
- // An `ObjectLiteralExpression` is an object like `{foo:'bar'}`:
399
- // https://ts-ast-viewer.com/#code/MYewdgzgLgBFCmBbADjAvDA3gKBjAZiCAFwwDkARgIYBOZ2AvkA
400
- if (typescript_1.default.isObjectLiteralExpression(arg)) {
401
- const styleObj = parseStyleObjFromNode(arg, prefix, variables, checker);
402
- return createStyleObjectNode(styleObj);
403
- }
404
- // An Identifier is a variable. It could come from anywhere - imports, earlier
405
- // assignments, etc. The easiest thing to do is to ask the TypeScript type checker what
406
- // the type representation is and go from there.
407
- if (typescript_1.default.isIdentifier(arg)) {
408
- const type = checker.getTypeAtLocation(arg);
409
- // `createStyles` accepts strings as class names. If the class name is
410
- if (type.isStringLiteral() || type.getFlags() & typescript_1.default.TypeFlags.String) {
411
- return arg;
412
- }
413
- // The type must be a object
414
- const styleObj = parseStyleObjFromType(type, prefix, variables, checker);
415
- return createStyleObjectNode(styleObj);
416
- }
417
- return arg;
418
- });
419
- newArguments.forEach(argument => {
420
- // TypeScript isn't expecting us to mutate arguments arguments and when emitting will
421
- // try to do something where it checks the `parent` node of the argument. Using
422
- // `ts.factory.create*`, the `parent` is `undefined` and this check will throw an error.
423
- // In order to get past this error, we manually update the `parent` node of each
424
- // argument to reference the existing call expression. This allows TypeScript to fully
425
- // type check and/or emit.
426
- argument.parent = node;
427
- });
428
- /**
429
- * We're not supposed to mutate arguments since it is supposed to be read-only. But, if I
430
- * return a new callExpression, there is no parent and it is no longer linked to the
431
- * import module. This causes incorrect code when the module export type is `commonjs`.
432
- * For example:
433
- *
434
- * ```ts
435
- * // with new callExpression
436
- * const canvas_kit_styling_1 = require(...)
437
- *
438
- * createStyles({...})
439
- *
440
- * // if we instead mutate arguments
441
- * const canvas_kit_styling_1 = require(...)
442
- *
443
- * canvas_kit_styling_1.createStyles({...})
444
- * ```
445
- *
446
- * My best guess as to why it fails when creating a new callExpression is the node's
447
- * symbol declaration link gets lost. TypeScript then has no idea `createStyles` comes
448
- * from an `ImportDeclaration` declaration node and when emitting `commonjs`, it doesn't
449
- * prefix with the `canvas_kit_styling_1`. This is hacky, but the only thing that works
450
- * correctly.
451
- */
452
- node.arguments = newArguments;
453
- return node;
454
- }
455
- }
456
- /**
457
- * This will create a variable
458
- */
459
- if (typescript_1.default.isCallExpression(node) &&
460
- typescript_1.default.isIdentifier(node.expression) &&
461
- node.expression.text === createVarExpressionName) {
462
- const id = canvas_kit_styling_1.slugify(getVarName(node));
463
- const variables = node.arguments
464
- .map(arg => typescript_1.default.isStringLiteral(arg) && arg.text)
465
- .filter(Boolean);
466
- variables.forEach(v => {
467
- vars[`${id}-${makeEmotionSafe(v)}`] = `--${prefix}-${id}-${makeEmotionSafe(v)}`;
468
- });
469
- return typescript_1.default.factory.createCallExpression(node.expression, [], [
470
- typescript_1.default.factory.createObjectLiteralExpression([
471
- typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier('id'), typescript_1.default.factory.createStringLiteral(`${prefix}-${id}`)),
472
- typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier('args'), typescript_1.default.factory.createArrayLiteralExpression(variables.map(val => typescript_1.default.factory.createStringLiteral(val)), false)),
473
- ], false),
474
- ]);
475
- }
476
- return node;
67
+ return handleTransformers(node, checker, prefix, vars)(transformers);
477
68
  };
478
69
  return node => typescript_1.default.visitNode(node, visit);
479
70
  };
480
71
  }
481
72
  exports.default = styleTransformer;
482
- // This should only be used for tests
483
- function transform(program, fileName, options) {
73
+ /**
74
+ * This function is useful for tests or a custom build. The `styleTransformer` function is used by
75
+ * the https://www.npmjs.com/package/ttypescript package.
76
+ */
77
+ function transform(program, fileName, options, transformers) {
484
78
  const source = program.getSourceFile(fileName) || typescript_1.default.createSourceFile(fileName, '', typescript_1.default.ScriptTarget.ES2019);
485
79
  const printer = typescript_1.default.createPrinter();
486
80
  return printer.printFile(typescript_1.default
487
- .transform(source, [styleTransformer(program, options)])
488
- .transformed.find(s => (s.fileName = fileName)) || source);
81
+ .transform(source, [styleTransformer(program, { ...options, transformers })])
82
+ .transformed.find(s => s.fileName === fileName) || source);
489
83
  }
490
84
  exports.transform = transform;
491
- function getVarName(node) {
492
- const parent = node.parent;
493
- if (typescript_1.default.isVariableDeclaration(parent) && typescript_1.default.isIdentifier(parent.name)) {
494
- return parent.name.text;
495
- }
496
- if (typescript_1.default.isPropertyAssignment(parent) && typescript_1.default.isIdentifier(parent.name)) {
497
- return `${getVarName(parent.parent)}-${parent.name.text}`;
498
- }
499
- return '';
500
- }
501
- /**
502
- * Creates an error message around a node. It will look something like:
503
- *
504
- * ```
505
- * Unknown type at: "fontSize".
506
- * File: test.ts, Line: 6, Character: 17.
507
- * const styles = createStyles({
508
- * fontSize: fontSize
509
- * ========
510
- * })
511
- * ```
512
- */
513
- function getErrorMessage(node) {
514
- const sourceFile = node.getSourceFile();
515
- const { line } = node.getSourceFile().getLineAndCharacterOfPosition(node.pos);
516
- const lineStarts = sourceFile.getLineStarts();
517
- const lineStartIndex = lineStarts.findIndex(s => s >= node.pos) - 1;
518
- // get a whole line's text given a lineStarts index
519
- function getLine(sourceFile, startIndex) {
520
- const lineStarts = sourceFile.getLineStarts();
521
- return sourceFile.text.substring(lineStarts[Math.max(0, startIndex)], startIndex + 1 >= lineStarts.length ? undefined : lineStarts[startIndex + 1]);
522
- }
523
- // Create a full context message with source code and highlighting
524
- const lineBefore = getLine(sourceFile, lineStartIndex - 1);
525
- const lineCurrent = getLine(sourceFile, lineStartIndex);
526
- const lineAfter = getLine(sourceFile, lineStartIndex + 1);
527
- const highlightedLine = ''
528
- .padStart(node.getStart() - lineStarts[lineStartIndex], ' ')
529
- .padEnd(node.getStart() - lineStarts[lineStartIndex] + node.getWidth(), '=') + '\n';
530
- /** This should look something like:
531
- * ```
532
- * const styles = createStyles({
533
- * fontSize: fontSize
534
- * ========
535
- * })
536
- * ```
537
- */
538
- const fullContext = lineBefore + lineCurrent + highlightedLine + lineAfter;
539
- const character = node.getStart() - lineStarts[lineStartIndex] + 1;
540
- return `File: ${sourceFile.fileName}:${line + 1}:${character}.\n${fullContext}`;
541
- }
542
- function getVariableNameParts(input) {
543
- const parts = input.split('.');
544
- // grab the last item in the array. This will also mutate the array, removing the last item
545
- const variable = parts.pop();
546
- return [parts.join('.'), variable];
547
- }
548
- function getVarsKeyFromNode(node) {
549
- if (typescript_1.default.isIdentifier(node)) {
550
- return canvas_kit_styling_1.slugify(node.text);
551
- }
552
- if (typescript_1.default.isPropertyAccessExpression(node) && typescript_1.default.isIdentifier(node.name)) {
553
- return `${getVarsKeyFromNode(node.expression)}-${makeEmotionSafe(node.name.text)}`;
554
- }
555
- return '';
556
- }
85
+ const handleTransformers = (node, checker, prefix, variables) => (transformers) => {
86
+ return (transformers.reduce((result, transformer) => {
87
+ if (result) {
88
+ return result;
89
+ }
90
+ return transformer(node, checker, prefix, variables);
91
+ }, undefined) || node);
92
+ };
@@ -0,0 +1,10 @@
1
+ import ts from 'typescript';
2
+ import { NestedStyleObject } from './parseObjectToStaticValue';
3
+ /**
4
+ * Creates an AST node representation of the passed in `styleObj`, but in the format of `{name:
5
+ * string, styles: serializedStyles}`. The `name` is hard-coded here to work with both server-side
6
+ * and client-side style injection. This results in a stable style key for Emotion while also
7
+ * optimizing style serialization.
8
+ */
9
+ export declare function createStyleObjectNode(styleObj: NestedStyleObject): ts.ObjectLiteralExpression;
10
+ //# sourceMappingURL=createStyleObjectNode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createStyleObjectNode.d.ts","sourceRoot":"","sources":["../../../../lib/utils/createStyleObjectNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAK5B,OAAO,EAAC,iBAAiB,EAAC,MAAM,4BAA4B,CAAC;AAE7D;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,8BAqBhE"}