@trebco/treb 23.6.5 → 25.0.0-rc1
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/.eslintignore +8 -0
- package/.eslintrc.js +164 -0
- package/README-shadow-DOM.md +88 -0
- package/README.md +37 -130
- package/api-config.json +29 -0
- package/api-generator/api-generator-types.ts +82 -0
- package/api-generator/api-generator.ts +1172 -0
- package/api-generator/package.json +3 -0
- package/build/treb-spreadsheet.mjs +14 -0
- package/{treb.d.ts → build/treb.d.ts} +285 -269
- package/esbuild-custom-element.mjs +336 -0
- package/esbuild.js +305 -0
- package/package.json +43 -14
- package/treb-base-types/package.json +5 -0
- package/treb-base-types/src/api_types.ts +36 -0
- package/treb-base-types/src/area.ts +583 -0
- package/treb-base-types/src/basic_types.ts +45 -0
- package/treb-base-types/src/cell.ts +612 -0
- package/treb-base-types/src/cells.ts +1066 -0
- package/treb-base-types/src/color.ts +124 -0
- package/treb-base-types/src/import.ts +71 -0
- package/treb-base-types/src/index-standalone.ts +29 -0
- package/treb-base-types/src/index.ts +42 -0
- package/treb-base-types/src/layout.ts +47 -0
- package/treb-base-types/src/localization.ts +187 -0
- package/treb-base-types/src/rectangle.ts +145 -0
- package/treb-base-types/src/render_text.ts +72 -0
- package/treb-base-types/src/style.ts +545 -0
- package/treb-base-types/src/table.ts +109 -0
- package/treb-base-types/src/text_part.ts +54 -0
- package/treb-base-types/src/theme.ts +608 -0
- package/treb-base-types/src/union.ts +152 -0
- package/treb-base-types/src/value-type.ts +164 -0
- package/treb-base-types/style/resizable.css +59 -0
- package/treb-calculator/modern.tsconfig.json +11 -0
- package/treb-calculator/package.json +5 -0
- package/treb-calculator/src/calculator.ts +2546 -0
- package/treb-calculator/src/complex-math.ts +558 -0
- package/treb-calculator/src/dag/array-vertex.ts +198 -0
- package/treb-calculator/src/dag/graph.ts +951 -0
- package/treb-calculator/src/dag/leaf_vertex.ts +118 -0
- package/treb-calculator/src/dag/spreadsheet_vertex.ts +327 -0
- package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +44 -0
- package/treb-calculator/src/dag/vertex.ts +352 -0
- package/treb-calculator/src/descriptors.ts +162 -0
- package/treb-calculator/src/expression-calculator.ts +1069 -0
- package/treb-calculator/src/function-error.ts +103 -0
- package/treb-calculator/src/function-library.ts +103 -0
- package/treb-calculator/src/functions/base-functions.ts +1214 -0
- package/treb-calculator/src/functions/checkbox.ts +164 -0
- package/treb-calculator/src/functions/complex-functions.ts +253 -0
- package/treb-calculator/src/functions/finance-functions.ts +399 -0
- package/treb-calculator/src/functions/information-functions.ts +102 -0
- package/treb-calculator/src/functions/matrix-functions.ts +182 -0
- package/treb-calculator/src/functions/sparkline.ts +335 -0
- package/treb-calculator/src/functions/statistics-functions.ts +350 -0
- package/treb-calculator/src/functions/text-functions.ts +298 -0
- package/treb-calculator/src/index.ts +27 -0
- package/treb-calculator/src/notifier-types.ts +59 -0
- package/treb-calculator/src/primitives.ts +428 -0
- package/treb-calculator/src/utilities.ts +305 -0
- package/treb-charts/package.json +5 -0
- package/treb-charts/src/chart-functions.ts +156 -0
- package/treb-charts/src/chart-types.ts +230 -0
- package/treb-charts/src/chart.ts +1288 -0
- package/treb-charts/src/index.ts +24 -0
- package/treb-charts/src/main.ts +37 -0
- package/treb-charts/src/rectangle.ts +52 -0
- package/treb-charts/src/renderer.ts +1841 -0
- package/treb-charts/src/util.ts +122 -0
- package/treb-charts/style/charts.scss +221 -0
- package/treb-charts/style/old-charts.scss +250 -0
- package/treb-embed/markup/layout.html +137 -0
- package/treb-embed/markup/toolbar.html +175 -0
- package/treb-embed/modern.tsconfig.json +25 -0
- package/treb-embed/src/custom-element/content-types.d.ts +18 -0
- package/treb-embed/src/custom-element/global.d.ts +11 -0
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +1227 -0
- package/treb-embed/src/custom-element/treb-global.ts +44 -0
- package/treb-embed/src/custom-element/treb-spreadsheet-element.ts +52 -0
- package/treb-embed/src/embedded-spreadsheet.ts +5362 -0
- package/treb-embed/src/index.ts +16 -0
- package/treb-embed/src/language-model.ts +41 -0
- package/treb-embed/src/options.ts +320 -0
- package/treb-embed/src/progress-dialog.ts +228 -0
- package/treb-embed/src/selection-state.ts +16 -0
- package/treb-embed/src/spinner.ts +42 -0
- package/treb-embed/src/toolbar-message.ts +96 -0
- package/treb-embed/src/types.ts +167 -0
- package/treb-embed/style/autocomplete.scss +103 -0
- package/treb-embed/style/dark-theme.scss +114 -0
- package/treb-embed/style/defaults.scss +36 -0
- package/treb-embed/style/dialog.scss +181 -0
- package/treb-embed/style/dropdown-select.scss +101 -0
- package/treb-embed/style/formula-bar.scss +193 -0
- package/treb-embed/style/grid.scss +374 -0
- package/treb-embed/style/layout.scss +424 -0
- package/treb-embed/style/mouse-mask.scss +67 -0
- package/treb-embed/style/note.scss +92 -0
- package/treb-embed/style/overlay-editor.scss +102 -0
- package/treb-embed/style/spinner.scss +92 -0
- package/treb-embed/style/tab-bar.scss +228 -0
- package/treb-embed/style/table.scss +80 -0
- package/treb-embed/style/theme-defaults.scss +444 -0
- package/treb-embed/style/toolbar.scss +416 -0
- package/treb-embed/style/tooltip.scss +68 -0
- package/treb-embed/style/treb-icons.scss +130 -0
- package/treb-embed/style/treb-spreadsheet-element.scss +20 -0
- package/treb-embed/style/z-index.scss +43 -0
- package/treb-export/docs/charts.md +68 -0
- package/treb-export/modern.tsconfig.json +19 -0
- package/treb-export/package.json +4 -0
- package/treb-export/src/address-type.ts +77 -0
- package/treb-export/src/base-template.ts +22 -0
- package/treb-export/src/column-width.ts +85 -0
- package/treb-export/src/drawing2/chart-template-components2.ts +389 -0
- package/treb-export/src/drawing2/chart2.ts +282 -0
- package/treb-export/src/drawing2/column-chart-template2.ts +521 -0
- package/treb-export/src/drawing2/donut-chart-template2.ts +296 -0
- package/treb-export/src/drawing2/drawing2.ts +355 -0
- package/treb-export/src/drawing2/embedded-image.ts +71 -0
- package/treb-export/src/drawing2/scatter-chart-template2.ts +555 -0
- package/treb-export/src/export-worker/export-worker.ts +99 -0
- package/treb-export/src/export-worker/index-modern.ts +22 -0
- package/treb-export/src/export2.ts +2204 -0
- package/treb-export/src/import2.ts +882 -0
- package/treb-export/src/relationship.ts +36 -0
- package/treb-export/src/shared-strings2.ts +128 -0
- package/treb-export/src/template-2.ts +22 -0
- package/treb-export/src/unescape_xml.ts +47 -0
- package/treb-export/src/workbook-sheet2.ts +182 -0
- package/treb-export/src/workbook-style2.ts +1285 -0
- package/treb-export/src/workbook-theme2.ts +88 -0
- package/treb-export/src/workbook2.ts +491 -0
- package/treb-export/src/xml-utils.ts +201 -0
- package/treb-export/template/base/[Content_Types].xml +2 -0
- package/treb-export/template/base/_rels/.rels +2 -0
- package/treb-export/template/base/docProps/app.xml +2 -0
- package/treb-export/template/base/docProps/core.xml +12 -0
- package/treb-export/template/base/xl/_rels/workbook.xml.rels +2 -0
- package/treb-export/template/base/xl/sharedStrings.xml +2 -0
- package/treb-export/template/base/xl/styles.xml +2 -0
- package/treb-export/template/base/xl/theme/theme1.xml +2 -0
- package/treb-export/template/base/xl/workbook.xml +2 -0
- package/treb-export/template/base/xl/worksheets/sheet1.xml +2 -0
- package/treb-export/template/base.xlsx +0 -0
- package/treb-format/package.json +8 -0
- package/treb-format/src/format.test.ts +213 -0
- package/treb-format/src/format.ts +942 -0
- package/treb-format/src/format_cache.ts +199 -0
- package/treb-format/src/format_parser.ts +723 -0
- package/treb-format/src/index.ts +25 -0
- package/treb-format/src/number_format_section.ts +100 -0
- package/treb-format/src/value_parser.ts +337 -0
- package/treb-grid/package.json +5 -0
- package/treb-grid/src/editors/autocomplete.ts +394 -0
- package/treb-grid/src/editors/autocomplete_matcher.ts +260 -0
- package/treb-grid/src/editors/formula_bar.ts +473 -0
- package/treb-grid/src/editors/formula_editor_base.ts +910 -0
- package/treb-grid/src/editors/overlay_editor.ts +511 -0
- package/treb-grid/src/index.ts +37 -0
- package/treb-grid/src/layout/base_layout.ts +2618 -0
- package/treb-grid/src/layout/grid_layout.ts +299 -0
- package/treb-grid/src/layout/rectangle_cache.ts +86 -0
- package/treb-grid/src/render/selection-renderer.ts +414 -0
- package/treb-grid/src/render/svg_header_overlay.ts +93 -0
- package/treb-grid/src/render/svg_selection_block.ts +187 -0
- package/treb-grid/src/render/tile_renderer.ts +2122 -0
- package/treb-grid/src/types/annotation.ts +216 -0
- package/treb-grid/src/types/border_constants.ts +34 -0
- package/treb-grid/src/types/clipboard_data.ts +31 -0
- package/treb-grid/src/types/data_model.ts +334 -0
- package/treb-grid/src/types/drag_mask.ts +81 -0
- package/treb-grid/src/types/grid.ts +7743 -0
- package/treb-grid/src/types/grid_base.ts +3644 -0
- package/treb-grid/src/types/grid_command.ts +470 -0
- package/treb-grid/src/types/grid_events.ts +124 -0
- package/treb-grid/src/types/grid_options.ts +97 -0
- package/treb-grid/src/types/grid_selection.ts +60 -0
- package/treb-grid/src/types/named_range.ts +369 -0
- package/treb-grid/src/types/scale-control.ts +202 -0
- package/treb-grid/src/types/serialize_options.ts +72 -0
- package/treb-grid/src/types/set_range_options.ts +52 -0
- package/treb-grid/src/types/sheet.ts +3099 -0
- package/treb-grid/src/types/sheet_types.ts +95 -0
- package/treb-grid/src/types/tab_bar.ts +464 -0
- package/treb-grid/src/types/tile.ts +59 -0
- package/treb-grid/src/types/update_flags.ts +75 -0
- package/treb-grid/src/util/dom_utilities.ts +44 -0
- package/treb-grid/src/util/fontmetrics2.ts +179 -0
- package/treb-grid/src/util/ua.ts +104 -0
- package/treb-logo.svg +18 -0
- package/treb-parser/package.json +5 -0
- package/treb-parser/src/csv-parser.ts +122 -0
- package/treb-parser/src/index.ts +25 -0
- package/treb-parser/src/md-parser.ts +526 -0
- package/treb-parser/src/parser-types.ts +397 -0
- package/treb-parser/src/parser.test.ts +298 -0
- package/treb-parser/src/parser.ts +2673 -0
- package/treb-utils/package.json +5 -0
- package/treb-utils/src/dispatch.ts +57 -0
- package/treb-utils/src/event_source.ts +147 -0
- package/treb-utils/src/ievent_source.ts +33 -0
- package/treb-utils/src/index.ts +31 -0
- package/treb-utils/src/measurement.ts +174 -0
- package/treb-utils/src/resizable.ts +160 -0
- package/treb-utils/src/scale.ts +137 -0
- package/treb-utils/src/serialize_html.ts +124 -0
- package/treb-utils/src/template.ts +70 -0
- package/treb-utils/src/validate_uri.ts +61 -0
- package/tsconfig.json +10 -0
- package/tsproject.json +30 -0
- package/util/license-plugin-esbuild.js +86 -0
- package/util/list-css-vars.sh +46 -0
- package/README-esm.md +0 -37
- package/treb-bundle.css +0 -2
- package/treb-bundle.mjs +0 -15
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of TREB.
|
|
3
|
+
*
|
|
4
|
+
* TREB is free software: you can redistribute it and/or modify it under the
|
|
5
|
+
* terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
* Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
+
* later version.
|
|
8
|
+
*
|
|
9
|
+
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
10
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
12
|
+
* details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License along
|
|
15
|
+
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
* Copyright 2022-2023 trebco, llc.
|
|
18
|
+
* info@treb.app
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export * from './number_format_section';
|
|
23
|
+
export * from './format';
|
|
24
|
+
export * from './format_cache';
|
|
25
|
+
export * from './value_parser';
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of TREB.
|
|
3
|
+
*
|
|
4
|
+
* TREB is free software: you can redistribute it and/or modify it under the
|
|
5
|
+
* terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
* Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
+
* later version.
|
|
8
|
+
*
|
|
9
|
+
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
10
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
12
|
+
* details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License along
|
|
15
|
+
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
* Copyright 2022-2023 trebco, llc.
|
|
18
|
+
* info@treb.app
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type { TextPart } from 'treb-base-types';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* essentially number formats have a core section with the number
|
|
26
|
+
* (possibly scaled), and some representation before and after.
|
|
27
|
+
* exponential and percentage notation scale the number. exponential
|
|
28
|
+
* is only allowed after the number. percent can come before or after.
|
|
29
|
+
*
|
|
30
|
+
* converting to class, default values
|
|
31
|
+
*
|
|
32
|
+
* FIXME: this should be an interface, you can create a default instance
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
35
|
+
export class NumberFormatSection {
|
|
36
|
+
|
|
37
|
+
/** flag: this is a date format */
|
|
38
|
+
public date_format = false;
|
|
39
|
+
|
|
40
|
+
/** flag: this is the string section, don't format numbers */
|
|
41
|
+
public string_format = false;
|
|
42
|
+
|
|
43
|
+
/** flag: this is a fractional format */
|
|
44
|
+
public fraction_format = false;
|
|
45
|
+
|
|
46
|
+
/** flag: time in 12-hour format */
|
|
47
|
+
public twelve_hour = false;
|
|
48
|
+
|
|
49
|
+
/** fraction: fixed denominator */
|
|
50
|
+
public fraction_denominator = 0;
|
|
51
|
+
|
|
52
|
+
/** fraction includes integer */
|
|
53
|
+
public fraction_integer = true;
|
|
54
|
+
|
|
55
|
+
/** align fraction digits (using ???) [TODO] */
|
|
56
|
+
public fraction_align = 0;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* fraction denominator digits. we will limit to [1,4] but this can
|
|
60
|
+
* be zero if there's an explicit denominator.
|
|
61
|
+
*/
|
|
62
|
+
public fraction_denominator_digits = 0;
|
|
63
|
+
|
|
64
|
+
/** prepend zeros */
|
|
65
|
+
public integer_min_digits = 0;
|
|
66
|
+
|
|
67
|
+
/** append zeros */
|
|
68
|
+
public decimal_min_digits = 0;
|
|
69
|
+
|
|
70
|
+
/** append decimal digits, but not trailing zeros */
|
|
71
|
+
public decimal_max_digits = 0;
|
|
72
|
+
|
|
73
|
+
/** use grouping (only supports groups of 3, no matter where you put the ,) */
|
|
74
|
+
public grouping = false;
|
|
75
|
+
|
|
76
|
+
/** this is a flag for switching whether we append strings to prefix or suffix */
|
|
77
|
+
public has_number_format = false;
|
|
78
|
+
|
|
79
|
+
/** leading string(s) */
|
|
80
|
+
public prefix: TextPart[] = [{ text: '' }];
|
|
81
|
+
|
|
82
|
+
/** trailing string(s) */
|
|
83
|
+
public suffix: TextPart[] = [{ text: '' }];
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* thousands scaling (trailing commas in the number format section). we set
|
|
87
|
+
* to zero for a faster flag if no scaling.
|
|
88
|
+
*/
|
|
89
|
+
public scaling = 0;
|
|
90
|
+
|
|
91
|
+
/** flag indicating percent -- will multiply value by 100 */
|
|
92
|
+
public percent = false;
|
|
93
|
+
|
|
94
|
+
/** flag indicating exponential -- turns numbers in to exp format */
|
|
95
|
+
public exponential = false;
|
|
96
|
+
|
|
97
|
+
/** this is a flag for testing -- we don't support multiple * in a format */
|
|
98
|
+
public has_asterisk = false;
|
|
99
|
+
|
|
100
|
+
}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of TREB.
|
|
3
|
+
*
|
|
4
|
+
* TREB is free software: you can redistribute it and/or modify it under the
|
|
5
|
+
* terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
* Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
+
* later version.
|
|
8
|
+
*
|
|
9
|
+
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
10
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
12
|
+
* details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License along
|
|
15
|
+
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
* Copyright 2022-2023 trebco, llc.
|
|
18
|
+
* info@treb.app
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { ValueType, Localization, Complex } from 'treb-base-types';
|
|
23
|
+
import { UnlotusDate } from './format';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* this is code that was in the old number format class, which was superceded
|
|
27
|
+
* by the new treb-format module. we still need to do rough value parsing,
|
|
28
|
+
* which is separate from parsing and from formatting.
|
|
29
|
+
*
|
|
30
|
+
* cleaning up to remove redundant bits, move inference in here
|
|
31
|
+
*
|
|
32
|
+
* FIXME: move this somewhere else, this is the format library
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
// tslint:disable:no-bitwise
|
|
36
|
+
|
|
37
|
+
/** hints is a bitfield */
|
|
38
|
+
export enum Hints {
|
|
39
|
+
None = 0x00,
|
|
40
|
+
Nan = 0x01,
|
|
41
|
+
Exponential = 0x02,
|
|
42
|
+
Percent = 0x04,
|
|
43
|
+
Currency = 0x08,
|
|
44
|
+
Grouping = 0x10,
|
|
45
|
+
Parens = 0x20,
|
|
46
|
+
Date = 0x40,
|
|
47
|
+
Time = 0x80,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* parse result now uses base valuetype
|
|
52
|
+
*/
|
|
53
|
+
export interface ParseResult {
|
|
54
|
+
|
|
55
|
+
value: number|string|boolean|undefined|Complex;
|
|
56
|
+
hints?: Hints;
|
|
57
|
+
type: ValueType;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const this_year = new Date().getUTCFullYear();
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* value parser class is a singleton, instance is exported
|
|
64
|
+
*/
|
|
65
|
+
class ValueParserType {
|
|
66
|
+
|
|
67
|
+
public compare_day?: Record<string, number>;
|
|
68
|
+
public compare_month?: Record<string, number>;
|
|
69
|
+
|
|
70
|
+
public TestDate(text: string): number|false {
|
|
71
|
+
|
|
72
|
+
// first check if JS can turn it into a date at all. we can
|
|
73
|
+
// use that as a baseline/initial check (in any event there's
|
|
74
|
+
// no point in doing the work otherwise)
|
|
75
|
+
|
|
76
|
+
const date_value = Date.parse(text);
|
|
77
|
+
if (isNaN(date_value)) {
|
|
78
|
+
// console.info('td false: is nan')
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const date = new Date(date_value);
|
|
83
|
+
|
|
84
|
+
// OK so there's a date, now we can do whatever validation we want
|
|
85
|
+
|
|
86
|
+
// is there a regexp for accented characters? actually we can
|
|
87
|
+
// maybe go backwards... remove things that properly belong in
|
|
88
|
+
// dates: numbers, dashes and slashes (+ comma, whitespace)
|
|
89
|
+
|
|
90
|
+
// dots are in some l10n systems... maybe we should check first?
|
|
91
|
+
|
|
92
|
+
// Q: what does lowercase do for accented characters? (...)
|
|
93
|
+
|
|
94
|
+
// NOTE: as it turns out, Date.parse() only handles US-EN. so
|
|
95
|
+
// all this is unecessary (and unused) in other locales. to really
|
|
96
|
+
// do this properly we will probably need to write our own locale-
|
|
97
|
+
// aware date parser. which is probably a lot of work. TODO.
|
|
98
|
+
|
|
99
|
+
const tmp = text.replace(/[\d\-\\/,.\s]+/g, ' ').toLocaleLowerCase();
|
|
100
|
+
|
|
101
|
+
// then split into individual strings. trim and drop empty
|
|
102
|
+
|
|
103
|
+
const components = tmp.split(/\s+/).map(component => component.trim()).filter(component => !!component);
|
|
104
|
+
|
|
105
|
+
if (!components.length) {
|
|
106
|
+
// console.info('td true: no strings');
|
|
107
|
+
return date_value; // probably a date
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// now we'll compare these to stuff we have in l10n. rule (WIP):
|
|
111
|
+
// should be in month or day-of-week. accept short or long, or one
|
|
112
|
+
// character. (one character introduces some ambiguity...)
|
|
113
|
+
|
|
114
|
+
// drop 1 character, it's ambiguous and annoying (also hard to handle)
|
|
115
|
+
|
|
116
|
+
// so basically, any string in here has to be a month or day; we can't
|
|
117
|
+
// have two of either; they have to match what was parsed; and you can't
|
|
118
|
+
// have a day-of-week but not a month.
|
|
119
|
+
|
|
120
|
+
// FIXME: cache/precalc
|
|
121
|
+
// let's do it lazily
|
|
122
|
+
|
|
123
|
+
// NOTE: portugeuse seems to include periods in their abbreviations...
|
|
124
|
+
|
|
125
|
+
if (!this.compare_month) {
|
|
126
|
+
this.compare_month = {};
|
|
127
|
+
for (let i = 0; i < 12; i++) {
|
|
128
|
+
this.compare_month[Localization.date_components.long_months[i].toLocaleLowerCase().replace(/\./, '')] = i;
|
|
129
|
+
this.compare_month[Localization.date_components.short_months[i].toLocaleLowerCase().replace(/\./, '')] = i;
|
|
130
|
+
// comparison[Localization.date_components.long_months[i][0].toLocaleLowerCase()] = i;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!this.compare_day) {
|
|
135
|
+
this.compare_day = {};
|
|
136
|
+
for (let i = 0; i < 7; i++) {
|
|
137
|
+
this.compare_day[Localization.date_components.long_days[i].toLocaleLowerCase().replace(/\./, '')] = i;
|
|
138
|
+
this.compare_day[Localization.date_components.short_days[i].toLocaleLowerCase().replace(/\./, '')] = i;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
let found_month = false;
|
|
143
|
+
let found_day = false;
|
|
144
|
+
|
|
145
|
+
for (const component of components) {
|
|
146
|
+
let found = false;
|
|
147
|
+
for (const [month, value] of Object.entries(this.compare_month)) {
|
|
148
|
+
if (component === month) {
|
|
149
|
+
|
|
150
|
+
// can't have two months in a single date
|
|
151
|
+
if (found_month) {
|
|
152
|
+
// console.info('td false: two months')
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// have a string match [FIXME: fuzzy?]
|
|
157
|
+
// check that the month matches
|
|
158
|
+
|
|
159
|
+
if (date.getUTCMonth() !== value) {
|
|
160
|
+
// console.info('td false: month mismatch')
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
found = true;
|
|
165
|
+
found_month = true;
|
|
166
|
+
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (!found) {
|
|
170
|
+
for (const [day, value] of Object.entries(this.compare_day)) {
|
|
171
|
+
if (component === day) {
|
|
172
|
+
|
|
173
|
+
// can't have two days either
|
|
174
|
+
if (found_day) {
|
|
175
|
+
// console.info('td false: two days')
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (date.getUTCDay() !== value) {
|
|
180
|
+
// console.info('td false: day mismatch')
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
found = true;
|
|
185
|
+
found_day = true;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (!found) {
|
|
191
|
+
|
|
192
|
+
// whatever this string is, we don't recognize it. so this is
|
|
193
|
+
// probably not a date.
|
|
194
|
+
|
|
195
|
+
// console.info('td false: unmatched string')
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// last check: no DOW without month.
|
|
201
|
+
|
|
202
|
+
if (found_day && !found_month) {
|
|
203
|
+
// console.info('td false: day but no month')
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// OK, accept it
|
|
208
|
+
|
|
209
|
+
// console.info('td true: ran out of cases')
|
|
210
|
+
return date_value;
|
|
211
|
+
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* parse a string. if it can reasonably be converted to a number,
|
|
216
|
+
* do that and return the number; otherwise return the original
|
|
217
|
+
* string. we also return hints as to formatting, which the caller
|
|
218
|
+
* may use to select a number format.
|
|
219
|
+
*
|
|
220
|
+
* remind me why this is better than just using a parser? (...)
|
|
221
|
+
*/
|
|
222
|
+
public TryParse(text = ''): ParseResult {
|
|
223
|
+
|
|
224
|
+
let hints: Hints = Hints.None;
|
|
225
|
+
|
|
226
|
+
// starts with SINGLE quote mark. express string.
|
|
227
|
+
if (text[0] === '\'') return { value: text, type: ValueType.string };
|
|
228
|
+
|
|
229
|
+
// empty string, treat as string (should be === 0 though?)
|
|
230
|
+
if (text === '') return { value: text, type: ValueType.string };
|
|
231
|
+
|
|
232
|
+
// we test if the conversion returns NaN, which usually means
|
|
233
|
+
// it's not a number -- unless the string is actually NaN, which
|
|
234
|
+
// is something we want to preserve.
|
|
235
|
+
if ( text === 'NaN' ) return { value: NaN, type: ValueType.number, hints: Hints.Nan };
|
|
236
|
+
|
|
237
|
+
let x = text.trim();
|
|
238
|
+
// x = x.replace(/^[\$£€]/, '').trim();
|
|
239
|
+
|
|
240
|
+
const currency = x.match(/^[$](.*?)$/);
|
|
241
|
+
if (currency) {
|
|
242
|
+
x = currency[1];
|
|
243
|
+
hints |= Hints.Currency;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const parens = x.match(/^\((.*?)\)$/);
|
|
247
|
+
if (parens) {
|
|
248
|
+
x = parens[1];
|
|
249
|
+
hints |= Hints.Parens;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const pct = x.match(/^(.*?)%\s*$/);
|
|
253
|
+
if (pct) {
|
|
254
|
+
x = pct[1];
|
|
255
|
+
hints |= Hints.Percent;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (Localization.decimal_separator === '.'){
|
|
259
|
+
if (/,/.test(x)) {
|
|
260
|
+
x = x.replace(/,/g, '');
|
|
261
|
+
hints |= Hints.Grouping;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
x = x.replace(/(\d)\s+/g, '$1'); // remove spaces inside numbers
|
|
266
|
+
x = x.replace(/\./g, ''); // remove point separators
|
|
267
|
+
x = x.replace(/,/, '.'); // convert to US-style
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
let num = Number(x);
|
|
271
|
+
|
|
272
|
+
if (null === num || isNaN(num)){
|
|
273
|
+
|
|
274
|
+
// check boolean
|
|
275
|
+
const lc = text.toLowerCase();
|
|
276
|
+
if (lc === 'false') return { value: false, type: ValueType.boolean };
|
|
277
|
+
if (lc === 'true' ) return { value: true, type: ValueType.boolean };
|
|
278
|
+
|
|
279
|
+
// check date, but bound on reasonable years...
|
|
280
|
+
// also maybe parameterize, make this optional
|
|
281
|
+
|
|
282
|
+
// this is too aggressive (at least in chrome). we need to dial it
|
|
283
|
+
// back a bit. to do that, we will validate any strings in the text
|
|
284
|
+
// and ensure they look like date components (usually months and days),
|
|
285
|
+
// within the current locale.
|
|
286
|
+
|
|
287
|
+
const date = this.TestDate(text);
|
|
288
|
+
|
|
289
|
+
if (false !== date && !isNaN(date)) {
|
|
290
|
+
|
|
291
|
+
// we can drop this bit, now (I think)
|
|
292
|
+
|
|
293
|
+
const check = new Date(date);
|
|
294
|
+
const year = check.getUTCFullYear();
|
|
295
|
+
|
|
296
|
+
if (year >= (this_year - 200) && year <= (this_year + 200)) {
|
|
297
|
+
hints = Hints.Date;
|
|
298
|
+
|
|
299
|
+
if (check.getHours() || check.getMinutes() || check.getSeconds()) {
|
|
300
|
+
hints |= Hints.Time;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
value: UnlotusDate(date),
|
|
305
|
+
type: ValueType.number,
|
|
306
|
+
hints,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return { value: text, type: ValueType.string };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (parens) { num = -num; }
|
|
316
|
+
if (pct) {
|
|
317
|
+
|
|
318
|
+
// NOTE: this is an attempt to reduce fp errors that arise
|
|
319
|
+
// if you /100 (or if you /10 twice, which actually helps, but
|
|
320
|
+
// is not sufficient). there's probably a better way to do this...
|
|
321
|
+
|
|
322
|
+
const sign = num < 0 ? -1 : 1;
|
|
323
|
+
const split = (sign * num).toString().split('.');
|
|
324
|
+
|
|
325
|
+
split[0] = ('00' + split[0]).replace(/(\d\d)$/, '.$1');
|
|
326
|
+
num = Number(split.join('')) * sign;
|
|
327
|
+
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (/e/.test(text)) hints |= Hints.Exponential;
|
|
331
|
+
return { value: num, type: ValueType.number, hints };
|
|
332
|
+
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export const ValueParser = new ValueParserType();
|