<commit_before>/**
 * Marionette Routing
 *
 * Copyright © 2015-2016 <NAME>. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import _ from 'underscore'
import Radio from 'backbone.radio'
import cherrytree from 'cherrytree'
import Route from './route'

let mnRouteMap = Object.create(null)
export const routerChannel = Radio.channel('router')
let router

export function createRouter(options) {
  if (router) {
    throw new Error('Instance of router already created')
  }
  return router = Route.prototype.$router = cherrytree(options)
}

export function destroyRouter(instance) {
  router = null
  Route.prototype.$router = null
  mnRouteMap = Object.create(null)
  instance.destroy()
}

export function getMnRoutes(routes) {
  return routes.map(function (route) {
    return mnRouteMap[route.name]
  })
}

routerChannel.reply('transitionTo', function () {
  return router.transitionTo.apply(router, arguments)
})

routerChannel.reply('isActive', function () {
  return router.isActive.apply(router, arguments)
})

routerChannel.reply('generate', function () {
  return router.generate.apply(router, arguments)
})

routerChannel.reply('goBack', function () {
  //in wait of a better implementation
  history.back();
})

function getChangingIndex(prevRoutes, currentRoutes){
  var index, prev, current;
  const count = Math.max(prevRoutes.length, currentRoutes.length)
  for (index = 0; index < count; index++) {
    prev = prevRoutes[index]
    current = currentRoutes[index]
    if (!(prev && current) || (prev.name !== current.name) || !_.isEqual(prev.params, current.params)) {
      break
    }
  }
  return index
}

function findRouteConfig(routeName, index, routes) {
  let parentRoutes = routes.slice(0, index).reverse().map(function (route) {
    return mnRouteMap[route.name]
  })
  let config
  parentRoutes.some(function (route) {
    let childRoutes = _.result(route, 'childRoutes')
    config = childRoutes && childRoutes[routeName]
    if (_.isFunction(config) && !(config.prototype instanceof Route)) {
      config = config.call(route)
    }
    return config
  })
  return config
}

function createRouteInstance(options, config) {
  if (options.prototype instanceof Route) {
    return new options(undefined, config)
  }
  let routeOptions = _.extend({}, options.routeOptions, _.pick(options, ['viewClass', 'viewOptions']))
  if (options.routeClass) {
    return new options.routeClass(routeOptions, config)
  } else if (options.viewClass) {
    return new Route(routeOptions, config)
  }
}

function createMnRoute(route, index, routes) {
  let instanceConfig = {
    name: route.name,
    path: route.path,
    options: _.clone(route.options)
  }
  let instance = createRouteInstance(route.options, instanceConfig)
  if (!instance) {
    let routeConfig = findRouteConfig(route.name, index, routes)
    return Promise.resolve(routeConfig).then(function (options) {
      return options && createRouteInstance(options, instanceConfig)
    })
  }
  return instance
}

function getParentRegion(routes, route) {
  var region, parent
  let routeIndex = routes.indexOf(route) - 1
  while (routeIndex >= 0) {
    parent = routes[routeIndex]
    if (parent.view && parent.$config.options.outlet !== false) {
      region = parent.getOutlet()
      if (region) {
        return region
      } else {
        throw new Error(`No outlet region defined in ${parent.$config.name} route`)
      }
    }
    routeIndex--
  }
  return router.rootRegion
}

function renderViews (mnRoutes, activated, transition) {
  //ensure at least the target (last) route is rendered
  let renderCandidates = activated.length ? activated : mnRoutes.slice(-1)

  let renderQueue = renderCandidates.reduce(function (memo, mnRoute) {
    if (mnRoute.viewClass) {
      if (memo.length && memo[memo.length - 1].$config.options.outlet === false) {
        memo.pop()
      }
      memo.push(mnRoute)
    }
    return memo
  }, [])

  renderQueue.forEach(function (mnRoute) {
    let parentRegion = getParentRegion(mnRoutes, mnRoute)
    mnRoute.renderView(parentRegion, transition)
  })
}

function isActivatingRoute (route) {
  return this.activating && this.activating.indexOf(route) !== -1
}

export function middleware(transition) {

  transition.isActivating = isActivatingRoute

  routerChannel.trigger('before:transition', transition)

  if (transition.isCancelled) return ;

  let prevRoutes = transition.prev.routes
  let changingIndex = getChangingIndex(prevRoutes, transition.routes)
  var routeIndex, routeInstance, deactivated = []

  //deactivate previous routes
  for (routeIndex = prevRoutes.length - 1; routeIndex >= changingIndex; routeIndex--) {
    routeInstance = mnRouteMap[prevRoutes[routeIndex].name]
    if (routeInstance) {
      deactivated.push(routeInstance)
    }
  }

  if (deactivated.some(function (route) {
      routerChannel.trigger('before:deactivate', transition, route)<commit_msg>Add isTarget method to transition<commit_after>/**
 * Marionette Routing
 *
 * Copyright © 2015-2016 <NAME>. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import _ from 'underscore'
import Radio from 'backbone.radio'
import cherrytree from 'cherrytree'
import Route from './route'

let mnRouteMap = Object.create(null)
export const routerChannel = Radio.channel('router')
let router

export function createRouter(options) {
  if (router) {
    throw new Error('Instance of router already created')
  }
  return router = Route.prototype.$router = cherrytree(options)
}

export function destroyRouter(instance) {
  router = null
  Route.prototype.$router = null
  mnRouteMap = Object.create(null)
  instance.destroy()
}

export function getMnRoutes(routes) {
  return routes.map(function (route) {
    return mnRouteMap[route.name]
  })
}

routerChannel.reply('transitionTo', function () {
  return router.transitionTo.apply(router, arguments)
})

routerChannel.reply('isActive', function () {
  return router.isActive.apply(router, arguments)
})

routerChannel.reply('generate', function () {
  return router.generate.apply(router, arguments)
})

routerChannel.reply('goBack', function () {
  //in wait of a better implementation
  history.back();
})

function getChangingIndex(prevRoutes, currentRoutes){
  var index, prev, current;
  const count = Math.max(prevRoutes.length, currentRoutes.length)
  for (index = 0; index < count; index++) {
    prev = prevRoutes[index]
    current = currentRoutes[index]
    if (!(prev && current) || (prev.name !== current.name) || !_.isEqual(prev.params, current.params)) {
      break
    }
  }
  return index
}

function findRouteConfig(routeName, index, routes) {
  let parentRoutes = routes.slice(0, index).reverse().map(function (route) {
    return mnRouteMap[route.name]
  })
  let config
  parentRoutes.some(function (route) {
    let childRoutes = _.result(route, 'childRoutes')
    config = childRoutes && childRoutes[routeName]
    if (_.isFunction(config) && !(config.prototype instanceof Route)) {
      config = config.call(route)
    }
    return config
  })
  return config
}

function createRouteInstance(options, config) {
  if (options.prototype instanceof Route) {
    return new options(undefined, config)
  }
  let routeOptions = _.extend({}, options.routeOptions, _.pick(options, ['viewClass', 'viewOptions']))
  if (options.routeClass) {
    return new options.routeClass(routeOptions, config)
  } else if (options.viewClass) {
    return new Route(routeOptions, config)
  }
}

function createMnRoute(route, index, routes) {
  let instanceConfig = {
    name: route.name,
    path: route.path,
    options: _.clone(route.options)
  }
  let instance = createRouteInstance(route.options, instanceConfig)
  if (!instance) {
    let routeConfig = findRouteConfig(route.name, index, routes)
    return Promise.resolve(routeConfig).then(function (options) {
      return options && createRouteInstance(options, instanceConfig)
    })
  }
  return instance
}

function getParentRegion(routes, route) {
  var region, parent
  let routeIndex = routes.indexOf(route) - 1
  while (routeIndex >= 0) {
    parent = routes[routeIndex]
    if (parent.view && parent.$config.options.outlet !== false) {
      region = parent.getOutlet()
      if (region) {
        return region
      } else {
        throw new Error(`No outlet region defined in ${parent.$config.name} route`)
      }
    }
    routeIndex--
  }
  return router.rootRegion
}

function renderViews (mnRoutes, activated, transition) {
  //ensure at least the target (last) route is rendered
  let renderCandidates = activated.length ? activated : mnRoutes.slice(-1)

  let renderQueue = renderCandidates.reduce(function (memo, mnRoute) {
    if (mnRoute.viewClass) {
      if (memo.length && memo[memo.length - 1].$config.options.outlet === false) {
        memo.pop()
      }
      memo.push(mnRoute)
    }
    return memo
  }, [])

  renderQueue.forEach(function (mnRoute) {
    let parentRegion = getParentRegion(mnRoutes, mnRoute)
    mnRoute.renderView(parentRegion, transition)
  })
}

function isActivatingRoute (route) {
  return this.activating && this.activating.indexOf(route) !== -1
}

function isTargetRoute (route) {
  return this.mnRoutes && this.mnRoutes.indexOf(route) === this.mnRoutes.length - 1
}

export function middleware(transition) {

  transition.isActivating = isActivatingRoute
  transition.isTarget = isTargetRoute

  routerChannel.trigger('before:transition', transition)

  if (transition.isCancelled) return ;

  let prevRoutes = transition.prev.routes
  let changingIndex = getChangingIndex(prevRoutes, transition.routes)
  var routeIndex, routeInstance, deactivated = []

  //deactivate previous routes
  for (routeIndex = prevRoutes.length - 1; routeIndex >= changingIndex; routeIndex--) {
    routeInstance = mnRouteMap[prevRoutes[routeIndex].name]
    if (routeInstance) {
      deactivated.push(routeInstance)
    }
  }

  if (deactivated.some(function (route) {
      routerChannel.trigger('before:deactivate', transition, route)
{'fraction_non_alphanumeric': 0.11728395061728394, 'fraction_numerical': 0.003233392122281011, 'mean_word_length': 4.000979911807938, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1972494', 'n_tokens_mistral': 3064, 'n_tokens_neox': 3009, 'n_words': 755}