vsn 0.1.27 → 0.1.30

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 (244) hide show
  1. package/demo/vsn.js +1 -1
  2. package/dist/AST/ArithmeticAssignmentNode.d.ts +23 -0
  3. package/dist/AST/ArithmeticAssignmentNode.js +324 -0
  4. package/dist/AST/ArithmeticAssignmentNode.js.map +1 -0
  5. package/dist/AST/ArithmeticNode.d.ts +15 -0
  6. package/dist/AST/ArithmeticNode.js +114 -0
  7. package/dist/AST/ArithmeticNode.js.map +1 -0
  8. package/dist/AST/ArrayNode.d.ts +14 -0
  9. package/dist/AST/ArrayNode.js +114 -0
  10. package/dist/AST/ArrayNode.js.map +1 -0
  11. package/dist/AST/BlockNode.d.ts +11 -0
  12. package/dist/AST/BlockNode.js +98 -0
  13. package/dist/AST/BlockNode.js.map +1 -0
  14. package/dist/AST/BooleanLiteralNode.d.ts +5 -0
  15. package/dist/{Model/Collection.js → AST/BooleanLiteralNode.js} +12 -18
  16. package/dist/AST/BooleanLiteralNode.js.map +1 -0
  17. package/dist/AST/ComparisonNode.d.ts +15 -0
  18. package/dist/AST/ComparisonNode.js +120 -0
  19. package/dist/AST/ComparisonNode.js.map +1 -0
  20. package/dist/AST/ConditionalNode.d.ts +13 -0
  21. package/dist/AST/ConditionalNode.js +95 -0
  22. package/dist/AST/ConditionalNode.js.map +1 -0
  23. package/dist/AST/ElementAttributeNode.d.ts +18 -0
  24. package/dist/AST/ElementAttributeNode.js +159 -0
  25. package/dist/AST/ElementAttributeNode.js.map +1 -0
  26. package/dist/AST/ElementQueryNode.d.ts +13 -0
  27. package/dist/AST/ElementQueryNode.js +116 -0
  28. package/dist/AST/ElementQueryNode.js.map +1 -0
  29. package/dist/AST/ElementStyleNode.d.ts +18 -0
  30. package/dist/AST/ElementStyleNode.js +159 -0
  31. package/dist/AST/ElementStyleNode.js.map +1 -0
  32. package/dist/AST/ForStatementNode.d.ts +17 -0
  33. package/dist/AST/ForStatementNode.js +121 -0
  34. package/dist/AST/ForStatementNode.js.map +1 -0
  35. package/dist/AST/FunctionArgumentNode.d.ts +11 -0
  36. package/dist/AST/FunctionArgumentNode.js +100 -0
  37. package/dist/AST/FunctionArgumentNode.js.map +1 -0
  38. package/dist/AST/FunctionCallNode.d.ts +13 -0
  39. package/dist/AST/FunctionCallNode.js +102 -0
  40. package/dist/AST/FunctionCallNode.js.map +1 -0
  41. package/dist/AST/IfStatementNode.d.ts +14 -0
  42. package/dist/AST/IfStatementNode.js +128 -0
  43. package/dist/AST/IfStatementNode.js.map +1 -0
  44. package/dist/AST/InNode.d.ts +15 -0
  45. package/dist/AST/InNode.js +107 -0
  46. package/dist/AST/InNode.js.map +1 -0
  47. package/dist/AST/IndexNode.d.ts +16 -0
  48. package/dist/AST/IndexNode.js +126 -0
  49. package/dist/AST/IndexNode.js.map +1 -0
  50. package/dist/AST/LiteralNode.d.ts +10 -0
  51. package/dist/AST/LiteralNode.js +74 -0
  52. package/dist/AST/LiteralNode.js.map +1 -0
  53. package/dist/AST/Node.d.ts +19 -0
  54. package/dist/AST/Node.js +117 -0
  55. package/dist/AST/Node.js.map +1 -0
  56. package/dist/AST/NotNode.d.ts +12 -0
  57. package/dist/AST/NotNode.js +103 -0
  58. package/dist/AST/NotNode.js.map +1 -0
  59. package/dist/AST/NumberLiteralNode.d.ts +5 -0
  60. package/dist/{Model/fields/EmailField.js → AST/NumberLiteralNode.js} +17 -17
  61. package/dist/AST/NumberLiteralNode.js.map +1 -0
  62. package/dist/AST/ObjectNode.d.ts +14 -0
  63. package/dist/AST/ObjectNode.js +131 -0
  64. package/dist/AST/ObjectNode.js.map +1 -0
  65. package/dist/AST/RootScopeMemberNode.d.ts +11 -0
  66. package/dist/AST/RootScopeMemberNode.js +87 -0
  67. package/dist/AST/RootScopeMemberNode.js.map +1 -0
  68. package/dist/AST/ScopeMemberNode.d.ts +12 -0
  69. package/dist/AST/ScopeMemberNode.js +134 -0
  70. package/dist/AST/ScopeMemberNode.js.map +1 -0
  71. package/dist/AST/UnitLiteralNode.d.ts +15 -0
  72. package/dist/AST/UnitLiteralNode.js +72 -0
  73. package/dist/AST/UnitLiteralNode.js.map +1 -0
  74. package/dist/AST.d.ts +7 -60
  75. package/dist/AST.js +74 -1493
  76. package/dist/AST.js.map +1 -1
  77. package/dist/Controller.d.ts +4 -2
  78. package/dist/Controller.js +10 -2
  79. package/dist/Controller.js.map +1 -1
  80. package/dist/EventDispatcher.d.ts +4 -1
  81. package/dist/EventDispatcher.js +27 -12
  82. package/dist/EventDispatcher.js.map +1 -1
  83. package/dist/MessageList.d.ts +2 -1
  84. package/dist/MessageList.js +9 -1
  85. package/dist/MessageList.js.map +1 -1
  86. package/dist/Model/Field.d.ts +8 -0
  87. package/dist/Model/{fields/StringField.js → Field.js} +19 -24
  88. package/dist/Model/Field.js.map +1 -0
  89. package/dist/Model.d.ts +5 -4
  90. package/dist/Model.js +7 -18
  91. package/dist/Model.js.map +1 -1
  92. package/dist/Registry.d.ts +3 -0
  93. package/dist/Registry.js +11 -0
  94. package/dist/Registry.js.map +1 -1
  95. package/dist/Scope/DynamicScopeData.d.ts +6 -0
  96. package/dist/{Model/DataModel.js → Scope/DynamicScopeData.js} +15 -17
  97. package/dist/Scope/DynamicScopeData.js.map +1 -0
  98. package/dist/Scope/QueryReference.d.ts +10 -0
  99. package/dist/Scope/QueryReference.js +103 -0
  100. package/dist/Scope/QueryReference.js.map +1 -0
  101. package/dist/Scope/ScopeData.d.ts +4 -0
  102. package/dist/Scope/ScopeData.js +40 -0
  103. package/dist/Scope/ScopeData.js.map +1 -0
  104. package/dist/Scope/ScopeDataAbstract.d.ts +22 -0
  105. package/dist/Scope/ScopeDataAbstract.js +138 -0
  106. package/dist/Scope/ScopeDataAbstract.js.map +1 -0
  107. package/dist/Scope/ScopeReference.d.ts +10 -0
  108. package/dist/Scope/ScopeReference.js +73 -0
  109. package/dist/Scope/ScopeReference.js.map +1 -0
  110. package/dist/Scope/ScopedVariableType.d.ts +6 -0
  111. package/dist/Scope/ScopedVariableType.js +14 -0
  112. package/dist/Scope/ScopedVariableType.js.map +1 -0
  113. package/dist/Scope/WrappedArray.d.ts +16 -0
  114. package/dist/Scope/WrappedArray.js +121 -0
  115. package/dist/Scope/WrappedArray.js.map +1 -0
  116. package/dist/Scope/properties/Property.d.ts +18 -0
  117. package/dist/Scope/properties/Property.js +93 -0
  118. package/dist/Scope/properties/Property.js.map +1 -0
  119. package/dist/Scope.d.ts +4 -45
  120. package/dist/Scope.js +31 -266
  121. package/dist/Scope.js.map +1 -1
  122. package/dist/SimplePromise.d.ts +2 -2
  123. package/dist/SimplePromise.js.map +1 -1
  124. package/dist/Tag/List.d.ts +2 -2
  125. package/dist/Tag/List.js +14 -6
  126. package/dist/Tag/List.js.map +1 -1
  127. package/dist/Tag.js +1 -1
  128. package/dist/Tag.js.map +1 -1
  129. package/dist/Types.d.ts +1 -0
  130. package/dist/Types.js +8 -2
  131. package/dist/Types.js.map +1 -1
  132. package/dist/Validators.d.ts +7 -0
  133. package/dist/Validators.js +54 -0
  134. package/dist/Validators.js.map +1 -0
  135. package/dist/attributes/Bind.js +1 -1
  136. package/dist/attributes/Bind.js.map +1 -1
  137. package/dist/attributes/ClassConstructor.d.ts +1 -0
  138. package/dist/attributes/ClassConstructor.js +1 -1
  139. package/dist/attributes/ClassConstructor.js.map +1 -1
  140. package/dist/attributes/JSONAttribute.js.map +1 -1
  141. package/dist/attributes/List.js +4 -4
  142. package/dist/attributes/List.js.map +1 -1
  143. package/dist/attributes/Radio.js.map +1 -1
  144. package/dist/attributes/SetAttribute.js.map +1 -1
  145. package/dist/attributes/StyleAttribute.js.map +1 -1
  146. package/dist/vsn.d.ts +9 -1
  147. package/dist/vsn.js +24 -9
  148. package/dist/vsn.js.map +1 -1
  149. package/package.json +1 -1
  150. package/src/AST/ArithmeticAssignmentNode.ts +243 -0
  151. package/src/AST/ArithmeticNode.ts +52 -0
  152. package/src/AST/ArrayNode.ts +39 -0
  153. package/src/AST/BlockNode.ts +25 -0
  154. package/src/AST/BooleanLiteralNode.ts +10 -0
  155. package/src/AST/ComparisonNode.ts +57 -0
  156. package/src/AST/ConditionalNode.ts +36 -0
  157. package/src/AST/ElementAttributeNode.ts +63 -0
  158. package/src/AST/ElementQueryNode.ts +27 -0
  159. package/src/AST/ElementStyleNode.ts +63 -0
  160. package/src/AST/ForStatementNode.ts +59 -0
  161. package/src/AST/FunctionArgumentNode.ts +27 -0
  162. package/src/AST/FunctionCallNode.ts +32 -0
  163. package/src/AST/IfStatementNode.ts +67 -0
  164. package/src/AST/InNode.ts +46 -0
  165. package/src/AST/IndexNode.ts +61 -0
  166. package/src/AST/LiteralNode.ts +17 -0
  167. package/src/AST/Node.ts +71 -0
  168. package/src/AST/NotNode.ts +41 -0
  169. package/src/AST/NumberLiteralNode.ts +14 -0
  170. package/src/AST/ObjectNode.ts +55 -0
  171. package/src/AST/RootScopeMemberNode.ts +25 -0
  172. package/src/AST/ScopeMemberNode.ts +58 -0
  173. package/src/AST/UnitLiteralNode.ts +51 -0
  174. package/src/AST.ts +34 -1094
  175. package/src/Controller.ts +10 -2
  176. package/src/EventDispatcher.ts +29 -12
  177. package/src/MessageList.ts +5 -1
  178. package/src/Model/Field.ts +20 -0
  179. package/src/Model.ts +8 -22
  180. package/src/Registry.ts +10 -0
  181. package/src/{Model/DataModel.ts → Scope/DynamicScopeData.ts} +8 -10
  182. package/src/Scope/QueryReference.ts +29 -0
  183. package/src/Scope/ScopeData.ts +21 -0
  184. package/src/Scope/ScopeDataAbstract.ts +127 -0
  185. package/src/Scope/ScopeReference.ts +30 -0
  186. package/src/Scope/ScopedVariableType.ts +7 -0
  187. package/src/Scope/WrappedArray.ts +88 -0
  188. package/src/Scope/properties/Property.ts +79 -0
  189. package/src/Scope.ts +28 -194
  190. package/src/SimplePromise.ts +2 -2
  191. package/src/Tag/List.ts +4 -4
  192. package/src/Tag.ts +1 -1
  193. package/src/Types.ts +7 -2
  194. package/src/Validators.ts +45 -0
  195. package/src/attributes/Bind.ts +3 -3
  196. package/src/attributes/ClassConstructor.ts +2 -1
  197. package/src/attributes/JSONAttribute.ts +2 -1
  198. package/src/attributes/List.ts +1 -1
  199. package/src/attributes/Radio.ts +2 -1
  200. package/src/attributes/ScopeChange.ts +1 -1
  201. package/src/attributes/SetAttribute.ts +2 -1
  202. package/src/attributes/StyleAttribute.ts +2 -1
  203. package/src/attributes/TypeAttribute.ts +1 -1
  204. package/src/vsn.ts +14 -4
  205. package/test/AST/ArithmeticAssignmentNode.spec.ts +47 -0
  206. package/test/AST.spec.ts +2 -2
  207. package/test/Controller.spec.ts +44 -0
  208. package/test/MessageList.spec.ts +1 -1
  209. package/test/Model/DataModel.spec.ts +0 -141
  210. package/test/Scope/DynamicScopeData.spec.ts +141 -0
  211. package/test/Scope.spec.ts +13 -1
  212. package/test/Tag/TagList.spec.ts +1 -1
  213. package/dist/Model/Collection.d.ts +0 -5
  214. package/dist/Model/Collection.js.map +0 -1
  215. package/dist/Model/DataModel.d.ts +0 -6
  216. package/dist/Model/DataModel.js.map +0 -1
  217. package/dist/Model/ModelAbstract.d.ts +0 -20
  218. package/dist/Model/ModelAbstract.js +0 -122
  219. package/dist/Model/ModelAbstract.js.map +0 -1
  220. package/dist/Model/fields/BooleanField.d.ts +0 -5
  221. package/dist/Model/fields/BooleanField.js +0 -43
  222. package/dist/Model/fields/BooleanField.js.map +0 -1
  223. package/dist/Model/fields/EmailField.d.ts +0 -5
  224. package/dist/Model/fields/EmailField.js.map +0 -1
  225. package/dist/Model/fields/Field.d.ts +0 -13
  226. package/dist/Model/fields/Field.js +0 -79
  227. package/dist/Model/fields/Field.js.map +0 -1
  228. package/dist/Model/fields/FloatField.d.ts +0 -5
  229. package/dist/Model/fields/FloatField.js +0 -47
  230. package/dist/Model/fields/FloatField.js.map +0 -1
  231. package/dist/Model/fields/PositiveNumberField.d.ts +0 -5
  232. package/dist/Model/fields/PositiveNumberField.js +0 -51
  233. package/dist/Model/fields/PositiveNumberField.js.map +0 -1
  234. package/dist/Model/fields/StringField.d.ts +0 -5
  235. package/dist/Model/fields/StringField.js.map +0 -1
  236. package/src/Model/Collection.ts +0 -13
  237. package/src/Model/ModelAbstract.ts +0 -114
  238. package/src/Model/fields/BooleanField.ts +0 -16
  239. package/src/Model/fields/EmailField.ts +0 -12
  240. package/src/Model/fields/Field.ts +0 -65
  241. package/src/Model/fields/FloatField.ts +0 -22
  242. package/src/Model/fields/PositiveNumberField.ts +0 -24
  243. package/src/Model/fields/StringField.ts +0 -16
  244. package/test/Model.spec.ts +0 -306
@@ -0,0 +1,27 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {TreeNode} from "../AST";
5
+ import {Node} from "./Node";
6
+
7
+ export class FunctionArgumentNode<T = any> extends Node implements TreeNode {
8
+ constructor(
9
+ protected args: Node[]
10
+ ) {
11
+ super();
12
+ }
13
+
14
+ protected _getChildNodes(): Node[] {
15
+ return [
16
+ ...(this.args as Node[])
17
+ ]
18
+ }
19
+
20
+ async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
21
+ const values: any[] = [];
22
+ for (const arg of this.args) {
23
+ values.push(await arg.evaluate(scope, dom, tag));
24
+ }
25
+ return values;
26
+ }
27
+ }
@@ -0,0 +1,32 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {TreeNode} from "../AST";
5
+ import {Node} from "./Node";
6
+ import {FunctionArgumentNode} from "./FunctionArgumentNode";
7
+ import {ScopeMemberNode} from "./ScopeMemberNode";
8
+
9
+ export class FunctionCallNode<T = any> extends Node implements TreeNode {
10
+ constructor(
11
+ public readonly fnc: TreeNode<(...args: any[]) => any>,
12
+ public readonly args: FunctionArgumentNode<any[]>
13
+ ) {
14
+ super();
15
+ }
16
+
17
+ protected _getChildNodes(): Node[] {
18
+ return [
19
+ this.fnc as Node,
20
+ this.args as Node
21
+ ]
22
+ }
23
+
24
+ public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
25
+ let functionScope: Scope = scope;
26
+ if (this.fnc instanceof ScopeMemberNode) {
27
+ functionScope = await this.fnc.scope.evaluate(scope, dom, tag);
28
+ }
29
+ const values = await this.args.evaluate(scope, dom, tag);
30
+ return (await this.fnc.evaluate(scope, dom, tag)).call(functionScope.wrapped || functionScope, ...values);
31
+ }
32
+ }
@@ -0,0 +1,67 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {Token, TokenType, Tree, TreeNode} from "../AST";
5
+ import {Node} from "./Node";
6
+ import {ConditionalNode} from "./ConditionalNode";
7
+ import {LiteralNode} from "./LiteralNode";
8
+
9
+ export class IfStatementNode extends Node implements TreeNode {
10
+ constructor(
11
+ protected nodes: ConditionalNode[]
12
+ ) {
13
+ super();
14
+ }
15
+
16
+ protected _getChildNodes(): Node[] {
17
+ return [
18
+ ...(this.nodes as Node[])
19
+ ]
20
+ }
21
+
22
+ public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
23
+ for (const condition of this.nodes) {
24
+ const uno: boolean = await condition.evaluate(scope, dom, tag);
25
+ if (uno) {
26
+ return await condition.block.evaluate(scope, dom, tag);
27
+ }
28
+ }
29
+ }
30
+
31
+ public static parseConditional(tokens: Token[]): ConditionalNode {
32
+ if ([
33
+ TokenType.IF,
34
+ TokenType.ELSE_IF
35
+ ].indexOf(tokens[0].type) === -1) {
36
+ throw SyntaxError('Invalid Syntax');
37
+ }
38
+
39
+ tokens.splice(0, 1); // consume if and else if
40
+ return new ConditionalNode(
41
+ Tree.processTokens(Tree.getBlockTokens(tokens, null)[0]),
42
+ Tree.processTokens(Tree.getBlockTokens(tokens, null)[0])
43
+ );
44
+ }
45
+
46
+ public static parse(lastNode, token, tokens: Token[]): IfStatementNode {
47
+ if (tokens[1].type !== TokenType.L_PAREN) {
48
+ throw SyntaxError('If statement needs to be followed by a condition encased in parenthesis.');
49
+ }
50
+ const nodes: ConditionalNode[] = [];
51
+ nodes.push(IfStatementNode.parseConditional(tokens));
52
+
53
+ while(tokens.length > 0 && TokenType.ELSE_IF === tokens[0].type) {
54
+ nodes.push(IfStatementNode.parseConditional(tokens));
55
+ }
56
+
57
+ if (tokens.length > 0 && TokenType.ELSE === tokens[0].type) {
58
+ tokens.splice(0, 1); // Consume else
59
+ nodes.push(new ConditionalNode(
60
+ new LiteralNode(true),
61
+ Tree.processTokens(Tree.getBlockTokens(tokens, null)[0])
62
+ ))
63
+ }
64
+
65
+ return new IfStatementNode(nodes);
66
+ }
67
+ }
@@ -0,0 +1,46 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {Token, TokenType, Tree, TreeNode} from "../AST";
5
+ import {Node} from "./Node";
6
+
7
+ export class InNode extends Node implements TreeNode {
8
+ constructor(
9
+ public readonly left: TreeNode,
10
+ public readonly right: TreeNode,
11
+ public readonly flip: boolean = false
12
+ ) {
13
+ super();
14
+ }
15
+
16
+ public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
17
+ const toCheck = await this.left.evaluate(scope, dom, tag);
18
+ const array = await this.right.evaluate(scope, dom, tag);
19
+
20
+ let inArray = array.indexOf(toCheck) > -1;
21
+ if (this.flip)
22
+ inArray = !inArray;
23
+ return inArray;
24
+ }
25
+
26
+ protected _getChildNodes(): Node[] {
27
+ return [
28
+ this.left as Node,
29
+ this.right as Node
30
+ ];
31
+ }
32
+
33
+ public static match(tokens: Token[]): boolean {
34
+ return tokens[0].type === TokenType.IN || (tokens[0].type === TokenType.NOT && tokens[1].type === TokenType.IN);
35
+ }
36
+
37
+ public static parse(lastNode, token, tokens: Token[]) {
38
+ const flip: boolean = tokens[0].type === TokenType.NOT;
39
+ if (flip)
40
+ tokens.splice(0, 1); // consume not
41
+ tokens.splice(0, 1); // consume in
42
+
43
+ const containedTokens = Tree.getNextStatementTokens(tokens, false, false, true);
44
+ return new InNode(lastNode, Tree.processTokens(containedTokens), flip);
45
+ }
46
+ }
@@ -0,0 +1,61 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {Token, TokenType, Tree, TreeNode} from "../AST";
5
+ import {Node} from "./Node";
6
+
7
+ export class IndexNode extends Node implements TreeNode {
8
+ constructor(
9
+ public readonly object: Node,
10
+ public readonly index: Node,
11
+ public readonly indexTwo: Node = null
12
+ ) {
13
+ super();
14
+ }
15
+
16
+ protected _getChildNodes(): Node[] {
17
+ const children = [
18
+ this.object,
19
+ this.index
20
+ ];
21
+ if (this.indexTwo)
22
+ children.push(this.indexTwo);
23
+
24
+ return children;
25
+ }
26
+
27
+ public negativeIndex(obj: any[], index: number | string): number | string {
28
+ if (Number.isFinite(index) && index < 0)
29
+ return obj.length + (index as number);
30
+ return index;
31
+ }
32
+
33
+ async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
34
+ const obj = await this.object.evaluate(scope, dom, tag);
35
+ const index: string | number = this.negativeIndex(obj, await this.index.evaluate(scope, dom, tag));
36
+
37
+ if (Number.isFinite(index) && this.indexTwo) {
38
+ const indexTwo: number = this.negativeIndex(obj, await this.indexTwo.evaluate(scope, dom, tag)) as number;
39
+ const values = [];
40
+ for (let i: number = index as number; i <= indexTwo; i++) {
41
+ values.push(obj[i]);
42
+ }
43
+ return values;
44
+ } else {
45
+ return (obj)[index];
46
+ }
47
+ }
48
+
49
+ public static match(tokens: Token[]): boolean {
50
+ return tokens[0].type === TokenType.L_BRACKET;
51
+ }
52
+
53
+ public static parse(lastNode, token, tokens: Token[]): IndexNode {
54
+ const valueTokens: Token[][] = Tree.getBlockTokens(tokens, TokenType.COLON);
55
+ const values: Node[] = [];
56
+ for (const arg of valueTokens) {
57
+ values.push(Tree.processTokens(arg));
58
+ }
59
+ return new IndexNode(lastNode, values[0], values.length > 1 && values[1]);
60
+ }
61
+ }
@@ -0,0 +1,17 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {TreeNode} from "../AST";
5
+ import {Node} from "./Node";
6
+
7
+ export class LiteralNode<T = any> extends Node implements TreeNode {
8
+ constructor(
9
+ public readonly value: T
10
+ ) {
11
+ super();
12
+ }
13
+
14
+ public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
15
+ return this.value;
16
+ }
17
+ }
@@ -0,0 +1,71 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {TreeNode} from "../AST";
5
+
6
+ export abstract class Node implements TreeNode {
7
+ protected requiresPrep: boolean = false;
8
+ protected _isPreparationRequired: boolean;
9
+ protected childNodes: Node[];
10
+ protected nodeCache: {[key: string]: Node[]} = {};
11
+ abstract evaluate(scope: Scope, dom: DOM, tag?: Tag);
12
+
13
+ isPreparationRequired(): boolean {
14
+ if (this.requiresPrep)
15
+ return true;
16
+
17
+ if (this._isPreparationRequired !== undefined)
18
+ return this._isPreparationRequired;
19
+
20
+ for (const node of this.getChildNodes()) {
21
+ if (node.isPreparationRequired()) {
22
+ this._isPreparationRequired = true;
23
+ return true;
24
+ }
25
+ }
26
+
27
+ return false;
28
+ }
29
+
30
+ async prepare(scope: Scope, dom: DOM, tag: Tag = null) {
31
+ for (const node of this.getChildNodes()) {
32
+ await node.prepare(scope, dom, tag);
33
+ }
34
+ }
35
+
36
+ protected _getChildNodes(): Node[] {
37
+ return [];
38
+ }
39
+
40
+ getChildNodes(): Node[] {
41
+ if (this.childNodes === undefined) {
42
+ this.childNodes = this._getChildNodes();
43
+ }
44
+ return this.childNodes;
45
+ }
46
+
47
+ findChildrenByType<T = Node>(t: any): T[] {
48
+ return this.findChildrenByTypes([t]);
49
+ }
50
+
51
+ findChildrenByTypes<T = Node>(types: any[], cacheKey: string = null): T[] {
52
+ if (cacheKey !== null && this.nodeCache[cacheKey])
53
+ return this.nodeCache[cacheKey] as any;
54
+
55
+ const nodes: T[] = [];
56
+ for (const child of this.getChildNodes()) {
57
+ for (const t of types) {
58
+ if (child instanceof t)
59
+ nodes.push(child as any as T);
60
+ const childNodes: T[] = child.findChildrenByType<T>(t);
61
+ nodes.push(...childNodes);
62
+ }
63
+ }
64
+
65
+ if (cacheKey !== null)
66
+ this.nodeCache[cacheKey] = nodes as any;
67
+
68
+ return nodes;
69
+ }
70
+ }
71
+
@@ -0,0 +1,41 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {Token, TokenType, Tree, TreeNode} from "../AST";
5
+ import {Node} from "./Node";
6
+
7
+ export class NotNode extends Node implements TreeNode {
8
+ constructor(
9
+ public readonly toFlip: Node
10
+ ) {
11
+ super();
12
+ }
13
+
14
+ public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
15
+ const flipping = await this.toFlip.evaluate(scope, dom, tag);
16
+ return !flipping;
17
+ }
18
+
19
+ protected _getChildNodes(): Node[] {
20
+ return [
21
+ this.toFlip
22
+ ];
23
+ }
24
+
25
+ public static parse(lastNode, token, tokens: Token[]) {
26
+ tokens.splice(0, 1); // Remove not operator
27
+ let containedTokens;
28
+ if (tokens[0].type === TokenType.L_PAREN) {
29
+ containedTokens = Tree.getNextStatementTokens(tokens);
30
+ } else {
31
+ containedTokens = Tree.consumeTypes(tokens, [
32
+ TokenType.BOOLEAN_LITERAL,
33
+ TokenType.NUMBER_LITERAL,
34
+ TokenType.STRING_LITERAL,
35
+ TokenType.NAME,
36
+ TokenType.PERIOD
37
+ ]);
38
+ }
39
+ return new NotNode(Tree.processTokens(containedTokens));
40
+ }
41
+ }
@@ -0,0 +1,14 @@
1
+ import {LiteralNode} from "./LiteralNode";
2
+
3
+ export class NumberLiteralNode extends LiteralNode<number> {
4
+ constructor(
5
+ public readonly value: any
6
+ ) {
7
+ super(value);
8
+ if (this.value.indexOf('.') > -1) {
9
+ this.value = parseFloat(this.value)
10
+ } else {
11
+ this.value = parseInt(this.value);
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,55 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {BlockType, Token, TokenType, Tree, TreeNode} from "../AST";
5
+ import {Node} from "./Node";
6
+
7
+ export class ObjectNode extends Node implements TreeNode {
8
+ constructor(
9
+ public readonly keys: Node[],
10
+ public readonly values: Node[]
11
+ ) {
12
+ super();
13
+ }
14
+
15
+ protected _getChildNodes(): Node[] {
16
+ return new Array(...this.values);
17
+ }
18
+
19
+ async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
20
+ const obj: Scope = new Scope();
21
+ for (let i = 0; i < this.values.length; i++) {
22
+ const key = this.keys[i];
23
+ const val = this.values[i];
24
+ obj.set(await key.evaluate(scope, dom, tag), await val.evaluate(scope, dom, tag));
25
+ }
26
+ return obj;
27
+ }
28
+
29
+ public static match(tokens: Token[]): boolean {
30
+ return tokens[0].type === TokenType.L_BRACE;
31
+ }
32
+
33
+ public static parse(lastNode, token, tokens: Token[]): ObjectNode {
34
+ const valueTokens: Token[] = Tree.getNextStatementTokens(tokens);
35
+ const keys: Node[] = [];
36
+ const values: Node[] = [];
37
+
38
+ while (valueTokens.length > 0) {
39
+ const key: Token[] = Tree.getTokensUntil(valueTokens, TokenType.COLON, false);
40
+ if (valueTokens[0].type !== TokenType.COLON)
41
+ throw Error('Invalid object literal syntax. Expecting :');
42
+ valueTokens.splice(0, 1); // Consume :
43
+ const val: Token[] = Tree.getTokensUntil(valueTokens, TokenType.COMMA, true, false, true, {
44
+ type: BlockType.STATEMENT,
45
+ open: null,
46
+ close: null,
47
+ openCharacter: null,
48
+ closeCharacter: null
49
+ });
50
+ keys.push(Tree.processTokens(key));
51
+ values.push(Tree.processTokens(val));
52
+ }
53
+ return new ObjectNode(keys, values);
54
+ }
55
+ }
@@ -0,0 +1,25 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {TreeNode} from "../AST";
5
+ import {Node} from "./Node";
6
+
7
+ export class RootScopeMemberNode<T = any> extends Node implements TreeNode {
8
+ constructor(
9
+ public readonly name: TreeNode<string>
10
+ ) {
11
+ super();
12
+ }
13
+
14
+ protected _getChildNodes(): Node[] {
15
+ return [
16
+ this.name as Node
17
+ ]
18
+ }
19
+
20
+ async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
21
+ const name = await this.name.evaluate(scope, dom, tag);
22
+ const value = scope.get(name);
23
+ return value instanceof Scope && value.wrapped || value;
24
+ }
25
+ }
@@ -0,0 +1,58 @@
1
+ import {Scope} from "../Scope";
2
+ import {DOM} from "../DOM";
3
+ import {Tag} from "../Tag";
4
+ import {TagList} from "../Tag/List";
5
+ import {DOMObject} from "../DOM/DOMObject";
6
+ import {TreeNode} from "../AST";
7
+ import {Node} from "./Node";
8
+ import {ElementQueryNode} from "./ElementQueryNode";
9
+
10
+ export class ScopeMemberNode extends Node implements TreeNode {
11
+ constructor(
12
+ public readonly scope: TreeNode<Scope>,
13
+ public readonly name: TreeNode<string>
14
+ ) {
15
+ super();
16
+ }
17
+
18
+ protected _getChildNodes(): Node[] {
19
+ return [
20
+ this.scope as Node,
21
+ this.name as Node
22
+ ]
23
+ }
24
+
25
+ async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
26
+ let scopes = [];
27
+ const values = [];
28
+
29
+ if (this.scope instanceof ElementQueryNode) {
30
+ const elements = await this.scope.evaluate(scope, dom, tag);
31
+ if (this.scope.first) {
32
+ scopes.push(elements);
33
+ } else {
34
+ scopes = elements;
35
+ }
36
+ } else {
37
+ const evalScope = await this.scope.evaluate(scope, dom, tag);
38
+ if (evalScope instanceof TagList) {
39
+ scopes = evalScope;
40
+ } else {
41
+ scopes.push(evalScope);
42
+ }
43
+ }
44
+
45
+ for (let parent of scopes) {
46
+ if (parent instanceof DOMObject)
47
+ parent = parent.scope;
48
+
49
+ if (!parent) {
50
+ throw Error(`Cannot access "${await this.name.evaluate(scope, dom, tag)}" of undefined.`);
51
+ }
52
+ const name = await this.name.evaluate(scope, dom, tag);
53
+ const value: any = parent.get(name, false);
54
+ values.push(value instanceof Scope && value.wrapped || value);
55
+ }
56
+ return values.length === 1 ? values[0] : values;
57
+ }
58
+ }
@@ -0,0 +1,51 @@
1
+ import {LiteralNode} from "./LiteralNode";
2
+
3
+ export class UnitLiteral {
4
+ protected _amount: number;
5
+ protected _unit: string;
6
+
7
+ constructor(
8
+ protected _value: any
9
+ ) {
10
+ this.value = this._value;
11
+ }
12
+
13
+ get amount(): number {
14
+ return this._amount;
15
+ }
16
+
17
+ get unit(): string {
18
+ return this._unit;
19
+ }
20
+
21
+ get value(): string {
22
+ return `${this._amount}${this._unit}`;
23
+ }
24
+
25
+ set value(value: string) {
26
+ if (value.indexOf('.') > -1) {
27
+ this._amount = parseFloat(value)
28
+ } else {
29
+ this._amount = parseInt(value);
30
+ }
31
+
32
+ if (isNaN(this._amount))
33
+ this._amount = 0;
34
+
35
+ const unit = /[^\d.]+$/.exec(value);
36
+ this._unit = unit && unit[0] || '';
37
+ }
38
+
39
+ public toString() {
40
+ return this.value;
41
+ }
42
+ }
43
+
44
+
45
+ export class UnitLiteralNode extends LiteralNode<UnitLiteral> {
46
+ constructor(
47
+ _value: any
48
+ ) {
49
+ super(new UnitLiteral(_value));
50
+ }
51
+ }