Skip to content

Commit b441a48

Browse files
authored
Merge pull request #11 from Jackardios/fix-issue-5
fix: at-rule is not converted if base rule is not defined
2 parents e417b51 + d504c3b commit b441a48

11 files changed

+665
-818
lines changed

src/TailwindConverter.ts

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ import {
2323
import {
2424
convertDeclarationValue,
2525
prepareArbitraryValue,
26-
TAILWIND_DECLARATION_CONVERTERS,
27-
} from './constants/converters';
26+
DECLARATION_CONVERTERS_MAPPING,
27+
} from './mappings/declaration-converters-mapping';
2828
import { isChildNode } from './utils/isChildNode';
29-
import { MEDIA_PARAMS_MAPPING } from './constants/media-params-mapping';
29+
import { MEDIA_PARAMS_MAPPING } from './mappings/media-params-mapping';
3030
import { removeUnnecessarySpaces } from './utils/removeUnnecessarySpaces';
3131
import { reduceTailwindClasses } from './utils/reduceTailwindClasses';
32-
import { PSEUDOS_MAPPING } from './constants/pseudos-mapping';
32+
import { PSEUDOS_MAPPING } from './mappings/pseudos-mapping';
3333
import { detectIndent } from './utils/detectIndent';
3434
import { resolveConfig, ResolvedTailwindConfig } from './utils/resolveConfig';
3535

@@ -91,12 +91,14 @@ export class TailwindConverter {
9191

9292
const nodes = nodesManager.getNodes();
9393
nodes.forEach(node => {
94-
node.rule.prepend(
95-
new AtRule({
96-
name: 'apply',
97-
params: node.tailwindClasses.join(' '),
98-
})
99-
);
94+
if (node.tailwindClasses.length) {
95+
node.rule.prepend(
96+
new AtRule({
97+
name: 'apply',
98+
params: node.tailwindClasses.join(' '),
99+
})
100+
);
101+
}
100102
});
101103

102104
this.cleanRaws(parsed.root);
@@ -158,7 +160,7 @@ export class TailwindConverter {
158160

159161
protected convertDeclarationToClasses(declaration: Declaration) {
160162
let classes =
161-
TAILWIND_DECLARATION_CONVERTERS[declaration.prop]?.(
163+
DECLARATION_CONVERTERS_MAPPING[declaration.prop]?.(
162164
declaration,
163165
this.config
164166
) || [];
@@ -178,24 +180,29 @@ export class TailwindConverter {
178180
): TailwindNode {
179181
let { baseSelector, classPrefix } = this.parseSelector(rule.selector);
180182

181-
const containerClassPrefix = this.convertContainerToClassPrefix(
183+
const classPrefixByParentNodes = this.convertContainerToClassPrefix(
182184
rule.parent
183185
);
184186

185-
if (containerClassPrefix) {
187+
if (classPrefixByParentNodes) {
186188
return {
187189
key: baseSelector,
188-
fallbackRule: rule,
189-
classesPrefixWhenFound: containerClassPrefix + classPrefix,
190+
rootRuleSelector: baseSelector,
191+
originalRule: rule,
192+
classesPrefix: classPrefixByParentNodes + classPrefix,
190193
tailwindClasses,
191194
};
192195
}
193196

194197
if (classPrefix) {
198+
const key = TailwindNodesManager.convertRuleToKey(rule, baseSelector);
199+
const isRootRule = key === baseSelector;
200+
195201
return {
196-
key: TailwindNodesManager.convertRuleToKey(rule, baseSelector),
197-
fallbackRule: rule,
198-
classesPrefixWhenFound: classPrefix,
202+
key: key,
203+
rootRuleSelector: isRootRule ? baseSelector : null,
204+
originalRule: rule,
205+
classesPrefix: classPrefix,
199206
tailwindClasses,
200207
};
201208
}

src/TailwindNodesManager.ts

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { AtRule, Rule } from 'postcss';
1+
import { type AtRule, type Node, Rule, ChildNode } from 'postcss';
22
import { isAtRuleNode } from './utils/isAtRuleNode';
33
import { isChildNode } from './utils/isChildNode';
44

@@ -9,8 +9,9 @@ export interface ResolvedTailwindNode {
99

1010
export interface UnresolvedTailwindNode {
1111
key: string;
12-
fallbackRule: Rule;
13-
classesPrefixWhenFound: string;
12+
rootRuleSelector?: string | null;
13+
originalRule: Rule;
14+
classesPrefix: string;
1415
tailwindClasses: string[];
1516
}
1617

@@ -40,33 +41,48 @@ export class TailwindNodesManager {
4041

4142
mergeNode(node: TailwindNode) {
4243
const nodeIsResolved = isResolvedTailwindNode(node);
43-
const key = nodeIsResolved
44+
const nodeKey = nodeIsResolved
4445
? TailwindNodesManager.convertRuleToKey(node.rule)
4546
: node.key;
46-
const foundNode = this.nodesMap.get(key);
47+
const foundNode = this.nodesMap.get(nodeKey);
48+
49+
if (foundNode) {
50+
foundNode.tailwindClasses = foundNode.tailwindClasses.concat(
51+
nodeIsResolved
52+
? node.tailwindClasses
53+
: node.tailwindClasses.map(
54+
className => `${node.classesPrefix}${className}`
55+
)
56+
);
4757

48-
if (!foundNode) {
49-
if (nodeIsResolved) {
50-
this.nodesMap.set(key, node);
51-
} else {
52-
this.nodesMap.set(
53-
TailwindNodesManager.convertRuleToKey(node.fallbackRule),
54-
{
55-
rule: node.fallbackRule,
56-
tailwindClasses: node.tailwindClasses,
57-
}
58-
);
59-
}
6058
return;
6159
}
6260

63-
foundNode.tailwindClasses = foundNode.tailwindClasses.concat(
64-
nodeIsResolved
65-
? node.tailwindClasses
66-
: node.tailwindClasses.map(
67-
className => `${node.classesPrefixWhenFound}${className}`
68-
)
69-
);
61+
if (nodeIsResolved) {
62+
this.nodesMap.set(nodeKey, node);
63+
} else {
64+
let rule;
65+
66+
if (node.rootRuleSelector) {
67+
rule = new Rule({
68+
selector: node.rootRuleSelector,
69+
});
70+
71+
const rootChild = this.upToRootChild(node.originalRule);
72+
if (rootChild) {
73+
node.originalRule.root().insertBefore(rootChild, rule);
74+
}
75+
} else {
76+
rule = node.originalRule;
77+
}
78+
79+
this.nodesMap.set(nodeKey, {
80+
rule,
81+
tailwindClasses: node.tailwindClasses.map(
82+
className => `${node.classesPrefix}${className}`
83+
),
84+
});
85+
}
7086
}
7187

7288
mergeNodes(nodes: TailwindNode[]) {
@@ -87,6 +103,21 @@ export class TailwindNodesManager {
87103
return Array.from(this.nodesMap.values());
88104
}
89105

106+
protected upToRootChild(node: Node) {
107+
let childNode: ChildNode | null = null;
108+
109+
while (
110+
node.parent &&
111+
node.parent.type !== 'root' &&
112+
isChildNode(node.parent)
113+
) {
114+
childNode = node = node.parent;
115+
continue;
116+
}
117+
118+
return childNode;
119+
}
120+
90121
static convertRuleToKey(
91122
rule: Rule,
92123
overriddenSelector: string | null = null

src/constants/converters.ts renamed to src/mappings/declaration-converters-mapping.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,16 @@ export function convertComposedSpacingDeclarationValue(
203203
return classes;
204204
}
205205

206-
interface TailwindDeclarationConverters {
207-
[property: string]: (
208-
declaration: Declaration,
209-
config: ResolvedTailwindConverterConfig
210-
) => string[];
206+
type DeclarationConverter = (
207+
declaration: Declaration,
208+
config: ResolvedTailwindConverterConfig
209+
) => string[];
210+
211+
interface DeclarationConvertersMapping {
212+
[property: string]: DeclarationConverter;
211213
}
212214

213-
export const TAILWIND_DECLARATION_CONVERTERS: TailwindDeclarationConverters = {
215+
export const DECLARATION_CONVERTERS_MAPPING: DeclarationConvertersMapping = {
214216
'accent-color': (declaration, config) =>
215217
config.tailwindConfig.corePlugins.accentColor
216218
? convertColorDeclarationValue(

0 commit comments

Comments
 (0)