@trebco/treb 28.7.0 → 28.10.5
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-spreadsheet-light.mjs +14 -14
- package/dist/treb-spreadsheet.mjs +12 -12
- package/dist/treb.d.ts +39 -6
- package/notes/connected-elements.md +37 -0
- package/package.json +1 -1
- package/treb-base-types/src/gradient.ts +1 -1
- package/treb-base-types/src/localization.ts +6 -0
- package/treb-calculator/src/calculator.ts +72 -30
- package/treb-calculator/src/dag/calculation_leaf_vertex.ts +7 -0
- package/treb-calculator/src/dag/graph.ts +8 -0
- package/treb-calculator/src/functions/base-functions.ts +30 -1
- package/treb-calculator/src/index.ts +1 -1
- package/treb-charts/src/chart-functions.ts +14 -0
- package/treb-charts/src/chart-types.ts +25 -1
- package/treb-charts/src/chart-utils.ts +195 -9
- package/treb-charts/src/chart.ts +4 -0
- package/treb-charts/src/default-chart-renderer.ts +17 -1
- package/treb-charts/src/renderer.ts +182 -9
- package/treb-charts/style/charts.scss +39 -0
- package/treb-embed/markup/toolbar.html +35 -34
- package/treb-embed/src/custom-element/treb-global.ts +10 -2
- package/treb-embed/src/embedded-spreadsheet.ts +209 -106
- package/treb-embed/src/options.ts +7 -0
- package/treb-embed/style/layout.scss +4 -0
- package/treb-embed/style/toolbar.scss +37 -0
- package/treb-grid/src/index.ts +1 -1
- package/treb-grid/src/types/conditional_format.ts +1 -1
- package/treb-grid/src/types/data_model.ts +32 -0
- package/treb-grid/src/types/grid.ts +11 -1
- package/treb-grid/src/types/grid_base.ts +161 -5
- package/treb-grid/src/types/grid_command.ts +32 -0
- package/treb-grid/src/types/grid_events.ts +7 -0
- package/treb-grid/src/types/grid_options.ts +8 -0
- package/treb-grid/src/types/sheet.ts +0 -56
- package/treb-grid/src/types/update_flags.ts +1 -0
- package/treb-parser/src/parser-types.ts +6 -0
- package/treb-parser/src/parser.ts +48 -1
|
@@ -67,6 +67,10 @@ interface PatchOptions extends PatchAreaOptions {
|
|
|
67
67
|
sheet: Sheet;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
const AssertNever = (value: never) => {
|
|
71
|
+
console.error('invalid case');
|
|
72
|
+
};
|
|
73
|
+
|
|
70
74
|
export class GridBase {
|
|
71
75
|
|
|
72
76
|
// --- public members --------------------------------------------------------
|
|
@@ -160,6 +164,24 @@ export class GridBase {
|
|
|
160
164
|
|
|
161
165
|
// --- API methods -----------------------------------------------------------
|
|
162
166
|
|
|
167
|
+
public RemoveConditionalFormat(options: {
|
|
168
|
+
format?: ConditionalFormat;
|
|
169
|
+
area?: IArea;
|
|
170
|
+
}) {
|
|
171
|
+
|
|
172
|
+
this.ExecCommand({
|
|
173
|
+
key: CommandKey.RemoveConditionalFormat,
|
|
174
|
+
...options,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
public AddConditionalFormat(format: ConditionalFormat) {
|
|
179
|
+
this.ExecCommand({
|
|
180
|
+
key: CommandKey.AddConditionalFormat,
|
|
181
|
+
format,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
163
185
|
/** remove a table. doesn't remove any data, just removes the overlay. */
|
|
164
186
|
public RemoveTable(table: Table) {
|
|
165
187
|
this.ExecCommand({
|
|
@@ -1887,7 +1909,7 @@ export class GridBase {
|
|
|
1887
1909
|
break;
|
|
1888
1910
|
*/
|
|
1889
1911
|
|
|
1890
|
-
// special
|
|
1912
|
+
// special cases
|
|
1891
1913
|
case CommandKey.SortTable:
|
|
1892
1914
|
case CommandKey.RemoveTable:
|
|
1893
1915
|
if (!command.table.area.start.sheet_id) {
|
|
@@ -1895,6 +1917,12 @@ export class GridBase {
|
|
|
1895
1917
|
}
|
|
1896
1918
|
break;
|
|
1897
1919
|
|
|
1920
|
+
case CommandKey.AddConditionalFormat:
|
|
1921
|
+
if (!command.format.area.start.sheet_id) {
|
|
1922
|
+
command.format.area.start.sheet_id = id;
|
|
1923
|
+
}
|
|
1924
|
+
break;
|
|
1925
|
+
|
|
1898
1926
|
// field
|
|
1899
1927
|
case CommandKey.ResizeRows:
|
|
1900
1928
|
case CommandKey.ResizeColumns:
|
|
@@ -1920,6 +1948,14 @@ export class GridBase {
|
|
|
1920
1948
|
case CommandKey.Select:
|
|
1921
1949
|
case CommandKey.InsertTable:
|
|
1922
1950
|
|
|
1951
|
+
// note that remove conditional format could have a format
|
|
1952
|
+
// object (with an area) instead of an area. but in that case,
|
|
1953
|
+
// the format object must match an existing format, so it would
|
|
1954
|
+
// have to have a proper area. there's no case where we would
|
|
1955
|
+
// want to add it. so we only handle the area case.
|
|
1956
|
+
|
|
1957
|
+
case CommandKey.RemoveConditionalFormat:
|
|
1958
|
+
|
|
1923
1959
|
if (command.area) {
|
|
1924
1960
|
if (IsCellAddress(command.area)) {
|
|
1925
1961
|
if (!command.area.sheet_id) {
|
|
@@ -1934,10 +1970,13 @@ export class GridBase {
|
|
|
1934
1970
|
}
|
|
1935
1971
|
break;
|
|
1936
1972
|
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1973
|
+
default:
|
|
1974
|
+
|
|
1975
|
+
// this is intended to check that we've handled all cases. if you
|
|
1976
|
+
// add additional commands and they're not handled, this should
|
|
1977
|
+
// raise a ts error.
|
|
1978
|
+
|
|
1979
|
+
AssertNever(command);
|
|
1941
1980
|
|
|
1942
1981
|
}
|
|
1943
1982
|
}
|
|
@@ -2231,6 +2270,16 @@ export class GridBase {
|
|
|
2231
2270
|
}
|
|
2232
2271
|
}
|
|
2233
2272
|
|
|
2273
|
+
for (const element of this.model.connected_elements.values()) {
|
|
2274
|
+
if (element.formula) {
|
|
2275
|
+
const updated = this.PatchExpressionSheetName(element.formula, old_name, name);
|
|
2276
|
+
if (updated) {
|
|
2277
|
+
element.formula = updated;
|
|
2278
|
+
changes++;
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2234
2283
|
return changes;
|
|
2235
2284
|
|
|
2236
2285
|
}
|
|
@@ -2811,6 +2860,18 @@ export class GridBase {
|
|
|
2811
2860
|
row_count: command.count
|
|
2812
2861
|
});
|
|
2813
2862
|
|
|
2863
|
+
// connected elements
|
|
2864
|
+
for (const external of this.model.connected_elements.values()) {
|
|
2865
|
+
if (external.formula) {
|
|
2866
|
+
const modified = this.PatchFormulasInternal(external.formula,
|
|
2867
|
+
command.before_row, command.count, 0, 0,
|
|
2868
|
+
target_sheet.name.toLowerCase(), false);
|
|
2869
|
+
if (modified) {
|
|
2870
|
+
external.formula = modified;
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2814
2875
|
// see InsertColumnsInternal re: tables. rows are less complicated,
|
|
2815
2876
|
// except that if you delete the header row we want to remove the
|
|
2816
2877
|
// table entirely.
|
|
@@ -3133,6 +3194,18 @@ export class GridBase {
|
|
|
3133
3194
|
before_row: 0,
|
|
3134
3195
|
row_count: 0 });
|
|
3135
3196
|
|
|
3197
|
+
// connected elements
|
|
3198
|
+
for (const element of this.model.connected_elements.values()) {
|
|
3199
|
+
if (element.formula) {
|
|
3200
|
+
const modified = this.PatchFormulasInternal(element.formula,
|
|
3201
|
+
0, 0, command.before_column, command.count,
|
|
3202
|
+
target_sheet.name.toLowerCase(), false);
|
|
3203
|
+
if (modified) {
|
|
3204
|
+
element.formula = modified;
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3136
3209
|
// patch tables. we removed this from the sheet routine entirely,
|
|
3137
3210
|
// we need to rebuild any affected tables now.
|
|
3138
3211
|
|
|
@@ -3534,6 +3607,88 @@ export class GridBase {
|
|
|
3534
3607
|
|
|
3535
3608
|
break;
|
|
3536
3609
|
|
|
3610
|
+
case CommandKey.AddConditionalFormat:
|
|
3611
|
+
{
|
|
3612
|
+
|
|
3613
|
+
const sheet = this.FindSheet(command.format.area);
|
|
3614
|
+
sheet.conditional_formats.push(command.format);
|
|
3615
|
+
|
|
3616
|
+
sheet.Invalidate(new Area(command.format.area.start, command.format.area.end));
|
|
3617
|
+
|
|
3618
|
+
if (sheet === this.active_sheet) {
|
|
3619
|
+
// flags.style_area = Area.Join(command.format.area, flags.style_area);
|
|
3620
|
+
flags.render_area = Area.Join(command.format.area, flags.render_area);
|
|
3621
|
+
}
|
|
3622
|
+
else {
|
|
3623
|
+
// flags.style_event = true;
|
|
3624
|
+
}
|
|
3625
|
+
|
|
3626
|
+
flags.structure_event = true;
|
|
3627
|
+
flags.conditional_formatting_event = true;
|
|
3628
|
+
|
|
3629
|
+
}
|
|
3630
|
+
break;
|
|
3631
|
+
|
|
3632
|
+
case CommandKey.RemoveConditionalFormat:
|
|
3633
|
+
|
|
3634
|
+
{
|
|
3635
|
+
let sheet: Sheet|undefined;
|
|
3636
|
+
let count = 0;
|
|
3637
|
+
|
|
3638
|
+
if (command.format) {
|
|
3639
|
+
|
|
3640
|
+
// we're removing by object equivalence, not strict equality.
|
|
3641
|
+
// this is in case we're switching contexts and the objects
|
|
3642
|
+
// are not strictly equal. may be unecessary. do we need to
|
|
3643
|
+
// normalize in some way? (...)
|
|
3644
|
+
|
|
3645
|
+
const format = JSON.stringify(command.format);
|
|
3646
|
+
|
|
3647
|
+
sheet = this.FindSheet(command.format.area);
|
|
3648
|
+
sheet.conditional_formats = sheet.conditional_formats.filter(test => {
|
|
3649
|
+
// if (test === command.format) {
|
|
3650
|
+
if (JSON.stringify(test) === format) {
|
|
3651
|
+
count++;
|
|
3652
|
+
flags.render_area = Area.Join(test.area, flags.render_area);
|
|
3653
|
+
return false;
|
|
3654
|
+
}
|
|
3655
|
+
return true;
|
|
3656
|
+
});
|
|
3657
|
+
|
|
3658
|
+
}
|
|
3659
|
+
else if (command.area) {
|
|
3660
|
+
const area = new Area(command.area.start, command.area.end);
|
|
3661
|
+
sheet = this.FindSheet(command.area);
|
|
3662
|
+
|
|
3663
|
+
sheet.conditional_formats = sheet.conditional_formats.filter(test => {
|
|
3664
|
+
const compare = new Area(test.area.start, test.area.end);
|
|
3665
|
+
if (compare.Intersects(area)) {
|
|
3666
|
+
count++;
|
|
3667
|
+
flags.render_area = Area.Join(compare, flags.render_area);
|
|
3668
|
+
return false;
|
|
3669
|
+
}
|
|
3670
|
+
return true;
|
|
3671
|
+
});
|
|
3672
|
+
|
|
3673
|
+
}
|
|
3674
|
+
|
|
3675
|
+
if (sheet && count) {
|
|
3676
|
+
sheet.FlushConditionalFormats();
|
|
3677
|
+
flags.structure_event = true;
|
|
3678
|
+
|
|
3679
|
+
// this will flush leaf vertices. but it's expensive because
|
|
3680
|
+
// it's rebuilding the whole graph. we could maybe reduce a
|
|
3681
|
+
// bit... the question is what's worse: rebuilding the graph
|
|
3682
|
+
// or leaving orphans for a while?
|
|
3683
|
+
|
|
3684
|
+
// flags.structure_rebuild_required = true;
|
|
3685
|
+
|
|
3686
|
+
flags.conditional_formatting_event = true;
|
|
3687
|
+
}
|
|
3688
|
+
|
|
3689
|
+
}
|
|
3690
|
+
break;
|
|
3691
|
+
|
|
3537
3692
|
case CommandKey.InsertTable:
|
|
3538
3693
|
|
|
3539
3694
|
// the most important thing here is validating that we can
|
|
@@ -4170,6 +4325,7 @@ export class GridBase {
|
|
|
4170
4325
|
events.push({
|
|
4171
4326
|
type: 'structure',
|
|
4172
4327
|
rebuild_required: flags.structure_rebuild_required,
|
|
4328
|
+
conditional_format: flags.conditional_formatting_event,
|
|
4173
4329
|
});
|
|
4174
4330
|
}
|
|
4175
4331
|
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import type { ICellAddress, IArea, Style, CellStyle, Color, CellValue, Table, TableSortType, TableTheme } from 'treb-base-types';
|
|
23
23
|
import type { ExpressionUnit } from 'treb-parser';
|
|
24
24
|
import type { BorderConstants } from './border_constants';
|
|
25
|
+
import type { ConditionalFormat } from './conditional_format';
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* switching to an exec-command based model, so we can serialize
|
|
@@ -73,6 +74,9 @@ export enum CommandKey {
|
|
|
73
74
|
InsertTable,
|
|
74
75
|
RemoveTable,
|
|
75
76
|
|
|
77
|
+
AddConditionalFormat,
|
|
78
|
+
RemoveConditionalFormat,
|
|
79
|
+
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
/** base type for sheet commands -- can select sheet by name, id or index */
|
|
@@ -418,6 +422,32 @@ export interface ReorderSheetCommand {
|
|
|
418
422
|
move_before: number;
|
|
419
423
|
}
|
|
420
424
|
|
|
425
|
+
/**
|
|
426
|
+
* add conditional format
|
|
427
|
+
*/
|
|
428
|
+
export interface AddConditionalFormatCommand {
|
|
429
|
+
key: CommandKey.AddConditionalFormat;
|
|
430
|
+
format: ConditionalFormat;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* remove conditional format, either as an object or from a target
|
|
435
|
+
* area. as an object, we'll match using object equivalence and not
|
|
436
|
+
* identity.
|
|
437
|
+
*/
|
|
438
|
+
export interface RemoveConditionalFormatCommand {
|
|
439
|
+
|
|
440
|
+
key: CommandKey.RemoveConditionalFormat;
|
|
441
|
+
|
|
442
|
+
/** if format is omitted, we will remove all formats from the target range */
|
|
443
|
+
format?: ConditionalFormat;
|
|
444
|
+
|
|
445
|
+
/** one of area or format should be supplied */
|
|
446
|
+
area?: IArea;
|
|
447
|
+
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
|
|
421
451
|
/**
|
|
422
452
|
* ephemeral flag added to commands.
|
|
423
453
|
* /
|
|
@@ -459,6 +489,8 @@ export type Command =
|
|
|
459
489
|
| ActivateSheetCommand
|
|
460
490
|
| DataValidationCommand
|
|
461
491
|
| DuplicateSheetCommand
|
|
492
|
+
| AddConditionalFormatCommand
|
|
493
|
+
| RemoveConditionalFormatCommand
|
|
462
494
|
) ; // & Ephemeral;
|
|
463
495
|
|
|
464
496
|
/**
|
|
@@ -23,6 +23,7 @@ import type { GridSelection } from './grid_selection';
|
|
|
23
23
|
import type { Annotation } from './annotation';
|
|
24
24
|
import type { Sheet } from './sheet';
|
|
25
25
|
import type { Area } from 'treb-base-types';
|
|
26
|
+
import type { ConditionalFormat } from './conditional_format';
|
|
26
27
|
|
|
27
28
|
export enum ErrorCode {
|
|
28
29
|
|
|
@@ -80,6 +81,12 @@ export interface StructureEvent {
|
|
|
80
81
|
* FIXME: merge/unmerge? (...) I think yes
|
|
81
82
|
*/
|
|
82
83
|
rebuild_required?: boolean;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* we can use this when conditional formats are modified/added/removed
|
|
87
|
+
*/
|
|
88
|
+
conditional_format?: boolean;
|
|
89
|
+
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
export interface AnnotationEvent {
|
|
@@ -24,6 +24,14 @@ import type { StatsEntry } from './tab_bar';
|
|
|
24
24
|
|
|
25
25
|
export type StatsFunction = (data: CellValue|CellValue[][]|undefined) => StatsEntry[];
|
|
26
26
|
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @internalRemarks
|
|
30
|
+
*
|
|
31
|
+
* why are there two levels of options? can we consolidate this with
|
|
32
|
+
* the embedded spreadsheet options? they are never (AFAICT) used
|
|
33
|
+
* independently. maybe that's recent.
|
|
34
|
+
*/
|
|
27
35
|
export interface GridOptions {
|
|
28
36
|
|
|
29
37
|
/** can expand rows/columns */
|
|
@@ -3232,62 +3232,6 @@ export class Sheet {
|
|
|
3232
3232
|
|
|
3233
3233
|
}
|
|
3234
3234
|
|
|
3235
|
-
/*
|
|
3236
|
-
public ApplyConditionalFormats() {
|
|
3237
|
-
|
|
3238
|
-
this.FlushConditionalFormatCache();
|
|
3239
|
-
|
|
3240
|
-
for (const entry of this.conditional_formats) {
|
|
3241
|
-
|
|
3242
|
-
console.info({entry});
|
|
3243
|
-
|
|
3244
|
-
if (entry.applied) {
|
|
3245
|
-
this.ApplyConditionalFormatCache(entry);
|
|
3246
|
-
}
|
|
3247
|
-
}
|
|
3248
|
-
|
|
3249
|
-
}
|
|
3250
|
-
|
|
3251
|
-
public FlushConditionalFormatCache() {
|
|
3252
|
-
|
|
3253
|
-
// FIXME: need to flush any styles that are set, unless they match;
|
|
3254
|
-
// perhaps we should use an alternate cache so we can compare? TODO/FIXME
|
|
3255
|
-
|
|
3256
|
-
for (const [row, row_data] of this.conditional_format_cache.entries()) {
|
|
3257
|
-
if (row_data) {
|
|
3258
|
-
for (const [column, column_data] of row_data.entries()) {
|
|
3259
|
-
if (column_data) {
|
|
3260
|
-
|
|
3261
|
-
this.CellData({row, column}).FlushStyle();
|
|
3262
|
-
|
|
3263
|
-
}
|
|
3264
|
-
}
|
|
3265
|
-
}
|
|
3266
|
-
}
|
|
3267
|
-
|
|
3268
|
-
this.conditional_format_cache = [];
|
|
3269
|
-
|
|
3270
|
-
}
|
|
3271
|
-
|
|
3272
|
-
public ApplyConditionalFormatCache(format: ConditionalFormat) {
|
|
3273
|
-
|
|
3274
|
-
for (let row = format.area.start.row; row <= format.area.end.row; row++ ) {
|
|
3275
|
-
for (let column = format.area.start.column; column <= format.area.end.column; column++ ) {
|
|
3276
|
-
if (!this.conditional_format_cache[row]) {
|
|
3277
|
-
this.conditional_format_cache[row] = [];
|
|
3278
|
-
}
|
|
3279
|
-
if (!this.conditional_format_cache[row][column]) {
|
|
3280
|
-
this.conditional_format_cache[row][column] = [];
|
|
3281
|
-
}
|
|
3282
|
-
this.conditional_format_cache[row][column].push(format.style);
|
|
3283
|
-
this.CellData({row, column}).FlushStyle();
|
|
3284
|
-
|
|
3285
|
-
}
|
|
3286
|
-
}
|
|
3287
|
-
|
|
3288
|
-
}
|
|
3289
|
-
*/
|
|
3290
|
-
|
|
3291
3235
|
private ConditionalFormatForCell(address: ICellAddress): CellStyle[] {
|
|
3292
3236
|
if (this.conditional_format_cache[address.row]) {
|
|
3293
3237
|
return this.conditional_format_cache[address.row][address.column] || [];
|
|
@@ -395,3 +395,9 @@ export interface RenderOptions {
|
|
|
395
395
|
long_structured_references: boolean;
|
|
396
396
|
table_name: string;
|
|
397
397
|
}
|
|
398
|
+
|
|
399
|
+
export interface PersistedParserConfig {
|
|
400
|
+
flags: Partial<ParserFlags>;
|
|
401
|
+
argument_separator: ArgumentSeparatorType;
|
|
402
|
+
decimal_mark: DecimalMarkType;
|
|
403
|
+
}
|
|
@@ -33,7 +33,8 @@ import type {
|
|
|
33
33
|
UnitLiteralNumber,
|
|
34
34
|
ParserFlags,
|
|
35
35
|
UnitStructuredReference,
|
|
36
|
-
RenderOptions
|
|
36
|
+
RenderOptions,
|
|
37
|
+
PersistedParserConfig} from './parser-types';
|
|
37
38
|
import {
|
|
38
39
|
ArgumentSeparatorType,
|
|
39
40
|
DecimalMarkType
|
|
@@ -248,6 +249,52 @@ export class Parser {
|
|
|
248
249
|
*/
|
|
249
250
|
protected full_reference_list: Array<UnitAddress | UnitRange | UnitIdentifier | UnitStructuredReference> = [];
|
|
250
251
|
|
|
252
|
+
protected parser_state: string[] = [];
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* save local configuration to a buffer, so it can be restored. we're doing
|
|
256
|
+
* this because in a lot of places we're caching parser flagss, changing
|
|
257
|
+
* them, and then restoring them. that's become repetitive, fragile to
|
|
258
|
+
* changes or new flags, and annoying.
|
|
259
|
+
*
|
|
260
|
+
* config is managed in a list with push/pop semantics. we store it as
|
|
261
|
+
* JSON so there's no possibility we'll accidentally mutate.
|
|
262
|
+
*
|
|
263
|
+
* FIXME: while we're at it why not migrate the separators -> flags, so
|
|
264
|
+
* there's a single location for this kind of state? (...TODO)
|
|
265
|
+
*
|
|
266
|
+
*/
|
|
267
|
+
public Save() {
|
|
268
|
+
const config: PersistedParserConfig = {
|
|
269
|
+
flags: this.flags,
|
|
270
|
+
argument_separator: this.argument_separator,
|
|
271
|
+
decimal_mark: this.decimal_mark,
|
|
272
|
+
}
|
|
273
|
+
this.parser_state.push(JSON.stringify(config));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* restore persisted config
|
|
278
|
+
* @see Save
|
|
279
|
+
*/
|
|
280
|
+
public Restore() {
|
|
281
|
+
const json = this.parser_state.shift();
|
|
282
|
+
if (json) {
|
|
283
|
+
try {
|
|
284
|
+
const config = JSON.parse(json) as PersistedParserConfig;
|
|
285
|
+
this.flags = config.flags;
|
|
286
|
+
this.argument_separator = config.argument_separator;
|
|
287
|
+
this.decimal_mark = config.decimal_mark;
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
console.error(err);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
console.warn("No parser state to restore");
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
251
298
|
/**
|
|
252
299
|
* recursive tree walk.
|
|
253
300
|
*
|