Skip to content

Commit

Permalink
Remove opts global leak. Fix #13 - v0.3.9
Browse files Browse the repository at this point in the history
  • Loading branch information
MadLittleMods committed Jun 29, 2015
1 parent 14dec8f commit b1a6ef2
Show file tree
Hide file tree
Showing 15 changed files with 109 additions and 97 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@

# v0.3.9 - 2015-6-29

- Remove `opts` global leak. Fix #13


# v0.3.8 - 2015-5-28

- Add support for pseudo selectors `:hover` `:before`
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ CSS variables or CSS Custom Properties limited subset polyfill/shim.

We strive for the most complete transformation but we/no plugin can achieve true complete parity according to the [specification](http://dev.w3.org/csswg/css-variables/) because of the DOM cascade unknowns.

## Latest Version: v0.3.8
## Latest Version: v0.3.9
### [Changelog](https://github.com/MadLittleMods/postcss-css-variables/blob/master/CHANGELOG.md)

### Install
Expand Down Expand Up @@ -217,7 +217,7 @@ will be processed to:

## Interoperability

`post-css-variables` plays really nice with [`postcss-nested`](https://github.com/postcss/postcss-nested) in order to get a larger subset of CSS variables features. *See [Nested rules, Usage section](#nested-rules)*
`postcss-css-variables` plays really nice with [`postcss-nested`](https://github.com/postcss/postcss-nested) in order to get a larger subset of CSS variables features. *See [Nested rules, Usage section](#nested-rules)*

If you are using [`postcss-custom-properties`](https://github.com/postcss/postcss-custom-properties) previously, we have a compatible feature set and more so you can switch over without having to refactor any of your code. You can just start writing the new awesome stuff.

Expand All @@ -230,7 +230,7 @@ There is another similar plugin available, [`postcss-custom-properties`](https:/

### Differences from `postcss-custom-properties`

The main features that we`post-css-variables` add/provide are:
The main features that we`postcss-css-variables` add/provide are:

- No limitation on what scope CSS variables can be declared or used (`:root` or wherever)
- Proper value substitution based on explicit DOM/structure traversal
Expand Down
14 changes: 7 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ var defaults = {
};

module.exports = postcss.plugin('postcss-css-variables', function(options) {
opts = extend({}, defaults, options);

var opts = extend({}, defaults, options);

// Work with opts here

Expand All @@ -78,7 +78,7 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {

// Add the js defined variables `opts.variables` to the map
map = extend(
map,
map,
Object.keys(opts.variables).reduce(function(prevVariableMap, variableName) {
var variableEntry = opts.variables[variableName];
// Automatically prefix any variable with `--` (CSS custom property syntax) if it doesn't have it already
Expand Down Expand Up @@ -187,7 +187,7 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
var rulesThatHaveDeclarationsWithVariablesList = [];
css.eachRule(function(rule) {
var doesRuleUseVariables = rule.nodes.some(function(node) {
if(node.type == 'decl') {
if(node.type === 'decl') {
var decl = node;
// If it uses variables
// and is not a variable declarations that we may be preserving from earlier
Expand Down Expand Up @@ -223,16 +223,16 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
// Resolve the declarations
rulesToWorkOn.forEach(function(ruleToWorkOn) {
ruleToWorkOn.nodes.slice(0).forEach(function(node) {
if(node.type == 'decl') {
if(node.type === 'decl') {
var decl = node;
resolveDecl(decl, map);
resolveDecl(decl, map, opts.preserve);
}
});
});

});





Expand Down
10 changes: 5 additions & 5 deletions lib/clone-splice-parent-onto-node-when.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,19 @@ var cloneSpliceParentOntoNodeWhen = function(node, parent, /*optional*/whenCb) {
// Assign parents to our parent clones
cloneParentList.forEach(function(parentClone, index, cloneParentList) {
// Keep assigning parents detached until just very end
if(index+1 < cloneParentList.length) {
if(index + 1 < cloneParentList.length) {
//parentClone.moveTo(cloneParentList[index+1]);
parentClone.parent = cloneParentList[index+1];
parentClone.parent = cloneParentList[index + 1];
}
});


// Assign parents to our node clones
cloneList.forEach(function(clone, index, cloneList) {
// Keep assigning parents detached until just very end
if(index+1 < cloneList.length) {
if(index + 1 < cloneList.length) {
//clone.moveTo(cloneList[index+1]);
clone.parent = cloneList[index+1];
clone.parent = cloneList[index + 1];
// Then splice on the new parent scope
} else {
// Set the highest parent ancestor to back to where we should splice in
Expand All @@ -61,4 +61,4 @@ var cloneSpliceParentOntoNodeWhen = function(node, parent, /*optional*/whenCb) {
return cloneList[0];
};

module.exports = cloneSpliceParentOntoNodeWhen;
module.exports = cloneSpliceParentOntoNodeWhen;
5 changes: 2 additions & 3 deletions lib/find-node-ancestor-with-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ var generateScopeList = require('./generate-scope-list');
var findNodeAncestorWithSelector = function(selector, node) {
var matchingNode;

var currentNode = node;
var stillFindingNode = true;
// Keep going until we run out of parents to search
// or we found the node
var currentNode = node;
while(currentNode.parent && !matchingNode) {
// A trick to get the selector split up. Generate a scope list on a clone(clean parent)
var currentNodeScopeList = generateScopeList(currentNode.clone(), true);
Expand All @@ -30,4 +29,4 @@ var findNodeAncestorWithSelector = function(selector, node) {
return matchingNode;
};

module.exports = findNodeAncestorWithSelector;
module.exports = findNodeAncestorWithSelector;
2 changes: 1 addition & 1 deletion lib/gather-variable-dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ var gatherVariableDependencies = function(variablesUsed, map, _dependencyVariabl
};
};

module.exports = gatherVariableDependencies;
module.exports = gatherVariableDependencies;
2 changes: 1 addition & 1 deletion lib/generate-descendant-pieces-from-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ var generateDescendantPiecesFromSelector = function(selector) {
});
};

module.exports = generateDescendantPiecesFromSelector;
module.exports = generateDescendantPiecesFromSelector;
2 changes: 1 addition & 1 deletion lib/generate-direct-descendant-pieces-from-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ var generateDirectDescendantPiecesFromSelector = function(selector) {
});
};

module.exports = generateDirectDescendantPiecesFromSelector;
module.exports = generateDirectDescendantPiecesFromSelector;
6 changes: 3 additions & 3 deletions lib/generate-scope-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ var generateScopeList = function(node, /*optional*/includeSelf) {

// Add to the front of the array
scopeStringPieces.unshift.apply(scopeStringPieces, descendantPieces);

return scopeStringPieces;
});
});
Expand All @@ -66,6 +66,6 @@ var generateScopeList = function(node, /*optional*/includeSelf) {
}

return selectorScopeList;
}
};

module.exports = generateScopeList;
module.exports = generateScopeList;
2 changes: 1 addition & 1 deletion lib/is-node-under-scope.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ var isNodeUnderScope = function(node, scopeNode, /*optional*/ignorePseudo) {
return isUnderScope(nodeScopeList, scopeNodeScopeList, ignorePseudo);
};

module.exports = isNodeUnderScope;
module.exports = isNodeUnderScope;
2 changes: 1 addition & 1 deletion lib/is-piece-always-ancestor-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ var isPieceIsAlwaysAncestorSelector = function(piece) {
return !!alwaysAncestorSelector[piece];
};

module.exports = isPieceIsAlwaysAncestorSelector;
module.exports = isPieceIsAlwaysAncestorSelector;
12 changes: 6 additions & 6 deletions lib/is-under-scope.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function getScopeMatchResults(nodeScopeList, scopeNodeScopeList) {
//
// Or the node scope piece could be an always-ancestor selector itself
// And we only want the first occurence so we can keep matching future scope pieces
if(isPieceAlwaysAncestorSelector(scopePiece) || isPieceAlwaysAncestorSelector(nodeScopePiece)) {
if(isPieceAlwaysAncestorSelector(scopePiece) || isPieceAlwaysAncestorSelector(nodeScopePiece)) {
foundIndex = overallIndex;

break;
Expand All @@ -76,11 +76,11 @@ function getScopeMatchResults(nodeScopeList, scopeNodeScopeList) {

// If it matches completely
// or there are still more pieces to match in the future
if(result.doesMatchScope || scopePieceIndex+1 < scopeNodeScopePieces.length) {
if(result.doesMatchScope || scopePieceIndex + 1 < scopeNodeScopePieces.length) {
foundIndex = overallIndex;
// Move the scope forward the amount that piece consumed
// -1 because the of for-loop increments at each iteration
scopePieceIndex += result.scopePieceIndex-1;
scopePieceIndex += result.scopePieceIndex - 1;
}

break;
Expand All @@ -90,7 +90,7 @@ function getScopeMatchResults(nodeScopeList, scopeNodeScopeList) {

var isFurther = foundIndex >= pieceOffset;

currentPieceOffset = foundIndex+1;
currentPieceOffset = foundIndex + 1;

// Mimicing a `[].every` with a for-loop
wasEveryPieceFound = wasEveryPieceFound && isFurther;
Expand All @@ -105,7 +105,7 @@ function getScopeMatchResults(nodeScopeList, scopeNodeScopeList) {

return {
doesMatchScope: doesMatchScope,
nodeScopePieceIndex: currentPieceOffset-1,
nodeScopePieceIndex: currentPieceOffset - 1,
scopePieceIndex: scopePieceIndex
};
}
Expand Down Expand Up @@ -148,4 +148,4 @@ var isUnderScope = function(nodeScopeList, scopeNodeScopeList, /*optional*/ignor

isUnderScope.RE_PSEUDO_SELECTOR = RE_PSEUDO_SELECTOR;

module.exports = isUnderScope;
module.exports = isUnderScope;
125 changes: 66 additions & 59 deletions lib/resolve-decl.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,72 @@ var isNodeUnderScope = require('./is-node-under-scope');
var findNodeAncestorWithSelector = require('./find-node-ancestor-with-selector');
var cloneSpliceParentOntoNodeWhen = require('./clone-splice-parent-onto-node-when');



function eachMapItemDependencyOfDecl(variablesUsedList, map, decl, cb) {
// Now find any at-rule declarations that pertains to each rule
// Loop through the variables used
variablesUsedList.forEach(function(variableUsedName) {

// Find anything in the map that corresponds to that variable
gatherVariableDependencies(variablesUsedList, map).deps.forEach(function(mapItem) {

var mimicDecl;
if(mapItem.isUnderAtRule) {

// Get the inner-most selector of the at-rule scope variable declaration we are matching
// Because the inner-most selector will be the same for each branch, we can look at the first one [0] or any of the others
var varDeclScopeList = generateScopeList(mapItem.parent, true);
var innerMostAtRuleSelector = varDeclScopeList[0].slice(-1)[0];
var nodeToSpliceParentOnto = findNodeAncestorWithSelector(innerMostAtRuleSelector, decl.parent);

// Splice on where the selector starts matching the selector inside at-rule
// See: `test/fixtures/cascade-on-nested-rules.css`
var varDeclAtRule = mapItem.parent.parent;
mimicDecl = cloneSpliceParentOntoNodeWhen(decl, varDeclAtRule, function(ancestor) {
return ancestor === nodeToSpliceParentOnto;
});


//console.log('amd og', generateScopeList(decl.parent, true));
//console.log('amd', generateScopeList(mimicDecl.parent, true));
//console.log(generateScopeList(mapItem.parent, true));
//console.log('amd isNodeUnderScope', isNodeUnderScope(mimicDecl.parent, mapItem.parent), mapItem.decl.value);
}
// TODO: use regex from `isUnderScope`
else if(isUnderScope.RE_PSEUDO_SELECTOR.test(mapItem.parent.selector)) {
// Create a detached clone
var ruleClone = decl.parent.clone().removeAll();
ruleClone.parent = decl.parent.parent;

// Add the declaration to it
mimicDecl = decl.clone();
ruleClone.append(mimicDecl);

var lastPseudoSelectorMatches = mapItem.parent.selector.match(new RegExp(isUnderScope.RE_PSEUDO_SELECTOR.source + '$'));
var lastPseudoSelector = lastPseudoSelectorMatches ? lastPseudoSelectorMatches[2] : '';

ruleClone.selector += lastPseudoSelector;
}

// If it is under the proper scope,
// we need to check because we are iterating over all map entries
if(mimicDecl && isNodeUnderScope(mimicDecl, mapItem.parent, true)) {
cb(mimicDecl, mapItem);
}
});
});
}




// Resolve the decl with the computed value
// Also add in any media queries that change the value as necessary
function resolveDecl(decl, map, /*optional*/logResolveValueResult) {
function resolveDecl(decl, map, /*optional*/shouldPreserve, /*optional*/logResolveValueResult) {
shouldPreserve = shouldPreserve || false;

// Make it chainable
var _logResolveValueResult = function(valueResults) {
if(logResolveValueResult) {
logResolveValueResult(valueResults);
Expand All @@ -23,7 +86,6 @@ function resolveDecl(decl, map, /*optional*/logResolveValueResult) {

// Grab the balue for this declarations
var valueResults = _logResolveValueResult(resolveValue(decl, map));



// Resolve the cascade dependencies
Expand Down Expand Up @@ -74,72 +136,17 @@ function resolveDecl(decl, map, /*optional*/logResolveValueResult) {


// If we are preserving var(...) usage and the value changed meaning it had some
if(opts.preserve === true && decl.value !== valueResults.value) {
if(shouldPreserve === true && decl.value !== valueResults.value) {
decl.cloneAfter();
}

// Set the new value after we are done dealing with at-rule stuff
decl.value = valueResults.value;

}


function eachMapItemDependencyOfDecl(variablesUsedList, map, decl, cb) {
// Now find any at-rule declarations that pertains to each rule
// Loop through the variables used
variablesUsedList.forEach(function(variableUsedName) {

// Find anything in the map that corresponds to that variable
gatherVariableDependencies(variablesUsedList, map).deps.forEach(function(mapItem) {

var mimicDecl;
if(mapItem.isUnderAtRule) {

// Get the inner-most selector of the at-rule scope variable declaration we are matching
// Because the inner-most selector will be the same for each branch, we can look at the first one [0] or any of the others
var varDeclScopeList = generateScopeList(mapItem.parent, true);
var innerMostAtRuleSelector = varDeclScopeList[0].slice(-1)[0];
var nodeToSpliceParentOnto = findNodeAncestorWithSelector(innerMostAtRuleSelector, decl.parent);

// Splice on where the selector starts matching the selector inside at-rule
// See: `test/fixtures/cascade-on-nested-rules.css`
var varDeclAtRule = mapItem.parent.parent;
mimicDecl = cloneSpliceParentOntoNodeWhen(decl, varDeclAtRule, function(ancestor) {
return ancestor === nodeToSpliceParentOnto;
});


//console.log('amd og', generateScopeList(decl.parent, true));
//console.log('amd', generateScopeList(mimicDecl.parent, true));
//console.log(generateScopeList(mapItem.parent, true));
//console.log('amd isNodeUnderScope', isNodeUnderScope(mimicDecl.parent, mapItem.parent), mapItem.decl.value);
}
// TODO: use regex from `isUnderScope`
else if(isUnderScope.RE_PSEUDO_SELECTOR.test(mapItem.parent.selector)) {
// Create a detached clone
var ruleClone = decl.parent.clone().removeAll();
ruleClone.parent = decl.parent.parent;

// Add the declaration to it
mimicDecl = decl.clone();
ruleClone.append(mimicDecl);

var lastPseudoSelectorMatches = mapItem.parent.selector.match(new RegExp(isUnderScope.RE_PSEUDO_SELECTOR.source + '$'));
var lastPseudoSelector = lastPseudoSelectorMatches ? lastPseudoSelectorMatches[2] : '';

ruleClone.selector += lastPseudoSelector;
}

// If it is under the proper scope,
// we need to check because we are iterating over all map entries
if(mimicDecl && isNodeUnderScope(mimicDecl, mapItem.parent, true)) {
cb(mimicDecl, mapItem);
}
});
});
}




module.exports = resolveDecl;
module.exports = resolveDecl;
Loading

0 comments on commit b1a6ef2

Please sign in to comment.