'use strict';

const Promise = require('bluebird');

describe('list_categories', () => {
  const Hexo = require('../../../lib/hexo');
  const hexo = new Hexo(__dirname);
  const Post = hexo.model('Post');
  const Category = hexo.model('Category');

  const ctx = {
    config: hexo.config
  };

  ctx.url_for = require('../../../lib/plugins/helper/url_for').bind(ctx);

  const listCategories = require('../../../lib/plugins/helper/list_categories').bind(ctx);

  before(() => hexo.init().then(() => Post.insert([
    {source: 'foo', slug: 'foo'},
    {source: 'bar', slug: 'bar'},
    {source: 'baz', slug: 'baz'},
    {source: 'boo', slug: 'boo'},
    {source: 'bat', slug: 'bat'}
  ])).then(posts => Promise.each([
    ['baz'],
    ['baz', 'bar'],
    ['foo'],
    ['baz'],
    ['bat', ['baz', 'bar']]
  ], (cats, i) => posts[i].setCategories(cats))).then(() => {
    hexo.locals.invalidate();
    ctx.site = hexo.locals.toObject();
    ctx.page = ctx.site.posts.data[1];
  }));

  it('default', () => {
    const result = listCategories();

    result.should.eql([
      '
',
      '
',
      'bat1',
      '
',
      '
',
      'baz4',
      '
',
      '
',
      'bar2',
      '
',
      '
',
      '
',
      '
',
      'foo1',
      '
',
      '
'
    ].join(''));
  });

  it('specified collection', () => {
    const result = listCategories(Category.find({
      parent: {$exists: false}
    }));

    result.should.eql([
      '
',
      '
',
      'bat1',
      '
',
      '
',
      'baz4',
      '
',
      '
',
      'foo1',
      '
',
      '
'
    ].join(''));
  });

  it('style: false', () => {
    const result = listCategories({
      style: false
    });

    result.should.eql([
      'bat1',
      'baz4',
      'bar2',
      'foo1'
    ].join(', '));
  });

  it('show_count: false', () => {
    const result = listCategories({
      show_count: false
    });

    result.should.eql([
      '
',
      '
',
      'bat',
      '
',
      '
',
      'baz',
      '
',
      '
',
      'bar',
      '
',
      '
',
      '
',
      '
',
      'foo',
      '
',
      '
'
    ].join(''));
  });

  it('class', () => {
    const result = listCategories({
      class: 'test'
    });

    result.should.eql([
      '
',
      '
',
      'bat1',
      '
',
      '
',
      'baz4',
      '
',
      '
',
      'bar2',
      '
',
      '
',
      '
',
      '
',
      'foo1',
      '
',
      '
'
    ].join(''));
  });

  it('depth', () => {
    const result = listCategories({
      depth: 1
    });

    result.should.eql([
      '
',
      '
',
      'bat1',
      '
',
      '
',
      'baz4',
      '
',
      '
',
      'foo1',
      '
',
      '
'
    ].join(''));
  });

  it('orderby', () => {
    const result = listCategories({
      orderby: 'length'
    });

    result.should.eql([
      '
',
      '
',
      'foo1',
      '
',
      '
',
      'bat1',
      '
',
      '
',
      'baz4',
      '
',
      '
',
      'bar2',
      '
',
      '
',
      '
',
      '
'
    ].join(''));
  });

  it('order', () => {
    const result = listCategories({
      order: -1
    });

    result.should.eql([
      '
',
      '
',
      'foo1',
      '
',
      '
',
      'baz4',
      '
',
      '
',
      'bar2',
      '
',
      '
',
      '
',
      '
',
      'bat1',
      '
',
      '
'
    ].join(''));
  });

  it('transform', () => {
    const result = listCategories({
      transform(name) {
        return name.toUpperCase();
      }
    });

    result.should.eql([
      '
',
      '
',
      'BAT1',
      '
',
      '
',
      'BAZ4',
      '
',
      '
',
      'BAR2',
      '
',
      '
',
      '
',
      '
',
      'FOO1',
      '
',
      '
'
    ].join(''));
  });

  it('separator (blank)', () => {
    const result = listCategories({
      style: false,
      separator: ''
    });

    result.should.eql([
      'bat1',
      'baz4',
      'bar2',
      'foo1'
    ].join(''));
  });

  it('separator (non-blank)', () => {
    const result = listCategories({
      style: false,
      separator: '|'
    });

    result.should.eql([
      'bat1|',
      'baz4|',
      'bar2|',
      'foo1'
    ].join(''));
  });

  it('children-indicator', () => {
    const result = listCategories({
      children_indicator: 'has-children'
    });

    result.should.eql([
      '
',
      '
',
      'bat1',
      '
',
      '
',
      'baz4',
      '
',
      '
',
      'bar2',
      '
',
      '
',
      '
',
      '
',
      'foo1',
      '
',
      '
'
    ].join(''));
  });

  it('show-current', () => {
    const result = listCategories({
      show_current: true
    });

    result.should.eql([
      '
',
      '
',
      'bat1',
      '
',
      '
',
      'baz4',
      '
',
      '
',
      'bar2',
      '
',
      '
',
      '
',
      '
',
      'foo1',
      '
',
      '
'
    ].join(''));
  });
});


'use strict';

const pathFn = require('path');
const fs = require('hexo-fs');
const cloneDeep = require('lodash/cloneDeep');

describe('Load config', () => {
  const Hexo = require('../../../lib/hexo');
  const hexo = new Hexo(pathFn.join(__dirname, 'config_test'), {silent: true});
  const loadConfig = require('../../../lib/hexo/load_config');
  const defaultConfig = require('../../../lib/hexo/default_config');

  hexo.env.init = true;

  before(() => fs.mkdirs(hexo.base_dir).then(() => hexo.init()));

  after(() => fs.rmdir(hexo.base_dir));

  beforeEach(() => {
    hexo.config = cloneDeep(defaultConfig);
  });

  it('config file does not exist', () => loadConfig(hexo).then(() => {
    hexo.config.should.eql(defaultConfig);
  }));

  it('_config.yml exists', () => {
    const configPath = pathFn.join(hexo.base_dir, '_config.yml');

    return fs.writeFile(configPath, 'foo: 1').then(() => loadConfig(hexo)).then(() => {
      hexo.config.foo.should.eql(1);
    }).finally(() => fs.unlink(configPath));
  });

  it('_config.json exists', () => {
    const configPath = pathFn.join(hexo.base_dir, '_config.json');

    return fs.writeFile(configPath, '{"baz": 3}').then(() => loadConfig(hexo)).then(() => {
      hexo.config.baz.should.eql(3);
    }).finally(() => fs.unlink(configPath));
  });

  it('_config.txt exists', () => {
    const configPath = pathFn.join(hexo.base_dir, '_config.txt');

    return fs.writeFile(configPath, 'foo: 1').then(() => loadConfig(hexo)).then(() => {
      hexo.config.should.eql(defaultConfig);
    }).finally(() => fs.unlink(configPath));
  });

  it('custom config path', () => {
    const configPath = pathFn.join(__dirname, 'werwerwer.yml');
    hexo.config_path = pathFn.join(__dirname, 'werwerwer.yml');

    return fs.writeFile(configPath, 'foo: 1').then(() => loadConfig(hexo)).then(() => {
      hexo.config.foo.should.eql(1);
    }).finally(() => {
      hexo.config_path = pathFn.join(hexo.base_dir, '_config.yml');
      return fs.unlink(configPath);
    });
  });

  it('custom config path with different extension name', () => {
    const realPath = pathFn.join(__dirname, 'werwerwer.json');
    hexo.config_path = pathFn.join(__dirname, 'werwerwer.yml');

    return fs.writeFile(realPath, '{"foo": 2}').then(() => loadConfig(hexo)).then(() => {
      hexo.config.foo.should.eql(2);
      hexo.config_path.should.eql(realPath);
    }).finally(() => {
      hexo.config_path = pathFn.join(hexo.base_dir, '_config.yml');
      return fs.unlink(realPath);
    });
  });

  it('handle trailing "/" of url', () => {
    const content = [
      'root: foo',
      'url: https://hexo.io/'
    ].join('\n');

    return fs.writeFile(hexo.config_path, content).then(() => loadConfig(hexo)).then(() => {
      hexo.config.root.should.eql('foo/');
      hexo.config.url.should.eql('https://hexo.io');
    }).finally(() => fs.unlink(hexo.config_path));
  });

  it('custom public_dir', () => fs.writeFile(hexo.config_path, 'public_dir: foo').then(() => loadConfig(hexo)).then(() => {
    hexo.public_dir.should.eql(pathFn.resolve(hexo.base_dir, 'foo') + pathFn.sep);
  }).finally(() => fs.unlink(hexo.config_path)));

  it('custom source_dir', () => fs.writeFile(hexo.config_path, 'source_dir: bar').then(() => loadConfig(hexo)).then(() => {
    hexo.source_dir.should.eql(pathFn.resolve(hexo.base_dir, 'bar') + pathFn.sep);
  }).finally(() => fs.unlink(hexo.config_path)));

  it('custom theme', () => fs.writeFile(hexo.config_path, 'theme: test').then(() => loadConfig(hexo)).then(() => {
    hexo.config.theme.should.eql('test');
    hexo.theme_dir.should.eql(pathFn.join(hexo.base_dir, 'themes', 'test') + pathFn.sep);
    hexo.theme_script_dir.should.eql(pathFn.join(hexo.theme_dir, 'scripts') + pathFn.sep);
    hexo.theme.base.should.eql(hexo.theme_dir);
  }).finally(() => fs.unlink(hexo.config_path)));

  it('merge config', () => {
    const content = [
      'highlight:',
      '  tab_replace: yoooo'
    ].join('\n');

    return fs.writeFile(hexo.config_path, content).then(() => loadConfig(hexo)).then(() => {
      hexo.config.highlight.enable.should.be.true;
      hexo.config.highlight.tab_replace.should.eql('yoooo');
    }).finally(() => fs.unlink(hexo.config_path));
  });
});


'use strict';

module.exports = ctx => {
  const { helper } = ctx.extend;

  const date = require('./date');

  helper.register('date', date.date);
  helper.register('date_xml', date.date_xml);
  helper.register('time', date.time);
  helper.register('full_date', date.full_date);
  helper.register('relative_date', date.relative_date);
  helper.register('time_tag', date.time_tag);
  helper.register('moment', date.moment);

  helper.register('search_form', require('./search_form'));

  const format = require('./format');

  helper.register('strip_html', format.strip_html);
  helper.register('trim', format.trim);
  helper.register('titlecase', format.titlecase);
  helper.register('word_wrap', format.word_wrap);
  helper.register('truncate', format.truncate);

  helper.register('fragment_cache', require('./fragment_cache')(ctx));

  helper.register('gravatar', require('./gravatar'));

  const is = require('./is');
  helper.register('is_current', is.current);
  helper.register('is_home', is.home);
  helper.register('is_post', is.post);
  helper.register('is_page', is.page);
  helper.register('is_archive', is.archive);
  helper.register('is_year', is.year);
  helper.register('is_month', is.month);
  helper.register('is_category', is.category);
  helper.register('is_tag', is.tag);

  helper.register('list_archives', require('./list_archives'));
  helper.register('list_categories', require('./list_categories'));
  helper.register('list_tags', require('./list_tags'));
  helper.register('list_posts', require('./list_posts'));

  helper.register('open_graph', require('./open_graph'));

  helper.register('number_format', require('./number_format'));

  helper.register('paginator', require('./paginator'));

  helper.register('partial', require('./partial')(ctx));

  helper.register('markdown', require('./markdown'));
  helper.register('render', require('./render')(ctx));

  helper.register('css', require('./css'));
  helper.register('js', require('./js'));
  helper.register('link_to', require('./link_to'));
  helper.register('mail_to', require('./mail_to'));
  helper.register('image_tag', require('./image_tag'));
  helper.register('favicon_tag', require('./favicon_tag'));
  helper.register('feed_tag', require('./feed_tag'));

  const tagcloud = require('./tagcloud');
  helper.register('tagcloud', tagcloud);
  helper.register('tag_cloud', tagcloud);

  helper.register('toc', require('./toc'));

  helper.register('relative_url', require('./relative_url'));
  helper.register('url_for', require('./url_for'));
  helper.register('full_url_for', require('./full_url_for'));

  const debug = require('./debug');
  helper.register('inspect', debug.inspectObject);
  helper.register('log', debug.log);
};


'use strict';

const cheerio = require('cheerio');

describe('iframe', () => {
  const iframe = require('../../../lib/plugins/tag/iframe');

  it('url', () => {
    const $ = cheerio.load(iframe(['https://zespia.tw']));

    $('iframe').attr('src').should.eql('https://zespia.tw');
    $('iframe').attr('width').should.eql('100%');
    $('iframe').attr('height').should.eql('300');
    $('iframe').attr('frameborder').should.eql('0');
    $('iframe').attr('allowfullscreen').should.eql('');
  });

  it('width', () => {
    const $ = cheerio.load(iframe(['https://zespia.tw', '500']));

    $('iframe').attr('src').should.eql('https://zespia.tw');
    $('iframe').attr('width').should.eql('500');
    $('iframe').attr('height').should.eql('300');
    $('iframe').attr('frameborder').should.eql('0');
    $('iframe').attr('allowfullscreen').should.eql('');
  });

  it('height', () => {
    const $ = cheerio.load(iframe(['https://zespia.tw', '500', '600']));

    $('iframe').attr('src').should.eql('https://zespia.tw');
    $('iframe').attr('width').should.eql('500');
    $('iframe').attr('height').should.eql('600');
    $('iframe').attr('frameborder').should.eql('0');
    $('iframe').attr('allowfullscreen').should.eql('');
  });
});


'use strict';

module.exports = ctx => {
  const { renderer } = ctx.extend;

  const plain = require('./plain');

  renderer.register('htm', 'html', plain, true);
  renderer.register('html', 'html', plain, true);
  renderer.register('css', 'css', plain, true);
  renderer.register('js', 'js', plain, true);

  renderer.register('json', 'json', require('./json'), true);

  renderer.register('swig', 'html', require('./swig'), true);

  const yaml = require('./yaml');

  renderer.register('yml', 'json', yaml, true);
  renderer.register('yaml', 'json', yaml, true);
};


'use strict';

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


'use strict';

const expect = require('chai').expect;

describe('Tag Errors', () => {
  const Tag = require('../../../lib/extend/tag');

  const assertNunjucksError = (err, line, type) => {
    console.log(err.name, err.line, err.type);
    console.log(err.message);

    err.should.have.property('name', 'Nunjucks Error');
    err.should.have.property('message');
    err.should.have.property('line', line);
    err.should.have.property('type', type);
  };

  it('unknown tag', () => {
    const tag = new Tag();

    const body = [
      '{% abc %}',
      '  content',
      '{% endabc %}'
    ].join('\n');

    return tag.render(body)
      .then(result => {
        console.log(result);
        throw new Error('should return error');
      })
      .catch(err => {
        assertNunjucksError(err, 1, 'unknown block tag: abc');
      });
  });

  it('no closing tag 1', () => {
    const tag = new Tag();

    tag.register('test',
      (args, content) => {},
      { ends: true });

    const body = [
      '{% test %}',
      '  content'
    ].join('\n');

    return tag.render(body)
      .then(result => {
        console.log(result);
        throw new Error('should return error');
      })
      .catch(err => {
        err.should.have.property('name', 'Template render error');
        err.should.have.property('message');
        expect(err.message).to.contain('unexpected end of file');
      });
  });

  it('no closing tag 2', () => {
    const tag = new Tag();

    tag.register('test',
      (args, content) => {},
      { ends: true });

    const body = [
      '{% test %}',
      '  content',
      '{% test %}'
    ].join('\n');

    return tag.render(body)
      .then(result => {
        console.log(result);
        throw new Error('should return error');
      })
      .catch(err => {
        err.should.have.property('name', 'Template render error');
        err.should.have.property('message');
        expect(err.message).to.contain('unexpected end of file');
      });
  });

  it('curly braces', () => {
    const tag = new Tag();

    const body = [
      '<code>{{docker ps -aq | map docker inspect -f "{{.Name}} {{.Mounts}}"}}</code>'
    ].join('\n');

    return tag.render(body)
      .then(result => {
        console.log(result);
        throw new Error('should return error');
      })
      .catch(err => {
        assertNunjucksError(err, 1, 'expected variable end');
      });
  });

  it('nested curly braces', () => {
    const tag = new Tag();

    tag.register('test',
      (args, content) => {},
      { ends: true });

    const body = [
      '{% test %}',
      '  {{docker ps -aq | map docker inspect -f "{{.Name}} {{.Mounts}}"}}',
      '{% endtest %}'
    ].join('\n');

    return tag.render(body)
      .then(result => {
        console.log(result);
        throw new Error('should return error');
      })
      .catch(err => {
        assertNunjucksError(err, 2, 'expected variable end');
      });
  });

});


v-tab-item(v-for="tab in tabs" :key="tab")

keep keep keep keep keep replace keep keep keep keep keep

<template>

    <prism :language="language">
      <slot />
    </prism>

      <v-icon @click="copyMarkup">content_copy</v-icon>
      <v-slide-x-transition>
        Copied
      </v-slide-x-transition>

</template>


<template lang="pug">
  component-view(v-bind:doc="doc")
    v-alert(color="info" icon="info" value="true" slot="top") If you are looking for Grid lists, please navigate <router-link class="white--text" to="/components/grid-lists">here</router-link>.
    grid(slot="top").mt-5
    v-alert(color="info" icon="info" value).mb-4 Vuetify breakpoint functionality requires the use of the v-app component.
    section-header Breakpoint object
    section-text Vuetify converts the available breakpoints into an accessible object from within your application. This will allow you to assign/apply specific properties and attributes based upon viewport size. The object can be accessed from:
    markup(lang="js")
      |export default {
      |    mounted () {
      |      console.log(this.$vuetify.breakpoint)
      |    },
      |    computed: {
      |      imageHeight () {
      |        switch (this.$vuetify.breakpoint.name) {
      |          case 'xs': return '220px'
      |          case 'sm': return '400px'
      |          case 'md': return '500px'
      |          case 'lg': return '600px'
      |          case 'xl': return '800px'
      |        }
      |      }
      |    }
      |}
    section-text This object contains the same semantic properties that you are already used to using from the grid system. Let's try a real world example. You have a v-dialog component that you want to convert to a full-screen dialog on mobile devices. Normally you would need to bind watchers for the viewport size, and/or check whenever the page loads.
    markup(lang="js")
      |export default {
      |    data: () => ({
      |       isMobile: false
      |    }),
      |    mounted () {
      |      this.$vuetify.load(this.init)
      |    },
      |    beforeDestroy () {
      |      if (typeof window !== 'undefined') {
      |         window.removeEventListener('resize', this.onResize, { passive: true })
      |      }
      |    },
      |    methods: {
      |      init () {
      |         this.onResize()
      |         window.addEventListener('resize', this.onResize, { passive: true })
      |      },
      |      onResize () {
      |         this.isMobile = window.innerWidth < 600
      |      }
      |    }
      |}
    section-text That's a lot of boilerplate to write. Even if you opt to use the built in <router-link to="/directives/resizing">v-resize</router-link> directive, you are still going to have to define a resize method. With the breakpoint object you can completely skip this logic and get back to building your application.
    markup(lang="html")
      |<v-dialog :fullscreen="$vuetify.breakpoint.xsOnly">
      |    ...
      |</v-dialog>
</template>


С помощью экранных помощников вы можете контролировать отображение содержимого. Это включает в себя условное отображение на основе текущего _viewport_ (области просмотра) или фактического типа отображения элемента.

Условно отобразить элемент, основанный на текущем **viewport (области просмотра)**. Эти классы могут быть применены с использованием следующего формата `hidden- {breakpoint} - {condition}`

_Контрольная точка_ устанавливает размер окна просмотра:

`xs` - маленькие устройства
`sm` - небольшие устройства
`md` - средние устройства
`lg` - большие устройства
`xl` - очень большие

_condition_ применяется база классов:

`only` - скрыть элемент только на `xs` через `xl` контрольные точки

`and-down` - скрыть элемент на указанной точке останова и скрыть `sm` через контрольные точки` lg`

`and-up` -скрыть элемент в указанной точке останова и до `sm` через контрольные точки` lg`

Укажите свойство `display`. Эти классы могут быть применены в следующем формате `d- {display}`.

`d-inline-flex` -  устанавливает свойство отображения элемента `inline-flex`

`d-flex` - устанавливает свойство отображения элемента `flex`

`d-inline-block` - устанавливает свойство отображения элемента `inline-block`

`d-block` -  устанавливает свойство отображения элемента `block`

`d-inline` - устанавливает свойство отображения элемента `inline`


<template>
  <v-app id="example-2" toolbar>
    <v-navigation-drawer absolute persistent light :mini-variant.sync="mini" v-model="drawer" overflow>
      <v-toolbar flat class="transparent">
        <v-list class="pa-0">
          <v-list-tile avatar>
            <v-list-tile-avatar>

            </v-list-tile-avatar>
            <v-list-tile-content>
              <v-list-tile-title>John Leider</v-list-tile-title>
            </v-list-tile-content>
            <v-list-tile-action>
              <v-btn icon @click.native.stop="mini = !mini">
                <v-icon>chevron_left</v-icon>
              </v-btn>
            </v-list-tile-action>
          </v-list-tile>
        </v-list>
      </v-toolbar>
      <v-list class="pt-0" dense>
        <v-divider></v-divider>
        <v-list-tile v-for="item in items" :key="item.title" @click="">
          <v-list-tile-action>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-tile-action>
          <v-list-tile-content>
            <v-list-tile-title>{{ item.title }}</v-list-tile-title>
          </v-list-tile-content>
        </v-list-tile>
      </v-list>
    </v-navigation-drawer>
    <v-toolbar fixed class="indigo darken-4" dark>
      <v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
      <v-toolbar-title>Toolbar</v-toolbar-title>
    </v-toolbar>

      <v-container fluid>

Click on sidebar to re-open.

      </v-container>

  </v-app>
</template>


overflow-x: auto
overflow-y: hidden
margin-bottom: 16px
background: #2d2d2d
pre, code
margin: 0

<template lang="pug">
  section.component-example(:id="id")
    //- Section header
    h3(v-if="header.length > 0").title.layout.align-center.mb-3
      translation-translatable(:i18n="header").d-inline-flex.align-center
        span(v-text="$t(header)")
        v-chip(
          v-if="newIn"
          class="white--text font-weight-regular"
          color="red lighten-2"
          small
        )
          span(v-text="$t('Generic.Common.newIn')")
          |
          span(v-text="`v${newIn}`")

    //- Description
    // TODO: make independant of english locale
    translation-translatable(v-if="$te(desc, 'en')" :i18n="desc")
      helpers-markdown(
        v-if="$t(desc)"
        :source="$t(desc)"
      )

    v-card(:class="{ 'elevation-0': readonly }").mt-4
      //- Example options
      v-toolbar(flat dense card v-if="!readonly").pr-1
        v-btn(
          :href="`#${id}`"
          icon
          @click.prevent.stop="goTo"
        )
          v-icon(color="grey darken-1") mdi-pound-box
        v-spacer
        v-tooltip(lazy top v-if="hasInverted")
          v-btn(icon slot="activator" @click="invertedProxy = !invertedProxy")
            v-icon(color="grey darken-1") invert_colors
          span Invert colors
        v-tooltip(lazy top)
          v-btn(
            icon
            tag="a"
            :href="`https://github.com/vuetifyjs/vuetifyjs.com/tree/master/src/examples/${file}.vue`"
            target="_blank"
            slot="activator"
          )
            v-icon(color="grey darken-1") fab fa-github
          span View on Github
        v-tooltip(lazy top)
          v-btn(
            icon
            @click="sendToCodepen"
            slot="activator"
          )
            v-icon(color="grey darken-1") fab fa-codepen
          span Edit in codepen
        v-tooltip(lazy top)
          v-btn(
            icon
            @click.stop="togglePanel"
            slot="activator"
          )
            v-icon(color="grey darken-1") code
          span View source

      //- Example markup
      v-expansion-panel(
        ref="panel"
        v-model="panel"
      ).elevation-0
        v-expansion-panel-content
          v-divider(v-if="!readonly")
          v-tabs(
            ref="tabs"
            color="grey lighten-4"
            v-show="!readonly"
          )
            v-tab(
              v-for="tab in tabs"
              :key="tab"
              v-show="parsed[tab]"
              active-class=""
              class="body-2"
            ) {{ tab }}
            v-tabs-items(class="grey lighten-3")
              v-tab-item(v-for="tab in tabs" :key="tab")
                helpers-markup(:lang="getLang(tab)" v-if="parsed[tab]").ma-0
                  | {{ parsed[tab] }}

      v-divider(v-if="!readonly")

      //- Example mount
      div(data-app :class="exampleClasses").application.application--example.pa-3
        component(:is="component")

    //- Codepen
    helpers-codepen(ref="codepen" :pen="parsed")
</template>

<script>
  import { goTo } from '@/util/helpers'

  const release = process.env.RELEASE

  export default {
    props: {
      active: {
        type: Boolean,
        default: false
      },
      hasInverted: {
        type: Boolean,
        default: false
      },
      file: {
        type: String,
        default: ''
      },
      header: {
        type: String,
        default: ''
      },
      desc: {
        type: String,
        default: ''
      },
      inverted: {
        type: Boolean,
        default: false
      },
      newIn: {
        type: [Boolean, String],
        default: false
      },
      id: {
        type: String,
        default: ''
      },
      readonly: {
        type: Boolean,
        default: false
      }
    },

    data () {
      return {
        tabs: ['template', 'script', 'style'],
        component: null,
        invertedProxy: this.inverted,
        panel: [],
        parsed: {
          script: null,
          style: null,
          template: null,
          codepenDeps: null
        },
        url: release ? `releases/${release}/` : ''
      }
    },

    computed: {
      currentColor () {
        return this.$store.state.currentColor
      },
      exampleClasses () {
        return {
          'theme--dark': this.invertedProxy,
          'theme--light': !this.invertedProxy,
          'grey lighten-3': !this.invertedProxy
        }
      }
    },

    watch: {
      panel () {
        this.$nextTick(this.$refs.tabs.callSlider)
      }
    },

    created () {
      if (this.active || this.readonly) {
        this.panel = []
      }
    },

    mounted () {
      import(
        /* webpackChunkName: "examples" */
        /* webpackMode: "lazy-once" */
        `../../examples/${this.file}.vue`
      ).then(comp => {
        this.component = comp.default
      })

      import(
        /* webpackChunkName: "examples-source" */
        /* webpackMode: "lazy-once" */
        `!raw-loader!../../examples/${this.file}.vue`
        ).then(comp => this.boot(comp.default))
    },

    methods: {
      getLang (tab) {
        if (tab === 'script') return 'js'
        if (tab === 'style') return 'css'
        return 'vue'
      },
      parseTemplate (target, template) {
        const string = `(<${target}(.*)?>[\\w\\W]*<\\/${target}>)`
        const regex = new RegExp(string, 'g')
        const parsed = regex.exec(template) || []

        return parsed[1] || ''
      },
      boot (res) {
        const template = this.parseTemplate('template', res)
        const script = this.parseTemplate('script', res)
        const style = this.parseTemplate('style', res)
        const codepenResources = this.parseTemplate('codepen-resources', res)
        const codepenAdditional = this.parseTemplate('codepen-additional', res)

        this.parsed = {
          template,
          script,
          style,
          codepenResources,
          codepenAdditional
        }
      },
      goTo () {
        goTo.call(this, `#${this.id}`)
      },
      toggle () {
        this.active = !this.active
      },
      sendToCodepen () {
        this.$refs.codepen.submit()
      },
      togglePanel () {
        const panel = this.$refs.panel.items[0].uid

        this.$refs.panel.panelClick(panel)
      }
    }
  }
</script>

<style lang="stylus">
  @import '~vuetify/src/stylus/settings/_variables.styl'

  #snackbars, #data-tables
    .component-example .application--example
      z-index: auto

  .component-example
    // margin-bottom: 32px

    .application--example
      position: relative
      transition: .3s $transition.swing
      overflow: hidden
      z-index: 0

      > div,
      > form,
      > footer
        width: 100%

    .component-example__panel
      .v-expansion-panel__body
        border: none

      .v-tabs__item, .markup
        height: 100%

      .v-tabs__items
        border: none
        max-height: 500px
        overflow-y: auto

      > li
        border: none

    .justify
      text-align: justify

    aside.v-navigation-drawer,
    .v-overlay
      z-index: 1

    nav.v-toolbar
      z-index: 0
</style>


import Resizing from './Resizing'
import Ripples from './Ripples'
import Scrolling from './Scrolling'
import TouchSupport from './TouchSupport'

export default {
  Resizing,
  Ripples,
  Scrolling,
  TouchSupport
}


import Vue from 'vue'
import { VNodeData } from 'vue/types/vnode'

function isCssColor (color?: string | false): boolean {
  return !!color && !!color.match(/^(#|(rgb|hsl)a?\()/)
}

export default Vue.extend({
  name: 'colorable',

  props: {
    color: String
  },

  methods: {
    setBackgroundColor (color?: string | false, data: VNodeData = {}): VNodeData {
      if (isCssColor(color)) {
        data.style = {
          ...data.style,
          'background-color': `${color}`,
          'border-color': `${color}`
        }
      } else if (color) {
        data.class = {
          ...data.class,
          [color]: true
        }
      }

      return data
    },

    setTextColor (color?: string | false, data: VNodeData = {}): VNodeData {
      if (isCssColor(color)) {
        data.style = {
          ...data.style,
          'color': `${color}`,
          'caret-color': `${color}`
        }
      } else if (color) {
        const [colorName, colorModifier] = color.toString().trim().split(' ', 2) as (string | undefined)[]
        data.class = {
          ...data.class,
          [colorName + '--text']: true
        }
        if (colorModifier) {
          data.class['text--' + colorModifier] = true
        }
      }
      return data
    }
  }
})


&:after
opacity: 0
.v-icon
position: absolute
right: 0
transition: opacity .2s ease-in
font-size: 1.5rem
opacity: 0

keep keep keep add keep keep keep keep keep


const express = require('express')
const simpleGit = require('simple-git/promise')
const diffJson = require('diff-json')
const helpers = require('vuetify/es5/util/helpers')
const fs = require('fs-extra')
const path = require('path')

var router = express.Router()

var git = simpleGit()

function kebab (str) {
  return (str || '').replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
}

function camel (str) {
  const camel = (str || '').replace(/-([^-])/g, g => g[1].toUpperCase())

  return capitalize(camel)
}

function capitalize (str) {
  str = str || ''

  return `${str.substr(0, 1).toUpperCase()}${str.slice(1)}`
}

function getPaths (locale, key) {
  const parts = key.split('.')
  const fileParts = parts.filter(p => p[0] === p[0].toUpperCase())
  const folderParts = fileParts.slice(0, -1).map(kebab).join('/')
  const fileName = fileParts.slice(-1)
  const keyParts = parts.filter(p => p[0] === p[0].toLowerCase())

  return {
    sourcePath: `./lang/en/${folderParts}/${fileName}.json`,
    localePath: `./lang/${locale}/${folderParts}/${fileName}.json`,
    fileKey: keyParts.join('.')
  }
}

function update (obj, path, value) {
  let pointer = obj
  for (let i = 0; i < path.length; i++) {
    const p = path[i]
    const matches = p.match(/(.*)\[(\d+)\](\.)?/)
    const isArray = matches && matches.length > 1

    const key = isArray ? matches[1] : p

    if (pointer[key] === undefined) pointer[key] = isArray ? [] : {}

    if (i === path.length - 1) {
      if (isArray) pointer[key][matches[2]] = value
      else pointer[key] = value
    } else {
      if (isArray) {
        pointer[key][matches[2]] = {}
        pointer = pointer[key][matches[2]]
      } else pointer = pointer[key]
    }
  }

  return obj
}

const cache = {}

function setupCache (path) {
  // setup cache
  if (!cache[path]) {
    cache[path] = {
      logs: null,
      json: {}
    }
  }
}

async function getLog (path, opts = {}) {
  if (cache[path].logs) return cache[path].logs

  const logs = await git.log({ file: path, ...opts })

  cache[path].logs = logs

  return logs
}

async function getJsonContent (path, hash) {
  if (cache[path].json[hash]) return cache[path].json[hash]

  const raw = await git.raw([
    'show',
    `${hash}:./${path}`
  ])

  try {
    const json = JSON.parse(raw)
    cache[path].json[hash] = json
    return json
  } catch (err) {
    return {}
  }
}

function getPreviousCommit (log, commit) {
  const targetDate = new Date(commit.date)
  for (let i = 0; i < log.all.length; i++) {
    const currentDate = new Date(log.all[i].date)

    if (currentDate <= targetDate) return log.all[i]
  }

  return null
}

async function checkStatus (locale, key) {
  const { sourcePath, localePath, fileKey } = getPaths(locale, key)

  setupCache(sourcePath)
  setupCache(localePath)

  // If no file exists yet
  // translation is missing
  if (!fs.existsSync(localePath)) return 'missing'

  // If file exists but no key found
  // then we are missing translation
  const localeJson = await fs.readJson(localePath)
  if (!helpers.getObjectValueByPath(localeJson, fileKey)) return 'missing'

  // Get git logs for both source and locale
  const localeLog = await getLog(localePath)
  const sourceLog = await getLog(sourcePath)

  // If file is not commited, there's not much we can do
  if (localeLog.total === 0) return 'unchanged'

  // If file is newer than latest commit
  // and value is changed then it's new
  const { mtime } = await fs.stat(localePath)
  const modifiedDate = new Date(mtime)
  const commitDate = new Date(localeLog.latest.date)
  if (modifiedDate > commitDate) {
    const commitJson = await getJsonContent(localePath, localeLog.latest.hash)
    if (helpers.getObjectValueByPath(commitJson, fileKey) !== helpers.getObjectValueByPath(localeJson, fileKey)) return 'new'
  }

  const latestSourceCommitDate = new Date(sourceLog.latest.date)
  const latestLocaleCommitDate = new Date(localeLog.latest.date)

  // If source has been updated after latest locale
  // then we might have a mismatch
  if (latestSourceCommitDate > latestLocaleCommitDate) {
    const previousCommit = getPreviousCommit(sourceLog, localeLog.latest)

    if (!previousCommit) throw new Error('asdasdas')

    const oldJson = await getJsonContent(sourcePath, previousCommit.hash)
    const newJson = await getJsonContent(sourcePath, sourceLog.latest.hash)

    const changes = diffJson.diff(oldJson, newJson)
    const change = changes.find(c => c.key === fileKey)

    if (!change) return 'unchanged'

    if (change.type === 'update') return 'updated'
    else if (change.type === 'add') return 'added'
    else if (change.type === 'remove') return 'removed'
    return 'unknown'
  }

  return 'unchanged'
}

async function updateIndexFiles (filePath, root = false) {
  let dir = path.dirname(filePath)

  do {
    const files = (await getAllFiles(dir, true, false)).filter(f => !f.includes('index.js'))

    const exports = files.map(f => path.basename(f).replace(/\.json|\.js/, ''))
    const imports = exports.map(f => `import ${!root ? camel(f) : f} from './${f}'`).join('\n')
    const index = `${imports}\n\nexport ${!root ? 'default ' : ''}{\n${exports.map(e => '  ' + (!root ? camel(e) : e)).join(',\n')}\n}\n`

    await fs.writeFile(`${dir}/index.js`, index)

    if (root) return

    dir = dir.split(path.sep).slice(0, -1).join(path.sep)
  } while (dir.length > 0 && !dir.endsWith('lang'))
}

async function updateTranslation (locale, key, value) {
  const { localePath, fileKey } = getPaths(locale, key)

  if (!fs.existsSync(localePath)) {
    await fs.ensureFile(localePath)
    await fs.writeJson(localePath, {})
  }

  const data = await fs.readJson(localePath)

  update(data, fileKey.split('.'), value)

  await fs.writeJson(localePath, data, { spaces: 2 })

  await updateIndexFiles(localePath)
}

async function getAllFiles (dir, includeDirs = false, recurse = true) {
  return (await fs.readdir(dir)).reduce(async (files, file) => {
    const name = path.join(dir, file)
    const isDirectory = (await fs.stat(name)).isDirectory()

    const f = await files

    // if (isDirectory && includeDirs) f.push(name)

    return isDirectory && recurse ? [...f, ...(await getAllFiles(name))] : [...f, name]
  }, [])
}

async function newTranslation (name, locale, country) {
  const localePath = `./lang/${locale}`

  if (fs.existsSync(localePath)) {
    throw new Error('locale already exists!')
  }

  await fs.ensureDir(localePath)

  const index = `export default {}`

  await fs.writeFile(path.join(localePath, 'index.js'), index)

  const languages = await fs.readJson('./data/i18n/languages.json')

  languages.push({
    name,
    locale,
    country
  })

  await fs.writeJson('./data/i18n/languages.json', languages, { spaces: 2 })

  await updateIndexFiles(localePath, true)
}

router.use(function (req, res, next) {
  if (req.body && req.body.locale) {
    req.body.locale = req.body.locale.replace('-', '')
  }
  if (req.query && req.query.locale) {
    req.query.locale = req.query.locale.replace('-', '')
  }

  next()
})

router.post('/new', async function (req, res) {
  try {
    const { name, locale, country } = req.body

    if (!name || !locale || !country) {
      res.send({ error: 'missing data' })
    }

    await newTranslation(name, locale, country)

    res.send({ status: 'ok' })
  } catch (err) {
    console.log('new', err)
    res.status(500).send({ error: JSON.stringify(err) })
  }
})

router.put('/', async function (req, res) {
  try {
    const { locale, key, value } = req.body

    if (!locale || !key || !value) {
      res.send({ error: 'missing data' })
    }

    await updateTranslation(locale, key, value)

    res.send(update({}, key.split('.'), value))
  } catch (err) {
    console.log('save', err)
    res.status(500).send({ error: JSON.stringify(err) })
  }
})

router.get('/status', async function (req, res) {
  try {
    const { locale, key } = req.query

    const status = await checkStatus(locale, key)

    res.send({ status })
  } catch (err) {
    console.log('status', err)
    res.status(500).send({ error: JSON.stringify(err) })
  }
})

async function run () {
  // console.log(await checkIfOutdated('ko', 'Components.Alerts.examples.closable.desc'))
  // console.log(await checkStatus('ko', 'GettingStarted.QuickStart.header'))
  // console.log(await updateTranslation('ko', 'GettingStarted.SponsorsAndBackers.header', 'new header'))
  // console.log(await newTranslation('Svenska', 'sv', 'se'))
  // let data = update({ GettingStarted: {} }, ['GettingStarted', 'arr[1]'], 'hello')
  // console.log(update(data, ['GettingStarted', 'arr[0]'], 'world'))
  // let data = update({ GettingStarted: {} }, ['GettingStarted', 'arr[1]', 'test'], 'hello')
  // console.log(JSON.stringify(data))
}

run()

module.exports = router


<template>
  <v-navigation-drawer permanent light>
    <v-toolbar flat class="transparent">
      <v-list class="pa-0">
        <v-list-tile avatar>
          <v-list-tile-avatar>
            <img src="https://randomuser.me/api/portraits/men/85.jpg" />
          </v-list-tile-avatar>
          <v-list-tile-content>
            <v-list-tile-title>John Leider</v-list-tile-title>
          </v-list-tile-content>
        </v-list-tile>
      </v-list>
    </v-toolbar>
    <v-list class="pt-0" dense>
      <v-divider></v-divider>
      <v-list-tile v-for="item in items" :key="item.title" @click="">
        <v-list-tile-action>
          <v-icon>{{ item.icon }}</v-icon>
        </v-list-tile-action>
        <v-list-tile-content>
          <v-list-tile-title>{{ item.title }}</v-list-tile-title>
        </v-list-tile-content>
      </v-list-tile>
    </v-list>
  </v-navigation-drawer>
</template>

<script>
  export default {
    data () {
      return {
        items: [
          { title: 'Home', icon: 'dashboard' },
          { title: 'About', icon: 'question_answer' }
        ]
      }
    }
  }
</script>


// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`VExpansionPanel.js should render an expanded component and match snapshot 1`] = `

        header

          keyboard_arrow_down

      content

`;

exports[`VExpansionPanel.js should render an expanded component and match snapshot 2`] = `

        header

          keyboard_arrow_down

      content

`;

exports[`VExpansionPanel.js should render component and match snapshot 1`] = `

        header

          keyboard_arrow_down

      content

`;

exports[`VExpansionPanel.js should render component and match snapshot 2`] = `

        header

          keyboard_arrow_down

      content

`;

exports[`VExpansionPanel.js should show content on v-model change 1`] = `

`;


keep keep keep keep keep replace replace replace replace keep keep keep keep keep

"use strict";

const dedent = require("dedent");
const getPort = require("get-port");
const npa = require("npm-package-arg");
const path = require("path");
const pFinally = require("p-finally");
const pMap = require("p-map");
const pMapSeries = require("p-map-series");
const pWaterfall = require("p-waterfall");

const Command = require("@lerna/command");
const rimrafDir = require("@lerna/rimraf-dir");
const hasNpmVersion = require("@lerna/has-npm-version");
const npmInstall = require("@lerna/npm-install");
const { createRunner } = require("@lerna/run-lifecycle");
const batchPackages = require("@lerna/batch-packages");
const runParallelBatches = require("@lerna/run-parallel-batches");
const symlinkBinary = require("@lerna/symlink-binary");
const symlinkDependencies = require("@lerna/symlink-dependencies");
const ValidationError = require("@lerna/validation-error");
const { getFilteredPackages } = require("@lerna/filter-options");
const PackageGraph = require("@lerna/package-graph");
const pulseTillDone = require("@lerna/pulse-till-done");

const hasDependencyInstalled = require("./lib/has-dependency-installed");
const isHoistedPackage = require("./lib/is-hoisted-package");

module.exports = factory;

function factory(argv) {
  return new BootstrapCommand(argv);
}

class BootstrapCommand extends Command {
  get requiresGit() {
    return false;
  }

  initialize() {
    const { registry, npmClient = "npm", npmClientArgs = [], mutex, hoist, nohoist } = this.options;

    if (npmClient === "yarn" && hoist) {
      throw new ValidationError(
        "EWORKSPACES",
        dedent`
            --hoist is not supported with --npm-client=yarn, use yarn workspaces instead
            A guide is available at https://yarnpkg.com/blog/2017/08/02/introducing-workspaces/
          `
      );
    }

    if (
      npmClient === "yarn" &&
      this.project.manifest.get("workspaces") &&
      this.options.useWorkspaces !== true
    ) {
      throw new ValidationError(
        "EWORKSPACES",
        dedent`
            Yarn workspaces are configured in package.json, but not enabled in lerna.json!
            Please choose one: useWorkspaces = true in lerna.json, or remove package.json workspaces config
          `
      );
    }

    // postinstall and prepare are commonly used to call `lerna bootstrap`,
    // but we need to avoid recursive execution when `--hoist` is enabled
    const { LERNA_EXEC_PATH = "leaf", LERNA_ROOT_PATH = "root" } = process.env;

    if (LERNA_EXEC_PATH === LERNA_ROOT_PATH) {
      this.logger.warn("bootstrap", "Skipping recursive execution");

      return false;
    }

    if (hoist) {
      let hoisting;

      if (hoist === true) {
        // lerna.json `hoist: true`
        hoisting = ["**"];
      } else {
        // `--hoist ...` or lerna.json `hoist: [...]`
        hoisting = [].concat(hoist);
      }

      if (nohoist) {
        if (!Array.isArray(nohoist)) {
          // `--nohoist` single
          hoisting = hoisting.concat(`!${nohoist}`);
        } else {
          // `--nohoist` multiple or lerna.json `nohoist: [...]`
          hoisting = hoisting.concat(nohoist.map(str => `!${str}`));
        }
      }

      this.logger.verbose("hoist", "using globs %j", hoisting);
      this.hoisting = hoisting;
    }

    this.runPackageLifecycle = createRunner({ registry });
    this.npmConfig = {
      registry,
      npmClient,
      npmClientArgs,
      mutex,
    };

    if (npmClient === "npm" && this.options.ci && hasNpmVersion(">=5.7.0")) {
      // never `npm ci` when hoisting
      this.npmConfig.subCommand = this.hoisting ? "install" : "ci";

      if (this.hoisting) {
        // don't mutate lockfiles in CI
        this.npmConfig.npmClientArgs.unshift("--no-save");
      }
    }

    // lerna bootstrap ... -- <input>
    const doubleDashArgs = this.options["--"] || [];
    if (doubleDashArgs.length) {
      this.npmConfig.npmClientArgs = [...npmClientArgs, ...doubleDashArgs];
    }

    // do not run any lifecycle scripts (if configured)
    if (this.options.ignoreScripts) {
      this.npmConfig.npmClientArgs.unshift("--ignore-scripts");
    }

    this.targetGraph = this.options.forceLocal
      ? new PackageGraph(this.packageGraph.rawPackageList, "allDependencies", "forceLocal")
      : this.packageGraph;

    let chain = Promise.resolve();

    chain = chain.then(() => {
      if (this.options.scope) {
        this.logger.notice("filter", "including %j", this.options.scope);
      }

      if (this.options.ignore) {
        this.logger.notice("filter", "excluding %j", this.options.ignore);
      }

      if (this.options.since) {
        this.logger.notice("filter", "changed since %j", this.options.since);
      }

      if (this.options.includeFilteredDependents) {
        this.logger.notice("filter", "including filtered dependents");
      }

      if (this.options.includeFilteredDependencies) {
        this.logger.notice("filter", "including filtered dependencies");
      }

      return getFilteredPackages(this.targetGraph, this.execOpts, this.options);
    });

    chain = chain.then(filteredPackages => {
      this.filteredPackages = filteredPackages;

      if (filteredPackages.length !== this.targetGraph.size && !this.options.forceLocal) {
        this.logger.warn("bootstrap", "Installing local packages that do not match filters from registry");

        // an explicit --scope, --ignore, or --since should only symlink the targeted packages, no others
        this.targetGraph = new PackageGraph(filteredPackages, "allDependencies", this.options.forceLocal);

        // never automatically --save or modify lockfiles
        this.npmConfig.npmClientArgs.unshift(npmClient === "yarn" ? "--pure-lockfile" : "--no-save");

        // never attempt `npm ci`, it would always fail
        if (this.npmConfig.subCommand === "ci") {
          this.npmConfig.subCommand = "install";
        }
      }
    });

    chain = chain.then(() => {
      this.batchedPackages = this.toposort
        ? batchPackages(this.filteredPackages, this.options.rejectCycles)
        : [this.filteredPackages];

      if (npmClient === "yarn" && !mutex) {
        return getPort({ port: 42424, host: "0.0.0.0" }).then(port => {
          this.npmConfig.mutex = `network:${port}`;
          this.logger.silly("npmConfig", this.npmConfig);
        });
      }

      this.logger.silly("npmConfig", this.npmConfig);
    });

    return chain;
  }

  execute() {
    if (this.options.useWorkspaces || this.rootHasLocalFileDependencies()) {
      return this.installRootPackageOnly();
    }

    const filteredLength = this.filteredPackages.length;
    const packageCountLabel = `${filteredLength} package${filteredLength > 1 ? "s" : ""}`;
    const scriptsEnabled = this.options.ignoreScripts !== true;

    // root install does not need progress bar
    this.enableProgressBar();
    this.logger.info("", `Bootstrapping ${packageCountLabel}`);

    // conditional task queue
    const tasks = [];

    if (scriptsEnabled) {
      tasks.push(() => this.runLifecycleInPackages("preinstall"));
    }

    tasks.push(
      () => this.getDependenciesToInstall(),
      result => this.installExternalDependencies(result),
      () => this.symlinkPackages()
    );

    if (scriptsEnabled) {
      tasks.push(
        () => this.runLifecycleInPackages("install"),
        () => this.runLifecycleInPackages("postinstall")
      );

      if (!this.options.ignorePrepublish) {
        tasks.push(() => this.runLifecycleInPackages("prepublish"));
      }

      // "run on local npm install without any arguments", AFTER prepublish
      tasks.push(() => this.runLifecycleInPackages("prepare"));
    }

    return pWaterfall(tasks).then(() => {
      this.logger.success("", `Bootstrapped ${packageCountLabel}`);
    });
  }

  installRootPackageOnly() {
    this.logger.info("bootstrap", "root only");

    // don't hide yarn or npm output
    this.npmConfig.stdio = "inherit";

    return npmInstall(this.project.manifest, this.npmConfig);
  }

  /**
   * If the root manifest has local dependencies with `file:` specifiers,
   * all the complicated bootstrap logic should be skipped in favor of
   * npm5's package-locked auto-hoisting.
   * @returns {Boolean}
   */
  rootHasLocalFileDependencies() {
    const rootDependencies = Object.assign({}, this.project.manifest.dependencies);

    return Object.keys(rootDependencies).some(
      name =>
        this.targetGraph.has(name) &&
        npa.resolve(name, rootDependencies[name], this.project.rootPath).type === "directory"
    );
  }

  runLifecycleInPackages(stage) {
    this.logger.verbose("lifecycle", stage);

    if (!this.filteredPackages.length) {
      return;
    }

    const tracker = this.logger.newItem(stage);

    const mapPackageWithScript = pkg =>
      this.runPackageLifecycle(pkg, stage).then(() => {
        tracker.completeWork(1);
      });

    tracker.addWork(this.filteredPackages.length);

    return pFinally(runParallelBatches(this.batchedPackages, this.concurrency, mapPackageWithScript), () =>
      tracker.finish()
    );
  }

  hoistedDirectory(dependency) {
    return path.join(this.project.rootPath, "node_modules", dependency);
  }

  hoistedPackageJson(dependency) {
    try {
      // eslint-disable-next-line import/no-dynamic-require, global-require
      return require(path.join(this.hoistedDirectory(dependency), "package.json"));
    } catch (e) {
      // Pass.
      return {};
    }
  }

  /**
   * Return a object of root and leaf dependencies to install
   * @returns {Object}
   */
  getDependenciesToInstall() {
    // Configuration for what packages to hoist may be in lerna.json or it may
    // come in as command line options.
    const rootPkg = this.project.manifest;

    // This will contain entries for each hoistable dependency.
    const rootSet = new Set();

    // This will map packages to lists of unhoistable dependencies
    const leaves = new Map();

    /**
     * Map of dependencies to install
     *
     * Map {
     *   "<externalName>": Map {
     *     "<versionRange>": Set { "<dependent1>", "<dependent2>", ... }
     *   }
     * }
     *
     * Example:
     *
     * Map {
     *   "react": Map {
     *     "15.x": Set { "my-component1", "my-component2", "my-component3" },
     *     "^0.14.0": Set { "my-component4" },
     *   }
     * }
     */
    const depsToInstall = new Map();
    const filteredNodes = new Map(
      this.filteredPackages.map(pkg => [pkg.name, this.targetGraph.get(pkg.name)])
    );

    // collect root dependency versions
    const mergedRootDeps = Object.assign(
      {},
      rootPkg.devDependencies,
      rootPkg.optionalDependencies,
      rootPkg.dependencies
    );
    const rootExternalVersions = new Map(
      Object.keys(mergedRootDeps).map(externalName => [externalName, mergedRootDeps[externalName]])
    );

    // seed the root dependencies
    rootExternalVersions.forEach((version, externalName) => {
      const externalDependents = new Set();
      const record = new Map();

      record.set(version, externalDependents);
      depsToInstall.set(externalName, record);
    });

    // build a map of external dependencies to install
    for (const [leafName, leafNode] of filteredNodes) {
      for (const [externalName, resolved] of leafNode.externalDependencies) {
        // rawSpec is something like "^1.2.3"
        const version = resolved.rawSpec;
        const record =
          depsToInstall.get(externalName) || depsToInstall.set(externalName, new Map()).get(externalName);
        const externalDependents = record.get(version) || record.set(version, new Set()).get(version);

        externalDependents.add(leafName);
      }
    }

    const rootActions = [];
    const leafActions = [];
    // We don't want to exit on the first hoist issue, but log them all and then exit
    let strictExitOnWarning = false;

    // determine where each dependency will be installed
    for (const [externalName, externalDependents] of depsToInstall) {
      let rootVersion;

      if (this.hoisting && isHoistedPackage(externalName, this.hoisting)) {
        const commonVersion = Array.from(externalDependents.keys()).reduce((a, b) =>
          externalDependents.get(a).size > externalDependents.get(b).size ? a : b
        );

        // Get the version required by the repo root (if any).
        // If the root doesn't have a dependency on this package then we'll
        // install the most common dependency there.
        rootVersion = rootExternalVersions.get(externalName) || commonVersion;

        if (rootVersion !== commonVersion) {
          this.logger.warn(
            "EHOIST_ROOT_VERSION",
            `The repository root depends on ${externalName}@${rootVersion}, ` +
              `which differs from the more common ${externalName}@${commonVersion}.`
          );
          if (this.options.strict) {
            strictExitOnWarning = true;
          }
        }

        const dependents = Array.from(externalDependents.get(rootVersion)).map(
          leafName => this.targetGraph.get(leafName).pkg
        );

        // remove collection so leaves don't repeat it
        externalDependents.delete(rootVersion);

        // Install the best version we can in the repo root.
        // Even if it's already installed there we still need to make sure any
        // binaries are linked to the packages that depend on them.
        rootActions.push(() =>
          hasDependencyInstalled(rootPkg, externalName, rootVersion).then(isSatisfied => {
            rootSet.add({
              name: externalName,
              dependents,
              dependency: `${externalName}@${rootVersion}`,
              isSatisfied,
            });
          })
        );
      }

      // Add less common versions to package installs.
      for (const [leafVersion, leafDependents] of externalDependents) {
        for (const leafName of leafDependents) {
          if (rootVersion) {
            this.logger.warn(
              "EHOIST_PKG_VERSION",
              `"${leafName}" package depends on ${externalName}@${leafVersion}, ` +
                `which differs from the hoisted ${externalName}@${rootVersion}.`
            );
            if (this.options.strict) {
              strictExitOnWarning = true;
            }
          }

          const leafNode = this.targetGraph.get(leafName);
          const leafRecord = leaves.get(leafNode) || leaves.set(leafNode, new Set()).get(leafNode);

          // only install dependency if it's not already installed
          leafActions.push(() =>
            hasDependencyInstalled(leafNode.pkg, externalName, leafVersion).then(isSatisfied => {
              leafRecord.add({
                dependency: `${externalName}@${leafVersion}`,
                isSatisfied,
              });
            })
          );
        }
      }
    }
    if (this.options.strict && strictExitOnWarning) {
      throw new ValidationError(
        "EHOISTSTRICT",
        "Package version inconsistencies found while hoisting. Fix the above warnings and retry."
      );
    }

    return pMapSeries([...rootActions, ...leafActions], el => el()).then(() => {
      this.logger.silly("root dependencies", JSON.stringify(rootSet, null, 2));
      this.logger.silly("leaf dependencies", JSON.stringify(leaves, null, 2));

      return { rootSet, leaves };
    });
  }

  /**
   * Install external dependencies for all packages
   * @returns {Promise}
   */
  installExternalDependencies({ leaves, rootSet }) {
    const tracker = this.logger.newItem("install dependencies");
    const rootPkg = this.project.manifest;
    const actions = [];

    // Start root install first, if any, since it's likely to take the longest.
    if (rootSet.size) {
      // If we have anything to install in the root then we'll install
      // _everything_ that needs to go there.  This is important for
      // consistent behavior across npm clients.
      const root = Array.from(rootSet);

      actions.push(() => {
        const depsToInstallInRoot = root.some(({ isSatisfied }) => !isSatisfied)
          ? root.map(({ dependency }) => dependency)
          : [];

        if (depsToInstallInRoot.length) {
          tracker.info("hoist", "Installing hoisted dependencies into root");
        }

        const promise = npmInstall.dependencies(rootPkg, depsToInstallInRoot, this.npmConfig);

        return pulseTillDone(promise)
          .then(() =>
            // Link binaries into dependent packages so npm scripts will
            // have access to them.
            pMapSeries(root, ({ name, dependents }) => {
              const { bin } = this.hoistedPackageJson(name);

              if (bin) {
                return pMap(dependents, pkg => {
                  const src = this.hoistedDirectory(name);

                  return symlinkBinary(src, pkg);
                });
              }
            })
          )
          .then(() => {
            tracker.info("hoist", "Finished bootstrapping root");
            tracker.completeWork(1);
          });
      });

      // Remove any hoisted dependencies that may have previously been
      // installed in package directories.
      actions.push(() => {
        // Compute the list of candidate directories synchronously
        const candidates = root
          .filter(dep => dep.dependents.length)
          .reduce((list, { name, dependents }) => {
            const dirs = dependents
              .filter(pkg => pkg.nodeModulesLocation !== rootPkg.nodeModulesLocation)
              .map(pkg => path.join(pkg.nodeModulesLocation, name));

            return list.concat(dirs);
          }, []);

        if (!candidates.length) {
          tracker.verbose("hoist", "nothing to prune");
          tracker.completeWork(1); // the action "work"

          return;
        }

        tracker.info("hoist", "Pruning hoisted dependencies");
        tracker.silly("prune", candidates);
        tracker.addWork(candidates.length);

        return pMap(
          candidates,
          dirPath =>
            pulseTillDone(rimrafDir(dirPath)).then(() => {
              tracker.verbose("prune", dirPath);
              tracker.completeWork(1);
            }),
          // these are mostly no-ops in the vast majority of cases
          { concurrency: this.concurrency }
        ).then(() => {
          tracker.info("hoist", "Finished pruning hoisted dependencies");
          tracker.completeWork(1); // the action "work"
        });
      });
    }

    const leafNpmConfig = Object.assign({}, this.npmConfig, {
      // Use `npm install --global-style` for leaves when hoisting is enabled
      npmGlobalStyle: !!this.options.hoist,
    });

    // Install anything that needs to go into the leaves.
    leaves.forEach((leafRecord, leafNode) => {
      const deps = Array.from(leafRecord);

      // If we have any unsatisfied deps then we need to install everything.
      // This is important for consistent behavior across npm clients.
      if (deps.some(({ isSatisfied }) => !isSatisfied)) {
        actions.push(() => {
          const dependencies = deps.map(({ dependency }) => dependency);
          const promise = npmInstall.dependencies(leafNode.pkg, dependencies, leafNpmConfig);

          return pulseTillDone(promise).then(() => {
            tracker.verbose("installed leaf", leafNode.name);
            tracker.completeWork(1);
          });
        });
      }
    });

    if (actions.length) {
      tracker.info("", "Installing external dependencies");
      tracker.verbose("actions", "%d actions, concurrency %d", actions.length, this.concurrency);
      tracker.addWork(actions.length);
    }

    return pFinally(pMap(actions, act => act(), { concurrency: this.concurrency }), () => tracker.finish());
  }

  /**
   * Symlink all packages to the packages/node_modules directory
   * Symlink package binaries to dependent packages' node_modules/.bin directory
   * @returns {Promise}
   */
  symlinkPackages() {
    return symlinkDependencies(
      this.filteredPackages,
      this.targetGraph,
      this.logger.newItem("bootstrap dependencies")
    );
  }
}

module.exports.BootstrapCommand = BootstrapCommand;


/* eslint-disable class-methods-use-this */

"use strict";

const fs = require("fs-extra");
const log = require("npmlog");
const path = require("path");
const tempy = require("tempy");

// partially mocked
const ChildProcessUtilities = require("@lerna/child-process");
const os = require("os");

// normalize concurrency across different environments (localhost, CI, etc)
jest.spyOn(os, "cpus").mockImplementation(() => new Array(42));

// helpers
const initFixture = require("@lerna-test/init-fixture")(__dirname);
const loggingOutput = require("@lerna-test/logging-output");
const updateLernaConfig = require("@lerna-test/update-lerna-config");

// file under test
const Command = require("..");

describe("core-command", () => {
  let testDir;

  beforeAll(async () => {
    testDir = await initFixture("basic");
  });

  afterEach(() => {
    // ensure common CWD is restored when individual tests
    // initialize their own fixture (which changes CWD)
    if (process.cwd() !== testDir) {
      process.chdir(testDir);
    }
  });

  ChildProcessUtilities.getChildProcessCount = jest.fn(() => 0);

  // swallow errors when passed in argv
  const onRejected = () => {};

  class OkCommand extends Command {
    initialize() {
      return true;
    }

    execute() {}
  }

  // convenience to avoid silly "not implemented errors"
  const testFactory = (argv = {}) => new OkCommand(Object.assign({ cwd: testDir }, argv));

  describe(".logger", () => {
    it("should be added to the instance", async () => {
      const command = testFactory();
      await command;

      expect(command.logger).toBeDefined();
    });
  });

  describe(".concurrency", () => {
    it("should be added to the instance", async () => {
      const command = testFactory({ concurrency: 6 });
      await command;

      expect(command.concurrency).toBe(6);
    });

    it("should fall back to default if concurrency given is NaN", async () => {
      const command = testFactory({ concurrency: "bla" });
      await command;

      expect(command.concurrency).toBe(42);
    });

    it("should fall back to default if concurrency given is 0", async () => {
      const command = testFactory({ concurrency: 0 });
      await command;

      expect(command.concurrency).toBe(42);
    });

    it("should fall back to 1 if concurrency given is smaller than 1", async () => {
      const command = testFactory({ concurrency: -1 });
      await command;

      expect(command.concurrency).toBe(1);
    });
  });

  describe(".toposort", () => {
    it("is enabled by default", async () => {
      const command = testFactory();
      await command;

      expect(command.toposort).toBe(true);
    });

    it("is disabled when sort config is explicitly false (--no-sort)", async () => {
      const command = testFactory({ sort: false });
      await command;

      expect(command.toposort).toBe(false);
    });
  });

  describe(".execOpts", () => {
    const ONE_HUNDRED_MEGABYTES = 1000 * 1000 * 100;

    it("has maxBuffer", async () => {
      const command = testFactory({ maxBuffer: ONE_HUNDRED_MEGABYTES });
      await command;

      expect(command.execOpts.maxBuffer).toBe(ONE_HUNDRED_MEGABYTES);
    });

    it("has repo path", async () => {
      const command = testFactory();
      await command;

      expect(command.execOpts.cwd).toBe(testDir);
    });
  });

  it("returns a Promise", async () => {
    await testFactory();
  });

  describe("when finished", () => {
    it("resolves immediately when no child processes active", async () => {
      await testFactory();

      const logMessages = loggingOutput("warn");
      expect(logMessages).toHaveLength(0);
    });

    it("waits to resolve when 1 child process active", async () => {
      ChildProcessUtilities.getChildProcessCount.mockReturnValueOnce(1);

      await testFactory();

      const [logMessage] = loggingOutput("warn");
      expect(logMessage).toMatch("Waiting for 1 child process to exit.");
    });

    it("waits to resolve when 2 child processes active", async () => {
      ChildProcessUtilities.getChildProcessCount.mockReturnValueOnce(2);

      await testFactory();

      const [logMessage] = loggingOutput("warn");
      expect(logMessage).toMatch("Waiting for 2 child processes to exit.");
    });
  });

  describe("with package error", () => {
    const originalConsoleError = console.error;

    beforeEach(() => {
      console.error = jest.fn();
    });
    afterEach(() => {
      console.error = originalConsoleError;
    });

    it("logs stdout and stderr of error from package", async () => {
      class PkgErrorCommand extends Command {
        initialize() {
          return true;
        }

        execute() {
          const err = new Error("message");

          err.cmd = "test-pkg-err";
          err.stdout = "pkg-err-stdout";
          err.stderr = "pkg-err-stderr";
          err.pkg = {
            name: "pkg-err-name",
          };

          throw err;
        }
      }

      try {
        await new PkgErrorCommand({ cwd: testDir });
      } catch (err) {
        expect(console.error.mock.calls).toHaveLength(2);
        expect(console.error.mock.calls[0]).toEqual(["pkg-err-stdout"]);
        expect(console.error.mock.calls[1]).toEqual(["pkg-err-stderr"]);

        expect(err.cmd).toEqual("test-pkg-err");
        expect(err.stdout).toEqual("pkg-err-stdout");
        expect(err.stderr).toEqual("pkg-err-stderr");
        expect(err.pkg).toEqual({
          name: "pkg-err-name",
        });
      }
    });

    it("does not log stdout/stderr after streaming ends", async () => {
      class PkgErrorCommand extends Command {
        initialize() {
          return true;
        }

        execute() {
          const err = new Error("message");

          err.cmd = "test-pkg-err";
          err.stdout = "pkg-err-stdout";
          err.stderr = "pkg-err-stderr";
          err.pkg = {
            name: "pkg-err-name",
          };

          throw err;
        }
      }

      try {
        await new PkgErrorCommand({ cwd: testDir, stream: true });
      } catch (err) {
        expect(console.error.mock.calls).toHaveLength(0);
      }
    });
  });

  describe("loglevel", () => {
    afterEach(() => {
      log.level = "silent";
    });

    it("is set from lerna.json config", async () => {
      const cwd = await initFixture("basic");

      await updateLernaConfig(cwd, { loglevel: "warn" });
      await testFactory({ cwd, onRejected });

      expect(log.level).toBe("warn");
    });
  });

  describe(".packageGraph", () => {
    it("returns the graph of packages", async () => {
      const command = testFactory();
      await command;

      expect(command.packageGraph).toBeInstanceOf(Map);
    });
  });

  describe(".options", () => {
    class TestACommand extends Command {}
    class TestBCommand extends Command {}
    class TestCCommand extends Command {
      get otherCommandConfigs() {
        return ["testb"];
      }
    }

    it("should pick up global options", async () => {
      const instance = new TestACommand({ cwd: testDir, onRejected });
      await instance;

      expect(instance.options.testOption).toBe("default");
    });

    it("should override global options with command-level options", async () => {
      const instance = new TestBCommand({ cwd: testDir, onRejected });
      await instance;

      expect(instance.options.testOption).toBe("b");
    });

    it("should override global options with inherited command-level options", async () => {
      const instance = new TestCCommand({ cwd: testDir, onRejected });
      await instance;

      expect(instance.options.testOption).toBe("b");
    });

    it("should override inherited command-level options with local command-level options", async () => {
      const instance = new TestCCommand({ cwd: testDir, onRejected });
      await instance;

      expect(instance.options.testOption2).toBe("c");
    });

    it("should override everything with a CLI flag", async () => {
      const instance = new TestCCommand({
        cwd: testDir,
        onRejected,
        testOption2: "f",
      });
      await instance;

      expect(instance.options.testOption2).toBe("f");
    });

    it("should inherit durable options when a CLI flag is undefined", async () => {
      const instance = new TestCCommand({
        cwd: testDir,
        onRejected,
        testOption: undefined, // yargs does this when --test-option is not passed
      });
      await instance;

      expect(instance.options.testOption).toBe("b");
    });
  });

  describe("subclass implementation", () => {
    ["initialize", "execute"].forEach(method => {
      it(`throws if ${method}() is not overridden`, () => {
        const command = new Command({ cwd: testDir, onRejected });
        expect(() => command[method]()).toThrow();
      });
    });
  });

  describe("validations", () => {
    it("throws ENOGIT when repository is not initialized", async () => {
      expect.assertions(1);

      const cwd = tempy.directory();

      try {
        await testFactory({ cwd });
      } catch (err) {
        expect(err.prefix).toBe("ENOGIT");
      }
    });

    it("throws ENOPKG when root package.json is not found", async () => {
      expect.assertions(1);

      const cwd = await initFixture("basic");

      await fs.remove(path.join(cwd, "package.json"));

      try {
        await testFactory({ cwd });
      } catch (err) {
        expect(err.prefix).toBe("ENOPKG");
      }
    });

    it("throws JSONError when root package.json has syntax error", async () => {
      expect.assertions(1);

      const cwd = await initFixture("basic");

      await fs.writeFile(
        path.join(cwd, "package.json"), // trailing comma ...v
        '{ "name": "invalid", "lerna": { "version": "1.0.0" }, }'
      );

      try {
        await testFactory({ cwd });
      } catch (err) {
        expect(err.prefix).toBe("JSONError");
      }
    });

    it("throws ENOLERNA when lerna.json is not found", async () => {
      expect.assertions(1);

      const cwd = await initFixture("basic");

      await fs.remove(path.join(cwd, "lerna.json"));

      try {
        await testFactory({ cwd });
      } catch (err) {
        expect(err.prefix).toBe("ENOLERNA");
      }
    });
  });
});


keep keep keep keep replace keep keep keep keep


keep keep keep keep keep replace replace replace replace replace replace replace keep keep keep

@lerna/bootstrap

Link local packages together and install remaining package dependencies


@lerna/validation-error

An internal Lerna tool


margin-bottom: 10px;
}
}
& a .file-name {
display: block;
padding: 10px 5px;

.rooms-list {
	position: relative;
	overflow-y: scroll;

	height: 100%;

	&__list {
		&:not(:last-child) {
			margin-bottom: 32px;
		}
	}

	&__type {
		display: flex;

		flex-direction: row;

		padding: 0 var(--sidebar-default-padding) 0.5rem var(--sidebar-default-padding);

		color: var(--rooms-list-title-color);

		font-size: var(--rooms-list-title-text-size);
		align-items: center;

		&-text--livechat {
			flex: 1;
		}
	}

	&__empty-room {
		padding: 0 var(--sidebar-default-padding);

		color: var(--rooms-list-empty-text-color);

		font-size: var(--rooms-list-empty-text-size);
	}

	& .badge {
		margin: 0 4px;
	}

	&__toolbar-search {
		position: absolute;
		z-index: 1;

		bottom: var(--sidebar-footer-height);
		left: 0;

		overflow-y: auto;

		width: 100%;
		padding: 0 8px;

		background-color: var(--sidebar-background);
	}
}

@media (width <= 400px) {
	padding: 0 calc(var(--sidebar-small-default-padding) - 4px);

	.rooms-list {
		&__type,
		&__empty-room {
			padding: 0 calc(var(--sidebar-small-default-padding) - 4px) 0.5rem calc(var(--sidebar-small-default-padding) - 4px);
		}

		&__toolbar-search {
			bottom: 0;

			padding: 0 var(--sidebar-small-default-padding)  var(--sidebar-small-default-padding)  var(--sidebar-small-default-padding);
		}
	}
}


this.LivechatCustomField = new Mongo.Collection('rocketchat_livechat_custom_field');


RocketChat.Migrations.add({
	version: 55,
	up() {
		RocketChat.models.Rooms.find({ 'topic': { $exists: 1, $ne: '' } }, { topic: 1 }).forEach(function(room) {
			const topic = s.escapeHTML(room.topic);
			RocketChat.models.Rooms.update({ _id: room._id }, { $set: { topic }});
			RocketChat.models.Messages.update({ t: 'room_changed_topic', rid: room._id }, { $set: { msg: topic }});
		});
	}
});


Package.describe({
	name: 'rocketchat:videobridge',
	version: '0.2.0',
	summary: 'jitsi integration',
	git: ''
});

Package.onUse(function(api) {
	api.use([
		'ecmascript',
		'underscore',
		'less',
		'rocketchat:lib'
	]);

	api.use('templating', 'client');

	api.addAssets('client/public/external_api.js', 'client');

	api.addFiles('client/stylesheets/video.less', 'client');
	api.addFiles('client/views/videoFlexTab.html', 'client');
	api.addFiles('client/views/videoFlexTab.js', 'client');
	api.addFiles('client/tabBar.js', 'client');
	api.addFiles('client/actionLink.js', 'client');

	//Need to register the messageType with both the server and client
	api.addFiles('lib/messageType.js', ['client', 'server']);

	api.addFiles('server/settings.js', 'server');
	api.addFiles('server/models/Rooms.js', 'server');
	api.addFiles('server/methods/jitsiSetTimeout.js', 'server');
	api.addFiles('server/actionLink.js', 'server');
});


keep keep keep keep replace keep keep keep

accounts-base@1.4.2
accounts-facebook@1.3.1
accounts-github@1.4.1
accounts-google@1.3.1
accounts-meteor-developer@1.4.1
accounts-oauth@1.1.15
accounts-password@1.5.1
accounts-twitter@1.4.1
aldeed:simple-schema@1.5.4
allow-deny@1.1.0
autoupdate@1.4.0
babel-compiler@7.0.9
babel-runtime@1.2.2
base64@1.0.11
binary-heap@1.0.10
blaze@2.3.2
blaze-html-templates@1.1.2
blaze-tools@1.0.10
boilerplate-generator@1.4.0
caching-compiler@1.1.12
caching-html-compiler@1.1.2
callback-hook@1.1.0
cfs:http-methods@0.0.32
chatpal:search@0.0.1
check@1.3.1
coffeescript@1.0.17
dandv:caret-position@2.1.1
ddp@1.4.0
ddp-client@2.3.2
ddp-common@1.4.0
ddp-rate-limiter@1.0.7
ddp-server@2.1.2
deepwell:bootstrap-datepicker2@1.3.0
deps@1.0.12
diff-sequence@1.1.0
dispatch:run-as-user@1.1.1
dynamic-import@0.3.0
ecmascript@0.10.9
ecmascript-runtime@0.5.0
ecmascript-runtime-client@0.6.2
ecmascript-runtime-server@0.5.0
edgee:slingshot@0.7.1
ejson@1.1.0
email@1.2.3
emojione:emojione@2.2.6
es5-shim@4.7.3
facebook-oauth@1.4.1
fastclick@1.0.13
francocatena:status@1.5.3
geojson-utils@1.0.10
github-oauth@1.2.0
google-oauth@1.2.5
hot-code-push@1.0.4
html-tools@1.0.11
htmljs@1.0.11
http@1.4.1
id-map@1.1.0
jalik:ufs@0.7.5
jalik:ufs-gridfs@0.2.1
jalik:ufs-local@0.2.9
jparker:crypto-core@0.1.0
jparker:crypto-md5@0.1.1
jparker:gravatar@0.5.1
jquery@1.11.11
kadira:blaze-layout@2.3.0
kadira:flow-router@2.12.1
keepnox:perfect-scrollbar@0.6.8
kenton:accounts-sandstorm@0.7.0
konecty:change-case@2.3.0
konecty:delayed-task@1.0.0
konecty:mongo-counter@0.0.5_3
konecty:multiple-instances-status@1.1.0
konecty:user-presence@2.1.0
launch-screen@1.1.1
less@2.7.12
livedata@1.0.18
localstorage@1.2.0
logging@1.1.20
matb33:collection-hooks@0.8.4
mdg:validation-error@0.5.1
meteor@1.8.6
meteor-base@1.3.0
meteor-developer-oauth@1.2.0
meteorhacks:inject-initial@1.0.4
meteorhacks:meteorx@1.4.1
meteorspark:util@0.2.0
minifier-css@1.3.1
minifier-js@2.3.5
minimongo@1.4.4
mizzao:autocomplete@0.5.1
mizzao:timesync@0.3.4
mobile-experience@1.0.5
mobile-status-bar@1.0.14
modules@0.11.8
modules-runtime@0.9.2
mongo@1.4.7
mongo-dev-server@1.1.0
mongo-id@1.0.7
mongo-livedata@1.0.12
mrt:reactive-store@0.0.1
mystor:device-detection@0.2.0
nimble:restivus@0.8.12
nooitaf:colors@1.1.2_1
npm-bcrypt@0.9.3
npm-mongo@2.2.34
oauth@1.2.3
oauth1@1.2.0
oauth2@1.2.0
observe-sequence@1.0.16
ordered-dict@1.1.0
ostrio:cookies@2.2.4
pauli:accounts-linkedin@2.1.5
pauli:linkedin-oauth@1.2.0
percolate:synced-cron@1.3.2
promise@0.10.2
raix:eventemitter@0.1.3
raix:eventstate@0.0.4
raix:handlebar-helpers@0.2.5
rocketchat:push@3.3.1
raix:ui-dropped-event@0.0.7
random@1.1.0
rate-limit@1.0.9
reactive-dict@1.2.0
reactive-var@1.0.11
reload@1.2.0
retry@1.1.0
rocketchat:2fa@0.0.1
rocketchat:accounts@0.0.1
rocketchat:action-links@0.0.1
rocketchat:analytics@0.0.2
rocketchat:api@0.0.1
rocketchat:apps@1.0.0
rocketchat:assets@0.0.1
rocketchat:authorization@0.0.1
rocketchat:autolinker@0.0.1
rocketchat:autotranslate@0.0.1
rocketchat:bot-helpers@0.0.1
rocketchat:cas@1.0.0
rocketchat:channel-settings@0.0.1
rocketchat:channel-settings-mail-messages@0.0.1
rocketchat:colors@0.0.1
rocketchat:cors@0.0.1
rocketchat:crowd@1.0.0
rocketchat:custom-oauth@1.0.0
rocketchat:custom-sounds@1.0.0
rocketchat:dolphin@0.0.2
rocketchat:drupal@0.0.1
rocketchat:emoji@1.0.0
rocketchat:emoji-custom@1.0.0
rocketchat:emoji-emojione@0.0.1
rocketchat:error-handler@1.0.0
rocketchat:favico@0.0.1
rocketchat:file@0.0.1
rocketchat:file-upload@0.0.1
rocketchat:github-enterprise@0.0.1
rocketchat:gitlab@0.0.1
rocketchat:google-vision@0.0.1
rocketchat:grant@0.0.1
rocketchat:grant-facebook@0.0.1
rocketchat:grant-github@0.0.1
rocketchat:grant-google@0.0.1
rocketchat:graphql@0.0.1
rocketchat:highlight-words@0.0.1
rocketchat:i18n@0.0.1
rocketchat:iframe-login@1.0.0
rocketchat:importer@0.0.1
rocketchat:importer-csv@1.0.0
rocketchat:importer-hipchat@0.0.1
rocketchat:importer-hipchat-enterprise@1.0.0
rocketchat:importer-slack@0.0.1
rocketchat:importer-slack-users@1.0.0
rocketchat:integrations@0.0.1
rocketchat:internal-hubot@0.0.1
rocketchat:irc@0.0.1
rocketchat:issuelinks@0.0.1
rocketchat:katex@0.0.1
rocketchat:lazy-load@0.0.1
rocketchat:ldap@0.0.1
rocketchat:lib@0.0.1
rocketchat:livechat@0.0.1
rocketchat:livestream@0.0.5
rocketchat:logger@0.0.1
rocketchat:login-token@1.0.0
rocketchat:mailer@0.0.1
rocketchat:mapview@0.0.1
rocketchat:markdown@0.0.2
rocketchat:mentions@0.0.1
rocketchat:mentions-flextab@0.0.1
rocketchat:message-attachments@0.0.1
rocketchat:message-mark-as-unread@0.0.1
rocketchat:message-pin@0.0.1
rocketchat:message-snippet@0.0.1
rocketchat:message-star@0.0.1
rocketchat:migrations@0.0.1
rocketchat:monitoring@2.30.2_3
rocketchat:nrr@1.0.0
rocketchat:oauth2-server@2.0.0
rocketchat:oauth2-server-config@1.0.0
rocketchat:oembed@0.0.1
rocketchat:otr@0.0.1
rocketchat:postcss@1.0.0
rocketchat:push-notifications@0.0.1
rocketchat:reactions@0.0.1
rocketchat:retention-policy@0.0.1
rocketchat:sandstorm@0.0.1
rocketchat:search@0.0.1
rocketchat:setup-wizard@0.0.1
rocketchat:slackbridge@0.0.1
rocketchat:slashcommands-archive@0.0.1
rocketchat:slashcommands-asciiarts@0.0.1
rocketchat:slashcommands-create@0.0.1
rocketchat:slashcommands-help@0.0.1
rocketchat:slashcommands-hide@0.0.1
rocketchat:slashcommands-invite@0.0.1
rocketchat:slashcommands-invite-all@0.0.1
rocketchat:slashcommands-join@0.0.1
rocketchat:slashcommands-kick@0.0.1
rocketchat:slashcommands-leave@0.0.1
rocketchat:slashcommands-me@0.0.1
rocketchat:slashcommands-msg@0.0.1
rocketchat:slashcommands-mute@0.0.1
rocketchat:slashcommands-open@0.0.1
rocketchat:slashcommands-topic@0.0.1
rocketchat:slashcommands-unarchive@0.0.1
rocketchat:slider@0.0.1
rocketchat:smarsh-connector@0.0.1
rocketchat:sms@0.0.1
rocketchat:spotify@0.0.1
rocketchat:statistics@0.0.1
rocketchat:streamer@0.6.2
rocketchat:theme@0.0.1
rocketchat:tokenpass@0.0.1
rocketchat:tooltip@0.0.1
rocketchat:tutum@0.0.1
rocketchat:ui@0.1.0
rocketchat:ui-account@0.1.0
rocketchat:ui-admin@0.1.0
rocketchat:ui-clean-history@0.0.1
rocketchat:ui-flextab@0.1.0
rocketchat:ui-login@0.1.0
rocketchat:ui-master@0.1.0
rocketchat:ui-message@0.1.0
rocketchat:ui-sidenav@0.1.0
rocketchat:ui-vrecord@0.0.1
rocketchat:user-data-download@1.0.0
rocketchat:version@1.0.0
rocketchat:version-check@0.0.1
rocketchat:videobridge@0.2.0
rocketchat:webrtc@0.0.1
rocketchat:wordpress@0.0.1
routepolicy@1.0.13
server-render@0.3.1
service-configuration@1.0.11
session@1.1.7
sha@1.0.9
shell-server@0.3.1
shim-common@0.1.0
simple:json-routes@2.1.0
socket-stream-client@0.1.0
spacebars@1.0.15
spacebars-compiler@1.1.3
srp@1.0.10
standard-minifier-js@2.3.4
steffo:meteor-accounts-saml@0.0.1
swydo:graphql@0.4.0
tap:i18n@1.8.2
templating@1.3.2
templating-compiler@1.3.3
templating-runtime@1.3.2
templating-tools@1.1.2
todda00:friendly-slugs@0.6.0
tracker@1.1.3
twitter-oauth@1.2.0
ui@1.0.13
underscore@1.0.10
url@1.2.0
webapp@1.5.0
webapp-hashing@1.0.9
yasaricli:slugify@0.0.7
yasinuslu:blaze-meta@0.3.3


Template.loginLayout.onRendered(function() {
	$('#initial-page-loading').remove();
});

Template.loginLayout.helpers({
	backgroundUrl() {
		const asset = RocketChat.settings.get('Assets_background');
		const prefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '';
		if (asset && (asset.url || asset.defaultUrl)) {
			return `${ prefix }/${ asset.url || asset.defaultUrl }`;
		}
	}
});


import s from 'underscore.string';

import { RocketChatTabBar } from 'meteor/rocketchat:lib';

Template.adminSounds.helpers({
	isReady() {
		if (Template.instance().ready != null) {
			return Template.instance().ready.get();
		}
		return undefined;
	},
	customsounds() {
		return Template.instance().customsounds();
	},
	isLoading() {
		if (Template.instance().ready != null) {
			if (!Template.instance().ready.get()) {
				return 'btn-loading';
			}
		}
	},
	hasMore() {
		if (Template.instance().limit != null) {
			if (typeof Template.instance().customsounds === 'function') {
				return Template.instance().limit.get() === Template.instance().customsounds().length;
			}
		}
		return false;
	},
	flexData() {
		return {
			tabBar: Template.instance().tabBar,
			data: Template.instance().tabBarData.get()
		};
	}
});

Template.adminSounds.onCreated(function() {
	const instance = this;
	this.limit = new ReactiveVar(50);
	this.filter = new ReactiveVar('');
	this.ready = new ReactiveVar(false);

	this.tabBar = new RocketChatTabBar();
	this.tabBar.showGroup(FlowRouter.current().route.name);
	this.tabBarData = new ReactiveVar();

	RocketChat.TabBar.addButton({
		groups: ['custom-sounds', 'custom-sounds-selected'],
		id: 'add-sound',
		i18nTitle: 'Custom_Sound_Add',
		icon: 'plus',
		template: 'adminSoundEdit',
		openClick(/*e, t*/) {
			instance.tabBarData.set();
			return true;
		},
		order: 1
	});

	RocketChat.TabBar.addButton({
		groups: ['custom-sounds-selected'],
		id: 'admin-sound-info',
		i18nTitle: 'Custom_Sound_Info',
		icon: 'customize',
		template: 'adminSoundInfo',
		order: 2
	});

	this.autorun(function() {
		const limit = (instance.limit != null) ? instance.limit.get() : 0;
		const subscription = instance.subscribe('customSounds', '', limit);
		instance.ready.set(subscription.ready());
	});

	this.customsounds = function() {
		const filter = (instance.filter != null) ? s.trim(instance.filter.get()) : '';

		let query = {};

		if (filter) {
			const filterReg = new RegExp(s.escapeRegExp(filter), 'i');
			query = { name: filterReg };
		}

		const limit = (instance.limit != null) ? instance.limit.get() : 0;

		return RocketChat.models.CustomSounds.find(query, { limit, sort: { name: 1 }}).fetch();
	};
});

Template.adminSounds.onRendered(() =>
	Tracker.afterFlush(function() {
		SideNav.setFlex('adminFlex');
		SideNav.openFlex();
	})
);

Template.adminSounds.events({
	'keydown #sound-filter'(e) {
		//stop enter key
		if (e.which === 13) {
			e.stopPropagation();
			e.preventDefault();
		}
	},

	'keyup #sound-filter'(e, t) {
		e.stopPropagation();
		e.preventDefault();
		t.filter.set(e.currentTarget.value);
	},

	'click .sound-info'(e, instance) {
		e.preventDefault();
		instance.tabBarData.set(RocketChat.models.CustomSounds.findOne({_id: this._id}));
		instance.tabBar.showGroup('custom-sounds-selected');
		instance.tabBar.open('admin-sound-info');
	},

	'click .load-more'(e, t) {
		e.preventDefault();
		e.stopPropagation();
		t.limit.set(t.limit.get() + 50);
	},

	'click .icon-play-circled'(e) {
		e.preventDefault();
		e.stopPropagation();
		const $audio = $(`audio#${ this._id }`);
		if ($audio && $audio[0] && $audio[0].play) {
			$audio[0].play();
		}
	}
});


/* globals RocketChatFileCustomSoundsInstance */
Meteor.methods({
	uploadCustomSound(binaryContent, contentType, soundData) {
		if (!RocketChat.authz.hasPermission(this.userId, 'manage-sounds')) {
			throw new Meteor.Error('not_authorized');
		}

		const file = new Buffer(binaryContent, 'binary');

		const rs = RocketChatFile.bufferToStream(file);
		RocketChatFileCustomSoundsInstance.deleteFile(`${ soundData._id }.${ soundData.extension }`);
		const ws = RocketChatFileCustomSoundsInstance.createWriteStream(`${ soundData._id }.${ soundData.extension }`, contentType);
		ws.on('end', Meteor.bindEnvironment(() =>
			Meteor.setTimeout(() => RocketChat.Notifications.notifyAll('updateCustomSound', {soundData}), 500)
		));

		rs.pipe(ws);
	}
});


import s from 'underscore.string';

let usernameBlackList = [];

const toRegExp = username => new RegExp(`^${ s.escapeRegExp(username).trim() }$`, 'i');

RocketChat.settings.get('Accounts_BlockedUsernameList', (key, value) => {
	usernameBlackList = value.split(',').map(toRegExp);
});

const usernameIsBlocked = (username, usernameBlackList) => usernameBlackList.length
	&& usernameBlackList.some(restrictedUsername => restrictedUsername.test(s.trim(s.escapeRegExp(username))));

RocketChat.checkUsernameAvailability = function(username) {

	if (usernameIsBlocked(username, usernameBlackList)) {
		return false;
	}

	return !Meteor.users.findOne({
		username: {
			$regex: toRegExp(username)
		}
	}, { fields: { _id: 1 } });
};


RocketChat.Migrations.add({
	version: 28,
	up() {
		return RocketChat.models.Permissions.addRole('view-c-room', 'bot');
	}
});


RocketChat.models.Users.disable2FAAndSetTempSecretByUserId = function(userId, tempToken) {
	return this.update({
		_id: userId
	}, {
		$set: {
			'services.totp': {
				enabled: false,
				tempSecret: tempToken
			}
		}
	});
};

RocketChat.models.Users.enable2FAAndSetSecretAndCodesByUserId = function(userId, secret, backupCodes) {
	return this.update({
		_id: userId
	}, {
		$set: {
			'services.totp.enabled': true,
			'services.totp.secret': secret,
			'services.totp.hashedBackup': backupCodes
		},
		$unset: {
			'services.totp.tempSecret': 1
		}
	});
};

RocketChat.models.Users.disable2FAByUserId = function(userId) {
	return this.update({
		_id: userId
	}, {
		$set: {
			'services.totp': {
				enabled: false
			}
		}
	});
};

RocketChat.models.Users.update2FABackupCodesByUserId = function(userId, backupCodes) {
	return this.update({
		_id: userId
	}, {
		$set: {
			'services.totp.hashedBackup': backupCodes
		}
	});
};


//! moment.js locale configuration
//! locale : English (Ireland) [en-ie]
//! author : Chris Cartlidge : https://github.com/chriscartlidge

;(function (global, factory) {
   typeof exports === 'object' && typeof module !== 'undefined'
       && typeof require === 'function' ? factory(require('../moment')) :
   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
   factory(global.moment)
}(this, function (moment) { 'use strict';

    var en_ie = moment.defineLocale('en-ie', {
        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
        longDateFormat : {
            LT : 'HH:mm',
            LTS : 'HH:mm:ss',
            L : 'DD-MM-YYYY',
            LL : 'D MMMM YYYY',
            LLL : 'D MMMM YYYY HH:mm',
            LLLL : 'dddd D MMMM YYYY HH:mm'
        },
        calendar : {
            sameDay : '[Today at] LT',
            nextDay : '[Tomorrow at] LT',
            nextWeek : 'dddd [at] LT',
            lastDay : '[Yesterday at] LT',
            lastWeek : '[Last] dddd [at] LT',
            sameElse : 'L'
        },
        relativeTime : {
            future : 'in %s',
            past : '%s ago',
            s : 'a few seconds',
            m : 'a minute',
            mm : '%d minutes',
            h : 'an hour',
            hh : '%d hours',
            d : 'a day',
            dd : '%d days',
            M : 'a month',
            MM : '%d months',
            y : 'a year',
            yy : '%d years'
        },
        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
        ordinal : function (number) {
            var b = number % 10,
                output = (~~(number % 100 / 10) === 1) ? 'th' :
                (b === 1) ? 'st' :
                (b === 2) ? 'nd' :
                (b === 3) ? 'rd' : 'th';
            return number + output;
        },
        week : {
            dow : 1, // Monday is the first day of the week.
            doy : 4  // The week that contains Jan 4th is the first week of the year.
        }
    });

    return en_ie;

}));


/* globals InstanceStatus, UserPresence, UserPresenceMonitor */

Meteor.startup(function() {
	const instance = {
		host: 'localhost',
		port: String(process.env.PORT).trim()
	};

	if (process.env.INSTANCE_IP) {
		instance.host = String(process.env.INSTANCE_IP).trim();
	}

	InstanceStatus.registerInstance('rocket.chat', instance);

	UserPresence.start();

	return UserPresenceMonitor.start();
});


{
"name": "Rocket.Chat",
"version": "0.68.0-develop",
"lockfileVersion": 1,
"requires": true,
"dependencies": {


.rc-input {
	position: relative;

	width: 100%;

	&__label {
		cursor: pointer;
	}

	&__title {
		font-size: var(--input-font-size);
	}

	&__wrapper {
		position: relative;

		padding: 0.5rem 0;

		color: var(--input-icon-color);
	}

	&__icon {
		position: absolute;
		top: 0;
		left: 1rem;

		display: flex;

		width: 20px;
		height: 100%;

		cursor: default;
		align-items: center;
		justify-content: center;

		& + .rc-input__element {
			padding: 0.75rem 1rem 0.75rem 2.75rem;
		}

		& + .rc-input__element--small {
			padding: 0.5rem 1rem 0.5rem 2.75rem;
		}

		&--right {
			right: 1rem;
			left: auto;
		}
	}

	&__element {
		width: 100%;
		padding: 0.75rem 1rem;

		color: var(--input-text-color);

		border-width: var(--input-border-width);
		border-color: var(--input-border-color);
		border-radius: var(--input-border-radius);
		background-color: transparent;

		font-size: var(--input-font-size);

		&--small {
			padding: 0.5rem 1rem;
		}

		&::placeholder {
			color: var(--input-placeholder-color);
		}

		&[type=color] {
			height: 45px;
		}
	}

	&__description {
		margin-bottom: 0.25rem;

		color: var(--input-description-text-color);

		font-size: var(--input-description-text-size);
	}

	&__error {
		display: flex;

		color: var(--input-error-color);
		align-items: center;

		&-icon {
			width: 20px;

			&--warning {
				width: 20px;
				height: 20px;
				stroke: currentColor;
			}
		}

		&-message {
			margin-left: 0.5rem;
		}
	}

	&--small {
		font-size: 14px;

		& .rc-input__element {
			padding-top: 8px;
			padding-bottom: 8px;
		}
	}

	&--error {
		.rc-tags {
			border-color: var(--input-error-color);
		}
		& .rc-input {
			&__element {
				border-color: var(--input-error-color);
			}
		}
	}
}

.rc-input-file {
	position: relative;

	width: 100%;

	&__label {
		cursor: pointer;
	}

	&__title {
		font-size: var(--input-font-size);
	}

	&__wrapper {
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: flex-end;

		width: 100%;
		padding: 0.3rem;
		margin: .5rem 0;

		color: var(--input-text-color);

		border-width: var(--input-border-width);
		border-color: var(--input-border-color);
		border-radius: var(--input-border-radius);
		background-color: transparent;

		font-size: var(--input-font-size);

		&::placeholder {
			color: var(--input-placeholder-color);
		}

		& > .rc-button {
			height: 10px;
			flex: 0 0 auto;
			min-height: 31px;
			border-color: #E1E5E8;
			background: #F1F1F1;
			border-radius: 2px;
			margin: 0;
			padding: 8px;
		}
	}

	&__name {
		white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 0 1 auto;
    padding: 0 5px;
		width: 100%;
		line-height: 16px;
	}

	&__element {
		display: none;
	}

	&__description {
		font-size: 0.875rem;
		color: var(--color-gray);
	}
}

select.rc-input {
	padding: 0.782rem;
	margin: 0.5rem 0;
	appearance: none;

	width: 100%;

	color: var(--input-text-color);

	border-width: var(--input-border-width);
	border-color: var(--input-border-color);
	border-radius: var(--input-border-radius);
	background-color: transparent;

	font-size: var(--input-font-size);

	&--small {
		padding: 0.5rem 1rem;
	}
}


Meteor.methods({
	'livechat:removeCustomField'(_id) {
		if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'view-livechat-manager')) {
			throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'livechat:removeCustomField' });
		}

		check(_id, String);

		const customField = RocketChat.models.LivechatCustomField.findOneById(_id, { fields: { _id: 1 } });

		if (!customField) {
			throw new Meteor.Error('error-invalid-custom-field', 'Custom field not found', { method: 'livechat:removeCustomField' });
		}

		return RocketChat.models.LivechatCustomField.removeById(_id);
	}
});


Package.describe({
	name: 'rocketchat:slashcommands-invite',
	version: '0.0.1',
	summary: 'Message pre-processor that will translate /me commands',
	git: ''
});

Package.onUse(function(api) {
	api.use([
		'ecmascript',
		'check',
		'rocketchat:lib'
	]);

	api.use('templating', 'client');

	api.addFiles('client/client.js', 'client');
	api.addFiles('server/server.js', 'server');
});


* Jest matchers for figgy-pudding instances

*    expect.extend(require("@lerna-test/figgy-pudding-matchers"))

keep keep keep keep add keep keep keep keep keep

const { equals } = require("expect/build/jasmine_utils");

@lerna-test/figgy-pudding-matchers

A local test helper


@lerna/init

Create a new Lerna repo or upgrade an existing repo to the current version of Lerna


"use strict";

const fs = require("fs-extra");
const path = require("path");
const pMap = require("p-map");
const readPkg = require("read-pkg");

const Package = require("@lerna/package");
const createSymlink = require("@lerna/create-symlink");

module.exports = symlinkBinary;

/**
 * Symlink bins of srcPackage to node_modules/.bin in destPackage
 * @param {Object|string} srcPackageRef
 * @param {Object|string} destPackageRef
 * @returns {Promise}
 */
function symlinkBinary(srcPackageRef, destPackageRef) {
  return Promise.all([resolvePackageRef(srcPackageRef), resolvePackageRef(destPackageRef)]).then(
    ([srcPackage, destPackage]) => {
      const actions = Object.keys(srcPackage.bin).map(name => {
        const src = path.join(srcPackage.location, srcPackage.bin[name]);
        const dst = path.join(destPackage.binLocation, name);

        return fs.pathExists(src).then(exists => {
          if (exists) {
            return { src, dst };
          }
        });
      });

      if (actions.length === 0) {
        return Promise.resolve();
      }

      return fs.mkdirp(destPackage.binLocation).then(() =>
        pMap(actions, meta => {
          if (meta) {
            return createSymlink(meta.src, meta.dst, "exec").then(() => fs.chmod(meta.src, "755"));
          }
        })
      );
    }
  );
}

function resolvePackageRef(pkgRef) {
  // don't use instanceof because it fails across nested module boundaries
  if (typeof pkgRef !== "string" && pkgRef.location) {
    return pkgRef;
  }

  return readPkg(pkgRef, { normalize: false }).then(json => new Package(json, pkgRef));
}


# `@lerna/check-working-tree`

> Check git working tree status and error appropriately

## Usage

```js
const checkWorkingTree = require('@lerna/check-working-tree');

// values listed here are their defaults
const options = {
  cwd: process.cwd(),
};

(async () => {
  try {
    await checkWorkingTree(options);
  } catch (err) {
    console.error(err.message);
    // "Working tree has uncommitted changes, ..."
  }
})();
```


"private": true,
"license": "MIT",
"dependencies": {
"jest-diff": "*",
"jest-matcher-utils": "*"
}

@lerna-test/figgy-pudding-matchers

A local test helper


lerna-monorepo

lerna dog-fooding lerna

npm test -- --ci --maxWorkers=2 && npm run integration -- --ci

jest --config jest.integration.js --maxWorkers=2

eslint . --ignore-path .gitignore --cache


# `@lerna/has-npm-version`

> Test if the current version of npm satisfies a given semver range

## Usage

```js
const hasNpmVersion = require('@lerna/has-npm-version');

// `npm --version` === 6.3.0
hasNpmVersion(">=6"); // => true

// `npm --version` === 5.6.0
hasNpmVersion(">=6"); // => false

// makePredicate() caches the call to `npm --version`
// useful if you're calling it repeatedly in a loop
const predicate = hasNpmVersion.makePredicate();

// `npm --version` === 6.3.0
hasNpmVersion(">=5"); // => true
```