@scaffscript/core 0.2.5 → 0.2.6

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 (2) hide show
  1. package/dist/index.cjs +106 -38
  2. package/package.json +41 -41
package/dist/index.cjs CHANGED
@@ -344,14 +344,14 @@ function getTabLevels(str, tabType) {
344
344
  // package.json
345
345
  var package_default = {
346
346
  name: "@scaffscript/core",
347
- version: "0.2.3",
347
+ version: "0.2.6",
348
348
  repository: {
349
349
  type: "git",
350
350
  url: "https://github.com/undervolta/scaffscript"
351
351
  },
352
352
  main: "dist/index.cjs",
353
353
  devDependencies: {
354
- "@types/bun": "latest"
354
+ "@types/bun": "^1.3.11"
355
355
  },
356
356
  peerDependencies: {
357
357
  typescript: "^5"
@@ -722,15 +722,21 @@ async function implementModules(module2, fileGroup, file, config, mods) {
722
722
  for (const [idx, [_, include]] of modIterator) {
723
723
  if (idx > 0)
724
724
  switch (include.value.type) {
725
- case "object":
726
- case "method":
727
- case "array":
725
+ case "function":
726
+ case "class":
727
+ case "type":
728
+ case "interface":
728
729
  case "enum":
729
730
  toReplace += `
730
731
  `;
731
732
  break;
732
733
  }
733
- toReplace += include.value.parsedStr + `
734
+ if (include.value.type === "class")
735
+ toReplace += `${include.value.declaration} {
736
+ ${include.value.body}
737
+ }`;
738
+ else
739
+ toReplace += include.value.parsedStr + `
734
740
  `;
735
741
  if (idx === modLen - 1)
736
742
  toReplace += `
@@ -773,7 +779,10 @@ async function implementModules(module2, fileGroup, file, config, mods) {
773
779
  case "content":
774
780
  const tabChar = config.tabType === "1t" ? "\t" : config.tabType === "2s" ? " " : " ";
775
781
  const tabCnt = countTabsBeforeSubstring(file.content, match[0], tabChar);
776
- parsedStr = module2[mod.targetPath][`@${contentMod}` in module2[mod.targetPath] ? `@${contentMod}` : contentMod].parsedStr;
782
+ const usedMod = module2[mod.targetPath][`@${contentMod}` in module2[mod.targetPath] ? `@${contentMod}` : contentMod];
783
+ parsedStr = usedMod?.type !== "class" ? usedMod?.parsedStr ?? "" : `${usedMod?.declaration} {
784
+ ${usedMod?.body}
785
+ }`;
777
786
  if (tabCnt > 0) {
778
787
  const tabLevels = getTabLevels(parsedStr, config.tabType).map((l) => l + tabCnt);
779
788
  file.content = file.content.replace(match[0], parsedStr.split(`
@@ -984,6 +993,7 @@ function countBraces(line) {
984
993
  return count;
985
994
  }
986
995
  function parseFnParams(str) {
996
+ fnParamsRegex.lastIndex = 0;
987
997
  const match = str.match(fnParamsRegex);
988
998
  let names = [];
989
999
  let defaults = [];
@@ -1004,9 +1014,10 @@ function parseFnParams(str) {
1004
1014
  return { names, defaults, combined };
1005
1015
  }
1006
1016
  function convertClassMethods(classBody) {
1017
+ const reservedMethodNames = new Set(["if", "for", "while", "switch", "catch", "do", "else", "try", "finally"]);
1007
1018
  const methodRegex = /(\w+)\s*\(([^)]*)\)\s*{([\s\S]*?)}/g;
1008
1019
  return classBody.replace(methodRegex, (match, methodName, params, body) => {
1009
- if (methodName === "function")
1020
+ if (methodName === "function" || reservedMethodNames.has(methodName))
1010
1021
  return match;
1011
1022
  return `${methodName} = function(${params.replaceAll("?", " = undefined")}) {${body}}`;
1012
1023
  });
@@ -1065,7 +1076,14 @@ function getExportedModules(files, config) {
1065
1076
  const body = funcCode.slice(funcCode.indexOf("{")).trim();
1066
1077
  const params = parseFnParams(funcCode);
1067
1078
  const parsedStr = `function ${name}(${params.combined.join(", ")}) ${body}`;
1068
- module2[filePath][name] = { name, value: body.slice(1, -1), type: "function", parsedStr };
1079
+ module2[filePath][name] = {
1080
+ name,
1081
+ value: body.slice(1, -1),
1082
+ type: "function",
1083
+ parsedStr,
1084
+ header: funcCode.slice(0, funcCode.indexOf("{")).trim(),
1085
+ blockValue: insertTabs(1, config.tabType) + body.slice(1, -1)
1086
+ };
1069
1087
  }
1070
1088
  } else if (line.startsWith("export class ")) {
1071
1089
  const classLines = [];
@@ -1101,7 +1119,14 @@ function getExportedModules(files, config) {
1101
1119
  const parsedStr = `function ${name}(${constructor.replaceAll("?", " = undefined")}) constructor {
1102
1120
  ${insertTabs(1, config.tabType)}${classBody}
1103
1121
  }`;
1104
- module2[filePath][name] = { name, value: classCode.replace("export ", ""), type: "class", parsedStr };
1122
+ module2[filePath][name] = {
1123
+ name,
1124
+ value: classCode.replace("export ", ""),
1125
+ type: "class",
1126
+ parsedStr,
1127
+ declaration: `function ${name}(${constructor.replaceAll("?", " = undefined")}) constructor`,
1128
+ body: `${insertTabs(1, config.tabType)}${classBody}`
1129
+ };
1105
1130
  }
1106
1131
  } else if (line.startsWith("export interface ")) {
1107
1132
  const interfaceLines = [];
@@ -1204,14 +1229,28 @@ ${insertTabs(1, config.tabType)}${classBody}
1204
1229
  const parsedStr = `${name} = function(${params.combined.join(", ")}) ${arrowBlock}`;
1205
1230
  if (!module2[filePath])
1206
1231
  module2[filePath] = {};
1207
- module2[filePath][name] = { name, value: arrowBlock.slice(1, -1), type: "arrow-fn", parsedStr };
1232
+ module2[filePath][name] = {
1233
+ name,
1234
+ value: arrowBlock.slice(1, -1),
1235
+ type: "function",
1236
+ header: `${name} = function(${params.combined.join(", ")})`,
1237
+ blockValue: arrowBlock,
1238
+ parsedStr
1239
+ };
1208
1240
  } else {
1209
1241
  const params = parseFnParams(valuePart);
1210
1242
  const body = valuePart.split("=>")[1].trim();
1211
1243
  const parsedStr = `${name} = function(${params.combined.join(", ")}) { return ${body}; }`;
1212
1244
  if (!module2[filePath])
1213
1245
  module2[filePath] = {};
1214
- module2[filePath][name] = { name, value: body, type: "arrow-fn", parsedStr };
1246
+ module2[filePath][name] = {
1247
+ name,
1248
+ value: body,
1249
+ type: "function",
1250
+ header: `${name} = function(${params.combined.join(", ")})`,
1251
+ blockValue: body,
1252
+ parsedStr
1253
+ };
1215
1254
  }
1216
1255
  } else if (valuePart.startsWith("function")) {
1217
1256
  if (valuePart.trim().endsWith("{")) {
@@ -1233,12 +1272,27 @@ ${insertTabs(1, config.tabType)}${classBody}
1233
1272
  const parsedStr = `${name} = function(${params.combined.join(", ")}) ${funcBlock}`;
1234
1273
  if (!module2[filePath])
1235
1274
  module2[filePath] = {};
1236
- module2[filePath][name] = { name, value: funcBlock.slice(1, -1), type: "method", parsedStr };
1275
+ module2[filePath][name] = {
1276
+ name,
1277
+ value: funcBlock.slice(1, -1),
1278
+ type: "function",
1279
+ header: `${name} = function(${params.combined.join(", ")})`,
1280
+ blockValue: funcBlock,
1281
+ parsedStr
1282
+ };
1237
1283
  } else {
1284
+ const params = parseFnParams(valuePart);
1238
1285
  const parsedStr = `${name} = ${valuePart}`;
1239
1286
  if (!module2[filePath])
1240
1287
  module2[filePath] = {};
1241
- module2[filePath][name] = { name, value: line.replace("export ", ""), type: "method", parsedStr };
1288
+ module2[filePath][name] = {
1289
+ name,
1290
+ value: line.replace("export ", ""),
1291
+ type: "function",
1292
+ header: `${name} = function(${params.combined.join(", ")})`,
1293
+ blockValue: valuePart,
1294
+ parsedStr
1295
+ };
1242
1296
  }
1243
1297
  } else {
1244
1298
  let varType = "var";
@@ -1248,7 +1302,6 @@ ${insertTabs(1, config.tabType)}${classBody}
1248
1302
  varType = "let";
1249
1303
  else if (decl?.includes("var"))
1250
1304
  varType = "var";
1251
- const noVarKeyword = varType === "var" && !parts[0].includes("var");
1252
1305
  if (!module2[filePath])
1253
1306
  module2[filePath] = {};
1254
1307
  const parsedStr = varType !== "const" ? `${varType === "let" ? "" : "var "}${name} = ${valuePart};` : `#macro ${name} ${valuePart}`;
@@ -1374,7 +1427,15 @@ function reexportModule(module2, file, config) {
1374
1427
  return true;
1375
1428
  }
1376
1429
  // src/parser/class-implement.ts
1430
+ function resolveOptionalParams(str) {
1431
+ const funcExprRegex = /(\w+)\s*=\s*function\s*\(([^)]*)\)/g;
1432
+ return str.replace(funcExprRegex, (match, name, params) => {
1433
+ const resolvedParams = params.replace(/\?/g, " = undefined");
1434
+ return `${name} = function(${resolvedParams})`;
1435
+ });
1436
+ }
1377
1437
  function convertArrowFn(str) {
1438
+ arrowFnHeaderRegex.lastIndex = 0;
1378
1439
  return str.replace(arrowFnHeaderRegex, (match, _p1, _p2, _offset, _input, groups) => {
1379
1440
  if (!groups?.name)
1380
1441
  return match;
@@ -1396,6 +1457,12 @@ function parseHeader(str, regex = implHeaderRegex) {
1396
1457
  let i = start;
1397
1458
  for (;i < str.length; i++) {
1398
1459
  const char = str[i];
1460
+ if (!inString && char === "/" && str[i + 1] === "/") {
1461
+ while (i < str.length && str[i] !== `
1462
+ `)
1463
+ i++;
1464
+ continue;
1465
+ }
1399
1466
  if (inString) {
1400
1467
  if (char === stringChar && (i === 0 || str[i - 1] !== "\\")) {
1401
1468
  inString = false;
@@ -1437,9 +1504,10 @@ function implementClass(module2, fileGroup, config) {
1437
1504
  const filePath = fileImpl.parent.isIndex ? fileImpl.parent.path : `${fileImpl.parent.path}/${fileImpl.parent.name}`;
1438
1505
  const match = parseHeader(fileImpl.file.content);
1439
1506
  const classNames = [];
1440
- for (const [mIdx, m] of match.entries()) {
1507
+ for (const [_, m] of match.entries()) {
1441
1508
  const { name: className } = m;
1442
1509
  let { body } = m;
1510
+ body = resolveOptionalParams(body);
1443
1511
  body = convertClassMethods(body);
1444
1512
  body = convertArrowFn(body);
1445
1513
  if (!className || !body)
@@ -1470,31 +1538,31 @@ function implementClass(module2, fileGroup, config) {
1470
1538
  continue;
1471
1539
  }
1472
1540
  }
1473
- const classCloseBracket = module2[newFilePath][className].parsedStr.lastIndexOf("}");
1474
- module2[newFilePath][className].parsedStr = module2[newFilePath][className].parsedStr.slice(0, classCloseBracket) + `${body.replace(`
1475
- `, "")}` + (mIdx < match.length - 1 ? `
1476
-
1477
- ` : `
1478
- }
1479
- `);
1480
- if (mIdx === match.length - 1) {
1481
- for (const name of classNames) {
1482
- if (!module2[filePath] || !module2[filePath][name])
1483
- continue;
1484
- module2[filePath][name].parsedStr += `}
1485
- `;
1541
+ if (module2[newFilePath][className].type === "class") {
1542
+ const newMod = module2[newFilePath][className];
1543
+ newMod.body += `
1544
+ ${body}`;
1545
+ } else {
1546
+ if (config.onNotFound === "error") {
1547
+ log.error(`Class \x1B[33m${className}\x1B[0m not found for file \x1B[34m${fileImpl.file.name}\x1B[0m. Aborting...`);
1548
+ return false;
1549
+ } else {
1550
+ log.warn(`Class \x1B[33m${className}\x1B[0m not found for file \x1B[34m${fileImpl.file.name}\x1B[0m. Skipping this class...`);
1551
+ continue;
1486
1552
  }
1487
- } else
1488
- classNames.splice(classNames.indexOf(className), 1);
1553
+ }
1489
1554
  continue;
1555
+ } else if (module2[filePath][className].type === "class") {
1556
+ module2[filePath][className].body += `
1557
+ ${body}`;
1490
1558
  } else {
1491
- const classCloseBracket = module2[filePath][className].parsedStr.lastIndexOf("}");
1492
- module2[filePath][className].parsedStr = module2[filePath][className].parsedStr.slice(0, classCloseBracket) + `${body.replace(`
1493
- `, "")}` + (mIdx < match.length - 1 ? `
1494
-
1495
- ` : `
1496
- }
1497
- `);
1559
+ if (config.onNotFound === "error") {
1560
+ log.error(`Class \x1B[33m${className}\x1B[0m not found for file \x1B[34m${fileImpl.file.name}\x1B[0m. Aborting...`);
1561
+ return false;
1562
+ } else {
1563
+ log.warn(`Class \x1B[33m${className}\x1B[0m not found for file \x1B[34m${fileImpl.file.name}\x1B[0m. Skipping this class...`);
1564
+ continue;
1565
+ }
1498
1566
  }
1499
1567
  }
1500
1568
  }
package/package.json CHANGED
@@ -1,41 +1,41 @@
1
- {
2
- "name": "@scaffscript/core",
3
- "version": "0.2.5",
4
- "repository": {
5
- "type": "git",
6
- "url": "https://github.com/undervolta/scaffscript"
7
- },
8
- "main": "dist/index.cjs",
9
- "devDependencies": {
10
- "@types/bun": "latest"
11
- },
12
- "peerDependencies": {
13
- "typescript": "^5"
14
- },
15
- "bin": {
16
- "scaff": "./dist/index.cjs"
17
- },
18
- "description": "A minimal superset language of GML with TypeScript-like module system",
19
- "files": [
20
- "dist"
21
- ],
22
- "keywords": [
23
- "gamemaker",
24
- "gml",
25
- "scaff",
26
- "script",
27
- "superset",
28
- "module",
29
- "cli"
30
- ],
31
- "license": "MIT",
32
- "scripts": {
33
- "build": "bun run build:all",
34
- "build:node": "bun build src/index-node.ts --outfile dist/index.cjs --target node --format cjs",
35
- "build:bun": "bun build src/index-bun.ts --outfile build/index.mjs --target bun --format esm",
36
- "build:all": "bun run build:node && bun run build:bun",
37
- "dev": "bun run src/index-node.ts",
38
- "prelink": "bun run build"
39
- },
40
- "type": "module"
41
- }
1
+ {
2
+ "name": "@scaffscript/core",
3
+ "version": "0.2.6",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "https://github.com/undervolta/scaffscript"
7
+ },
8
+ "main": "dist/index.cjs",
9
+ "devDependencies": {
10
+ "@types/bun": "^1.3.11"
11
+ },
12
+ "peerDependencies": {
13
+ "typescript": "^5"
14
+ },
15
+ "bin": {
16
+ "scaff": "./dist/index.cjs"
17
+ },
18
+ "description": "A minimal superset language of GML with TypeScript-like module system",
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "keywords": [
23
+ "gamemaker",
24
+ "gml",
25
+ "scaff",
26
+ "script",
27
+ "superset",
28
+ "module",
29
+ "cli"
30
+ ],
31
+ "license": "MIT",
32
+ "scripts": {
33
+ "build": "bun run build:all",
34
+ "build:node": "bun build src/index-node.ts --outfile dist/index.cjs --target node --format cjs",
35
+ "build:bun": "bun build src/index-bun.ts --outfile build/index.mjs --target bun --format esm",
36
+ "build:all": "bun run build:node && bun run build:bun",
37
+ "dev": "bun run src/index-node.ts",
38
+ "prelink": "bun run build"
39
+ },
40
+ "type": "module"
41
+ }