New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

postcss-extend

Package Overview
Dependencies
Maintainers
2
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

postcss-extend - npm Package Compare versions

Comparing version 0.4.0 to 0.4.1

6

CHANGELOG.md
# Changelog
## v0.4.1
- [Infinite recursion detection improvements, widespread minor corrections](https://github.com/travco/postcss-extend/releases/tag/v0.4.1)
## v0.4.0
- [All-intended-features release as 'postcss-extend'](https://github.com/travco/postcss-extend/releases/tag/v0.4.0)
## v0.3.1

@@ -4,0 +10,0 @@ - Ensure that unused defining at-rules and erroneous extending at-rules are removed from generated CSS.

112

index.js
'use strict';
var postcss = require('postcss');
// /*DEBUG*/ var appendout = require('fs').appendFileSync;

@@ -13,4 +12,2 @@ module.exports = postcss.plugin('postcss-simple-extend', function simpleExtend() {

// /*DEBUG*/ appendout('./test/debugout.txt', '\n----------------------------------------');
css.eachAtRule(function(atRule) {

@@ -24,4 +21,2 @@ if (definingAtRules.indexOf(atRule.name) !== -1) {

// Selectively disclude silents and placeholders, find unused,
// and exclude from the final output
css.eachRule(function(targetNode) {

@@ -39,4 +34,2 @@ var tgtSaved = targetNode.selectors;

targetNode.removeSelf();
// /*DEBUG*/ } else {
// /*DEBUG*/ appendout('./test/debugout.txt', '\nSifted out placeholder/silent ' + tgtSaved[i]);
}

@@ -48,3 +41,2 @@ }

});
//simplification process to find definitions in the future
function processDefinition(atRule) {

@@ -57,5 +49,2 @@ if (isBadDefinitionLocation(atRule)) {

// Manually copy styling properties (semicolon, whitespace)
// to newly created and cloned nodes,
// cf. https://github.com/postcss/postcss/issues/85
definition.semicolon = atRule.semicolon;

@@ -71,3 +60,2 @@ atRule.nodes.forEach(function(node) {

definition.selector = '@define-placeholder ' + atRule.params.toString();
// /*DEBUG*/ appendout('./test/debugout.txt', '\nDeclaring placeholder : ' + definition.selector);
atRule.parent.insertBefore(atRule, definition);

@@ -87,3 +75,3 @@ atRule.removeSelf();

var originSels = atRule.parent.selectors;
var selectorRetainer;
var selectorRetainer = [];
var couldExtend = false;

@@ -98,8 +86,5 @@ var subTarget = {

var tgtSaved = targetNode.selectors;
//Strip all @define-placeholders and save slug-selectors present in tgtSaved
for (var i = 0; i < tgtSaved.length; i++) {
if (tgtSaved[i].substring(0, 20) === '@define-placeholder ') {
// /*DEBUG*/ appendout('./test/debugout.txt', '\nn[' + i + ']String = ' + tgtSaved[i] + ' Substring 0-20 = \'' + tgtSaved[i].substring(0, 20) + '\'');
tgtSaved[i] = tgtSaved[i].substring(20, (tgtSaved[i].length));
// /*DEBUG*/ appendout('./test/debugout.txt', '\nresString = \'' + tgtSaved[i] + '\'');
}

@@ -110,8 +95,4 @@ }

for (var n = 0; n < tgtSaved.length; n++) {
// Operate on normal extendables
if (atRule.params === tgtSaved[n]) {
//check if target has unresolved extentions, then extend them
if (extentionRecursionHandler(atRule, targetNode)) {
// We need to re-evaluate the current atRule, as other classes (once passed over) may now be matching, so re-process and exit.
// /*DEBUG*/ appendout('./test/debugout.txt', '\n!Bumping evaluation of :' + atRule.parent);
if (extensionRecursionHandler(atRule, targetNode)) {
processExtension(atRule);

@@ -121,8 +102,5 @@ couldExtend = true;

}
// /*DEBUG*/ appendout('./test/debugout.txt', '\nfound and extending : ' + tgtSaved[n] + ' : ' + originSels);
tgtAccumulate = tgtAccumulate.concat(originSels);
// /*DEBUG*/ appendout('./test/debugout.txt', '\nCombined selectors :\n' + tgtAccumulate);
couldExtend = true;
//Operate on sub-elements of extendables (thus extending them)
} else if (tgtSaved[n].substring(1).search(/[\s.:#]/) + 1 !== -1) {

@@ -132,6 +110,3 @@ var tgtBase = tgtSaved[n].substring(0, tgtSaved[n].substring(1).search(/[\s.:#]/) + 1);

if (atRule.params === tgtBase) {
//check if target rule has unresolved extentions, then extend them
if (extentionRecursionHandler(atRule, targetNode)) {
// We need to re-evaluate the current atRule, as other classes (once passed over) may now be matching, so re-process and exit.
// /*DEBUG*/ appendout('./test/debugout.txt', '\n!Bumping evaluation of :' + atRule.parent);
if (extensionRecursionHandler(atRule, targetNode)) {
processExtension(atRule);

@@ -141,41 +116,25 @@ couldExtend = true;

}
//tack onto target node
// /*DEBUG*/ appendout('./test/debugout.txt', '\nfound and extending : ' + tgtSaved[n].substring(0, tgtSaved[n].substring(1).search(/[\s.:#]/) + 1) + ' :\n' + tgtBase + ' (' + tgtSub + ')');
// /*DEBUG*/ appendout('./test/debugout.txt', '\nCalling formSubSelector with (\n' + originSels + ',\n' + tgtSub);
tgtAccumulate = tgtAccumulate.concat(formSubSelector(originSels, tgtSub));
// /*DEBUG*/ appendout('./test/debugout.txt', '\nCombined selectors :\n' + tgtAccumulate);
couldExtend = true;
}
}//END OF sub root-extentions
}
}
if (couldExtend) {
// /*DEBUG*/ appendout('./test/debugout.txt', '\nStart uniqreq2 :\n' + tgtAccumulate);
//Kill off duplicate selectors
tgtAccumulate = uniqreq(tgtAccumulate).toString().replace(/,/g, ', ');
// /*DEBUG*/ appendout('./test/debugout.txt', '\nPost uniqreq2 :\n' + tgtAccumulate);
targetNode.selector = tgtAccumulate;
}
});
//hasMediaAncestor === true: ---------------
} else {
// /*DEBUG*/ appendout('./test/debugout.txt', '\nAttempting to fetch declarations for ' + atRule.params + '...');
var backFirstTargetNode;
var targetNodeArray = [];
css.eachRule(function(subRule) {
//create a back-is-top stack so that we can efficiently operate on nodes in reverse
//thus retaining priority when copying declarations if there are multiple matches
if (!hasMediaAncestor(subRule) || subRule.parent === atRule.parent.parent) {
targetNodeArray.push(subRule);
} // /*DEBUG*/ else {
// /*DEBUG*/ appendout('./test/debugout.txt', '\n\'' + atRule.params + '\' ignored possible target in another @media : \n' + subRule);
// /*DEBUG*/ }
}); //end of each rule
}
});
while (targetNodeArray.length > 0) {
backFirstTargetNode = targetNodeArray.pop();
if (backFirstTargetNode.selectors.indexOf(atRule.params) !== -1) {
//check if rule has unresolved extentions, then extend them
if (extentionRecursionHandler(atRule, backFirstTargetNode)) {
// We need to re-evaluate the current atRule, as other classes (once passed over) may now be matching, so re-process and exit.
// /*DEBUG*/ appendout('./test/debugout.txt', '\n!Bumping evaluation of :' + atRule.parent);
if (extensionRecursionHandler(atRule, backFirstTargetNode)) {
processExtension(atRule);

@@ -185,10 +144,6 @@ couldExtend = true;

}
//In scope, tack on selector to target rule
if (backFirstTargetNode.parent === atRule.parent.parent) {
// /*DEBUG*/ appendout('./test/debugout.txt', '\n...tacking onto backFirstTargetNode :' + backFirstTargetNode);
selectorRetainer = backFirstTargetNode.selector;
backFirstTargetNode.selector = selectorRetainer + ', ' + originSels.join(', ');
//Out of scope, direcly copy declarations
selectorRetainer = backFirstTargetNode.selectors;
backFirstTargetNode.selector = uniqreq(selectorRetainer.concat(originSels)).join(', ');
} else {
// /*DEBUG*/ appendout('./test/debugout.txt', '\n...grabbing backFirstTargetNode :\n' + backFirstTargetNode);
safeCopyDeclarations(backFirstTargetNode, atRule.parent);

@@ -198,3 +153,2 @@ }

} else {
//Pull from sub-elements of target nodes (thus extending them)
for (var m = 0; m < backFirstTargetNode.selectors.length; m++) {

@@ -204,6 +158,3 @@ var extTgtBase = backFirstTargetNode.selectors[m].substring(0, backFirstTargetNode.selectors[m].substring(1).search(/[\s.:#]/) + 1);

if (backFirstTargetNode.selectors[m].substring(1).search(/[\s.:#]/) + 1 !== -1 && extTgtBase === atRule.params) {
//check if target rule has unresolved extentions, then extend them
if (extentionRecursionHandler(atRule, backFirstTargetNode)) {
// We need to re-evaluate the current atRule, as other classes (once passed over) may now be matching, so re-process and exit.
// /*DEBUG*/ appendout('./test/debugout.txt', '\n!Bumping evaluation of :' + atRule.parent);
if (extensionRecursionHandler(atRule, backFirstTargetNode)) {
processExtension(atRule);

@@ -214,16 +165,9 @@ couldExtend = true;

if (backFirstTargetNode.parent === atRule.parent.parent) {
//Use Tacking onto exiting selectors instead of new creation
// /*DEBUG*/ appendout('./test/debugout.txt', '\nUtilizing existing brother subclass for extention, as nothing matches: \n' + atRule.parent.selector + ' sub-' + extTgtSub);
selectorRetainer = backFirstTargetNode.selector;
backFirstTargetNode.selector = selectorRetainer + ', ' + formSubSelector(originSels, extTgtSub).join(', ');
selectorRetainer = backFirstTargetNode.selectors;
backFirstTargetNode.selector = uniqreq(selectorRetainer.concat(formSubSelector(originSels, extTgtSub))).join(', ');
} else {
//check for prexisting sub classes before making one
subTarget = findBrotherSubClass(atRule.parent, extTgtSub);
if (subTarget.bool) {
//utilize existing subclass for extention
// /*DEBUG*/ appendout('./test/debugout.txt', '\nUtilizing existing subclass for extention:\n' + subTarget);
safeCopyDeclarations(backFirstTargetNode, subTarget.node);
} else {
//create additional nodes below existing for each instance of subs
// /*DEBUG*/ appendout('./test/debugout.txt', '\nUtilizing new subclass for extention, as nothing matches: \n' + atRule.parent.selector + ' sub-' + extTgtSub);
var newNode = postcss.rule();

@@ -241,6 +185,5 @@ newNode.semicolon = atRule.semicolon;

}
} //end of if hasMediaAncestor
}
if (!couldExtend) {
result.warn('\'' + atRule.params + '\', has not been defined, so cannot be extended');
// /*DEBUG*/ appendout('./test/debugout.txt', '\n\'' + atRule.params + '\' has not been defined!!!');
}

@@ -317,8 +260,5 @@ if (atRule.parent !== undefined) {

if (nodeDest.some(function(decl) { return decl.prop === node.prop; })) {
// /*DEBUG*/ appendout('./test/debugout.txt', '\nsafeIgnored : ' + node + ' for ' + nodeDest.selector);
return;
}
// /*DEBUG*/ appendout('./test/debugout.txt', '\nnodeDest Nodes:\n' + nodeDest.nodes);
var clone = node.clone();
//For lack of a better way to analyse how much tabbing is required:
if (nodeOrigin.parent === nodeDest.parent) {

@@ -357,5 +297,6 @@ clone.before = node.before;

function extentionRecursionHandler(atRule, targetNode) {
function extensionRecursionHandler(atRule, targetNode) {
var recursableRule = findUnresolvedExtendChild(targetNode);
// /*DEBUG*/ appendout('./test/debugout.txt', '\nopen eRH recurseStack : ' + recurseStack);
var isTopOfRecurse = false;
if (recurseStack.length === 0) { isTopOfRecurse = true; }
if (recursableRule.bool) {

@@ -365,13 +306,7 @@ recurseStack.push(atRule.params);

if (recurseStack.indexOf(recursableRule.node.params) === -1) {
// /*DEBUG*/ appendout('./test/debugout.txt', '\nRecursing from ' + atRule.parent.selector + ' on: ' + recursableRule.node.parent + '\n\\/\\/\\/\\/\\/\\/\\/\\/ ' + recurseStack.length);
// /*DEBUG*/ appendout('./test/debugout.txt', '\npre-process recurseStack : ' + recurseStack);
processExtension(recursableRule.node);
// /*DEBUG*/ appendout('./test/debugout.txt', '\n ^ ^ ^ ^ ^ ^ ^ ^ ' + recurseStack.length);
recursableRule = findUnresolvedExtendChild(targetNode);
} else {
result.warn('Infinite extention recursion detected', { node: atRule });
// /*DEBUG*/ appendout('./test/debugout.txt', '\nInfinite Recursion detected, recurseStack : ' + recurseStack + '\n -- on :\n' + atRule.parent + '\n!!!!!!!!!!!!');
//clean out the recurse stack of duplicates (from early aborts) before popping
result.warn('Infinite extension recursion detected', { node: atRule });
recurseStack = uniqreq(recurseStack);
// /*DEBUG*/ appendout('./test/debugout.txt', '\npost-uniqreq recurseStack : ' + recurseStack);
return false;

@@ -381,8 +316,8 @@ }

// /*DEBUG*/ appendout('./test/debugout.txt', '\npre-pop recurseStack : ' + recurseStack);
// if (recurseStack.pop() !== atRule.params) {
// result.warn('Detected mis-aligned recursion stack! (Please post your CSS in a github issue, this shouldn\'t happen!)', { node: atRule });
// /*DEBUG*/ appendout('./test/debugout.txt', '\n!!!!!!!!!!!!MISALIGNED RECURSE STACK\npost-pop recurseStack : ' + recurseStack + '');
// }
// Signal to do a recall and exit (only happens with badly formed css)
if (recurseStack.pop() !== atRule.params && recurseStack.indexOf(atRule.params) === -1) {
result.warn('Detected critically mis-aligned recursion stack! (Please post your CSS in a github issue, this shouldn\'t ever happen!)', { node: atRule });
}
if (isTopOfRecurse) {
recurseStack = [];
}
return true;

@@ -404,3 +339,2 @@ }

seldiff = uniqreq(seldiff);
// /*DEBUG*/ appendout('./test/debugout.txt', '\nseldiff : ' + seldiff + '\n\tBetween:\n' + node.selectors + '\n\tand:\n' + selectorAccumulator);
if (seldiff.length === selectorAccumulator.length) {

@@ -407,0 +341,0 @@ foundNode = node;

@@ -8,3 +8,3 @@ {

"license": "MIT",
"version": "0.4.0",
"version": "0.4.1",
"description": "Simple extends for PostCSS",

@@ -11,0 +11,0 @@ "homepage": "https://github.com/travco/postcss-extend",

@@ -9,3 +9,3 @@ # postcss-extend [![Build Status](https://travis-ci.org/travco/postcss-extend.svg?branch=master)](https://travis-ci.org/travco/postcss-extend)

- Define an 'silent' extendable selector — a "placeholder selector" — to which you can (from anywhere in the doc), add concrete selectors from other rule sets.
- Add concrete selectors from one rule (containing the `@extend`) to all rule sets with the selector specified (or a sub class of the one specified).
- Add concrete selectors from one rule (containing the `@extend`) to all rule sets with the selector specified (or a subclass of the one specified).
- Pull-in declarations in rulesets (most) anywhere in the doc (by a selector) from within `@media` statements (semi-safely)

@@ -53,4 +53,2 @@ - Extend existing media-conscious rulesets, even if some of them are within `@media` statements.

## Installation
This is just a fork, not an NPM module yet :(, it's also still in development, the origin is here, use it in the mean-time:
```

@@ -66,3 +64,3 @@ npm install postcss-extend --save

- [Defining Placeholders](https://github.com/travco/postcss-extend#extending-rules-or-placeholders)
- [Defining Placeholders](https://github.com/travco/postcss-extend#defining-placeholders)
- [The '%' placeholder](https://github.com/travco/postcss-extend#the--silent-placeholder)

@@ -76,3 +74,3 @@ - [Extending Rules or Placeholders](https://github.com/travco/postcss-extend#extending-rules-or-placeholders)

- [Extending something in an @media while inside an @media](https://github.com/travco/postcss-extend#extending-something-in-an-media-while-inside-an-media)
- [Chaining `@extend`s, or Extention-Recursion](https://github.com/travco/postcss-extend#chaining-extends-or-extention-recursion)
- [Chaining `@extend`s, or Extension-Recursion](https://github.com/travco/postcss-extend#chaining-extends-or-extension-recursion)

@@ -123,3 +121,3 @@ ### Defining Placeholders

Whenever extending a rule or placeholder, you are also automatically trying to extend any sub classes or elements that have *exactly* what you selected (before a space, `.`, `:`, or `#`). For example:
Whenever extending a rule or placeholder, you are also automatically trying to extend any subclasses or elements that have *exactly* what you selected (before a space, `.`, `:`, or `#`). For example:
```css

@@ -203,3 +201,3 @@ .potato {

So what does it do when sub classes of the extended rule are also outside `@media`?
So what does it do when subclasses of the extended rule are also outside `@media`?
```css

@@ -297,3 +295,3 @@ .potato {

#### Chaining `@extend`s, or extention-recursion
#### Chaining `@extend`s, or extension-recursion

@@ -362,8 +360,8 @@ Definately one of the more powerful features of SASS's `@extend` is here too. It does however, come with a slight caveat that it is order-agnostic. Meaning that it doesn't enforce order by only extending that which came above it, it just goes.

## Quirks
As with any piece of code it's got a few quirks. Behaviors that are not intended, and not enforced, and may disappear (or be forcively altered) with the next release, so it's useful to be aware of them.
As with any piece of code it's got a few quirks. Behaviors that are not intended, and not enforced, and may disappear (or be forcibly altered) with the next release, so it's useful to be aware of them.
**Order of Processing** : Currently, all of the `@extend`s being processed are run in a sequential manner from the top to the bottom of the doc. This keeps thing relatively snappy, but makes it so that we have to do conditional-recursion on not-yet-declared-or-extended rules. This leads to some blatant inefficiencies when processing badly formed CSS. So if you want to keep processing time down, write good CSS.
**Non-logical means of extention for `@media`** : As anyone who's aware of the complications discussed in the [SASS issue about extending across `@media`](https://github.com/sass/sass/issues/1050) would know. There is no way (known) of extending when `@media` rules are involved that is both 'clean and simple' and 'logically correct with how `@extend` is used elsewhere'. The way this plugin operates, and it's logical meaning, is a blatant compromise so that it has both common use cases and easier implementation. While the current implementations will not change (without flags), such things as extending an `@media` from within an `@media` does nothing, this could possibly change in the future.
**Non-logical means of extension for `@media`** : As anyone who's aware of the complications discussed in the [SASS issue about extending across `@media`](https://github.com/sass/sass/issues/1050) would know. There is no way (known) of extending when `@media` rules are involved that is both 'clean and simple' and 'logically correct with how `@extend` is used elsewhere'. The way this plugin operates, and it's logical meaning, is a blatant compromise so that it has both common use cases and easier implementation. While the current implementations will not change (without flags), such things as extending an `@media` from within an `@media` does nothing, this could possibly change in the future.
##### Originally a fork of davidtheclark's [postcss-simple-extend](https://github.com/davidtheclark/postcss-simple-extend) (extended) by way of the included [MIT License](https://github.com/travco/postcss-extend/blob/master/LICENSE)
##### Originally a fork of davidtheclark's [postcss-simple-extend](https://github.com/davidtheclark/postcss-simple-extend) (extended) by way of the included [MIT License](https://github.com/travco/postcss-extend/blob/master/LICENSE)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc