SideBarItem.js 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { useRoute, useSiteData } from 'vitepress';
  2. import { h } from 'vue';
  3. import { joinUrl, isActive } from '../utils';
  4. export const SideBarItem = (props) => {
  5. const { item: { link: relLink, text, children } } = props;
  6. const route = useRoute();
  7. const siteData = useSiteData();
  8. const link = resolveLink(siteData.value.base, relLink || '');
  9. const active = isActive(route, link);
  10. const headers = route.data.headers;
  11. const childItems = createChildren(active, children, headers);
  12. return h('li', { class: 'sidebar-item' }, [
  13. h(link ? 'a' : 'p', {
  14. class: { 'sidebar-link': true, active },
  15. href: link
  16. }, text),
  17. childItems
  18. ]);
  19. };
  20. function resolveLink(base, path) {
  21. return path
  22. ? // keep relative hash to the same page
  23. path.startsWith('#')
  24. ? path
  25. : joinUrl(base, path)
  26. : undefined;
  27. }
  28. function createChildren(active, children, headers) {
  29. if (children && children.length > 0) {
  30. return h('ul', { class: 'sidebar-items' }, children.map((c) => {
  31. return h(SideBarItem, { item: c });
  32. }));
  33. }
  34. return active && headers
  35. ? createChildren(false, resolveHeaders(headers))
  36. : null;
  37. }
  38. function resolveHeaders(headers) {
  39. return mapHeaders(groupHeaders(headers));
  40. }
  41. function groupHeaders(headers) {
  42. headers = headers.map((h) => Object.assign({}, h));
  43. let lastH2;
  44. headers.forEach((h) => {
  45. if (h.level === 2) {
  46. lastH2 = h;
  47. }
  48. else if (lastH2) {
  49. ;
  50. (lastH2.children || (lastH2.children = [])).push(h);
  51. }
  52. });
  53. return headers.filter((h) => h.level === 2);
  54. }
  55. function mapHeaders(headers) {
  56. return headers.map((header) => ({
  57. text: header.title,
  58. link: `#${header.slug}`,
  59. children: header.children ? mapHeaders(header.children) : undefined
  60. }));
  61. }