@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.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- /*! API v30.10. Copyright 2018-2024 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
1
+ /*! API v30.12. Copyright 2018-2024 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
2
2
 
3
3
  /**
4
4
  * add our tag to the map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trebco/treb",
3
- "version": "30.10.2",
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.1.0",
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.0",
20
- "eslint": "^9.8.0",
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.2.0",
34
+ "tslib": "^2.7.0",
35
35
  "typescript": "^5.3.3",
36
- "typescript-eslint": "^8.0.0",
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, NotImplError, NAError, ArgumentError, DivideByZeroError, ValueError } from '../function-error';
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: sum.real += (value.value ? 1 : 0); break;
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
- return { type: ValueType.string, value: reference.value.address.label.replace(/\$/g, '') };
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: (...args: unknown[]): UnionValue => {
809
- if (args.length === 0) {
810
- return ArgumentError();
811
- }
812
- if (args.length === 1) {
813
- return Box(!args[0]);
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
- return Box(true);
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
- const apply = args.map((arg, index) => arrays[index] ? (arrays[index][i][j] || { type: ValueType.undefined }) : arg);
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