@mbler/mcx-core 0.0.3-dev.20260229 → 0.0.3

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 (30) hide show
  1. package/dist/index.d.ts +185 -108
  2. package/dist/index.js +728 -1714
  3. package/dist/index.js.map +1 -1
  4. package/dist/types/compile-mcx/compiler/index.d.ts +2 -2
  5. package/dist/types/compile-mcx/compiler/main.d.ts +2 -1
  6. package/dist/types/compile-mcx/index.d.ts +1 -0
  7. package/dist/types/compile-mcx/types.d.ts +4 -2
  8. package/dist/types/index.d.ts +4 -13
  9. package/dist/types/mcx-component/index.d.ts +2 -0
  10. package/dist/types/{compile-component → mcx-component}/lib.d.ts +0 -3
  11. package/dist/types/transforms/config.d.ts +1 -0
  12. package/dist/types/transforms/file_id.d.ts +1 -0
  13. package/dist/types/transforms/index.d.ts +3 -3
  14. package/dist/types/transforms/main.d.ts +2 -0
  15. package/dist/types/transforms/utils.d.ts +20 -5
  16. package/dist/types/transforms/x-comp/index.d.ts +3 -0
  17. package/dist/types/transforms/x-comp/x-app.d.ts +2 -0
  18. package/dist/types/transforms/x-comp/x-event.d.ts +2 -0
  19. package/dist/types/transforms/x-comp/x-ui.d.ts +2 -0
  20. package/dist/types/tsc/index.d.ts +1 -0
  21. package/dist/types/tsc/volar/index.d.ts +1 -0
  22. package/dist/types/tsc/volar/plugins/index.d.ts +1 -0
  23. package/dist/types/tsc/volar/plugins/mcx-file.d.ts +37 -0
  24. package/dist/types/types.d.ts +41 -14
  25. package/package.json +20 -16
  26. package/dist/types/compile-component/index.d.ts +0 -4
  27. package/dist/types/compile-mcx/compiler/bundler.d.ts +0 -2
  28. package/dist/types/compile-mcx/compiler/str.d.ts +0 -6
  29. /package/dist/types/{compile-component → mcx-component}/types.d.ts +0 -0
  30. /package/dist/types/{compile-component → mcx-component}/utils.d.ts +0 -0
package/dist/index.js CHANGED
@@ -1,12 +1,16 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var fs = require('node:fs/promises');
6
4
  var path = require('node:path');
5
+ var rollup = require('rollup');
6
+ var commjs = require('@rollup/plugin-commonjs');
7
+ var json = require('@rollup/plugin-json');
8
+ var module_resolve = require('@rollup/plugin-node-resolve');
7
9
  var t = require('@babel/types');
8
10
  var Parser = require('@babel/parser');
11
+ var ts = require('typescript');
9
12
  var generator = require('@babel/generator');
13
+ var MagicString = require('magic-string');
10
14
 
11
15
  function _interopNamespaceDefault(e) {
12
16
  var n = Object.create(null);
@@ -29,8 +33,11 @@ var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
29
33
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
30
34
  var t__namespace = /*#__PURE__*/_interopNamespaceDefault(t);
31
35
  var Parser__namespace = /*#__PURE__*/_interopNamespaceDefault(Parser);
32
- var generator__namespace = /*#__PURE__*/_interopNamespaceDefault(generator);
33
36
 
37
+ /** 创建位置对象的辅助函数 */
38
+ function createPos(line, column) {
39
+ return { line, column };
40
+ }
34
41
  let Lexer$1 = class Lexer {
35
42
  text;
36
43
  booleanProxyCache;
@@ -114,12 +121,13 @@ let Lexer$1 = class Lexer {
114
121
  }
115
122
  /**
116
123
  * 拆分输入文本为 Token 流:Tag、TagEnd、Content
117
- * 新增:忽略 HTML 注释 <!-- ... --> 并记录每个 token 的起始位置与行号
124
+ * 忽略 HTML 注释 <!-- ... --> 并记录每个 token 的起始位置与行号
118
125
  */
119
126
  *tagSplitIterator() {
120
127
  const text = this.text;
121
128
  let i = 0;
122
129
  let line = 1;
130
+ let column = 0;
123
131
  const len = text.length;
124
132
  while (i < len) {
125
133
  const ch = text[i];
@@ -128,17 +136,23 @@ let Lexer$1 = class Lexer {
128
136
  if (text.startsWith('!--', i + 1)) {
129
137
  const endIdx = text.indexOf('-->', i + 4);
130
138
  const commentEnd = endIdx === -1 ? len - 1 : endIdx + 2;
131
- // 更新行号
132
- const segment = text.slice(i, commentEnd + 1);
133
- for (const c of segment)
134
- if (c === '\n')
139
+ // 更新行号和列号
140
+ for (let j = i; j <= commentEnd; j++) {
141
+ if (text[j] === '\n') {
135
142
  line++;
143
+ column = 0;
144
+ }
145
+ else {
146
+ column++;
147
+ }
148
+ }
136
149
  i = commentEnd + 1;
137
150
  continue; // 跳过注释
138
151
  }
139
152
  // 普通标签读取到 '>'
140
153
  const tokenStart = i;
141
154
  const tokenStartLine = line;
155
+ const tokenStartColumn = column;
142
156
  let j = i + 1;
143
157
  let sawGt = false;
144
158
  for (; j < len; j++) {
@@ -147,41 +161,51 @@ let Lexer$1 = class Lexer {
147
161
  sawGt = true;
148
162
  break;
149
163
  }
150
- if (c === '\n')
164
+ if (c === '\n') {
151
165
  line++;
166
+ column = 0;
167
+ }
168
+ else {
169
+ column++;
170
+ }
152
171
  }
153
- const tokenEnd = j;
154
172
  const buffer = text.slice(tokenStart, sawGt ? j + 1 : len);
155
173
  const type = buffer.startsWith('</') ? 'TagEnd' : 'Tag';
156
174
  const tok = {
157
175
  data: buffer,
158
176
  type,
159
- startIndex: tokenStart,
160
- endIndex: sawGt ? tokenEnd : len - 1,
161
- startLine: tokenStartLine
177
+ start: createPos(tokenStartLine, tokenStartColumn),
178
+ end: createPos(line, column)
162
179
  };
163
180
  yield tok;
164
181
  i = sawGt ? j + 1 : len;
182
+ if (sawGt)
183
+ column++;
165
184
  }
166
185
  else {
167
186
  // 内容直到下一个 '<'
168
187
  const contentStart = i;
169
188
  const contentStartLine = line;
189
+ const contentStartColumn = column;
170
190
  let j = i;
171
191
  for (; j < len; j++) {
172
192
  const c = text[j];
173
193
  if (c === '<')
174
194
  break;
175
- if (c === '\n')
195
+ if (c === '\n') {
176
196
  line++;
197
+ column = 0;
198
+ }
199
+ else {
200
+ column++;
201
+ }
177
202
  }
178
203
  const data = text.slice(contentStart, j);
179
204
  const n = {
180
205
  data,
181
206
  type: 'Content',
182
- startIndex: contentStart,
183
- endIndex: j - 1,
184
- startLine: contentStartLine
207
+ start: createPos(contentStartLine, contentStartColumn),
208
+ end: createPos(line, j > contentStart ? column - 1 : column)
185
209
  };
186
210
  yield n;
187
211
  i = j;
@@ -190,7 +214,7 @@ let Lexer$1 = class Lexer {
190
214
  }
191
215
  /**
192
216
  * 生成 Token 迭代器,用于遍历所有结构化 Token
193
- * 改为基于 stack 的解析以支持嵌套,并为 ParsedTagNode 添加 loc: { start:{line,index}, end:{line,index} }
217
+ * 改为基于 stack 的解析以支持嵌套,并为 ParsedTagNode 添加 loc: { start, end }
194
218
  * Content 改为递归节点数组 (ParsedTagContentNode | ParsedTagNode)[]
195
219
  */
196
220
  *tokenIterator() {
@@ -222,10 +246,10 @@ let Lexer$1 = class Lexer {
222
246
  // content 现在是一个数组,包含文本节点或子标签
223
247
  content: [],
224
248
  end: null,
225
- // loc: start/end positions will be set when available
249
+ type: 'TagNode',
226
250
  loc: {
227
- start: { line: token.startLine || 1, index: token.startIndex || 0 },
228
- end: { line: token.startLine || 1, index: token.endIndex || (token.startIndex || 0) }
251
+ start: { ...token.start },
252
+ end: { ...token.end }
229
253
  }
230
254
  };
231
255
  if (isSelfClosing) {
@@ -251,7 +275,7 @@ let Lexer$1 = class Lexer {
251
275
  if (candidate && candidate.name === name) {
252
276
  // 设置结束
253
277
  candidate.end = token;
254
- candidate.loc.end = { line: token.startLine || candidate.loc.start.line, index: token.endIndex || (token.loc.start.index) };
278
+ candidate.loc.end = { ...token.end };
255
279
  // 从 stack 中移除并附加到父节点或作为顶层节点产出
256
280
  stack.splice(s, 1);
257
281
  if (stack.length > 0) {
@@ -379,6 +403,8 @@ class MCXUtils {
379
403
  typeof obj === 'object' &&
380
404
  'data' in obj &&
381
405
  'type' in obj &&
406
+ 'start' in obj &&
407
+ 'end' in obj &&
382
408
  ((obj.type) === 'Tag' || (obj.type) === 'TagEnd' || (obj.type) === 'Content'));
383
409
  }
384
410
  static isTagToken(obj) {
@@ -397,7 +423,9 @@ class MCXUtils {
397
423
  return (!!obj &&
398
424
  typeof obj === 'object' &&
399
425
  'data' in obj &&
400
- 'type' in obj);
426
+ 'type' in obj &&
427
+ 'start' in obj &&
428
+ 'end' in obj);
401
429
  }
402
430
  static isTokenType(value) {
403
431
  return (value === 'Tag' ||
@@ -708,30 +736,31 @@ class CompileError extends Error {
708
736
  constructor(message, loc) {
709
737
  super(message);
710
738
  this.name = "CompileError";
711
- this.loc = loc || { line: -1, pos: -1 };
739
+ this.loc = loc || { line: -1, column: -1 };
712
740
  }
713
741
  }
714
742
  function extractLoc(node) {
715
743
  if (!node)
716
- return { line: -1, pos: -1 };
717
- // Node with loc.start (Babel or MCX): prefer column, fallback to index
744
+ return { line: -1, column: -1 };
745
+ // Node with loc.start (Babel or MCX): prefer column
718
746
  if (node.loc && node.loc.start) {
719
747
  const line = typeof node.loc.start.line === "number" ? node.loc.start.line : -1;
720
- const pos = typeof node.loc.start.column === "number"
748
+ const column = typeof node.loc.start.column === "number"
721
749
  ? node.loc.start.column
722
- : typeof node.loc.start.index === "number"
723
- ? node.loc.start.index
724
- : -1;
725
- return { line, pos };
726
- }
727
- // Our token shape from Lexer: startLine / startIndex
728
- if (typeof node.startLine === "number" || typeof node.startIndex === "number") {
729
- const line = typeof node.startLine === "number" ? node.startLine : -1;
730
- const pos = typeof node.startIndex === "number" ? node.startIndex : -1;
731
- return { line, pos };
732
- }
733
- // (handled above) MCX ParsedTagNode loc: { start: { line, index } }
734
- return { line: -1, pos: -1 };
750
+ : -1;
751
+ return { line, column };
752
+ }
753
+ else if (node.loc && node.loc.column !== undefined) {
754
+ return {
755
+ line: node.loc.line ?? -1,
756
+ column: node.loc.column
757
+ };
758
+ }
759
+ // MCX Token with unified position: start: { line, column }
760
+ if (node.start && typeof node.start.line === "number") {
761
+ return { line: node.start.line, column: node.start.column ?? -1 };
762
+ }
763
+ return { line: -1, column: -1 };
735
764
  }
736
765
  function makeError(msg, node) {
737
766
  return new CompileError(msg, extractLoc(node));
@@ -1120,10 +1149,11 @@ class CompileMCX {
1120
1149
  Event: {
1121
1150
  on: "after",
1122
1151
  subscribe: {},
1123
- loc: { line: -1, pos: -1 },
1152
+ loc: { line: -1, column: -1 },
1124
1153
  isLoad: false,
1125
1154
  },
1126
1155
  Component: {},
1156
+ UI: null,
1127
1157
  };
1128
1158
  getCompileData() {
1129
1159
  return this.CompileData;
@@ -1161,15 +1191,25 @@ class CompileMCX {
1161
1191
  let component = null;
1162
1192
  const temp = {
1163
1193
  script: "",
1164
- Event: null};
1194
+ Event: null,
1195
+ ui: null};
1165
1196
  for (const node of this.mcxCode || []) {
1166
1197
  if (!MCXUtils.isTagNode(node))
1167
1198
  continue;
1168
1199
  if (node.name == "script") {
1169
1200
  if (temp.script)
1170
1201
  throw makeError("[compile error]: duplicate script node", node);
1171
- temp.script =
1172
- node.content.length == 0 ? "" : this.commonTagNodeContent(node);
1202
+ const scriptNode = node.content.length == 0 ? "" : this.commonTagNodeContent(node);
1203
+ let code = scriptNode;
1204
+ if (node.arr.lang == "ts") {
1205
+ code = ts.transpileModule(scriptNode, {
1206
+ compilerOptions: {
1207
+ target: ts.ScriptTarget.ES2024,
1208
+ module: ts.ModuleKind.ESNext,
1209
+ },
1210
+ }).outputText;
1211
+ }
1212
+ temp.script = code;
1173
1213
  }
1174
1214
  else if (node.name == "Event") {
1175
1215
  if (temp.Event)
@@ -1185,8 +1225,15 @@ class CompileMCX {
1185
1225
  // if Event already discovered, report error
1186
1226
  if (temp.Event)
1187
1227
  throw makeError("[compile error]: Component node cannot appear after Event", node);
1228
+ if (temp.ui)
1229
+ throw makeError("[compile error]: Component node can't use with UI node");
1188
1230
  component = node;
1189
1231
  }
1232
+ else if (node.name == "Ui") {
1233
+ if (component || temp.Event || temp.ui)
1234
+ throw makeError("[compile error]: UI node can't use with component or event or other ui node", node);
1235
+ temp.ui = node;
1236
+ }
1190
1237
  }
1191
1238
  if (!temp.script)
1192
1239
  throw makeError("[compile error]: mcx must has a script");
@@ -1218,6 +1265,9 @@ class CompileMCX {
1218
1265
  this.handlerChildComponent(subNode);
1219
1266
  }
1220
1267
  }
1268
+ if (temp.ui) {
1269
+ this.tempLoc.UI = temp.ui;
1270
+ }
1221
1271
  }
1222
1272
  // 传入组件的节点,处理子组件(如 items entities)
1223
1273
  handlerChildComponent(node) {
@@ -1247,7 +1297,7 @@ class CompileMCX {
1247
1297
  this.tempLoc.Component[`${name}/${id}`] = {
1248
1298
  type: subName,
1249
1299
  useExpore: useExpore,
1250
- loc: extractLoc(subNode)
1300
+ loc: extractLoc(subNode),
1251
1301
  };
1252
1302
  }
1253
1303
  }
@@ -1261,7 +1311,34 @@ class CompileMCX {
1261
1311
  }
1262
1312
  }
1263
1313
  function compileJSFn(code) {
1264
- const comiler = new CompileJS(Parser.parse(code, { sourceType: "module" }).program);
1314
+ let parsedCode;
1315
+ try {
1316
+ parsedCode = Parser.parse(code, {
1317
+ sourceType: "module",
1318
+ allowImportExportEverywhere: true,
1319
+ errorRecovery: true,
1320
+ allowAwaitOutsideFunction: true,
1321
+ allowReturnOutsideFunction: true,
1322
+ allowSuperOutsideMethod: true,
1323
+ });
1324
+ }
1325
+ catch (err) {
1326
+ if (err instanceof SyntaxError) {
1327
+ const babelErr = err;
1328
+ const loc = babelErr.loc ?? { column: -1, line: -1 };
1329
+ throw makeError(`[babel parse error]: ${err.message}`, { loc: { start: loc } });
1330
+ }
1331
+ throw makeError(`[parse error]: ${String(err)}`);
1332
+ }
1333
+ // 检查解析过程中的错误(当启用 errorRecovery 时)
1334
+ const parseErrors = parsedCode.errors;
1335
+ if (parseErrors && Array.isArray(parseErrors) && parseErrors.length > 0) {
1336
+ const firstError = parseErrors[0];
1337
+ if (firstError && firstError.loc) {
1338
+ throw makeError(`[babel parse error]: ${firstError.message || 'Unknown parse error'}`, { loc: firstError.loc });
1339
+ }
1340
+ }
1341
+ const comiler = new CompileJS(parsedCode.program);
1265
1342
  comiler.run();
1266
1343
  return comiler.getCompileData();
1267
1344
  }
@@ -1270,7 +1347,7 @@ function compileMCXFn(mcxCode) {
1270
1347
  return compiler.getCompileData();
1271
1348
  }
1272
1349
 
1273
- var Compiler = /*#__PURE__*/Object.freeze({
1350
+ var index$2 = /*#__PURE__*/Object.freeze({
1274
1351
  __proto__: null,
1275
1352
  CompileError: CompileError,
1276
1353
  CompileJS: CompileJS,
@@ -1281,1699 +1358,468 @@ var Compiler = /*#__PURE__*/Object.freeze({
1281
1358
  var config = {
1282
1359
  // script tag compile function name
1283
1360
  scriptCompileFn: "__main",
1284
- eventVarName: "__use_event",
1285
- eventExtendsName: "McxExtendsBy"
1361
+ eventExtendsName: "McxExtendsBy",
1362
+ // paramName
1363
+ paramCtx: "__mcx__ctx"
1286
1364
  };
1287
1365
 
1288
- const allKeys = (() => {
1289
- // 闭包
1290
- const findkeyByVarId = (id, result) => {
1291
- if (id.type == "VoidPattern")
1292
- return;
1293
- if (id.type == "ArrayPattern") {
1294
- id.elements.forEach((node) => {
1295
- if (!node)
1296
- return;
1297
- findkeyByVarId(node, result);
1298
- });
1299
- }
1300
- else if (id.type == "Identifier") {
1301
- result.push(id.name);
1366
+ let fileIdCounter = 0;
1367
+ function generateFileId() {
1368
+ return `__file_import_${fileIdCounter++}__`;
1369
+ }
1370
+
1371
+ function extrectVarDefIdList(express) {
1372
+ const result = [];
1373
+ if (t__namespace.isIdentifier(express))
1374
+ result.push(express.name);
1375
+ if (t__namespace.isObjectPattern(express))
1376
+ express.properties.forEach((prop) => {
1377
+ // const {xxx:xxx,xxx=Litter} = xxx
1378
+ if (t__namespace.isObjectProperty(prop))
1379
+ return result.push(...extrectVarDefIdList(prop.value));
1380
+ // const {...restElement} = xx (restElement in this, ,must identifier)
1381
+ if (t__namespace.isRestElement(prop) && prop.argument.type == "Identifier")
1382
+ result.push(prop.argument.name);
1383
+ });
1384
+ if (t__namespace.isArrayPattern(express)) {
1385
+ for (const element of express.elements) {
1386
+ if (!element)
1387
+ continue;
1388
+ result.push(...extrectVarDefIdList(element));
1302
1389
  }
1303
- else if (id.type == "RestElement") {
1304
- const arg = id.argument;
1305
- findkeyByVarId(arg, result);
1390
+ }
1391
+ if (t__namespace.isAssignmentPattern(express)) {
1392
+ result.push(...extrectVarDefIdList(express.left));
1393
+ }
1394
+ return result;
1395
+ }
1396
+ function extractIdList(expression) {
1397
+ if (t__namespace.isFunctionDeclaration(expression)) {
1398
+ return [expression.id?.name || ""];
1399
+ }
1400
+ if (t__namespace.isVariableDeclaration(expression)) {
1401
+ const result = [];
1402
+ for (const varDef of expression.declarations) {
1403
+ result.push(...extrectVarDefIdList(varDef.id));
1306
1404
  }
1307
- else if (id.type == "ObjectPattern") {
1308
- for (const property of id.properties) {
1309
- if (property.type == "ObjectProperty") {
1310
- const key = property.key;
1311
- if (property.value.type == "AssignmentPattern") {
1312
- const assigmentNode = property.value;
1313
- findkeyByVarId(assigmentNode.left, result);
1405
+ return result;
1406
+ }
1407
+ if (t__namespace.isClassDeclaration(expression)) {
1408
+ // 'export class {}'is not vaild(error: class name is required).
1409
+ return [expression.id?.name || ""];
1410
+ }
1411
+ return [];
1412
+ }
1413
+ function ToExpression(s) {
1414
+ if (t__namespace.isFunctionDeclaration(s))
1415
+ return t__namespace.functionExpression(s.id, s.params, s.body, s.generator, s.async);
1416
+ if (t__namespace.isClassDeclaration(s))
1417
+ return t__namespace.classExpression(s.id, s.superClass, s.body, s.decorators);
1418
+ if (t__namespace.isTSDeclareFunction(s))
1419
+ return t__namespace.objectExpression([]);
1420
+ return s;
1421
+ }
1422
+ function generateMain(code) {
1423
+ const expBody = [];
1424
+ const impBody = code.BuildCache.import.map((item) => {
1425
+ return Utils.CacheToImportNode(item);
1426
+ });
1427
+ const codeBody = code.node.body;
1428
+ for (const exp of code.BuildCache.export) {
1429
+ if (t__namespace.isExportNamedDeclaration(exp)) {
1430
+ // export {xxx} from "./xxx" or export xxx from "./xxx"
1431
+ if (exp.source &&
1432
+ exp.specifiers &&
1433
+ exp.specifiers.length >= 1 &&
1434
+ exp.source.value.length >= 1) {
1435
+ impBody.push(t__namespace.importDeclaration(exp.specifiers.map((item) => {
1436
+ if (t__namespace.isExportDefaultSpecifier(item)) {
1437
+ expBody.push(t__namespace.objectProperty(item.exported, item.exported));
1438
+ return t__namespace.importDefaultSpecifier(item.exported);
1314
1439
  }
1315
- else if (key.type == "Identifier") {
1316
- result.push(key.name);
1440
+ if (t__namespace.isExportSpecifier(item)) {
1441
+ expBody.push(t__namespace.objectProperty(item.exported, item.exported));
1442
+ return t__namespace.importSpecifier(item.local, item.exported);
1317
1443
  }
1444
+ if (t__namespace.isExportNamespaceSpecifier(item)) {
1445
+ expBody.push(t__namespace.spreadElement(item.exported));
1446
+ return t__namespace.importNamespaceSpecifier(item.exported);
1447
+ }
1448
+ // 不加的话,ts就报错
1449
+ throw new Error("[build import]: 这也不是那也不是, 你是个登啊(ts也是galgame)");
1450
+ }), exp.source));
1451
+ }
1452
+ if (exp.declaration) {
1453
+ const idList = extractIdList(exp.declaration);
1454
+ // be like: const {} = {}; (worthless)
1455
+ if (idList.length < 1)
1318
1456
  continue;
1319
- }
1320
- findkeyByVarId(property.argument, result);
1321
- }
1457
+ codeBody.push(exp.declaration);
1458
+ expBody.push(...idList.map((id) => {
1459
+ return t__namespace.objectProperty(t__namespace.identifier(id), t__namespace.identifier(id));
1460
+ }));
1461
+ }
1462
+ // export { xxx }
1463
+ if (exp.specifiers && !exp.source) {
1464
+ expBody.push(...exp.specifiers.map((item) => {
1465
+ if (!t__namespace.isExportSpecifier(item))
1466
+ throw new Error(`[build import]: invaild specifiers`);
1467
+ return t__namespace.objectProperty(item.exported, item.local);
1468
+ }));
1469
+ }
1470
+ // export * from "xxx"
1322
1471
  }
1323
- else if (id.type == "AssignmentPattern") {
1324
- findkeyByVarId(id.left, result);
1472
+ else if (t__namespace.isExportAllDeclaration(exp)) {
1473
+ // xxx.js => xxx_js(id)
1474
+ const id = generateFileId();
1475
+ impBody.push(t__namespace.importDeclaration([t__namespace.importNamespaceSpecifier(t__namespace.identifier(id))], exp.source));
1476
+ expBody.push(t__namespace.objectProperty(t__namespace.identifier(id), t__namespace.identifier(id)));
1477
+ // export default {} or export default function a(){}
1325
1478
  }
1326
- };
1327
- return (node) => {
1328
- let result = [];
1329
- if (node.type == "VariableDeclaration") {
1330
- for (const declaration of node.declarations) {
1331
- findkeyByVarId(declaration.id, result);
1332
- }
1479
+ else if (t__namespace.isExportDefaultDeclaration(exp)) {
1480
+ // to expression
1481
+ expBody.push(t__namespace.objectProperty(t__namespace.identifier("default"), ToExpression(exp.declaration)));
1333
1482
  }
1334
- return result;
1335
- };
1336
- })();
1337
- const generateTempId = (() => {
1338
- let num = 0;
1339
- return () => {
1340
- num++;
1341
- return `__mcx_${num}`;
1342
- };
1343
- })();
1344
- function generateMain(JSIR) {
1345
- // Build a function `__main(ctx) { ... }` containing the original module body.
1346
- // After the function we emit explicit property assignments to attach exported
1347
- // bindings as properties on the function (e.g. `__main.default = ...`). This
1348
- // avoids using `Object.assign` while keeping handlers accessible as
1349
- // `__main.<exportName>`.
1350
- const iifeBody = t__namespace.blockStatement(JSIR.node.body.slice());
1351
- const importDeclarations = JSIR.BuildCache.import.map(Utils.CacheToImportNode);
1352
- const mainId = t__namespace.identifier(config.scriptCompileFn);
1353
- const exportsProps = [];
1354
- if (JSIR.BuildCache.export.length >= 1) {
1355
- for (let exportNode of JSIR.BuildCache.export) {
1356
- if (exportNode.type == "ExportNamedDeclaration") {
1357
- if (exportNode.declaration) {
1358
- // move declaration into the function body
1359
- iifeBody.body.push(exportNode.declaration);
1360
- const keys = allKeys(exportNode.declaration);
1361
- keys.forEach((name) => {
1362
- exportsProps.push(t__namespace.objectProperty(t__namespace.identifier(name), t__namespace.identifier(name)));
1363
- });
1364
- continue;
1365
- }
1366
- else if (exportNode.specifiers.length >= 1 && exportNode.source) {
1367
- // export ... from 'mod' — import namespace into a temp id and spread it in return
1368
- const id = generateTempId();
1369
- importDeclarations.push(t__namespace.importDeclaration([t__namespace.importNamespaceSpecifier(t__namespace.identifier(id))], exportNode.source));
1370
- exportsProps.push(t__namespace.spreadElement(t__namespace.identifier(id)));
1371
- }
1372
- }
1373
- else if (exportNode.type == "ExportDefaultDeclaration") {
1374
- if (t__namespace.isExpression(exportNode.declaration)) {
1375
- exportsProps.push(t__namespace.objectProperty(t__namespace.identifier("default"), exportNode.declaration));
1376
- }
1377
- else {
1378
- const decl = exportNode.declaration;
1379
- if (decl.id && decl.id.name) {
1380
- iifeBody.body.push(decl);
1381
- exportsProps.push(t__namespace.objectProperty(t__namespace.identifier("default"), t__namespace.identifier(decl.id.name)));
1382
- }
1383
- else {
1384
- exportsProps.push(t__namespace.objectProperty(t__namespace.identifier("default"), DeclarationToExpression(decl)));
1385
- }
1386
- }
1387
- }
1388
- else {
1389
- const source = exportNode.source;
1390
- const id = generateTempId();
1391
- importDeclarations.push(t__namespace.importDeclaration([t__namespace.importNamespaceSpecifier(t__namespace.identifier(id))], source));
1392
- exportsProps.push(t__namespace.spreadElement(t__namespace.identifier(id)));
1483
+ }
1484
+ return [
1485
+ [...codeBody, t__namespace.returnStatement(t__namespace.objectExpression(expBody))],
1486
+ impBody,
1487
+ ];
1488
+ }
1489
+ async function generateEventConfig(eventTag, ctx, impBody) {
1490
+ const prop = ctx.compiledCode.strLoc.Event.subscribe;
1491
+ const argm = t__namespace.objectExpression([
1492
+ t__namespace.objectProperty(t__namespace.identifier("on"), t__namespace.stringLiteral(ctx.compiledCode.strLoc.Event.on))
1493
+ ]);
1494
+ if (eventTag.arr.tick) {
1495
+ const num = parseFloat(eventTag.arr.tick);
1496
+ if (!Number.isNaN(num))
1497
+ argm.properties.push(t__namespace.objectProperty(t__namespace.identifier("tick"), t__namespace.numericLiteral(num)));
1498
+ }
1499
+ // extract event and hanler
1500
+ const data = [];
1501
+ const extend = [];
1502
+ for (const [name, handlerName] of Object.entries(prop)) {
1503
+ if (name == config.eventExtendsName) {
1504
+ const extendsFile = handlerName.split(",");
1505
+ for (const extFile of extendsFile) {
1506
+ if (!(await McxUtlis.FileExsit(path.join(path.dirname(ctx.currentId), extFile))))
1507
+ throw new Error("[transform event]: can't resolve");
1508
+ const id = generateFileId();
1509
+ impBody.push(t__namespace.importDeclaration([t__namespace.importDefaultSpecifier(t__namespace.identifier(id))], t__namespace.stringLiteral(extFile)));
1510
+ extend.push(t__namespace.identifier(id));
1393
1511
  }
1394
1512
  }
1513
+ data.push(t__namespace.objectProperty(t__namespace.identifier(name), t__namespace.stringLiteral(handlerName)));
1395
1514
  }
1396
- // append return statement returning the exports object
1397
- iifeBody.body.push(t__namespace.returnStatement(t__namespace.objectExpression(exportsProps)));
1398
- // Build function declaration: function __main(ctx) { <original module body> ; return { ... } }
1399
- const funcDecl = t__namespace.functionDeclaration(mainId, [], iifeBody, false, false);
1400
- return [...importDeclarations, funcDecl];
1515
+ argm.properties.push(t__namespace.objectProperty(t__namespace.identifier("data"), t__namespace.objectExpression(data)), t__namespace.objectProperty(t__namespace.identifier("extends"), t__namespace.arrayExpression(extend)));
1516
+ return argm;
1517
+ }
1518
+ /**
1519
+ * record enable
1520
+ * @returns {(): void} - only call one
1521
+ */
1522
+ function _enable() {
1523
+ let success = false;
1524
+ const fn = function () {
1525
+ if (success)
1526
+ throw new Error("[enable]: can't enable again");
1527
+ success = true;
1528
+ fn.prototype.enable = success;
1529
+ };
1530
+ fn.prototype.enable = success;
1531
+ return fn;
1401
1532
  }
1402
- function DeclarationToExpression(node) {
1403
- if (node.type == "ClassDeclaration")
1404
- return t__namespace.classExpression(node.id, node.superClass, node.body, node.decorators);
1405
- if (node.type == "FunctionDeclaration")
1406
- return t__namespace.functionExpression(node.id, node.params, node.body, node.generator, node.async);
1407
- throw new Error("[compile node]: can't to expression: " + node.type);
1533
+ function _enableWithData() {
1534
+ let d = null;
1535
+ const fn = function (data) {
1536
+ if (d)
1537
+ throw new Error("[enable]: can't enable again");
1538
+ d = data;
1539
+ fn.prototype.enable = d;
1540
+ };
1541
+ fn.prototype.enable = d;
1542
+ return fn;
1408
1543
  }
1409
1544
 
1410
- function handlerPath(p, base) {
1411
- const dir = p.split("/");
1412
- if (dir[0] && dir[0] in _MCXstructureLocComponentTypes) {
1413
- return path.join(base, p);
1545
+ async function Comp$2(ctx) {
1546
+ const internalCtx = ctx.ctx;
1547
+ ctx.impBody.push(t__namespace.importDeclaration([t__namespace.importSpecifier(t__namespace.identifier("__mcx_ui"), t__namespace.identifier("ui"))], t__namespace.stringLiteral("@mbler/mcx")), t__namespace.importDeclaration([
1548
+ t__namespace.importNamespaceSpecifier(t__namespace.identifier("__minecraft__ui"))
1549
+ ], t__namespace.stringLiteral("@minecraft/server-ui")));
1550
+ const uiTagNode = ctx.ctx.compiledCode.strLoc.UI;
1551
+ if (!uiTagNode || uiTagNode?.name !== "Ui")
1552
+ throw new Error("[UI Component]: why didn't parent compeled verify?");
1553
+ let MCXUIType = null;
1554
+ const UITree = [];
1555
+ for (const uiClientTag of uiTagNode.content) {
1556
+ if (uiClientTag.type == "TagNode") {
1557
+ // if has client TagNode
1558
+ if (uiClientTag.content.some(i => i.type == "TagNode")) {
1559
+ internalCtx.rollupContext.error("[UI]: can't support ui client element", uiClientTag.loc ? {
1560
+ column: uiClientTag.loc.start.column,
1561
+ line: uiClientTag.loc.start.line
1562
+ } : void 0);
1563
+ }
1564
+ // add to tree
1565
+ UITree.push({
1566
+ arr: uiClientTag.arr,
1567
+ content: uiClientTag.content.map(i => i.type == "TagContent" && i.data || "").join(""),
1568
+ type: uiClientTag.name,
1569
+ loc: uiClientTag.loc
1570
+ });
1571
+ }
1572
+ // continue TagContentNode
1573
+ }
1574
+ const parsedObj = [];
1575
+ function pushToTree(name, params, content) {
1576
+ parsedObj.push(t__namespace.objectExpression([
1577
+ t__namespace.objectProperty(t__namespace.identifier("type"), t__namespace.stringLiteral(name)),
1578
+ t__namespace.objectProperty(t__namespace.identifier("params"), t__namespace.objectExpression(Object.entries(params).map(i => {
1579
+ return t__namespace.objectProperty(t__namespace.identifier(i[0]), typeof i[1] == "boolean" ? t__namespace.booleanLiteral(i[1]) : t__namespace.stringLiteral(i[1]));
1580
+ }))),
1581
+ t__namespace.objectProperty(t__namespace.identifier("content"), (content.startsWith("{{ ") && content.endsWith(" }}")) ? t__namespace.objectExpression([
1582
+ t__namespace.objectProperty(t__namespace.identifier("useProp"), t__namespace.stringLiteral(content.slice(3, content.length - 3).trim()))
1583
+ ]) : t__namespace.stringLiteral(content))
1584
+ ]));
1585
+ }
1586
+ // generate type and parsed tree
1587
+ for (const tp of UITree) {
1588
+ const name = tp.type;
1589
+ // only ModalFormData Element
1590
+ if (["input", "dropdown", "submit", "toggle", "slider"].includes(name)) {
1591
+ // ModalFromData
1592
+ if (MCXUIType && MCXUIType !== "ModalFormData") {
1593
+ internalCtx.rollupContext.error("[UI]: a mcx can't have a ModalFormData Node and other form tag", tp.loc ? {
1594
+ line: tp.loc.start.line,
1595
+ column: tp.loc.start.column
1596
+ } : void 0);
1597
+ }
1598
+ MCXUIType = "ModalFormData";
1599
+ pushToTree(name, tp.arr, tp.content);
1600
+ }
1601
+ // only MessageFormData Element
1602
+ else if (["button-m"].includes(name)) {
1603
+ if (MCXUIType && MCXUIType !== "MessageFormData") {
1604
+ internalCtx.rollupContext.error("[UI]: ", tp.loc ? {
1605
+ line: tp.loc.start.line,
1606
+ column: tp.loc.start.column
1607
+ } : void 0);
1608
+ }
1609
+ MCXUIType = "MessageFormData";
1610
+ pushToTree(name, tp.arr, tp.content);
1611
+ }
1612
+ // public
1613
+ else if (["body", "divider", "title", "label"].includes(name)) {
1614
+ pushToTree(name, tp.arr, tp.content);
1615
+ }
1616
+ else if (name == "button") {
1617
+ if (MCXUIType !== "ActionFromData" && MCXUIType)
1618
+ internalCtx.rollupContext.error("[UI]: don't support use button for messageFormData", tp.loc ? {
1619
+ line: tp.loc.start.line,
1620
+ column: tp.loc.start.column
1621
+ } : void 0);
1622
+ pushToTree(name, tp.arr, tp.content);
1623
+ MCXUIType = "ActionFromData";
1624
+ }
1625
+ else {
1626
+ internalCtx.rollupContext.error("[UI]: don't support tag: " + name, tp.loc ? {
1627
+ line: tp.loc.start.line,
1628
+ column: tp.loc.start.column
1629
+ } : void 0);
1630
+ }
1414
1631
  }
1415
- throw new Error(`[component path]: path '${p}' is unreasonable. because root is not in '${Object.keys(_MCXstructureLocComponentTypes)}'`);
1632
+ if (!MCXUIType)
1633
+ MCXUIType = "ActionFromData";
1634
+ const finallyData = t__namespace.objectExpression([
1635
+ t__namespace.objectProperty(t__namespace.identifier("layout"), t__namespace.arrayExpression(parsedObj)),
1636
+ t__namespace.objectProperty(t__namespace.identifier("use"), t__namespace.memberExpression(t__namespace.identifier("__minecraft__ui"), t__namespace.identifier(MCXUIType))),
1637
+ t__namespace.objectProperty(t__namespace.identifier("_UI"), t__namespace.identifier("__minecraft__ui"))
1638
+ ]);
1639
+ ctx.app([
1640
+ t__namespace.objectProperty(t__namespace.identifier("ui"), t__namespace.newExpression(t__namespace.identifier("__mcx__ui"), [finallyData, t__namespace.identifier(config.scriptCompileFn)]))
1641
+ ]);
1416
1642
  }
1417
- const cache$1 = new Map();
1418
- async function compileComponent(compileData, opt) {
1419
- const component = compileData.strLoc.Component;
1420
- if (cache$1.get(opt)) {
1421
- throw new CompileError("[compile comonent]: can't load two and more component mcx in same project", {
1422
- pos: 1,
1423
- line: 1
1424
- });
1425
- }
1426
- cache$1.set(opt, true);
1427
- const projectDir = path.dirname(opt.ProjectDir);
1428
- for (const jsonKey in component) {
1429
- handlerPath(jsonKey, projectDir);
1430
- component[jsonKey];
1431
- }
1643
+
1644
+ async function Comp$1(ctx) {
1645
+ const appData = [
1646
+ t__namespace.objectProperty(t__namespace.identifier("event"), await generateEventConfig(ctx.ctx.compiledCode.raw.find((node) => node.name === "Event"), ctx.ctx, ctx.impBody)),
1647
+ ];
1648
+ ctx.app(appData);
1432
1649
  }
1433
1650
 
1434
- async function loadEvent(compileData, body, id, context) {
1435
- const event = compileData.strLoc.Event;
1436
- const subscribeBody = [];
1437
- for (const [name, useExport] of Object.entries(event.subscribe)) {
1438
- if (name == config.eventExtendsName) {
1651
+ async function Comp(ctx) {
1652
+ const eventImportIdList = [];
1653
+ for (const impNode of ctx.ctx.compiledCode.JSIR.BuildCache.import) {
1654
+ const source = impNode.source;
1655
+ const parsed = path.parse(source);
1656
+ if (!parsed.root && !parsed.dir.startsWith(".")) {
1439
1657
  continue;
1440
1658
  }
1441
- // store the export name as a string; runtime will call `setup()` to
1442
- // obtain the actual function and bind it to the event.
1443
- subscribeBody.push(t__namespace.objectProperty(t__namespace.identifier(name), t__namespace.stringLiteral(String(useExport))));
1444
- }
1445
- const armg = t__namespace.objectExpression([
1446
- t__namespace.objectProperty(t__namespace.identifier("on"), t__namespace.stringLiteral(event.on)),
1447
- t__namespace.objectProperty(t__namespace.identifier("data"), t__namespace.objectExpression(subscribeBody)),
1448
- ]);
1449
- const node = compileData.raw.find((item) => item.name == "Event");
1450
- if (node && node?.arr) {
1451
- const arr = node.arr;
1452
- if (typeof arr.tick == "string") {
1453
- const num = parseFloat(arr.tick);
1454
- if (!Number.isNaN(num)) {
1455
- armg.properties.push(t__namespace.objectProperty(t__namespace.identifier("tick"), t__namespace.numericLiteral(num)));
1659
+ // path
1660
+ const fPath = path.join(ctx.ctx.currentId, "../", source);
1661
+ try {
1662
+ // read file
1663
+ const code = await fs.readFile(fPath, "utf-8");
1664
+ const compiledCode = compileMCXFn(code);
1665
+ // write cache
1666
+ ctx.ctx.cache.set(fPath, compiledCode);
1667
+ if (compiledCode.strLoc.Event.isLoad) {
1668
+ for (const impItem of impNode.imported) {
1669
+ let type;
1670
+ if (impItem.isAll)
1671
+ type = "all";
1672
+ else if (impItem.import == "default")
1673
+ type = "default";
1674
+ else {
1675
+ throw new Error("not vaild importDeclartion: Event mcx only resolve default and all import, can't use other import");
1676
+ }
1677
+ eventImportIdList.push({
1678
+ type,
1679
+ as: impItem.as
1680
+ });
1681
+ }
1456
1682
  }
1457
1683
  }
1458
- }
1459
- if (event.subscribe[config.eventExtendsName]) {
1460
- const imp = event.subscribe[config.eventExtendsName];
1461
- const extendArr = [];
1462
- if (!imp)
1463
- return;
1464
- for (const pkg of imp.split(",")) {
1465
- const pkgTrim = pkg.trim();
1466
- const pkgDir = path.join(path.dirname(id), pkgTrim);
1467
- let st;
1468
- try {
1469
- st = await fs.stat(pkgDir);
1470
- if (!st.isFile())
1471
- throw new Error("Not File");
1472
- }
1473
- catch (err) {
1474
- context.error(`[event node]: extends ${pkg} error: ${err.message} code: ${err.code} file: ${id}`);
1475
- }
1476
- const impId = generateTempId();
1477
- body.unshift(t__namespace.importDeclaration([t__namespace.importDefaultSpecifier(t__namespace.identifier(impId))], t__namespace.stringLiteral(pkgTrim)));
1478
- extendArr.push(t__namespace.identifier(impId));
1684
+ catch (err) {
1685
+ // if error: file not found, file can't write, mcx syntax error
1686
+ ctx.ctx.rollupContext.warn(`[extract import]: can't resolve file ${fPath} and import by ${ctx.ctx.currentId}\n- err: ${(err instanceof Error) ? err.stack : err}`);
1479
1687
  }
1480
- armg.properties.push(t__namespace.objectProperty(t__namespace.identifier("extends"), t__namespace.arrayExpression(extendArr)));
1481
1688
  }
1482
- // produce a plain config object (do NOT instantiate Event here)
1483
- body.push(t__namespace.variableDeclaration("const", [
1484
- t__namespace.variableDeclarator(t__namespace.identifier(config.eventVarName), armg),
1485
- ]));
1486
- }
1487
- async function transform(compileData, cache, id, context, opt) {
1488
- // first compile script
1489
- const statement = generateMain(compileData.JSIR);
1490
- let mcxtype = null;
1491
- // detect imported mcx modules that are events by checking cache or compiling
1492
- const eventImportIds = [];
1493
- // build default export object: { type: <mcxtype>, setup: __main, ...(event?) }
1494
- // event MCX
1495
- if (compileData.strLoc.Event.isLoad) {
1496
- // mark as event MCX. Do NOT instantiate Event at compile-time — instead
1497
- // produce a plain config object referencing exported names (strings).
1498
- mcxtype = "event";
1499
- await loadEvent(compileData, statement, id, context);
1500
- }
1501
- // component MCX
1502
- if (Object.keys(compileData.strLoc.Component).length >= 1) {
1503
- if (mcxtype == "event")
1504
- throw new Error("[compile component]: a mcx must event or component, can't both");
1505
- // leave placeholder for component compilation
1506
- await compileComponent(compileData, opt);
1507
- // export a MCXFile-like default for components
1508
- const defObj = t__namespace.objectExpression([
1509
- t__namespace.objectProperty(t__namespace.identifier("type"), t__namespace.stringLiteral("component")),
1510
- t__namespace.objectProperty(t__namespace.identifier("setup"), t__namespace.identifier(config.scriptCompileFn)),
1511
- ]);
1512
- statement.push(t__namespace.exportDefaultDeclaration(defObj));
1513
- return generator__namespace.generate(t__namespace.program(statement)).code;
1514
- }
1515
- // app (default) MCX
1516
- if (!mcxtype) {
1517
- mcxtype = "app";
1518
- for (const imp of compileData.JSIR.BuildCache.import || []) {
1519
- if (path.parse(imp.source).dir == "")
1520
- continue;
1521
- const source = path.join(path.dirname(id), imp.source);
1522
- if (!source.endsWith(".mcx"))
1523
- continue;
1524
- // generate code;
1525
- let moduleData;
1526
- if (cache.has(source)) {
1527
- moduleData = cache.get(source);
1528
- }
1529
- else {
1530
- let code;
1531
- try {
1532
- code = await fs.readFile(source, "utf-8");
1689
+ // only have event import
1690
+ if (eventImportIdList.length >= 1) {
1691
+ const eventMemberNode = t__namespace.memberExpression(t__namespace.identifier(config.paramCtx), t__namespace.identifier("event"));
1692
+ ctx.mainFn.unshift(
1693
+ // add declaration
1694
+ t__namespace.variableDeclaration("var", eventImportIdList.map((item, index) => {
1695
+ if (item.type == "all") {
1696
+ return t__namespace.variableDeclarator(t__namespace.identifier(item.as), t__namespace.objectExpression([
1697
+ t__namespace.objectProperty(t__namespace.identifier("default"), t__namespace.memberExpression(eventMemberNode, t__namespace.numericLiteral(index), true)),
1698
+ ]));
1699
+ }
1700
+ else if (item.type == "default") {
1701
+ return t__namespace.variableDeclarator(t__namespace.identifier(item.as), t__namespace.memberExpression(eventMemberNode, t__namespace.numericLiteral(index), true));
1702
+ }
1703
+ // ts galgame
1704
+ throw new Error("[javascript error]: why it not in [default, all]");
1705
+ })));
1706
+ // app: add event export to runtime framework
1707
+ const appData = [
1708
+ t__namespace.objectProperty(t__namespace.identifier("event"), t__namespace.arrayExpression(eventImportIdList.map(vl => {
1709
+ if (vl.type == "all") {
1710
+ return t__namespace.memberExpression(t__namespace.identifier(vl.as), t__namespace.identifier("default"));
1533
1711
  }
1534
- catch (err) {
1535
- context.warn("import '" + source + "' not exsit");
1536
- continue;
1712
+ else if (vl.type == "default") {
1713
+ return t__namespace.identifier(vl.as);
1537
1714
  }
1538
- moduleData = compileMCXFn(code);
1539
- cache.set(source, moduleData);
1540
- }
1541
- if (!moduleData.strLoc.Event.isLoad)
1542
- continue;
1543
- for (const item of imp.imported) {
1544
- const base = t__namespace.identifier(item.as);
1545
- if (item.isAll)
1546
- eventImportIds.push(t__namespace.memberExpression(base, t__namespace.identifier("default")));
1547
- else if (item.import == "default")
1548
- eventImportIds.push(base, t__namespace.identifier("event"));
1549
- }
1550
- }
1551
- }
1552
- // Default export properties. `setup` references the compiled script wrapper
1553
- // function (callable as `setup(ctx)`) which returns the exported bindings
1554
- // object (e.g. `{ default: Handler }`). Event handler references in the
1555
- // compiled event config are string names that the runtime will resolve by
1556
- // calling `setup()` and looking up the named export.
1557
- const props = [
1558
- t__namespace.objectProperty(t__namespace.identifier("type"), t__namespace.stringLiteral(mcxtype)),
1559
- t__namespace.objectProperty(t__namespace.identifier("setup"), t__namespace.identifier(config.scriptCompileFn)),
1560
- ];
1561
- // if this app imports an event mcx, attach it under `event` property
1562
- if (mcxtype === "app" && eventImportIds.length > 0) {
1563
- // prefer first discovered event import id
1564
- if (eventImportIds.length > 1) {
1565
- context.warn(`multiple event MCX imports detected in ${id}. Only the first will be attached to the app export.`);
1566
- }
1567
- props.push(t__namespace.objectProperty(t__namespace.identifier("app"), t__namespace.objectExpression([
1568
- t__namespace.objectProperty(t__namespace.identifier("event"), eventImportIds[0]),
1569
- ])));
1570
- for (const statIndex in statement) {
1571
- const stat = statement[statIndex];
1572
- if (!stat)
1573
- continue;
1574
- console.log(stat);
1575
- if (stat.type == "FunctionDeclaration" && stat.id && stat.id.name == config.scriptCompileFn) {
1576
- console.log("into");
1577
- stat.params[0] =
1578
- eventImportIds[0] && eventImportIds[0].type == "Identifier"
1579
- ? eventImportIds[0]
1580
- : eventImportIds[0]?.object;
1581
- }
1582
- }
1583
- }
1584
- // if this is an event mcx we still need to provide named export 'event'
1585
- if (mcxtype === "event") {
1586
- // ensure default export still includes type and setup
1587
- props.push(t__namespace.objectProperty(t__namespace.identifier("event"), t__namespace.identifier(config.eventVarName)));
1588
- const defObj = t__namespace.objectExpression(props);
1589
- statement.push(t__namespace.exportDefaultDeclaration(defObj));
1590
- return generator__namespace.generate(t__namespace.program(statement)).code;
1591
- }
1592
- // normal app default export
1593
- const defObj = t__namespace.objectExpression(props);
1594
- statement.push(t__namespace.exportDefaultDeclaration(defObj));
1595
- return generator__namespace.generate(t__namespace.program(statement)).code;
1596
- }
1597
-
1598
- // src/vlq.ts
1599
- var comma = ",".charCodeAt(0);
1600
- var semicolon = ";".charCodeAt(0);
1601
- var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1602
- var intToChar = new Uint8Array(64);
1603
- var charToInt = new Uint8Array(128);
1604
- for (let i = 0; i < chars.length; i++) {
1605
- const c = chars.charCodeAt(i);
1606
- intToChar[i] = c;
1607
- charToInt[c] = i;
1608
- }
1609
- function encodeInteger(builder, num, relative) {
1610
- let delta = num - relative;
1611
- delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
1612
- do {
1613
- let clamped = delta & 31;
1614
- delta >>>= 5;
1615
- if (delta > 0) clamped |= 32;
1616
- builder.write(intToChar[clamped]);
1617
- } while (delta > 0);
1618
- return num;
1619
- }
1620
-
1621
- // src/strings.ts
1622
- var bufLength = 1024 * 16;
1623
- var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? {
1624
- decode(buf) {
1625
- const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
1626
- return out.toString();
1627
- }
1628
- } : {
1629
- decode(buf) {
1630
- let out = "";
1631
- for (let i = 0; i < buf.length; i++) {
1632
- out += String.fromCharCode(buf[i]);
1633
- }
1634
- return out;
1635
- }
1636
- };
1637
- var StringWriter = class {
1638
- constructor() {
1639
- this.pos = 0;
1640
- this.out = "";
1641
- this.buffer = new Uint8Array(bufLength);
1642
- }
1643
- write(v) {
1644
- const { buffer } = this;
1645
- buffer[this.pos++] = v;
1646
- if (this.pos === bufLength) {
1647
- this.out += td.decode(buffer);
1648
- this.pos = 0;
1649
- }
1650
- }
1651
- flush() {
1652
- const { buffer, out, pos } = this;
1653
- return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
1654
- }
1655
- };
1656
- function encode(decoded) {
1657
- const writer = new StringWriter();
1658
- let sourcesIndex = 0;
1659
- let sourceLine = 0;
1660
- let sourceColumn = 0;
1661
- let namesIndex = 0;
1662
- for (let i = 0; i < decoded.length; i++) {
1663
- const line = decoded[i];
1664
- if (i > 0) writer.write(semicolon);
1665
- if (line.length === 0) continue;
1666
- let genColumn = 0;
1667
- for (let j = 0; j < line.length; j++) {
1668
- const segment = line[j];
1669
- if (j > 0) writer.write(comma);
1670
- genColumn = encodeInteger(writer, segment[0], genColumn);
1671
- if (segment.length === 1) continue;
1672
- sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
1673
- sourceLine = encodeInteger(writer, segment[2], sourceLine);
1674
- sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
1675
- if (segment.length === 4) continue;
1676
- namesIndex = encodeInteger(writer, segment[4], namesIndex);
1677
- }
1678
- }
1679
- return writer.flush();
1680
- }
1681
-
1682
- class BitSet {
1683
- constructor(arg) {
1684
- this.bits = arg instanceof BitSet ? arg.bits.slice() : [];
1685
- }
1686
-
1687
- add(n) {
1688
- this.bits[n >> 5] |= 1 << (n & 31);
1689
- }
1690
-
1691
- has(n) {
1692
- return !!(this.bits[n >> 5] & (1 << (n & 31)));
1693
- }
1694
- }
1695
-
1696
- class Chunk {
1697
- constructor(start, end, content) {
1698
- this.start = start;
1699
- this.end = end;
1700
- this.original = content;
1701
-
1702
- this.intro = '';
1703
- this.outro = '';
1704
-
1705
- this.content = content;
1706
- this.storeName = false;
1707
- this.edited = false;
1708
-
1709
- {
1710
- this.previous = null;
1711
- this.next = null;
1712
- }
1713
- }
1714
-
1715
- appendLeft(content) {
1716
- this.outro += content;
1717
- }
1718
-
1719
- appendRight(content) {
1720
- this.intro = this.intro + content;
1721
- }
1722
-
1723
- clone() {
1724
- const chunk = new Chunk(this.start, this.end, this.original);
1725
-
1726
- chunk.intro = this.intro;
1727
- chunk.outro = this.outro;
1728
- chunk.content = this.content;
1729
- chunk.storeName = this.storeName;
1730
- chunk.edited = this.edited;
1731
-
1732
- return chunk;
1733
- }
1734
-
1735
- contains(index) {
1736
- return this.start < index && index < this.end;
1737
- }
1738
-
1739
- eachNext(fn) {
1740
- let chunk = this;
1741
- while (chunk) {
1742
- fn(chunk);
1743
- chunk = chunk.next;
1744
- }
1745
- }
1746
-
1747
- eachPrevious(fn) {
1748
- let chunk = this;
1749
- while (chunk) {
1750
- fn(chunk);
1751
- chunk = chunk.previous;
1752
- }
1753
- }
1754
-
1755
- edit(content, storeName, contentOnly) {
1756
- this.content = content;
1757
- if (!contentOnly) {
1758
- this.intro = '';
1759
- this.outro = '';
1760
- }
1761
- this.storeName = storeName;
1762
-
1763
- this.edited = true;
1764
-
1765
- return this;
1766
- }
1767
-
1768
- prependLeft(content) {
1769
- this.outro = content + this.outro;
1770
- }
1771
-
1772
- prependRight(content) {
1773
- this.intro = content + this.intro;
1774
- }
1775
-
1776
- reset() {
1777
- this.intro = '';
1778
- this.outro = '';
1779
- if (this.edited) {
1780
- this.content = this.original;
1781
- this.storeName = false;
1782
- this.edited = false;
1783
- }
1784
- }
1785
-
1786
- split(index) {
1787
- const sliceIndex = index - this.start;
1788
-
1789
- const originalBefore = this.original.slice(0, sliceIndex);
1790
- const originalAfter = this.original.slice(sliceIndex);
1791
-
1792
- this.original = originalBefore;
1793
-
1794
- const newChunk = new Chunk(index, this.end, originalAfter);
1795
- newChunk.outro = this.outro;
1796
- this.outro = '';
1797
-
1798
- this.end = index;
1799
-
1800
- if (this.edited) {
1801
- // after split we should save the edit content record into the correct chunk
1802
- // to make sure sourcemap correct
1803
- // For example:
1804
- // ' test'.trim()
1805
- // split -> ' ' + 'test'
1806
- // ✔️ edit -> '' + 'test'
1807
- // ✖️ edit -> 'test' + ''
1808
- // TODO is this block necessary?...
1809
- newChunk.edit('', false);
1810
- this.content = '';
1811
- } else {
1812
- this.content = originalBefore;
1813
- }
1814
-
1815
- newChunk.next = this.next;
1816
- if (newChunk.next) newChunk.next.previous = newChunk;
1817
- newChunk.previous = this;
1818
- this.next = newChunk;
1819
-
1820
- return newChunk;
1821
- }
1822
-
1823
- toString() {
1824
- return this.intro + this.content + this.outro;
1825
- }
1826
-
1827
- trimEnd(rx) {
1828
- this.outro = this.outro.replace(rx, '');
1829
- if (this.outro.length) return true;
1830
-
1831
- const trimmed = this.content.replace(rx, '');
1832
-
1833
- if (trimmed.length) {
1834
- if (trimmed !== this.content) {
1835
- this.split(this.start + trimmed.length).edit('', undefined, true);
1836
- if (this.edited) {
1837
- // save the change, if it has been edited
1838
- this.edit(trimmed, this.storeName, true);
1839
- }
1840
- }
1841
- return true;
1842
- } else {
1843
- this.edit('', undefined, true);
1844
-
1845
- this.intro = this.intro.replace(rx, '');
1846
- if (this.intro.length) return true;
1847
- }
1848
- }
1849
-
1850
- trimStart(rx) {
1851
- this.intro = this.intro.replace(rx, '');
1852
- if (this.intro.length) return true;
1853
-
1854
- const trimmed = this.content.replace(rx, '');
1855
-
1856
- if (trimmed.length) {
1857
- if (trimmed !== this.content) {
1858
- const newChunk = this.split(this.end - trimmed.length);
1859
- if (this.edited) {
1860
- // save the change, if it has been edited
1861
- newChunk.edit(trimmed, this.storeName, true);
1862
- }
1863
- this.edit('', undefined, true);
1864
- }
1865
- return true;
1866
- } else {
1867
- this.edit('', undefined, true);
1868
-
1869
- this.outro = this.outro.replace(rx, '');
1870
- if (this.outro.length) return true;
1871
- }
1872
- }
1873
- }
1874
-
1875
- function getBtoa() {
1876
- if (typeof globalThis !== 'undefined' && typeof globalThis.btoa === 'function') {
1877
- return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));
1878
- } else if (typeof Buffer === 'function') {
1879
- return (str) => Buffer.from(str, 'utf-8').toString('base64');
1880
- } else {
1881
- return () => {
1882
- throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
1883
- };
1884
- }
1885
- }
1886
-
1887
- const btoa = /*#__PURE__*/ getBtoa();
1888
-
1889
- class SourceMap {
1890
- constructor(properties) {
1891
- this.version = 3;
1892
- this.file = properties.file;
1893
- this.sources = properties.sources;
1894
- this.sourcesContent = properties.sourcesContent;
1895
- this.names = properties.names;
1896
- this.mappings = encode(properties.mappings);
1897
- if (typeof properties.x_google_ignoreList !== 'undefined') {
1898
- this.x_google_ignoreList = properties.x_google_ignoreList;
1899
- }
1900
- if (typeof properties.debugId !== 'undefined') {
1901
- this.debugId = properties.debugId;
1902
- }
1903
- }
1904
-
1905
- toString() {
1906
- return JSON.stringify(this);
1907
- }
1908
-
1909
- toUrl() {
1910
- return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());
1911
- }
1912
- }
1913
-
1914
- function guessIndent(code) {
1915
- const lines = code.split('\n');
1916
-
1917
- const tabbed = lines.filter((line) => /^\t+/.test(line));
1918
- const spaced = lines.filter((line) => /^ {2,}/.test(line));
1919
-
1920
- if (tabbed.length === 0 && spaced.length === 0) {
1921
- return null;
1922
- }
1923
-
1924
- // More lines tabbed than spaced? Assume tabs, and
1925
- // default to tabs in the case of a tie (or nothing
1926
- // to go on)
1927
- if (tabbed.length >= spaced.length) {
1928
- return '\t';
1929
- }
1930
-
1931
- // Otherwise, we need to guess the multiple
1932
- const min = spaced.reduce((previous, current) => {
1933
- const numSpaces = /^ +/.exec(current)[0].length;
1934
- return Math.min(numSpaces, previous);
1935
- }, Infinity);
1936
-
1937
- return new Array(min + 1).join(' ');
1938
- }
1939
-
1940
- function getRelativePath(from, to) {
1941
- const fromParts = from.split(/[/\\]/);
1942
- const toParts = to.split(/[/\\]/);
1943
-
1944
- fromParts.pop(); // get dirname
1945
-
1946
- while (fromParts[0] === toParts[0]) {
1947
- fromParts.shift();
1948
- toParts.shift();
1949
- }
1950
-
1951
- if (fromParts.length) {
1952
- let i = fromParts.length;
1953
- while (i--) fromParts[i] = '..';
1954
- }
1955
-
1956
- return fromParts.concat(toParts).join('/');
1957
- }
1958
-
1959
- const toString = Object.prototype.toString;
1960
-
1961
- function isObject(thing) {
1962
- return toString.call(thing) === '[object Object]';
1715
+ throw new Error("[add prop]: can't format eventImportList");
1716
+ })))
1717
+ ];
1718
+ ctx.app(appData);
1719
+ }
1963
1720
  }
1964
1721
 
1965
- function getLocator(source) {
1966
- const originalLines = source.split('\n');
1967
- const lineOffsets = [];
1968
-
1969
- for (let i = 0, pos = 0; i < originalLines.length; i++) {
1970
- lineOffsets.push(pos);
1971
- pos += originalLines[i].length + 1;
1972
- }
1973
-
1974
- return function locate(index) {
1975
- let i = 0;
1976
- let j = lineOffsets.length;
1977
- while (i < j) {
1978
- const m = (i + j) >> 1;
1979
- if (index < lineOffsets[m]) {
1980
- j = m;
1981
- } else {
1982
- i = m + 1;
1983
- }
1984
- }
1985
- const line = i - 1;
1986
- const column = index - lineOffsets[line];
1987
- return { line, column };
1988
- };
1722
+ async function compileComponent(compiledCode, project) {
1723
+ const component = compiledCode.strLoc.Component;
1724
+ for (const i of Object.entries(component)) {
1725
+ // TODO: compele compile component
1726
+ }
1989
1727
  }
1990
1728
 
1991
- const wordRegex = /\w/;
1992
-
1993
- class Mappings {
1994
- constructor(hires) {
1995
- this.hires = hires;
1996
- this.generatedCodeLine = 0;
1997
- this.generatedCodeColumn = 0;
1998
- this.raw = [];
1999
- this.rawSegments = this.raw[this.generatedCodeLine] = [];
2000
- this.pending = null;
2001
- }
2002
-
2003
- addEdit(sourceIndex, content, loc, nameIndex) {
2004
- if (content.length) {
2005
- const contentLengthMinusOne = content.length - 1;
2006
- let contentLineEnd = content.indexOf('\n', 0);
2007
- let previousContentLineEnd = -1;
2008
- // Loop through each line in the content and add a segment, but stop if the last line is empty,
2009
- // else code afterwards would fill one line too many
2010
- while (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {
2011
- const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
2012
- if (nameIndex >= 0) {
2013
- segment.push(nameIndex);
2014
- }
2015
- this.rawSegments.push(segment);
2016
-
2017
- this.generatedCodeLine += 1;
2018
- this.raw[this.generatedCodeLine] = this.rawSegments = [];
2019
- this.generatedCodeColumn = 0;
2020
-
2021
- previousContentLineEnd = contentLineEnd;
2022
- contentLineEnd = content.indexOf('\n', contentLineEnd + 1);
2023
- }
2024
-
2025
- const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
2026
- if (nameIndex >= 0) {
2027
- segment.push(nameIndex);
2028
- }
2029
- this.rawSegments.push(segment);
2030
-
2031
- this.advance(content.slice(previousContentLineEnd + 1));
2032
- } else if (this.pending) {
2033
- this.rawSegments.push(this.pending);
2034
- this.advance(content);
2035
- }
2036
-
2037
- this.pending = null;
2038
- }
2039
-
2040
- addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {
2041
- let originalCharIndex = chunk.start;
2042
- let first = true;
2043
- // when iterating each char, check if it's in a word boundary
2044
- let charInHiresBoundary = false;
2045
-
2046
- while (originalCharIndex < chunk.end) {
2047
- if (original[originalCharIndex] === '\n') {
2048
- loc.line += 1;
2049
- loc.column = 0;
2050
- this.generatedCodeLine += 1;
2051
- this.raw[this.generatedCodeLine] = this.rawSegments = [];
2052
- this.generatedCodeColumn = 0;
2053
- first = true;
2054
- charInHiresBoundary = false;
2055
- } else {
2056
- if (this.hires || first || sourcemapLocations.has(originalCharIndex)) {
2057
- const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
2058
-
2059
- if (this.hires === 'boundary') {
2060
- // in hires "boundary", group segments per word boundary than per char
2061
- if (wordRegex.test(original[originalCharIndex])) {
2062
- // for first char in the boundary found, start the boundary by pushing a segment
2063
- if (!charInHiresBoundary) {
2064
- this.rawSegments.push(segment);
2065
- charInHiresBoundary = true;
2066
- }
2067
- } else {
2068
- // for non-word char, end the boundary by pushing a segment
2069
- this.rawSegments.push(segment);
2070
- charInHiresBoundary = false;
2071
- }
2072
- } else {
2073
- this.rawSegments.push(segment);
2074
- }
2075
- }
2076
-
2077
- loc.column += 1;
2078
- this.generatedCodeColumn += 1;
2079
- first = false;
2080
- }
2081
-
2082
- originalCharIndex += 1;
2083
- }
2084
-
2085
- this.pending = null;
2086
- }
2087
-
2088
- advance(str) {
2089
- if (!str) return;
2090
-
2091
- const lines = str.split('\n');
2092
-
2093
- if (lines.length > 1) {
2094
- for (let i = 0; i < lines.length - 1; i++) {
2095
- this.generatedCodeLine++;
2096
- this.raw[this.generatedCodeLine] = this.rawSegments = [];
2097
- }
2098
- this.generatedCodeColumn = 0;
2099
- }
1729
+ var index$1 = /*#__PURE__*/Object.freeze({
1730
+ __proto__: null,
1731
+ compileComponent: compileComponent
1732
+ });
2100
1733
 
2101
- this.generatedCodeColumn += lines[lines.length - 1].length;
2102
- }
1734
+ async function _transform(ctx) {
1735
+ const _temp_main = generateMain(ctx.compiledCode.JSIR);
1736
+ const mainFn = ctx.mainFn.body = _temp_main[0];
1737
+ const prop = [];
1738
+ const app = _enableWithData();
1739
+ const params = ctx.mainFn.param = [
1740
+ t__namespace.identifier(config.paramCtx)
1741
+ ];
1742
+ const parseCtx = {
1743
+ impBody: _temp_main[1],
1744
+ mainFn,
1745
+ prop,
1746
+ ctx: ctx,
1747
+ app
1748
+ };
1749
+ let type = "app";
1750
+ // enable setup fn: use to generate setup
1751
+ const enableSetup = _enable();
1752
+ if (ctx.compiledCode.strLoc.Event.isLoad) {
1753
+ // handler event type mcx
1754
+ type = "event";
1755
+ // enable export setup
1756
+ enableSetup();
1757
+ await Comp$1(parseCtx);
1758
+ }
1759
+ if (ctx.compiledCode.strLoc.UI) {
1760
+ /**
1761
+ * Completed UI handler
1762
+ * @todo - handler
1763
+ */
1764
+ type = "ui"; // ui mcx
1765
+ enableSetup();
1766
+ await Comp$2(parseCtx);
1767
+ }
1768
+ if (Object.getOwnPropertyNames(ctx.compiledCode.strLoc.Component).length >= 1) {
1769
+ type = "component";
1770
+ await compileComponent(ctx.compiledCode, ctx.opt.ProjectDir);
1771
+ return `export default {type:'component',setup:null,app:{}}`;
1772
+ }
1773
+ if (type == "app") {
1774
+ // enable setup export
1775
+ enableSetup();
1776
+ // find event mcx import
1777
+ await Comp(parseCtx);
1778
+ }
1779
+ // add default export: type
1780
+ prop.push(t__namespace.objectProperty(t__namespace.identifier("type"), t__namespace.stringLiteral(type)));
1781
+ if (enableSetup.prototype.enable) {
1782
+ prop.push(t__namespace.objectProperty(t__namespace.identifier("setup"), t__namespace.identifier(config.scriptCompileFn)));
1783
+ }
1784
+ if (app.prototype.enable) {
1785
+ prop.push(t__namespace.objectProperty(t__namespace.identifier("app"), t__namespace.objectExpression(app.prototype.enable)));
1786
+ }
1787
+ // generate code
1788
+ const code = generator.generate(
1789
+ // create program
1790
+ (t__namespace.program([
1791
+ ...parseCtx.impBody,
1792
+ t__namespace.functionDeclaration(t__namespace.identifier(config.scriptCompileFn), params, t__namespace.blockStatement(mainFn), false, false),
1793
+ t__namespace.exportDefaultDeclaration(t__namespace.objectExpression(prop)),
1794
+ ]))).code;
1795
+ return code;
2103
1796
  }
2104
1797
 
2105
- const n = '\n';
2106
-
2107
- const warned = {
2108
- insertLeft: false,
2109
- insertRight: false,
2110
- storeName: false,
2111
- };
2112
-
2113
- class MagicString {
2114
- constructor(string, options = {}) {
2115
- const chunk = new Chunk(0, string.length, string);
2116
-
2117
- Object.defineProperties(this, {
2118
- original: { writable: true, value: string },
2119
- outro: { writable: true, value: '' },
2120
- intro: { writable: true, value: '' },
2121
- firstChunk: { writable: true, value: chunk },
2122
- lastChunk: { writable: true, value: chunk },
2123
- lastSearchedChunk: { writable: true, value: chunk },
2124
- byStart: { writable: true, value: {} },
2125
- byEnd: { writable: true, value: {} },
2126
- filename: { writable: true, value: options.filename },
2127
- indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
2128
- sourcemapLocations: { writable: true, value: new BitSet() },
2129
- storedNames: { writable: true, value: {} },
2130
- indentStr: { writable: true, value: undefined },
2131
- ignoreList: { writable: true, value: options.ignoreList },
2132
- offset: { writable: true, value: options.offset || 0 },
2133
- });
2134
-
2135
- this.byStart[0] = chunk;
2136
- this.byEnd[string.length] = chunk;
2137
- }
2138
-
2139
- addSourcemapLocation(char) {
2140
- this.sourcemapLocations.add(char);
2141
- }
2142
-
2143
- append(content) {
2144
- if (typeof content !== 'string') throw new TypeError('outro content must be a string');
2145
-
2146
- this.outro += content;
2147
- return this;
2148
- }
2149
-
2150
- appendLeft(index, content) {
2151
- index = index + this.offset;
2152
-
2153
- if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
2154
-
2155
- this._split(index);
2156
-
2157
- const chunk = this.byEnd[index];
2158
-
2159
- if (chunk) {
2160
- chunk.appendLeft(content);
2161
- } else {
2162
- this.intro += content;
2163
- }
2164
- return this;
2165
- }
2166
-
2167
- appendRight(index, content) {
2168
- index = index + this.offset;
2169
-
2170
- if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
2171
-
2172
- this._split(index);
2173
-
2174
- const chunk = this.byStart[index];
2175
-
2176
- if (chunk) {
2177
- chunk.appendRight(content);
2178
- } else {
2179
- this.outro += content;
2180
- }
2181
- return this;
2182
- }
2183
-
2184
- clone() {
2185
- const cloned = new MagicString(this.original, { filename: this.filename, offset: this.offset });
2186
-
2187
- let originalChunk = this.firstChunk;
2188
- let clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
2189
-
2190
- while (originalChunk) {
2191
- cloned.byStart[clonedChunk.start] = clonedChunk;
2192
- cloned.byEnd[clonedChunk.end] = clonedChunk;
2193
-
2194
- const nextOriginalChunk = originalChunk.next;
2195
- const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
2196
-
2197
- if (nextClonedChunk) {
2198
- clonedChunk.next = nextClonedChunk;
2199
- nextClonedChunk.previous = clonedChunk;
2200
-
2201
- clonedChunk = nextClonedChunk;
2202
- }
2203
-
2204
- originalChunk = nextOriginalChunk;
2205
- }
2206
-
2207
- cloned.lastChunk = clonedChunk;
2208
-
2209
- if (this.indentExclusionRanges) {
2210
- cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
2211
- }
2212
-
2213
- cloned.sourcemapLocations = new BitSet(this.sourcemapLocations);
2214
-
2215
- cloned.intro = this.intro;
2216
- cloned.outro = this.outro;
2217
-
2218
- return cloned;
2219
- }
2220
-
2221
- generateDecodedMap(options) {
2222
- options = options || {};
2223
-
2224
- const sourceIndex = 0;
2225
- const names = Object.keys(this.storedNames);
2226
- const mappings = new Mappings(options.hires);
2227
-
2228
- const locate = getLocator(this.original);
2229
-
2230
- if (this.intro) {
2231
- mappings.advance(this.intro);
2232
- }
2233
-
2234
- this.firstChunk.eachNext((chunk) => {
2235
- const loc = locate(chunk.start);
2236
-
2237
- if (chunk.intro.length) mappings.advance(chunk.intro);
2238
-
2239
- if (chunk.edited) {
2240
- mappings.addEdit(
2241
- sourceIndex,
2242
- chunk.content,
2243
- loc,
2244
- chunk.storeName ? names.indexOf(chunk.original) : -1,
2245
- );
2246
- } else {
2247
- mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);
2248
- }
2249
-
2250
- if (chunk.outro.length) mappings.advance(chunk.outro);
2251
- });
2252
-
2253
- if (this.outro) {
2254
- mappings.advance(this.outro);
2255
- }
2256
-
2257
- return {
2258
- file: options.file ? options.file.split(/[/\\]/).pop() : undefined,
2259
- sources: [
2260
- options.source ? getRelativePath(options.file || '', options.source) : options.file || '',
2261
- ],
2262
- sourcesContent: options.includeContent ? [this.original] : undefined,
2263
- names,
2264
- mappings: mappings.raw,
2265
- x_google_ignoreList: this.ignoreList ? [sourceIndex] : undefined,
2266
- };
2267
- }
2268
-
2269
- generateMap(options) {
2270
- return new SourceMap(this.generateDecodedMap(options));
2271
- }
2272
-
2273
- _ensureindentStr() {
2274
- if (this.indentStr === undefined) {
2275
- this.indentStr = guessIndent(this.original);
2276
- }
2277
- }
2278
-
2279
- _getRawIndentString() {
2280
- this._ensureindentStr();
2281
- return this.indentStr;
2282
- }
2283
-
2284
- getIndentString() {
2285
- this._ensureindentStr();
2286
- return this.indentStr === null ? '\t' : this.indentStr;
2287
- }
2288
-
2289
- indent(indentStr, options) {
2290
- const pattern = /^[^\r\n]/gm;
2291
-
2292
- if (isObject(indentStr)) {
2293
- options = indentStr;
2294
- indentStr = undefined;
2295
- }
2296
-
2297
- if (indentStr === undefined) {
2298
- this._ensureindentStr();
2299
- indentStr = this.indentStr || '\t';
2300
- }
2301
-
2302
- if (indentStr === '') return this; // noop
2303
-
2304
- options = options || {};
2305
-
2306
- // Process exclusion ranges
2307
- const isExcluded = {};
2308
-
2309
- if (options.exclude) {
2310
- const exclusions =
2311
- typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
2312
- exclusions.forEach((exclusion) => {
2313
- for (let i = exclusion[0]; i < exclusion[1]; i += 1) {
2314
- isExcluded[i] = true;
2315
- }
2316
- });
2317
- }
2318
-
2319
- let shouldIndentNextCharacter = options.indentStart !== false;
2320
- const replacer = (match) => {
2321
- if (shouldIndentNextCharacter) return `${indentStr}${match}`;
2322
- shouldIndentNextCharacter = true;
2323
- return match;
2324
- };
2325
-
2326
- this.intro = this.intro.replace(pattern, replacer);
2327
-
2328
- let charIndex = 0;
2329
- let chunk = this.firstChunk;
2330
-
2331
- while (chunk) {
2332
- const end = chunk.end;
2333
-
2334
- if (chunk.edited) {
2335
- if (!isExcluded[charIndex]) {
2336
- chunk.content = chunk.content.replace(pattern, replacer);
2337
-
2338
- if (chunk.content.length) {
2339
- shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
2340
- }
2341
- }
2342
- } else {
2343
- charIndex = chunk.start;
2344
-
2345
- while (charIndex < end) {
2346
- if (!isExcluded[charIndex]) {
2347
- const char = this.original[charIndex];
2348
-
2349
- if (char === '\n') {
2350
- shouldIndentNextCharacter = true;
2351
- } else if (char !== '\r' && shouldIndentNextCharacter) {
2352
- shouldIndentNextCharacter = false;
2353
-
2354
- if (charIndex === chunk.start) {
2355
- chunk.prependRight(indentStr);
2356
- } else {
2357
- this._splitChunk(chunk, charIndex);
2358
- chunk = chunk.next;
2359
- chunk.prependRight(indentStr);
2360
- }
2361
- }
2362
- }
2363
-
2364
- charIndex += 1;
2365
- }
2366
- }
2367
-
2368
- charIndex = chunk.end;
2369
- chunk = chunk.next;
2370
- }
2371
-
2372
- this.outro = this.outro.replace(pattern, replacer);
2373
-
2374
- return this;
2375
- }
2376
-
2377
- insert() {
2378
- throw new Error(
2379
- 'magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)',
2380
- );
2381
- }
2382
-
2383
- insertLeft(index, content) {
2384
- if (!warned.insertLeft) {
2385
- console.warn(
2386
- 'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead',
2387
- );
2388
- warned.insertLeft = true;
2389
- }
2390
-
2391
- return this.appendLeft(index, content);
2392
- }
2393
-
2394
- insertRight(index, content) {
2395
- if (!warned.insertRight) {
2396
- console.warn(
2397
- 'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead',
2398
- );
2399
- warned.insertRight = true;
2400
- }
2401
-
2402
- return this.prependRight(index, content);
2403
- }
2404
-
2405
- move(start, end, index) {
2406
- start = start + this.offset;
2407
- end = end + this.offset;
2408
- index = index + this.offset;
2409
-
2410
- if (index >= start && index <= end) throw new Error('Cannot move a selection inside itself');
2411
-
2412
- this._split(start);
2413
- this._split(end);
2414
- this._split(index);
2415
-
2416
- const first = this.byStart[start];
2417
- const last = this.byEnd[end];
2418
-
2419
- const oldLeft = first.previous;
2420
- const oldRight = last.next;
2421
-
2422
- const newRight = this.byStart[index];
2423
- if (!newRight && last === this.lastChunk) return this;
2424
- const newLeft = newRight ? newRight.previous : this.lastChunk;
2425
-
2426
- if (oldLeft) oldLeft.next = oldRight;
2427
- if (oldRight) oldRight.previous = oldLeft;
2428
-
2429
- if (newLeft) newLeft.next = first;
2430
- if (newRight) newRight.previous = last;
2431
-
2432
- if (!first.previous) this.firstChunk = last.next;
2433
- if (!last.next) {
2434
- this.lastChunk = first.previous;
2435
- this.lastChunk.next = null;
2436
- }
2437
-
2438
- first.previous = newLeft;
2439
- last.next = newRight || null;
2440
-
2441
- if (!newLeft) this.firstChunk = first;
2442
- if (!newRight) this.lastChunk = last;
2443
- return this;
2444
- }
2445
-
2446
- overwrite(start, end, content, options) {
2447
- options = options || {};
2448
- return this.update(start, end, content, { ...options, overwrite: !options.contentOnly });
2449
- }
2450
-
2451
- update(start, end, content, options) {
2452
- start = start + this.offset;
2453
- end = end + this.offset;
2454
-
2455
- if (typeof content !== 'string') throw new TypeError('replacement content must be a string');
2456
-
2457
- if (this.original.length !== 0) {
2458
- while (start < 0) start += this.original.length;
2459
- while (end < 0) end += this.original.length;
2460
- }
2461
-
2462
- if (end > this.original.length) throw new Error('end is out of bounds');
2463
- if (start === end)
2464
- throw new Error(
2465
- 'Cannot overwrite a zero-length range – use appendLeft or prependRight instead',
2466
- );
2467
-
2468
- this._split(start);
2469
- this._split(end);
2470
-
2471
- if (options === true) {
2472
- if (!warned.storeName) {
2473
- console.warn(
2474
- 'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string',
2475
- );
2476
- warned.storeName = true;
2477
- }
2478
-
2479
- options = { storeName: true };
2480
- }
2481
- const storeName = options !== undefined ? options.storeName : false;
2482
- const overwrite = options !== undefined ? options.overwrite : false;
2483
-
2484
- if (storeName) {
2485
- const original = this.original.slice(start, end);
2486
- Object.defineProperty(this.storedNames, original, {
2487
- writable: true,
2488
- value: true,
2489
- enumerable: true,
2490
- });
2491
- }
2492
-
2493
- const first = this.byStart[start];
2494
- const last = this.byEnd[end];
2495
-
2496
- if (first) {
2497
- let chunk = first;
2498
- while (chunk !== last) {
2499
- if (chunk.next !== this.byStart[chunk.end]) {
2500
- throw new Error('Cannot overwrite across a split point');
2501
- }
2502
- chunk = chunk.next;
2503
- chunk.edit('', false);
2504
- }
2505
-
2506
- first.edit(content, storeName, !overwrite);
2507
- } else {
2508
- // must be inserting at the end
2509
- const newChunk = new Chunk(start, end, '').edit(content, storeName);
2510
-
2511
- // TODO last chunk in the array may not be the last chunk, if it's moved...
2512
- last.next = newChunk;
2513
- newChunk.previous = last;
2514
- }
2515
- return this;
2516
- }
2517
-
2518
- prepend(content) {
2519
- if (typeof content !== 'string') throw new TypeError('outro content must be a string');
2520
-
2521
- this.intro = content + this.intro;
2522
- return this;
2523
- }
2524
-
2525
- prependLeft(index, content) {
2526
- index = index + this.offset;
2527
-
2528
- if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
2529
-
2530
- this._split(index);
2531
-
2532
- const chunk = this.byEnd[index];
2533
-
2534
- if (chunk) {
2535
- chunk.prependLeft(content);
2536
- } else {
2537
- this.intro = content + this.intro;
2538
- }
2539
- return this;
2540
- }
2541
-
2542
- prependRight(index, content) {
2543
- index = index + this.offset;
2544
-
2545
- if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
2546
-
2547
- this._split(index);
2548
-
2549
- const chunk = this.byStart[index];
2550
-
2551
- if (chunk) {
2552
- chunk.prependRight(content);
2553
- } else {
2554
- this.outro = content + this.outro;
2555
- }
2556
- return this;
2557
- }
2558
-
2559
- remove(start, end) {
2560
- start = start + this.offset;
2561
- end = end + this.offset;
2562
-
2563
- if (this.original.length !== 0) {
2564
- while (start < 0) start += this.original.length;
2565
- while (end < 0) end += this.original.length;
2566
- }
2567
-
2568
- if (start === end) return this;
2569
-
2570
- if (start < 0 || end > this.original.length) throw new Error('Character is out of bounds');
2571
- if (start > end) throw new Error('end must be greater than start');
2572
-
2573
- this._split(start);
2574
- this._split(end);
2575
-
2576
- let chunk = this.byStart[start];
2577
-
2578
- while (chunk) {
2579
- chunk.intro = '';
2580
- chunk.outro = '';
2581
- chunk.edit('');
2582
-
2583
- chunk = end > chunk.end ? this.byStart[chunk.end] : null;
2584
- }
2585
- return this;
2586
- }
2587
-
2588
- reset(start, end) {
2589
- start = start + this.offset;
2590
- end = end + this.offset;
2591
-
2592
- if (this.original.length !== 0) {
2593
- while (start < 0) start += this.original.length;
2594
- while (end < 0) end += this.original.length;
2595
- }
2596
-
2597
- if (start === end) return this;
2598
-
2599
- if (start < 0 || end > this.original.length) throw new Error('Character is out of bounds');
2600
- if (start > end) throw new Error('end must be greater than start');
2601
-
2602
- this._split(start);
2603
- this._split(end);
2604
-
2605
- let chunk = this.byStart[start];
2606
-
2607
- while (chunk) {
2608
- chunk.reset();
2609
-
2610
- chunk = end > chunk.end ? this.byStart[chunk.end] : null;
2611
- }
2612
- return this;
2613
- }
2614
-
2615
- lastChar() {
2616
- if (this.outro.length) return this.outro[this.outro.length - 1];
2617
- let chunk = this.lastChunk;
2618
- do {
2619
- if (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];
2620
- if (chunk.content.length) return chunk.content[chunk.content.length - 1];
2621
- if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];
2622
- } while ((chunk = chunk.previous));
2623
- if (this.intro.length) return this.intro[this.intro.length - 1];
2624
- return '';
2625
- }
2626
-
2627
- lastLine() {
2628
- let lineIndex = this.outro.lastIndexOf(n);
2629
- if (lineIndex !== -1) return this.outro.substr(lineIndex + 1);
2630
- let lineStr = this.outro;
2631
- let chunk = this.lastChunk;
2632
- do {
2633
- if (chunk.outro.length > 0) {
2634
- lineIndex = chunk.outro.lastIndexOf(n);
2635
- if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;
2636
- lineStr = chunk.outro + lineStr;
2637
- }
2638
-
2639
- if (chunk.content.length > 0) {
2640
- lineIndex = chunk.content.lastIndexOf(n);
2641
- if (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;
2642
- lineStr = chunk.content + lineStr;
2643
- }
2644
-
2645
- if (chunk.intro.length > 0) {
2646
- lineIndex = chunk.intro.lastIndexOf(n);
2647
- if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;
2648
- lineStr = chunk.intro + lineStr;
2649
- }
2650
- } while ((chunk = chunk.previous));
2651
- lineIndex = this.intro.lastIndexOf(n);
2652
- if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;
2653
- return this.intro + lineStr;
2654
- }
2655
-
2656
- slice(start = 0, end = this.original.length - this.offset) {
2657
- start = start + this.offset;
2658
- end = end + this.offset;
2659
-
2660
- if (this.original.length !== 0) {
2661
- while (start < 0) start += this.original.length;
2662
- while (end < 0) end += this.original.length;
2663
- }
2664
-
2665
- let result = '';
2666
-
2667
- // find start chunk
2668
- let chunk = this.firstChunk;
2669
- while (chunk && (chunk.start > start || chunk.end <= start)) {
2670
- // found end chunk before start
2671
- if (chunk.start < end && chunk.end >= end) {
2672
- return result;
2673
- }
2674
-
2675
- chunk = chunk.next;
2676
- }
2677
-
2678
- if (chunk && chunk.edited && chunk.start !== start)
2679
- throw new Error(`Cannot use replaced character ${start} as slice start anchor.`);
2680
-
2681
- const startChunk = chunk;
2682
- while (chunk) {
2683
- if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
2684
- result += chunk.intro;
2685
- }
2686
-
2687
- const containsEnd = chunk.start < end && chunk.end >= end;
2688
- if (containsEnd && chunk.edited && chunk.end !== end)
2689
- throw new Error(`Cannot use replaced character ${end} as slice end anchor.`);
2690
-
2691
- const sliceStart = startChunk === chunk ? start - chunk.start : 0;
2692
- const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
2693
-
2694
- result += chunk.content.slice(sliceStart, sliceEnd);
2695
-
2696
- if (chunk.outro && (!containsEnd || chunk.end === end)) {
2697
- result += chunk.outro;
2698
- }
2699
-
2700
- if (containsEnd) {
2701
- break;
2702
- }
2703
-
2704
- chunk = chunk.next;
2705
- }
2706
-
2707
- return result;
2708
- }
2709
-
2710
- // TODO deprecate this? not really very useful
2711
- snip(start, end) {
2712
- const clone = this.clone();
2713
- clone.remove(0, start);
2714
- clone.remove(end, clone.original.length);
2715
-
2716
- return clone;
2717
- }
2718
-
2719
- _split(index) {
2720
- if (this.byStart[index] || this.byEnd[index]) return;
2721
-
2722
- let chunk = this.lastSearchedChunk;
2723
- let previousChunk = chunk;
2724
- const searchForward = index > chunk.end;
2725
-
2726
- while (chunk) {
2727
- if (chunk.contains(index)) return this._splitChunk(chunk, index);
2728
-
2729
- chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
2730
-
2731
- // Prevent infinite loop (e.g. via empty chunks, where start === end)
2732
- if (chunk === previousChunk) return;
2733
-
2734
- previousChunk = chunk;
2735
- }
2736
- }
2737
-
2738
- _splitChunk(chunk, index) {
2739
- if (chunk.edited && chunk.content.length) {
2740
- // zero-length edited chunks are a special case (overlapping replacements)
2741
- const loc = getLocator(this.original)(index);
2742
- throw new Error(
2743
- `Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`,
2744
- );
2745
- }
2746
-
2747
- const newChunk = chunk.split(index);
2748
-
2749
- this.byEnd[index] = chunk;
2750
- this.byStart[index] = newChunk;
2751
- this.byEnd[newChunk.end] = newChunk;
2752
-
2753
- if (chunk === this.lastChunk) this.lastChunk = newChunk;
2754
-
2755
- this.lastSearchedChunk = chunk;
2756
- return true;
2757
- }
2758
-
2759
- toString() {
2760
- let str = this.intro;
2761
-
2762
- let chunk = this.firstChunk;
2763
- while (chunk) {
2764
- str += chunk.toString();
2765
- chunk = chunk.next;
2766
- }
2767
-
2768
- return str + this.outro;
2769
- }
2770
-
2771
- isEmpty() {
2772
- let chunk = this.firstChunk;
2773
- do {
2774
- if (
2775
- (chunk.intro.length && chunk.intro.trim()) ||
2776
- (chunk.content.length && chunk.content.trim()) ||
2777
- (chunk.outro.length && chunk.outro.trim())
2778
- )
2779
- return false;
2780
- } while ((chunk = chunk.next));
2781
- return true;
2782
- }
2783
-
2784
- length() {
2785
- let chunk = this.firstChunk;
2786
- let length = 0;
2787
- do {
2788
- length += chunk.intro.length + chunk.content.length + chunk.outro.length;
2789
- } while ((chunk = chunk.next));
2790
- return length;
2791
- }
2792
-
2793
- trimLines() {
2794
- return this.trim('[\\r\\n]');
2795
- }
2796
-
2797
- trim(charType) {
2798
- return this.trimStart(charType).trimEnd(charType);
2799
- }
2800
-
2801
- trimEndAborted(charType) {
2802
- const rx = new RegExp((charType || '\\s') + '+$');
2803
-
2804
- this.outro = this.outro.replace(rx, '');
2805
- if (this.outro.length) return true;
2806
-
2807
- let chunk = this.lastChunk;
2808
-
2809
- do {
2810
- const end = chunk.end;
2811
- const aborted = chunk.trimEnd(rx);
2812
-
2813
- // if chunk was trimmed, we have a new lastChunk
2814
- if (chunk.end !== end) {
2815
- if (this.lastChunk === chunk) {
2816
- this.lastChunk = chunk.next;
2817
- }
2818
-
2819
- this.byEnd[chunk.end] = chunk;
2820
- this.byStart[chunk.next.start] = chunk.next;
2821
- this.byEnd[chunk.next.end] = chunk.next;
2822
- }
2823
-
2824
- if (aborted) return true;
2825
- chunk = chunk.previous;
2826
- } while (chunk);
2827
-
2828
- return false;
2829
- }
2830
-
2831
- trimEnd(charType) {
2832
- this.trimEndAborted(charType);
2833
- return this;
2834
- }
2835
- trimStartAborted(charType) {
2836
- const rx = new RegExp('^' + (charType || '\\s') + '+');
2837
-
2838
- this.intro = this.intro.replace(rx, '');
2839
- if (this.intro.length) return true;
2840
-
2841
- let chunk = this.firstChunk;
2842
-
2843
- do {
2844
- const end = chunk.end;
2845
- const aborted = chunk.trimStart(rx);
2846
-
2847
- if (chunk.end !== end) {
2848
- // special case...
2849
- if (chunk === this.lastChunk) this.lastChunk = chunk.next;
2850
-
2851
- this.byEnd[chunk.end] = chunk;
2852
- this.byStart[chunk.next.start] = chunk.next;
2853
- this.byEnd[chunk.next.end] = chunk.next;
2854
- }
2855
-
2856
- if (aborted) return true;
2857
- chunk = chunk.next;
2858
- } while (chunk);
2859
-
2860
- return false;
2861
- }
2862
-
2863
- trimStart(charType) {
2864
- this.trimStartAborted(charType);
2865
- return this;
2866
- }
2867
-
2868
- hasChanged() {
2869
- return this.original !== this.toString();
2870
- }
2871
-
2872
- _replaceRegexp(searchValue, replacement) {
2873
- function getReplacement(match, str) {
2874
- if (typeof replacement === 'string') {
2875
- return replacement.replace(/\$(\$|&|\d+)/g, (_, i) => {
2876
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter
2877
- if (i === '$') return '$';
2878
- if (i === '&') return match[0];
2879
- const num = +i;
2880
- if (num < match.length) return match[+i];
2881
- return `$${i}`;
2882
- });
2883
- } else {
2884
- return replacement(...match, match.index, str, match.groups);
2885
- }
2886
- }
2887
- function matchAll(re, str) {
2888
- let match;
2889
- const matches = [];
2890
- while ((match = re.exec(str))) {
2891
- matches.push(match);
2892
- }
2893
- return matches;
2894
- }
2895
- if (searchValue.global) {
2896
- const matches = matchAll(searchValue, this.original);
2897
- matches.forEach((match) => {
2898
- if (match.index != null) {
2899
- const replacement = getReplacement(match, this.original);
2900
- if (replacement !== match[0]) {
2901
- this.overwrite(match.index, match.index + match[0].length, replacement);
2902
- }
2903
- }
2904
- });
2905
- } else {
2906
- const match = this.original.match(searchValue);
2907
- if (match && match.index != null) {
2908
- const replacement = getReplacement(match, this.original);
2909
- if (replacement !== match[0]) {
2910
- this.overwrite(match.index, match.index + match[0].length, replacement);
2911
- }
2912
- }
2913
- }
2914
- return this;
2915
- }
2916
-
2917
- _replaceString(string, replacement) {
2918
- const { original } = this;
2919
- const index = original.indexOf(string);
2920
-
2921
- if (index !== -1) {
2922
- if (typeof replacement === 'function') {
2923
- replacement = replacement(string, index, original);
2924
- }
2925
- if (string !== replacement) {
2926
- this.overwrite(index, index + string.length, replacement);
2927
- }
2928
- }
2929
-
2930
- return this;
2931
- }
2932
-
2933
- replace(searchValue, replacement) {
2934
- if (typeof searchValue === 'string') {
2935
- return this._replaceString(searchValue, replacement);
2936
- }
2937
-
2938
- return this._replaceRegexp(searchValue, replacement);
2939
- }
2940
-
2941
- _replaceAllString(string, replacement) {
2942
- const { original } = this;
2943
- const stringLength = string.length;
2944
- for (
2945
- let index = original.indexOf(string);
2946
- index !== -1;
2947
- index = original.indexOf(string, index + stringLength)
2948
- ) {
2949
- const previous = original.slice(index, index + stringLength);
2950
- let _replacement = replacement;
2951
- if (typeof replacement === 'function') {
2952
- _replacement = replacement(previous, index, original);
2953
- }
2954
- if (previous !== _replacement) this.overwrite(index, index + stringLength, _replacement);
2955
- }
2956
-
2957
- return this;
2958
- }
2959
-
2960
- replaceAll(searchValue, replacement) {
2961
- if (typeof searchValue === 'string') {
2962
- return this._replaceAllString(searchValue, replacement);
2963
- }
2964
-
2965
- if (!searchValue.global) {
2966
- throw new TypeError(
2967
- 'MagicString.prototype.replaceAll called with a non-global RegExp argument',
2968
- );
2969
- }
2970
-
2971
- return this._replaceRegexp(searchValue, replacement);
2972
- }
1798
+ async function transform(code, cache, id, context, opt) {
1799
+ const scriptTag = code.raw.find(node => {
1800
+ return node.name == "script";
1801
+ });
1802
+ if (!scriptTag)
1803
+ throw new Error("[transform check]: not found mcx script tag");
1804
+ const transformContext = {
1805
+ rollupContext: context,
1806
+ impAST: [],
1807
+ currentAST: t.program([]),
1808
+ opt,
1809
+ currentId: id,
1810
+ compiledCode: code,
1811
+ cache,
1812
+ scriptTag: scriptTag,
1813
+ mainFn: {
1814
+ param: [],
1815
+ body: []
1816
+ }
1817
+ };
1818
+ return await _transform(transformContext);
2973
1819
  }
2974
1820
 
2975
- const cache = new Map();
2976
1821
  function mcxPlugn(opt) {
1822
+ let cache = new Map();
2977
1823
  return {
2978
1824
  name: "mbler-mcx-core",
2979
1825
  async resolveId(id, imp) {
@@ -3016,22 +1862,56 @@ function mcxPlugn(opt) {
3016
1862
  if (err instanceof CompileError) {
3017
1863
  const error = err;
3018
1864
  this.error(error.message, {
3019
- column: error.loc.pos,
1865
+ column: error.loc.column,
3020
1866
  line: error.loc.line,
3021
1867
  });
3022
1868
  }
3023
- this.error(err.message);
1869
+ this.error(String(err));
3024
1870
  }
3025
1871
  compileData.setFilePath(id);
1872
+ const compiledCode = await transform(compileData, cache, id, this, opt);
3026
1873
  return {
3027
- code: await transform(compileData, cache, id, this, opt),
1874
+ code: compiledCode,
3028
1875
  map: magic.generateMap({ hires: true, source: id }),
3029
1876
  };
3030
1877
  }
3031
1878
  return null;
3032
1879
  },
1880
+ buildEnd() {
1881
+ cache.clear();
1882
+ },
1883
+ buildStart() {
1884
+ cache = new Map();
1885
+ }
3033
1886
  };
3034
1887
  }
1888
+ function AbsoluteJoin(base, dir) {
1889
+ return path.isAbsolute(dir) ? dir : path.join(base, dir);
1890
+ }
1891
+ async function CompileProject(opt) {
1892
+ const rollupResult = await rollup.rollup({
1893
+ input: opt.main,
1894
+ // only minecraft package
1895
+ external: ["@minecraft/server", "@minecraft/server-ui"],
1896
+ plugins: [
1897
+ mcxPlugn(opt),
1898
+ commjs(),
1899
+ json(),
1900
+ module_resolve({
1901
+ modulePaths: [opt.moduleDir],
1902
+ }),
1903
+ ],
1904
+ });
1905
+ // only index.js
1906
+ await fs.rm(opt.output, {
1907
+ recursive: true,
1908
+ });
1909
+ await rollupResult.write({
1910
+ file: AbsoluteJoin(opt.output, "./index.js"),
1911
+ format: "esm",
1912
+ sourcemap: true,
1913
+ });
1914
+ }
3035
1915
 
3036
1916
  /**
3037
1917
  * @description - this is a function factory to generate mcxProject
@@ -3057,7 +1937,7 @@ class Compile {
3057
1937
  await fs.mkdir(this.BuildOpt.moduleDir, {
3058
1938
  recursive: true,
3059
1939
  });
3060
- await mcxPlugn(this.BuildOpt);
1940
+ await CompileProject(this.BuildOpt);
3061
1941
  }
3062
1942
  }
3063
1943
 
@@ -3069,18 +1949,152 @@ var types = /*#__PURE__*/Object.freeze({
3069
1949
  __proto__: null
3070
1950
  });
3071
1951
 
3072
- var index = {
3073
- pulgn: CompileMcxDir,
3074
- AST: AST,
3075
- Compiler,
3076
- utils: McxUtlis,
3077
- transform
1952
+ /**
1953
+ * MCX Volar TSC 插件
1954
+ * 为 MCX 文件提供 TypeScript 智能感知支持
1955
+ */
1956
+ const mcxVolarTscPlugin = {
1957
+ getLanguageId(scriptId) {
1958
+ if (scriptId.path.endsWith('.mcx')) {
1959
+ return 'mcx';
1960
+ }
1961
+ return undefined;
1962
+ },
3078
1963
  };
1964
+ /**
1965
+ * MCX 虚拟代码
1966
+ * 用于在 Volar 中表示 MCX 文件的内容
1967
+ */
1968
+ class MCXVirtualCode {
1969
+ snapshot;
1970
+ id;
1971
+ languageId = 'mcx';
1972
+ mappings;
1973
+ embeddedCodes = [];
1974
+ constructor(snapshot, id = 'root') {
1975
+ this.snapshot = snapshot;
1976
+ this.id = id;
1977
+ const content = snapshot.getText(0, snapshot.getLength());
1978
+ // 基础映射:整个文件
1979
+ this.mappings = [{
1980
+ sourceOffsets: [0],
1981
+ generatedOffsets: [0],
1982
+ lengths: [snapshot.getLength()],
1983
+ data: {
1984
+ verification: true,
1985
+ completion: true,
1986
+ semantic: true,
1987
+ navigation: true,
1988
+ structure: true,
1989
+ format: true,
1990
+ }
1991
+ }];
1992
+ // 尝试提取 script 标签内容并创建嵌入式 JS/TS 代码
1993
+ try {
1994
+ const embeddedCode = this.extractScriptContent(content);
1995
+ if (embeddedCode) {
1996
+ this.embeddedCodes.push(embeddedCode);
1997
+ }
1998
+ }
1999
+ catch {
2000
+ // 解析失败时忽略嵌入式代码
2001
+ }
2002
+ }
2003
+ /**
2004
+ * 从 MCX 文件中提取 script 标签内容
2005
+ */
2006
+ extractScriptContent(content) {
2007
+ try {
2008
+ const ast = new AST.tag(content);
2009
+ const nodes = ast.data;
2010
+ // 查找 script 标签
2011
+ for (const node of nodes) {
2012
+ if (node.name === 'script') {
2013
+ const scriptContent = this.extractContent(node);
2014
+ if (scriptContent) {
2015
+ const scriptStart = this.findScriptStart(content);
2016
+ const isTypeScript = node.arr?.lang === 'ts';
2017
+ return {
2018
+ id: 'script',
2019
+ languageId: isTypeScript ? 'typescript' : 'javascript',
2020
+ snapshot: {
2021
+ getText: (start, end) => scriptContent.slice(start, end),
2022
+ getLength: () => scriptContent.length,
2023
+ getChangeRange: () => undefined,
2024
+ },
2025
+ mappings: [{
2026
+ sourceOffsets: [scriptStart],
2027
+ generatedOffsets: [0],
2028
+ lengths: [scriptContent.length],
2029
+ data: {
2030
+ verification: true,
2031
+ completion: true,
2032
+ semantic: true,
2033
+ navigation: true,
2034
+ structure: true,
2035
+ format: true,
2036
+ }
2037
+ }],
2038
+ embeddedCodes: [],
2039
+ };
2040
+ }
2041
+ }
2042
+ }
2043
+ }
2044
+ catch {
2045
+ // 解析失败
2046
+ }
2047
+ return null;
2048
+ }
2049
+ /**
2050
+ * 提取标签内容
2051
+ */
2052
+ extractContent(node) {
2053
+ if (!node.content)
2054
+ return '';
2055
+ return node.content
2056
+ .map(item => {
2057
+ if (item.type === 'TagContent') {
2058
+ return item.data;
2059
+ }
2060
+ return '';
2061
+ })
2062
+ .join('');
2063
+ }
2064
+ /**
2065
+ * 查找 script 标签在源文件中的起始位置
2066
+ */
2067
+ findScriptStart(content) {
2068
+ const scriptMatch = content.match(/<script[^>]*>([\s\S]*?)<\/script>/);
2069
+ if (scriptMatch && scriptMatch.index !== undefined) {
2070
+ // 返回 script 内容的开始位置(跳过开始标签)
2071
+ const tagEnd = content.indexOf('>', scriptMatch.index);
2072
+ return tagEnd + 1;
2073
+ }
2074
+ return 0;
2075
+ }
2076
+ }
2077
+ /**
2078
+ * 创建 MCX 虚拟代码实例
2079
+ */
2080
+ function createMCXVirtualCode(snapshot, id) {
2081
+ return new MCXVirtualCode(snapshot, id);
2082
+ }
2083
+
2084
+ var index = /*#__PURE__*/Object.freeze({
2085
+ __proto__: null,
2086
+ MCXVirtualCode: MCXVirtualCode,
2087
+ createMCXVirtualCode: createMCXVirtualCode,
2088
+ mcxVolarTscPlugin: mcxVolarTscPlugin
2089
+ });
3079
2090
 
3080
2091
  exports.AST = AST;
3081
- exports.Compiler = Compiler;
2092
+ exports.Compiler = index$2;
3082
2093
  exports.PUBTYPE = types;
3083
- exports.default = index;
2094
+ exports.TSC = index;
2095
+ exports.compile = CompileMcxDir;
2096
+ exports.compile_component = index$1;
2097
+ exports.plugin = mcxPlugn;
3084
2098
  exports.transform = transform;
3085
2099
  exports.utils = McxUtlis;
3086
2100
  //# sourceMappingURL=index.js.map