From 7913caee5010b137b1a7e77d87491f6af09e2ec9 Mon Sep 17 00:00:00 2001 From: pengzhanbo Date: Wed, 9 Oct 2024 00:37:53 +0800 Subject: [PATCH] refactor(theme): improve headers active anchor (#258) --- pnpm-lock.yaml | 17 ----------------- theme/package.json | 1 - theme/src/client/composables/outline.ts | 21 ++++++++++++++++++++- theme/src/node/plugins/getPlugins.ts | 5 ----- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a6a3474d..a339ffc9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -325,9 +325,6 @@ importers: '@vuepress/helper': specifier: 2.0.0-rc.52 version: 2.0.0-rc.52(typescript@5.6.2)(vuepress@2.0.0-rc.17(@vuepress/bundler-vite@2.0.0-rc.17(@types/node@20.12.10)(jiti@1.21.6)(sass-embedded@1.79.4)(sass@1.79.4)(typescript@5.6.2)(yaml@2.5.1))(typescript@5.6.2)(vue@3.5.10(typescript@5.6.2))) - '@vuepress/plugin-active-header-links': - specifier: 2.0.0-rc.52 - version: 2.0.0-rc.52(typescript@5.6.2)(vuepress@2.0.0-rc.17(@vuepress/bundler-vite@2.0.0-rc.17(@types/node@20.12.10)(jiti@1.21.6)(sass-embedded@1.79.4)(sass@1.79.4)(typescript@5.6.2)(yaml@2.5.1))(typescript@5.6.2)(vue@3.5.10(typescript@5.6.2))) '@vuepress/plugin-cache': specifier: 2.0.0-rc.52 version: 2.0.0-rc.52(vuepress@2.0.0-rc.17(@vuepress/bundler-vite@2.0.0-rc.17(@types/node@20.12.10)(jiti@1.21.6)(sass-embedded@1.79.4)(sass@1.79.4)(typescript@5.6.2)(yaml@2.5.1))(typescript@5.6.2)(vue@3.5.10(typescript@5.6.2))) @@ -1778,11 +1775,6 @@ packages: '@vuepress/markdown@2.0.0-rc.17': resolution: {integrity: sha512-eIwRostE3t3zsJzPjmOufVyyBpsaWQkZluk6o0i1e9WLW3EoinKrDZdzej0Jw8IQlq6nvOPD2JMFWyXwu8fv7w==} - '@vuepress/plugin-active-header-links@2.0.0-rc.52': - resolution: {integrity: sha512-2QJbVTurvHuIAkO6YqXHoHkY6t4H6o0nktxbUjCiezkOGtiN2DHn4wpD2AFKjYstezIWDGbPianbBuGAZKr+aQ==} - peerDependencies: - vuepress: 2.0.0-rc.17 - '@vuepress/plugin-cache@2.0.0-rc.52': resolution: {integrity: sha512-CyRYVg32btWwW2mhzfY+zqgtXPqaMkJ6SRt5kL/SoKtPy6eh6qxz9Bu3bZzYA1+l8FPdln0sNNhL8+QCveUUYQ==} peerDependencies: @@ -7100,15 +7092,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@vuepress/plugin-active-header-links@2.0.0-rc.52(typescript@5.6.2)(vuepress@2.0.0-rc.17(@vuepress/bundler-vite@2.0.0-rc.17(@types/node@20.12.10)(jiti@1.21.6)(sass-embedded@1.79.4)(sass@1.79.4)(typescript@5.6.2)(yaml@2.5.1))(typescript@5.6.2)(vue@3.5.10(typescript@5.6.2)))': - dependencies: - '@vueuse/core': 11.1.0(vue@3.5.10(typescript@5.6.2)) - vue: 3.5.10(typescript@5.6.2) - vuepress: 2.0.0-rc.17(@vuepress/bundler-vite@2.0.0-rc.17(@types/node@20.12.10)(jiti@1.21.6)(sass-embedded@1.79.4)(sass@1.79.4)(typescript@5.6.2)(yaml@2.5.1))(typescript@5.6.2)(vue@3.5.10(typescript@5.6.2)) - transitivePeerDependencies: - - '@vue/composition-api' - - typescript - '@vuepress/plugin-cache@2.0.0-rc.52(vuepress@2.0.0-rc.17(@vuepress/bundler-vite@2.0.0-rc.17(@types/node@20.12.10)(jiti@1.21.6)(sass-embedded@1.79.4)(sass@1.79.4)(typescript@5.6.2)(yaml@2.5.1))(typescript@5.6.2)(vue@3.5.10(typescript@5.6.2)))': dependencies: ci-info: 4.0.0 diff --git a/theme/package.json b/theme/package.json index 42268bcb..2dd47213 100644 --- a/theme/package.json +++ b/theme/package.json @@ -103,7 +103,6 @@ "@vuepress-plume/plugin-search": "workspace:*", "@vuepress-plume/plugin-shikiji": "workspace:*", "@vuepress/helper": "2.0.0-rc.52", - "@vuepress/plugin-active-header-links": "2.0.0-rc.52", "@vuepress/plugin-cache": "2.0.0-rc.52", "@vuepress/plugin-comment": "2.0.0-rc.53", "@vuepress/plugin-docsearch": "2.0.0-rc.52", diff --git a/theme/src/client/composables/outline.ts b/theme/src/client/composables/outline.ts index 7780baf4..4774efb7 100644 --- a/theme/src/client/composables/outline.ts +++ b/theme/src/client/composables/outline.ts @@ -1,7 +1,9 @@ import type { InjectionKey, Ref } from 'vue' +import type { Router } from 'vuepress/client' import type { ThemeOutline } from '../../shared/index.js' import { onContentUpdated } from '@vuepress-plume/plugin-content-update/client' import { inject, onMounted, onUnmounted, onUpdated, provide, ref } from 'vue' +import { useRouter } from 'vuepress/client' import { throttleAndDebounce } from '../utils/index.js' import { useAside } from './aside.js' import { useData } from './data.js' @@ -161,6 +163,7 @@ export function resolveHeaders(headers: MenuItem[], range?: ThemeOutline): MenuI export function useActiveAnchor(container: Ref, marker: Ref): void { const { isAsideEnabled } = useAside() + const router = useRouter() let prevActiveLink: HTMLAnchorElement | null = null @@ -203,7 +206,7 @@ export function useActiveAnchor(container: Ref, marker: Ref< // find the last header above the top of viewport let activeLink: string | null = null for (const { link, top } of headers) { - if (top > scrollY + 144) + if (top > scrollY + 88) break activeLink = link @@ -239,6 +242,8 @@ export function useActiveAnchor(container: Ref, marker: Ref< marker.value.style.opacity = '0' } } + + updateHash(router, hash || '') } const onScroll = throttleAndDebounce(setActiveLink, 100) @@ -273,3 +278,17 @@ function getAbsoluteTop(element: HTMLElement): number { } return offsetTop } + +/** + * Update current hash and do not trigger `scrollBehavior` + */ +async function updateHash(router: Router, hash: string): Promise { + const { path, query } = router.currentRoute.value + const { scrollBehavior } = router.options + + // temporarily disable `scrollBehavior` + router.options.scrollBehavior = undefined + await router.replace({ path, query, hash }) + // restore it after navigation + router.options.scrollBehavior = scrollBehavior +} diff --git a/theme/src/node/plugins/getPlugins.ts b/theme/src/node/plugins/getPlugins.ts index 62592caa..1b8d48e2 100644 --- a/theme/src/node/plugins/getPlugins.ts +++ b/theme/src/node/plugins/getPlugins.ts @@ -1,6 +1,5 @@ import type { App, PluginConfig } from 'vuepress/core' import type { PlumeThemePluginOptions } from '../../shared/index.js' -import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links' import { cachePlugin } from '@vuepress/plugin-cache' import { commentPlugin } from '@vuepress/plugin-comment' import { docsearchPlugin } from '@vuepress/plugin-docsearch' @@ -44,10 +43,6 @@ export function getPlugins({ markdownTitlePlugin(), fontsPlugin(), contentUpdatePlugin(), - activeHeaderLinksPlugin({ - headerLinkSelector: 'a.outline-link', - headerAnchorSelector: '.header-anchor', - }), markdownHintPlugin({ hint: true, alert: true, injectStyles: false }), ...customContainerPlugins,