mirror of
https://github.com/discourse/discourse.git
synced 2025-03-09 14:34:35 +00:00
FIX: Autocomplete incorrectly replacing text if used mid sentence.
* Adds test to document the behavior we were seeing.
This commit is contained in:
parent
232f840b60
commit
0aacd63436
@ -201,17 +201,22 @@ export default function (options) {
|
|||||||
|
|
||||||
if (term) {
|
if (term) {
|
||||||
let text = me.val();
|
let text = me.val();
|
||||||
|
|
||||||
text =
|
text =
|
||||||
text.substring(0, completeStart) +
|
text.substring(0, completeStart) +
|
||||||
(options.preserveKey ? options.key || "" : "") +
|
(options.preserveKey ? options.key || "" : "") +
|
||||||
term +
|
term +
|
||||||
" " +
|
" " +
|
||||||
text.substring(completeEnd + 1, text.length);
|
text.substring(completeEnd + 1, text.length);
|
||||||
|
|
||||||
me.val(text);
|
me.val(text);
|
||||||
|
|
||||||
let newCaretPos = completeStart + 1 + term.length;
|
let newCaretPos = completeStart + 1 + term.length;
|
||||||
|
|
||||||
if (options.key) {
|
if (options.key) {
|
||||||
newCaretPos++;
|
newCaretPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCaretPosition(me[0], newCaretPos);
|
setCaretPosition(me[0], newCaretPos);
|
||||||
|
|
||||||
if (options && options.afterComplete) {
|
if (options && options.afterComplete) {
|
||||||
@ -487,6 +492,7 @@ export default function (options) {
|
|||||||
if (options.key) {
|
if (options.key) {
|
||||||
if (options.onKeyUp && key !== options.key) {
|
if (options.onKeyUp && key !== options.key) {
|
||||||
let match = options.onKeyUp(me.val(), cp);
|
let match = options.onKeyUp(me.val(), cp);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
completeStart = cp - match[0].length;
|
completeStart = cp - match[0].length;
|
||||||
completeEnd = completeStart + match[0].length - 1;
|
completeEnd = completeStart + match[0].length - 1;
|
||||||
@ -543,26 +549,36 @@ export default function (options) {
|
|||||||
if (!options.key) {
|
if (!options.key) {
|
||||||
completeStart = 0;
|
completeStart = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.which === keys.shift) {
|
if (e.which === keys.shift) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (completeStart === null && e.which === keys.backSpace && options.key) {
|
if (completeStart === null && e.which === keys.backSpace && options.key) {
|
||||||
c = caretPosition(me[0]);
|
c = caretPosition(me[0]);
|
||||||
c -= 1;
|
c -= 1;
|
||||||
initial = c;
|
initial = c;
|
||||||
prevIsGood = true;
|
prevIsGood = true;
|
||||||
|
|
||||||
while (prevIsGood && c >= 0) {
|
while (prevIsGood && c >= 0) {
|
||||||
c -= 1;
|
c -= 1;
|
||||||
prev = me[0].value[c];
|
prev = me[0].value[c];
|
||||||
stopFound = prev === options.key;
|
stopFound = prev === options.key;
|
||||||
|
|
||||||
if (stopFound) {
|
if (stopFound) {
|
||||||
prev = me[0].value[c - 1];
|
prev = me[0].value[c - 1];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
checkTriggerRule({ backSpace: true }) &&
|
checkTriggerRule({ backSpace: true }) &&
|
||||||
(!prev || allowedLettersRegex.test(prev))
|
(!prev || allowedLettersRegex.test(prev))
|
||||||
) {
|
) {
|
||||||
completeStart = c;
|
completeStart = c;
|
||||||
term = me[0].value.substring(c + 1, initial);
|
term = me[0].value.substring(c + 1, initial);
|
||||||
|
|
||||||
|
if (!completeEnd) {
|
||||||
|
completeEnd = c + term.length;
|
||||||
|
}
|
||||||
|
|
||||||
updateAutoComplete(dataSource(term, options));
|
updateAutoComplete(dataSource(term, options));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -640,11 +656,12 @@ export default function (options) {
|
|||||||
return false;
|
return false;
|
||||||
case keys.backSpace:
|
case keys.backSpace:
|
||||||
autocompleteOptions = null;
|
autocompleteOptions = null;
|
||||||
completeEnd = cp;
|
|
||||||
cp--;
|
cp--;
|
||||||
|
completeEnd = cp;
|
||||||
|
|
||||||
if (cp < 0) {
|
if (cp < 0) {
|
||||||
closeAutocomplete();
|
closeAutocomplete();
|
||||||
|
|
||||||
if (isInput) {
|
if (isInput) {
|
||||||
i = wrap.find("a:last");
|
i = wrap.find("a:last");
|
||||||
if (i) {
|
if (i) {
|
||||||
|
@ -0,0 +1,109 @@
|
|||||||
|
import { test } from "qunit";
|
||||||
|
import { click, fillIn, triggerKeyEvent, visit } from "@ember/test-helpers";
|
||||||
|
import { acceptance, query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
|
import { setCaretPosition } from "discourse/lib/utilities";
|
||||||
|
|
||||||
|
const BACKSPACE_KEYCODE = 8;
|
||||||
|
|
||||||
|
acceptance("Composer - editor mentions", function (needs) {
|
||||||
|
needs.user();
|
||||||
|
needs.settings({ enable_mentions: true });
|
||||||
|
|
||||||
|
needs.pretender((server, helper) => {
|
||||||
|
server.get("/u/search/users", () => {
|
||||||
|
return helper.response({
|
||||||
|
users: [
|
||||||
|
{
|
||||||
|
username: "user",
|
||||||
|
name: "Some User",
|
||||||
|
avatar_template:
|
||||||
|
"https://avatars.discourse.org/v3/letter/t/41988e/{size}.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
username: "user2",
|
||||||
|
name: "Some User",
|
||||||
|
avatar_template:
|
||||||
|
"https://avatars.discourse.org/v3/letter/t/41988e/{size}.png",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("selecting user mentions", async function (assert) {
|
||||||
|
await visit("/");
|
||||||
|
await click("#create-topic");
|
||||||
|
|
||||||
|
// Emulate user pressing backspace in the editor
|
||||||
|
const editor = query(".d-editor-input");
|
||||||
|
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keydown", "@".charCodeAt(0));
|
||||||
|
await fillIn(".d-editor-input", "abc @");
|
||||||
|
await setCaretPosition(editor, 5);
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keyup", "@".charCodeAt(0));
|
||||||
|
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keydown", "u".charCodeAt(0));
|
||||||
|
await fillIn(".d-editor-input", "abc @u");
|
||||||
|
await setCaretPosition(editor, 6);
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keyup", "u".charCodeAt(0));
|
||||||
|
|
||||||
|
await click(".autocomplete.ac-user .selected");
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
query(".d-editor-input").value,
|
||||||
|
"abc @user ",
|
||||||
|
"should replace mention correctly"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("selecting user mentions after deleting characters", async function (assert) {
|
||||||
|
await visit("/");
|
||||||
|
await click("#create-topic");
|
||||||
|
await fillIn(".d-editor-input", "abc @user a");
|
||||||
|
|
||||||
|
// Emulate user typing `@` and `u` in the editor
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keydown", BACKSPACE_KEYCODE);
|
||||||
|
await fillIn(".d-editor-input", "abc @user ");
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keyup", BACKSPACE_KEYCODE);
|
||||||
|
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keydown", BACKSPACE_KEYCODE);
|
||||||
|
await fillIn(".d-editor-input", "abc @user");
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keyup", BACKSPACE_KEYCODE);
|
||||||
|
|
||||||
|
await click(".autocomplete.ac-user .selected");
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
query(".d-editor-input").value,
|
||||||
|
"abc @user ",
|
||||||
|
"should replace mention correctly"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("selecting user mentions after deleting characters mid sentence", async function (assert) {
|
||||||
|
await visit("/");
|
||||||
|
await click("#create-topic");
|
||||||
|
|
||||||
|
// Emulate user pressing backspace in the editor
|
||||||
|
const editor = query(".d-editor-input");
|
||||||
|
await fillIn(".d-editor-input", "abc @user 123");
|
||||||
|
await setCaretPosition(editor, 9);
|
||||||
|
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keydown", BACKSPACE_KEYCODE);
|
||||||
|
await fillIn(".d-editor-input", "abc @use 123");
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keyup", BACKSPACE_KEYCODE);
|
||||||
|
await setCaretPosition(editor, 8);
|
||||||
|
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keydown", BACKSPACE_KEYCODE);
|
||||||
|
await fillIn(".d-editor-input", "abc @us 123");
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keyup", BACKSPACE_KEYCODE);
|
||||||
|
await setCaretPosition(editor, 7);
|
||||||
|
|
||||||
|
await click(".autocomplete.ac-user .selected");
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
query(".d-editor-input").value,
|
||||||
|
"abc @user 123",
|
||||||
|
"should replace mention correctly"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user