vsn 0.1.58 → 0.1.59

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vsn",
3
- "version": "0.1.58",
3
+ "version": "0.1.59",
4
4
  "description": "SEO Friendly Javascript/Typescript Framework",
5
5
  "keywords": [
6
6
  "framework",
@@ -1,17 +1,17 @@
1
1
  import {Scope} from "../Scope";
2
2
  import {DOM} from "../DOM";
3
3
  import {Tag} from "../Tag";
4
- import {Token, TreeNode} from "../AST";
4
+ import {Token, Tree, TreeNode} from "../AST";
5
5
  import {Node} from "./Node";
6
- import {LiteralNode} from "./LiteralNode";
7
- import {RootScopeMemberNode} from "./RootScopeMemberNode";
8
- import {ScopeMemberNode} from "./ScopeMemberNode";
6
+ import {BlockNode} from "./BlockNode";
9
7
 
10
8
  export class FunctionNode extends Node implements TreeNode {
9
+ protected requiresPrep: boolean = true;
10
+
11
11
  constructor(
12
- public readonly name: LiteralNode<string>,
13
- public readonly variables: LiteralNode<string>[],
14
- public readonly block: RootScopeMemberNode | ScopeMemberNode,
12
+ public readonly name: string,
13
+ public readonly args: string[],
14
+ public readonly block: BlockNode
15
15
  ) {
16
16
  super();
17
17
  }
@@ -22,10 +22,29 @@ export class FunctionNode extends Node implements TreeNode {
22
22
  ];
23
23
  }
24
24
 
25
- public async prepare(scope: Scope, dom: DOM, tag: Tag = null) {}
26
- public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {}
25
+ public async prepare(scope: Scope, dom: DOM, tag: Tag = null) {
26
+ scope.set(this.name, async (...args) => {
27
+ const functionScope = new Scope(scope);
28
+ for (const arg of this.args) {
29
+ functionScope.set(arg, args.shift());
30
+ }
31
+ return await this.evaluate(functionScope, dom, tag);
32
+ });
33
+ }
34
+
35
+ public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
36
+ return await this.block.evaluate(scope, dom, tag);
37
+ }
27
38
 
28
39
  public static parse(lastNode, token, tokens: Token[]): FunctionNode {
29
- return new FunctionNode(null, null, null);
40
+ tokens.shift(); // skip 'func'
41
+ const name = tokens.shift();
42
+ const argTokens = Tree.getBlockTokens(tokens);
43
+ const funcArgs: string[] = [];
44
+ for (const t of argTokens) {
45
+ funcArgs.push(t[0].value);
46
+ }
47
+ const block = Tree.processTokens(Tree.getBlockTokens(tokens, null)[0]);
48
+ return new FunctionNode(name.value, funcArgs, block);
30
49
  }
31
50
  }
package/src/AST.ts CHANGED
@@ -26,6 +26,7 @@ import {BooleanLiteralNode} from "./AST/BooleanLiteralNode";
26
26
  import {NotNode} from "./AST/NotNode";
27
27
  import {XHRNode} from "./AST/XHRNode";
28
28
  import {StringFormatNode} from "./AST/StringFormatNode";
29
+ import {FunctionNode} from "./AST/FunctionNode";
29
30
 
30
31
  function lower(str: string): string {
31
32
  return str ? str.toLowerCase() : null;
@@ -65,6 +66,7 @@ export enum TokenType {
65
66
  IF,
66
67
  ELSE_IF,
67
68
  ELSE,
69
+ FUNC,
68
70
  NAME,
69
71
  L_BRACE,
70
72
  R_BRACE,
@@ -194,6 +196,10 @@ const TOKEN_PATTERNS: TokenPattern[] = [
194
196
  type: TokenType.ELSE,
195
197
  pattern: /^else\s?(?=\{)/
196
198
  },
199
+ {
200
+ type: TokenType.FUNC,
201
+ pattern: /^func\s/
202
+ },
197
203
  {
198
204
  type: TokenType.ELEMENT_ATTRIBUTE,
199
205
  pattern: /^\.?@[-_a-zA-Z0-9]*/
@@ -482,6 +488,10 @@ export class Tree {
482
488
  node = ForStatementNode.parse(node, token, tokens);
483
489
  blockNodes.push(node);
484
490
  node = null;
491
+ } else if (token.type === TokenType.FUNC) {
492
+ node = FunctionNode.parse(node, token, tokens);
493
+ blockNodes.push(node);
494
+ node = null;
485
495
  } else if (StringFormatNode.match(tokens)) {
486
496
  node = StringFormatNode.parse(node, tokens[0], tokens);
487
497
  } else if (token.type === TokenType.STRING_LITERAL) {
@@ -7,8 +7,12 @@ export class Exec extends Attribute {
7
7
  public static readonly canDefer: boolean = false;
8
8
  protected tree: Tree;
9
9
 
10
+ public get code() {
11
+ return this.getAttributeValue();
12
+ }
13
+
10
14
  public async compile() {
11
- this.tree = new Tree(this.getAttributeValue());
15
+ this.tree = new Tree(this.code);
12
16
  await this.tree.prepare(this.tag.scope, this.tag.dom, this.tag);
13
17
  await super.compile();
14
18
  }
@@ -0,0 +1,9 @@
1
+ import {Registry} from "../Registry";
2
+ import {Exec} from "./Exec";
3
+
4
+ @Registry.attribute('vsn-script')
5
+ export class ScriptAttribute extends Exec {
6
+ public get code() {
7
+ return this.tag.element.innerText;
8
+ }
9
+ }
@@ -16,7 +16,6 @@ export class StandardAttribute extends Attribute {
16
16
  }
17
17
 
18
18
  public async connect() {
19
- this.tag.scope.on(`change:${this.key}`, (v) => { console.log('updated', v);});
20
19
  this.tag.scope.on(`change:${this.key}`, this.updateTo.bind(this));
21
20
  await super.connect();
22
21
  }
@@ -19,6 +19,7 @@ export {Referenced} from "./Referenced";
19
19
  export {RootAttribute} from "./RootAttribute";
20
20
  export {ScopeAttribute} from "./ScopeAttribute";
21
21
  export {ScopeChange} from "./ScopeChange";
22
+ export {ScriptAttribute} from "./ScriptAttribute";
22
23
  export {SetAttribute} from "./SetAttribute";
23
24
  export {StandardAttribute} from "./StandardAttribute";
24
25
  export {StyleAttribute} from "./StyleAttribute";
@@ -0,0 +1,14 @@
1
+ import {Tree} from "../../src/AST";
2
+ import {Scope} from "../../src/Scope";
3
+
4
+
5
+ describe('FunctionNode', () => {
6
+ it("properly define a simple function", async () => {
7
+ const tree = new Tree(`func add(a, b) { return a + b; }; add(1, 2);`);
8
+ const scope = new Scope();
9
+ await tree.prepare(scope, null, null);
10
+ expect(scope.get('add')).toBeDefined();
11
+ const v = await tree.evaluate(scope, null, null);
12
+ expect(v).toBe(3);
13
+ });
14
+ });