@ecmaos/coreutils 0.2.1 → 0.3.1
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +37 -0
- package/LICENSE +1 -1
- package/dist/commands/cal.js +2 -2
- package/dist/commands/cal.js.map +1 -1
- package/dist/commands/cat.js +2 -2
- package/dist/commands/cd.js +2 -2
- package/dist/commands/chmod.d.ts.map +1 -1
- package/dist/commands/chmod.js +16 -11
- package/dist/commands/chmod.js.map +1 -1
- package/dist/commands/cp.js +2 -2
- package/dist/commands/cp.js.map +1 -1
- package/dist/commands/cron.d.ts +4 -0
- package/dist/commands/cron.d.ts.map +1 -0
- package/dist/commands/cron.js +439 -0
- package/dist/commands/cron.js.map +1 -0
- package/dist/commands/date.js +2 -2
- package/dist/commands/date.js.map +1 -1
- package/dist/commands/echo.js +2 -2
- package/dist/commands/echo.js.map +1 -1
- package/dist/commands/false.js +2 -2
- package/dist/commands/fetch.d.ts +4 -0
- package/dist/commands/fetch.d.ts.map +1 -0
- package/dist/commands/fetch.js +210 -0
- package/dist/commands/fetch.js.map +1 -0
- package/dist/commands/format.d.ts +4 -0
- package/dist/commands/format.d.ts.map +1 -0
- package/dist/commands/format.js +178 -0
- package/dist/commands/format.js.map +1 -0
- package/dist/commands/hash.d.ts +4 -0
- package/dist/commands/hash.d.ts.map +1 -0
- package/dist/commands/hash.js +200 -0
- package/dist/commands/hash.js.map +1 -0
- package/dist/commands/head.js +2 -2
- package/dist/commands/id.js +2 -2
- package/dist/commands/id.js.map +1 -1
- package/dist/commands/less.d.ts.map +1 -1
- package/dist/commands/less.js +53 -2
- package/dist/commands/less.js.map +1 -1
- package/dist/commands/ls.d.ts.map +1 -1
- package/dist/commands/ls.js +41 -15
- package/dist/commands/ls.js.map +1 -1
- package/dist/commands/man.d.ts +4 -0
- package/dist/commands/man.d.ts.map +1 -0
- package/dist/commands/man.js +564 -0
- package/dist/commands/man.js.map +1 -0
- package/dist/commands/mkdir.js +2 -2
- package/dist/commands/mkdir.js.map +1 -1
- package/dist/commands/mktemp.d.ts +4 -0
- package/dist/commands/mktemp.d.ts.map +1 -0
- package/dist/commands/mktemp.js +229 -0
- package/dist/commands/mktemp.js.map +1 -0
- package/dist/commands/nc.js +2 -2
- package/dist/commands/nc.js.map +1 -1
- package/dist/commands/open.d.ts +4 -0
- package/dist/commands/open.d.ts.map +1 -0
- package/dist/commands/open.js +74 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/passkey.js +3 -3
- package/dist/commands/play.d.ts +4 -0
- package/dist/commands/play.d.ts.map +1 -0
- package/dist/commands/play.js +231 -0
- package/dist/commands/play.js.map +1 -0
- package/dist/commands/pwd.js +2 -2
- package/dist/commands/pwd.js.map +1 -1
- package/dist/commands/rm.d.ts.map +1 -1
- package/dist/commands/rm.js +57 -12
- package/dist/commands/rm.js.map +1 -1
- package/dist/commands/rmdir.js +2 -2
- package/dist/commands/rmdir.js.map +1 -1
- package/dist/commands/sockets.js +1 -1
- package/dist/commands/stat.d.ts.map +1 -1
- package/dist/commands/stat.js +37 -15
- package/dist/commands/stat.js.map +1 -1
- package/dist/commands/tail.js +2 -2
- package/dist/commands/tar.d.ts +4 -0
- package/dist/commands/tar.d.ts.map +1 -0
- package/dist/commands/tar.js +743 -0
- package/dist/commands/tar.js.map +1 -0
- package/dist/commands/touch.js +2 -2
- package/dist/commands/touch.js.map +1 -1
- package/dist/commands/true.js +2 -2
- package/dist/commands/unzip.d.ts +4 -0
- package/dist/commands/unzip.d.ts.map +1 -0
- package/dist/commands/unzip.js +443 -0
- package/dist/commands/unzip.js.map +1 -0
- package/dist/commands/user.js +1 -1
- package/dist/commands/video.d.ts +4 -0
- package/dist/commands/video.d.ts.map +1 -0
- package/dist/commands/video.js +250 -0
- package/dist/commands/video.js.map +1 -0
- package/dist/commands/view.d.ts +4 -0
- package/dist/commands/view.d.ts.map +1 -0
- package/dist/commands/view.js +488 -0
- package/dist/commands/view.js.map +1 -0
- package/dist/commands/web.d.ts +4 -0
- package/dist/commands/web.d.ts.map +1 -0
- package/dist/commands/web.js +348 -0
- package/dist/commands/web.js.map +1 -0
- package/dist/commands/whoami.js +2 -2
- package/dist/commands/whoami.js.map +1 -1
- package/dist/commands/zip.d.ts +4 -0
- package/dist/commands/zip.d.ts.map +1 -0
- package/dist/commands/zip.js +264 -0
- package/dist/commands/zip.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -2
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
- package/src/commands/cal.ts +2 -2
- package/src/commands/cat.ts +2 -2
- package/src/commands/cd.ts +2 -2
- package/src/commands/chmod.ts +19 -11
- package/src/commands/cp.ts +2 -2
- package/src/commands/cron.ts +499 -0
- package/src/commands/date.ts +2 -2
- package/src/commands/echo.ts +2 -2
- package/src/commands/false.ts +2 -2
- package/src/commands/fetch.ts +205 -0
- package/src/commands/format.ts +204 -0
- package/src/commands/hash.ts +215 -0
- package/src/commands/head.ts +2 -2
- package/src/commands/id.ts +2 -2
- package/src/commands/less.ts +50 -2
- package/src/commands/ls.ts +40 -14
- package/src/commands/man.ts +651 -0
- package/src/commands/mkdir.ts +2 -2
- package/src/commands/mktemp.ts +235 -0
- package/src/commands/nc.ts +2 -2
- package/src/commands/open.ts +84 -0
- package/src/commands/passkey.ts +3 -3
- package/src/commands/play.ts +249 -0
- package/src/commands/pwd.ts +2 -2
- package/src/commands/rm.ts +54 -12
- package/src/commands/rmdir.ts +2 -2
- package/src/commands/sockets.ts +1 -1
- package/src/commands/stat.ts +44 -16
- package/src/commands/tail.ts +2 -2
- package/src/commands/tar.ts +780 -0
- package/src/commands/touch.ts +2 -2
- package/src/commands/true.ts +2 -2
- package/src/commands/unzip.ts +517 -0
- package/src/commands/user.ts +1 -1
- package/src/commands/video.ts +267 -0
- package/src/commands/view.ts +526 -0
- package/src/commands/web.ts +377 -0
- package/src/commands/whoami.ts +2 -2
- package/src/commands/zip.ts +319 -0
- package/src/index.ts +44 -2
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import type { Kernel, Process, Shell, Terminal } from '@ecmaos/types'
|
|
3
|
+
import { TerminalCommand } from '../shared/terminal-command.js'
|
|
4
|
+
import { writelnStderr } from '../shared/helpers.js'
|
|
5
|
+
|
|
6
|
+
function printUsage(process: Process | undefined, terminal: Terminal): void {
|
|
7
|
+
const usage = `Usage: web [OPTIONS] [URL]
|
|
8
|
+
Open a URL in a new contained window.
|
|
9
|
+
Many sites will block the COR, so this is mostly useful for local/bespoke/credentialless resources.
|
|
10
|
+
To open in a new tab/browser window, use the 'open' command instead.
|
|
11
|
+
|
|
12
|
+
--help display this help and exit
|
|
13
|
+
--no-navbar hide the navigation bar
|
|
14
|
+
|
|
15
|
+
Examples:
|
|
16
|
+
web https://example.com open a URL in a browser window
|
|
17
|
+
web --no-navbar https://example.com open a URL without navigation bar
|
|
18
|
+
web example.com open a URL (https:// will be prepended)
|
|
19
|
+
web http://example.com open a URL with http protocol`
|
|
20
|
+
writelnStderr(process, terminal, usage)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function normalizeUrl(url: string): string {
|
|
24
|
+
const urlPattern = /^[a-zA-Z][a-zA-Z\d+\-.]*:/
|
|
25
|
+
if (urlPattern.test(url)) return url
|
|
26
|
+
|
|
27
|
+
return `https://${url}`
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal): TerminalCommand {
|
|
31
|
+
return new TerminalCommand({
|
|
32
|
+
command: 'web',
|
|
33
|
+
description: 'Open a URL in a browser window',
|
|
34
|
+
kernel,
|
|
35
|
+
shell,
|
|
36
|
+
terminal,
|
|
37
|
+
run: async (pid: number, argv: string[]) => {
|
|
38
|
+
const process = kernel.processes.get(pid) as Process | undefined
|
|
39
|
+
|
|
40
|
+
if (!process) return 1
|
|
41
|
+
|
|
42
|
+
if (argv.length > 0 && (argv[0] === '--help' || argv[0] === '-h')) {
|
|
43
|
+
printUsage(process, terminal)
|
|
44
|
+
return 0
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Parse arguments
|
|
48
|
+
let hideNavbar = false
|
|
49
|
+
const urlArgs: string[] = []
|
|
50
|
+
|
|
51
|
+
for (const arg of argv) {
|
|
52
|
+
const trimmedArg = arg.trim()
|
|
53
|
+
if (trimmedArg === '--no-navbar' || trimmedArg === '--hide-navbar') {
|
|
54
|
+
hideNavbar = true
|
|
55
|
+
} else if (trimmedArg && trimmedArg !== '--help' && trimmedArg !== '-h') {
|
|
56
|
+
// Remove any flag prefixes that might have been concatenated
|
|
57
|
+
let cleanArg = trimmedArg
|
|
58
|
+
if (cleanArg.startsWith('--no-navbar')) {
|
|
59
|
+
cleanArg = cleanArg.replace(/^--no-navbar/, '').trim()
|
|
60
|
+
hideNavbar = true
|
|
61
|
+
} else if (cleanArg.startsWith('--hide-navbar')) {
|
|
62
|
+
cleanArg = cleanArg.replace(/^--hide-navbar/, '').trim()
|
|
63
|
+
hideNavbar = true
|
|
64
|
+
}
|
|
65
|
+
if (cleanArg) {
|
|
66
|
+
urlArgs.push(cleanArg)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (urlArgs.length === 0) {
|
|
72
|
+
await writelnStderr(process, terminal, `web: missing URL argument`)
|
|
73
|
+
await writelnStderr(process, terminal, `Try 'web --help' for more information.`)
|
|
74
|
+
return 1
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const urlString = urlArgs.join(' ').trim()
|
|
78
|
+
if (!urlString) {
|
|
79
|
+
await writelnStderr(process, terminal, `web: missing URL argument`)
|
|
80
|
+
return 1
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const url = normalizeUrl(urlString)
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
// Validate URL
|
|
87
|
+
new URL(url)
|
|
88
|
+
} catch (error) {
|
|
89
|
+
await writelnStderr(process, terminal, chalk.red(`web: invalid URL: ${urlString}`))
|
|
90
|
+
return 1
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Create container for browser UI
|
|
94
|
+
const container = document.createElement('div')
|
|
95
|
+
container.style.width = '100%'
|
|
96
|
+
container.style.height = '100%'
|
|
97
|
+
container.style.display = 'flex'
|
|
98
|
+
container.style.flexDirection = 'column'
|
|
99
|
+
container.style.background = '#fff'
|
|
100
|
+
container.style.overflow = 'hidden'
|
|
101
|
+
container.style.boxSizing = 'border-box'
|
|
102
|
+
|
|
103
|
+
// Create navigation bar
|
|
104
|
+
const navBar = document.createElement('div')
|
|
105
|
+
navBar.style.display = 'flex'
|
|
106
|
+
navBar.style.alignItems = 'center'
|
|
107
|
+
navBar.style.gap = '4px'
|
|
108
|
+
navBar.style.padding = '6px 8px'
|
|
109
|
+
navBar.style.borderBottom = '1px solid #ccc'
|
|
110
|
+
navBar.style.background = '#f5f5f5'
|
|
111
|
+
navBar.style.flexShrink = '0'
|
|
112
|
+
navBar.style.boxSizing = 'border-box'
|
|
113
|
+
|
|
114
|
+
// Back button
|
|
115
|
+
const backButton = document.createElement('button')
|
|
116
|
+
backButton.innerHTML = '←'
|
|
117
|
+
backButton.style.padding = '0'
|
|
118
|
+
backButton.style.margin = '0'
|
|
119
|
+
backButton.style.cursor = 'pointer'
|
|
120
|
+
backButton.style.border = '1px solid #ccc'
|
|
121
|
+
backButton.style.borderRadius = '4px'
|
|
122
|
+
backButton.style.background = '#fff'
|
|
123
|
+
backButton.style.color = '#000'
|
|
124
|
+
backButton.style.fontSize = '16px'
|
|
125
|
+
backButton.style.width = '32px'
|
|
126
|
+
backButton.style.height = '28px'
|
|
127
|
+
backButton.style.display = 'flex'
|
|
128
|
+
backButton.style.alignItems = 'center'
|
|
129
|
+
backButton.style.justifyContent = 'center'
|
|
130
|
+
backButton.style.flexShrink = '0'
|
|
131
|
+
backButton.style.boxSizing = 'border-box'
|
|
132
|
+
backButton.style.lineHeight = '1'
|
|
133
|
+
backButton.style.verticalAlign = 'middle'
|
|
134
|
+
backButton.disabled = true
|
|
135
|
+
backButton.style.opacity = backButton.disabled ? '0.5' : '1'
|
|
136
|
+
|
|
137
|
+
// Forward button
|
|
138
|
+
const forwardButton = document.createElement('button')
|
|
139
|
+
forwardButton.innerHTML = '→'
|
|
140
|
+
forwardButton.style.padding = '0'
|
|
141
|
+
forwardButton.style.margin = '0'
|
|
142
|
+
forwardButton.style.cursor = 'pointer'
|
|
143
|
+
forwardButton.style.border = '1px solid #ccc'
|
|
144
|
+
forwardButton.style.borderRadius = '4px'
|
|
145
|
+
forwardButton.style.background = '#fff'
|
|
146
|
+
forwardButton.style.color = '#000'
|
|
147
|
+
forwardButton.style.fontSize = '16px'
|
|
148
|
+
forwardButton.style.width = '32px'
|
|
149
|
+
forwardButton.style.height = '28px'
|
|
150
|
+
forwardButton.style.display = 'flex'
|
|
151
|
+
forwardButton.style.alignItems = 'center'
|
|
152
|
+
forwardButton.style.justifyContent = 'center'
|
|
153
|
+
forwardButton.style.flexShrink = '0'
|
|
154
|
+
forwardButton.style.boxSizing = 'border-box'
|
|
155
|
+
forwardButton.style.lineHeight = '1'
|
|
156
|
+
forwardButton.style.verticalAlign = 'middle'
|
|
157
|
+
forwardButton.disabled = true
|
|
158
|
+
forwardButton.style.opacity = forwardButton.disabled ? '0.5' : '1'
|
|
159
|
+
|
|
160
|
+
// URL input
|
|
161
|
+
const urlInput = document.createElement('input')
|
|
162
|
+
urlInput.type = 'text'
|
|
163
|
+
urlInput.value = url
|
|
164
|
+
urlInput.style.flex = '1'
|
|
165
|
+
urlInput.style.minWidth = '0'
|
|
166
|
+
urlInput.style.padding = '6px 12px'
|
|
167
|
+
urlInput.style.border = '1px solid #ccc'
|
|
168
|
+
urlInput.style.borderRadius = '4px'
|
|
169
|
+
urlInput.style.fontSize = '14px'
|
|
170
|
+
urlInput.style.height = '28px'
|
|
171
|
+
urlInput.style.boxSizing = 'border-box'
|
|
172
|
+
urlInput.style.margin = '0'
|
|
173
|
+
urlInput.style.verticalAlign = 'middle'
|
|
174
|
+
|
|
175
|
+
// Refresh button
|
|
176
|
+
const refreshButton = document.createElement('button')
|
|
177
|
+
refreshButton.innerHTML = '↻'
|
|
178
|
+
refreshButton.style.padding = '0'
|
|
179
|
+
refreshButton.style.margin = '0'
|
|
180
|
+
refreshButton.style.cursor = 'pointer'
|
|
181
|
+
refreshButton.style.border = '1px solid #ccc'
|
|
182
|
+
refreshButton.style.borderRadius = '4px'
|
|
183
|
+
refreshButton.style.background = '#fff'
|
|
184
|
+
refreshButton.style.color = '#000'
|
|
185
|
+
refreshButton.style.fontSize = '16px'
|
|
186
|
+
refreshButton.style.width = '32px'
|
|
187
|
+
refreshButton.style.height = '28px'
|
|
188
|
+
refreshButton.style.display = 'flex'
|
|
189
|
+
refreshButton.style.alignItems = 'center'
|
|
190
|
+
refreshButton.style.justifyContent = 'center'
|
|
191
|
+
refreshButton.style.flexShrink = '0'
|
|
192
|
+
refreshButton.style.boxSizing = 'border-box'
|
|
193
|
+
refreshButton.style.lineHeight = '1'
|
|
194
|
+
refreshButton.style.verticalAlign = 'middle'
|
|
195
|
+
|
|
196
|
+
navBar.appendChild(backButton)
|
|
197
|
+
navBar.appendChild(forwardButton)
|
|
198
|
+
navBar.appendChild(urlInput)
|
|
199
|
+
navBar.appendChild(refreshButton)
|
|
200
|
+
|
|
201
|
+
const iframeContainer = document.createElement('div')
|
|
202
|
+
iframeContainer.style.flex = '1'
|
|
203
|
+
iframeContainer.style.position = 'relative'
|
|
204
|
+
iframeContainer.style.overflow = 'hidden'
|
|
205
|
+
|
|
206
|
+
const iframe = document.createElement('iframe')
|
|
207
|
+
iframe.style.width = '100%'
|
|
208
|
+
iframe.style.height = '100%'
|
|
209
|
+
iframe.style.border = 'none'
|
|
210
|
+
iframe.setAttribute('credentialless', '')
|
|
211
|
+
iframe.src = url
|
|
212
|
+
|
|
213
|
+
iframeContainer.appendChild(iframe)
|
|
214
|
+
|
|
215
|
+
// Only append navbar if not hidden
|
|
216
|
+
if (!hideNavbar) container.appendChild(navBar)
|
|
217
|
+
container.appendChild(iframeContainer)
|
|
218
|
+
|
|
219
|
+
// Navigation history
|
|
220
|
+
const history: string[] = [url]
|
|
221
|
+
let historyIndex = 0
|
|
222
|
+
|
|
223
|
+
// Update navigation buttons state
|
|
224
|
+
const updateNavButtons = () => {
|
|
225
|
+
if (!hideNavbar) {
|
|
226
|
+
backButton.disabled = historyIndex <= 0
|
|
227
|
+
backButton.style.opacity = backButton.disabled ? '0.5' : '1'
|
|
228
|
+
forwardButton.disabled = historyIndex >= history.length - 1
|
|
229
|
+
forwardButton.style.opacity = forwardButton.disabled ? '0.5' : '1'
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Navigate to URL
|
|
234
|
+
const navigateTo = (targetUrl: string, addToHistory = true) => {
|
|
235
|
+
try {
|
|
236
|
+
const normalizedUrl = normalizeUrl(targetUrl)
|
|
237
|
+
new URL(normalizedUrl) // Validate URL
|
|
238
|
+
|
|
239
|
+
if (addToHistory) {
|
|
240
|
+
// Remove forward history if we're navigating to a new URL
|
|
241
|
+
if (historyIndex < history.length - 1) history.splice(historyIndex + 1)
|
|
242
|
+
|
|
243
|
+
history.push(normalizedUrl)
|
|
244
|
+
historyIndex = history.length - 1
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
iframe.src = normalizedUrl
|
|
248
|
+
if (!hideNavbar) {
|
|
249
|
+
urlInput.value = normalizedUrl
|
|
250
|
+
}
|
|
251
|
+
updateNavButtons()
|
|
252
|
+
} catch (error) {
|
|
253
|
+
terminal.writeln(chalk.red(`Invalid URL: ${targetUrl}`))
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Only set up button handlers if navbar is visible
|
|
258
|
+
if (!hideNavbar) {
|
|
259
|
+
// Add hover effects
|
|
260
|
+
const addHoverEffect = (button: HTMLButtonElement) => {
|
|
261
|
+
button.addEventListener('mouseenter', () => {
|
|
262
|
+
if (!button.disabled) {
|
|
263
|
+
button.style.background = '#f0f0f0'
|
|
264
|
+
}
|
|
265
|
+
})
|
|
266
|
+
button.addEventListener('mouseleave', () => {
|
|
267
|
+
button.style.background = '#fff'
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
addHoverEffect(backButton)
|
|
271
|
+
addHoverEffect(forwardButton)
|
|
272
|
+
addHoverEffect(refreshButton)
|
|
273
|
+
|
|
274
|
+
// Back button handler
|
|
275
|
+
backButton.addEventListener('click', () => {
|
|
276
|
+
if (historyIndex > 0) {
|
|
277
|
+
historyIndex--
|
|
278
|
+
const targetUrl = history[historyIndex]
|
|
279
|
+
if (targetUrl) {
|
|
280
|
+
iframe.src = targetUrl
|
|
281
|
+
urlInput.value = targetUrl
|
|
282
|
+
updateNavButtons()
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
// Forward button handler
|
|
288
|
+
forwardButton.addEventListener('click', () => {
|
|
289
|
+
if (historyIndex < history.length - 1) {
|
|
290
|
+
historyIndex++
|
|
291
|
+
const targetUrl = history[historyIndex]
|
|
292
|
+
if (targetUrl) {
|
|
293
|
+
iframe.src = targetUrl
|
|
294
|
+
urlInput.value = targetUrl
|
|
295
|
+
updateNavButtons()
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
})
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Only set up navbar event handlers if navbar is visible
|
|
302
|
+
if (!hideNavbar) {
|
|
303
|
+
// URL input handler (Enter key or blur)
|
|
304
|
+
const handleUrlSubmit = () => {
|
|
305
|
+
const inputValue = urlInput.value.trim()
|
|
306
|
+
if (inputValue) {
|
|
307
|
+
navigateTo(inputValue)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
urlInput.addEventListener('keydown', (e: KeyboardEvent) => {
|
|
312
|
+
if (e.key === 'Enter') {
|
|
313
|
+
e.preventDefault()
|
|
314
|
+
handleUrlSubmit()
|
|
315
|
+
}
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
urlInput.addEventListener('blur', handleUrlSubmit)
|
|
319
|
+
|
|
320
|
+
// Refresh button handler
|
|
321
|
+
refreshButton.addEventListener('click', () => {
|
|
322
|
+
iframe.src = iframe.src
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
// Update URL bar when iframe navigates (for same-origin or when possible)
|
|
326
|
+
iframe.addEventListener('load', () => {
|
|
327
|
+
try {
|
|
328
|
+
// Try to get the current URL from iframe (may fail due to CORS)
|
|
329
|
+
const iframeUrl = iframe.contentWindow?.location.href
|
|
330
|
+
if (iframeUrl && iframeUrl !== urlInput.value) {
|
|
331
|
+
urlInput.value = iframeUrl
|
|
332
|
+
// Only add to history if it's a different URL
|
|
333
|
+
if (iframeUrl !== history[historyIndex]) navigateTo(iframeUrl)
|
|
334
|
+
}
|
|
335
|
+
} catch (e) {
|
|
336
|
+
// CORS: Can't access iframe location, that's okay
|
|
337
|
+
// The URL bar will show what we set it to
|
|
338
|
+
}
|
|
339
|
+
updateNavButtons()
|
|
340
|
+
})
|
|
341
|
+
} else {
|
|
342
|
+
// Still track history even without navbar
|
|
343
|
+
iframe.addEventListener('load', () => {
|
|
344
|
+
try {
|
|
345
|
+
const iframeUrl = iframe.contentWindow?.location.href
|
|
346
|
+
if (iframeUrl && iframeUrl !== history[historyIndex]) {
|
|
347
|
+
navigateTo(iframeUrl, true)
|
|
348
|
+
}
|
|
349
|
+
} catch (e) {
|
|
350
|
+
// CORS: Can't access iframe location
|
|
351
|
+
}
|
|
352
|
+
})
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Create window
|
|
356
|
+
const win = kernel.windows.create({
|
|
357
|
+
title: url,
|
|
358
|
+
width: Math.floor(window.innerWidth * 0.75),
|
|
359
|
+
height: Math.floor(window.innerHeight * 0.75),
|
|
360
|
+
x: 'center',
|
|
361
|
+
y: 'center',
|
|
362
|
+
onclose: () => false
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
// Mount container to window
|
|
366
|
+
win.mount(container)
|
|
367
|
+
|
|
368
|
+
// Update window title when URL changes (only if navbar is visible)
|
|
369
|
+
if (!hideNavbar) {
|
|
370
|
+
const updateTitle = () => win.setTitle(urlInput.value)
|
|
371
|
+
urlInput.addEventListener('input', updateTitle)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return 0
|
|
375
|
+
}
|
|
376
|
+
})
|
|
377
|
+
}
|
package/src/commands/whoami.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Kernel, Process, Shell, Terminal } from '@ecmaos/types'
|
|
2
2
|
import { TerminalCommand } from '../shared/terminal-command.js'
|
|
3
|
-
import { writelnStdout } from '../shared/helpers.js'
|
|
3
|
+
import { writelnStdout, writelnStderr } from '../shared/helpers.js'
|
|
4
4
|
|
|
5
5
|
function printUsage(process: Process | undefined, terminal: Terminal): void {
|
|
6
6
|
const usage = `Usage: whoami
|
|
7
7
|
Print effective user ID.
|
|
8
8
|
|
|
9
9
|
--help display this help and exit`
|
|
10
|
-
|
|
10
|
+
writelnStderr(process, terminal, usage)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal): TerminalCommand {
|