@bobfrankston/msger 0.1.410 → 0.1.412

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
@@ -47,9 +47,10 @@ msger -html "<h1>Welcome!</h1><p>This is <strong>HTML</strong></p>"
47
47
  # Colored text with inline styles
48
48
  msger -html "<span style='color:red;background-color:yellow'>Alert!</span>"
49
49
 
50
- # Load a URL (web page or local file)
50
+ # Load a URL (web page, local file, or a directory's index.html)
51
51
  msger -url "https://example.com"
52
52
  msger -url "file:///path/to/page.html"
53
+ msger -url ./site # serves ./site/index.html and its sibling assets
53
54
 
54
55
  # Render a local markdown file — use the mdview wrapper (msger doesn't auto-render .md)
55
56
  mdview todo.md
@@ -307,7 +308,7 @@ Options:
307
308
  -message, --message <text> Plain text message
308
309
  -title, --title <text> Window title
309
310
  -html, --html <html> HTML content
310
- -url, --url <url> URL to load (web or file://)
311
+ -url, --url <url> URL to load (web, local file, or directory → its index.html)
311
312
  -hash, --hash <fragment> Hash fragment to append to URL (requires -url). Leading # optional.
312
313
  -buttons, --buttons <labels> Button labels (e.g., -buttons Yes No Cancel)
313
314
  -ok, --ok Add OK button
@@ -359,6 +360,13 @@ Notes:
359
360
  - OK button is green by default
360
361
  - URLs default to 1024x768 window size
361
362
  - Window title automatically updates from loaded page's <title> tag when using -url
363
+ - Local pages given to -url are served from their own directory over
364
+ http://msger.localhost/ rather than file:// (file:// pages cannot use the
365
+ msgapi IPC bridge at all — WebView2 aborts on them)
366
+ - Right-click → "Copy URL" copies the address of the current page; for local
367
+ content it copies the file's path on disk
368
+ - The loaded page's favicon becomes the window + taskbar icon (Windows);
369
+ pass -icon to keep your own icon instead
362
370
  - Windows auto-size to fit content when size not specified
363
371
  - Runtime zoom: Ctrl+Wheel, Ctrl+Plus, Ctrl+Minus
364
372
  ```
package/cli.js CHANGED
@@ -20,7 +20,8 @@ Options:
20
20
  -title <text> Set window title
21
21
  -html <html> Display HTML formatted message (inline)
22
22
  -htmlfrom <file|url> Fetch HTML from file/URL and embed in template (has buttons & msger API)
23
- -url <url> Load URL directly in webview (no template, no buttons)
23
+ -url <url|file|dir> Load URL directly in webview (no template, no buttons)
24
+ A local file or directory works too; a directory loads its index.html
24
25
  -hash <fragment> Hash fragment to append to URL (requires -url). Leading # optional.
25
26
  -buttons <label...> Specify button labels (e.g., -buttons Yes No Cancel)
26
27
  -ok Add OK button
@@ -72,6 +73,7 @@ Examples:
72
73
  msger -url "https://example.com"
73
74
  msger -url "https://example.com" -hash section1
74
75
  msger -url "https://example.com" -detach
76
+ msger -url ./site # local file or directory (directory → site/index.html)
75
77
  msger -title "Alert" -message "Operation complete"
76
78
  echo -e "\\x1b[31mError:\\x1b[0m Something failed" | msger
77
79
  echo '{"message":"Test","buttons":["OK"]}' | msger
Binary file
@@ -202,6 +202,36 @@ if (!isWindows) {
202
202
  }
203
203
  }
204
204
 
205
+ // Step 5: Linux — warn now if the WebKitGTK runtime is missing.
206
+ //
207
+ // npm cannot install it for you: it's an OS package, apt needs root, and the
208
+ // package name differs per distro — so all msger can do is check and tell you.
209
+ // Without this the first run dies with a bare loader error ("libwebkit2gtk-4.1
210
+ // .so.0: cannot open shared object file", exit 127) that reads like a broken
211
+ // msger rather than a missing dependency (Bob 2026-07-31, fresh Pi 4 with a
212
+ // Lite image; a Pi with the full desktop already has it via other packages).
213
+ if (!isWindows && process.platform === "linux") {
214
+ const soNames = ["libwebkit2gtk-4.1.so.0", "libjavascriptcoregtk-4.1.so.0"];
215
+ const libDirs = [
216
+ "/usr/lib", "/usr/local/lib", "/lib",
217
+ `/usr/lib/${process.arch === "arm64" ? "aarch64" : "x86_64"}-linux-gnu`,
218
+ ];
219
+ const found = soNames.every(so =>
220
+ libDirs.some(dir => { try { return fs.existsSync(path.join(dir, so)); } catch { return false; } })
221
+ );
222
+ if (!found) {
223
+ console.log("");
224
+ console.log(" msger: WARNING — the WebKitGTK runtime was not found.");
225
+ console.log(" msger renders with the system webview and cannot");
226
+ console.log(" start without it. Install it with:");
227
+ console.log("");
228
+ console.log(" sudo apt install libwebkit2gtk-4.1-0");
229
+ console.log("");
230
+ console.log(" (runtime only; -dev is needed just to build msger)");
231
+ console.log("");
232
+ }
233
+ }
234
+
205
235
  // Friendly message about the EPERM warnings npm itself emits during a
206
236
  // subsequent global upgrade. They come from npm trying to delete its own
207
237
  // staging directory while the previously-running msgernative.exe inside
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/msger",
3
- "version": "0.1.410",
3
+ "version": "0.1.412",
4
4
  "description": "Fast, lightweight, cross-platform message box - Rust-powered alternative to msgview",
5
5
  "type": "module",
6
6
  "main": "./index.js",
package/shower.js CHANGED
@@ -72,6 +72,42 @@ export function setAppName(name) { _appName = name; }
72
72
  * provision so Rust's window icon search picks it up. Per-call `icon` in
73
73
  * `MessageBoxOptions` still takes precedence. */
74
74
  export function setAppIcon(iconPath) { _appIcon = iconPath; }
75
+ /** The Linux/Pi binary dynamically links WebKitGTK, which a Lite or trimmed
76
+ * Raspberry Pi OS image doesn't ship — the loader then fails with a bare
77
+ * "libwebkit2gtk-4.1.so.0: cannot open shared object file" and exit 127, which
78
+ * reads like a broken msger rather than a missing dependency (Bob 2026-07-31,
79
+ * fresh pi4d). Turn it into the apt line that fixes it. */
80
+ function missingWebkitHint(stderr) {
81
+ if (!/libwebkit2gtk|libjavascriptcoregtk/.test(stderr))
82
+ return '';
83
+ return '\n\nmsger needs the WebKitGTK runtime, which this system does not have.\n' +
84
+ ' sudo apt install libwebkit2gtk-4.1-0\n' +
85
+ '(runtime only — the -dev package is needed just for building msger.)';
86
+ }
87
+ /** Raspberry Pi: WebKitGTK's DMABUF rendering path is broken on the vc4/v3d
88
+ * driver — the page comes up as interlaced shredded scanlines instead of
89
+ * content (verified on a Pi 5 / Debian 13 / WebKitGTK 2.50.6 Wayland session,
90
+ * 2026-07-31). This is what "msger doesn't display properly on the Pi" was;
91
+ * setting WEBKIT_DISABLE_DMABUF_RENDERER=1 renders correctly. Scoped to the
92
+ * Pi because the DMABUF path is the faster one everywhere it works, and never
93
+ * applied when the caller has already set the variable (either way) so an
94
+ * explicit choice always wins. The Rust binary does the same for callers that
95
+ * bypass this launcher. */
96
+ function isRaspberryPi() {
97
+ if (platform() !== 'linux')
98
+ return false;
99
+ try {
100
+ return fs.readFileSync('/proc/device-tree/model', 'latin1').includes('Raspberry Pi');
101
+ }
102
+ catch {
103
+ return false;
104
+ }
105
+ }
106
+ function applyPiWebkitWorkaround(env) {
107
+ if (env.WEBKIT_DISABLE_DMABUF_RENDERER === undefined && isRaspberryPi()) {
108
+ env.WEBKIT_DISABLE_DMABUF_RENDERER = '1';
109
+ }
110
+ }
75
111
  function getUserBinDirFor(appName) {
76
112
  const isWindows = platform() === 'win32';
77
113
  if (isWindows) {
@@ -393,6 +429,7 @@ function createMessageBoxHandle(options) {
393
429
  if ('NODE_OPTIONS' in childEnv) {
394
430
  delete childEnv.NODE_OPTIONS;
395
431
  }
432
+ applyPiWebkitWorkaround(childEnv);
396
433
  // Spawn before constructing the Promise so `child` is guaranteed defined
397
434
  // by the time we hand it to MessageBoxHandle.
398
435
  const child = spawn(binaryPath, [], {
@@ -429,7 +466,7 @@ function createMessageBoxHandle(options) {
429
466
  return;
430
467
  }
431
468
  if (code !== 0) {
432
- reject(new Error(`msger exited with code ${code}: ${stderr}`));
469
+ reject(new Error(`msger exited with code ${code}: ${stderr}${missingWebkitHint(stderr)}`));
433
470
  return;
434
471
  }
435
472
  try {
@@ -691,6 +728,7 @@ export function showService(options) {
691
728
  const childEnv = { ...process.env };
692
729
  if ("NODE_OPTIONS" in childEnv)
693
730
  delete childEnv.NODE_OPTIONS;
731
+ applyPiWebkitWorkaround(childEnv);
694
732
  const child = spawn(binaryPath, [], {
695
733
  stdio: ["pipe", "pipe", "pipe"],
696
734
  env: childEnv,
@@ -698,6 +736,11 @@ export function showService(options) {
698
736
  child.stderr?.on("data", (data) => {
699
737
  // Forward Rust stderr to parent stderr (debug messages)
700
738
  process.stderr.write(data);
739
+ // Service mode never inspects the exit code, so surface the
740
+ // missing-WebKitGTK case as it happens or it stays a bare loader error.
741
+ const hint = missingWebkitHint(data.toString());
742
+ if (hint)
743
+ process.stderr.write(hint + '\n');
701
744
  });
702
745
  child.stdin?.on("error", () => { });
703
746
  // Send options as first line of stdin (Rust reads one line for options, then keeps reading)