enhanceApp.js 2.8 KB
Newer Older
D
DCloud_LXH 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
function handleRedirectForCleanUrls(router, to) {
  if (isRouteExists(router, to.path)) {
    return to.path
  } else {
    if (!/(\/|\.html)$/.test(to.path)) {
      const endingSlashUrl = to.path + '/'
      const endingHtmlUrl = to.path + '.html'
      if (isRouteExists(router, endingHtmlUrl)) {
        return endingHtmlUrl
      } else if (isRouteExists(router, endingSlashUrl)) {
        return endingSlashUrl
      } else {
        return to.path
      }
    } else if (/\/$/.test(to.path)) {
      const endingHtmlUrl = to.path.replace(/\/$/, '') + '.html'
      if (isRouteExists(router, endingHtmlUrl)) {
        return endingHtmlUrl
      } else {
        return to.path
      }
    } else {
      return to.path
    }
  }
}

function isRouteExists(router, path) {
  const pathLower = path.toLowerCase()
  return router.options.routes.some(route => route.path.toLowerCase() === pathLower)
}

function handlePath(router, to) {
  const id = to.query.id
  const redirectPath = handleRedirectForCleanUrls(router, to)

  if (id) {
    return {
      path: redirectPath,
      hash: '#' + decodeURIComponent(id.toLowerCase())
    }
  }
  if (redirectPath !== to.path) {
    return {
      path: redirectPath,
      hash: decodeURIComponent(to.hash).toLowerCase()
    }
  }
  if (/\bREADME\b/.test(to.path)) {
    return {
      path: to.path.replace(/\bREADME\b/, ''),
      hash: decodeURIComponent(to.hash).toLowerCase()
    }
  }
}

export default ({
  Vue,
  options,
  router,
  siteData
}) => {
  let mounted = false
  const ScrollBehavior = 'smooth'

  router.beforeHooks.unshift((to, from, next) => {
    next(handlePath(router, to))
  })

  router.options.scrollBehavior = function scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return window.scrollTo({
        top: savedPosition.y,
        behavior: ScrollBehavior,
      });
    }
    else if (to.hash) {
      if (Vue.$vuepress.$get('disableScrollBehavior')) {
        return false;
      }
      const selector = decodeURIComponent(to.hash)
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (!mounted) mounted = true
          const targetElement = document.querySelector(selector);
          if (targetElement) {
            return window.scrollTo({
              top: getElementPosition(targetElement).y,
              behavior: ScrollBehavior,
            });
          }
          return resolve(false);
        }, mounted ? 0 : 700)
      })
    }
    else {
      return window.scrollTo({
        top: 0,
        behavior: ScrollBehavior,
      });
    }
  }
}

function getElementPosition(el) {
  const docEl = document.documentElement;
  const docRect = docEl.getBoundingClientRect();
  const elRect = el.getBoundingClientRect();
  return {
    x: elRect.left - docRect.left,
    y: elRect.top - docRect.top,
  };
}