tmux-weblink 2.0.13 → 2.0.14
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/agent.js +1 -1
- package/dist/index.js +3 -3
- package/dist/lib/build-app.js +6 -6
- package/dist/lib/cli.js +6 -6
- package/dist/lib/pages/files-index.js +20 -22
- package/dist/lib/pages/history-index.js +22 -24
- package/dist/lib/pages/notes-index.js +17 -19
- package/dist/lib/pages/notes-page.js +10 -13
- package/dist/lib/pages/quick-commands.js +25 -27
- package/dist/lib/pages/schedule-index.js +23 -25
- package/dist/lib/pages/settings.js +18 -24
- package/dist/lib/pages/shell.js +15 -27
- package/dist/lib/setup-features.js +1 -1
- package/dist/lib/shared-layout.js +38 -39
- package/package.json +1 -1
- package/dist/lib/commandbar.js +0 -555
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import{cssVarsStyle as
|
|
1
|
+
import{cssVarsStyle as c}from"../theme.js";import{escapeHtml as p}from"../html.js";import{notesDbScript as b}from"../notes-db.js";import{notesUtilsScript as m}from"../notes-utils.js";function f(t,n){const e=t==="__global__",a=e?"Global":t,r=e?"__global__":"session:"+t,i="/notes",s=e?"notes-global":"notes-session-"+t.replace(/[:\/\\]/g,"-"),d=JSON.stringify(r),l=JSON.stringify(`${s}.md`),o=p(a);return`<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
|
-
<title>Notes - ${
|
|
7
|
+
<title>Notes - ${o} - tmux-web</title>
|
|
8
8
|
<style>
|
|
9
|
-
${
|
|
9
|
+
${c(n.shell)}
|
|
10
10
|
html, body { background: var(--page-bg); color: var(--page-fg); min-height: 100%; font-family: var(--font-mono); }
|
|
11
11
|
.container { max-width: 720px; margin: 40px auto; padding: 0 20px; }
|
|
12
12
|
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; }
|
|
@@ -53,16 +53,15 @@ import{cssVarsStyle as b}from"../theme.js";import{escapeHtml as m}from"../html.j
|
|
|
53
53
|
.container { margin: 20px auto; padding: 0 16px; }
|
|
54
54
|
#notes-editor { min-height: 300px; padding: 12px; }
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
</style>
|
|
58
58
|
</head>
|
|
59
59
|
<body>
|
|
60
60
|
<div class="container">
|
|
61
61
|
<div class="page-header">
|
|
62
62
|
<div class="breadcrumb">
|
|
63
|
-
<a href="${
|
|
63
|
+
<a href="${i}">Notes</a> <span>/</span> <span>${o}</span>
|
|
64
64
|
</div>
|
|
65
|
-
${e?y("Search"):""}
|
|
66
65
|
</div>
|
|
67
66
|
<div class="toolbar">
|
|
68
67
|
<button id="notes-copy">Copy</button>
|
|
@@ -73,9 +72,9 @@ import{cssVarsStyle as b}from"../theme.js";import{escapeHtml as m}from"../html.j
|
|
|
73
72
|
</div>
|
|
74
73
|
|
|
75
74
|
<script type="module">
|
|
76
|
-
const NOTES_SCOPE = ${
|
|
77
|
-
${
|
|
78
|
-
${
|
|
75
|
+
const NOTES_SCOPE = ${d};
|
|
76
|
+
${b()}
|
|
77
|
+
${m()}
|
|
79
78
|
|
|
80
79
|
const notesEditor = document.getElementById('notes-editor');
|
|
81
80
|
const copyBtn = document.getElementById('notes-copy');
|
|
@@ -143,16 +142,14 @@ exportBtn.addEventListener('click', () => {
|
|
|
143
142
|
const blob = new Blob([notePlain], { type: 'text/markdown' });
|
|
144
143
|
const a = document.createElement('a');
|
|
145
144
|
a.href = URL.createObjectURL(blob);
|
|
146
|
-
a.download = ${
|
|
145
|
+
a.download = ${l};
|
|
147
146
|
a.click();
|
|
148
147
|
URL.revokeObjectURL(a.href);
|
|
149
148
|
});
|
|
150
149
|
|
|
151
150
|
renderNote();
|
|
152
151
|
</script>
|
|
153
|
-
${e?f():""}
|
|
154
152
|
<script type="module">
|
|
155
|
-
${e?v(r,[]):""}
|
|
156
153
|
</script>
|
|
157
154
|
</body>
|
|
158
|
-
</html>`}export{
|
|
155
|
+
</html>`}export{f as renderNotesPage};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{cssVarsStyle as
|
|
1
|
+
import{cssVarsStyle as n}from"../theme.js";import{sharedLayoutCSS as c,sharedHeader as s,sharedSidebar as d,newSessionModalHTML as l,newSessionModalScript as p}from"../shared-layout.js";import{icon as a}from"../icons.js";function t(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function u(e){return`<article class="quick-item" data-id="${t(e.id)}">
|
|
2
2
|
<div class="quick-card-head">
|
|
3
3
|
<div>
|
|
4
4
|
<div class="quick-title">${t(e.title)}</div>
|
|
@@ -6,16 +6,25 @@ import{cssVarsStyle as d}from"../theme.js";import{commandbarCSS as l,commandbarH
|
|
|
6
6
|
</div>
|
|
7
7
|
<div class="quick-icon-actions">
|
|
8
8
|
<button class="quick-icon-btn quick-edit" type="button" title="Edit command" aria-label="Edit ${t(e.title)}">
|
|
9
|
-
${
|
|
9
|
+
${a("edit")}
|
|
10
10
|
</button>
|
|
11
11
|
<button class="quick-icon-btn quick-delete" type="button" title="Delete command" aria-label="Delete ${t(e.title)}">
|
|
12
|
-
${
|
|
12
|
+
${a("delete")}
|
|
13
13
|
</button>
|
|
14
14
|
</div>
|
|
15
15
|
</div>
|
|
16
16
|
<pre class="quick-command-preview"><code>${t(e.command)}</code></pre>
|
|
17
|
-
</article>`}function
|
|
18
|
-
`):'<p class="empty">No quick commands yet. Add one below
|
|
17
|
+
</article>`}function x(e,r){const o=JSON.stringify(e).replace(/</g,"\\u003c"),i=e.length?e.map(u).join(`
|
|
18
|
+
`):'<p class="empty">No quick commands yet. Add one below.</p>';return`<!DOCTYPE html>
|
|
19
|
+
<html lang="en">
|
|
20
|
+
<head>
|
|
21
|
+
<meta charset="UTF-8" />
|
|
22
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
23
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
24
|
+
<title>Quick Commands - tmux-web</title>
|
|
25
|
+
<style>
|
|
26
|
+
${n(r.shell)}
|
|
27
|
+
${c(`
|
|
19
28
|
.intro {
|
|
20
29
|
margin: 0 0 18px; color: var(--panel-muted); font-size: var(--text-sm); line-height: 1.6;
|
|
21
30
|
}
|
|
@@ -155,27 +164,18 @@ import{cssVarsStyle as d}from"../theme.js";import{commandbarCSS as l,commandbarH
|
|
|
155
164
|
.quick-card-head { flex-wrap: wrap; }
|
|
156
165
|
.quick-icon-actions { width: 100%; justify-content: flex-end; }
|
|
157
166
|
}
|
|
158
|
-
|
|
159
|
-
<html lang="en">
|
|
160
|
-
<head>
|
|
161
|
-
<meta charset="UTF-8" />
|
|
162
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
163
|
-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
164
|
-
<title>Quick Commands - tmux-web</title>
|
|
165
|
-
<style>
|
|
166
|
-
${d(a.shell)}
|
|
167
|
-
${u(s)}
|
|
167
|
+
`)}
|
|
168
168
|
</style>
|
|
169
169
|
</head>
|
|
170
170
|
<body>
|
|
171
171
|
|
|
172
|
-
${
|
|
172
|
+
${s({title:"Quick Commands",themeTemplate:r.template})}
|
|
173
173
|
|
|
174
174
|
<div class="page-wrap">
|
|
175
175
|
<div class="page-layout">
|
|
176
|
-
${
|
|
176
|
+
${d({activePage:"quickCommands",refreshHref:"/quick-commands"})}
|
|
177
177
|
<main class="main-panel">
|
|
178
|
-
<p class="intro">Configure reusable snippets that can be pasted into the active tmux pane
|
|
178
|
+
<p class="intro">Configure reusable snippets that can be pasted into the active tmux pane.</p>
|
|
179
179
|
<p class="quick-error" id="quick-error"></p>
|
|
180
180
|
|
|
181
181
|
<h2 class="quick-section-title">Add Command</h2>
|
|
@@ -190,7 +190,7 @@ ${b({commandbarEnabled:r,title:"Quick Commands",themeTemplate:a.template})}
|
|
|
190
190
|
</label>
|
|
191
191
|
<label>
|
|
192
192
|
<span>Description</span>
|
|
193
|
-
<input name="description" type="text" placeholder="Optional
|
|
193
|
+
<input name="description" type="text" placeholder="Optional description" autocomplete="off" />
|
|
194
194
|
</label>
|
|
195
195
|
<div class="quick-actions">
|
|
196
196
|
<button class="quick-save" type="submit">Add Command</button>
|
|
@@ -198,18 +198,18 @@ ${b({commandbarEnabled:r,title:"Quick Commands",themeTemplate:a.template})}
|
|
|
198
198
|
</form>
|
|
199
199
|
|
|
200
200
|
<h2 class="quick-section-title">Configured</h2>
|
|
201
|
-
<div id="quick-list">${
|
|
201
|
+
<div id="quick-list">${i}</div>
|
|
202
202
|
</main>
|
|
203
203
|
</div>
|
|
204
204
|
</div>
|
|
205
205
|
|
|
206
|
-
${
|
|
206
|
+
${l()}
|
|
207
207
|
<div class="quick-drawer-backdrop" id="quick-edit-backdrop"></div>
|
|
208
208
|
<aside class="quick-drawer" id="quick-edit-drawer" aria-hidden="true" aria-label="Edit quick command">
|
|
209
209
|
<div class="quick-drawer-header">
|
|
210
210
|
<div>
|
|
211
211
|
<h2>Edit Command</h2>
|
|
212
|
-
|
|
212
|
+
|
|
213
213
|
</div>
|
|
214
214
|
<button class="quick-drawer-close" id="quick-edit-close" type="button" aria-label="Close edit drawer">×</button>
|
|
215
215
|
</div>
|
|
@@ -233,10 +233,9 @@ ${v()}
|
|
|
233
233
|
</div>
|
|
234
234
|
</form>
|
|
235
235
|
</aside>
|
|
236
|
-
${r?p():""}
|
|
237
236
|
|
|
238
237
|
<script type="module">
|
|
239
|
-
const commands = ${
|
|
238
|
+
const commands = ${o};
|
|
240
239
|
const errorEl = document.getElementById('quick-error');
|
|
241
240
|
const editBackdrop = document.getElementById('quick-edit-backdrop');
|
|
242
241
|
const editDrawer = document.getElementById('quick-edit-drawer');
|
|
@@ -354,8 +353,7 @@ document.addEventListener('keydown', (event) => {
|
|
|
354
353
|
if (event.key === 'Escape' && editDrawer.classList.contains('open')) closeEditDrawer();
|
|
355
354
|
});
|
|
356
355
|
|
|
357
|
-
${
|
|
358
|
-
${x()}
|
|
356
|
+
${p()}
|
|
359
357
|
</script>
|
|
360
358
|
</body>
|
|
361
|
-
</html>`}export{
|
|
359
|
+
</html>`}export{x as renderQuickCommandsPage};
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import{cssVarsStyle as
|
|
1
|
+
import{cssVarsStyle as v}from"../theme.js";import{notesDrawerCSS as w,notesDrawerHTML as y,notesDrawerScript as S}from"../notes-drawer.js";import{sharedLayoutCSS as k,sharedHeader as $,sharedSidebar as E,newSessionModalHTML as L,newSessionModalScript as A}from"../shared-layout.js";import{DELAY_INVALID_MESSAGE as B,DELAY_MAX_MESSAGE as C,MAX_SCHEDULE_MS as M,scheduleDelayParseScript as q}from"../schedule-delay.js";function t(s){return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function d(s){const n=new Date(s);return n.toLocaleDateString()+" "+n.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}function I(s,n){return s.length?`<div class="task-list">${s.map(e=>`<div class="task">
|
|
2
2
|
<div class="task-row1">
|
|
3
3
|
<span class="cmd">${t(e.text)}</span>
|
|
4
4
|
<span class="status-pill status-${e.status}">${e.status}</span>
|
|
5
5
|
</div>
|
|
6
6
|
<div class="task-row2">
|
|
7
7
|
<a class="trig-target" href="/s/${encodeURIComponent(e.sessionName)}?window=${e.windowIndex}">${t(e.sessionName)} · win:${e.windowIndex}</a>
|
|
8
|
-
<span class="meta">${t(
|
|
8
|
+
<span class="meta">${t(d(e.triggeredAt))}</span>
|
|
9
9
|
</div>${e.status==="error"&&e.error?`
|
|
10
10
|
<div class="trig-error">${t(e.error)}</div>`:""}
|
|
11
11
|
</div>`).join(`
|
|
12
|
-
`)}</div>`:`<p class="empty">No tasks triggered in the last ${n} day${n===1?"":"s"}.</p>`}function
|
|
12
|
+
`)}</div>`:`<p class="empty">No tasks triggered in the last ${n} day${n===1?"":"s"}.</p>`}function N(s,n,i,e=7){const l=[...s].sort((r,o)=>r.fireAt-o.fireAt),c=new Map;for(const r of l){const o=c.get(r.sessionName);o?o.push(r):c.set(r.sessionName,[r])}const p=[...c.entries()].map(([r,o])=>{const x=o.map(a=>`<div class="task" data-id="${t(a.id)}">
|
|
13
13
|
<div class="task-row1">
|
|
14
14
|
<span class="cmd">${t(a.text)}</span>
|
|
15
15
|
<span class="countdown" data-fire-at="${a.fireAt}">\u2026</span>
|
|
16
16
|
</div>
|
|
17
17
|
<div class="task-row2">
|
|
18
|
-
<span class="meta"><a class="win-link" href="/s/${encodeURIComponent(a.sessionName)}?window=${a.windowIndex}">win:${a.windowIndex}</a> · fires ${t(
|
|
18
|
+
<span class="meta"><a class="win-link" href="/s/${encodeURIComponent(a.sessionName)}?window=${a.windowIndex}">win:${a.windowIndex}</a> · fires ${t(d(a.fireAt))}</span>
|
|
19
19
|
<div style="display:flex;gap:4px;align-items:center;">
|
|
20
20
|
<button class="reschedule-btn" data-id="${t(a.id)}">reschedule</button>
|
|
21
21
|
<button class="cancel-btn" data-id="${t(a.id)}">cancel</button>
|
|
@@ -40,9 +40,9 @@ import{cssVarsStyle as y}from"../theme.js";import{commandbarCSS as S,commandbarH
|
|
|
40
40
|
<span class="sname">${t(r)}</span>
|
|
41
41
|
<span class="scount">${o.length}</span>
|
|
42
42
|
</a>
|
|
43
|
-
<div class="task-list">${
|
|
43
|
+
<div class="task-list">${x}</div>
|
|
44
44
|
</div>`}).join(`
|
|
45
|
-
`),
|
|
45
|
+
`),u=l.length?p:'<p class="empty" id="empty-msg">No scheduled tasks.</p>',m=I(n,e),h=M,g=B,f=C,b=`
|
|
46
46
|
.session-head {
|
|
47
47
|
display: flex; align-items: center; gap: 8px; text-decoration: none;
|
|
48
48
|
font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
|
|
@@ -154,8 +154,8 @@ import{cssVarsStyle as y}from"../theme.js";import{commandbarCSS as S,commandbarH
|
|
|
154
154
|
.reschedule-input-row { flex-direction: column; align-items: stretch; }
|
|
155
155
|
.reschedule-input-row button { align-self: flex-start; }
|
|
156
156
|
}
|
|
157
|
-
|
|
158
|
-
${
|
|
157
|
+
|
|
158
|
+
${w()}`;return`<!DOCTYPE html>
|
|
159
159
|
<html lang="en">
|
|
160
160
|
<head>
|
|
161
161
|
<meta charset="UTF-8" />
|
|
@@ -163,45 +163,43 @@ import{cssVarsStyle as y}from"../theme.js";import{commandbarCSS as S,commandbarH
|
|
|
163
163
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
164
164
|
<title>Scheduled tasks - tmux-web</title>
|
|
165
165
|
<style>
|
|
166
|
-
${
|
|
167
|
-
${
|
|
166
|
+
${v(i.shell)}
|
|
167
|
+
${k(b)}
|
|
168
168
|
</style>
|
|
169
169
|
</head>
|
|
170
170
|
<body>
|
|
171
171
|
|
|
172
|
-
${
|
|
172
|
+
${$({title:"Scheduled",themeTemplate:i.template})}
|
|
173
173
|
|
|
174
174
|
<div class="page-wrap">
|
|
175
175
|
<div class="page-layout">
|
|
176
|
-
${
|
|
176
|
+
${E({activePage:"schedule",refreshHref:"/schedule"})}
|
|
177
177
|
<main class="main-panel">
|
|
178
178
|
<div class="page-tab-bar">
|
|
179
179
|
<button class="page-tab active" data-tab="upcoming">Upcoming</button>
|
|
180
180
|
<button class="page-tab" data-tab="triggered">Recently Triggered</button>
|
|
181
181
|
</div>
|
|
182
182
|
<div class="tab-panel active" data-panel="upcoming">
|
|
183
|
-
<div id="schedule-list">${
|
|
183
|
+
<div id="schedule-list">${u}</div>
|
|
184
184
|
</div>
|
|
185
185
|
<div class="tab-panel" data-panel="triggered">
|
|
186
|
-
${
|
|
186
|
+
${m}
|
|
187
187
|
</div>
|
|
188
188
|
</main>
|
|
189
189
|
</div>
|
|
190
190
|
</div>
|
|
191
191
|
|
|
192
|
-
${
|
|
193
|
-
${
|
|
194
|
-
${L("Notes - Global")}
|
|
192
|
+
${L()}
|
|
193
|
+
${y("Notes - Global")}
|
|
195
194
|
|
|
196
195
|
<script type="module">
|
|
197
|
-
${
|
|
198
|
-
${
|
|
199
|
-
${I()}
|
|
196
|
+
${S("__global__")}
|
|
197
|
+
${A()}
|
|
200
198
|
</script>
|
|
201
199
|
|
|
202
200
|
<script>
|
|
203
|
-
const MAX_SCHEDULE_MS = ${
|
|
204
|
-
${
|
|
201
|
+
const MAX_SCHEDULE_MS = ${h};
|
|
202
|
+
${q()}
|
|
205
203
|
|
|
206
204
|
// \u2500\u2500 Tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
207
205
|
function activateTab(name) {
|
|
@@ -286,13 +284,13 @@ async function submitReschedule(id, delayStr) {
|
|
|
286
284
|
const delayMs = parseDelay(delayStr !== undefined ? delayStr : input.value);
|
|
287
285
|
if (!delayMs) {
|
|
288
286
|
input.classList.add('error');
|
|
289
|
-
errorEl.textContent = ${JSON.stringify(
|
|
287
|
+
errorEl.textContent = ${JSON.stringify(g)};
|
|
290
288
|
input.focus();
|
|
291
289
|
return;
|
|
292
290
|
}
|
|
293
291
|
if (delayMs > MAX_SCHEDULE_MS) {
|
|
294
292
|
input.classList.add('error');
|
|
295
|
-
errorEl.textContent = ${JSON.stringify(
|
|
293
|
+
errorEl.textContent = ${JSON.stringify(f)};
|
|
296
294
|
input.focus();
|
|
297
295
|
return;
|
|
298
296
|
}
|
|
@@ -389,4 +387,4 @@ tick();
|
|
|
389
387
|
setInterval(tick, 1000);
|
|
390
388
|
</script>
|
|
391
389
|
</body>
|
|
392
|
-
</html>`}export{
|
|
390
|
+
</html>`}export{N as renderScheduleIndex};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{cssVarsStyle as
|
|
1
|
+
import{cssVarsStyle as u}from"../theme.js";import{getThemeTemplates as h,THEME_TEMPLATE_IDS as b}from"../themes/index.js";function n(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function m(a,e){return`<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
@@ -6,7 +6,7 @@ import{cssVarsStyle as h}from"../theme.js";import{getThemeTemplates as b,THEME_T
|
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
7
|
<title>${n(a)} - tmux-web</title>
|
|
8
8
|
<style>
|
|
9
|
-
${
|
|
9
|
+
${u(e.shell)}
|
|
10
10
|
html, body { background: var(--page-bg); color: var(--page-fg); min-height: 100%; font-family: var(--font-sans); }
|
|
11
11
|
.container { max-width: 680px; margin: 80px auto; padding: 0 24px; }
|
|
12
12
|
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 28px; }
|
|
@@ -87,7 +87,7 @@ import{cssVarsStyle as h}from"../theme.js";import{getThemeTemplates as b,THEME_T
|
|
|
87
87
|
.num-input { width: 100%; }
|
|
88
88
|
}
|
|
89
89
|
</style>
|
|
90
|
-
</head>`}function
|
|
90
|
+
</head>`}function x(a,e){let r="";return a&&(r+='<div class="saved-flash">\u2713 Saved. Restart tmux-web to apply.</div>'),e&&(r+=`<div class="error-flash">${n(e)}</div>`),r}function $(a){const{settings:e,renderer:r,rendererOverridden:l,theme:d,plugins:t,saved:c=!1,error:s}=a,i=e.terminalRenderer??"xterm",o=e.defaultView??"default",g=e.scheduleHistoryDays??7,v=t.length?t.map(p=>`<div class="plugin-row">
|
|
91
91
|
<span class="pkg">${n(p)}</span>
|
|
92
92
|
<form method="POST" action="/settings/plugins" onsubmit="return confirm('Remove ${n(p)}?');">
|
|
93
93
|
<input type="hidden" name="action" value="remove" />
|
|
@@ -95,7 +95,7 @@ import{cssVarsStyle as h}from"../theme.js";import{getThemeTemplates as b,THEME_T
|
|
|
95
95
|
<button type="submit" class="btn danger">Remove</button>
|
|
96
96
|
</form>
|
|
97
97
|
</div>`).join(`
|
|
98
|
-
`):'<p class="desc" style="margin:0">No plugins enabled.</p>';return`${
|
|
98
|
+
`):'<p class="desc" style="margin:0">No plugins enabled.</p>';return`${m("Settings",d)}
|
|
99
99
|
<body>
|
|
100
100
|
<div class="container">
|
|
101
101
|
<div class="page-header">
|
|
@@ -108,38 +108,32 @@ import{cssVarsStyle as h}from"../theme.js";import{getThemeTemplates as b,THEME_T
|
|
|
108
108
|
<strong>restart the tmux-web process</strong> after making changes for them to take effect.
|
|
109
109
|
</div>
|
|
110
110
|
|
|
111
|
-
${
|
|
111
|
+
${x(c,s)}
|
|
112
112
|
|
|
113
113
|
<form method="POST" action="/settings">
|
|
114
|
-
<div class="section">
|
|
115
|
-
<h2>Command bar</h2>
|
|
116
|
-
<p class="desc">\u2318K session search + quick actions.</p>
|
|
117
|
-
<label class="row"><input type="checkbox" name="commandbar" ${c?"checked":""} /> Enable command bar</label>
|
|
118
|
-
</div>
|
|
119
|
-
|
|
120
114
|
<div class="section">
|
|
121
115
|
<h2>Terminal library</h2>
|
|
122
116
|
<p class="desc">Rendering engine for the terminal view.</p>
|
|
123
117
|
<div class="radios">
|
|
124
|
-
<label class="row"><input type="radio" name="terminalRenderer" value="xterm" ${
|
|
125
|
-
<label class="row"><input type="radio" name="terminalRenderer" value="ghostty" ${
|
|
118
|
+
<label class="row"><input type="radio" name="terminalRenderer" value="xterm" ${i==="xterm"?"checked":""} /> xterm.js (default)</label>
|
|
119
|
+
<label class="row"><input type="radio" name="terminalRenderer" value="ghostty" ${i==="ghostty"?"checked":""} /> ghostty-web</label>
|
|
126
120
|
</div>
|
|
127
|
-
${
|
|
121
|
+
${l?`<p class="override-note">\u26A0 A CLI flag or <code>TMUX_WEB_TERMINAL_RENDERER</code> env var is currently forcing <strong>${r}</strong>, overriding this setting for the running process.</p>`:""}
|
|
128
122
|
</div>
|
|
129
123
|
|
|
130
124
|
<div class="section">
|
|
131
125
|
<h2>Default home tab</h2>
|
|
132
126
|
<p class="desc">Which tab the home page opens on.</p>
|
|
133
127
|
<div class="radios">
|
|
134
|
-
<label class="row"><input type="radio" name="defaultView" value="default" ${
|
|
135
|
-
<label class="row"><input type="radio" name="defaultView" value="recent" ${
|
|
128
|
+
<label class="row"><input type="radio" name="defaultView" value="default" ${o==="default"?"checked":""} /> Default</label>
|
|
129
|
+
<label class="row"><input type="radio" name="defaultView" value="recent" ${o==="recent"?"checked":""} /> Last Updated</label>
|
|
136
130
|
</div>
|
|
137
131
|
</div>
|
|
138
132
|
|
|
139
133
|
<div class="section">
|
|
140
134
|
<h2>Schedule history</h2>
|
|
141
135
|
<p class="desc">Days to keep the <code>/schedule</code> "Recently Triggered" history (fired & missed tasks). 1\u2013365, default 7.</p>
|
|
142
|
-
<label class="row"><input type="number" class="num-input" name="scheduleHistoryDays" min="1" max="365" value="${
|
|
136
|
+
<label class="row"><input type="number" class="num-input" name="scheduleHistoryDays" min="1" max="365" value="${g}" /> days</label>
|
|
143
137
|
</div>
|
|
144
138
|
|
|
145
139
|
<div class="form-actions">
|
|
@@ -150,7 +144,7 @@ import{cssVarsStyle as h}from"../theme.js";import{getThemeTemplates as b,THEME_T
|
|
|
150
144
|
<div class="section" style="margin-top:16px">
|
|
151
145
|
<h2>Plugins</h2>
|
|
152
146
|
<p class="desc">Installed via npm into the tmux-web data dir. Add/remove runs npm and may take a few seconds.</p>
|
|
153
|
-
${
|
|
147
|
+
${v}
|
|
154
148
|
<form method="POST" action="/settings/plugins" class="plugin-add">
|
|
155
149
|
<input type="hidden" name="action" value="add" />
|
|
156
150
|
<input type="text" id="pkg-input" name="pkg" placeholder="npm package name" autocomplete="off" />
|
|
@@ -171,14 +165,14 @@ import{cssVarsStyle as h}from"../theme.js";import{getThemeTemplates as b,THEME_T
|
|
|
171
165
|
</div>
|
|
172
166
|
</div>
|
|
173
167
|
</body>
|
|
174
|
-
</html>`}const
|
|
168
|
+
</html>`}const f={vscode:"VS Code",ghostty:"Ghostty","warm-clay":"Warm Clay","dark-cove":"Dark Cove"},y=["background","foreground","red","green","yellow","blue","magenta","cyan"];function T(a){const{theme:e,saved:r=!1}=a,l=h(),d=b.map(t=>{const c=l[t],s=e.template===t,i=y.map(o=>`<span class="swatch" style="background:${n(c.terminal[o])}" title="${o}"></span>`).join("");return`<label class="theme-card${s?" active":""}">
|
|
175
169
|
<div class="tname">
|
|
176
170
|
<input type="radio" name="template" value="${t}" ${s?"checked":""} style="accent-color:var(--panel-success)" />
|
|
177
|
-
${n(
|
|
171
|
+
${n(f[t]??t)}
|
|
178
172
|
</div>
|
|
179
|
-
<div class="swatches">${
|
|
173
|
+
<div class="swatches">${i}</div>
|
|
180
174
|
</label>`}).join(`
|
|
181
|
-
`);return`${
|
|
175
|
+
`);return`${m("Theme",e)}
|
|
182
176
|
<body>
|
|
183
177
|
<div class="container">
|
|
184
178
|
<div class="page-header">
|
|
@@ -194,7 +188,7 @@ import{cssVarsStyle as h}from"../theme.js";import{getThemeTemplates as b,THEME_T
|
|
|
194
188
|
|
|
195
189
|
<form method="POST" action="/settings/theme">
|
|
196
190
|
<div class="theme-grid">
|
|
197
|
-
${
|
|
191
|
+
${d}
|
|
198
192
|
</div>
|
|
199
193
|
<div class="form-actions" style="margin-top:16px">
|
|
200
194
|
<button type="submit" class="btn primary">Save theme</button>
|
|
@@ -202,4 +196,4 @@ import{cssVarsStyle as h}from"../theme.js";import{getThemeTemplates as b,THEME_T
|
|
|
202
196
|
</form>
|
|
203
197
|
</div>
|
|
204
198
|
</body>
|
|
205
|
-
</html>`}export{
|
|
199
|
+
</html>`}export{$ as renderSettings,T as renderThemeSettings};
|
package/dist/lib/pages/shell.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{cssVarsStyle as
|
|
1
|
+
import{cssVarsStyle as c}from"../theme.js";import{newSessionModalCSS as f,newSessionModalHTML as g,newSessionModalScript as x,reducedMotion as b}from"../shared-layout.js";import{icon as i}from"../icons.js";function y(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function o(t="var(--panel-accent)"){return`box-shadow: 0 0 0 2px ${t}; outline: none;`}function k(t){const{theme:e,fsRoots:r,terminalCfg:a,renderer:n,scrollback:s,wsBase:p}=t,l=`
|
|
2
2
|
*, *::before, *::after { box-sizing: border-box; }
|
|
3
3
|
html, body {
|
|
4
4
|
background: var(--page-bg); color: var(--page-fg);
|
|
@@ -87,7 +87,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
87
87
|
}
|
|
88
88
|
.sidebar-footer .mode-btn:hover { color: var(--panel-accent); background: color-mix(in srgb, var(--panel-accent) 8%, transparent); }
|
|
89
89
|
.sidebar-footer .mode-btn.active { color: var(--panel-accent); background: color-mix(in srgb, var(--panel-accent) 10%, transparent); }
|
|
90
|
-
.sidebar-footer .mode-btn:focus-visible { ${
|
|
90
|
+
.sidebar-footer .mode-btn:focus-visible { ${o()} }
|
|
91
91
|
|
|
92
92
|
/* \u2500\u2500 Sidebar session mode \u2500\u2500 */
|
|
93
93
|
.session-item {
|
|
@@ -109,7 +109,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
109
109
|
}
|
|
110
110
|
.session-item:hover .session-edit-btn { display: flex; align-items: center; }
|
|
111
111
|
.session-edit-btn:hover { color: var(--panel-accent); background: color-mix(in srgb, var(--panel-accent) 8%, transparent); }
|
|
112
|
-
.session-edit-btn:focus-visible { ${
|
|
112
|
+
.session-edit-btn:focus-visible { ${o()} }
|
|
113
113
|
|
|
114
114
|
.sidebar-section-label {
|
|
115
115
|
font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.05em;
|
|
@@ -135,7 +135,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
135
135
|
color: var(--panel-accent); border-color: var(--panel-accent);
|
|
136
136
|
background: color-mix(in srgb, var(--panel-accent) 6%, transparent);
|
|
137
137
|
}
|
|
138
|
-
.new-session-sidebar-btn:focus-visible { ${
|
|
138
|
+
.new-session-sidebar-btn:focus-visible { ${o()} }
|
|
139
139
|
.new-session-sidebar-btn svg { width: 16px; height: 16px; fill: currentColor; }
|
|
140
140
|
|
|
141
141
|
/* \u2500\u2500 Sidebar files mode \u2500\u2500 */
|
|
@@ -409,7 +409,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
409
409
|
color: var(--page-fg); transition: opacity 0.15s; text-decoration: none;
|
|
410
410
|
}
|
|
411
411
|
.btn:hover { opacity: 0.85; }
|
|
412
|
-
.btn:focus-visible { ${
|
|
412
|
+
.btn:focus-visible { ${o()} }
|
|
413
413
|
.btn.primary { background: var(--panel-accent); border-color: var(--panel-accent); color: var(--panel-accent-on); font-weight: 500; }
|
|
414
414
|
.btn.primary:hover { opacity: 0.9; }
|
|
415
415
|
.btn.danger { color: #b91c1c; border-color: color-mix(in srgb, #b91c1c 30%, transparent); }
|
|
@@ -580,10 +580,8 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
580
580
|
.file-roots-list li:hover { border-color: var(--panel-accent); }
|
|
581
581
|
.file-roots-list li svg { width: 20px; height: 20px; flex-shrink: 0; fill: var(--panel-accent); }
|
|
582
582
|
|
|
583
|
-
|
|
584
|
-
${
|
|
585
|
-
${y()}
|
|
586
|
-
${v()}
|
|
583
|
+
${b()}
|
|
584
|
+
${f()}
|
|
587
585
|
@media (max-width: 640px) {
|
|
588
586
|
.app-layout { flex-direction: column; }
|
|
589
587
|
.sidebar { flex: 0 0 auto; border-right: none; border-bottom: 1px solid var(--panel-border); transition: max-height 0.2s; }
|
|
@@ -594,7 +592,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
594
592
|
.mobile-keys .mk-buttons { display: none; }
|
|
595
593
|
.mobile-keys.mk-focused .mk-buttons { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
596
594
|
}
|
|
597
|
-
`,
|
|
595
|
+
`,m=JSON.stringify(e.terminal).replace(/</g,"\\u003c"),d=JSON.stringify({terminal:a,scrollback:s,theme:e.terminal,renderer:n,fsRoots:r,wsBase:p||""}).replace(/</g,"\\u003c");return`<!DOCTYPE html>
|
|
598
596
|
<html lang="en">
|
|
599
597
|
<head>
|
|
600
598
|
<meta charset="UTF-8" />
|
|
@@ -607,8 +605,8 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
607
605
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
608
606
|
<title>tmux-weblink</title>
|
|
609
607
|
<style>
|
|
610
|
-
${
|
|
611
|
-
${
|
|
608
|
+
${c(e.shell)}
|
|
609
|
+
${l}
|
|
612
610
|
</style>
|
|
613
611
|
</head>
|
|
614
612
|
<body>
|
|
@@ -633,7 +631,6 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
633
631
|
<header class="fixed-header">
|
|
634
632
|
<div class="brand" id="brand-toggle">tmux<span>-weblink</span></div>
|
|
635
633
|
<div class="header-actions">
|
|
636
|
-
${t?`<button class="header-btn" id="cmdbar-btn" title="Search" aria-label="Search">${i("search")}</button>`:""}
|
|
637
634
|
</div>
|
|
638
635
|
<div id="header-git" title="Click to browse repository"></div>
|
|
639
636
|
<span id="header-ram"></span>
|
|
@@ -703,16 +700,9 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
703
700
|
<!-- Settings popover -->
|
|
704
701
|
<div class="popover-backdrop" id="settings-backdrop"></div>
|
|
705
702
|
<div class="settings-popover" id="settings-popover">
|
|
706
|
-
<div class="settings-item">
|
|
707
|
-
<span>Command bar</span>
|
|
708
|
-
<button class="toggle${t?" on":""}" id="set-commandbar"></button>
|
|
709
|
-
</div>
|
|
710
|
-
<div class="settings-item">
|
|
711
|
-
</div>
|
|
712
|
-
<hr class="settings-divider" />
|
|
713
703
|
<div class="settings-item">
|
|
714
704
|
<span>Terminal renderer</span>
|
|
715
|
-
<span style="font-size:var(--text-xs);color:var(--panel-muted)">${
|
|
705
|
+
<span style="font-size:var(--text-xs);color:var(--panel-muted)">${n==="ghostty"?"Ghostty":"xterm.js"}</span>
|
|
716
706
|
</div>
|
|
717
707
|
<hr class="settings-divider" />
|
|
718
708
|
<div style="padding:4px 0">
|
|
@@ -760,21 +750,19 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as b,commandbarH
|
|
|
760
750
|
})();
|
|
761
751
|
</script>
|
|
762
752
|
|
|
763
|
-
${
|
|
764
|
-
${t?x():""}
|
|
753
|
+
${g()}
|
|
765
754
|
|
|
766
755
|
<script>
|
|
767
|
-
window.__TMUX_WEB_SHELL__ = ${
|
|
756
|
+
window.__TMUX_WEB_SHELL__ = ${d};
|
|
768
757
|
</script>
|
|
769
758
|
<script type="module">
|
|
770
759
|
await import('/assets/shell-client.js');
|
|
771
|
-
${t?m(a,[]):""}
|
|
772
760
|
// Wrapper: refresh sidebar list, then open session
|
|
773
761
|
window.__onSessionCreated = async function(name, agentId) {
|
|
774
762
|
await window.__refreshSidebar();
|
|
775
763
|
window.__openSession(name, agentId || undefined);
|
|
776
764
|
};
|
|
777
|
-
${
|
|
765
|
+
${x("__onSessionCreated")}
|
|
778
766
|
</script>
|
|
779
767
|
<script>
|
|
780
768
|
// Sync app-layout height to visual viewport so mobile keyboard doesn't overlap
|
|
@@ -841,4 +829,4 @@ if ('serviceWorker' in navigator) {
|
|
|
841
829
|
}
|
|
842
830
|
</script>
|
|
843
831
|
</body>
|
|
844
|
-
</html>`}export{
|
|
832
|
+
</html>`}export{k as renderShell};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readSettings as
|
|
1
|
+
import{readSettings as a,writeSettings as t}from"./settings.js";const s=[{id:"agents",label:"Agents page",description:"watch AI agents (Claude, Codex, OpenCode, Cursor) in recently-viewed panes",kind:"builtin",isEnabled:e=>e.agents===!0,async enable(){const e=await a();await t({...e,agents:!0}),console.log("\u2713 agents page enabled")},async disable(){const e=await a();await t({...e,agents:!1}),console.log("\u2713 agents page disabled")}}];export{s as SETUP_FEATURES};
|