<commit_before>/* ========================================================================
 * Bootstrap: tooltip.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#affix
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ========================================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ======================================================================== */

+function ($) { "use strict";

  // TOOLTIP PUBLIC CLASS DEFINITION
  // ===============================

  var Tooltip = function (element, options) {
    this.type       =
    this.options    =
    this.enabled    =
    this.timeout    =
    this.hoverState =
    this.$element   = null

    this.init('tooltip', element, options)
  }

  Tooltip.DEFAULTS = {
    animation: true
  , placement: 'top'
  , selector: false
  , template: '

'
  , trigger: 'hover focus'
  , title: ''
  , delay: 0
  , html: false
  , container: false
  }

  Tooltip.prototype.init = function (type, element, options) {
    this.enabled  = true
    this.type     = type
    this.$element = $(element)
    this.options  = this.getOptions(options)

    var triggers = this.options.trigger.split(' ')

    for (var i = triggers.length; i--;) {
      var trigger = triggers[i]

      if (trigger == 'click') {
        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
      } else if (trigger != 'manual') {
        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'
        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'

        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
      }
    }

    this.options.selector ?
      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
      this.fixTitle()
  }

  Tooltip.prototype.getDefaults = function () {
    return Tooltip.DEFAULTS
  }

  Tooltip.prototype.getOptions = function (options) {
    options = $.extend({}, this.getDefaults(), this.$element.data(), options)

    if (options.delay && typeof options.delay == 'number') {
      options.delay = {
        show: options.delay
      , hide: options.delay
      }
    }

    return options
  }

  Tooltip.prototype.getDelegateOptions = function () {
    var options  = {}
    var defaults = this.getDefaults()

    this._options && $.each(this._options, function (key, value) {
      if (defaults[key] != value) options[key] = value
    })

    return options
  }

  Tooltip.prototype.enter = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)

    clearTimeout(self.timeout)

    if (!self.options.delay || !self.options.delay.show) return self.show()

    self.hoverState = 'in'
    self.timeout    = setTimeout(function () {
      if (self.hoverState == 'in') self.show()
    }, self.options.delay.show)
  }

  Tooltip.prototype.leave = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)

    clearTimeout(self.timeout)

    if (!self.options.delay || !self.options.delay.hide) return self.hide()

    self.hoverState = 'out'
    self.timeout    = setTimeout(function () {
      if (self.hoverState == 'out') self.hide()
    }, self.options.delay.hide)
  }

  Tooltip.prototype.show = function () {
    var e = $.Event('show.bs.'+ this.type)

    if (this.hasContent() && this.enabled) {
      this.$element.trigger(e)

      if (e.isDefaultPrevented()) return

      var $tip = this.tip()

      this.setContent()

      if (this.options.animation) $tip.addClass('fade')

      var placement = typeof this.options.placement == 'function' ?
        this.options.placement.call(this, $tip[0], this.$element[0]) :
        this.options.placement

      var autoToken = /\s?auto?\s?/i
      var autoPlace = autoToken.test(placement)
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'

      $tip
        .detach()
        .css({ top: 0, left: 0, display: 'block' })
        .addClass(placement)

      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)

      var pos          = this.getPosition()
      var actualWidth  = $tip[0].offsetWidth
      var actualHeight = $tip[0].offsetHeight

      if (autoPlace) {
        var $parent = this.$element.parent()

        var orgPlacement = placement
        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop
        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()
        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left

        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :
                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :
                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :
                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :
                    placement

        $tip
          .removeClass(orgPlacement)
          .addClass(placement)
      }

      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)

      this.applyPlacement(calculatedOffset, placement)
      this.$element.trigger('shown.bs.' + this.type)
    }
  }

  Tooltip.prototype.applyPlacement = function(offset, placement) {
    var replace
    var $tip   = this.tip()
    var width  = $tip[0].offsetWidth
    var height = $tip[0].offsetHeight

    // manually read margins because getBoundingClientRect includes difference
    var marginTop = parseInt($tip.css('margin-top'), 10)
    var marginLeft = parseInt($tip.css('margin-left'), 10)

    // we must check for NaN for ie 8/9
    if (isNaN(marginTop))  marginTop  = 0
    if (isNaN(marginLeft)) marginLeft = 0

    offset.top  = offset.top  + marginTop
    offset.left = offset.left + marginLeft

    $tip
      .offset(offset)
      .addClass('in')

    // check to see if placing tip in new offset caused the tip to resize itself
    var actualWidth  = $tip[0].offsetWidth
    var actualHeight = $tip[0].offsetHeight

    if (placement == 'top' && actualHeight != height) {
      replace = true
      offset.top = offset.top + height - actualHeight
    }

    if (/bottom|top/.test(placement)) {
      var delta = 0

      if (offset.left < 0) {
        delta       = offset.left * -2
        offset.left = 0

        $tip.offset(offset)

        actualWidth  = $tip[0].offsetWidth
        actualHeight = $tip[0].offsetHeight
      }

      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
    } else {
      this.replaceArrow(actualHeight - height, actualHeight, 'top')
    }

    if (replace) $tip.offset(offset)
  }

  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {
    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
  }

  Tooltip.prototype.setContent = function () {
    var $tip  = this.tip()
    var title = this.getTitle()

    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
    $tip.removeClass('fade in top bottom left right')
  }

  Tooltip.prototype.hide = function () {
    var that = this
    var $tip = this.tip()
    var e    = $.Event('hide.bs.' + this.type)

    function complete() { $tip.detach() }

    this.$element.trigger(e)

    if (e.isDefaultPrevented()) return

    $tip.removeClass('in')

    $.support.transition && this.$tip.hasClass('fade') ?
      $tip
        .one($.support.transition.end, complete)
        .emulateTransitionEnd(150) :
      complete()

    this.$element.trigger('hidden.bs.' + this.type)

    return this
  }

  Tooltip.prototype.fixTitle = function () {
    var $e = this.$element
    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
    }
  }

  Tooltip.prototype.hasContent = function () {
    return this.getTitle()
  }

  Tooltip.prototype.getPosition = function () {
    var el = this.$element[0]
    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
      width: el.offsetWidth
    , height: el.offsetHeight
    }, this.$element.offset())
  }

  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
  }

  Tooltip.prototype.getTitle = function () {
    var title
    var $e = this.$element
    var o  = this.options

    title = $e.attr('data-original-title')
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

    return title
  }

  Tooltip.prototype.tip = function () {
    return this.$tip = this.$tip || $(this.options.template)
  }

  Tooltip.prototype.arrow = function () {
    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
  }

  Tooltip.prototype.validate = function () {
    if (!this.$element[0].parentNode) {
      this.hide()
      this.$element = null
      this.options  = null
    }
  }

  Tooltip.prototype.enable = function () {
    this.enabled = true
  }

  Tooltip.prototype.disable = function () {
    this.enabled = false
  }

  Tooltip.prototype.toggleEnabled = function () {
    this.enabled = !this.enabled
  }

  Tooltip.prototype.toggle = function (e) {
    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  }

  Tooltip.prototype.destroy = function () {
    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
  }

  // TOOLTIP PLUGIN DEFINITION
  // =========================

  var old = $.fn.tooltip

  $.fn.tooltip = function (option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.tooltip')
      var options = typeof option == 'object' && option

      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.tooltip.Constructor = Tooltip

  // TOOLTIP NO CONFLICT
  // ===================

  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
    return this
  }

}(window.jQuery);
<commit_msg>fix comment in tooltip<commit_after>/* ========================================================================
 * Bootstrap: tooltip.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#tooltip
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ========================================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ======================================================================== */

+function ($) { "use strict";

  // TOOLTIP PUBLIC CLASS DEFINITION
  // ===============================

  var Tooltip = function (element, options) {
    this.type       =
    this.options    =
    this.enabled    =
    this.timeout    =
    this.hoverState =
    this.$element   = null

    this.init('tooltip', element, options)
  }

  Tooltip.DEFAULTS = {
    animation: true
  , placement: 'top'
  , selector: false
  , template: '

'
  , trigger: 'hover focus'
  , title: ''
  , delay: 0
  , html: false
  , container: false
  }

  Tooltip.prototype.init = function (type, element, options) {
    this.enabled  = true
    this.type     = type
    this.$element = $(element)
    this.options  = this.getOptions(options)

    var triggers = this.options.trigger.split(' ')

    for (var i = triggers.length; i--;) {
      var trigger = triggers[i]

      if (trigger == 'click') {
        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
      } else if (trigger != 'manual') {
        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'
        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'

        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
      }
    }

    this.options.selector ?
      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
      this.fixTitle()
  }

  Tooltip.prototype.getDefaults = function () {
    return Tooltip.DEFAULTS
  }

  Tooltip.prototype.getOptions = function (options) {
    options = $.extend({}, this.getDefaults(), this.$element.data(), options)

    if (options.delay && typeof options.delay == 'number') {
      options.delay = {
        show: options.delay
      , hide: options.delay
      }
    }

    return options
  }

  Tooltip.prototype.getDelegateOptions = function () {
    var options  = {}
    var defaults = this.getDefaults()

    this._options && $.each(this._options, function (key, value) {
      if (defaults[key] != value) options[key] = value
    })

    return options
  }

  Tooltip.prototype.enter = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)

    clearTimeout(self.timeout)

    if (!self.options.delay || !self.options.delay.show) return self.show()

    self.hoverState = 'in'
    self.timeout    = setTimeout(function () {
      if (self.hoverState == 'in') self.show()
    }, self.options.delay.show)
  }

  Tooltip.prototype.leave = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)

    clearTimeout(self.timeout)

    if (!self.options.delay || !self.options.delay.hide) return self.hide()

    self.hoverState = 'out'
    self.timeout    = setTimeout(function () {
      if (self.hoverState == 'out') self.hide()
    }, self.options.delay.hide)
  }

  Tooltip.prototype.show = function () {
    var e = $.Event('show.bs.'+ this.type)

    if (this.hasContent() && this.enabled) {
      this.$element.trigger(e)

      if (e.isDefaultPrevented()) return

      var $tip = this.tip()

      this.setContent()

      if (this.options.animation) $tip.addClass('fade')

      var placement = typeof this.options.placement == 'function' ?
        this.options.placement.call(this, $tip[0], this.$element[0]) :
        this.options.placement

      var autoToken = /\s?auto?\s?/i
      var autoPlace = autoToken.test(placement)
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'

      $tip
        .detach()
        .css({ top: 0, left: 0, display: 'block' })
        .addClass(placement)

      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)

      var pos          = this.getPosition()
      var actualWidth  = $tip[0].offsetWidth
      var actualHeight = $tip[0].offsetHeight

      if (autoPlace) {
        var $parent = this.$element.parent()

        var orgPlacement = placement
        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop
        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()
        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left

        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :
                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :
                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :
                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :
                    placement

        $tip
          .removeClass(orgPlacement)
          .addClass(placement)
      }

      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)

      this.applyPlacement(calculatedOffset, placement)
      this.$element.trigger('shown.bs.' + this.type)
    }
  }

  Tooltip.prototype.applyPlacement = function(offset, placement) {
    var replace
    var $tip   = this.tip()
    var width  = $tip[0].offsetWidth
    var height = $tip[0].offsetHeight

    // manually read margins because getBoundingClientRect includes difference
    var marginTop = parseInt($tip.css('margin-top'), 10)
    var marginLeft = parseInt($tip.css('margin-left'), 10)

    // we must check for NaN for ie 8/9
    if (isNaN(marginTop))  marginTop  = 0
    if (isNaN(marginLeft)) marginLeft = 0

    offset.top  = offset.top  + marginTop
    offset.left = offset.left + marginLeft

    $tip
      .offset(offset)
      .addClass('in')

    // check to see if placing tip in new offset caused the tip to resize itself
    var actualWidth  = $tip[0].offsetWidth
    var actualHeight = $tip[0].offsetHeight

    if (placement == 'top' && actualHeight != height) {
      replace = true
      offset.top = offset.top + height - actualHeight
    }

    if (/bottom|top/.test(placement)) {
      var delta = 0

      if (offset.left < 0) {
        delta       = offset.left * -2
        offset.left = 0

        $tip.offset(offset)

        actualWidth  = $tip[0].offsetWidth
        actualHeight = $tip[0].offsetHeight
      }

      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
    } else {
      this.replaceArrow(actualHeight - height, actualHeight, 'top')
    }

    if (replace) $tip.offset(offset)
  }

  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {
    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
  }

  Tooltip.prototype.setContent = function () {
    var $tip  = this.tip()
    var title = this.getTitle()

    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
    $tip.removeClass('fade in top bottom left right')
  }

  Tooltip.prototype.hide = function () {
    var that = this
    var $tip = this.tip()
    var e    = $.Event('hide.bs.' + this.type)

    function complete() { $tip.detach() }

    this.$element.trigger(e)

    if (e.isDefaultPrevented()) return

    $tip.removeClass('in')

    $.support.transition && this.$tip.hasClass('fade') ?
      $tip
        .one($.support.transition.end, complete)
        .emulateTransitionEnd(150) :
      complete()

    this.$element.trigger('hidden.bs.' + this.type)

    return this
  }

  Tooltip.prototype.fixTitle = function () {
    var $e = this.$element
    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
    }
  }

  Tooltip.prototype.hasContent = function () {
    return this.getTitle()
  }

  Tooltip.prototype.getPosition = function () {
    var el = this.$element[0]
    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
      width: el.offsetWidth
    , height: el.offsetHeight
    }, this.$element.offset())
  }

  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
  }

  Tooltip.prototype.getTitle = function () {
    var title
    var $e = this.$element
    var o  = this.options

    title = $e.attr('data-original-title')
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

    return title
  }

  Tooltip.prototype.tip = function () {
    return this.$tip = this.$tip || $(this.options.template)
  }

  Tooltip.prototype.arrow = function () {
    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
  }

  Tooltip.prototype.validate = function () {
    if (!this.$element[0].parentNode) {
      this.hide()
      this.$element = null
      this.options  = null
    }
  }

  Tooltip.prototype.enable = function () {
    this.enabled = true
  }

  Tooltip.prototype.disable = function () {
    this.enabled = false
  }

  Tooltip.prototype.toggleEnabled = function () {
    this.enabled = !this.enabled
  }

  Tooltip.prototype.toggle = function (e) {
    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  }

  Tooltip.prototype.destroy = function () {
    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
  }

  // TOOLTIP PLUGIN DEFINITION
  // =========================

  var old = $.fn.tooltip

  $.fn.tooltip = function (option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.tooltip')
      var options = typeof option == 'object' && option

      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.tooltip.Constructor = Tooltip

  // TOOLTIP NO CONFLICT
  // ===================

  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
    return this
  }

}(window.jQuery);
<|endoftext|>


<commit_before>import React from 'react'
import styled from 'styled-components'
import { Link } from 'gatsby'
import ExternalLink from './ExternalLink'

import profilePic from '../images/profile-pic.png'

const Container = styled.div`
  margin: 60px auto;
  padding: 0px 32px;

  @media (min-width: 768px) {
    margin: 80px auto;
    display: flex;
  }
`

const Sidebar = styled.div`
  margin: 0px 24px 0px 80px;
  position: fixed;
  width: 180px;
`

const Body = styled.div`
  font-size: 18px;

  @media (min-width: 768px) {
    margin-left: 284px;
    padding: 0px 1rem;
  }
`

const ImgLink = styled(Link)`
  background-image: none;
`

const Img = styled.img`
  width: 120px;
  height: 120px;
  border-radius: 50%;
`

const StyledLink = styled(Link)``

const StyledExternalLink = styled(ExternalLink)``

export default ({ children }) => (
  <Container>
    <Sidebar>
      <ImgLink to="/">

      </ImgLink>

      {/*

       */}

    </Sidebar>
    {children}
  </Container>
)
<commit_msg>Fix spacing on mobile<commit_after>import React from 'react'
import styled from 'styled-components'
import { Link } from 'gatsby'
import ExternalLink from './ExternalLink'

import profilePic from '../images/profile-pic.png'

const Container = styled.div`
  margin: 60px auto;
  padding: 0px 32px;

  @media (min-width: 768px) {
    margin: 80px auto;
    display: flex;
  }
`

const Sidebar = styled.div`
  width: 120px;

  @media (min-width: 768px) {
    margin: 0px 48px 0px 80px;
    position: fixed;
  }
`

const Body = styled.div`
  font-size: 18px;

  @media (min-width: 768px) {
    margin-left: 248px;
    padding: 0px 1rem;
  }
`

const ImgLink = styled(Link)`
  background-image: none;
`

const Img = styled.img`
  width: 120px;
  height: 120px;
  border-radius: 50%;
`

const StyledLink = styled(Link)``

const StyledExternalLink = styled(ExternalLink)``

export default ({ children }) => (
  <Container>
    <Sidebar>
      <ImgLink to="/">

      </ImgLink>

      {/*

       */}

    </Sidebar>
    {children}
  </Container>
)
<|endoftext|>


<commit_before>/*jslint indent: 2*/
/*global require: true, module: true*/
(function () {
  'use strict';

  var InvalidInputError = require('./input-error.js'),
    transformationFunctions = require('./transforms'),
    transformationKeys = require('./keys'),
    regex =  /^(\d*)d(\d+|\%)(([\+\-\/\*bw])(\d+))?(([\+\-\/\*])(\d+|(\d*)d(\d+|\%)(([\+\-\/\*bw])(\d+))?))*$/,
    roll;

  roll = function (random) {
    this.random = random || function () {
      return Math.random();
    };
  };

  roll.prototype.validate = function (s) {
    return regex.test(s);
  };

  roll.prototype.parse = function (s) {
    if (!this.validate(s)) {
      throw new InvalidInputError(s);
    }

    var match = regex.exec(s),
      quantity = match[1], // 2d20+3 => 2
      sides = match[2], // 2d20+3 => 20
      hasTransformation = !!match[3], // 2d20+3 => true
      operator,
      transformationParameter,
      transforms = [],
      opIndex = 0,
      segLength,
      segments = s.split(/[\+\-\/\*]/);

      for (var seg = 1; seg < segments.length; seg++){
        opIndex += segments[seg - 1].length;
        operator = s[opIndex]; // 2d20+3 => "+"
        opIndex += 1;
        transformationParameter = segments[seg]; // 2d20+3 => 3
        if (transformationParameter.indexOf('d') > -1){
          transforms.push(transformationKeys[operator](parseInt(this.roll(transformationParameter).result, 10)));
        } else {
          transforms.push(transformationKeys[operator](parseInt(transformationParameter, 10)));
        }
      }

    return {
      quantity: quantity ? parseInt(quantity, 10) : 1,
      sides: sides === '%' ? 100 : parseInt(sides, 10),
      transformations: hasTransformation ? transforms : ['sum'],
      toString: function () {
        return s;
      }
    };
  };

  roll.prototype.roll = function (input) {
    if (!input) {
      throw new InvalidInputError();
    } else if (typeof input === 'string') {
      input = this.parse(input);
    } else if (input instanceof Array) {
      var resultset = [];
      for (var i in input){
       resultset.push(this.roll(input[i]));
      }
      return resultset;
    }

    var rolled = [],
     calculations = [];

    while (rolled.length < input.quantity) {
      rolled.push(Math.floor((this.random() * input.sides) + 1));
    }

    calculations = input.transformations.reduce(function (previous, transformation) {
      var transformationFunction,
        transformationAdditionalParameter;

      if (typeof transformation === 'function') { // lets you pass something custom in
        transformationFunction = transformation;
      } else if (typeof transformation === 'string') { // "sum"
        transformationFunction = transformationFunctions[transformation];
      } else if (transformation instanceof Array) { // ["add", 3]
        transformationFunction = transformationFunctions[transformation[0]]; // fn for "add"
        transformationAdditionalParameter = transformation[1]; // 3
      }

      previous.unshift(transformationFunction(previous[0], transformationAdditionalParameter));
      return previous;
    }, [rolled]);

    return {
      input: input,
      calculations: calculations,
      rolled: calculations[calculations.length - 1],
      result: calculations[0]
    };
  };

  module.exports = roll;
  module.exports.InvalidInputError = InvalidInputError;

}());

<commit_msg>b/w operation with no mod needs special handling<commit_after>/*jslint indent: 2*/
/*global require: true, module: true*/
(function () {
  'use strict';

  var InvalidInputError = require('./input-error.js'),
    transformationFunctions = require('./transforms'),
    transformationKeys = require('./keys'),
    regex =  /^(\d*)d(\d+|\%)(([\+\-\/\*bw])(\d+))?(([\+\-\/\*])(\d+|(\d*)d(\d+|\%)(([\+\-\/\*bw])(\d+))?))*$/,
    roll;

  roll = function (random) {
    this.random = random || function () {
      return Math.random();
    };
  };

  roll.prototype.validate = function (s) {
    return regex.test(s);
  };

  roll.prototype.parse = function (s) {
    if (!this.validate(s)) {
      throw new InvalidInputError(s);
    }

    var match = regex.exec(s),
      quantity = match[1], // 2d20+3 => 2
      sides = match[2], // 2d20+3 => 20
      hasTransformation = !!match[3], // 2d20+3 => true
      operator,
      transformationParameter,
      transforms = [],
      opIndex = 0,
      segLength,
      segments = s.split(/[\+\-\/\*]/);

      for (var seg = 1; seg < segments.length; seg++){
        opIndex += segments[seg - 1].length;
        operator = s[opIndex]; // 2d20+3 => "+"
        opIndex += 1;
        transformationParameter = segments[seg]; // 2d20+3 => 3
        if (transformationParameter.indexOf('d') > -1){
          transforms.push(transformationKeys[operator](parseInt(this.roll(transformationParameter).result, 10)));
        } else {
          transforms.push(transformationKeys[operator](parseInt(transformationParameter, 10)));
        }
      }

    return {
      quantity: quantity ? parseInt(quantity, 10) : 1,
      sides: sides === '%' ? 100 : parseInt(sides, 10),
      transformations: hasTransformation ? transforms.length > 1 ? transforms : transformationKeys[match[4]](parseInt(match[5], 10)) : ['sum'],
      toString: function () {
        return s;
      }
    };
  };

  roll.prototype.roll = function (input) {
    if (!input) {
      throw new InvalidInputError();
    } else if (typeof input === 'string') {
      input = this.parse(input);
    } else if (input instanceof Array) {
      var resultset = [];
      for (var i in input){
       resultset.push(this.roll(input[i]));
      }
      return resultset;
    }

    var rolled = [],
     calculations = [];

    while (rolled.length < input.quantity) {
      rolled.push(Math.floor((this.random() * input.sides) + 1));
    }

    calculations = input.transformations.reduce(function (previous, transformation) {
      var transformationFunction,
        transformationAdditionalParameter;

      if (typeof transformation === 'function') { // lets you pass something custom in
        transformationFunction = transformation;
      } else if (typeof transformation === 'string') { // "sum"
        transformationFunction = transformationFunctions[transformation];
      } else if (transformation instanceof Array) { // ["add", 3]
        transformationFunction = transformationFunctions[transformation[0]]; // fn for "add"
        transformationAdditionalParameter = transformation[1]; // 3
      }

      previous.unshift(transformationFunction(previous[0], transformationAdditionalParameter));
      return previous;
    }, [rolled]);

    return {
      input: input,
      calculations: calculations,
      rolled: calculations[calculations.length - 1],
      result: calculations[0]
    };
  };

  module.exports = roll;
  module.exports.InvalidInputError = InvalidInputError;

}());

<|endoftext|>


<commit_before>/*jshint laxcomma:true, smarttabs: true */
/**
 * DESCRIPTION
 * @module NAME
 * @author
 * @requires command
 * @requires prime
 **/
var  command = require( './command' ) // this is command
   , prime = require( 'prime' ) // custom prime
   , isFunction = require("mout/lang/isFunction")
   , nopt = require('nopt')
   , domain = require("domain")
   , os = require("os")
   , fs = require("fs")
   , path = require("path")
   , abbrev = require("abbrev")
   , util = require("util")
   , chalk = require("chalk")
   , commands = require("./commands")
   , command_list
   , shorthands
   , parsed
   , clidomain
   , colors
   , help;                         // The primary Class exports from the module

colors = ['red', 'blue','green', 'yellow','bold', 'grey', 'dim', 'black', 'magenta']
clidomain = domain.create()
clidomain.on('error', function(err, domn ){
  console.log( chalk.red( util.format( "%s:", err.name) ), chalk.bold( err.message ) )
  if( parsed && parsed.traceback ){
	console.log( chalk.red( err.stack ) )
  } else {
  	console.log('use --traceback for full stacktrace')
  }

  return err.code ? process.exit( err.code ) : null;
})

exports.use = commands.register.bind( commands );
exports.remove = commands.unregister.bind( commands );

// primary flags
opts = {
	"help":Boolean
	,version:Boolean
	,traceback: Boolean
};

// flag alias
shorthands = {
	'h':['--help']
	,'v':['--version']
};

exports.Command = command;
exports.Class = prime;

Object.defineProperties( exports,{
	list:{
		get: function(){
			return Object.keys( commands )
		}
	}
});

exports.commands = commands
exports.reset = commands.reset.bind( commands );

colors.forEach( function( color ){
	exports[color] = chalk[color].bind( chalk )
})
exports.run = function( ){
	parsed = nopt( opts, shorthands );

	// pull out the first non-flag argument
	command = parsed.argv.remain.shift();
	// did the try to use the help command directly?
	help = !!parsed.help
	if( help || command == 'help' || command == null ){
		command = ( command == "help" || command == null ) ? parsed.argv.remain.shift() : command
		// allow for abbreviated commands
		return clidomain.run(function(){
			console.log( commands.help.run( command ) )
		});
	}

	if(commands.hasOwnProperty( command ) ) {
		return clidomain.run(function(){
		  commands[command].run(null)
		})
	}
	console.error('unknown command %s', command )
	console.log("know commands: %s ", Object.keys( commands ).join(', ') )
	process.exit(0);
}
<commit_msg>remove a douple console write<commit_after>/*jshint laxcomma:true, smarttabs: true */
/**
 * DESCRIPTION
 * @module NAME
 * @author
 * @requires command
 * @requires prime
 **/
var  command = require( './command' ) // this is command
   , prime = require( 'prime' ) // custom prime
   , isFunction = require("mout/lang/isFunction")
   , nopt = require('nopt')
   , domain = require("domain")
   , os = require("os")
   , fs = require("fs")
   , path = require("path")
   , abbrev = require("abbrev")
   , util = require("util")
   , chalk = require("chalk")
   , commands = require("./commands")
   , command_list
   , shorthands
   , parsed
   , clidomain
   , colors
   , help;                         // The primary Class exports from the module

colors = ['red', 'blue','green', 'yellow','bold', 'grey', 'dim', 'black', 'magenta']
clidomain = domain.create()
clidomain.on('error', function(err, domn ){
  console.log( chalk.red( util.format( "%s:", err.name) ), chalk.bold( err.message ) )
  if( parsed && parsed.traceback ){
	console.log( chalk.red( err.stack ) )
  } else {
  	console.log('use --traceback for full stacktrace')
  }

  return err.code ? process.exit( err.code ) : null;
})

exports.use = commands.register.bind( commands );
exports.remove = commands.unregister.bind( commands );

// primary flags
opts = {
	"help":Boolean
	,version:Boolean
	,traceback: Boolean
};

// flag alias
shorthands = {
	'h':['--help']
	,'v':['--version']
};

exports.Command = command;
exports.Class = prime;

Object.defineProperties( exports,{
	list:{
		get: function(){
			return Object.keys( commands )
		}
	}
});

exports.commands = commands
exports.reset = commands.reset.bind( commands );

colors.forEach( function( color ){
	exports[color] = chalk[color].bind( chalk )
})
exports.run = function( ){
	parsed = nopt( opts, shorthands );

	// pull out the first non-flag argument
	command = parsed.argv.remain.shift();
	// did the try to use the help command directly?
	help = !!parsed.help
	if( help || command == 'help' || command == null ){
		command = ( command == "help" || command == null ) ? parsed.argv.remain.shift() : command
		// allow for abbreviated commands
		return clidomain.run(function(){
			commands.help.run( command )
		});
	}

	if(commands.hasOwnProperty( command ) ) {
		return clidomain.run(function(){
		  commands[command].run(null)
		})
	}
	console.error('unknown command %s', command )
	console.log("know commands: %s ", Object.keys( commands ).join(', ') )
	process.exit(0);
}
<|endoftext|>


<commit_before>var q = require('q'),
    http = require('q-io/http'),
    log = require('./log');

function proxy(req, node, retryCounter) {
    retryCounter = retryCounter || 0;

    // TODO: make number of retries configurable
    var retries = req.retries || 3;

    return http
        .request({
            host: node.host,
            port: node.port,
            method: req.method,
            path: req.path,
            headers: req.headers,
            body: req.data ? [JSON.stringify(req.data)] : req.body
        })
        .catch(function(err) {
            var key = node.host + '_' + node.port;

            log.warn('Proxy to node %s failure: %s', key, err.message);

            if (retryCounter < retries) {
                log.warn('Retrying request to node %s', key);
                return proxy(req, node, retryCounter + 1);
            }

            log.warn('Giving up retrying to node %s, error: %s', key, err.message);
            return q.reject(err);
        });
}

module.exports = proxy;
<commit_msg>proxy: Add 2 sec delay before retry<commit_after>var q = require('q'),
    http = require('q-io/http'),
    log = require('./log');

function proxy(req, node, retryCounter) {
    retryCounter = retryCounter || 0;

    // TODO: make number of retries configurable
    var retries = req.retries || 3;

    return http
        .request({
            host: node.host,
            port: node.port,
            method: req.method,
            path: req.path,
            headers: req.headers,
            body: req.data ? [JSON.stringify(req.data)] : req.body
        })
        .catch(function(err) {
            var key = node.host + '_' + node.port;

            log.warn('Proxy to node %s failure: %s', key, err.message);

            if (retryCounter < retries) {
                log.warn('Retrying request to node %s', key);
                // TODO: make the delay configurable
                return q.delay(2000)
                    .then(function() {
                        return proxy(req, node, retryCounter + 1);
                    });
            }

            log.warn('Giving up retrying to node %s, error: %s', key, err.message);
            return q.reject(err);
        });
}

module.exports = proxy;
<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');
const glob = require('glob');
const svgo = require('svgo');
const merge = require('webpack-merge');
const mkdirp = require('mkdirp');
const loaderUtils = require('loader-utils');
const { RawSource } = require('webpack-sources');
const MultiEntryPlugin = require('webpack/lib/MultiEntryPlugin');

// Helpers
const generateSVG = require('./generate-svg');
const generateStyles = require('./generate-styles');
const { stripVariables, findVariables } = require('./variable-parser');
const formatOptions = require('./options-formatter');

// Errors & Warnings
const {
    OptionsMismatchWarning,
    VariablesNotSupportedInLanguageWarning,
    VariablesNotSupportedWithFragmentsWarning
} = require('./errors');

const plugin = {
    name: 'SVGSpritemapPlugin'
};

module.exports = class SVGSpritemapPlugin {
    constructor(pattern, options) {
        this.options = formatOptions(pattern, options);

        // Dependencies
        this.files = [];
        this.directories = [];
    }

    apply(compiler) {
        compiler.hooks.entryOption.tap(plugin, (context, entry) => {
            const { output: outputOptions } = this.options;

            if ( !outputOptions.svg4everybody ) {
                return;
            }

            // This is a little hacky but there's no other way since Webpack
            // doesn't support virtual files (https://github.com/rmarscher/virtual-module-webpack-plugin)
            const helper = {
                file: fs.readFileSync(path.join(__dirname, 'templates/svg4everybody.template.js'), 'utf8'),
                path: path.join(__dirname, '../svg4everybody-helper.js')
            };

            // Write the helper file to disk
            fs.writeFileSync(helper.path, helper.file.replace('/* PLACEHOLDER */', JSON.stringify(outputOptions.svg4everybody)), 'utf8');

            // Append helper to entry
            const applyEntryPlugin = (entries, name = 'main') => {
                const plugin = new MultiEntryPlugin(context, entries, name);
                plugin.apply(compiler);
            };

            if ( typeof entry === 'string' ) {
                applyEntryPlugin([entry, helper.path]);
            } else if ( Array.isArray(entry) ) {
                if ( !entry.includes(helper.path) ) {
                    applyEntryPlugin([...entry, helper.path]);
                }
            } else if ( typeof entry === 'object' && entry !== null ) {
                Object.keys(entry).forEach((name) => {
                    if ( typeof entry[name] === 'string' ) {
                        applyEntryPlugin([entry[name], helper.path], name);
                    } else if ( Array.isArray(entry[name]) ) {
                        if ( !entry[name].includes(helper.path) ) {
                            applyEntryPlugin([...entry[name], helper.path], name);
                        }
                    } else {
                        throw new Error(`Unsupported sub-entry type for svg4everybody helper: '${typeof entry[name]}'`);
                    }
                });
            } else {
                throw new Error(`Unsupported entry type for svg4everybody helper: '${typeof entry}'`);
            }

            return true;
        });

        // Update dependencies when needed
        compiler.hooks.environment.tap(plugin, this.updateDependencies.bind(this));
        compiler.hooks.watchRun.tap(plugin, this.updateDependencies.bind(this));

        // Generate spritemap
        compiler.hooks.make.tapAsync(plugin, (compilation, callback) => {
            const { sprite: spriteOptions, output: outputOptions, styles: stylesOptions } = this.options;

            // Generate SVG
            generateSVG(this.files, Object.assign(spriteOptions, {
                svgo: outputOptions.svgo
            })).then((spritemap) => {
                if ( !spritemap ) {
                    return callback();
                }

                // Add chunk and asset
                const sourceChunk = compilation.addChunk(outputOptions.chunk.name);
                compilation.assets[outputOptions.filename] = new RawSource(spritemap);
                sourceChunk.files.push(outputOptions.filename);

                if ( spriteOptions.generate.view && !spriteOptions.generate.use ) {
                    compilation.warnings.push(new OptionsMismatchWarning(`Using sprite.generate.view requires sprite.generate.use to be enabled`));
                }

                if ( spriteOptions.generate.use && !spriteOptions.generate.symbol ) {
                    compilation.warnings.push(new OptionsMismatchWarning(`Using sprite.generate.use requires sprite.generate.symbol to be enabled`));
                }

                if ( spriteOptions.generate.title && !spriteOptions.generate.symbol ) {
                    compilation.warnings.push(new OptionsMismatchWarning(`Using sprite.generate.title requires sprite.generate.symbol to be enabled`));
                }

                if ( spriteOptions.generate.symbol === true && spriteOptions.generate.view === true ) {
                    compilation.warnings.push(new OptionsMismatchWarning(`Both sprite.generate.symbol and sprite.generate.view are set to true which will cause identifier conflicts, use a string value (postfix) for either of these options`));
                }

                // Generate styles
                if ( stylesOptions ) {
                    const extension = path.extname(stylesOptions.filename).substring(1).toLowerCase();
                    this.styles = generateStyles(spritemap, {
                        extension: extension,
                        prefix: spriteOptions.prefix,
                        postfix: {
                            symbol: spriteOptions.generate.symbol,
                            view: spriteOptions.generate.view
                        },
                        format: {
                            type: stylesOptions.format,
                            publicPath: (() => {
                                const hashes = this.getSpritemapHashes(compilation);
                                const filename = this.hashFilename(outputOptions.filename, hashes);

                                return `${compilation.outputOptions.publicPath || '/'}${filename}`;
                            })()
                        },
                        variables: stylesOptions.variables
                    });

                    // Emit a warning when variables are detected while the language doesn't support it
                    if ( !['scss', 'sass'].includes(extension) && findVariables(spritemap).length ) {
                        compilation.warnings.push(new VariablesNotSupportedInLanguageWarning(extension));
                    }

                    // Emit a warning when variables are detected while the stylesOptions.format is set to 'fragment'
                    if ( stylesOptions.format === 'fragment' && findVariables(spritemap).length ) {
                        compilation.warnings.push(new VariablesNotSupportedWithFragmentsWarning());
                    }

                    if ( stylesOptions.format === 'fragment' && !spriteOptions.generate.view ) {
                        compilation.warnings.push(new OptionsMismatchWarning(`Using styles.format with value 'fragment' in combination with sprite.generate.view with value false will result in CSS fragments not working correctly`));
                    }

                    // Include warnings received from the style formatters
                    if ( this.styles.warnings.length ) {
                        compilation.warnings = [...compilation.warnings, ...this.styles.warnings];
                    }

                    // Write the styles file before compilation starts to make sure the files
                    // are written to disk before other plugins/loaders (e.g. mini-css-extract-plugin) can use them
                    this.stylesType = this.getStylesType(this.styles.content, stylesOptions.filename);
                    this.writeStylesToDisk(this.styles.content, this.stylesType);

                    if ( typeof this.styles !== 'undefined' && this.stylesType === 'asset' ) {
                        compilation.assets[stylesOptions.filename] = new RawSource(this.styles.content);
                    }
                }

                // Overwrite the spritemap chunk hash to the custom SVG contenthash to make sure
                // webpack notices the changes and prints the stats output again
                compilation.hooks.chunkHash.tap(plugin, (chunk, chunkHash) => {
                    const { output: outputOptions } = this.options;

                    if ( chunk.name !== outputOptions.chunk.name || !spritemap ) {
                        return;
                    }

                    chunkHash.digest = () => this.getContentHash(spritemap);
                });

                // Optimize spritemap SVG/filename
                compilation.hooks.optimizeAssets.tapAsync(plugin, (assets, callback) => {
                    const { output: outputOptions, sprite: spriteOptions } = this.options;

                    // Strip variables from spritemap SVG
                    const stripped = stripVariables(compilation.assets[outputOptions.filename].source());
                    compilation.assets[outputOptions.filename] = new RawSource(stripped);

                    // Rewrite the source chunk files hashes
                    const hashes = this.getSpritemapHashes(compilation);
                    const sourceChunk = compilation.namedChunks.get(outputOptions.chunk.name);
                    sourceChunk.files = sourceChunk.files.map((filename) => {
                        if ( filename !== outputOptions.filename ) {
                            return filename;
                        }

                        return this.hashFilename(filename, hashes);
                    });

                    // Rewrite the compilation.assets hashes for the spritemap asset
                    const hashedAssets = this.rewriteAssetsHashes(outputOptions.filename, compilation.assets, hashes);
                    compilation.assets = hashedAssets.assets;

                    if ( outputOptions.svgo === false ) {
                        return callback();
                    }

                    const SVGOptimizer = new svgo(merge({
                        plugins: [
                            // Disable the removeTitle plugin when title elements should be generated
                            { removeTitle: !spriteOptions.generate.title }
                        ]
                    }, outputOptions.svgo, {
                        plugins: [
                            // Force disable cleanupIDs as the identifiers are to be used to target a specific sprite
                            { cleanupIDs: false }
                        ]
                    }));
                    SVGOptimizer.optimize(assets[hashedAssets.filename].source()).then((output) => {
                        // Update the optimized asset based on the hashed filename
                        compilation.assets[hashedAssets.filename] = new RawSource(output.data);

                        return callback();
                    });
                });

                // Optimize styles filename
                compilation.hooks.optimizeAssets.tapAsync(plugin, (assets, callback) => {
                    const { styles: stylesOptions } = this.options;

                    if ( typeof this.styles === 'undefined' || this.stylesType !== 'asset' ) {
                        return callback();
                    }

                    // Rewrite the compilation.assets hashes for the styles asset
                    const hashedAssets = this.rewriteAssetsHashes(stylesOptions.filename, compilation.assets, this.getStylesHashes(compilation));

                    // Update the compilation assets with the hashed ones
                    compilation.assets = hashedAssets.assets;

                    return callback();
                });

                callback();
            }).catch((error) => {
                throw new Error(error);
            });
        });

        // Clean up the spritemap chunk
        compiler.hooks.emit.tapAsync(plugin, (compilation, callback) => {
            const { output: outputOptions } = this.options;

            if ( outputOptions.chunk.keep ) {
                return callback();
            }

            compilation.chunks.forEach((chunk) => {
                if ( chunk.name !== outputOptions.chunk.name ) {
                    return;
                }

                delete compilation.assets[chunk.files[0]];
            });

            return callback();
        });

        // Add context dependencies to webpack compilation to make sure watching works correctly
        compiler.hooks.afterCompile.tap(plugin, (compilation) => {
            this.directories.forEach((directory) => {
                compilation.contextDependencies.add(directory);
            });
        });
    }

    updateDependencies() {
        const { input: inputOptions } = this.options;

        this.files = inputOptions.patterns.reduce((accumulator, value) => {
            const files = glob.sync(value, inputOptions.options).map((file) => {
                return path.resolve(file);
            });

            if ( !files.length ) {
                return accumulator;
            }

            // Transform to Set temporarily to remove duplicates
            return [...new Set(accumulator.concat(files))];
        }, []);

        this.directories = inputOptions.patterns.reduce((accumulator, value) => {
            const directories = glob.sync(`${value.substring(0, value.lastIndexOf('/'))}/`, inputOptions.options).map((directory) => {
                return path.resolve(directory);
            });

            if ( !directories.length ) {
                return accumulator;
            }

            // Transform to Set temporarily to remove duplicates
            return [...new Set(accumulator.concat(directories))];
        }, []);
    }

    getStylesType(styles, filename = '') {
        if ( !styles || !filename ) {
            return;
        }

        if ( path.parse(filename).dir ) {
            return 'dir';
        }

        if ( filename.startsWith('~') ) {
            return 'module';
        }

        return 'asset';
    }

    writeStylesToDisk(styles, type) {
        const { styles: stylesOptions } = this.options;

        const location = {
            'dir': stylesOptions.filename,
            'module': path.resolve(__dirname, '../', stylesOptions.filename.replace('~', ''))
        }[type];

        if ( typeof location === 'undefined' ) {
            return;
        }

        // check is location exist
        const locationExists = fs.existsSync(location);

        // Make sure we don't rewrite the file when it's correct already
        const contents = locationExists && fs.readFileSync(location, 'utf8');
        if ( contents === styles ) {
            return;
        }

        if ( type === 'dir' && !locationExists ) {
            const dirname = path.dirname(location);

            if ( !fs.existsSync(dirname) ) {
                mkdirp.sync(dirname);
            }
        }

        fs.writeFileSync(location, styles, 'utf8');
    }

    rewriteAssetsHashes(filename, assets = {}, hashes = []) {
        if ( !filename || !Object.keys(assets).length || !hashes.length ) {
            return;
        }

        // Update patterns in original filename with hash values accordingly
        const hashedFilename = this.hashFilename(filename, hashes);

        // Update the assets when the filename contained hashes
        if ( hashedFilename !== filename ) {
            assets[hashedFilename] = assets[filename];
            delete assets[filename];
        }

        // Return the resulting (hashed) filename together with the assets
        return {
            filename: hashedFilename,
            assets: assets
        };
    }

    hashFilename(filename, hashes = []) {
        if ( !hashes.length ) {
            return;
        }

        return hashes.reduce((output, hash) => {
            const pattern = new RegExp(hash.pattern, 'ig');
            return output.replace(pattern, hash.value);
        }, filename);
    }

    getSpritemapHashes(compilation) {
        const { output: outputOptions } = this.options;

        if ( !compilation ) {
            return [];
        }

        return [{
            pattern: /\[hash]/,
            value: compilation.getStats().hash
        }, {
            pattern: /\[contenthash]/,
            value: this.getContentHash(compilation.assets[outputOptions.filename].source())
        }];
    }

    getStylesHashes(compilation) {
        const { styles: stylesOptions } = this.options;

        if ( !compilation ) {
            return [];
        }

        return [{
            pattern: /\[hash]/,
            value: compilation.getStats().hash
        }, {
            pattern: /\[contenthash]/,
            value: this.getContentHash(compilation.assets[stylesOptions.filename].source())
        }];
    }

    getContentHash(source) {
        return loaderUtils.getHashDigest(source, 'sha1', 'hex', 16);
    }
};
<commit_msg>Fixes chunk not being kept (and missing from stats) because it had no dependencies<commit_after>const fs = require('fs');
const path = require('path');
const glob = require('glob');
const svgo = require('svgo');
const merge = require('webpack-merge');
const mkdirp = require('mkdirp');
const loaderUtils = require('loader-utils');
const { RawSource } = require('webpack-sources');
const MultiEntryPlugin = require('webpack/lib/MultiEntryPlugin');
const RawModule = require('webpack/lib/RawModule');

// Helpers
const formatOptions = require('./options-formatter');
const generateSVG = require('./generate-svg');
const generateStyles = require('./generate-styles');
const { stripVariables, findVariables } = require('./variable-parser');

// Errors & Warnings
const {
    OptionsMismatchWarning,
    VariablesNotSupportedInLanguageWarning,
    VariablesNotSupportedWithFragmentsWarning
} = require('./errors');

const plugin = {
    name: 'SVGSpritemapPlugin'
};

module.exports = class SVGSpritemapPlugin {
    constructor(pattern, options) {
        this.options = formatOptions(pattern, options);

        // Dependencies
        this.files = [];
        this.directories = [];
    }

    apply(compiler) {
        compiler.hooks.entryOption.tap(plugin, (context, entry) => {
            const { output: outputOptions } = this.options;

            if ( !outputOptions.svg4everybody ) {
                return;
            }

            // This is a little hacky but there's no other way since Webpack
            // doesn't support virtual files (https://github.com/rmarscher/virtual-module-webpack-plugin)
            const helper = {
                file: fs.readFileSync(path.join(__dirname, 'templates/svg4everybody.template.js'), 'utf8'),
                path: path.join(__dirname, '../svg4everybody-helper.js')
            };

            // Write the helper file to disk
            fs.writeFileSync(helper.path, helper.file.replace('/* PLACEHOLDER */', JSON.stringify(outputOptions.svg4everybody)), 'utf8');

            // Append helper to entry
            const applyEntryPlugin = (entries, name = 'main') => {
                const plugin = new MultiEntryPlugin(context, entries, name);
                plugin.apply(compiler);
            };

            if ( typeof entry === 'string' ) {
                applyEntryPlugin([entry, helper.path]);
            } else if ( Array.isArray(entry) ) {
                if ( !entry.includes(helper.path) ) {
                    applyEntryPlugin([...entry, helper.path]);
                }
            } else if ( typeof entry === 'object' && entry !== null ) {
                Object.keys(entry).forEach((name) => {
                    if ( typeof entry[name] === 'string' ) {
                        applyEntryPlugin([entry[name], helper.path], name);
                    } else if ( Array.isArray(entry[name]) ) {
                        if ( !entry[name].includes(helper.path) ) {
                            applyEntryPlugin([...entry[name], helper.path], name);
                        }
                    } else {
                        throw new Error(`Unsupported sub-entry type for svg4everybody helper: '${typeof entry[name]}'`);
                    }
                });
            } else {
                throw new Error(`Unsupported entry type for svg4everybody helper: '${typeof entry}'`);
            }

            return true;
        });

        // Update dependencies when needed
        compiler.hooks.environment.tap(plugin, this.updateDependencies.bind(this));
        compiler.hooks.watchRun.tap(plugin, this.updateDependencies.bind(this));

        // Generate spritemap
        compiler.hooks.make.tapAsync(plugin, (compilation, callback) => {
            const { sprite: spriteOptions, output: outputOptions, styles: stylesOptions } = this.options;

            if ( spriteOptions.generate.view && !spriteOptions.generate.use ) {
                compilation.warnings.push(new OptionsMismatchWarning(`Using sprite.generate.view requires sprite.generate.use to be enabled`));
            }

            if ( spriteOptions.generate.use && !spriteOptions.generate.symbol ) {
                compilation.warnings.push(new OptionsMismatchWarning(`Using sprite.generate.use requires sprite.generate.symbol to be enabled`));
            }

            if ( spriteOptions.generate.title && !spriteOptions.generate.symbol ) {
                compilation.warnings.push(new OptionsMismatchWarning(`Using sprite.generate.title requires sprite.generate.symbol to be enabled`));
            }

            if ( spriteOptions.generate.symbol === true && spriteOptions.generate.view === true ) {
                compilation.warnings.push(new OptionsMismatchWarning(`Both sprite.generate.symbol and sprite.generate.view are set to true which will cause identifier conflicts, use a string value (postfix) for either of these options`));
            }

            // Generate SVG
            generateSVG(this.files, Object.assign(spriteOptions, {
                svgo: outputOptions.svgo
            })).then((spritemap) => {
                if ( !spritemap ) {
                    return callback();
                }

                // Create chunk and add spritemap to compilation.assets
                const sourceChunk = compilation.addChunk(outputOptions.chunk.name);
                compilation.assets[outputOptions.filename] = new RawSource(spritemap);

                // Set up a dummy module that we can add to our source chunk
                // To prevent it from getting cleaned up, this seems to be required
                // to correctly link the spritemap asset to the chunk
                const module = new RawModule('', `${outputOptions.chunk.name}-dummy-module`);
                module.buildInfo = {};
                module.hash = '';
                sourceChunk.addModule(module);

                // Generate styles
                if ( stylesOptions ) {
                    const extension = path.extname(stylesOptions.filename).substring(1).toLowerCase();
                    this.styles = generateStyles(spritemap, {
                        extension: extension,
                        prefix: spriteOptions.prefix,
                        postfix: {
                            symbol: spriteOptions.generate.symbol,
                            view: spriteOptions.generate.view
                        },
                        format: {
                            type: stylesOptions.format,
                            publicPath: (() => {
                                const hashes = this.getSpritemapHashes(compilation);
                                const filename = this.hashFilename(outputOptions.filename, hashes);

                                return `${compilation.outputOptions.publicPath || '/'}${filename}`;
                            })()
                        },
                        variables: stylesOptions.variables
                    });

                    // Emit a warning when variables are detected while the language doesn't support it
                    if ( !['scss', 'sass'].includes(extension) && findVariables(spritemap).length ) {
                        compilation.warnings.push(new VariablesNotSupportedInLanguageWarning(extension));
                    }

                    // Emit a warning when variables are detected while the stylesOptions.format is set to 'fragment'
                    if ( stylesOptions.format === 'fragment' && findVariables(spritemap).length ) {
                        compilation.warnings.push(new VariablesNotSupportedWithFragmentsWarning());
                    }

                    if ( stylesOptions.format === 'fragment' && !spriteOptions.generate.view ) {
                        compilation.warnings.push(new OptionsMismatchWarning(`Using styles.format with value 'fragment' in combination with sprite.generate.view with value false will result in CSS fragments not working correctly`));
                    }

                    // Include warnings received from the style formatters
                    if ( this.styles.warnings.length ) {
                        compilation.warnings = [...compilation.warnings, ...this.styles.warnings];
                    }

                    // Write the styles file before compilation starts to make sure the files
                    // are written to disk before other plugins/loaders (e.g. mini-css-extract-plugin) can use them
                    this.stylesType = this.getStylesType(this.styles.content, stylesOptions.filename);
                    this.writeStylesToDisk(this.styles.content, this.stylesType);

                    if ( typeof this.styles !== 'undefined' && this.stylesType === 'asset' ) {
                        compilation.assets[stylesOptions.filename] = new RawSource(this.styles.content);
                    }
                }

                // Overwrite the spritemap chunk hash to the custom SVG contenthash to make sure
                // webpack notices the changes and prints the stats output again
                compilation.hooks.chunkHash.tap(plugin, (chunk, chunkHash) => {
                    const { output: outputOptions } = this.options;

                    if ( chunk.name !== outputOptions.chunk.name || !spritemap ) {
                        return;
                    }

                    chunkHash.digest = () => this.getContentHash(spritemap);
                });

                // Optimize spritemap SVG/filename
                compilation.hooks.optimizeAssets.tapAsync(plugin, (assets, callback) => {
                    const { output: outputOptions, sprite: spriteOptions } = this.options;

                    // Strip variables from spritemap SVG
                    const stripped = stripVariables(compilation.assets[outputOptions.filename].source());
                    compilation.assets[outputOptions.filename] = new RawSource(stripped);

                    // Rewrite the source chunk files hashes
                    const hashes = this.getSpritemapHashes(compilation);
                    const sourceChunk = compilation.namedChunks.get(outputOptions.chunk.name);
                    sourceChunk.files = sourceChunk.files.map((filename) => {
                        if ( filename !== outputOptions.filename ) {
                            return filename;
                        }

                        return this.hashFilename(filename, hashes);
                    });

                    // Rewrite the compilation.assets hashes for the spritemap asset
                    const hashedAssets = this.rewriteAssetsHashes(outputOptions.filename, compilation.assets, hashes);
                    compilation.assets = hashedAssets.assets;

                    if ( outputOptions.svgo === false ) {
                        return callback();
                    }

                    const SVGOptimizer = new svgo(merge({
                        plugins: [
                            // Disable the removeTitle plugin when title elements should be generated
                            { removeTitle: !spriteOptions.generate.title }
                        ]
                    }, outputOptions.svgo, {
                        plugins: [
                            // Force disable cleanupIDs as the identifiers are to be used to target a specific sprite
                            { cleanupIDs: false }
                        ]
                    }));
                    SVGOptimizer.optimize(assets[hashedAssets.filename].source()).then((output) => {
                        // Update the optimized asset based on the hashed filename
                        compilation.assets[hashedAssets.filename] = new RawSource(output.data);

                        return callback();
                    });
                });

                // Optimize styles filename
                compilation.hooks.optimizeAssets.tapAsync(plugin, (assets, callback) => {
                    const { styles: stylesOptions } = this.options;

                    if ( typeof this.styles === 'undefined' || this.stylesType !== 'asset' ) {
                        return callback();
                    }

                    // Rewrite the compilation.assets hashes for the styles asset
                    const hashedAssets = this.rewriteAssetsHashes(stylesOptions.filename, compilation.assets, this.getStylesHashes(compilation));

                    // Update the compilation assets with the hashed ones
                    compilation.assets = hashedAssets.assets;

                    return callback();
                });

                // Make sure we add the generated SVG as a file to the spritemap chunk
                compilation.hooks.afterOptimizeChunkAssets.tap(plugin, () => {
                    compilation.chunks.forEach((chunk) => {
                        if ( chunk.name !== outputOptions.chunk.name ) {
                            return;
                        }

                        chunk.files.push(outputOptions.filename);
                    });
                });

                callback();
            }).catch((error) => {
                throw new Error(error);
            });
        });

        // Clean up the spritemap chunk
        compiler.hooks.emit.tapAsync(plugin, (compilation, callback) => {
            const { output: outputOptions } = this.options;

            if ( outputOptions.chunk.keep ) {
                return callback();
            }

            compilation.chunks.forEach((chunk) => {
                if ( chunk.name !== outputOptions.chunk.name ) {
                    return;
                }

                delete compilation.assets[chunk.files[0]];
            });

            return callback();
        });

        // Add context dependencies to webpack compilation to make sure watching works correctly
        compiler.hooks.afterCompile.tap(plugin, (compilation) => {
            this.directories.forEach((directory) => {
                compilation.contextDependencies.add(directory);
            });
        });
    }

    updateDependencies() {
        const { input: inputOptions } = this.options;

        this.files = inputOptions.patterns.reduce((accumulator, value) => {
            const files = glob.sync(value, inputOptions.options).map((file) => {
                return path.resolve(file);
            });

            if ( !files.length ) {
                return accumulator;
            }

            // Transform to Set temporarily to remove duplicates
            return [...new Set(accumulator.concat(files))];
        }, []);

        this.directories = inputOptions.patterns.reduce((accumulator, value) => {
            const directories = glob.sync(`${value.substring(0, value.lastIndexOf('/'))}/`, inputOptions.options).map((directory) => {
                return path.resolve(directory);
            });

            if ( !directories.length ) {
                return accumulator;
            }

            // Transform to Set temporarily to remove duplicates
            return [...new Set(accumulator.concat(directories))];
        }, []);
    }

    getStylesType(styles, filename = '') {
        if ( !styles || !filename ) {
            return;
        }

        if ( path.parse(filename).dir ) {
            return 'dir';
        }

        if ( filename.startsWith('~') ) {
            return 'module';
        }

        return 'asset';
    }

    writeStylesToDisk(styles, type) {
        const { styles: stylesOptions } = this.options;

        const location = {
            'dir': stylesOptions.filename,
            'module': path.resolve(__dirname, '../', stylesOptions.filename.replace('~', ''))
        }[type];

        if ( typeof location === 'undefined' ) {
            return;
        }

        // check is location exist
        const locationExists = fs.existsSync(location);

        // Make sure we don't rewrite the file when it's correct already
        const contents = locationExists && fs.readFileSync(location, 'utf8');
        if ( contents === styles ) {
            return;
        }

        if ( type === 'dir' && !locationExists ) {
            const dirname = path.dirname(location);

            if ( !fs.existsSync(dirname) ) {
                mkdirp.sync(dirname);
            }
        }

        fs.writeFileSync(location, styles, 'utf8');
    }

    rewriteAssetsHashes(filename, assets = {}, hashes = []) {
        if ( !filename || !Object.keys(assets).length || !hashes.length ) {
            return;
        }

        // Update patterns in original filename with hash values accordingly
        const hashedFilename = this.hashFilename(filename, hashes);

        // Update the assets when the filename contained hashes
        if ( hashedFilename !== filename ) {
            assets[hashedFilename] = assets[filename];
            delete assets[filename];
        }

        // Return the resulting (hashed) filename together with the assets
        return {
            filename: hashedFilename,
            assets: assets
        };
    }

    hashFilename(filename, hashes = []) {
        if ( !hashes.length ) {
            return;
        }

        return hashes.reduce((output, hash) => {
            const pattern = new RegExp(hash.pattern, 'ig');
            return output.replace(pattern, hash.value);
        }, filename);
    }

    getSpritemapHashes(compilation) {
        const { output: outputOptions } = this.options;

        if ( !compilation ) {
            return [];
        }

        return [{
            pattern: /\[hash]/,
            value: compilation.getStats().hash
        }, {
            pattern: /\[contenthash]/,
            value: this.getContentHash(compilation.assets[outputOptions.filename].source())
        }];
    }

    getStylesHashes(compilation) {
        const { styles: stylesOptions } = this.options;

        if ( !compilation ) {
            return [];
        }

        return [{
            pattern: /\[hash]/,
            value: compilation.getStats().hash
        }, {
            pattern: /\[contenthash]/,
            value: this.getContentHash(compilation.assets[stylesOptions.filename].source())
        }];
    }

    getContentHash(source) {
        return loaderUtils.getHashDigest(source, 'sha1', 'hex', 16);
    }
};
<|endoftext|>


<commit_before>'use strict';

var SettingsFile = require('nachos-settings-file');
var nachosHome = require('nachos-home');
var debug = require('debug')('nachosConfig');
var util = require('util');
var Q = require('q');

/**
 * Creating a settings file with nachos defaults
 *
 * @constructor
 */
function NachosConfig() {
  var defaults = {
    packages: nachosHome('packages'),
    server: 'http://nachosjs.herokuapp.com',
    defaults: {
      shell: 'shell',
      exts: {}
    }
  };

  debug('creating new settings file with these defaults: %j', defaults);

  SettingsFile.call(this, 'nachos', {
    globalDefaults: defaults
  });
}

util.inherits(NachosConfig, SettingsFile);

/**
 * Expose the constructor
 * @type {NachosConfig}
 */
NachosConfig.prototype.NachosConfig = NachosConfig;

/**
 * Get the default app command that opens the given extension
 *
 * @param {String} ext The file extension
 * @returns {Q.promise} Promise to the default app command
 */
NachosConfig.prototype.getDefaultApp = function (ext) {
  if (!ext) {
    return Q.reject(new TypeError('extension must be provided'));
  }

  if (typeof ext !== 'string') {
    return Q.reject(new TypeError('extension must be a string'));
  }

  debug('getting command for %s extension', ext);

  return this.get()
    .then(function (config) {
      var command = config.defaults.exts[ext];

      debug('got command %s for %s extension', command, ext);

      return command;
    });
};

/**
 * Set the default app command that opens the given extension
 *
 * @param {String} ext The file extension
 * @param {String} command The execution command
 * @returns {Q.promise} Promise to save
 */
NachosConfig.prototype.setDefaultApp = function (ext, command) {
  if (!ext) {
    return Q.reject(new TypeError('extension must be provided'));
  }

  if (typeof ext !== 'string') {
    return Q.reject(new TypeError('extension must be a string'));
  }

  if (!command) {
    return Q.reject(new TypeError('command must be provided'));
  }

  if (typeof command !== 'string') {
    return Q.reject(new TypeError('command must be a string'));
  }

  debug('setting command %s for %s extension', command, ext);

  var content = {defaults: {exts: {}}};

  content.defaults.exts[ext] = command;

  return this.set(content);
};

module.exports = new NachosConfig();<commit_msg>added startup to defaults<commit_after>'use strict';

var SettingsFile = require('nachos-settings-file');
var nachosHome = require('nachos-home');
var debug = require('debug')('nachosConfig');
var util = require('util');
var Q = require('q');

/**
 * Creating a settings file with nachos defaults
 *
 * @constructor
 */
function NachosConfig() {
  var defaults = {
    packages: nachosHome('packages'),
    server: 'http://nachosjs.herokuapp.com',
    defaults: {
      shell: 'shell',
      exts: {}
    },
    startup: []
  };

  debug('creating new settings file with these defaults: %j', defaults);

  SettingsFile.call(this, 'nachos', {
    globalDefaults: defaults
  });
}

util.inherits(NachosConfig, SettingsFile);

/**
 * Expose the constructor
 * @type {NachosConfig}
 */
NachosConfig.prototype.NachosConfig = NachosConfig;

/**
 * Get the default app command that opens the given extension
 *
 * @param {String} ext The file extension
 * @returns {Q.promise} Promise to the default app command
 */
NachosConfig.prototype.getDefaultApp = function (ext) {
  if (!ext) {
    return Q.reject(new TypeError('extension must be provided'));
  }

  if (typeof ext !== 'string') {
    return Q.reject(new TypeError('extension must be a string'));
  }

  debug('getting command for %s extension', ext);

  return this.get()
    .then(function (config) {
      var command = config.defaults.exts[ext];

      debug('got command %s for %s extension', command, ext);

      return command;
    });
};

/**
 * Set the default app command that opens the given extension
 *
 * @param {String} ext The file extension
 * @param {String} command The execution command
 * @returns {Q.promise} Promise to save
 */
NachosConfig.prototype.setDefaultApp = function (ext, command) {
  if (!ext) {
    return Q.reject(new TypeError('extension must be provided'));
  }

  if (typeof ext !== 'string') {
    return Q.reject(new TypeError('extension must be a string'));
  }

  if (!command) {
    return Q.reject(new TypeError('command must be provided'));
  }

  if (typeof command !== 'string') {
    return Q.reject(new TypeError('command must be a string'));
  }

  debug('setting command %s for %s extension', command, ext);

  var content = {defaults: {exts: {}}};

  content.defaults.exts[ext] = command;

  return this.set(content);
};

module.exports = new NachosConfig();<|endoftext|>


<commit_before>'use babel'

import autoCompleteProvider from './pxrem-provider.js'

const pxReg = /\d+px/gm

class Pxrem {
    config = {
        base: {
            title: 'Default base size',
            description: 'The base size for px convert to rem',
            type: 'integer',
            default: 75,
            minimum: 1
        },
        length: {
            title: 'Default length',
            description: 'The length after decimal point',
            type: 'integer',
            default: 2,
            minium: 0,
            maxium: 20
        }
    }
    activate() {
        let self = this
        atom.commands.add('atom-workspace', 'pxrem:convert', () => {
            self.convert()
        })
        this.autoCompleteProvider = autoCompleteProvider
    }
    deactivate() {
        this.autoCompleteProvider = null
    }
    hinter() {
        return this.autoCompleteProvider
    }
    convert() {
        const editor = atom.workspace.getActiveTextEditor()
        const buffer = editor.getBuffer()
        editor.scan(pxReg, res => {
            let num = parseFloat(res.match[0])
            num = Number((num / atom.config.get('pxrem.base')).toFixed(atom.config.get('pxrem.length')))
            res.replace(`${num}rem`)
        })
    }
}

export default new Pxrem()
<commit_msg>To support floating-point numbers<commit_after>'use babel'

import autoCompleteProvider from './pxrem-provider.js'

const pxReg = /[+-]?([0-9]*[.])?[0-9]+px/gm

class Pxrem {
    config = {
        base: {
            title: 'Default base size',
            description: 'The base size for px convert to rem',
            type: 'integer',
            default: 75,
            minimum: 1
        },
        length: {
            title: 'Default length',
            description: 'The length after decimal point',
            type: 'integer',
            default: 2,
            minium: 0,
            maxium: 20
        }
    }
    activate() {
        let self = this
        atom.commands.add('atom-workspace', 'pxrem:convert', () => {
            self.convert()
        })
        this.autoCompleteProvider = autoCompleteProvider
    }
    deactivate() {
        this.autoCompleteProvider = null
    }
    hinter() {
        return this.autoCompleteProvider
    }
    convert() {
        const editor = atom.workspace.getActiveTextEditor()
        const buffer = editor.getBuffer()
        editor.scan(pxReg, res => {
            let num = parseFloat(res.match[0])
            num = Number((num / atom.config.get('pxrem.base')).toFixed(atom.config.get('pxrem.length')))
            res.replace(`${num}rem`)
        })
    }
}

export default new Pxrem()
<|endoftext|>