<commit_before>define([
	"require",
	"dojo/colors", // colors.fromRgb
	"dojo/_base/declare", // declare
	"dojo/_base/lang",
	"../_Plugin",
	"../../form/DropDownButton"
], function(require, colors, declare, lang, _Plugin, DropDownButton){

// module:
//		dijit/_editor/plugins/TextColor

var TextColor = declare("dijit._editor.plugins.TextColor", _Plugin, {
	// summary:
	//		This plugin provides dropdown color pickers for setting text color and background color
	// description:
	//		The commands provided by this plugin are:
	//
	//		- foreColor - sets the text color
	//		- hiliteColor - sets the background color

	// Override _Plugin.buttonClass to use DropDownButton (with ColorPalette) to control this plugin
	buttonClass: DropDownButton,

	// useDefaultCommand: Boolean
	//		False as we do not use the default editor command/click behavior.
	useDefaultCommand: false,

	_initButton: function(){
		this.inherited(arguments);

		// Setup to lazy load ColorPalette first time the button is clicked
		var self = this;
		this.button.loadDropDown = function(callback){
			require(["../../ColorPalette"], lang.hitch(this, function(ColorPalette){
				this.dropDown = new ColorPalette({
					dir: self.editor.isLeftToRight() ? "" : "rtl",
					ownerDocument: self.editor.ownerDocument,
					value: self.value,
					onChange: function(color){
						self.editor.execCommand(self.command, color);
					}
				});
				callback();
			}));
		};
	},

	updateState: function(){
		// summary:
		//		Overrides _Plugin.updateState().  This updates the ColorPalette
		//		to show the color of the currently selected text.
		// tags:
		//		protected

		var _e = this.editor;
		var _c = this.command;
		if(!_e || !_e.isLoaded || !_c.length){
			return;
		}

		if(this.button){
			var disabled = this.get("disabled");
			this.button.set("disabled", disabled);
			if(disabled){ return; }

			var value;
			try{
				value = _e.queryCommandValue(_c)|| "";
			}catch(e){
				//Firefox may throw error above if the editor is just loaded, ignore it
				value = "";
			}
		}

		if(value == ""){
			value = "#000000";
		}
		if(value == "transparent"){
			value = "#ffffff";
		}

		if(typeof value == "string"){
			//if RGB value, convert to hex value
			if(value.indexOf("rgb")> -1){
				value = colors.fromRgb(value).toHex();
			}
		}else{	//it's an integer(IE returns an MS access #)
			value =((value & 0x0000ff)<< 16)|(value & 0x00ff00)|((value & 0xff0000)>>> 16);
			value = value.toString(16);
			value = "#000000".slice(0, 7 - value.length)+ value;

		}

		this.value = value;

		var dropDown = this.button.dropDown;
		if(dropDown && value !== dropDown.get('value')){
			dropDown.set('value', value, false);
		}
	}
});

// Register this plugin.
_Plugin.registry["foreColor"] = function(){
	return new TextColor({command: "foreColor"});
};
_Plugin.registry["hiliteColor"] = function(){
	return new TextColor({command: "hiliteColor"});
};

return TextColor;
});
<commit_msg>Use Bill's suggested way instead of calling directional test API.  refs #15978<commit_after>define([
	"require",
	"dojo/colors", // colors.fromRgb
	"dojo/_base/declare", // declare
	"dojo/_base/lang",
	"../_Plugin",
	"../../form/DropDownButton"
], function(require, colors, declare, lang, _Plugin, DropDownButton){

// module:
//		dijit/_editor/plugins/TextColor

var TextColor = declare("dijit._editor.plugins.TextColor", _Plugin, {
	// summary:
	//		This plugin provides dropdown color pickers for setting text color and background color
	// description:
	//		The commands provided by this plugin are:
	//
	//		- foreColor - sets the text color
	//		- hiliteColor - sets the background color

	// Override _Plugin.buttonClass to use DropDownButton (with ColorPalette) to control this plugin
	buttonClass: DropDownButton,

	// useDefaultCommand: Boolean
	//		False as we do not use the default editor command/click behavior.
	useDefaultCommand: false,

	_initButton: function(){
		this.inherited(arguments);

		// Setup to lazy load ColorPalette first time the button is clicked
		var self = this;
		this.button.loadDropDown = function(callback){
			require(["../../ColorPalette"], lang.hitch(this, function(ColorPalette){
				this.dropDown = new ColorPalette({
					dir: self.editor.dir,
					ownerDocument: self.editor.ownerDocument,
					value: self.value,
					onChange: function(color){
						self.editor.execCommand(self.command, color);
					}
				});
				callback();
			}));
		};
	},

	updateState: function(){
		// summary:
		//		Overrides _Plugin.updateState().  This updates the ColorPalette
		//		to show the color of the currently selected text.
		// tags:
		//		protected

		var _e = this.editor;
		var _c = this.command;
		if(!_e || !_e.isLoaded || !_c.length){
			return;
		}

		if(this.button){
			var disabled = this.get("disabled");
			this.button.set("disabled", disabled);
			if(disabled){ return; }

			var value;
			try{
				value = _e.queryCommandValue(_c)|| "";
			}catch(e){
				//Firefox may throw error above if the editor is just loaded, ignore it
				value = "";
			}
		}

		if(value == ""){
			value = "#000000";
		}
		if(value == "transparent"){
			value = "#ffffff";
		}

		if(typeof value == "string"){
			//if RGB value, convert to hex value
			if(value.indexOf("rgb")> -1){
				value = colors.fromRgb(value).toHex();
			}
		}else{	//it's an integer(IE returns an MS access #)
			value =((value & 0x0000ff)<< 16)|(value & 0x00ff00)|((value & 0xff0000)>>> 16);
			value = value.toString(16);
			value = "#000000".slice(0, 7 - value.length)+ value;

		}

		this.value = value;

		var dropDown = this.button.dropDown;
		if(dropDown && value !== dropDown.get('value')){
			dropDown.set('value', value, false);
		}
	}
});

// Register this plugin.
_Plugin.registry["foreColor"] = function(){
	return new TextColor({command: "foreColor"});
};
_Plugin.registry["hiliteColor"] = function(){
	return new TextColor({command: "hiliteColor"});
};

return TextColor;
});
<|endoftext|>


<commit_before>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('unisubs.translate.Dialog');

/**
 * @constructor
 *
 */
unisubs.translate.Dialog = function(opener,
                                     serverModel,
                                     videoSource,
                                     subtitleState,
                                     standardSubState) {
    unisubs.Dialog.call(this, videoSource);
    unisubs.SubTracker.getInstance().start(true);
    this.opener_ = opener;
    this.subtitleState_ = subtitleState;
    this.standardSubState_ = standardSubState;

    this.serverModel_ = serverModel;
    this.serverModel_.init();
    this.saved_ = false;
    this.rightPanelListener_ = new goog.events.EventHandler(this);
};
goog.inherits(unisubs.translate.Dialog, unisubs.subtitle.Dialog);

unisubs.translate.Dialog.State_ = {
    TRANSLATE: 0,
    EDIT_METADATA: 1,

};

unisubs.translate.Dialog.prototype.createDom = function() {
    unisubs.translate.Dialog.superClass_.createDom.call(this);
    this.setDraggable(false);
    this.translationPanel_ = new unisubs.translate.TranslationPanel(
        this.serverModel_.getCaptionSet(), this.standardSubState_, this);
    this.getCaptioningAreaInternal().addChild(
        this.translationPanel_, true);
    var rightPanel = this.createRightPanel_();
    this.setRightPanelInternal(rightPanel);
    this.getHandler().
        listen(
            rightPanel, unisubs.RightPanel.EventType.DONE,
            this.handleDoneKeyPress_).
        listen(
            rightPanel, unisubs.RightPanel.EventType.SAVEANDEXIT,
            this.handleSaveAndExitKeyPress_);
    goog.dom.classes.add(this.getContentElement(),
                         'unisubs-modal-widget-translate');
    this.showGuidelines_();
    this.enterState_(unisubs.translate.Dialog.State_.TRANSLATE);
};
unisubs.translate.Dialog.prototype.showGuidelines_ = function() {
    if (!unisubs.guidelines['translate']) {
        return;
    }

    var guidelinesPanel = new unisubs.GuidelinesPanel(unisubs.guidelines['translate']);
    this.showTemporaryPanel(guidelinesPanel);
    this.displayingGuidelines_ = true;

    var that = this;
    this.getHandler().listenOnce(guidelinesPanel, unisubs.GuidelinesPanel.CONTINUE, function(e) {
        goog.Timer.callOnce(function() {
            that.displayingGuidelines_ = false;
            that.hideTemporaryPanel();
        });
    });
};
unisubs.translate.Dialog.prototype.createRightPanel_ = function() {
    var title = this.subtitleState_.VERSION > 0 ?
        "Editing Translation" : "Adding a New Translation";
    var helpContents = new unisubs.RightPanel.HelpContents(
        title,
        [["Thanks for volunteering to translate! Your translation will be available to ",
"everyone  watching the video in our widget."].join(''),
         ["Please translate each line, one by one, in the white  ",
          "space below each line."].join(''),
         ["If you need to rearrange the order of words or split a phrase ",
          "differently, that's okay."].join(''),
         ["As you're translating, you can use the \"TAB\" key to advance to ",
          "the next line, and \"Shift-TAB\" to go back."].join('')
        ], 2, 0);
    var extraHelp = [
        ["Google Translate", "http://translate.google.com/"],
        ["List of dictionaries", "http://yourdictionary.com/languages.html"],
        ["Firefox spellcheck dictionaries",
         "https://addons.mozilla.org/en-US/firefox/browse/type:3"]
    ];
    return new unisubs.translate.TranslationRightPanel(
        this,
        this.serverModel_, helpContents, extraHelp, [], false, "Done?",
        "Next Step: Title & Description", "Resources for Translators");
};
unisubs.translate.Dialog.prototype.handleSaveAndExitKeyPress_ = function(e) {
    e.preventDefault();
    this.saveWork(false);
};
unisubs.translate.Dialog.prototype.handleDoneKeyPress_ = function(event) {
    event.preventDefault();
    if (this.state_ == unisubs.subtitle.Dialog.State_.EDIT_METADATA)
        this.saveWork(true);
    else
        this.enterState_(this.nextState_());
};

unisubs.translate.Dialog.prototype.isWorkSaved = function() {
    return this.saved_ || !this.serverModel_.anySubtitlingWorkDone();
};
unisubs.translate.Dialog.prototype.enterDocument = function() {
    // this is where we listen to the dialog close button
    unisubs.subtitle.Dialog.superClass_.enterDocument.call(this);
    unisubs.Dialog.translationDialogOpen = true;
    var that = this;
    this.getRightPanelInternal().showDownloadLink(
        function() {
            return that.makeJsonSubs();
        });
};
unisubs.translate.Dialog.prototype.saveWorkInternal = function(closeAfterSave) {
    var that = this;
    this.getRightPanelInternal().showLoading(true);
    this.serverModel_.finish(
        function(serverMsg){
            unisubs.subtitle.OnSavedDialog.show(serverMsg, function(){
                that.onWorkSaved(closeAfterSave);
            })
        },
        function(opt_status) {
            if (that.finishFailDialog_)
                that.finishFailDialog_.failedAgain(opt_status);
            else
                that.finishFailDialog_ = unisubs.finishfaildialog.Dialog.show(
                    that.serverModel_.getCaptionSet(), opt_status,
                    goog.bind(that.saveWorkInternal, that, closeAfterSave));
        });
};
unisubs.translate.Dialog.prototype.showGuidelinesForState_ = function(state) {
    this.setState_(state);
}

unisubs.Dialog.prototype.setVisible = function(visible) {
    if (visible) {
        unisubs.Dialog.superClass_.setVisible.call(this, true);
        goog.dom.getDocumentScrollElement().scrollTop = 0;
    }
    else {
        if (this.isWorkSaved()) {
            this.hideDialogImpl_();
        }
        else {
            this.showSaveWorkDialog_();
        }
    }
};

unisubs.translate.Dialog.prototype.onWorkSaved = function() {
    if (this.finishFailDialog_) {
        this.finishFailDialog_.setVisible(false);
        this.finishFailDialog_ = null;
    }
    unisubs.widget.ResumeEditingRecord.clear();
    this.getRightPanelInternal().showLoading(false);
    this.saved_ = true;
    this.setVisible(false);
}

unisubs.translate.Dialog.prototype.disposeInternal = function() {
    unisubs.translate.Dialog.superClass_.disposeInternal.call(this);
    this.serverModel_.dispose();
};

unisubs.translate.Dialog.prototype.enterState_ = function(state) {
    this.showGuidelinesForState_(state);
};

unisubs.translate.Dialog.prototype.suspendKeyEvents_ = function(suspended) {
    this.keyEventsSuspended_ = suspended;
    if (this.currentSubtitlePanel_ && this.currentSubtitlePanel_.suspendKeyEvents)
        this.currentSubtitlePanel_.suspendKeyEvents(suspended);
};

unisubs.translate.Dialog.prototype.setState_ = function(state) {
    this.state_ = state;

    this.suspendKeyEvents_(false);

    var s = unisubs.subtitle.Dialog.State_;

    this.setExtraClass_();

    var nextSubPanel = this.makeCurrentStateSubtitlePanel_();
    var captionPanel = this.getCaptioningAreaInternal();
    captionPanel.removeChildren(true);
    captionPanel.addChild(nextSubPanel, true);

    var rightPanel = nextSubPanel.getRightPanel();
    this.setRightPanelInternal(rightPanel);

    this.getTimelinePanelInternal().removeChildren(true);

    this.disposeCurrentPanels_();
    this.currentSubtitlePanel_ = nextSubPanel;

    var et = unisubs.RightPanel.EventType;
    this.rightPanelListener_.
        listen(
            rightPanel, et.LEGENDKEY, this.handleLegendKeyPress_).
        listen(
            rightPanel, et.DONE, this.handleDoneKeyPress_).
        listen(
            rightPanel, et.SAVEANDEXIT, this.handleSaveAndExitKeyPress_).
        listen(
            rightPanel, et.GOTOSTEP, this.handleGoToStep_);
    var backButtonText = null;
    if (state == s.EDIT_METADATA ){
        backButtonText = "Back to Translation";
    }
    if (backButtonText){
        rightPanel.showBackLink(backButtonText);
        this.rightPanelListener_.listen(
            rightPanel, et.BACK, this.handleBackKeyPress_);

    }

    var videoPlayer = this.getVideoPlayerInternal();
    if (this.isInDocument()) {
        videoPlayer.pause();
        videoPlayer.setPlayheadTime(0);
    }
};
unisubs.translate.Dialog.prototype.makeCurrentStateSubtitlePanel_ = function() {
    var s = unisubs.translate.Dialog.State_;
    if (this.state_ == s.TRANSLATE)
        return new unisubs.translate.TranslationPanel(
        this.serverModel_.getCaptionSet(), this.standardSubState_, this);
    else if (this.state_ == s.EDIT_METADATA)
        return new unisubs.editmetadata.Panel(
            this.serverModel_.getCaptionSet(),
            this.getVideoPlayerInternal(),
            this.serverModel_,
            this.captionManager_,
            this.standardSubState_ ,
            false
        );
};

/**
 * Tries translate subtitles with BingTranslator
 */
unisubs.translate.Dialog.prototype.translateViaBing = function(){
    //I don't know how better call this. I think it should be incapsulated in translationList_,
    //but have chain of function calls can confuse.
    this.translationPanel_.getTranslationList().translateViaBing(
        this.standardSubState_.LANGUAGE, this.subtitleState_.LANGUAGE);
};

unisubs.translate.Dialog.prototype.getStandardLanguage = function(){
    return this.standardSubState_.LANGUAGE;
};

unisubs.translate.Dialog.prototype.getSubtitleLanguage = function(){
    return this.subtitleState_.LANGUAGE;
};

unisubs.translate.Dialog.prototype.getServerModel = function(){
    return this.serverModel_;
}

unisubs.translate.Dialog.prototype.makeJsonSubs =  function (){
    return this.serverModel_.getCaptionSet().makeJsonSubs();
};

unisubs.translate.Dialog.prototype.forkAndClose = function() {
    var dialog = new unisubs.translate.ForkDialog(
        goog.bind(this.forkImpl_, this));
    dialog.setVisible(true);
};

unisubs.translate.Dialog.prototype.forkImpl_ = function() {
    this.subtitleState_.fork();
    this.serverModel_.fork(this.standardSubState_);
    this.hideToFork();
    this.opener_.openSubtitlingDialog(
        this.serverModel_,
        this.subtitleState_);
};
<commit_msg>Fixes the widget on compiled js<commit_after>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('unisubs.translate.Dialog');

/**
 * @constructor
 *
 */
unisubs.translate.Dialog = function(opener,
                                     serverModel,
                                     videoSource,
                                     subtitleState,
                                     standardSubState) {
    unisubs.Dialog.call(this, videoSource);
    unisubs.SubTracker.getInstance().start(true);
    this.opener_ = opener;
    this.subtitleState_ = subtitleState;
    this.standardSubState_ = standardSubState;

    this.serverModel_ = serverModel;
    this.serverModel_.init();
    this.saved_ = false;
    this.rightPanelListener_ = new goog.events.EventHandler(this);
};
goog.inherits(unisubs.translate.Dialog, unisubs.subtitle.Dialog);

unisubs.translate.Dialog.State_ = {
    TRANSLATE: 0,
    EDIT_METADATA: 1

};

unisubs.translate.Dialog.prototype.createDom = function() {
    unisubs.translate.Dialog.superClass_.createDom.call(this);
    this.setDraggable(false);
    this.translationPanel_ = new unisubs.translate.TranslationPanel(
        this.serverModel_.getCaptionSet(), this.standardSubState_, this);
    this.getCaptioningAreaInternal().addChild(
        this.translationPanel_, true);
    var rightPanel = this.createRightPanel_();
    this.setRightPanelInternal(rightPanel);
    this.getHandler().
        listen(
            rightPanel, unisubs.RightPanel.EventType.DONE,
            this.handleDoneKeyPress_).
        listen(
            rightPanel, unisubs.RightPanel.EventType.SAVEANDEXIT,
            this.handleSaveAndExitKeyPress_);
    goog.dom.classes.add(this.getContentElement(),
                         'unisubs-modal-widget-translate');
    this.showGuidelines_();
    this.enterState_(unisubs.translate.Dialog.State_.TRANSLATE);
};
unisubs.translate.Dialog.prototype.showGuidelines_ = function() {
    if (!unisubs.guidelines['translate']) {
        return;
    }

    var guidelinesPanel = new unisubs.GuidelinesPanel(unisubs.guidelines['translate']);
    this.showTemporaryPanel(guidelinesPanel);
    this.displayingGuidelines_ = true;

    var that = this;
    this.getHandler().listenOnce(guidelinesPanel, unisubs.GuidelinesPanel.CONTINUE, function(e) {
        goog.Timer.callOnce(function() {
            that.displayingGuidelines_ = false;
            that.hideTemporaryPanel();
        });
    });
};
unisubs.translate.Dialog.prototype.createRightPanel_ = function() {
    var title = this.subtitleState_.VERSION > 0 ?
        "Editing Translation" : "Adding a New Translation";
    var helpContents = new unisubs.RightPanel.HelpContents(
        title,
        [["Thanks for volunteering to translate! Your translation will be available to ",
"everyone  watching the video in our widget."].join(''),
         ["Please translate each line, one by one, in the white  ",
          "space below each line."].join(''),
         ["If you need to rearrange the order of words or split a phrase ",
          "differently, that's okay."].join(''),
         ["As you're translating, you can use the \"TAB\" key to advance to ",
          "the next line, and \"Shift-TAB\" to go back."].join('')
        ], 2, 0);
    var extraHelp = [
        ["Google Translate", "http://translate.google.com/"],
        ["List of dictionaries", "http://yourdictionary.com/languages.html"],
        ["Firefox spellcheck dictionaries",
         "https://addons.mozilla.org/en-US/firefox/browse/type:3"]
    ];
    return new unisubs.translate.TranslationRightPanel(
        this,
        this.serverModel_, helpContents, extraHelp, [], false, "Done?",
        "Next Step: Title & Description", "Resources for Translators");
};
unisubs.translate.Dialog.prototype.handleSaveAndExitKeyPress_ = function(e) {
    e.preventDefault();
    this.saveWork(false);
};
unisubs.translate.Dialog.prototype.handleDoneKeyPress_ = function(event) {
    event.preventDefault();
    if (this.state_ == unisubs.subtitle.Dialog.State_.EDIT_METADATA)
        this.saveWork(true);
    else
        this.enterState_(this.nextState_());
};

unisubs.translate.Dialog.prototype.isWorkSaved = function() {
    return this.saved_ || !this.serverModel_.anySubtitlingWorkDone();
};
unisubs.translate.Dialog.prototype.enterDocument = function() {
    // this is where we listen to the dialog close button
    unisubs.subtitle.Dialog.superClass_.enterDocument.call(this);
    unisubs.Dialog.translationDialogOpen = true;
    var that = this;
    this.getRightPanelInternal().showDownloadLink(
        function() {
            return that.makeJsonSubs();
        });
};
unisubs.translate.Dialog.prototype.saveWorkInternal = function(closeAfterSave) {
    var that = this;
    this.getRightPanelInternal().showLoading(true);
    this.serverModel_.finish(
        function(serverMsg){
            unisubs.subtitle.OnSavedDialog.show(serverMsg, function(){
                that.onWorkSaved(closeAfterSave);
            })
        },
        function(opt_status) {
            if (that.finishFailDialog_)
                that.finishFailDialog_.failedAgain(opt_status);
            else
                that.finishFailDialog_ = unisubs.finishfaildialog.Dialog.show(
                    that.serverModel_.getCaptionSet(), opt_status,
                    goog.bind(that.saveWorkInternal, that, closeAfterSave));
        });
};
unisubs.translate.Dialog.prototype.showGuidelinesForState_ = function(state) {
    this.setState_(state);
}

unisubs.Dialog.prototype.setVisible = function(visible) {
    if (visible) {
        unisubs.Dialog.superClass_.setVisible.call(this, true);
        goog.dom.getDocumentScrollElement().scrollTop = 0;
    }
    else {
        if (this.isWorkSaved()) {
            this.hideDialogImpl_();
        }
        else {
            this.showSaveWorkDialog_();
        }
    }
};

unisubs.translate.Dialog.prototype.onWorkSaved = function() {
    if (this.finishFailDialog_) {
        this.finishFailDialog_.setVisible(false);
        this.finishFailDialog_ = null;
    }
    unisubs.widget.ResumeEditingRecord.clear();
    this.getRightPanelInternal().showLoading(false);
    this.saved_ = true;
    this.setVisible(false);
}

unisubs.translate.Dialog.prototype.disposeInternal = function() {
    unisubs.translate.Dialog.superClass_.disposeInternal.call(this);
    this.serverModel_.dispose();
};

unisubs.translate.Dialog.prototype.enterState_ = function(state) {
    this.showGuidelinesForState_(state);
};

unisubs.translate.Dialog.prototype.suspendKeyEvents_ = function(suspended) {
    this.keyEventsSuspended_ = suspended;
    if (this.currentSubtitlePanel_ && this.currentSubtitlePanel_.suspendKeyEvents)
        this.currentSubtitlePanel_.suspendKeyEvents(suspended);
};

unisubs.translate.Dialog.prototype.setState_ = function(state) {
    this.state_ = state;

    this.suspendKeyEvents_(false);

    var s = unisubs.subtitle.Dialog.State_;

    this.setExtraClass_();

    var nextSubPanel = this.makeCurrentStateSubtitlePanel_();
    var captionPanel = this.getCaptioningAreaInternal();
    captionPanel.removeChildren(true);
    captionPanel.addChild(nextSubPanel, true);

    var rightPanel = nextSubPanel.getRightPanel();
    this.setRightPanelInternal(rightPanel);

    this.getTimelinePanelInternal().removeChildren(true);

    this.disposeCurrentPanels_();
    this.currentSubtitlePanel_ = nextSubPanel;

    var et = unisubs.RightPanel.EventType;
    this.rightPanelListener_.
        listen(
            rightPanel, et.LEGENDKEY, this.handleLegendKeyPress_).
        listen(
            rightPanel, et.DONE, this.handleDoneKeyPress_).
        listen(
            rightPanel, et.SAVEANDEXIT, this.handleSaveAndExitKeyPress_).
        listen(
            rightPanel, et.GOTOSTEP, this.handleGoToStep_);
    var backButtonText = null;
    if (state == s.EDIT_METADATA ){
        backButtonText = "Back to Translation";
    }
    if (backButtonText){
        rightPanel.showBackLink(backButtonText);
        this.rightPanelListener_.listen(
            rightPanel, et.BACK, this.handleBackKeyPress_);

    }

    var videoPlayer = this.getVideoPlayerInternal();
    if (this.isInDocument()) {
        videoPlayer.pause();
        videoPlayer.setPlayheadTime(0);
    }
};
unisubs.translate.Dialog.prototype.makeCurrentStateSubtitlePanel_ = function() {
    var s = unisubs.translate.Dialog.State_;
    if (this.state_ == s.TRANSLATE)
        return new unisubs.translate.TranslationPanel(
        this.serverModel_.getCaptionSet(), this.standardSubState_, this);
    else if (this.state_ == s.EDIT_METADATA)
        return new unisubs.editmetadata.Panel(
            this.serverModel_.getCaptionSet(),
            this.getVideoPlayerInternal(),
            this.serverModel_,
            this.captionManager_,
            this.standardSubState_ ,
            false
        );
};

/**
 * Tries translate subtitles with BingTranslator
 */
unisubs.translate.Dialog.prototype.translateViaBing = function(){
    //I don't know how better call this. I think it should be incapsulated in translationList_,
    //but have chain of function calls can confuse.
    this.translationPanel_.getTranslationList().translateViaBing(
        this.standardSubState_.LANGUAGE, this.subtitleState_.LANGUAGE);
};

unisubs.translate.Dialog.prototype.getStandardLanguage = function(){
    return this.standardSubState_.LANGUAGE;
};

unisubs.translate.Dialog.prototype.getSubtitleLanguage = function(){
    return this.subtitleState_.LANGUAGE;
};

unisubs.translate.Dialog.prototype.getServerModel = function(){
    return this.serverModel_;
}

unisubs.translate.Dialog.prototype.makeJsonSubs =  function (){
    return this.serverModel_.getCaptionSet().makeJsonSubs();
};

unisubs.translate.Dialog.prototype.forkAndClose = function() {
    var dialog = new unisubs.translate.ForkDialog(
        goog.bind(this.forkImpl_, this));
    dialog.setVisible(true);
};

unisubs.translate.Dialog.prototype.forkImpl_ = function() {
    this.subtitleState_.fork();
    this.serverModel_.fork(this.standardSubState_);
    this.hideToFork();
    this.opener_.openSubtitlingDialog(
        this.serverModel_,
        this.subtitleState_);
};
<|endoftext|>


<commit_before>var fs = require("fs"),
    path = require('path'),
    cp = require('child_process');

var db = require(CONFIG.root + "/core/model/orient.js");

/*
    Clones a git repo to a certain directory. The directory must exist
*/
function gitClone(url, dirName, baseName, callback) {

    path.exists(dirName + "/" + baseName, function(exists) {

        if (exists) {
            return callback({ error: "Path already exists: " + dirName + "/" + baseName, code: 201 });
        }

        var options = {
            cwd: dirName
        };
        var git = cp.spawn("git", ["clone", url, baseName], options);

        git.on("exit", function(code) {
            if (code) {
                return callback({ error: "Git error: git clone exited with code " + code, code: 200 });
            }
            callback(null);
        });
    });
}

function gitReset(repoDir, commit, callback) {

    path.exists(repoDir + "/.git", function(exists) {

        if (!exists) {
            return callback({ error: "Path is not a git repository: " + repoDir, code: 202 });
        }

        var options = {
            cwd: repoDir
        };
        var revert = cp.spawn("git", ["reset", "--hard", commit], options);

        revert.on("exit", function(code) {
            if (code) {
                return callback({ error: "Git error: git reset exited with code " + code, code: 200 });
            }
            callback(null);
        });
    });
}

function addModuleDir(source, owner, module, callback) {

    var options = {
        cwd: CONFIG.root + "/modules"
    };
    var mkdir = cp.spawn("mkdir", ["-p", source + "/" + owner + "/" + module], options);

    mkdir.on("exit", function(code) {

        if (code) {
            return callback({ error: "Failed to create module directory: " + source + "/" + owner + "/" + module, code: 203 });
        }
        callback(null);
    });
}

// ************** API **************

function fetchModule(module, callback) {

    addModuleDir(module.source, module.owner, module.name, function(err) {

        if (err) { return callback(err); }

        var dirName = CONFIG.root + "/modules/" + module.source + "/" + module.owner + "/" + module.name;
        var url = null;
        switch (module.source) {
            case "github":
                url = "https://github.com/" + module.owner + "/" + module.name + ".git";
                break;
            case "bitbucket":
                url = "git@bitbucket.org:" + module.owner + "/" + module.name.toLowerCase() + ".git";
                break;
            default:
                callback({ error: "Invalid source: " + module.source, code: 204});
                return;
        }

        // clone the repo first
        gitClone(url, dirName, module.version, function(err) {

            if (err) { return callback(err) };

            // reset to this version (commit)
            gitReset(dirName + "/" + module.version, module.version, callback);
        });
    });
}

function removeModule(source, owner, module, version, callback) {

    var options = {
        cwd: CONFIG.root + "/modules/" + source + "/" + owner + "/" + module + "/"
    };
    var git = cp.spawn("rm", ["-Rf", version], options);

    git.on("exit", function(code) {
        if (code) {
            return callback("Could not remove module: " + source + "/" + owner + "/" + module + "/" + version);
        }
        callback(null);
    });
}

function getModuleOperations(module, callback) {

    fs.readFile(CONFIG.root + "/modules/" + module.relativePath() + "/mono.json", function (err, data) {

        if (err) { return callback("Error while reading the mono.json file for module " + module.relativePath()) };

        var mono = {};

        try {
            mono = JSON.parse(data);
            operations = mono.operations;
        } catch (err) {
            callback("Invalid mono.json in module " + module.relativePath());
        }

        callback(null, mono.operations || []);
    });
}

function installModule(source, owner, name, version, callback) {

    var module = {
        source: source,
        owner: owner,
        name: name,
        version: version,
        relativePath: function() { return source + "/" + owner + "/" + name + "/" + version; }
    };

    fetchModule(module, function(err) {

        if (err) {
            return callback(err);
        }

        getModuleOperations(module, function(err, operations) {

            if (err) { return callback(err) };

            module.operations = operations;

            db.insertModuleVersion(module, callback);
        });
    });
}

function uninstallModule(source, owner, module, version, callback) {

    removeModule(source, owner, module, version, function(err) {

        if (err) {
            return callback(err);
        }

        db.deleteModuleVersion(source, owner, module, version, callback);
    });
}

exports.fetchModule = fetchModule;
exports.removeModule = removeModule;
exports.installModule = installModule;
exports.uninstallModule = uninstallModule;

<commit_msg>removed path module references not being replaced by the fs module<commit_after>var fs = require("fs"),
    cp = require('child_process');

var db = require(CONFIG.root + "/core/model/orient.js");

/*
    Clones a git repo to a certain directory. The directory must exist
*/
function gitClone(url, dirName, baseName, callback) {

    fs.exists(dirName + "/" + baseName, function(exists) {

        if (exists) {
            return callback({ error: "Path already exists: " + dirName + "/" + baseName, code: 201 });
        }

        var options = {
            cwd: dirName
        };
        var git = cp.spawn("git", ["clone", url, baseName], options);

        git.on("exit", function(code) {
            if (code) {
                return callback({ error: "Git error: git clone exited with code " + code, code: 200 });
            }
            callback(null);
        });
    });
}

function gitReset(repoDir, commit, callback) {

    fs.exists(repoDir + "/.git", function(exists) {

        if (!exists) {
            return callback({ error: "Path is not a git repository: " + repoDir, code: 202 });
        }

        var options = {
            cwd: repoDir
        };
        var revert = cp.spawn("git", ["reset", "--hard", commit], options);

        revert.on("exit", function(code) {
            if (code) {
                return callback({ error: "Git error: git reset exited with code " + code, code: 200 });
            }
            callback(null);
        });
    });
}

function addModuleDir(source, owner, module, callback) {

    var options = {
        cwd: CONFIG.root + "/modules"
    };
    var mkdir = cp.spawn("mkdir", ["-p", source + "/" + owner + "/" + module], options);

    mkdir.on("exit", function(code) {

        if (code) {
            return callback({ error: "Failed to create module directory: " + source + "/" + owner + "/" + module, code: 203 });
        }
        callback(null);
    });
}

// ************** API **************

function fetchModule(module, callback) {

    addModuleDir(module.source, module.owner, module.name, function(err) {

        if (err) { return callback(err); }

        var dirName = CONFIG.root + "/modules/" + module.source + "/" + module.owner + "/" + module.name;
        var url = null;
        switch (module.source) {
            case "github":
                url = "https://github.com/" + module.owner + "/" + module.name + ".git";
                break;
            case "bitbucket":
                url = "git@bitbucket.org:" + module.owner + "/" + module.name.toLowerCase() + ".git";
                break;
            default:
                callback({ error: "Invalid source: " + module.source, code: 204});
                return;
        }

        // clone the repo first
        gitClone(url, dirName, module.version, function(err) {

            if (err) { return callback(err) };

            // reset to this version (commit)
            gitReset(dirName + "/" + module.version, module.version, callback);
        });
    });
}

function removeModule(source, owner, module, version, callback) {

    var options = {
        cwd: CONFIG.root + "/modules/" + source + "/" + owner + "/" + module + "/"
    };
    var git = cp.spawn("rm", ["-Rf", version], options);

    git.on("exit", function(code) {
        if (code) {
            return callback("Could not remove module: " + source + "/" + owner + "/" + module + "/" + version);
        }
        callback(null);
    });
}

function getModuleOperations(module, callback) {

    fs.readFile(CONFIG.root + "/modules/" + module.relativePath() + "/mono.json", function (err, data) {

        if (err) { return callback("Error while reading the mono.json file for module " + module.relativePath()) };

        var mono = {};

        try {
            mono = JSON.parse(data);
            operations = mono.operations;
        } catch (err) {
            callback("Invalid mono.json in module " + module.relativePath());
        }

        callback(null, mono.operations || []);
    });
}

function installModule(source, owner, name, version, callback) {

    var module = {
        source: source,
        owner: owner,
        name: name,
        version: version,
        relativePath: function() { return source + "/" + owner + "/" + name + "/" + version; }
    };

    fetchModule(module, function(err) {

        if (err) {
            return callback(err);
        }

        getModuleOperations(module, function(err, operations) {

            if (err) { return callback(err) };

            module.operations = operations;

            db.insertModuleVersion(module, callback);
        });
    });
}

function uninstallModule(source, owner, module, version, callback) {

    removeModule(source, owner, module, version, function(err) {

        if (err) {
            return callback(err);
        }

        db.deleteModuleVersion(source, owner, module, version, callback);
    });
}

exports.fetchModule = fetchModule;
exports.removeModule = removeModule;
exports.installModule = installModule;
exports.uninstallModule = uninstallModule;

<|endoftext|>


<commit_before>const TLSARecord = require('../index.js')
const tls = require('tls')

module.exports = (req, res) => {
  let body = ''
  res.setHeader('Access-Control-Allow-Origin', '*')
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept')
  res.setHeader('Content-Type', 'application/json')
  if (req.method === 'POST') {
    req.on('data', chunk => { body += chunk.toString() })
    req.on('end', () => {
        body = JSON.parse(body)
        tls.connect(parseInt(body.port), body.domain, function() {
            const tlsaRecord = new TLSARecord(this.getPeerCertificate().raw)
            res.end(JSON.stringify({
                record: tlsaRecord.toString(
                    parseInt(body.usage),
                    parseInt(body.selector),
                    parseInt(body.matchingType),
                    body.domain,
                    parseInt(body.port),
                    body.protocol),
                status: 'ok'
            }))
        })
    })
  } else if (req.method === 'GET') {
    res.writeHead(301, { "Location": "https://proux.github.io/tlsa-builder/" })
    res.end()
  } else { res.end() }
}
<commit_msg>style: lint<commit_after>const TLSARecord = require('../index.js')
const tls = require('tls')

module.exports = (req, res) => {
  let body = ''
  if (req.method === 'POST') {
    req.on('data', chunk => { body += chunk.toString() })
    req.on('end', () => {
      body = JSON.parse(body)
      tls.connect(parseInt(body.port), body.domain, function () {
        const tlsaRecord = new TLSARecord(this.getPeerCertificate().raw)
        res.end(JSON.stringify({
          record: tlsaRecord.toString(
            parseInt(body.usage),
            parseInt(body.selector),
            parseInt(body.matchingType),
            body.domain,
            parseInt(body.port),
            body.protocol),
          status: 'ok'
        }))
      })
    })
  } else if (req.method === 'GET') {
    res.writeHead(301, { 'Location': 'https://proux.github.io/tlsa-builder/' })
    res.end()
  } else { res.end() }
}
<|endoftext|>


<commit_before>if (typeof define !== 'function') {
    //noinspection JSUnresolvedVariable
    var define = require('amdefine')(module);
}

define(function (require) {
    var transport = require('./transport'),
        auth = require('./auth'),
        urlencode = require('./urlencode'),
        Exception = require('./exception');

    var placeholder = /^{(.+)}$/,
        safeMethods = { 'GET': true, 'HEAD': true, 'OPTIONS': true },
        synonyms;

    synonyms = {
        'PUT': ['save', 'replace'],
        'POST': ['add'],
        'DELETE': ['remove']
    };

    function result(value) {

        if (value.indexOf('=') === -1) {
            return value;
        }

        var parts = value.split('=');

        // TODO: remove primitive type object wrapper
        value = new String(parts[0]);
        value.variable = parts[1];

        return value;
    }

    function last(arr, except) {
        except || (except = 0);
        return typeof arr[arr.length - except - 1];
    }

    return function apic(desc, options) {
        options = options || {};

        var root = {},
            base = desc.base,
            variables = {},
            augments = {},
            language,
            lastDate;

        var scheme = 'http:',
            dateRegex = /^Date:/mi;

        options.synonyms = options.synonyms || synonyms;
        options.tokenHeader = options.tokenHeader || 'X-Security-Token';
        options.authorizationHeader = options.authorizationHeader || 'Authorization';

        if (typeof window !== 'undefined') {
            scheme = location.protocol; // current URI scheme
        }

        auth.apply(root);

        root.augment = function (name, value) {

            if (value === undefined) {
                return augments[name];
            }

            augments[name] = value;
        };

        root.localize = function (value) {

            if (value !== undefined) {
                language = value;
            }

            return language;
        };

        root.variable = function (name, value) {

            if (value !== undefined) {
                variables[name] = value;
            }

            return variables[name];
        };

        root.getLastDate = function () {
            return Date.parse(lastDate);
        };

        function method(verb, uri, res, params, secure) {
            var safe = safeMethods[verb] || false,
                protocol = (secure = secure || !safe) ? 'https:' : scheme;

            // do not ever use this
            if (options.__forceProtocol) {
                protocol = options.__forceProtocol;
            }

            return function () {
                var args = Array.prototype.slice.call(arguments),
                    headers = last(args) === 'object' && last(args, 1) === 'function' ? args.pop() : {},
                    callback = (last(args) === 'function' || last(args) === 'undefined') ? args.pop() : undefined,
                    representation = last(args) === 'object' ? args.pop() : undefined,
                    query = last(args) === 'object' ? args.pop() : {},
                    path = uri,
                    _;

                if (safeMethods[verb]) {
                    query = representation || {};
                    representation = undefined;
                }

                /*
                 Check if all necessary arguments passed in arguments or have default variable value
                 */
                if (params.reduce(function (a, b) {
                    return a - +(query[b] !== undefined || variables[b.variable] !== undefined);
                }, params.length) > args.length) {

                    throw new Error([
                        params.length, ' argument', (params.length === 1 ? '' : 's'),
                        params.length ? ' (' + params.join(', ') + ')' : '',
                        ' expected ', args.length, ' given',
                        args.length ? ' (' + args.join(', ') + ')' : ''
                    ].join(''));

                }

                params.forEach(function (name, i) {

                    if (!query[name]) {
                        query[name] = args[i] === undefined
                            ? (name.variable && variables[name.variable])
                            : args[i];
                    }

                    if (name.template) {
                        var _ = '{' + name + '}',
                            value = args[i] || query[name];

                        path.indexOf(_) === -1
                            ? (path += '/' + value)
                            : (path = path.replace(_, value));

                        delete query[name];
                    }

                });

                // cleanup
                for (_ in query) {

                    if (query[_] === undefined) {
                        delete query[_];
                    }

                }

                if (secure && root.authorize()) {
                    headers[options.authorizationHeader] = root.authorize();
                }

                if (language) {

                    if (safe) {
                        headers['Accept-Language'] = language;
                    } else if (representation) {
                        headers['Content-Language'] = language;
                    }

                }

                for (_ in augments) {

                    if (augments[_] !== null) {
                        headers[_] = augments[_];
                    }

                }

                transport.request({
                    uri: protocol + base + path + urlencode.encode(query),
                    method: verb,
                    headers: headers,
                    body: representation,
                    cookie: options.cookie
                }, function (err, body, xhr) {
                    var token;

                    function cb(err) {

                        if (!callback) {
                            return;
                        }

                        var args = [err, body];

                        /**
                         * Pass xhr object only if explicitly expected
                         * otherwise some libraries using 'arguments' object
                         * can work incorrectly
                         */
                        callback.length === 3 && args.push(xhr);
                        callback.apply(this, args);
                    }

                    if (dateRegex.test(xhr.getAllResponseHeaders())) {
                        lastDate = xhr.getResponseHeader('Date');
                    }

                    if (err) {

                        if (err.status === 401) {
                            root.unauthorize();
                        }

                        cb(new Exception(err, body));

                        return;
                    }

                    res.variable && (variables[res.variable] = body && body[res]);

                    if (secure) {
                        token = xhr.getResponseHeader(options.tokenHeader);
                        token && root.authorize.token(token, root.authorize.realm());
                    }

                    cb(null);
                });
            };
        }

        return function generate(map, uri, res) {
            var key,
                value,
                parts,
                secure,
                transparent,
                tree,
                _;

            res = res || {};

            for (key in map) {
                if (map.hasOwnProperty(key) && key !== '@') {
                    value = map[key];

                    transparent = key.match(placeholder);

                    key = (parts = key.split('#')).shift();

                    parts = parts.map(function (name) {
                        var template, variable, match;

                        if (name.charAt(0) === '/') {
                            template = true;
                            name = name.substr(1);
                        }

                        if (match = name.match(placeholder)) {
                            _ = match[1].split('=');

                            name = _[0];
                            variable = _[1];
                        }

                        // monkey code
                        // TODO: remove primitive type object wrapper
                        name = new String(name);
                        name.template = template;
                        name.variable = variable;

                        return name;
                    });

                    if (key.charAt(key.length - 1) === '*')
                        secure = !!(key = key.substring(0, key.length - 1));

                    if (key.charAt(0) !== ':') {
                        _ = key.toLowerCase();

                        tree = typeof value === 'string'
                            ? method(key, uri || '/', result(value), parts, secure)
                            : generate(value, (uri || '') + '/' + (value['@'] || key), transparent && res);

                        transparent || (res[_] = tree);

                        options.synonyms[key] && options.synonyms[key].forEach(function (alias) {
                            res[alias] || (res[alias] = res[_]);
                        });
                    } else
                        res[key.substr(1)] = res[value.toLowerCase()];
                }
            }

            return res;
        }(desc.resources, undefined, root);
    };

});
<commit_msg>Changed method getLastDate to getLastResponse<commit_after>if (typeof define !== 'function') {
    //noinspection JSUnresolvedVariable
    var define = require('amdefine')(module);
}

define(function (require) {
    var transport = require('./transport'),
        auth = require('./auth'),
        urlencode = require('./urlencode'),
        Exception = require('./exception');

    var placeholder = /^{(.+)}$/,
        safeMethods = { 'GET': true, 'HEAD': true, 'OPTIONS': true },
        synonyms;

    synonyms = {
        'PUT': ['save', 'replace'],
        'POST': ['add'],
        'DELETE': ['remove']
    };

    function result(value) {

        if (value.indexOf('=') === -1) {
            return value;
        }

        var parts = value.split('=');

        // TODO: remove primitive type object wrapper
        value = new String(parts[0]);
        value.variable = parts[1];

        return value;
    }

    function last(arr, except) {
        except || (except = 0);
        return typeof arr[arr.length - except - 1];
    }

    return function apic(desc, options) {
        options = options || {};

        var root = {},
            base = desc.base,
            variables = {},
            augments = {},
            language,
            lastResponse;

        var scheme = 'http:';

        options.synonyms = options.synonyms || synonyms;
        options.tokenHeader = options.tokenHeader || 'X-Security-Token';
        options.authorizationHeader = options.authorizationHeader || 'Authorization';

        if (typeof window !== 'undefined') {
            scheme = location.protocol; // current URI scheme
        }

        auth.apply(root);

        root.augment = function (name, value) {

            if (value === undefined) {
                return augments[name];
            }

            augments[name] = value;
        };

        root.localize = function (value) {

            if (value !== undefined) {
                language = value;
            }

            return language;
        };

        root.variable = function (name, value) {

            if (value !== undefined) {
                variables[name] = value;
            }

            return variables[name];
        };

        root.getLastResponse = function () {
            return lastResponse;
        };

        function method(verb, uri, res, params, secure) {
            var safe = safeMethods[verb] || false,
                protocol = (secure = secure || !safe) ? 'https:' : scheme;

            // do not ever use this
            if (options.__forceProtocol) {
                protocol = options.__forceProtocol;
            }

            return function () {
                var args = Array.prototype.slice.call(arguments),
                    headers = last(args) === 'object' && last(args, 1) === 'function' ? args.pop() : {},
                    callback = (last(args) === 'function' || last(args) === 'undefined') ? args.pop() : undefined,
                    representation = last(args) === 'object' ? args.pop() : undefined,
                    query = last(args) === 'object' ? args.pop() : {},
                    path = uri,
                    _;

                if (safeMethods[verb]) {
                    query = representation || {};
                    representation = undefined;
                }

                /*
                 Check if all necessary arguments passed in arguments or have default variable value
                 */
                if (params.reduce(function (a, b) {
                        return a - +(query[b] !== undefined || variables[b.variable] !== undefined);
                    }, params.length) > args.length) {

                    throw new Error([
                        params.length, ' argument', (params.length === 1 ? '' : 's'),
                        params.length ? ' (' + params.join(', ') + ')' : '',
                        ' expected ', args.length, ' given',
                        args.length ? ' (' + args.join(', ') + ')' : ''
                    ].join(''));

                }

                params.forEach(function (name, i) {

                    if (!query[name]) {
                        query[name] = args[i] === undefined
                            ? (name.variable && variables[name.variable])
                            : args[i];
                    }

                    if (name.template) {
                        var _ = '{' + name + '}',
                            value = args[i] || query[name];

                        path.indexOf(_) === -1
                            ? (path += '/' + value)
                            : (path = path.replace(_, value));

                        delete query[name];
                    }

                });

                // cleanup
                for (_ in query) {

                    if (query[_] === undefined) {
                        delete query[_];
                    }

                }

                if (secure && root.authorize()) {
                    headers[options.authorizationHeader] = root.authorize();
                }

                if (language) {

                    if (safe) {
                        headers['Accept-Language'] = language;
                    } else if (representation) {
                        headers['Content-Language'] = language;
                    }

                }

                for (_ in augments) {

                    if (augments[_] !== null) {
                        headers[_] = augments[_];
                    }

                }

                transport.request({
                    uri: protocol + base + path + urlencode.encode(query),
                    method: verb,
                    headers: headers,
                    body: representation,
                    cookie: options.cookie
                }, function (err, body, xhr) {
                    var token;

                    function cb(err) {

                        if (!callback) {
                            return;
                        }

                        var args = [err, body];

                        /**
                         * Pass xhr object only if explicitly expected
                         * otherwise some libraries using 'arguments' object
                         * can work incorrectly
                         */
                        callback.length === 3 && args.push(xhr);
                        callback.apply(this, args);
                    }

                    lastResponse = xhr;

                    if (err) {

                        if (err.status === 401) {
                            root.unauthorize();
                        }

                        cb(new Exception(err, body));

                        return;
                    }

                    res.variable && (variables[res.variable] = body && body[res]);

                    if (secure) {
                        token = xhr.getResponseHeader(options.tokenHeader);
                        token && root.authorize.token(token, root.authorize.realm());
                    }

                    cb(null);
                });
            };
        }

        return function generate(map, uri, res) {
            var key,
                value,
                parts,
                secure,
                transparent,
                tree,
                _;

            res = res || {};

            for (key in map) {
                if (map.hasOwnProperty(key) && key !== '@') {
                    value = map[key];

                    transparent = key.match(placeholder);

                    key = (parts = key.split('#')).shift();

                    parts = parts.map(function (name) {
                        var template, variable, match;

                        if (name.charAt(0) === '/') {
                            template = true;
                            name = name.substr(1);
                        }

                        if (match = name.match(placeholder)) {
                            _ = match[1].split('=');

                            name = _[0];
                            variable = _[1];
                        }

                        // monkey code
                        // TODO: remove primitive type object wrapper
                        name = new String(name);
                        name.template = template;
                        name.variable = variable;

                        return name;
                    });

                    if (key.charAt(key.length - 1) === '*')
                        secure = !!(key = key.substring(0, key.length - 1));

                    if (key.charAt(0) !== ':') {
                        _ = key.toLowerCase();

                        tree = typeof value === 'string'
                            ? method(key, uri || '/', result(value), parts, secure)
                            : generate(value, (uri || '') + '/' + (value['@'] || key), transparent && res);

                        transparent || (res[_] = tree);

                        options.synonyms[key] && options.synonyms[key].forEach(function (alias) {
                            res[alias] || (res[alias] = res[_]);
                        });
                    } else
                        res[key.substr(1)] = res[value.toLowerCase()];
                }
            }

            return res;
        }(desc.resources, undefined, root);
    };

});
<|endoftext|>


<commit_before>var assert = require('assert')
var utilities = require('../lib/utilities.js')

describe('utilities', function () {
  describe('caller', function () {
    it('should take a string as a first argument', function () {
      assert.ok(utilities.caller('0'))
    })
    it('should return a function', function () {
      assert.equal('function', typeof utilities.caller('0'))
    })
    it('should return a function that calles a function on its argument, the function name is passed to caller', function () {
      assert.ok(utilities.caller('0')([function () {return true}]))
    })
  })
})<commit_msg>Add tests for utilities.runArray<commit_after>var assert = require('assert')
var utilities = require('../lib/utilities.js')

describe('utilities', function () {
  describe('caller', function () {
    it('should take a string as a first argument', function () {
      assert.ok(utilities.caller('0'))
    })
    it('should return a function', function () {
      assert.equal('function', typeof utilities.caller('0'))
    })
    it('should return a function that calles a function on its argument, the function name is passed to caller', function () {
      assert.ok(utilities.caller('0')([function () {return true}]))
    })
  })

  describe('runArray', function () {
    it('should take an array as an argument', function () {
      assert.ok(utilities.runArray([]))
    })
    it('should run all functions in an array', function () {
      var tst = 0
      assert.equal(2, utilities.runArray([function () {tst++}, function () {tst++}]))
    })
  })
})<|endoftext|>


<commit_before>'use strict';

var chalk = require('chalk');
var path = require('path');

/**
 * Logger component constructor
 * @param fileName The name of the file where the logs are going to be stored
 * @constructor
 */
function Logger(fileName) {
    this.fileName = fileName || 'default.log';
    this._winston = require('winston');
}

/**
 * Initializes the component
 * @param logsPath
 */
Logger.prototype.init = function (logsPath) {
    logsPath = logsPath || path.join(this.constants.logsPath);
    this._logger = new this._winston.Logger({
        transports: [
            new (this._winston.transports.Console)({ json: false, timestamp: true, level: 'debug' }),
            new this._winston.transports.File({ filename: path.join(logsPath, this.fileName), json: false })
        ],
        exitOnError: false
    });
};

/**
 * Blue information message
 * @param message
 */
Logger.prototype.info = function (message) {
    this._logger.info(chalk.blue(message));
};

/**
 * Normal debug message
 * @param message
 */
Logger.prototype.debug = function (message) {
    this._logger.debug(chalk.green(message));
};

/**
 * Normal information message
 * @param message
 */
Logger.prototype.message = function (message) {
    this._logger.info(message);
};

/**
 * Red error message
 * @param message
 */
Logger.prototype.error = function (message) {
    this._logger.error(chalk.red(message));
};

/**
 * Yellow warning message
 * @param message
 */
Logger.prototype.warn = function (message) {
    this._logger.warn(chalk.yellow(message));
};

module.exports = Logger;
<commit_msg>Escrita no arquivo de log comentada para testes do Tiago<commit_after>'use strict';

var chalk = require('chalk');
var path = require('path');

/**
 * Logger component constructor
 * @param fileName The name of the file where the logs are going to be stored
 * @constructor
 */
function Logger(fileName) {
    this.fileName = fileName || 'default.log';
    this._winston = require('winston');
}

/**
 * Initializes the component
 * @param logsPath
 */
Logger.prototype.init = function (logsPath) {
    logsPath = logsPath || path.join(this.constants.logsPath);
    this._logger = new this._winston.Logger({
        transports: [
            new (this._winston.transports.Console)({ json: false, timestamp: true, level: 'debug' })
            // new this._winston.transports.File({ filename: path.join(logsPath, this.fileName), json: false })
        ],
        exitOnError: false
    });
};

/**
 * Blue information message
 * @param message
 */
Logger.prototype.info = function (message) {
    this._logger.info(chalk.blue(message));
};

/**
 * Normal debug message
 * @param message
 */
Logger.prototype.debug = function (message) {
    this._logger.debug(chalk.green(message));
};

/**
 * Normal information message
 * @param message
 */
Logger.prototype.message = function (message) {
    this._logger.info(message);
};

/**
 * Red error message
 * @param message
 */
Logger.prototype.error = function (message) {
    this._logger.error(chalk.red(message));
};

/**
 * Yellow warning message
 * @param message
 */
Logger.prototype.warn = function (message) {
    this._logger.warn(chalk.yellow(message));
};

module.exports = Logger;
<|endoftext|>


<commit_before>/**
 * Copyright 2018 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author ebidel@ (Eric Bidelman)
 */

// Adapted from https://github.com/GoogleChromeLabs/puppeteer-examples/blob/master/google_search_features.js.

/* global document */

const fs = require('fs');
const caniuseDB = require('caniuse-db/data.json').data;

const GOOGLE_SEARCH_CHROME_VERSION = process.env.CHROME_VERSION || 41;

/* eslint-disable quote-props */
const BlinkFeatureNameToCaniuseName = {
  AddEventListenerPassiveTrue: 'passive-event-listener',
  AddEventListenerPassiveFalse: 'passive-event-listener',
  PromiseConstructor: 'promises',
  PromiseResolve: 'promises',
  PromiseReject: 'promises',
  V8PromiseChain: 'promises',
  DocumentRegisterElement: 'custom-elements',
  V0CustomElementsRegisterHTMLCustomTag: 'custom-elements',
  V0CustomElementsCreateCustomTagElement: 'custom-elements',
  V0CustomElementsRegisterHTMLTypeExtension: 'custom-elements',
  V0CustomElementsCreateTypeExtensionElement: 'custom-elements',
  CSSSelectorPseudoMatches: 'css-matches-pseudo',
  CustomElementRegistryDefine: 'custom-elementsv1',
  ElementAttachShadow: 'shadowdomv1',
  ElementAttachShadowOpen: 'shadowdomv1',
  ElementAttachShadowClosed: 'shadowdomv1',
  CSSSelectorPseudoSlotted: 'shadowdomv1',
  HTMLSlotElement: 'shadowdomv1',
  CSSSelectorPseudoHost: 'shadowdom',
  ElementCreateShadowRoot: 'shadowdom',
  CSSSelectorPseudoShadow: 'shadowdom',
  CSSSelectorPseudoContent: 'shadowdom',
  CSSSelectorPseudoHostContext: 'shadowdom',
  HTMLShadowElement: 'shadowdom',
  HTMLContentElement: 'shadowdom',
  LinkRelPreconnect: 'link-rel-preconnect',
  LinkRelPreload: 'link-rel-preload',
  HTMLImports: 'imports',
  HTMLImportsAsyncAttribute: 'imports',
  LinkRelModulePreload: 'es6-module',
  V8BroadcastChannel_Constructor: 'broadcastchannel',
  Fetch: 'fetch',
  GlobalCacheStorage: 'cachestorage', // missing: https://github.com/Fyrd/caniuse/issues/3122
  OffMainThreadFetch: 'fetch',
  IntersectionObserver_Constructor: 'intersectionobserver',
  V8Window_RequestIdleCallback_Method: 'requestidlecallback',
  NotificationPermission: 'notifications',
  UnprefixedPerformanceTimeline: 'user-timing',
  V8Element_GetBoundingClientRect_Method: 'getboundingclientrect',
  AddEventListenerThirdArgumentIsObject: 'once-event-listener', // TODO: not a perfect match.
  // TODO: appears to be no UMA tracking for classes, async/await, spread, and
  // other newer js features. Those aren't being caught here.
  contain: 'css-containment',
  'tab-size': 'css3-tabsize',
  // Explicitly disabled by search https://developers.google.com/search/docs/guides/rendering
  UnprefixedIndexedDB: 'indexeddb',
  DocumentCreateEventWebGLContextEvent: 'webgl',
  CSSGridLayout: 'css-grid',
  CSSValueDisplayContents: 'css-display-contents',
  CSSPaintFunction: 'css-paint-api',
  WorkerStart: 'webworkers',
  ServiceWorkerControlledPage: 'serviceworkers',
  // CookieGet:
  // CookieSet
};
/* eslint-enable quote-props */

/**
 * Unique items based on obj property.
 * @param {!Array} items
 * @param {string} propName Property name to filter on.
 * @return {!Array} unique array of items
 */
function uniqueByProperty(items, propName) {
  const posts = Array.from(items.reduce((map, item) => {
    return map.set(item[propName], item);
  }, new Map()).values());
  return posts;
}

/**
 * @param {!Object} usage Feature usage of page.
 * @return {string}
 */
function printHeader(usage) {
  const str = [];
  /* eslint-disable max-len */
  str.push(`
CAREFUL: using ${usage.FeatureFirstUsed.length} HTML/JS and ${usage.CSSFirstUsed.length} CSS features. Some features are not supported by the Google Search crawler. `);
  str.push(`The bot runs <u>Chrome ${GOOGLE_SEARCH_CHROME_VERSION}</u>, which may not render your page correctly when it's being indexed.`);
  str.push('More info at developers.google.com/search/docs/guides/rendering.');
  str.push('
');
  str.push('Features used:');
  str.push('
');
  /* eslint-enable max-len */
  return str;
}

/**
 * Returns true if `feature` is supported by the Google Search bot.
 * @param {string} feature caniuse.com feature name/id.
 * @return {boolean} True if the feature is (likely) supported by Google Search.
 */
function supportedByGoogleSearch(feature) {
  const data = caniuseDB[feature];
  if (!data) {
    return null;
  }
  const support = data.stats.chrome[GOOGLE_SEARCH_CHROME_VERSION];
  return support === 'y'; // TODO: consider 'p'. Partial support / polyfill.
}

/**
 * Injected into the page.
 * @return {!Object} key/val pairs of ids -> feature name
 */
function getPropertyMappings() {
  const timeline = document.querySelector('chromedash-feature-timeline');
  return timeline.props.reduce((accum, property) => {
    const [id, val] = property;
    accum[id] = val;
    return accum;
  }, {});
}

/**
 * Fetches HTML/JS feature id/names from chromestatus.com.
 * @param {!Browser} browser
 * @return {!Object}
 */
async function fetchFeatureToNameMapping(browser) {
  const page = await browser.newPage();
  await page.goto('https://www.chromestatus.com/metrics/feature/timeline/popularity');
  const result = await page.evaluate(getPropertyMappings);
  await page.close();
  return result;
}

/**
 * Fetches CSS property id/names from chromestatus.com
 * @param {!Browser} browser
 * @return {!Object}
 */
async function fetchCSSFeatureToNameMapping(browser) {
  const page = await browser.newPage();
  await page.goto('https://www.chromestatus.com/metrics/css/timeline/popularity');
  const result = await page.evaluate(getPropertyMappings);
  await page.close();
  return result;
}

/**
 * Start a trace during load to capture web platform features used by the page.
 * @param {!Browser} browser
 * @param {string} url
 * @param {string} outfile Trace file name.
 * @return {!Object}
 */
async function collectFeatureTraceEvents(browser, url, outfile) {
  const page = await browser.newPage();

  await page.tracing.start({
    path: outfile,
    categories: [
      '-*',
      'disabled-by-default-devtools.timeline', // for TracingStartedInPage
      'disabled-by-default-blink.feature_usage'
    ],
  });
  await page.goto(url, {waitUntil: 'networkidle2'});
  await page.waitFor(5000); // add a little more time in case other features are used.
  await page.tracing.stop();

  const trace = JSON.parse(fs.readFileSync(outfile, {encoding: 'utf-8'}));

  // Filter out all trace events that aren't 1. blink feature usage
  // and 2. from the same process/thread id as our test page's main thread.
  const traceStartEvent = trace.traceEvents.find(e => e.name === 'TracingStartedInPage');
  const events = trace.traceEvents.filter(e => {
    return e.cat === 'disabled-by-default-blink.feature_usage' &&
           e.pid === traceStartEvent.pid && e.tid === traceStartEvent.tid;
  });

  // // Gut check.
  // console.assert(events.every((entry, i, arr) => {
  //   // const nextIdx = Math.min(i + 1, arr.length - 1);
  //   // return entry.pid === arr[nextIdx].pid && entry.tid === arr[nextIdx].tid;
  //   return entry.pid === traceStartEvent.pid && entry.tid === traceStartEvent.tid;
  // }), 'Trace event is not from the same process/thread id as the page being tested.');

  await page.close();

  return events;
}

/**
 * @param {!Browser} browser
 * @param {string} url
 * @param {string} outfile
 * @return {string} console output
 */
async function run(browser, url, outfile) {
  // Parallelize the separate page loads.
  const [featureIdToName, cssFeatureIdToName, traceEvents] = await Promise.all([
    fetchFeatureToNameMapping(browser),
    fetchCSSFeatureToNameMapping(browser),
    collectFeatureTraceEvents(browser, url, outfile),
  ]);

  const usage = traceEvents.reduce((usage, e) => {
    if (!(e.name in usage)) {
      usage[e.name] = [];
    }
    const id = e.args.feature;
    const isCSS = e.name === 'CSSFirstUsed';
    const name = isCSS ? cssFeatureIdToName[id] : featureIdToName[id];
    usage[e.name].push({id, name, ts: e.ts, css: isCSS});

    return usage;
  }, {});

  // Unique events baed on feature proprety id.
  usage.FeatureFirstUsed = uniqueByProperty(usage.FeatureFirstUsed, 'id');
  usage.CSSFirstUsed = uniqueByProperty(usage.CSSFirstUsed, 'id');

  const lines = printHeader(usage);

  /* eslint-disable no-unused-vars */
  const list = ['
'];
  for (const [id, feature] of Object.entries([...usage.FeatureFirstUsed, ...usage.CSSFirstUsed])) {
    const caniuseName = BlinkFeatureNameToCaniuseName[feature.name];
    const supported = supportedByGoogleSearch(caniuseName);
    if (caniuseName && !supported) {
      const url = `https://caniuse.com/#feat=${caniuseName}`;
      if (feature.css) {
        list.push(
          `<li>CSS \`${feature.name}\`: <a href="${url}" target="_blank">${url}</a></li>`);
      } else {
        list.push(`<li>${feature.name}: <a href="${url}" target="_blank">${url}</a></li>`);
      }
    }
  }
  list.push('
');
  lines.push(...list);

  fs.unlinkSync(outfile);

  return lines.join('');
}

module.exports = {run};
<commit_msg>gsearch: add ES6 modules and list of all features used<commit_after>/**
 * Copyright 2018 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author ebidel@ (Eric Bidelman)
 */

// Adapted from https://github.com/GoogleChromeLabs/puppeteer-examples/blob/master/google_search_features.js.

/* global document */

const fs = require('fs');
const caniuseDB = require('caniuse-db/data.json').data;

const GOOGLE_SEARCH_CHROME_VERSION = process.env.CHROME_VERSION || 41;

/* eslint-disable quote-props */
const BlinkFeatureNameToCaniuseName = {
  AddEventListenerPassiveTrue: 'passive-event-listener',
  AddEventListenerPassiveFalse: 'passive-event-listener',
  PromiseConstructor: 'promises',
  PromiseResolve: 'promises',
  PromiseReject: 'promises',
  V8PromiseChain: 'promises',
  DocumentRegisterElement: 'custom-elements',
  V0CustomElementsRegisterHTMLCustomTag: 'custom-elements',
  V0CustomElementsCreateCustomTagElement: 'custom-elements',
  V0CustomElementsRegisterHTMLTypeExtension: 'custom-elements',
  V0CustomElementsCreateTypeExtensionElement: 'custom-elements',
  CSSSelectorPseudoMatches: 'css-matches-pseudo',
  CustomElementRegistryDefine: 'custom-elementsv1',
  ElementAttachShadow: 'shadowdomv1',
  ElementAttachShadowOpen: 'shadowdomv1',
  ElementAttachShadowClosed: 'shadowdomv1',
  CSSSelectorPseudoSlotted: 'shadowdomv1',
  HTMLSlotElement: 'shadowdomv1',
  CSSSelectorPseudoHost: 'shadowdom',
  ElementCreateShadowRoot: 'shadowdom',
  CSSSelectorPseudoShadow: 'shadowdom',
  CSSSelectorPseudoContent: 'shadowdom',
  CSSSelectorPseudoHostContext: 'shadowdom',
  HTMLShadowElement: 'shadowdom',
  HTMLContentElement: 'shadowdom',
  LinkRelPreconnect: 'link-rel-preconnect',
  LinkRelPreload: 'link-rel-preload',
  HTMLImports: 'imports',
  HTMLImportsAsyncAttribute: 'imports',
  LinkRelModulePreload: 'es6-module',
  V8BroadcastChannel_Constructor: 'broadcastchannel',
  Fetch: 'fetch',
  GlobalCacheStorage: 'cachestorage', // missing: https://github.com/Fyrd/caniuse/issues/3122
  OffMainThreadFetch: 'fetch',
  IntersectionObserver_Constructor: 'intersectionobserver',
  V8Window_RequestIdleCallback_Method: 'requestidlecallback',
  NotificationPermission: 'notifications',
  UnprefixedPerformanceTimeline: 'user-timing',
  V8Element_GetBoundingClientRect_Method: 'getboundingclientrect',
  AddEventListenerThirdArgumentIsObject: 'once-event-listener', // TODO: not a perfect match.
  // TODO: appears to be no UMA tracking for classes, async/await, spread, and
  // other newer js features. Those aren't being caught here.
  contain: 'css-containment',
  'tab-size': 'css3-tabsize',
  // Explicitly disabled by search https://developers.google.com/search/docs/guides/rendering
  UnprefixedIndexedDB: 'indexeddb',
  DocumentCreateEventWebGLContextEvent: 'webgl',
  CSSGridLayout: 'css-grid',
  CSSValueDisplayContents: 'css-display-contents',
  CSSPaintFunction: 'css-paint-api',
  WorkerStart: 'webworkers',
  ServiceWorkerControlledPage: 'serviceworkers',
  PrepareModuleScript: 'es6-module',
  // CookieGet:
  // CookieSet
};
/* eslint-enable quote-props */

/**
 * Unique items based on obj property.
 * @param {!Array} items
 * @param {string} propName Property name to filter on.
 * @return {!Array} unique array of items
 */
function uniqueByProperty(items, propName) {
  const posts = Array.from(items.reduce((map, item) => {
    return map.set(item[propName], item);
  }, new Map()).values());
  return posts;
}

/**
 * Sorts array of features by their name
 * @param {!Object} a
 * @param {!Object} b
 */
function sortByName(a, b) {
  if (a.name  b.name) {
    return 1;
  }
  return 0;
}

/**
 * @param {!Object} usage Feature usage of page.
 * @return {string}
 */
function printHeader(usage) {
  const str = [];
  /* eslint-disable max-len */
  str.push(`
CAREFUL: using ${usage.FeatureFirstUsed.length} HTML/JS and ${usage.CSSFirstUsed.length} CSS features. Some features are not supported by the Google Search crawler. `);
  str.push(`The bot runs <u>Chrome ${GOOGLE_SEARCH_CHROME_VERSION}</u>, which may not render your page correctly when it's being indexed.`);
  str.push('More info at developers.google.com/search/docs/guides/rendering.');
  str.push('
');
  str.push('Features not supported by Google Search:');
  str.push('
');
  /* eslint-enable max-len */
  return str;
}

/**
 * Returns true if `feature` is supported by the Google Search bot.
 * @param {string} feature caniuse.com feature name/id.
 * @return {boolean} True if the feature is (likely) supported by Google Search.
 */
function supportedByGoogleSearch(feature) {
  const data = caniuseDB[feature];
  if (!data) {
    return null;
  }
  const support = data.stats.chrome[GOOGLE_SEARCH_CHROME_VERSION];
  return support === 'y'; // TODO: consider 'p'. Partial support / polyfill.
}

/**
 * Injected into the page.
 * @return {!Object} key/val pairs of ids -> feature name
 */
function getPropertyMappings() {
  const timeline = document.querySelector('chromedash-feature-timeline');
  return timeline.props.reduce((accum, property) => {
    const [id, val] = property;
    accum[id] = val;
    return accum;
  }, {});
}

/**
 * Fetches HTML/JS feature id/names from chromestatus.com.
 * @param {!Browser} browser
 * @return {!Object}
 */
async function fetchFeatureToNameMapping(browser) {
  const page = await browser.newPage();
  await page.goto('https://www.chromestatus.com/metrics/feature/timeline/popularity');
  const result = await page.evaluate(getPropertyMappings);
  await page.close();
  return result;
}

/**
 * Fetches CSS property id/names from chromestatus.com
 * @param {!Browser} browser
 * @return {!Object}
 */
async function fetchCSSFeatureToNameMapping(browser) {
  const page = await browser.newPage();
  await page.goto('https://www.chromestatus.com/metrics/css/timeline/popularity');
  const result = await page.evaluate(getPropertyMappings);
  await page.close();
  return result;
}

/**
 * Start a trace during load to capture web platform features used by the page.
 * @param {!Browser} browser
 * @param {string} url
 * @param {string} outfile Trace file name.
 * @return {!Object}
 */
async function collectFeatureTraceEvents(browser, url, outfile) {
  const page = await browser.newPage();

  await page.tracing.start({
    path: outfile,
    categories: [
      '-*',
      'disabled-by-default-devtools.timeline', // for TracingStartedInPage
      'disabled-by-default-blink.feature_usage'
    ],
  });
  await page.goto(url, {waitUntil: 'networkidle2'});
  await page.waitFor(5000); // add a little more time in case other features are used.
  await page.tracing.stop();

  const trace = JSON.parse(fs.readFileSync(outfile, {encoding: 'utf-8'}));

  // Filter out all trace events that aren't 1. blink feature usage
  // and 2. from the same process/thread id as our test page's main thread.
  const traceStartEvent = trace.traceEvents.find(e => e.name === 'TracingStartedInPage');
  const events = trace.traceEvents.filter(e => {
    return e.cat === 'disabled-by-default-blink.feature_usage' &&
           e.pid === traceStartEvent.pid && e.tid === traceStartEvent.tid;
  });

  // // Gut check.
  // console.assert(events.every((entry, i, arr) => {
  //   // const nextIdx = Math.min(i + 1, arr.length - 1);
  //   // return entry.pid === arr[nextIdx].pid && entry.tid === arr[nextIdx].tid;
  //   return entry.pid === traceStartEvent.pid && entry.tid === traceStartEvent.tid;
  // }), 'Trace event is not from the same process/thread id as the page being tested.');

  await page.close();

  return events;
}

/**
 * @param {!Browser} browser
 * @param {string} url
 * @param {string} outfile
 * @return {string} console output
 */
async function run(browser, url, outfile) {
  // Parallelize the separate page loads.
  const [featureIdToName, cssFeatureIdToName, traceEvents] = await Promise.all([
    fetchFeatureToNameMapping(browser),
    fetchCSSFeatureToNameMapping(browser),
    collectFeatureTraceEvents(browser, url, outfile),
  ]);

  const usage = traceEvents.reduce((usage, e) => {
    if (!(e.name in usage)) {
      usage[e.name] = [];
    }
    const id = e.args.feature;
    const isCSS = e.name === 'CSSFirstUsed';
    const name = isCSS ? cssFeatureIdToName[id] : featureIdToName[id];
    usage[e.name].push({id, name, ts: e.ts, css: isCSS});

    return usage;
  }, {});

  // Unique events baed on feature proprety id.
  usage.FeatureFirstUsed = uniqueByProperty(usage.FeatureFirstUsed, 'id');
  usage.CSSFirstUsed = uniqueByProperty(usage.CSSFirstUsed, 'id');

  const lines = printHeader(usage);

  /* eslint-disable no-unused-vars */
  const allFeaturesUsed = Object.entries(
    [...usage.FeatureFirstUsed, ...usage.CSSFirstUsed].sort(sortByName));
  let list = ['
'];
  for (const [id, feature] of allFeaturesUsed) {
    const caniuseName = BlinkFeatureNameToCaniuseName[feature.name];
    const supported = supportedByGoogleSearch(caniuseName);
    if (caniuseName && !supported) {
      const url = `https://caniuse.com/#feat=${caniuseName}`;
      if (feature.css) {
        list.push(
          `<li>CSS \`${feature.name}\`: <a href="${url}" target="_blank">${url}</a></li>`);
      } else {
        list.push(`<li>${feature.name}: <a href="${url}" target="_blank">${url}</a></li>`);
      }
    }
  }
  list.push('
');
  lines.push(...list);

  list = ['
'];
  lines.push('
All features used:
');
  for (const [id, feature] of allFeaturesUsed) {
    if (feature.css) {
      list.push(`<li>CSS \`${feature.name}\`</li>`);
    } else {
      list.push(`<li>${feature.name}</li>`);
    }
  }
  list.push('
');
  lines.push(...list);

  fs.unlinkSync(outfile);

  return lines.join('');
}

module.exports = {run};
<|endoftext|>


<commit_before>r3.stacked_bargraph = function (graphdef) {
	r3.graph.call(this);
	graphdef.stepup = true;
	this.init(graphdef);

	this.bargroups = [];

	var bargroup, bars, idx, len, color,
		domainData = this.labels,
		csum = domainData.map(function (d) {return 0; }),
		tsum = domainData.map(function (d) {return 0; });

	this.axes[this.graphdef.orientation === 'hor' ? 'ver' : 'hor'].scale.domain(domainData);

	for (idx = 0, len = this.categories.length; idx < len; idx = idx + 1) {
		color = r3.util.getColorBand(this.config, idx);

		bargroup = this.panel.append('g').attr('class', 'r3_bargroup');
		bars = bargroup.selectAll('g').data(this.graphdef.dataset[this.categories[idx]]).enter().append('g').attr('class', 'stackedbar_' + this.categories[idx]);

		this['drawStack' + r3.util.getPascalCasedName(this.graphdef.orientation) + 'Bars'](bars, csum, tsum, idx);

		if (this.graphdef.orientation === 'ver') {
			bargroup.attr('transform', 'translate(0,' + 2 * this.height() + ') scale(1,-1)');
		}

		this.bargroups.push(bargroup);
	}

	this.finalize();
};

r3.stacked_bargraph.prototype = r3.util.extend(r3.graph);

r3.stacked_bargraph.prototype.drawStackHorBars = function (bars, csum, tsum, idx) {
	var axes = this.axes, color = r3.util.getColorBand(this.config, idx), config = this.config;
	bars.append('rect')
		.attr('height', axes.ver.scale.rangeBand())
		.attr('width', 0)
		.attr('x', function (d, i) { var value = axes.hor.scale(csum[i]); csum[i] += d.value; return value; })
		.attr('y', function (d) {return axes.ver.scale(d.name); })
		.style('stroke', 'none')
		.style('fill', color)
		.on('mouseover', r3.effects.bar.mouseover(config))
		.on('mouseout',  r3.effects.bar.mouseout(config, color))
		.transition()
			.duration(r3.config.effects.duration)
			.delay(idx * r3.config.effects.duration)
			.attr('width', function (d) { return axes.hor.scale(d.value); });

	bars.append('text')
		.attr('y', function(d) { return axes.ver.scale(d.name) + axes.ver.scale.rangeBand()/2; })
		.attr('dx', 0)
		.attr('dy', '.35em')
		.attr('text-anchor', 'end')
		.style('fill', 'none')
		.style('font-family', this.config.bar.fontfamily)
		.style('font-size', this.config.bar.fontsize)
		.style('font-weight', this.config.bar.fontweight)
		.text(function(d) { return ( axes.hor.scale(d.value) > 15 ) ? String(d.value) : null; })
		.transition()
			.duration(r3.config.effects.duration)
			.delay(idx * r3.config.effects.duration)
			.attr('x', function (d, i) { tsum[i] += d.value; return axes.hor.scale(tsum[i]) - 5; });
};

r3.stacked_bargraph.prototype.drawStackVerBars = function (bars, csum, tsum, idx) {
	var height = this.height(), axes = this.axes, color = r3.util.getColorBand(this.config, idx), config = this.config;
	bars.append('rect')
		.attr('height', 0)
		.attr('width', axes.hor.scale.rangeBand())
		.attr('x', function (d) { return axes.hor.scale(d.name); })
		.attr('y', function (d, i) { var value = axes.ver.scale(csum[i]); csum[i] -= d.value; return value; })
		.style('stroke', 'none')
		.style('fill', color)
		.on('mouseover', r3.effects.bar.mouseover(config))
		.on('mouseout',  r3.effects.bar.mouseout(config, color))
		.transition()
			.duration(r3.config.effects.duration)
			.delay(idx * r3.config.effects.duration)
			.attr('height', function (d) { return height - axes.ver.scale(d.value); });

	bars.append('text').attr('transform','scale(1,-1)')
		.attr('x', function(d) { return axes.hor.scale(d.name) + axes.hor.scale.rangeBand()/2; })
		.attr('y', -height + 5)
		.attr('dy', '.71em')
		.attr('text-anchor', 'middle')
		.style('fill', 'none')
		.style('font-family', this.config.bar.fontfamily)
		.style('font-size', this.config.bar.fontsize)
		.style('font-weight', this.config.bar.fontweight)
		.text(function(d) { return ( height - axes.ver.scale(d.value) > 15) ? String(d.value) : null; })
		.transition()
			.duration(r3.config.effects.duration)
			.delay(idx * r3.config.effects.duration)
			.attr('y', function (d, i) { tsum[i] += d.value; return -(2*height - axes.ver.scale(tsum[i])) + 5; });
};<commit_msg>refined code for stacked bar graph<commit_after>r3.stacked_bargraph = function (graphdef) {
	r3.graph.call(this);
	graphdef.stepup = true;
	this.init(graphdef);

	this.bargroups = {};

	var bargroup, bars, idx, len, color,
		domainData = this.labels,
		csum = domainData.map(function (d) {return 0; }),
		tsum = domainData.map(function (d) {return 0; });

	this.axes[this.graphdef.orientation === 'hor' ? 'ver' : 'hor'].scale.domain(domainData);

	for (idx = 0, len = this.categories.length; idx < len; idx = idx + 1) {
		this.bargroups[this.categories[idx]] = this.panel.append('g').attr('class', 'r3_stackedbargroup_' + this.categories[idx]);
		this['drawStack' + r3.util.getPascalCasedName(this.graphdef.orientation) + 'Bars'](idx, csum, tsum);
	}

	this.finalize();
};

r3.stacked_bargraph.prototype = r3.util.extend(r3.graph);

r3.stacked_bargraph.prototype.drawStackHorBars = function (idx, csum, tsum) {
	var axes = this.axes,
		color = r3.util.getColorBand(this.config, idx),
		config = this.config,
		bargroup = this.bargroups[this.categories[idx]];

	bars = bargroup.selectAll('g').data(this.graphdef.dataset[this.categories[idx]])
				.enter().append('g').attr('class', 'r3_stackedbar_' + this.categories[idx]);

	bars.append('rect')
		.attr('height', axes.ver.scale.rangeBand())
		.attr('width', 0)
		.attr('x', function (d, i) { var value = axes.hor.scale(csum[i]); csum[i] += d.value; return value; })
		.attr('y', function (d) {return axes.ver.scale(d.name); })
		.style('stroke', 'none')
		.style('fill', color)
		.on('mouseover', r3.effects.bar.mouseover(config))
		.on('mouseout',  r3.effects.bar.mouseout(config, color))
		.transition()
			.duration(r3.config.effects.duration)
			.delay(idx * r3.config.effects.duration)
			.attr('width', function (d) { return axes.hor.scale(d.value); });

	bars.append('text')
		.attr('y', function(d) { return axes.ver.scale(d.name) + axes.ver.scale.rangeBand()/2; })
		.attr('dx', 0)
		.attr('dy', '.35em')
		.attr('text-anchor', 'end')
		.style('fill', 'none')
		.style('font-family', config.bar.fontfamily)
		.style('font-size', config.bar.fontsize)
		.style('font-weight', config.bar.fontweight)
		.text(function(d) { return ( axes.hor.scale(d.value) > 15 ) ? String(d.value) : null; })
		.transition()
			.duration(r3.config.effects.duration)
			.delay(idx * r3.config.effects.duration)
			.attr('x', function (d, i) { tsum[i] += d.value; return axes.hor.scale(tsum[i]) - 5; });
};

r3.stacked_bargraph.prototype.drawStackVerBars = function (idx, csum, tsum) {
	var height = this.height(),
		axes = this.axes,
		color = r3.util.getColorBand(this.config, idx),
		config = this.config,
		bargroup = this.bargroups[this.categories[idx]];

	bars = bargroup.selectAll('g').data(this.graphdef.dataset[this.categories[idx]])
				.enter().append('g').attr('class', 'r3_stackedbar_' + this.categories[idx]);

	bars.append('rect')
		.attr('height', 0)
		.attr('width', axes.hor.scale.rangeBand())
		.attr('x', function (d) { return axes.hor.scale(d.name); })
		.attr('y', function (d, i) { var value = axes.ver.scale(csum[i]); csum[i] -= d.value; return value; })
		.style('stroke', 'none')
		.style('fill', color)
		.on('mouseover', r3.effects.bar.mouseover(config))
		.on('mouseout',  r3.effects.bar.mouseout(config, color))
		.transition()
			.duration(r3.config.effects.duration)
			.delay(idx * r3.config.effects.duration)
			.attr('height', function (d) { return height - axes.ver.scale(d.value); });

	bars.append('text').attr('transform','scale(1,-1)')
		.attr('x', function(d) { return axes.hor.scale(d.name) + axes.hor.scale.rangeBand()/2; })
		.attr('y', -height + 5)
		.attr('dy', '.71em')
		.attr('text-anchor', 'middle')
		.style('fill', 'none')
		.style('font-family', config.bar.fontfamily)
		.style('font-size', config.bar.fontsize)
		.style('font-weight', config.bar.fontweight)
		.text(function(d) { return ( height - axes.ver.scale(d.value) > 15) ? String(d.value) : null; })
		.transition()
			.duration(r3.config.effects.duration)
			.delay(idx * r3.config.effects.duration)
			.attr('y', function (d, i) { tsum[i] += d.value; return -(2*height - axes.ver.scale(tsum[i])) + 5; });

	bargroup.attr('transform', 'translate(0,' + 2 * this.height() + ') scale(1,-1)');
};<|endoftext|>


<commit_before>(function(){
	// Express server authentication
    // -----------------------------

	// Function helpers to make restricting routes and
	// accessing session info easier
    var Auth;
    if (typeof exports !== 'undefined') {
		// Dependancies
        Keys = require('keys');
        Auth = module.exports = {};
        Hash = require('./hash');
    } else {
        Auth = this.Auth = {};
    }

    // Hashing salt
    salt = "aebleskiver";

    // Storage container
    var store = new Keys.Redis();

    // Check for buffered data
    var buffered = true;
    if (store instanceof Keys.Redis) buffered = false;

	// Authenticate user with password
	Auth.authenticate = function(data, next) {
        if (!data.username || !data.password) return;

        var key = 'users:' + data.username;

        store.has(key, function(err, exists) {
            if (!exists) {
                // Uer could not be found
                next(new Error('No such user'));
            } else {
                // Check password
                store.get(key + '.password', function(err, val) {
                    val = buffered ? val.toString('utf8') : val;

                    var hashed = Hash.sha1(data.password, salt + data.username);
                    if (hashed === val) {
                        // Retrieve public accessable data
                        store.get(key, function(err, val) {
                            val = buffered ? val.toString('utf8') : val;
                            return next(null, JSON.parse(val));
                        });
                    } else {
                        next(new Error('Invalid password'));
                    }
                });
            }
        });
	};

	// Register a new user
	Auth.register = function(data, next) {
        if (!data.username || !data.password || !data.email) return;

        var key = 'users:' + data.username;
        var model = {
            id       : data.username,
            name     : data.displayname || data.username,
            username : data.username,
            email    : data.email,
        };

        store.has(key, function(err, exists) {
            if (exists) {
                // User already exists
                next(new Error('Username taken'));
                return;
            }
            // Create user
            store.set(key, JSON.stringify(model), function() {
                // Save password
                var hashed = Hash.sha1(data.password, salt + data.username);
                store.set(key + '.password', hashed, function() {
                    return next(null, model);
                });
            });
        });
	};

	// Restrict access to route
	Auth.restricted = function(req, res, next) {
		if (req.session.user) {
            // User found, move along
			next();
		} else {
            // Force login
			req.flash('error', 'Access denied');
			res.redirect('/login');
		}
	};
})()<commit_msg>Removing express auth middleware<commit_after><|endoftext|>