<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var NullDependency = require("./NullDependency");
var HarmonyModulesHelpers = require("./HarmonyModulesHelpers");

function HarmonyImportSpecifierDependency(importDependency, importedVar, id, name, range) {
	NullDependency.call(this);
	this.importDependency = importDependency;
	this.importedVar = importedVar;
	this.id = id;
	this.name = name;
	this.range = range;
}
module.exports = HarmonyImportSpecifierDependency;

HarmonyImportSpecifierDependency.prototype = Object.create(NullDependency.prototype);
HarmonyImportSpecifierDependency.prototype.constructor = HarmonyImportSpecifierDependency;
HarmonyImportSpecifierDependency.prototype.type = "harmony import specifier";

HarmonyImportSpecifierDependency.prototype.getReference = function() {
	if(!this.importDependency.module) return null;
	return {
		module: this.importDependency.module,
		importedNames: this.id ? [this.id] : true
	};
};

HarmonyImportSpecifierDependency.prototype.getWarnings = function() {
	var importedModule = this.importDependency.module;
	if(importedModule && importedModule.meta && importedModule.meta.harmonyModule) {
		if(this.id && importedModule.isProvided(this.id) === false) {
			return [
				new Error("export '" + this.id + "'" +
					(this.id !== this.name ? " (imported as '" + this.name + "')" : "") +
					" was not found in '" + this.importDependency.userRequest + "'")
			];
		}
	}
};

HarmonyImportSpecifierDependency.prototype.updateHash = function(hash) {
	NullDependency.prototype.updateHash.call(this, hash);
	var importedModule = this.importDependency.module;
	hash.update((importedModule && importedModule.id) + "");
	hash.update((importedModule && this.id) + "");
	hash.update((importedModule && this.importedVar) + "");
	hash.update((importedModule && this.id && importedModule.isUsed(this.id)) + "");
	hash.update((importedModule && (!importedModule.meta || importedModule.meta.harmonyModule)) + "");
	hash.update((importedModule && (importedModule.used + JSON.stringify(importedModule.usedExports))) + "");
};

HarmonyImportSpecifierDependency.Template = function HarmonyImportSpecifierDependencyTemplate() {};

HarmonyImportSpecifierDependency.Template.prototype.apply = function(dep, source) {
	var content;
	var importedModule = dep.importDependency.module;
	var defaultImport = dep.directImport && dep.id === "default" && !(importedModule && (!importedModule.meta || importedModule.meta.harmonyModule));
	if(defaultImport) {
		content = dep.importedVar + "_default.a";
	} else if(dep.id) {
		var used = importedModule ? importedModule.isUsed(dep.id) : dep.id;
		content = dep.importedVar + "[" + JSON.stringify(used) + (dep.id !== used ? " /* " + dep.id + " */" : "") + "]";
	} else {
		content = dep.importedVar;
	}
	if(dep.call) {
		if(defaultImport) {
			content = dep.importedVar + "_default()";
		} else if(dep.id) {
			content = "__webpack_require__.i(" + content + ")";
		}
	}
	if(dep.shorthand) {
		content = dep.name + ": " + content;
	}
	source.replace(dep.range[0], dep.range[1] - 1, content);
};
<commit_msg>hide stack trace in export warnings<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var NullDependency = require("./NullDependency");
var HarmonyModulesHelpers = require("./HarmonyModulesHelpers");

function HarmonyImportSpecifierDependency(importDependency, importedVar, id, name, range) {
	NullDependency.call(this);
	this.importDependency = importDependency;
	this.importedVar = importedVar;
	this.id = id;
	this.name = name;
	this.range = range;
}
module.exports = HarmonyImportSpecifierDependency;

HarmonyImportSpecifierDependency.prototype = Object.create(NullDependency.prototype);
HarmonyImportSpecifierDependency.prototype.constructor = HarmonyImportSpecifierDependency;
HarmonyImportSpecifierDependency.prototype.type = "harmony import specifier";

HarmonyImportSpecifierDependency.prototype.getReference = function() {
	if(!this.importDependency.module) return null;
	return {
		module: this.importDependency.module,
		importedNames: this.id ? [this.id] : true
	};
};

HarmonyImportSpecifierDependency.prototype.getWarnings = function() {
	var importedModule = this.importDependency.module;
	if(importedModule && importedModule.meta && importedModule.meta.harmonyModule) {
		if(this.id && importedModule.isProvided(this.id) === false) {
			var err = new Error("export '" + this.id + "'" +
				(this.id !== this.name ? " (imported as '" + this.name + "')" : "") +
				" was not found in '" + this.importDependency.userRequest + "'");
			err.hideStack = true;
			return [
				err
			];
		}
	}
};

HarmonyImportSpecifierDependency.prototype.updateHash = function(hash) {
	NullDependency.prototype.updateHash.call(this, hash);
	var importedModule = this.importDependency.module;
	hash.update((importedModule && importedModule.id) + "");
	hash.update((importedModule && this.id) + "");
	hash.update((importedModule && this.importedVar) + "");
	hash.update((importedModule && this.id && importedModule.isUsed(this.id)) + "");
	hash.update((importedModule && (!importedModule.meta || importedModule.meta.harmonyModule)) + "");
	hash.update((importedModule && (importedModule.used + JSON.stringify(importedModule.usedExports))) + "");
};

HarmonyImportSpecifierDependency.Template = function HarmonyImportSpecifierDependencyTemplate() {};

HarmonyImportSpecifierDependency.Template.prototype.apply = function(dep, source) {
	var content;
	var importedModule = dep.importDependency.module;
	var defaultImport = dep.directImport && dep.id === "default" && !(importedModule && (!importedModule.meta || importedModule.meta.harmonyModule));
	if(defaultImport) {
		content = dep.importedVar + "_default.a";
	} else if(dep.id) {
		var used = importedModule ? importedModule.isUsed(dep.id) : dep.id;
		content = dep.importedVar + "[" + JSON.stringify(used) + (dep.id !== used ? " /* " + dep.id + " */" : "") + "]";
	} else {
		content = dep.importedVar;
	}
	if(dep.call) {
		if(defaultImport) {
			content = dep.importedVar + "_default()";
		} else if(dep.id) {
			content = "__webpack_require__.i(" + content + ")";
		}
	}
	if(dep.shorthand) {
		content = dep.name + ": " + content;
	}
	source.replace(dep.range[0], dep.range[1] - 1, content);
};
<|endoftext|>


<commit_before>/*
 * LocalStore key => "gh_search_text"
 *
 * FORMAT
 *      "gh_search_text" : {
 *          "text_search" : {
 *              "value" :  "SEARCH_STRING",
 *              "matches" : [ "FILENAME", "FILENAME" ]
 *          }
 *      }
 *
 * */

window.addEventListener ("load", main, false);

// global variable used to loop on focus elements
var current_focus_index = 0;
var total_matches = 0;

function first_focus()
{
    if (total_matches == 0)
        return;

    var id_name = "gh_ext_match_0";

    document.getElementById(id_name).focus();
}

function go_to_prev_focus()
{

    if (total_matches == 0)
        return;

    var tmp_index = current_focus_index - 1;

    if (tmp_index < 0) {
        console.log("lower bound");
        tmp_index = total_matches - 1;
    }

    current_focus_index = tmp_index;

    var id_name = "gh_ext_match_" + current_focus_index;

    document.getElementById(id_name).focus();

}

function go_to_next_focus()
{

    if (total_matches == 0)
        return;

    var tmp_index = current_focus_index + 1;
    if (tmp_index > (total_matches - 1))
        tmp_index = 0;

    current_focus_index = tmp_index;

    var id_name = "gh_ext_match_" + current_focus_index;

    document.getElementById(id_name).focus();

}

function focus_keyUp(e) {

    // ctrl + arrow_right
    if (e.ctrlKey && e.keyCode == 39) {
        go_to_next_focus();
    }
    // ctrl + arrow_left
    if (e.ctrlKey && e.keyCode == 37) {
        go_to_prev_focus();
    }

    // MAC -> command key
    if (e.metaKey && e.keyCode == 39) {
        go_to_next_focus();
    }
    // ctrl + arrow_left
    if (e.metaKey && e.keyCode == 37) {
        go_to_prev_focus();
    }

}

document.addEventListener('keyup', focus_keyUp, false);

function clean_page()
{
    // clean table_elem
    var table_elem = document.getElementById("ext_matches");
    while (table_elem.hasChildNodes()){
        table_elem.removeChild(table_elem.firstChild);
    }
}

/* remove data from storage */
function clean_data()
{
}

function store_last_search(text_search, matches)
{
    json_data = JSON.parse(localStorage.getItem("gh_text_search"));

    json_data["text_search"] = {"value": text_search, "matches" : matches };
    // TODO add history
    localStorage.setItem("gh_text_search" , JSON.stringify(json_data));
}

function highlight(container, what, match_color) {

    var content = container.innerText;
    if (content == "")
        return;

    var id_name = "gh_ext_match_" + total_matches;
    var  pattern = new RegExp('(' + what + ')','ig');

    // tabindex is still 0 because the focus is handeld by hand
    var new_content = content.replace(pattern, '$1');
    if (new_content != content )
    {
        container.innerHTML = new_content;
        total_matches++;
    }

}

function search_in_table_file(container, search_for)
{

    // these files have a table
    // class="highlight tab-size js-file-line-container"
    // container is div with itemprop=text

    var match_color = null;

    chrome.runtime.sendMessage({type: "getMatchColor"}, function(response) {

        match_color = response.data;

        table = container.querySelectorAll('[class="highlight tab-size js-file-line-container"]');
        if (table)
        {
            // iterate rows and for each row the cells
            for (var i = 0, row; row = table[0].rows[i]; i++) {

                for (var j = 0, col; col = row.cells[j]; j++) {

                    highlight(col, search_for, match_color);

                }// end cells
            } // end ROWS
        }

        first_focus();

    });
}

function search_and_highlight_text(container, search_for)
{

    var children = container.childNodes;

    if (children.length == 0)
    {
        // search the text
        var content = container;
        if (content.indexOf(search_for) > -1)
        {
            console.log("Match ");
            // TODO TODO TODO
        }
    } else {
        for (i = 0; i < children.length; i++)
            search_and_highlight_text(children[i], search_for);
    }

}

function highlight_matches_on_current_file()
{
    // get current location/path
    var window_path = window.location.pathname;

    // TODO must be changed, this is a work around
    // split using 'master', the second item is  the real path + filename
    var tmp = window_path.split('master');

    // remove '/'
    var current_file = tmp[1].substring(1);

    var ext_data = JSON.parse(localStorage.getItem("gh_text_search"));
    if (ext_data["text_search"] === null)
        return;

    var match_infos = ext_data['text_search'];

    var search_for = match_infos["value"];
    var matches    = match_infos["matches"];

    if (matches.indexOf(current_file) <= -1)
    {
        console.log("This file is not correct one");
        return;
    }
    console.log("You are searching for " + search_for);

    // check which kinfd of file we're talking about (code, markup ecc)
    //itemprop="text"
    var container =  document.querySelectorAll('[itemprop="text"]');
    if (container)
        search_in_table_file(container[0], search_for);
        //search_and_highlight_text(container[0], search_for);
    else
        console.log("something is missing");

}

function show_matches(matches)
{

    var table_elem = document.getElementById("ext_matches");
    if (table_elem != null)
    {
         for (i = 0; i < matches.length; i++)
         {
            var row_elem = table_elem.insertRow(i);
            row_elem.className += "js-navigation-item";

            var text_elem = document.createTextNode(matches[i]);
            var a_elem = document.createElement("a");
            a_elem.appendChild(text_elem);
            a_elem.style.marginLeft =  '10px';

            var path_name = window.location.pathname;
            var items = path_name.split("/");
            var href_value = items[2]+'/blob/master/'+matches[i];
            a_elem.setAttribute('href', href_value);

            row_elem.appendChild(a_elem);
         }

    } else {
        console.log("not found");
    }
}

function do_search()
{
    var content = document.getElementById("ext_search_bar").value;

    // clean match result table
    clean_page();

    if (content == "")
      return;

    var gh_request = new XMLHttpRequest();
    gh_request.onreadystatechange = function() {

        if (this.readyState == 4 && this.status == 422) {
            // console.log("No results");
			return;
        }

        if (this.readyState == 4 && this.status == 200) {

            var data_json =  eval("(" + this.responseText + ")");
            var elements = document.getElementsByClassName("js-navigation-open");

            var matches = [];

            for (i = 0; i < data_json["total_count"]; i++)
            {

                var tmp = data_json["items"][i]["path"];
                matches.push(data_json["items"][i]["path"]);
            }

            store_last_search(content, matches);

            show_matches(matches);
        }
    };

    var path_name = window.location.pathname;
    var items = path_name.split("/");

    var url_query ='https://api.github.com/search/code?q=' + content;
    url_query += "+in:file+repo:"+items[1]+"/"+items[2];

    gh_request.open("GET", url_query, true);
    gh_request.send();

}

function create_match_container()
{
    var matches_div = document.createElement("div");
    matches_div.setAttribute('class', 'ext_matchs_div');
    matches_div.className += " boxed-group clearfix announce";

    var title_h3 = document.createElement("h3");
    var text = document.createTextNode("Matches");
    title_h3.appendChild(text);

    var file_wrap_div = document.createElement('div');
    file_wrap_div.setAttribute('class', 'file-wrap');

    // create table
    var table_elem = document.createElement("table");
    table_elem.setAttribute('id', 'ext_matches');
    table_elem.className += "files js-navigation-container js-active-navigation-container";

    file_wrap_div.appendChild(table_elem);
    matches_div.appendChild(title_h3);

    matches_div.appendChild(file_wrap_div);
    return matches_div;

}

function keypress_handler(event)
{
    // enter has keyCode = 13, change it if you want to use another button
    if (event.keyCode == 13) {
        do_search();
        return false;
    }
}

function create_ext_search_div(file_nav_node)
{

        var search_div = document.createElement("div");
        search_div.className += "file";

        var container_div = document.createElement("div");
        container_div.setAttribute('id', 'ext_search_container')
        container_div.setAttribute('class', 'file-header');

        var search_label = document.createElement("label");
        var label_text = document.createTextNode("Search for: ");

        var input = document.createElement("input");
        input.setAttribute('type', 'text');
        input.setAttribute('id', 'ext_search_bar');
        input.setAttribute('class', 'form-control');
        input.setAttribute('placeholder', 'Search into code');

        input.addEventListener("keypress", keypress_handler);

        container_div.appendChild(label_text);
        container_div.appendChild(input);

        search_div.appendChild(container_div);
        var file_wrap_div = document.createElement('div');

        // create table
        var table_elem = document.createElement("table");
        table_elem.setAttribute('id', 'ext_matches');
        table_elem.className += "files js-navigation-container js-active-navigation-container";

        file_wrap_div.appendChild(table_elem);

        search_div.appendChild(file_wrap_div);

        file_nav_node.parentNode.insertBefore(search_div, file_nav_node);
        document.getElementById("ext_search_container").style.marginLeft = "auto";
        document.getElementById("ext_search_container").style.marginRight = "auto";

}

function init_content_script()
{
    // check if background color is stored
    if (localStorage.getItem("gh_text_search") === null)
    {
        var data = {};
        // init background color if it not exists
        data["text_search"] = {};

        localStorage.setItem("gh_text_search" , JSON.stringify(data));

    }

}

function main(evt) {

    // check if localStorage
    init_content_script();

    var file_nav = document.getElementsByClassName("commit-tease");
    if (file_nav)
    {

        var file_div = document.getElementsByClassName("file");

		// if exists element with class file probably we're in a page
		// with content file, so do no show the search bar
        if (file_div.length > 0)
        {
            // do not show search bar
            // but try to highlight the matches
            highlight_matches_on_current_file();
            return;
        }
        create_ext_search_div(file_nav[0]);
    }

}
<commit_msg>key pressed linux/MAC merged together<commit_after>/*
 * LocalStore key => "gh_search_text"
 *
 * FORMAT
 *      "gh_search_text" : {
 *          "text_search" : {
 *              "value" :  "SEARCH_STRING",
 *              "matches" : [ "FILENAME", "FILENAME" ]
 *          }
 *      }
 *
 * */

window.addEventListener ("load", main, false);

// global variable used to loop on focus elements
var current_focus_index = 0;
var total_matches = 0;

function first_focus()
{
    if (total_matches == 0)
        return;

    var id_name = "gh_ext_match_0";

    document.getElementById(id_name).focus();
}

function go_to_prev_focus()
{

    if (total_matches == 0)
        return;

    var tmp_index = current_focus_index - 1;

    if (tmp_index < 0) {
        console.log("lower bound");
        tmp_index = total_matches - 1;
    }

    current_focus_index = tmp_index;

    var id_name = "gh_ext_match_" + current_focus_index;

    document.getElementById(id_name).focus();

}

function go_to_next_focus()
{

    if (total_matches == 0)
        return;

    var tmp_index = current_focus_index + 1;
    if (tmp_index > (total_matches - 1))
        tmp_index = 0;

    current_focus_index = tmp_index;

    var id_name = "gh_ext_match_" + current_focus_index;

    document.getElementById(id_name).focus();

}

function focus_keyUp(e) {

    // (ctrl | command) + arrow_right
    if ((e.ctrlKey || e.metaKey) && (e.keyCode == 39)) {
        go_to_next_focus();
    }
    // (ctrl | command) + arrow_left
    if ((e.ctrlKey || e.metaKey) && (e.keyCode == 37)) {
        go_to_prev_focus();
    }

}

document.addEventListener('keyup', focus_keyUp, false);

function clean_page()
{
    // clean table_elem
    var table_elem = document.getElementById("ext_matches");
    while (table_elem.hasChildNodes()){
        table_elem.removeChild(table_elem.firstChild);
    }
}

/* remove data from storage */
function clean_data()
{
}

function store_last_search(text_search, matches)
{
    json_data = JSON.parse(localStorage.getItem("gh_text_search"));

    json_data["text_search"] = {"value": text_search, "matches" : matches };
    // TODO add history
    localStorage.setItem("gh_text_search" , JSON.stringify(json_data));
}

function highlight(container, what, match_color) {

    var content = container.innerText;
    if (content == "")
        return;

    var id_name = "gh_ext_match_" + total_matches;
    var  pattern = new RegExp('(' + what + ')','ig');

    // tabindex is still 0 because the focus is handeld by hand
    var new_content = content.replace(pattern, '$1');
    if (new_content != content )
    {
        container.innerHTML = new_content;
        total_matches++;
    }

}

function search_in_table_file(container, search_for)
{

    // these files have a table
    // class="highlight tab-size js-file-line-container"
    // container is div with itemprop=text

    var match_color = null;

    chrome.runtime.sendMessage({type: "getMatchColor"}, function(response) {

        match_color = response.data;

        table = container.querySelectorAll('[class="highlight tab-size js-file-line-container"]');
        if (table)
        {
            // iterate rows and for each row the cells
            for (var i = 0, row; row = table[0].rows[i]; i++) {

                for (var j = 0, col; col = row.cells[j]; j++) {

                    highlight(col, search_for, match_color);

                }// end cells
            } // end ROWS
        }

        first_focus();

    });
}

function search_and_highlight_text(container, search_for)
{

    var children = container.childNodes;

    if (children.length == 0)
    {
        // search the text
        var content = container;
        if (content.indexOf(search_for) > -1)
        {
            console.log("Match ");
            // TODO TODO TODO
        }
    } else {
        for (i = 0; i < children.length; i++)
            search_and_highlight_text(children[i], search_for);
    }

}

function highlight_matches_on_current_file()
{
    // get current location/path
    var window_path = window.location.pathname;

    // TODO must be changed, this is a work around
    // split using 'master', the second item is  the real path + filename
    var tmp = window_path.split('master');

    // remove '/'
    var current_file = tmp[1].substring(1);

    var ext_data = JSON.parse(localStorage.getItem("gh_text_search"));
    if (ext_data["text_search"] === null)
        return;

    var match_infos = ext_data['text_search'];

    var search_for = match_infos["value"];
    var matches    = match_infos["matches"];

    if (matches.indexOf(current_file) <= -1)
    {
        console.log("This file is not correct one");
        return;
    }
    console.log("You are searching for " + search_for);

    // check which kinfd of file we're talking about (code, markup ecc)
    //itemprop="text"
    var container =  document.querySelectorAll('[itemprop="text"]');
    if (container)
        search_in_table_file(container[0], search_for);
        //search_and_highlight_text(container[0], search_for);
    else
        console.log("something is missing");

}

function show_matches(matches)
{

    var table_elem = document.getElementById("ext_matches");
    if (table_elem != null)
    {
         for (i = 0; i < matches.length; i++)
         {
            var row_elem = table_elem.insertRow(i);
            row_elem.className += "js-navigation-item";

            var text_elem = document.createTextNode(matches[i]);
            var a_elem = document.createElement("a");
            a_elem.appendChild(text_elem);
            a_elem.style.marginLeft =  '10px';

            var path_name = window.location.pathname;
            var items = path_name.split("/");
            var href_value = items[2]+'/blob/master/'+matches[i];
            a_elem.setAttribute('href', href_value);

            row_elem.appendChild(a_elem);
         }

    } else {
        console.log("not found");
    }
}

function do_search()
{
    var content = document.getElementById("ext_search_bar").value;

    // clean match result table
    clean_page();

    if (content == "")
      return;

    var gh_request = new XMLHttpRequest();
    gh_request.onreadystatechange = function() {

        if (this.readyState == 4 && this.status == 422) {
            // console.log("No results");
			return;
        }

        if (this.readyState == 4 && this.status == 200) {

            var data_json =  eval("(" + this.responseText + ")");
            var elements = document.getElementsByClassName("js-navigation-open");

            var matches = [];

            for (i = 0; i < data_json["total_count"]; i++)
            {

                var tmp = data_json["items"][i]["path"];
                matches.push(data_json["items"][i]["path"]);
            }

            store_last_search(content, matches);

            show_matches(matches);
        }
    };

    var path_name = window.location.pathname;
    var items = path_name.split("/");

    var url_query ='https://api.github.com/search/code?q=' + content;
    url_query += "+in:file+repo:"+items[1]+"/"+items[2];

    gh_request.open("GET", url_query, true);
    gh_request.send();

}

function create_match_container()
{
    var matches_div = document.createElement("div");
    matches_div.setAttribute('class', 'ext_matchs_div');
    matches_div.className += " boxed-group clearfix announce";

    var title_h3 = document.createElement("h3");
    var text = document.createTextNode("Matches");
    title_h3.appendChild(text);

    var file_wrap_div = document.createElement('div');
    file_wrap_div.setAttribute('class', 'file-wrap');

    // create table
    var table_elem = document.createElement("table");
    table_elem.setAttribute('id', 'ext_matches');
    table_elem.className += "files js-navigation-container js-active-navigation-container";

    file_wrap_div.appendChild(table_elem);
    matches_div.appendChild(title_h3);

    matches_div.appendChild(file_wrap_div);
    return matches_div;

}

function keypress_handler(event)
{
    // enter has keyCode = 13, change it if you want to use another button
    if (event.keyCode == 13) {
        do_search();
        return false;
    }
}

function create_ext_search_div(file_nav_node)
{

        var search_div = document.createElement("div");
        search_div.className += "file";

        var container_div = document.createElement("div");
        container_div.setAttribute('id', 'ext_search_container')
        container_div.setAttribute('class', 'file-header');

        var search_label = document.createElement("label");
        var label_text = document.createTextNode("Search for: ");

        var input = document.createElement("input");
        input.setAttribute('type', 'text');
        input.setAttribute('id', 'ext_search_bar');
        input.setAttribute('class', 'form-control');
        input.setAttribute('placeholder', 'Search into code');

        input.addEventListener("keypress", keypress_handler);

        container_div.appendChild(label_text);
        container_div.appendChild(input);

        search_div.appendChild(container_div);
        var file_wrap_div = document.createElement('div');

        // create table
        var table_elem = document.createElement("table");
        table_elem.setAttribute('id', 'ext_matches');
        table_elem.className += "files js-navigation-container js-active-navigation-container";

        file_wrap_div.appendChild(table_elem);

        search_div.appendChild(file_wrap_div);

        file_nav_node.parentNode.insertBefore(search_div, file_nav_node);
        document.getElementById("ext_search_container").style.marginLeft = "auto";
        document.getElementById("ext_search_container").style.marginRight = "auto";

}

function init_content_script()
{
    // check if background color is stored
    if (localStorage.getItem("gh_text_search") === null)
    {
        var data = {};
        // init background color if it not exists
        data["text_search"] = {};

        localStorage.setItem("gh_text_search" , JSON.stringify(data));

    }

}

function main(evt) {

    // check if localStorage
    init_content_script();

    var file_nav = document.getElementsByClassName("commit-tease");
    if (file_nav)
    {

        var file_div = document.getElementsByClassName("file");

		// if exists element with class file probably we're in a page
		// with content file, so do no show the search bar
        if (file_div.length > 0)
        {
            // do not show search bar
            // but try to highlight the matches
            highlight_matches_on_current_file();
            return;
        }
        create_ext_search_div(file_nav[0]);
    }

}
<|endoftext|>


<commit_before>var util = require("util");
var Type = require('./Type.js').abstract;

function Gauge(name, config){
    Gauge.super_.call(this,name,config);

    this.defaultType = 'sum';
    this.metric = config.metrics.name;
   // if ( config.from.name ) this.valid[config.from.name] = config.from;

};

util.inherits(Gauge, Type);
Gauge.prototype.payload = function() {
    var value = this.value(this.metric);
    if ( !value ) return false;

    var from = this.config.from.value;
    if ( !from ) from = this.value(this.config.from.name)
    else return {value:value/from};
};

exports.type = Gauge;<commit_msg>Finished Gauge and Number, i hope<commit_after>var util = require("util");
var Type = require('./Type.js').abstract;

function Gauge(name, config){
    Gauge.super_.call(this,name,config);

    this.defaultType = 'sum';
    this.metric = config.metrics.name;

    this.from = config.from;
    if ( !config.from.value ) this.add(config.from);
};

util.inherits(Gauge, Type);
Gauge.prototype.payload = function() {
    var value = this.value(this.metric);
    if ( !value ) return false;

    if ( !this.from.value ) var from = this.value(this.from.name);
    else var from = {data: this.from.value};

    if ( !from.data || !value.data ) return false;
    return {value:value.data/from.data};
};

exports.type = Gauge;<|endoftext|>


<commit_before>/*!
 * Cookies.js - 0.1.5
 * Saturday, May 06 2012 @ 5:53 PM EST
 *
 * Copyright (c) 2012, Scott Hamper
 * Licensed under the MIT license,
 * http://www.opensource.org/licenses/MIT
 */
(function (document, undefined) {

    var Cookies = function () {
        var args = Array.prototype.slice.call(arguments);
        if (args.length === 1) {
            return Cookies.get(args[0]);
        } else if (args[1] === undefined) {
            return Cookies.expire(args[0], args[2]);
        } else {
            return Cookies.set(args[0], args[1], args[2]);
        }
    };

    Cookies.get = function (key) {
        if (document.cookie !== Cookies._cacheString) {
            Cookies._populateCache();
        }

        return Cookies._cache[key];
    };

    Cookies.defaults = {
        path: '/'
    };

    Cookies.set = function (key, value, options) {
        var options = {
            path: options && options.path || Cookies.defaults.path,
            domain: options && options.domain || Cookies.defaults.domain,
            expires: options && options.expires || Cookies.defaults.expires,
            secure: options && options.secure !== undefined ? options.secure : Cookies.defaults.secure
        };

        switch (typeof options.expires) {
            // If a number is passed in, make it work like 'max-age'
            case 'number': options.expires = new Date(new Date().getTime() + options.expires * 1000); break;
            // Allow multiple string formats for dates
            case 'string': options.expires = new Date(options.expires); break;
        }

        var cookieString = encodeURIComponent(key) + '=' + encodeURIComponent(JSON.stringify(value));
        cookieString += options.path ? ';path=' + options.path : '';
        cookieString += options.domain ? ';domain=' + options.domain : '';
        cookieString += options.expires ? ';expires=' + options.expires.toGMTString() : '';
        cookieString += options.secure ? ';secure' : '';

        document.cookie = cookieString;

        return Cookies;
    };

    Cookies.expire = function (key, options) {
        return Cookies.set(key, '', {
            path: options && options.path,
            domain: options && options.domain,
            expires: -1
        });
    };

    Cookies._populateCache = function () {
        Cookies._cache = {};
        Cookies._cacheString = document.cookie;

        var cookiesArray = Cookies._cacheString.split(';');
        for (var i = 0; i < cookiesArray.length; i++) {
            var cookieKvp = typeof String.prototype.trim === 'function' ?
                cookiesArray[i].trim().split('=') : cookiesArray[i].replace(/^\s+|\s+$/g, '').split('=');

            var key = decodeURIComponent(cookieKvp[0]);
            var value = decodeURIComponent(cookieKvp[1]);

            // The first instance of a key in the document.cookie string
            // is the most locally scoped cookie with the specified key.
            // The value of this key will be sent to the web server, so we'll
            // just ignore any other instances of the key.
            if (Cookies._cache[key] === undefined) {
                try { value = JSON.parse(value); } catch (ex) { }
                Cookies._cache[key] = value;
            }
        }
    };

    Cookies.enabled = (function () {
        var isEnabled = Cookies.set('cookies.js', 1).get('cookies.js') === 1;
        Cookies.expire('cookies.js');
        return isEnabled;
    })();

    // AMD support
    if (typeof define === 'function' && define.amd) {
        define(function () { return Cookies; });
    // CommonJS support with backwards compatibility for the old `require` API.
    } else if (typeof exports !== 'undefined') {
        if (typeof module != 'undefined' && module.exports) {
            exports = module.exports = Cookies;
        }
        exports.Cookies = Cookies;
    } else {
        window.Cookies = Cookies;
    }

})(document);<commit_msg>Simplified how the 'document.cookie' string gets parsed.<commit_after>/*!
 * Cookies.js - 0.1.5
 * Saturday, May 06 2012 @ 5:53 PM EST
 *
 * Copyright (c) 2012, Scott Hamper
 * Licensed under the MIT license,
 * http://www.opensource.org/licenses/MIT
 */
(function (document, undefined) {

    var Cookies = function () {
        var args = Array.prototype.slice.call(arguments);
        if (args.length === 1) {
            return Cookies.get(args[0]);
        } else if (args[1] === undefined) {
            return Cookies.expire(args[0], args[2]);
        } else {
            return Cookies.set(args[0], args[1], args[2]);
        }
    };

    Cookies.get = function (key) {
        if (document.cookie !== Cookies._cacheString) {
            Cookies._populateCache();
        }

        return Cookies._cache[key];
    };

    Cookies.defaults = {
        path: '/'
    };

    Cookies.set = function (key, value, options) {
        var options = {
            path: options && options.path || Cookies.defaults.path,
            domain: options && options.domain || Cookies.defaults.domain,
            expires: options && options.expires || Cookies.defaults.expires,
            secure: options && options.secure !== undefined ? options.secure : Cookies.defaults.secure
        };

        switch (typeof options.expires) {
            // If a number is passed in, make it work like 'max-age'
            case 'number': options.expires = new Date(new Date().getTime() + options.expires * 1000); break;
            // Allow multiple string formats for dates
            case 'string': options.expires = new Date(options.expires); break;
        }

        var cookieString = encodeURIComponent(key) + '=' + encodeURIComponent(JSON.stringify(value));
        cookieString += options.path ? ';path=' + options.path : '';
        cookieString += options.domain ? ';domain=' + options.domain : '';
        cookieString += options.expires ? ';expires=' + options.expires.toGMTString() : '';
        cookieString += options.secure ? ';secure' : '';

        document.cookie = cookieString;

        return Cookies;
    };

    Cookies.expire = function (key, options) {
        return Cookies.set(key, '', {
            path: options && options.path,
            domain: options && options.domain,
            expires: -1
        });
    };

    Cookies._populateCache = function () {
        Cookies._cache = {};
        Cookies._cacheString = document.cookie;

        var cookiesArray = Cookies._cacheString.split(';');
        for (var i = 0; i < cookiesArray.length; i++) {
            var cookieKvp = cookiesArray[i].split('=');
            var key = decodeURIComponent(cookieKvp[0]);
            var value = decodeURIComponent(cookieKvp[1]);

            // The first instance of a key in the document.cookie string
            // is the most locally scoped cookie with the specified key.
            // The value of this key will be sent to the web server, so we'll
            // just ignore any other instances of the key.
            if (Cookies._cache[key] === undefined) {
                try { value = JSON.parse(value); } catch (ex) { }
                Cookies._cache[key] = value;
            }
        }
    };

    Cookies.enabled = (function () {
        var isEnabled = Cookies.set('cookies.js', 1).get('cookies.js') === 1;
        Cookies.expire('cookies.js');
        return isEnabled;
    })();

    // AMD support
    if (typeof define === 'function' && define.amd) {
        define(function () { return Cookies; });
    // CommonJS support with backwards compatibility for the old `require` API.
    } else if (typeof exports !== 'undefined') {
        if (typeof module != 'undefined' && module.exports) {
            exports = module.exports = Cookies;
        }
        exports.Cookies = Cookies;
    } else {
        window.Cookies = Cookies;
    }

})(document);<|endoftext|>


<commit_before>String.prototype.lpad = function(padString, length) {
    var str = this;
    while (str.length < length)
        str = padString + str;
    return str;
};

String.prototype.rpad = function(padString, length) {
    var str = this;
    while (str.length < length)
        str = str + padString;
    return str;
};

function getCaretPosition(node) {
    var caret, linestart, linenum, x, y, statusbar;
    var colnumLabel, linenumLabel, charcountLabel;
    var linenum = 1;
    var el = node.get(0);
    var content = node.val();

    caret = (el.selectionStart || el.selectionStart == '0')
        ? el.selectionStart : 0;

    linestart = caret;
    while (linestart-- > 0) if (content.charAt(linestart) == '\n') linenum++;

    linestart = caret;
    while (linestart-- > 0) if (content.charAt(linestart) == '\n') break;

    x = node.position().left;
    y = node.outerHeight(true) + node.position().top;

    if ($('#chromextTextareaStatusBar').length < 1) {
        node.after($('

')
                   .attr('id', 'chromextTextareaStatusBar')
                   .css({position: 'absolute',
                         top: y + 'px',
                         left: x + 'px',
                         padding: '0 .5em',
                         fontSize: '.8em',
                         fontFamily: 'monospace',
                         backgroundColor: 'white',
                         border: '1px solid gray',
                         whiteSpace: 'pre'
                        }));
    }

    colnumLabel= ('Col: ' + (caret - linestart)).rpad(' ', 10);
    linenumLabel = ('Ln: ' + linenum).rpad(' ', 8);
    charcountLabel = ('Len: ' + content.length).lpad(' ', 10);

    $('#chromextTextareaStatusBar')
        .html(linenumLabel + ' ' + colnumLabel + charcountLabel)
        .css({top: y + 'px', left: x + 'px'})
        .show();
}

$('textarea').live('keyup', function() { getCaretPosition($(this)); });
$('textarea').live('click', function() { getCaretPosition($(this)); });
$('textarea')
    .live('blur', function() { $('#chromextTextareaStatusBar').hide(); });

<commit_msg>Fix disgusting double loop from 2am...<commit_after>String.prototype.lpad = function(padString, length) {
    var str = this;
    while (str.length < length)
        str = padString + str;
    return str;
};

String.prototype.rpad = function(padString, length) {
    var str = this;
    while (str.length < length)
        str = str + padString;
    return str;
};

function getCaretPosition(node) {
    var linenum = 1;
    var linestart = -1;
    var el = node.get(0);
    var content = node.val();

    var caret = (el.selectionStart || el.selectionStart == '0')
        ? el.selectionStart : 0;

    var cnt = caret;
    while (cnt-- > 0) {
        if (content.charAt(cnt) == '\n') {
            linenum++;
            if (linestart < 0) linestart = cnt;
        }
    }

    var x = node.position().left;
    var y = node.outerHeight(true) + node.position().top;

    if ($('#chromextTextareaStatusBar').length < 1) {
        node.after($('

')
                   .attr('id', 'chromextTextareaStatusBar')
                   .css({position: 'absolute',
                         top: y + 'px',
                         left: x + 'px',
                         padding: '0 .5em',
                         fontSize: '.8em',
                         fontFamily: 'monospace',
                         backgroundColor: 'white',
                         border: '1px solid gray',
                         whiteSpace: 'pre'
                        }));
    }

    var colnumLabel= ('Col: ' + (caret - linestart)).rpad(' ', 10);
    var linenumLabel = ('Ln: ' + linenum).rpad(' ', 8);
    var charcountLabel = ('Len: ' + content.length).lpad(' ', 10);

    $('#chromextTextareaStatusBar')
        .html(linenumLabel + ' ' + colnumLabel + charcountLabel)
        .css({top: y + 'px', left: x + 'px'})
        .show();
}

$('textarea').live('keyup', function() { getCaretPosition($(this)); });
$('textarea').live('click', function() { getCaretPosition($(this)); });
$('textarea')
    .live('blur', function() { $('#chromextTextareaStatusBar').hide(); });

<|endoftext|>


<commit_before>const serverURL = 'http://glacial-cove-76906.herokuapp.com';

function getVotes(shoutId,cb){
	$.get(serverURL+'/get-votes?shout_id='+shoutId,function(res,status){
		return cb(res,status);
	});
}

function renderButtons(){

	$('.shout-footer > .s-action-list').each(function(){
		var self = this;
		var shoutId = $(this).attr('data-id') ? $(this).attr('data-id') .trim() : '' ;
		var $container = $($(self).closest('.activity-element'));
		//Fabi
		if($container.hasClass('negative-added'))
			return true; //continue

		var button = $(
			`

`);

		$(self).find('div.require-login.button-action-s.action-vote.hastipsy.pointer').before(button);
		//Mark as added - Fabi
		$container.addClass('negative-added');

		getVotes(shoutId,function(res,status){
			button.find('span.like_count').text(res?res.count:'0');
			button.on('click', function(event){
				event.preventDefault();
				var likes = parseInt(button.find('span.like_count').text());
				button.find('span.like_count').text(likes+1);
				vote(shoutId);
				button.off('click');
			});
		});
	});

	$('.list-main-actions').each(function(){
		var self = this;
		var shoutId = $(this).find('.shout-action-like').attr('data-id').trim();
		var $container = $($(self).closest('.shout-item'));
		//Fabi
		if($container.hasClass('negative-added'))
			return true; //continue

		var button = $(
			`

`);
		//Mark as added - Fabi
		$container.addClass('negative-added');
		$(self).append(button);

		getVotes(shoutId,function(res,status){
			button.find('span.like_count').text(res?res.count:'0');
			button.on('click', function(event){
				event.preventDefault();
				var likes = parseInt(button.find('span.like_count').text());
				button.find('span.like_count').text(likes+1);
				vote(shoutId);
				button.off('click');
			});
		});
	})

	$('article.shoutsb').each(function(){
		var self = this;
		var shoutId = $(this).attr('data-id') ? $(this).attr('data-id') .trim() : '' ;
		getVotes(shoutId,function(res,status){
			var button = $(
			`

					${res?res.count:'0'}

			`);
			$(self).find('.like.shoutsb__like.icon-pulgararriba').after(button);
			button.on('click', function(event){
				event.preventDefault();
				var likes = parseInt(button.find('span.like_count').text());
				button.find('span.like_count').text(likes+1);
				vote(shoutId);
				button.off('click');
			});
		});
	});

}

function vote(shoutId){

	var avatarUrl = '';
	var user_id = '';
	var nick = $('.user-name').text().trim();

	$.get('http://api.taringa.net/user/nick/view/'+nick,function(res,status){
		user_id = res.id;
		avatarUrl=res.avatar? res.avatar.medium:'';
		$.post(serverURL+'/vote',{
			shout_id:shoutId,
			avatarUrl:avatarUrl,
			nick:nick,
			user_id:user_id
		},function(res,status){
			console.log(res,status);
		});
	})
}

$(document).ready(function(){
	//Stylesheet
	var Stylesheet =".button-action-s.no-me-gusta .action-number{float:right;} .button-action-s.no-me-gusta .icon-pulgarabajo{float:left;margin:2px 11px;margin-right:2px;} ";
	$('head').append('');
	renderButtons();
});

//Fabi
if(window.location.pathname ==='/mi'){
	// /mi
	$('#Feed-list').onResize().on('resize',function(event){
		renderButtons();
	});
}else{
	//shouts
	$('.shouts-list').onResize().on('resize',function(event){
		renderButtons();
	});
}<commit_msg>Add activity of dislikes in shouts<commit_after>const serverURL = 'http://glacial-cove-76906.herokuapp.com';

function getVotes(shoutId,cb){
	$.get(serverURL+'/get-votes?shout_id='+shoutId,function(res,status){
		return cb(res,status);
	});
}

function renderButtons(){

	$('.shout-footer > .s-action-list').each(function(){
		var self = this;
		var shoutId = $(this).attr('data-id') ? $(this).attr('data-id') .trim() : '' ;
		var $container = $($(self).closest('.activity-element'));
		//Fabi
		if($container.hasClass('negative-added'))
			return true; //continue

		var button = $(
			`

`);

		$(self).find('div.require-login.button-action-s.action-vote.hastipsy.pointer').before(button);
		//Mark as added - Fabi
		$container.addClass('negative-added');

		getVotes(shoutId,function(res,status){
			button.find('span.like_count').text(res?res.count:'0');
			button.on('click', function(event){
				event.preventDefault();
				var likes = parseInt(button.find('span.like_count').text());
				button.find('span.like_count').text(likes+1);
				vote(shoutId);
				button.off('click');
			});
		});
	});

	$('.shout-footer').each(function(){
		var actions = $(this).find('.s-action-list');
		var shoutId = actions? actions.attr('data-id') .trim() : '' ;
		var self = this;
		$(this).find('a.button-action-s.action-activity.hastipsy').on('click',function(e){
			if($(this).hasClass('.activity-already-loaded'))
				return;
			$(this).addClass('.activity-already-loaded');
			var list = $(self).parent().parent().find('.list.small-list.activity-log.hide');
			getVotes(shoutId,function(res,status){console.log("llamado!");
				if(res){
					res.voters.forEach(user=>{
						console.log(user.date);
						var element=$(
						`

						   a @${user.nick} no le gustó

`
						)
						list.prepend(element);
					})
				}
			});

		})
	})

	$('.list-main-actions').each(function(){
		var self = this;
		var shoutId = $(this).find('.shout-action-like').attr('data-id').trim();
		var $container = $($(self).closest('.shout-item'));
		//Fabi
		if($container.hasClass('negative-added'))
			return true; //continue

		var button = $(
			`

`);
		//Mark as added - Fabi
		$container.addClass('negative-added');
		$(self).append(button);

		getVotes(shoutId,function(res,status){
			button.find('span.like_count').text(res?res.count:'0');
			button.on('click', function(event){
				event.preventDefault();
				var likes = parseInt(button.find('span.like_count').text());
				button.find('span.like_count').text(likes+1);
				vote(shoutId);
				button.off('click');
			});
		});
	})

	$('article.shoutsb').each(function(){
		var self = this;
		var shoutId = $(this).attr('data-id') ? $(this).attr('data-id') .trim() : '' ;
		getVotes(shoutId,function(res,status){
			var button = $(
			`

					${res?res.count:'0'}

			`);
			$(self).find('.like.shoutsb__like.icon-pulgararriba').after(button);
			button.on('click', function(event){
				event.preventDefault();
				var likes = parseInt(button.find('span.like_count').text());
				button.find('span.like_count').text(likes+1);
				vote(shoutId);
				button.off('click');
			});
		});
	});

}

function vote(shoutId){

	var avatarUrl = '';
	var user_id = '';
	var nick = $('.user-name').text().trim();

	$.get('http://api.taringa.net/user/nick/view/'+nick,function(res,status){
		user_id = res.id;
		avatarUrl=res.avatar? res.avatar.medium:'';
		$.post(serverURL+'/vote',{
			shout_id:shoutId,
			avatarUrl:avatarUrl,
			nick:nick,
			user_id:user_id
		},function(res,status){
			console.log(res,status);
		});
	})
}

$(document).ready(function(){
	//Stylesheet
	var Stylesheet =".button-action-s.no-me-gusta .action-number{float:right;} .button-action-s.no-me-gusta .icon-pulgarabajo{float:left;margin:2px 11px;margin-right:2px;} ";
	$('head').append('');
	renderButtons();
});

//Fabi
if(window.location.pathname ==='/mi'){
	// /mi
	$('#Feed-list').onResize().on('resize',function(event){
		renderButtons();
	});
}else{
	//shouts
	$('.shouts-list').onResize().on('resize',function(event){
		renderButtons();
	});
}<|endoftext|>


<commit_before>// async cookies API polyfill for document contexts
if (self.document) (function() {
  const DISALLOWED_IN_COOKIE_NAME_RE = /[()<>@,;:\\""\/\[\]?={} \0-\x1f\x7f]|[^\x21-\x7e\u00A0-\uFFFD]/;
  const DISALLOWED_IN_COOKIE_VALUE_RE = /[^\x2D-\x3A\x21\x23-\x2B\x3C-\x5B\x5D-\x7E\u00A0-\uFFFD]/;
  // based on https://tools.ietf.org/html/rfc3986#appendix-B
  const uriRegExp = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/;
  const uriSchemeGroup = 2;
  const uriAuthorityGroup = 4;
  const uriPathGroup = 5;
  const defUriGroups = String(location.href).match(uriRegExp) || [];
  const dirName = path => path.replace(/(^|\/)\.\.$/, '$1../').replace(/[^\/]+$/, '');
  const defReadPath = dirName(defUriGroups[uriPathGroup] || '/');
  const defOrigin = defUriGroups[uriSchemeGroup] + '://' + defUriGroups[uriAuthorityGroup];
  const defSecure = defUriGroups[uriSchemeGroup] === 'https:';
  const resolvePath = path => {
    path = String(path || defReadPath);
    if (path[0] !== '/') path = defReadPath + path;
    let pathSegments = path.split('/');
    let resolvedPathSegments = [];
    pathSegments.forEach(segment => {
      if (segment === '..') resolvedPathSegments.pop();
      else resolvedPathSegments.push(segment);
    });
    return resolvedPathSegments.join('/');
  };
  const readPathForUrl = url => {
    if (url == null) url = defReadPath;
    url = String(url);
    const urlGroups = url.match(uriRegExp) || [];
    const urlPath = resolvePath(dirName(String(urlGroups[uriPathGroup] || defReadPath)));
    const origin = [
      urlGroups[uriSchemeGroup] || defUriGroups[uriSchemeGroup],
      urlGroups[uriAuthorityGroup] || defUriGroups[uriAuthorityGroup]].join('://').toLowerCase();
    if ((origin + urlPath) !== (defOrigin + defReadPath)) {
      // TODO: iframe with unpredictable long pathname inside
      // requested path, maybe by appending as many
      // randomly-selected '$' and ':' as needed to reach 2083 chars
      // in the URL could be used to read same-origin, different-path cookies.
      throw new SyntaxError([
        'Cannot read cookies at requested URL ',
        JSON.stringify(url),
        ' from ',
        JSON.stringify(defOrigin + defReadPath),
        ': not yet implemented.'].join(''));
    }
    return defReadPath;
  };
  class AsyncCookieJar_ {
    constructor(document) {
      this.doc_ = document;
    }
    async set(setCookieString) {
      console.log('Set-Cookie: %s', setCookieString);
      this.doc_.cookie = setCookieString;
    }
    async get() {
      return this.doc_.cookie;
    }
  }
  const SECURE_PREFIX = '__Secure-', HOST_PREFIX = '__Host-';
  class CookieStore {
    constructor(asyncCookieJar) {
      this.asyncCookieJar_ = asyncCookieJar;
    }
    async has(nameOrOptions, moreOptions) {
      let cookieList = await this.getAll(nameOrOptions, moreOptions);
      return cookieList.length >= 1;
    }
    async get(nameOrOptions, moreOptions) {
      let cookieList = await this.getAll(nameOrOptions, moreOptions);
      return cookieList[0];
    }
    async getAll(nameOrOptions, moreOptions) {
      let options = Object.assign(
        {},
        (typeof nameOrOptions === 'object') ? nameOrOptions : {name: nameOrOptions},
        moreOptions);
      let {name, url = defReadPath, matchType} = options || {};
      if (name != null) {
      	name = String(name);
        if (name.indexOf(';') !== -1) throw new SyntaxError('Character ";" is not allowed in cookie name');
        if (name.indexOf('=') !== -1) throw new SyntaxError('Character "=" is not allowed in cookie name');
      } else {
        name = '';
        if (matchType == null) matchType = 'startsWith';
      }
      if (matchType == null) matchType = 'equals';
      matchType = String(matchType);
      if (matchType !== 'equals' && matchType !== 'startsWith') {
        throw new SyntaxError('Unrecognized matchType ' + JSON.stringify(matchType));
      }
      url = readPathForUrl(url);
      let cookieList = [];
      let jar = String(await this.asyncCookieJar_.get() || '');
      for (let i = 0, j = jar.length, k = jar.indexOf(';');
           k = (k == -1) ? j : k, i < j;
           i = k + 1 + (jar[k + 1] == ' ' ? 1 : 0), k = jar.indexOf(';', i)) {
       	let nv = jar.substr(i, k - i), c = nv.indexOf('=');
        if (c !== -1) {
          let n = nv.substr(0, c);
          // NOTE: some of the reported names and/or values will not be allowed in write operations.
          if (name === n || matchType === 'startsWith' && n.substr(0, name.length) === name) {
            let v = nv.substr(c + 1);
            cookieList.push({name: n, value: v});
          }
        }
      }
      return cookieList;
    }
    async delete(name, options) {
      await this.set(name, undefined, options);
    }
    async set(name, value, options) {
      name = String(name || '') || undefined;
      if (!name) throw new SyntaxError('Cookie name is required');
      if (name.match(DISALLOWED_IN_COOKIE_NAME_RE) || name !== decodeURIComponent(encodeURIComponent(name))) {
        throw new SyntaxError('Unsupported character in cookie name');
      }
      options = options || {};
      let expires = null;
      let maxAge = null;
      let expiresAsNumber;
      if (options.expires != null && !isNaN(expiresAsNumber = Number(options.expires))) {
        maxAge = (expiresAsNumber - Date.now()) / 1000;
      } else {
        expires = String(options.expires || '') || undefined;
      }
      if (expires && expires.indexOf(';') !== -1) {
        throw new SyntaxError('Character ";" is not allowed in cookie "expires" attribute');
      }
      let domain = String(options.domain || '') || undefined;
      if (domain && domain.indexOf(';') !== -1) {
        throw new SyntaxError('Character ";" is not allowed in cookie "domain" attribute');
      }
      let path = String(options.path || '/');
      if (path[0] !== '/') throw new SyntaxError('The "path" attribute must begin with "/"');
      if (path.match(/(^|\/)\.\.(\/|$)/)) {
        throw new SyntaxError('The cookie "path" attribute must not contain ".." path segments');
      }
      if (path.indexOf(';') !== -1) throw new SyntaxError('Character ";" is not allowed in cookie "path" attribute');
      if (path.indexOf('?') !== -1) throw new SyntaxError('Character "?" is not allowed in cookie "path" attribute');
      if (path.indexOf('#') !== -1) throw new SyntaxError('Character "#" is not allowed in cookie "path" attribute');
      // Add implicit trailing '/' if omitted. Does not match IE Set-Cookie behavior.
      path = path.replace(/([^\/]$)/, '$1/');
      let secure = options.secure;
      if (secure == null) secure = this.defSecure_;
      secure = !!secure;
      if (secure && !this.defSecure_) throw new SyntaxError('Secure cookies can only be modified from secure contexts');
      let httpOnly = !!options.httpOnly;
      if (value == null && maxAge == null && expires == null) maxAge = 0;
      value = String(value || '');
      if (value.match(DISALLOWED_IN_COOKIE_VALUE_RE) || value !== decodeURIComponent(encodeURIComponent(value))) {
        // Does not match document.cookie behavior!
        throw new SyntaxError('Unsupported character in cookie value');
      }
      if (name.substr(0, SECURE_PREFIX.length) === SECURE_PREFIX) {
        if (!this.defSecure_) {
          throw new SyntaxError([
            'Cookies with the ',
            JSON.stringify(SECURE_PREFIX),
            ' prefix can only be modified from secure contexts'].join(''));
        }
        if (!secure) {
          throw new SyntaxError('Cookies with the ' + JSON.stringify(SECURE_PREFIX) + ' prefix must use the Secure flag');
        }
      } else if (name.substr(0, HOST_PREFIX.length) === HOST_PREFIX) {
        if (!this.defSecure_) {
          throw new SyntaxError([
            'Cookies with the ',
            JSON.stringify(HOST_PREFIX),
            ' prefix can only be modified from secure contexts'].join(''));
        }
        if (!secure) {
          throw new SyntaxError('Cookies with the ' + JSON.stringify(HOST_PREFIX) + ' prefix must use the secure flag');
        }
        if (path !== '/') {
          throw new SyntaxError([
            'Cookies with the ',
            JSON.stringify(HOST_PREFIX),
            ' prefix must have path ',
            JSON.stringify('/')].join(''));
        }
        if (domain !== null) {
          throw new SyntaxError([
            'Cookies with the ',
            JSON.stringify(HOST_PREFIX),
            ' prefix cannot have the domain parameter'].join(''));
        }
      }
      let setCookieParts = [name, '=', value];
      if (domain != null) setCookieParts.push('; domain=', domain);
      if (path != null) setCookieParts.push('; path=', path);
      if (expires != null) setCookieParts.push('; expires=', expires);
      if (maxAge != null) setCookieParts.push('; max-age=', maxAge);
      if (secure) setCookieParts.push('; secure');
      if (httpOnly) setCookieParts.push('; httpOnly');
      let setCookie = setCookieParts.join('');
      await this.asyncCookieJar_.set(setCookie);
    }
  };
  const FAST_OBSERVER_INTERVAL = 200, SLOW_OBSERVER_INTERVAL = 5000; // ms
  const VERY_LOW_BATTERY_THRESHOLD = 0.05, LOW_BATTERY_THRESHOLD = 0.15; // 1.0 = charged
  class CookieObserver {
    constructor(callback) {
      this.callback_ = callback;
      this.timer_ = null;
      this.interests_ = [];
    }
    observe(cookieStore, interests) {
      const copiedInterests = [];
      (interests || [{}]).forEach(({name, url = defReadPath, matchType} = {}) => {
        if (name != null) {
        	name = String(name);
          if (name.indexOf(';') !== -1) throw new SyntaxError('Character ";" is not allowed in cookie name');
          if (name.indexOf('=') !== -1) throw new SyntaxError('Character "=" is not allowed in cookie name');
        } else {
          name = '';
          if (matchType == null) matchType = 'startsWith';
        }
        url = String(url || defReadPath);
        let path = readPathForUrl(url);
        // readPathForUrl will throw or return defReadPath so we can ignore path past this point
        if (matchType == null) matchType = 'equals';
        matchType = String(matchType);
        if (matchType !== 'equals' && matchType !== 'startsWith') {
          throw new SyntaxError('Unrecognized matchType ' + JSON.stringify(matchType));
        }
        copiedInterests.push({name: name, url: url, matchType: matchType});
      });
      if (!copiedInterests.length) return;
      this.interests_.push({cookieStore: cookieStore, interests: copiedInterests, cookies_: null});
      this.schedule_();
    }
    disconnect() {
      this.interests_ = null;
      this.snapshots_ = null;
      if (this.timer_) {
        clearTimeout(this.timer_);
        this.timer_ = null;
      }
    }
    schedule_() {
      navigator.getBattery().then(batteryManager => {
        if (this.timer_) return;
        let interval = SLOW_OBSERVER_INTERVAL;
        if (self.document.visibilityState === 'visible') {
          const level = batteryManager.level;
          if (level > VERY_LOW_BATTERY_THRESHOLD && level > LOW_BATTERY_THRESHOLD || batteryManager.charging) {
            interval = FAST_OBSERVER_INTERVAL;
          }
        }
        this.timer_ = setTimeout(() => this.tick_().then(() => this.schedule_()), interval);
      });
    }
    async tick_() {
      this.timer_ = null;
      let reported = {};
      let observed = [];
      let allCookies = await cookieStore.getAll();
      let forceReport = false;
      this.interests_.forEach(interestEntry => {
        let {cookieStore, interests, cookies_} = interestEntry;
        let oldCookies = cookies_;
        let newCookies = interestEntry.cookies_ = allCookies;
        let oldCookiesFlat = {};
        (oldCookies || {}).forEach(({name, value}) => {
          oldCookiesFlat[name + '='] = oldCookiesFlat[name + '='] || [];
          oldCookiesFlat[name + '='].push(name + '=' + value);
        });
        let newCookiesFlat = {};
        newCookies.forEach(({name, value}) => {
          newCookiesFlat[name + '='] = newCookiesFlat[name + '='] || [];
          newCookiesFlat[name + '='].push(name + '=' + value);
        });
        let changes = [];
        let newSame = {};
        (oldCookies || {}).forEach(({name, value}, index) => {
          if (oldCookiesFlat[name + '='].join(';') === (newCookiesFlat[name + '='] || []).join(';')) {
            newSame[name + '='] = true;
          } else {
            changes.push({type: 'hidden', name: name, value: value, index: index});
          }
        });
        newCookies.forEach(({name, value}, index) => {
          if (!newSame[name + '=']) changes.push({type: 'visible', name: name, value: value, index: index});
        });
        if (oldCookies == null || changes.length > 0) {
          interests.forEach(({name, url, matchType}) => {
            let matching =
              changes.filter(change => name === change.name || matchType === 'startsWith' && change.name.startsWith(name));
            matching.forEach(({type, name, value, index}) => {
              let serialized = type + ';' + name + '=' + value + ';' + index + ';' + url;
              if (reported[serialized]) return;
              observed.push({type: type, name: name, value: value, url: url, cookieStore: cookieStore, index: index});
              reported[serialized] = true;
            });
          });
        }
        if (oldCookies == null) forceReport = true;
      });
      if (forceReport || observed.length) this.callback_.call(null, observed, cookieObserver);
    }
  };
  if (!self.cookieStore) self.cookieStore = new CookieStore(new AsyncCookieJar_(self.document));
  if (!self.CookieObserver) self.CookieObserver = CookieObserver;
})();
<commit_msg>typo fixes<commit_after>// async cookies API polyfill for document contexts
if (self.document) (function() {
  const DISALLOWED_IN_COOKIE_NAME_RE = /[()<>@,;:\\""\/\[\]?={} \0-\x1f\x7f]|[^\x21-\x7e\u00A0-\uFFFD]/;
  const DISALLOWED_IN_COOKIE_VALUE_RE = /[^\x2D-\x3A\x21\x23-\x2B\x3C-\x5B\x5D-\x7E\u00A0-\uFFFD]/;
  // based on https://tools.ietf.org/html/rfc3986#appendix-B
  const uriRegExp = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/;
  const uriSchemeGroup = 2;
  const uriAuthorityGroup = 4;
  const uriPathGroup = 5;
  const defUriGroups = String(location.href).match(uriRegExp) || [];
  const dirName = path => path.replace(/(^|\/)\.\.$/, '$1../').replace(/[^\/]+$/, '');
  const defReadPath = dirName(defUriGroups[uriPathGroup] || '/');
  const defOrigin = defUriGroups[uriSchemeGroup] + '://' + defUriGroups[uriAuthorityGroup];
  const defSecure = defUriGroups[uriSchemeGroup] === 'https';
  const resolvePath = path => {
    path = String(path || defReadPath);
    if (path[0] !== '/') path = defReadPath + path;
    let pathSegments = path.split('/');
    let resolvedPathSegments = [];
    pathSegments.forEach(segment => {
      if (segment === '..') resolvedPathSegments.pop();
      else resolvedPathSegments.push(segment);
    });
    return resolvedPathSegments.join('/');
  };
  const readPathForUrl = url => {
    if (url == null) url = defReadPath;
    url = String(url);
    const urlGroups = url.match(uriRegExp) || [];
    const urlPath = resolvePath(dirName(String(urlGroups[uriPathGroup] || defReadPath)));
    const origin = [
      urlGroups[uriSchemeGroup] || defUriGroups[uriSchemeGroup],
      urlGroups[uriAuthorityGroup] || defUriGroups[uriAuthorityGroup]].join('://').toLowerCase();
    if ((origin + urlPath) !== (defOrigin + defReadPath)) {
      // TODO: iframe with unpredictable long pathname inside
      // requested path, maybe by appending as many
      // randomly-selected '$' and ':' as needed to reach 2083 chars
      // in the URL could be used to read same-origin, different-path cookies.
      throw new SyntaxError([
        'Cannot read cookies at requested URL ',
        JSON.stringify(url),
        ' from ',
        JSON.stringify(defOrigin + defReadPath),
        ': not yet implemented.'].join(''));
    }
    return defReadPath;
  };
  class AsyncCookieJar_ {
    constructor(document) {
      this.doc_ = document;
    }
    async set(setCookieString) {
      console.log('Set-Cookie: %s', setCookieString);
      this.doc_.cookie = setCookieString;
    }
    async get() {
      return this.doc_.cookie;
    }
  }
  const SECURE_PREFIX = '__Secure-', HOST_PREFIX = '__Host-';
  class CookieStore {
    constructor(asyncCookieJar) {
      this.asyncCookieJar_ = asyncCookieJar;
    }
    async has(nameOrOptions, moreOptions) {
      let cookieList = await this.getAll(nameOrOptions, moreOptions);
      return cookieList.length >= 1;
    }
    async get(nameOrOptions, moreOptions) {
      let cookieList = await this.getAll(nameOrOptions, moreOptions);
      return cookieList[0];
    }
    async getAll(nameOrOptions, moreOptions) {
      let options = Object.assign(
        {},
        (typeof nameOrOptions === 'object') ? nameOrOptions : {name: nameOrOptions},
        moreOptions);
      let {name, url = defReadPath, matchType} = options || {};
      if (name != null) {
      	name = String(name);
        if (name.indexOf(';') !== -1) throw new SyntaxError('Character ";" is not allowed in cookie name');
        if (name.indexOf('=') !== -1) throw new SyntaxError('Character "=" is not allowed in cookie name');
      } else {
        name = '';
        if (matchType == null) matchType = 'startsWith';
      }
      if (matchType == null) matchType = 'equals';
      matchType = String(matchType);
      if (matchType !== 'equals' && matchType !== 'startsWith') {
        throw new SyntaxError('Unrecognized matchType ' + JSON.stringify(matchType));
      }
      url = readPathForUrl(url);
      let cookieList = [];
      let jar = String(await this.asyncCookieJar_.get() || '');
      for (let i = 0, j = jar.length, k = jar.indexOf(';');
           k = (k == -1) ? j : k, i < j;
           i = k + 1 + (jar[k + 1] == ' ' ? 1 : 0), k = jar.indexOf(';', i)) {
       	let nv = jar.substr(i, k - i), c = nv.indexOf('=');
        if (c !== -1) {
          let n = nv.substr(0, c);
          // NOTE: some of the reported names and/or values will not be allowed in write operations.
          if (name === n || matchType === 'startsWith' && n.substr(0, name.length) === name) {
            let v = nv.substr(c + 1);
            cookieList.push({name: n, value: v});
          }
        }
      }
      return cookieList;
    }
    async delete(name, options) {
      await this.set(name, undefined, options);
    }
    async set(name, value, options) {
      name = String(name || '') || undefined;
      if (!name) throw new SyntaxError('Cookie name is required');
      if (name.match(DISALLOWED_IN_COOKIE_NAME_RE) || name !== decodeURIComponent(encodeURIComponent(name))) {
        throw new SyntaxError('Unsupported character in cookie name');
      }
      options = options || {};
      let expires = null;
      let maxAge = null;
      let expiresAsNumber;
      if (options.expires != null && !isNaN(expiresAsNumber = Number(options.expires))) {
        maxAge = (expiresAsNumber - Date.now()) / 1000;
      } else {
        expires = String(options.expires || '') || undefined;
      }
      if (expires && expires.indexOf(';') !== -1) {
        throw new SyntaxError('Character ";" is not allowed in cookie "expires" attribute');
      }
      let domain = String(options.domain || '') || undefined;
      if (domain && domain.indexOf(';') !== -1) {
        throw new SyntaxError('Character ";" is not allowed in cookie "domain" attribute');
      }
      let path = String(options.path || '/');
      if (path[0] !== '/') throw new SyntaxError('The "path" attribute must begin with "/"');
      if (path.match(/(^|\/)\.\.(\/|$)/)) {
        throw new SyntaxError('The cookie "path" attribute must not contain ".." path segments');
      }
      if (path.indexOf(';') !== -1) throw new SyntaxError('Character ";" is not allowed in cookie "path" attribute');
      if (path.indexOf('?') !== -1) throw new SyntaxError('Character "?" is not allowed in cookie "path" attribute');
      if (path.indexOf('#') !== -1) throw new SyntaxError('Character "#" is not allowed in cookie "path" attribute');
      // Add implicit trailing '/' if omitted. Does not match IE Set-Cookie behavior.
      path = path.replace(/([^\/]$)/, '$1/');
      let secure = options.secure;
      if (secure == null) secure = defSecure;
      secure = !!secure;
      if (secure && !defSecure) throw new SyntaxError('Secure cookies can only be modified from secure contexts');
      let httpOnly = !!options.httpOnly;
      if (value == null && maxAge == null && expires == null) maxAge = 0;
      value = String(value || '');
      if (value.match(DISALLOWED_IN_COOKIE_VALUE_RE) || value !== decodeURIComponent(encodeURIComponent(value))) {
        // Does not match document.cookie behavior!
        throw new SyntaxError('Unsupported character in cookie value');
      }
      if (name.substr(0, SECURE_PREFIX.length) === SECURE_PREFIX) {
        if (!defSecure) {
          throw new SyntaxError([
            'Cookies with the ',
            JSON.stringify(SECURE_PREFIX),
            ' prefix can only be modified from secure contexts'].join(''));
        }
        if (!secure) {
          throw new SyntaxError('Cookies with the ' + JSON.stringify(SECURE_PREFIX) + ' prefix must use the Secure flag');
        }
      } else if (name.substr(0, HOST_PREFIX.length) === HOST_PREFIX) {
        if (!defSecure) {
          throw new SyntaxError([
            'Cookies with the ',
            JSON.stringify(HOST_PREFIX),
            ' prefix can only be modified from secure contexts'].join(''));
        }
        if (!secure) {
          throw new SyntaxError('Cookies with the ' + JSON.stringify(HOST_PREFIX) + ' prefix must use the secure flag');
        }
        if (path !== '/') {
          throw new SyntaxError([
            'Cookies with the ',
            JSON.stringify(HOST_PREFIX),
            ' prefix must have path ',
            JSON.stringify('/')].join(''));
        }
        if (domain != null) {
          throw new SyntaxError([
            'Cookies with the ',
            JSON.stringify(HOST_PREFIX),
            ' prefix cannot have the domain parameter'].join(''));
        }
      }
      let setCookieParts = [name, '=', value];
      if (domain != null) setCookieParts.push('; domain=', domain);
      if (path != null) setCookieParts.push('; path=', path);
      if (expires != null) setCookieParts.push('; expires=', expires);
      if (maxAge != null) setCookieParts.push('; max-age=', maxAge);
      if (secure) setCookieParts.push('; secure');
      if (httpOnly) setCookieParts.push('; httpOnly');
      let setCookie = setCookieParts.join('');
      await this.asyncCookieJar_.set(setCookie);
    }
  };
  const FAST_OBSERVER_INTERVAL = 200, SLOW_OBSERVER_INTERVAL = 5000; // ms
  const VERY_LOW_BATTERY_THRESHOLD = 0.05, LOW_BATTERY_THRESHOLD = 0.15; // 1.0 = charged
  class CookieObserver {
    constructor(callback) {
      this.callback_ = callback;
      this.timer_ = null;
      this.interests_ = [];
    }
    observe(cookieStore, interests) {
      const copiedInterests = [];
      (interests || [{}]).forEach(({name, url = defReadPath, matchType} = {}) => {
        if (name != null) {
        	name = String(name);
          if (name.indexOf(';') !== -1) throw new SyntaxError('Character ";" is not allowed in cookie name');
          if (name.indexOf('=') !== -1) throw new SyntaxError('Character "=" is not allowed in cookie name');
        } else {
          name = '';
          if (matchType == null) matchType = 'startsWith';
        }
        url = String(url || defReadPath);
        let path = readPathForUrl(url);
        // readPathForUrl will throw or return defReadPath so we can ignore path past this point
        if (matchType == null) matchType = 'equals';
        matchType = String(matchType);
        if (matchType !== 'equals' && matchType !== 'startsWith') {
          throw new SyntaxError('Unrecognized matchType ' + JSON.stringify(matchType));
        }
        copiedInterests.push({name: name, url: url, matchType: matchType});
      });
      if (!copiedInterests.length) return;
      this.interests_.push({cookieStore: cookieStore, interests: copiedInterests, cookies_: null});
      this.schedule_();
    }
    disconnect() {
      this.interests_ = null;
      this.snapshots_ = null;
      if (this.timer_) {
        clearTimeout(this.timer_);
        this.timer_ = null;
      }
    }
    schedule_() {
      navigator.getBattery().then(batteryManager => {
        if (this.timer_) return;
        let interval = SLOW_OBSERVER_INTERVAL;
        if (self.document.visibilityState === 'visible') {
          const level = batteryManager.level;
          if (level > VERY_LOW_BATTERY_THRESHOLD && level > LOW_BATTERY_THRESHOLD || batteryManager.charging) {
            interval = FAST_OBSERVER_INTERVAL;
          }
        }
        this.timer_ = setTimeout(() => this.tick_().then(() => this.schedule_()), interval);
      });
    }
    async tick_() {
      this.timer_ = null;
      let reported = {};
      let observed = [];
      let allCookies = await cookieStore.getAll();
      let forceReport = false;
      this.interests_.forEach(interestEntry => {
        let {cookieStore, interests, cookies_} = interestEntry;
        let oldCookies = cookies_;
        let newCookies = interestEntry.cookies_ = allCookies;
        let oldCookiesFlat = {};
        (oldCookies || {}).forEach(({name, value}) => {
          oldCookiesFlat[name + '='] = oldCookiesFlat[name + '='] || [];
          oldCookiesFlat[name + '='].push(name + '=' + value);
        });
        let newCookiesFlat = {};
        newCookies.forEach(({name, value}) => {
          newCookiesFlat[name + '='] = newCookiesFlat[name + '='] || [];
          newCookiesFlat[name + '='].push(name + '=' + value);
        });
        let changes = [];
        let newSame = {};
        (oldCookies || {}).forEach(({name, value}, index) => {
          if (oldCookiesFlat[name + '='].join(';') === (newCookiesFlat[name + '='] || []).join(';')) {
            newSame[name + '='] = true;
          } else {
            changes.push({type: 'hidden', name: name, value: value, index: index});
          }
        });
        newCookies.forEach(({name, value}, index) => {
          if (!newSame[name + '=']) changes.push({type: 'visible', name: name, value: value, index: index});
        });
        if (oldCookies == null || changes.length > 0) {
          interests.forEach(({name, url, matchType}) => {
            let matching =
              changes.filter(change => name === change.name || matchType === 'startsWith' && change.name.startsWith(name));
            matching.forEach(({type, name, value, index}) => {
              let serialized = type + ';' + name + '=' + value + ';' + index + ';' + url;
              if (reported[serialized]) return;
              observed.push({type: type, name: name, value: value, url: url, cookieStore: cookieStore, index: index});
              reported[serialized] = true;
            });
          });
        }
        if (oldCookies == null) forceReport = true;
      });
      if (forceReport || observed.length) this.callback_.call(null, observed, cookieObserver);
    }
  };
  if (!self.cookieStore) self.cookieStore = new CookieStore(new AsyncCookieJar_(self.document));
  if (!self.CookieObserver) self.CookieObserver = CookieObserver;
})();
<|endoftext|>


<commit_before>var marks = new Array();
var cur = 0;

chrome.runtime.onMessage.addListener(
	function(request, sender, sendResponse) {
		if (request.command == "search") {
			var flags = "g";
			if (request.caseInsensitive == true) {
				var flags = "gi";
			}
			var re = new RegExp(request.regexp, flags);
			var html = document.getElementsByTagName('body')[0];
			clear();
			html.normalize();
			recurse(html, re);
			displayCount();
		} else if (request.command == "clear") {
			clear();
		} else if (request.command == "prev") {
			moveToPrev();
		} else if (request.command == "next") {
			moveToNext();
		} else {
			console.log("Regex search: Invalid command");
		}
		marks[cur].className="__regexp_search_selected";
		$('body').scrollTop($(marks[cur]).offset().top - 20);
	});

function recurse(element, regexp) {
	if (element.nodeName == "MARK") {
		return;
	}
	if (element.childNodes.length > 0) {
		for (var i = 0; i < element.childNodes.length; i++) {
			recurse(element.childNodes[i], regexp);
		}
	}

	if (element.nodeType == Node.TEXT_NODE && element.nodeValue.trim() != '') {
		/*
		 * 1. Find all regex matches
		 * 2. Loop through matches, finding their starting positions
		 * 3. Add everything between the last match and this match as a text node
		 * 4. Add the match as a <mark>
		 * 5. After loop is finished, add remainder as text node
		 */
		var str = element.nodeValue;
		var matches = str.match(regexp);
		var parent = element.parentNode;
		if (matches != null) {
			parent.removeChild(element);

			var pos = 0;
			for (var i = 0; i < matches.length; i++) {
				var index = str.indexOf(matches[i], pos);
				var before = document.createTextNode(str.substring(pos, index));
				pos = index + matches[i].length;

				var mark = document.createElement('mark');
				mark.appendChild(document.createTextNode(matches[i]));

				parent.appendChild(before);
				parent.appendChild(mark);

				marks.push(mark);
			}
			parent.appendChild(document.createTextNode(str.substring(pos)));
		}
	}
}

function clear() {
	cur = 0;
	for (var i = 0; i < marks.length; i++) {
		var mark = marks[i];
		mark.parentNode.replaceChild(mark.firstChild, mark);
	}
	marks.length = 0;
	var s = document.getElementById("_regexp_search_count");
	if (s != null) {
		s.parentNode.removeChild(s);
	}
}

function displayCount() {
	var num = cur + 1;
	var s = document.createElement('span');
	s.id = "_regexp_search_count";
	s.innerHTML = num + " of " + marks.length + " matches.";
	s.style.position = 'fixed';
	s.style.top = 0;
	s.style.left = 0;
	s.style.padding = '8px';
	s.style.background = 'rgba(255, 255, 0, 0.5)';
	s.addEventListener('mouseover', function(event) {
		document.getElementById("_regexp_search_count").style.opacity = "0";
	});
	s.addEventListener('mouseout', function(event) {
		document.getElementById("_regexp_search_count").style.opacity = "1";
	});
	document.getElementsByTagName('body')[0].appendChild(s);
}

function moveToNext() {
	if (cur < marks.length - 1) {
		marks[cur++].className="";
		marks[cur].className="__regexp_search_selected";
		updatePosText();
	}
}

function moveToPrev() {
	if (cur > 0) {
		marks[cur--].className="";
		marks[cur].className="__regexp_search_selected";
		updatePosText();
	}
}

function updatePosText() {
	if (marks.length > 0) {
		var elt = document.getElementById("_regexp_search_count");
		var num = cur + 1;
		elt.innerHTML = num + " of " + marks.length + " matches.";
	}
}
<commit_msg>Fixed 1 of 0 matches bug and matching text in hidden nodes<commit_after>var marks = new Array();
var cur = 0;

chrome.runtime.onMessage.addListener(
	function(request, sender, sendResponse) {
		if (request.command == "search") {
			var flags = "g";
			if (request.caseInsensitive == true) {
				var flags = "gi";
			}
			var re = new RegExp(request.regexp, flags);
			var html = document.getElementsByTagName('body')[0];
			clear();
			html.normalize();
			recurse(html, re);
			displayCount();
		} else if (request.command == "clear") {
			clear();
		} else if (request.command == "prev") {
			moveToPrev();
		} else if (request.command == "next") {
			moveToNext();
		} else {
			console.log("Regex search: Invalid command");
		}
		if (marks.length > 0) {
			marks[cur].className="__regexp_search_selected";
			$('body').scrollTop($(marks[cur]).offset().top - 20);
		}
	});

function recurse(element, regexp) {
	if (element.nodeName == "MARK" || element.nodeName == "SCRIPT" ||
		element.nodeName == "NOSCRIPT" ||
		element.nodeName == "STYLE" ||
		element.nodeType == Node.COMMENT_NODE) {
		return;
	}
	if (element.nodeType != Node.TEXT_NODE && !$(element).is(':visible')) {
		return;
	}

	if (element.childNodes.length > 0) {
		for (var i = 0; i < element.childNodes.length; i++) {
			recurse(element.childNodes[i], regexp);
		}
	}

	if (element.nodeType == Node.TEXT_NODE && element.nodeValue.trim() != '') {
		/*
		 * 1. Find all regex matches
		 * 2. Loop through matches, finding their starting positions
		 * 3. Add everything between the last match and this match as a text node
		 * 4. Add the match as a <mark>
		 * 5. After loop is finished, add remainder as text node
		 */
		var str = element.nodeValue;
		var matches = str.match(regexp);
		var parent = element.parentNode;
		if (matches != null) {
			parent.removeChild(element);

			var pos = 0;
			for (var i = 0; i < matches.length; i++) {
				var index = str.indexOf(matches[i], pos);
				var before = document.createTextNode(str.substring(pos, index));
				pos = index + matches[i].length;

				var mark = document.createElement('mark');
				mark.appendChild(document.createTextNode(matches[i]));

				parent.appendChild(before);
				parent.appendChild(mark);
				marks.push(mark);
			}
			parent.appendChild(document.createTextNode(str.substring(pos)));
		}
	}
}

function clear() {
	cur = 0;
	for (var i = 0; i < marks.length; i++) {
		var mark = marks[i];
		mark.parentNode.replaceChild(mark.firstChild, mark);
	}
	marks.length = 0;
	var s = document.getElementById("_regexp_search_count");
	if (s != null) {
		s.parentNode.removeChild(s);
	}
}

function displayCount() {
	if (marks.length > 0) {
		var num = cur + 1;
	} else {
		var num = 0;
	}
	var s = document.createElement('span');
	s.id = "_regexp_search_count";
	s.innerHTML = num + " of " + marks.length + " matches.";
	s.style.position = 'fixed';
	s.style.top = 0;
	s.style.left = 0;
	s.style.padding = '8px';
	s.style.background = 'rgba(255, 255, 0, 0.5)';
	s.addEventListener('mouseover', function(event) {
		document.getElementById("_regexp_search_count").style.opacity = "0";
	});
	s.addEventListener('mouseout', function(event) {
		document.getElementById("_regexp_search_count").style.opacity = "1";
	});
	document.getElementsByTagName('body')[0].appendChild(s);
}

function moveToNext() {
	if (cur < marks.length - 1) {
		marks[cur++].className="";
		marks[cur].className="__regexp_search_selected";
		updatePosText();
	}
}

function moveToPrev() {
	if (cur > 0) {
		marks[cur--].className="";
		marks[cur].className="__regexp_search_selected";
		updatePosText();
	}
}

function updatePosText() {
	if (marks.length > 0) {
		var elt = document.getElementById("_regexp_search_count");
		var num = cur + 1;
		elt.innerHTML = num + " of " + marks.length + " matches.";
	}
}
<|endoftext|>


<commit_before>/* global $, Mousetrap, chrome, defaults */

const LookListenRead = (function() {

  const last = xs => xs[xs.length - 1]
  const info = s => console.log('LookListenRead: ' + s)

  const commands = {
    next: () => gotoChunk(chunkIx + 1) && reset(),
    previous: () => gotoChunk(chunkIx - 1) && reset(),
    nextBlock: () => gotoBlock(blockIx + 1),
    previousBlock: () => gotoBlock(blockIx - 1),
    pauseOrResume: pauseOrResume,
    slowdown: () => speedup(-10),
    speedup: () => speedup(10),
    exitMode: exitMode,
  }

  let playing = false
  let chunkIx = null
  let blockIx = null
  let options
  let voice
  const chunks = []
  const blocks = []

  function initVoice(next) {
    const voices = speechSynthesis.getVoices()
    info('Found voices: ' + voices.length)
    voice = voices.find(v => v.name === options.voice)
    if (voice) {
      next()
    } else {
      info('Selected voice not found. Waiting for voices...')
      speechSynthesis.onvoiceschanged = () => initVoice(next)
    }
  }

  function speakText(text, next) {
    const msg = new SpeechSynthesisUtterance(text)
    msg.rate = options.rate
    msg.voice = voice
    msg.onend = () => playing && next()
    msg.onerror = console.log
    speechSynthesis.speak(msg)
  }

  /* Chunk is a set of blast nodes sharing common block-style parent. Nodes in chunk are
     played and highlighted together. */
  function initChunks() {

    function displayType(elem) {
      return (elem.currentStyle || window.getComputedStyle(elem, '')).display
    }

    function closestBlock(elem) {
      while (displayType(elem) !== 'block' && elem.parentNode) {
        elem = elem.parentNode
      }
      return elem
    }

    document.normalize()
    $('body').blast({ delimiter: options.delimiter, customClass: 'looklistenread' })
    const regexFilter = new RegExp(options.regexFilter)
    const regexIgnore = new RegExp(options.regexIgnore)
    Array.from(document.getElementsByClassName('looklistenread'))
      .filter(span => regexFilter.test(span.innerText) && !regexIgnore.test(span.innerText))
         .forEach(span => {
           const chunk = chunks.length > 0 ? last(chunks) : null
           const block = closestBlock(span)
           if (chunk && chunk.block === block &&
               chunk.text.length + span.innerText.length <= options.maxLength
           ) {
             chunk.nodes.push(span)
             chunk.text += ' ' + span.innerText
           } else {
             chunks.push({nodes: [span], text: span.innerText, block: block})
             const i = chunks.length - 1
             blocks.length > 0 && last(blocks).node === block ?
                     last(blocks).chunkIxs.push(i) :
                     blocks.push({node: block, chunkIxs: [i]})
           }
         })
  }

  function bringToRange(i, xs) {
    return i == null ? i : Math.max(0, Math.min(xs.length - 1, i))
  }

  function play() {
    chunkIx != null || gotoChunk(0)
    playing = true
    speakText(chunks[chunkIx].text, () =>
      chunkIx < chunks.length - 1 ? gotoChunk(chunkIx + 1) && play() : pause())
  }

  function pause() {
    playing = false
    speechSynthesis.cancel()
  }

  function pauseOrResume() {
    playing ? pause() : play()
  }

  function reset(startPlaying) {
    if (playing) {
      pause()
      setTimeout(play, 30)
    } else if (startPlaying) {
      play()
    }
  }

  function stop() {
    pause()
    gotoChunk(null)
  }

  function gotoBlock(i) {
    i = bringToRange(i, blocks)
    blockIx === i || gotoChunk(blocks[i].chunkIxs[0]) && reset()
  }

  // Go to new chunk index, highlight the chunk nodes and return true if new chunk index is
  // not null.
  function gotoChunk(i) {
    i = bringToRange(i, chunks)
    if (chunkIx !== i) {
      chunkIx !== null &&
        chunks[chunkIx].nodes.forEach(node => $(node).removeClass('llr-active'))
      chunkIx = i
      blockIx = blocks.findIndex(block => block.chunkIxs.includes(chunkIx))
      if (chunkIx !== null) {
        chunks[chunkIx].nodes.forEach(node => $(node).addClass('llr-active'))
        chunks[chunkIx].nodes[0].scrollIntoViewIfNeeded()
      }
    }
    return chunkIx !== null
  }

  function speedup(percentage) {
    options.rate *= 1 + 0.01 * percentage
    reset()
  }

  function bindHotkey(hotkey, action) {
    Mousetrap.bind(hotkey, () => {
      action()
      return false
    })
  }

  function enterMode() {
    initChunks()
    initVoice(() => {
      Mousetrap.unbind(options.hotkeys.enterMode)
      Object.keys(commands).forEach(cmd => bindHotkey(options.hotkeys[cmd], commands[cmd]))
      chunks.forEach((chunk, i) => chunk.nodes.forEach(node => node.ondblclick = e => {
        gotoChunk(i) && reset(true)
        e.stopPropagation()
      }))
      blocks.forEach(block => block.node.ondblclick = e => {
        gotoChunk(block.chunkIxs[0]) && reset(true)
        e.stopPropagation()
      })
      info('Enter speaking mode')
    })
  }

  function exitMode() {
    stop()
    Object.keys(commands).forEach(cmd => Mousetrap.unbind(options.hotkeys[cmd]))
    bindHotkey(options.hotkeys.exitMode, exitMode)
    bindHotkey(options.hotkeys.enterMode, enterMode)
    info('Exit speaking mode')
  }

  return opts => {
    options = opts
    bindHotkey(options.hotkeys.enterMode, enterMode)
  }

})()

chrome.storage.sync.get(defaults, LookListenRead)
<commit_msg>Seems to fix #3 (circumvent chrome bug).<commit_after>/* global $, Mousetrap, chrome, defaults */

const LookListenRead = (function() {

  const last = xs => xs[xs.length - 1]
  const info = s => console.log('LookListenRead: ' + s)

  const commands = {
    next: () => gotoChunk(chunkIx + 1) && reset(),
    previous: () => gotoChunk(chunkIx - 1) && reset(),
    nextBlock: () => gotoBlock(blockIx + 1),
    previousBlock: () => gotoBlock(blockIx - 1),
    pauseOrResume: pauseOrResume,
    slowdown: () => speedup(-10),
    speedup: () => speedup(10),
    exitMode: exitMode,
  }

  let playing = false
  let chunkIx = null
  let blockIx = null
  let options
  let voice
  const chunks = []
  const blocks = []
  const utterances = []

  function initVoice(next) {
    const voices = speechSynthesis.getVoices()
    info('Found voices: ' + voices.length)
    voice = voices.find(v => v.name === options.voice)
    if (voice) {
      next()
    } else {
      info('Selected voice not found. Waiting for voices...')
      speechSynthesis.onvoiceschanged = () => initVoice(next)
    }
  }

  function speakText(text, next) {
    const msg = new SpeechSynthesisUtterance(text)
    msg.rate = options.rate
    msg.voice = voice
    msg.onend = () => playing && next()
    msg.onerror = console.log
    utterances.push(msg)
    speechSynthesis.speak(msg)
  }

  /* Chunk is a set of blast nodes sharing common block-style parent. Nodes in chunk are
     played and highlighted together. */
  function initChunks() {

    function displayType(elem) {
      return (elem.currentStyle || window.getComputedStyle(elem, '')).display
    }

    function closestBlock(elem) {
      while (displayType(elem) !== 'block' && elem.parentNode) {
        elem = elem.parentNode
      }
      return elem
    }

    document.normalize()
    $('body').blast({ delimiter: options.delimiter, customClass: 'looklistenread' })
    const regexFilter = new RegExp(options.regexFilter)
    const regexIgnore = new RegExp(options.regexIgnore)
    Array.from(document.getElementsByClassName('looklistenread'))
      .filter(span => regexFilter.test(span.innerText) && !regexIgnore.test(span.innerText))
         .forEach(span => {
           const chunk = chunks.length > 0 ? last(chunks) : null
           const block = closestBlock(span)
           if (chunk && chunk.block === block &&
               chunk.text.length + span.innerText.length <= options.maxLength
           ) {
             chunk.nodes.push(span)
             chunk.text += ' ' + span.innerText
           } else {
             chunks.push({nodes: [span], text: span.innerText, block: block})
             const i = chunks.length - 1
             blocks.length > 0 && last(blocks).node === block ?
                     last(blocks).chunkIxs.push(i) :
                     blocks.push({node: block, chunkIxs: [i]})
           }
         })
  }

  function bringToRange(i, xs) {
    return i == null ? i : Math.max(0, Math.min(xs.length - 1, i))
  }

  function play() {
    chunkIx != null || gotoChunk(0)
    playing = true
    speakText(chunks[chunkIx].text, () => {
      chunkIx < chunks.length - 1 ? gotoChunk(chunkIx + 1) && play() : pause()
    })
  }

  function pause() {
    playing = false
    speechSynthesis.cancel()
  }

  function pauseOrResume() {
    playing ? pause() : play()
  }

  function reset(startPlaying) {
    if (playing) {
      pause()
      setTimeout(play, 30)
    } else if (startPlaying) {
      play()
    }
  }

  function stop() {
    pause()
    gotoChunk(null)
  }

  function gotoBlock(i) {
    i = bringToRange(i, blocks)
    blockIx === i || gotoChunk(blocks[i].chunkIxs[0]) && reset()
  }

  // Go to new chunk index, highlight the chunk nodes and return true if new chunk index is
  // not null.
  function gotoChunk(i) {
    i = bringToRange(i, chunks)
    if (chunkIx !== i) {
      chunkIx !== null &&
        chunks[chunkIx].nodes.forEach(node => $(node).removeClass('llr-active'))
      chunkIx = i
      blockIx = blocks.findIndex(block => block.chunkIxs.includes(chunkIx))
      if (chunkIx !== null) {
        chunks[chunkIx].nodes.forEach(node => $(node).addClass('llr-active'))
        chunks[chunkIx].nodes[0].scrollIntoViewIfNeeded()
      }
    }
    return chunkIx !== null
  }

  function speedup(percentage) {
    options.rate *= 1 + 0.01 * percentage
    reset()
  }

  function bindHotkey(hotkey, action) {
    Mousetrap.bind(hotkey, () => {
      action()
      return false
    })
  }

  function enterMode() {
    initChunks()
    initVoice(() => {
      Mousetrap.unbind(options.hotkeys.enterMode)
      Object.keys(commands).forEach(cmd => bindHotkey(options.hotkeys[cmd], commands[cmd]))
      chunks.forEach((chunk, i) => chunk.nodes.forEach(node => node.ondblclick = e => {
        gotoChunk(i) && reset(true)
        e.stopPropagation()
      }))
      blocks.forEach(block => block.node.ondblclick = e => {
        gotoChunk(block.chunkIxs[0]) && reset(true)
        e.stopPropagation()
      })
      info('Enter speaking mode')
    })
  }

  function exitMode() {
    stop()
    Object.keys(commands).forEach(cmd => Mousetrap.unbind(options.hotkeys[cmd]))
    bindHotkey(options.hotkeys.exitMode, exitMode)
    bindHotkey(options.hotkeys.enterMode, enterMode)
    info('Exit speaking mode')
  }

  return opts => {
    options = opts
    bindHotkey(options.hotkeys.enterMode, enterMode)
  }

})()

chrome.storage.sync.get(defaults, LookListenRead)
<|endoftext|>