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

Next.js SSG + markdown-it #346

Open
realChakrawarti opened this issue May 11, 2024 · 10 comments
Open

Next.js SSG + markdown-it #346

realChakrawarti opened this issue May 11, 2024 · 10 comments

Comments

@realChakrawarti
Copy link

realChakrawarti commented May 11, 2024

I am using Next.js for SSG with markdown-it. I have markown files on disk locally from which I generate the HTML string.

I want the TOC HTML string at build time with my custom class name attached to the parent for styling it.

export default async function markdownToHtml(markdown: string) {
  const md = markdownit({
    html: true,
    linkify: true,
    typographer: true,
    highlight: function (str: string, lang: string) {
      if (lang && hljs.getLanguage(lang)) {
        try {
          return hljs.highlight(str, { language: lang }).value;
        } catch (__) {}
      }

      return ''; // use external default escaping
    },
  });
  md.use(anchor, {
    tabIndex: false,
    slugify: (s: string) => slugify(s),
    permalink: anchor.permalink.headerLink(),
  });
  md.linkify.set({ fuzzyEmail: false });
  const result = md.render(markdown);
  return result;
}

The idea is to pass the result to a function for example tocify(result) => HTML TOC content

Is this something possible, if so then how? Thanks.

@tscanlin
Copy link
Owner

tscanlin commented May 13, 2024

Hey, thanks for opening this issue! Currently this may be possible using jsdom on the server, but isn't natively supported since tocbot uses the browsers DOM methods and those are not typically available server side. However, this is something I'd be open to supporting better, if you have ideas for how this could be improved I'd love to hear them. Can you tell me any more about your use case? Thanks!

@realChakrawarti
Copy link
Author

My use-case is quite generic. I am using Next.js to statically build a blog/portfolio site and I serve this on GitHub Pages.

All the operations, from building page slugs to parsing markdown to HTML happens at the build time and I want to keep it that way for peace of mind 😄 and this approach ensures a faster loading experience for visitors as all content is pre-rendered and avoids any client-side processing for TOC generation.

For example, I have this blog https://realchakrawarti.github.io/aham/blog/microdata-seo where content is parsed by markdown-it, and using one of its plugin I add the heading IDs for quick links.

I want to generate the TOC at build time against the headings without adding a placeholder text to inject the TOC generated at runtime on like [[toc]] to the original markdown file.

The way I am thinking is, the user will pass the HTML string, for example in the above code snippet result to a function tocify(result) which will output the TOC parsed from the result HTML string as unordered/ordered list (configurable) as HTML string.

This eliminates the need for placeholders in the markdown and allows for TOC insertion anywhere.

My requirement is to add the TOC HTML inside an <aside /> tag using innerHTML (plainJs) or dangerouslySetInnerHTML (React like library, virtual dom) and position it accordingly.

@tscanlin
Copy link
Owner

Thanks for the explanation! Is this a feature you would be interested in contributing to tocbot?
I'd definitely appreciate a PR for this! Let me know what you think.

@realChakrawarti
Copy link
Author

Coming weekend, I would go over code once and see how I could go about making changes. If this ends up with quite a lot of changes and across files, would create a separate package altogether.

Keeping this issue open for now. Will close it with an update in a week or two. Thanks :D

@tscanlin
Copy link
Owner

Here is a quick utility I put together that handles SSR of the toc content that you could use at build time.
#347
Let me know if that works for you.

@realChakrawarti
Copy link
Author

Hi @tscanlin, I can see that #347 has been merged to the main branch but I didn't find any note on how serverRender API is exposed? While testing on the PR, I imported the function directly from node_modules after linking it. I thought serverRender to be a named export like this, import {serverRender} from 'tocbot' but this isn't the case.

Please do let me know if I am missing something. Thanks!

@tscanlin
Copy link
Owner

Hey, I was planning to keep this separate from the main bundle since not all users may use it.
But you should be able to import it with: import { serverRender } from 'tocbot/src/js/server-render.js'
Let me know if that doesn't work for you.

@realChakrawarti
Copy link
Author

Hi, this isn't working, tried with omitting the extension as well. module not found.
image
image

@tscanlin
Copy link
Owner

Hey, I forgot to add this into the exports, but I just pushed a fix to add the src/js folder. If you install the latest version (tocbot@4.28.2) it should work. Let me know if you still run into issues though.

@realChakrawarti
Copy link
Author

Hi, I was able import it and get this running but has 2 minor issues, non-blocking

  1. I am getting this error: ⨯ Error: Cannot find module 'jsdom' at build time. To get around this, had to install jsdom manually on my project though, then it worked fine.
  2. Type declaration, just ignoring it using //@ts-ignore for now
    image

Just letting you know. Thanks for supporting server generation of toc 👍🏼

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

2 participants