171 lines
3.8 KiB
JavaScript
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);
|