PageSidebarTocLink.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <script>
  2. import { isActive, hashRE, groupHeaders } from '../util'
  3. export default {
  4. functional: true,
  5. props: ['item', 'sidebarDepth'],
  6. render (h,
  7. {
  8. parent: {
  9. $page,
  10. $site,
  11. $route,
  12. $themeConfig,
  13. $themeLocaleConfig
  14. },
  15. props: {
  16. item,
  17. sidebarDepth
  18. }
  19. }) {
  20. // use custom active class matching logic
  21. // due to edge case of paths ending with / + hash
  22. const selfActive = isActive($route, item.path)
  23. // for sidebar: auto pages, a hash link should be active if one of its child
  24. // matches
  25. const active = item.type === 'auto'
  26. ? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug))
  27. : selfActive
  28. const link = item.type === 'external'
  29. ? renderExternal(h, item.path, item.title || item.path)
  30. : renderLink(h, item.path, item.title || item.path, active)
  31. const maxDepth = [
  32. $page.frontmatter.sidebarDepth,
  33. sidebarDepth,
  34. $themeLocaleConfig.sidebarDepth,
  35. $themeConfig.sidebarDepth,
  36. 1
  37. ].find(depth => depth !== undefined)
  38. const displayAllHeaders = $themeLocaleConfig.displayAllHeaders
  39. || $themeConfig.displayAllHeaders
  40. if (item.type === 'auto') {
  41. return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)]
  42. } else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) {
  43. const children = groupHeaders(item.headers)
  44. return [link, renderChildren(h, children, item.path, $route, maxDepth)]
  45. } else {
  46. return link
  47. }
  48. }
  49. }
  50. function renderLink (h, to, text, active) {
  51. return h('router-link', {
  52. props: {
  53. to,
  54. activeClass: '',
  55. exactActiveClass: ''
  56. },
  57. class: {
  58. active,
  59. 'toc-sidebar-link': true
  60. }
  61. }, text)
  62. }
  63. function renderChildren (h, children, path, route, maxDepth, depth = 1) {
  64. if (!children || depth > maxDepth) return null
  65. return h('ul', { class: 'toc-sidebar-sub-headers' }, children.map(c => {
  66. const active = isActive(route, path + '#' + c.slug)
  67. return h('li', { class: 'toc-sidebar-sub-header' }, [
  68. renderLink(h, path + '#' + c.slug, c.title, active),
  69. renderChildren(h, c.children, path, route, maxDepth, depth + 1)
  70. ])
  71. }))
  72. }
  73. function renderExternal (h, to, text) {
  74. return h('a', {
  75. attrs: {
  76. href: to,
  77. target: '_blank',
  78. rel: 'noopener noreferrer'
  79. },
  80. class: {
  81. 'toc-sidebar-link': true
  82. }
  83. }, [text, h('OutboundLink')])
  84. }
  85. </script>
  86. <style lang="stylus">
  87. .toc-sidebar .toc-sidebar-sub-headers
  88. padding-left 1rem
  89. font-size 0.95em
  90. a.toc-sidebar-link
  91. font-size 1em
  92. font-weight 400
  93. display inline-block
  94. color $textColor
  95. //border-left 0.25rem solid transparent
  96. //padding 0.35rem 1rem 0.35rem 1.25rem
  97. line-height 1
  98. width: 100%
  99. box-sizing: border-box
  100. &:hover
  101. color $accentColor
  102. &.active
  103. font-weight 600
  104. color $accentColor
  105. border-left-color $accentColor
  106. .toc-sidebar-sub-headers &
  107. padding-top 0.25rem
  108. padding-bottom 0.25rem
  109. border-left none
  110. font-weight 300
  111. &.active
  112. font-weight 500
  113. </style>