mirror of
https://github.com/flarum/core.git
synced 2025-08-02 22:47:33 +02:00
1
extensions/emoji/.gitignore
vendored
1
extensions/emoji/.gitignore
vendored
@@ -4,3 +4,4 @@ composer.phar
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
node_modules
|
node_modules
|
||||||
js/dist/*
|
js/dist/*
|
||||||
|
.vscode
|
6
extensions/emoji/js/.prettierrc.json
Normal file
6
extensions/emoji/js/.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 150,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5"
|
||||||
|
}
|
5211
extensions/emoji/js/package-lock.json
generated
5211
extensions/emoji/js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,14 +2,15 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"name": "@flarum/emoji",
|
"name": "@flarum/emoji",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"flarum-webpack-config": "0.1.0-beta.10",
|
"flarum-webpack-config": "^1.0.0",
|
||||||
"simple-emoji-map": "^0.4.1",
|
"simple-emoji-map": "^0.4.1",
|
||||||
"twemoji": "^13.0.0",
|
"twemoji": "^13.1.0",
|
||||||
"webpack": "^4.43.0",
|
"webpack": "^4.46.0",
|
||||||
"webpack-cli": "^3.3.12"
|
"webpack-cli": "^3.3.12"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "webpack --mode development --watch",
|
"dev": "webpack --mode development --watch",
|
||||||
"build": "webpack --mode production"
|
"build": "webpack --mode production",
|
||||||
|
"format": "prettier --write src"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,7 +27,6 @@ export default function addComposerAutocomplete() {
|
|||||||
.bindTo($editor);
|
.bindTo($editor);
|
||||||
|
|
||||||
$editor.after($container);
|
$editor.after($container);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
extend(TextEditor.prototype, 'buildEditorParams', function (params) {
|
extend(TextEditor.prototype, 'buildEditorParams', function (params) {
|
||||||
@@ -79,7 +78,8 @@ export default function addComposerAutocomplete() {
|
|||||||
onclick={() => applySuggestion(emoji)}
|
onclick={() => applySuggestion(emoji)}
|
||||||
onmouseenter={function () {
|
onmouseenter={function () {
|
||||||
dropdown.setIndex($(this).parent().index() - 1);
|
dropdown.setIndex($(this).parent().index() - 1);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<img alt={emoji} class="emoji" draggable="false" loading="lazy" src={`${cdn}72x72/${code}.png`} />
|
<img alt={emoji} class="emoji" draggable="false" loading="lazy" src={`${cdn}72x72/${code}.png`} />
|
||||||
{name}
|
{name}
|
||||||
</button>
|
</button>
|
||||||
@@ -91,14 +91,14 @@ export default function addComposerAutocomplete() {
|
|||||||
|
|
||||||
// Build a regular expression to do a fuzzy match of the given input string
|
// Build a regular expression to do a fuzzy match of the given input string
|
||||||
const fuzzyRegexp = function (str) {
|
const fuzzyRegexp = function (str) {
|
||||||
const reEscape = new RegExp('\\(([' + ('+.*?[]{}()^$|\\'.replace(/(.)/g, '\\$1')) + '])\\)', 'g');
|
const reEscape = new RegExp('\\(([' + '+.*?[]{}()^$|\\'.replace(/(.)/g, '\\$1') + '])\\)', 'g');
|
||||||
return new RegExp('(.*)' + (str.toLowerCase().replace(/(.)/g, '($1)(.*?)')).replace(reEscape, '(\\$1)') + '$', 'i');
|
return new RegExp('(.*)' + str.toLowerCase().replace(/(.)/g, '($1)(.*?)').replace(reEscape, '(\\$1)') + '$', 'i');
|
||||||
};
|
};
|
||||||
const regTyped = fuzzyRegexp(typed);
|
const regTyped = fuzzyRegexp(typed);
|
||||||
|
|
||||||
let maxSuggestions = 7;
|
let maxSuggestions = 7;
|
||||||
|
|
||||||
const findMatchingEmojis = matcher => {
|
const findMatchingEmojis = (matcher) => {
|
||||||
for (let i = 0; i < emojiKeys.length && maxSuggestions > 0; i++) {
|
for (let i = 0; i < emojiKeys.length && maxSuggestions > 0; i++) {
|
||||||
const curEmoji = emojiKeys[i];
|
const curEmoji = emojiKeys[i];
|
||||||
|
|
||||||
@@ -116,16 +116,18 @@ export default function addComposerAutocomplete() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// First, try to find all emojis starting with the given string
|
// First, try to find all emojis starting with the given string
|
||||||
findMatchingEmojis(emoji => emoji.indexOf(typed) === 0);
|
findMatchingEmojis((emoji) => emoji.indexOf(typed) === 0);
|
||||||
|
|
||||||
// If there are still suggestions left, try for some fuzzy matches
|
// If there are still suggestions left, try for some fuzzy matches
|
||||||
findMatchingEmojis(emoji => regTyped.test(emoji));
|
findMatchingEmojis((emoji) => regTyped.test(emoji));
|
||||||
|
|
||||||
const suggestions = similarEmoji.map(emoji => ({
|
const suggestions = similarEmoji
|
||||||
emoji,
|
.map((emoji) => ({
|
||||||
name: emojiMap[emoji][0],
|
emoji,
|
||||||
code: getEmojiIconCode(emoji),
|
name: emojiMap[emoji][0],
|
||||||
})).map(makeSuggestion);
|
code: getEmojiIconCode(emoji),
|
||||||
|
}))
|
||||||
|
.map(makeSuggestion);
|
||||||
|
|
||||||
if (suggestions.length) {
|
if (suggestions.length) {
|
||||||
dropdown.items = suggestions;
|
dropdown.items = suggestions;
|
||||||
@@ -165,10 +167,11 @@ export default function addComposerAutocomplete() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
extend(TextEditor.prototype, 'toolbarItems', function (items) {
|
extend(TextEditor.prototype, 'toolbarItems', function (items) {
|
||||||
items.add('emoji', (
|
items.add(
|
||||||
|
'emoji',
|
||||||
<TextEditorButton onclick={() => this.attrs.composer.editor.insertAtCursor(' :')} icon="far fa-smile">
|
<TextEditorButton onclick={() => this.attrs.composer.editor.insertAtCursor(' :')} icon="far fa-smile">
|
||||||
{app.translator.trans('flarum-emoji.forum.composer.emoji_tooltip')}
|
{app.translator.trans('flarum-emoji.forum.composer.emoji_tooltip')}
|
||||||
</TextEditorButton>
|
</TextEditorButton>
|
||||||
));
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -10,16 +10,20 @@ export default class AutocompleteDropdown extends Fragment {
|
|||||||
return (
|
return (
|
||||||
<ul className="Dropdown-menu EmojiDropdown">
|
<ul className="Dropdown-menu EmojiDropdown">
|
||||||
<li className="Dropdown-header">{app.translator.trans('flarum-emoji.forum.composer.type_to_search_text')}</li>
|
<li className="Dropdown-header">{app.translator.trans('flarum-emoji.forum.composer.type_to_search_text')}</li>
|
||||||
{this.items.map(item => <li key={item.attrs.key}>{item}</li>)}
|
{this.items.map((item) => (
|
||||||
|
<li key={item.attrs.key}>{item}</li>
|
||||||
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
show(left, top) {
|
show(left, top) {
|
||||||
this.$().show().css({
|
this.$()
|
||||||
left: left + 'px',
|
.show()
|
||||||
top: top + 'px'
|
.css({
|
||||||
});
|
left: left + 'px',
|
||||||
|
top: top + 'px',
|
||||||
|
});
|
||||||
this.active = true;
|
this.active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +36,7 @@ export default class AutocompleteDropdown extends Fragment {
|
|||||||
this.keyWasJustPressed = true;
|
this.keyWasJustPressed = true;
|
||||||
this.setIndex(this.index + delta, true);
|
this.setIndex(this.index + delta, true);
|
||||||
clearTimeout(this.keyWasJustPressedTimeout);
|
clearTimeout(this.keyWasJustPressedTimeout);
|
||||||
this.keyWasJustPressedTimeout = setTimeout(() => this.keyWasJustPressed = false, 500);
|
this.keyWasJustPressedTimeout = setTimeout(() => (this.keyWasJustPressed = false), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
complete() {
|
complete() {
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
/*! Copyright Twitter Inc. and other contributors. Licensed under MIT *//*
|
/*! Copyright Twitter Inc. and other contributors. Licensed under MIT */ /*
|
||||||
https://github.com/twitter/twemoji/blob/gh-pages/LICENSE
|
https://github.com/twitter/twemoji/blob/gh-pages/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import twemoji from 'twemoji';
|
import twemoji from 'twemoji';
|
||||||
|
|
||||||
// avoid using a string literal like '\u200D' here because minifiers expand it inline
|
// avoid using a string literal like '\u200D' here because minifiers expand it inline
|
||||||
const U200D = String.fromCharCode(0x200D);
|
const U200D = String.fromCharCode(0x200d);
|
||||||
|
|
||||||
// avoid runtime RegExp creation for not so smart,
|
// avoid runtime RegExp creation for not so smart,
|
||||||
// not JIT based, and old browsers / engines
|
// not JIT based, and old browsers / engines
|
||||||
@@ -19,8 +19,5 @@ const UFE0Fg = /\uFE0F/g;
|
|||||||
* @return string the code point
|
* @return string the code point
|
||||||
*/
|
*/
|
||||||
export default function getEmojiIconCode(emoji) {
|
export default function getEmojiIconCode(emoji) {
|
||||||
return twemoji.convert.toCodePoint(emoji.indexOf(U200D) < 0 ?
|
return twemoji.convert.toCodePoint(emoji.indexOf(U200D) < 0 ? emoji.replace(UFE0Fg, '') : emoji);
|
||||||
emoji.replace(UFE0Fg, '') :
|
|
||||||
emoji
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@ const options = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function renderEmoji() {
|
export default function renderEmoji() {
|
||||||
override(Post.prototype, 'contentHtml', function(original) {
|
override(Post.prototype, 'contentHtml', function (original) {
|
||||||
const contentHtml = original();
|
const contentHtml = original();
|
||||||
|
|
||||||
if (this.oldContentHtml !== contentHtml) {
|
if (this.oldContentHtml !== contentHtml) {
|
||||||
|
Reference in New Issue
Block a user