buninu 0.1.1 → 0.1.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ ## 0.1.3 - 2026-08-16
4
+
5
+ ### Fixed
6
+
7
+ - Preserve a single canonical child-process path variable: `Path` on Windows
8
+ and `PATH` on other platforms. This ensures the Buninu `bin` directory is
9
+ available inside the shell started by jsgotty on Windows.
10
+ - Keep the jsgotty reconnect overlay clickable in WebGL mode by placing it
11
+ above the canvas and preventing Kitty image pointer handling from intercepting
12
+ its mouse and touch events.
13
+
14
+ ### Changed
15
+
16
+ - Enable jsmdcui's mdcui encoding from the Unix and Windows launchers only when
17
+ at least one command-line argument is a `.md` file. Launching without a
18
+ Markdown file now retains the editor-first behavior.
@@ -3,6 +3,10 @@
3
3
  [中文 README](README.md)
4
4
 
5
5
  ## News
6
+ ### 2026/08/16
7
+ - Fixed the disconnected-screen `Reconnect` button not being clickable in WebGL mode.
8
+ - The `Reconnect` UI now stays above the WebGL canvas and receives mouse and touch events correctly; Kitty image handling no longer intercepts right-click / long-press for entering a reconnect token or PID.
9
+
6
10
  ### 2026/07/03 - [1.1.0]
7
11
  - Unicode 11 from upstream
8
12
  - WebGL support by `--webgl` and query args
@@ -3,6 +3,10 @@
3
3
  [English README](README.en.md)
4
4
 
5
5
  ## News
6
+ ### 2026/08/16
7
+ - 修正 WebGL 模式下斷線畫面的 `Reconnect` 按鈕無法點擊。
8
+ - `Reconnect` 介面現在會正確位於 WebGL canvas 上方並接收滑鼠與觸控事件;右鍵/長按輸入 reconnect token 或 PID 也不會被 Kitty 圖片事件攔截。
9
+
6
10
  ### 2026/07/03 - [1.1.0]
7
11
  - Unicode 11 from upstream
8
12
  - WebGL support by `--webgl` & query args
@@ -17,6 +17,8 @@
17
17
  user-select: none;
18
18
  transition: opacity 180ms ease-in;
19
19
  text-align: center;
20
+ z-index: 10;
21
+ pointer-events: auto;
20
22
  }
21
23
 
22
24
  .xterm-overlay-button {
@@ -29,4 +31,5 @@
29
31
  color: white;
30
32
  font: inherit;
31
33
  cursor: pointer;
34
+ pointer-events: auto;
32
35
  }
@@ -763,6 +763,9 @@
763
763
  if (state.contextMenu && state.contextMenu.root.contains(event.target)) {
764
764
  return;
765
765
  }
766
+ if (event.target instanceof Element && event.target.closest(".xterm-overlay")) {
767
+ return;
768
+ }
766
769
  const key = placementAtPoint(event.clientX, event.clientY);
767
770
  if (!key) {
768
771
  return;
@@ -2,4 +2,10 @@
2
2
 
3
3
  sd=$(dirname "$(realpath "$0")")
4
4
 
5
- exec bun "$sd"/tui --mdcui "$@"
5
+ for arg do
6
+ case "$arg" in
7
+ *.[mM][dD]) exec bun "$sd"/tui --mdcui "$@" ;;
8
+ esac
9
+ done
10
+
11
+ exec bun "$sd"/tui "$@"
package/bin/bun.bat ADDED
@@ -0,0 +1,37 @@
1
+ @echo off
2
+ setlocal EnableExtensions EnableDelayedExpansion
3
+
4
+ set "BUNINU_BUN_ARCHIVE=%~dp0..\apps\bun\bunBin.tgz"
5
+ set "BUNINU_BUN_WX=%~dp0bun-wx.exe"
6
+ set "BUNINU_EXTRACT_BUN="
7
+
8
+ if exist "%BUNINU_BUN_ARCHIVE%" (
9
+ if not exist "%BUNINU_BUN_WX%" set "BUNINU_EXTRACT_BUN=1"
10
+
11
+ if exist "%BUNINU_BUN_WX%" if exist "%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" (
12
+ for /f "delims=" %%U in ('"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -NonInteractive -Command "if ((Get-Item -LiteralPath $env:BUNINU_BUN_ARCHIVE).LastWriteTimeUtc -gt (Get-Item -LiteralPath $env:BUNINU_BUN_WX).LastWriteTimeUtc) { '1' }"') do set "BUNINU_EXTRACT_BUN=%%U"
13
+ )
14
+ )
15
+
16
+ if defined BUNINU_EXTRACT_BUN (
17
+ tar -xzf "%BUNINU_BUN_ARCHIVE%" -C "%~dp0"
18
+ if errorlevel 1 (
19
+ echo Failed to extract Bun archive: %BUNINU_BUN_ARCHIVE% 1>&2
20
+ exit /b 1
21
+ )
22
+ )
23
+
24
+ if exist "%~dp0bun-wx.exe" (
25
+ "%~dp0bun-wx.exe" %*
26
+ exit /b !ERRORLEVEL!
27
+ )
28
+
29
+ for /f "delims=" %%B in ('where bun.exe 2^>nul') do (
30
+ if /I not "%%~dpB"=="%~dp0" (
31
+ "%%~fB" %*
32
+ exit /b !ERRORLEVEL!
33
+ )
34
+ )
35
+
36
+ echo Bun Binary not found: %~dp0bun-wx.exe ^(and no external bun.exe found in PATH^) 1>&2
37
+ exit /b 127
package/bin/glow.bat ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+ call "%~dp0bun.bat" "%~dp0..\apps\jsmdcui\tui" --cat %*
3
+ exit /b %ERRORLEVEL%
package/bin/init.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
3
  import pkg from "../package.json" with { type: "json" };
4
- import { existsSync, mkdirSync } from "node:fs";
4
+ import { existsSync, lstatSync, mkdirSync, symlinkSync, unlinkSync } from "node:fs";
5
5
  import { tmpdir as systemTmpDir } from "node:os";
6
6
  import { basename, delimiter, dirname, isAbsolute, resolve } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
@@ -25,6 +25,7 @@ Init options:
25
25
  -h, --help Show this help and exit
26
26
  -V, --version Show version and runtime information, then exit
27
27
  --readme Render README.md in the terminal and exit
28
+ --changelog Render CHANGELOG.md in the terminal and exit
28
29
  --shell <path|name> Override buninu.shell for this run
29
30
  --command <command> Override buninu.command for this run
30
31
 
@@ -62,6 +63,15 @@ async function handleInformationArguments(arguments_) {
62
63
  return true;
63
64
  }
64
65
 
66
+ if (arguments_.includes("--changelog")) {
67
+ const changelogPath = resolve(REPO_ROOT, "CHANGELOG.md");
68
+ if (!await pathExists(changelogPath)) fail(`CHANGELOG not found: ${changelogPath}`);
69
+ const markdown = await Bun.file(changelogPath).text();
70
+ process.stdout.write(Bun.markdown.ansi(markdown, { hyperlinks: true }));
71
+ if (!markdown.endsWith("\n")) process.stdout.write("\n");
72
+ return true;
73
+ }
74
+
65
75
  return false;
66
76
  }
67
77
 
@@ -109,7 +119,8 @@ async function findCommand(command) {
109
119
 
110
120
  async function detectEnvironment() {
111
121
  const windows = process.platform === "win32" || Boolean(process.env.WINDIR);
112
- const android = !windows && (
122
+ const termux = !windows && await pathExists("/data/data/com.termux");
123
+ const android = !windows && !termux && (
113
124
  process.platform === "android" ||
114
125
  await pathExists("/system/bin/linker64") ||
115
126
  Boolean(process.env.ANDROID_ROOT && process.env.ANDROID_DATA)
@@ -127,6 +138,17 @@ async function detectEnvironment() {
127
138
  };
128
139
  }
129
140
 
141
+ if (termux) {
142
+ return {
143
+ name: "linux",
144
+ shell:
145
+ await findCommand(process.env.SHELL) ||
146
+ Bun.which("bash") ||
147
+ Bun.which("sh") ||
148
+ "/bin/sh",
149
+ };
150
+ }
151
+
130
152
  if (android) {
131
153
  return {
132
154
  name: "android",
@@ -200,6 +222,42 @@ async function runPlatformSwitch(environment) {
200
222
  }
201
223
  }
202
224
 
225
+ function rebuildNativeSymlinks(environment) {
226
+ if (environment.name === "windows") return;
227
+
228
+ const platformLinks = environment.name === "android"
229
+ ? {
230
+ bun: "androidNativeLibs/libbun.so",
231
+ shloader: "androidNativeLibs/libsh-loader.so",
232
+ }
233
+ : {
234
+ bun: "bun.sh",
235
+ shloader: "multicall.sh",
236
+ };
237
+ const links = {
238
+ ...platformLinks,
239
+ glow: "shloader",
240
+ jmi: "shloader",
241
+ jsgotty: "shloader",
242
+ jsmdcui: "shloader",
243
+ "musl-la": "shloader",
244
+ };
245
+
246
+ for (const [name, target] of Object.entries(links)) {
247
+ const linkPath = resolve(binDir, name);
248
+ try {
249
+ const existing = lstatSync(linkPath);
250
+ if (!existing.isSymbolicLink()) {
251
+ fail(`cannot rebuild symlink over non-symlink: ${linkPath}`);
252
+ }
253
+ unlinkSync(linkPath);
254
+ } catch (error) {
255
+ if (error?.code !== "ENOENT") throw error;
256
+ }
257
+ symlinkSync(target, linkPath);
258
+ }
259
+ }
260
+
203
261
  function getFreePort() {
204
262
  const listener = Bun.listen({
205
263
  hostname: "127.0.0.1",
@@ -242,9 +300,15 @@ async function createChildEnvironment(environment) {
242
300
  binDir,
243
301
  ].filter(Boolean);
244
302
 
303
+ const childEnvironment = { ...process.env };
304
+ for (const key of Object.keys(childEnvironment)) {
305
+ if (key.toLowerCase() === "path") delete childEnvironment[key];
306
+ }
307
+ childEnvironment[environment.name === "windows" ? "Path" : "PATH"] =
308
+ pathEntries.join(delimiter);
309
+
245
310
  return {
246
- ...process.env,
247
- PATH: pathEntries.join(delimiter),
311
+ ...childEnvironment,
248
312
  HOME: homeDir,
249
313
  TMPDIR: tmpDir,
250
314
  SHELL: process.env.SHELL || environment.shell,
@@ -332,6 +396,7 @@ if (command[0] === "bun") command[0] = process.execPath;
332
396
 
333
397
  const environment = await detectEnvironment();
334
398
  await runPlatformSwitch(environment);
399
+ rebuildNativeSymlinks(environment);
335
400
  const initArguments = readInitArguments(process.argv.slice(2));
336
401
  const configuredShell =
337
402
  pkg.buninu?.shell?.[environment.name] ??
package/bin/jmi.bat ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+ call "%~dp0bun.bat" "%~dp0..\apps\jsmdcui\tui" %*
3
+ exit /b %ERRORLEVEL%
@@ -0,0 +1,3 @@
1
+ @echo off
2
+ call "%~dp0bun.bat" "%~dp0..\apps\jsgotty\gotty.js" %*
3
+ exit /b %ERRORLEVEL%
@@ -0,0 +1,5 @@
1
+ @echo off
2
+ set "JSMDCUI_ENCODING="
3
+ for %%A in (%*) do if /I "%%~xA"==".md" set "JSMDCUI_ENCODING=--mdcui"
4
+ call "%~dp0bun.bat" "%~dp0..\apps\jsmdcui\tui" %JSMDCUI_ENCODING% %*
5
+ exit /b %ERRORLEVEL%
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buninu",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Buninu is a portable, self-bootstrapping Unix-like userspace built on Bun that runs across operating systems",
5
5
  "type": "module",
6
6
  "main": "./bin/init.js",