boomack 0.8.2 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/client/public/js/client.js +41 -20
  2. package/client/themes/blue-night/properties.json +1 -0
  3. package/client/themes/dark/properties.json +1 -0
  4. package/client/themes/default/properties.json +1 -0
  5. package/client/themes/green-night/properties.json +1 -0
  6. package/client/themes/iron/properties.json +1 -0
  7. package/client/themes/red-night/properties.json +1 -0
  8. package/client/themes/science/properties.json +1 -0
  9. package/client/views/panel.ejs +3 -1
  10. package/client/views/parts/client-resources.ejs +6 -6
  11. package/client/views/parts/document-layout.ejs +2 -0
  12. package/client/views/parts/grid-layout.ejs +2 -0
  13. package/client/views/parts/panel-head.ejs +2 -0
  14. package/client/views/parts/slot.ejs +22 -4
  15. package/client/views/slot-panel.ejs +2 -1
  16. package/default-config.yaml +7 -2
  17. package/package.json +6 -5
  18. package/server-build/cli.js +0 -0
  19. package/server-build/index.js +47 -21
  20. package/server-build/pipeline/render.js +0 -1
  21. package/server-build/pipeline/render.test.js +5 -5
  22. package/server-build/pipeline/transform.test.js +1 -1
  23. package/server-build/pipeline.js +4 -3
  24. package/server-build/plugins/csv.js +3 -6
  25. package/server-build/plugins/generic.js +1 -1
  26. package/server-build/plugins/highlight.js +1 -1
  27. package/server-build/plugins/markdown.js +2 -2
  28. package/server-build/plugins/media.js +3 -3
  29. package/server-build/plugins/text.js +3 -3
  30. package/server-build/routes/eval-request.js +134 -0
  31. package/server-build/routes/eval-requests.js +152 -0
  32. package/server-build/routes/export.js +25 -10
  33. package/server-build/routes/panels.js +25 -28
  34. package/server-build/routes/web-client.js +80 -7
  35. package/server-build/service/client-resources.js +1 -1
  36. package/server-build/service/panels.js +5 -0
  37. package/server-build/service/plugins.js +74 -57
  38. package/server-build/service/plugins.test.js +14 -7
  39. package/server-build/service/render.js +7 -1
  40. package/server-build/service/render.test.js +11 -11
  41. package/server-build/service/transform.js +4 -2
  42. package/server-build/service/transform.test.js +4 -4
  43. package/server-build/typedefs.js +14 -5
@@ -57,35 +57,35 @@ window.boomack = window.boomack || {};
57
57
 
58
58
  var clientResourceGroups = {};
59
59
 
60
- ctx.registerClientResourceGroup = function (id, resourceIndices) {
60
+ ctx.registerClientResourceGroup = function (id, resourceGroupInfo) {
61
61
  trace('Registered client resource group "' + id + '"');
62
62
  clientResourceGroups[id] = {
63
63
  // id: id,
64
64
  state: false,
65
- css: resourceIndices.css,
66
- js: resourceIndices.js,
65
+ stylesCount: resourceGroupInfo.stylesCount || 0,
66
+ scriptsCount: resourceGroupInfo.scriptsCount || 0,
67
67
  };
68
68
  };
69
69
 
70
- function buildPluginResourceUrl(groupId, index) {
70
+ function buildPluginResourceUrl(groupId, type, index) {
71
71
  var pathPrefix = _.trim(ctx.pathPrefix, '/');
72
72
  if (pathPrefix) pathPrefix = '/' + pathPrefix;
73
73
  var location = _.trimEnd(window.location.origin, '/');
74
- return location + pathPrefix + '/plugins/client-resources/' + groupId + '/' + index;
74
+ return location + pathPrefix + '/plugins/' + type + '/' + groupId + '/' + index;
75
75
  }
76
76
 
77
- function injectClientResourceCss(groupId, index) {
77
+ function injectClientResourceStyle(groupId, index) {
78
78
  $('head').append(
79
- '<link rel="stylesheet" type="text/css" src="' +
80
- buildPluginResourceUrl(groupId, index) +
79
+ '<link rel="stylesheet" type="text/css" href="' +
80
+ buildPluginResourceUrl(groupId, 'styles', index) +
81
81
  '">');
82
82
  }
83
83
 
84
- function runInjectClientResourceJs(groupId, index) {
84
+ function runInjectClientResourceScript(groupId, index) {
85
85
  trace('run inject js', groupId, index);
86
86
  ctx.runAsync(function (cb) {
87
87
  trace('run execution inject js', groupId, index);
88
- $.getScript(buildPluginResourceUrl(groupId, index),
88
+ $.getScript(buildPluginResourceUrl(groupId, 'scripts', index),
89
89
  function () {
90
90
  trace('inject js callback', groupId, index);
91
91
  cb();
@@ -97,13 +97,17 @@ window.boomack = window.boomack || {};
97
97
  if (ctx.offline) return;
98
98
  var group = _.get(clientResourceGroups, id);
99
99
  if (!group) {
100
- console.err('Client resource group "' + id + '" not found.');
100
+ console.error('Client resource group "' + id + '" not found.');
101
101
  return;
102
102
  }
103
103
  if (group.loaded) return;
104
104
  group.loaded = 'loading';
105
- _.forEach(group.css, function (index) { injectClientResourceCss(id, index); });
106
- _.forEach(group.js, function (index) { runInjectClientResourceJs(id, index); });
105
+ for (var i = 0; i < group.stylesCount; i++) {
106
+ injectClientResourceStyle(id, i);
107
+ }
108
+ for (var i = 0; i < group.scriptsCount; i++) {
109
+ runInjectClientResourceScript(id, i);
110
+ }
107
111
  ctx.run(function () {
108
112
  group.loaded = true;
109
113
  trace('Loaded client resource group "' + id + '" on demand.');
@@ -357,6 +361,10 @@ window.boomack = window.boomack || {};
357
361
  updateExtensionsCount(slotId, slotE, count + 1);
358
362
  }
359
363
 
364
+ function updateVersion(slotE, version) {
365
+ setData(slotE, 'version', version)
366
+ }
367
+
360
368
  function limitExtensions(slotId, slotE, limit, extend, contentE) {
361
369
  let count = getExtensionsCount(slotId, slotE, contentE);
362
370
  const contentN = contentE[0];
@@ -475,6 +483,13 @@ window.boomack = window.boomack || {};
475
483
  const cmd = envelope.command;
476
484
  if (cmd.panel != ctx.panelId) return;
477
485
  const slotE = findSlot(cmd.slot);
486
+ const contentE = slotE.find('.slot-content');
487
+ if (!contentE) return;
488
+ const empty = contentE.is(':empty');
489
+ if (!empty && (cmd.extend == 'begin' || cmd.extend == 'end')) {
490
+ // handle race condition of extensions
491
+ if (cmd.version <= Number.parseInt(slotE.data('version'))) return;
492
+ }
478
493
  if (slotE.hasClass('paused')) {
479
494
  notifySlotContent(slotE, cmd);
480
495
  return;
@@ -483,19 +498,19 @@ window.boomack = window.boomack || {};
483
498
  titleE.html(cmd.title || '');
484
499
  notifySlotContent(slotE, cmd);
485
500
  clearSlotResizeHandlers(slotE.data('slot-id'));
486
- const contentE = slotE.find('.slot-content');
487
- if (!contentE) return;
488
501
  const extensionLimit = Number.parseInt(slotE.data('extension-limit') || 0);
489
- const empty = contentE.is(':empty');
490
502
  if (!empty && cmd.extend == 'begin') {
491
503
  contentE.prepend(cmd.content + '<!--' + CONTENT_SEPARATOR_TEXT + '-->');
504
+ updateVersion(slotE, cmd.version);
492
505
  incrementExtensionsCount(cmd.slot, slotE, contentE);
493
506
  limitExtensions(cmd.slot, slotE, extensionLimit, cmd.extend, contentE);
494
507
  } else if (!empty && cmd.extend == 'end') {
495
508
  contentE.append('<!--' + CONTENT_SEPARATOR_TEXT + '-->' + cmd.content);
509
+ updateVersion(slotE, cmd.version);
496
510
  incrementExtensionsCount(cmd.slot, slotE, contentE);
497
511
  limitExtensions(cmd.slot, slotE, extensionLimit, cmd.extend, contentE);
498
512
  } else {
513
+ updateVersion(slotE, cmd.version);
499
514
  updateExtensionsCount(cmd.slot, slotE, 0);
500
515
  showContent(slotE, cmd);
501
516
  }
@@ -543,8 +558,6 @@ window.boomack = window.boomack || {};
543
558
  }
544
559
  });
545
560
 
546
- socket.on('layout', updateLayout);
547
-
548
561
  socket.on('display', envelopes => {
549
562
  _.forEach(envelopes, displayMediaItemWithRequirements);
550
563
  });
@@ -568,6 +581,14 @@ window.boomack = window.boomack || {};
568
581
  window.location.reload();
569
582
  });
570
583
 
584
+ socket.on('reload-layout', () => {
585
+ $.get('/panels/' + ctx.panelId + '/layout' + (ctx.themeOverride ? '?theme=' + ctx.theme.name : ''),
586
+ (html, status) => {
587
+ trace('Layout reload', status);
588
+ updateLayout(html);
589
+ }, 'html');
590
+ });
591
+
571
592
  socket.on('action-error', err => {
572
593
  if (actionCallback) {
573
594
  actionCallback(err);
@@ -672,8 +693,8 @@ window.boomack = window.boomack || {};
672
693
  const transform = zoom == 1.0 ? 'none' : 'scale(' + zoom + ')';
673
694
  const contentE = slotE.find('.slot-content');
674
695
  contentE.css('transform', transform);
675
- contentE.css('min-width', 100.0 / zoom + '%');
676
- contentE.css('max-width', 100.0 / zoom + '%');
696
+ contentE.css('min-width', slotE.data('align') ? '' : 100.0 / zoom + '%');
697
+ contentE.css('max-width', slotE.data('align') ? '' : 100.0 / zoom + '%');
677
698
  const iframeE = slotE.find('iframe.isolated-slot-content');
678
699
  iframeE.css('transform', transform);
679
700
  iframeE.css('width', 100.0 / zoom + '%');
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "dark": true,
3
3
  "monoColor": [0, 0, 1],
4
+ "saturation": 0,
4
5
 
5
6
  "headline-font-family": "Roboto, 'Helvetica Neue', Arial, Helvetica, sans-serif",
6
7
  "headline-font-weight": "600",
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "dark": true,
3
3
  "monoColor": [0.917, 0.949, 0.965],
4
+ "saturation": 1,
4
5
 
5
6
  "headline-font-family": "Signika, Cambria, Times, serif",
6
7
  "headline-font-weight": "600",
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "dark": false,
3
3
  "monoColor": [1, 1, 1],
4
+ "saturation": 1,
4
5
 
5
6
  "headline-font-family": "Signika, Cambria, Times, serif",
6
7
  "headline-font-weight": "600",
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "dark": true,
3
3
  "monoColor": [0, 1, 0],
4
+ "saturation": 0,
4
5
 
5
6
  "headline-font-family": "Roboto, 'Helvetica Neue', Arial, Helvetica, sans-serif",
6
7
  "headline-font-weight": "600",
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "dark": true,
3
3
  "monoColor": [0.729, 0.863, 0.969],
4
+ "saturation": 0.95,
4
5
 
5
6
  "headline-font-family": "Roboto, 'Helvetica Neue', Arial, Helvetica, sans-serif",
6
7
  "headline-font-weight": "600",
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "dark": true,
3
3
  "monoColor": [1, 0, 0],
4
+ "saturation": 0,
4
5
 
5
6
  "headline-font-family": "Roboto, 'Helvetica Neue', Arial, Helvetica, sans-serif",
6
7
  "headline-font-weight": "600",
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "dark": false,
3
3
  "monoColor": [1, 1, 1],
4
+ "saturation": 1,
4
5
 
5
6
  "headline-font-family": "Archivo, 'Heveltica Neue', Arial, sans-serif",
6
7
  "headline-font-weight": "600",
@@ -2,7 +2,7 @@
2
2
  <html>
3
3
  <head>
4
4
  <%- include('parts/head.ejs', { title: (panel.layout.title || panel.id), offline }); %>
5
- <%- include('parts/panel-head.ejs', { basePath, panelId: panel.id, offline }); %>
5
+ <%- include('parts/panel-head.ejs', { basePath, panelId: panel.id, offline, theme, themeOverride }); %>
6
6
  <%- include('parts/theme-info.ejs', {
7
7
  theme,
8
8
  themeProperties,
@@ -64,6 +64,7 @@
64
64
  _,
65
65
  theme,
66
66
  themeOverride,
67
+ themeProperties,
67
68
  panel,
68
69
  offline,
69
70
  }); %><%
@@ -72,6 +73,7 @@
72
73
  _,
73
74
  theme,
74
75
  themeOverride,
76
+ themeProperties,
75
77
  panel,
76
78
  offline,
77
79
  }); %><%
@@ -11,12 +11,12 @@
11
11
  } else {
12
12
  _.forEach(clientRes.getResourceGroupsForPanel(panel, slot), groupId => {
13
13
  const group = _.get(clientResGroups, groupId);
14
- _.forEach(group.css, index => {
15
- %> <link rel="stylesheet" type="text/css" href="<%- basePath + 'plugins/client-resources/' + groupId + '/' + index %>" />
16
- <% });
17
- _.forEach(group.js, index => {
18
- %> <script src="<%- basePath + 'plugins/client-resources/' + groupId + '/' + index %>"></script>
19
- <% });
14
+ for (let i = 0; i < group.stylesCount; i++) {
15
+ %> <link rel="stylesheet" type="text/css" href="<%- basePath + 'plugins/styles/' + groupId + '/' + i %>" />
16
+ <% }
17
+ for (let i = 0; i < group.scriptsCount; i++) {
18
+ %> <script type="application/javascript" src="<%- basePath + 'plugins/scripts/' + groupId + '/' + i %>"></script>
19
+ <% }
20
20
  });
21
21
  }
22
22
  %>
@@ -5,6 +5,7 @@ expects context:
5
5
  - basePath {string}
6
6
  - theme {string}
7
7
  - themeOverride {boolean}
8
+ - themeProperties {Object}
8
9
  - panel {Panel}
9
10
  - offline {boolean}
10
11
 
@@ -18,6 +19,7 @@ expects context:
18
19
  basePath,
19
20
  theme,
20
21
  themeOverride,
22
+ themeProperties,
21
23
  panel,
22
24
  slot,
23
25
  offline,
@@ -5,6 +5,7 @@ expects context:
5
5
  - basePath {string}
6
6
  - theme {string}
7
7
  - themeOverride {boolean}
8
+ - themeProperties {Object}
8
9
  - panel {Panel}
9
10
  - offline {boolean}
10
11
 
@@ -24,6 +25,7 @@ expects context:
24
25
  basePath,
25
26
  theme,
26
27
  themeOverride,
28
+ themeProperties,
27
29
  panel,
28
30
  slot,
29
31
  offline,
@@ -6,4 +6,6 @@
6
6
  window.boomack.pathPrefix = "<%- basePath %>";
7
7
  window.boomack.panelId = <%- panelId ? '"' + panelId + '"' : 'null' %>;
8
8
  window.boomack.offline = <%- offline %>;
9
+ window.boomack.theme = "<%- theme %>";
10
+ window.boomack.themeOverride = <%- themeOverride %>;
9
11
  </script>
@@ -7,6 +7,7 @@ expects context:
7
7
  - slot {Slot}
8
8
  - theme {string}
9
9
  - themeOverride {boolean}
10
+ - themeProperties {Object}
10
11
  - offline {boolean}
11
12
  - singled {boolean}
12
13
 
@@ -56,6 +57,7 @@ if (tbMaximize) toolbarWidth += 39;
56
57
  data-history="<%= slot.history || 0 %>"
57
58
  data-max-sequence-no="<%= command ? command.no : 0 %>"
58
59
  data-sequence-no="<%= command ? command.no : 0 %>"
60
+ data-version="<%= command ? command.version : 0 %>"
59
61
  data-extension-limit="<%= slot.extensions || 0 %>"
60
62
  data-extensions="<%= command ? command.extensions : 0 %>"
61
63
  data-zoom="<%= slot.zoom %>"
@@ -156,6 +158,22 @@ if (tbMaximize) toolbarWidth += 39;
156
158
  ), ' ') %><%
157
159
  }
158
160
  %>" /></filter></svg><%
161
+ } else if (slot.colorFilter === 'theme') {
162
+ var s = Math.min(1, Math.max(0, themeProperties.saturation));
163
+ var si = 1.0 - s;
164
+ var rv = themeProperties.monoColor[0];
165
+ var gv = themeProperties.monoColor[1];
166
+ var bv = themeProperties.monoColor[2];
167
+ var rM = 0.2125, gM = 0.7154, bM = 0.0721;
168
+ var cf = [
169
+ rv * (s + rM * si), rv * gM * si, rv * bM * si, 0, 0,
170
+ gv * rM * si, gv * (s + gM * si), gv * bM * si, 0, 0,
171
+ bv * rM * si, bv * gM * si, bv * (s + bM * si), 0, 0,
172
+ 0, 0, 0, 1, 0
173
+ ];
174
+ %><svg style="display: hidden; position: absolute; width: 0; height: 0;"><filter id="slot-color-filter-<%= slot.id %>"><feColorMatrix in="SourceGraphic" type="matrix" values="<%
175
+ %><%= _.join(cf, ' ') %><%
176
+ %>" /></filter></svg><%
159
177
  } %>
160
178
  <div class="slot-background" style="<%
161
179
  if (slot.minHeight) {
@@ -177,9 +195,9 @@ if (tbMaximize) toolbarWidth += 39;
177
195
  %>display:none;<%
178
196
  }
179
197
  if (slot.colorFilter) {
180
- if (_.isString(slot.colorFilter)) {
198
+ if (_.isString(slot.colorFilter) && slot.colorFilter !== 'theme') {
181
199
  %>filter: <%= slot.colorFilter %>;<%
182
- } else if (_.isArray(slot.colorFilter)) {
200
+ } else if (_.isArray(slot.colorFilter) || slot.colorFilter === 'theme') {
183
201
  %>filter: url(#slot-color-filter-<%= slot.id %>);<%
184
202
  }
185
203
  }
@@ -192,9 +210,9 @@ if (tbMaximize) toolbarWidth += 39;
192
210
  %><div class="slot-content" style="<%
193
211
  if (slot.zoom !== 1.0 && !contentScale) {
194
212
  %>transform:scale(<%= slot.zoom %>);<%
195
- %>min-width:<%= 100.0 / slot.zoom %>%;<%
213
+ if (!contentAlign) { %>min-width:<%= 100.0 / slot.zoom %>%;<% }
196
214
  %>width:auto;<%
197
- %>max-width:<%= 100.0 / slot.zoom %>%;<%
215
+ if (!contentAlign) { %>max-width:<%= 100.0 / slot.zoom %>%;<% }
198
216
  }
199
217
  %>"><%
200
218
  if (commandContent) {
@@ -2,7 +2,7 @@
2
2
  <html>
3
3
  <head>
4
4
  <%- include('parts/head.ejs', { title: panel.id + ' – ' + slot.id, offline }); %>
5
- <%- include('parts/panel-head.ejs', { basePath, panelId: panel.id, offline }); %>
5
+ <%- include('parts/panel-head.ejs', { basePath, panelId: panel.id, offline, theme, themeOverride }); %>
6
6
  <%- include('parts/theme-info.ejs', {
7
7
  theme,
8
8
  themeProperties,
@@ -23,6 +23,7 @@
23
23
  basePath,
24
24
  theme,
25
25
  themeOverride,
26
+ themeProperties,
26
27
  panel,
27
28
  slot,
28
29
  offline,
@@ -199,9 +199,14 @@ cache:
199
199
  global: 4 MB
200
200
 
201
201
  plugins:
202
- # search the globally installed node packages for plugins
202
+ # The root directory where to find plugin packages.
203
+ # If not set, npm is used to find the global node_modules folder.
204
+ root: null
205
+ # Search the plugin root for plugin packages.
206
+ # If plugins.root is not set, searches for globally installed packages.
207
+ # Plugin packages must start with 'boomack-plugin-'.
203
208
  discover: false
204
- # a list with node package names of plugins to use
209
+ # A list with node package names of plugins to use.
205
210
  packages: []
206
211
 
207
212
  export:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "boomack",
3
- "version": "0.8.2",
3
+ "version": "0.9.2",
4
4
  "description": "web app for displaying hyper-media items in concert with e.g. an IDE",
5
5
  "author": "Tobias Kiertscher <dev@mastersign.de>",
6
6
  "license": "MIT",
@@ -29,6 +29,7 @@
29
29
  "chardet": "^0.8.0",
30
30
  "commonmark": "^0.29.3",
31
31
  "cookie-parser": "^1.4.5",
32
+ "cors": "^2.8.5",
32
33
  "csv-parse": "^4.15.1",
33
34
  "ejs": "^2.7.4",
34
35
  "express": "^4.17.1",
@@ -36,9 +37,9 @@
36
37
  "got": "^10.7.0",
37
38
  "iconv-lite": "^0.5.2",
38
39
  "lodash": "^4.17.20",
39
- "markdown-it": "^10.0.0",
40
- "markdown-it-container": "^2.0.0",
41
- "markdown-it-emoji": "^1.4.0",
40
+ "markdown-it": "^12.3.2",
41
+ "markdown-it-container": "^3.0.0",
42
+ "markdown-it-emoji": "^2.0.0",
42
43
  "markdown-it-ins": "^3.0.1",
43
44
  "markdown-it-mark": "^3.0.1",
44
45
  "markdown-it-sub": "^1.0.0",
@@ -74,7 +75,7 @@
74
75
  "gulp-text-simple": "^0.5.4",
75
76
  "jquery": "^3.5.1",
76
77
  "jsdoc": "^3.6.6",
77
- "mocha": "^6.2.3",
78
+ "mocha": "^9.2.1",
78
79
  "nock": "^11.9.1",
79
80
  "typescript": "^4.1.5"
80
81
  },
File without changes
@@ -4,6 +4,7 @@ const chalk = require('chalk');
4
4
  const async = require('async');
5
5
  const open = require('open');
6
6
  const express = require('express');
7
+ const cors = require('cors');
7
8
  const app = express();
8
9
  const http = require('http');
9
10
  const server = http.createServer(app);
@@ -154,35 +155,55 @@ function loadCorePlugIns(cb) {
154
155
  plugins.register(require('./plugins/media'));
155
156
  cb(null);
156
157
  }
157
- function loadPlugIn(packageName, cb) {
158
- plugins.load(packageName, (err, plugin) => {
159
- if (err) {
160
- cb(err);
161
- return;
162
- }
158
+ function loadPlugIn(pluginRoot, packageName) {
159
+ try {
160
+ const plugin = plugins.load(pluginRoot, packageName);
163
161
  plugins.register(plugin);
164
162
  log.info(`PlugIn loaded: ${plugin.id}`);
165
- cb(null);
166
- });
163
+ return true;
164
+ }
165
+ catch (err) {
166
+ log.error(`Failed to load plugin from package '${packageName}': ${err}`);
167
+ return false;
168
+ }
167
169
  }
168
170
  function loadPlugIns(cb) {
169
- log.info('Loading external plugins');
171
+ let pluginRoot = cfg.get('plugins.root');
172
+ if (!pluginRoot) {
173
+ try {
174
+ pluginRoot = plugins.getGlobalNodeModules();
175
+ }
176
+ catch (err) {
177
+ cb(err);
178
+ return;
179
+ }
180
+ }
181
+ log.info(`Loading external plugins from: ${pluginRoot}`);
170
182
  const discover = utils.parseBoolean(cfg.get('plugins.discover', false));
171
183
  const explicitPkgNames = new Set(cfg.get('plugins.packages', []));
172
- let tasks = [
173
- cb => async.eachSeries(explicitPkgNames, loadPlugIn, cb)
174
- ];
175
- if (discover) {
176
- tasks.push(cb => plugins.discover('boomack-plugin-', cb), (discoveredPkgNames, cb) => async.eachSeries(_.filter(discoveredPkgNames, pn => !explicitPkgNames.has(pn)), loadPlugIn, cb));
184
+ let success = true;
185
+ for (const name of explicitPkgNames) {
186
+ success && (success = loadPlugIn(pluginRoot, name));
177
187
  }
178
- async.waterfall(tasks, err => {
179
- if (err) {
180
- cb(new Error("Loading PlugIns failed with: " + err.message));
188
+ if (discover) {
189
+ log.info(`Discovering plugins`);
190
+ let discoveredPkgNames = [];
191
+ try {
192
+ discoveredPkgNames = plugins.discover(pluginRoot, 'boomack-plugin-');
181
193
  }
182
- else {
183
- cb(null);
194
+ catch (err) {
195
+ log.error(`Discovering plugins failed with: ${err}`);
184
196
  }
185
- });
197
+ for (const name of discoveredPkgNames) {
198
+ success && (success = loadPlugIn(pluginRoot, name));
199
+ }
200
+ }
201
+ if (success) {
202
+ cb(null);
203
+ }
204
+ else {
205
+ cb(new Error("Loading plugins failed."));
206
+ }
186
207
  }
187
208
  function loadPresets(cb) {
188
209
  log.info('Loading presets from configuration');
@@ -286,6 +307,7 @@ function setupApp(cb) {
286
307
  log.http(`${req.method} ${req.url}`);
287
308
  next();
288
309
  });
310
+ app.use(cors());
289
311
  require('./routes/web-client').setup(app, io);
290
312
  require('./routes/panels').setup(app, io);
291
313
  require('./routes/presets').setup(app, io);
@@ -328,7 +350,11 @@ function startServer(cb) {
328
350
  return;
329
351
  }
330
352
  else {
331
- log.info(`Server listening on http://${host}:${port}/`);
353
+ log.info(`Server is listening on http://${host}:${port}/`);
354
+ const publicUrl = cfg.serverBaseUrl();
355
+ if (`http://${host}:${port}/` !== publicUrl) {
356
+ log.info(`Public URL of the server is ${publicUrl}`);
357
+ }
332
358
  cb(null);
333
359
  }
334
360
  })
@@ -13,7 +13,6 @@ const displayRequestModel = require('../model/display-request');
13
13
  const resources = require('../service/resources');
14
14
  const render = require('../service/render');
15
15
  const displayTaskHelper = require('../service/display-task-helper');
16
- const highlight = require('../service/highlight');
17
16
  /**
18
17
  * Selects the render function for the given {@link DisplayTask}.
19
18
  *
@@ -77,12 +77,12 @@ describe('pipeline/render', function () {
77
77
  plugins.register({
78
78
  id: 'test-plugin',
79
79
  renderers: {
80
- 'test-renderer': (u, t, o) => {
81
- passedUrl = u;
82
- passedType = t;
83
- passedOptions = o;
80
+ 'test-renderer': (url, { type, options }) => {
81
+ passedUrl = url;
82
+ passedType = type;
83
+ passedOptions = options;
84
84
  return {
85
- html: `<a href="${u}">link</a>`,
85
+ html: `<a href="${url}">link</a>`,
86
86
  requires: ['client-resource-group-1'],
87
87
  };
88
88
  },
@@ -43,7 +43,7 @@ describe('pipeline/transform', function () {
43
43
  plugins.register({
44
44
  id: 'test-plugin',
45
45
  textTransformations: {
46
- 'test-transformation': ({ text, options }) => {
46
+ 'test-transformation': (text, { options }) => {
47
47
  passedText = text;
48
48
  passedOptions = options;
49
49
  return {
@@ -26,13 +26,11 @@
26
26
  *
27
27
  * @module
28
28
  */
29
- const fs = require('fs');
30
29
  const _ = require('lodash');
31
30
  const async = require('async');
32
- const { isFileUrl, isHttpUrl, error, parseDataAmount } = require('./utils');
31
+ const { isFileUrl, error, parseDataAmount } = require('./utils');
33
32
  const displayRequestModel = require('./model/display-request');
34
33
  const cfg = require('./service/config');
35
- const encode = require('./service/char-encoding');
36
34
  const mimeType = require('./service/mime-type');
37
35
  const mediaTypes = require('./service/media-types');
38
36
  const html = require('./service/html');
@@ -460,6 +458,7 @@ function buildDisplayCommand(displayTask) {
460
458
  src: t.output.src,
461
459
  extend: o.extend,
462
460
  extensions: 0,
461
+ version: 0,
463
462
  requires: mergeClientResourcGroupRequirements(displayTask),
464
463
  scale: o.scale,
465
464
  align: o.scale ? null : o.align,
@@ -493,6 +492,7 @@ function buildDisplayCommandForError(err, displayRequest, displayTask) {
493
492
  no: null,
494
493
  extend: extend,
495
494
  extensions: 0,
495
+ version: 0,
496
496
  content: html.errorMessage('Unknown Error', 'An unknown error occured. This is defenitly a bug!'),
497
497
  resource: null,
498
498
  background: null,
@@ -506,6 +506,7 @@ function buildDisplayCommandForError(err, displayRequest, displayTask) {
506
506
  no: null,
507
507
  extend: extend,
508
508
  extensions: 0,
509
+ version: 0,
509
510
  content: html.errorMessage(err.title, err.message, err.details),
510
511
  resource: null,
511
512
  background: null,
@@ -64,18 +64,15 @@ const parse = require('csv-parse');
64
64
  const uuid = require('uuid/v4');
65
65
  const html = require('../service/html');
66
66
  exports.id = 'core-csv';
67
- exports.clientResourceGroups = {
67
+ exports.scripts = {
68
68
  'tablesort': [
69
- {
70
- type: 'application/javascript',
71
- path: path.join(__dirname, 'client-resources', 'tablesort.js'),
72
- },
69
+ path.join(__dirname, 'client-resources', 'tablesort.js'),
73
70
  ],
74
71
  };
75
72
  exports.textTransformations = {
76
73
  'csv-table': textTransformationCsvTable,
77
74
  };
78
- async function textTransformationCsvTable({ text, options }) {
75
+ async function textTransformationCsvTable(text, { options }) {
79
76
  const detectColumns = _.isNil(options.columns) || options.columns === true;
80
77
  let columns = _.isArray(options.columns) ? options.columns : null;
81
78
  return new Promise((resolve, reject) => {
@@ -18,7 +18,7 @@ exports.id = 'core-generic';
18
18
  exports.renderers = {
19
19
  'generic': renderTemplate,
20
20
  };
21
- function renderTemplate(url, type, options) {
21
+ function renderTemplate(url, { options }) {
22
22
  let html = options.template || '';
23
23
  return html.replace(/\{\{\s*url\s*\}\}/g, url);
24
24
  }
@@ -23,7 +23,7 @@ exports.id = 'core-highlight';
23
23
  exports.textTransformations = {
24
24
  'highlight': textTransformationHighlight,
25
25
  };
26
- function textTransformationHighlight({ text, options }) {
26
+ function textTransformationHighlight(text, { options }) {
27
27
  const language = _.get(options, 'syntax');
28
28
  let result = text;
29
29
  if (!language) {