Vuepress: Menu links not displaying router-link-active

Created on 31 Jul 2019  路  7Comments  路  Source: vuejs/vuepress




  • [x] I confirm that this is an issue rather than a question.




Bug report

When using letters like 脝, 脴, 脜 in the menu text and menu links, the header active bottom border will not display. When using normal english characters in the text and links it works how it's supposed to.

Steps to reproduce

Use letters like 脝, 脴 or 脜 in the nav menu text.

What is expected?

The border-bottom router-link-active should display normally with the 脝, 脴, 脜 letters just like it does with normal text characters.

What is actually happening?

The router-link-active (bottom border) isn't displaying when using weird characters.

Other relevant information

  • Output of npx vuepress info in my VuePress project:

Environment Info:

System:
OS: Linux 5.2 Arch Linux undefined
CPU: (8) x64 Intel(R) Core(TM) i7-4770K CPU @ 3.50GHz
Binaries:
Node: 11.15.0 - /usr/bin/node
Yarn: 1.17.3 - /usr/bin/yarn
npm: 6.10.2 - /usr/bin/npm
Browsers:
Chrome: Not Found
Firefox: 68.0.1
npmPackages:
@vuepress/core: Not Found
@vuepress/theme-default: Not Found
vuepress: Not Found
npmGlobalPackages:
vuepress: 1.0.2

question or discussion

All 7 comments

After some investigation, this turns out to be a vue-router issue. The problem lies in the string comparison features of default Javascript. A similar issue is described on this Stackoverflow page:

https://stackoverflow.com/questions/10805711/javascript-string-comparison-fails-when-comparing-unicode-characters.

Since it takes a whole library just to add this functionality into the Vue router, it might become a router plugin or something, but I would recommend using kebabCase / slugCase formats when it comes to files and have the titles be user-friendly.

@posva Do you have some thoughts about this?

Here's the actual Vue Router snippet that does the comparison:

function isObjectEqual (a, b) {
  if ( a === void 0 ) a = {};
  if ( b === void 0 ) b = {};

  // handle null value #1566
  if (!a || !b) { return a === b }
  var aKeys = Object.keys(a);
  var bKeys = Object.keys(b);
  if (aKeys.length !== bKeys.length) {
    return false
  }
  return aKeys.every(function (key) {
    var aVal = a[key];
    var bVal = b[key];
    // check nested equality
    if (typeof aVal === 'object' && typeof bVal === 'object') {
      return isObjectEqual(aVal, bVal)
    }
    return String(aVal) === String(bVal)
  })
}

I don't understand very well what behavior is failing in Vue Router as a route with unicode is matched correctly and applies the active classes. Maybe there is a case that we didn't handle and in that case I will need a boiled down repro to check it

Thanks for the answers.

Small update to the problem:

After having tested it further, I've noticed that using unicode characters in the menu text CAN actually work, but only if you DON'T use unicode characters in the link. I am in a situation where I need to be able to use unicode chars in both the text and the link.

I've made a repo with some short descriptions that may or may not help you. I think I've probably explained it well enough/shown it for you to get what I mean.

https://github.com/Mbensler/testvuepress

So to sum it up: I can make it work with unicode characters like 脝, 脴, 脜 in the menu text, but not if i also use it in the link text(folder names), which is what i need.

I appreciate the help.

@posva is right. (thanks btw). I've tested it with the vue-router examples. I will dive a bit deeper. vuepress doesn't seem to do any custom matching..

Screenshot from 2019-08-06 21-38-25

please, let me know if you find something we need to fix on vue-router!

I've found the issue and the fix. The issue is related to ./package/@vuepress/core/lib/node/Page.js. All scanned filepaths are 'fixed' with encodeURI meaning the special chars get converted to their encoded form. This doesnt happen with the link's uri, that's why it does show the correct file, but its not matching it for the link to make it an active state.

Here's a snippet of that code:

    if (relative) {
      this.regularPath = encodeURI(fileToPath(relative))
    } else if (_path) {
      this.regularPath = encodeURI(_path)
    } else if (permalink) {
      this.regularPath = encodeURI(permalink)
    }

It could ofcourse be fixed by removing the encodeURI. However, there is a test explicitly checking if the paths are properly encoded, meaning that this might break existing dependants.

@ulivz To you have an idea of the impact that this change would bring? If it does have a breaking impact, I might add a PR with some config approach to make exceptions.

Found a nice workaround for now @Mbensler .

You can use permalinks in your frontmatter. For example in your README.md:

---
permalink: /the脜me
---

This would put the permalink as the matcher for the url and it will become active. Unfortunatly only for exact matches so you will need to add it to every sub readme file:

---
permalink: /the脜me/someintro.md
---
Was this page helpful?
0 / 5 - 0 ratings

Related issues

alinnert picture alinnert  路  3Comments

kid1412621 picture kid1412621  路  3Comments

lesliecdubs picture lesliecdubs  路  3Comments

higuoxing picture higuoxing  路  3Comments

gaomd picture gaomd  路  3Comments