Commit 8aaf50d5 authored by JC Brand's avatar JC Brand

Use webpack's dynamic imports feature for fetching emoji JSON

parent d619012b
{ {
"parser": "babel-eslint",
"parserOptions": { "parserOptions": {
"ecmaVersion": 2017, "ecmaVersion": 2017,
"sourceType": "module" "sourceType": "module",
"allowImportExportEverywhere": true
}, },
"env": { "env": {
"browser": true, "browser": true,
......
# Changelog # Changelog
## 5.0.2 (Unreleased)
- The JSON representing emojis is now fetched asynchronously as a separate file `converse.emojis.js`.
- Webpack is now configured with a `publicPath` set to `/dist/`. This is necessary
so that chunks (such as the Emojis JSON) can be fetched asynchronously. This
means that all your assets need to be served at `/dist`. If you need to set a
different path, you'll need to set `publicPath` in `webpack.config.js` to
your preferred path and then rebuild all assets (e.g. `make dist`).
## 5.0.1 (2019-08-14) ## 5.0.1 (2019-08-14)
- Add a new GUI for moderator actions. You can trigger it by entering `/modtools` in a MUC. - Add a new GUI for moderator actions. You can trigger it by entering `/modtools` in a MUC.
......
...@@ -647,10 +647,6 @@ domain_placeholder ...@@ -647,10 +647,6 @@ domain_placeholder
The placeholder text shown in the domain input on the registration form. The placeholder text shown in the domain input on the registration form.
emoji_json_path
---------------
* Default: ``emojis/``
emoji_image_path emoji_image_path
......
...@@ -2681,6 +2681,32 @@ ...@@ -2681,6 +2681,32 @@
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
"dev": true "dev": true
}, },
"babel-eslint": {
"version": "10.0.2",
"resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.2.tgz",
"integrity": "sha512-UdsurWPtgiPgpJ06ryUnuaSXC2s0WoSZnQmEpbAH65XZSdwowgN5MvyP7e88nW07FYXv72erVtpBkxyDVKhH1Q==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"@babel/parser": "^7.0.0",
"@babel/traverse": "^7.0.0",
"@babel/types": "^7.0.0",
"eslint-scope": "3.7.1",
"eslint-visitor-keys": "^1.0.0"
},
"dependencies": {
"eslint-scope": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
"integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
}
}
},
"babel-loader": { "babel-loader": {
"version": "8.0.6", "version": "8.0.6",
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz",
...@@ -2710,6 +2736,12 @@ ...@@ -2710,6 +2736,12 @@
"object.assign": "^4.1.0" "object.assign": "^4.1.0"
} }
}, },
"babel-plugin-syntax-dynamic-import": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
"integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=",
"dev": true
},
"backbone": { "backbone": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.0.tgz", "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.0.tgz",
......
...@@ -170,7 +170,6 @@ converse.plugins.add('converse-emoji', { ...@@ -170,7 +170,6 @@ converse.plugins.add('converse-emoji', {
_converse.api.settings.update({ _converse.api.settings.update({
'emoji_image_path': twemoji.default.base, 'emoji_image_path': twemoji.default.base,
'emoji_json_path': '/dist/emojis.json',
'emoji_categories': { 'emoji_categories': {
"smileys": ":grinning:", "smileys": ":grinning:",
"people": ":thumbsup:", "people": ":thumbsup:",
...@@ -225,36 +224,6 @@ converse.plugins.add('converse-emoji', { ...@@ -225,36 +224,6 @@ converse.plugins.add('converse-emoji', {
return _converse.toned_emojis; return _converse.toned_emojis;
} }
function fetchEmojiJSON () {
_converse.emojis.json = {};
const promise = u.getResolveablePromise();
const xhr = new XMLHttpRequest();
xhr.open('GET', _converse.emoji_json_path, true);
xhr.setRequestHeader('Accept', "application/json, text/javascript");
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 400) {
try {
_converse.emojis.json = JSON.parse(xhr.responseText);
} catch (e) {
xhr.onerror(e);
}
} else {
xhr.onerror();
}
promise.resolve();
};
xhr.onerror = (e) => {
const err_message = e ? ` Error: ${e.message}` : '';
_converse.log(
`Could not fetch Emoji JSON. Status: ${xhr.statusText}. ${err_message}`,
Strophe.LogLevel.ERROR
);
promise.resolve();
}
xhr.send();
return promise;
}
/************************ BEGIN Utils ************************/ /************************ BEGIN Utils ************************/
// Closured cache // Closured cache
...@@ -350,26 +319,25 @@ converse.plugins.add('converse-emoji', { ...@@ -350,26 +319,25 @@ converse.plugins.add('converse-emoji', {
if (attr === 'category') { if (attr === 'category') {
return _converse.emojis.json; return _converse.emojis.json;
} }
emojis_by_attribute[attr] = {};
const all_variants = _converse.emojis_list const all_variants = _converse.emojis_list
.map(e => e[attr]) .map(e => e[attr])
.filter((c, i, arr) => arr.indexOf(c) == i); .filter((c, i, arr) => arr.indexOf(c) == i);
all_variants.forEach(v => { emojis_by_attribute[attr] = {};
emojis_by_attribute[attr][v] = _.find(_converse.emojis_list, i => (i[attr] === v)); all_variants.forEach(v => (emojis_by_attribute[attr][v] = _.find(_converse.emojis_list, i => (i[attr] === v))));
});
return emojis_by_attribute[attr]; return emojis_by_attribute[attr];
} }
}); });
/************************ END Utils ************************/ /************************ END Utils ************************/
await fetchEmojiJSON(); const { default: json } = await import(/*webpackChunkName: "emojis" */ './emojis.json');
_converse.emojis.json = json;
_converse.emojis_map = Object.keys(_converse.emojis.json).reduce((result, cat) => Object.assign(result, _converse.emojis.json[cat]), {}); _converse.emojis_map = Object.keys(_converse.emojis.json).reduce((result, cat) => Object.assign(result, _converse.emojis.json[cat]), {});
_converse.emojis_list = Object.keys(_converse.emojis.json).reduce((result, cat) => [...result, ...Object.values(_converse.emojis.json[cat])], []); _converse.emojis_list = Object.values(_converse.emojis_map);
_converse.emoji_shortnames = _converse.emojis_list.map(m => m.sn); _converse.emoji_shortnames = _converse.emojis_list.map(m => m.sn);
_converse.emoji_shortnames.sort(); _converse.emoji_shortnames.sort();
const getShortNames = () => _converse.emojis_list.map(emoji => emoji.sn.replace(/[+]/g, "\\$&")).join('|'); const getShortNames = () => _converse.emoji_shortnames.map(s => s.replace(/[+]/g, "\\$&")).join('|');
_converse.emojis.shortnames_regex = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+getShortNames()+")", "gi"); _converse.emojis.shortnames_regex = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+getShortNames()+")", "gi");
const excluded_categories = ['modifier', 'regional']; const excluded_categories = ['modifier', 'regional'];
......
...@@ -11,8 +11,10 @@ const config = { ...@@ -11,8 +11,10 @@ const config = {
"window": "window" "window": "window"
}], }],
output: { output: {
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'), // Output path for generated bundles
filename: 'converse.js' publicPath: '/dist/', // URL base path for all assets
filename: 'converse.js',
chunkFilename: 'converse.[name].js'
}, },
devtool: 'source-map', devtool: 'source-map',
plugins: [new MiniCssExtractPlugin({filename: '../dist/converse.css'})], plugins: [new MiniCssExtractPlugin({filename: '../dist/converse.css'})],
...@@ -139,37 +141,26 @@ function parameterize () { ...@@ -139,37 +141,26 @@ function parameterize () {
if (type === 'headless') { if (type === 'headless') {
console.log("Making a headless build"); console.log("Making a headless build");
extend(config, { config.entry = "@converse/headless/headless.js";
entry: "@converse/headless/headless.js", config.output.filename = 'converse-headless.js';
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'converse-headless.js'
},
});
} }
if (type === 'nodeps') { if (type === 'nodeps') {
console.log("Making a build without 3rd party dependencies"); console.log("Making a build without 3rd party dependencies");
extend(config, { config.output.filename = 'converse-no-dependencies.js';
entry: path.resolve(__dirname, 'src/converse.js'), config.externals = [{
externals: [{ "backbone": "backbone",
"backbone": "backbone", "backbone.nativeview": "backbone.nativeview",
"backbone.nativeview": "backbone.nativeview", "backbone.vdomview": "backbone.vdomview",
"backbone.vdomview": "backbone.vdomview", "backbone.browserStorage": "backbone.browserStorage",
"backbone.browserStorage": "backbone.browserStorage", "backbone.overview": "backbone.overview",
"backbone.overview": "backbone.overview", "es6-promise": "es6-promise",
"es6-promise": "es6-promise", "lodash": "lodash",
"lodash": "lodash", "lodash.converter": "lodash.converter",
"lodash.converter": "lodash.converter", "lodash.noconflict": "lodash.noconflict",
"lodash.noconflict": "lodash.noconflict", "strophe": "strophe",
"strophe": "strophe", "window": "window"
"window": "window" }];
}],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'converse-no-dependencies.js'
},
});
} }
if (type === 'css') { if (type === 'css') {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment