@bobfrankston/msger 0.1.80 → 0.1.82
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/DEVELOPERS.md +265 -0
- package/README.md +233 -187
- package/msger-native/bin/msgernative.exe +0 -0
- package/msger-native/example-config.json +4 -2
- package/msger-native/src/main.rs +36 -7
- package/package.json +1 -1
package/DEVELOPERS.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# msger - Developer Guide
|
|
2
|
+
|
|
3
|
+
This document contains technical information for developers working on msger.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
@bobfrankston/msger (TypeScript wrapper)
|
|
9
|
+
↓ spawns native binary with JSON via stdin OR file + CLI args
|
|
10
|
+
@bobfrankston/msger-native (Rust binary - platform-specific)
|
|
11
|
+
↓ creates native window with webview
|
|
12
|
+
↓ displays HTML/URL content with buttons
|
|
13
|
+
↓ outputs JSON result to stdout
|
|
14
|
+
TypeScript wrapper returns Promise<MessageBoxResult>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Platform-specific binaries:**
|
|
18
|
+
- `msgernative.exe` - Windows x64 (WebView2)
|
|
19
|
+
- `msgernative` - Linux x86_64 (WebKitGTK)
|
|
20
|
+
- `msgernative-arm64` - Linux ARM64/Raspberry Pi (WebKitGTK)
|
|
21
|
+
|
|
22
|
+
The correct binary is automatically selected based on `process.platform` and `process.arch`.
|
|
23
|
+
|
|
24
|
+
## Building from Source
|
|
25
|
+
|
|
26
|
+
### Prerequisites
|
|
27
|
+
|
|
28
|
+
- **Rust** (install from https://rustup.rs/)
|
|
29
|
+
- **Node.js** (v16 or later)
|
|
30
|
+
- **Windows**: Visual Studio Build Tools with C++ development tools
|
|
31
|
+
- **macOS**: Xcode Command Line Tools
|
|
32
|
+
- **Linux**: WebKitGTK development packages
|
|
33
|
+
|
|
34
|
+
### Build Commands
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Build everything (TypeScript + all native binaries)
|
|
38
|
+
npm run build
|
|
39
|
+
|
|
40
|
+
# Build only TypeScript wrapper
|
|
41
|
+
npm run build:ts
|
|
42
|
+
|
|
43
|
+
# Build Windows binary
|
|
44
|
+
npm run build:native
|
|
45
|
+
|
|
46
|
+
# Build Linux x64 binary (via WSL)
|
|
47
|
+
npm run build:native:wsl
|
|
48
|
+
|
|
49
|
+
# Build ARM64 binary (via SSH to Raspberry Pi)
|
|
50
|
+
npm run build:native:pi
|
|
51
|
+
|
|
52
|
+
# Build all native binaries
|
|
53
|
+
npm run build:native:all
|
|
54
|
+
|
|
55
|
+
# Watch mode for TypeScript development
|
|
56
|
+
npm run watch
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Building ARM64 Binary
|
|
60
|
+
|
|
61
|
+
To build the ARM64 binary for Raspberry Pi:
|
|
62
|
+
|
|
63
|
+
1. Update `PI_HOST` in `msger-native/build-pi.ts` with your Pi's hostname/IP
|
|
64
|
+
2. Ensure SSH keys are set up: `ssh-copy-id pi@your-pi`
|
|
65
|
+
3. Run: `npm run build:native:pi`
|
|
66
|
+
|
|
67
|
+
The script will automatically:
|
|
68
|
+
- Copy source files to the Pi via SSH
|
|
69
|
+
- Install Rust and build dependencies if needed
|
|
70
|
+
- Build the binary on the Pi
|
|
71
|
+
- Copy the binary back to your development machine
|
|
72
|
+
|
|
73
|
+
### Manual Rust Build
|
|
74
|
+
|
|
75
|
+
If you prefer to build the Rust binary manually:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
cd msger-native
|
|
79
|
+
|
|
80
|
+
# Debug build (faster compile, larger binary)
|
|
81
|
+
cargo build
|
|
82
|
+
|
|
83
|
+
# Release build (optimized, smaller binary)
|
|
84
|
+
cargo build --release
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Note**: If you encounter linker errors on Windows, make sure Visual Studio Build Tools with C++ workload is installed.
|
|
88
|
+
|
|
89
|
+
### Cross-Platform Builds
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Windows
|
|
93
|
+
cargo build --release --target x86_64-pc-windows-msvc
|
|
94
|
+
|
|
95
|
+
# Linux (from Linux or WSL)
|
|
96
|
+
cargo build --release --target x86_64-unknown-linux-gnu
|
|
97
|
+
|
|
98
|
+
# macOS (requires macOS or CI)
|
|
99
|
+
cargo build --release --target x86_64-apple-darwin
|
|
100
|
+
cargo build --release --target aarch64-apple-darwin # Apple Silicon
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Project Structure
|
|
104
|
+
|
|
105
|
+
The project consists of two parts:
|
|
106
|
+
|
|
107
|
+
1. **`msger-native/`** - Rust binary (subdirectory with its own Cargo.toml)
|
|
108
|
+
- `src/main.rs` - Main application logic
|
|
109
|
+
- `src/msger-api.js` - JavaScript API injected into webviews
|
|
110
|
+
- `src/template.html` - HTML template for message boxes
|
|
111
|
+
- `bin/` - Compiled binaries for distribution
|
|
112
|
+
- `README.md` - Rust-specific documentation
|
|
113
|
+
|
|
114
|
+
2. **Root directory** - TypeScript wrapper and npm package
|
|
115
|
+
- TypeScript wrapper for Node.js API
|
|
116
|
+
- CLI interface
|
|
117
|
+
- Build scripts
|
|
118
|
+
|
|
119
|
+
When you run `npm run build`, it:
|
|
120
|
+
1. Builds platform-specific Rust binaries
|
|
121
|
+
2. Copies binaries to `msger-native/bin/`
|
|
122
|
+
3. Compiles TypeScript to JavaScript
|
|
123
|
+
|
|
124
|
+
All binaries are bundled with the npm package, and the correct one is selected at runtime.
|
|
125
|
+
|
|
126
|
+
## Dependencies
|
|
127
|
+
|
|
128
|
+
### Rust (msger-native)
|
|
129
|
+
|
|
130
|
+
- **wry** (0.47) - Cross-platform webview library
|
|
131
|
+
- **tao** (0.30) - Cross-platform windowing
|
|
132
|
+
- **serde** / **serde_json** (1.0) - JSON serialization
|
|
133
|
+
- **clap** (4.5) - Command-line argument parsing
|
|
134
|
+
- **windows** (0.58) - Windows API bindings (Windows only)
|
|
135
|
+
- **image** (0.24) - Icon loading
|
|
136
|
+
|
|
137
|
+
### TypeScript/Node.js
|
|
138
|
+
|
|
139
|
+
- Standard Node.js APIs for process spawning
|
|
140
|
+
- No runtime dependencies
|
|
141
|
+
|
|
142
|
+
## Design Trade-offs
|
|
143
|
+
|
|
144
|
+
### Why Rust + WebView instead of Electron?
|
|
145
|
+
|
|
146
|
+
**Size:**
|
|
147
|
+
- Electron: ~100MB bundled app
|
|
148
|
+
- msger: ~2-5MB per platform binary
|
|
149
|
+
- **50-100x smaller**
|
|
150
|
+
|
|
151
|
+
**Startup Time:**
|
|
152
|
+
- Electron: ~2-3 seconds
|
|
153
|
+
- msger: ~50-200ms
|
|
154
|
+
- **10-20x faster**
|
|
155
|
+
|
|
156
|
+
**Memory:**
|
|
157
|
+
- Electron: ~100-200MB
|
|
158
|
+
- msger: ~20-50MB
|
|
159
|
+
- **3-5x less**
|
|
160
|
+
|
|
161
|
+
**Trade-off:** Platform-specific binaries vs single JavaScript bundle. We chose better performance.
|
|
162
|
+
|
|
163
|
+
### Why Multiple Binaries?
|
|
164
|
+
|
|
165
|
+
We ship separate binaries for each platform instead of one universal binary:
|
|
166
|
+
|
|
167
|
+
**Pros:**
|
|
168
|
+
- Smaller download per platform
|
|
169
|
+
- Native performance
|
|
170
|
+
- No cross-compilation complexity
|
|
171
|
+
|
|
172
|
+
**Cons:**
|
|
173
|
+
- Larger npm package overall
|
|
174
|
+
- Need to build on each platform
|
|
175
|
+
|
|
176
|
+
**Decision:** Better user experience (smaller, faster) outweighs developer complexity.
|
|
177
|
+
|
|
178
|
+
### Why stdin/stdout JSON instead of native Node.js addon?
|
|
179
|
+
|
|
180
|
+
**Pros:**
|
|
181
|
+
- Platform independence (no native compilation at install time)
|
|
182
|
+
- Easy debugging (can test with echo/pipes)
|
|
183
|
+
- Clear separation of concerns
|
|
184
|
+
- No version compatibility issues
|
|
185
|
+
|
|
186
|
+
**Cons:**
|
|
187
|
+
- Slightly higher overhead (process spawn)
|
|
188
|
+
- No shared memory
|
|
189
|
+
|
|
190
|
+
**Decision:** The 50-200ms startup is fast enough, and JSON is simpler than N-API.
|
|
191
|
+
|
|
192
|
+
## Testing the Native Binary
|
|
193
|
+
|
|
194
|
+
### Standalone Tests
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Simple message
|
|
198
|
+
echo '{"message":"Hello from Rust!","buttons":["Cancel","OK"]}' | ./msger-native/bin/msgernative
|
|
199
|
+
|
|
200
|
+
# With input field
|
|
201
|
+
echo '{"message":"Enter your name:","allowInput":true,"defaultValue":"John","buttons":["Cancel","Submit"]}' | ./msger-native/bin/msgernative
|
|
202
|
+
|
|
203
|
+
# With HTML content
|
|
204
|
+
echo '{"title":"Rich Content","html":"<h2>Welcome</h2><p>This is <strong>HTML</strong> content</p>","buttons":["Close"]}' | ./msger-native/bin/msgernative
|
|
205
|
+
|
|
206
|
+
# JSON file + CLI overrides
|
|
207
|
+
./msger-native/bin/msgernative config.json --title "Override Title" --width 800
|
|
208
|
+
|
|
209
|
+
# Pure CLI
|
|
210
|
+
./msger-native/bin/msgernative --message "Hello" --buttons "OK,Cancel" --width 600
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Contributing
|
|
214
|
+
|
|
215
|
+
### Code Style
|
|
216
|
+
|
|
217
|
+
- **Rust**: Follow standard `rustfmt` style
|
|
218
|
+
- **TypeScript**: 4-space indentation, semicolons
|
|
219
|
+
- **Comments**: Explain why, not what
|
|
220
|
+
|
|
221
|
+
### Pull Requests
|
|
222
|
+
|
|
223
|
+
1. Create a feature branch
|
|
224
|
+
2. Make your changes
|
|
225
|
+
3. Test on your platform
|
|
226
|
+
4. Submit PR with description
|
|
227
|
+
|
|
228
|
+
### Testing Checklist
|
|
229
|
+
|
|
230
|
+
Before submitting:
|
|
231
|
+
- [ ] Test on Windows (if available)
|
|
232
|
+
- [ ] Test on Linux (if available)
|
|
233
|
+
- [ ] Test stdin mode
|
|
234
|
+
- [ ] Test JSON file mode
|
|
235
|
+
- [ ] Test CLI argument mode
|
|
236
|
+
- [ ] Test button clicks
|
|
237
|
+
- [ ] Test input fields
|
|
238
|
+
- [ ] Test HTML content
|
|
239
|
+
- [ ] Test URL loading
|
|
240
|
+
- [ ] Update documentation
|
|
241
|
+
|
|
242
|
+
## Performance Comparison
|
|
243
|
+
|
|
244
|
+
| | **Electron (msgview)** | **Rust (msger)** | **Improvement** |
|
|
245
|
+
|---|---|---|---|
|
|
246
|
+
| **Binary Size** | ~100MB | ~1-2MB per platform | **50-100x smaller** |
|
|
247
|
+
| **Startup Time** | ~2-3 seconds | ~50-200ms | **10-20x faster** |
|
|
248
|
+
| **Memory Usage** | ~100-200MB | ~20-50MB | **3-5x less** |
|
|
249
|
+
| **Cross-Platform** | ✅ Win/Mac/Linux | ✅ Win/Linux x64/ARM64 | Similar |
|
|
250
|
+
| **Full HTML/CSS** | ✅ Chromium | ✅ WebView2/WebKit | Same |
|
|
251
|
+
| **URL Loading** | ✅ | ✅ | Same |
|
|
252
|
+
|
|
253
|
+
## Technical Documentation
|
|
254
|
+
|
|
255
|
+
For detailed technical status, known issues, and roadmap, see:
|
|
256
|
+
- [TODO.md](TODO.md) - Development roadmap and known issues
|
|
257
|
+
- [SESSION-NOTES.md](SESSION-NOTES.md) - Implementation notes and decisions (if available)
|
|
258
|
+
|
|
259
|
+
## License
|
|
260
|
+
|
|
261
|
+
ISC
|
|
262
|
+
|
|
263
|
+
## Author
|
|
264
|
+
|
|
265
|
+
Bob Frankston
|
package/README.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# @bobfrankston/msger
|
|
2
2
|
|
|
3
|
-
Fast, lightweight
|
|
3
|
+
Fast, lightweight message boxes for Node.js applications.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- **
|
|
5
|
+
Display native message boxes, dialogs, and HTML content with a simple JavaScript API. Works on Windows, Linux (x64), and Linux (ARM64/Raspberry Pi).
|
|
6
|
+
|
|
7
|
+
## Quick Links
|
|
8
|
+
|
|
9
|
+
- **[Installation](#installation)** - Get started
|
|
10
|
+
- **[Command Line Usage](#command-line-usage)** - Use from shell scripts
|
|
11
|
+
- **[Node.js API](#nodejs-api-reference)** - Use from JavaScript/TypeScript
|
|
12
|
+
- **[For Developers](DEVELOPERS.md)** - Building & architecture
|
|
13
|
+
- **[Roadmap](TODO.md)** - Technical status & planned features
|
|
10
14
|
|
|
11
15
|
## Installation
|
|
12
16
|
|
|
@@ -19,34 +23,18 @@ For global CLI usage:
|
|
|
19
23
|
npm install -g @bobfrankston/msger
|
|
20
24
|
```
|
|
21
25
|
|
|
22
|
-
**
|
|
23
|
-
- Windows (x64)
|
|
24
|
-
- Linux
|
|
25
|
-
- Linux ARM64/Raspberry Pi
|
|
26
|
+
**Supported Platforms:**
|
|
27
|
+
- Windows (x64)
|
|
28
|
+
- Linux (x64)
|
|
29
|
+
- Linux (ARM64 / Raspberry Pi)
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
---
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
# Command Line Usage
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
The `msger` command-line tool provides a quick way to display message boxes from shell scripts, batch files, or terminal.
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
import { showMessageBox } from '@bobfrankston/msger';
|
|
35
|
-
|
|
36
|
-
const result = await showMessageBox({
|
|
37
|
-
title: 'Confirm Action',
|
|
38
|
-
message: 'Are you sure you want to proceed?',
|
|
39
|
-
buttons: ['Cancel', 'OK']
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
console.log('User clicked:', result.button);
|
|
43
|
-
|
|
44
|
-
if (result.value) {
|
|
45
|
-
console.log('User entered:', result.value);
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### As a CLI Tool
|
|
37
|
+
## Basic Examples
|
|
50
38
|
|
|
51
39
|
```bash
|
|
52
40
|
# Simple message
|
|
@@ -91,7 +79,194 @@ msger -message "Closing in 5 seconds..." -timeout 5
|
|
|
91
79
|
msger --help
|
|
92
80
|
```
|
|
93
81
|
|
|
94
|
-
##
|
|
82
|
+
## JSON Configuration Files
|
|
83
|
+
|
|
84
|
+
You can store message box configuration in a JSON file for reuse:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Load configuration from file
|
|
88
|
+
msger config.json
|
|
89
|
+
|
|
90
|
+
# Override specific values
|
|
91
|
+
msger config.json --title "New Title" --width 800
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Complete JSON Structure
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"title": "Window Title",
|
|
99
|
+
"message": "Plain text message (supports ANSI color codes)",
|
|
100
|
+
"html": "<h1>HTML content</h1><p>Rich formatting</p>",
|
|
101
|
+
"url": "https://example.com",
|
|
102
|
+
"size": {
|
|
103
|
+
"width": 600,
|
|
104
|
+
"height": 400
|
|
105
|
+
},
|
|
106
|
+
"pos": {
|
|
107
|
+
"x": 100,
|
|
108
|
+
"y": 100,
|
|
109
|
+
"screen": 0
|
|
110
|
+
},
|
|
111
|
+
"buttons": ["Cancel", "OK"],
|
|
112
|
+
"defaultValue": "default input text",
|
|
113
|
+
"inputPlaceholder": "Enter text here...",
|
|
114
|
+
"allowInput": false,
|
|
115
|
+
"timeout": 30,
|
|
116
|
+
"autoSize": false,
|
|
117
|
+
"alwaysOnTop": false,
|
|
118
|
+
"fullscreen": false,
|
|
119
|
+
"zoomPercent": 100,
|
|
120
|
+
"debug": false,
|
|
121
|
+
"icon": "path/to/icon.png",
|
|
122
|
+
"dev": false
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Field Reference
|
|
127
|
+
|
|
128
|
+
| Field | Type | Default | Description |
|
|
129
|
+
|-------|------|---------|-------------|
|
|
130
|
+
| `title` | string | "Message" | Window title |
|
|
131
|
+
| `message` | string | null | Plain text message (supports ANSI color codes) |
|
|
132
|
+
| `html` | string | null | HTML content to display |
|
|
133
|
+
| `url` | string | null | URL to load (web or file://) |
|
|
134
|
+
| `size` | object | `{"width": 600, "height": 400}` | Window size |
|
|
135
|
+
| `size.width` | number | 600 (or 1024 for URLs) | Window width in pixels |
|
|
136
|
+
| `size.height` | number | 400 (or 768 for URLs) | Window height in pixels |
|
|
137
|
+
| `pos` | object | null | Window position |
|
|
138
|
+
| `pos.x` | number | - | X coordinate in pixels |
|
|
139
|
+
| `pos.y` | number | - | Y coordinate in pixels |
|
|
140
|
+
| `pos.screen` | number | null | [Windows only] Screen index (0=primary, 1=second, etc.) |
|
|
141
|
+
| `buttons` | string[] | ["OK"] | Button labels |
|
|
142
|
+
| `defaultValue` | string | null | Default input value |
|
|
143
|
+
| `inputPlaceholder` | string | null | Placeholder text for input field |
|
|
144
|
+
| `allowInput` | boolean | false | Show input field |
|
|
145
|
+
| `timeout` | number | null | Auto-close after N seconds |
|
|
146
|
+
| `autoSize` | boolean | true when no size | Auto-resize window to fit content |
|
|
147
|
+
| `alwaysOnTop` | boolean | false | Keep window on top |
|
|
148
|
+
| `fullscreen` | boolean | false | Start in fullscreen mode |
|
|
149
|
+
| `zoomPercent` | number | 100 | Initial zoom level (100=100%, 150=150%) |
|
|
150
|
+
| `debug` | boolean | false | Return debug info in result |
|
|
151
|
+
| `icon` | string | null | Path to window icon (.png, .ico) |
|
|
152
|
+
| `dev` | boolean | false | Enable developer mode |
|
|
153
|
+
|
|
154
|
+
**Content Priority:** Only one content type will be displayed (in order):
|
|
155
|
+
1. `url` - If provided, loads URL (ignores message/html)
|
|
156
|
+
2. `html` - If provided, displays HTML (ignores message)
|
|
157
|
+
3. `message` - Plain text with ANSI color support
|
|
158
|
+
|
|
159
|
+
**Backward Compatibility:** The old `width` and `height` fields (at the top level) are still supported for backward compatibility, but the `size` object is preferred. If both are provided, `size` takes precedence.
|
|
160
|
+
|
|
161
|
+
### JSON Examples
|
|
162
|
+
|
|
163
|
+
**Simple dialog:**
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"title": "Confirm",
|
|
167
|
+
"message": "Are you sure?",
|
|
168
|
+
"buttons": ["Cancel", "OK"]
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Input dialog:**
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"title": "Enter Name",
|
|
176
|
+
"message": "Please enter your name:",
|
|
177
|
+
"allowInput": true,
|
|
178
|
+
"inputPlaceholder": "Your name here",
|
|
179
|
+
"defaultValue": "John Doe",
|
|
180
|
+
"buttons": ["Cancel", "Submit"]
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**HTML content:**
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"title": "Welcome",
|
|
188
|
+
"html": "<h1>Welcome!</h1><p>Getting started...</p>",
|
|
189
|
+
"size": {
|
|
190
|
+
"width": 700,
|
|
191
|
+
"height": 500
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Positioned window on second monitor:**
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"message": "Second screen",
|
|
200
|
+
"pos": {
|
|
201
|
+
"x": 0,
|
|
202
|
+
"y": 100,
|
|
203
|
+
"screen": 1
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## CLI Options Reference
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
Usage: msger [options] [message words...]
|
|
212
|
+
|
|
213
|
+
Options:
|
|
214
|
+
-message, --message <text> Plain text message
|
|
215
|
+
-title, --title <text> Window title
|
|
216
|
+
-html, --html <html> HTML content
|
|
217
|
+
-url, --url <url> URL to load (web or file://)
|
|
218
|
+
-buttons, --buttons <labels> Button labels (e.g., -buttons Yes No Cancel)
|
|
219
|
+
-ok, --ok Add OK button
|
|
220
|
+
-cancel, --cancel Add Cancel button
|
|
221
|
+
-input, --input [placeholder] Include input field with optional placeholder text
|
|
222
|
+
-default, --default <text> Default value for input field
|
|
223
|
+
-size, --size <width,height> Window size (e.g., -size 800,600)
|
|
224
|
+
-pos, --pos <x,y> Window position (e.g., -pos 100,200)
|
|
225
|
+
-screen, --screen <number> [Windows only] Screen index (0=primary, 1=second, etc.)
|
|
226
|
+
-zoom, --zoom <percent> Zoom level as percentage (e.g., -zoom 150 for 150%)
|
|
227
|
+
-timeout, --timeout <seconds> Auto-close after specified seconds
|
|
228
|
+
-ontop, --ontop Keep window always on top
|
|
229
|
+
-detach, --detach Launch window independently (parent returns immediately)
|
|
230
|
+
-fullscreen, --fullscreen Start window in fullscreen mode (F11 to toggle, Escape to exit)
|
|
231
|
+
-debug, --debug Return debug info (HTML, size, autoSize) in result
|
|
232
|
+
-v, -version, --version Show version number
|
|
233
|
+
-help, -?, --help Show help message
|
|
234
|
+
|
|
235
|
+
Notes:
|
|
236
|
+
- If no options provided, all non-option arguments are concatenated as message
|
|
237
|
+
- Press ESC to dismiss (returns button: "dismissed")
|
|
238
|
+
- Press Enter to click last (default) button
|
|
239
|
+
- OK button is green by default
|
|
240
|
+
- URLs default to 1024x768 window size
|
|
241
|
+
- Windows auto-size to fit content when size not specified
|
|
242
|
+
- Runtime zoom: Ctrl+Wheel, Ctrl+Plus, Ctrl+Minus
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
# Node.js API Reference
|
|
248
|
+
|
|
249
|
+
Use msger in your Node.js or TypeScript applications with a simple Promise-based API.
|
|
250
|
+
|
|
251
|
+
## Quick Start
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import { showMessageBox } from '@bobfrankston/msger';
|
|
255
|
+
|
|
256
|
+
const result = await showMessageBox({
|
|
257
|
+
title: 'Confirm Action',
|
|
258
|
+
message: 'Are you sure you want to proceed?',
|
|
259
|
+
buttons: ['Cancel', 'OK']
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
console.log('User clicked:', result.button);
|
|
263
|
+
|
|
264
|
+
if (result.value) {
|
|
265
|
+
console.log('User entered:', result.value);
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## API Functions
|
|
95
270
|
|
|
96
271
|
### `showMessageBox(options: MessageBoxOptions): Promise<MessageBoxResult>`
|
|
97
272
|
|
|
@@ -147,7 +322,7 @@ interface MessageBoxResult {
|
|
|
147
322
|
}
|
|
148
323
|
```
|
|
149
324
|
|
|
150
|
-
## Examples
|
|
325
|
+
## API Examples
|
|
151
326
|
|
|
152
327
|
### Simple Confirmation Dialog
|
|
153
328
|
|
|
@@ -254,17 +429,12 @@ const result = await showMessageBox({
|
|
|
254
429
|
});
|
|
255
430
|
|
|
256
431
|
if (result.timeout) {
|
|
257
|
-
console.log('
|
|
432
|
+
console.log('Notification auto-closed');
|
|
258
433
|
}
|
|
259
434
|
```
|
|
260
435
|
|
|
261
436
|
The countdown timer displays as a subtle yellow badge in the top-right corner, showing the remaining seconds (e.g., "10s", "9s", "8s"...).
|
|
262
437
|
|
|
263
|
-
if (result.timeout) {
|
|
264
|
-
console.log('Notification auto-closed');
|
|
265
|
-
}
|
|
266
|
-
```
|
|
267
|
-
|
|
268
438
|
### HTML Forms
|
|
269
439
|
|
|
270
440
|
```typescript
|
|
@@ -356,161 +526,35 @@ await showMessageBox({
|
|
|
356
526
|
});
|
|
357
527
|
```
|
|
358
528
|
|
|
359
|
-
## Architecture
|
|
360
|
-
|
|
361
|
-
```
|
|
362
|
-
@bobfrankston/msger (TypeScript wrapper)
|
|
363
|
-
↓ spawns native binary with JSON via stdin
|
|
364
|
-
@bobfrankston/msger-native (Rust binary - platform-specific)
|
|
365
|
-
↓ creates native window with webview
|
|
366
|
-
↓ displays HTML/URL content with buttons
|
|
367
|
-
↓ outputs JSON result to stdout
|
|
368
|
-
TypeScript wrapper returns Promise<MessageBoxResult>
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
**Platform-specific binaries:**
|
|
372
|
-
- `msgernative.exe` - Windows x64 (WebView2)
|
|
373
|
-
- `msgernative` - Linux x86_64 (WebKitGTK)
|
|
374
|
-
- `msgernative-arm64` - Linux ARM64/Raspberry Pi (WebKitGTK)
|
|
375
|
-
|
|
376
|
-
The correct binary is automatically selected based on `process.platform` and `process.arch`.
|
|
377
|
-
|
|
378
|
-
## Building from Source
|
|
379
|
-
|
|
380
|
-
```bash
|
|
381
|
-
# Build everything (TypeScript + all native binaries)
|
|
382
|
-
npm run build
|
|
383
|
-
|
|
384
|
-
# Build only TypeScript wrapper
|
|
385
|
-
npm run build:ts
|
|
386
|
-
|
|
387
|
-
# Build Windows binary
|
|
388
|
-
npm run build:native
|
|
389
|
-
|
|
390
|
-
# Build Linux x64 binary (via WSL)
|
|
391
|
-
npm run build:native:wsl
|
|
392
|
-
|
|
393
|
-
# Build ARM64 binary (via SSH to Raspberry Pi)
|
|
394
|
-
npm run build:native:pi
|
|
395
|
-
|
|
396
|
-
# Build all native binaries
|
|
397
|
-
npm run build:native:all
|
|
398
|
-
|
|
399
|
-
# Watch mode for TypeScript development
|
|
400
|
-
npm run watch
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
### Building ARM64 Binary
|
|
404
|
-
|
|
405
|
-
To build the ARM64 binary for Raspberry Pi:
|
|
406
|
-
|
|
407
|
-
1. Update `PI_HOST` in `msger-native/build-pi.ts` with your Pi's hostname/IP
|
|
408
|
-
2. Ensure SSH keys are set up: `ssh-copy-id pi@your-pi`
|
|
409
|
-
3. Run: `npm run build:native:pi`
|
|
410
|
-
|
|
411
|
-
The script will automatically:
|
|
412
|
-
- Copy source files to the Pi via SSH
|
|
413
|
-
- Install Rust and build dependencies if needed
|
|
414
|
-
- Build the binary on the Pi
|
|
415
|
-
- Copy the binary back to your development machine
|
|
416
|
-
|
|
417
|
-
## Development
|
|
418
|
-
|
|
419
|
-
The project consists of two parts:
|
|
420
|
-
|
|
421
|
-
1. **`msger-native/`** - Rust binary (subdirectory with its own Cargo.toml)
|
|
422
|
-
2. **Root directory** - TypeScript wrapper and npm package
|
|
423
|
-
|
|
424
|
-
When you run `npm run build`, it:
|
|
425
|
-
1. Builds platform-specific Rust binaries
|
|
426
|
-
2. Copies binaries to `msger-native/bin/`
|
|
427
|
-
3. Compiles TypeScript to JavaScript
|
|
428
|
-
|
|
429
|
-
All binaries are bundled with the npm package, and the correct one is selected at runtime.
|
|
430
|
-
|
|
431
529
|
## Features
|
|
432
530
|
|
|
433
|
-
- ✅
|
|
434
|
-
- ✅ Full HTML/CSS support
|
|
435
|
-
- ✅ ANSI color
|
|
436
|
-
- ✅
|
|
437
|
-
- ✅
|
|
438
|
-
- ✅ Input field support with placeholder text
|
|
439
|
-
- ✅ HTML forms with automatic data collection
|
|
531
|
+
- ✅ Display plain text, HTML content, or load URLs
|
|
532
|
+
- ✅ Full HTML/CSS support
|
|
533
|
+
- ✅ ANSI color codes (colored terminal output)
|
|
534
|
+
- ✅ Customizable buttons
|
|
535
|
+
- ✅ Input fields and forms
|
|
440
536
|
- ✅ Auto-close with timeout
|
|
441
|
-
- ✅ Window positioning
|
|
442
|
-
- ✅ Multi-monitor support (Windows
|
|
537
|
+
- ✅ Window positioning and sizing
|
|
538
|
+
- ✅ Multi-monitor support (Windows)
|
|
443
539
|
- ✅ Always on top mode
|
|
444
|
-
- ✅ Zoom control
|
|
445
|
-
- ✅
|
|
446
|
-
- ✅ Keyboard shortcuts (Enter, Escape, F11)
|
|
447
|
-
- ✅ Window close detection
|
|
448
|
-
- ✅ Detached process mode (independent window)
|
|
449
|
-
- ✅ Fullscreen mode with F11 toggle
|
|
540
|
+
- ✅ Zoom control
|
|
541
|
+
- ✅ Fullscreen mode
|
|
450
542
|
- ✅ TypeScript type definitions
|
|
451
|
-
- ✅
|
|
452
|
-
- ✅ Fast startup (~50-200ms)
|
|
453
|
-
- ✅ Low memory usage (~20-50MB)
|
|
543
|
+
- ✅ Keyboard shortcuts (Enter, Escape, F11)
|
|
454
544
|
|
|
455
|
-
##
|
|
545
|
+
## Why msger?
|
|
456
546
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
| **Cross-Platform** | ✅ Win/Mac/Linux | ✅ Win/Linux x64/ARM64 | Similar |
|
|
463
|
-
| **Full HTML/CSS** | ✅ Chromium | ✅ WebView2/WebKit | Same |
|
|
464
|
-
| **URL Loading** | ✅ | ✅ | Same |
|
|
547
|
+
- **Fast** - Opens in under 200ms
|
|
548
|
+
- **Small** - Only a few MB installed
|
|
549
|
+
- **Simple** - Easy Promise-based API
|
|
550
|
+
- **Flexible** - Plain text, HTML, or load URLs
|
|
551
|
+
- **Cross-platform** - Works on Windows and Linux
|
|
465
552
|
|
|
466
|
-
|
|
553
|
+
For technical details and performance metrics, see [DEVELOPERS.md](DEVELOPERS.md).
|
|
467
554
|
|
|
468
|
-
|
|
469
|
-
Usage: msger [options] [message words...]
|
|
555
|
+
---
|
|
470
556
|
|
|
471
|
-
|
|
472
|
-
-message, --message <text> Plain text message
|
|
473
|
-
-title, --title <text> Window title
|
|
474
|
-
-html, --html <html> HTML content
|
|
475
|
-
-url, --url <url> URL to load (web or file://)
|
|
476
|
-
-buttons, --buttons <labels> Button labels (e.g., -buttons Yes No Cancel)
|
|
477
|
-
-ok, --ok Add OK button
|
|
478
|
-
-cancel, --cancel Add Cancel button
|
|
479
|
-
-input, --input [placeholder] Include input field with optional placeholder text
|
|
480
|
-
-default, --default <text> Default value for input field
|
|
481
|
-
-size, --size <width,height> Window size (e.g., -size 800,600)
|
|
482
|
-
-pos, --pos <x,y> Window position (e.g., -pos 100,200)
|
|
483
|
-
-screen, --screen <number> [Windows only] Screen index (0=primary, 1=second, etc.)
|
|
484
|
-
-zoom, --zoom <percent> Zoom level as percentage (e.g., -zoom 150 for 150%)
|
|
485
|
-
-timeout, --timeout <seconds> Auto-close after specified seconds
|
|
486
|
-
-ontop, --ontop Keep window always on top
|
|
487
|
-
-detach, --detach Launch window independently (parent returns immediately)
|
|
488
|
-
-fullscreen, --fullscreen Start window in fullscreen mode (F11 to toggle, Escape to exit)
|
|
489
|
-
-debug, --debug Return debug info (HTML, size, autoSize) in result
|
|
490
|
-
-v, -version, --version Show version number
|
|
491
|
-
-help, -?, --help Show help message
|
|
492
|
-
|
|
493
|
-
Examples:
|
|
494
|
-
msger Hello World
|
|
495
|
-
msger -message "Save changes?" -buttons Yes No Cancel
|
|
496
|
-
msger -message "Enter your name:" -input "Your name" -default "John Doe"
|
|
497
|
-
msger -html "<h1>Title</h1><p>Formatted <b>content</b></p>"
|
|
498
|
-
msger -html "<span style='color:red;background-color:yellow'>Colored text</span>"
|
|
499
|
-
msger -url "https://example.com"
|
|
500
|
-
msger -url "https://example.com" -detach
|
|
501
|
-
msger -title "Alert" -message "Operation complete"
|
|
502
|
-
msger -message "Positioned" -pos 100,100 -screen 1
|
|
503
|
-
msger -message "Large text" -zoom 150 -ontop
|
|
504
|
-
|
|
505
|
-
Notes:
|
|
506
|
-
- If no options provided, all non-option arguments are concatenated as message
|
|
507
|
-
- Press ESC to dismiss (returns button: "dismissed")
|
|
508
|
-
- Press Enter to click last (default) button
|
|
509
|
-
- OK button is green by default
|
|
510
|
-
- URLs default to 1024x768 window size
|
|
511
|
-
- Windows auto-size to fit content when size not specified
|
|
512
|
-
- Runtime zoom: Ctrl+Wheel, Ctrl+Plus, Ctrl+Minus
|
|
513
|
-
```
|
|
557
|
+
# Additional Information
|
|
514
558
|
|
|
515
559
|
## Important Notes
|
|
516
560
|
|
|
@@ -518,10 +562,6 @@ Notes:
|
|
|
518
562
|
|
|
519
563
|
⚠️ **msger is designed for displaying trusted, friendly content** (local apps, your HTML files). It is NOT a secure sandbox for untrusted/hostile web content. Use `-htmlfrom` and `-url` with trusted sources only.
|
|
520
564
|
|
|
521
|
-
### Technical Details & Known Issues
|
|
522
|
-
|
|
523
|
-
For detailed technical information, known limitations, current status, and planned features, see [TODO.md](TODO.md).
|
|
524
|
-
|
|
525
565
|
### msger JavaScript API
|
|
526
566
|
|
|
527
567
|
**Minimal API** - Most functionality uses native browser APIs:
|
|
@@ -530,6 +570,12 @@ For detailed technical information, known limitations, current status, and plann
|
|
|
530
570
|
|
|
531
571
|
**Recommendation:** Use native browser APIs (`localStorage`, `window.close()`) for compatibility. Code will work in any browser context, not just msger.
|
|
532
572
|
|
|
573
|
+
## For Developers
|
|
574
|
+
|
|
575
|
+
- **Building & Architecture**: See [DEVELOPERS.md](DEVELOPERS.md)
|
|
576
|
+
- **Technical Status & Roadmap**: See [TODO.md](TODO.md)
|
|
577
|
+
- **Native Binary Documentation**: See [msger-native/README.md](msger-native/README.md)
|
|
578
|
+
|
|
533
579
|
## License
|
|
534
580
|
|
|
535
581
|
ISC
|
|
Binary file
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "Example Message Box",
|
|
3
3
|
"message": "This is a sample message box configuration.\n\nYou can override any of these settings via command-line arguments.",
|
|
4
|
-
"
|
|
5
|
-
|
|
4
|
+
"size": {
|
|
5
|
+
"width": 600,
|
|
6
|
+
"height": 400
|
|
7
|
+
},
|
|
6
8
|
"pos": {
|
|
7
9
|
"x": 100,
|
|
8
10
|
"y": 100,
|
package/msger-native/src/main.rs
CHANGED
|
@@ -166,6 +166,13 @@ struct Position {
|
|
|
166
166
|
screen: Option<i32>,
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
#[derive(Deserialize, Debug)]
|
|
170
|
+
#[serde(rename_all = "camelCase")]
|
|
171
|
+
struct Size {
|
|
172
|
+
width: i32,
|
|
173
|
+
height: i32,
|
|
174
|
+
}
|
|
175
|
+
|
|
169
176
|
#[derive(Deserialize, Debug)]
|
|
170
177
|
#[serde(rename_all = "camelCase")]
|
|
171
178
|
struct MessageBoxOptions {
|
|
@@ -177,8 +184,13 @@ struct MessageBoxOptions {
|
|
|
177
184
|
html: Option<String>,
|
|
178
185
|
#[serde(default)]
|
|
179
186
|
url: Option<String>,
|
|
187
|
+
// New size object (preferred)
|
|
188
|
+
#[serde(default)]
|
|
189
|
+
size: Option<Size>,
|
|
190
|
+
// Deprecated: use size.width instead
|
|
180
191
|
#[serde(default = "default_width")]
|
|
181
192
|
width: i32,
|
|
193
|
+
// Deprecated: use size.height instead
|
|
182
194
|
#[serde(default = "default_height")]
|
|
183
195
|
height: i32,
|
|
184
196
|
#[serde(default)]
|
|
@@ -358,11 +370,21 @@ fn merge_cli_with_options(cli: &Cli, mut options: MessageBoxOptions) -> MessageB
|
|
|
358
370
|
if let Some(ref url) = cli.url {
|
|
359
371
|
options.url = Some(url.clone());
|
|
360
372
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
373
|
+
|
|
374
|
+
// Handle size - if CLI provides width or height, update both old fields and size object
|
|
375
|
+
if cli.width.is_some() || cli.height.is_some() {
|
|
376
|
+
let existing_size = options.size.take().unwrap_or(Size {
|
|
377
|
+
width: options.width,
|
|
378
|
+
height: options.height,
|
|
379
|
+
});
|
|
380
|
+
let new_size = Size {
|
|
381
|
+
width: cli.width.unwrap_or(existing_size.width),
|
|
382
|
+
height: cli.height.unwrap_or(existing_size.height),
|
|
383
|
+
};
|
|
384
|
+
// Update both for backward compatibility
|
|
385
|
+
options.width = new_size.width;
|
|
386
|
+
options.height = new_size.height;
|
|
387
|
+
options.size = Some(new_size);
|
|
366
388
|
}
|
|
367
389
|
|
|
368
390
|
// Handle position
|
|
@@ -504,6 +526,13 @@ fn main() {
|
|
|
504
526
|
None
|
|
505
527
|
};
|
|
506
528
|
|
|
529
|
+
// Determine final width and height (size object takes precedence over individual width/height)
|
|
530
|
+
let (final_width, final_height) = if let Some(ref size) = options.size {
|
|
531
|
+
(size.width, size.height)
|
|
532
|
+
} else {
|
|
533
|
+
(options.width, options.height)
|
|
534
|
+
};
|
|
535
|
+
|
|
507
536
|
// Load window icon (default or custom)
|
|
508
537
|
let icon = if let Some(ref icon_path) = options.icon {
|
|
509
538
|
load_icon(icon_path)
|
|
@@ -515,8 +544,8 @@ fn main() {
|
|
|
515
544
|
let mut window_builder = WindowBuilder::new()
|
|
516
545
|
.with_title(&options.title)
|
|
517
546
|
.with_inner_size(tao::dpi::LogicalSize::new(
|
|
518
|
-
|
|
519
|
-
|
|
547
|
+
final_width as f64,
|
|
548
|
+
final_height as f64,
|
|
520
549
|
))
|
|
521
550
|
.with_resizable(true)
|
|
522
551
|
.with_always_on_top(options.always_on_top);
|