Using Dynamic Anchor Links in React Markdown

My development team’s project is currently using Contentful to manage site content. This creates a lower barrier for non-developers to make changes. Developers come up with a structure for the content, and content managers duplicate and arrange content as needed. Among the many different fields it supports, Contentful is able to allow Markdown for long text fields. In this way, content managers are able to go far with styling and structure. One little hiccup we’ve had recently is dynamically creating anchor tags with headers like GitHub flow markdown.

The Workaround

We are using React Markdown to parse the Contentful markdown, and, although the parser does not automatically generate anchor tags, there are ways around it. The goal is to allow content creators to create links to headers. For example, clicking on “below” links the page directly to the header “Sample Examples.”

 For more examples, see [below](#sample-examples).
 
 h2 Sample Examples

React Markdown allows customization for components, and that is where we can generate the dynamic anchor tag while it is being parsed.

     <div className="container">
       <ReactMarkdown
         remarkPlugins={[remarkGfm]}
         components={{
           h2: ({ node, ...props }) => (
             <h2 id={generateSlug(props.children[0])} {...props}></h2>
           ),
         }}
         children={content}
       ></ReactMarkdown>
     </div>
   
 
 const generateSlug = (string) => {
   let str = string.replace(/^\s+|\s+$/g, "");
   str = str.toLowerCase();
   str = str
     .replace(/[^a-z0-9 -]/g, "")
     .replace(/\s+/g, "-")
     .replace(/-+/g, "-");
 
   return str;
 };

Using Dynamic Anchor Tags in React Markdown

With this simple function, any H2 headers receive a dynamically-generated anchor tag that is based on the title. The only thing content creators need to keep in mind is adding the correct tag when they add the anchor link in Contentful.

Conversation

Join the conversation

Your email address will not be published. Required fields are marked *