<commit_before>import { Component } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import Link from 'next/link'
import PropTypes from 'prop-types'

import { lottery } from '../modules/game'

import Slot from './Slot'

const onClick = select => () => {
  select(1)
}

class IndexContainer extends Component {
  render () {
    return (

            <Slot
              pattern={this.props.pattern}
              members={this.props.members}
              reelTop={this.props.reelTop}
            />

        <Link href='result'>

        </Link>

        <button className='btn-next' onClick={onClick(this.props.lottery)} disabled={this.props.isEnd || this.props.isAnimating} aria-label='next' />

    )
  }
}

IndexContainer.propTypes = {
  isEnd: PropTypes.bool.isRequired,
  members: PropTypes.object.isRequired,
  lottery: PropTypes.func.isRequired,
  isAnimating: PropTypes.bool.isRequired,
  pattern: PropTypes.array.isRequired,
  reelTop: PropTypes.number.isRequired
}

const mapStateToProps = (state) => {
  return {
    isEnd: state.game.isEnd,
    members: state.members.byId,
    isAnimating: state.slot.isAnimating,
    pattern: state.slot.pattern,
    reelTop: state.slot.reelTop
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    lottery: bindActionCreators(lottery, dispatch)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(IndexContainer)
<commit_msg>Modify style.<commit_after>import { Component } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import Link from 'next/link'
import PropTypes from 'prop-types'

import { lottery } from '../modules/game'

import Slot from './Slot'

const onClick = select => () => {
  select(1)
}

class IndexContainer extends Component {
  render () {
    return (

            <Slot
              pattern={this.props.pattern}
              members={this.props.members}
              reelTop={this.props.reelTop}
            />

        <Link href='result'>

        </Link>

        <button className='btn-next' onClick={onClick(this.props.lottery)} disabled={this.props.isEnd || this.props.isAnimating} aria-label='next' />

    )
  }
}

IndexContainer.propTypes = {
  isEnd: PropTypes.bool.isRequired,
  members: PropTypes.object.isRequired,
  lottery: PropTypes.func.isRequired,
  isAnimating: PropTypes.bool.isRequired,
  pattern: PropTypes.array.isRequired,
  reelTop: PropTypes.number.isRequired
}

const mapStateToProps = (state) => {
  return {
    isEnd: state.game.isEnd,
    members: state.members.byId,
    isAnimating: state.slot.isAnimating,
    pattern: state.slot.pattern,
    reelTop: state.slot.reelTop
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    lottery: bindActionCreators(lottery, dispatch)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(IndexContainer)
<|endoftext|>


<commit_before>/**
 * Grunt autoprefixer plugin
 * https://github.com/jscs-dev/grunt-jscs
 */
module.exports = function( grunt, options ) {
    return {
        options: {
            browsers: [ 'last 2 versions', 'ie >= 8', 'Firefox >= 12', 'ios >= 7', 'android >= 4' ]
        },
        development: {
            src: '<%= srcPath %>css/**/*.css'
        },
        production: {
            src: '<%= distPath %>css/**/*.css'
        }
    };
};
<commit_msg>change path to src for autoprefixer<commit_after>/**
 * Grunt autoprefixer plugin
 * https://github.com/jscs-dev/grunt-jscs
 */
module.exports = function( grunt, options ) {
    return {
        options: {
            browsers: [ 'last 2 versions', 'ie >= 8', 'Firefox >= 12', 'ios >= 7', 'android >= 4' ]
        },
        development: {
            src: '<%= distPath %>css/**/*.css'
        },
        production: {
            src: '<%= distPath %>css/**/*.css'
        }
    };
};
<|endoftext|>


<commit_before>module.exports = function(config) {
  'use strict';
  return {
    options: {
      livereload: false
    },

    assets: {
      files: [
        '<%= pkg.gruntConfig.clientDir %>/{fonts,images}/**/*',
        '<%= pkg.gruntConfig.clientDir %>/index.html',
        '<%= pkg.gruntConfig.clientDir %>/favicon.ico'
      ],
      tasks: [
        'newer:copy:assets'
      ]
    },

    styles: {
      files: [
        '<%= pkg.gruntConfig.clientDir %>/styles/**/*.{css,less}',
        '<%= pkg.gruntConfig.clientDir %>/scripts/**/*.{css,less}'
      ],
      tasks: [
        'less'
      ]
    },

    scripts: {
      files: [
        '<%= pkg.gruntConfig.clientDir %>/scripts/**/*.{js,html,json}'
      ],
      tasks: [
        'newer:jshint:scripts',
        'localescompile',
        'requirejs:scripts'
      ]
    },

    config: {
      files: [
        '<%= pkg.gruntConfig.clientDir %>/scripts/config/config.js'
      ],
      tasks: [
        'copy:config'
      ]
    },

    sdk: {
      files: [
        'node_modules/camunda-commons-ui/lib/**/*.js',
        'node_modules/camunda-commons-ui/{resources,lib/*}/locales/**/*.json',
        'node_modules/camunda-bpm-sdk-js/dist/**/*.js'
      ],
      tasks: [
        'localescompile',
        'requirejs:scripts',
        'requirejs:dependencies'
      ]
    },

    served: {
      files: ['<%= buildTarget %>/**/*'],
      options: {
        livereload: config.livereloadPort || false
      }
    }
  };
};
<commit_msg>impr(watch): align served watch task<commit_after>module.exports = function(config) {
  'use strict';
  return {
    options: {
      livereload: false
    },

    assets: {
      files: [
        '<%= pkg.gruntConfig.clientDir %>/{fonts,images}/**/*',
        '<%= pkg.gruntConfig.clientDir %>/index.html',
        '<%= pkg.gruntConfig.clientDir %>/favicon.ico'
      ],
      tasks: [
        'newer:copy:assets'
      ]
    },

    styles: {
      files: [
        '<%= pkg.gruntConfig.clientDir %>/styles/**/*.{css,less}',
        '<%= pkg.gruntConfig.clientDir %>/scripts/**/*.{css,less}'
      ],
      tasks: [
        'less'
      ]
    },

    scripts: {
      files: [
        '<%= pkg.gruntConfig.clientDir %>/scripts/**/*.{js,html,json}'
      ],
      tasks: [
        'newer:jshint:scripts',
        'localescompile',
        'requirejs:scripts'
      ]
    },

    config: {
      files: [
        '<%= pkg.gruntConfig.clientDir %>/scripts/config/config.js'
      ],
      tasks: [
        'copy:config'
      ]
    },

    sdk: {
      files: [
        'node_modules/camunda-commons-ui/lib/**/*.js',
        'node_modules/camunda-commons-ui/{resources,lib/*}/locales/**/*.json',
        'node_modules/camunda-bpm-sdk-js/dist/**/*.js'
      ],
      tasks: [
        'localescompile',
        'requirejs:scripts',
        'requirejs:dependencies'
      ]
    },

    served: {
      options: {
        cwd: '<%= buildTarget %>/',
        livereload: config.livereloadPort || false
      },
      files: '**/*.{css,html,js}'
    }
  };
};
<|endoftext|>


<commit_before>const schedule = require('./schedule');
const { getUpdatedPackageFiles } = require('./get-updated');
const { getAdditionalFiles } = require('../../manager/npm/post-update');
const { commitFilesToBranch } = require('./commit');
const { getParentBranch } = require('./parent');
const { tryBranchAutomerge } = require('./automerge');
const { setUnpublishable } = require('./status-checks');
const { prAlreadyExisted } = require('./check-existing');
const prWorker = require('../pr');

const { isScheduledNow } = schedule;

module.exports = {
  processBranch,
};

async function processBranch(branchConfig, packageFiles) {
  logger.debug(`processBranch with ${branchConfig.upgrades.length} upgrades`);
  const config = { ...branchConfig };
  const dependencies = config.upgrades
    .map(upgrade => upgrade.depName)
    .filter(v => v) // remove nulls (happens for lock file maintenance)
    .filter((value, i, list) => list.indexOf(value) === i); // remove duplicates
  logger.setMeta({
    repository: config.repository,
    branch: config.branchName,
    dependencies,
  });
  logger.debug('processBranch()');
  logger.trace({ config });
  await platform.setBaseBranch(config.baseBranch);
  const branchExists = await platform.branchExists(config.branchName);
  logger.debug(`branchExists=${branchExists}`);
  if (!branchExists && config.prHourlyLimitReached) {
    logger.info('Reached PR creation limit - skipping branch creation');
    return 'pr-hourly-limit-reached';
  }
  try {
    logger.info(
      `Branch has ${dependencies ? dependencies.length : 0} upgrade(s)`
    );

    // Check if branch already existed
    const existingPr = await prAlreadyExisted(config);
    if (existingPr) {
      logger.info(
        { prTitle: config.prTitle },
        'Closed PR already exists. Skipping branch.'
      );
      if (existingPr.state === 'closed') {
        const subject = 'Renovate Ignore Notification';
        let content;
        if (config.type === 'major') {
          content = `As this PR has been closed unmerged, Renovate will ignore this upgrade and you will not receive PRs for *any* future ${
            config.newVersionMajor
          }.x releases. However, if you upgrade to ${
            config.newVersionMajor
          }.x manually then Renovate will then reenable updates for minor and patch updates automatically.`;
        } else if (config.type === 'digest') {
          content = `As this PR has been closed unmerged, Renovate will ignore this upgrade type and you will not receive PRs for *any* future ${
            config.depName
          }:${
            config.currentTag
          } digest updates. Digest updates will resume if you update the specified tag at any time.`;
        } else {
          content = `As this PR has been closed unmerged, Renovate will now ignore this update (${
            config.newVersion
          }). You will still receive a PR once a newer version is released, so if you wish to permanently ignore this dependency, please add it to the \`ignoreDeps\` array of your renovate config.`;
        }
        content +=
          '\n\nIf this PR was closed by mistake or you changed your mind, you can simply rename this PR and you will soon get a fresh replacement PR opened.';
        await platform.ensureComment(existingPr.number, subject, content);
        if (branchExists) {
          await platform.deleteBranch(config.branchName);
        }
      } else if (existingPr.state === 'merged') {
        logger.info(
          { pr: existingPr.number },
          'Merged PR is blocking this branch'
        );
      }
      return 'already-existed';
    }
    if (branchExists) {
      logger.debug('Checking if PR has been edited');
      const branchPr = await platform.getBranchPr(config.branchName);
      if (branchPr) {
        logger.debug({ branchPr }, 'Found existing PR');
        if (!branchPr.canRebase) {
          const subject = 'PR has been edited';
          logger.info(subject);
          let content =
            'As this PR has been edited, Renovate will stop updating it in order to not cause any conflicts or other problems.';
          content +=
            ' If you wish to abandon your edits and have Renovate recreate this PR then you should rename this PR and then close it.';
          await platform.ensureComment(branchPr.number, subject, content);
          return 'pr-edited';
        }
      }
    }

    // Check schedule
    config.isScheduledNow = isScheduledNow(config);
    if (!config.isScheduledNow) {
      if (!branchExists) {
        logger.info('Skipping branch creation as not within schedule');
        return 'not-scheduled';
      }
      if (config.updateNotScheduled === false) {
        logger.debug('Skipping branch update as not within schedule');
        return 'not-scheduled';
      }
      logger.debug(
        'Branch exists but is not scheduled -- will update if necessary'
      );
    }

    if (
      config.type !== 'lockFileMaintenance' &&
      config.unpublishSafe &&
      !config.unpublishable &&
      (config.prCreation === 'not-pending' ||
        config.prCreation === 'status-success')
    ) {
      logger.info(
        'Skipping branch creation due to unpublishSafe + status checks'
      );
      return 'pending';
    }

    Object.assign(config, await getParentBranch(config));
    logger.debug(`Using parentBranch: ${config.parentBranch}`);
    Object.assign(config, await getUpdatedPackageFiles(config));
    if (config.updatedPackageFiles && config.updatedPackageFiles.length) {
      logger.debug(
        `Updated ${config.updatedPackageFiles.length} package files`
      );
    } else {
      logger.debug('No package files need updating');
    }
    Object.assign(config, await getAdditionalFiles(config, packageFiles));
    if (config.updatedLockFiles && config.updatedLockFiles.length) {
      logger.debug(
        { updatedLockFiles: config.updatedLockFiles.map(f => f.name) },
        `Updated ${config.updatedLockFiles.length} lock files`
      );
    } else {
      logger.debug('No updated lock files in branch');
    }

    const committedFiles = await commitFilesToBranch(config);
    // istanbul ignore if
    if (
      config.type === 'lockFileMaintenance' &&
      !committedFiles &&
      !config.parentBranch &&
      branchExists
    ) {
      logger.info(
        'Deleting lock file maintenance branch as master lock file no longer needs updating'
      );
      await platform.deleteBranch(config.branchName);
      return 'done';
    }
    if (!(committedFiles || branchExists)) {
      return 'no-work';
    }

    // Set branch statuses
    await setUnpublishable(config);

    // Try to automerge branch and finish if successful
    const mergeStatus = await tryBranchAutomerge(config);
    logger.debug(`mergeStatus=${mergeStatus}`);
    if (mergeStatus === 'automerged') {
      logger.debug('Branch is automerged - returning');
      return 'automerged';
    } else if (
      mergeStatus === 'automerge aborted - PR exists' ||
      mergeStatus === 'failed'
    ) {
      logger.info({ mergeStatus }, 'Branch automerge not possible');
      config.forcePr = true;
    }
  } catch (err) /* istanbul ignore next */ {
    if (err.message === 'rate-limit-exceeded') {
      logger.debug('Passing rate-limit-exceeded error up');
      throw err;
    }
    if (err.message === 'repository-changed') {
      logger.debug('Passing repository-changed error up');
      throw err;
    }
    if (err.message === 'bad-credentials') {
      logger.debug('Passing bad-credentials error up');
      throw err;
    }
    if (err.message === 'lockfile-error') {
      logger.info('Lock file error');
      throw err;
    }
    if (err.message !== 'registry-failure') {
      logger.error({ err }, `Error updating branch: ${err.message}`);
    }
    // Don't throw here - we don't want to stop the other renovations
    return 'error';
  }
  try {
    logger.debug('Ensuring PR');
    logger.debug(
      `There are ${config.errors.length} errors and ${
        config.warnings.length
      } warnings`
    );
    const pr = await prWorker.ensurePr(config);
    // TODO: ensurePr should check for automerge itself
    if (pr) {
      const topic = 'Lock file problem';
      if (config.lockFileErrors && config.lockFileErrors.length) {
        logger.warn(
          { lockFileErrors: config.lockFileErrors },
          'lockFileErrors'
        );
        let content = `Renovate failed when attempting to generate `;
        content +=
          config.lockFileErrors.length > 1 ? 'lock files' : 'a lock file';
        content +=
          '. This is usually happens when you have private modules but have not added configuration for [private module support](https://renovatebot.com/docs/deep-dives/private-modules). It is strongly recommended that you do not merge this PR as-is.';
        content +=
          '\n\nRenovate **will not retry** generating a lockfile for this PR unless either (a) the `package.json` in this branch needs updating, or (b) ';
        if (config.recreateClosed) {
          content +=
            'you manually delete this PR so that it can be regenerated.';
        } else {
          content +=
            'you rename then delete this PR unmerged, so that it can be regenerated.';
        }
        content += '\n\nThe output from `stderr` is included below:\n\n';
        config.lockFileErrors.forEach(error => {
          content += `##### ${error.lockFile}\n\n`;
          content += `\`\`\`\n${error.stderr}\n\`\`\`\n\n`;
        });
        await platform.ensureComment(pr.number, topic, content);
      } else {
        if (config.updatedLockFiles && config.updatedLockFiles.length) {
          await platform.ensureCommentRemoval(pr.number, topic);
        }
        const prAutomerged = await prWorker.checkAutoMerge(pr, config);
        if (prAutomerged) {
          return 'automerged';
        }
      }
    }
  } catch (err) /* istanbul ignore next */ {
    if (err.message === 'rate-limit-exceeded') {
      logger.debug('Passing rate-limit-exceeded error up');
      throw err;
    }
    // Otherwise don't throw here - we don't want to stop the other renovations
    logger.error({ err }, `Error ensuring PR: ${err.message}`);
  }
  if (!branchExists) {
    return 'pr-created';
  }
  return 'done';
}
<commit_msg>logs: don’t log full pr in branch<commit_after>const schedule = require('./schedule');
const { getUpdatedPackageFiles } = require('./get-updated');
const { getAdditionalFiles } = require('../../manager/npm/post-update');
const { commitFilesToBranch } = require('./commit');
const { getParentBranch } = require('./parent');
const { tryBranchAutomerge } = require('./automerge');
const { setUnpublishable } = require('./status-checks');
const { prAlreadyExisted } = require('./check-existing');
const prWorker = require('../pr');

const { isScheduledNow } = schedule;

module.exports = {
  processBranch,
};

async function processBranch(branchConfig, packageFiles) {
  logger.debug(`processBranch with ${branchConfig.upgrades.length} upgrades`);
  const config = { ...branchConfig };
  const dependencies = config.upgrades
    .map(upgrade => upgrade.depName)
    .filter(v => v) // remove nulls (happens for lock file maintenance)
    .filter((value, i, list) => list.indexOf(value) === i); // remove duplicates
  logger.setMeta({
    repository: config.repository,
    branch: config.branchName,
    dependencies,
  });
  logger.debug('processBranch()');
  logger.trace({ config });
  await platform.setBaseBranch(config.baseBranch);
  const branchExists = await platform.branchExists(config.branchName);
  logger.debug(`branchExists=${branchExists}`);
  if (!branchExists && config.prHourlyLimitReached) {
    logger.info('Reached PR creation limit - skipping branch creation');
    return 'pr-hourly-limit-reached';
  }
  try {
    logger.info(
      `Branch has ${dependencies ? dependencies.length : 0} upgrade(s)`
    );

    // Check if branch already existed
    const existingPr = await prAlreadyExisted(config);
    if (existingPr) {
      logger.info(
        { prTitle: config.prTitle },
        'Closed PR already exists. Skipping branch.'
      );
      if (existingPr.state === 'closed') {
        const subject = 'Renovate Ignore Notification';
        let content;
        if (config.type === 'major') {
          content = `As this PR has been closed unmerged, Renovate will ignore this upgrade and you will not receive PRs for *any* future ${
            config.newVersionMajor
          }.x releases. However, if you upgrade to ${
            config.newVersionMajor
          }.x manually then Renovate will then reenable updates for minor and patch updates automatically.`;
        } else if (config.type === 'digest') {
          content = `As this PR has been closed unmerged, Renovate will ignore this upgrade type and you will not receive PRs for *any* future ${
            config.depName
          }:${
            config.currentTag
          } digest updates. Digest updates will resume if you update the specified tag at any time.`;
        } else {
          content = `As this PR has been closed unmerged, Renovate will now ignore this update (${
            config.newVersion
          }). You will still receive a PR once a newer version is released, so if you wish to permanently ignore this dependency, please add it to the \`ignoreDeps\` array of your renovate config.`;
        }
        content +=
          '\n\nIf this PR was closed by mistake or you changed your mind, you can simply rename this PR and you will soon get a fresh replacement PR opened.';
        await platform.ensureComment(existingPr.number, subject, content);
        if (branchExists) {
          await platform.deleteBranch(config.branchName);
        }
      } else if (existingPr.state === 'merged') {
        logger.info(
          { pr: existingPr.number },
          'Merged PR is blocking this branch'
        );
      }
      return 'already-existed';
    }
    if (branchExists) {
      logger.debug('Checking if PR has been edited');
      const branchPr = await platform.getBranchPr(config.branchName);
      if (branchPr) {
        logger.debug('Found existing branch PR');
        if (!branchPr.canRebase) {
          const subject = 'PR has been edited';
          logger.info(subject);
          let content =
            'As this PR has been edited, Renovate will stop updating it in order to not cause any conflicts or other problems.';
          content +=
            ' If you wish to abandon your edits and have Renovate recreate this PR then you should rename this PR and then close it.';
          await platform.ensureComment(branchPr.number, subject, content);
          return 'pr-edited';
        }
      }
    }

    // Check schedule
    config.isScheduledNow = isScheduledNow(config);
    if (!config.isScheduledNow) {
      if (!branchExists) {
        logger.info('Skipping branch creation as not within schedule');
        return 'not-scheduled';
      }
      if (config.updateNotScheduled === false) {
        logger.debug('Skipping branch update as not within schedule');
        return 'not-scheduled';
      }
      logger.debug(
        'Branch exists but is not scheduled -- will update if necessary'
      );
    }

    if (
      config.type !== 'lockFileMaintenance' &&
      config.unpublishSafe &&
      !config.unpublishable &&
      (config.prCreation === 'not-pending' ||
        config.prCreation === 'status-success')
    ) {
      logger.info(
        'Skipping branch creation due to unpublishSafe + status checks'
      );
      return 'pending';
    }

    Object.assign(config, await getParentBranch(config));
    logger.debug(`Using parentBranch: ${config.parentBranch}`);
    Object.assign(config, await getUpdatedPackageFiles(config));
    if (config.updatedPackageFiles && config.updatedPackageFiles.length) {
      logger.debug(
        `Updated ${config.updatedPackageFiles.length} package files`
      );
    } else {
      logger.debug('No package files need updating');
    }
    Object.assign(config, await getAdditionalFiles(config, packageFiles));
    if (config.updatedLockFiles && config.updatedLockFiles.length) {
      logger.debug(
        { updatedLockFiles: config.updatedLockFiles.map(f => f.name) },
        `Updated ${config.updatedLockFiles.length} lock files`
      );
    } else {
      logger.debug('No updated lock files in branch');
    }

    const committedFiles = await commitFilesToBranch(config);
    // istanbul ignore if
    if (
      config.type === 'lockFileMaintenance' &&
      !committedFiles &&
      !config.parentBranch &&
      branchExists
    ) {
      logger.info(
        'Deleting lock file maintenance branch as master lock file no longer needs updating'
      );
      await platform.deleteBranch(config.branchName);
      return 'done';
    }
    if (!(committedFiles || branchExists)) {
      return 'no-work';
    }

    // Set branch statuses
    await setUnpublishable(config);

    // Try to automerge branch and finish if successful
    const mergeStatus = await tryBranchAutomerge(config);
    logger.debug(`mergeStatus=${mergeStatus}`);
    if (mergeStatus === 'automerged') {
      logger.debug('Branch is automerged - returning');
      return 'automerged';
    } else if (
      mergeStatus === 'automerge aborted - PR exists' ||
      mergeStatus === 'failed'
    ) {
      logger.info({ mergeStatus }, 'Branch automerge not possible');
      config.forcePr = true;
    }
  } catch (err) /* istanbul ignore next */ {
    if (err.message === 'rate-limit-exceeded') {
      logger.debug('Passing rate-limit-exceeded error up');
      throw err;
    }
    if (err.message === 'repository-changed') {
      logger.debug('Passing repository-changed error up');
      throw err;
    }
    if (err.message === 'bad-credentials') {
      logger.debug('Passing bad-credentials error up');
      throw err;
    }
    if (err.message === 'lockfile-error') {
      logger.info('Lock file error');
      throw err;
    }
    if (err.message !== 'registry-failure') {
      logger.error({ err }, `Error updating branch: ${err.message}`);
    }
    // Don't throw here - we don't want to stop the other renovations
    return 'error';
  }
  try {
    logger.debug('Ensuring PR');
    logger.debug(
      `There are ${config.errors.length} errors and ${
        config.warnings.length
      } warnings`
    );
    const pr = await prWorker.ensurePr(config);
    // TODO: ensurePr should check for automerge itself
    if (pr) {
      const topic = 'Lock file problem';
      if (config.lockFileErrors && config.lockFileErrors.length) {
        logger.warn(
          { lockFileErrors: config.lockFileErrors },
          'lockFileErrors'
        );
        let content = `Renovate failed when attempting to generate `;
        content +=
          config.lockFileErrors.length > 1 ? 'lock files' : 'a lock file';
        content +=
          '. This is usually happens when you have private modules but have not added configuration for [private module support](https://renovatebot.com/docs/deep-dives/private-modules). It is strongly recommended that you do not merge this PR as-is.';
        content +=
          '\n\nRenovate **will not retry** generating a lockfile for this PR unless either (a) the `package.json` in this branch needs updating, or (b) ';
        if (config.recreateClosed) {
          content +=
            'you manually delete this PR so that it can be regenerated.';
        } else {
          content +=
            'you rename then delete this PR unmerged, so that it can be regenerated.';
        }
        content += '\n\nThe output from `stderr` is included below:\n\n';
        config.lockFileErrors.forEach(error => {
          content += `##### ${error.lockFile}\n\n`;
          content += `\`\`\`\n${error.stderr}\n\`\`\`\n\n`;
        });
        await platform.ensureComment(pr.number, topic, content);
      } else {
        if (config.updatedLockFiles && config.updatedLockFiles.length) {
          await platform.ensureCommentRemoval(pr.number, topic);
        }
        const prAutomerged = await prWorker.checkAutoMerge(pr, config);
        if (prAutomerged) {
          return 'automerged';
        }
      }
    }
  } catch (err) /* istanbul ignore next */ {
    if (err.message === 'rate-limit-exceeded') {
      logger.debug('Passing rate-limit-exceeded error up');
      throw err;
    }
    // Otherwise don't throw here - we don't want to stop the other renovations
    logger.error({ err }, `Error ensuring PR: ${err.message}`);
  }
  if (!branchExists) {
    return 'pr-created';
  }
  return 'done';
}
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React from 'react'
import {reducer as reducerUtil, navigationStrategy} from 'tocco-util'
import {
  appFactory,
  notification,
  errorLogging,
  actionEmitter,
  externalEvents,
  actions,
  formData
} from 'tocco-app-extensions'
import _pickBy from 'lodash/pickBy'
import _isEqual from 'lodash/isEqual'
import _isEmpty from 'lodash/isEmpty'
import SimpleFormApp from 'tocco-simple-form/src/main'

import reducers, {sagas} from './modules/reducers'
import {reloadData, reloadAll} from './modules/entityList/actions'
import {refresh} from './modules/list/actions'
import EntityList from './components/EntityList'
import {getDispatchActions, getReloadOption, reloadOptions} from './input'
import {selectionStylePropType} from './util/selectionStyles'
import customActions from './customActions'
import {searchFormTypePropTypes} from './util/searchFormTypes'

const packageName = 'entity-list'

const EXTERNAL_EVENTS = [
  'onRowClick',
  'emitAction',
  'onSelectChange',
  'onStoreCreate',
  'onSearchChange',
  'onSearchFormCollapsedChange'
]

const initApp = (id, input, events = {}, publicPath) => {
  const content = <EntityList/>

  let store = input.store

  const allCustomActions = {
    ...customActions(input),
    ...(input.customActions || {})
  }

  const context = {
    viewName: 'list',
    formName: input.formName,
    ...(input.contextParams || {})
  }

  if (!store) {
    store = appFactory.createStore(reducers, sagas, input, packageName)

    externalEvents.addToStore(store, events)
    actionEmitter.addToStore(store, events.emitAction)
    errorLogging.addToStore(store, false)
    notification.addToStore(store, false)
    actions.addToStore(store, {
      formApp: SimpleFormApp,
      listApp: EntityListApp,
      customActions: allCustomActions,
      appComponent: input.actionAppComponent,
      navigationStrategy: input.navigationStrategy,
      context
    })
    formData.addToStore(store, {listApp: EntityListApp, navigationStrategy: input.navigationStrategy})

    store.dispatch(externalEvents.fireExternalEvent('onStoreCreate', store))
  } else {
    store.dispatch(refresh())
  }

  const app = appFactory.createApp(
    packageName,
    content,
    store,
    {
      input,
      events,
      actions: getDispatchActions(input),
      publicPath,
      textResourceModules: ['component', 'common']
    }
  )

  if (module.hot) {
    module.hot.accept('./modules/reducers', () => {
      const reducers = require('./modules/reducers').default
      reducerUtil.hotReloadReducers(app.store, reducers)
    })
  }

  return app
}

(() => {
  if (__DEV__ && __PACKAGE_NAME__ === 'entity-list') {
    const input = require('./dev/input.json')

    if (!__NO_MOCK__) {
      const fetchMock = require('fetch-mock').default
      fetchMock.config.overwriteRoutes = false
      const setupFetchMocks = require('./dev/fetchMocks').default
      setupFetchMocks(packageName, fetchMock)
      fetchMock.spy()
    }

    const app = initApp('id', input)
    appFactory.renderApp(app.component)
  } else {
    appFactory.registerAppInRegistry(packageName, initApp)
  }
})()

const getEvents = props =>
  EXTERNAL_EVENTS.reduce((events, event) => {
    if (props[event]) {
      events[event] = props[event]
    }
    return events
  }, {})

class EntityListApp extends React.Component {
  constructor(props) {
    super(props)
    this.app = initApp(props.id, props, getEvents(props))
  }

  componentDidUpdate(prevProps) {
    const changedProps = _pickBy(this.props, (value, key) => !_isEqual(value, prevProps[key]))
    if (changedProps.store) {
      this.app = initApp(this.props.id, this.props, getEvents(this.props))
    } else if (!_isEmpty(changedProps)) {
      getDispatchActions(changedProps).forEach(action => {
        this.app.store.dispatch(action)
      })

      const reloadOption = getReloadOption(changedProps)
      if (reloadOption === reloadOptions.ALL) {
        this.app.store.dispatch(reloadAll())
      } else if (reloadOption === reloadOptions.DATA) {
        this.app.store.dispatch(reloadData())
      }
    }
  }

  render() {
    return this.app.component
  }
}

EntityListApp.propTypes = {
  id: PropTypes.string.isRequired,
  entityName: PropTypes.string.isRequired,
  formName: PropTypes.string.isRequired,
  store: PropTypes.object,
  limit: PropTypes.number,
  searchFormType: searchFormTypePropTypes,
  searchFormPosition: PropTypes.oneOf(['top', 'left']),
  searchFilters: PropTypes.arrayOf(PropTypes.string),
  preselectedSearchFields: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.string,
      value: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.number,
        PropTypes.arrayOf(PropTypes.number),
        PropTypes.arrayOf(PropTypes.string)
      ]),
      hidden: PropTypes.bool
    })
  ),
  tql: PropTypes.string,
  keys: PropTypes.arrayOf(PropTypes.string),
  disableSimpleSearch: PropTypes.bool,
  simpleSearchFields: PropTypes.string,
  onSelectChange: PropTypes.func,
  selectionStyle: selectionStylePropType,
  selection: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
  ...EXTERNAL_EVENTS.reduce((propTypes, event) => {
    propTypes[event] = PropTypes.func
    return propTypes
  }, {}),
  selectOnRowClick: PropTypes.bool,
  parent: PropTypes.shape({
    id: PropTypes.string,
    value: PropTypes.string
  }),
  actionAppComponent: PropTypes.func,
  navigationStrategy: navigationStrategy.propTypes,
  contextParams: PropTypes.object
}

export default EntityListApp
<commit_msg>refactor(entity-list): update prop types<commit_after>import PropTypes from 'prop-types'
import React from 'react'
import {reducer as reducerUtil, navigationStrategy} from 'tocco-util'
import {
  appFactory,
  notification,
  errorLogging,
  actionEmitter,
  externalEvents,
  actions,
  formData
} from 'tocco-app-extensions'
import _pickBy from 'lodash/pickBy'
import _isEqual from 'lodash/isEqual'
import _isEmpty from 'lodash/isEmpty'
import SimpleFormApp from 'tocco-simple-form/src/main'

import reducers, {sagas} from './modules/reducers'
import {reloadData, reloadAll} from './modules/entityList/actions'
import {refresh} from './modules/list/actions'
import EntityList from './components/EntityList'
import {getDispatchActions, getReloadOption, reloadOptions} from './input'
import {selectionStylePropType} from './util/selectionStyles'
import customActions from './customActions'
import {searchFormTypePropTypes} from './util/searchFormTypes'

const packageName = 'entity-list'

const EXTERNAL_EVENTS = [
  'onRowClick',
  'emitAction',
  'onSelectChange',
  'onStoreCreate',
  'onSearchChange',
  'onSearchFormCollapsedChange'
]

const initApp = (id, input, events = {}, publicPath) => {
  const content = <EntityList/>

  let store = input.store

  const allCustomActions = {
    ...customActions(input),
    ...(input.customActions || {})
  }

  const context = {
    viewName: 'list',
    formName: input.formName,
    ...(input.contextParams || {})
  }

  if (!store) {
    store = appFactory.createStore(reducers, sagas, input, packageName)

    externalEvents.addToStore(store, events)
    actionEmitter.addToStore(store, events.emitAction)
    errorLogging.addToStore(store, false)
    notification.addToStore(store, false)
    actions.addToStore(store, {
      formApp: SimpleFormApp,
      listApp: EntityListApp,
      customActions: allCustomActions,
      appComponent: input.actionAppComponent,
      navigationStrategy: input.navigationStrategy,
      context
    })
    formData.addToStore(store, {listApp: EntityListApp, navigationStrategy: input.navigationStrategy})

    store.dispatch(externalEvents.fireExternalEvent('onStoreCreate', store))
  } else {
    store.dispatch(refresh())
  }

  const app = appFactory.createApp(
    packageName,
    content,
    store,
    {
      input,
      events,
      actions: getDispatchActions(input),
      publicPath,
      textResourceModules: ['component', 'common']
    }
  )

  if (module.hot) {
    module.hot.accept('./modules/reducers', () => {
      const reducers = require('./modules/reducers').default
      reducerUtil.hotReloadReducers(app.store, reducers)
    })
  }

  return app
}

(() => {
  if (__DEV__ && __PACKAGE_NAME__ === 'entity-list') {
    const input = require('./dev/input.json')

    if (!__NO_MOCK__) {
      const fetchMock = require('fetch-mock').default
      fetchMock.config.overwriteRoutes = false
      const setupFetchMocks = require('./dev/fetchMocks').default
      setupFetchMocks(packageName, fetchMock)
      fetchMock.spy()
    }

    const app = initApp('id', input)
    appFactory.renderApp(app.component)
  } else {
    appFactory.registerAppInRegistry(packageName, initApp)
  }
})()

const getEvents = props =>
  EXTERNAL_EVENTS.reduce((events, event) => {
    if (props[event]) {
      events[event] = props[event]
    }
    return events
  }, {})

class EntityListApp extends React.Component {
  constructor(props) {
    super(props)
    this.app = initApp(props.id, props, getEvents(props))
  }

  componentDidUpdate(prevProps) {
    const changedProps = _pickBy(this.props, (value, key) => !_isEqual(value, prevProps[key]))
    if (changedProps.store) {
      this.app = initApp(this.props.id, this.props, getEvents(this.props))
    } else if (!_isEmpty(changedProps)) {
      getDispatchActions(changedProps).forEach(action => {
        this.app.store.dispatch(action)
      })

      const reloadOption = getReloadOption(changedProps)
      if (reloadOption === reloadOptions.ALL) {
        this.app.store.dispatch(reloadAll())
      } else if (reloadOption === reloadOptions.DATA) {
        this.app.store.dispatch(reloadData())
      }
    }
  }

  render() {
    return this.app.component
  }
}

EntityListApp.propTypes = {
  id: PropTypes.string.isRequired,
  entityName: PropTypes.string.isRequired,
  formName: PropTypes.string.isRequired,
  store: PropTypes.object,
  limit: PropTypes.number,
  searchFormType: searchFormTypePropTypes,
  searchFormPosition: PropTypes.oneOf(['top', 'left']),
  searchFilters: PropTypes.arrayOf(PropTypes.string),
  preselectedSearchFields: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.string,
      value: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.number,
        PropTypes.arrayOf(PropTypes.number),
        PropTypes.arrayOf(PropTypes.string)
      ]),
      hidden: PropTypes.bool
    })
  ),
  tql: PropTypes.string,
  keys: PropTypes.arrayOf(PropTypes.string),
  disableSimpleSearch: PropTypes.bool,
  simpleSearchFields: PropTypes.string,
  onSelectChange: PropTypes.func,
  selectionStyle: selectionStylePropType,
  selection: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
  ...EXTERNAL_EVENTS.reduce((propTypes, event) => {
    propTypes[event] = PropTypes.func
    return propTypes
  }, {}),
  selectOnRowClick: PropTypes.bool,
  parent: PropTypes.shape({
    id: PropTypes.string,
    value: PropTypes.string
  }),
  actionAppComponent: PropTypes.func,
  navigationStrategy: navigationStrategy.propTypes,
  contextParams: PropTypes.object,
  searchFormCollapsed: PropTypes.bool
}

export default EntityListApp
<|endoftext|>


<commit_before>/*jslint node: true, indent: 4 */
(function () {
    'use strict';
    var discourse,
        summons = {},
        configuration;

    /**
     * @var {string} description Brief description of this module for Help Docs
     */
    exports.description = 'Allow Summoning of bot to play in certain threads';

    /**
     * @var {object} configuration Default Configuration settings for this
     * sock_module
     */
    exports.configuration = {
        enabled: false,
        autoTimeout: 60 * 1000,
        userTimeout: 60 * 60 * 1000,
        messages: [
            '@%__username__% has summoned me, and so I appear.',
            'Yes master %__name__%, I shall appear as summoned.',
            'Yes mistress %__name__%, I shall appear as summoned.'
        ]
    };

    /**
     * @var {string} name The name of this sock_module
     */
    exports.name = 'Summoner';

    /**
     * @var {number} priority If defined by a sock_module it is the priority
     * of the module with respect to other modules.
     *
     * sock_modules **should not** define modules with negative permissions.
     * Default value is 50 with lower numbers being higher priority.
     */
    exports.priority = 1000;

    /**
     * @var {string} version The version of this sock_module
     */
    exports.version = '1.1.0';

    function purgeMemory() {
        var lastHour = (new Date().getTime()) - 60 * 60 * 1000, // an hour ago;
            k; //key
        for (k in summons) {
            if (summons.hasOwnProperty(k) && summons[k] < lastHour) {
                delete summons[k];
            }
        }
    }

    exports.onNotify = function onNotify(type, notification, topic,
        post, callback) {
        if (type === 'mentioned') {
            var now = (new Date().getTime()),
                r = Math.floor(Math.random() * configuration.messages.length),
                s = configuration.messages[r];
            if (summons[notification.topic_id] &&
                now < summons[notification.topic_id]) {
                return callback();
            }
            discourse.log(notification.data.display_username +
                ' summoned me to play in ' + notification.slug);
            s = s.replace(/%__(\w+)__%/g, function (m, key) {
                if (post.hasOwnProperty(key)) {
                    return post[key];
                }
                return m;
            });
            summons[notification.topic_id] = now + configuration.autoTimeout;
            discourse.createPost(notification.topic_id,
                notification.post_number, s,
                function () {
                    callback(true);
                });
        } else {
            callback();
        }
    };
    exports.begin = function begin(browser, config) {
        configuration = config.modules[exports.name];
        discourse = browser;
        setInterval(purgeMemory, 30 * 60 * 1000);
    };
}());
<commit_msg> add a probability to the summoning<commit_after>/*jslint node: true, indent: 4 */
(function () {
    'use strict';
    var discourse,
        summons = {},
        configuration;

    /**
     * @var {string} description Brief description of this module for Help Docs
     */
    exports.description = 'Allow Summoning of bot to play in certain threads';

    /**
     * @var {object} configuration Default Configuration settings for this
     * sock_module
     */
    exports.configuration = {
        enabled: false,
        autoTimeout: 60 * 1000,
        userTimeout: 60 * 60 * 1000,
        probability: 1,
        messages: [
            '@%__username__% has summoned me, and so I appear.',
            'Yes master %__name__%, I shall appear as summoned.',
            'Yes mistress %__name__%, I shall appear as summoned.'
        ]
    };

    /**
     * @var {string} name The name of this sock_module
     */
    exports.name = 'Summoner';

    /**
     * @var {number} priority If defined by a sock_module it is the priority
     * of the module with respect to other modules.
     *
     * sock_modules **should not** define modules with negative permissions.
     * Default value is 50 with lower numbers being higher priority.
     */
    exports.priority = 1000;

    /**
     * @var {string} version The version of this sock_module
     */
    exports.version = '1.1.0';

    function purgeMemory() {
        var lastHour = (new Date().getTime()) - 60 * 60 * 1000, // an hour ago;
            k; //key
        for (k in summons) {
            if (summons.hasOwnProperty(k) && summons[k] < lastHour) {
                delete summons[k];
            }
        }
    }

    exports.onNotify = function onNotify(type, notification, topic,
        post, callback) {
        if (type === 'mentioned' && Math.random() < configuration.probability) {
            var now = (new Date().getTime()),
                r = Math.floor(Math.random() * configuration.messages.length),
                s = configuration.messages[r];
            if (summons[notification.topic_id] &&
                now < summons[notification.topic_id]) {
                return callback();
            }
            discourse.log(notification.data.display_username +
                ' summoned me to play in ' + notification.slug);
            s = s.replace(/%__(\w+)__%/g, function (m, key) {
                if (post.hasOwnProperty(key)) {
                    return post[key];
                }
                return m;
            });
            summons[notification.topic_id] = now + configuration.autoTimeout;
            discourse.createPost(notification.topic_id,
                notification.post_number, s,
                function () {
                    callback(true);
                });
        } else {
            callback();
        }
    };
    exports.begin = function begin(browser, config) {
        configuration = config.modules[exports.name];
        discourse = browser;
        setInterval(purgeMemory, 30 * 60 * 1000);
    };
}());
<|endoftext|>


<commit_before>const path = require('path');
const fs = require('fs');
const mkdirp = require('mkdirp');
const version = require('kolibri-tools/lib/version');
const webpack = require('webpack');

function Plugin() {}

Plugin.prototype.apply = function(compiler) {
  var self = this;

  const done = function(stats) {
    if (stats.compilation.errors.length > 0) {
      return;
    }

    let hashiFilename;
    stats.compilation.chunks.map(function(chunk) {
      hashiFilename = chunk.files[0];
    });

    self.writeOutput(hashiFilename);
  };

  if (compiler.hooks) {
    const plugin = { name: 'HashiHashWriterPlugin' };
    compiler.hooks.done.tap(plugin, done);
  }
};

Plugin.prototype.writeOutput = function(filename) {
  var outputFilename = path.resolve(__dirname, '../../kolibri/core/content/build/hashi_filename');
  mkdirp.sync(path.dirname(outputFilename));

  fs.writeFileSync(outputFilename, filename);
};

// Note that the hashi iframe client doesn't currently support code splitting
// in the way that it is loaded, so don't do any code splitting just yet.

const kolibriVersion = version.getVersion();

module.exports = {
  entry: path.resolve(__dirname, './src/iframe.js'),
  output: {
    filename: 'hashiframe-[hash].js',
    path: path.resolve(__dirname, '../../kolibri/core/content/static/content'),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
      },
    ],
  },
  plugins: [
    new Plugin(),
    new webpack.DefinePlugin({
      __version: `"${kolibriVersion}"`,
    }),
  ],
};
<commit_msg>Revert "Inject __version into hashi webpack build"<commit_after>const path = require('path');
const fs = require('fs');
const mkdirp = require('mkdirp');

function Plugin() {}

Plugin.prototype.apply = function(compiler) {
  var self = this;

  const done = function(stats) {
    if (stats.compilation.errors.length > 0) {
      return;
    }

    let hashiFilename;
    stats.compilation.chunks.map(function(chunk) {
      hashiFilename = chunk.files[0];
    });

    self.writeOutput(hashiFilename);
  };

  if (compiler.hooks) {
    const plugin = { name: 'HashiHashWriterPlugin' };
    compiler.hooks.done.tap(plugin, done);
  }
};

Plugin.prototype.writeOutput = function(filename) {
  var outputFilename = path.resolve(__dirname, '../../kolibri/core/content/build/hashi_filename');
  mkdirp.sync(path.dirname(outputFilename));

  fs.writeFileSync(outputFilename, filename);
};

// Note that the hashi iframe client doesn't currently support code splitting
// in the way that it is loaded, so don't do any code splitting just yet.

module.exports = {
  entry: path.resolve(__dirname, './src/iframe.js'),
  output: {
    filename: 'hashiframe-[hash].js',
    path: path.resolve(__dirname, '../../kolibri/core/content/static/content'),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
      },
    ],
  },
  plugins: [new Plugin()],
};
<|endoftext|>


<commit_before>/*
 * loquat-prim / prim.js
 * copyright (c) 2016 Susisu
 */

/**
 * @module prim
 */

"use strict";

module.exports = _core => {
    function end() {
        return Object.freeze({
            map,
            pure,
            bind,
            then,
            fail
        });
    }

    const ErrorMessageType = _core.ErrorMessageType;
    const ErrorMessage     = _core.ErrorMessage;
    const ParseError       = _core.ParseError;
    const Result           = _core.Result;
    const Parser           = _core.Parser;

    /**
     * @function module:prim.map
     * @static
     * @param {AbstractParser} parser
     * @param {function} func
     * @returns {AbstractParser}
     */
    function map(parser, func) {
        return new Parser(state => {
            let res = parser.run(state);
            return res.succeeded
                ? new Result(res.consumed, true, res.err, func(res.val), res.state)
                : res;
        });
    }

    /**
     * @function module:prim.pure
     * @static
     * @param {*} val
     * @returns {AbstractParser}
     */
    function pure(val) {
        return new Parser(state => Result.esuc(ParseError.unknown(state.pos), val, state));
    }

    /**
     * @function module:prim.bind
     * @static
     * @param {AbstractParser} parser
     * @param {function} func
     * @returns {AbstractParser}
     */
    function bind(parser, func) {
        return new Parser(state => {
            let resA = parser.run(state);
            if (resA.succeeded) {
                let parserB = func(resA.val);
                let resB = parserB.run(resA.state);
                return new Result(
                    resA.consumed || resB.consumed,
                    resB.succeeded,
                    resB.consumed ? resB.err : ParseError.merge(resA.err, resB.err),
                    resB.val,
                    resB.state
                );
            }
            else {
                return resA;
            }
        });
    }

    /**
     * @function module:prim.then
     * @static
     * @param {AbstractParser} parserA
     * @param {AbstractParser} parserB
     * @returns {AbstracParser}
     */
    function then(parserA, parserB) {
        return bind(parserA, () => parserB);
    }

    /**
     * @function module:prim.fail
     * @static
     * @param {string} msgStr
     * @returns {AbstractParser}
     */
    function fail(msgStr) {
        return new Parser(state => Result.eerr(
            new ParseError(state.pos, [new ErrorMessage(ErrorMessageType.MESSAGE, msgStr)])
        ));
    }

    return end();
};
<commit_msg>[prim] Add `ap()`<commit_after>/*
 * loquat-prim / prim.js
 * copyright (c) 2016 Susisu
 */

/**
 * @module prim
 */

"use strict";

module.exports = _core => {
    function end() {
        return Object.freeze({
            map,
            pure,
            ap,
            bind,
            then,
            fail
        });
    }

    const ErrorMessageType = _core.ErrorMessageType;
    const ErrorMessage     = _core.ErrorMessage;
    const ParseError       = _core.ParseError;
    const Result           = _core.Result;
    const Parser           = _core.Parser;

    /**
     * @function module:prim.map
     * @static
     * @param {AbstractParser} parser
     * @param {function} func
     * @returns {AbstractParser}
     */
    function map(parser, func) {
        return new Parser(state => {
            let res = parser.run(state);
            return res.succeeded
                ? new Result(res.consumed, true, res.err, func(res.val), res.state)
                : res;
        });
    }

    /**
     * @function module:prim.pure
     * @static
     * @param {*} val
     * @returns {AbstractParser}
     */
    function pure(val) {
        return new Parser(state => Result.esuc(ParseError.unknown(state.pos), val, state));
    }

    /**
     * @function module:prim.ap
     * @static
     * @param {AbstractParser} parserA
     * @param {AbstractParser} parserB
     * @returns {AbstractParser}
     */
    function ap(parserA, parserB) {
        return bind(parserA, valA =>
            bind(parserB, valB =>
                pure(valA(valB))
            )
        );
    }

    /**
     * @function module:prim.bind
     * @static
     * @param {AbstractParser} parser
     * @param {function} func
     * @returns {AbstractParser}
     */
    function bind(parser, func) {
        return new Parser(state => {
            let resA = parser.run(state);
            if (resA.succeeded) {
                let parserB = func(resA.val);
                let resB = parserB.run(resA.state);
                return new Result(
                    resA.consumed || resB.consumed,
                    resB.succeeded,
                    resB.consumed ? resB.err : ParseError.merge(resA.err, resB.err),
                    resB.val,
                    resB.state
                );
            }
            else {
                return resA;
            }
        });
    }

    /**
     * @function module:prim.then
     * @static
     * @param {AbstractParser} parserA
     * @param {AbstractParser} parserB
     * @returns {AbstracParser}
     */
    function then(parserA, parserB) {
        return bind(parserA, () => parserB);
    }

    /**
     * @function module:prim.fail
     * @static
     * @param {string} msgStr
     * @returns {AbstractParser}
     */
    function fail(msgStr) {
        return new Parser(state => Result.eerr(
            new ParseError(state.pos, [new ErrorMessage(ErrorMessageType.MESSAGE, msgStr)])
        ));
    }

    return end();
};
<|endoftext|>


<commit_before>import min from 'lodash/min'

import { BodyComponent } from 'mjml-core'

import widthParser from 'mjml-core/lib/helpers/widthParser'

export default class MjImage extends BodyComponent {
  static tagOmission = true

  static allowedAttributes = {
    alt: 'string',
    href: 'string',
    name: 'string',
    src: 'string',
    srcset: 'string',
    title: 'string',
    rel: 'string',
    align: 'enum(left,center,right)',
    border: 'string',
    'border-bottom': 'string',
    'border-left': 'string',
    'border-right': 'string',
    'border-top': 'string',
    'border-radius': 'unit(px,%){1,4}',
    'container-background-color': 'color',
    'fluid-on-mobile': 'boolean',
    padding: 'unit(px,%){1,4}',
    'padding-bottom': 'unit(px,%)',
    'padding-left': 'unit(px,%)',
    'padding-right': 'unit(px,%)',
    'padding-top': 'unit(px,%)',
    target: 'string',
    width: 'unit(px)',
    height: 'unit(px)',
  }

  static defaultAttributes = {
    align: 'center',
    border: '0',
    height: 'auto',
    padding: '10px 25px',
    target: '_blank',
  }

  getStyles() {
    const width = this.getContentWidth()
    const fullWidth = this.getAttribute('full-width') === 'full-width'

    const { parsedWidth, unit } = widthParser(width)

    return {
      img: {
        border: this.getAttribute('border'),
        'border-left': this.getAttribute('left'),
        'border-right': this.getAttribute('right'),
        'border-top': this.getAttribute('top'),
        'border-bottom': this.getAttribute('bottom'),
        'border-radius': this.getAttribute('border-radius'),
        display: 'block',
        outline: 'none',
        'text-decoration': 'none',
        height: this.getAttribute('height'),
        'min-width': fullWidth ? '100%' : null,
        width: '100%',
        'max-width': fullWidth ? '100%' : null,
      },
      td: {
        width: fullWidth ? null : `${parsedWidth}${unit}`,
      },
      table: {
        'min-width': fullWidth ? '100%' : null,
        'max-width': fullWidth ? '100%' : null,
        width: fullWidth ? `${parsedWidth}${unit}` : null,
        'border-collapse': 'collapse',
        'border-spacing': '0px',
      },
    }
  }

  getContentWidth() {
    const width = this.getAttribute('width')
                ? parseInt(this.getAttribute('width'), 10)
                : Infinity

    const { box } = this.getBoxWidths()

    return min([ box, width ])
  }

  renderImage() {
    const height = this.getAttribute('height')

    const img = `

    `

    if (this.getAttribute('href')) {
      return `

          ${img}

      `
    }

    return img
  }

  headStyle = breakpoint => `
    @media only screen and (max-width:${breakpoint}) {
      table.full-width-mobile { width: 100% !important; }
      td.full-width-mobile { width: auto !important; }
    }
  `

  render() {
    return `

              ${this.renderImage()}

    `
  }
}
<commit_msg>Fix Alt Text Hidden Bug/Allow for Font Size && Allow Max-Height to Change Placholder Size<commit_after>import min from 'lodash/min'

import { BodyComponent } from 'mjml-core'

import widthParser from 'mjml-core/lib/helpers/widthParser'

export default class MjImage extends BodyComponent {
  static tagOmission = true

  static allowedAttributes = {
    alt: 'string',
    href: 'string',
    name: 'string',
    src: 'string',
    srcset: 'string',
    title: 'string',
    rel: 'string',
    align: 'enum(left,center,right)',
    border: 'string',
    'border-bottom': 'string',
    'border-left': 'string',
    'border-right': 'string',
    'border-top': 'string',
    'border-radius': 'unit(px,%){1,4}',
    'container-background-color': 'color',
    'fluid-on-mobile': 'boolean',
    padding: 'unit(px,%){1,4}',
    'padding-bottom': 'unit(px,%)',
    'padding-left': 'unit(px,%)',
    'padding-right': 'unit(px,%)',
    'padding-top': 'unit(px,%)',
    target: 'string',
    width: 'unit(px)',
    height: 'unit(px)',
    'max-height': 'unit(px,%)',
    'font-size': 'unit(px)',
  }

  static defaultAttributes = {
    align: 'center',
    border: '0',
    height: 'auto',
    padding: '10px 25px',
    target: '_blank',
    'font-size': '13px',
  }

  getStyles() {
    const width = this.getContentWidth()
    const fullWidth = this.getAttribute('full-width') === 'full-width'

    const { parsedWidth, unit } = widthParser(width)

    return {
      img: {
        border: this.getAttribute('border'),
        'border-left': this.getAttribute('left'),
        'border-right': this.getAttribute('right'),
        'border-top': this.getAttribute('top'),
        'border-bottom': this.getAttribute('bottom'),
        'border-radius': this.getAttribute('border-radius'),
        display: 'block',
        outline: 'none',
        'text-decoration': 'none',
        height: this.getAttribute('height'),
        'max-height': this.getAttribute('max-height'),
        'min-width': fullWidth ? '100%' : null,
        width: '100%',
        'max-width': fullWidth ? '100%' : null,
        'font-size': this.getAttribute('font-size'),
      },
      td: {
        width: fullWidth ? null : `${parsedWidth}${unit}`,
      },
      table: {
        'min-width': fullWidth ? '100%' : null,
        'max-width': fullWidth ? '100%' : null,
        width: fullWidth ? `${parsedWidth}${unit}` : null,
        'border-collapse': 'collapse',
        'border-spacing': '0px',
      },
    }
  }

  getContentWidth() {
    const width = this.getAttribute('width')
                ? parseInt(this.getAttribute('width'), 10)
                : Infinity

    const { box } = this.getBoxWidths()

    return min([ box, width ])
  }

  renderImage() {
    const height = this.getAttribute('height')

    const img = `

    `

    if (this.getAttribute('href')) {
      return `

          ${img}

      `
    }

    return img
  }

  headStyle = breakpoint => `
    @media only screen and (max-width:${breakpoint}) {
      table.full-width-mobile { width: 100% !important; }
      td.full-width-mobile { width: auto !important; }
    }
  `

  render() {
    return `

              ${this.renderImage()}

    `
  }
}
<|endoftext|>


<commit_before>const Promise = require('bluebird');
const merge = require('merge-options');

const AbstractSprite = require('./abstract-sprite');
const {
  arraySum,
  calculateImgTopPosition,
  createSymbolFromImage,
  createSprite
} = require('./utils');

const defaultConfig = {
  gap: 10
};

class Sprite extends AbstractSprite {
  constructor(config) {
    super();
    this.config = merge(defaultConfig, config);
  }

  get width() {
    const { images } = this;
    return images.length ? Math.max(...images.map(img => img.width)) : 0;
  }

  get height() {
    const { images, config } = this;
    const heights = arraySum(images.map(img => img.height));
    const gaps = images.length
      ? (images.length - 1) * config.gap
      : 0;
    return heights + gaps;
  }

  /**
   * @param contentOrOpts {@see AbstractSprite.addFromFile}
   * @return {Promise<Image>}
   */
  addFromFile(contentOrOpts) {
    const { images, config } = this;
    return super.addFromFile(contentOrOpts).then(img => {
      const y = calculateImgTopPosition(img, images, config.gap);
      img.coords = { x: 0, y };
      return img;
    });
  }

  /**
   * @return {Promise<PostSvgTree>}
   */
  generate() {
    const { images } = this;

    return Promise
      .map(images, img => createSymbolFromImage(img))
      .then(symbols => createSprite({ symbols }))
      .then(spriteTree => {
        const { root } = spriteTree;

        const usages = images.map(({ id, width, height, coords }) => ({
          tag: 'use',
          attrs: {
            'xlink:href': `#${id}`,
            width,
            height,
            transform: `translate(${coords.x}, ${coords.y})`
          }
        }));

        root.content = root.content.concat(usages);
        root.attrs.width = this.width;
        root.attrs.height = this.height;

        return spriteTree;
      });
  }

  /**
   * @return {Promise<string>}
   */
  render() {
    return this.generate().then(tree => tree.toString());
  }
}

module.exports = Sprite;
<commit_msg>WIP: add `generatePositioningData` method<commit_after>const Promise = require('bluebird');
const merge = require('merge-options');

const AbstractSprite = require('./abstract-sprite');
const {
  arraySum,
  calculateImgSizeToFitViewport,
  calculateImgTopPosition,
  createSymbolFromImage,
  createSprite
} = require('./utils');

const defaultConfig = {
  gap: 10
};

class Sprite extends AbstractSprite {
  constructor(config) {
    super();
    this.config = merge(defaultConfig, config);
  }

  get width() {
    const { images } = this;
    return images.length ? Math.max(...images.map(img => img.width)) : 0;
  }

  get height() {
    const { images, config } = this;
    const heights = arraySum(images.map(img => img.height));
    const gaps = images.length
      ? (images.length - 1) * config.gap
      : 0;
    return heights + gaps;
  }

  /**
   * @param contentOrOpts {@see AbstractSprite.addFromFile}
   * @return {Promise<Image>}
   */
  addFromFile(contentOrOpts) {
    const { images, config } = this;
    return super.addFromFile(contentOrOpts).then(img => {
      const y = calculateImgTopPosition(img, images, config.gap);
      img.coords = { x: 0, y };
      return img;
    });
  }

  /**
   * Generate data for proper symbol positioning and scaling on sprite canvas.
   * All returned values are percentages.
   * @param {Image} img
   * @return {{aspectRatio: number, width, height, topPos: number}}
   */
  generatePositioningData(img) {
    const spriteWidth = this.width;
    const spriteHeight = this.height;

    const { width, height } = calculateImgSizeToFitViewport(
      spriteWidth,
      spriteHeight,
      img.width,
      img.height
    );

    const topPos = (img.coords.y / spriteHeight) * 100;
    const aspectRatio = (img.height / img.width) * 100;

    return {
      width,
      height,
      aspectRatio,
      topPos
    };
  }

  /**
   * @return {Promise<PostSvgTree>}
   */
  generate() {
    const { images } = this;

    return Promise
      .map(images, img => createSymbolFromImage(img))
      .then(symbols => createSprite({ symbols }))
      .then(spriteTree => {
        const { root } = spriteTree;

        const usages = images.map(({ id, width, height, coords }) => ({
          tag: 'use',
          attrs: {
            'xlink:href': `#${id}`,
            width,
            height,
            transform: `translate(${coords.x}, ${coords.y})`
          }
        }));

        root.content = root.content.concat(usages);
        root.attrs.width = this.width;
        root.attrs.height = this.height;

        return spriteTree;
      });
  }

  /**
   * @return {Promise<string>}
   */
  render() {
    return this.generate().then(tree => tree.toString());
  }
}

module.exports = Sprite;
<|endoftext|>


<commit_before>/*jshint browser: true, devel: true, bitwise: true, camelcase: true, curly: true, eqeqeq: true, forin: true, immed: true, indent: 4, latedef: true, newcap: true, noarg: true, noempty: true, nonew: true, regexp: true, undef: true, unused: true, strict: true*/
/*global require*/
require(["src/reader"], function (reader) {

    "use strict";

    function trace() {
        var arr = Array.prototype.slice.apply(arguments);
        var out = document.getElementById(arr[0]);
        out.innerHTML += arr.slice(1).join(" ") + "\n";
    }

    var errored = false;

    function run(cat, name, input, runner) {
        if (errored) {
            return;
        }
        console.log(document.getElementById(cat));
        document.getElementById(cat).parentNode.className = "block populated";
        trace(cat, name + ":");
        if (Array.isArray(input)) {
            for (var i = 0; i < input.length; i++) {
                trace(cat, input[i], "=", runner(input[i]));
            }
        } else {
            trace(cat, input, "=", runner(input));
        }
        trace(cat);
    }

    function read(name, input) {
        run("reader", name, input, function (x) {
            return reader.read(x).join(", ");
        });
    }

    window.onload = function () {

        var t = new Date().getTime();

        read("symbols", ["a", "lower", "UPPER", "camelCase", "CamelCase", "j0", "hyphen-ated", "under_scored", "dot.ted", ".length", "úņīčőđē"]);

        read("ints", "5");
        read("floats", "5.2");
        read("hex", "0xFF");

        read("strings", ['"word"', '"how long is a piece of..."; string', '"escape \\"this\\""']);

        read("comments", ["; sup?", "; an expr:\n(do 1)"]);

        read("empty paren list", "()");
        read("empty bracket list", "[]");
        read("empty brace list", "{}");

        read("1-item paren list", "(a)");
        read("1-item bracket list", "[a]");
        read("1-item brace list", "{a}");

        read("2-item paren list", "(a 5)");
        read("2-item bracket list", "[a 5]");
        read("2-item brace list", "{a 5}");

        read("quoting", ["'a", "'5", "'()", "'(a)", "'(a 5)"]);
        read("quasiquoting", ["`a", "`5", "`()", "`(a)", "`(a 5)"]);
        read("unquoting", [",a", ",5", ",()", ",(a)", ",(a 5)"]);
        read("unquote-splicing", [",@a", ",@5", ",@()", ",@(a)", ",@(a 5)"]);

        if (!errored) {
            trace("status", "It's all good.", new Date().getTime() - t, "ms.");
        }
    };

    window.onerror = function (e) {
        trace("status", "There was an error:", e);
        errored = true;
    };

});<commit_msg>Updated playground to use util.printRawForm<commit_after>/*jshint browser: true, devel: true, bitwise: true, camelcase: true, curly: true, eqeqeq: true, forin: true, immed: true, indent: 4, latedef: true, newcap: true, noarg: true, noempty: true, nonew: true, regexp: true, undef: true, unused: true, strict: true*/
/*global require*/
require(["reader", "expander", "util"], function (reader, expander, util) {

    "use strict";

    function trace() {
        var arr = Array.prototype.slice.apply(arguments);
        var out = document.getElementById(arr[0]);
        out.innerHTML += arr.slice(1).join(" ") + "\n";
    }

    var errored = false;

    function run(cat, name, input, runner) {
        if (errored) {
            return;
        }
        document.getElementById(cat).parentNode.className = "block populated";
        trace(cat, name + ":");
        if (Array.isArray(input)) {
            for (var i = 0; i < input.length; i++) {
                trace(cat, input[i], "=", runner(input[i]));
            }
        } else {
            trace(cat, input, "=", runner(input));
        }
        trace(cat);
    }

    function read(name, input) {
        run("reader", name, input, function (x) {
            return util.printRawForm(reader.read(x));
        });
    }

    function expand(name, input) {
        run("expander", name, input, function (x) {
            return util.printRawForm(expander.expand(reader.read(x)));
        });
    }

    window.onload = function () {

        var t = new Date().getTime();

        read("symbols", ["a", "lower", "UPPER", "camelCase", "CamelCase", "j0", "hyphen-ated", "under_scored", "dot.ted", ".length", "úņīčőđē"]);

        read("ints", "5");
        read("floats", "5.2");
        read("hex", "0xFF");

        read("strings", ['"word"', '"how long is a piece of..."; string', '"escape \\"this\\""']);

        read("comments", ["; sup?", "; an expr:\n(do 1)"]);

        read("empty paren list", "()");
        read("empty bracket list", "[]");
        read("empty brace list", "{}");

        read("1-item paren list", "(a)");
        read("1-item bracket list", "[a]");
        read("1-item brace list", "{a}");

        read("2-item paren list", "(a 5)");
        read("2-item bracket list", "[a 5]");
        read("2-item brace list", "{a 5}");

        read("multiline paren list", ["(do\nsome\nthing)", "(do\n;some\nthing)"]);

        read("quoting", ["'a", "'5", "'()", "'(a)", "'(a 5)"]);
        read("quasiquoting", ["`a", "`5", "`()", "`(a)", "`(a 5)"]);
        read("unquoting", [",a", ",5", ",()", ",(a)", ",(a 5)"]);
        read("unquote-splicing", [",@a", ",@5", ",@()", ",@(a)", ",@(a 5)"]);

        // ---

        expand("symbols", ["a", ".length"]);
        expand("literals", ["5", "5.2", "0xFF", '"word"']);
        expand("comments", ["; sup?"]);

        expand("1-item paren list", "(a)");

        expand("comments in lists", ["(do\n;some\nthing)"]);

        if (!errored) {
            trace("status", "It's all good.", new Date().getTime() - t, "ms.");
        }
    };

    window.onerror = function (e) {
        trace("status", "There was an error:", e);
        errored = true;
    };

});<|endoftext|>


<commit_before>;(function(exports){
    var D = function(a){function b(a){j(function(){throw a})}function c(b){return this.then(b,a)}function d(b){return this.then(a,b)}function e(b,c){return this.then(function(a){return k(b)?b.apply(null,l(a)?a:[a]):t.onlyFuncs?a:b},c||a)}function f(a){function b(){a()}return this.then(b,b),this}function g(a){return this.then(function(b){return k(a)?a.apply(null,l(b)?b.splice(0,0,void 0)&&b:[void 0,b]):t.onlyFuncs?b:a},function(b){return a(b)})}function h(c){return this.then(a,c?function(a){throw c(a),a}:b)}function i(a,b){var c=o(a);if(1===c.length&&l(c[0])){if(!c[0].length)return t.fulfilled([]);c=c[0]}var d=[],e=t(),f=c.length;if(f)for(var g=(function(a){c[a]=t.promisify(c[a]),c[a].then(function(g){a in d||(d[a]=b?c[a]:g,--f||e.resolve(d))},function(g){a in d||(b?(d[a]=c[a],--f||e.resolve(d)):e.reject(g))})}),h=0,i=f;i>h;h++)g(h);else e.resolve(d);return e.promise}var j,k=function(a){return"function"==typeof a},l=function(a){return Array.isArray?Array.isArray(a):a instanceof Array},m=function(a){return!(!a||!(typeof a).match(/function|object/))},n=function(b){return b===!1||b===a||null===b},o=function(a,b){return[].slice.call(a,b)},p="undefined",q=typeof TypeError===p?Error:TypeError;if(typeof process!==p&&process.nextTick)j=process.nextTick;else if(typeof MessageChannel!==p){var r=new MessageChannel,s=[];r.port1.onmessage=function(){s.length&&s.shift()()},j=function(a){s.push(a),r.port2.postMessage(0)}}else j=function(a){setTimeout(a,0)};var t=function(b){function i(){if(0!==s){var a,b=u,c=0,d=b.length,e=~s?0:1;for(u=[];d>c;c++)(a=b[c][e])&&a(p)}}function l(a){function b(a){return function(b){return c?void 0:(c=!0,a(b))}}var c=!1;if(s)return this;try{var d=m(a)&&a.then;if(k(d)){if(a===v)throw new q("Promise can't resolve itself");return d.call(a,b(l),b(o)),this}}catch(e){return b(o)(e),this}return r(function(){p=a,s=1,i()}),this}function o(a){return s||r(function(){try{throw a}catch(b){p=b}s=-1,i()}),this}var p,r=(a!==b?b:t.alwaysAsync)?j:function(a){a()},s=0,u=[],v={then:function(a,b){var c=t();return u.push([function(b){try{n(a)?c.resolve(b):c.resolve(k(a)?a(b):t.onlyFuncs?b:a)}catch(d){c.reject(d)}},function(a){if((n(b)||!k(b)&&t.onlyFuncs)&&c.reject(a),b)try{c.resolve(k(b)?b(a):b)}catch(d){c.reject(d)}}]),0!==s&&r(i),c.promise},success:c,error:d,otherwise:d,apply:e,spread:e,ensure:f,nodify:g,rethrow:h,isPending:function(){return!(0!==s)},getStatus:function(){return s}};return v.toSource=v.toString=v.valueOf=function(){return p===a?this:p},{promise:v,resolve:l,fulfill:l,reject:o}};t.deferred=t.defer=t,t.nextTick=j,t.alwaysAsync=!0,t.onlyFuncs=!0,t.resolved=t.fulfilled=function(a){return t(!0).resolve(a).promise},t.rejected=function(a){return t(!0).reject(a).promise},t.wait=function(a){var b=t();return setTimeout(b.resolve,a||0),b.promise},t.delay=function(a,b){var c=t();return setTimeout(function(){try{c.resolve(a.apply(null))}catch(b){c.reject(b)}},b||0),c.promise},t.promisify=function(a){return a&&k(a.then)?a:t.resolved(a)},t.all=function(){return i(arguments,!1)},t.resolveAll=function(){return i(arguments,!0)},t.nodeCapsule=function(a,b){return b||(b=a,a=void 0),function(){var c=t(),d=o(arguments);d.push(function(a,b){a?c.reject(a):c.resolve(arguments.length>2?o(arguments,1):b)});try{b.apply(a,d)}catch(e){c.reject(e)}return c.promise}};return t;}();

    BASE_URL = "https://api.outbound.io/v2";
    VERSION = '0.1.1';

    function headers(apiKey) {
        return {
            'Content-type': 'application/json',
            'X-Outbound-Client': 'javascript',
            'X-Outbound-Client-Version': VERSION,
            'X-Outbound-Key': apiKey
        };
    }

    function error(msg, receivedCall) {
        return {
            'receivedCall': receivedCall || false,
            'message': msg
        }
    }

    function user(info, attributes) {
        data = {};
        if (info && Object.prototype.toString.call(info) === '[object Object]') {
            if (info.firstName && typeof info.firstName) {
                data.first_name = info.firstName;
            }
            if (info.lastName && typeof info.lastName) {
                data.last_name = info.lastName;
            }
            if (info.email && typeof info.email) {
                data.email = info.email;
            }
            if (info.phoneNumber && typeof info.phoneNumber) {
                data.phone_number = info.phoneNumber;
            }
            if (info.apnsTokens) {
                if (typeof info.apnsTokens == 'string') {
                    info.apnsTokens = [info.apnsTokens];
                }
                if (Object.prototype.toString.call(info.apnsTokens) === '[object Array]') {
                    data.apns = info.apnsTokens;
                }
            }
            if (info.gcmTokens) {
                if (typeof info.gcmTokens == 'string') {
                    attributes.gcmTokens = [info.gcmTokens];
                }
                if (Object.prototype.toString.call(info.gcmTokens) === '[object Array]') {
                    data.gcm = info.gcmTokens;
                }
            }
        }
        if (attributes && Object.prototype.toString.call(attributes) === '[object Object]') {
            data.attributes = attributes;
        }
        return data
    }

    function post(endpoint, data, headers, deferred) {
        if (module !== 'undefined') {
            var request = require('request');
            request(
                {
                    url: BASE_URL + endpoint,
                    method: 'POST',
                    headers: headers,
                    json: data
                },
                function (err, response, body) {
                    if (err) {
                        deferred.reject(error(err.Error, false));
                    } else if(response.statusCode >= 200 && response.statusCode < 400) {
                        deferred.resolve();
                    } else {
                        deferred.reject(error(body, true));
                    }
                }
            );
        } else {
            var request = new XMLHttpRequest();
            request.open('POST', BASE_URL + endpoint, true);
            for (var header in headers) {
                request.setRequestHeader(header, headers[header]);
            }

            request.onload = function() {
                resp = request.responseText;
                if (request.status >= 200 && request.status < 400){
                    deferred.resolve();
                } else {
                    deferred.reject(error(resp, true));
                }
            };
            request.onerror = function() {
                deferred.reject(error(null, false));
            };
            request.send(data);
        }
    }

    function Outbound(apiKey) {
        this.apiKey = apiKey;
    }

    Outbound.prototype.identify = function(userId, info, attributes) {
        var deferred = D();

        var typeofUserId = typeof userId;
        if (typeofUserId != "number" && typeofUserId != "string") {
            deferred.reject(error("Invalid user ID. Expected string or number, got " + typeofUserId, false));
        } else {
            requestData = {"user_id": userId}

            user = user(info, attributes)
            for (var attr in user) {
                requestData[attr] = user[attr];
            }

            post('/identify', requestData, headers(this.apiKey), deferred);
        }
        return deferred.promise;
    }

    Outbound.prototype.track = function(userId, event, properties, userInfo, userAttributes) {
        var deferred = D();

        var typeofUserId = typeof userId;
        var typeofEvent = typeof event;
        if (typeofUserId != "number" || typeofUserId != "string") {
            deferred.reject(error("Invalid user ID. Expected string or number, got " + typeofUserId, false));
        } else  if (typeofEvent != "string") {
            deferred.reject(error("Invalid event. Expected string, got " + typeofEvent, false));
        } else {
            requestData = {"user_id": userId, "properties": {}}

            user = user(userInfo, userAttributes)
            for (var attr in user) {
                if (!requestData.user) {
                    requestData.user = {};
                }
                requestData.user[attr] = user[attr];
            }

            if (properties && typeof properties == 'object') {
                for (var attr in properties) {
                    requestData.properties[attr] = user[attr];
                }
            }
            post('/track', requestData, headers(this.apiKey), deferred);
        }
        return deferred.promise;
    }

    typeof window !== 'undefined' && (window.outbound = Outbound)
    typeof module !== 'undefined' && module.exports && (module.exports = Outbound)
})();
<commit_msg>Use correct operator<commit_after>;(function(exports){
    var D = function(a){function b(a){j(function(){throw a})}function c(b){return this.then(b,a)}function d(b){return this.then(a,b)}function e(b,c){return this.then(function(a){return k(b)?b.apply(null,l(a)?a:[a]):t.onlyFuncs?a:b},c||a)}function f(a){function b(){a()}return this.then(b,b),this}function g(a){return this.then(function(b){return k(a)?a.apply(null,l(b)?b.splice(0,0,void 0)&&b:[void 0,b]):t.onlyFuncs?b:a},function(b){return a(b)})}function h(c){return this.then(a,c?function(a){throw c(a),a}:b)}function i(a,b){var c=o(a);if(1===c.length&&l(c[0])){if(!c[0].length)return t.fulfilled([]);c=c[0]}var d=[],e=t(),f=c.length;if(f)for(var g=(function(a){c[a]=t.promisify(c[a]),c[a].then(function(g){a in d||(d[a]=b?c[a]:g,--f||e.resolve(d))},function(g){a in d||(b?(d[a]=c[a],--f||e.resolve(d)):e.reject(g))})}),h=0,i=f;i>h;h++)g(h);else e.resolve(d);return e.promise}var j,k=function(a){return"function"==typeof a},l=function(a){return Array.isArray?Array.isArray(a):a instanceof Array},m=function(a){return!(!a||!(typeof a).match(/function|object/))},n=function(b){return b===!1||b===a||null===b},o=function(a,b){return[].slice.call(a,b)},p="undefined",q=typeof TypeError===p?Error:TypeError;if(typeof process!==p&&process.nextTick)j=process.nextTick;else if(typeof MessageChannel!==p){var r=new MessageChannel,s=[];r.port1.onmessage=function(){s.length&&s.shift()()},j=function(a){s.push(a),r.port2.postMessage(0)}}else j=function(a){setTimeout(a,0)};var t=function(b){function i(){if(0!==s){var a,b=u,c=0,d=b.length,e=~s?0:1;for(u=[];d>c;c++)(a=b[c][e])&&a(p)}}function l(a){function b(a){return function(b){return c?void 0:(c=!0,a(b))}}var c=!1;if(s)return this;try{var d=m(a)&&a.then;if(k(d)){if(a===v)throw new q("Promise can't resolve itself");return d.call(a,b(l),b(o)),this}}catch(e){return b(o)(e),this}return r(function(){p=a,s=1,i()}),this}function o(a){return s||r(function(){try{throw a}catch(b){p=b}s=-1,i()}),this}var p,r=(a!==b?b:t.alwaysAsync)?j:function(a){a()},s=0,u=[],v={then:function(a,b){var c=t();return u.push([function(b){try{n(a)?c.resolve(b):c.resolve(k(a)?a(b):t.onlyFuncs?b:a)}catch(d){c.reject(d)}},function(a){if((n(b)||!k(b)&&t.onlyFuncs)&&c.reject(a),b)try{c.resolve(k(b)?b(a):b)}catch(d){c.reject(d)}}]),0!==s&&r(i),c.promise},success:c,error:d,otherwise:d,apply:e,spread:e,ensure:f,nodify:g,rethrow:h,isPending:function(){return!(0!==s)},getStatus:function(){return s}};return v.toSource=v.toString=v.valueOf=function(){return p===a?this:p},{promise:v,resolve:l,fulfill:l,reject:o}};t.deferred=t.defer=t,t.nextTick=j,t.alwaysAsync=!0,t.onlyFuncs=!0,t.resolved=t.fulfilled=function(a){return t(!0).resolve(a).promise},t.rejected=function(a){return t(!0).reject(a).promise},t.wait=function(a){var b=t();return setTimeout(b.resolve,a||0),b.promise},t.delay=function(a,b){var c=t();return setTimeout(function(){try{c.resolve(a.apply(null))}catch(b){c.reject(b)}},b||0),c.promise},t.promisify=function(a){return a&&k(a.then)?a:t.resolved(a)},t.all=function(){return i(arguments,!1)},t.resolveAll=function(){return i(arguments,!0)},t.nodeCapsule=function(a,b){return b||(b=a,a=void 0),function(){var c=t(),d=o(arguments);d.push(function(a,b){a?c.reject(a):c.resolve(arguments.length>2?o(arguments,1):b)});try{b.apply(a,d)}catch(e){c.reject(e)}return c.promise}};return t;}();

    BASE_URL = "https://api.outbound.io/v2";
    VERSION = '0.1.3';

    function headers(apiKey) {
        return {
            'Content-type': 'application/json',
            'X-Outbound-Client': 'javascript',
            'X-Outbound-Client-Version': VERSION,
            'X-Outbound-Key': apiKey
        };
    }

    function error(msg, receivedCall) {
        return {
            'receivedCall': receivedCall || false,
            'message': msg
        }
    }

    function user(info, attributes) {
        data = {};
        if (info && Object.prototype.toString.call(info) === '[object Object]') {
            if (info.firstName && typeof info.firstName) {
                data.first_name = info.firstName;
            }
            if (info.lastName && typeof info.lastName) {
                data.last_name = info.lastName;
            }
            if (info.email && typeof info.email) {
                data.email = info.email;
            }
            if (info.phoneNumber && typeof info.phoneNumber) {
                data.phone_number = info.phoneNumber;
            }
            if (info.apnsTokens) {
                if (typeof info.apnsTokens == 'string') {
                    info.apnsTokens = [info.apnsTokens];
                }
                if (Object.prototype.toString.call(info.apnsTokens) === '[object Array]') {
                    data.apns = info.apnsTokens;
                }
            }
            if (info.gcmTokens) {
                if (typeof info.gcmTokens == 'string') {
                    attributes.gcmTokens = [info.gcmTokens];
                }
                if (Object.prototype.toString.call(info.gcmTokens) === '[object Array]') {
                    data.gcm = info.gcmTokens;
                }
            }
        }
        if (attributes && Object.prototype.toString.call(attributes) === '[object Object]') {
            data.attributes = attributes;
        }
        return data
    }

    function post(endpoint, data, headers, deferred) {
        if (module !== 'undefined') {
            var request = require('request');
            request(
                {
                    url: BASE_URL + endpoint,
                    method: 'POST',
                    headers: headers,
                    json: data
                },
                function (err, response, body) {
                    if (err) {
                        deferred.reject(error(err.Error, false));
                    } else if(response.statusCode >= 200 && response.statusCode < 400) {
                        deferred.resolve();
                    } else {
                        deferred.reject(error(body, true));
                    }
                }
            );
        } else {
            var request = new XMLHttpRequest();
            request.open('POST', BASE_URL + endpoint, true);
            for (var header in headers) {
                request.setRequestHeader(header, headers[header]);
            }

            request.onload = function() {
                resp = request.responseText;
                if (request.status >= 200 && request.status < 400){
                    deferred.resolve();
                } else {
                    deferred.reject(error(resp, true));
                }
            };
            request.onerror = function() {
                deferred.reject(error(null, false));
            };
            request.send(data);
        }
    }

    function Outbound(apiKey) {
        this.apiKey = apiKey;
    }

    Outbound.prototype.identify = function(userId, info, attributes) {
        var deferred = D();

        var typeofUserId = typeof userId;
        if (typeofUserId != "number" && typeofUserId != "string") {
            deferred.reject(error("Invalid user ID. Expected string or number, got " + typeofUserId, false));
        } else {
            requestData = {"user_id": userId}

            user = user(info, attributes)
            for (var attr in user) {
                requestData[attr] = user[attr];
            }

            post('/identify', requestData, headers(this.apiKey), deferred);
        }
        return deferred.promise;
    }

    Outbound.prototype.track = function(userId, event, properties, userInfo, userAttributes) {
        var deferred = D();

        var typeofUserId = typeof userId;
        var typeofEvent = typeof event;
        if (typeofUserId != "number" && typeofUserId != "string") {
            deferred.reject(error("Invalid user ID. Expected string or number, got " + typeofUserId, false));
        } else  if (typeofEvent != "string") {
            deferred.reject(error("Invalid event. Expected string, got " + typeofEvent, false));
        } else {
            requestData = {"user_id": userId, "properties": {}}

            user = user(userInfo, userAttributes)
            for (var attr in user) {
                if (!requestData.user) {
                    requestData.user = {};
                }
                requestData.user[attr] = user[attr];
            }

            if (properties && typeof properties == 'object') {
                for (var attr in properties) {
                    requestData.properties[attr] = user[attr];
                }
            }
            post('/track', requestData, headers(this.apiKey), deferred);
        }
        return deferred.promise;
    }

    typeof window !== 'undefined' && (window.outbound = Outbound)
    typeof module !== 'undefined' && module.exports && (module.exports = Outbound)
})();
<|endoftext|>


<commit_before>// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

class BaseTimeline {
	constructor(opts) {
		Object.assign(this, opts);
		this.make();
	}

	make() {
		this.timeline_wrapper = $(`<div class="new-timeline">`);
		this.timeline_items_wrapper = $(`<div class="timeline-items">`);
		this.timeline_actions_wrapper = $(`

		`);

		this.timeline_wrapper.append(this.timeline_actions_wrapper);
		this.timeline_actions_wrapper.hide();
		this.timeline_wrapper.append(this.timeline_items_wrapper);

		this.parent.replaceWith(this.timeline_wrapper);
		this.timeline_items = [];
	}

	refresh() {
		this.render_timeline_items();
	}

	add_action_button(label, action) {
		this.timeline_actions_wrapper.show();
		let action_btn = $(`<button class="btn btn-xs btn-default action-btn">${label}</button>`);
		action_btn.click(action);
		this.timeline_actions_wrapper.append(action_btn);
		return action_btn;
	}

	render_timeline_items() {
		this.timeline_items_wrapper.empty();
		this.timeline_items = [];
		this.doc_info = this.frm && this.frm.get_docinfo() || {};
		let response = this.prepare_timeline_contents();
		if (response instanceof Promise) {
			response.then(() => {
				this.timeline_items.sort((item1, item2) => new Date(item1.creation) - new Date(item2.creation));
				this.timeline_items.forEach(this.add_timeline_item.bind(this));
			});
		} else {
			this.timeline_items.sort((item1, item2) => new Date(item1.creation) - new Date(item2.creation));
			this.timeline_items.forEach(this.add_timeline_item.bind(this));
		}
	}

	prepare_timeline_contents() {
		//
	}

	add_timeline_item(item, append_at_the_end=false) {
		let timeline_item = this.get_timeline_item(item);
		if (append_at_the_end) {
			this.timeline_items_wrapper.append(timeline_item);
		} else {
			this.timeline_items_wrapper.prepend(timeline_item);
		}
		return timeline_item;
	}

	add_timeline_items(items, append_at_the_end=false) {
		items.forEach((item) => this.add_timeline_item(item, append_at_the_end));
	}

	get_timeline_item(item) {
		// item can have content*, creation*,
		// timeline_badge, icon, icon_size,
		// hide_timestamp, is_card
		const timeline_item = $(`<div class="timeline-item">`);

		if (item.icon) {
			timeline_item.append(`

					${frappe.utils.icon(item.icon, item.icon_size || 'md')}

			`);
		} else if (item.timeline_badge) {
			timeline_item.append(item.timeline_badge);
		} else {
			timeline_item.append(`<div class="timeline-dot">`);
		}

		timeline_item.append(`<div class="timeline-content ${item.is_card ? 'frappe-card' : ''}">`);
		timeline_item.find('.timeline-content').append(item.content);
		if (!item.hide_timestamp && !item.is_card) {
			timeline_item.find('.timeline-content').append(`<span> - ${comment_when(item.creation)}</span>`);
		}
		return timeline_item;
	}
}

export default BaseTimeline;<commit_msg>fix: Timeline sequence<commit_after>// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

class BaseTimeline {
	constructor(opts) {
		Object.assign(this, opts);
		this.make();
	}

	make() {
		this.timeline_wrapper = $(`<div class="new-timeline">`);
		this.timeline_items_wrapper = $(`<div class="timeline-items">`);
		this.timeline_actions_wrapper = $(`

		`);

		this.timeline_wrapper.append(this.timeline_actions_wrapper);
		this.timeline_actions_wrapper.hide();
		this.timeline_wrapper.append(this.timeline_items_wrapper);

		this.parent.replaceWith(this.timeline_wrapper);
		this.timeline_items = [];
	}

	refresh() {
		this.render_timeline_items();
	}

	add_action_button(label, action) {
		this.timeline_actions_wrapper.show();
		let action_btn = $(`<button class="btn btn-xs btn-default action-btn">${label}</button>`);
		action_btn.click(action);
		this.timeline_actions_wrapper.append(action_btn);
		return action_btn;
	}

	render_timeline_items() {
		this.timeline_items_wrapper.empty();
		this.timeline_items = [];
		this.doc_info = this.frm && this.frm.get_docinfo() || {};
		let response = this.prepare_timeline_contents();
		if (response instanceof Promise) {
			response.then(() => {
				this.timeline_items.sort((item1, item2) =>  new Date(item2.creation) - new Date(item1.creation));
				this.timeline_items.forEach(this.add_timeline_item.bind(this));
			});
		} else {
			this.timeline_items.sort((item1, item2) =>  new Date(item2.creation) - new Date(item1.creation));
			this.timeline_items.forEach(this.add_timeline_item.bind(this));
		}
	}

	prepare_timeline_contents() {
		//
	}

	add_timeline_item(item, append_at_the_end=false) {
		let timeline_item = this.get_timeline_item(item);
		if (append_at_the_end) {
			this.timeline_items_wrapper.append(timeline_item);
		} else {
			this.timeline_items_wrapper.prepend(timeline_item);
		}
		return timeline_item;
	}

	add_timeline_items(items, append_at_the_end=false) {
		items.forEach((item) => this.add_timeline_item(item, append_at_the_end));
	}

	get_timeline_item(item) {
		// item can have content*, creation*,
		// timeline_badge, icon, icon_size,
		// hide_timestamp, is_card
		const timeline_item = $(`<div class="timeline-item">`);

		if (item.icon) {
			timeline_item.append(`

					${frappe.utils.icon(item.icon, item.icon_size || 'md')}

			`);
		} else if (item.timeline_badge) {
			timeline_item.append(item.timeline_badge);
		} else {
			timeline_item.append(`<div class="timeline-dot">`);
		}

		timeline_item.append(`<div class="timeline-content ${item.is_card ? 'frappe-card' : ''}">`);
		timeline_item.find('.timeline-content').append(item.content);
		if (!item.hide_timestamp && !item.is_card) {
			timeline_item.find('.timeline-content').append(`<span> - ${comment_when(item.creation)}</span>`);
		}
		return timeline_item;
	}
}

export default BaseTimeline;<|endoftext|>