<commit_before>(function(root) {
  var Core = function() {
    this.modules = {};
  };

  Core.prototype.register = function(module, constructor) {
    this.modules[module] = {
      constructor: constructor,
      instance: null
    };
  };

  Core.prototype.start = function(module) {
    var module = this.modules[module];

    module.instance = new module.constructor(new Sandbox());
    module.instance.init();
  };

  Core.prototype.startAll = function() {
    for(var module in this.modules) {
      if(this.modules.hasOwnProperty(module) && !this.modules[module].instance) {
        this.start(module);
      }
    }
  };

  Core.prototype.stop = function(module) {
    var module = this.modules[module];

    module.instance.destroy();
    module.instance = null;
  };

  Core.prototype.stopAll = function() {
    for(var module in this.modules) {
      if(this.modules.hasOwnProperty(module)) {
        this.stop(module);
      }
    }
  };

  root.Core = new Core();
} (window));
<commit_msg>Now destroy and init is not a required method<commit_after>(function(root) {
  var Core = function() {
    this.modules = {};
  };

  Core.prototype.register = function(module, constructor) {
    this.modules[module] = {
      constructor: constructor,
      instance: null
    };
  };

  Core.prototype.start = function(module) {
    var module = this.modules[module];

    module.instance = new module.constructor(new Sandbox());
    module.instance.init && module.instance.init();
  };

  Core.prototype.startAll = function() {
    for(var module in this.modules) {
      if(this.modules.hasOwnProperty(module) && !this.modules[module].instance) {
        this.start(module);
      }
    }
  };

  Core.prototype.stop = function(module) {
    var module = this.modules[module];

    module.instance.destroy && module.instance.destroy();
    module.instance = null;
  };

  Core.prototype.stopAll = function() {
    for(var module in this.modules) {
      if(this.modules.hasOwnProperty(module)) {
        this.stop(module);
      }
    }
  };

  root.Core = new Core();
} (window));
<|endoftext|>


<commit_before>var native_dmp = require("../build/Release/dmp");
<commit_msg>Actually call patch_make<commit_after>var native_dmp = require("../build/Release/dmp");

var text1 = new Buffer("blah");
var text2 = new Buffer("blah123");
var patch = native_dmp.patch_make(text1, text2);

console.log(patch, patch.toString());
<|endoftext|>


<commit_before>const dns = require('dns')

const logger = require('./logger')
const TimeTracker = require('./time')

const config = require('../config')

const SKIP_SRV_TIMEOUT = config.skipSrvTimeout || 60 * 60 * 1000

class DNSResolver {
  constructor (ip, port) {
    this._ip = ip
    this._port = port
  }

  _skipSrv () {
    this._skipSrvUntil = TimeTracker.getEpochMillis() + SKIP_SRV_TIMEOUT
  }

  _isSkipSrv () {
    const ignoreSkipSrv = typeof config.skipSrvTimeout === 'number' && config.skipSrvTimeout <= 0
    return !ignoreSkipSrv && this._skipSrvUntil && TimeTracker.getEpochMillis() <= this._skipSrvUntil
  }

  resolve (callback) {
    if (this._isSkipSrv()) {
      callback(this._ip, this._port, config.rates.connectTimeout)

      return
    }

    const startTime = TimeTracker.getEpochMillis()

    let callbackFired = false

    const fireCallback = (ip, port) => {
      if (!callbackFired) {
        callbackFired = true

        // Send currentTime - startTime to provide remaining connectionTime allowance
        callback(ip || this._ip, port || this._port, TimeTracker.getEpochMillis() - startTime)
      }
    }

    const timeoutCallback = setTimeout(fireCallback, config.rates.connectTimeout)

    dns.resolveSrv('_minecraft._tcp.' + this._ip, (err, records) => {
      // Cancel the timeout handler if not already fired
      if (!callbackFired) {
        clearTimeout(timeoutCallback)
      }

      // Test if the error indicates a miss, or if the records returned are empty
      if ((err && (err.code === 'ENOTFOUND' || err.code === 'ENODATA')) || !records || records.length === 0) {
        if (!this._isSkipSrv()) {
          this._skipSrv()

          logger.log('warn', 'No SRV records were resolved for %s. Minetrack will skip attempting to resolve %s SRV records for %d minutes.', this._ip, this._ip, SKIP_SRV_TIMEOUT / (60 * 1000))
        }

        fireCallback()
      } else {
        // Only fires if !err && records.length > 0
        fireCallback(records[0].name, records[0].port)
      }
    })
  }
}

module.exports = DNSResolver
<commit_msg>optimize skipSrvTimeout handling<commit_after>const dns = require('dns')

const logger = require('./logger')
const TimeTracker = require('./time')

const config = require('../config')

const SKIP_SRV_TIMEOUT = config.skipSrvTimeout || 60 * 60 * 1000

class DNSResolver {
  constructor (ip, port) {
    this._ip = ip
    this._port = port
  }

  _skipSrv () {
    this._skipSrvUntil = TimeTracker.getEpochMillis() + SKIP_SRV_TIMEOUT
  }

  _isSkipSrv () {
    const ignoreSkipSrv = typeof config.skipSrvTimeout === 'number' && config.skipSrvTimeout <= 0
    return !ignoreSkipSrv && this._skipSrvUntil && TimeTracker.getEpochMillis() <= this._skipSrvUntil
  }

  resolve (callback) {
    if (this._isSkipSrv()) {
      callback(this._ip, this._port, config.rates.connectTimeout)

      return
    }

    const startTime = TimeTracker.getEpochMillis()

    let callbackFired = false

    const fireCallback = (ip, port) => {
      if (!callbackFired) {
        callbackFired = true

        // Send currentTime - startTime to provide remaining connectionTime allowance
        callback(ip || this._ip, port || this._port, TimeTracker.getEpochMillis() - startTime)
      }
    }

    const timeoutCallback = setTimeout(fireCallback, config.rates.connectTimeout)

    dns.resolveSrv('_minecraft._tcp.' + this._ip, (err, records) => {
      // Cancel the timeout handler if not already fired
      if (!callbackFired) {
        clearTimeout(timeoutCallback)
      }

      // Test if the error indicates a miss, or if the records returned are empty
      if ((err && (err.code === 'ENOTFOUND' || err.code === 'ENODATA')) || !records || records.length === 0) {
        // Compare config.skipSrvTimeout directly since SKIP_SRV_TIMEOUT has an or'd value
        const isSkipSrvTimeoutActive = typeof config.skipSrvTimeout !== 'number' || config.skipSrvTimeout > 0

        // Only activate _skipSrv if the skipSrvTimeout value is either NaN or > 0
        // 0 represents a disabled flag
        if (!this._isSkipSrv() && !isSkipSrvTimeoutActive) {
          this._skipSrv()

          logger.log('warn', 'No SRV records were resolved for %s. Minetrack will skip attempting to resolve %s SRV records for %d minutes.', this._ip, this._ip, SKIP_SRV_TIMEOUT / (60 * 1000))
        }

        fireCallback()
      } else {
        // Only fires if !err && records.length > 0
        fireCallback(records[0].name, records[0].port)
      }
    })
  }
}

module.exports = DNSResolver
<|endoftext|>


<commit_before>'use strict';

function guess(){
    if(!guessing){
        return;
    }

    var element = document.getElementById('guess-input');
    var guessvalue = parseInt(
      element.value,
      10
    );

    // If the guess is not a number or not in guessing range.
    if(isNaN(guessvalue)
      || guessvalue.length < 1
      || guessvalue > core_storage_data['max']
      || guessvalue < core_storage_data['min']){
        document.getElementById('info').innerHTML =
          'Invalid integer.';
        return;
    }

    element.value = guessvalue;
    var result = '';

    // Check if valid guess is lower than value.
    if(guessvalue > value){
        result = 'LOWER';

    // Check if valid guess is higher than value.
    }else if(guessvalue < value){
        result = 'HIGHER';

    // Only option left is guess is correct.
    }else{
        guessing = false;
        result = 'CORRECT! YOU WIN!';
    }

    element = document.getElementById('guesses');
    element.innerHTML = parseInt(
      element.innerHTML,
      10
    ) + 1;
    document.getElementById('info').innerHTML = result;
}

function new_game(skip){
    if(!skip
      && !window.confirm('Start new game?')){
        return;
    }

    document.getElementById('guess-input').value = '';
    document.getElementById('guesses').innerHTML = 0;
    document.getElementById('info').innerHTML = '';
    guessing = true;

    // Generate new value to guess.
    value = core_random_integer({
      'max': core_storage_data['max'] - core_storage_data['min'],
    }) + core_storage_data['min'];
}
<commit_msg>removed guess-input value set<commit_after>'use strict';

function guess(){
    if(!guessing){
        return;
    }

    var guessvalue = parseInt(
      document.getElementById('guess-input').value,
      10
    );

    // If the guess is not a number or not in guessing range.
    if(isNaN(guessvalue)
      || guessvalue.length < 1
      || guessvalue > core_storage_data['max']
      || guessvalue < core_storage_data['min']){
        document.getElementById('info').innerHTML =
          'Invalid integer.';
        return;
    }

    var result = '';

    // Check if valid guess is lower than value.
    if(guessvalue > value){
        result = 'LOWER';

    // Check if valid guess is higher than value.
    }else if(guessvalue < value){
        result = 'HIGHER';

    // Only option left is guess is correct.
    }else{
        guessing = false;
        result = 'CORRECT! YOU WIN!';
    }

    var element = document.getElementById('guesses');
    element.innerHTML = parseInt(
      element.innerHTML,
      10
    ) + 1;
    document.getElementById('info').innerHTML = result;
}

function new_game(skip){
    if(!skip
      && !window.confirm('Start new game?')){
        return;
    }

    document.getElementById('guess-input').value = '';
    document.getElementById('guesses').innerHTML = 0;
    document.getElementById('info').innerHTML = '';
    guessing = true;

    // Generate new value to guess.
    value = core_random_integer({
      'max': core_storage_data['max'] - core_storage_data['min'],
    }) + core_storage_data['min'];
}
<|endoftext|>


<commit_before>module.exports = {

	//---------------------------------------------------------------------
	// Action Name
	//
	// This is the name of the action displayed in the editor.
	//---------------------------------------------------------------------

	name: "Store Message Info",

	//---------------------------------------------------------------------
	// Action Section
	//
	// This is the section the action will fall into.
	//---------------------------------------------------------------------

	section: "Messaging",

	//---------------------------------------------------------------------
	// Action Subtitle
	//
	// This function generates the subtitle displayed next to the name.
	//---------------------------------------------------------------------

	subtitle: function(data) {
		const message = ['Command Message', 'Temp Variable', 'Server Variable', 'Global Variable'];
		const info = ['Message Object', 'Message ID', 'Message Text', 'Message Author', 'Message Channel', 'Message Timestamp', 'Message Is Pinned?', 'Message Is TTS?', 'Message edited at', 'Message edits history', 'Message is pinnable?', 'Message includes @everyone mention?', 'Messages different reactions count', 'Mentioned users list', 'Mentioned users count', 'Message URL'];
		return `${message[parseInt(data.message)]} - ${info[parseInt(data.info)]}`;
	},

	//---------------------------------------------------------------------
		 // DBM Mods Manager Variables (Optional but nice to have!)
		 //
		 // These are variables that DBM Mods Manager uses to show information
		 // about the mods for people to see in the list.
		 //---------------------------------------------------------------------

		 // Who made the mod (If not set, defaults to "DBM Mods")
		 author: "DBM Mods, Lasse & NetLuis",

		 // The version of the mod (Defaults to 1.0.0)
		 version: "1.9.4",

		 // A short description to show on the mod line for this mod (Must be on a single line)
		 short_description: "Added more options to default action.",

		 // If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods

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

	//---------------------------------------------------------------------
	// Action Storage Function
	//
	// Stores the relevant variable info for the editor.
	//---------------------------------------------------------------------

	variableStorage: function(data, varType) {
		const type = parseInt(data.storage);
		if(type !== varType) return;
		const info = parseInt(data.info);
		let dataType = 'Unknown Type';
		switch(info) {
			case 0:
				dataType = 'Message';
				break;
			case 1:
				dataType = 'Message ID';
				break;
			case 2:
				dataType = 'Text';
				break;
			case 3:
				dataType = 'Server Member';
				break;
			case 4:
				dataType = 'Channel';
				break;
			case 5:
				dataType = 'Text';
				break;
			case 6:
			case 7:
				dataType = 'Boolean';
				break;
			case 8:
				dataType = "Date";
				break;
			case 9:
				dataType = "Array";
				break;
			case 10:
				dataType = "Boolean";
				break;
			case 11:
				dataType = "Boolean";
				break;
			case 12:
				dataType = "Number";
				break;
			case 13:
				dataType = "Array";
				break;
			case 14:
				dataType = "Number";
				break;
			case 15:
				dataType = "URL";
				break;
		}
		return ([data.varName2, dataType]);
	},

	//---------------------------------------------------------------------
	// Action Fields
	//
	// These are the fields for the action. These fields are customized
	// by creating elements with corresponding IDs in the HTML. These
	// are also the names of the fields stored in the action's JSON data.
	//---------------------------------------------------------------------

	fields: ["message", "varName", "info", "storage", "varName2"],

	//---------------------------------------------------------------------
	// Command HTML
	//
	// This function returns a string containing the HTML used for
	// editting actions.
	//
	// The "isEvent" parameter will be true if this action is being used
	// for an event. Due to their nature, events lack certain information,
	// so edit the HTML to reflect this.
	//
	// The "data" parameter stores constants for select elements to use.
	// Each is an array: index 0 for commands, index 1 for events.
	// The names are: sendTargets, members, roles, channels,
	//                messages, servers, variables
	//---------------------------------------------------------------------

	html: function(isEvent, data) {
		return `

This action has been modified by DBM Mods.

			Source Message:

			<select id="message" class="round" onchange="glob.messageChange(this, 'varNameContainer')">
				${data.messages[isEvent ? 1 : 0]}
			</select>

			Variable Name:

			<input id="varName" class="round" type="text" list="variableList">

			Source Info:

			<select id="info" class="round">
				<option value="0" selected>Message Object</option>
				<option value="1">Message ID</option>
				<option value="2">Message Text</option>
				<option value="3">Message Author</option>
				<option value="4">Message Channel</option>
				<option value="5">Message Timestamp</option>
				<option value="6">Message Is Pinned?</option>
				<option value="7">Message Is TTS?</option>
				<option value="8">Message edited at</option>
				<option value="9">Message edit history</option>
				<option value="10">Message is pinnable?</option>
				<option value="11">Message includes @everyone mention?</option>
				<option value="12">Messages different reactions count</option>
				<option value="13">Messages mentioned users list</option>
				<option value="14">Messages mentioned users count</option>
				<option value="15">Message URL</option>
			</select>

			Store In:

			<select id="storage" class="round">
				${data.variables[1]}
			</select>

			Variable Name:

			<input id="varName2" class="round" type="text">

`
	},

	//---------------------------------------------------------------------
	// Action Editor Init Code
	//
	// When the HTML is first applied to the action editor, this code
	// is also run. This helps add modifications or setup reactionary
	// functions for the DOM elements.
	//---------------------------------------------------------------------

	init: function() {
		const {glob, document} = this;

		glob.messageChange(document.getElementById('message'), 'varNameContainer')
	},

	//---------------------------------------------------------------------
	// Action Bot Function
	//
	// This is the function for the action within the Bot's Action class.
	// Keep in mind event calls won't have access to the "msg" parameter,
	// so be sure to provide checks for variable existance.
	//---------------------------------------------------------------------

	action: function(cache) {
		const data = cache.actions[cache.index];
		const message = parseInt(data.message);
		const varName = this.evalMessage(data.varName, cache);
		const info = parseInt(data.info);
		const msg = this.getMessage(message, varName, cache);
		if(!msg) {
			this.callNextAction(cache);
			return;
		}
		let result;
		switch(info) {
			case 0:
				result = msg;
				break;
			case 1:
				result = msg.id;
				break;
			case 2:
				result = msg.content;
				break;
			case 3:
				if(msg.member) {
					result = msg.member;
				} else if (msg.recipient) {
					result = msg.recipient; // Used for DM Channels
				}
				break;
			case 4:
				result = msg.channel;
				break;
			case 5:
				result = msg.createdTimestamp;
				break;
			case 6:
				result = msg.pinned;
				break;
			case 7:
				result = msg.tts;
			case 8:
				result = msg.editedAt;
				break;
			case 9:
				result = msg.edits;
				break;
			case 10:
				result = msg.pinnable;
				break;
			case 11:
				result = msg.mentions.everyone;
				break;
			case 12:
				result = msg.reactions.array().length;
				break;
			case 13:
				result = msg.mentions.users.array();
				break;
			case 14:
				result = msg.mentions.users.array().length;
				break;
			case 15:
				result = msg.url;
				break;
			default:
				break;
		}
		if(result !== undefined) {
			const storage = parseInt(data.storage);
			const varName2 = this.evalMessage(data.varName2, cache);
			this.storeValue(result, storage, varName2, cache);
		}
		this.callNextAction(cache);
	},

	//---------------------------------------------------------------------
	// Action Bot Mod
	//
	// Upon initialization of the bot, this code is run. Using the bot's
	// DBM namespace, one can add/modify existing functions if necessary.
	// In order to reduce conflictions between mods, be sure to alias
	// functions you wish to overwrite.
	//---------------------------------------------------------------------

	mod: function(DBM) {
	}

	}; // End of module
	<commit_msg>New UI, fixes, and options in Store Message Info<commit_after>module.exports = {

	//---------------------------------------------------------------------
	// Action Name
	//
	// This is the name of the action displayed in the editor.
	//---------------------------------------------------------------------

	name: "Store Message Info",

	//---------------------------------------------------------------------
	// Action Section
	//
	// This is the section the action will fall into.
	//---------------------------------------------------------------------

	section: "Messaging",

	//---------------------------------------------------------------------
	// Action Subtitle
	//
	// This function generates the subtitle displayed next to the name.
	//---------------------------------------------------------------------

	subtitle: function(data) {
		const message = ['Command Message', 'Temp Variable', 'Server Variable', 'Global Variable'];
		const info = ['Message Object', 'Message ID', 'Message Text', 'Message Author', 'Message Channel', 'Message Timestamp', 'Message Is Pinned?', 'Message Is TTS?', 'Message Edited At', 'Message Edits History', 'Message Is Pinnable?', 'Message Includes @everyone Mention?', 'Messages Different Reactions Count', 'Mentioned Users List', 'Mentioned Users Count', 'Message URL', 'Message Creation Date', 'Message Length', 'Message Attachments Count', 'Message Guild', 'Message Type', 'Message Is Deletable?', 'Message Is Deleted?', 'Message Is Of Discord?', 'Message Webhook ID'];
		return `${message[parseInt(data.message)]} - ${info[parseInt(data.info)]}`;
	},

	//---------------------------------------------------------------------
		 // DBM Mods Manager Variables (Optional but nice to have!)
		 //
		 // These are variables that DBM Mods Manager uses to show information
		 // about the mods for people to see in the list.
		 //---------------------------------------------------------------------

		 // Who made the mod (If not set, defaults to "DBM Mods")
		 author: "DBM Mods, Lasse, NetLuis & Cap",

		 // The version of the mod (Defaults to 1.0.0)
		 version: "1.9.6",

		 // A short description to show on the mod line for this mod (Must be on a single line)
		 short_description: "New user interface, fixes, and new default action options added.",

		 // If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods

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

	//---------------------------------------------------------------------
	// Action Storage Function
	//
	// Stores the relevant variable info for the editor.
	//---------------------------------------------------------------------

	variableStorage: function(data, varType) {
		const type = parseInt(data.storage);
		if(type !== varType) return;
		const info = parseInt(data.info);
		let dataType = 'Unknown Type';
		switch(info) {
			case 0:
				dataType = 'Message';
				break;
			case 1:
				dataType = 'Message ID';
				break;
			case 2:
				dataType = 'Text';
				break;
			case 3:
				dataType = 'Server Member';
				break;
			case 4:
				dataType = 'Channel';
				break;
			case 5:
				dataType = 'Text';
				break;
			case 6:
			case 7:
			case 10:
			case 11:
			case 21: // Added by Cap in 1.9.6
			case 22: // Added by Cap in 1.9.6
			case 23: // Added by Cap in 1.9.6
				dataType = 'Boolean';
				break;
			case 8:
			case 16: // Added by Cap in 1.9.6
				dataType = "Date";
				break;
			case 9:
			case 13:
				dataType = "Array";
				break;
			case 12:
			case 14:
			case 17: // Added by Cap in 1.9.6
			case 18: // Added by Cap in 1.9.6
				dataType = "Number";
				break;
			case 15:
				dataType = "URL";
				break;
			case 19: // Added by Cap in 1.9.6
				dataType = "Guild";
				break;
			case 20: // Added by Cap in 1.9.6
				dataType = "Message Type";
				break;
			case 24: // Added by Cap in 1.9.6
				dataType = "Webhook ID";
				break;
		}
		return ([data.varName2, dataType]);
	},

	//---------------------------------------------------------------------
	// Action Fields
	//
	// These are the fields for the action. These fields are customized
	// by creating elements with corresponding IDs in the HTML. These
	// are also the names of the fields stored in the action's JSON data.
	//---------------------------------------------------------------------

	fields: ["message", "varName", "info", "storage", "varName2"],

	//---------------------------------------------------------------------
	// Command HTML
	//
	// This function returns a string containing the HTML used for
	// editting actions.
	//
	// The "isEvent" parameter will be true if this action is being used
	// for an event. Due to their nature, events lack certain information,
	// so edit the HTML to reflect this.
	//
	// The "data" parameter stores constants for select elements to use.
	// Each is an array: index 0 for commands, index 1 for events.
	// The names are: sendTargets, members, roles, channels,
	//                messages, servers, variables
	//---------------------------------------------------------------------

	html: function(isEvent, data) {
		return `

This action has been modified by DBM Mods.

			Source Message:

			<select id="message" class="round" onchange="glob.messageChange(this, 'varNameContainer')">
				${data.messages[isEvent ? 1 : 0]}
			</select>

			Variable Name:

			<input id="varName" class="round" type="text" list="variableList">

			Source Info:

			<select id="info" class="round">
			<optgroup label="Main">
				<option value="0" selected>Message Object</option>
				<option value="1">Message ID</option>
				<option value="2">Message Text</option>
				<option value="17">Message Length</option>
				<option value="3">Message Author</option>
				<option value="4">Message Channel</option>
				<option value="19">Message Guild</option>
				<option value="18">Message Attachments Count</option>
				<option value="20">Message Type</option>
				<option value="16">Message Creation Date</option>
				<option value="5">Message Timestamp</option>
				<option value="15">Message URL</option>
			</optgroup>
			<optgroup label="Booleans">
				<option value="10">Message Is Pinnable?</option>
				<option value="6">Message Is Pinned?</option>
				<option value="21">Message Is Deletable?</option>
				<option value="22">Message Is Deleted?</option>
				<option value="7">Message Is TTS?</option>
				<option value="11">Message Includes @everyone Mention?</option>
				<option value="23">Message Is Of Discord?</option>
			</optgroup>
			<optgroup label="Others">
				<option value="8">Message Edited At</option>
				<option value="9">Message Edit History</option>
				<option value="12">Messages Different Reactions Count</option>
				<option value="13">Messages Mentioned Users List</option>
				<option value="14">Messages Mentioned Users Count</option>
				<option value="24">Message Webhook ID</option>
			</optgroup>
			</select>

			Store In:

			<select id="storage" class="round">
				${data.variables[1]}
			</select>

			Variable Name:

			<input id="varName2" class="round" type="text">

`
	},

	//---------------------------------------------------------------------
	// Action Editor Init Code
	//
	// When the HTML is first applied to the action editor, this code
	// is also run. This helps add modifications or setup reactionary
	// functions for the DOM elements.
	//---------------------------------------------------------------------

	init: function() {
		const {glob, document} = this;

		glob.messageChange(document.getElementById('message'), 'varNameContainer')
	},

	//---------------------------------------------------------------------
	// Action Bot Function
	//
	// This is the function for the action within the Bot's Action class.
	// Keep in mind event calls won't have access to the "msg" parameter,
	// so be sure to provide checks for variable existance.
	//---------------------------------------------------------------------

	action: function(cache) {
		const data = cache.actions[cache.index];
		const message = parseInt(data.message);
		const varName = this.evalMessage(data.varName, cache);
		const info = parseInt(data.info);
		const msg = this.getMessage(message, varName, cache);
		if(!msg) {
			this.callNextAction(cache);
			return;
		}
		let result;
		switch(info) {
			case 0:
				result = msg;
				break;
			case 1:
				result = msg.id;
				break;
			case 2:
				result = msg.content;
				break;
			case 3:
				if(msg.member) {
					result = msg.member;
				} else if (msg.recipient) {
					result = msg.recipient; // Used for DM Channels
				}
				break;
			case 4:
				result = msg.channel;
				break;
			case 5:
				result = msg.createdTimestamp;
				break;
			case 6:
				result = msg.pinned;
				break;
			case 7:
				result = msg.tts;
			case 8:
				result = msg.editedAt;
				break;
			case 9:
				result = msg.edits;
				break;
			case 10:
				result = msg.pinnable;
				break;
			case 11:
				result = msg.mentions.everyone;
				break;
			case 12:
				result = msg.reactions.array().length;
				break;
			case 13:
				result = msg.mentions.users.array();
				break;
			case 14:
				result = msg.mentions.users.array().length;
				break;
			case 15:
				result = msg.url;
				break;
			case 16: // Added by Cap in 1.9.6
				result = msg.createdAt;
				break;
			case 17: // Added by Cap in 1.9.6
				result = msg.content.length;
				break;
			case 18: // Added by Cap in 1.9.6
				result = msg.attachments.array().length;
				break;
			case 19: // Added by Cap in 1.9.6
				result = msg.guild;
				break;
			case 20: // Added by Cap in 1.9.6
				result = msg.type;
				break;
			case 21: // Added by Cap in 1.9.6
				result = msg.deletable;
				break;
			case 22: // Added by Cap in 1.9.6
				result = msg.deleted;
				break;
			case 23: // Added by Cap in 1.9.6
				result = msg.system;
				break;
			case 24: // Added by Cap in 1.9.6
				result = msg.webhookID;
				break;
			default:
				break;
		}
		if(result !== undefined) {
			const storage = parseInt(data.storage);
			const varName2 = this.evalMessage(data.varName2, cache);
			this.storeValue(result, storage, varName2, cache);
		}
		this.callNextAction(cache);
	},

	//---------------------------------------------------------------------
	// Action Bot Mod
	//
	// Upon initialization of the bot, this code is run. Using the bot's
	// DBM namespace, one can add/modify existing functions if necessary.
	// In order to reduce conflictions between mods, be sure to alias
	// functions you wish to overwrite.
	//---------------------------------------------------------------------

	mod: function(DBM) {
	}

	}; // End of module

<|endoftext|>


<commit_before>
/*
 * Warning.
 * Do not edit this file.  It is generated from data/apps.yaml
 * ...edit that file instead.
 */

var json = {
  "id": 0,
  "data": {
    "description": "This is a landing page for Fedora Apps.  Fedora Infrastructure is huge; this page details only the public facing portion of it all.  Explore!\n"
  },
  "name": "Fedora Apps",
  "children": [
    {
      "id": 1,
      "data": {
        "description": "No clue what's going on?  That's okay.. take a look at some of these sites -- they might help you get your bearings.\n"
      },
      "name": "For New People",
      "children": [
        {
          "data": {
            "url": "http://ask.fedoraproject.org/",
            "description": "Any question at all about Fedora?  Ask it here.\n"
          },
          "name": "Ask Fedora",
          "id": 2
        },
        {
          "data": {
            "url": "http://apps.fedoraproject.org/tagger",
            "description": "Help build a tag cloud of all our packages.. It's actually really useful.  It'll help improve the search of the \"Packages\" webapp.\n"
          },
          "name": "Tagger",
          "id": 3
        },
        {
          "data": {
            "url": "http://fedoraproject.org/easyfix",
            "description": "A list of easy-to-fix problems for the different projects in Fedora.  Interested in getting into helping out with sysadmin work or web application development?  This should be useful to you.\n"
          },
          "name": "Easyfix",
          "id": 4
        },
        {
          "data": {
            "url": "http://docs.fedoraproject.org",
            "description": "RTFM!  Everything you could ever want to know. Probably the best place to find documentation about Fedora, including the changes between releases (and a big kudos to the translation teams to keep this resource up to date in the different languages!)\n"
          },
          "name": "Docs",
          "id": 5
        }
      ]
    },
    {
      "id": 6,
      "data": {
        "description": "TODO -- put a description here.\n"
      },
      "name": "For the Community",
      "children": [
        {
          "id": 7,
          "data": {
            "url": "http://fedoraproject.org/wiki",
            "description": "Maintain your own user profile page, contribute to documents about features, process, and governance.\n"
          },
          "name": " The Wiki",
          "icon": "mediawiki.png"
        },
        {
          "data": {
            "url": "http://admin.fedoraproject.org/voting",
            "description": "As a member of the community, you can now vote for the different steering committees, for this you will use the Election application.  Voting is a right and a duty as a member of the community; it is one of the things you can do to influence the development of Fedora.\n"
          },
          "name": "Elections",
          "id": 8
        },
        {
          "data": {
            "url": "http://fedorapeople.org",
            "description": "Being a community member you gain access to fedorapeople which provides you with a space on the web where you can upload files to share them with the community.\n"
          },
          "name": "FedoraPeople",
          "id": 9
        },
        {
          "id": 10,
          "data": {
            "url": "http://planet.fedoraproject.org",
            "description": "The planet is a blog aggregator, a space accessible to you as a community member where you can express your opinion and talk about what you are doing for Fedora.\n"
          },
          "name": " The Planet",
          "icon": "planet_logo.png"
        },
        {
          "id": 11,
          "data": {
            "url": "http://lists.fedoraproject.org",
            "description": "Mailing lists are used for communication within the community. There are lists for generic topics and lists more dedicated to a specific topic, there is for sure one for you.\n"
          },
          "name": " The Mailing lists",
          "icon": "gnu.png"
        }
      ]
    },
    {
      "id": 12,
      "data": {
        "description": "TODO -- put a description here.\n"
      },
      "name": "For Packagers",
      "children": [
        {
          "data": {
            "url": "http://admin.fedoraproject.org/pkgdb",
            "description": "Manage ACLs of your packages.\n"
          },
          "name": "PkgDB",
          "id": 13
        },
        {
          "id": 14,
          "data": {
            "url": "http://koji.fedoraproject.org/koji",
            "description": "Build your packages in a safe and trusted environment.\n"
          },
          "name": " Koji",
          "icon": "koji.png"
        },
        {
          "id": 15,
          "data": {
            "url": "http://admin.fedoraproject.org/updates",
            "description": "The tool you will use to push your packages to the Fedora repositories as an update, first an update to be tested (repository: updates-testing) then a stable updates (repository: updates).\n"
          },
          "name": " Bodhi",
          "icon": "bodhi.png"
        },
        {
          "data": {
            "url": "http://apps.fedoraproject.org/packages",
            "description": "The best place for someone outside the community to find out what is in the Fedora repositories. Which packages is present, in which version, who is maintaining it, what patches have been applied, what bugs have been reported against it. All this kind of questions can be answered there.\n"
          },
          "name": "Packages",
          "id": 16
        }
      ]
    },
    {
      "id": 17,
      "data": {
        "description": "TODO -- not sure how to categorize these yet.\n"
      },
      "name": "Other",
      "children": [
        {
          "data": {
            "url": "http://apps.fedoraproject.org/busmon",
            "description": "A \"cardiogram\" for the fedmsg project.\n"
          },
          "name": "Busmon",
          "id": 18
        },
        {
          "data": {
            "url": "http://mirrors.fedoraproject.org",
            "description": "TODO -- I dunno what to say about this.\n"
          },
          "name": "MirrorManager",
          "id": 19
        },
        {
          "id": 20,
          "data": {
            "url": "http://status.fedoraproject.org",
            "description": "Down for everyone, or just me?\n"
          },
          "name": " Status",
          "icon": "status-good.png"
        },
        {
          "id": 21,
          "data": {
            "url": "http://fedorahosted.org",
            "description": "Project hosting.\n"
          },
          "name": " Fedora Hosted",
          "icon": "trac.png"
        },
        {
          "id": 22,
          "data": {
            "url": "http://pkgs.fedoraproject.org/cgit",
            "description": "Spec files..."
          },
          "name": " SCM",
          "icon": "git-logo.png"
        },
        {
          "id": 23,
          "data": {
            "url": "http://admin.fedoraproject.org/nagios",
            "description": "Is telia down?\n"
          },
          "name": " Nagios",
          "icon": "nagios-logo.png"
        },
        {
          "id": 24,
          "data": {
            "url": "http://admin.fedoraproject.org/collectd",
            "description": "What happened to that httpd root process again?\n"
          },
          "name": " Collectd",
          "icon": "collectd.png"
        }
      ]
    }
  ]
}
<commit_msg>Rebuild of js/data.js<commit_after>
/*
 * Warning.
 * Do not edit this file.  It is generated from data/apps.yaml
 * ...edit that file instead.
 */

var json = {
  "id": 0,
  "data": {
    "description": "This is a landing page for Fedora Apps.  Fedora Infrastructure is huge; this page details only the public facing portion of it all.  Explore!\n"
  },
  "name": "Fedora Apps",
  "children": [
    {
      "id": 1,
      "data": {
        "description": "No clue what's going on?  That's okay.. take a look at some of these sites -- they might help you get your bearings.\n"
      },
      "name": "For New People",
      "children": [
        {
          "data": {
            "url": "http://ask.fedoraproject.org/",
            "description": "Any question at all about Fedora?  Ask it here.\n"
          },
          "name": "Ask Fedora",
          "id": 2
        },
        {
          "data": {
            "url": "http://apps.fedoraproject.org/tagger",
            "description": "Help build a tag cloud of all our packages.. It's actually really useful.  It'll help improve the search of the \"Packages\" webapp.\n"
          },
          "name": "Tagger",
          "id": 3
        },
        {
          "data": {
            "url": "http://fedoraproject.org/easyfix",
            "description": "A list of easy-to-fix problems for the different projects in Fedora.  Interested in getting into helping out with sysadmin work or web application development?  This should be useful to you.\n"
          },
          "name": "Easyfix",
          "id": 4
        },
        {
          "data": {
            "url": "http://docs.fedoraproject.org",
            "description": "RTFM!  Everything you could ever want to know. Probably the best place to find documentation about Fedora, including the changes between releases (and a big kudos to the translation teams to keep this resource up to date in the different languages!)\n"
          },
          "name": "Docs",
          "id": 5
        }
      ]
    },
    {
      "id": 6,
      "data": {
        "description": "Things for everyone! (chances are, this includes you).\n"
      },
      "name": "For the Community",
      "children": [
        {
          "id": 7,
          "data": {
            "url": "http://status.fedoraproject.org",
            "description": "Sometimes the Fedora Infrastructure team messes up (or lightning strikes our datacenter(s)).  Sorry about that. You can use this website to check the status.  Is it \"down for everyone, or just me?\"
Notice the favicon in your browser tab.  It changes based on the status, so if you keep this open you can check back to it at a glance.\n"
          },
          "name": " Status",
          "icon": "status-good.png"
        },
        {
          "id": 8,
          "data": {
            "url": "http://fedoraproject.org/wiki",
            "description": "Maintain your own user profile page, contribute to documents about features, process, and governance.\n"
          },
          "name": " The Wiki",
          "icon": "mediawiki.png"
        },
        {
          "data": {
            "url": "http://admin.fedoraproject.org/voting",
            "description": "As a member of the community, you can now vote for the different steering committees, for this you will use the Election application.  Voting is a right and a duty as a member of the community; it is one of the things you can do to influence the development of Fedora.\n"
          },
          "name": "Elections",
          "id": 9
        },
        {
          "data": {
            "url": "http://fedorapeople.org",
            "description": "Being a community member you gain access to fedorapeople which provides you with a space on the web where you can upload files to share them with the community.\n"
          },
          "name": "FedoraPeople",
          "id": 10
        },
        {
          "id": 11,
          "data": {
            "url": "http://planet.fedoraproject.org",
            "description": "The planet is a blog aggregator, a space accessible to you as a community member where you can express your opinion and talk about what you are doing for Fedora.\n"
          },
          "name": " The Planet",
          "icon": "planet_logo.png"
        },
        {
          "id": 12,
          "data": {
            "url": "http://lists.fedoraproject.org",
            "description": "Mailing lists are used for communication within the community. There are lists for generic topics and lists more dedicated to a specific topic, there is for sure one for you.\n"
          },
          "name": " The Mailing lists",
          "icon": "gnu.png"
        },
        {
          "data": {
            "url": "http://apps.fedoraproject.org/busmon",
            "description": "A \"cardiogram\" for the fedmsg project.  It's not really useful for anything, but it's something pretty to look at -- it can give you the 10,000 foot view of \"what's going on in Fedora\" in real-time.\n"
          },
          "name": "Busmon",
          "id": 13
        },
        {
          "id": 14,
          "data": {
            "url": "http://fedorahosted.org",
            "description": "Fedora is dedicated to open source software. This commitment can extend beyond regular Fedora offerings.
 Fedora Hosted is our most feature rich hosting solution. It includes an scm, trac instance, release dir, account system for access control, etc. This is our most common hosting option.  When most groups want hosting, this is what they want.  \n"
          },
          "name": " Fedora Hosted",
          "icon": "trac.png"
        }
      ]
    },
    {
      "id": 15,
      "data": {
        "description": "Here you'll find apps useful for Packagers' workflow.\n"
      },
      "name": "For Packagers",
      "children": [
        {
          "data": {
            "url": "http://admin.fedoraproject.org/pkgdb",
            "description": "Manage ACLs of your packages.\n"
          },
          "name": "PkgDB",
          "id": 16
        },
        {
          "id": 17,
          "data": {
            "url": "http://koji.fedoraproject.org/koji",
            "description": "Koji is the software that builds RPM packages for the Fedora project.  It uses Mock to create chroot environments to perform builds that are both safe and trusted.\n"
          },
          "name": " Koji",
          "icon": "koji.png"
        },
        {
          "id": 18,
          "data": {
            "url": "http://admin.fedoraproject.org/updates",
            "description": "The tool you will use to push your packages to the Fedora repositories as an update, first an update to be tested (repository: updates-testing) then a stable update (repository: updates).  Behold -- the Magic Cabbage.\n"
          },
          "name": " Bodhi",
          "icon": "bodhi.png"
        },
        {
          "data": {
            "url": "http://apps.fedoraproject.org/packages",
            "description": "The best place for someone outside the community to find out what is in the Fedora repositories. Which packages is present, in which version, who is maintaining it, what patches have been applied, what bugs have been reported against it. All this kind of questions can be answered there.\n"
          },
          "name": "Packages",
          "id": 19
        },
        {
          "id": 20,
          "data": {
            "url": "http://pkgs.fedoraproject.org/cgit",
            "description": "Ever wonder Exactly what is in the new release of a Fedora package?  This is where the change histories of all the packages in Fedora for every release of Fedora (and EPEL) are kept.. forever!  A gold mine."
          },
          "name": " SCM",
          "icon": "git-logo.png"
        }
      ]
    },
    {
      "id": 21,
      "data": {
        "description": "Tools for sysadmins -- the people who run the servers who run Fedora (and otherwise).\n"
      },
      "name": "Sysadmins",
      "children": [
        {
          "data": {
            "url": "http://mirrors.fedoraproject.org",
            "description": "Fedora is distributed to millions of systems globally. This would not be possible without the donations of time, disk space, and bandwidth by hundreds of volunteer system administrators and their companies or institutions.  Your fast download experience is made possible by these donations.  The list on the MirrorManager site is dynamically generated every hour, listing only up-to-date mirrors. \n"
          },
          "name": "MirrorManager",
          "id": 22
        },
        {
          "id": 23,
          "data": {
            "url": "http://admin.fedoraproject.org/nagios",
            "description": "\"Is telia down?\"  The answer can most definitively be found here (and in detail).  The Fedora Infrastructure team uses Nagios to monitor the servers that serve Fedora.  Accessing most details requires membership in the sysadmin group.\n"
          },
          "name": " Nagios",
          "icon": "nagios-logo.png"
        },
        {
          "id": 24,
          "data": {
            "url": "http://admin.fedoraproject.org/collectd",
            "description": "Tracks and displays statistics on the Fedora Infrastructure machines over time.  Useful for debugging ineffeciencies and problems.\n"
          },
          "name": " Collectd",
          "icon": "collectd.png"
        }
      ]
    }
  ]
}
<|endoftext|>


<commit_before>/*!
 * Module dependencies.
 */

var markdown = require('github-flavored-markdown').parse
  , escape = require('./utils').escape;

/**
 * Expose api.
 */

exports.api = require('./api');

/**
 * Parse comments in the given string of `js`.
 *
 * @param {String} js
 * @param {Object} options
 * @return {Array}
 * @see exports.parseComment
 * @api public
 */

exports.parseComments = function(js, options){
  options = options || {};
  js = js.replace(/\r\n/gm, '\n');

  var comments = []
    , raw = options.raw
    , comment
    , buf = ''
    , ignore
    , withinMultiline = false
    , withinSingle = false
    , code;

  for (var i = 0, len = js.length; i < len; ++i) {
    // start comment
    if (!withinMultiline && !withinSingle && '/' == js[i] && '*' == js[i+1]) {
      // code following previous comment
      if (buf.trim().length) {
        comment = comments[comments.length - 1];
        if(comment) {
          comment.code = code = buf.trim();
          comment.ctx = exports.parseCodeContext(code);
        }
        buf = '';
      }
      i += 2;
      withinMultiline = true;
      ignore = '!' == js[i];
    // end comment
    } else if (withinMultiline && !withinSingle && '*' == js[i] && '/' == js[i+1]) {
      i += 2;
      buf = buf.replace(/^[ \t]*\* ?/gm, '');
      var comment = exports.parseComment(buf, options);
      comment.ignore = ignore;
      comments.push(comment);
      withinMultiline = ignore = false;
      buf = '';
    } else if (!withinSingle && !withinMultiline && '/' == js[i] && '/' == js[i+1]) {
      withinSingle = true;
      buf += js[i];
    } else if (withinSingle && !withinMultiline && '\n' == js[i]) {
      withinSingle = false;
      buf += js[i];
    // buffer comment or code
    } else {
      buf += js[i];
    }
  }

  if (comments.length === 0) {
    comments.push({
      tags: [],
      description: {full: '', summary: '', body: ''},
      isPrivate: false
    });
  }

  // trailing code
  if (buf.trim().length) {
    comment = comments[comments.length - 1];
    code = buf.trim();
    comment.code = code;
    comment.ctx = exports.parseCodeContext(code);
  }

  return comments;
};

/**
 * Parse the given comment `str`.
 *
 * The comment object returned contains the following
 *
 *  - `tags`  array of tag objects
 *  - `description` the first line of the comment
 *  - `body` lines following the description
 *  - `content` both the description and the body
 *  - `isPrivate` true when "@api private" is used
 *
 * @param {String} str
 * @param {Object} options
 * @return {Object}
 * @see exports.parseTag
 * @api public
 */

exports.parseComment = function(str, options) {
  str = str.trim();
  options = options || {};

  var comment = { tags: [] }
    , raw = options.raw
    , description = {};

  // parse comment body
  description.full = str.split('\n@')[0];
  description.summary = description.full.split('\n\n')[0];
  description.body = description.full.split('\n\n').slice(1).join('\n\n');
  comment.description = description;

  // parse tags
  if (~str.indexOf('\n@')) {
    var tags = '@' + str.split('\n@').slice(1).join('\n@');
    comment.tags = tags.split('\n').map(exports.parseTag);
    comment.isPrivate = comment.tags.some(function(tag){
      return 'api' == tag.type && 'private' == tag.visibility;
    })
  }

  // markdown
  if (!raw) {
    description.full = markdown(description.full);
    description.summary = markdown(description.summary);
    description.body = markdown(description.body);
  }

  return comment;
}

/**
 * Parse tag string "@param {Array} name description" etc.
 *
 * @param {String}
 * @return {Object}
 * @api public
 */

exports.parseTag = function(str) {
  var tag = {}
    , parts = str.split(/ +/)
    , type = tag.type = parts.shift().replace('@', '');

  switch (type) {
    case 'param':
      tag.types = exports.parseTagTypes(parts.shift());
      tag.name = parts.shift() || '';
      tag.description = parts.join(' ');
      break;
    case 'return':
      tag.types = exports.parseTagTypes(parts.shift());
      tag.description = parts.join(' ');
      break;
    case 'see':
      if (~str.indexOf('http')) {
        tag.title = parts.length > 1
          ? parts.shift()
          : '';
        tag.url = parts.join(' ');
      } else {
        tag.local = parts.join(' ');
      }
    case 'api':
      tag.visibility = parts.shift();
      break;
    case 'type':
      tag.types = exports.parseTagTypes(parts.shift());
      break;
    case 'memberOf':
      tag.parent = parts.shift();
      break;
    case 'augments':
      tag.otherClass = parts.shift();
      break;
    case 'borrows':
      tag.otherMemberName = parts.join(' ').split(' as ')[0];
      tag.thisMemberName = parts.join(' ').split(' as ')[1];
      break;
    case 'throws':
      tag.types = exports.parseTagTypes(parts.shift());
      tag.description = parts.join(' ');
      break;
    default:
      tag.string = parts.join(' ');
      break;
  }

  return tag;
}

/**
 * Parse tag type string "{Array|Object}" etc.
 *
 * @param {String} str
 * @return {Array}
 * @api public
 */

exports.parseTagTypes = function(str) {
  return str
    .replace(/[{}]/g, '')
    .split(/ *[|,\/] */);
};

/**
 * Parse the context from the given `str` of js.
 *
 * This method attempts to discover the context
 * for the comment based on it's code. Currently
 * supports:
 *
 *   - function statements
 *   - function expressions
 *   - prototype methods
 *   - prototype properties
 *   - methods
 *   - properties
 *   - declarations
 *
 * @param {String} str
 * @return {Object}
 * @api public
 */

exports.parseCodeContext = function(str){
  var str = str.split('\n')[0];

  // function statement
  if (/^function ([\w$]+) *\(/.exec(str)) {
    return {
        type: 'function'
      , name: RegExp.$1
      , string: RegExp.$1 + '()'
    };
  // function expression
  } else if (/^var *([\w$]+)[ \t]*=[ \t]*function/.exec(str)) {
    return {
        type: 'function'
      , name: RegExp.$1
      , string: RegExp.$1 + '()'
    };
  // prototype method
  } else if (/^([\w$]+)\.prototype\.([\w$]+)[ \t]*=[ \t]*function/.exec(str)) {
    return {
        type: 'method'
      , constructor: RegExp.$1
      , cons: RegExp.$1
      , name: RegExp.$2
      , string: RegExp.$1 + '.prototype.' + RegExp.$2 + '()'
    };
  // prototype property
  } else if (/^([\w$]+)\.prototype\.([\w$]+)[ \t]*=[ \t]*([^\n;]+)/.exec(str)) {
    return {
        type: 'property'
      , constructor: RegExp.$1
      , cons: RegExp.$1
      , name: RegExp.$2
      , value: RegExp.$3
      , string: RegExp.$1 + '.prototype.' + RegExp.$2
    };
  // method
  } else if (/^([\w$.]+)\.([\w$]+)[ \t]*=[ \t]*function/.exec(str)) {
    return {
        type: 'method'
      , receiver: RegExp.$1
      , name: RegExp.$2
      , string: RegExp.$1 + '.' + RegExp.$2 + '()'
    };
  // property
  } else if (/^([\w$]+)\.([\w$]+)[ \t]*=[ \t]*([^\n;]+)/.exec(str)) {
    return {
        type: 'property'
      , receiver: RegExp.$1
      , name: RegExp.$2
      , value: RegExp.$3
      , string: RegExp.$1 + '.' + RegExp.$2
    };
  // declaration
  } else if (/^var +([\w$]+)[ \t]*=[ \t]*([^\n;]+)/.exec(str)) {
    return {
        type: 'declaration'
      , name: RegExp.$1
      , value: RegExp.$2
      , string: RegExp.$1
    };
  }
};
<commit_msg>add more tags for google closure see https://developers.google.com/closure/compiler/docs/js-for-compiler<commit_after>/*!
 * Module dependencies.
 */

var markdown = require('github-flavored-markdown').parse
  , escape = require('./utils').escape;

/**
 * Expose api.
 */

exports.api = require('./api');

/**
 * Parse comments in the given string of `js`.
 *
 * @param {String} js
 * @param {Object} options
 * @return {Array}
 * @see exports.parseComment
 * @api public
 */

exports.parseComments = function(js, options){
  options = options || {};
  js = js.replace(/\r\n/gm, '\n');

  var comments = []
    , raw = options.raw
    , comment
    , buf = ''
    , ignore
    , withinMultiline = false
    , withinSingle = false
    , code;

  for (var i = 0, len = js.length; i < len; ++i) {
    // start comment
    if (!withinMultiline && !withinSingle && '/' == js[i] && '*' == js[i+1]) {
      // code following previous comment
      if (buf.trim().length) {
        comment = comments[comments.length - 1];
        if(comment) {
          comment.code = code = buf.trim();
          comment.ctx = exports.parseCodeContext(code);
        }
        buf = '';
      }
      i += 2;
      withinMultiline = true;
      ignore = '!' == js[i];
    // end comment
    } else if (withinMultiline && !withinSingle && '*' == js[i] && '/' == js[i+1]) {
      i += 2;
      buf = buf.replace(/^[ \t]*\* ?/gm, '');
      var comment = exports.parseComment(buf, options);
      comment.ignore = ignore;
      comments.push(comment);
      withinMultiline = ignore = false;
      buf = '';
    } else if (!withinSingle && !withinMultiline && '/' == js[i] && '/' == js[i+1]) {
      withinSingle = true;
      buf += js[i];
    } else if (withinSingle && !withinMultiline && '\n' == js[i]) {
      withinSingle = false;
      buf += js[i];
    // buffer comment or code
    } else {
      buf += js[i];
    }
  }

  if (comments.length === 0) {
    comments.push({
      tags: [],
      description: {full: '', summary: '', body: ''},
      isPrivate: false
    });
  }

  // trailing code
  if (buf.trim().length) {
    comment = comments[comments.length - 1];
    code = buf.trim();
    comment.code = code;
    comment.ctx = exports.parseCodeContext(code);
  }

  return comments;
};

/**
 * Parse the given comment `str`.
 *
 * The comment object returned contains the following
 *
 *  - `tags`  array of tag objects
 *  - `description` the first line of the comment
 *  - `body` lines following the description
 *  - `content` both the description and the body
 *  - `isPrivate` true when "@api private" is used
 *
 * @param {String} str
 * @param {Object} options
 * @return {Object}
 * @see exports.parseTag
 * @api public
 */

exports.parseComment = function(str, options) {
  str = str.trim();
  options = options || {};

  var comment = { tags: [] }
    , raw = options.raw
    , description = {};

  // parse comment body
  description.full = str.split('\n@')[0];
  description.summary = description.full.split('\n\n')[0];
  description.body = description.full.split('\n\n').slice(1).join('\n\n');
  comment.description = description;

  // parse tags
  if (~str.indexOf('\n@')) {
    var tags = '@' + str.split('\n@').slice(1).join('\n@');
    comment.tags = tags.split('\n').map(exports.parseTag);
    comment.isPrivate = comment.tags.some(function(tag){
      return 'private' == tag.visibility;
    })
  }

  // markdown
  if (!raw) {
    description.full = markdown(description.full);
    description.summary = markdown(description.summary);
    description.body = markdown(description.body);
  }

  return comment;
}

/**
 * Parse tag string "@param {Array} name description" etc.
 *
 * @param {String}
 * @return {Object}
 * @api public
 */

exports.parseTag = function(str) {
  var tag = {}
    , parts = str.split(/ +/)
    , type = tag.type = parts.shift().replace('@', '');

  switch (type) {
    case 'property':
    case 'template':
    case 'param':
      tag.types = exports.parseTagTypes(parts.shift());
      tag.name = parts.shift() || '';
      tag.description = parts.join(' ');
      break;
    case 'define':
    case 'return':
      tag.types = exports.parseTagTypes(parts.shift());
      tag.description = parts.join(' ');
      break;
    case 'see':
      if (~str.indexOf('http')) {
        tag.title = parts.length > 1
          ? parts.shift()
          : '';
        tag.url = parts.join(' ');
      } else {
        tag.local = parts.join(' ');
      }
      break;
    case 'api':
      tag.visibility = parts.shift();
      break;
    case 'public':
    case 'private':
    case 'protected':
      tag.visibility = type;
      break;
    case 'enum':
    case 'typedef':
    case 'type':
      tag.types = exports.parseTagTypes(parts.shift());
      break;
    case 'lends':
    case 'memberOf':
      tag.parent = parts.shift();
      break;
    case 'extends':
    case 'implements':
    case 'augments':
      tag.otherClass = parts.shift();
      break;
    case 'borrows':
      tag.otherMemberName = parts.join(' ').split(' as ')[0];
      tag.thisMemberName = parts.join(' ').split(' as ')[1];
      break;
    case 'throws':
      tag.types = exports.parseTagTypes(parts.shift());
      tag.description = parts.join(' ');
      break;
    default:
      tag.string = parts.join(' ');
      break;
  }

  return tag;
}

/**
 * Parse tag type string "{Array|Object}" etc.
 *
 * @param {String} str
 * @return {Array}
 * @api public
 */

exports.parseTagTypes = function(str) {
  return str
    .replace(/[{}]/g, '')
    .split(/ *[|,\/] */);
};

/**
 * Parse the context from the given `str` of js.
 *
 * This method attempts to discover the context
 * for the comment based on it's code. Currently
 * supports:
 *
 *   - function statements
 *   - function expressions
 *   - prototype methods
 *   - prototype properties
 *   - methods
 *   - properties
 *   - declarations
 *
 * @param {String} str
 * @return {Object}
 * @api public
 */

exports.parseCodeContext = function(str){
  var str = str.split('\n')[0];

  // function statement
  if (/^function ([\w$]+) *\(/.exec(str)) {
    return {
        type: 'function'
      , name: RegExp.$1
      , string: RegExp.$1 + '()'
    };
  // function expression
  } else if (/^var *([\w$]+)[ \t]*=[ \t]*function/.exec(str)) {
    return {
        type: 'function'
      , name: RegExp.$1
      , string: RegExp.$1 + '()'
    };
  // prototype method
  } else if (/^([\w$]+)\.prototype\.([\w$]+)[ \t]*=[ \t]*function/.exec(str)) {
    return {
        type: 'method'
      , constructor: RegExp.$1
      , cons: RegExp.$1
      , name: RegExp.$2
      , string: RegExp.$1 + '.prototype.' + RegExp.$2 + '()'
    };
  // prototype property
  } else if (/^([\w$]+)\.prototype\.([\w$]+)[ \t]*=[ \t]*([^\n;]+)/.exec(str)) {
    return {
        type: 'property'
      , constructor: RegExp.$1
      , cons: RegExp.$1
      , name: RegExp.$2
      , value: RegExp.$3
      , string: RegExp.$1 + '.prototype.' + RegExp.$2
    };
  // method
  } else if (/^([\w$.]+)\.([\w$]+)[ \t]*=[ \t]*function/.exec(str)) {
    return {
        type: 'method'
      , receiver: RegExp.$1
      , name: RegExp.$2
      , string: RegExp.$1 + '.' + RegExp.$2 + '()'
    };
  // property
  } else if (/^([\w$]+)\.([\w$]+)[ \t]*=[ \t]*([^\n;]+)/.exec(str)) {
    return {
        type: 'property'
      , receiver: RegExp.$1
      , name: RegExp.$2
      , value: RegExp.$3
      , string: RegExp.$1 + '.' + RegExp.$2
    };
  // declaration
  } else if (/^var +([\w$]+)[ \t]*=[ \t]*([^\n;]+)/.exec(str)) {
    return {
        type: 'declaration'
      , name: RegExp.$1
      , value: RegExp.$2
      , string: RegExp.$1
    };
  }
};
<|endoftext|>


<commit_before>'use strict';

function update_color(){
    var current_time = Math.floor(time_date_to_timestamp() / interval).toString();
    var hex = '#' + current_time.substr(current_time.length - 6);

    document.body.style.background = hex;
    document.getElementById('current-color').innerHTML = hex;
}

var interval = 100;
<commit_msg>added pause<commit_after>'use strict';

function update_color(){
    if(core_menu_open){
        return;
    }

    var current_time = Math.floor(time_date_to_timestamp() / interval).toString();
    var hex = '#' + current_time.substr(current_time.length - 6);

    document.body.style.background = hex;
    document.getElementById('current-color').innerHTML = hex;
}

var interval = 100;
<|endoftext|>


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

var utils = require('./utils')
  , ejs
  , templateCache = {}
  , jsCache = {}
  , includeFile
  , includeSource
  , resolveInclude
  , compile
  , rethrow
  , _DEFAULT_DELIMITER = '%'
  , _REGEX_STRING = '(<%%)|(<%=)|(<%-)|(<%#)|(<%)|(%>)|(-%>)'
  , _OPTS_MAP = {
      cache: 'cache'
    , filename: 'filename'
    , delimiter: 'delimiter'
    , scope: 'context'
    , context: 'context'
    , debug: 'debug'
    , compileDebug: 'compileDebug'
    , client: 'client'
    };

resolveInclude = function (name, filename) {
  var path = require('path')
    , dirname = path.dirname
    , extname = path.extname
    , join = path.join
    , includePath = join(dirname(filename), name)
    , ext = extname(name);
  if (!ext) {
    includePath += '.ejs';
  }
  return includePath;
};

includeFile = function (path, options) {
  var fn
    , opts = utils.shallowCopy({}, options || {})
    , fs = require('fs')
    , includePath
    , template;
  if (!opts.filename) {
    throw new Error('`include` requires the \'filename\' option.');
  }
  includePath = resolveInclude(path, opts.filename);
  if (opts.cache) {
    template = templateCache[includePath];
    if (!template) {
      template = fs.readFileSync(includePath).toString().trim();
      templateCache[includePath] = template;
    }
  }
  else {
    template = fs.readFileSync(includePath).toString().trim();
  }

  opts.filename = includePath;
  fn = exports.compile(template, opts);
  return fn;
};

includeSource = function (path, options) {
  var fn
    , opts = utils.shallowCopy({}, options || {})
    , fs = require('fs')
    , includePath
    , template;
  if (!opts.filename) {
    throw new Error('`include` requires the \'filename\' option.');
  }
  includePath = resolveInclude(path, opts.filename);
  if (opts.cache) {
    template = templateCache[includePath];
    if (!template) {
      template = fs.readFileSync(includePath).toString().trim();
      templateCache[includePath] = template;
    }
  }
  else {
    template = fs.readFileSync(includePath).toString().trim();
  }

  opts.filename = includePath;
  var templ = new Template(template, opts);
  templ.generateSource();
  return templ.source;
};

function rethrow(err, str, filename, lineno){
  var lines = str.split('\n')
    , start = Math.max(lineno - 3, 0)
    , end = Math.min(lines.length, lineno + 3);

  // Error context
  var context = lines.slice(start, end).map(function(line, i){
    var curr = i + start + 1;
    return (curr == lineno ? ' >> ' : '    ')
      + curr
      + '| '
      + line;
  }).join('\n');

  // Alter exception message
  err.path = filename;
  err.message = (filename || 'ejs') + ':'
    + lineno + '\n'
    + context + '\n\n'
    + err.message;

  throw err;
}

compile = exports.compile = function (template, opts) {
  var templ = new Template(template, opts);
  return templ.compile();
};

// template, [data], [opts]
// Have to include an empty data object if you want opts and no data
exports.render = function () {
  var args = Array.prototype.slice.call(arguments)
    , template = args.shift()
    , data = args.shift() || {}
    , opts = args.shift() || {}
    , fn
    , filename;

  // No options object -- if there are optiony names
  // in the data, copy them to options
  if (arguments.length == 2) {
    for (var p in _OPTS_MAP) {
      if (typeof data[p] != 'undefined') {
        opts[_OPTS_MAP[p]] = data[p];
      }
    }
  }
  // v1 compat
  // 'scope' is 'context'
  // FIXME: Remove this in a future version
  if (opts.scope) {
    opts.context = opts.scope;
    delete opts.context;
  }

  if (opts.cache) {
    filename = opts.filename;
    if (!filename) {
      throw new Error('cache option requrires a filename');
    }
    fn = jsCache[filename];
    if (!fn) {
      fn = exports.compile(template, opts);
      jsCache[filename] = fn;
    }
  }
  else {
    fn = exports.compile(template, opts);
  }
  return fn.call(opts.context, data);
};

// path, [data] [opts], cb
// Have to include an empty data object if you want opts and no data
exports.renderFile = function () {
  var read = require('fs').readFile
    , args = Array.prototype.slice.call(arguments)
    , path = args.shift()
    , cb = args.pop()
    , data = args.shift() || {}
    , opts = args.pop() || {}
    , template
    , handleTemplate;

  // Set the filename for includes
  opts.filename = path;

  handleTemplate = function (template) {
    var result;
    try {
      result = exports.render(template, data, opts);
    }
    catch(err) {
      cb(err);
    }
    cb(null, result);
  };

  template = templateCache[path];
  if (opts.cache && template) {
    handleTemplate(template);
  }
  else {
    read(path, function (err, data) {
      var tmpl;
      if (err) {
        return cb(err);
      }
      tmpl = data.toString().trim();
      if (opts.cache) {
        templateCache[path] = tmpl;
      }
      handleTemplate(tmpl);
    });
  }
};

exports.clearCache = function () {
  templateCache = {};
  jsCache = {};
};

var Template = function (text, opts) {
  opts = opts || {};
  var options = {};
  this.templateText = text;
  this.mode = null;
  this.truncate = false;
  this.currentLine = 1;
  this.source = '';
  options.client = opts.client || false;
  options.escapeFunction = opts.escape || utils.escapeXML;
  options.compileDebug = opts.compileDebug !== false;
  options.filename = opts.filename;
  options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER;
  this.opts = options;

  this.regex = this.createRegex();
};

Template.prototype = new function () {

  this.modes = {
      EVAL: 'eval'
    , ESCAPED: 'escaped'
    , RAW: 'raw'
    , APPEND: 'append'
    , COMMENT: 'comment'
    , LITERAL: 'literal'
  };

  this.createRegex = function () {
    var str = _REGEX_STRING
      , delim = utils.escapeRegExpChars(this.opts.delimiter);
    str = str.replace(/%/g, delim);
    return new RegExp(str);
  };

  this.compile = function () {
    var self = this
      , src
      , fn
      , opts = this.opts
      , escape = opts.escapeFunction;

    if (!this.source) {
      this.generateSource();
      // FIXME: EtherpadLite accesses the old internal `buf` variable
      // in their bootstrap code: https://github.com/ether/etherpad-lite/issues/2437
      // Remove this bandaid ASAP
      var appended = 'var buf = []; var __output = "";';
      if (opts._with !== false) appended +=  ' with (locals || {}) { ';
      this.source  = appended + this.source;
      if (opts._with !== false) this.source += '}';
      this.source += 'buf = [__output]; return __output.trim();';
    }

    if (opts.compileDebug) {
      src = 'var __line = 1' +
          ', __lines = ' + JSON.stringify(this.templateText) +
          ', __filename = ' + (opts.filename ?
                JSON.stringify(opts.filename) : 'undefined') +
          '; try {' +
          this.source + '} catch (e) { rethrow(e, __lines, __filename, __line); }';
    }
    else {
      src = this.source;
    }

    if (opts.debug) {
      console.log(src);
    }

    if (opts.client) {
      src = 'escape = escape || ' + escape.toString() + ';\n' + src;
      src = 'rethrow = rethrow || ' + rethrow.toString() + ';\n' + src;
    }

    try {
      fn = new Function('locals, escape, include, rethrow', src);
    }
    catch(e) {
      if (e instanceof SyntaxError) {
        if (opts.filename) {
          e.message += ' in ' + opts.filename;
        }
        e.message += ' while compiling ejs';
        throw e;
      }
    }

    if (opts.client) {
      return fn;
    }

    // Return a callable function which will execute the function
    // created by the source-code, with the passed data as locals
    return function (data) {
      var include = function (path, includeData) {
        var d = utils.shallowCopy({}, data);
        if (includeData) {
          d = utils.shallowCopy(d, includeData);
        }
        return includeFile(path, opts).apply(this, [d]);
      };
      return fn.apply(this, [data || {}, escape, include, rethrow]);
    };

  };

  this.generateSource = function () {
    var self = this
      , matches = this.parseTemplateText()
      , d = this.opts.delimiter;

    if (matches && matches.length) {
      matches.forEach(function (line, index) {
        var closing
          , include
          , includeOpts
          , includeSrc;
        // If this is an opening tag, check for closing tags
        // FIXME: May end up with some false positives here
        // Better to store modes as k/v with '<' + delimiter as key
        // Then this can simply check against the map
        if (line.indexOf('<' + d) === 0) {
          closing = matches[index + 2];
          if (!(closing == d + '>' || closing == '-' + d + '>')) {
            throw new Error('Could not find matching close tag for "' + line + '".');
          }
        }
        // HACK: backward-compat `include` preprocessor directives
        if ((include = line.match(/^\s*include\s+(\S+)/))) {
          includeOpts = utils.shallowCopy({}, self.opts);
          includeSrc = includeSource(include[1], includeOpts);
          includeSrc = ";(function(){" + includeSrc + "})();";
          self.source += includeSrc;
        }
        else {
          self.scanLine(line);
        }
      });
    }

  };

  this.parseTemplateText = function () {
    var str = this.templateText
      , pat = this.regex
      , result = pat.exec(str)
      , arr = []
      , firstPos
      , lastPos;

    while (result) {
      firstPos = result.index;
      lastPos = pat.lastIndex;

      if (firstPos !== 0) {
        arr.push(str.substring(0, firstPos));
        str = str.slice(firstPos);
      }

      arr.push(result[0]);
      str = str.slice(result[0].length);
      result = pat.exec(str);
    }

    if (str !== '') {
      arr.push(str);
    }

    return arr;
  };

  this.scanLine = function (line) {
    var self = this
      , d = this.opts.delimiter
      , newLineCount = 0
      , _addOutput;

    _addOutput = function () {
      if (self.truncate) {
        line = line.replace('\n', '');
      }

      // Preserve literal slashes
      line = line.replace(/\\/g, '\\\\');

      // Convert linebreaks
      line = line.replace(/\n/g, '\\n');
      line = line.replace(/\r/g, '\\r');

      // Escape double-quotes
      // - this will be the delimiter during execution
      line = line.replace(/"/g, '\\"');
      self.source += ';__output += "' + line + '";';
    };

    newLineCount = (line.split('\n').length - 1);

    switch (line) {
      case '<' + d:
        this.mode = this.modes.EVAL;
        break;
      case '<' + d + '=':
        this.mode = this.modes.ESCAPED;
        break;
      case '<' + d + '-':
        this.mode = this.modes.RAW;
        break;
      case '<' + d + '#':
        this.mode = this.modes.COMMENT;
        break;
      case '<' + d + d:
        this.mode = this.modes.LITERAL;
        this.source += ';__output += "' + line.replace('<' + d + d, '<' + d) + '";';
        break;
      case d + '>':
      case '-' + d + '>':
        if (this.mode == this.modes.LITERAL) {
          _addOutput();
        }

        this.mode = null;
        this.truncate = line.indexOf('-') === 0;
        break;
      default:
        // In script mode, depends on type of tag
        if (this.mode) {
          // Strip double-slash comments in all exec modes
          switch (this.mode) {
            case this.modes.EVAL:
            case this.modes.ESCAPED:
            case this.modes.RAW:
              line = line.replace(/\/\/.*$/, '');
          }
          switch (this.mode) {
            // Just executing code
            case this.modes.EVAL:
              this.source += line;
              break;
            // Exec, esc, and output
            case this.modes.ESCAPED:
              // Add the exec'd, escaped result to the output
              this.source += ';__output += escape(' +
                  line.replace(/;\S*/, '').trim() + ');';
              break;
            // Exec and output
            case this.modes.RAW:
              // Add the exec'd result to the output
              this.source += ';__output += ' + line.trim() + ';';
              break;
            case this.modes.COMMENT:
              // Do nothing
              break;
            // Literal <%% mode, append as raw output
            case this.modes.LITERAL:
              _addOutput();
              break;
          }
        }
        // In string mode, just add the output
        else {
          _addOutput();
        }
    }

    if (newLineCount) {
      this.currentLine += newLineCount;
      this.source += ';__line = ' + this.currentLine + ';';
    }
  };
};

// Express support
exports.__express = exports.renderFile;

// Add require support
if (require.extensions) {
  require.extensions['.ejs'] = function (module, filename) {
    filename = filename || module.filename;
    var fs = require('fs')
      , options = {
          filename: filename
        , client: true
        }
      , template = fs.readFileSync(filename).toString().trim()
      , fn = compile(template, options);
    module._compile('module.exports = ' + fn.toString() + ';', filename);
  };
}

if (typeof window != 'undefined') {
  window.ejs = exports;
}
<commit_msg>Fix _with<commit_after>/*
 * EJS Embedded JavaScript templates
 * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

var utils = require('./utils')
  , ejs
  , templateCache = {}
  , jsCache = {}
  , includeFile
  , includeSource
  , resolveInclude
  , compile
  , rethrow
  , _DEFAULT_DELIMITER = '%'
  , _REGEX_STRING = '(<%%)|(<%=)|(<%-)|(<%#)|(<%)|(%>)|(-%>)'
  , _OPTS_MAP = {
      cache: 'cache'
    , filename: 'filename'
    , delimiter: 'delimiter'
    , scope: 'context'
    , context: 'context'
    , debug: 'debug'
    , compileDebug: 'compileDebug'
    , client: 'client'
    };

resolveInclude = function (name, filename) {
  var path = require('path')
    , dirname = path.dirname
    , extname = path.extname
    , join = path.join
    , includePath = join(dirname(filename), name)
    , ext = extname(name);
  if (!ext) {
    includePath += '.ejs';
  }
  return includePath;
};

includeFile = function (path, options) {
  var fn
    , opts = utils.shallowCopy({}, options || {})
    , fs = require('fs')
    , includePath
    , template;
  if (!opts.filename) {
    throw new Error('`include` requires the \'filename\' option.');
  }
  includePath = resolveInclude(path, opts.filename);
  if (opts.cache) {
    template = templateCache[includePath];
    if (!template) {
      template = fs.readFileSync(includePath).toString().trim();
      templateCache[includePath] = template;
    }
  }
  else {
    template = fs.readFileSync(includePath).toString().trim();
  }

  opts.filename = includePath;
  fn = exports.compile(template, opts);
  return fn;
};

includeSource = function (path, options) {
  var fn
    , opts = utils.shallowCopy({}, options || {})
    , fs = require('fs')
    , includePath
    , template;
  if (!opts.filename) {
    throw new Error('`include` requires the \'filename\' option.');
  }
  includePath = resolveInclude(path, opts.filename);
  if (opts.cache) {
    template = templateCache[includePath];
    if (!template) {
      template = fs.readFileSync(includePath).toString().trim();
      templateCache[includePath] = template;
    }
  }
  else {
    template = fs.readFileSync(includePath).toString().trim();
  }

  opts.filename = includePath;
  var templ = new Template(template, opts);
  templ.generateSource();
  return templ.source;
};

function rethrow(err, str, filename, lineno){
  var lines = str.split('\n')
    , start = Math.max(lineno - 3, 0)
    , end = Math.min(lines.length, lineno + 3);

  // Error context
  var context = lines.slice(start, end).map(function(line, i){
    var curr = i + start + 1;
    return (curr == lineno ? ' >> ' : '    ')
      + curr
      + '| '
      + line;
  }).join('\n');

  // Alter exception message
  err.path = filename;
  err.message = (filename || 'ejs') + ':'
    + lineno + '\n'
    + context + '\n\n'
    + err.message;

  throw err;
}

compile = exports.compile = function (template, opts) {
  var templ = new Template(template, opts);
  return templ.compile();
};

// template, [data], [opts]
// Have to include an empty data object if you want opts and no data
exports.render = function () {
  var args = Array.prototype.slice.call(arguments)
    , template = args.shift()
    , data = args.shift() || {}
    , opts = args.shift() || {}
    , fn
    , filename;

  // No options object -- if there are optiony names
  // in the data, copy them to options
  if (arguments.length == 2) {
    for (var p in _OPTS_MAP) {
      if (typeof data[p] != 'undefined') {
        opts[_OPTS_MAP[p]] = data[p];
      }
    }
  }
  // v1 compat
  // 'scope' is 'context'
  // FIXME: Remove this in a future version
  if (opts.scope) {
    opts.context = opts.scope;
    delete opts.context;
  }

  if (opts.cache) {
    filename = opts.filename;
    if (!filename) {
      throw new Error('cache option requrires a filename');
    }
    fn = jsCache[filename];
    if (!fn) {
      fn = exports.compile(template, opts);
      jsCache[filename] = fn;
    }
  }
  else {
    fn = exports.compile(template, opts);
  }
  return fn.call(opts.context, data);
};

// path, [data] [opts], cb
// Have to include an empty data object if you want opts and no data
exports.renderFile = function () {
  var read = require('fs').readFile
    , args = Array.prototype.slice.call(arguments)
    , path = args.shift()
    , cb = args.pop()
    , data = args.shift() || {}
    , opts = args.pop() || {}
    , template
    , handleTemplate;

  // Set the filename for includes
  opts.filename = path;

  handleTemplate = function (template) {
    var result;
    try {
      result = exports.render(template, data, opts);
    }
    catch(err) {
      cb(err);
    }
    cb(null, result);
  };

  template = templateCache[path];
  if (opts.cache && template) {
    handleTemplate(template);
  }
  else {
    read(path, function (err, data) {
      var tmpl;
      if (err) {
        return cb(err);
      }
      tmpl = data.toString().trim();
      if (opts.cache) {
        templateCache[path] = tmpl;
      }
      handleTemplate(tmpl);
    });
  }
};

exports.clearCache = function () {
  templateCache = {};
  jsCache = {};
};

var Template = function (text, opts) {
  opts = opts || {};
  var options = {};
  this.templateText = text;
  this.mode = null;
  this.truncate = false;
  this.currentLine = 1;
  this.source = '';
  options.client = opts.client || false;
  options.escapeFunction = opts.escape || utils.escapeXML;
  options.compileDebug = opts.compileDebug !== false;
  options.filename = opts.filename;
  options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER;
  options._with = opts._with != null ? opts._with : true
  this.opts = options;

  this.regex = this.createRegex();
};

Template.prototype = new function () {

  this.modes = {
      EVAL: 'eval'
    , ESCAPED: 'escaped'
    , RAW: 'raw'
    , APPEND: 'append'
    , COMMENT: 'comment'
    , LITERAL: 'literal'
  };

  this.createRegex = function () {
    var str = _REGEX_STRING
      , delim = utils.escapeRegExpChars(this.opts.delimiter);
    str = str.replace(/%/g, delim);
    return new RegExp(str);
  };

  this.compile = function () {
    var self = this
      , src
      , fn
      , opts = this.opts
      , escape = opts.escapeFunction;

    if (!this.source) {
      this.generateSource();
      // FIXME: EtherpadLite accesses the old internal `buf` variable
      // in their bootstrap code: https://github.com/ether/etherpad-lite/issues/2437
      // Remove this bandaid ASAP
      var appended = 'var buf = []; var __output = "";';
      if (opts._with !== false) appended +=  ' with (locals || {}) { ';
      this.source  = appended + this.source;
      if (opts._with !== false) this.source += '}';
      this.source += 'buf = [__output]; return __output.trim();';
    }

    if (opts.compileDebug) {
      src = 'var __line = 1' +
          ', __lines = ' + JSON.stringify(this.templateText) +
          ', __filename = ' + (opts.filename ?
                JSON.stringify(opts.filename) : 'undefined') +
          '; try {' +
          this.source + '} catch (e) { rethrow(e, __lines, __filename, __line); }';
    }
    else {
      src = this.source;
    }

    if (opts.debug) {
      console.log(src);
    }

    if (opts.client) {
      src = 'escape = escape || ' + escape.toString() + ';\n' + src;
      src = 'rethrow = rethrow || ' + rethrow.toString() + ';\n' + src;
    }

    try {
      fn = new Function('locals, escape, include, rethrow', src);
    }
    catch(e) {
      if (e instanceof SyntaxError) {
        if (opts.filename) {
          e.message += ' in ' + opts.filename;
        }
        e.message += ' while compiling ejs';
        throw e;
      }
    }

    if (opts.client) {
      return fn;
    }

    // Return a callable function which will execute the function
    // created by the source-code, with the passed data as locals
    return function (data) {
      var include = function (path, includeData) {
        var d = utils.shallowCopy({}, data);
        if (includeData) {
          d = utils.shallowCopy(d, includeData);
        }
        return includeFile(path, opts).apply(this, [d]);
      };
      return fn.apply(this, [data || {}, escape, include, rethrow]);
    };

  };

  this.generateSource = function () {
    var self = this
      , matches = this.parseTemplateText()
      , d = this.opts.delimiter;

    if (matches && matches.length) {
      matches.forEach(function (line, index) {
        var closing
          , include
          , includeOpts
          , includeSrc;
        // If this is an opening tag, check for closing tags
        // FIXME: May end up with some false positives here
        // Better to store modes as k/v with '<' + delimiter as key
        // Then this can simply check against the map
        if (line.indexOf('<' + d) === 0) {
          closing = matches[index + 2];
          if (!(closing == d + '>' || closing == '-' + d + '>')) {
            throw new Error('Could not find matching close tag for "' + line + '".');
          }
        }
        // HACK: backward-compat `include` preprocessor directives
        if ((include = line.match(/^\s*include\s+(\S+)/))) {
          includeOpts = utils.shallowCopy({}, self.opts);
          includeSrc = includeSource(include[1], includeOpts);
          includeSrc = ";(function(){" + includeSrc + "})();";
          self.source += includeSrc;
        }
        else {
          self.scanLine(line);
        }
      });
    }

  };

  this.parseTemplateText = function () {
    var str = this.templateText
      , pat = this.regex
      , result = pat.exec(str)
      , arr = []
      , firstPos
      , lastPos;

    while (result) {
      firstPos = result.index;
      lastPos = pat.lastIndex;

      if (firstPos !== 0) {
        arr.push(str.substring(0, firstPos));
        str = str.slice(firstPos);
      }

      arr.push(result[0]);
      str = str.slice(result[0].length);
      result = pat.exec(str);
    }

    if (str !== '') {
      arr.push(str);
    }

    return arr;
  };

  this.scanLine = function (line) {
    var self = this
      , d = this.opts.delimiter
      , newLineCount = 0
      , _addOutput;

    _addOutput = function () {
      if (self.truncate) {
        line = line.replace('\n', '');
      }

      // Preserve literal slashes
      line = line.replace(/\\/g, '\\\\');

      // Convert linebreaks
      line = line.replace(/\n/g, '\\n');
      line = line.replace(/\r/g, '\\r');

      // Escape double-quotes
      // - this will be the delimiter during execution
      line = line.replace(/"/g, '\\"');
      self.source += ';__output += "' + line + '";';
    };

    newLineCount = (line.split('\n').length - 1);

    switch (line) {
      case '<' + d:
        this.mode = this.modes.EVAL;
        break;
      case '<' + d + '=':
        this.mode = this.modes.ESCAPED;
        break;
      case '<' + d + '-':
        this.mode = this.modes.RAW;
        break;
      case '<' + d + '#':
        this.mode = this.modes.COMMENT;
        break;
      case '<' + d + d:
        this.mode = this.modes.LITERAL;
        this.source += ';__output += "' + line.replace('<' + d + d, '<' + d) + '";';
        break;
      case d + '>':
      case '-' + d + '>':
        if (this.mode == this.modes.LITERAL) {
          _addOutput();
        }

        this.mode = null;
        this.truncate = line.indexOf('-') === 0;
        break;
      default:
        // In script mode, depends on type of tag
        if (this.mode) {
          // Strip double-slash comments in all exec modes
          switch (this.mode) {
            case this.modes.EVAL:
            case this.modes.ESCAPED:
            case this.modes.RAW:
              line = line.replace(/\/\/.*$/, '');
          }
          switch (this.mode) {
            // Just executing code
            case this.modes.EVAL:
              this.source += line;
              break;
            // Exec, esc, and output
            case this.modes.ESCAPED:
              // Add the exec'd, escaped result to the output
              this.source += ';__output += escape(' +
                  line.replace(/;\S*/, '').trim() + ');';
              break;
            // Exec and output
            case this.modes.RAW:
              // Add the exec'd result to the output
              this.source += ';__output += ' + line.trim() + ';';
              break;
            case this.modes.COMMENT:
              // Do nothing
              break;
            // Literal <%% mode, append as raw output
            case this.modes.LITERAL:
              _addOutput();
              break;
          }
        }
        // In string mode, just add the output
        else {
          _addOutput();
        }
    }

    if (newLineCount) {
      this.currentLine += newLineCount;
      this.source += ';__line = ' + this.currentLine + ';';
    }
  };
};

// Express support
exports.__express = exports.renderFile;

// Add require support
if (require.extensions) {
  require.extensions['.ejs'] = function (module, filename) {
    filename = filename || module.filename;
    var fs = require('fs')
      , options = {
          filename: filename
        , client: true
        }
      , template = fs.readFileSync(filename).toString().trim()
      , fn = compile(template, options);
    module._compile('module.exports = ' + fn.toString() + ';', filename);
  };
}

if (typeof window != 'undefined') {
  window.ejs = exports;
}
<|endoftext|>


<commit_before>DateUtilities = {

    addDay : function(date, days) {
        date.setHours(date.getHours() + 24*days);
    },

    roundToFollowingHalfHour : function(date) {
        date.setMilliseconds(0);
        date.setSeconds(0);

        if(date.getMinutes() < 30) {
            date.setMinutes(30);
        }

        if(date.getMinutes() > 30) {
            date.setMinutes(30);
            date.setHours(date.getHours() + 1);
        }
    },

    // TODO: handle time before opening
    nextOpenTime: function(date) {
        var changed = false;

        if(date.getHours() >= 20) {
            date.setHours(8 + 24);
            changed = true;
        }

        if(date.getDay() == 0) {
            date.setHours(date.getHours() + 24);
            changed = true;
        }

        return changed;
    }

};
<commit_msg>Fix function nextOpenTime to handle hours before opening.<commit_after>DateUtilities = {

    addDay : function(date, days) {
        date.setHours(date.getHours() + 24*days);
    },

    roundToFollowingHalfHour : function(date) {
        date.setMilliseconds(0);
        date.setSeconds(0);

        if(date.getMinutes() < 30) {
            date.setMinutes(30);
        }

        if(date.getMinutes() > 30) {
            date.setMinutes(30);
            date.setHours(date.getHours() + 1);
        }
    },

    // TODO: handle time before opening
    nextOpenTime: function(date) {
        var changed = false;

        if(date.getHours() < 8) {
            date.setHours(8);
            changed = true;
        }

        if(date.getHours() >= 20) {
            date.setHours(8 + 24);
            changed = true;
        }

        if(date.getDay() == 0) {
            date.setHours(date.getHours() + 24);
            changed = true;
        }

        return changed;
    }

};
<|endoftext|>


<commit_before>
/*!
 * EJS
 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var sys = require('sys');

/**
 * Library version.
 */

exports.version = '0.0.3';

/**
 * Intermediate js cache.
 *
 * @type Object
 */

var cache = {};

/**
 * Clear intermediate js cache.
 *
 * @api public
 */

exports.clearCache = function(){
    cache = {};
};

/**
 * Escape the given string of `html`.
 *
 * @param {String} html
 * @return {String}
 * @api private
 */

function escape(html){
    return String(html)
        .replace(/&(?!\w+;)/g, '&')
        .replace(/</g, '<')
        .replace(/>/g, '>')
        .replace(/"/g, '"');
}

/**
 * Parse the given `str` of ejs, returning the function body.
 *
 * @param {String} str
 * @return {String}
 * @api public
 */

var parse = exports.parse = function(str){
    str = String(str)
        .replace(/\r/g, " ")    // no carriage returns, used later
        .replace(/\n/g, "\\n"); // escaped newlines

    var output = '';

    while(str) {
        // split() with a limit doesn't return the remainder, do it another way
        var parts = str.replace('<%', '\r').split('\r');
        var content = parts.shift(), remainder = parts.shift();

        if(content) {
          // escape single quotes
          content = content.replace(/(^|[^\\])'/g, "$1\\'");
          output += '\'' + content + '\', ';
        }

        if(remainder) {
          var code_parts = remainder.replace('%>', '\r').split('\r');
          var code = code_parts.shift();
          // escaped output
          if(code.match(/^=/)) {
            output += code.replace(/^=(.*)/, "escape($1), ");
          }
          // raw output
          else if(code.match(/^-/)) {
            output +=  code.replace(/^-(.*)/, "$1, ");
          }
          // unbuffered output
          else {
            output += "''); " + code + 'buf.push(';
          }
          str = code_parts.shift();
        }
        else {
          str = remainder;
        }
    }

    return 'var buf = [];\n'
        + "with (locals) {\nbuf.push("
        + output
        + "'');\n}\nreturn buf.join('');";
};

/**
 * Compile the given `str` of ejs into a `Function`.
 *
 * @param {String} str
 * @param {Object} options
 * @return {Function}
 * @api public
 */

var compile = exports.compile = function(str, options){
    if (options.debug) sys.puts(parse(str));
    return function(locals){
        var fn = new Function('locals, escape', parse(str));
        return fn.call(this, locals, escape);
    }
};

/**
 * Render the given `str` of ejs.
 *
 * Options:
 *
 *   - `locals`          Local variables object
 *   - `cache`           Compiled functions are cached, requires `filename`
 *   - `filename`        Used by `cache` to key caches
 *   - `context|scope`   Function execution context
 *   - `debug`           Output generated function body
 *
 * @param {String} str
 * @param {Object} options
 * @return {String}
 * @api public
 */

exports.render = function(str, options){
    var fn,
        options = options || {};
    if (options.cache) {
        if (options.filename) {
            fn = cache[options.filename] = compile(str, options);
        } else {
            throw new Error('"cache" option requires "filename".');
        }
    } else {
        fn = compile(str, options);
    }
    return fn.call(options.context || options.scope, options.locals || {});
};
<commit_msg>Style fixes<commit_after>
/*!
 * EJS
 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var sys = require('sys');

/**
 * Library version.
 */

exports.version = '0.0.3';

/**
 * Intermediate js cache.
 *
 * @type Object
 */

var cache = {};

/**
 * Clear intermediate js cache.
 *
 * @api public
 */

exports.clearCache = function(){
    cache = {};
};

/**
 * Escape the given string of `html`.
 *
 * @param {String} html
 * @return {String}
 * @api private
 */

function escape(html){
    return String(html)
        .replace(/&(?!\w+;)/g, '&')
        .replace(/</g, '<')
        .replace(/>/g, '>')
        .replace(/"/g, '"');
}

/**
 * Parse the given `str` of ejs, returning the function body.
 *
 * @param {String} str
 * @return {String}
 * @api public
 */

var parse = exports.parse = function(str){
    var buf = '',
        str = String(str)
        .replace(/\r/g, " ")
        .replace(/\n/g, "\\n");

    while(str) {
        var parts = str.replace('<%', '\r').split('\r');
        var content = parts.shift(), remainder = parts.shift();

        if (content) {
            // escape single quotes
            content = content.replace(/(^|[^\\])'/g, "$1\\'");
            buf += '\'' + content + '\', ';
        }

        if (remainder) {
            var code_parts = remainder.replace('%>', '\r').split('\r');
            var code = code_parts.shift();
            // escaped output
            if(code.match(/^=/)) {
                buf += code.replace(/^=(.*)/, "escape($1), ");
            }
            // raw output
            else if (code.match(/^-/)) {
                buf +=  code.replace(/^-(.*)/, "$1, ");
            }
            // unbuffered output
            else {
                buf += "''); " + code + 'buf.push(';
            }
            str = code_parts.shift();
        } else {
            str = remainder;
        }
    }

    return 'var buf = [];\n'
        + "with (locals) {\nbuf.push("
        + buf
        + "'');\n}\nreturn buf.join('');";
};

/**
 * Compile the given `str` of ejs into a `Function`.
 *
 * @param {String} str
 * @param {Object} options
 * @return {Function}
 * @api public
 */

var compile = exports.compile = function(str, options){
    if (options.debug) sys.puts(parse(str));
    return function(locals){
        var fn = new Function('locals, escape', parse(str));
        return fn.call(this, locals, escape);
    }
};

/**
 * Render the given `str` of ejs.
 *
 * Options:
 *
 *   - `locals`          Local variables object
 *   - `cache`           Compiled functions are cached, requires `filename`
 *   - `filename`        Used by `cache` to key caches
 *   - `context|scope`   Function execution context
 *   - `debug`           Output generated function body
 *
 * @param {String} str
 * @param {Object} options
 * @return {String}
 * @api public
 */

exports.render = function(str, options){
    var fn,
        options = options || {};
    if (options.cache) {
        if (options.filename) {
            fn = cache[options.filename] = compile(str, options);
        } else {
            throw new Error('"cache" option requires "filename".');
        }
    } else {
        fn = compile(str, options);
    }
    return fn.call(options.context || options.scope, options.locals || {});
};
<|endoftext|>