@workday/canvas-kit-styling-transform 10.0.0-alpha.553-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.
@@ -0,0 +1,511 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.transform = void 0;
7
+ /// <reference types="node" />
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
+ 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
+ * A `PropertyExpression` is an expression with a dot in it. Like `a.b.c`. It may be nested. This
32
+ * function will walk the AST and create a string like `a.b.c` to be passed on to variable name
33
+ * generation. This will be used for CSS variable lookups.
34
+ */
35
+ function getPropertyAccessExpressionText(node) {
36
+ if (typescript_1.default.isIdentifier(node.name)) {
37
+ if (typescript_1.default.isIdentifier(node.expression)) {
38
+ return `${node.expression.text}.${node.name.text}`;
39
+ }
40
+ if (typescript_1.default.isPropertyAccessExpression(node.expression)) {
41
+ return `${getPropertyAccessExpressionText(node.expression)}.${node.name.text}`;
42
+ }
43
+ }
44
+ return '';
45
+ }
46
+ function parseStyleObjValue(initializer, variables, checker) {
47
+ /**
48
+ * String literals like 'red' or empty Template Expressions like `red`
49
+ */
50
+ if (typescript_1.default.isStringLiteral(initializer) || typescript_1.default.isNoSubstitutionTemplateLiteral(initializer)) {
51
+ return initializer.text;
52
+ }
53
+ // numeric literal values like `12`
54
+ if (typescript_1.default.isNumericLiteral(initializer)) {
55
+ return `${initializer.text}px`;
56
+ }
57
+ // The source file is using an identifier which will be known at runtime, we'll try to
58
+ // determine the type
59
+ if (typescript_1.default.isIdentifier(initializer)) {
60
+ const type = checker.getTypeAtLocation(initializer);
61
+ return getStyleValueFromType(initializer, type, checker);
62
+ }
63
+ /**
64
+ * ```ts
65
+ * PropertyAccessExpressions are dot-notation
66
+ *
67
+ * foo.bar.baz
68
+ * ```
69
+ */
70
+ if (typescript_1.default.isPropertyAccessExpression(initializer)) {
71
+ const type = checker.getTypeAtLocation(initializer);
72
+ return getStyleValueFromType(initializer, type, checker);
73
+ }
74
+ /**
75
+ * This will find patterns like:
76
+ *
77
+ * ```ts
78
+ * cssVar(myVars.color);
79
+ * cssVar(myVars.colors.background);
80
+ * cssVar(myVars.colors.background, 'red')
81
+ * ```
82
+ */
83
+ if (typescript_1.default.isCallExpression(initializer) &&
84
+ typescript_1.default.isIdentifier(initializer.expression) &&
85
+ initializer.expression.text === cssVarExpressionName) {
86
+ const value = getCSSValueAtLocation(initializer.arguments[0], checker);
87
+ const value2 = initializer.arguments[1]
88
+ ? parseStyleObjValue(initializer.arguments[1], variables, checker)
89
+ : undefined;
90
+ // handle fallback variables
91
+ const fallbackValue = getCssVariables_1.getFallbackVariable(value, variables);
92
+ if (value && (value2 || fallbackValue)) {
93
+ return `var(${value}, ${((value2 === null || value2 === void 0 ? void 0 : value2.startsWith('--')) ? `var(${value2})` : value2) || fallbackValue})`;
94
+ }
95
+ if (value) {
96
+ return `var(${value})`;
97
+ }
98
+ }
99
+ /**
100
+ * ```ts
101
+ * `border 1px ${myVars.colors.border}`
102
+ * ```
103
+ */
104
+ if (typescript_1.default.isTemplateExpression(initializer)) {
105
+ return getStyleValueFromTemplateExpression(initializer, variables, checker);
106
+ }
107
+ return '';
108
+ }
109
+ /**
110
+ * Gets a static string value from a template expression. It could recurse.
111
+ */
112
+ function getStyleValueFromTemplateExpression(node, variables, checker) {
113
+ if (!node) {
114
+ return '';
115
+ }
116
+ if (typescript_1.default.isTemplateExpression(node)) {
117
+ return (getStyleValueFromTemplateExpression(node.head, variables, checker) +
118
+ node.templateSpans
119
+ .map(value => getStyleValueFromTemplateExpression(value, variables, checker))
120
+ .join(''));
121
+ }
122
+ if (typescript_1.default.isTemplateHead(node) || typescript_1.default.isTemplateTail(node) || typescript_1.default.isTemplateMiddle(node)) {
123
+ return node.text;
124
+ }
125
+ if (typescript_1.default.isTemplateSpan(node)) {
126
+ return (parseStyleObjValue(node.expression, variables, checker) +
127
+ getStyleValueFromTemplateExpression(node.literal, variables, checker));
128
+ }
129
+ return '';
130
+ }
131
+ /**
132
+ * Gets a CSS value from an AST node
133
+ */
134
+ function getCSSValueAtLocation(node, checker,
135
+ /**
136
+ * Optional type. This works for cases where the node is a TypeNode or TypeScript infers the Type
137
+ * via a generic resolution. For example:
138
+ * ```ts
139
+ * function someFn<T extends string>(input: T): {fontSize: T} {
140
+ * return { fontSize: input }
141
+ * }
142
+ *
143
+ * // in styles
144
+ * ...someFn('12px')
145
+ * ```
146
+ *
147
+ * If we don't pass a type of the property given by `type.getProperties()`, TypeScript will
148
+ * resolve the type at the value node as `T` instead of `12px`. Allowing for a type override is
149
+ * useful when the caller may have more context about the type at a given node than we do.
150
+ */
151
+ type = checker.getTypeAtLocation(node)) {
152
+ const varsKey = getVarsKeyFromNode(node);
153
+ if (vars[varsKey]) {
154
+ return vars[varsKey];
155
+ }
156
+ if (type.isStringLiteral()) {
157
+ // This isn't a component variable, it is a static CSS variable
158
+ return type.value;
159
+ }
160
+ if (type.isNumberLiteral()) {
161
+ return `${type.value}px`;
162
+ }
163
+ if (node && typescript_1.default.isPropertyAccessExpression(node)) {
164
+ return getPropertyAccessExpressionText(node);
165
+ }
166
+ return '';
167
+ }
168
+ function getModuleSpecifierFromDeclaration(node) {
169
+ if (!node) {
170
+ return undefined;
171
+ }
172
+ if (typescript_1.default.isImportSpecifier(node) && typescript_1.default.isStringLiteral(node.parent.parent.parent.moduleSpecifier)) {
173
+ return node.parent.parent.parent.moduleSpecifier.text;
174
+ }
175
+ return undefined;
176
+ }
177
+ function getStyleFromProperty(property, prefix, variables, checker) {
178
+ if (typescript_1.default.isPropertyAssignment(property)) {
179
+ // All properties should be non-objects
180
+ // {foo: 'bar'}
181
+ if (typescript_1.default.isIdentifier(property.name)) {
182
+ const value = parseStyleObjValue(property.initializer, variables, checker);
183
+ if (value) {
184
+ return { [property.name.text]: value };
185
+ }
186
+ }
187
+ if (typescript_1.default.isComputedPropertyName(property.name)) {
188
+ if (typescript_1.default.isPropertyAccessExpression(property.name.expression)) {
189
+ const value = parseStyleObjValue(property.initializer, variables, checker);
190
+ if (value) {
191
+ // test if the property is a static value
192
+ getPropertyAccessExpressionText(property.name.expression);
193
+ const type = checker.getTypeAtLocation(property.name.expression);
194
+ checker.typeToString(type);
195
+ if (type.isStringLiteral()) {
196
+ return { [type.value]: value };
197
+ }
198
+ else {
199
+ const expressionText = getPropertyAccessExpressionText(property.name.expression);
200
+ const [id, name] = getVariableNameParts(expressionText);
201
+ return { [`--${prefix}-${canvas_kit_styling_1.slugify(id)}-${name}`]: value };
202
+ }
203
+ }
204
+ }
205
+ }
206
+ // String literal property names are special selectors with more styles
207
+ // {'&:hover': {}}
208
+ if (typescript_1.default.isStringLiteral(property.name)) {
209
+ return {
210
+ [property.name.text]: parseStyleObjFromNode(property.initializer, prefix, variables, checker),
211
+ };
212
+ }
213
+ }
214
+ /**
215
+ * A spread assignment looks like:
216
+ *
217
+ * ```ts
218
+ * {
219
+ * ...styles
220
+ * }
221
+ * ```
222
+ *
223
+ * https://ts-ast-viewer.com/#code/MYewdgzgLgBFCmBbADjAvDA3gMxCAXDAOQBGAhgE5EC+AUKJLAigEzpYB0Xzy1QA
224
+ */
225
+ if (typescript_1.default.isSpreadAssignment(property)) {
226
+ // Detect `focusRing` calls. This is temporary until we figure out a better way to do focus
227
+ // rings that doesn't require a special entry in the transform function.
228
+ //
229
+ // TODO: implement a fully working type resolver for CSS variables or remove support for them an
230
+ // remove all uses of `focusRing` from new styling code
231
+ if (typescript_1.default.isCallExpression(property.expression) &&
232
+ typescript_1.default.isIdentifier(property.expression.expression) &&
233
+ property.expression.expression.text === 'focusRing') {
234
+ const argumentObject = property.expression.arguments[0];
235
+ // defaults
236
+ const defaults = {
237
+ width: '2px',
238
+ separation: '0px',
239
+ inset: undefined,
240
+ innerColor: `var(${canvas_tokens_web_1.base.frenchVanilla100}, rgba(255,255,255,1))`,
241
+ outerColor: `var(${canvas_tokens_web_1.brand.common.focusOutline}, rgba(8,117,225,1))`,
242
+ };
243
+ if (argumentObject && typescript_1.default.isObjectLiteralExpression(argumentObject)) {
244
+ argumentObject.properties.forEach(property => {
245
+ if (typescript_1.default.isPropertyAssignment(property) && typescript_1.default.isIdentifier(property.name)) {
246
+ defaults[property.name.text] = parseStyleObjValue(property.initializer, variables, checker);
247
+ }
248
+ });
249
+ let boxShadow;
250
+ switch (defaults.inset) {
251
+ case 'outer':
252
+ boxShadow = `inset 0 0 0 ${defaults.separation} ${defaults.outerColor}, inset 0 0 0 calc(${defaults.width} + ${defaults.separation}) ${defaults.innerColor}`;
253
+ break;
254
+ case 'inner':
255
+ boxShadow = `inset 0 0 0 ${defaults.separation} ${defaults.innerColor}, 0 0 0 ${defaults.width} ${defaults.outerColor}`;
256
+ break;
257
+ default:
258
+ boxShadow = `0 0 0 ${defaults.separation} ${defaults.innerColor}, 0 0 0 calc(${defaults.width} + ${defaults.separation}) ${defaults.outerColor}`;
259
+ break;
260
+ }
261
+ return { boxShadow };
262
+ }
263
+ }
264
+ // Spread assignments are a bit complicated to use the AST to figure out, so we'll ask the
265
+ // TypeScript type checker.
266
+ const type = checker.getTypeAtLocation(property.expression);
267
+ checker.typeToString(type); //?
268
+ return parseStyleObjFromType(type, prefix, variables, checker);
269
+ }
270
+ return {};
271
+ }
272
+ /**
273
+ * If we're here, we have a `ts.Type` that represents a style object. We try to parse a style object
274
+ * from the AST, but we might have something that is more complicated like a function call or an
275
+ * identifier that represents an object. It could be imported from another file.
276
+ */
277
+ function parseStyleObjFromType(type, prefix, variables, checker) {
278
+ const styleObj = {};
279
+ // Gets all the properties of the type object
280
+ return type.getProperties().reduce((result, property) => {
281
+ const declaration = property.declarations[0];
282
+ if (declaration) {
283
+ const propType = checker.getTypeOfSymbolAtLocation(property, declaration);
284
+ return {
285
+ ...result,
286
+ [property.name]: getStyleValueFromType(declaration, propType, checker),
287
+ };
288
+ }
289
+ return result;
290
+ }, styleObj);
291
+ }
292
+ /**
293
+ * If the node is an `ObjectLiteralExpression`, we'll walk the `properties` of the AST node and
294
+ * create a style object for each property we find.
295
+ */
296
+ function parseStyleObjFromNode(node, prefix, variables, checker) {
297
+ const styleObj = {};
298
+ if (typescript_1.default.isObjectLiteralExpression(node)) {
299
+ return node.properties.reduce((result, property) => {
300
+ return { ...result, ...getStyleFromProperty(property, prefix, variables, checker) };
301
+ }, styleObj);
302
+ }
303
+ return styleObj;
304
+ }
305
+ /**
306
+ * Creates an AST node representation of the passed in `styleObj`, but in the format of `{name:
307
+ * string, styles: serializedStyles}`. The `name` is hard-coded here to work with both server-side
308
+ * and client-side style injection. This results in a stable style key for Emotion while also
309
+ * optimizing style serialization.
310
+ */
311
+ function createStyleObjectNode(styleObj) {
312
+ const serialized = serialize_1.serializeStyles([styleObj]);
313
+ const styleText = serialized.styles;
314
+ const styleExpression = typescript_1.default.factory.createStringLiteral(styleText);
315
+ // create an emotion-optimized object: https://github.com/emotion-js/emotion/blob/f3b268f7c52103979402da919c9c0dd3f9e0e189/packages/serialize/src/index.js#L315-L322
316
+ // Looks like: `{name: $hash, styles: $styleText }`
317
+ return typescript_1.default.factory.createObjectLiteralExpression([
318
+ typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier('name'),
319
+ // TODO - we may need this to be a static variable for the CSS package
320
+ 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
321
+ ),
322
+ 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
323
+ ),
324
+ ], false);
325
+ }
326
+ function styleTransformer(program, { prefix = 'css', variables = {}, fallbackFiles } = {
327
+ prefix: 'css',
328
+ variables: {},
329
+ }) {
330
+ if (fallbackFiles) {
331
+ const files = fallbackFiles
332
+ .filter(file => file) // don't process empty files
333
+ .map(file => {
334
+ // Find the fully-qualified path name. This could error which should give "module not found" errors
335
+ return file.startsWith('.') ? node_path_1.default.resolve(process.cwd(), file) : require.resolve(file);
336
+ })
337
+ .map(file => typescript_1.default.sys.readFile(file) || '');
338
+ // eslint-disable-next-line no-param-reassign
339
+ variables = getCssVariables_1.getVariablesFromFiles(files);
340
+ }
341
+ const checker = program.getTypeChecker();
342
+ return context => {
343
+ const visit = node => {
344
+ // eslint-disable-next-line no-param-reassign
345
+ node = typescript_1.default.visitEachChild(node, visit, context);
346
+ /**
347
+ * Check if the node is a call expression that looks like:
348
+ *
349
+ * ```ts
350
+ * createStyles({
351
+ * // properties
352
+ * })
353
+ * ```
354
+ *
355
+ * It will also make sure the `createStyles` function was imported from
356
+ * `@workday/canvas-kit-styling` to ensure we don't rewrite the AST of code we don't own.
357
+ *
358
+ * This transformation will pre-serialize the style objects and turn them into strings for
359
+ * faster runtime processing in Emotion. The following is an example of the transformation.
360
+ *
361
+ * ```ts
362
+ * // before transformation
363
+ * const myStyles = createStyles({
364
+ * fontSize: '1rem'
365
+ * })
366
+ *
367
+ * // after transformation
368
+ * const myStyles = createStyles({
369
+ * name: 'abc123',
370
+ * styles: 'font-size: 1rem;'
371
+ * })
372
+ * ```
373
+ *
374
+ * The after transformation already serialized the styles and goes through a shortcut process
375
+ * in `@emotion/css` where only the Emotion cache is checked and styles are inserted if the
376
+ * cache key wasn't found.
377
+ */
378
+ if (typescript_1.default.isCallExpression(node) &&
379
+ typescript_1.default.isIdentifier(node.expression) &&
380
+ node.expression.text === styleExpressionName &&
381
+ node.arguments.length > 0) {
382
+ // get the declaration of the symbol of the styleExpression
383
+ const symbol = checker.getSymbolAtLocation(node.expression);
384
+ const declaration = symbol === null || symbol === void 0 ? void 0 : symbol.declarations[0];
385
+ if (getModuleSpecifierFromDeclaration(declaration) === styleImportString) {
386
+ const newArguments = [...node.arguments].map(arg => {
387
+ // An `ObjectLiteralExpression` is an object like `{foo:'bar'}`:
388
+ // https://ts-ast-viewer.com/#code/MYewdgzgLgBFCmBbADjAvDA3gKBjAZiCAFwwDkARgIYBOZ2AvkA
389
+ if (typescript_1.default.isObjectLiteralExpression(arg)) {
390
+ const styleObj = parseStyleObjFromNode(arg, prefix, variables, checker);
391
+ return createStyleObjectNode(styleObj);
392
+ }
393
+ // An Identifier is a variable. It could come from anywhere - imports, earlier
394
+ // assignments, etc. The easiest thing to do is to ask the TypeScript type checker what
395
+ // the type representation is and go from there.
396
+ if (typescript_1.default.isIdentifier(arg)) {
397
+ const type = checker.getTypeAtLocation(arg);
398
+ // `createStyles` accepts strings as class names. If the class name is
399
+ if (type.isStringLiteral() || type.getFlags() & typescript_1.default.TypeFlags.String) {
400
+ return arg;
401
+ }
402
+ // The type must be a object
403
+ const styleObj = parseStyleObjFromType(type, prefix, variables, checker);
404
+ return createStyleObjectNode(styleObj);
405
+ }
406
+ return arg;
407
+ });
408
+ return typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(styleExpressionName), [], newArguments);
409
+ }
410
+ }
411
+ /**
412
+ * This will create a variable
413
+ */
414
+ if (typescript_1.default.isCallExpression(node) &&
415
+ typescript_1.default.isIdentifier(node.expression) &&
416
+ node.expression.text === createVarExpressionName) {
417
+ const id = canvas_kit_styling_1.slugify(getVarName(node));
418
+ const variables = node.arguments
419
+ .map(arg => typescript_1.default.isStringLiteral(arg) && arg.text)
420
+ .filter(Boolean);
421
+ variables.forEach(v => {
422
+ vars[`${id}-${v}`] = `--${prefix}-${id}-${v}`;
423
+ });
424
+ return typescript_1.default.factory.createCallExpression(node.expression, [], [
425
+ typescript_1.default.factory.createObjectLiteralExpression([
426
+ typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier('id'), typescript_1.default.factory.createStringLiteral(`${prefix}-${id}`)),
427
+ 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)),
428
+ ], false),
429
+ ]);
430
+ }
431
+ return node;
432
+ };
433
+ return node => typescript_1.default.visitNode(node, visit);
434
+ };
435
+ }
436
+ exports.default = styleTransformer;
437
+ // This should only be used for tests
438
+ function transform(program, fileName, options) {
439
+ const source = program.getSourceFile(fileName) || typescript_1.default.createSourceFile(fileName, '', typescript_1.default.ScriptTarget.ES2019);
440
+ const printer = typescript_1.default.createPrinter();
441
+ return printer.printFile(typescript_1.default
442
+ .transform(source, [styleTransformer(program, options)])
443
+ .transformed.find(s => (s.fileName = fileName)) || source);
444
+ }
445
+ exports.transform = transform;
446
+ function getVarName(node) {
447
+ const parent = node.parent;
448
+ if (typescript_1.default.isVariableDeclaration(parent) && typescript_1.default.isIdentifier(parent.name)) {
449
+ return parent.name.text;
450
+ }
451
+ if (typescript_1.default.isPropertyAssignment(parent) && typescript_1.default.isIdentifier(parent.name)) {
452
+ return `${getVarName(parent.parent)}-${parent.name.text}`;
453
+ }
454
+ return '';
455
+ }
456
+ /**
457
+ * Creates an error message around a node. It will look something like:
458
+ *
459
+ * ```
460
+ * Unknown type at: "fontSize".
461
+ * File: test.ts, Line: 6, Character: 17.
462
+ * const styles = createStyles({
463
+ * fontSize: fontSize
464
+ * ========
465
+ * })
466
+ * ```
467
+ */
468
+ function getErrorMessage(node) {
469
+ const sourceFile = node.getSourceFile();
470
+ const { line } = node.getSourceFile().getLineAndCharacterOfPosition(node.pos);
471
+ const lineStarts = sourceFile.getLineStarts();
472
+ const lineStartIndex = lineStarts.findIndex(s => s >= node.pos) - 1;
473
+ // get a whole line's text given a lineStarts index
474
+ function getLine(sourceFile, startIndex) {
475
+ const lineStarts = sourceFile.getLineStarts();
476
+ return sourceFile.text.substring(lineStarts[Math.max(0, startIndex)], startIndex + 1 >= lineStarts.length ? undefined : lineStarts[startIndex + 1]);
477
+ }
478
+ // Create a full context message with source code and highlighting
479
+ const lineBefore = getLine(sourceFile, lineStartIndex - 1);
480
+ const lineCurrent = getLine(sourceFile, lineStartIndex);
481
+ const lineAfter = getLine(sourceFile, lineStartIndex + 1);
482
+ const highlightedLine = ''
483
+ .padStart(node.getStart() - lineStarts[lineStartIndex], ' ')
484
+ .padEnd(node.getStart() - lineStarts[lineStartIndex] + node.getWidth(), '=') + '\n';
485
+ /** This should look something like:
486
+ * ```
487
+ * const styles = createStyles({
488
+ * fontSize: fontSize
489
+ * ========
490
+ * })
491
+ * ```
492
+ */
493
+ const fullContext = lineBefore + lineCurrent + highlightedLine + lineAfter;
494
+ const character = node.getStart() - lineStarts[lineStartIndex] + 1;
495
+ return `File: ${sourceFile.fileName}:${line + 1}:${character}.\n${fullContext}`;
496
+ }
497
+ function getVariableNameParts(input) {
498
+ const parts = input.split('.');
499
+ // grab the last item in the array. This will also mutate the array, removing the last item
500
+ const variable = parts.pop();
501
+ return [parts.join('.'), variable];
502
+ }
503
+ function getVarsKeyFromNode(node) {
504
+ if (typescript_1.default.isIdentifier(node)) {
505
+ return canvas_kit_styling_1.slugify(node.text);
506
+ }
507
+ if (typescript_1.default.isPropertyAccessExpression(node) && typescript_1.default.isIdentifier(node.name)) {
508
+ return `${getVarsKeyFromNode(node.expression)}-${node.name.text}`;
509
+ }
510
+ return '';
511
+ }
@@ -0,0 +1,3 @@
1
+ import styleTransformer from './lib/styleTransform';
2
+ export default styleTransformer;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,sBAAsB,CAAC;AAEpD,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import styleTransformer from './lib/styleTransform';
2
+ export default styleTransformer;
@@ -0,0 +1,5 @@
1
+ import { Element } from 'stylis';
2
+ export declare function getVariablesFromFiles(files: string[]): Record<string, string>;
3
+ export declare function extractVariables(blocks: Element[] | string, variables?: Record<string, string>): Record<string, string>;
4
+ export declare function getFallbackVariable(variableName: string, variables: Record<string, string>): string | undefined;
5
+ //# sourceMappingURL=getCssVariables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCssVariables.d.ts","sourceRoot":"","sources":["../../../lib/getCssVariables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAC,MAAM,QAAQ,CAAC;AAExC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAK7E;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAC1B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACrC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAuBxB;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,GAAG,SAAS,CAwBpB"}
@@ -0,0 +1,45 @@
1
+ import { compile } from 'stylis';
2
+ export function getVariablesFromFiles(files) {
3
+ return files.reduce((result, file) => {
4
+ extractVariables(compile(file));
5
+ return { ...result, ...extractVariables(compile(file)) };
6
+ }, {});
7
+ }
8
+ export function extractVariables(blocks, variables = {}) {
9
+ if (typeof blocks === 'string') {
10
+ return variables;
11
+ }
12
+ return blocks
13
+ .filter(block => block.type === 'rule')
14
+ .reduce((result, rule) => {
15
+ if (Array.isArray(rule.children)) {
16
+ rule.children.forEach(child => {
17
+ if (typeof child.props === 'string' &&
18
+ child.props.startsWith('--') &&
19
+ typeof child.children === 'string') {
20
+ result[child.props] = child.children;
21
+ }
22
+ });
23
+ }
24
+ return result;
25
+ }, { ...variables });
26
+ }
27
+ export function getFallbackVariable(variableName, variables) {
28
+ const variable = variableName.includes('var(') ? variableName : variables[variableName];
29
+ if (variable && variable.includes('var(')) {
30
+ return variable.replace(/(var\(([A-Za-z0-9\-_]+)\))/, (
31
+ /** matched substring "var(--var-name)" */ _,
32
+ /** the full match of the first group "var(--var-name)" */ varMatch,
33
+ /** the variable name - match of the second group "--var-name" */ cssVarName, ...args) => {
34
+ const value = variables[cssVarName];
35
+ if (value && value.startsWith('var')) {
36
+ return getFallbackVariable(value, variables);
37
+ }
38
+ return value || varMatch;
39
+ });
40
+ }
41
+ if (variable) {
42
+ return variable;
43
+ }
44
+ return;
45
+ }
@@ -0,0 +1,12 @@
1
+ import ts from 'typescript';
2
+ export declare type NestedStyleObject = {
3
+ [key: string]: string | NestedStyleObject;
4
+ };
5
+ export interface StyleTransformerOptions {
6
+ prefix: string;
7
+ variables: Record<string, string>;
8
+ fallbackFiles?: string[];
9
+ }
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
+ //# sourceMappingURL=styleTransform.d.ts.map
@@ -0,0 +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;AAmZ5E,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,CAgJtC;AAGD,wBAAgB,SAAS,CACvB,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,UAY3C"}