@fieldia/core 0.20.0 → 0.21.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/package.json +1 -1
- package/schema/page.schema.json +24 -0
- package/src/lib/expression/parser.js +4 -4
- package/src/lib/expression/parser.js.map +1 -1
- package/src/lib/expression/parser.mjs +5 -5
- package/src/lib/expression/parser.mjs.map +1 -1
- package/src/lib/expression/tokenizer.d.mts +12 -0
- package/src/lib/expression/tokenizer.d.ts +12 -0
- package/src/lib/expression/tokenizer.js +21 -12
- package/src/lib/expression/tokenizer.js.map +1 -1
- package/src/lib/expression/tokenizer.mjs +20 -12
- package/src/lib/expression/tokenizer.mjs.map +1 -1
- package/src/lib/format/field.d.mts +16 -0
- package/src/lib/format/field.d.ts +16 -0
- package/src/lib/format/field.js +11 -1
- package/src/lib/format/field.js.map +1 -1
- package/src/lib/format/field.mjs +11 -1
- package/src/lib/format/field.mjs.map +1 -1
- package/src/lib/format/page.d.mts +18 -0
- package/src/lib/format/page.d.ts +18 -0
- package/src/lib/format/page.js +1 -0
- package/src/lib/format/page.js.map +1 -1
- package/src/lib/format/page.mjs +1 -0
- package/src/lib/format/page.mjs.map +1 -1
- package/src/lib/format/pattern.d.mts +10 -0
- package/src/lib/format/pattern.d.ts +10 -0
- package/src/lib/format/pattern.js +33 -0
- package/src/lib/format/pattern.js.map +1 -0
- package/src/lib/format/pattern.mjs +30 -0
- package/src/lib/format/pattern.mjs.map +1 -0
- package/src/lib/format/references.js +8 -0
- package/src/lib/format/references.js.map +1 -1
- package/src/lib/format/references.mjs +8 -0
- package/src/lib/format/references.mjs.map +1 -1
- package/src/lib/format/translate.js +3 -2
- package/src/lib/format/translate.js.map +1 -1
- package/src/lib/format/translate.mjs +3 -2
- package/src/lib/format/translate.mjs.map +1 -1
- package/src/lib/record/check.d.mts +13 -3
- package/src/lib/record/check.d.ts +13 -3
- package/src/lib/record/check.js +87 -17
- package/src/lib/record/check.js.map +1 -1
- package/src/lib/record/check.mjs +85 -17
- package/src/lib/record/check.mjs.map +1 -1
- package/src/lib/record/filter.js +14 -2
- package/src/lib/record/filter.js.map +1 -1
- package/src/lib/record/filter.mjs +14 -2
- package/src/lib/record/filter.mjs.map +1 -1
- package/src/lib/record/form.d.mts +44 -0
- package/src/lib/record/form.d.ts +44 -0
- package/src/lib/record/form.js +249 -20
- package/src/lib/record/form.js.map +1 -1
- package/src/lib/record/form.mjs +251 -22
- package/src/lib/record/form.mjs.map +1 -1
- package/src/lib/record/input-rules.d.mts +277 -0
- package/src/lib/record/input-rules.d.ts +277 -0
- package/src/lib/record/input-rules.js +724 -0
- package/src/lib/record/input-rules.js.map +1 -0
- package/src/lib/record/input-rules.mjs +705 -0
- package/src/lib/record/input-rules.mjs.map +1 -0
- package/src/lib/record/inputs.d.mts +25 -0
- package/src/lib/record/inputs.d.ts +25 -0
- package/src/lib/record/inputs.js +135 -9
- package/src/lib/record/inputs.js.map +1 -1
- package/src/lib/record/inputs.mjs +131 -9
- package/src/lib/record/inputs.mjs.map +1 -1
- package/src/lib/record/locales/ar.js +13 -2
- package/src/lib/record/locales/ar.js.map +1 -1
- package/src/lib/record/locales/ar.mjs +13 -2
- package/src/lib/record/locales/ar.mjs.map +1 -1
- package/src/lib/record/locales/de.js +13 -2
- package/src/lib/record/locales/de.js.map +1 -1
- package/src/lib/record/locales/de.mjs +13 -2
- package/src/lib/record/locales/de.mjs.map +1 -1
- package/src/lib/record/locales/fr.js +13 -2
- package/src/lib/record/locales/fr.js.map +1 -1
- package/src/lib/record/locales/fr.mjs +13 -2
- package/src/lib/record/locales/fr.mjs.map +1 -1
- package/src/lib/record/memory-data-source.js +7 -3
- package/src/lib/record/memory-data-source.js.map +1 -1
- package/src/lib/record/memory-data-source.mjs +7 -3
- package/src/lib/record/memory-data-source.mjs.map +1 -1
- package/src/lib/record/messages.d.mts +22 -0
- package/src/lib/record/messages.d.ts +22 -0
- package/src/lib/record/messages.js +13 -2
- package/src/lib/record/messages.js.map +1 -1
- package/src/lib/record/messages.mjs +13 -2
- package/src/lib/record/messages.mjs.map +1 -1
- package/src/lib/record/rules.js +3 -1
- package/src/lib/record/rules.js.map +1 -1
- package/src/lib/record/rules.mjs +3 -1
- package/src/lib/record/rules.mjs.map +1 -1
- package/src/lib/record/run.d.mts +3 -2
- package/src/lib/record/run.d.ts +3 -2
- package/src/lib/record/run.js +1 -1
- package/src/lib/record/run.js.map +1 -1
- package/src/lib/record/run.mjs +1 -1
- package/src/lib/record/run.mjs.map +1 -1
- package/src/lib/record/search.d.mts +8 -1
- package/src/lib/record/search.d.ts +8 -1
- package/src/lib/record/search.js +28 -8
- package/src/lib/record/search.js.map +1 -1
- package/src/lib/record/search.mjs +28 -8
- package/src/lib/record/search.mjs.map +1 -1
- package/src/lib/record/structures.d.mts +8 -3
- package/src/lib/record/structures.d.ts +8 -3
- package/src/lib/record/structures.js +51 -7
- package/src/lib/record/structures.js.map +1 -1
- package/src/lib/record/structures.mjs +48 -6
- package/src/lib/record/structures.mjs.map +1 -1
- package/src/runtime.d.mts +5 -2
- package/src/runtime.d.ts +5 -2
- package/src/runtime.js +31 -1
- package/src/runtime.js.map +1 -1
- package/src/runtime.mjs +5 -2
- package/src/runtime.mjs.map +1 -1
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How Fieldia reads what a person types or pastes into a box: one set of
|
|
3
|
+
* readers for every box — a form's fields, a table's cells, a list's filters,
|
|
4
|
+
* the designer's settings — so a number, a duration, a date or a word is read
|
|
5
|
+
* the same way wherever it is typed. Pure: no DOM, no form.
|
|
6
|
+
*
|
|
7
|
+
* People in Egypt and the Gulf type in Arabic too: Arabic-Indic digits
|
|
8
|
+
* (٠١٢…), Persian ones (۰۱۲…), the Arabic decimal separator (٫) and its
|
|
9
|
+
* thousands separator (٬), and a French or German decimal comma are read,
|
|
10
|
+
* never refused. Invisible direction marks, which Arabic text carries and
|
|
11
|
+
* copying brings along, are never part of what is read.
|
|
12
|
+
*/
|
|
13
|
+
/** Invisible direction marks taken out: everywhere (what is structured), or only at the ends (any one line of text). */
|
|
14
|
+
export declare function stripMarks(text: string, where?: 'all' | 'ends'): string;
|
|
15
|
+
/** Arabic-Indic (٠-٩), Persian (۰-۹) and fullwidth (0-9) digits as 0-9; every other character as it is. */
|
|
16
|
+
export declare function foldDigits(text: string): string;
|
|
17
|
+
/** Line breaks as spaces, as one line of text keeps them; a password drops them instead. */
|
|
18
|
+
export declare function oneLine(text: string, options?: {
|
|
19
|
+
password?: boolean;
|
|
20
|
+
}): string;
|
|
21
|
+
/** How many characters a text has, as a server counts them: by code point, so an emoji is one. */
|
|
22
|
+
export declare function charCount(text: string): number;
|
|
23
|
+
/**
|
|
24
|
+
* Words folded for finding: case, Arabic letter forms (أ إ آ ٱ as ا, ة as ه,
|
|
25
|
+
* ى as ي, the tatweel and short vowels dropped), digits in any script as 0-9,
|
|
26
|
+
* and no direction marks — so "أحمد" finds "احمد" and "١٢" finds "12".
|
|
27
|
+
*/
|
|
28
|
+
export declare function foldForSearch(text: string): string;
|
|
29
|
+
/** A page's own marks for numbers: its decimal mark and its grouping mark. */
|
|
30
|
+
export interface NumberMarks {
|
|
31
|
+
decimal: string;
|
|
32
|
+
group: string;
|
|
33
|
+
}
|
|
34
|
+
/** The marks a language writes numbers with, in Latin digits: en "." and ",", de "," and ".", fr "," and a narrow space. */
|
|
35
|
+
export declare function numberMarks(locale: string): NumberMarks;
|
|
36
|
+
/** Why a text is not a number, or not yet one. */
|
|
37
|
+
export type NumberProblem =
|
|
38
|
+
/** A letter, an emoji or another symbol: never part of a number. */
|
|
39
|
+
'numbersOnly'
|
|
40
|
+
/** A minus that is not first. */
|
|
41
|
+
| 'minusFirst'
|
|
42
|
+
/** Two decimal marks. */
|
|
43
|
+
| 'oneDecimalMark'
|
|
44
|
+
/** Grouping marks where groups of three cannot be: "12 34". */
|
|
45
|
+
| 'groupsOfThree'
|
|
46
|
+
/** A tab or a line break: several values, as spreadsheets copy them. */
|
|
47
|
+
| 'severalValues'
|
|
48
|
+
/** Not a whole number yet: "-", ".", "1,". */
|
|
49
|
+
| 'unfinished';
|
|
50
|
+
/** A number read: its value (null for nothing typed), as written plain in the page's way, and how many places and digits it has. */
|
|
51
|
+
export interface NumberReading {
|
|
52
|
+
ok: true;
|
|
53
|
+
value: number | null;
|
|
54
|
+
/** The number with no grouping, in Latin digits and the page's decimal mark: "-1234,5" on a German page. Empty for nothing. */
|
|
55
|
+
plain: string;
|
|
56
|
+
/** Its decimal places as typed: "1.50" has 2. */
|
|
57
|
+
places: number;
|
|
58
|
+
/** Its digits, leading zeros of the whole part left out: what a field's `digits[0]` counts. */
|
|
59
|
+
digits: number;
|
|
60
|
+
/** Its significant digits: past 15, a number is no longer kept exactly. */
|
|
61
|
+
significant: number;
|
|
62
|
+
}
|
|
63
|
+
export type NumberRead = NumberReading | {
|
|
64
|
+
ok: false;
|
|
65
|
+
problem: NumberProblem;
|
|
66
|
+
};
|
|
67
|
+
/** What a box reads besides plain numbers: a trailing per cent sign (% or ٪); and whether its numbers are never grouped. */
|
|
68
|
+
export interface NumberReadOptions {
|
|
69
|
+
percent?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Never grouped, as a coordinate (30.0444) is: its one mark — . , ، or ٫ — is the decimal mark whatever the
|
|
72
|
+
* page's language, so "31,235" is 31.235 and never 31235; a space or a second mark does not read.
|
|
73
|
+
*/
|
|
74
|
+
ungrouped?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Typed or pasted text as a number, in the page's language (`locale`).
|
|
78
|
+
*
|
|
79
|
+
* Digits in Latin, Arabic-Indic, Persian and fullwidth script; one leading
|
|
80
|
+
* minus (also \u2212 U+2212) or plus; spaces, and the marks . , ، ٫ ٬. Which mark
|
|
81
|
+
* is the decimal one:
|
|
82
|
+
* - both . and , : the last; the other groups;
|
|
83
|
+
* - one kind repeated: it groups;
|
|
84
|
+
* - one mark once: the page's decimal mark, ٫ or ، is decimal; the page's
|
|
85
|
+
* grouping mark groups only with exactly three digits after it and one to
|
|
86
|
+
* three before; a mark the page does not use is decimal;
|
|
87
|
+
* - spaces and ٬ only group.
|
|
88
|
+
* Groups run one to three digits, then threes, and never come after the
|
|
89
|
+
* decimal mark, and the first group is never led by a 0. So on en and ar
|
|
90
|
+
* pages 1,500 is 1500 and 1,5 is 1.5; on a de page 1.500 is 1500 and 1.5 is
|
|
91
|
+
* 1.5; anywhere 0,500 and 0.500 are a half, 1 234,56 is 1234.56, and 12 34
|
|
92
|
+
* does not read. Nothing reads letters, a tab or a line break.
|
|
93
|
+
*/
|
|
94
|
+
export declare function readNumber(text: string, locale: string, options?: NumberReadOptions): NumberRead;
|
|
95
|
+
/** What a field takes, for judging a keystroke or a paste. */
|
|
96
|
+
export interface NumberLimits {
|
|
97
|
+
/** A whole number: no decimal mark. */
|
|
98
|
+
integer?: boolean;
|
|
99
|
+
/** At most these decimal places. */
|
|
100
|
+
places?: number;
|
|
101
|
+
/** At most these digits in all (a field's `digits[0]`); never more than 15 are kept exactly. */
|
|
102
|
+
digits?: number;
|
|
103
|
+
/** The least: a minus is refused when it is 0 or more. */
|
|
104
|
+
min?: number;
|
|
105
|
+
/** A per cent box: a trailing % or ٪ may be typed. */
|
|
106
|
+
percent?: boolean;
|
|
107
|
+
/** An hours box: `:` and `h` may be typed too ("6:30", "6h30"). */
|
|
108
|
+
duration?: boolean;
|
|
109
|
+
/** Never grouped, as a coordinate: its one mark is the decimal mark (see NumberReadOptions). */
|
|
110
|
+
ungrouped?: boolean;
|
|
111
|
+
}
|
|
112
|
+
/** Why a keystroke or a paste is refused, with what the words name. */
|
|
113
|
+
export type NumberRefusal = {
|
|
114
|
+
problem: 'numbersOnly' | 'minusFirst' | 'oneDecimalMark' | 'groupsOfThree' | 'severalValues' | 'integer';
|
|
115
|
+
} | {
|
|
116
|
+
problem: 'min';
|
|
117
|
+
min: number;
|
|
118
|
+
} | {
|
|
119
|
+
problem: 'decimals';
|
|
120
|
+
places: number;
|
|
121
|
+
} | {
|
|
122
|
+
problem: 'digits';
|
|
123
|
+
n: number;
|
|
124
|
+
};
|
|
125
|
+
/** The most significant digits a number keeps exactly. */
|
|
126
|
+
export declare const MOST_DIGITS = 15;
|
|
127
|
+
/**
|
|
128
|
+
* Whether the text a box would hold after a keystroke may stand: null when it
|
|
129
|
+
* may, or why not. Only what no more typing can make right is refused, so
|
|
130
|
+
* every way of writing a number the field takes can be typed key by key:
|
|
131
|
+
* letters, emoji and other symbols; a minus that is not first, or any minus
|
|
132
|
+
* where the least is 0 or more; a decimal mark that can only be one followed
|
|
133
|
+
* by a digit other than 0 in a whole number, or by more places than the
|
|
134
|
+
* field's (trailing zeros are no places: 12.50 has one, 12.0 none); a second
|
|
135
|
+
* decimal mark; a digit past `digits` or past 15 significant ones; and
|
|
136
|
+
* grouping that can never be right ("1.2." on a German page). Text on its way
|
|
137
|
+
* to a number ("-", "1,", "12 3", "1.234" on its way to "1.234,56") may stand;
|
|
138
|
+
* what it turns out to be, and min and max, are said as the box is left.
|
|
139
|
+
*/
|
|
140
|
+
export declare function couldBeNumber(text: string, locale: string, limits?: NumberLimits): NumberRefusal | null;
|
|
141
|
+
/**
|
|
142
|
+
* Why a number read cannot be held by a field of these limits, or null: a
|
|
143
|
+
* decimal in a whole number, places past the field's, digits past its own or
|
|
144
|
+
* past 15. Not its least and most, which check says. For text a box is left
|
|
145
|
+
* with: as it was typed, "12.345" in a box of two places could not be told
|
|
146
|
+
* from "12.345,67" on its way.
|
|
147
|
+
*/
|
|
148
|
+
export declare function numberMisfit(value: number, limits: NumberLimits): NumberRefusal | null;
|
|
149
|
+
/** A pasted or dropped amount, cleaned: the plain number for the box, or why nothing is pasted. */
|
|
150
|
+
export type PastedNumber = {
|
|
151
|
+
ok: true;
|
|
152
|
+
text: string;
|
|
153
|
+
value: number;
|
|
154
|
+
} | {
|
|
155
|
+
ok: false;
|
|
156
|
+
problem: 'notANumber' | 'severalValues';
|
|
157
|
+
} | {
|
|
158
|
+
ok: false;
|
|
159
|
+
problem: 'otherCurrency';
|
|
160
|
+
currency: string;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Pasted (or dropped) text as the plain number a box takes, in the page's
|
|
164
|
+
* way: direction marks, the box's own currency (its symbol, narrow symbol,
|
|
165
|
+
* code or Arabic symbol), grouping, % and spaces taken out, and an
|
|
166
|
+
* accounting negative read — (1,200.00) and 1,200- are -1200. Another
|
|
167
|
+
* currency is named; a tab or a line break inside is several values; a
|
|
168
|
+
* single line break at the end, as a copied cell brings, is let go.
|
|
169
|
+
*/
|
|
170
|
+
export declare function cleanPastedNumber(text: string, locale: string, options?: {
|
|
171
|
+
currency?: string | null;
|
|
172
|
+
percent?: boolean;
|
|
173
|
+
ungrouped?: boolean;
|
|
174
|
+
}): PastedNumber;
|
|
175
|
+
/** Why typed hours do not read. */
|
|
176
|
+
export type DurationProblem = 'unfinished' | 'minutes' | 'duration' | 'numbersOnly' | 'minusFirst' | 'severalValues';
|
|
177
|
+
export type DurationRead = {
|
|
178
|
+
ok: true;
|
|
179
|
+
value: number | null;
|
|
180
|
+
} | {
|
|
181
|
+
ok: false;
|
|
182
|
+
problem: DurationProblem;
|
|
183
|
+
}
|
|
184
|
+
/** Minutes of one digit that could be more than one time ("6:3", 6:03 or 6:30): never one of them in silence. */
|
|
185
|
+
| {
|
|
186
|
+
ok: false;
|
|
187
|
+
problem: 'minuteDigits';
|
|
188
|
+
times: string[];
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Typed hours: "6:30", "06:30", "6.5" (or "6,5"), "6h30", "6h", "6:30:00"
|
|
192
|
+
* (seconds only when :00), Arabic digits too; a leading minus. Minutes past 59
|
|
193
|
+
* do not read ('minutes'), nor do "6 30" or other shapes ('duration'); "6:"
|
|
194
|
+
* and "-" are on their way ('unfinished'). Minutes of one digit that could be
|
|
195
|
+
* more than one ("6:3": 6:03 or 6:30) are never read as one ('minuteDigits',
|
|
196
|
+
* naming each); "6:7" can only be 6:07.
|
|
197
|
+
*/
|
|
198
|
+
export declare function readDuration(text: string, locale: string): DurationRead;
|
|
199
|
+
/** The order a page types a date's day, month and year in. */
|
|
200
|
+
export type DateOrder = 'dmy' | 'mdy' | 'ymd';
|
|
201
|
+
export type DateProblem = 'unfinished' | 'noSuchMonth' | 'yearDigits' | 'time';
|
|
202
|
+
export type DateRead =
|
|
203
|
+
/** Read; `timeLeftOut`, the time (HH:MM, here) an instant had, where a day alone is kept: said, never dropped in silence. */
|
|
204
|
+
{
|
|
205
|
+
ok: true;
|
|
206
|
+
value: string | null;
|
|
207
|
+
timeLeftOut?: string;
|
|
208
|
+
} | {
|
|
209
|
+
ok: false;
|
|
210
|
+
problem: DateProblem;
|
|
211
|
+
}
|
|
212
|
+
/** A time whose minutes have one digit that could be more than one time ("14:3"): each named. */
|
|
213
|
+
| {
|
|
214
|
+
ok: false;
|
|
215
|
+
problem: 'minuteDigits';
|
|
216
|
+
times: string[];
|
|
217
|
+
} | {
|
|
218
|
+
ok: false;
|
|
219
|
+
problem: 'noSuchDay';
|
|
220
|
+
year: number;
|
|
221
|
+
month: number;
|
|
222
|
+
days: number;
|
|
223
|
+
}
|
|
224
|
+
/** A year of two digits ("85"): never given a century in silence; the two it could be are named. */
|
|
225
|
+
| {
|
|
226
|
+
ok: false;
|
|
227
|
+
problem: 'shortYear';
|
|
228
|
+
short: string;
|
|
229
|
+
early: number;
|
|
230
|
+
late: number;
|
|
231
|
+
};
|
|
232
|
+
/** Whether `word` is how a month's name begins, in any of the languages its names are read in: typing it is on its way. */
|
|
233
|
+
export declare function couldBeMonth(word: string, locale?: string): boolean;
|
|
234
|
+
/**
|
|
235
|
+
* A typed date, in the page's order (`order`, day/month/year unless told):
|
|
236
|
+
* separators / . - or a space; ISO yyyy-mm-dd always; Arabic and Persian
|
|
237
|
+
* digits; a year of four digits, from 1000 — one of two digits could be either
|
|
238
|
+
* century, so it is never read as one ('shortYear', naming both). Its month
|
|
239
|
+
* may be a word, as Fieldia writes a date at rest — "15 Oct 2026", "15
|
|
240
|
+
* أكتوبر 2026", "15 oct. 2026", "15. Okt. 2026", "Oct 15, 2026" — in
|
|
241
|
+
* English, Arabic, French, German or the page's language (`locale`); the
|
|
242
|
+
* numbers beside a month in words are its day and its year of four digits,
|
|
243
|
+
* in either order. With `time`, a time may follow ("13/10/2026 14:30", "…,
|
|
244
|
+
* 2:30 pm", "… ٢:٣٠ م"), and the value is yyyy-mm-ddTHH:MM. An instant with
|
|
245
|
+
* its zone (2026-10-15T14:30:00Z) is the local day and time it is — with
|
|
246
|
+
* `time`, its seconds :00, never dropped. Unfinished or impossible dates say
|
|
247
|
+
* why (31/02 → 'noSuchDay' with the days that month has).
|
|
248
|
+
*/
|
|
249
|
+
export declare function readDate(text: string, options?: {
|
|
250
|
+
order?: DateOrder;
|
|
251
|
+
time?: boolean;
|
|
252
|
+
locale?: string;
|
|
253
|
+
}): DateRead;
|
|
254
|
+
export type TimeRead = {
|
|
255
|
+
ok: true;
|
|
256
|
+
value: string | null;
|
|
257
|
+
} | {
|
|
258
|
+
ok: false;
|
|
259
|
+
problem: 'unfinished' | 'time';
|
|
260
|
+
} | {
|
|
261
|
+
ok: false;
|
|
262
|
+
problem: 'minuteDigits';
|
|
263
|
+
times: string[];
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* A typed time of day: 24-hour "14:30" (or "14.30", "14h30", "1430"), or
|
|
267
|
+
* twelve-hour with am/pm or ص/م; Arabic digits; seconds only when :00.
|
|
268
|
+
* The value is HH:MM. Minutes of one digit are read as written only when they
|
|
269
|
+
* can be one time alone ("14:7" is 14:07, "14:0" 14:00); "14:3" could be
|
|
270
|
+
* 14:03 or 14:30, and "14.5" 14:05, half past two or 14:50: those are never
|
|
271
|
+
* read, and each time it could be is named ('minuteDigits').
|
|
272
|
+
*/
|
|
273
|
+
export declare function readTime(text: string): TimeRead;
|
|
274
|
+
/** The places a currency's amounts are written with: 3 for the Kuwaiti, Bahraini, Omani and Jordanian dinars and rials, 2 for most. */
|
|
275
|
+
export declare function placesOfCurrency(currency: string | null | undefined): number;
|
|
276
|
+
/** The decimal places a number has as JavaScript writes it: 12.345 has 3, 1e-7 has 7. */
|
|
277
|
+
export declare function placesOf(value: number): number;
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How Fieldia reads what a person types or pastes into a box: one set of
|
|
3
|
+
* readers for every box — a form's fields, a table's cells, a list's filters,
|
|
4
|
+
* the designer's settings — so a number, a duration, a date or a word is read
|
|
5
|
+
* the same way wherever it is typed. Pure: no DOM, no form.
|
|
6
|
+
*
|
|
7
|
+
* People in Egypt and the Gulf type in Arabic too: Arabic-Indic digits
|
|
8
|
+
* (٠١٢…), Persian ones (۰۱۲…), the Arabic decimal separator (٫) and its
|
|
9
|
+
* thousands separator (٬), and a French or German decimal comma are read,
|
|
10
|
+
* never refused. Invisible direction marks, which Arabic text carries and
|
|
11
|
+
* copying brings along, are never part of what is read.
|
|
12
|
+
*/
|
|
13
|
+
/** Invisible direction marks taken out: everywhere (what is structured), or only at the ends (any one line of text). */
|
|
14
|
+
export declare function stripMarks(text: string, where?: 'all' | 'ends'): string;
|
|
15
|
+
/** Arabic-Indic (٠-٩), Persian (۰-۹) and fullwidth (0-9) digits as 0-9; every other character as it is. */
|
|
16
|
+
export declare function foldDigits(text: string): string;
|
|
17
|
+
/** Line breaks as spaces, as one line of text keeps them; a password drops them instead. */
|
|
18
|
+
export declare function oneLine(text: string, options?: {
|
|
19
|
+
password?: boolean;
|
|
20
|
+
}): string;
|
|
21
|
+
/** How many characters a text has, as a server counts them: by code point, so an emoji is one. */
|
|
22
|
+
export declare function charCount(text: string): number;
|
|
23
|
+
/**
|
|
24
|
+
* Words folded for finding: case, Arabic letter forms (أ إ آ ٱ as ا, ة as ه,
|
|
25
|
+
* ى as ي, the tatweel and short vowels dropped), digits in any script as 0-9,
|
|
26
|
+
* and no direction marks — so "أحمد" finds "احمد" and "١٢" finds "12".
|
|
27
|
+
*/
|
|
28
|
+
export declare function foldForSearch(text: string): string;
|
|
29
|
+
/** A page's own marks for numbers: its decimal mark and its grouping mark. */
|
|
30
|
+
export interface NumberMarks {
|
|
31
|
+
decimal: string;
|
|
32
|
+
group: string;
|
|
33
|
+
}
|
|
34
|
+
/** The marks a language writes numbers with, in Latin digits: en "." and ",", de "," and ".", fr "," and a narrow space. */
|
|
35
|
+
export declare function numberMarks(locale: string): NumberMarks;
|
|
36
|
+
/** Why a text is not a number, or not yet one. */
|
|
37
|
+
export type NumberProblem =
|
|
38
|
+
/** A letter, an emoji or another symbol: never part of a number. */
|
|
39
|
+
'numbersOnly'
|
|
40
|
+
/** A minus that is not first. */
|
|
41
|
+
| 'minusFirst'
|
|
42
|
+
/** Two decimal marks. */
|
|
43
|
+
| 'oneDecimalMark'
|
|
44
|
+
/** Grouping marks where groups of three cannot be: "12 34". */
|
|
45
|
+
| 'groupsOfThree'
|
|
46
|
+
/** A tab or a line break: several values, as spreadsheets copy them. */
|
|
47
|
+
| 'severalValues'
|
|
48
|
+
/** Not a whole number yet: "-", ".", "1,". */
|
|
49
|
+
| 'unfinished';
|
|
50
|
+
/** A number read: its value (null for nothing typed), as written plain in the page's way, and how many places and digits it has. */
|
|
51
|
+
export interface NumberReading {
|
|
52
|
+
ok: true;
|
|
53
|
+
value: number | null;
|
|
54
|
+
/** The number with no grouping, in Latin digits and the page's decimal mark: "-1234,5" on a German page. Empty for nothing. */
|
|
55
|
+
plain: string;
|
|
56
|
+
/** Its decimal places as typed: "1.50" has 2. */
|
|
57
|
+
places: number;
|
|
58
|
+
/** Its digits, leading zeros of the whole part left out: what a field's `digits[0]` counts. */
|
|
59
|
+
digits: number;
|
|
60
|
+
/** Its significant digits: past 15, a number is no longer kept exactly. */
|
|
61
|
+
significant: number;
|
|
62
|
+
}
|
|
63
|
+
export type NumberRead = NumberReading | {
|
|
64
|
+
ok: false;
|
|
65
|
+
problem: NumberProblem;
|
|
66
|
+
};
|
|
67
|
+
/** What a box reads besides plain numbers: a trailing per cent sign (% or ٪); and whether its numbers are never grouped. */
|
|
68
|
+
export interface NumberReadOptions {
|
|
69
|
+
percent?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Never grouped, as a coordinate (30.0444) is: its one mark — . , ، or ٫ — is the decimal mark whatever the
|
|
72
|
+
* page's language, so "31,235" is 31.235 and never 31235; a space or a second mark does not read.
|
|
73
|
+
*/
|
|
74
|
+
ungrouped?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Typed or pasted text as a number, in the page's language (`locale`).
|
|
78
|
+
*
|
|
79
|
+
* Digits in Latin, Arabic-Indic, Persian and fullwidth script; one leading
|
|
80
|
+
* minus (also \u2212 U+2212) or plus; spaces, and the marks . , ، ٫ ٬. Which mark
|
|
81
|
+
* is the decimal one:
|
|
82
|
+
* - both . and , : the last; the other groups;
|
|
83
|
+
* - one kind repeated: it groups;
|
|
84
|
+
* - one mark once: the page's decimal mark, ٫ or ، is decimal; the page's
|
|
85
|
+
* grouping mark groups only with exactly three digits after it and one to
|
|
86
|
+
* three before; a mark the page does not use is decimal;
|
|
87
|
+
* - spaces and ٬ only group.
|
|
88
|
+
* Groups run one to three digits, then threes, and never come after the
|
|
89
|
+
* decimal mark, and the first group is never led by a 0. So on en and ar
|
|
90
|
+
* pages 1,500 is 1500 and 1,5 is 1.5; on a de page 1.500 is 1500 and 1.5 is
|
|
91
|
+
* 1.5; anywhere 0,500 and 0.500 are a half, 1 234,56 is 1234.56, and 12 34
|
|
92
|
+
* does not read. Nothing reads letters, a tab or a line break.
|
|
93
|
+
*/
|
|
94
|
+
export declare function readNumber(text: string, locale: string, options?: NumberReadOptions): NumberRead;
|
|
95
|
+
/** What a field takes, for judging a keystroke or a paste. */
|
|
96
|
+
export interface NumberLimits {
|
|
97
|
+
/** A whole number: no decimal mark. */
|
|
98
|
+
integer?: boolean;
|
|
99
|
+
/** At most these decimal places. */
|
|
100
|
+
places?: number;
|
|
101
|
+
/** At most these digits in all (a field's `digits[0]`); never more than 15 are kept exactly. */
|
|
102
|
+
digits?: number;
|
|
103
|
+
/** The least: a minus is refused when it is 0 or more. */
|
|
104
|
+
min?: number;
|
|
105
|
+
/** A per cent box: a trailing % or ٪ may be typed. */
|
|
106
|
+
percent?: boolean;
|
|
107
|
+
/** An hours box: `:` and `h` may be typed too ("6:30", "6h30"). */
|
|
108
|
+
duration?: boolean;
|
|
109
|
+
/** Never grouped, as a coordinate: its one mark is the decimal mark (see NumberReadOptions). */
|
|
110
|
+
ungrouped?: boolean;
|
|
111
|
+
}
|
|
112
|
+
/** Why a keystroke or a paste is refused, with what the words name. */
|
|
113
|
+
export type NumberRefusal = {
|
|
114
|
+
problem: 'numbersOnly' | 'minusFirst' | 'oneDecimalMark' | 'groupsOfThree' | 'severalValues' | 'integer';
|
|
115
|
+
} | {
|
|
116
|
+
problem: 'min';
|
|
117
|
+
min: number;
|
|
118
|
+
} | {
|
|
119
|
+
problem: 'decimals';
|
|
120
|
+
places: number;
|
|
121
|
+
} | {
|
|
122
|
+
problem: 'digits';
|
|
123
|
+
n: number;
|
|
124
|
+
};
|
|
125
|
+
/** The most significant digits a number keeps exactly. */
|
|
126
|
+
export declare const MOST_DIGITS = 15;
|
|
127
|
+
/**
|
|
128
|
+
* Whether the text a box would hold after a keystroke may stand: null when it
|
|
129
|
+
* may, or why not. Only what no more typing can make right is refused, so
|
|
130
|
+
* every way of writing a number the field takes can be typed key by key:
|
|
131
|
+
* letters, emoji and other symbols; a minus that is not first, or any minus
|
|
132
|
+
* where the least is 0 or more; a decimal mark that can only be one followed
|
|
133
|
+
* by a digit other than 0 in a whole number, or by more places than the
|
|
134
|
+
* field's (trailing zeros are no places: 12.50 has one, 12.0 none); a second
|
|
135
|
+
* decimal mark; a digit past `digits` or past 15 significant ones; and
|
|
136
|
+
* grouping that can never be right ("1.2." on a German page). Text on its way
|
|
137
|
+
* to a number ("-", "1,", "12 3", "1.234" on its way to "1.234,56") may stand;
|
|
138
|
+
* what it turns out to be, and min and max, are said as the box is left.
|
|
139
|
+
*/
|
|
140
|
+
export declare function couldBeNumber(text: string, locale: string, limits?: NumberLimits): NumberRefusal | null;
|
|
141
|
+
/**
|
|
142
|
+
* Why a number read cannot be held by a field of these limits, or null: a
|
|
143
|
+
* decimal in a whole number, places past the field's, digits past its own or
|
|
144
|
+
* past 15. Not its least and most, which check says. For text a box is left
|
|
145
|
+
* with: as it was typed, "12.345" in a box of two places could not be told
|
|
146
|
+
* from "12.345,67" on its way.
|
|
147
|
+
*/
|
|
148
|
+
export declare function numberMisfit(value: number, limits: NumberLimits): NumberRefusal | null;
|
|
149
|
+
/** A pasted or dropped amount, cleaned: the plain number for the box, or why nothing is pasted. */
|
|
150
|
+
export type PastedNumber = {
|
|
151
|
+
ok: true;
|
|
152
|
+
text: string;
|
|
153
|
+
value: number;
|
|
154
|
+
} | {
|
|
155
|
+
ok: false;
|
|
156
|
+
problem: 'notANumber' | 'severalValues';
|
|
157
|
+
} | {
|
|
158
|
+
ok: false;
|
|
159
|
+
problem: 'otherCurrency';
|
|
160
|
+
currency: string;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Pasted (or dropped) text as the plain number a box takes, in the page's
|
|
164
|
+
* way: direction marks, the box's own currency (its symbol, narrow symbol,
|
|
165
|
+
* code or Arabic symbol), grouping, % and spaces taken out, and an
|
|
166
|
+
* accounting negative read — (1,200.00) and 1,200- are -1200. Another
|
|
167
|
+
* currency is named; a tab or a line break inside is several values; a
|
|
168
|
+
* single line break at the end, as a copied cell brings, is let go.
|
|
169
|
+
*/
|
|
170
|
+
export declare function cleanPastedNumber(text: string, locale: string, options?: {
|
|
171
|
+
currency?: string | null;
|
|
172
|
+
percent?: boolean;
|
|
173
|
+
ungrouped?: boolean;
|
|
174
|
+
}): PastedNumber;
|
|
175
|
+
/** Why typed hours do not read. */
|
|
176
|
+
export type DurationProblem = 'unfinished' | 'minutes' | 'duration' | 'numbersOnly' | 'minusFirst' | 'severalValues';
|
|
177
|
+
export type DurationRead = {
|
|
178
|
+
ok: true;
|
|
179
|
+
value: number | null;
|
|
180
|
+
} | {
|
|
181
|
+
ok: false;
|
|
182
|
+
problem: DurationProblem;
|
|
183
|
+
}
|
|
184
|
+
/** Minutes of one digit that could be more than one time ("6:3", 6:03 or 6:30): never one of them in silence. */
|
|
185
|
+
| {
|
|
186
|
+
ok: false;
|
|
187
|
+
problem: 'minuteDigits';
|
|
188
|
+
times: string[];
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Typed hours: "6:30", "06:30", "6.5" (or "6,5"), "6h30", "6h", "6:30:00"
|
|
192
|
+
* (seconds only when :00), Arabic digits too; a leading minus. Minutes past 59
|
|
193
|
+
* do not read ('minutes'), nor do "6 30" or other shapes ('duration'); "6:"
|
|
194
|
+
* and "-" are on their way ('unfinished'). Minutes of one digit that could be
|
|
195
|
+
* more than one ("6:3": 6:03 or 6:30) are never read as one ('minuteDigits',
|
|
196
|
+
* naming each); "6:7" can only be 6:07.
|
|
197
|
+
*/
|
|
198
|
+
export declare function readDuration(text: string, locale: string): DurationRead;
|
|
199
|
+
/** The order a page types a date's day, month and year in. */
|
|
200
|
+
export type DateOrder = 'dmy' | 'mdy' | 'ymd';
|
|
201
|
+
export type DateProblem = 'unfinished' | 'noSuchMonth' | 'yearDigits' | 'time';
|
|
202
|
+
export type DateRead =
|
|
203
|
+
/** Read; `timeLeftOut`, the time (HH:MM, here) an instant had, where a day alone is kept: said, never dropped in silence. */
|
|
204
|
+
{
|
|
205
|
+
ok: true;
|
|
206
|
+
value: string | null;
|
|
207
|
+
timeLeftOut?: string;
|
|
208
|
+
} | {
|
|
209
|
+
ok: false;
|
|
210
|
+
problem: DateProblem;
|
|
211
|
+
}
|
|
212
|
+
/** A time whose minutes have one digit that could be more than one time ("14:3"): each named. */
|
|
213
|
+
| {
|
|
214
|
+
ok: false;
|
|
215
|
+
problem: 'minuteDigits';
|
|
216
|
+
times: string[];
|
|
217
|
+
} | {
|
|
218
|
+
ok: false;
|
|
219
|
+
problem: 'noSuchDay';
|
|
220
|
+
year: number;
|
|
221
|
+
month: number;
|
|
222
|
+
days: number;
|
|
223
|
+
}
|
|
224
|
+
/** A year of two digits ("85"): never given a century in silence; the two it could be are named. */
|
|
225
|
+
| {
|
|
226
|
+
ok: false;
|
|
227
|
+
problem: 'shortYear';
|
|
228
|
+
short: string;
|
|
229
|
+
early: number;
|
|
230
|
+
late: number;
|
|
231
|
+
};
|
|
232
|
+
/** Whether `word` is how a month's name begins, in any of the languages its names are read in: typing it is on its way. */
|
|
233
|
+
export declare function couldBeMonth(word: string, locale?: string): boolean;
|
|
234
|
+
/**
|
|
235
|
+
* A typed date, in the page's order (`order`, day/month/year unless told):
|
|
236
|
+
* separators / . - or a space; ISO yyyy-mm-dd always; Arabic and Persian
|
|
237
|
+
* digits; a year of four digits, from 1000 — one of two digits could be either
|
|
238
|
+
* century, so it is never read as one ('shortYear', naming both). Its month
|
|
239
|
+
* may be a word, as Fieldia writes a date at rest — "15 Oct 2026", "15
|
|
240
|
+
* أكتوبر 2026", "15 oct. 2026", "15. Okt. 2026", "Oct 15, 2026" — in
|
|
241
|
+
* English, Arabic, French, German or the page's language (`locale`); the
|
|
242
|
+
* numbers beside a month in words are its day and its year of four digits,
|
|
243
|
+
* in either order. With `time`, a time may follow ("13/10/2026 14:30", "…,
|
|
244
|
+
* 2:30 pm", "… ٢:٣٠ م"), and the value is yyyy-mm-ddTHH:MM. An instant with
|
|
245
|
+
* its zone (2026-10-15T14:30:00Z) is the local day and time it is — with
|
|
246
|
+
* `time`, its seconds :00, never dropped. Unfinished or impossible dates say
|
|
247
|
+
* why (31/02 → 'noSuchDay' with the days that month has).
|
|
248
|
+
*/
|
|
249
|
+
export declare function readDate(text: string, options?: {
|
|
250
|
+
order?: DateOrder;
|
|
251
|
+
time?: boolean;
|
|
252
|
+
locale?: string;
|
|
253
|
+
}): DateRead;
|
|
254
|
+
export type TimeRead = {
|
|
255
|
+
ok: true;
|
|
256
|
+
value: string | null;
|
|
257
|
+
} | {
|
|
258
|
+
ok: false;
|
|
259
|
+
problem: 'unfinished' | 'time';
|
|
260
|
+
} | {
|
|
261
|
+
ok: false;
|
|
262
|
+
problem: 'minuteDigits';
|
|
263
|
+
times: string[];
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* A typed time of day: 24-hour "14:30" (or "14.30", "14h30", "1430"), or
|
|
267
|
+
* twelve-hour with am/pm or ص/م; Arabic digits; seconds only when :00.
|
|
268
|
+
* The value is HH:MM. Minutes of one digit are read as written only when they
|
|
269
|
+
* can be one time alone ("14:7" is 14:07, "14:0" 14:00); "14:3" could be
|
|
270
|
+
* 14:03 or 14:30, and "14.5" 14:05, half past two or 14:50: those are never
|
|
271
|
+
* read, and each time it could be is named ('minuteDigits').
|
|
272
|
+
*/
|
|
273
|
+
export declare function readTime(text: string): TimeRead;
|
|
274
|
+
/** The places a currency's amounts are written with: 3 for the Kuwaiti, Bahraini, Omani and Jordanian dinars and rials, 2 for most. */
|
|
275
|
+
export declare function placesOfCurrency(currency: string | null | undefined): number;
|
|
276
|
+
/** The decimal places a number has as JavaScript writes it: 12.345 has 3, 1e-7 has 7. */
|
|
277
|
+
export declare function placesOf(value: number): number;
|