Slugs.vue 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. <template>
  2. <!-- <aside to="body"> -->
  3. <ul class="slugs">
  4. <li v-for="{ level, link, title } of slugs" :class="`slug-item level-${level}`" :key="link">
  5. <a :href="link" class="link">
  6. {{ title }}
  7. </a>
  8. </li>
  9. </ul>
  10. <!-- </aside> -->
  11. </template>
  12. <script lang="ts">
  13. import { computed } from 'vue';
  14. import { useRoute } from 'vitepress';
  15. export default {
  16. setup() {
  17. const route = useRoute();
  18. const slugs = computed(() => {
  19. // only display two level
  20. const headers = (route.data.headers ?? []).filter((i) => i.level > 1);
  21. let minLevel = 10;
  22. for (const { level } of headers) {
  23. minLevel > level && (minLevel = level);
  24. }
  25. return headers
  26. .filter((h) => h.level < minLevel + 2)
  27. .map((h) => ({
  28. ...h,
  29. link: `#${h.slug}`,
  30. level: h.level === minLevel ? 1 : 2,
  31. }));
  32. });
  33. return {
  34. slugs,
  35. };
  36. },
  37. };
  38. </script>
  39. <style scoped>
  40. .slug-item {
  41. list-style: none;
  42. font-size: 14px;
  43. white-space: nowrap;
  44. text-overflow: ellipsis;
  45. overflow: hidden;
  46. padding: 4px 0 4px 16px;
  47. margin: 0;
  48. border-left: 2px solid #ebedf1;
  49. }
  50. .level-2 {
  51. font-size: 13px;
  52. padding-left: 28px;
  53. }
  54. .link {
  55. color: var(--text-color);
  56. }
  57. .slugs {
  58. transform: translateX(100%);
  59. transition: transform 0.25s ease;
  60. }
  61. @media (min-width: 900px) {
  62. .slugs {
  63. transform: translateX(0);
  64. }
  65. }
  66. </style>