static normalize(globList, restrictive = false) {
        const { _inspect, _covers, _intersect } = NotationGlob;

        const original = utils.ensureArray(globList);

        const list = original
            // prevent mutation
            .concat()
            // move negated globs to top so that we inspect non-negated globs
            // against others first. when complete, we'll sort with our
            // .compare() function.
            .sort(restrictive ? _negFirstSort : _negLastSort)
            // turning string array into inspect-obj array, so that we'll not
            // run _inspect multiple times in the inner loop. this also
            // pre-validates each glob.
            .map(_inspect);

        // early return if we have a single item
        if (list.length === 1) {
            const g = list[0];
            // single negated item is redundant
            if (g.isNegated) return [];
            // return normalized
            return [g.glob];
        }

        // flag to return an empty array (in restrictive mode), if true.
        let negateAll = false;

        // we'll push keepers in this array
        let normalized = [];
        // we'll need to remember excluded globs, so that we can move to next
        // item early.
        const ignored = {};

        // storage to keep intersections.
        // using an object to prevent duplicates.
        let intersections = {};

        const checkAddIntersection = (gA, gB) => {
            const inter = _intersect(gA, gB, restrictive);
            if (!inter) return;
            // if the intersection result has an inverted version in the
            // original list, don't add this.
            const hasInverted = restrictive ? false : original.indexOf(_invert(inter)) >= 0;
            // also if intersection result is in the current list, don't add it.
            if (list.indexOf(inter) >= 0 || hasInverted) return;
            intersections[inter] = inter;
        };

        // iterate each glob by comparing it to remaining globs.
        utils.eachRight(list, (a, indexA) => {

            // if `strict` is enabled, return empty if a negate-all is found
            // (which itself is also redundant if single): '!*' or '![*]'
            if (re.NEGATE_ALL.test(a.glob)) {
                negateAll = true;
                if (restrictive) return false;
            }

            // flags
            let duplicate = false;
            let hasExactNeg = false;
            // flags for negated
            let negCoversPos = false;
            let negCoveredByPos = false;
            let negCoveredByNeg = false;
            // flags for non-negated (positive)
            let posCoversPos = false;
            let posCoveredByNeg = false;
            let posCoveredByPos = false;

            utils.eachRight(list, (b, indexB) => {
                // don't inspect glob with itself
                if (indexA === indexB) return; // move to next
                // console.log(indexA, a.glob, 'vs', b.glob);

                // remove if duplicate
                if (a.glob === b.glob) {
                    list.splice(indexA, 1);
                    duplicate = true;
                    return false; // break out
                }

                // remove if positive has an exact negated (negated wins when
                // normalized) e.g. ['*', 'a', '!a'] => ['*', '!a']
                if (!a.isNegated && _isReverseOf(a, b)) {
                    // list.splice(indexA, 1);
                    ignored[a.glob] = true;
                    hasExactNeg = true;
                    return false; // break out
                }

                // if already excluded b, go on to next
                if (ignored[b.glob]) return; // next

                const coversB = _covers(a, b);
                const coveredByB = coversB ? false : _covers(b, a);
                if (a.isNegated) {
                    if (b.isNegated) {
                        // if negated (a) covered by any other negated (b); remove (a)!
                        if (coveredByB) {
                            negCoveredByNeg = true;
                            // list.splice(indexA, 1);
                            ignored[a.glob] = true;
                            return false; // break out
                        }
                    } else {
                        /* istanbul ignore if */
                        if (coversB) negCoversPos = true;
                        if (coveredByB) negCoveredByPos = true;
                        // try intersection if none covers the other and only
                        // one of them is negated.
                        if (!coversB && !coveredByB) {
                            checkAddIntersection(a.glob, b.glob);
                        }
                    }
                } else {
                    if (b.isNegated) {
                        // if positive (a) covered by any negated (b); remove (a)!
                        if (coveredByB) {
                            posCoveredByNeg = true;
                            if (restrictive) {
                                // list.splice(indexA, 1);
                                ignored[a.glob] = true;
                                return false; // break out
                            }
                            return; // next
                        }
                        // try intersection if none covers the other and only
                        // one of them is negated.
                        if (!coversB && !coveredByB) {
                            checkAddIntersection(a.glob, b.glob);
                        }
                    } else {
                        if (coversB) posCoversPos = coversB;
                        // if positive (a) covered by any other positive (b); remove (a)!
                        if (coveredByB) {
                            posCoveredByPos = true;
                            if (restrictive) {
                                // list.splice(indexA, 1);
                                return false; // break out
                            }
                        }
                    }
                }

            });

            // const keepNeg = (negCoversPos || negCoveredByPos) && !negCoveredByNeg;
            const keepNeg = restrictive
                ? (negCoversPos || negCoveredByPos) && negCoveredByNeg === false
                : negCoveredByPos && negCoveredByNeg === false;
            const keepPos = restrictive
                ? (posCoversPos || posCoveredByPos === false) && posCoveredByNeg === false
                : posCoveredByNeg || posCoveredByPos === false;
            const keep = duplicate === false
                && hasExactNeg === false
                && (a.isNegated ? keepNeg : keepPos);

            if (keep) {
                normalized.push(a.glob);
            } else {
                // this is excluded from final (normalized) list, so mark as
                // ignored (don't remove from "list" for now)
                ignored[a.glob] = true;
            }
        });

        if (restrictive && negateAll) return [];

        intersections = Object.keys(intersections);
        if (intersections.length > 0) {
            // merge normalized list with intersections if any
            normalized = normalized.concat(intersections);
            // we have new (intersection) items, so re-normalize
            return NotationGlob.normalize(normalized, restrictive);
        }

        return NotationGlob.sort(normalized);
    }
/**
     *  Normalizes the given notation globs array by removing duplicate or
     *  redundant items, eliminating extra verbosity (also with intersection
     *  globs) and returns a priority-sorted globs array.
     *
     *  <ul>
     *  <li>If any exact duplicates found, all except first is removed.
     *  <br />example: `['car', 'dog', 'car']` normalizes to `['car', 'dog']`.</li>
     *  <li>If both normal and negated versions of a glob are found, negated wins.
     *  <br />example: `['*', 'id', '!id']` normalizes to `['*', '!id']`.</li>
     *  <li>If a glob is covered by another, it's removed.
     *  <br />example: `['car.*', 'car.model']` normalizes to `['car']`.</li>
     *  <li>If a negated glob is covered by another glob, it's kept.
     *  <br />example: `['*', 'car', '!car.model']` normalizes as is.</li>
     *  <li>If a negated glob is not covered by another or it does not cover any other;
     *  then we check for for intersection glob. If found, adds them to list;
     *  removes the original negated.
     *  <br />example: `['car.*', '!*.model']` normalizes as to `['car', '!car.model']`.</li>
     *  <li>In restrictive mode; if a glob is covered by another negated glob, it's removed.
     *  Otherwise, it's kept.
     *  <br />example: `['*', '!car.*', 'car.model']` normalizes to `['*', '!car']` if restrictive.</li>
     *  </ul>
     *  @name Notation.Glob.normalize
     *  @function
     *  @param {Array} globList - Notation globs array to be normalized.
     *  @param {Boolean} [restrictive=false] - Whether negated items strictly
     *  remove every match. Note that, regardless of this option, if any item has an
     *  exact negated version; non-negated is always removed.
     *  @returns {Array} -
     *
     *  @throws {NotationError} - If any item in globs list is invalid.
     *
     *  @example
     *  const { normalize } = Notation.Glob;
     *  const globs = ['*', '!id', 'name', '!car.model', 'car.*', 'id', 'name'];
     *  normalize(globs)                            // ['*', '!id', '!car.model']
     *  normalize(['!*.id', 'user.*', 'company'])   // ['company', 'user', '!company.id', '!user.id']
     */
Normalizes the given notation globs array by removing duplicate or
redundant items, eliminating extra verbosity (also with intersection
globs) and returns a priority-sorted globs array.


If any exact duplicates found, all except first is removed.

@throws {NotationError} - If any item in globs list is invalid.


Normalizes the given notation globs array by removing duplicate or redundant items eliminating extra verbosity ( also with intersection globs ) and returns a priority - sorted globs array . If any exact duplicates found all except first is removed . @throws { NotationError } - If any item in globs list is invalid .
static normalize(globList, restrictive = false) {
        const { _inspect, _covers, _intersect } = NotationGlob;
        const original = utils.ensureArray(globList);
        const list = original
            .concat()
            .sort(restrictive ? _negFirstSort : _negLastSort)
            .map(_inspect);
        if (list.length === 1) {
            const g = list[0];
            if (g.isNegated) return [];
            return [g.glob];
        }
        let negateAll = false;
        let normalized = [];
        const ignored = {};
        let intersections = {};
        const checkAddIntersection = (gA, gB) => {
            const inter = _intersect(gA, gB, restrictive);
            if (!inter) return;
            const hasInverted = restrictive ? false : original.indexOf(_invert(inter)) >= 0;
            if (list.indexOf(inter) >= 0 || hasInverted) return;
            intersections[inter] = inter;
        };
        utils.eachRight(list, (a, indexA) => {
            if (re.NEGATE_ALL.test(a.glob)) {
                negateAll = true;
                if (restrictive) return false;
            }
            let duplicate = false;
            let hasExactNeg = false;
             for negated
            let negCoversPos = false;
            let negCoveredByPos = false;
            let negCoveredByNeg = false;
             for non-negated (positive)
            let posCoversPos = false;
            let posCoveredByNeg = false;
            let posCoveredByPos = false;
            utils.eachRight(list, (b, indexB) => {
                if (indexA === indexB) return; 
                if (a.glob === b.glob) {
                    list.splice(indexA, 1);
                    duplicate = true;
                    return false; 
                }
                if (!a.isNegated && _isReverseOf(a, b)) {
                    ignored[a.glob] = true;
                    hasExactNeg = true;
                    return false; 
                }
                if (ignored[b.glob]) return; 
                const coversB = _covers(a, b);
                const coveredByB = coversB ? false : _covers(b, a);
                if (a.isNegated) {
                    if (b.isNegated) {
                        if (coveredByB) {
                            negCoveredByNeg = true;
                            ignored[a.glob] = true;
                            return false; 
                        }
                    } else {
                        if (coversB) negCoversPos = true;
                        if (coveredByB) negCoveredByPos = true;
                        if (!coversB && !coveredByB) {
                            checkAddIntersection(a.glob, b.glob);
                        }
                    }
                } else {
                    if (b.isNegated) {
                        if (coveredByB) {
                            posCoveredByNeg = true;
                            if (restrictive) {
                                ignored[a.glob] = true;
                                return false; 
                            }
                            return; 
                        }
                        if (!coversB && !coveredByB) {
                            checkAddIntersection(a.glob, b.glob);
                        }
                    } else {
                        if (coversB) posCoversPos = coversB;
                        if (coveredByB) {
                            posCoveredByPos = true;
                            if (restrictive) {
                                return false; 
                            }
                        }
                    }
                }
            });
            const keepNeg = restrictive
                ? (negCoversPos || negCoveredByPos) && negCoveredByNeg === false
                : negCoveredByPos && negCoveredByNeg === false;
            const keepPos = restrictive
                ? (posCoversPos || posCoveredByPos === false) && posCoveredByNeg === false
                : posCoveredByNeg || posCoveredByPos === false;
            const keep = duplicate === false
                && hasExactNeg === false
                && (a.isNegated ? keepNeg : keepPos);
            if (keep) {
                normalized.push(a.glob);
            } else {
                ignored[a.glob] = true;
            }
        });
        if (restrictive && negateAll) return [];
        intersections = Object.keys(intersections);
        if (intersections.length > 0) {
            normalized = normalized.concat(intersections);
            return NotationGlob.normalize(normalized, restrictive);
        }
        return NotationGlob.sort(normalized);
    }
static normalize ( globList , restrictive = false ) { const { _inspect , _covers , _intersect } = NotationGlob ; const original = utils . ensureArray ( globList ) ; const list = original . concat ( ) . sort ( restrictive ? _negFirstSort : _negLastSort ) . map ( _inspect ) ; if ( list . length === 1 ) { const g = list [ 0 ] ; if ( g . isNegated ) return [ ] ; return [ g . glob ] ; } let negateAll = false ; let normalized = [ ] ; const ignored = { } ; let intersections = { } ; const checkAddIntersection = ( gA , gB ) => { const inter = _intersect ( gA , gB , restrictive ) ; if ( ! inter ) return ; const hasInverted = restrictive ? false : original . indexOf ( _invert ( inter ) ) >= 0 ; if ( list . indexOf ( inter ) >= 0 || hasInverted ) return ; intersections [ inter ] = inter ; } ; utils . eachRight ( list , ( a , indexA ) => { if ( re . NEGATE_ALL . test ( a . glob ) ) { negateAll = true ; if ( restrictive ) return false ; } let duplicate = false ; let hasExactNeg = false ; let negCoversPos = false ; let negCoveredByPos = false ; let negCoveredByNeg = false ; let posCoversPos = false ; let posCoveredByNeg = false ; let posCoveredByPos = false ; utils . eachRight ( list , ( b , indexB ) => { if ( indexA === indexB ) return ; if ( a . glob === b . glob ) { list . splice ( indexA , 1 ) ; duplicate = true ; return false ; } if ( ! a . isNegated && _isReverseOf ( a , b ) ) { ignored [ a . glob ] = true ; hasExactNeg = true ; return false ; } if ( ignored [ b . glob ] ) return ; const coversB = _covers ( a , b ) ; const coveredByB = coversB ? false : _covers ( b , a ) ; if ( a . isNegated ) { if ( b . isNegated ) { if ( coveredByB ) { negCoveredByNeg = true ; ignored [ a . glob ] = true ; return false ; } } else { if ( coversB ) negCoversPos = true ; if ( coveredByB ) negCoveredByPos = true ; if ( ! coversB && ! coveredByB ) { checkAddIntersection ( a . glob , b . glob ) ; } } } else { if ( b . isNegated ) { if ( coveredByB ) { posCoveredByNeg = true ; if ( restrictive ) { ignored [ a . glob ] = true ; return false ; } return ; } if ( ! coversB && ! coveredByB ) { checkAddIntersection ( a . glob , b . glob ) ; } } else { if ( coversB ) posCoversPos = coversB ; if ( coveredByB ) { posCoveredByPos = true ; if ( restrictive ) { return false ; } } } } } ) ; const keepNeg = restrictive ? ( negCoversPos || negCoveredByPos ) && negCoveredByNeg === false : negCoveredByPos && negCoveredByNeg === false ; const keepPos = restrictive ? ( posCoversPos || posCoveredByPos === false ) && posCoveredByNeg === false : posCoveredByNeg || posCoveredByPos === false ; const keep = duplicate === false && hasExactNeg === false && ( a . isNegated ? keepNeg : keepPos ) ; if ( keep ) { normalized . push ( a . glob ) ; } else { ignored [ a . glob ] = true ; } } ) ; if ( restrictive && negateAll ) return [ ] ; intersections = Object . keys ( intersections ) ; if ( intersections . length > 0 ) { normalized = normalized . concat ( intersections ) ; return NotationGlob . normalize ( normalized , restrictive ) ; } return NotationGlob . sort ( normalized ) ; }
Normalizes the given notation globs array by removing duplicate or
  redundant items, eliminating extra verbosity (also with intersection
  globs) and returns a priority-sorted globs array.
Normalizes the given notation globs array by removing duplicate or redundant items eliminating extra verbosity ( also with intersection globs ) and returns a priority - sorted globs array .
// prevent mutation // move negated globs to top so that we inspect non-negated globs // against others first. when complete, we'll sort with our // .compare() function. // turning string array into inspect-obj array, so that we'll not // run _inspect multiple times in the inner loop. this also // pre-validates each glob. // early return if we have a single item // single negated item is redundant // return normalized // flag to return an empty array (in restrictive mode), if true. // we'll push keepers in this array // we'll need to remember excluded globs, so that we can move to next // item early. // storage to keep intersections. // using an object to prevent duplicates. // if the intersection result has an inverted version in the // original list, don't add this. // also if intersection result is in the current list, don't add it. // iterate each glob by comparing it to remaining globs. // if `strict` is enabled, return empty if a negate-all is found // (which itself is also redundant if single): '!*' or '![*]' // flags // flags for negated // flags for non-negated (positive) // don't inspect glob with itself // move to next // console.log(indexA, a.glob, 'vs', b.glob); // remove if duplicate // break out // remove if positive has an exact negated (negated wins when // normalized) e.g. ['*', 'a', '!a'] => ['*', '!a'] // list.splice(indexA, 1); // break out // if already excluded b, go on to next // next // if negated (a) covered by any other negated (b); remove (a)! // list.splice(indexA, 1); // break out /* istanbul ignore if */ // try intersection if none covers the other and only // one of them is negated. // if positive (a) covered by any negated (b); remove (a)! // list.splice(indexA, 1); // break out // next // try intersection if none covers the other and only // one of them is negated. // if positive (a) covered by any other positive (b); remove (a)! // list.splice(indexA, 1); // break out // const keepNeg = (negCoversPos || negCoveredByPos) && !negCoveredByNeg; // this is excluded from final (normalized) list, so mark as // ignored (don't remove from "list" for now) // merge normalized list with intersections if any // we have new (intersection) items, so re-normalize