Skip to content

Commit 976e605

Browse files
committed
more fixes
1 parent 55691c9 commit 976e605

10 files changed

+137
-50
lines changed

lib/is-under-scope.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
var log = require('debug')('postcss-css-variables:is-under-scope');
2+
13
var escapeStringRegexp = require('escape-string-regexp');
24

35
var isPieceAlwaysAncestorSelector = require('./is-piece-always-ancestor-selector');
@@ -14,26 +16,34 @@ function getScopeMatchResults(nodeScopeList, scopeNodeScopeList) {
1416
var currentPieceOffset;
1517
var scopePieceIndex;
1618

19+
log('######### getScopeMatchResults', nodeScopeList, scopeNodeScopeList);
20+
1721
// Check each comma separated piece of the complex selector
1822
var doesMatchScope = scopeNodeScopeList.some(function(scopeNodeScopePieces) {
1923
return nodeScopeList.some(function(nodeScopePieces) {
2024

2125
//console.log('sp', scopeNodeScopePieces);
2226
//console.log('np', nodeScopePieces);
2327

28+
log(nodeScopePieces, scopeNodeScopePieces);
29+
2430
currentPieceOffset = null;
2531
var wasEveryPieceFound = true;
2632
for(scopePieceIndex = 0; scopePieceIndex < scopeNodeScopePieces.length; scopePieceIndex++) {
2733
var scopePiece = scopeNodeScopePieces[scopePieceIndex];
2834
var pieceOffset = currentPieceOffset || 0;
2935

36+
log('###### LOOP1', scopePiece, pieceOffset);
37+
3038
var foundIndex = -1;
3139
// Look through the remaining pieces(start from the offset)
3240
var piecesWeCanMatch = nodeScopePieces.slice(pieceOffset);
3341
for(var nodeScopePieceIndex = 0; nodeScopePieceIndex < piecesWeCanMatch.length; nodeScopePieceIndex++) {
3442
var nodeScopePiece = piecesWeCanMatch[nodeScopePieceIndex];
3543
var overallIndex = pieceOffset + nodeScopePieceIndex;
3644

45+
log('### LOOP2', nodeScopePiece, overallIndex);
46+
3747
// Find the scope piece at the end of the node selector
3848
// Last-occurence
3949
if(
@@ -42,6 +52,7 @@ function getScopeMatchResults(nodeScopeList, scopeNodeScopeList) {
4252
// scopePiece `.bar` matches node `.foo + .bar`
4353
new RegExp(escapeStringRegexp(scopePiece) + '$').test(nodeScopePiece)
4454
) {
55+
log('break 1', scopePiece, nodeScopePiece);
4556
foundIndex = overallIndex;
4657
break;
4758
}
@@ -54,15 +65,19 @@ function getScopeMatchResults(nodeScopeList, scopeNodeScopeList) {
5465
if(isPieceAlwaysAncestorSelector(scopePiece) || isPieceAlwaysAncestorSelector(nodeScopePiece)) {
5566
foundIndex = overallIndex;
5667

68+
log('break 2', scopePiece, isPieceAlwaysAncestorSelector(scopePiece), nodeScopePiece, isPieceAlwaysAncestorSelector(nodeScopePiece));
5769
break;
5870
}
5971

6072

6173
// Handle any direct descendant operators in each piece
6274
var directDescendantPieces = generateDirectDescendantPiecesFromSelector(nodeScopePiece);
75+
6376
// Only try to work out direct descendants if there was the `>` combinator, meaning multiple pieces
6477
if(directDescendantPieces.length > 1) {
6578

79+
log('directDescendantPieces', directDescendantPieces);
80+
6681
var ddNodeScopeList = [].concat([directDescendantPieces]);
6782
// Massage into a direct descendant separated list
6883
var ddScopeList = [].concat([
@@ -83,6 +98,13 @@ function getScopeMatchResults(nodeScopeList, scopeNodeScopeList) {
8398
scopePieceIndex += result.scopePieceIndex - 1;
8499
}
85100

101+
log('break 3', result.doesMatchScope);
102+
103+
// if(!result.doesMatchScope)
104+
// {
105+
// wasEveryPieceFound = false;
106+
// }
107+
86108
break;
87109
}
88110
}
@@ -95,14 +117,19 @@ function getScopeMatchResults(nodeScopeList, scopeNodeScopeList) {
95117
// Mimicing a `[].every` with a for-loop
96118
wasEveryPieceFound = wasEveryPieceFound && isFurther;
97119
if(!wasEveryPieceFound) {
120+
log('break 4');
98121
break;
99122
}
100123
}
101124

125+
log('###### FOUND', wasEveryPieceFound, scopePiece, nodeScopePiece);
126+
102127
return wasEveryPieceFound;
103128
});
104129
});
105130

131+
log('######### RETURN', doesMatchScope, nodeScopeList, scopeNodeScopeList);
132+
106133
return {
107134
doesMatchScope: doesMatchScope,
108135
nodeScopePieceIndex: currentPieceOffset - 1,

lib/resolve-decl.js

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,10 @@ function isSpace(a) {
5050

5151
function findIndex(s, fn, start)
5252
{
53-
if(!start)
54-
{
53+
if(!start) {
5554
start = 0;
5655
}
57-
else
58-
{
56+
else {
5957
s = s.slice(start);
6058
}
6159

@@ -121,33 +119,18 @@ function eachMapItemDependencyOfDecl(variablesUsedList, map, decl, cb) {
121119
//console.log(generateScopeList(mapItem.parent, true));
122120
//console.log('amd isNodeUnderScope', isNodeUnderScope(mimicDecl.parent, mapItem.parent), mapItem.decl.value);
123121
}
124-
// // TODO: use regex from `isUnderScope`
125-
// else if(isUnderScope.RE_PSEUDO_SELECTOR.test(mapItem.parent.selector)) {
126-
// // Create a detached clone
127-
// var ruleClone = shallowCloneNode(decl.parent);
128-
// ruleClone.parent = decl.parent.parent;
129-
//
130-
// // Add the declaration to it
131-
// mimicDecl = decl.clone();
132-
// ruleClone.append(mimicDecl);
133-
//
134-
// var lastPseudoSelectorMatches = mapItem.parent.selector.match(new RegExp(isUnderScope.RE_PSEUDO_SELECTOR.source + '$'));
135-
// var lastPseudoSelector = lastPseudoSelectorMatches ? lastPseudoSelectorMatches[2] : '';
136-
//
137-
// ruleClone.selector += lastPseudoSelector;
138-
// }
139122
else if(mapItem.parent.selector !== decl.parent.selector && declSelector) {
140123
var s = parseSelector(mapItem.parent);
141124

142125
log(s);
143126

144127
var append = null;
145128
var idx = 0;
146-
var process = false;
129+
var process = s.length > 1;
147130
for(var i = 0; i < declSelector.length; i++) {
148131
var a = declSelector[i];
149132
var b = findIndex(s, c => compatible(c, a), idx);
150-
process |= s.findIndex(c => compatible2(c, a)) != -1;
133+
process |= s.findIndex(c => compatible2(c, a), idx) != -1;
151134

152135
if(b < idx) {
153136
// no match: already compatible or wildcard
@@ -165,6 +148,12 @@ function eachMapItemDependencyOfDecl(variablesUsedList, map, decl, cb) {
165148
append = a;
166149
}
167150
else {
151+
// check if the element following the combinator is compatible
152+
if(s[b].find(a => a.type === 'combinator') && !equals(declSelector[i+1][0], s[b+1][0])) {
153+
state = 6;
154+
break;
155+
}
156+
168157
idx = b;
169158
}
170159
}
@@ -194,13 +183,9 @@ function eachMapItemDependencyOfDecl(variablesUsedList, map, decl, cb) {
194183
// Add the declaration to it
195184
mimicDecl = decl.clone();
196185

197-
// FIXME? short-circuit to fix pseudo selectors
198-
mimicDecl.value = mapItem.calculatedInPlaceValue;
199-
200186
ruleClone.append(mimicDecl);
201187

202-
if(state === 0)
203-
{
188+
if(state === 0) {
204189
ruleClone.selector = mapItem.parent.selector;
205190

206191
// append last element of selector where needed
@@ -209,12 +194,10 @@ function eachMapItemDependencyOfDecl(variablesUsedList, map, decl, cb) {
209194
append.forEach(a => ruleClone.selector += String(a));
210195
}
211196
}
212-
else if(state === 5)
213-
{
197+
else if(state === 5) {
214198
ruleClone.selector = removeWildcard(mapItem.parent.selector).trim() + ' ' + decl.parent.selector;
215199
}
216-
else
217-
{
200+
else {
218201
throw new Error("Invalid state: "+state);
219202
}
220203
}

lib/resolve-value.js

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -116,26 +116,61 @@ var resolveValue = function(decl, map, /*optional*/ignorePseudoScope, /*internal
116116
var variableName = variableFallbackSplitPieces[0].trim();
117117
var fallback = variableFallbackSplitPieces.length > 1 ? variableFallbackSplitPieces.slice(1).join(',').trim() : undefined;
118118

119-
(map[variableName] || []).forEach(function(varDeclMapItem) {
120-
// Make sure the variable declaration came from the right spot
121-
// And if the current matching variable is already important, a new one to replace it has to be important
122-
var isRoot = varDeclMapItem.parent.type === 'root' || varDeclMapItem.parent.selectors[0] === ':root';
119+
var process = (ignorePseudo, ignorePseudo2) =>
120+
{
121+
(map[variableName] || []).forEach(function(varDeclMapItem) {
122+
// Make sure the variable declaration came from the right spot
123+
// And if the current matching variable is already important, a new one to replace it has to be important
124+
var isRoot = varDeclMapItem.parent.type === 'root' || varDeclMapItem.parent.selectors[0] === ':root';
125+
126+
var underScope = isNodeUnderScope(decl.parent, varDeclMapItem.parent, false, !ignorePseudo2);
127+
log('---------------');
128+
var underScopeIgnorePseudo = isNodeUnderScope(decl.parent, varDeclMapItem.parent, ignorePseudoScope, !ignorePseudo2);
129+
130+
log("###", variableName, ignorePseudo, ignorePseudo2, '=', underScope, underScopeIgnorePseudo, varDeclMapItem.decl.value, decl.parent.selector, '<>', varDeclMapItem.parent.selector);
131+
132+
//console.log(debugIndent, 'isNodeUnderScope', underScope, underScopeIgnorePseudo, generateScopeList(varDeclMapItem.parent, true), varDeclMapItem.decl.value);
133+
134+
if(
135+
(ignorePseudo ? underScopeIgnorePseudo : underScope) &&
136+
// And if the currently matched declaration is `!important`, it will take another `!important` to override it
137+
(!(matchingVarDeclMapItem || {}).isImportant || varDeclMapItem.isImportant)
138+
) {
139+
matchingVarDeclMapItem = varDeclMapItem;
140+
}
141+
});
142+
};
123143

124-
var underScope = isNodeUnderScope(decl.parent, varDeclMapItem.parent);
125-
var underScsopeIgnorePseudo = isNodeUnderScope(decl.parent, varDeclMapItem.parent, ignorePseudoScope, !!matchingVarDeclMapItem);
144+
!matchingVarDeclMapItem && process(false, false);
145+
!matchingVarDeclMapItem && process(false, true);
146+
!matchingVarDeclMapItem && process(true, false);
147+
!matchingVarDeclMapItem && process(true, true);
126148

127-
// log("###", variableName, underScope, underScsopeIgnorePseudo, matchingVarDeclMapItem && matchingVarDeclMapItem.decl.value, /*matchingVarDeclMapItem,*/ decl.parent, varDeclMapItem.parent);
149+
if(!matchingVarDeclMapItem)
150+
{
151+
(map[variableName] || []).forEach(function(varDeclMapItem) {
152+
// Make sure the variable declaration came from the right spot
153+
// And if the current matching variable is already important, a new one to replace it has to be important
154+
var isRoot = varDeclMapItem.parent.type === 'root' || varDeclMapItem.parent.selectors[0] === ':root';
128155

129-
//console.log(debugIndent, 'isNodeUnderScope', underScope, underScsopeIgnorePseudo, generateScopeList(varDeclMapItem.parent, true), varDeclMapItem.decl.value);
156+
var underScope = isNodeUnderScope(decl.parent, varDeclMapItem.parent, false, true);
157+
var underScopeIgnorePseudo = isNodeUnderScope(decl.parent, varDeclMapItem.parent, ignorePseudoScope, false);
130158

131-
if(
132-
underScsopeIgnorePseudo &&
133-
// And if the currently matched declaration is `!important`, it will take another `!important` to override it
134-
(!(matchingVarDeclMapItem || {}).isImportant || varDeclMapItem.isImportant)
135-
) {
136-
matchingVarDeclMapItem = varDeclMapItem;
137-
}
138-
});
159+
log("###", variableName, underScope, underScopeIgnorePseudo, varDeclMapItem.decl.value, decl.parent.selector, varDeclMapItem.parent.selector);
160+
161+
//console.log(debugIndent, 'isNodeUnderScope', underScope, underScopeIgnorePseudo, generateScopeList(varDeclMapItem.parent, true), varDeclMapItem.decl.value);
162+
163+
if(
164+
underScope &&
165+
// And if the currently matched declaration is `!important`, it will take another `!important` to override it
166+
(!(matchingVarDeclMapItem || {}).isImportant || varDeclMapItem.isImportant)
167+
) {
168+
matchingVarDeclMapItem = varDeclMapItem;
169+
}
170+
});
171+
}
172+
173+
// log('%%%%%%%%%%%%%%%%%%%%%%%%%%', matchingVarDeclMapItem);
139174

140175
// Default to the calculatedInPlaceValue which might be a previous fallback, then try this declarations fallback
141176
var replaceValue = (matchingVarDeclMapItem || {}).calculatedInPlaceValue || (function() {

test/fixtures/compound17.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@
2020
--color: #111111;
2121
}
2222

23+
#foo1.bar ul div > li {
24+
--color: #777777;
25+
}
26+
27+
#foo1.bar ul > div li {
28+
--color: #888888;
29+
}
30+
2331
#foo2.bar ul ~ li {
2432
--color: #222222;
2533
}

test/fixtures/compound18.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
--color: #ffffff;
55
}
66

7+
/* getScopeMatchResults fails */
8+
79
#foo > * li {
810
color: var(--color);
911
}

test/fixtures/compound21.css

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
:root {
3+
--padding: 25px;
4+
}
5+
6+
#foo {
7+
max-width: calc(5px + var(--padding) + var(--padding));
8+
}
9+
10+
body.bar * {
11+
--padding: 10px;
12+
}
13+
14+
#bar #foo {
15+
--padding: 5px;
16+
}

test/fixtures/compound21.expected.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
#foo {
3+
max-width: calc(5px + 25px + 25px);
4+
}
5+
6+
#bar #foo {
7+
max-width: calc(5px + 5px + 5px);
8+
}
9+
10+
body.bar #foo {
11+
max-width: calc(5px + 10px + 10px);
12+
}

test/fixtures/pseudo-selector-declare-variable.css

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@
77
--foo-color: #00ff00;
88
}
99

10-
11-
/* This should add nothing to `.foo`, wrong scope */
1210
.bar:hover + .foo {
1311
--foo-color: #f0f000;
1412
}
13+
1514
/* This should add nothing to `.foo`, wrong scope */
1615
.foo:hover + .bar {
1716
--foo-color: #0000ff;
1817
}
1918
/* This should add nothing to `.foo`, wrong scope */
2019
.foo:hover + .bar:focus {
2120
--foo-color: #000f0f;
22-
}
21+
}

test/fixtures/pseudo-selector-declare-variable.expected.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
color: #ff0000;
33
}
44

5+
.bar:hover + .foo {
6+
color: #f0f000;
7+
}
8+
59
.foo:hover {
610
color: #00ff00;
711
}

test/test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ var test = function(message, fixtureName, options) {
7979
});
8080
};
8181

82+
8283
describe("postcss-css-variables", function() {
8384
// Just make sure it doesn't mangle anything
8485
test(
@@ -375,7 +376,7 @@ describe("postcss-css-variables", function() {
375376
});
376377

377378
describe("compound selectors", function() {
378-
for(var i = 1; i <= 20; i++) {
379+
for(var i = 1; i <= 21; i++) {
379380
test(
380381
"should support compound selectors #"+i,
381382
"compound"+i

0 commit comments

Comments
 (0)