@21stware/rpui 0.3.1 → 0.4.2

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/dist/serve.js CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createServer } from "node:http";
3
- import { existsSync, statSync, readFileSync, readdirSync } from "node:fs";
4
- import { dirname, join, resolve, sep, relative } from "node:path";
3
+ import { existsSync, statSync, readFileSync, writeFileSync, readdirSync } from "node:fs";
4
+ import { dirname, join, resolve, sep, basename, relative } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
+ import { spawn } from "node:child_process";
6
7
  const __dirname$1 = dirname(fileURLToPath(import.meta.url));
7
8
  const GALLERY_JS = join(__dirname$1, "gallery.js");
8
9
  function collectRpml(dir) {
@@ -44,31 +45,51 @@ ${galleryJs}
44
45
  </html>
45
46
  `;
46
47
  }
48
+ function openBrowser(url) {
49
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
50
+ const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
51
+ try {
52
+ const child = spawn(cmd, args, { stdio: "ignore", detached: true });
53
+ child.on("error", () => {
54
+ });
55
+ child.unref();
56
+ } catch {
57
+ }
58
+ }
47
59
  function parseArgs(argv) {
48
60
  let dir = ".";
49
61
  let port = 3e3;
50
62
  let host = "localhost";
63
+ let open = true;
51
64
  let sawPositional = false;
52
65
  for (let i = 0; i < argv.length; i++) {
53
66
  const a = argv[i];
54
67
  if (a === "-p" || a === "--port") port = Number(argv[++i]) || port;
55
68
  else if (a === "--host") host = argv[++i] || host;
69
+ else if (a === "--no-open") open = false;
70
+ else if (a === "--open") open = true;
56
71
  else if (a === "-h" || a === "--help") usage();
57
72
  else if (!a.startsWith("-") && !sawPositional) {
58
73
  dir = a;
59
74
  sawPositional = true;
60
75
  }
61
76
  }
62
- return { dir, port, host };
77
+ return { dir, port, host, open };
63
78
  }
64
79
  function usage() {
65
- console.error(`Usage: rpui serve [dir] [--port 3000] [--host localhost]
80
+ console.error(`Usage:
81
+ rpui serve [dir] [--port 3000] [--host localhost] [--no-open]
82
+ rpui build [dir] [-o out.html] [--title "..."]
66
83
 
67
- Host a directory of .rpml files as one navigable gallery.
84
+ serve — host a directory of .rpml files as one navigable gallery (opens the browser).
85
+ build — compile a directory of .rpml files into one self-contained HTML.
68
86
 
69
- dir directory to serve (default: current directory)
70
- -p, --port port (default 3000; auto-increments if busy)
71
- --host host (default localhost)`);
87
+ dir directory (default: current directory)
88
+ -p, --port serve: port (default 3000; auto-increments if busy)
89
+ --host serve: host (default localhost)
90
+ --no-open serve: do not open the browser
91
+ -o, --out build: output HTML path (default: <dir>.html)
92
+ --title build: gallery title (default: directory name)`);
72
93
  process.exit(1);
73
94
  }
74
95
  function listen(server, port, host) {
@@ -88,7 +109,7 @@ function listen(server, port, host) {
88
109
  });
89
110
  }
90
111
  async function serve(argv) {
91
- const { dir, port, host } = parseArgs(argv);
112
+ const { dir, port, host, open } = parseArgs(argv);
92
113
  const root = resolve(dir);
93
114
  if (!existsSync(root) || !statSync(root).isDirectory()) {
94
115
  console.error(`✗ Not a directory: ${dir}`);
@@ -130,10 +151,49 @@ async function serve(argv) {
130
151
  console.log(` Local: ${addr}`);
131
152
  console.log(``);
132
153
  console.log(` Press Ctrl+C to stop`);
154
+ if (open) openBrowser(addr);
155
+ }
156
+ function build(argv) {
157
+ let dir = ".";
158
+ let out = "";
159
+ let title = "";
160
+ let sawPositional = false;
161
+ for (let i = 0; i < argv.length; i++) {
162
+ const a = argv[i];
163
+ if (a === "-o" || a === "--out") out = argv[++i] || out;
164
+ else if (a === "--title") title = argv[++i] || title;
165
+ else if (a === "-h" || a === "--help") usage();
166
+ else if (!a.startsWith("-") && !sawPositional) {
167
+ dir = a;
168
+ sawPositional = true;
169
+ }
170
+ }
171
+ const root = resolve(dir);
172
+ if (!existsSync(root) || !statSync(root).isDirectory()) {
173
+ console.error(`✗ Not a directory: ${dir}`);
174
+ process.exit(1);
175
+ }
176
+ if (!existsSync(GALLERY_JS)) {
177
+ console.error(`✗ Missing runtime bundle (gallery.js). Reinstall @21stware/rpui or run the build.`);
178
+ process.exit(1);
179
+ }
180
+ const name = basename(root) || "RPML";
181
+ if (!out) out = `${name}.html`;
182
+ if (!title) title = name;
183
+ const galleryJs = readFileSync(GALLERY_JS, "utf8");
184
+ const count = collectRpml(root).length;
185
+ if (!count) {
186
+ console.error(`✗ No .rpml files found in ${root}`);
187
+ process.exit(1);
188
+ }
189
+ writeFileSync(out, buildHtml(root, title, galleryJs));
190
+ console.log(`✓ compiled ${count} .rpml file${count === 1 ? "" : "s"} → ${out}`);
133
191
  }
134
192
  const [sub, ...rest] = process.argv.slice(2);
135
193
  if (sub === "serve") {
136
194
  serve(rest);
195
+ } else if (sub === "build") {
196
+ build(rest);
137
197
  } else if (sub === "-h" || sub === "--help" || sub === void 0) {
138
198
  usage();
139
199
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@21stware/rpui",
3
- "version": "0.3.1",
3
+ "version": "0.4.2",
4
4
  "description": "RPUI: static UI prototype renderer (RPML Web Components runtime)",
5
5
  "type": "module",
6
6
  "main": "dist/rpui.js",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "./dist/rpui.js": "./dist/rpui.js",
18
18
  "./llms.txt": "../../llms.txt",
19
- "./SKILL.md": "../../SKILL.md"
19
+ "./SKILL.md": "../../rapid-prototype-implement/SKILL.md"
20
20
  },
21
21
  "sideEffects": true,
22
22
  "files": [
@@ -35,5 +35,8 @@
35
35
  "rpml-parser": "workspace:*",
36
36
  "typescript": "^5.8.3",
37
37
  "vite": "^5.4.11"
38
+ },
39
+ "dependencies": {
40
+ "beautiful-mermaid": "^1.1.3"
38
41
  }
39
42
  }