@fieldia/core 0.9.1 → 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.
Files changed (208) hide show
  1. package/package.json +1 -1
  2. package/schema/page.schema.json +1128 -89
  3. package/src/lib/expression/evaluator.d.mts +6 -5
  4. package/src/lib/expression/evaluator.d.ts +6 -5
  5. package/src/lib/expression/evaluator.js +37 -22
  6. package/src/lib/expression/evaluator.js.map +1 -1
  7. package/src/lib/expression/evaluator.mjs +32 -18
  8. package/src/lib/expression/evaluator.mjs.map +1 -1
  9. package/src/lib/expression/expression.d.mts +21 -0
  10. package/src/lib/expression/expression.d.ts +21 -0
  11. package/src/lib/expression/expression.js +29 -0
  12. package/src/lib/expression/expression.js.map +1 -0
  13. package/src/lib/expression/expression.mjs +26 -0
  14. package/src/lib/expression/expression.mjs.map +1 -0
  15. package/src/lib/expression/extractFieldNames.js +6 -1
  16. package/src/lib/expression/extractFieldNames.js.map +1 -1
  17. package/src/lib/expression/extractFieldNames.mjs +6 -1
  18. package/src/lib/expression/extractFieldNames.mjs.map +1 -1
  19. package/src/lib/expression/functions.d.mts +35 -0
  20. package/src/lib/expression/functions.d.ts +35 -0
  21. package/src/lib/expression/functions.js +129 -0
  22. package/src/lib/expression/functions.js.map +1 -0
  23. package/src/lib/expression/functions.mjs +124 -0
  24. package/src/lib/expression/functions.mjs.map +1 -0
  25. package/src/lib/expression/modifier.d.mts +3 -1
  26. package/src/lib/expression/modifier.d.ts +3 -1
  27. package/src/lib/expression/modifier.js +4 -27
  28. package/src/lib/expression/modifier.js.map +1 -1
  29. package/src/lib/expression/modifier.mjs +3 -26
  30. package/src/lib/expression/modifier.mjs.map +1 -1
  31. package/src/lib/expression/operations.d.mts +25 -0
  32. package/src/lib/expression/operations.d.ts +25 -0
  33. package/src/lib/expression/operations.js +81 -0
  34. package/src/lib/expression/operations.js.map +1 -0
  35. package/src/lib/expression/operations.mjs +72 -0
  36. package/src/lib/expression/operations.mjs.map +1 -0
  37. package/src/lib/expression/order.d.mts +11 -0
  38. package/src/lib/expression/order.d.ts +11 -0
  39. package/src/lib/expression/order.js +36 -0
  40. package/src/lib/expression/order.js.map +1 -0
  41. package/src/lib/expression/order.mjs +33 -0
  42. package/src/lib/expression/order.mjs.map +1 -0
  43. package/src/lib/expression/parser.d.mts +34 -4
  44. package/src/lib/expression/parser.d.ts +34 -4
  45. package/src/lib/expression/parser.js +72 -6
  46. package/src/lib/expression/parser.js.map +1 -1
  47. package/src/lib/expression/parser.mjs +72 -6
  48. package/src/lib/expression/parser.mjs.map +1 -1
  49. package/src/lib/expression/reads.d.mts +8 -0
  50. package/src/lib/expression/reads.d.ts +8 -0
  51. package/src/lib/expression/reads.js +48 -0
  52. package/src/lib/expression/reads.js.map +1 -0
  53. package/src/lib/expression/reads.mjs +44 -0
  54. package/src/lib/expression/reads.mjs.map +1 -0
  55. package/src/lib/expression/tokenizer.d.mts +7 -6
  56. package/src/lib/expression/tokenizer.d.ts +7 -6
  57. package/src/lib/expression/tokenizer.js +28 -18
  58. package/src/lib/expression/tokenizer.js.map +1 -1
  59. package/src/lib/expression/tokenizer.mjs +28 -18
  60. package/src/lib/expression/tokenizer.mjs.map +1 -1
  61. package/src/lib/format/field.d.mts +686 -5
  62. package/src/lib/format/field.d.ts +686 -5
  63. package/src/lib/format/field.js +115 -13
  64. package/src/lib/format/field.js.map +1 -1
  65. package/src/lib/format/field.mjs +114 -12
  66. package/src/lib/format/field.mjs.map +1 -1
  67. package/src/lib/format/layout.d.mts +388 -10
  68. package/src/lib/format/layout.d.ts +388 -10
  69. package/src/lib/format/layout.js +50 -3
  70. package/src/lib/format/layout.js.map +1 -1
  71. package/src/lib/format/layout.mjs +49 -2
  72. package/src/lib/format/layout.mjs.map +1 -1
  73. package/src/lib/format/names.d.mts +1 -1
  74. package/src/lib/format/names.d.ts +1 -1
  75. package/src/lib/format/names.js +1 -0
  76. package/src/lib/format/names.js.map +1 -1
  77. package/src/lib/format/names.mjs +1 -0
  78. package/src/lib/format/names.mjs.map +1 -1
  79. package/src/lib/format/page.d.mts +391 -4
  80. package/src/lib/format/page.d.ts +391 -4
  81. package/src/lib/format/page.js +13 -0
  82. package/src/lib/format/page.js.map +1 -1
  83. package/src/lib/format/page.mjs +13 -0
  84. package/src/lib/format/page.mjs.map +1 -1
  85. package/src/lib/format/references.d.mts +14 -1
  86. package/src/lib/format/references.d.ts +14 -1
  87. package/src/lib/format/references.js +96 -8
  88. package/src/lib/format/references.js.map +1 -1
  89. package/src/lib/format/references.mjs +96 -8
  90. package/src/lib/format/references.mjs.map +1 -1
  91. package/src/lib/format/translate.d.mts +20 -0
  92. package/src/lib/format/translate.d.ts +20 -0
  93. package/src/lib/format/translate.js +79 -21
  94. package/src/lib/format/translate.js.map +1 -1
  95. package/src/lib/format/translate.mjs +76 -21
  96. package/src/lib/format/translate.mjs.map +1 -1
  97. package/src/lib/record/check.d.mts +19 -1
  98. package/src/lib/record/check.d.ts +19 -1
  99. package/src/lib/record/check.js +84 -21
  100. package/src/lib/record/check.js.map +1 -1
  101. package/src/lib/record/check.mjs +82 -21
  102. package/src/lib/record/check.mjs.map +1 -1
  103. package/src/lib/record/compute.d.mts +24 -0
  104. package/src/lib/record/compute.d.ts +24 -0
  105. package/src/lib/record/compute.js +107 -0
  106. package/src/lib/record/compute.js.map +1 -0
  107. package/src/lib/record/compute.mjs +103 -0
  108. package/src/lib/record/compute.mjs.map +1 -0
  109. package/src/lib/record/data-source.d.mts +9 -1
  110. package/src/lib/record/data-source.d.ts +9 -1
  111. package/src/lib/record/data-source.js.map +1 -1
  112. package/src/lib/record/data-source.mjs.map +1 -1
  113. package/src/lib/record/env.d.mts +9 -0
  114. package/src/lib/record/env.d.ts +9 -0
  115. package/src/lib/record/env.js +28 -0
  116. package/src/lib/record/env.js.map +1 -0
  117. package/src/lib/record/env.mjs +25 -0
  118. package/src/lib/record/env.mjs.map +1 -0
  119. package/src/lib/record/form.d.mts +24 -0
  120. package/src/lib/record/form.d.ts +24 -0
  121. package/src/lib/record/form.js +160 -32
  122. package/src/lib/record/form.js.map +1 -1
  123. package/src/lib/record/form.mjs +160 -32
  124. package/src/lib/record/form.mjs.map +1 -1
  125. package/src/lib/record/inputs.d.mts +5 -0
  126. package/src/lib/record/inputs.d.ts +5 -0
  127. package/src/lib/record/inputs.js +47 -0
  128. package/src/lib/record/inputs.js.map +1 -0
  129. package/src/lib/record/inputs.mjs +44 -0
  130. package/src/lib/record/inputs.mjs.map +1 -0
  131. package/src/lib/record/limits.d.mts +13 -0
  132. package/src/lib/record/limits.d.ts +13 -0
  133. package/src/lib/record/limits.js +45 -0
  134. package/src/lib/record/limits.js.map +1 -0
  135. package/src/lib/record/limits.mjs +41 -0
  136. package/src/lib/record/limits.mjs.map +1 -0
  137. package/src/lib/record/locales/all.d.mts +7 -0
  138. package/src/lib/record/locales/all.d.ts +7 -0
  139. package/src/lib/record/locales/all.js +13 -0
  140. package/src/lib/record/locales/all.js.map +1 -0
  141. package/src/lib/record/locales/all.mjs +10 -0
  142. package/src/lib/record/locales/all.mjs.map +1 -0
  143. package/src/lib/record/locales/ar.d.mts +3 -0
  144. package/src/lib/record/locales/ar.d.ts +3 -0
  145. package/src/lib/record/locales/ar.js +55 -0
  146. package/src/lib/record/locales/ar.js.map +1 -0
  147. package/src/lib/record/locales/ar.mjs +52 -0
  148. package/src/lib/record/locales/ar.mjs.map +1 -0
  149. package/src/lib/record/locales/de.d.mts +3 -0
  150. package/src/lib/record/locales/de.d.ts +3 -0
  151. package/src/lib/record/locales/de.js +55 -0
  152. package/src/lib/record/locales/de.js.map +1 -0
  153. package/src/lib/record/locales/de.mjs +52 -0
  154. package/src/lib/record/locales/de.mjs.map +1 -0
  155. package/src/lib/record/locales/fr.d.mts +3 -0
  156. package/src/lib/record/locales/fr.d.ts +3 -0
  157. package/src/lib/record/locales/fr.js +55 -0
  158. package/src/lib/record/locales/fr.js.map +1 -0
  159. package/src/lib/record/locales/fr.mjs +52 -0
  160. package/src/lib/record/locales/fr.mjs.map +1 -0
  161. package/src/lib/record/memory-data-source.d.mts +3 -0
  162. package/src/lib/record/memory-data-source.d.ts +3 -0
  163. package/src/lib/record/memory-data-source.js +8 -0
  164. package/src/lib/record/memory-data-source.js.map +1 -1
  165. package/src/lib/record/memory-data-source.mjs +8 -0
  166. package/src/lib/record/memory-data-source.mjs.map +1 -1
  167. package/src/lib/record/messages.d.mts +46 -0
  168. package/src/lib/record/messages.d.ts +46 -0
  169. package/src/lib/record/messages.js +58 -101
  170. package/src/lib/record/messages.js.map +1 -1
  171. package/src/lib/record/messages.mjs +58 -101
  172. package/src/lib/record/messages.mjs.map +1 -1
  173. package/src/lib/record/rules.d.mts +33 -0
  174. package/src/lib/record/rules.d.ts +33 -0
  175. package/src/lib/record/rules.js +83 -0
  176. package/src/lib/record/rules.js.map +1 -0
  177. package/src/lib/record/rules.mjs +79 -0
  178. package/src/lib/record/rules.mjs.map +1 -0
  179. package/src/lib/record/score.d.mts +16 -0
  180. package/src/lib/record/score.d.ts +16 -0
  181. package/src/lib/record/score.js +35 -0
  182. package/src/lib/record/score.js.map +1 -0
  183. package/src/lib/record/score.mjs +32 -0
  184. package/src/lib/record/score.mjs.map +1 -0
  185. package/src/lib/record/set-when.d.mts +24 -0
  186. package/src/lib/record/set-when.d.ts +24 -0
  187. package/src/lib/record/set-when.js +68 -0
  188. package/src/lib/record/set-when.js.map +1 -0
  189. package/src/lib/record/set-when.mjs +65 -0
  190. package/src/lib/record/set-when.mjs.map +1 -0
  191. package/src/lib/record/structures.d.mts +14 -0
  192. package/src/lib/record/structures.d.ts +14 -0
  193. package/src/lib/record/structures.js +32 -0
  194. package/src/lib/record/structures.js.map +1 -0
  195. package/src/lib/record/structures.mjs +28 -0
  196. package/src/lib/record/structures.mjs.map +1 -0
  197. package/src/lib/record/values.d.mts +10 -5
  198. package/src/lib/record/values.d.ts +10 -5
  199. package/src/lib/record/values.js +20 -6
  200. package/src/lib/record/values.js.map +1 -1
  201. package/src/lib/record/values.mjs +19 -6
  202. package/src/lib/record/values.mjs.map +1 -1
  203. package/src/runtime.d.mts +10 -7
  204. package/src/runtime.d.ts +10 -7
  205. package/src/runtime.js +12 -1
  206. package/src/runtime.js.map +1 -1
  207. package/src/runtime.mjs +5 -2
  208. package/src/runtime.mjs.map +1 -1
@@ -0,0 +1,44 @@
1
+ /** Every node of an expression, each visited once, the outer before the inner. */
2
+ function walk(ast, visit) {
3
+ visit(ast);
4
+ switch (ast.type) {
5
+ case 'BinaryOp':
6
+ walk(ast.left, visit);
7
+ walk(ast.right, visit);
8
+ return;
9
+ case 'UnaryOp':
10
+ walk(ast.operand, visit);
11
+ return;
12
+ case 'Call':
13
+ for (const arg of ast.args)
14
+ walk(arg, visit);
15
+ return;
16
+ default:
17
+ return;
18
+ }
19
+ }
20
+ /** The fields an expression reads, by their first name, once each, in order of appearance. Functions are not fields. */
21
+ export function fieldsRead(ast) {
22
+ const names = [];
23
+ walk(ast, (node) => {
24
+ if (node.type !== 'Identifier')
25
+ return;
26
+ const root = node.name.split('.')[0];
27
+ if (!names.includes(root))
28
+ names.push(root);
29
+ });
30
+ return names;
31
+ }
32
+ /** The line fields an expression adds up, as `sum(lines, 'subtotal')` names them. */
33
+ export function sumsRead(ast) {
34
+ const sums = [];
35
+ walk(ast, (node) => {
36
+ if (node.type !== 'Call' || node.name !== 'sum')
37
+ return;
38
+ const [lines, field] = node.args;
39
+ if (lines.type === 'Identifier' && field?.type === 'Literal')
40
+ sums.push({ lines: lines.name, field: field.value });
41
+ });
42
+ return sums;
43
+ }
44
+ //# sourceMappingURL=reads.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reads.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/reads.ts"],"names":[],"mappings":"AAEA,kFAAkF;AAClF,SAAS,IAAI,CAAC,GAAY,EAAE,KAA8B;IACxD,KAAK,CAAC,GAAG,CAAC,CAAC;IACX,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,UAAU;YACb,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACvB,OAAO;QACT,KAAK,SAAS;YACZ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACzB,OAAO;QACT,KAAK,MAAM;YACT,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI;gBAAE,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC7C,OAAO;QACT;YACE,OAAO;IACX,CAAC;AACH,CAAC;AAED,wHAAwH;AACxH,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;QACjB,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY;YAAE,OAAO;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,QAAQ,CAAC,GAAY;IACnC,MAAM,IAAI,GAAuC,EAAE,CAAC;IACpD,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;QACjB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;YAAE,OAAO;QACxD,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAe,EAAE,CAAC,CAAC;IAC/H,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,19 +1,22 @@
1
1
  /**
2
- * Tokenizer for modifier expressions.
2
+ * Tokenizer for expressions: modifiers, and values worked out from others.
3
3
  *
4
4
  * Ported from the React form engine, with one change in behaviour: a
5
5
  * character the language does not know is an error, not something to skip.
6
6
  * The React version dropped it silently, so `amount > -5` read as
7
- * `amount > 5` and `a && b` read as `a b`.
7
+ * `amount > 5` and `a && b` read as `a b`. A minus sign is a token of its
8
+ * own, so `a-5` is a subtraction; the parser reads `-5` as a negative number.
8
9
  */
9
- export type TokenType = 'IDENTIFIER' | 'NUMBER' | 'STRING' | 'LIST' | 'OPERATOR' | 'LOGICAL' | 'CONSTANT' | 'PAREN';
10
+ export type TokenType = 'IDENTIFIER' | 'NUMBER' | 'STRING' | 'LIST' | 'OPERATOR' | 'LOGICAL' | 'CONSTANT' | 'ARITHMETIC' | 'COMMA' | 'PAREN';
10
11
  export interface Token {
11
12
  type: TokenType;
12
13
  value: string;
13
14
  position: number;
14
15
  }
16
+ /** The words that are values, not field names. */
17
+ export declare const CONSTANTS: ReadonlyMap<string, boolean | null>;
15
18
  /**
16
- * Tokenizes a Flectra modifier expression.
19
+ * Tokenizes an expression: a Flectra modifier, or a value worked out from others.
17
20
  *
18
21
  * @param expr - The expression string to tokenize
19
22
  * @returns Array of tokens
@@ -26,6 +29,4 @@ export interface Token {
26
29
  * // { type: 'STRING', value: "'draft'", position: 2 }
27
30
  * // ]
28
31
  */
29
- /** The words that are values, not field names. */
30
- export declare const CONSTANTS: ReadonlyMap<string, boolean | null>;
31
32
  export declare function tokenize(expr: string): Token[];
@@ -1,19 +1,22 @@
1
1
  /**
2
- * Tokenizer for modifier expressions.
2
+ * Tokenizer for expressions: modifiers, and values worked out from others.
3
3
  *
4
4
  * Ported from the React form engine, with one change in behaviour: a
5
5
  * character the language does not know is an error, not something to skip.
6
6
  * The React version dropped it silently, so `amount > -5` read as
7
- * `amount > 5` and `a && b` read as `a b`.
7
+ * `amount > 5` and `a && b` read as `a b`. A minus sign is a token of its
8
+ * own, so `a-5` is a subtraction; the parser reads `-5` as a negative number.
8
9
  */
9
- export type TokenType = 'IDENTIFIER' | 'NUMBER' | 'STRING' | 'LIST' | 'OPERATOR' | 'LOGICAL' | 'CONSTANT' | 'PAREN';
10
+ export type TokenType = 'IDENTIFIER' | 'NUMBER' | 'STRING' | 'LIST' | 'OPERATOR' | 'LOGICAL' | 'CONSTANT' | 'ARITHMETIC' | 'COMMA' | 'PAREN';
10
11
  export interface Token {
11
12
  type: TokenType;
12
13
  value: string;
13
14
  position: number;
14
15
  }
16
+ /** The words that are values, not field names. */
17
+ export declare const CONSTANTS: ReadonlyMap<string, boolean | null>;
15
18
  /**
16
- * Tokenizes a Flectra modifier expression.
19
+ * Tokenizes an expression: a Flectra modifier, or a value worked out from others.
17
20
  *
18
21
  * @param expr - The expression string to tokenize
19
22
  * @returns Array of tokens
@@ -26,6 +29,4 @@ export interface Token {
26
29
  * // { type: 'STRING', value: "'draft'", position: 2 }
27
30
  * // ]
28
31
  */
29
- /** The words that are values, not field names. */
30
- export declare const CONSTANTS: ReadonlyMap<string, boolean | null>;
31
32
  export declare function tokenize(expr: string): Token[];
@@ -1,17 +1,29 @@
1
1
  "use strict";
2
2
  /**
3
- * Tokenizer for modifier expressions.
3
+ * Tokenizer for expressions: modifiers, and values worked out from others.
4
4
  *
5
5
  * Ported from the React form engine, with one change in behaviour: a
6
6
  * character the language does not know is an error, not something to skip.
7
7
  * The React version dropped it silently, so `amount > -5` read as
8
- * `amount > 5` and `a && b` read as `a b`.
8
+ * `amount > 5` and `a && b` read as `a b`. A minus sign is a token of its
9
+ * own, so `a-5` is a subtraction; the parser reads `-5` as a negative number.
9
10
  */
10
11
  Object.defineProperty(exports, "__esModule", { value: true });
11
12
  exports.CONSTANTS = void 0;
12
13
  exports.tokenize = tokenize;
14
+ /** The words that are values, not field names. */
15
+ exports.CONSTANTS = new Map([
16
+ ['True', true],
17
+ ['False', false],
18
+ ['None', null],
19
+ ['true', true],
20
+ ['false', false],
21
+ ['null', null],
22
+ ]);
23
+ /** The operators that work out numbers, and join text. */
24
+ const ARITHMETIC = new Set(['+', '-', '*', '/', '%']);
13
25
  /**
14
- * Tokenizes a Flectra modifier expression.
26
+ * Tokenizes an expression: a Flectra modifier, or a value worked out from others.
15
27
  *
16
28
  * @param expr - The expression string to tokenize
17
29
  * @returns Array of tokens
@@ -24,24 +36,15 @@ exports.tokenize = tokenize;
24
36
  * // { type: 'STRING', value: "'draft'", position: 2 }
25
37
  * // ]
26
38
  */
27
- /** The words that are values, not field names. */
28
- exports.CONSTANTS = new Map([
29
- ['True', true],
30
- ['False', false],
31
- ['None', null],
32
- ['true', true],
33
- ['false', false],
34
- ['null', null],
35
- ]);
36
39
  function tokenize(expr) {
37
40
  const tokens = [];
38
41
  if (!expr)
39
42
  return tokens;
40
43
  // Alternatives in priority order: "not in" before "not", operators of two
41
- // characters before one, a signed number before anything else that could
42
- // start with a digit. Sticky (`y`), so a position nothing matches is an
43
- // error instead of a gap.
44
- const token = /(\(|\)|==|!=|<=|>=|<>|<|>|not\s+in\b|in\b|and\b|or\b|not\b|\[[^\]]*\]|'[^']*'|"[^"]*"|-?\d+\.?\d*|\w+(?:\.\w+)*)/iy;
44
+ // characters before one, a number before anything else that could start
45
+ // with a digit. Sticky (`y`), so a position nothing matches is an error
46
+ // instead of a gap.
47
+ const token = /(\(|\)|,|==|!=|<=|>=|<>|<|>|[-+*/%]|not\s+in\b|in\b|and\b|or\b|not\b|\[[^\]]*\]|'[^']*'|"[^"]*"|\d+\.?\d*|\w+(?:\.\w+)*)/iy;
45
48
  const space = /\s*/y;
46
49
  let at = 0;
47
50
  for (;;) {
@@ -82,6 +85,13 @@ function getTokenType(text) {
82
85
  if (text === '(' || text === ')') {
83
86
  return 'PAREN';
84
87
  }
88
+ // Arithmetic, and the comma between a function's values
89
+ if (ARITHMETIC.has(text)) {
90
+ return 'ARITHMETIC';
91
+ }
92
+ if (text === ',') {
93
+ return 'COMMA';
94
+ }
85
95
  // Lists (start with '[')
86
96
  if (text.startsWith('[')) {
87
97
  return 'LIST';
@@ -90,8 +100,8 @@ function getTokenType(text) {
90
100
  if (text.startsWith("'") || text.startsWith('"')) {
91
101
  return 'STRING';
92
102
  }
93
- // Numbers (matches integer or float, either sign)
94
- if (/^-?\d+\.?\d*$/.test(text)) {
103
+ // Numbers (integer or float; a minus sign before one is its own token)
104
+ if (/^\d+\.?\d*$/.test(text)) {
95
105
  return 'NUMBER';
96
106
  }
97
107
  // Default to identifier
@@ -1 +1 @@
1
- {"version":3,"file":"tokenizer.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/tokenizer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tokenizer.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/tokenizer.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,25 @@
1
1
  /**
2
- * Tokenizer for modifier expressions.
2
+ * Tokenizer for expressions: modifiers, and values worked out from others.
3
3
  *
4
4
  * Ported from the React form engine, with one change in behaviour: a
5
5
  * character the language does not know is an error, not something to skip.
6
6
  * The React version dropped it silently, so `amount > -5` read as
7
- * `amount > 5` and `a && b` read as `a b`.
7
+ * `amount > 5` and `a && b` read as `a b`. A minus sign is a token of its
8
+ * own, so `a-5` is a subtraction; the parser reads `-5` as a negative number.
8
9
  */
10
+ /** The words that are values, not field names. */
11
+ export const CONSTANTS = new Map([
12
+ ['True', true],
13
+ ['False', false],
14
+ ['None', null],
15
+ ['true', true],
16
+ ['false', false],
17
+ ['null', null],
18
+ ]);
19
+ /** The operators that work out numbers, and join text. */
20
+ const ARITHMETIC = new Set(['+', '-', '*', '/', '%']);
9
21
  /**
10
- * Tokenizes a Flectra modifier expression.
22
+ * Tokenizes an expression: a Flectra modifier, or a value worked out from others.
11
23
  *
12
24
  * @param expr - The expression string to tokenize
13
25
  * @returns Array of tokens
@@ -20,24 +32,15 @@
20
32
  * // { type: 'STRING', value: "'draft'", position: 2 }
21
33
  * // ]
22
34
  */
23
- /** The words that are values, not field names. */
24
- export const CONSTANTS = new Map([
25
- ['True', true],
26
- ['False', false],
27
- ['None', null],
28
- ['true', true],
29
- ['false', false],
30
- ['null', null],
31
- ]);
32
35
  export function tokenize(expr) {
33
36
  const tokens = [];
34
37
  if (!expr)
35
38
  return tokens;
36
39
  // Alternatives in priority order: "not in" before "not", operators of two
37
- // characters before one, a signed number before anything else that could
38
- // start with a digit. Sticky (`y`), so a position nothing matches is an
39
- // error instead of a gap.
40
- const token = /(\(|\)|==|!=|<=|>=|<>|<|>|not\s+in\b|in\b|and\b|or\b|not\b|\[[^\]]*\]|'[^']*'|"[^"]*"|-?\d+\.?\d*|\w+(?:\.\w+)*)/iy;
40
+ // characters before one, a number before anything else that could start
41
+ // with a digit. Sticky (`y`), so a position nothing matches is an error
42
+ // instead of a gap.
43
+ const token = /(\(|\)|,|==|!=|<=|>=|<>|<|>|[-+*/%]|not\s+in\b|in\b|and\b|or\b|not\b|\[[^\]]*\]|'[^']*'|"[^"]*"|\d+\.?\d*|\w+(?:\.\w+)*)/iy;
41
44
  const space = /\s*/y;
42
45
  let at = 0;
43
46
  for (;;) {
@@ -78,6 +81,13 @@ function getTokenType(text) {
78
81
  if (text === '(' || text === ')') {
79
82
  return 'PAREN';
80
83
  }
84
+ // Arithmetic, and the comma between a function's values
85
+ if (ARITHMETIC.has(text)) {
86
+ return 'ARITHMETIC';
87
+ }
88
+ if (text === ',') {
89
+ return 'COMMA';
90
+ }
81
91
  // Lists (start with '[')
82
92
  if (text.startsWith('[')) {
83
93
  return 'LIST';
@@ -86,8 +96,8 @@ function getTokenType(text) {
86
96
  if (text.startsWith("'") || text.startsWith('"')) {
87
97
  return 'STRING';
88
98
  }
89
- // Numbers (matches integer or float, either sign)
90
- if (/^-?\d+\.?\d*$/.test(text)) {
99
+ // Numbers (integer or float; a minus sign before one is its own token)
100
+ if (/^\d+\.?\d*$/.test(text)) {
91
101
  return 'NUMBER';
92
102
  }
93
103
  // Default to identifier
@@ -1 +1 @@
1
- {"version":3,"file":"tokenizer.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/tokenizer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tokenizer.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/tokenizer.ts"],"names":[],"mappings":"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"}