Browse Source

Remove need for lodash templates in headless build

JC Brand 4 years ago
parent
commit
0ca2e5ae08

+ 2 - 2
spec/http-file-upload.js

@@ -1,4 +1,4 @@
-/*global mock */
+/*global mock, converse */
 
 
 const Strophe = converse.env.Strophe;
 const Strophe = converse.env.Strophe;
 const $iq = converse.env.$iq;
 const $iq = converse.env.$iq;
@@ -391,7 +391,7 @@ describe("XEP-0363: HTTP File Upload", function () {
                         u.waitUntil(() => view.el.querySelector('.chat-content progress').getAttribute('value') === '0.5')
                         u.waitUntil(() => view.el.querySelector('.chat-content progress').getAttribute('value') === '0.5')
                         .then(() => {
                         .then(() => {
                             message.set('progress', 1);
                             message.set('progress', 1);
-                            u.waitUntil(() => view.el.querySelector('.chat-content progress').getAttribute('value') === '1')
+                            u.waitUntil(() => view.el.querySelector('.chat-content progress')?.getAttribute('value') === '1')
                         }).then(() => {
                         }).then(() => {
                             message.save({
                             message.save({
                                 'upload': _converse.SUCCESS,
                                 'upload': _converse.SUCCESS,

+ 18 - 30
spec/mock.js

@@ -39,13 +39,12 @@ mock.initConverse = function (promise_names=[], settings=null, func) {
 };
 };
 
 
 window.addEventListener('converse-loaded', () => {
 window.addEventListener('converse-loaded', () => {
-    const { _, u, sizzle, Strophe, dayjs, $iq, $msg, $pres } = converse.env;
+    const { u, sizzle, Strophe, dayjs, $iq, $msg, $pres } = converse.env;
 
 
     mock.waitUntilDiscoConfirmed = async function (_converse, entity_jid, identities, features=[], items=[], type='info') {
     mock.waitUntilDiscoConfirmed = async function (_converse, entity_jid, identities, features=[], items=[], type='info') {
         const iq = await u.waitUntil(() => {
         const iq = await u.waitUntil(() => {
-            return _.filter(
-                _converse.connection.IQ_stanzas,
-                (iq) => sizzle(`iq[to="${entity_jid}"] query[xmlns="http://jabber.org/protocol/disco#${type}"]`, iq).length
+            return _converse.connection.IQ_stanzas.filter(
+                iq => sizzle(`iq[to="${entity_jid}"] query[xmlns="http://jabber.org/protocol/disco#${type}"]`, iq).length
             ).pop();
             ).pop();
         }, 300);
         }, 300);
         const stanza = $iq({
         const stanza = $iq({
@@ -55,15 +54,9 @@ window.addEventListener('converse-loaded', () => {
             'id': iq.getAttribute('id'),
             'id': iq.getAttribute('id'),
         }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#'+type});
         }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#'+type});
 
 
-        _.forEach(identities, function (identity) {
-            stanza.c('identity', {'category': identity.category, 'type': identity.type}).up()
-        });
-        _.forEach(features, function (feature) {
-            stanza.c('feature', {'var': feature}).up();
-        });
-        _.forEach(items, function (item) {
-            stanza.c('item', {'jid': item}).up();
-        });
+        identities?.forEach(identity => stanza.c('identity', {'category': identity.category, 'type': identity.type}).up());
+        features?.forEach(feature => stanza.c('feature', {'var': feature}).up());
+        items?.forEach(item => stanza.c('item', {'jid': item}).up());
         _converse.connection._dataRecv(mock.createRequest(stanza));
         _converse.connection._dataRecv(mock.createRequest(stanza));
     }
     }
 
 
@@ -99,9 +92,7 @@ window.addEventListener('converse-loaded', () => {
         const controlbox = document.querySelector("#controlbox");
         const controlbox = document.querySelector("#controlbox");
         if (u.isVisible(controlbox)) {
         if (u.isVisible(controlbox)) {
             const button = controlbox.querySelector(".close-chatbox-button");
             const button = controlbox.querySelector(".close-chatbox-button");
-            if (!_.isNull(button)) {
-                button.click();
-            }
+            (button !== null) && button.click();
         }
         }
         return this;
         return this;
     };
     };
@@ -239,9 +230,8 @@ window.addEventListener('converse-loaded', () => {
         const stanzas = _converse.connection.IQ_stanzas;
         const stanzas = _converse.connection.IQ_stanzas;
 
 
         if (affiliations.includes('member')) {
         if (affiliations.includes('member')) {
-            const member_IQ = await u.waitUntil(() => _.filter(
-                stanzas,
-                s => sizzle(`iq[to="${muc_jid}"] query[xmlns="${Strophe.NS.MUC_ADMIN}"] item[affiliation="member"]`, s).length
+            const member_IQ = await u.waitUntil(() =>
+                stanzas.filter(s => sizzle(`iq[to="${muc_jid}"] query[xmlns="${Strophe.NS.MUC_ADMIN}"] item[affiliation="member"]`, s).length
             ).pop());
             ).pop());
             const member_list_stanza = $iq({
             const member_list_stanza = $iq({
                     'from': 'coven@chat.shakespeare.lit',
                     'from': 'coven@chat.shakespeare.lit',
@@ -260,8 +250,7 @@ window.addEventListener('converse-loaded', () => {
         }
         }
 
 
         if (affiliations.includes('admin')) {
         if (affiliations.includes('admin')) {
-            const admin_IQ = await u.waitUntil(() => _.filter(
-                stanzas,
+            const admin_IQ = await u.waitUntil(() => stanzas.filter(
                 s => sizzle(`iq[to="${muc_jid}"] query[xmlns="${Strophe.NS.MUC_ADMIN}"] item[affiliation="admin"]`, s).length
                 s => sizzle(`iq[to="${muc_jid}"] query[xmlns="${Strophe.NS.MUC_ADMIN}"] item[affiliation="admin"]`, s).length
             ).pop());
             ).pop());
             const admin_list_stanza = $iq({
             const admin_list_stanza = $iq({
@@ -281,8 +270,7 @@ window.addEventListener('converse-loaded', () => {
         }
         }
 
 
         if (affiliations.includes('owner')) {
         if (affiliations.includes('owner')) {
-            const owner_IQ = await u.waitUntil(() => _.filter(
-                stanzas,
+            const owner_IQ = await u.waitUntil(() => stanzas.filter(
                 s => sizzle(`iq[to="${muc_jid}"] query[xmlns="${Strophe.NS.MUC_ADMIN}"] item[affiliation="owner"]`, s).length
                 s => sizzle(`iq[to="${muc_jid}"] query[xmlns="${Strophe.NS.MUC_ADMIN}"] item[affiliation="owner"]`, s).length
             ).pop());
             ).pop());
             const owner_list_stanza = $iq({
             const owner_list_stanza = $iq({
@@ -452,7 +440,7 @@ window.addEventListener('converse-loaded', () => {
         view.el.querySelector('.chat-textarea').value = message;
         view.el.querySelector('.chat-textarea').value = message;
         view.onKeyDown({
         view.onKeyDown({
             target: view.el.querySelector('textarea.chat-textarea'),
             target: view.el.querySelector('textarea.chat-textarea'),
-            preventDefault: _.noop,
+            preventDefault: () => {},
             keyCode: 13
             keyCode: 13
         });
         });
         return promise;
         return promise;
@@ -652,7 +640,7 @@ window.addEventListener('converse-loaded', () => {
 
 
         _converse.api.vcard.get = function (model, force) {
         _converse.api.vcard.get = function (model, force) {
             let jid;
             let jid;
-            if (_.isString(model)) {
+            if (typeof model === 'string' || model instanceof String) {
                 jid = model;
                 jid = model;
             } else if (!model.get('vcard_updated') || force) {
             } else if (!model.get('vcard_updated') || force) {
                 jid = model.get('jid') || model.get('muc_jid');
                 jid = model.get('jid') || model.get('muc_jid');
@@ -671,15 +659,15 @@ window.addEventListener('converse-loaded', () => {
             const vcard = $iq().c('vCard').c('FN').t(fullname).nodeTree;
             const vcard = $iq().c('vCard').c('FN').t(fullname).nodeTree;
             return {
             return {
                 'vcard': vcard,
                 'vcard': vcard,
-                'fullname': _.get(vcard.querySelector('FN'), 'textContent'),
-                'image': _.get(vcard.querySelector('PHOTO BINVAL'), 'textContent'),
-                'image_type': _.get(vcard.querySelector('PHOTO TYPE'), 'textContent'),
-                'url': _.get(vcard.querySelector('URL'), 'textContent'),
+                'fullname': vcard.querySelector('FN')?.textContent,
+                'image': vcard.querySelector('PHOTO BINVAL')?.textContent,
+                'image_type': vcard.querySelector('PHOTO TYPE')?.textContent,
+                'url': vcard.querySelector('URL')?.textContent,
                 'vcard_updated': dayjs().format(),
                 'vcard_updated': dayjs().format(),
                 'vcard_error': undefined
                 'vcard_error': undefined
             };
             };
         };
         };
-        if (_.get(settings, 'auto_login') !== false) {
+        if (settings?.auto_login !== false) {
             _converse.api.user.login('romeo@montague.lit/orchard', 'secret');
             _converse.api.user.login('romeo@montague.lit/orchard', 'secret');
             await _converse.api.waitUntil('afterResourceBinding');
             await _converse.api.waitUntil('afterResourceBinding');
         }
         }

+ 16 - 0
src/converse.js

@@ -4,6 +4,8 @@
  * @license Mozilla Public License (MPLv2)
  * @license Mozilla Public License (MPLv2)
  */
  */
 
 
+import _ from './lodash.noconflict';
+
 /* START: Removable components
 /* START: Removable components
  * --------------------
  * --------------------
  * Any of the following components may be removed if they're not needed.
  * Any of the following components may be removed if they're not needed.
@@ -59,6 +61,20 @@ const WHITELISTED_PLUGINS = [
     'converse-singleton'
     'converse-singleton'
 ];
 ];
 
 
+// Use Mustache style syntax for variable interpolation
+/* Configuration of Lodash templates (this config is distinct to the
+ * config of requirejs-tpl in main.js). This one is for normal inline templates.
+ */
+_.templateSettings = {
+    'escape': /\{\{\{([\s\S]+?)\}\}\}/g,
+    'evaluate': /\{\[([\s\S]+?)\]\}/g,
+    'interpolate': /\{\{([\s\S]+?)\}\}/g,
+    'imports': { '_': _ }
+};
+
+converse.env._ = _;
+
+
 const initialize = converse.initialize;
 const initialize = converse.initialize;
 
 
 converse.initialize = function (settings, callback) {
 converse.initialize = function (settings, callback) {

+ 0 - 14
src/headless/converse-core.js

@@ -6,7 +6,6 @@
 import './polyfill';
 import './polyfill';
 import 'strophe.js/src/websocket';
 import 'strophe.js/src/websocket';
 import Storage from '@converse/skeletor/src/storage.js';
 import Storage from '@converse/skeletor/src/storage.js';
-import _ from './lodash.noconflict';
 import advancedFormat from 'dayjs/plugin/advancedFormat';
 import advancedFormat from 'dayjs/plugin/advancedFormat';
 import dayjs from 'dayjs';
 import dayjs from 'dayjs';
 import log from '@converse/headless/log';
 import log from '@converse/headless/log';
@@ -55,18 +54,6 @@ Strophe.addNamespace('VCARD', 'vcard-temp');
 Strophe.addNamespace('VCARDUPDATE', 'vcard-temp:x:update');
 Strophe.addNamespace('VCARDUPDATE', 'vcard-temp:x:update');
 Strophe.addNamespace('XFORM', 'jabber:x:data');
 Strophe.addNamespace('XFORM', 'jabber:x:data');
 
 
-// Use Mustache style syntax for variable interpolation
-/* Configuration of Lodash templates (this config is distinct to the
- * config of requirejs-tpl in main.js). This one is for normal inline templates.
- */
-_.templateSettings = {
-    'escape': /\{\{\{([\s\S]+?)\}\}\}/g,
-    'evaluate': /\{\[([\s\S]+?)\]\}/g,
-    'interpolate': /\{\{([\s\S]+?)\}\}/g,
-    'imports': { '_': _ }
-};
-
-
 /**
 /**
  * Custom error for indicating timeouts
  * Custom error for indicating timeouts
  * @namespace _converse
  * @namespace _converse
@@ -1641,7 +1628,6 @@ Object.assign(converse, {
         Model,
         Model,
         Promise,
         Promise,
         Strophe,
         Strophe,
-        _,
         dayjs,
         dayjs,
         html,
         html,
         log,
         log,

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

@@ -5,7 +5,6 @@
  */
  */
 import "./converse-status";
 import "./converse-status";
 import log from "@converse/headless/log";
 import log from "@converse/headless/log";
-import tpl_vcard from "./templates/vcard.html";
 import { Collection } from "@converse/skeletor/src/collection";
 import { Collection } from "@converse/skeletor/src/collection";
 import { Model } from '@converse/skeletor/src/model.js';
 import { Model } from '@converse/skeletor/src/model.js';
 import { _converse, api, converse } from "./converse-core";
 import { _converse, api, converse } from "./converse-core";
@@ -294,7 +293,19 @@ converse.plugins.add('converse-vcard', {
                     if (!jid) {
                     if (!jid) {
                         throw Error("No jid provided for the VCard data");
                         throw Error("No jid provided for the VCard data");
                     }
                     }
-                    const vcard_el = Strophe.xmlHtmlNode(tpl_vcard(data)).firstElementChild;
+                    const div = document.createElement('div');
+                    const vcard_el = u.toStanza(`
+                        <vCard xmlns="vcard-temp">
+                            <FN>${data.fn}</FN>
+                            <NICKNAME>${data.nickname}</NICKNAME>
+                            <URL>${data.url}</URL>
+                            <ROLE>${data.role}</ROLE>
+                            <EMAIL><INTERNET/><PREF/><USERID>${data.email}</USERID></EMAIL>
+                            <PHOTO>
+                                <TYPE>${data.image_type}</TYPE>
+                                <BINVAL>${data.image}</BINVAL>
+                            </PHOTO>
+                        </vCard>`, div);
                     let result;
                     let result;
                     try {
                     try {
                         result = await api.sendIQ(createStanza("set", jid, vcard_el));
                         result = await api.sendIQ(createStanza("set", jid, vcard_el));

+ 3 - 12
src/headless/package-lock.json

@@ -4,15 +4,6 @@
 	"lockfileVersion": 1,
 	"lockfileVersion": 1,
 	"requires": true,
 	"requires": true,
 	"dependencies": {
 	"dependencies": {
-		"@converse/skeletor": {
-			"version": "github:conversejs/skeletor#b260c554f4ce961c29deea4740083e58a489aa9b",
-			"from": "github:conversejs/skeletor#b260c554f4ce961c29deea4740083e58a489aa9b",
-			"dev": true,
-			"requires": {
-				"lit-html": "^1.2.1",
-				"lodash-es": "^4.17.14"
-			}
-		},
 		"abab": {
 		"abab": {
 			"version": "2.0.5",
 			"version": "2.0.5",
 			"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
 			"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
@@ -41,9 +32,9 @@
 			}
 			}
 		},
 		},
 		"lit-html": {
 		"lit-html": {
-			"version": "1.2.1",
-			"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.2.1.tgz",
-			"integrity": "sha512-GSJHHXMGLZDzTRq59IUfL9FCdAlGfqNp/dEa7k7aBaaWD+JKaCjsAk9KYm2V12ItonVaYx2dprN66Zdm1AuBTQ==",
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.3.0.tgz",
+			"integrity": "sha512-0Q1bwmaFH9O14vycPHw8C/IeHMk/uSDldVLIefu/kfbTBGIc44KGH6A8p1bDfxUfHdc8q6Ct7kQklWoHgr4t1Q==",
 			"dev": true
 			"dev": true
 		},
 		},
 		"localforage": {
 		"localforage": {

+ 0 - 6
src/headless/templates/field.html

@@ -1,6 +0,0 @@
-<field var="{{{o.name}}}">
-{[ if (o.value.constructor === Array) { ]}
-    {[ o.value.forEach(function (arrayValue) { ]}<value>{{{arrayValue}}}</value>{[ }); ]}
-{[ } else { ]}
-    <value>{{{o.value}}}</value>
-{[ } ]}</field>

+ 0 - 11
src/headless/templates/vcard.html

@@ -1,11 +0,0 @@
-<vCard xmlns="vcard-temp">
-    <FN>{{{o.fn}}}</FN>
-    <NICKNAME>{{{o.nickname}}}</NICKNAME>
-    <URL>{{{o.url}}}</URL>
-    <ROLE>{{{o.role}}}</ROLE>
-    <EMAIL><INTERNET/><PREF/><USERID>{{{o.email}}}</USERID></EMAIL>
-    <PHOTO>
-      <TYPE>{{{o.image_type}}}</TYPE>
-      <BINVAL>{{{o.image}}}</BINVAL>
-    </PHOTO>
-</vCard>

+ 1 - 15
src/headless/utils/core.js

@@ -193,7 +193,7 @@ u.isServiceUnavailableError = function (stanza) {
 /**
 /**
  * Merge the second object into the first one.
  * Merge the second object into the first one.
  * @private
  * @private
- * @method u#stringToNode
+ * @method u#merge
  * @param { Object } first
  * @param { Object } first
  * @param { Object } second
  * @param { Object } second
  */
  */
@@ -207,20 +207,6 @@ u.merge = function merge (first, second) {
     }
     }
 };
 };
 
 
-/**
- * Converts an HTML string into a DOM Node.
- * Expects that the HTML string has only one top-level element,
- * i.e. not multiple ones.
- * @private
- * @method u#stringToNode
- * @param { String } s - The HTML string
- */
-u.stringToNode = function (s) {
-    var div = document.createElement('div');
-    div.innerHTML = s;
-    return div.firstElementChild;
-};
-
 u.getOuterWidth = function (el, include_margin=false) {
 u.getOuterWidth = function (el, include_margin=false) {
     let width = el.offsetWidth;
     let width = el.offsetWidth;
     if (!include_margin) {
     if (!include_margin) {

+ 6 - 2
src/headless/utils/form.js

@@ -3,7 +3,6 @@
  * @license Mozilla Public License (MPLv2)
  * @license Mozilla Public License (MPLv2)
  * @description This is the form utilities module.
  * @description This is the form utilities module.
  */
  */
-import tpl_field from "../templates/field.html";
 import u from "./core";
 import u from "./core";
 
 
 /**
 /**
@@ -27,6 +26,11 @@ u.webForm2xForm = function (field) {
     } else {
     } else {
         value = field.value;
         value = field.value;
     }
     }
-    return u.stringToNode(tpl_field({ name, value }));
+    return u.toStanza(`
+        <field var="${name}">
+            ${ value.constructor === Array ?
+                value.map(v => `<value>${v}</value>`) :
+                `<value>${value}</value>` }
+        </field>`);
 };
 };
 export default u;
 export default u;

+ 0 - 0
src/headless/lodash.noconflict.js → src/lodash.noconflict.js