Stackedit/public/res/extensions/toc.js

156 lines
5.1 KiB
JavaScript
Raw Permalink Normal View History

2013-05-27 19:45:33 +00:00
define([
"jquery",
"underscore",
2013-06-10 21:22:32 +00:00
"utils",
2013-06-22 23:48:57 +00:00
"classes/Extension",
2013-06-24 19:47:27 +00:00
"text!html/buttonToc.html",
2013-06-22 23:48:57 +00:00
"text!html/tocSettingsBlock.html",
2013-06-24 19:47:27 +00:00
], function($, _, utils, Extension, buttonTocHTML, tocSettingsBlockHTML) {
2013-05-29 19:55:23 +00:00
2013-06-24 19:47:27 +00:00
var toc = new Extension("toc", "Table of Contents", true);
2013-06-22 23:48:57 +00:00
toc.settingsBlock = tocSettingsBlockHTML;
toc.defaultConfig = {
2013-06-24 19:47:27 +00:00
marker: "\\[(TOC|toc)\\]",
2013-12-02 00:09:39 +00:00
maxDepth: 6,
2013-06-24 19:47:27 +00:00
button: true,
2013-05-29 19:55:23 +00:00
};
2013-05-30 22:16:12 +00:00
toc.onLoadSettings = function() {
utils.setInputValue("#input-toc-marker", toc.config.marker);
2013-12-02 00:09:39 +00:00
utils.setInputValue("#input-toc-maxdepth", toc.config.maxDepth);
2013-06-24 19:47:27 +00:00
utils.setInputChecked("#input-toc-button", toc.config.button);
2013-05-30 22:16:12 +00:00
};
toc.onSaveSettings = function(newConfig, event) {
newConfig.marker = utils.getInputRegExpValue("#input-toc-marker", event);
2013-12-02 00:09:39 +00:00
newConfig.maxDepth = utils.getInputIntValue("#input-toc-maxdepth");
2013-06-24 19:47:27 +00:00
newConfig.button = utils.getInputChecked("#input-toc-button");
};
toc.onCreatePreviewButton = function() {
if(toc.config.button) {
2013-07-30 08:46:36 +00:00
return buttonTocHTML;
2013-06-24 19:47:27 +00:00
}
2013-06-22 23:48:57 +00:00
};
2013-05-30 22:16:12 +00:00
2013-05-29 19:55:23 +00:00
// TOC element description
function TocElement(tagName, anchor, text) {
this.tagName = tagName;
this.anchor = anchor;
this.text = text;
this.children = [];
}
TocElement.prototype.childrenToString = function() {
if(this.children.length === 0) {
return "";
}
2013-06-24 19:47:27 +00:00
var result = "<ul>\n";
2013-05-29 19:55:23 +00:00
_.each(this.children, function(child) {
result += child.toString();
});
2013-06-24 19:47:27 +00:00
result += "</ul>\n";
2013-05-29 19:55:23 +00:00
return result;
};
TocElement.prototype.toString = function() {
var result = "<li>";
if(this.anchor && this.text) {
result += '<a href="#' + this.anchor + '">' + this.text + '</a>';
}
2013-06-24 19:47:27 +00:00
result += this.childrenToString() + "</li>\n";
2013-05-29 19:55:23 +00:00
return result;
};
// Transform flat list of TocElement into a tree
function groupTags(array, level) {
level = level || 1;
var tagName = "H" + level;
var result = [];
2013-11-07 23:10:38 +00:00
var currentElement;
2013-05-29 19:55:23 +00:00
function pushCurrentElement() {
if(currentElement !== undefined) {
if(currentElement.children.length > 0) {
currentElement.children = groupTags(currentElement.children, level + 1);
}
result.push(currentElement);
}
}
2013-11-07 23:10:38 +00:00
_.each(array, function(element) {
2013-05-29 19:55:23 +00:00
if(element.tagName != tagName) {
2013-12-02 00:09:39 +00:00
if(level !== toc.config.maxDepth) {
if(currentElement === undefined) {
currentElement = new TocElement();
}
currentElement.children.push(element);
2013-05-29 19:55:23 +00:00
}
}
else {
pushCurrentElement();
currentElement = element;
}
});
pushCurrentElement();
return result;
}
// Build the TOC
2013-11-07 23:10:38 +00:00
var previewContentsElt;
2013-05-29 19:55:23 +00:00
function buildToc() {
var anchorList = {};
function createAnchor(element) {
2013-09-03 10:37:59 +00:00
var id = element.id || utils.slugify(element.textContent) || 'title';
2013-05-29 19:55:23 +00:00
var anchor = id;
var index = 0;
while (_.has(anchorList, anchor)) {
anchor = id + "-" + (++index);
}
anchorList[anchor] = true;
// Update the id of the element
2013-07-28 17:14:42 +00:00
element.id = anchor;
2013-05-29 19:55:23 +00:00
return anchor;
}
var elementList = [];
_.each(previewContentsElt.querySelectorAll('h1, h2, h3, h4, h5, h6'), function(elt) {
2013-07-28 17:14:42 +00:00
elementList.push(new TocElement(elt.tagName, createAnchor(elt), elt.textContent));
2013-05-29 19:55:23 +00:00
});
elementList = groupTags(elementList);
2013-06-24 19:47:27 +00:00
return '<div class="toc">\n<ul>\n' + elementList.join("") + '</ul>\n</div>\n';
2013-05-29 19:55:23 +00:00
}
2013-09-09 23:32:24 +00:00
toc.onPagedownConfigure = function(editor) {
2013-07-28 17:14:42 +00:00
previewContentsElt = document.getElementById('preview-contents');
2014-03-17 02:01:46 +00:00
var tocExp = new RegExp("^\\s*" + toc.config.marker + "\\s*$");
2013-05-29 19:55:23 +00:00
// Run TOC generation when conversion is finished directly on HTML
editor.hooks.chain("onPreviewRefresh", function() {
var tocEltList = document.querySelectorAll('.table-of-contents, .toc');
2013-05-30 22:16:12 +00:00
var htmlToc = buildToc();
2013-07-28 10:35:04 +00:00
// Replace toc paragraphs
2013-07-28 17:14:42 +00:00
_.each(previewContentsElt.getElementsByTagName('p'), function(elt) {
if(tocExp.test(elt.innerHTML)) {
elt.innerHTML = htmlToc;
2013-07-28 10:35:04 +00:00
}
2013-07-24 23:20:56 +00:00
});
// Add toc in the TOC button
2013-07-28 17:14:42 +00:00
_.each(tocEltList, function(elt) {
elt.innerHTML = htmlToc;
});
2013-05-29 19:55:23 +00:00
});
};
toc.onReady = function() {
var isPreviewVisible = true;
$(".preview-panel").on('hide.layout.toggle', function() {
isPreviewVisible = false;
}).on('shown.layout.toggle', function() {
isPreviewVisible = true;
});
$('.extension-preview-buttons .table-of-contents').on('click', 'a', function(evt) {
!isPreviewVisible && evt.preventDefault();
});
};
2013-05-29 19:55:23 +00:00
return toc;
2013-05-26 01:10:58 +00:00
});