My script generates a table of contents based on the headings h2
and h3
. The issue arises when there is a span
tag within an h2
, causing the script to skip that heading and not create a link for it. I suspect the problem lies in the regular expression
/<h([\d]).*>\s*[\d]*\s?[.]?\s?([^<]+)<\/h([\d])>/gi
but I'm not proficient in regex to fix it.
$(document).ready(function() {
var toc = "";
var level = 0;
var maxLevel = 3;
if (document.getElementById("contents") != null) {
document.getElementById("contents").innerHTML =
document.getElementById("contents").innerHTML.replace(
/<h([\d]).*>\s*[\d]*\s?[.]?\s?([^<]+)<\/h([\d])>/gi,
function(str, openLevel, titleText, closeLevel) {
if (openLevel > maxLevel) {
return str;
}
if (openLevel > level) {
toc += (new Array(2)).join("<ol>");
} else if (openLevel < level) {
toc += (new Array(level - openLevel + 1)).join("</ol>");
}
level = parseInt(openLevel);
var anchor = titleText.replace(/[^a-zA-Z]+/g, "-");
toc += "<li><a href=\"#" + anchor + "\">" + titleText +
"</a></li>";
return "<a name=\"" + anchor + "\">" +
"<h" + openLevel + "\">" + str + "</h" + closeLevel + ">" + "</a>";
}
);
if (level) {
toc += (new Array(level + 1)).join("</ol>");
}
document.getElementById("toc").innerHTML += toc;
}
});
.blink {
animation: blinker 1s step-start infinite;
color: #ff0000;
font-weight: bold;
font-size: 0.85em;
}
@keyframes blinker {
50% {
opacity: 0;
}
}
<head>
<script type="text/javascript" src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
</head>
<body>
<div id="toc">
<div id="contents">
<h2>What is JS?</h2>
<h2 style="margin-top:1em;">Python Jobs - <span class="blink">New!</span></h2>
<h2 style="margin-top:1em;">
What is Python?
</h2><h3>Introduction</h3>
</div>
</div>
</body>