vitepress
vitepress copied to clipboard
feat(theme): support nested headings in outline
resolve #954
- [x] no breaking change
- [x] test added
- [x] new frontmatter config added
@brc-dd Friendly ping. Could you take a review or is there something else I could provide to this PR to ensure the functionality?
Hi! Kia will have a look on this one.
Rest of the stuff seems fine. I still haven't checked the UI though.
Made an update with a new commit and some refactoring. And I think I made another breaking change 😅.
before:
There would be an outline title without items but only a title when the content does not have h2/h3 headings, such as ##### xx.
now:
Outline will only be displayed when there are really outline items to display.
Rest of the stuff seems fine. I still haven't checked the UI though.
The UI is like this, I'm also wondering is there a better way to release a preview build for custom config and docs that can reveal the different UI.
Made an update with a new commit and some refactoring. And I think I made another breaking change 😅.
before:
There would be an outline title without items but only a title when the content does not have h2/h3 headings, such as
##### xx.
This was probably a bug 😅. Thanks for fixing that! 🙌
I created a stackblitz project to preview the affection on UI.
- project https://github-b4nsvg--3000.local.webcontainer.io/
- live show https://github-b4nsvg--3000.local.webcontainer.io/guide/what-is-vitepress.html
I think we can do more things to make preview more easy in two ways:
- Provide a stackblitz like which will be created from the branch of the PR via a comment by GitHub bot for each PR automatically. So the reviewer can know the UI affection by changing some file or the PR author could provide the demo as above.
- Add example docs that contain different use cases of Vitepress which could also be used by E2E test, and deploy a preview link by Netlify for each PR.
@fi3ework Is there a way not to add this on every file: outline: "deep", otherwise it would be too much trouble
@fi3ework Is there a way not to add this on every file: outline: "deep", otherwise it would be too much trouble
Yes, it should support. Seems like I lost some code with the app configuration. 😅 I'll bring it back later.
@fi3ework Is there a way not to add this on every file: outline: "deep", otherwise it would be too much trouble
Yes, it should support. Seems like I lost some code with the app configuration. 😅 I'll bring it back later. Haha, trouble you,😁😁😁
Ready to be reviewed again.
I kind of want to add preview deploy for examples before this PR. But multiple sites deploy Netlify (doc) require setting permission to add a new site for the example site that I don't have. If there is any vuejs member who has permission also thinks of a preview deployment of examples to facilitate observing UI changes of code, let me know and I would like to come up with the PR with your help of setting Netlify.
would it make sense to add a max depth in this pr?
would it make sense to add a max depth in this pr?
max depth is supported in this PR. Using like this - [2, 4]
Can we fix #785 here itself? I can fix that separately too, but then this would need rebase and might cause other issues. Here is the diff on vite-3 branch. You will need to modify then manually apply it. That query selector h2 thing probably need to be made h2, h3, h4, h5, h6. Also probably we need something like .innerText.split('\n')[0] instead of textContent.
diff --git a/src/client/theme-default/components/VPDocAside.vue b/src/client/theme-default/components/VPDocAside.vue
index 4232d15..2f590ab 100644
--- a/src/client/theme-default/components/VPDocAside.vue
+++ b/src/client/theme-default/components/VPDocAside.vue
@@ -3,7 +3,7 @@ import { useData } from 'vitepress'
import VPDocAsideOutline from './VPDocAsideOutline.vue'
import VPDocAsideCarbonAds from './VPDocAsideCarbonAds.vue'
-const { page, theme } = useData()
+const { theme } = useData()
</script>
<template>
@@ -11,7 +11,7 @@ const { page, theme } = useData()
<slot name="aside-top" />
<slot name="aside-outline-before" />
- <VPDocAsideOutline v-if="page.headers.length" />
+ <ClientOnly><VPDocAsideOutline /></ClientOnly>
<slot name="aside-outline-after" />
<div class="spacer" />
diff --git a/src/client/theme-default/components/VPDocAsideOutline.vue b/src/client/theme-default/components/VPDocAsideOutline.vue
index dad4378..42acb27 100644
--- a/src/client/theme-default/components/VPDocAsideOutline.vue
+++ b/src/client/theme-default/components/VPDocAsideOutline.vue
@@ -1,25 +1,35 @@
<script setup lang="ts">
-import { ref, computed } from 'vue'
-import { useData } from 'vitepress'
-import {
- resolveHeaders,
- useOutline,
- useActiveAnchor
-} from '../composables/outline.js'
-
-const { page, frontmatter, theme } = useData()
-
-const { hasOutline } = useOutline()
+import { useData, useRoute, type Header } from 'vitepress'
+import { computed, ref, watch } from 'vue'
+import { resolveHeaders, useActiveAnchor } from '../composables/outline.js'
+
+const { frontmatter, theme } = useData()
+const route = useRoute()
+
+const headers = ref<Header[]>([])
+
+watch(
+ () => route.path,
+ () => {
+ document.querySelectorAll('h2').forEach((el) => {
+ if (el.textContent && el.id)
+ headers.value.push({
+ level: Number(el.tagName[1]),
+ title: el.textContent,
+ slug: el.id
+ })
+ })
+ },
+ { immediate: true }
+)
+
+const hasOutline = computed(() => !!headers.value.length)
+const resolvedHeaders = computed(() => resolveHeaders(headers.value))
const container = ref()
const marker = ref()
-
useActiveAnchor(container, marker)
-const resolvedHeaders = computed(() => {
- return resolveHeaders(page.value.headers)
-})
-
function handleClick({ target: el }: Event) {
const id = '#' + (el as HTMLAnchorElement).href!.split('#')[1]
const heading = document.querySelector<HTMLAnchorElement>(
Looking forward this feature.