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
Create Table of Contents #1
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall this approach is fine and it works but it's a little problematic from a perf perspective IMO
you're passing down html
through props in your React and then dynamically building an entire new DOM representation of your current page during each rerender of TableOfContents just to parse it and find the header tags, then dynamically render some stuff to make them a TOC
This can become really suboptimal if you have a really long post or a not-so-great computer. Instead, you could try a different approach:
-
[not great] just parse the
html
string directly instead of doingdocument.createElement
and making an entire new DOM representation of the page. This is still not great because you still have to pass down thehtml
string, seems like a big waste, also parsing the string directly can be complicated / expensive still -
[best?] generate the TOC at build time. I haven't looked into the specifics of this yet but it definitely should be possible, and I think this is the "optimal" solution. You push all the heavy computation (generating TOCs) to build time, and at actual runtime everything is very light: you only pass down the minimum data needed to render TOC to the client (very little data, just some strings really) and the render is extremely cheap.
const AStart = `<a href=#${id} >`; | ||
const AEnd = '</a>'; | ||
|
||
node.removeAttribute('id'); | ||
|
||
return AStart + node.outerHTML + AEnd; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit this could all have just been one template string that reads clearer
return `<a href=#${id}>${node.outerHTML}</a>`;
This PR adds a sticky table of contents to the right of posts. It's only visible for screen sizes of
$layout-breakpoint-lg
(1100px
) and up (I considered shoving it under the title for smaller screens but think it looks too much of a long boi).On MBP 13":

In😬
Post.js
, I pass in thehtml
string to the component. Then I create anhtml
document element in order to traverse the DOM tree and grab the header elements. For each of header elements, I remove their one child (which was thegatsby-remark-autolink-headers
anchor. Then I wrap the header node in an<a>
tag, with the header'sid
as thehref
. IMPORTANT: you have to remove theid
attribute of the header or elsegatsby-remark-autolink-headers
breaks since it'll use the links in this new component. Finally, IdangerouslySetInnerHTML
this generated string. Honestly, not very elegant at allCurrently, the CSS only supports up to
h4
because I don't anticipate using smaller headers than that (don't even think I useh4
s anywhere yet).Iffy about:
text-shadow
hover -- it's not super apparent; maybe underline is better?max-width
/max-height
/positioning of component (I did a jank calculation)