@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 +10 -2
- package/cli.js +3 -1
- package/msger-native/bin/msgernative-linux-aarch64 +0 -0
- package/msger-native/bin/msgernative.exe +0 -0
- package/msger-native/builder/postinstall.js +30 -0
- package/package.json +1 -1
- package/shower.js +44 -1
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
|
|
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
|
|
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>
|
|
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
|
|
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
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)
|