@hyperfixi/core 2.9.4 → 2.11.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 (102) hide show
  1. package/dist/ast-utils/index.js +400 -89
  2. package/dist/ast-utils/index.mjs +400 -89
  3. package/dist/behaviors/index.js +2 -1
  4. package/dist/behaviors/index.mjs +2 -1
  5. package/dist/chunks/{bridge-DhmZ3Khh.js → bridge-De7lnU_9.js} +2 -2
  6. package/dist/chunks/browser-modular-DpHHlmJ0.js +2 -0
  7. package/dist/chunks/{index-DKrx4rv2.js → index-D6-8bcsy.js} +2 -2
  8. package/dist/commands/advanced/async.d.ts +0 -8
  9. package/dist/commands/advanced/js.d.ts +0 -8
  10. package/dist/commands/animation/measure.d.ts +0 -8
  11. package/dist/commands/animation/settle.d.ts +0 -8
  12. package/dist/commands/animation/start-view-transition.d.ts +0 -8
  13. package/dist/commands/animation/take.d.ts +0 -8
  14. package/dist/commands/animation/transition.d.ts +0 -8
  15. package/dist/commands/async/fetch.d.ts +0 -8
  16. package/dist/commands/async/wait.d.ts +0 -8
  17. package/dist/commands/behaviors/install.d.ts +0 -8
  18. package/dist/commands/content/append.d.ts +0 -8
  19. package/dist/commands/content/prepend.d.ts +0 -8
  20. package/dist/commands/control-flow/break.d.ts +0 -8
  21. package/dist/commands/control-flow/continue.d.ts +0 -8
  22. package/dist/commands/control-flow/exit.d.ts +0 -8
  23. package/dist/commands/control-flow/halt.d.ts +0 -8
  24. package/dist/commands/control-flow/if.d.ts +0 -8
  25. package/dist/commands/control-flow/repeat.d.ts +0 -8
  26. package/dist/commands/control-flow/return.d.ts +0 -8
  27. package/dist/commands/control-flow/throw.d.ts +0 -8
  28. package/dist/commands/data/clear.d.ts +0 -8
  29. package/dist/commands/data/default.d.ts +0 -8
  30. package/dist/commands/data/get.d.ts +0 -8
  31. package/dist/commands/data/increment.d.ts +0 -8
  32. package/dist/commands/data/set.d.ts +0 -8
  33. package/dist/commands/decorators/index.d.ts +2 -8
  34. package/dist/commands/dom/add.d.ts +0 -8
  35. package/dist/commands/dom/close.d.ts +0 -8
  36. package/dist/commands/dom/empty.d.ts +0 -8
  37. package/dist/commands/dom/hide.d.ts +0 -8
  38. package/dist/commands/dom/make.d.ts +0 -8
  39. package/dist/commands/dom/open.d.ts +0 -8
  40. package/dist/commands/dom/process-partials.d.ts +0 -8
  41. package/dist/commands/dom/put.d.ts +0 -8
  42. package/dist/commands/dom/remove.d.ts +0 -8
  43. package/dist/commands/dom/reset.d.ts +0 -8
  44. package/dist/commands/dom/select.d.ts +0 -8
  45. package/dist/commands/dom/show.d.ts +0 -8
  46. package/dist/commands/dom/swap.d.ts +2 -18
  47. package/dist/commands/dom/toggle.d.ts +0 -8
  48. package/dist/commands/events/trigger.d.ts +0 -8
  49. package/dist/commands/execution/blur.d.ts +0 -8
  50. package/dist/commands/execution/call.d.ts +0 -8
  51. package/dist/commands/execution/focus.d.ts +0 -8
  52. package/dist/commands/execution/pseudo-command.d.ts +0 -8
  53. package/dist/commands/helpers/dom-mutation.d.ts +3 -2
  54. package/dist/commands/helpers/index.d.ts +1 -1
  55. package/dist/commands/index.js +156 -31
  56. package/dist/commands/index.mjs +156 -31
  57. package/dist/commands/navigation/go.d.ts +0 -8
  58. package/dist/commands/navigation/push-url.d.ts +0 -8
  59. package/dist/commands/navigation/scroll-to.d.ts +0 -8
  60. package/dist/commands/templates/render.d.ts +0 -8
  61. package/dist/commands/utility/beep.d.ts +0 -8
  62. package/dist/commands/utility/breakpoint.d.ts +0 -8
  63. package/dist/commands/utility/copy.d.ts +0 -8
  64. package/dist/commands/utility/log.d.ts +0 -8
  65. package/dist/commands/utility/pick.d.ts +0 -8
  66. package/dist/commands/utility/tell.d.ts +0 -8
  67. package/dist/hyperfixi-browser-classic-i18n.js +1 -1
  68. package/dist/hyperfixi-browser-minimal.js +1 -1
  69. package/dist/hyperfixi-browser-standard.js +1 -1
  70. package/dist/hyperfixi-browser.js +1 -1
  71. package/dist/hyperfixi-classic-i18n.js +1 -1
  72. package/dist/hyperfixi-hx-v4.js +1 -1
  73. package/dist/hyperfixi-minimal.js +1 -1
  74. package/dist/hyperfixi-multilingual.js +1 -1
  75. package/dist/hyperfixi-standard.js +1 -1
  76. package/dist/hyperfixi.js +1 -1
  77. package/dist/hyperfixi.mjs +1 -1
  78. package/dist/index.js +660 -171
  79. package/dist/index.min.js +1 -1
  80. package/dist/index.mjs +660 -171
  81. package/dist/lokascript-browser-classic-i18n.js +1 -1
  82. package/dist/lokascript-browser-minimal.js +1 -1
  83. package/dist/lokascript-browser-standard.js +1 -1
  84. package/dist/lokascript-browser.js +1 -1
  85. package/dist/lokascript-multilingual.js +1 -1
  86. package/dist/lsp-metadata.js +2 -2
  87. package/dist/lsp-metadata.mjs +2 -2
  88. package/dist/metadata.d.ts +1 -1
  89. package/dist/metadata.js +13 -11
  90. package/dist/metadata.mjs +13 -11
  91. package/dist/parser/command-parsers/dom-commands.d.ts +1 -0
  92. package/dist/parser/full-parser.js +47 -1
  93. package/dist/parser/full-parser.mjs +47 -1
  94. package/dist/reference/index.js +13 -7
  95. package/dist/reference/index.mjs +13 -7
  96. package/dist/registry/index.js +56 -10
  97. package/dist/registry/index.mjs +56 -10
  98. package/dist/runtime/command-adapter.d.ts +8 -8
  99. package/dist/utils/element-check.d.ts +1 -0
  100. package/dist/version.d.ts +2 -0
  101. package/package.json +5 -5
  102. package/dist/chunks/browser-modular-BllAMlht.js +0 -2
@@ -167,8 +167,8 @@ const HOVER_DOCS = {
167
167
  },
168
168
  put: {
169
169
  title: 'put',
170
- description: 'Sets the content of an element.',
171
- example: 'put "Hello" into #message\nput response into #results',
170
+ description: 'Sets the content of an element. An array of elements is moved in order (an in-place reorder when they are already children of the target).',
171
+ example: 'put "Hello" into #message\nput response into #results\nput <tr/> in me sorted by its @data-price as Number at end of me',
172
172
  category: 'command',
173
173
  },
174
174
  set: {
@@ -165,8 +165,8 @@ const HOVER_DOCS = {
165
165
  },
166
166
  put: {
167
167
  title: 'put',
168
- description: 'Sets the content of an element.',
169
- example: 'put "Hello" into #message\nput response into #results',
168
+ description: 'Sets the content of an element. An array of elements is moved in order (an in-place reorder when they are already children of the target).',
169
+ example: 'put "Hello" into #message\nput response into #results\nput <tr/> in me sorted by its @data-price as Number at end of me',
170
170
  category: 'command',
171
171
  },
172
172
  set: {
@@ -1,6 +1,6 @@
1
1
  export declare const packageInfo: {
2
2
  readonly name: "@hyperfixi/core";
3
- readonly version: "2.7.2";
3
+ readonly version: "2.10.0";
4
4
  readonly description: "Modern hyperscript engine with fixi/htmx integration";
5
5
  readonly compatibility: "~85% official _hyperscript";
6
6
  readonly languages: 24;
package/dist/metadata.js CHANGED
@@ -62,10 +62,12 @@ const COMMAND_NAMES = [
62
62
  'wait',
63
63
  ];
64
64
 
65
+ const VERSION = '2.10.0';
66
+
65
67
  const FULL_RUNTIME_COMMAND_COUNT = COMMAND_NAMES.length;
66
68
  const packageInfo = {
67
69
  name: '@hyperfixi/core',
68
- version: '2.7.2',
70
+ version: VERSION,
69
71
  description: 'Modern hyperscript engine with fixi/htmx integration',
70
72
  compatibility: '~85% official _hyperscript',
71
73
  languages: 24,
@@ -146,8 +148,8 @@ const bundleInfo = [
146
148
  id: 'hybrid-hx-v4',
147
149
  name: 'Hybrid HX v4',
148
150
  filename: 'hyperfixi-hx-v4.js',
149
- gzipSize: '320.9 KB',
150
- rawSize: '1490 KB',
151
+ gzipSize: '322.4 KB',
152
+ rawSize: '1501 KB',
151
153
  commandCount: FULL_RUNTIME_COMMAND_COUNT,
152
154
  parser: 'full',
153
155
  hasBlocks: true,
@@ -163,8 +165,8 @@ const bundleInfo = [
163
165
  id: 'minimal',
164
166
  name: 'Minimal',
165
167
  filename: 'hyperfixi-minimal.js',
166
- gzipSize: '71.5 KB',
167
- rawSize: '289 KB',
168
+ gzipSize: '71.9 KB',
169
+ rawSize: '292 KB',
168
170
  commandCount: 10,
169
171
  parser: 'full',
170
172
  hasBlocks: true,
@@ -180,8 +182,8 @@ const bundleInfo = [
180
182
  id: 'standard',
181
183
  name: 'Standard',
182
184
  filename: 'hyperfixi-standard.js',
183
- gzipSize: '78.3 KB',
184
- rawSize: '317 KB',
185
+ gzipSize: '78.8 KB',
186
+ rawSize: '321 KB',
185
187
  commandCount: 25,
186
188
  parser: 'full',
187
189
  hasBlocks: true,
@@ -197,8 +199,8 @@ const bundleInfo = [
197
199
  id: 'browser',
198
200
  name: 'Full Browser',
199
201
  filename: 'hyperfixi.js',
200
- gzipSize: '309.1 KB',
201
- rawSize: '1453 KB',
202
+ gzipSize: '310.8 KB',
203
+ rawSize: '1464 KB',
202
204
  commandCount: FULL_RUNTIME_COMMAND_COUNT,
203
205
  parser: 'full',
204
206
  hasBlocks: true,
@@ -214,8 +216,8 @@ const bundleInfo = [
214
216
  id: 'multilingual',
215
217
  name: 'Multilingual',
216
218
  filename: 'hyperfixi-multilingual.js',
217
- gzipSize: '93.4 KB',
218
- rawSize: '380 KB',
219
+ gzipSize: '94.5 KB',
220
+ rawSize: '388 KB',
219
221
  commandCount: 52,
220
222
  parser: 'full',
221
223
  hasBlocks: true,
package/dist/metadata.mjs CHANGED
@@ -60,10 +60,12 @@ const COMMAND_NAMES = [
60
60
  'wait',
61
61
  ];
62
62
 
63
+ const VERSION = '2.10.0';
64
+
63
65
  const FULL_RUNTIME_COMMAND_COUNT = COMMAND_NAMES.length;
64
66
  const packageInfo = {
65
67
  name: '@hyperfixi/core',
66
- version: '2.7.2',
68
+ version: VERSION,
67
69
  description: 'Modern hyperscript engine with fixi/htmx integration',
68
70
  compatibility: '~85% official _hyperscript',
69
71
  languages: 24,
@@ -144,8 +146,8 @@ const bundleInfo = [
144
146
  id: 'hybrid-hx-v4',
145
147
  name: 'Hybrid HX v4',
146
148
  filename: 'hyperfixi-hx-v4.js',
147
- gzipSize: '320.9 KB',
148
- rawSize: '1490 KB',
149
+ gzipSize: '322.4 KB',
150
+ rawSize: '1501 KB',
149
151
  commandCount: FULL_RUNTIME_COMMAND_COUNT,
150
152
  parser: 'full',
151
153
  hasBlocks: true,
@@ -161,8 +163,8 @@ const bundleInfo = [
161
163
  id: 'minimal',
162
164
  name: 'Minimal',
163
165
  filename: 'hyperfixi-minimal.js',
164
- gzipSize: '71.5 KB',
165
- rawSize: '289 KB',
166
+ gzipSize: '71.9 KB',
167
+ rawSize: '292 KB',
166
168
  commandCount: 10,
167
169
  parser: 'full',
168
170
  hasBlocks: true,
@@ -178,8 +180,8 @@ const bundleInfo = [
178
180
  id: 'standard',
179
181
  name: 'Standard',
180
182
  filename: 'hyperfixi-standard.js',
181
- gzipSize: '78.3 KB',
182
- rawSize: '317 KB',
183
+ gzipSize: '78.8 KB',
184
+ rawSize: '321 KB',
183
185
  commandCount: 25,
184
186
  parser: 'full',
185
187
  hasBlocks: true,
@@ -195,8 +197,8 @@ const bundleInfo = [
195
197
  id: 'browser',
196
198
  name: 'Full Browser',
197
199
  filename: 'hyperfixi.js',
198
- gzipSize: '309.1 KB',
199
- rawSize: '1453 KB',
200
+ gzipSize: '310.8 KB',
201
+ rawSize: '1464 KB',
200
202
  commandCount: FULL_RUNTIME_COMMAND_COUNT,
201
203
  parser: 'full',
202
204
  hasBlocks: true,
@@ -212,8 +214,8 @@ const bundleInfo = [
212
214
  id: 'multilingual',
213
215
  name: 'Multilingual',
214
216
  filename: 'hyperfixi-multilingual.js',
215
- gzipSize: '93.4 KB',
216
- rawSize: '380 KB',
217
+ gzipSize: '94.5 KB',
218
+ rawSize: '388 KB',
217
219
  commandCount: 52,
218
220
  parser: 'full',
219
221
  hasBlocks: true,
@@ -3,6 +3,7 @@ import type { Token } from '../../types/core';
3
3
  export declare function parseRemoveCommand(ctx: ParserContext, identifierNode: IdentifierNode): import("../..").CommandNode;
4
4
  export declare function parseToggleCommand(ctx: ParserContext, identifierNode: IdentifierNode): import("../..").CommandNode;
5
5
  export declare function parseTakeCommand(ctx: ParserContext, identifierNode: IdentifierNode): import("../..").CommandNode;
6
+ export declare function parseProcessCommand(ctx: ParserContext, identifierNode: IdentifierNode): import("../..").CommandNode | null;
6
7
  export declare function parseAddCommand(ctx: ParserContext, commandToken: Token): import("../..").CommandNode;
7
8
  export declare function parsePutCommand(ctx: ParserContext, identifierNode: IdentifierNode): import("../..").CommandNode | null;
8
9
  export declare function parseSwapCommand(ctx: ParserContext, identifierNode: IdentifierNode): import("../..").CommandNode;
@@ -3820,6 +3820,40 @@ function parseTakeCommand(ctx, identifierNode) {
3820
3820
  .endingAt(ctx.getPosition())
3821
3821
  .build();
3822
3822
  }
3823
+ function consumeViewTransitionTail(ctx, args) {
3824
+ if (!ctx.check('using')) {
3825
+ return false;
3826
+ }
3827
+ ctx.advance();
3828
+ if (!ctx.match('view')) {
3829
+ throw new Error("expected 'view transition' after 'using'");
3830
+ }
3831
+ if (!ctx.match('transition')) {
3832
+ throw new Error("expected 'transition' after 'using view'");
3833
+ }
3834
+ args.push(ctx.createIdentifier('using'));
3835
+ args.push(ctx.createIdentifier('view'));
3836
+ args.push(ctx.createIdentifier('transition'));
3837
+ return true;
3838
+ }
3839
+ function parseProcessCommand(ctx, identifierNode) {
3840
+ if (!ctx.check('partials')) {
3841
+ return null;
3842
+ }
3843
+ const args = [];
3844
+ consumeKeywordToArgs(ctx, 'partials', args);
3845
+ if (consumeKeywordToArgs(ctx, KEYWORDS.IN, args)) {
3846
+ const contentArg = parseOneArgument(ctx, ['using']);
3847
+ if (contentArg) {
3848
+ args.push(contentArg);
3849
+ }
3850
+ }
3851
+ consumeViewTransitionTail(ctx, args);
3852
+ return CommandNodeBuilder.fromIdentifier(identifierNode)
3853
+ .withArgs(...args)
3854
+ .endingAt(ctx.getPosition())
3855
+ .build();
3856
+ }
3823
3857
  function parseAddCommand(ctx, commandToken) {
3824
3858
  const args = [];
3825
3859
  if (ctx.match('{')) {
@@ -3941,6 +3975,7 @@ function parseSwapCommand(ctx, identifierNode) {
3941
3975
  args.push(contentExpr);
3942
3976
  }
3943
3977
  }
3978
+ consumeViewTransitionTail(ctx, args);
3944
3979
  return CommandNodeBuilder.fromIdentifier(identifierNode)
3945
3980
  .withArgs(...args)
3946
3981
  .endingAt(ctx.getPosition())
@@ -4454,6 +4489,9 @@ function parseCompoundCommand(ctx, identifierNode) {
4454
4489
  case 'swap':
4455
4490
  case 'morph':
4456
4491
  return parseSwapCommand(ctx, identifierNode);
4492
+ case 'process':
4493
+ return (parseProcessCommand(ctx, identifierNode) ??
4494
+ parseRegularCommand(ctx, identifierNode));
4457
4495
  default:
4458
4496
  return parseRegularCommand(ctx, identifierNode);
4459
4497
  }
@@ -4785,6 +4823,9 @@ function parseTellCommand(ctx, identifierNode) {
4785
4823
  if (!target) {
4786
4824
  throw new Error('tell command requires a target expression');
4787
4825
  }
4826
+ if (ctx.check(KEYWORDS.TO)) {
4827
+ ctx.advance();
4828
+ }
4788
4829
  const commands = [];
4789
4830
  while (!ctx.isAtEnd()) {
4790
4831
  if (ctx.checkIsCommand()) {
@@ -4804,7 +4845,11 @@ function parseTellCommand(ctx, identifierNode) {
4804
4845
  if (ctx.match(KEYWORDS.AND) || ctx.match(KEYWORDS.THEN)) {
4805
4846
  continue;
4806
4847
  }
4807
- if (ctx.check(KEYWORDS.ELSE) || ctx.check(KEYWORDS.END)) {
4848
+ if (ctx.check(KEYWORDS.ELSE)) {
4849
+ break;
4850
+ }
4851
+ if (ctx.check(KEYWORDS.END)) {
4852
+ ctx.advance();
4808
4853
  break;
4809
4854
  }
4810
4855
  if (ctx.checkIsCommand()) {
@@ -7142,6 +7187,7 @@ class Parser {
7142
7187
  'js',
7143
7188
  'tell',
7144
7189
  'fetch',
7190
+ 'process',
7145
7191
  ];
7146
7192
  if (this.semanticAdapter && !skipSemanticParsing.includes(commandName.toLowerCase())) {
7147
7193
  const remainingInput = this.getRemainingInput();
@@ -3818,6 +3818,40 @@ function parseTakeCommand(ctx, identifierNode) {
3818
3818
  .endingAt(ctx.getPosition())
3819
3819
  .build();
3820
3820
  }
3821
+ function consumeViewTransitionTail(ctx, args) {
3822
+ if (!ctx.check('using')) {
3823
+ return false;
3824
+ }
3825
+ ctx.advance();
3826
+ if (!ctx.match('view')) {
3827
+ throw new Error("expected 'view transition' after 'using'");
3828
+ }
3829
+ if (!ctx.match('transition')) {
3830
+ throw new Error("expected 'transition' after 'using view'");
3831
+ }
3832
+ args.push(ctx.createIdentifier('using'));
3833
+ args.push(ctx.createIdentifier('view'));
3834
+ args.push(ctx.createIdentifier('transition'));
3835
+ return true;
3836
+ }
3837
+ function parseProcessCommand(ctx, identifierNode) {
3838
+ if (!ctx.check('partials')) {
3839
+ return null;
3840
+ }
3841
+ const args = [];
3842
+ consumeKeywordToArgs(ctx, 'partials', args);
3843
+ if (consumeKeywordToArgs(ctx, KEYWORDS.IN, args)) {
3844
+ const contentArg = parseOneArgument(ctx, ['using']);
3845
+ if (contentArg) {
3846
+ args.push(contentArg);
3847
+ }
3848
+ }
3849
+ consumeViewTransitionTail(ctx, args);
3850
+ return CommandNodeBuilder.fromIdentifier(identifierNode)
3851
+ .withArgs(...args)
3852
+ .endingAt(ctx.getPosition())
3853
+ .build();
3854
+ }
3821
3855
  function parseAddCommand(ctx, commandToken) {
3822
3856
  const args = [];
3823
3857
  if (ctx.match('{')) {
@@ -3939,6 +3973,7 @@ function parseSwapCommand(ctx, identifierNode) {
3939
3973
  args.push(contentExpr);
3940
3974
  }
3941
3975
  }
3976
+ consumeViewTransitionTail(ctx, args);
3942
3977
  return CommandNodeBuilder.fromIdentifier(identifierNode)
3943
3978
  .withArgs(...args)
3944
3979
  .endingAt(ctx.getPosition())
@@ -4452,6 +4487,9 @@ function parseCompoundCommand(ctx, identifierNode) {
4452
4487
  case 'swap':
4453
4488
  case 'morph':
4454
4489
  return parseSwapCommand(ctx, identifierNode);
4490
+ case 'process':
4491
+ return (parseProcessCommand(ctx, identifierNode) ??
4492
+ parseRegularCommand(ctx, identifierNode));
4455
4493
  default:
4456
4494
  return parseRegularCommand(ctx, identifierNode);
4457
4495
  }
@@ -4783,6 +4821,9 @@ function parseTellCommand(ctx, identifierNode) {
4783
4821
  if (!target) {
4784
4822
  throw new Error('tell command requires a target expression');
4785
4823
  }
4824
+ if (ctx.check(KEYWORDS.TO)) {
4825
+ ctx.advance();
4826
+ }
4786
4827
  const commands = [];
4787
4828
  while (!ctx.isAtEnd()) {
4788
4829
  if (ctx.checkIsCommand()) {
@@ -4802,7 +4843,11 @@ function parseTellCommand(ctx, identifierNode) {
4802
4843
  if (ctx.match(KEYWORDS.AND) || ctx.match(KEYWORDS.THEN)) {
4803
4844
  continue;
4804
4845
  }
4805
- if (ctx.check(KEYWORDS.ELSE) || ctx.check(KEYWORDS.END)) {
4846
+ if (ctx.check(KEYWORDS.ELSE)) {
4847
+ break;
4848
+ }
4849
+ if (ctx.check(KEYWORDS.END)) {
4850
+ ctx.advance();
4806
4851
  break;
4807
4852
  }
4808
4853
  if (ctx.checkIsCommand()) {
@@ -7140,6 +7185,7 @@ class Parser {
7140
7185
  'js',
7141
7186
  'tell',
7142
7187
  'fetch',
7188
+ 'process',
7143
7189
  ];
7144
7190
  if (this.semanticAdapter && !skipSemanticParsing.includes(commandName.toLowerCase())) {
7145
7191
  const remainingInput = this.getRemainingInput();
@@ -44,10 +44,15 @@ const commands = {
44
44
  put: {
45
45
  name: 'put',
46
46
  description: 'Set content or values',
47
- syntax: 'put value into target',
47
+ syntax: 'put value into|before|after|at start of|at end of target',
48
48
  category: 'dom',
49
49
  availability: 'lite',
50
- examples: ['put "Hello" into #output', 'put it into me', "put '<p>New</p>' into #container"],
50
+ examples: [
51
+ 'put "Hello" into #output',
52
+ 'put it into me',
53
+ "put '<p>New</p>' into #container",
54
+ 'put <tr/> in me sorted by its @data-price as Number at end of me',
55
+ ],
51
56
  },
52
57
  make: {
53
58
  name: 'make',
@@ -150,14 +155,15 @@ const commands = {
150
155
  examples: ['morph result into #content', 'morph "<div>New</div>" into me'],
151
156
  },
152
157
  processPartials: {
153
- name: 'processPartials',
154
- description: 'Process partial templates in HTML content',
155
- syntax: 'processPartials content [into target]',
158
+ name: 'process partials',
159
+ description: 'Process <hx-partial> elements for multi-target swaps',
160
+ syntax: 'process partials in <content> [using view transition]',
156
161
  category: 'dom',
157
162
  availability: 'full',
158
163
  examples: [
159
- 'processPartials result into #container',
160
- 'processPartials "<partial name=\"header\">...</partial>"',
164
+ 'process partials in it',
165
+ 'process partials in fetchedHtml',
166
+ 'process partials in it using view transition',
161
167
  ],
162
168
  },
163
169
  wait: {
@@ -42,10 +42,15 @@ const commands = {
42
42
  put: {
43
43
  name: 'put',
44
44
  description: 'Set content or values',
45
- syntax: 'put value into target',
45
+ syntax: 'put value into|before|after|at start of|at end of target',
46
46
  category: 'dom',
47
47
  availability: 'lite',
48
- examples: ['put "Hello" into #output', 'put it into me', "put '<p>New</p>' into #container"],
48
+ examples: [
49
+ 'put "Hello" into #output',
50
+ 'put it into me',
51
+ "put '<p>New</p>' into #container",
52
+ 'put <tr/> in me sorted by its @data-price as Number at end of me',
53
+ ],
49
54
  },
50
55
  make: {
51
56
  name: 'make',
@@ -148,14 +153,15 @@ const commands = {
148
153
  examples: ['morph result into #content', 'morph "<div>New</div>" into me'],
149
154
  },
150
155
  processPartials: {
151
- name: 'processPartials',
152
- description: 'Process partial templates in HTML content',
153
- syntax: 'processPartials content [into target]',
156
+ name: 'process partials',
157
+ description: 'Process <hx-partial> elements for multi-target swaps',
158
+ syntax: 'process partials in <content> [using view transition]',
154
159
  category: 'dom',
155
160
  availability: 'full',
156
161
  examples: [
157
- 'processPartials result into #container',
158
- 'processPartials "<partial name=\"header\">...</partial>"',
162
+ 'process partials in it',
163
+ 'process partials in fetchedHtml',
164
+ 'process partials in it using view transition',
159
165
  ],
160
166
  },
161
167
  wait: {
@@ -5512,6 +5512,40 @@ function parseTakeCommand(ctx, identifierNode) {
5512
5512
  .endingAt(ctx.getPosition())
5513
5513
  .build();
5514
5514
  }
5515
+ function consumeViewTransitionTail(ctx, args) {
5516
+ if (!ctx.check('using')) {
5517
+ return false;
5518
+ }
5519
+ ctx.advance();
5520
+ if (!ctx.match('view')) {
5521
+ throw new Error("expected 'view transition' after 'using'");
5522
+ }
5523
+ if (!ctx.match('transition')) {
5524
+ throw new Error("expected 'transition' after 'using view'");
5525
+ }
5526
+ args.push(ctx.createIdentifier('using'));
5527
+ args.push(ctx.createIdentifier('view'));
5528
+ args.push(ctx.createIdentifier('transition'));
5529
+ return true;
5530
+ }
5531
+ function parseProcessCommand(ctx, identifierNode) {
5532
+ if (!ctx.check('partials')) {
5533
+ return null;
5534
+ }
5535
+ const args = [];
5536
+ consumeKeywordToArgs(ctx, 'partials', args);
5537
+ if (consumeKeywordToArgs(ctx, KEYWORDS.IN, args)) {
5538
+ const contentArg = parseOneArgument(ctx, ['using']);
5539
+ if (contentArg) {
5540
+ args.push(contentArg);
5541
+ }
5542
+ }
5543
+ consumeViewTransitionTail(ctx, args);
5544
+ return CommandNodeBuilder.fromIdentifier(identifierNode)
5545
+ .withArgs(...args)
5546
+ .endingAt(ctx.getPosition())
5547
+ .build();
5548
+ }
5515
5549
  function parseAddCommand(ctx, commandToken) {
5516
5550
  const args = [];
5517
5551
  if (ctx.match('{')) {
@@ -5633,6 +5667,7 @@ function parseSwapCommand(ctx, identifierNode) {
5633
5667
  args.push(contentExpr);
5634
5668
  }
5635
5669
  }
5670
+ consumeViewTransitionTail(ctx, args);
5636
5671
  return CommandNodeBuilder.fromIdentifier(identifierNode)
5637
5672
  .withArgs(...args)
5638
5673
  .endingAt(ctx.getPosition())
@@ -6146,6 +6181,9 @@ function parseCompoundCommand(ctx, identifierNode) {
6146
6181
  case 'swap':
6147
6182
  case 'morph':
6148
6183
  return parseSwapCommand(ctx, identifierNode);
6184
+ case 'process':
6185
+ return (parseProcessCommand(ctx, identifierNode) ??
6186
+ parseRegularCommand(ctx, identifierNode));
6149
6187
  default:
6150
6188
  return parseRegularCommand(ctx, identifierNode);
6151
6189
  }
@@ -6477,6 +6515,9 @@ function parseTellCommand(ctx, identifierNode) {
6477
6515
  if (!target) {
6478
6516
  throw new Error('tell command requires a target expression');
6479
6517
  }
6518
+ if (ctx.check(KEYWORDS.TO)) {
6519
+ ctx.advance();
6520
+ }
6480
6521
  const commands = [];
6481
6522
  while (!ctx.isAtEnd()) {
6482
6523
  if (ctx.checkIsCommand()) {
@@ -6496,7 +6537,11 @@ function parseTellCommand(ctx, identifierNode) {
6496
6537
  if (ctx.match(KEYWORDS.AND) || ctx.match(KEYWORDS.THEN)) {
6497
6538
  continue;
6498
6539
  }
6499
- if (ctx.check(KEYWORDS.ELSE) || ctx.check(KEYWORDS.END)) {
6540
+ if (ctx.check(KEYWORDS.ELSE)) {
6541
+ break;
6542
+ }
6543
+ if (ctx.check(KEYWORDS.END)) {
6544
+ ctx.advance();
6500
6545
  break;
6501
6546
  }
6502
6547
  if (ctx.checkIsCommand()) {
@@ -8834,6 +8879,7 @@ class Parser {
8834
8879
  'js',
8835
8880
  'tell',
8836
8881
  'fetch',
8882
+ 'process',
8837
8883
  ];
8838
8884
  if (this.semanticAdapter && !skipSemanticParsing.includes(commandName.toLowerCase())) {
8839
8885
  const remainingInput = this.getRemainingInput();
@@ -9861,6 +9907,12 @@ function evaluateLiteral(node) {
9861
9907
  }
9862
9908
  async function evaluateIdentifier(node, context) {
9863
9909
  const name = node.name;
9910
+ if (name.startsWith('$')) {
9911
+ notifyGlobalRead(name.slice(1), context);
9912
+ }
9913
+ else if (node.scope === 'global') {
9914
+ notifyGlobalRead(name, context);
9915
+ }
9864
9916
  if (name === 'me' || name === 'my' || name === 'I') {
9865
9917
  return getExpr(context, 'me').evaluate(context);
9866
9918
  }
@@ -9880,7 +9932,6 @@ async function evaluateIdentifier(node, context) {
9880
9932
  return getExpr(context, 'document').evaluate(context);
9881
9933
  }
9882
9934
  if (node.scope === 'global' && context.globals?.has(name)) {
9883
- notifyGlobalRead(name, context);
9884
9935
  return context.globals.get(name);
9885
9936
  }
9886
9937
  if (node.scope === 'element') {
@@ -9891,12 +9942,9 @@ async function evaluateIdentifier(node, context) {
9891
9942
  return context.locals.get(name);
9892
9943
  }
9893
9944
  if (context.globals && context.globals.has(name)) {
9894
- if (name.startsWith('$'))
9895
- notifyGlobalRead(name.slice(1), context);
9896
9945
  return context.globals.get(name);
9897
9946
  }
9898
9947
  if (name.startsWith('$') && context.globals && context.globals.has(name.slice(1))) {
9899
- notifyGlobalRead(name.slice(1), context);
9900
9948
  return context.globals.get(name.slice(1));
9901
9949
  }
9902
9950
  if (context[name] !== undefined) {
@@ -10870,7 +10918,7 @@ class CommandAdapterV2 {
10870
10918
  return {
10871
10919
  description: this.impl.metadata?.description || '',
10872
10920
  examples: this.impl.metadata?.examples || [],
10873
- syntax: Array.isArray(syntax) ? syntax.join(' | ') : syntax || '',
10921
+ syntax: typeof syntax === 'string' ? syntax : syntax ? syntax.join(' | ') : '',
10874
10922
  };
10875
10923
  }
10876
10924
  async execute(context, ...args) {
@@ -10946,10 +10994,8 @@ class CommandAdapterV2 {
10946
10994
  }
10947
10995
  }
10948
10996
  validate(input) {
10949
- if (this.impl.validate) {
10950
- return this.impl.validate(input);
10951
- }
10952
- return { isValid: true, errors: [], suggestions: [] };
10997
+ const isValid = this.impl.validate ? this.impl.validate(input) : true;
10998
+ return { isValid, errors: [], suggestions: [] };
10953
10999
  }
10954
11000
  }
10955
11001
  class CommandRegistryV2 {