summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js.es634
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb43
2 files changed, 76 insertions, 1 deletions
diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6
index 5d9ac4d350a..89fe13b7a45 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.es6
+++ b/app/assets/javascripts/gfm_auto_complete.js.es6
@@ -53,6 +53,26 @@
} else {
return value;
}
+ },
+ matcher: function (flag, subtext) {
+ // The below is taken from At.js source
+ // Tweaked to commands to start without a space only if char before is a non-word character
+ // https://github.com/ichord/At.js
+ var _a, _y, regexp, match;
+ flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+
+ _a = decodeURI("%C3%80");
+ _y = decodeURI("%C3%BF");
+
+ regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)|([^\\x00-\\xff]*)$", 'gi');
+
+ match = regexp.exec(subtext);
+
+ if (match) {
+ return match[2] || match[1];
+ } else {
+ return null;
+ }
}
},
setup: _.debounce(function(input) {
@@ -91,10 +111,12 @@
})(this),
insertTpl: ':${name}:',
data: ['loading'],
+ startWithSpace: false,
callbacks: {
sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter,
- beforeInsert: this.DefaultOptions.beforeInsert
+ beforeInsert: this.DefaultOptions.beforeInsert,
+ matcher: this.DefaultOptions.matcher
}
});
// Team Members
@@ -112,11 +134,13 @@
insertTpl: '${atwho-at}${username}',
searchKey: 'search',
data: ['loading'],
+ startWithSpace: false,
alwaysHighlightFirst: true,
callbacks: {
sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter,
beforeInsert: this.DefaultOptions.beforeInsert,
+ matcher: this.DefaultOptions.matcher,
beforeSave: function(members) {
return $.map(members, function(m) {
let title = '';
@@ -157,10 +181,12 @@
})(this),
data: ['loading'],
insertTpl: '${atwho-at}${id}',
+ startWithSpace: false,
callbacks: {
sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter,
beforeInsert: this.DefaultOptions.beforeInsert,
+ matcher: this.DefaultOptions.matcher,
beforeSave: function(issues) {
return $.map(issues, function(i) {
if (i.title == null) {
@@ -190,7 +216,9 @@
})(this),
insertTpl: '${atwho-at}"${title}"',
data: ['loading'],
+ startWithSpace: false,
callbacks: {
+ matcher: this.DefaultOptions.matcher,
sorter: this.DefaultOptions.sorter,
beforeSave: function(milestones) {
return $.map(milestones, function(m) {
@@ -220,11 +248,13 @@
};
})(this),
data: ['loading'],
+ startWithSpace: false,
insertTpl: '${atwho-at}${id}',
callbacks: {
sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter,
beforeInsert: this.DefaultOptions.beforeInsert,
+ matcher: this.DefaultOptions.matcher,
beforeSave: function(merges) {
return $.map(merges, function(m) {
if (m.title == null) {
@@ -245,7 +275,9 @@
searchKey: 'search',
displayTpl: this.Labels.template,
insertTpl: '${atwho-at}${title}',
+ startWithSpace: false,
callbacks: {
+ matcher: this.DefaultOptions.matcher,
sorter: this.DefaultOptions.sorter,
beforeSave: function(merges) {
var sanitizeLabelTitle;
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
new file mode 100644
index 00000000000..c421da97d76
--- /dev/null
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -0,0 +1,43 @@
+require 'rails_helper'
+
+feature 'GFM autocomplete', feature: true, js: true do
+ include WaitForAjax
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:issue) { create(:issue, project: project) }
+
+ before do
+ project.team << [user, :master]
+ login_as(user)
+ visit namespace_project_issue_path(project.namespace, project, issue)
+
+ wait_for_ajax
+ end
+
+ it 'opens autocomplete menu when field starts with text' do
+ page.within '.timeline-content-form' do
+ find('#note_note').native.send_keys('')
+ find('#note_note').native.send_keys('@')
+ end
+
+ expect(page).to have_selector('.atwho-container')
+ end
+
+ it 'opens autocomplete menu when field is prefixed with non-text character' do
+ page.within '.timeline-content-form' do
+ find('#note_note').native.send_keys('')
+ find('#note_note').native.send_keys('@')
+ end
+
+ expect(page).to have_selector('.atwho-container')
+ end
+
+ it 'doesnt open autocomplete menu character is prefixed with text' do
+ page.within '.timeline-content-form' do
+ find('#note_note').native.send_keys('testing')
+ find('#note_note').native.send_keys('@')
+ end
+
+ expect(page).not_to have_selector('.atwho-view')
+ end
+end