define([ "jquery", "underscore", "utils", "text!html/tocSettingsBloc.html", ], function($, _, utils, tocSettingsBlocHTML) { var toc = { extensionId: "toc", extensionName: "Table of Content", optional: true, defaultConfig: { marker: "\\[(TOC|toc)\\]" }, settingsBloc: tocSettingsBlocHTML }; toc.onLoadSettings = function() { utils.setInputValue("#input-toc-marker", toc.config.marker); }; toc.onSaveSettings = function(newConfig, event) { newConfig.marker = utils.getInputRegExpValue("#input-toc-marker", event); }; // 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 ""; } var result = ""; return result; }; TocElement.prototype.toString = function() { var result = "
  • "; if(this.anchor && this.text) { result += '' + this.text + ''; } result += this.childrenToString() + "
  • "; return result; }; // Transform flat list of TocElement into a tree function groupTags(array, level) { level = level || 1; var tagName = "H" + level; var result = []; var currentElement = undefined; function pushCurrentElement() { if(currentElement !== undefined) { if(currentElement.children.length > 0) { currentElement.children = groupTags(currentElement.children, level + 1); } result.push(currentElement); } } _.each(array, function(element, index) { if(element.tagName != tagName) { if(currentElement === undefined) { currentElement = new TocElement(); } currentElement.children.push(element); } else { pushCurrentElement(); currentElement = element; } }); pushCurrentElement(); return result; } // Build the TOC function buildToc() { var anchorList = {}; function createAnchor(element) { var id = element.prop("id") || utils.slugify(element.text()); var anchor = id; var index = 0; while (_.has(anchorList, anchor)) { anchor = id + "-" + (++index); } anchorList[anchor] = true; // Update the id of the element element.prop("id", anchor); return anchor; } var elementList = []; $("#wmd-preview > h1," + "#wmd-preview > h2," + "#wmd-preview > h3," + "#wmd-preview > h4," + "#wmd-preview > h5," + "#wmd-preview > h6").each(function() { elementList.push(new TocElement($(this).prop("tagName"), createAnchor($(this)), $(this).text())); }); elementList = groupTags(elementList); return '
    '; } toc.onEditorConfigure = function(editor) { // Run TOC generation when conversion is finished directly on HTML editor.hooks.chain("onPreviewRefresh", function() { var htmlToc = buildToc(); var html = $("#wmd-preview").html(); html = html.replace(new RegExp("

    " + toc.config.marker + "<\\/p>", "g"), htmlToc); $("#wmd-preview").html(html); }); }; return toc; });