<commit_before>/*global module, require, define*/
/*jslint evil: true*/

/**
 * Html Templating.
 * The MIT License (MIT)
 * Copyright (c) 2014 Munawwar
 */
(function (root, factory, saferEval) {
    if (typeof exports === 'object') {
        var jsdom = require('jsdom').jsdom,
            window = jsdom('').parentWindow;
        module.exports = factory(
            require('./jquery')(window),
            require('./js-object-literal-parse.js'),
            saferEval,
            window
        );
    } else if (typeof define === 'function' && define.amd) {
        define(['jquery', './js-object-literal-parse'], factory, saferEval);
    } else {
        root.Htmlizer = factory(root.jQuery, root.parseObjectLiteral, saferEval);
    }
}(this, function ($, parseObjectLiteral, saferEval, window) {
    //browser and jsdom compatibility
    window = window || this;
    var document = window.document;

    function unwrap(str) {
        var o = {};
        str.split(',').forEach(function (val) {
            o[val] = true;
        });
        return o;
    }

    function replaceJsCssPropWithCssProp(m) {
        return '-' + m.toLowerCase();
    }

    //HTML 4 and 5 void tags
    var voidTags = unwrap('area,base,basefont,br,col,command,embed,frame,hr,img,input,keygen,link,meta,param,source,track,wbr'),
        regexString = {
            JSVar: "[$_A-Za-z][$_A-Za-z0-9]*"
        };
    regexString.DotNotation = '(' + regexString.JSVar + '(?:\\.' + regexString.JSVar + ')*)';

    var regexMap = {
        DotNotation: new RegExp(regexString.DotNotation)
    };

    //Valid statements.
    var syntaxRegex = {
        "if": new RegExp("(?:(ko[ ]+if|if):(.+))"),
        "ifnot": new RegExp("(?:(ko[ ]+ifnot|ifnot):(.+))"),
        foreach: new RegExp("(?:(ko[ ]+foreach|foreach):(.+))")
    };

    var conflictingBindings = unwrap('if,ifnot,foreach,text,html');

    /**
     * @param {String|DocumentFragment} template If string, then it is better if the HTML is balanced, else it probably won't be correctly converted to DOM.
     */
    function Htmlizer(template) {
        if (typeof template === 'string') {
            this.frag = document.createDocumentFragment();
            $.parseHTML(template).forEach(function (node) {
                this.frag.appendChild(node);
            }, this);
        } else { //assuming DocumentFragment
            this.frag = template;
        }
    }

    Htmlizer.prototype = {
        /**
         * @param {Object} data
         */
        toDocumentFragment: function (data, context) {
            var frag = this.frag.cloneNode(true);

            if (!context) {
                context = {
                    $parents: [],
                    $root: data,
                    $data: data,
                    $rawData: data
                };
            }

            var stack = [], //Keep track of ifs and fors
                block = [],
                foreachOpen = false,
                blockNestingCount = 0,
                toRemove = []; //use this to remove nodes within if statement that are false.
            traverse(frag, frag, function (node, isOpenTag) {
                if (isOpenTag) {
                    if (stack[0] && stack[0].key === 'if' && !stack[0].val) {
                        toRemove.push(node);
                        return 'continue';
                    }
                    if (foreachOpen) {
                        block.push(node);
                    }

                    var val, match, tempFrag, inner;
                    if (node.nodeType === 1 && !foreachOpen) { //element
                        var bindOpts = node.getAttribute('data-bind');

                        if (bindOpts) {
                            node.removeAttribute('data-bind');
                            var conflict = [];
                            this.forEachObjectLiteral(bindOpts, function (binding) {
                                if (binding in conflictingBindings) {
                                    conflict.push(binding);
                                }
                            });
                            if (conflict.length > 1) {
                                throw new Error('Multiple bindings (' + conflict[0] + ' and ' + conflict[1] + ') are trying to control descendant bindings of the same element.' +
                                    'You cannot use these bindings together on the same element.');
                            }
                        }

                        this.forEachObjectLiteral(bindOpts, function (binding, value) {
                            //Convert ifnot: (...) to if: !(...)
                            if (binding === 'ifnot') {
                                value = '!(' + value + ')';
                            }

                            //First evaluate if
                            if (binding === 'if') {
                                val = saferEval(value, context, data, node);
                                if (!val) {
                                    toRemove = toRemove.concat(this.slice(node.childNodes));
                                    return 'continue';
                                }
                            }

                            if (binding === 'foreach') {
                                if (value[0] === '{') {
                                    inner = this.parseObjectLiteral(value);
                                    val = {
                                        items: saferEval(inner.data, context, data, node),
                                        as: inner.as.slice(1, -1) //strip string quote
                                    };
                                } else {
                                    val = {items: saferEval(value, context, data, node)};
                                }
                                tempFrag = document.createDocumentFragment();
                                this.slice(node.childNodes).forEach(function (n) {
                                    n.parentNode.removeChild(n);
                                    tempFrag.appendChild(n);
                                });
                                if (tempFrag.firstChild && val.items instanceof Array) {
                                    tempFrag = this.executeForEach(tempFrag, context, data, val.items, val.as);
                                    node.appendChild(tempFrag);
                                }
                            }

                            if (binding === 'with') {
                                val = saferEval(value, context, data, node);

                                tempFrag = document.createDocumentFragment();
                                this.slice(node.childNodes).forEach(function (n) {
                                    n.parentNode.removeChild(n);
                                    tempFrag.appendChild(n);
                                });

                                if (tempFrag.firstChild && val) {
                                    var newContext = this.getNewContext(context, val);
                                    node.appendChild((new Htmlizer(tempFrag)).toDocumentFragment(val, newContext));
                                }
                            }

                            if (binding === 'text' && regexMap.DotNotation.test(value)) {
                                val = saferEval(value, context, data, node);
                                if (val !== undefined) {
                                    node.appendChild(document.createTextNode(val));
                                }
                            }

                            if (binding === 'html') {
                                $(node).empty();
                                val = saferEval(value, context, data, node);
                                if (val) {
                                    tempFrag = document.createDocumentFragment();
                                    $.parseHTML(val).forEach(function (node) {
                                        tempFrag.appendChild(node);
                                    }, this);
                                    node.appendChild(tempFrag);
                                }
                            }

                            if (binding === 'attr') {
                                this.forEachObjectLiteral(value.slice(1, -1), function (attr, value) {
                                    if (regexMap.DotNotation.test(value)) {
                                        val = saferEval(value, context, data, node);
                                        if (val) {
                                            node.setAttribute(attr, val);
                                        }
                                    }
                                });<commit_msg>text binding: KO seems to nuke innerHTML before setting text.<commit_after>/*global module, require, define*/
/*jslint evil: true*/

/**
 * Html Templating.
 * The MIT License (MIT)
 * Copyright (c) 2014 Munawwar
 */
(function (root, factory, saferEval) {
    if (typeof exports === 'object') {
        var jsdom = require('jsdom').jsdom,
            window = jsdom('').parentWindow;
        module.exports = factory(
            require('./jquery')(window),
            require('./js-object-literal-parse.js'),
            saferEval,
            window
        );
    } else if (typeof define === 'function' && define.amd) {
        define(['jquery', './js-object-literal-parse'], factory, saferEval);
    } else {
        root.Htmlizer = factory(root.jQuery, root.parseObjectLiteral, saferEval);
    }
}(this, function ($, parseObjectLiteral, saferEval, window) {
    //browser and jsdom compatibility
    window = window || this;
    var document = window.document;

    function unwrap(str) {
        var o = {};
        str.split(',').forEach(function (val) {
            o[val] = true;
        });
        return o;
    }

    function replaceJsCssPropWithCssProp(m) {
        return '-' + m.toLowerCase();
    }

    //HTML 4 and 5 void tags
    var voidTags = unwrap('area,base,basefont,br,col,command,embed,frame,hr,img,input,keygen,link,meta,param,source,track,wbr'),
        regexString = {
            JSVar: "[$_A-Za-z][$_A-Za-z0-9]*"
        };
    regexString.DotNotation = '(' + regexString.JSVar + '(?:\\.' + regexString.JSVar + ')*)';

    var regexMap = {
        DotNotation: new RegExp(regexString.DotNotation)
    };

    //Valid statements.
    var syntaxRegex = {
        "if": new RegExp("(?:(ko[ ]+if|if):(.+))"),
        "ifnot": new RegExp("(?:(ko[ ]+ifnot|ifnot):(.+))"),
        foreach: new RegExp("(?:(ko[ ]+foreach|foreach):(.+))")
    };

    var conflictingBindings = unwrap('if,ifnot,foreach,text,html');

    /**
     * @param {String|DocumentFragment} template If string, then it is better if the HTML is balanced, else it probably won't be correctly converted to DOM.
     */
    function Htmlizer(template) {
        if (typeof template === 'string') {
            this.frag = document.createDocumentFragment();
            $.parseHTML(template).forEach(function (node) {
                this.frag.appendChild(node);
            }, this);
        } else { //assuming DocumentFragment
            this.frag = template;
        }
    }

    Htmlizer.prototype = {
        /**
         * @param {Object} data
         */
        toDocumentFragment: function (data, context) {
            var frag = this.frag.cloneNode(true);

            if (!context) {
                context = {
                    $parents: [],
                    $root: data,
                    $data: data,
                    $rawData: data
                };
            }

            var stack = [], //Keep track of ifs and fors
                block = [],
                foreachOpen = false,
                blockNestingCount = 0,
                toRemove = []; //use this to remove nodes within if statement that are false.
            traverse(frag, frag, function (node, isOpenTag) {
                if (isOpenTag) {
                    if (stack[0] && stack[0].key === 'if' && !stack[0].val) {
                        toRemove.push(node);
                        return 'continue';
                    }
                    if (foreachOpen) {
                        block.push(node);
                    }

                    var val, match, tempFrag, inner;
                    if (node.nodeType === 1 && !foreachOpen) { //element
                        var bindOpts = node.getAttribute('data-bind');

                        if (bindOpts) {
                            node.removeAttribute('data-bind');
                            var conflict = [];
                            this.forEachObjectLiteral(bindOpts, function (binding) {
                                if (binding in conflictingBindings) {
                                    conflict.push(binding);
                                }
                            });
                            if (conflict.length > 1) {
                                throw new Error('Multiple bindings (' + conflict[0] + ' and ' + conflict[1] + ') are trying to control descendant bindings of the same element.' +
                                    'You cannot use these bindings together on the same element.');
                            }
                        }

                        this.forEachObjectLiteral(bindOpts, function (binding, value) {
                            //Convert ifnot: (...) to if: !(...)
                            if (binding === 'ifnot') {
                                value = '!(' + value + ')';
                            }

                            //First evaluate if
                            if (binding === 'if') {
                                val = saferEval(value, context, data, node);
                                if (!val) {
                                    toRemove = toRemove.concat(this.slice(node.childNodes));
                                    return 'continue';
                                }
                            }

                            if (binding === 'foreach') {
                                if (value[0] === '{') {
                                    inner = this.parseObjectLiteral(value);
                                    val = {
                                        items: saferEval(inner.data, context, data, node),
                                        as: inner.as.slice(1, -1) //strip string quote
                                    };
                                } else {
                                    val = {items: saferEval(value, context, data, node)};
                                }
                                tempFrag = document.createDocumentFragment();
                                this.slice(node.childNodes).forEach(function (n) {
                                    n.parentNode.removeChild(n);
                                    tempFrag.appendChild(n);
                                });
                                if (tempFrag.firstChild && val.items instanceof Array) {
                                    tempFrag = this.executeForEach(tempFrag, context, data, val.items, val.as);
                                    node.appendChild(tempFrag);
                                }
                            }

                            if (binding === 'with') {
                                val = saferEval(value, context, data, node);

                                tempFrag = document.createDocumentFragment();
                                this.slice(node.childNodes).forEach(function (n) {
                                    n.parentNode.removeChild(n);
                                    tempFrag.appendChild(n);
                                });

                                if (tempFrag.firstChild && val) {
                                    var newContext = this.getNewContext(context, val);
                                    node.appendChild((new Htmlizer(tempFrag)).toDocumentFragment(val, newContext));
                                }
                            }

                            if (binding === 'text' && regexMap.DotNotation.test(value)) {
                                val = saferEval(value, context, data, node);
                                if (val !== undefined) {
                                    node.innerHTML = ''; //KO nukes the inner content.
                                    node.appendChild(document.createTextNode(val));
                                }
                            }

                            if (binding === 'html') {
                                $(node).empty();
                                val = saferEval(value, context, data, node);
                                if (val) {
                                    tempFrag = document.createDocumentFragment();
                                    $.parseHTML(val).forEach(function (node) {
                                        tempFrag.appendChild(node);
                                    }, this);
                                    node.appendChild(tempFrag);
                                }
                            }

                            if (binding === 'attr') {
                                this.forEachObjectLiteral(value.slice(1, -1), function (attr, value) {
                                    if (regexMap.DotNotation.test(value)) {
                                        val = saferEval(value, context, data, node);
                                        if (val) {
                                            node.setAttribute(attr, val);
                                        }
                                    }
                                });
{'fraction_non_alphanumeric': 0.11099276865295139, 'fraction_numerical': 0.0023543920623353325, 'mean_word_length': 0.9939644573600089, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 95, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1949088', 'n_tokens_mistral': 4181, 'n_tokens_neox': 3962, 'n_words': 871}