2021-01-21 21:06:52 +00:00
|
|
|
'use strict';
|
|
|
|
|
2020-11-23 13:24:19 -05:00
|
|
|
const minify = require('../../utils/Minify');
|
2021-01-21 21:06:52 +00:00
|
|
|
const plugins = require('../../../static/js/pluginfw/plugin_defs');
|
2021-02-11 13:43:10 -05:00
|
|
|
const settings = require('../../utils/Settings');
|
2020-11-23 13:24:19 -05:00
|
|
|
const CachingMiddleware = require('../../utils/caching_middleware');
|
|
|
|
const Yajsml = require('etherpad-yajsml');
|
2012-02-24 20:45:02 +01:00
|
|
|
|
2021-12-03 00:49:32 -05:00
|
|
|
const tar = (() => {
|
|
|
|
const associations = {
|
|
|
|
'pad.js': [
|
|
|
|
'pad.js',
|
|
|
|
'pad_utils.js',
|
|
|
|
'$js-cookie/dist/js.cookie.js',
|
|
|
|
'security.js',
|
|
|
|
'$security.js',
|
|
|
|
'vendors/browser.js',
|
|
|
|
'pad_cookie.js',
|
|
|
|
'pad_editor.js',
|
|
|
|
'pad_editbar.js',
|
|
|
|
'vendors/nice-select.js',
|
|
|
|
'pad_modals.js',
|
|
|
|
'pad_automatic_reconnect.js',
|
|
|
|
'ace.js',
|
|
|
|
'collab_client.js',
|
|
|
|
'cssmanager.js',
|
|
|
|
'pad_userlist.js',
|
|
|
|
'pad_impexp.js',
|
|
|
|
'pad_savedrevs.js',
|
|
|
|
'pad_connectionstatus.js',
|
|
|
|
'ChatMessage.js',
|
|
|
|
'chat.js',
|
|
|
|
'vendors/gritter.js',
|
|
|
|
'$js-cookie/dist/js.cookie.js',
|
|
|
|
'$tinycon/tinycon.js',
|
|
|
|
'vendors/farbtastic.js',
|
|
|
|
'skin_variants.js',
|
|
|
|
'socketio.js',
|
|
|
|
'colorutils.js',
|
|
|
|
],
|
|
|
|
'timeslider.js': [
|
|
|
|
'timeslider.js',
|
|
|
|
'colorutils.js',
|
|
|
|
'draggable.js',
|
|
|
|
'pad_utils.js',
|
|
|
|
'$js-cookie/dist/js.cookie.js',
|
|
|
|
'vendors/browser.js',
|
|
|
|
'pad_cookie.js',
|
|
|
|
'pad_editor.js',
|
|
|
|
'pad_editbar.js',
|
|
|
|
'vendors/nice-select.js',
|
|
|
|
'pad_modals.js',
|
|
|
|
'pad_automatic_reconnect.js',
|
|
|
|
'pad_savedrevs.js',
|
|
|
|
'pad_impexp.js',
|
|
|
|
'AttributePool.js',
|
|
|
|
'Changeset.js',
|
|
|
|
'domline.js',
|
|
|
|
'linestylefilter.js',
|
|
|
|
'cssmanager.js',
|
|
|
|
'broadcast.js',
|
|
|
|
'broadcast_slider.js',
|
|
|
|
'broadcast_revisions.js',
|
|
|
|
'socketio.js',
|
|
|
|
'AttributeManager.js',
|
|
|
|
'AttributeMap.js',
|
|
|
|
'attributes.js',
|
|
|
|
'ChangesetUtils.js',
|
|
|
|
],
|
|
|
|
'ace2_inner.js': [
|
|
|
|
'ace2_inner.js',
|
|
|
|
'vendors/browser.js',
|
|
|
|
'AttributePool.js',
|
|
|
|
'Changeset.js',
|
|
|
|
'ChangesetUtils.js',
|
|
|
|
'skiplist.js',
|
|
|
|
'colorutils.js',
|
|
|
|
'undomodule.js',
|
|
|
|
'$unorm/lib/unorm.js',
|
|
|
|
'contentcollector.js',
|
|
|
|
'changesettracker.js',
|
|
|
|
'linestylefilter.js',
|
|
|
|
'domline.js',
|
|
|
|
'AttributeManager.js',
|
|
|
|
'AttributeMap.js',
|
|
|
|
'attributes.js',
|
|
|
|
'scroll.js',
|
|
|
|
'caretPosition.js',
|
|
|
|
'pad_utils.js',
|
|
|
|
'$js-cookie/dist/js.cookie.js',
|
|
|
|
'security.js',
|
|
|
|
'$security.js',
|
|
|
|
],
|
|
|
|
'ace2_common.js': [
|
|
|
|
'ace2_common.js',
|
|
|
|
'vendors/browser.js',
|
|
|
|
'vendors/jquery.js',
|
|
|
|
'rjquery.js',
|
|
|
|
'$async.js',
|
|
|
|
'underscore.js',
|
|
|
|
'$underscore.js',
|
|
|
|
'$underscore/underscore.js',
|
|
|
|
'security.js',
|
|
|
|
'$security.js',
|
|
|
|
'pluginfw/client_plugins.js',
|
|
|
|
'pluginfw/plugin_defs.js',
|
|
|
|
'pluginfw/shared.js',
|
|
|
|
'pluginfw/hooks.js',
|
|
|
|
],
|
|
|
|
};
|
2021-02-11 13:43:10 -05:00
|
|
|
const prefixLocalLibraryPath = (path) => {
|
|
|
|
if (path.charAt(0) === '$') {
|
|
|
|
return path.slice(1);
|
|
|
|
} else {
|
|
|
|
return `ep_etherpad-lite/static/js/${path}`;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const tar = {};
|
2021-12-03 00:49:32 -05:00
|
|
|
for (const [key, relativeFiles] of Object.entries(associations)) {
|
2021-02-11 13:43:10 -05:00
|
|
|
const files = relativeFiles.map(prefixLocalLibraryPath);
|
|
|
|
tar[prefixLocalLibraryPath(key)] = files
|
|
|
|
.concat(files.map((p) => p.replace(/\.js$/, '')))
|
|
|
|
.concat(files.map((p) => `${p.replace(/\.js$/, '')}/index.js`));
|
|
|
|
}
|
|
|
|
return tar;
|
2021-12-03 00:49:32 -05:00
|
|
|
})();
|
2021-02-11 13:43:10 -05:00
|
|
|
|
2021-12-17 17:01:55 -05:00
|
|
|
exports.expressPreSession = async (hookName, {app}) => {
|
2012-03-04 23:45:33 +01:00
|
|
|
// Cache both minified and static.
|
2020-11-23 13:24:19 -05:00
|
|
|
const assetCache = new CachingMiddleware();
|
2021-12-17 17:01:55 -05:00
|
|
|
app.all(/\/javascripts\/(.*)/, assetCache.handle.bind(assetCache));
|
2012-03-04 23:45:33 +01:00
|
|
|
|
|
|
|
// Minify will serve static files compressed (minify enabled). It also has
|
|
|
|
// file-specific hacks for ace/require-kernel/etc.
|
2021-12-17 17:01:55 -05:00
|
|
|
app.all('/static/:filename(*)', minify.minify);
|
2012-03-04 23:45:33 +01:00
|
|
|
|
|
|
|
// Setup middleware that will package JavaScript files served by minify for
|
|
|
|
// CommonJS loader on the client-side.
|
Fix misparse of port when binding Unix socket
The hostname:port of URIs used in Minify are currently bogus and refer
to localhost only for historical reasons; there's no reason to retain
them and omitting them avoids generating an invalid URI when "port" is
not an integer.
Context: settings.port is passed to express's listen; if not numeric, it
is used a filename for a Unix domain socket.
This allows e.g. starting a server to be reverse-proxied on a multi-user
system, using the filesystem to handle access control and avoiding need
to allocate port numbers.
Before this change, etherpad-lite starts without error when configured
to listen on a Unix domain socket in this manner. However, `pad.js` and
`ace2_common.js` are generated incorrecting, causing an error
"Uncaught Error: The module at "ep_etherpad-lite/static/js/rjquery" does not exist."
when loading the editor:
When settings.port is a non-numeric string, e.g. `etherpad.sock`, a URI
of the form `http://localhost:etherpad.sock/static/js/rjquery.js` is
generated and parsed to find the file needed. In this case, the file
searched for is `:etherpad.sock/static/js/rjquery.js`, rather than the
expected `static/js/rjquery.js`. No such file exists, and the required
code is silently omitted from the bundle.
As a workaround, hard-code a (meaningless) hostname which can be parsed
correctly, since the current code makes no use of it anyway.
2018-07-28 04:38:17 -04:00
|
|
|
// Hostname "invalid.invalid" is a dummy value to allow parsing as a URI.
|
2020-11-23 13:24:19 -05:00
|
|
|
const jsServer = new (Yajsml.Server)({
|
|
|
|
rootPath: 'javascripts/src/',
|
|
|
|
rootURI: 'http://invalid.invalid/static/js/',
|
|
|
|
libraryPath: 'javascripts/lib/',
|
|
|
|
libraryURI: 'http://invalid.invalid/static/plugins/',
|
|
|
|
requestURIs: minify.requestURIs, // Loop-back is causing problems, this is a workaround.
|
2012-02-25 19:43:00 +01:00
|
|
|
});
|
|
|
|
|
2020-11-23 13:24:19 -05:00
|
|
|
const StaticAssociator = Yajsml.associators.StaticAssociator;
|
2021-12-03 00:49:32 -05:00
|
|
|
const associations = Yajsml.associators.associationsForSimpleMapping(tar);
|
2020-11-23 13:24:19 -05:00
|
|
|
const associator = new StaticAssociator(associations);
|
2012-03-04 23:45:33 +01:00
|
|
|
jsServer.setAssociator(associator);
|
2015-04-07 07:55:05 -05:00
|
|
|
|
2021-12-17 17:01:55 -05:00
|
|
|
app.use(jsServer.handle.bind(jsServer));
|
2012-03-04 23:45:33 +01:00
|
|
|
|
|
|
|
// serve plugin definitions
|
2021-01-21 21:06:52 +00:00
|
|
|
// not very static, but served here so that client can do
|
|
|
|
// require("pluginfw/static/js/plugin-definitions.js");
|
2021-12-17 17:01:55 -05:00
|
|
|
app.get('/pluginfw/plugin-definitions.json', (req, res, next) => {
|
2022-04-07 21:00:16 -04:00
|
|
|
// No need to tell clients about server-side hooks.
|
|
|
|
const stripServerSideHooks = (parts) => parts.reduce((parts, part) => {
|
|
|
|
if (part.client_hooks != null) {
|
|
|
|
if (part.hooks) part = {...part, hooks: undefined};
|
|
|
|
parts.push(part);
|
|
|
|
}
|
|
|
|
return parts;
|
|
|
|
}, []);
|
|
|
|
const clientParts = stripServerSideHooks(plugins.parts);
|
2020-11-23 13:24:19 -05:00
|
|
|
const clientPlugins = {};
|
2021-02-09 16:54:25 -05:00
|
|
|
for (const name of new Set(clientParts.map((part) => part.plugin))) {
|
2022-04-07 21:00:16 -04:00
|
|
|
const plugin = plugins.plugins[name];
|
|
|
|
clientPlugins[name] = {
|
|
|
|
...plugin,
|
|
|
|
parts: stripServerSideHooks(plugin.parts),
|
|
|
|
};
|
2021-02-09 16:54:25 -05:00
|
|
|
delete clientPlugins[name].package;
|
|
|
|
}
|
2021-02-13 08:13:48 +00:00
|
|
|
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
|
|
res.setHeader('Cache-Control', `public, max-age=${settings.maxAge}`);
|
2020-11-23 13:24:19 -05:00
|
|
|
res.write(JSON.stringify({plugins: clientPlugins, parts: clientParts}));
|
2012-03-04 23:45:33 +01:00
|
|
|
res.end();
|
2012-02-24 20:45:02 +01:00
|
|
|
});
|
2020-11-23 13:24:19 -05:00
|
|
|
};
|