Switch to ACE editor
This commit is contained in:
parent
24ba484010
commit
582337d595
@ -18,7 +18,7 @@ define([
|
||||
return new Range(rangeComponents[0], rangeComponents[1], rangeComponents[2], rangeComponents[3]);
|
||||
}
|
||||
catch(e) {
|
||||
return new Range();
|
||||
return new Range(0, 0, 0, 0);
|
||||
}
|
||||
})();
|
||||
this._editorEnd = parseInt(localStorage[fileIndex + ".editorEnd"]) || 0;
|
||||
|
155
res/core.js
155
res/core.js
@ -187,56 +187,64 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
// Create the layout
|
||||
// Create ACE editor
|
||||
var aceEditor = undefined;
|
||||
function createLayout() {
|
||||
function createAceEditor() {
|
||||
aceEditor = ace.edit("wmd-input");
|
||||
aceEditor.renderer.setShowGutter(false);
|
||||
aceEditor.renderer.setShowPrintMargin(false);
|
||||
aceEditor.renderer.setPrintMarginColumn(false);
|
||||
aceEditor.renderer.setPadding(12);
|
||||
aceEditor.renderer.setPadding(10);
|
||||
aceEditor.session.setUseWrapMode(true);
|
||||
aceEditor.session.setMode("libs/acemode");
|
||||
// Make bold titles...
|
||||
(function(bgTokenizer) {
|
||||
var worker = bgTokenizer.$worker;
|
||||
bgTokenizer.$worker = function() {
|
||||
bgTokenizer.currentLine = bgTokenizer.currentLine ? bgTokenizer.currentLine - 1 : 0;
|
||||
worker();
|
||||
_.each(bgTokenizer.lines, function(line, i) {
|
||||
if(i !== 0 && line && line.length !== 0 && line[0].type.indexOf("markup.heading.multi") === 0) {
|
||||
_.each(bgTokenizer.lines[i-1], function(previousLineObject) {
|
||||
previousLineObject.type = "markup.heading.prev.multi";
|
||||
});
|
||||
(function(self) {
|
||||
function customWorker() {
|
||||
if (!self.running) { return; }
|
||||
|
||||
var workerStart = new Date();
|
||||
var startLine = self.currentLine;
|
||||
var doc = self.doc;
|
||||
|
||||
var processedLines = 0;
|
||||
|
||||
var len = doc.getLength();
|
||||
while (self.currentLine < len) {
|
||||
self.$tokenizeRow(self.currentLine);
|
||||
while (self.lines[self.currentLine]) {
|
||||
var line = self.lines[self.currentLine];
|
||||
if(line.length !== 0 && line[0].type.indexOf("markup.heading.multi") === 0) {
|
||||
_.each(self.lines[self.currentLine-1], function(previousLineObject) {
|
||||
previousLineObject.type = "markup.heading.prev.multi";
|
||||
});
|
||||
}
|
||||
self.currentLine++;
|
||||
}
|
||||
});
|
||||
|
||||
// only check every 5 lines
|
||||
processedLines ++;
|
||||
if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {
|
||||
self.fireUpdateEvent(startLine, self.currentLine-1);
|
||||
self.running = setTimeout(customWorker, 20);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.running = false;
|
||||
|
||||
self.fireUpdateEvent(startLine, len - 1);
|
||||
}
|
||||
self.$worker = function() {
|
||||
self.currentLine = self.currentLine ? self.currentLine - 1 : 0;
|
||||
customWorker();
|
||||
};
|
||||
})(aceEditor.session.bgTokenizer);
|
||||
eventMgr.onAceCreated(aceEditor);
|
||||
window.aceEditor = aceEditor;
|
||||
}
|
||||
|
||||
|
||||
window.wmdInput = {
|
||||
editor: aceEditor,
|
||||
focus: function() {
|
||||
aceEditor.focus();
|
||||
}
|
||||
};
|
||||
Object.defineProperty(window.wmdInput, 'value', {
|
||||
get: function() {
|
||||
return aceEditor.getValue();
|
||||
},
|
||||
set: function(value) {
|
||||
aceEditor.setValue(value);
|
||||
}
|
||||
});
|
||||
Object.defineProperty(window.wmdInput, 'scrollTop', {
|
||||
get: function() {
|
||||
return aceEditor.renderer.getScrollTop();
|
||||
},
|
||||
set: function(value) {
|
||||
aceEditor.renderer.scrollToY(value);
|
||||
}
|
||||
});
|
||||
|
||||
// Create the layout
|
||||
function createLayout() {
|
||||
var layoutGlobalConfig = {
|
||||
closable: true,
|
||||
resizable: false,
|
||||
@ -319,7 +327,7 @@ define([
|
||||
var editor = undefined;
|
||||
var fileDesc = undefined;
|
||||
var documentContent = undefined;
|
||||
var $editorElt = undefined;
|
||||
var UndoManager = require("ace/undomanager").UndoManager;
|
||||
core.initEditor = function(fileDescParam) {
|
||||
if(fileDesc !== undefined) {
|
||||
eventMgr.onFileClosed(fileDesc);
|
||||
@ -329,15 +337,12 @@ define([
|
||||
var initDocumentContent = fileDesc.content;
|
||||
|
||||
aceEditor.setValue(initDocumentContent, -1);
|
||||
_.defer(function() {
|
||||
aceEditor.session.getUndoManager().reset();
|
||||
});
|
||||
aceEditor.getSession().setUndoManager(new UndoManager());
|
||||
|
||||
if(editor !== undefined) {
|
||||
// If the editor is already created
|
||||
aceEditor.selection.setSelectionRange(fileDesc.editorSelectRange);
|
||||
aceEditor.renderer.scrollToY(fileDesc.editorScrollTop);
|
||||
aceEditor.focus();
|
||||
eventMgr.onFileOpen(fileDesc);
|
||||
editor.refreshPreview();
|
||||
return;
|
||||
}
|
||||
@ -345,9 +350,12 @@ define([
|
||||
var $previewContainerElt = $(".preview-container");
|
||||
|
||||
// Store editor scrollTop on scroll event
|
||||
var debouncedUpdateScroll = _.debounce(function() {
|
||||
fileDesc.editorScrollTop = aceEditor.renderer.getScrollTop();
|
||||
}, 100);
|
||||
aceEditor.session.on('changeScrollTop', function() {
|
||||
if(documentContent !== undefined) {
|
||||
fileDesc.editorScrollTop = aceEditor.renderer.getScrollTop();
|
||||
debouncedUpdateScroll();
|
||||
}
|
||||
});
|
||||
// Store editor selection on change
|
||||
@ -419,9 +427,12 @@ define([
|
||||
var debouncedMakePreview = _.debounce(makePreview, 500);
|
||||
return function() {
|
||||
if(documentContent === undefined) {
|
||||
aceEditor.renderer.scrollToY(fileDesc.editorScrollTop);
|
||||
makePreview();
|
||||
//$editorElt.scrollTop(fileDesc.editorScrollTop);
|
||||
$previewContainerElt.scrollTop(fileDesc.previewScrollTop);
|
||||
_.defer(function() {
|
||||
eventMgr.onFileOpen(fileDesc);
|
||||
});
|
||||
}
|
||||
else {
|
||||
debouncedMakePreview();
|
||||
@ -441,13 +452,12 @@ define([
|
||||
};
|
||||
};
|
||||
}
|
||||
eventMgr.onEditorConfigure(editor);
|
||||
eventMgr.onPagedownConfigure(editor);
|
||||
editor.hooks.chain("onPreviewRefresh", eventMgr.onAsyncPreview);
|
||||
editor.run(previewWrapper);
|
||||
editor.run(aceEditor, previewWrapper);
|
||||
// editor.undoManager.reinit(initDocumentContent, fileDesc.editorStart,
|
||||
// fileDesc.editorEnd, fileDesc.editorScrollTop);
|
||||
aceEditor.selection.setSelectionRange(fileDesc.editorSelectRange);
|
||||
aceEditor.renderer.scrollToY(fileDesc.editorScrollTop);
|
||||
aceEditor.focus();
|
||||
|
||||
// Hide default buttons
|
||||
@ -470,23 +480,6 @@ define([
|
||||
var $btnGroupElt = $('.wmd-button-group4');
|
||||
$("#wmd-undo-button").append($('<i class="icon-reply">')).appendTo($btnGroupElt);
|
||||
$("#wmd-redo-button").append($('<i class="icon-forward">')).appendTo($btnGroupElt);
|
||||
|
||||
eventMgr.onFileOpen(fileDesc);
|
||||
};
|
||||
|
||||
// Used to lock the editor from the user interaction during asynchronous
|
||||
// tasks
|
||||
var uiLocked = false;
|
||||
core.lockUI = function(param) {
|
||||
uiLocked = param;
|
||||
$editorElt.prop("disabled", uiLocked);
|
||||
$(".navbar-inner .btn").toggleClass("blocked", uiLocked);
|
||||
if(uiLocked) {
|
||||
$(".lock-ui").removeClass("hide");
|
||||
}
|
||||
else {
|
||||
$(".lock-ui").addClass("hide");
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize multiple things and then fire eventMgr.onReady
|
||||
@ -569,29 +562,18 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
// UI layout
|
||||
createLayout();
|
||||
$editorElt = $("#wmd-input");
|
||||
|
||||
// Editor's textarea
|
||||
$("#wmd-input, #md-section-helper").css({
|
||||
$("#wmd-input").css({
|
||||
// Apply editor font
|
||||
"font-family": settings.editorFontFamily,
|
||||
"font-size": settings.editorFontSize + "px",
|
||||
"line-height": Math.round(settings.editorFontSize * (20 / 14)) + "px"
|
||||
"line-height": Math.round(settings.editorFontSize * (20 / 12)) + "px"
|
||||
});
|
||||
|
||||
// Handle tab key
|
||||
$editorElt.keydown(function(e) {
|
||||
if(e.keyCode === 9) {
|
||||
var value = $editorElt.val();
|
||||
var start = this.selectionStart;
|
||||
var end = this.selectionEnd;
|
||||
$(this).val(value.substring(0, start) + "\t" + value.substring(end));
|
||||
this.selectionStart = this.selectionEnd = start + 1;
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
// ACE editor
|
||||
createAceEditor();
|
||||
// UI layout
|
||||
createLayout();
|
||||
|
||||
// Do periodic tasks
|
||||
intervalId = window.setInterval(function() {
|
||||
@ -617,13 +599,14 @@ define([
|
||||
isModalShown = true;
|
||||
}).on('shown.bs.modal', function() {
|
||||
// Focus on the first input when modal opens
|
||||
_.defer(function(elt) {
|
||||
var elt = $(this);
|
||||
setTimeout(function() {
|
||||
elt.find("input:enabled:visible:first").focus();
|
||||
}, $(this));
|
||||
}, 50);
|
||||
}).on('hidden.bs.modal', function() {
|
||||
// Focus on the editor when modal is gone
|
||||
isModalShown = false;
|
||||
$editorElt.focus();
|
||||
aceEditor.focus();
|
||||
// Revert to current theme when settings modal is closed
|
||||
applyTheme(localStorage.theme);
|
||||
}).keyup(function(e) {
|
||||
|
@ -171,9 +171,12 @@ define([
|
||||
addEventHook("onLayoutResize");
|
||||
|
||||
// Operations on PageDown
|
||||
addEventHook("onEditorConfigure");
|
||||
addEventHook("onPagedownConfigure");
|
||||
addEventHook("onSectionsCreated");
|
||||
|
||||
// Operation on ACE
|
||||
addEventHook("onAceCreated");
|
||||
|
||||
var onPreviewFinished = createEventHook("onPreviewFinished");
|
||||
var onAsyncPreviewListenerList = getExtensionListenerList("onAsyncPreview");
|
||||
// The number of times we expect tryFinished to be called
|
||||
|
@ -30,7 +30,7 @@ define([
|
||||
var files = (evt.dataTransfer || evt.target).files;
|
||||
$(".modal-import-harddrive-markdown, .modal-import-harddrive-html").modal("hide");
|
||||
_.each(files, function(file) {
|
||||
if($(evt.target).is("#wmd-input") && file.name.match(/.(jpe?g|png|gif)$/)) {
|
||||
if($(evt.target).is("#wmd-input *") && file.name.match(/.(jpe?g|png|gif)$/)) {
|
||||
return;
|
||||
}
|
||||
var reader = new FileReader();
|
||||
|
@ -29,6 +29,11 @@ define([
|
||||
newConfig.shortcutNext = utils.getInputTextValue("#input-document-selector-shortcut-next", event);
|
||||
};
|
||||
|
||||
var aceEditor = undefined;
|
||||
documentSelector.onAceCreated = function(aceEditorParam) {
|
||||
aceEditor = aceEditorParam;
|
||||
};
|
||||
|
||||
var fileMgr = undefined;
|
||||
documentSelector.onFileMgrCreated = function(fileMgrParameter) {
|
||||
fileMgr = fileMgrParameter;
|
||||
@ -41,7 +46,6 @@ define([
|
||||
' </a>',
|
||||
'</li>'
|
||||
].join('');
|
||||
var $editorElt = undefined;
|
||||
var dropdownElt = undefined;
|
||||
var liEltMap = undefined;
|
||||
var liEltList = undefined;
|
||||
@ -70,7 +74,7 @@ define([
|
||||
fileMgr.selectFile(fileDesc);
|
||||
}
|
||||
else {
|
||||
$editorElt.focus();
|
||||
aceEditor.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -91,8 +95,6 @@ define([
|
||||
documentSelector.onPublishRemoved = buildSelector;
|
||||
|
||||
documentSelector.onReady = function() {
|
||||
$editorElt = $("#wmd-input");
|
||||
|
||||
if(documentSelector.config.orderBy == "title") {
|
||||
sortFunction = function(fileDesc) {
|
||||
return fileDesc.title.toLowerCase();
|
||||
|
@ -5,7 +5,7 @@ define([
|
||||
var emailConverter = new Extension("emailConverter", "Markdown Email", true);
|
||||
emailConverter.settingsBlock = '<p>Converts email adresses in the form <email@example.com> into clickable links.</p>';
|
||||
|
||||
emailConverter.onEditorConfigure = function(editor) {
|
||||
emailConverter.onPagedownConfigure = function(editor) {
|
||||
editor.getConverter().hooks.chain("postConversion", function(text) {
|
||||
return text.replace(/<(mailto\:)?([^\s>]+@[^\s>]+\.\S+?)>/g, function(match, mailto, email) {
|
||||
return '<a href="mailto:' + email + '">' + email + '</a>';
|
||||
|
@ -44,7 +44,7 @@ define([
|
||||
newConfig.highlighter = utils.getInputValue("#input-markdownextra-highlighter");
|
||||
};
|
||||
|
||||
markdownExtra.onEditorConfigure = function(editor) {
|
||||
markdownExtra.onPagedownConfigure = function(editor) {
|
||||
var converter = editor.getConverter();
|
||||
var options = {
|
||||
extensions: markdownExtra.config.extensions
|
||||
|
@ -61,7 +61,7 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
mathJax.onEditorConfigure = function(editorObject) {
|
||||
mathJax.onPagedownConfigure = function(editorObject) {
|
||||
t = document.getElementById("preview-contents");
|
||||
|
||||
var converter = editorObject.getConverter();
|
||||
|
@ -172,7 +172,7 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
partialRendering.onEditorConfigure = function(editor) {
|
||||
partialRendering.onPagedownConfigure = function(editor) {
|
||||
converter = editor.getConverter();
|
||||
converter.hooks.chain("preConversion", function(text) {
|
||||
var result = _.map(modifiedSections, function(section) {
|
||||
|
@ -10,14 +10,17 @@ define([
|
||||
var scrollLink = new Extension("scrollLink", "Scroll Link", true, true);
|
||||
scrollLink.settingsBlock = scrollLinkSettingsBlockHTML;
|
||||
|
||||
var aceEditor = undefined;
|
||||
scrollLink.onAceCreated = function(aceEditorParam) {
|
||||
aceEditor = aceEditorParam;
|
||||
};
|
||||
|
||||
var sectionList = undefined;
|
||||
scrollLink.onSectionsCreated = function(sectionListParam) {
|
||||
sectionList = sectionListParam;
|
||||
};
|
||||
|
||||
var $editorElt = undefined;
|
||||
var $previewElt = undefined;
|
||||
var $textareaElt = undefined;
|
||||
var mdSectionList = [];
|
||||
var htmlSectionList = [];
|
||||
function pxToFloat(px) {
|
||||
@ -27,57 +30,21 @@ define([
|
||||
var lastPreviewScrollTop = undefined;
|
||||
var buildSections = _.debounce(function() {
|
||||
|
||||
// Try to find Markdown sections by looking for titles
|
||||
mdSectionList = [];
|
||||
// It has to be the same width as wmd-input
|
||||
$textareaElt.width($editorElt.width());
|
||||
// Consider wmd-input top padding (will be used for 1st and last
|
||||
// section)
|
||||
var padding = pxToFloat($editorElt.css('padding-top'));
|
||||
var mdTextOffset = 0;
|
||||
var mdSectionOffset = 0;
|
||||
function addMdSection(sectionText) {
|
||||
var sectionHeight = padding;
|
||||
if(sectionText !== undefined) {
|
||||
$textareaElt.val(sectionText);
|
||||
sectionHeight += $textareaElt.prop('scrollHeight');
|
||||
}
|
||||
var newSectionOffset = mdSectionOffset + sectionHeight;
|
||||
_.each(sectionList, function(sectionText) {
|
||||
mdTextOffset += sectionText.length;
|
||||
var documentPosition = aceEditor.session.doc.indexToPosition(mdTextOffset);
|
||||
var screenPosition = aceEditor.session.documentToScreenPosition(documentPosition.row, documentPosition.column);
|
||||
var newSectionOffset = screenPosition.row * aceEditor.renderer.lineHeight;
|
||||
var sectionHeight = newSectionOffset - mdSectionOffset;
|
||||
mdSectionList.push({
|
||||
startOffset: mdSectionOffset,
|
||||
endOffset: newSectionOffset,
|
||||
height: sectionHeight
|
||||
});
|
||||
mdSectionOffset = newSectionOffset;
|
||||
padding = 0;
|
||||
}
|
||||
_.each(sectionList, function(sectionText, index) {
|
||||
if(index !== sectionList.length - 1) {
|
||||
if(sectionText.length === 0) {
|
||||
sectionText = undefined;
|
||||
}
|
||||
else {
|
||||
// Remove the last \n preceding the next title
|
||||
sectionText = sectionText.substring(0, sectionText.length - 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Last section
|
||||
// Consider wmd-input bottom padding and keep last empty line
|
||||
padding += pxToFloat($editorElt.css('padding-bottom'));
|
||||
}
|
||||
addMdSection(sectionText);
|
||||
});
|
||||
|
||||
// Apply a coef to manage divergence in some browsers
|
||||
var theoricalHeight = _.last(mdSectionList).endOffset;
|
||||
var realHeight = $editorElt[0].scrollHeight;
|
||||
var coef = realHeight/theoricalHeight;
|
||||
mdSectionList = _.map(mdSectionList, function(mdSection) {
|
||||
return {
|
||||
startOffset: mdSection.startOffset * coef,
|
||||
endOffset: mdSection.endOffset * coef,
|
||||
height: mdSection.height * coef,
|
||||
};
|
||||
});
|
||||
|
||||
// Try to find corresponding sections in the preview
|
||||
@ -114,11 +81,13 @@ define([
|
||||
var isScrollPreview = false;
|
||||
var doScrollLink = _.debounce(function() {
|
||||
if(mdSectionList.length === 0 || mdSectionList.length !== htmlSectionList.length) {
|
||||
// Delay
|
||||
doScrollLink();
|
||||
return;
|
||||
}
|
||||
var editorScrollTop = $editorElt.scrollTop();
|
||||
var editorScrollTop = aceEditor.renderer.getScrollTop();
|
||||
var previewScrollTop = $previewElt.scrollTop();
|
||||
function animate(srcScrollTop, srcSectionList, destElt, destSectionList, currentDestScrollTop, callback) {
|
||||
function getDestScrollTop(srcScrollTop, srcSectionList, destSectionList) {
|
||||
// Find the section corresponding to the offset
|
||||
var sectionIndex = undefined;
|
||||
var srcSection = _.find(srcSectionList, function(section, index) {
|
||||
@ -131,38 +100,56 @@ define([
|
||||
}
|
||||
var posInSection = (srcScrollTop - srcSection.startOffset) / srcSection.height;
|
||||
var destSection = destSectionList[sectionIndex];
|
||||
var destScrollTop = destSection.startOffset + destSection.height * posInSection;
|
||||
destScrollTop = _.min([
|
||||
destScrollTop,
|
||||
destElt.prop('scrollHeight') - destElt.outerHeight()
|
||||
]);
|
||||
if(Math.abs(destScrollTop - currentDestScrollTop) <= 9) {
|
||||
// Skip the animation if diff is <= 9
|
||||
callback(currentDestScrollTop);
|
||||
return;
|
||||
}
|
||||
destElt.animate({
|
||||
scrollTop: destScrollTop
|
||||
}, 500, function() {
|
||||
callback(destScrollTop);
|
||||
});
|
||||
return destSection.startOffset + destSection.height * posInSection;
|
||||
}
|
||||
// Perform the animation if diff > 9px
|
||||
if(isScrollEditor === true && Math.abs(editorScrollTop - lastEditorScrollTop) > 9) {
|
||||
isScrollEditor = false;
|
||||
// Animate the preview
|
||||
lastEditorScrollTop = editorScrollTop;
|
||||
animate(editorScrollTop, mdSectionList, $previewElt, htmlSectionList, previewScrollTop, function(destScrollTop) {
|
||||
lastPreviewScrollTop = destScrollTop;
|
||||
});
|
||||
var destScrollTop = getDestScrollTop(editorScrollTop, mdSectionList, htmlSectionList);
|
||||
destScrollTop = _.min([
|
||||
destScrollTop,
|
||||
$previewElt.prop('scrollHeight') - $previewElt.outerHeight()
|
||||
]);
|
||||
if(Math.abs(destScrollTop - previewScrollTop) <= 9) {
|
||||
// Skip the animation if diff is <= 9
|
||||
lastPreviewScrollTop = previewScrollTop;
|
||||
}
|
||||
else {
|
||||
$previewElt.animate({
|
||||
scrollTop: destScrollTop
|
||||
}, 'easeOutQuad', function() {
|
||||
lastPreviewScrollTop = destScrollTop;
|
||||
});
|
||||
}
|
||||
}
|
||||
else if(isScrollPreview === true && Math.abs(previewScrollTop - lastPreviewScrollTop) > 9) {
|
||||
isScrollPreview = false;
|
||||
// Animate the editor
|
||||
lastPreviewScrollTop = previewScrollTop;
|
||||
animate(previewScrollTop, htmlSectionList, $editorElt, mdSectionList, editorScrollTop, function(destScrollTop) {
|
||||
lastEditorScrollTop = destScrollTop;
|
||||
});
|
||||
var destScrollTop = getDestScrollTop(previewScrollTop, htmlSectionList, mdSectionList);
|
||||
destScrollTop = _.min([
|
||||
destScrollTop,
|
||||
aceEditor.session.getScreenLength() * aceEditor.renderer.lineHeight - aceEditor.renderer.$size.scrollerHeight
|
||||
]);
|
||||
if(Math.abs(destScrollTop - editorScrollTop) <= 9) {
|
||||
// Skip the animation if diff is <= 9
|
||||
lastEditorScrollTop = editorScrollTop;
|
||||
}
|
||||
else {
|
||||
$("<div>").animate({
|
||||
value: destScrollTop - editorScrollTop
|
||||
}, {
|
||||
easing: 'easeOutQuad',
|
||||
step: function(now) {
|
||||
aceEditor.session.setScrollTop(editorScrollTop + now);
|
||||
},
|
||||
complete: function() {
|
||||
lastEditorScrollTop = destScrollTop;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
|
||||
@ -171,12 +158,12 @@ define([
|
||||
buildSections();
|
||||
};
|
||||
|
||||
scrollLink.onReady = function() {
|
||||
$editorElt = $("#wmd-input");
|
||||
$previewElt = $(".preview-container");
|
||||
scrollLink.onFileClosed = function() {
|
||||
mdSectionList = [];
|
||||
};
|
||||
|
||||
// This textarea is used to measure sections height
|
||||
$textareaElt = $("#md-section-helper");
|
||||
scrollLink.onReady = function() {
|
||||
$previewElt = $(".preview-container");
|
||||
|
||||
$previewElt.bind("keyup mouseup mousewheel", function() {
|
||||
isScrollPreview = true;
|
||||
@ -188,7 +175,7 @@ define([
|
||||
isScrollEditor = false;
|
||||
doScrollLink();
|
||||
});
|
||||
$editorElt.bind("keyup mouseup mousewheel", function() {
|
||||
aceEditor.session.on("changeScrollTop", function(e) {
|
||||
isScrollEditor = true;
|
||||
isScrollPreview = false;
|
||||
doScrollLink();
|
||||
@ -196,7 +183,7 @@ define([
|
||||
};
|
||||
|
||||
var $previewContentsElt = undefined;
|
||||
scrollLink.onEditorConfigure = function(editor) {
|
||||
scrollLink.onPagedownConfigure = function(editor) {
|
||||
$previewContentsElt = $("#preview-contents");
|
||||
editor.getConverter().hooks.chain("postConversion", function(text) {
|
||||
// To avoid losing scrolling position before elements are fully
|
||||
|
@ -114,7 +114,7 @@ define([
|
||||
return '<div class="toc">\n<ul>\n' + elementList.join("") + '</ul>\n</div>\n';
|
||||
}
|
||||
|
||||
toc.onEditorConfigure = function(editor) {
|
||||
toc.onPagedownConfigure = function(editor) {
|
||||
previewContentsElt = document.getElementById('preview-contents');
|
||||
var tocEltList = document.querySelectorAll('.table-of-contents');
|
||||
var tocExp = new RegExp("^" + toc.config.marker + "$", "g");
|
||||
|
@ -150,9 +150,12 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
eventMgr.addListener("onReady", function() {
|
||||
var $editorElt = $("#wmd-input");
|
||||
var aceEditor = undefined;
|
||||
eventMgr.addListener('onAceCreated', function(aceEditorParam) {
|
||||
aceEditor = aceEditorParam;
|
||||
});
|
||||
|
||||
eventMgr.addListener("onReady", function() {
|
||||
fileMgr.selectFile();
|
||||
|
||||
var $fileTitleElt = $('.file-title-navbar');
|
||||
@ -160,10 +163,6 @@ define([
|
||||
$(".action-create-file").click(function() {
|
||||
var fileDesc = fileMgr.createFile();
|
||||
fileMgr.selectFile(fileDesc);
|
||||
var wmdInput = $editorElt.focus().get(0);
|
||||
if(wmdInput.setSelectionRange) {
|
||||
wmdInput.setSelectionRange(0, 0);
|
||||
}
|
||||
$fileTitleElt.click();
|
||||
});
|
||||
$(".action-remove-file").click(function() {
|
||||
@ -189,7 +188,7 @@ define([
|
||||
eventMgr.onTitleChanged(fileDesc);
|
||||
}
|
||||
$fileTitleInputElt.val(fileDesc.title);
|
||||
$editorElt.focus();
|
||||
aceEditor.focus();
|
||||
}
|
||||
$fileTitleInputElt.blur(function() {
|
||||
applyTitle();
|
||||
@ -206,7 +205,7 @@ define([
|
||||
window.location.href = ".";
|
||||
});
|
||||
$(".action-edit-document").click(function() {
|
||||
var content = $editorElt.val();
|
||||
var content = aceEditor.getValue();
|
||||
var title = fileMgr.currentFile.title;
|
||||
var fileDesc = fileMgr.createFile(title, content);
|
||||
fileMgr.selectFile(fileDesc);
|
||||
|
@ -39,7 +39,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wmd-input" class="ui-layout-center form-control"></div>
|
||||
<div id="wmd-input" class="ui-layout-center"></div>
|
||||
<div class="ui-layout-east preview-container"></div>
|
||||
<div class="ui-layout-south preview-container"></div>
|
||||
<div id="wmd-button-bar" class="hide"></div>
|
||||
@ -1076,6 +1076,5 @@
|
||||
</div>
|
||||
|
||||
|
||||
<textarea id="md-section-helper" class="form-control"></textarea>
|
||||
<div class="lock-ui hide"></div>
|
||||
<div id="dropboxjs" data-app-key="x0k2l8puemfvg0o"></div>
|
@ -34,7 +34,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="wmd-button-bar" class="hide"></div>
|
||||
<textarea id="wmd-input" class="hide"></textarea>
|
||||
<div id="wmd-input" class="hide"></div>
|
||||
<div class="ui-layout-center preview-container"></div>
|
||||
|
||||
<div class="menu-panel collapse width">
|
||||
|
@ -135,11 +135,11 @@
|
||||
panels;
|
||||
|
||||
var undoManager;
|
||||
this.run = function (previewWrapper) {
|
||||
this.run = function (aceEditor, previewWrapper) {
|
||||
if (panels)
|
||||
return; // already initialized
|
||||
|
||||
panels = new PanelCollection(idPostfix);
|
||||
panels = new PanelCollection(idPostfix, aceEditor);
|
||||
var commandManager = new CommandManager(hooks, getString);
|
||||
var previewManager = new PreviewManager(markdownConverter, panels, function () { hooks.onPreviewRefresh(); }, previewWrapper);
|
||||
var uiManager;
|
||||
@ -318,10 +318,10 @@
|
||||
// This ONLY affects Internet Explorer (tested on versions 6, 7
|
||||
// and 8) and ONLY on button clicks. Keyboard shortcuts work
|
||||
// normally since the focus never leaves the textarea.
|
||||
function PanelCollection(postfix) {
|
||||
function PanelCollection(postfix, aceEditor) {
|
||||
this.buttonBar = doc.getElementById("wmd-button-bar" + postfix);
|
||||
this.preview = doc.getElementById("wmd-preview" + postfix);
|
||||
this.input = window.wmdInput;
|
||||
this.input = aceEditor;
|
||||
};
|
||||
|
||||
// Returns true if the DOM element is visible, false if it's hidden.
|
||||
@ -467,6 +467,7 @@
|
||||
return [maxWidth, maxHeight, innerWidth, innerHeight];
|
||||
};
|
||||
|
||||
/*benweet
|
||||
// Handles pushing and popping TextareaStates for undo/redo commands.
|
||||
// I should rename the stack variables to list.
|
||||
function UndoManager(callback, panels) {
|
||||
@ -717,6 +718,7 @@
|
||||
}
|
||||
|
||||
// end of UndoManager
|
||||
*/
|
||||
|
||||
// The input textarea state/contents.
|
||||
// This is used to implement undo/redo by the undo manager.
|
||||
@ -737,14 +739,14 @@
|
||||
|
||||
var Range = require('ace/range').Range;
|
||||
(function(range) {
|
||||
stateObj.before = inputArea.editor.session.getTextRange(new Range(0,0,range.start.row, range.start.column));
|
||||
stateObj.selection = inputArea.editor.session.getTextRange();
|
||||
stateObj.after = inputArea.editor.session.getTextRange(new Range(range.end.row, range.end.column, Number.MAX_VALUE, Number.MAX_VALUE));
|
||||
})(inputArea.editor.selection.getRange());
|
||||
stateObj.before = inputArea.session.getTextRange(new Range(0,0,range.start.row, range.start.column));
|
||||
stateObj.selection = inputArea.session.getTextRange();
|
||||
stateObj.after = inputArea.session.getTextRange(new Range(range.end.row, range.end.column, Number.MAX_VALUE, Number.MAX_VALUE));
|
||||
})(inputArea.selection.getRange());
|
||||
this.text = [this.before, this.selection, this.after].join('');
|
||||
this.length = this.text.length;
|
||||
this.setInputAreaSelectionStartEnd();
|
||||
this.scrollTop = inputArea.scrollTop;
|
||||
this.scrollTop = inputArea.renderer.getScrollTop();
|
||||
/*benweet
|
||||
if (!this.text && inputArea.selectionStart || inputArea.selectionStart === 0) {
|
||||
this.text = inputArea.value;
|
||||
@ -757,11 +759,11 @@
|
||||
this.setInputAreaSelection = function () {
|
||||
|
||||
var Range = require('ace/range').Range;
|
||||
inputArea.editor.selection.setSelectionRange((function(posStart, posEnd) {
|
||||
inputArea.selection.setSelectionRange((function(posStart, posEnd) {
|
||||
return new Range(posStart.row, posStart.column, posEnd.row, posEnd.column);
|
||||
})(inputArea.editor.session.doc.indexToPosition(stateObj.start), inputArea.editor.session.doc.indexToPosition(stateObj.end)));
|
||||
inputArea.editor.renderer.scrollToY(stateObj.scrollTop);
|
||||
inputArea.editor.focus();
|
||||
})(inputArea.session.doc.indexToPosition(stateObj.start), inputArea.session.doc.indexToPosition(stateObj.end)));
|
||||
inputArea.renderer.scrollToY(stateObj.scrollTop);
|
||||
inputArea.focus();
|
||||
|
||||
/*benweet
|
||||
if (!util.isVisible(inputArea)) {
|
||||
@ -871,8 +873,8 @@
|
||||
var Range = require('ace/range').Range;
|
||||
var range = (function(posStart, posEnd) {
|
||||
return new Range(posStart.row, posStart.column, posEnd.row, posEnd.column);
|
||||
})(inputArea.editor.session.doc.indexToPosition(startIndex), inputArea.editor.session.doc.indexToPosition(stateObj.length - endIndex));
|
||||
inputArea.editor.session.replace(range, stateObj.text.substring(startIndex, afterMaxOffset - endIndex + 1));
|
||||
})(inputArea.session.doc.indexToPosition(startIndex), inputArea.session.doc.indexToPosition(stateObj.length - endIndex));
|
||||
inputArea.session.replace(range, stateObj.text.substring(startIndex, afterMaxOffset - endIndex + 1));
|
||||
this.setInputAreaSelection();
|
||||
|
||||
/*benweet
|
||||
@ -960,7 +962,7 @@
|
||||
return;
|
||||
|
||||
|
||||
var text = panels.input.value;
|
||||
var text = panels.input.getValue();
|
||||
if (text && text == oldInputText) {
|
||||
return; // Input text hasn't changed.
|
||||
}
|
||||
@ -1103,7 +1105,7 @@
|
||||
/*benweet
|
||||
setupEvents(panels.input, applyTimeout);
|
||||
*/
|
||||
panels.input.editor.session.on('change', applyTimeout);
|
||||
panels.input.session.on('change', applyTimeout);
|
||||
//Not necessary
|
||||
//makePreviewHtml();
|
||||
|
||||
@ -1330,7 +1332,7 @@
|
||||
return;
|
||||
}
|
||||
var identifier = identifierList.pop();
|
||||
inputBox.editor.commands.addCommand({
|
||||
inputBox.commands.addCommand({
|
||||
name: getString(identifier),
|
||||
bindKey: {win: 'Ctrl-' + keyStrokes[identifier], mac: 'Command-' + keyStrokes[identifier]},
|
||||
exec: function(editor) {
|
||||
@ -1530,7 +1532,7 @@
|
||||
return;
|
||||
}
|
||||
panels.ieCachedRange = document.selection.createRange();
|
||||
panels.ieCachedScrollTop = panels.input.scrollTop;
|
||||
panels.ieCachedScrollTop = panels.input.renderer.getScrollTop();
|
||||
};
|
||||
}
|
||||
|
||||
@ -1617,10 +1619,10 @@
|
||||
buttons.hr = makeButton("wmd-hr-button", getStringAndKey("hr"), "-180px", bindCommand("doHorizontalRule"));
|
||||
makeSpacer(3);
|
||||
buttons.undo = makeButton("wmd-undo-button", getStringAndKey("undo"), "-200px", null);
|
||||
buttons.undo.execute = function (manager) { inputBox.editor.session.getUndoManager().undo(); };
|
||||
buttons.undo.execute = function (manager) { inputBox.session.getUndoManager().undo(); };
|
||||
|
||||
buttons.redo = makeButton("wmd-redo-button", getStringAndKey("redo"), "-220px", null);
|
||||
buttons.redo.execute = function (manager) { inputBox.editor.session.getUndoManager().redo(); };
|
||||
buttons.redo.execute = function (manager) { inputBox.session.getUndoManager().redo(); };
|
||||
|
||||
if (helpOptions) {
|
||||
var helpButton = document.createElement("li");
|
||||
@ -1640,7 +1642,7 @@
|
||||
}
|
||||
|
||||
setUndoRedoButtonStates();
|
||||
inputBox.editor.session.on('change', setUndoRedoButtonStates);
|
||||
inputBox.session.on('change', setUndoRedoButtonStates);
|
||||
}
|
||||
|
||||
function setUndoRedoButtonStates() {
|
||||
@ -1651,8 +1653,8 @@
|
||||
}
|
||||
*/
|
||||
setTimeout(function() {
|
||||
setupButton(buttons.undo, inputBox.editor.session.getUndoManager().hasUndo());
|
||||
setupButton(buttons.redo, inputBox.editor.session.getUndoManager().hasRedo());
|
||||
setupButton(buttons.undo, inputBox.session.getUndoManager().hasUndo());
|
||||
setupButton(buttons.redo, inputBox.session.getUndoManager().hasRedo());
|
||||
}, 0);
|
||||
};
|
||||
|
||||
|
@ -55,13 +55,13 @@ var MarkdownHighlightRules = function() {
|
||||
token : "support.function",
|
||||
regex : "(`+)(.*?[^`])(\\1)"
|
||||
}, { // reference
|
||||
token : ["text", "constant", "text", "url", "string", "text"],
|
||||
token : ["text", "reference", "text", "markup.underline", "description", "text"],
|
||||
regex : "^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:[\"][^\"]+[\"])?(\\s*))$"
|
||||
}, { // link by reference
|
||||
token : ["text", "string", "text", "constant", "text"],
|
||||
token : ["text", "description", "text", "markup.underline", "text"],
|
||||
regex : "(\\[)((?:[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(.*?)(\\])"
|
||||
}, { // link by url
|
||||
token : ["text", "string", "text", "markup.underline", "string", "text"],
|
||||
token : ["text", "description", "text", "markup.underline", "string", "text"],
|
||||
regex : "(\\[)"+
|
||||
"(\\[[^\\]]*\\]|[^\\[\\]]*)"+
|
||||
"(\\]\\([ \\t]*)"+
|
||||
|
@ -274,7 +274,7 @@ define([
|
||||
|
||||
// Keep a link to the pagedown editor
|
||||
var editor = undefined;
|
||||
eventMgr.addListener("onEditorConfigure", function(editorParam) {
|
||||
eventMgr.addListener("onPagedownConfigure", function(editorParam) {
|
||||
editor = editorParam;
|
||||
});
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
@primary-color: #333;
|
||||
@primary-color-light: lighten(@primary-color, 13%);
|
||||
@primary-color-lighter: lighten(@primary-color, 20%);
|
||||
@primary-color-lightest: lighten(@primary-color, 40%);
|
||||
@primary-color-lightest: lighten(@primary-color, 33%);
|
||||
@primary-color-inv: #fff;
|
||||
@bg-navbar-hover: @primary-bg-lighter;
|
||||
@error-border: #ff8661;
|
||||
@ -908,6 +908,10 @@ ul,ol {
|
||||
* Editor
|
||||
*****************************/
|
||||
|
||||
.ace_editor {
|
||||
color: @primary-color-light;
|
||||
}
|
||||
|
||||
.ace-tm .ace_marker-layer .ace_active-line {
|
||||
background-color: @primary-bg-lighter;
|
||||
}
|
||||
@ -934,6 +938,10 @@ ul,ol {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.ace-tm .ace_description {
|
||||
color: @primary-color-lightest;
|
||||
}
|
||||
|
||||
#wmd-input {
|
||||
.box-shadow(none);
|
||||
padding: 0;
|
||||
|
Loading…
Reference in New Issue
Block a user