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

Table of contents with linkable headers #58

Open
HugoGranstrom opened this issue Jun 19, 2021 · 12 comments
Open

Table of contents with linkable headers #58

HugoGranstrom opened this issue Jun 19, 2021 · 12 comments
Labels
2023H1 enhancement New feature or request
Milestone

Comments

@HugoGranstrom
Copy link
Collaborator

Initial discussion here: SciNim/getting-started#21

The cheatsheet example has links to specific headers. This makes it easy to refer to specific sections of a post. The current implementation needs some work though, optimally the headers themself (or a symbol in front/after of them) should be clickable so one easily can copy the link.

The discussed approaches:

  • Hook into the rendering of the markdown and find the headers and insert links.
  • Explicit nbHeader, nbSubHeader etc, templates
@pietroppeter pietroppeter added the enhancement New feature or request label Sep 21, 2021
@pietroppeter
Copy link
Owner

both approaches will need anyway something that translates heading into anchors (e.g. "My smart heading" -> "my-smart-heading"). I note down here for future reference a discussion on how it is done in github: https://gist.github.com/asabaylus/3071099

I also have some thoughts about pros and cons of the two approaches. I will add some comments later on.

@pietroppeter
Copy link
Owner

my current thoughts on how we should do this, and the related issue of being able to add an inline toc is to do post processing the html of each block, add anchor link to each header and update a toc element in nb.context. This should be doable automatically after this is completed: #35

(to add the inline toc then one would have a nbToc or similar command to place it where you want.)

@pietroppeter pietroppeter changed the title Make headers linkable Table of contents with linkable headers Mar 6, 2022
@pietroppeter
Copy link
Owner

after completing #78 I changed my mind and I think we could do like we do in cheatsheet, only making the api better and a bit more general.

@pietroppeter
Copy link
Owner

pietroppeter commented Oct 26, 2022

I think I figured out the api:

# add field to NbDoc:
type
  NbDoc = object
    ...
    headings: seq[Heading]
    ...
  Heading = object
    level: int
    title: str
    anchor: str

template nbHeading(text: string)
  let level = ... # count numbers of "#" chars at beginning of text
  assert level > 0, "nbHeading must start with at least one #"
  let firstLine = ... # first line of text
  let restLines = ... # other lines of text, if there are other
  let anchor = ... # derive from firstLine
  # create a new block with command nbHeading and anchor and firstLine as data
  # add a new Heading object to NbDoc
  # process restLines (if there are) as in nbText

# rendering of nbHeading is with a partial like this (headingAsHtml is processed from firstLine)
"""<a href="{{anchor}}">{{headingAsHtml}}</a>"""

# we could also have an overload that allows to provide a custom anchor
template nbHeading(anchor: string, text: string)

template nbToc # a placeholder block that when rendered accesses nb.headings and renders it
# it will likely have some TocOptions to customize appearance (how many levels? skip first level? numbered? ...)

Notes:

  • I would go with heading instead of header (googling one vs the other seems heading is better, considered also section but is usually a specific heading, see also toc on wikipedia)
  • having anchor outside of element is fine with html5, edit: on secound thougts maybe better anchor inside header
  • I thought of requiring nbHeading to have only one line, but I guess it is fine to have more lines that are treated like a nbText (one can always give one line and use nbText for the rest).

@HugoGranstrom
Copy link
Collaborator Author

This all sounds good to me 👍 I don't have any preferences regarding the anchor inside/outside the header tag. We will probably want to add some styling to it regardless.

@pietroppeter
Copy link
Owner

Yep it would be nice to have the link icon on hover like in GitHub

@pietroppeter
Copy link
Owner

as an additional remark, when generating anchor text from headers we might want to do as nim documentation does it, where the anchor will be generated from current heading and the parent heading, if it exists (check examples from manual...).

I guess this is done to help disambiguate common subsection names:

# Animals -> #animals
## birds -> # animals-birds
### what do they eat? -> #birds-what-do-they-eat
## cats -> #animals-cats
### what do they eat? -> #cats-what-do-they-eat

incidentally, ran into this feature while following up on an old "mistake" of mine, see nim-lang/Nim#20688

@pietroppeter
Copy link
Owner

and it seems that github does not do that, though: https://github.com/nim-lang/nimble#tests
I wonder if they manage somehow the collisions...

@pietroppeter pietroppeter added this to the 2023H1 milestone Feb 1, 2023
@beef331
Copy link

beef331 commented Mar 8, 2023

It's probably naive but is there any reason not to just treat all markdown headers as headings in HTML? If someone really does not want the heading they could use nbText(noHeadings = true): .... Though perhaps this view just comes from my annoyance of seeing headings that are not linkable on webpages or having to inspect the page to get the id for an entry. 😄

@pietroppeter
Copy link
Owner

that's indeed one of the approaches mentioned at the beginning: :)

Hook into the rendering of the markdown and find the headers and insert links.

indeed to support this (treating all heading as anchors) a third option - other than change the markdown parser - is to postprocess html. But changing markdown parser is actually something that looks to be easy, we recently had some conversations about it so I would probably say at the moment this might be the way to go.

I agree with the annoyance of non linkable headings!

@pietroppeter
Copy link
Owner

pietroppeter commented Mar 8, 2023

changing markdown parser

and just to make this a bit more concrete, we would need to inherit from current heading parsers and customize rendering to add a slug with the anchor:

@pietroppeter
Copy link
Owner

this PR on nim-markdown motivated me to actually write what it would take to get have linkable headings by default (see my comment there), it should not be to hard: soasme/nim-markdown#67 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2023H1 enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants