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

Support explicit heading IDs #1608

Closed
tesseralis opened this issue Jan 30, 2019 · 12 comments
Closed

Support explicit heading IDs #1608

tesseralis opened this issue Jan 30, 2019 · 12 comments

Comments

@tesseralis
Copy link
Member

We currently auto-generate IDs for headings and often link to those generated IDs. As pointed out by @smikitky, this causes issues with translation (see #1605). If article sections are translated (which they should), the generated IDs will be inconsistent with the English ones, which means translators will need to search for links to those sections and change them correspondingly.

There are two steps needed for this:

First, adding support for custom heading IDs in the markdown parser (I checked, we don't support the syntax right now). While this isn't strictly necessary, it would be a great aid for translators and prevent them from having to write ugly html (<h2 id="examples">Amplesexay</h2>).

Second, create a script and node task to add explicit IDs to all headings, and a test/lint to make sure that all headings have an explicit heading. The task allows English documentation writers to not worry about creating IDs whenever they write new blog posts/documentation. The test helps ensure that IDs are consistent among the English and international versions of the documentation.

We also may want to consider things like warning when generated IDs are too long (#what-do-hooks-mean-for-popular-apis-like-redux-connect-and-react-router), or allowing headings in code blocks (## `Context.Provider` ) to not have an explicit heading, since those should not be translated anyway.

@tesseralis
Copy link
Member Author

Another approach would be a plugin that verifies that all links have a reference (https://github.com/remarkjs/remark-validate-links). This might be the preferable approach, since it'll complain if a heading is translated but a link to it is not. @smikitky, what do you think?

@smikitky
Copy link
Member

smikitky commented Jan 31, 2019

I usually use markdown-it and have no experience about marked, but if there is no appropriate plug-in, I'm wondering if this approach is usable. Something like:

const renderer = new marked.Renderer();
renderer.heading = (text, level) => {
  const [, caption, id] = /(.+)\s*\{#(.+)\}$/.exec(text);
  return `<h${level} id=${id}>${caption}</h${level}>`;
}
marked.setOptions({renderer});

I think enforcing the existence of valid IDs at the original repository's level is the safer approach. If an original markdown file in English defines an explicit, "source-of-truth" ID, translators can just leave it unchanged, and there is little chance to introduce a bug during the i18n process. However, if there is no ID in the original source file, translators of all languages independently have to generate it, compare it with the auto-generated one using a browser, and test it instead. Even if there is a means to detect broken links, this would be a lot of duplication of error-prone tasks, and it would be harder to maintain cross-language consistency. In addition, if I understand correctly, a broken link detector cannot detect misspelled IDs that are not linked from other articles of the same site. Such headings may be linked from some external articles.

After all, since IDs are IDs, I see no reason not to define it in the original :)

Either way, I found slugify extensions both for Atom and for VSCode (not tested), which may be useful.

@smikitky
Copy link
Member

Of course, if we only look at English files, an explicit ID may look redundant, but it has its own advantages:

  • You can choose arbitrary short IDs for long headings
  • You can rephrase the text without worrying about breaking links (including ones from external sites)

I suppose Hooks FAQ could have been much cleaner and easier-to-maintain with explicit IDs.

@tesseralis
Copy link
Member Author

Upon further research I really like how yarnpkg.com does it:

### Creating your first package <a class="toc" id="toc-creating-your-first-package" href="#toc-creating-your-first-package"></a>

The toc style generates the following style:

@media (min-width: 768px)
.toc::before {
    position: absolute;
    display: inline-block;
    right: 100%;
}

Essentially, the link creates the anchor element, no plugins needed! And it would be easy to create a script to auto-generate the ids.

@gaearon @smikitky what do you think of this approach?

@smikitky
Copy link
Member

smikitky commented Feb 6, 2019

You mean we can't use the ## Foo Bar {#foo-bar} syntax?

I may be completely wrong since I know almost nothing about Gatsby, but can't we tweak this file to add this syntax? https://github.com/reactjs/reactjs.org/blob/7d12082d8b57b5317d28986c382b251950914587/gatsby/onCreateNode.js

@tesseralis
Copy link
Member Author

Not right now, and I have too much on my plate right now to really dive in and learn since I'm also not really familiar with gatsby/remark. Since this seems like an important issue to you, maybe you'd like to try to research some more?

@smikitky
Copy link
Member

smikitky commented Feb 6, 2019

Okay, I'll try, I was thinking of using Gatsby in my future projects, anyway :)

@tesseralis
Copy link
Member Author

Thank you so much! And if we get this done we can probably publish it as a plugin :D

@smikitky
Copy link
Member

smikitky commented Feb 6, 2019

@tesseralis I created a PR to support this syntax. Please check #1636.

@tesseralis
Copy link
Member Author

tesseralis commented Feb 6, 2019

@smikitky do you want to do the next step (auto add ids to all the current headers)?

If not, I can probably get to it tonight.

@smikitky
Copy link
Member

smikitky commented Feb 6, 2019

@tesseralis I don't have time to do that for today, so could you do that part? The task should be basically simple, but I am wondering if there are a few "pseudo-headings" within fenced code blocks...

Type this command:

```bash
# This is a *comment* in a fenced code block
$ node hello-world
```

@tesseralis
Copy link
Member Author

Good point! I'll be careful about that...

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

No branches or pull requests

2 participants