<commit_before>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

var Playback = require('playback')
var Styler = require('../../base/styler')
var JST = require('../../base/jst')
var _ = require("underscore")
var Mediator = require('mediator')
var Browser = require('browser')

var objectIE = '<object type="application/x-shockwave-flash" id="<%= cid %>" class="hls-playback" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" data-hls="" width="100%" height="100%"><param name="movie" value="<%= swfPath %>"> <param name="quality" value="autohigh"> <param name="swliveconnect" value="true"> <param name="allowScriptAccess" value="always"> <param name="bgcolor" value="#001122"> <param name="allowFullScreen" value="false"> <param name="wmode" value="transparent"> <param name="tabindex" value="1"> <param name=FlashVars value="playbackId=<%= playbackId %>" /> </object>'

class HLS extends Playback {
  get name() { return 'hls' }
  get tagName() { return 'object' }
  get template() { return JST.hls }
  get attributes() {
    return {
      'class': 'hls-playback',
      'data-hls': '',
      'type': 'application/x-shockwave-flash'
    }
  }

  constructor(options) {
    super(options)
    this.src = options.src
    this.swfPath = options.swfPath || "http://cdn.clappr.io/latest/assets/HLSPlayer.swf"
    this.flushLiveURLCache = (options.flushLiveURLCache === undefined)? true: options.flushLiveURLCache
    this.capLevelToStage = (options.capLevelToStage === undefined)? true: options.capLevelToStage
    this.highDefinition = false
    this.autoPlay = options.autoPlay
    this.defaultSettings = {
      left: ["playstop"],
      default: ['seekbar'],
      right: ["fullscreen", "volume", "hd-indicator"],
      seekEnabled: false
    }
    this.settings = _.extend({}, this.defaultSettings)
    this.playbackType = 'live'
    this.addListeners()
  }

  addListeners() {
    Mediator.on(this.uniqueId + ':flashready', () => this.bootstrap())
    Mediator.on(this.uniqueId + ':timeupdate', () => this.updateTime())
    Mediator.on(this.uniqueId + ':playbackstate', (state) => this.setPlaybackState(state))
    Mediator.on(this.uniqueId + ':highdefinition', (isHD) => this.updateHighDefinition(isHD))
    Mediator.on(this.uniqueId + ':playbackerror', () => this.flashPlaybackError())
  }

  stopListening() {
    super()
    Mediator.off(this.uniqueId + ':flashready')
    Mediator.off(this.uniqueId + ':timeupdate')
    Mediator.off(this.uniqueId + ':playbackstate')
    Mediator.off(this.uniqueId + ':highdefinition')
    Mediator.off(this.uniqueId + ':playbackerror')
  }

  bootstrap() {
    this.el.width = "100%"
    this.el.height = "100%"
    this.isReady = true
    this.trigger('playback:ready', this.name)
    this.currentState = "IDLE"
    this.setFlashSettings()
    this.autoPlay && this.play()
  }

  setFlashSettings() {
    this.el.globoPlayerSetflushLiveURLCache(this.flushLiveURLCache)
    this.el.globoPlayerCapLeveltoStage(this.capLevelToStage)
    this.el.globoPlayerSetmaxBufferLength(0)
  }

  updateHighDefinition(isHD) {
    this.highDefinition = (isHD === "true");
    this.trigger('playback:highdefinitionupdate')
  }

  updateTime() {
    var duration = this.getDuration()
    var position = Math.min(Math.max(this.el.globoGetPosition(), 0), duration)
    var previousDVRStatus = this.dvrEnabled
    var livePlayback = (this.playbackType === 'live')
    this.dvrEnabled = (livePlayback && duration > 240)

    if (duration === 100 || livePlayback === undefined) {
      return;
    }

    if (this.dvrEnabled !== previousDVRStatus) {
      this.updateSettings()
      this.trigger('playback:settingsupdate', this.name)
    }

    if (livePlayback && (!this.dvrEnabled || !this.dvrInUse)) {
      position = duration
    }

    this.trigger('playback:timeupdate', position, duration, this.name)
  }

  play() {
    if(this.currentState === 'PAUSED') {
      this.el.globoPlayerResume()
    } else if (this.currentState !== "PLAYING") {
      this.firstPlay()
    }
    this.trigger('playback:play', this.name)
  }

  getPlaybackType() {
    return this.playbackType? this.playbackType: null
  }

  getCurrentBitrate() {
    var currentLevel = this.getLevels()[this.el.globoGetLevel()]
    return currentLevel.bitrate
  }

  getLastProgramDate() {
    var programDate = this.el.globoGetLastProgramDate()
    // normalizing for BRT
    return programDate - 1.08e+7
  }

  isHighDefinitionInUse() {
    return this.highDefinition
  }

  getLevels() {
    if (!this.levels || this.levels.length === 0) {
      this.levels = this.el.globoGetLevels()
    }
    return this.levels
  }

  setPlaybackState(state) {
    var bufferLength = this.el.globoGetbufferLength()
    if (state === "PLAYING_BUFFERING" && bufferLength < 1)  {
      this.trigger('playback:buffering', this.name)
      this.updateCurrentState(state)
    } else if (state === "PLAYING") {
      if (_.contains(["PLAYING_BUFFERING", "PAUSED", "IDLE"], this.currentState)) {
        this.trigger('playback:bufferfull', this.name)
        this.updateCurrentState(state)
      }
    } else if (state === "PAUSED") {
      this.updateCurrentState(state)
    } else if (state === "IDLE") {
      this.trigger('playback:ended', this.name)
      this.trigger('playback:timeupdate', 0, this.el.globoGetDuration(), this.name)
      this.updateCurrentState(state)
    }
    this.lastBufferLength = bufferLength
  }

  updateCurrentState(state) {
    this.currentState = state
    this.updatePlaybackType()
  }

  updatePlaybackType() {
    this.playbackType = this.el.globoGetType()
    if (this.playbackType) {
      this.playbackType = this.playbackType.toLowerCase()
      if (this.playbackType === 'vod') {
        this.startReportingProgress()
      } else {
        this.stopReportingProgress()
      }
    }
    this.trigger('playback:playbackstate')
  }

  startReportingProgress() {
    if (!this.reportingProgress) {
      this.reportingProgress = true
      Mediator.on(this.uniqueId + ':fragmentloaded', () => this.onFragmentLoaded())
    }
  }

  stopReportingProgress() {
    Mediator.off(this.uniqueId + ':fragmentloaded')
  }

  onFragmentLoaded() {
    var buffered = this.el.globoGetPosition() + this.el.globoGetbufferLength()
    this.trigger('playback:progress', this.el.globoGetPosition(), buffered, this.getDuration(), this.name)
  }

  firstPlay() {
    this.el.globoPlayerLoad(this.src)
    this.el.globoPlayerPlay()
  }

  volume(value) {
    if (this.isReady) {
      this.el.globoPlayerVolume(value)
    } else {
      this.listenToOnce(this, 'playback:bufferfull', () => this.volume(value))
    }
  }

  pause() {
    if (this.playbackType !== 'live' || this.dvrEnabled) {
      this.el.globoPlayerPause()
      if (this.playbackType === 'live' && this.dvrEnabled) {
        this.updateDvr(true)
      }
    }
  }

  stop() {
    this.el.globoPlayerStop()
    this.trigger('playback:timeupdate', 0, this.name)
  }

  isPlaying() {
    if (this.currentState) {
      return !!(this.currentState.match(/playing/i))
    }
    return false
  }

  getDuration() {
    var duration = this.el.globoGetDuration()
    if (this.playbackType === 'live') {
      // estimate 10 seconds of buffer time for live streams for seek positions
      duration = duration - 10
    }
    return duration
  }

  seek(time) {
    var duration = this.getDuration()
    if (time > 0) {
      time = duration * time / 100
    }

    if (this.playbackType === 'live') {
      // seek operations to a time within 5 seconds from live stream will position playhead back to live
      var dvrInUse = (time >= 0 && duration - time > 5)
      if (!dvrInUse) {
        time = -1
      }
      this.updateDvr(dvrInUse)
    }
    this.el.globoPlayerSeek(time)
    this.trigger('playback:timeupdate', time, duration, this.name)
  }

  updateDvr(dvrInUse) {
    var previousDvrInUse = !!this.dvrInUse
    this.dvrInUse = dvrInUse
    if (this.dvrInUse !== previousDvrInUse) {
      this.updateSettings()
      this.trigger('playback:dvr', this.dvrInUse)
      this.trigger('playback:stats:add', {'dvr': this.dvrInUse})
    }
  }

  flashPlaybackError() {
    this.trigger('playback:stop')
  }

  timeUpdate(time, duration) {
    this.trigger('playback:timeupdate', time, duration, this.name)
  }

  destroy() {
    this.stopListening()
    this.$el.remove()
  }

  setupFirefox() {
    var $el = this.$('embed')
    $el.attr('data-hls', '')
    this.setElement($el)
  }

  setupIE() {
    this.setElement($(_.template(objectIE)({cid: this.cid, swfPath: this.swfPath, playbackId: this.uniqueId})))
  }

  updateSettings() {
    this.settings = _.extend({}, this.defaultSettings)
    if (this.playbackType === "vod" || this.dvrInUse) {
      this.settings.left = ["playpause", "position", "duration"]
      this.settings.seekEnabled = true
    } else if (this.dvrEnabled) {
      this.settings.left = ["playpause"]
      this.settings.seekEnabled = true
    } else {
      this.settings.seekEnabled = false
    }
  }

  setElement(element) {
    this.$el = element
    this.el = element[0]
  }

  render() {
    var style = Styler.getStyleFor(this.name)
    if(Browser.isLegacyIE) {
      this.setupIE()
    } else {
      this.$el.html(this.template({cid: this.cid, swfPath: this.swfPath, playbackId: this.uniqueId}))
      if(Browser.isFirefox) {
        this.setupFirefox()
      } else if (Browser.isIE) {
        this.$('embed').remove()
      }
    }
    this.el.id = this.cid
    this.$el.append(style)
    return this
  }
}

HLS.canPlay = function(resource) {
  return !!resource.match(/^http(.*).m3u8/)
}

module.exports = HLS
<commit_msg>hls: fix canPlay regex according to HLS spec (refs #188)<commit_after>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

var Playback = require('playback')
var Styler = require('../../base/styler')
var JST = require('../../base/jst')
var _ = require("underscore")
var Mediator = require('mediator')
var Browser = require('browser')

var objectIE = '<object type="application/x-shockwave-flash" id="<%= cid %>" class="hls-playback" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" data-hls="" width="100%" height="100%"><param name="movie" value="<%= swfPath %>"> <param name="quality" value="autohigh"> <param name="swliveconnect" value="true"> <param name="allowScriptAccess" value="always"> <param name="bgcolor" value="#001122"> <param name="allowFullScreen" value="false"> <param name="wmode" value="transparent"> <param name="tabindex" value="1"> <param name=FlashVars value="playbackId=<%= playbackId %>" /> </object>'

class HLS extends Playback {
  get name() { return 'hls' }
  get tagName() { return 'object' }
  get template() { return JST.hls }
  get attributes() {
    return {
      'class': 'hls-playback',
      'data-hls': '',
      'type': 'application/x-shockwave-flash'
    }
  }

  constructor(options) {
    super(options)
    this.src = options.src
    this.swfPath = options.swfPath || "http://cdn.clappr.io/latest/assets/HLSPlayer.swf"
    this.flushLiveURLCache = (options.flushLiveURLCache === undefined)? true: options.flushLiveURLCache
    this.capLevelToStage = (options.capLevelToStage === undefined)? true: options.capLevelToStage
    this.highDefinition = false
    this.autoPlay = options.autoPlay
    this.defaultSettings = {
      left: ["playstop"],
      default: ['seekbar'],
      right: ["fullscreen", "volume", "hd-indicator"],
      seekEnabled: false
    }
    this.settings = _.extend({}, this.defaultSettings)
    this.playbackType = 'live'
    this.addListeners()
  }

  addListeners() {
    Mediator.on(this.uniqueId + ':flashready', () => this.bootstrap())
    Mediator.on(this.uniqueId + ':timeupdate', () => this.updateTime())
    Mediator.on(this.uniqueId + ':playbackstate', (state) => this.setPlaybackState(state))
    Mediator.on(this.uniqueId + ':highdefinition', (isHD) => this.updateHighDefinition(isHD))
    Mediator.on(this.uniqueId + ':playbackerror', () => this.flashPlaybackError())
  }

  stopListening() {
    super()
    Mediator.off(this.uniqueId + ':flashready')
    Mediator.off(this.uniqueId + ':timeupdate')
    Mediator.off(this.uniqueId + ':playbackstate')
    Mediator.off(this.uniqueId + ':highdefinition')
    Mediator.off(this.uniqueId + ':playbackerror')
  }

  bootstrap() {
    this.el.width = "100%"
    this.el.height = "100%"
    this.isReady = true
    this.trigger('playback:ready', this.name)
    this.currentState = "IDLE"
    this.setFlashSettings()
    this.autoPlay && this.play()
  }

  setFlashSettings() {
    this.el.globoPlayerSetflushLiveURLCache(this.flushLiveURLCache)
    this.el.globoPlayerCapLeveltoStage(this.capLevelToStage)
    this.el.globoPlayerSetmaxBufferLength(0)
  }

  updateHighDefinition(isHD) {
    this.highDefinition = (isHD === "true");
    this.trigger('playback:highdefinitionupdate')
  }

  updateTime() {
    var duration = this.getDuration()
    var position = Math.min(Math.max(this.el.globoGetPosition(), 0), duration)
    var previousDVRStatus = this.dvrEnabled
    var livePlayback = (this.playbackType === 'live')
    this.dvrEnabled = (livePlayback && duration > 240)

    if (duration === 100 || livePlayback === undefined) {
      return;
    }

    if (this.dvrEnabled !== previousDVRStatus) {
      this.updateSettings()
      this.trigger('playback:settingsupdate', this.name)
    }

    if (livePlayback && (!this.dvrEnabled || !this.dvrInUse)) {
      position = duration
    }

    this.trigger('playback:timeupdate', position, duration, this.name)
  }

  play() {
    if(this.currentState === 'PAUSED') {
      this.el.globoPlayerResume()
    } else if (this.currentState !== "PLAYING") {
      this.firstPlay()
    }
    this.trigger('playback:play', this.name)
  }

  getPlaybackType() {
    return this.playbackType? this.playbackType: null
  }

  getCurrentBitrate() {
    var currentLevel = this.getLevels()[this.el.globoGetLevel()]
    return currentLevel.bitrate
  }

  getLastProgramDate() {
    var programDate = this.el.globoGetLastProgramDate()
    // normalizing for BRT
    return programDate - 1.08e+7
  }

  isHighDefinitionInUse() {
    return this.highDefinition
  }

  getLevels() {
    if (!this.levels || this.levels.length === 0) {
      this.levels = this.el.globoGetLevels()
    }
    return this.levels
  }

  setPlaybackState(state) {
    var bufferLength = this.el.globoGetbufferLength()
    if (state === "PLAYING_BUFFERING" && bufferLength < 1)  {
      this.trigger('playback:buffering', this.name)
      this.updateCurrentState(state)
    } else if (state === "PLAYING") {
      if (_.contains(["PLAYING_BUFFERING", "PAUSED", "IDLE"], this.currentState)) {
        this.trigger('playback:bufferfull', this.name)
        this.updateCurrentState(state)
      }
    } else if (state === "PAUSED") {
      this.updateCurrentState(state)
    } else if (state === "IDLE") {
      this.trigger('playback:ended', this.name)
      this.trigger('playback:timeupdate', 0, this.el.globoGetDuration(), this.name)
      this.updateCurrentState(state)
    }
    this.lastBufferLength = bufferLength
  }

  updateCurrentState(state) {
    this.currentState = state
    this.updatePlaybackType()
  }

  updatePlaybackType() {
    this.playbackType = this.el.globoGetType()
    if (this.playbackType) {
      this.playbackType = this.playbackType.toLowerCase()
      if (this.playbackType === 'vod') {
        this.startReportingProgress()
      } else {
        this.stopReportingProgress()
      }
    }
    this.trigger('playback:playbackstate')
  }

  startReportingProgress() {
    if (!this.reportingProgress) {
      this.reportingProgress = true
      Mediator.on(this.uniqueId + ':fragmentloaded', () => this.onFragmentLoaded())
    }
  }

  stopReportingProgress() {
    Mediator.off(this.uniqueId + ':fragmentloaded')
  }

  onFragmentLoaded() {
    var buffered = this.el.globoGetPosition() + this.el.globoGetbufferLength()
    this.trigger('playback:progress', this.el.globoGetPosition(), buffered, this.getDuration(), this.name)
  }

  firstPlay() {
    this.el.globoPlayerLoad(this.src)
    this.el.globoPlayerPlay()
  }

  volume(value) {
    if (this.isReady) {
      this.el.globoPlayerVolume(value)
    } else {
      this.listenToOnce(this, 'playback:bufferfull', () => this.volume(value))
    }
  }

  pause() {
    if (this.playbackType !== 'live' || this.dvrEnabled) {
      this.el.globoPlayerPause()
      if (this.playbackType === 'live' && this.dvrEnabled) {
        this.updateDvr(true)
      }
    }
  }

  stop() {
    this.el.globoPlayerStop()
    this.trigger('playback:timeupdate', 0, this.name)
  }

  isPlaying() {
    if (this.currentState) {
      return !!(this.currentState.match(/playing/i))
    }
    return false
  }

  getDuration() {
    var duration = this.el.globoGetDuration()
    if (this.playbackType === 'live') {
      // estimate 10 seconds of buffer time for live streams for seek positions
      duration = duration - 10
    }
    return duration
  }

  seek(time) {
    var duration = this.getDuration()
    if (time > 0) {
      time = duration * time / 100
    }

    if (this.playbackType === 'live') {
      // seek operations to a time within 5 seconds from live stream will position playhead back to live
      var dvrInUse = (time >= 0 && duration - time > 5)
      if (!dvrInUse) {
        time = -1
      }
      this.updateDvr(dvrInUse)
    }
    this.el.globoPlayerSeek(time)
    this.trigger('playback:timeupdate', time, duration, this.name)
  }

  updateDvr(dvrInUse) {
    var previousDvrInUse = !!this.dvrInUse
    this.dvrInUse = dvrInUse
    if (this.dvrInUse !== previousDvrInUse) {
      this.updateSettings()
      this.trigger('playback:dvr', this.dvrInUse)
      this.trigger('playback:stats:add', {'dvr': this.dvrInUse})
    }
  }

  flashPlaybackError() {
    this.trigger('playback:stop')
  }

  timeUpdate(time, duration) {
    this.trigger('playback:timeupdate', time, duration, this.name)
  }

  destroy() {
    this.stopListening()
    this.$el.remove()
  }

  setupFirefox() {
    var $el = this.$('embed')
    $el.attr('data-hls', '')
    this.setElement($el)
  }

  setupIE() {
    this.setElement($(_.template(objectIE)({cid: this.cid, swfPath: this.swfPath, playbackId: this.uniqueId})))
  }

  updateSettings() {
    this.settings = _.extend({}, this.defaultSettings)
    if (this.playbackType === "vod" || this.dvrInUse) {
      this.settings.left = ["playpause", "position", "duration"]
      this.settings.seekEnabled = true
    } else if (this.dvrEnabled) {
      this.settings.left = ["playpause"]
      this.settings.seekEnabled = true
    } else {
      this.settings.seekEnabled = false
    }
  }

  setElement(element) {
    this.$el = element
    this.el = element[0]
  }

  render() {
    var style = Styler.getStyleFor(this.name)
    if(Browser.isLegacyIE) {
      this.setupIE()
    } else {
      this.$el.html(this.template({cid: this.cid, swfPath: this.swfPath, playbackId: this.uniqueId}))
      if(Browser.isFirefox) {
        this.setupFirefox()
      } else if (Browser.isIE) {
        this.$('embed').remove()
      }
    }
    this.el.id = this.cid
    this.$el.append(style)
    return this
  }
}

HLS.canPlay = function(resource) {
  return !!resource.match(/^http(.*).m3u8?/)
}

module.exports = HLS
<|endoftext|>


<commit_before>/**
 *  gbm Plugin - CSS
 */

import GPlugin from '../core/GPlugin';

export default class CSSPlugin extends GPlugin {
  constructor(options={}, slots='build') { super(options, slots); }

  process(stream, mopts, conf, slot) {
    const opts = conf.buildOptions || {};
    const lint = this.options.lint || opts.lint;
    const postcss = this.options.postcss || opts.postcss;
    const sourceType = this.options.sourceType || opts.sourceType || 'scss';
    const autoPrefixer = this.options.autoPrefixer || opts.autoPrefixer || opts.autoPrefixer===undefined;
    // const rename = this.options.autoPrefixer || opts.autoPrefixer || opts.autoPrefixer===undefined;

    if (lint && !postcss)
      console.log('CSSPlugin:Notice: postcss will be enabled to run stylelint.');
    const pcss = (lint || postcss) ? require('gulp-postcss') : undefined;

    // check lint option
    if (lint) {
      const reporter = require('postcss-reporter');
      const stylelint = require('stylelint');
      const syntax = (sourceType && sourceType!=='css') ? require('postcss-'+sourceType) : undefined;
      const lintOpts = this.options.stylelint || mopts.stylelint || {rules:{}};
      const lintExtra = this.options.stylelintExtra || mopts.stylelintExtra || {reporter:{clearMessages:true, throwError:true}};
      stream = stream.pipe(pcss([
        stylelint(lintOpts),
        reporter(lintExtra.reporter)
      ], {syntax:syntax}));
    }

    // check CSS processor option
    if (sourceType && sourceType !== 'css') {
      const processor = require('gulp-' + (sourceType==='scss' ? 'sass' : sourceType));
      stream = stream.pipe(processor(this.options[sourceType] || mopts[sourceType]));
    }

    // check postcss option
    if (postcss) {
      const pcssOpts = this.options.postcss || mopts.postcss || {};
      stream = stream.pipe(pcss(pcssOpts.plugins || [], pcssOpts.options));
    }
    else if (autoPrefixer) {
      stream = stream.pipe(require('gulp-autoprefixer')(this.options.autoprefixer || opts.autoPrefixer));
    }

    // check rename option
    // if (opts.rename) stream = stream.pipe(require('gulp-rename')(this.options.rename || opts.rename));

    return stream;
  }
}
module.exports = CSSPlugin;
<commit_msg>Fixed mopts.sass options error.<commit_after>/**
 *  gbm Plugin - CSS
 */

import GPlugin from '../core/GPlugin';

export default class CSSPlugin extends GPlugin {
  constructor(options={}, slots='build') { super(options, slots); }

  process(stream, mopts, conf, slot) {
    const opts = conf.buildOptions || {};
    const lint = this.options.lint || opts.lint;
    const postcss = this.options.postcss || opts.postcss;
    const sourceType = this.options.sourceType || opts.sourceType || 'scss';
    const autoPrefixer = this.options.autoPrefixer || opts.autoPrefixer || opts.autoPrefixer===undefined;
    // const rename = this.options.autoPrefixer || opts.autoPrefixer || opts.autoPrefixer===undefined;

    if (lint && !postcss)
      console.log('CSSPlugin:Notice: postcss will be enabled to run stylelint.');
    const pcss = (lint || postcss) ? require('gulp-postcss') : undefined;

    // check lint option
    if (lint) {
      const reporter = require('postcss-reporter');
      const stylelint = require('stylelint');
      const syntax = (sourceType && sourceType!=='css') ? require('postcss-'+sourceType) : undefined;
      const lintOpts = this.options.stylelint || mopts.stylelint || {rules:{}};
      const lintExtra = this.options.stylelintExtra || mopts.stylelintExtra || {reporter:{clearMessages:true, throwError:true}};
      stream = stream.pipe(pcss([
        stylelint(lintOpts),
        reporter(lintExtra.reporter)
      ], {syntax:syntax}));
    }

    // check CSS processor option
    if (sourceType && sourceType !== 'css') {
      const index = sourceType==='scss' ? 'sass' : sourceType;
      const processor = require('gulp-' + index);
      stream = stream.pipe(processor(this.options[index] || mopts[index]));
    }

    // check postcss option
    if (postcss) {
      const pcssOpts = this.options.postcss || mopts.postcss || {};
      stream = stream.pipe(pcss(pcssOpts.plugins || [], pcssOpts.options));
    }
    else if (autoPrefixer) {
      stream = stream.pipe(require('gulp-autoprefixer')(this.options.autoprefixer || opts.autoPrefixer));
    }

    // check rename option
    // if (opts.rename) stream = stream.pipe(require('gulp-rename')(this.options.rename || opts.rename));

    return stream;
  }
}
module.exports = CSSPlugin;
<|endoftext|>


<commit_before>const Plugin = require('../../core/Plugin')
const Translator = require('../../core/Translator')
const { h } = require('preact')
const { RequestClient } = require('../../server')
const UrlUI = require('./UrlUI.js')
require('whatwg-fetch')

/**
 * Url
 *
 */
module.exports = class Url extends Plugin {
  constructor (uppy, opts) {
    super(uppy, opts)
    this.id = this.opts.id || 'Url'
    this.title = 'Link'
    this.type = 'acquirer'
    this.icon = () => <svg aria-hidden="true" class="UppyIcon UppyModalTab-icon" width="64" height="64" viewBox="0 0 64 64">
      <circle cx="32" cy="32" r="31" />
      <g fill-rule="nonzero" fill="#FFF">
        <path d="M25.774 47.357a4.077 4.077 0 0 1-5.76 0L16.9 44.24a4.076 4.076 0 0 1 0-5.758l5.12-5.12-1.817-1.818-5.12 5.122a6.651 6.651 0 0 0 0 9.392l3.113 3.116a6.626 6.626 0 0 0 4.699 1.943c1.7 0 3.401-.649 4.697-1.943l10.241-10.243a6.591 6.591 0 0 0 1.947-4.696 6.599 6.599 0 0 0-1.947-4.696l-3.116-3.114-1.817 1.817 3.116 3.114a4.045 4.045 0 0 1 1.194 2.88 4.045 4.045 0 0 1-1.194 2.878L25.774 47.357z" />
        <path d="M46.216 14.926a6.597 6.597 0 0 0-4.696-1.946h-.001a6.599 6.599 0 0 0-4.696 1.945L26.582 25.167a6.595 6.595 0 0 0-1.947 4.697 6.599 6.599 0 0 0 1.946 4.698l3.114 3.114 1.818-1.816-3.114-3.114a4.05 4.05 0 0 1-1.194-2.882c0-1.086.424-2.108 1.194-2.878L38.64 16.744a4.042 4.042 0 0 1 2.88-1.194c1.089 0 2.11.425 2.88 1.194l3.114 3.114a4.076 4.076 0 0 1 0 5.758l-5.12 5.12 1.818 1.817 5.12-5.122a6.649 6.649 0 0 0 0-9.393l-3.113-3.114-.003.002z" />
      </g>
    </svg>

    // Set default options and locale
    const defaultLocale = {
      strings: {
        import: 'Import',
        enterUrlToImport: 'Enter URL to import a file',
        failedToFetch: 'Uppy Server failed to fetch this URL, please make sure it’s correct',
        enterCorrectUrl: 'Incorrect URL: Please make sure you are entering a direct link to a file'
      }
    }

    const defaultOptions = {
      locale: defaultLocale
    }

    this.opts = Object.assign({}, defaultOptions, opts)

    this.locale = Object.assign({}, defaultLocale, this.opts.locale)
    this.locale.strings = Object.assign({}, defaultLocale.strings, this.opts.locale.strings)

    this.translator = new Translator({locale: this.locale})
    this.i18n = this.translator.translate.bind(this.translator)

    this.hostname = this.opts.host

    if (!this.hostname) {
      throw new Error('Uppy Server hostname is required, please consult https://uppy.io/docs/server')
    }

    // Bind all event handlers for referencability
    this.getMeta = this.getMeta.bind(this)
    this.addFile = this.addFile.bind(this)
    this.handleDrop = this.handleDrop.bind(this)
    this.handleDragOver = this.handleDragOver.bind(this)
    this.handleDragLeave = this.handleDragLeave.bind(this)

    this.server = new RequestClient(uppy, {host: this.opts.host})
  }

  getFileNameFromUrl (url) {
    return url.substring(url.lastIndexOf('/') + 1)
  }

  checkIfCorrectURL (url) {
    if (!url) return false

    const protocol = url.match(/^([a-z0-9]+):\/\//)[1]
    if (protocol !== 'http' && protocol !== 'https') {
      return false
    }

    return true
  }

  addProtocolToURL (url) {
    const protocolRegex = /^[a-z0-9]+:\/\//
    const defaultProtocol = 'http://'
    if (protocolRegex.test(url)) {
      return url
    }

    return defaultProtocol + url
  }

  getMeta (url) {
    return this.server.post('url/meta', { url })
      .then((res) => {
        if (res.error) {
          this.uppy.log('[URL] Error:')
          this.uppy.log(res.error)
          throw new Error('Failed to fetch the file')
        }
        return res
      })
  }

  addFile (url) {
    url = this.addProtocolToURL(url)
    if (!this.checkIfCorrectURL(url)) {
      this.uppy.log(`[URL] Incorrect URL entered: ${url}`)
      this.uppy.info(this.i18n('enterCorrectUrl'), 'error', 4000)
      return
    }

    return this.getMeta(url)
      .then((meta) => {
        const tagFile = {
          source: this.id,
          name: this.getFileNameFromUrl(url),
          type: meta.type,
          data: {
            size: meta.size
          },
          isRemote: true,
          body: {
            url: url
          },
          remote: {
            host: this.opts.host,
            url: `${this.hostname}/url/get`,
            body: {
              fileId: url,
              url: url
            }
          }
        }
        return tagFile
      })
      .then((tagFile) => {
        this.uppy.log('[Url] Adding remote file')
        return this.uppy.addFile(tagFile)
      })
      .then(() => {
        const dashboard = this.uppy.getPlugin('Dashboard')
        if (dashboard) dashboard.hideAllPanels()
      })
      .catch((err) => {
        this.uppy.log(err)
        this.uppy.info({
          message: this.i18n('failedToFetch'),
          details: err
        }, 'error', 4000)
      })
  }

  handleDrop (e) {
    e.preventDefault()
    if (e.dataTransfer.items) {
      const items = Array.from(e.dataTransfer.items)
      items.forEach((item) => {
        if (item.kind === 'string' && item.type.match('^text/uri-list')) {
          item.getAsString((url) => {
            this.uppy.log(`[URL] Adding file from dropped url: ${url}`)
            this.addFile(url)
          })
        }
      })
    }
  }

  handleDragOver (e) {
    e.preventDefault()
    this.el.classList.add('drag')
  }

  handleDragLeave (e) {
    e.preventDefault()
    this.el.classList.remove('drag')
  }

  render (state) {
    return <UrlUI
      i18n={this.i18n}
      addFile={this.addFile} />
  }

  install () {
    const target = this.opts.target
    if (target) {
      this.mount(target, this)
    }

    this.el.addEventListener('drop', this.handleDrop)
    this.el.addEventListener('dragover', this.handleDragOver)
    this.el.addEventListener('dragleave', this.handleDragLeave)
  }

  uninstall () {
    this.el.removeEventListener('drop', this.handleDrop)
    this.el.removeEventListener('dragover', this.handleDragOver)
    this.el.removeEventListener('dragleave', this.handleDragLeave)

    this.unmount()
  }
}
<commit_msg>Add pasting of url strings: as in “copy link address” -> paste in Uppy<commit_after>const Plugin = require('../../core/Plugin')
const Translator = require('../../core/Translator')
const { h } = require('preact')
const { RequestClient } = require('../../server')
const UrlUI = require('./UrlUI.js')
const { toArray } = require('../../core/Utils')
require('whatwg-fetch')

/**
 * Url
 *
 */
module.exports = class Url extends Plugin {
  constructor (uppy, opts) {
    super(uppy, opts)
    this.id = this.opts.id || 'Url'
    this.title = 'Link'
    this.type = 'acquirer'
    this.icon = () => <svg aria-hidden="true" class="UppyIcon UppyModalTab-icon" width="64" height="64" viewBox="0 0 64 64">
      <circle cx="32" cy="32" r="31" />
      <g fill-rule="nonzero" fill="#FFF">
        <path d="M25.774 47.357a4.077 4.077 0 0 1-5.76 0L16.9 44.24a4.076 4.076 0 0 1 0-5.758l5.12-5.12-1.817-1.818-5.12 5.122a6.651 6.651 0 0 0 0 9.392l3.113 3.116a6.626 6.626 0 0 0 4.699 1.943c1.7 0 3.401-.649 4.697-1.943l10.241-10.243a6.591 6.591 0 0 0 1.947-4.696 6.599 6.599 0 0 0-1.947-4.696l-3.116-3.114-1.817 1.817 3.116 3.114a4.045 4.045 0 0 1 1.194 2.88 4.045 4.045 0 0 1-1.194 2.878L25.774 47.357z" />
        <path d="M46.216 14.926a6.597 6.597 0 0 0-4.696-1.946h-.001a6.599 6.599 0 0 0-4.696 1.945L26.582 25.167a6.595 6.595 0 0 0-1.947 4.697 6.599 6.599 0 0 0 1.946 4.698l3.114 3.114 1.818-1.816-3.114-3.114a4.05 4.05 0 0 1-1.194-2.882c0-1.086.424-2.108 1.194-2.878L38.64 16.744a4.042 4.042 0 0 1 2.88-1.194c1.089 0 2.11.425 2.88 1.194l3.114 3.114a4.076 4.076 0 0 1 0 5.758l-5.12 5.12 1.818 1.817 5.12-5.122a6.649 6.649 0 0 0 0-9.393l-3.113-3.114-.003.002z" />
      </g>
    </svg>

    // Set default options and locale
    const defaultLocale = {
      strings: {
        import: 'Import',
        enterUrlToImport: 'Enter URL to import a file',
        failedToFetch: 'Uppy Server failed to fetch this URL, please make sure it’s correct',
        enterCorrectUrl: 'Incorrect URL: Please make sure you are entering a direct link to a file'
      }
    }

    const defaultOptions = {
      locale: defaultLocale
    }

    this.opts = Object.assign({}, defaultOptions, opts)

    this.locale = Object.assign({}, defaultLocale, this.opts.locale)
    this.locale.strings = Object.assign({}, defaultLocale.strings, this.opts.locale.strings)

    this.translator = new Translator({locale: this.locale})
    this.i18n = this.translator.translate.bind(this.translator)

    this.hostname = this.opts.host

    if (!this.hostname) {
      throw new Error('Uppy Server hostname is required, please consult https://uppy.io/docs/server')
    }

    // Bind all event handlers for referencability
    this.getMeta = this.getMeta.bind(this)
    this.addFile = this.addFile.bind(this)
    this.handleDrop = this.handleDrop.bind(this)
    this.handleDragOver = this.handleDragOver.bind(this)
    this.handleDragLeave = this.handleDragLeave.bind(this)

    this.handlePaste = this.handlePaste.bind(this)

    this.server = new RequestClient(uppy, {host: this.opts.host})
  }

  getFileNameFromUrl (url) {
    return url.substring(url.lastIndexOf('/') + 1)
  }

  checkIfCorrectURL (url) {
    if (!url) return false

    const protocol = url.match(/^([a-z0-9]+):\/\//)[1]
    if (protocol !== 'http' && protocol !== 'https') {
      return false
    }

    return true
  }

  addProtocolToURL (url) {
    const protocolRegex = /^[a-z0-9]+:\/\//
    const defaultProtocol = 'http://'
    if (protocolRegex.test(url)) {
      return url
    }

    return defaultProtocol + url
  }

  getMeta (url) {
    return this.server.post('url/meta', { url })
      .then((res) => {
        if (res.error) {
          this.uppy.log('[URL] Error:')
          this.uppy.log(res.error)
          throw new Error('Failed to fetch the file')
        }
        return res
      })
  }

  addFile (url) {
    url = this.addProtocolToURL(url)
    if (!this.checkIfCorrectURL(url)) {
      this.uppy.log(`[URL] Incorrect URL entered: ${url}`)
      this.uppy.info(this.i18n('enterCorrectUrl'), 'error', 4000)
      return
    }

    return this.getMeta(url)
      .then((meta) => {
        const tagFile = {
          source: this.id,
          name: this.getFileNameFromUrl(url),
          type: meta.type,
          data: {
            size: meta.size
          },
          isRemote: true,
          body: {
            url: url
          },
          remote: {
            host: this.opts.host,
            url: `${this.hostname}/url/get`,
            body: {
              fileId: url,
              url: url
            }
          }
        }
        return tagFile
      })
      .then((tagFile) => {
        this.uppy.log('[Url] Adding remote file')
        return this.uppy.addFile(tagFile)
      })
      .then(() => {
        const dashboard = this.uppy.getPlugin('Dashboard')
        if (dashboard) dashboard.hideAllPanels()
      })
      .catch((err) => {
        this.uppy.log(err)
        this.uppy.info({
          message: this.i18n('failedToFetch'),
          details: err
        }, 'error', 4000)
      })
  }

  handleDrop (e) {
    e.preventDefault()
    if (e.dataTransfer.items) {
      const items = toArray(e.dataTransfer.items)
      items.forEach((item) => {
        if (item.kind === 'string' && item.type.match('^text/uri-list')) {
          item.getAsString((url) => {
            this.uppy.log(`[URL] Adding file from dropped url: ${url}`)
            this.addFile(url)
          })
        }
      })
    }
  }

  handleDragOver (e) {
    e.preventDefault()
    this.el.classList.add('drag')
  }

  handleDragLeave (e) {
    e.preventDefault()
    this.el.classList.remove('drag')
  }

  handlePaste (e) {
    if (e.clipboardData.items) {
      const items = toArray(e.clipboardData.items)

      // When a file is pasted, it appears as two items: file name string, then
      // the file itself; Url then treats file name string as URL, which is wrong.
      // This makes sure Url ignores paste event if it contains an actual file
      const hasFiles = items.filter(item => item.kind === 'file').length > 0
      if (hasFiles) return

      items.forEach((item) => {
        if (item.kind === 'string' && item.type.match('text/plain')) {
          item.getAsString((url) => {
            this.uppy.log(`[URL] Adding file from pasted url: ${url}`)
            this.addFile(url)
          })
        }
      })
    }
  }

  render (state) {
    return <UrlUI
      i18n={this.i18n}
      addFile={this.addFile} />
  }

  install () {
    const target = this.opts.target
    if (target) {
      this.mount(target, this)
    }

    this.el.addEventListener('drop', this.handleDrop)
    this.el.addEventListener('dragover', this.handleDragOver)
    this.el.addEventListener('dragleave', this.handleDragLeave)
    this.el.addEventListener('paste', this.handlePaste)
  }

  uninstall () {
    this.el.removeEventListener('drop', this.handleDrop)
    this.el.removeEventListener('dragover', this.handleDragOver)
    this.el.removeEventListener('dragleave', this.handleDragLeave)
    this.el.removeEventListener('paste', this.handlePaste)

    this.unmount()
  }
}
<|endoftext|>


<commit_before>define(['durandal/system', 'durandal/app', 'durandal/activator', 'durandal/events', 'durandal/composition', 'plugins/history', 'knockout', 'jquery'], function(system, app, activator, events, composition, history, ko, $) {
    var optionalParam = /\((.*?)\)/g;
    var namedParam = /(\(\?)?:\w+/g;
    var splatParam = /\*\w+/g;
    var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
    var startDeferred, rootRouter;
    var trailingSlash = /\/$/;

    function routeStringToRegExp(routeString) {
        routeString = routeString.replace(escapeRegExp, '\\$&')
            .replace(optionalParam, '(?:$1)?')
            .replace(namedParam, function(match, optional) {
                return optional ? match : '([^\/]+)';
            })
            .replace(splatParam, '(.*?)');

        return new RegExp('^' + routeString + '$');
    }

    function stripParametersFromRoute(route) {
        var colonIndex = route.indexOf(':');
        var length = colonIndex > 0 ? colonIndex - 1 : route.length;
        return route.substring(0, length);
    }

    function hasChildRouter(instance) {
        return instance.router && instance.router.loadUrl;
    }

    function endsWith(str, suffix) {
        return str.indexOf(suffix, str.length - suffix.length) !== -1;
    }

    var createRouter = function() {
        var queue = [],
            isProcessing = ko.observable(false),
            currentActivation,
            currentInstruction,
            activeItem = activator.create();

        var router = {
            handlers: [],
            routes: [],
            navigationModel: ko.observableArray([]),
            activeItem: activeItem,
            isNavigating: ko.computed(function() {
                var current = activeItem();
                return isProcessing() || (current && current.router && current.router.isNavigating());
            }),
            __router__:true
        };

        events.includeIn(router);
        activeItem.settings.areSameItem = function () {
            return false;
        };

        function completeNavigation(instance, instruction) {
            system.log('Navigation Complete', instance, instruction);

            if (currentActivation && currentActivation.__moduleId__) {
                router.trigger('router:navigatedFrom:' + currentActivation.__moduleId__);
            }

            currentActivation = instance;
            currentInstruction = instruction;

            if (currentActivation && currentActivation.__moduleId__) {
                router.trigger('router:navigatedTo:' + currentActivation.__moduleId__);
            }

            if (!hasChildRouter(instance)) {
                router.updateDocumentTitle(instance, instruction);
            }

            rootRouter.explicitNavigation = false;
            rootRouter.navigatingBack = false;
            router.trigger('router:navigation:complete', instance, instruction, router);
        }

        function cancelNavigation(instance, instruction) {
            system.log('Navigation Cancelled');

            if (currentInstruction) {
                router.navigate(currentInstruction.fragment, { trigger: false });
            }

            isProcessing(false);
            rootRouter.explicitNavigation = false;
            rootRouter.navigatingBack = false;
            router.trigger('router:navigation:cancelled', instance, instruction, router);
        }

        function redirect(url) {
            system.log('Navigation Redirecting');

            isProcessing(false);
            rootRouter.explicitNavigation = false;
            rootRouter.navigatingBack = false;
            router.navigate(url, { trigger: true, replace: true });
        }

        function activateRoute(activator, instance, instruction) {
            rootRouter.navigatingBack = !rootRouter.explicitNavigation && currentActivation != instruction.fragment;

            if(rootRouter.navigatingBack){
                system.log('Navigating Back');
            }

            activator.activateItem(instance, instruction.params).then(function(succeeded, failData) {
                if (succeeded) {
                    var previousActivation = currentActivation;
                    completeNavigation(instance, instruction);

                    if (hasChildRouter(instance)) {
                        queueInstruction({
                            router: instance.router,
                            fragment: instruction.fragment,
                            queryString: instruction.queryString
                        });
                    }

                    if (previousActivation == instance) {
                        router.attachedToParent();
                    }
                } else if(failData.redirect){
                    redirect(failData.redirect);
                }else{
                    cancelNavigation(instance, instruction);
                }

                if (startDeferred) {
                    startDeferred.resolve();
                    startDeferred = null;
                }
            });
        }

        function handleGuardedRoute(activator, instance, instruction) {
            var resultOrPromise = router.guardRoute(instance, instruction);
            if (resultOrPromise) {
                if (resultOrPromise.then) {
                    resultOrPromise.then(function(result) {
                        if (result) {
                            if (system.isString(result)) {
                                redirect(result);
                            } else {
                                activateRoute(activator, instance, instruction);
                            }
                        } else {
                            cancelNavigation(instance, instruction);
                        }
                    });
                } else {
                    if (system.isString(resultOrPromise)) {
                        redirect(resultOrPromise);
                    } else {
                        activateRoute(activator, instance, instruction);
                    }
                }
            } else {
                cancelNavigation(instance, instruction);
            }
        }

        function ensureActivation(activator, instance, instruction) {
            if (router.guardRoute) {
                handleGuardedRoute(activator, instance, instruction);
            } else {
                activateRoute(activator, instance, instruction);
            }
        }

        function canReuseCurrentActivation(instruction) {
            return currentInstruction
                && currentInstruction.config.moduleId == instruction.config.moduleId
                && currentActivation
                && ((currentActivation.canReuseForRoute && currentActivation.canReuseForRoute.apply(currentActivation, instruction.params))
                    || (currentActivation.router && currentActivation.router.loadUrl));
        }

        function dequeueInstruction() {
            if (isProcessing()) {
                return;
            }

            var instruction = queue.shift();
            queue = [];

            if (!instruction) {
                return;
            }

            if (instruction.router) {
                var fullFragment = instruction.fragment;
                if (instruction.queryString) {
                    fullFragment += "?" + instruction.queryString;
                }

                instruction.router.loadUrl(fullFragment);
                return;
            }

            isProcessing(true);

            if (canReuseCurrentActivation(instruction)) {
                ensureActivation(activator.create(), currentActivation, instruction);
            } else {
                system.acquire(instruction.config.moduleId).then(function(module) {
                    var instance = system.resolveObject(module);
                    ensureActivation(activeItem, instance, instruction);
                });
            }
        }

        function queueInstruction(instruction) {
            queue.unshift(instruction);
            dequeueInstruction();
        }

        // Given a route, and a URL fragment that it matches, return the array of
        // extracted decoded parameters. Empty or unmatched parameters will be
        // treated as `null` to normalize cross-browser behavior.
        function createParams(routePattern, fragment, queryString) {
            var params = routePattern.exec(fragment).slice(1);

            for (var i = 0; i < params.length; i++) {
                var current = params[i];
                params[i] = current ? decodeURIComponent(current) : null;
            }

            var queryParams = router.parseQueryString(queryString);
            if (queryParams) {
                params.push(queryParams);
            }

            return {
                params:params,
                queryParams:queryParams
            };
        }

        function mapRoute(config) {
            router.trigger('router:route:before-config', config, router);

            if (!system.isRegExp(config.route)) {
                config.title = config.title || router.convertRouteToTitle(config.route);
                config.moduleId = config.moduleId || router.convertRouteToModuleId(config.route);
                config.hash = config.hash || router.convertRouteToHash(config.route);
                config.routePattern = routeStringToRegExp(config.route);
            }else{
                config.routePattern = config.route;
            }

            router.trigger('router:route:after-config', config, router);

            router.routes.push(config);

            router.route(config.routePattern, function(fragment, queryString) {
                var paramInfo = createParams(config.routePattern, fragment, queryString);
                queueInstruction({
                    fragment: fragment,
                    queryString:queryString,
                    config: config,
                    params: paramInfo.params,
                    queryParams:paramInfo.queryParams
                });
            });

            return router;
        }

        function addActiveFlag(config) {
            config.isActive = ko.computed(function() {
                return activeItem() && activeItem().__moduleId__ == config.moduleId;
            });
        }

        router.parseQueryString = function (queryString) {
            var queryObject, pairs;

            if (!queryString) {
                return null;
            }

            pairs = queryString.split('&');

            if (pairs.length == 0) {
                return null;
            }

            queryObject = {};

            for (var i = 0; i < pairs.length; i++) {
                var pair = pairs[i];
                if (pair === '') {
                    continue;
                }

                var parts = pair.split('=');
                queryObject[parts[0]] = parts[1] && decodeURIComponent(parts[1].replace(/\+/g, ' '));
            }

            return queryObject;
        };

        // Add a route to be tested when the fragment changes. Routes added later
        // may override previous routes.
        router.route = function(routePattern, callback) {
            router.handlers.push({ routePattern: routePattern, callback: callback });
        };

        // Attempt to load the current URL fragment. If a route succeeds with a
        // match, returns `true`. If no defined routes matches the fragment,
        // returns `false`.
        router.loadUrl = function(fragment) {
            var handlers = router.handlers,
                queryString = null,
                coreFragment = fragment,
                queryIndex = fragment.indexOf('?');

            if (queryIndex != -1) {
                coreFragment = fragment.substring(0, queryIndex);
                queryString = fragment.substr(queryIndex + 1);
            }

            coreFragment = coreFragment.replace(trailingSlash, '');

            for (var i = 0; i < handlers.length; i++) {
                var current = handlers[i];
                if (current.routePattern.test(coreFragment)) {
                    current.callback(coreFragment, queryString);
                    return true;
                }
            }

            return false;
        };

        router.updateDocumentTitle = function(instance, instruction) {
            if (instruction.config.title) {
                if (app.title) {
                    document.title = instruction.config.title + " | " + app.title;
                } else {
                    document.title = instruction.config.title;
                }
            } else if (app.title) {
                document.title = app.title;
            }
        };

        router.navigate = function(fragment, options) {
            rootRouter.explicitNavigation = true;
            history.navigate(fragment, options);
        };

        router.navigateBack = function() {
            history.history.back();
        };

        router.attachedToParent = function() {
            setTimeout(function() {
                isProcessing(false);
                router.trigger('router:navigation:attached-to-parent', currentActivation, currentInstruction, router);
                dequeueInstruction();
            }, 10);
        };

        router.compositionComplete = function(){
            router.trigger('router:navigation:composition-complete', currentActivation, currentInstruction, router);
        };

        router.convertRouteToHash = function(route) {
            return "#" + route;
        };

        router.convertRouteToModuleId = function(route) {
            return stripParametersFromRoute(route);
        };

        router.convertRouteToTitle = function(route) {
            var value = stripParametersFromRoute(route);
            return value.substring(0, 1).toUpperCase() + value.substring(1);
        };

        // Manually bind a single named route to a module. For example:
        //
        //     router.map('search/:query/p:num', 'viewmodels/search');
        //
        router.map = function(route, config) {
            if (system.isArray(route)) {
                for (var i = 0; i < route.length; i++) {
                    router.map(route[i]);
                }

                return router;
            }

            if (system.isString(route) || system.isRegExp(route)) {
                if (!config) {
                    config = {};
                } else if (system.isString(config)) {
                    config = { moduleId: config };
                }

                config.route = route;
            } else {
                config = route;
            }

            return mapRoute(config);
        };

        router.buildNavigationModel = function(defaultOrder) {
            var nav = [], routes = router.routes;
            defaultOrder = defaultOrder || 100;

            for (var i = 0; i < routes.length; i++) {
                var current = routes[i];

                if (current.nav) {
                    if (!system.isNumber(current.nav)) {
                        current.nav = defaultOrder;
                    }

                    addActiveFlag(current);
                    nav.push(current);
                }
            }

            nav.sort(function(a, b) { return a.nav - b.nav; });
            router.navigationModel(nav);

            return router;
        };

        router.mapUnknownRoutes = function(config) {
            var route = "*catchall";
            var routePattern = routeStringToRegExp(route);

            router.route(routePattern, function (fragment, queryString) {
                var paramInfo = createParams(routePattern, fragment, queryString);
                var instruction = {
                    fragment: fragment,
                    queryString: queryString,
                    config: {
                        route: route,
                        routePattern: routePattern
                    },
                    params: paramInfo.params,
                    queryParams: paramInfo.queryParams
                };

                if (!config) {
                    instruction.config.moduleId = fragment;
                } else if (system.isString(config)) {
                    instruction.config.moduleId = config;
                } else if (system.isFunction(config)) {
                    var result = config(instruction);
                    if (result && result.then) {
                        result.then(function() {
                            router.trigger('router:route:before-config', instruction.config, router);
                            router.trigger('router:route:after-config', instruction.config, router);
                            queueInstruction(instruction);
                        });
                        return;
                    }
                } else {
                    instruction.config = config;
                    instruction.config.route = route;
                    instruction.config.routePattern = routePattern;
                }

                router.trigger('router:route:before-config', instruction.config, router);
                router.trigger('router:route:after-config', instruction.config, router);
                queueInstruction(instruction);
            });

            return router;
        };

        router.reset = function() {
            router.handlers = [];
            router.routes = [];
            delete router.options;
        };

        router.makeRelative = function(settings){
            if(system.isString(settings)){
                settings = {
                    moduleId:settings,
                    route:settings
                };
            }

            if(settings.moduleId && !endsWith(settings.moduleId, '/')){
                settings.moduleId += '/';
            }

            if(settings.route && !endsWith(settings.route, '/')){
                settings.route += '/';
            }

            this.on('router:route:before-config').then(function(config){
                if(settings.moduleId){
                    config.moduleId = settings.moduleId + config.moduleId;
                }

                if(settings.route){
                    if(config.route === ''){
                        config.route = settings.route.substring(0, settings.route.length - 1);
                    }else{
                        config.route = settings.route + config.route;
                    }
                }
            });

            return this;
        };

        router.createChildRouter = function() {
            var childRouter = createRouter();
            childRouter.parent = router;
            return childRouter;
        };

        return router;
    };

    rootRouter = createRouter();
    rootRouter.explicitNavigation = false;
    rootRouter.navigatingBack = false;

    rootRouter.activate = function(options) {
        return system.defer(function(dfd) {
            startDeferred = dfd;
            rootRouter.options = system.extend({ routeHandler: rootRouter.loadUrl }, rootRouter.options, options);
            history.activate(rootRouter.options);
            $(document).on('click', 'a', function(){
                rootRouter.explicitNavigation = true;
            });
        }).promise();
    };

    rootRouter.deactivate = function() {
        history.deactivate();
    };

    rootRouter.install = function(){
        ko.bindingHandlers.router = {
            init: function() {
                return { controlsDescendantBindings: true };
            },
            update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
                var settings = ko.utils.unwrapObservable(valueAccessor()) || {};

                if (settings.__router__) {
                    settings = {
                        model:settings.activeItem(),
                        attachedToParent:settings.attachedToParent,
                        compositionComplete:settings.compositionComplete,
                        activate: false
                    };
                } else {
                    var theRouter = ko.utils.unwrapObservable(settings.router || viewModel.router) || rootRouter;
                    settings.model = theRouter.activeItem();
                    settings.attachedToParent = theRouter.attachedToParent;
                    settings.compositionComplete = theRouter.compositionComplete;
                    settings.activate = false;
                }

                composition.compose(element, settings, bindingContext);
            }
        };

        ko.virtualElements.allowedBindings.router = true;
    };

    return rootRouter;
});<commit_msg>Modify isNavigating that is always looking at child router's isNavigating property<commit_after>define(['durandal/system', 'durandal/app', 'durandal/activator', 'durandal/events', 'durandal/composition', 'plugins/history', 'knockout', 'jquery'], function(system, app, activator, events, composition, history, ko, $) {
    var optionalParam = /\((.*?)\)/g;
    var namedParam = /(\(\?)?:\w+/g;
    var splatParam = /\*\w+/g;
    var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
    var startDeferred, rootRouter;
    var trailingSlash = /\/$/;

    function routeStringToRegExp(routeString) {
        routeString = routeString.replace(escapeRegExp, '\\$&')
            .replace(optionalParam, '(?:$1)?')
            .replace(namedParam, function(match, optional) {
                return optional ? match : '([^\/]+)';
            })
            .replace(splatParam, '(.*?)');

        return new RegExp('^' + routeString + '$');
    }

    function stripParametersFromRoute(route) {
        var colonIndex = route.indexOf(':');
        var length = colonIndex > 0 ? colonIndex - 1 : route.length;
        return route.substring(0, length);
    }

    function hasChildRouter(instance) {
        return instance.router && instance.router.loadUrl;
    }

    function endsWith(str, suffix) {
        return str.indexOf(suffix, str.length - suffix.length) !== -1;
    }

    var createRouter = function() {
        var queue = [],
            isProcessing = ko.observable(false),
            currentActivation,
            currentInstruction,
            activeItem = activator.create();

        var router = {
            handlers: [],
            routes: [],
            navigationModel: ko.observableArray([]),
            activeItem: activeItem,
            isNavigating: ko.computed(function() {
                var current = activeItem();
                var processing = isProcessing();
                	var currentRouterIsProcesing = current
						&& current.router
						&& current.router != router
						&& current.router.isNavigating() ? true : false;
            	return  processing || currentRouterIsProcesing;
            }),
            __router__:true
        };

        events.includeIn(router);
        activeItem.settings.areSameItem = function () {
            return false;
        };

        function completeNavigation(instance, instruction) {
            system.log('Navigation Complete', instance, instruction);

            if (currentActivation && currentActivation.__moduleId__) {
                router.trigger('router:navigatedFrom:' + currentActivation.__moduleId__);
            }

            currentActivation = instance;
            currentInstruction = instruction;

            if (currentActivation && currentActivation.__moduleId__) {
                router.trigger('router:navigatedTo:' + currentActivation.__moduleId__);
            }

            if (!hasChildRouter(instance)) {
                router.updateDocumentTitle(instance, instruction);
            }

            rootRouter.explicitNavigation = false;
            rootRouter.navigatingBack = false;
            router.trigger('router:navigation:complete', instance, instruction, router);
        }

        function cancelNavigation(instance, instruction) {
            system.log('Navigation Cancelled');

            if (currentInstruction) {
                router.navigate(currentInstruction.fragment, { trigger: false });
            }

            isProcessing(false);
            rootRouter.explicitNavigation = false;
            rootRouter.navigatingBack = false;
            router.trigger('router:navigation:cancelled', instance, instruction, router);
        }

        function redirect(url) {
            system.log('Navigation Redirecting');

            isProcessing(false);
            rootRouter.explicitNavigation = false;
            rootRouter.navigatingBack = false;
            router.navigate(url, { trigger: true, replace: true });
        }

        function activateRoute(activator, instance, instruction) {
            rootRouter.navigatingBack = !rootRouter.explicitNavigation && currentActivation != instruction.fragment;

            if(rootRouter.navigatingBack){
                system.log('Navigating Back');
            }

            activator.activateItem(instance, instruction.params).then(function(succeeded, failData) {
                if (succeeded) {
                    var previousActivation = currentActivation;
                    completeNavigation(instance, instruction);

                    if (hasChildRouter(instance)) {
                        queueInstruction({
                            router: instance.router,
                            fragment: instruction.fragment,
                            queryString: instruction.queryString
                        });
                    }

                    if (previousActivation == instance) {
                        router.attachedToParent();
                    }
                } else if(failData.redirect){
                    redirect(failData.redirect);
                }else{
                    cancelNavigation(instance, instruction);
                }

                if (startDeferred) {
                    startDeferred.resolve();
                    startDeferred = null;
                }
            });
        }

        function handleGuardedRoute(activator, instance, instruction) {
            var resultOrPromise = router.guardRoute(instance, instruction);
            if (resultOrPromise) {
                if (resultOrPromise.then) {
                    resultOrPromise.then(function(result) {
                        if (result) {
                            if (system.isString(result)) {
                                redirect(result);
                            } else {
                                activateRoute(activator, instance, instruction);
                            }
                        } else {
                            cancelNavigation(instance, instruction);
                        }
                    });
                } else {
                    if (system.isString(resultOrPromise)) {
                        redirect(resultOrPromise);
                    } else {
                        activateRoute(activator, instance, instruction);
                    }
                }
            } else {
                cancelNavigation(instance, instruction);
            }
        }

        function ensureActivation(activator, instance, instruction) {
            if (router.guardRoute) {
                handleGuardedRoute(activator, instance, instruction);
            } else {
                activateRoute(activator, instance, instruction);
            }
        }

        function canReuseCurrentActivation(instruction) {
            return currentInstruction
                && currentInstruction.config.moduleId == instruction.config.moduleId
                && currentActivation
                && ((currentActivation.canReuseForRoute && currentActivation.canReuseForRoute.apply(currentActivation, instruction.params))
                    || (currentActivation.router && currentActivation.router.loadUrl));
        }

        function dequeueInstruction() {
            if (isProcessing()) {
                return;
            }

            var instruction = queue.shift();
            queue = [];

            if (!instruction) {
                return;
            }

            if (instruction.router) {
                var fullFragment = instruction.fragment;
                if (instruction.queryString) {
                    fullFragment += "?" + instruction.queryString;
                }

                instruction.router.loadUrl(fullFragment);
                return;
            }

            isProcessing(true);

            if (canReuseCurrentActivation(instruction)) {
                ensureActivation(activator.create(), currentActivation, instruction);
            } else {
                system.acquire(instruction.config.moduleId).then(function(module) {
                    var instance = system.resolveObject(module);
                    ensureActivation(activeItem, instance, instruction);
                });
            }
        }

        function queueInstruction(instruction) {
            queue.unshift(instruction);
            dequeueInstruction();
        }

        // Given a route, and a URL fragment that it matches, return the array of
        // extracted decoded parameters. Empty or unmatched parameters will be
        // treated as `null` to normalize cross-browser behavior.
        function createParams(routePattern, fragment, queryString) {
            var params = routePattern.exec(fragment).slice(1);

            for (var i = 0; i < params.length; i++) {
                var current = params[i];
                params[i] = current ? decodeURIComponent(current) : null;
            }

            var queryParams = router.parseQueryString(queryString);
            if (queryParams) {
                params.push(queryParams);
            }

            return {
                params:params,
                queryParams:queryParams
            };
        }

        function mapRoute(config) {
            router.trigger('router:route:before-config', config, router);

            if (!system.isRegExp(config.route)) {
                config.title = config.title || router.convertRouteToTitle(config.route);
                config.moduleId = config.moduleId || router.convertRouteToModuleId(config.route);
                config.hash = config.hash || router.convertRouteToHash(config.route);
                config.routePattern = routeStringToRegExp(config.route);
            }else{
                config.routePattern = config.route;
            }

            router.trigger('router:route:after-config', config, router);

            router.routes.push(config);

            router.route(config.routePattern, function(fragment, queryString) {
                var paramInfo = createParams(config.routePattern, fragment, queryString);
                queueInstruction({
                    fragment: fragment,
                    queryString:queryString,
                    config: config,
                    params: paramInfo.params,
                    queryParams:paramInfo.queryParams
                });
            });

            return router;
        }

        function addActiveFlag(config) {
            config.isActive = ko.computed(function() {
                return activeItem() && activeItem().__moduleId__ == config.moduleId;
            });
        }

        router.parseQueryString = function (queryString) {
            var queryObject, pairs;

            if (!queryString) {
                return null;
            }

            pairs = queryString.split('&');

            if (pairs.length == 0) {
                return null;
            }

            queryObject = {};

            for (var i = 0; i < pairs.length; i++) {
                var pair = pairs[i];
                if (pair === '') {
                    continue;
                }

                var parts = pair.split('=');
                queryObject[parts[0]] = parts[1] && decodeURIComponent(parts[1].replace(/\+/g, ' '));
            }

            return queryObject;
        };

        // Add a route to be tested when the fragment changes. Routes added later
        // may override previous routes.
        router.route = function(routePattern, callback) {
            router.handlers.push({ routePattern: routePattern, callback: callback });
        };

        // Attempt to load the current URL fragment. If a route succeeds with a
        // match, returns `true`. If no defined routes matches the fragment,
        // returns `false`.
        router.loadUrl = function(fragment) {
            var handlers = router.handlers,
                queryString = null,
                coreFragment = fragment,
                queryIndex = fragment.indexOf('?');

            if (queryIndex != -1) {
                coreFragment = fragment.substring(0, queryIndex);
                queryString = fragment.substr(queryIndex + 1);
            }

            coreFragment = coreFragment.replace(trailingSlash, '');

            for (var i = 0; i < handlers.length; i++) {
                var current = handlers[i];
                if (current.routePattern.test(coreFragment)) {
                    current.callback(coreFragment, queryString);
                    return true;
                }
            }

            return false;
        };

        router.updateDocumentTitle = function(instance, instruction) {
            if (instruction.config.title) {
                if (app.title) {
                    document.title = instruction.config.title + " | " + app.title;
                } else {
                    document.title = instruction.config.title;
                }
            } else if (app.title) {
                document.title = app.title;
            }
        };

        router.navigate = function(fragment, options) {
            rootRouter.explicitNavigation = true;
            history.navigate(fragment, options);
        };

        router.navigateBack = function() {
            history.history.back();
        };

        router.attachedToParent = function() {
            setTimeout(function() {
                isProcessing(false);
                router.trigger('router:navigation:attached-to-parent', currentActivation, currentInstruction, router);
                dequeueInstruction();
            }, 10);
        };

        router.compositionComplete = function(){
            router.trigger('router:navigation:composition-complete', currentActivation, currentInstruction, router);
        };

        router.convertRouteToHash = function(route) {
            return "#" + route;
        };

        router.convertRouteToModuleId = function(route) {
            return stripParametersFromRoute(route);
        };

        router.convertRouteToTitle = function(route) {
            var value = stripParametersFromRoute(route);
            return value.substring(0, 1).toUpperCase() + value.substring(1);
        };

        // Manually bind a single named route to a module. For example:
        //
        //     router.map('search/:query/p:num', 'viewmodels/search');
        //
        router.map = function(route, config) {
            if (system.isArray(route)) {
                for (var i = 0; i < route.length; i++) {
                    router.map(route[i]);
                }

                return router;
            }

            if (system.isString(route) || system.isRegExp(route)) {
                if (!config) {
                    config = {};
                } else if (system.isString(config)) {
                    config = { moduleId: config };
                }

                config.route = route;
            } else {
                config = route;
            }

            return mapRoute(config);
        };

        router.buildNavigationModel = function(defaultOrder) {
            var nav = [], routes = router.routes;
            defaultOrder = defaultOrder || 100;

            for (var i = 0; i < routes.length; i++) {
                var current = routes[i];

                if (current.nav) {
                    if (!system.isNumber(current.nav)) {
                        current.nav = defaultOrder;
                    }

                    addActiveFlag(current);
                    nav.push(current);
                }
            }

            nav.sort(function(a, b) { return a.nav - b.nav; });
            router.navigationModel(nav);

            return router;
        };

        router.mapUnknownRoutes = function(config) {
            var route = "*catchall";
            var routePattern = routeStringToRegExp(route);

            router.route(routePattern, function (fragment, queryString) {
                var paramInfo = createParams(routePattern, fragment, queryString);
                var instruction = {
                    fragment: fragment,
                    queryString: queryString,
                    config: {
                        route: route,
                        routePattern: routePattern
                    },
                    params: paramInfo.params,
                    queryParams: paramInfo.queryParams
                };

                if (!config) {
                    instruction.config.moduleId = fragment;
                } else if (system.isString(config)) {
                    instruction.config.moduleId = config;
                } else if (system.isFunction(config)) {
                    var result = config(instruction);
                    if (result && result.then) {
                        result.then(function() {
                            router.trigger('router:route:before-config', instruction.config, router);
                            router.trigger('router:route:after-config', instruction.config, router);
                            queueInstruction(instruction);
                        });
                        return;
                    }
                } else {
                    instruction.config = config;
                    instruction.config.route = route;
                    instruction.config.routePattern = routePattern;
                }

                router.trigger('router:route:before-config', instruction.config, router);
                router.trigger('router:route:after-config', instruction.config, router);
                queueInstruction(instruction);
            });

            return router;
        };

        router.reset = function() {
            router.handlers = [];
            router.routes = [];
            delete router.options;
        };

        router.makeRelative = function(settings){
            if(system.isString(settings)){
                settings = {
                    moduleId:settings,
                    route:settings
                };
            }

            if(settings.moduleId && !endsWith(settings.moduleId, '/')){
                settings.moduleId += '/';
            }

            if(settings.route && !endsWith(settings.route, '/')){
                settings.route += '/';
            }

            this.on('router:route:before-config').then(function(config){
                if(settings.moduleId){
                    config.moduleId = settings.moduleId + config.moduleId;
                }

                if(settings.route){
                    if(config.route === ''){
                        config.route = settings.route.substring(0, settings.route.length - 1);
                    }else{
                        config.route = settings.route + config.route;
                    }
                }
            });

            return this;
        };

        router.createChildRouter = function() {
            var childRouter = createRouter();
            childRouter.parent = router;
            return childRouter;
        };

        return router;
    };

    rootRouter = createRouter();
    rootRouter.explicitNavigation = false;
    rootRouter.navigatingBack = false;

    rootRouter.activate = function(options) {
        return system.defer(function(dfd) {
            startDeferred = dfd;
            rootRouter.options = system.extend({ routeHandler: rootRouter.loadUrl }, rootRouter.options, options);
            history.activate(rootRouter.options);
            $(document).on('click', 'a', function(){
                rootRouter.explicitNavigation = true;
            });
        }).promise();
    };

    rootRouter.deactivate = function() {
        history.deactivate();
    };

    rootRouter.install = function(){
        ko.bindingHandlers.router = {
            init: function() {
                return { controlsDescendantBindings: true };
            },
            update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
                var settings = ko.utils.unwrapObservable(valueAccessor()) || {};

                if (settings.__router__) {
                    settings = {
                        model:settings.activeItem(),
                        attachedToParent:settings.attachedToParent,
                        compositionComplete:settings.compositionComplete,
                        activate: false
                    };
                } else {
                    var theRouter = ko.utils.unwrapObservable(settings.router || viewModel.router) || rootRouter;
                    settings.model = theRouter.activeItem();
                    settings.attachedToParent = theRouter.attachedToParent;
                    settings.compositionComplete = theRouter.compositionComplete;
                    settings.activate = false;
                }

                composition.compose(element, settings, bindingContext);
            }
        };

        ko.virtualElements.allowedBindings.router = true;
    };

    return rootRouter;
});
<|endoftext|>


<commit_before>'use strict';

import fs from 'fs';
import path from 'path';

/******************************************************************************/

function findSuffixes (name, files) {
  let result = [];
  for (let file of files) {
    const regex = new RegExp (`${name}\.([a-zA-Z]+)\.js`);
    const match = file.match (regex);
    if (match) {
      result.push (match[1]);
    }
  }
  return result;
}

/******************************************************************************/

export default function processDirectory (root, dir, suffix, next) {
  if (typeof dir === 'string') {
    dir = [dir];
  }
  if (Array.isArray (dir) === false) {
    throw new Error ('dir should be a string or an array of strings');
  }

  const filter  = new RegExp (suffix.replace ('.', '\\.') + '$');
  const pattern = new RegExp ('([^\\/\\\\]+)' + filter.source);
  let   result  = [];

  function extract (dirs, file, files) {
    const matches = file.match (pattern);
    if (matches) {
      const name = matches[1];
      const filePath = [...dirs, file].join (path.sep);
      const suffixes = findSuffixes (name, files.filter (x => x !== file));
      result.push ([name, filePath, suffixes]);
    }
  }

  traverse (root, dir, extract, err => {
    if (err) {
      next (err);
    } else {
      result.sort ((a, b) => a[1].localeCompare (b[1]));
      next (err, result);
    }
  });
}

/******************************************************************************/

function traverse (root, dirs, collect, next) {
  const rootPath = path.join (root, ...dirs);
  fs.lstat (rootPath, (err, stats) => {
    if (err) {
      next (err);
    } else {
      fs.readdir (rootPath, (err, files) => {
        let pending = files.length;
        for (let file of files) {
          const filePath = path.join (root, ...dirs, file);
          fs.lstat (filePath, (err, stats) => {
            if (err) {
              next (err);
            } else {
              if (stats.isDirectory ()) {
                traverse (root, [...dirs, file], collect, err => {
                  if (err) {
                    next (err);
                  } else {
                    if (--pending === 0) {
                      next ();
                    }
                  }
                });
              } else {
                if (stats.isFile ()) {
                  collect (dirs, file, files);
                  if (--pending === 0) {
                    next ();
                  }
                }
              }
            }
          });
        }
      });
    }
  });
}

/******************************************************************************/
<commit_msg>Revert last commit<commit_after>'use strict';

import fs from 'fs';
import path from 'path';

/******************************************************************************/

function findSuffixes (name, files) {
  let result = [];
  for (let file of files) {
    const regex = new RegExp (`${name}\.([a-zA-Z]+)\.js`);
    const match = file.match (regex);
    if (match) {
      result.push (match[1]);
    }
  }
  return result;
}

/******************************************************************************/

export default function processDirectory (root, dir, suffix, next) {
  if (typeof dir === 'string') {
    dir = [dir];
  }
  if (Array.isArray (dir) === false) {
    throw new Error ('dir should be a string or an array of strings');
  }

  const filter  = new RegExp (suffix.replace ('.', '\\.') + '$');
  const pattern = new RegExp ('([^\\/\\\\]+)' + filter.source);
  let   result  = [];

  function extract (dirs, file, files) {
    const matches = file.match (pattern);
    if (matches) {
      const name = matches[1];
      const filePath = [...dirs, file].join ('/');
      const suffixes = findSuffixes (name, files.filter (x => x !== file));
      result.push ([name, filePath, suffixes]);
    }
  }

  traverse (root, dir, extract, err => {
    if (err) {
      next (err);
    } else {
      result.sort ((a, b) => a[1].localeCompare (b[1]));
      next (err, result);
    }
  });
}

/******************************************************************************/

function traverse (root, dirs, collect, next) {
  const rootPath = path.join (root, ...dirs);
  fs.lstat (rootPath, (err, stats) => {
    if (err) {
      next (err);
    } else {
      fs.readdir (rootPath, (err, files) => {
        let pending = files.length;
        for (let file of files) {
          const filePath = path.join (root, ...dirs, file);
          fs.lstat (filePath, (err, stats) => {
            if (err) {
              next (err);
            } else {
              if (stats.isDirectory ()) {
                traverse (root, [...dirs, file], collect, err => {
                  if (err) {
                    next (err);
                  } else {
                    if (--pending === 0) {
                      next ();
                    }
                  }
                });
              } else {
                if (stats.isFile ()) {
                  collect (dirs, file, files);
                  if (--pending === 0) {
                    next ();
                  }
                }
              }
            }
          });
        }
      });
    }
  });
}

/******************************************************************************/
<|endoftext|>


<commit_before>/**
 *  Vic Shóstak <truewebartisans@gmail.com>
 *  Copyright (c) 2019 True web artisans https://1wa.co
 *  http://opensource.org/licenses/MIT The MIT License (MIT)
 *
 *  goodshare.js
 *
 *  Twitter (https://twitter.com) provider.
 */

import { ProviderMixin } from "../utils/ProviderMixin";

export class Twitter extends ProviderMixin {
  constructor(url = document.location.href, title = document.title) {
    super();
    this.url = encodeURIComponent(url);
    this.title = encodeURIComponent(title);
    this.createEvents = this.createEvents.bind(this);
  }

  getPreparedData(item) {
    const url = item.dataset.url
      ? encodeURIComponent(item.dataset.url)
      : this.url;
    const title = item.dataset.title
      ? encodeURIComponent(item.dataset.title)
      : this.title;
    const share_url = `https://twitter.com/share?url=${url}&text=${title}`;

    return {
      callback: this.callback,
      share_url: share_url,
      windowTitle: "Share this",
      windowWidth: 640,
      windowHeight: 480
    };
  }

  // Share event
  shareWindow() {
    const share_elements = document.querySelectorAll('[data-social="twitter"]');

    return this.createEvents(share_elements);
  }
}
<commit_msg>Update Twitter.js<commit_after>/**
 *  Vic Shóstak <truewebartisans@gmail.com>
 *  Copyright (c) 2019 True web artisans https://1wa.co
 *  http://opensource.org/licenses/MIT The MIT License (MIT)
 *
 *  goodshare.js
 *
 *  Twitter (https://twitter.com) provider.
 */

import { ProviderMixin } from "../utils/ProviderMixin";

export class Twitter extends ProviderMixin {
  constructor(url = document.location.href, title = document.title, hashtags = "") {
    super();
    this.url = encodeURIComponent(url);
    this.title = encodeURIComponent(title);
    // Allow easy discovery of Tweets by topic by including a comma-separated list of hashtag values without the preceding # character.
    this.hashtags = encodeURIComponent(hashtags);
    this.createEvents = this.createEvents.bind(this);
  }

  getPreparedData(item) {
    const url = item.dataset.url
      ? encodeURIComponent(item.dataset.url)
      : this.url;
    const title = item.dataset.title
      ? encodeURIComponent(item.dataset.title)
      : this.title;
    // Allow easy discovery of Tweets by topic by including a comma-separated list of hashtag values without the preceding # character.
    // example: nature,sunset
    const hashtags = item.dataset.hashtags
      ? encodeURIComponent(item.dataset.hashtags)
      : this.hashtags;
    const share_url = `https://twitter.com/share?url=${url}&text=${title}&hashtags=${hashtags}`;

    return {
      callback: this.callback,
      share_url: share_url,
      windowTitle: "Share this",
      windowWidth: 640,
      windowHeight: 480
    };
  }

  // Share event
  shareWindow() {
    const share_elements = document.querySelectorAll('[data-social="twitter"]');

    return this.createEvents(share_elements);
  }
}
<|endoftext|>


<commit_before>const logger = require('../lib/logger');

module.exports = () =>
  (err, req, res, next) => {
    res.statusCode = err.status || 500;
    res.body = { error: err.message };
    if (res.statusCode >= 500) {
      req.error = err;
      logger.error({
        error: req,
      });
      req.body = { error: 'Internal Error' };
    }
    next();
  };

<commit_msg>error properties are non-enumerable<commit_after>const logger = require('../lib/logger');

module.exports = () =>
  (err, req, res, next) => {
    res.statusCode = err.status || 500;
    res.body = { error: err.message };
    if (res.statusCode >= 500) {
      req.error = {
        message: err.message,
        stack: err.stack,
      };
      logger.error({
        error: req,
      });
      req.body = { error: 'Internal Error' };
    }
    next();
  };

<|endoftext|>


<commit_before>//----------------------------------------------------------------------------//
var express = require('express');
var router = express.Router();
var pg = require('pg');
var connectionString = require('../modules/db-config.module');
//----------------------------------------------------------------------------//

// Edit user profile info ----------------------------------------------------//
router.put('/update', function(req, res) {
  // console.log('ARRIVED IN EDIT ROUTE');
  // console.log('USER DATA:', req.body.userData);
  var userData = req.body.userData;
  var userId = req.userStatus.userId;

  var queryObject = profileEditQueryBuilder(userData, userId);

  if (queryObject.queryString !== 'UPDATE mentors SE WHERE id = $1') {
    pg.connect(connectionString, function(error, client, done) {
      connectionErrorCheck(error);

      // Update the database
      client.query(queryObject.queryString, queryObject.propertyArray,
        function(error, result) {
          done(); // Close connection to the database

          if(error) {
            console.log('Unable to update user information: ', error);
            res.sendStatus(500);
          } else {
            res.sendStatus(200);
          }

        }
      );
    });
  }
});
//----------------------------------------------------------------------------//

// Create a new FAQ entry ----------------------------------------------------//
router.post('/new-faq', function(req, res) {
  var userId = req.userStatus.userId;
  var question = req.body.faqData.question;
  var answer = req.body.faqData.answer;
  console.log("FAQ OBJECT:", req.body.faqData);

  pg.connect(connectionString, function(error, client, done) {
    connectionErrorCheck(error);

    client.query(
      'INSERT INTO faq (mentor_id, question, answer) VALUES ($1, $2, $3)',
      [userId, question, answer],
      function(error, result) {
        done(); // Close connection to the database

        if(error) {
          console.log('Error when creating new FAQ: ', error);
          res.sendStatus(500);
        } else {
          res.sendStatus(201);
        }
      }
    );
  });
});
//----------------------------------------------------------------------------//

// Edit an existing FAQ entry ------------------------------------------------//
router.put('/edit-faq', function(req, res) {
  var userId = req.userStatus.userId;
  var faqArray = req.body.faqArray;
  console.log('--- profile-edit.route faqArray: ', faqArray);

  var queryObject = faqEditQueryBuilder(faqArray, userId);

  pg.connect(connectionString, function(error, client, done) {
    connectionErrorCheck(error);

    client.query(
      'UPDATE faq SET question = $1 AND answer = $2 WHERE id = $3',
      [question, answer, faqId],
      function(error, result) {
        done(); // Close connection to the database

        if(error) {
          console.log('Error when updating FAQ: ', error);
          res.sendStatus(500);
        } else {
          res.sendStatus(201);
        }
      }
    );
  });
});
//----------------------------------------------------------------------------//

module.exports = router;

// Checks for errors connecting to the database ------------------------------//
function connectionErrorCheck(error) {
  if (error) {
    console.log('Database connection error: ', error);
    res.sendStatus(500);
  }
}
//----------------------------------------------------------------------------//

// Cunstructs SQL query based off of the profile fields ----------------------//
function profileEditQueryBuilder(object, userId) {
  // console.log('OBJECT IN QUERY BUILDER', object);
  var query = 'UPDATE mentors SET ';
  var array = [];
  var index = 0;

  for (var property in object) {
    if (object[property]) {
      index++;
      query += property + ' = $' + index + ', ';
      array.push(object[property]);
    }
  }

  index++;
  query = query.slice(0, -2);
  query += ' WHERE id = $' + index;
  array.push(userId);

  return {
    queryString: query,
    propertyArray: array
  };
}
//----------------------------------------------------------------------------//

// Constructs SQL query based off of updated FAQ info ------------------------//
function faqEditQueryBuilder(object, userId) {
  var query = '';
  var array = [];
  var index = 0;

}
//----------------------------------------------------------------------------//
<commit_msg>More work on building FAQ edit query builder<commit_after>//----------------------------------------------------------------------------//
var express = require('express');
var router = express.Router();
var pg = require('pg');
var connectionString = require('../modules/db-config.module');
//----------------------------------------------------------------------------//

// Edit user profile info ----------------------------------------------------//
router.put('/update', function(req, res) {
  // console.log('ARRIVED IN EDIT ROUTE');
  // console.log('USER DATA:', req.body.userData);
  var userData = req.body.userData;
  var userId = req.userStatus.userId;

  var queryObject = profileEditQueryBuilder(userData, userId);

  if (queryObject.queryString !== 'UPDATE mentors SE WHERE id = $1') {
    pg.connect(connectionString, function(error, client, done) {
      connectionErrorCheck(error);

      // Update the database
      client.query(queryObject.queryString, queryObject.propertyArray,
        function(error, result) {
          done(); // Close connection to the database

          if(error) {
            console.log('Unable to update user information: ', error);
            res.sendStatus(500);
          } else {
            res.sendStatus(200);
          }

        }
      );
    });
  }
});
//----------------------------------------------------------------------------//

// Create a new FAQ entry ----------------------------------------------------//
router.post('/new-faq', function(req, res) {
  var userId = req.userStatus.userId;
  var question = req.body.faqData.question;
  var answer = req.body.faqData.answer;
  console.log("FAQ OBJECT:", req.body.faqData);

  pg.connect(connectionString, function(error, client, done) {
    connectionErrorCheck(error);

    client.query(
      'INSERT INTO faq (mentor_id, question, answer) VALUES ($1, $2, $3)',
      [userId, question, answer],
      function(error, result) {
        done(); // Close connection to the database

        if(error) {
          console.log('Error when creating new FAQ: ', error);
          res.sendStatus(500);
        } else {
          res.sendStatus(201);
        }
      }
    );
  });
});
//----------------------------------------------------------------------------//

// Edit an existing FAQ entry ------------------------------------------------//
router.put('/edit-faq', function(req, res) {
  var userId = req.userStatus.userId;
  var faqArray = req.body.faqArray;
  console.log('--- profile-edit.route faqArray: ', faqArray);

  var queryObject = faqEditQueryBuilder(faqArray, userId);

  pg.connect(connectionString, function(error, client, done) {
    connectionErrorCheck(error);

    client.query(queryObject.queryString, queryObject.propertyArray,
      function(error, result) {
        done(); // Close connection to the database

        if(error) {
          console.log('Error when updating FAQ: ', error);
          res.sendStatus(500);
        } else {
          res.sendStatus(201);
        }
      }
    );
  });
});
//----------------------------------------------------------------------------//

module.exports = router;

// Checks for errors connecting to the database ------------------------------//
function connectionErrorCheck(error) {
  if (error) {
    console.log('Database connection error: ', error);
    res.sendStatus(500);
  }
}
//----------------------------------------------------------------------------//

// Cunstructs SQL query based off of the profile fields ----------------------//
function profileEditQueryBuilder(object, userId) {
  var query = 'UPDATE mentors SET ';
  var array = [];
  var index = 0;

  for (var property in object) {
    if (object[property]) {
      index++;
      query += property + ' = $' + index + ', ';
      array.push(object[property]);
    }
  }

  index++;
  query = query.slice(0, -2);
  query += ' WHERE id = $' + index;
  array.push(userId);

  return {
    queryString: query,
    propertyArray: array
  };
}
//----------------------------------------------------------------------------//

// Constructs SQL query based off of updated FAQ info ------------------------//
function faqEditQueryBuilder(faqArray, userId) {
  // console.log('ARRAY IN QUERY BUILDER', array);

  var queryString = 'UPDATE faq SET ';
  var propertyArray = [];
  var questionString = 'question = CASE';
  var answerString = '';

  for (var index = 0; index < faqArray.length; index++) {
    questionString += ' WHEN ' + faqArray[index].id + ' THEN ' + faqArray[index].question;
    answerString += ' WHEN ' + faqArray[index].id + ' THEN ' + faqArray[index].answer;
  }

  console.log('questionString: ', questionString);
  console.log('answerString: ', answerString);

  // console.log('--- profile.edit queryString: ', queryString);
  // console.log('--- profile.edit propertyArray: ', propertyArray);
  // console.log('--- profile.edit index: ', index);

  return {
    queryString: queryString,
    propertyArray: propertyArray
  };
}
//----------------------------------------------------------------------------//
<|endoftext|>