mirror of https://github.com/Meekdai/Gmeek.git
Merge 24a5d90914 into 77a8aaa2b1
This commit is contained in:
commit
6cac81e339
|
|
@ -1,158 +1,188 @@
|
||||||
function loadResource(type, attributes) {
|
(function () {
|
||||||
if (type === 'style') {
|
if (window.__GmeekTocReady) return;
|
||||||
const style = document.createElement('style');
|
window.__GmeekTocReady = true;
|
||||||
style.textContent = attributes.css;
|
console.log("🍏 articletoc 插件已启用 https://code.buxiantang.top/");
|
||||||
document.head.appendChild(style);
|
|
||||||
|
const TOC_STYLE = `
|
||||||
|
:root {
|
||||||
|
--toc-bg: rgba(255,255,255,0.8);
|
||||||
|
--toc-border: #e1e4e8;
|
||||||
|
--toc-text: #24292e;
|
||||||
|
--toc-hover: rgba(0,0,0,0.05);
|
||||||
|
--toc-icon-bg: rgba(255,255,255,0.8);
|
||||||
|
--toc-icon-color: #333;
|
||||||
|
--toc-icon-active-bg: #fff;
|
||||||
|
--toc-icon-active-color: #333;
|
||||||
}
|
}
|
||||||
}
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
function createTOC() {
|
--toc-bg: rgba(45, 51, 59, 0.8);
|
||||||
const tocElement = document.createElement('div');
|
--toc-border: #444c56;
|
||||||
tocElement.className = 'toc';
|
--toc-text: #adbac7;
|
||||||
const contentContainer = document.querySelector('.markdown-body');
|
--toc-hover: rgba(255, 255, 255, 0.05);
|
||||||
contentContainer.appendChild(tocElement);
|
--toc-icon-bg: rgba(45, 51, 59, 0.8);
|
||||||
|
--toc-icon-color: #adbac7;
|
||||||
const headings = contentContainer.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
--toc-icon-active-bg: #2d333b;
|
||||||
headings.forEach(heading => {
|
--toc-icon-active-color: #adbac7;
|
||||||
if (!heading.id) {
|
}
|
||||||
heading.id = heading.textContent.trim().replace(/\s+/g, '-').toLowerCase();
|
|
||||||
}
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = '#' + heading.id;
|
|
||||||
link.textContent = heading.textContent;
|
|
||||||
link.className = 'toc-link';
|
|
||||||
link.style.paddingLeft = `${(parseInt(heading.tagName.charAt(1)) - 1) * 10}px`;
|
|
||||||
tocElement.appendChild(link);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleTOC() {
|
|
||||||
const tocElement = document.querySelector('.toc');
|
|
||||||
const tocIcon = document.querySelector('.toc-icon');
|
|
||||||
if (tocElement) {
|
|
||||||
tocElement.classList.toggle('show');
|
|
||||||
tocIcon.classList.toggle('active');
|
|
||||||
tocIcon.textContent = tocElement.classList.contains('show') ? '✖' : '☰';
|
|
||||||
}
|
}
|
||||||
}
|
.toc {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 80px;
|
||||||
|
right: 20px;
|
||||||
|
width: 250px;
|
||||||
|
max-height: 70vh;
|
||||||
|
background-color: var(--toc-bg);
|
||||||
|
border: 1px solid var(--toc-border);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 10px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
overflow-y: auto;
|
||||||
|
z-index: 1000;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transform: translateY(20px);
|
||||||
|
transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
}
|
||||||
|
.toc.show {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
.toc a {
|
||||||
|
display: block;
|
||||||
|
color: var(--toc-text);
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 5px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
border-bottom: 1px solid var(--toc-border);
|
||||||
|
transition: background-color 0.2s ease, padding-left 0.2s ease;
|
||||||
|
}
|
||||||
|
.toc a:last-child { border-bottom: none; }
|
||||||
|
.toc a:hover {
|
||||||
|
background-color: var(--toc-hover);
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
.toc-icon {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: var(--toc-icon-bg);
|
||||||
|
color: var(--toc-icon-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
z-index: 1001;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.toc-icon:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
background-color: var(--toc-icon-active-bg);
|
||||||
|
}
|
||||||
|
.toc-icon:active {
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
.toc-icon.active {
|
||||||
|
background-color: var(--toc-icon-active-bg);
|
||||||
|
color: var(--toc-icon-active-color);
|
||||||
|
}
|
||||||
|
.toc-icon svg {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
fill: none;
|
||||||
|
stroke: currentColor;
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.toc { width: 200px; bottom: 70px; right: 10px; }
|
||||||
|
.toc-icon { width: 40px; height: 40px; bottom: 15px; right: 15px; }
|
||||||
|
.toc-icon svg { width: 20px; height: 20px; }
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
injectStyle(TOC_STYLE);
|
||||||
createTOC();
|
createTocIcon();
|
||||||
const css = `
|
observeMarkdown();
|
||||||
:root {
|
|
||||||
--toc-bg: #fff;
|
|
||||||
--toc-border: #e1e4e8;
|
|
||||||
--toc-text: #24292e;
|
|
||||||
--toc-hover: #f6f8fa;
|
|
||||||
--toc-icon-bg: #fff;
|
|
||||||
--toc-icon-color: #ad6598;
|
|
||||||
--toc-icon-active-bg: #813c85;
|
|
||||||
--toc-icon-active-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
function injectStyle(cssText) {
|
||||||
:root {
|
const style = document.createElement("style");
|
||||||
--toc-bg: #2d333b;
|
style.textContent = cssText;
|
||||||
--toc-border: #444c56;
|
document.head.appendChild(style);
|
||||||
--toc-text: #adbac7;
|
}
|
||||||
--toc-hover: #373e47;
|
|
||||||
--toc-icon-bg: #22272e;
|
|
||||||
--toc-icon-color: #ad6598;
|
|
||||||
--toc-icon-active-bg: #813c85;
|
|
||||||
--toc-icon-active-color: #adbac7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.toc {
|
function createTocIcon() {
|
||||||
position: fixed;
|
const icon = document.createElement("div");
|
||||||
bottom: 60px;
|
icon.className = "toc-icon";
|
||||||
right: 20px;
|
icon.innerHTML = '<svg viewBox="0 0 24 24"><path d="M3 12h18M3 6h18M3 18h18"/></svg>';
|
||||||
width: 250px;
|
icon.onclick = (e) => {
|
||||||
max-height: 70vh;
|
e.stopPropagation();
|
||||||
background-color: var(--toc-bg);
|
toggleTOC();
|
||||||
border: 1px solid var(--toc-border);
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 10px;
|
|
||||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
||||||
overflow-y: auto;
|
|
||||||
z-index: 1000;
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
transform: translateY(20px) scale(0.9);
|
|
||||||
transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
|
|
||||||
}
|
|
||||||
.toc.show {
|
|
||||||
opacity: 1;
|
|
||||||
visibility: visible;
|
|
||||||
transform: translateY(0) scale(1);
|
|
||||||
}
|
|
||||||
.toc a {
|
|
||||||
display: block;
|
|
||||||
color: var(--toc-text);
|
|
||||||
text-decoration: none;
|
|
||||||
padding: 5px 0;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.5;
|
|
||||||
border-bottom: 1px solid var(--toc-border);
|
|
||||||
transition: background-color 0.2s ease, padding-left 0.2s ease;
|
|
||||||
}
|
|
||||||
.toc a:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
.toc a:hover {
|
|
||||||
background-color: var(--toc-hover);
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
.toc-icon {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 20px;
|
|
||||||
right: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 24px;
|
|
||||||
background-color: var(--toc-icon-bg);
|
|
||||||
color: var(--toc-icon-color);
|
|
||||||
border: 2px solid var(--toc-icon-color);
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.12);
|
|
||||||
z-index: 1001;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
user-select: none;
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
.toc-icon:hover {
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
.toc-icon:active {
|
|
||||||
transform: scale(0.9);
|
|
||||||
}
|
|
||||||
.toc-icon.active {
|
|
||||||
background-color: var(--toc-icon-active-bg);
|
|
||||||
color: var(--toc-icon-active-color);
|
|
||||||
border-color: var(--toc-icon-active-bg);
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
loadResource('style', {css: css});
|
|
||||||
|
|
||||||
const tocIcon = document.createElement('div');
|
|
||||||
tocIcon.className = 'toc-icon';
|
|
||||||
tocIcon.textContent = '☰';
|
|
||||||
tocIcon.onclick = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
toggleTOC();
|
|
||||||
};
|
};
|
||||||
document.body.appendChild(tocIcon);
|
document.body.appendChild(icon);
|
||||||
|
document.addEventListener("click", (e) => {
|
||||||
document.addEventListener('click', (e) => {
|
const toc = document.querySelector(".toc");
|
||||||
const tocElement = document.querySelector('.toc');
|
if (toc && toc.classList.contains("show") && !toc.contains(e.target) && !e.target.classList.contains("toc-icon")) {
|
||||||
if (tocElement && tocElement.classList.contains('show') && !tocElement.contains(e.target) && !e.target.classList.contains('toc-icon')) {
|
toggleTOC();
|
||||||
toggleTOC();
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
function observeMarkdown() {
|
||||||
|
const container = document.querySelector(".markdown-body");
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
const headings = container.querySelectorAll("h1,h2,h3,h4,h5,h6");
|
||||||
|
if (headings.length > 0) {
|
||||||
|
renderTOC(container, headings);
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(container, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTOC(container, headings) {
|
||||||
|
if (document.querySelector(".toc")) return;
|
||||||
|
|
||||||
|
const toc = document.createElement("div");
|
||||||
|
toc.className = "toc";
|
||||||
|
headings.forEach((h) => {
|
||||||
|
if (!h.id) h.id = h.textContent.trim().replace(/\s+/g, "-").toLowerCase();
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = "#" + h.id;
|
||||||
|
link.textContent = h.textContent;
|
||||||
|
link.style.paddingLeft = `${(parseInt(h.tagName[1]) - 1) * 10}px`;
|
||||||
|
link.onclick = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
document.getElementById(h.id)?.scrollIntoView({ behavior: "smooth" });
|
||||||
|
toggleTOC();
|
||||||
|
};
|
||||||
|
toc.appendChild(link);
|
||||||
|
});
|
||||||
|
container.appendChild(toc);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleTOC() {
|
||||||
|
const toc = document.querySelector(".toc");
|
||||||
|
const icon = document.querySelector(".toc-icon");
|
||||||
|
if (!toc || !icon) return;
|
||||||
|
toc.classList.toggle("show");
|
||||||
|
icon.classList.toggle("active");
|
||||||
|
icon.innerHTML = toc.classList.contains("show")
|
||||||
|
? '<svg viewBox="0 0 24 24"><path d="M18 6L6 18M6 6l12 12"/></svg>'
|
||||||
|
: '<svg viewBox="0 0 24 24"><path d="M3 12h18M3 6h18M3 18h18"/></svg>';
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue