function replaceParentSelector(paths, context, inSelector) {
        // The paths are [[Selector]]
        // The first list is a list of comma separated selectors
        // The inner list is a list of inheritance separated selectors
        // e.g.
        // .a, .b {
        //   .c {
        //   }
        // }
        // == [[.a] [.c]] [[.b] [.c]]
        //
        var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false, length, lastSelector;
        function findNestedSelector(element) {
            var maybeSelector;
            if (!(element.value instanceof Paren)) {
                return null;
            }

            maybeSelector = element.value.value;
            if (!(maybeSelector instanceof Selector)) {
                return null;
            }

            return maybeSelector;
        }

        // the elements from the current selector so far
        currentElements = [];
        // the current list of new selectors to add to the path.
        // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
        // by the parents
        newSelectors = [
            []
        ];

        for (i = 0; (el = inSelector.elements[i]); i++) {
            // non parent reference elements just get added
            if (el.value !== "&") {
                var nestedSelector = findNestedSelector(el);
                if (nestedSelector != null) {
                    // merge the current list of non parent selector elements
                    // on to the current list of selectors to add
                    mergeElementsOnToSelectors(currentElements, newSelectors);

                    var nestedPaths = [], replaced, replacedNewSelectors = [];
                    replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
                    hadParentSelector = hadParentSelector || replaced;
                    // the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
                    for (k = 0; k < nestedPaths.length; k++) {
                        var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
                        addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
                    }
                    newSelectors = replacedNewSelectors;
                    currentElements = [];

                } else {
                    currentElements.push(el);
                }

            } else {
                hadParentSelector = true;
                // the new list of selectors to add
                selectorsMultiplied = [];

                // merge the current list of non parent selector elements
                // on to the current list of selectors to add
                mergeElementsOnToSelectors(currentElements, newSelectors);

                // loop through our current selectors
                for (j = 0; j < newSelectors.length; j++) {
                    sel = newSelectors[j];
                    // if we don't have any parent paths, the & might be in a mixin so that it can be used
                    // whether there are parents or not
                    if (context.length === 0) {
                        // the combinator used on el should now be applied to the next element instead so that
                        // it is not lost
                        if (sel.length > 0) {
                            sel[0].elements.push(new Element(el.combinator, '', el._index, el._fileInfo));
                        }
                        selectorsMultiplied.push(sel);
                    }
                    else {
                        // and the parent selectors
                        for (k = 0; k < context.length; k++) {
                            // We need to put the current selectors
                            // then join the last selector's elements on to the parents selectors
                            var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
                            // add that to our new set of selectors
                            selectorsMultiplied.push(newSelectorPath);
                        }
                    }
                }

                // our new selectors has been multiplied, so reset the state
                newSelectors = selectorsMultiplied;
                currentElements = [];
            }
        }

        // if we have any elements left over (e.g. .a& .b == .b)
        // add them on to all the current selectors
        mergeElementsOnToSelectors(currentElements, newSelectors);

        for (i = 0; i < newSelectors.length; i++) {
            length = newSelectors[i].length;
            if (length > 0) {
                paths.push(newSelectors[i]);
                lastSelector = newSelectors[i][length - 1];
                newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList);
            }
        }

        return hadParentSelector;
    }
// returns true if `inSelector` contained at least one parent selector
returns true if `inSelector` contained at least one parent selector
returns true if ` inSelector ` contained at least one parent selector
function replaceParentSelector(paths, context, inSelector) {
        var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false, length, lastSelector;
        function findNestedSelector(element) {
            var maybeSelector;
            if (!(element.value instanceof Paren)) {
                return null;
            }
            maybeSelector = element.value.value;
            if (!(maybeSelector instanceof Selector)) {
                return null;
            }
            return maybeSelector;
        }
         the elements from the current selector so far
        currentElements = [];
         the current list of new selectors to add to the path.
         We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
         by the parents
        newSelectors = [
            []
        ];
        for (i = 0; (el = inSelector.elements[i]); i++) {
             non parent reference elements just get added
            if (el.value !== "&") {
                var nestedSelector = findNestedSelector(el);
                if (nestedSelector != null) {
                     merge the current list of non parent selector elements
                     on to the current list of selectors to add
                    mergeElementsOnToSelectors(currentElements, newSelectors);
                    var nestedPaths = [], replaced, replacedNewSelectors = [];
                    replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
                    hadParentSelector = hadParentSelector || replaced;
                     the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
                    for (k = 0; k < nestedPaths.length; k++) {
                        var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
                        addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
                    }
                    newSelectors = replacedNewSelectors;
                    currentElements = [];
                } else {
                    currentElements.push(el);
                }
            } else {
                hadParentSelector = true;
                 the new list of selectors to add
                selectorsMultiplied = [];
                 merge the current list of non parent selector elements
                 on to the current list of selectors to add
                mergeElementsOnToSelectors(currentElements, newSelectors);
                 loop through our current selectors
                for (j = 0; j < newSelectors.length; j++) {
                    sel = newSelectors[j];
                     if we don't have any parent paths, the & might be in a mixin so that it can be used
                     whether there are parents or not
                    if (context.length === 0) {
                         the combinator used on el should now be applied to the next element instead so that
                         it is not lost
                        if (sel.length > 0) {
                            sel[0].elements.push(new Element(el.combinator, '', el._index, el._fileInfo));
                        }
                        selectorsMultiplied.push(sel);
                    }
                    else {
                         and the parent selectors
                        for (k = 0; k < context.length; k++) {
                             We need to put the current selectors
                             then join the last selector's elements on to the parents selectors
                            var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
                             add that to our new set of selectors
                            selectorsMultiplied.push(newSelectorPath);
                        }
                    }
                }
                 our new selectors has been multiplied, so reset the state
                newSelectors = selectorsMultiplied;
                currentElements = [];
            }
        }
         if we have any elements left over (e.g. .a& .b == .b)
         add them on to all the current selectors
        mergeElementsOnToSelectors(currentElements, newSelectors);
        for (i = 0; i < newSelectors.length; i++) {
            length = newSelectors[i].length;
            if (length > 0) {
                paths.push(newSelectors[i]);
                lastSelector = newSelectors[i][length - 1];
                newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList);
            }
        }
        return hadParentSelector;
    }
function replaceParentSelector ( paths , context , inSelector ) { var i , j , k , currentElements , newSelectors , selectorsMultiplied , sel , el , hadParentSelector = false , length , lastSelector ; function findNestedSelector ( element ) { var maybeSelector ; if ( ! ( element . value instanceof Paren ) ) { return null ; } maybeSelector = element . value . value ; if ( ! ( maybeSelector instanceof Selector ) ) { return null ; } return maybeSelector ; } currentElements = [ ] ; newSelectors = [ [ ] ] ; for ( i = 0 ; ( el = inSelector . elements [ i ] ) ; i ++ ) { if ( el . value !== "&" ) { var nestedSelector = findNestedSelector ( el ) ; if ( nestedSelector != null ) { mergeElementsOnToSelectors ( currentElements , newSelectors ) ; var nestedPaths = [ ] , replaced , replacedNewSelectors = [ ] ; replaced = replaceParentSelector ( nestedPaths , context , nestedSelector ) ; hadParentSelector = hadParentSelector || replaced ; for ( k = 0 ; k < nestedPaths . length ; k ++ ) { var replacementSelector = createSelector ( createParenthesis ( nestedPaths [ k ] , el ) , el ) ; addAllReplacementsIntoPath ( newSelectors , [ replacementSelector ] , el , inSelector , replacedNewSelectors ) ; } newSelectors = replacedNewSelectors ; currentElements = [ ] ; } else { currentElements . push ( el ) ; } } else { hadParentSelector = true ; selectorsMultiplied = [ ] ; mergeElementsOnToSelectors ( currentElements , newSelectors ) ; for ( j = 0 ; j < newSelectors . length ; j ++ ) { sel = newSelectors [ j ] ; if ( context . length === 0 ) { if ( sel . length > 0 ) { sel [ 0 ] . elements . push ( new Element ( el . combinator , '' , el . _index , el . _fileInfo ) ) ; } selectorsMultiplied . push ( sel ) ; } else { for ( k = 0 ; k < context . length ; k ++ ) { var newSelectorPath = addReplacementIntoPath ( sel , context [ k ] , el , inSelector ) ; selectorsMultiplied . push ( newSelectorPath ) ; } } } newSelectors = selectorsMultiplied ; currentElements = [ ] ; } } mergeElementsOnToSelectors ( currentElements , newSelectors ) ; for ( i = 0 ; i < newSelectors . length ; i ++ ) { length = newSelectors [ i ] . length ; if ( length > 0 ) { paths . push ( newSelectors [ i ] ) ; lastSelector = newSelectors [ i ] [ length - 1 ] ; newSelectors [ i ] [ length - 1 ] = lastSelector . createDerived ( lastSelector . elements , inSelector . extendList ) ; } } return hadParentSelector ; }
returns true if `inSelector` contained at least one parent selector
returns true if ` inSelector ` contained at least one parent selector
// The paths are [[Selector]] // The first list is a list of comma separated selectors // The inner list is a list of inheritance separated selectors // e.g. // .a, .b { //   .c { //   } // } // == [[.a] [.c]] [[.b] [.c]] // // the elements from the current selector so far // the current list of new selectors to add to the path. // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors // by the parents // non parent reference elements just get added // merge the current list of non parent selector elements // on to the current list of selectors to add // the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors // the new list of selectors to add // merge the current list of non parent selector elements // on to the current list of selectors to add // loop through our current selectors // if we don't have any parent paths, the & might be in a mixin so that it can be used // whether there are parents or not // the combinator used on el should now be applied to the next element instead so that // it is not lost // and the parent selectors // We need to put the current selectors // then join the last selector's elements on to the parents selectors // add that to our new set of selectors // our new selectors has been multiplied, so reset the state // if we have any elements left over (e.g. .a& .b == .b) // add them on to all the current selectors