Переглянути джерело

Replace moment with DayJS

JC Brand 6 роки тому
батько
коміт
c3dac272f8

+ 1 - 0
CHANGES.md

@@ -10,6 +10,7 @@
 - In the `/help` menu, only show allowed commands
 - Message deduplication bugfixes and improvements
 - Continuously retry (in 2s intervals) to fetch login credentials (via [credentials_url](https://conversejs.org/docs/html/configuration.html#credentials-url)) in case of failure
+- Replace `moment` with [DayJS](https://github.com/iamkun/dayjs).
 - #1296: `embedded` view mode shows `chatbox-navback` arrow in header
 - #1532: Converse reloads on enter pressed in the filter box
 - #1550: Legitimate carbons being blocked due to erroneous forgery check

Різницю між файлами не показано, бо вона завелика
+ 9 - 0
dist/converse.js


+ 5 - 3
docs/source/configuration.rst

@@ -1533,9 +1533,11 @@ time_format
 
 Examples: ``HH:mm``, ``hh:mm``, ``hh:mm a``.
 
-This option makes the time format for the time shown, for each message, configurable. Converse uses `moment.js <https://momentjs.com/>`_
-for showing time. This option allows the configuration of the format in which `moment` will display the time for the messages. For detailed
-description of time-format options available for `moment` you can check this `link <https://momentjs.com/docs/#/parsing/string-format/>`_.
+This option makes the time format for the time shown, for each message, configurable. Converse uses `DayJS <https://github.com/iamkun/dayjs>`_
+for showing time. This option allows the configuration of the format in which `DayJS` will display the time for the messages. For detailed
+description of time-format options available for `DayJS` you can check the
+`default formatting options <https://github.com/iamkun/dayjs/blob/dev/docs/en/API-reference.md#displaying>`_ and the
+`advanced options <https://github.com/iamkun/dayjs/blob/master/docs/en/Plugin.md#advancedformat>`_.
 
 use_otr_by_default
 ------------------

+ 1 - 1
docs/source/dependencies.rst

@@ -82,7 +82,7 @@ Brief description of Converse's dependencies
 
 Converse relies on the following dependencies:
 
-* `moment.js <http://momentjs.com/>`_ provides a better API for handling dates and times.
+* `DayJS <https://github.com/iamkun/dayjs>`_ provides a better API for handling dates and times.
 * `Strophe.js <http://strophe.im/>`_ maintains the XMPP session, is used to
   build XMPP stanzas, to send them, and to register handlers for received stanzas.
 * `lodash <https://lodash.com/>`_ provides very useful utility functions.

+ 3 - 3
docs/source/plugin_development.rst

@@ -180,7 +180,7 @@ Accessing 3rd party libraries
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Immediately inside the module shown above you can access 3rd party libraries (such
-moment and lodash) via the ``converse.env`` map.
+dayjs and lodash) via the ``converse.env`` map.
 
 The code for it would look something like this:
 
@@ -196,7 +196,7 @@ The code for it would look something like this:
         $build = converse.env.$build,
         b64_sha1 = converse.env.b64_sha1,
         _ = converse.env._,
-        moment = converse.env.moment;
+        dayjs = converse.env.dayjs;
 
 These dependencies are closured so that they don't pollute the global
 namespace, that's why you need to access them in such a way inside the module.
@@ -384,7 +384,7 @@ generated by `generator-conversejs <https://github.com/jcbrand/generator-convers
             $build = converse.env.$build,
             b64_sha1 = converse.env.b64_sha1,
             _ = converse.env._,
-            moment = converse.env.moment;
+            dayjs = converse.env.dayjs;
 
         // The following line registers your plugin.
         converse.plugins.add("myplugin", {

+ 5 - 6
package-lock.json

@@ -3774,6 +3774,11 @@
       "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==",
       "dev": true
     },
+    "dayjs": {
+      "version": "1.8.13",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.13.tgz",
+      "integrity": "sha512-JZ01l/PMU8OqwuUs2mOQ/CTekMtoXOUSylfjqjgDzbhRSxpFIrPnHn8Y8a0lfocNgAdBNZb8y0/gbzJ2riQ4WQ=="
+    },
     "debug": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
@@ -7722,12 +7727,6 @@
       "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==",
       "dev": true
     },
-    "moment": {
-      "version": "2.19.4",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.4.tgz",
-      "integrity": "sha512-1xFTAknSLfc47DIxHDUbnJWC+UwgWxATmymaxIPQpmMh7LBm7ZbwVEsuushqwL2GYZU0jie4xO+TK44hJPjNSQ==",
-      "dev": true
-    },
     "move-concurrently": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",

+ 3 - 1
package.json

@@ -69,7 +69,6 @@
     "long": "^3.1.0",
     "mini-css-extract-plugin": "^0.5.0",
     "minimist": "^1.2.0",
-    "moment": "~> 2.19.3 ",
     "node-sass": "^4.9.4",
     "npm": "^6.4.1",
     "pluggable.js": "2.0.0",
@@ -88,5 +87,8 @@
     "webpack": "^4.28.1",
     "webpack-cli": "^3.1.2",
     "xss": "^0.3.3"
+  },
+  "dependencies": {
+    "dayjs": "^1.8.13"
   }
 }

+ 7 - 7
spec/mam.js

@@ -7,7 +7,7 @@
     const Strophe = converse.env.Strophe;
     const $iq = converse.env.$iq;
     const $msg = converse.env.$msg;
-    const moment = converse.env.moment;
+    const dayjs = converse.env.dayjs;
     const u = converse.env.utils;
     // See: https://xmpp.org/rfcs/rfc3921.html
 
@@ -338,10 +338,10 @@
                                 `<value>urn:xmpp:mam:2</value>`+
                             `</field>`+
                             `<field var="start">`+
-                                `<value>${moment(start).toISOString()}</value>`+
+                                `<value>${dayjs(start).toISOString()}</value>`+
                             `</field>`+
                             `<field var="end">`+
-                                `<value>${moment(end).toISOString()}</value>`+
+                                `<value>${dayjs(end).toISOString()}</value>`+
                             `</field>`+
                             `</x>`+
                         `</query>`+
@@ -391,7 +391,7 @@
                                 `<value>urn:xmpp:mam:2</value>`+
                             `</field>`+
                             `<field var="start">`+
-                                `<value>${moment(start).toISOString()}</value>`+
+                                `<value>${dayjs(start).toISOString()}</value>`+
                             `</field>`+
                             `</x>`+
                         `</query>`+
@@ -424,7 +424,7 @@
                                     `<value>urn:xmpp:mam:2</value>`+
                                 `</field>`+
                                 `<field var="start">`+
-                                    `<value>${moment(start).toISOString()}</value>`+
+                                    `<value>${dayjs(start).toISOString()}</value>`+
                                 `</field>`+
                             `</x>`+
                             `<set xmlns="http://jabber.org/protocol/rsm">`+
@@ -464,7 +464,7 @@
                                     `<value>urn:xmpp:mam:2</value>`+
                                 `</field>`+
                                 `<field var="start">`+
-                                    `<value>${moment(start).toISOString()}</value>`+
+                                    `<value>${dayjs(start).toISOString()}</value>`+
                                 `</field>`+
                             `</x>`+
                             `<set xmlns="http://jabber.org/protocol/rsm">`+
@@ -541,7 +541,7 @@
                                     `<value>romeo@montague.lit</value>`+
                                 `</field>`+
                                 `<field var="start">`+
-                                    `<value>${moment(rsm.start).toISOString()}</value>`+
+                                    `<value>${dayjs(rsm.start).toISOString()}</value>`+
                                 `</field>`+
                             `</x>`+
                             `<set xmlns="http://jabber.org/protocol/rsm">`+

+ 15 - 17
spec/messages.js

@@ -6,7 +6,7 @@
         ], factory);
 } (this, function (jasmine, mock, test_utils) {
     "use strict";
-    const { Backbone, Promise, Strophe, $iq, $msg, $pres, b64_sha1, moment, sizzle, _ } = converse.env;
+    const { Backbone, Promise, Strophe, $iq, $msg, $pres, b64_sha1, dayjs, sizzle, _ } = converse.env;
     const u = converse.env.utils;
 
 
@@ -408,7 +408,7 @@
             expect(chat_content.querySelectorAll('.date-separator').length).toEqual(4);
 
             let day = sizzle('.date-separator:first', chat_content).pop();
-            expect(day.getAttribute('data-isodate')).toEqual(moment('2017-12-31T00:00:00').toISOString());
+            expect(day.getAttribute('data-isodate')).toEqual(dayjs('2017-12-31T00:00:00').toISOString());
 
             let time = sizzle('time:first', chat_content).pop();
             expect(time.textContent).toEqual('Sunday Dec 31st 2017')
@@ -424,7 +424,7 @@
             expect(time.textContent).toEqual("Monday Jan 1st 2018");
 
             day = sizzle('.date-separator:eq(1)', chat_content).pop();
-            expect(day.getAttribute('data-isodate')).toEqual(moment('2018-01-01T00:00:00').toISOString());
+            expect(day.getAttribute('data-isodate')).toEqual(dayjs('2018-01-01T00:00:00').toISOString());
             expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('Inbetween message');
 
             el = sizzle('.chat-msg:eq(1)', chat_content).pop();
@@ -439,7 +439,7 @@
             expect(time.textContent).toEqual("Tuesday Jan 2nd 2018");
 
             day = sizzle('.date-separator:nth(2)', chat_content).pop();
-            expect(day.getAttribute('data-isodate')).toEqual(moment('2018-01-02T00:00:00').toISOString());
+            expect(day.getAttribute('data-isodate')).toEqual(dayjs('2018-01-02T00:00:00').toISOString());
             expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('An earlier message on the next day');
 
             el = sizzle('.chat-msg:eq(3)', chat_content).pop();
@@ -452,7 +452,7 @@
             expect(u.hasClass('chat-msg--followup', el)).toBe(false);
 
             day = sizzle('.date-separator:last', chat_content).pop();
-            expect(day.getAttribute('data-isodate')).toEqual(moment().startOf('day').toISOString());
+            expect(day.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
             expect(day.nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('latest message');
             expect(u.hasClass('chat-msg--followup', el)).toBe(false);
             done();
@@ -719,8 +719,7 @@
             await test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length);
             await test_utils.openChatBoxFor(_converse, contact_jid);
             test_utils.clearChatBoxMessages(_converse, contact_jid);
-            const one_day_ago = moment();
-            one_day_ago.subtract('days', 1);
+            const one_day_ago = dayjs().subtract(1, 'day');
             const chatbox = _converse.chatboxes.get(contact_jid);
             const view = _converse.chatboxviews.get(contact_jid);
 
@@ -729,7 +728,7 @@
                 from: contact_jid,
                 to: _converse.connection.jid,
                 type: 'chat',
-                id: one_day_ago.unix()
+                id: one_day_ago.toDate().getTime()
             }).c('body').t(message).up()
             .c('delay', { xmlns:'urn:xmpp:delay', from: 'localhost', stamp: one_day_ago.toISOString() })
             .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
@@ -753,10 +752,10 @@
             expect(chat_content.querySelectorAll('.date-separator').length).toEqual(1);
             let day = chat_content.querySelector('.date-separator');
             expect(day.getAttribute('class')).toEqual('message date-separator');
-            expect(day.getAttribute('data-isodate')).toEqual(moment(one_day_ago.startOf('day')).toISOString());
+            expect(day.getAttribute('data-isodate')).toEqual(dayjs(one_day_ago.startOf('day')).toISOString());
 
             let time = chat_content.querySelector('time.separator-text');
-            expect(time.textContent).toEqual(moment(one_day_ago.startOf('day')).format("dddd MMM Do YYYY"));
+            expect(time.textContent).toEqual(dayjs(one_day_ago.startOf('day')).format("dddd MMM Do YYYY"));
 
             message = 'This is a current message';
             msg = $msg({
@@ -770,18 +769,17 @@
             await new Promise((resolve, reject) => view.once('messageInserted', resolve));
 
             expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
-            // Check that there is a <time> element, with the required
-            // props.
+            // Check that there is a <time> element, with the required props.
             expect(chat_content.querySelectorAll('time.separator-text').length).toEqual(2); // There are now two time elements
 
             const message_date = new Date();
             day = sizzle('.date-separator:last', chat_content);
             expect(day.length).toEqual(1);
             expect(day[0].getAttribute('class')).toEqual('message date-separator');
-            expect(day[0].getAttribute('data-isodate')).toEqual(moment(message_date).startOf('day').toISOString());
+            expect(day[0].getAttribute('data-isodate')).toEqual(dayjs(message_date).startOf('day').toISOString());
 
             time = sizzle('time.separator-text:last', chat_content).pop();
-            expect(time.textContent).toEqual(moment(message_date).startOf('day').format("dddd MMM Do YYYY"));
+            expect(time.textContent).toEqual(dayjs(message_date).startOf('day').format("dddd MMM Do YYYY"));
 
             // Normal checks for the 2nd message
             expect(chatbox.messages.length).toEqual(2);
@@ -1055,7 +1053,7 @@
             expect(msg_author.textContent.trim()).toBe('Max Mustermann');
 
             const msg_time = view.el.querySelector('.chat-content .chat-msg:last-child .chat-msg__time');
-            const time = moment(msg_object.get('time')).format(_converse.time_format);
+            const time = dayjs(msg_object.get('time')).format(_converse.time_format);
             expect(msg_time.textContent).toBe(time);
             done();
         }));
@@ -1159,7 +1157,7 @@
             _converse.chatboxes.onMessage($msg({'id': 'aeb218', 'to': _converse.bare_jid})
                 .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
                     .c('delay', {'xmlns': 'urn:xmpp:delay',
-                                    'stamp': moment(base_time).add(5, 'minutes').toISOString()
+                                    'stamp': dayjs(base_time).add(5, 'minutes').toISOString()
                                 }).up()
                     .c('message', {
                         'xmlns': 'jabber:client',
@@ -1190,7 +1188,7 @@
 
             _converse.chatboxes.onMessage($msg({'id': 'aeb213', 'to': _converse.bare_jid})
                 .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
-                    .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':moment(base_time).add(4, 'minutes').toISOString()}).up()
+                    .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':dayjs(base_time).add(4, 'minutes').toISOString()}).up()
                     .c('message', {
                         'xmlns': 'jabber:client',
                         'to': sender_jid,

+ 13 - 13
spec/muc.js

@@ -7,7 +7,7 @@
           $msg = converse.env.$msg,
           Strophe = converse.env.Strophe,
           Promise = converse.env.Promise,
-          moment = converse.env.moment,
+          dayjs = converse.env.dayjs,
           sizzle = converse.env.sizzle,
           Backbone = converse.env.Backbone,
           u = converse.env.utils;
@@ -969,8 +969,8 @@
                 let indicator = chat_content.querySelector('.date-separator');
                 expect(indicator).not.toBe(null);
                 expect(indicator.getAttribute('class')).toEqual('message date-separator');
-                expect(indicator.getAttribute('data-isodate')).toEqual(moment().startOf('day').toISOString());
-                expect(indicator.querySelector('time').textContent).toEqual(moment().startOf('day').format("dddd MMM Do YYYY"));
+                expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
+                expect(indicator.querySelector('time').textContent).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
                 expect(chat_content.querySelectorAll('div.chat-info').length).toBe(1);
                 expect(chat_content.querySelector('div.chat-info').textContent).toBe("dummy has entered the groupchat");
 
@@ -999,13 +999,13 @@
                     });
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
 
-                indicator = chat_content.querySelector('.date-separator[data-isodate="'+moment().startOf('day').toISOString()+'"]');
+                indicator = chat_content.querySelector('.date-separator[data-isodate="'+dayjs().startOf('day').toISOString()+'"]');
                 expect(indicator).not.toBe(null);
 
                 expect(indicator.getAttribute('class')).toEqual('message date-separator');
-                expect(indicator.getAttribute('data-isodate')).toEqual(moment().startOf('day').toISOString());
+                expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
                 expect(indicator.querySelector('time').getAttribute('class')).toEqual('separator-text');
-                expect(indicator.querySelector('time').textContent).toEqual(moment().startOf('day').format("dddd MMM Do YYYY"));
+                expect(indicator.querySelector('time').textContent).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
                 expect(chat_content.querySelectorAll('div.chat-info').length).toBe(2);
                 expect(chat_content.querySelector('div.chat-info:last-child').textContent).toBe(
                     "some1 has entered the groupchat"
@@ -1028,13 +1028,13 @@
                         });
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
 
-                indicator = chat_content.querySelector('.date-separator[data-isodate="'+moment().startOf('day').toISOString()+'"]');
+                indicator = chat_content.querySelector('.date-separator[data-isodate="'+dayjs().startOf('day').toISOString()+'"]');
 
                 expect(indicator).not.toBe(null);
                 expect(indicator.getAttribute('class')).toEqual('message date-separator');
-                expect(indicator.getAttribute('data-isodate')).toEqual(moment().startOf('day').toISOString());
+                expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
 
-                expect(indicator.querySelector('time').textContent).toEqual(moment().startOf('day').format("dddd MMM Do YYYY"));
+                expect(indicator.querySelector('time').textContent).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
                 expect(chat_content.querySelectorAll('div.chat-info').length).toBe(3);
                 expect(sizzle('div.chat-info:last', chat_content).pop().textContent).toBe(
                     'some1 has left the groupchat. '+
@@ -1069,8 +1069,8 @@
 
                 indicator = sizzle('.date-separator:eq(3)', chat_content).pop();
                 expect(indicator.getAttribute('class')).toEqual('message date-separator');
-                expect(indicator.getAttribute('data-isodate')).toEqual(moment().startOf('day').toISOString());
-                expect(indicator.querySelector('time').textContent).toEqual(moment().startOf('day').format("dddd MMM Do YYYY"));
+                expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
+                expect(indicator.querySelector('time').textContent).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
                 expect(chat_content.querySelectorAll('div.chat-info').length).toBe(4);
                 expect(sizzle('div.chat-info:last', chat_content).pop().textContent)
                     .toBe("newguy has entered the groupchat");
@@ -1109,8 +1109,8 @@
 
                 indicator = sizzle('.date-separator:eq(5)', chat_content).pop();
                 expect(indicator.getAttribute('class')).toEqual('message date-separator');
-                expect(indicator.getAttribute('data-isodate')).toEqual(moment().startOf('day').toISOString());
-                expect(indicator.querySelector('time').textContent).toEqual(moment().startOf('day').format("dddd MMM Do YYYY"));
+                expect(indicator.getAttribute('data-isodate')).toEqual(dayjs().startOf('day').toISOString());
+                expect(indicator.querySelector('time').textContent).toEqual(dayjs().startOf('day').format("dddd MMM Do YYYY"));
                 expect(chat_content.querySelectorAll('div.chat-info').length).toBe(5);
                 expect(sizzle('div.chat-info:last', chat_content).pop().textContent).toBe(
                     'newguy has left the groupchat. '+

+ 11 - 11
src/converse-chatview.js

@@ -28,7 +28,7 @@ import tpl_user_details_modal from "templates/user_details_modal.html";
 import u from "@converse/headless/utils/emoji";
 import xss from "xss";
 
-const { $msg, Backbone, Promise, Strophe, _, b64_sha1, f, sizzle, moment } = converse.env;
+const { $msg, Backbone, Promise, Strophe, _, b64_sha1, f, sizzle, dayjs } = converse.env;
 
 
 converse.plugins.add('converse-chatview', {
@@ -618,8 +618,8 @@ converse.plugins.add('converse-chatview', {
                 if (_.isNull(prev_msg_date) && _.isNull(next_msg_date)) {
                     return;
                 }
-                if (_.isNull(prev_msg_date) || moment(next_msg_date).isAfter(prev_msg_date, 'day')) {
-                    const day_date = moment(next_msg_date).startOf('day');
+                if (_.isNull(prev_msg_date) || dayjs(next_msg_date).isAfter(prev_msg_date, 'day')) {
+                    const day_date = dayjs(next_msg_date).startOf('day');
                     next_msg_el.insertAdjacentHTML('beforeBegin',
                         tpl_new_day({
                             'isodate': day_date.toISOString(),
@@ -640,7 +640,7 @@ converse.plugins.add('converse-chatview', {
             getLastMessageDate (cutoff) {
                 const first_msg = u.getFirstChildElement(this.content, '.message:not(.chat-state-notification)');
                 const oldest_date = first_msg ? first_msg.getAttribute('data-isodate') : null;
-                if (!_.isNull(oldest_date) && moment(oldest_date).isAfter(cutoff)) {
+                if (!_.isNull(oldest_date) && dayjs(oldest_date).isAfter(cutoff)) {
                     return null;
                 }
                 const last_msg = u.getLastChildElement(this.content, '.message:not(.chat-state-notification)');
@@ -648,8 +648,8 @@ converse.plugins.add('converse-chatview', {
                 if (_.isNull(most_recent_date)) {
                     return null;
                 }
-                if (moment(most_recent_date).isBefore(cutoff)) {
-                    return moment(most_recent_date).toDate();
+                if (dayjs(most_recent_date).isBefore(cutoff)) {
+                    return dayjs(most_recent_date).toDate();
                 }
                 /* XXX: We avoid .chat-state-notification messages, since they are
                  * temporary and get removed once a new element is
@@ -668,7 +668,7 @@ converse.plugins.add('converse-chatview', {
                 if (idx === 0) {
                     return null;
                 } else {
-                    return moment(msg_dates[idx-1]).toDate();
+                    return dayjs(msg_dates[idx-1]).toDate();
                 }
             },
 
@@ -733,7 +733,7 @@ converse.plugins.add('converse-chatview', {
                         return this.trigger('messageInserted', view.el);
                     }
                 }
-                const current_msg_date = moment(view.model.get('time')).toDate() || new Date(),
+                const current_msg_date = dayjs(view.model.get('time')).toDate() || new Date(),
                       previous_msg_date = this.getLastMessageDate(current_msg_date);
 
                 if (_.isNull(previous_msg_date)) {
@@ -770,12 +770,12 @@ converse.plugins.add('converse-chatview', {
             markFollowups (el) {
                 const from = el.getAttribute('data-from'),
                       previous_el = el.previousElementSibling,
-                      date = moment(el.getAttribute('data-isodate')),
+                      date = dayjs(el.getAttribute('data-isodate')),
                       next_el = el.nextElementSibling;
 
                 if (!u.hasClass('chat-msg--action', el) && !u.hasClass('chat-msg--action', previous_el) &&
                         previous_el.getAttribute('data-from') === from &&
-                        date.isBefore(moment(previous_el.getAttribute('data-isodate')).add(10, 'minutes')) &&
+                        date.isBefore(dayjs(previous_el.getAttribute('data-isodate')).add(10, 'minutes')) &&
                         el.getAttribute('data-encrypted') === previous_el.getAttribute('data-encrypted')) {
                     u.addClass('chat-msg--followup', el);
                 }
@@ -783,7 +783,7 @@ converse.plugins.add('converse-chatview', {
 
                 if (!u.hasClass('chat-msg--action', 'el') &&
                         next_el.getAttribute('data-from') === from &&
-                        moment(next_el.getAttribute('data-isodate')).isBefore(date.add(10, 'minutes')) &&
+                        dayjs(next_el.getAttribute('data-isodate')).isBefore(date.add(10, 'minutes')) &&
                         el.getAttribute('data-encrypted') === next_el.getAttribute('data-encrypted')) {
                     u.addClass('chat-msg--followup', next_el);
                 } else {

+ 2 - 2
src/converse-controlbox.js

@@ -19,7 +19,7 @@ import tpl_controlbox_toggle from "templates/controlbox_toggle.html";
 import tpl_login_panel from "templates/login_panel.html";
 
 const CHATBOX_TYPE = 'chatbox';
-const { Strophe, Backbone, Promise, _, moment } = converse.env;
+const { Strophe, Backbone, Promise, _, dayjs } = converse.env;
 const u = converse.env.utils;
 
 const CONNECTION_STATUS_CSS_CLASS = {
@@ -148,7 +148,7 @@ converse.plugins.add('converse-controlbox', {
 
             initialize () {
                 if (this.get('id') === 'controlbox') {
-                    this.set({'time_opened': moment(0).valueOf()});
+                    this.set({'time_opened': dayjs(0).valueOf()});
                 } else {
                     this.__super__.initialize.apply(this, arguments);
                 }

+ 1 - 1
src/converse-headline.js

@@ -8,7 +8,7 @@ import "converse-chatview";
 import converse from "@converse/headless/converse-core";
 import tpl_chatbox from "templates/chatbox.html";
 
-const { _, moment, utils } = converse.env;
+const { _, dayjs, utils } = converse.env;
 
 
 converse.plugins.add('converse-headline', {

+ 3 - 3
src/converse-message-view.js

@@ -16,7 +16,7 @@ import tpl_message_versions_modal from "templates/message_versions_modal.html";
 import u from "@converse/headless/utils/emoji";
 import xss from "xss";
 
-const { Backbone, _, moment } = converse.env;
+const { Backbone, _, dayjs } = converse.env;
 
 
 converse.plugins.add('converse-message-view', {
@@ -149,7 +149,7 @@ converse.plugins.add('converse-message-view', {
 
             async renderChatMessage () {
                 const is_me_message = this.isMeCommand(),
-                      time = moment(this.model.get('time')),
+                      time = dayjs(this.model.get('time')),
                       role = this.model.vcard ? this.model.vcard.get('role') : null,
                       roles = role ? role.split(',') : [];
 
@@ -204,7 +204,7 @@ converse.plugins.add('converse-message-view', {
                 const msg = u.stringToElement(
                     tpl_info(Object.assign(this.model.toJSON(), {
                         'extra_classes': 'chat-error',
-                        'isodate': moment(this.model.get('time')).toISOString()
+                        'isodate': dayjs(this.model.get('time')).toISOString()
                     }))
                 );
                 return this.replaceElement(msg);

+ 2 - 2
src/converse-minimize.js

@@ -12,7 +12,7 @@ import tpl_toggle_chats from "templates/toggle_chats.html";
 import tpl_trimmed_chat from "templates/trimmed_chat.html";
 
 
-const { _ , Backbone, Promise, Strophe, moment } = converse.env;
+const { _ , Backbone, Promise, Strophe, dayjs } = converse.env;
 const u = converse.env.utils;
 
 converse.plugins.add('converse-minimize', {
@@ -51,7 +51,7 @@ converse.plugins.add('converse-minimize', {
                 }
                 this.save({
                     'minimized': this.get('minimized') || false,
-                    'time_minimized': this.get('time_minimized') || moment(),
+                    'time_minimized': this.get('time_minimized') || dayjs(),
                 });
             },
 

+ 2 - 2
src/converse-muc-views.js

@@ -38,7 +38,7 @@ import tpl_spinner from "templates/spinner.html";
 import xss from "xss";
 
 
-const { Backbone, Promise, Strophe, moment, f, sizzle, _, $build, $iq, $msg, $pres } = converse.env;
+const { Backbone, Promise, Strophe, dayjs, f, sizzle, _, $build, $iq, $msg, $pres } = converse.env;
 const u = converse.env.utils;
 const AFFILIATION_CHANGE_COMANDS = ['admin', 'ban', 'owner', 'member', 'revoke'];
 const OWNER_COMMANDS = ['owner'];
@@ -1574,7 +1574,7 @@ converse.plugins.add('converse-muc-views', {
                     if (!_.includes(_.get(el, 'classList', []), 'chat-info')) {
                         return;
                     }
-                    if (!moment(el.getAttribute('data-isodate')).isSame(new Date(), "day")) {
+                    if (!dayjs(el.getAttribute('data-isodate')).isSame(new Date(), "day")) {
                         el = el.previousElementSibling;
                         continue;
                     }

+ 1 - 1
src/converse-omemo.js

@@ -9,7 +9,7 @@
 import converse from "@converse/headless/converse-core";
 import tpl_toolbar_omemo from "templates/toolbar_omemo.html";
 
-const { Backbone, Promise, Strophe, moment, sizzle, $build, $iq, $msg, _, f } = converse.env;
+const { Backbone, Promise, Strophe, dayjs, sizzle, $build, $iq, $msg, _, f } = converse.env;
 const u = converse.env.utils;
 
 Strophe.addNamespace('OMEMO_DEVICELIST', Strophe.NS.OMEMO+".devicelist");

+ 1 - 1
src/converse-profile.js

@@ -18,7 +18,7 @@ import tpl_profile_view from "templates/profile_view.html";
 import tpl_status_option from "templates/status_option.html";
 
 
-const { Strophe, Backbone, Promise, utils, _, moment, sizzle } = converse.env;
+const { Strophe, Backbone, Promise, utils, _, dayjs, sizzle } = converse.env;
 const u = converse.env.utils;
 
 

+ 2 - 2
src/headless/converse-chatboxes.js

@@ -9,7 +9,7 @@ import "./utils/form";
 import converse from "./converse-core";
 import filesize from "filesize";
 
-const { $msg, Backbone, Promise, Strophe, moment, sizzle, utils, _ } = converse.env;
+const { $msg, Backbone, Promise, Strophe, dayjs, sizzle, utils, _ } = converse.env;
 const u = converse.env.utils;
 
 Strophe.addNamespace('MESSAGE_CORRECT', 'urn:xmpp:message-correct:0');
@@ -746,7 +746,7 @@ converse.plugins.add('converse-chatboxes', {
                     'references': this.getReferencesFromStanza(stanza),
                     'subject': _.propertyOf(stanza.querySelector('subject'))('textContent'),
                     'thread': _.propertyOf(stanza.querySelector('thread'))('textContent'),
-                    'time': delay ? moment(delay.getAttribute('stamp')).toISOString() : (new Date()).toISOString(),
+                    'time': delay ? dayjs(delay.getAttribute('stamp')).toISOString() : (new Date()).toISOString(),
                     'type': stanza.getAttribute('type')
                 }, this.getStanzaIDs(original_stanza));
 

+ 6 - 3
src/headless/converse-core.js

@@ -9,9 +9,10 @@ import Backbone from "backbone";
 import BrowserStorage from "backbone.browserStorage";
 import Promise from "es6-promise/dist/es6-promise.auto";
 import _ from "./lodash.noconflict";
+import advancedFormat from 'dayjs/plugin/advancedFormat'
+import dayjs from "dayjs";
 import f from "./lodash.fp";
 import i18n from "./i18n";
-import moment from "moment";
 import pluggable from "pluggable.js/dist/pluggable";
 import polyfill from "./polyfill";
 import sizzle from "sizzle";
@@ -19,6 +20,8 @@ import u from "@converse/headless/utils/core";
 
 Backbone = Backbone.noConflict();
 
+dayjs.extend(advancedFormat)
+
 // Strophe globals
 const b64_sha1 = SHA1.b64_sha1;
 
@@ -1906,7 +1909,7 @@ const converse = {
      * @property {object} converse.env._           - The instance of [lodash](http://lodash.com) used by Converse.
      * @property {function} converse.env.f         - And instance of Lodash with its methods wrapped to produce immutable auto-curried iteratee-first data-last methods.
      * @property {function} converse.env.b64_sha1  - Utility method from Strophe for creating base64 encoded sha1 hashes.
-     * @property {object} converse.env.moment      - [Moment](https://momentjs.com) date manipulation library.
+     * @property {object} converse.env.dayjs       - [DayJS](https://github.com/iamkun/dayjs) date manipulation library.
      * @property {function} converse.env.sizzle    - [Sizzle](https://sizzlejs.com) CSS selector engine.
      * @property {object} converse.env.utils       - Module containing common utility methods used by Converse.
      */
@@ -1921,7 +1924,7 @@ const converse = {
         '_': _,
         'f': f,
         'b64_sha1':  b64_sha1,
-        'moment': moment,
+        'dayjs': dayjs,
         'sizzle': sizzle,
         'utils': u
     }

+ 2 - 2
src/headless/converse-mam.js

@@ -13,7 +13,7 @@ import sizzle from "sizzle";
 
 
 const CHATROOMS_TYPE = 'chatroom';
-const { Promise, Strophe, $iq, _, moment } = converse.env;
+const { Promise, Strophe, $iq, _, dayjs } = converse.env;
 const u = converse.env.utils;
 
 const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'count'];
@@ -361,7 +361,7 @@ converse.plugins.add('converse-mam', {
                         }
                         ['start', 'end'].forEach(t => {
                             if (options[t]) {
-                                const date = moment(options[t]);
+                                const date = dayjs(options[t]);
                                 if (date.isValid()) {
                                     stanza.c('field', {'var':t}).c('value').t(date.toISOString()).up().up();
                                 } else {

+ 1 - 1
src/headless/converse-muc.js

@@ -19,7 +19,7 @@ const MUC_ROLE_WEIGHTS = {
     'none':         2,
 };
 
-const { Strophe, Backbone, Promise, $iq, $build, $msg, $pres, sizzle, f, moment, _ } = converse.env;
+const { Strophe, Backbone, Promise, $iq, $build, $msg, $pres, sizzle, f, dayjs, _ } = converse.env;
 
 // Add Strophe Namespaces
 Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC + "#admin");

+ 1 - 1
src/headless/converse-pubsub.js

@@ -7,7 +7,7 @@
 import "./converse-disco";
 import converse from "./converse-core";
 
-const { Strophe, Backbone, Promise, $iq, $build, $msg, $pres, f, moment, _ } = converse.env;
+const { Strophe, Backbone, Promise, $iq, $build, $msg, $pres, f, dayjs, _ } = converse.env;
 
 Strophe.addNamespace('PUBSUB_ERROR', Strophe.NS.PUBSUB+"#errors");
 

+ 2 - 2
src/headless/converse-roster.js

@@ -6,7 +6,7 @@
 
 import converse from "@converse/headless/converse-core";
 
-const { Backbone, Promise, Strophe, $iq, $pres, moment, sizzle, _ } = converse.env;
+const { Backbone, Promise, Strophe, $iq, $pres, dayjs, sizzle, _ } = converse.env;
 const u = converse.env.utils;
 
 
@@ -175,7 +175,7 @@ converse.plugins.add('converse-roster', {
                           'name': name,
                           'priority': _.isNaN(parseInt(priority, 10)) ? 0 : parseInt(priority, 10),
                           'show': _.propertyOf(presence.querySelector('show'))('textContent') || 'online',
-                          'timestamp': _.isNil(delay) ? (new Date()).toISOString() : moment(delay.getAttribute('stamp')).toISOString()
+                          'timestamp': _.isNil(delay) ? (new Date()).toISOString() : dayjs(delay.getAttribute('stamp')).toISOString()
                        };
                 if (resource) {
                     resource.save(settings);

+ 2 - 2
src/headless/converse-vcard.js

@@ -8,7 +8,7 @@
 import converse from "./converse-core";
 import tpl_vcard from "./templates/vcard.html";
 
-const { Backbone, Promise, Strophe, _, $iq, $build, moment, sizzle } = converse.env;
+const { Backbone, Promise, Strophe, _, $iq, $build, dayjs, sizzle } = converse.env;
 const u = converse.env.utils;
 
 
@@ -196,7 +196,7 @@ converse.plugins.add('converse-vcard', {
                         return getVCard(_converse, model);
                     } else if (force ||
                             !model.get('vcard_updated') ||
-                            !moment(model.get('vcard_error')).isSame(new Date(), "day")) {
+                            !dayjs(model.get('vcard_error')).isSame(new Date(), "day")) {
 
                         const jid = model.get('jid');
                         if (!jid) {

Різницю між файлами не показано, бо вона завелика
+ 9 - 0
src/headless/dist/converse-headless.js


+ 30 - 34
src/headless/i18n.js

@@ -8,42 +8,42 @@
 //
 /*global define */
 
-import 'moment/locale/af';
-import 'moment/locale/ar';
-import 'moment/locale/bg';
-import 'moment/locale/ca';
-import 'moment/locale/cs';
-import 'moment/locale/de';
-import 'moment/locale/eo';
-import 'moment/locale/es';
-import 'moment/locale/eu';
-import 'moment/locale/fr';
-import 'moment/locale/gl';
-import 'moment/locale/he';
-import 'moment/locale/hi';
-import 'moment/locale/hu';
-import 'moment/locale/id';
-import 'moment/locale/it';
-import 'moment/locale/ja';
-import 'moment/locale/nb';
-import 'moment/locale/nl';
-import 'moment/locale/pl';
-import 'moment/locale/pt-br';
-import 'moment/locale/ro';
-import 'moment/locale/ru';
-import 'moment/locale/tr';
-import 'moment/locale/uk';
-import 'moment/locale/zh-cn';
-import 'moment/locale/zh-tw';
+import 'dayjs/locale/af';
+import 'dayjs/locale/ar';
+import 'dayjs/locale/bg';
+import 'dayjs/locale/ca';
+import 'dayjs/locale/cs';
+import 'dayjs/locale/de';
+import 'dayjs/locale/eo';
+import 'dayjs/locale/es';
+import 'dayjs/locale/eu';
+import 'dayjs/locale/fr';
+import 'dayjs/locale/gl';
+import 'dayjs/locale/he';
+import 'dayjs/locale/hi';
+import 'dayjs/locale/hu';
+import 'dayjs/locale/id';
+import 'dayjs/locale/it';
+import 'dayjs/locale/ja';
+import 'dayjs/locale/nb';
+import 'dayjs/locale/nl';
+import 'dayjs/locale/pl';
+import 'dayjs/locale/pt-br';
+import 'dayjs/locale/ro';
+import 'dayjs/locale/ru';
+import 'dayjs/locale/tr';
+import 'dayjs/locale/uk';
+import 'dayjs/locale/zh-cn';
+import 'dayjs/locale/zh-tw';
 import Jed from "jed";
 import Promise from "es6-promise/dist/es6-promise.auto";
 import _ from "./lodash.noconflict";
-import moment from "moment";
+import dayjs from "dayjs";
 
 
 function detectLocale (library_check) {
     /* Determine which locale is supported by the user's system as well
-     * as by the relevant library (e.g. converse.js or moment.js).
+     * as by the relevant library (e.g. converse.js or dayjs).
      * @param { Function } library_check - Returns a boolean indicating whether
      *   the locale is supported.
      */
@@ -68,10 +68,6 @@ function detectLocale (library_check) {
     return locale || 'en';
 }
 
-function isMomentLocale (locale) {
-    return _.includes(moment.locales(), locale);
-}
-
 function isConverseLocale (locale, supported_locales) {
     return _.isString(locale) && _.includes(supported_locales, locale);
 }
@@ -112,7 +108,7 @@ export default {
             preferred_locale,
             _.partial(isConverseLocale, _, _converse.locales)
         );
-        moment.locale(getLocale(preferred_locale, isMomentLocale));
+        dayjs.locale(getLocale(preferred_locale, l => dayjs.locale(l)));
     },
 
     translate (str) {

+ 0 - 1
src/headless/package.json

@@ -28,7 +28,6 @@
     "filesize": "^3.6.1",
     "jed": "1.1.1",
     "lodash": "^4.17.11",
-    "moment": "~> 2.19.3 ",
     "pluggable.js": "2.0.0",
     "strophe.js": "1.3.2",
     "strophejs-plugin-ping": "0.0.3",

+ 2 - 2
tests/mock.js

@@ -4,7 +4,7 @@
     const _ = converse.env._;
     const Promise = converse.env.Promise;
     const Strophe = converse.env.Strophe;
-    const moment = converse.env.moment;
+    const dayjs = converse.env.dayjs;
     const $iq = converse.env.$iq;
     const u = converse.env.utils;
 
@@ -222,7 +222,7 @@
                     'image': _.get(vcard.querySelector('PHOTO BINVAL'), 'textContent'),
                     'image_type': _.get(vcard.querySelector('PHOTO TYPE'), 'textContent'),
                     'url': _.get(vcard.querySelector('URL'), 'textContent'),
-                    'vcard_updated': moment().format(),
+                    'vcard_updated': dayjs().format(),
                     'vcard_error': undefined
                 };
                 resolve(result);

+ 1 - 5
webpack.config.js

@@ -15,10 +15,7 @@ const config = {
         filename: 'converse.js'
     },
     devtool: 'source-map',
-    plugins: [
-        new MiniCssExtractPlugin({filename: '../css/converse.css'}),
-        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
-    ],
+    plugins: [new MiniCssExtractPlugin({filename: '../css/converse.css'})],
     module: {
         rules: [
         {
@@ -172,7 +169,6 @@ function parameterize () {
                 "lodash": "lodash",
                 "lodash.converter": "lodash.converter",
                 "lodash.noconflict": "lodash.noconflict",
-                "moment": "moment",
                 "strophe": "strophe",
                 "strophe.ping": "strophe.ping",
                 "strophe.rsm": "strophe.rsm",

Деякі файли не було показано, через те що забагато файлів було змінено