2025-06-10 00:24:01 +08:00

171 lines
3.8 KiB
JavaScript

var defaultOptions = {
headings: 'h1, h2',
scope: '.markdown-section',
// To make work
title: 'Contents',
listType: 'ul',
}
// Element builders
var tocHeading = function(Title) {
return document.createElement('h2').appendChild(
document.createTextNode(Title)
)
}
var aTag = function(src) {
var a = document.createElement('a');
var content = src.firstChild.innerHTML;
// Use this to clip text w/ HTML in it.
// https://github.com/arendjr/text-clipper
a.innerHTML = content;
a.href = src.firstChild.href;
a.onclick = tocClick
// In order to remove this gotta fix the styles.
a.setAttribute('class', 'anchor');
return a
};
var tocClick = function(e) {
var divs = document.querySelectorAll('.page_toc .active');
// Remove the previous classes
[].forEach.call(divs, function(div) {
div.setAttribute('class', 'anchor')
});
// Make sure this is attached to the parent not itself
e.target.parentNode.setAttribute('class', 'active')
};
var createList = function(wrapper, count) {
while (count--) {
wrapper = wrapper.appendChild(
document.createElement('ul')
);
if (count) {
wrapper = wrapper.appendChild(
document.createElement('li')
);
}
}
return wrapper;
};
//------------------------------------------------------------------------
var getHeaders = function(selector) {
var headings2 = document.querySelectorAll(selector);
var ret = [];
[].forEach.call(headings2, function(heading) {
ret = ret.concat(heading);
});
return ret;
};
var getLevel = function(header) {
var decs = header.match(/\d/g);
return decs ? Math.min.apply(null, decs) : 1;
};
var jumpBack = function(currentWrapper, offset) {
while (offset--) {
currentWrapper = currentWrapper.parentElement;
}
return currentWrapper;
};
var buildTOC = function(options) {
var ret = document.createElement('ul');
var wrapper = ret;
var lastLi = null;
var selector = options.scope + ' ' + options.headings
var headers = getHeaders(selector)
headers.reduce(function(prev, curr, index) {
var currentLevel = getLevel(curr.tagName);
var offset = currentLevel - prev;
wrapper = (offset > 0)
? createList(lastLi, offset)
: jumpBack(wrapper, -offset * 2)
wrapper = wrapper || ret;
var li = document.createElement('li');
wrapper.appendChild(li).appendChild(aTag(curr));
lastLi = li;
return currentLevel;
}, getLevel(options.headings));
return ret;
};
// Docsify plugin functions
function plugin(hook, vm) {
var userOptions = vm.config.toc;
hook.mounted(function () {
var content = window.Docsify.dom.find(".content");
if (content) {
var nav = window.Docsify.dom.create("aside", "");
window.Docsify.dom.toggleClass(nav, "add", "nav");
window.Docsify.dom.before(content, nav);
}
});
hook.doneEach(function () {
var nav = document.querySelectorAll('.nav')[0]
var t = Array.from(document.querySelectorAll('.nav'))
if (!nav) {
return;
}
const toc = buildTOC(userOptions);
// Just unset it for now.
if (!toc.innerHTML) {
nav.innerHTML = null
return;
}
// Fix me in the future
var title = document.createElement('p');
title.innerHTML = userOptions.title;
title.setAttribute('class', 'title');
var container = document.createElement('div');
container.setAttribute('class', 'page_toc');
container.appendChild(title);
container.appendChild(toc);
// Existing TOC
var tocChild = document.querySelectorAll('.nav .page_toc');
if (tocChild.length > 0) {
tocChild[0].parentNode.removeChild(tocChild[0]);
}
nav.appendChild(container);
});
}
// Docsify plugin options
window.$docsify['toc'] = Object.assign(defaultOptions, window.$docsify['toc']);
window.$docsify.plugins = [].concat(plugin, window.$docsify.plugins);