@signageos/front-display 14.21.0 → 14.21.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/dist/console.js CHANGED
@@ -4,312 +4,410 @@
4
4
  Include console.js to any application to display a semi-transparent overlay
5
5
  with contents of the web console. This is useful for environments where the
6
6
  console is not available. This code should work in almost any browser and does
7
- not need to be transpiled
7
+ not need to be transpiled.
8
+
9
+ A query string after console.js can be used to set primitive settings values (such as depth, fontSize, disableShadow, defaultColor).
8
10
 
9
11
  Example use:
10
- <script type="text/javascript" language="javascript" src="js/console.js"></script>
12
+ <script type="text/javascript" language="javascript" src="js/console.js?fontSize=14"></script>
11
13
  */
12
14
  'use strict';
13
15
 
14
- var errorsMap = {};
16
+ (function () {
17
+ var SETTINGS = {
18
+ /** Maximal depth of displayed object, if depth is exhausted remaining values are rendered inline. */
19
+ depth: 3,
20
+
21
+ /** Which console methods are displayed on screen, currently supported methods are: error, warn, info, log. */
22
+ patchedMethods: /** @type {ConsoleMethod[]} */ (['error', 'warn', 'info', 'log']),
23
+
24
+ /** Dictionary of console method => color, for each patched method. */
25
+ colors: /** @type {Record<string, string>} */ ({
26
+ error: 'lightcoral',
27
+ warn: 'gold',
28
+ }),
29
+
30
+ /** Default color of text, if colors does not contain value for a method. */
31
+ defaultColor: 'white',
32
+
33
+ /** Font size of the console */
34
+ fontSize: '14px',
15
35
 
16
- // Polyfill for Error constructor with stack for older browsers
17
- var ErrorOrig = Error;
18
- var ErrorWithStack = function (message) {
19
- this.name = 'Error';
20
- if (!(this instanceof ErrorWithStack)) {
21
- return new ErrorWithStack(message);
36
+ /** Disable text-shadow in the console, this may make the text harder to read. */
37
+ disableShadow: false,
38
+
39
+ /**
40
+ * Polyfill ErrorEvent.error property, this is disabled by default. This polyfill is not entirely spec compliant and may cause memory
41
+ * leaks in the application.
42
+ */
43
+ polyfillErrorStack: false,
44
+ };
45
+
46
+ /** @param {string} name */
47
+ function getParameterByName(name) {
48
+ name = name.replace(/[\[\]]/g, '\\$&');
49
+ var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
50
+ results = regex.exec(/** @type {HTMLScriptElement} */ (document.currentScript).src);
51
+ if (!results) {
52
+ return null;
53
+ }
54
+ if (!results[2]) {
55
+ return '';
56
+ }
57
+ return decodeURIComponent(results[2].replace(/\+/g, ' '));
22
58
  }
23
- var stack;
24
- try {
25
- throw new ErrorOrig();
26
- } catch (error) {
27
- stack = error.stack;
59
+
60
+ if (document.currentScript) {
61
+ SETTINGS.depth = Number(getParameterByName('depth')) || SETTINGS.depth;
62
+ SETTINGS.fontSize = Number(getParameterByName('fontSize')) ? Number(getParameterByName('fontSize')) + 'px' : SETTINGS.fontSize;
63
+ SETTINGS.disableShadow = getParameterByName('disableShadow') !== null;
64
+ SETTINGS.defaultColor = getParameterByName('defaultColor') || SETTINGS.defaultColor;
65
+ SETTINGS.polyfillErrorStack = getParameterByName('polyfillErrorStack') !== null;
28
66
  }
29
- this.constructor = ErrorWithStack;
30
- this.message = message;
31
- this.stack = stack;
32
- errorsMap[message] = this;
33
- };
34
- ErrorWithStack.prototype = ErrorOrig.prototype;
35
- window.Error = ErrorWithStack;
36
-
37
- // Polyfill ErrorEvent.error of addEventListener('error') for older browsers
38
- window.addEventListener('error', function (event) {
39
- if (event.error === undefined) {
40
- // Not standardized. ErrorEvent.message can be prefixed with 'Error: ' or 'Uncaught Error: ' based on version of chrome
41
- var errorMessage = Object.keys(errorsMap).find(function (key) {
42
- return event.message.indexOf(key) !== -1;
67
+
68
+ if (SETTINGS.polyfillErrorStack) {
69
+ var errorsMap = {};
70
+
71
+ // Polyfill for Error constructor with stack for older browsers
72
+ var ErrorOrig = Error;
73
+ /** @param {string} message */
74
+ var ErrorWithStack = function (message) {
75
+ this.name = 'Error';
76
+ if (!(this instanceof ErrorWithStack)) {
77
+ return new ErrorWithStack(message);
78
+ }
79
+ var stack;
80
+ try {
81
+ throw new ErrorOrig();
82
+ } catch (error) {
83
+ stack = error.stack;
84
+ }
85
+ this.constructor = ErrorWithStack;
86
+ this.message = message;
87
+ this.stack = stack;
88
+ errorsMap[message] = this;
89
+ };
90
+ ErrorWithStack.prototype = ErrorOrig.prototype;
91
+ window.Error = /** @type {any} */ (ErrorWithStack);
92
+
93
+ // Polyfill ErrorEvent.error of addEventListener('error') for older browsers
94
+ window.addEventListener('error', function (event) {
95
+ if (event.error === undefined) {
96
+ // Not standardized. ErrorEvent.message can be prefixed with 'Error: ' or 'Uncaught Error: ' based on version of chrome
97
+ var errorMessage = Object.keys(errorsMap).find(function (key) {
98
+ return event.message.indexOf(key) !== -1;
99
+ });
100
+ if (errorMessage) {
101
+ var error = errorsMap[errorMessage];
102
+ delete errorsMap[errorMessage];
103
+ // @ts-ignore error is not defined in ErrorEvent for old browsers so it's not read-only
104
+ event.error = error;
105
+ }
106
+ }
43
107
  });
44
- if (errorMessage) {
45
- var error = errorsMap[errorMessage];
46
- delete errorsMap[errorMessage];
47
- // @ts-ignore error is not defined in ErrorEvent for old browsers so it's not read-only
48
- event.error = error;
49
- }
50
108
  }
51
- });
52
109
 
53
- var DEFAULT_DEPTH = 3;
110
+ /** @type {[string, unknown][] | null} */
111
+ var preMountQueue = [];
54
112
 
55
- // Console settings
56
- /** @type {ConsoleMethod[]} */
57
- var patchedMethods = ['error', 'warn', 'info', 'log'];
113
+ /** @type {HTMLIFrameElement} */
114
+ var iframe;
58
115
 
59
- /** @type {Record<string, string>} */
60
- var colors = {
61
- error: 'lightcoral',
62
- warn: 'gold',
63
- };
116
+ /** @type {HTMLTableElement} */
117
+ var log;
64
118
 
65
- // Console settings end
119
+ /**
120
+ * @param {string} level
121
+ * @param {unknown} content
122
+ */
123
+ function reportToScreen(level, content) {
124
+ if (preMountQueue === null) {
125
+ var color = SETTINGS.colors[level] || SETTINGS.defaultColor;
66
126
 
67
- /** @type {[string, unknown][] | null} */
68
- var preMountQueue = [];
127
+ var row = document.createElement('tr');
69
128
 
70
- /** @type {HTMLTableElement} */
71
- var log;
129
+ row.style.color = color;
72
130
 
73
- /**
74
- * @param {string} level
75
- * @param {unknown} content
76
- */
77
- function reportToScreen(level, content) {
78
- if (preMountQueue === null) {
79
- var color = colors[level];
80
- if (!color) {
81
- color = 'white';
82
- }
131
+ ['[' + level + ']:', formatAny(content, SETTINGS.depth)].forEach(function (itm) {
132
+ var td = document.createElement('td');
133
+ td.style.verticalAlign = 'top';
83
134
 
84
- addLine(['[' + level + ']:', formatAny(content)], color);
85
- } else {
86
- preMountQueue.push([level, content]);
135
+ var pre = document.createElement('pre');
136
+ pre.style.margin = '0';
137
+
138
+ pre.appendChild(typeof itm === 'string' ? document.createTextNode(itm) : itm);
139
+ td.appendChild(pre);
140
+ row.appendChild(td);
141
+ });
142
+
143
+ var firstChild = log.childNodes[0];
144
+
145
+ log.insertBefore(row, firstChild);
146
+ } else {
147
+ preMountQueue.push([level, content]);
148
+ }
87
149
  }
88
- }
89
150
 
90
- /**
91
- * @param {(string | HTMLDivElement)[]} content
92
- * @param {string} color
93
- */
94
- function addLine(content, color) {
95
- var row = document.createElement('tr');
151
+ /**
152
+ * @param {unknown} content
153
+ * @param {number} depth
154
+ * @returns {HTMLElement}
155
+ */
156
+ function formatAny(content, depth) {
157
+ var indent = SETTINGS.depth - depth;
158
+
159
+ if (depth <= 0 || isInlineable(content, depth)) {
160
+ try {
161
+ return block([
162
+ JSON.stringify(content, function (_, v) {
163
+ return typeof v === 'bigint' ? v.toString() + 'n' : v;
164
+ }),
165
+ ]);
166
+ } catch (e) {
167
+ return block(['{ ... }']);
168
+ }
169
+ }
96
170
 
97
- row.style.color = color;
171
+ /** @type {(string | HTMLElement)[]} */
172
+ var lines = [];
98
173
 
99
- content.forEach(function (itm) {
100
- var td = document.createElement('td');
101
- td.style.verticalAlign = 'top';
174
+ if (Array.isArray(content)) {
175
+ lines.push('[\n');
176
+ content.forEach(function (itm) {
177
+ lines.push(indentWS(indent + 1), formatAny(itm, depth - 1), '\n');
178
+ });
179
+ lines.push(']');
180
+ return block(lines);
181
+ }
102
182
 
103
- var pre = document.createElement('pre');
104
- pre.style.margin = '0';
183
+ if (content instanceof Error) {
184
+ lines.push('Error {\n');
105
185
 
106
- pre.appendChild(typeof itm === 'string' ? document.createTextNode(itm + '\n') : itm);
107
- td.appendChild(pre);
108
- row.appendChild(td);
109
- });
186
+ lines.push(block([indentWS(indent + 1), 'name: "' + content.name + '"\n']));
187
+ lines.push(block([indentWS(indent + 1), 'message: "' + content.message + '"\n']));
110
188
 
111
- var firstChild = log.childNodes[0];
189
+ var stackStr = 'stack: "' + String(content.stack).replace(new RegExp('\n', 'g'), '\n' + indentWS(indent + 1)) + '"\n';
190
+ lines.push(block([indentWS(indent + 1), stackStr]));
191
+ lines.push('}');
192
+ return block(lines);
193
+ }
112
194
 
113
- log.insertBefore(row, firstChild);
114
- }
195
+ if (content instanceof ErrorEvent) {
196
+ lines.push('ErrorEvent {');
115
197
 
116
- /**
117
- * @param {unknown} content
118
- * @param {number} [depth]
119
- * @returns {HTMLDivElement}
120
- */
121
- function formatAny(content, depth) {
122
- depth = depth === undefined ? DEFAULT_DEPTH : depth;
198
+ lines.push(block([indentWS(indent + 1), 'message: "' + content.message + '"']));
199
+ lines.push(block([indentWS(indent + 1), 'filename: "' + content.filename.substr(content.filename.length - 50) + '"']));
200
+ lines.push(block([indentWS(indent + 1), 'lineno:colno: ' + content.lineno + ':' + content.colno]));
201
+ lines.push(block([indentWS(indent + 1), 'error: ', formatAny(content.error, depth - 1)]));
202
+ lines.push('}');
203
+ return block(lines);
204
+ }
123
205
 
124
- if (depth <= 0) {
125
- return indentedBlock(['{...}']);
126
- }
206
+ if (typeof content === 'bigint') {
207
+ return block([content + 'n']);
208
+ }
127
209
 
128
- /** @type {(string | HTMLDivElement)[]} */
129
- var lines = [];
210
+ if (typeof content === 'symbol' || content === undefined) {
211
+ return block([String(content)]);
212
+ }
130
213
 
131
- if (isInlineable(content)) {
132
- return indentedBlock([JSON.stringify(content)]);
133
- }
214
+ if (typeof content === 'function') {
215
+ var name = content.name;
216
+ if (!name) {
217
+ name = 'function';
218
+ }
219
+ return block([name + '()']);
220
+ }
134
221
 
135
- if (Array.isArray(content)) {
136
- lines.push('[');
137
- content.forEach(function (itm) {
138
- lines.push(formatAny(itm));
139
- });
140
- lines.push(']');
141
- return indentedBlock(lines);
142
- }
222
+ if (content instanceof Date) {
223
+ lines.push('Date(', content.toISOString(), ')');
224
+ return block(lines);
225
+ }
143
226
 
144
- if (content instanceof Error) {
145
- lines.push('Error {');
227
+ if (content && typeof content === 'object') {
228
+ if (!isPlainObject(content)) {
229
+ var proto = Object.getPrototypeOf(content);
230
+ if (proto.constructor) {
231
+ lines.push(proto.constructor.name, ' ');
232
+ }
233
+ }
234
+
235
+ lines.push('{\n');
236
+ Object.keys(content).forEach(function (key) {
237
+ lines.push(block([indentWS(indent + 1), key + ': ', formatAny(content[key], depth - 1), '\n']));
238
+ });
239
+ lines.push(indentWS(indent) + '}');
240
+ return block(lines);
241
+ }
146
242
 
147
- lines.push(indentedBlock(['name: "' + content.name + '"']));
148
- lines.push(indentedBlock(['message: "' + content.message + '"']));
149
- lines.push(indentedBlock(['stack: "' + String(content.stack) + '"']));
150
- lines.push('}');
151
- return indentedBlock(lines);
243
+ try {
244
+ return block([JSON.stringify(content)]);
245
+ } catch (e) {
246
+ return block(['{ Unable to display value ' + String(content) + ' }']);
247
+ }
152
248
  }
153
249
 
154
- if (content instanceof ErrorEvent) {
155
- lines.push('ErrorEvent {');
250
+ /** @param {(string | HTMLElement)[]} lines */
251
+ function block(lines) {
252
+ var el = document.createElement('span');
253
+ el.style.whiteSpace = 'pre';
156
254
 
157
- lines.push(indentedBlock(['message: "' + content.message + '"']));
158
- lines.push(indentedBlock(['filename: "' + content.filename.substr(content.filename.length - 50) + '"']));
159
- lines.push(indentedBlock(['lineno:colno: ' + content.lineno + ':' + content.colno]));
160
- lines.push(indentedBlock(['error: ', formatAny(content.error)]));
161
- lines.push('}');
162
- return indentedBlock(lines);
255
+ lines.forEach(function (itm) {
256
+ el.appendChild(typeof itm === 'string' ? document.createTextNode(itm) : itm);
257
+ });
258
+ return el;
163
259
  }
164
260
 
165
- if (typeof content === 'bigint') {
166
- return indentedBlock([content + 'n']);
261
+ /** @param {number} i */
262
+ function indentWS(i) {
263
+ return repeatString(' ', i);
167
264
  }
168
265
 
169
- if (typeof content === 'symbol' || content === undefined) {
170
- return indentedBlock([String(content)]);
266
+ /**
267
+ * All console keys which values are callable
268
+ * @typedef {{ [K in keyof Console]: Console[K] extends (...x: any[]) => any ? K : never}[keyof Console]} ConsoleMethod
269
+ */
270
+
271
+ /**
272
+ * @param {ConsoleMethod} level
273
+ */
274
+ function patch(level) {
275
+ var original = window.console[level];
276
+
277
+ var func = function () {
278
+ var args = Array.prototype.slice.call(arguments);
279
+ reportToScreen(level, args);
280
+ original.apply(console, args);
281
+ };
282
+ window.console[level] = func.bind(window.console);
171
283
  }
172
284
 
173
- if (typeof content === 'function') {
174
- var name = content.name;
175
- if (!name) {
176
- name = 'function';
285
+ /**
286
+ * @param {unknown} content
287
+ * @param {number} depth
288
+ * @returns {boolean}
289
+ */
290
+ function isInlineable(content, depth) {
291
+ if (depth <= 0) {
292
+ return false;
177
293
  }
178
- return indentedBlock([name + '()']);
179
- }
180
294
 
181
- if (content && typeof content === 'object') {
182
- lines.push('{');
183
- Object.keys(content).forEach(function (key) {
184
- lines.push(indentedBlock([key + ': ', formatAny(content[key], depth - 1)]));
185
- });
186
- lines.push('}');
187
- return indentedBlock(lines);
188
- }
295
+ if (Array.isArray(content)) {
296
+ return content.every(function (c) {
297
+ return isInlineable(c, depth - 1);
298
+ });
299
+ }
189
300
 
190
- try {
191
- return indentedBlock([JSON.stringify(content)]);
192
- } catch (e) {
193
- return indentedBlock(['{ Unable to display value ' + String(content) + ' }']);
194
- }
195
- }
196
-
197
- /**
198
- * @param {(string | HTMLDivElement)[]} lines
199
- */
200
- function indentedBlock(lines) {
201
- var block = document.createElement('div');
202
- block.style.paddingLeft = '1em';
203
- block.style.whiteSpace = 'pre';
204
-
205
- lines.forEach(function (itm) {
206
- block.appendChild(typeof itm === 'string' ? document.createTextNode(itm + '\n') : itm);
207
- });
208
- return block;
209
- }
301
+ if (isPlainObject(content)) {
302
+ return Object.keys(content).every(function (k) {
303
+ return isInlineable(content[k], depth - 1);
304
+ });
305
+ }
210
306
 
211
- /**
212
- * All console keys which values are callable
213
- * @typedef {{ [K in keyof Console]: Console[K] extends (...x: any[]) => any ? K : never}[keyof Console]} ConsoleMethod
214
- */
307
+ return typeof content === 'boolean' || typeof content === 'number' || typeof content === 'string' || content === null;
308
+ }
215
309
 
216
- /**
217
- * @param {ConsoleMethod} level
218
- */
219
- function patch(level) {
220
- var original = window.console[level];
310
+ /**
311
+ * @param {unknown} value
312
+ * @returns {value is object}
313
+ */
314
+ function isPlainObject(value) {
315
+ if (typeof value !== 'object' || value === null) {
316
+ return false;
317
+ }
221
318
 
222
- var func = function () {
223
- var args = Array.prototype.slice.call(arguments);
224
- reportToScreen(level, args);
225
- original.apply(console, args);
226
- };
227
- window.console[level] = func.bind(window.console);
228
- }
229
-
230
- /**
231
- * @param {unknown} content
232
- * @param {number} [depth]
233
- * @returns {boolean}
234
- */
235
- function isInlineable(content, depth) {
236
- depth = depth === undefined ? DEFAULT_DEPTH : depth;
237
- if (depth <= 0) {
238
- return false;
319
+ var proto = Object.getPrototypeOf(value);
320
+ return proto !== null && Object.getPrototypeOf(proto) === null;
239
321
  }
240
322
 
241
- if (Array.isArray(content)) {
242
- return content.every(function (c) {
243
- return isInlineable(c, depth - 1);
244
- });
323
+ /**
324
+ * @param {string} str
325
+ * @param {number} count
326
+ */
327
+ function repeatString(str, count) {
328
+ var result = '';
329
+ for (var i = 0; i < count; i++) {
330
+ result += str;
331
+ }
332
+ return result;
245
333
  }
246
334
 
247
- if (isPlainObject(content)) {
248
- return Object.keys(content).every(function (k) {
249
- return isInlineable(/** @type {any} */ content[k], depth - 1);
250
- });
251
- }
335
+ SETTINGS.patchedMethods.forEach(function (m) {
336
+ patch(m);
337
+ });
252
338
 
253
- return typeof content === 'boolean' || typeof content === 'number' || typeof content === 'string' || content === null;
254
- }
339
+ function init() {
340
+ if (!preMountQueue) {
341
+ return;
342
+ }
255
343
 
256
- /**
257
- * @param {unknown} value
258
- * @returns {value is object}
259
- */
260
- function isPlainObject(value) {
261
- if (typeof value !== 'object' || value === null) {
262
- return false;
263
- }
344
+ iframe = document.createElement('iframe');
345
+ document.body.appendChild(iframe);
346
+
347
+ iframe.style.position = 'absolute';
348
+ iframe.style.top = '0';
349
+ iframe.style.left = '0';
350
+ iframe.style.right = '0';
351
+ iframe.style.bottom = '0';
352
+ iframe.style.zIndex = '99999';
353
+ iframe.style.width = '100%';
354
+ iframe.style.height = '100%';
355
+ iframe.style.border = 'none';
356
+ iframe.style.fontSize = SETTINGS.fontSize;
357
+ iframe.style.fontFamily = "'courier new',monospace";
358
+ iframe.style.pointerEvents = 'none';
359
+
360
+ log = document.createElement('table');
361
+
362
+ log.style.position = 'absolute';
363
+ log.style.top = '0';
364
+ log.style.left = '0';
365
+ log.style.right = '0';
366
+ log.style.bottom = '0';
367
+ log.style.zIndex = '99999';
368
+ if (!SETTINGS.disableShadow) {
369
+ log.style.textShadow = repeatString('0px 0px 6px #000, ', 10) + '0px 0px 8px #000';
370
+ }
371
+ log.style.color = 'white';
372
+ log.style.whiteSpace = 'pre';
373
+ log.style.fontSize = SETTINGS.fontSize;
264
374
 
265
- var proto = Object.getPrototypeOf(value);
266
- return proto !== null && Object.getPrototypeOf(proto) === null;
267
- }
375
+ function onIframeLoad() {
376
+ if (!preMountQueue || !iframe.contentDocument) {
377
+ throw new Error('Unreachable');
378
+ }
268
379
 
269
- patchedMethods.forEach(function (m) {
270
- patch(m);
271
- });
380
+ iframe.contentDocument.body.appendChild(log);
272
381
 
273
- function init() {
274
- if (!preMountQueue) {
275
- return;
276
- }
382
+ var q = preMountQueue;
383
+ preMountQueue = null;
277
384
 
278
- log = document.createElement('table');
279
- document.body.appendChild(log);
280
-
281
- log.style.position = 'absolute';
282
- log.style.top = '0';
283
- log.style.left = '0';
284
- log.style.right = '0';
285
- log.style.bottom = '0';
286
- log.style.zIndex = '99999';
287
- log.style.textShadow = '-1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000';
288
- log.style.color = 'white';
289
- log.style.whiteSpace = 'pre';
290
- log.style.fontFamily = "'courier new',monospace";
291
-
292
- var q = preMountQueue;
293
- preMountQueue = null;
294
-
295
- q.forEach(function (entry) {
296
- reportToScreen(entry[0], entry[1]);
297
- });
298
- }
385
+ q.forEach(function (entry) {
386
+ reportToScreen(entry[0], entry[1]);
387
+ });
388
+ }
389
+
390
+ if (iframe.contentDocument && iframe.contentDocument.readyState === 'complete') {
391
+ onIframeLoad();
392
+ } else {
393
+ iframe.addEventListener('load', onIframeLoad);
394
+ }
395
+ }
299
396
 
300
- var documentReady = document.readyState === 'complete' || document.readyState === 'interactive';
397
+ var documentReady = document.readyState === 'complete' || document.readyState === 'interactive';
301
398
 
302
- if (documentReady) {
303
- init();
304
- } else {
305
- window.addEventListener('DOMContentLoaded', function () {
399
+ if (documentReady) {
306
400
  init();
307
- });
308
- }
401
+ } else {
402
+ window.addEventListener('DOMContentLoaded', function () {
403
+ init();
404
+ });
405
+ }
309
406
 
310
- window.addEventListener('error', function () {
311
- var args = Array.prototype.slice.call(arguments);
312
- reportToScreen('onerror', args);
313
- });
407
+ window.addEventListener('error', function () {
408
+ var args = Array.prototype.slice.call(arguments);
409
+ reportToScreen('onerror', args);
410
+ });
314
411
 
315
- reportToScreen('ready', 'On screen console has loaded');
412
+ reportToScreen('ready', 'On screen console has loaded');
413
+ })();