/
styled.ts
83 lines (69 loc) · 2.23 KB
/
styled.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import type { SourceLocation } from '@babel/types';
import { debug } from '@linaria/logger';
import type { IProps } from '@linaria/react/processors/styled';
import StyledProcessor from '@linaria/react/processors/styled';
import type { Rules, ValueCache } from '@linaria/tags';
import { hasMeta } from '@linaria/utils';
import atomize from './helpers/atomize';
export default class AtomicStyledProcessor extends StyledProcessor {
#classes: string | undefined;
private get classes(): string {
if (this.#classes) {
return this.#classes;
}
throw new Error(
'Styles are not extracted yet. Please call `extractRules` first.'
);
}
public override extractRules(
valueCache: ValueCache,
cssText: string,
loc?: SourceLocation | null
): Rules {
const rules: Rules = {};
const wrappedValue =
typeof this.component === 'string'
? null
: valueCache.get(this.component.node.name);
const atomicRules = atomize(cssText, hasMeta(wrappedValue));
atomicRules.forEach((rule) => {
// eslint-disable-next-line no-param-reassign
rules[rule.cssText] = {
cssText: rule.cssText,
start: loc?.start ?? null,
className: this.className,
displayName: this.displayName,
atom: true,
};
debug(
'evaluator:template-processor:extracted-atomic-rule',
`\n${rule.cssText}`
);
});
this.#classes = atomicRules
// Some atomic rules produced (eg. keyframes) don't have class names, and they also don't need to appear in the object
.filter((rule) => !!rule.className)
.map((rule) => rule.className!)
.join(' ');
return rules;
}
protected override getProps(): IProps {
const props = super.getProps();
props.class = [this.classes, this.className].filter(Boolean).join(' ');
props.atomic = true;
return props;
}
protected override getVariableId(
source: string,
unit: string,
precedingCss: string
): string {
const id = this.getCustomVariableId(source, unit, precedingCss);
if (id) {
return id;
}
const context = this.getVariableContext(source, unit, precedingCss);
// id is based on the slugified value
return context.valueSlug;
}
}