tileLength: 0,
window: {},
absoluteX: 0,
absoluteY: 0,
insideContent: false
}
},
props: {

keep keep keep keep replace keep keep keep keep

insideContent: false,
hasJustFocused: false,
focusedTimeout: {}

export default {
  methods: {
    getActivator () {
      if (this.activator) return this.activator
      return this.$refs.activator.children
        ? this.$refs.activator.children[0]
        : this.$refs.activator
    },
    activatorClickHandler (e) {
      if (!this.closeOnClick) e.stopPropagation()
      if (this.disabled) return
      else if (this.openOnClick && !this.isActive) {
        this.isActive = true
        this.absoluteX = e.clientX
        this.absoluteY = e.clientY
      } else if (this.closeOnClick && this.isActive) this.isActive = false
    },
    mouseEnterHandler (e) {
      if (this.disabled) return
      this.isActive = true
    },
    mouseLeaveHandler (e) {
      if (this.insideContent) return
      this.isActive = false
    }
  }
}


import { createSimpleFunctional } from '../../util/helpers'
import App from './App'

const AppBar = createSimpleFunctional('app__bar')

export default {
  App,
  AppBar
}


.footer
  align-items: center
  display: flex
  height: $footer-height
  transition: .3s $transition.swing

  &--absolute, &--fixed
    bottom: 0
    left: 0
    width: 100%
    z-index: 3

  &--absolute
    position: absolute

  &--fixed
    position: fixed

  > *:first-child
    margin-left: $grid-gutter

  > *:last-child
    margin-right: $grid-gutter

  @media $display-breakpoints.xs-only
    > *:first-child
      margin-left: $grid-gutter-mobile

    > *:last-child
      margin-right: $grid-gutter-mobile


.divider
  border: none
  display: block
  height: 1px
  flex: 1
  width: 100%

  &--inset
    margin-left: 72px
    width: calc(100% - 72px)


this.focusedTimeout = setTimeout(() => (this.hasJustFocused = false), 600)

import Activator from './mixins/activator'
import Generators from './mixins/generators'
import Position from './mixins/position'
import Utils from './mixins/utils'
import Toggleable from '../../mixins/toggleable'
import Keyable from './mixins/keyable'

export default {
  name: 'menu',

  mixins: [Activator, Generators, Keyable, Position, Utils, Toggleable],

  data () {
    return {
      app: null,
      autoIndex: null,
      dimensions: {
        activator: {
          top: 0, left: 0,
          bottom: 0, right: 0,
          width: 0, height: 0,
          offsetTop: 0, scrollHeight: 0
        },
        content: {
          top: 0, left: 0,
          bottom: 0, right: 0,
          width: 0, height: 0,
          offsetTop: 0, scrollHeight: 0
        },
        list: null,
        selected: null
      },
      direction: { vert: 'bottom', horiz: 'right' },
      isContentActive: false,
      isBooted: false,
      maxHeightAutoDefault: '200px',
      resizeTimeout: {},
      startIndex: 3,
      stopIndex: 0,
      tileLength: 0,
      window: {},
      absoluteX: 0,
      absoluteY: 0,
      insideContent: false
    }
  },

  props: {
    top: Boolean,
    left: Boolean,
    bottom: Boolean,
    right: Boolean,
    auto: Boolean,
    offsetX: Boolean,
    offsetY: Boolean,
    disabled: Boolean,
    maxHeight: {
      default: 'auto'
    },
    nudgeTop: {
      type: Number,
      default: 0
    },
    nudgeBottom: {
      type: Number,
      default: 0
    },
    nudgeLeft: {
      type: Number,
      default: 0
    },
    nudgeRight: {
      type: Number,
      default: 0
    },
    nudgeWidth: {
      type: Number,
      default: 0
    },
    openOnClick: {
      type: Boolean,
      default: true
    },
    openOnHover: {
      type: Boolean,
      default: false
    },
    lazy: Boolean,
    closeOnClick: {
      type: Boolean,
      default: true
    },
    closeOnContentClick: {
      type: Boolean,
      default: true
    },
    origin: {
      type: String,
      default: 'top left'
    },
    transition: {
      type: String,
      default: 'v-menu-transition'
    },
    positionX: {
      type: Number,
      default: null
    },
    positionY: {
      type: Number,
      default: null
    },
    positionAbsolutely: {
      type: Boolean,
      default: false
    }
  },

  computed: {
    minWidth () {
      return this.dimensions.activator.width + this.nudgeWidth + (this.auto ? 16 : 0)
    },
    styles () {
      return {
        maxHeight: this.auto ? '200px' : isNaN(this.maxHeight) ? this.maxHeight : `${this.maxHeight}px`,
        minWidth: `${this.minWidth}px`,
        top: `${this.calcTop()}px`,
        left: `${this.calcLeft()}px`
      }
    },
    hasActivator () {
      return !!this.$refs.activator
    }
  },

  watch: {
    activator (newActivator, oldActivator) {
      this.removeActivatorEvents(oldActivator)
      this.addActivatorEvents(newActivator)
    },
    disabled (val) {
      val && this.deactivate()
    },
    isActive (val) {
      if (this.disabled) return

      val && this.activate() || this.deactivate()
    },
    windowResizeHandler () {
      this.isBooted = false
    }
  },

  mounted () {
    window.addEventListener('resize', this.onResize, { passive: true })
    this.app = document.querySelector('[data-app]')
    this.$nextTick(() => {
      this.app && this.app.appendChild(this.$refs.content)
    })
  },

  beforeDestroy () {
    window.removeEventListener('resize', this.onResize, { passive: true })
    this.app &&
      this.app.contains(this.$refs.content) &&
      this.app.removeChild(this.$refs.content)

    window.removeEventListener('resize', this.windowResizeHandler)
  },

  methods: {
    activate () {
      this.insideContent = true
      this.initWindow()
      this.getTiles()
      this.updateDimensions()
      this.$nextTick(this.startTransition)
    },
    deactivate () {
      this.isContentActive = false
    },
    onResize () {
      clearTimeout(this.resizeTimeout)
      if (!this.isActive) return
      this.resizeTimeout = setTimeout(this.updateDimensions, 200)
    },
    startTransition () {
      this.isContentActive = true
      this.$nextTick(this.calculateScroll)
    }
  },

  render (h) {
    const directives = !this.openOnHover ? [{
      name: 'click-outside',
      value: () => this.closeOnClick
    }] : []

    const data = {
      'class': 'menu',
      directives,
      on: {
        keydown: e => {
          if (e.keyCode === 27) this.isActive = false
          else this.changeListIndex(e)
        }
      }
    }

    return h('div', data, [
      this.genActivator(),
      this.genTransition()
    ])
  }
}


import Input from '../../mixins/input'

export default {
  name: 'text-field',

  mixins: [Input],

  data () {
    return {
      hasFocused: false,
      inputHeight: null
    }
  },

  props: {
    autofocus: Boolean,
    autoGrow: Boolean,
    counter: Boolean,
    fullWidth: Boolean,
    id: String,
    name: String,
    maxlength: [Number, String],
    max: [Number, String],
    min: [Number, String],
    step: [Number, String],
    multiLine: Boolean,
    prefix: String,
    readonly: Boolean,
    rows: {
      default: 5
    },
    singleLine: Boolean,
    suffix: String,
    type: {
      type: String,
      default: 'text'
    }
  },

  computed: {
    classes () {
      return {
        'input-group--text-field': true,
        'input-group--single-line': this.singleLine,
        'input-group--multi-line': this.multiLine,
        'input-group--full-width': this.fullWidth
      }
    },
    hasError () {
      return this.errors.length !== 0 ||
        !this.counterIsValid() ||
        !this.validateIsValid()
    },
    count () {
      const inputLength = (this.inputValue && this.inputValue.toString() || '').length
      let min = inputLength

      if (this.counterMin !== 0 && inputLength < this.counterMin) {
        min = this.counterMin
      }

      return `${min} / ${this.counterMax}`
    },
    counterMin () {
      const parsedMin = Number.parseInt(this.min, 10)
      return Number.isNaN(parsedMin) ? 0 : parsedMin
    },
    counterMax () {
      const parsedMax = Number.parseInt(this.max, 10)
      return Number.isNaN(parsedMax) ? 25 : parsedMax
    },
    inputValue: {
      get () {
        return this.value
      },
      set (val) {
        if (this.modifiers.trim) {
          val = val.trim()
        }

        if (this.modifiers.number) {
          val = Number(val)
        }

        if (!this.modifiers.lazy) {
          this.$emit('input', val)
        }

        this.lazyValue = val
      }
    },
    isDirty () {
      return this.lazyValue !== null &&
        typeof this.lazyValue !== 'undefined' &&
        this.lazyValue.toString().length > 0
    }
  },

  watch: {
    focused (val) {
      this.hasFocused = true

      !val && this.$emit('change', this.lazyValue)
    },
    value () {
      this.lazyValue = this.value
      this.validate()
      this.multiLine && this.autoGrow && this.calculateInputHeight()
    }
  },

  mounted () {
    this.$vuetify.load(() => {
      this.multiLine && this.autoGrow && this.calculateInputHeight()
      this.autofocus && this.focus()
    })
  },

  methods: {
    calculateInputHeight () {
      const height = this.$refs.input.scrollHeight
      const minHeight = this.rows * 24
      this.inputHeight = height < minHeight ? minHeight : height
    },
    onInput (e) {
      this.inputValue = e.target.value
      this.multiLine && this.autoGrow && this.calculateInputHeight()
    },
    blur (e) {
      this.validate()
      this.$nextTick(() => (this.focused = false))
      this.$emit('blur', e)
    },
    focus (e) {
      this.focused = true
      this.$refs.input.focus()
      this.$emit('focus', e)
    },
    genCounter () {
      return this.$createElement('div', {
        'class': {
          'input-group__counter': true,
          'input-group__counter--error': !this.counterIsValid()
        }
      }, this.count)
    },
    genInput () {
      const tag = this.multiLine ? 'textarea' : 'input'

      const data = {
        style: {
          'height': this.inputHeight && `${this.inputHeight}px`
        },
        domProps: {
          disabled: this.disabled,
          required: this.required,
          value: this.lazyValue,
          autofucus: this.autofocus
        },
        attrs: {
          tabindex: this.tabindex,
          readonly: this.readonly
        },
        on: {
          blur: this.blur,
          input: this.onInput,
          focus: this.focus
        },
        ref: 'input'
      }

      if (this.placeholder) data.domProps.placeholder = this.placeholder
      if (this.autocomplete) data.domProps.autocomplete = true
      if (this.name) data.attrs.name = this.name
      if (this.maxlength) data.attrs.maxlength = this.maxlength
      if (this.id) data.domProps.id = this.id
      if (this.step) data.attrs.step = this.step
      if (!this.counter) {
        if (this.max) data.attrs.max = this.max
        if (this.min) data.attrs.min = this.min
      }

      if (this.multiLine) {
        data.domProps.rows = this.rows
      } else {
        data.domProps.type = this.type
      }

      const children = [this.$createElement(tag, data)]

      this.prefix && children.unshift(this.genFix('prefix'))
      this.suffix && children.push(this.genFix('suffix'))

      return children
    },
    genFix (type) {
      return this.$createElement('span', {
        'class': `input-group--text-field__${type}`
      }, this[type])
    },
    counterIsValid: function counterIsValid () {
      const val = (this.inputValue && this.inputValue.toString() || '')

      return (!this.counter ||
        (val.length >= this.counterMin && val.length <= this.counterMax)
      )
    },
    validateIsValid () {
      return (!this.required ||
        (this.required &&
          this.isDirty) ||
        !this.hasFocused ||
        (this.hasFocused && this.focused))
    }
  },

  render () {
    return this.genInputGroup(this.genInput(), { attrs: { tabindex: -1 }})
  }
}


function style (el, value) {
  [
    'transform',
    'webkitTransform'
  ].forEach(i => {
    el.style[i] = value
  })
}

const ripple = {
  show: (e, el, { value = {}}) => {
    var container = document.createElement('span')
    var animation = document.createElement('span')

    container.appendChild(animation)
    container.className = 'ripple__container'

    if (value.class) {
      container.className += ` ${value.class}`
    }

    const size = el.clientWidth > el.clientHeight ? el.clientWidth : el.clientHeight
    animation.className = 'ripple__animation'
    animation.style.width = `${size * (value.center ? 1 : 2)}px`
    animation.style.height = animation.style.width

    el.appendChild(container)

    const offset = el.getBoundingClientRect()
    const x = value.center ? '50%' : `${e.clientX - offset.left}px`
    const y = value.center ? '50%' : `${e.clientY - offset.top}px`

    animation.classList.add('ripple__animation--enter')
    animation.classList.add('ripple__animation--visible')
    style(animation, `translate(-50%, -50%) translate(${x}, ${y}) scale3d(0.01,0.01,0.01)`)
    animation.dataset.activated = Date.now()

    setTimeout(() => {
      animation.classList.remove('ripple__animation--enter')
      style(animation, `translate(-50%, -50%) translate(${x}, ${y})  scale3d(0.99,0.99,0.99)`)
    }, 0)
  },

  hide: (el) => {
    const ripples = el.getElementsByClassName('ripple__animation')

    if (ripples.length === 0) return
    const animation = ripples[ripples.length - 1]
    const diff = Date.now() - Number(animation.dataset.activated)
    let delay = 400 - diff

    delay = delay < 0 ? 0 : delay

    setTimeout(() => {
      animation.classList.remove('ripple__animation--visible')

      setTimeout(() => {
        // Need to figure out a new way to do this
        try {
          animation.parentNode && el.removeChild(animation.parentNode)
        } catch (e) {}
      }, 300)
    }, delay)
  }
}

function directive (el, binding, v) {
  if (binding.value === false) return

  if ('ontouchstart' in window) {
    el.addEventListener('touchend', () => ripple.hide(el), false)
    el.addEventListener('touchcancel', () => ripple.hide(el), false)
  }

  el.addEventListener('mousedown', e => ripple.show(e, el, binding), false)
  el.addEventListener('mouseup', () => ripple.hide(el), false)
  el.addEventListener('mouseleave', () => ripple.hide(el), false)
}

function unbind (el, binding) {
  el.removeEventListener('touchstart', e => ripple.show(e, el, binding), false)
  el.removeEventListener('mousedown', e => ripple.show(e, el, binding), false)
  el.removeEventListener('touchend', () => ripple.hide(el), false)
  el.removeEventListener('touchcancel', () => ripple.hide(el), false)
  el.removeEventListener('mouseup', () => ripple.hide(el), false)
  el.removeEventListener('mouseleave', () => ripple.hide(el), false)
}

export default {
  bind: directive,
  unbind: unbind
}


export default {
  methods: {
    genMenu () {
      const data = {
        ref: 'menu',
        props: {
          auto: this.auto,
          closeOnClick: false,
          closeOnContentClick: !this.multiple,
          disabled: this.disabled,
          offsetY: this.autocomplete || this.offset,
          maxHeight: this.maxHeight,
          activator: this.$refs.activator,
          value: this.isActive
        },
        on: { input: val => (this.isActive = val) }
      }

      return this.$createElement('v-menu', data, [this.genList()])
    },
    genSelectionsAndSearch () {
      let input

      if (this.autocomplete) {
        input = [this.$createElement('input', {
          'class': 'input-group--select__autocomplete',
          domProps: { value: this.searchValue },
          on: {
            input: e => (this.searchValue = e.target.value),
            keyup: e => {
              if (e.keyCode === 27) {
                this.isActive = false
                e.target.blur()
              }
            }
          },
          ref: 'input',
          key: 'input'
        })]
      }

      const group = this.$createElement('transition-group', {
        props: {
          name: 'fade-transition'
        }
      }, this.isDirty ? this.genSelections() : [])

      return this.$createElement('div', {
        'class': 'input-group__selections',
        style: { 'overflow': 'hidden' },
        ref: 'activator'
      }, [group, input])
    },
    genSelections () {
      const children = []
      const chips = this.chips
      const slots = this.$scopedSlots.selection
      const length = this.selectedItems.length

      this.selectedItems.forEach((item, i) => {
        if (slots) {
          children.push(this.genSlotSelection(item))
        } else if (chips) {
          children.push(this.genChipSelection(item))
        } else {
          children.push(this.genCommaSelection(item, i < length - 1))
        }
      })

      return children
    },
    genSlotSelection (item) {
      return this.$scopedSlots.selection({ parent: this, item })
    },
    genChipSelection (item) {
      return this.$createElement('v-chip', {
        'class': 'chip--select-multi',
        props: { close: true },
        on: { input: () => this.selectItem(item) },
        nativeOn: { click: e => e.stopPropagation() },
        key: item
      }, this.getText(item))
    },
    genCommaSelection (item, comma) {
      return this.$createElement('div', {
        'class': 'input-group__selections__comma',
        key: item
      }, `${this.getText(item)}${comma ? ', ' : ''}`)
    },
    genList () {
      return this.$createElement('v-card', [
        this.$createElement('v-list', {
          ref: 'list'
        }, this.filteredItems.map(o => {
          if (o.header) return this.genHeader(o)
          if (o.divider) return this.genDivider(o)
          else return this.genListItem(o)
        }))
      ])
    },
    genHeader (item) {
      return this.$createElement('v-subheader', {
        props: item
      }, item.header)
    },
    genDivider (item) {
      return this.$createElement('v-divider', {
        props: item
      })
    },
    genListItem (item) {
      return this.$createElement('v-list-item', [this.genTile(item)])
    },
    genTile (item) {
      const active = this.selectedItems.indexOf(item) !== -1
      const data = {
        'class': {
          'list__tile--active': active,
          'list__tile--select-multi': this.multiple
        },
        nativeOn: { click: () => this.selectItem(item) },
        props: {
          avatar: item === Object(item) && 'avatar' in item,
          ripple: true
        }
      }

      if (this.$scopedSlots.item) {
        return this.$createElement('v-list-tile', data,
          [this.$scopedSlots.item({ parent: this, item })]
        )
      }

      return this.$createElement('v-list-tile', data,
        [this.genAction(item, active), this.genContent(item)]
      )
    },
    genAction (item, active) {
      if (!this.multiple) return null

      const data = {
        'class': {
          'list__tile__action--select-multi': this.multiple
        },
        nativeOn: { click: () => this.selectItem(item) }
      }

      return this.$createElement('v-list-tile-action', data, [
        this.$createElement('v-checkbox', { props: { inputValue: active }})
      ])
    },
    genContent (item) {
      return this.$createElement('v-list-tile-content',
        [this.$createElement('v-list-tile-title', this.getText(item))]
      )
    }
  }
}


} else if (this.closeOnClick && this.isActive) this.isActive = false

if (this.disabled || this.hasJustFocused) return


env:
  node: true
  mocha: true
  chai: true
  sinon: true


.stepper
  overflow: hidden
  position: relative
  elevation(2)

.stepper
  &__header
    align-items: stretch
    display: flex
    flex-wrap: wrap
    justify-content: space-between
    elevation(2)

    .divider
      align-self: center
      margin: 0 -16px

.stepper
  &__step__step
    align-items: center
    background: rgba($material-theme.fg-color, $material-theme.disabledORhints-text-percent)
    border-radius: 50%
    color: $material-theme.bg-color
    display: flex
    font-size: 12px
    justify-content: center
    height: 24px
    margin-right: 8px
    width: 24px
    transition: .3s $transition.fast-in-fast-out

    .icon
      font-size: 18px
      color: rgba($material-theme.bg-color)

.stepper
  &__step
    align-items: center
    display: flex
    flex-direction: row
    flex-wrap: wrap
    padding: 24px
    position: relative

    &--active
      .stepper__label
        text-shadow: 0px 0px 0px black
        transition: .3s $transition.ease-in-out

      .stepper__step__step
        background: $theme.primary
        // font-size: 12px

    &--editable
      cursor: pointer

      &:hover
        background: rgba($material-theme.fg-color, .06)
        text-shadow: 0px 0px 0px black

    &--inactive
      .stepper__label
        color: rgba($material-theme.fg-color, $material-theme.disabledORhints-text-percent)

        small
          color: rgba($material-theme.fg-color, $material-theme.disabledORhints-text-percent)

      .stepper__step__step:not(&.stepper__step--error)
        color: $material-theme.bg-color
        background: rgba($material-theme.fg-color, $material-theme.disabledORhints-text-percent)

        &:hover
          background: rgba(#000, .50)

      &.stepper__step--editable
        &:hover
          .stepper__step__step
            background: rgba(#000, .5)

    &--error
      .stepper__step__step
        background: transparent
        color: $theme.error

        .icon
          font-size: 24px
          color: $theme.error

      .stepper__label
        color: $theme.error
        text-shadow: none
        font-weight: 500

        small
          color: $theme.error

    &--complete
      .stepper__label
        color: rgba($material-theme.fg-color, $material-theme.primary-text-percent)

      .stepper__step__step
        background: $theme.primary

.stepper
  &__label
    align-items: flex-start
    display: flex
    flex-direction: column
    text-align: left
    color: rgba($material-theme.fg-color, $material-theme.disabledORhints-text-percent)

    small
      font-size: 12px
      font-weight: 300
      color: rgba($material-theme.fg-color, $material-theme.secondary-text-percent)
      text-shadow: none

.stepper
  &__wrapper
    overflow: hidden
    transition: .4s $transition.ease-in-out

.stepper
  &__content
    top: initial
    bottom: 0
    padding: 16px
    transition: .4s $transition.ease-in-out
    flex: 1
    // Chrome has an issue with overflow hidden for rendering
    // Originally used translateZ but this messes up fixed
    // elements within the stepper
    // Fix for #512 and #620
    // overflow: hidden
    width: 100%

    .btn
      margin-left: 0

.stepper
  &--non-linear
    .stepper__step:not(.stepper__step--complete)
      .stepper__label
        color: rgba($material-theme.fg-color, $material-theme.secondary-text-percent)

  &--vertical
    padding-bottom: 36px

    .stepper__content
      margin: -8px 0 -16px 36px
      padding: 16px 60px 16px 23px
      width: auto

    .stepper__content:not(:last-child)
      border-left: 1px solid $material-twelve-percent-dark

    .stepper__step
      padding: 24px 24px 16px

    .stepper__step__step
      margin-right: 12px

  &--alt-labels
    .stepper__header
      .divider
        margin: 35px -67px 0
        align-self: flex-start

    .stepper__step
      flex-direction: column
      justify-content: flex-start
      align-items: center
      flex-basis: 175px

      small
        align-self: center

    .stepper__step__step
      margin-right: 0
      margin-bottom: 12px

@media $display-breakpoints.sm-and-down
  .stepper:not(.stepper--vertical)
    .stepper__label
      display: none

    .stepper__step__step
      margin-right: 0


mouseLeaveHandler (e) {
if (this.insideContent) return
this.isActive = false
}
}
}


import Icon from './Icon'

export default {
  Icon
}


<template lang="pug">
  div(
    class="progress-linear"
    v-bind:class="classes"
    v-bind:style="{ height: height + 'px' }"
  )
    div(class="progress-linear__bar" v-bind:style="styles")
      v-fade-transition
        div(class="progress-linear__bar__indeterminate" v-if="indeterminate")
      v-slide-x-transition
        div(
          class="progress-linear__bar__determinate"
          v-bind:style="{ width: value + '%' }"
          v-if="!indeterminate"
        )
</template>

<script>
  export default {
    name: 'progress',

    props: {
      active: {
        type: Boolean,
        default: true
      },

      buffer: Boolean,

      bufferValue: Number,

      error: Boolean,

      height: {
        type: [Number, String],
        default: 7
      },

      indeterminate: Boolean,

      info: Boolean,

      secondary: Boolean,

      success: Boolean,

      query: Boolean,

      warning: Boolean,

      value: {
        type: [Number, String],
        default: 0
      }
    },

    computed: {
      classes () {
        return {
          'progress-linear--query': this.query,
          'progress-linear--secondary': this.secondary,
          'progress-linear--success': this.success,
          'progress-linear--info': this.info,
          'progress-linear--warning': this.warning,
          'progress-linear--error': this.error
        }
      },

      styles () {
        const styles = {}

        if (!this.active) {
          styles.height = 0
        }

        if (this.buffer) {
          styles.width = `${this.bufferValue}%`
        }

        return styles
      },

      bufferStyles () {
        const styles = {}

        if (!this.active) {
          styles.height = 0
        }

        return styles
      }
    }
  }
</script>


import { createSimpleFunctional } from '../../util/helpers'
import Stepper from './Stepper'
import StepperStep from './StepperStep'
import StepperContent from './StepperContent'

const StepperHeader = createSimpleFunctional('stepper__header')

export default {
  Stepper,
  StepperContent,
  StepperHeader,
  StepperStep
}


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

bottom: this.positionY || this.absoluteY,

right: this.positionX || this.absoluteX,

export default {
  methods: {
    // Revisit this
    calculateScroll () {
      if (this.selectedIndex === null) return

      let scrollTop = 0

      if (this.selectedIndex >= this.stopIndex) {
        scrollTop = this.$refs.content.scrollHeight
      } else if (this.selectedIndex > this.startIndex) {
        scrollTop = (this.selectedIndex * 48) - 56
      }

      this.$refs.content.scrollTop = scrollTop
    },
    calcLeftAuto () {
      const a = this.dimensions.activator

      return parseInt(a.left - 16)
    },
    calcTopAuto () {
      if (!this.$refs.content) return this.calcTop(true)

      const selectedIndex = Array.from(this.tiles).findIndex(n => n.classList.contains('list__tile--active'))

      if (selectedIndex === -1) {
        this.selectedIndex = null

        return this.calcTop(true)
      }

      this.selectedIndex = selectedIndex
      let actingIndex = selectedIndex

      let offsetPadding = -16
      // #708 Stop index should vary by tile length
      this.stopIndex = this.tiles.length > 4
        ? this.tiles.length - 4
        : this.tiles.length

      if (selectedIndex > this.startIndex && selectedIndex < this.stopIndex) {
        actingIndex = 2
        offsetPadding = 24
      } else if (selectedIndex >= this.stopIndex) {
        offsetPadding = -8
        actingIndex = selectedIndex - this.stopIndex
      }

      return this.calcTop(true) + offsetPadding - (actingIndex * 48)
    },
    calcLeft () {
      if (this.auto) return this.calcLeftAuto()

      const a = this.dimensions.activator
      const c = this.dimensions.content
      let left = this.left ? a.right - c.width : a.left

      if (this.offsetX) left += this.left ? -a.width : a.width
      if (this.nudgeLeft) left += this.nudgeLeft
      if (this.nudgeRight) left -= this.nudgeRight

      const totalWidth = left + this.minWidth - this.window.innerWidth

      if (totalWidth > 0) left -= (totalWidth + 24) // give a little extra space

      return left
    },
    calcTop (force) {
      if (this.auto && !force) return this.calcTopAuto()

      const a = this.dimensions.activator
      const c = this.dimensions.content
      let top = this.top ? a.bottom - c.height : a.top

      if (this.offsetY) top += this.top ? -a.height : a.height
      if (this.nudgeTop) top -= this.nudgeTop
      if (this.nudgeBottom) top += this.nudgeBottom

      return top + this.window.pageYOffset
    },
    sneakPeek (cb) {
      const el = this.$refs.content
      const currentDisplay = el.style.display

      el.style.display = 'inline-block'
      cb()
      el.style.display = currentDisplay
    },
    absolutePosition () {
      return {
        offsetTop: 0,
        scrollHeight: 0,
        top: this.positionY !== null ? this.positionY : this.absoluteY,
        bottom: this.positionY !== null ? this.positionY : this.absoluteY,
        left: this.positionX !== null ? this.positionX : this.absoluteX,
        right: this.positionX !== null ? this.positionX : this.absoluteX,
        height: 0,
        width: 0
      }
    },
    updateDimensions () {
      this.sneakPeek(() => {
        this.dimensions = {
          activator: !this.hasActivator || this.positionAbsolutely
            ? this.absolutePosition() : this.measure(this.getActivator()),
          content: this.measure(this.$refs.content)
        }
      })
    }
  }
}


export default {
  name: 'stepper-content',

  data () {
    return {
      height: 0,
      isActive: false,
      isReverse: false,
      isVertical: false
    }
  },

  props: {
    step: {
      type: [Number, String],
      required: true
    }
  },

  computed: {
    classes () {
      return {
        'stepper__content': true
      }
    },
    computedTransition () {
      return this.isReverse
        ? 'v-tab-reverse-transition'
        : 'v-tab-transition'
    },
    styles () {
      if (!this.isVertical) return {}

      return {
        height: !isNaN(this.height) ? `${this.height}px` : this.height
      }
    },
    wrapperClasses () {
      return {
        'stepper__wrapper': true
      }
    }
  },

  watch: {
    isActive () {
      if (!this.isVertical) {
        return
      }

      if (this.isActive) {
        this.enter()
      } else {
        this.leave()
      }
    }
  },

  mounted () {
    this.$refs.wrapper.addEventListener(
      'transitionend',
      this.onTransition,
      false
    )
  },

  beforeDestroy () {
    this.$refs.wrapper.removeEventListener(
      'transitionend',
      this.onTransition,
      false
    )
  },

  methods: {
    onTransition () {
      if (!this.isActive) return

      this.height = 'auto'
    },
    enter () {
      let scrollHeight = 0

      // Render bug with height
      setTimeout(() => {
        scrollHeight = this.$refs.wrapper.scrollHeight
      }, 0)

      this.height = 0

      // Give the collapsing element time to collapse
      setTimeout(() => (this.height = scrollHeight), 450)
    },
    leave () {
      this.height = this.$refs.wrapper.clientHeight
      setTimeout(() => (this.height = 0), 0)
    },
    toggle (step, reverse) {
      this.isActive = step.toString() === this.step.toString()
      this.isReverse = reverse
    }
  },

  render (h) {
    const contentData = {
      'class': this.classes
    }
    const wrapperData = {
      'class': this.wrapperClasses,
      style: this.styles,
      ref: 'wrapper'
    }

    if (!this.isVertical) {
      contentData.directives = [{
        name: 'show',
        value: this.isActive
      }]
    }

    const wrapper = h('div', wrapperData, [this.$slots.default])
    const content = h('div', contentData, [wrapper])

    return h(this.computedTransition, {}, [content])
  }
}


export default {
  name: 'stepper',

  provide () {
    return {
      stepClick: this.stepClick
    }
  },

  data () {
    return {
      inputValue: null,
      steps: [],
      content: [],
      isReverse: false
    }
  },

  props: {
    nonLinear: Boolean,
    altLabels: Boolean,
    vertical: Boolean,
    value: [Number, String]
  },

  computed: {
    classes () {
      return {
        'stepper': true,
        'stepper--vertical': this.vertical,
        'stepper--alt-labels': this.altLabels,
        'stepper--non-linear': this.nonLinear
      }
    }
  },

  watch: {
    inputValue (val, prev) {
      this.isReverse = Number(val) < Number(prev)
      this.steps.forEach(i => i.toggle(this.inputValue))
      this.content.forEach(i => i.toggle(this.inputValue, this.isReverse))

      this.$emit('input', this.inputValue)
    },
    value () {
      this.inputValue = this.value
    }
  },

  mounted () {
    this.$vuetify.load(this.init)
  },

  methods: {
    init () {
      this.$children.forEach(i => {
        if (i.$options._componentTag === 'v-stepper-step') {
          this.steps.push(i)
        } else if (i.$options._componentTag === 'v-stepper-content') {
          i.isVertical = this.vertical
          this.content.push(i)
        }
      })

      this.inputValue = this.value || this.steps[0].step || 1
    },
    stepClick (step) {
      this.inputValue = step
    }
  },

  render (h) {
    return h('div', {
      'class': this.classes
    }, this.$slots.default)
  }
}


import Select from './Select'

export default {
  Select
}


"use strict";

const log = require("npmlog");
const childProcess = require("@lerna/child-process");

const hasTags = require("./lib/has-tags");
const collectDependents = require("./lib/collect-dependents");
const getForcedPackages = require("./lib/get-forced-packages");
const makeDiffPredicate = require("./lib/make-diff-predicate");

module.exports = collectUpdates;

function collectUpdates(filteredPackages, packageGraph, execOpts, commandOptions) {
  const packages =
    filteredPackages.length === packageGraph.size
      ? packageGraph
      : new Map(filteredPackages.map(({ name }) => [name, packageGraph.get(name)]));

  let committish = commandOptions.since;

  if (hasTags(execOpts)) {
    if (commandOptions.canary) {
      const sha = childProcess.execSync("git", ["rev-parse", "--short", "HEAD"], execOpts);

      // if it's a merge commit, it will return all the commits that were part of the merge
      // ex: If `ab7533e` had 2 commits, ab7533e^..ab7533e would contain 2 commits + the merge commit
      committish = `${sha}^..${sha}`;
    } else if (!committish) {
      // attempt to find the last annotated tag in the current branch
      committish = childProcess.execSync("git", ["describe", "--abbrev=0"], execOpts);
    }
  }

  log.info("", `Looking for changed packages since ${committish || "initial commit."}`);

  const forced = getForcedPackages(commandOptions.forcePublish);
  let candidates;

  if (!committish || forced.has("*")) {
    candidates = new Set(packages.values());
  } else {
    candidates = new Set();

    const hasDiff = makeDiffPredicate(committish, execOpts, commandOptions.ignoreChanges);
    const needsBump = (commandOptions.bump || "").startsWith("pre")
      ? () => false
      : /* skip packages that have not been previously prereleased */
        node => node.prereleaseId;

    packages.forEach((node, name) => {
      if (forced.has(name) || needsBump(node) || hasDiff(node)) {
        candidates.add(node);
      }
    });
  }

  const dependents = collectDependents(candidates);
  dependents.forEach(node => candidates.add(node));

  // The result should always be in the same order as the input
  const updates = [];

  packages.forEach((node, name) => {
    if (candidates.has(node)) {
      log.verbose("updated", name);

      updates.push(node);
    }
  });

  return updates;
}


"use strict";

const dedent = require("dedent");
const isCI = require("is-ci");
const log = require("npmlog");
const yargs = require("yargs/yargs");
const globalOptions = require("@lerna/global-options");

const addCmd = require("@lerna/add/command");
const bootstrapCmd = require("@lerna/bootstrap/command");
const changedCmd = require("@lerna/changed/command");
const cleanCmd = require("@lerna/clean/command");
const createCmd = require("@lerna/create/command");
const diffCmd = require("@lerna/diff/command");
const execCmd = require("@lerna/exec/command");
const importCmd = require("@lerna/import/command");
const initCmd = require("@lerna/init/command");
const linkCmd = require("@lerna/link/command");
const listCmd = require("@lerna/list/command");
const publishCmd = require("@lerna/publish/command");
const runCmd = require("@lerna/run/command");
const versionCmd = require("@lerna/version/command");

module.exports = lernaCLI;

/**
 * Essentially a factory that returns a yargs() instance that can
 * be used to call parse() immediately (as in ../lerna) or by
 * unit tests to encapsulate instantiation with "real" arguments.
 *
 * @param {Array = []} argv
 * @param {String = process.cwd()} cwd
 */
function lernaCLI(argv, cwd) {
  const cli = yargs(argv, cwd);
  const defaults = { ci: isCI };

  if (defaults.ci || !process.stderr.isTTY) {
    log.disableColor();
    defaults.progress = false;
  } else if (!process.stdout.isTTY) {
    // stdout is being piped, don't log non-errors or progress bars
    defaults.progress = false;
    defaults.loglevel = "error";
  } else if (process.stderr.isTTY) {
    log.enableColor();
    log.enableUnicode();
  }

  return globalOptions(cli, defaults)
    .usage("Usage: $0 <command> [options]")
    .command(addCmd)
    .command(bootstrapCmd)
    .command(changedCmd)
    .command(cleanCmd)
    .command(createCmd)
    .command(diffCmd)
    .command(execCmd)
    .command(importCmd)
    .command(initCmd)
    .command(linkCmd)
    .command(listCmd)
    .command(publishCmd)
    .command(runCmd)
    .command(versionCmd)
    .demandCommand(1, "A command is required. Pass --help to see all available commands and options.")
    .recommendCommands()
    .strict()
    .fail((msg, err) => {
      // certain yargs validations throw strings :P
      const actual = err || new Error(msg);

      // ValidationErrors are already logged, as are package errors
      if (actual.name !== "ValidationError" && !actual.pkg) {
        // the recommendCommands() message is too terse
        if (/Did you mean/.test(actual.message)) {
          log.error("lerna", `Unknown command "${cli.parsed.argv._[0]}"`);
        }

        log.error("lerna", actual.message);
      }

      // exit non-zero so the CLI can be usefully chained
      cli.exit(actual.code || 1, actual);
    })
    .alias("h", "help")
    .alias("v", "version")
    .wrap(cli.terminalWidth()).epilogue(dedent`
      When a command fails, all logs are written to lerna-debug.log in the current working directory.

      For more information, find our manual at https://github.com/lerna/lerna
    `);
}


Copyright (c) 2018 Tester McPerson <test@example.com>

XYZ License


const childProcess = require("@lerna/child-process");

const hasTags = require("./lib/has-tags");

const collectDependents = require("./lib/collect-dependents");

const getForcedPackages = require("./lib/get-forced-packages");

keep keep keep replace keep keep keep keep

const describeRef = require("@lerna/describe-ref");


"use strict";

const versionCommand = require("@lerna/version/command");

/**
 * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module
 */
exports.command = "publish [bump]";

exports.describe = "Publish packages in the current project.";

exports.builder = yargs => {
  const opts = {
    c: {
      describe: "Publish packages after every successful merge using the sha as part of the tag.",
      alias: "canary",
      type: "boolean",
    },
    // preid is copied from ../version/command because a whitelist for one option isn't worth it
    preid: {
      describe: "Specify the prerelease identifier when publishing a prerelease",
      type: "string",
      requiresArg: true,
      defaultDescription: "alpha",
    },
    "npm-tag": {
      describe: "Publish packages with the specified npm dist-tag",
      type: "string",
      requiresArg: true,
    },
    "npm-client": {
      defaultDescription: "npm",
      describe: "Executable used to publish dependencies (npm, yarn, pnpm, ...)",
      type: "string",
      requiresArg: true,
    },
    registry: {
      describe: "Use the specified registry for all npm client operations.",
      type: "string",
      requiresArg: true,
    },
    "require-scripts": {
      describe: "Execute ./scripts/prepublish.js and ./scripts/postpublish.js, relative to package root.",
      type: "boolean",
    },
    "temp-tag": {
      describe: "Create a temporary tag while publishing.",
      type: "boolean",
    },
    "verify-access": {
      describe: "Verify package read-write access for current npm user.\nPass --no-verify-access to disable.",
      type: "boolean",
      defaultDescription: "true",
    },
    "verify-registry": {
      describe: "Verify registry authentication for current npm user.\nPass --no-verify-registry to disable.",
      type: "boolean",
      defaultDescription: "true",
    },
    y: {
      describe: "Skip all confirmation prompts.",
      alias: "yes",
      type: "boolean",
    },
  };

  return composeVersionOptions(yargs)
    .options(opts)
    .group(Object.keys(opts), "Command Options:")
    .option("skip-npm", {
      // TODO: remove in next major release
      // deprecation notice handled in initialize()
      hidden: true,
      type: "boolean",
    });
};

exports.handler = function handler(argv) {
  return require(".")(argv);
};

function composeVersionOptions(yargs) {
  versionCommand.addBumpPositional(yargs, ["from-git"]);
  versionCommand.builder(yargs, "publish");

  return yargs;
}


: new Map(filteredPackages.map(({ name }) => [name, packageGraph.get(name)]));

const sha = childProcess.execSync("git", ["rev-parse", "--short", "HEAD"], execOpts);

keep keep keep keep keep replace replace keep

// describe the last annotated tag in the current branch

const { sha, refCount, lastTag } = describeRef.sync(execOpts);

@lerna/collect-updates

An internal Lerna tool


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

exports[`lerna init initializes empty directory: lerna.json 1`] = `
Object {
  packages: Array [
    packages/*,
  ],
  version: 0.0.0,
}
`;

exports[`lerna init initializes empty directory: package.json 1`] = `
Object {
  devDependencies: Object {
    lerna: "^__TEST_VERSION__",
  },
  name: root,
  private: true,
}
`;

exports[`lerna init initializes empty directory: stderr 1`] = `
lerna notice cli __TEST_VERSION__
lerna info Initializing Git repository
lerna info Creating package.json
lerna info Creating lerna.json
lerna info Creating packages directory
lerna success Initialized Lerna files
`;

exports[`lerna init updates existing metadata: lerna.json 1`] = `
Object {
  command: Object {
    bootstrap: Object {
      hoist: true,
    },
    init: Object {
      exact: true,
    },
  },
  packages: Array [
    packages/*,
  ],
  version: 1.0.0,
}
`;

exports[`lerna init updates existing metadata: package.json 1`] = `
Object {
  devDependencies: Object {
    lerna: "__TEST_VERSION__",
  },
  name: updates,
}
`;

exports[`lerna init updates existing metadata: stderr 1`] = `
lerna notice cli __TEST_VERSION__
lerna WARN project Deprecated key "commands" found in lerna.json
lerna WARN project Please rename "commands" => "command"
lerna info Updating package.json
lerna info Updating lerna.json
lerna info Creating packages directory
lerna success Initialized Lerna files
`;


// if it's a merge commit, it will return all the commits that were part of the merge

// ex: If `ab7533e` had 2 commits, ab7533e^..ab7533e would contain 2 commits + the merge commit


# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10)

**Note:** Version bump only for package @lerna/validation-error

# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27)

**Note:** Version bump only for package @lerna/validation-error

# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27)

**Note:** Version bump only for package @lerna/validation-error


"use strict";

const log = require("npmlog");
const npmLifecycle = require("npm-lifecycle");
const npmConf = require("@lerna/npm-conf");

module.exports = runLifecycle;
module.exports.createRunner = createRunner;

function runLifecycle(pkg, stage, opts) {
  log.silly("run-lifecycle", stage, pkg.name);

  const config = {};
  const dir = pkg.location;

  // https://github.com/isaacs/proto-list/blob/27764cd/proto-list.js#L29
  for (const key of opts.keys) {
    const val = opts.get(key);

    if (val != null) {
      config[key] = val;
    }
  }

  // env.npm_config_prefix should be the package directory
  config.prefix = dir;

  // TODO: remove pkg._id when npm-lifecycle no longer relies on it
  pkg._id = `${pkg.name}@${pkg.version}`; // eslint-disable-line

  return npmLifecycle(pkg, stage, dir, {
    config,
    dir,
    failOk: false,
    log,
    unsafePerm: true,
  });
}

function createRunner(commandOptions) {
  const cfg = npmConf(commandOptions);

  return (pkg, stage) => {
    if (pkg.scripts && pkg.scripts[stage]) {
      return runLifecycle(pkg, stage, cfg).catch(err => {
        log.error("lifecycle", `error running ${stage} in ${pkg.name}\n`, err.stack || err);
      });
    }

    return Promise.resolve();
  };
}


// attempt to find the last annotated tag in the current branch

committish = childProcess.execSync("git", ["describe", "--abbrev=0"], execOpts);

log.info("", `Looking for changed packages since ${committish || "initial commit."}`);

keep keep keep keep replace replace keep keep keep keep keep

log.notice("", "Current HEAD is already released, no changes possible.");

// if no tags found, this will be undefined and we'll use the initial commit

An internal Lerna tool


# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10)

**Note:** Version bump only for package @lerna/run-lifecycle

# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27)

### Features

* **run-lifecycle:** Encapsulate npm-conf with createRunner() factory ([488f98d](https://github.com/lerna/lerna/commit/488f98d))


"test": "echo \"Run tests from root\" && exit 1"


"use strict";

const path = require("path");
const resolveFrom = require("resolve-from");
const ValidationError = require("@lerna/validation-error");
const deprecateConfig = require("./deprecate-config");
const shallowExtend = require("./shallow-extend");

module.exports = applyExtends;

function applyExtends(config, cwd, seen = new Set()) {
  let defaultConfig = {};

  if ("extends" in config) {
    let pathToDefault;

    try {
      pathToDefault = resolveFrom(cwd, config.extends);
    } catch (err) {
      throw new ValidationError("ERESOLVED", "Config .extends must be locally-resolvable", err);
    }

    if (seen.has(pathToDefault)) {
      throw new ValidationError("ECIRCULAR", "Config .extends cannot be circular", seen);
    }

    seen.add(pathToDefault);

    // eslint-disable-next-line import/no-dynamic-require, global-require
    defaultConfig = require(pathToDefault);
    delete config.extends; // eslint-disable-line no-param-reassign

    deprecateConfig(defaultConfig, pathToDefault);

    defaultConfig = applyExtends(defaultConfig, path.dirname(pathToDefault), seen);
  }

  return shallowExtend(config, defaultConfig);
}


"use strict";

console.log("__fixtures__/local-install/node_modules/@lerna/cli/index.js");

module.exports = function cli() {
  return {
    parse() {},
  };
};


"use strict";

// eslint-disable-next-line import/no-extraneous-dependencies, node/no-extraneous-require
const Project = require("@lerna/project");

module.exports = updateLernaConfig;

/**
 * Update lerna config inside a test case.
 *
 * @param {String} testDir where target lerna.json exists
 * @param {Object} updates mixed into existing JSON via Object.assign
 */
function updateLernaConfig(testDir, updates) {
  const project = new Project(testDir);

  Object.assign(project.config, updates);

  return project.serializeConfig();
}


modified: {type: Number, default: Date.now() } // UnixTime

'use strict';

const { Schema } = require('warehouse');
const Promise = require('bluebird');

module.exports = ctx => {
  const Cache = new Schema({
    _id: {type: String, required: true},
    hash: {type: String, default: ''},
    modified: {type: Number, default: Date.now}
  });

  Cache.static('compareFile', function(id, hashFn, statFn) {
    const cache = this.findById(id);

    // If cache does not exist, then it must be a new file. We have to get both
    // file hash and stats.
    if (!cache) {
      return Promise.all([hashFn(id), statFn(id)]).spread((hash, stats) => this.insert({
        _id: id,
        hash,
        modified: stats.mtime
      })).thenReturn({
        type: 'create'
      });
    }

    let mtime;

    // Get file stats
    return statFn(id).then(stats => {
      mtime = stats.mtime;

      // Skip the file if the modified time is unchanged
      if (cache.modified === mtime) {
        return {
          type: 'skip'
        };
      }

      // Get file hash
      return hashFn(id);
    }).then(result => {
      // If the result is an object, skip the following steps because it's an
      // unchanged file
      if (typeof result === 'object') return result;

      const hash = result;

      // Skip the file if the hash is unchanged
      if (cache.hash === hash) {
        return {
          type: 'skip'
        };
      }

      // Update cache info
      cache.hash = hash;
      cache.modified = mtime;

      return cache.save().thenReturn({
        type: 'update'
      });
    });
  });

  return Cache;
};


'use strict';

const { resolve } = require('path');
const tildify = require('tildify');
const prettyHrtime = require('pretty-hrtime');
const fs = require('hexo-fs');
const chalk = require('chalk');

function renderConsole(args) {
  // Display help message if user didn't input any arguments
  if (!args._.length) {
    return this.call('help', {_: 'render'});
  }

  const baseDir = this.base_dir;
  const src = resolve(baseDir, args._[0]);
  const output = args.o || args.output;
  const start = process.hrtime();
  const { log } = this;

  return this.render.render({
    path: src,
    engine: args.engine
  }).then(result => {
    if (typeof result === 'object') {
      if (args.pretty) {
        result = JSON.stringify(result, null, '  ');
      } else {
        result = JSON.stringify(result);
      }
    }

    if (!output) return console.log(result);

    const dest = resolve(baseDir, output);
    const interval = prettyHrtime(process.hrtime(start));

    log.info('Rendered in %s: %s -> %s', chalk.cyan(interval), chalk.magenta(tildify(src)), chalk.magenta(tildify(dest)));
    return fs.writeFile(dest, result);
  });
}

module.exports = renderConsole;


root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true

[vcbuild.bat]
end_of_line = crlf

[*.{md,markdown}]
trim_trailing_whitespace = false

[{lib,src,test}/**.js]
indent_style = space
indent_size = 2

[src/**.{h,cc}]
indent_style = space
indent_size = 2

[test/*.py]
indent_style = space
indent_size = 2

[configure]
indent_style = space
indent_size = 2

[Makefile]
indent_style = tab
indent_size = 8

[{deps,tools}/**]
indent_style = ignore
indent_size = ignore
end_of_line = ignore
trim_trailing_whitespace = ignore
charset = ignore


'use strict';

const url = require('url');
const relative_url = require('./relative_url');

function urlForHelper(path = '/', options) {
  if (path[0] === '#' || path.startsWith('//')) {
    return path;
  }

  const { config } = this;
  const { root } = config;
  const data = url.parse(path);

  options = Object.assign({
    relative: config.relative_link
  }, options);

  // Exit if this is an external path
  if (data.protocol) {
    return path;
  }

  // Resolve relative url
  if (options.relative) {
    return relative_url(this.path, path);
  }

  // Prepend root path
  path = root + path;

  return path.replace(/\/{2,}/g, '/');
}

module.exports = urlForHelper;


return Promise.all([hashFn(id), statFn(id)]).spread((hash, stats) => this.insert({

keep keep keep keep replace keep keep keep

'use strict';

const pathFn = require('path');
const fs = require('hexo-fs');
const Promise = require('bluebird');
const util = require('hexo-util');
const sinon = require('sinon');
const Pattern = util.Pattern;

describe('Box', () => {
  const Hexo = require('../../../lib/hexo');
  const baseDir = pathFn.join(__dirname, 'box_tmp');
  const Box = require('../../../lib/box');

  function newBox(path, config) {
    const hexo = new Hexo(baseDir, {silent: true});
    hexo.config = Object.assign(hexo.config, config);
    const base = path ? pathFn.join(baseDir, path) : baseDir;
    return new Box(hexo, base);
  }

  before(() => fs.mkdir(baseDir));

  after(() => fs.rmdir(baseDir));

  it('constructor - add trailing "/" to the base path', () => {
    const box = newBox('foo');
    box.base.should.eql(pathFn.join(baseDir, 'foo') + pathFn.sep);
  });

  it('addProcessor() - no pattern', () => {
    const box = newBox();

    box.addProcessor(() => 'test');

    const p = box.processors[0];

    p.pattern.match('').should.eql({});
    p.process().should.eql('test');
  });

  it('addProcessor() - with regex', () => {
    const box = newBox();

    box.addProcessor(/^foo/, () => 'test');

    const p = box.processors[0];

    p.pattern.match('foobar').should.be.ok;
    p.pattern.should.be.an.instanceof(Pattern);
    p.process().should.eql('test');
  });

  it('addProcessor() - with pattern', () => {
    const box = newBox();

    box.addProcessor(new Pattern(/^foo/), () => 'test');

    const p = box.processors[0];

    p.pattern.match('foobar').should.be.ok;
    p.pattern.should.be.an.instanceof(Pattern);
    p.process().should.eql('test');
  });

  it('addProcessor() - no fn', () => {
    const box = newBox();
    const errorCallback = sinon.spy(err => {
      err.should.have.property('message', 'fn must be a function');
    });

    try {
      box.addProcessor('test');
    } catch (err) {
      errorCallback(err);
    }

    errorCallback.calledOnce.should.be.true;
  });

  it('process()', () => {
    const box = newBox('test');
    const data = {};

    box.addProcessor(file => {
      data[file.path] = file;
    });

    return Promise.all([
      fs.writeFile(pathFn.join(box.base, 'a.txt'), 'a'),
      fs.writeFile(pathFn.join(box.base, 'b', 'c.js'), 'c')
    ]).then(() => box.process()).then(() => {
      const keys = Object.keys(data);
      let key, item;

      for (let i = 0, len = keys.length; i < len; i++) {
        key = keys[i];
        item = data[key];

        item.path.should.eql(key);
        item.source.should.eql(pathFn.join(box.base, key));
        item.type.should.eql('create');
        item.params.should.eql({});
      }
    }).finally(() => fs.rmdir(box.base));
  });

  it('process() - do nothing if target does not exist', () => {
    const box = newBox('test');

    return box.process();
  });

  it('process() - create', () => {
    const box = newBox('test');
    const name = 'a.txt';
    const path = pathFn.join(box.base, name);

    const processor = sinon.spy();
    box.addProcessor(processor);

    return fs.writeFile(path, 'a').then(() => box.process()).then(() => {
      const file = processor.args[0][0];
      file.type.should.eql('create');
      file.path.should.eql(name);
    }).finally(() => fs.rmdir(box.base));
  });

  it('process() - mtime changed', () => {
    const box = newBox('test');
    const name = 'a.txt';
    const path = pathFn.join(box.base, name);
    const cacheId = 'test/' + name;

    const processor = sinon.spy();
    box.addProcessor(processor);

    return Promise.all([
      fs.writeFile(path, 'a'),
      box.Cache.insert({
        _id: cacheId,
        modified: 0
      })
    ]).then(() => box.process()).then(() => {
      const file = processor.args[0][0];
      file.type.should.eql('update');
      file.path.should.eql(name);
    }).finally(() => fs.rmdir(box.base));
  });

  it('process() - hash changed', () => {
    const box = newBox('test');
    const name = 'a.txt';
    const path = pathFn.join(box.base, name);
    const cacheId = 'test/' + name;

    const processor = sinon.spy();
    box.addProcessor(processor);

    return fs.writeFile(path, 'a').then(() => fs.stat(path)).then(stats => box.Cache.insert({
      _id: cacheId,
      modified: stats.mtime
    })).then(() => box.process()).then(() => {
      const file = processor.args[0][0];
      file.type.should.eql('update');
      file.path.should.eql(name);
    }).finally(() => fs.rmdir(box.base));
  });

  it('process() - skip', () => {
    const box = newBox('test');
    const name = 'a.txt';
    const path = pathFn.join(box.base, name);
    const cacheId = 'test/' + name;

    const processor = sinon.spy();
    box.addProcessor(processor);

    return fs.writeFile(path, 'a').then(() => fs.stat(path)).then(stats => box.Cache.insert({
      _id: cacheId,
      modified: stats.mtime,
      hash: util.hash('a').toString('hex')
    })).then(() => box.process()).then(() => {
      const file = processor.args[0][0];
      file.type.should.eql('skip');
      file.path.should.eql(name);
    }).finally(() => fs.rmdir(box.base));
  });

  it('process() - delete', () => {
    const box = newBox('test');
    const cacheId = 'test/a.txt';

    const processor = sinon.spy(file => {
      file.type.should.eql('delete');
    });

    box.addProcessor(processor);

    return Promise.all([
      fs.mkdirs(box.base),
      box.Cache.insert({
        _id: cacheId
      })
    ]).then(() => box.process()).then(() => {
      processor.calledOnce.should.be.true;
    }).finally(() => fs.rmdir(box.base));
  });

  it('process() - params', () => {
    const box = newBox('test');
    const path = pathFn.join(box.base, 'posts', '123456');

    const processor = sinon.spy(file => {
      file.params.id.should.eql('123456');
    });

    box.addProcessor('posts/:id', processor);

    return fs.writeFile(path, 'a').then(() => box.process()).then(() => {
      processor.calledOnce.should.be.true;
    }).finally(() => fs.rmdir(box.base));
  });

  it('process() - skip files if they match a glob epression in ignore', () => {
    const box = newBox('test', {ignore: '**/ignore_me'});
    const data = {};

    box.addProcessor(file => {
      data[file.path] = file;
    });

    return Promise.all([
      fs.writeFile(pathFn.join(box.base, 'foo.txt'), 'foo'),
      fs.writeFile(pathFn.join(box.base, 'ignore_me', 'bar.txt'), 'ignore_me')
    ]).then(() => box.process()).then(() => {
      const keys = Object.keys(data);

      keys.length.should.eql(1);
      keys[0].should.eql('foo.txt');
    }).finally(() => fs.rmdir(box.base));
  });

  it('process() - skip files if they match any of the glob expressions in ignore', () => {
    const box = newBox('test', {ignore: ['**/ignore_me', '**/ignore_me_too']});
    const data = {};

    box.addProcessor(file => {
      data[file.path] = file;
    });

    return Promise.all([
      fs.writeFile(pathFn.join(box.base, 'foo.txt'), 'foo'),
      fs.writeFile(pathFn.join(box.base, 'ignore_me', 'bar.txt'), 'ignore_me')
    ]).then(() => box.process()).then(() => {
      const keys = Object.keys(data);

      keys.length.should.eql(1);
      keys[0].should.eql('foo.txt');
    }).finally(() => fs.rmdir(box.base));
  });

  it('watch() - create', () => {
    const box = newBox('test');
    const path = 'a.txt';
    const src = pathFn.join(box.base, path);
    const processor = sinon.spy();

    box.addProcessor(processor);

    return Promise.all([fs.writeFile(src, 'a')])
      .then(() => box.watch())
      .then(() => box.isWatching().should.be.true)
      .delay(500).then(() => {
        const file = processor.args[0][0];

        file.source.should.eql(src);
        file.path.should.eql(path);
        file.type.should.eql('create');
        file.params.should.eql({});
      }).finally(() => {
        box.unwatch();
        return fs.rmdir(box.base);
      });
  });

  it('watch() - update', () => {
    const box = newBox('test');
    const path = 'a.txt';
    const src = pathFn.join(box.base, path);
    const cacheId = 'test/' + path;
    const Cache = box.Cache;
    const processor = sinon.spy();

    box.addProcessor(processor);

    return Promise.all([
      fs.writeFile(src, 'a'),
      Cache.insert({_id: cacheId})
    ]).then(() => box.watch()).then(() => fs.appendFile(src, 'b')).delay(500).then(() => {
      const file = processor.lastCall.args[0];

      file.source.should.eql(src);
      file.path.should.eql(path);
      file.type.should.eql('update');
      file.params.should.eql({});
    }).finally(() => {
      box.unwatch();
      return fs.rmdir(box.base);
    });
  });

  it('watch() - delete', () => {
    const box = newBox('test');
    const path = 'a.txt';
    const src = pathFn.join(box.base, path);
    const cacheId = 'test/' + path;
    const Cache = box.Cache;
    const processor = sinon.spy();

    box.addProcessor(processor);

    return Promise.all([
      fs.writeFile(src, 'a'),
      Cache.insert({_id: cacheId})
    ]).then(() => box.watch()).then(() => fs.unlink(src)).delay(500).then(() => {
      const file = processor.lastCall.args[0];

      file.source.should.eql(src);
      file.path.should.eql(path);
      file.type.should.eql('delete');
      file.params.should.eql({});
    }).finally(() => {
      box.unwatch();
      return fs.rmdir(box.base);
    });
  });

  it('watch() - rename file', () => {
    const box = newBox('test');
    const path = 'a.txt';
    const src = pathFn.join(box.base, path);
    const newPath = 'b.txt';
    const newSrc = pathFn.join(box.base, newPath);
    const cacheId = 'test/' + path;
    const Cache = box.Cache;
    const processor = sinon.spy();

    box.addProcessor(processor);

    return Promise.all([
      fs.writeFile(src, 'a'),
      Cache.insert({_id: cacheId})
    ]).then(() => box.watch()).then(() => fs.rename(src, newSrc)).delay(500).then(() => {
      const lastTwoCalls = processor.args.slice(processor.args.length - 2, processor.args.length);

      lastTwoCalls.forEach(args => {
        const file = args[0];

        switch (file.type) {
          case 'create':
            file.source.should.eql(newSrc);
            file.path.should.eql(newPath);
            break;

          case 'delete':
            file.source.should.eql(src);
            file.path.should.eql(path);
            break;
        }
      });
    }).finally(() => {
      box.unwatch();
      return fs.rmdir(box.base);
    });
  });

  it('watch() - rename folder', () => {
    const box = newBox('test');
    const path = 'a/b.txt';
    const src = pathFn.join(box.base, path);
    const newPath = 'b/b.txt';
    const newSrc = pathFn.join(box.base, newPath);
    const cacheId = 'test/' + path;
    const Cache = box.Cache;
    const processor = sinon.spy();

    box.addProcessor(processor);

    return Promise.all([
      fs.writeFile(src, 'a'),
      Cache.insert({_id: cacheId})
    ]).then(() => box.watch()).then(() => fs.rename(pathFn.join(box.base, 'a'), pathFn.join(box.base, 'b'))).delay(500).then(() => {
      const lastTwoCalls = processor.args.slice(processor.args.length - 2, processor.args.length);

      lastTwoCalls.forEach(args => {
        const file = args[0];

        switch (file.type) {
          case 'create':
            file.source.should.eql(newSrc);
            file.path.should.eql(newPath);
            break;

          case 'delete':
            file.source.should.eql(src);
            file.path.should.eql(path);
            break;
        }
      });
    }).finally(() => {
      box.unwatch();
      return fs.rmdir(box.base);
    });
  });

  it('watch() - watcher has started', () => {
    const box = newBox();

    return box.watch().then(() => {
      const errorCallback = sinon.spy(err => {
        err.should.have.property('message', 'Watcher has already started.');
      });

      return box.watch().catch(errorCallback).then(() => {
        errorCallback.calledOnce.should.be.true;
      });
    }).finally(() => {
      box.unwatch();
    });
  });

  it('watch() - run process() before start watching', () => {
    const box = newBox('test');
    const data = [];

    box.addProcessor(file => {
      data.push(file.path);
    });

    return Promise.all([
      fs.writeFile(pathFn.join(box.base, 'a.txt'), 'a'),
      fs.writeFile(pathFn.join(box.base, 'b', 'c.js'), 'c')
    ]).then(() => box.watch()).then(() => {
      data.should.have.members(['a.txt', 'b/c.js']);
    }).finally(() => {
      box.unwatch();
      return fs.rmdir(box.base);
    });
  });

  it('unwatch()', () => {
    const box = newBox('test');
    const processor = sinon.spy();

    return box.watch().then(() => {
      box.addProcessor(processor);
      box.unwatch();

      return fs.writeFile(pathFn.join(box.base, 'a.txt'), 'a');
    }).then(() => {
      processor.called.should.be.false;
    }).finally(() => {
      box.unwatch();
      return fs.rmdir(box.base);
    });
  });

  it('isWatching()', () => {
    const box = newBox();

    box.isWatching().should.be.false;

    return box.watch().then(() => {
      box.isWatching().should.be.true;
      return box.unwatch();
    }).then(() => {
      box.isWatching().should.be.false;
    }).finally(() => {
      box.unwatch();
    });
  });

  it('processBefore & processAfter events', () => {
    const box = newBox('test');

    const beforeSpy = sinon.spy(file => {
      file.type.should.eql('create');
      file.path.should.eql('a.txt');
    });

    const afterSpy = sinon.spy(file => {
      file.type.should.eql('create');
      file.path.should.eql('a.txt');
    });

    box.on('processBefore', beforeSpy);
    box.on('processAfter', afterSpy);

    return fs.writeFile(pathFn.join(box.base, 'a.txt'), 'a').then(() => box.process()).then(() => {
      beforeSpy.calledOnce.should.be.true;
      afterSpy.calledOnce.should.be.true;
    }).finally(() => fs.rmdir(box.base));
  });
});


'use strict';

/**
* Vimeo tag
*
* Syntax:
*   {% vimeo video_id %}
*/

function vimeoTag(args, content) {
  const id = args[0];

  return `<div class="video-container"><iframe src="//player.vimeo.com/video/${id}" frameborder="0" allowfullscreen></iframe></div>`;
}

module.exports = vimeoTag;


'use strict';

const Promise = require('bluebird');
const { Pattern } = require('hexo-util');

function Processor() {
  this.store = [];
}

Processor.prototype.list = function() {
  return this.store;
};

Processor.prototype.register = function(pattern, fn) {
  if (!fn) {
    if (typeof pattern === 'function') {
      fn = pattern;
      pattern = /(.*)/;
    } else {
      throw new TypeError('fn must be a function');
    }
  }

  if (fn.length > 1) {
    fn = Promise.promisify(fn);
  } else {
    fn = Promise.method(fn);
  }

  this.store.push({
    pattern: new Pattern(pattern),
    process: fn
  });
};

module.exports = Processor;


// Skip the file if the modified time is unchanged

keep keep keep keep keep replace keep keep keep


'use strict';

function feedTagHelper(path, options = {}) {
  const title = options.title || this.config.title;

  return `<link rel="alternate" href="${this.url_for(path)}" title="${title}">`;
}

module.exports = feedTagHelper;


'use strict';

describe('Theme processors', () => {
  require('./config');
  require('./i18n');
  require('./source');
  require('./view');
});


'use strict';

const stripIndent = require('strip-indent');
const chalk = require('chalk');
const nunjucks = require('nunjucks');
const { inherits } = require('util');
const Promise = require('bluebird');

function Tag() {
  this.env = new nunjucks.Environment(null, {
    autoescape: false
  });
}

Tag.prototype.register = function(name, fn, options) {
  if (!name) throw new TypeError('name is required');
  if (typeof fn !== 'function') throw new TypeError('fn must be a function');

  if (options == null || typeof options === 'boolean') {
    options = {ends: options};
  }

  let tag;

  if (options.async) {
    if (fn.length > 2) {
      fn = Promise.promisify(fn);
    } else {
      fn = Promise.method(fn);
    }

    if (options.ends) {
      tag = new NunjucksAsyncBlock(name, fn);
    } else {
      tag = new NunjucksAsyncTag(name, fn);
    }
  } else if (options.ends) {
    tag = new NunjucksBlock(name, fn);
  } else {
    tag = new NunjucksTag(name, fn);
  }

  this.env.addExtension(name, tag);
};

const placeholder = '\uFFFC';
const rPlaceholder = /(?:<|<)!--\uFFFC(\d+)--(?:>|>)/g;

function getContextLineNums(min, max, center, amplitude) {
  var result = [];
  var lbound = Math.max(min, center - amplitude);
  var hbound = Math.min(max, center + amplitude);
  for (var i = lbound; i <= hbound; i++) {
    result.push(i);
  }

  return result;
}

const LINES_OF_CONTEXT = 5;
function getContext(lines, errLine, location, type) {
  const colorize = chalk.cyan;
  const message = [
    location + ' ' + type,
    colorize('    =====               Context Dump               ====='),
    colorize('    === (line number probably different from source) ===')
  ];

  Array.prototype.push.apply(message,
    // get LINES_OF_CONTEXT lines surrounding `errLine`
    getContextLineNums(1, lines.length, errLine, LINES_OF_CONTEXT)
      .map(function(lnNum) {
        const line = '  ' + lnNum + ' | ' + lines[lnNum - 1];
        if (lnNum === errLine) {
          return colorize.bold(line);
        }

        return colorize(line);
      })
  );
  message.push(colorize(
    '    =====             Context Dump Ends            ====='));

  return message;
}

/**
 * Provide context for Nunjucks error
 * @param  {Error}    err Nunjucks error
 * @param  {string}   str string input for Nunjucks
 * @return {Error}    New error object with embedded context
 */
function formatNunjucksError(err, input) {
  const match = err.message.match(/Line (\d+), Column \d+/);
  if (!match) return err;
  const errLine = parseInt(match[1], 10);
  if (isNaN(errLine)) return err;

  // trim useless info from Nunjucks Error
  const splited = err.message.replace('(unknown path)', '').split('\n');

  const e = new Error();
  e.name = 'Nunjucks Error';
  e.line = errLine;
  e.location = splited[0];
  e.type = splited[1].trim();
  e.message = getContext(input.split(/\r?\n/), errLine, e.location, e.type).join('\n');
  return e;
}

Tag.prototype.render = function(str, options, callback) {
  if (!callback && typeof options === 'function') {
    callback = options;
    options = {};
  }

  const cache = [];

  const escapeContent = str => `<!--${placeholder}${cache.push(str) - 1}-->`;

  str = str.replace(/<pre><code.*>[\s\S]*?<\/code><\/pre>/gm, escapeContent);

  return Promise.fromCallback(cb => { this.env.renderString(str, options, cb); })
    .catch(err => Promise.reject(formatNunjucksError(err, str)))
    .then(result => result.replace(rPlaceholder, (_, index) => cache[index]));
};

function NunjucksTag(name, fn) {
  this.tags = [name];
  this.fn = fn;
}

NunjucksTag.prototype.parse = function(parser, nodes, lexer) {
  const node = this._parseArgs(parser, nodes, lexer);

  return new nodes.CallExtension(this, 'run', node, []);
};

NunjucksTag.prototype._parseArgs = (parser, nodes, lexer) => {
  const tag = parser.nextToken();
  const node = new nodes.NodeList(tag.lineno, tag.colno);
  const argarray = new nodes.Array(tag.lineno, tag.colno);

  let token;
  let argitem = '';

  while ((token = parser.nextToken(true))) {
    if (token.type === lexer.TOKEN_WHITESPACE || token.type === lexer.TOKEN_BLOCK_END) {
      if (argitem !== '') {
        const argnode = new nodes.Literal(tag.lineno, tag.colno, argitem.trim());
        argarray.addChild(argnode);
        argitem = '';
      }

      if (token.type === lexer.TOKEN_BLOCK_END) {
        break;
      }
    } else {
      argitem += token.value;
    }
  }

  node.addChild(argarray);

  return node;
};

NunjucksTag.prototype.run = function(context, args) {
  return this._run(context, args, '');
};

NunjucksTag.prototype._run = function(context, args, body) {
  return Reflect.apply(this.fn, context.ctx, [args, body]);
};

function NunjucksBlock(name, fn) {
  Reflect.apply(NunjucksTag, this, [name, fn]);
}

inherits(NunjucksBlock, NunjucksTag);

NunjucksBlock.prototype.parse = function(parser, nodes, lexer) {
  const node = this._parseArgs(parser, nodes, lexer);
  const body = this._parseBody(parser, nodes, lexer);

  return new nodes.CallExtension(this, 'run', node, [body]);
};

NunjucksBlock.prototype._parseBody = function(parser, nodes, lexer) {
  const body = parser.parseUntilBlocks(`end${this.tags[0]}`);

  parser.advanceAfterBlockEnd();
  return body;
};

NunjucksBlock.prototype.run = function(context, args, body) {
  return this._run(context, args, trimBody(body));
};

function trimBody(body) {
  return stripIndent(body()).replace(/^\n?|\n?$/g, '');
}

function NunjucksAsyncTag(name, fn) {
  Reflect.apply(NunjucksTag, this, [name, fn]);
}

inherits(NunjucksAsyncTag, NunjucksTag);

NunjucksAsyncTag.prototype.parse = function(parser, nodes, lexer) {
  const node = this._parseArgs(parser, nodes, lexer);

  return new nodes.CallExtensionAsync(this, 'run', node, []);
};

NunjucksAsyncTag.prototype.run = function(context, args, callback) {
  return this._run(context, args, '').then(result => {
    callback(null, result);
  }, callback);
};

function NunjucksAsyncBlock(name, fn) {
  Reflect.apply(NunjucksBlock, this, [name, fn]);
}

inherits(NunjucksAsyncBlock, NunjucksBlock);

NunjucksAsyncBlock.prototype.parse = function(parser, nodes, lexer) {
  const node = this._parseArgs(parser, nodes, lexer);
  const body = this._parseBody(parser, nodes, lexer);

  return new nodes.CallExtensionAsync(this, 'run', node, [body]);
};

NunjucksAsyncBlock.prototype.run = function(context, args, body, callback) {
  // enable async tag nesting
  body((err, result) => {
    // wrapper for trimBody expecting
    // body to be a function
    body = () => result || '';

    this._run(context, args, trimBody(body)).then(result => {
      callback(err, result);
    });
  });
};

module.exports = Tag;


return fs.writeFile(path, 'a').then(() => fs.stat(path)).then(stats => box.Cache.insert({

keep keep keep replace replace keep keep keep keep


'use strict';

function isCurrentHelper(path = '/', strict) {
  const currentPath = this.path.replace(/^[^/].*/, '/$&');

  if (strict) {
    if (path[path.length - 1] === '/') path += 'index.html';
    path = path.replace(/^[^/].*/, '/$&');

    return currentPath === path;
  }

  path = path.replace(/\/index\.html$/, '/');

  if (path === '/') return currentPath === '/index.html';

  path = path.replace(/^[^/].*/, '/$&');

  return currentPath.startsWith(path);
}

function isHomeHelper() {
  return Boolean(this.page.__index);
}

function isPostHelper() {
  return Boolean(this.page.__post);
}

function isPageHelper() {
  return Boolean(this.page.__page);
}

function isArchiveHelper() {
  return Boolean(this.page.archive);
}

function isYearHelper(year) {
  const { page } = this;
  if (!page.archive) return false;

  if (year) {
    return page.year === year;
  }

  return Boolean(page.year);
}

function isMonthHelper(year, month) {
  const { page } = this;
  if (!page.archive) return false;

  if (year) {
    if (month) {
      return page.year === year && page.month === month;
    }

    return page.month === year;
  }

  return Boolean(page.year && page.month);
}

function isCategoryHelper(category) {
  if (category) {
    return this.page.category === category;
  }

  return Boolean(this.page.category);
}

function isTagHelper(tag) {
  if (tag) {
    return this.page.tag === tag;
  }

  return Boolean(this.page.tag);
}

exports.current = isCurrentHelper;
exports.home = isHomeHelper;
exports.post = isPostHelper;
exports.page = isPageHelper;
exports.archive = isArchiveHelper;
exports.year = isYearHelper;
exports.month = isMonthHelper;
exports.category = isCategoryHelper;
exports.tag = isTagHelper;


'use strict';

describe('Core', () => {
  require('./hexo');
  require('./load_config');
  require('./load_database');
  require('./load_plugins');
  require('./locals');
  require('./multi_config_path');
  require('./post');
  require('./render');
  require('./router');
  require('./scaffold');
  require('./update_package');
});


'use strict';

exports.Console = require('./console');
exports.Deployer = require('./deployer');
exports.Filter = require('./filter');
exports.Generator = require('./generator');
exports.Helper = require('./helper');
exports.Migrator = require('./migrator');
exports.Processor = require('./processor');
exports.Renderer = require('./renderer');
exports.Tag = require('./tag');


keep keep keep add keep keep keep keep keep

n8n Workflow Automation Tool

concurrently -k -n "TypeScript,Node" -c "yellow.bold,cyan.bold" "npm run watch" "nodemon"

echo "Building project..." && rm -rf dist && tsc -b && oclif-dev manifest

tslint --fix -p tsconfig.json -c tslint.json

automate automation IaaS iPaaS n8n workflow


# n8n with PostgreSQL

Starts n8n with PostgreSQL as database.

## Start

To start n8n with PostgreSQL simply start docker-compose by executing the following
command in the current folder.

**IMPORTANT:** But before you do that change the default users and passwords in the [`.env`](.env) file!

```
docker-compose up -d
```

To stop it execute:

```
docker-compose stop
```

## Configuration

The default name of the database, user and password for PostgreSQL can be changed in the [`.env`](.env) file in the current directory.


import {
	OptionsWithUri,
} from 'request';

import {
	IExecuteFunctions,
	IExecuteSingleFunctions,
	ILoadOptionsFunctions,
} from 'n8n-core';

import {
	IDataObject, NodeApiError,
} from 'n8n-workflow';

export async function gotifyApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, path: string, body: any = {}, qs: IDataObject = {}, uri?: string | undefined, option = {}): Promise<any> { // tslint:disable-line:no-any

	const credentials = this.getCredentials('gotifyApi') as IDataObject;

	const options: OptionsWithUri = {
		method,
		headers: {
			'X-Gotify-Key': (method === 'POST') ? credentials.appApiToken : credentials.clientApiToken,
			accept: 'application/json',
		},
		body,
		qs,
		uri: uri || `${credentials.url}${path}`,
		json: true,
	};
	try {
		if (Object.keys(body).length === 0) {
			delete options.body;
		}

		//@ts-ignore
		return await this.helpers.request.call(this, options);
	} catch (error) {
		throw new NodeApiError(this.getNode(), error);
	}
}

export async function gotifyApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, propertyName: string, method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any

	const returnData: IDataObject[] = [];

	let responseData;
	let uri: string | undefined;
	query.limit = 100;
	do {
		responseData = await gotifyApiRequest.call(this, method, endpoint, body, query, uri);
		if (responseData.paging.next) {
			uri = responseData.paging.next;
		}
		returnData.push.apply(returnData, responseData[propertyName]);
	} while (
		responseData.paging.next
	);

	return returnData;
}


import {
	ICredentialType,
	NodePropertyTypes,
} from 'n8n-workflow';

export class NextCloudOAuth2Api implements ICredentialType {
	name = 'nextCloudOAuth2Api';
	extends = [
		'oAuth2Api',
	];
	displayName = 'NextCloud OAuth2 API';
	documentationUrl = 'nextCloud';
	properties = [
		{
			displayName: 'Web DAV URL',
			name: 'webDavUrl',
			type: 'string' as NodePropertyTypes,
			placeholder: 'https://nextcloud.example.com/remote.php/webdav',
			default: '',
		},
		{
			displayName: 'Authorization URL',
			name: 'authUrl',
			type: 'string' as NodePropertyTypes,
			default: 'https://nextcloud.example.com/apps/oauth2/authorize',
			required: true,
		},
		{
			displayName: 'Access Token URL',
			name: 'accessTokenUrl',
			type: 'string' as NodePropertyTypes,
			default: 'https://nextcloud.example.com/apps/oauth2/api/v1/token',
			required: true,
		},
		{
			displayName: 'Scope',
			name: 'scope',
			type: 'hidden' as NodePropertyTypes,
			default: '',
		},
		{
			displayName: 'Auth URI Query Parameters',
			name: 'authQueryParameters',
			type: 'hidden' as NodePropertyTypes,
			default: '',
		},
		{
			displayName: 'Authentication',
			name: 'authentication',
			type: 'hidden' as NodePropertyTypes,
			default: 'body',
		},
	];
}


n8n Workflow Automation Tool


import {
	INodeProperties,
} from 'n8n-workflow';

export const checklistItemOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'checklistItem',
				],
			},
		},
		options: [
			{
				name: 'Create',
				value: 'create',
				description: 'Create a checklist item',
			},
			{
				name: 'Delete',
				value: 'delete',
				description: 'Delete a checklist item',
			},
			{
				name: 'Update',
				value: 'update',
				description: 'Update a checklist item',
			},
		],
		default: 'create',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const checklistItemFields = [

	/* -------------------------------------------------------------------------- */
	/*                                checklistItem:create                        */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Checklist ID',
		name: 'checklist',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklistItem',
				],
				operation: [
					'create',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Name',
		name: 'name',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklistItem',
				],
				operation: [
					'create',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Additional Fields',
		name: 'additionalFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'checklistItem',
				],
				operation: [
					'create',
				],
			},
		},
		options: [
			{
				displayName: 'Assignee ID',
				name: 'assignee',
				type: 'string',
				default: '',
			},
		],
	},

	/* -------------------------------------------------------------------------- */
	/*                                checklistItem:delete                        */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Checklist ID',
		name: 'checklist',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklistItem',
				],
				operation: [
					'delete',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Checklist Item ID',
		name: 'checklistItem',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklistItem',
				],
				operation: [
					'delete',
				],
			},
		},
		required: true,
	},

	/* -------------------------------------------------------------------------- */
	/*                                checklistItem:update                        */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Checklist ID',
		name: 'checklist',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklistItem',
				],
				operation: [
					'update',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Checklist Item ID',
		name: 'checklistItem',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklistItem',
				],
				operation: [
					'update',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Update Fields',
		name: 'updateFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'checklistItem',
				],
				operation: [
					'update',
				],
			},
		},
		options: [
			{
				displayName: 'Assignee ID',
				name: 'assignee',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Name',
				name: 'name',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Parent Checklist Item ID',
				name: 'parent',
				type: 'string',
				default: '',
				description: 'Checklist item that you want to nest the target checklist item underneath.',
			},
			{
				displayName: 'Resolved',
				name: 'resolved',
				type: 'boolean',
				default: false,
			},
		],
	},
] as INodeProperties[];


import {
	INodeProperties,
} from 'n8n-workflow';

export const portfolioCompanyOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'portfolioCompany',
				],
			},
		},
		options: [
			{
				name: 'Add',
				value: 'add',
				description: 'Add a company to portfolio',
			},
			{
				name: 'Get All',
				value: 'getAll',
				description: 'Get all companies in a portfolio',
			},
			{
				name: 'Remove',
				value: 'remove',
				description: 'Remove a company from portfolio',
			},
		],
		default: 'add',
	},
] as INodeProperties[];

export const portfolioCompanyFields = [
	{
		displayName: 'Portfolio ID',
		name: 'portfolioId',
		type: 'string',
		required: true,
		default: '',
		displayOptions: {
			show: {
				resource: [
					'portfolioCompany',
				],
				operation: [
					'getAll',
					'add',
					'remove',
				],
			},
		},
	},
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				resource: [
					'portfolioCompany',
				],
				operation: [
					'getAll',
				],
			},
		},
		default: false,
		description: 'If all results should be returned or only up to a given limit.',
	},
	{
		displayName: 'Limit',
		name: 'limit',
		type: 'number',
		displayOptions: {
			show: {
				resource: [
					'portfolioCompany',
				],
				operation: [
					'getAll',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 100,
		},
		default: 100,
		description: 'Number of results to return.',
	},
	{
		displayName: 'Filters',
		name: 'filters',
		displayOptions: {
			show: {
				resource: [
					'portfolioCompany',
				],
				operation: [
					'getAll',
				],
			},
		},
		type: 'collection',
		placeholder: 'Add Filter',
		default: {},
		options: [
			{
				displayName: 'Grade',
				name: 'grade',
				type: 'string',
				placeholder: '',
				default: '',
				description: 'Company score grade filter',
			},
			{
				displayName: 'Industry',
				name: 'industry',
				type: 'string',
				placeholder: '',
				default: '',
				description: 'Industry filter',
			},
			{
				displayName: 'Issue Type',
				name: 'issueType',
				type: 'string',
				placeholder: '',
				description: 'Issue type filter',
				default: '',
			},
			{
				displayName: 'Status',
				name: 'status',
				type: 'options',
				options: [
					{
						name: 'Active',
						value: 'active',
					},
					{
						name: 'Inactive',
						value: 'inactive',
					},
				],
				default: '',
			},
			{
				displayName: 'Vulnerability',
				name: 'vulnerability',
				type: 'string',
				placeholder: '',
				description: 'CVE vulnerability filter',
				default: '',
			},
		],
	},
	{
		displayName: 'Domain',
		name: 'domain',
		type: 'string',
		required: true,
		default: '',
		displayOptions: {
			show: {
				resource: [
					'portfolioCompany',
				],
				operation: [
					'add',
					'remove',
				],
			},
		},
		description: 'Company\'s domain name',
	},

] as INodeProperties[];