htmv 0.0.42 → 0.0.43

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.
@@ -35,17 +35,20 @@ export function parse(tokens) {
35
35
  const tag = token.tag.toLowerCase();
36
36
  i++;
37
37
  if (tag === "for") {
38
- const nextToken = tokens[i]; //should be arguments token
38
+ const itemNameToken = tokens[i];
39
+ if (itemNameToken?.type !== "arguments")
40
+ throw new Error("Missing item name in for");
41
+ const itemName = itemNameToken.value;
42
+ i++;
43
+ const inToken = tokens[i];
44
+ if (inToken?.type !== "arguments" || inToken.value !== "in")
45
+ throw new Error("Expected reserved word in");
46
+ i++;
47
+ const listNameToken = tokens[i];
48
+ if (listNameToken?.type !== "arguments")
49
+ throw new Error("Expected list name in for");
50
+ const listName = listNameToken.value;
39
51
  i++;
40
- if (nextToken?.type !== "arguments")
41
- throw new Error("Missing arguments in for");
42
- const [itemName, _in, listName] = nextToken.value;
43
- if (itemName === undefined ||
44
- _in === undefined ||
45
- listName === undefined)
46
- throw new Error("Incorrect amount of arguments in for. Expected 3 arguments");
47
- if (_in !== "in")
48
- throw new Error("Expected reserved word in.");
49
52
  const children = parseChildren(tag);
50
53
  nodes.push({
51
54
  type: "for",
@@ -71,23 +74,28 @@ export function parse(tokens) {
71
74
  });
72
75
  continue;
73
76
  }
74
- const nextToken = tokens[i]; //may be arguments token
75
- if (nextToken?.type === "arguments") {
76
- nodes.push({
77
- type: "text",
78
- text: `<${tag} `,
79
- });
77
+ nodes.push({
78
+ type: "text",
79
+ text: `<${tag} `,
80
+ });
81
+ let nextToken = tokens[i];
82
+ while (nextToken?.type === "arguments") {
80
83
  parseArgs(nextToken.value);
84
+ i++;
85
+ nextToken = tokens[i];
86
+ }
87
+ while (nextToken?.type === "attr-binding") {
81
88
  nodes.push({
82
- type: "text",
83
- text: `>`,
89
+ type: "attr-binding",
90
+ name: nextToken.name,
91
+ expr: nextToken.expression,
84
92
  });
85
93
  i++;
86
- continue;
94
+ nextToken = tokens[i];
87
95
  }
88
96
  nodes.push({
89
97
  type: "text",
90
- text: `<${tag}>`,
98
+ text: `>`,
91
99
  });
92
100
  continue;
93
101
  }
@@ -103,8 +111,7 @@ export function parse(tokens) {
103
111
  }
104
112
  }
105
113
  return nodes;
106
- function parseArgs(_args) {
107
- const args = _args.join(" ");
114
+ function parseArgs(args) {
108
115
  let textBuffer = "";
109
116
  for (let i = 0; i < args.length; i++) {
110
117
  const letter = args[i];
@@ -1,4 +1,4 @@
1
- export type Node = RootNode | TextNode | InterpolationNode | IssetNode | ForNode;
1
+ export type Node = RootNode | TextNode | InterpolationNode | IssetNode | ForNode | AttributeBindingNode;
2
2
  export interface RootNode {
3
3
  type: "root";
4
4
  children: Node[];
@@ -22,5 +22,10 @@ interface ForNode {
22
22
  itemName: string;
23
23
  children: Node[];
24
24
  }
25
+ interface AttributeBindingNode {
26
+ type: "attr-binding";
27
+ name: string;
28
+ expr: string;
29
+ }
25
30
  export declare function render(node: Node, context: Record<string, unknown>): string;
26
31
  export {};
@@ -1,4 +1,9 @@
1
1
  export function render(node, context) {
2
+ if (node.type === "attr-binding") {
3
+ const prop = resolvePropertyPath(node.expr);
4
+ const exists = isset(prop);
5
+ return exists ? node.name : "";
6
+ }
2
7
  if (node.type === "text") {
3
8
  return node.text;
4
9
  }
@@ -1,4 +1,4 @@
1
- export type Token = TextToken | InterpolationToken | OpenToken | CloseToken | ArgumentsToken;
1
+ export type Token = TextToken | InterpolationToken | OpenToken | CloseToken | ArgumentsToken | AttributeBindingToken;
2
2
  type TextToken = {
3
3
  type: "text";
4
4
  text: string;
@@ -17,7 +17,12 @@ type CloseToken = {
17
17
  };
18
18
  type ArgumentsToken = {
19
19
  type: "arguments";
20
- value: string[];
20
+ value: string;
21
+ };
22
+ type AttributeBindingToken = {
23
+ type: "attr-binding";
24
+ name: string;
25
+ expression: string;
21
26
  };
22
27
  export declare function tokenize(input: string): Token[];
23
28
  export {};
@@ -40,10 +40,28 @@ export function tokenize(input) {
40
40
  type: "open",
41
41
  tag,
42
42
  });
43
- if (args.length > 0) {
43
+ for (const arg of args) {
44
+ if (!arg.startsWith(":")) {
45
+ tokens.push({
46
+ type: "arguments",
47
+ value: arg,
48
+ });
49
+ continue;
50
+ }
51
+ const [name, expr] = arg.slice(1).split("=");
52
+ if (name === undefined)
53
+ throw new Error("Missing name on attribute binding attempt.");
54
+ if (expr === undefined)
55
+ throw new Error("Missing expression on attribute binding attempt.");
56
+ if (!expr.startsWith("{"))
57
+ throw new Error("Expected interpolation on expression when using attribute binding");
58
+ if (!expr.endsWith("}"))
59
+ throw new Error("Expected interpolation closure on expression when using attribute binding");
60
+ const expression = expr.slice(1, -1);
44
61
  tokens.push({
45
- type: "arguments",
46
- value: args,
62
+ type: "attr-binding",
63
+ name,
64
+ expression,
47
65
  });
48
66
  }
49
67
  i = finishingPosition;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "htmv",
3
3
  "main": "dist/index.js",
4
4
  "type": "module",
5
- "version": "0.0.42",
5
+ "version": "0.0.43",
6
6
  "devDependencies": {
7
7
  "@biomejs/biome": "2.3.3",
8
8
  "@types/bun": "latest"