Ensure emoji completion always takes effect

This commit is contained in:
Chris Svenningsen 2020-11-11 14:54:23 -08:00 committed by GitHub
parent ff0794e08b
commit fef8c5b2f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 10 deletions
ts
quill/emoji
test/quill/emoji

View file

@ -65,8 +65,26 @@ export class EmojiCompletion {
this.quill.keyboard.addBinding({ key: 38 }, changeIndex(-1)); // 38 = Up this.quill.keyboard.addBinding({ key: 38 }, changeIndex(-1)); // 38 = Up
this.quill.keyboard.addBinding({ key: 39 }, clearResults); // 39 = Right this.quill.keyboard.addBinding({ key: 39 }, clearResults); // 39 = Right
this.quill.keyboard.addBinding({ key: 40 }, changeIndex(1)); // 40 = Down this.quill.keyboard.addBinding({ key: 40 }, changeIndex(1)); // 40 = Down
this.quill.keyboard.addBinding(
{
// 186 + Shift = Colon
key: 186,
shiftKey: true,
},
() => this.onTextChange(true)
);
this.quill.keyboard.addBinding(
{
// 58 = Also Colon
key: 58,
},
() => this.onTextChange(true)
);
this.quill.on('text-change', _.debounce(this.onTextChange.bind(this), 100)); this.quill.on(
'text-change',
_.debounce(() => this.onTextChange(), 100)
);
this.quill.on('selection-change', this.onSelectionChange.bind(this)); this.quill.on('selection-change', this.onSelectionChange.bind(this));
} }
@ -91,10 +109,13 @@ export class EmojiCompletion {
this.reset(); this.reset();
} }
onTextChange(): void { onTextChange(justPressedColon = false): boolean {
const PASS_THROUGH = true;
const INTERCEPT = false;
const range = this.quill.getSelection(); const range = this.quill.getSelection();
if (!range) return; if (!range) return PASS_THROUGH;
const [blot, index] = this.quill.getLeaf(range.index); const [blot, index] = this.quill.getLeaf(range.index);
const [leftTokenTextMatch, rightTokenTextMatch] = matchBlotTextPartitions( const [leftTokenTextMatch, rightTokenTextMatch] = matchBlotTextPartitions(
@ -107,24 +128,26 @@ export class EmojiCompletion {
if (leftTokenTextMatch) { if (leftTokenTextMatch) {
const [, leftTokenText, isSelfClosing] = leftTokenTextMatch; const [, leftTokenText, isSelfClosing] = leftTokenTextMatch;
if (isSelfClosing) { if (isSelfClosing || justPressedColon) {
if (isShortName(leftTokenText)) { if (isShortName(leftTokenText)) {
const emojiData = convertShortNameToData( const emojiData = convertShortNameToData(
leftTokenText, leftTokenText,
this.options.skinTone this.options.skinTone
); );
const numberOfColons = isSelfClosing ? 2 : 1;
if (emojiData) { if (emojiData) {
this.insertEmoji( this.insertEmoji(
emojiData, emojiData,
range.index - leftTokenText.length - 2, range.index - leftTokenText.length - numberOfColons,
leftTokenText.length + 2 leftTokenText.length + numberOfColons
); );
return; return INTERCEPT;
} }
} else { } else {
this.reset(); this.reset();
return; return PASS_THROUGH;
} }
} }
@ -144,14 +167,14 @@ export class EmojiCompletion {
range.index - leftTokenText.length - 1, range.index - leftTokenText.length - 1,
tokenText.length + 2 tokenText.length + 2
); );
return; return INTERCEPT;
} }
} }
} }
if (leftTokenText.length < 2) { if (leftTokenText.length < 2) {
this.reset(); this.reset();
return; return PASS_THROUGH;
} }
const showEmojiResults = search(leftTokenText, 10); const showEmojiResults = search(leftTokenText, 10);
@ -165,6 +188,8 @@ export class EmojiCompletion {
} else if (this.results.length !== 0) { } else if (this.results.length !== 0) {
this.reset(); this.reset();
} }
return PASS_THROUGH;
} }
completeEmoji(): void { completeEmoji(): void {

View file

@ -336,6 +336,40 @@ describe('emojiCompletion', () => {
}); });
}); });
}); });
describe('given a completeable emoji and colon was just pressed', () => {
beforeEach(function beforeEach() {
mockQuill.getSelection.returns({
index: 6,
length: 0,
});
});
describe('and given it matches a short name', () => {
const text = ':smile';
beforeEach(function beforeEach() {
const blot = {
text,
};
mockQuill.getLeaf.returns([blot, 6]);
emojiCompletion.onTextChange(true);
});
it('inserts the emoji at the current cursor position', () => {
const [emoji, index, range] = insertEmojiStub.args[0];
assert.equal(emoji.short_name, 'smile');
assert.equal(index, 0);
assert.equal(range, 6);
});
it('does not show results', () => {
assert.equal(emojiCompletion.results.length, 0);
});
});
});
}); });
describe('completeEmoji', () => { describe('completeEmoji', () => {