lilact 0.26.16 → 0.27.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.
Files changed (62) hide show
  1. package/dist/lilact.development.js +236 -337
  2. package/dist/lilact.development.js.map +3 -3
  3. package/dist/lilact.development.min.js +34 -34
  4. package/dist/lilact.development.min.js.map +3 -3
  5. package/dist/lilact.production.min.js +34 -34
  6. package/docs/assets/navigation.js +1 -1
  7. package/docs/assets/search.js +1 -1
  8. package/docs/classes/accessories.ErrorBoundary.html +8 -8
  9. package/docs/classes/accessories.Suspense.html +7 -7
  10. package/docs/classes/components.Component.html +11 -11
  11. package/docs/classes/components.HTMLComponent.html +11 -11
  12. package/docs/classes/components.RootComponent.html +11 -11
  13. package/docs/functions/components.cloneComponent.html +1 -1
  14. package/docs/functions/components.createComponent.html +1 -1
  15. package/docs/functions/components.createPortal.html +1 -1
  16. package/docs/functions/components.createRoot.html +1 -1
  17. package/docs/functions/components.memo.html +1 -1
  18. package/docs/functions/components.render.html +1 -1
  19. package/docs/functions/errors.globalErrorHandler.html +1 -2
  20. package/docs/functions/errors.scanBlockLabels.html +1 -2
  21. package/docs/functions/errors.traceError.html +1 -3
  22. package/docs/functions/hooks.startTransition.html +1 -1
  23. package/docs/functions/hooks.useActionState.html +1 -1
  24. package/docs/functions/hooks.useDebugValue.html +1 -1
  25. package/docs/functions/hooks.useDeferredValue.html +1 -1
  26. package/docs/functions/hooks.useEffect.html +1 -1
  27. package/docs/functions/hooks.useImperativeHandle.html +1 -1
  28. package/docs/functions/hooks.useInsertionEffect.html +1 -1
  29. package/docs/functions/hooks.useMemo.html +1 -1
  30. package/docs/functions/hooks.useReducer.html +1 -1
  31. package/docs/functions/run.lazy.html +1 -2
  32. package/docs/functions/run.require.html +1 -2
  33. package/docs/functions/run.run.html +1 -2
  34. package/docs/functions/run.runScripts.html +1 -1
  35. package/docs/functions/timers.timeoutPromise.html +3 -3
  36. package/docs/modules/errors.html +1 -1
  37. package/docs/modules/run.html +1 -1
  38. package/docs/static/index.html +1 -1
  39. package/docs/static/lilact.development.js +236 -337
  40. package/docs/static/lilact.development.js.map +3 -3
  41. package/docs/static/lilact.development.min.js +34 -34
  42. package/docs/static/lilact.development.min.js.map +3 -3
  43. package/docs/static/lilact.production.min.js +34 -34
  44. package/docs/variables/components.cloneElement.html +1 -1
  45. package/docs/variables/errors.blocks_info.html +1 -1
  46. package/docs/variables/errors.error.html +1 -1
  47. package/docs/variables/run.required_scripts.html +1 -0
  48. package/examples/index.html +1 -1
  49. package/examples/lilact.development.js +236 -337
  50. package/examples/lilact.development.js.map +3 -3
  51. package/examples/lilact.development.min.js +34 -34
  52. package/examples/lilact.development.min.js.map +3 -3
  53. package/examples/lilact.production.min.js +34 -34
  54. package/package.json +1 -1
  55. package/src/components.jsx +10 -4
  56. package/src/errors.jsx +179 -364
  57. package/src/expscan.js +1 -1
  58. package/src/hooks.jsx +8 -5
  59. package/src/jsx.js +14 -14
  60. package/src/lilact.jsx +1 -1
  61. package/src/run.jsx +119 -157
  62. package/docs/functions/errors.mapLocation.html +0 -1
package/src/errors.jsx CHANGED
@@ -29,7 +29,7 @@
29
29
  */
30
30
  /*
31
31
  Lilact
32
- Copyright (C) 2024-2026 Arash Kazemi
32
+ Copyright (C) 2024-2026 Arash Kazemi <contact.arash.kazemi@gmail.com>
33
33
  BSD-2-Clause
34
34
  */
35
35
 
@@ -37,398 +37,224 @@ import Lilact from "./lilact.jsx";
37
37
  import { required_scripts } from "./run.jsx";
38
38
  import { css } from "@emotion/css";
39
39
 
40
- function numberOrNull(value) {
41
- const n = Number(value);
42
- return Number.isFinite(n) ? n : null;
43
- }
44
-
45
- function firstNumber(...values) {
46
- for (const value of values) {
47
- const n = numberOrNull(value);
48
- if (n !== null) return n;
49
- }
50
- return null;
40
+ function number(value) {
41
+ const result = Number(value);
42
+ return Number.isFinite(result) ? result : null;
51
43
  }
52
44
 
53
45
  function asError(value) {
54
46
  if (value instanceof Error) return value;
47
+ if (value?.error instanceof Error) return value.error;
55
48
 
56
- if (value && typeof value === "object") {
57
- if (value.error instanceof Error) return value.error;
58
-
59
- const error = new Error(
60
- value.message == null ? String(value) : String(value.message)
61
- );
49
+ const error = new Error(
50
+ value?.message == null
51
+ ? String(value)
52
+ : String(value.message)
53
+ );
62
54
 
55
+ if (value && typeof value === "object") {
63
56
  if (value.name) error.name = value.name;
64
57
  if (value.stack) error.stack = value.stack;
65
58
 
66
59
  for (const key of Object.keys(value)) {
67
60
  if (!(key in error)) error[key] = value[key];
68
61
  }
69
-
70
- return error;
71
62
  }
72
63
 
73
- return new Error(String(value));
64
+ return error;
74
65
  }
75
66
 
76
67
  function isParserError(error) {
77
- return error?.name === "JSXParserError";
78
- }
79
-
80
- /*
81
- Returns zero-based line and column numbers.
82
-
83
- Parser errors produced by jsx.js already use zero-based positions.
84
- Browser Error objects and ErrorEvents normally use one-based positions.
85
- */
86
- function getErrorLocation(error, { zeroBased = false } = {}) {
87
- const line = firstNumber(
88
- error?.lineNumber,
89
- error?.lineno,
90
- error?.line
91
- );
92
-
93
- const column = firstNumber(
94
- error?.columnNumber,
95
- error?.colno,
96
- error?.column
97
- );
98
-
99
- if (line !== null || column !== null) {
100
- return {
101
- line:
102
- line === null
103
- ? null
104
- : zeroBased
105
- ? line
106
- : Math.max(0, line - 1),
107
-
108
- col:
109
- column === null
110
- ? null
111
- : zeroBased
112
- ? column
113
- : Math.max(0, column - 1),
114
- };
115
- }
116
-
117
- return null;
68
+ return error?.name === "JSXParserError";
118
69
  }
119
70
 
120
- function sourceUrlFromStack(stack) {
121
- const text = typeof stack === "string" ? stack : "";
71
+ function stackLocation(stack) {
72
+ if (typeof stack !== "string") return null;
122
73
 
123
- /*
124
- * The final two colon-separated numeric values are the line and column.
125
- * The path is intentionally greedy so paths containing ':' still work.
126
- *
127
- * Examples:
128
- *
129
- * at fn (eval:/components/App.jsx:12:8)
130
- * fn@eval:/components/App.jsx:12:8
131
- * eval:/components/App.jsx:12:8
132
- */
133
- const expression = /(?:^|[\s(@])((?:eval:\/)[\s\S]*):(\d+):(\d+)(?:\)?$)/;
74
+ for (const line of stack.split(/\r?\n/)) {
75
+ const match = line.match(/(eval:\/.*):(\d+):(\d+)/);
134
76
 
135
- for (const line of text.split(/\r?\n/)) {
136
- const match = line.trim().match(expression);
137
77
  if (!match) continue;
138
78
 
139
79
  return {
140
- url: match[1],
141
- line: Number(match[2]),
142
- col: Number(match[3]),
80
+ path: match[1].replace(/^eval:\/+/, ""),
81
+ line: Number(match[2]) - 1,
82
+ column: Number(match[3]) - 1,
143
83
  };
144
84
  }
145
85
 
146
86
  return null;
147
87
  }
148
88
 
149
- function sourcePathFromEvalUrl(url) {
150
- if (typeof url !== "string") return null;
151
-
152
- if (url.startsWith("eval:/")) {
153
- return url.slice("eval:/".length);
154
- }
89
+ function browserLocation(error) {
90
+ const line = number(
91
+ error?.lineNumber ??
92
+ error?.lineno ??
93
+ error?.line
94
+ );
155
95
 
156
- if (url.startsWith("eval:")) {
157
- return url.slice("eval:".length).replace(/^\/+/, "");
158
- }
96
+ const column = number(
97
+ error?.columnNumber ??
98
+ error?.colno ??
99
+ error?.column
100
+ );
159
101
 
160
- return null;
102
+ return {
103
+ line: line == null ? null : Math.max(0, line - 1),
104
+ column: column == null ? null : Math.max(0, column - 1),
105
+ };
161
106
  }
162
107
 
163
- /*
164
- Mappings generated by jsx.js have this shape:
165
-
166
- [
167
- generatedLine,
168
- generatedColumn,
169
- sourceLine,
170
- sourceColumn,
171
- node
172
- ]
173
-
174
- All four coordinates are zero-based.
175
-
176
- The correct mapping is the closest mapping at or before the generated
177
- location. The old implementation searched in the opposite direction and
178
- used the final mapping for errors occurring before the first mapping.
179
- */
180
- export function mapLocation(mappings, generatedLine, generatedColumn) {
181
- if (!Array.isArray(mappings) || mappings.length === 0) {
182
- return {
183
- line: generatedLine,
184
- col: generatedColumn,
185
- };
186
- }
108
+ function traceBlock(error) {
109
+ const trace = error?.lilact_trace;
110
+ return Array.isArray(trace) ? trace[0] : trace;
111
+ }
187
112
 
188
- const line = Number(generatedLine);
189
- const col = Number(generatedColumn);
113
+ function blockInfo(error) {
114
+ const trace = traceBlock(error);
115
+ return trace == null
116
+ ? null
117
+ : Lilact.blocks_info?.labels?.[trace];
118
+ }
190
119
 
191
- if (!Number.isFinite(line) || !Number.isFinite(col)) {
192
- return {
193
- line: null,
194
- col: null,
195
- };
120
+ function mapLocation(mappings, line, column) {
121
+ if (
122
+ !Array.isArray(mappings) ||
123
+ !mappings.length ||
124
+ !Number.isFinite(line) ||
125
+ !Number.isFinite(column)
126
+ ) {
127
+ return { line, column };
196
128
  }
197
129
 
198
- const validMappings = mappings
199
- .filter(
200
- (mapping) =>
201
- Array.isArray(mapping) &&
202
- mapping.length >= 4 &&
203
- Number.isFinite(Number(mapping[0])) &&
204
- Number.isFinite(Number(mapping[1])) &&
205
- Number.isFinite(Number(mapping[2])) &&
206
- Number.isFinite(Number(mapping[3]))
130
+ const valid = mappings
131
+ .filter(mapping =>
132
+ Array.isArray(mapping) &&
133
+ mapping.length >= 4 &&
134
+ mapping
135
+ .slice(0, 4)
136
+ .every(value => Number.isFinite(Number(value)))
207
137
  )
208
- .slice()
209
- .sort((a, b) => {
210
- const lineDifference = Number(a[0]) - Number(b[0]);
211
-
212
- if (lineDifference !== 0) {
213
- return lineDifference;
214
- }
215
-
216
- return Number(a[1]) - Number(b[1]);
217
- });
138
+ .sort((a, b) =>
139
+ Number(a[0]) - Number(b[0]) ||
140
+ Number(a[1]) - Number(b[1])
141
+ );
218
142
 
219
- if (validMappings.length === 0) {
220
- return {
221
- line,
222
- col,
223
- };
224
- }
143
+ if (!valid.length) return { line, column };
225
144
 
226
- /*
227
- * Find the last mapping whose generated position is before or equal
228
- * to the runtime position.
229
- */
230
- let mapping = validMappings[0];
145
+ let selected = valid[0];
231
146
 
232
- for (const candidate of validMappings) {
233
- const generatedMappingLine = Number(candidate[0]);
234
- const generatedMappingColumn = Number(candidate[1]);
147
+ for (const mapping of valid) {
148
+ const generatedLine = Number(mapping[0]);
149
+ const generatedColumn = Number(mapping[1]);
235
150
 
236
151
  if (
237
- generatedMappingLine < line ||
152
+ generatedLine < line ||
238
153
  (
239
- generatedMappingLine === line &&
240
- generatedMappingColumn <= col
154
+ generatedLine === line &&
155
+ generatedColumn <= column
241
156
  )
242
157
  ) {
243
- mapping = candidate;
244
- continue;
158
+ selected = mapping;
159
+ } else {
160
+ break;
245
161
  }
246
-
247
- break;
248
162
  }
249
163
 
250
- const mappingGeneratedLine = Number(mapping[0]);
251
- const mappingGeneratedColumn = Number(mapping[1]);
252
- const mappingSourceLine = Number(mapping[2]);
253
- const mappingSourceColumn = Number(mapping[3]);
254
-
255
- /*
256
- * A mapping points to the beginning of a generated region. Preserve
257
- * the relative line offset inside that region.
258
- *
259
- * This is the important part. Returning mappingSourceLine directly
260
- * causes errors inside a generated multi-line block to point to the
261
- * first line of the block.
262
- */
263
- const sourceLine =
264
- mappingSourceLine + (line - mappingGeneratedLine);
265
-
266
- /*
267
- * Columns are only safely relative when the generated error is on the
268
- * same generated line as the mapping. On later lines, use the source
269
- * anchor column instead of carrying the generated column across lines.
270
- */
271
- const sourceColumn =
272
- line === mappingGeneratedLine
273
- ? Math.max(
274
- 0,
275
- mappingSourceColumn +
276
- (col - mappingGeneratedColumn)
277
- )
278
- : mappingSourceColumn;
164
+ const generatedLine = Number(selected[0]);
165
+ const generatedColumn = Number(selected[1]);
166
+ const sourceLine = Number(selected[2]);
167
+ const sourceColumn = Number(selected[3]);
279
168
 
280
169
  return {
281
- line: sourceLine,
282
- col: sourceColumn,
170
+ line:
171
+ sourceLine +
172
+ (line === generatedLine ? 0 : line - generatedLine),
173
+ column:
174
+ line === generatedLine
175
+ ? Math.max(0, sourceColumn + column - generatedColumn)
176
+ : sourceColumn,
283
177
  };
284
178
  }
285
179
 
286
- function getBlockTrace(error) {
287
- const trace = error?.lilact_trace;
288
-
289
- if (Array.isArray(trace)) {
290
- return trace[0];
291
- }
292
-
293
- return trace;
294
- }
295
-
296
- function getBlockInfo(error) {
297
- const trace = getBlockTrace(error);
298
-
299
- if (trace === undefined || trace === null) {
300
- return null;
301
- }
302
-
303
- return Lilact.blocks_info?.labels?.[trace] ?? null;
304
- }
305
-
306
- function applyBlockFallback(error, result, currentPath) {
307
- const block = getBlockInfo(error);
308
- if (!block) return result;
309
-
310
- if (block.path) {
311
- result.fileName = block.path;
312
- } else if (!result.fileName) {
313
- result.fileName = currentPath;
314
- }
315
-
316
- /*
317
- * scanBlockLabels() stores the original source position of the block.
318
- * This is more reliable than using the location of the generated catch
319
- * wrapper.
320
- */
321
- if (
322
- Number.isFinite(block.line) &&
323
- Number.isFinite(block.col)
324
- ) {
325
- result.lineNumber = block.line;
326
- result.columnNumber = block.col;
327
- }
328
-
329
- if (block.desc) {
330
- result.label = block.desc;
331
- }
332
-
333
- return result;
334
- }
335
-
336
- function copyErrorMetadata(source, target) {
337
- if (!source || typeof source !== "object") return;
338
-
339
- for (const key of [
340
- "fileName",
341
- "lineNumber",
342
- "columnNumber",
343
- "lineno",
344
- "colno",
345
- "line",
346
- "column",
347
- "componentStackLog",
348
- "lilact_trace",
349
- ]) {
350
- if (source[key] !== undefined && target[key] === undefined) {
351
- target[key] = source[key];
352
- }
353
- }
354
- }
355
-
356
- /**
357
- * Converts parser errors, runtime errors, ErrorEvents, and rejected
358
- * promises into one consistent zero-based representation.
359
- */
360
180
  export function traceError(value, runPath) {
361
181
  if (value?.isTraced) return value;
362
182
 
363
- const original =
364
- value?.error instanceof Error ? value.error : asError(value);
183
+ const error = asError(value);
184
+ const source = error.lilact_source;
185
+ const stack = isParserError(error)
186
+ ? null
187
+ : stackLocation(error.stack);
188
+ const browser = isParserError(error)
189
+ ? {
190
+ line: number(error.lineNumber),
191
+ column: number(error.columnNumber),
192
+ }
193
+ : browserLocation(error);
365
194
 
366
- const parserError = isParserError(original);
195
+ /*
196
+ * lilact_source is authoritative. In particular, it prevents a syntax
197
+ * error from a nested eval from inheriting the caller's eval filename.
198
+ */
199
+ const fileName =
200
+ source?.path ||
201
+ stack?.path ||
202
+ error.fileName ||
203
+ runPath ||
204
+ null;
367
205
 
368
- const stackLocation = parserError
369
- ? null
370
- : sourceUrlFromStack(original.stack);
206
+ let line =
207
+ stack?.line ??
208
+ browser.line ??
209
+ null;
371
210
 
372
- const eventLocation = parserError
373
- ? getErrorLocation(original, { zeroBased: true })
374
- : getErrorLocation(original);
211
+ let column =
212
+ stack?.column ??
213
+ browser.column ??
214
+ null;
375
215
 
376
216
  const result = {
377
- fileName:
378
- sourcePathFromEvalUrl(stackLocation?.url) ||
379
- original.fileName ||
380
- runPath ||
381
- null,
382
-
383
- lineNumber:
384
- stackLocation?.line != null
385
- ? Math.max(0, stackLocation.line - 1)
386
- : eventLocation?.line ?? null,
387
-
388
- columnNumber:
389
- stackLocation?.col != null
390
- ? Math.max(0, stackLocation.col - 1)
391
- : eventLocation?.col ?? null,
392
-
217
+ fileName,
218
+ lineNumber: line,
219
+ columnNumber: column,
393
220
  message:
394
- original.message == null
395
- ? String(original)
396
- : String(original.message),
397
-
398
- name: original.name || "Error",
399
- stack: original.stack || null,
400
- _error: original,
221
+ error.message == null
222
+ ? String(error)
223
+ : String(error.message),
224
+ name: error.name || "Error",
225
+ stack: error.stack || null,
226
+ lilact_source: source || null,
227
+ _error: error,
401
228
  isTraced: true,
402
229
  };
403
230
 
404
- copyErrorMetadata(value, result);
405
- copyErrorMetadata(original, result);
231
+ const module = fileName && required_scripts[fileName];
406
232
 
407
- /*
408
- * Parser errors already point into the original JSX source. Do not map
409
- * them again.
410
- */
411
- if (!parserError && stackLocation?.url) {
412
- const module = required_scripts[result.fileName];
413
-
414
- if (module?.mappings) {
415
- const mapped = mapLocation(
416
- module.mappings,
417
- result.lineNumber,
418
- result.columnNumber
419
- );
420
-
421
- result.lineNumber = mapped.line;
422
- result.columnNumber = mapped.col;
423
- }
233
+ if (module) {
234
+ const mapped = mapLocation(
235
+ module.mappings,
236
+ result.lineNumber,
237
+ result.columnNumber
238
+ );
239
+
240
+ result.lineNumber = mapped.line;
241
+ result.columnNumber = mapped.column;
424
242
  }
425
243
 
426
- /*
427
- * When the browser does not preserve the eval sourceURL, the injected
428
- * Lilact block label is the reliable fallback.
429
- */
430
- if (!parserError && !stackLocation?.url) {
431
- applyBlockFallback(original, result, runPath);
244
+ const block = blockInfo(error);
245
+
246
+ if (
247
+ block &&
248
+ (
249
+ result.lineNumber == null ||
250
+ result.columnNumber == null ||
251
+ !result.fileName
252
+ )
253
+ ) {
254
+ result.fileName ||= block.path || runPath || null;
255
+ result.lineNumber ??= block.line;
256
+ result.columnNumber ??= block.col;
257
+ result.label = block.desc;
432
258
  }
433
259
 
434
260
  Lilact.error = result;
@@ -444,37 +270,35 @@ function escapeHtml(value) {
444
270
  .replaceAll("'", "&#39;");
445
271
  }
446
272
 
447
- function sourceExcerpt(module, zeroBasedLine) {
448
- if (!module || !Number.isFinite(zeroBasedLine)) {
449
- return null;
450
- }
273
+ function sourceExcerpt(module, line) {
274
+ if (!module || !Number.isFinite(line)) return null;
451
275
 
452
276
  const lines = String(module.code ?? "").split(/\r?\n/);
453
- const before = lines[zeroBasedLine - 1] ?? "";
454
- const current = lines[zeroBasedLine] ?? "";
455
- const after = lines[zeroBasedLine + 1] ?? "";
456
277
 
457
- return { before, current, after };
278
+ return {
279
+ before: lines[line - 1] ?? "",
280
+ current: lines[line] ?? "",
281
+ after: lines[line + 1] ?? "",
282
+ };
458
283
  }
459
284
 
460
- /**
461
- * Displays an unhandled error.
462
- */
463
285
  export function globalErrorHandler(eventOrError) {
464
- const raw =
286
+ const value =
465
287
  eventOrError?.error instanceof Error
466
288
  ? eventOrError.error
467
289
  : eventOrError?.reason !== undefined
468
290
  ? eventOrError.reason
469
291
  : eventOrError;
470
292
 
471
- const runPath =
472
- eventOrError?.fileName ||
473
- null;
293
+ const error = traceError(
294
+ value,
295
+ eventOrError?.fileName || null
296
+ );
474
297
 
475
- const traced = traceError(raw, runPath);
476
- const module = required_scripts[traced.fileName];
477
- const excerpt = sourceExcerpt(module, traced.lineNumber);
298
+ const excerpt = sourceExcerpt(
299
+ required_scripts[error.fileName],
300
+ error.lineNumber
301
+ );
478
302
 
479
303
  const className = css(`
480
304
  background: linear-gradient(135deg, #fff2f2d4, #ffffffd4);
@@ -501,26 +325,24 @@ export function globalErrorHandler(eventOrError) {
501
325
  const dialog = document.createElement("dialog");
502
326
  dialog.className = className;
503
327
 
504
- const location =
505
- traced.fileName
506
- ? `At ${escapeHtml(traced.fileName)}`
507
- : "";
328
+ const location = error.fileName
329
+ ? `At ${escapeHtml(error.fileName)}`
330
+ : "";
508
331
 
509
- const line =
510
- Number.isFinite(traced.lineNumber)
511
- ? `: Line ${traced.lineNumber + 1}`
512
- : "";
332
+ const line = Number.isFinite(error.lineNumber)
333
+ ? `: Line ${error.lineNumber + 1}`
334
+ : "";
513
335
 
514
336
  const componentStack =
515
- traced._error?.componentStackLog ||
516
- traced._error?.componentStack ||
337
+ error._error?.componentStackLog ||
338
+ error._error?.componentStack ||
517
339
  "";
518
340
 
519
341
  dialog.innerHTML = `
520
342
  <h3><red>Error!</red></h3>
521
343
  <b>${location}${line}</b><br><br>
522
- <b>${escapeHtml(traced.name)}</b>:
523
- <span>${escapeHtml(traced.message)}</span>
344
+ <b>${escapeHtml(error.name)}</b>:
345
+ <span>${escapeHtml(error.message)}</span>
524
346
  <br><br>
525
347
 
526
348
  ${
@@ -556,21 +378,14 @@ export function globalErrorHandler(eventOrError) {
556
378
  dialog.setAttribute("open", "");
557
379
  }
558
380
 
559
- return traced;
381
+ return error;
560
382
  }
561
383
 
562
- /**
563
- * Registers the source location of an injected Lilact block.
564
- */
565
384
  export function scanBlockLabels(code, path) {
566
- const labels = String(code).matchAll(
385
+ for (const match of String(code).matchAll(
567
386
  /LILACTBLOCK(\d+):(\d+),(\d+):([^*]+)\*\//gm
568
- );
569
-
570
- for (const match of labels) {
571
- const id = match[1];
572
-
573
- Lilact.blocks_info.labels[id] = {
387
+ )) {
388
+ Lilact.blocks_info.labels[match[1]] = {
574
389
  path,
575
390
  line: Number(match[2]),
576
391
  col: Number(match[3]),
package/src/expscan.js CHANGED
@@ -91,7 +91,7 @@ export function labeler(custom_words, x)
91
91
  if(x.type==='comment') return 'C';
92
92
  if(x.type==='regexp') return 'R';
93
93
  if(x.type==='js') return 'J';
94
- if(x.type==='paranthesis') return 'P';
94
+ if(x.type==='parenthesis') return 'P';
95
95
  if(x.type==='string') return 'S';
96
96
  if(x.type==='xml') return 'X';
97
97
  }