Blinking highlight targeted heading v2.11.1
Demo
Try clicking the following two links and observe the changes of the title elements:
When we click on the outline on the right to navigate, there will be a yellow blinking block flashing around the targeted title element.
Why
Today's documentation websites will support reading the Hash ID passed in the URL and then scrolling the page until the Hash ID selected element appears or appears at the top position. This function is usually triggered by the user clicking the anchor icon on the left or right of the title, or clicking the interactive and selectable outline list on the right.
However, most of the targeted title elements of the documentation website will not highlight and indicate where the currently highlighted title line is after clicking.
What is the targeted title? How does this feature work?
When you click on the link in the outline on the right or directly click the link button on the left of the title, pay attention to the changes in the address bar.
You will find that there is a #
symbol in the URL, followed by an ID, which is the ID of the targeted title.
The ID of the targeted title mentioned here is actually the ID of the HTML element, so in theory, not only can the framework and the browser be required to scroll the title element into the viewport, but also other valid elements with matching HTML IDs.
This kind of element can be found by pressing F12 to open the developer tool, and then enter
document.querySelector('#why')
in the console to find it. This code will return an HTML element, which is what we call the "targeted title".
Why do you need to highlight?
- When user clicks one of the titles, the page scrolls to the position where the title is located, but the user does not know where the current title is due to the fact that there are several titles on the screen.
- When user clocks one of the titles, the page is already at the bottom of the page, and the user cannot learn how to find the title by a fixed "look at the top of the viewport to find and locate the title" repeatable behavior pattern. Such scenario is even more critical when several titles appear at the end of the document.
At this time, being able to indicate and highlight the title that cannot be noticed is a very important thing, and this integration was born because of this.
How to install and configure
Install
You can install @nolebase/vitepress-plugin-highlight-targeted-heading
to the dependencies of the VitePress project with the following command:
pnpm add @nolebase/vitepress-plugin-highlight-targeted-heading -D
npm install @nolebase/vitepress-plugin-highlight-targeted-heading -D
yarn add @nolebase/vitepress-plugin-highlight-targeted-heading -D
Integrate with VitePress
It consists two major steps to integrate the Enhanced Readabilities plugin into your VitePress project:
Add plugin-specific options into configurations of Vite
First of all, in VitePress's primary configuration file (not this is not a theme configuration file, it's usually located at docs/.vitepress/config.ts
, file paths and extensions may be vary), you need to supply some of the Server-Side Rendering related options in the root configuration object of Vite.
Add the Blinking highlight targeted heading plugin package name @nolebase/vitepress-plugin-highlight-targeted-heading
into the Vite options that required by VitePress to process this plugin:
If you've never seen a colored diff before
This is a markup rule for displaying diff in the user interface (UI).
Red parts usually represents the lines you are going to remove, commonly appeared with a Minus sign -, or you could simply understand it as: this line will be removed.
Green parts usually represents the lines you are going to add, commonly appeared with a Plus sign +, or you could simply understand it as: this line will be added.
To learn more about diff, you can check out this answer about the history of diffutils and Git's documentation
A TypeScript User?
You need to configure at least the following options:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Bundler",
},
"include": [
"**/.vitepress/**/*.ts",
"**/.vitepress/**/*.mts",
"**/.vitepress/**/*.vue"
],
"exclude": [
"node_modules"
]
}
And the options
module
option specifies the JavaScript/TypeScript module format, and Nolebase Integrations uses theESNext
-compatible module format by default.moduleResolution
option specifies the module resolution policy, since all Nolebase Integrations plugins follow the latest ECMAScript specifications and export declarations, if you encounter aCannot find module ... or its corresponding type declarations
error you may need to setmoduleResolution
toBundler
.
If you want more configurations, you can refer to the following example:
{
"compilerOptions": {
"jsx": "preserve",
"lib": [
"DOM",
"ESNext"
],
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"strict": true,
"strictNullChecks": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noEmit": true,
"removeComments": false,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true
},
"include": [
"**/.vitepress/**/*.ts",
"**/.vitepress/**/*.mts",
"**/.vitepress/**/*.vue"
],
"exclude": [
"node_modules"
]
}
import { defineConfig } from 'vitepress'
// https://vitepress.dev/reference/site-config
export default defineConfig({
vite: {
ssr: {
noExternal: [
// If there are other packages that need to be processed by Vite, you can add them here.
'@nolebase/vitepress-plugin-highlight-targeted-heading',
],
},
},
lang: 'en',
title: 'Site Name',
themeConfig: {
// rest of the options...
}
// rest of the options...
})
You might have configured the separated Vite configuration file (e.g. vite.config.ts
) if you are already mastered Vite. In this case, you could ignore the above configuration and add the following configuration to your Vite configuration file:
If you've never seen a colored diff before
This is a markup rule for displaying diff in the user interface (UI).
Red parts usually represents the lines you are going to remove, commonly appeared with a Minus sign -, or you could simply understand it as: this line will be removed.
Green parts usually represents the lines you are going to add, commonly appeared with a Plus sign +, or you could simply understand it as: this line will be added.
To learn more about diff, you can check out this answer about the history of diffutils and Git's documentation
A TypeScript User?
You need to configure at least the following options:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Bundler",
},
"include": [
"**/.vitepress/**/*.ts",
"**/.vitepress/**/*.mts",
"**/.vitepress/**/*.vue"
],
"exclude": [
"node_modules"
]
}
And the options
module
option specifies the JavaScript/TypeScript module format, and Nolebase Integrations uses theESNext
-compatible module format by default.moduleResolution
option specifies the module resolution policy, since all Nolebase Integrations plugins follow the latest ECMAScript specifications and export declarations, if you encounter aCannot find module ... or its corresponding type declarations
error you may need to setmoduleResolution
toBundler
.
If you want more configurations, you can refer to the following example:
{
"compilerOptions": {
"jsx": "preserve",
"lib": [
"DOM",
"ESNext"
],
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"strict": true,
"strictNullChecks": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noEmit": true,
"removeComments": false,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true
},
"include": [
"**/.vitepress/**/*.ts",
"**/.vitepress/**/*.mts",
"**/.vitepress/**/*.vue"
],
"exclude": [
"node_modules"
]
}
import { defineConfig } from 'vite'
export default defineConfig(() => {
return {
ssr: {
noExternal: [
// If there are other packages that need to be processed by Vite, you can add them here.
'@nolebase/vitepress-plugin-highlight-targeted-heading',
],
},
optimizeDeps: {
exclude: ['vitepress'],
},
plugins: [
// other vite plugins...
],
// other vite configurations...
}
})
If you haven't configured any of the separated Vite configuration file (e.g. vite.config.ts
) before but still want to have a try with the above configuration, you can create a vite.config.ts
file in the root directory of your VitePress project and add the above configuration to it. (Don't forget to install vite
through your package manager as well!)
Add plugin into the Theme options of VitePress
In VitePress's theme configuration file (note that it's not a configuration file, it's usually located at docs/.vitepress/theme/index.ts
, file paths and extensions may be vary), import @nolebase/vitepress-plugin-highlight-targeted-heading
import and add it to the Layout
extension:
If you've never seen a colored diff before
This is a markup rule for displaying diff in the user interface (UI).
Red parts usually represents the lines you are going to remove, commonly appeared with a Minus sign -, or you could simply understand it as: this line will be removed.
Green parts usually represents the lines you are going to add, commonly appeared with a Plus sign +, or you could simply understand it as: this line will be added.
To learn more about diff, you can check out this answer about the history of diffutils and Git's documentation
A TypeScript User?
You need to configure at least the following options:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Bundler",
},
"include": [
"**/.vitepress/**/*.ts",
"**/.vitepress/**/*.mts",
"**/.vitepress/**/*.vue"
],
"exclude": [
"node_modules"
]
}
And the options
module
option specifies the JavaScript/TypeScript module format, and Nolebase Integrations uses theESNext
-compatible module format by default.moduleResolution
option specifies the module resolution policy, since all Nolebase Integrations plugins follow the latest ECMAScript specifications and export declarations, if you encounter aCannot find module ... or its corresponding type declarations
error you may need to setmoduleResolution
toBundler
.
If you want more configurations, you can refer to the following example:
{
"compilerOptions": {
"jsx": "preserve",
"lib": [
"DOM",
"ESNext"
],
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"strict": true,
"strictNullChecks": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noEmit": true,
"removeComments": false,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true
},
"include": [
"**/.vitepress/**/*.ts",
"**/.vitepress/**/*.mts",
"**/.vitepress/**/*.vue"
],
"exclude": [
"node_modules"
]
}
import { h } from 'vue'
import DefaultTheme from 'vitepress/theme'
import type { Theme as ThemeConfig } from 'vitepress'
import {
NolebaseHighlightTargetedHeading,
} from '@nolebase/vitepress-plugin-highlight-targeted-heading/client'
import '@nolebase/vitepress-plugin-highlight-targeted-heading/client/style.css' // [!code ++]*
export const Theme: ThemeConfig = {
extends: DefaultTheme,
Layout: () => {
return h(DefaultTheme.Layout, null, {
// other configurations...
'layout-top': () => [
h(NolebaseHighlightTargetedHeading),
],
})
},
enhanceApp() {
// other configurations...
},
}
export default Theme
That's it, it is usable now 🎉.
How to use
Now build or open the VitePress development server again, you will be able to observe that as long as there is an element with a corresponding ID in the #
in the URL, the following situations will take effect:
- Click the link button on the left of the title directly
- Click the link in the outline on the right directly
- The URL containing
#
is loaded for the first time
That's all, happy writing!
Troubleshooting
Encountered Cannot find module ... or its corresponding type declarations
error?
If you are encountering this error with Nolebase Integrations packages inside of .ts
or .vue
files, you may need to configure the moduleResolution
option in your tsconfig.json
file.
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Bundler",
},
"include": [
"**/.vitepress/**/*.ts",
"**/.vitepress/**/*.mts",
"**/.vitepress/**/*.vue"
],
"exclude": [
"node_modules"
]
}
If the error persists, please submit a GitHub issue for further assistance and troubleshooting.