@trebco/treb 30.10.2 → 30.12.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/dist/treb-export-worker.mjs +1 -1
- package/dist/treb-spreadsheet.mjs +8 -8
- package/dist/treb.d.ts +1 -1
- package/package.json +6 -6
- package/treb-calculator/src/calculator.ts +55 -2
- package/treb-calculator/src/functions/base-functions.ts +72 -11
- package/treb-calculator/src/functions/text-functions.ts +4 -0
- package/treb-calculator/src/utilities.ts +10 -1
package/dist/treb.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trebco/treb",
|
|
3
|
-
"version": "30.
|
|
3
|
+
"version": "30.12.0",
|
|
4
4
|
"license": "LGPL-3.0-or-later",
|
|
5
5
|
"homepage": "https://treb.app",
|
|
6
6
|
"repository": {
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
"type": "module",
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@types/html-minifier": "^4.0.2",
|
|
15
|
-
"@types/node": "^22.
|
|
15
|
+
"@types/node": "^22.5.2",
|
|
16
16
|
"@types/uzip": "^0.20201231.0",
|
|
17
17
|
"base64-js": "^1.5.1",
|
|
18
18
|
"cssnano": "^7.0.4",
|
|
19
|
-
"esbuild": "^0.23.
|
|
20
|
-
"eslint": "^9.
|
|
19
|
+
"esbuild": "^0.23.1",
|
|
20
|
+
"eslint": "^9.9.1",
|
|
21
21
|
"fast-xml-parser": "^4.0.7",
|
|
22
22
|
"html-minifier-terser": "^7.2.0",
|
|
23
23
|
"sass": "^1.69.3",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"treb-parser": "file:treb-parser",
|
|
32
32
|
"treb-utils": "file:treb-utils",
|
|
33
33
|
"ts-node-dev": "^2.0.0",
|
|
34
|
-
"tslib": "^2.
|
|
34
|
+
"tslib": "^2.7.0",
|
|
35
35
|
"typescript": "^5.3.3",
|
|
36
|
-
"typescript-eslint": "^8.
|
|
36
|
+
"typescript-eslint": "^8.3.0",
|
|
37
37
|
"uzip": "^0.20201231.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
@@ -55,7 +55,7 @@ import * as Primitives from './primitives';
|
|
|
55
55
|
import type { FunctionDescriptor } from 'treb-grid';
|
|
56
56
|
import type { LeafVertex } from './dag/graph';
|
|
57
57
|
|
|
58
|
-
import { ArgumentError, ReferenceError, UnknownError, ValueError, ExpressionError, NAError, DivideByZeroError } from './function-error';
|
|
58
|
+
import { ArgumentError, ReferenceError, UnknownError, ValueError, ExpressionError, NAError, DivideByZeroError, NotImplError } from './function-error';
|
|
59
59
|
import { StateLeafVertex } from './dag/state_leaf_vertex';
|
|
60
60
|
import { CalculationLeafVertex } from './dag/calculation_leaf_vertex';
|
|
61
61
|
|
|
@@ -605,6 +605,60 @@ export class Calculator extends Graph {
|
|
|
605
605
|
},
|
|
606
606
|
},
|
|
607
607
|
|
|
608
|
+
Cell: {
|
|
609
|
+
description: 'Returns data about a cell',
|
|
610
|
+
arguments: [
|
|
611
|
+
{ name: 'type', description: 'Type of data to return', unroll: true, },
|
|
612
|
+
{ name: 'reference', description: 'Cell reference', metadata: true, unroll: true, },
|
|
613
|
+
],
|
|
614
|
+
|
|
615
|
+
// there's no concept of "structure volatile", and structure events
|
|
616
|
+
// don't trigger recalc, so this is not helpful -- we may need to
|
|
617
|
+
// think about both of those things
|
|
618
|
+
|
|
619
|
+
// volatile: true,
|
|
620
|
+
|
|
621
|
+
fn: (type: string, reference: UnionValue): UnionValue => {
|
|
622
|
+
|
|
623
|
+
if (!UnionIsMetadata(reference)) {
|
|
624
|
+
return ReferenceError();
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (type) {
|
|
628
|
+
switch (type.toString().toLowerCase()) {
|
|
629
|
+
case 'format':
|
|
630
|
+
return reference.value.format ? // || ReferenceError;
|
|
631
|
+
{ type: ValueType.string, value: reference.value.format } : ReferenceError();
|
|
632
|
+
case 'address':
|
|
633
|
+
{
|
|
634
|
+
let sheet_name = '';
|
|
635
|
+
if (reference.value.address.sheet_id) {
|
|
636
|
+
const sheet = this.model.sheets.Find(reference.value.address.sheet_id);
|
|
637
|
+
sheet_name = sheet?.name || '';
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (sheet_name) {
|
|
641
|
+
if (QuotedSheetNameRegex.test(sheet_name)) {
|
|
642
|
+
sheet_name = `'${sheet_name}'`;
|
|
643
|
+
}
|
|
644
|
+
sheet_name += '!';
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
return {
|
|
648
|
+
type: ValueType.string,
|
|
649
|
+
value: '[]' + sheet_name + reference.value.address.label.replace(/\$/g, ''),
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
return { type: ValueType.error, value: NotImplError.error };
|
|
656
|
+
|
|
657
|
+
},
|
|
658
|
+
|
|
659
|
+
},
|
|
660
|
+
|
|
661
|
+
|
|
608
662
|
Address: {
|
|
609
663
|
arguments: [
|
|
610
664
|
{ name: 'row' },
|
|
@@ -2484,7 +2538,6 @@ export class Calculator extends Graph {
|
|
|
2484
2538
|
|
|
2485
2539
|
// first pass, run the calculation
|
|
2486
2540
|
const check = this.Evaluate(expression, context, options, true);
|
|
2487
|
-
|
|
2488
2541
|
entry.internal.vertex.result = check;
|
|
2489
2542
|
entry.internal.vertex.updated = true;
|
|
2490
2543
|
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
import type { FunctionMap, IntrinsicValue } from '../descriptors';
|
|
23
23
|
import * as Utils from '../utilities';
|
|
24
24
|
// import { StringUnion, NumberUnion } from '../utilities';
|
|
25
|
-
import { ReferenceError,
|
|
25
|
+
import { ReferenceError, NAError, ArgumentError, DivideByZeroError, ValueError } from '../function-error';
|
|
26
26
|
import type { UnionValue,
|
|
27
27
|
RenderFunctionResult, RenderFunctionOptions, Complex, CellValue,
|
|
28
28
|
// ICellAddress
|
|
@@ -404,7 +404,9 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
404
404
|
|
|
405
405
|
switch (value.type) {
|
|
406
406
|
case ValueType.number: sum.real += value.value; break;
|
|
407
|
-
case ValueType.boolean:
|
|
407
|
+
case ValueType.boolean:
|
|
408
|
+
// sum.real += (value.value ? 1 : 0); // ??
|
|
409
|
+
break;
|
|
408
410
|
case ValueType.complex:
|
|
409
411
|
sum.real += value.value.real;
|
|
410
412
|
sum.imaginary += value.value.imaginary;
|
|
@@ -418,6 +420,44 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
418
420
|
},
|
|
419
421
|
},
|
|
420
422
|
|
|
423
|
+
SumSQ: {
|
|
424
|
+
description: 'Returns the sum of the squares of all arguments',
|
|
425
|
+
arguments: [{ boxed: true, name: 'values or ranges' }],
|
|
426
|
+
fn: (...args: UnionValue[]) => {
|
|
427
|
+
|
|
428
|
+
const sum = { real: 0, imaginary: 0 };
|
|
429
|
+
const values = Utils.FlattenBoxed(args); // as UnionValue[];
|
|
430
|
+
|
|
431
|
+
for (const value of values) {
|
|
432
|
+
|
|
433
|
+
switch (value.type) {
|
|
434
|
+
case ValueType.number: sum.real += value.value * value.value; break;
|
|
435
|
+
case ValueType.boolean:
|
|
436
|
+
// sum.real += (value.value ? 1 : 0); // ??
|
|
437
|
+
break;
|
|
438
|
+
case ValueType.complex:
|
|
439
|
+
|
|
440
|
+
{
|
|
441
|
+
const squared = ComplexMath.Multiply(value.value, value.value);
|
|
442
|
+
|
|
443
|
+
// sum.real += value.value.real;
|
|
444
|
+
// sum.imaginary += value.value.imaginary;
|
|
445
|
+
|
|
446
|
+
sum.real += squared.real;
|
|
447
|
+
sum.imaginary += squared.imaginary;
|
|
448
|
+
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
break;
|
|
452
|
+
case ValueType.error: return value;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
return ComplexOrReal(sum);
|
|
457
|
+
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
|
|
421
461
|
// --- FIXME: break out date functions? --------------------------------------
|
|
422
462
|
|
|
423
463
|
EDate: {
|
|
@@ -678,6 +718,7 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
678
718
|
},
|
|
679
719
|
|
|
680
720
|
|
|
721
|
+
/*
|
|
681
722
|
Cell: {
|
|
682
723
|
description: 'Returns data about a cell',
|
|
683
724
|
arguments: [
|
|
@@ -703,7 +744,10 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
703
744
|
return reference.value.format ? // || ReferenceError;
|
|
704
745
|
{ type: ValueType.string, value: reference.value.format } : ReferenceError();
|
|
705
746
|
case 'address':
|
|
706
|
-
|
|
747
|
+
|
|
748
|
+
// FIXME: this needs to return a fully-qualified address, we'll need access to the model
|
|
749
|
+
|
|
750
|
+
return { type: ValueType.string, value: '[]' + reference.value.address.label.replace(/\$/g, '') };
|
|
707
751
|
}
|
|
708
752
|
}
|
|
709
753
|
|
|
@@ -712,6 +756,7 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
712
756
|
},
|
|
713
757
|
|
|
714
758
|
},
|
|
759
|
+
*/
|
|
715
760
|
|
|
716
761
|
Year: {
|
|
717
762
|
description: 'Returns year from date',
|
|
@@ -804,15 +849,31 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
804
849
|
},
|
|
805
850
|
|
|
806
851
|
Not: {
|
|
807
|
-
arguments: [{ unroll: true }],
|
|
808
|
-
fn: (
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
if (
|
|
813
|
-
|
|
852
|
+
arguments: [{ unroll: true, boxed: true }],
|
|
853
|
+
fn: (arg: UnionValue): UnionValue => {
|
|
854
|
+
|
|
855
|
+
let value = false;
|
|
856
|
+
|
|
857
|
+
if (arg) {
|
|
858
|
+
switch (arg.type) {
|
|
859
|
+
|
|
860
|
+
case ValueType.undefined:
|
|
861
|
+
value = false;
|
|
862
|
+
break;
|
|
863
|
+
|
|
864
|
+
case ValueType.string:
|
|
865
|
+
case ValueType.boolean:
|
|
866
|
+
case ValueType.number:
|
|
867
|
+
value = !!arg.value;
|
|
868
|
+
break;
|
|
869
|
+
|
|
870
|
+
case ValueType.error:
|
|
871
|
+
return arg;
|
|
872
|
+
|
|
873
|
+
}
|
|
814
874
|
}
|
|
815
|
-
|
|
875
|
+
|
|
876
|
+
return Box(!value);
|
|
816
877
|
},
|
|
817
878
|
},
|
|
818
879
|
|
|
@@ -284,12 +284,16 @@ export const TextFunctionLibrary: FunctionMap = {
|
|
|
284
284
|
{ name: 'Start', default: 1, },
|
|
285
285
|
],
|
|
286
286
|
fn: (needle: string, haystack: string, start = 1): UnionValue => {
|
|
287
|
+
|
|
287
288
|
if (start >= 1) {
|
|
288
289
|
if (!needle) {
|
|
289
290
|
return {
|
|
290
291
|
type: ValueType.number, value: start,
|
|
291
292
|
}
|
|
292
293
|
}
|
|
294
|
+
|
|
295
|
+
needle = needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
296
|
+
|
|
293
297
|
const match = new RegExp(needle).exec(haystack.substr(start - 1));
|
|
294
298
|
if (match) {
|
|
295
299
|
return {
|
|
@@ -280,7 +280,9 @@ export const ApplyArrayX = <TFunc extends (...args: any[]) => UnionValue>(map: b
|
|
|
280
280
|
let shape: unknown[][] = [];
|
|
281
281
|
|
|
282
282
|
for (const [i, arg] of args.entries()) {
|
|
283
|
+
|
|
283
284
|
if (arg && map[i]) {
|
|
285
|
+
|
|
284
286
|
const arr = Array.isArray(arg) ? arg : IsArrayUnion(arg) ? arg.value : undefined;
|
|
285
287
|
if (arr) {
|
|
286
288
|
arrays[i] = arr;
|
|
@@ -298,8 +300,15 @@ export const ApplyArrayX = <TFunc extends (...args: any[]) => UnionValue>(map: b
|
|
|
298
300
|
return {
|
|
299
301
|
type: ValueType.array,
|
|
300
302
|
value: shape.map((_, i) => _.map((_, j) => {
|
|
301
|
-
|
|
303
|
+
|
|
304
|
+
// this was breaking on boolean false, because
|
|
305
|
+
// it used || instead of ??. if we don't require
|
|
306
|
+
// boxed arguments, we need to handle naked booleans
|
|
307
|
+
|
|
308
|
+
const apply = args.map((arg, index) => arrays[index] ? (arrays[index][i][j] ?? { type: ValueType.undefined }) : arg);
|
|
309
|
+
|
|
302
310
|
return base(...apply as Parameters<TFunc>);
|
|
311
|
+
|
|
303
312
|
})),
|
|
304
313
|
};
|
|
305
314
|
|