@terrazzo/plugin-css 0.0.2 → 0.0.4
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/README.md +5 -0
- package/dist/build.d.ts +8 -0
- package/dist/build.js +94 -0
- package/dist/build.js.map +1 -0
- package/dist/index.d.ts +2 -20
- package/dist/index.js +7 -259
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +31 -0
- package/dist/lib.js +64 -0
- package/dist/lib.js.map +1 -0
- package/dist/transform.d.ts +8 -0
- package/dist/transform.js +199 -0
- package/dist/transform.js.map +1 -0
- package/package.json +6 -6
- package/src/build.ts +108 -0
- package/src/index.ts +10 -305
- package/src/lib.ts +106 -0
- package/src/transform.ts +227 -0
package/src/lib.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export const FORMAT_ID = 'css';
|
|
2
|
+
|
|
3
|
+
export const FILE_PREFIX = `/* -------------------------------------------
|
|
4
|
+
* Autogenerated by ⛋ Terrazzo. DO NOT EDIT!
|
|
5
|
+
* ------------------------------------------- */`;
|
|
6
|
+
|
|
7
|
+
export interface CSSPluginOptions {
|
|
8
|
+
/** Where to output CSS */
|
|
9
|
+
filename?: string;
|
|
10
|
+
/** Glob patterns to exclude tokens from output */
|
|
11
|
+
exclude?: string[];
|
|
12
|
+
/** Define mode selectors as media queries or CSS classes */
|
|
13
|
+
modeSelectors?: ModeSelector[];
|
|
14
|
+
/** Control the final CSS variable name */
|
|
15
|
+
variableName?: (name: string) => string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ModeSelector {
|
|
19
|
+
/** The name of the mode to match */
|
|
20
|
+
mode: string;
|
|
21
|
+
/** (optional) Provide token IDs to match. Globs are allowed (e.g: `["color.*", "shadow.dark"]`) */
|
|
22
|
+
tokens?: string[];
|
|
23
|
+
/** Provide CSS selectors to generate. (e.g.: `["@media (prefers-color-scheme: dark)", "[data-color-theme='dark']"]` ) */
|
|
24
|
+
selectors: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// note: this is NOT an adequate replacement for a CSS AST; this just performs
|
|
28
|
+
// basic deduplication and allows some limited parsing/reformatting before
|
|
29
|
+
// flattening to a CSS string.
|
|
30
|
+
export interface CSSRule {
|
|
31
|
+
selectors: string[];
|
|
32
|
+
nestedQuery?: string;
|
|
33
|
+
declarations: Record<string, string>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Convert CSSRules into a formatted, indented CSS string */
|
|
37
|
+
export function printRules(rules: CSSRule[]): string {
|
|
38
|
+
const output: string[] = [];
|
|
39
|
+
for (const rule of rules) {
|
|
40
|
+
if (!rule.selectors.length || !Object.keys(rule.declarations).length) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const mqSelectors: string[] = [];
|
|
45
|
+
const joinableSelectors: string[] = [];
|
|
46
|
+
for (const s of rule.selectors) {
|
|
47
|
+
(s.startsWith('@') ? mqSelectors : joinableSelectors).push(s);
|
|
48
|
+
}
|
|
49
|
+
// @media-query selectors get pushed individually
|
|
50
|
+
for (const s of mqSelectors) {
|
|
51
|
+
output.push(_printRule({ ...rule, selectors: [s] }));
|
|
52
|
+
}
|
|
53
|
+
// all other selectors get joined as one
|
|
54
|
+
if (joinableSelectors.length) {
|
|
55
|
+
output.push(_printRule({ ...rule, selectors: joinableSelectors }));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return output.join('\n\n');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function _printRule(rule: CSSRule): string {
|
|
62
|
+
const output: string[] = [];
|
|
63
|
+
const isMediaQuery = rule.selectors.some((s) => s.startsWith('@'));
|
|
64
|
+
let indent = '';
|
|
65
|
+
|
|
66
|
+
// if both levels are media queries, preserve order
|
|
67
|
+
if (rule.nestedQuery && isMediaQuery) {
|
|
68
|
+
output.push(`${indent}${rule.selectors.join(`,\n${indent}`)} {`);
|
|
69
|
+
indent += ' ';
|
|
70
|
+
output.push(`${indent}${rule.nestedQuery} {`);
|
|
71
|
+
}
|
|
72
|
+
// otherwise if nested query exists but parens aren’t media queries, reverse order (media queries on top)
|
|
73
|
+
else if (rule.nestedQuery && !isMediaQuery) {
|
|
74
|
+
output.push(`${indent}${rule.nestedQuery} {`);
|
|
75
|
+
indent += ' ';
|
|
76
|
+
output.push(`${indent}${rule.selectors.join(`,\n${indent}`)} {`);
|
|
77
|
+
}
|
|
78
|
+
// if no media queries, just print selectors
|
|
79
|
+
else {
|
|
80
|
+
output.push(`${indent}${rule.selectors.join(`,\n${indent}`)} {`);
|
|
81
|
+
}
|
|
82
|
+
indent += ' ';
|
|
83
|
+
|
|
84
|
+
// note: this is ONLY dependent on whether the top level is a media query (ignores nestedQuery)
|
|
85
|
+
if (isMediaQuery) {
|
|
86
|
+
output.push(`${indent}:root {`);
|
|
87
|
+
indent += ' ';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
for (const [k, v] of Object.entries(rule.declarations)) {
|
|
91
|
+
output.push(`${indent}${k}: ${v};`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// base closing brackets on indent level
|
|
95
|
+
while (indent !== '') {
|
|
96
|
+
indent = indent.substring(0, indent.length - 2);
|
|
97
|
+
output.push(`${indent}}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return output.join('\n');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface GetRuleOptions {
|
|
104
|
+
/** Combine a selector with parent selectors (e.g. if adding a @media-query within another selector list) */
|
|
105
|
+
parentSelectors?: string[];
|
|
106
|
+
}
|
package/src/transform.ts
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import type { TokenNormalized, TransformHookOptions } from '@terrazzo/parser';
|
|
2
|
+
import {
|
|
3
|
+
transformBooleanValue,
|
|
4
|
+
transformBorderValue,
|
|
5
|
+
transformColorValue,
|
|
6
|
+
transformCubicBezierValue,
|
|
7
|
+
transformDimensionValue,
|
|
8
|
+
transformDurationValue,
|
|
9
|
+
transformFontFamilyValue,
|
|
10
|
+
transformFontWeightValue,
|
|
11
|
+
transformGradientValue,
|
|
12
|
+
transformLinkValue,
|
|
13
|
+
transformNumberValue,
|
|
14
|
+
transformShadowValue,
|
|
15
|
+
transformStringValue,
|
|
16
|
+
transformStrokeStyleValue,
|
|
17
|
+
transformTransitionValue,
|
|
18
|
+
transformTypographyValue,
|
|
19
|
+
} from '@terrazzo/token-tools/css';
|
|
20
|
+
import { FORMAT_ID } from './lib.js';
|
|
21
|
+
|
|
22
|
+
export interface TransformValueOptions {
|
|
23
|
+
transformAlias: (id: string) => string;
|
|
24
|
+
id: string;
|
|
25
|
+
localID: string;
|
|
26
|
+
setTransform: TransformHookOptions['setTransform'];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default function transformValue(
|
|
30
|
+
token: TokenNormalized,
|
|
31
|
+
{ id, localID, transformAlias, setTransform }: TransformValueOptions,
|
|
32
|
+
): void {
|
|
33
|
+
switch (token.$type) {
|
|
34
|
+
case 'boolean': {
|
|
35
|
+
for (const mode in token.mode) {
|
|
36
|
+
const { $value, aliasOf } = token.mode[mode]!;
|
|
37
|
+
setTransform(id, {
|
|
38
|
+
format: FORMAT_ID,
|
|
39
|
+
localID,
|
|
40
|
+
value: transformBooleanValue($value, { aliasOf, transformAlias }),
|
|
41
|
+
mode,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
case 'border': {
|
|
47
|
+
for (const mode in token.mode) {
|
|
48
|
+
const { $value, aliasOf, partialAliasOf } = token.mode[mode]!;
|
|
49
|
+
setTransform(id, {
|
|
50
|
+
format: FORMAT_ID,
|
|
51
|
+
localID,
|
|
52
|
+
value: transformBorderValue($value, { aliasOf, partialAliasOf, transformAlias }),
|
|
53
|
+
mode,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case 'color': {
|
|
59
|
+
for (const mode in token.mode) {
|
|
60
|
+
const { $value, aliasOf } = token.mode[mode]!;
|
|
61
|
+
setTransform(id, {
|
|
62
|
+
format: FORMAT_ID,
|
|
63
|
+
localID,
|
|
64
|
+
value: transformColorValue($value, { aliasOf, transformAlias }),
|
|
65
|
+
mode,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case 'cubicBezier': {
|
|
71
|
+
for (const mode in token.mode) {
|
|
72
|
+
const { $value, aliasOf, partialAliasOf } = token.mode[mode]!;
|
|
73
|
+
setTransform(id, {
|
|
74
|
+
format: FORMAT_ID,
|
|
75
|
+
localID,
|
|
76
|
+
value: transformCubicBezierValue($value, { aliasOf, partialAliasOf, transformAlias }),
|
|
77
|
+
mode,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case 'dimension': {
|
|
83
|
+
for (const mode in token.mode) {
|
|
84
|
+
const { $value, aliasOf } = token.mode[mode]!;
|
|
85
|
+
setTransform(id, {
|
|
86
|
+
format: FORMAT_ID,
|
|
87
|
+
localID,
|
|
88
|
+
value: transformDimensionValue($value, { aliasOf, transformAlias }),
|
|
89
|
+
mode,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case 'duration': {
|
|
95
|
+
for (const mode in token.mode) {
|
|
96
|
+
const { $value, aliasOf } = token.mode[mode]!;
|
|
97
|
+
setTransform(id, {
|
|
98
|
+
format: FORMAT_ID,
|
|
99
|
+
localID,
|
|
100
|
+
value: transformDurationValue($value, { aliasOf, transformAlias }),
|
|
101
|
+
mode,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
case 'fontFamily': {
|
|
107
|
+
for (const mode in token.mode) {
|
|
108
|
+
const { $value, aliasOf, partialAliasOf } = token.mode[mode]!;
|
|
109
|
+
setTransform(id, {
|
|
110
|
+
format: FORMAT_ID,
|
|
111
|
+
localID,
|
|
112
|
+
value: transformFontFamilyValue($value, { aliasOf, partialAliasOf, transformAlias }),
|
|
113
|
+
mode,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case 'fontWeight': {
|
|
119
|
+
for (const mode in token.mode) {
|
|
120
|
+
const { $value, aliasOf } = token.mode[mode]!;
|
|
121
|
+
setTransform(id, {
|
|
122
|
+
format: FORMAT_ID,
|
|
123
|
+
localID,
|
|
124
|
+
value: transformFontWeightValue($value, { aliasOf, transformAlias }),
|
|
125
|
+
mode,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
case 'gradient': {
|
|
131
|
+
for (const mode in token.mode) {
|
|
132
|
+
const { $value, aliasOf, partialAliasOf } = token.mode[mode]!;
|
|
133
|
+
setTransform(id, {
|
|
134
|
+
format: FORMAT_ID,
|
|
135
|
+
localID,
|
|
136
|
+
value: transformGradientValue($value, { aliasOf, partialAliasOf, transformAlias }),
|
|
137
|
+
mode,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
case 'link': {
|
|
143
|
+
for (const mode in token.mode) {
|
|
144
|
+
const { $value, aliasOf } = token.mode[mode]!;
|
|
145
|
+
setTransform(id, {
|
|
146
|
+
format: FORMAT_ID,
|
|
147
|
+
localID,
|
|
148
|
+
value: transformLinkValue($value, { aliasOf, transformAlias }),
|
|
149
|
+
mode,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case 'number': {
|
|
155
|
+
for (const mode in token.mode) {
|
|
156
|
+
const { $value, aliasOf } = token.mode[mode]!;
|
|
157
|
+
setTransform(id, {
|
|
158
|
+
format: FORMAT_ID,
|
|
159
|
+
localID,
|
|
160
|
+
value: transformNumberValue($value, { aliasOf, transformAlias }),
|
|
161
|
+
mode,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case 'shadow': {
|
|
167
|
+
for (const mode in token.mode) {
|
|
168
|
+
const { $value, aliasOf, partialAliasOf } = token.mode[mode]!;
|
|
169
|
+
setTransform(id, {
|
|
170
|
+
format: FORMAT_ID,
|
|
171
|
+
localID,
|
|
172
|
+
value: transformShadowValue($value, { aliasOf, partialAliasOf, transformAlias }),
|
|
173
|
+
mode,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case 'string': {
|
|
179
|
+
for (const mode in token.mode) {
|
|
180
|
+
const { $value, aliasOf } = token.mode[mode]!;
|
|
181
|
+
setTransform(id, {
|
|
182
|
+
format: FORMAT_ID,
|
|
183
|
+
localID,
|
|
184
|
+
value: transformStringValue($value, { aliasOf, transformAlias }),
|
|
185
|
+
mode,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
case 'strokeStyle': {
|
|
191
|
+
for (const mode in token.mode) {
|
|
192
|
+
const { $value, aliasOf } = token.mode[mode]!;
|
|
193
|
+
setTransform(id, {
|
|
194
|
+
format: FORMAT_ID,
|
|
195
|
+
localID,
|
|
196
|
+
value: transformStrokeStyleValue($value, { aliasOf, transformAlias }),
|
|
197
|
+
mode,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
case 'transition': {
|
|
203
|
+
for (const mode in token.mode) {
|
|
204
|
+
const { $value, aliasOf, partialAliasOf } = token.mode[mode]!;
|
|
205
|
+
setTransform(id, {
|
|
206
|
+
format: FORMAT_ID,
|
|
207
|
+
localID,
|
|
208
|
+
value: transformTransitionValue($value, { aliasOf, partialAliasOf, transformAlias }),
|
|
209
|
+
mode,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
case 'typography': {
|
|
215
|
+
for (const mode in token.mode) {
|
|
216
|
+
const { $value, aliasOf, partialAliasOf } = token.mode[mode]!;
|
|
217
|
+
setTransform(id, {
|
|
218
|
+
format: FORMAT_ID,
|
|
219
|
+
localID,
|
|
220
|
+
value: transformTypographyValue($value, { aliasOf, partialAliasOf, transformAlias }),
|
|
221
|
+
mode,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|