<commit_before>/*
MIT License

Copyright (c) 2017 Andrew S (Andrews54757_at_gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

var version = "1.1.6";

var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1; //January is 0!

var yyyy = today.getFullYear();
if (dd < 10) {
    dd = '0' + dd;
}
if (mm < 10) {
    mm = '0' + mm;
}
var date = dd + '/' + mm + '/' + yyyy;

function removeComments(str) {

    str = str.split("");
    var len = str.length;
    var out = [];
    var i = 0

    function skip(match) {

        var backslash = false;
        out.push(match);

        for (++i; i < len; i++) {
            char = str[i];
            out.push(char);
            if (char === "\\") backslash = true;
            else if (char === match && !backslash) {
                break;
            } else if (backslash) {
                backslash = false;
            }
        }
    }
    for (; i < len; i++) {
        var char = str[i];

        if (char == "\"") {
            skip("\"");
        } else if (char == "'") {
            skip("'");
        } else if (char == "/") {
            i++
            if (str[i] == "/") {
                for (++i; i < len; i++) {
                    var c = str[i];
                    if (c == "\n") {
                        out.push("\n")
                        break;
                    }
                }

            } else if (str[i] == "*") {

                var star = false;
                for (++i; i < len; i++) {
                    var c = str[i];
                    if (c == "*") {
                        star = true;
                    } else
                    if (c == "/" && star) {
                        break;
                    } else if (star) {
                        star = false;
                    }
                }
            }
        } else {
            out.push(char);
        }

    }
    return out.join('').replace(/\n\s*\n/g, "\n");
}

// Minifier -> https://github.com/ThreeLetters/PHP-Minify-js
function minify(str, options) {
    if (!options) options = {};
    str = removeComments(str);
    var varReplace = options.varReplace === undefined ? true : options.varReplace;
    var extreme = options.extremeMinify === undefined ? true : options.extremeMinify;
    var removeLine = options.removeLine === undefined ? true : options.removeLine;

    if (removeLine) {
        str = str.replace(/\n/g, "").replace(/\t/g, "").split("");
    } else {
        str = str.split("");
    }
    var len = str.length;
    var out = [];
    var i = 0;
    var varIndex = [0];
    var varChars = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
    var varLen = varChars.length;
    var varMap = {};

    function getNextVar() {

        var str = "";
        var j = 0;
        while (true) {
            if (!varIndex[j]) varIndex[j] = 0;
            varIndex[j]++;

            if (varIndex[j] > varLen) {
                varIndex[j] = 1;
            } else {
                break;
            }
            j++;
        }

        for (var i = 0; i < varIndex.length; i++) {
            str += varChars[varIndex[i] - 1];
        }

        return str;
    }

    function skip(match) {

        var backslash = false;
        out.push(match);

        for (++i; i < len; i++) {
            char = str[i];
            out.push(char);
            if (char === "\\") backslash = true;
            else if (char === match && !backslash) {
                break;
            } else if (backslash) {
                backslash = false;
            }
        }
    }

    function includes(char) {

        var dt = [";", "{", "}", ",", "(", ")", "[", "]", "=", ">", "<", ".", "?", ":"];
        if (extreme) dt.push("&", "|", "+", "-", "*", "/");
        return dt.indexOf(char) != -1;
    }

    function includes2(char) {
        var dt = ["=", "{", "(", "}", ")", "]", ">", "<", "!", ".", "?", ":"];
        if (extreme) dt.push("$", "&", "|", "+", "-", "*", "/");
        return dt.indexOf(char) != -1;
    }

    function includes3(char) {
        var dt = ["_", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];

        return dt.indexOf(char.toLowerCase()) != -1;
    }

    for (; i < len; i++) {
        var char = str[i];

        if (char == "\"") {
            skip("\"");
        } else if (char == "'") {
            skip("'");
        } else if (char == "`") {
            skip("`");
        } else if (varReplace && char == "$") {

            var v = "";
            for (; i < len; i++) {

                if (!includes3(str[i + 1])) break;
                v += str[i + 1];
            }
            if (varMap[v]) {
                out.push(varMap[v]);
            } else if (v != "this") {
                var found = false;
                for (var j = i; j < len; j++) {
                    if (str[j + 1] == "=" || str[j + 1] == "," || str[j + 1] == ")") {
                        found = true;
                        break;
                    } else if (str[j + 1] != " ") {
                        break;
                    }
                }
                if (found) {
                    for (var j = i - v.length - 1; j > 0; j--) {
                        if (str[j] == "c" || str[j] == "e" || str[j] == "l" || str[j] == "d") {
                            found = false;
                            break;
                        } else if (str[j] != " ") {
                            break;
                        }
                    }
                }
                if (found) {
                    varMap[v] = "$" + getNextVar();
                    // console.log(v, varMap[v])
                    out.push(varMap[v]);
                } else {
                    out.push("$" + v);
                }
            } else {
                out.push("$" + v);
            }
            //console.log(v);

        } else if (char == " ") {

            var d = true;

            for (; i < len; i++) {

                if (includes2(str[i + 1])) {
                    d = false;
                }
                if (str[i + 1] != " ") break;
            }
            if (d) out.push(" ");

        } else if (includes(char)) {
            out.push(char);
            for (; i < len; i++) {
                if (str[i + 1] != " ") break;
            }
        } else if (char === 'f' && str[i + 1] === 'u' && str[i + 2] === 'n' && str[i + 3] === 'c' && str[i + 4] === 't' && str[i + 5] === 'i' && str[i + 6] === 'o' && str[i + 7] === 'n') {
            i += 7;
            varMap = {};
            varIndex = [0];
            out.push('function')
        } else {
            out.push(char)
        }

    }
    return out.join("");

}

var fs = require("fs");

var adv = fs.readFileSync(__dirname + "/SuperSQL/lib/parser.php", "utf8");

var connector = fs.readFileSync(__dirname + "/SuperSQL/lib/connector.php", "utf8");

var main = fs.readFileSync(__dirname + "/SuperSQL/SuperSQL.php", "utf8");

var helper = fs.readFileSync(__dirname + "/SuperSQL/helper.php", "utf8");

var startstr = "// BUILD BETWEEN";

adv = removeComments(adv.split(startstr)[1]);
connector = removeComments(connector.split(startstr)[1]);
var index = main.split(startstr)[1];
main = removeComments(index);
helper = removeComments(helper.split(startstr)[1]);

var out = `<?php\n\
/*\n\
 Author: Andrews54757\n\
 License: MIT (https://github.com/ThreeLetters/SuperSQL/blob/master/LICENSE)\n\
 Source: https://github.com/ThreeLetters/SQL-Library\n\
 Build: v${version}\n\
 Built on: ${date}\n\
*/\n\
\n\
namespace SuperSQL;\n\
\n`;

var complete = `// lib/connector.php\
${connector}\n\
// lib/parser.php\
${adv}\n\
// index.php\
${main}\
?>`;

var completeMin = `// lib/connector.php\n\
${minify(connector)}\n\
// lib/parser.php\n\
${minify(adv)}\n\
// index.php\n\
${minify(main)}\n\
?>`;

var a = out + complete,
    b = out + completeMin,
    c = out + helper,
    d = out + minify(helper) + "\n?>",
    e = out + minify(connector) + minify(adv) + minify(main) + minify(helper) + '\n?>';

var dir1 = __dirname + "/dist/SuperSQL.php",
    dir2 = __dirname + "/dist/SuperSQL_min.php",
    dir3 = __dirname + "/dist/SuperSQL_helper.php",
    dir4 = __dirname + "/dist/SuperSQL_helper_min.php",
    dir5 = __dirname + '/dist/SuperSQL_complete.php';

fs.writeFileSync(dir1, a);
fs.writeFileSync(dir2, b);

fs.writeFileSync(dir3, c);
fs.writeFileSync(dir4, d);

fs.writeFileSync(dir5, e);

var readme = "## Files\n\
\n\
* `SuperSQL.php` - Main file\n\
* `SuperSQL_min.php`\n\
* `SuperSQL_helper.php` - Helper functions\n\
* `SuperSQL_helper_min.php`\n\
\n\
### Sizes\n\
\n";
var crypto = require('crypto');

function size(filename) {
    const stats = fs.statSync(filename);
    const fileSizeInBytes = stats.size
    return Math.round(fileSizeInBytes / 100) / 10;
}

function hash(data) {

    return crypto.createHash('md5').update(data).digest("hex");
}
var sizes = `\
* \`SuperSQL.php\` - ${a.length} Chars (${size(dir1)} MB)\n\
* \`SuperSQL_min.php\` - ${b.length} Chars (${size(dir2)} MB)\n\
* \`SuperSQL_helper.php\` - ${c.length} Chars (${size(dir3)} MB)\n\
* \`SuperSQL_helper_min.php\` - ${d.length} Chars (${size(dir4)} MB)\n\
* \`SuperSQL_complete_min.php\` - ${e.length} Chars (${size(dir5)} MB)\n\
\n\
## Hashes\n\
\n\
\`\`\`\n\
* SuperSQL.php - ${hash(a)}\n\
* SuperSQL_min.php - ${hash(b)}\n\
* SuperSQL_helper.php - ${hash(c)}\n\
* SuperSQL_helper_min.php - ${hash(d)}\n\
* SuperSQL_complete.php - ${hash(e)}\n\
\`\`\`\n\n`;

readme += sizes;

var exec = require('child_process').exec;

exec('php -v', function (error, version, err) {
    if (error) throw error;
    if (err) throw err;

    function round(num) {
        return (Math.round(num * 10000) / 10000)
    }

    exec('php ' + __dirname + '/profile.php', function (err, out, er) {
        if (err) throw err;
        if (er) throw er;

        var data = JSON.parse(out);

        var sum = 0;
        data.data.forEach((d) => {
            sum += (d.end - d.start);
        })

        var avg = sum / data.data.length;
        console.log(round(avg) + 'ms average time, ' + round(sum) + 'ms sum');

        var insert1 = stats('insert1'),
            insert = stats('insert'),
            select = stats('select'),
            select2 = stats('select2'),
            select3 = stats('select3'),
            update = stats('update'),
            d = stats('delete');
        var performance = `## Performance\n\n\
Profiled on PHP v${data.version}, ${data.data.length} loops\n\
\n\
\n\
${round(avg)}ms Average Time, Sum: ${round(sum)}ms\n\n\
### Specifics\n\n\
| Name                    |  Avg   |  Sum   |\n\
|-------------------------|--------|--------|\n\
| 1 Row Insert            | ${insert1[0]} | ${insert1[1]} |\n\
| 100 R Insert W Temp     | ${insert[0]} | ${insert[1]} |\n\
| Select *                | ${select[0]} | ${select[1]} |\n\
| Select * W Cast         | ${select2[0]} | ${select2[1]} |\n\
| Select * W Cast W where | ${select3[0]} | ${select3[1]} |\n\
| 1 Row Update            | ${update[0]} | ${update[1]} |\n\
| Delete                  | ${d[0]} | ${d[1]} |\n`;

        function stats(prop) {
            var sum = 0;
            var error = false;
            data.data.forEach((d) => {
                sum += (d[prop].end - d[prop].start);
                if (d.error) error = d.error
            });

            return [round(sum / data.data.length), round(sum), error];
        }
        readme += performance;

        fs.writeFileSync(__dirname + "/dist/README.md", readme);
        console.log("Compiled files into dist");

    })

})
<commit_msg>Fix unit<commit_after>/*
MIT License

Copyright (c) 2017 Andrew S (Andrews54757_at_gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

var version = "1.1.6";

var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1; //January is 0!

var yyyy = today.getFullYear();
if (dd < 10) {
    dd = '0' + dd;
}
if (mm < 10) {
    mm = '0' + mm;
}
var date = dd + '/' + mm + '/' + yyyy;

function removeComments(str) {

    str = str.split("");
    var len = str.length;
    var out = [];
    var i = 0

    function skip(match) {

        var backslash = false;
        out.push(match);

        for (++i; i < len; i++) {
            char = str[i];
            out.push(char);
            if (char === "\\") backslash = true;
            else if (char === match && !backslash) {
                break;
            } else if (backslash) {
                backslash = false;
            }
        }
    }
    for (; i < len; i++) {
        var char = str[i];

        if (char == "\"") {
            skip("\"");
        } else if (char == "'") {
            skip("'");
        } else if (char == "/") {
            i++
            if (str[i] == "/") {
                for (++i; i < len; i++) {
                    var c = str[i];
                    if (c == "\n") {
                        out.push("\n")
                        break;
                    }
                }

            } else if (str[i] == "*") {

                var star = false;
                for (++i; i < len; i++) {
                    var c = str[i];
                    if (c == "*") {
                        star = true;
                    } else
                    if (c == "/" && star) {
                        break;
                    } else if (star) {
                        star = false;
                    }
                }
            }
        } else {
            out.push(char);
        }

    }
    return out.join('').replace(/\n\s*\n/g, "\n");
}

// Minifier -> https://github.com/ThreeLetters/PHP-Minify-js
function minify(str, options) {
    if (!options) options = {};
    str = removeComments(str);
    var varReplace = options.varReplace === undefined ? true : options.varReplace;
    var extreme = options.extremeMinify === undefined ? true : options.extremeMinify;
    var removeLine = options.removeLine === undefined ? true : options.removeLine;

    if (removeLine) {
        str = str.replace(/\n/g, "").replace(/\t/g, "").split("");
    } else {
        str = str.split("");
    }
    var len = str.length;
    var out = [];
    var i = 0;
    var varIndex = [0];
    var varChars = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
    var varLen = varChars.length;
    var varMap = {};

    function getNextVar() {

        var str = "";
        var j = 0;
        while (true) {
            if (!varIndex[j]) varIndex[j] = 0;
            varIndex[j]++;

            if (varIndex[j] > varLen) {
                varIndex[j] = 1;
            } else {
                break;
            }
            j++;
        }

        for (var i = 0; i < varIndex.length; i++) {
            str += varChars[varIndex[i] - 1];
        }

        return str;
    }

    function skip(match) {

        var backslash = false;
        out.push(match);

        for (++i; i < len; i++) {
            char = str[i];
            out.push(char);
            if (char === "\\") backslash = true;
            else if (char === match && !backslash) {
                break;
            } else if (backslash) {
                backslash = false;
            }
        }
    }

    function includes(char) {

        var dt = [";", "{", "}", ",", "(", ")", "[", "]", "=", ">", "<", ".", "?", ":"];
        if (extreme) dt.push("&", "|", "+", "-", "*", "/");
        return dt.indexOf(char) != -1;
    }

    function includes2(char) {
        var dt = ["=", "{", "(", "}", ")", "]", ">", "<", "!", ".", "?", ":"];
        if (extreme) dt.push("$", "&", "|", "+", "-", "*", "/");
        return dt.indexOf(char) != -1;
    }

    function includes3(char) {
        var dt = ["_", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];

        return dt.indexOf(char.toLowerCase()) != -1;
    }

    for (; i < len; i++) {
        var char = str[i];

        if (char == "\"") {
            skip("\"");
        } else if (char == "'") {
            skip("'");
        } else if (char == "`") {
            skip("`");
        } else if (varReplace && char == "$") {

            var v = "";
            for (; i < len; i++) {

                if (!includes3(str[i + 1])) break;
                v += str[i + 1];
            }
            if (varMap[v]) {
                out.push(varMap[v]);
            } else if (v != "this") {
                var found = false;
                for (var j = i; j < len; j++) {
                    if (str[j + 1] == "=" || str[j + 1] == "," || str[j + 1] == ")") {
                        found = true;
                        break;
                    } else if (str[j + 1] != " ") {
                        break;
                    }
                }
                if (found) {
                    for (var j = i - v.length - 1; j > 0; j--) {
                        if (str[j] == "c" || str[j] == "e" || str[j] == "l" || str[j] == "d") {
                            found = false;
                            break;
                        } else if (str[j] != " ") {
                            break;
                        }
                    }
                }
                if (found) {
                    varMap[v] = "$" + getNextVar();
                    // console.log(v, varMap[v])
                    out.push(varMap[v]);
                } else {
                    out.push("$" + v);
                }
            } else {
                out.push("$" + v);
            }
            //console.log(v);

        } else if (char == " ") {

            var d = true;

            for (; i < len; i++) {

                if (includes2(str[i + 1])) {
                    d = false;
                }
                if (str[i + 1] != " ") break;
            }
            if (d) out.push(" ");

        } else if (includes(char)) {
            out.push(char);
            for (; i < len; i++) {
                if (str[i + 1] != " ") break;
            }
        } else if (char === 'f' && str[i + 1] === 'u' && str[i + 2] === 'n' && str[i + 3] === 'c' && str[i + 4] === 't' && str[i + 5] === 'i' && str[i + 6] === 'o' && str[i + 7] === 'n') {
            i += 7;
            varMap = {};
            varIndex = [0];
            out.push('function')
        } else {
            out.push(char)
        }

    }
    return out.join("");

}

var fs = require("fs");

var adv = fs.readFileSync(__dirname + "/SuperSQL/lib/parser.php", "utf8");

var connector = fs.readFileSync(__dirname + "/SuperSQL/lib/connector.php", "utf8");

var main = fs.readFileSync(__dirname + "/SuperSQL/SuperSQL.php", "utf8");

var helper = fs.readFileSync(__dirname + "/SuperSQL/helper.php", "utf8");

var startstr = "// BUILD BETWEEN";

adv = removeComments(adv.split(startstr)[1]);
connector = removeComments(connector.split(startstr)[1]);
var index = main.split(startstr)[1];
main = removeComments(index);
helper = removeComments(helper.split(startstr)[1]);

var out = `<?php\n\
/*\n\
 Author: Andrews54757\n\
 License: MIT (https://github.com/ThreeLetters/SuperSQL/blob/master/LICENSE)\n\
 Source: https://github.com/ThreeLetters/SQL-Library\n\
 Build: v${version}\n\
 Built on: ${date}\n\
*/\n\
\n\
namespace SuperSQL;\n\
\n`;

var complete = `// lib/connector.php\
${connector}\n\
// lib/parser.php\
${adv}\n\
// index.php\
${main}\
?>`;

var completeMin = `// lib/connector.php\n\
${minify(connector)}\n\
// lib/parser.php\n\
${minify(adv)}\n\
// index.php\n\
${minify(main)}\n\
?>`;

var a = out + complete,
    b = out + completeMin,
    c = out + helper,
    d = out + minify(helper) + "\n?>",
    e = out + minify(connector) + minify(adv) + minify(main) + minify(helper) + '\n?>';

var dir1 = __dirname + "/dist/SuperSQL.php",
    dir2 = __dirname + "/dist/SuperSQL_min.php",
    dir3 = __dirname + "/dist/SuperSQL_helper.php",
    dir4 = __dirname + "/dist/SuperSQL_helper_min.php",
    dir5 = __dirname + '/dist/SuperSQL_complete.php';

fs.writeFileSync(dir1, a);
fs.writeFileSync(dir2, b);

fs.writeFileSync(dir3, c);
fs.writeFileSync(dir4, d);

fs.writeFileSync(dir5, e);

var readme = "## Files\n\
\n\
* `SuperSQL.php` - Main file\n\
* `SuperSQL_min.php`\n\
* `SuperSQL_helper.php` - Helper functions\n\
* `SuperSQL_helper_min.php`\n\
\n\
### Sizes\n\
\n";
var crypto = require('crypto');

function size(filename) {
    const stats = fs.statSync(filename);
    const fileSizeInBytes = stats.size
    return Math.round(fileSizeInBytes / 100) / 10;
}

function hash(data) {

    return crypto.createHash('md5').update(data).digest("hex");
}
var sizes = `\
* \`SuperSQL.php\` - ${a.length} Chars (${size(dir1)} MB)\n\
* \`SuperSQL_min.php\` - ${b.length} Chars (${size(dir2)} MB)\n\
* \`SuperSQL_helper.php\` - ${c.length} Chars (${size(dir3)} MB)\n\
* \`SuperSQL_helper_min.php\` - ${d.length} Chars (${size(dir4)} MB)\n\
* \`SuperSQL_complete_min.php\` - ${e.length} Chars (${size(dir5)} MB)\n\
\n\
## Hashes\n\
\n\
\`\`\`\n\
* SuperSQL.php - ${hash(a)}\n\
* SuperSQL_min.php - ${hash(b)}\n\
* SuperSQL_helper.php - ${hash(c)}\n\
* SuperSQL_helper_min.php - ${hash(d)}\n\
* SuperSQL_complete.php - ${hash(e)}\n\
\`\`\`\n\n`;

readme += sizes;

var exec = require('child_process').exec;

exec('php -v', function (error, version, err) {
    if (error) throw error;
    if (err) throw err;

    function round(num) {
        return (Math.round(num * 10000) / 10000)
    }

    exec('php ' + __dirname + '/profile.php', function (err, out, er) {
        if (err) throw err;
        if (er) throw er;

        var data = JSON.parse(out);

        var sum = 0;
        data.data.forEach((d) => {
            sum += (d.end - d.start);
        })

        var avg = sum / data.data.length;
        console.log(round(avg) + 'ms average time, ' + round(sum) + 'ms sum');

        var insert1 = stats('insert1'),
            insert = stats('insert'),
            select = stats('select'),
            select2 = stats('select2'),
            select3 = stats('select3'),
            update = stats('update'),
            d = stats('delete');
        var performance = `## Performance\n\n\
Profiled on PHP v${data.version}, ${data.data.length} loops\n\
\n\
\n\
${round(avg)}sec Average Time, Sum: ${round(sum)}sec\n\n\
### Specifics\n\n\
| Name                    |  Avg   |  Sum   |\n\
|-------------------------|--------|--------|\n\
| 1 Row Insert            | ${insert1[0]} | ${insert1[1]} |\n\
| 100 R Insert W Temp     | ${insert[0]} | ${insert[1]} |\n\
| Select *                | ${select[0]} | ${select[1]} |\n\
| Select * W Cast         | ${select2[0]} | ${select2[1]} |\n\
| Select * W Cast W where | ${select3[0]} | ${select3[1]} |\n\
| 1 Row Update            | ${update[0]} | ${update[1]} |\n\
| Delete                  | ${d[0]} | ${d[1]} |\n`;

        function stats(prop) {
            var sum = 0;
            var error = false;
            data.data.forEach((d) => {
                sum += (d[prop].end - d[prop].start);
                if (d.error) error = d.error
            });

            return [round(sum / data.data.length), round(sum), error];
        }
        readme += performance;

        fs.writeFileSync(__dirname + "/dist/README.md", readme);
        console.log("Compiled files into dist");

    })

})
<|endoftext|>


<commit_before>angular
  .module('lift-ng', [])
  .service('plumbing', [ '$q', function($q){
    var defers = {};

    var create = function(id) {
      var q = $q.defer();
      defers[id] = q;
      return q;
    };

    var resolve = function(data, q) {
      if(data.msg) {
        q.reject(data.msg)
      } else {
        if (typeof data.data !== 'undefined') {
          inject(data.data);
          q.resolve(data.data);
        }
        else {
          q.resolve();
        }
      }
      return q;
    };

    // Called by the LiftNgFutureActor when a Future is fulfilled
    var fulfill = function(data, id) {
      var theId = id || data.id;
      var q = defers[theId];
      if(typeof q !== "undefined" && q !== null) { // We found our awaiting defer/promise
        resolve(data, q);
        delete defers[theId];
      } else { // We arrived before the model which embeds us!
        resolve(data, create(theId));
      }
    };

    // Called to inject promises wherever our serializer encountered a Future
    var inject = function(model) {
      for(var k in model) {
        if(model[k] == null) {
          // Don't do anything, skip
        }
        // It is a future which we need to inject
        else if(model[k]["net.liftmodules.ng.Angular.future"]) {
          var id   = model[k]["net.liftmodules.ng.Angular.future"];
          var data = model[k].data;
          var msg  = model[k].msg;
          var q = defers[id];
          if(typeof q !== "undefined" && q !== null) { // The future resolved before we arrived here
            model[k] = q.promise;
            delete defers[id];
          } else if(data) { // The future had already RESOLVED at serialization time
            var d = $q.defer();
            d.resolve(data);
            model[k] = d.promise;
          } else if(msg) { // The future had already FAILED at serialization time
            var d = $q.defer();
            d.reject(msg);
            model[k] = d.promise;
          } else { // Promise/Future pending
            model[k] = create(id).promise;
          }
        }
        // Not a future, so check children
        else if(typeof model[k] === 'object') {
          inject(model[k]);
        }
      }
    };

    return {
      createDefer: create,
      resolve: resolve,
      fulfill: fulfill,
      inject: inject
    }
  }])
  .service('liftProxy', ['$rootScope', '$q', 'plumbing', function ($rootScope, $q, plumbing) {
    net_liftmodules_ng.init();

    var svc = {
      request: function (requestData) {
        var req = {
          data: requestData.name + '=' + encodeURIComponent(JSON.stringify({data: requestData.data})),
          when: (new Date()).getTime()
        };
        var defer = $q.defer();

        var onSuccess = function(response) { $rootScope.$apply(function(){ // Must work under the watchful eye of angular
          // If there is no future ID, then we have our data and we're done.
          if(!response.futureId) {
            plumbing.resolve(response, defer);
          }

          // Otherwise, we need to plumb out a new promise because we'll get the value later.
          else {
            plumbing.createDefer(response.futureId).promise.then(
              function(data)  { defer.resolve(data)  },
              function(error) { defer.reject(error)  },
              function(notify){ defer.notify(notify) }
            )
          }
        })};

        var onFailure = function() { $rootScope.$apply(function() {
          defer.reject("net.liftmodules.ng.Angular.ajaxFailure");
        })};

        net_liftmodules_ng.ajax(req, onSuccess, onFailure, "json");

        return defer.promise;
      }
    };

    return svc;
  }
]);

var net_liftmodules_ng = net_liftmodules_ng || {};
net_liftmodules_ng.init = function() {
  // We've passed {data, when} to the ajax lift machinery, so we need to pull the data part back out.
  var grabData = function(obj) {
    // This check prevents us from screwing up any non-lift-ng ajax calls someone could possibly be making.
    if(typeof obj === "object") return obj.data;
    else return obj;
  };

  // Grab a reference to the original function so we can wrap it
  var origCall = liftAjax.lift_actualJSONCall;

  // Wrap the json call with our data grab
  liftAjax.lift_actualJSONCall = function(data, onSuccess, onFailure) {
    return origCall(grabData(data), onSuccess, onFailure);
  };

  // Override the sort function if we should retry ajax in order.
  if(net_liftmodules_ng.retryAjaxInOrder) {
    liftAjax.lift_ajaxQueueSort = function() {
      liftAjax.lift_ajaxQueue.sort(function (a, b) {
        // If both items are one of our doctored-up requests, grab our 'when' which is the original request time.
        if(typeof a.theData === "object" && a.theData.when && typeof b.theData === "object" && b.theData.when)
          return a.theData.when - b.theData.when;
        else // Not our stuff, so let's not screw around with the original order logic.
          return a.when - b.when;
      });
    };
  }
};<commit_msg>Just changing the name of an internal function<commit_after>angular
  .module('lift-ng', [])
  .service('plumbing', [ '$q', function($q){
    var defers = {};

    var create = function(id) {
      var q = $q.defer();
      defers[id] = q;
      return q;
    };

    var resolve = function(data, q) {
      if(data.msg) {
        q.reject(data.msg)
      } else {
        if (typeof data.data !== 'undefined') {
          inject(data.data);
          q.resolve(data.data);
        }
        else {
          q.resolve();
        }
      }
      return q;
    };

    // Called by the LiftNgFutureActor when a Future is fulfilled
    var fulfill = function(data, id) {
      var theId = id || data.id;
      var q = defers[theId];
      if(typeof q !== "undefined" && q !== null) { // We found our awaiting defer/promise
        resolve(data, q);
        delete defers[theId];
      } else { // We arrived before the model which embeds us!
        resolve(data, create(theId));
      }
    };

    // Called to inject promises wherever our serializer encountered a Future
    var inject = function(model) {
      for(var k in model) {
        if(model[k] == null) {
          // Don't do anything, skip
        }
        // It is a future which we need to inject
        else if(model[k]["net.liftmodules.ng.Angular.future"]) {
          var id   = model[k]["net.liftmodules.ng.Angular.future"];
          var data = model[k].data;
          var msg  = model[k].msg;
          var q = defers[id];
          if(typeof q !== "undefined" && q !== null) { // The future resolved before we arrived here
            model[k] = q.promise;
            delete defers[id];
          } else if(data) { // The future had already RESOLVED at serialization time
            var d = $q.defer();
            d.resolve(data);
            model[k] = d.promise;
          } else if(msg) { // The future had already FAILED at serialization time
            var d = $q.defer();
            d.reject(msg);
            model[k] = d.promise;
          } else { // Promise/Future pending
            model[k] = create(id).promise;
          }
        }
        // Not a future, so check children
        else if(typeof model[k] === 'object') {
          inject(model[k]);
        }
      }
    };

    return {
      createDefer: create,
      resolve: resolve,
      fulfill: fulfill,
      inject: inject
    }
  }])
  .service('liftProxy', ['$rootScope', '$q', 'plumbing', function ($rootScope, $q, plumbing) {
    net_liftmodules_ng.init();

    var svc = {
      request: function (requestData) {
        var req = {
          data: requestData.name + '=' + encodeURIComponent(JSON.stringify({data: requestData.data})),
          when: (new Date()).getTime()
        };
        var defer = $q.defer();

        var onSuccess = function(response) { $rootScope.$apply(function(){ // Must work under the watchful eye of angular
          // If there is no future ID, then we have our data and we're done.
          if(!response.futureId) {
            plumbing.resolve(response, defer);
          }

          // Otherwise, we need to plumb out a new promise because we'll get the value later.
          else {
            plumbing.createDefer(response.futureId).promise.then(
              function(data)  { defer.resolve(data)  },
              function(error) { defer.reject(error)  },
              function(notify){ defer.notify(notify) }
            )
          }
        })};

        var onFailure = function() { $rootScope.$apply(function() {
          defer.reject("net.liftmodules.ng.Angular.ajaxFailure");
        })};

        net_liftmodules_ng.ajax(req, onSuccess, onFailure, "json");

        return defer.promise;
      }
    };

    return svc;
  }
]);

var net_liftmodules_ng = net_liftmodules_ng || {};
net_liftmodules_ng.init = function() {
  // We've passed {data, when} to the ajax lift machinery, so we need to pull the data part back out.
  var onlyData = function(obj) {
    // This check prevents us from screwing up any non-lift-ng ajax calls someone could possibly be making.
    if(typeof obj === "object") return obj.data;
    else return obj;
  };

  // Grab a reference to the original function so we can wrap it
  var origCall = liftAjax.lift_actualJSONCall;

  // Wrap the json call with our data grab
  liftAjax.lift_actualJSONCall = function(data, onSuccess, onFailure) {
    return origCall(onlyData(data), onSuccess, onFailure);
  };

  // Override the sort function if we should retry ajax in order.
  if(net_liftmodules_ng.retryAjaxInOrder) {
    liftAjax.lift_ajaxQueueSort = function() {
      liftAjax.lift_ajaxQueue.sort(function (a, b) {
        // If both items are one of our doctored-up requests, grab our 'when' which is the original request time.
        if(typeof a.theData === "object" && a.theData.when && typeof b.theData === "object" && b.theData.when)
          return a.theData.when - b.theData.when;
        else // Not our stuff, so let's not screw around with the original order logic.
          return a.when - b.when;
      });
    };
  }
};<|endoftext|>


<commit_before>/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	fs = require('fs-extra'),
	{src, webpack} = require('config');

const
	ss = include('src/super/i-static-page/modules/ss-helpers'),
	deps = include('src/super/i-static-page/deps');

const entryPoints = {
	std: ['std'],
	'p-v4-components-demo': ['p-v4-components-demo']
};

describe('super/i-static-page/modules/ss-helpers/page', () => {
	const assets = ss.getAssets(entryPoints);

	describe('`generateInitJS`', () => {
		it('simple usage', async () => {
			const
				name = 'p-v4-components-demo',
				file = src.clientOutput(`${webpack.output({name})}.init.js`);

			fs.unlinkSync(file);

			await ss.generateInitJS(name, {
				deps,
				ownDeps: entryPoints[name],

				assets: await assets,
				rootTag: 'main',

				rootAttrs: {
					'data-foo': 'bla'
				}
			});

			expect(fs.readFileSync(file).toString()).toBe(
`
Object.defineProperty(window, 'GLOBAL_NONCE', {
\tvalue: undefined
});

var PATH = Object.create(null);
var PUBLIC_PATH = undefined;

if (false) {
\t(function () {
\t\tvar publicPath = /publicPath=([^&]+)/.exec(location.search);

\t\tif (publicPath != null) {
\t\t\tPUBLIC_PATH = decodeURIComponent(publicPath[1]);
\t\t}
\t})();
}

try {
\tPATH = new Proxy(PATH, {
\t\tget: function (target, prop) {
\t\t\tif (prop in target) {
\t\t\t\tvar v = target[prop];
\t\t\t\treturn typeof v === 'string' ? v : v.publicPath || v.path;
\t\t\t}

\t\t\tthrow new ReferenceError('A resource by the path "' + prop + '" is not defined');
\t\t}
\t});
} catch (_) {}
PATH['p-v4-components-demo'] = 'p-v4-components-demo.js';
PATH['p-v4-components-demo_tpl'] = 'p-v4-components-demo_tpl.js';
PATH['webpack.runtime'] = 'webpack.runtime.js';
PATH['vendor'] = 'vendor.js';
PATH['std'] = 'std.js';
PATH['std_tpl'] = 'std_tpl.js';
PATH['std_style'] = 'std_style.css';
PATH['p-v4-components-demo_style'] = 'p-v4-components-demo_style.css';
PATH['std_view'] = 'std_view.js';
PATH['p-v4-components-demo_view'] = 'p-v4-components-demo_view.js';

if ('std_style' in PATH) {
\t
(function () {
\tvar el = document.createElement('link');
\t
\tel.setAttribute('rel', 'preload');
\tel.setAttribute('as', 'style');
\tel.setAttribute('href', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['std_style']); })()));
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('link');
\t
\tel.setAttribute('href', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['std_style']); })()));
\tel.setAttribute('rel', 'stylesheet');
\tel.setAttribute('media', 'print');
\tel.setAttribute('onload', 'this.media=\\'all\\'; this.onload=null;');
\tdocument.head.appendChild(el);
})();

}

function $__RENDER_ROOT() {
\t
(function () {
\tvar el = document.createElement('main');
\tel.setAttribute('data-foo', 'bla');
\tel.setAttribute('class', 'i-static-page p-v4-components-demo');
\tdocument.body.appendChild(el);
})();

(function () {
\tvar el = document.createElement('link');
\t
\tel.setAttribute('rel', 'preload');
\tel.setAttribute('as', 'style');
\tel.setAttribute('href', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['p-v4-components-demo_style']); })()));
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('link');
\t
\tel.setAttribute('href', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['p-v4-components-demo_style']); })()));
\tel.setAttribute('rel', 'stylesheet');
\tel.setAttribute('media', 'print');
\tel.setAttribute('onload', 'this.media=\\'all\\'; this.onload=null;');
\tdocument.head.appendChild(el);
})();

if ('std' in PATH) {
\t
(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['std']); })()));
\tdocument.head.appendChild(el);
})();

}

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', '/dist/client/lib/requestidlecallback.js');
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', '/dist/client/lib/eventemitter2.js');
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', '/dist/client/lib/vue.js');
\tdocument.head.appendChild(el);
})();

if ('index-core' in PATH) {
\t
(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['index-core']); })()));
\tdocument.head.appendChild(el);
})();

}
if ('vendor' in PATH) {
\t
(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['vendor']); })()));
\tdocument.head.appendChild(el);
})();

}

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['p-v4-components-demo_tpl']); })()));
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['p-v4-components-demo']); })()));
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['webpack.runtime']); })()));
\tdocument.head.appendChild(el);
})();

}

`
			);
		});
	});
});
<commit_msg>Fixed a test<commit_after>/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	fs = require('fs-extra'),
	{src, webpack} = require('config');

const
	ss = include('src/super/i-static-page/modules/ss-helpers'),
	deps = include('src/super/i-static-page/deps');

const entryPoints = {
	std: ['std'],
	'p-v4-components-demo': ['p-v4-components-demo']
};

describe('super/i-static-page/modules/ss-helpers/page', () => {
	const assets = ss.getAssets(entryPoints);

	describe('`generateInitJS`', () => {
		it('simple usage', async () => {
			const
				name = 'p-v4-components-demo',
				file = src.clientOutput(`${webpack.output({name})}.init.js`);

			fs.unlinkSync(file);

			await ss.generateInitJS(name, {
				deps,
				ownDeps: entryPoints[name],

				assets: await assets,
				rootTag: 'main',

				rootAttrs: {
					'data-foo': 'bla'
				}
			});

			expect(fs.readFileSync(file).toString()).toBe(
`
Object.defineProperty(window, 'GLOBAL_NONCE', {
\tvalue: undefined
});

var PATH = Object.create(null);
var PUBLIC_PATH = undefined;

if (false) {
\t(function () {
\t\tvar publicPath = /publicPath=([^&]+)/.exec(location.search);

\t\tif (publicPath != null) {
\t\t\tPUBLIC_PATH = decodeURIComponent(publicPath[1]);
\t\t\tPUBLIC_PATH = PUBLIC_PATH.replace(/\\/+$/, '') + '/';
\t\t}
\t})();
}

try {
\tPATH = new Proxy(PATH, {
\t\tget: function (target, prop) {
\t\t\tif (prop in target) {
\t\t\t\tvar v = target[prop];
\t\t\t\treturn typeof v === 'string' ? v : v.publicPath || v.path;
\t\t\t}

\t\t\tthrow new ReferenceError('A resource by the path "' + prop + '" is not defined');
\t\t}
\t});
} catch (_) {}
PATH['p-v4-components-demo'] = 'p-v4-components-demo.js';
PATH['p-v4-components-demo_tpl'] = 'p-v4-components-demo_tpl.js';
PATH['webpack.runtime'] = 'webpack.runtime.js';
PATH['vendor'] = 'vendor.js';
PATH['std'] = 'std.js';
PATH['std_tpl'] = 'std_tpl.js';
PATH['std_style'] = 'std_style.css';
PATH['p-v4-components-demo_style'] = 'p-v4-components-demo_style.css';
PATH['std_view'] = 'std_view.js';
PATH['p-v4-components-demo_view'] = 'p-v4-components-demo_view.js';

if ('std_style' in PATH) {
\t
(function () {
\tvar el = document.createElement('link');
\t
\tel.setAttribute('rel', 'preload');
\tel.setAttribute('as', 'style');
\tel.setAttribute('href', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['std_style']); })()));
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('link');
\t
\tel.setAttribute('href', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['std_style']); })()));
\tel.setAttribute('rel', 'stylesheet');
\tel.setAttribute('media', 'print');
\tel.setAttribute('onload', 'this.media=\\'all\\'; this.onload=null;');
\tdocument.head.appendChild(el);
})();

}

function $__RENDER_ROOT() {
\t
(function () {
\tvar el = document.createElement('main');
\tel.setAttribute('data-foo', 'bla');
\tel.setAttribute('class', 'i-static-page p-v4-components-demo');
\tdocument.body.appendChild(el);
})();

(function () {
\tvar el = document.createElement('link');
\t
\tel.setAttribute('rel', 'preload');
\tel.setAttribute('as', 'style');
\tel.setAttribute('href', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['p-v4-components-demo_style']); })()));
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('link');
\t
\tel.setAttribute('href', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['p-v4-components-demo_style']); })()));
\tel.setAttribute('rel', 'stylesheet');
\tel.setAttribute('media', 'print');
\tel.setAttribute('onload', 'this.media=\\'all\\'; this.onload=null;');
\tdocument.head.appendChild(el);
})();

if ('std' in PATH) {
\t
(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['std']); })()));
\tdocument.head.appendChild(el);
})();

}

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', '/dist/client/lib/requestidlecallback.js');
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', '/dist/client/lib/eventemitter2.js');
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', '/dist/client/lib/vue.js');
\tdocument.head.appendChild(el);
})();

if ('index-core' in PATH) {
\t
(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['index-core']); })()));
\tdocument.head.appendChild(el);
})();

}
if ('vendor' in PATH) {
\t
(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['vendor']); })()));
\tdocument.head.appendChild(el);
})();

}

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['p-v4-components-demo_tpl']); })()));
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['p-v4-components-demo']); })()));
\tdocument.head.appendChild(el);
})();

(function () {
\tvar el = document.createElement('script');
\tel.async = false;
\tel.setAttribute('src', ((function () { function concatURLs(a, b) { return a ? a.replace(/[\\\\/]+$/, '') + '/' + b.replace(/^[\\\\/]+/, '') : b; } return concatURLs('/dist/client/', PATH['webpack.runtime']); })()));
\tdocument.head.appendChild(el);
})();

}

`
			);
		});
	});
});
<|endoftext|>


<commit_before>import React, { PropTypes } from "react";
import { Link } from "react-router";
import "./SearchHit.css";
import { injectIntl, intlShape } from "react-intl";
import { Row, Col } from "reactstrap";
import moment from "moment";
import backgroundImage from "../../img/pp-thumbnail-1.jpg";

export class SearchHit extends React.Component {
  getInnerHTML() {
    return { __html: this.props.record.body };
  }
  render() {
    let result = this.props.record;
    let awsUrl = process.env.REACT_APP_ASSETS_URL;
    let pic = "";
    if (result.lead_image) {
      pic = awsUrl + encodeURIComponent(result.lead_image.url);
    } else if (result.other_images && result.other_images.length > 0) {
      pic = awsUrl + encodeURIComponent(result.other_images[0].url);
    }
    let locale = this.props.intl.locale;
    let id = result.id;
    let type = result.type;
    let title = type + ": " + result.title;
    let link = `/${locale}/${type}/${id}`;
    let firstSubmit = moment(result.post_date).format("dddd, MMMM Do YYYY");
    if (!title) {
      console.log("missing title: ", result);
    }
    let thumbnailStyle = {
      backgroundImageSrc: backgroundImage
    };
    let dateString = moment(result.updated_date).fromNow();
    let blob = (
      <Col md={this.props.selectedViewType === "grid" ? "4" : "12"}>
        {this.props.selectedViewType === "grid"
          ?

              <Link to={link} className="result-title">
                {pic
                  ?

                  :
}

{title}

              </Link>

                {firstSubmit}

                {dateString}

          : <Row className="list-item">
              <Col md="3">
                {pic
                  ? <Link to={link}>

                    </Link>
                  : <Link to={link}>

                    </Link>}
              </Col>
              <Col md="6">
                <Link to={link}>

{title}

                </Link>

                  {firstSubmit}

                  {dateString}

              </Col>

            </Row>}
      </Col>
    );
    return blob;
  }
}

SearchHit.propTypes = {
  record: PropTypes.object.isRequired,
  intl: intlShape.isRequired
};

export default injectIntl(SearchHit);
<commit_msg>minor addition to search hit js thumbnail class names<commit_after>import React, { PropTypes } from "react";
import { Link } from "react-router";
import "./SearchHit.css";
import { injectIntl, intlShape } from "react-intl";
import { Row, Col } from "reactstrap";
import moment from "moment";
import backgroundImage from "../../img/pp-thumbnail-1.jpg";

export class SearchHit extends React.Component {
  getInnerHTML() {
    return { __html: this.props.record.body };
  }
  render() {
    let result = this.props.record;
    let awsUrl = process.env.REACT_APP_ASSETS_URL;
    let pic = "";
    if (result.lead_image) {
      pic = awsUrl + encodeURIComponent(result.lead_image.url);
    } else if (result.other_images && result.other_images.length > 0) {
      pic = awsUrl + encodeURIComponent(result.other_images[0].url);
    }
    let locale = this.props.intl.locale;
    let id = result.id;
    let type = result.type;
    let title = result.title;
    let link = `/${locale}/${type}/${id}`;
    let firstSubmit = moment(result.post_date).format("dddd, MMMM Do YYYY");
    let thumbnailClass = "thumbnail " + type;
    if (!title) {
      console.log("missing title: ", result);
    }
    let thumbnailStyle = {
      backgroundImageSrc: backgroundImage
    };
    let dateString = moment(result.updated_date).fromNow();
    let blob = (
      <Col md={this.props.selectedViewType === "grid" ? "4" : "12"}>
        {this.props.selectedViewType === "grid"
          ?

              <Link to={link} className="result-title">
                {pic
                  ?

                  :
}

{title}

              </Link>

                {firstSubmit}

                {dateString}

          : <Row className="list-item">
              <Col md="3">
                {pic
                  ? <Link to={link}>

                    </Link>
                  : <Link to={link}>

                    </Link>}
              </Col>
              <Col md="6">
                <Link to={link}>

{title}

                </Link>

                  {firstSubmit}

                  {dateString}

              </Col>

            </Row>}
      </Col>
    );
    return blob;
  }
}

SearchHit.propTypes = {
  record: PropTypes.object.isRequired,
  intl: intlShape.isRequired
};

export default injectIntl(SearchHit);
<|endoftext|>


<commit_before>var dicfiles = ['char.category', 'code2category', 'word2id', 'word.dat', 'word.ary.idx', 'word.inf', 'matrix.bin'];
var tagger = null;
var furiganized = {};
var exceptions = null;
var furiganaEnabled = false;

//initialize variables
if (!localStorage)
    console.log("Error: localStorage not available to background page. Has local storage been disabled in this instance of Chrome?");

if (localStorage.getItem("user_kanji_list") === null) {
    console.log("The localStorage \"user_kanji_list\" value was null. It will be initialised to the installation default list.");
    var defaultUserKanjiList = "日一国会人年大十二本中長出三同時政事自行社見月分議後前民生連五発間対上部東者党地合市業内相方四定今回新場金員九入選立開手米力学問高代明実円関決子動京全目表戦経通外最言氏現理調体化田当八六約主題下首意法不来作性的要用制治度務強気小七成期公持野協取都和統以機平総加山思家話世受区領多県続進正安設保改数記院女初北午指権心界支第産結百派点教報済書府活原先共得解名交資予川向際査勝面委告軍文反元重近千考判認画海参売利組知案道信策集在件団別物側任引使求所次水半品昨論計死官増係感特情投示変打男基私各始島直両朝革価式確村提運終挙果西勢減台広容必応演電歳住争談能無再位置企真流格有疑口過局少放税検藤町常校料沢裁状工建語球営空職証土与急止送援供可役構木割聞身費付施切由説転食比難防補車優夫研収断井何南石足違消境神番規術護展態導鮮備宅害配副算視条幹独警宮究育席輸訪楽起万着乗店述残想線率病農州武声質念待試族象銀域助労例衛然早張映限親額監環験追審商葉義伝働形景落欧担好退準賞訴辺造英被株頭技低毎医復仕去姿味負閣韓渡失移差衆個門写評課末守若脳極種美岡影命含福蔵量望松非撃佐核観察整段横融型白深字答夜製票況音申様財港識注呼渉達";
    localStorage.setItem("user_kanji_list", defaultUserKanjiList);
}
var userKanjiRegexp = new RegExp("[" + localStorage.getItem("user_kanji_list") + "]");

//initialize local storage
var localStoragePrefDefaults = {
    "include_link_text": true,
    "furigana_display": "hira",
    "filter_okurigana": true,
    "persistent_mode": false,
    "yomi_size": "",
    "yomi_color": ""
}

for (var key in localStoragePrefDefaults) {
    if (localStorage.getItem(key) === null) {
        console.log("The localStorage \"" + key + "\" value was null. It will be initialised to" + localStoragePrefDefaults[key] + ".");
        localStorage.setItem(key, localStoragePrefDefaults[key]);
    }
}

//initialize IGO-JS
igo.getServerFileToArrayBufffer("res/ipadic.zip", function(buffer) {
    try {
        var blob = new Blob([new Uint8Array(buffer)]);
        var reader = new FileReader();
        reader.onload = function(e) {
            var dic = Zip.inflate(new Uint8Array(reader.result))
            tagger = loadTagger(dic);
        }
        reader.readAsArrayBuffer(blob);
    } catch (e) {
        console.error(e.toString());
    }
});

$.getJSON("res/exceptions.json", function(data) {
    exceptions = data;
});

/*****************
 *  Functions
 *****************/
//load dictionaries
function loadTagger(dicdir) {
    var files = new Array();
    for (var i = 0; i < dicfiles.length; ++i) {
        files[dicfiles[i]] = dicdir.files[dicfiles[i]].inflate();
    }

    var category = new igo.CharCategory(files['code2category'], files['char.category']);
    var wdc = new igo.WordDic(files['word2id'], files['word.dat'], files['word.ary.idx'], files['word.inf']);
    var unk = new igo.Unknown(category);
    var mtx = new igo.Matrix(files['matrix.bin']);
    return new igo.Tagger(wdc, unk, mtx);
}
//prepare a tab for furigana injection
function enableTabForFI(tab) {
    chrome.pageAction.setIcon({
        path: {
            "19": "img/icons/furigana_inactive_38.png",
            "38": "img/icons/furigana_inactive_76.png"
        },
        tabId: tab.id
    });
    chrome.pageAction.setTitle({
        title: "Insert furigana",
        tabId: tab.id
    });
    chrome.pageAction.show(tab.id);
    chrome.tabs.executeScript(tab.id, {
        file: "text_to_furigana_dom_parse.js"
    });
}

/*****************
 *  Chrome events
 *****************/

//Page action listener
chrome.pageAction.onClicked.addListener(function(tab) {
    if (JSON.parse(localStorage.getItem('persistent_mode')) == true) {
        console.log('persistent')
        chrome.tabs.query({} ,function (tabs) {
            for (var i = 0; i < tabs.length; i++) {
                chrome.tabs.executeScript(tabs[i].id, {code: "toggleFurigana();"});
            }
        });
    } else {
        chrome.tabs.executeScript(tab.id, {
            code: "toggleFurigana();"
        });
    }
});

//Keyboard action listener
chrome.commands.onCommand.addListener(function(command) {
    if (JSON.parse(localStorage.getItem('persistent_mode')) == true) {
        console.log('persistent')
        chrome.tabs.query({} ,function (tabs) {
            for (var i = 0; i < tabs.length; i++) {
                chrome.tabs.executeScript(tabs[i].id, {code: "toggleFurigana();"});
            }
        });
    } else {
        chrome.tabs.executeScript(tab.id, {
            code: "toggleFurigana();"
        });
    }
});

//Ruby tag injector
function addRuby(furiganized, kanji, yomi, key, processed) {
    //furigana can be displayed in either hiragana, katakana or romaji
    switch (localStorage.getItem("furigana_display")) {
        case "hira":
            yomi = wanakana.toHiragana(yomi);
            break;
        case "roma":
            yomi = wanakana.toRomaji(yomi);
            break;
        default:
            break;
    }

    ruby_rxp = new RegExp(sprintf('<ruby><rb>%s<\\/rb><rp>\\(<\\/rp><rt[ style=]*.*?>([\\u3040-\\u3096|\\u30A1-\\u30FA|\\uFF66-\\uFF9D|\\u31F0-\\u31FF]+)<\\/rt><rp>\\)<\\/rp><\\/ruby>', kanji), 'g');

    //apply user styles to furigana text
    yomi_size = '';
    yomi_color = '';

    localStorage.getItem('yomi_size').length > 0 ? yomi_size = sprintf('font-size:%spt', localStorage.getItem('yomi_size')) : yomi_size = '';
    localStorage.getItem('yomi_color').length > 0 ? yomi_color = sprintf(';color:%s', localStorage.getItem('yomi_color')) : yomi_color = '';

    yomi_style = yomi_size + yomi_color;

    //inject furigana into text nodes
    //a different regex is used for repeat passes to avoid having multiple rubies on the same base
    if (processed.indexOf(kanji) == -1) {
        processed += kanji;
        if (furiganized[key].match(ruby_rxp)) {
            furiganized[key] = furiganized[key].replace(ruby_rxp, sprintf('<ruby><rb>%s</rb><rp>(</rp><rt style="%s">%s</rt><rp>)</rp></ruby>', kanji, yomi_style, yomi));
        } else {
            bare_rxp = new RegExp(kanji, 'g');
            furiganized[key] = furiganized[key].replace(bare_rxp, sprintf('<ruby><rb>%s</rb><rp>(</rp><rt style="%s">%s</rt><rp>)</rp></ruby>', kanji, yomi_style, yomi));
        }
    }
}

//Extension requests listener. Handles communication between extension and the content scripts
chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponseCallback) {
        //send config variables to content script
        if (request.message == "config_values_request") {
            sendResponseCallback({
                userKanjiList: localStorage.getItem("user_kanji_list"),
                includeLinkText: localStorage.getItem("include_link_text"),
                persistentMode: localStorage.getItem("persistent_mode"),
                furiganaEnabled: furiganaEnabled
            });
        //prepare tab for injection
        } else if (request.message == "init_tab_for_fi") {
            enableTabForFI(sender.tab);
        //process DOM nodes containing kanji and insert furigana
        } else if (request.message == 'text_to_furiganize') {
            furiganized = {};
            for (key in request.textToFuriganize) {
                furiganized[key] = request.textToFuriganize[key];
                tagged = tagger.parse(request.textToFuriganize[key]);

                processed = '';
                var numeric = false;
                var numeric_yomi = exceptions;
                var numeric_kanji = '';

                tagged.forEach(function(t) {
                    if (t.surface.match(/[\u3400-\u9FBF]/)) {
                        kanji = t.surface;
                        yomi = t.feature.split(',')[t.feature.split(',').length - 2];

                        //filter okurigana (word endings)
                        if (JSON.parse(localStorage.getItem("filter_okurigana"))) {
                            diff = JsDiff.diffChars(kanji, wanakana.toHiragana(yomi));
                            kanjiFound = false;
                            yomiFound = false;
                            //separate kanji and kana characters in the string using diff
                            //and inject furigana only into kanji part
                            diff.forEach(function(part) {
                                if (part.added) {
                                    yomi = wanakana.toKatakana(part.value);
                                    yomiFound = true;
                                }
                                if (part.removed) {
                                    kanji = part.value;
                                    kanjiFound = true;
                                }
                                if (kanjiFound && yomiFound) {
                                    addRuby(furiganized, kanji, yomi, key, processed);
                                    kanjiFound = false;
                                    yomiFound = false;
                                }
                            });
                        } else {
                            addRuby(furiganized, kanji, yomi, key, processed);
                        }
                    }
                });
            }
            //send processed DOM nodes back to the tab content script
            chrome.tabs.sendMessage(sender.tab.id, {
                furiganizedTextNodes: furiganized
            });
            furiganaEnabled = true;
        //update page icon to 'enabled'
        } else if (request.message == "show_page_processed") {
            chrome.pageAction.setIcon({
                path: {
                    "19": "img/icons/furigana_active_38.png",
                    "38": "img/icons/furigana_active_76.png"
                },
                tabId: sender.tab.id
            });
            chrome.pageAction.setTitle({
                title: "Remove furigana",
                tabId: sender.tab.id
            });
        //update page icon to 'disabled'
        } else if (request.message == "reset_page_action_icon") {
            chrome.pageAction.setIcon({
                path: {
                    "19": "img/icons/furigana_inactive_38.png",
                    "38": "img/icons/furigana_inactive_76.png"
                },
                tabId: sender.tab.id
            });
            chrome.pageAction.setTitle({
                title: "Insert furigana",
                tabId: sender.tab.id
            });
            furiganaEnabled = false;
        } else {
            console.log("Programming error: a request with the unexpected \"message\" value \"" + request.message + "\" was received in the background page.");
        }
    }
);

//Storage events
window.addEventListener("storage",
    function(e) {
        if (e.key == "user_kanji_list") { //re-initialize the data in each tab (when they reload or they move to a new page)
            userKanjiRegexp = new RegExp("[" + localStorage.getItem("user_kanji_list") + "]");
        }
    }, false);<commit_msg>FIXED: persistent mode flag now correctly checked when toggling furigana<commit_after>var dicfiles = ['char.category', 'code2category', 'word2id', 'word.dat', 'word.ary.idx', 'word.inf', 'matrix.bin'];
var tagger = null;
var furiganized = {};
var exceptions = null;
var furiganaEnabled = false;

//initialize variables
if (!localStorage)
    console.log("Error: localStorage not available to background page. Has local storage been disabled in this instance of Chrome?");

if (localStorage.getItem("user_kanji_list") === null) {
    console.log("The localStorage \"user_kanji_list\" value was null. It will be initialised to the installation default list.");
    var defaultUserKanjiList = "日一国会人年大十二本中長出三同時政事自行社見月分議後前民生連五発間対上部東者党地合市業内相方四定今回新場金員九入選立開手米力学問高代明実円関決子動京全目表戦経通外最言氏現理調体化田当八六約主題下首意法不来作性的要用制治度務強気小七成期公持野協取都和統以機平総加山思家話世受区領多県続進正安設保改数記院女初北午指権心界支第産結百派点教報済書府活原先共得解名交資予川向際査勝面委告軍文反元重近千考判認画海参売利組知案道信策集在件団別物側任引使求所次水半品昨論計死官増係感特情投示変打男基私各始島直両朝革価式確村提運終挙果西勢減台広容必応演電歳住争談能無再位置企真流格有疑口過局少放税検藤町常校料沢裁状工建語球営空職証土与急止送援供可役構木割聞身費付施切由説転食比難防補車優夫研収断井何南石足違消境神番規術護展態導鮮備宅害配副算視条幹独警宮究育席輸訪楽起万着乗店述残想線率病農州武声質念待試族象銀域助労例衛然早張映限親額監環験追審商葉義伝働形景落欧担好退準賞訴辺造英被株頭技低毎医復仕去姿味負閣韓渡失移差衆個門写評課末守若脳極種美岡影命含福蔵量望松非撃佐核観察整段横融型白深字答夜製票況音申様財港識注呼渉達";
    localStorage.setItem("user_kanji_list", defaultUserKanjiList);
}
var userKanjiRegexp = new RegExp("[" + localStorage.getItem("user_kanji_list") + "]");

//initialize local storage
var localStoragePrefDefaults = {
    "include_link_text": true,
    "furigana_display": "hira",
    "filter_okurigana": true,
    "persistent_mode": false,
    "yomi_size": "",
    "yomi_color": ""
}

for (var key in localStoragePrefDefaults) {
    if (localStorage.getItem(key) === null) {
        console.log("The localStorage \"" + key + "\" value was null. It will be initialised to" + localStoragePrefDefaults[key] + ".");
        localStorage.setItem(key, localStoragePrefDefaults[key]);
    }
}

//initialize IGO-JS
igo.getServerFileToArrayBufffer("res/ipadic.zip", function(buffer) {
    try {
        var blob = new Blob([new Uint8Array(buffer)]);
        var reader = new FileReader();
        reader.onload = function(e) {
            var dic = Zip.inflate(new Uint8Array(reader.result))
            tagger = loadTagger(dic);
        }
        reader.readAsArrayBuffer(blob);
    } catch (e) {
        console.error(e.toString());
    }
});

$.getJSON("res/exceptions.json", function(data) {
    exceptions = data;
});

/*****************
 *  Functions
 *****************/
//load dictionaries
function loadTagger(dicdir) {
    var files = new Array();
    for (var i = 0; i < dicfiles.length; ++i) {
        files[dicfiles[i]] = dicdir.files[dicfiles[i]].inflate();
    }

    var category = new igo.CharCategory(files['code2category'], files['char.category']);
    var wdc = new igo.WordDic(files['word2id'], files['word.dat'], files['word.ary.idx'], files['word.inf']);
    var unk = new igo.Unknown(category);
    var mtx = new igo.Matrix(files['matrix.bin']);
    return new igo.Tagger(wdc, unk, mtx);
}
//prepare a tab for furigana injection
function enableTabForFI(tab) {
    chrome.pageAction.setIcon({
        path: {
            "19": "img/icons/furigana_inactive_38.png",
            "38": "img/icons/furigana_inactive_76.png"
        },
        tabId: tab.id
    });
    chrome.pageAction.setTitle({
        title: "Insert furigana",
        tabId: tab.id
    });
    chrome.pageAction.show(tab.id);
    chrome.tabs.executeScript(tab.id, {
        file: "text_to_furigana_dom_parse.js"
    });
}

/*****************
 *  Chrome events
 *****************/

//Page action listener
chrome.pageAction.onClicked.addListener(function(tab) {
    if (JSON.parse(localStorage.getItem('persistent_mode')) == true) {
        chrome.tabs.query({} ,function (tabs) {
            for (var i = 0; i < tabs.length; i++) {
                chrome.tabs.executeScript(tabs[i].id, {code: "toggleFurigana();"});
            }
        });
    } else {
        chrome.tabs.executeScript(tab.id, {
            code: "toggleFurigana();"
        });
    }
});

//Keyboard action listener
chrome.commands.onCommand.addListener(function(command) {
    if (JSON.parse(localStorage.getItem('persistent_mode')) == true) {
        chrome.tabs.query({} ,function (tabs) {
            for (var i = 0; i < tabs.length; i++) {
                chrome.tabs.executeScript(tabs[i].id, {code: "toggleFurigana();"});
            }
        });
    } else {
        chrome.tabs.executeScript(tab.id, {
            code: "toggleFurigana();"
        });
    }
});

//Ruby tag injector
function addRuby(furiganized, kanji, yomi, key, processed) {
    //furigana can be displayed in either hiragana, katakana or romaji
    switch (localStorage.getItem("furigana_display")) {
        case "hira":
            yomi = wanakana.toHiragana(yomi);
            break;
        case "roma":
            yomi = wanakana.toRomaji(yomi);
            break;
        default:
            break;
    }

    ruby_rxp = new RegExp(sprintf('<ruby><rb>%s<\\/rb><rp>\\(<\\/rp><rt[ style=]*.*?>([\\u3040-\\u3096|\\u30A1-\\u30FA|\\uFF66-\\uFF9D|\\u31F0-\\u31FF]+)<\\/rt><rp>\\)<\\/rp><\\/ruby>', kanji), 'g');

    //apply user styles to furigana text
    yomi_size = '';
    yomi_color = '';

    localStorage.getItem('yomi_size').length > 0 ? yomi_size = sprintf('font-size:%spt', localStorage.getItem('yomi_size')) : yomi_size = '';
    localStorage.getItem('yomi_color').length > 0 ? yomi_color = sprintf(';color:%s', localStorage.getItem('yomi_color')) : yomi_color = '';

    yomi_style = yomi_size + yomi_color;

    //inject furigana into text nodes
    //a different regex is used for repeat passes to avoid having multiple rubies on the same base
    if (processed.indexOf(kanji) == -1) {
        processed += kanji;
        if (furiganized[key].match(ruby_rxp)) {
            furiganized[key] = furiganized[key].replace(ruby_rxp, sprintf('<ruby><rb>%s</rb><rp>(</rp><rt style="%s">%s</rt><rp>)</rp></ruby>', kanji, yomi_style, yomi));
        } else {
            bare_rxp = new RegExp(kanji, 'g');
            furiganized[key] = furiganized[key].replace(bare_rxp, sprintf('<ruby><rb>%s</rb><rp>(</rp><rt style="%s">%s</rt><rp>)</rp></ruby>', kanji, yomi_style, yomi));
        }
    }
}

//Extension requests listener. Handles communication between extension and the content scripts
chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponseCallback) {
        //send config variables to content script
        if (request.message == "config_values_request") {
            sendResponseCallback({
                userKanjiList: localStorage.getItem("user_kanji_list"),
                includeLinkText: localStorage.getItem("include_link_text"),
                persistentMode: localStorage.getItem("persistent_mode"),
                furiganaEnabled: furiganaEnabled
            });
        //prepare tab for injection
        } else if (request.message == "init_tab_for_fi") {
            enableTabForFI(sender.tab);
        //process DOM nodes containing kanji and insert furigana
        } else if (request.message == 'text_to_furiganize') {
            furiganized = {};
            for (key in request.textToFuriganize) {
                furiganized[key] = request.textToFuriganize[key];
                tagged = tagger.parse(request.textToFuriganize[key]);

                processed = '';
                var numeric = false;
                var numeric_yomi = exceptions;
                var numeric_kanji = '';

                tagged.forEach(function(t) {
                    if (t.surface.match(/[\u3400-\u9FBF]/)) {
                        kanji = t.surface;
                        yomi = t.feature.split(',')[t.feature.split(',').length - 2];

                        //filter okurigana (word endings)
                        if (JSON.parse(localStorage.getItem("filter_okurigana"))) {
                            diff = JsDiff.diffChars(kanji, wanakana.toHiragana(yomi));
                            kanjiFound = false;
                            yomiFound = false;
                            //separate kanji and kana characters in the string using diff
                            //and inject furigana only into kanji part
                            diff.forEach(function(part) {
                                if (part.added) {
                                    yomi = wanakana.toKatakana(part.value);
                                    yomiFound = true;
                                }
                                if (part.removed) {
                                    kanji = part.value;
                                    kanjiFound = true;
                                }
                                if (kanjiFound && yomiFound) {
                                    addRuby(furiganized, kanji, yomi, key, processed);
                                    kanjiFound = false;
                                    yomiFound = false;
                                }
                            });
                        } else {
                            addRuby(furiganized, kanji, yomi, key, processed);
                        }
                    }
                });
            }
            //send processed DOM nodes back to the tab content script
            chrome.tabs.sendMessage(sender.tab.id, {
                furiganizedTextNodes: furiganized
            });
            furiganaEnabled = true;
        //update page icon to 'enabled'
        } else if (request.message == "show_page_processed") {
            chrome.pageAction.setIcon({
                path: {
                    "19": "img/icons/furigana_active_38.png",
                    "38": "img/icons/furigana_active_76.png"
                },
                tabId: sender.tab.id
            });
            chrome.pageAction.setTitle({
                title: "Remove furigana",
                tabId: sender.tab.id
            });
        //update page icon to 'disabled'
        } else if (request.message == "reset_page_action_icon") {
            chrome.pageAction.setIcon({
                path: {
                    "19": "img/icons/furigana_inactive_38.png",
                    "38": "img/icons/furigana_inactive_76.png"
                },
                tabId: sender.tab.id
            });
            chrome.pageAction.setTitle({
                title: "Insert furigana",
                tabId: sender.tab.id
            });
            furiganaEnabled = false;
        } else {
            console.log("Programming error: a request with the unexpected \"message\" value \"" + request.message + "\" was received in the background page.");
        }
    }
);

//Storage events
window.addEventListener("storage",
    function(e) {
        if (e.key == "user_kanji_list") { //re-initialize the data in each tab (when they reload or they move to a new page)
            userKanjiRegexp = new RegExp("[" + localStorage.getItem("user_kanji_list") + "]");
        }
    }, false);<|endoftext|>