From b70fde159d1e0b6e99e066e437f3f391f94818f9 Mon Sep 17 00:00:00 2001 From: JC Brand Date: Sun, 6 Oct 2019 12:48:05 +0200 Subject: [PATCH] Fixes #1738. Allow webpack's `publicPath` to be specified at runtime --- CHANGES.md | 15 ++++---- docs/source/configuration.rst | 15 ++++++++ src/converse.js | 7 ++++ src/entry.js | 67 +++++++++++++++++++++++++++++++++++ src/headless/converse-core.js | 6 ++-- tests/mock.js | 17 +++++---- webpack.common.js | 2 +- webpack.html | 22 ++++++------ 8 files changed, 121 insertions(+), 30 deletions(-) create mode 100644 src/entry.js diff --git a/CHANGES.md b/CHANGES.md index 6818777c9..86c6542ba 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,13 +2,14 @@ ## 5.0.4 -- Add config option [allow_message_corrections](https://conversejs.org/docs/html/configuration.html#allow_message_corrections) - which, if set to `last`, limits editing of sent messages to the last message sent -- Bugfix: Don't treat every duplicate message ID as a message correction; since some - clients don't use globally unique ID's this causes false positives. +- New config option [allow_message_corrections](https://conversejs.org/docs/html/configuration.html#allow_message_corrections) + which, if set to `last`, limits editing of sent messages to the last message sent. +- Bugfix: Don't treat every duplicate message ID as a message correction; since some clients don't use globally unique ID's this causes false positives. - Bugfix: process stanzas from mam one-by-one in order to correctly process message receipts - #1712: `TypeError: plugin._features is not a function` -- #1714 Don't notify the user in case we're receiving a message delivery receipt only +- #1714: Don't notify the user in case we're receiving a message delivery receipt only +- #1739: New config option [assets_path](https://conversejs.org/docs/html/configuration.html#assets_path) + which lets you set the path from which "chunks" are loaded. ## 5.0.3 (2019-09-13) @@ -29,8 +30,8 @@ - Use `listenTo` to avoid memory leaks when views get removed. - SECURITY FIX: Ignore MAM `chat` messages not sent from yourself - #1692 Bugfix: `TypeError: oldest_message is undefined` -- #1704 SECURITY FIX: Impersonation by misusage of groupchat carbons -- #1705 Bugfix: `this.roomspanel` is `undefined` after hibernating +- #1704: SECURITY FIX: Impersonation by misusage of groupchat carbons +- #1705: Bugfix: `this.roomspanel` is `undefined` after hibernating ## 5.0.1 (2019-08-14) diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index d209db06c..97068fe69 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -1222,6 +1222,21 @@ providers_link The hyperlink on the registration form which points to a directory of public XMPP servers. +assets_path +----------- + +* Default: The `publicPath `_ value configured in the relevant Webpack configuration. + +Since version 5.0.0, Converse serves a smaller bundle by extracting various +resources (for example emojis and translations) into separate files (aka +"chunks") which are loaded asynchronously on demand. + +The URL path at which these resources are loaded is normally set by the ``publicPath`` +setting of Webpack but this means that it's hardcoded to a particular value at +compile time. + +This configuration seting allows this value to be set at runtime as well. + push_app_servers ---------------- diff --git a/src/converse.js b/src/converse.js index 496b23ccc..fba362bac 100644 --- a/src/converse.js +++ b/src/converse.js @@ -1,3 +1,10 @@ +// Converse.js (A browser based XMPP chat client) +// https://conversejs.org +// +// Copyright (c) 2019, The Converse developers +// Licensed under the Mozilla Public License (MPLv2) +// + /* START: Removable components * -------------------- * Any of the following components may be removed if they're not needed. diff --git a/src/entry.js b/src/entry.js new file mode 100644 index 000000000..258a5ab4a --- /dev/null +++ b/src/entry.js @@ -0,0 +1,67 @@ +// Converse.js +// https://conversejs.org +// +// Copyright (c) 2013-2019, the Converse.js developers +// Licensed under the Mozilla Public License (MPLv2) +// +// Webpack entry file +// +// The purpose of this file is to provide an initial temporary public API +// (window.converse) for **before** the rest of converse.js is loaded so +// that we can set the __webpack_public_path__ global variable. +// +// Once the rest converse.js has been loaded, window.converse will be replaced +// with the full-fledged public API. + +const plugins = {}; + +const converse = { + plugins: { + add (name, plugin) { + if (plugins[name] !== undefined) { + throw new TypeError( + `Error: plugin with name "${name}" has already been ` + 'registered!' + ); + } + plugins[name] = plugin; + } + }, + + initialize (settings={}) { + converse.load(settings).initialize(settings); + }, + + /** + * Public API method which explicitly loads Converse and allows you the + * possibility to pass in configuration settings which need to be defined + * before loading. Currently this is only the [assets_path](https://conversejs.org/docs/html/configuration.html#assets_path) + * setting. + * + * If not called explicitly, this method will be called implicitly once + * {@link converse.initialize} is called. + * + * In most cases, you probably don't need to explicitly call this method, + * however, until converse.js has been loaded you won't have access to the + * utility methods and globals exposed via {@link converse.env}. So if you + * need to access `converse.env` outside of any plugins and before + * `converse.initialize` has been called, then you need to call + * `converse.load` first. + * + * @memberOf converse + * @method load + * @param {object} settings A map of configuration-settings that are needed at load time. + * @example + * converse.load({assets_path: '/path/to/assets/'}); + */ + load (settings={}) { + if (settings.assets_path) { + __webpack_public_path__ = settings.assets_path; // eslint-disable-line no-undef + } + require('./converse.js'); + Object.keys(plugins).forEach(name => converse.plugins.add(name, plugins[name])); + return converse; + } +} + +window.converse = converse; +export default converse; diff --git a/src/headless/converse-core.js b/src/headless/converse-core.js index 8564991af..f57457373 100644 --- a/src/headless/converse-core.js +++ b/src/headless/converse-core.js @@ -1904,7 +1904,7 @@ _converse.api = { * @global * @namespace converse */ -const converse = { +Object.assign(window.converse, { /** * Public API method which initializes Converse. * This method must always be called when using Converse. @@ -1997,9 +1997,7 @@ const converse = { 'sizzle': sizzle, 'utils': u } -}; - -window.converse = converse; +}); /** * Once Converse.js has loaded, it'll dispatch a custom event with the name `converse-loaded`. diff --git a/tests/mock.js b/tests/mock.js index 7d92c7706..09c444475 100644 --- a/tests/mock.js +++ b/tests/mock.js @@ -1,6 +1,9 @@ (function (root, factory) { define("mock", [], factory); }(this, function () { + + converse.load(); + const _ = converse.env._; const Promise = converse.env.Promise; const Strophe = converse.env.Strophe; @@ -178,7 +181,7 @@ }; }(); - async function initConverse (settings, spies, promises) { + async function initConverse (settings, spies={}, promises) { window.localStorage.clear(); window.sessionStorage.clear(); const el = document.querySelector('#conversejs'); @@ -187,8 +190,8 @@ } const connection = mock.mock_connection(); - if (!_.isNil(spies)) { - _.forEach(spies.connection, method => spyOn(connection, method)); + if (spies && spies.connection) { + spies.connection.forEach(method => spyOn(connection, method)); } const _converse = await converse.initialize(Object.assign({ @@ -204,8 +207,8 @@ 'debug': false }, settings || {})); - if (!_.isNil(spies)) { - _.forEach(spies._converse, method => spyOn(_converse, method).and.callThrough()); + if (spies && spies._converse) { + spies._converse.forEach(method => spyOn(_converse, method).and.callThrough()); } _converse.ChatBoxViews.prototype.trimChat = function () {}; @@ -240,7 +243,7 @@ 'vcard_error': undefined }; resolve(result); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + }).catch(e => _converse.log(e, Strophe.LogLevel.FATAL)); }; if (_.get(settings, 'auto_login') !== false) { _converse.api.user.login('romeo@montague.lit/orchard', 'secret'); @@ -250,7 +253,7 @@ return _converse; } - mock.initConverse = function (spies, promise_names=[], settings=null, func) { + mock.initConverse = function (spies={}, promise_names=[], settings=null, func) { if (_.isFunction(spies)) { func = spies; spies = null; diff --git a/webpack.common.js b/webpack.common.js index 87ea650d5..47c11d027 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -7,7 +7,7 @@ module.exports = { path: path.resolve(__dirname, 'dist'), // Output path for generated bundles chunkFilename: '[name].js' }, - entry: path.resolve(__dirname, 'src/converse.js'), + entry: path.resolve(__dirname, 'src/entry.js'), externals: [{ "window": "window" }], diff --git a/webpack.html b/webpack.html index 9840cb22b..3b7a00596 100644 --- a/webpack.html +++ b/webpack.html @@ -17,21 +17,21 @@ } }); converse.initialize({ - auto_register_muc_nickname: true, - enable_smacks: true, auto_away: 300, - i18n: 'en', - view_mode: 'fullscreen', - muc_respect_autojoin: true, + auto_login: true, + auto_register_muc_nickname: true, bosh_service_url: 'http://chat.example.org:5380/http-bind/', + debug: true, + enable_smacks: true, + i18n: 'en', + jid: 'klaus.dresner@chat.example.org', + message_archiving: 'always', + muc_domain: 'conference.chat.example.org', + muc_respect_autojoin: true, + password: 'secret', + view_mode: 'fullscreen', websocket_url: 'ws://chat.example.org:5380/xmpp-websocket', whitelisted_plugins: ['converse-debug'], - muc_domain: 'conference.chat.example.org', - message_archiving: 'always', - debug: true, - jid: 'klaus.dresner@chat.example.org', - password: 'secret', - auto_login: true });