@trebco/treb 29.5.4 → 29.7.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/api-generator/api-generator.ts +10 -1
- package/dist/treb-spreadsheet-light.mjs +10 -10
- package/dist/treb-spreadsheet.mjs +10 -10
- package/dist/treb.d.ts +102 -22
- package/package.json +1 -1
- package/treb-base-types/src/cells.ts +34 -0
- package/treb-base-types/src/evaluate-options.ts +22 -1
- package/treb-base-types/src/union.ts +0 -11
- package/treb-base-types/src/value-type.ts +3 -3
- package/treb-calculator/src/calculator.ts +34 -29
- package/treb-calculator/src/descriptors.ts +2 -0
- package/treb-calculator/src/expression-calculator.ts +31 -173
- package/treb-calculator/src/function-error.ts +16 -21
- package/treb-calculator/src/functions/matrix-functions.ts +1 -1
- package/treb-charts/src/util.ts +3 -36
- package/treb-data-model/src/data_model.ts +2 -63
- package/treb-data-model/src/index.ts +2 -10
- package/treb-data-model/src/sheet.ts +7 -3
- package/treb-data-model/src/types.ts +71 -0
- package/treb-embed/src/embedded-spreadsheet.ts +215 -83
- package/treb-export/src/xml-utils.ts +20 -8
- package/treb-grid/src/index.ts +1 -0
- package/treb-grid/src/types/clipboard_data2.ts +85 -0
- package/treb-grid/src/types/grid.ts +252 -13
- package/treb-grid/src/types/grid_base.ts +14 -2
- package/treb-parser/src/parser-types.ts +3 -0
- package/treb-parser/src/parser.ts +86 -2
|
@@ -116,6 +116,7 @@ import type { ClipboardCellData } from './clipboard_data';
|
|
|
116
116
|
|
|
117
117
|
import type { ExternalEditorConfig } from './external_editor_config';
|
|
118
118
|
import { ExternalEditor } from '../editors/external_editor';
|
|
119
|
+
import type { ClipboardData, PasteOptions } from './clipboard_data2';
|
|
119
120
|
|
|
120
121
|
interface DoubleClickData {
|
|
121
122
|
timeout?: number;
|
|
@@ -416,6 +417,227 @@ export class Grid extends GridBase {
|
|
|
416
417
|
|
|
417
418
|
}
|
|
418
419
|
|
|
420
|
+
|
|
421
|
+
// --- Copy/paste API methods ------------------------------------------------
|
|
422
|
+
//
|
|
423
|
+
// moving here with a view towards (eventually) merging with the UI/browser
|
|
424
|
+
// copy/paste routines (in grid)
|
|
425
|
+
//
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* internal composite for cut/copy. mostly identical except we
|
|
430
|
+
* read data as A1 for cut, so it will retain references. also
|
|
431
|
+
* cut clears the data.
|
|
432
|
+
*
|
|
433
|
+
* FIXME: merge with grid cut/copy/paste routines. we already
|
|
434
|
+
* handle recycling and relative addressing, the only thing missing
|
|
435
|
+
* is alternate formats.
|
|
436
|
+
*/
|
|
437
|
+
public CopyArea(resolved: Area, semantics: 'cut'|'copy' = 'copy'): ClipboardData {
|
|
438
|
+
|
|
439
|
+
// resolve range so we can use it later -> Area
|
|
440
|
+
const sheet = (resolved.start.sheet_id ? this.model.sheets.Find(resolved.start.sheet_id) : this.active_sheet) || this.active_sheet;
|
|
441
|
+
|
|
442
|
+
// get style data, !apply theme but do apply r/c styles
|
|
443
|
+
const style_data = sheet.GetCellStyle(resolved, false);
|
|
444
|
+
|
|
445
|
+
// flag we want R1C1 (copy)
|
|
446
|
+
const r1c1 = (semantics !== 'cut');
|
|
447
|
+
|
|
448
|
+
// NOTE: we're losing arrays here. need to fix. also think
|
|
449
|
+
// about merges? we'll reimplement what grid does (only in part)
|
|
450
|
+
|
|
451
|
+
const data: ClipboardData = [];
|
|
452
|
+
|
|
453
|
+
for (const { cell, row, column } of sheet.cells.IterateRC(resolved)) {
|
|
454
|
+
|
|
455
|
+
// raw value
|
|
456
|
+
let value = cell.value;
|
|
457
|
+
|
|
458
|
+
// seems like we're using a loop function unecessarily
|
|
459
|
+
if (r1c1 && value && cell.type === ValueType.formula) {
|
|
460
|
+
value = this.FormatR1C1(value, { row, column })[0][0];
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const r = row - resolved.start.row;
|
|
464
|
+
const c = column - resolved.start.column;
|
|
465
|
+
|
|
466
|
+
if (!data[r]) {
|
|
467
|
+
data[r] = [];
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
let array_head: IArea|undefined;
|
|
471
|
+
if (cell.area) {
|
|
472
|
+
|
|
473
|
+
// scrubbing to just area (and unlinking)
|
|
474
|
+
array_head = {
|
|
475
|
+
start: {
|
|
476
|
+
row: cell.area.start.row - resolved.start.row,
|
|
477
|
+
column: cell.area.start.column - resolved.start.column,
|
|
478
|
+
},
|
|
479
|
+
end: {
|
|
480
|
+
row: cell.area.end.row - resolved.start.row,
|
|
481
|
+
column: cell.area.end.column - resolved.start.column,
|
|
482
|
+
},
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
data[r][c] = {
|
|
488
|
+
value,
|
|
489
|
+
calculated: cell.calculated,
|
|
490
|
+
style: style_data[r][c],
|
|
491
|
+
area: array_head,
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// EmbeddedSpreadsheet.clipboard = structuredClone(data);
|
|
497
|
+
|
|
498
|
+
if (semantics === 'cut') {
|
|
499
|
+
this.SetRange(resolved, undefined, { recycle: true }); // clear
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
return data;
|
|
503
|
+
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* paste clipboard data into a target range. this method does not use
|
|
508
|
+
* the system clipboard; pass in clipboard data returned from the Cut or
|
|
509
|
+
* Copy method.
|
|
510
|
+
*
|
|
511
|
+
* @param target - the target to paste data into. this can be larger
|
|
512
|
+
* than the clipboard data, in which case values will be recycled in
|
|
513
|
+
* blocks. if the target is smaller than the source data, we will expand
|
|
514
|
+
* it to fit the data.
|
|
515
|
+
*
|
|
516
|
+
* @param data - clipboard data to paste.
|
|
517
|
+
*
|
|
518
|
+
* @privateRemarks LLM API
|
|
519
|
+
*
|
|
520
|
+
* @privateRemarks this was async when we were thinking of using the
|
|
521
|
+
* system clipboard, but that's pretty broken so we're not going to
|
|
522
|
+
* bother atm.
|
|
523
|
+
*/
|
|
524
|
+
public PasteArea(resolved: Area, data: ClipboardData, options: PasteOptions = {}): void {
|
|
525
|
+
|
|
526
|
+
if (!data) {
|
|
527
|
+
throw new Error('no clipboad data');
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// paste has some special semantics. if the target smaller than the
|
|
531
|
+
// source data, we write the full data irrespective of size (similar
|
|
532
|
+
// to "spill"). otherwise, we recycle in blocks.
|
|
533
|
+
|
|
534
|
+
// the setrange method will recycle, but we also need to recycle styles.
|
|
535
|
+
|
|
536
|
+
// start with data length
|
|
537
|
+
|
|
538
|
+
const rows = data.length;
|
|
539
|
+
const columns = data[0]?.length || 0;
|
|
540
|
+
|
|
541
|
+
// target -> block size
|
|
542
|
+
|
|
543
|
+
resolved.Resize(
|
|
544
|
+
Math.max(1, Math.floor(resolved.rows / rows)) * rows,
|
|
545
|
+
Math.max(1, Math.floor(resolved.columns / columns)) * columns );
|
|
546
|
+
|
|
547
|
+
const sheet = (resolved.start.sheet_id ? this.model.sheets.Find(resolved.start.sheet_id) : this.active_sheet) || this.active_sheet;
|
|
548
|
+
|
|
549
|
+
const values: CellValue[][] = [];
|
|
550
|
+
|
|
551
|
+
// optionally collect calculated values, instead of raw values
|
|
552
|
+
|
|
553
|
+
if (options.values) {
|
|
554
|
+
for (const [index, row] of data.entries()) {
|
|
555
|
+
values[index] = [];
|
|
556
|
+
for (const cell of row) {
|
|
557
|
+
values[index].push(typeof cell.calculated === 'undefined' ? cell.value : cell.calculated);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// this is to resolve the reference in the callback,
|
|
563
|
+
// but we should copy -- there's a possibility that
|
|
564
|
+
// this points to the static member, which could get
|
|
565
|
+
// overwritten. FIXME
|
|
566
|
+
|
|
567
|
+
const local = data;
|
|
568
|
+
|
|
569
|
+
// batch to limit events, sync up undo
|
|
570
|
+
|
|
571
|
+
const events = this.Batch(() => {
|
|
572
|
+
|
|
573
|
+
// this needs to change to support arrays (and potentially merges...)
|
|
574
|
+
|
|
575
|
+
// actually we could leave as is for just calculated values
|
|
576
|
+
|
|
577
|
+
if (options.values) {
|
|
578
|
+
this.SetRange(resolved, values, {
|
|
579
|
+
r1c1: true, recycle: true,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
|
|
584
|
+
// so this is for formulas only now
|
|
585
|
+
|
|
586
|
+
// start by clearing... (but leave styles as-is for now)
|
|
587
|
+
|
|
588
|
+
// probably a better way to do this
|
|
589
|
+
this.SetRange(resolved, undefined, { recycle: true });
|
|
590
|
+
|
|
591
|
+
for (const address of resolved) {
|
|
592
|
+
const r = (address.row - resolved.start.row) % rows;
|
|
593
|
+
const c = (address.column - resolved.start.column) % columns;
|
|
594
|
+
|
|
595
|
+
const cell_data = local[r][c];
|
|
596
|
+
|
|
597
|
+
if (cell_data.area) {
|
|
598
|
+
// only the head
|
|
599
|
+
if (cell_data.area.start.row === r && cell_data.area.start.column === c) {
|
|
600
|
+
const array_target = new Area(cell_data.area.start, cell_data.area.end);
|
|
601
|
+
array_target.Shift(resolved.start.row, resolved.start.column);
|
|
602
|
+
this.SetRange(array_target, cell_data.value, { r1c1: true, array: true });
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
else if (cell_data.value) {
|
|
606
|
+
this.SetRange(new Area(address), cell_data.value, { r1c1: true });
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if (options.formatting === 'number-formats') {
|
|
614
|
+
|
|
615
|
+
// number format only, and apply delta
|
|
616
|
+
|
|
617
|
+
for (const address of resolved) {
|
|
618
|
+
const r = (address.row - resolved.start.row) % rows;
|
|
619
|
+
const c = (address.column - resolved.start.column) % columns;
|
|
620
|
+
const number_format = (local[r][c].style || {}).number_format;
|
|
621
|
+
sheet.UpdateCellStyle(address, { number_format }, true);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
else if (options.formatting !== 'target') {
|
|
625
|
+
|
|
626
|
+
// use source formatting (default)
|
|
627
|
+
for (const address of resolved) {
|
|
628
|
+
const r = (address.row - resolved.start.row) % rows;
|
|
629
|
+
const c = (address.column - resolved.start.column) % columns;
|
|
630
|
+
sheet.UpdateCellStyle(address, local[r][c].style || {}, false);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
}, true);
|
|
636
|
+
|
|
637
|
+
this.grid_events.Publish(events);
|
|
638
|
+
|
|
639
|
+
}
|
|
640
|
+
|
|
419
641
|
// --- public methods --------------------------------------------------------
|
|
420
642
|
|
|
421
643
|
/**
|
|
@@ -1883,23 +2105,19 @@ export class Grid extends GridBase {
|
|
|
1883
2105
|
let convert = false;
|
|
1884
2106
|
|
|
1885
2107
|
if (options.argument_separator === ',' && this.parser.argument_separator !== ArgumentSeparatorType.Comma) {
|
|
1886
|
-
// this.parser.argument_separator = ArgumentSeparatorType.Comma;
|
|
1887
|
-
// this.parser.decimal_mark = DecimalMarkType.Period;
|
|
1888
2108
|
this.parser.SetLocaleSettings(DecimalMarkType.Period);
|
|
1889
|
-
|
|
1890
2109
|
convert = true;
|
|
1891
2110
|
}
|
|
1892
2111
|
|
|
1893
2112
|
if (options.argument_separator === ';' && this.parser.argument_separator !== ArgumentSeparatorType.Semicolon) {
|
|
1894
|
-
// this.parser.argument_separator = ArgumentSeparatorType.Semicolon;
|
|
1895
|
-
// this.parser.decimal_mark = DecimalMarkType.Comma;
|
|
1896
2113
|
this.parser.SetLocaleSettings(DecimalMarkType.Comma);
|
|
1897
|
-
|
|
1898
2114
|
convert = true;
|
|
1899
2115
|
}
|
|
1900
2116
|
|
|
1901
2117
|
if (convert) {
|
|
1902
2118
|
|
|
2119
|
+
this.parser.flags.r1c1 = r1c1;
|
|
2120
|
+
|
|
1903
2121
|
const Convert = (value: CellValue): CellValue => {
|
|
1904
2122
|
if (typeof value === 'string' && value[0] === '=') {
|
|
1905
2123
|
const result = this.parser.Parse(value);
|
|
@@ -1908,8 +2126,10 @@ export class Grid extends GridBase {
|
|
|
1908
2126
|
missing: '',
|
|
1909
2127
|
convert_decimal: current.decimal_mark,
|
|
1910
2128
|
convert_argument_separator: current.argument_separator,
|
|
2129
|
+
pass_through_addresses: true,
|
|
1911
2130
|
});
|
|
1912
2131
|
}
|
|
2132
|
+
// console.info("CVT", this.parser.flags, result.expression, value);
|
|
1913
2133
|
}
|
|
1914
2134
|
return value;
|
|
1915
2135
|
};
|
|
@@ -2176,21 +2396,40 @@ export class Grid extends GridBase {
|
|
|
2176
2396
|
/**
|
|
2177
2397
|
* batch updates. returns all the events that _would_ have been sent.
|
|
2178
2398
|
* also does a paint (can disable).
|
|
2399
|
+
*
|
|
2400
|
+
* update for nesting/stacking. we won't return events until the last
|
|
2401
|
+
* batch is complete. paint will similarly toll until the last batch
|
|
2402
|
+
* is complete, and we'll carry forward any paint requirement from
|
|
2403
|
+
* inner batch funcs.
|
|
2404
|
+
*
|
|
2179
2405
|
* @param func
|
|
2180
2406
|
*/
|
|
2181
2407
|
public Batch(func: () => void, paint = true): GridEvent[] {
|
|
2182
2408
|
|
|
2183
|
-
this.batch
|
|
2409
|
+
if (this.batch === 0) {
|
|
2410
|
+
this.batch_paint = paint; // clear any old setting
|
|
2411
|
+
}
|
|
2412
|
+
else {
|
|
2413
|
+
this.batch_paint = this.batch_paint || paint; // ensure we honor it at the end
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
this.batch++;
|
|
2184
2417
|
func();
|
|
2185
|
-
this.batch
|
|
2186
|
-
|
|
2187
|
-
this.
|
|
2418
|
+
this.batch--;
|
|
2419
|
+
|
|
2420
|
+
if (this.batch === 0) {
|
|
2421
|
+
const events = this.batch_events.slice(0);
|
|
2422
|
+
this.batch_events = [];
|
|
2188
2423
|
|
|
2189
|
-
|
|
2190
|
-
|
|
2424
|
+
if (this.batch_paint) {
|
|
2425
|
+
this.DelayedRender(false);
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2428
|
+
return events;
|
|
2191
2429
|
}
|
|
2192
2430
|
|
|
2193
|
-
return
|
|
2431
|
+
return []; // either nothing happened or we're not done
|
|
2432
|
+
|
|
2194
2433
|
}
|
|
2195
2434
|
|
|
2196
2435
|
|
|
@@ -109,7 +109,19 @@ export class GridBase {
|
|
|
109
109
|
|
|
110
110
|
// --- protected members -----------------------------------------------------
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
/**
|
|
113
|
+
* switching to a stack, in case batching is nested. we don't need
|
|
114
|
+
* actual data so (atm) just count the depth.
|
|
115
|
+
*/
|
|
116
|
+
protected batch = 0; // false;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* if any batch method along the way requests a paint update, we
|
|
120
|
+
* want to toll it until the last batch call is complete, but we don't
|
|
121
|
+
* want to lose it. just remember to reset. [FIXME: isn't tolling this
|
|
122
|
+
* paint implicit, since it's async? ...]
|
|
123
|
+
*/
|
|
124
|
+
protected batch_paint = false;
|
|
113
125
|
|
|
114
126
|
protected batch_events: GridEvent[] = [];
|
|
115
127
|
|
|
@@ -4474,7 +4486,7 @@ export class GridBase {
|
|
|
4474
4486
|
});
|
|
4475
4487
|
}
|
|
4476
4488
|
|
|
4477
|
-
if (this.batch) {
|
|
4489
|
+
if (this.batch > 0) {
|
|
4478
4490
|
this.batch_events.push(...events);
|
|
4479
4491
|
}
|
|
4480
4492
|
else {
|
|
@@ -411,6 +411,9 @@ export interface RenderOptions {
|
|
|
411
411
|
/** base for offsetting relative R1C1 addresses */
|
|
412
412
|
r1c1_base?: UnitAddress;
|
|
413
413
|
|
|
414
|
+
/** if we're just translating, don't have to render addresses */
|
|
415
|
+
pass_through_addresses?: boolean;
|
|
416
|
+
|
|
414
417
|
missing: string;
|
|
415
418
|
convert_decimal: DecimalMarkType;
|
|
416
419
|
convert_argument_separator: ArgumentSeparatorType;
|
|
@@ -34,6 +34,7 @@ import type {
|
|
|
34
34
|
ParserFlags,
|
|
35
35
|
UnitStructuredReference,
|
|
36
36
|
RenderOptions,
|
|
37
|
+
BaseExpressionUnit,
|
|
37
38
|
} from './parser-types';
|
|
38
39
|
import {
|
|
39
40
|
ArgumentSeparatorType,
|
|
@@ -334,6 +335,77 @@ export class Parser {
|
|
|
334
335
|
}
|
|
335
336
|
}
|
|
336
337
|
|
|
338
|
+
/**
|
|
339
|
+
* recursive tree walk that allows substitution. this should be
|
|
340
|
+
* a drop-in replacement for the original Walk function but I'm
|
|
341
|
+
* keeping it separate temporarily just in case it breaks something.
|
|
342
|
+
*
|
|
343
|
+
* @param func - in this version function can return `true` (continue
|
|
344
|
+
* walking subtree), `false` (don't walk subtree), or an ExpressionUnit.
|
|
345
|
+
* in the last case, we'll replace the original unit with the substitution.
|
|
346
|
+
* obviously in that case we don't recurse.
|
|
347
|
+
*/
|
|
348
|
+
public Walk2(unit: ExpressionUnit, func: (unit: ExpressionUnit) => boolean|ExpressionUnit|undefined): ExpressionUnit {
|
|
349
|
+
|
|
350
|
+
const result = func(unit);
|
|
351
|
+
if (typeof result === 'object') {
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
switch (unit.type) {
|
|
356
|
+
case 'address':
|
|
357
|
+
case 'missing':
|
|
358
|
+
case 'literal':
|
|
359
|
+
case 'complex':
|
|
360
|
+
case 'identifier':
|
|
361
|
+
case 'operator':
|
|
362
|
+
case 'structured-reference':
|
|
363
|
+
break;
|
|
364
|
+
|
|
365
|
+
case 'dimensioned':
|
|
366
|
+
if (result) {
|
|
367
|
+
unit.expression = this.Walk2(unit.expression, func) as BaseExpressionUnit; // could be an issue
|
|
368
|
+
unit.unit = this.Walk2(unit.unit, func) as UnitIdentifier; // could be an issue
|
|
369
|
+
}
|
|
370
|
+
break;
|
|
371
|
+
|
|
372
|
+
case 'range':
|
|
373
|
+
if (func(unit)) {
|
|
374
|
+
unit.start = this.Walk2(unit.start, func) as UnitAddress; // could be an issue
|
|
375
|
+
unit.end = this.Walk2(unit.end, func) as UnitAddress; // could be an issue
|
|
376
|
+
}
|
|
377
|
+
break;
|
|
378
|
+
|
|
379
|
+
case 'binary':
|
|
380
|
+
if (func(unit)) {
|
|
381
|
+
unit.left = this.Walk2(unit.left, func);
|
|
382
|
+
unit.right = this.Walk2(unit.right, func);
|
|
383
|
+
}
|
|
384
|
+
break;
|
|
385
|
+
|
|
386
|
+
case 'unary':
|
|
387
|
+
if (func(unit)) {
|
|
388
|
+
unit.operand = this.Walk2(unit.operand, func);
|
|
389
|
+
}
|
|
390
|
+
break;
|
|
391
|
+
|
|
392
|
+
case 'group':
|
|
393
|
+
if (func(unit)) {
|
|
394
|
+
unit.elements = unit.elements.map(source => this.Walk2(source, func));
|
|
395
|
+
}
|
|
396
|
+
break;
|
|
397
|
+
|
|
398
|
+
case 'call':
|
|
399
|
+
if (func(unit)) {
|
|
400
|
+
unit.args = unit.args.map(source => this.Walk2(source, func));
|
|
401
|
+
}
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return unit;
|
|
406
|
+
|
|
407
|
+
}
|
|
408
|
+
|
|
337
409
|
/**
|
|
338
410
|
* recursive tree walk.
|
|
339
411
|
*
|
|
@@ -382,13 +454,19 @@ export class Parser {
|
|
|
382
454
|
|
|
383
455
|
case 'group':
|
|
384
456
|
if (func(unit)) {
|
|
385
|
-
unit.elements.forEach((element) => this.Walk(element, func));
|
|
457
|
+
// unit.elements.forEach((element) => this.Walk(element, func));
|
|
458
|
+
for (const element of unit.elements) {
|
|
459
|
+
this.Walk(element, func);
|
|
460
|
+
}
|
|
386
461
|
}
|
|
387
462
|
return;
|
|
388
463
|
|
|
389
464
|
case 'call':
|
|
390
465
|
if (func(unit)) {
|
|
391
|
-
|
|
466
|
+
for (const arg of unit.args) {
|
|
467
|
+
this.Walk(arg, func);
|
|
468
|
+
}
|
|
469
|
+
// unit.args.forEach((arg) => this.Walk(arg, func));
|
|
392
470
|
}
|
|
393
471
|
}
|
|
394
472
|
}
|
|
@@ -489,9 +567,15 @@ export class Parser {
|
|
|
489
567
|
|
|
490
568
|
switch (unit.type) {
|
|
491
569
|
case 'address':
|
|
570
|
+
if (options.pass_through_addresses) {
|
|
571
|
+
return unit.label;
|
|
572
|
+
}
|
|
492
573
|
return options.r1c1 ? this.R1C1Label(unit, options.r1c1_base) : this.AddressLabel(unit, offset);
|
|
493
574
|
|
|
494
575
|
case 'range':
|
|
576
|
+
if (options.pass_through_addresses) {
|
|
577
|
+
return unit.label;
|
|
578
|
+
}
|
|
495
579
|
return options.r1c1 ?
|
|
496
580
|
this.R1C1Label(unit.start, options.r1c1_base) + ':' + this.R1C1Label(unit.end, options.r1c1_base) :
|
|
497
581
|
this.AddressLabel(unit.start, offset) + ':' + this.AddressLabel(unit.end, offset);
|