@jspicl/cli 4.0.0-alpha.2 → 4.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -39,9 +39,10 @@ import type {Config} from "@jspicl/cli/types";
39
39
  const config: Config = {
40
40
  spritesheetImagePath: "assets/sprites.png",
41
41
  jsOutput: "build/game.js",
42
- picoPath: "/Applications/PICO-8.app/Contents/MacOS/pico8",
43
- reloadOnSave: true,
44
- showStats: true
42
+ showStats: true,
43
+ picoOptions: {
44
+ executablePath: "/Applications/PICO-8.app/Contents/MacOS/pico8"
45
+ }
45
46
  };
46
47
 
47
48
  export default config;
@@ -49,24 +50,33 @@ export default config;
49
50
 
50
51
  ### Config Options
51
52
 
52
- | Name | Type | Required | Description |
53
- | ---------------------- | -------- | -------- | -------------------------------------------------- |
54
- | `spritesheetImagePath` | string | Yes | Path to PNG spritesheet |
55
- | `jsOutput` | string | Yes | Path to output bundled JavaScript (for debugging) |
56
- | `picoPath` | string | No | Custom path to PICO-8 executable |
57
- | `includeBanner` | boolean | No | Include jspicl info comment in output |
58
- | `luaOutput` | string | No | Path to output transpiled Lua (for debugging) |
59
- | `pipeOutputToConsole` | boolean | No | Pipe console.log to terminal |
60
- | `reloadOnSave` | boolean | No | Reload PICO-8 when cartridge is updated |
61
- | `showStats` | boolean | No | Display build statistics |
62
- | `jspicl` | object | No | Options passed to @jspicl/core (prettify, etc.) |
53
+ | Name | Type | Required | Description |
54
+ | ---------------------- | -------- | -------- | ------------------------------------------------- |
55
+ | `spritesheetImagePath` | string | Yes | Path to PNG spritesheet |
56
+ | `jsOutput` | string | Yes | Path to output bundled JavaScript (for debugging) |
57
+ | `includeBanner` | boolean | No | Include jspicl info comment in output |
58
+ | `luaOutput` | string | No | Path to output transpiled Lua (for debugging) |
59
+ | `minify` | boolean | No | Experimental: Minify bundled JavaScript via esbuild |
60
+ | `pipeOutputToConsole` | boolean | No | Pipe PICO-8 output to terminal |
61
+ | `showStats` | boolean | No | Display build statistics |
62
+ | `jspiclOptions` | object | No | Options passed to @jspicl/core (prettify, etc.) |
63
+ | `polyfillTransform` | function | No | Custom function to transform polyfill output |
64
+ | `picoOptions` | object | No | PICO-8 configuration (see below) |
65
+
66
+ #### picoOptions
67
+
68
+ | Name | Type | Description |
69
+ | ---------------- | ------ | ---------------------------------------------- |
70
+ | `executablePath` | string | Custom path to PICO-8 executable |
71
+ | `cartDataPath` | string | Path to PICO-8 cart data directory |
72
+ | `cartDataId` | string | Cart data ID for hot reload (default: "jspicl_hotreload") |
63
73
 
64
74
  ## CLI Options
65
75
 
66
- | Name | Description |
67
- | ----------------- | ---------------------------------------- |
68
- | `--config`, `-c` | Path to config file (required) |
69
- | `--watch`, `-w` | Watch for changes and rebuild |
76
+ | Name | Description |
77
+ | ---------------- | ------------------------------ |
78
+ | `--config`, `-c` | Path to config file (required) |
79
+ | `--watch`, `-w` | Watch for changes and rebuild |
70
80
 
71
81
  ## Watch Mode
72
82
 
@@ -78,7 +88,7 @@ This applies for the spritesheet as well. Simply save your image and your change
78
88
 
79
89
  ![](https://github.com/AgronKabashi/assets/raw/814f6efe24bc9aca5d9d6ca6259279733529e300/rollup-plugin-jspicl/spritesheetLiveReload.gif)
80
90
 
81
- **Note:** Automatic PICO-8 reload is currently only supported on macOS.
91
+ **Note:** Automatic PICO-8 reload is supported on macOS and Linux. On Windows, PICO-8 will launch but you'll need to press Ctrl+R to reload manually.
82
92
 
83
93
  ## Requirements
84
94
 
package/dist/cli.js CHANGED
@@ -24,9 +24,21 @@ var cliArguments = {
24
24
  default: {
25
25
  jsOutput: "build/jsOutput.js"
26
26
  },
27
- coerce: async (p) => {
28
- const configModule = await import(path.resolve(p));
29
- return configModule.default;
27
+ coerce: async (configPath) => {
28
+ const configDir = path.dirname(configPath);
29
+ const configModule = await import(path.resolve(configPath));
30
+ const config = configModule.default;
31
+ config.jsOutput = path.resolve(configDir, config.jsOutput);
32
+ if (config.luaOutput) {
33
+ config.luaOutput = path.resolve(configDir, config.luaOutput);
34
+ }
35
+ if (config.spritesheetImagePath) {
36
+ config.spritesheetImagePath = path.resolve(
37
+ configDir,
38
+ config.spritesheetImagePath
39
+ );
40
+ }
41
+ return config;
30
42
  }
31
43
  }
32
44
  };
@@ -143,71 +155,11 @@ function logStats(lua, polyfillOutput, code) {
143
155
  });
144
156
  }
145
157
 
146
- // src/createPico8Launcher.ts
147
- import path3 from "path";
148
- import { spawn, exec } from "child_process";
149
- import { fileURLToPath } from "url";
150
- var __dirname = path3.dirname(fileURLToPath(import.meta.url));
151
- var osMatrix = {
152
- win32: {
153
- execPath: `"C:\\Program Files (x86)\\PICO-8\\pico8.exe"`
154
- },
155
- darwin: {
156
- execPath: "/Applications/PICO-8.app/Contents/MacOS/pico8",
157
- reloadCommand: path3.resolve(__dirname, "../scripts/reload-pico8-bin")
158
- },
159
- linux: {
160
- execPath: "~/pico-8/pico8"
161
- }
162
- };
163
- function createPico8Launcher(watch, customPicoPath, reloadOnSave, pipeOutputToConsole) {
164
- let picoProcess;
165
- const { execPath, reloadCommand } = osMatrix[process.platform];
166
- return (cartridgePath) => {
167
- if (!watch || !cartridgePath) {
168
- return;
169
- }
170
- if (picoProcess) {
171
- if (!reloadOnSave) {
172
- return;
173
- }
174
- if (reloadCommand) {
175
- logSuccess("Reloading cartridge in PICO-8");
176
- exec(reloadCommand);
177
- } else {
178
- logWarning(
179
- "Autoreloading is currently not supported on your OS. Please press Ctrl+R in PICO-8 to see new changes."
180
- );
181
- }
182
- } else {
183
- logSuccess("Running cartridge in PICO-8");
184
- picoProcess = launchPico8(
185
- customPicoPath || execPath,
186
- cartridgePath,
187
- pipeOutputToConsole
188
- );
189
- picoProcess.on("close", (errorCode) => {
190
- if (errorCode !== 0) {
191
- logWarning(`PICO-8 process exited with code ${errorCode}`);
192
- }
193
- picoProcess = null;
194
- });
195
- }
196
- };
197
- }
198
- function launchPico8(picoPath, cartridgePath, pipeOutputToConsole) {
199
- return spawn(picoPath, ["-run", `"${path3.resolve(cartridgePath)}"`], {
200
- shell: true,
201
- stdio: pipeOutputToConsole ? "inherit" : "pipe"
202
- });
203
- }
204
-
205
- // src/watchPlugin.ts
158
+ // src/esbuildPlugins/buildPlugin.ts
206
159
  import fs4 from "node:fs";
207
160
 
208
161
  // src/cartridge.ts
209
162
  import fs2 from "fs";
210
- import path4 from "path";
211
163
  function generateCartridgeContent({
212
164
  lua = "",
213
165
  gff = "",
@@ -236,8 +188,7 @@ ${music}`,
236
188
  }
237
189
  function getPicoSectionsFromCartridge(cartridgePath) {
238
190
  try {
239
- const resolvedCartridgePath = path4.resolve(cartridgePath);
240
- const content = fs2.existsSync(resolvedCartridgePath) ? fs2.readFileSync(resolvedCartridgePath, "utf8") : "";
191
+ const content = fs2.existsSync(cartridgePath) ? fs2.readFileSync(cartridgePath, "utf8") : "";
241
192
  return parsePico8Cartridge(content);
242
193
  } catch (error) {
243
194
  throw new Error(
@@ -359,6 +310,14 @@ var PICO8_PALETTE = [
359
310
  b: 170
360
311
  }
361
312
  ];
313
+ var EMPTY_CART_DATA = `0000000000000000000000000000000000000000000000000000000000000000
314
+ 0000000000000000000000000000000000000000000000000000000000000000
315
+ 0000000000000000000000000000000000000000000000000000000000000000
316
+ 0000000000000000000000000000000000000000000000000000000000000000
317
+ 0000000000000000000000000000000000000000000000000000000000000000
318
+ 0000000000000000000000000000000000000000000000000000000000000000
319
+ 0000000000000000000000000000000000000000000000000000000000000000
320
+ 0000000000000000000000000000000000000000000000000000000000000000`;
362
321
 
363
322
  // src/spritesheet.ts
364
323
  var spritesheetWidth = 128;
@@ -413,7 +372,7 @@ function getSpritesheetFromImage(imagePath) {
413
372
  // src/transpile.ts
414
373
  import { jspicl } from "@jspicl/core";
415
374
  function transpile(javascriptCode, config) {
416
- const { includeBanner, polyfillTransform, jspicl: jspiclOptions = {} } = config;
375
+ const { includeBanner, polyfillTransform, jspiclOptions } = config;
417
376
  const jspiclBanner = includeBanner && `${JSPICL_BANNER}` || "";
418
377
  const { code, polyfills } = jspicl(javascriptCode, jspiclOptions);
419
378
  const polyfillOutput = polyfillTransform ? polyfillTransform(polyfills) : Object.values(polyfills).join("\n");
@@ -424,9 +383,9 @@ function transpile(javascriptCode, config) {
424
383
  };
425
384
  }
426
385
 
427
- // src/watchPlugin.ts
428
- var watchPlugin = (options) => ({
429
- name: "watcher",
386
+ // src/esbuildPlugins/buildPlugin.ts
387
+ var buildPlugin = (options) => ({
388
+ name: "buildPlugin",
430
389
  setup(build) {
431
390
  build.onEnd(async (result) => {
432
391
  const { onBuildEnd, onBuildError, config, output } = options;
@@ -446,12 +405,146 @@ var watchPlugin = (options) => ({
446
405
  lua: transpiledSource.lua,
447
406
  gfx: gfxSection
448
407
  });
408
+ logToFile(cartridgeContent, output);
449
409
  onBuildEnd?.(cartridgeContent, transpiledSource);
450
410
  });
451
411
  }
452
412
  });
453
413
 
414
+ // src/esbuildPlugins/hotReloadPlugin.ts
415
+ import path4 from "node:path";
416
+ import fs6 from "node:fs";
417
+
418
+ // src/createPico8Launcher.ts
419
+ import { spawn } from "child_process";
420
+ import fs5 from "node:fs";
421
+ import path3 from "node:path";
422
+ import untildify from "untildify";
423
+ var osMatrix = {
424
+ win32: {
425
+ executablePath: `"C:\\Program Files (x86)\\PICO-8\\pico8.exe"`
426
+ },
427
+ darwin: {
428
+ executablePath: "/Applications/PICO-8.app/Contents/MacOS/pico8",
429
+ cartDataPath: untildify("~/Library/Application Support/pico-8/cdata/")
430
+ },
431
+ linux: {
432
+ executablePath: untildify("~/pico-8/pico8"),
433
+ cartDataPath: untildify("~/.lexaloffle/pico-8/cdata/")
434
+ }
435
+ };
436
+ function createPico8Launcher(picoOptions, pipeOutputToConsole) {
437
+ const platform = process.platform;
438
+ let picoProcess;
439
+ const {
440
+ executablePath,
441
+ cartDataPath,
442
+ cartDataId = "jspicl_hotreload"
443
+ } = {
444
+ ...osMatrix[platform],
445
+ ...picoOptions
446
+ };
447
+ return (cartridgePath) => {
448
+ if (!executablePath) {
449
+ logError(
450
+ `PICO-8 executable not found. Please install PICO-8 or set the executablePath option. Default path for your OS: ${osMatrix[platform].executablePath}`
451
+ );
452
+ return;
453
+ }
454
+ if (!cartridgePath) {
455
+ logError("No cartridge path provided");
456
+ return;
457
+ }
458
+ if (picoProcess) {
459
+ if (!cartDataPath) {
460
+ logWarning(
461
+ "Autoreloading is currently not supported on your OS. Please press Ctrl+R in PICO-8 to see the new changes."
462
+ );
463
+ return;
464
+ }
465
+ if (!fs5.existsSync(cartDataPath)) {
466
+ logWarning(
467
+ "Unable to reload cartridge in PICO-8 since the cartridge data path does not exist or is inaccessible. Please press Ctrl+R in PICO-8 to see the new changes."
468
+ );
469
+ return;
470
+ }
471
+ const cartDataFilePath = path3.resolve(
472
+ cartDataPath,
473
+ `${cartDataId}.p8d.txt`
474
+ );
475
+ const cartDataContent = fs5.existsSync(cartDataFilePath) ? fs5.readFileSync(
476
+ path3.resolve(cartDataPath, `${cartDataId}.p8d.txt`),
477
+ "utf-8"
478
+ ) : EMPTY_CART_DATA;
479
+ fs5.writeFileSync(
480
+ cartDataFilePath,
481
+ cartDataContent.slice(0, 64 * 8 + 8 - 2) + "1"
482
+ );
483
+ logSuccess("Reloading cartridge in PICO-8");
484
+ } else {
485
+ logSuccess("Running cartridge in PICO-8");
486
+ picoProcess = launchPico8(
487
+ executablePath,
488
+ cartridgePath,
489
+ pipeOutputToConsole
490
+ );
491
+ picoProcess.on("close", (errorCode) => {
492
+ if (errorCode !== 0) {
493
+ logWarning(`PICO-8 process exited with code ${errorCode}`);
494
+ }
495
+ picoProcess = null;
496
+ });
497
+ }
498
+ };
499
+ }
500
+ function launchPico8(picoPath, cartridgePath, pipeOutputToConsole) {
501
+ return spawn(
502
+ picoPath,
503
+ [
504
+ "-run",
505
+ `"${cartridgePath}"`,
506
+ "-root_path",
507
+ `"${path3.dirname(cartridgePath)}"`
508
+ ],
509
+ {
510
+ shell: true,
511
+ stdio: pipeOutputToConsole ? "inherit" : "pipe"
512
+ }
513
+ );
514
+ }
515
+
516
+ // src/esbuildPlugins/hotReloadPlugin.ts
517
+ var hotReloadPlugin = (options) => ({
518
+ name: "hotReloadPlugin",
519
+ setup: function(build) {
520
+ const runPico = createPico8Launcher(
521
+ options.config.picoOptions,
522
+ options.config.pipeOutputToConsole
523
+ );
524
+ build.onEnd(async () => {
525
+ const { output } = options;
526
+ const hotReloadScript = `
527
+ local shouldreload = false
528
+ function hotreload()
529
+ cartdata("${options.config.picoOptions?.cartDataId || "jspicl_hotreload"}")
530
+ shouldreload=peek(0x5eff - 3) == 1
531
+ if shouldreload then
532
+ poke(0x5eff - 3, 0)
533
+ load("${path4.basename(output)}")
534
+ end
535
+ end`;
536
+ const content = fs6.readFileSync(output, "utf-8");
537
+ const newContent = content.replace("__lua__", `__lua__
538
+ ${hotReloadScript}`).replace("function _draw()", `function _draw()
539
+ hotreload()`);
540
+ logToFile(newContent, output);
541
+ runPico(output);
542
+ });
543
+ }
544
+ });
545
+
454
546
  // src/index.ts
547
+ import chokidar from "chokidar";
455
548
  async function getCommandlineArguments() {
456
549
  const argv = await yargs(hideBin(process2.argv)).options(cliArguments).usage("jspicl-cli input output [<args>]").demandCommand(2, "Please specify an input and output file").help(false).strict().wrap(null).parseAsync();
457
550
  const {
@@ -466,23 +559,17 @@ async function getCommandlineArguments() {
466
559
  }
467
560
  async function startBuildService(input, output, cliOptions) {
468
561
  const { watch, config } = cliOptions;
469
- const runPico = createPico8Launcher(
470
- watch,
471
- config.picoPath,
472
- config.reloadOnSave,
473
- config.pipeOutputToConsole
474
- );
475
- const jsOutput = path5.resolve(config.jsOutput || "build/jsOutput.js");
562
+ const { jsOutput } = config;
476
563
  const buildConfig = {
477
564
  entryPoints: [input],
478
565
  bundle: true,
479
566
  platform: "neutral",
480
567
  treeShaking: false,
481
- minify: false,
568
+ minify: config.minify,
482
569
  format: "esm",
483
570
  outfile: jsOutput,
484
571
  plugins: [
485
- watchPlugin({
572
+ buildPlugin({
486
573
  config,
487
574
  output,
488
575
  onBuildError: (errors) => {
@@ -490,21 +577,26 @@ async function startBuildService(input, output, cliOptions) {
490
577
  ${errors}`);
491
578
  },
492
579
  onBuildEnd: (cartridgeContent, transpiledSource) => {
493
- config.luaOutput && logToFile(transpiledSource.lua, config.luaOutput);
494
- logToFile(cartridgeContent, output);
495
580
  logSuccess("Build completed");
496
- runPico(output);
581
+ config.luaOutput && logToFile(transpiledSource.lua, config.luaOutput);
497
582
  config.showStats && logStats(
498
583
  transpiledSource.lua,
499
584
  transpiledSource.polyfillOutput,
500
585
  cartridgeContent
501
586
  );
502
587
  }
588
+ }),
589
+ watch && hotReloadPlugin({
590
+ config,
591
+ output
503
592
  })
504
- ]
593
+ ].filter(Boolean)
505
594
  };
506
595
  if (watch) {
507
596
  const context = await esbuild.context(buildConfig);
597
+ chokidar.watch(config.spritesheetImagePath).on("change", async () => {
598
+ await context.rebuild();
599
+ });
508
600
  await context.watch();
509
601
  } else {
510
602
  await esbuild.build(buildConfig);
package/dist/cli.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts", "../src/arguments.ts", "../src/logging.ts", "../src/tokenCounter.ts", "../src/createPico8Launcher.ts", "../src/watchPlugin.ts", "../src/cartridge.ts", "../src/spritesheet.ts", "../src/constants.ts", "../src/transpile.ts"],
4
- "sourcesContent": ["import yargs from \"yargs\";\nimport {hideBin} from \"yargs/helpers\";\n\nimport path from \"node:path\";\n\nimport process from \"process\";\n\nimport esbuild, {type BuildOptions} from \"esbuild\";\nimport {cliArguments} from \"./arguments.js\";\nimport {logError, logInfo, logStats, logSuccess, logToFile} from \"./logging.js\";\nimport type {CommandLineOptions} from \"./types.js\";\nimport {createPico8Launcher} from \"./createPico8Launcher.js\";\nimport {watchPlugin} from \"./watchPlugin.js\";\n\nasync function getCommandlineArguments(): Promise<{\n input: string;\n output: string;\n options: CommandLineOptions;\n}> {\n const argv = await yargs(hideBin(process.argv))\n .options(cliArguments)\n .usage(\"jspicl-cli input output [<args>]\")\n .demandCommand(2, \"Please specify an input and output file\")\n .help(false)\n .strict()\n .wrap(null)\n .parseAsync();\n\n const {\n _: [input, output],\n ...restArguments\n } = argv;\n\n return {\n input: path.resolve(input.toString()),\n output: path.resolve(output.toString()),\n options: restArguments as CommandLineOptions\n };\n}\n\nexport async function startBuildService(\n input: string,\n output: string,\n cliOptions: CommandLineOptions\n) {\n const {watch, config} = cliOptions;\n const runPico = createPico8Launcher(\n watch,\n config.picoPath,\n config.reloadOnSave,\n config.pipeOutputToConsole\n );\n\n const jsOutput = path.resolve(config.jsOutput || \"build/jsOutput.js\");\n\n const buildConfig: BuildOptions = {\n entryPoints: [input],\n bundle: true,\n platform: \"neutral\",\n treeShaking: false,\n minify: false,\n format: \"esm\",\n outfile: jsOutput,\n plugins: [\n watchPlugin({\n config,\n output,\n\n onBuildError: (errors) => {\n logError(`Build failed with errors:\\n${errors}`);\n },\n\n onBuildEnd: (cartridgeContent, transpiledSource) => {\n config.luaOutput && logToFile(transpiledSource.lua, config.luaOutput);\n logToFile(cartridgeContent, output);\n\n logSuccess(\"Build completed\");\n runPico(output);\n\n // Statistics\n config.showStats &&\n logStats(\n transpiledSource.lua,\n transpiledSource.polyfillOutput,\n cartridgeContent\n );\n }\n })\n ]\n };\n\n if (watch) {\n const context = await esbuild.context(buildConfig);\n await context.watch();\n } else {\n await esbuild.build(buildConfig);\n }\n}\n\nasync function runCLI() {\n const {input, output, options} = await getCommandlineArguments();\n\n process.on(\"SIGINT\", () => {\n logInfo(\"Shutting down...\");\n process.exit(0);\n });\n\n try {\n await startBuildService(input, output, options);\n } catch (error) {\n logError(String(error));\n throw error;\n }\n}\n\nrunCLI();\n", "import path from \"node:path\";\nimport type {Options} from \"yargs\";\nimport type {CommandLineOptions, Config} from \"./types.js\";\n\nexport const cliArguments: Record<keyof CommandLineOptions, Options> = {\n watch: {\n description: \"Reload cartridge on rebuilds\",\n type: \"boolean\",\n default: false,\n alias: \"w\"\n },\n config: {\n description: \"Path to a config file\",\n type: \"string\",\n alias: \"c\",\n requiresArg: true,\n default: {\n jsOutput: \"build/jsOutput.js\"\n } as Config,\n coerce: async (p: string) => {\n const configModule = await import(path.resolve(p));\n return configModule.default;\n }\n }\n};\n", "import fs from \"node:fs\";\nimport path from \"node:path\";\nimport {mkdirp} from \"mkdirp\";\nimport {getTokenCount} from \"./tokenCounter.js\";\n\nenum ICONS {\n info = \"\\x1b[34m\u2139\",\n success = \"\\x1b[32m\u2714\",\n warning = \"\\x1b[33m\u26A0\",\n error = \"\\x1b[31m\u2716\"\n}\n\nexport function logToFile(content: string, filePath: string) {\n mkdirp.sync(path.dirname(filePath));\n fs.writeFileSync(path.resolve(filePath), content);\n}\n\nexport function logInfo(content: string) {\n logToConsole(content, ICONS.info);\n}\n\nexport function logSuccess(content: string) {\n logToConsole(content, ICONS.success);\n}\n\nexport function logWarning(content: string) {\n logToConsole(content, ICONS.warning);\n}\n\nexport function logError(content: string) {\n logToConsole(content, ICONS.error);\n}\n\nfunction logToConsole(content: string, icon: string) {\n console.log(`${icon} ${content}\\x1b[0m`);\n}\n\nexport function logStats(lua: string, polyfillOutput: string, code: string) {\n const tokens = getTokenCount(lua);\n const polyfillTokens = getTokenCount(polyfillOutput);\n\n logInfo(\"Cartridge Statistics\");\n console.log(\"\".padEnd(41, \"\u2014\"));\n\n const stats = [\n {\n label: \"Characters\",\n value: lua.length,\n percent: `${~~((lua.length * 100) / 65535)}%`\n },\n {\n label: \"Tokens\",\n value: `~${tokens}`,\n percent: `${~~((tokens * 100) / 8192)}%`\n },\n {\n label: \" - Polyfills\",\n value: `~${polyfillTokens}`\n },\n {\n label: \"Filesize\",\n value: `${Math.ceil(code.length / 1024)} KB`\n }\n ];\n\n stats.forEach((stats) => {\n const label = `${stats.label}:`.padEnd(20, \" \");\n const value = `${stats.value}`.padStart(15, \" \");\n const percent = stats.percent\n ? `\\x1b[33m${stats.percent}`.padStart(10, \" \")\n : \"\";\n\n console.log(`${label}${value}${percent}\\x1b[0m`);\n });\n}\n", "// Each token is a word (e.g. variable name) or operator.\n// Pairs of brackets, and strings count as 1 token.\n// Commas, periods, LOCALs, semi-colons, ENDs, and comments are not counted.\nconst tokens = [\n /\\\"[^\\\"]*\\\"/, // Strings\n /\\d+\\.\\d+/, // floating numbers\n /\\w+/, // words\n /\\d+/, // numbers\n\n /!=/, // inequality\n /==/, // comparison\n /\\+=/, // incrementing assignment\n /-=/, // decrementing assignment\n /<=/, // equal or less than\n />=/, // equal or greater than\n /\\.\\./, // string concatenation\n\n /</, // less than\n />/, // greater than\n /\\+/, // addition\n /-/, // subtraction\n /\\//, // division\n /\\*/, // multiplication\n /=/, // equals\n /\\%/, // percentage\n /\\(/, // paranthesis\n /\\[/, // left bracket\n /\\{/ // left curly brace\n]\n .map((r) => r.source)\n .join(\"|\");\n\n/** Calculates the token count for the passed in Lua code*/\nexport function getTokenCount(luaCode: string) {\n const regex = new RegExp(`(${tokens})`, \"gi\");\n\n return (luaCode.match(regex) || []).filter(\n (token) => token !== \"local\" && token !== \"end\"\n ).length;\n}\n", "import path from \"path\";\nimport {spawn, exec, ChildProcess} from \"child_process\";\nimport {fileURLToPath} from \"url\";\nimport {logSuccess, logWarning} from \"./logging.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst osMatrix: Record<string, {execPath: string; reloadCommand?: string}> = {\n win32: {\n execPath: `\"C:\\\\Program Files (x86)\\\\PICO-8\\\\pico8.exe\"`\n },\n darwin: {\n execPath: \"/Applications/PICO-8.app/Contents/MacOS/pico8\",\n reloadCommand: path.resolve(__dirname, \"../scripts/reload-pico8-bin\")\n },\n linux: {\n execPath: \"~/pico-8/pico8\"\n }\n};\n\nexport function createPico8Launcher(\n watch: boolean,\n customPicoPath?: string,\n reloadOnSave?: boolean,\n pipeOutputToConsole?: boolean\n) {\n let picoProcess: ChildProcess | null;\n const {execPath, reloadCommand} = osMatrix[process.platform];\n\n return (cartridgePath: string) => {\n if (!watch || !cartridgePath) {\n return;\n }\n\n if (picoProcess) {\n if (!reloadOnSave) {\n return;\n }\n\n if (reloadCommand) {\n logSuccess(\"Reloading cartridge in PICO-8\");\n exec(reloadCommand);\n } else {\n logWarning(\n \"Autoreloading is currently not supported on your OS. Please press Ctrl+R in PICO-8 to see new changes.\"\n );\n }\n } else {\n logSuccess(\"Running cartridge in PICO-8\");\n // Use customized path if available, otherwise fallback to the default one for the current OS\n picoProcess = launchPico8(\n customPicoPath || execPath,\n cartridgePath,\n pipeOutputToConsole\n );\n\n picoProcess.on(\"close\", (errorCode) => {\n if (errorCode !== 0) {\n logWarning(`PICO-8 process exited with code ${errorCode}`);\n }\n picoProcess = null;\n });\n }\n };\n}\n\nfunction launchPico8(\n picoPath: string,\n cartridgePath: string,\n pipeOutputToConsole?: boolean\n) {\n return spawn(picoPath, [\"-run\", `\"${path.resolve(cartridgePath)}\"`], {\n shell: true,\n stdio: pipeOutputToConsole ? \"inherit\" : \"pipe\"\n });\n}\n", "import type {BuildResult, Plugin} from \"esbuild\";\nimport fs from \"node:fs\";\nimport {\n generateCartridgeContent,\n getPicoSectionsFromCartridge\n} from \"./cartridge.js\";\nimport {getSpritesheetFromImage} from \"./spritesheet.js\";\nimport {transpile} from \"./transpile.js\";\nimport type {Config} from \"./types.js\";\n\ntype WatchPluginOptions = {\n config: Config;\n output: string;\n onBuildEnd?: (\n cartridgeContent: string,\n transpiledSource: {lua: string; polyfillOutput: string}\n ) => void;\n onBuildError?: (errors: string) => void;\n};\n\nexport const watchPlugin = (options: WatchPluginOptions): Plugin => ({\n name: \"watcher\",\n setup(build) {\n build.onEnd(async (result: BuildResult) => {\n const {onBuildEnd, onBuildError, config, output} = options;\n\n const {jsOutput, spritesheetImagePath} = config;\n\n if (result.errors.length) {\n const errors = result.errors.map((error) => error.text).join(\"\\n\");\n onBuildError?.(errors);\n\n return;\n }\n\n console.clear();\n\n const jsContent = fs.readFileSync(jsOutput, \"utf-8\");\n const transpiledSource = transpile(jsContent, config);\n const cartridgeSections = getPicoSectionsFromCartridge(output);\n const gfxSection = await getSpritesheetFromImage(spritesheetImagePath);\n\n const cartridgeContent = generateCartridgeContent({\n ...cartridgeSections,\n lua: transpiledSource.lua,\n gfx: gfxSection\n });\n\n onBuildEnd?.(cartridgeContent, transpiledSource);\n });\n }\n});\n", "import fs from \"fs\";\nimport path from \"path\";\nimport type {PicoSections} from \"./types.js\";\n\nexport function generateCartridgeContent({\n lua = \"\",\n gff = \"\",\n gfx = \"\",\n music = \"\",\n map = \"\",\n sfx = \"\"\n}: Partial<PicoSections> = {}) {\n return [\n \"pico-8 cartridge // http://www.pico-8.com\",\n \"version 42\",\n \"__lua__\",\n lua,\n gfx && `__gfx__\\n${gfx}`,\n gff && `__gff__\\n${gff}`,\n map && `__map__\\n${map}`,\n sfx && `__sfx__\\n${sfx}`,\n music && `__music__\\n${music}`,\n \"\\n\"\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nexport function getPicoSectionsFromCartridge(\n cartridgePath: string\n): PicoSections {\n try {\n const resolvedCartridgePath = path.resolve(cartridgePath);\n const content = fs.existsSync(resolvedCartridgePath)\n ? fs.readFileSync(resolvedCartridgePath, \"utf8\")\n : \"\";\n return parsePico8Cartridge(content);\n } catch (error) {\n throw new Error(\n `Failed to read cartridge at ${cartridgePath}: ${(error as Error).message}`\n );\n }\n}\n\nfunction parsePico8Cartridge(content: string): PicoSections {\n const cartridgeSections: PicoSections = {\n lua: \"\",\n gff: \"\",\n gfx: \"\",\n music: \"\",\n map: \"\",\n sfx: \"\"\n };\n\n // Extract the contents of each section\n const regex = /__(\\w+)__\\n([\\s\\S]*?)(?=\\n__\\w+__\\n|\\n(\\n|$))/g;\n // /__(\\w+)__\\r?\\n([\\s\\S]*?)(?=__\\w+__|\\s*$)/g;\n\n let result;\n while ((result = regex.exec(content)) !== null) {\n const [, section, content] = result;\n cartridgeSections[section as keyof PicoSections] = content;\n }\n\n return cartridgeSections;\n}\n", "import fs from \"fs\";\nimport pngjs from \"pngjs\";\nimport {PICO8_PALETTE} from \"./constants.js\";\n\nconst spritesheetWidth = 128;\nconst spritesheetHeight = 128;\nconst hexBase = 16;\nconst pixelDataSize = 4; // red + green + blue + alpha\n\nconst toClosestColor = (pixels: Buffer) => (_: any, offset: number) => {\n const pixelOffset = offset * pixelDataSize;\n const pixel = {\n r: pixels[pixelOffset],\n g: pixels[pixelOffset + 1],\n b: pixels[pixelOffset + 2]\n };\n\n let minDistance = Number.MAX_VALUE;\n let closestPaletteColor = 0;\n PICO8_PALETTE.forEach(\n (color: {r: number; g: number; b: number}, i: number) => {\n const diff =\n (color.r - pixel.r) ** 2 +\n (color.g - pixel.g) ** 2 +\n (color.b - pixel.b) ** 2;\n\n if (diff < minDistance) {\n minDistance = diff;\n closestPaletteColor = i;\n }\n }\n );\n\n return closestPaletteColor.toString(hexBase);\n};\n\nexport function getSpritesheetFromImage(imagePath: string): Promise<string> {\n if (!imagePath) {\n throw new Error(\"Image path is missing\");\n }\n\n const stream = fs.createReadStream(imagePath).pipe(new pngjs.PNG());\n\n return new Promise((resolve) =>\n stream.on(\"parsed\", () => {\n if (\n stream.width !== spritesheetWidth ||\n stream.height !== spritesheetHeight\n ) {\n throw new Error(\"The spritesheet must be a 128x128 png image\");\n }\n\n const pixels = new Array(stream.width * stream.height)\n .fill(0)\n .map(toClosestColor(stream.data));\n\n const pixelsAsString = new Array(stream.height)\n .fill(0)\n .map((_: any, offset) =>\n // cut the strings so we get stacks of 128 characters\n pixels\n .slice(\n offset * spritesheetWidth,\n offset * spritesheetWidth + spritesheetWidth\n )\n .join(\"\")\n )\n .join(\"\\n\");\n\n resolve(pixelsAsString);\n })\n );\n}\n", "export const JSPICL_BANNER = `--[[\ngenerated with jspicl,\na javascript to pico-8 lua\ntranspiler.\n\nplease report any bugs at:\nhttps://github.com/jspicl/jspicl/issues\n]]--\n`;\n\nexport const PICO8_PALETTE = [\n {\n r: 0,\n g: 0,\n b: 0\n },\n {\n r: 29,\n g: 43,\n b: 83\n },\n {\n r: 126,\n g: 37,\n b: 83\n },\n {\n r: 0,\n g: 135,\n b: 81\n },\n {\n r: 171,\n g: 82,\n b: 54\n },\n {\n r: 95,\n g: 87,\n b: 79\n },\n {\n r: 194,\n g: 195,\n b: 199\n },\n {\n r: 255,\n g: 241,\n b: 232\n },\n {\n r: 255,\n g: 0,\n b: 77\n },\n {\n r: 255,\n g: 163,\n b: 0\n },\n {\n r: 255,\n g: 236,\n b: 39\n },\n {\n r: 0,\n g: 228,\n b: 54\n },\n {\n r: 41,\n g: 173,\n b: 255\n },\n {\n r: 131,\n g: 118,\n b: 156\n },\n {\n r: 255,\n g: 119,\n b: 168\n },\n {\n r: 255,\n g: 204,\n b: 170\n }\n];\n", "import {jspicl} from \"@jspicl/core\";\nimport {JSPICL_BANNER} from \"./constants.js\";\nimport type {Config} from \"./types.js\";\n\nexport function transpile(javascriptCode: string, config: Config) {\n const {includeBanner, polyfillTransform, jspicl: jspiclOptions = {}} = config;\n\n const jspiclBanner = (includeBanner && `${JSPICL_BANNER}`) || \"\";\n\n const {code, polyfills} = jspicl(javascriptCode, jspiclOptions);\n const polyfillOutput = polyfillTransform\n ? polyfillTransform(polyfills)\n : Object.values(polyfills).join(\"\\n\");\n\n const lua = `${jspiclBanner}${polyfillOutput}${code}`;\n\n return {\n lua,\n polyfillOutput\n };\n}\n"],
5
- "mappings": "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",
6
- "names": ["path", "process", "path", "path", "tokens", "stats", "path", "path", "fs", "fs", "path", "content", "fs", "fs", "fs", "process", "path"]
3
+ "sources": ["../src/index.ts", "../src/arguments.ts", "../src/logging.ts", "../src/tokenCounter.ts", "../src/esbuildPlugins/buildPlugin.ts", "../src/cartridge.ts", "../src/spritesheet.ts", "../src/constants.ts", "../src/transpile.ts", "../src/esbuildPlugins/hotReloadPlugin.ts", "../src/createPico8Launcher.ts"],
4
+ "sourcesContent": ["import yargs from \"yargs\";\nimport {hideBin} from \"yargs/helpers\";\n\nimport path from \"node:path\";\n\nimport process from \"process\";\n\nimport esbuild, {type BuildOptions, type Plugin} from \"esbuild\";\nimport {cliArguments} from \"./arguments.js\";\nimport {logError, logInfo, logStats, logSuccess, logToFile} from \"./logging.js\";\nimport type {CommandLineOptions} from \"./types.js\";\nimport {buildPlugin} from \"./esbuildPlugins/buildPlugin.js\";\nimport {hotReloadPlugin} from \"./esbuildPlugins/hotReloadPlugin.js\";\nimport chokidar from \"chokidar\";\n\nasync function getCommandlineArguments(): Promise<{\n input: string;\n output: string;\n options: CommandLineOptions;\n}> {\n const argv = await yargs(hideBin(process.argv))\n .options(cliArguments)\n .usage(\"jspicl-cli input output [<args>]\")\n .demandCommand(2, \"Please specify an input and output file\")\n .help(false)\n .strict()\n .wrap(null)\n .parseAsync();\n\n const {\n _: [input, output],\n ...restArguments\n } = argv;\n\n return {\n input: path.resolve(input.toString()),\n output: path.resolve(output.toString()),\n options: restArguments as CommandLineOptions\n };\n}\n\nexport async function startBuildService(\n input: string,\n output: string,\n cliOptions: CommandLineOptions\n) {\n const {watch, config} = cliOptions;\n const {jsOutput} = config;\n\n const buildConfig: BuildOptions = {\n entryPoints: [input],\n bundle: true,\n platform: \"neutral\",\n treeShaking: false,\n minify: config.minify,\n format: \"esm\",\n outfile: jsOutput,\n plugins: [\n buildPlugin({\n config,\n output,\n\n onBuildError: (errors) => {\n logError(`Build failed with errors:\\n${errors}`);\n },\n\n onBuildEnd: (cartridgeContent, transpiledSource) => {\n logSuccess(\"Build completed\");\n\n config.luaOutput && logToFile(transpiledSource.lua, config.luaOutput);\n\n // Statistics\n config.showStats &&\n logStats(\n transpiledSource.lua,\n transpiledSource.polyfillOutput,\n cartridgeContent\n );\n }\n }),\n watch &&\n hotReloadPlugin({\n config,\n output\n })\n ].filter(Boolean) as Plugin[]\n };\n\n if (watch) {\n const context = await esbuild.context(buildConfig);\n\n // Rebuild if the spritesheet is changed, since it's not part of the esbuild graph\n chokidar.watch(config.spritesheetImagePath).on(\"change\", async () => {\n await context.rebuild();\n });\n\n await context.watch();\n } else {\n await esbuild.build(buildConfig);\n }\n}\n\nasync function runCLI() {\n const {input, output, options} = await getCommandlineArguments();\n\n process.on(\"SIGINT\", () => {\n logInfo(\"Shutting down...\");\n process.exit(0);\n });\n\n try {\n await startBuildService(input, output, options);\n } catch (error) {\n logError(String(error));\n throw error;\n }\n}\n\nrunCLI();\n", "import path from \"node:path\";\nimport type {Options} from \"yargs\";\nimport type {CommandLineOptions, Config} from \"./types.js\";\n\nexport const cliArguments: Record<keyof CommandLineOptions, Options> = {\n watch: {\n description: \"Reload cartridge on rebuilds\",\n type: \"boolean\",\n default: false,\n alias: \"w\"\n },\n config: {\n description: \"Path to a config file\",\n type: \"string\",\n alias: \"c\",\n requiresArg: true,\n default: {\n jsOutput: \"build/jsOutput.js\"\n } as Config,\n coerce: async (configPath: string) => {\n const configDir = path.dirname(configPath);\n const configModule = await import(path.resolve(configPath));\n\n const config: Config = configModule.default;\n\n config.jsOutput = path.resolve(configDir, config.jsOutput);\n if (config.luaOutput) {\n config.luaOutput = path.resolve(configDir, config.luaOutput);\n }\n\n if (config.spritesheetImagePath) {\n config.spritesheetImagePath = path.resolve(\n configDir,\n config.spritesheetImagePath\n );\n }\n\n return config;\n }\n }\n};\n", "import fs from \"node:fs\";\nimport path from \"node:path\";\nimport {mkdirp} from \"mkdirp\";\nimport {getTokenCount} from \"./tokenCounter.js\";\n\nenum ICONS {\n info = \"\\x1b[34m\u2139\",\n success = \"\\x1b[32m\u2714\",\n warning = \"\\x1b[33m\u26A0\",\n error = \"\\x1b[31m\u2716\"\n}\n\nexport function logToFile(content: string, filePath: string) {\n mkdirp.sync(path.dirname(filePath));\n fs.writeFileSync(path.resolve(filePath), content);\n}\n\nexport function logInfo(content: string) {\n logToConsole(content, ICONS.info);\n}\n\nexport function logSuccess(content: string) {\n logToConsole(content, ICONS.success);\n}\n\nexport function logWarning(content: string) {\n logToConsole(content, ICONS.warning);\n}\n\nexport function logError(content: string) {\n logToConsole(content, ICONS.error);\n}\n\nfunction logToConsole(content: string, icon: string) {\n console.log(`${icon} ${content}\\x1b[0m`);\n}\n\nexport function logStats(lua: string, polyfillOutput: string, code: string) {\n const tokens = getTokenCount(lua);\n const polyfillTokens = getTokenCount(polyfillOutput);\n\n logInfo(\"Cartridge Statistics\");\n console.log(\"\".padEnd(41, \"\u2014\"));\n\n const stats = [\n {\n label: \"Characters\",\n value: lua.length,\n percent: `${~~((lua.length * 100) / 65535)}%`\n },\n {\n label: \"Tokens\",\n value: `~${tokens}`,\n percent: `${~~((tokens * 100) / 8192)}%`\n },\n {\n label: \" - Polyfills\",\n value: `~${polyfillTokens}`\n },\n {\n label: \"Filesize\",\n value: `${Math.ceil(code.length / 1024)} KB`\n }\n ];\n\n stats.forEach((stats) => {\n const label = `${stats.label}:`.padEnd(20, \" \");\n const value = `${stats.value}`.padStart(15, \" \");\n const percent = stats.percent\n ? `\\x1b[33m${stats.percent}`.padStart(10, \" \")\n : \"\";\n\n console.log(`${label}${value}${percent}\\x1b[0m`);\n });\n}\n", "// Each token is a word (e.g. variable name) or operator.\n// Pairs of brackets, and strings count as 1 token.\n// Commas, periods, LOCALs, semi-colons, ENDs, and comments are not counted.\nconst tokens = [\n /\\\"[^\\\"]*\\\"/, // Strings\n /\\d+\\.\\d+/, // floating numbers\n /\\w+/, // words\n /\\d+/, // numbers\n\n /!=/, // inequality\n /==/, // comparison\n /\\+=/, // incrementing assignment\n /-=/, // decrementing assignment\n /<=/, // equal or less than\n />=/, // equal or greater than\n /\\.\\./, // string concatenation\n\n /</, // less than\n />/, // greater than\n /\\+/, // addition\n /-/, // subtraction\n /\\//, // division\n /\\*/, // multiplication\n /=/, // equals\n /\\%/, // percentage\n /\\(/, // paranthesis\n /\\[/, // left bracket\n /\\{/ // left curly brace\n]\n .map((r) => r.source)\n .join(\"|\");\n\n/** Calculates the token count for the passed in Lua code*/\nexport function getTokenCount(luaCode: string) {\n const regex = new RegExp(`(${tokens})`, \"gi\");\n\n return (luaCode.match(regex) || []).filter(\n (token) => token !== \"local\" && token !== \"end\"\n ).length;\n}\n", "import type {BuildResult, Plugin} from \"esbuild\";\nimport fs from \"node:fs\";\nimport {\n generateCartridgeContent,\n getPicoSectionsFromCartridge\n} from \"../cartridge.js\";\nimport {getSpritesheetFromImage} from \"../spritesheet.js\";\nimport {transpile} from \"../transpile.js\";\nimport type {Config} from \"../types.js\";\nimport {logToFile} from \"../logging.js\";\n\ntype BuildPluginOptions = {\n config: Config;\n output: string;\n onBuildEnd?: (\n cartridgeContent: string,\n transpiledSource: {lua: string; polyfillOutput: string}\n ) => void;\n onBuildError?: (errors: string) => void;\n};\n\nexport const buildPlugin = (options: BuildPluginOptions): Plugin => ({\n name: \"buildPlugin\",\n setup(build) {\n build.onEnd(async (result: BuildResult) => {\n const {onBuildEnd, onBuildError, config, output} = options;\n\n const {jsOutput, spritesheetImagePath} = config;\n\n if (result.errors.length) {\n const errors = result.errors.map((error) => error.text).join(\"\\n\");\n onBuildError?.(errors);\n\n return;\n }\n\n console.clear();\n\n const jsContent = fs.readFileSync(jsOutput, \"utf-8\");\n const transpiledSource = transpile(jsContent, config);\n const cartridgeSections = getPicoSectionsFromCartridge(output);\n const gfxSection = await getSpritesheetFromImage(spritesheetImagePath);\n\n const cartridgeContent = generateCartridgeContent({\n ...cartridgeSections,\n lua: transpiledSource.lua,\n gfx: gfxSection\n });\n\n logToFile(cartridgeContent, output);\n\n onBuildEnd?.(cartridgeContent, transpiledSource);\n });\n }\n});\n", "import fs from \"fs\";\nimport type {PicoSections} from \"./types.js\";\n\nexport function generateCartridgeContent({\n lua = \"\",\n gff = \"\",\n gfx = \"\",\n music = \"\",\n map = \"\",\n sfx = \"\"\n}: Partial<PicoSections> = {}) {\n return [\n \"pico-8 cartridge // http://www.pico-8.com\",\n \"version 42\",\n \"__lua__\",\n lua,\n gfx && `__gfx__\\n${gfx}`,\n gff && `__gff__\\n${gff}`,\n map && `__map__\\n${map}`,\n sfx && `__sfx__\\n${sfx}`,\n music && `__music__\\n${music}`,\n \"\\n\"\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nexport function getPicoSectionsFromCartridge(\n cartridgePath: string\n): PicoSections {\n try {\n const content = fs.existsSync(cartridgePath)\n ? fs.readFileSync(cartridgePath, \"utf8\")\n : \"\";\n return parsePico8Cartridge(content);\n } catch (error) {\n throw new Error(\n `Failed to read cartridge at ${cartridgePath}: ${(error as Error).message}`\n );\n }\n}\n\nfunction parsePico8Cartridge(content: string): PicoSections {\n const cartridgeSections: PicoSections = {\n lua: \"\",\n gff: \"\",\n gfx: \"\",\n music: \"\",\n map: \"\",\n sfx: \"\"\n };\n\n // Extract the contents of each section\n const regex = /__(\\w+)__\\n([\\s\\S]*?)(?=\\n__\\w+__\\n|\\n(\\n|$))/g;\n // /__(\\w+)__\\r?\\n([\\s\\S]*?)(?=__\\w+__|\\s*$)/g;\n\n let result;\n while ((result = regex.exec(content)) !== null) {\n const [, section, content] = result;\n cartridgeSections[section as keyof PicoSections] = content;\n }\n\n return cartridgeSections;\n}\n", "import fs from \"fs\";\nimport pngjs from \"pngjs\";\nimport {PICO8_PALETTE} from \"./constants.js\";\n\nconst spritesheetWidth = 128;\nconst spritesheetHeight = 128;\nconst hexBase = 16;\nconst pixelDataSize = 4; // red + green + blue + alpha\n\nconst toClosestColor = (pixels: Buffer) => (_: any, offset: number) => {\n const pixelOffset = offset * pixelDataSize;\n const pixel = {\n r: pixels[pixelOffset],\n g: pixels[pixelOffset + 1],\n b: pixels[pixelOffset + 2]\n };\n\n let minDistance = Number.MAX_VALUE;\n let closestPaletteColor = 0;\n PICO8_PALETTE.forEach(\n (color: {r: number; g: number; b: number}, i: number) => {\n const diff =\n (color.r - pixel.r) ** 2 +\n (color.g - pixel.g) ** 2 +\n (color.b - pixel.b) ** 2;\n\n if (diff < minDistance) {\n minDistance = diff;\n closestPaletteColor = i;\n }\n }\n );\n\n return closestPaletteColor.toString(hexBase);\n};\n\nexport function getSpritesheetFromImage(imagePath: string): Promise<string> {\n if (!imagePath) {\n throw new Error(\"Image path is missing\");\n }\n\n const stream = fs.createReadStream(imagePath).pipe(new pngjs.PNG());\n\n return new Promise((resolve) =>\n stream.on(\"parsed\", () => {\n if (\n stream.width !== spritesheetWidth ||\n stream.height !== spritesheetHeight\n ) {\n throw new Error(\"The spritesheet must be a 128x128 png image\");\n }\n\n const pixels = new Array(stream.width * stream.height)\n .fill(0)\n .map(toClosestColor(stream.data));\n\n const pixelsAsString = new Array(stream.height)\n .fill(0)\n .map((_: any, offset) =>\n // cut the strings so we get stacks of 128 characters\n pixels\n .slice(\n offset * spritesheetWidth,\n offset * spritesheetWidth + spritesheetWidth\n )\n .join(\"\")\n )\n .join(\"\\n\");\n\n resolve(pixelsAsString);\n })\n );\n}\n", "export const JSPICL_BANNER = `--[[\ngenerated with jspicl,\na javascript to pico-8 lua\ntranspiler.\n\nplease report any bugs at:\nhttps://github.com/jspicl/jspicl/issues\n]]--\n`;\n\nexport const PICO8_PALETTE = [\n {\n r: 0,\n g: 0,\n b: 0\n },\n {\n r: 29,\n g: 43,\n b: 83\n },\n {\n r: 126,\n g: 37,\n b: 83\n },\n {\n r: 0,\n g: 135,\n b: 81\n },\n {\n r: 171,\n g: 82,\n b: 54\n },\n {\n r: 95,\n g: 87,\n b: 79\n },\n {\n r: 194,\n g: 195,\n b: 199\n },\n {\n r: 255,\n g: 241,\n b: 232\n },\n {\n r: 255,\n g: 0,\n b: 77\n },\n {\n r: 255,\n g: 163,\n b: 0\n },\n {\n r: 255,\n g: 236,\n b: 39\n },\n {\n r: 0,\n g: 228,\n b: 54\n },\n {\n r: 41,\n g: 173,\n b: 255\n },\n {\n r: 131,\n g: 118,\n b: 156\n },\n {\n r: 255,\n g: 119,\n b: 168\n },\n {\n r: 255,\n g: 204,\n b: 170\n }\n];\n\nexport const EMPTY_CART_DATA = `0000000000000000000000000000000000000000000000000000000000000000\n0000000000000000000000000000000000000000000000000000000000000000\n0000000000000000000000000000000000000000000000000000000000000000\n0000000000000000000000000000000000000000000000000000000000000000\n0000000000000000000000000000000000000000000000000000000000000000\n0000000000000000000000000000000000000000000000000000000000000000\n0000000000000000000000000000000000000000000000000000000000000000\n0000000000000000000000000000000000000000000000000000000000000000`;\n", "import {jspicl} from \"@jspicl/core\";\nimport {JSPICL_BANNER} from \"./constants.js\";\nimport type {Config} from \"./types.js\";\n\nexport function transpile(javascriptCode: string, config: Config) {\n const {includeBanner, polyfillTransform, jspiclOptions} = config;\n\n const jspiclBanner = (includeBanner && `${JSPICL_BANNER}`) || \"\";\n\n const {code, polyfills} = jspicl(javascriptCode, jspiclOptions);\n const polyfillOutput = polyfillTransform\n ? polyfillTransform(polyfills)\n : Object.values(polyfills).join(\"\\n\");\n\n const lua = `${jspiclBanner}${polyfillOutput}${code}`;\n\n return {\n lua,\n polyfillOutput\n };\n}\n", "import type {Plugin, PluginBuild} from \"esbuild\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport {createPico8Launcher} from \"../createPico8Launcher.js\";\nimport type {Config} from \"../types.js\";\nimport {logToFile} from \"../logging.js\";\n\ntype HotReloadPluginOptions = {\n config: Config;\n output: string;\n};\n\nexport const hotReloadPlugin = (options: HotReloadPluginOptions): Plugin => ({\n name: \"hotReloadPlugin\",\n setup: function (build: PluginBuild): void | Promise<void> {\n const runPico = createPico8Launcher(\n options.config.picoOptions,\n options.config.pipeOutputToConsole\n );\n\n build.onEnd(async () => {\n const {output} = options;\n\n // Brute force hotreload injection\n const hotReloadScript = `\nlocal shouldreload = false\nfunction hotreload()\n cartdata(\"${options.config.picoOptions?.cartDataId || \"jspicl_hotreload\"}\")\n shouldreload=peek(0x5eff - 3) == 1\n if shouldreload then\n poke(0x5eff - 3, 0)\n load(\"${path.basename(output)}\")\n end\nend`;\n\n const content = fs.readFileSync(output, \"utf-8\");\n\n const newContent = content\n .replace(\"__lua__\", `__lua__\\n${hotReloadScript}`)\n .replace(\"function _draw()\", `function _draw()\\n hotreload()`);\n\n logToFile(newContent, output);\n\n runPico(output);\n });\n }\n});\n", "import {ChildProcess, spawn} from \"child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport untildify from \"untildify\";\nimport {logError, logSuccess, logWarning} from \"./logging.js\";\nimport type {\n PicoOptions,\n PicoOptionsMatrix,\n SupportedPlatforms\n} from \"./types.js\";\nimport {EMPTY_CART_DATA} from \"./constants.js\";\n\nconst osMatrix: PicoOptionsMatrix = {\n win32: {\n executablePath: `\"C:\\\\Program Files (x86)\\\\PICO-8\\\\pico8.exe\"`\n },\n darwin: {\n executablePath: \"/Applications/PICO-8.app/Contents/MacOS/pico8\",\n cartDataPath: untildify(\"~/Library/Application Support/pico-8/cdata/\")\n },\n linux: {\n executablePath: untildify(\"~/pico-8/pico8\"),\n cartDataPath: untildify(\"~/.lexaloffle/pico-8/cdata/\")\n }\n};\n\nexport function createPico8Launcher(\n picoOptions?: PicoOptions,\n pipeOutputToConsole?: boolean\n) {\n const platform = process.platform as SupportedPlatforms;\n let picoProcess: ChildProcess | null;\n const {\n executablePath,\n cartDataPath,\n cartDataId = \"jspicl_hotreload\"\n } = {\n ...osMatrix[platform],\n ...picoOptions\n };\n\n return (cartridgePath: string) => {\n if (!executablePath) {\n logError(\n `PICO-8 executable not found. Please install PICO-8 or set the executablePath option. Default path for your OS: ${osMatrix[platform].executablePath}`\n );\n return;\n }\n\n if (!cartridgePath) {\n logError(\"No cartridge path provided\");\n return;\n }\n\n if (picoProcess) {\n if (!cartDataPath) {\n logWarning(\n \"Autoreloading is currently not supported on your OS. Please press Ctrl+R in PICO-8 to see the new changes.\"\n );\n return;\n }\n\n if (!fs.existsSync(cartDataPath)) {\n logWarning(\n \"Unable to reload cartridge in PICO-8 since the cartridge data path does not exist or is inaccessible. Please press Ctrl+R in PICO-8 to see the new changes.\"\n );\n return;\n }\n\n const cartDataFilePath = path.resolve(\n cartDataPath,\n `${cartDataId}.p8d.txt`\n );\n\n const cartDataContent = fs.existsSync(cartDataFilePath)\n ? fs.readFileSync(\n path.resolve(cartDataPath, `${cartDataId}.p8d.txt`),\n \"utf-8\"\n )\n : EMPTY_CART_DATA;\n\n fs.writeFileSync(\n cartDataFilePath,\n cartDataContent.slice(0, 64 * 8 + 8 - 2) + \"1\"\n );\n logSuccess(\"Reloading cartridge in PICO-8\");\n } else {\n logSuccess(\"Running cartridge in PICO-8\");\n\n picoProcess = launchPico8(\n executablePath,\n cartridgePath,\n pipeOutputToConsole\n );\n\n picoProcess.on(\"close\", (errorCode) => {\n if (errorCode !== 0) {\n logWarning(`PICO-8 process exited with code ${errorCode}`);\n }\n picoProcess = null;\n });\n }\n };\n}\n\nfunction launchPico8(\n picoPath: string,\n cartridgePath: string,\n pipeOutputToConsole?: boolean\n) {\n return spawn(\n picoPath,\n [\n \"-run\",\n `\"${cartridgePath}\"`,\n \"-root_path\",\n `\"${path.dirname(cartridgePath)}\"`\n ],\n {\n shell: true,\n stdio: pipeOutputToConsole ? \"inherit\" : \"pipe\"\n }\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["path", "process", "path", "path", "tokens", "stats", "fs", "fs", "content", "fs", "fs", "fs", "path", "fs", "fs", "path", "fs", "path", "path", "fs", "process", "path"]
7
7
  }
package/dist/types.d.ts CHANGED
@@ -7,17 +7,24 @@ export interface PicoSections extends Record<string, string> {
7
7
  map: string;
8
8
  sfx: string;
9
9
  }
10
+ export interface PicoOptions {
11
+ executablePath?: string;
12
+ cartDataPath?: string;
13
+ cartDataId?: string;
14
+ }
15
+ export type SupportedPlatforms = "win32" | "darwin" | "linux";
16
+ export type PicoOptionsMatrix = Record<SupportedPlatforms, PicoOptions>;
10
17
  export interface Config {
11
18
  spritesheetImagePath: string;
12
19
  jsOutput: string;
13
- picoPath?: string;
14
20
  includeBanner?: boolean;
15
21
  luaOutput?: string;
22
+ minify?: boolean;
16
23
  pipeOutputToConsole?: boolean;
17
24
  polyfillTransform?: (polyfills: Record<string, string>) => string;
18
- reloadOnSave?: boolean;
19
25
  showStats?: boolean;
20
- jspicl?: JspiclOptions;
26
+ picoOptions?: PicoOptions;
27
+ jspiclOptions?: JspiclOptions;
21
28
  }
22
29
  export interface CommandLineOptions {
23
30
  watch: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jspicl/cli",
3
- "version": "4.0.0-alpha.2",
3
+ "version": "4.0.0-alpha.4",
4
4
  "description": "CLI for simplifying PICO-8 game development in JavaScript",
5
5
  "author": "Agron Kabashi",
6
6
  "license": "MIT",
@@ -58,17 +58,18 @@
58
58
  "@types/yargs": "^17.0.33"
59
59
  },
60
60
  "dependencies": {
61
- "@jspicl/core": "^4.0.0-alpha.2",
61
+ "@jspicl/core": "^4.0.0-alpha.4",
62
62
  "chokidar": "^5.0.0",
63
63
  "esbuild": "^0.25.0",
64
64
  "lodash.debounce": "^4.0.8",
65
65
  "mkdirp": "^3.0.1",
66
66
  "pngjs": "^7.0.0",
67
67
  "typescript": "^5.7.0",
68
+ "untildify": "^6.0.0",
68
69
  "yargs": "^18.0.0"
69
70
  },
70
71
  "engines": {
71
72
  "node": ">=22"
72
73
  },
73
- "stableVersion": "4.0.0-alpha.1"
74
+ "stableVersion": "4.0.0-alpha.4"
74
75
  }