@workday/canvas-kit-styling-transform 13.2.1 → 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.
- package/dist/commonjs/index.d.ts +14 -0
- package/dist/commonjs/index.d.ts.map +1 -0
- package/dist/commonjs/index.js +28 -0
- package/dist/commonjs/lib/createObjectTransform.d.ts +10 -0
- package/dist/commonjs/lib/createObjectTransform.d.ts.map +1 -0
- package/dist/commonjs/lib/createObjectTransform.js +14 -0
- package/dist/commonjs/lib/createPropertyTransform.d.ts +7 -0
- package/dist/commonjs/lib/createPropertyTransform.d.ts.map +1 -0
- package/dist/commonjs/lib/createPropertyTransform.js +11 -0
- package/dist/commonjs/lib/createTypeScriptWatchProgram.d.ts +16 -0
- package/dist/commonjs/lib/createTypeScriptWatchProgram.d.ts.map +1 -0
- package/dist/commonjs/lib/createTypeScriptWatchProgram.js +45 -0
- package/dist/commonjs/lib/styleTransform.d.ts +23 -0
- package/dist/commonjs/lib/styleTransform.d.ts.map +1 -0
- package/dist/commonjs/lib/styleTransform.js +131 -0
- package/dist/commonjs/lib/utils/createStyleObjectNode.d.ts +35 -0
- package/dist/commonjs/lib/utils/createStyleObjectNode.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/createStyleObjectNode.js +84 -0
- package/dist/commonjs/lib/utils/getCssVariables.d.ts +4 -0
- package/dist/commonjs/lib/utils/getCssVariables.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/getCssVariables.js +31 -0
- package/dist/commonjs/lib/utils/getErrorMessage.d.ts +16 -0
- package/dist/commonjs/lib/utils/getErrorMessage.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/getErrorMessage.js +45 -0
- package/dist/commonjs/lib/utils/getFallbackVariable.d.ts +9 -0
- package/dist/commonjs/lib/utils/getFallbackVariable.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/getFallbackVariable.js +30 -0
- package/dist/commonjs/lib/utils/getHash.d.ts +4 -0
- package/dist/commonjs/lib/utils/getHash.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/getHash.js +16 -0
- package/dist/commonjs/lib/utils/getVarName.d.ts +17 -0
- package/dist/commonjs/lib/utils/getVarName.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/getVarName.js +34 -0
- package/dist/commonjs/lib/utils/handleCalc.d.ts +2 -0
- package/dist/commonjs/lib/utils/handleCalc.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/handleCalc.js +33 -0
- package/dist/commonjs/lib/utils/handleCreateStencil.d.ts +7 -0
- package/dist/commonjs/lib/utils/handleCreateStencil.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/handleCreateStencil.js +309 -0
- package/dist/commonjs/lib/utils/handleCreateStyles.d.ts +3 -0
- package/dist/commonjs/lib/utils/handleCreateStyles.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/handleCreateStyles.js +86 -0
- package/dist/commonjs/lib/utils/handleCreateVars.d.ts +3 -0
- package/dist/commonjs/lib/utils/handleCreateVars.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/handleCreateVars.js +65 -0
- package/dist/commonjs/lib/utils/handleCssVar.d.ts +2 -0
- package/dist/commonjs/lib/utils/handleCssVar.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/handleCssVar.js +19 -0
- package/dist/commonjs/lib/utils/handleInjectGlobal.d.ts +3 -0
- package/dist/commonjs/lib/utils/handleInjectGlobal.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/handleInjectGlobal.js +40 -0
- package/dist/commonjs/lib/utils/handleKeyframes.d.ts +3 -0
- package/dist/commonjs/lib/utils/handleKeyframes.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/handleKeyframes.js +48 -0
- package/dist/commonjs/lib/utils/handleParentModifier.d.ts +2 -0
- package/dist/commonjs/lib/utils/handleParentModifier.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/handleParentModifier.js +26 -0
- package/dist/commonjs/lib/utils/handlePx2Rem.d.ts +2 -0
- package/dist/commonjs/lib/utils/handlePx2Rem.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/handlePx2Rem.js +19 -0
- package/dist/commonjs/lib/utils/injectStyles.d.ts +3 -0
- package/dist/commonjs/lib/utils/injectStyles.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/injectStyles.js +11 -0
- package/dist/commonjs/lib/utils/isImportedFromStyling.d.ts +7 -0
- package/dist/commonjs/lib/utils/isImportedFromStyling.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/isImportedFromStyling.js +24 -0
- package/dist/commonjs/lib/utils/parseNodeToStaticValue.d.ts +11 -0
- package/dist/commonjs/lib/utils/parseNodeToStaticValue.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/parseNodeToStaticValue.js +217 -0
- package/dist/commonjs/lib/utils/parseObjectToStaticValue.d.ts +15 -0
- package/dist/commonjs/lib/utils/parseObjectToStaticValue.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/parseObjectToStaticValue.js +168 -0
- package/dist/commonjs/lib/utils/stylisFns.d.ts +3 -0
- package/dist/commonjs/lib/utils/stylisFns.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/stylisFns.js +45 -0
- package/dist/commonjs/lib/utils/types.d.ts +210 -0
- package/dist/commonjs/lib/utils/types.d.ts.map +1 -0
- package/dist/commonjs/lib/utils/types.js +2 -0
- package/dist/commonjs/lib/webpack-loader.d.ts +7 -0
- package/dist/commonjs/lib/webpack-loader.d.ts.map +1 -0
- package/dist/commonjs/lib/webpack-loader.js +21 -0
- package/dist/commonjs/lib/webpackPlugin.d.ts +31 -0
- package/dist/commonjs/lib/webpackPlugin.d.ts.map +1 -0
- package/dist/commonjs/lib/webpackPlugin.js +38 -0
- package/dist/commonjs/spec/createProgramFromSource.d.ts +8 -0
- package/dist/commonjs/spec/createProgramFromSource.d.ts.map +1 -0
- package/dist/commonjs/spec/createProgramFromSource.js +111 -0
- package/dist/commonjs/spec/findNodes.d.ts +3 -0
- package/dist/commonjs/spec/findNodes.d.ts.map +1 -0
- package/dist/commonjs/spec/findNodes.js +33 -0
- package/dist/commonjs/testing.d.ts +4 -0
- package/dist/commonjs/testing.d.ts.map +1 -0
- package/dist/commonjs/testing.js +11 -0
- package/dist/es6/index.d.ts +14 -0
- package/dist/es6/index.d.ts.map +1 -0
- package/dist/es6/index.js +14 -0
- package/dist/es6/lib/createObjectTransform.d.ts +10 -0
- package/dist/es6/lib/createObjectTransform.d.ts.map +1 -0
- package/dist/es6/lib/createObjectTransform.js +10 -0
- package/dist/es6/lib/createPropertyTransform.d.ts +7 -0
- package/dist/es6/lib/createPropertyTransform.d.ts.map +1 -0
- package/dist/es6/lib/createPropertyTransform.js +7 -0
- package/dist/es6/lib/createTypeScriptWatchProgram.d.ts +16 -0
- package/dist/es6/lib/createTypeScriptWatchProgram.d.ts.map +1 -0
- package/dist/es6/lib/createTypeScriptWatchProgram.js +36 -0
- package/dist/es6/lib/styleTransform.d.ts +23 -0
- package/dist/es6/lib/styleTransform.d.ts.map +1 -0
- package/dist/es6/lib/styleTransform.js +120 -0
- package/dist/es6/lib/utils/createStyleObjectNode.d.ts +35 -0
- package/dist/es6/lib/utils/createStyleObjectNode.d.ts.map +1 -0
- package/dist/es6/lib/utils/createStyleObjectNode.js +74 -0
- package/dist/es6/lib/utils/getCssVariables.d.ts +4 -0
- package/dist/es6/lib/utils/getCssVariables.d.ts.map +1 -0
- package/dist/es6/lib/utils/getCssVariables.js +26 -0
- package/dist/es6/lib/utils/getErrorMessage.d.ts +16 -0
- package/dist/es6/lib/utils/getErrorMessage.d.ts.map +1 -0
- package/dist/es6/lib/utils/getErrorMessage.js +41 -0
- package/dist/es6/lib/utils/getFallbackVariable.d.ts +9 -0
- package/dist/es6/lib/utils/getFallbackVariable.d.ts.map +1 -0
- package/dist/es6/lib/utils/getFallbackVariable.js +26 -0
- package/dist/es6/lib/utils/getHash.d.ts +4 -0
- package/dist/es6/lib/utils/getHash.d.ts.map +1 -0
- package/dist/es6/lib/utils/getHash.js +9 -0
- package/dist/es6/lib/utils/getVarName.d.ts +17 -0
- package/dist/es6/lib/utils/getVarName.d.ts.map +1 -0
- package/dist/es6/lib/utils/getVarName.js +27 -0
- package/dist/es6/lib/utils/handleCalc.d.ts +2 -0
- package/dist/es6/lib/utils/handleCalc.d.ts.map +1 -0
- package/dist/es6/lib/utils/handleCalc.js +27 -0
- package/dist/es6/lib/utils/handleCreateStencil.d.ts +7 -0
- package/dist/es6/lib/utils/handleCreateStencil.d.ts.map +1 -0
- package/dist/es6/lib/utils/handleCreateStencil.js +301 -0
- package/dist/es6/lib/utils/handleCreateStyles.d.ts +3 -0
- package/dist/es6/lib/utils/handleCreateStyles.d.ts.map +1 -0
- package/dist/es6/lib/utils/handleCreateStyles.js +79 -0
- package/dist/es6/lib/utils/handleCreateVars.d.ts +3 -0
- package/dist/es6/lib/utils/handleCreateVars.d.ts.map +1 -0
- package/dist/es6/lib/utils/handleCreateVars.js +58 -0
- package/dist/es6/lib/utils/handleCssVar.d.ts +2 -0
- package/dist/es6/lib/utils/handleCssVar.d.ts.map +1 -0
- package/dist/es6/lib/utils/handleCssVar.js +13 -0
- package/dist/es6/lib/utils/handleInjectGlobal.d.ts +3 -0
- package/dist/es6/lib/utils/handleInjectGlobal.d.ts.map +1 -0
- package/dist/es6/lib/utils/handleInjectGlobal.js +33 -0
- package/dist/es6/lib/utils/handleKeyframes.d.ts +3 -0
- package/dist/es6/lib/utils/handleKeyframes.d.ts.map +1 -0
- package/dist/es6/lib/utils/handleKeyframes.js +41 -0
- package/dist/es6/lib/utils/handleParentModifier.d.ts +2 -0
- package/dist/es6/lib/utils/handleParentModifier.d.ts.map +1 -0
- package/dist/es6/lib/utils/handleParentModifier.js +20 -0
- package/dist/es6/lib/utils/handlePx2Rem.d.ts +2 -0
- package/dist/es6/lib/utils/handlePx2Rem.d.ts.map +1 -0
- package/dist/es6/lib/utils/handlePx2Rem.js +13 -0
- package/dist/es6/lib/utils/injectStyles.d.ts +3 -0
- package/dist/es6/lib/utils/injectStyles.d.ts.map +1 -0
- package/dist/es6/lib/utils/injectStyles.js +7 -0
- package/dist/es6/lib/utils/isImportedFromStyling.d.ts +7 -0
- package/dist/es6/lib/utils/isImportedFromStyling.d.ts.map +1 -0
- package/dist/es6/lib/utils/isImportedFromStyling.js +17 -0
- package/dist/es6/lib/utils/parseNodeToStaticValue.d.ts +11 -0
- package/dist/es6/lib/utils/parseNodeToStaticValue.d.ts.map +1 -0
- package/dist/es6/lib/utils/parseNodeToStaticValue.js +209 -0
- package/dist/es6/lib/utils/parseObjectToStaticValue.d.ts +15 -0
- package/dist/es6/lib/utils/parseObjectToStaticValue.d.ts.map +1 -0
- package/dist/es6/lib/utils/parseObjectToStaticValue.js +159 -0
- package/dist/es6/lib/utils/stylisFns.d.ts +3 -0
- package/dist/es6/lib/utils/stylisFns.d.ts.map +1 -0
- package/dist/es6/lib/utils/stylisFns.js +41 -0
- package/dist/es6/lib/utils/types.d.ts +210 -0
- package/dist/es6/lib/utils/types.d.ts.map +1 -0
- package/dist/es6/lib/utils/types.js +1 -0
- package/dist/es6/lib/webpack-loader.d.ts +7 -0
- package/dist/es6/lib/webpack-loader.d.ts.map +1 -0
- package/dist/es6/lib/webpack-loader.js +15 -0
- package/dist/es6/lib/webpackPlugin.d.ts +31 -0
- package/dist/es6/lib/webpackPlugin.d.ts.map +1 -0
- package/dist/es6/lib/webpackPlugin.js +31 -0
- package/dist/es6/spec/createProgramFromSource.d.ts +8 -0
- package/dist/es6/spec/createProgramFromSource.d.ts.map +1 -0
- package/dist/es6/spec/createProgramFromSource.js +81 -0
- package/dist/es6/spec/findNodes.d.ts +3 -0
- package/dist/es6/spec/findNodes.d.ts.map +1 -0
- package/dist/es6/spec/findNodes.js +26 -0
- package/dist/es6/testing.d.ts +4 -0
- package/dist/es6/testing.d.ts.map +1 -0
- package/dist/es6/testing.js +3 -0
- package/index.ts +19 -0
- package/lib/createObjectTransform.ts +12 -0
- package/lib/createPropertyTransform.ts +9 -0
- package/lib/createTypeScriptWatchProgram.ts +52 -0
- package/lib/styleTransform.ts +169 -0
- package/lib/utils/createStyleObjectNode.ts +105 -0
- package/lib/utils/getCssVariables.ts +36 -0
- package/lib/utils/getErrorMessage.ts +57 -0
- package/lib/utils/getFallbackVariable.ts +34 -0
- package/lib/utils/getHash.ts +13 -0
- package/lib/utils/getVarName.ts +32 -0
- package/lib/utils/handleCalc.ts +33 -0
- package/lib/utils/handleCreateStencil.ts +442 -0
- package/lib/utils/handleCreateStyles.ts +97 -0
- package/lib/utils/handleCreateVars.ts +90 -0
- package/lib/utils/handleCssVar.ts +19 -0
- package/lib/utils/handleInjectGlobal.ts +51 -0
- package/lib/utils/handleKeyframes.ts +60 -0
- package/lib/utils/handleParentModifier.ts +29 -0
- package/lib/utils/handlePx2Rem.ts +22 -0
- package/lib/utils/injectStyles.ts +14 -0
- package/lib/utils/isImportedFromStyling.ts +21 -0
- package/lib/utils/parseNodeToStaticValue.ts +281 -0
- package/lib/utils/parseObjectToStaticValue.ts +201 -0
- package/lib/utils/stylisFns.ts +56 -0
- package/lib/utils/types.ts +223 -0
- package/lib/webpack-loader.ts +28 -0
- package/lib/webpackPlugin.ts +69 -0
- package/package.json +19 -14
- package/index.js +0 -22
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
|
|
5
|
+
import {getVariablesFromFiles} from './utils/getCssVariables';
|
|
6
|
+
import {handleCalc} from './utils/handleCalc';
|
|
7
|
+
import {handleCreateStencil} from './utils/handleCreateStencil';
|
|
8
|
+
import {handleCreateStyles} from './utils/handleCreateStyles';
|
|
9
|
+
import {handleCreateVars} from './utils/handleCreateVars';
|
|
10
|
+
import {handleCssVar} from './utils/handleCssVar';
|
|
11
|
+
import {handleInjectGlobal} from './utils/handleInjectGlobal';
|
|
12
|
+
import {handleKeyframes} from './utils/handleKeyframes';
|
|
13
|
+
import {handleParentModifier} from './utils/handleParentModifier';
|
|
14
|
+
import {handlePx2Rem} from './utils/handlePx2Rem';
|
|
15
|
+
import {NodeTransformer, ObjectTransform, TransformerContext} from './utils/types';
|
|
16
|
+
|
|
17
|
+
export type NestedStyleObject = {[key: string]: string | NestedStyleObject};
|
|
18
|
+
|
|
19
|
+
export interface StyleTransformerOptions extends TransformerContext {
|
|
20
|
+
fallbackFiles?: string[];
|
|
21
|
+
transformers?: NodeTransformer[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let vars: TransformerContext['names'] = {};
|
|
25
|
+
let extractedNames: TransformerContext['extractedNames'] = {};
|
|
26
|
+
let styles: TransformerContext['styles'] = {};
|
|
27
|
+
let cache: TransformerContext['cache'] = {};
|
|
28
|
+
let loadedFallbacks = false;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The reset is used in tests and should not be called normally.
|
|
32
|
+
*/
|
|
33
|
+
export function _reset() {
|
|
34
|
+
vars = {};
|
|
35
|
+
extractedNames = {};
|
|
36
|
+
styles = {};
|
|
37
|
+
cache = {};
|
|
38
|
+
loadedFallbacks = false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Optional list of transformers. Useful to override for tests
|
|
43
|
+
*/
|
|
44
|
+
const defaultTransformers = [
|
|
45
|
+
handleKeyframes,
|
|
46
|
+
handleCreateVars,
|
|
47
|
+
handleCreateStyles,
|
|
48
|
+
handleCreateStencil,
|
|
49
|
+
handleInjectGlobal,
|
|
50
|
+
];
|
|
51
|
+
export default styleTransformer;
|
|
52
|
+
export function styleTransformer(
|
|
53
|
+
program: ts.Program,
|
|
54
|
+
{fallbackFiles = [], ...options}: Partial<StyleTransformerOptions> = {}
|
|
55
|
+
): ts.TransformerFactory<ts.SourceFile> {
|
|
56
|
+
const {names, ...transformContext} = withDefaultContext(program.getTypeChecker(), options);
|
|
57
|
+
|
|
58
|
+
if (!loadedFallbacks) {
|
|
59
|
+
const files: string[] = fallbackFiles
|
|
60
|
+
.filter(file => file) // don't process empty files
|
|
61
|
+
.map(file => {
|
|
62
|
+
// Find the fully-qualified path name. This could error which should give "module not found" errors
|
|
63
|
+
return file.startsWith('.') ? path.resolve(process.cwd(), file) : require.resolve(file);
|
|
64
|
+
})
|
|
65
|
+
.map(file => {
|
|
66
|
+
console.log(`Loading CSS variable fallback file: ${file}`);
|
|
67
|
+
return ts.sys.readFile(file) || '';
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const fallbackVars = getVariablesFromFiles(files);
|
|
71
|
+
console.log(`Found ${Object.keys(fallbackVars).length} variables.`);
|
|
72
|
+
|
|
73
|
+
// eslint-disable-next-line guard-for-in
|
|
74
|
+
for (const key in fallbackVars) {
|
|
75
|
+
names[key] = fallbackVars[key];
|
|
76
|
+
}
|
|
77
|
+
loadedFallbacks = true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return context => {
|
|
81
|
+
const visit: ts.Visitor = node => {
|
|
82
|
+
if (!transformContext.fileName) {
|
|
83
|
+
transformContext.fileName = node.getSourceFile()?.fileName;
|
|
84
|
+
transformContext.prefix = transformContext.getPrefix(transformContext.fileName);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (
|
|
88
|
+
ts.isSourceFile(node) &&
|
|
89
|
+
node.fileName !== 'test.ts' &&
|
|
90
|
+
transformContext.styles[transformContext.getFileName(node.fileName)] &&
|
|
91
|
+
transformContext.extractCSS
|
|
92
|
+
) {
|
|
93
|
+
ts.sys.writeFile(
|
|
94
|
+
transformContext.getFileName(transformContext.getFileName(node.fileName)),
|
|
95
|
+
(transformContext.styles[transformContext.getFileName(node.fileName)] || []).join('\n')
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const newNode = transformContext.transform(node, {
|
|
100
|
+
names,
|
|
101
|
+
...transformContext,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return newNode || ts.visitEachChild(node, visit, context);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return (node => ts.visitNode(node, visit)) as ts.Transformer<ts.SourceFile>;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function withDefaultContext(
|
|
112
|
+
checker: ts.TypeChecker,
|
|
113
|
+
{transformers, ...input}: Partial<StyleTransformerOptions> = {}
|
|
114
|
+
): TransformerContext {
|
|
115
|
+
return {
|
|
116
|
+
prefix: 'css',
|
|
117
|
+
getPrefix: path => input.prefix || 'css',
|
|
118
|
+
names: vars,
|
|
119
|
+
extractedNames,
|
|
120
|
+
styles,
|
|
121
|
+
cache,
|
|
122
|
+
checker,
|
|
123
|
+
seed: '',
|
|
124
|
+
extractCSS: false,
|
|
125
|
+
getFileName: path => path.replace(/\.tsx?/, '.css'),
|
|
126
|
+
objectTransforms: [] as ObjectTransform[],
|
|
127
|
+
transform: handleTransformers(transformers || defaultTransformers),
|
|
128
|
+
...input,
|
|
129
|
+
propertyTransforms: [handleCalc, handlePx2Rem, handleCssVar, handleParentModifier].concat(
|
|
130
|
+
input.propertyTransforms || []
|
|
131
|
+
),
|
|
132
|
+
} as TransformerContext;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* This function is useful for tests or a custom build. The `styleTransformer` function is used by
|
|
137
|
+
* the https://www.npmjs.com/package/ts-patch package.
|
|
138
|
+
*/
|
|
139
|
+
export function transform(
|
|
140
|
+
program: ts.Program,
|
|
141
|
+
fileName = 'test.ts',
|
|
142
|
+
options?: Partial<StyleTransformerOptions>
|
|
143
|
+
) {
|
|
144
|
+
const source =
|
|
145
|
+
program.getSourceFile(fileName) || ts.createSourceFile(fileName, '', ts.ScriptTarget.ES2019);
|
|
146
|
+
|
|
147
|
+
const printer = ts.createPrinter();
|
|
148
|
+
|
|
149
|
+
const transformers = [styleTransformer(program, options)];
|
|
150
|
+
|
|
151
|
+
return printer.printFile(
|
|
152
|
+
ts.transform(source, transformers).transformed.find(s => s.fileName === source.fileName) ||
|
|
153
|
+
source
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const handleTransformers =
|
|
158
|
+
(transformers: ((node: ts.Node, context: TransformerContext) => ts.Node | void)[]) =>
|
|
159
|
+
(node: ts.Node, context: TransformerContext) => {
|
|
160
|
+
return transformers.reduce((result, transformer) => {
|
|
161
|
+
return result || transformer(node, context);
|
|
162
|
+
}, undefined as ts.Node | void);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export function getConfig(basePath = '.') {
|
|
166
|
+
const tsconfigPath = ts.findConfigFile(basePath, ts.sys.fileExists, 'styling.config.ts');
|
|
167
|
+
|
|
168
|
+
return tsconfigPath;
|
|
169
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {serializeStyles as serializedStylesEmotion} from '@emotion/serialize';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
import {compile, serialize} from 'stylis';
|
|
4
|
+
import ts from 'typescript';
|
|
5
|
+
|
|
6
|
+
import {generateUniqueId} from '@workday/canvas-kit-styling';
|
|
7
|
+
|
|
8
|
+
import {prettyStringify} from './stylisFns';
|
|
9
|
+
import {NestedStyleObject, TransformerContext} from './types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates an AST node representation of the passed in `styleObj`, but in the format of `{name:
|
|
13
|
+
* string, styles: serializedStyles}`. The `name` is hard-coded here to work with both server-side
|
|
14
|
+
* and client-side style injection. This results in a stable style key for Emotion while also
|
|
15
|
+
* optimizing style serialization.
|
|
16
|
+
*
|
|
17
|
+
* If `name` is provided, the name will be whatever `name` is, replacing "{hash}" with the hash
|
|
18
|
+
* created via `serializeStyles`. For example: 'animation-{hash}' will be converted into
|
|
19
|
+
* 'animation-abc123'
|
|
20
|
+
*/
|
|
21
|
+
export function createStyleObjectNode(styles: string, name?: string) {
|
|
22
|
+
const styleExpression = ts.factory.createStringLiteral(styles);
|
|
23
|
+
|
|
24
|
+
// create an emotion-optimized object: https://github.com/emotion-js/emotion/blob/f3b268f7c52103979402da919c9c0dd3f9e0e189/packages/serialize/src/index.js#L315-L322
|
|
25
|
+
// Looks like: `{name: $hash, styles: $styleText }`
|
|
26
|
+
return ts.factory.createObjectLiteralExpression(
|
|
27
|
+
[
|
|
28
|
+
ts.factory.createPropertyAssignment(
|
|
29
|
+
ts.factory.createIdentifier('name'),
|
|
30
|
+
ts.factory.createStringLiteral(name || 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
|
|
31
|
+
),
|
|
32
|
+
ts.factory.createPropertyAssignment(
|
|
33
|
+
ts.factory.createIdentifier('styles'),
|
|
34
|
+
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
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
false
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Compiles CSS using stylis. Emotion's `serializeStyles` creates an unwrapped string for cache
|
|
43
|
+
* storage and it often needs to be wrapped by a CSS selector or `@keyframes`. This function does
|
|
44
|
+
* this the same way Emotion does it internally.
|
|
45
|
+
*/
|
|
46
|
+
export function compileCSS(input: string): string {
|
|
47
|
+
return serialize(compile(input), prettyStringify);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Serialize styles and put them to style output. The styles will be serialized via Emotion. Returns
|
|
52
|
+
* the serialized styles.
|
|
53
|
+
* @param node
|
|
54
|
+
* @param input
|
|
55
|
+
* @param template The template for creating styles for static CSS. There are two placeholders: `%n`
|
|
56
|
+
* represents the hash name while `%s` represents the string styles.
|
|
57
|
+
* @param context
|
|
58
|
+
* @returns
|
|
59
|
+
*/
|
|
60
|
+
export function serializeStyles(
|
|
61
|
+
node: ts.Node,
|
|
62
|
+
input: NestedStyleObject | string,
|
|
63
|
+
template: string,
|
|
64
|
+
context: TransformerContext
|
|
65
|
+
) {
|
|
66
|
+
const {getFileName, styles, cache, names, extractedNames} = context;
|
|
67
|
+
const fileName = getFileName(node.getSourceFile().fileName);
|
|
68
|
+
const serialized = serializedStylesEmotion([input]);
|
|
69
|
+
const hash = getHash(node, context);
|
|
70
|
+
serialized.name = hash;
|
|
71
|
+
|
|
72
|
+
if (!cache[hash]) {
|
|
73
|
+
const styleOutput = compileCSS(
|
|
74
|
+
template.replace('%s', serialized.styles).replace('%n', serialized.name)
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
let extractedStyleOutput = styleOutput;
|
|
78
|
+
|
|
79
|
+
for (const key in names) {
|
|
80
|
+
if (extractedNames[names[key]]) {
|
|
81
|
+
// @ts-ignore replaceAll was added in es2021, but our lib versions don't go past es2019. replaceAll is available in node 15+
|
|
82
|
+
extractedStyleOutput = extractedStyleOutput.replaceAll(
|
|
83
|
+
names[key],
|
|
84
|
+
extractedNames[names[key]]
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
styles[fileName] = styles[fileName] || [];
|
|
89
|
+
styles[fileName].push(extractedStyleOutput);
|
|
90
|
+
cache[hash] = styleOutput;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return serialized;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Generate a deterministic hash that is unique to the seed +
|
|
98
|
+
*/
|
|
99
|
+
export function getHash(node: ts.Node, context: TransformerContext) {
|
|
100
|
+
const content = context.seed + node.getStart() + node.getEnd();
|
|
101
|
+
// Convert content to a sha256 hash and then convert to a base36 number for better compression
|
|
102
|
+
return Number(
|
|
103
|
+
`0x${crypto.createHash('sha256').update(content).digest('hex').slice(0, 7)}`
|
|
104
|
+
).toString(36);
|
|
105
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {compile, Element} from 'stylis';
|
|
2
|
+
|
|
3
|
+
export function getVariablesFromFiles(files: string[]): Record<string, string> {
|
|
4
|
+
return files.reduce((result, file) => {
|
|
5
|
+
extractVariables(compile(file));
|
|
6
|
+
return {...result, ...extractVariables(compile(file))};
|
|
7
|
+
}, {} as Record<string, string>);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function extractVariables(
|
|
11
|
+
blocks: Element[] | string,
|
|
12
|
+
variables: Record<string, string> = {}
|
|
13
|
+
): Record<string, string> {
|
|
14
|
+
if (typeof blocks === 'string') {
|
|
15
|
+
return variables;
|
|
16
|
+
}
|
|
17
|
+
return blocks
|
|
18
|
+
.filter(block => block.type === 'rule')
|
|
19
|
+
.reduce(
|
|
20
|
+
(result, rule) => {
|
|
21
|
+
if (Array.isArray(rule.children)) {
|
|
22
|
+
rule.children.forEach(child => {
|
|
23
|
+
if (
|
|
24
|
+
typeof child.props === 'string' &&
|
|
25
|
+
child.props.startsWith('--') &&
|
|
26
|
+
typeof child.children === 'string'
|
|
27
|
+
) {
|
|
28
|
+
result[child.props] = child.children;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
},
|
|
34
|
+
{...variables}
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import {TransformerContext} from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates an error message around a node. It will look something like:
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* Unknown type at: "fontSize".
|
|
9
|
+
* File: test.ts, Line: 6, Character: 17.
|
|
10
|
+
* const styles = createStyles({
|
|
11
|
+
* fontSize: fontSize
|
|
12
|
+
* ========
|
|
13
|
+
* })
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function getErrorMessage(node: ts.Node, context: TransformerContext) {
|
|
17
|
+
const sourceFile = node.getSourceFile();
|
|
18
|
+
|
|
19
|
+
const {line} = node.getSourceFile().getLineAndCharacterOfPosition(node.pos);
|
|
20
|
+
const lineStarts = sourceFile.getLineStarts();
|
|
21
|
+
|
|
22
|
+
const lineStartIndex = lineStarts.findIndex(s => s >= node.pos) - 1;
|
|
23
|
+
|
|
24
|
+
// get a whole line's text given a lineStarts index
|
|
25
|
+
function getLine(sourceFile: ts.SourceFile, startIndex: number) {
|
|
26
|
+
const lineStarts = sourceFile.getLineStarts();
|
|
27
|
+
|
|
28
|
+
return sourceFile.text.substring(
|
|
29
|
+
lineStarts[Math.max(0, startIndex)],
|
|
30
|
+
startIndex + 1 >= lineStarts.length ? undefined : lineStarts[startIndex + 1]
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Create a full context message with source code and highlighting
|
|
35
|
+
const lineBefore = getLine(sourceFile, lineStartIndex - 1);
|
|
36
|
+
const lineCurrent = getLine(sourceFile, lineStartIndex);
|
|
37
|
+
const lineAfter = getLine(sourceFile, lineStartIndex + 1);
|
|
38
|
+
const highlightedLine =
|
|
39
|
+
''
|
|
40
|
+
.padStart(node.getStart() - lineStarts[lineStartIndex], ' ')
|
|
41
|
+
.padEnd(node.getStart() - lineStarts[lineStartIndex] + node.getWidth(), '=') + '\n';
|
|
42
|
+
|
|
43
|
+
/** This should look something like:
|
|
44
|
+
* ```
|
|
45
|
+
* const styles = createStyles({
|
|
46
|
+
* fontSize: fontSize
|
|
47
|
+
* ========
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
const fullContext = lineBefore + lineCurrent + highlightedLine + lineAfter;
|
|
52
|
+
|
|
53
|
+
const character = node.getStart() - lineStarts[lineStartIndex];
|
|
54
|
+
return `File: ${sourceFile.fileName}:${line + 1}:${character}.\n${fullContext}\nOriginal File: ${
|
|
55
|
+
context.fileName
|
|
56
|
+
}`;
|
|
57
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Looks for a variable value that doesn't include a fallback and automatically adds one if found in
|
|
3
|
+
* the current cache of names. This allows fallbacks to be automatically included in environments
|
|
4
|
+
* without the names defined. This is most useful for Storybook or other sandboxes that may not have
|
|
5
|
+
* CSS Variables defined. The fallbacks will allow the UI to look correct without additional setup.
|
|
6
|
+
* Fallbacks come from the `fallbackFiles` transform configuration.
|
|
7
|
+
*/
|
|
8
|
+
export function getFallbackVariable(
|
|
9
|
+
variableName: string,
|
|
10
|
+
names: Record<string, string>
|
|
11
|
+
): string | undefined {
|
|
12
|
+
const variable = variableName.includes('var(') ? variableName : names[variableName];
|
|
13
|
+
if (variable && variable.includes('var(')) {
|
|
14
|
+
return variable.replace(
|
|
15
|
+
/(var\(([A-Za-z0-9\-_]+)\))/,
|
|
16
|
+
(
|
|
17
|
+
/** matched substring "var(--var-name)" */ _,
|
|
18
|
+
/** the full match of the first group "var(--var-name)" */ varMatch,
|
|
19
|
+
/** the variable name - match of the second group "--var-name" */ cssVarName
|
|
20
|
+
) => {
|
|
21
|
+
const value = names[cssVarName];
|
|
22
|
+
if (value && value.startsWith('var')) {
|
|
23
|
+
return getFallbackVariable(value, names);
|
|
24
|
+
}
|
|
25
|
+
return value || varMatch;
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
if (variable) {
|
|
30
|
+
return variable;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
|
|
4
|
+
import {TransformerContext} from './types';
|
|
5
|
+
|
|
6
|
+
export function getHash(node: ts.Node, context: TransformerContext) {
|
|
7
|
+
const fileName = context.getFileName(node.getSourceFile().fileName);
|
|
8
|
+
return crypto
|
|
9
|
+
.createHash('md5')
|
|
10
|
+
.update(fileName + node.pos) // file name + position should be unique and repeatable
|
|
11
|
+
.digest('hex')
|
|
12
|
+
.substring(0, 6);
|
|
13
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This function returns a calculated name of a node by walking up the AST and looking for nodes
|
|
5
|
+
* with a `name` property that has an `Identifier` node type. The result is dash-case. This is
|
|
6
|
+
* useful for automatically generating variable names based on a TS file.
|
|
7
|
+
*
|
|
8
|
+
* In the following example, the `baz` node would have a name of `foo-bar-baz`.
|
|
9
|
+
* ```ts
|
|
10
|
+
* const foo = {
|
|
11
|
+
* bar: {
|
|
12
|
+
* baz: ''
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function getVarName(node: ts.Node, parts: string[] = []): string {
|
|
18
|
+
// base case. Join all the parts
|
|
19
|
+
if (!node.parent || node.kind === ts.SyntaxKind.VariableStatement) {
|
|
20
|
+
return parts.join('.');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Any node with a `name` property that is an identifier can add to the var name
|
|
24
|
+
if (
|
|
25
|
+
(node as any).name &&
|
|
26
|
+
(ts.isIdentifier((node as any).name) || ts.isStringLiteral((node as any).name))
|
|
27
|
+
) {
|
|
28
|
+
return getVarName(node.parent, [(node as any).name.text, ...parts]);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return getVarName(node.parent, parts);
|
|
32
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
import {calc} from '@workday/canvas-kit-styling';
|
|
4
|
+
import {createPropertyTransform} from '../createPropertyTransform';
|
|
5
|
+
import {parseNodeToStaticValue} from './parseNodeToStaticValue';
|
|
6
|
+
|
|
7
|
+
export const handleCalc = createPropertyTransform((node, context) => {
|
|
8
|
+
if (
|
|
9
|
+
ts.isCallExpression(node) &&
|
|
10
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
11
|
+
ts.isIdentifier(node.expression.expression) &&
|
|
12
|
+
node.expression.expression.text === 'calc' &&
|
|
13
|
+
ts.isIdentifier(node.expression.name)
|
|
14
|
+
) {
|
|
15
|
+
function toStaticValue(node: ts.Node) {
|
|
16
|
+
return parseNodeToStaticValue(node, context);
|
|
17
|
+
}
|
|
18
|
+
const args = node.arguments;
|
|
19
|
+
const method = node.expression.name.text;
|
|
20
|
+
|
|
21
|
+
if (method === 'add' || method === 'subtract') {
|
|
22
|
+
return calc[method](toStaticValue(args[0]).toString(), toStaticValue(args[1]).toString());
|
|
23
|
+
}
|
|
24
|
+
if (method === 'multiply' || method === 'divide') {
|
|
25
|
+
return calc[method](toStaticValue(args[0]).toString(), toStaticValue(args[1]));
|
|
26
|
+
}
|
|
27
|
+
if (method === 'negate') {
|
|
28
|
+
return calc.negate(toStaticValue(args[0]).toString());
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return;
|
|
33
|
+
});
|