function score(target, query, cache) {
        if (!target || !query) {
            return 0; // return early if target or query are undefined
        }
        var hash = target + query;
        var cached = cache && cache[hash];
        if (typeof cached === 'number') {
            return cached;
        }
        var queryLen = query.length;
        var targetLower = target.toLowerCase();
        var queryLower = query.toLowerCase();
        var index = 0;
        var startAt = 0;
        var score = 0;
        var _loop_1 = function () {
            var indexOf = targetLower.indexOf(queryLower[index], startAt);
            if (indexOf < 0) {
                score = 0; // This makes sure that the query is contained in the target
                return "break";
            }
            // Character match bonus
            score += 1;
            // Consecutive match bonus
            if (startAt === indexOf) {
                score += 5;
            }
            // Same case bonus
            if (target[indexOf] === query[indexOf]) {
                score += 1;
            }
            // Start of word bonus
            if (indexOf === 0) {
                score += 8;
            }
            else if (wordPathBoundary.some(function (w) { return w === target[indexOf - 1]; })) {
                score += 7;
            }
            else if (isUpper(target.charCodeAt(indexOf))) {
                score += 1;
            }
            startAt = indexOf + 1;
            index++;
        };
        while (index < queryLen) {
            var state_1 = _loop_1();
            if (state_1 === "break")
                break;
        }
        if (cache) {
            cache[hash] = score;
        }
        return score;
    }
Compute a score for the given string and the given query.

Rules:
Character score: 1
Same case bonus: 1
Upper case bonus: 1
Consecutive match bonus: 5
Start of word/path bonus: 7
Start of string bonus: 8