@aigne/afs-ui 1.11.0-beta.12
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/LICENSE.md +26 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +10 -0
- package/dist/aup-protocol.cjs +235 -0
- package/dist/aup-protocol.d.cts +78 -0
- package/dist/aup-protocol.d.cts.map +1 -0
- package/dist/aup-protocol.d.mts +78 -0
- package/dist/aup-protocol.d.mts.map +1 -0
- package/dist/aup-protocol.mjs +235 -0
- package/dist/aup-protocol.mjs.map +1 -0
- package/dist/aup-registry.cjs +2489 -0
- package/dist/aup-registry.mjs +2487 -0
- package/dist/aup-registry.mjs.map +1 -0
- package/dist/aup-spec.cjs +1467 -0
- package/dist/aup-spec.mjs +1466 -0
- package/dist/aup-spec.mjs.map +1 -0
- package/dist/aup-types.cjs +165 -0
- package/dist/aup-types.d.cts +157 -0
- package/dist/aup-types.d.cts.map +1 -0
- package/dist/aup-types.d.mts +157 -0
- package/dist/aup-types.d.mts.map +1 -0
- package/dist/aup-types.mjs +157 -0
- package/dist/aup-types.mjs.map +1 -0
- package/dist/backend.cjs +14 -0
- package/dist/backend.d.cts +104 -0
- package/dist/backend.d.cts.map +1 -0
- package/dist/backend.d.mts +104 -0
- package/dist/backend.d.mts.map +1 -0
- package/dist/backend.mjs +13 -0
- package/dist/backend.mjs.map +1 -0
- package/dist/degradation.cjs +85 -0
- package/dist/degradation.d.cts +17 -0
- package/dist/degradation.d.cts.map +1 -0
- package/dist/degradation.d.mts +17 -0
- package/dist/degradation.d.mts.map +1 -0
- package/dist/degradation.mjs +84 -0
- package/dist/degradation.mjs.map +1 -0
- package/dist/index.cjs +36 -0
- package/dist/index.d.cts +12 -0
- package/dist/index.d.mts +12 -0
- package/dist/index.mjs +13 -0
- package/dist/runtime.cjs +117 -0
- package/dist/runtime.d.cts +59 -0
- package/dist/runtime.d.cts.map +1 -0
- package/dist/runtime.d.mts +59 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +118 -0
- package/dist/runtime.mjs.map +1 -0
- package/dist/session.cjs +159 -0
- package/dist/session.d.cts +80 -0
- package/dist/session.d.cts.map +1 -0
- package/dist/session.d.mts +80 -0
- package/dist/session.d.mts.map +1 -0
- package/dist/session.mjs +159 -0
- package/dist/session.mjs.map +1 -0
- package/dist/snapshot.cjs +162 -0
- package/dist/snapshot.mjs +163 -0
- package/dist/snapshot.mjs.map +1 -0
- package/dist/term-page.cjs +264 -0
- package/dist/term-page.mjs +264 -0
- package/dist/term-page.mjs.map +1 -0
- package/dist/term.cjs +295 -0
- package/dist/term.d.cts +84 -0
- package/dist/term.d.cts.map +1 -0
- package/dist/term.d.mts +84 -0
- package/dist/term.d.mts.map +1 -0
- package/dist/term.mjs +296 -0
- package/dist/term.mjs.map +1 -0
- package/dist/tty.cjs +136 -0
- package/dist/tty.d.cts +53 -0
- package/dist/tty.d.cts.map +1 -0
- package/dist/tty.d.mts +53 -0
- package/dist/tty.d.mts.map +1 -0
- package/dist/tty.mjs +135 -0
- package/dist/tty.mjs.map +1 -0
- package/dist/ui-provider.cjs +4615 -0
- package/dist/ui-provider.d.cts +307 -0
- package/dist/ui-provider.d.cts.map +1 -0
- package/dist/ui-provider.d.mts +307 -0
- package/dist/ui-provider.d.mts.map +1 -0
- package/dist/ui-provider.mjs +4616 -0
- package/dist/ui-provider.mjs.map +1 -0
- package/dist/web-page/core.cjs +1388 -0
- package/dist/web-page/core.mjs +1387 -0
- package/dist/web-page/core.mjs.map +1 -0
- package/dist/web-page/css.cjs +1699 -0
- package/dist/web-page/css.mjs +1698 -0
- package/dist/web-page/css.mjs.map +1 -0
- package/dist/web-page/icons.cjs +248 -0
- package/dist/web-page/icons.mjs +248 -0
- package/dist/web-page/icons.mjs.map +1 -0
- package/dist/web-page/overlay-themes.cjs +514 -0
- package/dist/web-page/overlay-themes.mjs +513 -0
- package/dist/web-page/overlay-themes.mjs.map +1 -0
- package/dist/web-page/renderers/action.cjs +72 -0
- package/dist/web-page/renderers/action.mjs +72 -0
- package/dist/web-page/renderers/action.mjs.map +1 -0
- package/dist/web-page/renderers/broadcast.cjs +160 -0
- package/dist/web-page/renderers/broadcast.mjs +160 -0
- package/dist/web-page/renderers/broadcast.mjs.map +1 -0
- package/dist/web-page/renderers/calendar.cjs +137 -0
- package/dist/web-page/renderers/calendar.mjs +137 -0
- package/dist/web-page/renderers/calendar.mjs.map +1 -0
- package/dist/web-page/renderers/canvas.cjs +173 -0
- package/dist/web-page/renderers/canvas.mjs +173 -0
- package/dist/web-page/renderers/canvas.mjs.map +1 -0
- package/dist/web-page/renderers/cdn-loader.cjs +25 -0
- package/dist/web-page/renderers/cdn-loader.mjs +25 -0
- package/dist/web-page/renderers/cdn-loader.mjs.map +1 -0
- package/dist/web-page/renderers/chart.cjs +101 -0
- package/dist/web-page/renderers/chart.mjs +101 -0
- package/dist/web-page/renderers/chart.mjs.map +1 -0
- package/dist/web-page/renderers/deck.cjs +390 -0
- package/dist/web-page/renderers/deck.mjs +390 -0
- package/dist/web-page/renderers/deck.mjs.map +1 -0
- package/dist/web-page/renderers/device.cjs +1015 -0
- package/dist/web-page/renderers/device.mjs +1015 -0
- package/dist/web-page/renderers/device.mjs.map +1 -0
- package/dist/web-page/renderers/editor.cjs +127 -0
- package/dist/web-page/renderers/editor.mjs +127 -0
- package/dist/web-page/renderers/editor.mjs.map +1 -0
- package/dist/web-page/renderers/finance-chart.cjs +178 -0
- package/dist/web-page/renderers/finance-chart.mjs +178 -0
- package/dist/web-page/renderers/finance-chart.mjs.map +1 -0
- package/dist/web-page/renderers/frame.cjs +274 -0
- package/dist/web-page/renderers/frame.mjs +274 -0
- package/dist/web-page/renderers/frame.mjs.map +1 -0
- package/dist/web-page/renderers/globe.cjs +119 -0
- package/dist/web-page/renderers/globe.mjs +119 -0
- package/dist/web-page/renderers/globe.mjs.map +1 -0
- package/dist/web-page/renderers/input.cjs +137 -0
- package/dist/web-page/renderers/input.mjs +137 -0
- package/dist/web-page/renderers/input.mjs.map +1 -0
- package/dist/web-page/renderers/list.cjs +1243 -0
- package/dist/web-page/renderers/list.mjs +1243 -0
- package/dist/web-page/renderers/list.mjs.map +1 -0
- package/dist/web-page/renderers/map.cjs +126 -0
- package/dist/web-page/renderers/map.mjs +126 -0
- package/dist/web-page/renderers/map.mjs.map +1 -0
- package/dist/web-page/renderers/media.cjs +106 -0
- package/dist/web-page/renderers/media.mjs +106 -0
- package/dist/web-page/renderers/media.mjs.map +1 -0
- package/dist/web-page/renderers/moonphase.cjs +105 -0
- package/dist/web-page/renderers/moonphase.mjs +105 -0
- package/dist/web-page/renderers/moonphase.mjs.map +1 -0
- package/dist/web-page/renderers/natal-chart.cjs +222 -0
- package/dist/web-page/renderers/natal-chart.mjs +222 -0
- package/dist/web-page/renderers/natal-chart.mjs.map +1 -0
- package/dist/web-page/renderers/overlay.cjs +531 -0
- package/dist/web-page/renderers/overlay.mjs +531 -0
- package/dist/web-page/renderers/overlay.mjs.map +1 -0
- package/dist/web-page/renderers/table.cjs +74 -0
- package/dist/web-page/renderers/table.mjs +74 -0
- package/dist/web-page/renderers/table.mjs.map +1 -0
- package/dist/web-page/renderers/terminal.cjs +30 -0
- package/dist/web-page/renderers/terminal.mjs +30 -0
- package/dist/web-page/renderers/terminal.mjs.map +1 -0
- package/dist/web-page/renderers/text.cjs +109 -0
- package/dist/web-page/renderers/text.mjs +109 -0
- package/dist/web-page/renderers/text.mjs.map +1 -0
- package/dist/web-page/renderers/ticker.cjs +133 -0
- package/dist/web-page/renderers/ticker.mjs +133 -0
- package/dist/web-page/renderers/ticker.mjs.map +1 -0
- package/dist/web-page/renderers/time.cjs +69 -0
- package/dist/web-page/renderers/time.mjs +69 -0
- package/dist/web-page/renderers/time.mjs.map +1 -0
- package/dist/web-page/renderers/unknown.cjs +20 -0
- package/dist/web-page/renderers/unknown.mjs +20 -0
- package/dist/web-page/renderers/unknown.mjs.map +1 -0
- package/dist/web-page/renderers/view.cjs +161 -0
- package/dist/web-page/renderers/view.mjs +161 -0
- package/dist/web-page/renderers/view.mjs.map +1 -0
- package/dist/web-page/renderers/wm.cjs +669 -0
- package/dist/web-page/renderers/wm.mjs +669 -0
- package/dist/web-page/renderers/wm.mjs.map +1 -0
- package/dist/web-page/skeleton.cjs +103 -0
- package/dist/web-page/skeleton.mjs +103 -0
- package/dist/web-page/skeleton.mjs.map +1 -0
- package/dist/web-page.cjs +114 -0
- package/dist/web-page.d.cts +19 -0
- package/dist/web-page.d.cts.map +1 -0
- package/dist/web-page.d.mts +19 -0
- package/dist/web-page.d.mts.map +1 -0
- package/dist/web-page.mjs +115 -0
- package/dist/web-page.mjs.map +1 -0
- package/dist/web.cjs +827 -0
- package/dist/web.d.cts +144 -0
- package/dist/web.d.cts.map +1 -0
- package/dist/web.d.mts +144 -0
- package/dist/web.d.mts.map +1 -0
- package/dist/web.mjs +828 -0
- package/dist/web.mjs.map +1 -0
- package/dist/wm-state.cjs +172 -0
- package/dist/wm-state.mjs +171 -0
- package/dist/wm-state.mjs.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { CORE_HEAD_JS } from "./web-page/core.mjs";
|
|
2
|
+
import { CSS, DECK_SHADOW_CSS } from "./web-page/css.mjs";
|
|
3
|
+
import { ICONS_JS } from "./web-page/icons.mjs";
|
|
4
|
+
import { OVERLAY_THEMES_CSS, OVERLAY_THEMES_JS } from "./web-page/overlay-themes.mjs";
|
|
5
|
+
import { ACTION_JS } from "./web-page/renderers/action.mjs";
|
|
6
|
+
import { BROADCAST_JS } from "./web-page/renderers/broadcast.mjs";
|
|
7
|
+
import { CALENDAR_JS } from "./web-page/renderers/calendar.mjs";
|
|
8
|
+
import { CANVAS_JS } from "./web-page/renderers/canvas.mjs";
|
|
9
|
+
import { CDN_LOADER_JS } from "./web-page/renderers/cdn-loader.mjs";
|
|
10
|
+
import { CHART_JS } from "./web-page/renderers/chart.mjs";
|
|
11
|
+
import { DECK_JS } from "./web-page/renderers/deck.mjs";
|
|
12
|
+
import { DEVICE_JS } from "./web-page/renderers/device.mjs";
|
|
13
|
+
import { EDITOR_JS } from "./web-page/renderers/editor.mjs";
|
|
14
|
+
import { FINANCE_CHART_JS } from "./web-page/renderers/finance-chart.mjs";
|
|
15
|
+
import { FRAME_JS } from "./web-page/renderers/frame.mjs";
|
|
16
|
+
import { GLOBE_JS } from "./web-page/renderers/globe.mjs";
|
|
17
|
+
import { INPUT_JS } from "./web-page/renderers/input.mjs";
|
|
18
|
+
import { LIST_JS } from "./web-page/renderers/list.mjs";
|
|
19
|
+
import { MAP_JS } from "./web-page/renderers/map.mjs";
|
|
20
|
+
import { MEDIA_JS } from "./web-page/renderers/media.mjs";
|
|
21
|
+
import { MOONPHASE_JS } from "./web-page/renderers/moonphase.mjs";
|
|
22
|
+
import { NATAL_CHART_JS } from "./web-page/renderers/natal-chart.mjs";
|
|
23
|
+
import { OVERLAY_JS } from "./web-page/renderers/overlay.mjs";
|
|
24
|
+
import { TABLE_JS } from "./web-page/renderers/table.mjs";
|
|
25
|
+
import { TERMINAL_JS } from "./web-page/renderers/terminal.mjs";
|
|
26
|
+
import { TEXT_JS } from "./web-page/renderers/text.mjs";
|
|
27
|
+
import { TICKER_JS } from "./web-page/renderers/ticker.mjs";
|
|
28
|
+
import { TIME_JS } from "./web-page/renderers/time.mjs";
|
|
29
|
+
import { UNKNOWN_JS } from "./web-page/renderers/unknown.mjs";
|
|
30
|
+
import { VIEW_JS } from "./web-page/renderers/view.mjs";
|
|
31
|
+
import { createRequire } from "node:module";
|
|
32
|
+
|
|
33
|
+
//#region src/snapshot.ts
|
|
34
|
+
/**
|
|
35
|
+
* AUP Snapshot Generator — Freeze an AUP tree into a self-contained HTML file.
|
|
36
|
+
*
|
|
37
|
+
* The snapshot HTML includes:
|
|
38
|
+
* - All CSS (inlined)
|
|
39
|
+
* - All renderer JS (inlined)
|
|
40
|
+
* - AUP tree data (embedded as JSON)
|
|
41
|
+
* - CDN dependencies (marked.js, highlight.js, DOMPurify, Google Fonts)
|
|
42
|
+
* - SEO metadata (og tags, title, description)
|
|
43
|
+
*
|
|
44
|
+
* The snapshot does NOT include:
|
|
45
|
+
* - WebSocket connection code
|
|
46
|
+
* - Session/token management
|
|
47
|
+
* - Input/prompt handling
|
|
48
|
+
* - Chat UI elements
|
|
49
|
+
*/
|
|
50
|
+
const AFS_VERSION = createRequire(import.meta.url)("../package.json").version || "unknown";
|
|
51
|
+
const AFS_VERSION_LITERAL = JSON.stringify(String(AFS_VERSION)).replace(/</g, "\\u003c");
|
|
52
|
+
/** HTML-escape a string for safe embedding in HTML attributes and content */
|
|
53
|
+
function escapeHtml(str) {
|
|
54
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
55
|
+
}
|
|
56
|
+
/** Build SEO meta tags for the <head> section */
|
|
57
|
+
function buildSeoTags(slug, meta) {
|
|
58
|
+
const tags = [];
|
|
59
|
+
const title = meta?.title || slug;
|
|
60
|
+
tags.push(`<title>${escapeHtml(title)}</title>`);
|
|
61
|
+
if (meta?.description) {
|
|
62
|
+
const desc = meta.description.length > 200 ? `${meta.description.slice(0, 200)}...` : meta.description;
|
|
63
|
+
tags.push(`<meta name="description" content="${escapeHtml(desc)}">`);
|
|
64
|
+
}
|
|
65
|
+
tags.push(`<meta property="og:title" content="${escapeHtml(title)}">`);
|
|
66
|
+
tags.push(`<meta property="og:type" content="website">`);
|
|
67
|
+
tags.push(`<meta property="og:url" content="/s/${escapeHtml(slug)}">`);
|
|
68
|
+
if (meta?.description) {
|
|
69
|
+
const ogDesc = meta.description.length > 200 ? `${meta.description.slice(0, 200)}...` : meta.description;
|
|
70
|
+
tags.push(`<meta property="og:description" content="${escapeHtml(ogDesc)}">`);
|
|
71
|
+
}
|
|
72
|
+
if (meta?.image && /^https?:\/\//i.test(meta.image)) tags.push(`<meta property="og:image" content="${escapeHtml(meta.image)}">`);
|
|
73
|
+
return tags.join("\n");
|
|
74
|
+
}
|
|
75
|
+
/** Generate a self-contained HTML snapshot of an AUP tree */
|
|
76
|
+
function generateSnapshot(options) {
|
|
77
|
+
const { tree, slug, meta, style, locale } = options;
|
|
78
|
+
const treeJson = JSON.stringify(tree).replace(/<\/script>/gi, "<\\/script>");
|
|
79
|
+
const seoTags = buildSeoTags(slug, meta);
|
|
80
|
+
return `<!DOCTYPE html>
|
|
81
|
+
<html lang="${locale ? escapeHtml(locale) : "en"}">
|
|
82
|
+
<head>
|
|
83
|
+
<meta charset="UTF-8">
|
|
84
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
85
|
+
${seoTags}
|
|
86
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
87
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
88
|
+
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600;9..40,700&family=Manrope:wght@400;500;600;700&family=Sora:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700&family=Share+Tech+Mono&family=JetBrains+Mono:wght@400;500&family=DM+Serif+Display:ital@0;1&family=Noto+Sans+SC:wght@300;400;500;600&family=Space+Mono:ital,wght@0,400;0,700;1,400&family=Instrument+Serif:ital@0;1&family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,700;1,9..144,400&family=Crimson+Pro:ital,wght@0,400;0,600;1,400&display=swap" rel="stylesheet">
|
|
89
|
+
<script src="https://cdn.jsdelivr.net/npm/marked@15/marked.min.js"><\/script>
|
|
90
|
+
<script src="https://cdn.jsdelivr.net/npm/marked-highlight@2/lib/index.umd.min.js"><\/script>
|
|
91
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark-dimmed.min.css">
|
|
92
|
+
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"><\/script>
|
|
93
|
+
<script src="https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js"><\/script>
|
|
94
|
+
<style>
|
|
95
|
+
${CSS}
|
|
96
|
+
</style>
|
|
97
|
+
</head>
|
|
98
|
+
<body>
|
|
99
|
+
<div id="aup-display" class="active full-page" style="display:flex">
|
|
100
|
+
<div id="aup-root" class="aup-animating"></div>
|
|
101
|
+
</div>
|
|
102
|
+
<script>
|
|
103
|
+
(function() {
|
|
104
|
+
var _AFS_VERSION = ${AFS_VERSION_LITERAL};
|
|
105
|
+
var _SNAPSHOT_MODE = true;
|
|
106
|
+
${CORE_HEAD_JS}
|
|
107
|
+
${ICONS_JS}
|
|
108
|
+
|
|
109
|
+
${VIEW_JS}
|
|
110
|
+
${TEXT_JS}
|
|
111
|
+
${ACTION_JS}
|
|
112
|
+
${INPUT_JS}
|
|
113
|
+
${MEDIA_JS}
|
|
114
|
+
${OVERLAY_JS}
|
|
115
|
+
${TABLE_JS}
|
|
116
|
+
${TERMINAL_JS}
|
|
117
|
+
${CDN_LOADER_JS}
|
|
118
|
+
${TIME_JS}
|
|
119
|
+
${CHART_JS}
|
|
120
|
+
${FINANCE_CHART_JS}
|
|
121
|
+
${MAP_JS}
|
|
122
|
+
${GLOBE_JS}
|
|
123
|
+
${CALENDAR_JS}
|
|
124
|
+
${MOONPHASE_JS}
|
|
125
|
+
${NATAL_CHART_JS}
|
|
126
|
+
${EDITOR_JS}
|
|
127
|
+
${FRAME_JS}
|
|
128
|
+
${CANVAS_JS}
|
|
129
|
+
${TICKER_JS}
|
|
130
|
+
${BROADCAST_JS}
|
|
131
|
+
${LIST_JS}
|
|
132
|
+
${DEVICE_JS}
|
|
133
|
+
var _OVERLAY_THEMES_CSS = ${JSON.stringify(OVERLAY_THEMES_CSS)};
|
|
134
|
+
${OVERLAY_THEMES_JS}
|
|
135
|
+
var _DECK_SHADOW_CSS = ${JSON.stringify(DECK_SHADOW_CSS)};
|
|
136
|
+
${DECK_JS}
|
|
137
|
+
${UNKNOWN_JS}
|
|
138
|
+
|
|
139
|
+
// ── Snapshot: static render (no WebSocket) ──
|
|
140
|
+
var aupDisplayEl = document.getElementById("aup-display");
|
|
141
|
+
var aupRootEl = document.getElementById("aup-root");
|
|
142
|
+
var aupNodeTree = ${treeJson};
|
|
143
|
+
|
|
144
|
+
${style ? `setStyle(${JSON.stringify(style)});` : ""}
|
|
145
|
+
|
|
146
|
+
function renderAupTree() {
|
|
147
|
+
if (!aupNodeTree || !aupRootEl) return;
|
|
148
|
+
aupRootEl.innerHTML = "";
|
|
149
|
+
var el = renderAupNode(aupNodeTree);
|
|
150
|
+
if (el) aupRootEl.appendChild(el);
|
|
151
|
+
aupRootEl.classList.remove("aup-animating");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
renderAupTree();
|
|
155
|
+
})();
|
|
156
|
+
<\/script>
|
|
157
|
+
</body>
|
|
158
|
+
</html>`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
//#endregion
|
|
162
|
+
export { generateSnapshot };
|
|
163
|
+
//# sourceMappingURL=snapshot.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.mjs","names":[],"sources":["../src/snapshot.ts"],"sourcesContent":["/**\n * AUP Snapshot Generator — Freeze an AUP tree into a self-contained HTML file.\n *\n * The snapshot HTML includes:\n * - All CSS (inlined)\n * - All renderer JS (inlined)\n * - AUP tree data (embedded as JSON)\n * - CDN dependencies (marked.js, highlight.js, DOMPurify, Google Fonts)\n * - SEO metadata (og tags, title, description)\n *\n * The snapshot does NOT include:\n * - WebSocket connection code\n * - Session/token management\n * - Input/prompt handling\n * - Chat UI elements\n */\n\nimport { createRequire } from \"node:module\";\nimport type { AUPNode } from \"./aup-types.js\";\nimport { CORE_HEAD_JS } from \"./web-page/core.js\";\nimport { CSS, DECK_SHADOW_CSS } from \"./web-page/css.js\";\nimport { ICONS_JS } from \"./web-page/icons.js\";\nimport { OVERLAY_THEMES_CSS, OVERLAY_THEMES_JS } from \"./web-page/overlay-themes.js\";\nimport { ACTION_JS } from \"./web-page/renderers/action.js\";\nimport { BROADCAST_JS } from \"./web-page/renderers/broadcast.js\";\nimport { CALENDAR_JS } from \"./web-page/renderers/calendar.js\";\nimport { CANVAS_JS } from \"./web-page/renderers/canvas.js\";\nimport { CDN_LOADER_JS } from \"./web-page/renderers/cdn-loader.js\";\nimport { CHART_JS } from \"./web-page/renderers/chart.js\";\nimport { DECK_JS } from \"./web-page/renderers/deck.js\";\nimport { DEVICE_JS } from \"./web-page/renderers/device.js\";\nimport { EDITOR_JS } from \"./web-page/renderers/editor.js\";\nimport { FINANCE_CHART_JS } from \"./web-page/renderers/finance-chart.js\";\nimport { FRAME_JS } from \"./web-page/renderers/frame.js\";\nimport { GLOBE_JS } from \"./web-page/renderers/globe.js\";\nimport { INPUT_JS } from \"./web-page/renderers/input.js\";\nimport { LIST_JS } from \"./web-page/renderers/list.js\";\nimport { MAP_JS } from \"./web-page/renderers/map.js\";\nimport { MEDIA_JS } from \"./web-page/renderers/media.js\";\nimport { MOONPHASE_JS } from \"./web-page/renderers/moonphase.js\";\nimport { NATAL_CHART_JS } from \"./web-page/renderers/natal-chart.js\";\nimport { OVERLAY_JS } from \"./web-page/renderers/overlay.js\";\nimport { TABLE_JS } from \"./web-page/renderers/table.js\";\nimport { TERMINAL_JS } from \"./web-page/renderers/terminal.js\";\nimport { TEXT_JS } from \"./web-page/renderers/text.js\";\nimport { TICKER_JS } from \"./web-page/renderers/ticker.js\";\nimport { TIME_JS } from \"./web-page/renderers/time.js\";\nimport { UNKNOWN_JS } from \"./web-page/renderers/unknown.js\";\nimport { VIEW_JS } from \"./web-page/renderers/view.js\";\n\nconst _require = createRequire(import.meta.url);\nconst _pkg = _require(\"../package.json\");\nconst AFS_VERSION: string = _pkg.version || \"unknown\";\nconst AFS_VERSION_LITERAL = JSON.stringify(String(AFS_VERSION)).replace(/</g, \"\\\\u003c\");\n\nexport interface SnapshotOptions {\n /** AUP tree to embed */\n tree: AUPNode;\n /** Sharing entry slug (for og:url) */\n slug: string;\n /** SEO metadata */\n meta?: {\n title?: string;\n description?: string;\n image?: string;\n };\n /** Style/theme for the snapshot */\n style?: string;\n /** Locale for the snapshot */\n locale?: string;\n}\n\n/** HTML-escape a string for safe embedding in HTML attributes and content */\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n/** Build SEO meta tags for the <head> section */\nfunction buildSeoTags(slug: string, meta?: SnapshotOptions[\"meta\"]): string {\n const tags: string[] = [];\n const title = meta?.title || slug;\n\n // Title tag\n tags.push(`<title>${escapeHtml(title)}</title>`);\n\n // Description meta tag (only if description is provided)\n if (meta?.description) {\n const desc =\n meta.description.length > 200 ? `${meta.description.slice(0, 200)}...` : meta.description;\n tags.push(`<meta name=\"description\" content=\"${escapeHtml(desc)}\">`);\n }\n\n // Open Graph tags\n tags.push(`<meta property=\"og:title\" content=\"${escapeHtml(title)}\">`);\n tags.push(`<meta property=\"og:type\" content=\"website\">`);\n tags.push(`<meta property=\"og:url\" content=\"/s/${escapeHtml(slug)}\">`);\n\n if (meta?.description) {\n const ogDesc =\n meta.description.length > 200 ? `${meta.description.slice(0, 200)}...` : meta.description;\n tags.push(`<meta property=\"og:description\" content=\"${escapeHtml(ogDesc)}\">`);\n }\n\n // Only include og:image for http/https URLs\n if (meta?.image && /^https?:\\/\\//i.test(meta.image)) {\n tags.push(`<meta property=\"og:image\" content=\"${escapeHtml(meta.image)}\">`);\n }\n\n return tags.join(\"\\n\");\n}\n\n/** Generate a self-contained HTML snapshot of an AUP tree */\nexport function generateSnapshot(options: SnapshotOptions): string {\n const { tree, slug, meta, style, locale } = options;\n\n // Serialize tree to JSON for embedding\n const treeJson = JSON.stringify(tree).replace(/<\\/script>/gi, \"<\\\\/script>\");\n\n const seoTags = buildSeoTags(slug, meta);\n\n const langAttr = locale ? escapeHtml(locale) : \"en\";\n\n return `<!DOCTYPE html>\n<html lang=\"${langAttr}\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n${seoTags}\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600;9..40,700&family=Manrope:wght@400;500;600;700&family=Sora:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700&family=Share+Tech+Mono&family=JetBrains+Mono:wght@400;500&family=DM+Serif+Display:ital@0;1&family=Noto+Sans+SC:wght@300;400;500;600&family=Space+Mono:ital,wght@0,400;0,700;1,400&family=Instrument+Serif:ital@0;1&family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,700;1,9..144,400&family=Crimson+Pro:ital,wght@0,400;0,600;1,400&display=swap\" rel=\"stylesheet\">\n<script src=\"https://cdn.jsdelivr.net/npm/marked@15/marked.min.js\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/marked-highlight@2/lib/index.umd.min.js\"></script>\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark-dimmed.min.css\">\n<script src=\"https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js\"></script>\n<style>\n${CSS}\n</style>\n</head>\n<body>\n<div id=\"aup-display\" class=\"active full-page\" style=\"display:flex\">\n<div id=\"aup-root\" class=\"aup-animating\"></div>\n</div>\n<script>\n(function() {\nvar _AFS_VERSION = ${AFS_VERSION_LITERAL};\nvar _SNAPSHOT_MODE = true;\n${CORE_HEAD_JS}\n${ICONS_JS}\n\n${VIEW_JS}\n${TEXT_JS}\n${ACTION_JS}\n${INPUT_JS}\n${MEDIA_JS}\n${OVERLAY_JS}\n${TABLE_JS}\n${TERMINAL_JS}\n${CDN_LOADER_JS}\n${TIME_JS}\n${CHART_JS}\n${FINANCE_CHART_JS}\n${MAP_JS}\n${GLOBE_JS}\n${CALENDAR_JS}\n${MOONPHASE_JS}\n${NATAL_CHART_JS}\n${EDITOR_JS}\n${FRAME_JS}\n${CANVAS_JS}\n${TICKER_JS}\n${BROADCAST_JS}\n${LIST_JS}\n${DEVICE_JS}\nvar _OVERLAY_THEMES_CSS = ${JSON.stringify(OVERLAY_THEMES_CSS)};\n${OVERLAY_THEMES_JS}\nvar _DECK_SHADOW_CSS = ${JSON.stringify(DECK_SHADOW_CSS)};\n${DECK_JS}\n${UNKNOWN_JS}\n\n// ── Snapshot: static render (no WebSocket) ──\nvar aupDisplayEl = document.getElementById(\"aup-display\");\nvar aupRootEl = document.getElementById(\"aup-root\");\nvar aupNodeTree = ${treeJson};\n\n${style ? `setStyle(${JSON.stringify(style)});` : \"\"}\n\nfunction renderAupTree() {\n if (!aupNodeTree || !aupRootEl) return;\n aupRootEl.innerHTML = \"\";\n var el = renderAupNode(aupNodeTree);\n if (el) aupRootEl.appendChild(el);\n aupRootEl.classList.remove(\"aup-animating\");\n}\n\nrenderAupTree();\n})();\n</script>\n</body>\n</html>`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAM,cAFW,cAAc,OAAO,KAAK,IAAI,CACzB,kBAAkB,CACP,WAAW;AAC5C,MAAM,sBAAsB,KAAK,UAAU,OAAO,YAAY,CAAC,CAAC,QAAQ,MAAM,UAAU;;AAoBxF,SAAS,WAAW,KAAqB;AACvC,QAAO,IACJ,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,SAAS,CACvB,QAAQ,MAAM,SAAS;;;AAI5B,SAAS,aAAa,MAAc,MAAwC;CAC1E,MAAM,OAAiB,EAAE;CACzB,MAAM,QAAQ,MAAM,SAAS;AAG7B,MAAK,KAAK,UAAU,WAAW,MAAM,CAAC,UAAU;AAGhD,KAAI,MAAM,aAAa;EACrB,MAAM,OACJ,KAAK,YAAY,SAAS,MAAM,GAAG,KAAK,YAAY,MAAM,GAAG,IAAI,CAAC,OAAO,KAAK;AAChF,OAAK,KAAK,qCAAqC,WAAW,KAAK,CAAC,IAAI;;AAItE,MAAK,KAAK,sCAAsC,WAAW,MAAM,CAAC,IAAI;AACtE,MAAK,KAAK,8CAA8C;AACxD,MAAK,KAAK,uCAAuC,WAAW,KAAK,CAAC,IAAI;AAEtE,KAAI,MAAM,aAAa;EACrB,MAAM,SACJ,KAAK,YAAY,SAAS,MAAM,GAAG,KAAK,YAAY,MAAM,GAAG,IAAI,CAAC,OAAO,KAAK;AAChF,OAAK,KAAK,4CAA4C,WAAW,OAAO,CAAC,IAAI;;AAI/E,KAAI,MAAM,SAAS,gBAAgB,KAAK,KAAK,MAAM,CACjD,MAAK,KAAK,sCAAsC,WAAW,KAAK,MAAM,CAAC,IAAI;AAG7E,QAAO,KAAK,KAAK,KAAK;;;AAIxB,SAAgB,iBAAiB,SAAkC;CACjE,MAAM,EAAE,MAAM,MAAM,MAAM,OAAO,WAAW;CAG5C,MAAM,WAAW,KAAK,UAAU,KAAK,CAAC,QAAQ,gBAAgB,cAAc;CAE5E,MAAM,UAAU,aAAa,MAAM,KAAK;AAIxC,QAAO;cAFU,SAAS,WAAW,OAAO,GAAG,KAG1B;;;;EAIrB,QAAQ;;;;;;;;;;EAUR,IAAI;;;;;;;;;qBASe,oBAAoB;;EAEvC,aAAa;EACb,SAAS;;EAET,QAAQ;EACR,QAAQ;EACR,UAAU;EACV,SAAS;EACT,SAAS;EACT,WAAW;EACX,SAAS;EACT,YAAY;EACZ,cAAc;EACd,QAAQ;EACR,SAAS;EACT,iBAAiB;EACjB,OAAO;EACP,SAAS;EACT,YAAY;EACZ,aAAa;EACb,eAAe;EACf,UAAU;EACV,SAAS;EACT,UAAU;EACV,UAAU;EACV,aAAa;EACb,QAAQ;EACR,UAAU;4BACgB,KAAK,UAAU,mBAAmB,CAAC;EAC7D,kBAAkB;yBACK,KAAK,UAAU,gBAAgB,CAAC;EACvD,QAAQ;EACR,WAAW;;;;;oBAKO,SAAS;;EAE3B,QAAQ,YAAY,KAAK,UAAU,MAAM,CAAC,MAAM,GAAG"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/term-page.ts
|
|
3
|
+
/**
|
|
4
|
+
* Inline HTML template for the AFS UI terminal client.
|
|
5
|
+
*
|
|
6
|
+
* Self-contained — CDN dependencies for xterm.js terminal emulator.
|
|
7
|
+
* Ported from AOS terminal surface, adapted for AFS UIBackend WS protocol.
|
|
8
|
+
*
|
|
9
|
+
* WS Protocol (server→client):
|
|
10
|
+
* { type: "output", data: "text" } — write text to terminal
|
|
11
|
+
* { type: "prompt", message, promptType, options } — prompt request
|
|
12
|
+
* { type: "clear" } — clear terminal
|
|
13
|
+
* { type: "notify", message } — notification
|
|
14
|
+
*
|
|
15
|
+
* WS Protocol (client→server):
|
|
16
|
+
* { type: "line", content: "user input" } — complete line
|
|
17
|
+
* { type: "prompt_response", value: ... } — prompt answer
|
|
18
|
+
* { type: "resize", cols, rows } — terminal resize
|
|
19
|
+
*/
|
|
20
|
+
const TERM_CLIENT_HTML = `<!DOCTYPE html>
|
|
21
|
+
<html lang="en">
|
|
22
|
+
<head>
|
|
23
|
+
<meta charset="utf-8">
|
|
24
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
25
|
+
<title>AFS Terminal</title>
|
|
26
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xterm/xterm@5/css/xterm.min.css">
|
|
27
|
+
<style>
|
|
28
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
29
|
+
html, body { width: 100%; height: 100%; overflow: hidden; background: #0a0e14; }
|
|
30
|
+
#terminal { width: 100%; height: 100%; }
|
|
31
|
+
</style>
|
|
32
|
+
</head>
|
|
33
|
+
<body>
|
|
34
|
+
<div id="terminal"></div>
|
|
35
|
+
|
|
36
|
+
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@5/lib/xterm.min.js"><\/script>
|
|
37
|
+
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0/lib/addon-fit.min.js"><\/script>
|
|
38
|
+
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-webgl@0/lib/addon-webgl.min.js"><\/script>
|
|
39
|
+
<script>
|
|
40
|
+
var term = new window.Terminal({
|
|
41
|
+
cursorBlink: true,
|
|
42
|
+
fontSize: 14,
|
|
43
|
+
lineHeight: 1.2,
|
|
44
|
+
fontFamily: 'Menlo, "Fira Code", "Cascadia Code", monospace',
|
|
45
|
+
theme: {
|
|
46
|
+
background: '#0a0e14',
|
|
47
|
+
foreground: '#b3b1ad',
|
|
48
|
+
cursor: '#e6b450',
|
|
49
|
+
selectionBackground: '#1d3b53',
|
|
50
|
+
green: '#91b362',
|
|
51
|
+
brightGreen: '#a6cc70',
|
|
52
|
+
red: '#f07178',
|
|
53
|
+
brightRed: '#ff8f80',
|
|
54
|
+
yellow: '#e6b450',
|
|
55
|
+
brightYellow: '#ffee99',
|
|
56
|
+
blue: '#59c2ff',
|
|
57
|
+
brightBlue: '#73d0ff',
|
|
58
|
+
magenta: '#d2a6ff',
|
|
59
|
+
brightMagenta: '#dfbfff',
|
|
60
|
+
cyan: '#95e6cb',
|
|
61
|
+
brightCyan: '#a8e6cf',
|
|
62
|
+
white: '#b3b1ad',
|
|
63
|
+
brightWhite: '#ffffff',
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
var fitAddon = new window.FitAddon.FitAddon();
|
|
67
|
+
term.loadAddon(fitAddon);
|
|
68
|
+
term.open(document.getElementById('terminal'));
|
|
69
|
+
|
|
70
|
+
// WebGL renderer for pixel-perfect rendering
|
|
71
|
+
try {
|
|
72
|
+
var webglAddon = new window.WebglAddon.WebglAddon();
|
|
73
|
+
webglAddon.onContextLoss(function() { webglAddon.dispose(); });
|
|
74
|
+
term.loadAddon(webglAddon);
|
|
75
|
+
} catch(e) {
|
|
76
|
+
// WebGL not available — fall back to canvas
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
fitAddon.fit();
|
|
80
|
+
|
|
81
|
+
// ── State ──
|
|
82
|
+
var lineBuffer = '';
|
|
83
|
+
var ws = null;
|
|
84
|
+
var currentPrompt = null;
|
|
85
|
+
|
|
86
|
+
function writeAnsi(text) {
|
|
87
|
+
// Convert \\n to \\r\\n for xterm
|
|
88
|
+
var lines = text.split('\\n');
|
|
89
|
+
for (var i = 0; i < lines.length; i++) {
|
|
90
|
+
if (i > 0) term.write('\\r\\n');
|
|
91
|
+
term.write(lines[i]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function writePromptText() {
|
|
96
|
+
if (currentPrompt) return;
|
|
97
|
+
term.write('\\x1b[33m> \\x1b[0m');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Replace the current line buffer, updating the terminal display. */
|
|
101
|
+
function replaceLine(text) {
|
|
102
|
+
if (lineBuffer.length > 0) {
|
|
103
|
+
term.write('\\x1b[' + lineBuffer.length + 'D');
|
|
104
|
+
term.write('\\x1b[K');
|
|
105
|
+
}
|
|
106
|
+
lineBuffer = text;
|
|
107
|
+
term.write(text);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ── WebSocket ──
|
|
111
|
+
function connect() {
|
|
112
|
+
var proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
113
|
+
ws = new WebSocket(proto + '//' + location.host);
|
|
114
|
+
|
|
115
|
+
ws.onopen = function() {
|
|
116
|
+
term.writeln('\\x1b[32m● connected\\x1b[0m');
|
|
117
|
+
writePromptText();
|
|
118
|
+
// Send initial size
|
|
119
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
120
|
+
ws.send(JSON.stringify({ type: 'resize', cols: term.cols, rows: term.rows }));
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
ws.onclose = function() {
|
|
125
|
+
term.writeln('\\r\\n\\x1b[31m● disconnected — reconnecting...\\x1b[0m');
|
|
126
|
+
setTimeout(connect, 2000);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
ws.onerror = function() {
|
|
130
|
+
term.writeln('\\r\\n\\x1b[31m● connection error\\x1b[0m');
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
ws.onmessage = function(evt) {
|
|
134
|
+
var msg;
|
|
135
|
+
try { msg = JSON.parse(evt.data); } catch(e) { return; }
|
|
136
|
+
|
|
137
|
+
if (msg.type === 'output') {
|
|
138
|
+
writeAnsi(msg.data);
|
|
139
|
+
if (!msg.data.endsWith('\\n')) term.write('\\r\\n');
|
|
140
|
+
writePromptText();
|
|
141
|
+
} else if (msg.type === 'prompt') {
|
|
142
|
+
handlePrompt(msg);
|
|
143
|
+
} else if (msg.type === 'clear') {
|
|
144
|
+
term.clear();
|
|
145
|
+
writePromptText();
|
|
146
|
+
} else if (msg.type === 'notify') {
|
|
147
|
+
term.write('\\x1b[36m[notice] ' + msg.message + '\\x1b[0m\\r\\n');
|
|
148
|
+
writePromptText();
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function handlePrompt(msg) {
|
|
154
|
+
currentPrompt = msg;
|
|
155
|
+
var promptType = msg.promptType || 'text';
|
|
156
|
+
|
|
157
|
+
if (promptType === 'confirm') {
|
|
158
|
+
writeAnsi(msg.message + ' (y/n) ');
|
|
159
|
+
} else if (promptType === 'select' && msg.options) {
|
|
160
|
+
writeAnsi(msg.message + '\\n');
|
|
161
|
+
for (var i = 0; i < msg.options.length; i++) {
|
|
162
|
+
writeAnsi(' ' + (i + 1) + '. ' + msg.options[i] + '\\n');
|
|
163
|
+
}
|
|
164
|
+
term.write('Choice: ');
|
|
165
|
+
} else if (promptType === 'multiselect' && msg.options) {
|
|
166
|
+
writeAnsi(msg.message + '\\n');
|
|
167
|
+
for (var i = 0; i < msg.options.length; i++) {
|
|
168
|
+
writeAnsi(' ' + (i + 1) + '. ' + msg.options[i] + '\\n');
|
|
169
|
+
}
|
|
170
|
+
term.write('Choices (comma-separated): ');
|
|
171
|
+
} else {
|
|
172
|
+
// text or password
|
|
173
|
+
writeAnsi(msg.message + ' ');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function sendPromptResponse(value) {
|
|
178
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
179
|
+
ws.send(JSON.stringify({ type: 'prompt_response', value: value }));
|
|
180
|
+
}
|
|
181
|
+
currentPrompt = null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function submitLine() {
|
|
185
|
+
var text = lineBuffer;
|
|
186
|
+
lineBuffer = '';
|
|
187
|
+
term.writeln('');
|
|
188
|
+
|
|
189
|
+
if (currentPrompt) {
|
|
190
|
+
var promptType = currentPrompt.promptType || 'text';
|
|
191
|
+
if (promptType === 'confirm') {
|
|
192
|
+
sendPromptResponse(text.trim().toLowerCase().indexOf('y') === 0);
|
|
193
|
+
} else if (promptType === 'select') {
|
|
194
|
+
var idx = parseInt(text.trim(), 10) - 1;
|
|
195
|
+
if (idx >= 0 && currentPrompt.options && idx < currentPrompt.options.length) {
|
|
196
|
+
sendPromptResponse(currentPrompt.options[idx]);
|
|
197
|
+
} else if (currentPrompt.options && currentPrompt.options.length > 0) {
|
|
198
|
+
sendPromptResponse(currentPrompt.options[0]);
|
|
199
|
+
}
|
|
200
|
+
} else if (promptType === 'multiselect') {
|
|
201
|
+
var indices = text.split(',').map(function(s) { return parseInt(s.trim(), 10) - 1; });
|
|
202
|
+
var selected = [];
|
|
203
|
+
for (var i = 0; i < indices.length; i++) {
|
|
204
|
+
if (indices[i] >= 0 && currentPrompt.options && indices[i] < currentPrompt.options.length) {
|
|
205
|
+
selected.push(currentPrompt.options[indices[i]]);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
sendPromptResponse(selected);
|
|
209
|
+
} else {
|
|
210
|
+
sendPromptResponse(text);
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
214
|
+
ws.send(JSON.stringify({ type: 'line', content: text }));
|
|
215
|
+
}
|
|
216
|
+
writePromptText();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ── Input handling ──
|
|
221
|
+
term.onData(function(data) {
|
|
222
|
+
if (data === '\\r') {
|
|
223
|
+
// Enter
|
|
224
|
+
submitLine();
|
|
225
|
+
} else if (data === '\\x7f') {
|
|
226
|
+
// Backspace
|
|
227
|
+
if (lineBuffer.length > 0) {
|
|
228
|
+
lineBuffer = lineBuffer.slice(0, -1);
|
|
229
|
+
term.write('\\b \\b');
|
|
230
|
+
}
|
|
231
|
+
} else if (data === '\\x03') {
|
|
232
|
+
// Ctrl-C — clear line
|
|
233
|
+
lineBuffer = '';
|
|
234
|
+
term.write('^C\\r\\n');
|
|
235
|
+
writePromptText();
|
|
236
|
+
} else if (data >= ' ') {
|
|
237
|
+
// Printable characters
|
|
238
|
+
if (currentPrompt && currentPrompt.promptType === 'password') {
|
|
239
|
+
lineBuffer += data;
|
|
240
|
+
term.write('*');
|
|
241
|
+
} else {
|
|
242
|
+
lineBuffer += data;
|
|
243
|
+
term.write(data);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// ── Resize ──
|
|
249
|
+
window.addEventListener('resize', function() {
|
|
250
|
+
fitAddon.fit();
|
|
251
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
252
|
+
ws.send(JSON.stringify({ type: 'resize', cols: term.cols, rows: term.rows }));
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
term.writeln('\\x1b[1;33mAFS Terminal\\x1b[0m');
|
|
257
|
+
term.writeln('');
|
|
258
|
+
connect();
|
|
259
|
+
<\/script>
|
|
260
|
+
</body>
|
|
261
|
+
</html>`;
|
|
262
|
+
|
|
263
|
+
//#endregion
|
|
264
|
+
exports.TERM_CLIENT_HTML = TERM_CLIENT_HTML;
|