vuepress
vuepress copied to clipboard
URL fragment (hash anchor) lost when global guard fills in .html suffix
- [x] I confirm that this is an issue rather than a question.
Bug report
Steps to reproduce
- Create a vuepress site. This issue should be reproducible with the default theme and settings
- Create an .md page with heading titles. The issue is much clearer when smooth scrolling is off (so when combined with #2558 ), and with the target header is off-screen (if you need to scroll down to reach it).
- Instead of
mypage.html#mytitle
, navigate tomypage#mytitle
by following external links or by pasting the URL in the browser
Examples:
- without smooth scrolling, you can see the page losing the hash + no navigation happening https://docs.laravel-excel.com/3.1/getting-started/contributing#how-to-report-a-bug
- with smooth scrolling, you get smooth scrolled to your title but the fragment anchor is lost https://vuepress.vuejs.org/miscellaneous/local-development#vuepress-sandbox-setup
What is expected?
- The fragment hash is not lost
- The page scrolls down automatically to the desired spot.
What is actually happening?
Any URL fragment hash and query string are erased by this router guard: https://github.com/vuejs/vuepress/blob/38e98634af117f83b6a32c8ff42488d91b66f663/packages/%40vuepress/core/lib/client/redirect.js
Other relevant information
The fix is to patch the router object, instead of passing on just the path. Let me know if you'd approve a pull request:
if (isRouteExists(router, endingHtmlUrl)) {
next({
...to,
path: endingHtmlUrl
})
} else if (isRouteExists(router, endingSlashUrl)) {
next({
...to,
path: endingSlashUrl
})
} else {
next()
}
} else if (/\/$/.test(to.path)) {
const endingHtmlUrl = to.path.replace(/\/$/, '') + '.html'
if (isRouteExists(router, endingHtmlUrl)) {
next({
...to,
path: endingHtmlUrl
})
- Output of
npx vuepress info
in my VuePress project: As mentioned above, it reproduces with the official vuepress docs, so this is not particularly relevant.
Dirty hack. Until this gets fixed in the official version, I've patched the router global hooks:
export default ({
Vue, // the version of Vue being used in the VuePress app
options, // the options for the root Vue instance
router, // the router instance for the app
siteData // site metadata
}) => {
// ...apply enhancements for the site.
router.beforeHooks =[];
router.beforeEach((to, from, next) => { // fixed version
Please let's fix vuepress v1 and let me delete this abomination.