Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Markdown headers with numbers break sub-navigation #1

Open
allanwhite opened this issue Apr 22, 2019 · 10 comments
Open

Markdown headers with numbers break sub-navigation #1

allanwhite opened this issue Apr 22, 2019 · 10 comments

Comments

@allanwhite
Copy link
Contributor

allanwhite commented Apr 22, 2019

Live demo: https://datica-docs-stack.netlify.com/docs/introduction

The app walks through the document to generate anchors in the markdown, and links from the sidebar (in layouts/Docs.vue). The page navigation works, but when headings start with numbers (# 1.1 Introduction for example; it’s a biz requirement on our side) I get queryselector errors. I’ve noticed a lot of trouble with in-page links being a gotcha for new Vue devs (requiring different handling). I can’t tell if it’s the dots or the numbers that are throwing it. The generated anchors look correct (the above would yield, #11-introduction, I’m not sure why it’s generating an error.

vue.runtime.esm.js [Vue warn]: Error in nextTick: "SyntaxError: Failed to execute 'querySelector' on 'Document': '#11-introduction' is not a valid selector."

The app currently parses the Markdown and injects IDs on headers, so they can be linked to (super cool!). Resulting markup:

<h2 id="11-platform-as-a-service-paas"><a href="#11-platform-as-a-service-paas" aria-hidden="true">#</a>1.1 Platform as a Service (PaaS)</h2>
@loke-dev
Copy link

loke-dev commented Apr 22, 2019

Seem to be an issue with ID's starting with a number. Would it be possible to escape the number like this #\1?

@allanwhite
Copy link
Contributor Author

@LokeCarlsson The challenge there is that it breaks markdown formatting, which is a problem for the content workflow I have (in my case, developers and legal experts writing documentation on healthcare compliance in the US). That also then is rendered in the document as \2.1 section title for example.

@allanwhite
Copy link
Contributor Author

allanwhite commented Apr 23, 2019

Two thoughts:

  • While HTML 4 was opinionated about IDs not starting with numbers, HTML5 has very few opinions about IDs (only that they have at least one character, even non-latin ones).
  • If I can find the place in vue that's generating the anchors, they could be prepended with a string like section_123-section-title or something, working around the limitation.

@allanwhite
Copy link
Contributor Author

I wonder if there's a way to configure the plugins that are transforming the markdown into HTML, like Remark-autolink-headings. Playing with the options seems to have no effect.

@eostrom
Copy link

eostrom commented Apr 24, 2019

A link to a fragment identifier that starts with a number works fine in plain HTML, so I think you could argue that this is a bug in whatever package is simulating link following (maybe Vue Router? Or some other part of Vue, or Gridsome). Of course, the road from moral correctness to locating the bug, submitting a PR or hoping someone else fixes it, getting it accepted and into a released version of the package might be too long to be practical...

... but if you want to travel it, I did find one thing that might help. This code works fine in a Chromium console:

document.querySelector('[id="11-platform-as-a-service-paas"]')

If you can find the code that's passing "#11-platform-as-a-service-paas" to querySelector and make it generate this selector instead, I think that would fix the bug. (Or, if this makes sense in context, getElementById("11-platform-as-a-service-pass").)

@eostrom
Copy link

eostrom commented Apr 24, 2019

Following up, you might be able to fix it here: https://github.com/gridsome/gridsome/blob/master/gridsome/app/router.js

    } else if (to.hash) {
      return { selector: `[id="${to.hash.substring(2)}"]`  }
    }

(You'd probably also have to escape the hash value in case it contains quotes or other characters that cause trouble.)

If that works, I also suggest submitting a documentation fix to vue-router: https://github.com/vuejs/vue-router/blob/dev/docs/guide/advanced/scroll-behavior.md

You may still run into compatibility problems if there are any browsers still that don't support HTML 5 ID rules.

@allanwhite
Copy link
Contributor Author

allanwhite commented Apr 24, 2019

@eostrom Thanks for looking at this! A seemingly simple, but vexing problem!

Okay soooo your code snippet was very close, it just needed to target 1 level higher (substring being a level deeper already, I think):

} else if (to.hash) {
  // return { selector: to.hash }
  return { selector: `[id="${to.hash.substring(1)}"]` }
}

Works, and didn't throw any errors. =) Now, the practical tasks of testing and submitting a PR to a huge project remain.

Great insights and thank you, Erik!

@allanwhite
Copy link
Contributor Author

It looks like there's a method to use a custom router, rather than the one built into the Gridsome node-module. This example is close but I haven't got it working yet, need to learn more about routing first.

@eostrom
Copy link

eostrom commented Apr 24, 2019

Nice – seems like that'll be a good short-term fix if it takes a while for the Gridsome PR to make its way through. (And yeah, I don't know why I typed 2 here. I used 1 in my informal test.)

@allanwhite
Copy link
Contributor Author

For anyone following, this is now at Gridsome core. gridsome/gridsome#380

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants