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.
- package/client/public/js/client.js +41 -20
- package/client/themes/blue-night/properties.json +1 -0
- package/client/themes/dark/properties.json +1 -0
- package/client/themes/default/properties.json +1 -0
- package/client/themes/green-night/properties.json +1 -0
- package/client/themes/iron/properties.json +1 -0
- package/client/themes/red-night/properties.json +1 -0
- package/client/themes/science/properties.json +1 -0
- package/client/views/panel.ejs +3 -1
- package/client/views/parts/client-resources.ejs +6 -6
- package/client/views/parts/document-layout.ejs +2 -0
- package/client/views/parts/grid-layout.ejs +2 -0
- package/client/views/parts/panel-head.ejs +2 -0
- package/client/views/parts/slot.ejs +22 -4
- package/client/views/slot-panel.ejs +2 -1
- package/default-config.yaml +7 -2
- package/package.json +6 -5
- package/server-build/cli.js +0 -0
- package/server-build/index.js +47 -21
- package/server-build/pipeline/render.js +0 -1
- package/server-build/pipeline/render.test.js +5 -5
- package/server-build/pipeline/transform.test.js +1 -1
- package/server-build/pipeline.js +4 -3
- package/server-build/plugins/csv.js +3 -6
- package/server-build/plugins/generic.js +1 -1
- package/server-build/plugins/highlight.js +1 -1
- package/server-build/plugins/markdown.js +2 -2
- package/server-build/plugins/media.js +3 -3
- package/server-build/plugins/text.js +3 -3
- package/server-build/routes/eval-request.js +134 -0
- package/server-build/routes/eval-requests.js +152 -0
- package/server-build/routes/export.js +25 -10
- package/server-build/routes/panels.js +25 -28
- package/server-build/routes/web-client.js +80 -7
- package/server-build/service/client-resources.js +1 -1
- package/server-build/service/panels.js +5 -0
- package/server-build/service/plugins.js +74 -57
- package/server-build/service/plugins.test.js +14 -7
- package/server-build/service/render.js +7 -1
- package/server-build/service/render.test.js +11 -11
- package/server-build/service/transform.js +4 -2
- package/server-build/service/transform.test.js +4 -4
- 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,
|
|
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
|
-
|
|
66
|
-
|
|
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/
|
|
74
|
+
return location + pathPrefix + '/plugins/' + type + '/' + groupId + '/' + index;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
function
|
|
77
|
+
function injectClientResourceStyle(groupId, index) {
|
|
78
78
|
$('head').append(
|
|
79
|
-
'<link rel="stylesheet" type="text/css"
|
|
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
|
|
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.
|
|
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
|
-
|
|
106
|
-
|
|
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 + '%');
|
package/client/views/panel.ejs
CHANGED
|
@@ -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
|
-
|
|
15
|
-
%> <link rel="stylesheet" type="text/css" href="<%- basePath + 'plugins/
|
|
16
|
-
<% }
|
|
17
|
-
|
|
18
|
-
%> <script src="<%- basePath + 'plugins/
|
|
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,
|
package/default-config.yaml
CHANGED
|
@@ -199,9 +199,14 @@ cache:
|
|
|
199
199
|
global: 4 MB
|
|
200
200
|
|
|
201
201
|
plugins:
|
|
202
|
-
#
|
|
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
|
-
#
|
|
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.
|
|
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": "^
|
|
40
|
-
"markdown-it-container": "^
|
|
41
|
-
"markdown-it-emoji": "^
|
|
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": "^
|
|
78
|
+
"mocha": "^9.2.1",
|
|
78
79
|
"nock": "^11.9.1",
|
|
79
80
|
"typescript": "^4.1.5"
|
|
80
81
|
},
|
package/server-build/cli.js
CHANGED
|
File without changes
|
package/server-build/index.js
CHANGED
|
@@ -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(
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
173
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
188
|
+
if (discover) {
|
|
189
|
+
log.info(`Discovering plugins`);
|
|
190
|
+
let discoveredPkgNames = [];
|
|
191
|
+
try {
|
|
192
|
+
discoveredPkgNames = plugins.discover(pluginRoot, 'boomack-plugin-');
|
|
181
193
|
}
|
|
182
|
-
|
|
183
|
-
|
|
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': (
|
|
81
|
-
passedUrl =
|
|
82
|
-
passedType =
|
|
83
|
-
passedOptions =
|
|
80
|
+
'test-renderer': (url, { type, options }) => {
|
|
81
|
+
passedUrl = url;
|
|
82
|
+
passedType = type;
|
|
83
|
+
passedOptions = options;
|
|
84
84
|
return {
|
|
85
|
-
html: `<a href="${
|
|
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': (
|
|
46
|
+
'test-transformation': (text, { options }) => {
|
|
47
47
|
passedText = text;
|
|
48
48
|
passedOptions = options;
|
|
49
49
|
return {
|
package/server-build/pipeline.js
CHANGED
|
@@ -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,
|
|
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.
|
|
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(
|
|
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,
|
|
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(
|
|
26
|
+
function textTransformationHighlight(text, { options }) {
|
|
27
27
|
const language = _.get(options, 'syntax');
|
|
28
28
|
let result = text;
|
|
29
29
|
if (!language) {
|