summaryrefslogtreecommitdiff
path: root/public/js/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/js/index.js')
-rw-r--r--public/js/index.js541
1 files changed, 444 insertions, 97 deletions
diff --git a/public/js/index.js b/public/js/index.js
index 24b38f75..5f7e6992 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -1,16 +1,21 @@
//constant vars
//settings
var debug = false;
-var version = '0.2.9';
+var version = '0.3.1';
var defaultTextHeight = 18;
var viewportMargin = 20;
var defaultExtraKeys = {
+ "Cmd-S": function () {
+ return CodeMirror.PASS
+ },
+ "Ctrl-S": function () {
+ return CodeMirror.PASS
+ },
"Enter": "newlineAndIndentContinueMarkdownList"
};
var idleTime = 300000; //5 mins
-var doneTypingDelay = 400;
var finishChangeDelay = 400;
var cursorActivityDelay = 50;
var cursorAnimatePeriod = 100;
@@ -97,12 +102,27 @@ var supportExternals = [
search: 'gist'
}
];
-var supportGenerals = [
+var supportBlockquoteTags = [
+ {
+ text: '[name tag]',
+ search: '[]',
+ command: function () {
+ return '[name=' + personalInfo.name + ']';
+ },
+ },
{
+ text: '[time tag]',
+ search: '[]',
command: function () {
- return moment().format('llll');
+ return '[time=' + moment().format('llll') + ']';
},
- search: 'time'
+ },
+ {
+ text: '[color tag]',
+ search: '[]',
+ command: function () {
+ return '[color=' + personalInfo.color + ']';
+ }
}
];
var modeType = {
@@ -131,6 +151,7 @@ var defaultMode = modeType.both;
//global vars
var loaded = false;
+var needRefresh = false;
var isDirty = false;
var editShown = false;
var visibleXS = false;
@@ -192,7 +213,7 @@ var editor = CodeMirror.fromTextArea(textit, {
extraKeys: defaultExtraKeys,
readOnly: true
});
-inlineAttachment.editors.codemirror4.attach(editor);
+var inlineAttach = inlineAttachment.editors.codemirror4.attach(editor);
defaultTextHeight = parseInt($(".CodeMirror").css('line-height'));
//ui vars
@@ -203,7 +224,7 @@ var ui = {
shortStatus: $(".ui-short-status"),
status: $(".ui-status"),
new: $(".ui-new"),
- pretty: $(".ui-pretty"),
+ share: $(".ui-share"),
download: {
markdown: $(".ui-download-markdown")
},
@@ -217,7 +238,24 @@ var ui = {
mode: $(".ui-mode"),
edit: $(".ui-edit"),
view: $(".ui-view"),
- both: $(".ui-both")
+ both: $(".ui-both"),
+ uploadImage: $(".ui-upload-image")
+ },
+ infobar: {
+ lastchange: $(".ui-lastchange"),
+ permission: {
+ permission: $(".ui-permission"),
+ label: $(".ui-permission-label"),
+ freely: $(".ui-permission-freely"),
+ editable: $(".ui-permission-editable"),
+ locked: $(".ui-permission-locked")
+ }
+ },
+ toc: {
+ toc: $('.ui-toc'),
+ affix: $('.ui-affix-toc'),
+ label: $('.ui-toc-label'),
+ dropdown: $('.ui-toc-dropdown')
},
area: {
edit: $(".ui-edit-area"),
@@ -263,10 +301,16 @@ function idleStateChange() {
updateOnlineStatus();
}
-loginStateChangeEvent = function () {
- location.reload(true);
+function setNeedRefresh() {
+ $('#refreshModal').modal('show');
+ needRefresh = true;
+ editor.setOption('readOnly', true);
+ socket.disconnect();
+ showStatus(statusType.offline);
}
+loginStateChangeEvent = setNeedRefresh;
+
//visibility
var wasFocus = false;
Visibility.change(function (e, state) {
@@ -315,6 +359,11 @@ $(document).ready(function () {
$body.removeClass('fixfixed');
});
}
+ //showup
+ $().showUp('.navbar', {
+ upClass: 'navbar-hide',
+ downClass: 'navbar-show'
+ });
});
//when page resize
var windowResizeDelay = 200;
@@ -327,12 +376,38 @@ $(window).resize(function () {
});
//when page unload
$(window).unload(function () {
- emitRefresh();
+ emitUpdate();
});
+//when page hash change
+window.onhashchange = locationHashChanged;
+
+function locationHashChanged(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ if (currentMode != modeType.both) {
+ return;
+ }
+ var hashtarget = $("[id$='" + location.hash.substr(1) + "']");
+ if (hashtarget.length > 0) {
+ var linenumber = hashtarget.attr('data-startline');
+ if (linenumber) {
+ editor.setOption('viewportMargin', Infinity);
+ editor.setOption('viewportMargin', viewportMargin);
+ var t = editor.charCoords({
+ line: linenumber,
+ ch: 0
+ }, "local").top;
+ editor.scrollTo(null, t - defaultTextHeight * 1.2);
+ }
+ }
+}
+
function windowResize() {
checkResponsive();
checkEditorStyle();
+ checkTocStyle();
+ //refresh editor
if (loaded) {
editor.setOption('viewportMargin', Infinity);
setTimeout(function () {
@@ -373,6 +448,39 @@ function checkEditorStyle() {
}
}
+function checkTocStyle() {
+ //toc right
+ var paddingRight = parseFloat(ui.area.markdown.css('padding-right'));
+ var right = ($(window).width() - (ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - paddingRight));
+ ui.toc.toc.css('right', right + 'px');
+ //affix toc left
+ var newbool;
+ var rightMargin = (ui.area.markdown.parent().outerWidth() - ui.area.markdown.outerWidth()) / 2;
+ //for ipad or wider device
+ if (rightMargin >= 133) {
+ newbool = true;
+ var affixLeftMargin = (ui.toc.affix.outerWidth() - ui.toc.affix.width()) / 2;
+ var left = ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - affixLeftMargin;
+ ui.toc.affix.css('left', left + 'px');
+ } else {
+ newbool = false;
+ }
+ //toc scrollspy
+ ui.toc.toc.removeClass('scrollspy-body, scrollspy-view');
+ ui.toc.affix.removeClass('scrollspy-body, scrollspy-view');
+ if (currentMode != modeType.both && !newbool) {
+ ui.toc.toc.addClass('scrollspy-body');
+ ui.toc.affix.addClass('scrollspy-body');
+ } else {
+ ui.toc.toc.addClass('scrollspy-view');
+ ui.toc.affix.addClass('scrollspy-body');
+ }
+ if (newbool != enoughForAffixToc) {
+ enoughForAffixToc = newbool;
+ generateScrollspy();
+ }
+}
+
function showStatus(type, num) {
currentStatus = type;
var shortStatus = ui.toolbar.shortStatus;
@@ -461,12 +569,21 @@ function changeMode(type) {
}
if (currentMode != modeType.view && visibleLG) {
//editor.focus();
- editor.refresh();
+ //editor.refresh();
} else {
editor.getInputField().blur();
}
- if (changeMode != modeType.edit)
+ if (currentMode == modeType.edit || currentMode == modeType.both) {
+ ui.toolbar.uploadImage.fadeIn();
+ } else {
+ ui.toolbar.uploadImage.fadeOut();
+ }
+ if (currentMode != modeType.edit) {
+ $(document.body).css('background-color', 'white');
updateView();
+ } else {
+ $(document.body).css('background-color', ui.area.codemirror.css('background-color'));
+ }
restoreInfo();
windowResize();
@@ -489,10 +606,9 @@ function changeMode(type) {
}
//button actions
-var noteId = window.location.pathname.split('/')[1];
-var url = window.location.origin + '/' + noteId;
-//pretty
-ui.toolbar.pretty.attr("href", url + "/pretty");
+var url = window.location.pathname;
+//share
+ui.toolbar.share.attr("href", url + "/share");
//download
//markdown
ui.toolbar.download.markdown.click(function () {
@@ -534,6 +650,73 @@ ui.toolbar.import.dropbox.click(function () {
ui.toolbar.import.clipboard.click(function () {
//na
});
+//upload image
+ui.toolbar.uploadImage.bind('change', function (e) {
+ var files = e.target.files || e.dataTransfer.files;
+ e.dataTransfer = {};
+ e.dataTransfer.files = files;
+ inlineAttach.onDrop(e);
+});
+//toc
+ui.toc.dropdown.click(function (e) {
+ e.stopPropagation();
+});
+
+function scrollToTop() {
+ if (currentMode == modeType.both) {
+ if (editor.getScrollInfo().top != 0)
+ editor.scrollTo(0, 0);
+ else
+ ui.area.view.animate({
+ scrollTop: 0
+ }, 100, "linear");
+ } else {
+ $(document.body).animate({
+ scrollTop: 0
+ }, 100, "linear");
+ }
+}
+
+function scrollToBottom() {
+ if (currentMode == modeType.both) {
+ var scrollInfo = editor.getScrollInfo();
+ var scrollHeight = scrollInfo.height;
+ if (scrollInfo.top != scrollHeight)
+ editor.scrollTo(0, scrollHeight * 2);
+ else
+ ui.area.view.animate({
+ scrollTop: ui.area.view[0].scrollHeight
+ }, 100, "linear");
+ } else {
+ $(document.body).animate({
+ scrollTop: $(document.body)[0].scrollHeight
+ }, 100, "linear");
+ }
+}
+
+var enoughForAffixToc = true;
+
+//scrollspy
+function generateScrollspy() {
+ $(document.body).scrollspy({
+ target: '.scrollspy-body'
+ });
+ ui.area.view.scrollspy({
+ target: '.scrollspy-view'
+ });
+ $(document.body).scrollspy('refresh');
+ ui.area.view.scrollspy('refresh');
+ if (enoughForAffixToc) {
+ ui.toc.toc.hide();
+ ui.toc.affix.show();
+ } else {
+ ui.toc.affix.hide();
+ ui.toc.toc.show();
+ }
+ $(document.body).scroll();
+ ui.area.view.scroll();
+}
+
//fix for wrong autofocus
$('#clipboardModal').on('shown.bs.modal', function () {
$('#clipboardModal').blur();
@@ -549,6 +732,9 @@ $("#clipboardModalConfirm").click(function () {
$("#clipboardModalContent").html('');
}
});
+$('#refreshModalRefresh').click(function () {
+ location.reload(true);
+});
function parseToEditor(data) {
var parsed = toMarkdown(data);
@@ -585,19 +771,20 @@ function importFromUrl(url) {
}
function isValidURL(str) {
- var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
- '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
- '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
- '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
- '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
- '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
- if (!pattern.test(str)) {
- return false;
- } else {
- return true;
- }
+ var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
+ '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
+ '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
+ '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
+ '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
+ '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
+ if (!pattern.test(str)) {
+ return false;
+ } else {
+ return true;
}
- //mode
+}
+
+//mode
ui.toolbar.mode.click(function () {
toggleMode();
});
@@ -613,18 +800,63 @@ ui.toolbar.view.click(function () {
ui.toolbar.both.click(function () {
changeMode(modeType.both);
});
+//permission
+//freely
+ui.infobar.permission.freely.click(function () {
+ updatePermission("freely");
+});
+//editable
+ui.infobar.permission.editable.click(function () {
+ updatePermission("editable");
+});
+//locked
+ui.infobar.permission.locked.click(function () {
+ updatePermission("locked");
+});
+
+function updatePermission(_permission) {
+ if (_permission != permission) {
+ socket.emit('permission', _permission);
+ }
+}
+
+function checkPermission() {
+ var label = null;
+ var title = null;
+ switch (permission) {
+ case "freely":
+ label = '<i class="fa fa-leaf"></i> Freely';
+ title = "Anyone can edit";
+ break;
+ case "editable":
+ label = '<i class="fa fa-pencil"></i> Editable';
+ title = "Signed people can edit";
+ break;
+ case "locked":
+ label = '<i class="fa fa-lock"></i> Locked';
+ title = "Only owner can edit";
+ break;
+ }
+ if (personalInfo.userid == owner) {
+ label += ' <i class="fa fa-caret-down"></i>';
+ ui.infobar.permission.label.removeClass('disabled');
+ } else {
+ ui.infobar.permission.label.addClass('disabled');
+ }
+ ui.infobar.permission.label.html(label).attr('title', title);
+}
//socket.io actions
var socket = io.connect();
//overwrite original event for checking login state
var on = socket.on;
socket.on = function () {
- if (!checkLoginStateChanged())
+ if (!checkLoginStateChanged() && !needRefresh)
on.apply(socket, arguments);
};
var emit = socket.emit;
socket.emit = function () {
- if (!checkLoginStateChanged())
+ if (!checkLoginStateChanged() && !needRefresh)
emit.apply(socket, arguments);
};
socket.on('info', function (data) {
@@ -653,17 +885,53 @@ socket.on('connect', function (data) {
});
socket.on('version', function (data) {
if (data != version)
- location.reload(true);
+ setNeedRefresh();
+});
+socket.on('check', function (data) {
+ if (data.id == socket.id) {
+ lastchangetime = data.updatetime;
+ lastchangeui = ui.infobar.lastchange;
+ updateLastChange();
+ return;
+ }
+ var currentHash = md5(LZString.compressToUTF16(editor.getValue()));
+ var hashMismatch = (currentHash != data.hash);
+ if (hashMismatch)
+ socket.emit('refresh');
+ else {
+ lastchangetime = data.updatetime;
+ lastchangeui = ui.infobar.lastchange;
+ updateLastChange();
+ }
});
+socket.on('permission', function (data) {
+ permission = data.permission;
+ checkPermission();
+});
+var otk = null;
+var owner = null;
+var permission = null;
socket.on('refresh', function (data) {
+ var currentHash = md5(LZString.compressToUTF16(editor.getValue()));
+ var hashMismatch = (currentHash != data.hash);
saveInfo();
- var body = data.body;
- body = LZString.decompressFromUTF16(body);
- if (body)
- editor.setValue(body);
- else
- editor.setValue("");
+ otk = data.otk;
+ owner = data.owner;
+ permission = data.permission;
+
+ if (hashMismatch) {
+ var body = data.body;
+ body = LZString.decompressFromUTF16(body);
+ if (body)
+ editor.setValue(body);
+ else
+ editor.setValue("");
+ }
+
+ lastchangetime = data.updatetime;
+ lastchangeui = ui.infobar.lastchange;
+ updateLastChange();
if (!loaded) {
editor.clearHistory();
@@ -673,9 +941,19 @@ socket.on('refresh', function (data) {
loaded = true;
emitUserStatus(); //send first user status
updateOnlineStatus(); //update first online status
+ setTimeout(function () {
+ //work around editor not refresh
+ editor.refresh();
+ //work around cursor not refresh
+ for (var i = 0; i < onlineUsers.length; i++) {
+ buildCursor(onlineUsers[i]);
+ }
+ //work around might not scroll to hash
+ scrollToHash();
+ }, 1);
} else {
//if current doc is equal to the doc before disconnect
- if (LZString.compressToUTF16(editor.getValue()) !== data.body)
+ if (hashMismatch)
editor.clearHistory();
else {
if (lastInfo.history)
@@ -684,21 +962,58 @@ socket.on('refresh', function (data) {
lastInfo.history = null;
}
- updateView();
+ if (hashMismatch)
+ updateView();
if (editor.getOption('readOnly'))
editor.setOption('readOnly', false);
restoreInfo();
+ checkPermission();
});
+
+var changeStack = [];
+var changeBusy = false;
+
socket.on('change', function (data) {
data = LZString.decompressFromUTF16(data);
data = JSON.parse(data);
- editor.replaceRange(data.text, data.from, data.to, "ignoreHistory");
- isDirty = true;
- clearTimeout(finishChangeTimer);
- finishChangeTimer = setTimeout(finishChange, finishChangeDelay);
+ changeStack.push(data);
+ if (!changeBusy)
+ executeChange();
});
+
+function executeChange() {
+ if (changeStack.length > 0) {
+ changeBusy = true;
+ var data = changeStack.shift();
+ if (data.otk != otk) {
+ var found = false;
+ for (var i = 0, l = changeStack.length; i < l; i++) {
+ if (changeStack[i].otk == otk) {
+ changeStack.unshift(data);
+ data = changeStack[i];
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ socket.emit('refresh');
+ changeBusy = false;
+ return;
+ }
+ }
+ otk = data.nextotk;
+ if (data.id == personalInfo.id)
+ editor.replaceRange(data.text, data.from, data.to, 'self::' + data.origin);
+ else
+ editor.replaceRange(data.text, data.from, data.to, "ignoreHistory");
+ executeChange();
+ } else {
+ changeBusy = false;
+ }
+}
+
socket.on('online users', function (data) {
data = LZString.decompressFromUTF16(data);
data = JSON.parse(data);
@@ -795,7 +1110,7 @@ var onlineUserList = new List('online-user-list', options);
var shortOnlineUserList = new List('short-online-user-list', options);
function updateOnlineStatus() {
- if (!loaded) return;
+ if (!loaded || !socket.connected) return;
var _onlineUsers = deduplicateOnlineUsers(onlineUsers);
showStatus(statusType.online, _onlineUsers.length);
var items = onlineUserList.items;
@@ -851,7 +1166,7 @@ function sortOnlineUserList(list) {
var userbIsSelf = (userb.id == personalInfo.id || (userb.login && userb.userid == personalInfo.userid));
if (useraIsSelf && !userbIsSelf) {
return -1;
- } else if(!useraIsSelf && userbIsSelf) {
+ } else if (!useraIsSelf && userbIsSelf) {
return 1;
} else {
if (usera.login && !userb.login)
@@ -975,7 +1290,7 @@ function checkCursorTag(coord, ele) {
var offsetTop = defaultTextHeight;
if (width > 0 && height > 0) {
if (left + width + offsetLeft > editorWidth - curosrtagMargin) {
- offsetLeft = -(width + 4);
+ offsetLeft = -(width + 10);
}
if (top + height + offsetTop > Math.max(viewportHeight, editorHeight) + curosrtagMargin && top - height > curosrtagMargin) {
offsetTop = -(height);
@@ -1124,16 +1439,61 @@ function buildCursor(user) {
editor.on('beforeChange', function (cm, change) {
if (debug)
console.debug(change);
+ var self = change.origin.split('self::');
+ if (self.length == 2) {
+ change.origin = self[1];
+ self = true;
+ } else {
+ self = false;
+ }
+ if (self) {
+ change.canceled = true;
+ } else {
+ var isIgnoreEmitEvent = (ignoreEmitEvents.indexOf(change.origin) != -1);
+ if (!isIgnoreEmitEvent) {
+ switch (permission) {
+ case "freely":
+ //na
+ break;
+ case "editable":
+ if (!personalInfo.login) {
+ change.canceled = true;
+ $('.signin-modal').modal('show');
+ }
+ break;
+ case "locked":
+ if (personalInfo.userid != owner) {
+ change.canceled = true;
+ $('.locked-modal').modal('show');
+ }
+ break;
+ }
+ }
+ }
});
+
+var ignoreEmitEvents = ['setValue', 'ignoreHistory'];
editor.on('change', function (i, op) {
if (debug)
console.debug(op);
- if (op.origin != 'setValue' && op.origin != 'ignoreHistory') {
- socket.emit('change', LZString.compressToUTF16(JSON.stringify(op)));
+ var isIgnoreEmitEvent = (ignoreEmitEvents.indexOf(op.origin) != -1);
+ if (!isIgnoreEmitEvent) {
+ var out = {
+ text: op.text,
+ from: op.from,
+ to: op.to,
+ origin: op.origin
+ };
+ socket.emit('change', LZString.compressToUTF16(JSON.stringify(out)));
}
isDirty = true;
- clearTimeout(doneTypingTimer);
- doneTypingTimer = setTimeout(doneTyping, doneTypingDelay);
+ clearTimeout(finishChangeTimer);
+ finishChangeTimer = setTimeout(function () {
+ if (!isIgnoreEmitEvent)
+ finishChange(true);
+ else
+ finishChange(false);
+ }, finishChangeDelay);
});
editor.on('focus', function (cm) {
for (var i = 0; i < onlineUsers.length; i++) {
@@ -1236,22 +1596,17 @@ function restoreInfo() {
}
//view actions
-var doneTypingTimer = null;
var finishChangeTimer = null;
-var input = editor.getInputField();
-//user is "finished typing," do something
-function doneTyping() {
- emitRefresh();
- updateView();
-}
-function finishChange() {
+function finishChange(emit) {
+ if (emit)
+ emitUpdate();
updateView();
}
-function emitRefresh() {
+function emitUpdate() {
var value = editor.getValue();
- socket.emit('refresh', LZString.compressToUTF16(value));
+ socket.emit('update', LZString.compressToUTF16(value));
}
var lastResult = null;
@@ -1267,6 +1622,11 @@ function updateView() {
updateDataAttrs(result, ui.area.markdown.children().toArray());
lastResult = $(result).clone();
finishView(ui.area.view);
+ autoLinkify(ui.area.view);
+ generateToc('toc');
+ generateToc('toc-affix');
+ generateScrollspy();
+ smoothHashScroll();
writeHistory(ui.area.markdown);
isDirty = false;
clearMap();
@@ -1535,7 +1895,7 @@ $(editor.getInputField())
return '$1```' + lang + '=\n\n```';
},
done: function () {
- editor.doc.cm.moveV(-1, "line");
+ editor.doc.cm.execCommand("goLineUp");
},
context: function () {
return isInCode;
@@ -1556,12 +1916,19 @@ $(editor.getInputField())
return !isInCode;
}
},
- { //referral
- match: /(^|\n|\s)(\!|\!|\[\])(\w*)$/,
+ { //blockquote personal info & general info
+ match: /(?:^|\n|\s)(\>.*)(\[\])(\w*)$/,
search: function (term, callback) {
- callback($.map(supportReferrals, function (referral) {
- return referral.search.indexOf(term) === 0 ? referral.text : null;
- }));
+ var list = [];
+ $.map(supportBlockquoteTags, function (blockquotetag) {
+ if (blockquotetag.search.indexOf(term) === 0)
+ list.push(blockquotetag.command());
+ });
+ $.map(supportReferrals, function (referral) {
+ if (referral.search.indexOf(term) === 0)
+ list.push(referral.text);
+ })
+ callback(list);
checkCursorMenu();
},
replace: function (value) {
@@ -1571,11 +1938,11 @@ $(editor.getInputField())
return !isInCode;
}
},
- { //externals
- match: /(^|\n|\s)\{\}(\w*)$/,
+ { //referral
+ match: /(^|\n|\s)(\!|\!|\[\])(\w*)$/,
search: function (term, callback) {
- callback($.map(supportExternals, function (external) {
- return external.search.indexOf(term) === 0 ? external.text : null;
+ callback($.map(supportReferrals, function (referral) {
+ return referral.search.indexOf(term) === 0 ? referral.text : null;
}));
checkCursorMenu();
},
@@ -1586,36 +1953,16 @@ $(editor.getInputField())
return !isInCode;
}
},
- { //blockquote personal info & general info
- match: /(^|\n|\s|\>.*)\[(\w*)=$/,
- search: function (term, callback) {
- var list = typeof personalInfo[term] != 'undefined' ? [personalInfo[term]] : [];
- $.map(supportGenerals, function (general) {
- if (general.search.indexOf(term) === 0)
- list.push(general.command());
- });
- callback(list);
- checkCursorMenu();
- },
- replace: function (value) {
- return '$1[$2=' + value;
- },
- context: function (text) {
- return !isInCode;
- }
- },
- { //blockquote quick start tag
- match: /(^.*(?!>)\n|)(\>\s{0,1})$/,
+ { //externals
+ match: /(^|\n|\s)\{\}(\w*)$/,
search: function (term, callback) {
- var self = '[name=' + personalInfo.name + '] [time=' + moment().format('llll') + '] [color=' + personalInfo.color + ']';
- callback([self]);
+ callback($.map(supportExternals, function (external) {
+ return external.search.indexOf(term) === 0 ? external.text : null;
+ }));
checkCursorMenu();
},
- template: function (value) {
- return '[Your name, time, color tags]';
- },
replace: function (value) {
- return '$1$2' + value;
+ return '$1' + value;
},
context: function (text) {
return !isInCode;