@1771technologies/lytenyte-pro 2.0.4-dev.3 → 2.1.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 (180) hide show
  1. package/README.md +54 -11
  2. package/css/components/expression-editor.css +106 -0
  3. package/dist/components/column-manager/column-manager.d.ts +6 -1
  4. package/dist/components/column-manager/column-manager.js +23 -2
  5. package/dist/components/expressions-editor/create-completion-provider.d.ts +10 -0
  6. package/dist/components/expressions-editor/create-completion-provider.js +391 -0
  7. package/dist/components/expressions-editor/create-key-down-handler.d.ts +18 -0
  8. package/dist/components/expressions-editor/create-key-down-handler.js +49 -0
  9. package/dist/components/expressions-editor/cursor-position/measure-cursor-at-pointer.d.ts +2 -0
  10. package/dist/components/expressions-editor/cursor-position/measure-cursor-at-pointer.js +56 -0
  11. package/dist/components/expressions-editor/cursor-position/use-cursor-position.d.ts +5 -0
  12. package/dist/components/expressions-editor/cursor-position/use-cursor-position.js +33 -0
  13. package/dist/components/expressions-editor/expression-editor.d.ts +3 -0
  14. package/dist/components/expressions-editor/expression-editor.js +158 -0
  15. package/dist/components/expressions-editor/get-indentation.d.ts +1 -0
  16. package/dist/components/expressions-editor/get-indentation.js +7 -0
  17. package/dist/components/expressions-editor/handle-completion-key-down.d.ts +2 -0
  18. package/dist/components/expressions-editor/handle-completion-key-down.js +22 -0
  19. package/dist/components/expressions-editor/handle-enter-key.d.ts +4 -0
  20. package/dist/components/expressions-editor/handle-enter-key.js +11 -0
  21. package/dist/components/expressions-editor/handle-manual-trigger.d.ts +2 -0
  22. package/dist/components/expressions-editor/handle-manual-trigger.js +3 -0
  23. package/dist/components/expressions-editor/index.d.ts +18 -0
  24. package/dist/components/expressions-editor/index.js +11 -0
  25. package/dist/components/expressions-editor/intellisence/completion-context.d.ts +17 -0
  26. package/dist/components/expressions-editor/intellisence/completion-context.js +7 -0
  27. package/dist/components/expressions-editor/intellisence/completion-item.d.ts +5 -0
  28. package/dist/components/expressions-editor/intellisence/completion-item.js +11 -0
  29. package/dist/components/expressions-editor/intellisence/completion-list.d.ts +8 -0
  30. package/dist/components/expressions-editor/intellisence/completion-list.js +18 -0
  31. package/dist/components/expressions-editor/intellisence/completion-popover.d.ts +1 -0
  32. package/dist/components/expressions-editor/intellisence/completion-popover.js +47 -0
  33. package/dist/components/expressions-editor/intellisence/filter-completions-by-prefix.d.ts +2 -0
  34. package/dist/components/expressions-editor/intellisence/filter-completions-by-prefix.js +6 -0
  35. package/dist/components/expressions-editor/intellisence/get-word-at-cursor.d.ts +2 -0
  36. package/dist/components/expressions-editor/intellisence/get-word-at-cursor.js +12 -0
  37. package/dist/components/expressions-editor/intellisence/use-complete-trigger.d.ts +13 -0
  38. package/dist/components/expressions-editor/intellisence/use-complete-trigger.js +41 -0
  39. package/dist/components/expressions-editor/intellisence/use-completions.d.ts +14 -0
  40. package/dist/components/expressions-editor/intellisence/use-completions.js +78 -0
  41. package/dist/components/expressions-editor/replace-word-at-cursor.d.ts +5 -0
  42. package/dist/components/expressions-editor/replace-word-at-cursor.js +7 -0
  43. package/dist/components/expressions-editor/token-highlighter-default.d.ts +4 -0
  44. package/dist/components/expressions-editor/token-highlighter-default.js +20 -0
  45. package/dist/components/expressions-editor/types.d.ts +48 -0
  46. package/dist/components/expressions-editor/types.js +1 -0
  47. package/dist/components/expressions-editor/use-keyboard-navigation.d.ts +10 -0
  48. package/dist/components/expressions-editor/use-keyboard-navigation.js +37 -0
  49. package/dist/components/pill-manager/container.js +55 -9
  50. package/dist/components/pill-manager/item.js +15 -1
  51. package/dist/components/select-all.js +1 -1
  52. package/dist/components/tree-view/root.d.ts +9 -0
  53. package/dist/components/tree-view/root.js +4 -2
  54. package/dist/data-source-client/hooks/use-flattened-groups.js +2 -2
  55. package/dist/expressions/compiler/compile.d.ts +3 -0
  56. package/dist/expressions/compiler/compile.js +4 -0
  57. package/dist/expressions/compiler/eval-constant.d.ts +2 -0
  58. package/dist/expressions/compiler/eval-constant.js +19 -0
  59. package/dist/expressions/compiler/is-constant.d.ts +2 -0
  60. package/dist/expressions/compiler/is-constant.js +6 -0
  61. package/dist/expressions/compiler/make-constant.d.ts +2 -0
  62. package/dist/expressions/compiler/make-constant.js +11 -0
  63. package/dist/expressions/compiler/optimize.d.ts +3 -0
  64. package/dist/expressions/compiler/optimize.js +47 -0
  65. package/dist/expressions/compiler/value-of.d.ts +2 -0
  66. package/dist/expressions/compiler/value-of.js +11 -0
  67. package/dist/expressions/errors/clamp-offset.d.ts +1 -0
  68. package/dist/expressions/errors/clamp-offset.js +3 -0
  69. package/dist/expressions/errors/expression-error.d.ts +10 -0
  70. package/dist/expressions/errors/expression-error.js +19 -0
  71. package/dist/expressions/errors/format-error.d.ts +3 -0
  72. package/dist/expressions/errors/format-error.js +27 -0
  73. package/dist/expressions/errors/get-line-end.d.ts +1 -0
  74. package/dist/expressions/errors/get-line-end.js +8 -0
  75. package/dist/expressions/errors/get-line-start.d.ts +1 -0
  76. package/dist/expressions/errors/get-line-start.js +8 -0
  77. package/dist/expressions/errors/index.d.ts +7 -0
  78. package/dist/expressions/errors/index.js +6 -0
  79. package/dist/expressions/errors/offset-to-position.d.ts +2 -0
  80. package/dist/expressions/errors/offset-to-position.js +17 -0
  81. package/dist/expressions/errors/types.d.ts +10 -0
  82. package/dist/expressions/errors/types.js +1 -0
  83. package/dist/expressions/evaluator/evaluate-binary.d.ts +4 -0
  84. package/dist/expressions/evaluator/evaluate-binary.js +21 -0
  85. package/dist/expressions/evaluator/evaluate-unary.d.ts +2 -0
  86. package/dist/expressions/evaluator/evaluate-unary.js +10 -0
  87. package/dist/expressions/evaluator/evaluate.d.ts +15 -0
  88. package/dist/expressions/evaluator/evaluate.js +62 -0
  89. package/dist/expressions/index.d.ts +7 -0
  90. package/dist/expressions/index.js +5 -0
  91. package/dist/expressions/lexer/predicates/is-alpha-numeric.d.ts +1 -0
  92. package/dist/expressions/lexer/predicates/is-alpha-numeric.js +5 -0
  93. package/dist/expressions/lexer/predicates/is-alpha.d.ts +1 -0
  94. package/dist/expressions/lexer/predicates/is-alpha.js +3 -0
  95. package/dist/expressions/lexer/predicates/is-binary-digit.d.ts +1 -0
  96. package/dist/expressions/lexer/predicates/is-binary-digit.js +3 -0
  97. package/dist/expressions/lexer/predicates/is-digit.d.ts +1 -0
  98. package/dist/expressions/lexer/predicates/is-digit.js +3 -0
  99. package/dist/expressions/lexer/predicates/is-hex-digit.d.ts +1 -0
  100. package/dist/expressions/lexer/predicates/is-hex-digit.js +4 -0
  101. package/dist/expressions/lexer/predicates/is-octal-digit.d.ts +1 -0
  102. package/dist/expressions/lexer/predicates/is-octal-digit.js +3 -0
  103. package/dist/expressions/lexer/tokenize/consume-digits.d.ts +1 -0
  104. package/dist/expressions/lexer/tokenize/consume-digits.js +5 -0
  105. package/dist/expressions/lexer/tokenize/scan-identifier.d.ts +6 -0
  106. package/dist/expressions/lexer/tokenize/scan-identifier.js +20 -0
  107. package/dist/expressions/lexer/tokenize/scan-number.d.ts +4 -0
  108. package/dist/expressions/lexer/tokenize/scan-number.js +32 -0
  109. package/dist/expressions/lexer/tokenize/scan-operator.d.ts +6 -0
  110. package/dist/expressions/lexer/tokenize/scan-operator.js +71 -0
  111. package/dist/expressions/lexer/tokenize/scan-string-literal.d.ts +4 -0
  112. package/dist/expressions/lexer/tokenize/scan-string-literal.js +22 -0
  113. package/dist/expressions/lexer/tokenize/scan-string.d.ts +4 -0
  114. package/dist/expressions/lexer/tokenize/scan-string.js +98 -0
  115. package/dist/expressions/lexer/tokenize/scan-template-literal.d.ts +4 -0
  116. package/dist/expressions/lexer/tokenize/scan-template-literal.js +51 -0
  117. package/dist/expressions/lexer/tokenize/tokenize.d.ts +4 -0
  118. package/dist/expressions/lexer/tokenize/tokenize.js +99 -0
  119. package/dist/expressions/lexer/types.d.ts +12 -0
  120. package/dist/expressions/lexer/types.js +1 -0
  121. package/dist/expressions/parser/parse-array-literal.d.ts +3 -0
  122. package/dist/expressions/parser/parse-array-literal.js +15 -0
  123. package/dist/expressions/parser/parse-expression.d.ts +3 -0
  124. package/dist/expressions/parser/parse-expression.js +74 -0
  125. package/dist/expressions/parser/parse-object-literal.d.ts +3 -0
  126. package/dist/expressions/parser/parse-object-literal.js +69 -0
  127. package/dist/expressions/parser/parse-pipe-transform.d.ts +3 -0
  128. package/dist/expressions/parser/parse-pipe-transform.js +26 -0
  129. package/dist/expressions/parser/parse-postfix.d.ts +3 -0
  130. package/dist/expressions/parser/parse-postfix.js +23 -0
  131. package/dist/expressions/parser/parse-primary.d.ts +3 -0
  132. package/dist/expressions/parser/parse-primary.js +35 -0
  133. package/dist/expressions/parser/parse-template-literal.d.ts +3 -0
  134. package/dist/expressions/parser/parse-template-literal.js +41 -0
  135. package/dist/expressions/parser/parse-unary.d.ts +3 -0
  136. package/dist/expressions/parser/parse-unary.js +28 -0
  137. package/dist/expressions/parser/parse.d.ts +3 -0
  138. package/dist/expressions/parser/parse.js +26 -0
  139. package/dist/expressions/parser/parser-context.d.ts +12 -0
  140. package/dist/expressions/parser/parser-context.js +14 -0
  141. package/dist/expressions/parser/precedence.d.ts +1 -0
  142. package/dist/expressions/parser/precedence.js +8 -0
  143. package/dist/expressions/parser/types.d.ts +101 -0
  144. package/dist/expressions/parser/types.js +1 -0
  145. package/dist/expressions/plugin.d.ts +20 -0
  146. package/dist/expressions/plugin.js +1 -0
  147. package/dist/expressions/plugins/access.d.ts +2 -0
  148. package/dist/expressions/plugins/access.js +138 -0
  149. package/dist/expressions/plugins/arrows.d.ts +2 -0
  150. package/dist/expressions/plugins/arrows.js +83 -0
  151. package/dist/expressions/plugins/booleans.d.ts +2 -0
  152. package/dist/expressions/plugins/booleans.js +34 -0
  153. package/dist/expressions/plugins/collections.d.ts +2 -0
  154. package/dist/expressions/plugins/collections.js +70 -0
  155. package/dist/expressions/plugins/comparison.d.ts +2 -0
  156. package/dist/expressions/plugins/comparison.js +51 -0
  157. package/dist/expressions/plugins/date-identifier.d.ts +4 -0
  158. package/dist/expressions/plugins/date-identifier.js +29 -0
  159. package/dist/expressions/plugins/date-literal.d.ts +2 -0
  160. package/dist/expressions/plugins/date-literal.js +71 -0
  161. package/dist/expressions/plugins/logical.d.ts +2 -0
  162. package/dist/expressions/plugins/logical.js +103 -0
  163. package/dist/expressions/plugins/membership.d.ts +2 -0
  164. package/dist/expressions/plugins/membership.js +71 -0
  165. package/dist/expressions/plugins/pipe.d.ts +2 -0
  166. package/dist/expressions/plugins/pipe.js +57 -0
  167. package/dist/expressions/plugins/quoted-identifier.d.ts +2 -0
  168. package/dist/expressions/plugins/quoted-identifier.js +35 -0
  169. package/dist/expressions/plugins/resolved-identifier.d.ts +5 -0
  170. package/dist/expressions/plugins/resolved-identifier.js +19 -0
  171. package/dist/expressions/plugins/standard.d.ts +15 -0
  172. package/dist/expressions/plugins/standard.js +27 -0
  173. package/dist/expressions/plugins/strings.d.ts +2 -0
  174. package/dist/expressions/plugins/strings.js +44 -0
  175. package/dist/expressions/plugins/ternary.d.ts +2 -0
  176. package/dist/expressions/plugins/ternary.js +58 -0
  177. package/dist/expressions.d.ts +2 -0
  178. package/dist/expressions.js +2 -0
  179. package/dist/index.d.ts +1 -0
  180. package/package.json +12 -5
@@ -0,0 +1,101 @@
1
+ import type { BinaryExpressionOperator, UnaryOperator } from "../lexer/types.js";
2
+ interface BaseNode {
3
+ start: number;
4
+ end: number;
5
+ }
6
+ export interface NumberLiteral extends BaseNode {
7
+ type: "NumberLiteral";
8
+ value: number;
9
+ }
10
+ export interface StringLiteral extends BaseNode {
11
+ type: "StringLiteral";
12
+ value: string;
13
+ }
14
+ export interface BooleanLiteral extends BaseNode {
15
+ type: "BooleanLiteral";
16
+ value: boolean;
17
+ }
18
+ export interface NullLiteral extends BaseNode {
19
+ type: "NullLiteral";
20
+ value: null;
21
+ }
22
+ export interface UndefinedLiteral extends BaseNode {
23
+ type: "UndefinedLiteral";
24
+ value: undefined;
25
+ }
26
+ export interface Identifier extends BaseNode {
27
+ type: "Identifier";
28
+ name: string;
29
+ }
30
+ export interface BinaryExpression extends BaseNode {
31
+ type: "BinaryExpression";
32
+ operator: BinaryExpressionOperator;
33
+ left: ASTNode;
34
+ right: ASTNode;
35
+ }
36
+ export interface UnaryExpression extends BaseNode {
37
+ type: "UnaryExpression";
38
+ operator: UnaryOperator;
39
+ operand: ASTNode;
40
+ }
41
+ export interface ConditionalExpression extends BaseNode {
42
+ type: "ConditionalExpression";
43
+ test: ASTNode;
44
+ consequent: ASTNode;
45
+ alternate: ASTNode;
46
+ }
47
+ export interface MemberExpression extends BaseNode {
48
+ type: "MemberExpression";
49
+ object: ASTNode;
50
+ property: ASTNode;
51
+ computed: boolean;
52
+ }
53
+ export interface OptionalMemberExpression extends BaseNode {
54
+ type: "OptionalMemberExpression";
55
+ object: ASTNode;
56
+ property: ASTNode;
57
+ computed: boolean;
58
+ }
59
+ export interface ArrayLiteral extends BaseNode {
60
+ type: "ArrayLiteral";
61
+ readonly elements: readonly (ASTNode | SpreadElement)[];
62
+ }
63
+ export interface ObjectLiteral extends BaseNode {
64
+ type: "ObjectLiteral";
65
+ readonly properties: readonly ObjectProperty[];
66
+ }
67
+ export interface ObjectProperty extends BaseNode {
68
+ type: "ObjectProperty";
69
+ key: ASTNode;
70
+ value: ASTNode;
71
+ computed: boolean;
72
+ }
73
+ export interface CallExpression extends BaseNode {
74
+ type: "CallExpression";
75
+ callee: ASTNode;
76
+ readonly args: readonly ASTNode[];
77
+ }
78
+ export interface PipeExpression extends BaseNode {
79
+ type: "PipeExpression";
80
+ input: ASTNode;
81
+ transform: ASTNode;
82
+ }
83
+ export interface TemplateLiteral extends BaseNode {
84
+ type: "TemplateLiteral";
85
+ readonly parts: readonly (StringLiteral | ASTNode)[];
86
+ }
87
+ export interface SpreadElement extends BaseNode {
88
+ type: "SpreadElement";
89
+ argument: ASTNode;
90
+ }
91
+ export interface ArrowFunctionExpression extends BaseNode {
92
+ type: "ArrowFunctionExpression";
93
+ params: string[];
94
+ body: ASTNode;
95
+ }
96
+ export interface DateLiteralNode extends BaseNode {
97
+ type: "DateLiteralNode";
98
+ value: string;
99
+ }
100
+ export type ASTNode = NumberLiteral | StringLiteral | BooleanLiteral | NullLiteral | UndefinedLiteral | Identifier | BinaryExpression | UnaryExpression | ConditionalExpression | MemberExpression | OptionalMemberExpression | ArrayLiteral | ObjectLiteral | CallExpression | PipeExpression | TemplateLiteral | SpreadElement | ArrowFunctionExpression | DateLiteralNode;
101
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import type { ASTNode } from "./parser/types.js";
2
+ import type { ParserContext } from "./parser/parser-context.js";
3
+ export type EvalFn = (node: ASTNode, context: Record<string, unknown>) => unknown;
4
+ export interface Plugin {
5
+ name: string;
6
+ scan?: (source: string, pos: number) => {
7
+ type: string;
8
+ value: string;
9
+ end: number;
10
+ } | null;
11
+ parsePrefix?: (ctx: ParserContext) => ASTNode | null;
12
+ parseInfix?: (ctx: ParserContext, left: ASTNode, minPrec: number) => ASTNode | null;
13
+ parsePostfix?: (ctx: ParserContext, node: ASTNode) => ASTNode | null;
14
+ parseUnary?: (ctx: ParserContext, parseNext: (ctx: ParserContext) => ASTNode) => ASTNode | null;
15
+ infixPrecedence?: (ctx: ParserContext) => number | undefined;
16
+ optimize?: (node: ASTNode, optimize: (n: ASTNode) => ASTNode) => ASTNode | null;
17
+ evaluate?: (node: ASTNode, context: Record<string, unknown>, evaluate: EvalFn) => {
18
+ value: unknown;
19
+ } | null;
20
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from "../plugin.js";
2
+ export declare const accessPlugin: Plugin;
@@ -0,0 +1,138 @@
1
+ import { current, advance, expect } from "../parser/parser-context.js";
2
+ import { parseExpression } from "../parser/parse-expression.js";
3
+ export const accessPlugin = {
4
+ name: "access",
5
+ parsePostfix: (ctx, node) => {
6
+ const tok = current(ctx);
7
+ // Member access: .prop
8
+ if (tok.type === "Punctuation" && tok.value === ".") {
9
+ advance(ctx);
10
+ const prop = expect(ctx, "Identifier");
11
+ return {
12
+ type: "MemberExpression",
13
+ object: node,
14
+ property: { type: "Identifier", name: prop.value, start: prop.start, end: prop.end },
15
+ computed: false,
16
+ start: node.start,
17
+ end: prop.end,
18
+ };
19
+ }
20
+ // Computed member access: [expr]
21
+ if (tok.type === "Punctuation" && tok.value === "[") {
22
+ advance(ctx);
23
+ const property = parseExpression(ctx, 0);
24
+ const end = expect(ctx, "Punctuation", "]").end;
25
+ return {
26
+ type: "MemberExpression",
27
+ object: node,
28
+ property,
29
+ computed: true,
30
+ start: node.start,
31
+ end,
32
+ };
33
+ }
34
+ // Optional chaining: ?.prop or ?.[expr]
35
+ if (tok.type === "OptionalChain") {
36
+ advance(ctx);
37
+ if (current(ctx).type === "Punctuation" && current(ctx).value === "[") {
38
+ advance(ctx);
39
+ const property = parseExpression(ctx, 0);
40
+ const end = expect(ctx, "Punctuation", "]").end;
41
+ return {
42
+ type: "OptionalMemberExpression",
43
+ object: node,
44
+ property,
45
+ computed: true,
46
+ start: node.start,
47
+ end,
48
+ };
49
+ }
50
+ const prop = expect(ctx, "Identifier");
51
+ return {
52
+ type: "OptionalMemberExpression",
53
+ object: node,
54
+ property: { type: "Identifier", name: prop.value, start: prop.start, end: prop.end },
55
+ computed: false,
56
+ start: node.start,
57
+ end: prop.end,
58
+ };
59
+ }
60
+ // Function call: (args)
61
+ if (tok.type === "Punctuation" && tok.value === "(") {
62
+ advance(ctx);
63
+ const args = [];
64
+ while (!(current(ctx).type === "Punctuation" && current(ctx).value === ")")) {
65
+ if (args.length > 0)
66
+ expect(ctx, "Punctuation", ",");
67
+ if (current(ctx).type === "Punctuation" && current(ctx).value === ")")
68
+ break;
69
+ args.push(parseExpression(ctx, 0));
70
+ }
71
+ const end = expect(ctx, "Punctuation", ")").end;
72
+ return {
73
+ type: "CallExpression",
74
+ callee: node,
75
+ args,
76
+ start: node.start,
77
+ end,
78
+ };
79
+ }
80
+ return null;
81
+ },
82
+ optimize: (node, opt) => {
83
+ if (node.type === "MemberExpression" || node.type === "OptionalMemberExpression") {
84
+ const n = node;
85
+ return {
86
+ ...node,
87
+ object: opt(n.object),
88
+ property: n.computed ? opt(n.property) : n.property,
89
+ };
90
+ }
91
+ if (node.type === "CallExpression") {
92
+ const n = node;
93
+ return { ...node, callee: opt(n.callee), args: n.args.map((a) => opt(a)) };
94
+ }
95
+ return null;
96
+ },
97
+ evaluate: (node, context, evalFn) => {
98
+ if (node.type === "MemberExpression") {
99
+ const n = node;
100
+ const object = evalFn(n.object, context);
101
+ if (n.computed) {
102
+ const property = evalFn(n.property, context);
103
+ return { value: object[property] };
104
+ }
105
+ return { value: object[n.property.name] };
106
+ }
107
+ if (node.type === "OptionalMemberExpression") {
108
+ const n = node;
109
+ const object = evalFn(n.object, context);
110
+ if (object == null)
111
+ return { value: undefined };
112
+ if (n.computed) {
113
+ const property = evalFn(n.property, context);
114
+ return { value: object[property] };
115
+ }
116
+ return { value: object[n.property.name] };
117
+ }
118
+ if (node.type === "CallExpression") {
119
+ const n = node;
120
+ const args = n.args.map((a) => evalFn(a, context));
121
+ // Method call — preserve this binding
122
+ if (n.callee.type === "MemberExpression" || n.callee.type === "OptionalMemberExpression") {
123
+ const obj = evalFn(n.callee.object, context);
124
+ if (n.callee.type === "OptionalMemberExpression" && obj == null) {
125
+ return { value: undefined };
126
+ }
127
+ const prop = n.callee.computed
128
+ ? evalFn(n.callee.property, context)
129
+ : n.callee.property.name;
130
+ const method = obj[prop];
131
+ return { value: method.apply(obj, args) };
132
+ }
133
+ const fn = evalFn(n.callee, context);
134
+ return { value: fn(...args) };
135
+ }
136
+ return null;
137
+ },
138
+ };
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from "../plugin.js";
2
+ export declare const arrowsPlugin: Plugin;
@@ -0,0 +1,83 @@
1
+ import { current, advance, expect } from "../parser/parser-context.js";
2
+ import { parseExpression } from "../parser/parse-expression.js";
3
+ function isArrowParams(ctx) {
4
+ let i = ctx.pos + 1;
5
+ let depth = 1;
6
+ while (i < ctx.tokens.length && depth > 0) {
7
+ const t = ctx.tokens[i];
8
+ if (t.type === "Punctuation" && t.value === "(")
9
+ depth++;
10
+ else if (t.type === "Punctuation" && t.value === ")")
11
+ depth--;
12
+ if (depth > 0)
13
+ i++;
14
+ }
15
+ const after = ctx.tokens[i + 1];
16
+ return after?.type === "Arrow";
17
+ }
18
+ function parseArrowFunction(ctx) {
19
+ const start = current(ctx).start;
20
+ advance(ctx); // consume (
21
+ const params = [];
22
+ while (!(current(ctx).type === "Punctuation" && current(ctx).value === ")")) {
23
+ if (params.length > 0)
24
+ expect(ctx, "Punctuation", ",");
25
+ const param = expect(ctx, "Identifier");
26
+ params.push(param.value);
27
+ }
28
+ expect(ctx, "Punctuation", ")"); // consume )
29
+ advance(ctx); // consume =>
30
+ const body = parseExpression(ctx, 0);
31
+ return {
32
+ type: "ArrowFunctionExpression",
33
+ params,
34
+ body,
35
+ start,
36
+ end: body.end,
37
+ };
38
+ }
39
+ export const arrowsPlugin = {
40
+ name: "arrows",
41
+ parsePrefix: (ctx) => {
42
+ const tok = current(ctx);
43
+ // Single-param arrow: identifier => expr
44
+ if (tok.type === "Identifier" && ctx.tokens[ctx.pos + 1]?.type === "Arrow") {
45
+ advance(ctx); // consume identifier
46
+ advance(ctx); // consume =>
47
+ const body = parseExpression(ctx, 0);
48
+ return {
49
+ type: "ArrowFunctionExpression",
50
+ params: [tok.value],
51
+ body,
52
+ start: tok.start,
53
+ end: body.end,
54
+ };
55
+ }
56
+ // Multi-param arrow: (a, b) => expr
57
+ if (tok.type === "Punctuation" && tok.value === "(" && isArrowParams(ctx)) {
58
+ return parseArrowFunction(ctx);
59
+ }
60
+ return null;
61
+ },
62
+ optimize: (node, opt) => {
63
+ if (node.type === "ArrowFunctionExpression") {
64
+ return { ...node, body: opt(node.body) };
65
+ }
66
+ return null;
67
+ },
68
+ evaluate: (node, context, evalFn) => {
69
+ if (node.type === "ArrowFunctionExpression") {
70
+ const n = node;
71
+ return {
72
+ value: (...args) => {
73
+ const childContext = { ...context };
74
+ for (let i = 0; i < n.params.length; i++) {
75
+ childContext[n.params[i]] = args[i];
76
+ }
77
+ return evalFn(n.body, childContext);
78
+ },
79
+ };
80
+ }
81
+ return null;
82
+ },
83
+ };
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from "../plugin.js";
2
+ export declare const booleansPlugin: Plugin;
@@ -0,0 +1,34 @@
1
+ import { current, advance } from "../parser/parser-context.js";
2
+ export const booleansPlugin = {
3
+ name: "booleans",
4
+ parsePrefix: (ctx) => {
5
+ const tok = current(ctx);
6
+ if (tok.type === "Boolean") {
7
+ advance(ctx);
8
+ return {
9
+ type: "BooleanLiteral",
10
+ value: tok.value === "true",
11
+ start: tok.start,
12
+ end: tok.end,
13
+ };
14
+ }
15
+ if (tok.type === "Null") {
16
+ advance(ctx);
17
+ return { type: "NullLiteral", value: null, start: tok.start, end: tok.end };
18
+ }
19
+ if (tok.type === "Undefined") {
20
+ advance(ctx);
21
+ return { type: "UndefinedLiteral", value: undefined, start: tok.start, end: tok.end };
22
+ }
23
+ return null;
24
+ },
25
+ evaluate: (node) => {
26
+ if (node.type === "BooleanLiteral")
27
+ return { value: node.value };
28
+ if (node.type === "NullLiteral")
29
+ return { value: null };
30
+ if (node.type === "UndefinedLiteral")
31
+ return { value: undefined };
32
+ return null;
33
+ },
34
+ };
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from "../plugin.js";
2
+ export declare const collectionsPlugin: Plugin;
@@ -0,0 +1,70 @@
1
+ import { current, advance } from "../parser/parser-context.js";
2
+ import { parseArrayLiteral } from "../parser/parse-array-literal.js";
3
+ import { parseObjectLiteral } from "../parser/parse-object-literal.js";
4
+ import { parseExpression } from "../parser/parse-expression.js";
5
+ export const collectionsPlugin = {
6
+ name: "collections",
7
+ parsePrefix: (ctx) => {
8
+ const tok = current(ctx);
9
+ // Array literal: [elements]
10
+ if (tok.type === "Punctuation" && tok.value === "[") {
11
+ return parseArrayLiteral(ctx);
12
+ }
13
+ // Object literal: { props }
14
+ if (tok.type === "Punctuation" && tok.value === "{") {
15
+ return parseObjectLiteral(ctx);
16
+ }
17
+ // Spread element: ...expr
18
+ if (tok.type === "Spread") {
19
+ advance(ctx);
20
+ const argument = parseExpression(ctx, 0);
21
+ return { type: "SpreadElement", argument, start: tok.start, end: argument.end };
22
+ }
23
+ return null;
24
+ },
25
+ optimize: (node, opt) => {
26
+ if (node.type === "ArrayLiteral") {
27
+ return { ...node, elements: node.elements.map((e) => opt(e)) };
28
+ }
29
+ if (node.type === "ObjectLiteral") {
30
+ return {
31
+ ...node,
32
+ properties: node.properties.map((p) => ({
33
+ ...p,
34
+ key: p.computed ? opt(p.key) : p.key,
35
+ value: opt(p.value),
36
+ })),
37
+ };
38
+ }
39
+ return null;
40
+ },
41
+ evaluate: (node, context, evalFn) => {
42
+ if (node.type === "ArrayLiteral") {
43
+ const result = [];
44
+ for (const element of node.elements) {
45
+ if (element.type === "SpreadElement") {
46
+ const spread = evalFn(element.argument, context);
47
+ result.push(...spread);
48
+ }
49
+ else {
50
+ result.push(evalFn(element, context));
51
+ }
52
+ }
53
+ return { value: result };
54
+ }
55
+ if (node.type === "ObjectLiteral") {
56
+ const result = {};
57
+ for (const prop of node.properties) {
58
+ const key = prop.computed
59
+ ? evalFn(prop.key, context)
60
+ : prop.key.type === "Identifier"
61
+ ? prop.key.name
62
+ : prop.key.value;
63
+ const value = evalFn(prop.value, context);
64
+ result[key] = value;
65
+ }
66
+ return { value: result };
67
+ }
68
+ return null;
69
+ },
70
+ };
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from "../plugin.js";
2
+ export declare const comparisonPlugin: Plugin;
@@ -0,0 +1,51 @@
1
+ import { current } from "../parser/parser-context.js";
2
+ const COMPARISON_PRECEDENCE = {
3
+ "==": 30,
4
+ "!=": 30,
5
+ "<": 40,
6
+ ">": 40,
7
+ "<=": 40,
8
+ ">=": 40,
9
+ };
10
+ export const comparisonPlugin = {
11
+ name: "comparison",
12
+ infixPrecedence: (ctx) => {
13
+ const tok = current(ctx);
14
+ if (tok.type === "Operator") {
15
+ return COMPARISON_PRECEDENCE[tok.value];
16
+ }
17
+ return undefined;
18
+ },
19
+ optimize: (node, opt) => {
20
+ if (node.type === "BinaryExpression" && node.operator in COMPARISON_PRECEDENCE) {
21
+ const left = opt(node.left);
22
+ const right = opt(node.right);
23
+ return { ...node, left, right };
24
+ }
25
+ return null;
26
+ },
27
+ evaluate: (node, context, evalFn) => {
28
+ if (node.type === "BinaryExpression") {
29
+ const op = node.operator;
30
+ if (op in COMPARISON_PRECEDENCE) {
31
+ const left = evalFn(node.left, context);
32
+ const right = evalFn(node.right, context);
33
+ switch (op) {
34
+ case "==":
35
+ return { value: left === right };
36
+ case "!=":
37
+ return { value: left !== right };
38
+ case "<":
39
+ return { value: left < right };
40
+ case ">":
41
+ return { value: left > right };
42
+ case "<=":
43
+ return { value: left <= right };
44
+ case ">=":
45
+ return { value: left >= right };
46
+ }
47
+ }
48
+ }
49
+ return null;
50
+ },
51
+ };
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from "../plugin.js";
2
+ export declare function createDateIdentifierPlugin(options: {
3
+ identifiers: string[];
4
+ }): Plugin;
@@ -0,0 +1,29 @@
1
+ function toDate(value) {
2
+ if (value instanceof Date)
3
+ return value;
4
+ if (typeof value === "string" || typeof value === "number") {
5
+ const d = new Date(value);
6
+ return isNaN(d.getTime()) ? null : d;
7
+ }
8
+ return null;
9
+ }
10
+ export function createDateIdentifierPlugin(options) {
11
+ const identifierSet = new Set(options.identifiers);
12
+ return {
13
+ name: "date-identifier",
14
+ evaluate: (node, context) => {
15
+ if (node.type !== "Identifier")
16
+ return null;
17
+ if (!identifierSet.has(node.name))
18
+ return null;
19
+ const raw = context[node.name];
20
+ const date = toDate(raw);
21
+ if (date === null) {
22
+ if (raw === undefined || raw === null)
23
+ return { value: null };
24
+ throw new Error(`Context value for "${node.name}" cannot be coerced to a Date`);
25
+ }
26
+ return { value: date };
27
+ },
28
+ };
29
+ }
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from "../plugin.js";
2
+ export declare const dateLiteralPlugin: Plugin;
@@ -0,0 +1,71 @@
1
+ import { scanString } from "../lexer/tokenize/scan-string.js";
2
+ import { current, advance } from "../parser/parser-context.js";
3
+ import { ExpressionError } from "../errors/expression-error.js";
4
+ const DATE_OPS = new Set(["==", "!=", "<", ">", "<=", ">="]);
5
+ export const dateLiteralPlugin = {
6
+ name: "date-literal",
7
+ scan(source, pos) {
8
+ if (source[pos] !== "d")
9
+ return null;
10
+ const next = source[pos + 1];
11
+ if (next !== '"' && next !== "'")
12
+ return null;
13
+ try {
14
+ const r = scanString(source, pos + 1);
15
+ // Store the full source text (d"2023-02-11") so the editor overlay renders it correctly.
16
+ return { type: "DateLiteral", value: source.slice(pos, r.end), end: r.end };
17
+ }
18
+ catch (e) {
19
+ if (e instanceof ExpressionError) {
20
+ throw new ExpressionError(e.rawMessage, { source, start: pos, end: e.end });
21
+ }
22
+ throw e;
23
+ }
24
+ },
25
+ parsePrefix(ctx) {
26
+ const tok = current(ctx);
27
+ if (tok.type !== "DateLiteral")
28
+ return null;
29
+ advance(ctx);
30
+ // tok.value is the full d"2023-02-11" — strip the d" prefix and closing quote for the AST.
31
+ const dateStr = tok.value.slice(2, -1);
32
+ return { type: "DateLiteralNode", value: dateStr, start: tok.start, end: tok.end };
33
+ },
34
+ evaluate(node, context, evalFn) {
35
+ if (node.type === "DateLiteralNode") {
36
+ const d = new Date(node.value);
37
+ if (isNaN(d.getTime())) {
38
+ throw new Error(`Invalid date literal: "${node.value}"`);
39
+ }
40
+ return { value: d };
41
+ }
42
+ // Intercept comparison operators when at least one operand is a Date.
43
+ // This must run before comparisonPlugin (place dateLiteralPlugin first in the array).
44
+ if (node.type === "BinaryExpression") {
45
+ const op = node.operator;
46
+ if (!DATE_OPS.has(op))
47
+ return null;
48
+ const left = evalFn(node.left, context);
49
+ const right = evalFn(node.right, context);
50
+ if (!(left instanceof Date) && !(right instanceof Date))
51
+ return null;
52
+ const lt = left instanceof Date ? left.getTime() : Number(left);
53
+ const rt = right instanceof Date ? right.getTime() : Number(right);
54
+ switch (op) {
55
+ case "==":
56
+ return { value: lt === rt };
57
+ case "!=":
58
+ return { value: lt !== rt };
59
+ case "<":
60
+ return { value: lt < rt };
61
+ case ">":
62
+ return { value: lt > rt };
63
+ case "<=":
64
+ return { value: lt <= rt };
65
+ case ">=":
66
+ return { value: lt >= rt };
67
+ }
68
+ }
69
+ return null;
70
+ },
71
+ };
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from "../plugin.js";
2
+ export declare const logicalPlugin: Plugin;