<commit_before>/*
	compiles a selector to an executable function
*/

module.exports = compile;

var parse = require("CSSwhat"),
    Rules = require("./general.js"),
    sortRules = require("./sort.js"),
    BaseFuncs = require("./basefunctions.js"),
    rootFunc = BaseFuncs.rootFunc,
    trueFunc = BaseFuncs.trueFunc,
    falseFunc = BaseFuncs.falseFunc;

function compile(selector, options) {
    return parse(selector, options)
        .map(compileRules)
        .reduce(reduceRules, falseFunc);
}

function compileRules(arr) {
    return sortRules(arr).reduce(function(func, rule) {
        if (func === falseFunc) return func;
        return Rules[rule.type](func, rule);
    }, rootFunc);
}

function reduceRules(a, b) {
    if (a === trueFunc || b === rootFunc) return a;
    if (a === falseFunc || a === rootFunc || b === trueFunc) return b;

    return function combine(elem) {
        return a(elem) || b(elem);
    };
}

//:not and :has have to compile selectors
//doing this in lib/pseudos.js would lead to circular dependencies,
//so we add them here

var filters = require("./pseudos.js").filters,
    DomUtils = require("domutils"),
    findOne = DomUtils.findOne,
    getChildren = DomUtils.getChildren;

filters.not = function(next, select) {
    var func = compile(select);

    if (func === falseFunc) {
        return next === rootFunc ? trueFunc : next;
    }
    if (func === trueFunc || func === rootFunc) {
        return falseFunc;
    }

    return function(elem) {
        return !func(elem) && next(elem);
    };
};

filters.has = function(next, selector) {
    var func = compile(selector);

    if (func === rootFunc || func === trueFunc) return next;
    if (func === falseFunc) return falseFunc;

    return function proc(elem) {
        return findOne(func, getChildren(elem)) !== null && next(elem);
    };
};<commit_msg>[compile] reversed the order of :has<commit_after>/*
	compiles a selector to an executable function
*/

module.exports = compile;

var parse = require("CSSwhat"),
    Rules = require("./general.js"),
    sortRules = require("./sort.js"),
    BaseFuncs = require("./basefunctions.js"),
    rootFunc = BaseFuncs.rootFunc,
    trueFunc = BaseFuncs.trueFunc,
    falseFunc = BaseFuncs.falseFunc;

function compile(selector, options) {
    return parse(selector, options)
        .map(compileRules)
        .reduce(reduceRules, falseFunc);
}

function compileRules(arr) {
    return sortRules(arr).reduce(function(func, rule) {
        if (func === falseFunc) return func;
        return Rules[rule.type](func, rule);
    }, rootFunc);
}

function reduceRules(a, b) {
    if (a === trueFunc || b === rootFunc) return a;
    if (a === falseFunc || a === rootFunc || b === trueFunc) return b;

    return function combine(elem) {
        return a(elem) || b(elem);
    };
}

//:not and :has have to compile selectors
//doing this in lib/pseudos.js would lead to circular dependencies,
//so we add them here

var filters = require("./pseudos.js").filters,
    DomUtils = require("domutils"),
    findOne = DomUtils.findOne,
    getChildren = DomUtils.getChildren;

filters.not = function(next, select) {
    var func = compile(select);

    if (func === falseFunc) {
        return next === rootFunc ? trueFunc : next;
    }
    if (func === trueFunc || func === rootFunc) {
        return falseFunc;
    }

    return function(elem) {
        return !func(elem) && next(elem);
    };
};

filters.has = function(next, selector) {
    var func = compile(selector);

    if (func === rootFunc || func === trueFunc) return next;
    if (func === falseFunc) return falseFunc;

    return function proc(elem) {
        return next(elem) && findOne(func, getChildren(elem)) !== null;
    };
};
{'fraction_non_alphanumeric': 0.1464524765729585, 'fraction_numerical': 0.0, 'mean_word_length': 3.1145374449339207, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '862652', 'n_tokens_mistral': 1139, 'n_tokens_neox': 1118, 'n_words': 315}