<commit_before>const { Language, util } = require('klasa');

module.exports = class extends Language {

	constructor(...args) {
		super(...args);
		this.language = {
			DEFAULT: (key) => `${key} has not been localized for en-US yet.`,
			DEFAULT_LANGUAGE: 'Default Language',
			PREFIX_REMINDER: (prefix) => `The prefix${Array.isArray(prefix) ?
				`es for this guild are: ${prefix.map(pre => `\`${pre}\``).join(', ')}` :
				` in this guild is set to: \`${prefix}\``
			}`,
			SETTING_GATEWAY_EXPECTS_GUILD: 'The parameter <Guild> expects either a Guild or a Guild Object.',
			SETTING_GATEWAY_VALUE_FOR_KEY_NOEXT: (data, key) => `The value ${data} for the key ${key} does not exist.`,
			SETTING_GATEWAY_VALUE_FOR_KEY_ALREXT: (data, key) => `The value ${data} for the key ${key} already exists.`,
			SETTING_GATEWAY_SPECIFY_VALUE: 'You must specify the value to add or filter.',
			SETTING_GATEWAY_KEY_NOT_ARRAY: (key) => `The key ${key} is not an Array.`,
			SETTING_GATEWAY_KEY_NOEXT: (key) => `The key ${key} does not exist in the current data schema.`,
			SETTING_GATEWAY_INVALID_TYPE: 'The type parameter must be either add or remove.',
			RESOLVER_INVALID_CUSTOM: (name, type) => `${name} must be a valid ${type}.`,
			RESOLVER_INVALID_PIECE: (name, piece) => `${name} must be a valid ${piece} name.`,
			RESOLVER_INVALID_MESSAGE: (name) => `${name} must be a valid message id.`,
			RESOLVER_INVALID_USER: (name) => `${name} must be a mention or valid user id.`,
			RESOLVER_INVALID_MEMBER: (name) => `${name} must be a mention or valid user id.`,
			RESOLVER_INVALID_CHANNEL: (name) => `${name} must be a channel tag or valid channel id.`,
			RESOLVER_INVALID_EMOJI: (name) => `${name} must be a custom emoji tag or valid emoji id.`,
			RESOLVER_INVALID_GUILD: (name) => `${name} must be a valid guild id.`,
			RESOLVER_INVALID_ROLE: (name) => `${name} must be a role mention or role id.`,
			RESOLVER_INVALID_LITERAL: (name) => `Your option did not match the only possibility: ${name}`,
			RESOLVER_INVALID_BOOL: (name) => `${name} must be true or false.`,
			RESOLVER_INVALID_INT: (name) => `${name} must be an integer.`,
			RESOLVER_INVALID_FLOAT: (name) => `${name} must be a valid number.`,
			RESOLVER_INVALID_REGEX_MATCH: (name, pattern) => `${name} must follow this regex pattern \`${pattern}\`.`,
			RESOLVER_INVALID_URL: (name) => `${name} must be a valid url.`,
			RESOLVER_INVALID_DATE: (name) => `${name} must be a valid date.`,
			RESOLVER_INVALID_DURATION: (name) => `${name} must be a valid duration string.`,
			RESOLVER_INVALID_TIME: (name) => `${name} must be a valid duration or date string.`,
			RESOLVER_STRING_SUFFIX: ' characters',
			RESOLVER_MINMAX_EXACTLY: (name, min, suffix) => `${name} must be exactly ${min}${suffix}.`,
			RESOLVER_MINMAX_BOTH: (name, min, max, suffix) => `${name} must be between ${min} and ${max}${suffix}.`,
			RESOLVER_MINMAX_MIN: (name, min, suffix) => `${name} must be greater than ${min}${suffix}.`,
			RESOLVER_MINMAX_MAX: (name, max, suffix) => `${name} must be less than ${max}${suffix}.`,
			REACTIONHANDLER_PROMPT: 'Which page would you like to jump to?',
			COMMANDMESSAGE_MISSING: 'Missing one or more required arguments after end of input.',
			COMMANDMESSAGE_MISSING_REQUIRED: (name) => `${name} is a required argument.`,
			COMMANDMESSAGE_MISSING_OPTIONALS: (possibles) => `Missing a required option: (${possibles})`,
			COMMANDMESSAGE_NOMATCH: (possibles) => `Your option didn't match any of the possibilities: (${possibles})`,
			MONITOR_COMMAND_HANDLER_REPROMPT: (tag, error, time) => `${tag} | **${error}** | You have **${time}** seconds to respond to this prompt with a valid argument. Type **"ABORT"** to abort this prompt.`, // eslint-disable-line max-len
			MONITOR_COMMAND_HANDLER_REPEATING_REPROMPT: (tag, name, time) => `${tag} | **${name}** is a repeating argument | You have **${time}** seconds to respond to this prompt with additional valid arguments. Type **"CANCEL"** to cancel this prompt.`, // eslint-disable-line max-len
			MONITOR_COMMAND_HANDLER_ABORTED: 'Aborted',
			INHIBITOR_COOLDOWN: (remaining) => `You have just used this command. You can use this command again in ${remaining} second${remaining === 1 ? '' : 's'}.`,
			INHIBITOR_DISABLED: 'This command is currently disabled',
			INHIBITOR_MISSING_BOT_PERMS: (missing) => `Insufficient permissions, missing: **${missing}**`,
			INHIBITOR_NSFW: 'You may not use NSFW commands in this channel.',
			INHIBITOR_PERMISSIONS: 'You do not have permission to use this command',
			INHIBITOR_REQUIRED_CONFIGS: (configs) => `The guild is missing the **${configs.join(', ')}** guild setting${configs.length !== 1 ? 's' : ''} and thus the command cannot run.`,
			INHIBITOR_RUNIN: (types) => `This command is only available in ${types} channels`,
			INHIBITOR_RUNIN_NONE: (name) => `The ${name} command is not configured to run in any channel.`,
			COMMAND_BLACKLIST_DESCRIPTION: 'Blacklists or un-blacklists users and guilds from the bot.',
			COMMAND_BLACKLIST_SUCCESS: (usersAdded, usersRemoved, guildsAdded, guildsRemoved) => [
				usersAdded.length ? `**Users Added**\n${util.codeBlock('', usersAdded.join(', '))}` : '',
				usersRemoved.length ? `**Users Removed**\n${util.codeBlock('', usersRemoved.join(', '))}` : '',
				guildsAdded.length ? `**Guilds Added**\n${util.codeBlock('', guildsAdded.join(', '))}` : '',
				guildsRemoved.length ? `**Guilds Removed**\n${util.codeBlock('', guildsRemoved.join(', '))}` : ''
			].filter(val => val !== '').join('\n'),
			COMMAND_EVAL_DESCRIPTION: 'Evaluates arbitrary Javascript. Reserved for bot owner.',
			COMMAND_EVAL_EXTENDEDHELP: [
				'The eval command evaluates code as-in, any error thrown from it will be handled.',
				'It also uses the flags feature. Write --silent, --depth=number or --async to customize the output.',
				'The --silent flag will make it output nothing.',
				"The --depth flag accepts a number, for example, --depth=2, to customize util.inspect's depth.",
				'The --async flag will wrap the code into an async function where you can enjoy the use of await, however, if you want to return something, you will need the return keyword',
				'The --showHidden flag will enable the showHidden option in util.inspect.',
				'If the output is too large, it\'ll send the output as a file, or in the console if the bot does not have the ATTACH_FILES permission.'
			].join('\n'),
			COMMAND_EVAL_ERROR: (time, output, type) => `**Error**:${output}\n**Type**:${type}\n${time}`,
			COMMAND_EVAL_OUTPUT: (time, output, type) => `**Output**:${output}\n**Type**:${type}\n${time}`,
			COMMAND_EVAL_SENDFILE: (time, type) => `Output was too long... sent the result as a file.\n**Type**:${type}\n${time}`,
			COMMAND_EVAL_SENDCONSOLE: (time, type) => `Output was too long... sent the result to console.\n**Type**:${type}\n${time}`,
			COMMAND_UNLOAD: (type, name) => `✅ Unloaded ${type}: ${name}`,
			COMMAND_UNLOAD_DESCRIPTION: 'Unloads the klasa piece.',
			COMMAND_UNLOAD_WARN: 'You probably don\'t want to unload that, since you wouldn\'t be able to run any command to enable it again',
			COMMAND_TRANSFER_ERROR: '❌ That file has been transfered already or never existed.',
			COMMAND_TRANSFER_SUCCESS: (type, name) => `✅ Successfully transferred ${type}: ${name}`,
			COMMAND_TRANSFER_FAILED: (type, name) => `Transfer of ${type}: ${name} to Client has failed. Please check your Console.`,
			COMMAND_TRANSFER_DESCRIPTION: 'Transfers a core piece to its respective folder',
			COMMAND_RELOAD: (type, name) => `✅ Reloaded ${type}: ${name}`,
			COMMAND_RELOAD_ALL: (type) => `✅ Reloaded all ${type}.`,
			COMMAND_RELOAD_DESCRIPTION: 'Reloads a klasa piece, or all pieces of a klasa store.',
			COMMAND_REBOOT: 'Rebooting...',
			COMMAND_REBOOT_DESCRIPTION: 'Reboots the bot.',
			COMMAND_LOAD: (time, type, name) => `✅ Successfully loaded ${type}: ${name}. (Took: ${time})`,
			COMMAND_LOAD_FAIL: 'The file does not exist, or an error occurred while loading your file. Please check your console.',
			COMMAND_LOAD_ERROR: (type, name, error) => `❌ Failed to load ${type}: ${name}. Reason:${util.codeBlock('js', error)}`,
			COMMAND_LOAD_DESCRIPTION: 'Load a piece from your bot.',
			COMMAND_PING: 'Ping?',
			COMMAND_PING_DESCRIPTION: 'Runs a connection test to Discord.',
			COMMAND_PINGPONG: (diff, ping) => `Pong! (Roundtrip took: ${diff}ms. Heartbeat: ${ping}ms.)`,
			COMMAND_INVITE_SELFBOT: 'Why would you need an invite link for a selfbot...',
			COMMAND_INVITE: (client) => [
				`To add ${client.user.username} to your discord guild:`,
				client.invite,
				util.codeBlock('', [
					'The above link is generated requesting the minimum permissions required to use every command currently.',
					'I know not all permissions are right for every server, so don\'t be afraid to uncheck any of the boxes.',
					'If you try to use a command that requires more permissions than the bot is granted, it will let you know.'
				].join(' ')),
				'Please file an issue at <https://github.com/dirigeants/klasa> if you find any bugs.'
			],
			COMMAND_INVITE_DESCRIPTION: 'Displays the join server link of the bot.',
			COMMAND_INFO: [
				"Klasa is a 'plug-and-play' framework built on top of the Discord.js library.",
				'Most of the code is modularized, which allows developers to edit Klasa to suit their needs.',
				'',
				'Some features of Klasa include:',
				'• 🐇💨 Fast loading times with ES2017 support (`async`/`await`)',
				'• 🎚🎛 Per-client/server/user settings that can be extended with your own fields',
				'• 💬 Customizable command system with automated parameter resolving and the ability to load/reload commands on-the-fly',
				'• 👀 "Monitors", which can watch messages and edits (for swear filters, spam protection, etc.)',
				'• ⛔ "Inhibitors", which can prevent commands from running based on any condition you wish to apply (for permissions, blacklists, etc.)',
				'• 🗄 "Providers", which simplify usage of any database of your choosing',
				'• ✅ "Finalizers", which run after successful commands (for logging, collecting stats, cleaning up responses, etc.)',
				'• ➕ "Extendables", which passively add methods, getters/setters, or static properties to existing Discord.js or Klasa classes',
				'• 🌐 "Languages", which allow you to localize your bot\'s responses',
				'• ⏲ "Tasks", which can be scheduled to run in the future, optionally repeating',
				'',
				'We hope to be a 100% customizable framework that can cater to all audiences. We do frequent updates and bugfixes when available.',
				"If you're interested in us, check us out at https://klasa.js.org"
			],
			COMMAND_INFO_DESCRIPTION: 'Provides some information about this bot.',
			COMMAND_HELP_DESCRIPTION: 'Display help for a command.',
			COMMAND_HELP_NO_EXTENDED: 'No extended help available.',
			COMMAND_HELP_DM: '📥 | The list of commands you have access to has been sent to your DMs.',
			COMMAND_HELP_NODM: '❌ | You have DMs disabled, I couldn\'t send you the commands in DMs.',
			COMMAND_HELP_USAGE: (usage) => `usage :: ${usage}`,
			COMMAND_HELP_EXTENDED: 'Extended Help ::',
			COMMAND_ENABLE: (type, name) => `+ Successfully enabled ${type}: ${name}`,
			COMMAND_ENABLE_DESCRIPTION: 'Re-enables or temporarily enables a command/inhibitor/monitor/finalizer. Default state restored on reboot.',
			COMMAND_DISABLE: (type, name) => `+ Successfully disabled ${type}: ${name}`,
			COMMAND_DISABLE_DESCRIPTION: 'Re-disables or temporarily disables a command/inhibitor/monitor/finalizer/event. Default state restored on reboot.',
			COMMAND_DISABLE_WARN: 'You probably don\'t want to disable that, since you wouldn\'t be able to run any command to enable it again',
			COMMAND_CONF_NOKEY: 'You must provide a key',
			COMMAND_CONF_NOVALUE: 'You must provide a value',
			COMMAND_CONF_GUARDED: (name) => `${util.toTitleCase(name)} may not be disabled.`,
			COMMAND_CONF_UPDATED: (key, response) => `Successfully updated the key **${key}**: \`${response}\``,
			COMMAND_CONF_KEY_NOT_ARRAY: 'This key is not array type. Use the action \'reset\' instead.',
			COMMAND_CONF_GET_NOEXT: (key) => `The key **${key}** does not seem to exist.`,
			COMMAND_CONF_GET: (key, value) => `The value for the key **${key}** is: \`${value}\``,
			COMMAND_CONF_RESET: (key, response) => `The key **${key}** has been reset to: \`${response}\``,
			COMMAND_CONF_NOCHANGE: (key) => `The value for **${key}** was already that value.`,
			COMMAND_CONF_SERVER_DESCRIPTION: 'Define per-server configuration.',
			COMMAND_CONF_SERVER: (key, list) => `**Server Configuration${key}**\n${list}`,
			COMMAND_CONF_USER_DESCRIPTION: 'Define per-user configuration.',
			COMMAND_CONF_USER: (key, list) => `**User Configuration${key}**\n${list}`,
			COMMAND_STATS: (memUsage, uptime, users, servers, channels, klasaVersion, discordVersion, processVersion, message) => [
				'= STATISTICS =',
				'',
				`• Mem Usage  :: ${memUsage} MB`,
				`• Uptime     :: ${uptime}`,
				`• Users      :: ${users}`,
				`• Servers    :: ${servers}`,
				`• Channels   :: ${channels}`,
				`• Klasa      :: v${klasaVersion}`,
				`• Discord.js :: v${discordVersion}`,
				`• Node.js    :: ${processVersion}`,
				this.client.options.shardCount ?
					`• Shard      :: ${((message.guild ? message.guild.shardID : message.channel.shardID) || this.client.options.shardId) + 1} / ${this.client.options.shardCount}` :
					''
			],
			COMMAND_STATS_DESCRIPTION: 'Provides some details about the bot and stats.',
			MESSAGE_PROMPT_TIMEOUT: 'The prompt has timed out.'
		};
	}

	async init() {
		await super.init();
	}

};
<commit_msg>Consistancy (#360)<commit_after>const { Language, util } = require('klasa');

module.exports = class extends Language {

	constructor(...args) {
		super(...args);
		this.language = {
			DEFAULT: (key) => `${key} has not been localized for en-US yet.`,
			DEFAULT_LANGUAGE: 'Default Language',
			PREFIX_REMINDER: (prefix) => `The prefix${Array.isArray(prefix) ?
				`es for this guild are: ${prefix.map(pre => `\`${pre}\``).join(', ')}` :
				` in this guild is set to: \`${prefix}\``
			}`,
			SETTING_GATEWAY_EXPECTS_GUILD: 'The parameter <Guild> expects either a Guild or a Guild Object.',
			SETTING_GATEWAY_VALUE_FOR_KEY_NOEXT: (data, key) => `The value ${data} for the key ${key} does not exist.`,
			SETTING_GATEWAY_VALUE_FOR_KEY_ALREXT: (data, key) => `The value ${data} for the key ${key} already exists.`,
			SETTING_GATEWAY_SPECIFY_VALUE: 'You must specify the value to add or filter.',
			SETTING_GATEWAY_KEY_NOT_ARRAY: (key) => `The key ${key} is not an Array.`,
			SETTING_GATEWAY_KEY_NOEXT: (key) => `The key ${key} does not exist in the current data schema.`,
			SETTING_GATEWAY_INVALID_TYPE: 'The type parameter must be either add or remove.',
			RESOLVER_INVALID_CUSTOM: (name, type) => `${name} must be a valid ${type}.`,
			RESOLVER_INVALID_PIECE: (name, piece) => `${name} must be a valid ${piece} name.`,
			RESOLVER_INVALID_MESSAGE: (name) => `${name} must be a valid message id.`,
			RESOLVER_INVALID_USER: (name) => `${name} must be a mention or valid user id.`,
			RESOLVER_INVALID_MEMBER: (name) => `${name} must be a mention or valid user id.`,
			RESOLVER_INVALID_CHANNEL: (name) => `${name} must be a channel tag or valid channel id.`,
			RESOLVER_INVALID_EMOJI: (name) => `${name} must be a custom emoji tag or valid emoji id.`,
			RESOLVER_INVALID_GUILD: (name) => `${name} must be a valid guild id.`,
			RESOLVER_INVALID_ROLE: (name) => `${name} must be a role mention or role id.`,
			RESOLVER_INVALID_LITERAL: (name) => `Your option did not match the only possibility: ${name}`,
			RESOLVER_INVALID_BOOL: (name) => `${name} must be true or false.`,
			RESOLVER_INVALID_INT: (name) => `${name} must be an integer.`,
			RESOLVER_INVALID_FLOAT: (name) => `${name} must be a valid number.`,
			RESOLVER_INVALID_REGEX_MATCH: (name, pattern) => `${name} must follow this regex pattern \`${pattern}\`.`,
			RESOLVER_INVALID_URL: (name) => `${name} must be a valid url.`,
			RESOLVER_INVALID_DATE: (name) => `${name} must be a valid date.`,
			RESOLVER_INVALID_DURATION: (name) => `${name} must be a valid duration string.`,
			RESOLVER_INVALID_TIME: (name) => `${name} must be a valid duration or date string.`,
			RESOLVER_STRING_SUFFIX: ' characters',
			RESOLVER_MINMAX_EXACTLY: (name, min, suffix) => `${name} must be exactly ${min}${suffix}.`,
			RESOLVER_MINMAX_BOTH: (name, min, max, suffix) => `${name} must be between ${min} and ${max}${suffix}.`,
			RESOLVER_MINMAX_MIN: (name, min, suffix) => `${name} must be greater than ${min}${suffix}.`,
			RESOLVER_MINMAX_MAX: (name, max, suffix) => `${name} must be less than ${max}${suffix}.`,
			REACTIONHANDLER_PROMPT: 'Which page would you like to jump to?',
			COMMANDMESSAGE_MISSING: 'Missing one or more required arguments after end of input.',
			COMMANDMESSAGE_MISSING_REQUIRED: (name) => `${name} is a required argument.`,
			COMMANDMESSAGE_MISSING_OPTIONALS: (possibles) => `Missing a required option: (${possibles})`,
			COMMANDMESSAGE_NOMATCH: (possibles) => `Your option didn't match any of the possibilities: (${possibles})`,
			MONITOR_COMMAND_HANDLER_REPROMPT: (tag, error, time) => `${tag} | **${error}** | You have **${time}** seconds to respond to this prompt with a valid argument. Type **"ABORT"** to abort this prompt.`, // eslint-disable-line max-len
			MONITOR_COMMAND_HANDLER_REPEATING_REPROMPT: (tag, name, time) => `${tag} | **${name}** is a repeating argument | You have **${time}** seconds to respond to this prompt with additional valid arguments. Type **"CANCEL"** to cancel this prompt.`, // eslint-disable-line max-len
			MONITOR_COMMAND_HANDLER_ABORTED: 'Aborted',
			INHIBITOR_COOLDOWN: (remaining) => `You have just used this command. You can use this command again in ${remaining} second${remaining === 1 ? '' : 's'}.`,
			INHIBITOR_DISABLED: 'This command is currently disabled',
			INHIBITOR_MISSING_BOT_PERMS: (missing) => `Insufficient permissions, missing: **${missing}**`,
			INHIBITOR_NSFW: 'You may not use NSFW commands in this channel.',
			INHIBITOR_PERMISSIONS: 'You do not have permission to use this command',
			INHIBITOR_REQUIRED_CONFIGS: (configs) => `The guild is missing the **${configs.join(', ')}** guild setting${configs.length !== 1 ? 's' : ''} and thus the command cannot run.`,
			INHIBITOR_RUNIN: (types) => `This command is only available in ${types} channels`,
			INHIBITOR_RUNIN_NONE: (name) => `The ${name} command is not configured to run in any channel.`,
			COMMAND_BLACKLIST_DESCRIPTION: 'Blacklists or un-blacklists users and guilds from the bot.',
			COMMAND_BLACKLIST_SUCCESS: (usersAdded, usersRemoved, guildsAdded, guildsRemoved) => [
				usersAdded.length ? `**Users Added**\n${util.codeBlock('', usersAdded.join(', '))}` : '',
				usersRemoved.length ? `**Users Removed**\n${util.codeBlock('', usersRemoved.join(', '))}` : '',
				guildsAdded.length ? `**Guilds Added**\n${util.codeBlock('', guildsAdded.join(', '))}` : '',
				guildsRemoved.length ? `**Guilds Removed**\n${util.codeBlock('', guildsRemoved.join(', '))}` : ''
			].filter(val => val !== '').join('\n'),
			COMMAND_EVAL_DESCRIPTION: 'Evaluates arbitrary Javascript. Reserved for bot owner.',
			COMMAND_EVAL_EXTENDEDHELP: [
				'The eval command evaluates code as-in, any error thrown from it will be handled.',
				'It also uses the flags feature. Write --silent, --depth=number or --async to customize the output.',
				'The --silent flag will make it output nothing.',
				"The --depth flag accepts a number, for example, --depth=2, to customize util.inspect's depth.",
				'The --async flag will wrap the code into an async function where you can enjoy the use of await, however, if you want to return something, you will need the return keyword',
				'The --showHidden flag will enable the showHidden option in util.inspect.',
				'If the output is too large, it\'ll send the output as a file, or in the console if the bot does not have the ATTACH_FILES permission.'
			].join('\n'),
			COMMAND_EVAL_ERROR: (time, output, type) => `**Error**:${output}\n**Type**:${type}\n${time}`,
			COMMAND_EVAL_OUTPUT: (time, output, type) => `**Output**:${output}\n**Type**:${type}\n${time}`,
			COMMAND_EVAL_SENDFILE: (time, type) => `Output was too long... sent the result as a file.\n**Type**:${type}\n${time}`,
			COMMAND_EVAL_SENDCONSOLE: (time, type) => `Output was too long... sent the result to console.\n**Type**:${type}\n${time}`,
			COMMAND_UNLOAD: (type, name) => `✅ Unloaded ${type}: ${name}`,
			COMMAND_UNLOAD_DESCRIPTION: 'Unloads the klasa piece.',
			COMMAND_UNLOAD_WARN: 'You probably don\'t want to unload that, since you wouldn\'t be able to run any command to enable it again',
			COMMAND_TRANSFER_ERROR: '❌ That file has been transfered already or never existed.',
			COMMAND_TRANSFER_SUCCESS: (type, name) => `✅ Successfully transferred ${type}: ${name}`,
			COMMAND_TRANSFER_FAILED: (type, name) => `Transfer of ${type}: ${name} to Client has failed. Please check your Console.`,
			COMMAND_TRANSFER_DESCRIPTION: 'Transfers a core piece to its respective folder',
			COMMAND_RELOAD: (type, name) => `✅ Reloaded ${type}: ${name}`,
			COMMAND_RELOAD_ALL: (type) => `✅ Reloaded all ${type}.`,
			COMMAND_RELOAD_DESCRIPTION: 'Reloads a klasa piece, or all pieces of a klasa store.',
			COMMAND_REBOOT: 'Rebooting...',
			COMMAND_REBOOT_DESCRIPTION: 'Reboots the bot.',
			COMMAND_LOAD: (time, type, name) => `✅ Successfully loaded ${type}: ${name}. (Took: ${time})`,
			COMMAND_LOAD_FAIL: 'The file does not exist, or an error occurred while loading your file. Please check your console.',
			COMMAND_LOAD_ERROR: (type, name, error) => `❌ Failed to load ${type}: ${name}. Reason:${util.codeBlock('js', error)}`,
			COMMAND_LOAD_DESCRIPTION: 'Load a piece from your bot.',
			COMMAND_PING: 'Ping?',
			COMMAND_PING_DESCRIPTION: 'Runs a connection test to Discord.',
			COMMAND_PINGPONG: (diff, ping) => `Pong! (Roundtrip took: ${diff}ms. Heartbeat: ${ping}ms.)`,
			COMMAND_INVITE_SELFBOT: 'Why would you need an invite link for a selfbot...',
			COMMAND_INVITE: (client) => [
				`To add ${client.user.username} to your discord guild:`,
				client.invite,
				util.codeBlock('', [
					'The above link is generated requesting the minimum permissions required to use every command currently.',
					'I know not all permissions are right for every guild, so don\'t be afraid to uncheck any of the boxes.',
					'If you try to use a command that requires more permissions than the bot is granted, it will let you know.'
				].join(' ')),
				'Please file an issue at <https://github.com/dirigeants/klasa> if you find any bugs.'
			],
			COMMAND_INVITE_DESCRIPTION: 'Displays the join guild link of the bot.',
			COMMAND_INFO: [
				"Klasa is a 'plug-and-play' framework built on top of the Discord.js library.",
				'Most of the code is modularized, which allows developers to edit Klasa to suit their needs.',
				'',
				'Some features of Klasa include:',
				'• 🐇💨 Fast loading times with ES2017 support (`async`/`await`)',
				'• 🎚🎛 Per-client/guild/user settings that can be extended with your own fields',
				'• 💬 Customizable command system with automated parameter resolving and the ability to load/reload commands on-the-fly',
				'• 👀 "Monitors", which can watch messages and edits (for swear filters, spam protection, etc.)',
				'• ⛔ "Inhibitors", which can prevent commands from running based on any condition you wish to apply (for permissions, blacklists, etc.)',
				'• 🗄 "Providers", which simplify usage of any database of your choosing',
				'• ✅ "Finalizers", which run after successful commands (for logging, collecting stats, cleaning up responses, etc.)',
				'• ➕ "Extendables", which passively add methods, getters/setters, or static properties to existing Discord.js or Klasa classes',
				'• 🌐 "Languages", which allow you to localize your bot\'s responses',
				'• ⏲ "Tasks", which can be scheduled to run in the future, optionally repeating',
				'',
				'We hope to be a 100% customizable framework that can cater to all audiences. We do frequent updates and bugfixes when available.',
				"If you're interested in us, check us out at https://klasa.js.org"
			],
			COMMAND_INFO_DESCRIPTION: 'Provides some information about this bot.',
			COMMAND_HELP_DESCRIPTION: 'Display help for a command.',
			COMMAND_HELP_NO_EXTENDED: 'No extended help available.',
			COMMAND_HELP_DM: '📥 | The list of commands you have access to has been sent to your DMs.',
			COMMAND_HELP_NODM: '❌ | You have DMs disabled, I couldn\'t send you the commands in DMs.',
			COMMAND_HELP_USAGE: (usage) => `usage :: ${usage}`,
			COMMAND_HELP_EXTENDED: 'Extended Help ::',
			COMMAND_ENABLE: (type, name) => `+ Successfully enabled ${type}: ${name}`,
			COMMAND_ENABLE_DESCRIPTION: 'Re-enables or temporarily enables a command/inhibitor/monitor/finalizer. Default state restored on reboot.',
			COMMAND_DISABLE: (type, name) => `+ Successfully disabled ${type}: ${name}`,
			COMMAND_DISABLE_DESCRIPTION: 'Re-disables or temporarily disables a command/inhibitor/monitor/finalizer/event. Default state restored on reboot.',
			COMMAND_DISABLE_WARN: 'You probably don\'t want to disable that, since you wouldn\'t be able to run any command to enable it again',
			COMMAND_CONF_NOKEY: 'You must provide a key',
			COMMAND_CONF_NOVALUE: 'You must provide a value',
			COMMAND_CONF_GUARDED: (name) => `${util.toTitleCase(name)} may not be disabled.`,
			COMMAND_CONF_UPDATED: (key, response) => `Successfully updated the key **${key}**: \`${response}\``,
			COMMAND_CONF_KEY_NOT_ARRAY: 'This key is not array type. Use the action \'reset\' instead.',
			COMMAND_CONF_GET_NOEXT: (key) => `The key **${key}** does not seem to exist.`,
			COMMAND_CONF_GET: (key, value) => `The value for the key **${key}** is: \`${value}\``,
			COMMAND_CONF_RESET: (key, response) => `The key **${key}** has been reset to: \`${response}\``,
			COMMAND_CONF_NOCHANGE: (key) => `The value for **${key}** was already that value.`,
			COMMAND_CONF_SERVER_DESCRIPTION: 'Define per-guild configuration.',
			COMMAND_CONF_SERVER: (key, list) => `**Guild Configuration${key}**\n${list}`,
			COMMAND_CONF_USER_DESCRIPTION: 'Define per-user configuration.',
			COMMAND_CONF_USER: (key, list) => `**User Configuration${key}**\n${list}`,
			COMMAND_STATS: (memUsage, uptime, users, guilds, channels, klasaVersion, discordVersion, processVersion, message) => [
				'= STATISTICS =',
				'',
				`• Mem Usage  :: ${memUsage} MB`,
				`• Uptime     :: ${uptime}`,
				`• Users      :: ${users}`,
				`• Guilds    :: ${guilds}`,
				`• Channels   :: ${channels}`,
				`• Klasa      :: v${klasaVersion}`,
				`• Discord.js :: v${discordVersion}`,
				`• Node.js    :: ${processVersion}`,
				this.client.options.shardCount ?
					`• Shard      :: ${((message.guild ? message.guild.shardID : message.channel.shardID) || this.client.options.shardId) + 1} / ${this.client.options.shardCount}` :
					''
			],
			COMMAND_STATS_DESCRIPTION: 'Provides some details about the bot and stats.',
			MESSAGE_PROMPT_TIMEOUT: 'The prompt has timed out.'
		};
	}

	async init() {
		await super.init();
	}

};
<|endoftext|>


<commit_before>/*
Language: Nginx
Author: Peter Leonov <gojpeg@yandex.ru>
Contributors: Ivan Sagalaev <maniac@softwaremaniacs.org>
*/

function(hljs) {
  var VARS = [
    {
      className: 'variable', begin: '\\$\\d+'
    },
    {
      className: 'variable', begin: '\\${', end: '}'
    },
    {
      className: 'variable', begin: '[\\$\\@]' + hljs.UNDERSCORE_IDENT_RE
    }
  ];
  var DEFAULT = {
    endsWithParent: true,
    lexems: '[a-z/_]+',
    keywords: {
      built_in:
        'on off yes no true false none blocked debug info notice warn error crit ' +
        'select break last permanent redirect kqueue rtsig epoll poll /dev/poll'
    },
    relevance: 0,
    illegal: '=>',
    contains: [
      hljs.HASH_COMMENT_MODE,
      {
        className: 'string',
        begin: '"', end: '"',
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS),
        relevance: 0
      },
      {
        className: 'string',
        begin: "'", end: "'",
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS),
        relevance: 0
      },
      {
        className: 'url',
        begin: '([a-z]+):/', end: '\\s', endsWithParent: true, excludeEnd: true
      },
      {
        className: 'regexp',
        begin: "\\s\\^", end: "\\s|{|;", returnEnd: true,
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS)
      },
      // regexp locations (~, ~*)
      {
        className: 'regexp',
        begin: "~\\*?\\s+", end: "\\s|{|;", returnEnd: true,
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS)
      },
      // *.example.com
      {
        className: 'regexp',
        begin: "\\*(\\.[a-z\\-]+)+",
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS)
      },
      // sub.example.*
      {
        className: 'regexp',
        begin: "([a-z\\-]+\\.)+\\*",
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS)
      },
      // IP
      {
        className: 'number',
        begin: '\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b'
      },
      // units
      {
        className: 'number',
        begin: '\\b\\d+[kKmMgGdshdwy]*\\b',
        relevance: 0
      }
    ].concat(VARS)
  };

  return {
    contains: [
      hljs.HASH_COMMENT_MODE,
      {
        begin: hljs.UNDERSCORE_IDENT_RE + '\\s', end: ';|{', returnBegin: true,
        contains: [
          {
            className: 'title',
            begin: hljs.UNDERSCORE_IDENT_RE,
            starts: DEFAULT
          }
        ]
      }
    ],
    illegal: '[^\\s\\}]'
  };
}
<commit_msg>Don't count relevance of nginx titles twice.<commit_after>/*
Language: Nginx
Author: Peter Leonov <gojpeg@yandex.ru>
Contributors: Ivan Sagalaev <maniac@softwaremaniacs.org>
*/

function(hljs) {
  var VARS = [
    {
      className: 'variable', begin: '\\$\\d+'
    },
    {
      className: 'variable', begin: '\\${', end: '}'
    },
    {
      className: 'variable', begin: '[\\$\\@]' + hljs.UNDERSCORE_IDENT_RE
    }
  ];
  var DEFAULT = {
    endsWithParent: true,
    lexems: '[a-z/_]+',
    keywords: {
      built_in:
        'on off yes no true false none blocked debug info notice warn error crit ' +
        'select break last permanent redirect kqueue rtsig epoll poll /dev/poll'
    },
    relevance: 0,
    illegal: '=>',
    contains: [
      hljs.HASH_COMMENT_MODE,
      {
        className: 'string',
        begin: '"', end: '"',
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS),
        relevance: 0
      },
      {
        className: 'string',
        begin: "'", end: "'",
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS),
        relevance: 0
      },
      {
        className: 'url',
        begin: '([a-z]+):/', end: '\\s', endsWithParent: true, excludeEnd: true
      },
      {
        className: 'regexp',
        begin: "\\s\\^", end: "\\s|{|;", returnEnd: true,
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS)
      },
      // regexp locations (~, ~*)
      {
        className: 'regexp',
        begin: "~\\*?\\s+", end: "\\s|{|;", returnEnd: true,
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS)
      },
      // *.example.com
      {
        className: 'regexp',
        begin: "\\*(\\.[a-z\\-]+)+",
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS)
      },
      // sub.example.*
      {
        className: 'regexp',
        begin: "([a-z\\-]+\\.)+\\*",
        contains: [hljs.BACKSLASH_ESCAPE].concat(VARS)
      },
      // IP
      {
        className: 'number',
        begin: '\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b'
      },
      // units
      {
        className: 'number',
        begin: '\\b\\d+[kKmMgGdshdwy]*\\b',
        relevance: 0
      }
    ].concat(VARS)
  };

  return {
    contains: [
      hljs.HASH_COMMENT_MODE,
      {
        begin: hljs.UNDERSCORE_IDENT_RE + '\\s', end: ';|{', returnBegin: true,
        contains: [
          {
            className: 'title',
            begin: hljs.UNDERSCORE_IDENT_RE,
            starts: DEFAULT
          }
        ],
        relevance: 0
      }
    ],
    illegal: '[^\\s\\}]'
  };
}
<|endoftext|>


<commit_before>"use strict";

var katex = require('katex');

export function LaTeXTransform(mimetype, latex, document) {
    var el = document.createElement('div');
    if (typeof MathJaX !== "undefined") {
        el.textContent = latex;
        MathJax.Hub.Queue(["Typeset", MathJax.Hub, node]);
    } else {
        el.innerHTML = katex.renderToString(latex);
    }
    return el;
}

LaTeXTransform.mimetype = 'text/latex';
<commit_msg>Fix mathjax call<commit_after>"use strict";

var katex = require('katex');

export function LaTeXTransform(mimetype, latex, document) {
    var el = document.createElement('div');
    if (typeof MathJaX !== "undefined") {
        el.textContent = latex;
        MathJax.Hub.Queue(["Typeset", MathJax.Hub, el]);
    } else {
        el.innerHTML = katex.renderToString(latex);
    }
    return el;
}

LaTeXTransform.mimetype = 'text/latex';
<|endoftext|>


<commit_before>/*
 * The algorithms here are based on Brandes and Köpf, "Fast and Simple
 * Horizontal Coordinate Assignment".
 */
dagre.layout.position = (function() {
  function actualNodeWidth(u) {
    var uAttrs = u.attrs;
    return uAttrs.width + uAttrs.marginX * 2 + uAttrs.strokeWidth;
  }

  function actualNodeHeight(u) {
    var uAttrs = u.attrs;
    return uAttrs.height + uAttrs.marginY * 2 + uAttrs.strokeWidth;
  }

  function markType1Conflicts(layering) {
    var pos = {};
    layering[0].forEach(function(u, i) {
      pos[u.id()] = i;
    });

    for (var i = 1; i < layering.length; ++i) {
      var layer = layering[i];

      // Position of last inner segment in the previous layer
      var innerLeft = 0;
      var currIdx = 0;

      // Scan current layer for next node with an inner segment.
      for (var j = 0; j < layer.length; ++j) {
        var u = layer[j];
        // Update positions map for next layer iteration
        pos[u.id()] = j;

        // Search for the next inner segment in the previous layer
        var innerRight = null;
        u.predecessors().forEach(function(v) {
          // TODO could abort as soon as we find a dummy
          if (u.attrs.dummy || v.attrs.dummy) {
            innerRight = pos[v.id()];
          }
        });

        // If no inner segment but at the end of the list we still
        // need to check for type 1 conflicts with earlier segments
        if (innerRight === null && j === layer.length - 1) {
          innerRight = layer.length;
        }

        if (innerRight !== null) {
          for (;currIdx <= j; ++currIdx) {
            var v = layer[currIdx];
            v.inEdges().forEach(function(e) {
              var tailPos = pos[e.tail().id()];
              if (tailPos < innerLeft || tailPos > innerRight) {
                e.attrs.type1Conflict = true;
              }
            });
          }
          innerLeft = innerRight;
        }
      }
    }
  }

  function verticalAlignment(layering, relationship) {
    var pos = {};
    var root = {};
    var align = {};

    layering.forEach(function(layer) {
      layer.forEach(function(u, i) {
        root[u.id()] = u;
        align[u.id()] = u;
        pos[u.id()] = i;
      });
    });

    layering.forEach(function(layer) {
      var prevIdx = -1;
      layer.forEach(function(v) {
        var related = v[relationship]();
        if (related.length > 0) {
          // TODO could find medians with linear algorithm if performance warrants it.
          related.sort(function(x, y) { return pos[x] - pos[y]; });
          var mid = (related.length - 1) / 2;
          related.slice(Math.floor(mid), Math.ceil(mid) + 1).forEach(function(u) {
            if (align[v.id()].id() === v.id()) {
              // TODO should we collapse multi-edges for vertical alignment?

              // Only need to check first returned edge for a type 1 conflict
              if (!u.edges(v)[0].attrs.type1Conflict && prevIdx < pos[u.id()]) {
                align[u.id()] = v;
                align[v.id()] = root[v.id()] = root[u.id()];
                prevIdx = pos[u.id()];
              }
            }
          });
        }
      });
    });

    return { pos: pos, root: root, align: align };
  }

  /*
   * Determines how much spacing u needs from its origin (center) to satisfy
   * width, margin, stroke, and node separation.
   */
  function deltaX(u, nodeSep, edgeSep) {
    var sep = u.attrs.dummy ? edgeSep : nodeSep;
    return actualNodeWidth(u) / 2 + sep / 2;
  }

  function horizontalCompaction(layering, pos, root, align, nodeSep, edgeSep) {
    // Mapping of node id -> sink node id for class
    var sink = {};

    // Mapping of sink node id -> x delta
    var shift = {};

    // Mapping of node id -> predecessor node id (or null)
    var pred = {};

    // Calculated X positions
    var xs = {};

    layering.forEach(function(layer) {
      layer.forEach(function(u, i) {
        sink[u.id()] = u;
        shift[u.id()] = Number.POSITIVE_INFINITY;
        pred[u.id()] = i > 0 ? layer[i - 1].id() : null;
      });
    });

    function placeBlock(v) {
      var vId = v.id();
      if (xs[vId] === undefined) {
        xs[vId] = 0;
        var wId = vId;
        do {
          if (pos[wId] > 0) {
            var u = root[pred[wId]];
            placeBlock(u);
            if (sink[vId].id() === vId) {
              sink[vId] = sink[u.id()];
            }
            var delta = deltaX(u, nodeSep, edgeSep) + deltaX(v, nodeSep, edgeSep);
            if (sink[vId] !== sink[u.id()]) {
              shift[sink[u.id()]] = Math.min(shift[sink[u.id()]], v.attrs.x - u.attrs.x - delta);
            } else {
              xs[vId] = Math.max(xs[vId], xs[u.id()] + delta);
            }
          }
          wId = align[wId].id();
        } while (wId !== vId);
      }
    }

    // Root coordinates relative to sink
    Object.keys(root).forEach(function(uId) {
      if (root[uId].id() === uId) {
        placeBlock(root[uId]);
      }
    });

    // Absolute coordinates
    concat(layering).forEach(function(u) {
      xs[u.id()] = xs[root[u.id()].id()];
      var xDelta = shift[sink[root[u.id()].id()]];
      if (xDelta < Number.POSITIVE_INFINITY) {
        xs[u.id()] += xDelta;
      }
    });

    return xs;
  }

  function findMinCoord(layering, xs) {
    return min(layering.map(function(layer) {
      var u = layer[0];
      return xs[u.id()] - actualNodeWidth(u) / 2;
    }));
  }

  function findMaxCoord(layering, xs) {
    return max(layering.map(function(layer) {
      var u = layer[layer.length - 1];
      return xs[u.id()] - actualNodeWidth(u) / 2;
    }));
  }

  function shiftX(delta, xs) {
    Object.keys(xs).forEach(function(x) {
      xs[x] += delta;
    });
  }

  function alignToSmallest(layering, xss) {
    // First find the smallest width
    var smallestWidthMinCoord;
    var smallestWidthMaxCoord;
    var smallestWidth = Number.POSITIVE_INFINITY;
    values(xss).forEach(function(xs) {
      var minCoord = findMinCoord(layering, xs);
      var maxCoord = findMaxCoord(layering, xs);
      var width = maxCoord - minCoord;
      if (width < smallestWidth) {
        smallestWidthMinCoord = minCoord;
        smallestWidthMaxCoord = maxCoord;
        smallestWidth = width;
      }
    });

    // Realign coordinates with smallest width
    ["up", "down"].forEach(function(vertDir) {
      var xs = xss[vertDir + "-left"];
      var delta = smallestWidthMinCoord - findMinCoord(layering, xs);
      if (delta) {
        shiftX(delta, xs);
      }
    });

    ["up", "down"].forEach(function(vertDir) {
      var xs = xss[vertDir + "-right"];
      var delta = smallestWidthMaxCoord - findMaxCoord(layering, xs);
      if (delta) {
        shiftX(delta, xs);
      }
    });
  }

  function flipHorizontally(layering, xs) {
    var maxCenter = max(values(xs));
    Object.keys(xs).forEach(function(uId) {
      xs[uId] = maxCenter - xs[uId];
    });
  }

  function reverseInnerOrder(layering) {
    layering.forEach(function(layer) {
      layer.reverse();
    });
  }

  return function(g, layering) {
    markType1Conflicts(layering);

    var xss = {};
    ["up", "down"].forEach(function(vertDir) {
      if (vertDir === "down") { layering.reverse(); }

      ["left", "right"].forEach(function(horizDir) {
        if (horizDir === "right") { reverseInnerOrder(layering); }

        var align = verticalAlignment(layering, vertDir === "up" ? "predecessors" : "successors");
        var dir = vertDir + "-" + horizDir;
        xss[dir]= horizontalCompaction(layering, align.pos, align.root, align.align, g.attrs.nodeSep, g.attrs.edgeSep);
        if (horizDir === "right") { flipHorizontally(layering, xss[dir]); }

        if (horizDir === "right") { reverseInnerOrder(layering); }
      });

      if (vertDir === "down") { layering.reverse(); }
    });

    alignToSmallest(layering, xss);

    // Find average of medians for xss array
    g.nodes().forEach(function(u) {
      var xs = values(xss).map(function(xs) { return xs[u.id()]; }).sort();
      u.attrs.x = (xs[1] + xs[2]) / 2;
    });

    // Align min center point with 0
    var minX = min(g.nodes().map(function(u) { return u.attrs.x - actualNodeWidth(u) / 2; }));
    g.nodes().forEach(function(u) {
      u.attrs.x -= minX;
    });

    // Align y coordinates with ranks
    var posY = 0;
    for (var i = 0; i < layering.length; ++i) {
      var layer = layering[i];
      var height = max(layer.map(actualNodeHeight));
      posY += height / 2;
      for (var j = 0; j < layer.length; ++j) {
        var uAttrs = layer[j].attrs;
        uAttrs.y = posY;
      }
      posY += height / 2 + g.attrs.rankSep;
    }

    /*
    g.nodes().forEach(function(u) {
      u.attrs.x = xss["up-right"][u.id()];
    });
    */
  };
})();
<commit_msg>Add ability to debug position alignments<commit_after>/*
 * The algorithms here are based on Brandes and Köpf, "Fast and Simple
 * Horizontal Coordinate Assignment".
 */
dagre.layout.position = (function() {
  function actualNodeWidth(u) {
    var uAttrs = u.attrs;
    return uAttrs.width + uAttrs.marginX * 2 + uAttrs.strokeWidth;
  }

  function actualNodeHeight(u) {
    var uAttrs = u.attrs;
    return uAttrs.height + uAttrs.marginY * 2 + uAttrs.strokeWidth;
  }

  function markType1Conflicts(layering) {
    var pos = {};
    layering[0].forEach(function(u, i) {
      pos[u.id()] = i;
    });

    for (var i = 1; i < layering.length; ++i) {
      var layer = layering[i];

      // Position of last inner segment in the previous layer
      var innerLeft = 0;
      var currIdx = 0;

      // Scan current layer for next node with an inner segment.
      for (var j = 0; j < layer.length; ++j) {
        var u = layer[j];
        // Update positions map for next layer iteration
        pos[u.id()] = j;

        // Search for the next inner segment in the previous layer
        var innerRight = null;
        u.predecessors().forEach(function(v) {
          // TODO could abort as soon as we find a dummy
          if (u.attrs.dummy || v.attrs.dummy) {
            innerRight = pos[v.id()];
          }
        });

        // If no inner segment but at the end of the list we still
        // need to check for type 1 conflicts with earlier segments
        if (innerRight === null && j === layer.length - 1) {
          innerRight = layer.length;
        }

        if (innerRight !== null) {
          for (;currIdx <= j; ++currIdx) {
            var v = layer[currIdx];
            v.inEdges().forEach(function(e) {
              var tailPos = pos[e.tail().id()];
              if (tailPos < innerLeft || tailPos > innerRight) {
                e.attrs.type1Conflict = true;
              }
            });
          }
          innerLeft = innerRight;
        }
      }
    }
  }

  function verticalAlignment(layering, relationship) {
    var pos = {};
    var root = {};
    var align = {};

    layering.forEach(function(layer) {
      layer.forEach(function(u, i) {
        root[u.id()] = u;
        align[u.id()] = u;
        pos[u.id()] = i;
      });
    });

    layering.forEach(function(layer) {
      var prevIdx = -1;
      layer.forEach(function(v) {
        var related = v[relationship]();
        if (related.length > 0) {
          // TODO could find medians with linear algorithm if performance warrants it.
          related.sort(function(x, y) { return pos[x] - pos[y]; });
          var mid = (related.length - 1) / 2;
          related.slice(Math.floor(mid), Math.ceil(mid) + 1).forEach(function(u) {
            if (align[v.id()].id() === v.id()) {
              // TODO should we collapse multi-edges for vertical alignment?

              // Only need to check first returned edge for a type 1 conflict
              if (!u.edges(v)[0].attrs.type1Conflict && prevIdx < pos[u.id()]) {
                align[u.id()] = v;
                align[v.id()] = root[v.id()] = root[u.id()];
                prevIdx = pos[u.id()];
              }
            }
          });
        }
      });
    });

    return { pos: pos, root: root, align: align };
  }

  /*
   * Determines how much spacing u needs from its origin (center) to satisfy
   * width, margin, stroke, and node separation.
   */
  function deltaX(u, nodeSep, edgeSep) {
    var sep = u.attrs.dummy ? edgeSep : nodeSep;
    return actualNodeWidth(u) / 2 + sep / 2;
  }

  function horizontalCompaction(layering, pos, root, align, nodeSep, edgeSep) {
    // Mapping of node id -> sink node id for class
    var sink = {};

    // Mapping of sink node id -> x delta
    var shift = {};

    // Mapping of node id -> predecessor node id (or null)
    var pred = {};

    // Calculated X positions
    var xs = {};

    layering.forEach(function(layer) {
      layer.forEach(function(u, i) {
        sink[u.id()] = u;
        shift[u.id()] = Number.POSITIVE_INFINITY;
        pred[u.id()] = i > 0 ? layer[i - 1].id() : null;
      });
    });

    function placeBlock(v) {
      var vId = v.id();
      if (xs[vId] === undefined) {
        xs[vId] = 0;
        var wId = vId;
        do {
          if (pos[wId] > 0) {
            var u = root[pred[wId]];
            placeBlock(u);
            if (sink[vId].id() === vId) {
              sink[vId] = sink[u.id()];
            }
            var delta = deltaX(u, nodeSep, edgeSep) + deltaX(v, nodeSep, edgeSep);
            if (sink[vId] !== sink[u.id()]) {
              shift[sink[u.id()]] = Math.min(shift[sink[u.id()]], v.attrs.x - u.attrs.x - delta);
            } else {
              xs[vId] = Math.max(xs[vId], xs[u.id()] + delta);
            }
          }
          wId = align[wId].id();
        } while (wId !== vId);
      }
    }

    // Root coordinates relative to sink
    Object.keys(root).forEach(function(uId) {
      if (root[uId].id() === uId) {
        placeBlock(root[uId]);
      }
    });

    // Absolute coordinates
    concat(layering).forEach(function(u) {
      xs[u.id()] = xs[root[u.id()].id()];
      var xDelta = shift[sink[root[u.id()].id()]];
      if (xDelta < Number.POSITIVE_INFINITY) {
        xs[u.id()] += xDelta;
      }
    });

    return xs;
  }

  function findMinCoord(layering, xs) {
    return min(layering.map(function(layer) {
      var u = layer[0];
      return xs[u.id()] - actualNodeWidth(u) / 2;
    }));
  }

  function findMaxCoord(layering, xs) {
    return max(layering.map(function(layer) {
      var u = layer[layer.length - 1];
      return xs[u.id()] - actualNodeWidth(u) / 2;
    }));
  }

  function shiftX(delta, xs) {
    Object.keys(xs).forEach(function(x) {
      xs[x] += delta;
    });
  }

  function alignToSmallest(layering, xss) {
    // First find the smallest width
    var smallestWidthMinCoord;
    var smallestWidthMaxCoord;
    var smallestWidth = Number.POSITIVE_INFINITY;
    values(xss).forEach(function(xs) {
      var minCoord = findMinCoord(layering, xs);
      var maxCoord = findMaxCoord(layering, xs);
      var width = maxCoord - minCoord;
      if (width < smallestWidth) {
        smallestWidthMinCoord = minCoord;
        smallestWidthMaxCoord = maxCoord;
        smallestWidth = width;
      }
    });

    // Realign coordinates with smallest width
    ["up", "down"].forEach(function(vertDir) {
      var xs = xss[vertDir + "-left"];
      var delta = smallestWidthMinCoord - findMinCoord(layering, xs);
      if (delta) {
        shiftX(delta, xs);
      }
    });

    ["up", "down"].forEach(function(vertDir) {
      var xs = xss[vertDir + "-right"];
      var delta = smallestWidthMaxCoord - findMaxCoord(layering, xs);
      if (delta) {
        shiftX(delta, xs);
      }
    });
  }

  function flipHorizontally(layering, xs) {
    var maxCenter = max(values(xs));
    Object.keys(xs).forEach(function(uId) {
      xs[uId] = maxCenter - xs[uId];
    });
  }

  function reverseInnerOrder(layering) {
    layering.forEach(function(layer) {
      layer.reverse();
    });
  }

  return function(g, layering) {
    markType1Conflicts(layering);

    var xss = {};
    ["up", "down"].forEach(function(vertDir) {
      if (vertDir === "down") { layering.reverse(); }

      ["left", "right"].forEach(function(horizDir) {
        if (horizDir === "right") { reverseInnerOrder(layering); }

        var dir = vertDir + "-" + horizDir;
        if (!("debugPosDir" in g.attrs) || g.attrs.debugPosDir === dir) {
          var align = verticalAlignment(layering, vertDir === "up" ? "predecessors" : "successors");
          xss[dir]= horizontalCompaction(layering, align.pos, align.root, align.align, g.attrs.nodeSep, g.attrs.edgeSep);
          if (horizDir === "right") { flipHorizontally(layering, xss[dir]); }
        }

        if (horizDir === "right") { reverseInnerOrder(layering); }
      });

      if (vertDir === "down") { layering.reverse(); }
    });

    if (g.attrs.debugPosDir) {
      // In debug mode we allow forcing layout to a particular alignment.
      g.nodes().forEach(function(u) {
        u.attrs.x = xss[g.attrs.debugPosDir][u.id()];
      });
    } else {
      alignToSmallest(layering, xss);

      // Find average of medians for xss array
      g.nodes().forEach(function(u) {
        var xs = values(xss).map(function(xs) { return xs[u.id()]; }).sort();
        u.attrs.x = (xs[1] + xs[2]) / 2;
      });
    }

    // Align min center point with 0
    var minX = min(g.nodes().map(function(u) { return u.attrs.x - actualNodeWidth(u) / 2; }));
    g.nodes().forEach(function(u) {
      u.attrs.x -= minX;
    });

    // Align y coordinates with ranks
    var posY = 0;
    for (var i = 0; i < layering.length; ++i) {
      var layer = layering[i];
      var height = max(layer.map(actualNodeHeight));
      posY += height / 2;
      for (var j = 0; j < layer.length; ++j) {
        var uAttrs = layer[j].attrs;
        uAttrs.y = posY;
      }
      posY += height / 2 + g.attrs.rankSep;
    }
  };
})();
<|endoftext|>


<commit_before>import { setSources } from "./lazyload.setSources";
import { getWasProcessed, setWasProcessed } from "./lazyload.data";
import { addClass, removeClass } from "./lazyload.class";

const callCallback = function(callback, argument) {
	if (callback) {
		callback(argument);
	}
};

const loadString = "load";
const errorString = "error";

const removeListeners = function(element, loadHandler, errorHandler) {
	element.removeEventListener(loadString, loadHandler);
	element.removeEventListener(errorString, errorHandler);
};

const addOneShotListeners = function(element, settings) {
	const onLoad = event => {
		onEvent(event, true, settings);
		removeListeners(element, onLoad, onError);
	};
	const onError = event => {
		onEvent(event, false, settings);
		removeListeners(element, onLoad, onError);
	};
	element.addEventListener(loadString, onLoad);
	element.addEventListener(errorString, onError);
};

const onEvent = function(event, success, settings) {
	const element = event.target;
	removeClass(element, settings.class_loading);
	addClass(element, success ? settings.class_loaded : settings.class_error); // Setting loaded or error class
	callCallback(
		success ? settings.callback_load : settings.callback_error,
		element
	);
};

export default function(element, settings, force) {
	if (!force && getWasProcessed(element)) {
		return; // element has already been processed and force wasn't true
	}
	callCallback(settings.callback_enter, element);
	if (["IMG", "IFRAME", "VIDEO"].indexOf(element.tagName) > -1) {
		addOneShotListeners(element, settings);
		addClass(element, settings.class_loading);
	}
	setSources(element, settings);
	setWasProcessed(element);
	callCallback(settings.callback_set, element);
}
<commit_msg>Performance: static array moved out from function<commit_after>import { setSources } from "./lazyload.setSources";
import { getWasProcessed, setWasProcessed } from "./lazyload.data";
import { addClass, removeClass } from "./lazyload.class";

const managedTags = ["IMG", "IFRAME", "VIDEO"];

const callCallback = function(callback, argument) {
	if (callback) {
		callback(argument);
	}
};

const loadString = "load";
const errorString = "error";

const removeListeners = function(element, loadHandler, errorHandler) {
	element.removeEventListener(loadString, loadHandler);
	element.removeEventListener(errorString, errorHandler);
};

const addOneShotListeners = function(element, settings) {
	const onLoad = event => {
		onEvent(event, true, settings);
		removeListeners(element, onLoad, onError);
	};
	const onError = event => {
		onEvent(event, false, settings);
		removeListeners(element, onLoad, onError);
	};
	element.addEventListener(loadString, onLoad);
	element.addEventListener(errorString, onError);
};

const onEvent = function(event, success, settings) {
	const element = event.target;
	removeClass(element, settings.class_loading);
	addClass(element, success ? settings.class_loaded : settings.class_error); // Setting loaded or error class
	callCallback(
		success ? settings.callback_load : settings.callback_error,
		element
	);
};

export default function(element, settings, force) {
	if (!force && getWasProcessed(element)) {
		return; // element has already been processed and force wasn't true
	}
	callCallback(settings.callback_enter, element);
	if (managedTags.indexOf(element.tagName) > -1) {
		addOneShotListeners(element, settings);
		addClass(element, settings.class_loading);
	}
	setSources(element, settings);
	setWasProcessed(element);
	callCallback(settings.callback_set, element);
}
<|endoftext|>


<commit_before>L.Util.ajax = function (url, cb) {
	// the following is from JavaScript: The Definitive Guide
	// and https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest_in_IE6
	if (window.XMLHttpRequest === undefined) {
		window.XMLHttpRequest = function() {
			try {
				return new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch  (e) {
				throw new Error("XMLHttpRequest is not supported");
			}
		};
	}
	var response, request = new XMLHttpRequest();
	request.open("GET", url);
	request.onreadystatechange = function() {
		if (request.readyState === 4 && request.status === 200) {
			if(window.JSON) {
				response = JSON.parse(request.responseText);
			} else {
				response = eval("("+ request.responseText + ")");
			}
			cb(response);
		}
	};
	request.send();
};
L.UtfGrid = L.Class.extend({
	includes: L.Mixin.Events,
	options: {
		subdomains: 'abc',

		minZoom: 0,
		maxZoom: 18,
		tileSize: 256,

		resolution: 2,

		useJsonP: true
	},

	//The thing the mouse is currently on
	_mouseOn: null,

	initialize: function (url, options) {
		L.Util.setOptions(this, options);

		this._url = url;
		this._cache = {};

		//Find a unique id in window we can use for our callbacks
		//Required for jsonP
		var i = 0;
		while (window['lu' + i]) {
			i++;
		}
		this._windowKey = 'lu' + i;
		window[this._windowKey] = {};

		var subdomains = this.options.subdomains;
		if (typeof this.options.subdomains === 'string') {
			this.options.subdomains = subdomains.split('');
		}
	},

	onAdd: function (map) {
		this._map = map;

		this._update();

		var zoom = this._map.getZoom();

		if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
			return;
		}

		map.on('click', this._click, this);
		map.on('mousemove', this._move, this);
		map.on('moveend', this._update, this);
	},

	onRemove: function () {
		var map = this._map;
		map.off('click', this._click, this);
		map.off('mousemove', this._move, this);
		map.off('moveend', this._update, this);
	},

	_click: function (e) {
		this.fire('click', this._objectForEvent(e));
	},
	_move: function (e) {
		var on = this._objectForEvent(e);

		if (on.data != this._mouseOn) {
			if (this._mouseOn) {
				this.fire('mouseout', { latlng: e.latlng, data: this._mouseOn });
			}
			if (on.data) {
				this.fire('mouseover', on);
			}

			this._mouseOn = on.data;
		}
	},

	_objectForEvent: function (e) {
		var map = this._map,
		    point = map.project(e.latlng),
		    tileSize = this.options.tileSize,
		    resolution = this.options.resolution,
		    x = Math.floor(point.x / tileSize),
		    y = Math.floor(point.y / tileSize),
		    gridX = Math.floor((point.x - (x * tileSize)) / resolution),
		    gridY = Math.floor((point.y - (y * tileSize)) / resolution),
			max = map.options.crs.scale(map.getZoom()) / tileSize;

		x = (x + max) % max;
		y = (y + max) % max;

		var data = this._cache[map.getZoom() + '_' + x + '_' + y];
		if (!data) {
			//console.log('not cached ' + map.getZoom() + '_' + x + '_' + y);
			return { latlng: e.latlng, data: null };
		}

		var idx = this._utfDecode(data.grid[gridY].charCodeAt(gridX)),
		    key = data.keys[idx],
		    result = data.data[key];

		if (!data.data.hasOwnProperty(key))
			result = null;

		return { latlng: e.latlng, data: result};
	},

	//Load up all required json grid files
	//TODO: Load from center etc
	_update: function () {

		var bounds = this._map.getPixelBounds(),
		    zoom = this._map.getZoom(),
		    tileSize = this.options.tileSize;

		if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
			return;
		}

		var nwTilePoint = new L.Point(
				Math.floor(bounds.min.x / tileSize),
				Math.floor(bounds.min.y / tileSize)),
			seTilePoint = new L.Point(
				Math.floor(bounds.max.x / tileSize),
				Math.floor(bounds.max.y / tileSize)),
				max = this._map.options.crs.scale(zoom) / tileSize;

		//Load all required ones
		for (var x = nwTilePoint.x; x <= seTilePoint.x; x++) {
			for (var y = nwTilePoint.y; y <= seTilePoint.y; y++) {

				var xw = (x + max) % max, yw = (y + max) % max;
				var key = zoom + '_' + xw + '_' + yw;

				if (!this._cache.hasOwnProperty(key)) {
					this._cache[key] = null;

					if (this.options.useJsonP) {
						this._loadTileP(zoom, xw, yw);
					} else {
						this._loadTile(zoom, xw, yw);
					}
				}
			}
		}
	},

	_loadTileP: function (zoom, x, y) {
		var head = document.getElementsByTagName('head')[0],
		    key = zoom + '_' + x + '_' + y,
		    functionName = 'lu_' + key,
		    wk = this._windowKey,
		    self = this;

		var url = L.Util.template(this._url, L.Util.extend({
			s: L.TileLayer.prototype._getSubdomain.call(this, { x: x, y: y }),
			z: zoom,
			x: x,
			y: y,
			cb: wk + '.' + functionName
		}, this.options));

		var script = document.createElement('script');
		script.setAttribute("type", "text/javascript");
		script.setAttribute("src", url);

		window[wk][functionName] = function (data) {
			self._cache[key] = data;
			delete window[wk][functionName];
			head.removeChild(script);
		};

		head.appendChild(script);
	},

	_loadTile: function (zoom, x, y) {
		var url = L.Util.template(this._url, L.Util.extend({
			s: L.TileLayer.prototype._getSubdomain.call(this, { x: x, y: y }),
			z: zoom,
			x: x,
			y: y
		}, this.options));

		var key = zoom + '_' + x + '_' + y;
		var self = this;
		L.Util.ajax(url, function (data) {
			self._cache[key] = data;
		});
	},

	_utfDecode: function (c) {
		if (c >= 93)
			c--;
		if (c >= 35)
			c--;
		return c - 32;
	}
});<commit_msg>Make jshint happy<commit_after>L.Util.ajax = function (url, cb) {
	// the following is from JavaScript: The Definitive Guide
	// and https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest_in_IE6
	if (window.XMLHttpRequest === undefined) {
		window.XMLHttpRequest = function () {
			/*global ActiveXObject:true */
			try {
				return new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch  (e) {
				throw new Error("XMLHttpRequest is not supported");
			}
		};
	}
	var response, request = new XMLHttpRequest();
	request.open("GET", url);
	request.onreadystatechange = function () {
		/*jshint evil: true */
		if (request.readyState === 4 && request.status === 200) {
			if (window.JSON) {
				response = JSON.parse(request.responseText);
			} else {
				response = eval("(" + request.responseText + ")");
			}
			cb(response);
		}
	};
	request.send();
};
L.UtfGrid = L.Class.extend({
	includes: L.Mixin.Events,
	options: {
		subdomains: 'abc',

		minZoom: 0,
		maxZoom: 18,
		tileSize: 256,

		resolution: 2,

		useJsonP: true
	},

	//The thing the mouse is currently on
	_mouseOn: null,

	initialize: function (url, options) {
		L.Util.setOptions(this, options);

		this._url = url;
		this._cache = {};

		//Find a unique id in window we can use for our callbacks
		//Required for jsonP
		var i = 0;
		while (window['lu' + i]) {
			i++;
		}
		this._windowKey = 'lu' + i;
		window[this._windowKey] = {};

		var subdomains = this.options.subdomains;
		if (typeof this.options.subdomains === 'string') {
			this.options.subdomains = subdomains.split('');
		}
	},

	onAdd: function (map) {
		this._map = map;

		this._update();

		var zoom = this._map.getZoom();

		if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
			return;
		}

		map.on('click', this._click, this);
		map.on('mousemove', this._move, this);
		map.on('moveend', this._update, this);
	},

	onRemove: function () {
		var map = this._map;
		map.off('click', this._click, this);
		map.off('mousemove', this._move, this);
		map.off('moveend', this._update, this);
	},

	_click: function (e) {
		this.fire('click', this._objectForEvent(e));
	},
	_move: function (e) {
		var on = this._objectForEvent(e);

		if (on.data !== this._mouseOn) {
			if (this._mouseOn) {
				this.fire('mouseout', { latlng: e.latlng, data: this._mouseOn });
			}
			if (on.data) {
				this.fire('mouseover', on);
			}

			this._mouseOn = on.data;
		}
	},

	_objectForEvent: function (e) {
		var map = this._map,
		    point = map.project(e.latlng),
		    tileSize = this.options.tileSize,
		    resolution = this.options.resolution,
		    x = Math.floor(point.x / tileSize),
		    y = Math.floor(point.y / tileSize),
		    gridX = Math.floor((point.x - (x * tileSize)) / resolution),
		    gridY = Math.floor((point.y - (y * tileSize)) / resolution),
			max = map.options.crs.scale(map.getZoom()) / tileSize;

		x = (x + max) % max;
		y = (y + max) % max;

		var data = this._cache[map.getZoom() + '_' + x + '_' + y];
		if (!data) {
			//console.log('not cached ' + map.getZoom() + '_' + x + '_' + y);
			return { latlng: e.latlng, data: null };
		}

		var idx = this._utfDecode(data.grid[gridY].charCodeAt(gridX)),
		    key = data.keys[idx],
		    result = data.data[key];

		if (!data.data.hasOwnProperty(key)) {
			result = null;
		}

		return { latlng: e.latlng, data: result};
	},

	//Load up all required json grid files
	//TODO: Load from center etc
	_update: function () {

		var bounds = this._map.getPixelBounds(),
		    zoom = this._map.getZoom(),
		    tileSize = this.options.tileSize;

		if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
			return;
		}

		var nwTilePoint = new L.Point(
				Math.floor(bounds.min.x / tileSize),
				Math.floor(bounds.min.y / tileSize)),
			seTilePoint = new L.Point(
				Math.floor(bounds.max.x / tileSize),
				Math.floor(bounds.max.y / tileSize)),
				max = this._map.options.crs.scale(zoom) / tileSize;

		//Load all required ones
		for (var x = nwTilePoint.x; x <= seTilePoint.x; x++) {
			for (var y = nwTilePoint.y; y <= seTilePoint.y; y++) {

				var xw = (x + max) % max, yw = (y + max) % max;
				var key = zoom + '_' + xw + '_' + yw;

				if (!this._cache.hasOwnProperty(key)) {
					this._cache[key] = null;

					if (this.options.useJsonP) {
						this._loadTileP(zoom, xw, yw);
					} else {
						this._loadTile(zoom, xw, yw);
					}
				}
			}
		}
	},

	_loadTileP: function (zoom, x, y) {
		var head = document.getElementsByTagName('head')[0],
		    key = zoom + '_' + x + '_' + y,
		    functionName = 'lu_' + key,
		    wk = this._windowKey,
		    self = this;

		var url = L.Util.template(this._url, L.Util.extend({
			s: L.TileLayer.prototype._getSubdomain.call(this, { x: x, y: y }),
			z: zoom,
			x: x,
			y: y,
			cb: wk + '.' + functionName
		}, this.options));

		var script = document.createElement('script');
		script.setAttribute("type", "text/javascript");
		script.setAttribute("src", url);

		window[wk][functionName] = function (data) {
			self._cache[key] = data;
			delete window[wk][functionName];
			head.removeChild(script);
		};

		head.appendChild(script);
	},

	_loadTile: function (zoom, x, y) {
		var url = L.Util.template(this._url, L.Util.extend({
			s: L.TileLayer.prototype._getSubdomain.call(this, { x: x, y: y }),
			z: zoom,
			x: x,
			y: y
		}, this.options));

		var key = zoom + '_' + x + '_' + y;
		var self = this;
		L.Util.ajax(url, function (data) {
			self._cache[key] = data;
		});
	},

	_utfDecode: function (c) {
		if (c >= 93) {
			c--;
		}
		if (c >= 35) {
			c--;
		}
		return c - 32;
	}
});<|endoftext|>


<commit_before>'use strict';

var L = require('leaflet');

var standard = L.tileLayer('//tile.osm.ch/switzerland/{z}/{x}/{y}.png', {
    attribution: 'Map data © OpenStreetMap contributors under ODbL'
  }),
  swiss_style = L.tileLayer('http://tile.osm.ch/osm-swiss-style/{z}/{x}/{y}.png', {
    attribution: 'Map data © OpenStreetMap contributors under ODbL'
  }),
 osm_de = L.tileLayer('//{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', {
    attribution: 'Map data © OpenStreetMap contributors under ODbL'
  }),
  hiking = L.tileLayer('//tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png', {}),
  bike = L.tileLayer('//tile.waymarkedtrails.org/cycling/{z}/{x}/{y}.png', {})

module.exports = {
  defaultState: {
    center: L.latLng(47, 8),
    zoom: 10,
    waypoints: [],
    language: 'en',
    alternative: 0,
    layer: standard
  },
  services: [{
    label: 'Car (fastest)',
    path: 'http://127.0.0.1:3331/route/v1'
  },
  {
    label: 'Bike (city)',
    path: 'http://127.0.0.1:3332/route/v1'
  },
  {
    label: 'Bike (touring)',
    path: 'http://127.0.0.1:3333/route/v1'
  },
  {
    label: 'Foot',
    path: 'http://127.0.0.1:3334/route/v1'
  },
  {
    label: 'Hiking',
    path: 'http://127.0.0.1:3335/route/v1'
  }],
  layer: [{
    'standard': standard,
    'swiss style': swiss_style,
    'osm.de': osm_de
  }],
  overlay: {
    'hiking': hiking,
    'bike': bike,
  },
  baselayer: {
    one: standard,
    two: swiss_style,
    three: osm_de
  }
};
<commit_msg>correct url of routing profiles<commit_after>'use strict';

var L = require('leaflet');

var standard = L.tileLayer('//tile.osm.ch/switzerland/{z}/{x}/{y}.png', {
    attribution: 'Map data © OpenStreetMap contributors under ODbL'
  }),
  swiss_style = L.tileLayer('http://tile.osm.ch/osm-swiss-style/{z}/{x}/{y}.png', {
    attribution: 'Map data © OpenStreetMap contributors under ODbL'
  }),
 osm_de = L.tileLayer('//{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', {
    attribution: 'Map data © OpenStreetMap contributors under ODbL'
  }),
  hiking = L.tileLayer('//tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png', {}),
  bike = L.tileLayer('//tile.waymarkedtrails.org/cycling/{z}/{x}/{y}.png', {})

module.exports = {
  defaultState: {
    center: L.latLng(47, 8),
    zoom: 10,
    waypoints: [],
    language: 'en',
    alternative: 0,
    layer: standard
  },
  services: [{
    label: 'Car (fastest)',
    path: '/routed-car/route/v1'
  },
  {
    label: 'Bike (city)',
    path: '/routed-bike/route/v1'
  },
  {
    label: 'Bike (touring)',
    path: '/routed-bike-touring/route/v1'
  },
  {
    label: 'Foot',
    path: '/routed-foot/route/v1'
  },
  {
    label: 'Hiking',
    path: '/routed-hiking/route/v1'
  }],
  layer: [{
    'standard': standard,
    'swiss style': swiss_style,
    'osm.de': osm_de
  }],
  overlay: {
    'hiking': hiking,
    'bike': bike,
  },
  baselayer: {
    one: standard,
    two: swiss_style,
    three: osm_de
  }
};
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import anime from 'animejs';
import Draggable from 'react-draggable';

// import Container from './Container';

import styled, { css } from 'react-emotion';

const MENU_WIDTH = 160;
const MENU_BORDER_RADIUS = '11px';

const Container = styled('div')`
  height: 100vh;
  width: 100vw;
`;

const Menu = styled('nav')`
  position: fixed;
  width: ${MENU_WIDTH}px;
  height: 70px;
  background-color: rgba(54, 149, 217, 0.8);
  box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
  border-radius: ${MENU_BORDER_RADIUS};
  z-position: 2;
`;

const PlacementOutline = styled('nav')`
  position: fixed;
  ${({ left }) => left && `left: ${left};`}
  ${({ right }) => right && `right: ${right};`}
  ${({ top }) => top && `top: ${top};`}
  ${({ height }) => height && `height: ${height};`}
  ${({ width }) => width && `width: ${width};`}

  z-position: 1;
  background-color: rgba(94, 80, 80, 0.8);
  opacity: 1;
  opacity: ${({ shouldShow }) => (shouldShow ? 1 : 0) };
`;

/* ----------------------------------------------------------------------------*/
/* Menu Router Container
/* ----------------------------------------------------------------------------*/

// dock top or bottom
const RouterContainerHorizontal = css`
  height: 100%;
  flex-direction: row;
  width: 150px;
  border-radius: 0px;
`;

// dock left or right
const RouterContainerVertical = css`
  width: 100%;
  flex-direction: row;
`;

const RouterContainer = styled('nav')`
  position: absolute;
  bottom: 0px;
  left: 0px;
  display: flex;
  justify-content: space-around;
  align-items: center;
  background-color: rgba(54, 149, 217, 1);
  border-bottom-left-radius: ${MENU_BORDER_RADIUS};
  border-bottom-right-radius: ${MENU_BORDER_RADIUS};
  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') ? RouterContainerHorizontal : RouterContainerVertical) }
`;

/* ----------------------------------------------------------------------------*/
/* Menu Router Features
/* ----------------------------------------------------------------------------*/
// dock top or bottom
const FAIconHorizontal = css`
  height: 100%;

  &:hover {
    border-radius: 0px;
  }
`;

// dock left or right
const FAIconVertical = css`
  padding: 10px;
`;

const FAIcon = styled('div')`
  color: gray;
  font-size: 20px;
  font-weight: light;
  width: 50%;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;

  &:hover {
    color: rgba(54, 149, 217, 1);
    background-color: gray;
    ${({ leftOrRight }) => `border-bottom-${leftOrRight}-radius: ${MENU_BORDER_RADIUS};`}
  };

  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') ? FAIconHorizontal : FAIconVertical)}
`;

/* ----------------------------------------------------------------------------*/
/* Menu Control Container
/* ----------------------------------------------------------------------------*/

// dock top or bottom
const MenuControllerContainerHorizontal = css`
  right: 0px;
  height: 100%;
  flex-direction: row;
  width: 150px;
`;

// dock left or right
const MenuControllerContainerVertical = css`
  left: 0px;
  width: 100%;
  height: 35px;
`;

const MenuControllerContainer = styled('div')`
  position: absolute;
  top: 0px;
  display: flex;
  justify-content: center;
  align-items: center;
  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') ? MenuControllerContainerHorizontal : MenuControllerContainerVertical) }
`;

/* ----------------------------------------------------------------------------*/
/* Menu Control Features
/* ----------------------------------------------------------------------------*/

// dock top or bottom
const MenuDraggableContainerHorizontal = css`
  width: 50%;
  height: 100%;
`;

// dock left or right
const MenuDraggableContainerVertical = css`
  width: 100%;
  height: 100%;
  border-top-left-radius: ${MENU_BORDER_RADIUS};
`;

const MenuDraggableContainer = styled('div')`
  display: flex;
  justify-content: center;
  align-items: center;
  flex: 2;
  background-color: rgba(54, 149, 217, 0.7);

  &:hover {
    cursor: grab;
  }

  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') ? MenuDraggableContainerHorizontal : MenuDraggableContainerVertical) }
`

const DraggableIcon = styled('div')`
  background-color: gray;
  border-radius: 50%;
  height: 6px;
  width: 6px;
  margin: 5px;
  margin-left: 3px;
  margin-right: 3px;
`;

// dock top or bottom
const MenuShrinkContainerHorizontal = css`
  width: 50%;
  height: 100%;
`;

// dock left or right
const MenuShrinkContainerVertical = css`
  width: 70px;
  height: 100%;
  border-top-right-radius: ${MENU_BORDER_RADIUS};
`;

const MenuShrinkContainer = styled('div')`
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(54, 149, 217, 1);

  &:hover {
    cursor: pointer;
  }

  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') ? MenuShrinkContainerHorizontal : MenuShrinkContainerVertical) }
`;

const MenuShrinkButton = styled('div')`
  width: 20px;
  background-color: gray;
  height: 4px;
  border-radius: 2px;
`;

export default class Component extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isOpen: false,
      menuPlacement: undefined, // willDockTop, willDockLeft, willDockRight, hasDockedTop, hasDockedLeft, hasDockedRight
      width: undefined, // window.width
      height: undefined, // window.height
      menuX: 50,
      menuY: 70,
    };

    this.myRef = React.createRef();

    this.handleMenuOpenToggleClick = this.handleMenuOpenToggleClick.bind(this);
    this.onStartDragEvent = this.onStartDragEvent.bind(this);
    this.onDragEvent = this.onDragEvent.bind(this);
    this.onStopDragEvent = this.onStopDragEvent.bind(this);
    this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
  }

  componentWillMount() {
    window.addEventListener('resize', this.updateWindowDimensions);
   }

  componentDidMount() {
    if (this.isRouterHere()) { this.openMenu(); }
    this.updateWindowDimensions()
  }

  componentDidUpdate({ location: { state: prevRouterState} }) {
    const routerLocationJustChanged = this.hasRouterLocationJustChanged(prevRouterState);
    if (routerLocationJustChanged && this.isRouterHere()) { this.openMenu(); }
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.updateWindowDimensions);
  }

  updateWindowDimensions() {
    this.setState(state => ({ ...state, width: window.innerWidth, height: window.innerHeight }));
  }

  onStartDragEvent({ clientX: x, clientY: y }, data) {
    console.log(x, y)
    const { menuPlacement: placement } = this.state;
    if (placement !== undefined) { this.animateUnDock(x, y) }
  }

  onDragEvent(e, { x, y }) {
    const { menuPlacement: placement, width } = this.state;

    if (y < 10) {
      if (placement !== 'willDockTop' ) this.setState(state => ({ ...state, menuPlacement: 'willDockTop' }))
    } else if (x < 10) {
      if (placement !== 'willDockLeft' ) this.setState(state => ({ ...state, menuPlacement: 'willDockLeft' }))
    } else if (x > (width - MENU_WIDTH - 10)) {
      if (placement !== 'willDockRight' ) this.setState(state => ({ ...state, menuPlacement: 'willDockRight' }))
    } else {
       if (placement !== undefined) this.setState(state => ({ ...state, menuPlacement: undefined }))
    }
  }

  onStopDragEvent(e, { x, y }) {
    const { menuPlacement: placement } = this.state;
    if (placement === 'willDockLeft') {
      this.animateDockLeft();
      this.setState(state => ({ ...state, menuPlacement: 'hasDockedLeft' }))
    }
    if (placement === 'willDockRight') {
      this.animateDockRight();
      this.setState(state => ({ ...state, menuPlacement: 'hasDockedRight' }))
    }
    if (placement === 'willDockTop') {
      this.animateDockTop();
      this.setState(state => ({ ...state, menuPlacement: 'hasDockedTop' }))
    }
  }

  isRouterHere() {
    const { location: { state } } = this.props;
    return state ? state.atLocation === 'view' : true; // is the router here with no modals in the way;
  }

  hasRouterLocationJustChanged(prevRouterState) {
    const { location: { state: currentRouterState} } = this.props;
    const currentAt = currentRouterState ? currentRouterState.atLocation : undefined;
    const prevAt = prevRouterState ? prevRouterState.atLocation : undefined;

    return currentAt !== prevAt
  }

  openMenu() {
    const { isOpen } = this.state;
    if (!isOpen) {
      this.setState({ isOpen: true });
      this.animateOpen();
    }
  }

  closeMenu() {
    const { isOpen } = this.state;
    if (isOpen) {
      this.setState({ isOpen: false });
      this.animateClose();
    }
  }

  animateOpen() {
    anime({
      targets: '.view-menu-container',
      height: [70, 500],
      width: `${MENU_WIDTH}px`,
      duration: 500,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 100,
    })
  }

  animateClose() {
    anime({
      targets: '.view-menu-container',
      height: [500, 70],
      duration: 500,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 100,
    })
  }

  animateUnDock(left, top) {
    anime({
      targets: '.view-menu-container',
      height: 500,
      width: 160,
      duration: 200,
      elasticity: 0,
      borderRadius: MENU_BORDER_RADIUS,
      easing: 'easeOutQuint',
      delay: 0,
    })
  }

  animateDockLeft() {
    anime({
      targets: '.view-menu-container',
      height: '100%',
      top: '0',
      left: '0',
      borderRadius: 0,
      duration: 300,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 0,
    })
  }

  animateDockTop() {
    anime({
      targets: '.view-menu-container',
      width: '100%',
      height: '70px',
      top: '0',
      left: '0px',
      borderRadius: 0,
      duration: 300,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 0,
    })
  }

  animateDockRight() {
    anime({
      targets: '.view-menu-container',
      height: '100%',
      top: '0',
      right: '0',
      borderRadius: 0,
      duration: 300,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 0,
    })
  }

  handleMenuOpenToggleClick() {
    const { isOpen } = this.state;
    if (isOpen) {
      this.closeMenu();
    } else {
      this.openMenu();
    }
  }

  render() {
    const { menuPlacement: placement, menuX, menuY, width } = this.state;
    let position
    switch(placement) {
      case 'hasDockedLeft': {
        position = { x: 0, y: 0 };
        break;
      }
      case 'hasDockedTop': {
        position = { x: 0, y: 0 };
        break;
      }
      case 'hasDockedRight': {
        position = { x: (width - MENU_WIDTH), y: 0 };
        break;
      }
    }

    const positionProp = position ? { position } : {};
    console.log(positionProp)
    console.log('placmenet', placement)
    return (
      <Container>
      <PlacementOutline shouldShow={placement === 'willDockLeft'} height="100vh" width={`${MENU_WIDTH}px`} top="0" left="0"/>
      <PlacementOutline shouldShow={placement === 'willDockRight'} height="100vh" width={`${MENU_WIDTH}px`} top="0" right="0"/>
      <PlacementOutline shouldShow={placement === 'willDockTop'} height="70px" width="100vw" top="0" left="0"/>
      <Draggable
        handle=".view-menu-draggable-handle"
        axis="both"
        bounds="parent"
        defaultPosition={{ x: 50, y: 70 }}
        onStart={this.onStartDragEvent}
        onDrag={this.onDragEvent}
        onStop={this.onStopDragEvent}
        {...positionProp}
      >
        <Menu className="view-menu-container here" menuPlacement={placement}>
          <MenuControllerContainer menuPlacement={placement}>
            <MenuDraggableContainer menuPlacement={placement} className='view-menu-draggable-handle'>
              <DraggableIcon />
              <DraggableIcon />
              <DraggableIcon />
            </MenuDraggableContainer>
            <MenuShrinkContainer menuPlacement={placement} onClick={this.handleMenuOpenToggleClick}>
              <MenuShrinkButton />
            </MenuShrinkContainer>
          </MenuControllerContainer>
          <RouterContainer menuPlacement={placement}>
            <FAIcon menuPlacement={placement} leftOrRight="left" className="fas fa-home" />
            <FAIcon menuPlacement={placement} leftOrRight="right" className="fas fa-question" />
          </RouterContainer>
        </Menu>
      </Draggable>
      </Container>
    );
  }
}
<commit_msg>add more granular styling for view menu docking positions<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import anime from 'animejs';
import Draggable from 'react-draggable';

// import Container from './Container';

import styled, { css } from 'react-emotion';

const MENU_WIDTH = 160;
const MENU_BORDER_RADIUS = '11px';

const Container = styled('div')`
  height: 100vh;
  width: 100vw;
`;

const Menu = styled('nav')`
  position: fixed;
  width: ${MENU_WIDTH}px;
  height: 70px;
  background-color: rgba(54, 149, 217, 0.8);
  box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
  border-radius: ${MENU_BORDER_RADIUS};
  z-position: 2;
`;

const PlacementOutline = styled('nav')`
  position: fixed;
  ${({ left }) => left && `left: ${left};`}
  ${({ right }) => right && `right: ${right};`}
  ${({ top }) => top && `top: ${top};`}
  ${({ height }) => height && `height: ${height};`}
  ${({ width }) => width && `width: ${width};`}

  z-position: 1;
  background-color: rgba(94, 80, 80, 0.8);
  opacity: 1;
  opacity: ${({ shouldShow }) => (shouldShow ? 1 : 0) };
`;

/* ----------------------------------------------------------------------------*/
/* Menu Router Container
/* ----------------------------------------------------------------------------*/

// dock top or bottom
const RouterContainerHorizontal = css`
  height: 100%;
  flex-direction: row;
  width: 150px;
  border-radius: 0px;
`;

// dock left or right
const RouterContainerVertical = css`
  width: 100%;
  flex-direction: row;
  height: 50px;
`;

const RouterContainerNotDocked = css`
  width: 100%;
  flex-direction: row;
`;

const RouterContainer = styled('nav')`
  position: absolute;
  bottom: 0px;
  left: 0px;
  display: flex;
  justify-content: space-around;
  align-items: center;
  background-color: rgba(54, 149, 217, 1);
  border-bottom-left-radius: ${MENU_BORDER_RADIUS};
  border-bottom-right-radius: ${MENU_BORDER_RADIUS};

  ${({ menuPlacement }) => ((!menuPlacement || !menuPlacement.includes('hasDocked')) && RouterContainerNotDocked) }
  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') && RouterContainerHorizontal) }
  ${({ menuPlacement }) => (menuPlacement && (menuPlacement.includes('hasDockedLeft') || menuPlacement.includes('hasDockedRight')) && RouterContainerVertical) }
`;

/* ----------------------------------------------------------------------------*/
/* Menu Router Features
/* ----------------------------------------------------------------------------*/
// dock top or bottom
const FAIconHorizontal = css`
  height: 100%;

  &:hover {
    border-radius: 0px;
  }
`;

// dock left or right
const FAIconVertical = css`
  padding: 10px;
`;

const FAIconNotDocked = css`
  padding: 10px;
  &:hover {
    border-radius: 0px;
  }
`;

const FAIcon = styled('div')`
  color: gray;
  font-size: 20px;
  font-weight: light;
  width: 50%;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;

  &:hover {
    color: rgba(54, 149, 217, 1);
    background-color: gray;
    ${({ leftOrRight }) => `border-bottom-${leftOrRight}-radius: ${MENU_BORDER_RADIUS};`}
  };

  ${({ menuPlacement }) => ((!menuPlacement || !menuPlacement.includes('hasDocked')) && FAIconNotDocked) }
  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') && FAIconHorizontal) }
  ${({ menuPlacement }) => (menuPlacement && (menuPlacement.includes('hasDockedLeft') || menuPlacement.includes('hasDockedRight')) && FAIconVertical) }
`;

/* ----------------------------------------------------------------------------*/
/* Menu Control Container
/* ----------------------------------------------------------------------------*/

// dock top or bottom
const MenuControllerContainerHorizontal = css`
  right: 0px;
  height: 100%;
  flex-direction: row;
  width: 150px;
`;

// dock left or right
const MenuControllerContainerVertical = css`
  left: 0px;
  width: 100%;
  height: 50px;
  border-radius: 0px;
`;

// not docked
const MenuControllerContainerNotDocked = css`
  left: 0px;
  width: 100%;
  height: 35px;
`;

const MenuControllerContainer = styled('div')`
  position: absolute;
  top: 0px;
  display: flex;
  justify-content: center;
  align-items: center;
  ${({ menuPlacement }) => ((!menuPlacement || !menuPlacement.includes('hasDocked')) && MenuControllerContainerNotDocked) }
  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') && MenuControllerContainerHorizontal) }
  ${({ menuPlacement }) => (menuPlacement && (menuPlacement.includes('hasDockedLeft') || menuPlacement.includes('hasDockedRight')) && MenuControllerContainerVertical) }

`;

/* ----------------------------------------------------------------------------*/
/* Menu Control Features
/* ----------------------------------------------------------------------------*/

// dock top or bottom
const MenuDraggableContainerHorizontal = css`
  width: 50%;
  height: 100%;
`;

// dock left or right
const MenuDraggableContainerVertical = css`
  width: 100%;
  height: 100%;
`;

// not docked
const MenuDraggableContainerNotDocked = css`
  width: 100%;
  height: 100%;
  border-top-left-radius: ${MENU_BORDER_RADIUS};
`;

const MenuDraggableContainer = styled('div')`
  display: flex;
  justify-content: center;
  align-items: center;
  flex: 2;
  background-color: rgba(54, 149, 217, 0.7);

  &:hover {
    cursor: grab;
  }

  ${({ menuPlacement }) => ((!menuPlacement || !menuPlacement.includes('hasDocked')) && MenuDraggableContainerNotDocked) }
  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') && MenuDraggableContainerHorizontal) }
  ${({ menuPlacement }) => (menuPlacement && (menuPlacement.includes('hasDockedLeft') || menuPlacement.includes('hasDockedRight')) && MenuDraggableContainerVertical) }
`;

const DraggableIcon = styled('div')`
  background-color: gray;
  border-radius: 50%;
  height: 6px;
  width: 6px;
  margin: 5px;
  margin-left: 3px;
  margin-right: 3px;
`;

// dock top or bottom
const MenuShrinkContainerHorizontal = css`
  width: 50%;
  height: 100%;
`;

// dock left or right
const MenuShrinkContainerVertical = css`
  width: 70px;
  height: 100%;
`;

// not docked
const MenuShrinkContainerNotDocked = css`
  width: 70px;
  height: 100%;
  border-top-right-radius: ${MENU_BORDER_RADIUS};
`;

const MenuShrinkContainer = styled('div')`
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(54, 149, 217, 1);

  &:hover {
    cursor: pointer;
  }

  ${({ menuPlacement }) => ((!menuPlacement || !menuPlacement.includes('hasDocked')) && MenuShrinkContainerNotDocked) }
  ${({ menuPlacement }) => (menuPlacement && menuPlacement.includes('hasDockedTop') && MenuShrinkContainerHorizontal) }
  ${({ menuPlacement }) => (menuPlacement && (menuPlacement.includes('hasDockedLeft') || menuPlacement.includes('hasDockedRight')) && MenuShrinkContainerVertical) }
`;

const MenuShrinkButton = styled('div')`
  width: 20px;
  background-color: gray;
  height: 4px;
  border-radius: 2px;
`;

export default class Component extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isOpen: false,
      menuPlacement: undefined, // willDockTop, willDockLeft, willDockRight, hasDockedTop, hasDockedLeft, hasDockedRight
      width: undefined, // window.width
      height: undefined, // window.height
      menuX: 50,
      menuY: 70,
    };

    this.myRef = React.createRef();

    this.handleMenuOpenToggleClick = this.handleMenuOpenToggleClick.bind(this);
    this.onStartDragEvent = this.onStartDragEvent.bind(this);
    this.onDragEvent = this.onDragEvent.bind(this);
    this.onStopDragEvent = this.onStopDragEvent.bind(this);
    this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
  }

  componentWillMount() {
    window.addEventListener('resize', this.updateWindowDimensions);
   }

  componentDidMount() {
    if (this.isRouterHere()) { this.openMenu(); }
    this.updateWindowDimensions()
  }

  componentDidUpdate({ location: { state: prevRouterState} }) {
    const routerLocationJustChanged = this.hasRouterLocationJustChanged(prevRouterState);
    if (routerLocationJustChanged && this.isRouterHere()) { this.openMenu(); }
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.updateWindowDimensions);
  }

  updateWindowDimensions() {
    this.setState(state => ({ ...state, width: window.innerWidth, height: window.innerHeight }));
  }

  onStartDragEvent({ clientX: x, clientY: y }, data) {
    console.log(x, y)
    const { menuPlacement: placement } = this.state;
    if (placement !== undefined) { this.animateUnDock(x, y) }
  }

  onDragEvent(e, { x, y }) {
    const { menuPlacement: placement, width } = this.state;

    if (y < 10) {
      if (placement !== 'willDockTop' ) this.setState(state => ({ ...state, menuPlacement: 'willDockTop' }))
    } else if (x < 10) {
      if (placement !== 'willDockLeft' ) this.setState(state => ({ ...state, menuPlacement: 'willDockLeft' }))
    } else if (x > (width - MENU_WIDTH - 10)) {
      if (placement !== 'willDockRight' ) this.setState(state => ({ ...state, menuPlacement: 'willDockRight' }))
    } else {
       if (placement !== undefined) this.setState(state => ({ ...state, menuPlacement: undefined }))
    }
  }

  onStopDragEvent(e, { x, y }) {
    const { menuPlacement: placement } = this.state;
    if (placement === 'willDockLeft') {
      this.animateDockLeft();
      this.setState(state => ({ ...state, menuPlacement: 'hasDockedLeft' }))
    }
    if (placement === 'willDockRight') {
      this.animateDockRight();
      this.setState(state => ({ ...state, menuPlacement: 'hasDockedRight' }))
    }
    if (placement === 'willDockTop') {
      this.animateDockTop();
      this.setState(state => ({ ...state, menuPlacement: 'hasDockedTop' }))
    }
  }

  isRouterHere() {
    const { location: { state } } = this.props;
    return state ? state.atLocation === 'view' : true; // is the router here with no modals in the way;
  }

  hasRouterLocationJustChanged(prevRouterState) {
    const { location: { state: currentRouterState} } = this.props;
    const currentAt = currentRouterState ? currentRouterState.atLocation : undefined;
    const prevAt = prevRouterState ? prevRouterState.atLocation : undefined;

    return currentAt !== prevAt
  }

  openMenu() {
    const { isOpen } = this.state;
    if (!isOpen) {
      this.setState({ isOpen: true });
      this.animateOpen();
    }
  }

  closeMenu() {
    const { isOpen } = this.state;
    if (isOpen) {
      this.setState({ isOpen: false });
      this.animateClose();
    }
  }

  animateOpen() {
    anime({
      targets: '.view-menu-container',
      height: [70, 500],
      width: `${MENU_WIDTH}px`,
      duration: 500,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 100,
    })
  }

  animateClose() {
    anime({
      targets: '.view-menu-container',
      height: [500, 70],
      duration: 500,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 100,
    })
  }

  animateUnDock(left, top) {
    anime({
      targets: '.view-menu-container',
      height: 500,
      width: 160,
      duration: 200,
      elasticity: 0,
      borderRadius: MENU_BORDER_RADIUS,
      easing: 'easeOutQuint',
      delay: 0,
    })
  }

  animateDockLeft() {
    anime({
      targets: '.view-menu-container',
      height: '100%',
      top: '0',
      left: '0',
      borderRadius: 0,
      duration: 300,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 0,
    })
  }

  animateDockTop() {
    anime({
      targets: '.view-menu-container',
      width: '100%',
      height: '70px',
      top: '0',
      left: '0px',
      borderRadius: 0,
      duration: 300,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 0,
    })
  }

  animateDockRight() {
    anime({
      targets: '.view-menu-container',
      height: '100%',
      top: '0',
      right: '0',
      borderRadius: 0,
      duration: 300,
      elasticity: 100,
      easing: 'easeOutQuint',
      delay: 0,
    })
  }

  handleMenuOpenToggleClick() {
    const { isOpen } = this.state;
    if (isOpen) {
      this.closeMenu();
    } else {
      this.openMenu();
    }
  }

  render() {
    const { menuPlacement: placement, menuX, menuY, width } = this.state;
    let position
    switch(placement) {
      case 'hasDockedLeft': {
        position = { x: 0, y: 0 };
        break;
      }
      case 'hasDockedTop': {
        position = { x: 0, y: 0 };
        break;
      }
      case 'hasDockedRight': {
        position = { x: (width - MENU_WIDTH), y: 0 };
        break;
      }
    }

    const positionProp = position ? { position } : {};
    console.log(positionProp)
    console.log('placmenet', placement)
    return (
      <Container>
      <PlacementOutline shouldShow={placement === 'willDockLeft'} height="100vh" width={`${MENU_WIDTH}px`} top="0" left="0"/>
      <PlacementOutline shouldShow={placement === 'willDockRight'} height="100vh" width={`${MENU_WIDTH}px`} top="0" right="0"/>
      <PlacementOutline shouldShow={placement === 'willDockTop'} height="70px" width="100vw" top="0" left="0"/>
      <Draggable
        handle=".view-menu-draggable-handle"
        axis="both"
        bounds="parent"
        defaultPosition={{ x: 50, y: 70 }}
        onStart={this.onStartDragEvent}
        onDrag={this.onDragEvent}
        onStop={this.onStopDragEvent}
        {...positionProp}
      >
        <Menu className="view-menu-container here" menuPlacement={placement}>
          <MenuControllerContainer menuPlacement={placement}>
            <MenuDraggableContainer menuPlacement={placement} className='view-menu-draggable-handle'>
              <DraggableIcon />
              <DraggableIcon />
              <DraggableIcon />
            </MenuDraggableContainer>
            <MenuShrinkContainer menuPlacement={placement} onClick={this.handleMenuOpenToggleClick}>
              <MenuShrinkButton />
            </MenuShrinkContainer>
          </MenuControllerContainer>
          <RouterContainer menuPlacement={placement}>
            <FAIcon menuPlacement={placement} leftOrRight="left" className="fas fa-home" />
            <FAIcon menuPlacement={placement} leftOrRight="right" className="fas fa-question" />
          </RouterContainer>
        </Menu>
      </Draggable>
      </Container>
    );
  }
}
<|endoftext|>


<commit_before>/**
 * Attributes allowed on input elements
 */
const allowedAttributes = [
  'autocapitalize',
  'autocomplete',
  'autocorrect',
  'autoFocus',
  'autosave',
  'disabled',
  'form',
  'formaction',
  'formenctype',
  'formmethod',
  'formnovalidate',
  'formtarget',
  'height',
  'id',
  'inputmode',
  'maxlength',
  'maxlength',
  'name',
  'pattern',
  'placeholder',
  'readonly',
  'required',
  'selectionDirection',
  'size',
  'spellcheck',
  'tabindex'
];

/**
 * Filter the properties for only allowed input properties
 * @param  {Object} props The properties to filter
 * @return {Object} The filtered, allowed properties
 */
export default function(props) {
  const attributes = {};

  allowedAttributes.forEach(allowedAttribute => {
    if (props[allowedAttribute]) {
      attributes[allowedAttribute] = props[allowedAttribute];
    }
  });

  return attributes;
}
<commit_msg>autocomplete -> autoComplete<commit_after>/**
 * Attributes allowed on input elements
 */
const allowedAttributes = [
  'autocapitalize',
  'autoComplete',
  'autocorrect',
  'autoFocus',
  'autosave',
  'disabled',
  'form',
  'formaction',
  'formenctype',
  'formmethod',
  'formnovalidate',
  'formtarget',
  'height',
  'id',
  'inputmode',
  'maxlength',
  'maxlength',
  'name',
  'pattern',
  'placeholder',
  'readonly',
  'required',
  'selectionDirection',
  'size',
  'spellcheck',
  'tabindex'
];

/**
 * Filter the properties for only allowed input properties
 * @param  {Object} props The properties to filter
 * @return {Object} The filtered, allowed properties
 */
export default function(props) {
  const attributes = {};

  allowedAttributes.forEach(allowedAttribute => {
    if (props[allowedAttribute]) {
      attributes[allowedAttribute] = props[allowedAttribute];
    }
  });

  return attributes;
}
<|endoftext|>