DEV Community

Cover image for Transform Your dev.to Experience with a Custom Extension!
Dhanush Adithya
Dhanush Adithya

Posted on

Transform Your dev.to Experience with a Custom Extension!

Preface

Hey there dev.to community!

Have you ever found yourself scrolling through a long article on dev.to, trying to find a specific section? Well, worry no more - today we're going to create a Table of Contents (ToC) extension to make navigation a breeze!

Steps

  • Creating the Extension Structure
  • Setting up the Extension for Development
  • Building the ToC (Table of Contents)
  • Publishing the Extension

Creating the Extension Structure

.
└── dev.toc/
    ├── extension.css
    ├── extension.js
    └── manifest.json
Enter fullscreen mode Exit fullscreen mode

Setting up the Extension for Development

  • Chrome & Edge
    1. Click on (or in Edge) in the top-right corner
    2. Select "More Tools" and "Extensions"
    3. Click on the "Load Unpacked" button on the top-left side of the page.
    4. Choose the folder containing the extension or select the extension manifest file
  • Firefox
    1. Go to about:debugging#/runtime/this-firefox
    2. Select "Load Temporary Add-ons"
    3. Choose the folder containing the extension or select the extension manifest file

Building the ToC

First, we’ll add the following to our manifest.json file,

{
    "manifest_version": 3, // 2 for firefox
    "name": "Dev.to Table of Contents",
    "short_name": "dev.toc",
    "version": "1.0",
    "description": "Add table of contents to dev.to articles",
    "content_scripts": [
        {
            "matches": [ "https://dev.to/*/*" ],
            "js": ["extension.js"]
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

We specified the following in the manifest file

  • manifest_version and extension version
  • name and short_name
  • description
  • content_scripts
    • matches - the URL we need this extension to run
    • js - the extension.js we created that’ll add the ToC for the articles

(more about manifest file here)

We will now work on the extension.js file, using the mockup as a reference, to create the Table of Contents

ToC

Let’s select the article-body element, which is the main container element for the article's content

Next, we create an array of all the heading elements within the article-body element by using the Array.from method to convert the articleBody.children NodeList into an array, and then filtering this array to only include heading tags with the regular expression /h[1-6]/g. This regular expression will match any heading element, from h1 to h6.

const articleBody = document.getElementById("article-body");
const articleHeadings = Array.from(articleBody.children).filter(
    (e) => /h[1-6]/g.test(e.localName)
);
Enter fullscreen mode Exit fullscreen mode

Then we’ll create a details element, which will serve as the container for the TOC with a summary element and a ul element, which will be used as the heading and list, respectively, for the ToC.

const tocDetails = document.createElement("details");
const tocSummary = document.createElement("summary");
tocSummary.textContent = "Table of Contents";
const tocList = document.createElement("ul");
Enter fullscreen mode Exit fullscreen mode

The code then creates a li element and an a element, which will be used to create a link to the main title of the article (or the Go to Top link). The a element's href attribute is set to #main-title, and its textContent is set to the article title

Next, let’s add an event listener to the a element that will prevent the default behavior of the click event (i.e., following the link) and instead scroll the page smoothly back to the top when the link is clicked.

The li and a elements are then appended to the ToC list, and the ToC list is appended to the details element.

const titleItem = document.createElement("li");
const titleAnchor = document.createElement("a");
titleAnchor.href = "#main-title";
titleAnchor.textContent = document
    .querySelector(".crayons-article__header__meta h1")
    .textContent.trim();

titleAnchor.addEventListener("click", (e) => {
    e.preventDefault();
    tocDetails.open = false;
    window.scrollTo({ top: 0, behavior: "smooth" });
});

titleItem.append(titleAnchor);
tocList.append(titleItem);

tocDetails.append(tocSummary);
tocDetails.append(tocList);
Enter fullscreen mode Exit fullscreen mode

Finally, if there are any heading elements within the article-body element, we will create a nested ul element and iterate over the heading elements, creating a new li and a element for each one.

The a element's href attribute is set to the heading element, and its textContent is set to the heading element's text content. An event listener is added to the a element that’ll prevent the default behavior and do the smooth scroll to the position of the heading element just like before. The li and a elements are then appended to the nested ul element, and the nested ul element is appended to the main ToC list.

if (articleHeadings.length > 0) {
    const headingList = document.createElement("ul");
    for (const heading of articleHeadings) {
        const headingItem = document.createElement("li");
        const headingLink = document.createElement("a");
        headingLink.href = Array.from(heading.children)[0].href;
        headingLink.textContent = heading.textContent.trim();

        headingLink.addEventListener("click", (e) => {
            e.preventDefault();
            tocDetails.open = false;
            const headingTop = heading.offsetTop;
            window.scrollTo({ top: headingTop - 35, behavior: "smooth" });
        });

        headingItem.append(headingLink);
        headingList.append(headingItem);
    }
    tocList.append(headingList);
}
Enter fullscreen mode Exit fullscreen mode

At last, the ToC is inserted at the beginning of the article-body element.

articleBody.prepend(tocDetails);
Enter fullscreen mode Exit fullscreen mode

Note: Be sure to reload the extension after every change you make (The reload button will be on the same page where you load the extension for development purpose)

After adding styling to the elements, the final result will look like this,

  • ToC close ToC close
  • ToC open ToC open

(I tried my best to match the stylings with dev.to styles)

Publishing the Extension

  • Chrome

Publishing an extension on Chrome is simple. All you need to do is create a developer account, upload your extension through the Chrome Web Store Developer Dashboard, and wait for it to be reviewed by the Chrome team. Once your extension has been approved, it will be available for download to millions of Chrome users around the world.

  • Firefox

The process for publishing on Firefox is similar to Chrome, with a developer account and submission through the Firefox Add-ons Developer Hub.

Next steps

Great job on building a browser extension! Now it's time to take it to the next level and create your own (or improve this extension). Make sure to test it out before publishing. And don't forget to keep it updated, maintain it regularly and share it with the community.

Resources

GitHub logo DhanushAdithya / dev.toc

A browser extension that adds a Table of Contents to dev.to articles

dev.toc

A browser extension that adds a Table of Contents to any dev.to article


Happy Coding!

Top comments (0)