Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
converse.js
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
converse.js
Commits
be20b8e1
Commit
be20b8e1
authored
Jun 22, 2020
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
emojis: fix rendering of custom emojis
parent
77a0a01e
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
173 additions
and
95 deletions
+173
-95
karma.conf.js
karma.conf.js
+3
-1
spec/emojis.js
spec/emojis.js
+46
-1
src/headless/converse-chat.js
src/headless/converse-chat.js
+11
-9
src/headless/converse-emoji.js
src/headless/converse-emoji.js
+100
-61
src/headless/converse-muc.js
src/headless/converse-muc.js
+1
-3
src/headless/emojis.json
src/headless/emojis.json
+2
-2
src/templates/directives/body.js
src/templates/directives/body.js
+7
-8
src/templates/emoji_picker.js
src/templates/emoji_picker.js
+3
-10
No files found.
karma.conf.js
View file @
be20b8e1
...
...
@@ -12,6 +12,7 @@ module.exports = function(config) {
{
pattern
:
"
dist/emojis.js
"
,
served
:
true
},
"
dist/converse.js
"
,
"
dist/converse.css
"
,
{
pattern
:
"
dist/images/**/*.*
"
,
included
:
false
},
{
pattern
:
"
dist/webfonts/**/*.*
"
,
included
:
false
},
{
pattern
:
"
dist/
\
@fortawesome/fontawesome-free/sprites/solid.svg
"
,
watched
:
false
,
...
...
@@ -60,7 +61,8 @@ module.exports = function(config) {
],
proxies
:
{
"
/dist/
\
@fortawesome/fontawesome-free/sprites/solid.svg
"
:
"
/base/dist/
\
@fortawesome/fontawesome-free/sprites/solid.svg
"
"
/dist/
\
@fortawesome/fontawesome-free/sprites/solid.svg
"
:
"
/base/dist/
\
@fortawesome/fontawesome-free/sprites/solid.svg
"
,
"
/dist/images/custom_emojis/
"
:
"
/base/dist/images/custom_emojis/
"
},
client
:
{
...
...
spec/emojis.js
View file @
be20b8e1
...
...
@@ -100,7 +100,6 @@ describe("Emojis", function () {
done
();
}));
it
(
"
allows you to search for particular emojis
"
,
mock
.
initConverse
(
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
...
...
@@ -239,5 +238,51 @@ describe("Emojis", function () {
expect
(
u
.
hasClass
(
'
chat-msg__text--larger
'
,
message
)).
toBe
(
true
);
done
()
}));
it
(
"
can show custom emojis
"
,
mock
.
initConverse
(
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{
emoji_categories
:
{
"
smileys
"
:
"
:grinning:
"
,
"
people
"
:
"
:thumbsup:
"
,
"
activity
"
:
"
:soccer:
"
,
"
travel
"
:
"
:motorcycle:
"
,
"
objects
"
:
"
:bomb:
"
,
"
nature
"
:
"
:rainbow:
"
,
"
food
"
:
"
:hotdog:
"
,
"
symbols
"
:
"
:musical_note:
"
,
"
flags
"
:
"
:flag_ac:
"
,
"
custom
"
:
'
:xmpp:
'
}
},
async
function
(
done
,
_converse
)
{
await
mock
.
waitForRoster
(
_converse
,
'
current
'
,
1
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@montague.lit
'
;
await
mock
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
view
=
_converse
.
api
.
chatviews
.
get
(
contact_jid
);
const
toolbar
=
await
u
.
waitUntil
(()
=>
view
.
el
.
querySelector
(
'
ul.chat-toolbar
'
));
expect
(
toolbar
.
querySelectorAll
(
'
li.toggle-smiley__container
'
).
length
).
toBe
(
1
);
toolbar
.
querySelector
(
'
a.toggle-smiley
'
).
click
();
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
view
.
el
.
querySelector
(
'
.emoji-picker__lists
'
)),
1000
);
const
picker
=
await
u
.
waitUntil
(()
=>
view
.
el
.
querySelector
(
'
.emoji-picker__container
'
),
1000
);
const
custom_category
=
picker
.
querySelector
(
'
.pick-category[data-category="custom"]
'
);
expect
(
custom_category
.
innerHTML
.
replace
(
/<!---->/g
,
''
).
trim
()).
toBe
(
'
<img class="emoji" draggable="false" title=":xmpp:" alt=":xmpp:" src="/dist/images/custom_emojis/xmpp.png">
'
);
const
textarea
=
view
.
el
.
querySelector
(
'
textarea.chat-textarea
'
);
textarea
.
value
=
'
Running tests for :converse:
'
;
view
.
onKeyDown
({
target
:
textarea
,
preventDefault
:
function
preventDefault
()
{},
keyCode
:
13
// Enter
});
await
new
Promise
(
resolve
=>
view
.
model
.
messages
.
once
(
'
rendered
'
,
resolve
));
const
body
=
view
.
el
.
querySelector
(
'
converse-chat-message-body
'
);
expect
(
body
.
innerHTML
.
replace
(
/<!---->/g
,
''
).
trim
()).
toBe
(
'
Running tests for <img class="emoji" draggable="false" title=":converse:" alt=":converse:" src="/dist/images/custom_emojis/converse.png">
'
);
done
();
}));
});
});
src/headless/converse-chat.js
View file @
be20b8e1
...
...
@@ -951,21 +951,23 @@ converse.plugins.add('converse-chat', {
getOutgoingMessageAttributes
(
text
,
spoiler_hint
)
{
const
is_spoiler
=
this
.
get
(
'
composing_spoiler
'
);
const
origin_id
=
u
.
getUniqueId
();
const
body
=
text
?
u
.
httpToGeoUri
(
u
.
shortnameToUnicode
(
text
),
_converse
)
:
undefined
;
return
{
'
from
'
:
_converse
.
bare_jid
,
'
fullname
'
:
_converse
.
xmppstatus
.
get
(
'
fullname
'
),
'
id
'
:
origin_id
,
'
is_only_emojis
'
:
text
?
u
.
isOnlyEmojis
(
text
)
:
false
,
'
jid
'
:
this
.
get
(
'
jid
'
),
'
nickname
'
:
this
.
get
(
'
nickname
'
)
,
'
message
'
:
body
,
'
msgid
'
:
origin_id
,
'
origin_id
'
:
origin_id
,
'
fullname
'
:
_converse
.
xmppstatus
.
get
(
'
fullname
'
),
'
from
'
:
_converse
.
bare_jid
,
'
is_only_emojis
'
:
text
?
u
.
isOnlyEmojis
(
text
)
:
false
,
'
nickname
'
:
this
.
get
(
'
nickname
'
),
'
sender
'
:
'
me
'
,
'
time
'
:
(
new
Date
()).
toISOString
(),
'
message
'
:
text
?
u
.
httpToGeoUri
(
u
.
shortnameToUnicode
(
text
),
_converse
)
:
undefined
,
'
is_spoiler
'
:
is_spoiler
,
'
spoiler_hint
'
:
is_spoiler
?
spoiler_hint
:
undefined
,
'
type
'
:
this
.
get
(
'
message_type
'
)
'
time
'
:
(
new
Date
()).
toISOString
(),
'
type
'
:
this
.
get
(
'
message_type
'
),
body
,
is_spoiler
,
origin_id
}
},
...
...
src/headless/converse-emoji.js
View file @
be20b8e1
...
...
@@ -3,10 +3,11 @@
* @copyright 2020, the Converse.js contributors
* @license Mozilla Public License (MPLv2)
*/
import
{
Model
}
from
'
@converse/skeletor/src/model.js
'
;
import
{
find
,
uniq
}
from
"
lodash-es
"
;
import
*
as
twemoji
from
"
twemoji
"
;
import
{
Model
}
from
'
@converse/skeletor/src/model.js
'
;
import
{
_converse
,
api
,
converse
}
from
"
./converse-core
"
;
import
{
find
,
isString
,
uniq
}
from
"
lodash-es
"
;
import
{
html
}
from
'
lit-html
'
;
const
u
=
converse
.
env
.
utils
;
...
...
@@ -27,6 +28,7 @@ const ASCII_LIST = {
};
let
shortnames_regex
;
const
ASCII_REGEX
=
'
(
\\
*
\\\\
0
\\
/
\\
*|
\\
*
\\\\
O
\\
/
\\
*|
\\
-___
\\
-|
\\
:
\'\\
-
\\
)|
\'\\
:
\\
-
\\
)|
\'\\
:
\\
-D|
\\
>
\\
:
\\
-
\\
)|>
\\
:
\\
-
\\
)|
\'\\
:
\\
-
\\
(|
\\
>
\\
:
\\
-
\\
(|>
\\
:
\\
-
\\
(|
\\
:
\'\\
-
\\
(|O
\\
:
\\
-
\\
)|0
\\
:
\\
-3|0
\\
:
\\
-
\\
)|0;
\\
^
\\
)|O;
\\
-
\\
)|0;
\\
-
\\
)|O
\\
:
\\
-3|
\\
-__
\\
-|
\\
:
\\
-Þ|
\\
:
\\
-Þ|
\\
<
\\
/3|<
\\
/3|
\\
:
\'\\
)|
\\
:
\\
-D|
\'\\
:
\\
)|
\'\\
=
\\
)|
\'\\
:D|
\'\\
=D|
\\
>
\\
:
\\
)|>
\\
:
\\
)|
\\
>;
\\
)|>;
\\
)|
\\
>
\\
=
\\
)|>
\\
=
\\
)|;
\\
-
\\
)|
\\
*
\\
-
\\
)|;
\\
-
\\
]|;
\\
^
\\
)|
\'\\
:
\\
(|
\'\\
=
\\
(|
\\
:
\\
-
\\
*|
\\
:
\\
^
\\
*|
\\
>
\\
:P|>
\\
:P|X
\\
-P|
\\
>
\\
:
\\
[|>
\\
:
\\
[|
\\
:
\\
-
\\
(|
\\
:
\\
-
\\
[|
\\
>
\\
:
\\
(|>
\\
:
\\
(|
\\
:
\'\\
(|;
\\
-
\\
(|
\\
>
\\
.
\\
<|>
\\
.<|#
\\
-
\\
)|%
\\
-
\\
)|X
\\
-
\\
)|
\\\\
0
\\
/|
\\\\
O
\\
/|0
\\
:3|0
\\
:
\\
)|O
\\
:
\\
)|O
\\
=
\\
)|O
\\
:3|B
\\
-
\\
)|8
\\
-
\\
)|B
\\
-D|8
\\
-D|
\\
-_
\\
-|
\\
>
\\
:
\\\\
|>
\\
:
\\\\
|
\\
>
\\
:
\\
/|>
\\
:
\\
/|
\\
:
\\
-
\\
/|
\\
:
\\
-
\\
.|
\\
:
\\
-P|
\\
:Þ|
\\
:Þ|
\\
:
\\
-b|
\\
:
\\
-O|O_O|
\\
>
\\
:O|>
\\
:O|
\\
:
\\
-X|
\\
:
\\
-#|
\\
:
\\
-
\\
)|
\\
(y
\\
)|
\\
<3|<3|
\\
:D|
\\
=D|;
\\
)|
\\
*
\\
)|;
\\
]|;D|
\\
:
\\
*|
\\
=
\\
*|
\\
:
\\
(|
\\
:
\\
[|
\\
=
\\
(|
\\
:@|;
\\
(|D
\\
:|
\\
:
\\
$|
\\
=
\\
$|#
\\
)|%
\\
)|X
\\
)|B
\\
)|8
\\
)|
\\
:
\\
/|
\\
:
\\\\
|
\\
=
\\
/|
\\
=
\\\\
|
\\
:L|
\\
=L|
\\
:P|
\\
=P|
\\
:b|
\\
:O|
\\
:X|
\\
:#|
\\
=X|
\\
=#|
\\
:
\\
)|
\\
=
\\
]|
\\
=
\\
)|
\\
:
\\
])
'
;
const
ASCII_REPLACE_REGEX
=
new
RegExp
(
"
<object[^>]*>.*?<
\
/object>|<span[^>]*>.*?<
\
/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((
\\
s|^)
"
+
ASCII_REGEX
+
"
(?=
\\
s|$|[!,.?]))
"
,
"
gi
"
);
...
...
@@ -54,6 +56,74 @@ function convert (unicode) {
}
function
getTonedEmojis
()
{
if
(
!
_converse
.
toned_emojis
)
{
_converse
.
toned_emojis
=
uniq
(
Object
.
values
(
_converse
.
emojis
.
json
.
people
)
.
filter
(
person
=>
person
.
sn
.
includes
(
'
_tone
'
))
.
map
(
person
=>
person
.
sn
.
replace
(
/_tone
[
1-5
]
/
,
''
))
);
}
return
_converse
.
toned_emojis
;
}
function
convertASCII2Emoji
(
str
)
{
// Replace ASCII smileys
return
str
.
replace
(
ASCII_REPLACE_REGEX
,
(
entire
,
m1
,
m2
,
m3
)
=>
{
if
(
(
typeof
m3
===
'
undefined
'
)
||
(
m3
===
''
)
||
(
!
(
u
.
unescapeHTML
(
m3
)
in
ASCII_LIST
))
)
{
// if the ascii doesnt exist just return the entire match
return
entire
;
}
m3
=
u
.
unescapeHTML
(
m3
);
const
unicode
=
ASCII_LIST
[
m3
].
toUpperCase
();
return
m2
+
convert
(
unicode
);
});
}
function
getEmojiMarkup
(
shortname
,
unicode_only
)
{
if
((
typeof
shortname
===
'
undefined
'
)
||
(
shortname
===
''
)
||
(
!
_converse
.
emoji_shortnames
.
includes
(
shortname
)))
{
// if the shortname doesnt exist just return the entire match
return
shortname
;
}
const
codepoint
=
_converse
.
emojis_map
[
shortname
].
cp
;
if
(
codepoint
)
{
return
convert
(
codepoint
.
toUpperCase
());
}
else
if
(
unicode_only
)
{
return
shortname
;
}
else
{
return
html
`<img class="emoji" draggable="false" title="
${
shortname
}
" alt="
${
shortname
}
" src="
${
_converse
.
emojis_map
[
shortname
].
url
}
">`
;
}
}
function
addEmojisMarkup
(
text
,
unicode_only
=
false
)
{
const
original_text
=
text
;
let
list
=
[
text
];
const
references
=
[...
text
.
matchAll
(
shortnames_regex
)];
if
(
references
.
length
)
{
references
.
map
(
ref
=>
{
ref
.
begin
=
ref
.
index
;
ref
.
end
=
ref
.
index
+
ref
[
0
].
length
;
return
ref
;
})
.
sort
((
a
,
b
)
=>
b
.
begin
-
a
.
begin
)
.
forEach
(
ref
=>
{
const
text
=
list
.
shift
();
const
shortname
=
original_text
.
slice
(
ref
.
begin
,
ref
.
end
);
const
emoji
=
getEmojiMarkup
(
shortname
,
unicode_only
);
if
(
isString
(
emoji
))
{
list
=
[
text
.
slice
(
0
,
ref
.
begin
)
+
emoji
+
text
.
slice
(
ref
.
end
),
...
list
];
}
else
{
list
=
[
text
.
slice
(
0
,
ref
.
begin
),
emoji
,
text
.
slice
(
ref
.
end
),
...
list
];
}
});
}
return
list
;
}
converse
.
plugins
.
add
(
'
converse-emoji
'
,
{
initialize
()
{
...
...
@@ -115,42 +185,15 @@ converse.plugins.add('converse-emoji', {
}
});
function
getTonedEmojis
()
{
if
(
!
_converse
.
toned_emojis
)
{
_converse
.
toned_emojis
=
uniq
(
Object
.
values
(
_converse
.
emojis
.
json
.
people
)
.
filter
(
person
=>
person
.
sn
.
includes
(
'
_tone
'
))
.
map
(
person
=>
person
.
sn
.
replace
(
/_tone
[
1-5
]
/
,
''
))
);
}
return
_converse
.
toned_emojis
;
}
/************************ BEGIN Utils ************************/
// Closured cache
const
emojis_by_attribute
=
{};
Object
.
assign
(
u
,
{
/**
* Replaces emoji shortnames in the passed-in string with unicode or image-based emojis
* (based on the value of `use_system_emojis`).
* @method u.addEmoji
* @param {string} text = The text
* @returns {string} The text with shortnames replaced with emoji
* unicodes or images.
*/
addEmoji
(
text
)
{
return
u
.
getEmojiRenderer
()(
text
);
},
/**
* Based on the value of `use_system_emojis` will return either
* a function that converts emoji shortnames into unicode glyphs
* (see {@link u.shortnameToUnicode} or one that converts them into images.
* unicode emojis
* @method u.getEmojiRenderer
* (see {@link u.shortnamesToEmojis} or one that converts them into images.
* @returns {function}
*/
getEmojiRenderer
()
{
...
...
@@ -164,55 +207,51 @@ converse.plugins.add('converse-emoji', {
return
api
.
settings
.
get
(
'
use_system_emojis
'
)
?
transform
:
text
=>
twemoji
.
default
.
parse
(
transform
(
text
),
how
);
},
/**
* Replaces emoji shortnames in the passed-in string with unicode or image-based emojis
* (based on the value of `use_system_emojis`).
* @method u.addEmoji
* @param {string} text = The text
* @returns {string} The text with shortnames replaced with emoji
* unicodes or images.
*/
addEmoji
(
text
)
{
return
u
.
getEmojiRenderer
()(
text
);
},
/**
* Returns an emoji represented by the passed in shortname.
* Scans the passed in text for shortnames and replaces them with
* emoji unicode glyphs or alternatively if it's a custom emoji
* without unicode representation then
markup for an HTML image tag
* is returned.
* without unicode representation then
a lit-html TemplateResult
*
which represents image tag markup
is returned.
*
* The shortname needs to be defined in `emojis.json`
* and needs to have either a `cp` attribute for the codepoint, or
* an `url` attribute which points to the source for the image.
*
* @method u.shortnamesToEmojis
* @param {string} str - String containg the shortname(s)
* @param {String} str - String containg the shortname(s)
* @param {Boolean} unicode_only - Whether emojis are rendered as
* unicode codepoints. If so, the returned result will be an array
* with containing one string, because the emojis themselves will
* also be strings. If set to false, emojis will be represented by
* lit-html TemplateResult objects.
* @returns {Array} An array of at least one string, or otherwise
* strings and lit-html TemplateResult objects.
*/
shortnamesToEmojis
(
str
,
unicode_only
=
false
)
{
str
=
str
.
replace
(
_converse
.
emojis
.
shortnames_regex
,
shortname
=>
{
if
((
typeof
shortname
===
'
undefined
'
)
||
(
shortname
===
''
)
||
(
!
_converse
.
emoji_shortnames
.
includes
(
shortname
)))
{
// if the shortname doesnt exist just return the entire match
return
shortname
;
}
const
codepoint
=
_converse
.
emojis_map
[
shortname
].
cp
;
if
(
codepoint
)
{
return
convert
(
codepoint
.
toUpperCase
());
}
else
if
(
unicode_only
)
{
return
shortname
;
}
else
{
return
`<img class="emoji" draggable="false" alt="
${
shortname
}
" src="
${
_converse
.
emojis_map
[
shortname
].
url
}
">`
;
}
});
// Also replace ASCII smileys
str
=
str
.
replace
(
ASCII_REPLACE_REGEX
,
(
entire
,
m1
,
m2
,
m3
)
=>
{
if
(
(
typeof
m3
===
'
undefined
'
)
||
(
m3
===
''
)
||
(
!
(
u
.
unescapeHTML
(
m3
)
in
ASCII_LIST
))
)
{
// if the ascii doesnt exist just return the entire match
return
entire
;
}
m3
=
u
.
unescapeHTML
(
m3
);
const
unicode
=
ASCII_LIST
[
m3
].
toUpperCase
();
return
m2
+
convert
(
unicode
);
});
return
str
;
str
=
convertASCII2Emoji
(
str
);
return
addEmojisMarkup
(
str
,
unicode_only
);
},
/**
* Returns unicode represented by the passed in shortname.
* @method u.shortnameToUnicode
* @param {string} str - String containg the shortname(s)
* @param {string} str - String contain
in
g the shortname(s)
*/
shortnameToUnicode
(
str
)
{
return
this
.
shortnamesToEmojis
(
str
,
true
)
;
return
u
.
shortnamesToEmojis
(
str
,
true
)[
0
]
;
},
/**
...
...
@@ -290,7 +329,7 @@ converse.plugins.add('converse-emoji', {
_converse
.
emoji_shortnames
=
_converse
.
emojis_list
.
map
(
m
=>
m
.
sn
);
const
getShortNames
=
()
=>
_converse
.
emoji_shortnames
.
map
(
s
=>
s
.
replace
(
/
[
+
]
/g
,
"
\\
$&
"
)).
join
(
'
|
'
);
_converse
.
emojis
.
shortnames_regex
=
new
RegExp
(
"
<object[^>]*>.*?<
\
/object>|<span[^>]*>.*?<
\
/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(
"
+
getShortNames
()
+
"
)
"
,
"
gi
"
);
shortnames_regex
=
new
RegExp
(
getShortNames
()
,
"
gi
"
);
_converse
.
emojis
.
toned
=
getTonedEmojis
();
_converse
.
emojis
.
initialized
.
resolve
();
...
...
src/headless/converse-muc.js
View file @
be20b8e1
...
...
@@ -964,8 +964,6 @@ converse.plugins.add('converse-muc', {
if
(
!
raw_mentions
)
return
[
original_message
,
[]];
const
known_nicknames
=
this
.
getAllKnownNicknames
();
const
known_nicknames_with_at_regex
=
this
.
getAllKnownNicknamesRegex
();
const
getMatchesForNickRegex
=
nick_regex
=>
[...
findRegexInMessage
(
nick_regex
)];
const
getMatchingNickname
=
p
.
findFirstMatchInArray
(
known_nicknames
);
const
uriFromNickname
=
nickname
=>
{
...
...
@@ -985,7 +983,7 @@ converse.plugins.add('converse-muc', {
return
{
begin
,
end
,
value
,
type
,
uri
}
}
const
mentions
=
getMatchesForNickRegex
(
known_nicknames_with_at_regex
)
;
const
mentions
=
[...
findRegexInMessage
(
this
.
getAllKnownNicknamesRegex
())]
;
const
references
=
mentions
.
map
(
matchToReference
);
const
[
updated_message
,
updated_references
]
=
p
.
reduceTextFromReferences
(
...
...
src/headless/emojis.json
View file @
be20b8e1
{
"custom"
:
{
":converse:"
:{
"sn"
:
":converse:"
,
"url"
:
"/dist/custom_emojis/converse.png"
,
"c"
:
"custom"
},
":xmpp:"
:{
"sn"
:
":xmpp:"
,
"url"
:
"/dist/custom_emojis/xmpp.png"
,
"c"
:
"custom"
}
":converse:"
:{
"sn"
:
":converse:"
,
"url"
:
"/dist/
images/
custom_emojis/converse.png"
,
"c"
:
"custom"
},
":xmpp:"
:{
"sn"
:
":xmpp:"
,
"url"
:
"/dist/
images/
custom_emojis/xmpp.png"
,
"c"
:
"custom"
}
},
"smileys"
:
{
":smiley:"
:{
"sn"
:
":smiley:"
,
"cp"
:
"1f603"
,
"sns"
:[],
"c"
:
"smileys"
},
...
...
src/templates/directives/body.js
View file @
be20b8e1
...
...
@@ -30,12 +30,12 @@ class MessageBodyRenderer extends String {
text
=
text
.
replace
(
/
\n\n
+/g
,
'
\n\n
'
);
text
=
u
.
geoUriToHttp
(
text
,
_converse
.
geouri_replacement
);
const
process
=
(
text
)
=>
{
text
=
u
.
addEmoji
(
text
);
return
addMentionsMarkup
(
text
,
this
.
model
.
get
(
'
references
'
),
this
.
model
.
collection
.
chatbox
);
}
const
list
=
await
Promise
.
all
(
u
.
addHyperlinks
(
text
));
this
.
list
=
list
.
reduce
((
acc
,
i
)
=>
isString
(
i
)
?
[...
acc
,
...
proces
s
(
i
)]
:
[...
acc
,
i
],
[]);
let
list
=
await
Promise
.
all
(
u
.
addHyperlinks
(
text
));
list
=
list
.
reduce
((
acc
,
i
)
=>
isString
(
i
)
?
[...
acc
,
...
u
.
addEmoji
(
i
)]
:
[...
acc
,
i
],
[]
);
const
addMentions
=
text
=>
addMentionsMarkup
(
text
,
this
.
model
.
get
(
'
references
'
),
this
.
model
.
collection
.
chatbox
)
list
=
list
.
reduce
((
acc
,
i
)
=>
isString
(
i
)
?
[...
acc
,
...
addMention
s
(
i
)]
:
[...
acc
,
i
],
[]);
/**
* Synchronous event which provides a hook for transforming a chat message's body text
* after the default transformations have been applied.
...
...
@@ -45,8 +45,7 @@ class MessageBodyRenderer extends String {
* @example _converse.api.listen.on('afterMessageBodyTransformed', (view, text) => { ... });
*/
await
api
.
trigger
(
'
afterMessageBodyTransformed
'
,
this
.
model
,
text
,
{
'
Synchronous
'
:
true
});
return
this
.
list
;
return
list
;
}
async
render
()
{
...
...
src/templates/emoji_picker.js
View file @
be20b8e1
import
{
html
}
from
"
lit-html
"
;
import
{
__
}
from
'
@converse/headless/i18n
'
;
import
{
unsafeHTML
}
from
'
lit-html/directives/unsafe-html.js
'
;
import
xss
from
"
xss/dist/xss
"
;
const
i18n_search
=
__
(
'
Search
'
);
...
...
@@ -10,7 +8,6 @@ const skintones = ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'];
const
emoji_category
=
(
o
)
=>
{
const
category_emoji
=
unsafeHTML
(
xss
.
filterXSS
(
o
.
transformCategory
(
o
.
emoji_categories
[
o
.
category
]),
{
'
whiteList
'
:
{
'
img
'
:
[
'
class
'
,
'
draggable
'
,
'
alt
'
,
'
src
'
,
'
title
'
]}}));
return
html
`
<li data-category="
${
o
.
category
}
"
class="emoji-category
${
o
.
category
}
${(
o
.
current_category
===
o
.
category
)
?
'
picked
'
:
''
}
"
...
...
@@ -19,7 +16,7 @@ const emoji_category = (o) => {
<a class="pick-category"
@click=
${
o
.
onCategoryPicked
}
href="#emoji-picker-
${
o
.
category
}
"
data-category="
${
o
.
category
}
">
${
category_emoji
}
</a>
data-category="
${
o
.
category
}
">
${
o
.
transformCategory
(
o
.
emoji_categories
[
o
.
category
])
}
</a>
</li>
`
;
}
...
...
@@ -30,12 +27,10 @@ const emoji_picker_header = (o) => html`
</ul>
`
;
const
emoji_item
=
(
o
)
=>
{
const
emoji
=
unsafeHTML
(
xss
.
filterXSS
(
o
.
transform
(
o
.
emoji
.
sn
),
{
'
whiteList
'
:
{
'
img
'
:
[
'
class
'
,
'
draggable
'
,
'
alt
'
,
'
src
'
,
'
title
'
]}}));
return
html
`
<li class="emoji insert-emoji
${
o
.
shouldBeHidden
(
o
.
emoji
.
sn
)
?
'
hidden
'
:
''
}
" data-emoji="
${
o
.
emoji
.
sn
}
" title="
${
o
.
emoji
.
sn
}
">
<a href="#" @click=
${
o
.
onEmojiPicked
}
data-emoji="
${
o
.
emoji
.
sn
}
">
${
emoji
}
</a>
<a href="#" @click=
${
o
.
onEmojiPicked
}
data-emoji="
${
o
.
emoji
.
sn
}
">
${
o
.
transform
(
o
.
emoji
.
sn
)
}
</a>
</li>
`
;
}
...
...
@@ -58,11 +53,9 @@ const emojis_for_category = (o) => html`
const
skintone_emoji
=
(
o
)
=>
{
const
shortname
=
'
:
'
+
o
.
skintone
+
'
:
'
;
const
emoji
=
unsafeHTML
(
xss
.
filterXSS
(
o
.
transform
(
shortname
),
{
'
whiteList
'
:
{
'
img
'
:
[
'
class
'
,
'
draggable
'
,
'
alt
'
,
'
src
'
,
'
title
'
]}}));
return
html
`
<li data-skintone="
${
o
.
skintone
}
" class="emoji-skintone
${(
o
.
current_skintone
===
o
.
skintone
)
?
'
picked
'
:
''
}
">
<a class="pick-skintone" href="#" data-skintone="
${
o
.
skintone
}
" @click=
${
o
.
onSkintonePicked
}
>
${
emoji
}
</a>
<a class="pick-skintone" href="#" data-skintone="
${
o
.
skintone
}
" @click=
${
o
.
onSkintonePicked
}
>
${
o
.
transform
(
'
:
'
+
o
.
skintone
+
'
:
'
)
}
</a>
</li>
`
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment