Stackedit/js/extensions/partialRendering.js

193 lines
7.4 KiB
JavaScript
Raw Normal View History

2013-07-23 23:51:21 +00:00
define([
"jquery",
"underscore",
"classes/Extension",
"text!html/partialRenderingSettingsBlock.html",
], function($, _, Extension, partialRenderingSettingsBlockHTML) {
2013-07-28 10:35:04 +00:00
var partialRendering = new Extension("partialRendering", "Partial Rendering", true);
2013-07-23 23:51:21 +00:00
partialRendering.settingsBlock = partialRenderingSettingsBlockHTML;
var converter = undefined;
2013-07-26 00:44:12 +00:00
var sectionCounter = 0;
var sectionList = [];
2013-07-28 10:35:04 +00:00
var linkDefinition = undefined;
2013-07-26 00:44:12 +00:00
var sectionsToRemove = [];
var modifiedSections = [];
var insertAfterSection = undefined;
2013-07-28 10:35:04 +00:00
var fileChanged = false;
2013-07-26 00:44:12 +00:00
function updateSectionList(newSectionList, newLinkDefinition) {
modifiedSections = [];
sectionsToRemove = [];
insertAfterSection = undefined;
2013-07-28 10:35:04 +00:00
// Render everything if file or linkDefinition changed
2013-07-26 00:44:12 +00:00
if(fileChanged === true || linkDefinition != newLinkDefinition) {
fileChanged = false;
linkDefinition = newLinkDefinition;
sectionsToRemove = sectionList;
sectionList = newSectionList;
modifiedSections = newSectionList;
return;
2013-07-24 23:20:56 +00:00
}
2013-07-28 10:35:04 +00:00
// Find modified sections starting from top
2013-07-24 23:20:56 +00:00
var leftIndex = sectionList.length;
_.some(sectionList, function(section, index) {
if(index >= newSectionList.length || section.text != newSectionList[index].text) {
leftIndex = index;
return true;
}
});
2013-07-28 10:35:04 +00:00
// Find modified sections starting from bottom
2013-07-24 23:20:56 +00:00
var rightIndex = -sectionList.length;
_.some(sectionList.slice().reverse(), function(section, index) {
if(index >= newSectionList.length || section.text != newSectionList[newSectionList.length - index - 1].text) {
rightIndex = -index;
return true;
}
});
if(leftIndex === sectionList.length && rightIndex === -leftIndex) {
// No modification detected...
return;
}
// Create an array composed of left unmodified, modified, right
// unmodified sections
var leftSections = sectionList.slice(0, leftIndex);
2013-07-26 00:44:12 +00:00
modifiedSections = newSectionList.slice(leftIndex, newSectionList.length + rightIndex);
2013-07-24 23:20:56 +00:00
var rightSections = sectionList.slice(sectionList.length + rightIndex, sectionList.length);
2013-07-26 00:44:12 +00:00
insertAfterSection = _.last(leftSections);
2013-07-24 23:20:56 +00:00
sectionsToRemove = sectionList.slice(leftIndex, sectionList.length + rightIndex);
sectionList = leftSections.concat(modifiedSections).concat(rightSections);
}
2013-07-26 00:44:12 +00:00
var doFootnotes = false;
2013-07-23 23:51:21 +00:00
var hasFootnotes = false;
2013-07-26 00:44:12 +00:00
partialRendering.onSectionsCreated = function(sectionListParam) {
2013-07-23 23:51:21 +00:00
2013-07-26 00:44:12 +00:00
var newSectionList = [];
var newLinkDefinition = "";
2013-07-23 23:51:21 +00:00
hasFootnotes = false;
2013-07-26 00:44:12 +00:00
_.each(sectionListParam, function(text) {
text += "\n\n";
// Strip link definitions
text = text.replace(/^```.*\n[\s\S]*?\n```|^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm, function(wholeMatch, link) {
if(link) {
newLinkDefinition += wholeMatch;
return "";
}
return wholeMatch;
2013-07-23 23:51:21 +00:00
});
2013-07-28 10:35:04 +00:00
// And footnotes eventually
2013-07-26 00:44:12 +00:00
if(doFootnotes) {
text = text.replace(/^```.*\n[\s\S]*?\n```|\n[ ]{0,3}\[\^(.+?)\]\:[ \t]*\n?([\s\S]*?)\n{1,2}((?=\n[ ]{0,3}\S)|$)/g, function(wholeMatch, footnote) {
if(footnote) {
hasFootnotes = true;
newLinkDefinition += wholeMatch;
return "";
}
return wholeMatch;
});
}
// Skip space only sections
if(/\S/.test(text)) {
// Add section to the newSectionList
newSectionList.push({
id: ++sectionCounter,
text: text
});
2013-07-23 23:51:21 +00:00
}
2013-07-24 23:20:56 +00:00
});
2013-07-23 23:51:21 +00:00
2013-07-26 00:44:12 +00:00
updateSectionList(newSectionList, newLinkDefinition);
};
var footnoteContainerElt = $('<div id="wmd-preview-section-footnotes" class="preview-content">');
var footnoteList = {};
function refreshSections() {
2013-07-23 23:51:21 +00:00
2013-07-24 23:20:56 +00:00
// Remove outdated sections
_.each(sectionsToRemove, function(section) {
$("#wmd-preview-section-" + section.id).remove();
});
2013-07-26 00:44:12 +00:00
var wmdPreviewElt = $("#wmd-preview");
var insertAfterSectionElt = insertAfterSection === undefined ? wmdPreviewElt : $("#wmd-preview-section-" + insertAfterSection.id);
_.each(modifiedSections, function(section) {
var sectionElt = $('<div id="wmd-preview-section-' + section.id + '" class="wmd-preview-section preview-content">');
2013-07-28 10:35:04 +00:00
_.some(wmdPreviewElt.contents(), function(elt, index) {
2013-07-26 00:44:12 +00:00
elt = $(elt);
if(index !== 0 && elt.is(".wmd-title")) {
return true;
}
else if(elt.is("div.footnotes")) {
elt.find("ol > li").each(function() {
var footnoteElt = $(this).clone();
var id = footnoteElt.attr("id").substring(3);
footnoteList[id] = footnoteElt;
});
elt.remove();
}
else {
sectionElt.append(elt);
}
2013-07-24 23:20:56 +00:00
});
2013-07-26 00:44:12 +00:00
insertAfterSectionElt.after(sectionElt);
insertAfterSectionElt = sectionElt;
2013-07-24 23:20:56 +00:00
});
2013-07-23 23:51:21 +00:00
2013-07-26 00:44:12 +00:00
// Rewrite footnotes in the footer and update footnote numbers
footnoteContainerElt.empty();
var usedFootnoteIds = [];
2013-07-23 23:51:21 +00:00
if(hasFootnotes === true) {
var footnoteElts = $("<ol>");
2013-07-26 00:44:12 +00:00
$("#preview-contents a.footnote").each(function(index) {
var id=$(this).text(index + 1).attr("id").substring(6);
usedFootnoteIds.push(id);
footnoteElts.append(footnoteList[id].clone());
2013-07-23 23:51:21 +00:00
});
2013-07-26 00:44:12 +00:00
if(usedFootnoteIds.length > 0) {
// Append the whole footnotes at the end of the document
footnoteContainerElt.html($('<div class="footnotes">').append("<hr>").append(footnoteElts));
}
2013-07-28 10:35:04 +00:00
// Keep used footnotes only in our map
2013-07-26 00:44:12 +00:00
footnoteList = _.pick(footnoteList, usedFootnoteIds);
2013-07-23 23:51:21 +00:00
}
}
partialRendering.onEditorConfigure = function(editor) {
converter = editor.getConverter();
converter.hooks.chain("preConversion", function(text) {
2013-07-26 00:44:12 +00:00
var result = _.map(modifiedSections, function(section) {
return section.text;
});
result.push(linkDefinition + "\n\n");
return result.join("");
2013-07-23 23:51:21 +00:00
});
editor.hooks.chain("onPreviewRefresh", function() {
2013-07-26 00:44:12 +00:00
refreshSections();
2013-07-23 23:51:21 +00:00
});
};
2013-07-24 23:20:56 +00:00
2013-07-26 00:44:12 +00:00
partialRendering.onReady = function() {
$("#preview-contents").append(footnoteContainerElt);
$("#wmd-preview").hide();
};
2013-07-28 10:35:04 +00:00
partialRendering.onFileSelected = function() {
2013-07-26 00:44:12 +00:00
fileChanged = true;
};
partialRendering.onFileOpen = function() {
if(converter.extraExtensions) {
doFootnotes = _.some(converter.extraExtensions, function(extension) {
return extension == "footnotes";
});
}
2013-07-24 23:20:56 +00:00
};
2013-07-23 23:51:21 +00:00
return partialRendering;
});