...(args.mode ? ['--mode', args.mode] : []),

...(args.rule ? ['--rule', args.rule] : []),

...(args.plugin ? ['--plugin', args.plugin] : []),

let patched = false
function patchWebpackChain () {
  if (patched) return

  const Config = require('webpack-chain')

  const toConfig = Config.prototype.toConfig
  Config.prototype.toConfig = function () {
    const config = toConfig.call(this)

    // inject plugin metadata
    const { entries: plugins, order: pluginNames } = this.plugins.order()
    config.plugins.forEach((p, i) => {
      Object.defineProperties(p, {
        __pluginName: {
          value: pluginNames[i]
        },
        __pluginArgs: {
          value: plugins[pluginNames[i]].get('args')
        }
      })
    })

    // inject rule metadata
    const { entries: rules, order: ruleNames } = this.module.rules.order()
    config.module.rules.forEach((rawRule, i) => {
      const ruleName = ruleNames[i]
      const rule = rules[ruleName]
      Object.defineProperties(rawRule, {
        __ruleName: {
          value: ruleName
        }
      })

      if (rawRule.oneOf) {
        const { entries: oneOfs, order: oneOfNames } = rule.oneOfs.order()
        rawRule.oneOf.forEach((o, i) => {
          const oneOfName = oneOfNames[i]
          const oneOf = oneOfs[oneOfName]
          Object.defineProperties(o, {
            __ruleName: {
              value: ruleName
            },
            __oneOfName: {
              value: oneOfName
            }
          })
          patchUse(oneOf, ruleName, oneOfName, o)
        })
      }

      patchUse(rule, ruleName, null, rawRule)
    })

    return config
  }

  patched = true
}

function patchUse (rule, ruleName, oneOfName, rawRule) {
  if (Array.isArray(rawRule.use)) {
    const { order: useNames } = rule.uses.order()
    rawRule.use.forEach((use, i) => {
      Object.defineProperties(use, {
        __ruleName: {
          value: ruleName
        },
        __oneOfName: {
          value: oneOfName
        },
        __useName: {
          value: useNames[i]
        }
      })
    })
  }
}

module.exports = (api, options) => {
  api.registerCommand('inspect', {
    description: 'inspect internal webpack config',
    usage: 'vue-cli-service inspect [options] [...paths]',
    options: {
      '--mode': 'specify env mode (default: development)',
      '--rule': 'inspect a specific module rule',
      '--plugin': 'inspect a specific plugin',
      '--verbose': 'show full function definitions in output'
    }
  }, args => {
    patchWebpackChain()

    const get = require('get-value')
    const stringify = require('javascript-stringify')
    const config = api.resolveWebpackConfig()
    const paths = args._

    let res
    if (args.rule) {
      res = config.module.rules.find(r => r.__ruleName === args.rule)
    } else if (args.plugin) {
      res = config.plugins.find(p => p.__pluginName === args.plugin)
    } else if (paths.length > 1) {
      res = {}
      paths.forEach(path => {
        res[path] = get(config, path)
      })
    } else if (paths.length === 1) {
      res = get(config, paths[0])
    } else {
      res = config
    }

    const pluginRE = /(?:function|class) (\w+Plugin)/
    const output = stringify(res, (value, indent, stringify) => {
      // shorten long functions
      if (
        !args.verbose &&
        typeof value === 'function' &&
        value.toString().length > 100
      ) {
        return `function () { /* omitted long function */ }`
      }

      // improve plugin output
      if (value && value.__pluginName) {
        let match = (
          value.constructor &&
          value.constructor.toString().match(pluginRE)
        )
        // copy-webpack-plugin
        if (value.__pluginName === 'copy') {
          match = [null, `CopyWebpackPlugin`]
        }
        const name = match[1]
        const prefix = `/* config.plugin('${value.__pluginName}') */\n`

        if (name) {
          return prefix + `new ${name}(${
            value.__pluginArgs.map(arg => stringify(arg)).join(',\n')
          })`
        } else {
          return prefix + stringify({
            args: value.__pluginArgs || []
          })
        }
      }

      // improve rule output
      if (value && value.__ruleName) {
        const prefix = `/* config.module.rule('${value.__ruleName}')${
          value.__oneOfName ? `.oneOf('${value.__oneOfName}')` : ``
        }${
          value.__useName ? `.use('${value.__useName}')` : ``
        } */\n`
        return prefix + stringify(value)
      }

      return stringify(value)
    }, 2)

    console.log(output)
  })
}

module.exports.defaultModes = {
  inspect: 'development'
}


module.exports = cli => {
  const chalk = require('chalk')
  const { hasGit } = require('@vue/cli-shared-utils')

  cli.injectFeature({
    name: 'Linter / Formatter',
    value: 'linter',
    short: 'Linter'
  })

  cli.injectPrompt({
    name: 'eslintConfig',
    when: answers => answers.features.includes('linter'),
    type: 'list',
    message: 'Pick a linter / formatter config:',
    choices: answers => [
      ...(
        answers.features.includes('ts')
          ? [{
            name: `TSLint`,
            value: 'tslint',
            short: 'TSLint'
          }]
          : []
      ),
      {
        name: 'ESLint with error prevention only',
        value: 'base',
        short: 'Basic'
      },
      {
        name: 'ESLint + Airbnb config',
        value: 'airbnb',
        short: 'Airbnb'
      },
      {
        name: 'ESLint + Standard config',
        value: 'standard',
        short: 'Standard'
      },
      {
        name: 'ESLint + Prettier',
        value: 'prettier',
        short: 'Prettier'
      }
    ]
  })

  cli.injectPrompt({
    name: 'lintOn',
    message: 'Pick additional lint features:',
    when: answers => answers.features.includes('linter'),
    type: 'checkbox',
    choices: [
      {
        name: 'Lint on save',
        value: 'save'
      },
      {
        name: 'Lint and fix on commit' + (hasGit() ? '' : chalk.red(' (requires Git)')),
        value: 'commit'
      }
    ]
  })

  cli.onPromptComplete((answers, options) => {
    if (answers.features.includes('linter') && answers.eslintConfig !== 'tslint') {
      options.plugins['@vue/cli-plugin-eslint'] = {
        config: answers.eslintConfig,
        lintOn: answers.lintOn
      }
    }
  })
}


[
  'env',
  'logger',
  'spinner',
  'validate',
  'openBrowser',
  'pluginResolution'
].forEach(m => {
  Object.assign(exports, require(`./lib/${m}`))
})


const AUTHORIZE_URL = 'https://foo.com/authorizeAuthCode';

const REDIRECT_URI = 'https://foo.com/redirect';

const AUDIENCE = 'https://foo.com/userinfo';

// @flow
import getAccessTokenAuthorizationCode from './grant-authorization-code';
import getAccessTokenClientCredentials from './grant-client-credentials';
import getAccessTokenPassword from './grant-password';
import getAccessTokenImplicit from './grant-implicit';
import refreshAccessToken from './refresh-token';
import {
  GRANT_TYPE_AUTHORIZATION_CODE,
  GRANT_TYPE_CLIENT_CREDENTIALS,
  GRANT_TYPE_IMPLICIT,
  GRANT_TYPE_PASSWORD,
  P_ACCESS_TOKEN,
  P_ERROR,
  P_ERROR_DESCRIPTION,
  P_ERROR_URI,
  P_EXPIRES_IN,
  P_REFRESH_TOKEN
} from './constants';
import * as models from '../../models';
import type { RequestAuthentication } from '../../models/request';
import type { OAuth2Token } from '../../models/o-auth-2-token';

/** Get an OAuth2Token object and also handle storing/saving/refreshing */
export default async function(
  requestId: string,
  authentication: RequestAuthentication,
  forceRefresh: boolean = false
): Promise<OAuth2Token | null> {
  switch (authentication.grantType) {
    case GRANT_TYPE_AUTHORIZATION_CODE:
      return _getOAuth2AuthorizationCodeHeader(
        requestId,
        authentication,
        forceRefresh
      );
    case GRANT_TYPE_CLIENT_CREDENTIALS:
      return _getOAuth2ClientCredentialsHeader(
        requestId,
        authentication,
        forceRefresh
      );
    case GRANT_TYPE_IMPLICIT:
      return _getOAuth2ImplicitHeader(requestId, authentication, forceRefresh);
    case GRANT_TYPE_PASSWORD:
      return _getOAuth2PasswordHeader(requestId, authentication, forceRefresh);
  }

  return null;
}

async function _getOAuth2AuthorizationCodeHeader(
  requestId: string,
  authentication: RequestAuthentication,
  forceRefresh: boolean
): Promise<OAuth2Token | null> {
  const oAuth2Token = await _getAccessToken(
    requestId,
    authentication,
    forceRefresh
  );

  if (oAuth2Token) {
    return oAuth2Token;
  }

  const results = await getAccessTokenAuthorizationCode(
    requestId,
    authentication.authorizationUrl,
    authentication.accessTokenUrl,
    authentication.credentialsInBody,
    authentication.clientId,
    authentication.clientSecret,
    authentication.redirectUrl,
    authentication.scope,
    authentication.state
  );

  return _updateOAuth2Token(requestId, results);
}

async function _getOAuth2ClientCredentialsHeader(
  requestId: string,
  authentication: RequestAuthentication,
  forceRefresh: boolean
): Promise<OAuth2Token | null> {
  const oAuth2Token = await _getAccessToken(
    requestId,
    authentication,
    forceRefresh
  );

  if (oAuth2Token) {
    return oAuth2Token;
  }

  const results = await getAccessTokenClientCredentials(
    requestId,
    authentication.accessTokenUrl,
    authentication.credentialsInBody,
    authentication.clientId,
    authentication.clientSecret,
    authentication.scope,
    authentication.audience
  );

  return _updateOAuth2Token(requestId, results);
}

async function _getOAuth2ImplicitHeader(
  requestId: string,
  authentication: RequestAuthentication,
  forceRefresh: boolean
): Promise<OAuth2Token | null> {
  const oAuth2Token = await _getAccessToken(
    requestId,
    authentication,
    forceRefresh
  );

  if (oAuth2Token) {
    return oAuth2Token;
  }

  const results = await getAccessTokenImplicit(
    requestId,
    authentication.authorizationUrl,
    authentication.clientId,
    authentication.responseType,
    authentication.redirectUrl,
    authentication.scope,
    authentication.state
  );

  return _updateOAuth2Token(requestId, results);
}

async function _getOAuth2PasswordHeader(
  requestId: string,
  authentication: RequestAuthentication,
  forceRefresh: boolean
): Promise<OAuth2Token | null> {
  const oAuth2Token = await _getAccessToken(
    requestId,
    authentication,
    forceRefresh
  );

  if (oAuth2Token) {
    return oAuth2Token;
  }

  const results = await getAccessTokenPassword(
    requestId,
    authentication.accessTokenUrl,
    authentication.credentialsInBody,
    authentication.clientId,
    authentication.clientSecret,
    authentication.username,
    authentication.password,
    authentication.scope
  );

  return _updateOAuth2Token(requestId, results);
}

async function _getAccessToken(
  requestId: string,
  authentication: RequestAuthentication,
  forceRefresh: boolean
): Promise<OAuth2Token | null> {
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
  // See if we have a token already //
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

  let token: OAuth2Token | null = await models.oAuth2Token.getByParentId(
    requestId
  );

  if (!token) {
    return null;
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
  // Check if the token needs refreshing //
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

  // Refresh tokens are part of Auth Code, Password
  const expiresAt = token.expiresAt || Infinity;
  const isExpired = Date.now() > expiresAt;

  if (!isExpired && !forceRefresh) {
    return token;
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
  // Refresh the token if necessary //
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

  // We've expired, but don't have a refresh token, so tell caller to fetch new
  // access token
  if (!token.refreshToken) {
    return null;
  }

  const refreshResults = await refreshAccessToken(
    requestId,
    authentication.accessTokenUrl,
    authentication.credentialsInBody,
    authentication.clientId,
    authentication.clientSecret,
    token.refreshToken,
    authentication.scope
  );

  // ~~~~~~~~~~~~~ //
  // Update the DB //
  // ~~~~~~~~~~~~~ //

  return _updateOAuth2Token(requestId, refreshResults);
}

async function _updateOAuth2Token(
  requestId: string,
  authResults: Object
): Promise<OAuth2Token> {
  const oAuth2Token = await models.oAuth2Token.getOrCreateByParentId(requestId);

  // Calculate expiry date
  const expiresIn = authResults[P_EXPIRES_IN];
  const expiresAt = expiresIn ? Date.now() + expiresIn * 1000 : null;

  return models.oAuth2Token.update(oAuth2Token, {
    expiresAt,
    refreshToken: authResults[P_REFRESH_TOKEN] || null,
    accessToken: authResults[P_ACCESS_TOKEN] || null,
    error: authResults[P_ERROR] || null,
    errorDescription: authResults[P_ERROR_DESCRIPTION] || null,
    errorUri: authResults[P_ERROR_URI] || null
  });
}


// @flow
import type { Plugin } from '../index';
import * as models from '../../models';

export function init(plugin: Plugin) {
  return {
    store: {
      async hasItem(key: string): Promise<boolean> {
        const doc = await models.pluginData.getByKey(plugin.name, key);
        return doc !== null;
      },
      async setItem(key: string, value: string): Promise<void> {
        await models.pluginData.upsertByKey(plugin.name, key, String(value));
      },
      async getItem(key: string): Promise<string | null> {
        const doc = await models.pluginData.getByKey(plugin.name, key);
        return doc ? doc.value : null;
      },
      async removeItem(key: string): Promise<void> {
        await models.pluginData.removeByKey(plugin.name, key);
      }
    }
  };
}


import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import autobind from 'autobind-decorator';
import { Cookie } from 'tough-cookie';

@autobind
class ResponseCookiesViewer extends PureComponent {
  renderRow(h, i) {
    let cookie = null;
    try {
      cookie = h ? Cookie.parse(h.value || '') : null;
    } catch (err) {
      console.warn('Failed to parse set-cookie header', h);
    }

    const blank = --;
    return (

        {cookie ? cookie.key : blank}
        {cookie ? cookie.value : blank}

    );
  }

  render() {
    const {
      headers,
      showCookiesModal,
      cookiesSent,
      cookiesStored
    } = this.props;

    const notifyNotStored = !cookiesStored && headers.length;

    let noticeMessage = null;
    if (!cookiesSent && notifyNotStored) {
      noticeMessage = 'sending and storing';
    } else if (!cookiesSent) {
      noticeMessage = 'sending';
    } else if (notifyNotStored) {
      noticeMessage = 'storing';
    }

    return (

        {noticeMessage && (

              Automatic {noticeMessage} of cookies was disabled at the time this
              request was made

        )}

              Name
              Value

            {!headers.length
              ? this.renderRow(null, -1)
              : headers.map(this.renderRow)}

          <button
            className="pull-right btn btn--clicky"
            onClick={e => showCookiesModal()}>
            Manage Cookies
          </button>

    );
  }
}

ResponseCookiesViewer.propTypes = {
  showCookiesModal: PropTypes.func.isRequired,
  cookiesSent: PropTypes.bool.isRequired,
  cookiesStored: PropTypes.bool.isRequired,
  headers: PropTypes.array.isRequired,
  handleShowRequestSettings: PropTypes.func.isRequired
};

export default ResponseCookiesViewer;


// @flow
import * as c from './constants';
import {
  buildQueryStringFromParams,
  joinUrlAndQueryString
} from 'insomnia-url';
import { responseToObject, authorizeUserInWindow } from './misc';

export default async function(
  requestId: string,
  authorizationUrl: string,
  clientId: string,
  responseType: string = c.RESPONSE_TYPE_TOKEN,
  redirectUri: string = '',
  scope: string = '',
  state: string = ''
): Promise<Object> {
  const params = [
    { name: c.P_RESPONSE_TYPE, value: responseType },
    { name: c.P_CLIENT_ID, value: clientId }
  ];

  // Add optional params
  if (
    responseType === c.RESPONSE_TYPE_ID_TOKEN_TOKEN ||
    responseType === c.RESPONSE_TYPE_ID_TOKEN
  ) {
    const nonce = Math.floor(Math.random() * 9999999999999) + 1;
    params.push({ name: c.P_NONCE, value: nonce });
  }

  redirectUri && params.push({ name: c.P_REDIRECT_URI, value: redirectUri });
  scope && params.push({ name: c.P_SCOPE, value: scope });
  state && params.push({ name: c.P_STATE, value: state });

  // Add query params to URL
  const qs = buildQueryStringFromParams(params);
  const finalUrl = joinUrlAndQueryString(authorizationUrl, qs);

  const redirectedTo = await authorizeUserInWindow(
    finalUrl,
    /(access_token=)/,
    /(error=)/
  );
  const fragment = redirectedTo.split('#')[1];

  if (fragment) {
    return responseToObject(fragment, [
      c.P_ACCESS_TOKEN,
      c.P_TOKEN_TYPE,
      c.P_EXPIRES_IN,
      c.P_SCOPE,
      c.P_STATE,
      c.P_ERROR,
      c.P_ERROR_DESCRIPTION,
      c.P_ERROR_URI
    ]);
  } else {
    // Bad redirect
    return {};
  }
}


import * as renderUtils from '../render';
import * as models from '../../models';
import { globalBeforeEach } from '../../__jest__/before-each';

jest.mock('electron');

describe('render()', () => {
  beforeEach(globalBeforeEach);
  it('renders hello world', async () => {
    const rendered = await renderUtils.render('Hello {{ msg }}!', {
      msg: 'World'
    });
    expect(rendered).toBe('Hello World!');
  });

  it('renders custom tag: uuid', async () => {
    const rendered = await renderUtils.render('Hello {% uuid %}!');
    expect(rendered).toMatch(
      /Hello [a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}!/
    );
  });

  it('renders custom tag: timestamp', async () => {
    const rendered = await renderUtils.render('Hello {% timestamp %}!');
    expect(rendered).toMatch(/Hello \d{13}!/);
  });

  it('fails on invalid template', async () => {
    try {
      await renderUtils.render('Hello {{ msg }!', { msg: 'World' });
      fail('Render should have failed');
    } catch (err) {
      expect(err.message).toContain('expected variable end');
    }
  });
});

describe('buildRenderContext()', () => {
  beforeEach(globalBeforeEach);
  it('cascades properly', async () => {
    const ancestors = [
      {
        type: models.requestGroup.type,
        environment: { foo: 'parent', ancestor: true }
      },
      {
        type: models.requestGroup.type,
        environment: { foo: 'grandparent', ancestor: true }
      }
    ];

    const rootEnvironment = {
      type: models.environment.type,
      data: { foo: 'root', root: true }
    };

    const subEnvironment = {
      type: models.environment.type,
      data: { foo: 'sub', sub: true }
    };

    const context = await renderUtils.buildRenderContext(
      ancestors,
      rootEnvironment,
      subEnvironment
    );

    expect(context).toEqual({
      foo: 'parent',
      ancestor: true,
      root: true,
      sub: true
    });
  });

  it('rendered recursive should not infinite loop', async () => {
    const ancestors = [
      {
        // Sub Environment
        type: models.requestGroup.type,
        environment: { recursive: '{{ recursive }}/hello' }
      }
    ];

    const context = await renderUtils.buildRenderContext(ancestors);

    // This is longer than 3 because it multiplies every time (1 -> 2 -> 4 -> 8)
    expect(context).toEqual({
      recursive:
        '{{ recursive }}/hello/hello/hello/hello/hello/hello/hello/hello'
    });
  });

  it('render up to 3 recursion levels', async () => {
    const ancestors = [
      {
        // Sub Environment
        type: models.requestGroup.type,
        environment: {
          d: '/d',
          c: '/c{{ d }}',
          b: '/b{{ c }}',
          a: '/a{{ b }}',
          test: 'http://insomnia.rest{{ a }}'
        }
      }
    ];

    const context = await renderUtils.buildRenderContext(ancestors);

    expect(context).toEqual({
      d: '/d',
      c: '/c/d',
      b: '/b/c/d',
      a: '/a/b/c/d',
      test: 'http://insomnia.rest/a/b/c/d'
    });
  });

  it('rendered sibling environment variables', async () => {
    const ancestors = [
      {
        // Sub Environment
        type: models.requestGroup.type,
        environment: {
          sibling: 'sibling',
          test: '{{ sibling }}/hello'
        }
      }
    ];

    const context = await renderUtils.buildRenderContext(ancestors);

    expect(context).toEqual({ sibling: 'sibling', test: 'sibling/hello' });
  });

  it('rendered parent environment variables', async () => {
    const ancestors = [
      {
        name: 'Parent',
        type: models.requestGroup.type,
        environment: {
          test: '{{ grandparent }} parent'
        }
      },
      {
        name: 'Grandparent',
        type: models.requestGroup.type,
        environment: {
          grandparent: 'grandparent'
        }
      }
    ];

    const context = await renderUtils.buildRenderContext(ancestors);

    expect(context).toEqual({
      grandparent: 'grandparent',
      test: 'grandparent parent'
    });
  });

  it('rendered parent same name environment variables', async () => {
    const ancestors = [
      {
        name: 'Parent',
        type: models.requestGroup.type,
        environment: {
          base_url: '{{ base_url }}/resource'
        }
      },
      {
        name: 'Grandparent',
        type: models.requestGroup.type,
        environment: {
          base_url: 'https://insomnia.rest'
        }
      }
    ];

    const context = await renderUtils.buildRenderContext(ancestors);

    expect(context).toEqual({ base_url: 'https://insomnia.rest/resource' });
  });

  it('rendered parent, ignoring sibling environment variables', async () => {
    const ancestors = [
      {
        name: 'Parent',
        type: models.requestGroup.type,
        environment: {
          host: 'parent.com'
        }
      },
      {
        name: 'Grandparent',
        type: models.requestGroup.type,
        environment: {
          host: 'grandparent.com',
          node: {
            admin: 'admin',
            test: 'test',
            port: 8080
          },
          urls: {
            admin: 'https://{{ host }}/{{ node.admin }}',
            test: 'https://{{ host }}/{{ node.test }}'
          }
        }
      }
    ];

    const context = await renderUtils.buildRenderContext(ancestors);
    expect(await renderUtils.render('{{ urls.admin }}/foo', context)).toBe(
      'https://parent.com/admin/foo'
    );
    expect(await renderUtils.render('{{ urls.test }}/foo', context)).toBe(
      'https://parent.com/test/foo'
    );
  });

  it('renders child environment variables', async () => {
    const ancestors = [
      {
        name: 'Parent',
        type: models.requestGroup.type,
        environment: {
          parent: 'parent'
        }
      },
      {
        name: 'Grandparent',
        type: models.requestGroup.type,
        environment: {
          test: '{{ parent }} grandparent'
        }
      }
    ];

    const context = await renderUtils.buildRenderContext(ancestors);

    expect(context).toEqual({ parent: 'parent', test: 'parent grandparent' });
  });

  it('cascades properly and renders', async () => {
    const ancestors = [
      {
        type: models.requestGroup.type,
        environment: {
          url: '{{ base_url }}/resource',
          ancestor: true,
          winner: 'folder parent'
        }
      },
      {
        type: models.requestGroup.type,
        environment: {
          ancestor: true,
          winner: 'folder grandparent'
        }
      }
    ];

    const subEnvironment = {
      type: models.environment.type,
      data: { winner: 'sub', sub: true, base_url: 'https://insomnia.rest' }
    };

    const rootEnvironment = {
      type: models.environment.type,
      data: { winner: 'root', root: true, base_url: 'ignore this' }
    };

    const context = await renderUtils.buildRenderContext(
      ancestors,
      rootEnvironment,
      subEnvironment
    );

    expect(context).toEqual({
      base_url: 'https://insomnia.rest',
      url: 'https://insomnia.rest/resource',
      ancestor: true,
      winner: 'folder parent',
      root: true,
      sub: true
    });
  });

  it('handles variables being used in tags', async () => {
    const rootEnvironment = {
      type: models.environment.type,
      data: {
        hash_input: '{{ orderId }}{{ secret }}',
        hash_input_expected: '123456789012345ThisIsATopSecretValue',
        orderId: 123456789012345,
        password: "{% hash 'sha512', 'hex', hash_input %}",
        password_expected: "{% hash 'sha512', 'hex', hash_input_expected %}",
        secret: 'ThisIsATopSecretValue'
      }
    };

    const context = await renderUtils.buildRenderContext([], rootEnvironment);

    expect(context).toEqual({
      hash_input: '123456789012345ThisIsATopSecretValue',
      hash_input_expected: '123456789012345ThisIsATopSecretValue',
      orderId: 123456789012345,
      password:
        'ea84d15f33d3f9e9098fe01659b1ea0599d345770bba20ba98bf9056676a83ffe6b5528b2451ad04badbf690cf3009a94c510121cc6897045f8bb4ba0826134c',
      password_expected:
        'ea84d15f33d3f9e9098fe01659b1ea0599d345770bba20ba98bf9056676a83ffe6b5528b2451ad04badbf690cf3009a94c510121cc6897045f8bb4ba0826134c',
      secret: 'ThisIsATopSecretValue'
    });
  });

  it('works with minimal parameters', async () => {
    const ancestors = null;
    const rootEnvironment = null;
    const subEnvironment = null;

    const context = await renderUtils.buildRenderContext(
      ancestors,
      rootEnvironment,
      subEnvironment
    );

    expect(context).toEqual({});
  });
});

describe('render()', () => {
  beforeEach(globalBeforeEach);
  it('correctly renders simple Object', async () => {
    const newObj = await renderUtils.render(
      {
        foo: '{{ foo }}',
        bar: 'bar',
        baz: '{{ bad }}'
      },
      { foo: 'bar', bad: 'hi' }
    );

    expect(newObj).toEqual({
      foo: 'bar',
      bar: 'bar',
      baz: 'hi'
    });
  });

  it('correctly renders complex Object', async () => {
    const d = new Date();
    const obj = {
      foo: '{{ foo }}',
      null: null,
      bool: true,
      date: d,
      undef: undefined,
      num: 1234,
      nested: {
        foo: '{{ foo }}',
        arr: [1, 2, '{{ foo }}']
      }
    };

    const newObj = await renderUtils.render(obj, { foo: 'bar' });

    expect(newObj).toEqual({
      foo: 'bar',
      null: null,
      bool: true,
      date: d,
      undef: undefined,
      num: 1234,
      nested: {
        foo: 'bar',
        arr: [1, 2, 'bar']
      }
    });

    // Make sure original request isn't changed
    expect(obj.foo).toBe('{{ foo }}');
    expect(obj.nested.foo).toBe('{{ foo }}');
    expect(obj.nested.arr[2]).toBe('{{ foo }}');
  });

  it('fails on bad template', async () => {
    try {
      await renderUtils.render(
        {
          foo: '{{ foo }',
          bar: 'bar',
          baz: '{{ bad }}'
        },
        { foo: 'bar' }
      );
      fail('Render should have failed');
    } catch (err) {
      expect(err.message).toContain('expected variable end');
    }
  });

  it('keep on error setting', async () => {
    const template = '{{ foo }} {% invalid "hi" %}';
    const context = { foo: 'bar' };

    const resultOnlyVars = await renderUtils.render(
      template,
      context,
      null,
      renderUtils.KEEP_ON_ERROR
    );

    expect(resultOnlyVars).toBe('{{ foo }} {% invalid "hi" %}');
    try {
      await renderUtils.render(template, context, null);
      fail('Render should not have succeeded');
    } catch (err) {
      expect(err.message).toBe('unknown block tag: invalid');
    }
  });

  it('outputs correct error path', async () => {
    const template = {
      foo: [{ bar: '{% foo %}' }]
    };

    try {
      await renderUtils.render(template);
      fail('Should have failed to render');
    } catch (err) {
      expect(err.path).toBe('foo[0].bar');
    }
  });

  it('outputs correct error path when private first node', async () => {
    const template = {
      _foo: { _bar: { baz: '{% foo %}' } }
    };

    try {
      await renderUtils.render(template);
      fail('Should have failed to render');
    } catch (err) {
      expect(err.path).toBe('_bar.baz');
    }
  });
});


var client = new RestClient("http://mockbin.com/har");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"number\":1,\"string\":\"f\\\"oo\",\"arr\":[1,2,3],\"nested\":{\"a\":\"b\"},\"arr_mix\":[1,\"a\",{\"arr_mix_nested\":{}}],\"boolean\":false}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);


import * as crypt from '../crypt';
import { globalBeforeEach } from '../../__jest__/before-each';

describe('deriveKey()', () => {
  beforeEach(globalBeforeEach);
  it('derives a key properly', async () => {
    const result = await crypt.deriveKey('Password', 'email', 'salt');

    const expected = '';

    expect(result).toBe(expected);
  });
});

describe('encryptRSA', () => {
  beforeEach(globalBeforeEach);
  it('encrypts and decrypts', () => {
    const resultEncrypted = crypt.encryptAES(
      'rawkey',
      'Hello World!',
      'additional data'
    );
    const resultDecrypted = crypt.decryptAES('rawkey', resultEncrypted);

    const expectedEncrypted = {
      ad: '6164646974696f6e616c2064617461',
      d: '48656c6c6f253230576f726c6421',
      iv: '616161616161616161616161',
      t: '746167'
    };

    const expectedDecrypted = 'Hello World!';

    expect(resultEncrypted).toEqual(expectedEncrypted);
    expect(resultDecrypted).toEqual(expectedDecrypted);
  });
});


keep keep keep keep keep replace keep keep keep keep keep


curl 'http://requestb.in/api/v1/bins' -H 'Cookie: __cfduid=d9e3031f00abce97dfdf7119a2d4620cc1478677611; _gat=1; session=eyJyZWNlbnQiOlsiMTlwd3g5NzEiLCIxYTNsaHg2MSJdfQ.CxF25Q.WfyUPLe9lQjtibrpD55c2gOD-YA; _ga=GA1.2.525721040.1478677612' -H 'Origin: http://requestb.in' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Accept: */*' -H 'Referer: http://requestb.in/' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' --data 'private=false' --compressed


import * as renderer from '../renderer';
import { globalBeforeEach } from '../__jest__/before-each';

describe('imports', () => {
  beforeEach(globalBeforeEach);
  it('ui module should import successfully', () => {
    expect(renderer).toBeDefined();
  });
});


/* global it */

'use strict';

require('should');

module.exports = function(HTTPSnippet, fixtures) {
  it('should ask for verbose output', function() {
    var result = new HTTPSnippet(fixtures.requests.short).convert(
      'shell',
      'httpie',
      {
        indent: false,
        verbose: true
      }
    );

    result.should.be.a.String;
    result.should.eql('http --verbose GET http://mockbin.com/har');
  });

  it('should use short flags', function() {
    var result = new HTTPSnippet(fixtures.requests.short).convert(
      'shell',
      'httpie',
      {
        body: true,
        cert: 'foo',
        headers: true,
        indent: false,
        pretty: 'x',
        print: 'x',
        short: true,
        style: 'x',
        timeout: 1,
        verbose: true,
        verify: 'x'
      }
    );

    result.should.be.a.String;
    result.should.eql(
      'http -h -b -v -p=x --verify=x --cert=foo --pretty=x --style=x --timeout=1 GET http://mockbin.com/har'
    );
  });

  it('should use long flags', function() {
    var result = new HTTPSnippet(fixtures.requests.short).convert(
      'shell',
      'httpie',
      {
        body: true,
        cert: 'foo',
        headers: true,
        indent: false,
        pretty: 'x',
        print: 'x',
        style: 'x',
        timeout: 1,
        verbose: true,
        verify: 'x'
      }
    );

    result.should.be.a.String;
    result.should.eql(
      'http --headers --body --verbose --print=x --verify=x --cert=foo --pretty=x --style=x --timeout=1 GET http://mockbin.com/har'
    );
  });

  it('should use custom indentation', function() {
    var result = new HTTPSnippet(fixtures.requests.full).convert(
      'shell',
      'httpie',
      {
        indent: '@'
      }
    );

    result.should.be.a.String;
    result
      .replace(/\\\n/g, '')
      .should.eql(
        "http --form POST 'http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value' @accept:application/json @content-type:application/x-www-form-urlencoded @cookie:'foo=bar; bar=baz' @foo=bar"
      );
  });

  it('should use queryString parameters', function() {
    var result = new HTTPSnippet(fixtures.requests.query).convert(
      'shell',
      'httpie',
      {
        indent: false,
        queryParams: true
      }
    );

    result.should.be.a.String;
    result
      .replace(/\\\n/g, '')
      .should.eql(
        'http GET http://mockbin.com/har foo==bar foo==baz baz==abc key==value'
      );
  });

  it('should build parameterized output of query string', function() {
    var result = new HTTPSnippet(fixtures.requests.query).convert(
      'shell',
      'httpie',
      {
        indent: false,
        queryParams: true
      }
    );

    result.should.be.a.String;
    result
      .replace(/\\\n/g, '')
      .should.eql(
        'http GET http://mockbin.com/har foo==bar foo==baz baz==abc key==value'
      );
  });

  it('should build parameterized output of post data', function() {
    var result = new HTTPSnippet(
      fixtures.requests['application-form-encoded']
    ).convert('shell', 'httpie', {
      short: true,
      indent: false,
      queryParams: true
    });

    result.should.be.a.String;
    result
      .replace(/\\\n/g, '')
      .should.eql(
        'http -f POST http://mockbin.com/har content-type:application/x-www-form-urlencoded foo=bar hello=world'
      );
  });
};


responseType: string = c.RESPONSE_TYPE_TOKEN,

{ name: c.P_RESPONSE_TYPE, value: responseType },

{ name: c.P_CLIENT_ID, value: clientId }

keep keep keep keep keep replace keep keep keep keep

state: string = '',
audience: string = ''


import Foundation

let headers = ["content-type": "multipart/form-data; boundary=---011000010111000001101001"]
let parameters = [
  [
    "name": "foo",
    "value": "Hello World",
    "fileName": "hello.txt",
    "contentType": "text/plain"
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "http://mockbin.com/har")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()


import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';

class ModalBody extends PureComponent {
  render() {
    const { className, children, noScroll, ...props } = this.props;
    const classes = classnames(className, 'modal__body', {
      'modal__body--no-scroll': noScroll
    });

    return (
      <div className={classes} {...props}>
        {children}
      </div>
    );
  }
}

ModalBody.propTypes = {
  noScroll: PropTypes.bool,
  className: PropTypes.string,
  children: PropTypes.node
};

export default ModalBody;


import Foundation

let headers = [
  "cookie": "foo=bar; bar=baz",
  "accept": "application/json",
  "content-type": "application/x-www-form-urlencoded"
]

let postData = NSMutableData(data: "foo=bar".data(using: String.Encoding.utf8)!)

let request = NSMutableURLRequest(url: NSURL(string: "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()


redirectUri && params.push({ name: c.P_REDIRECT_URI, value: redirectUri });

scope && params.push({ name: c.P_SCOPE, value: scope });

state && params.push({ name: c.P_STATE, value: state });

const qs = buildQueryStringFromParams(params);

audience && params.push({ name: c.P_AUDIENCE, value: audience });

import getToken from '../grant-implicit';
import { createBWRedirectMock } from './helpers';
import { globalBeforeEach } from '../../../__jest__/before-each';

// Mock some test things
const AUTHORIZE_URL = 'https://foo.com/authorizeAuthCode';
const CLIENT_ID = 'client_123';
const REDIRECT_URI = 'https://foo.com/redirect';
const SCOPE = 'scope_123';
const STATE = 'state_123';

describe('implicit', () => {
  beforeEach(globalBeforeEach);
  it('works in default case', async () => {
    createBWRedirectMock(
      `${REDIRECT_URI}#access_token=token_123&state=${STATE}&foo=bar`
    );

    const result = await getToken(
      AUTHORIZE_URL,
      CLIENT_ID,
      REDIRECT_URI,
      SCOPE,
      STATE
    );

    expect(result).toEqual({
      access_token: 'token_123',
      token_type: null,
      expires_in: null,
      scope: null,
      state: STATE,
      error: null,
      error_description: null,
      error_uri: null
    });
  });
});


import requests

url = "https://mockbin.com/har"

response = requests.request("GET", url)

print(response.text)


module.exports.setDefaults = function(obj) {
  if (!obj || !obj._type) {
    return obj;
  } else if (obj._type === 'request') {
    return module.exports.setDefaultsRequest(obj);
  } else if (obj._type === 'request_group') {
    return module.exports.setDefaultsRequestGroup(obj);
  } else if (obj._type === 'environment') {
    return module.exports.setDefaultsEnvironment(obj);
  } else {
    return obj;
  }
};

module.exports.setDefaultsRequest = function(request) {
  request.method = (request.method || 'GET').toUpperCase();
  return Object.assign(
    {
      parentId: '__WORKSPACE_ID__',
      name: 'Imported',
      url: '',
      body: '',
      method: 'GET',
      parameters: [],
      headers: [],
      authentication: {}
    },
    request
  );
};

module.exports.setDefaultsRequestGroup = function(requestGroup) {
  return Object.assign(
    {
      parentId: '__WORKSPACE_ID__',
      name: 'Imported',
      environment: {}
    },
    requestGroup
  );
};

module.exports.setDefaultsEnvironment = function(environment) {
  return Object.assign(
    {
      parentId: '__BASE_ENVIRONMENT_ID__',
      name: 'Imported Environment',
      data: {}
    },
    environment
  );
};

module.exports.getDateString = function() {
  return new Date().toISOString();
};


advancedFields = [scope, credentialsInBody, tokenPrefix];

} else if (grantType === GRANT_TYPE_IMPLICIT) {

basicFields = [authorizationUrl, clientId, redirectUri, enabled];

advancedFields = [responseType, scope, state, tokenPrefix];

return { basic: basicFields, advanced: advancedFields };

keep keep keep keep replace keep keep keep keep keep

advancedFields = [responseType, scope, state, tokenPrefix, audience];


wget --quiet \
  --method GET \
  --output-document \
  - https://mockbin.com/har


<?php

$client = new http\Client;
$request = new http\Client\Request;

$body = new http\Message\Body;
$body->append('{"number":1,"string":"f\\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}');

$request->setRequestUrl('http://mockbin.com/har');
$request->setRequestMethod('POST');
$request->setBody($body);

$request->setHeaders(array(
  'content-type' => 'application/json'
));

$client->enqueue($request)->send();
$response = $client->getResponse();

echo $response->getBody();


open Cohttp_lwt_unix
open Cohttp
open Lwt

let uri = Uri.of_string "https://mockbin.com/har" in

Client.call `GET uri
>>= fun (res, body_stream) ->
  (* Do stuff with the result *)


keep keep keep keep add keep keep keep keep

* @return {Phaser.Animation} The animation instance.

/**
* @author       Richard Davey <rich@photonstorm.com>
* @copyright    2016 Photon Storm Ltd.
* @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

/**
* An Animation instance contains a single animation and the controls to play it.
*
* It is created by the AnimationManager, consists of Animation.Frame objects and belongs to a single Game Object such as a Sprite.
*
* @class Phaser.Animation
* @constructor
* @param {Phaser.Game} game - A reference to the currently running game.
* @param {Phaser.Sprite} parent - A reference to the owner of this Animation.
* @param {string} name - The unique name for this animation, used in playback commands.
* @param {Phaser.FrameData} frameData - The FrameData object that contains all frames used by this Animation.
* @param {number[]|string[]} frames - An array of numbers or strings indicating which frames to play in which order.
* @param {number} [frameRate=60] - The speed at which the animation should play. The speed is given in frames per second.
* @param {boolean} [loop=false] - Whether or not the animation is looped or just plays once.
*/
Phaser.Animation = function (game, parent, name, frameData, frames, frameRate, loop) {

    if (loop === undefined) { loop = false; }

    /**
    * @property {Phaser.Game} game - A reference to the currently running Game.
    */
    this.game = game;

    /**
    * @property {Phaser.Sprite} _parent - A reference to the parent Sprite that owns this Animation.
    * @private
    */
    this._parent = parent;

    /**
    * @property {Phaser.FrameData} _frameData - The FrameData the Animation uses.
    * @private
    */
    this._frameData = frameData;

    /**
    * @property {string} name - The user defined name given to this Animation.
    */
    this.name = name;

    /**
    * @property {array} _frames
    * @private
    */
    this._frames = [];
    this._frames = this._frames.concat(frames);

    /**
    * @property {number} delay - The delay in ms between each frame of the Animation, based on the given frameRate.
    */
    this.delay = 1000 / frameRate;

    /**
    * @property {boolean} loop - The loop state of the Animation.
    */
    this.loop = loop;

    /**
    * @property {number} loopCount - The number of times the animation has looped since it was last started.
    */
    this.loopCount = 0;

    /**
    * @property {boolean} killOnComplete - Should the parent of this Animation be killed when the animation completes?
    * @default
    */
    this.killOnComplete = false;

    /**
    * @property {boolean} isFinished - The finished state of the Animation. Set to true once playback completes, false during playback.
    * @default
    */
    this.isFinished = false;

    /**
    * @property {boolean} isPlaying - The playing state of the Animation. Set to false once playback completes, true during playback.
    * @default
    */
    this.isPlaying = false;

    /**
    * @property {boolean} isPaused - The paused state of the Animation.
    * @default
    */
    this.isPaused = false;

    /**
    * @property {boolean} _pauseStartTime - The time the animation paused.
    * @private
    * @default
    */
    this._pauseStartTime = 0;

    /**
    * @property {number} _frameIndex
    * @private
    * @default
    */
    this._frameIndex = 0;

    /**
    * @property {number} _frameDiff
    * @private
    * @default
    */
    this._frameDiff = 0;

    /**
    * @property {number} _frameSkip
    * @private
    * @default
    */
    this._frameSkip = 1;

    /**
    * @property {Phaser.Frame} currentFrame - The currently displayed frame of the Animation.
    */
    this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);

    /**
    * @property {Phaser.Signal} onStart - This event is dispatched when this Animation starts playback.
    */
    this.onStart = new Phaser.Signal();

    /**
    * This event is dispatched when the Animation changes frame.
    * By default this event is disabled due to its intensive nature. Enable it with: `Animation.enableUpdate = true`.
    * Note that the event is only dispatched with the current frame. In a low-FPS environment Animations
    * will automatically frame-skip to try and claw back time, so do not base your code on expecting to
    * receive a perfectly sequential set of frames from this event.
    * @property {Phaser.Signal|null} onUpdate
    * @default
    */
    this.onUpdate = null;

    /**
    * @property {Phaser.Signal} onComplete - This event is dispatched when this Animation completes playback. If the animation is set to loop this is never fired, listen for onLoop instead.
    */
    this.onComplete = new Phaser.Signal();

    /**
    * @property {Phaser.Signal} onLoop - This event is dispatched when this Animation loops.
    */
    this.onLoop = new Phaser.Signal();

    /**
     * @property {boolean} isReversed - Indicates if the animation will play backwards.
     * @default
     */
    this.isReversed = false;

    //  Set-up some event listeners
    this.game.onPause.add(this.onPause, this);
    this.game.onResume.add(this.onResume, this);

};

Phaser.Animation.prototype = {

    /**
    * Plays this animation.
    *
    * @method Phaser.Animation#play
    * @param {number} [frameRate=null] - The framerate to play the animation at. The speed is given in frames per second. If not provided the previously set frameRate of the Animation is used.
    * @param {boolean} [loop=false] - Should the animation be looped after playback. If not provided the previously set loop value of the Animation is used.
    * @param {boolean} [killOnComplete=false] - If set to true when the animation completes (only happens if loop=false) the parent Sprite will be killed.
    * @return {Phaser.Animation} - A reference to this Animation instance.
    */
    play: function (frameRate, loop, killOnComplete) {

        if (typeof frameRate === 'number')
        {
            //  If they set a new frame rate then use it, otherwise use the one set on creation
            this.delay = 1000 / frameRate;
        }

        if (typeof loop === 'boolean')
        {
            //  If they set a new loop value then use it, otherwise use the one set on creation
            this.loop = loop;
        }

        if (typeof killOnComplete !== 'undefined')
        {
            //  Remove the parent sprite once the animation has finished?
            this.killOnComplete = killOnComplete;
        }

        this.isPlaying = true;
        this.isFinished = false;
        this.paused = false;
        this.loopCount = 0;

        this._timeLastFrame = this.game.time.time;
        this._timeNextFrame = this.game.time.time + this.delay;

        this._frameIndex = this.isReversed ? this._frames.length - 1 : 0;
        this.updateCurrentFrame(false, true);

        this._parent.events.onAnimationStart$dispatch(this._parent, this);

        this.onStart.dispatch(this._parent, this);

        this._parent.animations.currentAnim = this;
        this._parent.animations.currentFrame = this.currentFrame;

        return this;

    },

    /**
    * Sets this animation back to the first frame and restarts the animation.
    *
    * @method Phaser.Animation#restart
    */
    restart: function () {

        this.isPlaying = true;
        this.isFinished = false;
        this.paused = false;
        this.loopCount = 0;

        this._timeLastFrame = this.game.time.time;
        this._timeNextFrame = this.game.time.time + this.delay;

        this._frameIndex = 0;

        this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);

        this._parent.setFrame(this.currentFrame);

        this._parent.animations.currentAnim = this;
        this._parent.animations.currentFrame = this.currentFrame;

        this.onStart.dispatch(this._parent, this);

    },

    /**
     * Reverses the animation direction
     *
     * @method Phaser.Animation#reverse
     * */
    reverse: function () {
        this.reversed = !this.reversed;
    },

    /**
     * Reverses the animation direction for the current/next animation only
     * Once the onComplete event is called this method will be called again and revert
     * the reversed state.
     *
     * @method Phaser.Animation#reverseOnce
     * */
    reverseOnce: function () {
        this.reverse();

        this.onComplete.addOnce(this.reverse.bind(this));
    },

    /**
    * Sets this animations playback to a given frame with the given ID.
    *
    * @method Phaser.Animation#setFrame
    * @param {string|number} [frameId] - The identifier of the frame to set. Can be the name of the frame, the sprite index of the frame, or the animation-local frame index.
    * @param {boolean} [useLocalFrameIndex=false] - If you provide a number for frameId, should it use the numeric indexes of the frameData, or the 0-indexed frame index local to the animation.
    */
    setFrame: function(frameId, useLocalFrameIndex) {

        var frameIndex;

        if (useLocalFrameIndex === undefined)
        {
            useLocalFrameIndex = false;
        }

        //  Find the index to the desired frame.
        if (typeof frameId === "string")
        {
            for (var i = 0; i < this._frames.length; i++)
            {
                if (this._frameData.getFrame(this._frames[i]).name === frameId)
                {
                    frameIndex = i;
                }
            }
        }
        else if (typeof frameId === "number")
        {
            if (useLocalFrameIndex)
            {
                frameIndex = frameId;
            }
            else
            {
                for (var i = 0; i < this._frames.length; i++)
                {
                    if (this._frames[i] === frameIndex)
                    {
                        frameIndex = i;
                    }
                }
            }
        }

        if (frameIndex)
        {
            //  Set the current frame index to the found index. Subtract 1 so that it animates to the desired frame on update.
            this._frameIndex = frameIndex - 1;

            //  Make the animation update at next update
            this._timeNextFrame = this.game.time.time;

            this.update();
        }

    },

    /**
    * Stops playback of this animation and set it to a finished state. If a resetFrame is provided it will stop playback and set frame to the first in the animation.
    * If `dispatchComplete` is true it will dispatch the complete events, otherwise they'll be ignored.
    *
    * @method Phaser.Animation#stop
    * @param {boolean} [resetFrame=false] - If true after the animation stops the currentFrame value will be set to the first frame in this animation.
    * @param {boolean} [dispatchComplete=false] - Dispatch the Animation.onComplete and parent.onAnimationComplete events?
    */
    stop: function (resetFrame, dispatchComplete) {

        if (resetFrame === undefined) { resetFrame = false; }
        if (dispatchComplete === undefined) { dispatchComplete = false; }

        this.isPlaying = false;
        this.isFinished = true;
        this.paused = false;

        if (resetFrame)
        {
            this.currentFrame = this._frameData.getFrame(this._frames[0]);
            this._parent.setFrame(this.currentFrame);
        }

        if (dispatchComplete)
        {
            this._parent.events.onAnimationComplete$dispatch(this._parent, this);
            this.onComplete.dispatch(this._parent, this);
        }

    },

    /**
    * Called when the Game enters a paused state.
    *
    * @method Phaser.Animation#onPause
    */
    onPause: function () {

        if (this.isPlaying)
        {
            this._frameDiff = this._timeNextFrame - this.game.time.time;
        }

    },

    /**
    * Called when the Game resumes from a paused state.
    *
    * @method Phaser.Animation#onResume
    */
    onResume: function () {

        if (this.isPlaying)
        {
            this._timeNextFrame = this.game.time.time + this._frameDiff;
        }

    },

    /**
    * Updates this animation. Called automatically by the AnimationManager.
    *
    * @method Phaser.Animation#update
    */
    update: function () {

        if (this.isPaused)
        {
            return false;
        }

        if (this.isPlaying && this.game.time.time >= this._timeNextFrame)
        {
            this._frameSkip = 1;

            //  Lagging?
            this._frameDiff = this.game.time.time - this._timeNextFrame;

            this._timeLastFrame = this.game.time.time;

            if (this._frameDiff > this.delay)
            {
                //  We need to skip a frame, work out how many
                this._frameSkip = Math.floor(this._frameDiff / this.delay);
                this._frameDiff -= (this._frameSkip * this.delay);
            }

            //  And what's left now?
            this._timeNextFrame = this.game.time.time + (this.delay - this._frameDiff);

            if (this.isReversed){
                this._frameIndex -= this._frameSkip;
            }else{
                this._frameIndex += this._frameSkip;
            }

            if (!this.isReversed && this._frameIndex >= this._frames.length || this.isReversed && this._frameIndex <= -1)
            {
                if (this.loop)
                {
                    // Update current state before event callback
                    this._frameIndex = Math.abs(this._frameIndex) % this._frames.length;

                    if (this.isReversed){
                        this._frameIndex = this._frames.length - 1 - this._frameIndex;
                    }

                    this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);

                    //  Instead of calling updateCurrentFrame we do it here instead
                    if (this.currentFrame)
                    {
                        this._parent.setFrame(this.currentFrame);
                    }

                    this.loopCount++;
                    this._parent.events.onAnimationLoop$dispatch(this._parent, this);
                    this.onLoop.dispatch(this._parent, this);

                    if (this.onUpdate)
                    {
                        this.onUpdate.dispatch(this, this.currentFrame);

                        // False if the animation was destroyed from within a callback
                        return !!this._frameData;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    this.complete();
                    return false;
                }
            }
            else
            {
                return this.updateCurrentFrame(true);
            }
        }

        return false;

    },

    /**
    * Changes the currentFrame per the _frameIndex, updates the display state,
    * and triggers the update signal.
    *
    * Returns true if the current frame update was 'successful', false otherwise.
    *
    * @method Phaser.Animation#updateCurrentFrame
    * @private
    * @param {boolean} signalUpdate - If true the `Animation.onUpdate` signal will be dispatched.
    * @param {boolean} fromPlay - Was this call made from the playing of a new animation?
    * @return {boolean} True if the current frame was updated, otherwise false.
    */
    updateCurrentFrame: function (signalUpdate, fromPlay) {

        if (fromPlay === undefined) { fromPlay = false; }

        if (!this._frameData)
        {
            // The animation is already destroyed, probably from a callback
            return false;
        }

        //  Previous index
        var idx = this.currentFrame.index;

        this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);

        if (this.currentFrame && (fromPlay || (!fromPlay && idx !== this.currentFrame.index)))
        {
            this._parent.setFrame(this.currentFrame);
        }

        if (this.onUpdate && signalUpdate)
        {
            this.onUpdate.dispatch(this, this.currentFrame);

            // False if the animation was destroyed from within a callback
            return !!this._frameData;
        }
        else
        {
            return true;
        }

    },

    /**
    * Advances by the given number of frames in the Animation, taking the loop value into consideration.
    *
    * @method Phaser.Animation#next
    * @param {number} [quantity=1] - The number of frames to advance.
    */
    next: function (quantity) {

        if (quantity === undefined) { quantity = 1; }

        var frame = this._frameIndex + quantity;

        if (frame >= this._frames.length)
        {
            if (this.loop)
            {
                frame %= this._frames.length;
            }
            else
            {
                frame = this._frames.length - 1;
            }
        }

        if (frame !== this._frameIndex)
        {
            this._frameIndex = frame;
            this.updateCurrentFrame(true);
        }

    },

    /**
    * Moves backwards the given number of frames in the Animation, taking the loop value into consideration.
    *
    * @method Phaser.Animation#previous
    * @param {number} [quantity=1] - The number of frames to move back.
    */
    previous: function (quantity) {

        if (quantity === undefined) { quantity = 1; }

        var frame = this._frameIndex - quantity;

        if (frame < 0)
        {
            if (this.loop)
            {
                frame = this._frames.length + frame;
            }
            else
            {
                frame++;
            }
        }

        if (frame !== this._frameIndex)
        {
            this._frameIndex = frame;
            this.updateCurrentFrame(true);
        }

    },

    /**
    * Changes the FrameData object this Animation is using.
    *
    * @method Phaser.Animation#updateFrameData
    * @param {Phaser.FrameData} frameData - The FrameData object that contains all frames used by this Animation.
    */
    updateFrameData: function (frameData) {

        this._frameData = frameData;
        this.currentFrame = this._frameData ? this._frameData.getFrame(this._frames[this._frameIndex % this._frames.length]) : null;

    },

    /**
    * Cleans up this animation ready for deletion. Nulls all values and references.
    *
    * @method Phaser.Animation#destroy
    */
    destroy: function () {

        if (!this._frameData)
        {
            // Already destroyed
            return;
        }

        this.game.onPause.remove(this.onPause, this);
        this.game.onResume.remove(this.onResume, this);

        this.game = null;
        this._parent = null;
        this._frames = null;
        this._frameData = null;
        this.currentFrame = null;
        this.isPlaying = false;

        this.onStart.dispose();
        this.onLoop.dispose();
        this.onComplete.dispose();

        if (this.onUpdate)
        {
            this.onUpdate.dispose();
        }

    },

    /**
    * Called internally when the animation finishes playback.
    * Sets the isPlaying and isFinished states and dispatches the onAnimationComplete event if it exists on the parent and local onComplete event.
    *
    * @method Phaser.Animation#complete
    */
    complete: function () {

        this._frameIndex = this._frames.length - 1;
        this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);

        this.isPlaying = false;
        this.isFinished = true;
        this.paused = false;

        this._parent.events.onAnimationComplete$dispatch(this._parent, this);

        this.onComplete.dispatch(this._parent, this);

        if (this.killOnComplete)
        {
            this._parent.kill();
        }

    }

};

Phaser.Animation.prototype.constructor = Phaser.Animation;

/**
* @name Phaser.Animation#paused
* @property {boolean} paused - Gets and sets the paused state of this Animation.
*/
Object.defineProperty(Phaser.Animation.prototype, 'paused', {

    get: function () {

        return this.isPaused;

    },

    set: function (value) {

        this.isPaused = value;

        if (value)
        {
            //  Paused
            this._pauseStartTime = this.game.time.time;
        }
        else
        {
            //  Un-paused
            if (this.isPlaying)
            {
                this._timeNextFrame = this.game.time.time + this.delay;
            }
        }

    }

});

/**
* @name Phaser.Animation#reversed
* @property {boolean} reversed - Gets and sets the isReversed state of this Animation.
*/
Object.defineProperty(Phaser.Animation.prototype, 'reversed', {

    get: function () {

        return this.isReversed;

    },

    set: function (value) {

        this.isReversed = value;

    }

});

/**
* @name Phaser.Animation#frameTotal
* @property {number} frameTotal - The total number of frames in the currently loaded FrameData, or -1 if no FrameData is loaded.
* @readonly
*/
Object.defineProperty(Phaser.Animation.prototype, 'frameTotal', {

    get: function () {
        return this._frames.length;
    }

});

/**
* @name Phaser.Animation#frame
* @property {number} frame - Gets or sets the current frame index and updates the Texture Cache for display.
*/
Object.defineProperty(Phaser.Animation.prototype, 'frame', {

    get: function () {

        if (this.currentFrame !== null)
        {
            return this.currentFrame.index;
        }
        else
        {
            return this._frameIndex;
        }

    },

    set: function (value) {

        this.currentFrame = this._frameData.getFrame(this._frames[value]);

        if (this.currentFrame !== null)
        {
            this._frameIndex = value;
            this._parent.setFrame(this.currentFrame);

            if (this.onUpdate)
            {
                this.onUpdate.dispatch(this, this.currentFrame);
            }
        }

    }

});

/**
* @name Phaser.Animation#speed
* @property {number} speed - Gets or sets the current speed of the animation in frames per second. Changing this in a playing animation will take effect from the next frame. Minimum value is 1.
*/
Object.defineProperty(Phaser.Animation.prototype, 'speed', {

    get: function () {

        return Math.round(1000 / this.delay);

    },

    set: function (value) {

        if (value >= 1)
        {
            this.delay = 1000 / value;
        }

    }

});

/**
* @name Phaser.Animation#enableUpdate
* @property {boolean} enableUpdate - Gets or sets if this animation will dispatch the onUpdate events upon changing frame.
*/
Object.defineProperty(Phaser.Animation.prototype, 'enableUpdate', {

    get: function () {

        return (this.onUpdate !== null);

    },

    set: function (value) {

        if (value && this.onUpdate === null)
        {
            this.onUpdate = new Phaser.Signal();
        }
        else if (!value && this.onUpdate !== null)
        {
            this.onUpdate.dispose();
            this.onUpdate = null;
        }

    }

});

/**
* Really handy function for when you are creating arrays of animation data but it's using frame names and not numbers.
* For example imagine you've got 30 frames named: 'explosion_0001-large' to 'explosion_0030-large'
* You could use this function to generate those by doing: Phaser.Animation.generateFrameNames('explosion_', 1, 30, '-large', 4);
*
* @method Phaser.Animation.generateFrameNames
* @static
* @param {string} prefix - The start of the filename. If the filename was 'explosion_0001-large' the prefix would be 'explosion_'.
* @param {number} start - The number to start sequentially counting from. If your frames are named 'explosion_0001' to 'explosion_0034' the start is 1.
* @param {number} stop - The number to count to. If your frames are named 'explosion_0001' to 'explosion_0034' the stop value is 34.
* @param {string} [suffix=''] - The end of the filename. If the filename was 'explosion_0001-large' the prefix would be '-large'.
* @param {number} [zeroPad=0] - The number of zeros to pad the min and max values with. If your frames are named 'explosion_0001' to 'explosion_0034' then the zeroPad is 4.
* @return {string[]} An array of framenames.
*/
Phaser.Animation.generateFrameNames = function (prefix, start, stop, suffix, zeroPad) {

    if (suffix === undefined) { suffix = ''; }

    var output = [];
    var frame = '';

    if (start < stop)
    {
        for (var i = start; i <= stop; i++)
        {
            if (typeof zeroPad === 'number')
            {
                //  str, len, pad, dir
                frame = Phaser.Utils.pad(i.toString(), zeroPad, '0', 1);
            }
            else
            {
                frame = i.toString();
            }

            frame = prefix + frame + suffix;

            output.push(frame);
        }
    }
    else
    {
        for (var i = start; i >= stop; i--)
        {
            if (typeof zeroPad === 'number')
            {
                //  str, len, pad, dir
                frame = Phaser.Utils.pad(i.toString(), zeroPad, '0', 1);
            }
            else
            {
                frame = i.toString();
            }

            frame = prefix + frame + suffix;

            output.push(frame);
        }
    }

    return output;

};


/**
* @author       Miller Medeiros http://millermedeiros.github.com/js-signals/
* @author       Richard Davey <rich@photonstorm.com>
* @copyright    2016 Photon Storm Ltd.
* @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

/**
* Object that represents a binding between a Signal and a listener function.
* This is an internal constructor and shouldn't be created directly.
* Inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.
*
* @class Phaser.SignalBinding
* @constructor
* @param {Phaser.Signal} signal - Reference to Signal object that listener is currently bound to.
* @param {function} listener - Handler function bound to the signal.
* @param {boolean} isOnce - If binding should be executed just once.
* @param {object} [listenerContext=null] - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
* @param {number} [priority] - The priority level of the event listener. (default = 0).
* @param {...any} [args=(none)] - Additional arguments to pass to the callback (listener) function. They will be appended after any arguments usually dispatched.
*/
Phaser.SignalBinding = function (signal, listener, isOnce, listenerContext, priority, args) {

    /**
    * @property {Phaser.Game} _listener - Handler function bound to the signal.
    * @private
    */
    this._listener = listener;

    if (isOnce)
    {
        this._isOnce = true;
    }

    if (listenerContext != null) /* not null/undefined */
    {
        this.context = listenerContext;
    }

    /**
    * @property {Phaser.Signal} _signal - Reference to Signal object that listener is currently bound to.
    * @private
    */
    this._signal = signal;

    if (priority)
    {
        this._priority = priority;
    }

    if (args && args.length)
    {
        this._args = args;
    }

};

Phaser.SignalBinding.prototype = {

    /**
    * @property {?object} context - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    */
    context: null,

    /**
    * @property {boolean} _isOnce - If binding should be executed just once.
    * @private
    */
    _isOnce: false,

    /**
    * @property {number} _priority - Listener priority.
    * @private
    */
    _priority: 0,

    /**
    * @property {array} _args - Listener arguments.
    * @private
    */
    _args: null,

    /**
    * @property {number} callCount - The number of times the handler function has been called.
    */
    callCount: 0,

    /**
    * If binding is active and should be executed.
    * @property {boolean} active
    * @default
    */
    active: true,

    /**
    * Default parameters passed to listener during `Signal.dispatch` and `SignalBinding.execute` (curried parameters).
    * @property {array|null} params
    * @default
    */
    params: null,

    /**
    * Call listener passing arbitrary parameters.
    * If binding was added using `Signal.addOnce()` it will be automatically removed from signal dispatch queue, this method is used internally for the signal dispatch.
    * @method Phaser.SignalBinding#execute
    * @param {any[]} [paramsArr] - Array of parameters that should be passed to the listener.
    * @return {any} Value returned by the listener.
    */
    execute: function(paramsArr) {

        var handlerReturn, params;

        if (this.active && !!this._listener)
        {
            params = this.params ? this.params.concat(paramsArr) : paramsArr;

            if (this._args)
            {
                params = params.concat(this._args);
            }

            handlerReturn = this._listener.apply(this.context, params);

            this.callCount++;

            if (this._isOnce)
            {
                this.detach();
            }
        }

        return handlerReturn;

    },

    /**
    * Detach binding from signal.
    * alias to: @see mySignal.remove(myBinding.getListener());
    * @method Phaser.SignalBinding#detach
    * @return {function|null} Handler function bound to the signal or `null` if binding was previously detached.
    */
    detach: function () {
        return this.isBound() ? this._signal.remove(this._listener, this.context) : null;
    },

    /**
    * @method Phaser.SignalBinding#isBound
    * @return {boolean} True if binding is still bound to the signal and has a listener.
    */
    isBound: function () {
        return (!!this._signal && !!this._listener);
    },

    /**
    * @method Phaser.SignalBinding#isOnce
    * @return {boolean} If SignalBinding will only be executed once.
    */
    isOnce: function () {
        return this._isOnce;
    },

    /**
    * @method Phaser.SignalBinding#getListener
    * @return {function} Handler function bound to the signal.
    */
    getListener: function () {
        return this._listener;
    },

    /**
    * @method Phaser.SignalBinding#getSignal
    * @return {Phaser.Signal} Signal that listener is currently bound to.
    */
    getSignal: function () {
        return this._signal;
    },

    /**
    * Delete instance properties
    * @method Phaser.SignalBinding#_destroy
    * @private
    */
    _destroy: function () {
        delete this._signal;
        delete this._listener;
        delete this.context;
    },

    /**
    * @method Phaser.SignalBinding#toString
    * @return {string} String representation of the object.
    */
    toString: function () {
        return '[Phaser.SignalBinding isOnce:' + this._isOnce +', isBound:'+ this.isBound() +', active:' + this.active + ']';
    }

};

Phaser.SignalBinding.prototype.constructor = Phaser.SignalBinding;


<?php
    class Processor
    {
        public $file;
        public $blocks;

        public $class;
        public $consts;
        public $methods;
        public $properties;

        public $docgen;
        public $processLog;

        public $dataTypes;
        public $domTypes;

        public $corrupted;

        /**
        * Processes the given JS source file.
        *
        * @param mixed $file
        * @return Processor
        */
        public function __construct($docgen, $file)
        {
            $this->docgen = $docgen;

            $this->class = null;
            $this->consts = [];
            $this->methods = [];
            $this->properties = [];
            $this->file = $file;

            $this->corrupted = false;

            $this->methods['private'] = [];
            $this->methods['protected'] = [];
            $this->methods['public'] = [];
            $this->methods['static'] = [];

            $this->properties['private'] = [];
            $this->properties['protected'] = [];
            $this->properties['public'] = [];

            $this->domTypes = [
                'ArrayBuffer',
                'AudioContext',
                'CanvasRenderingContext2D',
                'DOMElement',
                'Event',
                'Float32Array',
                'HTMLCanvasElement',
                'HTMLElement',
                'Image',
                'ImageData',
                'KeyboardEvent',
                'MouseEvent',
                'Pointer',
                'PointerEvent',
                'TouchEvent',
                'Uint16Array',
                'Uint32Array',
                'Uint8ClampedArray',
                'XDomainRequest',
                'XMLHttpRequest'
            ];

            $this->dataTypes = [
                'any',
                'array',
                'boolean',
                'function',
                'null',
                'number',
                'object',
                'string',
                'undefined'
            ];

            $this->scanFile();
        }

        /**
        * Scans the given JS source file and extracts blocks from it
        */
        private function scanFile() {

            $js = file($this->file);

            $scanningForOpen = true;
            $scanningForClose = false;

            $openLine = 0;
            $closeLine = 0;
            $chunk = [];

            //  Literally scan the JS file, line by line
            for ($i = 0; $i < count($js); $i++)
            {
                $line = trim($js[$i]);

                if ($scanningForOpen && $line === "/**")
                {
                    $scanningForOpen = false;
                    $scanningForClose = true;
                    $chunk = [];
                    $openLine = $i;
                }

                if ($scanningForClose && $line === "*/")
                {
                    $scanningForOpen = true;
                    $scanningForClose = false;
                    $closeLine = $i;

                    //  The first element is always the opening /** so remove it
                    array_shift($chunk);

                    if (isset($js[$i + 1]))
                    {
                        $this->blocks[] = new Block($openLine, $closeLine, $js[$i + 1], $chunk);
                    }
                }
                else
                {
                    $chunk[] = $line;
                }
            }

            //  Process the data into our documentation types
            for ($i = 0; $i < $this->total(); $i++)
            {
                if ($this->blocks[$i]->isClass)
                {
                    //  Some files like PIXI.Graphics have multiple class blocks within them
                    if ($this->class === null)
                    {
                        $tempClass = new ClassDesc($this, $this->blocks[$i]);
                        $this->class = $tempClass;

                        if ($tempClass->corrupted)
                        {
                            $this->corrupted = true;
                        }
                    }
                }
                else if ($this->blocks[$i]->isConst)
                {
                    $tempConst = new Constant($this, $this->blocks[$i]);

                    $this->consts[$tempConst->name] = $tempConst;
                }
                else if ($this->blocks[$i]->isMethod)
                {
                    $tempMethod = new Method($this, $this->blocks[$i]);

                    if ($tempMethod->isPublic)
                    {
                        $this->methods['public'][$tempMethod->name] = $tempMethod;
                    }
                    else if ($tempMethod->isProtected)
                    {
                        $this->methods['protected'][$tempMethod->name] = $tempMethod;
                    }
                    else if ($tempMethod->isPrivate)
                    {
                        $this->methods['private'][$tempMethod->name] = $tempMethod;
                    }
                    else if ($tempMethod->isStatic)
                    {
                        $this->methods['static'][$tempMethod->name] = $tempMethod;
                    }
                }
                else if ($this->blocks[$i]->isProperty)
                {
                    $tempProperty = new Property($this, $this->blocks[$i]);

                    if ($tempProperty->corrupted === false)
                    {
                        if ($tempProperty->isPublic)
                        {
                            $this->properties['public'][$tempProperty->name] = $tempProperty;
                        }
                        else if ($tempProperty->isProtected)
                        {
                            $this->properties['protected'][$tempProperty->name] = $tempProperty;
                        }
                        else if ($tempProperty->isPrivate)
                        {
                            $this->properties['private'][$tempProperty->name] = $tempProperty;
                        }
                    }
                }
            }

            if ($this->class === null)
            {
                $this->corrupted = true;
            }

            $this->sortArrays();

        }

        public function parseTypes($output, $pixi, $name)
        {
            //  Remove optional braces
            if (substr($output, 0, 1) === "(")
            {
                $output = substr($output, 1, -1);
            }

            $types = explode('|', $output);

            if (!is_array($types))
            {
                $types = array($output);
            }

            //  @param {number[]|string[]} frames - An array of numbers or strings indicating which frames to play in which order.
            //  @param {(number[]|...number)} points - An array of 2d vectors that form the convex or concave polygon.
            //      Either [[0,0], [0,1],...] or a flat array of numbers that will be interpreted as [x,y, x,y, ...],
            //      or the arguments passed can be flat x,y values e.g. `setPolygon(options, x,y, x,y, x,y, ...)` where `x` and `y` are numbers.

            foreach ($types as $key => $type)
            {
                trim($type);

                if (substr($type, -2) === "[]")
                {
                    $tidy = substr($type, 0, -2);
                    $types[$key] = "array " . substr($type, 0, -2);
                }
                else if (strpos($type, '<') > 0)
                {
                    //  array<Phaser.Physics.P2.Material>

                    $left = strpos($type, '<') + 1;
                    // $right = strpos($type, '>') - 1;
                    $tidy = substr($type, $left, -1);

                    if ($tidy === 'Number' || $tidy === 'String')
                    {
                        $tidy = strtolower($tidy);
                    }
                    else if ($tidy === 'Point')
                    {
                        $tidy = 'Phaser.Point';
                    }
                    else if ($tidy === 'Texture' || $tidy === 'DisplayObject')
                    {
                        $tidy = 'PIXI.' . $tidy;
                    }

                    $types[$key] = 'array ' . $tidy;
                }
                else if (substr($type, 0, 5) === "Array")
                {
                    $types[$key] = "array";
                }
                else if ($type === "Number" || $type === "{Number}" || substr($type, 0, 7) === "Number " || $type === "Number..." || $type === "...number")
                {
                    $types[$key] = "number";
                }
                else if ($type === "String")
                {
                    $types[$key] = "string";
                }
                else if ($type === "Boolean")
                {
                    $types[$key] = "boolean";
                }
                else if ($type === "Function")
                {
                    $types[$key] = "function";
                }
                else if ($type === "Object")
                {
                    $types[$key] = "object";
                }
                else if ($type === "Null")
                {
                    $types[$key] = "null";
                }
                else if ($type === "Circle")
                {
                    $types[$key] = "Phaser.Circle";
                }
                else if ($type === "Point" || $type === "Point...")
                {
                    $types[$key] = "Phaser.Point";
                }
                else if ($type === "Line")
                {
                    $types[$key] = "Phaser.Line";
                }
                else if ($type === "Texture")
                {
                    $types[$key] = "PIXI.Texture";
                }
                else if ($type === "Polygon")
                {
                    $types[$key] = "Phaser.Polygon";
                }
                else if ($type === "Ellipse")
                {
                    $types[$key] = "Phaser.Ellipse";
                }
                else if ($type === "Rectangle")
                {
                    $types[$key] = "Phaser.Rectangle";
                }
                else if ($type === "Matrix")
                {
                    $types[$key] = "PIXI.Matrix";
                }
                else if ($type === "DisplayObject")
                {
                    $types[$key] = "PIXI.DisplayObject";
                }
                else if ($type === "Any" || $type === "{Any}" || $type === "*" || $type === "...*")
                {
                    $types[$key] = "any";
                }
                else
                {
                    //  Valid DOM types?
                    if (!in_array($type, $this->domTypes) && !in_array($type, $this->dataTypes))
                    {
                        if ($pixi === null)
                        {
                            //  It's a ReturnType but we don't know which sort
                            if (substr($type, 0, 7) !== 'Phaser.' && substr($type, 0, 5) !== 'PIXI.' && substr($type, 0, 3) !== 'p2.')
                            {
                                //  Going to assume PIXI here as Phaser has the return types properly namespaced
                                $types[$key] = "PIXI.$type";
                            }
                        }
                        else
                        {
                            //  Not a DOM type, shall we add PIXI to the front?
                            if ($pixi)
                            {
                                if (substr($type, 0, 5) !== 'PIXI.')
                                {
                                    $types[$key] = "PIXI.$type";
                                }
                            }
                            else
                            {
                                if (substr($type, 0, 7) !== 'Phaser.' && substr($type, 0, 5) !== 'PIXI.' && substr($type, 0, 3) !== 'p2.')
                                {
                                    $types[$key] = "wtf.$type";
                                    echo($name . '=');
                                    var_dump($type);
                                }
                            }
                        }
                    }
                }

                if (isset($this->docgen->uniqueTypes[$types[$key]]))
                {
                    $this->docgen->uniqueTypes[$types[$key]] += 1;
                }
                else
                {
                    $this->docgen->uniqueTypes[$types[$key]] = 1;
                    // echo($name . '=' . $type . "\n");
                    // var_dump($name);
                }
            }

            return $types;

        }

        public function getPublicProperties()
        {
            return $this->properties['public'];
        }

        public function getPublicMethods()
        {
            return $this->methods['public'];
        }

        public function getArray()
        {
            $consts = [];
            $methods = [];
            $properties = [];

            foreach ($this->consts as $key => $value)
            {
                $consts[] = $value->getArray();
            }

            //  Methods

            $methods['public'] = [];
            $methods['protected'] = [];
            $methods['private'] = [];
            $methods['static'] = [];

            foreach ($this->methods['public'] as $key => $value)
            {
                $methods['public'][] = $value->getArray();
            }

            foreach ($this->methods['protected'] as $key => $value)
            {
                $methods['protected'][] = $value->getArray();
            }

            foreach ($this->methods['private'] as $key => $value)
            {
                $methods['private'][] = $value->getArray();
            }

            foreach ($this->methods['static'] as $key => $value)
            {
                $methods['static'][] = $value->getArray();
            }

            //  Properties

            $properties['public'] = [];
            $properties['protected'] = [];
            $properties['private'] = [];

            foreach ($this->properties['public'] as $key => $value)
            {
                $properties['public'][] = $value->getArray();
            }

            foreach ($this->properties['protected'] as $key => $value)
            {
                $properties['protected'][] = $value->getArray();
            }

            foreach ($this->properties['private'] as $key => $value)
            {
                $properties['private'][] = $value->getArray();
            }

            return array(
                'class' => $this->class->getArray(),
                'consts' => $consts,
                'methods' => $methods,
                'properties' => $properties
            );

        }

        public function getJSON()
        {
            return json_encode($this->getArray());
        }

        public function export($path)
        {
            file_put_contents($path . $this->class->name . '.json', $this->getJSON());
        }

        public function getConstsArray()
        {
            $out = [];

            for ($i = 0; $i < count($this->consts); $i++)
            {
                $out[] = $this->consts[$i]->getArray();
            }

            return $out;
        }

        public function extend()
        {
            //  Quick bailout
            if (!$this->class->extendsFrom())
            {
                return;
            }

            $proc = $this;

            do
            {
                $extends = $proc->class->extends;
                $proc = $this->docgen->get($extends);

                if ($proc !== null)
                {
                    // echo "\n\nextend found: " . $proc->getName() . "\n";
                    $this->merge($proc);
                }
                else
                {
                    // echo "\n\n --------> fatal extend: " . $extends . "\n";
                }
            }
            while ($proc->class->extendsFrom());

            $this->sortArrays();

        }

        public function sortArrays()
        {
            //  Alphabetically sort the arrays based on the key
            ksort($this->consts);

            ksort($this->methods['public']);
            ksort($this->methods['protected']);
            ksort($this->methods['private']);
            ksort($this->methods['static']);

            ksort($this->properties['public']);
            ksort($this->properties['protected']);
            ksort($this->properties['private']);
        }

        public function getMethodNames()
        {
            $output = [];

            foreach ($this->methods['public'] as $key => $method)
            {
                $output[$method->name] = true;
            }

            return $output;
        }

        public function getPropertyNames()
        {
            $output = [];

            foreach ($this->properties['public'] as $key => $property)
            {
                $output[$property->name] = true;
            }

            return $output;
        }

        public function merge($processor)
        {
            //  We only want to merge in public methods and properties.
            //  Technically JavaScript merges in bloody everything, but for the sake of docs we'll keep them #public# only.

            $inheritedMethods = $processor->getPublicMethods();
            $currentMethods = $this->getMethodNames();

            //  Flag them as inherited
            foreach ($inheritedMethods as $key => $method)
            {
                if (!array_key_exists($method->name, $currentMethods))
                {
                    $method->inherited = true;
                    $method->inheritedFrom = $processor->getName();
                    $this->methods['public'][$method->name] = $method;
                }
            }

            $inheritedProperties = $processor->getPublicProperties();
            $currentProperties = $this->getPropertyNames();

            //  Flag them as inherited!
            foreach ($inheritedProperties as $key => $property)
            {
                if (!array_key_exists($property->name, $currentProperties))
                {
                    $property->inherited = true;
                    $property->inheritedFrom = $processor->getName();
                    $this->properties['public'][$property->name] = $property;
                }
            }
        }

        /**
        * The total number of blocks scanned.
        */
        public function total()
        {
            return count($this->blocks);
        }

        public function log($text) {

            $this->processLog[] = $text;

        }

        public function getLog() {

            return $this->processLog;
            // return array_reverse($this->processLog);

        }

        public function getName() {

            return $this->class->name;

        }

        public function __toString()
        {
            if ($this->corrupted)
            {
                return "JSDoc Corrupted Class";
            }
            else
            {
                return "Class: " . $this->class->name . ", Methods: " . count($this->methods['public']) . ", Properties: " . count($this->properties['public']);
            }
        }

    }
?>


Phaser.Point

A Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis.\nThe following code creates a point at (0,0):\n`var myPoint = new Phaser.Point();`\nYou can also use them as 2D Vectors and you'll find different vector related methods in this class.

add

Adds the coordinates of two points together to create a new point.

out

Optional Point to store the value in, if not supplied a new Point object will be created.

angle

Returns the angle between two Point objects.

angleSq

The angle squared between the two Points.

Returns the angle squared between two Point objects.

centroid

Calculates centroid (or midpoint) from an array of points. If only one point is provided, that point is returned.

clamp

Clamps this Point object values to be between the given min and max.

min

The minimum value to clamp this Point to.

max

The maximum value to clamp this Point to.

clampX

Clamps the x value of this Point to be between the given min and max.

clampY

Clamps the y value of this Point to be between the given min and max

clone

output

Optional Point object. If given the values will be set into this object, otherwise a brand new Point object will be created and returned.

copyFrom

Copies the x and y properties from any given object to this Point.

copyTo

Copies the x and y properties from this Point to any given object.

cross

The cross product of this and another Point object.

a

The Point object to get the cross product combined with this Point.

distance

The distance between this Point object and the destination Point object.

Returns the distance of this Point object to the given object (can be a Circle, Point or anything with x/y properties).

a

The target object. Must have visible x and y properties that represent the center of the object.

round

Round the distance to the nearest integer (default false).

divide

Divides the coordinates of two points to create a new point.

dot

The dot product of this and another Point object.

a

The Point object to get the dot product combined with this Point.

equals

A value of true if the Points are equal, otherwise false.

Determines whether the two given Point objects are equal. They are considered equal if they have the same x and y values.

getMagnitude

Calculates the length of the Point object.

getMagnitudeSq

Calculates the length squared of the Point object.

interpolate

Interpolates the two given Points, based on the `f` value (between 0 and 1) and returns a new Point.

f

The level of interpolation between the two points. Indicates where the new point will be, along the line between pt1 and pt2. If f=1, pt1 is returned; if f=0, pt2 is returned.

invert

Inverts the x and y values of this Point

isZero

True if this Point is 0,0, otherwise false.

multiply

Multiplies the coordinates of two points to create a new point.

multiplyAdd

Adds two 2D Points together and multiplies the result by the given scalar.

normalRightHand

Right-hand normalize (make unit length) a Point.

parse

Parses an object for x and/or y properties and returns a new Phaser.Point with matching values.\nIf the object doesn't contain those properties a Point with x/y of zero will be returned.

xProp

The property used to set the Point.x value.

yProp

The property used to set the Point.y value.

perp

Return a perpendicular vector (90 degrees rotation)

projectUnit

Project two Points onto a Point of unit length.

rotate

Rotates a Point around the x/y coordinates given to the desired angle.

angle

The angle in radians (unless asDegrees is true) to rotate the Point to.

asDegrees

Is the given rotation in radians (false) or degrees (true)?

distance

An optional distance constraint between the Point and the anchor.

rperp

Return a perpendicular vector (-90 degrees rotation)

set

This Point object. Useful for chaining method calls.

Sets the `x` and `y` values of this Point object to the given values.\nIf you omit the `y` value then the `x` value will be applied to both, for example:\n`Point.setTo(2)` is the same as `Point.setTo(2, 2)`

y

The vertical value of this point. If not given the x value will be used in its place.

setMagnitude

Alters the length of the Point without changing the direction.

magnitude

The desired magnitude of the resulting Point.

subtract

Subtracts the coordinates of two points to create a new point.

toString

A string representation of the instance.

Returns a string representation of this object.


* Once the onComplete event is called this method will be called again and revert


PIXI.SepiaFilter

This applies a sepia effect to your Display Objects.

syncUniforms

Syncs the uniforms between the class object and the shaders.

sepia

The strength of the sepia. 1 will apply the full sepia effect, 0 will make the object its normal color.