@21stware/rpui 0.4.4 → 0.5.4
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/core/live-render.d.ts +6 -0
- package/dist/gallery.d.ts +4 -1
- package/dist/gallery.js +137 -70
- package/dist/gallery.js.map +1 -1
- package/dist/rpui.d.ts +2 -1
- package/dist/rpui.js +25 -0
- package/dist/rpui.js.map +1 -1
- package/dist/serve.js +48 -8
- package/package.json +2 -4
package/dist/serve.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createServer } from "node:http";
|
|
3
|
-
import { existsSync, statSync, readFileSync, writeFileSync, readdirSync } from "node:fs";
|
|
3
|
+
import { existsSync, statSync, readFileSync, watch, writeFileSync, readdirSync } from "node:fs";
|
|
4
4
|
import { dirname, join, resolve, sep, basename, relative } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { spawn } from "node:child_process";
|
|
@@ -25,9 +25,10 @@ function collectRpml(dir) {
|
|
|
25
25
|
function escapeHtml(s) {
|
|
26
26
|
return s.replace(/[&<>]/g, (c) => ({ "&": "&", "<": "<", ">": ">" })[c]);
|
|
27
27
|
}
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
function safeJson(docs) {
|
|
29
|
+
return JSON.stringify(docs).replace(/<\/script/gi, "<\\/script").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
30
|
+
}
|
|
31
|
+
function buildHtml(docs, title, galleryJs, live = false) {
|
|
31
32
|
return `<!doctype html>
|
|
32
33
|
<html lang="zh-CN">
|
|
33
34
|
<head>
|
|
@@ -37,7 +38,7 @@ function buildHtml(dir, title, galleryJs) {
|
|
|
37
38
|
<style>html,body{margin:0;height:100%}</style>
|
|
38
39
|
</head>
|
|
39
40
|
<body>
|
|
40
|
-
<script>globalThis.__RPML_DOCS__ = ${
|
|
41
|
+
<script>globalThis.__RPML_DOCS__ = ${safeJson(docs)};${live ? "globalThis.__RPML_LIVE__ = true;" : ""}<\/script>
|
|
41
42
|
<script type="module">
|
|
42
43
|
${galleryJs}
|
|
43
44
|
<\/script>
|
|
@@ -121,12 +122,24 @@ async function serve(argv) {
|
|
|
121
122
|
}
|
|
122
123
|
const galleryJs = readFileSync(GALLERY_JS, "utf8");
|
|
123
124
|
const title = root.split(sep).pop() || "RPML";
|
|
125
|
+
const clients = /* @__PURE__ */ new Set();
|
|
124
126
|
const server = createServer((req, res) => {
|
|
125
127
|
const url = (req.url || "/").split("?")[0];
|
|
126
128
|
try {
|
|
129
|
+
if (url === "/~live") {
|
|
130
|
+
res.writeHead(200, {
|
|
131
|
+
"content-type": "text/event-stream; charset=utf-8",
|
|
132
|
+
"cache-control": "no-cache, no-transform",
|
|
133
|
+
connection: "keep-alive"
|
|
134
|
+
});
|
|
135
|
+
res.write("retry: 1000\n\n");
|
|
136
|
+
clients.add(res);
|
|
137
|
+
req.on("close", () => clients.delete(res));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
127
140
|
if (url === "/" || !url.endsWith(".rpml")) {
|
|
128
141
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
129
|
-
res.end(buildHtml(root, title, galleryJs));
|
|
142
|
+
res.end(buildHtml(collectRpml(root), title, galleryJs, true));
|
|
130
143
|
return;
|
|
131
144
|
}
|
|
132
145
|
const file = join(root, decodeURIComponent(url.replace(/^\/+/, "")));
|
|
@@ -142,15 +155,42 @@ async function serve(argv) {
|
|
|
142
155
|
res.end("Error: " + e.message);
|
|
143
156
|
}
|
|
144
157
|
});
|
|
158
|
+
let lastJson = "";
|
|
159
|
+
const pushUpdate = () => {
|
|
160
|
+
let docs;
|
|
161
|
+
try {
|
|
162
|
+
docs = collectRpml(root);
|
|
163
|
+
} catch {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const json = safeJson(docs);
|
|
167
|
+
if (json === lastJson) return;
|
|
168
|
+
lastJson = json;
|
|
169
|
+
const frame = `data: ${json}
|
|
170
|
+
|
|
171
|
+
`;
|
|
172
|
+
for (const res of clients) res.write(frame);
|
|
173
|
+
};
|
|
174
|
+
let debounce;
|
|
175
|
+
const onChange = () => {
|
|
176
|
+
clearTimeout(debounce);
|
|
177
|
+
debounce = setTimeout(pushUpdate, 80);
|
|
178
|
+
};
|
|
179
|
+
try {
|
|
180
|
+
watch(root, { recursive: true }, onChange);
|
|
181
|
+
} catch {
|
|
182
|
+
setInterval(pushUpdate, 700);
|
|
183
|
+
}
|
|
145
184
|
const actualPort = await listen(server, port, host);
|
|
146
185
|
const count = collectRpml(root).length;
|
|
186
|
+
lastJson = safeJson(collectRpml(root));
|
|
147
187
|
const addr = `http://${host}:${actualPort}`;
|
|
148
188
|
console.log(``);
|
|
149
189
|
console.log(` RPUI serving ${count} .rpml file${count === 1 ? "" : "s"} from ${root}`);
|
|
150
190
|
console.log(``);
|
|
151
191
|
console.log(` Local: ${addr}`);
|
|
152
192
|
console.log(``);
|
|
153
|
-
console.log(` Press Ctrl+C to stop`);
|
|
193
|
+
console.log(` Live reload on — edits render in place. Press Ctrl+C to stop`);
|
|
154
194
|
if (open) openBrowser(addr);
|
|
155
195
|
}
|
|
156
196
|
function build(argv) {
|
|
@@ -186,7 +226,7 @@ function build(argv) {
|
|
|
186
226
|
console.error(`✗ No .rpml files found in ${root}`);
|
|
187
227
|
process.exit(1);
|
|
188
228
|
}
|
|
189
|
-
writeFileSync(out, buildHtml(root, title, galleryJs));
|
|
229
|
+
writeFileSync(out, buildHtml(collectRpml(root), title, galleryJs));
|
|
190
230
|
console.log(`✓ compiled ${count} .rpml file${count === 1 ? "" : "s"} → ${out}`);
|
|
191
231
|
}
|
|
192
232
|
const [sub, ...rest] = process.argv.slice(2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@21stware/rpui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "RPUI: static UI prototype renderer (RPML Web Components runtime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/rpui.js",
|
|
@@ -14,9 +14,7 @@
|
|
|
14
14
|
"types": "./dist/rpui.d.ts",
|
|
15
15
|
"default": "./dist/rpui.js"
|
|
16
16
|
},
|
|
17
|
-
"./dist/rpui.js": "./dist/rpui.js"
|
|
18
|
-
"./llms.txt": "../../llms.txt",
|
|
19
|
-
"./SKILL.md": "../../rapid-prototype-implement/SKILL.md"
|
|
17
|
+
"./dist/rpui.js": "./dist/rpui.js"
|
|
20
18
|
},
|
|
21
19
|
"sideEffects": true,
|
|
22
20
|
"files": [
|