@fieldia/core 0.9.2 → 0.10.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 +1128 -89
- package/src/lib/expression/evaluator.d.mts +6 -5
- package/src/lib/expression/evaluator.d.ts +6 -5
- package/src/lib/expression/evaluator.js +37 -22
- package/src/lib/expression/evaluator.js.map +1 -1
- package/src/lib/expression/evaluator.mjs +32 -18
- package/src/lib/expression/evaluator.mjs.map +1 -1
- package/src/lib/expression/expression.d.mts +21 -0
- package/src/lib/expression/expression.d.ts +21 -0
- package/src/lib/expression/expression.js +29 -0
- package/src/lib/expression/expression.js.map +1 -0
- package/src/lib/expression/expression.mjs +26 -0
- package/src/lib/expression/expression.mjs.map +1 -0
- package/src/lib/expression/extractFieldNames.js +6 -1
- package/src/lib/expression/extractFieldNames.js.map +1 -1
- package/src/lib/expression/extractFieldNames.mjs +6 -1
- package/src/lib/expression/extractFieldNames.mjs.map +1 -1
- package/src/lib/expression/functions.d.mts +35 -0
- package/src/lib/expression/functions.d.ts +35 -0
- package/src/lib/expression/functions.js +129 -0
- package/src/lib/expression/functions.js.map +1 -0
- package/src/lib/expression/functions.mjs +124 -0
- package/src/lib/expression/functions.mjs.map +1 -0
- package/src/lib/expression/modifier.d.mts +3 -1
- package/src/lib/expression/modifier.d.ts +3 -1
- package/src/lib/expression/modifier.js +4 -27
- package/src/lib/expression/modifier.js.map +1 -1
- package/src/lib/expression/modifier.mjs +3 -26
- package/src/lib/expression/modifier.mjs.map +1 -1
- package/src/lib/expression/operations.d.mts +25 -0
- package/src/lib/expression/operations.d.ts +25 -0
- package/src/lib/expression/operations.js +81 -0
- package/src/lib/expression/operations.js.map +1 -0
- package/src/lib/expression/operations.mjs +72 -0
- package/src/lib/expression/operations.mjs.map +1 -0
- package/src/lib/expression/order.d.mts +11 -0
- package/src/lib/expression/order.d.ts +11 -0
- package/src/lib/expression/order.js +36 -0
- package/src/lib/expression/order.js.map +1 -0
- package/src/lib/expression/order.mjs +33 -0
- package/src/lib/expression/order.mjs.map +1 -0
- package/src/lib/expression/parser.d.mts +34 -4
- package/src/lib/expression/parser.d.ts +34 -4
- package/src/lib/expression/parser.js +72 -6
- package/src/lib/expression/parser.js.map +1 -1
- package/src/lib/expression/parser.mjs +72 -6
- package/src/lib/expression/parser.mjs.map +1 -1
- package/src/lib/expression/reads.d.mts +8 -0
- package/src/lib/expression/reads.d.ts +8 -0
- package/src/lib/expression/reads.js +48 -0
- package/src/lib/expression/reads.js.map +1 -0
- package/src/lib/expression/reads.mjs +44 -0
- package/src/lib/expression/reads.mjs.map +1 -0
- package/src/lib/expression/tokenizer.d.mts +7 -6
- package/src/lib/expression/tokenizer.d.ts +7 -6
- package/src/lib/expression/tokenizer.js +28 -18
- package/src/lib/expression/tokenizer.js.map +1 -1
- package/src/lib/expression/tokenizer.mjs +28 -18
- package/src/lib/expression/tokenizer.mjs.map +1 -1
- package/src/lib/format/field.d.mts +686 -5
- package/src/lib/format/field.d.ts +686 -5
- package/src/lib/format/field.js +115 -13
- package/src/lib/format/field.js.map +1 -1
- package/src/lib/format/field.mjs +114 -12
- package/src/lib/format/field.mjs.map +1 -1
- package/src/lib/format/layout.d.mts +388 -10
- package/src/lib/format/layout.d.ts +388 -10
- package/src/lib/format/layout.js +50 -3
- package/src/lib/format/layout.js.map +1 -1
- package/src/lib/format/layout.mjs +49 -2
- package/src/lib/format/layout.mjs.map +1 -1
- package/src/lib/format/names.d.mts +1 -1
- package/src/lib/format/names.d.ts +1 -1
- package/src/lib/format/names.js +1 -0
- package/src/lib/format/names.js.map +1 -1
- package/src/lib/format/names.mjs +1 -0
- package/src/lib/format/names.mjs.map +1 -1
- package/src/lib/format/page.d.mts +391 -4
- package/src/lib/format/page.d.ts +391 -4
- package/src/lib/format/page.js +13 -0
- package/src/lib/format/page.js.map +1 -1
- package/src/lib/format/page.mjs +13 -0
- package/src/lib/format/page.mjs.map +1 -1
- package/src/lib/format/references.d.mts +14 -1
- package/src/lib/format/references.d.ts +14 -1
- package/src/lib/format/references.js +96 -8
- package/src/lib/format/references.js.map +1 -1
- package/src/lib/format/references.mjs +96 -8
- package/src/lib/format/references.mjs.map +1 -1
- package/src/lib/format/translate.d.mts +20 -0
- package/src/lib/format/translate.d.ts +20 -0
- package/src/lib/format/translate.js +79 -21
- package/src/lib/format/translate.js.map +1 -1
- package/src/lib/format/translate.mjs +76 -21
- package/src/lib/format/translate.mjs.map +1 -1
- package/src/lib/record/check.d.mts +19 -1
- package/src/lib/record/check.d.ts +19 -1
- package/src/lib/record/check.js +84 -21
- package/src/lib/record/check.js.map +1 -1
- package/src/lib/record/check.mjs +82 -21
- package/src/lib/record/check.mjs.map +1 -1
- package/src/lib/record/compute.d.mts +24 -0
- package/src/lib/record/compute.d.ts +24 -0
- package/src/lib/record/compute.js +107 -0
- package/src/lib/record/compute.js.map +1 -0
- package/src/lib/record/compute.mjs +103 -0
- package/src/lib/record/compute.mjs.map +1 -0
- package/src/lib/record/data-source.d.mts +9 -1
- package/src/lib/record/data-source.d.ts +9 -1
- package/src/lib/record/data-source.js.map +1 -1
- package/src/lib/record/data-source.mjs.map +1 -1
- package/src/lib/record/env.d.mts +9 -0
- package/src/lib/record/env.d.ts +9 -0
- package/src/lib/record/env.js +28 -0
- package/src/lib/record/env.js.map +1 -0
- package/src/lib/record/env.mjs +25 -0
- package/src/lib/record/env.mjs.map +1 -0
- package/src/lib/record/form.d.mts +24 -0
- package/src/lib/record/form.d.ts +24 -0
- package/src/lib/record/form.js +160 -32
- package/src/lib/record/form.js.map +1 -1
- package/src/lib/record/form.mjs +160 -32
- package/src/lib/record/form.mjs.map +1 -1
- package/src/lib/record/inputs.d.mts +5 -0
- package/src/lib/record/inputs.d.ts +5 -0
- package/src/lib/record/inputs.js +47 -0
- package/src/lib/record/inputs.js.map +1 -0
- package/src/lib/record/inputs.mjs +44 -0
- package/src/lib/record/inputs.mjs.map +1 -0
- package/src/lib/record/limits.d.mts +13 -0
- package/src/lib/record/limits.d.ts +13 -0
- package/src/lib/record/limits.js +45 -0
- package/src/lib/record/limits.js.map +1 -0
- package/src/lib/record/limits.mjs +41 -0
- package/src/lib/record/limits.mjs.map +1 -0
- package/src/lib/record/locales/all.d.mts +7 -0
- package/src/lib/record/locales/all.d.ts +7 -0
- package/src/lib/record/locales/all.js +13 -0
- package/src/lib/record/locales/all.js.map +1 -0
- package/src/lib/record/locales/all.mjs +10 -0
- package/src/lib/record/locales/all.mjs.map +1 -0
- package/src/lib/record/locales/ar.d.mts +3 -0
- package/src/lib/record/locales/ar.d.ts +3 -0
- package/src/lib/record/locales/ar.js +55 -0
- package/src/lib/record/locales/ar.js.map +1 -0
- package/src/lib/record/locales/ar.mjs +52 -0
- package/src/lib/record/locales/ar.mjs.map +1 -0
- package/src/lib/record/locales/de.d.mts +3 -0
- package/src/lib/record/locales/de.d.ts +3 -0
- package/src/lib/record/locales/de.js +55 -0
- package/src/lib/record/locales/de.js.map +1 -0
- package/src/lib/record/locales/de.mjs +52 -0
- package/src/lib/record/locales/de.mjs.map +1 -0
- package/src/lib/record/locales/fr.d.mts +3 -0
- package/src/lib/record/locales/fr.d.ts +3 -0
- package/src/lib/record/locales/fr.js +55 -0
- package/src/lib/record/locales/fr.js.map +1 -0
- package/src/lib/record/locales/fr.mjs +52 -0
- package/src/lib/record/locales/fr.mjs.map +1 -0
- package/src/lib/record/memory-data-source.d.mts +3 -0
- package/src/lib/record/memory-data-source.d.ts +3 -0
- package/src/lib/record/memory-data-source.js +8 -0
- package/src/lib/record/memory-data-source.js.map +1 -1
- package/src/lib/record/memory-data-source.mjs +8 -0
- package/src/lib/record/memory-data-source.mjs.map +1 -1
- package/src/lib/record/messages.d.mts +46 -0
- package/src/lib/record/messages.d.ts +46 -0
- package/src/lib/record/messages.js +58 -101
- package/src/lib/record/messages.js.map +1 -1
- package/src/lib/record/messages.mjs +58 -101
- package/src/lib/record/messages.mjs.map +1 -1
- package/src/lib/record/rules.d.mts +33 -0
- package/src/lib/record/rules.d.ts +33 -0
- package/src/lib/record/rules.js +83 -0
- package/src/lib/record/rules.js.map +1 -0
- package/src/lib/record/rules.mjs +79 -0
- package/src/lib/record/rules.mjs.map +1 -0
- package/src/lib/record/score.d.mts +16 -0
- package/src/lib/record/score.d.ts +16 -0
- package/src/lib/record/score.js +35 -0
- package/src/lib/record/score.js.map +1 -0
- package/src/lib/record/score.mjs +32 -0
- package/src/lib/record/score.mjs.map +1 -0
- package/src/lib/record/set-when.d.mts +24 -0
- package/src/lib/record/set-when.d.ts +24 -0
- package/src/lib/record/set-when.js +68 -0
- package/src/lib/record/set-when.js.map +1 -0
- package/src/lib/record/set-when.mjs +65 -0
- package/src/lib/record/set-when.mjs.map +1 -0
- package/src/lib/record/structures.d.mts +14 -0
- package/src/lib/record/structures.d.ts +14 -0
- package/src/lib/record/structures.js +32 -0
- package/src/lib/record/structures.js.map +1 -0
- package/src/lib/record/structures.mjs +28 -0
- package/src/lib/record/structures.mjs.map +1 -0
- package/src/lib/record/values.d.mts +10 -5
- package/src/lib/record/values.d.ts +10 -5
- package/src/lib/record/values.js +20 -6
- package/src/lib/record/values.js.map +1 -1
- package/src/lib/record/values.mjs +19 -6
- package/src/lib/record/values.mjs.map +1 -1
- package/src/runtime.d.mts +10 -7
- package/src/runtime.d.ts +10 -7
- package/src/runtime.js +12 -1
- package/src/runtime.js.map +1 -1
- package/src/runtime.mjs +5 -2
- package/src/runtime.mjs.map +1 -1
|
@@ -2,108 +2,65 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MESSAGES = void 0;
|
|
4
4
|
exports.fill = fill;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
de: {
|
|
57
|
-
required: '{label} ist erforderlich',
|
|
58
|
-
maxLength: 'Maximal {max} Zeichen erlaubt',
|
|
59
|
-
pattern: '{label} hat nicht das erwartete Format',
|
|
60
|
-
text: '{label} muss Text sein',
|
|
61
|
-
number: '{label} muss eine Zahl sein',
|
|
62
|
-
integer: '{label} muss eine ganze Zahl sein',
|
|
63
|
-
min: '{label} muss mindestens {min} sein',
|
|
64
|
-
max: '{label} darf höchstens {max} sein',
|
|
65
|
-
decimals: 'Maximal {digits} Nachkommastellen erlaubt',
|
|
66
|
-
boolean: '{label} muss ja oder nein sein',
|
|
67
|
-
dateFormat: 'Ungültiges Datumsformat (erwartet JJJJ-MM-TT)',
|
|
68
|
-
dateInvalid: 'Ungültiges Datum (Monat und Tag prüfen)',
|
|
69
|
-
datetimeFormat: 'Ungültiges Datums- und Zeitformat (erwartet JJJJ-MM-TTTHH:MM:SS)',
|
|
70
|
-
datetimeInvalid: 'Ungültiges Datum oder ungültige Uhrzeit',
|
|
71
|
-
choice: 'Muss eines davon sein: {options}',
|
|
72
|
-
choices: '{label} muss eine Liste von Optionen sein',
|
|
73
|
-
record: '{label} muss ein Datensatz sein',
|
|
74
|
-
records: '{label} muss eine Liste von Datensätzen sein',
|
|
75
|
-
reference: '{label} muss auf {models} verweisen',
|
|
76
|
-
file: '{label} muss eine Datei sein',
|
|
77
|
-
fileSize: '{label} ist größer als {size}',
|
|
78
|
-
fileType: '{label} muss eine {types}-Datei sein',
|
|
79
|
-
or: 'oder',
|
|
80
|
-
},
|
|
81
|
-
fr: {
|
|
82
|
-
required: '{label} est obligatoire',
|
|
83
|
-
maxLength: '{max} caractères au maximum',
|
|
84
|
-
pattern: "{label} n'a pas le format attendu",
|
|
85
|
-
text: '{label} doit être du texte',
|
|
86
|
-
number: '{label} doit être un nombre',
|
|
87
|
-
integer: '{label} doit être un nombre entier',
|
|
88
|
-
min: '{label} doit être au moins {min}',
|
|
89
|
-
max: '{label} doit être au plus {max}',
|
|
90
|
-
decimals: '{digits} décimales au maximum',
|
|
91
|
-
boolean: '{label} doit être oui ou non',
|
|
92
|
-
dateFormat: 'Format de date invalide (attendu AAAA-MM-JJ)',
|
|
93
|
-
dateInvalid: 'Date invalide (vérifiez le mois et le jour)',
|
|
94
|
-
datetimeFormat: 'Format de date et heure invalide (attendu AAAA-MM-JJTHH:MM:SS)',
|
|
95
|
-
datetimeInvalid: 'Date ou heure invalide',
|
|
96
|
-
choice: 'Doit être parmi : {options}',
|
|
97
|
-
choices: '{label} doit être une liste de choix',
|
|
98
|
-
record: '{label} doit être un enregistrement',
|
|
99
|
-
records: "{label} doit être une liste d'enregistrements",
|
|
100
|
-
reference: '{label} doit pointer vers {models}',
|
|
101
|
-
file: '{label} doit être un fichier',
|
|
102
|
-
fileSize: '{label} dépasse {size}',
|
|
103
|
-
fileType: '{label} doit être un fichier {types}',
|
|
104
|
-
or: 'ou',
|
|
105
|
-
},
|
|
5
|
+
const all_1 = require("./locales/all");
|
|
6
|
+
/** English: always here, and the words a language leaves out. */
|
|
7
|
+
const en = {
|
|
8
|
+
required: '{label} is required',
|
|
9
|
+
maxLength: 'Maximum {max} characters allowed',
|
|
10
|
+
pattern: '{label} is not in the expected format',
|
|
11
|
+
text: '{label} must be text',
|
|
12
|
+
number: '{label} must be a number',
|
|
13
|
+
integer: '{label} must be a whole number',
|
|
14
|
+
min: '{label} must be at least {min}',
|
|
15
|
+
max: '{label} must be at most {max}',
|
|
16
|
+
decimals: 'Maximum {digits} decimal places allowed',
|
|
17
|
+
boolean: '{label} must be yes or no',
|
|
18
|
+
dateFormat: 'Invalid date format (expected YYYY-MM-DD)',
|
|
19
|
+
dateInvalid: 'Invalid date (check month/day values)',
|
|
20
|
+
datetimeFormat: 'Invalid date and time format (expected YYYY-MM-DDTHH:MM:SS)',
|
|
21
|
+
datetimeInvalid: 'Invalid date and time (check the values)',
|
|
22
|
+
choice: 'Must be one of: {options}',
|
|
23
|
+
choiceOrOther: 'Must be one of: {options}, or an answer of its own',
|
|
24
|
+
matrix: '{label} takes an answer for each row',
|
|
25
|
+
matrixRow: 'Rows are: {rows}',
|
|
26
|
+
matrixRows: 'Answer every row of {label}',
|
|
27
|
+
choices: '{label} must be a list of choices',
|
|
28
|
+
record: '{label} must be a record',
|
|
29
|
+
records: '{label} must be a list of records',
|
|
30
|
+
reference: '{label} must point to {aModels}',
|
|
31
|
+
file: '{label} must be a file',
|
|
32
|
+
fileSize: '{label} is larger than {size}',
|
|
33
|
+
fileType: '{label} must be {aTypes} file',
|
|
34
|
+
minFiles: 'Add at least {min} files to {label}',
|
|
35
|
+
maxFiles: 'Too many files for {label}: at most {max}',
|
|
36
|
+
minLength: '{label} must be at least {min} characters',
|
|
37
|
+
endsWith: '{label} must end with {ending}',
|
|
38
|
+
atLeast: 'Choose at least {min} for {label}',
|
|
39
|
+
atMost: 'Choose at most {max} for {label}',
|
|
40
|
+
datePast: '{label} must be in the past',
|
|
41
|
+
dateFuture: '{label} must be in the future',
|
|
42
|
+
holds: '{label} does not agree with the other answers',
|
|
43
|
+
or: 'or',
|
|
44
|
+
tick: 'Tick this box to go on',
|
|
45
|
+
email: 'Enter an email address, like name@example.com',
|
|
46
|
+
url: 'Enter a web address, like example.com',
|
|
47
|
+
phone: 'Enter a phone number, like +20 100 123 4567',
|
|
48
|
+
time: 'Enter a time, like 14:30',
|
|
49
|
+
before: '{label} can’t be before {min}',
|
|
50
|
+
after: '{label} can’t be after {max}',
|
|
51
|
+
weekday: '{label} can’t be on a {days}',
|
|
52
|
+
minLines: 'Add at least {min} to {label}',
|
|
53
|
+
maxLines: 'Too many in {label}: at most {max}',
|
|
54
|
+
addressParts: 'Street address|Address line 2|City|State or region|Postcode|Country',
|
|
55
|
+
locale: 'en',
|
|
106
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* The messages in every language Fieldia has. This package holds all four;
|
|
59
|
+
* the one-tag script holds English alone, and a page adds another language
|
|
60
|
+
* with that language's script (fieldia.ar.js, …), through the viewer's
|
|
61
|
+
* `addLanguage`.
|
|
62
|
+
*/
|
|
63
|
+
exports.MESSAGES = { en, ...all_1.LANGUAGES };
|
|
107
64
|
/** Fill `{name}` placeholders. */
|
|
108
65
|
function fill(template, values) {
|
|
109
66
|
return template.replace(/\{(\w+)\}/g, (match, name) => (name in values ? String(values[name]) : match));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/messages.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/messages.ts"],"names":[],"mappings":";;;AAyIA,oBAEC;AA3ID,uCAA0C;AA4E1C,iEAAiE;AACjE,MAAM,EAAE,GAAa;IACnB,QAAQ,EAAE,qBAAqB;IAC/B,SAAS,EAAE,kCAAkC;IAC7C,OAAO,EAAE,uCAAuC;IAChD,IAAI,EAAE,sBAAsB;IAC5B,MAAM,EAAE,0BAA0B;IAClC,OAAO,EAAE,gCAAgC;IACzC,GAAG,EAAE,gCAAgC;IACrC,GAAG,EAAE,+BAA+B;IACpC,QAAQ,EAAE,yCAAyC;IACnD,OAAO,EAAE,2BAA2B;IACpC,UAAU,EAAE,2CAA2C;IACvD,WAAW,EAAE,uCAAuC;IACpD,cAAc,EAAE,6DAA6D;IAC7E,eAAe,EAAE,0CAA0C;IAC3D,MAAM,EAAE,2BAA2B;IACnC,aAAa,EAAE,oDAAoD;IACnE,MAAM,EAAE,sCAAsC;IAC9C,SAAS,EAAE,kBAAkB;IAC7B,UAAU,EAAE,6BAA6B;IACzC,OAAO,EAAE,mCAAmC;IAC5C,MAAM,EAAE,0BAA0B;IAClC,OAAO,EAAE,mCAAmC;IAC5C,SAAS,EAAE,iCAAiC;IAC5C,IAAI,EAAE,wBAAwB;IAC9B,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE,qCAAqC;IAC/C,QAAQ,EAAE,2CAA2C;IACrD,SAAS,EAAE,2CAA2C;IACtD,QAAQ,EAAE,gCAAgC;IAC1C,OAAO,EAAE,mCAAmC;IAC5C,MAAM,EAAE,kCAAkC;IAC1C,QAAQ,EAAE,6BAA6B;IACvC,UAAU,EAAE,+BAA+B;IAC3C,KAAK,EAAE,+CAA+C;IACtD,EAAE,EAAE,IAAI;IACR,IAAI,EAAE,wBAAwB;IAC9B,KAAK,EAAE,+CAA+C;IACtD,GAAG,EAAE,uCAAuC;IAC5C,KAAK,EAAE,6CAA6C;IACpD,IAAI,EAAE,0BAA0B;IAChC,MAAM,EAAE,+BAA+B;IACvC,KAAK,EAAE,8BAA8B;IACrC,OAAO,EAAE,8BAA8B;IACvC,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE,oCAAoC;IAC9C,YAAY,EAAE,qEAAqE;IACnF,MAAM,EAAE,IAAI;CACb,CAAC;AAEF;;;;;GAKG;AACU,QAAA,QAAQ,GAA6B,EAAE,EAAE,EAAE,GAAG,eAAS,EAAE,CAAC;AAEvE,kCAAkC;AAClC,SAAgB,IAAI,CAAC,QAAgB,EAAE,MAAuC;IAC5E,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAClH,CAAC"}
|
|
@@ -1,105 +1,62 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
de: {
|
|
53
|
-
required: '{label} ist erforderlich',
|
|
54
|
-
maxLength: 'Maximal {max} Zeichen erlaubt',
|
|
55
|
-
pattern: '{label} hat nicht das erwartete Format',
|
|
56
|
-
text: '{label} muss Text sein',
|
|
57
|
-
number: '{label} muss eine Zahl sein',
|
|
58
|
-
integer: '{label} muss eine ganze Zahl sein',
|
|
59
|
-
min: '{label} muss mindestens {min} sein',
|
|
60
|
-
max: '{label} darf höchstens {max} sein',
|
|
61
|
-
decimals: 'Maximal {digits} Nachkommastellen erlaubt',
|
|
62
|
-
boolean: '{label} muss ja oder nein sein',
|
|
63
|
-
dateFormat: 'Ungültiges Datumsformat (erwartet JJJJ-MM-TT)',
|
|
64
|
-
dateInvalid: 'Ungültiges Datum (Monat und Tag prüfen)',
|
|
65
|
-
datetimeFormat: 'Ungültiges Datums- und Zeitformat (erwartet JJJJ-MM-TTTHH:MM:SS)',
|
|
66
|
-
datetimeInvalid: 'Ungültiges Datum oder ungültige Uhrzeit',
|
|
67
|
-
choice: 'Muss eines davon sein: {options}',
|
|
68
|
-
choices: '{label} muss eine Liste von Optionen sein',
|
|
69
|
-
record: '{label} muss ein Datensatz sein',
|
|
70
|
-
records: '{label} muss eine Liste von Datensätzen sein',
|
|
71
|
-
reference: '{label} muss auf {models} verweisen',
|
|
72
|
-
file: '{label} muss eine Datei sein',
|
|
73
|
-
fileSize: '{label} ist größer als {size}',
|
|
74
|
-
fileType: '{label} muss eine {types}-Datei sein',
|
|
75
|
-
or: 'oder',
|
|
76
|
-
},
|
|
77
|
-
fr: {
|
|
78
|
-
required: '{label} est obligatoire',
|
|
79
|
-
maxLength: '{max} caractères au maximum',
|
|
80
|
-
pattern: "{label} n'a pas le format attendu",
|
|
81
|
-
text: '{label} doit être du texte',
|
|
82
|
-
number: '{label} doit être un nombre',
|
|
83
|
-
integer: '{label} doit être un nombre entier',
|
|
84
|
-
min: '{label} doit être au moins {min}',
|
|
85
|
-
max: '{label} doit être au plus {max}',
|
|
86
|
-
decimals: '{digits} décimales au maximum',
|
|
87
|
-
boolean: '{label} doit être oui ou non',
|
|
88
|
-
dateFormat: 'Format de date invalide (attendu AAAA-MM-JJ)',
|
|
89
|
-
dateInvalid: 'Date invalide (vérifiez le mois et le jour)',
|
|
90
|
-
datetimeFormat: 'Format de date et heure invalide (attendu AAAA-MM-JJTHH:MM:SS)',
|
|
91
|
-
datetimeInvalid: 'Date ou heure invalide',
|
|
92
|
-
choice: 'Doit être parmi : {options}',
|
|
93
|
-
choices: '{label} doit être une liste de choix',
|
|
94
|
-
record: '{label} doit être un enregistrement',
|
|
95
|
-
records: "{label} doit être une liste d'enregistrements",
|
|
96
|
-
reference: '{label} doit pointer vers {models}',
|
|
97
|
-
file: '{label} doit être un fichier',
|
|
98
|
-
fileSize: '{label} dépasse {size}',
|
|
99
|
-
fileType: '{label} doit être un fichier {types}',
|
|
100
|
-
or: 'ou',
|
|
101
|
-
},
|
|
1
|
+
import { LANGUAGES } from './locales/all.mjs';
|
|
2
|
+
/** English: always here, and the words a language leaves out. */
|
|
3
|
+
const en = {
|
|
4
|
+
required: '{label} is required',
|
|
5
|
+
maxLength: 'Maximum {max} characters allowed',
|
|
6
|
+
pattern: '{label} is not in the expected format',
|
|
7
|
+
text: '{label} must be text',
|
|
8
|
+
number: '{label} must be a number',
|
|
9
|
+
integer: '{label} must be a whole number',
|
|
10
|
+
min: '{label} must be at least {min}',
|
|
11
|
+
max: '{label} must be at most {max}',
|
|
12
|
+
decimals: 'Maximum {digits} decimal places allowed',
|
|
13
|
+
boolean: '{label} must be yes or no',
|
|
14
|
+
dateFormat: 'Invalid date format (expected YYYY-MM-DD)',
|
|
15
|
+
dateInvalid: 'Invalid date (check month/day values)',
|
|
16
|
+
datetimeFormat: 'Invalid date and time format (expected YYYY-MM-DDTHH:MM:SS)',
|
|
17
|
+
datetimeInvalid: 'Invalid date and time (check the values)',
|
|
18
|
+
choice: 'Must be one of: {options}',
|
|
19
|
+
choiceOrOther: 'Must be one of: {options}, or an answer of its own',
|
|
20
|
+
matrix: '{label} takes an answer for each row',
|
|
21
|
+
matrixRow: 'Rows are: {rows}',
|
|
22
|
+
matrixRows: 'Answer every row of {label}',
|
|
23
|
+
choices: '{label} must be a list of choices',
|
|
24
|
+
record: '{label} must be a record',
|
|
25
|
+
records: '{label} must be a list of records',
|
|
26
|
+
reference: '{label} must point to {aModels}',
|
|
27
|
+
file: '{label} must be a file',
|
|
28
|
+
fileSize: '{label} is larger than {size}',
|
|
29
|
+
fileType: '{label} must be {aTypes} file',
|
|
30
|
+
minFiles: 'Add at least {min} files to {label}',
|
|
31
|
+
maxFiles: 'Too many files for {label}: at most {max}',
|
|
32
|
+
minLength: '{label} must be at least {min} characters',
|
|
33
|
+
endsWith: '{label} must end with {ending}',
|
|
34
|
+
atLeast: 'Choose at least {min} for {label}',
|
|
35
|
+
atMost: 'Choose at most {max} for {label}',
|
|
36
|
+
datePast: '{label} must be in the past',
|
|
37
|
+
dateFuture: '{label} must be in the future',
|
|
38
|
+
holds: '{label} does not agree with the other answers',
|
|
39
|
+
or: 'or',
|
|
40
|
+
tick: 'Tick this box to go on',
|
|
41
|
+
email: 'Enter an email address, like name@example.com',
|
|
42
|
+
url: 'Enter a web address, like example.com',
|
|
43
|
+
phone: 'Enter a phone number, like +20 100 123 4567',
|
|
44
|
+
time: 'Enter a time, like 14:30',
|
|
45
|
+
before: '{label} can’t be before {min}',
|
|
46
|
+
after: '{label} can’t be after {max}',
|
|
47
|
+
weekday: '{label} can’t be on a {days}',
|
|
48
|
+
minLines: 'Add at least {min} to {label}',
|
|
49
|
+
maxLines: 'Too many in {label}: at most {max}',
|
|
50
|
+
addressParts: 'Street address|Address line 2|City|State or region|Postcode|Country',
|
|
51
|
+
locale: 'en',
|
|
102
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* The messages in every language Fieldia has. This package holds all four;
|
|
55
|
+
* the one-tag script holds English alone, and a page adds another language
|
|
56
|
+
* with that language's script (fieldia.ar.js, …), through the viewer's
|
|
57
|
+
* `addLanguage`.
|
|
58
|
+
*/
|
|
59
|
+
export const MESSAGES = { en, ...LANGUAGES };
|
|
103
60
|
/** Fill `{name}` placeholders. */
|
|
104
61
|
export function fill(template, values) {
|
|
105
62
|
return template.replace(/\{(\w+)\}/g, (match, name) => (name in values ? String(values[name]) : match));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/messages.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"messages.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AA4E1C,iEAAiE;AACjE,MAAM,EAAE,GAAa;IACnB,QAAQ,EAAE,qBAAqB;IAC/B,SAAS,EAAE,kCAAkC;IAC7C,OAAO,EAAE,uCAAuC;IAChD,IAAI,EAAE,sBAAsB;IAC5B,MAAM,EAAE,0BAA0B;IAClC,OAAO,EAAE,gCAAgC;IACzC,GAAG,EAAE,gCAAgC;IACrC,GAAG,EAAE,+BAA+B;IACpC,QAAQ,EAAE,yCAAyC;IACnD,OAAO,EAAE,2BAA2B;IACpC,UAAU,EAAE,2CAA2C;IACvD,WAAW,EAAE,uCAAuC;IACpD,cAAc,EAAE,6DAA6D;IAC7E,eAAe,EAAE,0CAA0C;IAC3D,MAAM,EAAE,2BAA2B;IACnC,aAAa,EAAE,oDAAoD;IACnE,MAAM,EAAE,sCAAsC;IAC9C,SAAS,EAAE,kBAAkB;IAC7B,UAAU,EAAE,6BAA6B;IACzC,OAAO,EAAE,mCAAmC;IAC5C,MAAM,EAAE,0BAA0B;IAClC,OAAO,EAAE,mCAAmC;IAC5C,SAAS,EAAE,iCAAiC;IAC5C,IAAI,EAAE,wBAAwB;IAC9B,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE,qCAAqC;IAC/C,QAAQ,EAAE,2CAA2C;IACrD,SAAS,EAAE,2CAA2C;IACtD,QAAQ,EAAE,gCAAgC;IAC1C,OAAO,EAAE,mCAAmC;IAC5C,MAAM,EAAE,kCAAkC;IAC1C,QAAQ,EAAE,6BAA6B;IACvC,UAAU,EAAE,+BAA+B;IAC3C,KAAK,EAAE,+CAA+C;IACtD,EAAE,EAAE,IAAI;IACR,IAAI,EAAE,wBAAwB;IAC9B,KAAK,EAAE,+CAA+C;IACtD,GAAG,EAAE,uCAAuC;IAC5C,KAAK,EAAE,6CAA6C;IACpD,IAAI,EAAE,0BAA0B;IAChC,MAAM,EAAE,+BAA+B;IACvC,KAAK,EAAE,8BAA8B;IACrC,OAAO,EAAE,8BAA8B;IACvC,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE,oCAAoC;IAC9C,YAAY,EAAE,qEAAqE;IACnF,MAAM,EAAE,IAAI;CACb,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAA6B,EAAE,EAAE,EAAE,GAAG,SAAS,EAAE,CAAC;AAEvE,kCAAkC;AAClC,MAAM,UAAU,IAAI,CAAC,QAAgB,EAAE,MAAuC;IAC5E,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAClH,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Field } from '../format/field.mjs';
|
|
2
|
+
import type { AnswerRule } from '../format/layout.mjs';
|
|
3
|
+
import type { ExpressionEnv } from '../expression/functions.mjs';
|
|
4
|
+
import { type CompiledModifier } from '../expression/modifier.mjs';
|
|
5
|
+
import { type Messages } from './messages.mjs';
|
|
6
|
+
import { type Value } from './values.mjs';
|
|
7
|
+
/**
|
|
8
|
+
* Answer rules: what a field node's `validate` asks of an answer, besides its
|
|
9
|
+
* field's own rules. An empty answer passes every rule (`required` decides
|
|
10
|
+
* whether one is needed), a rule applies only while its `when` holds, and an
|
|
11
|
+
* ask that does not fit the answer — a length of a number — is not broken. A
|
|
12
|
+
* rule across fields (`holds`) waits until every field it reads is filled in.
|
|
13
|
+
*/
|
|
14
|
+
/** A rule read once: its condition and its rule across fields parsed, its pattern made whole. */
|
|
15
|
+
export interface CompiledRule {
|
|
16
|
+
readonly rule: AnswerRule;
|
|
17
|
+
readonly when: CompiledModifier;
|
|
18
|
+
readonly pattern: RegExp | null;
|
|
19
|
+
readonly holds: CompiledModifier | null;
|
|
20
|
+
}
|
|
21
|
+
export declare function compileRules(rules: readonly AnswerRule[] | undefined): CompiledRule[];
|
|
22
|
+
/** What a rule is checked with: the record as expressions read it, the clock, and the words to say. */
|
|
23
|
+
export interface RuleContext {
|
|
24
|
+
context: Record<string, unknown>;
|
|
25
|
+
env: ExpressionEnv;
|
|
26
|
+
now: Date;
|
|
27
|
+
messages: Messages;
|
|
28
|
+
}
|
|
29
|
+
/** The first broken error rule's message and the first broken warning rule's, for one answer. */
|
|
30
|
+
export declare function checkRules(field: Field, label: string, value: Value | undefined, rules: readonly CompiledRule[], at: RuleContext): {
|
|
31
|
+
error?: string;
|
|
32
|
+
warning?: string;
|
|
33
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Field } from '../format/field';
|
|
2
|
+
import type { AnswerRule } from '../format/layout';
|
|
3
|
+
import type { ExpressionEnv } from '../expression/functions';
|
|
4
|
+
import { type CompiledModifier } from '../expression/modifier';
|
|
5
|
+
import { type Messages } from './messages';
|
|
6
|
+
import { type Value } from './values';
|
|
7
|
+
/**
|
|
8
|
+
* Answer rules: what a field node's `validate` asks of an answer, besides its
|
|
9
|
+
* field's own rules. An empty answer passes every rule (`required` decides
|
|
10
|
+
* whether one is needed), a rule applies only while its `when` holds, and an
|
|
11
|
+
* ask that does not fit the answer — a length of a number — is not broken. A
|
|
12
|
+
* rule across fields (`holds`) waits until every field it reads is filled in.
|
|
13
|
+
*/
|
|
14
|
+
/** A rule read once: its condition and its rule across fields parsed, its pattern made whole. */
|
|
15
|
+
export interface CompiledRule {
|
|
16
|
+
readonly rule: AnswerRule;
|
|
17
|
+
readonly when: CompiledModifier;
|
|
18
|
+
readonly pattern: RegExp | null;
|
|
19
|
+
readonly holds: CompiledModifier | null;
|
|
20
|
+
}
|
|
21
|
+
export declare function compileRules(rules: readonly AnswerRule[] | undefined): CompiledRule[];
|
|
22
|
+
/** What a rule is checked with: the record as expressions read it, the clock, and the words to say. */
|
|
23
|
+
export interface RuleContext {
|
|
24
|
+
context: Record<string, unknown>;
|
|
25
|
+
env: ExpressionEnv;
|
|
26
|
+
now: Date;
|
|
27
|
+
messages: Messages;
|
|
28
|
+
}
|
|
29
|
+
/** The first broken error rule's message and the first broken warning rule's, for one answer. */
|
|
30
|
+
export declare function checkRules(field: Field, label: string, value: Value | undefined, rules: readonly CompiledRule[], at: RuleContext): {
|
|
31
|
+
error?: string;
|
|
32
|
+
warning?: string;
|
|
33
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compileRules = compileRules;
|
|
4
|
+
exports.checkRules = checkRules;
|
|
5
|
+
const functions_1 = require("../expression/functions");
|
|
6
|
+
const modifier_1 = require("../expression/modifier");
|
|
7
|
+
const operations_1 = require("../expression/operations");
|
|
8
|
+
const messages_1 = require("./messages");
|
|
9
|
+
const values_1 = require("./values");
|
|
10
|
+
function compileRules(rules) {
|
|
11
|
+
return (rules ?? []).map((rule) => ({
|
|
12
|
+
rule,
|
|
13
|
+
when: (0, modifier_1.compileModifier)(rule.when ?? true),
|
|
14
|
+
// A pattern is about the whole answer, not a part of it.
|
|
15
|
+
pattern: rule.pattern === undefined ? null : new RegExp(`^(?:${rule.pattern})$`),
|
|
16
|
+
holds: rule.holds === undefined ? null : (0, modifier_1.compileModifier)(rule.holds),
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
/** The first broken error rule's message and the first broken warning rule's, for one answer. */
|
|
20
|
+
function checkRules(field, label, value, rules, at) {
|
|
21
|
+
const found = {};
|
|
22
|
+
if (!rules.length || (0, values_1.isEmpty)(field, value))
|
|
23
|
+
return found;
|
|
24
|
+
for (const compiled of rules) {
|
|
25
|
+
const level = compiled.rule.level ?? 'error';
|
|
26
|
+
if (found[level] !== undefined || !compiled.when.evaluate(at.context, at.env))
|
|
27
|
+
continue;
|
|
28
|
+
const broken = brokenAsk(compiled, field, value, at.now) ?? brokenAcross(compiled, at);
|
|
29
|
+
if (broken)
|
|
30
|
+
found[level] = compiled.rule.message ?? (0, messages_1.fill)(at.messages[broken.say], { label, ...broken.values });
|
|
31
|
+
}
|
|
32
|
+
return found;
|
|
33
|
+
}
|
|
34
|
+
/** The first thing a rule asks that the answer does not keep, in the order a rule lists them. */
|
|
35
|
+
function brokenAsk({ rule, pattern }, field, value, now) {
|
|
36
|
+
const text = typeof value === 'string' ? value : null;
|
|
37
|
+
if (text !== null && rule.minLength !== undefined && text.length < rule.minLength)
|
|
38
|
+
return { say: 'minLength', values: { min: rule.minLength } };
|
|
39
|
+
if (text !== null && rule.maxLength !== undefined && text.length > rule.maxLength)
|
|
40
|
+
return { say: 'maxLength', values: { max: rule.maxLength } };
|
|
41
|
+
if (pattern && (text !== null || (0, operations_1.isNumber)(value)) && !pattern.test(String(value)))
|
|
42
|
+
return { say: 'pattern' };
|
|
43
|
+
if (text !== null && rule.endsWith !== undefined && !text.trim().toLowerCase().endsWith(rule.endsWith.toLowerCase())) {
|
|
44
|
+
return { say: 'endsWith', values: { ending: rule.endsWith } };
|
|
45
|
+
}
|
|
46
|
+
if ((0, operations_1.isNumber)(value) && rule.min !== undefined && value < rule.min)
|
|
47
|
+
return { say: 'min', values: { min: rule.min } };
|
|
48
|
+
if ((0, operations_1.isNumber)(value) && rule.max !== undefined && value > rule.max)
|
|
49
|
+
return { say: 'max', values: { max: rule.max } };
|
|
50
|
+
const count = Array.isArray(value) ? value.length : null;
|
|
51
|
+
if (count !== null && rule.atLeast !== undefined && count < rule.atLeast)
|
|
52
|
+
return { say: 'atLeast', values: { min: rule.atLeast } };
|
|
53
|
+
if (count !== null && rule.atMost !== undefined && count > rule.atMost)
|
|
54
|
+
return { say: 'atMost', values: { max: rule.atMost } };
|
|
55
|
+
if (text !== null && rule.date !== undefined) {
|
|
56
|
+
const side = whenIs(field, text, now);
|
|
57
|
+
if (rule.date === 'past' && side >= 0)
|
|
58
|
+
return { say: 'datePast' };
|
|
59
|
+
if (rule.date === 'future' && side <= 0)
|
|
60
|
+
return { say: 'dateFuture' };
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
/** Nothing to compare with yet: an empty value, as expressions read it. */
|
|
65
|
+
const blank = (value) => value === null || value === undefined || (typeof value === 'string' && !value.trim()) || (Array.isArray(value) && !value.length);
|
|
66
|
+
/** A rule across fields, once every field it reads is filled in: broken when it does not hold. */
|
|
67
|
+
function brokenAcross({ holds }, at) {
|
|
68
|
+
if (!holds || holds.fields.some((name) => blank(at.context[name])))
|
|
69
|
+
return undefined;
|
|
70
|
+
return holds.evaluate(at.context, at.env) ? undefined : { say: 'holds' };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Whether an answer is before (-1) or after (1) now, or is now (0): a day
|
|
74
|
+
* against today, a date and time against the clock itself. A date and time
|
|
75
|
+
* that cannot be read is neither (NaN): the field's own rules name it.
|
|
76
|
+
*/
|
|
77
|
+
function whenIs(field, text, now) {
|
|
78
|
+
if (field.type === 'datetime')
|
|
79
|
+
return Math.sign(Date.parse(text) - now.getTime());
|
|
80
|
+
const today = (0, functions_1.localDay)(now);
|
|
81
|
+
return text < today ? -1 : text > today ? 1 : 0;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { localDay } from '../expression/functions.mjs';
|
|
2
|
+
import { compileModifier } from '../expression/modifier.mjs';
|
|
3
|
+
import { isNumber } from '../expression/operations.mjs';
|
|
4
|
+
import { fill } from './messages.mjs';
|
|
5
|
+
import { isEmpty } from './values.mjs';
|
|
6
|
+
export function compileRules(rules) {
|
|
7
|
+
return (rules ?? []).map((rule) => ({
|
|
8
|
+
rule,
|
|
9
|
+
when: compileModifier(rule.when ?? true),
|
|
10
|
+
// A pattern is about the whole answer, not a part of it.
|
|
11
|
+
pattern: rule.pattern === undefined ? null : new RegExp(`^(?:${rule.pattern})$`),
|
|
12
|
+
holds: rule.holds === undefined ? null : compileModifier(rule.holds),
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
/** The first broken error rule's message and the first broken warning rule's, for one answer. */
|
|
16
|
+
export function checkRules(field, label, value, rules, at) {
|
|
17
|
+
const found = {};
|
|
18
|
+
if (!rules.length || isEmpty(field, value))
|
|
19
|
+
return found;
|
|
20
|
+
for (const compiled of rules) {
|
|
21
|
+
const level = compiled.rule.level ?? 'error';
|
|
22
|
+
if (found[level] !== undefined || !compiled.when.evaluate(at.context, at.env))
|
|
23
|
+
continue;
|
|
24
|
+
const broken = brokenAsk(compiled, field, value, at.now) ?? brokenAcross(compiled, at);
|
|
25
|
+
if (broken)
|
|
26
|
+
found[level] = compiled.rule.message ?? fill(at.messages[broken.say], { label, ...broken.values });
|
|
27
|
+
}
|
|
28
|
+
return found;
|
|
29
|
+
}
|
|
30
|
+
/** The first thing a rule asks that the answer does not keep, in the order a rule lists them. */
|
|
31
|
+
function brokenAsk({ rule, pattern }, field, value, now) {
|
|
32
|
+
const text = typeof value === 'string' ? value : null;
|
|
33
|
+
if (text !== null && rule.minLength !== undefined && text.length < rule.minLength)
|
|
34
|
+
return { say: 'minLength', values: { min: rule.minLength } };
|
|
35
|
+
if (text !== null && rule.maxLength !== undefined && text.length > rule.maxLength)
|
|
36
|
+
return { say: 'maxLength', values: { max: rule.maxLength } };
|
|
37
|
+
if (pattern && (text !== null || isNumber(value)) && !pattern.test(String(value)))
|
|
38
|
+
return { say: 'pattern' };
|
|
39
|
+
if (text !== null && rule.endsWith !== undefined && !text.trim().toLowerCase().endsWith(rule.endsWith.toLowerCase())) {
|
|
40
|
+
return { say: 'endsWith', values: { ending: rule.endsWith } };
|
|
41
|
+
}
|
|
42
|
+
if (isNumber(value) && rule.min !== undefined && value < rule.min)
|
|
43
|
+
return { say: 'min', values: { min: rule.min } };
|
|
44
|
+
if (isNumber(value) && rule.max !== undefined && value > rule.max)
|
|
45
|
+
return { say: 'max', values: { max: rule.max } };
|
|
46
|
+
const count = Array.isArray(value) ? value.length : null;
|
|
47
|
+
if (count !== null && rule.atLeast !== undefined && count < rule.atLeast)
|
|
48
|
+
return { say: 'atLeast', values: { min: rule.atLeast } };
|
|
49
|
+
if (count !== null && rule.atMost !== undefined && count > rule.atMost)
|
|
50
|
+
return { say: 'atMost', values: { max: rule.atMost } };
|
|
51
|
+
if (text !== null && rule.date !== undefined) {
|
|
52
|
+
const side = whenIs(field, text, now);
|
|
53
|
+
if (rule.date === 'past' && side >= 0)
|
|
54
|
+
return { say: 'datePast' };
|
|
55
|
+
if (rule.date === 'future' && side <= 0)
|
|
56
|
+
return { say: 'dateFuture' };
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
/** Nothing to compare with yet: an empty value, as expressions read it. */
|
|
61
|
+
const blank = (value) => value === null || value === undefined || (typeof value === 'string' && !value.trim()) || (Array.isArray(value) && !value.length);
|
|
62
|
+
/** A rule across fields, once every field it reads is filled in: broken when it does not hold. */
|
|
63
|
+
function brokenAcross({ holds }, at) {
|
|
64
|
+
if (!holds || holds.fields.some((name) => blank(at.context[name])))
|
|
65
|
+
return undefined;
|
|
66
|
+
return holds.evaluate(at.context, at.env) ? undefined : { say: 'holds' };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Whether an answer is before (-1) or after (1) now, or is now (0): a day
|
|
70
|
+
* against today, a date and time against the clock itself. A date and time
|
|
71
|
+
* that cannot be read is neither (NaN): the field's own rules name it.
|
|
72
|
+
*/
|
|
73
|
+
function whenIs(field, text, now) {
|
|
74
|
+
if (field.type === 'datetime')
|
|
75
|
+
return Math.sign(Date.parse(text) - now.getTime());
|
|
76
|
+
const today = localDay(now);
|
|
77
|
+
return text < today ? -1 : text > today ? 1 : 0;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=rules.mjs.map
|