@hyperfixi/core 2.6.0 → 2.7.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 (54) hide show
  1. package/dist/api/hyperscript-api.d.ts +6 -0
  2. package/dist/ast-utils/index.js +8 -8
  3. package/dist/ast-utils/index.mjs +8 -8
  4. package/dist/bundle-generator/index.js +12 -4
  5. package/dist/bundle-generator/index.mjs +12 -4
  6. package/dist/chunks/{bridge-fFLEvCQs.js → bridge-lZbOVRDD.js} +2 -2
  7. package/dist/chunks/browser-modular-DegkWQ8d.js +2 -0
  8. package/dist/chunks/{index-BRgVy8nY.js → index-i_j9Z-1e.js} +2 -2
  9. package/dist/commands/data/set.d.ts +1 -0
  10. package/dist/commands/index.js +156 -47
  11. package/dist/commands/index.mjs +156 -47
  12. package/dist/core/context.d.ts +4 -0
  13. package/dist/dom/attribute-processor.d.ts +1 -0
  14. package/dist/hyperfixi-browser-classic-i18n.js +1 -1
  15. package/dist/hyperfixi-browser-minimal.js +1 -1
  16. package/dist/hyperfixi-browser-standard.js +1 -1
  17. package/dist/hyperfixi-browser.js +1 -1
  18. package/dist/hyperfixi-classic-i18n.js +1 -1
  19. package/dist/hyperfixi-hx-v4.js +1 -1
  20. package/dist/hyperfixi-hx.js +1 -1
  21. package/dist/hyperfixi-hybrid-complete.js +1 -1
  22. package/dist/hyperfixi-hybrid-hx.js +1 -1
  23. package/dist/hyperfixi-lite-plus.js +1 -1
  24. package/dist/hyperfixi-lite.js +1 -1
  25. package/dist/hyperfixi-minimal.js +1 -1
  26. package/dist/hyperfixi-multilingual.js +1 -1
  27. package/dist/hyperfixi-standard.js +1 -1
  28. package/dist/hyperfixi.js +1 -1
  29. package/dist/hyperfixi.mjs +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +694 -459
  32. package/dist/index.min.js +1 -1
  33. package/dist/index.mjs +691 -460
  34. package/dist/lokascript-browser-classic-i18n.js +1 -1
  35. package/dist/lokascript-browser-minimal.js +1 -1
  36. package/dist/lokascript-browser-standard.js +1 -1
  37. package/dist/lokascript-browser.js +1 -1
  38. package/dist/lokascript-hybrid-complete.js +1 -1
  39. package/dist/lokascript-hybrid-hx.js +1 -1
  40. package/dist/lokascript-lite-plus.js +1 -1
  41. package/dist/lokascript-lite.js +1 -1
  42. package/dist/lokascript-multilingual.js +1 -1
  43. package/dist/parser/full-parser.js +70 -35
  44. package/dist/parser/full-parser.mjs +70 -35
  45. package/dist/parser/parser-types.d.ts +1 -1
  46. package/dist/parser/parser.d.ts +2 -0
  47. package/dist/parser/regex-parser.js +23 -14
  48. package/dist/parser/regex-parser.mjs +23 -14
  49. package/dist/registry/index.js +178 -45
  50. package/dist/registry/index.mjs +178 -45
  51. package/dist/types/core-context.d.ts +1 -0
  52. package/package.json +6 -6
  53. package/dist/chunks/browser-modular-BK3IOo93.js +0 -2
  54. package/dist/compatibility/browser-bundle.d.ts +0 -164
@@ -3746,6 +3746,36 @@ function setGlobal(context, name, value) {
3746
3746
  }
3747
3747
  }
3748
3748
 
3749
+ const elementScopes = new WeakMap();
3750
+ function getElementScopeMap(element) {
3751
+ let map = elementScopes.get(element);
3752
+ if (!map) {
3753
+ map = new Map();
3754
+ elementScopes.set(element, map);
3755
+ }
3756
+ return map;
3757
+ }
3758
+ function resolveScopeOwner(context) {
3759
+ const owner = context.owner;
3760
+ if (owner)
3761
+ return owner;
3762
+ return context.me instanceof Element ? context.me : null;
3763
+ }
3764
+ function getElementVar(context, name) {
3765
+ const owner = resolveScopeOwner(context);
3766
+ if (!owner)
3767
+ return undefined;
3768
+ notifyLocalRead(name, context);
3769
+ return getElementScopeMap(owner).get(name);
3770
+ }
3771
+ function setElementVar(context, name, value) {
3772
+ const owner = resolveScopeOwner(context);
3773
+ if (!owner)
3774
+ return;
3775
+ getElementScopeMap(owner).set(name, value);
3776
+ notifyLocalWrite(name, value, context);
3777
+ }
3778
+
3749
3779
  function convertToNumber(value) {
3750
3780
  if (value === null || value === undefined) {
3751
3781
  return 0;
@@ -3778,6 +3808,9 @@ function convertToNumber(value) {
3778
3808
  return 0;
3779
3809
  }
3780
3810
  function getVariableValue(name, context, preferredScope) {
3811
+ if (preferredScope === 'element') {
3812
+ return getElementVar(context, name);
3813
+ }
3781
3814
  if (preferredScope === 'global' && context.globals && context.globals.has(name)) {
3782
3815
  return context.globals.get(name);
3783
3816
  }
@@ -3804,6 +3837,10 @@ function getVariableValue(name, context, preferredScope) {
3804
3837
  return undefined;
3805
3838
  }
3806
3839
  function setVariableValue(name, value, context, preferredScope) {
3840
+ if (preferredScope === 'element') {
3841
+ setElementVar(context, name, value);
3842
+ return;
3843
+ }
3807
3844
  if (preferredScope === 'global') {
3808
3845
  setGlobal(context, name, value);
3809
3846
  if (typeof window !== 'undefined') {
@@ -3897,6 +3934,9 @@ function getCurrentNumericValue(target, property, scope, context) {
3897
3934
  }
3898
3935
  }
3899
3936
  if (typeof target === 'string') {
3937
+ if (scope === 'element') {
3938
+ return convertToNumber(getVariableValue(target, context, 'element'));
3939
+ }
3900
3940
  if (scope === 'global') {
3901
3941
  const value = getVariableValue(target, context, 'global');
3902
3942
  return convertToNumber(value);
@@ -3941,6 +3981,10 @@ function setTargetValue(target, property, scope, newValue, context) {
3941
3981
  return;
3942
3982
  }
3943
3983
  if (typeof target === 'string') {
3984
+ if (scope === 'element') {
3985
+ setVariableValue(target, newValue, context, 'element');
3986
+ return;
3987
+ }
3944
3988
  if (scope === 'global') {
3945
3989
  setVariableValue(target, newValue, context, 'global');
3946
3990
  return;
@@ -9179,7 +9223,7 @@ function parseColonVariable(ctx) {
9179
9223
  return {
9180
9224
  type: 'identifier',
9181
9225
  name: varToken.value,
9182
- scope: 'local',
9226
+ scope: 'element',
9183
9227
  start: varToken.start - 1,
9184
9228
  end: varToken.end,
9185
9229
  };
@@ -9231,7 +9275,7 @@ function parseTargetFallback(ctx) {
9231
9275
  expression: {
9232
9276
  type: 'identifier',
9233
9277
  name: varToken.value,
9234
- scope: 'local',
9278
+ scope: 'element',
9235
9279
  start: varToken.start,
9236
9280
  end: varToken.end,
9237
9281
  },
@@ -9312,6 +9356,11 @@ function parseSetCommand(ctx, identifierNode) {
9312
9356
  }
9313
9357
  ctx.advance();
9314
9358
  const value = ctx.parseExpression() ?? ctx.parsePrimary();
9359
+ let scopeTarget;
9360
+ if (ctx.check(KEYWORDS$1.ON) && tokenLooksLikeElementTarget(ctx.peekAt(1))) {
9361
+ ctx.advance();
9362
+ scopeTarget = parseOneArgument(ctx);
9363
+ }
9315
9364
  const finalArgs = [];
9316
9365
  if (targetExpression) {
9317
9366
  finalArgs.push(targetExpression);
@@ -9323,11 +9372,22 @@ function parseSetCommand(ctx, identifierNode) {
9323
9372
  if (value) {
9324
9373
  finalArgs.push(value);
9325
9374
  }
9326
- return CommandNodeBuilder.fromIdentifier(identifierNode)
9327
- .withArgs(...finalArgs)
9328
- .endingAt(ctx.getPosition())
9329
- .build();
9375
+ const builder = CommandNodeBuilder.fromIdentifier(identifierNode).withArgs(...finalArgs);
9376
+ if (scopeTarget) {
9377
+ builder.withModifier('on', scopeTarget);
9378
+ }
9379
+ return builder.endingAt(ctx.getPosition()).build();
9330
9380
  }
9381
+ function tokenLooksLikeElementTarget(token) {
9382
+ if (!token)
9383
+ return false;
9384
+ if (token.kind === 'selector')
9385
+ return true;
9386
+ if (token.value.startsWith('<'))
9387
+ return true;
9388
+ return ELEMENT_PRONOUNS.has(token.value);
9389
+ }
9390
+ const ELEMENT_PRONOUNS = new Set(['me', 'my', 'it', 'its', 'you', 'your', 'yourself']);
9331
9391
  function parseIncrementDecrementCommand(ctx, commandToken) {
9332
9392
  const commandName = commandToken.value;
9333
9393
  const isIncrement = commandName === 'increment';
@@ -9373,6 +9433,7 @@ function parseIncrementDecrementCommand(ctx, commandToken) {
9373
9433
  column: commandToken.column,
9374
9434
  };
9375
9435
  const binaryExpr = createBinaryExpression(operator, target, amount, pos);
9436
+ binaryExpr.coerceNumeric = true;
9376
9437
  const toIdentifier = createIdentifier(KEYWORDS$1.TO, pos);
9377
9438
  const args = [targetWithScope, toIdentifier, binaryExpr];
9378
9439
  return CommandNodeBuilder.from(commandToken)
@@ -9991,6 +10052,18 @@ class Parser {
9991
10052
  this.advance();
9992
10053
  continue;
9993
10054
  }
10055
+ if (this.check('then')) {
10056
+ const next = this.peekAt(1);
10057
+ const startsFeature = next !== null &&
10058
+ (next.value === 'init' ||
10059
+ next.value === 'on' ||
10060
+ next.value === 'def' ||
10061
+ getRegisteredFeature(next.value) !== undefined);
10062
+ if (startsFeature) {
10063
+ this.advance();
10064
+ continue;
10065
+ }
10066
+ }
9994
10067
  if (this.check('init')) {
9995
10068
  this.advance();
9996
10069
  const initBlock = this.parseTopLevelInitBlock();
@@ -10791,7 +10864,7 @@ class Parser {
10791
10864
  return {
10792
10865
  type: 'identifier',
10793
10866
  name: varToken.value,
10794
- scope: 'local',
10867
+ scope: 'element',
10795
10868
  start: varToken.start - 1,
10796
10869
  end: varToken.end,
10797
10870
  line: varToken.line,
@@ -11418,6 +11491,33 @@ class Parser {
11418
11491
  return null;
11419
11492
  }
11420
11493
  }
11494
+ parseTemporalKeywordModifiers(modifiers) {
11495
+ if (!this.check('debounced') && !this.check('throttled')) {
11496
+ return;
11497
+ }
11498
+ const modToken = this.advance();
11499
+ const modName = modToken.value.toLowerCase();
11500
+ const modifierKey = modName === 'debounced' ? 'debounce' : 'throttle';
11501
+ if (this.match('at')) {
11502
+ if (this.checkTimeExpression()) {
11503
+ const timeToken = this.advance();
11504
+ const delayMs = parseTimeToMs(timeToken.value);
11505
+ modifiers[modifierKey] = delayMs;
11506
+ debug.parse(`🔧 parseEventHandler: Parsed '${modName} at ${timeToken.value}' (${delayMs}ms)`);
11507
+ }
11508
+ else if (this.matchNumber()) {
11509
+ const delayMs = parseInt(this.previous().value, 10);
11510
+ modifiers[modifierKey] = delayMs;
11511
+ debug.parse(`🔧 parseEventHandler: Parsed '${modName} at ${delayMs}'`);
11512
+ }
11513
+ else {
11514
+ this.addError(`Expected time expression after '${modName} at', got: ${this.peek().value}`);
11515
+ }
11516
+ }
11517
+ else {
11518
+ this.addError(`Expected 'at' after '${modName}'`);
11519
+ }
11520
+ }
11421
11521
  parseEventHandler() {
11422
11522
  debug.parse(`🔧 parseEventHandler: ENTRY - parsing event handler`);
11423
11523
  const eventNames = [];
@@ -11505,30 +11605,7 @@ class Parser {
11505
11605
  debug.parse(`🔧 parseEventHandler: Warning - unknown modifier '.${modName}'`);
11506
11606
  }
11507
11607
  }
11508
- if (this.check('debounced') || this.check('throttled')) {
11509
- const modToken = this.advance();
11510
- const modName = modToken.value.toLowerCase();
11511
- const modifierKey = modName === 'debounced' ? 'debounce' : 'throttle';
11512
- if (this.match('at')) {
11513
- if (this.checkTimeExpression()) {
11514
- const timeToken = this.advance();
11515
- const delayMs = parseTimeToMs(timeToken.value);
11516
- modifiers[modifierKey] = delayMs;
11517
- debug.parse(`🔧 parseEventHandler: Parsed '${modName} at ${timeToken.value}' (${delayMs}ms)`);
11518
- }
11519
- else if (this.matchNumber()) {
11520
- const delayMs = parseInt(this.previous().value, 10);
11521
- modifiers[modifierKey] = delayMs;
11522
- debug.parse(`🔧 parseEventHandler: Parsed '${modName} at ${delayMs}'`);
11523
- }
11524
- else {
11525
- this.addError(`Expected time expression after '${modName} at', got: ${this.peek().value}`);
11526
- }
11527
- }
11528
- else {
11529
- this.addError(`Expected 'at' after '${modName}'`);
11530
- }
11531
- }
11608
+ this.parseTemporalKeywordModifiers(modifiers);
11532
11609
  if (firstOnceAlias) {
11533
11610
  modifiers.once = true;
11534
11611
  }
@@ -11545,6 +11622,7 @@ class Parser {
11545
11622
  const targetToken = this.advance();
11546
11623
  target = targetToken.value;
11547
11624
  debug.parse(`🔧 parseEventHandler: Parsed 'from' target: ${target} (kind: ${targetToken.kind})`);
11625
+ this.parseTemporalKeywordModifiers(modifiers);
11548
11626
  }
11549
11627
  let attributeName;
11550
11628
  if (this.match('of')) {
@@ -12515,6 +12593,10 @@ class Parser {
12515
12593
  }
12516
12594
  return this.tokens[this.current];
12517
12595
  }
12596
+ peekAt(offset) {
12597
+ const index = this.current + offset;
12598
+ return index >= 0 && index < this.tokens.length ? this.tokens[index] : null;
12599
+ }
12518
12600
  previous() {
12519
12601
  return this.tokens[this.current - 1];
12520
12602
  }
@@ -12719,10 +12801,7 @@ class Parser {
12719
12801
  restorePosition: (pos) => {
12720
12802
  parser.current = pos;
12721
12803
  },
12722
- peekAt: (offset) => {
12723
- const index = parser.current + offset;
12724
- return index >= 0 && index < parser.tokens.length ? parser.tokens[index] : null;
12725
- },
12804
+ peekAt: (offset) => parser.peekAt(offset),
12726
12805
  getInputSlice: (start, end) => {
12727
12806
  if (!this.originalInput)
12728
12807
  return '';
@@ -12866,7 +12945,7 @@ function evaluateExpressionSync(node, context) {
12866
12945
  case 'selector':
12867
12946
  return evaluateSelectorSync(n, context);
12868
12947
  case 'identifier':
12869
- return resolveIdentifierSync(n.name, context);
12948
+ return resolveIdentifierSync(n.name, context, n.scope);
12870
12949
  case 'contextReference':
12871
12950
  return resolveContextReferenceSync(n.contextType, context);
12872
12951
  case 'arrayLiteral':
@@ -12902,7 +12981,7 @@ function evaluateExpressionSync(node, context) {
12902
12981
  throw new NotSyncEvaluable(n?.type ?? 'unknown');
12903
12982
  }
12904
12983
  }
12905
- function resolveIdentifierSync(name, context) {
12984
+ function resolveIdentifierSync(name, context, scope) {
12906
12985
  if (name === 'me' || name === 'my' || name === 'I')
12907
12986
  return context.me;
12908
12987
  if (name === 'you' || name === 'your' || name === 'yourself')
@@ -12913,6 +12992,8 @@ function resolveIdentifierSync(name, context) {
12913
12992
  return typeof window !== 'undefined' ? window : globalThis;
12914
12993
  if (name === 'document')
12915
12994
  return typeof document !== 'undefined' ? document : undefined;
12995
+ if (scope === 'element')
12996
+ return getElementVar(context, name);
12916
12997
  if (context.locals?.has(name))
12917
12998
  return context.locals.get(name);
12918
12999
  if (context.globals?.has(name))
@@ -13042,6 +13123,9 @@ async function evaluateIdentifier(node, context) {
13042
13123
  notifyGlobalRead(name, context);
13043
13124
  return context.globals.get(name);
13044
13125
  }
13126
+ if (node.scope === 'element') {
13127
+ return getElementVar(context, name);
13128
+ }
13045
13129
  if (context.locals && context.locals.has(name)) {
13046
13130
  notifyLocalRead(name, context);
13047
13131
  return context.locals.get(name);
@@ -13077,6 +13161,9 @@ async function evaluateBinaryExpression(node, context) {
13077
13161
  else if (leftNode.scope === 'global') {
13078
13162
  setGlobal(context, name, value);
13079
13163
  }
13164
+ else if (leftNode.scope === 'element') {
13165
+ setElementVar(context, name, value);
13166
+ }
13080
13167
  else {
13081
13168
  if (!context.locals)
13082
13169
  context.locals = new Map();
@@ -13158,14 +13245,26 @@ async function evaluateBinaryExpression(node, context) {
13158
13245
  const L = node.ignoringCase ? applyCI(left) : left;
13159
13246
  const R = node.ignoringCase ? applyCI(right) : right;
13160
13247
  switch (operator) {
13161
- case '+':
13162
- if (typeof left === 'string' || typeof right === 'string') {
13163
- return String(left ?? '') + String(right ?? '');
13164
- }
13165
- if (Array.isArray(left)) {
13166
- return Array.isArray(right) ? [...left, ...right] : [...left, right];
13167
- }
13168
- return unwrapTypedResult(await getExpr(context, 'addition').evaluate(context, { left, right }));
13248
+ case '+': {
13249
+ let addLeft = left;
13250
+ let addRight = right;
13251
+ if (node.coerceNumeric) {
13252
+ if (typeof addLeft === 'string')
13253
+ addLeft = convertToNumber(addLeft);
13254
+ if (typeof addRight === 'string')
13255
+ addRight = convertToNumber(addRight);
13256
+ }
13257
+ if (typeof addLeft === 'string' || typeof addRight === 'string') {
13258
+ return String(addLeft ?? '') + String(addRight ?? '');
13259
+ }
13260
+ if (Array.isArray(addLeft)) {
13261
+ return Array.isArray(addRight) ? [...addLeft, ...addRight] : [...addLeft, addRight];
13262
+ }
13263
+ return unwrapTypedResult(await getExpr(context, 'addition').evaluate(context, {
13264
+ left: addLeft,
13265
+ right: addRight,
13266
+ }));
13267
+ }
13169
13268
  case '-':
13170
13269
  return unwrapTypedResult(await getExpr(context, 'subtraction').evaluate(context, { left, right }));
13171
13270
  case '*':
@@ -16676,6 +16775,7 @@ let SetCommand = (() => {
16676
16775
  }
16677
16776
  const firstArg = raw.args[0];
16678
16777
  const argName = (firstArg?.name || firstArg?.value);
16778
+ const argScope = firstArg?.scope;
16679
16779
  const firstArgType = firstArg?.type;
16680
16780
  if (firstArgType) {
16681
16781
  const writer = getRegisteredNodeWriter(firstArgType);
@@ -16769,12 +16869,21 @@ let SetCommand = (() => {
16769
16869
  throw new Error(`set command target must be a string or object literal${hint}`);
16770
16870
  }
16771
16871
  const value = await this.extractValue(raw, evaluator, context);
16772
- return { type: 'variable', name: firstValue, value };
16872
+ const scope = argScope === 'element' || argScope === 'global' ? argScope : undefined;
16873
+ return { type: 'variable', name: firstValue, value, scope };
16773
16874
  }
16774
16875
  async execute(input, context) {
16775
16876
  switch (input.type) {
16776
16877
  case 'variable':
16777
- setVariableValue(input.name, input.value, context);
16878
+ if (input.scope === 'element') {
16879
+ setElementVar(context, input.name, input.value);
16880
+ }
16881
+ else if (input.scope === 'global') {
16882
+ setVariableValue(input.name, input.value, context, 'global');
16883
+ }
16884
+ else {
16885
+ setVariableValue(input.name, input.value, context);
16886
+ }
16778
16887
  if (input.name === 'result' || input.name === 'it') {
16779
16888
  Object.assign(context, { [input.name]: input.value });
16780
16889
  }
@@ -1,4 +1,8 @@
1
1
  import type { ExecutionContext } from '../types/core';
2
+ export declare function getElementScopeMap(element: Element): Map<string, unknown>;
3
+ export declare function resolveScopeOwner(context: ExecutionContext): Element | null;
4
+ export declare function getElementVar(context: ExecutionContext, name: string): unknown;
5
+ export declare function setElementVar(context: ExecutionContext, name: string, value: unknown): void;
2
6
  export declare function createContext(element?: Element | null, globals?: Map<string, any>): ExecutionContext;
3
7
  export declare function getSharedGlobals(): Map<string, any>;
4
8
  export declare function createChildContext(parent: ExecutionContext, element?: Element | null): ExecutionContext;
@@ -22,6 +22,7 @@ export declare class AttributeProcessor {
22
22
  constructor(options?: AttributeProcessorOptions);
23
23
  init(): Promise<void>;
24
24
  scanAndProcessAll(): Promise<void>;
25
+ private reportCompileError;
25
26
  private processHyperscriptTag;
26
27
  private processHyperscriptTagForElements;
27
28
  private processHyperscriptTagGlobal;