Skip to content

Commit ff20f38

Browse files
committed
added TOC
1 parent fb2f117 commit ff20f38

File tree

5 files changed

+161
-1
lines changed

5 files changed

+161
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ Changes made to fulfil my needs:
126126
* Customized landing page with dynamic message
127127
* Added date dropdown page to list posts in blog
128128
* Added subtitle to skills bars
129+
* Added a Table of Contents for the HTML in the blog posts (.html and .scss)
129130

130131
<div align="center">
131132
<sub><sup>© 2025 Alejandro Garnung Menéndez, licensed under the <a href="./LICENSE">MIT License</a>.</sup></sub>

_includes/blog/toc.html

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<aside id="toc-container" class="right">
2+
<button id="toggle-toc"></button>
3+
<!--<button id="toggle-toc-visibility">👁️</button>-->
4+
<h3>Index</h3>
5+
<nav id="toc"></nav>
6+
</aside>
7+
8+
<script>
9+
document.addEventListener("DOMContentLoaded", function () {
10+
let headers = document.querySelectorAll("h1, h2, h3");
11+
let toc = document.getElementById("toc");
12+
13+
headers.forEach((header, index) => {
14+
if (header.textContent.trim() === "Index") {
15+
return; // Si el encabezado es "Index", ignorarlo y continuar con el siguiente
16+
}
17+
18+
if (!header.id) header.id = "header-" + index; // Asegura un ID único
19+
let link = document.createElement("a");
20+
link.href = "#" + header.id;
21+
link.textContent = header.textContent;
22+
link.classList.add("toc-link", "level-" + header.tagName.toLowerCase());
23+
toc.appendChild(link);
24+
});
25+
26+
// Resaltar sección activa al hacer scroll
27+
window.addEventListener("scroll", () => {
28+
let fromTop = window.scrollY + 20;
29+
let links = document.querySelectorAll(".toc-link");
30+
31+
links.forEach(link => {
32+
let section = document.querySelector(link.getAttribute("href"));
33+
if (section && section.offsetTop <= fromTop && section.offsetTop + section.offsetHeight > fromTop) {
34+
link.classList.add("active");
35+
} else {
36+
link.classList.remove("active");
37+
}
38+
});
39+
});
40+
41+
// Alternar posición (izquierda/derecha)
42+
document.getElementById("toggle-toc").addEventListener("click", function () {
43+
let tocContainer = document.getElementById("toc-container");
44+
tocContainer.classList.toggle("left");
45+
tocContainer.classList.toggle("right");
46+
});
47+
48+
// Alternar visibilidad del índice
49+
document.getElementById("toggle-toc-visibility").addEventListener("click", function () {
50+
let tocContainer = document.getElementById("toc-container");
51+
tocContainer.classList.toggle("hidden"); // Alterna la visibilidad
52+
});
53+
});
54+
</script>
55+

_layouts/post.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ <h1><b>{{ page.title }}</b></h1>
3030

3131
{{ content }}
3232

33+
{% include blog/toc.html %}
34+
3335
{% if page.comments %}
3436
<div class="pt-5">
3537
{% include blog/disqus.html %}

_sass/portfolYOU.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@
1818
"theme",
1919
"theme-dark",
2020
"pdf",
21-
"dropdown";
21+
"dropdown",
22+
"toc";
23+

_sass/toc.scss

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#toc-container {
2+
position: fixed;
3+
top: 20%;
4+
width: 220px;
5+
max-height: 70vh;
6+
overflow-y: auto;
7+
padding: 10px;
8+
font-size: 14px;
9+
z-index: 1000;
10+
transition: transform 1.3s ease;
11+
}
12+
13+
#toc-container.hidden {
14+
transform: translateX(100%); /* Desplazar el índice fuera de la pantalla */
15+
visibility: hidden;
16+
opacity: 0;
17+
transition: transform 1.3s ease, visibility 1.3s ease, opacity 1.3s ease;
18+
}
19+
20+
/* Mantener el botón de mostrar visible aunque el índice esté oculto */
21+
#toggle-toc-visibility {
22+
position: fixed;
23+
top: 20%;
24+
right: 15px;
25+
background: none;
26+
border: none;
27+
font-size: 20px;
28+
cursor: pointer;
29+
z-index: 1001;
30+
padding: 5px;
31+
@include themed(color, black, $text-white);
32+
}
33+
34+
/* Quitar estilos predeterminados de los botones */
35+
button {
36+
background: none;
37+
border: none;
38+
outline: none;
39+
cursor: pointer;
40+
}
41+
42+
#toc-container.right { right: 20px; }
43+
#toc-container.left { left: 20px; }
44+
45+
#toggle-toc {
46+
position: absolute;
47+
top: 5px;
48+
right: 0px;
49+
background: none;
50+
border: none;
51+
font-size: 18px;
52+
cursor: pointer;
53+
@include themed(color, black, $text-white);
54+
}
55+
56+
#toc a {
57+
display: block;
58+
text-decoration: none;
59+
padding: 5px;
60+
transition: all 0.3s ease;
61+
@include themed(color, black, $text-white);
62+
63+
/* Permitir salto de línea en títulos largos */
64+
white-space: normal;
65+
word-wrap: break-word;
66+
overflow-wrap: break-word;
67+
}
68+
69+
/* Hover y selección en modo claro/oscuro */
70+
#toc a:hover,
71+
#toc a.active {
72+
@include themed(background, rgba(0, 0, 0, 0.05), rgba(255, 255, 255, 0.1));
73+
border-radius: 5px;
74+
}
75+
76+
/* Estilos por nivel de encabezado */
77+
#toc .level-h1 {
78+
font-size: 18px;
79+
font-weight: bold;
80+
margin-top: 10px;
81+
}
82+
83+
#toc .level-h2 {
84+
font-size: 16px;
85+
font-weight: 600;
86+
padding-left: 15px;
87+
}
88+
89+
#toc .level-h3 {
90+
font-size: 14px;
91+
font-weight: 500;
92+
padding-left: 25px;
93+
}
94+
95+
#toc .level-h4 {
96+
font-size: 13px;
97+
font-weight: 400;
98+
padding-left: 35px;
99+
}
100+

0 commit comments

Comments
 (0)