illimi-core 1.0.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 (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -0
  3. package/dist/ast/nodes.d.ts +91 -0
  4. package/dist/ast/nodes.d.ts.map +1 -0
  5. package/dist/ast/nodes.js +8 -0
  6. package/dist/ast/nodes.js.map +1 -0
  7. package/dist/compiler/mergeSlots.d.ts +31 -0
  8. package/dist/compiler/mergeSlots.d.ts.map +1 -0
  9. package/dist/compiler/mergeSlots.js +85 -0
  10. package/dist/compiler/mergeSlots.js.map +1 -0
  11. package/dist/compiler/resolveLayout.d.ts +22 -0
  12. package/dist/compiler/resolveLayout.d.ts.map +1 -0
  13. package/dist/compiler/resolveLayout.js +212 -0
  14. package/dist/compiler/resolveLayout.js.map +1 -0
  15. package/dist/index.d.ts +8 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +14 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/ir/transform.d.ts +50 -0
  20. package/dist/ir/transform.d.ts.map +1 -0
  21. package/dist/ir/transform.js +128 -0
  22. package/dist/ir/transform.js.map +1 -0
  23. package/dist/parser/directiveParser.d.ts +34 -0
  24. package/dist/parser/directiveParser.d.ts.map +1 -0
  25. package/dist/parser/directiveParser.js +131 -0
  26. package/dist/parser/directiveParser.js.map +1 -0
  27. package/dist/parser/htmlParser.d.ts +13 -0
  28. package/dist/parser/htmlParser.d.ts.map +1 -0
  29. package/dist/parser/htmlParser.js +350 -0
  30. package/dist/parser/htmlParser.js.map +1 -0
  31. package/dist/vdom/diff.d.ts +33 -0
  32. package/dist/vdom/diff.d.ts.map +1 -0
  33. package/dist/vdom/diff.js +259 -0
  34. package/dist/vdom/diff.js.map +1 -0
  35. package/dist/vdom/vnode.d.ts +52 -0
  36. package/dist/vdom/vnode.d.ts.map +1 -0
  37. package/dist/vdom/vnode.js +206 -0
  38. package/dist/vdom/vnode.js.map +1 -0
  39. package/package.json +38 -0
  40. package/tsconfig.base.json +28 -0
  41. package/tsconfig.json +8 -0
@@ -0,0 +1,350 @@
1
+ /**
2
+ * FeedJS Core - HTML Parser
3
+ *
4
+ * Parses HTML templates into Feed AST nodes.
5
+ * Handles standard HTML elements, text, comments, slots, and template blocks.
6
+ * Supports {{ expression }} interpolation syntax.
7
+ */
8
+ import { isDirective, parseDirective } from './directiveParser.js';
9
+ /**
10
+ * Parse HTML template string into Feed AST
11
+ */
12
+ export function parseTemplate(html) {
13
+ const tokens = tokenize(html);
14
+ const state = { tokens, pos: 0 };
15
+ const nodes = parseNodes(state);
16
+ return {
17
+ type: 'FeedAST',
18
+ nodes,
19
+ source: html,
20
+ };
21
+ }
22
+ // Simple HTML tokenizer with interpolation support
23
+ function tokenize(html) {
24
+ const tokens = [];
25
+ const segments = splitByInterpolation(html);
26
+ for (const segment of segments) {
27
+ if (segment.isInterpolation) {
28
+ tokens.push({ type: 'interpolation', value: segment.content, attributes: {} });
29
+ continue;
30
+ }
31
+ tokens.push(...tokenizeHtml(segment.content));
32
+ }
33
+ return tokens;
34
+ }
35
+ /**
36
+ * Split HTML by interpolation markers {{ }}
37
+ */
38
+ function splitByInterpolation(html) {
39
+ const segments = [];
40
+ let lastIndex = 0;
41
+ let match;
42
+ const regex = /\{\{([\s\S]*?)\}\}/g;
43
+ while ((match = regex.exec(html)) !== null) {
44
+ const expr = match[1];
45
+ if (!expr)
46
+ continue;
47
+ if (match.index > lastIndex) {
48
+ segments.push({
49
+ content: html.slice(lastIndex, match.index),
50
+ isInterpolation: false,
51
+ });
52
+ }
53
+ segments.push({ content: expr.trim(), isInterpolation: true });
54
+ lastIndex = match.index + match[0].length;
55
+ }
56
+ if (lastIndex < html.length) {
57
+ segments.push({ content: html.slice(lastIndex), isInterpolation: false });
58
+ }
59
+ if (segments.length === 0 && html.length > 0) {
60
+ segments.push({ content: html, isInterpolation: false });
61
+ }
62
+ return segments;
63
+ }
64
+ /**
65
+ * Tokenize plain HTML content (without interpolation markers)
66
+ */
67
+ function tokenizeHtml(html) {
68
+ const tokens = [];
69
+ let pos = 0;
70
+ while (pos < html.length) {
71
+ // Comment
72
+ if (html.slice(pos, pos + 4) === '<!--') {
73
+ const end = html.indexOf('-->', pos + 4);
74
+ if (end === -1) {
75
+ tokens.push({ type: 'comment', value: html.slice(pos), attributes: {} });
76
+ break;
77
+ }
78
+ tokens.push({ type: 'comment', value: html.slice(pos + 4, end), attributes: {} });
79
+ pos = end + 3;
80
+ continue;
81
+ }
82
+ // Tag
83
+ if (html[pos] === '<') {
84
+ const nextChar = html[pos + 1] ?? '';
85
+ // Closing tag
86
+ if (nextChar === '/') {
87
+ const end = html.indexOf('>', pos + 2);
88
+ if (end === -1)
89
+ break;
90
+ const tagName = html.slice(pos + 2, end).trim().toLowerCase();
91
+ tokens.push({ type: 'tagClose', value: html.slice(pos, end + 1), tagName, attributes: {} });
92
+ pos = end + 1;
93
+ continue;
94
+ }
95
+ // Doctype / declaration
96
+ if (nextChar === '!') {
97
+ const end = html.indexOf('>', pos + 2);
98
+ if (end === -1)
99
+ break;
100
+ tokens.push({ type: 'doctype', value: html.slice(pos, end + 1), attributes: {} });
101
+ pos = end + 1;
102
+ continue;
103
+ }
104
+ const end = findTagEnd(html, pos + 1);
105
+ if (end === -1)
106
+ break;
107
+ const rawTagContent = html.slice(pos + 1, end).trim();
108
+ const selfClosing = rawTagContent.endsWith('/');
109
+ const cleanContent = selfClosing ? rawTagContent.slice(0, -1).trim() : rawTagContent;
110
+ const spaceIndex = cleanContent.search(/\s/);
111
+ const tagName = (spaceIndex === -1 ? cleanContent : cleanContent.slice(0, spaceIndex)).toLowerCase();
112
+ const attrString = spaceIndex === -1 ? '' : cleanContent.slice(spaceIndex + 1);
113
+ if (!tagName) {
114
+ pos = end + 1;
115
+ continue;
116
+ }
117
+ const attributes = parseAttributes(attrString);
118
+ const tokenType = selfClosing || isSelfClosingTag(tagName) ? 'tagSelfClosing' : 'tagOpen';
119
+ tokens.push({
120
+ type: tokenType,
121
+ value: html.slice(pos, end + 1),
122
+ tagName,
123
+ attributes,
124
+ selfClosing: tokenType === 'tagSelfClosing',
125
+ });
126
+ pos = end + 1;
127
+ continue;
128
+ }
129
+ // Text
130
+ const nextTag = html.indexOf('<', pos);
131
+ if (nextTag === -1) {
132
+ const text = html.slice(pos);
133
+ if (text)
134
+ tokens.push({ type: 'text', value: text, attributes: {} });
135
+ break;
136
+ }
137
+ const text = html.slice(pos, nextTag);
138
+ if (text)
139
+ tokens.push({ type: 'text', value: text, attributes: {} });
140
+ pos = nextTag;
141
+ }
142
+ return tokens;
143
+ }
144
+ function findTagEnd(html, start) {
145
+ let inSingleQuote = false;
146
+ let inDoubleQuote = false;
147
+ for (let i = start; i < html.length; i++) {
148
+ const ch = html[i];
149
+ if (!ch)
150
+ continue;
151
+ if (ch === "'" && !inDoubleQuote) {
152
+ inSingleQuote = !inSingleQuote;
153
+ continue;
154
+ }
155
+ if (ch === '"' && !inSingleQuote) {
156
+ inDoubleQuote = !inDoubleQuote;
157
+ continue;
158
+ }
159
+ if (ch === '>' && !inSingleQuote && !inDoubleQuote) {
160
+ return i;
161
+ }
162
+ }
163
+ return -1;
164
+ }
165
+ // Parse HTML attributes string into key-value map
166
+ function parseAttributes(attrString) {
167
+ const attributes = {};
168
+ // Supports:
169
+ // - name="value"
170
+ // - name='value'
171
+ // - name=value
172
+ // - bare attributes
173
+ // - directive/modifier names like x-on:click.stop
174
+ // - shorthand slot names like #header
175
+ const attrRegex = /([#@]?[\w:-]+(?:\.[\w:-]+)*)(?:=(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g;
176
+ let match;
177
+ while ((match = attrRegex.exec(attrString)) !== null) {
178
+ const name = match[1];
179
+ if (!name)
180
+ continue;
181
+ const doubleQuoted = match[2];
182
+ const singleQuoted = match[3];
183
+ const unquoted = match[4];
184
+ const value = doubleQuoted ?? singleQuoted ?? unquoted ?? '';
185
+ attributes[name] = value;
186
+ }
187
+ return attributes;
188
+ }
189
+ function isSelfClosingTag(tagName) {
190
+ const selfClosingTags = [
191
+ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
192
+ 'link', 'meta', 'param', 'source', 'track', 'wbr'
193
+ ];
194
+ return selfClosingTags.includes(tagName.toLowerCase());
195
+ }
196
+ /**
197
+ * Parse nodes recursively until EOF or matching closing tag.
198
+ */
199
+ function parseNodes(state, stopAtTag) {
200
+ const nodes = [];
201
+ while (state.pos < state.tokens.length) {
202
+ const token = state.tokens[state.pos];
203
+ if (!token) {
204
+ state.pos++;
205
+ continue;
206
+ }
207
+ if (token.type === 'tagClose') {
208
+ if (!stopAtTag || token.tagName === stopAtTag) {
209
+ break;
210
+ }
211
+ state.pos++;
212
+ continue;
213
+ }
214
+ if (token.type === 'doctype') {
215
+ state.pos++;
216
+ continue;
217
+ }
218
+ if (token.type === 'interpolation') {
219
+ nodes.push(createInterpolationNode(token.value));
220
+ state.pos++;
221
+ continue;
222
+ }
223
+ if (token.type === 'text') {
224
+ nodes.push(createTextNode(token.value));
225
+ state.pos++;
226
+ continue;
227
+ }
228
+ if (token.type === 'comment') {
229
+ nodes.push(createCommentNode(token.value));
230
+ state.pos++;
231
+ continue;
232
+ }
233
+ if (token.type === 'tagOpen' || token.type === 'tagSelfClosing') {
234
+ nodes.push(parseElement(state, token));
235
+ continue;
236
+ }
237
+ state.pos++;
238
+ }
239
+ return nodes;
240
+ }
241
+ function parseElement(state, token) {
242
+ const tagName = token.tagName ?? '';
243
+ if (tagName === 'slot') {
244
+ return parseSlotElement(state, token);
245
+ }
246
+ if (tagName === 'slot-placeholder') {
247
+ return parseSlotPlaceholderElement(state, token);
248
+ }
249
+ if (tagName === 'template') {
250
+ return parseTemplateElement(state, token);
251
+ }
252
+ return parseRegularElement(state, token);
253
+ }
254
+ function parseSlotElement(state, token) {
255
+ const attributes = token.attributes ?? {};
256
+ const name = attributes['name'] || 'default';
257
+ state.pos++;
258
+ const fallback = token.selfClosing ? [] : parseNodes(state, 'slot');
259
+ if (!token.selfClosing && state.tokens[state.pos]?.type === 'tagClose') {
260
+ state.pos++;
261
+ }
262
+ return {
263
+ type: 'Slot',
264
+ name,
265
+ fallback,
266
+ };
267
+ }
268
+ function parseSlotPlaceholderElement(state, token) {
269
+ const attributes = token.attributes ?? {};
270
+ const name = attributes['name'] || 'default';
271
+ state.pos++;
272
+ const children = token.selfClosing ? [] : parseNodes(state, 'slot-placeholder');
273
+ if (!token.selfClosing && state.tokens[state.pos]?.type === 'tagClose') {
274
+ state.pos++;
275
+ }
276
+ return {
277
+ type: 'SlotPlaceholder',
278
+ name,
279
+ children,
280
+ };
281
+ }
282
+ function parseTemplateElement(state, token) {
283
+ const attributes = token.attributes ?? {};
284
+ const hashSlot = Object.keys(attributes).find((key) => key.startsWith('#'));
285
+ const name = attributes['name'] || attributes['slot'] || (hashSlot ? hashSlot.slice(1) : '') || 'default';
286
+ state.pos++;
287
+ const children = token.selfClosing ? [] : parseNodes(state, 'template');
288
+ if (!token.selfClosing && state.tokens[state.pos]?.type === 'tagClose') {
289
+ state.pos++;
290
+ }
291
+ return {
292
+ type: 'TemplateBlock',
293
+ name,
294
+ children,
295
+ };
296
+ }
297
+ function parseRegularElement(state, token) {
298
+ const tagName = token.tagName ?? '';
299
+ const attributes = token.attributes ?? {};
300
+ const elementAttrs = {};
301
+ const directives = [];
302
+ for (const [key, value] of Object.entries(attributes)) {
303
+ if (isDirective(key)) {
304
+ directives.push(parseDirective(key, value));
305
+ continue;
306
+ }
307
+ // Vue-like shorthand support for developer ergonomics.
308
+ if (key.startsWith(':')) {
309
+ directives.push(parseDirective(`x-bind:${key.slice(1)}`, value));
310
+ continue;
311
+ }
312
+ if (key.startsWith('@')) {
313
+ directives.push(parseDirective(`x-on:${key.slice(1)}`, value));
314
+ continue;
315
+ }
316
+ elementAttrs[key] = value;
317
+ }
318
+ state.pos++;
319
+ const children = token.selfClosing ? [] : parseNodes(state, tagName);
320
+ if (!token.selfClosing && state.tokens[state.pos]?.type === 'tagClose') {
321
+ state.pos++;
322
+ }
323
+ return {
324
+ type: 'Element',
325
+ tag: tagName,
326
+ attributes: elementAttrs,
327
+ children,
328
+ directives,
329
+ };
330
+ }
331
+ function createInterpolationNode(expression) {
332
+ return {
333
+ type: 'Text',
334
+ value: '',
335
+ interpolation: expression,
336
+ };
337
+ }
338
+ function createTextNode(value) {
339
+ return {
340
+ type: 'Text',
341
+ value,
342
+ };
343
+ }
344
+ function createCommentNode(value) {
345
+ return {
346
+ type: 'Comment',
347
+ value,
348
+ };
349
+ }
350
+ //# sourceMappingURL=htmlParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"htmlParser.js","sourceRoot":"","sources":["../../src/parser/htmlParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * FeedJS Core - VDOM Diff Algorithm
3
+ *
4
+ * Deterministic, keyed diff algorithm for VDOM trees.
5
+ * Outputs patch operations for minimal DOM updates.
6
+ */
7
+ import type { VNode } from './vnode.js';
8
+ export type PatchType = 'CREATE' | 'REMOVE' | 'REPLACE' | 'UPDATE_PROPS' | 'MOVE';
9
+ export interface Patch {
10
+ type: PatchType;
11
+ node?: VNode;
12
+ index?: number;
13
+ from?: number;
14
+ to?: number;
15
+ props?: Record<string, unknown>;
16
+ }
17
+ export type PatchList = Patch[];
18
+ /**
19
+ * Diff two VDOM trees and produce patch operations
20
+ *
21
+ * @param oldTree - The previous VDOM tree
22
+ * @param newTree - The new VDOM tree
23
+ * @returns Array of patch operations
24
+ */
25
+ export declare function diff(oldTree: VNode | null, newTree: VNode | null): PatchList;
26
+ /**
27
+ * Apply patches to a VNode tree (for testing)
28
+ *
29
+ * Note: This is a simplified implementation. In production,
30
+ * the runtime would apply these patches to the actual DOM.
31
+ */
32
+ export declare function applyPatches(tree: VNode, patches: PatchList): VNode;
33
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/vdom/diff.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,cAAc,GACd,MAAM,CAAC;AAGX,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAGD,MAAM,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC;AAEhC;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,CAsB5E;AA4OD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,GAAG,KAAK,CAyBnE"}
@@ -0,0 +1,259 @@
1
+ /**
2
+ * FeedJS Core - VDOM Diff Algorithm
3
+ *
4
+ * Deterministic, keyed diff algorithm for VDOM trees.
5
+ * Outputs patch operations for minimal DOM updates.
6
+ */
7
+ /**
8
+ * Diff two VDOM trees and produce patch operations
9
+ *
10
+ * @param oldTree - The previous VDOM tree
11
+ * @param newTree - The new VDOM tree
12
+ * @returns Array of patch operations
13
+ */
14
+ export function diff(oldTree, newTree) {
15
+ const patches = [];
16
+ // Handle null cases
17
+ if (oldTree === null && newTree === null) {
18
+ return patches;
19
+ }
20
+ if (oldTree === null && newTree !== null) {
21
+ patches.push({ type: 'CREATE', node: newTree });
22
+ return patches;
23
+ }
24
+ if (oldTree !== null && newTree === null) {
25
+ patches.push({ type: 'REMOVE', index: 0 });
26
+ return patches;
27
+ }
28
+ // Both exist - diff them
29
+ diffNodes(oldTree, newTree, patches, 0);
30
+ return patches;
31
+ }
32
+ /**
33
+ * Diff two VNodes
34
+ */
35
+ function diffNodes(oldNode, newNode, patches, index) {
36
+ // Check if nodes are the same type
37
+ if (oldNode.type !== newNode.type) {
38
+ // Different types - replace
39
+ patches.push({ type: 'REPLACE', node: newNode });
40
+ return;
41
+ }
42
+ // Same type - check if it's a text node
43
+ if (typeof oldNode.type === 'symbol') {
44
+ // Text or Fragment
45
+ const oldText = getTextContent(oldNode);
46
+ const newText = getTextContent(newNode);
47
+ if (oldText !== newText) {
48
+ patches.push({ type: 'REPLACE', node: newNode });
49
+ }
50
+ return;
51
+ }
52
+ // Element node - diff props
53
+ if (oldNode.props || newNode.props) {
54
+ const propPatches = diffProps(oldNode.props, newNode.props);
55
+ if (propPatches && Object.keys(propPatches).length > 0) {
56
+ patches.push({ type: 'UPDATE_PROPS', props: propPatches });
57
+ }
58
+ }
59
+ // Diff children
60
+ diffChildren(oldNode.children, newNode.children, patches, index);
61
+ }
62
+ /**
63
+ * Get text content from a VNode
64
+ */
65
+ function getTextContent(node) {
66
+ if (typeof node.children === 'string') {
67
+ return node.children;
68
+ }
69
+ return '';
70
+ }
71
+ /**
72
+ * Diff props between two nodes
73
+ */
74
+ function diffProps(oldProps, newProps) {
75
+ const patches = {};
76
+ const allKeys = new Set([
77
+ ...Object.keys(oldProps ?? {}),
78
+ ...Object.keys(newProps ?? {}),
79
+ ]);
80
+ for (const key of allKeys) {
81
+ const oldValue = oldProps?.[key];
82
+ const newValue = newProps?.[key];
83
+ if (oldValue !== newValue) {
84
+ patches[key] = newValue;
85
+ }
86
+ }
87
+ return Object.keys(patches).length > 0 ? patches : null;
88
+ }
89
+ /**
90
+ * Diff children arrays
91
+ */
92
+ function diffChildren(oldChildren, newChildren, patches, parentIndex) {
93
+ // Normalize to arrays
94
+ const oldArray = normalizeChildren(oldChildren);
95
+ const newArray = normalizeChildren(newChildren);
96
+ // Handle simple case: both empty
97
+ if (oldArray.length === 0 && newArray.length === 0) {
98
+ return;
99
+ }
100
+ // Handle simple case: old empty, new has items
101
+ if (oldArray.length === 0) {
102
+ for (let i = 0; i < newArray.length; i++) {
103
+ const node = newArray[i];
104
+ if (node) {
105
+ patches.push({ type: 'CREATE', node, index: i });
106
+ }
107
+ }
108
+ return;
109
+ }
110
+ // Handle simple case: new empty, old has items
111
+ if (newArray.length === 0) {
112
+ for (let i = 0; i < oldArray.length; i++) {
113
+ patches.push({ type: 'REMOVE', index: parentIndex + i });
114
+ }
115
+ return;
116
+ }
117
+ // Both have children - use keyed diff
118
+ keyedDiff(oldArray, newArray, patches, parentIndex);
119
+ }
120
+ /**
121
+ * Normalize children to array
122
+ */
123
+ function normalizeChildren(children) {
124
+ if (children === null || children === undefined) {
125
+ return [];
126
+ }
127
+ if (typeof children === 'string') {
128
+ // Text node - return as single element
129
+ return [{
130
+ type: Symbol.for('feedjs.text'),
131
+ props: null,
132
+ children: children,
133
+ key: '',
134
+ }];
135
+ }
136
+ return children;
137
+ }
138
+ /**
139
+ * Keyed diff algorithm - O(n*m) but produces minimal patches
140
+ *
141
+ * This implements a simplified version of the keyed diff algorithm:
142
+ * 1. Match nodes by key
143
+ * 2. Reorder matched nodes
144
+ * 3. Create/remove unmatched nodes
145
+ */
146
+ function keyedDiff(oldArray, newArray, patches, parentIndex) {
147
+ // Build key maps
148
+ const oldKeyMap = new Map();
149
+ const newKeyMap = new Map();
150
+ // Index keyed nodes
151
+ for (let i = 0; i < oldArray.length; i++) {
152
+ const node = oldArray[i];
153
+ if (!node)
154
+ continue;
155
+ const key = node.key;
156
+ if (key) {
157
+ oldKeyMap.set(key, { node, index: i });
158
+ }
159
+ }
160
+ for (let i = 0; i < newArray.length; i++) {
161
+ const node = newArray[i];
162
+ if (!node)
163
+ continue;
164
+ const key = node.key;
165
+ if (key) {
166
+ newKeyMap.set(key, { node, index: i });
167
+ }
168
+ }
169
+ // Process new array
170
+ let oldIndex = 0;
171
+ for (let newIndex = 0; newIndex < newArray.length; newIndex++) {
172
+ const newNode = newArray[newIndex];
173
+ if (!newNode) {
174
+ // Skip undefined nodes but still track the position
175
+ oldIndex++;
176
+ continue;
177
+ }
178
+ const key = newNode.key;
179
+ if (key && oldKeyMap.has(key)) {
180
+ // Keyed match found
181
+ const oldMatch = oldKeyMap.get(key);
182
+ if (!oldMatch)
183
+ continue;
184
+ // Diff the matched nodes
185
+ diffNodes(oldMatch.node, newNode, patches, parentIndex + newIndex);
186
+ // Handle move if indices differ
187
+ if (oldMatch.index !== newIndex) {
188
+ patches.push({
189
+ type: 'MOVE',
190
+ from: oldMatch.index,
191
+ to: newIndex
192
+ });
193
+ }
194
+ oldIndex = oldMatch.index + 1;
195
+ }
196
+ else {
197
+ // No key match - check for type match at current position
198
+ if (oldIndex < oldArray.length) {
199
+ const oldNode = oldArray[oldIndex];
200
+ if (!oldNode) {
201
+ patches.push({ type: 'CREATE', node: newNode, index: newIndex });
202
+ oldIndex++;
203
+ continue;
204
+ }
205
+ if (oldNode.type === newNode.type && !oldNode.key) {
206
+ // Same type, diff them
207
+ diffNodes(oldNode, newNode, patches, parentIndex + newIndex);
208
+ oldIndex++;
209
+ }
210
+ else {
211
+ // Create new node
212
+ patches.push({ type: 'CREATE', node: newNode, index: newIndex });
213
+ }
214
+ }
215
+ else {
216
+ // No more old nodes - create
217
+ patches.push({ type: 'CREATE', node: newNode, index: newIndex });
218
+ }
219
+ }
220
+ }
221
+ // Remove remaining old nodes
222
+ for (let i = oldIndex; i < oldArray.length; i++) {
223
+ const oldNode = oldArray[i];
224
+ if (!oldNode)
225
+ continue;
226
+ if (!oldNode.key || !newKeyMap.has(oldNode.key)) {
227
+ patches.push({ type: 'REMOVE', index: parentIndex + i });
228
+ }
229
+ }
230
+ }
231
+ /**
232
+ * Apply patches to a VNode tree (for testing)
233
+ *
234
+ * Note: This is a simplified implementation. In production,
235
+ * the runtime would apply these patches to the actual DOM.
236
+ */
237
+ export function applyPatches(tree, patches) {
238
+ // Deep clone to avoid mutation
239
+ const result = JSON.parse(JSON.stringify(tree));
240
+ for (const patch of patches) {
241
+ switch (patch.type) {
242
+ case 'REPLACE':
243
+ // In a real implementation, we'd replace at the correct index
244
+ break;
245
+ case 'UPDATE_PROPS':
246
+ if (result.props && patch.props) {
247
+ Object.assign(result.props, patch.props);
248
+ }
249
+ break;
250
+ case 'CREATE':
251
+ case 'REMOVE':
252
+ case 'MOVE':
253
+ // These would be handled by the runtime
254
+ break;
255
+ }
256
+ }
257
+ return result;
258
+ }
259
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/vdom/diff.ts"],"names":[],"mappings":"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"}