@mulanjs/mulanjs 1.0.1-dev.20260227135307 → 1.0.1-dev.20260227172006

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 (52) hide show
  1. package/dist/compiler/ast-parser.d.ts +48 -0
  2. package/dist/compiler/ast-parser.js +54 -9
  3. package/dist/compiler/compiler.d.ts +9 -0
  4. package/dist/compiler/compiler.js +45 -2
  5. package/dist/compiler/dom-compiler.d.ts +7 -0
  6. package/dist/compiler/dom-compiler.js +90 -33
  7. package/dist/compiler/script-compiler.d.ts +11 -0
  8. package/dist/compiler/script-compiler.js +108 -116
  9. package/dist/compiler/sfc-parser.d.ts +21 -0
  10. package/dist/compiler/ssr-compiler.d.ts +7 -0
  11. package/dist/compiler/ssr-compiler.js +142 -0
  12. package/dist/compiler/style-compiler.d.ts +8 -0
  13. package/dist/compiler/template-compiler.d.ts +8 -0
  14. package/dist/components/bloch-sphere.js +9 -3
  15. package/dist/components/infinity-list.js +7 -1
  16. package/dist/core/component.js +66 -15
  17. package/dist/core/hooks.js +53 -29
  18. package/dist/core/quantum.js +30 -17
  19. package/dist/core/query.js +11 -6
  20. package/dist/core/reactive.js +88 -7
  21. package/dist/core/renderer.js +9 -8
  22. package/dist/core/ssr.js +50 -0
  23. package/dist/core/surge.js +7 -2
  24. package/dist/core/vault.js +9 -5
  25. package/dist/index.js +63 -27
  26. package/dist/mulan.esm.js +1933 -1626
  27. package/dist/mulan.esm.js.map +1 -1
  28. package/dist/mulan.js +1890 -1590
  29. package/dist/mulan.js.map +1 -1
  30. package/dist/router/index.js +17 -10
  31. package/dist/security/sanitizer.js +5 -1
  32. package/dist/store/index.js +9 -5
  33. package/dist/types/ast-parser.d.ts +2 -0
  34. package/dist/types/compiler/ast-parser.d.ts +2 -0
  35. package/dist/types/compiler/compiler.d.ts +1 -0
  36. package/dist/types/compiler/ssr-compiler.d.ts +7 -0
  37. package/dist/types/compiler.d.ts +1 -0
  38. package/dist/types/components/bloch-sphere.d.ts +3 -1
  39. package/dist/types/components/infinity-list.d.ts +3 -1
  40. package/dist/types/core/component.d.ts +14 -0
  41. package/dist/types/core/reactive.d.ts +5 -1
  42. package/dist/types/core/renderer.d.ts +0 -1
  43. package/dist/types/core/ssr.d.ts +9 -0
  44. package/dist/types/index.d.ts +1 -0
  45. package/dist/types/ssr-compiler.d.ts +7 -0
  46. package/package.json +1 -1
  47. package/src/compiler/ast-parser.ts +62 -10
  48. package/src/compiler/compiler.ts +46 -1
  49. package/src/compiler/dom-compiler.ts +100 -34
  50. package/src/compiler/script-compiler.ts +117 -126
  51. package/src/compiler/ssr-compiler.ts +157 -0
  52. package/src/loader/index.js +12 -19
@@ -175,118 +175,112 @@ export default ${hasDefineComponent ? 'defineComponent' : '_defineComponent'}({
175
175
  });
176
176
  `;
177
177
  const finalCode = preamble + scriptBody + postamble;
178
- if (isTs) {
179
- // Transpile extracted TS code to JS
180
- const result = ts.transpileModule(finalCode, {
181
- compilerOptions: {
182
- module: ts.ModuleKind.ESNext,
183
- target: ts.ScriptTarget.ES2019,
184
- sourceMap: true, // ENABLE SOURCE MAPS
185
- inlineSources: true,
186
- sourceRoot: '/',
187
- },
188
- fileName: filename // We ask TS to map to filename, but it maps 'finalCode' -> 'filename'
189
- });
190
- // Fix: Remove the //# sourceMappingURL= comment added by TS
191
- const codeWithoutMapComment = result.outputText.replace(/\/\/# sourceMappingURL=.*$/gm, '');
192
- // Enhance Source Map to show ORIGINAL .mujs content or EXTERNAL content
193
- let finalMap = result.sourceMapText;
194
- if (finalMap) {
195
- try {
196
- // Determine offsets
197
- const preambleLines = preamble.split('\n').length - 1;
198
- // scriptBody starts at line `preambleLines` (0-indexed) in finalCode.
199
- // Determine where script starts
200
- // If External: Start at 0
201
- // If Inline: Start at script.start line
202
- let linesBeforeScript = 0;
203
- let originalSource = content;
204
- if (!isExternal) {
205
- originalSource = descriptor.source;
206
- linesBeforeScript = originalSource.substring(0, script.start).split('\n').length - 1;
207
- }
208
- const consumer = new source_map_1.SourceMapConsumer(JSON.parse(finalMap));
209
- const generator = new source_map_1.SourceMapGenerator({
210
- file: filename,
211
- sourceRoot: ''
212
- });
213
- // Determine relative path for source
214
- let relativePath = filename.split(/[/\\]/).pop() || 'unknown.mujs'; // Default to basename
215
- if (isExternal) {
216
- // For external files, we want Source Map to point to the actual TS file
217
- // externalPath is absolute. Make it relative to project root or something reasonable?
218
- // Webpack often likes 'webpack:///[resource-path]'
219
- // We'll try to map it so it looks like a separate file
220
- const normalized = externalPath.replace(/\\/g, '/');
221
- const srcIdx = normalized.indexOf('/src/');
222
- if (srcIdx !== -1) {
223
- relativePath = 'webpack:///' + normalized.substring(srcIdx + 1); // e.g. webpack:///src/logic.ts
224
- }
225
- else {
226
- relativePath = 'webpack:///' + path.basename(externalPath);
227
- }
178
+ // Standardize to CommonJS for SSR/Node compatibility
179
+ // Transpile extracted code to JS (handles TS and ESM -> CJS)
180
+ const result = ts.transpileModule(finalCode, {
181
+ compilerOptions: {
182
+ module: ts.ModuleKind.CommonJS,
183
+ target: ts.ScriptTarget.ES2019,
184
+ sourceMap: true,
185
+ inlineSources: true,
186
+ sourceRoot: '/',
187
+ },
188
+ fileName: filename
189
+ });
190
+ const codeWithoutMapComment = result.outputText.replace(/\/\/# sourceMappingURL=.*$/gm, '');
191
+ let finalMap = result.sourceMapText;
192
+ if (isTs && finalMap) {
193
+ // ... (source map logic)
194
+ }
195
+ if (finalMap) {
196
+ try {
197
+ // Determine offsets
198
+ const preambleLines = preamble.split('\n').length - 1;
199
+ // scriptBody starts at line `preambleLines` (0-indexed) in finalCode.
200
+ // Determine where script starts
201
+ // If External: Start at 0
202
+ // If Inline: Start at script.start line
203
+ let linesBeforeScript = 0;
204
+ let originalSource = content;
205
+ if (!isExternal) {
206
+ originalSource = descriptor.source;
207
+ linesBeforeScript = originalSource.substring(0, script.start).split('\n').length - 1;
208
+ }
209
+ const consumer = new source_map_1.SourceMapConsumer(JSON.parse(finalMap));
210
+ const generator = new source_map_1.SourceMapGenerator({
211
+ file: filename,
212
+ sourceRoot: ''
213
+ });
214
+ // Determine relative path for source
215
+ let relativePath = filename.split(/[/\\]/).pop() || 'unknown.mujs'; // Default to basename
216
+ if (isExternal) {
217
+ // For external files, we want Source Map to point to the actual TS file
218
+ // externalPath is absolute. Make it relative to project root or something reasonable?
219
+ // Webpack often likes 'webpack:///[resource-path]'
220
+ // We'll try to map it so it looks like a separate file
221
+ const normalized = externalPath.replace(/\\/g, '/');
222
+ const srcIdx = normalized.indexOf('/src/');
223
+ if (srcIdx !== -1) {
224
+ relativePath = 'webpack:///' + normalized.substring(srcIdx + 1); // e.g. webpack:///src/logic.ts
228
225
  }
229
226
  else {
230
- // Inline: Point to .mujs file
231
- const normalized = filename.replace(/\\/g, '/');
232
- const srcIdx = normalized.indexOf('/src/');
233
- if (srcIdx !== -1) {
234
- relativePath = 'webpack:///' + normalized.substring(srcIdx + 1); // e.g. webpack:///src/App.mujs
235
- }
227
+ relativePath = 'webpack:///' + path.basename(externalPath);
236
228
  }
237
- // If inline, we set source content of .mujs (the whole file)
238
- // If external, we set source content of the .ts file
239
- generator.setSourceContent(relativePath, originalSource);
240
- consumer.eachMapping((m) => {
241
- if (m.originalLine === null)
242
- return;
243
- // m.originalLine is the line in `finalCode` (1-based because SourceMapConsumer uses 1-based)
244
- // We need to convert it to line in `.mujs`.
245
- // Check if this line belongs to scriptBody
246
- // scriptBody spans from (preambleLines + 1) to (preambleLines + scriptBodyLines)
247
- const lineInFinalCode = m.originalLine;
248
- // Check if strictly inside body
249
- if (lineInFinalCode > preambleLines) {
250
- // Calculate offset inside scriptBody
251
- const lineOffsetInBody = lineInFinalCode - preambleLines; // 1-based offset (1st line of body is 1)
252
- // Calculate original line
253
- // If External: lineOffsetInBody is the line number
254
- // If Inline: linesBeforeScript + lineOffsetInBody
255
- const originalLine = linesBeforeScript + lineOffsetInBody;
256
- // Add mapping
257
- generator.addMapping({
258
- generated: {
259
- line: m.generatedLine,
260
- column: m.generatedColumn
261
- },
262
- original: {
263
- line: originalLine,
264
- column: m.originalColumn // Column should be preserved if we didn't change indentation
265
- },
266
- source: relativePath,
267
- name: m.name
268
- });
269
- }
270
- });
271
- finalMap = generator.toString();
272
- // consumer.destroy() not needed in 0.6.x
273
229
  }
274
- catch (e) {
275
- console.warn('[MulanJS] Failed to patch source map:', e);
230
+ else {
231
+ // Inline: Point to .mujs file
232
+ const normalized = filename.replace(/\\/g, '/');
233
+ const srcIdx = normalized.indexOf('/src/');
234
+ if (srcIdx !== -1) {
235
+ relativePath = 'webpack:///' + normalized.substring(srcIdx + 1); // e.g. webpack:///src/App.mujs
236
+ }
276
237
  }
238
+ // If inline, we set source content of .mujs (the whole file)
239
+ // If external, we set source content of the .ts file
240
+ generator.setSourceContent(relativePath, originalSource);
241
+ consumer.eachMapping((m) => {
242
+ if (m.originalLine === null)
243
+ return;
244
+ // m.originalLine is the line in `finalCode` (1-based because SourceMapConsumer uses 1-based)
245
+ // We need to convert it to line in `.mujs`.
246
+ // Check if this line belongs to scriptBody
247
+ // scriptBody spans from (preambleLines + 1) to (preambleLines + scriptBodyLines)
248
+ const lineInFinalCode = m.originalLine;
249
+ // Check if strictly inside body
250
+ if (lineInFinalCode > preambleLines) {
251
+ // Calculate offset inside scriptBody
252
+ const lineOffsetInBody = lineInFinalCode - preambleLines; // 1-based offset (1st line of body is 1)
253
+ // Calculate original line
254
+ // If External: lineOffsetInBody is the line number
255
+ // If Inline: linesBeforeScript + lineOffsetInBody
256
+ const originalLine = linesBeforeScript + lineOffsetInBody;
257
+ // Add mapping
258
+ generator.addMapping({
259
+ generated: {
260
+ line: m.generatedLine,
261
+ column: m.generatedColumn
262
+ },
263
+ original: {
264
+ line: originalLine,
265
+ column: m.originalColumn // Column should be preserved if we didn't change indentation
266
+ },
267
+ source: relativePath,
268
+ name: m.name
269
+ });
270
+ }
271
+ });
272
+ finalMap = generator.toString();
273
+ // consumer.destroy() not needed in 0.6.x
274
+ }
275
+ catch (e) {
276
+ console.warn('[MulanJS] Failed to patch source map:', e);
277
277
  }
278
- return {
279
- code: codeWithoutMapComment,
280
- bindings,
281
- errors: [],
282
- map: finalMap // Return the enhanced map
283
- };
284
278
  }
285
279
  return {
286
- code: finalCode,
280
+ code: codeWithoutMapComment,
287
281
  bindings,
288
282
  errors: [],
289
- map: undefined
283
+ map: finalMap // Return the enhanced map
290
284
  };
291
285
  }
292
286
  async function compileStandardScript(script, descriptor, content, filename, isExternal, externalPath) {
@@ -294,20 +288,18 @@ async function compileStandardScript(script, descriptor, content, filename, isEx
294
288
  // and/or just to map it back to .mujs
295
289
  let finalMap;
296
290
  let code = content;
297
- // Transpile if TS
298
- if (externalPath.endsWith('.ts') || script.attrs.lang === 'ts') {
299
- const result = ts.transpileModule(content, {
300
- compilerOptions: {
301
- module: ts.ModuleKind.ESNext,
302
- target: ts.ScriptTarget.ES2019,
303
- sourceMap: true,
304
- inlineSources: true,
305
- },
306
- fileName: filename
307
- });
308
- code = result.outputText.replace(/\/\/# sourceMappingURL=.*$/gm, '');
309
- finalMap = result.sourceMapText;
310
- }
291
+ // Standardize to CommonJS for SSR/Node compatibility
292
+ const result = ts.transpileModule(content, {
293
+ compilerOptions: {
294
+ module: ts.ModuleKind.CommonJS,
295
+ target: ts.ScriptTarget.ES2019,
296
+ sourceMap: true,
297
+ inlineSources: true,
298
+ },
299
+ fileName: filename
300
+ });
301
+ code = result.outputText.replace(/\/\/# sourceMappingURL=.*$/gm, '');
302
+ finalMap = result.sourceMapText;
311
303
  // Adjust Source Map
312
304
  if (finalMap) {
313
305
  try {
@@ -0,0 +1,21 @@
1
+ export interface SFCBlock {
2
+ type: 'script' | 'template' | 'style';
3
+ content: string;
4
+ attrs: Record<string, string>;
5
+ start: number;
6
+ end: number;
7
+ }
8
+ export interface SFCDescriptor {
9
+ filename: string;
10
+ source: string;
11
+ template: SFCBlock | null;
12
+ script: SFCBlock | null;
13
+ scripts: SFCBlock[];
14
+ styles: SFCBlock[];
15
+ customBlocks: SFCBlock[];
16
+ }
17
+ /**
18
+ * Standardized State-Machine Parser for MulanJS
19
+ * Parses .mujs files safely, handling attributes, quotes, and nested content.
20
+ */
21
+ export declare function parseMUJS(source: string, filename: string): SFCDescriptor;
@@ -0,0 +1,7 @@
1
+ import { SFCDescriptor } from './sfc-parser';
2
+ import { ScriptCompileResult } from './script-compiler';
3
+ export interface SSRCompileResult {
4
+ code: string;
5
+ errors: string[];
6
+ }
7
+ export declare function compileToSSR(descriptor: SFCDescriptor, scriptResult: ScriptCompileResult, scopedId?: string): SSRCompileResult;
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compileToSSR = void 0;
4
+ const ast_parser_1 = require("./ast-parser");
5
+ function compileToSSR(descriptor, scriptResult, scopedId) {
6
+ const template = descriptor.template;
7
+ if (!template)
8
+ return { code: 'function render() { return ""; }', errors: [] };
9
+ const errors = [];
10
+ const ast = (0, ast_parser_1.parse)(template.content, errors);
11
+ // Simplistic Transformer (Options API bindings mapping)
12
+ const bindings = scriptResult.bindings || [];
13
+ const localScope = [];
14
+ let uidRef = { current: 0 };
15
+ const getUid = () => uidRef.current++;
16
+ let codeChunks = [];
17
+ ast.children.forEach(child => {
18
+ const chunk = generateSSRInstruction(child, bindings, localScope, getUid);
19
+ if (chunk)
20
+ codeChunks.push(chunk);
21
+ });
22
+ // The render function generates a giant template literal
23
+ const bodyFn = `return \`${codeChunks.join('')}\`;`;
24
+ const renderFn = `function render() {
25
+ const _s = (v) => (v && typeof v === 'object' && 'value' in v) ? v.value : (v === null || v === undefined ? '' : v);
26
+ const _h = (v) => {
27
+ const val = _s(v);
28
+ if (val === null || val === undefined) return '';
29
+ if (typeof val !== 'string') return val;
30
+ if (typeof Mulan !== 'undefined' && Mulan.Security) {
31
+ return Mulan.Security.sanitize(val);
32
+ }
33
+ return val.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;');
34
+ };
35
+
36
+ ${bodyFn}
37
+ }`;
38
+ return {
39
+ code: renderFn,
40
+ errors
41
+ };
42
+ }
43
+ exports.compileToSSR = compileToSSR;
44
+ function processBindings(exp, bindings, localScope) {
45
+ const isOptionsAPI = !bindings || bindings.length === 0;
46
+ const bindingSet = new Set(bindings || []);
47
+ return exp.replace(/\b([a-zA-Z_$][\w$]*)\b/g, (match, id, offset, str) => {
48
+ if (offset > 0 && str[offset - 1] === '.')
49
+ return match;
50
+ // simplistic keyword check
51
+ if (['true', 'false', 'null', 'undefined', 'this', 'Math'].includes(id) || localScope.includes(id))
52
+ return match;
53
+ if (isOptionsAPI)
54
+ return `this.${id}`;
55
+ if (bindingSet.has(id))
56
+ return `this.${id}`;
57
+ return match;
58
+ });
59
+ }
60
+ function generateSSRInstruction(node, bindings, localScope, getUid) {
61
+ if (node.type === 'Text') {
62
+ const text = node;
63
+ // we can preserve interpolation \${ } because the outer string is also a template literal
64
+ // but we need to ensure the variables map to 'this'
65
+ if (text.content.includes('${')) {
66
+ let processed = text.content.replace(/\$\{(.*?)\}/g, (_, expr) => {
67
+ return `\${_h(${processBindings(expr, bindings, localScope)})}`;
68
+ });
69
+ return processed;
70
+ }
71
+ return text.content;
72
+ }
73
+ if (node.type === 'Interpolation') {
74
+ const interp = node;
75
+ return `\${_h(${processBindings(interp.content, bindings, localScope)})}`;
76
+ }
77
+ if (node.type === 'Element') {
78
+ const el = node;
79
+ const uid = getUid();
80
+ let html = `<${el.tag} data-mu-node-id="${uid}"`;
81
+ let vIfCondition = '';
82
+ let vForDirective = null;
83
+ for (const key in el.props) {
84
+ if (key === 'v-if' || key === 'mu-if') {
85
+ vIfCondition = processBindings(el.props[key], bindings, localScope);
86
+ continue;
87
+ }
88
+ if (key === 'v-for' || key === 'mu-for') {
89
+ const parts = el.props[key].split(' in ');
90
+ if (parts.length >= 2) {
91
+ vForDirective = { item: parts[0].trim(), list: processBindings(parts.slice(1).join(' in ').trim(), bindings, localScope) };
92
+ }
93
+ continue;
94
+ }
95
+ // Client side events are ignored in SSR HTML output
96
+ if (key.startsWith('@') || key.startsWith('v-on:') || key.startsWith('on')) {
97
+ // To support Resumability, we'd inject a serialize marker here
98
+ // html += ` mu-event="${key}"`;
99
+ continue;
100
+ }
101
+ let value = el.props[key];
102
+ if (key.startsWith(':') || key.startsWith('.')) {
103
+ let attrName = key.slice(1);
104
+ let expr = processBindings(value, bindings, localScope);
105
+ html += ` ${attrName}="\${_h(${expr})}"`;
106
+ }
107
+ else {
108
+ if (value.includes('${')) {
109
+ value = value.replace(/\$\{(.*?)\}/g, (_, expr) => {
110
+ return `\${_h(${processBindings(expr, bindings, localScope)})}`;
111
+ });
112
+ html += ` ${key}="${value}"`;
113
+ }
114
+ else {
115
+ html += ` ${key}="${value.replace(/"/g, '&quot;')}"`;
116
+ }
117
+ }
118
+ }
119
+ const isSelfClosing = ['img', 'br', 'input', 'hr', 'link', 'meta'].includes(el.tag.toLowerCase());
120
+ if (isSelfClosing) {
121
+ html += '/>';
122
+ }
123
+ else {
124
+ html += '>';
125
+ for (const child of el.children) {
126
+ html += generateSSRInstruction(child, bindings, localScope, getUid);
127
+ }
128
+ html += `</${el.tag}>`;
129
+ }
130
+ // Apply wrappers for Control Flow (v-if / v-for)
131
+ if (vIfCondition) {
132
+ html = `\${(${vIfCondition}) ? \`${html}\` : '<!--mu-if-->'}`;
133
+ }
134
+ if (vForDirective) {
135
+ const { item, list } = vForDirective;
136
+ // The mapping function returns strings which we join
137
+ html = `\${(${list}).map((${item}, _index) => \`${html}\`).join('')}`;
138
+ }
139
+ return html;
140
+ }
141
+ return '';
142
+ }
@@ -0,0 +1,8 @@
1
+ import { SFCDescriptor } from './sfc-parser';
2
+ import { CompilerOptions } from './script-compiler';
3
+ export interface StyleCompileResult {
4
+ css: string;
5
+ scopedId?: string;
6
+ errors: string[];
7
+ }
8
+ export declare function compileStyle(descriptor: SFCDescriptor, filename: string, options?: CompilerOptions): StyleCompileResult;
@@ -0,0 +1,8 @@
1
+ import { SFCDescriptor } from './sfc-parser';
2
+ import { ScriptCompileResult } from './script-compiler';
3
+ export interface TemplateCompileResult {
4
+ code: string;
5
+ errors: string[];
6
+ map?: string;
7
+ }
8
+ export declare function compileTemplate(descriptor: SFCDescriptor, scriptResult: ScriptCompileResult, scopedId?: string): TemplateCompileResult;
@@ -1,5 +1,10 @@
1
- import { effect } from '../core/reactive';
2
- export class MuBlochSphereElement extends HTMLElement {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MuBlochSphereElement = void 0;
4
+ const reactive_1 = require("../core/reactive");
5
+ const MuBlochBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {
6
+ };
7
+ class MuBlochSphereElement extends MuBlochBase {
3
8
  static get observedAttributes() {
4
9
  return ['size'];
5
10
  }
@@ -39,7 +44,7 @@ export class MuBlochSphereElement extends HTMLElement {
39
44
  if (!this._qubit)
40
45
  return;
41
46
  // MulanJS Effect: Run whenever the qubit state changes
42
- this._disposeEffect = effect(() => {
47
+ this._disposeEffect = (0, reactive_1.effect)(() => {
43
48
  const state = this._qubit.value; // Access reactive proxy
44
49
  if (!state || !state.amplitudes)
45
50
  return;
@@ -246,6 +251,7 @@ export class MuBlochSphereElement extends HTMLElement {
246
251
  this.initReactivity();
247
252
  }
248
253
  }
254
+ exports.MuBlochSphereElement = MuBlochSphereElement;
249
255
  // Register the custom element
250
256
  if (typeof customElements !== 'undefined') {
251
257
  customElements.define('mu-bloch-sphere', MuBlochSphereElement);
@@ -1,4 +1,9 @@
1
- export class MuInfinity extends HTMLElement {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MuInfinity = void 0;
4
+ const MuInfinityBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {
5
+ };
6
+ class MuInfinity extends MuInfinityBase {
2
7
  constructor() {
3
8
  super();
4
9
  this._items = [];
@@ -104,6 +109,7 @@ export class MuInfinity extends HTMLElement {
104
109
  this.content.innerHTML = html;
105
110
  }
106
111
  }
112
+ exports.MuInfinity = MuInfinity;
107
113
  // Register
108
114
  if (typeof customElements !== 'undefined' && !customElements.get('mu-infinity')) {
109
115
  customElements.define('mu-infinity', MuInfinity);
@@ -1,14 +1,19 @@
1
- import { render } from './renderer';
2
- import { setCurrentInstance } from './hooks';
3
- import { effect } from './reactive';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineComponent = exports.MuComponent = void 0;
4
+ const renderer_1 = require("./renderer");
5
+ const hooks_1 = require("./hooks");
6
+ const reactive_1 = require("./reactive");
4
7
  // Or a simple component that returns an object of state/methods used by template?
5
8
  // For Mulan 2.0, let's say functional component returns a template string render function explicitly.
6
- export class MuComponent {
9
+ class MuComponent {
7
10
  constructor(container) {
8
11
  this._hooks = {};
9
12
  this._effects = [];
10
13
  this._domEffects = [];
11
14
  this._isDestroyed = false;
15
+ this._isResuming = false; // Quantum Resumability Flag
16
+ this._resumeRoot = null;
12
17
  this._propsQueue = [];
13
18
  this._eventQueue = [];
14
19
  // --- MulanJS List Reconciliation Engine (No-VDOM) ---
@@ -20,6 +25,26 @@ export class MuComponent {
20
25
  this.container = container;
21
26
  this.state = {};
22
27
  this.$uid = 'mu_' + Math.random().toString(36).substr(2, 9);
28
+ // MULAN INSIGHT: Quantum Resumability Detection
29
+ if (typeof window !== 'undefined' && container) {
30
+ const rootAttr = container.getAttribute('data-mu-root');
31
+ const stateScript = container.querySelector('script[type="mulan/state"]');
32
+ if (rootAttr || stateScript) {
33
+ console.log(`%c[Mulan Quantum]%c Resuming component from server state...`, "color: #00ffcc; font-weight: bold;", "");
34
+ this._isResuming = true;
35
+ this.$uid = rootAttr || this.$uid;
36
+ if (stateScript) {
37
+ try {
38
+ const serverState = JSON.parse(stateScript.textContent || '{}');
39
+ // Inject server state into this instance
40
+ Object.assign(this, serverState);
41
+ }
42
+ catch (e) {
43
+ console.error("[Mulan Quantum] Failed to parse server state:", e);
44
+ }
45
+ }
46
+ }
47
+ }
23
48
  // MULAN INSIGHT: Global Registry for Debugging
24
49
  if (typeof window !== 'undefined') {
25
50
  const global = window;
@@ -27,9 +52,9 @@ export class MuComponent {
27
52
  global.__MULAN_INSIGHT__.components.set(this.$uid, this);
28
53
  }
29
54
  // Setup context for hooks
30
- setCurrentInstance(this);
55
+ (0, hooks_1.setCurrentInstance)(this);
31
56
  this.setup();
32
- setCurrentInstance(null);
57
+ (0, hooks_1.setCurrentInstance)(null);
33
58
  }
34
59
  // Optional setup method for class components wanting to use hooks
35
60
  setup() { }
@@ -80,17 +105,41 @@ export class MuComponent {
80
105
  }
81
106
  mount() {
82
107
  console.log(`[Mulan Cycle] Mounting component ${this.$uid}`);
83
- // The main render effect (legacy strings fallback / macro structure)
84
- const stop = effect(() => {
85
- console.log(`[Mulan Reactivity] Triggering macro-update for ${this.$uid}`);
86
- this.update();
87
- });
88
- this._effects.push(stop);
108
+ if (this._isResuming) {
109
+ // Quantum Resumability: Skip initial render, just attach effects to existing DOM
110
+ console.log(`[Mulan Quantum] Skipping initial render, recovering DOM nodes...`);
111
+ this._resume();
112
+ }
113
+ else {
114
+ // Standard Hydration/Mount
115
+ const stop = (0, reactive_1.effect)(() => {
116
+ console.log(`[Mulan Reactivity] Triggering macro-update for ${this.$uid}`);
117
+ this.update();
118
+ });
119
+ this._effects.push(stop);
120
+ }
89
121
  this.onMount();
90
122
  }
123
+ /**
124
+ * Internal method to execute the resumability pass.
125
+ * Overridden by compiler-generated code.
126
+ */
127
+ _resume() {
128
+ // Clear queues
129
+ this._propsQueue = [];
130
+ this._eventQueue = [];
131
+ // Call the template with resumption context
132
+ // In a real implementation, the compiler will inject 'recovery' instructions
133
+ this._recoveryMode = true;
134
+ this.template();
135
+ this._recoveryMode = false;
136
+ // Flush bindings (events/props) to existing nodes
137
+ this.flushProps();
138
+ this.flushEvents();
139
+ }
91
140
  // New helper for the compiler to register a fine-grained DOM property effect
92
141
  _bindEffect(fn, targetNode) {
93
- const stop = effect(fn, targetNode);
142
+ const stop = (0, reactive_1.effect)(fn, targetNode);
94
143
  this._domEffects.push(stop);
95
144
  return stop;
96
145
  }
@@ -104,7 +153,7 @@ export class MuComponent {
104
153
  this._eventQueue = [];
105
154
  const template = this.template();
106
155
  // Render HTML
107
- render(template, this.container);
156
+ (0, renderer_1.render)(template, this.container);
108
157
  // Flush Side Effects
109
158
  this.flushProps();
110
159
  this.flushEvents();
@@ -272,10 +321,11 @@ export class MuComponent {
272
321
  }
273
322
  }
274
323
  }
324
+ exports.MuComponent = MuComponent;
275
325
  // Helper to create functional components wrapped in the class system
276
326
  // Helper to create functional components wrapped in the class system
277
327
  // Supports both () => render and { setup() } signatures
278
- export function defineComponent(optionsOrSetup) {
328
+ function defineComponent(optionsOrSetup) {
279
329
  return class UniversalComponent extends MuComponent {
280
330
  constructor(container) {
281
331
  super(container);
@@ -307,3 +357,4 @@ export function defineComponent(optionsOrSetup) {
307
357
  }
308
358
  };
309
359
  }
360
+ exports.defineComponent = defineComponent;