<commit_before>'use strict';

var VirtualDOM = require('./../virtual-dom/virtual-dom');
var Behaviors = require('./../behaviors/behaviors');
var ControlFlowUtils = require('./control-flow-utils');

var BOOLEAN_KEY = 'boolean';
var REPEAT_INFO_KEY = ControlFlowUtils.CONSTANTS.REPEAT_INFO_KEY;
var REPEAT_KEY = ControlFlowUtils.CONSTANTS.REPEAT_KEY;
var SELF_KEY = '$self';
var STRING_KEY = 'string';
var UID_KEY = 'uid';
var YIELD_KEY = ControlFlowUtils.CONSTANTS.YIELD_KEY;

function initializeSelfContainedFlows(blueprint, uid, controlFlowDataMngr) {
    var expandedBlueprint = VirtualDOM.clone(blueprint);
    initializeIfBehaviors(blueprint, expandedBlueprint, uid, controlFlowDataMngr);
    initializeRepeatBehaviors(expandedBlueprint, uid, controlFlowDataMngr);
    return expandedBlueprint;
}

function removeNodesFromExpandedBlueprint(expandedBlueprint, selector) {
    VirtualDOM.eachNode(expandedBlueprint, selector, function(node) {
        node.parentNode.removeChild(node);
    });
}

function initializeIfBehaviors(blueprint, expandedBlueprint, uid, controlFlowDataMngr) {
    var ifBehaviors = controlFlowDataMngr.getIfBehaviors();
    var behavior;
    var payload;
    for (var i = 0; i < ifBehaviors.length; i++) {
        behavior = ifBehaviors[i];
        payload = Behaviors.getPayloadFromUID(behavior, uid);

        controlFlowDataMngr.initializeDataForIfBehavior(behavior.selector, payload, blueprint);
        if (!payload) {
            // Remove node from expanded blueprint to avoid overhead of processing components
            removeNodesFromExpandedBlueprint(expandedBlueprint, behavior.selector);
        }
    }
}

function findChildRepeatSelectors(ifSelector, expandedBlueprint, controlFlowDataMngr) {
    var repeatSelectors = Object.keys(controlFlowDataMngr.getRepeatData());
    var repeatNodes = [];
    var childRepeatSelectors = [];
    var repeatNode;
    var i;
    for (i = 0; i < repeatSelectors.length; i++) {
        VirtualDOM.eachNode(expandedBlueprint, repeatSelectors[i], function(repeatNode) {
            if (repeatNodes.indexOf(repeatNode) === -1) {
                repeatNodes.push({
                    selector: repeatSelectors[i],
                    node: repeatNode
                });
            }
        });
    }
    VirtualDOM.eachNode(expandedBlueprint, ifSelector, function(ifNode) {
        for (i = 0; i < repeatNodes.length; i++) {
            repeatNode = repeatNodes[i];
            if (VirtualDOM.isDescendant(repeatNode.node, ifNode)) {
                if (childRepeatSelectors.indexOf(repeatNode.selector) === -1) {
                    childRepeatSelectors.push(repeatNode.selector);
                }
            }
        }
    });
    return childRepeatSelectors;
}

function processIfBehavior(behavior, expandedBlueprint, uid, controlFlowDataMngr) {
    var payload = Behaviors.getPayloadFromUID(behavior, uid);
    var selector = behavior.selector;
    var data = controlFlowDataMngr.getIfData()[selector];
    if (!data) {
        throw new Error('If behavior for selector: `' + selector + '` has not yet been initialized');
    }

    var oldPayload = controlFlowDataMngr.getIfPayload(selector);
    if (payload !== oldPayload) {
        applyIfBehaviorToVirtualDOM(payload, selector, expandedBlueprint, data);

        // If the payload has updated from `true` to `false`, all data associated with 'childRepeatSelectors'
        // (i.e., selectors that target nodes that are descendants of the nodes that are targeted
        // by the current '$if' behavior) needs to be reset because those behaviors will need to be re-run
        // and the parentUIDs associated with the behaviors will need to be recalculated.
        if (payload) {
            controlFlowDataMngr.resetRepeatData(
                findChildRepeatSelectors(selector, expandedBlueprint, controlFlowDataMngr)
            );
        }

        controlFlowDataMngr.setIfPayload(selector, payload);
    }
}

function verifyRepeatPayload(payload) {
    if (!(payload instanceof Array)) {
        throw new Error('Unsupported payload type for $repeat: `' + payload + '`');
    }
}

function initializeRepeatBehaviors(expandedBlueprint, uid, controlFlowDataMngr) {
    var repeatBehaviors = controlFlowDataMngr.behaviors[REPEAT_KEY];
    for (var i = 0; i < repeatBehaviors.length; i++) {
        processRepeatBehavior(repeatBehaviors[i], expandedBlueprint, uid, controlFlowDataMngr);
    }
}

function removeNodesStoredInRepeatData(data) {
    var repeatedNodes;
    for (var i = 0; i < data.parentUIDs.length; i++) {
        repeatedNodes = data.parentUIDs[i].repeatedNodes;
        for (var j = 0; j < repeatedNodes.length; j++) {
            VirtualDOM.deleteNode(repeatedNodes[j]);
        }
    }
}

function processRepeatBehavior(behavior, expandedBlueprint, uid, controlFlowDataMngr) {
    var payload = Behaviors.getPayloadFromUID(behavior, uid);
    verifyRepeatPayload(payload);
    var selector = behavior.selector;

    var repeatData = controlFlowDataMngr.getRepeatData();

    if (!repeatData[selector]) {
        controlFlowDataMngr.initializeDataForRepeatBehavior(selector, payload, expandedBlueprint);

        // Remove manually repeated (i.e., nodes that have been repeated in tree w/o applying behavior)
        // nodes from expandedBlueprint to avoid overhead of creating unnecessary component since
        // they will be overwritten by nodes that are created using behavior.
        removeNodesStoredInRepeatData(repeatData[selector]);
    }

    // Update repeat payload
    controlFlowDataMngr.setRepeatPayload(selector, payload);
    applyRepeatBehaviorToVirtualDOM(expandedBlueprint, repeatData[selector]);
}

function initializeParentDefinedFlows(expandedBlueprint, childrenRoot, injectablesRoot, controlFlowDataMngr) {
    processYield(childrenRoot, injectablesRoot, expandedBlueprint, controlFlowDataMngr);
    return childrenRoot;
}

function processYield(target, injectablesRoot, expandedBlueprint, controlFlowDataMngr) {
    if (injectablesRoot) {
        var yieldBehaviors = controlFlowDataMngr.behaviors[YIELD_KEY];
        for (var i = 0; i < yieldBehaviors.length; i++) {
            applyYieldBehaviorToVirtualDOM(yieldBehaviors[i], target, injectablesRoot, expandedBlueprint);
        }
    }
}

/*-----------------------------------------------------------------------------------------*/
// VirtualDOM manipulation
/*-----------------------------------------------------------------------------------------*/
function addDeleteMessages(expandedBlueprint, selector) {
    var targets = VirtualDOM.query(expandedBlueprint, selector);
    for (var i = 0; i < targets.length; i++) {
        ControlFlowUtils.addDeleteMessage(targets[i]);
    }
}

function applyIfBehaviorToVirtualDOM(payload, selector, expandedBlueprint, data) {
    // Add elements to expandedBlueprint
    if (payload) {
        var parentUID;
        // Cycle through all parents whose children have $if behavior applied to them
        for (parentUID in data.parentUIDs) {
            // Cycle through all nodes that should be added to parent port
            for (var i = 0; i < data.parentUIDs[parentUID].length; i++) {
                ControlFlowUtils.attachNewNode(
                    data.parentUIDs[parentUID][i], expandedBlueprint, parentUID
                );
            }
        }
    }
    // Remove elements from expandedBlueprint
    else {
        addDeleteMessages(expandedBlueprint, selector);
    }
}

function applyRepeatBehaviorToVirtualDOM(expandedBlueprint, data) {
    for (var payloadIndex = 0; payloadIndex < data.payloadEquality.length; payloadIndex++) {
        if (data.payloadEquality[payloadIndex]) {
            continue;
        }

        var payload = data.payload[payloadIndex];
        var parentData;
        var newNode;
        for (var parentIndex = 0; parentIndex < data.parentUIDs.length; parentIndex++) {
            parentData = data.parentUIDs[parentIndex];

            // Delete existing node since payload is different
            if (parentData.repeatedNodes[payloadIndex]) {
                ControlFlowUtils.addDeleteMessage(parentData.repeatedNodes[payloadIndex]);
                parentData.repeatedNodes[payloadIndex] = null;
            }

            // Create new node if payload exists
            // (payload equality can be false if payload is missing)
            if (payload) {
                newNode = ControlFlowUtils.attachNewNode(
                    parentData.blueprint, expandedBlueprint, parentData.uid
                );
                ControlFlowUtils.addRepeatInfo(newNode, payloadIndex, payload);
                parentData.repeatedNodes[payloadIndex] = newNode;
            }
        }
    }
    return expandedBlueprint;
}

function applyYieldBehaviorToVirtualDOM(yieldBehavior, target, injectablesRoot, expandedBlueprint) {
    // Process yield payload
    var yieldValue = yieldBehavior.action();
    var injectables;
    switch (typeof yieldValue) {
        case BOOLEAN_KEY:
            injectables = yieldValue ? injectablesRoot.children : [];
            break;
        case STRING_KEY:
            injectables = VirtualDOM.query(injectablesRoot, yieldValue);
            break;
        default:
            throw new Error('Unsupported payload type for $yield');
    }

    // Only continue processing $yield if injectables have been passed
    // in from parent.
    if (injectables.length === 0) {
        return;
    }

    // Locate 'ports' that accept injected nodes from parent
    var selector = yieldBehavior.selector;
    var yieldPorts;
    if (selector === SELF_KEY) {
        yieldPorts = [target];
    }
    else {
        yieldPorts = VirtualDOM.query(target, selector);
    }

    // Attach cloned injectables into the ports. A new port should be created for
    // each injectable and the ports should be indexed based on the index of the
    // injectable. For example:
    /*
        alpha
            behavior
                .item-view
                    yield: true
            tree
                node.item-view

        beta
            tree
                alpha
                    node item 1
                    node item 2
                    node item 3

        After processing, <node.item-view> will be created for each passed in <node>
        i.e.:
            tree:
                node.item-view // index 0
                    node item 1
                node.item-view // index 1
                    node item 2
                node.item-view // index 2
                    node item3
     */
    var parentNode;
    var parentUID;
    var parentNodeFromExpandedBlueprint;
    var yieldPort;
    var blueprintPort;
    var clonedPort;
    var clonedInjectable;

    var i;

    // When the $yield behavior is applied to the $self selector, yield ports should not be cloned.
    // Instead, all of the injectables should be added directly to component's children root.
    if (selector === SELF_KEY) {
        yieldPort = yieldPorts[0];
        ControlFlowUtils.addRepeatInfo(yieldPort, 0, {});
        for (i = 0; i < injectables.length; i++) {
            clonedInjectable = VirtualDOM.clone(injectables[i]);
            if (!VirtualDOM.getAttribute(clonedInjectable, REPEAT_INFO_KEY)) {
                // Add $index to element being repeated unless its already defined
                ControlFlowUtils.addRepeatInfo(clonedInjectable, j, {});
            }
            yieldPort.appendChild(clonedInjectable);
        }
    }
    else {
        for (i = 0; i < yieldPorts.length; i++) {
            yieldPort = yieldPorts[i];
            blueprintPort = VirtualDOM.removeAttribute(VirtualDOM.clone(yieldPort), UID_KEY); // clone port before children are added
            parentNode = yieldPort.parentNode || yieldPort;

            // Get parent node from expandedBlueprint in order to update expandedBlueprint with
            // dynamically created ports
            parentUID = VirtualDOM.getUID(parentNode);
            if (VirtualDOM.getUID(expandedBlueprint) === parentUID) {
                parentNodeFromExpandedBlueprint = expandedBlueprint;
            }
            else {
                parentNodeFromExpandedBlueprint = VirtualDOM.getNodeByUID(expandedBlueprint, parentUID);
            }

            VirtualDOM.removeChildNodes(yieldPorts);
            for (var j = 0; j < injectables.length; j++) {
                clonedInjectable = VirtualDOM.clone(injectables[j]);
                if (!VirtualDOM.getAttribute(clonedInjectable, REPEAT_INFO_KEY)) {
                    // Add $index to element being repeated unless its already defined
                    ControlFlowUtils.addRepeatInfo(clonedInjectable, j, {});
                }

                // yieldPort already attached to parent
                if (j === 0) {
                    ControlFlowUtils.addRepeatInfo(yieldPort, j, {});
                    yieldPort.appendChild(clonedInjectable);
                }
                // clone yieldPort & attach to parent
                else {
                    clonedPort = VirtualDOM.clone(blueprintPort);
                    VirtualDOM.setUID(clonedPort);
                    // Add dynamically create port to expandedBlueprint in order
                    // to properly apply behaviors
                    VirtualDOM.addNode(
                        VirtualDOM.clone(clonedPort),
                        parentNodeFromExpandedBlueprint
                    );

                    ControlFlowUtils.addRepeatInfo(clonedPort, j, {});
                    clonedPort.appendChild(clonedInjectable);
                    parentNode.appendChild(clonedPort);
                }
            }
        }
    }
}

module.exports = {
    initializeSelfContainedFlows: initializeSelfContainedFlows,
    initializeParentDefinedFlows: initializeParentDefinedFlows,
    initializeIfBehaviors: initializeIfBehaviors,
    processIfBehavior: processIfBehavior,
    processRepeatBehavior: processRepeatBehavior,
    applyIfBehaviorToVirtualDOM: applyIfBehaviorToVirtualDOM,
    applyRepeatBehaviorToVirtualDOM: applyRepeatBehaviorToVirtualDOM,
    applyYieldBehaviorToVirtualDOM: applyYieldBehaviorToVirtualDOM
};
<commit_msg>fix: always add $index to components, even if not processed through $yield<commit_after>'use strict';

var VirtualDOM = require('./../virtual-dom/virtual-dom');
var Behaviors = require('./../behaviors/behaviors');
var ControlFlowUtils = require('./control-flow-utils');

var BOOLEAN_KEY = 'boolean';
var REPEAT_INFO_KEY = ControlFlowUtils.CONSTANTS.REPEAT_INFO_KEY;
var REPEAT_KEY = ControlFlowUtils.CONSTANTS.REPEAT_KEY;
var SELF_KEY = '$self';
var STRING_KEY = 'string';
var UID_KEY = 'uid';
var YIELD_KEY = ControlFlowUtils.CONSTANTS.YIELD_KEY;

function initializeSelfContainedFlows(blueprint, uid, controlFlowDataMngr) {
    var expandedBlueprint = VirtualDOM.clone(blueprint);
    initializeIfBehaviors(blueprint, expandedBlueprint, uid, controlFlowDataMngr);
    initializeRepeatBehaviors(expandedBlueprint, uid, controlFlowDataMngr);
    return expandedBlueprint;
}

function removeNodesFromExpandedBlueprint(expandedBlueprint, selector) {
    VirtualDOM.eachNode(expandedBlueprint, selector, function(node) {
        node.parentNode.removeChild(node);
    });
}

function initializeIfBehaviors(blueprint, expandedBlueprint, uid, controlFlowDataMngr) {
    var ifBehaviors = controlFlowDataMngr.getIfBehaviors();
    var behavior;
    var payload;
    for (var i = 0; i < ifBehaviors.length; i++) {
        behavior = ifBehaviors[i];
        payload = Behaviors.getPayloadFromUID(behavior, uid);

        controlFlowDataMngr.initializeDataForIfBehavior(behavior.selector, payload, blueprint);
        if (!payload) {
            // Remove node from expanded blueprint to avoid overhead of processing components
            removeNodesFromExpandedBlueprint(expandedBlueprint, behavior.selector);
        }
    }
}

function findChildRepeatSelectors(ifSelector, expandedBlueprint, controlFlowDataMngr) {
    var repeatSelectors = Object.keys(controlFlowDataMngr.getRepeatData());
    var repeatNodes = [];
    var childRepeatSelectors = [];
    var repeatNode;
    var i;
    for (i = 0; i < repeatSelectors.length; i++) {
        VirtualDOM.eachNode(expandedBlueprint, repeatSelectors[i], function(repeatNode) {
            if (repeatNodes.indexOf(repeatNode) === -1) {
                repeatNodes.push({
                    selector: repeatSelectors[i],
                    node: repeatNode
                });
            }
        });
    }
    VirtualDOM.eachNode(expandedBlueprint, ifSelector, function(ifNode) {
        for (i = 0; i < repeatNodes.length; i++) {
            repeatNode = repeatNodes[i];
            if (VirtualDOM.isDescendant(repeatNode.node, ifNode)) {
                if (childRepeatSelectors.indexOf(repeatNode.selector) === -1) {
                    childRepeatSelectors.push(repeatNode.selector);
                }
            }
        }
    });
    return childRepeatSelectors;
}

function processIfBehavior(behavior, expandedBlueprint, uid, controlFlowDataMngr) {
    var payload = Behaviors.getPayloadFromUID(behavior, uid);
    var selector = behavior.selector;
    var data = controlFlowDataMngr.getIfData()[selector];
    if (!data) {
        throw new Error('If behavior for selector: `' + selector + '` has not yet been initialized');
    }

    var oldPayload = controlFlowDataMngr.getIfPayload(selector);
    if (payload !== oldPayload) {
        applyIfBehaviorToVirtualDOM(payload, selector, expandedBlueprint, data);

        // If the payload has updated from `true` to `false`, all data associated with 'childRepeatSelectors'
        // (i.e., selectors that target nodes that are descendants of the nodes that are targeted
        // by the current '$if' behavior) needs to be reset because those behaviors will need to be re-run
        // and the parentUIDs associated with the behaviors will need to be recalculated.
        if (payload) {
            controlFlowDataMngr.resetRepeatData(
                findChildRepeatSelectors(selector, expandedBlueprint, controlFlowDataMngr)
            );
        }

        controlFlowDataMngr.setIfPayload(selector, payload);
    }
}

function verifyRepeatPayload(payload) {
    if (!(payload instanceof Array)) {
        throw new Error('Unsupported payload type for $repeat: `' + payload + '`');
    }
}

function initializeRepeatBehaviors(expandedBlueprint, uid, controlFlowDataMngr) {
    var repeatBehaviors = controlFlowDataMngr.behaviors[REPEAT_KEY];
    for (var i = 0; i < repeatBehaviors.length; i++) {
        processRepeatBehavior(repeatBehaviors[i], expandedBlueprint, uid, controlFlowDataMngr);
    }
}

function removeNodesStoredInRepeatData(data) {
    var repeatedNodes;
    for (var i = 0; i < data.parentUIDs.length; i++) {
        repeatedNodes = data.parentUIDs[i].repeatedNodes;
        for (var j = 0; j < repeatedNodes.length; j++) {
            VirtualDOM.deleteNode(repeatedNodes[j]);
        }
    }
}

function processRepeatBehavior(behavior, expandedBlueprint, uid, controlFlowDataMngr) {
    var payload = Behaviors.getPayloadFromUID(behavior, uid);
    verifyRepeatPayload(payload);
    var selector = behavior.selector;

    var repeatData = controlFlowDataMngr.getRepeatData();

    if (!repeatData[selector]) {
        controlFlowDataMngr.initializeDataForRepeatBehavior(selector, payload, expandedBlueprint);

        // Remove manually repeated (i.e., nodes that have been repeated in tree w/o applying behavior)
        // nodes from expandedBlueprint to avoid overhead of creating unnecessary component since
        // they will be overwritten by nodes that are created using behavior.
        removeNodesStoredInRepeatData(repeatData[selector]);
    }

    // Update repeat payload
    controlFlowDataMngr.setRepeatPayload(selector, payload);
    applyRepeatBehaviorToVirtualDOM(expandedBlueprint, repeatData[selector]);
}

function initializeParentDefinedFlows(expandedBlueprint, childrenRoot, injectablesRoot, controlFlowDataMngr) {
    processYield(childrenRoot, injectablesRoot, expandedBlueprint, controlFlowDataMngr);
    return childrenRoot;
}

function processYield(target, injectablesRoot, expandedBlueprint, controlFlowDataMngr) {
    if (injectablesRoot) {
        var yieldBehaviors = controlFlowDataMngr.behaviors[YIELD_KEY];
        for (var i = 0; i < yieldBehaviors.length; i++) {
            applyYieldBehaviorToVirtualDOM(yieldBehaviors[i], target, injectablesRoot, expandedBlueprint);
        }
    }
    else {
        for (var i = 0; i < target.children.length; i++) {
            attachIndexToNode(target.children[i], i);
        }
    }
}

/*-----------------------------------------------------------------------------------------*/
// VirtualDOM manipulation
/*-----------------------------------------------------------------------------------------*/
function addDeleteMessages(expandedBlueprint, selector) {
    var targets = VirtualDOM.query(expandedBlueprint, selector);
    for (var i = 0; i < targets.length; i++) {
        ControlFlowUtils.addDeleteMessage(targets[i]);
    }
}

// Add $index to element being repeated unless its already add
function attachIndexToNode(node, index) {
    if (!VirtualDOM.getAttribute(node, REPEAT_INFO_KEY)) {
        ControlFlowUtils.addRepeatInfo(node, index, {});
    }
}

function applyIfBehaviorToVirtualDOM(payload, selector, expandedBlueprint, data) {
    // Add elements to expandedBlueprint
    if (payload) {
        var parentUID;
        // Cycle through all parents whose children have $if behavior applied to them
        for (parentUID in data.parentUIDs) {
            // Cycle through all nodes that should be added to parent port
            for (var i = 0; i < data.parentUIDs[parentUID].length; i++) {
                ControlFlowUtils.attachNewNode(
                    data.parentUIDs[parentUID][i], expandedBlueprint, parentUID
                );
            }
        }
    }
    // Remove elements from expandedBlueprint
    else {
        addDeleteMessages(expandedBlueprint, selector);
    }
}

function applyRepeatBehaviorToVirtualDOM(expandedBlueprint, data) {
    for (var payloadIndex = 0; payloadIndex < data.payloadEquality.length; payloadIndex++) {
        if (data.payloadEquality[payloadIndex]) {
            continue;
        }

        var payload = data.payload[payloadIndex];
        var parentData;
        var newNode;
        for (var parentIndex = 0; parentIndex < data.parentUIDs.length; parentIndex++) {
            parentData = data.parentUIDs[parentIndex];

            // Delete existing node since payload is different
            if (parentData.repeatedNodes[payloadIndex]) {
                ControlFlowUtils.addDeleteMessage(parentData.repeatedNodes[payloadIndex]);
                parentData.repeatedNodes[payloadIndex] = null;
            }

            // Create new node if payload exists
            // (payload equality can be false if payload is missing)
            if (payload) {
                newNode = ControlFlowUtils.attachNewNode(
                    parentData.blueprint, expandedBlueprint, parentData.uid
                );
                ControlFlowUtils.addRepeatInfo(newNode, payloadIndex, payload);
                parentData.repeatedNodes[payloadIndex] = newNode;
            }
        }
    }
    return expandedBlueprint;
}

function applyYieldBehaviorToVirtualDOM(yieldBehavior, target, injectablesRoot, expandedBlueprint) {
    // Process yield payload
    var yieldValue = yieldBehavior.action();
    var injectables;
    switch (typeof yieldValue) {
        case BOOLEAN_KEY:
            injectables = yieldValue ? injectablesRoot.children : [];
            break;
        case STRING_KEY:
            injectables = VirtualDOM.query(injectablesRoot, yieldValue);
            break;
        default:
            throw new Error('Unsupported payload type for $yield');
    }

    // Only continue processing $yield if injectables have been passed
    // in from parent.
    if (injectables.length === 0) {
        return;
    }

    // Locate 'ports' that accept injected nodes from parent
    var selector = yieldBehavior.selector;
    var yieldPorts;
    if (selector === SELF_KEY) {
        yieldPorts = [target];
    }
    else {
        yieldPorts = VirtualDOM.query(target, selector);
    }

    // Attach cloned injectables into the ports. A new port should be created for
    // each injectable and the ports should be indexed based on the index of the
    // injectable. For example:
    /*
        alpha
            behavior
                .item-view
                    yield: true
            tree
                node.item-view

        beta
            tree
                alpha
                    node item 1
                    node item 2
                    node item 3

        After processing, <node.item-view> will be created for each passed in <node>
        i.e.:
            tree:
                node.item-view // index 0
                    node item 1
                node.item-view // index 1
                    node item 2
                node.item-view // index 2
                    node item3
     */
    var parentNode;
    var parentUID;
    var parentNodeFromExpandedBlueprint;
    var yieldPort;
    var blueprintPort;
    var clonedPort;
    var clonedInjectable;
    var i;

    // When the $yield behavior is applied to the $self selector, yield ports should not be cloned.
    // Instead, all of the injectables should be added directly to component's children root.
    if (selector === SELF_KEY) {
        yieldPort = yieldPorts[0];
        ControlFlowUtils.addRepeatInfo(yieldPort, 0, {});
        for (i = 0; i < injectables.length; i++) {
            clonedInjectable = VirtualDOM.clone(injectables[i]);
            attachIndexToNode(clonedInjectable, i);
            yieldPort.appendChild(clonedInjectable);
        }
    }
    else {
        for (i = 0; i < yieldPorts.length; i++) {
            yieldPort = yieldPorts[i];
            blueprintPort = VirtualDOM.removeAttribute(VirtualDOM.clone(yieldPort), UID_KEY); // clone port before children are added
            parentNode = yieldPort.parentNode || yieldPort;

            // Get parent node from expandedBlueprint in order to update expandedBlueprint with
            // dynamically created ports
            parentUID = VirtualDOM.getUID(parentNode);
            if (VirtualDOM.getUID(expandedBlueprint) === parentUID) {
                parentNodeFromExpandedBlueprint = expandedBlueprint;
            }
            else {
                parentNodeFromExpandedBlueprint = VirtualDOM.getNodeByUID(expandedBlueprint, parentUID);
            }

            VirtualDOM.removeChildNodes(yieldPorts);
            for (var j = 0; j < injectables.length; j++) {
                clonedInjectable = VirtualDOM.clone(injectables[j]);
                attachIndexToNode(clonedInjectable, j);

                // yieldPort already attached to parent
                if (j === 0) {
                    ControlFlowUtils.addRepeatInfo(yieldPort, j, {});
                    yieldPort.appendChild(clonedInjectable);
                }
                // clone yieldPort & attach to parent
                else {
                    clonedPort = VirtualDOM.clone(blueprintPort);
                    VirtualDOM.setUID(clonedPort);
                    // Add dynamically create port to expandedBlueprint in order
                    // to properly apply behaviors
                    VirtualDOM.addNode(
                        VirtualDOM.clone(clonedPort),
                        parentNodeFromExpandedBlueprint
                    );

                    ControlFlowUtils.addRepeatInfo(clonedPort, j, {});
                    clonedPort.appendChild(clonedInjectable);
                    parentNode.appendChild(clonedPort);
                }
            }
        }
    }
}

module.exports = {
    initializeSelfContainedFlows: initializeSelfContainedFlows,
    initializeParentDefinedFlows: initializeParentDefinedFlows,
    initializeIfBehaviors: initializeIfBehaviors,
    processIfBehavior: processIfBehavior,
    processRepeatBehavior: processRepeatBehavior,
    applyIfBehaviorToVirtualDOM: applyIfBehaviorToVirtualDOM,
    applyRepeatBehaviorToVirtualDOM: applyRepeatBehaviorToVirtualDOM,
    applyYieldBehaviorToVirtualDOM: applyYieldBehaviorToVirtualDOM
};
<|endoftext|>


<commit_before>'use strict';

module.exports = function(grunt) {
    require('time-grunt')(grunt);

    // Project Configuration
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        assets: grunt.file.readJSON('server/config/assets.json'),
        watch: {
            js: {
                files: ['gruntfile.js', 'server.js', 'server/**/*.js', 'public/js/**', 'test/**/*.js'],
                tasks: ['jshint'],
                options: {
                    livereload: true
                }
            },
            html: {
                files: ['public/views/**', 'server/views/**'],
                options: {
                    livereload: true
                }
            },
            css: {
                files: ['public/css/**'],
                tasks: ['csslint'],
                options: {
                    livereload: true
                }
            }
        },
        jshint: {
            all: {
                src: ['gruntfile.js', 'server.js', 'server/**/*.js', 'public/js/**', 'test/**/*.js', '!test/coverage/**/*.js'],
                options: {
                    jshintrc: true
                }
            }
        },
        uglify: {
            options: {
                mangle: false
            },
            production: {
                files: '<%= assets.js %>'
            }
        },
        csslint: {
            options: {
                csslintrc: '.csslintrc'
            },
            all: {
                src: ['public/css/**/*.css']
            }
        },
        cssmin: {
            combine: {
                files: '<%= assets.css %>'
            }
        },
        nodemon: {
            dev: {
                script: 'server.js',
                options: {
                    args: [],
                    ignore: ['public/**'],
                    ext: 'js,html',
                    nodeArgs: ['--debug'],
                    delayTime: 1,
                    env: {
                        PORT: require('./server/config/config').port
                    },
                    cwd: __dirname
                }
            }
        },
        concurrent: {
            tasks: ['nodemon', 'watch'],
            options: {
                logConcurrentOutput: true
            }
        },
        mochaTest: {
            options: {
                reporter: 'spec',
                require: 'server.js'
            },
            src: ['test/mocha/**/*.js']
        },
        env: {
            test: {
                NODE_ENV: 'test'
            }
        },
        karma: {
            unit: {
                configFile: 'test/karma/karma.conf.js'
            }
        }
    });

    //Load NPM tasks
    require('load-grunt-tasks')(grunt);

    //Making grunt default to force in order not to break the project.
    grunt.option('force', true);

    //Default task(s).
    if (process.env.NODE_ENV === 'production') {
        grunt.registerTask('default', ['jshint', 'csslint', 'cssmin', 'uglify', 'concurrent']);
    } else {
        grunt.registerTask('default', ['jshint', 'csslint', 'concurrent']);
    }

    //Test task.
    grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit']);
};
<commit_msg>Fix gruntfile css live reload. Also add in Sass.<commit_after>'use strict';

module.exports = function(grunt) {
    require('time-grunt')(grunt);

    // Project Configuration
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        assets: grunt.file.readJSON('server/config/assets.json'),
        watch: {
            js: {
                files: ['gruntfile.js', 'server.js', 'server/**/*.js', 'public/js/**', 'test/**/*.js'],
                tasks: ['jshint'],
                options: {
                    livereload: true
                }
            },
            html: {
                files: ['public/views/**', 'server/views/**'],
                options: {
                    livereload: true
                }
            },
            css: {
                files: ['public/system/assets/css/**'],
                tasks: ['csslint'],
                options: {
                    livereload: true
                }
            },
            scss: {
                files: ['public/system/assets/scss/**'],
                tasks: ['sass:dev'],
                options: {
                    livereload: false
                }
            }
        },
        jshint: {
            all: {
                src: ['gruntfile.js', 'server.js', 'server/**/*.js', 'public/js/**', 'test/**/*.js', '!test/coverage/**/*.js'],
                options: {
                    jshintrc: true
                }
            }
        },
        uglify: {
            options: {
                mangle: false
            },
            production: {
                files: '<%= assets.js %>'
            }
        },
        csslint: {
            options: {
                csslintrc: '.csslintrc'
            },
            all: {
                src: ['public/css/**/*.css']
            }
        },
        cssmin: {
            combine: {
                files: '<%= assets.css %>'
            }
        },
        sass: {
            dist: {
                files: {
                    'public/system/assets/css/main.css': 'public/system/assets/scss/main.scss'
                }
            },
            dev: {
                options: {
                    sourceComments: 'map'
                },
                files: {
                    'public/system/assets/css/main.css': 'public/system/assets/scss/main.scss'
                }
            }
        },
        nodemon: {
            dev: {
                script: 'server.js',
                options: {
                    args: [],
                    ignore: ['public/**'],
                    ext: 'js,html',
                    nodeArgs: ['--debug'],
                    delayTime: 1,
                    env: {
                        PORT: require('./server/config/config').port
                    },
                    cwd: __dirname
                }
            }
        },
        concurrent: {
            tasks: ['nodemon', 'watch'],
            options: {
                logConcurrentOutput: true
            }
        },
        mochaTest: {
            options: {
                reporter: 'spec',
                require: 'server.js'
            },
            src: ['test/mocha/**/*.js']
        },
        env: {
            test: {
                NODE_ENV: 'test'
            }
        },
        karma: {
            unit: {
                configFile: 'test/karma/karma.conf.js'
            }
        }
    });

    //Load NPM tasks
    require('load-grunt-tasks')(grunt);

    //Making grunt default to force in order not to break the project.
    grunt.option('force', true);

    //Default task(s).
    if (process.env.NODE_ENV === 'production') {
        grunt.registerTask('default', ['jshint', 'sass', 'csslint', 'cssmin', 'uglify', 'concurrent']);
    } else {
        grunt.registerTask('default', ['jshint', 'sass', 'csslint', 'concurrent']);
    }

    //Test task.
    grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit']);
};
<|endoftext|>


<commit_before>fdescribe('Unit: JFrogSubRouter Service', function () {

    let JFrogSubRouter;
    let subRouter;
    let $rootScope;
    let $scope;
    let $state;
    let $timeout;
    let $location;

    let eventHandlers = {};

    function setupSubRouter() {
        $state.current.url = '/base/path/{subPath:JFrogSubRouterPath}';
        $state.current.name = 'karma';
        $location.path('/base/path');
        subRouter = JFrogSubRouter.createLocalRouter({
            parentScope: $scope,
            urlStructure: '/:pathParam1/:pathParam2/:pathParam3/?:searchParam1&:searchParam2',
            hotSyncUrl: true,
            states: [
                {
                    name: 'state1',
                    params: {mandatory: ['pathParam1'], nullify: ['pathParam2', 'pathParam3']}
                },
                {
                    name: 'state2',
                    params: {mandatory: ['pathParam1', 'pathParam2'], nullify: ['pathParam3']}
                },
                {
                    name: 'state3',
                    params: {mandatory: ['pathParam1', 'pathParam2', 'pathParam3']}
                }
            ],
            onInit: () => {
                if (eventHandlers.onInit) eventHandlers.onInit();
            },
            onChangeFromUrl: (oldParams, newParams) => {
                if (eventHandlers.onChangeFromUrl) eventHandlers.onChangeFromUrl(oldParams, newParams);
            },
            onStateChange: (oldState, newState) => {
                if (eventHandlers.onStateChange) eventHandlers.onStateChange(oldState, newState);
            },
            onInvalidState: (oldState, params) => {
                if (eventHandlers.onInvalidState) eventHandlers.onInvalidState(oldState, params);
            }
        })
    }

    function tick(func) {
        return new Promise((res, rej) => {
            setTimeout(() => {
                if (func) func();
                $scope.$apply();
                res();
            })
        })
    }

    function checkEventHandler(eventHandler, action, check) {
        return new Promise((res, rej) => {
            eventHandlers[eventHandler] = (...params) => {
                check(...params);
                res();
            }

            tick(() => {
                action();
            })
        })
    }

    function checkSecondaryEventHandler(api, eventHandler, action, check) {
        return new Promise((res, rej) => {
            api.on(eventHandler, (...params) => {
                check(...params);
                res();
            })

            tick(() => {
                action();
            })
        })
    }

    beforeEach(m('jfrog.ui.essentials'));

    beforeEach(inject((_JFrogSubRouter_, _$rootScope_, _$state_, _$timeout_, _$location_) => {
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        $state = _$state_;
        $timeout = _$timeout_;
        $location = _$location_;
        JFrogSubRouter = _JFrogSubRouter_;
    }));

    beforeEach(() => {
        eventHandlers = {};
    });

    it ('should initialize sub router, fire onInit event, and be in invalid state', (done) => {
        eventHandlers.onInit = () => {
            expect(subRouter.state).toEqual(null);
            done();
        }
        setupSubRouter();
        $scope.$apply();
    })

    it ('should switch states and update url when changing params', (done) => {
        eventHandlers.onInit = () => {
            expect(subRouter.state).toEqual(null);
            expect($location.path()).toEqual('/base/path');
            subRouter.params.pathParam1 = 'momo';
            expect(subRouter.state).toEqual('state1');

            tick(() => {
                expect($location.path()).toEqual('/base/path/momo/');
                subRouter.params.pathParam2 = 'jojo';
                expect(subRouter.state).toEqual('state2');
            })
            .then(() => tick(() => {
                expect($location.path()).toEqual('/base/path/momo/jojo/');
                subRouter.params.pathParam3 = 'lala';
                expect(subRouter.state).toEqual('state3');
            }))
            .then(() => tick(() => {
                expect($location.path()).toEqual('/base/path/momo/jojo/lala/');
                subRouter.params.searchParam1 = 'quakwa';
                expect(subRouter.state).toEqual('state3');
            }))
            .then(() => tick(() => {
                expect($location.path()).toEqual('/base/path/momo/jojo/lala/');
                expect($location.search().searchParam1).toEqual('quakwa');
                subRouter.params.searchParam2 = 'blublu';
            }))
            .then(() => tick(() => {
                expect($location.search().searchParam2).toEqual('blublu');
                done();
            }))
        }
        setupSubRouter();
        $scope.$apply();
    })

    it ('should change params and switch states when changing changing url', (done) => {
        eventHandlers.onInit = () => {
            expect(subRouter.state).toEqual(null);
            expect($location.path()).toEqual('/base/path');

            tick(() => {
                $location.path('/base/path/momo');
                $scope.$apply();
                expect(subRouter.params.pathParam1).toEqual('momo');
                expect(subRouter.state).toEqual('state1');
            })
            .then(() => tick(() => {
                $location.path('/base/path/momo/yaya');
                $scope.$apply();
                expect(subRouter.params.pathParam2).toEqual('yaya');
                expect(subRouter.state).toEqual('state2');
            }))
            .then(() => tick(() => {
                $location.path('/base/path/momo/yaya/kaja');
                $scope.$apply();
                expect(subRouter.params.pathParam3).toEqual('kaja');
                expect(subRouter.state).toEqual('state3');
            }))
            .then(() => tick(() => {
                $location.search({searchParam1: 456, searchParam2: 99776, shouldBeRemoved: 'blabla'});
                $scope.$apply();
                expect(subRouter.params.searchParam1).toEqual(456);
                expect(subRouter.params.searchParam2).toEqual(99776);
                expect(subRouter.params.shouldBeRemoved).toBeUndefined();
                done();
            }))
        }
        setupSubRouter();
        $scope.$apply();
    })

    it ('should fire state change events, both when changing params, and when changing url', (done) => {
        eventHandlers.onInit = () => {
            checkEventHandler('onStateChange', () => {
                subRouter.params.pathParam1 = 'momo';
            }, (oldState, newState) => {
                expect(oldState).toEqual(null);
                expect(newState).toEqual('state1');
                expect(subRouter.state).toEqual('state1');
            })
                .then(() => checkEventHandler('onStateChange', () =>{
                    subRouter.params.pathParam2 = 'lupo';
                }, (oldState, newState) => {
                    expect(oldState).toEqual('state1');
                    expect(newState).toEqual('state2');
                    expect(subRouter.state).toEqual('state2');
                }))
                .then(() => checkEventHandler('onStateChange', () =>{
                    subRouter.params.pathParam3 = 'rafa';
                }, (oldState, newState) => {
                    expect(oldState).toEqual('state2');
                    expect(newState).toEqual('state3');
                    expect(subRouter.state).toEqual('state3');
                }))
                .then(() => checkEventHandler('onStateChange', () =>{
                    $location.path('/base/path/momo/yaya');
                }, (oldState, newState) => {
                    expect(oldState).toEqual('state3');
                    expect(newState).toEqual('state2');
                    expect(subRouter.state).toEqual('state2');
                }))
                .then(() => checkEventHandler('onStateChange', () =>{
                    $location.path('/base/path/lasso');
                }, (oldState, newState) => {
                    expect(oldState).toEqual('state2');
                    expect(newState).toEqual('state1');
                    expect(subRouter.state).toEqual('state1');
                })
                .then(() => {
                    done();
                }))
        }
        setupSubRouter();
        $scope.$apply();
    });

    it ('should fire change from url events', (done) => {
        eventHandlers.onInit = () => {
            checkEventHandler('onChangeFromUrl', () => {
                $location.path('/base/path/momo/yaya');
            }, (oldParams, newParams) => {
                expect(_.isEqual(oldParams, {pathParam1: null, pathParam2: null, pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                expect(_.isEqual(newParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                expect(subRouter.state).toEqual('state2');
            })
                .then(() => checkEventHandler('onChangeFromUrl', () => {
                    $location.path('/base/path/momo/yaya/dudu');
                }, (oldParams, newParams) => {
                    expect(_.isEqual(oldParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                    expect(_.isEqual(newParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: 'dudu', searchParam1: null, searchParam2: null})).toBeTrue();
                    expect(subRouter.state).toEqual('state3');
                }))
                .then(() => checkEventHandler('onChangeFromUrl', () => {
                    $location.search({searchParam1: 'fifa', searchParam2: 'fiba'});
                }, (oldParams, newParams) => {
                    expect(_.isEqual(oldParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: 'dudu', searchParam1: null, searchParam2: null})).toBeTrue();
                    expect(_.isEqual(newParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: 'dudu', searchParam1: 'fifa', searchParam2: 'fiba'})).toBeTrue();
                    expect(subRouter.state).toEqual('state3');
                }))
                .then(() => {
                    done();
                })
        }
        setupSubRouter();
        $scope.$apply();
    });

    it ('should fire invalid state event', (done) => {
        let resetState1 = () => checkEventHandler('onStateChange', () => {
            subRouter.params.pathParam1 = 'momo';
        }, (oldState, newState) => {
            expect(oldState).toEqual(null);
            expect(newState).toEqual('state1');
            expect(subRouter.state).toEqual('state1');
            delete eventHandlers.onStateChange;
        })

        eventHandlers.onInit = () => {
            resetState1()
                .then(() => checkEventHandler('onInvalidState', () =>{
                    subRouter.params.pathParam1 = null
                }, (oldState, params) => {
                    expect(oldState).toEqual('state1');
                    expect(_.isEqual(params, {pathParam1: null, pathParam2: null, pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                }))
                .then(() => resetState1())
                .then(() => checkEventHandler('onInvalidState', () =>{
                    subRouter.params.pathParam1 = null;
                    subRouter.params.pathParam2 = 'momo';
                }, (oldState, params) => {
                    expect(oldState).toEqual('state1');
                    expect(_.isEqual(params, {pathParam1: null, pathParam2: 'momo', pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                }))
                .then(() => resetState1())
                .then(() => checkEventHandler('onInvalidState', () =>{
                    $location.path('/base/path/');
                }, (oldState, params) => {
                    expect(oldState).toEqual('state1');
                    expect(_.isEqual(params, {pathParam1: null, pathParam2: null, pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                }))
                .then(() => resetState1())
                .then(() => checkEventHandler('onInvalidState', () =>{
                    $location.path('/base/path/rojo/jojo');
                    setTimeout(()=>{
                        subRouter.params.pathParam1 = null;
                        $scope.$apply();
                    })
                }, (oldState, params) => {
                    expect(oldState).toEqual('state2');
                    expect(_.isEqual(params, {pathParam1: null, pathParam2: 'jojo', pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                }))
                .then(() => {
                    done();
                })
        }
        setupSubRouter();
        $scope.$apply();
    });

    it ('should fire secondary registered event listeners', (done) => {
        eventHandlers.onInit = () => {
            let activeRouter = JFrogSubRouter.getActiveRouter();
            checkSecondaryEventHandler(activeRouter, 'state.change', () => {
                $location.path('/yaya')
            }, (oldState, newState) => {
                expect(oldState).toEqual(null);
                expect(newState).toEqual('state1');
            })
                .then(() => checkSecondaryEventHandler(activeRouter, 'params.change', () => {
                    activeRouter.off('state.change');
                    $location.path('/yaya/yuki')
                }, (oldParams, newParams) => {
                    expect(oldParams.pathParam2).toEqual(null);
                    expect(newParams.pathParam2).toEqual('yuki');
                }))
                .then(() => {
                    done();
                })

        }
        setupSubRouter();
        $scope.$apply();
    });

    it ('should clean when parent scope is destroyed', () => {
        setupSubRouter();
        $scope.$apply();

        expect(JFrogSubRouter.$config).toBeObject();
        $scope.$destroy();
        expect(JFrogSubRouter.$config).toBeNull();
    });
});<commit_msg>karma: Remove fdescribe<commit_after>describe('Unit: JFrogSubRouter Service', function () {

    let JFrogSubRouter;
    let subRouter;
    let $rootScope;
    let $scope;
    let $state;
    let $timeout;
    let $location;

    let eventHandlers = {};

    function setupSubRouter() {
        $state.current.url = '/base/path/{subPath:JFrogSubRouterPath}';
        $state.current.name = 'karma';
        $location.path('/base/path');
        subRouter = JFrogSubRouter.createLocalRouter({
            parentScope: $scope,
            urlStructure: '/:pathParam1/:pathParam2/:pathParam3/?:searchParam1&:searchParam2',
            hotSyncUrl: true,
            states: [
                {
                    name: 'state1',
                    params: {mandatory: ['pathParam1'], nullify: ['pathParam2', 'pathParam3']}
                },
                {
                    name: 'state2',
                    params: {mandatory: ['pathParam1', 'pathParam2'], nullify: ['pathParam3']}
                },
                {
                    name: 'state3',
                    params: {mandatory: ['pathParam1', 'pathParam2', 'pathParam3']}
                }
            ],
            onInit: () => {
                if (eventHandlers.onInit) eventHandlers.onInit();
            },
            onChangeFromUrl: (oldParams, newParams) => {
                if (eventHandlers.onChangeFromUrl) eventHandlers.onChangeFromUrl(oldParams, newParams);
            },
            onStateChange: (oldState, newState) => {
                if (eventHandlers.onStateChange) eventHandlers.onStateChange(oldState, newState);
            },
            onInvalidState: (oldState, params) => {
                if (eventHandlers.onInvalidState) eventHandlers.onInvalidState(oldState, params);
            }
        })
    }

    function tick(func) {
        return new Promise((res, rej) => {
            setTimeout(() => {
                if (func) func();
                $scope.$apply();
                res();
            })
        })
    }

    function checkEventHandler(eventHandler, action, check) {
        return new Promise((res, rej) => {
            eventHandlers[eventHandler] = (...params) => {
                check(...params);
                res();
            }

            tick(() => {
                action();
            })
        })
    }

    function checkSecondaryEventHandler(api, eventHandler, action, check) {
        return new Promise((res, rej) => {
            api.on(eventHandler, (...params) => {
                check(...params);
                res();
            })

            tick(() => {
                action();
            })
        })
    }

    beforeEach(m('jfrog.ui.essentials'));

    beforeEach(inject((_JFrogSubRouter_, _$rootScope_, _$state_, _$timeout_, _$location_) => {
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        $state = _$state_;
        $timeout = _$timeout_;
        $location = _$location_;
        JFrogSubRouter = _JFrogSubRouter_;
    }));

    beforeEach(() => {
        eventHandlers = {};
    });

    it ('should initialize sub router, fire onInit event, and be in invalid state', (done) => {
        eventHandlers.onInit = () => {
            expect(subRouter.state).toEqual(null);
            done();
        }
        setupSubRouter();
        $scope.$apply();
    })

    it ('should switch states and update url when changing params', (done) => {
        eventHandlers.onInit = () => {
            expect(subRouter.state).toEqual(null);
            expect($location.path()).toEqual('/base/path');
            subRouter.params.pathParam1 = 'momo';
            expect(subRouter.state).toEqual('state1');

            tick(() => {
                expect($location.path()).toEqual('/base/path/momo/');
                subRouter.params.pathParam2 = 'jojo';
                expect(subRouter.state).toEqual('state2');
            })
            .then(() => tick(() => {
                expect($location.path()).toEqual('/base/path/momo/jojo/');
                subRouter.params.pathParam3 = 'lala';
                expect(subRouter.state).toEqual('state3');
            }))
            .then(() => tick(() => {
                expect($location.path()).toEqual('/base/path/momo/jojo/lala/');
                subRouter.params.searchParam1 = 'quakwa';
                expect(subRouter.state).toEqual('state3');
            }))
            .then(() => tick(() => {
                expect($location.path()).toEqual('/base/path/momo/jojo/lala/');
                expect($location.search().searchParam1).toEqual('quakwa');
                subRouter.params.searchParam2 = 'blublu';
            }))
            .then(() => tick(() => {
                expect($location.search().searchParam2).toEqual('blublu');
                done();
            }))
        }
        setupSubRouter();
        $scope.$apply();
    })

    it ('should change params and switch states when changing changing url', (done) => {
        eventHandlers.onInit = () => {
            expect(subRouter.state).toEqual(null);
            expect($location.path()).toEqual('/base/path');

            tick(() => {
                $location.path('/base/path/momo');
                $scope.$apply();
                expect(subRouter.params.pathParam1).toEqual('momo');
                expect(subRouter.state).toEqual('state1');
            })
            .then(() => tick(() => {
                $location.path('/base/path/momo/yaya');
                $scope.$apply();
                expect(subRouter.params.pathParam2).toEqual('yaya');
                expect(subRouter.state).toEqual('state2');
            }))
            .then(() => tick(() => {
                $location.path('/base/path/momo/yaya/kaja');
                $scope.$apply();
                expect(subRouter.params.pathParam3).toEqual('kaja');
                expect(subRouter.state).toEqual('state3');
            }))
            .then(() => tick(() => {
                $location.search({searchParam1: 456, searchParam2: 99776, shouldBeRemoved: 'blabla'});
                $scope.$apply();
                expect(subRouter.params.searchParam1).toEqual(456);
                expect(subRouter.params.searchParam2).toEqual(99776);
                expect(subRouter.params.shouldBeRemoved).toBeUndefined();
                done();
            }))
        }
        setupSubRouter();
        $scope.$apply();
    })

    it ('should fire state change events, both when changing params, and when changing url', (done) => {
        eventHandlers.onInit = () => {
            checkEventHandler('onStateChange', () => {
                subRouter.params.pathParam1 = 'momo';
            }, (oldState, newState) => {
                expect(oldState).toEqual(null);
                expect(newState).toEqual('state1');
                expect(subRouter.state).toEqual('state1');
            })
                .then(() => checkEventHandler('onStateChange', () =>{
                    subRouter.params.pathParam2 = 'lupo';
                }, (oldState, newState) => {
                    expect(oldState).toEqual('state1');
                    expect(newState).toEqual('state2');
                    expect(subRouter.state).toEqual('state2');
                }))
                .then(() => checkEventHandler('onStateChange', () =>{
                    subRouter.params.pathParam3 = 'rafa';
                }, (oldState, newState) => {
                    expect(oldState).toEqual('state2');
                    expect(newState).toEqual('state3');
                    expect(subRouter.state).toEqual('state3');
                }))
                .then(() => checkEventHandler('onStateChange', () =>{
                    $location.path('/base/path/momo/yaya');
                }, (oldState, newState) => {
                    expect(oldState).toEqual('state3');
                    expect(newState).toEqual('state2');
                    expect(subRouter.state).toEqual('state2');
                }))
                .then(() => checkEventHandler('onStateChange', () =>{
                    $location.path('/base/path/lasso');
                }, (oldState, newState) => {
                    expect(oldState).toEqual('state2');
                    expect(newState).toEqual('state1');
                    expect(subRouter.state).toEqual('state1');
                })
                .then(() => {
                    done();
                }))
        }
        setupSubRouter();
        $scope.$apply();
    });

    it ('should fire change from url events', (done) => {
        eventHandlers.onInit = () => {
            checkEventHandler('onChangeFromUrl', () => {
                $location.path('/base/path/momo/yaya');
            }, (oldParams, newParams) => {
                expect(_.isEqual(oldParams, {pathParam1: null, pathParam2: null, pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                expect(_.isEqual(newParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                expect(subRouter.state).toEqual('state2');
            })
                .then(() => checkEventHandler('onChangeFromUrl', () => {
                    $location.path('/base/path/momo/yaya/dudu');
                }, (oldParams, newParams) => {
                    expect(_.isEqual(oldParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                    expect(_.isEqual(newParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: 'dudu', searchParam1: null, searchParam2: null})).toBeTrue();
                    expect(subRouter.state).toEqual('state3');
                }))
                .then(() => checkEventHandler('onChangeFromUrl', () => {
                    $location.search({searchParam1: 'fifa', searchParam2: 'fiba'});
                }, (oldParams, newParams) => {
                    expect(_.isEqual(oldParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: 'dudu', searchParam1: null, searchParam2: null})).toBeTrue();
                    expect(_.isEqual(newParams, {pathParam1: 'momo', pathParam2: 'yaya', pathParam3: 'dudu', searchParam1: 'fifa', searchParam2: 'fiba'})).toBeTrue();
                    expect(subRouter.state).toEqual('state3');
                }))
                .then(() => {
                    done();
                })
        }
        setupSubRouter();
        $scope.$apply();
    });

    it ('should fire invalid state event', (done) => {
        let resetState1 = () => checkEventHandler('onStateChange', () => {
            subRouter.params.pathParam1 = 'momo';
        }, (oldState, newState) => {
            expect(oldState).toEqual(null);
            expect(newState).toEqual('state1');
            expect(subRouter.state).toEqual('state1');
            delete eventHandlers.onStateChange;
        })

        eventHandlers.onInit = () => {
            resetState1()
                .then(() => checkEventHandler('onInvalidState', () =>{
                    subRouter.params.pathParam1 = null
                }, (oldState, params) => {
                    expect(oldState).toEqual('state1');
                    expect(_.isEqual(params, {pathParam1: null, pathParam2: null, pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                }))
                .then(() => resetState1())
                .then(() => checkEventHandler('onInvalidState', () =>{
                    subRouter.params.pathParam1 = null;
                    subRouter.params.pathParam2 = 'momo';
                }, (oldState, params) => {
                    expect(oldState).toEqual('state1');
                    expect(_.isEqual(params, {pathParam1: null, pathParam2: 'momo', pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                }))
                .then(() => resetState1())
                .then(() => checkEventHandler('onInvalidState', () =>{
                    $location.path('/base/path/');
                }, (oldState, params) => {
                    expect(oldState).toEqual('state1');
                    expect(_.isEqual(params, {pathParam1: null, pathParam2: null, pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                }))
                .then(() => resetState1())
                .then(() => checkEventHandler('onInvalidState', () =>{
                    $location.path('/base/path/rojo/jojo');
                    setTimeout(()=>{
                        subRouter.params.pathParam1 = null;
                        $scope.$apply();
                    })
                }, (oldState, params) => {
                    expect(oldState).toEqual('state2');
                    expect(_.isEqual(params, {pathParam1: null, pathParam2: 'jojo', pathParam3: null, searchParam1: null, searchParam2: null})).toBeTrue();
                }))
                .then(() => {
                    done();
                })
        }
        setupSubRouter();
        $scope.$apply();
    });

    it ('should fire secondary registered event listeners', (done) => {
        eventHandlers.onInit = () => {
            let activeRouter = JFrogSubRouter.getActiveRouter();
            checkSecondaryEventHandler(activeRouter, 'state.change', () => {
                $location.path('/yaya')
            }, (oldState, newState) => {
                expect(oldState).toEqual(null);
                expect(newState).toEqual('state1');
            })
                .then(() => checkSecondaryEventHandler(activeRouter, 'params.change', () => {
                    activeRouter.off('state.change');
                    $location.path('/yaya/yuki')
                }, (oldParams, newParams) => {
                    expect(oldParams.pathParam2).toEqual(null);
                    expect(newParams.pathParam2).toEqual('yuki');
                }))
                .then(() => {
                    done();
                })

        }
        setupSubRouter();
        $scope.$apply();
    });

    it ('should clean when parent scope is destroyed', () => {
        setupSubRouter();
        $scope.$apply();

        expect(JFrogSubRouter.$config).toBeObject();
        $scope.$destroy();
        expect(JFrogSubRouter.$config).toBeNull();
    });
});<|endoftext|>


<commit_before>import {Components, getComponent} from './components';

export const Routes = {}; // will be populated on startup (see vulcan:routing)
export const RoutesTable = {}; // storage for infos about routes themselves

/*
 A route is defined in the list like:
 RoutesTable.foobar = {
 name: 'foobar',
 path: '/xyz',
 component: getComponent('FooBar')
 componentName: 'FooBar' // optional
 }

 if there there is value for parentRouteName it will look for the route and add the new route as a child of it
 */
export const addRoute = (routeOrRouteArray, parentRouteName) => {

  // be sure to have an array of routes to manipulate
  const addedRoutes = Array.isArray(routeOrRouteArray) ? routeOrRouteArray : [routeOrRouteArray];

  // if there is a value for parentRouteName you are adding this route as new child
  if (parentRouteName) {

    addAsChildRoute(parentRouteName, addedRoutes);

  } else {

    // modify the routes table with the new routes
    addedRoutes.map(({name, path, ...properties}) => {

      // check if there is already a route registered to this path
      // note: destructure in order to get the first item of the array, as _.filter returns an array
      const [routeWithSamePath] = _.filter(RoutesTable, route => route.path === path);

      if (routeWithSamePath) {
        // delete the route registered with same path
        delete RoutesTable[routeWithSamePath.name];
      }

      // register the new route
      RoutesTable[name] = {
        name,
        path,
        ...properties
      };

    });
  }
};

/**
 A route is defined in the list like: (same as above)
 RoutesTable.foobar = {
 name: 'foobar',
 path: '/xyz',
 component: getComponent('FooBar')
 componentName: 'FooBar' // optional
 }

 NOTE: This is implemented on single level deep ONLY for now
 **/

export const addAsChildRoute = (parentRouteName, addedRoutes) => {

  // if the parentRouteName does not exist, error
  if (!RoutesTable[parentRouteName]) {
    throw new Error(`Route ${parentRouteName} doesn't exist`)
  }

  // modify the routes table with the new routes
  addedRoutes.map(({name, path, ...properties}) => {

    // get the current child routes for this Route
    const childRoutes = RoutesTable[parentRouteName]['childRoutes'] || [];

    // check if there is already a route registered to this path
    const [routeWithSamePath] = _.filter(childRoutes, route => route.path === path);

    if (routeWithSamePath) {
      // delete the route registered with same path
      delete childRoutes[routeWithSamePath.name];
    }

    // append to the child routes the new route
    childRoutes.push({
      name,
      path,
      ...properties
    });

    // register the new child route (overwriting the current which is fine)
    RoutesTable[parentRouteName]['childRoutes'] = childRoutes;

  });
};

export const getRoute = name => {
  const routeDef = RoutesTable[name];

  // components should be loaded by now (populateComponentsApp function), we can grab the component in the lookup table and assign it to the route
  if (!routeDef.component && routeDef.componentName) {
    routeDef.component = getComponent(routeDef.componentName);
  }

  return routeDef;
}

/**
 * Populate the lookup table for routes to be callable
 * ℹ Called once on app startup
 **/
export const populateRoutesApp = () => {
  // loop over each component in the list
  Object.keys(RoutesTable).map(name => {

    // populate an entry in the lookup table
    Routes[name] = getRoute(name);

    // uncomment for debug
    // console.log('init route:', name);
  });
}

<commit_msg>add extendRoute<commit_after>import {Components, getComponent} from './components';

export const Routes = {}; // will be populated on startup (see vulcan:routing)
export const RoutesTable = {}; // storage for infos about routes themselves

/*
 A route is defined in the list like:
 RoutesTable.foobar = {
 name: 'foobar',
 path: '/xyz',
 component: getComponent('FooBar')
 componentName: 'FooBar' // optional
 }

 if there there is value for parentRouteName it will look for the route and add the new route as a child of it
 */
export const addRoute = (routeOrRouteArray, parentRouteName) => {

  // be sure to have an array of routes to manipulate
  const addedRoutes = Array.isArray(routeOrRouteArray) ? routeOrRouteArray : [routeOrRouteArray];

  // if there is a value for parentRouteName you are adding this route as new child
  if (parentRouteName) {

    addAsChildRoute(parentRouteName, addedRoutes);

  } else {

    // modify the routes table with the new routes
    addedRoutes.map(({name, path, ...properties}) => {

      // check if there is already a route registered to this path
      const routeWithSamePath = _.findWhere(RoutesTable, { path });

      if (routeWithSamePath) {
        // delete the route registered with same path
        delete RoutesTable[routeWithSamePath.name];
      }

      // register the new route
      RoutesTable[name] = {
        name,
        path,
        ...properties
      };

    });
  }
};

export const extendRoute = (routeName, routeProps) => {

  const route = _.findWhere(RoutesTable, {name: routeName});

  RoutesTable[route.name] = {
    ...route,
    ...routeProps
  };
};

/**
 A route is defined in the list like: (same as above)
 RoutesTable.foobar = {
 name: 'foobar',
 path: '/xyz',
 component: getComponent('FooBar')
 componentName: 'FooBar' // optional
 }

 NOTE: This is implemented on single level deep ONLY for now
 **/

export const addAsChildRoute = (parentRouteName, addedRoutes) => {

  // if the parentRouteName does not exist, error
  if (!RoutesTable[parentRouteName]) {
    throw new Error(`Route ${parentRouteName} doesn't exist`)
  }

  // modify the routes table with the new routes
  addedRoutes.map(({name, path, ...properties}) => {

    // get the current child routes for this Route
    const childRoutes = RoutesTable[parentRouteName]['childRoutes'] || [];

    // check if there is already a route registered to this path
    const [routeWithSamePath] = _.filter(childRoutes, route => route.path === path);

    if (routeWithSamePath) {
      // delete the route registered with same path
      delete childRoutes[routeWithSamePath.name];
    }

    // append to the child routes the new route
    childRoutes.push({
      name,
      path,
      ...properties
    });

    // register the new child route (overwriting the current which is fine)
    RoutesTable[parentRouteName]['childRoutes'] = childRoutes;

  });
};

export const getRoute = name => {
  const routeDef = RoutesTable[name];

  // components should be loaded by now (populateComponentsApp function), we can grab the component in the lookup table and assign it to the route
  if (!routeDef.component && routeDef.componentName) {
    routeDef.component = getComponent(routeDef.componentName);
  }

  return routeDef;
}

/**
 * Populate the lookup table for routes to be callable
 * ℹ Called once on app startup
 **/
export const populateRoutesApp = () => {
  // loop over each component in the list
  Object.keys(RoutesTable).map(name => {

    // populate an entry in the lookup table
    Routes[name] = getRoute(name);

    // uncomment for debug
    // console.log('init route:', name);
  });
}

<|endoftext|>


<commit_before>var Scheduler = require('happenstance').Scheduler
var Timer = require('happenstance').Timer
var coalesce = require('extant')
var interrupt = require('interrupt').createInterrupter('destructible')

function Terminator (timeout, options) {
    options = coalesce(options, {})
    var _setImmediate = coalesce(options.setImmediate, setImmediate)
    this._timeout = timeout
    this.scheduler = coalesce(new Scheduler)
    this.scheduler.events.pump(new Timer(this.scheduler), 'push')
    this.scheduler.events.pump(function (envelope) {
        if (envelope.method != 'event') {
            return
        }
        _setImmediate(function () {
            var body = envelope.body.body.body
            throw interrupt('hung', {
                destructor: body.destructor,
                destructible: body.destructible,
                waiting: body.waiting
            }, {
                cause: body.errors[0]
            })
        })
    })
}

Terminator.prototype.push = function (envelope) {
    switch (envelope.method) {
    case 'destroyed':
    case 'popped':
        if (!envelope.body.destroyed) {
            break
        }
        if (envelope.body.waiting.length == 0) {
            this.scheduler.unschedule(envelope.from)
        } else {
            this.scheduler.schedule(Date.now() + this._timeout, envelope.from, {
                module: 'destructible',
                method: 'timeout',
                body: envelope
            })
        }
        break
    }
}

module.exports = Terminator
<commit_msg>More docco for preamble.<commit_after>// Timer driven event queue.
var Scheduler = require('happenstance').Scheduler
var Timer = require('happenstance').Timer

// Return the first not null-like value.
var coalesce = require('extant')

// Exceptions that you can catch by type.
var interrupt = require('interrupt').createInterrupter('destructible')

function Terminator (timeout, options) {
    options = coalesce(options, {})
    var _setImmediate = coalesce(options.setImmediate, setImmediate)
    this._timeout = timeout
    this.scheduler = coalesce(new Scheduler)
    this.scheduler.events.pump(new Timer(this.scheduler), 'push')
    this.scheduler.events.pump(function (envelope) {
        if (envelope.method != 'event') {
            return
        }
        _setImmediate(function () {
            var body = envelope.body.body.body
            throw interrupt('hung', {
                destructor: body.destructor,
                destructible: body.destructible,
                waiting: body.waiting
            }, {
                cause: body.errors[0]
            })
        })
    })
}

Terminator.prototype.push = function (envelope) {
    switch (envelope.method) {
    case 'destroyed':
    case 'popped':
        if (!envelope.body.destroyed) {
            break
        }
        if (envelope.body.waiting.length == 0) {
            this.scheduler.unschedule(envelope.from)
        } else {
            this.scheduler.schedule(Date.now() + this._timeout, envelope.from, {
                module: 'destructible',
                method: 'timeout',
                body: envelope
            })
        }
        break
    }
}

module.exports = Terminator
<|endoftext|>


<commit_before>var express = require('express'),
    router = express.Router(),
    isWithoutReplacement = true,
    conf = require('../conf').preloadCandidates,
    _ = require('lodash'),
    fs = require('fs'),
    io = require('../lib/io');

var candidates = _.keys(conf);
var dict = conf;

router.post("/addCandidate", function(req, res) {
    var val = req.param('candidate');
    if (val && val !== "") {
        candidates.push(val);
        boardcastCandidates();
    }
    res.end();
});

router.post('/removeCandidate', function(req, res) {
    var val = req.param('candidate');
    candidates = _.without(candidates, val);
    boardcastCandidates();
    res.end();
});

router.post('/clearCandidates', function(req, res) {
    candidates = [];
    boardcastCandidates();
    res.end();
});

router.post('/setWithReplacement', function(req, res) {
    isWithoutReplacement = req.param('isWithoutReplacement') === "true";
    io.emitIsWithoutReplacement(isWithoutReplacement);
    res.end();
});

router.post('/rand', function(req, res) {
    var maxDistance = 50;
    var minDistance = 30;
    var randomNumber = _.random(candidates.length)-1,
        poorMan = candidates[randomNumber],
        distance = _.random(minDistance, maxDistance);
    console.log('Randomizing among items of: ' + candidates.length);
    io.emitRandResult({poorMan: poorMan, randomNumber: randomNumber, distance: distance});
    if (isWithoutReplacement) {
        candidates = _.without(candidates, poorMan);
        boardcastCandidates();
    }
    fs.appendFile('winners.txt', req.param('prize') + ': ' + poorMan + "\n", function (err) {
      if (err) throw err;
      console.log('Saved: ' + poorMan);
    });
    res.end();
});

io.on('connection', function(socket) {
    socket.emit('candidates', {candidates: candidates, dict: dict});
    socket.emit('isWithoutReplacement', isWithoutReplacement);
});

var boardcastCandidates = function() {
        io.emitCandidates({candidates: candidates, dict: dict});
    };

module.exports = router;
<commit_msg>shuffled candidate list beforehand<commit_after>var express = require('express'),
    router = express.Router(),
    isWithoutReplacement = true,
    conf = require('../conf').preloadCandidates,
    _ = require('lodash'),
    fs = require('fs'),
    io = require('../lib/io');

var candidates = _.shuffle(_.keys(conf));
var dict = conf;

router.post("/addCandidate", function(req, res) {
    var val = req.param('candidate');
    if (val && val !== "") {
        candidates.push(val);
        boardcastCandidates();
    }
    res.end();
});

router.post('/removeCandidate', function(req, res) {
    var val = req.param('candidate');
    candidates = _.without(candidates, val);
    boardcastCandidates();
    res.end();
});

router.post('/clearCandidates', function(req, res) {
    candidates = [];
    boardcastCandidates();
    res.end();
});

router.post('/setWithReplacement', function(req, res) {
    isWithoutReplacement = req.param('isWithoutReplacement') === "true";
    io.emitIsWithoutReplacement(isWithoutReplacement);
    res.end();
});

router.post('/rand', function(req, res) {
    var maxDistance = 50;
    var minDistance = 30;
    var randomNumber = _.random(candidates.length)-1,
        poorMan = candidates[randomNumber],
        distance = _.random(minDistance, maxDistance);
    console.log('Randomizing among items of: ' + candidates.length);
    io.emitRandResult({poorMan: poorMan, randomNumber: randomNumber, distance: distance});
    if (isWithoutReplacement) {
        candidates = _.without(candidates, poorMan);
        boardcastCandidates();
    }
    fs.appendFile('winners.txt', req.param('prize') + ': ' + poorMan + "\n", function (err) {
      if (err) throw err;
      console.log('Saved: ' + poorMan);
    });
    res.end();
});

io.on('connection', function(socket) {
    socket.emit('candidates', {candidates: candidates, dict: dict});
    socket.emit('isWithoutReplacement', isWithoutReplacement);
});

var boardcastCandidates = function() {
        io.emitCandidates({candidates: candidates, dict: dict});
    };

module.exports = router;
<|endoftext|>


<commit_before>import { get, set } from 'lodash';
import { getModule, replaceCodeMemory, templateReplaceMemory } from '../utils';

export default async function generateJsFrameworkAngularJs(params) {
  switch (params.framework) {
    case 'express':
      if (params.buildTool === 'none') {
        await replaceCodeMemory(params, 'server.js', 'ANGULARJS_ROUTES', await getModule('js-framework/angularjs/angularjs-routes-no-build.js'));
      } else {
        await replaceCodeMemory(params, 'server.js', 'ANGULARJS_ROUTES', await getModule('js-framework/angularjs/angularjs-routes.js'));
      }

      set(params.build, ['app', 'app.js'], await getModule('js-framework/angularjs/app.js'));
      set(params.build, ['app', 'controllers', 'contact.js'], await getModule('js-framework/angularjs/controllers/contact.js'));
      set(params.build, ['app', 'controllers', 'forgot.js'], await getModule('js-framework/angularjs/controllers/forgot.js'));
      set(params.build, ['app', 'controllers', 'header.js'], await getModule('js-framework/angularjs/controllers/header.js'));
      set(params.build, ['app', 'controllers', 'login.js'], await getModule('js-framework/angularjs/controllers/login.js'));
      set(params.build, ['app', 'controllers', 'profile.js'], await getModule('js-framework/angularjs/controllers/profile.js'));
      set(params.build, ['app', 'controllers', 'reset.js'], await getModule('js-framework/angularjs/controllers/reset.js'));
      set(params.build, ['app', 'controllers', 'signup.js'], await getModule('js-framework/angularjs/controllers/signup.js'));

      set(params.build, ['app', 'services', 'account.js'], await getModule('js-framework/angularjs/services/account.js'));
      set(params.build, ['app', 'services', 'contact.js'], await getModule('js-framework/angularjs/services/contact.js'));

      set(params.build, ['public', 'js', 'lib', 'angular.js'], await getModule('js-framework/angularjs/lib/angular.js'));
      set(params.build, ['public', 'js', 'lib', 'angular-mocks.js'], await getModule('js-framework/angularjs/lib/angular-mocks.js'));
      set(params.build, ['public', 'js', 'lib', 'angular-route.js'], await getModule('js-framework/angularjs/lib/angular-route.js'));
      set(params.build, ['public', 'js', 'lib', 'satellizer.js'], await getModule('js-framework/angularjs/lib/satellizer.js'));

      // Move all third-party libs to "app/vendor"
      if (params.buildTool === 'gulp') {
        set(params.build, ['app', 'vendor'], get(params.build, ['public', 'js', 'lib']));
        set(params.build, ['public', 'js'], undefined);
      }

      set(params.build, ['app', 'partials', '404.html'], await getModule('js-framework/angularjs/partials/404.html'));
      set(params.build, ['app', 'partials', 'home.html'], await getModule(`js-framework/angularjs/partials/home-${params.cssFramework}.html`));
      set(params.build, ['app', 'partials', 'contact.html'], await getModule(`js-framework/angularjs/partials/contact-${params.cssFramework}.html`));
      set(params.build, ['app', 'partials', 'header.html'], await getModule(`js-framework/angularjs/partials/header-${params.cssFramework}.html`));
      set(params.build, ['app', 'partials', 'footer.html'], await getModule('js-framework/angularjs/partials/footer.html'));

      if (params.authentication.length) {
        set(params.build, ['app', 'partials', 'forgot.html'], await getModule(`js-framework/angularjs/partials/forgot-${params.cssFramework}.html`));
        set(params.build, ['app', 'partials', 'login.html'], await getModule(`js-framework/angularjs/partials/login-${params.cssFramework}.html`));
        set(params.build, ['app', 'partials', 'profile.html'], await getModule(`js-framework/angularjs/partials/profile-${params.cssFramework}.html`));
        set(params.build, ['app', 'partials', 'reset.html'], await getModule(`js-framework/angularjs/partials/reset-${params.cssFramework}.html`));
        set(params.build, ['app', 'partials', 'signup.html'], await getModule(`js-framework/angularjs/partials/signup-${params.cssFramework}.html`));

        templateReplaceMemory(params, 'app/app.js', {
          satellizer: params.authentication.length ? `, 'satellizer'` : null
        });

        const headerAuthIndent = { none: 2, bootstrap: 3, foundation: 2 };
        await replaceCodeMemory(params, 'app/partials/header.html', 'HEADER_AUTH', await getModule(`js-framework/angularjs/partials/header-auth-${params.cssFramework}.html`), {
          indentLevel: headerAuthIndent[params.cssFramework]
        });

        // Initialize Foundation JS components
        if (params.cssFramework === 'foundation') {
          await replaceCodeMemory(params, 'app/controllers/header.js', 'FOUNDATION_INIT', await getModule('css-framework/foundation/foundation-init.js'));
        }
      }
      break;
    case 'meteor':
      break;
    default:
  }
}
<commit_msg>correctly replaced satellizer template string<commit_after>import { get, set } from 'lodash';
import { getModule, replaceCodeMemory, templateReplaceMemory } from '../utils';

export default async function generateJsFrameworkAngularJs(params) {
  switch (params.framework) {
    case 'express':
      if (params.buildTool === 'none') {
        await replaceCodeMemory(params, 'server.js', 'ANGULARJS_ROUTES', await getModule('js-framework/angularjs/angularjs-routes-no-build.js'));
      } else {
        await replaceCodeMemory(params, 'server.js', 'ANGULARJS_ROUTES', await getModule('js-framework/angularjs/angularjs-routes.js'));
      }

      set(params.build, ['app', 'app.js'], await getModule('js-framework/angularjs/app.js'));
      set(params.build, ['app', 'controllers', 'contact.js'], await getModule('js-framework/angularjs/controllers/contact.js'));
      set(params.build, ['app', 'controllers', 'forgot.js'], await getModule('js-framework/angularjs/controllers/forgot.js'));
      set(params.build, ['app', 'controllers', 'header.js'], await getModule('js-framework/angularjs/controllers/header.js'));
      set(params.build, ['app', 'controllers', 'login.js'], await getModule('js-framework/angularjs/controllers/login.js'));
      set(params.build, ['app', 'controllers', 'profile.js'], await getModule('js-framework/angularjs/controllers/profile.js'));
      set(params.build, ['app', 'controllers', 'reset.js'], await getModule('js-framework/angularjs/controllers/reset.js'));
      set(params.build, ['app', 'controllers', 'signup.js'], await getModule('js-framework/angularjs/controllers/signup.js'));

      set(params.build, ['app', 'services', 'account.js'], await getModule('js-framework/angularjs/services/account.js'));
      set(params.build, ['app', 'services', 'contact.js'], await getModule('js-framework/angularjs/services/contact.js'));

      set(params.build, ['public', 'js', 'lib', 'angular.js'], await getModule('js-framework/angularjs/lib/angular.js'));
      set(params.build, ['public', 'js', 'lib', 'angular-mocks.js'], await getModule('js-framework/angularjs/lib/angular-mocks.js'));
      set(params.build, ['public', 'js', 'lib', 'angular-route.js'], await getModule('js-framework/angularjs/lib/angular-route.js'));
      set(params.build, ['public', 'js', 'lib', 'satellizer.js'], await getModule('js-framework/angularjs/lib/satellizer.js'));

      // Move all third-party libs to "app/vendor"
      if (params.buildTool === 'gulp') {
        set(params.build, ['app', 'vendor'], get(params.build, ['public', 'js', 'lib']));
        set(params.build, ['public', 'js'], undefined);
      }

      set(params.build, ['app', 'partials', '404.html'], await getModule('js-framework/angularjs/partials/404.html'));
      set(params.build, ['app', 'partials', 'home.html'], await getModule(`js-framework/angularjs/partials/home-${params.cssFramework}.html`));
      set(params.build, ['app', 'partials', 'contact.html'], await getModule(`js-framework/angularjs/partials/contact-${params.cssFramework}.html`));
      set(params.build, ['app', 'partials', 'header.html'], await getModule(`js-framework/angularjs/partials/header-${params.cssFramework}.html`));
      set(params.build, ['app', 'partials', 'footer.html'], await getModule('js-framework/angularjs/partials/footer.html'));

      if (params.authentication.length) {
        set(params.build, ['app', 'partials', 'forgot.html'], await getModule(`js-framework/angularjs/partials/forgot-${params.cssFramework}.html`));
        set(params.build, ['app', 'partials', 'login.html'], await getModule(`js-framework/angularjs/partials/login-${params.cssFramework}.html`));
        set(params.build, ['app', 'partials', 'profile.html'], await getModule(`js-framework/angularjs/partials/profile-${params.cssFramework}.html`));
        set(params.build, ['app', 'partials', 'reset.html'], await getModule(`js-framework/angularjs/partials/reset-${params.cssFramework}.html`));
        set(params.build, ['app', 'partials', 'signup.html'], await getModule(`js-framework/angularjs/partials/signup-${params.cssFramework}.html`));

        const headerAuthIndent = { none: 2, bootstrap: 3, foundation: 2 };
        await replaceCodeMemory(params, 'app/partials/header.html', 'HEADER_AUTH', await getModule(`js-framework/angularjs/partials/header-auth-${params.cssFramework}.html`), {
          indentLevel: headerAuthIndent[params.cssFramework]
        });

        // Initialize Foundation JS components
        if (params.cssFramework === 'foundation') {
          await replaceCodeMemory(params, 'app/controllers/header.js', 'FOUNDATION_INIT', await getModule('css-framework/foundation/foundation-init.js'));
        }
      }

      // Optionally add satellizer module dependency
      templateReplaceMemory(params, 'app/app.js', {
        satellizer: params.authentication.length ? `, 'satellizer'` : ''
      });
      break;
    case 'meteor':
      break;
    default:
  }
}
<|endoftext|>


<commit_before>module.exports = function(skill, info, bot, message, db) {
  var userData = message.text.match(/\<(.*?)\>/g);  //suss out any @mentions of users
  if (userData) {
    // if there is a user is mentioned initiate the challenge!
    var challenged = userData[0].replace(/[^\w\s]/gi, '');

    bot.api.users.info({user: challenged}, (error, response) => {
        bot.reply(message, ':rotating_light: <@' + response.user.name + '> you have been challenged to a game of ROCK:mountain: , PAPER:spiral_note_pad: , SCISSORS:scissors:! Prepare to defend your honor!');
    });
    bot.startPrivateConversation(message, privateConvo(bot, message));
  } else {
    //if no user challenged
    bot.reply(message, 'You didn\'t challenge anyone you chicken shit! :chicken: :poop:');
  }

function privateConvo(bot, message) {
  const { user, channel } = message;
  return (err, convo) => {
    if (err) throw err;
    var rnd = Math.floor(Math.random()* 65);
    var encouragementArray = [
    'I believe in you!:hugging_face:',
    'I\'m sure you\'ll do your best!:heart:',
    'you\'re already a winner in my book!:wink:',
    'nothing can stop you!:smirk_cat:',
    'you have the eye of the tiger:smirk_cat:',
    'you have the heart of a champion:trophy:',
    'your lucky numbers are ' + rnd + ', ' + rnd + ', ' + rnd + ', ' + rnd + ', ' + rnd + '. :four_leaf_clover:',
    'take no prisoners! :rage1:',
    'Rock! On second thought- Paper! No Wait! Scissors...actually IDK',
    'Paper! NO, Rock! No Wait! Scissors; I made things worse, sorry. :disappointed:',
    'shoot straight!:grin:',
    'trust the force.',
    'trust in your instincts.',
    'Paper is on a roll!',
    'Get it. GET IT!',
    'You got this.:raised_hands:',
    'like a boss.:man_in_business_suit_levitating: ',
    'Establish dominance!',
    'what is best in life- Crush your enemies. See them driven before you. Hear the lamentations of their women.',
    'Rock it, or paper it? or _scissor_ it??:flushed:',
    'Cut em with scissors!',
    'Steady like a rock!',
    'give no quarter, and expect none either!:crossed_swords: ',
    'no retreat, no surrender!:crossed_swords: ',
    'I\'m not friends with losers- so try not to lose, eh? :trollface:',
    'If you\'re not first you\'re last!:medal:',
    'if you lose, don\'t bother coming home. :trollface:',
    'nothing can conquer your indomitable spirit!:raised_hands:'
    ];
    var randomEncouragement = Math.floor(Math.random()* encouragementArray.length);
    convo.ask('Do you want to play `paper`, `rock`, or `scissors`? No matter what you choose just remember: ' + encouragementArray[randomEncouragement], [
      {
        pattern: 'paper|rock|scissors',
        callback(response, convo) {
          // since no further messages are queued after this,
          // the conversation will end naturally with status === 'completed'
          convo.next();
        },
      }, {
        default: true,
        callback(response, convo) {
          convo.repeat();
          convo.next();
        },
      },
    ], { key: 'rockPaperScissors' }); // store the results in a field called rockPaperScissors

    convo.on('end', (convo) => {
      if (convo.status === 'completed') {
        var userPlay = convo.extractResponse('rockPaperScissors');
	var rpsObj = db.getSync("rps");
          if (err) throw err;

          if (rpsObj.played === "") { //no one played yet. enter player move and note to channel
		console.log(rpsObj.played);
		  console.log('no one played');
		  rpsObj.played=message.user + '-' + userPlay;
		  var id = db.saveSync("rps", rpsObj);
		  bot.reply(message, message.user + ' played!');
          } else { //someone played. enter current player move and existing move to game engine. print results. update w-l records for players. and clear played entry
		console.log(rpsObj.played);
		console.log('someone played');
		var gameEngine = require('./Rock-Paper-Spock');
  		var instance = new gameEngine(gameEngine.DefaultRules);
		var player1 = rpsObj.played.split("-");
  		instance.addPlayer({id: player1[0], sign: player1[1]});
  		instance.addPlayer({id: message.user, sign: userPlay});
  		instance.play();
  		console.log(instance.winner);
		bot.reply(message, instance.winner.id + ' won!');

          }

      } else {
        // this happens if the conversation ended prematurely for some reason
        bot.reply(message, 'OK, nevermind!');
      }

	  });
 }
 };

};
<commit_msg>Update RockPaperScissors.js<commit_after>module.exports = function(skill, info, bot, message, db) {
  var userData = message.text.match(/\<(.*?)\>/g);  //suss out any @mentions of users
  if (userData) {
    // if there is a user is mentioned initiate the challenge!
    var challenged = userData[0].replace(/[^\w\s]/gi, '');

    bot.api.users.info({user: challenged}, (error, response) => {
        bot.reply(message, ':rotating_light: <@' + response.user.name + '> you have been challenged to a game of ROCK:mountain: , PAPER:spiral_note_pad: , SCISSORS:scissors:! Prepare to defend your honor!');
    });
    bot.startPrivateConversation(message, privateConvo(bot, message));
  } else {
    //if no user challenged
    bot.reply(message, 'You didn\'t challenge anyone you chicken shit! :chicken: :poop:');
  }

function privateConvo(bot, message) {
  const { user, channel } = message;
  return (err, convo) => {
    if (err) throw err;
    var rnd = Math.floor(Math.random()* 65);
    var encouragementArray = [
    'I believe in you!:hugging_face:',
    'I\'m sure you\'ll do your best!:heart:',
    'you\'re already a winner in my book!:wink:',
    'nothing can stop you!:smirk_cat:',
    'you have the eye of the tiger:smirk_cat:',
    'you have the heart of a champion:trophy:',
    'your lucky numbers are ' + rnd + ', ' + rnd + ', ' + rnd + ', ' + rnd + ', ' + rnd + '. :four_leaf_clover:',
    'take no prisoners! :rage1:',
    'Rock! On second thought- Paper! No Wait! Scissors...actually IDK',
    'Paper! NO, Rock! No Wait! Scissors; I made things worse, sorry. :disappointed:',
    'shoot straight!:grin:',
    'trust the force.',
    'trust in your instincts.',
    'Paper is on a roll!',
    'Get it. GET IT!',
    'You got this.:raised_hands:',
    'like a boss.:man_in_business_suit_levitating: ',
    'Establish dominance!',
    'what is best in life- Crush your enemies. See them driven before you. Hear the lamentations of their women.',
    'Rock it, or paper it? or _scissor_ it??:flushed:',
    'Cut em with scissors!',
    'Steady like a rock!',
    'give no quarter, and expect none either!:crossed_swords: ',
    'no retreat, no surrender!:crossed_swords: ',
    'I\'m not friends with losers- so try not to lose, eh? :trollface:',
    'If you\'re not first you\'re last!:medal:',
    'if you lose, don\'t bother coming home. :trollface:',
    'nothing can conquer your indomitable spirit!:raised_hands:'
    ];
    var randomEncouragement = Math.floor(Math.random()* encouragementArray.length);
    convo.ask('Do you want to play `paper`, `rock`, or `scissors`? No matter what you choose just remember: ' + encouragementArray[randomEncouragement], [
      {
        pattern: 'paper|rock|scissors',
        callback(response, convo) {
          // since no further messages are queued after this,
          // the conversation will end naturally with status === 'completed'
          convo.next();
        },
      }, {
        default: true,
        callback(response, convo) {
          convo.repeat();
          convo.next();
        },
      },
    ], { key: 'rockPaperScissors' }); // store the results in a field called rockPaperScissors

    convo.on('end', (convo) => {
      if (convo.status === 'completed') {
        var userPlay = convo.extractResponse('rockPaperScissors');
	var rpsObj = db.getSync("rps");
          if (err) throw err;

          if (rpsObj.played === "") { //no one played yet. enter player move and note to channel
		console.log(rpsObj.played);
		  console.log('no one played');
		  rpsObj.played=message.user + '-' + userPlay;
		  var id = db.saveSync("rps", rpsObj);
		  bot.reply(message, message.user + ' played!');
          } else { //someone played. enter current player move and existing move to game engine. print results. update w-l records for players. and clear played entry
		console.log(rpsObj.played);
		console.log('someone played');
		var gameEngine = require('./Rock-Paper-Spock');
  		var instance = new gameEngine(gameEngine.DefaultRules);
		var player1 = rpsObj.played.split("-");
  		instance.addPlayer({id: player1[0], sign: player1[1]});
  		instance.addPlayer({id: 'player2', sign: userPlay});
  		instance.play();
  		console.log(instance.winner);
		bot.reply(message, instance.winner.id + ' won!');

          }

      } else {
        // this happens if the conversation ended prematurely for some reason
        bot.reply(message, 'OK, nevermind!');
      }

	  });
 }
 };

};
<|endoftext|>