Extract editor related code
- in public/js/lib/editor/index.js
This commit is contained in:
parent
121d84863a
commit
6556c284e5
3 changed files with 536 additions and 569 deletions
|
@ -73,145 +73,12 @@ import {
|
|||
var renderer = require('./render');
|
||||
var preventXSS = renderer.preventXSS;
|
||||
|
||||
import Editor from './lib/editor';
|
||||
|
||||
import getUIElements from './lib/editor/ui-elements';
|
||||
|
||||
var defaultTextHeight = 20;
|
||||
var viewportMargin = 20;
|
||||
var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;
|
||||
var defaultEditorMode = 'gfm';
|
||||
var defaultExtraKeys = {
|
||||
"F10": function (cm) {
|
||||
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
|
||||
},
|
||||
"Esc": function (cm) {
|
||||
if (cm.getOption('keyMap').substr(0, 3) === 'vim') return CodeMirror.Pass;
|
||||
else if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
|
||||
},
|
||||
"Cmd-S": function () {
|
||||
return false;
|
||||
},
|
||||
"Ctrl-S": function () {
|
||||
return false;
|
||||
},
|
||||
"Enter": "newlineAndIndentContinueMarkdownList",
|
||||
"Tab": function (cm) {
|
||||
var tab = '\t';
|
||||
var spaces = Array(parseInt(cm.getOption("indentUnit")) + 1).join(" ");
|
||||
//auto indent whole line when in list or blockquote
|
||||
var cursor = cm.getCursor();
|
||||
var line = cm.getLine(cursor.line);
|
||||
var regex = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))/;
|
||||
var match;
|
||||
var multiple = cm.getSelection().split('\n').length > 1 || cm.getSelections().length > 1;
|
||||
if (multiple) {
|
||||
cm.execCommand('defaultTab');
|
||||
} else if ((match = regex.exec(line)) !== null) {
|
||||
var ch = match[1].length;
|
||||
var pos = {
|
||||
line: cursor.line,
|
||||
ch: ch
|
||||
};
|
||||
if (cm.getOption('indentWithTabs'))
|
||||
cm.replaceRange(tab, pos, pos, '+input');
|
||||
else
|
||||
cm.replaceRange(spaces, pos, pos, '+input');
|
||||
} else {
|
||||
if (cm.getOption('indentWithTabs'))
|
||||
cm.execCommand('defaultTab');
|
||||
else {
|
||||
cm.replaceSelection(spaces);
|
||||
}
|
||||
}
|
||||
},
|
||||
"Cmd-Left": "goLineLeftSmart",
|
||||
"Cmd-Right": "goLineRight",
|
||||
"Ctrl-C": function (cm) {
|
||||
if (!mac && cm.getOption('keyMap').substr(0, 3) === 'vim') document.execCommand("copy");
|
||||
else return CodeMirror.Pass;
|
||||
},
|
||||
"Ctrl-*": function (cm) {
|
||||
wrapTextWith(cm, '*');
|
||||
},
|
||||
"Shift-Ctrl-8": function (cm) {
|
||||
wrapTextWith(cm, '*');
|
||||
},
|
||||
"Ctrl-_": function (cm) {
|
||||
wrapTextWith(cm, '_');
|
||||
},
|
||||
"Shift-Ctrl--": function (cm) {
|
||||
wrapTextWith(cm, '_');
|
||||
},
|
||||
"Ctrl-~": function (cm) {
|
||||
wrapTextWith(cm, '~');
|
||||
},
|
||||
"Shift-Ctrl-`": function (cm) {
|
||||
wrapTextWith(cm, '~');
|
||||
},
|
||||
"Ctrl-^": function (cm) {
|
||||
wrapTextWith(cm, '^');
|
||||
},
|
||||
"Shift-Ctrl-6": function (cm) {
|
||||
wrapTextWith(cm, '^');
|
||||
},
|
||||
"Ctrl-+": function (cm) {
|
||||
wrapTextWith(cm, '+');
|
||||
},
|
||||
"Shift-Ctrl-=": function (cm) {
|
||||
wrapTextWith(cm, '+');
|
||||
},
|
||||
"Ctrl-=": function (cm) {
|
||||
wrapTextWith(cm, '=');
|
||||
},
|
||||
"Shift-Ctrl-Backspace": function (cm) {
|
||||
wrapTextWith(cm, 'Backspace');
|
||||
}
|
||||
};
|
||||
|
||||
var wrapSymbols = ['*', '_', '~', '^', '+', '='];
|
||||
|
||||
function wrapTextWith(cm, symbol) {
|
||||
if (!cm.getSelection()) {
|
||||
return CodeMirror.Pass;
|
||||
} else {
|
||||
var ranges = cm.listSelections();
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var range = ranges[i];
|
||||
if (!range.empty()) {
|
||||
var from = range.from(), to = range.to();
|
||||
if (symbol !== 'Backspace') {
|
||||
cm.replaceRange(symbol, to, to, '+input');
|
||||
cm.replaceRange(symbol, from, from, '+input');
|
||||
// workaround selection range not correct after add symbol
|
||||
var _ranges = cm.listSelections();
|
||||
var anchorIndex = editor.indexFromPos(_ranges[i].anchor);
|
||||
var headIndex = editor.indexFromPos(_ranges[i].head);
|
||||
if (anchorIndex > headIndex) {
|
||||
_ranges[i].anchor.ch--;
|
||||
} else {
|
||||
_ranges[i].head.ch--;
|
||||
}
|
||||
cm.setSelections(_ranges);
|
||||
} else {
|
||||
var preEndPos = {
|
||||
line: to.line,
|
||||
ch: to.ch + 1
|
||||
};
|
||||
var preText = cm.getRange(to, preEndPos);
|
||||
var preIndex = wrapSymbols.indexOf(preText);
|
||||
var postEndPos = {
|
||||
line: from.line,
|
||||
ch: from.ch - 1
|
||||
};
|
||||
var postText = cm.getRange(postEndPos, from);
|
||||
var postIndex = wrapSymbols.indexOf(postText);
|
||||
// check if surround symbol are list in array and matched
|
||||
if (preIndex > -1 && postIndex > -1 && preIndex === postIndex) {
|
||||
cm.replaceRange("", to, preEndPos, '+delete');
|
||||
cm.replaceRange("", postEndPos, from, '+delete');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var idleTime = 300000; //5 mins
|
||||
var updateViewDebounce = 100;
|
||||
|
@ -432,353 +299,25 @@ window.fileTypes = {
|
|||
"py": "python"
|
||||
};
|
||||
|
||||
//editor settings
|
||||
// editor settings
|
||||
var textit = document.getElementById("textit");
|
||||
if (!textit) throw new Error("There was no textit area!");
|
||||
window.editor = CodeMirror.fromTextArea(textit, {
|
||||
mode: defaultEditorMode,
|
||||
backdrop: defaultEditorMode,
|
||||
keyMap: "sublime",
|
||||
viewportMargin: viewportMargin,
|
||||
styleActiveLine: true,
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
showCursorWhenSelecting: true,
|
||||
highlightSelectionMatches: true,
|
||||
indentUnit: 4,
|
||||
continueComments: "Enter",
|
||||
theme: "one-dark",
|
||||
inputStyle: "textarea",
|
||||
matchBrackets: true,
|
||||
autoCloseBrackets: true,
|
||||
matchTags: {
|
||||
bothTags: true
|
||||
},
|
||||
autoCloseTags: true,
|
||||
foldGutter: true,
|
||||
gutters: ["CodeMirror-linenumbers", "authorship-gutters", "CodeMirror-foldgutter"],
|
||||
extraKeys: defaultExtraKeys,
|
||||
flattenSpans: true,
|
||||
addModeClass: true,
|
||||
readOnly: true,
|
||||
autoRefresh: true,
|
||||
otherCursors: true,
|
||||
placeholder: "← Start by entering a title here\n===\nVisit /features if you don't know what to do.\nHappy hacking :)"
|
||||
});
|
||||
if (!textit) {
|
||||
throw new Error("There was no textit area!");
|
||||
}
|
||||
|
||||
const editorInstance = new Editor();
|
||||
var editor = editorInstance.init(textit);
|
||||
|
||||
// TODO: global referncing in jquery-textcomplete patch
|
||||
window.editor = editor;
|
||||
|
||||
var inlineAttach = inlineAttachment.editors.codemirror4.attach(editor);
|
||||
defaultTextHeight = parseInt($(".CodeMirror").css('line-height'));
|
||||
|
||||
var statusBarTemplate = null;
|
||||
var statusBar = null;
|
||||
var statusPanel = null;
|
||||
var statusCursor = null;
|
||||
var statusFile = null;
|
||||
var statusIndicators = null;
|
||||
var statusLength = null;
|
||||
var statusKeymap = null;
|
||||
var statusIndent = null;
|
||||
var statusTheme = null;
|
||||
var statusSpellcheck = null;
|
||||
var statusPreferences = null;
|
||||
|
||||
function getStatusBarTemplate(callback) {
|
||||
$.get(serverurl + '/views/statusbar.html', function (template) {
|
||||
statusBarTemplate = template;
|
||||
if (callback) callback();
|
||||
});
|
||||
}
|
||||
getStatusBarTemplate();
|
||||
|
||||
function addStatusBar() {
|
||||
if (!statusBarTemplate) {
|
||||
getStatusBarTemplate(addStatusBar);
|
||||
return;
|
||||
}
|
||||
statusBar = $(statusBarTemplate);
|
||||
statusCursor = statusBar.find('.status-cursor');
|
||||
statusFile = statusBar.find('.status-file');
|
||||
statusIndicators = statusBar.find('.status-indicators');
|
||||
statusIndent = statusBar.find('.status-indent');
|
||||
statusKeymap = statusBar.find('.status-keymap');
|
||||
statusLength = statusBar.find('.status-length');
|
||||
statusTheme = statusBar.find('.status-theme');
|
||||
statusSpellcheck = statusBar.find('.status-spellcheck');
|
||||
statusPreferences = statusBar.find('.status-preferences');
|
||||
statusPanel = editor.addPanel(statusBar[0], {
|
||||
position: "bottom"
|
||||
});
|
||||
|
||||
setIndent();
|
||||
setKeymap();
|
||||
setTheme();
|
||||
setSpellcheck();
|
||||
setPreferences();
|
||||
}
|
||||
|
||||
function setIndent() {
|
||||
var cookieIndentType = Cookies.get('indent_type');
|
||||
var cookieTabSize = parseInt(Cookies.get('tab_size'));
|
||||
var cookieSpaceUnits = parseInt(Cookies.get('space_units'));
|
||||
if (cookieIndentType) {
|
||||
if (cookieIndentType == 'tab') {
|
||||
editor.setOption('indentWithTabs', true);
|
||||
if (cookieTabSize)
|
||||
editor.setOption('indentUnit', cookieTabSize);
|
||||
} else if (cookieIndentType == 'space') {
|
||||
editor.setOption('indentWithTabs', false);
|
||||
if (cookieSpaceUnits)
|
||||
editor.setOption('indentUnit', cookieSpaceUnits);
|
||||
}
|
||||
}
|
||||
if (cookieTabSize)
|
||||
editor.setOption('tabSize', cookieTabSize);
|
||||
|
||||
var type = statusIndicators.find('.indent-type');
|
||||
var widthLabel = statusIndicators.find('.indent-width-label');
|
||||
var widthInput = statusIndicators.find('.indent-width-input');
|
||||
|
||||
function setType() {
|
||||
if (editor.getOption('indentWithTabs')) {
|
||||
Cookies.set('indent_type', 'tab', {
|
||||
expires: 365
|
||||
});
|
||||
type.text('Tab Size:');
|
||||
} else {
|
||||
Cookies.set('indent_type', 'space', {
|
||||
expires: 365
|
||||
});
|
||||
type.text('Spaces:');
|
||||
}
|
||||
}
|
||||
setType();
|
||||
|
||||
function setUnit() {
|
||||
var unit = editor.getOption('indentUnit');
|
||||
if (editor.getOption('indentWithTabs')) {
|
||||
Cookies.set('tab_size', unit, {
|
||||
expires: 365
|
||||
});
|
||||
} else {
|
||||
Cookies.set('space_units', unit, {
|
||||
expires: 365
|
||||
});
|
||||
}
|
||||
widthLabel.text(unit);
|
||||
}
|
||||
setUnit();
|
||||
|
||||
type.click(function () {
|
||||
if (editor.getOption('indentWithTabs')) {
|
||||
editor.setOption('indentWithTabs', false);
|
||||
cookieSpaceUnits = parseInt(Cookies.get('space_units'));
|
||||
if (cookieSpaceUnits)
|
||||
editor.setOption('indentUnit', cookieSpaceUnits)
|
||||
} else {
|
||||
editor.setOption('indentWithTabs', true);
|
||||
cookieTabSize = parseInt(Cookies.get('tab_size'));
|
||||
if (cookieTabSize) {
|
||||
editor.setOption('indentUnit', cookieTabSize);
|
||||
editor.setOption('tabSize', cookieTabSize);
|
||||
}
|
||||
}
|
||||
setType();
|
||||
setUnit();
|
||||
});
|
||||
widthLabel.click(function () {
|
||||
if (widthLabel.is(':visible')) {
|
||||
widthLabel.addClass('hidden');
|
||||
widthInput.removeClass('hidden');
|
||||
widthInput.val(editor.getOption('indentUnit'));
|
||||
widthInput.select();
|
||||
} else {
|
||||
widthLabel.removeClass('hidden');
|
||||
widthInput.addClass('hidden');
|
||||
}
|
||||
});
|
||||
widthInput.on('change', function () {
|
||||
var val = parseInt(widthInput.val());
|
||||
if (!val) val = editor.getOption('indentUnit');
|
||||
if (val < 1) val = 1;
|
||||
else if (val > 10) val = 10;
|
||||
|
||||
if (editor.getOption('indentWithTabs')) {
|
||||
editor.setOption('tabSize', val);
|
||||
}
|
||||
editor.setOption('indentUnit', val);
|
||||
setUnit();
|
||||
});
|
||||
widthInput.on('blur', function () {
|
||||
widthLabel.removeClass('hidden');
|
||||
widthInput.addClass('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
function setKeymap() {
|
||||
var cookieKeymap = Cookies.get('keymap');
|
||||
if (cookieKeymap)
|
||||
editor.setOption('keyMap', cookieKeymap);
|
||||
|
||||
var label = statusIndicators.find('.ui-keymap-label');
|
||||
var sublime = statusIndicators.find('.ui-keymap-sublime');
|
||||
var emacs = statusIndicators.find('.ui-keymap-emacs');
|
||||
var vim = statusIndicators.find('.ui-keymap-vim');
|
||||
|
||||
function setKeymapLabel() {
|
||||
var keymap = editor.getOption('keyMap');
|
||||
Cookies.set('keymap', keymap, {
|
||||
expires: 365
|
||||
});
|
||||
label.text(keymap);
|
||||
restoreOverrideEditorKeymap();
|
||||
setOverrideBrowserKeymap();
|
||||
}
|
||||
setKeymapLabel();
|
||||
|
||||
sublime.click(function () {
|
||||
editor.setOption('keyMap', 'sublime');
|
||||
setKeymapLabel();
|
||||
});
|
||||
emacs.click(function () {
|
||||
editor.setOption('keyMap', 'emacs');
|
||||
setKeymapLabel();
|
||||
});
|
||||
vim.click(function () {
|
||||
editor.setOption('keyMap', 'vim');
|
||||
setKeymapLabel();
|
||||
});
|
||||
}
|
||||
|
||||
function setTheme() {
|
||||
var cookieTheme = Cookies.get('theme');
|
||||
if (cookieTheme) {
|
||||
editor.setOption('theme', cookieTheme);
|
||||
}
|
||||
|
||||
var themeToggle = statusTheme.find('.ui-theme-toggle');
|
||||
themeToggle.click(function () {
|
||||
var theme = editor.getOption('theme');
|
||||
if (theme == "one-dark") {
|
||||
theme = "default";
|
||||
} else {
|
||||
theme = "one-dark";
|
||||
}
|
||||
editor.setOption('theme', theme);
|
||||
Cookies.set('theme', theme, {
|
||||
expires: 365
|
||||
});
|
||||
checkTheme();
|
||||
});
|
||||
function checkTheme() {
|
||||
var theme = editor.getOption('theme');
|
||||
if (theme == "one-dark") {
|
||||
themeToggle.removeClass('active');
|
||||
} else {
|
||||
themeToggle.addClass('active');
|
||||
}
|
||||
}
|
||||
checkTheme();
|
||||
}
|
||||
|
||||
function setSpellcheck() {
|
||||
var cookieSpellcheck = Cookies.get('spellcheck');
|
||||
if (cookieSpellcheck) {
|
||||
var mode = null;
|
||||
if (cookieSpellcheck === 'true' || cookieSpellcheck === true) {
|
||||
mode = 'spell-checker';
|
||||
} else {
|
||||
mode = defaultEditorMode;
|
||||
}
|
||||
if (mode && mode !== editor.getOption('mode')) {
|
||||
editor.setOption('mode', mode);
|
||||
}
|
||||
}
|
||||
|
||||
var spellcheckToggle = statusSpellcheck.find('.ui-spellcheck-toggle');
|
||||
spellcheckToggle.click(function () {
|
||||
var mode = editor.getOption('mode');
|
||||
if (mode == defaultEditorMode) {
|
||||
mode = "spell-checker";
|
||||
} else {
|
||||
mode = defaultEditorMode;
|
||||
}
|
||||
if (mode && mode !== editor.getOption('mode')) {
|
||||
editor.setOption('mode', mode);
|
||||
}
|
||||
Cookies.set('spellcheck', (mode == "spell-checker"), {
|
||||
expires: 365
|
||||
});
|
||||
checkSpellcheck();
|
||||
});
|
||||
function checkSpellcheck() {
|
||||
var mode = editor.getOption('mode');
|
||||
if (mode == defaultEditorMode) {
|
||||
spellcheckToggle.removeClass('active');
|
||||
} else {
|
||||
spellcheckToggle.addClass('active');
|
||||
}
|
||||
}
|
||||
checkSpellcheck();
|
||||
|
||||
//workaround spellcheck might not activate beacuse the ajax loading
|
||||
if (num_loaded < 2) {
|
||||
var spellcheckTimer = setInterval(function () {
|
||||
if (num_loaded >= 2) {
|
||||
if (editor.getOption('mode') == "spell-checker")
|
||||
editor.setOption('mode', "spell-checker");
|
||||
clearInterval(spellcheckTimer);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
var jumpToAddressBarKeymapName = mac ? "Cmd-L" : "Ctrl-L";
|
||||
var jumpToAddressBarKeymapValue = null;
|
||||
function resetEditorKeymapToBrowserKeymap() {
|
||||
var keymap = editor.getOption('keyMap');
|
||||
if (!jumpToAddressBarKeymapValue) {
|
||||
jumpToAddressBarKeymapValue = CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName];
|
||||
delete CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName];
|
||||
}
|
||||
}
|
||||
function restoreOverrideEditorKeymap() {
|
||||
var keymap = editor.getOption('keyMap');
|
||||
if (jumpToAddressBarKeymapValue) {
|
||||
CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName] = jumpToAddressBarKeymapValue;
|
||||
jumpToAddressBarKeymapValue = null;
|
||||
}
|
||||
}
|
||||
function setOverrideBrowserKeymap() {
|
||||
var overrideBrowserKeymap = $('.ui-preferences-override-browser-keymap label > input[type="checkbox"]');
|
||||
if(overrideBrowserKeymap.is(":checked")) {
|
||||
Cookies.set('preferences-override-browser-keymap', true, {
|
||||
expires: 365
|
||||
});
|
||||
restoreOverrideEditorKeymap();
|
||||
} else {
|
||||
Cookies.remove('preferences-override-browser-keymap');
|
||||
resetEditorKeymapToBrowserKeymap();
|
||||
}
|
||||
}
|
||||
|
||||
function setPreferences() {
|
||||
var overrideBrowserKeymap = $('.ui-preferences-override-browser-keymap label > input[type="checkbox"]');
|
||||
var cookieOverrideBrowserKeymap = Cookies.get('preferences-override-browser-keymap');
|
||||
if (cookieOverrideBrowserKeymap && cookieOverrideBrowserKeymap === "true") {
|
||||
overrideBrowserKeymap.prop('checked', true);
|
||||
} else {
|
||||
overrideBrowserKeymap.prop('checked', false);
|
||||
}
|
||||
setOverrideBrowserKeymap();
|
||||
|
||||
overrideBrowserKeymap.change(function() {
|
||||
setOverrideBrowserKeymap();
|
||||
});
|
||||
}
|
||||
|
||||
var selection = null;
|
||||
|
||||
function updateStatusBar() {
|
||||
if (!statusBar) return;
|
||||
if (!editorInstance.statusBar) return;
|
||||
var cursor = editor.getCursor();
|
||||
var cursorText = 'Line ' + (cursor.line + 1) + ', Columns ' + (cursor.ch + 1);
|
||||
if (selection) {
|
||||
|
@ -800,102 +339,25 @@ function updateStatusBar() {
|
|||
if (start.line !== end.line || selectionCharCount > 0)
|
||||
cursorText += selectionText;
|
||||
}
|
||||
statusCursor.text(cursorText);
|
||||
editorInstance.statusCursor.text(cursorText);
|
||||
var fileText = ' — ' + editor.lineCount() + ' Lines';
|
||||
statusFile.text(fileText);
|
||||
editorInstance.statusFile.text(fileText);
|
||||
var docLength = editor.getValue().length;
|
||||
statusLength.text('Length ' + docLength);
|
||||
editorInstance.statusLength.text('Length ' + docLength);
|
||||
if (docLength > (docmaxlength * 0.95)) {
|
||||
statusLength.css('color', 'red');
|
||||
statusLength.attr('title', 'Your almost reach note max length limit.');
|
||||
editorInstance.statusLength.css('color', 'red');
|
||||
editorInstance.statusLength.attr('title', 'Your almost reach note max length limit.');
|
||||
} else if (docLength > (docmaxlength * 0.8)) {
|
||||
statusLength.css('color', 'orange');
|
||||
statusLength.attr('title', 'You nearly fill the note, consider to make more pieces.');
|
||||
editorInstance.statusLength.css('color', 'orange');
|
||||
editorInstance.statusLength.attr('title', 'You nearly fill the note, consider to make more pieces.');
|
||||
} else {
|
||||
statusLength.css('color', 'white');
|
||||
statusLength.attr('title', 'You could write up to ' + docmaxlength + ' characters in this note.');
|
||||
editorInstance.statusLength.css('color', 'white');
|
||||
editorInstance.statusLength.attr('title', 'You could write up to ' + docmaxlength + ' characters in this note.');
|
||||
}
|
||||
}
|
||||
|
||||
//ui vars
|
||||
window.ui = {
|
||||
spinner: $(".ui-spinner"),
|
||||
content: $(".ui-content"),
|
||||
toolbar: {
|
||||
shortStatus: $(".ui-short-status"),
|
||||
status: $(".ui-status"),
|
||||
new: $(".ui-new"),
|
||||
publish: $(".ui-publish"),
|
||||
extra: {
|
||||
revision: $(".ui-extra-revision"),
|
||||
slide: $(".ui-extra-slide")
|
||||
},
|
||||
download: {
|
||||
markdown: $(".ui-download-markdown"),
|
||||
html: $(".ui-download-html"),
|
||||
rawhtml: $(".ui-download-raw-html"),
|
||||
pdf: $(".ui-download-pdf-beta"),
|
||||
},
|
||||
export: {
|
||||
dropbox: $(".ui-save-dropbox"),
|
||||
googleDrive: $(".ui-save-google-drive"),
|
||||
gist: $(".ui-save-gist"),
|
||||
snippet: $(".ui-save-snippet")
|
||||
},
|
||||
import: {
|
||||
dropbox: $(".ui-import-dropbox"),
|
||||
googleDrive: $(".ui-import-google-drive"),
|
||||
gist: $(".ui-import-gist"),
|
||||
snippet: $(".ui-import-snippet"),
|
||||
clipboard: $(".ui-import-clipboard")
|
||||
},
|
||||
mode: $(".ui-mode"),
|
||||
edit: $(".ui-edit"),
|
||||
view: $(".ui-view"),
|
||||
both: $(".ui-both"),
|
||||
uploadImage: $(".ui-upload-image")
|
||||
},
|
||||
infobar: {
|
||||
lastchange: $(".ui-lastchange"),
|
||||
lastchangeuser: $(".ui-lastchangeuser"),
|
||||
nolastchangeuser: $(".ui-no-lastchangeuser"),
|
||||
permission: {
|
||||
permission: $(".ui-permission"),
|
||||
label: $(".ui-permission-label"),
|
||||
freely: $(".ui-permission-freely"),
|
||||
editable: $(".ui-permission-editable"),
|
||||
locked: $(".ui-permission-locked"),
|
||||
private: $(".ui-permission-private"),
|
||||
limited: $(".ui-permission-limited"),
|
||||
protected: $(".ui-permission-protected")
|
||||
},
|
||||
delete: $(".ui-delete-note")
|
||||
},
|
||||
toc: {
|
||||
toc: $('.ui-toc'),
|
||||
affix: $('.ui-affix-toc'),
|
||||
label: $('.ui-toc-label'),
|
||||
dropdown: $('.ui-toc-dropdown')
|
||||
},
|
||||
area: {
|
||||
edit: $(".ui-edit-area"),
|
||||
view: $(".ui-view-area"),
|
||||
codemirror: $(".ui-edit-area .CodeMirror"),
|
||||
codemirrorScroll: $(".ui-edit-area .CodeMirror .CodeMirror-scroll"),
|
||||
codemirrorSizer: $(".ui-edit-area .CodeMirror .CodeMirror-sizer"),
|
||||
codemirrorSizerInner: $(".ui-edit-area .CodeMirror .CodeMirror-sizer > div"),
|
||||
markdown: $(".ui-view-area .markdown-body"),
|
||||
resize: {
|
||||
handle: $('.ui-resizable-handle'),
|
||||
syncToggle: $('.ui-sync-toggle')
|
||||
}
|
||||
},
|
||||
modal: {
|
||||
snippetImportProjects: $("#snippetImportModalProjects"),
|
||||
snippetImportSnippets: $("#snippetImportModalSnippets"),
|
||||
revision: $("#revisionModal")
|
||||
}
|
||||
};
|
||||
// initalize ui reference
|
||||
const ui = getUIElements();
|
||||
|
||||
//page actions
|
||||
var opts = {
|
||||
|
@ -1146,7 +608,7 @@ var lastEditorWidth = 0;
|
|||
var previousFocusOnEditor = null;
|
||||
|
||||
function checkEditorStyle() {
|
||||
var desireHeight = statusBar ? (ui.area.edit.height() - statusBar.outerHeight()) : ui.area.edit.height();
|
||||
var desireHeight = editorInstance.statusBar ? (ui.area.edit.height() - editorInstance.statusBar.outerHeight()) : ui.area.edit.height();
|
||||
// set editor height and min height based on scrollbar style and mode
|
||||
var scrollbarStyle = editor.getOption('scrollbarStyle');
|
||||
if (scrollbarStyle == 'overlay' || currentMode == modeType.both) {
|
||||
|
@ -1381,8 +843,8 @@ function changeMode(type) {
|
|||
if (currentMode == modeType.edit || currentMode == modeType.both) {
|
||||
ui.toolbar.uploadImage.fadeIn();
|
||||
//add and update status bar
|
||||
if (!statusBar) {
|
||||
addStatusBar();
|
||||
if (!editorInstance.statusBar) {
|
||||
editorInstance.addStatusBar();
|
||||
updateStatusBar();
|
||||
}
|
||||
//work around foldGutter might not init properly
|
||||
|
@ -4069,6 +3531,6 @@ $(editor.getInputField())
|
|||
},
|
||||
'textComplete:hide': function (e) {
|
||||
$(this).data('autocompleting', false);
|
||||
editor.setOption("extraKeys", defaultExtraKeys);
|
||||
editor.setOption("extraKeys", editorInstance.defaultExtraKeys);
|
||||
}
|
||||
});
|
||||
|
|
459
public/js/lib/editor/index.js
Normal file
459
public/js/lib/editor/index.js
Normal file
|
@ -0,0 +1,459 @@
|
|||
import * as utils from './utils';
|
||||
|
||||
/* config section */
|
||||
const isMac = CodeMirror.keyMap.default === CodeMirror.keyMap.macDefault;
|
||||
const defaultEditorMode = 'gfm';
|
||||
const viewportMargin = 20;
|
||||
|
||||
const jumpToAddressBarKeymapName = isMac ? "Cmd-L" : "Ctrl-L";
|
||||
|
||||
export default class Editor {
|
||||
constructor() {
|
||||
this.editor = null;
|
||||
|
||||
this.defaultExtraKeys = {
|
||||
"F10": function (cm) {
|
||||
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
|
||||
},
|
||||
"Esc": function (cm) {
|
||||
if (cm.getOption('keyMap').substr(0, 3) === 'vim') return CodeMirror.Pass;
|
||||
else if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
|
||||
},
|
||||
"Cmd-S": function () {
|
||||
return false;
|
||||
},
|
||||
"Ctrl-S": function () {
|
||||
return false;
|
||||
},
|
||||
"Enter": "newlineAndIndentContinueMarkdownList",
|
||||
"Tab": function (cm) {
|
||||
var tab = '\t';
|
||||
|
||||
// contruct x length spaces
|
||||
var spaces = Array(parseInt(cm.getOption("indentUnit")) + 1).join(" ");
|
||||
|
||||
//auto indent whole line when in list or blockquote
|
||||
var cursor = cm.getCursor();
|
||||
var line = cm.getLine(cursor.line);
|
||||
|
||||
// this regex match the following patterns
|
||||
// 1. blockquote starts with "> " or ">>"
|
||||
// 2. unorder list starts with *+-
|
||||
// 3. order list starts with "1." or "1)"
|
||||
var regex = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))/;
|
||||
|
||||
var match;
|
||||
var multiple = cm.getSelection().split('\n').length > 1 || cm.getSelections().length > 1;
|
||||
|
||||
if (multiple) {
|
||||
cm.execCommand('defaultTab');
|
||||
} else if ((match = regex.exec(line)) !== null) {
|
||||
var ch = match[1].length;
|
||||
var pos = {
|
||||
line: cursor.line,
|
||||
ch: ch
|
||||
};
|
||||
if (cm.getOption('indentWithTabs'))
|
||||
cm.replaceRange(tab, pos, pos, '+input');
|
||||
else
|
||||
cm.replaceRange(spaces, pos, pos, '+input');
|
||||
} else {
|
||||
if (cm.getOption('indentWithTabs'))
|
||||
cm.execCommand('defaultTab');
|
||||
else {
|
||||
cm.replaceSelection(spaces);
|
||||
}
|
||||
}
|
||||
},
|
||||
"Cmd-Left": "goLineLeftSmart",
|
||||
"Cmd-Right": "goLineRight",
|
||||
"Ctrl-C": function (cm) {
|
||||
if (!isMac && cm.getOption('keyMap').substr(0, 3) === 'vim') {
|
||||
document.execCommand("copy");
|
||||
} else {
|
||||
return CodeMirror.Pass;
|
||||
}
|
||||
},
|
||||
"Ctrl-*": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '*');
|
||||
},
|
||||
"Shift-Ctrl-8": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '*');
|
||||
},
|
||||
"Ctrl-_": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '_');
|
||||
},
|
||||
"Shift-Ctrl--": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '_');
|
||||
},
|
||||
"Ctrl-~": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '~');
|
||||
},
|
||||
"Shift-Ctrl-`": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '~');
|
||||
},
|
||||
"Ctrl-^": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '^');
|
||||
},
|
||||
"Shift-Ctrl-6": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '^');
|
||||
},
|
||||
"Ctrl-+": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '+');
|
||||
},
|
||||
"Shift-Ctrl-=": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '+');
|
||||
},
|
||||
"Ctrl-=": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, '=');
|
||||
},
|
||||
"Shift-Ctrl-Backspace": (cm) => {
|
||||
utils.wrapTextWith(this.editor, cm, 'Backspace');
|
||||
}
|
||||
};
|
||||
|
||||
this.jumpToAddressBarKeymapValue = null;
|
||||
}
|
||||
|
||||
getStatusBarTemplate(callback) {
|
||||
$.get(window.serverurl + '/views/statusbar.html', (template) => {
|
||||
this.statusBarTemplate = template;
|
||||
if (callback) callback();
|
||||
});
|
||||
}
|
||||
|
||||
addStatusBar() {
|
||||
if (!this.statusBarTemplate) {
|
||||
this.getStatusBarTemplate(this.addStatusBar);
|
||||
return;
|
||||
}
|
||||
this.statusBar = $(this.statusBarTemplate);
|
||||
this.statusCursor = this.statusBar.find('.status-cursor');
|
||||
this.statusFile = this.statusBar.find('.status-file');
|
||||
this.statusIndicators = this.statusBar.find('.status-indicators');
|
||||
this.statusIndent = this.statusBar.find('.status-indent');
|
||||
this.statusKeymap = this.statusBar.find('.status-keymap');
|
||||
this.statusLength = this.statusBar.find('.status-length');
|
||||
this.statusTheme = this.statusBar.find('.status-theme');
|
||||
this.statusSpellcheck = this.statusBar.find('.status-spellcheck');
|
||||
this.statusPreferences = this.statusBar.find('.status-preferences');
|
||||
this.statusPanel = this.editor.addPanel(this.statusBar[0], {
|
||||
position: "bottom"
|
||||
});
|
||||
|
||||
this.setIndent();
|
||||
this.setKeymap();
|
||||
this.setTheme();
|
||||
this.setSpellcheck();
|
||||
this.setPreferences();
|
||||
}
|
||||
|
||||
setIndent() {
|
||||
var cookieIndentType = Cookies.get('indent_type');
|
||||
var cookieTabSize = parseInt(Cookies.get('tab_size'));
|
||||
var cookieSpaceUnits = parseInt(Cookies.get('space_units'));
|
||||
if (cookieIndentType) {
|
||||
if (cookieIndentType == 'tab') {
|
||||
this.editor.setOption('indentWithTabs', true);
|
||||
if (cookieTabSize)
|
||||
this.editor.setOption('indentUnit', cookieTabSize);
|
||||
} else if (cookieIndentType == 'space') {
|
||||
this.editor.setOption('indentWithTabs', false);
|
||||
if (cookieSpaceUnits)
|
||||
this.editor.setOption('indentUnit', cookieSpaceUnits);
|
||||
}
|
||||
}
|
||||
if (cookieTabSize)
|
||||
this.editor.setOption('tabSize', cookieTabSize);
|
||||
|
||||
var type = this.statusIndicators.find('.indent-type');
|
||||
var widthLabel = this.statusIndicators.find('.indent-width-label');
|
||||
var widthInput = this.statusIndicators.find('.indent-width-input');
|
||||
|
||||
const setType = () => {
|
||||
if (this.editor.getOption('indentWithTabs')) {
|
||||
Cookies.set('indent_type', 'tab', {
|
||||
expires: 365
|
||||
});
|
||||
type.text('Tab Size:');
|
||||
} else {
|
||||
Cookies.set('indent_type', 'space', {
|
||||
expires: 365
|
||||
});
|
||||
type.text('Spaces:');
|
||||
}
|
||||
}
|
||||
setType();
|
||||
|
||||
const setUnit = () => {
|
||||
var unit = this.editor.getOption('indentUnit');
|
||||
if (this.editor.getOption('indentWithTabs')) {
|
||||
Cookies.set('tab_size', unit, {
|
||||
expires: 365
|
||||
});
|
||||
} else {
|
||||
Cookies.set('space_units', unit, {
|
||||
expires: 365
|
||||
});
|
||||
}
|
||||
widthLabel.text(unit);
|
||||
}
|
||||
setUnit();
|
||||
|
||||
type.click(() => {
|
||||
if (this.editor.getOption('indentWithTabs')) {
|
||||
this.editor.setOption('indentWithTabs', false);
|
||||
cookieSpaceUnits = parseInt(Cookies.get('space_units'));
|
||||
if (cookieSpaceUnits)
|
||||
this.editor.setOption('indentUnit', cookieSpaceUnits)
|
||||
} else {
|
||||
this.editor.setOption('indentWithTabs', true);
|
||||
cookieTabSize = parseInt(Cookies.get('tab_size'));
|
||||
if (cookieTabSize) {
|
||||
this.editor.setOption('indentUnit', cookieTabSize);
|
||||
this.editor.setOption('tabSize', cookieTabSize);
|
||||
}
|
||||
}
|
||||
setType();
|
||||
setUnit();
|
||||
});
|
||||
widthLabel.click(() => {
|
||||
if (widthLabel.is(':visible')) {
|
||||
widthLabel.addClass('hidden');
|
||||
widthInput.removeClass('hidden');
|
||||
widthInput.val(this.editor.getOption('indentUnit'));
|
||||
widthInput.select();
|
||||
} else {
|
||||
widthLabel.removeClass('hidden');
|
||||
widthInput.addClass('hidden');
|
||||
}
|
||||
});
|
||||
widthInput.on('change', () => {
|
||||
var val = parseInt(widthInput.val());
|
||||
if (!val) val = this.editor.getOption('indentUnit');
|
||||
if (val < 1) val = 1;
|
||||
else if (val > 10) val = 10;
|
||||
|
||||
if (this.editor.getOption('indentWithTabs')) {
|
||||
this.editor.setOption('tabSize', val);
|
||||
}
|
||||
this.editor.setOption('indentUnit', val);
|
||||
setUnit();
|
||||
});
|
||||
widthInput.on('blur', function () {
|
||||
widthLabel.removeClass('hidden');
|
||||
widthInput.addClass('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
setKeymap() {
|
||||
var cookieKeymap = Cookies.get('keymap');
|
||||
if (cookieKeymap)
|
||||
this.editor.setOption('keyMap', cookieKeymap);
|
||||
|
||||
var label = this.statusIndicators.find('.ui-keymap-label');
|
||||
var sublime = this.statusIndicators.find('.ui-keymap-sublime');
|
||||
var emacs = this.statusIndicators.find('.ui-keymap-emacs');
|
||||
var vim = this.statusIndicators.find('.ui-keymap-vim');
|
||||
|
||||
const setKeymapLabel = () => {
|
||||
var keymap = this.editor.getOption('keyMap');
|
||||
Cookies.set('keymap', keymap, {
|
||||
expires: 365
|
||||
});
|
||||
label.text(keymap);
|
||||
this.restoreOverrideEditorKeymap();
|
||||
this.setOverrideBrowserKeymap();
|
||||
}
|
||||
setKeymapLabel();
|
||||
|
||||
sublime.click(() => {
|
||||
this.editor.setOption('keyMap', 'sublime');
|
||||
setKeymapLabel();
|
||||
});
|
||||
emacs.click(() => {
|
||||
this.editor.setOption('keyMap', 'emacs');
|
||||
setKeymapLabel();
|
||||
});
|
||||
vim.click(() => {
|
||||
this.editor.setOption('keyMap', 'vim');
|
||||
setKeymapLabel();
|
||||
});
|
||||
}
|
||||
|
||||
setTheme() {
|
||||
var cookieTheme = Cookies.get('theme');
|
||||
if (cookieTheme) {
|
||||
this.editor.setOption('theme', cookieTheme);
|
||||
}
|
||||
|
||||
var themeToggle = this.statusTheme.find('.ui-theme-toggle');
|
||||
|
||||
const checkTheme = () => {
|
||||
var theme = this.editor.getOption('theme');
|
||||
if (theme == "one-dark") {
|
||||
themeToggle.removeClass('active');
|
||||
} else {
|
||||
themeToggle.addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
themeToggle.click(() => {
|
||||
var theme = this.editor.getOption('theme');
|
||||
if (theme == "one-dark") {
|
||||
theme = "default";
|
||||
} else {
|
||||
theme = "one-dark";
|
||||
}
|
||||
this.editor.setOption('theme', theme);
|
||||
Cookies.set('theme', theme, {
|
||||
expires: 365
|
||||
});
|
||||
|
||||
checkTheme();
|
||||
});
|
||||
|
||||
checkTheme();
|
||||
}
|
||||
|
||||
setSpellcheck() {
|
||||
var cookieSpellcheck = Cookies.get('spellcheck');
|
||||
if (cookieSpellcheck) {
|
||||
var mode = null;
|
||||
if (cookieSpellcheck === 'true' || cookieSpellcheck === true) {
|
||||
mode = 'spell-checker';
|
||||
} else {
|
||||
mode = defaultEditorMode;
|
||||
}
|
||||
if (mode && mode !== this.editor.getOption('mode')) {
|
||||
this.editor.setOption('mode', mode);
|
||||
}
|
||||
}
|
||||
|
||||
var spellcheckToggle = this.statusSpellcheck.find('.ui-spellcheck-toggle');
|
||||
|
||||
const checkSpellcheck = () => {
|
||||
var mode = this.editor.getOption('mode');
|
||||
if (mode == defaultEditorMode) {
|
||||
spellcheckToggle.removeClass('active');
|
||||
} else {
|
||||
spellcheckToggle.addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
spellcheckToggle.click(() => {
|
||||
var mode = this.editor.getOption('mode');
|
||||
if (mode == defaultEditorMode) {
|
||||
mode = "spell-checker";
|
||||
} else {
|
||||
mode = defaultEditorMode;
|
||||
}
|
||||
if (mode && mode !== this.editor.getOption('mode')) {
|
||||
this.editor.setOption('mode', mode);
|
||||
}
|
||||
Cookies.set('spellcheck', (mode == "spell-checker"), {
|
||||
expires: 365
|
||||
});
|
||||
|
||||
checkSpellcheck();
|
||||
});
|
||||
|
||||
checkSpellcheck();
|
||||
|
||||
//workaround spellcheck might not activate beacuse the ajax loading
|
||||
if (window.num_loaded < 2) {
|
||||
var spellcheckTimer = setInterval(() => {
|
||||
if (window.num_loaded >= 2) {
|
||||
if (this.editor.getOption('mode') == "spell-checker") {
|
||||
this.editor.setOption('mode', "spell-checker");
|
||||
}
|
||||
clearInterval(spellcheckTimer);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
resetEditorKeymapToBrowserKeymap() {
|
||||
var keymap = this.editor.getOption('keyMap');
|
||||
if (!this.jumpToAddressBarKeymapValue) {
|
||||
this.jumpToAddressBarKeymapValue = CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName];
|
||||
delete CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName];
|
||||
}
|
||||
}
|
||||
|
||||
restoreOverrideEditorKeymap() {
|
||||
var keymap = this.editor.getOption('keyMap');
|
||||
if (this.jumpToAddressBarKeymapValue) {
|
||||
CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName] = this.jumpToAddressBarKeymapValue;
|
||||
this.jumpToAddressBarKeymapValue = null;
|
||||
}
|
||||
}
|
||||
setOverrideBrowserKeymap() {
|
||||
var overrideBrowserKeymap = $('.ui-preferences-override-browser-keymap label > input[type="checkbox"]');
|
||||
if (overrideBrowserKeymap.is(":checked")) {
|
||||
Cookies.set('preferences-override-browser-keymap', true, {
|
||||
expires: 365
|
||||
});
|
||||
this.restoreOverrideEditorKeymap();
|
||||
} else {
|
||||
Cookies.remove('preferences-override-browser-keymap');
|
||||
this.resetEditorKeymapToBrowserKeymap();
|
||||
}
|
||||
}
|
||||
|
||||
setPreferences() {
|
||||
var overrideBrowserKeymap = $('.ui-preferences-override-browser-keymap label > input[type="checkbox"]');
|
||||
var cookieOverrideBrowserKeymap = Cookies.get('preferences-override-browser-keymap');
|
||||
if (cookieOverrideBrowserKeymap && cookieOverrideBrowserKeymap === "true") {
|
||||
overrideBrowserKeymap.prop('checked', true);
|
||||
} else {
|
||||
overrideBrowserKeymap.prop('checked', false);
|
||||
}
|
||||
this.setOverrideBrowserKeymap();
|
||||
|
||||
overrideBrowserKeymap.change(() => {
|
||||
this.setOverrideBrowserKeymap();
|
||||
});
|
||||
}
|
||||
|
||||
init(textit) {
|
||||
this.editor = CodeMirror.fromTextArea(textit, {
|
||||
mode: defaultEditorMode,
|
||||
backdrop: defaultEditorMode,
|
||||
keyMap: "sublime",
|
||||
viewportMargin: viewportMargin,
|
||||
styleActiveLine: true,
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
showCursorWhenSelecting: true,
|
||||
highlightSelectionMatches: true,
|
||||
indentUnit: 4,
|
||||
continueComments: "Enter",
|
||||
theme: "one-dark",
|
||||
inputStyle: "textarea",
|
||||
matchBrackets: true,
|
||||
autoCloseBrackets: true,
|
||||
matchTags: {
|
||||
bothTags: true
|
||||
},
|
||||
autoCloseTags: true,
|
||||
foldGutter: true,
|
||||
gutters: ["CodeMirror-linenumbers", "authorship-gutters", "CodeMirror-foldgutter"],
|
||||
extraKeys: this.defaultExtraKeys,
|
||||
flattenSpans: true,
|
||||
addModeClass: true,
|
||||
readOnly: true,
|
||||
autoRefresh: true,
|
||||
otherCursors: true,
|
||||
placeholder: "← Start by entering a title here\n===\nVisit /features if you don't know what to do.\nHappy hacking :)"
|
||||
});
|
||||
|
||||
this.getStatusBarTemplate();
|
||||
|
||||
return this.editor;
|
||||
}
|
||||
|
||||
getEditor() {
|
||||
return this.editor;
|
||||
}
|
||||
}
|
46
public/js/lib/editor/utils.js
Normal file
46
public/js/lib/editor/utils.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
const wrapSymbols = ['*', '_', '~', '^', '+', '='];
|
||||
export function wrapTextWith(editor, cm, symbol) {
|
||||
if (!cm.getSelection()) {
|
||||
return CodeMirror.Pass;
|
||||
} else {
|
||||
var ranges = cm.listSelections();
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var range = ranges[i];
|
||||
if (!range.empty()) {
|
||||
var from = range.from(), to = range.to();
|
||||
if (symbol !== 'Backspace') {
|
||||
cm.replaceRange(symbol, to, to, '+input');
|
||||
cm.replaceRange(symbol, from, from, '+input');
|
||||
// workaround selection range not correct after add symbol
|
||||
var _ranges = cm.listSelections();
|
||||
var anchorIndex = editor.indexFromPos(_ranges[i].anchor);
|
||||
var headIndex = editor.indexFromPos(_ranges[i].head);
|
||||
if (anchorIndex > headIndex) {
|
||||
_ranges[i].anchor.ch--;
|
||||
} else {
|
||||
_ranges[i].head.ch--;
|
||||
}
|
||||
cm.setSelections(_ranges);
|
||||
} else {
|
||||
var preEndPos = {
|
||||
line: to.line,
|
||||
ch: to.ch + 1
|
||||
};
|
||||
var preText = cm.getRange(to, preEndPos);
|
||||
var preIndex = wrapSymbols.indexOf(preText);
|
||||
var postEndPos = {
|
||||
line: from.line,
|
||||
ch: from.ch - 1
|
||||
};
|
||||
var postText = cm.getRange(postEndPos, from);
|
||||
var postIndex = wrapSymbols.indexOf(postText);
|
||||
// check if surround symbol are list in array and matched
|
||||
if (preIndex > -1 && postIndex > -1 && preIndex === postIndex) {
|
||||
cm.replaceRange("", to, preEndPos, '+delete');
|
||||
cm.replaceRange("", postEndPos, from, '+delete');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue