@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
@@ -71,7 +71,7 @@ function command(config) {
71
71
  };
72
72
  }
73
73
  function commandMeta(metadata) {
74
- return { isBlocking: false, hasBody: false, version: '1.0.0', ...metadata };
74
+ return { ...metadata };
75
75
  }
76
76
  function createFactory(CommandClass) {
77
77
  return () => new CommandClass();
@@ -86,6 +86,12 @@ function isHTMLElement$2(value) {
86
86
  typeof value.tagName === 'string' &&
87
87
  'classList' in value);
88
88
  }
89
+ function isInsertableNode(value) {
90
+ if (value === null || typeof value !== 'object')
91
+ return false;
92
+ const nodeType = value.nodeType;
93
+ return nodeType === 1 || nodeType === 3 || nodeType === 11;
94
+ }
89
95
  function isNodeList(value) {
90
96
  return (value !== null &&
91
97
  typeof value === 'object' &&
@@ -1067,7 +1073,7 @@ function insertContent(target, content, position) {
1067
1073
  insertReplace(target, content);
1068
1074
  return;
1069
1075
  }
1070
- if (isHTMLElement$2(content)) {
1076
+ if (isInsertableNode(content)) {
1071
1077
  insertElement(target, content, position);
1072
1078
  }
1073
1079
  else {
@@ -1078,7 +1084,7 @@ function insertContentSemantic(target, content, position) {
1078
1084
  insertContent(target, content, toInsertPosition(position));
1079
1085
  }
1080
1086
  function insertReplace(target, content) {
1081
- if (isHTMLElement$2(content)) {
1087
+ if (isInsertableNode(content)) {
1082
1088
  target.innerHTML = '';
1083
1089
  target.appendChild(content);
1084
1090
  }
@@ -1125,6 +1131,53 @@ function insertText(target, content, position) {
1125
1131
  target.insertAdjacentText(domPosition, content);
1126
1132
  }
1127
1133
  }
1134
+ function moveOrInsert(parent, element, ref) {
1135
+ const p = parent;
1136
+ if (typeof p.moveBefore === 'function' && element.isConnected && parent.isConnected) {
1137
+ try {
1138
+ p.moveBefore(element, ref);
1139
+ return;
1140
+ }
1141
+ catch {
1142
+ }
1143
+ }
1144
+ parent.insertBefore(element, ref);
1145
+ }
1146
+ function insertElementsInOrder(target, elements, position) {
1147
+ switch (position) {
1148
+ case 'beforeend':
1149
+ for (const el of elements)
1150
+ moveOrInsert(target, el, null);
1151
+ break;
1152
+ case 'afterbegin':
1153
+ for (let i = elements.length - 1; i >= 0; i--) {
1154
+ moveOrInsert(target, elements[i], target.firstChild);
1155
+ }
1156
+ break;
1157
+ case 'beforebegin': {
1158
+ const parent = target.parentElement;
1159
+ if (!parent)
1160
+ return;
1161
+ for (const el of elements)
1162
+ moveOrInsert(parent, el, target);
1163
+ break;
1164
+ }
1165
+ case 'afterend': {
1166
+ const parent = target.parentElement;
1167
+ if (!parent)
1168
+ return;
1169
+ for (let i = elements.length - 1; i >= 0; i--) {
1170
+ moveOrInsert(parent, elements[i], target.nextSibling);
1171
+ }
1172
+ break;
1173
+ }
1174
+ case 'replace':
1175
+ target.innerHTML = '';
1176
+ for (const el of elements)
1177
+ moveOrInsert(target, el, null);
1178
+ break;
1179
+ }
1180
+ }
1128
1181
  function removeElement(element) {
1129
1182
  if (element.parentNode) {
1130
1183
  element.remove();
@@ -2747,7 +2800,12 @@ let PutCommand = (() => {
2747
2800
  else {
2748
2801
  for (const t of targets) {
2749
2802
  const content = this.parseValue(value);
2750
- insertContentSemantic(t, content, position);
2803
+ if (Array.isArray(content)) {
2804
+ insertElementsInOrder(t, content, toInsertPosition(position));
2805
+ }
2806
+ else {
2807
+ insertContentSemantic(t, content, position);
2808
+ }
2751
2809
  }
2752
2810
  }
2753
2811
  return targets;
@@ -2779,6 +2837,11 @@ let PutCommand = (() => {
2779
2837
  parseValue(v) {
2780
2838
  if (isHTMLElement$2(v))
2781
2839
  return v;
2840
+ if (Array.isArray(v) && v.length > 0 && v.every(isHTMLElement$2)) {
2841
+ return v;
2842
+ }
2843
+ if (isInsertableNode(v))
2844
+ return v;
2782
2845
  return v == null ? '' : String(v);
2783
2846
  }
2784
2847
  looksLikeCss(s) {
@@ -7750,6 +7813,40 @@ function parseTakeCommand(ctx, identifierNode) {
7750
7813
  .endingAt(ctx.getPosition())
7751
7814
  .build();
7752
7815
  }
7816
+ function consumeViewTransitionTail(ctx, args) {
7817
+ if (!ctx.check('using')) {
7818
+ return false;
7819
+ }
7820
+ ctx.advance();
7821
+ if (!ctx.match('view')) {
7822
+ throw new Error("expected 'view transition' after 'using'");
7823
+ }
7824
+ if (!ctx.match('transition')) {
7825
+ throw new Error("expected 'transition' after 'using view'");
7826
+ }
7827
+ args.push(ctx.createIdentifier('using'));
7828
+ args.push(ctx.createIdentifier('view'));
7829
+ args.push(ctx.createIdentifier('transition'));
7830
+ return true;
7831
+ }
7832
+ function parseProcessCommand(ctx, identifierNode) {
7833
+ if (!ctx.check('partials')) {
7834
+ return null;
7835
+ }
7836
+ const args = [];
7837
+ consumeKeywordToArgs(ctx, 'partials', args);
7838
+ if (consumeKeywordToArgs(ctx, KEYWORDS$1.IN, args)) {
7839
+ const contentArg = parseOneArgument(ctx, ['using']);
7840
+ if (contentArg) {
7841
+ args.push(contentArg);
7842
+ }
7843
+ }
7844
+ consumeViewTransitionTail(ctx, args);
7845
+ return CommandNodeBuilder.fromIdentifier(identifierNode)
7846
+ .withArgs(...args)
7847
+ .endingAt(ctx.getPosition())
7848
+ .build();
7849
+ }
7753
7850
  function parseAddCommand(ctx, commandToken) {
7754
7851
  const args = [];
7755
7852
  if (ctx.match('{')) {
@@ -7871,6 +7968,7 @@ function parseSwapCommand(ctx, identifierNode) {
7871
7968
  args.push(contentExpr);
7872
7969
  }
7873
7970
  }
7971
+ consumeViewTransitionTail(ctx, args);
7874
7972
  return CommandNodeBuilder.fromIdentifier(identifierNode)
7875
7973
  .withArgs(...args)
7876
7974
  .endingAt(ctx.getPosition())
@@ -8384,6 +8482,9 @@ function parseCompoundCommand(ctx, identifierNode) {
8384
8482
  case 'swap':
8385
8483
  case 'morph':
8386
8484
  return parseSwapCommand(ctx, identifierNode);
8485
+ case 'process':
8486
+ return (parseProcessCommand(ctx, identifierNode) ??
8487
+ parseRegularCommand(ctx, identifierNode));
8387
8488
  default:
8388
8489
  return parseRegularCommand(ctx, identifierNode);
8389
8490
  }
@@ -8715,6 +8816,9 @@ function parseTellCommand(ctx, identifierNode) {
8715
8816
  if (!target) {
8716
8817
  throw new Error('tell command requires a target expression');
8717
8818
  }
8819
+ if (ctx.check(KEYWORDS$1.TO)) {
8820
+ ctx.advance();
8821
+ }
8718
8822
  const commands = [];
8719
8823
  while (!ctx.isAtEnd()) {
8720
8824
  if (ctx.checkIsCommand()) {
@@ -8734,7 +8838,11 @@ function parseTellCommand(ctx, identifierNode) {
8734
8838
  if (ctx.match(KEYWORDS$1.AND) || ctx.match(KEYWORDS$1.THEN)) {
8735
8839
  continue;
8736
8840
  }
8737
- if (ctx.check(KEYWORDS$1.ELSE) || ctx.check(KEYWORDS$1.END)) {
8841
+ if (ctx.check(KEYWORDS$1.ELSE)) {
8842
+ break;
8843
+ }
8844
+ if (ctx.check(KEYWORDS$1.END)) {
8845
+ ctx.advance();
8738
8846
  break;
8739
8847
  }
8740
8848
  if (ctx.checkIsCommand()) {
@@ -11072,6 +11180,7 @@ class Parser {
11072
11180
  'js',
11073
11181
  'tell',
11074
11182
  'fetch',
11183
+ 'process',
11075
11184
  ];
11076
11185
  if (this.semanticAdapter && !skipSemanticParsing.includes(commandName.toLowerCase())) {
11077
11186
  const remainingInput = this.getRemainingInput();
@@ -12099,6 +12208,12 @@ function evaluateLiteral(node) {
12099
12208
  }
12100
12209
  async function evaluateIdentifier(node, context) {
12101
12210
  const name = node.name;
12211
+ if (name.startsWith('$')) {
12212
+ notifyGlobalRead(name.slice(1), context);
12213
+ }
12214
+ else if (node.scope === 'global') {
12215
+ notifyGlobalRead(name, context);
12216
+ }
12102
12217
  if (name === 'me' || name === 'my' || name === 'I') {
12103
12218
  return getExpr(context, 'me').evaluate(context);
12104
12219
  }
@@ -12118,7 +12233,6 @@ async function evaluateIdentifier(node, context) {
12118
12233
  return getExpr(context, 'document').evaluate(context);
12119
12234
  }
12120
12235
  if (node.scope === 'global' && context.globals?.has(name)) {
12121
- notifyGlobalRead(name, context);
12122
12236
  return context.globals.get(name);
12123
12237
  }
12124
12238
  if (node.scope === 'element') {
@@ -12129,12 +12243,9 @@ async function evaluateIdentifier(node, context) {
12129
12243
  return context.locals.get(name);
12130
12244
  }
12131
12245
  if (context.globals && context.globals.has(name)) {
12132
- if (name.startsWith('$'))
12133
- notifyGlobalRead(name.slice(1), context);
12134
12246
  return context.globals.get(name);
12135
12247
  }
12136
12248
  if (name.startsWith('$') && context.globals && context.globals.has(name.slice(1))) {
12137
- notifyGlobalRead(name.slice(1), context);
12138
12249
  return context.globals.get(name.slice(1));
12139
12250
  }
12140
12251
  if (context[name] !== undefined) {
@@ -14072,8 +14183,9 @@ const morphAdapter = {
14072
14183
  function getStartViewTransition() {
14073
14184
  if (typeof document === 'undefined')
14074
14185
  return undefined;
14075
- return document
14186
+ const fn = document
14076
14187
  .startViewTransition;
14188
+ return typeof fn === 'function' ? fn.bind(document) : undefined;
14077
14189
  }
14078
14190
  function isViewTransitionsSupported() {
14079
14191
  return typeof getStartViewTransition() === 'function';
@@ -14335,7 +14447,7 @@ let SwapCommand = (() => {
14335
14447
  };
14336
14448
  }
14337
14449
  }
14338
- let useViewTransition = false;
14450
+ let useViewTransition = raw.modifiers?.viewTransition !== undefined;
14339
14451
  if (usingIndex !== -1) {
14340
14452
  const afterUsing = argKeywords.slice(usingIndex + 1);
14341
14453
  if (afterUsing.includes('view') && afterUsing.includes('transition')) {
@@ -14545,7 +14657,7 @@ let MorphCommand = (() => {
14545
14657
  const withIndex = argKeywords.findIndex(k => k === 'with');
14546
14658
  const overIndex = argKeywords.findIndex(k => k === 'over');
14547
14659
  const usingIndex = argKeywords.findIndex(k => k === 'using');
14548
- let useViewTransition = false;
14660
+ let useViewTransition = raw.modifiers?.viewTransition !== undefined;
14549
14661
  if (usingIndex !== -1) {
14550
14662
  const afterUsing = argKeywords.slice(usingIndex + 1);
14551
14663
  if (afterUsing.includes('view') && afterUsing.includes('transition')) {
@@ -14626,7 +14738,11 @@ let MorphCommand = (() => {
14626
14738
  })();
14627
14739
  _classThis.metadata = commandMeta({
14628
14740
  description: 'Morph content into target elements (intelligent diffing, preserves state)',
14629
- syntax: ['morph <target> with <content>', 'morph over <target> with <content>'],
14741
+ syntax: [
14742
+ 'morph <target> with <content>',
14743
+ 'morph over <target> with <content>',
14744
+ 'morph <target> with <content> using view transition',
14745
+ ],
14630
14746
  examples: ['morph #target with it', 'morph over #modal with fetchedContent'],
14631
14747
  sideEffects: ['dom-mutation'],
14632
14748
  category: 'dom',
@@ -15236,24 +15352,33 @@ let ProcessPartialsCommand = (() => {
15236
15352
  if (!args || args.length === 0) {
15237
15353
  throw new Error('process partials command requires content argument');
15238
15354
  }
15239
- const evaluatedArgs = [];
15240
- const argStrings = [];
15241
- for (const arg of args) {
15242
- const evaluated = await evaluator.evaluate(arg, context);
15243
- evaluatedArgs.push(evaluated);
15244
- if (typeof evaluated === 'string') {
15245
- argStrings.push(evaluated.toLowerCase());
15246
- }
15247
- }
15248
- const partialsIndex = argStrings.findIndex(s => s === 'partials');
15355
+ const keywordOf = (node) => {
15356
+ const n = node;
15357
+ if (!n || typeof n !== 'object')
15358
+ return null;
15359
+ if (n.type === 'identifier' && typeof n.name === 'string')
15360
+ return n.name.toLowerCase();
15361
+ if (n.type === 'literal' && typeof n.value === 'string')
15362
+ return n.value.toLowerCase();
15363
+ return null;
15364
+ };
15365
+ const keywords = args.map(keywordOf);
15366
+ const partialsIndex = keywords.indexOf('partials');
15367
+ const inIndex = keywords.indexOf('in');
15368
+ let contentNode;
15249
15369
  if (partialsIndex === -1) {
15250
- throw new Error('process command expects "partials" keyword: process partials in <content>');
15370
+ if (inIndex !== -1) {
15371
+ throw new Error('process command expects "partials" keyword: process partials in <content>');
15372
+ }
15373
+ contentNode = args[0];
15251
15374
  }
15252
- const inIndex = argStrings.findIndex(s => s === 'in');
15253
- if (inIndex === -1 || inIndex <= partialsIndex) {
15254
- throw new Error('process partials command expects "in" keyword: process partials in <content>');
15375
+ else {
15376
+ if (inIndex === -1 || inIndex <= partialsIndex) {
15377
+ throw new Error('process partials command expects "in" keyword: process partials in <content>');
15378
+ }
15379
+ contentNode = args[inIndex + 1];
15255
15380
  }
15256
- const contentArg = evaluatedArgs[inIndex + 1];
15381
+ const contentArg = contentNode ? await evaluator.evaluate(contentNode, context) : undefined;
15257
15382
  let html;
15258
15383
  if (typeof contentArg === 'string') {
15259
15384
  html = contentArg;
@@ -15267,10 +15392,10 @@ let ProcessPartialsCommand = (() => {
15267
15392
  else {
15268
15393
  throw new Error('process partials: content must be an HTML string or element');
15269
15394
  }
15270
- const usingIndex = argStrings.findIndex(s => s === 'using');
15271
- let useViewTransition = false;
15395
+ let useViewTransition = raw.modifiers?.viewTransition !== undefined;
15396
+ const usingIndex = keywords.indexOf('using');
15272
15397
  if (usingIndex !== -1) {
15273
- const remaining = argStrings.slice(usingIndex + 1).join(' ');
15398
+ const remaining = keywords.slice(usingIndex + 1);
15274
15399
  if (remaining.includes('view') && remaining.includes('transition')) {
15275
15400
  useViewTransition = true;
15276
15401
  }
@@ -69,7 +69,7 @@ function command(config) {
69
69
  };
70
70
  }
71
71
  function commandMeta(metadata) {
72
- return { isBlocking: false, hasBody: false, version: '1.0.0', ...metadata };
72
+ return { ...metadata };
73
73
  }
74
74
  function createFactory(CommandClass) {
75
75
  return () => new CommandClass();
@@ -84,6 +84,12 @@ function isHTMLElement$2(value) {
84
84
  typeof value.tagName === 'string' &&
85
85
  'classList' in value);
86
86
  }
87
+ function isInsertableNode(value) {
88
+ if (value === null || typeof value !== 'object')
89
+ return false;
90
+ const nodeType = value.nodeType;
91
+ return nodeType === 1 || nodeType === 3 || nodeType === 11;
92
+ }
87
93
  function isNodeList(value) {
88
94
  return (value !== null &&
89
95
  typeof value === 'object' &&
@@ -1065,7 +1071,7 @@ function insertContent(target, content, position) {
1065
1071
  insertReplace(target, content);
1066
1072
  return;
1067
1073
  }
1068
- if (isHTMLElement$2(content)) {
1074
+ if (isInsertableNode(content)) {
1069
1075
  insertElement(target, content, position);
1070
1076
  }
1071
1077
  else {
@@ -1076,7 +1082,7 @@ function insertContentSemantic(target, content, position) {
1076
1082
  insertContent(target, content, toInsertPosition(position));
1077
1083
  }
1078
1084
  function insertReplace(target, content) {
1079
- if (isHTMLElement$2(content)) {
1085
+ if (isInsertableNode(content)) {
1080
1086
  target.innerHTML = '';
1081
1087
  target.appendChild(content);
1082
1088
  }
@@ -1123,6 +1129,53 @@ function insertText(target, content, position) {
1123
1129
  target.insertAdjacentText(domPosition, content);
1124
1130
  }
1125
1131
  }
1132
+ function moveOrInsert(parent, element, ref) {
1133
+ const p = parent;
1134
+ if (typeof p.moveBefore === 'function' && element.isConnected && parent.isConnected) {
1135
+ try {
1136
+ p.moveBefore(element, ref);
1137
+ return;
1138
+ }
1139
+ catch {
1140
+ }
1141
+ }
1142
+ parent.insertBefore(element, ref);
1143
+ }
1144
+ function insertElementsInOrder(target, elements, position) {
1145
+ switch (position) {
1146
+ case 'beforeend':
1147
+ for (const el of elements)
1148
+ moveOrInsert(target, el, null);
1149
+ break;
1150
+ case 'afterbegin':
1151
+ for (let i = elements.length - 1; i >= 0; i--) {
1152
+ moveOrInsert(target, elements[i], target.firstChild);
1153
+ }
1154
+ break;
1155
+ case 'beforebegin': {
1156
+ const parent = target.parentElement;
1157
+ if (!parent)
1158
+ return;
1159
+ for (const el of elements)
1160
+ moveOrInsert(parent, el, target);
1161
+ break;
1162
+ }
1163
+ case 'afterend': {
1164
+ const parent = target.parentElement;
1165
+ if (!parent)
1166
+ return;
1167
+ for (let i = elements.length - 1; i >= 0; i--) {
1168
+ moveOrInsert(parent, elements[i], target.nextSibling);
1169
+ }
1170
+ break;
1171
+ }
1172
+ case 'replace':
1173
+ target.innerHTML = '';
1174
+ for (const el of elements)
1175
+ moveOrInsert(target, el, null);
1176
+ break;
1177
+ }
1178
+ }
1126
1179
  function removeElement(element) {
1127
1180
  if (element.parentNode) {
1128
1181
  element.remove();
@@ -2745,7 +2798,12 @@ let PutCommand = (() => {
2745
2798
  else {
2746
2799
  for (const t of targets) {
2747
2800
  const content = this.parseValue(value);
2748
- insertContentSemantic(t, content, position);
2801
+ if (Array.isArray(content)) {
2802
+ insertElementsInOrder(t, content, toInsertPosition(position));
2803
+ }
2804
+ else {
2805
+ insertContentSemantic(t, content, position);
2806
+ }
2749
2807
  }
2750
2808
  }
2751
2809
  return targets;
@@ -2777,6 +2835,11 @@ let PutCommand = (() => {
2777
2835
  parseValue(v) {
2778
2836
  if (isHTMLElement$2(v))
2779
2837
  return v;
2838
+ if (Array.isArray(v) && v.length > 0 && v.every(isHTMLElement$2)) {
2839
+ return v;
2840
+ }
2841
+ if (isInsertableNode(v))
2842
+ return v;
2780
2843
  return v == null ? '' : String(v);
2781
2844
  }
2782
2845
  looksLikeCss(s) {
@@ -7748,6 +7811,40 @@ function parseTakeCommand(ctx, identifierNode) {
7748
7811
  .endingAt(ctx.getPosition())
7749
7812
  .build();
7750
7813
  }
7814
+ function consumeViewTransitionTail(ctx, args) {
7815
+ if (!ctx.check('using')) {
7816
+ return false;
7817
+ }
7818
+ ctx.advance();
7819
+ if (!ctx.match('view')) {
7820
+ throw new Error("expected 'view transition' after 'using'");
7821
+ }
7822
+ if (!ctx.match('transition')) {
7823
+ throw new Error("expected 'transition' after 'using view'");
7824
+ }
7825
+ args.push(ctx.createIdentifier('using'));
7826
+ args.push(ctx.createIdentifier('view'));
7827
+ args.push(ctx.createIdentifier('transition'));
7828
+ return true;
7829
+ }
7830
+ function parseProcessCommand(ctx, identifierNode) {
7831
+ if (!ctx.check('partials')) {
7832
+ return null;
7833
+ }
7834
+ const args = [];
7835
+ consumeKeywordToArgs(ctx, 'partials', args);
7836
+ if (consumeKeywordToArgs(ctx, KEYWORDS$1.IN, args)) {
7837
+ const contentArg = parseOneArgument(ctx, ['using']);
7838
+ if (contentArg) {
7839
+ args.push(contentArg);
7840
+ }
7841
+ }
7842
+ consumeViewTransitionTail(ctx, args);
7843
+ return CommandNodeBuilder.fromIdentifier(identifierNode)
7844
+ .withArgs(...args)
7845
+ .endingAt(ctx.getPosition())
7846
+ .build();
7847
+ }
7751
7848
  function parseAddCommand(ctx, commandToken) {
7752
7849
  const args = [];
7753
7850
  if (ctx.match('{')) {
@@ -7869,6 +7966,7 @@ function parseSwapCommand(ctx, identifierNode) {
7869
7966
  args.push(contentExpr);
7870
7967
  }
7871
7968
  }
7969
+ consumeViewTransitionTail(ctx, args);
7872
7970
  return CommandNodeBuilder.fromIdentifier(identifierNode)
7873
7971
  .withArgs(...args)
7874
7972
  .endingAt(ctx.getPosition())
@@ -8382,6 +8480,9 @@ function parseCompoundCommand(ctx, identifierNode) {
8382
8480
  case 'swap':
8383
8481
  case 'morph':
8384
8482
  return parseSwapCommand(ctx, identifierNode);
8483
+ case 'process':
8484
+ return (parseProcessCommand(ctx, identifierNode) ??
8485
+ parseRegularCommand(ctx, identifierNode));
8385
8486
  default:
8386
8487
  return parseRegularCommand(ctx, identifierNode);
8387
8488
  }
@@ -8713,6 +8814,9 @@ function parseTellCommand(ctx, identifierNode) {
8713
8814
  if (!target) {
8714
8815
  throw new Error('tell command requires a target expression');
8715
8816
  }
8817
+ if (ctx.check(KEYWORDS$1.TO)) {
8818
+ ctx.advance();
8819
+ }
8716
8820
  const commands = [];
8717
8821
  while (!ctx.isAtEnd()) {
8718
8822
  if (ctx.checkIsCommand()) {
@@ -8732,7 +8836,11 @@ function parseTellCommand(ctx, identifierNode) {
8732
8836
  if (ctx.match(KEYWORDS$1.AND) || ctx.match(KEYWORDS$1.THEN)) {
8733
8837
  continue;
8734
8838
  }
8735
- if (ctx.check(KEYWORDS$1.ELSE) || ctx.check(KEYWORDS$1.END)) {
8839
+ if (ctx.check(KEYWORDS$1.ELSE)) {
8840
+ break;
8841
+ }
8842
+ if (ctx.check(KEYWORDS$1.END)) {
8843
+ ctx.advance();
8736
8844
  break;
8737
8845
  }
8738
8846
  if (ctx.checkIsCommand()) {
@@ -11070,6 +11178,7 @@ class Parser {
11070
11178
  'js',
11071
11179
  'tell',
11072
11180
  'fetch',
11181
+ 'process',
11073
11182
  ];
11074
11183
  if (this.semanticAdapter && !skipSemanticParsing.includes(commandName.toLowerCase())) {
11075
11184
  const remainingInput = this.getRemainingInput();
@@ -12097,6 +12206,12 @@ function evaluateLiteral(node) {
12097
12206
  }
12098
12207
  async function evaluateIdentifier(node, context) {
12099
12208
  const name = node.name;
12209
+ if (name.startsWith('$')) {
12210
+ notifyGlobalRead(name.slice(1), context);
12211
+ }
12212
+ else if (node.scope === 'global') {
12213
+ notifyGlobalRead(name, context);
12214
+ }
12100
12215
  if (name === 'me' || name === 'my' || name === 'I') {
12101
12216
  return getExpr(context, 'me').evaluate(context);
12102
12217
  }
@@ -12116,7 +12231,6 @@ async function evaluateIdentifier(node, context) {
12116
12231
  return getExpr(context, 'document').evaluate(context);
12117
12232
  }
12118
12233
  if (node.scope === 'global' && context.globals?.has(name)) {
12119
- notifyGlobalRead(name, context);
12120
12234
  return context.globals.get(name);
12121
12235
  }
12122
12236
  if (node.scope === 'element') {
@@ -12127,12 +12241,9 @@ async function evaluateIdentifier(node, context) {
12127
12241
  return context.locals.get(name);
12128
12242
  }
12129
12243
  if (context.globals && context.globals.has(name)) {
12130
- if (name.startsWith('$'))
12131
- notifyGlobalRead(name.slice(1), context);
12132
12244
  return context.globals.get(name);
12133
12245
  }
12134
12246
  if (name.startsWith('$') && context.globals && context.globals.has(name.slice(1))) {
12135
- notifyGlobalRead(name.slice(1), context);
12136
12247
  return context.globals.get(name.slice(1));
12137
12248
  }
12138
12249
  if (context[name] !== undefined) {
@@ -14070,8 +14181,9 @@ const morphAdapter = {
14070
14181
  function getStartViewTransition() {
14071
14182
  if (typeof document === 'undefined')
14072
14183
  return undefined;
14073
- return document
14184
+ const fn = document
14074
14185
  .startViewTransition;
14186
+ return typeof fn === 'function' ? fn.bind(document) : undefined;
14075
14187
  }
14076
14188
  function isViewTransitionsSupported() {
14077
14189
  return typeof getStartViewTransition() === 'function';
@@ -14333,7 +14445,7 @@ let SwapCommand = (() => {
14333
14445
  };
14334
14446
  }
14335
14447
  }
14336
- let useViewTransition = false;
14448
+ let useViewTransition = raw.modifiers?.viewTransition !== undefined;
14337
14449
  if (usingIndex !== -1) {
14338
14450
  const afterUsing = argKeywords.slice(usingIndex + 1);
14339
14451
  if (afterUsing.includes('view') && afterUsing.includes('transition')) {
@@ -14543,7 +14655,7 @@ let MorphCommand = (() => {
14543
14655
  const withIndex = argKeywords.findIndex(k => k === 'with');
14544
14656
  const overIndex = argKeywords.findIndex(k => k === 'over');
14545
14657
  const usingIndex = argKeywords.findIndex(k => k === 'using');
14546
- let useViewTransition = false;
14658
+ let useViewTransition = raw.modifiers?.viewTransition !== undefined;
14547
14659
  if (usingIndex !== -1) {
14548
14660
  const afterUsing = argKeywords.slice(usingIndex + 1);
14549
14661
  if (afterUsing.includes('view') && afterUsing.includes('transition')) {
@@ -14624,7 +14736,11 @@ let MorphCommand = (() => {
14624
14736
  })();
14625
14737
  _classThis.metadata = commandMeta({
14626
14738
  description: 'Morph content into target elements (intelligent diffing, preserves state)',
14627
- syntax: ['morph <target> with <content>', 'morph over <target> with <content>'],
14739
+ syntax: [
14740
+ 'morph <target> with <content>',
14741
+ 'morph over <target> with <content>',
14742
+ 'morph <target> with <content> using view transition',
14743
+ ],
14628
14744
  examples: ['morph #target with it', 'morph over #modal with fetchedContent'],
14629
14745
  sideEffects: ['dom-mutation'],
14630
14746
  category: 'dom',
@@ -15234,24 +15350,33 @@ let ProcessPartialsCommand = (() => {
15234
15350
  if (!args || args.length === 0) {
15235
15351
  throw new Error('process partials command requires content argument');
15236
15352
  }
15237
- const evaluatedArgs = [];
15238
- const argStrings = [];
15239
- for (const arg of args) {
15240
- const evaluated = await evaluator.evaluate(arg, context);
15241
- evaluatedArgs.push(evaluated);
15242
- if (typeof evaluated === 'string') {
15243
- argStrings.push(evaluated.toLowerCase());
15244
- }
15245
- }
15246
- const partialsIndex = argStrings.findIndex(s => s === 'partials');
15353
+ const keywordOf = (node) => {
15354
+ const n = node;
15355
+ if (!n || typeof n !== 'object')
15356
+ return null;
15357
+ if (n.type === 'identifier' && typeof n.name === 'string')
15358
+ return n.name.toLowerCase();
15359
+ if (n.type === 'literal' && typeof n.value === 'string')
15360
+ return n.value.toLowerCase();
15361
+ return null;
15362
+ };
15363
+ const keywords = args.map(keywordOf);
15364
+ const partialsIndex = keywords.indexOf('partials');
15365
+ const inIndex = keywords.indexOf('in');
15366
+ let contentNode;
15247
15367
  if (partialsIndex === -1) {
15248
- throw new Error('process command expects "partials" keyword: process partials in <content>');
15368
+ if (inIndex !== -1) {
15369
+ throw new Error('process command expects "partials" keyword: process partials in <content>');
15370
+ }
15371
+ contentNode = args[0];
15249
15372
  }
15250
- const inIndex = argStrings.findIndex(s => s === 'in');
15251
- if (inIndex === -1 || inIndex <= partialsIndex) {
15252
- throw new Error('process partials command expects "in" keyword: process partials in <content>');
15373
+ else {
15374
+ if (inIndex === -1 || inIndex <= partialsIndex) {
15375
+ throw new Error('process partials command expects "in" keyword: process partials in <content>');
15376
+ }
15377
+ contentNode = args[inIndex + 1];
15253
15378
  }
15254
- const contentArg = evaluatedArgs[inIndex + 1];
15379
+ const contentArg = contentNode ? await evaluator.evaluate(contentNode, context) : undefined;
15255
15380
  let html;
15256
15381
  if (typeof contentArg === 'string') {
15257
15382
  html = contentArg;
@@ -15265,10 +15390,10 @@ let ProcessPartialsCommand = (() => {
15265
15390
  else {
15266
15391
  throw new Error('process partials: content must be an HTML string or element');
15267
15392
  }
15268
- const usingIndex = argStrings.findIndex(s => s === 'using');
15269
- let useViewTransition = false;
15393
+ let useViewTransition = raw.modifiers?.viewTransition !== undefined;
15394
+ const usingIndex = keywords.indexOf('using');
15270
15395
  if (usingIndex !== -1) {
15271
- const remaining = argStrings.slice(usingIndex + 1).join(' ');
15396
+ const remaining = keywords.slice(usingIndex + 1);
15272
15397
  if (remaining.includes('view') && remaining.includes('transition')) {
15273
15398
  useViewTransition = true;
15274
15399
  }