hispano-lang 1.1.7 → 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.
- package/README.md +672 -237
- package/dist/evaluator.js +1390 -261
- package/dist/parser.js +758 -201
- package/dist/tokenizer.js +202 -121
- package/package.json +12 -3
package/dist/tokenizer.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
class Tokenizer {
|
|
7
7
|
constructor() {
|
|
8
|
-
this.source =
|
|
8
|
+
this.source = "";
|
|
9
9
|
this.tokens = [];
|
|
10
10
|
this.current = 0;
|
|
11
11
|
this.startPos = 0;
|
|
@@ -27,8 +27,8 @@ class Tokenizer {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
this.tokens.push({
|
|
30
|
-
type:
|
|
31
|
-
lexeme:
|
|
30
|
+
type: "EOF",
|
|
31
|
+
lexeme: "",
|
|
32
32
|
literal: null,
|
|
33
33
|
line: this.currentLine,
|
|
34
34
|
});
|
|
@@ -43,8 +43,8 @@ class Tokenizer {
|
|
|
43
43
|
|
|
44
44
|
// Check for comments before advancing
|
|
45
45
|
if (
|
|
46
|
-
this.source[this.current] ===
|
|
47
|
-
this.source[this.current + 1] ===
|
|
46
|
+
this.source[this.current] === "/" &&
|
|
47
|
+
this.source[this.current + 1] === "/"
|
|
48
48
|
) {
|
|
49
49
|
this.comment();
|
|
50
50
|
return;
|
|
@@ -53,141 +53,144 @@ class Tokenizer {
|
|
|
53
53
|
const char = this.advance();
|
|
54
54
|
|
|
55
55
|
switch (char) {
|
|
56
|
-
case
|
|
57
|
-
case
|
|
58
|
-
case
|
|
56
|
+
case " ":
|
|
57
|
+
case "\r":
|
|
58
|
+
case "\t":
|
|
59
59
|
// Ignore whitespace
|
|
60
60
|
break;
|
|
61
61
|
|
|
62
|
-
case
|
|
62
|
+
case "\n":
|
|
63
63
|
this.currentLine++;
|
|
64
64
|
break;
|
|
65
65
|
|
|
66
|
-
case
|
|
67
|
-
if (this.peek() ===
|
|
66
|
+
case "=":
|
|
67
|
+
if (this.peek() === "=") {
|
|
68
68
|
this.advance();
|
|
69
|
-
this.addToken(
|
|
69
|
+
this.addToken("EQUAL_EQUAL");
|
|
70
|
+
} else if (this.peek() === ">") {
|
|
71
|
+
this.advance();
|
|
72
|
+
this.addToken("ARROW");
|
|
70
73
|
} else {
|
|
71
|
-
this.addToken(
|
|
74
|
+
this.addToken("EQUAL");
|
|
72
75
|
}
|
|
73
76
|
break;
|
|
74
77
|
|
|
75
|
-
case
|
|
76
|
-
if (this.peek() ===
|
|
78
|
+
case "*":
|
|
79
|
+
if (this.peek() === "=") {
|
|
77
80
|
this.advance();
|
|
78
|
-
this.addToken(
|
|
81
|
+
this.addToken("STAR_EQUAL");
|
|
79
82
|
} else {
|
|
80
|
-
this.addToken(
|
|
83
|
+
this.addToken("STAR");
|
|
81
84
|
}
|
|
82
85
|
break;
|
|
83
86
|
|
|
84
|
-
case
|
|
85
|
-
if (this.peek() ===
|
|
87
|
+
case "/":
|
|
88
|
+
if (this.peek() === "=") {
|
|
86
89
|
this.advance();
|
|
87
|
-
this.addToken(
|
|
90
|
+
this.addToken("SLASH_EQUAL");
|
|
88
91
|
} else {
|
|
89
|
-
this.addToken(
|
|
92
|
+
this.addToken("SLASH");
|
|
90
93
|
}
|
|
91
94
|
break;
|
|
92
95
|
|
|
93
|
-
case
|
|
94
|
-
if (this.peek() ===
|
|
96
|
+
case "%":
|
|
97
|
+
if (this.peek() === "=") {
|
|
95
98
|
this.advance();
|
|
96
|
-
this.addToken(
|
|
99
|
+
this.addToken("PERCENT_EQUAL");
|
|
97
100
|
} else {
|
|
98
|
-
this.addToken(
|
|
101
|
+
this.addToken("PERCENT");
|
|
99
102
|
}
|
|
100
103
|
break;
|
|
101
104
|
|
|
102
|
-
case
|
|
103
|
-
if (this.peek() ===
|
|
105
|
+
case ">":
|
|
106
|
+
if (this.peek() === "=") {
|
|
104
107
|
this.advance();
|
|
105
|
-
this.addToken(
|
|
108
|
+
this.addToken("GREATER_EQUAL");
|
|
106
109
|
} else {
|
|
107
|
-
this.addToken(
|
|
110
|
+
this.addToken("GREATER");
|
|
108
111
|
}
|
|
109
112
|
break;
|
|
110
113
|
|
|
111
|
-
case
|
|
112
|
-
if (this.peek() ===
|
|
114
|
+
case "<":
|
|
115
|
+
if (this.peek() === "=") {
|
|
113
116
|
this.advance();
|
|
114
|
-
this.addToken(
|
|
117
|
+
this.addToken("LESS_EQUAL");
|
|
115
118
|
} else {
|
|
116
|
-
this.addToken(
|
|
119
|
+
this.addToken("LESS");
|
|
117
120
|
}
|
|
118
121
|
break;
|
|
119
122
|
|
|
120
|
-
case
|
|
121
|
-
if (this.peek() ===
|
|
123
|
+
case "!":
|
|
124
|
+
if (this.peek() === "=") {
|
|
122
125
|
this.advance();
|
|
123
|
-
this.addToken(
|
|
126
|
+
this.addToken("BANG_EQUAL");
|
|
124
127
|
} else {
|
|
125
|
-
this.addToken(
|
|
128
|
+
this.addToken("BANG");
|
|
126
129
|
}
|
|
127
130
|
break;
|
|
128
131
|
|
|
129
|
-
case
|
|
130
|
-
if (this.peek() ===
|
|
132
|
+
case "+":
|
|
133
|
+
if (this.peek() === "+") {
|
|
131
134
|
this.advance();
|
|
132
|
-
this.addToken(
|
|
133
|
-
} else if (this.peek() ===
|
|
135
|
+
this.addToken("PLUS_PLUS");
|
|
136
|
+
} else if (this.peek() === "=") {
|
|
134
137
|
this.advance();
|
|
135
|
-
this.addToken(
|
|
138
|
+
this.addToken("PLUS_EQUAL");
|
|
136
139
|
} else {
|
|
137
|
-
this.addToken(
|
|
140
|
+
this.addToken("PLUS");
|
|
138
141
|
}
|
|
139
142
|
break;
|
|
140
143
|
|
|
141
|
-
case
|
|
142
|
-
if (this.peek() ===
|
|
144
|
+
case "-":
|
|
145
|
+
if (this.peek() === "-") {
|
|
143
146
|
this.advance();
|
|
144
|
-
this.addToken(
|
|
145
|
-
} else if (this.peek() ===
|
|
147
|
+
this.addToken("MINUS_MINUS");
|
|
148
|
+
} else if (this.peek() === "=") {
|
|
146
149
|
this.advance();
|
|
147
|
-
this.addToken(
|
|
150
|
+
this.addToken("MINUS_EQUAL");
|
|
148
151
|
} else {
|
|
149
|
-
this.addToken(
|
|
152
|
+
this.addToken("MINUS");
|
|
150
153
|
}
|
|
151
154
|
break;
|
|
152
155
|
|
|
153
|
-
case
|
|
154
|
-
this.addToken(
|
|
156
|
+
case "{":
|
|
157
|
+
this.addToken("LEFT_BRACE");
|
|
155
158
|
break;
|
|
156
159
|
|
|
157
|
-
case
|
|
158
|
-
this.addToken(
|
|
160
|
+
case "}":
|
|
161
|
+
this.addToken("RIGHT_BRACE");
|
|
159
162
|
break;
|
|
160
163
|
|
|
161
|
-
case
|
|
162
|
-
this.addToken(
|
|
164
|
+
case "(":
|
|
165
|
+
this.addToken("LEFT_PAREN");
|
|
163
166
|
break;
|
|
164
167
|
|
|
165
|
-
case
|
|
166
|
-
this.addToken(
|
|
168
|
+
case ")":
|
|
169
|
+
this.addToken("RIGHT_PAREN");
|
|
167
170
|
break;
|
|
168
171
|
|
|
169
|
-
case
|
|
170
|
-
this.addToken(
|
|
172
|
+
case ",":
|
|
173
|
+
this.addToken("COMMA");
|
|
171
174
|
break;
|
|
172
175
|
|
|
173
|
-
case
|
|
174
|
-
this.addToken(
|
|
176
|
+
case ";":
|
|
177
|
+
this.addToken("SEMICOLON");
|
|
175
178
|
break;
|
|
176
179
|
|
|
177
|
-
case
|
|
178
|
-
this.addToken(
|
|
180
|
+
case ":":
|
|
181
|
+
this.addToken("COLON");
|
|
179
182
|
break;
|
|
180
183
|
|
|
181
|
-
case
|
|
182
|
-
this.addToken(
|
|
184
|
+
case "[":
|
|
185
|
+
this.addToken("LEFT_BRACKET");
|
|
183
186
|
break;
|
|
184
187
|
|
|
185
|
-
case
|
|
186
|
-
this.addToken(
|
|
188
|
+
case "]":
|
|
189
|
+
this.addToken("RIGHT_BRACKET");
|
|
187
190
|
break;
|
|
188
191
|
|
|
189
|
-
case
|
|
190
|
-
this.addToken(
|
|
192
|
+
case ".":
|
|
193
|
+
this.addToken("DOT");
|
|
191
194
|
break;
|
|
192
195
|
|
|
193
196
|
case '"':
|
|
@@ -198,11 +201,15 @@ class Tokenizer {
|
|
|
198
201
|
this.string("'");
|
|
199
202
|
break;
|
|
200
203
|
|
|
201
|
-
case
|
|
202
|
-
|
|
204
|
+
case "`":
|
|
205
|
+
this.templateString();
|
|
206
|
+
break;
|
|
207
|
+
|
|
208
|
+
case "/":
|
|
209
|
+
if (this.peek() === "/") {
|
|
203
210
|
this.comment();
|
|
204
211
|
} else {
|
|
205
|
-
this.addToken(
|
|
212
|
+
this.addToken("SLASH");
|
|
206
213
|
}
|
|
207
214
|
break;
|
|
208
215
|
|
|
@@ -213,7 +220,7 @@ class Tokenizer {
|
|
|
213
220
|
this.identifier();
|
|
214
221
|
} else {
|
|
215
222
|
throw new Error(
|
|
216
|
-
`Carácter inesperado: ${char} en la línea ${this.currentLine}
|
|
223
|
+
`Carácter inesperado: ${char} en la línea ${this.currentLine}`,
|
|
217
224
|
);
|
|
218
225
|
}
|
|
219
226
|
break;
|
|
@@ -226,12 +233,12 @@ class Tokenizer {
|
|
|
226
233
|
*/
|
|
227
234
|
string(quoteType = '"') {
|
|
228
235
|
while (this.peek() !== quoteType && !this.isAtEnd()) {
|
|
229
|
-
if (this.peek() ===
|
|
236
|
+
if (this.peek() === "\n") this.currentLine++;
|
|
230
237
|
this.advance();
|
|
231
238
|
}
|
|
232
239
|
|
|
233
240
|
if (this.isAtEnd()) {
|
|
234
|
-
throw new Error(
|
|
241
|
+
throw new Error("Cadena no terminada");
|
|
235
242
|
}
|
|
236
243
|
|
|
237
244
|
// Consume the closing quote
|
|
@@ -239,7 +246,68 @@ class Tokenizer {
|
|
|
239
246
|
|
|
240
247
|
// Extract the string value
|
|
241
248
|
const value = this.source.substring(this.startPos + 1, this.current - 1);
|
|
242
|
-
this.addToken(
|
|
249
|
+
this.addToken("STRING", value);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Processes a template string with interpolation (backticks)
|
|
254
|
+
* Supports ${expression} syntax for embedding expressions
|
|
255
|
+
*/
|
|
256
|
+
templateString() {
|
|
257
|
+
const parts = []; // Literal string parts
|
|
258
|
+
const expressions = []; // Expression source strings
|
|
259
|
+
let currentPart = "";
|
|
260
|
+
|
|
261
|
+
while (!this.isAtEnd()) {
|
|
262
|
+
const char = this.peek();
|
|
263
|
+
|
|
264
|
+
if (char === "`") {
|
|
265
|
+
// End of template string
|
|
266
|
+
this.advance();
|
|
267
|
+
parts.push(currentPart);
|
|
268
|
+
this.addToken("TEMPLATE_STRING", { parts, expressions });
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (char === "$" && this.peekNext() === "{") {
|
|
273
|
+
// Start of interpolation
|
|
274
|
+
parts.push(currentPart);
|
|
275
|
+
currentPart = "";
|
|
276
|
+
this.advance(); // consume $
|
|
277
|
+
this.advance(); // consume {
|
|
278
|
+
|
|
279
|
+
// Extract the expression
|
|
280
|
+
let braceCount = 1;
|
|
281
|
+
let expressionSource = "";
|
|
282
|
+
|
|
283
|
+
while (!this.isAtEnd() && braceCount > 0) {
|
|
284
|
+
const c = this.peek();
|
|
285
|
+
if (c === "{") {
|
|
286
|
+
braceCount++;
|
|
287
|
+
expressionSource += c;
|
|
288
|
+
this.advance();
|
|
289
|
+
} else if (c === "}") {
|
|
290
|
+
braceCount--;
|
|
291
|
+
if (braceCount > 0) {
|
|
292
|
+
expressionSource += c;
|
|
293
|
+
}
|
|
294
|
+
this.advance();
|
|
295
|
+
} else {
|
|
296
|
+
if (c === "\n") this.currentLine++;
|
|
297
|
+
expressionSource += c;
|
|
298
|
+
this.advance();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
expressions.push(expressionSource);
|
|
303
|
+
} else {
|
|
304
|
+
if (char === "\n") this.currentLine++;
|
|
305
|
+
currentPart += char;
|
|
306
|
+
this.advance();
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
throw new Error("Cadena de plantilla no terminada");
|
|
243
311
|
}
|
|
244
312
|
|
|
245
313
|
/**
|
|
@@ -250,7 +318,7 @@ class Tokenizer {
|
|
|
250
318
|
this.advance();
|
|
251
319
|
|
|
252
320
|
// Skip until end of line
|
|
253
|
-
while (this.peek() !==
|
|
321
|
+
while (this.peek() !== "\n" && !this.isAtEnd()) {
|
|
254
322
|
this.advance();
|
|
255
323
|
}
|
|
256
324
|
|
|
@@ -267,7 +335,7 @@ class Tokenizer {
|
|
|
267
335
|
}
|
|
268
336
|
|
|
269
337
|
// Look for decimal part
|
|
270
|
-
if (this.peek() ===
|
|
338
|
+
if (this.peek() === "." && this.isDigit(this.peekNext())) {
|
|
271
339
|
// Consume the dot
|
|
272
340
|
this.advance();
|
|
273
341
|
|
|
@@ -277,7 +345,7 @@ class Tokenizer {
|
|
|
277
345
|
}
|
|
278
346
|
|
|
279
347
|
const value = this.source.substring(this.startPos, this.current);
|
|
280
|
-
this.addToken(
|
|
348
|
+
this.addToken("NUMBER", parseFloat(value));
|
|
281
349
|
}
|
|
282
350
|
|
|
283
351
|
/**
|
|
@@ -285,7 +353,7 @@ class Tokenizer {
|
|
|
285
353
|
* @returns {string} Next character
|
|
286
354
|
*/
|
|
287
355
|
peekNext() {
|
|
288
|
-
if (this.current + 1 >= this.source.length) return
|
|
356
|
+
if (this.current + 1 >= this.source.length) return "\0";
|
|
289
357
|
return this.source[this.current + 1];
|
|
290
358
|
}
|
|
291
359
|
|
|
@@ -300,36 +368,36 @@ class Tokenizer {
|
|
|
300
368
|
const text = this.source.substring(this.startPos, this.current);
|
|
301
369
|
|
|
302
370
|
// Special handling for 'y' - only treat as AND in logical contexts
|
|
303
|
-
if (text ===
|
|
371
|
+
if (text === "y") {
|
|
304
372
|
// Check if this is a logical context by looking at previous tokens
|
|
305
373
|
const prevToken = this.tokens[this.tokens.length - 1];
|
|
306
374
|
if (
|
|
307
375
|
prevToken &&
|
|
308
|
-
(prevToken.type ===
|
|
309
|
-
prevToken.type ===
|
|
310
|
-
prevToken.type ===
|
|
311
|
-
prevToken.type ===
|
|
312
|
-
prevToken.type ===
|
|
313
|
-
prevToken.type ===
|
|
314
|
-
prevToken.type ===
|
|
376
|
+
(prevToken.type === "IDENTIFIER" ||
|
|
377
|
+
prevToken.type === "NUMBER" ||
|
|
378
|
+
prevToken.type === "STRING" ||
|
|
379
|
+
prevToken.type === "TRUE" ||
|
|
380
|
+
prevToken.type === "FALSE" ||
|
|
381
|
+
prevToken.type === "RIGHT_PAREN" ||
|
|
382
|
+
prevToken.type === "RIGHT_BRACKET")
|
|
315
383
|
) {
|
|
316
384
|
// Check if the next token is a logical operator or end of expression
|
|
317
385
|
const nextChar = this.peek();
|
|
318
386
|
if (
|
|
319
|
-
nextChar ===
|
|
320
|
-
nextChar ===
|
|
321
|
-
nextChar ===
|
|
322
|
-
nextChar ===
|
|
323
|
-
nextChar ===
|
|
324
|
-
nextChar ===
|
|
387
|
+
nextChar === " " ||
|
|
388
|
+
nextChar === "\n" ||
|
|
389
|
+
nextChar === "\t" ||
|
|
390
|
+
nextChar === ")" ||
|
|
391
|
+
nextChar === "}" ||
|
|
392
|
+
nextChar === ";" ||
|
|
325
393
|
this.isAtEnd()
|
|
326
394
|
) {
|
|
327
|
-
this.addToken(
|
|
395
|
+
this.addToken("AND");
|
|
328
396
|
} else {
|
|
329
|
-
this.addToken(
|
|
397
|
+
this.addToken("IDENTIFIER");
|
|
330
398
|
}
|
|
331
399
|
} else {
|
|
332
|
-
this.addToken(
|
|
400
|
+
this.addToken("IDENTIFIER");
|
|
333
401
|
}
|
|
334
402
|
} else {
|
|
335
403
|
const type = this.getKeywordType(text);
|
|
@@ -344,27 +412,40 @@ class Tokenizer {
|
|
|
344
412
|
*/
|
|
345
413
|
getKeywordType(text) {
|
|
346
414
|
const keywords = {
|
|
347
|
-
variable:
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
415
|
+
variable: "VARIABLE",
|
|
416
|
+
constante: "CONSTANTE",
|
|
417
|
+
mostrar: "MOSTRAR",
|
|
418
|
+
leer: "LEER",
|
|
419
|
+
si: "SI",
|
|
420
|
+
sino: "SINO",
|
|
421
|
+
mientras: "MIENTRAS",
|
|
422
|
+
para: "PARA",
|
|
423
|
+
funcion: "FUNCION",
|
|
424
|
+
retornar: "RETORNAR",
|
|
425
|
+
verdadero: "TRUE",
|
|
426
|
+
falso: "FALSE",
|
|
427
|
+
o: "OR",
|
|
428
|
+
romper: "ROMPER",
|
|
429
|
+
continuar: "CONTINUAR",
|
|
430
|
+
intentar: "INTENTAR",
|
|
431
|
+
capturar: "CAPTURAR",
|
|
432
|
+
nulo: "NULL",
|
|
433
|
+
indefinido: "UNDEFINED",
|
|
434
|
+
elegir: "ELEGIR",
|
|
435
|
+
caso: "CASO",
|
|
436
|
+
pordefecto: "PORDEFECTO",
|
|
437
|
+
hacer: "HACER",
|
|
438
|
+
cada: "CADA",
|
|
439
|
+
en: "EN",
|
|
440
|
+
clase: "CLASE",
|
|
441
|
+
constructor: "CONSTRUCTOR",
|
|
442
|
+
este: "ESTE",
|
|
443
|
+
nuevo: "NUEVO",
|
|
444
|
+
extiende: "EXTIENDE",
|
|
445
|
+
super: "SUPER",
|
|
365
446
|
};
|
|
366
447
|
|
|
367
|
-
return keywords[text] ||
|
|
448
|
+
return keywords[text] || "IDENTIFIER";
|
|
368
449
|
}
|
|
369
450
|
|
|
370
451
|
/**
|
|
@@ -388,7 +469,7 @@ class Tokenizer {
|
|
|
388
469
|
* @returns {string} Current character
|
|
389
470
|
*/
|
|
390
471
|
peek() {
|
|
391
|
-
if (this.isAtEnd()) return
|
|
472
|
+
if (this.isAtEnd()) return "\0";
|
|
392
473
|
return this.source[this.current];
|
|
393
474
|
}
|
|
394
475
|
|
|
@@ -406,7 +487,7 @@ class Tokenizer {
|
|
|
406
487
|
* @returns {boolean} True if it is a digit
|
|
407
488
|
*/
|
|
408
489
|
isDigit(char) {
|
|
409
|
-
return char >=
|
|
490
|
+
return char >= "0" && char <= "9";
|
|
410
491
|
}
|
|
411
492
|
|
|
412
493
|
/**
|
|
@@ -416,9 +497,9 @@ class Tokenizer {
|
|
|
416
497
|
*/
|
|
417
498
|
isAlpha(char) {
|
|
418
499
|
return (
|
|
419
|
-
(char >=
|
|
420
|
-
(char >=
|
|
421
|
-
char ===
|
|
500
|
+
(char >= "a" && char <= "z") ||
|
|
501
|
+
(char >= "A" && char <= "Z") ||
|
|
502
|
+
char === "_"
|
|
422
503
|
);
|
|
423
504
|
}
|
|
424
505
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hispano-lang",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Un lenguaje de programación educativo en español para enseñar programación sin barreras de idioma",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"build:types": "mkdir -p dist && node scripts/generate-types.js",
|
|
27
27
|
"demo": "node main.js",
|
|
28
28
|
"prepublishOnly": "npm run build",
|
|
29
|
-
"prepack": "npm run build"
|
|
29
|
+
"prepack": "npm run build",
|
|
30
|
+
"prepare": "husky"
|
|
30
31
|
},
|
|
31
32
|
"keywords": [
|
|
32
33
|
"programming-language",
|
|
@@ -58,8 +59,10 @@
|
|
|
58
59
|
},
|
|
59
60
|
"homepage": "https://github.com/nicvazquezdev/hispano-lang#readme",
|
|
60
61
|
"devDependencies": {
|
|
61
|
-
"nodemon": "^3.1.10",
|
|
62
62
|
"eslint": "^8.57.0",
|
|
63
|
+
"husky": "^9.1.7",
|
|
64
|
+
"lint-staged": "^16.2.7",
|
|
65
|
+
"nodemon": "^3.1.10",
|
|
63
66
|
"prettier": "^3.2.5"
|
|
64
67
|
},
|
|
65
68
|
"dependencies": {
|
|
@@ -68,5 +71,11 @@
|
|
|
68
71
|
"preferGlobal": true,
|
|
69
72
|
"publishConfig": {
|
|
70
73
|
"access": "public"
|
|
74
|
+
},
|
|
75
|
+
"lint-staged": {
|
|
76
|
+
"*.js": [
|
|
77
|
+
"eslint --fix",
|
|
78
|
+
"prettier --write"
|
|
79
|
+
]
|
|
71
80
|
}
|
|
72
81
|
}
|