@mulanjs/mulanjs 1.0.1-dev.20260227173253 → 1.0.1-dev.20260227175607
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.
- package/dist/compiler/ast-parser.js +57 -5
- package/dist/compiler/compiler.js +13 -6
- package/dist/compiler/dom-compiler.js +30 -6
- package/dist/compiler/script-compiler.js +22 -2
- package/dist/compiler/sfc-parser.js +1 -1
- package/dist/components/bloch-sphere.js +1 -1
- package/dist/mulan.esm.js +1 -1
- package/dist/mulan.esm.js.map +1 -1
- package/dist/mulan.js +1 -1
- package/dist/mulan.js.map +1 -1
- package/dist/types/ast-parser.d.ts +4 -0
- package/dist/types/compiler/ast-parser.d.ts +4 -0
- package/dist/types/compiler/dom-compiler.d.ts +1 -0
- package/dist/types/dom-compiler.d.ts +1 -0
- package/package.json +1 -1
- package/src/compiler/ast-parser.ts +63 -5
- package/src/compiler/compiler.ts +12 -7
- package/src/compiler/dom-compiler.ts +33 -7
- package/src/compiler/script-compiler.ts +22 -1
- package/src/compiler/sfc-parser.ts +1 -1
|
@@ -25,10 +25,21 @@ function parse(template, errors) {
|
|
|
25
25
|
tag: 'fragment',
|
|
26
26
|
props: {},
|
|
27
27
|
children: [],
|
|
28
|
-
directives: {}
|
|
28
|
+
directives: {},
|
|
29
|
+
startLine: 1,
|
|
30
|
+
startColumn: 0,
|
|
31
|
+
endLine: 1,
|
|
32
|
+
endColumn: 0
|
|
29
33
|
};
|
|
30
34
|
const stack = [root];
|
|
31
35
|
let cursor = 0;
|
|
36
|
+
const getPos = (idx) => {
|
|
37
|
+
const lines = template.slice(0, idx).split('\n');
|
|
38
|
+
return {
|
|
39
|
+
startLine: lines.length,
|
|
40
|
+
startColumn: lines[lines.length - 1].length
|
|
41
|
+
};
|
|
42
|
+
};
|
|
32
43
|
while (cursor < template.length) {
|
|
33
44
|
const char = template[cursor];
|
|
34
45
|
// 1. Comments
|
|
@@ -69,7 +80,18 @@ function parse(template, errors) {
|
|
|
69
80
|
const tagContent = template.slice(cursor + 1, end);
|
|
70
81
|
const { tag, props, directives } = parseTag(tagContent);
|
|
71
82
|
const isSelfClosing = tagContent.endsWith('/') || ['img', 'br', 'input', 'hr', 'link', 'meta'].includes(tag.toLowerCase());
|
|
72
|
-
const
|
|
83
|
+
const startPos = getPos(cursor);
|
|
84
|
+
const endPos = getPos(end + 1);
|
|
85
|
+
const element = {
|
|
86
|
+
type: 'Element',
|
|
87
|
+
tag,
|
|
88
|
+
props,
|
|
89
|
+
children: [],
|
|
90
|
+
directives,
|
|
91
|
+
...startPos,
|
|
92
|
+
endLine: endPos.startLine,
|
|
93
|
+
endColumn: endPos.startColumn
|
|
94
|
+
};
|
|
73
95
|
stack[stack.length - 1].children.push(element);
|
|
74
96
|
if (!isSelfClosing) {
|
|
75
97
|
stack.push(element);
|
|
@@ -85,7 +107,15 @@ function parse(template, errors) {
|
|
|
85
107
|
break;
|
|
86
108
|
}
|
|
87
109
|
const content = template.slice(cursor + 2, end).trim();
|
|
88
|
-
|
|
110
|
+
const startPos = getPos(cursor);
|
|
111
|
+
const endPos = getPos(end + 2);
|
|
112
|
+
stack[stack.length - 1].children.push({
|
|
113
|
+
type: 'Interpolation',
|
|
114
|
+
content,
|
|
115
|
+
...startPos,
|
|
116
|
+
endLine: endPos.startLine,
|
|
117
|
+
endColumn: endPos.startColumn
|
|
118
|
+
});
|
|
89
119
|
cursor = end + 2;
|
|
90
120
|
}
|
|
91
121
|
// 4. Native Template Literals ${ } (Protection)
|
|
@@ -105,9 +135,20 @@ function parse(template, errors) {
|
|
|
105
135
|
const lastChild = stack[stack.length - 1].children[stack[stack.length - 1].children.length - 1];
|
|
106
136
|
if (lastChild && lastChild.type === 'Text') {
|
|
107
137
|
lastChild.content += content;
|
|
138
|
+
const endPos = getPos(innerCursor);
|
|
139
|
+
lastChild.endLine = endPos.startLine;
|
|
140
|
+
lastChild.endColumn = endPos.startColumn;
|
|
108
141
|
}
|
|
109
142
|
else {
|
|
110
|
-
|
|
143
|
+
const startPos = getPos(cursor);
|
|
144
|
+
const endPos = getPos(innerCursor);
|
|
145
|
+
stack[stack.length - 1].children.push({
|
|
146
|
+
type: 'Text',
|
|
147
|
+
content,
|
|
148
|
+
...startPos,
|
|
149
|
+
endLine: endPos.startLine,
|
|
150
|
+
endColumn: endPos.startColumn
|
|
151
|
+
});
|
|
111
152
|
}
|
|
112
153
|
cursor = innerCursor;
|
|
113
154
|
}
|
|
@@ -136,9 +177,20 @@ function parse(template, errors) {
|
|
|
136
177
|
const lastChild = stack[stack.length - 1].children[stack[stack.length - 1].children.length - 1];
|
|
137
178
|
if (lastChild && lastChild.type === 'Text') {
|
|
138
179
|
lastChild.content += content;
|
|
180
|
+
const endPos = getPos(end);
|
|
181
|
+
lastChild.endLine = endPos.startLine;
|
|
182
|
+
lastChild.endColumn = endPos.startColumn;
|
|
139
183
|
}
|
|
140
184
|
else {
|
|
141
|
-
|
|
185
|
+
const startPos = getPos(cursor);
|
|
186
|
+
const endPos = getPos(end);
|
|
187
|
+
stack[stack.length - 1].children.push({
|
|
188
|
+
type: 'Text',
|
|
189
|
+
content,
|
|
190
|
+
...startPos,
|
|
191
|
+
endLine: endPos.startLine,
|
|
192
|
+
endColumn: endPos.startColumn
|
|
193
|
+
});
|
|
142
194
|
}
|
|
143
195
|
}
|
|
144
196
|
cursor = end;
|
|
@@ -13,14 +13,21 @@ async function compileSFC(source, filename, options) {
|
|
|
13
13
|
// 2. Script
|
|
14
14
|
const scriptResult = await (0, script_compiler_1.compileScript)(descriptor, options);
|
|
15
15
|
// Replace export default to capture the component
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
scriptCode = scriptCode.replace(
|
|
16
|
+
let scriptCode = scriptResult.code;
|
|
17
|
+
// Improved export capture
|
|
18
|
+
if (scriptCode.includes('export default')) {
|
|
19
|
+
scriptCode = scriptCode.replace('export default', 'const __component__ =');
|
|
20
20
|
}
|
|
21
|
-
if (
|
|
21
|
+
else if (scriptCode.includes('exports.default =')) {
|
|
22
22
|
scriptCode = scriptCode.replace('exports.default =', 'const __component__ =');
|
|
23
23
|
}
|
|
24
|
+
else if (scriptCode.includes('module.exports =')) {
|
|
25
|
+
scriptCode = scriptCode.replace('module.exports =', 'const __component__ =');
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// Fallback for simple assignment
|
|
29
|
+
scriptCode += '\nconst __component__ = exports.default || module.exports || {};';
|
|
30
|
+
}
|
|
24
31
|
// 3. Style
|
|
25
32
|
const styleResult = (0, style_compiler_1.compileStyle)(descriptor, filename, options);
|
|
26
33
|
// 4. Template (Use the new unified No-VDOM compiler!)
|
|
@@ -167,7 +174,7 @@ module.exports = __component__;
|
|
|
167
174
|
code: finalCode,
|
|
168
175
|
css: styleResult.css,
|
|
169
176
|
errors: [...scriptResult.errors, ...templateResult.errors],
|
|
170
|
-
map: mergedMap || scriptResult.map
|
|
177
|
+
map: mergedMap || scriptResult.map || templateResult.map
|
|
171
178
|
};
|
|
172
179
|
}
|
|
173
180
|
exports.compileSFC = compileSFC;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.compileToDOM = void 0;
|
|
4
4
|
const ast_parser_1 = require("./ast-parser");
|
|
5
|
+
const source_map_1 = require("source-map");
|
|
5
6
|
function compileToDOM(descriptor, scriptResult, scopedId) {
|
|
6
7
|
console.log(`[MulanJS DOM Compiler v2.0] Compiling template for: ${descriptor.filename || 'anonymous'}`);
|
|
7
8
|
const template = descriptor.template;
|
|
@@ -21,9 +22,12 @@ function compileToDOM(descriptor, scriptResult, scopedId) {
|
|
|
21
22
|
// We generate a DocumentFragment at the root
|
|
22
23
|
let codeChunks = [];
|
|
23
24
|
codeChunks.push(`const _frag = this._recoveryMode ? null : document.createDocumentFragment();`);
|
|
25
|
+
const generator = descriptor.filename ? new source_map_1.SourceMapGenerator({
|
|
26
|
+
file: descriptor.filename + '.template.js'
|
|
27
|
+
}) : null;
|
|
24
28
|
// Generate code for all top-level children and append them to the fragment
|
|
25
29
|
ast.children.forEach(child => {
|
|
26
|
-
const rootId = generateDOMInstruction(child, codeChunks, getUid, getHoistId, hoists, uidRef, scriptResult.bindings || [], []);
|
|
30
|
+
const rootId = generateDOMInstruction(child, codeChunks, getUid, getHoistId, hoists, uidRef, scriptResult.bindings || [], [], generator, descriptor.filename);
|
|
27
31
|
if (rootId) {
|
|
28
32
|
codeChunks.push(`if (_frag) _frag.appendChild(${rootId});`);
|
|
29
33
|
}
|
|
@@ -50,7 +54,8 @@ function compileToDOM(descriptor, scriptResult, scopedId) {
|
|
|
50
54
|
}`;
|
|
51
55
|
return {
|
|
52
56
|
code: renderFn,
|
|
53
|
-
errors
|
|
57
|
+
errors,
|
|
58
|
+
map: generator ? generator.toString() : undefined
|
|
54
59
|
};
|
|
55
60
|
}
|
|
56
61
|
exports.compileToDOM = compileToDOM;
|
|
@@ -88,7 +93,22 @@ function htmlEscape(str) {
|
|
|
88
93
|
.replace(/"/g, '"')
|
|
89
94
|
.replace(/'/g, ''');
|
|
90
95
|
}
|
|
91
|
-
function generateDOMInstruction(node, chunks, getUid, getHoistId, hoists, uidRef, bindings, localScope) {
|
|
96
|
+
function generateDOMInstruction(node, chunks, getUid, getHoistId, hoists, uidRef, bindings, localScope, generator, filename) {
|
|
97
|
+
const addMapping = (generatedLine) => {
|
|
98
|
+
if (generator && filename) {
|
|
99
|
+
generator.addMapping({
|
|
100
|
+
generated: {
|
|
101
|
+
line: generatedLine,
|
|
102
|
+
column: 0
|
|
103
|
+
},
|
|
104
|
+
original: {
|
|
105
|
+
line: node.startLine,
|
|
106
|
+
column: node.startColumn
|
|
107
|
+
},
|
|
108
|
+
source: filename
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
};
|
|
92
112
|
// --- STATIC NODE HOISTING (THE COMPILER INTELLIGENCE) ---
|
|
93
113
|
// If the node and ALL its children contain ZERO reactivity, we hoist it.
|
|
94
114
|
if (node.type === 'Element' && node.isStatic) {
|
|
@@ -116,11 +136,13 @@ function generateDOMInstruction(node, chunks, getUid, getHoistId, hoists, uidRef
|
|
|
116
136
|
const numericId = uidRef.current - 1; // Not used for text nodes in SSR but kept for parity if needed
|
|
117
137
|
// Native template literal interpolation
|
|
118
138
|
if (text.content.includes('${')) {
|
|
139
|
+
addMapping(chunks.length + 1);
|
|
119
140
|
chunks.push(`const ${id} = this._recoveryMode ? null : document.createTextNode("");`);
|
|
120
141
|
// Wrap in effect for reactivity
|
|
121
142
|
chunks.push(`this._bindEffect(() => { if (!${id}) return; ${id}.textContent = \`${text.content}\`; }, ${id});`);
|
|
122
143
|
}
|
|
123
144
|
else {
|
|
145
|
+
addMapping(chunks.length + 1);
|
|
124
146
|
chunks.push(`const ${id} = this._recoveryMode ? null : document.createTextNode(${JSON.stringify(text.content)});`);
|
|
125
147
|
}
|
|
126
148
|
return id;
|
|
@@ -128,6 +150,7 @@ function generateDOMInstruction(node, chunks, getUid, getHoistId, hoists, uidRef
|
|
|
128
150
|
if (node.type === 'Interpolation') {
|
|
129
151
|
const interp = node;
|
|
130
152
|
const id = getUid();
|
|
153
|
+
addMapping(chunks.length + 1);
|
|
131
154
|
chunks.push(`const ${id} = document.createTextNode("");`);
|
|
132
155
|
// Fine-grained reactivity!
|
|
133
156
|
chunks.push(`this._bindEffect(() => { ${id}.textContent = _h(${interp.content}, false); }, ${id});`);
|
|
@@ -151,7 +174,7 @@ function generateDOMInstruction(node, chunks, getUid, getHoistId, hoists, uidRef
|
|
|
151
174
|
let originalLength = blockChunks.length;
|
|
152
175
|
// 2b. Generate the actual block
|
|
153
176
|
const elementWithoutIf = { ...element, directives: { ...element.directives, vIf: undefined } };
|
|
154
|
-
const clonedChildId = generateDOMInstruction(elementWithoutIf, blockChunks, getUid, getHoistId, hoists, uidRef, bindings, localScope);
|
|
177
|
+
const clonedChildId = generateDOMInstruction(elementWithoutIf, blockChunks, getUid, getHoistId, hoists, uidRef, bindings, localScope, generator, filename);
|
|
155
178
|
if (clonedChildId) {
|
|
156
179
|
blockChunks.push(`if (${blockId}_frag && ${clonedChildId} && !this._recoveryMode) ${blockId}_frag.appendChild(${clonedChildId});`);
|
|
157
180
|
}
|
|
@@ -184,7 +207,7 @@ function generateDOMInstruction(node, chunks, getUid, getHoistId, hoists, uidRef
|
|
|
184
207
|
// 2b. Generate the actual repeating element (the template root of the mu-for)
|
|
185
208
|
// We strip the vFor directive so it doesn't recurse infinitely
|
|
186
209
|
const elementWithoutFor = { ...element, directives: { ...element.directives, vFor: undefined } };
|
|
187
|
-
const clonedChildId = generateDOMInstruction(elementWithoutFor, rowChunks, getUid, getHoistId, hoists, uidRef, bindings, rowChildScope);
|
|
210
|
+
const clonedChildId = generateDOMInstruction(elementWithoutFor, rowChunks, getUid, getHoistId, hoists, uidRef, bindings, rowChildScope, generator, filename);
|
|
188
211
|
if (clonedChildId) {
|
|
189
212
|
rowChunks.push(`if (${rowId}_frag && ${clonedChildId} && !this._recoveryMode) ${rowId}_frag.appendChild(${clonedChildId});`);
|
|
190
213
|
}
|
|
@@ -205,6 +228,7 @@ function generateDOMInstruction(node, chunks, getUid, getHoistId, hoists, uidRef
|
|
|
205
228
|
}
|
|
206
229
|
const numericId = uidRef.current;
|
|
207
230
|
const id = getUid();
|
|
231
|
+
addMapping(chunks.length + 1);
|
|
208
232
|
chunks.push(`const ${id} = this._recoveryMode ? (this.container.getAttribute('data-mu-node-id') === "${numericId}" ? this.container : this.container.querySelector('[data-mu-node-id="${numericId}"]')) : document.createElement("${element.tag}");`);
|
|
209
233
|
// Handle standard properties and classes
|
|
210
234
|
for (const [key, value] of Object.entries(element.props)) {
|
|
@@ -252,7 +276,7 @@ function generateDOMInstruction(node, chunks, getUid, getHoistId, hoists, uidRef
|
|
|
252
276
|
// Recursively generate children
|
|
253
277
|
const childScope = [...localScope];
|
|
254
278
|
element.children.forEach(child => {
|
|
255
|
-
const childId = generateDOMInstruction(child, chunks, getUid, getHoistId, hoists, uidRef, bindings, childScope);
|
|
279
|
+
const childId = generateDOMInstruction(child, chunks, getUid, getHoistId, hoists, uidRef, bindings, childScope, generator, filename);
|
|
256
280
|
if (childId) {
|
|
257
281
|
chunks.push(`if (${id} && ${childId} && !this._recoveryMode) ${id}.appendChild(${childId});`);
|
|
258
282
|
}
|
|
@@ -29,8 +29,28 @@ const source_map_1 = require("source-map");
|
|
|
29
29
|
const path = __importStar(require("path"));
|
|
30
30
|
async function compileScript(descriptor, options) {
|
|
31
31
|
const script = descriptor.script;
|
|
32
|
-
if (!script)
|
|
33
|
-
|
|
32
|
+
if (!script) {
|
|
33
|
+
let finalMap;
|
|
34
|
+
if (descriptor.filename) {
|
|
35
|
+
const generator = new source_map_1.SourceMapGenerator({
|
|
36
|
+
file: descriptor.filename
|
|
37
|
+
});
|
|
38
|
+
let relativePath = descriptor.filename.split(/[/\\]/).pop() || 'unknown.mujs';
|
|
39
|
+
const normalized = descriptor.filename.replace(/\\/g, '/');
|
|
40
|
+
const srcIdx = normalized.indexOf('/src/');
|
|
41
|
+
if (srcIdx !== -1) {
|
|
42
|
+
relativePath = 'webpack:///' + normalized.substring(srcIdx + 1);
|
|
43
|
+
}
|
|
44
|
+
generator.setSourceContent(relativePath, descriptor.source);
|
|
45
|
+
generator.addMapping({
|
|
46
|
+
generated: { line: 1, column: 0 },
|
|
47
|
+
original: { line: 1, column: 0 },
|
|
48
|
+
source: relativePath
|
|
49
|
+
});
|
|
50
|
+
finalMap = generator.toString();
|
|
51
|
+
}
|
|
52
|
+
return { code: 'export default {}', errors: [], map: finalMap };
|
|
53
|
+
}
|
|
34
54
|
let content = script.content;
|
|
35
55
|
let filename = descriptor.filename;
|
|
36
56
|
let isExternal = false;
|
|
@@ -66,7 +66,7 @@ function parseMUJS(source, filename) {
|
|
|
66
66
|
const content = source.slice(contentStart, contentEnd);
|
|
67
67
|
const block = {
|
|
68
68
|
type: tagName,
|
|
69
|
-
content: content
|
|
69
|
+
content: content,
|
|
70
70
|
attrs,
|
|
71
71
|
start: start,
|
|
72
72
|
end: contentEnd + closeTag.length
|
|
@@ -253,6 +253,6 @@ class MuBlochSphereElement extends MuBlochBase {
|
|
|
253
253
|
}
|
|
254
254
|
exports.MuBlochSphereElement = MuBlochSphereElement;
|
|
255
255
|
// Register the custom element
|
|
256
|
-
if (typeof customElements !== 'undefined') {
|
|
256
|
+
if (typeof customElements !== 'undefined' && !customElements.get('mu-bloch-sphere')) {
|
|
257
257
|
customElements.define('mu-bloch-sphere', MuBlochSphereElement);
|
|
258
258
|
}
|
package/dist/mulan.esm.js
CHANGED
|
@@ -2318,7 +2318,7 @@ class MuBlochSphereElement extends MuBlochBase {
|
|
|
2318
2318
|
}
|
|
2319
2319
|
}
|
|
2320
2320
|
// Register the custom element
|
|
2321
|
-
if (typeof customElements !== 'undefined') {
|
|
2321
|
+
if (typeof customElements !== 'undefined' && !customElements.get('mu-bloch-sphere')) {
|
|
2322
2322
|
customElements.define('mu-bloch-sphere', MuBlochSphereElement);
|
|
2323
2323
|
}
|
|
2324
2324
|
|