<commit_before>/*
 * This file is part of the KUBEjs package
 *
 * (c) Red Scotch Software Inc <kube+js@redscotch.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
(function(KUBE){
	"use strict";
	KUBE.LoadFactory('/Library/UI/UI',UI,['/Library/UI/Loader','/Library/Ajax/Client','/Library/DOM/DomJack','/Library/Extend/Object','/Library/Extend/Array','/Library/Extend/Date','/Library/Extend/Math']);

	UI.prototype.toString = function(){ return '[object '+this.constructor.name+']' };
	function UI(_DomJack){
        if(KUBE.Is(_DomJack,true) !== 'DomJack'){
            throw new Error('Failed to initialize User Interface, constructor must be a valid DomJack object');
        }
        var Root,Client,NotifyClient,nRequestManager,nResponseHandler,RequestTemplate,$API,UILoader,requestManager,responseHandler,notifications,lastNRun,nState,nPause,nThreshold;
        var UIPipe; //This is new

        UILoader = KUBE.Class('/Library/UI/Loader')();
        notifications = {};
        lastNRun = 0;
        nState = false;
        nPause = false;

        //Our API
        $API = {
            'SetPipe':SetPipe,
            'Send':Send,
            'SendAction':SendAction,
            'SendSubscription':SendSubscription,
            'SendUnsubscription':SendUnsubscription,
            'ProcessInstructions':ProcessInstructions
        }.KUBE().create(UI.prototype);

        Root = UILoader.Create(undefined,'Root','Root','Root');

        var rootDimensions = getRootDimensions(_DomJack);

        Root.Init({
            'UI':$API,
            'DomJackRoot':_DomJack
        },rootDimensions[0],rootDimensions[1]);

        Root.Once('delete',function(){
            throw new Error('The Root Node of the UI was deleted. This is an irrecoverable UI state.');
            Root = undefined;
        });

        $API.Root = Root;
        return $API;

        //Instruction processing
        function SetPipe(_UIPipe){
            if(KUBE.Is(_UIPipe) === 'object' && KUBE.Is(_UIPipe.Send) === 'function'){
                UIPipe = _UIPipe;
            }
        }

        function Send(_data,_type){
            return UIPipe.Send(_data,_type);
        }

        function SendAction(_data){
            if(UIPipe){
                return UIPipe.Send(_data,'action');
            }
        }

        function SendSubscription(_data){
            if(UIPipe){
                return UIPipe.Send(_data,'subscribe');
            }
        }

        function SendUnsubscription(_data){
            if(UIPipe){
                return UIPipe.Send(_data,'unsubscribe');
            }
        }

        function ProcessInstructions(_InstructionsObj){
            if(KUBE.Is(_InstructionsObj,true) === 'ViewInstructions'){
                var FoundView = Root.Find(_InstructionsObj);
                if(KUBE.Is(FoundView,true) === 'UIView'){
                    if(_InstructionsObj.GetData()){
                        FoundView.Update(_InstructionsObj.GetData());
                    }

                    if(KUBE.Is(_InstructionsObj.GetChildViews()) === 'array'){
                        FoundView.UpdateChildren(_InstructionsObj.GetChildViews(),_InstructionsObj.GetBehavior());
                    }
                }
            }
        }

        function getRootDimensions(_RootDJ){
            //So... what should I do with this? For now, take its width/height if they exist, otherwise go full screen. It is likely this should be more robust in the future to handle a variety of spaces
            var width,height;
            width = _RootDJ.Style().Width() || KUBE.Class('/Library/DOM/WinDocJack')().WindowWidth();
            height = _RootDJ.Style().Height() || KUBE.Class('/Library/DOM/WinDocJack')().WindowHeight();
            return [width,height];
        }

	}
}(KUBE));

//
//
//function SetClient(_Client){
//    if(KUBE.Is(_Client,true) === 'Client'){
//        Client = _Client;
//    }
//    else{
//        throw new Error('UI Client object must be a valid /Library/Ajax/Client object.');
//    }
//}
//
//function SetNotificationClient(_Client,_notifyThreshold){
//    if(KUBE.Is(_Client,true) === 'Client'){
//        nThreshold = _notifyThreshold || 500;
//        NotifyClient = _Client;
//    }
//    else{
//        throw new Error('UI Client object must be a valid /Library/Ajax/Client object.');
//    }
//}
//
//function SendRequest(_Request){
//    if(KUBE.Is(_Request,true) === 'Request' && Client){
//        var ResponsePromise = Client.SendRequest(_Request);
//        ResponsePromise.then(handleClientResponse).catch(handleClientError);
//        return ResponsePromise.then(function(_Response){
//            return {'code':_Response.GetStatusCode(),'reason':_Response.GetStatusText()};
//        });
//    }
//}
//
//function SetRequestManager(_managerCallback){
//    if(KUBE.Is(_managerCallback) === 'function'){
//        requestManager = _managerCallback;
//    }
//}
//
//function SetResponseHandler(_handlerCallback){
//    if(KUBE.Is(_handlerCallback) === 'function'){
//        responseHandler = _handlerCallback;
//    }
//}
//
//function AddNotification(_UIView,_callCallback,_receiveCallback,_interval){
//    if(KUBE.Is(NotifyClient,true) !== 'Client'){
//        //throw new Error();
//    }
//    else{
//        if(KUBE.Is(_UIView,true) === 'UIView' && KUBE.Is(_callCallback) === 'function' && KUBE.Is(_receiveCallback) === 'function'){
//            var notifyId = generateNotifyId();
//            _interval = _interval || 1000;
//
//            //I could probably optimize this if it becomes a burden on the system
//            notifications[notifyId] = {
//                'interval':_interval,
//                'callCallback':_callCallback,
//                'receiveCallback':_receiveCallback,
//                'lastRun':0
//            };
//
//            //I'm fairly sure this will stack and clear properly, but might be worth double checking
//            _UIView.Once('delete',function(){
//                CancelNotification(notifyId);
//            });
//
//            if(!nState){
//                nState = setInterval(function(){
//                    requestAnimationFrame(runNotifications);
//                },nThreshold);
//            }
//            return notifyId;
//        }
//    }
//}
//
//function CancelNotification(_notifyId){
//    if(notifications[_notifyId]){
//        delete notifications[_notifyId];
//    }
//}
//
//function Send(_data){
//    if(KUBE.Is(requestManager) === 'function'){
//        return SendRequest(requestManager(_data));
//    }
//}
//
//function handleClientError(_Error){
//    throw _Error;
//}
//
//function handleClientResponse(_Response){
//    if(KUBE.Is(responseHandler) === 'function'){
//        responseHandler(_Response);
//    }
//    else{
//        throw new Error('UI requires a Response Handler to translate Client Responses to Instructions. No response handler set');
//    }
//}
//
//function getRootDimensions(_RootDJ){
//    //So... what should I do with this? For now, take its width/height if they exist, otherwise go full screen. It is likely this should be more robust in the future to handle a variety of spaces
//    var width,height;
//    width = _RootDJ.Style().Width() || KUBE.Class('/Library/DOM/WinDocJack')().WindowWidth();
//    height = _RootDJ.Style().Height() || KUBE.Class('/Library/DOM/WinDocJack')().WindowHeight();
//    return [width,height];
//}
//
//function generateNotifyId(){
//    var id = genId();
//    while(notifications[id]){
//        id = genId();
//    }
//    return id;
//
//    function genId() {
//        var $return = [], index, char;
//        for (var i = 0; i < 52; i++) {
//            index = Math.floor(Math.random() * 26) + 65;
//            char = String.fromCharCode(index);
//            char = (Math.random() > 0.5 ? char.toLowerCase() : char);
//            $return.push(char);
//        }
//        return $return.join("");
//    }
//}
//
//function runNotifications(){
//    //SetInterval will try to run this pretty fast, but we do wait for the server notification to finish, this way we don't stack up weird.
//    // Individual notifications will always execute if the time inbetween their last run and current time is longer than their interval
//    if(!nPause){
//        nPause = true;
//        lastNRun = Date.now();
//        var send = false;
//        var Request = KUBE.Class('/Library/Ajax/Request')();
//        Request.SetMethod('post');
//        Request.SetResponseType('json');
//
//        notifications.KUBE().each(function(_notifyId,_notifyObj){
//            if(Date.now()-_notifyObj.lastRun > _notifyObj.interval){
//                _notifyObj.lastRun = Date.now();
//                var payloadData = _notifyObj.callCallback();
//                if(payloadData){
//                    Request.AddData(_notifyId,payloadData);
//                    send = true;
//                }
//            }
//        });
//
//        if(send){
//            NotifyClient.SendRequest(Request).then(function(_Response){
//                if(_Response.GetStatusCode() === 200){
//                    var responseData = _Response.GetData();
//                    responseData.KUBE().each(function(_notifyId,_notification){
//                        //Just making sure it's still around
//                        if(notifications[_notifyId]){
//                            notifications[_notifyId].receiveCallback(_notification);
//                        }
//                    });
//                }
//                nPause = false;
//            }).catch(function(_Err){
//                setTimeout(function(){
//                    nPause = false;
//                },5000);
//            });
//        }
//        else{
//            nPause = false;
//        }
//    }
//}<commit_msg>Tweaking UI.js to be less dependant<commit_after>/*
 * This file is part of the KUBEjs package
 *
 * (c) Red Scotch Software Inc <kube+js@redscotch.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
(function(KUBE){
	"use strict";
	KUBE.LoadFactory('/Library/UI/UI',UI,['/Library/UI/Loader','/Library/Ajax/Client','/Library/DOM/DomJack','/Library/Extend/Object','/Library/Extend/Array','/Library/Extend/Date','/Library/Extend/Math']);

	UI.prototype.toString = function(){ return '[object '+this.constructor.name+']' };
	function UI(_DomJack){
        if(KUBE.Is(_DomJack,true) !== 'DomJack'){
            throw new Error('Failed to initialize User Interface, constructor must be a valid DomJack object');
        }
        var Root,Client,NotifyClient,nRequestManager,nResponseHandler,RequestTemplate,$API,UILoader,requestManager,responseHandler,notifications,lastNRun,nState,nPause,nThreshold;
        var UIGroundControl; //This is new

        UILoader = KUBE.Class('/Library/UI/Loader')();

        //Our API
        $API = {
            'SetGroundControl':SetGroundControl,
            'Send':Send,
            'ProcessInstructions':ProcessInstructions
        }.KUBE().create(UI.prototype);

        Root = UILoader.Create(undefined,'Root','Root','Root');

        var rootDimensions = getRootDimensions(_DomJack);

        Root.Init({
            'UI':$API,
            'DomJackRoot':_DomJack
        },rootDimensions[0],rootDimensions[1]);

        Root.Once('delete',function(){
            throw new Error('The Root Node of the UI was deleted. This is an irrecoverable UI state.');
            Root = undefined;
        });

        $API.Root = Root;
        return $API;

        //Instruction processing
        function SetGroundControl(_UIGroundControl){
            if(KUBE.Is(_UIGroundControl) === 'object' && KUBE.Is(_UIGroundControl.Send) === 'function'){
                UIGroundControl = _UIGroundControl;
            }
        }

        function Send(_data,_type){
            return UIGroundControl.Send(_data,_type);
        }

        function ProcessInstructions(_InstructionsObj){
            if(KUBE.Is(_InstructionsObj,true) === 'ViewInstructions'){
                var FoundView = Root.Find(_InstructionsObj);
                if(KUBE.Is(FoundView,true) === 'UIView'){
                    if(_InstructionsObj.GetData()){
                        FoundView.Update(_InstructionsObj.GetData());
                    }

                    if(KUBE.Is(_InstructionsObj.GetChildViews()) === 'array'){
                        FoundView.UpdateChildren(_InstructionsObj.GetChildViews(),_InstructionsObj.GetBehavior());
                    }
                }
            }
        }

        function getRootDimensions(_RootDJ){
            //So... what should I do with this? For now, take its width/height if they exist, otherwise go full screen. It is likely this should be more robust in the future to handle a variety of spaces
            var width,height;
            width = _RootDJ.Style().Width() || KUBE.Class('/Library/DOM/WinDocJack')().WindowWidth();
            height = _RootDJ.Style().Height() || KUBE.Class('/Library/DOM/WinDocJack')().WindowHeight();
            return [width,height];
        }

	}
}(KUBE));

//
//
//function SetClient(_Client){
//    if(KUBE.Is(_Client,true) === 'Client'){
//        Client = _Client;
//    }
//    else{
//        throw new Error('UI Client object must be a valid /Library/Ajax/Client object.');
//    }
//}
//
//function SetNotificationClient(_Client,_notifyThreshold){
//    if(KUBE.Is(_Client,true) === 'Client'){
//        nThreshold = _notifyThreshold || 500;
//        NotifyClient = _Client;
//    }
//    else{
//        throw new Error('UI Client object must be a valid /Library/Ajax/Client object.');
//    }
//}
//
//function SendRequest(_Request){
//    if(KUBE.Is(_Request,true) === 'Request' && Client){
//        var ResponsePromise = Client.SendRequest(_Request);
//        ResponsePromise.then(handleClientResponse).catch(handleClientError);
//        return ResponsePromise.then(function(_Response){
//            return {'code':_Response.GetStatusCode(),'reason':_Response.GetStatusText()};
//        });
//    }
//}
//
//function SetRequestManager(_managerCallback){
//    if(KUBE.Is(_managerCallback) === 'function'){
//        requestManager = _managerCallback;
//    }
//}
//
//function SetResponseHandler(_handlerCallback){
//    if(KUBE.Is(_handlerCallback) === 'function'){
//        responseHandler = _handlerCallback;
//    }
//}
//
//function AddNotification(_UIView,_callCallback,_receiveCallback,_interval){
//    if(KUBE.Is(NotifyClient,true) !== 'Client'){
//        //throw new Error();
//    }
//    else{
//        if(KUBE.Is(_UIView,true) === 'UIView' && KUBE.Is(_callCallback) === 'function' && KUBE.Is(_receiveCallback) === 'function'){
//            var notifyId = generateNotifyId();
//            _interval = _interval || 1000;
//
//            //I could probably optimize this if it becomes a burden on the system
//            notifications[notifyId] = {
//                'interval':_interval,
//                'callCallback':_callCallback,
//                'receiveCallback':_receiveCallback,
//                'lastRun':0
//            };
//
//            //I'm fairly sure this will stack and clear properly, but might be worth double checking
//            _UIView.Once('delete',function(){
//                CancelNotification(notifyId);
//            });
//
//            if(!nState){
//                nState = setInterval(function(){
//                    requestAnimationFrame(runNotifications);
//                },nThreshold);
//            }
//            return notifyId;
//        }
//    }
//}
//
//function CancelNotification(_notifyId){
//    if(notifications[_notifyId]){
//        delete notifications[_notifyId];
//    }
//}
//
//function Send(_data){
//    if(KUBE.Is(requestManager) === 'function'){
//        return SendRequest(requestManager(_data));
//    }
//}
//
//function handleClientError(_Error){
//    throw _Error;
//}
//
//function handleClientResponse(_Response){
//    if(KUBE.Is(responseHandler) === 'function'){
//        responseHandler(_Response);
//    }
//    else{
//        throw new Error('UI requires a Response Handler to translate Client Responses to Instructions. No response handler set');
//    }
//}
//
//function getRootDimensions(_RootDJ){
//    //So... what should I do with this? For now, take its width/height if they exist, otherwise go full screen. It is likely this should be more robust in the future to handle a variety of spaces
//    var width,height;
//    width = _RootDJ.Style().Width() || KUBE.Class('/Library/DOM/WinDocJack')().WindowWidth();
//    height = _RootDJ.Style().Height() || KUBE.Class('/Library/DOM/WinDocJack')().WindowHeight();
//    return [width,height];
//}
//
//function generateNotifyId(){
//    var id = genId();
//    while(notifications[id]){
//        id = genId();
//    }
//    return id;
//
//    function genId() {
//        var $return = [], index, char;
//        for (var i = 0; i < 52; i++) {
//            index = Math.floor(Math.random() * 26) + 65;
//            char = String.fromCharCode(index);
//            char = (Math.random() > 0.5 ? char.toLowerCase() : char);
//            $return.push(char);
//        }
//        return $return.join("");
//    }
//}
//
//function runNotifications(){
//    //SetInterval will try to run this pretty fast, but we do wait for the server notification to finish, this way we don't stack up weird.
//    // Individual notifications will always execute if the time inbetween their last run and current time is longer than their interval
//    if(!nPause){
//        nPause = true;
//        lastNRun = Date.now();
//        var send = false;
//        var Request = KUBE.Class('/Library/Ajax/Request')();
//        Request.SetMethod('post');
//        Request.SetResponseType('json');
//
//        notifications.KUBE().each(function(_notifyId,_notifyObj){
//            if(Date.now()-_notifyObj.lastRun > _notifyObj.interval){
//                _notifyObj.lastRun = Date.now();
//                var payloadData = _notifyObj.callCallback();
//                if(payloadData){
//                    Request.AddData(_notifyId,payloadData);
//                    send = true;
//                }
//            }
//        });
//
//        if(send){
//            NotifyClient.SendRequest(Request).then(function(_Response){
//                if(_Response.GetStatusCode() === 200){
//                    var responseData = _Response.GetData();
//                    responseData.KUBE().each(function(_notifyId,_notification){
//                        //Just making sure it's still around
//                        if(notifications[_notifyId]){
//                            notifications[_notifyId].receiveCallback(_notification);
//                        }
//                    });
//                }
//                nPause = false;
//            }).catch(function(_Err){
//                setTimeout(function(){
//                    nPause = false;
//                },5000);
//            });
//        }
//        else{
//            nPause = false;
//        }
//    }
//}<|endoftext|>


<commit_before>// node_modules
import 'angular';

import 'angular-ui-router';

<% for(var i=0; i<importList.length; i++) { %>
import '<%= importList[i] %>';
<% } %>

// local scripts
//import "../assets/js/...";
<commit_msg>index vendor loop uses let not var<commit_after>// node_modules
import 'angular';

import 'angular-ui-router';

<% for(let i=0; i<importList.length; i++) { %>
import '<%= importList[i] %>';
<% } %>

// local scripts
//import "../assets/js/...";
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

/**
 * Render an actual component on the Khan Academy site and profile that.
 *
 * You must have a webapp dev-server already running (this script does
 * not currently work against prod).  You must also have a
 * react-render-server running in 'profile' mode:
 *    npm run profile
 * You must pass in a .fixture.{js,jsx} file; we can only render
 * components that have an associated fixture.  We will figure out
 * everything else needed to render the relevant profile.
 *
 * For now, we can only handle .fixture files without any other
 * dependencies (since we're not running in a webapp context).
 */

/* eslint-disable no-console */

const path = require("path");

const argparse = require("argparse");
const superagent = require("superagent");

const packageInfo = require("../package.json");
const secret = require("../src/secret.js");

/**
 * Given a map from package-name to immediate dependencies, and a package
 * name of interest, return the transitive dependencies for the package
 * of interest.  The deps are topologically sorted, so no package in the
 * returned array depends on a package that comes earlier in the array.
 */
const getTransitiveDependencies = function(pkg, depmap) {
    const retval = [];
    const seenPkgs = {};

    const addDeps = function(currentPkg) {
        if (seenPkgs[currentPkg]) {
            return;
        }
        seenPkgs[currentPkg] = true;
        (depmap[currentPkg] || []).forEach(dep => addDeps(dep));
        retval.push(currentPkg);
    };

    addDeps(pkg);
    return retval;
};

/**
 * Given a package and a package-manifest.js file, return a list of
 * the urls of all the packages that the input package transitively
 * depends on (itself included).
 */
const getDependentPackageUrls = function(pkg, manifestContents,
                                         gaeHostPort) {
    const dependencyString = manifestContents.replace(
            /^.*"javascript": (\[.*\]), "stylesheets":.*/, '$1');
    const dependencyInfo = JSON.parse(dependencyString);

    const dependencyMap = {};    // for some value of "const"
    const pkgToUrl = {};
    dependencyInfo.forEach((packageInfo) => {
        dependencyMap[packageInfo.name] = packageInfo.dependencies;
        pkgToUrl[packageInfo.name] = gaeHostPort + packageInfo.url;
    });
    const packageDeps = getTransitiveDependencies(pkg, dependencyMap);
    return packageDeps.map(pkg => pkgToUrl[pkg]);
};

/**
 * Guess what package a component lives in from its filename.  Usually
 * the filename will have 'foo-package' in it.  That's not a guarantee
 * the component is in foo-package, but it's a good sign...
 * Calls resolve/reject, because that's easiest given how this is used.
 */
const guessPackage = function(componentPath, resolve, reject) {
    const result = /\/([^\/]*)-package\//.exec(componentPath);
    if (result) {
        resolve(result[1] + '.js');
    } else {
        reject(new Error('Could not guess package for ' + componentPath));
    }
};

/**
 * Return the package that a given component lives in.
 * On localhost, we can just ask the system to do this mapping.  But for
 * prod, we don't have access to the necessary information, so we just
 * guess.  TODO(csilvers): if guessing isn't good enough, we could also
 * talk to a local dev-server just for this mapping, and assume it's the
 * same for dev and prod.  But that's a lot of work for minimal gain.
 */
const getPackage = function(componentPath, gaeHostPort) {
    // For known prod servers, we don't even bother trying to talk to
    // them as if they're dev.
    if (gaeHostPort.indexOf('khanacademy.org') > -1 ||
           gaeHostPort.indexOf('appspot.com') > -1) {
        return new Promise((resolve, reject) => {
            guessPackage(componentPath, resolve, reject);
        });
    }
    // First try to talk to /_kake/ -- that will work on localhost.
    // If it fails, assume we're on prod and just guess the package.
    const pathToPackageMapUrl = (
        '/_kake/genfiles/js_path_to_pkgs/en/path_to_packages_prod.json');
    return new Promise((resolve, reject) => {
        superagent.get(gaeHostPort + pathToPackageMapUrl).end((err, res) => {
            if (err) {
                // Presumably we're on prod, let's just guess the package!
                guessPackage(componentPath, resolve, reject);
            } else {
                const pathToPackagesMap = res.body;
                const componentPackage = pathToPackagesMap[componentPath][0];
                resolve(componentPackage);
            }
        });
    });
};

// Convert superagent-style callbacks to promises.
const requestToPromise = function(req) {
    return new Promise((resolve, reject) => {
        req.buffer().end((err, res) => {
            if (err) {
                reject(err);
            } else {
                resolve(res);
            }
        });
    });
};

/**
 * Return the package-manifest contents.
 *
 * This is needed for figuring out package dependencies for render.
 */
const getPackageManifestContents = function(gaeHostPort) {
    // We need the transitive dependency map for the package
    // containing our component.  This is a bit annoying for 3
    // reasons:
    // 1) On prod, the file containing the map has a hard-to-guess
    //    filename, so we need to extract it from the homepage;
    // 2) The file containing the map is not json, so we have to
    //    extract out the info we want using regexps;
    // 3) We need to figure out the transitive deps ourselves.
    // We do (1) and (2), at least, here.
    // TODO(csilvers): compute (3) here as well too.
    return requestToPromise(superagent.get(gaeHostPort + '/')).then(res => {
        const re = /['"]([^"']*\/package-manifest[^'"]*)["']/;
        const results = re.exec(res.text);
        if (!results) {
            throw new Error("Can't find package-manifest in homepage");
        }
        let packageManifestUrl = results[1];
        if (packageManifestUrl.indexOf('://') === -1) {
            packageManifestUrl = gaeHostPort + packageManifestUrl;
        }
        return packageManifestUrl;
    }).then((packageManifestUrl) => {
        return requestToPromise(superagent.get(packageManifestUrl));
    }).then((packageManifestResult) => {
        return packageManifestResult.text;
    });
};

/**
 * Return profile information about rendering component with fixture.
 *
 * @param {string} componentPath - a path to the component,
 *     relative to webapp's ka-root.
 * @param {string} fixturePath - where the fixture file lives on
 *     the local filesystem.  Should be an absolute path.
 * @param {number} instanceSeed - a (preferably large) integer.
 *     When the props file has multiple instances that could be used
 *     to populate the fixture, we use the instanceSeed to decide which
 *     one to use.  The mapping from seed to instance is arbitrary but
 *     fixed -- using the same seed again will yield the same instance.
 * @param {string} gaeHostPort - actually a protocol-host-port, where
 *     the webapp server is running.
 * @param {string} renderHostPort - actually a protocol-host-port, where
 *      the react-render-server is running.
 * @param {string} packageManifestContents - the output of
 *      getPackageManifestContents().
 */
const render = function(componentPath, fixturePath, instanceSeed,
                        gaeHostPort, renderHostPort,
                        packageManifestContents) {
    const relativeFixturePath = path.relative(__dirname, fixturePath);
    const allProps = require(relativeFixturePath).instances;
    const props = allProps[instanceSeed % allProps.length];

    getPackage(componentPath, gaeHostPort).then((componentPackage) => {
        const depPackageUrls = getDependentPackageUrls(
            componentPackage, packageManifestContents, gaeHostPort);

        const reqBody = {
            secret: secret.get(),
            urls: depPackageUrls,
            path: "./" + componentPath,
            props: props,
        };

        const url = renderHostPort + "/render?path=" + componentPath;

        return requestToPromise(
            superagent.post(url).send(reqBody)
        );
    }).then(res => {
        console.log(`${componentPath}: ${res.text.length}`);
    }).catch(err => {
        // If it's an http error, print the status code rather than name,
        // and the error text if the body is json.
        if (err.response && err.response.status && err.response.text) {
            console.log(`${componentPath}: ` +
                        `${err.response.text} (${err.response.status})`);
        } else {
            console.log(`${componentPath}: ${err})`);
        }
    });
};

const main = function(parseArgs) {
    let gaeHostPort;
    let rrsHostPort;

    if (parseArgs.dev || parseArgs.dev_webapp) {
        gaeHostPort = "http://localhost:8080";
    } else {
        gaeHostPort = "https://www.khanacademy.org";
    }

    if (parseArgs.dev || parseArgs.dev_render) {
        rrsHostPort = "http://localhost:8060";
    } else {
        rrsHostPort = "https://react-render-dot-khan-academy.appspot.com";
    }

    getPackageManifestContents(gaeHostPort).then((packageManifestContents) => {
        // To get the path to the component, we just remove the trailing
        // .fixture.js, and the leading ka-root prefix.  For now, we
        // assume that the fixture is at <ka_root>/javascript/...
        // TODO(csilvers): figure out ka-root better.
        parseArgs.fixtures.forEach((fixturePath) => {
            try {
                const fixtureAbspath = path.resolve(fixturePath);
                const re = /(javascript\/.*)\.fixture\./;
                const result = re.exec(fixtureAbspath);
                if (!result) {
                    throw new Error('cannot infer component from ' +
                                    fixtureAbspath);
                }
                const componentPath = result[1];
                for (let i = 0; i < parseArgs.num_trials_per_component; i++) {
                    // Let's do the work!
                    render(componentPath, fixtureAbspath, i,
                           gaeHostPort, rrsHostPort,
                           packageManifestContents);
                }
            } catch (err) {
                console.log(`Skipping ${fixturePath}: ${err}`);
            }
        });
    });
};

process.on('unhandledRejection', (reason, p) => {
    console.log("Unhandled Rejection at: Promise ", p,
                " reason: ", reason.stack);
});

const parser = new argparse.ArgumentParser({
    version: packageInfo.version,
    addHelp: true,
    description: "A load tester/benchmarker for the react-render-server",
});
parser.addArgument(['fixtures'],
                   {nargs: '*',
                    defaultValue: ["../webapp/javascript/content-library-package/components/concept-thumbnail.jsx.fixture.js"],  // @Nolint(long line)
                    help: "List of fixture files on the local filesystem"});
parser.addArgument(['--dev'],
                   {action: 'storeTrue',
                    help: "Connect to local gae and render-server"});
parser.addArgument(['--dev-webapp'],
                   {action: 'storeTrue',
                    help: "Use local webapp (on localhost:8080)"});
parser.addArgument(['--dev-render'],
                   {action: 'storeTrue',
                    help: "Use local render-server (on localhost:8060)"});
parser.addArgument(['-n', '--num-trials-per-component'],
                   {type: 'int', defaultValue: 1,
                    help: ("How many times we render a given component " +
                           "with a given fixture file (for load testing)")});

main(parser.parseArgs());

/* For manual testing, here's a curl command you can send to a server directly:

curl -H "Content-type: application/json" -d '{"secret":"'`cat ../secret`'", "urls":["https://www.khanacademy.org/genfiles/javascript/en/corelibs-package-31375e.js","https://www.khanacademy.org/genfiles/javascript/en/corelibs-legacy-package-fbfab0.js","https://www.khanacademy.org/genfiles/javascript/en/shared-package-1e468a.js","https://www.khanacademy.org/genfiles/javascript/en/shared-styles-package-32d405.js","https://www.khanacademy.org/genfiles/javascript/en/hover-card-package-de8d87.js","https://www.khanacademy.org/genfiles/javascript/en/react-package-9b7fb9.js","https://www.khanacademy.org/genfiles/javascript/en/react-components-package-a7e18c.js","https://www.khanacademy.org/genfiles/javascript/en/flux-package-838d8f.js","https://www.khanacademy.org/genfiles/javascript/en/tasks-package-43bf44.js","https://www.khanacademy.org/genfiles/javascript/en/tutorial-package-8e5302.js","https://www.khanacademy.org/genfiles/javascript/en/video-package-9b200b.js","https://www.khanacademy.org/genfiles/javascript/en/content-library-package-9ac69b.js"],"path":"./javascript/content-library-package/components/concept-thumbnail.jsx","props":{"domain":"math","kind":"concept","progressData":{"skillsCompleted":3,"skillsTotal":32},"url":"/images/topic-icons-large/linear_equations.png"}}' 127.0.0.1:8080/render
*/
<commit_msg>Add comment explaining that the ?path= is ignored by the server<commit_after>#!/usr/bin/env node

'use strict';

/**
 * Render an actual component on the Khan Academy site and profile that.
 *
 * You must have a webapp dev-server already running (this script does
 * not currently work against prod).  You must also have a
 * react-render-server running in 'profile' mode:
 *    npm run profile
 * You must pass in a .fixture.{js,jsx} file; we can only render
 * components that have an associated fixture.  We will figure out
 * everything else needed to render the relevant profile.
 *
 * For now, we can only handle .fixture files without any other
 * dependencies (since we're not running in a webapp context).
 */

/* eslint-disable no-console */

const path = require("path");

const argparse = require("argparse");
const superagent = require("superagent");

const packageInfo = require("../package.json");
const secret = require("../src/secret.js");

/**
 * Given a map from package-name to immediate dependencies, and a package
 * name of interest, return the transitive dependencies for the package
 * of interest.  The deps are topologically sorted, so no package in the
 * returned array depends on a package that comes earlier in the array.
 */
const getTransitiveDependencies = function(pkg, depmap) {
    const retval = [];
    const seenPkgs = {};

    const addDeps = function(currentPkg) {
        if (seenPkgs[currentPkg]) {
            return;
        }
        seenPkgs[currentPkg] = true;
        (depmap[currentPkg] || []).forEach(dep => addDeps(dep));
        retval.push(currentPkg);
    };

    addDeps(pkg);
    return retval;
};

/**
 * Given a package and a package-manifest.js file, return a list of
 * the urls of all the packages that the input package transitively
 * depends on (itself included).
 */
const getDependentPackageUrls = function(pkg, manifestContents,
                                         gaeHostPort) {
    const dependencyString = manifestContents.replace(
            /^.*"javascript": (\[.*\]), "stylesheets":.*/, '$1');
    const dependencyInfo = JSON.parse(dependencyString);

    const dependencyMap = {};    // for some value of "const"
    const pkgToUrl = {};
    dependencyInfo.forEach((packageInfo) => {
        dependencyMap[packageInfo.name] = packageInfo.dependencies;
        pkgToUrl[packageInfo.name] = gaeHostPort + packageInfo.url;
    });
    const packageDeps = getTransitiveDependencies(pkg, dependencyMap);
    return packageDeps.map(pkg => pkgToUrl[pkg]);
};

/**
 * Guess what package a component lives in from its filename.  Usually
 * the filename will have 'foo-package' in it.  That's not a guarantee
 * the component is in foo-package, but it's a good sign...
 * Calls resolve/reject, because that's easiest given how this is used.
 */
const guessPackage = function(componentPath, resolve, reject) {
    const result = /\/([^\/]*)-package\//.exec(componentPath);
    if (result) {
        resolve(result[1] + '.js');
    } else {
        reject(new Error('Could not guess package for ' + componentPath));
    }
};

/**
 * Return the package that a given component lives in.
 * On localhost, we can just ask the system to do this mapping.  But for
 * prod, we don't have access to the necessary information, so we just
 * guess.  TODO(csilvers): if guessing isn't good enough, we could also
 * talk to a local dev-server just for this mapping, and assume it's the
 * same for dev and prod.  But that's a lot of work for minimal gain.
 */
const getPackage = function(componentPath, gaeHostPort) {
    // For known prod servers, we don't even bother trying to talk to
    // them as if they're dev.
    if (gaeHostPort.indexOf('khanacademy.org') > -1 ||
           gaeHostPort.indexOf('appspot.com') > -1) {
        return new Promise((resolve, reject) => {
            guessPackage(componentPath, resolve, reject);
        });
    }
    // First try to talk to /_kake/ -- that will work on localhost.
    // If it fails, assume we're on prod and just guess the package.
    const pathToPackageMapUrl = (
        '/_kake/genfiles/js_path_to_pkgs/en/path_to_packages_prod.json');
    return new Promise((resolve, reject) => {
        superagent.get(gaeHostPort + pathToPackageMapUrl).end((err, res) => {
            if (err) {
                // Presumably we're on prod, let's just guess the package!
                guessPackage(componentPath, resolve, reject);
            } else {
                const pathToPackagesMap = res.body;
                const componentPackage = pathToPackagesMap[componentPath][0];
                resolve(componentPackage);
            }
        });
    });
};

// Convert superagent-style callbacks to promises.
const requestToPromise = function(req) {
    return new Promise((resolve, reject) => {
        req.buffer().end((err, res) => {
            if (err) {
                reject(err);
            } else {
                resolve(res);
            }
        });
    });
};

/**
 * Return the package-manifest contents.
 *
 * This is needed for figuring out package dependencies for render.
 */
const getPackageManifestContents = function(gaeHostPort) {
    // We need the transitive dependency map for the package
    // containing our component.  This is a bit annoying for 3
    // reasons:
    // 1) On prod, the file containing the map has a hard-to-guess
    //    filename, so we need to extract it from the homepage;
    // 2) The file containing the map is not json, so we have to
    //    extract out the info we want using regexps;
    // 3) We need to figure out the transitive deps ourselves.
    // We do (1) and (2), at least, here.
    // TODO(csilvers): compute (3) here as well too.
    return requestToPromise(superagent.get(gaeHostPort + '/')).then(res => {
        const re = /['"]([^"']*\/package-manifest[^'"]*)["']/;
        const results = re.exec(res.text);
        if (!results) {
            throw new Error("Can't find package-manifest in homepage");
        }
        let packageManifestUrl = results[1];
        if (packageManifestUrl.indexOf('://') === -1) {
            packageManifestUrl = gaeHostPort + packageManifestUrl;
        }
        return packageManifestUrl;
    }).then((packageManifestUrl) => {
        return requestToPromise(superagent.get(packageManifestUrl));
    }).then((packageManifestResult) => {
        return packageManifestResult.text;
    });
};

/**
 * Return profile information about rendering component with fixture.
 *
 * @param {string} componentPath - a path to the component,
 *     relative to webapp's ka-root.
 * @param {string} fixturePath - where the fixture file lives on
 *     the local filesystem.  Should be an absolute path.
 * @param {number} instanceSeed - a (preferably large) integer.
 *     When the props file has multiple instances that could be used
 *     to populate the fixture, we use the instanceSeed to decide which
 *     one to use.  The mapping from seed to instance is arbitrary but
 *     fixed -- using the same seed again will yield the same instance.
 * @param {string} gaeHostPort - actually a protocol-host-port, where
 *     the webapp server is running.
 * @param {string} renderHostPort - actually a protocol-host-port, where
 *      the react-render-server is running.
 * @param {string} packageManifestContents - the output of
 *      getPackageManifestContents().
 */
const render = function(componentPath, fixturePath, instanceSeed,
                        gaeHostPort, renderHostPort,
                        packageManifestContents) {
    const relativeFixturePath = path.relative(__dirname, fixturePath);
    const allProps = require(relativeFixturePath).instances;
    const props = allProps[instanceSeed % allProps.length];

    getPackage(componentPath, gaeHostPort).then((componentPackage) => {
        const depPackageUrls = getDependentPackageUrls(
            componentPackage, packageManifestContents, gaeHostPort);

        const reqBody = {
            secret: secret.get(),
            urls: depPackageUrls,
            path: "./" + componentPath,
            props: props,
        };

        // The `?path=` query param we add onto the end is completely ignored
        // by the server -- we add it here in order to make reading request
        // logs easier.
        const url = renderHostPort + "/render?path=" + componentPath;

        return requestToPromise(
            superagent.post(url).send(reqBody)
        );
    }).then(res => {
        console.log(`${componentPath}: ${res.text.length}`);
    }).catch(err => {
        // If it's an http error, print the status code rather than name,
        // and the error text if the body is json.
        if (err.response && err.response.status && err.response.text) {
            console.log(`${componentPath}: ` +
                        `${err.response.text} (${err.response.status})`);
        } else {
            console.log(`${componentPath}: ${err})`);
        }
    });
};

const main = function(parseArgs) {
    let gaeHostPort;
    let rrsHostPort;

    if (parseArgs.dev || parseArgs.dev_webapp) {
        gaeHostPort = "http://localhost:8080";
    } else {
        gaeHostPort = "https://www.khanacademy.org";
    }

    if (parseArgs.dev || parseArgs.dev_render) {
        rrsHostPort = "http://localhost:8060";
    } else {
        rrsHostPort = "https://react-render-dot-khan-academy.appspot.com";
    }

    getPackageManifestContents(gaeHostPort).then((packageManifestContents) => {
        // To get the path to the component, we just remove the trailing
        // .fixture.js, and the leading ka-root prefix.  For now, we
        // assume that the fixture is at <ka_root>/javascript/...
        // TODO(csilvers): figure out ka-root better.
        parseArgs.fixtures.forEach((fixturePath) => {
            try {
                const fixtureAbspath = path.resolve(fixturePath);
                const re = /(javascript\/.*)\.fixture\./;
                const result = re.exec(fixtureAbspath);
                if (!result) {
                    throw new Error('cannot infer component from ' +
                                    fixtureAbspath);
                }
                const componentPath = result[1];
                for (let i = 0; i < parseArgs.num_trials_per_component; i++) {
                    // Let's do the work!
                    render(componentPath, fixtureAbspath, i,
                           gaeHostPort, rrsHostPort,
                           packageManifestContents);
                }
            } catch (err) {
                console.log(`Skipping ${fixturePath}: ${err}`);
            }
        });
    });
};

process.on('unhandledRejection', (reason, p) => {
    console.log("Unhandled Rejection at: Promise ", p,
                " reason: ", reason.stack);
});

const parser = new argparse.ArgumentParser({
    version: packageInfo.version,
    addHelp: true,
    description: "A load tester/benchmarker for the react-render-server",
});
parser.addArgument(['fixtures'],
                   {nargs: '*',
                    defaultValue: ["../webapp/javascript/content-library-package/components/concept-thumbnail.jsx.fixture.js"],  // @Nolint(long line)
                    help: "List of fixture files on the local filesystem"});
parser.addArgument(['--dev'],
                   {action: 'storeTrue',
                    help: "Connect to local gae and render-server"});
parser.addArgument(['--dev-webapp'],
                   {action: 'storeTrue',
                    help: "Use local webapp (on localhost:8080)"});
parser.addArgument(['--dev-render'],
                   {action: 'storeTrue',
                    help: "Use local render-server (on localhost:8060)"});
parser.addArgument(['-n', '--num-trials-per-component'],
                   {type: 'int', defaultValue: 1,
                    help: ("How many times we render a given component " +
                           "with a given fixture file (for load testing)")});

main(parser.parseArgs());

/* For manual testing, here's a curl command you can send to a server directly:

curl -H "Content-type: application/json" -d '{"secret":"'`cat ../secret`'", "urls":["https://www.khanacademy.org/genfiles/javascript/en/corelibs-package-31375e.js","https://www.khanacademy.org/genfiles/javascript/en/corelibs-legacy-package-fbfab0.js","https://www.khanacademy.org/genfiles/javascript/en/shared-package-1e468a.js","https://www.khanacademy.org/genfiles/javascript/en/shared-styles-package-32d405.js","https://www.khanacademy.org/genfiles/javascript/en/hover-card-package-de8d87.js","https://www.khanacademy.org/genfiles/javascript/en/react-package-9b7fb9.js","https://www.khanacademy.org/genfiles/javascript/en/react-components-package-a7e18c.js","https://www.khanacademy.org/genfiles/javascript/en/flux-package-838d8f.js","https://www.khanacademy.org/genfiles/javascript/en/tasks-package-43bf44.js","https://www.khanacademy.org/genfiles/javascript/en/tutorial-package-8e5302.js","https://www.khanacademy.org/genfiles/javascript/en/video-package-9b200b.js","https://www.khanacademy.org/genfiles/javascript/en/content-library-package-9ac69b.js"],"path":"./javascript/content-library-package/components/concept-thumbnail.jsx","props":{"domain":"math","kind":"concept","progressData":{"skillsCompleted":3,"skillsTotal":32},"url":"/images/topic-icons-large/linear_equations.png"}}' 127.0.0.1:8080/render
*/
<|endoftext|>


<commit_before>if (window['bridge']) {

    bridge.previous.connect(player.control.previous);
    bridge.pause.connect(player.control.pause);
    bridge.next.connect(player.control.next);

}<commit_msg>Отключение (временное) wall.post в Десктопе.<commit_after>if (window['bridge']) {

    bridge.previous.connect(player.control.previous);
    bridge.pause.connect(player.control.pause);
    bridge.next.connect(player.control.next);

    // TODO fix this
    $(document).ready(function(){
        $('#menu_track__poststatus').remove();
        $('#menu_track__postwall').remove();
        $('#menu_station__poststatus').remove();
        $('#menu_station__postwall').remove();
    });

}<|endoftext|>


<commit_before>var NXAPIPacks = require('./api-connector/api-connector.js');

const najax = require('najax');
const iso6391Table = require('./data/iso639-1');

const EmojiFunctions = require('./emoji.js');

var AlchemyLanguageV1 = require('watson-developer-cloud/alchemy-language/v1');

var alchemyLangAnalysisAPIPack = function(apiInfo, packType) {
  // var alchemy_language;
  // var alchemy_params;

  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {

    var phrase = req.body.phrase;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      serverPack.alchemy_language = new AlchemyLanguageV1({
        "url": "https://gateway-a.watsonplatform.net/calls",
        api_key: process.env.IBM_ALCHEMY_API_KEY
      });

      serverPack.alchemy_params = {
        text: phrase
      };

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {

    serverPack.alchemy_language.language(serverPack.alchemy_params, function(err, response) {
      var resultObject;

      if (err) {
        // console.log('alchemy_api error:', err);
        apiResponse.result.score = -1;
        apiResponse.error = "Error received on API call.";
        resultObject = err;
      } else {
        var isoCode = response['iso-639-1'];
        var lang = iso6391Table[isoCode];
        apiResponse.result.score = (lang == undefined) ? isoCode : lang;

        // console.log(' alchemy_api: ok');
        resultObject = response;
      }
      apiResponse.serverResponse = resultObject;

      completion(apiResponse);
    });
  });

  return entitypack;
};

exports.alchemyLangAnalysisAPIPack = alchemyLangAnalysisAPIPack;

//Google

var googleLangAnalysisAPIPack = function(apiInfo, packType) {

  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {

    var phrase = req.body.phrase;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      baseAPIResponse.phrase = phrase;

      var gcloud_pid = process.env.GCLOUD_PROJECT;
      var privateKey = process.env.GOOGLE_CLOUD_PRIVATE_KEY.replace(/\\n/g, '\n');
      var clientEmail = process.env.GOOGLE_CLOUD_EMAIL;

      serverPack.gcloudConfig = {
        projectId: gcloud_pid,
        credentials: {
          client_email: clientEmail,
          private_key: privateKey
        }
      };
      serverPack.gcloud = require('google-cloud')(serverPack.gcloudConfig);

      // var translate = require('google-cloud/translate');

      var translateClient = serverPack.gcloud.translate({
        key: process.env.GOOGLE_NLP_API_KEY
      });
      var config = {
        verbose: true
      }; // Get more detailed results

      serverPack.gcloudParameters = {
        // language: language,
        doc: phrase,
        config: config
      };

      serverPack.translateClient = translateClient;

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {
    // See https://googlecloudplatform.github.io/google-cloud-node/#/docs/language/latest/language/document

    var language = serverPack.translateClient;
    var doc = serverPack.gcloudParameters.doc;
    var config = serverPack.gcloudParameters.config;

    serverPack.translateClient.detect(doc, function(err, results) {

      // console.log("entities = "+JSON.stringify(entities));
      var resultObject;
      if (err) {
        console.log('error:', err);
        apiResponse.result.score = -1;
        resultObject = err;
      } else {

        // results = {
        //   language: 'en',
        //   confidence: 1,
        //   input: 'Hello'
        // }
        var count = 0;
        var lang = iso6391Table[results.language];
        apiResponse.result.score = (lang == undefined) ? results.language : lang;
        resultObject = results;
      }

      apiResponse.serverResponse = resultObject;

      completion(apiResponse);
    });
  });

  return entitypack;
};

exports.googleLangAnalysisAPIPack = googleLangAnalysisAPIPack;

var msAzureLangAnalysisAPIPack = function(apiInfo, packType) {

  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {

    var phrase = req.body.phrase;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      baseAPIResponse.phrase = phrase;

      var azureCognitiveApiKey = process.env.MS_AZURE_COGNITIVE_SERVICES_API_KEY;

      // var textAnalytics = new cognitiveServices.textAnalytics({
      //     API_KEY: azureCognitiveApiKey
      // })
      var docBodyObj = {
        "documents": [{
          "language": "en",
          "id": "1",
          "text": phrase
        }]
      }
      var jsonData = JSON.stringify(docBodyObj);
      var params = {
        // Request parameters
      };

      serverPack.azureCognitiveApiKey = azureCognitiveApiKey;
      serverPack.azureJSONData = jsonData;
      serverPack.azureParameters = params;

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {
    najax({
        url: "https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/languages",
        dataType: "json",
        beforeSend: function(xhrObj) {
          // Request headers
          xhrObj.setRequestHeader("Content-Type", "application/json");
          xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", serverPack.azureCognitiveApiKey);
        },
        type: "POST",
        // Request body
        data: serverPack.azureJSONData,
      })
      .done(function(response) {

        apiResponse.serverResponse = response;

        apiResponse.result.score = -1;
        var detectedLanguages = (response.documents != undefined) ? response.documents[0].detectedLanguages : undefined;
        if (detectedLanguages != undefined && detectedLanguages.length > 0) {
          // var score = detectedLanguages[0].score;
          //returns values between 0 and 1
          var res = detectedLanguages[0]['iso6391Name'];

          var lang = iso6391Table[res];
          apiResponse.result.score = (lang == undefined) ? res : lang;

        }
        // var multiplier = (sentiment.polarity >= 0) ? 1 : -1;
        // responseData.result.score = sentiment.magnitude * multiplier;
        // console.log(JSON.stringify(response, null, 2));

        completion(apiResponse);

      })
      .fail(function(err) {

        console.error('MS Azure Sentiment - Encountered error making request:', err);

        apiResponse.result = Object();
        apiResponse.serverResponse = err;

        completion(apiResponse);

      });
  });

  return entitypack;
};

exports.msAzureLangAnalysisAPIPack = msAzureLangAnalysisAPIPack;

var googleLangTranslationAPIPack = function(apiInfo, packType) {

  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {

    var phrase = req.body.phrase;
    var xtra = req.body.xtra;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      baseAPIResponse.phrase = phrase;
      baseAPIResponse.language = xtra != undefined ? xtra : 'es';

      var gcloud_pid = process.env.GCLOUD_PROJECT;
      var privateKey = process.env.GOOGLE_CLOUD_PRIVATE_KEY.replace(/\\n/g, '\n');
      var clientEmail = process.env.GOOGLE_CLOUD_EMAIL;

      serverPack.gcloudConfig = {
        projectId: gcloud_pid,
        credentials: {
          client_email: clientEmail,
          private_key: privateKey
        }
      };
      serverPack.gcloud = require('google-cloud')(serverPack.gcloudConfig);

      // var translate = require('google-cloud/translate');

      var translateClient = serverPack.gcloud.translate({
        key: process.env.GOOGLE_NLP_API_KEY
      });
      var config = {
        verbose: true
      }; // Get more detailed results

      serverPack.gcloudParameters = {
        // language: language,
        doc: phrase,
        language: baseAPIResponse.language,
        config: config
      };

      serverPack.translateClient = translateClient;

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {
    // See https://googlecloudplatform.github.io/google-cloud-node/#/docs/language/latest/language/document

    var doc = serverPack.gcloudParameters.doc;
    var language = serverPack.gcloudParameters.language;
    var config = serverPack.gcloudParameters.config;

    serverPack.translateClient.translate(doc, language, function(err, results) {

      // console.log("entities = "+JSON.stringify(entities));
      var resultObject;
      if (err) {
        console.log('error:', err);
        apiResponse.result.score = -1;
        resultObject = err;
      } else {
        apiResponse.result.score = 'OK';
        resultObject = results;
      }

      apiResponse.serverResponse = resultObject;

      completion(apiResponse);
    });
  });

  return entitypack;
};

exports.googleLangTranslationAPIPack = googleLangTranslationAPIPack;

var baiduLangTranslationAPIPack = function(apiInfo, packType) {
  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {
    var phrase = req.body.phrase;
    var xtra = req.body.xtra;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      baseAPIResponse.phrase = phrase;
      baseAPIResponse.language = xtra != undefined ? xtra : 'spa';

      var baiduAppId = process.env.BAIDU_TRANSLATION_APP_ID;
      var baiduApiKey = process.env.BAIDU_TRANSLATION_KEY;

      serverPack.baiduAppId = baiduAppId;
      serverPack.baiduApiKey = baiduApiKey;
      serverPack.phrase = phrase;
      serverPack.language = baseAPIResponse.language;

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {
    najax({
        url: "https://fanyi-api.baidu.com/api/trans/vip/translate",
        type: "GET",
        // Request body
        data: {
          q: serverPack.phrase,
          from: 'auto',
          to: serverPack.language,
          appid: serverPack.baiduAppId
          // add salt and sig
        }
      })
      .done(function(response) {
        apiResponse.serverResponse = response.dst;
        apiResponse.result.score = 'OK';

        completion(apiResponse);

      })
      .fail(function(err) {

        console.error('Baidu Translation - Encountered error making request:', err);

        apiResponse.result = Object();
        apiResponse.serverResponse = err;

        completion(apiResponse);
      });

  return entitypack;
};

exports.baiduLangTranslationAPIPack = baiduLangTranslationAPIPack;
<commit_msg>fix scoping<commit_after>var NXAPIPacks = require('./api-connector/api-connector.js');

const najax = require('najax');
const iso6391Table = require('./data/iso639-1');

const EmojiFunctions = require('./emoji.js');

var AlchemyLanguageV1 = require('watson-developer-cloud/alchemy-language/v1');

var alchemyLangAnalysisAPIPack = function(apiInfo, packType) {
  // var alchemy_language;
  // var alchemy_params;

  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {

    var phrase = req.body.phrase;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      serverPack.alchemy_language = new AlchemyLanguageV1({
        "url": "https://gateway-a.watsonplatform.net/calls",
        api_key: process.env.IBM_ALCHEMY_API_KEY
      });

      serverPack.alchemy_params = {
        text: phrase
      };

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {

    serverPack.alchemy_language.language(serverPack.alchemy_params, function(err, response) {
      var resultObject;

      if (err) {
        // console.log('alchemy_api error:', err);
        apiResponse.result.score = -1;
        apiResponse.error = "Error received on API call.";
        resultObject = err;
      } else {
        var isoCode = response['iso-639-1'];
        var lang = iso6391Table[isoCode];
        apiResponse.result.score = (lang == undefined) ? isoCode : lang;

        // console.log(' alchemy_api: ok');
        resultObject = response;
      }
      apiResponse.serverResponse = resultObject;

      completion(apiResponse);
    });
  });

  return entitypack;
};

exports.alchemyLangAnalysisAPIPack = alchemyLangAnalysisAPIPack;

//Google

var googleLangAnalysisAPIPack = function(apiInfo, packType) {

  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {

    var phrase = req.body.phrase;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      baseAPIResponse.phrase = phrase;

      var gcloud_pid = process.env.GCLOUD_PROJECT;
      var privateKey = process.env.GOOGLE_CLOUD_PRIVATE_KEY.replace(/\\n/g, '\n');
      var clientEmail = process.env.GOOGLE_CLOUD_EMAIL;

      serverPack.gcloudConfig = {
        projectId: gcloud_pid,
        credentials: {
          client_email: clientEmail,
          private_key: privateKey
        }
      };
      serverPack.gcloud = require('google-cloud')(serverPack.gcloudConfig);

      // var translate = require('google-cloud/translate');

      var translateClient = serverPack.gcloud.translate({
        key: process.env.GOOGLE_NLP_API_KEY
      });
      var config = {
        verbose: true
      }; // Get more detailed results

      serverPack.gcloudParameters = {
        // language: language,
        doc: phrase,
        config: config
      };

      serverPack.translateClient = translateClient;

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {
    // See https://googlecloudplatform.github.io/google-cloud-node/#/docs/language/latest/language/document

    var language = serverPack.translateClient;
    var doc = serverPack.gcloudParameters.doc;
    var config = serverPack.gcloudParameters.config;

    serverPack.translateClient.detect(doc, function(err, results) {

      // console.log("entities = "+JSON.stringify(entities));
      var resultObject;
      if (err) {
        console.log('error:', err);
        apiResponse.result.score = -1;
        resultObject = err;
      } else {

        // results = {
        //   language: 'en',
        //   confidence: 1,
        //   input: 'Hello'
        // }
        var count = 0;
        var lang = iso6391Table[results.language];
        apiResponse.result.score = (lang == undefined) ? results.language : lang;
        resultObject = results;
      }

      apiResponse.serverResponse = resultObject;

      completion(apiResponse);
    });
  });

  return entitypack;
};

exports.googleLangAnalysisAPIPack = googleLangAnalysisAPIPack;

var msAzureLangAnalysisAPIPack = function(apiInfo, packType) {

  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {

    var phrase = req.body.phrase;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      baseAPIResponse.phrase = phrase;

      var azureCognitiveApiKey = process.env.MS_AZURE_COGNITIVE_SERVICES_API_KEY;

      // var textAnalytics = new cognitiveServices.textAnalytics({
      //     API_KEY: azureCognitiveApiKey
      // })
      var docBodyObj = {
        "documents": [{
          "language": "en",
          "id": "1",
          "text": phrase
        }]
      }
      var jsonData = JSON.stringify(docBodyObj);
      var params = {
        // Request parameters
      };

      serverPack.azureCognitiveApiKey = azureCognitiveApiKey;
      serverPack.azureJSONData = jsonData;
      serverPack.azureParameters = params;

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {
    najax({
        url: "https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/languages",
        dataType: "json",
        beforeSend: function(xhrObj) {
          // Request headers
          xhrObj.setRequestHeader("Content-Type", "application/json");
          xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", serverPack.azureCognitiveApiKey);
        },
        type: "POST",
        // Request body
        data: serverPack.azureJSONData,
      })
      .done(function(response) {

        apiResponse.serverResponse = response;

        apiResponse.result.score = -1;
        var detectedLanguages = (response.documents != undefined) ? response.documents[0].detectedLanguages : undefined;
        if (detectedLanguages != undefined && detectedLanguages.length > 0) {
          // var score = detectedLanguages[0].score;
          //returns values between 0 and 1
          var res = detectedLanguages[0]['iso6391Name'];

          var lang = iso6391Table[res];
          apiResponse.result.score = (lang == undefined) ? res : lang;

        }
        // var multiplier = (sentiment.polarity >= 0) ? 1 : -1;
        // responseData.result.score = sentiment.magnitude * multiplier;
        // console.log(JSON.stringify(response, null, 2));

        completion(apiResponse);

      })
      .fail(function(err) {

        console.error('MS Azure Sentiment - Encountered error making request:', err);

        apiResponse.result = Object();
        apiResponse.serverResponse = err;

        completion(apiResponse);

      });
  });

  return entitypack;
};

exports.msAzureLangAnalysisAPIPack = msAzureLangAnalysisAPIPack;

var googleLangTranslationAPIPack = function(apiInfo, packType) {

  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {

    var phrase = req.body.phrase;
    var xtra = req.body.xtra;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      baseAPIResponse.phrase = phrase;
      baseAPIResponse.language = xtra != undefined ? xtra : 'es';

      var gcloud_pid = process.env.GCLOUD_PROJECT;
      var privateKey = process.env.GOOGLE_CLOUD_PRIVATE_KEY.replace(/\\n/g, '\n');
      var clientEmail = process.env.GOOGLE_CLOUD_EMAIL;

      serverPack.gcloudConfig = {
        projectId: gcloud_pid,
        credentials: {
          client_email: clientEmail,
          private_key: privateKey
        }
      };
      serverPack.gcloud = require('google-cloud')(serverPack.gcloudConfig);

      // var translate = require('google-cloud/translate');

      var translateClient = serverPack.gcloud.translate({
        key: process.env.GOOGLE_NLP_API_KEY
      });
      var config = {
        verbose: true
      }; // Get more detailed results

      serverPack.gcloudParameters = {
        // language: language,
        doc: phrase,
        language: baseAPIResponse.language,
        config: config
      };

      serverPack.translateClient = translateClient;

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {
    // See https://googlecloudplatform.github.io/google-cloud-node/#/docs/language/latest/language/document

    var doc = serverPack.gcloudParameters.doc;
    var language = serverPack.gcloudParameters.language;
    var config = serverPack.gcloudParameters.config;

    serverPack.translateClient.translate(doc, language, function(err, results) {

      // console.log("entities = "+JSON.stringify(entities));
      var resultObject;
      if (err) {
        console.log('error:', err);
        apiResponse.result.score = -1;
        resultObject = err;
      } else {
        apiResponse.result.score = 'OK';
        resultObject = results;
      }

      apiResponse.serverResponse = resultObject;

      completion(apiResponse);
    });
  });

  return entitypack;
};

exports.googleLangTranslationAPIPack = googleLangTranslationAPIPack;

var baiduLangTranslationAPIPack = function(apiInfo, packType) {
  var entitypack = new NXAPIPacks.NXAPIPack(apiInfo, packType);

  entitypack.setAPIFunctionInitialize(function(serverPack, req, res, baseAPIResponse) {
    var phrase = req.body.phrase;
    var xtra = req.body.xtra;

    if (phrase != undefined && phrase.length > 0) {
      baseAPIResponse.inputDataPresent = "true";
      baseAPIResponse.phrase = phrase;
      baseAPIResponse.language = xtra != undefined ? xtra : 'spa';

      var baiduAppId = process.env.BAIDU_TRANSLATION_APP_ID;
      var baiduApiKey = process.env.BAIDU_TRANSLATION_KEY;

      serverPack.baiduAppId = baiduAppId;
      serverPack.baiduApiKey = baiduApiKey;
      serverPack.phrase = phrase;
      serverPack.language = baseAPIResponse.language;

      serverPack.setReady(true);
    } else {
      baseAPIResponse.error = "Error processing input data.";
    }

  });

  entitypack.setAPIFunctionExecute(function(serverPack, apiResponse, completion) {
    najax({
        url: "https://fanyi-api.baidu.com/api/trans/vip/translate",
        type: "GET",
        // Request body
        data: {
          q: serverPack.phrase,
          from: 'auto',
          to: serverPack.language,
          appid: serverPack.baiduAppId
          // add salt and sig
        }
      })
      .done(function(response) {
        apiResponse.serverResponse = response.dst;
        apiResponse.result.score = 'OK';

        completion(apiResponse);

      })
      .fail(function(err) {

        console.error('Baidu Translation - Encountered error making request:', err);

        apiResponse.result = Object();
        apiResponse.serverResponse = err;

        completion(apiResponse);
      });

  return entitypack;
  });
}

exports.baiduLangTranslationAPIPack = baiduLangTranslationAPIPack;
<|endoftext|>


<commit_before>module.exports = {
  // Binds a listener to a component's resource so the component can be updated
  // when the resource changes.
  //
  // An object that uses this mixin must implement `getBackboneModels` and
  // return an object that extends `Backbone.Events`. Common use cases are
  // `Backbone.Model` and `Backbone.Collection`.
  componentDidMount: function() {
    this._boundForceUpdate = this.forceUpdate.bind(this, null);
    this.getBackboneModels().forEach(function(model) {
      // There are more events that we can listen on. For most cases, we're
      // fetching pages of data, listening to add events causes superfluous
      // calls to render.
      model.on("batch reset", this._boundForceUpdate, this);
      model.fetch({ reset: true });
    }, this);
  },

  componentWillUnmount: function() {
    this.getBackboneModels().forEach(function(model) {
      model.off("batch reset", this._boundForceUpdate, this);
    }, this);
  }
};
<commit_msg>Updating backbone mixing to autohandle common cases<commit_after>var _ = require("underscore");

var BackboneMixin = {
  resolveModels: function() {
    var models = [this.props.model, this.props.collection];

    if (_.isFunction(this.getBackboneModels)) {
      models = _.union(models, this.getBackboneModels());
    }

    models = _.filter(models, function(model) {
      if (model != null) {
        return model;
      }
    });

    return models;
  },
  // Binds a listener to a component's resource so the component can be updated
  // when the resource changes.
  //
  // An object that uses this mixin must implement `getBackboneModels` and
  // return an object that extends `Backbone.Events`. Common use cases are
  // `Backbone.Model` and `Backbone.Collection`.
  componentDidMount: function() {
    this._boundForceUpdate = this.forceUpdate.bind(this, null);
    var models = this.resolveModels();
    models.forEach(function(model) {
      // There are more events that we can listen on. For most cases, we're
      // fetching pages of data, listening to add events causes superfluous
      // calls to render.
      model.on("batch reset sync", this._boundForceUpdate, this);
      model.fetch({ reset: true });
    }, this);
  },

  componentWillUnmount: function() {
    var models = this.resolveModels();
    models.forEach(function(model) {
      model.off("batch reset sync", this._boundForceUpdate, this);
    }, this);
  }
};

module.exports = BackboneMixin;
<|endoftext|>


<commit_before>const badge = require('gh-badges');
const path = require('path');
const fs = require('fs');
const { promisify } = require('util');
const { percentageToColor } = require('./calculations');
const ReportGeneratorV2 = require('../node_modules/lighthouse/lighthouse-core/report/v2/report-generator');
const exec = promisify(require('child_process').exec);

// Buffer size for stdout, must be big enough to handle lighthouse CLI output
const maxBuffer = 1024 * 5000;

async function metricsToSvg(lighthouseMetrics, badgeStyle) {
  const metricKeys = Object.keys(lighthouseMetrics);
  for (let i = 0; i < metricKeys.length; i += 1) {
    const badgeColor = percentageToColor(lighthouseMetrics[metricKeys[i]]);
    const badgeText = [metricKeys[i], `${lighthouseMetrics[metricKeys[i]]}%`];

    badge.loadFont(path.join(__dirname, '..', 'assets', 'fonts', 'Verdana.ttf'), (err) => {
      if (err) {
        throw err;
      }
      badge({ text: badgeText, colorscheme: badgeColor, template: badgeStyle }, (svg, err) => {
        if (err) {
          throw err;
        }
        const filepath = path.join(process.cwd(), `${metricKeys[i].replace(/ /g, '_')}.svg`);
        fs.writeFile(filepath, svg, (err) => {
          if (err) {
            return console.log(err);
          }
          return console.log(`Saved file to ${filepath}`);
        });
      });
    });
  }
}

async function htmlReportsToFile(htmlReports) {
  for (let i = 0; i < htmlReports.length; i += 1) {
    const url = Object.keys(htmlReports[i])[0];
    const report = Object.values(htmlReports[i])[0];
    const escapedUrl = url.toLowerCase().replace(/(^\w+:|^)\/\//, '').replace(/[^a-z0-9]/g, '_');
    const filepath = path.join(process.cwd(), `${escapedUrl}.html`);
    fs.writeFile(filepath, report, (err) => {
      if (err) {
        return console.log(err);
      }
      return console.log(`Saved report to ${filepath}`);
    });
  }
}

async function getLighthouseMetrics(url, htmlReportToggle) {
  let htmlReport = false;
  const lighthouseMetrics = {};
  const lighthouseBinary = path.join(__dirname, '..', 'node_modules', '.bin', 'lighthouse');
  const params = '--chrome-flags=\'--headless\' --output=json --output-path=stdout --quiet';
  const lighthouseCommand = `${lighthouseBinary} ${params} ${url}`;
  try {
    const { stdout } = await exec(`${lighthouseCommand}`, { maxBuffer });
    const results = JSON.parse(stdout);
    if (htmlReportToggle) {
      htmlReport = new ReportGeneratorV2().generateReportHtml(results);
    }
    const { reportCategories } = results;
    for (let i = 0; i < reportCategories.length; i += 1) {
      lighthouseMetrics[`lighthouse ${reportCategories[i].name.toLowerCase()}`] = reportCategories[i].score;
    }
    return { metrics: lighthouseMetrics, report: { [url]: htmlReport } };
  } catch (err) {
    throw err;
  }
}

module.exports = {
  metricsToSvg,
  htmlReportsToFile,
  getLighthouseMetrics,
};
<commit_msg>Fix creation of empty files<commit_after>const badge = require('gh-badges');
const path = require('path');
const fs = require('fs');
const { promisify } = require('util');
const { percentageToColor } = require('./calculations');
const ReportGeneratorV2 = require('../node_modules/lighthouse/lighthouse-core/report/v2/report-generator');
const exec = promisify(require('child_process').exec);

// Buffer size for stdout, must be big enough to handle lighthouse CLI output
const maxBuffer = 1024 * 5000;

async function metricsToSvg(lighthouseMetrics, badgeStyle) {
  const metricKeys = Object.keys(lighthouseMetrics);
  for (let i = 0; i < metricKeys.length; i += 1) {
    const badgeColor = percentageToColor(lighthouseMetrics[metricKeys[i]]);
    const badgeText = [metricKeys[i], `${lighthouseMetrics[metricKeys[i]]}%`];

    badge.loadFont(path.join(__dirname, '..', 'assets', 'fonts', 'Verdana.ttf'), (err) => {
      if (err) {
        throw err;
      }
      badge({ text: badgeText, colorscheme: badgeColor, template: badgeStyle }, (svg, err) => {
        if (err) {
          throw err;
        }
        const filepath = path.join(process.cwd(), `${metricKeys[i].replace(/ /g, '_')}.svg`);
        fs.writeFile(filepath, svg, (err) => {
          if (err) {
            return console.log(err);
          }
          return console.log(`Saved file to ${filepath}`);
        });
      });
    });
  }
}

async function htmlReportsToFile(htmlReports) {
  for (let i = 0; i < htmlReports.length; i += 1) {
    const report = Object.values(htmlReports[i])[0];
    if (report) {
      const url = Object.keys(htmlReports[i])[0];
      const escapedUrl = url.toLowerCase().replace(/(^\w+:|^)\/\//, '').replace(/[^a-z0-9]/g, '_');
      const filepath = path.join(process.cwd(), `${escapedUrl}.html`);
      fs.writeFile(filepath, report, (err) => {
        if (err) {
          return console.log(err);
        }
        return console.log(`Saved report to ${filepath}`);
      });
    }
  }
}

async function getLighthouseMetrics(url, htmlReportToggle) {
  let htmlReport = false;
  const lighthouseMetrics = {};
  const lighthouseBinary = path.join(__dirname, '..', 'node_modules', '.bin', 'lighthouse');
  const params = '--chrome-flags=\'--headless\' --output=json --output-path=stdout --quiet';
  const lighthouseCommand = `${lighthouseBinary} ${params} ${url}`;
  try {
    const { stdout } = await exec(`${lighthouseCommand}`, { maxBuffer });
    const results = JSON.parse(stdout);
    if (htmlReportToggle) {
      htmlReport = new ReportGeneratorV2().generateReportHtml(results);
    }
    const { reportCategories } = results;
    for (let i = 0; i < reportCategories.length; i += 1) {
      lighthouseMetrics[`lighthouse ${reportCategories[i].name.toLowerCase()}`] = reportCategories[i].score;
    }
    return { metrics: lighthouseMetrics, report: { [url]: htmlReport } };
  } catch (err) {
    throw err;
  }
}

module.exports = {
  metricsToSvg,
  htmlReportsToFile,
  getLighthouseMetrics,
};
<|endoftext|>


<commit_before>//fix for double click stack traces in IE - SAK-10625
sak10625_disabler = function(){
	 $("a, input[type=button], input[type=submit]").attr("onclick", "");
}
if (typeof window.jQuery != "undefined") {

$(document).ready(function(){
	$("a").filter(function(){regexp=/submit\(\)/; return regexp.test($(this).attr("onclick"));}).bind("click", sak10625_disabler);
	 $("input[type=button], input[type=submit]").bind("click", sak10625_disabler);
});
    }
<commit_msg>SAK-28168 - Double clicking links in chrome freezes forums<commit_after>//fix for double click stack traces in IE - SAK-10625
var click=0;
sak10625_disabler = function(){
  var existing_event = this.onclick;
  this.onclick = null;
  if(existing_event) $(this).click(existing_event);
}
if (typeof window.jQuery != "undefined") {

$(document).ready(function(){
	$("a").filter(function(){regexp=/submit\(\)/; return regexp.test($(this).attr("onclick"));}).bind("click", sak10625_disabler);
	 $("input[type=button], input[type=submit]").bind("click", sak10625_disabler);
});
    }
<|endoftext|>


<commit_before>/*
 * SimplePlugin.js: Example for an external Squeak VM module
 *
 * primNavigatorInfo: anInteger
 *     <primitive: 'primitiveNavigatorInfo' module: 'SimplePlugin'>
 *     ^ self primitiveFailed
 */

var SimplePlugin = function() {
    var proxy;

    function initializeModule(interpreterProxy) {
        // interpreterProxy is vm.primHandler - might change to a real proxy later?
        proxy = interpreterProxy;
    };

    function primitiveNavigatorInfo(argCount) {
        if (argCount !== 1) return false; // fail
        var which = proxy.stackInteger(0);
        if (!proxy.success) return false; // fail
        var result;
        switch (which) {
            case 1: result = navigator.userAgent; break;
            case 2: result = navigator.language; break;
        }
        if (!result) return false; // fail
        var resultObj = proxy.makeStString(result);
        proxy.vm.popNandPush(1 + argCount, resultObj);
        return true; // success
    };

    return {
        initializeModule: initializeModule,
        primitiveNavigatorInfo: primitiveNavigatorInfo,
    }
};

// register plugin in global Squeak object
Squeak.registerExternalModule('SimplePlugin', SimplePlugin());

/**********************************
NOTE: the mini.image does not have compiler support for
named primitives, yet. You need to declare it manually
using prim 117:

primNavigatorInfo: anInteger
    <primitive: 117>
    #(SimplePlugin primitiveNavigatorInfo 0 0).
    ^ self primitiveFailed
***********************************/
<commit_msg>SimplePlugin: clarify<commit_after>/*
 * SimplePlugin.js: Example for an external Squeak VM module
 *
 * primNavigatorInfo: anInteger
 *     <primitive: 'primitiveNavigatorInfo' module: 'SimplePlugin'>
 *     ^ self primitiveFailed
 */

var SimplePlugin = function() {
    var proxy;

    function initializeModule(interpreterProxy) {
        // interpreterProxy is vm.primHandler - might change to a real proxy later?
        proxy = interpreterProxy;
    };

    function primitiveNavigatorInfo(argCount) {
        if (argCount !== 1) return false; // fail
        var which = proxy.stackInteger(0);
        if (!proxy.success) return false; // fail
        var result = this.getNavigatorInfo(which);
        if (!result) return false; // fail
        var resultObj = proxy.makeStString(result);
        proxy.popNandPushIfOK(1 + argCount, resultObj);
        return true; // success
    };

    function getNavigatorInfo(index) {
        switch (index) {
            case 1: return navigator.userAgent;
            case 2: return navigator.language;
        }
    };

    // hide private functions
    return {
        initializeModule: initializeModule.bind(this),
        primitiveNavigatorInfo: primitiveNavigatorInfo.bind(this),
    }
};

// register plugin in global Squeak object
Squeak.registerExternalModule('SimplePlugin', SimplePlugin());

/**********************************
NOTE: the mini.image does not have compiler support for
named primitives, yet. You need to declare it manually
using prim 117:

primNavigatorInfo: anInteger
    <primitive: 117>
    #(SimplePlugin primitiveNavigatorInfo 0 0).
    ^ self primitiveFailed
***********************************/
<|endoftext|>


<commit_before>/*global WeakMap*/
import { arr, string, obj } from "lively.lang";
import { connect, disconnect } from "lively.bindings";

function newKeyIn(obj, base = "_") {
  var i = 1, key;
  do {
    key = base + "-" + i++;
  } while (key in obj);
  return key;
}

function signalBindings(obj, name, change) {
  // optimized lively.bindings.signal
  var conns = obj.attributeConnections;
  if (!conns) return
  conns = conns.slice();
  for (var i = 0; i < conns.length; i++) {
    if (conns[i].sourceAttrName === name)
      conns[i].update(change);
    if (change.prop && conns[i].sourceAttrName === change.prop)
      conns[i].update(change.value);
  }
}

function informMorph(changeManager, change, morph) {
  try {
    morph.onChange(change);
    signalBindings(morph, "change", change);
    var owner = morph.owner;
    while (owner) {
      owner.onSubmorphChange(change, morph);
      owner = owner.owner;
    }
  } catch (err) {
    console.error(`Error in informMorph: ${err.stack}`)
  }
}

class Change {
  constructor(target) {
    this.target = target;
    this.group = null;
  }
  get type() { return "abstract change" }
  apply() { throw new Error("Not yet implemented"); }
  reverseApply() { throw new Error("Not yet implemented"); }
}

export class GroupChange extends Change {
  constructor(target) {
    super(target);
    this.changes = [];
  }

  consumesChanges() { return true }

  addChange(c) {
    this.changes.push(c);
    c.group = this;
  }

  apply() {
    this.changes.slice().forEach(change => change.apply());
    return this;
  }

  reverseApply() {
    this.changes.slice().reverse().forEach(change => change.reverseApply());
    return this;
  }
}

export class ValueChange extends Change {

  get type() { return "setter" }

  constructor(target, prop, value, meta) {
    super(target);
    this.prop = prop;
    this.value = value;
    this.prevValue = null;
    this.meta = meta;
  }

  apply() {
    var {target, prop, value} = this;
    target[prop] = value;
  }

  reverseApply() {
    var {target, prop, prevValue} = this;
    target[prop] = prevValue;
  }
}

export class MethodCallChange extends GroupChange {

  get type() { return "method-call" }

  constructor(target, selector, args, undo, meta) {
    super(target);
    this.selector = selector;
    this.args = args;
    this.undo = undo;
    this.meta = meta;
  }

  apply() {
    var {target, selector, args} = this;
    target[selector].apply(target, args);
  }

  reverseApply() {
    if (!this.undo) return;
    if (typeof this.undo === "function") this.undo();
    else {
      var {target, selector, args} = this.undo;
      target[selector].apply(target, args);
    }
  }

}

export class ChangeManager {

  constructor() {
    this.reset();
  }

  reset() {
    this.changes = [];
    this.revision = 0;

    this.changeRecordersPerMorph = new WeakMap();
    this.changeRecorders = {};

    this.changeGroupStack = [];
    this.defaultMeta = {};
    this.metaStack = [];
  }

  changesFor(morph) { return this.changes.filter(c => c.target === morph); }

  apply(target, change) { change.apply(); }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // interface for adding changes, used by morphs

  doWithValueChangeMeta(meta, morph, doFn) {
     this.defaultMeta = meta;
     this.metaStack.push(meta);
     const res = doFn(morph);
     this.metaStack.pop();
     this.defaultMeta = arr.last(this.metaStack) || {};
     return res;
  }

  addValueChange(morph, prop, value, meta) {
    var change = new ValueChange(morph, prop, value, {...this.defaultMeta, ...meta});
    return this._record(morph, change);
  }

  addMethodCallChangeDoing(spec, morph, doFn) {
    var {target, selector, args, undo} = spec;
    if (!undo) undo = () => console.warn(`No undo recorded for ${target}.${selector}`);
    var change = new MethodCallChange(target, selector, args, undo, this.defaultMeta);
    morph.groupChangesWhile(change, doFn);
    return change;
  }

  _record(morph, change) {
    // FIXME
    if (change.hasOwnProperty("value")) {
      change.prevValue = morph._morphicState[change.prop];
      morph._morphicState[change.prop] = change.value;
    }

    morph.makeDirty();

    var grouping = arr.last(this.changeGroupStack);
    if (grouping && grouping.consumesChanges()) {
      grouping.addChange(change);
    } else {
      this.changes.push(change);
      morph._rev = ++this.revision;
      this.informChangeListeners(change)
    }
    informMorph(this, change, morph);

    return change;
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // group changes

  groupChangesWhile(targetMorph, groupChange, whileFn, record = true) {
    if (!groupChange) groupChange = new GroupChange(targetMorph);
    this.changeGroupStack.push(groupChange);
    try {
      whileFn();
      arr.remove(this.changeGroupStack, groupChange);
      return record ? this._record(targetMorph, groupChange) : groupChange;
    } catch (err) {
      arr.remove(this.changeGroupStack, groupChange);
      throw err;
    }
  }

  dontRecordChangesWhile(targetMorph, whileFn) {
    return this.groupChangesWhile(targetMorph, undefined, whileFn, false);
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // listen for changes / record changes

  recordChangesWhile(whileFn, optFilter) {
    var from = this.changes.length;
    whileFn();
    var changes = this.changes.slice(from, this.changes.length);
    return optFilter ? changes.filter(optFilter) : changes;
  }

  addChangeListener(listenFn) {
    connect(this, 'changeRecorded', listenFn, 'call', {
      updater: ($upd, change) => $upd(null, change)});
  }

  removeChangeListener(listenFn) {
    disconnect(this, 'changeRecorded', listenFn, 'call');
  }

  informChangeListeners(change) {
    // optimized version if lively.binings.signal
    var conns = this.attributeConnections;
    if (!conns) return;
    conns = conns.slice();
    for (var i = 0; i < conns.length; i++) {
      var c = conns[i];
      if (c.sourceAttrName === "changeRecorded")
        c.update(change);
    }
  }

  recordChangesStart(optFilter, optName = "") {
    // change recorder is a change listener that is identified by id

    // Recorder object to be used to record specific changes when they occur,
    // based on change listeners
    var id = newKeyIn(this.changeRecorders, optName + "__change_recorder_" + Date.now()),
        listener = optFilter ?
          change => optFilter(change) && recorder.changes.push(change) :
          change => recorder.changes.push(change),
        recorder = this.changeRecorders[id] = {id, filter: optFilter, changes: [], listener};

    this.addChangeListener(listener);

    return recorder;
  }

  recordChangesStop(id) {
    if (!(id in this.changeRecorders)) return [];
    var {changes, listener} = this.changeRecorders[id];
    delete this.changeRecorders[id];
    this.removeChangeListener(listener);
    return changes;
  }

  recordChangesStartForMorph(morph, optFilter) {
    var recorder = this.recordChangesStart(optFilter, morph.id);

    // store recorder alongside morph for easy lookup and
    // to make it easy to just start / stop recordings
    // without having to manage listener storage and its lifetime

    var perMorph = this.changeRecordersPerMorph.get(morph);
    if (!perMorph) {
      perMorph = [];
      this.changeRecordersPerMorph.set(morph, perMorph);
    }
    perMorph.push(recorder.id);

    return recorder;
  }

  recordChangesStopForMorph(morph, optId) {
    var perMorph = this.changeRecordersPerMorph.get(morph);
    if (!perMorph || !perMorph.length) {
      console.warn(`Cannot endMorphChangeRecorder for morph ${morph}: recorder not found`)
      return [];
    }

    var id = optId;
    if (!optId) id = perMorph.pop();
    else arr.remove(perMorph, id);

    return this.recordChangesStop(id);
  }

}
<commit_msg>using newKeyIn from lively.lang<commit_after>/*global WeakMap*/
import { arr, string, obj } from "lively.lang";
import { connect, disconnect } from "lively.bindings";

function signalBindings(obj, name, change) {
  // optimized lively.bindings.signal
  var conns = obj.attributeConnections;
  if (!conns) return
  conns = conns.slice();
  for (var i = 0; i < conns.length; i++) {
    if (conns[i].sourceAttrName === name)
      conns[i].update(change);
    if (change.prop && conns[i].sourceAttrName === change.prop)
      conns[i].update(change.value);
  }
}

function informMorph(changeManager, change, morph) {
  try {
    morph.onChange(change);
    signalBindings(morph, "change", change);
    var owner = morph.owner;
    while (owner) {
      owner.onSubmorphChange(change, morph);
      owner = owner.owner;
    }
  } catch (err) {
    console.error(`Error in informMorph: ${err.stack}`)
  }
}

class Change {
  constructor(target) {
    this.target = target;
    this.group = null;
  }
  get type() { return "abstract change" }
  apply() { throw new Error("Not yet implemented"); }
  reverseApply() { throw new Error("Not yet implemented"); }
}

export class GroupChange extends Change {
  constructor(target) {
    super(target);
    this.changes = [];
  }

  consumesChanges() { return true }

  addChange(c) {
    this.changes.push(c);
    c.group = this;
  }

  apply() {
    this.changes.slice().forEach(change => change.apply());
    return this;
  }

  reverseApply() {
    this.changes.slice().reverse().forEach(change => change.reverseApply());
    return this;
  }
}

export class ValueChange extends Change {

  get type() { return "setter" }

  constructor(target, prop, value, meta) {
    super(target);
    this.prop = prop;
    this.value = value;
    this.prevValue = null;
    this.meta = meta;
  }

  apply() {
    var {target, prop, value} = this;
    target[prop] = value;
  }

  reverseApply() {
    var {target, prop, prevValue} = this;
    target[prop] = prevValue;
  }
}

export class MethodCallChange extends GroupChange {

  get type() { return "method-call" }

  constructor(target, selector, args, undo, meta) {
    super(target);
    this.selector = selector;
    this.args = args;
    this.undo = undo;
    this.meta = meta;
  }

  apply() {
    var {target, selector, args} = this;
    target[selector].apply(target, args);
  }

  reverseApply() {
    if (!this.undo) return;
    if (typeof this.undo === "function") this.undo();
    else {
      var {target, selector, args} = this.undo;
      target[selector].apply(target, args);
    }
  }

}

export class ChangeManager {

  constructor() {
    this.reset();
  }

  reset() {
    this.changes = [];
    this.revision = 0;

    this.changeRecordersPerMorph = new WeakMap();
    this.changeRecorders = {};

    this.changeGroupStack = [];
    this.defaultMeta = {};
    this.metaStack = [];
  }

  changesFor(morph) { return this.changes.filter(c => c.target === morph); }

  apply(target, change) { change.apply(); }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // interface for adding changes, used by morphs

  doWithValueChangeMeta(meta, morph, doFn) {
     this.defaultMeta = meta;
     this.metaStack.push(meta);
     const res = doFn(morph);
     this.metaStack.pop();
     this.defaultMeta = arr.last(this.metaStack) || {};
     return res;
  }

  addValueChange(morph, prop, value, meta) {
    var change = new ValueChange(morph, prop, value, {...this.defaultMeta, ...meta});
    return this._record(morph, change);
  }

  addMethodCallChangeDoing(spec, morph, doFn) {
    var {target, selector, args, undo} = spec;
    if (!undo) undo = () => console.warn(`No undo recorded for ${target}.${selector}`);
    var change = new MethodCallChange(target, selector, args, undo, this.defaultMeta);
    morph.groupChangesWhile(change, doFn);
    return change;
  }

  _record(morph, change) {
    // FIXME
    if (change.hasOwnProperty("value")) {
      change.prevValue = morph._morphicState[change.prop];
      morph._morphicState[change.prop] = change.value;
    }

    morph.makeDirty();

    var grouping = arr.last(this.changeGroupStack);
    if (grouping && grouping.consumesChanges()) {
      grouping.addChange(change);
    } else {
      this.changes.push(change);
      morph._rev = ++this.revision;
      this.informChangeListeners(change)
    }
    informMorph(this, change, morph);

    return change;
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // group changes

  groupChangesWhile(targetMorph, groupChange, whileFn, record = true) {
    if (!groupChange) groupChange = new GroupChange(targetMorph);
    this.changeGroupStack.push(groupChange);
    try {
      whileFn();
      arr.remove(this.changeGroupStack, groupChange);
      return record ? this._record(targetMorph, groupChange) : groupChange;
    } catch (err) {
      arr.remove(this.changeGroupStack, groupChange);
      throw err;
    }
  }

  dontRecordChangesWhile(targetMorph, whileFn) {
    return this.groupChangesWhile(targetMorph, undefined, whileFn, false);
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // listen for changes / record changes

  recordChangesWhile(whileFn, optFilter) {
    var from = this.changes.length;
    whileFn();
    var changes = this.changes.slice(from, this.changes.length);
    return optFilter ? changes.filter(optFilter) : changes;
  }

  addChangeListener(listenFn) {
    connect(this, 'changeRecorded', listenFn, 'call', {
      updater: ($upd, change) => $upd(null, change)});
  }

  removeChangeListener(listenFn) {
    disconnect(this, 'changeRecorded', listenFn, 'call');
  }

  informChangeListeners(change) {
    // optimized version if lively.binings.signal
    var conns = this.attributeConnections;
    if (!conns) return;
    conns = conns.slice();
    for (var i = 0; i < conns.length; i++) {
      var c = conns[i];
      if (c.sourceAttrName === "changeRecorded")
        c.update(change);
    }
  }

  recordChangesStart(optFilter, optName = "") {
    // change recorder is a change listener that is identified by id

    // Recorder object to be used to record specific changes when they occur,
    // based on change listeners
    var id = obj.newKeyIn(this.changeRecorders, optName + "__change_recorder_" + Date.now()),
        listener = optFilter ?
          change => optFilter(change) && recorder.changes.push(change) :
          change => recorder.changes.push(change),
        recorder = this.changeRecorders[id] = {id, filter: optFilter, changes: [], listener};

    this.addChangeListener(listener);

    return recorder;
  }

  recordChangesStop(id) {
    if (!(id in this.changeRecorders)) return [];
    var {changes, listener} = this.changeRecorders[id];
    delete this.changeRecorders[id];
    this.removeChangeListener(listener);
    return changes;
  }

  recordChangesStartForMorph(morph, optFilter) {
    var recorder = this.recordChangesStart(optFilter, morph.id);

    // store recorder alongside morph for easy lookup and
    // to make it easy to just start / stop recordings
    // without having to manage listener storage and its lifetime

    var perMorph = this.changeRecordersPerMorph.get(morph);
    if (!perMorph) {
      perMorph = [];
      this.changeRecordersPerMorph.set(morph, perMorph);
    }
    perMorph.push(recorder.id);

    return recorder;
  }

  recordChangesStopForMorph(morph, optId) {
    var perMorph = this.changeRecordersPerMorph.get(morph);
    if (!perMorph || !perMorph.length) {
      console.warn(`Cannot endMorphChangeRecorder for morph ${morph}: recorder not found`)
      return [];
    }

    var id = optId;
    if (!optId) id = perMorph.pop();
    else arr.remove(perMorph, id);

    return this.recordChangesStop(id);
  }

}
<|endoftext|>