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
Setting up the Extension for Development
- Chrome & Edge
- Click on
⋮
(or⋯
in Edge) in the top-right corner - Select "More Tools" and "Extensions"
- Click on the "Load Unpacked" button on the top-left side of the page.
- Choose the folder containing the extension or select the extension manifest file
- Click on
- Firefox
- Go to
about:debugging#/runtime/this-firefox
- Select "Load Temporary Add-ons"
- Choose the folder containing the extension or select the extension manifest file
- Go to
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"]
}
]
}
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
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)
);
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");
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);
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);
}
At last, the ToC is inserted at the beginning of the article-body
element.
articleBody.prepend(tocDetails);
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 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
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)