<commit_before>/* jshint node: true */
'use strict';

const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const SshStub = require('./ssh-stub.js');
const RSVP = require('rsvp');
const Plugin = require('../index.js');
chai.use(chaiAsPromised);

var assert = chai.assert;

describe('simply-ssh', () => {
  var subject, mockUi, plugin, context, revisions;

  beforeEach(() => {
    subject = Plugin;
    mockUi = {
      verbose: true,
      messages: [],
      write() {},
      writeLine(m) { this.messages.push(m); },
      received(reg) {
        return this.messages.some((m) => reg.test(m));
      }
    };
    context = {
      distDir: process.cwd() + '/tests/fixtures/dist',
      distFiles: ['app.css', 'app.js'],
      ui: mockUi,
      ssh: 0,
      config: {
        "simply-ssh": {
          sshClient: new SshStub(),
          connection: {
            username: "deploy",
            host: "localhost"
          }
        }
      },
      ssh: new SshStub()
    };
    plugin = subject.createDeployPlugin({
      name: 'simply-ssh'
    });
  });

  it('has a name', () => {
    assert.equal(plugin.name, 'simply-ssh');
  });

  describe('setup hook:', () => {
    it('rejects when connection params missing', () => {
      delete context.config["simply-ssh"].connection;
      delete context.config["simply-ssh"].sshClient;
      plugin.beforeHook(context);
      return assert.isRejected(plugin.setup(context)).then((e) => {
        assert.equal(e.message, "config.host or config.sock must be provided");
      });
    });

    it('connects with valid params', () => {
      plugin.beforeHook(context);
      return assert.isFulfilled(plugin.setup(context)).then((context) => {
        assert.ok(mockUi.received(/SSH connection established/));
        assert.ok(context.ssh instanceof SshStub);
      });
    });
  });

  describe('fetchRevisions hook:', () => {
    it('retrieves revisions.json with normalization', () => {
      revisions = [
        {revision: "1", timestamp: Date.now() - 50000},
        {revision: "2", timestamp: Date.now() - 100000},
        {revision: "3", timestamp: Date.now()},
        {trash: "LOL"} // Just to check we wouldn't consider corrupt data
      ]
      plugin.beforeHook(context);
      plugin.configure(context);
      context.ssh.commandResponse({stdout: JSON.stringify(revisions)});
      return assert.isFulfilled(plugin.fetchRevisions(context)).then((res) => {
        assert.equal(res.revisions.length, 3);
        assert.equal(res.revisions[0].revision, "2");
        assert.equal(res.revisions[1].revision, "1");
        assert.equal(res.revisions[2].revision, "3");
      });
    });
  });

  describe('willUpload hook:', () => {
    it('with -revision-data', () => {
      context.revisionData = {
        revisionKey: "COOLREVISION"
      };
      plugin.beforeHook(context);
      plugin.configure(context);
      const dir = "/var/www/releases/COOLREVISION";
      return assert.isFulfilled(plugin.willUpload(context)).then((context) => {
        assert.ok(mockUi.received(new RegExp("Creating directory " + dir)));
        assert.equal(context.releaseDir, dir);
      });
    });

    it('without -revision-data', () => {
      plugin.beforeHook(context);
      plugin.configure(context);
      const dir = "/var/www";
      return assert.isFulfilled(plugin.willUpload(context)).then((context) => {
        assert.ok(mockUi.received(new RegExp("Creating directory " + dir)));
        assert.equal(context.releaseDir, dir);
      });
    });
  });

  describe('upload hook:', () => {
    beforeEach(() => {
      context.releaseDir = '/var/www/release';
    });

    it('uploads files one-by-one without -release-data', () => {
      plugin.beforeHook(context);
      return assert.isFulfilled(plugin.upload(context)).then((res) => {
        assert.ok(mockUi.received(/Uploading files/));
        context.distFiles.forEach((file) => {
          assert.ok(mockUi.received(new RegExp(file)));
        });
        assert.notOk(res);
      });
    });

    it('uploads files one-by-one with -release-data', () => {
      context.revisionData = {
        revisionKey: "COOLREVISION"
      };
      plugin.beforeHook(context);
      return assert.isFulfilled(plugin.upload(context)).then((res) => {
        assert.equal(res.uploadedRevision.revision, "COOLREVISION");
        assert.ok(res.uploadedRevision.timestamp - Date.now() < 50);
      });
    });

    it('rejects when connection is down', () => {
      plugin.beforeHook(context);
      context.ssh.connectionState(false);
      return assert.isRejected(plugin.upload(context)).then((e) => {
        assert.equal(e, "Connection is down");
      });
    });
  });

  describe('didUpload hook:', () => {
    beforeEach(() => {
      context.uploadedRevision = {revision: "4", timestamp: Date.now(), active: false};
      revisions = [
        {revision: "1", timestamp: Date.now() - 50000, active: true},
        {revision: "2", timestamp: Date.now() - 100000, active: false},
        {revision: "3", timestamp: Date.now() - 1000, active: false},
      ];
      plugin._fetchRevisionsJson = (context) => { return RSVP.resolve(revisions) };
      plugin.beforeHook(context);
      plugin.configure(context);
    });

    it('cleans up old revisions if above `keep`', () => {
      return assert.isFulfilled(plugin.didUpload(context)).then(() => {
        const deletedDir = new RegExp('/var/www/releases/2');
        const updatedRevs = revisions.filter((r) => r.revision == 2)
          .push(context.uploadedRevision);
        const mask = new RegExp(JSON.stringify(updatedRevs));
        assert.ok(mockUi.received(/Purging revisions/));
        assert.ok(mockUi.received(deletedDir));
        assert.ok(mockUi.received(/revisions\.json updated/));
        assert.ok(context.ssh.commands.some((c) => {
          return deletedDir.test(c) && /rm -rf/.test(c);
        }));
        assert.ok(context.ssh.commands.some((c) => {
          return mask.test(c);
        }));
      });
    });
  });

  describe('activate hook:', () => {
    beforeEach(() => {
      context.releaseDir = '/var/www/release';
      context.commandOptions = {
        revision: "12345"
      };
      plugin.beforeHook(context);
      plugin.configure(context);
    });

    it('creates symbolic link to selected release', () => {
      return assert.isFulfilled(plugin.activate(context)).then((res) => {
        assert.ok(mockUi.received(/Revision 12345 is now active!/));
        assert.equal(res.activatedRevision, "12345");
      });
    });

    it('does nothing if revisions are not supported', () => {
      delete context.commandOptions.revision;
      plugin.beforeHook(context);
      return assert.isFulfilled(plugin.activate(context)).then((res) => {
        assert.notOk(mockUi.received(/is now active!/));
        assert.notOk(res);
      });
    });

    it('stops pipeline if release is missing', () => {
      context.ssh.commandResponse({stderr: "Revision is missing!"});
      return assert.isRejected(plugin.activate(context)).then((e) => {
        assert.equal(e, "Revision is missing!");
      });
    });
  });

  describe('didActivate hook:', () => {
    it('does nothing if activatedRevision is undefined', () => {
      plugin.beforeHook(context);
      plugin.configure(context);
      return assert.isFulfilled(plugin.didActivate(context)).then((res) => {
        assert.notOk(res);
      });
    });

    it('updated revisions.json after activate', () => {
      context.activatedRevision = "12345";
      let oldRev = {revision: "LOL", timestamp: Date.now() - 50000, active: true};
      let newRev = {revision: "12345", timestamp: Date.now(), active: false};
      context.revisions = [oldRev, newRev];
      plugin.beforeHook(context);
      plugin.configure(context);
      return assert.isFulfilled(plugin.didActivate(context)).then((res) => {
        assert.notOk(res);
        oldRev.active = false;
        newRev.active = true;
        const mask = new RegExp(JSON.stringify([oldRev, newRev]));
        assert.ok(mask.test(context.ssh.commands[0]));
      });
    });
  });

  describe('teardown hook:', () => {
    it('shuts down ssh', () => {
      plugin.beforeHook(context);
      plugin.teardown(context);
      assert.notOk(context.ssh.up);
      assert.ok(mockUi.received(/SSH connection closed/));
    });
  });
});
<commit_msg>Add ignore-pattern test<commit_after>/* jshint node: true */
'use strict';

const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const SshStub = require('./ssh-stub.js');
const RSVP = require('rsvp');
const minimatch = require('minimatch');
const Plugin = require('../index.js');
chai.use(chaiAsPromised);

var assert = chai.assert;

describe('simply-ssh', () => {
  var subject, mockUi, plugin, context, revisions;

  beforeEach(() => {
    subject = Plugin;
    mockUi = {
      verbose: true,
      messages: [],
      write() {},
      writeLine(m) { this.messages.push(m); },
      received(reg) {
        return this.messages.some((m) => reg.test(m));
      }
    };
    context = {
      distDir: process.cwd() + '/tests/fixtures/dist',
      distFiles: ['app.css', 'app.js', 'app.map'],
      ui: mockUi,
      ssh: 0,
      config: {
        "simply-ssh": {
          sshClient: new SshStub(),
          connection: {
            username: "deploy",
            host: "localhost"
          }
        }
      },
      ssh: new SshStub()
    };
    plugin = subject.createDeployPlugin({
      name: 'simply-ssh'
    });
  });

  it('has a name', () => {
    assert.equal(plugin.name, 'simply-ssh');
  });

  describe('setup hook:', () => {
    it('rejects when connection params missing', () => {
      delete context.config["simply-ssh"].connection;
      delete context.config["simply-ssh"].sshClient;
      plugin.beforeHook(context);
      return assert.isRejected(plugin.setup(context)).then((e) => {
        assert.equal(e.message, "config.host or config.sock must be provided");
      });
    });

    it('connects with valid params', () => {
      plugin.beforeHook(context);
      return assert.isFulfilled(plugin.setup(context)).then((context) => {
        assert.ok(mockUi.received(/SSH connection established/));
        assert.ok(context.ssh instanceof SshStub);
      });
    });
  });

  describe('fetchRevisions hook:', () => {
    it('retrieves revisions.json with normalization', () => {
      revisions = [
        {revision: "1", timestamp: Date.now() - 50000},
        {revision: "2", timestamp: Date.now() - 100000},
        {revision: "3", timestamp: Date.now()},
        {trash: "LOL"} // Just to check we wouldn't consider corrupt data
      ]
      plugin.beforeHook(context);
      plugin.configure(context);
      context.ssh.commandResponse({stdout: JSON.stringify(revisions)});
      return assert.isFulfilled(plugin.fetchRevisions(context)).then((res) => {
        assert.equal(res.revisions.length, 3);
        assert.equal(res.revisions[0].revision, "2");
        assert.equal(res.revisions[1].revision, "1");
        assert.equal(res.revisions[2].revision, "3");
      });
    });
  });

  describe('willUpload hook:', () => {
    it('with -revision-data', () => {
      context.revisionData = {
        revisionKey: "COOLREVISION"
      };
      plugin.beforeHook(context);
      plugin.configure(context);
      const dir = "/var/www/releases/COOLREVISION";
      return assert.isFulfilled(plugin.willUpload(context)).then((context) => {
        assert.ok(mockUi.received(new RegExp("Creating directory " + dir)));
        assert.equal(context.releaseDir, dir);
      });
    });

    it('without -revision-data', () => {
      plugin.beforeHook(context);
      plugin.configure(context);
      const dir = "/var/www";
      return assert.isFulfilled(plugin.willUpload(context)).then((context) => {
        assert.ok(mockUi.received(new RegExp("Creating directory " + dir)));
        assert.equal(context.releaseDir, dir);
      });
    });
  });

  describe('upload hook:', () => {
    beforeEach(() => {
      context.releaseDir = '/var/www/release';
    });

    it('uploads files one-by-one without -release-data', () => {
      plugin.beforeHook(context);
      return assert.isFulfilled(plugin.upload(context)).then((res) => {
        assert.ok(mockUi.received(/Uploading files/));
        context.distFiles.forEach((file) => {
          assert.ok(mockUi.received(new RegExp(file)));
        });
        assert.notOk(res);
      });
    });

    it('uploads files one-by-one with -release-data', () => {
      context.revisionData = {
        revisionKey: "COOLREVISION"
      };
      plugin.beforeHook(context);
      return assert.isFulfilled(plugin.upload(context)).then((res) => {
        assert.equal(res.uploadedRevision.revision, "COOLREVISION");
        assert.ok(res.uploadedRevision.timestamp - Date.now() < 50);
      });
    });

    it('uploads files one-by-one with -ignore-pattern', () => {
      context.config["simply-ssh"].ignorePattern = "**/*.map";
      plugin.beforeHook(context);
      return assert.isFulfilled(plugin.upload(context)).then((res) => {
        assert.ok(mockUi.received(/Uploading files/));
        assert.notOk(mockUi.received(minimatch.makeRe("**/*.map", { matchBase: true })));
        assert.notOk(res);
      });
    });

    it('rejects when connection is down', () => {
      plugin.beforeHook(context);
      context.ssh.connectionState(false);
      return assert.isRejected(plugin.upload(context)).then((e) => {
        assert.equal(e, "Connection is down");
      });
    });
  });

  describe('didUpload hook:', () => {
    beforeEach(() => {
      context.uploadedRevision = {revision: "4", timestamp: Date.now(), active: false};
      revisions = [
        {revision: "1", timestamp: Date.now() - 50000, active: true},
        {revision: "2", timestamp: Date.now() - 100000, active: false},
        {revision: "3", timestamp: Date.now() - 1000, active: false},
      ];
      plugin._fetchRevisionsJson = (context) => { return RSVP.resolve(revisions) };
      plugin.beforeHook(context);
      plugin.configure(context);
    });

    it('cleans up old revisions if above `keep`', () => {
      return assert.isFulfilled(plugin.didUpload(context)).then(() => {
        const deletedDir = new RegExp('/var/www/releases/2');
        const updatedRevs = revisions.filter((r) => r.revision == 2)
          .push(context.uploadedRevision);
        const mask = new RegExp(JSON.stringify(updatedRevs));
        assert.ok(mockUi.received(/Purging revisions/));
        assert.ok(mockUi.received(deletedDir));
        assert.ok(mockUi.received(/revisions\.json updated/));
        assert.ok(context.ssh.commands.some((c) => {
          return deletedDir.test(c) && /rm -rf/.test(c);
        }));
        assert.ok(context.ssh.commands.some((c) => {
          return mask.test(c);
        }));
      });
    });
  });

  describe('activate hook:', () => {
    beforeEach(() => {
      context.releaseDir = '/var/www/release';
      context.commandOptions = {
        revision: "12345"
      };
      plugin.beforeHook(context);
      plugin.configure(context);
    });

    it('creates symbolic link to selected release', () => {
      return assert.isFulfilled(plugin.activate(context)).then((res) => {
        assert.ok(mockUi.received(/Revision 12345 is now active!/));
        assert.equal(res.activatedRevision, "12345");
      });
    });

    it('does nothing if revisions are not supported', () => {
      delete context.commandOptions.revision;
      plugin.beforeHook(context);
      return assert.isFulfilled(plugin.activate(context)).then((res) => {
        assert.notOk(mockUi.received(/is now active!/));
        assert.notOk(res);
      });
    });

    it('stops pipeline if release is missing', () => {
      context.ssh.commandResponse({stderr: "Revision is missing!"});
      return assert.isRejected(plugin.activate(context)).then((e) => {
        assert.equal(e, "Revision is missing!");
      });
    });
  });

  describe('didActivate hook:', () => {
    it('does nothing if activatedRevision is undefined', () => {
      plugin.beforeHook(context);
      plugin.configure(context);
      return assert.isFulfilled(plugin.didActivate(context)).then((res) => {
        assert.notOk(res);
      });
    });

    it('updated revisions.json after activate', () => {
      context.activatedRevision = "12345";
      let oldRev = {revision: "LOL", timestamp: Date.now() - 50000, active: true};
      let newRev = {revision: "12345", timestamp: Date.now(), active: false};
      context.revisions = [oldRev, newRev];
      plugin.beforeHook(context);
      plugin.configure(context);
      return assert.isFulfilled(plugin.didActivate(context)).then((res) => {
        assert.notOk(res);
        oldRev.active = false;
        newRev.active = true;
        const mask = new RegExp(JSON.stringify([oldRev, newRev]));
        assert.ok(mask.test(context.ssh.commands[0]));
      });
    });
  });

  describe('teardown hook:', () => {
    it('shuts down ssh', () => {
      plugin.beforeHook(context);
      plugin.teardown(context);
      assert.notOk(context.ssh.up);
      assert.ok(mockUi.received(/SSH connection closed/));
    });
  });
});
<|endoftext|>


<commit_before>import * as regex from '../lib/regex.js';

/*
Language: TOML, also INI
Description: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.
Contributors: Guillaume Gomez <guillaume1.gomez@gmail.com>
Category: common, config
Website: https://github.com/toml-lang/toml
*/

export default function(hljs) {
  var NUMBERS = {
    className: 'number',
    relevance: 0,
    variants: [
      { begin: /([\+\-]+)?[\d]+_[\d_]+/ },
      { begin: hljs.NUMBER_RE }
    ]
  };
  var COMMENTS = hljs.COMMENT();
  COMMENTS.variants = [
    {begin: /;/, end: /$/},
    {begin: /#/, end: /$/},
  ];
  var VARIABLES = {
    className: 'variable',
    variants: [
      { begin: /\$[\w\d"][\w\d_]*/ },
      { begin: /\$\{(.*?)}/ }
    ]
  };
  var LITERALS = {
    className: 'literal',
    begin: /\bon|off|true|false|yes|no\b/
  };
  var STRINGS = {
    className: "string",
    contains: [hljs.BACKSLASH_ESCAPE],
    variants: [
      { begin: "'''", end: "'''", relevance: 10 },
      { begin: '"""', end: '"""', relevance: 10 },
      { begin: '"', end: '"' },
      { begin: "'", end: "'" }
    ]
  };
  var ARRAY = {
    begin: /\[/, end: /\]/,
    contains: [
      COMMENTS,
      LITERALS,
      VARIABLES,
      STRINGS,
      NUMBERS,
      'self'
    ],
    relevance:0
  };

  var BARE_KEY = /[A-Za-z0-9_-]+/;
  var QUOTED_KEY_DOUBLE_QUOTE = /"(\\"|[^"])*"/;
  var QUOTED_KEY_SINGLE_QUOTE = /'[^']*'/;
  var ANY_KEY = regex.either(
    BARE_KEY, QUOTED_KEY_DOUBLE_QUOTE, QUOTED_KEY_SINGLE_QUOTE
  );
  var DOTTED_KEY = regex.concat(
    ANY_KEY, '(\\s*\\.\\s*', ANY_KEY, ')*',
    regex.lookahead(/\s*=\s*[^#\s]/)
  );

  return {
    name: 'TOML, also INI',
    aliases: ['toml'],
    case_insensitive: true,
    illegal: /\S/,
    contains: [
      COMMENTS,
      {
        className: 'section',
        begin: /\[+/, end: /\]+/
      },
      {
        begin: DOTTED_KEY,
        className: 'attr',
        starts: {
          end: /$/,
          contains: [
            COMMENTS,
            ARRAY,
            LITERALS,
            VARIABLES,
            STRINGS,
            NUMBERS
          ]
        }
      }
    ]
  };
}
<commit_msg>(chore) more import below metadata comment<commit_after>/*
Language: TOML, also INI
Description: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.
Contributors: Guillaume Gomez <guillaume1.gomez@gmail.com>
Category: common, config
Website: https://github.com/toml-lang/toml
*/

import * as regex from '../lib/regex.js';

export default function(hljs) {
  var NUMBERS = {
    className: 'number',
    relevance: 0,
    variants: [
      { begin: /([\+\-]+)?[\d]+_[\d_]+/ },
      { begin: hljs.NUMBER_RE }
    ]
  };
  var COMMENTS = hljs.COMMENT();
  COMMENTS.variants = [
    {begin: /;/, end: /$/},
    {begin: /#/, end: /$/},
  ];
  var VARIABLES = {
    className: 'variable',
    variants: [
      { begin: /\$[\w\d"][\w\d_]*/ },
      { begin: /\$\{(.*?)}/ }
    ]
  };
  var LITERALS = {
    className: 'literal',
    begin: /\bon|off|true|false|yes|no\b/
  };
  var STRINGS = {
    className: "string",
    contains: [hljs.BACKSLASH_ESCAPE],
    variants: [
      { begin: "'''", end: "'''", relevance: 10 },
      { begin: '"""', end: '"""', relevance: 10 },
      { begin: '"', end: '"' },
      { begin: "'", end: "'" }
    ]
  };
  var ARRAY = {
    begin: /\[/, end: /\]/,
    contains: [
      COMMENTS,
      LITERALS,
      VARIABLES,
      STRINGS,
      NUMBERS,
      'self'
    ],
    relevance:0
  };

  var BARE_KEY = /[A-Za-z0-9_-]+/;
  var QUOTED_KEY_DOUBLE_QUOTE = /"(\\"|[^"])*"/;
  var QUOTED_KEY_SINGLE_QUOTE = /'[^']*'/;
  var ANY_KEY = regex.either(
    BARE_KEY, QUOTED_KEY_DOUBLE_QUOTE, QUOTED_KEY_SINGLE_QUOTE
  );
  var DOTTED_KEY = regex.concat(
    ANY_KEY, '(\\s*\\.\\s*', ANY_KEY, ')*',
    regex.lookahead(/\s*=\s*[^#\s]/)
  );

  return {
    name: 'TOML, also INI',
    aliases: ['toml'],
    case_insensitive: true,
    illegal: /\S/,
    contains: [
      COMMENTS,
      {
        className: 'section',
        begin: /\[+/, end: /\]+/
      },
      {
        begin: DOTTED_KEY,
        className: 'attr',
        starts: {
          end: /$/,
          contains: [
            COMMENTS,
            ARRAY,
            LITERALS,
            VARIABLES,
            STRINGS,
            NUMBERS
          ]
        }
      }
    ]
  };
}
<|endoftext|>


<commit_before>/*
Language: PHP
Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Ivan Sagalaev <maniac@softwaremaniacs.org>
*/

function(hljs) {
  var VARIABLE = {
    className: 'variable', begin: '\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
  };
  var STRINGS = [
    hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),
    hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),
    {
      className: 'string',
      begin: 'b"', end: '"',
      contains: [hljs.BACKSLASH_ESCAPE]
    },
    {
      className: 'string',
      begin: 'b\'', end: '\'',
      contains: [hljs.BACKSLASH_ESCAPE]
    }
  ];
  var NUMBERS = [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE];
  var TITLE = {
    className: 'title', begin: hljs.UNDERSCORE_IDENT_RE
  };
  return {
    case_insensitive: true,
    keywords:
      'and include_once list abstract global private echo interface as static endswitch ' +
      'array null if endwhile or const for endforeach self var while isset public ' +
      'protected exit foreach throw elseif include __FILE__ empty require_once do xor ' +
      'return implements parent clone use __CLASS__ __LINE__ else break print eval new ' +
      'catch __METHOD__ case exception php_user_filter default die require __FUNCTION__ ' +
      'enddeclare final try this switch continue endfor endif declare unset true false ' +
      'namespace trait goto instanceof insteadof __DIR__ __NAMESPACE__ __halt_compiler',
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.HASH_COMMENT_MODE,
      {
        className: 'comment',
        begin: '/\\*', end: '\\*/',
        contains: [{
            className: 'phpdoc',
            begin: '\\s@[A-Za-z]+'
        }]
      },
      {
          className: 'comment',
          excludeBegin: true,
          begin: '__halt_compiler.+?;', endsWithParent: true
      },
      {
        className: 'string',
        begin: '<<<[\'"]?\\w+[\'"]?$', end: '^\\w+;',
        contains: [hljs.BACKSLASH_ESCAPE]
      },
      {
        className: 'preprocessor',
        begin: '<\\?php',
        relevance: 10
      },
      {
        className: 'preprocessor',
        begin: '\\?>'
      },
      VARIABLE,
      {
        className: 'function',
        beginWithKeyword: true, end: '{',
        keywords: 'function',
        illegal: '\\$|\\[|%',
        contains: [
          TITLE,
          {
            className: 'params',
            begin: '\\(', end: '\\)',
            contains: [
              'self',
              VARIABLE,
              hljs.C_BLOCK_COMMENT_MODE
            ].concat(STRINGS).concat(NUMBERS)
          }
        ]
      },
      {
        className: 'class',
        beginWithKeyword: true, end: '{',
        keywords: 'class',
        illegal: '[:\\(\\$]',
        contains: [
          {
            beginWithKeyword: true, endsWithParent: true,
            keywords: 'extends',
            contains: [TITLE]
          },
          TITLE
        ]
      },
      {
        begin: '=>' // No markup, just a relevance booster
      }
    ].concat(STRINGS).concat(NUMBERS)
  };
}
<commit_msg>Fix to support PHP prototypes (fixes #276)<commit_after>/*
Language: PHP
Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Ivan Sagalaev <maniac@softwaremaniacs.org>
*/

function(hljs) {
  var VARIABLE = {
    className: 'variable', begin: '\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
  };
  var STRINGS = [
    hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),
    hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),
    {
      className: 'string',
      begin: 'b"', end: '"',
      contains: [hljs.BACKSLASH_ESCAPE]
    },
    {
      className: 'string',
      begin: 'b\'', end: '\'',
      contains: [hljs.BACKSLASH_ESCAPE]
    }
  ];
  var NUMBERS = [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE];
  var TITLE = {
    className: 'title', begin: hljs.UNDERSCORE_IDENT_RE
  };
  return {
    case_insensitive: true,
    keywords:
      'and include_once list abstract global private echo interface as static endswitch ' +
      'array null if endwhile or const for endforeach self var while isset public ' +
      'protected exit foreach throw elseif include __FILE__ empty require_once do xor ' +
      'return implements parent clone use __CLASS__ __LINE__ else break print eval new ' +
      'catch __METHOD__ case exception php_user_filter default die require __FUNCTION__ ' +
      'enddeclare final try this switch continue endfor endif declare unset true false ' +
      'namespace trait goto instanceof insteadof __DIR__ __NAMESPACE__ __halt_compiler',
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.HASH_COMMENT_MODE,
      {
        className: 'comment',
        begin: '/\\*', end: '\\*/',
        contains: [{
            className: 'phpdoc',
            begin: '\\s@[A-Za-z]+'
        }]
      },
      {
          className: 'comment',
          excludeBegin: true,
          begin: '__halt_compiler.+?;', endsWithParent: true
      },
      {
        className: 'string',
        begin: '<<<[\'"]?\\w+[\'"]?$', end: '^\\w+;',
        contains: [hljs.BACKSLASH_ESCAPE]
      },
      {
        className: 'preprocessor',
        begin: '<\\?php',
        relevance: 10
      },
      {
        className: 'preprocessor',
        begin: '\\?>'
      },
      VARIABLE,
      {
        className: 'function',
        beginWithKeyword: true, end: /[;{]/,
        keywords: 'function',
        illegal: '\\$|\\[|%',
        contains: [
          TITLE,
          {
            className: 'params',
            begin: '\\(', end: '\\)',
            contains: [
              'self',
              VARIABLE,
              hljs.C_BLOCK_COMMENT_MODE
            ].concat(STRINGS).concat(NUMBERS)
          }
        ]
      },
      {
        className: 'class',
        beginWithKeyword: true, end: '{',
        keywords: 'class',
        illegal: '[:\\(\\$]',
        contains: [
          {
            beginWithKeyword: true, endsWithParent: true,
            keywords: 'extends',
            contains: [TITLE]
          },
          TITLE
        ]
      },
      {
        begin: '=>' // No markup, just a relevance booster
      }
    ].concat(STRINGS).concat(NUMBERS)
  };
}
<|endoftext|>


<commit_before>/*
Language: PHP
Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Ivan Sagalaev <maniac@softwaremaniacs.org>
Website: https://www.php.net
Category: common
*/

/**
 * @param {HLJSApi} hljs
 * @returns {LanguageDetail}
 * */
export default function(hljs) {
  const regex = hljs.regex;
  const VARIABLE = {
    className: 'variable',
    begin: '\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*' +
      // negative look-ahead tries to avoid matching patterns that are not
      // Perl at all like $ident$, @ident@, etc.
      `(?![A-Za-z0-9])(?![$])`
  };
  const PREPROCESSOR = {
    className: 'meta',
    variants: [
      { begin: /<\?php/, relevance: 10 }, // boost for obvious PHP
      { begin: /<\?[=]?/ },
      { begin: /\?>/ } // end php tag
    ]
  };
  const SUBST = {
    className: 'subst',
    variants: [
      { begin: /\$\w+/ },
      { begin: /\{\$/, end: /\}/ }
    ]
  };
  const SINGLE_QUOTED = hljs.inherit(hljs.APOS_STRING_MODE, {
    illegal: null,
  });
  const DOUBLE_QUOTED = hljs.inherit(hljs.QUOTE_STRING_MODE, {
    illegal: null,
    contains: hljs.QUOTE_STRING_MODE.contains.concat(SUBST),
  });
  const HEREDOC = hljs.END_SAME_AS_BEGIN({
    begin: /<<<[ \t]*(\w+)\n/,
    end: /[ \t]*(\w+)\b/,
    contains: hljs.QUOTE_STRING_MODE.contains.concat(SUBST),
  });
  const STRING = {
    className: 'string',
    variants: [
      DOUBLE_QUOTED,
      SINGLE_QUOTED,
      HEREDOC
    ]
  };
  const NUMBER = {
    className: 'number',
    variants: [
      { begin: `\\b0[bB][01]+(?:_[01]+)*\\b` }, // Binary w/ underscore support
      { begin: `\\b0[oO][0-7]+(?:_[0-7]+)*\\b` }, // Octals w/ underscore support
      { begin: `\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b` }, // Hex w/ underscore support
      // Decimals w/ underscore support, with optional fragments and scientific exponent (e) suffix.
      { begin: `(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?` }
    ],
    relevance: 0
  };
  const LITERALS = [
    "false",
    "null",
    "true"
  ];
  const KWS = [
    // Magic constants:
    // <https://www.php.net/manual/en/language.constants.predefined.php>
    "__CLASS__",
    "__DIR__",
    "__FILE__",
    "__FUNCTION__",
    "__COMPILER_HALT_OFFSET__",
    "__LINE__",
    "__METHOD__",
    "__NAMESPACE__",
    "__TRAIT__",
    // Function that look like language construct or language construct that look like function:
    // List of keywords that may not require parenthesis
    "die",
    "echo",
    "exit",
    "include",
    "include_once",
    "print",
    "require",
    "require_once",
    // These are not language construct (function) but operate on the currently-executing function and can access the current symbol table
    // 'compact extract func_get_arg func_get_args func_num_args get_called_class get_parent_class ' +
    // Other keywords:
    // <https://www.php.net/manual/en/reserved.php>
    // <https://www.php.net/manual/en/language.types.type-juggling.php>
    "array",
    "abstract",
    "and",
    "as",
    "binary",
    "bool",
    "boolean",
    "break",
    "callable",
    "case",
    "catch",
    "class",
    "clone",
    "const",
    "continue",
    "declare",
    "default",
    "do",
    "double",
    "else",
    "elseif",
    "empty",
    "enddeclare",
    "endfor",
    "endforeach",
    "endif",
    "endswitch",
    "endwhile",
    "enum",
    "eval",
    "extends",
    "final",
    "finally",
    "float",
    "for",
    "foreach",
    "from",
    "global",
    "goto",
    "if",
    "implements",
    "instanceof",
    "insteadof",
    "int",
    "integer",
    "interface",
    "isset",
    "iterable",
    "list",
    "match|0",
    "mixed",
    "new",
    "object",
    "or",
    "private",
    "protected",
    "public",
    "real",
    "return",
    "string",
    "switch",
    "throw",
    "trait",
    "try",
    "unset",
    "use",
    "var",
    "void",
    "while",
    "xor",
    "yield"
  ];

  const BUILT_INS = [
    // Standard PHP library:
    // <https://www.php.net/manual/en/book.spl.php>
    "Error|0",
    "AppendIterator",
    "ArgumentCountError",
    "ArithmeticError",
    "ArrayIterator",
    "ArrayObject",
    "AssertionError",
    "BadFunctionCallException",
    "BadMethodCallException",
    "CachingIterator",
    "CallbackFilterIterator",
    "CompileError",
    "Countable",
    "DirectoryIterator",
    "DivisionByZeroError",
    "DomainException",
    "EmptyIterator",
    "ErrorException",
    "Exception",
    "FilesystemIterator",
    "FilterIterator",
    "GlobIterator",
    "InfiniteIterator",
    "InvalidArgumentException",
    "IteratorIterator",
    "LengthException",
    "LimitIterator",
    "LogicException",
    "MultipleIterator",
    "NoRewindIterator",
    "OutOfBoundsException",
    "OutOfRangeException",
    "OuterIterator",
    "OverflowException",
    "ParentIterator",
    "ParseError",
    "RangeException",
    "RecursiveArrayIterator",
    "RecursiveCachingIterator",
    "RecursiveCallbackFilterIterator",
    "RecursiveDirectoryIterator",
    "RecursiveFilterIterator",
    "RecursiveIterator",
    "RecursiveIteratorIterator",
    "RecursiveRegexIterator",
    "RecursiveTreeIterator",
    "RegexIterator",
    "RuntimeException",
    "SeekableIterator",
    "SplDoublyLinkedList",
    "SplFileInfo",
    "SplFileObject",
    "SplFixedArray",
    "SplHeap",
    "SplMaxHeap",
    "SplMinHeap",
    "SplObjectStorage",
    "SplObserver",
    "SplPriorityQueue",
    "SplQueue",
    "SplStack",
    "SplSubject",
    "SplTempFileObject",
    "TypeError",
    "UnderflowException",
    "UnexpectedValueException",
    "UnhandledMatchError",
    // Reserved interfaces:
    // <https://www.php.net/manual/en/reserved.interfaces.php>
    "ArrayAccess",
    "Closure",
    "Generator",
    "Iterator",
    "IteratorAggregate",
    "Serializable",
    "Stringable",
    "Throwable",
    "Traversable",
    "WeakReference",
    "WeakMap",
    // Reserved classes:
    // <https://www.php.net/manual/en/reserved.classes.php>
    "Directory",
    "__PHP_Incomplete_Class",
    "parent",
    "php_user_filter",
    "self",
    "static",
    "stdClass"
  ];

  /** Dual-case keywords
   *
   * ["then","FILE"] =>
   *     ["then", "THEN", "FILE", "file"]
   *
   * @param {string[]} items */
  const dualCase = (items) => {
    /** @type string[] */
    const result = [];
    items.forEach(item => {
      result.push(item);
      if (item.toLowerCase() === item) {
        result.push(item.toUpperCase());
      } else {
        result.push(item.toLowerCase());
      }
    });
    return result;
  };

  const KEYWORDS = {
    keyword: KWS,
    literal: dualCase(LITERALS),
    built_in: BUILT_INS,
  };

  /**
   * @param {string[]} items */
  const normalizeKeywords = (items) => {
    return items.map(item => {
      return item.replace(/\|\d+$/, "");
    });
  };

  const CONSTRUCTOR_CALL = {
    variants: [
      {
        match: [
          /new/,
          / +/,
          // to prevent built ins from being confused as the class constructor call
          regex.concat("(?!", normalizeKeywords(BUILT_INS).join("\\b|"), "\\b)"),
          /\\?\w+/,
          / *\(/,
        ],
        scope: {
          1: "keyword",
          4: "title.class",
        },
      }
    ]
  };

  const FUNCTION_INVOKE = {
    relevance: 0,
    match: [
      /\b/,
      // to prevent keywords from being confused as the function title
      regex.concat("(?!fn\\b|function\\b|", normalizeKeywords(KWS).join("\\b|"), "|", normalizeKeywords(BUILT_INS).join("\\b|"), "\\b)"),
      /\w+/,
      / */,
      regex.lookahead(/(?=\()/)
    ],
    scope: {
      3: "function.title.invoke",
    }
  };

  return {
    case_insensitive: false,
    keywords: KEYWORDS,
    contains: [
      hljs.HASH_COMMENT_MODE,
      hljs.COMMENT('//', '$'),
      hljs.COMMENT(
        '/\\*',
        '\\*/',
        {
          contains: [
            {
              className: 'doctag',
              begin: '@[A-Za-z]+'
            }
          ]
        }
      ),
      {
        match: /__halt_compiler\(\);/,
        keywords: '__halt_compiler',
        starts: {
          scope: "comment",
          end: hljs.MATCH_NOTHING_RE,
          contains: [
            {
              match: /\?>/,
              scope: "meta",
              endsParent: true
            }
          ]
        }
      },
      PREPROCESSOR,
      {
        className: 'variable.language',
        begin: /\$this\b/
      },
      VARIABLE,
      FUNCTION_INVOKE,
      {
        // swallow composed identifiers to avoid parsing them as keywords
        begin: /(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?! *\()(?![a-zA-Z0-9_\x7f-\xff])/,
        // scope:"wrong"
      },
      CONSTRUCTOR_CALL,
      {
        className: 'function',
        relevance: 0,
        beginKeywords: 'fn function', end: /[;{]/, excludeEnd: true,
        illegal: '[$%\\[]',
        contains: [
          {
            beginKeywords: 'use',
          },
          hljs.UNDERSCORE_TITLE_MODE,
          {
            begin: '=>', // No markup, just a relevance booster
            endsParent: true
          },
          {
            className: 'params',
            begin: '\\(', end: '\\)',
            excludeBegin: true,
            excludeEnd: true,
            keywords: KEYWORDS,
            contains: [
              'self',
              VARIABLE,
              hljs.C_BLOCK_COMMENT_MODE,
              STRING,
              NUMBER
            ]
          }
        ]
      },
      {
        className: 'class',
        variants: [
          { beginKeywords: "enum", illegal: /[($"]/ },
          { beginKeywords: "class interface trait", illegal: /[:($"]/ }
        ],
        relevance: 0,
        end: /\{/,
        excludeEnd: true,
        contains: [
          {beginKeywords: 'extends implements'},
          hljs.UNDERSCORE_TITLE_MODE
        ]
      },
      // both use and namespace still use "old style" rules (vs multi-match)
      // because the namespace name can include `\` and we still want each
      // element to be treated as its own *individual* title
      {
        beginKeywords: 'namespace',
        relevance: 0,
        end: ';',
        illegal: /[.']/,
        contains: [
          hljs.inherit(hljs.UNDERSCORE_TITLE_MODE, { scope: "title.class" })
        ]
      },
      {
        beginKeywords: 'use',
        relevance: 0,
        end: ';',
        contains: [
          // TODO: title.function vs title.class
          {
            match: /\b(as|const|function)\b/,
            scope: "keyword"
          },
          // TODO: could be title.class or title.function
          hljs.UNDERSCORE_TITLE_MODE
        ]
      },
      STRING,
      NUMBER
    ]
  };
}
<commit_msg>chore(php) add list of valid whitespaces<commit_after>/*
Language: PHP
Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Ivan Sagalaev <maniac@softwaremaniacs.org>
Website: https://www.php.net
Category: common
*/

/**
 * @param {HLJSApi} hljs
 * @returns {LanguageDetail}
 * */
export default function(hljs) {
  const regex = hljs.regex;
  const VARIABLE = {
    className: 'variable',
    begin: '\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*' +
      // negative look-ahead tries to avoid matching patterns that are not
      // Perl at all like $ident$, @ident@, etc.
      `(?![A-Za-z0-9])(?![$])`
  };
  const PREPROCESSOR = {
    className: 'meta',
    variants: [
      { begin: /<\?php/, relevance: 10 }, // boost for obvious PHP
      { begin: /<\?[=]?/ },
      { begin: /\?>/ } // end php tag
    ]
  };
  const SUBST = {
    className: 'subst',
    variants: [
      { begin: /\$\w+/ },
      { begin: /\{\$/, end: /\}/ }
    ]
  };
  const SINGLE_QUOTED = hljs.inherit(hljs.APOS_STRING_MODE, {
    illegal: null,
  });
  const DOUBLE_QUOTED = hljs.inherit(hljs.QUOTE_STRING_MODE, {
    illegal: null,
    contains: hljs.QUOTE_STRING_MODE.contains.concat(SUBST),
  });
  const HEREDOC = hljs.END_SAME_AS_BEGIN({
    begin: /<<<[ \t]*(\w+)\n/,
    end: /[ \t]*(\w+)\b/,
    contains: hljs.QUOTE_STRING_MODE.contains.concat(SUBST),
  });
  // list of valid whitespaces because non-breaking space might be part of a name
  const WHITESPACE = '[ \t\n]';
  const STRING = {
    className: 'string',
    variants: [
      DOUBLE_QUOTED,
      SINGLE_QUOTED,
      HEREDOC
    ]
  };
  const NUMBER = {
    className: 'number',
    variants: [
      { begin: `\\b0[bB][01]+(?:_[01]+)*\\b` }, // Binary w/ underscore support
      { begin: `\\b0[oO][0-7]+(?:_[0-7]+)*\\b` }, // Octals w/ underscore support
      { begin: `\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b` }, // Hex w/ underscore support
      // Decimals w/ underscore support, with optional fragments and scientific exponent (e) suffix.
      { begin: `(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?` }
    ],
    relevance: 0
  };
  const LITERALS = [
    "false",
    "null",
    "true"
  ];
  const KWS = [
    // Magic constants:
    // <https://www.php.net/manual/en/language.constants.predefined.php>
    "__CLASS__",
    "__DIR__",
    "__FILE__",
    "__FUNCTION__",
    "__COMPILER_HALT_OFFSET__",
    "__LINE__",
    "__METHOD__",
    "__NAMESPACE__",
    "__TRAIT__",
    // Function that look like language construct or language construct that look like function:
    // List of keywords that may not require parenthesis
    "die",
    "echo",
    "exit",
    "include",
    "include_once",
    "print",
    "require",
    "require_once",
    // These are not language construct (function) but operate on the currently-executing function and can access the current symbol table
    // 'compact extract func_get_arg func_get_args func_num_args get_called_class get_parent_class ' +
    // Other keywords:
    // <https://www.php.net/manual/en/reserved.php>
    // <https://www.php.net/manual/en/language.types.type-juggling.php>
    "array",
    "abstract",
    "and",
    "as",
    "binary",
    "bool",
    "boolean",
    "break",
    "callable",
    "case",
    "catch",
    "class",
    "clone",
    "const",
    "continue",
    "declare",
    "default",
    "do",
    "double",
    "else",
    "elseif",
    "empty",
    "enddeclare",
    "endfor",
    "endforeach",
    "endif",
    "endswitch",
    "endwhile",
    "enum",
    "eval",
    "extends",
    "final",
    "finally",
    "float",
    "for",
    "foreach",
    "from",
    "global",
    "goto",
    "if",
    "implements",
    "instanceof",
    "insteadof",
    "int",
    "integer",
    "interface",
    "isset",
    "iterable",
    "list",
    "match|0",
    "mixed",
    "new",
    "object",
    "or",
    "private",
    "protected",
    "public",
    "real",
    "return",
    "string",
    "switch",
    "throw",
    "trait",
    "try",
    "unset",
    "use",
    "var",
    "void",
    "while",
    "xor",
    "yield"
  ];

  const BUILT_INS = [
    // Standard PHP library:
    // <https://www.php.net/manual/en/book.spl.php>
    "Error|0",
    "AppendIterator",
    "ArgumentCountError",
    "ArithmeticError",
    "ArrayIterator",
    "ArrayObject",
    "AssertionError",
    "BadFunctionCallException",
    "BadMethodCallException",
    "CachingIterator",
    "CallbackFilterIterator",
    "CompileError",
    "Countable",
    "DirectoryIterator",
    "DivisionByZeroError",
    "DomainException",
    "EmptyIterator",
    "ErrorException",
    "Exception",
    "FilesystemIterator",
    "FilterIterator",
    "GlobIterator",
    "InfiniteIterator",
    "InvalidArgumentException",
    "IteratorIterator",
    "LengthException",
    "LimitIterator",
    "LogicException",
    "MultipleIterator",
    "NoRewindIterator",
    "OutOfBoundsException",
    "OutOfRangeException",
    "OuterIterator",
    "OverflowException",
    "ParentIterator",
    "ParseError",
    "RangeException",
    "RecursiveArrayIterator",
    "RecursiveCachingIterator",
    "RecursiveCallbackFilterIterator",
    "RecursiveDirectoryIterator",
    "RecursiveFilterIterator",
    "RecursiveIterator",
    "RecursiveIteratorIterator",
    "RecursiveRegexIterator",
    "RecursiveTreeIterator",
    "RegexIterator",
    "RuntimeException",
    "SeekableIterator",
    "SplDoublyLinkedList",
    "SplFileInfo",
    "SplFileObject",
    "SplFixedArray",
    "SplHeap",
    "SplMaxHeap",
    "SplMinHeap",
    "SplObjectStorage",
    "SplObserver",
    "SplPriorityQueue",
    "SplQueue",
    "SplStack",
    "SplSubject",
    "SplTempFileObject",
    "TypeError",
    "UnderflowException",
    "UnexpectedValueException",
    "UnhandledMatchError",
    // Reserved interfaces:
    // <https://www.php.net/manual/en/reserved.interfaces.php>
    "ArrayAccess",
    "Closure",
    "Generator",
    "Iterator",
    "IteratorAggregate",
    "Serializable",
    "Stringable",
    "Throwable",
    "Traversable",
    "WeakReference",
    "WeakMap",
    // Reserved classes:
    // <https://www.php.net/manual/en/reserved.classes.php>
    "Directory",
    "__PHP_Incomplete_Class",
    "parent",
    "php_user_filter",
    "self",
    "static",
    "stdClass"
  ];

  /** Dual-case keywords
   *
   * ["then","FILE"] =>
   *     ["then", "THEN", "FILE", "file"]
   *
   * @param {string[]} items */
  const dualCase = (items) => {
    /** @type string[] */
    const result = [];
    items.forEach(item => {
      result.push(item);
      if (item.toLowerCase() === item) {
        result.push(item.toUpperCase());
      } else {
        result.push(item.toLowerCase());
      }
    });
    return result;
  };

  const KEYWORDS = {
    keyword: KWS,
    literal: dualCase(LITERALS),
    built_in: BUILT_INS,
  };

  /**
   * @param {string[]} items */
  const normalizeKeywords = (items) => {
    return items.map(item => {
      return item.replace(/\|\d+$/, "");
    });
  };

  const CONSTRUCTOR_CALL = {
    variants: [
      {
        match: [
          /new/,
          regex.concat(WHITESPACE, "+"),
          // to prevent built ins from being confused as the class constructor call
          regex.concat("(?!", normalizeKeywords(BUILT_INS).join("\\b|"), "\\b)"),
          /\\?\w+/,
          regex.concat(WHITESPACE, "*\\("),
        ],
        scope: {
          1: "keyword",
          4: "title.class",
        },
      }
    ]
  };

  const FUNCTION_INVOKE = {
    relevance: 0,
    match: [
      /\b/,
      // to prevent keywords from being confused as the function title
      regex.concat("(?!fn\\b|function\\b|", normalizeKeywords(KWS).join("\\b|"), "|", normalizeKeywords(BUILT_INS).join("\\b|"), "\\b)"),
      /\w+/,
      regex.concat(WHITESPACE, "*"),
      regex.lookahead(/(?=\()/)
    ],
    scope: {
      3: "function.title.invoke",
    }
  };

  return {
    case_insensitive: false,
    keywords: KEYWORDS,
    contains: [
      hljs.HASH_COMMENT_MODE,
      hljs.COMMENT('//', '$'),
      hljs.COMMENT(
        '/\\*',
        '\\*/',
        {
          contains: [
            {
              className: 'doctag',
              begin: '@[A-Za-z]+'
            }
          ]
        }
      ),
      {
        match: /__halt_compiler\(\);/,
        keywords: '__halt_compiler',
        starts: {
          scope: "comment",
          end: hljs.MATCH_NOTHING_RE,
          contains: [
            {
              match: /\?>/,
              scope: "meta",
              endsParent: true
            }
          ]
        }
      },
      PREPROCESSOR,
      {
        className: 'variable.language',
        begin: /\$this\b/
      },
      VARIABLE,
      FUNCTION_INVOKE,
      {
        // swallow composed identifiers to avoid parsing them as keywords
        match: regex.concat(
          /(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/,
          regex.concat("(?!", WHITESPACE, "*\\()"),
          /(?![a-zA-Z0-9_\x7f-\xff])/
        ),
        // scope:"wrong"
      },
      CONSTRUCTOR_CALL,
      {
        className: 'function',
        relevance: 0,
        beginKeywords: 'fn function', end: /[;{]/, excludeEnd: true,
        illegal: '[$%\\[]',
        contains: [
          {
            beginKeywords: 'use',
          },
          hljs.UNDERSCORE_TITLE_MODE,
          {
            begin: '=>', // No markup, just a relevance booster
            endsParent: true
          },
          {
            className: 'params',
            begin: '\\(', end: '\\)',
            excludeBegin: true,
            excludeEnd: true,
            keywords: KEYWORDS,
            contains: [
              'self',
              VARIABLE,
              hljs.C_BLOCK_COMMENT_MODE,
              STRING,
              NUMBER
            ]
          }
        ]
      },
      {
        className: 'class',
        variants: [
          { beginKeywords: "enum", illegal: /[($"]/ },
          { beginKeywords: "class interface trait", illegal: /[:($"]/ }
        ],
        relevance: 0,
        end: /\{/,
        excludeEnd: true,
        contains: [
          {beginKeywords: 'extends implements'},
          hljs.UNDERSCORE_TITLE_MODE
        ]
      },
      // both use and namespace still use "old style" rules (vs multi-match)
      // because the namespace name can include `\` and we still want each
      // element to be treated as its own *individual* title
      {
        beginKeywords: 'namespace',
        relevance: 0,
        end: ';',
        illegal: /[.']/,
        contains: [
          hljs.inherit(hljs.UNDERSCORE_TITLE_MODE, { scope: "title.class" })
        ]
      },
      {
        beginKeywords: 'use',
        relevance: 0,
        end: ';',
        contains: [
          // TODO: title.function vs title.class
          {
            match: /\b(as|const|function)\b/,
            scope: "keyword"
          },
          // TODO: could be title.class or title.function
          hljs.UNDERSCORE_TITLE_MODE
        ]
      },
      STRING,
      NUMBER
    ]
  };
}
<|endoftext|>


<commit_before>/*
Language: PHP
Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Ivan Sagalaev <maniac@softwaremaniacs.org>
*/

function(hljs) {
  var VARIABLE = {
    className: 'variable', begin: '\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
  };
  var PREPROCESSOR = {
    className: 'preprocessor', begin: /<\?(php)?|\?>/
  };
  var STRING = {
    className: 'string',
    contains: [hljs.BACKSLASH_ESCAPE, PREPROCESSOR],
    variants: [
      {
        begin: 'b"', end: '"'
      },
      {
        begin: 'b\'', end: '\''
      },
      hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),
      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null})
    ]
  };
  var NUMBER = {variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE]};
  var TITLE = {
    className: 'title', begin: hljs.UNDERSCORE_IDENT_RE, relevance: 0
  };
  return {
    case_insensitive: true,
    keywords:
      'and include_once list abstract global private echo interface as static endswitch ' +
      'array null if endwhile or const for endforeach self var while isset public ' +
      'protected exit foreach throw elseif include __FILE__ empty require_once do xor ' +
      'return parent clone use __CLASS__ __LINE__ else break print eval new ' +
      'catch __METHOD__ case exception default die require __FUNCTION__ ' +
      'enddeclare final try switch continue endfor endif declare unset true false ' +
      'trait goto instanceof insteadof __DIR__ __NAMESPACE__ ' +
      'yield finally',
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.HASH_COMMENT_MODE,
      {
        className: 'comment',
        begin: '/\\*', end: '\\*/',
        contains: [
          {
            className: 'phpdoc',
            begin: '\\s@[A-Za-z]+'
          },
          PREPROCESSOR
        ]
      },
      {
          className: 'comment',
          begin: '__halt_compiler.+?;', endsWithParent: true,
          keywords: '__halt_compiler', lexemes: hljs.UNDERSCORE_IDENT_RE
      },
      {
        className: 'string',
        begin: '<<<[\'"]?\\w+[\'"]?$', end: '^\\w+;',
        contains: [hljs.BACKSLASH_ESCAPE]
      },
      PREPROCESSOR,
      VARIABLE,
      {
        className: 'function',
        beginKeywords: 'function', end: /[;{]/,
        illegal: '\\$|\\[|%',
        contains: [
          TITLE,
          {
            className: 'params',
            begin: '\\(', end: '\\)',
            contains: [
              'self',
              VARIABLE,
              hljs.C_BLOCK_COMMENT_MODE,
              STRING,
              NUMBER
            ]
          }
        ]
      },
      {
        className: 'class',
        beginKeywords: 'class interface', end: '{',
        illegal: '[:\\(\\$]',
        contains: [
          {
            beginKeywords: 'extends implements',
            relevance: 10
          },
          TITLE
        ]
      },
      {
        className: 'namespace',
        beginKeywords: 'namespace', end: ';',
        contains: [TITLE]
      },
      {
        className: 'use',
        beginKeywords: 'use', end: ';',
        contains: [TITLE]
      },
      {
        begin: '=>' // No markup, just a relevance booster
      },
      STRING,
      NUMBER
    ]
  };
}
<commit_msg>Restored base relevance for PHP titles, added illegals for namespaces.<commit_after>/*
Language: PHP
Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Ivan Sagalaev <maniac@softwaremaniacs.org>
*/

function(hljs) {
  var VARIABLE = {
    className: 'variable', begin: '\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
  };
  var PREPROCESSOR = {
    className: 'preprocessor', begin: /<\?(php)?|\?>/
  };
  var STRING = {
    className: 'string',
    contains: [hljs.BACKSLASH_ESCAPE, PREPROCESSOR],
    variants: [
      {
        begin: 'b"', end: '"'
      },
      {
        begin: 'b\'', end: '\''
      },
      hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),
      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null})
    ]
  };
  var NUMBER = {variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE]};
  var TITLE = {
    className: 'title', begin: hljs.UNDERSCORE_IDENT_RE
  };
  return {
    case_insensitive: true,
    keywords:
      'and include_once list abstract global private echo interface as static endswitch ' +
      'array null if endwhile or const for endforeach self var while isset public ' +
      'protected exit foreach throw elseif include __FILE__ empty require_once do xor ' +
      'return parent clone use __CLASS__ __LINE__ else break print eval new ' +
      'catch __METHOD__ case exception default die require __FUNCTION__ ' +
      'enddeclare final try switch continue endfor endif declare unset true false ' +
      'trait goto instanceof insteadof __DIR__ __NAMESPACE__ ' +
      'yield finally',
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.HASH_COMMENT_MODE,
      {
        className: 'comment',
        begin: '/\\*', end: '\\*/',
        contains: [
          {
            className: 'phpdoc',
            begin: '\\s@[A-Za-z]+'
          },
          PREPROCESSOR
        ]
      },
      {
          className: 'comment',
          begin: '__halt_compiler.+?;', endsWithParent: true,
          keywords: '__halt_compiler', lexemes: hljs.UNDERSCORE_IDENT_RE
      },
      {
        className: 'string',
        begin: '<<<[\'"]?\\w+[\'"]?$', end: '^\\w+;',
        contains: [hljs.BACKSLASH_ESCAPE]
      },
      PREPROCESSOR,
      VARIABLE,
      {
        className: 'function',
        beginKeywords: 'function', end: /[;{]/,
        illegal: '\\$|\\[|%',
        contains: [
          TITLE,
          {
            className: 'params',
            begin: '\\(', end: '\\)',
            contains: [
              'self',
              VARIABLE,
              hljs.C_BLOCK_COMMENT_MODE,
              STRING,
              NUMBER
            ]
          }
        ]
      },
      {
        className: 'class',
        beginKeywords: 'class interface', end: '{',
        illegal: '[:\\(\\$]',
        contains: [
          {
            beginKeywords: 'extends implements',
            relevance: 10
          },
          TITLE
        ]
      },
      {
        className: 'namespace',
        beginKeywords: 'namespace', end: ';',
        illegal: /[\.']/,
        contains: [TITLE]
      },
      {
        className: 'use',
        beginKeywords: 'use', end: ';',
        contains: [TITLE]
      },
      {
        begin: '=>' // No markup, just a relevance booster
      },
      STRING,
      NUMBER
    ]
  };
}
<|endoftext|>


<commit_before>/*
Language: HTML, XML
*/

function(hljs) {
  var XML_IDENT_RE = '[A-Za-z0-9\\._:-]+';
  var TAG_INTERNALS = {
    endsWithParent: true,
    illegal: /</,
    relevance: 0,
    contains: [
      {
        className: 'attribute',
        begin: XML_IDENT_RE,
        relevance: 0
      },
      {
        begin: '=',
        relevance: 0,
        contains: [
          {
            className: 'value',
            variants: [
              {begin: /"/, end: /"/},
              {begin: /'/, end: /'/},
              {begin: /[^\s\/>]+/}
            ]
          }
        ]
      }
    ]
  };
  return {
    aliases: ['html'],
    case_insensitive: true,
    contains: [
      {
        className: 'doctype',
        begin: '<!DOCTYPE', end: '>',
        relevance: 10,
        contains: [{begin: '\\[', end: '\\]'}]
      },
      {
        className: 'comment',
        begin: '<!--', end: '-->',
        relevance: 10
      },
      {
        className: 'cdata',
        begin: '<\\!\\[CDATA\\[', end: '\\]\\]>',
        relevance: 10
      },
      {
        className: 'tag',
        /*
        The lookahead pattern (?=...) ensures that 'begin' only matches
        '<style' as a single word, followed by a whitespace or an
        ending braket. The '$' is needed for the lexeme to be recognized
        by hljs.subMode() that tests lexemes outside the stream.
        */
        begin: '<style(?=\\s|>|$)', end: '>',
        keywords: {title: 'style'},
        contains: [TAG_INTERNALS],
        starts: {
          end: '</style>', returnEnd: true,
          subLanguage: 'css'
        }
      },
      {
        className: 'tag',
        // See the comment in the <style tag about the lookahead pattern
        begin: '<script(?=\\s|>|$)', end: '>',
        keywords: {title: 'script'},
        contains: [TAG_INTERNALS],
        starts: {
          end: '</script>', returnEnd: true,
          subLanguage: 'javascript'
        }
      },
      {
        begin: '<%', end: '%>',
        subLanguage: 'vbscript'
      },
      {
        begin: /<\?(php)?(?!\w)/, end: /\?>/,
        subLanguage: 'php', subLanguageMode: 'continuous'
      },
      {
        className: 'pi',
        begin: /<\?\w+/, end: /\?>/,
        relevance: 10
      },
      {
        className: 'tag',
        begin: '</?', end: '/?>',
        contains: [
          {
            className: 'title', begin: '[^ /><]+', relevance: 0
          },
          TAG_INTERNALS
        ]
      }
    ]
  };
}
<commit_msg>Allow PHP in TAG_INTERNALS.<commit_after>/*
Language: HTML, XML
*/

function(hljs) {
  var XML_IDENT_RE = '[A-Za-z0-9\\._:-]+';
  var PHP = {
    begin: /<\?(php)?(?!\w)/, end: /\?>/,
    subLanguage: 'php', subLanguageMode: 'continuous'
  };
  var TAG_INTERNALS = {
    endsWithParent: true,
    illegal: /</,
    relevance: 0,
    contains: [
      PHP,
      {
        className: 'attribute',
        begin: XML_IDENT_RE,
        relevance: 0
      },
      {
        begin: '=',
        relevance: 0,
        contains: [
          {
            className: 'value',
            variants: [
              {begin: /"/, end: /"/},
              {begin: /'/, end: /'/},
              {begin: /[^\s\/>]+/}
            ]
          }
        ]
      }
    ]
  };
  return {
    aliases: ['html'],
    case_insensitive: true,
    contains: [
      {
        className: 'doctype',
        begin: '<!DOCTYPE', end: '>',
        relevance: 10,
        contains: [{begin: '\\[', end: '\\]'}]
      },
      {
        className: 'comment',
        begin: '<!--', end: '-->',
        relevance: 10
      },
      {
        className: 'cdata',
        begin: '<\\!\\[CDATA\\[', end: '\\]\\]>',
        relevance: 10
      },
      {
        className: 'tag',
        /*
        The lookahead pattern (?=...) ensures that 'begin' only matches
        '<style' as a single word, followed by a whitespace or an
        ending braket. The '$' is needed for the lexeme to be recognized
        by hljs.subMode() that tests lexemes outside the stream.
        */
        begin: '<style(?=\\s|>|$)', end: '>',
        keywords: {title: 'style'},
        contains: [TAG_INTERNALS],
        starts: {
          end: '</style>', returnEnd: true,
          subLanguage: 'css'
        }
      },
      {
        className: 'tag',
        // See the comment in the <style tag about the lookahead pattern
        begin: '<script(?=\\s|>|$)', end: '>',
        keywords: {title: 'script'},
        contains: [TAG_INTERNALS],
        starts: {
          end: '</script>', returnEnd: true,
          subLanguage: 'javascript'
        }
      },
      {
        begin: '<%', end: '%>',
        subLanguage: 'vbscript'
      },
      PHP,
      {
        className: 'pi',
        begin: /<\?\w+/, end: /\?>/,
        relevance: 10
      },
      {
        className: 'tag',
        begin: '</?', end: '/?>',
        contains: [
          {
            className: 'title', begin: '[^ /><]+', relevance: 0
          },
          TAG_INTERNALS
        ]
      }
    ]
  };
}
<|endoftext|>


<commit_before> console.log("Adebayo olanrewaju");

/*activity one (data type)

14 = numnber
-80 = numbed
8.5 =number
true = boolean
(5 < 17) = boolean
null = undefined
3.142 = number
"pi" = string
67 + 18 = number*/

 //function converts decimals to binary (activity 2)
 var binaryConverter = function(number){

var reverseNumber = [];

	do {
		reverseNumber.push(number % 2);
		number = Math.floor(number / 2);
		console.log (number);

	} while(number>=1)

	return console.log(reverseNumber.reverse().join(''));

}

binaryConverter(50);

//Activity 3
countChar = function (string, letter)
{
	var letter = letter;
  var counter = 0;
  for (var i = 0; i < (string.length); i++)
    {
      if (string.charAt(i) === letter)
        {
          counter++;
        }
    }

  return counter;
}

countBs = function (string)
{
  var letter = "B";
  var count = 0;
  for (var i = 0; i < (string.length); i++)
    {
      if (string.charAt(i) === letter)
        {
          count++;
        }
    }

  return count;
}

console.log(countBs("BABAA"));
console.log(countChar("Bbazzzooookkkkka", "a"));

//activity 4 fibernacci

var numItems= function(num){
  var number =[2,3]
  for (var i= 0;i < (num-2); i++)
  {
    number.push(number[i]+number[i+1]);

  }
  console.log(number);
};
numItems(prompt("enter a number"));<commit_msg>add activity to feature.js<commit_after> console.log("Adebayo olanrewaju");

/*activity one (data type)

14 = numnber
-80 = numbed
8.5 =number
true = boolean
(5 < 17) = boolean
null = undefined
3.142 = number
"pi" = string
67 + 18 = number*/

 //function converts decimals to binary (activity 2)
 var binaryConverter = function(number){

var reverseNumber = [];

	do {
		reverseNumber.push(number % 2);
		number = Math.floor(number / 2);
		console.log (number);

	} while(number>=1)

	return console.log(reverseNumber.reverse().join(''));

}

binaryConverter(50);

//Activity 3
countChar = function (string, letter)
{
	var letter = letter;
  var counter = 0;
  for (var i = 0; i < (string.length); i++)
    {
      if (string.charAt(i) === letter)
        {
          counter++;
        }
    }

  return counter;
}

countBs = function (string)
{
  var letter = "B";
  var count = 0;
  for (var i = 0; i < (string.length); i++)
    {
      if (string.charAt(i) === letter)
        {
          count++;
        }
    }

  return count;
}

console.log(countBs("BABAA"));
console.log(countChar("Bbazzzooookkkkka", "a"));

//activity 4 fibernacci

var numItems= function(num){
  var number =[2,3]
  for (var i= 0;i < (num-2); i++)
  {
    number.push(number[i]+number[i+1]);

  }
  console.log(number);
};
numItems(prompt("enter a number"));

// fibernacci recussively

var fibo = function(num){
  if (num ==0) return 0;
  if (num ==1) return 1;

  return fibo(num-1) + fibo(num-2);

}

var fibonacci = function(n){
  for (var i=0;i<=n; i++){
  console.log(fibo(i))
}
}
fibonacci(8)

//factorial recussively
var factorial = function(number) {
    if(number === 0) {
        return 1
    } else {
        return number * factorial(number - 1);
    }
}<|endoftext|>


<commit_before>(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define([ 'module', 'angular' ], function (module, angular) {
            module.exports = factory(angular);
        });
    } else if (typeof module === 'object') {
        module.exports = factory(require('angular'));
    } else {
        if (!root.mp) {
            root.mp = {};
        }

        root.mp.autocomplete = factory(root.angular);
    }
}(this, function (angular) {
    'use strict';

    return angular.module('mp.autocomplete', []).directive('autocomplete', [
        '$window', '$q', '$compile', '$parse', '$timeout',
        function($window, $q, $compile, $parse, $timeout) {
            var TEMPLATE = '' +
                '
' +
                '
{{ match }}
' +
                '
';

            var HOT_KEYS = [9, 13, 27, 38, 40];

            return {
                restrict: 'A',
                require: 'ngModel',
                link: function (originalScope, $element, $attributes, ngModel) {
                    // model setter executed upon match selection
                    var $setModelValue = $parse($attributes.ngModel).assign;

                    // suggestion fetch function
                    var fetchSuggestions = originalScope.$eval($attributes.autocomplete);

                    // create a child scope for the directive so that we are not
                    // polluting original scope with matches, query etc.
                    var $scope = originalScope.$new();
                    originalScope.$on('$destroy', function () {
                        $scope.$destroy();
                    });

                    var resetMatches = function () {
                        $scope.matches = [];
                        $scope.selectedIndex = -1;
                    };

                    $scope.isOpen = function () {
                        return $scope.matches.length > 0;
                    };

                    $scope.select = function (selectedIndex) {
                        //called from within the $digest() cycle
                        $setModelValue(originalScope, $scope.matches[selectedIndex]);
                        resetMatches();

                        // @todo Notify observer of selection

                        //return focus to the input element if a match was selected via a mouse click event
                        // use timeout to avoid $rootScope:inprog error
                        $timeout(function () {
                            $element[0].focus();
                        }, 0, false);
                    };

                    $scope.selectNext = function () {
                        $scope.selectedIndex = ($scope.selectedIndex + 1) % $scope.matches.length;
                    };

                    $scope.selectPrev = function () {
                        $scope.selectedIndex = ($scope.selectedIndex > 0
                                                ? $scope.selectedIndex
                                                : $scope.matches.length) - 1;
                    };

                    // 0. Initialize to empty state
                    resetMatches();

                    // 1. Watch model for changes
                    ngModel.$parsers.unshift(function (inputValue) {
                        // @todo: add debouncing
                        // 2. Fetch suggestions
                        fetchSuggestions(inputValue).then(function (suggestions) {
                            // 3. Present suggestions
                            $scope.matches = suggestions;
                        });
                    });

                    // 4. Handle mouse selection or keypresses
                    $element.bind('keydown', function (evt) {
                        // we have matches and an "interesting" key was pressed
                        if ($scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
                            return;
                        }

                        // if there's nothing selected and enter/tab is hit, don't do anything
                        if ($scope.selectedIndex == -1 && (evt.which === 13 || evt.which === 9)) {
                            return;
                        }

                        evt.preventDefault();

                        $scope.$apply(function () {
                            if (evt.which === 40) { // Down Arrow
                                $scope.selectNext();
                            } else if (evt.which === 38) { // Up Arrow
                                $scope.selectPrev();
                            } else if (evt.which === 13 || evt.which === 9) { // Enter or Tab
                                $scope.select($scope.selectedIndex);
                            } else if (evt.which === 27) { // Esc
                                // 6. Handle cancelling of the dialog
                                resetMatches();
                                evt.stopPropagation();
                            }
                        });
                    }).bind('blur', function () {
                        // Close the autocomplete dialog when the element loses focus
                        $scope.$apply(function () {
                            resetMatches();
                        });
                    });

                    var $template = $compile(TEMPLATE)($scope);
                    $element.after($template);
                }
            };
        }
    ]);
}));<commit_msg>Fix selection on click by using ng-mousedown<commit_after>(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define([ 'module', 'angular' ], function (module, angular) {
            module.exports = factory(angular);
        });
    } else if (typeof module === 'object') {
        module.exports = factory(require('angular'));
    } else {
        if (!root.mp) {
            root.mp = {};
        }

        root.mp.autocomplete = factory(root.angular);
    }
}(this, function (angular) {
    'use strict';

    return angular.module('mp.autocomplete', []).directive('autocomplete', [
        '$window', '$q', '$compile', '$parse', '$timeout',
        function($window, $q, $compile, $parse, $timeout) {
            var TEMPLATE = '' +
                '
' +
                '
{{ match }}
' +
                '
';

            var HOT_KEYS = [9, 13, 27, 38, 40];

            return {
                restrict: 'A',
                require: 'ngModel',
                link: function (originalScope, $element, $attributes, ngModel) {
                    // model setter executed upon match selection
                    var $setModelValue = $parse($attributes.ngModel).assign;

                    // suggestion fetch function
                    var fetchSuggestions = originalScope.$eval($attributes.autocomplete);

                    // create a child scope for the directive so that we are not
                    // polluting original scope with matches, query etc.
                    var $scope = originalScope.$new();
                    originalScope.$on('$destroy', function () {
                        $scope.$destroy();
                    });

                    var resetMatches = function () {
                        $scope.matches = [];
                        $scope.selectedIndex = -1;
                    };

                    $scope.isOpen = function () {
                        return $scope.matches.length > 0;
                    };

                    $scope.select = function (selectedIndex) {
                        //called from within the $digest() cycle
                        $setModelValue(originalScope, $scope.matches[selectedIndex]);
                        resetMatches();

                        // @todo Notify observer of selection

                        //return focus to the input element if a match was selected via a mouse click event
                        // use timeout to avoid $rootScope:inprog error
                        $timeout(function () {
                            $element[0].focus();
                        }, 0, false);
                    };

                    $scope.selectNext = function () {
                        $scope.selectedIndex = ($scope.selectedIndex + 1) % $scope.matches.length;
                    };

                    $scope.selectPrev = function () {
                        $scope.selectedIndex = ($scope.selectedIndex > 0
                                                ? $scope.selectedIndex
                                                : $scope.matches.length) - 1;
                    };

                    // 0. Initialize to empty state
                    resetMatches();

                    // 1. Watch model for changes
                    ngModel.$parsers.unshift(function (inputValue) {
                        // @todo: add debouncing
                        // 2. Fetch suggestions
                        fetchSuggestions(inputValue).then(function (suggestions) {
                            // 3. Present suggestions
                            $scope.matches = suggestions;
                        });
                    });

                    // 4. Handle mouse selection or keypresses
                    $element.bind('keydown', function (evt) {
                        // we have matches and an "interesting" key was pressed
                        if ($scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
                            return;
                        }

                        // if there's nothing selected and enter/tab is hit, don't do anything
                        if ($scope.selectedIndex == -1 && (evt.which === 13 || evt.which === 9)) {
                            return;
                        }

                        evt.preventDefault();

                        $scope.$apply(function () {
                            if (evt.which === 40) { // Down Arrow
                                $scope.selectNext();
                            } else if (evt.which === 38) { // Up Arrow
                                $scope.selectPrev();
                            } else if (evt.which === 13 || evt.which === 9) { // Enter or Tab
                                $scope.select($scope.selectedIndex);
                            } else if (evt.which === 27) { // Esc
                                // 6. Handle cancelling of the dialog
                                resetMatches();
                                evt.stopPropagation();
                            }
                        });
                    }).bind('blur', function () {
                        // Close the autocomplete dialog when the element loses focus
                        $scope.$apply(function () {
                            resetMatches();
                        });
                    });

                    var $template = $compile(TEMPLATE)($scope);
                    $element.after($template);
                }
            };
        }
    ]);
}));<|endoftext|>


<commit_before>/*
 * L.GeoJSON turns any GeoJSON data into a Leaflet layer.
 */

L.GeoJSON = L.FeatureGroup.extend({

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

		this._layers = {};

		if (geojson) {
			this.addData(geojson);
		}
	},

	addData: function (geojson) {
		var features = geojson instanceof Array ? geojson : geojson.features,
		    i, len;

		if (features) {
			for (i = 0, len = features.length; i < len; i++) {
				// Only add this if geometry or geometries are set and not null
				if ((typeof features[i].geometries !== undefined && features[i].geometries !== null) &&
					(typeof features[i].geometry !== undefined && features[i].geometry !== null)) {

					this.addData(features[i]);

				}
			}
			return this;
		}

		var options = this.options;

		if (options.filter && !options.filter(geojson)) { return; }

		var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer);
		layer.feature = geojson;

		layer.defaultOptions = layer.options;
		this.resetStyle(layer);

		if (options.onEachFeature) {
			options.onEachFeature(geojson, layer);
		}

		return this.addLayer(layer);
	},

	resetStyle: function (layer) {
		var style = this.options.style;
		if (style) {
			// reset any custom styles
			L.Util.extend(layer.options, layer.defaultOptions);

			this._setLayerStyle(layer, style);
		}
	},

	setStyle: function (style) {
		this.eachLayer(function (layer) {
			this._setLayerStyle(layer, style);
		}, this);
	},

	_setLayerStyle: function (layer, style) {
		if (typeof style === 'function') {
			style = style(layer.feature);
		}
		if (layer.setStyle) {
			layer.setStyle(style);
		}
	}
});

L.extend(L.GeoJSON, {
	geometryToLayer: function (geojson, pointToLayer) {
		var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
		    coords = geometry.coordinates,
		    layers = [],
		    latlng, latlngs, i, len, layer;

		switch (geometry.type) {
		case 'Point':
			latlng = this.coordsToLatLng(coords);
			return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);

		case 'MultiPoint':
			for (i = 0, len = coords.length; i < len; i++) {
				latlng = this.coordsToLatLng(coords[i]);
				layer = pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);
				layers.push(layer);
			}
			return new L.FeatureGroup(layers);

		case 'LineString':
			latlngs = this.coordsToLatLngs(coords);
			return new L.Polyline(latlngs);

		case 'Polygon':
			latlngs = this.coordsToLatLngs(coords, 1);
			return new L.Polygon(latlngs);

		case 'MultiLineString':
			latlngs = this.coordsToLatLngs(coords, 1);
			return new L.MultiPolyline(latlngs);

		case "MultiPolygon":
			latlngs = this.coordsToLatLngs(coords, 2);
			return new L.MultiPolygon(latlngs);

		case "GeometryCollection":
			for (i = 0, len = geometry.geometries.length; i < len; i++) {
				layer = this.geometryToLayer(geometry.geometries[i], pointToLayer);
				layers.push(layer);
			}
			return new L.FeatureGroup(layers);

		default:
			throw new Error('Invalid GeoJSON object.');
		}
	},

	coordsToLatLng: function (coords, reverse) { // (Array, Boolean) -> LatLng
		var lat = parseFloat(coords[reverse ? 0 : 1]),
		    lng = parseFloat(coords[reverse ? 1 : 0]);

		return new L.LatLng(lat, lng);
	},

	coordsToLatLngs: function (coords, levelsDeep, reverse) { // (Array, Number, Boolean) -> Array
		var latlng,
		    latlngs = [],
		    i, len;

		for (i = 0, len = coords.length; i < len; i++) {
			latlng = levelsDeep ?
			        this.coordsToLatLngs(coords[i], levelsDeep - 1, reverse) :
			        this.coordsToLatLng(coords[i], reverse);

			latlngs.push(latlng);
		}

		return latlngs;
	}
});

L.geoJson = function (geojson, options) {
	return new L.GeoJSON(geojson, options);
};
<commit_msg>Simplifying condition for null geojson geometries.<commit_after>/*
 * L.GeoJSON turns any GeoJSON data into a Leaflet layer.
 */

L.GeoJSON = L.FeatureGroup.extend({

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

		this._layers = {};

		if (geojson) {
			this.addData(geojson);
		}
	},

	addData: function (geojson) {
		var features = geojson instanceof Array ? geojson : geojson.features,
		    i, len;

		if (features) {
			for (i = 0, len = features.length; i < len; i++) {
				// Only add this if geometry or geometries are set and not null
				if (features[i].geometries || features[i].geometry) {
					this.addData(features[i]);
				}
			}
			return this;
		}

		var options = this.options;

		if (options.filter && !options.filter(geojson)) { return; }

		var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer);
		layer.feature = geojson;

		layer.defaultOptions = layer.options;
		this.resetStyle(layer);

		if (options.onEachFeature) {
			options.onEachFeature(geojson, layer);
		}

		return this.addLayer(layer);
	},

	resetStyle: function (layer) {
		var style = this.options.style;
		if (style) {
			// reset any custom styles
			L.Util.extend(layer.options, layer.defaultOptions);

			this._setLayerStyle(layer, style);
		}
	},

	setStyle: function (style) {
		this.eachLayer(function (layer) {
			this._setLayerStyle(layer, style);
		}, this);
	},

	_setLayerStyle: function (layer, style) {
		if (typeof style === 'function') {
			style = style(layer.feature);
		}
		if (layer.setStyle) {
			layer.setStyle(style);
		}
	}
});

L.extend(L.GeoJSON, {
	geometryToLayer: function (geojson, pointToLayer) {
		var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
		    coords = geometry.coordinates,
		    layers = [],
		    latlng, latlngs, i, len, layer;

		switch (geometry.type) {
		case 'Point':
			latlng = this.coordsToLatLng(coords);
			return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);

		case 'MultiPoint':
			for (i = 0, len = coords.length; i < len; i++) {
				latlng = this.coordsToLatLng(coords[i]);
				layer = pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);
				layers.push(layer);
			}
			return new L.FeatureGroup(layers);

		case 'LineString':
			latlngs = this.coordsToLatLngs(coords);
			return new L.Polyline(latlngs);

		case 'Polygon':
			latlngs = this.coordsToLatLngs(coords, 1);
			return new L.Polygon(latlngs);

		case 'MultiLineString':
			latlngs = this.coordsToLatLngs(coords, 1);
			return new L.MultiPolyline(latlngs);

		case "MultiPolygon":
			latlngs = this.coordsToLatLngs(coords, 2);
			return new L.MultiPolygon(latlngs);

		case "GeometryCollection":
			for (i = 0, len = geometry.geometries.length; i < len; i++) {
				layer = this.geometryToLayer(geometry.geometries[i], pointToLayer);
				layers.push(layer);
			}
			return new L.FeatureGroup(layers);

		default:
			throw new Error('Invalid GeoJSON object.');
		}
	},

	coordsToLatLng: function (coords, reverse) { // (Array, Boolean) -> LatLng
		var lat = parseFloat(coords[reverse ? 0 : 1]),
		    lng = parseFloat(coords[reverse ? 1 : 0]);

		return new L.LatLng(lat, lng);
	},

	coordsToLatLngs: function (coords, levelsDeep, reverse) { // (Array, Number, Boolean) -> Array
		var latlng,
		    latlngs = [],
		    i, len;

		for (i = 0, len = coords.length; i < len; i++) {
			latlng = levelsDeep ?
			        this.coordsToLatLngs(coords[i], levelsDeep - 1, reverse) :
			        this.coordsToLatLng(coords[i], reverse);

			latlngs.push(latlng);
		}

		return latlngs;
	}
});

L.geoJson = function (geojson, options) {
	return new L.GeoJSON(geojson, options);
};
<|endoftext|>


<commit_before>var dom = require('@nymag/dom'),
  _ = require('lodash'),
  createService = require('../services/create-service'),
  kilnServices = window.kiln.services,
  references = kilnServices.references,
  references = kilnServices.references,
  render = kilnServices.render,
  focus = kilnServices.focus,
  select = kilnServices.select,
  progress = kilnServices.progress,
  select = kilnServices.select,
  edit = kilnServices.edit,
  filterableList = kilnServices['filterable-list'],
  pane = kilnServices.pane,
  activeClass = 'space-logic-active',
  spaceName = 'clay-space',
  editingClass = 'space-logic-editing',
  kilnHide = 'kiln-hide';

function AddComponent(spaceParent, callback) {
  this.parent = spaceParent;

  this.parentRef = spaceParent.getAttribute('data-uri');

  this.callback = callback;

  this.launchPane();
}

var proto = AddComponent.prototype;

/**
 * [launchPane description]
 * @return {[type]} [description]
 */
proto.launchPane = function() {
  var availableComponents = this.parent.getAttribute('data-components').split(','),
    paneContent = filterableList.create(availableComponents, {
      click: this.listItemClick.bind(this),
    });
  pane.close();

  pane.open([{ header: 'Browse Space', content: paneContent }]);
}

/**
 * [listItemClick description]
 * @return {[type]} [description]
 */
proto.listItemClick = function(id) {
  createService.newComponentInLogic(id)
    .then(function(newComponent) {
      var prevRef = dom.find(this.parent, '.space-logic').getAttribute('data-uri'),
        args = {
          ref: newComponent._ref,
          parentField: 'content',
          parentRef: this.parentRef,
          prevRef: prevRef,
          above: true
        };

      return edit.addToParentList(args)
        .then(function(newEl) {
          // insert it at the beginning of the component list
          dom.prependChild(this.parent, newEl);
          return newEl;
        }.bind(this))
        .then(function(newEl) {
          return render.addComponentsHandlers(newEl).then(function() {
            this.makeNewComponentActive(newEl);
            focus.unfocus();
            select.unselect();
            pane.close();
            this.callback(newEl);
            return select.select(dom.find(newEl, '[data-uri]'));
          }.bind(this));
        }.bind(this));
    }.bind(this));
}

proto.makeNewComponentActive = function(targetEl) {
  var logics = dom.findAll(this.parent, '.space-logic');

  _.forEach(logics, function(logic) {
    logic.classList.remove(editingClass);
  });

  targetEl.classList.add(editingClass);
}

module.exports = function(spaceParent, callback) {
  return new AddComponent(spaceParent, callback);
};
<commit_msg>Reordering the function for assigning active component on addition of new component to space<commit_after>var dom = require('@nymag/dom'),
  _ = require('lodash'),
  createService = require('../services/create-service'),
  kilnServices = window.kiln.services,
  references = kilnServices.references,
  references = kilnServices.references,
  render = kilnServices.render,
  focus = kilnServices.focus,
  select = kilnServices.select,
  progress = kilnServices.progress,
  select = kilnServices.select,
  edit = kilnServices.edit,
  filterableList = kilnServices['filterable-list'],
  pane = kilnServices.pane,
  activeClass = 'space-logic-active',
  spaceName = 'clay-space',
  editingClass = 'space-logic-editing',
  kilnHide = 'kiln-hide';

function AddComponent(spaceParent, callback) {
  this.parent = spaceParent;

  this.parentRef = spaceParent.getAttribute('data-uri');

  this.callback = callback;

  this.launchPane();
}

var proto = AddComponent.prototype;

/**
 * [launchPane description]
 * @return {[type]} [description]
 */
proto.launchPane = function() {
  var availableComponents = this.parent.getAttribute('data-components').split(','),
    paneContent = filterableList.create(availableComponents, {
      click: this.listItemClick.bind(this),
    });
  pane.close();

  pane.open([{ header: 'Browse Space', content: paneContent }]);
}

/**
 * [listItemClick description]
 * @return {[type]} [description]
 */
proto.listItemClick = function(id) {
  createService.newComponentInLogic(id)
    .then(function(newComponent) {
      var prevRef = dom.find(this.parent, '.space-logic').getAttribute('data-uri'),
        args = {
          ref: newComponent._ref,
          parentField: 'content',
          parentRef: this.parentRef,
          prevRef: prevRef,
          above: true
        };

      return edit.addToParentList(args)
        .then(function(newEl) {
          // insert it at the beginning of the component list
          dom.prependChild(this.parent, newEl);
          return newEl;
        }.bind(this))
        .then(function(newEl) {
          return render.addComponentsHandlers(newEl).then(function() {

            focus.unfocus();
            select.unselect();
            pane.close();
            this.callback(newEl);
            this.makeNewComponentActive(newEl);
            return select.select(dom.find(newEl, '[data-uri]'));
          }.bind(this));
        }.bind(this));
    }.bind(this));
}

proto.makeNewComponentActive = function(targetEl) {
  var logics = dom.findAll(this.parent, '.space-logic');

  _.forEach(logics, function(logic) {
    logic.classList.remove(editingClass);
  });

  targetEl.classList.add(editingClass);
}

module.exports = function(spaceParent, callback) {
  return new AddComponent(spaceParent, callback);
};
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import Link, { navigateTo } from 'gatsby-link'
import Helmet from 'react-helmet'

// React components
import Header from '../components/Header/Header'
import Footer from '../components/Footer'
import Container from '../components/Container'
import SecretsModal from '../components/SecretsModal'

import 'normalize.css'
import '../fonts/pxplus_ibm_vga8.css'
import '../styles/globals.css'

import styles from './index.module.css'

class TemplateWrapper extends React.Component {
  constructor () {
    super()
  }

  render () {
    const { siteMetadata, buildTime } = this.props.data.site
    const { children } = this.props

    return (

        <Container>

            <Helmet
              title={siteMetadata.title}
              meta={[
                { name: 'description', content: siteMetadata.description },
                { name: 'keywords', content: 'sample, something' },
              ]}
            />
            <SecretsModal />

              {children()}

        </Container>

    )
  }
}

TemplateWrapper.propTypes = {
  data: PropTypes.object,
  children: PropTypes.func
}

export default TemplateWrapper

export const query = graphql`
  query IndexLayoutQuery {
    site {
      siteMetadata {
        title
        description
        author {
          name
          url
          email
        }
      }
      buildTime
    }
  }
`
<commit_msg>locrian<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import Link, { navigateTo } from 'gatsby-link'
import Helmet from 'react-helmet'
import Konami from 'react-konami'

// React components
import Header from '../components/Header/Header'
import Footer from '../components/Footer'
import Container from '../components/Container'
import SecretsModal from '../components/SecretsModal'

import 'normalize.css'
import '../fonts/pxplus_ibm_vga8.css'
import '../styles/globals.css'

import styles from './index.module.css'

class TemplateWrapper extends React.Component {
  constructor () {
    super()
  }

  render () {
    const { siteMetadata, buildTime } = this.props.data.site
    const { children } = this.props

    return (

        <Container>

            <Helmet
              title={siteMetadata.title}
              meta={[
                { name: 'description', content: siteMetadata.description },
                { name: 'keywords', content: 'sample, something' },
              ]}
            />
            <Konami konami={[76, 79, 67, 82, 73, 65, 78]} easterEgg={() => window.open("https://twitter.com/locrian_memes")} />
            <SecretsModal />

              {children()}

        </Container>

    )
  }
}

TemplateWrapper.propTypes = {
  data: PropTypes.object,
  children: PropTypes.func
}

export default TemplateWrapper

export const query = graphql`
  query IndexLayoutQuery {
    site {
      siteMetadata {
        title
        description
        author {
          name
          url
          email
        }
      }
      buildTime
    }
  }
`
<|endoftext|>