@angular-wave/angular.ts 0.0.48 → 0.0.50

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 (38) hide show
  1. package/Makefile +3 -0
  2. package/README.md +1 -1
  3. package/css/angular.css +0 -6
  4. package/dist/angular-ts.esm.js +2 -2
  5. package/dist/angular-ts.umd.js +2 -2
  6. package/jsdoc.json +24 -0
  7. package/package.json +6 -2
  8. package/src/core/compile/compile.md +1 -1
  9. package/src/core/compile/compile.spec.js +50 -48
  10. package/src/core/interpolate/interpolate.js +1 -18
  11. package/src/core/on.spec.js +7 -12
  12. package/src/core/parser/ast.js +234 -69
  13. package/src/core/parser/interpreter.js +246 -50
  14. package/src/core/parser/lexer.js +144 -57
  15. package/src/core/parser/parse.js +38 -278
  16. package/src/core/parser/parse.md +44 -0
  17. package/src/core/parser/parser.js +32 -6
  18. package/src/core/parser/shared.js +7 -1
  19. package/src/core/prop.spec.js +4 -4
  20. package/src/core/scope/scope.js +14 -10
  21. package/src/directive/csp.md +0 -26
  22. package/src/directive/form/form.spec.js +18 -18
  23. package/src/directive/include/include.spec.js +18 -18
  24. package/src/directive/switch/switch.spec.js +4 -4
  25. package/src/shared/constants.js +3 -2
  26. package/src/shared/jqlite/jqlite.js +2 -2
  27. package/src/types.js +4 -1
  28. package/types/core/parser/ast.d.ts +269 -67
  29. package/types/core/parser/interpreter.d.ts +202 -53
  30. package/types/core/parser/lexer.d.ts +153 -0
  31. package/types/core/parser/parse.d.ts +23 -34
  32. package/types/core/parser/parser.d.ts +43 -14
  33. package/types/core/parser/shared.d.ts +7 -1
  34. package/types/core/scope/scope.d.ts +11 -11
  35. package/types/shared/jqlite/jqlite.d.ts +4 -4
  36. package/types/types.d.ts +1 -1
  37. package/src/core/parser/compiler.js +0 -561
  38. package/types/core/parser/compiler.d.ts +0 -49
@@ -1,5 +1,4 @@
1
1
  import { $parseMinErr } from "./parse";
2
-
3
2
  import { isDefined } from "../../shared/utils";
4
3
 
5
4
  const ESCAPE = {
@@ -17,18 +16,45 @@ const OPERATORS = new Set(
17
16
  );
18
17
 
19
18
  /**
20
- * @constructor
19
+ * @typedef {Object} LexerOptions
20
+ * @property {(ch: string, codePoint: number) => boolean} [isIdentifierStart] - Custom function to determine if a character is a valid identifier start.
21
+ * @property {(ch: string, codePoint: number) => boolean} [isIdentifierContinue] - Custom function to determine if a character is a valid identifier continuation.
21
22
  */
22
- export const Lexer = function Lexer(options) {
23
- this.options = options;
24
- };
25
23
 
26
- Lexer.prototype = {
27
- constructor: Lexer,
24
+ /**
25
+ * Represents a token produced by the lexer.
26
+ * @typedef {Object} Token
27
+ * @property {number} index - Index of the token.
28
+ * @property {string} text - Text of the token.
29
+ * @property {boolean} [identifier] - Indicates if token is an identifier.
30
+ * @property {boolean} [constant] - Indicates if token is a constant.
31
+ * @property {string|number} [value] - Value of the token if it's a constant.
32
+ * @property {boolean} [operator] - Indicates if token is an operator.
33
+ */
28
34
 
35
+ /**
36
+ * Represents a lexer that tokenizes input text. The Lexer takes the original expression string and returns an array of tokens parsed from that string.
37
+ * For example, the string "a + b" would result in tokens for a, +, and b.
38
+ */
39
+ export class Lexer {
40
+ /**
41
+ * Creates an instance of Lexer.
42
+ * @param {LexerOptions} options - Lexer options.
43
+ */
44
+ constructor(options) {
45
+ /** @type {LexerOptions} */
46
+ this.options = options;
47
+ }
48
+
49
+ /**
50
+ * Tokenizes the input text.
51
+ * @param {string} text Input text to lex.
52
+ * @returns {Array<Token>} Array of tokens.
53
+ */
29
54
  lex(text) {
30
55
  this.text = text;
31
56
  this.index = 0;
57
+ /** @type {Array<Token>} */
32
58
  this.tokens = [];
33
59
 
34
60
  while (this.index < this.text.length) {
@@ -37,7 +63,7 @@ Lexer.prototype = {
37
63
  this.readString(ch);
38
64
  } else if (
39
65
  this.isNumber(ch) ||
40
- (ch === "." && this.isNumber(this.peek()))
66
+ (ch === "." && this.isNumber(/** @type {string} */ (this.peek())))
41
67
  ) {
42
68
  this.readNumber();
43
69
  } else if (this.isIdentifierStart(this.peekMultichar())) {
@@ -67,23 +93,44 @@ Lexer.prototype = {
67
93
  }
68
94
  }
69
95
  return this.tokens;
70
- },
96
+ }
71
97
 
98
+ /**
99
+ * Checks if a character is contained in a set of characters.
100
+ * @param {string} ch Character to check.
101
+ * @param {string} chars Set of characters.
102
+ * @returns {boolean} True if character is in the set, false otherwise.
103
+ */
72
104
  is(ch, chars) {
73
105
  return chars.indexOf(ch) !== -1;
74
- },
106
+ }
75
107
 
108
+ /**
109
+ * Peeks at the next character in the text.
110
+ * @param {number} [i=1] Number of characters to peek.
111
+ * @returns {string|false} Next character or false if end of text.
112
+ */
76
113
  peek(i) {
77
114
  const num = i || 1;
78
115
  return this.index + num < this.text.length
79
116
  ? this.text.charAt(this.index + num)
80
117
  : false;
81
- },
118
+ }
82
119
 
120
+ /**
121
+ * Checks if a character is a number.
122
+ * @param {string} ch Character to check.
123
+ * @returns {boolean} True if character is a number, false otherwise.
124
+ */
83
125
  isNumber(ch) {
84
126
  return ch >= "0" && ch <= "9" && typeof ch === "string";
85
- },
127
+ }
86
128
 
129
+ /**
130
+ * Checks if a character is whitespace.
131
+ * @param {string} ch Character to check.
132
+ * @returns {boolean} True if character is whitespace, false otherwise.
133
+ */
87
134
  isWhitespace(ch) {
88
135
  // IE treats non-breaking space as \u00A0
89
136
  return (
@@ -94,39 +141,52 @@ Lexer.prototype = {
94
141
  ch === "\v" ||
95
142
  ch === "\u00A0"
96
143
  );
97
- },
144
+ }
98
145
 
146
+ /**
147
+ * Checks if a character is a valid identifier start.
148
+ * @param {string} ch Character to check.
149
+ * @returns {boolean} True if character is a valid identifier start, false otherwise.
150
+ */
99
151
  isIdentifierStart(ch) {
100
152
  return this.options.isIdentifierStart
101
153
  ? this.options.isIdentifierStart(ch, this.codePointAt(ch))
102
- : this.isValidIdentifierStart(ch);
103
- },
104
-
105
- isValidIdentifierStart(ch) {
106
- return (
107
- (ch >= "a" && ch <= "z") ||
108
- (ch >= "A" && ch <= "Z") ||
109
- ch === "_" ||
110
- ch === "$"
111
- );
112
- },
154
+ : (ch >= "a" && ch <= "z") ||
155
+ (ch >= "A" && ch <= "Z") ||
156
+ ch === "_" ||
157
+ ch === "$";
158
+ }
113
159
 
160
+ /**
161
+ * Checks if a character is a valid identifier continuation.
162
+ * @param {string} ch Character to check.
163
+ * @returns {boolean} True if character is a valid identifier continuation, false otherwise.
164
+ */
114
165
  isIdentifierContinue(ch) {
115
166
  return this.options.isIdentifierContinue
116
167
  ? this.options.isIdentifierContinue(ch, this.codePointAt(ch))
117
- : this.isValidIdentifierContinue(ch);
118
- },
119
-
120
- isValidIdentifierContinue(ch) {
121
- return this.isValidIdentifierStart(ch) || this.isNumber(ch);
122
- },
168
+ : (ch >= "a" && ch <= "z") ||
169
+ (ch >= "A" && ch <= "Z") ||
170
+ ch === "_" ||
171
+ ch === "$" ||
172
+ (ch >= "0" && ch <= "9");
173
+ }
123
174
 
175
+ /**
176
+ * Converts a character to its Unicode code point.
177
+ * @param {string} ch Character to convert.
178
+ * @returns {number} Unicode code point.
179
+ */
124
180
  codePointAt(ch) {
125
181
  if (ch.length === 1) return ch.charCodeAt(0);
126
182
 
127
183
  return (ch.charCodeAt(0) << 10) + ch.charCodeAt(1) - 0x35fdc00;
128
- },
184
+ }
129
185
 
186
+ /**
187
+ * Peeks at the next multicharacter sequence in the text.
188
+ * @returns {string} Next multicharacter sequence.
189
+ */
130
190
  peekMultichar() {
131
191
  const ch = this.text.charAt(this.index);
132
192
  const peek = this.peek();
@@ -139,12 +199,24 @@ Lexer.prototype = {
139
199
  return ch + peek;
140
200
  }
141
201
  return ch;
142
- },
202
+ }
143
203
 
204
+ /**
205
+ * Checks if a character is an exponent operator.
206
+ * @param {string} ch Character to check.
207
+ * @returns {boolean} True if character is an exponent operator, false otherwise.
208
+ */
144
209
  isExpOperator(ch) {
145
210
  return ch === "-" || ch === "+" || this.isNumber(ch);
146
- },
211
+ }
147
212
 
213
+ /**
214
+ * Throws a lexer error.
215
+ * @param {string} error Error message.
216
+ * @param {number} [start] Start index.
217
+ * @param {number} [end] End index.
218
+ * @throws {Error} Lexer error.
219
+ */
148
220
  throwError(error, start, end) {
149
221
  end = end || this.index;
150
222
  const colStr = isDefined(start)
@@ -152,13 +224,13 @@ Lexer.prototype = {
152
224
  : ` ${end}`;
153
225
  throw $parseMinErr(
154
226
  "lexerr",
155
- "Lexer Error: {0} at column{1} in expression [{2}].",
156
- error,
157
- colStr,
158
- this.text,
227
+ `Lexer Error: ${error} at column${colStr} in expression [${this.text}].`,
159
228
  );
160
- },
229
+ }
161
230
 
231
+ /**
232
+ * Reads and tokenizes a number from the text.
233
+ */
162
234
  readNumber() {
163
235
  let number = "";
164
236
  const start = this.index;
@@ -168,7 +240,7 @@ Lexer.prototype = {
168
240
  number += ch;
169
241
  } else {
170
242
  const peekCh = this.peek();
171
- if (ch === "e" && this.isExpOperator(peekCh)) {
243
+ if (ch === "e" && this.isExpOperator(/** @type {string} */ (peekCh))) {
172
244
  number += ch;
173
245
  } else if (
174
246
  this.isExpOperator(ch) &&
@@ -195,8 +267,11 @@ Lexer.prototype = {
195
267
  constant: true,
196
268
  value: Number(number),
197
269
  });
198
- },
270
+ }
199
271
 
272
+ /**
273
+ * Reads and tokenizes an identifier from the text.
274
+ */
200
275
  readIdent() {
201
276
  const start = this.index;
202
277
  this.index += this.peekMultichar().length;
@@ -212,46 +287,58 @@ Lexer.prototype = {
212
287
  text: this.text.slice(start, this.index),
213
288
  identifier: true,
214
289
  });
215
- },
290
+ }
216
291
 
292
+ /**
293
+ * Reads and tokenizes a string from the text.
294
+ * @param {string} quote Quote character used for the string.
295
+ */
217
296
  readString(quote) {
218
297
  const start = this.index;
219
- this.index++;
220
298
  let string = "";
221
- let rawString = quote;
222
299
  let escape = false;
300
+
301
+ this.index++; // Skip opening quote
302
+
223
303
  while (this.index < this.text.length) {
224
- const ch = this.text.charAt(this.index);
225
- rawString += ch;
304
+ const ch = this.text[this.index];
305
+
226
306
  if (escape) {
227
307
  if (ch === "u") {
228
- const hex = this.text.substring(this.index + 1, this.index + 5);
229
- if (!hex.match(/[\da-f]{4}/i)) {
230
- this.throwError(`Invalid unicode escape [\\u${hex}]`);
231
- }
232
- this.index += 4;
233
- string += String.fromCharCode(parseInt(hex, 16));
308
+ // Handle unicode escapes
309
+ // Simplified for brevity
310
+ string += this.handleUnicodeEscape();
234
311
  } else {
235
- const rep = ESCAPE[ch];
236
- string += rep || ch;
312
+ string += ESCAPE[ch] || ch;
237
313
  }
238
314
  escape = false;
239
315
  } else if (ch === "\\") {
240
316
  escape = true;
241
317
  } else if (ch === quote) {
242
- this.index++;
243
318
  this.tokens.push({
244
319
  index: start,
245
- text: rawString,
320
+ text: this.text.slice(start, this.index + 1),
246
321
  constant: true,
247
322
  value: string,
248
323
  });
324
+ this.index++; // Skip closing quote
249
325
  return;
250
326
  } else {
251
327
  string += ch;
252
328
  }
329
+
253
330
  this.index++;
254
331
  }
332
+
255
333
  this.throwError("Unterminated quote", start);
256
- },
257
- };
334
+ }
335
+
336
+ handleUnicodeEscape() {
337
+ const hex = this.text.substring(this.index + 1, this.index + 5);
338
+ if (!hex.match(/[\da-f]{4}/i)) {
339
+ this.throwError(`Invalid unicode escape [\\u${hex}]`);
340
+ }
341
+ this.index += 4; // Move index past the four hexadecimal digits
342
+ return String.fromCharCode(parseInt(hex, 16));
343
+ }
344
+ }