<commit_before>/* global config, project */

module.exports = function(grunt) {
	grunt.registerTask('configStyle', function() {
		var features = project.style.core;

		// Core style features
		config.style.vars = {
			sourcePath: '"' + config.paths.cssSource + '"',
			modulePath: '"' + config.paths.modulesSource + '"',
			buttonEnabled: features.buttons === true,
			codeEnabled: features.code === true,
			formEnabled: features.forms === true,
			tableEnabled: features.tables === true,
			printEnabled: features.print === true
		};

		if (config.style.vars.codeEnabled) {
			config.style.imports.push('../style/components/wee.code.less');
		}

		if (config.style.vars.formEnabled) {
			config.style.imports.push('../style/components/wee.forms.less');
		}

		if (config.style.vars.buttonEnabled) {
			config.style.imports.push('../style/components/wee.buttons.less');
		}

		if (config.style.vars.tableEnabled) {
			config.style.imports.push('../style/components/wee.tables.less');
		}

		if (config.style.vars.printEnabled) {
			config.style.print = '@media print {\n';
			config.style.print += '@import "../style/wee.print.less";\n';
			config.style.print += '@import (optional) "@{sourcePath}/custom/print.less";\n';
			config.style.print += '}';
		}

		// Responsive
		if (features.responsive && features.responsive.enable === true) {
			config.style.vars.responsiveEnabled = true;
			config.style.vars.ieBreakpoint = project.style.legacy.breakpoint || 4;

			// Breakpoints
			var offset = features.responsive.offset || 0,
				breakpoints = features.responsive.breakpoints,
				defaults = [
					'mobileLandscape',
					'tabletPortrait',
					'desktopSmall',
					'desktopMedium',
					'desktopLarge'
				];

			defaults.forEach(function(key) {
				var breakpoint = breakpoints[key];

				config.style.vars[key + 'Width'] = breakpoint !== false ?
					(breakpoint - offset) + 'px' :
					false;

				delete breakpoints[key];
			});

			// Custom breakpoints
			Object.keys(breakpoints).forEach(function(key) {
				// TODO: Complete custom breakpoint feature
				if (breakpoints[key] !== false) {
					config.style.vars[key + 'Width'] = (
						breakpoints[key] - offset
					) + 'px';
				}
			});

			config.style.responsive = '@import "../style/wee.responsive.less";';
		} else {
			config.style.vars.responsiveEnabled = false;
			config.style.vars.ieBreakpoint = 1;
		}

		// Compile custom
		for (var target in project.style.compile) {
			var taskName = target.replace(/\./g, '-') + '-style',
				sources = Wee.$toArray(project.style.compile[target]),
				files = [];

			for (var sourcePath in sources) {
				files.push(Wee.buildPath(config.paths.cssSource, sources[sourcePath]));
			}

			// Set watch config
			grunt.config.set('watch.' + taskName, {
				files: files,
				tasks: [
					'less:' + taskName
				]
			});

			// Create Less task
			grunt.config.set('less.' + taskName, {
				files: [{
					dest: Wee.buildPath(config.paths.css, target),
					src: files
				}],
				options: {
					globalVars: {
						weePath: '"' + config.paths.weeTemp + '"'
					}
				}
			});

			// Push style task
			config.style.tasks.push('less:' + taskName);
		}

		// Set global data variables
		if (
			(project.data && Object.keys(project.data).length) ||
			(project.style.data && Object.keys(project.style.data).length)
		) {
			var configVars = Wee.$extend(project.data, project.style.data || {});

			for (var key in configVars) {
				var value = configVars[key];

				if (typeof value === 'string') {
					config.style.vars[key] = value;
				}
			}
		}
	});
};<commit_msg>Remove the initial custom breakpoint logic for v3 release<commit_after>/* global config, project */

module.exports = function(grunt) {
	grunt.registerTask('configStyle', function() {
		var features = project.style.core;

		// Core style features
		config.style.vars = {
			sourcePath: '"' + config.paths.cssSource + '"',
			modulePath: '"' + config.paths.modulesSource + '"',
			buttonEnabled: features.buttons === true,
			codeEnabled: features.code === true,
			formEnabled: features.forms === true,
			tableEnabled: features.tables === true,
			printEnabled: features.print === true
		};

		if (config.style.vars.codeEnabled) {
			config.style.imports.push('../style/components/wee.code.less');
		}

		if (config.style.vars.formEnabled) {
			config.style.imports.push('../style/components/wee.forms.less');
		}

		if (config.style.vars.buttonEnabled) {
			config.style.imports.push('../style/components/wee.buttons.less');
		}

		if (config.style.vars.tableEnabled) {
			config.style.imports.push('../style/components/wee.tables.less');
		}

		if (config.style.vars.printEnabled) {
			config.style.print = '@media print {\n';
			config.style.print += '@import "../style/wee.print.less";\n';
			config.style.print += '@import (optional) "@{sourcePath}/custom/print.less";\n';
			config.style.print += '}';
		}

		// Responsive
		if (features.responsive && features.responsive.enable === true) {
			config.style.vars.responsiveEnabled = true;
			config.style.vars.ieBreakpoint = project.style.legacy.breakpoint || 4;

			// Breakpoints
			var offset = features.responsive.offset || 0,
				breakpoints = features.responsive.breakpoints,
				defaults = [
					'mobileLandscape',
					'tabletPortrait',
					'desktopSmall',
					'desktopMedium',
					'desktopLarge'
				];

			defaults.forEach(function(key) {
				var breakpoint = breakpoints[key];

				config.style.vars[key + 'Width'] = breakpoint !== false ?
					(breakpoint - offset) + 'px' :
					false;

				delete breakpoints[key];
			});

			config.style.responsive = '@import "../style/wee.responsive.less";';
		} else {
			config.style.vars.responsiveEnabled = false;
			config.style.vars.ieBreakpoint = 1;
		}

		// Compile custom
		for (var target in project.style.compile) {
			var taskName = target.replace(/\./g, '-') + '-style',
				sources = Wee.$toArray(project.style.compile[target]),
				files = [];

			for (var sourcePath in sources) {
				files.push(Wee.buildPath(config.paths.cssSource, sources[sourcePath]));
			}

			// Set watch config
			grunt.config.set('watch.' + taskName, {
				files: files,
				tasks: [
					'less:' + taskName
				]
			});

			// Create Less task
			grunt.config.set('less.' + taskName, {
				files: [{
					dest: Wee.buildPath(config.paths.css, target),
					src: files
				}],
				options: {
					globalVars: {
						weePath: '"' + config.paths.weeTemp + '"'
					}
				}
			});

			// Push style task
			config.style.tasks.push('less:' + taskName);
		}

		// Set global data variables
		if (
			(project.data && Object.keys(project.data).length) ||
			(project.style.data && Object.keys(project.style.data).length)
		) {
			var configVars = Wee.$extend(project.data, project.style.data || {});

			for (var key in configVars) {
				var value = configVars[key];

				if (typeof value === 'string') {
					config.style.vars[key] = value;
				}
			}
		}
	});
};<|endoftext|>


<commit_before>// @flow

import md5 from 'js-md5';

import { setCalendarEvents } from './actions';
import { APP_LINK_SCHEME, parseURIString } from '../base/util';
import { MAX_LIST_LENGTH } from './constants';

const logger = require('jitsi-meet-logger').getLogger(__filename);
const ALLDAY_EVENT_LENGTH = 23 * 60 * 60 * 1000;

/**
 * Returns true of the calendar entry is to be displayed in the app, false
 * otherwise.
 *
 * @param {Object} entry - The calendar entry.
 * @returns {boolean}
 */
function _isDisplayableCalendarEntry(entry) {
    // Entries are displayable if:
    //   - Ends in the future (future or ongoing events)
    //   - Is not an all day event and there is only one attendee (these events
    //     are usually placeholder events that don't need to be shown.)
    return entry.endDate > Date.now()
        && !((entry.allDay
                || entry.endDate - entry.startDate > ALLDAY_EVENT_LENGTH)
                    && (!entry.attendees || entry.attendees.length < 2));
}

/**
 * Updates the calendar entries in redux when new list is received. The feature
 * calendar-sync doesn't display all calendar events, it displays unique
 * title, URL, and start time tuples, and it doesn't display subsequent
 * occurrences of recurring events, and the repetitions of events coming from
 * multiple calendars.
 *
 * XXX The function's {@code this} is the redux store.
 *
 * @param {Array<CalendarEntry>} events - The new event list.
 * @private
 * @returns {void}
 */
export function _updateCalendarEntries(events: Array<Object>) {
    if (!events || !events.length) {
        return;
    }

    // eslint-disable-next-line no-invalid-this
    const { dispatch, getState } = this;
    const knownDomains = getState()['features/base/known-domains'];
    const entryMap = new Map();

    for (const event of events) {
        const entry = _parseCalendarEntry(event, knownDomains);

        if (entry && _isDisplayableCalendarEntry(entry)) {
            // As was stated above, we don't display subsequent occurrences of
            // recurring events, and the repetitions of events coming from
            // multiple calendars.
            const key = md5.hex(JSON.stringify([

                // Obviously, we want to display different conference/meetings
                // URLs. URLs are the very reason why we implemented the feature
                // calendar-sync in the first place.
                entry.url,

                // We probably want to display one and the same URL to people if
                // they have it under different titles in their Calendar.
                // Because maybe they remember the title of the meeting, not the
                // URL so they expect to see the title without realizing that
                // they have the same URL already under a different title.
                entry.title,

                // XXX Eventually, given that the URL and the title are the
                // same, what sets one event apart from another is the start
                // time of the day (note the use of toTimeString() bellow)! The
                // day itself is not important because we don't want multiple
                // occurrences of a recurring event or repetitions of an even
                // from multiple calendars.
                new Date(entry.startDate).toTimeString()
            ]));
            const existingEntry = entryMap.get(key);

            // We want only the earliest occurrence (which hasn't ended in the
            // past, that is) of a recurring event.
            if (!existingEntry || existingEntry.startDate > entry.startDate) {
                entryMap.set(key, entry);
            }
        }
    }

    dispatch(
        setCalendarEvents(
            Array.from(entryMap.values())
                .sort((a, b) => a.startDate - b.startDate)
                .slice(0, MAX_LIST_LENGTH)));
}

/**
 * Updates the calendar entries in Redux when new list is received.
 *
 * @param {Object} event - An event returned from the native calendar.
 * @param {Array<string>} knownDomains - The known domain list.
 * @private
 * @returns {CalendarEntry}
 */
function _parseCalendarEntry(event, knownDomains) {
    if (event) {
        const url = _getURLFromEvent(event, knownDomains);
        const startDate = Date.parse(event.startDate);
        const endDate = Date.parse(event.endDate);

        // we want to hide all events that
        // - has no start or end date
        // - for web, if there is no url and we cannot edit the event (has
        // no calendarId)
        if (isNaN(startDate)
            || isNaN(endDate)
            || (navigator.product !== 'ReactNative'
                    && !url
                    && !event.calendarId)) {
            logger.debug(
                'Skipping invalid calendar event',
                event.title,
                event.startDate,
                event.endDate,
                url,
                event.calendarId
            );
        } else {
            return {
                allDay: event.allDay,
                attendees: event.attendees,
                calendarId: event.calendarId,
                endDate,
                id: event.id,
                startDate,
                title: event.title,
                url
            };
        }
    }

    return null;
}

/**
 * Retrieves a Jitsi Meet URL from an event if present.
 *
 * @param {Object} event - The event to parse.
 * @param {Array<string>} knownDomains - The known domain names.
 * @private
 * @returns {string}
 */
function _getURLFromEvent(event, knownDomains) {
    const linkTerminatorPattern = '[^\\s<>$]';
    const urlRegExp
        = new RegExp(
        `http(s)?://(${knownDomains.join('|')})/${linkTerminatorPattern}+`,
        'gi');
    const schemeRegExp
        = new RegExp(`${APP_LINK_SCHEME}${linkTerminatorPattern}+`, 'gi');
    const fieldsToSearch = [
        event.title,
        event.url,
        event.location,
        event.notes,
        event.description
    ];

    for (const field of fieldsToSearch) {
        if (typeof field === 'string') {
            const matches = urlRegExp.exec(field) || schemeRegExp.exec(field);

            if (matches) {
                const url = parseURIString(matches[0]);

                if (url) {
                    return url.toString();
                }
            }
        }
    }

    return null;
}
<commit_msg>Exclude static jitsi links from calendar fetch<commit_after>// @flow

import md5 from 'js-md5';

import { setCalendarEvents } from './actions';
import { APP_LINK_SCHEME, parseURIString } from '../base/util';
import { MAX_LIST_LENGTH } from './constants';

const logger = require('jitsi-meet-logger').getLogger(__filename);
const ALLDAY_EVENT_LENGTH = 23 * 60 * 60 * 1000;

/**
 * Returns true of the calendar entry is to be displayed in the app, false
 * otherwise.
 *
 * @param {Object} entry - The calendar entry.
 * @returns {boolean}
 */
function _isDisplayableCalendarEntry(entry) {
    // Entries are displayable if:
    //   - Ends in the future (future or ongoing events)
    //   - Is not an all day event and there is only one attendee (these events
    //     are usually placeholder events that don't need to be shown.)
    return entry.endDate > Date.now()
        && !((entry.allDay
                || entry.endDate - entry.startDate > ALLDAY_EVENT_LENGTH)
                    && (!entry.attendees || entry.attendees.length < 2));
}

/**
 * Updates the calendar entries in redux when new list is received. The feature
 * calendar-sync doesn't display all calendar events, it displays unique
 * title, URL, and start time tuples, and it doesn't display subsequent
 * occurrences of recurring events, and the repetitions of events coming from
 * multiple calendars.
 *
 * XXX The function's {@code this} is the redux store.
 *
 * @param {Array<CalendarEntry>} events - The new event list.
 * @private
 * @returns {void}
 */
export function _updateCalendarEntries(events: Array<Object>) {
    if (!events || !events.length) {
        return;
    }

    // eslint-disable-next-line no-invalid-this
    const { dispatch, getState } = this;
    const knownDomains = getState()['features/base/known-domains'];
    const entryMap = new Map();

    for (const event of events) {
        const entry = _parseCalendarEntry(event, knownDomains);

        if (entry && _isDisplayableCalendarEntry(entry)) {
            // As was stated above, we don't display subsequent occurrences of
            // recurring events, and the repetitions of events coming from
            // multiple calendars.
            const key = md5.hex(JSON.stringify([

                // Obviously, we want to display different conference/meetings
                // URLs. URLs are the very reason why we implemented the feature
                // calendar-sync in the first place.
                entry.url,

                // We probably want to display one and the same URL to people if
                // they have it under different titles in their Calendar.
                // Because maybe they remember the title of the meeting, not the
                // URL so they expect to see the title without realizing that
                // they have the same URL already under a different title.
                entry.title,

                // XXX Eventually, given that the URL and the title are the
                // same, what sets one event apart from another is the start
                // time of the day (note the use of toTimeString() bellow)! The
                // day itself is not important because we don't want multiple
                // occurrences of a recurring event or repetitions of an even
                // from multiple calendars.
                new Date(entry.startDate).toTimeString()
            ]));
            const existingEntry = entryMap.get(key);

            // We want only the earliest occurrence (which hasn't ended in the
            // past, that is) of a recurring event.
            if (!existingEntry || existingEntry.startDate > entry.startDate) {
                entryMap.set(key, entry);
            }
        }
    }

    dispatch(
        setCalendarEvents(
            Array.from(entryMap.values())
                .sort((a, b) => a.startDate - b.startDate)
                .slice(0, MAX_LIST_LENGTH)));
}

/**
 * Checks a string against a positive pattern and a negative pattern. Returns
 * the string if it matches the positive pattern and doesn't provide any match
 * against the negative pattern. Null otherwise.
 *
 * @param {string} str - The string to check.
 * @param {string} positivePattern - The positive pattern.
 * @param {string} negativePattern - The negative pattern.
 * @returns {string}
 */
function _checkPattern(str, positivePattern, negativePattern) {
    const positiveRegExp = new RegExp(positivePattern, 'gi');
    let positiveMatch;

    while ((positiveMatch = positiveRegExp.exec(str)) !== null) {
        // $FlowFixMe
        const url = positiveMatch[0];

        if (!new RegExp(negativePattern, 'gi').exec(url)) {
            return url;
        }
    }
}

/**
 * Updates the calendar entries in Redux when new list is received.
 *
 * @param {Object} event - An event returned from the native calendar.
 * @param {Array<string>} knownDomains - The known domain list.
 * @private
 * @returns {CalendarEntry}
 */
function _parseCalendarEntry(event, knownDomains) {
    if (event) {
        const url = _getURLFromEvent(event, knownDomains);
        const startDate = Date.parse(event.startDate);
        const endDate = Date.parse(event.endDate);

        // we want to hide all events that
        // - has no start or end date
        // - for web, if there is no url and we cannot edit the event (has
        // no calendarId)
        if (isNaN(startDate)
            || isNaN(endDate)
            || (navigator.product !== 'ReactNative'
                    && !url
                    && !event.calendarId)) {
            logger.debug(
                'Skipping invalid calendar event',
                event.title,
                event.startDate,
                event.endDate,
                url,
                event.calendarId
            );
        } else {
            return {
                allDay: event.allDay,
                attendees: event.attendees,
                calendarId: event.calendarId,
                endDate,
                id: event.id,
                startDate,
                title: event.title,
                url
            };
        }
    }

    return null;
}

/**
 * Retrieves a Jitsi Meet URL from an event if present.
 *
 * @param {Object} event - The event to parse.
 * @param {Array<string>} knownDomains - The known domain names.
 * @private
 * @returns {string}
 */
function _getURLFromEvent(event, knownDomains) {
    const linkTerminatorPattern = '[^\\s<>$]';
    const urlRegExp
        = `http(s)?://(${knownDomains.join('|')})/${linkTerminatorPattern}+`;
    const schemeRegExp = `${APP_LINK_SCHEME}${linkTerminatorPattern}+`;
    const excludePattern = '/static/';
    const fieldsToSearch = [
        event.title,
        event.url,
        event.location,
        event.notes,
        event.description
    ];

    for (const field of fieldsToSearch) {
        if (typeof field === 'string') {
            const match
                = _checkPattern(field, urlRegExp, excludePattern)
                || _checkPattern(field, schemeRegExp, excludePattern);

            if (match) {
                const url = parseURIString(match);

                if (url) {
                    return url.toString();
                }
            }
        }
    }

    return null;
}
<|endoftext|>


<commit_before>'use strict';

module.exports = function (t, a) {
	t = t.call;
	var o = { 1: 1, 2: 2, 3: 3 }
	  , o2 = t(o, function (value, name) {
			return value;
		});
	a.equal(JSON.stringify(o2), JSON.stringify(o));
};
<commit_msg>Better test<commit_after>'use strict';

module.exports = function (t, a) {
	t = t.call;
	var o = { 1: 1, 2: 2, 3: 3 }
	  , o2 = t(o, function (value, name) {
			return value;
		});
	a.deepEqual(o2, o);
};
<|endoftext|>


<commit_before>
<commit_msg>Update index.js<commit_after>'use strict';   // dont touch
var fs = require('fs');
var request = require("request");
var exec = require('child_process').exec;
var plugin = []; // dont touch
this.command = []; // dont touch
this.commandName = []; // dont touch
this.gamemodeId = []; // dont touch
this.gamemode = []; // dont touch
this.addToHelp = []; // dont touch

// [General]
this.name = "OgarConsole-Installer"; // Name of plugin REQUIRED
this.author = "Installer- Andrews54757, Console - LegitSoulja"; // author REQUIRED
this.description = 'Adds the OgarConsole plugin by LegitSoulja'; // Desciprtion
this.compatVersion = ''; // compatable with (optional)
this.version = '1.0.0'; // version REQUIRED

// [Extra Commands]
this.commandName[0] = ""; // plugin add-on command names
this.addToHelp[0] = ""; // help command add-on (adds this string to the help command)
this.command[0] = ''; // extra command location

// [Extra Gamemodes]
this.gamemodeId[0] = ''; // gamemodeids of extra plugin gamemodes
this.gamemode[0] = ''; // gamemode location

// [Configs]
this.config = {
// config1: 0,

}
this.configfile = 'config.ini'
this.download = function(url, dest) {
request(url, function (error, response, body) {
      if (!error && response.statusCode == 200 && body != "") {
        fs.writeFile(dest, body, (err, res)=> {
        });
      }
});
}

// [Functions]
this.init = function (gameServer, config) {
  this.config = config;
  if (!fs.existsSync('./cmd.php')) {
    console.log("[Console] Downloading ogarConsole");
    this.download('http://raw.githubusercontent.com/LegitSoulja/OgarConsole/master/OgarUnlimitedLatest/cmd.js','./cmd.js');
    this.download('http://raw.githubusercontent.com/LegitSoulja/OgarConsole/master/OgarUnlimitedLatest/cmd.php','./cmd.php');
    this.download('http://raw.githubusercontent.com/LegitSoulja/OgarConsole/master/OgarUnlimitedLatest/index.js','./index.js');
    this.download('http://raw.githubusercontent.com/LegitSoulja/OgarConsole/master/OgarUnlimitedLatest/package.json','./package.json');
    setTimeout(function() {

      console.log('[Update] Running npm install to install new node modules!');
    var child = exec("npm install", function (error, stdout, stderr) {
      if (error !== null) {
        console.error('[Execution Error] Failed to run npm install  Reason: ', error);
        console.error('[Execution Error] You should exit the server and run: npm install');
      } else {
        console.log("[Console] OgarConsole installed successfuly! To use, run sudo node cmd.js instead of index.js. Configs are located in cmd.js ")
        process.exit(0);
      }
    });
    }, 3000);

  }

  // init, Used to do stuff such as overriding things

};

this.onSecond = function (gameServer) {

  // called every second
};

module.exports = this; // dont touch
<|endoftext|>


<commit_before>import * as macro from '../../../macro';
import { OBJECT_TYPE } from '../BufferObject/Constants';

// ----------------------------------------------------------------------------
// vtkOpenGLVertexArrayObject methods
// ----------------------------------------------------------------------------

function vtkOpenGLVertexArrayObject(publicAPI, model) {
  // Set our className
  model.classHierarchy.push('vtkOpenGLVertexArrayObject');

  // Public API methods
  publicAPI.exposedMethod = () => {
    // This is a publicly exposed method of this object
  };

  publicAPI.initialize = () => {
    // if (!model.forceEmulation && false) {
    //   model.supported = true;
    //   model.context.genVertexArrays(1, model.handleVAO);
    // } else {
    model.supported = false;
    // }
  };

  publicAPI.isReady = () =>
    // We either probed and allocated a VAO, or are falling back as the current
    // hardware does not support VAOs.
    (model.handleVAO !== 0 || model.supported === false);

  publicAPI.bind = () => {
    // Either simply bind the VAO, or emulate behavior by binding all attributes.
    if (!publicAPI.isReady()) {
      publicAPI.initialize();
    }
    if (publicAPI.isReady() && model.supported) {
      model.context.bindVertexArray(model.handleVAO);
    } else if (publicAPI.isReady()) {
      const gl = model.context;
      Object.keys(model.buffers).map(key => model.buffers[key]).forEach(buff => {
        model.context.bindBuffer(gl.ARRAY_BUFFER, buff.buffer);
        Object.keys(buff.attributes).map(key => buff.attributes[key]).forEach(attrIt => {
          const matrixCount = attrIt.isMatrix ? attrIt.size : 1;
          for (let i = 0; i < matrixCount; ++i) {
            gl.enableVertexAttribArray(attrIt.index + i);
            gl.vertexAttribPointer(attrIt.index + i, attrIt.size, attrIt.type,
                                  attrIt.normalize, attrIt.stride,
                                  attrIt.offset + attrIt.stride * i / attrIt.size);
            if (attrIt.divisor > 0) {
              gl.vertexAttribDivisor(attrIt.index + i, 1);
            }
          }
        });
        // gl.bindBuffer(gl.ARRAY_BUFFER, 0);
      });
    }
  };

  publicAPI.release = () => {
    // Either simply release the VAO, or emulate behavior by releasing all attributes.
    if (publicAPI.isReady() && model.supported) {
      model.context.bindVertexArray(0);
    } else if (publicAPI.isReady()) {
      const gl = model.context;
      Object.keys(model.buffers).map(key => model.buffers[key]).forEach(buff => {
        Object.keys(buff.attributes).map(key => buff.attributes[key]).forEach(attrIt => {
          const matrixCount = attrIt.isMatrix ? attrIt.size : 1;
          for (let i = 0; i < matrixCount; ++i) {
            gl.enableVertexAttribArray(attrIt.index + i);
            gl.vertexAttribPointer(attrIt.index + i, attrIt.size, attrIt.type,
                                  attrIt.normalize, attrIt.stride,
                                  attrIt.offset + attrIt.stride * i / attrIt.size);
            if (attrIt.divisor > 0) {
              gl.vertexAttribDivisor(attrIt.index + i, 0);
            }
            gl.disableVertexAttribArray(attrIt.index + i);
          }
        });
      });
    }
  };

  publicAPI.shaderProgramChanged = () => {
    publicAPI.release();
    if (model.handleVAO) {
      model.context.deleteVertexArrays(1, this.handleVAO);
    }
    model.handleVAO = 0;
    model.handleProgram = 0;
  };

  publicAPI.releaseGraphicsResources = () => {
    publicAPI.shaderProgramChanged();
    if (model.handleVAO) {
      model.context.deleteVertexArrays(1, model.handleVAO);
    }
    model.handleVAO = 0;
    model.supported = true;
    model.handleProgram = 0;
  };

  publicAPI.addAttributeArray = (program, buffer, name, offset, stride, elementType, elementTupleSize, normalize) =>
    publicAPI.addAttributeArrayWithDivisor(program, buffer, name, offset, stride, elementType, elementTupleSize, normalize, 0, false);

  publicAPI.addAttributeArrayWithDivisor = (program, buffer, name, offset, stride, elementType, elementTupleSize, normalize, divisor, isMatrix) => {
    if (!program) {
      return false;
    }

    // Check the program is bound, and the buffer is valid.
    if (!program.isBound() || buffer.getHandle() === 0 ||
         buffer.getType() !== OBJECT_TYPE.ARRAY_BUFFER) {
      return false;
    }

    // Perform initalization if necessary, ensure program matches VAOs.
    if (model.handleProgram === 0) {
      model.handleProgram = program.getHandle();
    }
    if (!publicAPI.isReady()) {
      publicAPI.initialize();
    }
    if (!publicAPI.isReady() || model.handleProgram !== program.getHandle()) {
      return false;
    }

    const gl = model.context;

    const attribs = {};
    attribs.index = gl.getAttribLocation(model.handleProgram, name);
    attribs.offset = offset;
    attribs.stride = stride;
  //    attribs.type = convertTypeToGL(elementType);
    attribs.type = elementType;
    attribs.size = elementTupleSize;
    attribs.normalize = normalize;
    attribs.isMatrix = isMatrix;
    attribs.divisor = divisor;

    if (attribs.Index === -1) {
      return false;
    }

    // Always make the call as even the first use wants the attrib pointer setting
    // up when we are emulating.
    buffer.bind();
    gl.enableVertexAttribArray(attribs.index);
    gl.vertexAttribPointer(attribs.index, attribs.size, attribs.type,
                          attribs.normalize, attribs.stride,
                          attribs.offset);

    if (divisor > 0) {
      gl.vertexAttribDivisor(attribs.index, 1);
    }

    // If vertex array objects are not supported then build up our list.
    if (!model.supported) {
      const handleBuffer = buffer.getHandle();
      // find the buffer
      if (Object.keys(model.buffers).indexOf(handleBuffer) !== -1) {
        model.buffers[handleBuffer].attributes[attribs.index] = attribs;
        model.buffers[handleBuffer].buffer = handleBuffer;
      } else {
        // a single handle can have multiple attribs
        model.buffers[handleBuffer] = { buffer: handleBuffer, attributes: { [attribs.index]: attribs } };
      }
    }
    return true;
  };

  publicAPI.addAttributeMatrixWithDivisor = (program, buffer, name, offset, stride, elementType, elementTupleSize, normalize, divisor) => {
    // bind the first row of values
    const result =
      publicAPI.addAttributeArrayWithDivisor(program, buffer, name,
        offset, stride, elementType, elementTupleSize, normalize, divisor, true);

    if (!result) {
      return result;
    }

    const gl = model.context;

    const index = gl.getAttribLocation(model.handleProgram, name);

    for (let i = 1; i < elementTupleSize; i++) {
      gl.enableVertexAttribArray(index + i);
//      gl.vertexAttribPointer(index + i, elementTupleSize, convertTypeToGL(elementType),
      gl.vertexAttribPointer(index + i, elementTupleSize, elementType,
                            normalize, stride,
                            offset + stride * i / elementTupleSize);
      if (divisor > 0) {
        gl.vertexAttribDivisor(index + i, 1);
      }
    }

    return true;
  };

  publicAPI.removeAttributeArray = (name) => {
    if (!publicAPI.isReady() || model.handleProgram === 0) {
      return false;
    }

    const gl = model.context;
    const location = gl.getAttribLocation(model.handleProgram, name);

    if (location === -1) {
      return false;
    }

    gl.disableVertexAttribArray(location);
    // If we don't have real VAOs find the entry and remove it too.
    if (!model.supported) {
      Object.keys(model.buffers).map(key => model.buffers[key]).forEach(buff => {
        delete buff.attributes[location];
      });
    }

    return true;
  };
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
  forceEmulation: false,
  handleVAO: 0,
  handleProgram: 0,
  supported: true,
  buffers: null,
  context: null,
};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
  Object.assign(model, DEFAULT_VALUES, initialValues);

  // Internal objects initialization
  model.buffers = {};

  // Object methods
  macro.obj(publicAPI, model);

  // Create get-only macros
  macro.get(publicAPI, model, ['supported']);

  // Create get-set macros
  macro.setGet(publicAPI, model, ['context', 'forceEmulation']);

  // For more macro methods, see "Sources/macro.js"

  // Object specific methods
  vtkOpenGLVertexArrayObject(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend);

// ----------------------------------------------------------------------------

export default { newInstance, extend };
<commit_msg>added support for the VAO extension to WebGL<commit_after>import * as macro from '../../../macro';
import { OBJECT_TYPE } from '../BufferObject/Constants';

// ----------------------------------------------------------------------------
// vtkOpenGLVertexArrayObject methods
// ----------------------------------------------------------------------------

function vtkOpenGLVertexArrayObject(publicAPI, model) {
  // Set our className
  model.classHierarchy.push('vtkOpenGLVertexArrayObject');

  // Public API methods
  publicAPI.exposedMethod = () => {
    // This is a publicly exposed method of this object
  };

  publicAPI.initialize = () => {
    model.extension = model.context.getExtension('OES_vertex_array_object');

  // Start setting up VAO
    if (!model.forceEmulation && model.extension) {
      model.supported = true;
      model.handleVAO = model.extension.createVertexArrayOES();
    } else {
      model.supported = false;
    }
  };

  publicAPI.isReady = () =>
    // We either probed and allocated a VAO, or are falling back as the current
    // hardware does not support VAOs.
    (model.handleVAO !== 0 || model.supported === false);

  publicAPI.bind = () => {
    // Either simply bind the VAO, or emulate behavior by binding all attributes.
    if (!publicAPI.isReady()) {
      publicAPI.initialize();
    }
    if (publicAPI.isReady() && model.supported) {
      model.extension.bindVertexArrayOES(model.handleVAO);
    } else if (publicAPI.isReady()) {
      const gl = model.context;
      Object.keys(model.buffers).map(key => model.buffers[key]).forEach(buff => {
        model.context.bindBuffer(gl.ARRAY_BUFFER, buff.buffer);
        Object.keys(buff.attributes).map(key => buff.attributes[key]).forEach(attrIt => {
          const matrixCount = attrIt.isMatrix ? attrIt.size : 1;
          for (let i = 0; i < matrixCount; ++i) {
            gl.enableVertexAttribArray(attrIt.index + i);
            gl.vertexAttribPointer(attrIt.index + i, attrIt.size, attrIt.type,
                                  attrIt.normalize, attrIt.stride,
                                  attrIt.offset + attrIt.stride * i / attrIt.size);
            if (attrIt.divisor > 0) {
              gl.vertexAttribDivisor(attrIt.index + i, 1);
            }
          }
        });
        // gl.bindBuffer(gl.ARRAY_BUFFER, 0);
      });
    }
  };

  publicAPI.release = () => {
    // Either simply release the VAO, or emulate behavior by releasing all attributes.
    if (publicAPI.isReady() && model.supported) {
      model.extension.bindVertexArrayOES(null);
    } else if (publicAPI.isReady()) {
      const gl = model.context;
      Object.keys(model.buffers).map(key => model.buffers[key]).forEach(buff => {
        Object.keys(buff.attributes).map(key => buff.attributes[key]).forEach(attrIt => {
          const matrixCount = attrIt.isMatrix ? attrIt.size : 1;
          for (let i = 0; i < matrixCount; ++i) {
            gl.enableVertexAttribArray(attrIt.index + i);
            gl.vertexAttribPointer(attrIt.index + i, attrIt.size, attrIt.type,
                                  attrIt.normalize, attrIt.stride,
                                  attrIt.offset + attrIt.stride * i / attrIt.size);
            if (attrIt.divisor > 0) {
              gl.vertexAttribDivisor(attrIt.index + i, 0);
            }
            gl.disableVertexAttribArray(attrIt.index + i);
          }
        });
      });
    }
  };

  publicAPI.shaderProgramChanged = () => {
    publicAPI.release();
    if (model.handleVAO) {
      model.extension.deleteVertexArrayOES(model.handleVAO);
    }
    model.handleVAO = 0;
    model.handleProgram = 0;
  };

  publicAPI.releaseGraphicsResources = () => {
    publicAPI.shaderProgramChanged();
    if (model.handleVAO) {
      model.extension.deleteVertexArrayOES(model.handleVAO);
    }
    model.handleVAO = 0;
    model.supported = true;
    model.handleProgram = 0;
  };

  publicAPI.addAttributeArray = (program, buffer, name, offset, stride, elementType, elementTupleSize, normalize) =>
    publicAPI.addAttributeArrayWithDivisor(program, buffer, name, offset, stride, elementType, elementTupleSize, normalize, 0, false);

  publicAPI.addAttributeArrayWithDivisor = (program, buffer, name, offset, stride, elementType, elementTupleSize, normalize, divisor, isMatrix) => {
    if (!program) {
      return false;
    }

    // Check the program is bound, and the buffer is valid.
    if (!program.isBound() || buffer.getHandle() === 0 ||
         buffer.getType() !== OBJECT_TYPE.ARRAY_BUFFER) {
      return false;
    }

    // Perform initalization if necessary, ensure program matches VAOs.
    if (model.handleProgram === 0) {
      model.handleProgram = program.getHandle();
    }
    if (!publicAPI.isReady()) {
      publicAPI.initialize();
    }
    if (!publicAPI.isReady() || model.handleProgram !== program.getHandle()) {
      return false;
    }

    const gl = model.context;

    const attribs = {};
    attribs.index = gl.getAttribLocation(model.handleProgram, name);
    attribs.offset = offset;
    attribs.stride = stride;
  //    attribs.type = convertTypeToGL(elementType);
    attribs.type = elementType;
    attribs.size = elementTupleSize;
    attribs.normalize = normalize;
    attribs.isMatrix = isMatrix;
    attribs.divisor = divisor;

    if (attribs.Index === -1) {
      return false;
    }

    // Always make the call as even the first use wants the attrib pointer setting
    // up when we are emulating.
    buffer.bind();
    gl.enableVertexAttribArray(attribs.index);
    gl.vertexAttribPointer(attribs.index, attribs.size, attribs.type,
                          attribs.normalize, attribs.stride,
                          attribs.offset);

    if (divisor > 0) {
      gl.vertexAttribDivisor(attribs.index, 1);
    }

    // If vertex array objects are not supported then build up our list.
    if (!model.supported) {
      const handleBuffer = buffer.getHandle();
      // find the buffer
      if (Object.keys(model.buffers).indexOf(handleBuffer) !== -1) {
        model.buffers[handleBuffer].attributes[attribs.index] = attribs;
        model.buffers[handleBuffer].buffer = handleBuffer;
      } else {
        // a single handle can have multiple attribs
        model.buffers[handleBuffer] = { buffer: handleBuffer, attributes: { [attribs.index]: attribs } };
      }
    }
    return true;
  };

  publicAPI.addAttributeMatrixWithDivisor = (program, buffer, name, offset, stride, elementType, elementTupleSize, normalize, divisor) => {
    // bind the first row of values
    const result =
      publicAPI.addAttributeArrayWithDivisor(program, buffer, name,
        offset, stride, elementType, elementTupleSize, normalize, divisor, true);

    if (!result) {
      return result;
    }

    const gl = model.context;

    const index = gl.getAttribLocation(model.handleProgram, name);

    for (let i = 1; i < elementTupleSize; i++) {
      gl.enableVertexAttribArray(index + i);
//      gl.vertexAttribPointer(index + i, elementTupleSize, convertTypeToGL(elementType),
      gl.vertexAttribPointer(index + i, elementTupleSize, elementType,
                            normalize, stride,
                            offset + stride * i / elementTupleSize);
      if (divisor > 0) {
        gl.vertexAttribDivisor(index + i, 1);
      }
    }

    return true;
  };

  publicAPI.removeAttributeArray = (name) => {
    if (!publicAPI.isReady() || model.handleProgram === 0) {
      return false;
    }

    const gl = model.context;
    const location = gl.getAttribLocation(model.handleProgram, name);

    if (location === -1) {
      return false;
    }

    gl.disableVertexAttribArray(location);
    // If we don't have real VAOs find the entry and remove it too.
    if (!model.supported) {
      Object.keys(model.buffers).map(key => model.buffers[key]).forEach(buff => {
        delete buff.attributes[location];
      });
    }

    return true;
  };
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
  forceEmulation: false,
  handleVAO: 0,
  handleProgram: 0,
  supported: true,
  buffers: null,
  context: null,
};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
  Object.assign(model, DEFAULT_VALUES, initialValues);

  // Internal objects initialization
  model.buffers = {};

  // Object methods
  macro.obj(publicAPI, model);

  // Create get-only macros
  macro.get(publicAPI, model, ['supported']);

  // Create get-set macros
  macro.setGet(publicAPI, model, ['context', 'forceEmulation']);

  // For more macro methods, see "Sources/macro.js"

  // Object specific methods
  vtkOpenGLVertexArrayObject(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend);

// ----------------------------------------------------------------------------

export default { newInstance, extend };
<|endoftext|>


<commit_before>var jsp  = require('uglify-js').parser,
    pro  = require('uglify-js').uglify,
    fs   = require('fs'),
    path = require('path'),
    util = require('util'),
    cssom = require('cssom'),
    mime = require('mime'),
    url = require('url'),
    mod = require('module');

var REQUIRE = 'require';
var REQUIRE_TEXT = 'requireText';
var REQUIRE_CSS  = 'requireCss';
var TO_DATA_URI  = 'toDataUri';
var PREFIX  = '__module_';

function new_sate () {
    return {
        required: {},
        requiredCount: 0,
        requiredAsts: [],

        requiredCss: {},
        requiredCssFiles: [],
        requiredCssUsed: false,

        currentPath: '',
        searchPaths: [],
        options: {}
    };
}

var sate = exports.state = null;

var walker = pro.ast_walker(),
    walkers = {
       "call": function(expr, args) {
           if (expr[0] === 'name' && expr[1] === REQUIRE) {
               var file = resolvePath(args[0][1]);

               if (state.required[file] === undefined) {
                   addFileToAstList(file, true);
               }
               return [this[0], expr, [['num', state.required[file]]] ];
           } else if (expr[0] === 'name' && expr[1] === REQUIRE_TEXT) {
               var file = resolvePath(args[0][1]);
               return ['string', fs.readFileSync(file, 'utf8')];
           } else if (expr[0] === 'name' && expr[1] === REQUIRE_CSS) {
               var file = resolvePath(args[0][1]);
               if (!state.requiredCss[file]) {
                   state.requiredCss[file] = true;
                   state.requiredCssFiles.push(file);
               }
               return ['num', 1];
           }
           return null;
       },
       "name": function(name) {
           if (name === "__dirname") {
               return ['string', path.dirname(state.currentPath)];
           } else if (name === '__filename') {
               return ['string', state.currentPath];
           } else if (name === '__requiredCss') {
               state.requiredCssUsed = true;
               return null;
           }
           return null;
       }
    };

function imagePathToDataUri (filePath) {
    var contentType = mime.lookup( path.extname(filePath) ),
        buffer = fs.readFileSync(filePath);
    return 'data:' + contentType + ';base64,' + buffer.toString('base64');
}

function absoluteImagePath (filePath) {
    return filePath.substring(state.options.serverRoot.length);
}

function dataUriCssImages (cssPath, string) {
    return string.replace(/url\(([^)]+)\)/, function(_, filePath) {
        var imagePath = path.join( path.dirname(cssPath), filePath );
        return 'url(' + imagePathToDataUri(imagePath) + ')';
    });
}

function addIEBackground (cssPath, style, sourceValue) {
    if (style['*background-image']) return;
    var filePath = sourceValue.match(/url\(([^)]+)\)/)[1],
        url = path.join( path.dirname(cssPath), filePath );

    style.setProperty('*background-image', 'url(' + absoluteImagePath(url) + ')');
}

function processCssIncludes (cssPath) {
    var code = fs.readFileSync(cssPath, 'utf8');
    var styleSheet = cssom.parse(code);
    styleSheet.cssRules.forEach(function(rule) {
        var style = rule.style;
        if (style.background) {
            var newBg = dataUriCssImages(cssPath, style.background);
            if (newBg != style.background) {
                addIEBackground(cssPath, style, style.background);
                style.background = newBg;
            }
        }
        if (style['background-image']) {
            var newBg = dataUriCssImages(cssPath, style['background-image']);
            if (newBg != style['background-image']) {
                addIEBackground(cssPath, stle, style['background-image']);
                style['background-image'] = newBg;
            };
        }
    });
    return styleSheet + '';
}

function resolvePath (filePath) {
    var resolvedPath = mod._findPath(filePath,
        [path.dirname(state.currentPath)].concat(state.options.searchPaths));
    if (!resolvedPath) throw new Error('Path ' + filePath + ' not found.');
    return fs.realpathSync(resolvedPath);
}

function addFileToAstList (filePath, wrap) {
    state.required[filePath] = state.requiredCount++;
    var oldPath = state.currentPath;
    state.currentPath = filePath;
    var text = fs.readFileSync(filePath, 'utf8');
    // remove shebang
    text = text.replace(/^\#\!.*/, '');
    var ast;
    if (text.indexOf('@static_require noprocess') === -1) {
        if (wrap) {
            text = '(function(global, module, require) {var exports = this;' + text + '})';
        }
        ast = jsp.parse(text);
        ast = walker.with_walkers(walkers, function() {
            return walker.walk(ast);
        });
    } else {
        if (wrap) {
            text = '(function() { var require = undefined;' + text + '})';
        }
        ast = jsp.parse(text);
    }
    state.currentPath = oldPath;
    state.requiredAsts[state.required[filePath]] = ast;
}

function staticRequire (filePath, options) {
    state = exports.state = new_sate();
    filePath = fs.realpathSync(filePath);
    state.currentPath = filePath;
    var newOptions = {};
    options = Object.create(options || {});

    options.searchPaths = options.searchPaths ? options.searchPaths : [];
    options.searchPaths = [path.dirname(state.currentPath)].concat(options.searchPaths);

    options.serverRoot = options.serverRoot ?
        fs.realpathSync(options.serverRoot) :
        path.dirname(currentPath);

    state.options = options;

    state.requiredAsts = [];

    addFileToAstList(filePath, true);

    var code = 'var global = this;';
    code    += 'function require(index) { if (!require_cache[index]) {var module = require_cache[index] = {exports: {}}; require_modules[index].call(module.exports, global, module, require);} return require_cache[index].exports; }\n';
    code    += 'var require_modules = require.modules = []; var require_cache = require.cache = [];';
    var body = jsp.parse(code)[1];

    if (state.requiredCssUsed) {
        var code = state.requiredCssFiles.map(function(filePath) {
            return processCssIncludes(filePath);
        }).join('\n');
        body.push( ['var', [['__requiredCss', ['string', code]]]] );
    }

    for (var i=0; i < state.requiredCount; i++) {
        body[body.length] =
            [ 'stat',
                ['assign',
                    true,
                    ['sub',
                        ['name', 'require_modules'],
                        ['num', i]
                    ],
                    state.requiredAsts[i][1][0][1]
                ]
            ];
    };
    if (options.globalize) {
        var name = options.globalize || 'exports';
        body = body.concat(jsp.parse('global[' + JSON.stringify(name) + '] = require(0);')[1]);
    } else {
        body.push(['stat', ['call', ['name', 'require'], [['num', '0']]]]);
    }

    return [ 'toplevel',
      [ [ 'stat',
          [ 'call',
            [ 'function',
              null,
              [],
              body
            ],
            [] ] ] ] ];

}

exports.parse = staticRequire;

exports.getAppHandler = function(title, src) {
    return function(req, res) {
        res.send('<!DOCTYPE html><title>' + title + '</title>' +
            '' +
            '' +
            '' +
        '');
    };
};

exports.getHandler = function(options) {
    return function(req, res) {
        exports.handle(req, res, options);
    };
};

exports.handle = function(req, res, options) {
    options = options || {};
    var filePath = options.filePath || (url.parse(req.url).pathname.substr(1));
    if (!options.serverRoot) {
        options.serverRoot = process.cwd();
    }
    filePath = path.resolve(options.serverRoot, filePath);
    options.globalize = req.param('globalize');
    try {
        var ast = staticRequire(filePath, options);
        if (req.param('squeeze')) {
            ast = pro.ast_mangle(ast);
            ast = pro.ast_squeeze(ast);
            ast = pro.ast_squeeze_more(ast);
        }
        var code = pro.gen_code(ast, !req.param('squeeze'));
    } catch (e) {
        require('util').error(e);
        var code = 'alert(' + JSON.stringify(e.stack + '. Current file ' + exports.state.currentPath) + ')';
        console.log(e.stack);
    }
    res.writeHead(200, {
        "Content-Type": 'application/javascript',
        "Content-Length": Buffer.byteLength(code, 'utf8')
    });
    res.end(req.method === "HEAD" ? "" : code);
};<commit_msg>update uglify gen_code call<commit_after>var jsp  = require('uglify-js').parser,
    pro  = require('uglify-js').uglify,
    fs   = require('fs'),
    path = require('path'),
    util = require('util'),
    cssom = require('cssom'),
    mime = require('mime'),
    url = require('url'),
    mod = require('module');

var REQUIRE = 'require';
var REQUIRE_TEXT = 'requireText';
var REQUIRE_CSS  = 'requireCss';
var TO_DATA_URI  = 'toDataUri';
var PREFIX  = '__module_';

function new_sate () {
    return {
        required: {},
        requiredCount: 0,
        requiredAsts: [],

        requiredCss: {},
        requiredCssFiles: [],
        requiredCssUsed: false,

        currentPath: '',
        searchPaths: [],
        options: {}
    };
}

var sate = exports.state = null;

var walker = pro.ast_walker(),
    walkers = {
       "call": function(expr, args) {
           if (expr[0] === 'name' && expr[1] === REQUIRE) {
               var file = resolvePath(args[0][1]);

               if (state.required[file] === undefined) {
                   addFileToAstList(file, true);
               }
               return [this[0], expr, [['num', state.required[file]]] ];
           } else if (expr[0] === 'name' && expr[1] === REQUIRE_TEXT) {
               var file = resolvePath(args[0][1]);
               return ['string', fs.readFileSync(file, 'utf8')];
           } else if (expr[0] === 'name' && expr[1] === REQUIRE_CSS) {
               var file = resolvePath(args[0][1]);
               if (!state.requiredCss[file]) {
                   state.requiredCss[file] = true;
                   state.requiredCssFiles.push(file);
               }
               return ['num', 1];
           }
           return null;
       },
       "name": function(name) {
           if (name === "__dirname") {
               return ['string', path.dirname(state.currentPath)];
           } else if (name === '__filename') {
               return ['string', state.currentPath];
           } else if (name === '__requiredCss') {
               state.requiredCssUsed = true;
               return null;
           }
           return null;
       }
    };

function imagePathToDataUri (filePath) {
    var contentType = mime.lookup( path.extname(filePath) ),
        buffer = fs.readFileSync(filePath);
    return 'data:' + contentType + ';base64,' + buffer.toString('base64');
}

function absoluteImagePath (filePath) {
    return filePath.substring(state.options.serverRoot.length);
}

function dataUriCssImages (cssPath, string) {
    return string.replace(/url\(([^)]+)\)/, function(_, filePath) {
        var imagePath = path.join( path.dirname(cssPath), filePath );
        return 'url(' + imagePathToDataUri(imagePath) + ')';
    });
}

function addIEBackground (cssPath, style, sourceValue) {
    if (style['*background-image']) return;
    var filePath = sourceValue.match(/url\(([^)]+)\)/)[1],
        url = path.join( path.dirname(cssPath), filePath );

    style.setProperty('*background-image', 'url(' + absoluteImagePath(url) + ')');
}

function processCssIncludes (cssPath) {
    var code = fs.readFileSync(cssPath, 'utf8');
    var styleSheet = cssom.parse(code);
    styleSheet.cssRules.forEach(function(rule) {
        var style = rule.style;
        if (style.background) {
            var newBg = dataUriCssImages(cssPath, style.background);
            if (newBg != style.background) {
                addIEBackground(cssPath, style, style.background);
                style.background = newBg;
            }
        }
        if (style['background-image']) {
            var newBg = dataUriCssImages(cssPath, style['background-image']);
            if (newBg != style['background-image']) {
                addIEBackground(cssPath, stle, style['background-image']);
                style['background-image'] = newBg;
            };
        }
    });
    return styleSheet + '';
}

function resolvePath (filePath) {
    var resolvedPath = mod._findPath(filePath,
        [path.dirname(state.currentPath)].concat(state.options.searchPaths));
    if (!resolvedPath) throw new Error('Path ' + filePath + ' not found.');
    return fs.realpathSync(resolvedPath);
}

function addFileToAstList (filePath, wrap) {
    state.required[filePath] = state.requiredCount++;
    var oldPath = state.currentPath;
    state.currentPath = filePath;
    var text = fs.readFileSync(filePath, 'utf8');
    // remove shebang
    text = text.replace(/^\#\!.*/, '');
    var ast;
    if (text.indexOf('@static_require noprocess') === -1) {
        if (wrap) {
            text = '(function(global, module, require) {var exports = this;' + text + '})';
        }
        ast = jsp.parse(text);
        ast = walker.with_walkers(walkers, function() {
            return walker.walk(ast);
        });
    } else {
        if (wrap) {
            text = '(function() {' + text + '})';
        }
        ast = jsp.parse(text);
    }
    state.currentPath = oldPath;
    state.requiredAsts[state.required[filePath]] = ast;
}

function staticRequire (filePath, options) {
    state = exports.state = new_sate();
    filePath = fs.realpathSync(filePath);
    state.currentPath = filePath;
    var newOptions = {};
    options = Object.create(options || {});

    options.searchPaths = options.searchPaths ? options.searchPaths : [];
    options.searchPaths = [path.dirname(state.currentPath)].concat(options.searchPaths);

    options.serverRoot = options.serverRoot ?
        fs.realpathSync(options.serverRoot) :
        path.dirname(currentPath);

    state.options = options;

    state.requiredAsts = [];

    addFileToAstList(filePath, true);

    var code = 'var global = this;';
    code    += 'function require(index) { if (!require_cache[index]) {var module = require_cache[index] = {exports: {}}; require_modules[index].call(module.exports, global, module, require);} return require_cache[index].exports; }\n';
    code    += 'var require_modules = require.modules = []; var require_cache = require.cache = [];';
    var body = jsp.parse(code)[1];

    if (state.requiredCssUsed) {
        var code = state.requiredCssFiles.map(function(filePath) {
            return processCssIncludes(filePath);
        }).join('\n');
        body.push( ['var', [['__requiredCss', ['string', code]]]] );
    }

    for (var i=0; i < state.requiredCount; i++) {
        body[body.length] =
            [ 'stat',
                ['assign',
                    true,
                    ['sub',
                        ['name', 'require_modules'],
                        ['num', i]
                    ],
                    state.requiredAsts[i][1][0][1]
                ]
            ];
    };
    if (options.globalize) {
        var name = options.globalize || 'exports';
        body = body.concat(jsp.parse('global[' + JSON.stringify(name) + '] = require(0);')[1]);
    } else {
        body.push(['stat', ['call', ['name', 'require'], [['num', '0']]]]);
    }

    return [ 'toplevel',
      [ [ 'stat',
          [ 'call',
            [ 'function',
              null,
              [],
              body
            ],
            [] ] ] ] ];

}

exports.parse = staticRequire;

exports.getAppHandler = function(title, src) {
    return function(req, res) {
        res.send('<!DOCTYPE html><title>' + title + '</title>' +
            '' +
            '' +
            '' +
        '');
    };
};

exports.getHandler = function(options) {
    return function(req, res) {
        exports.handle(req, res, options);
    };
};

exports.handle = function(req, res, options) {
    options = options || {};
    var filePath = options.filePath || (url.parse(req.url).pathname.substr(1));
    if (!options.serverRoot) {
        options.serverRoot = process.cwd();
    }
    filePath = path.resolve(options.serverRoot, filePath);
    options.globalize = req.param('globalize');
    try {
        var ast = staticRequire(filePath, options);
        if (req.param('squeeze')) {
            ast = pro.ast_mangle(ast);
            ast = pro.ast_squeeze(ast);
            ast = pro.ast_squeeze_more(ast);
        }
        var code = pro.gen_code(ast, { beautify: !req.param('squeeze') });
    } catch (e) {
        require('util').error(e);
        var code = 'alert(' + JSON.stringify(e.stack + '. Current file ' + exports.state.currentPath) + ')';
        console.log(e.stack);
    }
    res.writeHead(200, {
        "Content-Type": 'application/javascript',
        "Content-Length": Buffer.byteLength(code, 'utf8')
    });
    res.end(req.method === "HEAD" ? "" : code);
};<|endoftext|>


<commit_before>/**
* Module that controls the Box node settings. Includes Knockout view-model
* for syncing data, and HGrid-folderpicker for selecting a folder.
*/
'use strict';

var ko = require('knockout');
require('knockout-punches');
var $ = require('jquery');
var bootbox = require('bootbox');
var Raven = require('raven-js');

var FolderPicker = require('folderpicker');
var ZeroClipboard = require('zeroclipboard');
ZeroClipboard.config('/static/vendor/bower_components/zeroclipboard/dist/ZeroClipboard.swf');
var $osf = require('osfHelpers');

ko.punches.enableAll();
/**
*  Knockout view model for the Box node settings widget.
*/
var ViewModel = function(url, selector, folderPicker) {
    var self = this;
    self.selector = selector;
    // Auth information
    self.nodeHasAuth = ko.observable(false);
    // whether current user is authorizer of the addon
    self.userIsOwner = ko.observable(false);
    // whether current user has an auth token
    self.userHasAuth = ko.observable(false);
    // whether the auth token is valid
    self.validCredentials = ko.observable(true);
    // Currently linked folder, an Object of the form {name: ..., path: ...}
    self.folder = ko.observable({name: null, path: null, id: null});
    self.ownerName = ko.observable('');
    self.urls = ko.observable({});
    // Flashed messages
    self.message = ko.observable('');
    self.messageClass = ko.observable('text-info');
    // Display names
    self.PICKER = 'picker';
    self.SHARE = 'share';
    // Current folder display
    self.currentDisplay = ko.observable(null);
    // CSS selector for the folder picker div
    self.folderPicker = folderPicker;
    // Currently selected folder, an Object of the form {name: ..., path: ...}
    self.selected = ko.observable(null);
    // Emails of contributors, can only be populated by activating the share dialog
    self.emails = ko.observableArray([]);
    self.loading = ko.observable(false);
    // Whether the initial data has been fetched form the server. Used for
    // error handling.
    self.loadedSettings = ko.observable(false);
    // Whether the contributor emails have been loaded from the server
    self.loadedEmails = ko.observable(false);

    // Whether the box folders have been loaded from the server/Box API
    self.loadedFolders = ko.observable(false);

    // List of contributor emails as a comma-separated values
    self.emailList = ko.computed(function() {
        return self.emails().join([', ']);
    });

    self.disableShare = ko.computed(function() {
        return !self.urls().emails;
    });

    /**
    *  Update the view model from data returned from the server.
    */
    self.updateFromData = function(data) {
        self.ownerName(data.ownerName);
        self.nodeHasAuth(data.nodeHasAuth);
        self.userIsOwner(data.userIsOwner);
        self.userHasAuth(data.userHasAuth);
        self.validCredentials(data.validCredentials);
        // Make sure folder has name and path properties defined
        self.folder(data.folder || {name: null, path: null, id: null});
        self.urls(data.urls);
    };

    self.fetchFromServer = function() {
        var request = $.ajax({
            url: url, type: 'GET', dataType: 'json',
        })
        .done(function(response) {
            self.updateFromData(response.result);
            self.loadedSettings(true);
            if (!self.validCredentials()){
                if (self.userIsOwner()) {
                    self.changeMessage('Could not retrieve Box settings at ' +
                    'this time. The Box addon credentials may no longer be valid.' +
                    ' Try deauthorizing and reauthorizing Box on your account settings page.',
                    'text-warning');
                } else {
                    self.changeMessage('Could not retrieve Box settings at ' +
                    'this time. The Box addon credentials may no longer be valid.' +
                    ' Contact ' + self.ownerName() + ' to verify.',
                    'text-warning');
                }
            }
        })
        .fail(function(xhr, textStatus, error) {
            self.changeMessage('Could not retrieve Box settings at ' +
                'this time. Please refresh ' +
                'the page. If the problem persists, email ' +
                'support@osf.io.',
                'text-warning');
            Raven.captureMessage('Could not GET Box settings', {
                url: url,
                textStatus: textStatus,
                error: error
            });
        });
        return request;
    };

    // Initial fetch from server
    self.fetchFromServer();

    self.toggleShare = function() {
        if (self.currentDisplay() === self.SHARE) {
            self.currentDisplay(null);
        } else {
            // Clear selection
            self.cancelSelection();
            self.currentDisplay(self.SHARE);
            self.activateShare();
        }
    };

    function onGetEmailsSuccess(response) {
        var emails = response.result.emails;
        self.emails(emails);
        self.loadedEmails(true);
    }

    self.activateShare = function() {
        if (!self.loadedEmails()) {
            $.ajax({
                url: self.urls().emails, type: 'GET', dataType: 'json',
                success: onGetEmailsSuccess
            });
        }
        var $copyBtn = $('#copyBtn');
        new ZeroClipboard($copyBtn);
    };

    /**
    *  Whether or not to show the Import Access Token Button
    */
    self.showImport = ko.computed(function() {
        // Invoke the observables to ensure dependency tracking
        var userHasAuth = self.userHasAuth();
        var nodeHasAuth = self.nodeHasAuth();
        var loaded = self.loadedSettings();
        return userHasAuth && !nodeHasAuth && loaded;
    });

    /** Whether or not to show the full settings pane. */
    self.showSettings = ko.computed(function() {
        return self.nodeHasAuth();
    });

    /** Whether or not to show the Create Access Token button */
    self.showTokenCreateButton = ko.computed(function() {
        // Invoke the observables to ensure dependency tracking
        var userHasAuth = self.userHasAuth();
        var nodeHasAuth = self.nodeHasAuth();
        var loaded = self.loadedSettings();
        return !userHasAuth && !nodeHasAuth && loaded;
    });

    /** Computed functions for the linked and selected folders' display text.*/

    self.folderName = ko.computed(function() {
        // Invoke the observables to ensure dependency tracking
        var nodeHasAuth = self.nodeHasAuth();
        var folder = self.folder();
        return (nodeHasAuth && folder) ? folder.name : '';
    });

    self.selectedFolderName = ko.computed(function() {
        var userIsOwner = self.userIsOwner();
        var selected = self.selected();
        return (userIsOwner && selected) ? selected.name : '';
    });

    function onSubmitSuccess(response) {
        self.changeMessage('Successfully linked "' + $osf.htmlEscape(self.selected().name) +
            '". Go to the Files page to view your files.',
            'text-success', 5000);
        // Update folder in ViewModel
        self.folder(response.result.folder);
        self.urls(response.result.urls);
        self.cancelSelection();
    }

    function onSubmitError() {
        self.changeMessage('Could not change settings. Please try again later.', 'text-danger');
    }

    /**
    * Send a PUT request to change the linked Box folder.
    */
    self.submitSettings = function() {
        $osf.putJSON(self.urls().config, ko.toJS(self))
            .done(onSubmitSuccess)
            .fail(onSubmitError);
    };

    /**
    *  Must be used to update radio buttons and knockout view model simultaneously
    */
    self.cancelSelection = function() {
        self.selected(null);
    };

    /** Change the flashed message. */
    self.changeMessage = function(text, css, timeout) {
        self.message(text);
        var cssClass = css || 'text-info';
        self.messageClass(cssClass);
        if (timeout) {
            // Reset message after timeout period
            setTimeout(function() {
                self.message('');
                self.messageClass('text-info');
            }, timeout);
        }
    };

    /**
    *  Send DELETE request to deauthorize this node.
    */
    function sendDeauth() {
        var url = self.urls().deauthorize;
        return $.ajax({
            url: url,
            type: 'DELETE',
        }).done(function() {
            // Update observables
            self.nodeHasAuth(false);
            self.cancelSelection();
            self.currentDisplay(null);
            self.changeMessage('Deauthorized Box.', 'text-warning', 3000);
        }).fail(function(xhr, status, error) {
            self.changeMessage('Could not deauthorize because of an error. Please try again later.',
                'text-danger');
            Raven.captureMessage('Failed to deauthorize Box.', {
                url: url, status: status, error: error
            });
        });
    }

    /** Pop up a confirmation to deauthorize Box from this node.
    *   Send DELETE request if confirmed.
    */
    self.deauthorize = function() {
        bootbox.confirm({
            title: 'Deauthorize Box?',
            message: 'Are you sure you want to remove this Box authorization?',
            callback: function(confirmed) {
                if (confirmed) {
                    return sendDeauth();
                }
            }
        });
    };

    // Callback for when PUT request to import user access token
    function onImportSuccess(response) {
        var msg = response.message || 'Successfully imported access token from profile.';
        // Update view model based on response
        self.changeMessage(msg, 'text-success', 3000);
        self.updateFromData(response.result);
        self.activatePicker();
    }

    function onImportError(xhr, status, error) {
        self.message('Error occurred while importing access token.');
        self.messageClass('text-danger');
        Raven.captureMessage('Failed to import Box access token.', {
            xhr: xhr, status: status, error: error
        });
    }

    /**
        * Send PUT request to import access token from user profile.
        */
    self.importAuth = function() {
        bootbox.confirm({
            title: 'Import Box Access Token?',
            message: 'Are you sure you want to authorize this project with your Box access token?',
            callback: function(confirmed) {
                if (confirmed) {
                    return $osf.putJSON(self.urls().importAuth, {})
                        .done(onImportSuccess)
                        .fail(onImportError);
                }
            }
        });
    };

    /** Callback for chooseFolder action.
    *   Just changes the ViewModel's self.selected observable to the selected
    *   folder.
    */
    function onPickFolder(evt, item) {
            evt.preventDefault();
            var name = item.data.path === '/' ? '/ (Full Box)' : item.data.path.replace('All Files', '');
            self.selected({name: name, path: item.data.path, id: item.data.id});
            return false; // Prevent event propagation
        }

    /**
    *  Activates the HGrid folder picker.
    */
    self.activatePicker = function() {
        self.currentDisplay(self.PICKER);
        // Only load folders if they haven't already been requested
        if (!self.loadedFolders()) {
            // Show loading indicator
            self.loading(true);
            $(self.folderPicker).folderpicker({
                onPickFolder: onPickFolder,
                initialFolderPath : self.folder().path,
                // initialFolderPath : 'All Files',
                // Fetch Box folders with AJAX
                filesData: self.urls().folders, // URL for fetching folders
                // Lazy-load each folder's contents
                // Each row stores its url for fetching the folders it contains
                resolveLazyloadUrl : function(item){
                    return item.data.urls.folders;
                },
                oddEvenClass : {
                    odd : 'box-folderpicker-odd',
                    even : 'box-folderpicker-even'
                },
                ajaxOptions: {
                    error: function(xhr, textStatus, error) {
                        self.loading(false);
                        self.changeMessage('Could not connect to Box at this time. ' +
                                            'Please try again later.', 'text-warning');
                        Raven.captureMessage('Could not GET get Box contents.', {
                            textStatus: textStatus,
                            error: error
                        });
                    }
                },
                folderPickerOnload: function() {
                    // Hide loading indicator
                    self.loading(false);
                    // Set flag to prevent repeated requests
                    self.loadedFolders(true);
                }
            });
        }
    };

    /**
    *  Toggles the visibility of the folder picker.
    */
    self.togglePicker = function() {
        // Toggle visibility of folder picker
        var shown = self.currentDisplay() === self.PICKER;
        if (!shown) {
            self.currentDisplay(self.PICKER);
            self.activatePicker();
        } else {
            self.currentDisplay(null);
            // Clear selection
            self.cancelSelection();
        }
    };
};

// Public API
function BoxNodeConfig(selector, url, folderPicker) {
    var self = this;
    self.url = url;
    self.folderPicker = folderPicker;
    self.viewModel = new ViewModel(url, selector, folderPicker);
    $osf.applyBindings(self.viewModel, selector);
}

module.exports = BoxNodeConfig;
<commit_msg>/ is actually All Files<commit_after>/**
* Module that controls the Box node settings. Includes Knockout view-model
* for syncing data, and HGrid-folderpicker for selecting a folder.
*/
'use strict';

var ko = require('knockout');
require('knockout-punches');
var $ = require('jquery');
var bootbox = require('bootbox');
var Raven = require('raven-js');

var FolderPicker = require('folderpicker');
var ZeroClipboard = require('zeroclipboard');
ZeroClipboard.config('/static/vendor/bower_components/zeroclipboard/dist/ZeroClipboard.swf');
var $osf = require('osfHelpers');

ko.punches.enableAll();
/**
*  Knockout view model for the Box node settings widget.
*/
var ViewModel = function(url, selector, folderPicker) {
    var self = this;
    self.selector = selector;
    // Auth information
    self.nodeHasAuth = ko.observable(false);
    // whether current user is authorizer of the addon
    self.userIsOwner = ko.observable(false);
    // whether current user has an auth token
    self.userHasAuth = ko.observable(false);
    // whether the auth token is valid
    self.validCredentials = ko.observable(true);
    // Currently linked folder, an Object of the form {name: ..., path: ...}
    self.folder = ko.observable({name: null, path: null, id: null});
    self.ownerName = ko.observable('');
    self.urls = ko.observable({});
    // Flashed messages
    self.message = ko.observable('');
    self.messageClass = ko.observable('text-info');
    // Display names
    self.PICKER = 'picker';
    self.SHARE = 'share';
    // Current folder display
    self.currentDisplay = ko.observable(null);
    // CSS selector for the folder picker div
    self.folderPicker = folderPicker;
    // Currently selected folder, an Object of the form {name: ..., path: ...}
    self.selected = ko.observable(null);
    // Emails of contributors, can only be populated by activating the share dialog
    self.emails = ko.observableArray([]);
    self.loading = ko.observable(false);
    // Whether the initial data has been fetched form the server. Used for
    // error handling.
    self.loadedSettings = ko.observable(false);
    // Whether the contributor emails have been loaded from the server
    self.loadedEmails = ko.observable(false);

    // Whether the box folders have been loaded from the server/Box API
    self.loadedFolders = ko.observable(false);

    // List of contributor emails as a comma-separated values
    self.emailList = ko.computed(function() {
        return self.emails().join([', ']);
    });

    self.disableShare = ko.computed(function() {
        return !self.urls().emails;
    });

    /**
    *  Update the view model from data returned from the server.
    */
    self.updateFromData = function(data) {
        self.ownerName(data.ownerName);
        self.nodeHasAuth(data.nodeHasAuth);
        self.userIsOwner(data.userIsOwner);
        self.userHasAuth(data.userHasAuth);
        self.validCredentials(data.validCredentials);
        // Make sure folder has name and path properties defined
        self.folder(data.folder || {name: null, path: null, id: null});
        self.urls(data.urls);
    };

    self.fetchFromServer = function() {
        var request = $.ajax({
            url: url, type: 'GET', dataType: 'json',
        })
        .done(function(response) {
            self.updateFromData(response.result);
            self.loadedSettings(true);
            if (!self.validCredentials()){
                if (self.userIsOwner()) {
                    self.changeMessage('Could not retrieve Box settings at ' +
                    'this time. The Box addon credentials may no longer be valid.' +
                    ' Try deauthorizing and reauthorizing Box on your account settings page.',
                    'text-warning');
                } else {
                    self.changeMessage('Could not retrieve Box settings at ' +
                    'this time. The Box addon credentials may no longer be valid.' +
                    ' Contact ' + self.ownerName() + ' to verify.',
                    'text-warning');
                }
            }
        })
        .fail(function(xhr, textStatus, error) {
            self.changeMessage('Could not retrieve Box settings at ' +
                'this time. Please refresh ' +
                'the page. If the problem persists, email ' +
                'support@osf.io.',
                'text-warning');
            Raven.captureMessage('Could not GET Box settings', {
                url: url,
                textStatus: textStatus,
                error: error
            });
        });
        return request;
    };

    // Initial fetch from server
    self.fetchFromServer();

    self.toggleShare = function() {
        if (self.currentDisplay() === self.SHARE) {
            self.currentDisplay(null);
        } else {
            // Clear selection
            self.cancelSelection();
            self.currentDisplay(self.SHARE);
            self.activateShare();
        }
    };

    function onGetEmailsSuccess(response) {
        var emails = response.result.emails;
        self.emails(emails);
        self.loadedEmails(true);
    }

    self.activateShare = function() {
        if (!self.loadedEmails()) {
            $.ajax({
                url: self.urls().emails, type: 'GET', dataType: 'json',
                success: onGetEmailsSuccess
            });
        }
        var $copyBtn = $('#copyBtn');
        new ZeroClipboard($copyBtn);
    };

    /**
    *  Whether or not to show the Import Access Token Button
    */
    self.showImport = ko.computed(function() {
        // Invoke the observables to ensure dependency tracking
        var userHasAuth = self.userHasAuth();
        var nodeHasAuth = self.nodeHasAuth();
        var loaded = self.loadedSettings();
        return userHasAuth && !nodeHasAuth && loaded;
    });

    /** Whether or not to show the full settings pane. */
    self.showSettings = ko.computed(function() {
        return self.nodeHasAuth();
    });

    /** Whether or not to show the Create Access Token button */
    self.showTokenCreateButton = ko.computed(function() {
        // Invoke the observables to ensure dependency tracking
        var userHasAuth = self.userHasAuth();
        var nodeHasAuth = self.nodeHasAuth();
        var loaded = self.loadedSettings();
        return !userHasAuth && !nodeHasAuth && loaded;
    });

    /** Computed functions for the linked and selected folders' display text.*/

    self.folderName = ko.computed(function() {
        // Invoke the observables to ensure dependency tracking
        var nodeHasAuth = self.nodeHasAuth();
        var folder = self.folder();
        return (nodeHasAuth && folder) ? folder.name : '';
    });

    self.selectedFolderName = ko.computed(function() {
        var userIsOwner = self.userIsOwner();
        var selected = self.selected();
        return (userIsOwner && selected) ? selected.name : '';
    });

    function onSubmitSuccess(response) {
        self.changeMessage('Successfully linked "' + $osf.htmlEscape(self.selected().name) +
            '". Go to the Files page to view your files.',
            'text-success', 5000);
        // Update folder in ViewModel
        self.folder(response.result.folder);
        self.urls(response.result.urls);
        self.cancelSelection();
    }

    function onSubmitError() {
        self.changeMessage('Could not change settings. Please try again later.', 'text-danger');
    }

    /**
    * Send a PUT request to change the linked Box folder.
    */
    self.submitSettings = function() {
        $osf.putJSON(self.urls().config, ko.toJS(self))
            .done(onSubmitSuccess)
            .fail(onSubmitError);
    };

    /**
    *  Must be used to update radio buttons and knockout view model simultaneously
    */
    self.cancelSelection = function() {
        self.selected(null);
    };

    /** Change the flashed message. */
    self.changeMessage = function(text, css, timeout) {
        self.message(text);
        var cssClass = css || 'text-info';
        self.messageClass(cssClass);
        if (timeout) {
            // Reset message after timeout period
            setTimeout(function() {
                self.message('');
                self.messageClass('text-info');
            }, timeout);
        }
    };

    /**
    *  Send DELETE request to deauthorize this node.
    */
    function sendDeauth() {
        var url = self.urls().deauthorize;
        return $.ajax({
            url: url,
            type: 'DELETE',
        }).done(function() {
            // Update observables
            self.nodeHasAuth(false);
            self.cancelSelection();
            self.currentDisplay(null);
            self.changeMessage('Deauthorized Box.', 'text-warning', 3000);
        }).fail(function(xhr, status, error) {
            self.changeMessage('Could not deauthorize because of an error. Please try again later.',
                'text-danger');
            Raven.captureMessage('Failed to deauthorize Box.', {
                url: url, status: status, error: error
            });
        });
    }

    /** Pop up a confirmation to deauthorize Box from this node.
    *   Send DELETE request if confirmed.
    */
    self.deauthorize = function() {
        bootbox.confirm({
            title: 'Deauthorize Box?',
            message: 'Are you sure you want to remove this Box authorization?',
            callback: function(confirmed) {
                if (confirmed) {
                    return sendDeauth();
                }
            }
        });
    };

    // Callback for when PUT request to import user access token
    function onImportSuccess(response) {
        var msg = response.message || 'Successfully imported access token from profile.';
        // Update view model based on response
        self.changeMessage(msg, 'text-success', 3000);
        self.updateFromData(response.result);
        self.activatePicker();
    }

    function onImportError(xhr, status, error) {
        self.message('Error occurred while importing access token.');
        self.messageClass('text-danger');
        Raven.captureMessage('Failed to import Box access token.', {
            xhr: xhr, status: status, error: error
        });
    }

    /**
        * Send PUT request to import access token from user profile.
        */
    self.importAuth = function() {
        bootbox.confirm({
            title: 'Import Box Access Token?',
            message: 'Are you sure you want to authorize this project with your Box access token?',
            callback: function(confirmed) {
                if (confirmed) {
                    return $osf.putJSON(self.urls().importAuth, {})
                        .done(onImportSuccess)
                        .fail(onImportError);
                }
            }
        });
    };

    /** Callback for chooseFolder action.
    *   Just changes the ViewModel's self.selected observable to the selected
    *   folder.
    */
    function onPickFolder(evt, item) {
            evt.preventDefault();
            var name = item.data.path === 'All Files' ? '/ (Full Box)' : item.data.path.replace('All Files', '');
            self.selected({name: name, path: item.data.path, id: item.data.id});
            return false; // Prevent event propagation
        }

    /**
    *  Activates the HGrid folder picker.
    */
    self.activatePicker = function() {
        self.currentDisplay(self.PICKER);
        // Only load folders if they haven't already been requested
        if (!self.loadedFolders()) {
            // Show loading indicator
            self.loading(true);
            $(self.folderPicker).folderpicker({
                onPickFolder: onPickFolder,
                initialFolderPath : self.folder().path,
                // initialFolderPath : 'All Files',
                // Fetch Box folders with AJAX
                filesData: self.urls().folders, // URL for fetching folders
                // Lazy-load each folder's contents
                // Each row stores its url for fetching the folders it contains
                resolveLazyloadUrl : function(item){
                    return item.data.urls.folders;
                },
                oddEvenClass : {
                    odd : 'box-folderpicker-odd',
                    even : 'box-folderpicker-even'
                },
                ajaxOptions: {
                    error: function(xhr, textStatus, error) {
                        self.loading(false);
                        self.changeMessage('Could not connect to Box at this time. ' +
                                            'Please try again later.', 'text-warning');
                        Raven.captureMessage('Could not GET get Box contents.', {
                            textStatus: textStatus,
                            error: error
                        });
                    }
                },
                folderPickerOnload: function() {
                    // Hide loading indicator
                    self.loading(false);
                    // Set flag to prevent repeated requests
                    self.loadedFolders(true);
                }
            });
        }
    };

    /**
    *  Toggles the visibility of the folder picker.
    */
    self.togglePicker = function() {
        // Toggle visibility of folder picker
        var shown = self.currentDisplay() === self.PICKER;
        if (!shown) {
            self.currentDisplay(self.PICKER);
            self.activatePicker();
        } else {
            self.currentDisplay(null);
            // Clear selection
            self.cancelSelection();
        }
    };
};

// Public API
function BoxNodeConfig(selector, url, folderPicker) {
    var self = this;
    self.url = url;
    self.folderPicker = folderPicker;
    self.viewModel = new ViewModel(url, selector, folderPicker);
    $osf.applyBindings(self.viewModel, selector);
}

module.exports = BoxNodeConfig;
<|endoftext|>


<commit_before>// Docs aren't that great to find. Mostly JAVA based. Here are few helpful resources:
// - https://www.browserstack.com/automate/node#testing-frameworks
// - http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/firefox/index_exports_Driver.html
// - https://github.com/SeleniumHQ/selenium/blob/8f988e07cc316a48e0ff94d8ff823c95142532e9/javascript/webdriver/webdriver.js
// - https://github.com/SeleniumHQ/selenium/blob/c10e8a955883f004452cdde18096d70738397788/javascript/node/selenium-webdriver/test/upload_test.js
//
// - https://github.com/SeleniumHQ/selenium/wiki/WebDriverJs
// - http://seleniumhq.github.io/selenium/docs/api/javascript/
// - http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/firefox/index.html
// - http://selenium.googlecode.com/git/docs/api/javascript/namespace_webdriver_By.html
// - http://selenium.googlecode.com/git/docs/api/javascript/class_webdriver_WebElement.html

require('babel-register')

var webdriver = require('selenium-webdriver')
var remote = require('selenium-webdriver/remote')

// The Travis Sauce Connect addon exports the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables,
// and relays connections to the hub URL back to Sauce Labs.
// See: https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-Sauce-Labs
var username = process.env.SAUCE_USERNAME
var accessKey = process.env.SAUCE_ACCESS_KEY

var remoteHost = 'http://uppy.io'
var localHost = 'http://localhost:4000'

// if accessKey is supplied as env variable, this is a remote Saucelabs test
var isTravisTest = process.env.TRAVIS === 'true'
var isRemoteTest = !!accessKey

var host = localHost
if (isTravisTest) {
  // @todo This should become localhost to utilize the Travis saucelabs addon tunnel
  // But it seems Edge and Safari fail on that right now, so targeting uppy.io instead.
  // That is unideal, as we are then testing a previous deploy, and not the current build
  // host = localHost
  host = remoteHost
} else if (isRemoteTest) {
  // We're not too sure about a working tunnel otherwise, best just test uppy.io
  host = remoteHost
} else {
  // If we don't have any access keys set, we'll assume you'll be playing around with a local
  // firefox webdriver.
  host = localHost
}

console.log('Acceptance tests will be targetting: ' + host)

var platforms = [
  // { browser: 'Safari', version: '8.0', os: 'OS X 10.10' },
  // { browser: 'MicrosoftEdge', version: '13.10586', os: 'Windows 10' },
  { browser: 'Firefox', version: '38.0', os: 'Linux' },
  { browser: 'Internet Explorer', version: '10.0', os: 'Windows 8' },
  { browser: 'Internet Explorer', version: '11.103', os: 'Windows 10' },
  { browser: 'Chrome', version: '48.0', os: 'Windows XP' },
  { browser: 'Firefox', version: '34.0', os: 'Windows 7' }
]

var tests = [
  require('./multipart.spec.js'),
  require('./i18n.spec.js')
  // require('./dragdrop.spec.js')
]

function buildDriver (platform) {
  var driver
  if (isRemoteTest) {
    var capabilities = {
      'browserName': platform.browser,
      'platform': platform.os,
      'version': platform.version,
      'username': username,
      'accessKey': accessKey
    }

    if (isTravisTest) {
      // @todo Do we need a hub_url = "%s:%s@localhost:4445" % (username, access_key)
      // as mentioned in https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-Sauce-Labs ?
      capabilities['tunnel-identifier'] = process.env.TRAVIS_JOB_NUMBER
      capabilities['build'] = process.env.TRAVIS_BUILD_NUMBER
      capabilities['name'] = 'Travis ##' + process.env.TRAVIS_JOB_NUMBER
      capabilities['tags'] = [process.env.TRAVIS_NODE_VERSION, 'CI']
    }

    driver = new webdriver
      .Builder()
      .withCapabilities(capabilities)
      .usingServer('http://' + username + ':' + accessKey +
                   '@ondemand.saucelabs.com:80/wd/hub')
      .build()
    driver.setFileDetector(new remote.FileDetector())
  } else {
    driver = new webdriver
      .Builder()
      .forBrowser('firefox')
      .build()
  }
  return driver
}

var customTests = {
  fallback: function () {
    var ancientPlatform = { browser: 'internet explorer', version: '6.0', os: 'Windows XP' }
    var driver = buildDriver({ browser: 'internet explorer', version: '6.0', os: 'Windows XP' })
    var test = require('./fallback.spec.js')

    test(driver, ancientPlatform, host)
  }
}

// RUN TESTS

function runAllTests () {
  if (isRemoteTest) {
    // run all tests for all platforms
    platforms.forEach(function (platform) {
      tests.forEach(function (test) {
        var driver = buildDriver(platform)
        test(driver, platform, host)
      })
    })

    // run custom platform-specific tests here
    // fallback test
    customTests.fallback()
  } else {
    // run tests just for local Firefox
    tests.forEach(function (test) {
      var driver = buildDriver()
      test(driver, { browser: 'Firefox', version: 'Version', os: 'Local' }, host)
    })
  }
}

runAllTests()
<commit_msg>disable fallback test<commit_after>// Docs aren't that great to find. Mostly JAVA based. Here are few helpful resources:
// - https://www.browserstack.com/automate/node#testing-frameworks
// - http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/firefox/index_exports_Driver.html
// - https://github.com/SeleniumHQ/selenium/blob/8f988e07cc316a48e0ff94d8ff823c95142532e9/javascript/webdriver/webdriver.js
// - https://github.com/SeleniumHQ/selenium/blob/c10e8a955883f004452cdde18096d70738397788/javascript/node/selenium-webdriver/test/upload_test.js
//
// - https://github.com/SeleniumHQ/selenium/wiki/WebDriverJs
// - http://seleniumhq.github.io/selenium/docs/api/javascript/
// - http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/firefox/index.html
// - http://selenium.googlecode.com/git/docs/api/javascript/namespace_webdriver_By.html
// - http://selenium.googlecode.com/git/docs/api/javascript/class_webdriver_WebElement.html

require('babel-register')

var webdriver = require('selenium-webdriver')
var remote = require('selenium-webdriver/remote')

// The Travis Sauce Connect addon exports the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables,
// and relays connections to the hub URL back to Sauce Labs.
// See: https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-Sauce-Labs
var username = process.env.SAUCE_USERNAME
var accessKey = process.env.SAUCE_ACCESS_KEY

var remoteHost = 'http://uppy.io'
var localHost = 'http://localhost:4000'

// if accessKey is supplied as env variable, this is a remote Saucelabs test
var isTravisTest = process.env.TRAVIS === 'true'
var isRemoteTest = !!accessKey

var host = localHost
if (isTravisTest) {
  // @todo This should become localhost to utilize the Travis saucelabs addon tunnel
  // But it seems Edge and Safari fail on that right now, so targeting uppy.io instead.
  // That is unideal, as we are then testing a previous deploy, and not the current build
  // host = localHost
  host = remoteHost
} else if (isRemoteTest) {
  // We're not too sure about a working tunnel otherwise, best just test uppy.io
  host = remoteHost
} else {
  // If we don't have any access keys set, we'll assume you'll be playing around with a local
  // firefox webdriver.
  host = localHost
}

console.log('Acceptance tests will be targetting: ' + host)

var platforms = [
  // { browser: 'Safari', version: '8.0', os: 'OS X 10.10' },
  // { browser: 'MicrosoftEdge', version: '13.10586', os: 'Windows 10' },
  { browser: 'Firefox', version: '38.0', os: 'Linux' },
  { browser: 'Internet Explorer', version: '10.0', os: 'Windows 8' },
  { browser: 'Internet Explorer', version: '11.103', os: 'Windows 10' },
  { browser: 'Chrome', version: '48.0', os: 'Windows XP' },
  { browser: 'Firefox', version: '34.0', os: 'Windows 7' }
]

var tests = [
  require('./multipart.spec.js'),
  require('./i18n.spec.js')
  // require('./dragdrop.spec.js')
]

function buildDriver (platform) {
  var driver
  if (isRemoteTest) {
    var capabilities = {
      'browserName': platform.browser,
      'platform': platform.os,
      'version': platform.version,
      'username': username,
      'accessKey': accessKey
    }

    if (isTravisTest) {
      // @todo Do we need a hub_url = "%s:%s@localhost:4445" % (username, access_key)
      // as mentioned in https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-Sauce-Labs ?
      capabilities['tunnel-identifier'] = process.env.TRAVIS_JOB_NUMBER
      capabilities['build'] = process.env.TRAVIS_BUILD_NUMBER
      capabilities['name'] = 'Travis ##' + process.env.TRAVIS_JOB_NUMBER
      capabilities['tags'] = [process.env.TRAVIS_NODE_VERSION, 'CI']
    }

    driver = new webdriver
      .Builder()
      .withCapabilities(capabilities)
      .usingServer('http://' + username + ':' + accessKey +
                   '@ondemand.saucelabs.com:80/wd/hub')
      .build()
    driver.setFileDetector(new remote.FileDetector())
  } else {
    driver = new webdriver
      .Builder()
      .forBrowser('firefox')
      .build()
  }
  return driver
}

// var customTests = {
//   fallback: function () {
//     var ancientPlatform = { browser: 'internet explorer', version: '6.0', os: 'Windows XP' }
//     var driver = buildDriver({ browser: 'internet explorer', version: '6.0', os: 'Windows XP' })
//     var test = require('./fallback.spec.js')
//
//     test(driver, ancientPlatform, host)
//   }
// }

// RUN TESTS

function runAllTests () {
  if (isRemoteTest) {
    // run all tests for all platforms
    platforms.forEach(function (platform) {
      tests.forEach(function (test) {
        var driver = buildDriver(platform)
        test(driver, platform, host)
      })
    })

    // run custom platform-specific tests here
    // fallback test
    // customTests.fallback()
  } else {
    // run tests just for local Firefox
    tests.forEach(function (test) {
      var driver = buildDriver()
      test(driver, { browser: 'Firefox', version: 'Version', os: 'Local' }, host)
    })
  }
}

runAllTests()
<|endoftext|>