esm-styles 0.2.1 → 0.2.3
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 +25 -19
- package/dist/lib/build.js +4 -1
- package/dist/lib/index.js +4 -7
- package/dist/lib/utils/content.js +25 -5
- package/dist/lib/utils/index.d.ts +1 -0
- package/dist/lib/utils/index.js +1 -0
- package/dist/lib/utils/selector.js +17 -1
- package/dist/lib/utils/to-css-value.d.ts +1 -0
- package/dist/lib/utils/to-css-value.js +15 -0
- package/doc/usage-guide.md +8 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -133,11 +133,12 @@ export default {
|
|
|
133
133
|
},
|
|
134
134
|
},
|
|
135
135
|
|
|
136
|
-
// Media query shorthands
|
|
136
|
+
// Media query shorthands (in addition to media.device and media.theme names)
|
|
137
137
|
mediaQueries: {
|
|
138
|
-
|
|
139
|
-
tablet: '(
|
|
140
|
-
|
|
138
|
+
'min-tablet': '(min-width: 768px)',
|
|
139
|
+
'max-tablet': '(max-width: 1024px)',
|
|
140
|
+
hover: '(hover: hover)',
|
|
141
|
+
// ...whatever you want
|
|
141
142
|
},
|
|
142
143
|
}
|
|
143
144
|
```
|
|
@@ -184,16 +185,18 @@ p strong {
|
|
|
184
185
|
|
|
185
186
|
```js
|
|
186
187
|
{
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
188
|
+
div: {
|
|
189
|
+
highlighted: {
|
|
190
|
+
// highlighted is not a tag
|
|
191
|
+
border: '1px solid red',
|
|
192
|
+
},
|
|
193
|
+
p: {
|
|
194
|
+
// p is a tag
|
|
195
|
+
fontSize: '16px',
|
|
196
|
+
},
|
|
197
|
+
_video: {
|
|
198
|
+
// video is a tag, but the class is meant, use single underscore prefix
|
|
199
|
+
aspectRatio: 1.77,
|
|
197
200
|
}
|
|
198
201
|
}
|
|
199
202
|
}
|
|
@@ -202,13 +205,16 @@ p strong {
|
|
|
202
205
|
Compiles to:
|
|
203
206
|
|
|
204
207
|
```css
|
|
205
|
-
.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
+
div.highlighted {
|
|
209
|
+
border: 1px solid red;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
div p {
|
|
213
|
+
font-size: 16px;
|
|
208
214
|
}
|
|
209
215
|
|
|
210
|
-
|
|
211
|
-
|
|
216
|
+
div.video {
|
|
217
|
+
aspect-ratio: 1.77;
|
|
212
218
|
}
|
|
213
219
|
```
|
|
214
220
|
|
package/dist/lib/build.js
CHANGED
|
@@ -123,7 +123,10 @@ export async function build(configPath = 'esm-styles.config.js') {
|
|
|
123
123
|
if (key === '') {
|
|
124
124
|
// Only possible at non-root
|
|
125
125
|
const varName = '--' + path.map((k) => k.replace(/_/g, '-')).join('-');
|
|
126
|
-
const leaf = {
|
|
126
|
+
const leaf = {
|
|
127
|
+
var: `var(${varName})`,
|
|
128
|
+
name: varName,
|
|
129
|
+
};
|
|
127
130
|
for (let i = 0; i < sets.length; i++) {
|
|
128
131
|
const v = path.length === 0
|
|
129
132
|
? mergedSets[sets[i]]
|
package/dist/lib/index.js
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import * as utils from './utils/index.js';
|
|
2
|
+
import { toCssValue } from './utils/to-css-value.js';
|
|
2
3
|
function flatWalk(obj, selectorPath = [], result = { rules: [], media: {}, layers: {} }, options = {}, currentMedia = []) {
|
|
3
4
|
const props = {};
|
|
4
5
|
for (const key in obj) {
|
|
5
6
|
const value = obj[key];
|
|
6
7
|
if (utils.isEndValue(value)) {
|
|
7
8
|
const cssKey = utils.jsKeyToCssKey(key);
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
'var' in value &&
|
|
11
|
-
typeof value.var === 'string') {
|
|
12
|
-
// Use CSS variable reference
|
|
13
|
-
props[cssKey] = `var(${value.var})`;
|
|
9
|
+
if (cssKey === 'content') {
|
|
10
|
+
props[cssKey] = utils.contentValue(toCssValue(value));
|
|
14
11
|
}
|
|
15
12
|
else {
|
|
16
|
-
props[cssKey] =
|
|
13
|
+
props[cssKey] = toCssValue(value);
|
|
17
14
|
}
|
|
18
15
|
}
|
|
19
16
|
else if (typeof value === 'object' && value !== null) {
|
|
@@ -1,13 +1,33 @@
|
|
|
1
|
+
const keywords = [
|
|
2
|
+
'normal',
|
|
3
|
+
'none',
|
|
4
|
+
'open-quote',
|
|
5
|
+
'close-quote',
|
|
6
|
+
'no-open-quote',
|
|
7
|
+
'no-close-quote',
|
|
8
|
+
'inherit',
|
|
9
|
+
'initial',
|
|
10
|
+
'revert',
|
|
11
|
+
'revert-layer',
|
|
12
|
+
'unset',
|
|
13
|
+
];
|
|
1
14
|
export const contentValue = (value) => {
|
|
2
15
|
if (typeof value !== 'string')
|
|
3
16
|
return value;
|
|
4
|
-
|
|
5
|
-
|
|
17
|
+
if (keywords.some((keyword) => {
|
|
18
|
+
const regex = new RegExp(`\\b${keyword}\\b`);
|
|
19
|
+
return regex.test(value);
|
|
20
|
+
}))
|
|
6
21
|
return value;
|
|
7
|
-
// If
|
|
8
|
-
if (
|
|
22
|
+
// If already contains quoted values, return as is
|
|
23
|
+
if (/'.*'/.test(value) || /".*"/.test(value))
|
|
9
24
|
return value;
|
|
10
|
-
|
|
25
|
+
// If contains functions, return as is
|
|
26
|
+
if (/[a-z]+\(.*\)/i.test(value))
|
|
27
|
+
return value; // url(...), attr(...), etc.
|
|
28
|
+
// If all characters are printable ASCII, wrap in single quotes
|
|
29
|
+
if (/^[\x20-\x7E]*$/.test(value))
|
|
30
|
+
return `'${value}'`;
|
|
11
31
|
// Otherwise, convert each character to CSS unicode escape: \00xxxx
|
|
12
32
|
const unicode = value
|
|
13
33
|
.split('')
|
package/dist/lib/utils/index.js
CHANGED
|
@@ -195,7 +195,16 @@ export const joinSelectorPath = (path) => {
|
|
|
195
195
|
return acc + (acc ? ' ' : '') + '.' + part.slice(2);
|
|
196
196
|
}
|
|
197
197
|
else if (part.startsWith('_')) {
|
|
198
|
-
|
|
198
|
+
// Attach class directly to previous part unless prev is combinator or root
|
|
199
|
+
const combinators = ['>', '+', '~'];
|
|
200
|
+
const isPrevCombinator = prev && combinators.some((c) => prev.startsWith(c));
|
|
201
|
+
if (isPrevRoot || isPrevCombinator || !acc) {
|
|
202
|
+
return acc + (acc ? ' ' : '') + '.' + part.slice(1);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
// Attach directly (no space)
|
|
206
|
+
return acc + '.' + part.slice(1);
|
|
207
|
+
}
|
|
199
208
|
}
|
|
200
209
|
else if (part.startsWith('>') ||
|
|
201
210
|
part.startsWith('+') ||
|
|
@@ -224,6 +233,13 @@ export const joinSelectorPath = (path) => {
|
|
|
224
233
|
return acc + (acc ? ' ' : '') + match[1] + '.' + match[2];
|
|
225
234
|
}
|
|
226
235
|
}
|
|
236
|
+
else if (/^([a-z][a-z0-9]*)#([\w-]+)$/.test(part)) {
|
|
237
|
+
// If part matches 'tag#id' and tag is an HTML tag
|
|
238
|
+
const match = part.match(/^([a-z][a-z0-9]*)#([\w-]+)$/);
|
|
239
|
+
if (match && isHtmlTag(match[1])) {
|
|
240
|
+
return acc + (acc ? ' ' : '') + match[1] + '#' + match[2];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
227
243
|
// Not a tag, not a special selector: treat as class or custom element
|
|
228
244
|
// If previous part is a root selector, insert a space
|
|
229
245
|
if (isPrevRoot) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function toCssValue(value: any): string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Utility to convert a value to a CSS string, handling arrays, objects with 'var', and primitives
|
|
2
|
+
export function toCssValue(value) {
|
|
3
|
+
if (Array.isArray(value)) {
|
|
4
|
+
// Join array parts, recursively converting each
|
|
5
|
+
return value.map(toCssValue).join(' ');
|
|
6
|
+
}
|
|
7
|
+
if (typeof value === 'object' &&
|
|
8
|
+
value !== null &&
|
|
9
|
+
'var' in value &&
|
|
10
|
+
typeof value.var === 'string') {
|
|
11
|
+
return value.var;
|
|
12
|
+
}
|
|
13
|
+
// For primitives (string, number), just return as string
|
|
14
|
+
return String(value);
|
|
15
|
+
}
|
package/doc/usage-guide.md
CHANGED
|
@@ -307,21 +307,9 @@ Use commas to target multiple selectors:
|
|
|
307
307
|
}
|
|
308
308
|
```
|
|
309
309
|
|
|
310
|
-
### T9: Content Property
|
|
311
|
-
|
|
312
|
-
For the `content` property, use JavaScript unicode notation for special characters:
|
|
313
|
-
|
|
314
|
-
```js
|
|
315
|
-
{
|
|
316
|
-
'::before': {
|
|
317
|
-
content: '\u2022', // Bullet character
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
```
|
|
321
|
-
|
|
322
310
|
## Layers
|
|
323
311
|
|
|
324
|
-
|
|
312
|
+
ESM Styles supports @layer directives:
|
|
325
313
|
|
|
326
314
|
```js
|
|
327
315
|
{
|
|
@@ -551,12 +539,14 @@ The build process automatically generates modules like `$theme.mjs`:
|
|
|
551
539
|
export default {
|
|
552
540
|
colors: {
|
|
553
541
|
background: {
|
|
554
|
-
var: '--colors-background',
|
|
542
|
+
var: 'var(--colors-background)',
|
|
543
|
+
name: '--colors-background',
|
|
555
544
|
light: '#ffffff',
|
|
556
545
|
dark: '#121212',
|
|
557
546
|
},
|
|
558
547
|
surface: {
|
|
559
|
-
var: '--colors-surface',
|
|
548
|
+
var: 'var(--colors-surface)',
|
|
549
|
+
name: '--colors-surface',
|
|
560
550
|
light: '#f5f5f5',
|
|
561
551
|
dark: '#222222',
|
|
562
552
|
},
|
|
@@ -575,10 +565,11 @@ import $theme from './$theme.mjs'
|
|
|
575
565
|
|
|
576
566
|
export default {
|
|
577
567
|
button: {
|
|
578
|
-
backgroundColor: $theme.colors.primary,
|
|
568
|
+
backgroundColor: $theme.colors.primary, // automatically replaced with var(--colors-primary) by compiler
|
|
579
569
|
color: $theme.colors.background,
|
|
580
570
|
padding: '10px 20px',
|
|
581
571
|
borderRadius: '4px',
|
|
572
|
+
border: `1px solid ${$theme.colors.surface.var}`, // in case of concatenation, use .var property, otherwise it will be [object Object], sorry
|
|
582
573
|
},
|
|
583
574
|
}
|
|
584
575
|
```
|
|
@@ -591,6 +582,7 @@ button {
|
|
|
591
582
|
color: var(--colors-background);
|
|
592
583
|
padding: 10px 20px;
|
|
593
584
|
border-radius: 4px;
|
|
585
|
+
border: 1px solid var(--colors-surface);
|
|
594
586
|
}
|
|
595
587
|
```
|
|
596
588
|
|