@ceeblue/web-utils 2.6.0 → 3.0.0

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/README.md CHANGED
@@ -27,6 +27,13 @@ import { Util, ILog } from '@ceeblue/web-utils';
27
27
  > }
28
28
  > ```
29
29
 
30
+ > ⚠️ **REMARKS**
31
+ >
32
+ > To debug production code without modifying it, the library can use special query parameter of the main page's URL:
33
+ > - __!cb-override-log-level__ : allows to override the log level for the entire library, see [Log.ts](./src/Log.ts) for details on handling log levels.
34
+
35
+
36
+
30
37
  ## Building locally
31
38
 
32
39
  1. [Clone](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) this repository
@@ -72,10 +72,124 @@ declare class BinaryWriter {
72
72
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
73
73
  * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
74
74
  */
75
+ /**
76
+ * Log levels
77
+ */
78
+ declare enum LogLevel {
79
+ ERROR = "error",
80
+ WARN = "warn",
81
+ INFO = "info",
82
+ DEBUG = "debug"
83
+ }
84
+ /**
85
+ * Log interface to deal with log everywhere:
86
+ * - filter log level: filter log level independantly of the browser
87
+ * - subscribe logs: listen logs to effectuate some specific job related logs
88
+ * - intercept logs: intercept logs to change the default behavior
89
+ * - redirect logs: redirect logs to one other logger engine
90
+ * - redefine logs: change log text like adding a prefix
91
+ *
92
+ * You have 4 {@link LogLevel} 'error','warn','info',and 'debug', as commonly managed by browsers.
93
+ * You can use {@link ILog.level} or {@link ILog.on} to customer log level and behavior.
94
+ *
95
+ * @example
96
+ * // filter log level globally, independantly of the browser
97
+ * import { log } from '@ceeblue/web-utils';
98
+ * log.level = LogLevel.WARN; // displays errors and warns
99
+ *
100
+ * // filter log level only for Player compoment
101
+ * player.log.level = false; // no logs at all for player compoment
102
+ *
103
+ * // Intercept and redirect all the logs to the console (default behavior)
104
+ * import { log } from '@ceeblue/web-utils';
105
+ * log.on = (level:LogLevel,args:unknown[]) => {
106
+ * console[level](...args.splice(0)); // args is empty after this call = final interception
107
+ * }
108
+ *
109
+ * // Intercept the logs from Player compoment and displays only WARN logs
110
+ * player.log.on = (level:LogLevel,args:unknown[]) => {
111
+ * if (level !== LogLevel.WARN) {
112
+ * args.length = 0; // args is empty after this call = final interception
113
+ * }
114
+ * }
115
+ *
116
+ * // Subscribe and redirect all the logs to a file logger
117
+ * import { log } from '@ceeblue/web-utils';
118
+ * log.on = (level:LogLevel,args:unknown[]) => {
119
+ * fileLogger[level](...args); // args stays unchanged to let's continue the default behavior
120
+ * }
121
+ *
122
+ * // Redefine the log to add some prefix indication
123
+ * class Player {
124
+ * connector = new Connector();
125
+ * constructor() {
126
+ * connector.log = this.log.bind(this,"Connector log:");
127
+ * }
128
+ * }
129
+ *
130
+ */
131
+ interface ILog {
132
+ /**
133
+ * Build a log
134
+ */
135
+ (...args: unknown[]): Log;
136
+ /**
137
+ * Intercept,redefine or redirect any log
138
+ * If you clear args you intercept the log and nothing happen more after this call.
139
+ * @param type log level
140
+ * @param args args
141
+ * @returns
142
+ */
143
+ on: (level: LogLevel, args: unknown[]) => void;
144
+ /**
145
+ * Change log level, default log level is {@link LogLevel.INFO},
146
+ * Boolean can be user to lets pass all the logs with `true` or disables all the logs with `false`.
147
+ * @note To debug production code without modifying it you can use a special query parameter
148
+ * called !cb-override-log-level to override this configuration.
149
+ */
150
+ level?: LogLevel | boolean;
151
+ }
152
+ /**
153
+ * Log instance
154
+ */
155
+ declare class Log {
156
+ get error(): (...args: any[]) => void;
157
+ get warn(): (...args: any[]) => void;
158
+ get info(): (...args: any[]) => void;
159
+ get debug(): (...args: any[]) => void;
160
+ private _args;
161
+ private _done?;
162
+ private _log;
163
+ constructor(log: ILog, ...args: unknown[]);
164
+ private _onLog;
165
+ private _bind;
166
+ }
167
+ /**
168
+ * Inherits from this class to use logs
169
+ */
170
+ declare class Loggable {
171
+ /**
172
+ * Start a log
173
+ * @param args
174
+ * @returns a Log object with the levels of log to call
175
+ */
176
+ log: ILog;
177
+ }
178
+ /**
179
+ * Global log
180
+ */
181
+ declare const log: ILog;
182
+
183
+ /**
184
+ * Copyright 2024 Ceeblue B.V.
185
+ * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
186
+ * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
187
+ */
188
+
75
189
  /**
76
190
  * BitReader allows to read binary data bit by bit
77
191
  */
78
- declare class BitReader {
192
+ declare class BitReader extends Loggable {
79
193
  private _data;
80
194
  private _size;
81
195
  private _position;
@@ -179,99 +293,6 @@ declare namespace Connect {
179
293
  export { type Connect_Params as Params, Connect_Type as Type, Connect_buildURL as buildURL, Connect_defineMediaExt as defineMediaExt };
180
294
  }
181
295
 
182
- /**
183
- * Copyright 2024 Ceeblue B.V.
184
- * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
185
- * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
186
- */
187
- /**
188
- * Log interface to deal with log everywhere:
189
- * - subscribe logs: listen logs to effectuate some specific job related logs
190
- * - intercept logs: intercept logs to change the default behavior
191
- * - redirect logs: redirect logs to one other logger engine
192
- * - redefine logs: change log text like adding a prefix
193
- *
194
- * You have 4 {@link LogType} 'error', 'warn', 'info', and 'debug', as commonly managed by browsers.
195
- *
196
- * @example
197
- * // Intercept and redirect all the logs to the console (default behavior)
198
- * import { log } from '@ceeblue/web-utils';
199
- * log.on(type:LogType, args:uknown[]) => {
200
- * console[type](...args.splice(0)); // args is empty after this call = final interception
201
- * }
202
- *
203
- * // Intercept and redirect the logs from Player compoment to the console
204
- * player.log.on(type:LogType, args:uknown[]) => {
205
- * console[type](...args.splice(0)); // args is empty after this call = final interception
206
- * }
207
- *
208
- * // Subscribe and redirect all the logs to a file logger
209
- * log.on(type:LogType, args:uknown[]) => {
210
- * fileLogger[type](...args); // args stays unchanged to let's continue the default behavior
211
- * }
212
- *
213
- * // Redefine the log to add some prefix indication
214
- * class Player {
215
- * connector = new Connector();
216
- * constructor() {
217
- * connector.log = this.log.bind(this, "Connector log:");
218
- * }
219
- * }
220
- *
221
- */
222
- interface ILog {
223
- /**
224
- * Build a log
225
- */
226
- (...args: unknown[]): Log;
227
- /**
228
- * Intercept, redefine or redirect any log
229
- * If you clear args you intercept the log and nothing happen more after this call.
230
- * @param type log level
231
- * @param args args
232
- * @returns
233
- */
234
- on: (type: LogType, args: unknown[]) => void;
235
- }
236
- /**
237
- * Log types
238
- */
239
- declare enum LogType {
240
- ERROR = "error",
241
- WARN = "warn",
242
- INFO = "info",
243
- DEBUG = "debug"
244
- }
245
- /**
246
- * Log instance
247
- */
248
- declare class Log {
249
- get error(): (...args: any[]) => void;
250
- get warn(): (...args: any[]) => void;
251
- get info(): (...args: any[]) => void;
252
- get debug(): (...args: any[]) => void;
253
- private _args;
254
- private _done?;
255
- private _onLog;
256
- constructor(onLog: Function, ...args: unknown[]);
257
- private _bind;
258
- }
259
- /**
260
- * Inherits from this class to use logs
261
- */
262
- declare class Loggable {
263
- /**
264
- * Start a log
265
- * @param args
266
- * @returns a Log object with the levels of log to call
267
- */
268
- log: ILog;
269
- }
270
- /**
271
- * Global log
272
- */
273
- declare const log: ILog;
274
-
275
296
  /**
276
297
  * Copyright 2024 Ceeblue B.V.
277
298
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
@@ -694,7 +715,7 @@ declare function timeOrigin(): number;
694
715
  * @param urlOrQueryOrSearch string, url, or searchParams containing query. If not set it uses `location.search` to determinate query.
695
716
  * @returns An javascript object containing each option
696
717
  */
697
- declare function options(urlOrQueryOrSearch?: URL | URLSearchParams | string | object | undefined): object;
718
+ declare function options(urlOrQueryOrSearch?: URL | URLSearchParams | string | object | undefined): any;
698
719
  /**
699
720
  * Returns an easy-to-use Javascript object something iterable, such as a Map, Set, or Array
700
721
  * @param value iterable input
@@ -705,7 +726,7 @@ declare function options(urlOrQueryOrSearch?: URL | URLSearchParams | string | o
705
726
  declare function objectFrom(value: any, params: {
706
727
  withType: boolean;
707
728
  noEmptyString: boolean;
708
- }): object;
729
+ }): any;
709
730
  /**
710
731
  * Returns entries from something iterable, such as a Map, Set, or Array
711
732
  * @param value iterable input
@@ -1020,4 +1041,4 @@ declare namespace EpochTime {
1020
1041
 
1021
1042
  declare const VERSION: string;
1022
1043
 
1023
- export { BinaryReader, BinaryWriter, BitReader, ByteRate, Connect, EpochTime, EventEmitter, FixMap, type ILog, Log, LogType, Loggable, NetAddress, Numbers, Queue, SDP, Util, VERSION, WebSocketReliable, type WebSocketReliableError, log };
1044
+ export { BinaryReader, BinaryWriter, BitReader, ByteRate, Connect, EpochTime, EventEmitter, FixMap, type ILog, Log, LogLevel, Loggable, NetAddress, Numbers, Queue, SDP, Util, VERSION, WebSocketReliable, type WebSocketReliableError, log };
package/dist/web-utils.js CHANGED
@@ -275,87 +275,6 @@ class BinaryWriter {
275
275
  this._view = undefined; // release view
276
276
  return this;
277
277
  }
278
- }/**
279
- * Copyright 2024 Ceeblue B.V.
280
- * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
281
- * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
282
- */
283
- /**
284
- * BitReader allows to read binary data bit by bit
285
- */
286
- class BitReader {
287
- constructor(data) {
288
- if ('buffer' in data) {
289
- this._data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
290
- }
291
- else {
292
- this._data = new Uint8Array(data);
293
- }
294
- this._size = this._data.byteLength;
295
- this._position = 0;
296
- this._bit = 0;
297
- }
298
- data() {
299
- return this._data;
300
- }
301
- size() {
302
- return this._size;
303
- }
304
- available() {
305
- return (this._size - this._position) * 8 - this._bit;
306
- }
307
- next(count = 1) {
308
- let gotten = 0;
309
- while (this._position !== this._size && count--) {
310
- ++gotten;
311
- if (++this._bit === 8) {
312
- this._bit = 0;
313
- ++this._position;
314
- }
315
- }
316
- return gotten;
317
- }
318
- read(count = 1) {
319
- let result = 0;
320
- while (this._position !== this._size && count--) {
321
- result <<= 1;
322
- if (this._data[this._position] & (0x80 >> this._bit++)) {
323
- result |= 1;
324
- }
325
- if (this._bit === 8) {
326
- this._bit = 0;
327
- ++this._position;
328
- }
329
- }
330
- return result;
331
- }
332
- read8() {
333
- return this.read(8);
334
- }
335
- read16() {
336
- return this.read(16);
337
- }
338
- read24() {
339
- return this.read(24);
340
- }
341
- read32() {
342
- return this.read(32);
343
- }
344
- readExpGolomb() {
345
- let i = 0;
346
- while (!this.read()) {
347
- if (!this.available()) {
348
- return 0;
349
- }
350
- ++i;
351
- }
352
- const result = this.read(i);
353
- if (i > 15) {
354
- console.warn('Exponential-Golomb code exceeding unsigned 16 bits');
355
- return 0;
356
- }
357
- return result + (1 << i) - 1;
358
- }
359
278
  }/******************************************************************************
360
279
  Copyright (c) Microsoft Corporation.
361
280
 
@@ -563,12 +482,15 @@ function stringify(obj, params = {}) {
563
482
  }
564
483
  return (res += space + ']');
565
484
  }
566
- let res = '';
485
+ let res = '{';
567
486
  for (const name in obj) {
568
- res += (res ? ',' : '{') + space + name + ':';
569
- res += stringify(obj[name], Object.assign(Object.assign({}, params), { recursion: params.recursion - 1 }));
487
+ if (res.length > 1) {
488
+ res += ',';
489
+ }
490
+ res += space + name + ':';
491
+ res += stringify(obj[name], Object.assign(Object.assign({}, params), { recursion: params.recursion - 1 })) + space;
570
492
  }
571
- return (res += space + '}');
493
+ return (res += '}');
572
494
  }
573
495
  /**
574
496
  * Encode a string to a binary representation
@@ -727,6 +649,197 @@ function trimEnd(value, chars = ' ') {
727
649
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
728
650
  * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
729
651
  */
652
+ /**
653
+ * Log levels
654
+ */
655
+ var LogLevel;
656
+ (function (LogLevel) {
657
+ LogLevel["ERROR"] = "error";
658
+ LogLevel["WARN"] = "warn";
659
+ LogLevel["INFO"] = "info";
660
+ LogLevel["DEBUG"] = "debug";
661
+ })(LogLevel || (LogLevel = {}));
662
+ // check coder issuer: everytime we don't forget to use the built Log
663
+ let _logging = 0;
664
+ setInterval(() => {
665
+ console.assert(_logging === 0, _logging.toFixed(), 'calls to log was useless');
666
+ }, 10000);
667
+ // !cb-override-log-level
668
+ const _overrideLogLevel = options()['!cb-override-log-level'];
669
+ const _charLevels = new Array(128);
670
+ _charLevels[101] = _charLevels[69] = 1; // error
671
+ _charLevels[119] = _charLevels[87] = 2; // warn
672
+ _charLevels[105] = _charLevels[73] = 3; // info
673
+ _charLevels[100] = _charLevels[68] = 4; // debug
674
+ /**
675
+ * Log instance
676
+ */
677
+ class Log {
678
+ get error() {
679
+ return this._bind(LogLevel.ERROR);
680
+ }
681
+ get warn() {
682
+ return this._bind(LogLevel.WARN);
683
+ }
684
+ get info() {
685
+ return this._bind(LogLevel.INFO);
686
+ }
687
+ get debug() {
688
+ return this._bind(LogLevel.DEBUG);
689
+ }
690
+ constructor(log, ...args) {
691
+ if (!args.length) {
692
+ // cannot have 0 args to be called correctly!
693
+ args.push(undefined);
694
+ }
695
+ this._args = args;
696
+ this._log = log;
697
+ ++_logging;
698
+ }
699
+ _onLog(localLog, level) {
700
+ var _a, _b;
701
+ // we take like log-level by priority order:
702
+ // 1- the overrideLogLevel
703
+ // 2- the localLog.level
704
+ // 3- the global log.level
705
+ // 4- LogLevel.INFO
706
+ const logLevel = (_b = (_a = _overrideLogLevel !== null && _overrideLogLevel !== void 0 ? _overrideLogLevel : localLog.level) !== null && _a !== void 0 ? _a : log.level) !== null && _b !== void 0 ? _b : LogLevel.INFO;
707
+ if (logLevel === false) {
708
+ // explicit null, no log at all!
709
+ return false;
710
+ }
711
+ if (logLevel !== true && _charLevels[level.charCodeAt(0)] > _charLevels[logLevel.charCodeAt(0)]) {
712
+ return false;
713
+ }
714
+ if (localLog.on) {
715
+ localLog.on(level, this._args);
716
+ }
717
+ return this._args.length ? true : false;
718
+ }
719
+ _bind(level) {
720
+ if (!this._done) {
721
+ this._done = true;
722
+ --_logging;
723
+ }
724
+ // call the global onLog in first (global filter)
725
+ if (!this._onLog(log, level)) {
726
+ return EMPTY_FUNCTION;
727
+ }
728
+ // call the local onLog (local filter)
729
+ if (this._log !== log && !this._onLog(this._log, level)) {
730
+ return EMPTY_FUNCTION;
731
+ }
732
+ // if not intercepted display the log
733
+ return console[level].bind(console, ...this._args);
734
+ }
735
+ }
736
+ /**
737
+ * Inherits from this class to use logs
738
+ */
739
+ class Loggable {
740
+ constructor() {
741
+ /**
742
+ * Start a log
743
+ * @param args
744
+ * @returns a Log object with the levels of log to call
745
+ */
746
+ this.log = ((...args) => {
747
+ return new Log(this.log, ...args);
748
+ });
749
+ }
750
+ }
751
+ /**
752
+ * Global log
753
+ */
754
+ const log = ((...args) => {
755
+ return new Log(log, ...args);
756
+ });/**
757
+ * Copyright 2024 Ceeblue B.V.
758
+ * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
759
+ * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
760
+ */
761
+ /**
762
+ * BitReader allows to read binary data bit by bit
763
+ */
764
+ class BitReader extends Loggable {
765
+ constructor(data) {
766
+ super();
767
+ if ('buffer' in data) {
768
+ this._data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
769
+ }
770
+ else {
771
+ this._data = new Uint8Array(data);
772
+ }
773
+ this._size = this._data.byteLength;
774
+ this._position = 0;
775
+ this._bit = 0;
776
+ }
777
+ data() {
778
+ return this._data;
779
+ }
780
+ size() {
781
+ return this._size;
782
+ }
783
+ available() {
784
+ return (this._size - this._position) * 8 - this._bit;
785
+ }
786
+ next(count = 1) {
787
+ let gotten = 0;
788
+ while (this._position !== this._size && count--) {
789
+ ++gotten;
790
+ if (++this._bit === 8) {
791
+ this._bit = 0;
792
+ ++this._position;
793
+ }
794
+ }
795
+ return gotten;
796
+ }
797
+ read(count = 1) {
798
+ let result = 0;
799
+ while (this._position !== this._size && count--) {
800
+ result <<= 1;
801
+ if (this._data[this._position] & (0x80 >> this._bit++)) {
802
+ result |= 1;
803
+ }
804
+ if (this._bit === 8) {
805
+ this._bit = 0;
806
+ ++this._position;
807
+ }
808
+ }
809
+ return result;
810
+ }
811
+ read8() {
812
+ return this.read(8);
813
+ }
814
+ read16() {
815
+ return this.read(16);
816
+ }
817
+ read24() {
818
+ return this.read(24);
819
+ }
820
+ read32() {
821
+ return this.read(32);
822
+ }
823
+ readExpGolomb() {
824
+ let i = 0;
825
+ while (!this.read()) {
826
+ if (!this.available()) {
827
+ return 0;
828
+ }
829
+ ++i;
830
+ }
831
+ const result = this.read(i);
832
+ if (i > 15) {
833
+ this.log('Exponential-Golomb code exceeding unsigned 16 bits').warn();
834
+ return 0;
835
+ }
836
+ return result + (1 << i) - 1;
837
+ }
838
+ }/**
839
+ * Copyright 2024 Ceeblue B.V.
840
+ * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
841
+ * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
842
+ */
730
843
  /**
731
844
  * Compute ByteRate every delta time
732
845
  */
@@ -996,87 +1109,6 @@ function buildURL(type, params, protocol = 'wss') {
996
1109
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
997
1110
  * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
998
1111
  */
999
- let _logging = 0;
1000
- setInterval(() => {
1001
- console.assert(_logging === 0, _logging.toFixed(), 'calls to log was useless');
1002
- }, 10000);
1003
- /**
1004
- * Log types
1005
- */
1006
- var LogType;
1007
- (function (LogType) {
1008
- LogType["ERROR"] = "error";
1009
- LogType["WARN"] = "warn";
1010
- LogType["INFO"] = "info";
1011
- LogType["DEBUG"] = "debug";
1012
- })(LogType || (LogType = {}));
1013
- /**
1014
- * Log instance
1015
- */
1016
- class Log {
1017
- get error() {
1018
- return this._bind(LogType.ERROR);
1019
- }
1020
- get warn() {
1021
- return this._bind(LogType.WARN);
1022
- }
1023
- get info() {
1024
- return this._bind(LogType.INFO);
1025
- }
1026
- get debug() {
1027
- return this._bind(LogType.DEBUG);
1028
- }
1029
- constructor(onLog, ...args) {
1030
- if (!args.length) {
1031
- // cannot have 0 args to be called correctly!
1032
- args.push(undefined);
1033
- }
1034
- this._args = args;
1035
- this._onLog = onLog;
1036
- ++_logging;
1037
- }
1038
- _bind(type) {
1039
- if (!this._done) {
1040
- this._done = true;
1041
- --_logging;
1042
- }
1043
- // call the local onLog
1044
- if (this._onLog) {
1045
- this._onLog(type, this._args);
1046
- }
1047
- // call the global onLog
1048
- if (this._args.length && log.on) {
1049
- log.on(type, this._args);
1050
- }
1051
- // if not intercepted display the log
1052
- return this._args.length ? console[type].bind(console, ...this._args) : EMPTY_FUNCTION;
1053
- }
1054
- }
1055
- /**
1056
- * Inherits from this class to use logs
1057
- */
1058
- class Loggable {
1059
- constructor() {
1060
- /**
1061
- * Start a log
1062
- * @param args
1063
- * @returns a Log object with the levels of log to call
1064
- */
1065
- this.log = ((...args) => {
1066
- return new Log(this.log.on, ...args);
1067
- });
1068
- }
1069
- }
1070
- /**
1071
- * Global log
1072
- */
1073
- const log = ((...args) => {
1074
- return new Log(() => { }, ...args);
1075
- });/**
1076
- * Copyright 2024 Ceeblue B.V.
1077
- * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
1078
- * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
1079
- */
1080
1112
  /**
1081
1113
  * A advanced EventEmitter which allows to declare event as natural function in the inheriting children class,
1082
1114
  * function must start by `on` prefix to be recognized as an event.
@@ -1965,16 +1997,17 @@ function decodeTimestamp(context, lineWidth, blocksPerRow = 32, tolerance = 0.2)
1965
1997
  let i = blockSize / 2;
1966
1998
  const data = context.getImageData(0, Math.round(i), lineWidth, 1).data;
1967
1999
  const pixels = new Uint32Array(data.buffer);
1968
- const blackThreshold = 0xffffff * tolerance;
1969
- const whiteThreshold = 0xffffff * (1 - tolerance);
2000
+ const blackThreshold = 0xff * tolerance;
2001
+ const whiteThreshold = 0xff * (1 - tolerance);
1970
2002
  while (i < pixels.length) {
1971
2003
  const pixel = pixels[Math.round(i)] & 0xffffff;
1972
- pixels[Math.round(i)] = pixel;
1973
- if (pixel < blackThreshold) {
2004
+ // Extract luminance from RGB
2005
+ const Y = 0.299 * ((pixel >> 16) & 0xff) + 0.587 * ((pixel >> 8) & 0xff) + 0.114 * (pixel & 0xff);
2006
+ if (Y < blackThreshold) {
1974
2007
  // Black
1975
2008
  binaryTime += '1';
1976
2009
  }
1977
- else if (pixel > whiteThreshold) {
2010
+ else if (Y > whiteThreshold) {
1978
2011
  // White
1979
2012
  binaryTime += '0';
1980
2013
  }
@@ -2024,4 +2057,4 @@ function encodeTimestamp(context, lineWidth, blocksPerRow = 32, now = new Date()
2024
2057
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
2025
2058
  * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
2026
2059
  */
2027
- const VERSION = '2.6.0';export{BinaryReader,BinaryWriter,BitReader,ByteRate,Connect,EpochTime,EventEmitter,FixMap,Log,LogType,Loggable,NetAddress,Numbers,Queue,SDP,Util,VERSION,WebSocketReliable,log};//# sourceMappingURL=web-utils.js.map
2060
+ const VERSION = '3.0.0';export{BinaryReader,BinaryWriter,BitReader,ByteRate,Connect,EpochTime,EventEmitter,FixMap,Log,LogLevel,Loggable,NetAddress,Numbers,Queue,SDP,Util,VERSION,WebSocketReliable,log};//# sourceMappingURL=web-utils.js.map