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
e6e23a1a
Commit
e6e23a1a
authored
Oct 16, 2019
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add initial support for custom emojis
parent
2ed8b466
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
823 additions
and
693 deletions
+823
-693
CHANGES.md
CHANGES.md
+3
-0
Makefile
Makefile
+1
-1
dist/custom_emojis/converse.png
dist/custom_emojis/converse.png
+0
-0
dist/custom_emojis/xmpp.png
dist/custom_emojis/xmpp.png
+0
-0
docs/source/configuration.rst
docs/source/configuration.rst
+57
-0
locale/af/LC_MESSAGES/converse.po
locale/af/LC_MESSAGES/converse.po
+557
-546
sass/_emoji.scss
sass/_emoji.scss
+100
-95
spec/emojis.js
spec/emojis.js
+1
-1
spec/messages.js
spec/messages.js
+3
-2
src/headless/converse-core.js
src/headless/converse-core.js
+22
-0
src/headless/converse-emoji.js
src/headless/converse-emoji.js
+55
-22
src/headless/converse-muc.js
src/headless/converse-muc.js
+2
-11
src/headless/emojis.json
src/headless/emojis.json
+4
-1
src/templates/emojis.html
src/templates/emojis.html
+15
-10
webpack.common.js
webpack.common.js
+1
-2
webpack.serve.js
webpack.serve.js
+2
-2
No files found.
CHANGES.md
View file @
e6e23a1a
...
...
@@ -6,6 +6,9 @@
-
#1691 Fix
`collection.chatbox is undefined`
errors
-
#1733 New message notifications for a minimized chat stack on top of each other
-
Prevent editing of sent file uploads.
-
Initial support for sending custom emojis. Currently only between Converse
instances. Still working out a wire protocol for compatibility with other clients.
To add custom emojis, edit the
`emojis.json`
file.
### Breaking changes
...
...
Makefile
View file @
e6e23a1a
...
...
@@ -68,7 +68,7 @@ serve_bg: stamp-npm
dist/converse-no-dependencies.js
:
src webpack.common.js webpack.nodeps.js stamp-npm @converse/headless
npm run nodeps
GETTEXT
=
$(XGETTEXT)
--from-code
=
UTF-8
--language
=
JavaScript
--keyword
=
__
-keyword
=
___
--force-po
--output
=
locale/converse.pot
--package-name
=
Converse.js
--copyright-holder
=
"Jan-Carel Brand"
--package-version
=
5.0.4 dist/converse-no-dependencies.js
-c
GETTEXT
=
$(XGETTEXT)
--from-code
=
UTF-8
--language
=
JavaScript
--keyword
=
__
-
-
keyword
=
___
--force-po
--output
=
locale/converse.pot
--package-name
=
Converse.js
--copyright-holder
=
"Jan-Carel Brand"
--package-version
=
5.0.4 dist/converse-no-dependencies.js
-c
.PHONY
:
pot
pot
:
dist/converse-no-dependencies.js
...
...
dist/custom_emojis/converse.png
0 → 100644
View file @
e6e23a1a
6.6 KB
dist/custom_emojis/xmpp.png
0 → 100644
View file @
e6e23a1a
8.56 KB
docs/source/configuration.rst
View file @
e6e23a1a
...
...
@@ -664,6 +664,63 @@ domain_placeholder
The placeholder text shown in the domain input on the registration form.
emoji_categories
----------------
* Default:::
{
"smileys": ":grinning:",
"people": ":thumbsup:",
"activity": ":soccer:",
"travel": ":motorcycle:",
"objects": ":bomb:",
"nature": ":rainbow:",
"food": ":hotdog:",
"symbols": ":musical_note:",
"flags": ":flag_ac:",
"custom": ":converse:"
}
This setting lets you define the categories that are available in the emoji
picker, as well as the default image that's shown for each category.
The keys of the map are the categories and the values are the shortnames of the
representative images.
If you want to remove a category, don't just remove the key, instead set its
value to ``undefined``.
Due to restrictions intended to prevent addition of undeclared configuration
settings, it's not possible to add new emoji categories. There is however a
``custom`` category where you can put your own custom emojis (also known as
"stickers").
To add custom emojis, you need to edit ``src/headless/emojis.json`` to add new
entries to the map under the ``custom`` key.
emoji_categories_label
----------------------
* Default:::
{
"smileys": "Smileys and emotions",
"people": "People",
"activity": "Activities",
"travel": "Travel",
"objects": "Objects",
"nature": "Animals and nature",
"food": "Food and drink",
"symbols": "Symbols",
"flags": "Flags",
"custom": "Stickers"
}
This setting lets you pass in the text value that goes into the `title`
attribute for the emoji categories. These strings will be translated, but for
your custom text to be translatable, you'll need to wrap it in `__()``
somewhere in your own code.
emoji_image_path
----------------
...
...
locale/af/LC_MESSAGES/converse.po
View file @
e6e23a1a
This diff is collapsed.
Click to expand it.
sass/_emoji.scss
View file @
e6e23a1a
...
...
@@ -7,100 +7,103 @@
vertical-align
:
-0
.1em
;
}
.toggle-smiley
{
a
.toggle-smiley
{
padding
:
0
;
}
.emoji-picker.toolbar-menu
{
padding-top
:
0
;
padding-bottom
:
0
;
background-color
:
var
(
--
chat-head-color
);
.emoji-picker__container
{
display
:
flex
;
flex-direction
:
column
;
overflow-y
:
hidden
;
background
:
white
;
.emoji-picker__lists
{
height
:
100%
;
overflow-y
:
auto
;
.emoji-category__heading
{
cursor
:
auto
;
color
:
var
(
--
subdued-color
);
font-size
:
var
(
--
font-size
);
padding
:
0
.5em
0
0
0
.5em
;
}
.sendXMPPMessage
{
.toggle-smiley
{
a
.toggle-smiley
{
padding
:
0
;
}
.emoji-picker.toolbar-menu
{
min-width
:
23rem
;
padding-top
:
0
;
padding-bottom
:
0
;
background-color
:
var
(
--
chat-head-color
);
.emoji-picker__container
{
display
:
flex
;
flex-direction
:
column
;
}
.emoji-skintone-picker
{
display
:
flex
;
label
{
margin
:
0
;
padding
:
0
0
.5em
;
white-space
:
nowrap
;
font-size
:
var
(
--
font-size-small
);
color
:
var
(
--
heading-color
);
overflow-y
:
hidden
;
background
:
white
;
.emoji-picker__lists
{
height
:
100%
;
overflow-y
:
auto
;
.emoji-category__heading
{
cursor
:
auto
;
color
:
var
(
--
subdued-color
);
font-size
:
var
(
--
font-size
);
padding
:
0
.5em
0
0
0
.5em
;
}
display
:
flex
;
flex-direction
:
column
;
}
li
{
padding
:
0
0
.25em
;
.emoji-skintone-picker
{
display
:
flex
;
label
{
margin
:
0
;
padding
:
0
0
.5em
;
white-space
:
nowrap
;
font-size
:
var
(
--
font-size-small
);
color
:
var
(
--
heading-color
);
}
li
{
padding
:
0
0
.25em
;
}
padding
:
0
.5em
0
;
background-color
:
var
(
--
chat-head-color
);
width
:
auto
;
font-size
:
var
(
--
font-size
);
}
padding
:
0
.5em
0
;
background-color
:
var
(
--
chat-head-color
);
width
:
auto
;
font-size
:
var
(
--
font-size
);
}
}
.emoji-picker
{
background-color
:
white
;
padding
:
0
.5em
;
li
{
margin-left
:
0
;
cursor
:
pointer
;
list-style
:
none
;
position
:
relative
;
&
.insert-emoji
{
margin
:
0
;
height
:
32px
;
width
:
32px
;
.emoji-picker
{
background-color
:
white
;
padding
:
0
.5em
;
li
{
margin-left
:
0
;
cursor
:
pointer
;
list-style
:
none
;
position
:
relative
;
&
.insert-emoji
{
margin
:
0
;
height
:
32px
;
width
:
32px
;
&
.picked
{
background-color
:
var
(
--
highlight-color
);
}
a
{
&
:hover
{
&
.picked
{
background-color
:
var
(
--
highlight-color
);
}
font-size
:
var
(
--
font-size-huge
);
a
{
&
:hover
{
background-color
:
var
(
--
highlight-color
);
}
font-size
:
var
(
--
font-size-huge
);
}
}
}
}
}
.emoji-picker__header
{
display
:
flex
;
flex-direction
:
column
;
padding-top
:
0
.5em
;
background-color
:
var
(
--
chat-head-color
);
.emoji-search
{
width
:
auto
;
margin
:
0
.25em
;
height
:
2em
;
font-size
:
var
(
--
font-size-small
);
}
ul
{
.emoji-picker__header
{
display
:
flex
;
flex-direction
:
row
;
justify-content
:
space-between
;
flex-direction
:
column
;
padding-top
:
0
.5em
;
background-color
:
var
(
--
chat-head-color
);
.emoji-search
{
width
:
auto
;
margin
:
0
.25em
;
height
:
2em
;
font-size
:
var
(
--
font-size-small
);
}
ul
{
display
:
flex
;
flex-direction
:
row
;
justify-content
:
space-between
;
.emoji-category
{
&
.picked
{
background-color
:
white
;
border
:
1px
var
(
--
chat-head-color
)
solid
;
border-bottom
:
none
;
}
padding
:
0
.25em
;
font-size
:
var
(
--
font-size-huge
);
&
:hover
{
background-color
:
var
(
--
highlight-color
);
.emoji-category
{
&
.picked
{
background-color
:
white
;
border
:
1px
var
(
--
chat-head-color
)
solid
;
border-bottom
:
none
;
}
padding
:
0
.25em
;
font-size
:
var
(
--
font-size-huge
);
&
:hover
{
background-color
:
var
(
--
highlight-color
);
}
}
}
}
...
...
@@ -110,20 +113,22 @@
}
.chatroom
{
.toggle-smiley
{
.emoji-picker.toolbar-menu
{
background-color
:
var
(
--
chatroom-head-color
);
.emoji-picker__container
{
background
:
white
;
.emoji-skintone-picker
{
background-color
:
var
(
--
chatroom-head-color
);
}
.emoji-picker__header
{
background-color
:
var
(
--
chatroom-head-color
);
.emoji-category
{
&
.picked
{
border
:
1px
var
(
--
chatroom-head-color
)
solid
;
border-bottom
:
none
;
.sendXMPPMessage
{
.toggle-smiley
{
.emoji-picker.toolbar-menu
{
background-color
:
var
(
--
chatroom-head-color
);
.emoji-picker__container
{
background
:
white
;
.emoji-skintone-picker
{
background-color
:
var
(
--
chatroom-head-color
);
}
.emoji-picker__header
{
background-color
:
var
(
--
chatroom-head-color
);
.emoji-category
{
&
.picked
{
border
:
1px
var
(
--
chatroom-head-color
)
solid
;
border-bottom
:
none
;
}
}
}
}
...
...
spec/emojis.js
View file @
e6e23a1a
...
...
@@ -121,7 +121,7 @@
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
view
.
el
.
querySelector
(
'
.toggle-smiley .emoji-picker__container
'
)));
const
picker
=
await
u
.
waitUntil
(()
=>
view
.
el
.
querySelector
(
'
.toggle-smiley .emoji-picker__container
'
));
const
input
=
picker
.
querySelector
(
'
.emoji-search
'
);
expect
(
sizzle
(
'
.insert-emoji:not(.hidden)
'
,
picker
).
length
).
toBe
(
15
89
);
expect
(
sizzle
(
'
.insert-emoji:not(.hidden)
'
,
picker
).
length
).
toBe
(
15
91
);
expect
(
view
.
emoji_picker_view
.
model
.
get
(
'
query
'
)).
toBeUndefined
();
input
.
value
=
'
smiley
'
;
...
...
spec/messages.js
View file @
e6e23a1a
...
...
@@ -1026,9 +1026,10 @@
// Non-https images aren't rendered
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
];
message
=
base_url
+
"
/logo/conversejs-filled.svg
"
;
expect
(
view
.
el
.
querySelectorAll
(
'
img
'
).
length
).
toBe
(
4
);
const
chat_content
=
view
.
el
.
querySelector
(
'
.chat-content
'
);
expect
(
chat_content
.
querySelectorAll
(
'
img
'
).
length
).
toBe
(
4
);
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
el
.
querySelectorAll
(
'
img
'
).
length
).
toBe
(
4
);
expect
(
chat_content
.
querySelectorAll
(
'
img
'
).
length
).
toBe
(
4
);
done
();
}));
...
...
src/headless/converse-core.js
View file @
e6e23a1a
...
...
@@ -313,6 +313,28 @@ _converse.__ = function (str) {
return
i18n
.
translate
.
apply
(
i18n
,
arguments
);
};
/**
* A no-op method which is used to signal to gettext that the passed in string
* should be included in the pot translation file.
*
* In contrast to the double-underscore method, the triple underscore method
* doesn't actually translate the strings.
*
* One reason for this method might be because we're using strings we cannot
* send to the translation function because they require variable interpolation
* and we don't yet have the variables at scan time.
*
* @method ___
* @private
* @memberOf _converse
* @param { String } str
*/
_converse
.
___
=
function
(
str
)
{
return
str
;
}
const
__
=
_converse
.
__
;
const
PROMISES
=
[
...
...
src/headless/converse-emoji.js
View file @
e6e23a1a
...
...
@@ -10,7 +10,7 @@ import * as twemoji from "twemoji";
import
_
from
"
./lodash.noconflict
"
;
import
converse
from
"
./converse-core
"
;
const
{
Backbone
,
}
=
converse
.
env
;
const
{
Backbone
}
=
converse
.
env
;
const
u
=
converse
.
env
.
utils
;
const
ASCII_LIST
=
{
...
...
@@ -166,7 +166,7 @@ converse.plugins.add('converse-emoji', {
* loaded by converse.js's plugin machinery.
*/
const
{
_converse
}
=
this
;
const
{
__
}
=
_converse
;
const
{
__
_
}
=
_converse
;
_converse
.
api
.
settings
.
update
({
'
emoji_image_path
'
:
twemoji
.
default
.
base
,
...
...
@@ -179,23 +179,32 @@ converse.plugins.add('converse-emoji', {
"
nature
"
:
"
:rainbow:
"
,
"
food
"
:
"
:hotdog:
"
,
"
symbols
"
:
"
:musical_note:
"
,
"
flags
"
:
"
:flag_ac:
"
"
flags
"
:
"
:flag_ac:
"
,
"
custom
"
:
"
:converse:
"
},
// We use the triple-underscore method which doesn't actually
// translate but does signify to gettext that these strings should
// go into the POT file. The translation then happens in the
// template. We do this so that users can pass in their own
// strings via converse.initialize, which is before __ is
// available.
'
emoji_category_labels
'
:
{
"
smileys
"
:
___
(
"
Smileys and emotions
"
),
"
people
"
:
___
(
"
People
"
),
"
activity
"
:
___
(
"
Activities
"
),
"
travel
"
:
___
(
"
Travel
"
),
"
objects
"
:
___
(
"
Objects
"
),
"
nature
"
:
___
(
"
Animals and nature
"
),
"
food
"
:
___
(
"
Food and drink
"
),
"
symbols
"
:
___
(
"
Symbols
"
),
"
flags
"
:
___
(
"
Flags
"
),
"
custom
"
:
___
(
"
Stickers
"
)
}
});
_converse
.
api
.
promises
.
add
([
'
emojisInitialized
'
]);
twemoji
.
default
.
base
=
_converse
.
emoji_image_path
;
_converse
.
emoji_category_labels
=
{
"
smileys
"
:
__
(
"
Smileys and emotions
"
),
"
people
"
:
__
(
"
People
"
),
"
activity
"
:
__
(
"
Activities
"
),
"
travel
"
:
__
(
"
Travel
"
),
"
objects
"
:
__
(
"
Objects
"
),
"
nature
"
:
__
(
"
Animals and nature
"
),
"
food
"
:
__
(
"
Food and drink
"
),
"
symbols
"
:
__
(
"
Symbols
"
),
"
flags
"
:
__
(
"
Flags
"
)
}
/**
* Model for storing data related to the Emoji picker widget
...
...
@@ -253,28 +262,43 @@ converse.plugins.add('converse-emoji', {
*/
getEmojiRenderer
()
{
const
how
=
{
'
attributes
'
:
(
icon
)
=>
{
'
attributes
'
:
icon
=>
{
const
codepoint
=
twemoji
.
default
.
convert
.
toCodePoint
(
icon
);
return
{
'
title
'
:
`
${
u
.
getEmojisByAtrribute
(
'
cp
'
)[
codepoint
][
'
sn
'
]}
${
icon
}
`
}
}
};
const
t
oUnicode
=
u
.
shortnameToUnicode
;
return
_converse
.
use_system_emojis
?
t
oUnicode
:
text
=>
twemoji
.
default
.
parse
(
toUnicode
(
text
),
how
);
const
t
ransform
=
u
.
shortnamesToEmojis
;
return
_converse
.
use_system_emojis
?
t
ransform
:
text
=>
twemoji
.
default
.
parse
(
transform
(
text
),
how
);
},
/**
* Returns unicode represented by the passed in shortname.
* @method u.shortnameToUnicode
* 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.
*
* 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)
*/
shortname
ToUnicode
(
str
)
{
shortname
sToEmojis
(
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
unicode
=
_converse
.
emojis_map
[
shortname
].
cp
.
toUpperCase
();
return
convert
(
unicode
);
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
)
=>
{
...
...
@@ -289,6 +313,15 @@ converse.plugins.add('converse-emoji', {
return
str
;
},
/**
* Returns unicode represented by the passed in shortname.
* @method u.shortnameToUnicode
* @param {string} str - String containg the shortname(s)
*/
shortnameToUnicode
(
str
)
{
return
this
.
shortnamesToEmojis
(
str
,
true
);
},
/**
* Determines whether the passed in string is just a single emoji shortname;
* @method u.isSingleEmoji
...
...
src/headless/converse-muc.js
View file @
e6e23a1a
...
...
@@ -100,8 +100,8 @@ converse.plugins.add('converse-muc', {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const
{
_converse
}
=
this
,
{
__
}
=
_converse
;
const
{
_converse
}
=
this
;
const
{
__
,
_
__
}
=
_converse
;
// Configuration values for this plugin
// ====================================
...
...
@@ -128,15 +128,6 @@ converse.plugins.add('converse-muc', {
}
function
___
(
str
)
{
/* This is part of a hack to get gettext to scan strings to be
* translated. Strings we cannot send to the function above because
* they require variable interpolation and we don't yet have the
* variables at scan time.
*/
return
str
;
}
/* https://xmpp.org/extensions/xep-0045.html
* ----------------------------------------
* 100 message Entering a groupchat Inform user that any occupant is allowed to see the user's full JID
...
...
src/headless/emojis.json
View file @
e6e23a1a
{
"custom"
:
{
":converse:"
:{
"sn"
:
":converse:"
,
"url"
:
"/dist/custom_emojis/converse.png"
,
"c"
:
"custom"
},
":xmpp:"
:{
"sn"
:
":xmpp:"
,
"url"
:
"/dist/custom_emojis/xmpp.png"
,
"c"
:
"custom"
}
},
"smileys"
:
{
":smiley:"
:{
"sn"
:
":smiley:"
,
"cp"
:
"1f603"
,
"sns"
:[],
"c"
:
"smileys"
},
":smile:"
:{
"sn"
:
":smile:"
,
"cp"
:
"1f604"
,
"sns"
:[],
"c"
:
"smileys"
},
...
...
@@ -2692,4 +2696,3 @@
":tone5:"
:{
"sn"
:
":tone5:"
,
"cp"
:
"1f3ff"
,
"sns"
:[],
"c"
:
"modifier"
}
}
}
src/templates/emojis.html
View file @
e6e23a1a
...
...
@@ -4,9 +4,12 @@
{[ if (!o.query) { ]}
<ul>
{[ Object.keys(o.emoji_categories).forEach(function (category) { ]}
<li
data-category=
"{{{category}}}"
class=
"emoji-category {{{o.current_category}}} {{{ category}}} {[ if (o.current_category === category) { ]} picked {[ } ]}"
title=
"{{{o._converse.emoji_category_labels[category]}}}"
>
{[ if (o.emoji_categories[category]) { ]}
<li
data-category=
"{{{category}}}"
class=
"emoji-category {{{o.current_category}}} {{{ category}}} {[ if (o.current_category === category) { ]} picked {[ } ]}"
title=
"{{{ o.__(o._converse.emoji_category_labels[category]) }}}"
>
<a
class=
"pick-category"
href=
"#emoji-picker-{{{category}}}"
data-category=
"{{{category}}}"
>
{{ o.transformCategory(o.emoji_categories[category]) }}
</a>
</li>
{[ } ]}
{[ }); ]}
</ul>
{[ } ]}
...
...
@@ -24,15 +27,17 @@
</ul>
{[ } else { ]}
{[ Object.keys(o.emoji_categories).forEach(function (category) { ]}
<a
id=
"emoji-picker-{{{category}}}"
class=
"emoji-category__heading"
data-category=
"{{{category}}}"
>
{{{o._converse.emoji_category_labels[category]}}}
</a>
<ul
class=
"emoji-picker"
data-category=
"{{{category}}}"
>
{[ Object.values(o.emojis_by_category[category]).forEach(function (emoji) { ]}
<li
class=
"emoji insert-emoji {[ if (o.shouldBeHidden(emoji.sn)) { ]} hidden {[ }; ]}"
data-emoji=
"{{{emoji.sn}}}"
title=
"{{{emoji.sn}}}"
>
<a
href=
"#"
data-emoji=
"{{{emoji.sn}}}"
>
{{ o.transform(emoji.sn) }}
</a>
</li>
{[ }); ]}
</ul>
{[ if (o.emoji_categories[category]) { ]}
<a
id=
"emoji-picker-{{{category}}}"
class=
"emoji-category__heading"
data-category=
"{{{category}}}"
>
{{{ o.__(o._converse.emoji_category_labels[category]) }}}
</a>
<ul
class=
"emoji-picker"
data-category=
"{{{category}}}"
>
{[ Object.values(o.emojis_by_category[category]).forEach(function (emoji) { ]}
<li
class=
"emoji insert-emoji {[ if (o.shouldBeHidden(emoji.sn)) { ]} hidden {[ }; ]}"
data-emoji=
"{{{emoji.sn}}}"
title=
"{{{emoji.sn}}}"
>
<a
href=
"#"
data-emoji=
"{{{emoji.sn}}}"
>
{{ o.transform(emoji.sn) }}
</a>
</li>
{[ }); ]}
</ul>
{[ } ]}
{[ }); ]}
{[ } ]}
</div>
...
...
webpack.common.js
View file @
e6e23a1a
/* global __dirname, module
, process
*/
/* global __dirname, module */
const
path
=
require
(
'
path
'
);
const
webpack
=
require
(
'
webpack
'
);
module
.
exports
=
{
output
:
{
...
...
webpack.serve.js
View file @
e6e23a1a
...
...
@@ -7,11 +7,11 @@ module.exports = merge(common, {
mode
:
"
development
"
,
devtool
:
"
inline-source-map
"
,
devServer
:
{
contentBase
:
"
./
dist
"
contentBase
:
"
./
"
},
plugins
:
[
new
HTMLWebpackPlugin
({
title
:
'
Production
'
,
title
:
'
Converse.js Dev
'
,
template
:
'
webpack.html
'
})
],
...
...
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