1
0
mirror of https://github.com/flarum/core.git synced 2025-08-07 08:56:38 +02:00

Update for Editor Drivers Abstraction (#34)

This commit is contained in:
Alexander Skvortsov
2021-02-26 16:18:32 -05:00
committed by GitHub
parent 5c1fa4aea8
commit 720ea6c576
3 changed files with 143 additions and 137 deletions

View File

@@ -1778,9 +1778,9 @@
"integrity": "sha512-rYWlogJ2q5P78U8Xx1vhsXHcYKu1wFnr7+o6z9QHssZ1SsJLTCkJINZIPHRFWuDreAUK457TkqHpdOXElu0fzA=="
},
"end-of-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"requires": {
"once": "^1.4.0"
}
@@ -3441,9 +3441,12 @@
"integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw=="
},
"serialize-javascript": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
"integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ=="
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
"requires": {
"randombytes": "^2.1.0"
}
},
"set-blocking": {
"version": "2.0.0",
@@ -3500,7 +3503,8 @@
},
"simple-emoji-map": {
"version": "0.4.1",
"resolved": "git+https://github.com/davwheat/simple-emoji-map.git#dfa29dae25b4620302b1330cf54e12d4492fedf0",
"resolved": "https://registry.npmjs.org/simple-emoji-map/-/simple-emoji-map-0.4.1.tgz",
"integrity": "sha512-K40UJhKs0VGE4gXj4cV/REnBLIUfPJ5n+eLWwpaOWQmjnJnK1+uyw/KIqFAWemD1kpsL2/khUNYRLe48YH9MKA==",
"requires": {
"cosmiconfig": "^6.0.0",
"emojibase-data": "^5.0.1",
@@ -3770,9 +3774,9 @@
"integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA=="
},
"terser": {
"version": "4.6.13",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.6.13.tgz",
"integrity": "sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw==",
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
"integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
"requires": {
"commander": "^2.20.0",
"source-map": "~0.6.1",
@@ -3787,15 +3791,15 @@
}
},
"terser-webpack-plugin": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz",
"integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==",
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
"integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
"requires": {
"cacache": "^12.0.2",
"find-cache-dir": "^2.1.0",
"is-wsl": "^1.1.0",
"schema-utils": "^1.0.0",
"serialize-javascript": "^2.1.2",
"serialize-javascript": "^4.0.0",
"source-map": "^0.6.1",
"terser": "^4.1.2",
"webpack-sources": "^1.4.0",
@@ -3809,11 +3813,6 @@
}
}
},
"textarea-caret": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/textarea-caret/-/textarea-caret-3.1.0.tgz",
"integrity": "sha512-cXAvzO9pP5CGa6NKx0WYHl+8CHKZs8byMkt3PCJBCmq2a34YA9pO1NrQET5pzeqnBjBdToF5No4rrmkDUgQC2Q=="
},
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",

View File

@@ -4,7 +4,6 @@
"dependencies": {
"flarum-webpack-config": "0.1.0-beta.10",
"simple-emoji-map": "^0.4.1",
"textarea-caret": "^3.1.0",
"twemoji": "^13.0.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"

View File

@@ -1,4 +1,3 @@
import getCaretCoordinates from 'textarea-caret';
import emojiMap from 'simple-emoji-map';
import { extend } from 'flarum/extend';
@@ -12,20 +11,11 @@ import cdn from './cdn';
export default function addComposerAutocomplete() {
const emojiKeys = Object.keys(emojiMap);
extend(TextEditor.prototype, 'oncreate', function() {
const $container = $('<div class="ComposerBody-emojiDropdownContainer"></div>');
const dropdown = new AutocompleteDropdown();
const $textarea = this.$('textarea').wrap('<div class="ComposerBody-emojiWrapper"></div>');
let emojiStart;
let typed;
const applySuggestion = (replacement) => {
this.attrs.composer.editor.replaceBeforeCursor(emojiStart - 1, replacement + ' ');
dropdown.hide();
};
extend(TextEditor.prototype, 'oncreate', function () {
const $editor = this.$('.TextEditor-editor').wrap('<div class="ComposerBody-emojiWrapper"></div>');
this.navigator = new KeyboardNavigatable();
this.navigator
@@ -34,31 +24,44 @@ export default function addComposerAutocomplete() {
.onDown(() => dropdown.navigate(1))
.onSelect(dropdown.complete.bind(dropdown))
.onCancel(dropdown.hide.bind(dropdown))
.bindTo($textarea);
.bindTo($editor);
$textarea
.after($container)
.on('click keyup input', function(e) {
// Up, down, enter, tab, escape, left, right.
if ([9, 13, 27, 40, 38, 37, 39].indexOf(e.which) !== -1) return;
$editor.after($container);
const cursor = this.selectionStart;
});
if (this.selectionEnd - cursor > 0) return;
extend(TextEditor.prototype, 'buildEditorParams', function (params) {
let relEmojiStart;
let absEmojiStart;
let typed;
const applySuggestion = (replacement) => {
this.attrs.composer.editor.replaceBeforeCursor(absEmojiStart - 1, replacement + ' ');
dropdown.hide();
};
params.inputListeners.push(function (e) {
const selection = app.composer.editor.getSelectionRange();
const cursor = selection[0];
if (selection[1] - cursor > 0) return;
// Search backwards from the cursor for an ':' symbol. If we find
// one and followed by a whitespace, we will want to show the
// autocomplete dropdown!
const value = this.value;
emojiStart = 0;
for (let i = cursor - 1; i >= 0; i--) {
const character = value.substr(i, 1);
const lastChunk = app.composer.editor.getLastNChars(15);
absEmojiStart = 0;
for (let i = lastChunk.length - 1; i >= 0; i--) {
const character = lastChunk.substr(i, 1);
// check what user typed, emoji names only contains alphanumeric,
// underline, '+' and '-'
if (!/[a-z0-9]|\+|\-|_|\:/.test(character)) break;
// make sure ':' followed by a whitespace or newline
if (character === ':' && (i == 0 || /\s/.test(value.substr(i - 1, 1)))) {
emojiStart = i + 1;
// make sure ':' preceded by a whitespace or newline
if (character === ':' && (i == 0 || /\s/.test(lastChunk.substr(i - 1, 1)))) {
relEmojiStart = i + 1;
absEmojiStart = cursor - lastChunk.length + i + 1;
break;
}
}
@@ -66,8 +69,8 @@ export default function addComposerAutocomplete() {
dropdown.hide();
dropdown.active = false;
if (emojiStart) {
typed = value.substring(emojiStart, cursor).toLowerCase();
if (absEmojiStart) {
typed = lastChunk.substring(relEmojiStart).toLowerCase();
const makeSuggestion = function ({ emoji, name, code }) {
return (
@@ -129,20 +132,25 @@ export default function addComposerAutocomplete() {
m.render($container[0], dropdown.render());
dropdown.show();
const coordinates = getCaretCoordinates(this, emojiStart);
const coordinates = app.composer.editor.getCaretCoordinates(absEmojiStart);
const width = dropdown.$().outerWidth();
const height = dropdown.$().outerHeight();
const parent = dropdown.$().offsetParent();
let left = coordinates.left;
let top = coordinates.top + 15;
// Keep the dropdown inside the editor.
if (top + height > parent.height()) {
top = coordinates.top - height - 15;
}
if (left + width > parent.width()) {
left = parent.width() - width;
}
top = Math.max(-$(this).offset().top, top);
left = Math.max(-$(this).offset().left, left);
// Prevent the dropdown from going off screen on mobile
top = Math.max(-parent.offset().top, top);
left = Math.max(-parent.offset().left, left);
dropdown.show(left, top);
}
};