nimib
nimib copied to clipboard
Table of contents with linkable headers
Initial discussion here: https://github.com/SciNim/getting-started/issues/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
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.
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: https://github.com/pietroppeter/nimib/pull/35
(to add the inline toc then one would have a nbToc
or similar command to place it where you want.)
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.
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 anbText
(one can always give one line and use nbText for the rest).
This all sounds good to me :+1: 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.
Yep it would be nice to have the link icon on hover like in GitHub
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 https://github.com/nim-lang/Nim/pull/20688
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...