typescript-virtual-container 1.6.0 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,7 +43,7 @@ export const dmesgCommand = {
43
43
  const n = args.includes("-n") ? parseInt(args[args.indexOf("-n") + 1] ?? "20", 10) : 20;
44
44
  const msgs = [
45
45
  "[ 0.000000] Booting Linux on physical CPU 0x0",
46
- "[ 0.000000] Linux version 6.1.0-fortune (gcc version 12.2.0)",
46
+ "[ 0.000000] Linux version 6.1.0-fortune (gcc (Fortune 13.3.0-nyx1) 13.3.0)",
47
47
  "[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-6.1.0 root=/dev/sda1 ro quiet",
48
48
  "[ 0.000000] BIOS-provided physical RAM map:",
49
49
  "[ 0.000000] ACPI: IRQ0 used by override.",
@@ -429,7 +429,7 @@ OPTIONS
429
429
  "dpkg": `DPKG(1) User Commands DPKG(1)
430
430
 
431
431
  NAME
432
- dpkg - package manager for Debian-like systems
432
+ dpkg - package manager for Fortune GNU/Linux
433
433
 
434
434
  SYNOPSIS
435
435
  dpkg [OPTION]... ACTION
@@ -23,7 +23,7 @@ export const realpathCommand = {
23
23
  const resolved = shell.vfs.isSymlink(p)
24
24
  ? shell.vfs.resolveSymlink(p)
25
25
  : p;
26
- return { stdout: path.posix.normalize(resolved) + "\n", exitCode: 0 };
26
+ return { stdout: `${path.posix.normalize(resolved)}\n`, exitCode: 0 };
27
27
  },
28
28
  };
29
29
  /**
@@ -106,7 +106,7 @@ export const stringsCommand = {
106
106
  }
107
107
  if (current.length >= 4)
108
108
  results.push(current);
109
- return { stdout: results.join("\n") + "\n", exitCode: 0 };
109
+ return { stdout: `${results.join("\n")}\n`, exitCode: 0 };
110
110
  },
111
111
  };
112
112
  /**
@@ -228,6 +228,6 @@ export const fmtCommand = {
228
228
  }
229
229
  if (current)
230
230
  lines.push(current);
231
- return { stdout: lines.join("\n") + "\n", exitCode: 0 };
231
+ return { stdout: `${lines.join("\n")}\n`, exitCode: 0 };
232
232
  },
233
233
  };
@@ -0,0 +1,2 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const mousepadCommand: ShellModule;
@@ -0,0 +1,21 @@
1
+ export const mousepadCommand = {
2
+ name: "mousepad",
3
+ aliases: ["gedit", "xed"],
4
+ params: ["[file]"],
5
+ description: "Open a text file in the desktop text editor",
6
+ category: "desktop",
7
+ run(ctx) {
8
+ const dm = ctx.shell.desktopManager;
9
+ if (!dm) {
10
+ return { stderr: "mousepad: desktop is only available in the browser", exitCode: 1 };
11
+ }
12
+ if (!dm.isActive()) {
13
+ return { stderr: "mousepad: no desktop session running (start with startxfce4)", exitCode: 1 };
14
+ }
15
+ const path = ctx.args[0]
16
+ ? ctx.args[0].startsWith("/") ? ctx.args[0] : `${ctx.cwd}/${ctx.args[0]}`
17
+ : "/root/untitled.txt";
18
+ dm.createEditorWindow(path);
19
+ return { exitCode: 0 };
20
+ },
21
+ };
@@ -42,7 +42,7 @@ export const ncCommand = {
42
42
  const nonFlag = args.filter((a) => !a.startsWith("-"));
43
43
  const host = nonFlag[0];
44
44
  const portNum = nonFlag[1] ? parseInt(nonFlag[1], 10) : NaN;
45
- if (host && !isNaN(portNum)) {
45
+ if (host && !Number.isNaN(portNum)) {
46
46
  return new Promise((resolve) => {
47
47
  const socket = net.createConnection({ host, port: portNum }, () => {
48
48
  if (verbose) {
@@ -27,7 +27,7 @@ export const pgrepCommand = {
27
27
  }
28
28
  if (results.length === 0)
29
29
  return { exitCode: 1 };
30
- return { stdout: results.join("\n") + "\n", exitCode: 0 };
30
+ return { stdout: `${results.join("\n")}\n`, exitCode: 0 };
31
31
  }
32
32
  catch {
33
33
  return { stderr: "pgrep: invalid pattern\n", exitCode: 2 };
@@ -109,6 +109,9 @@ import { pgrepCommand, pkillCommand } from "./procUtils";
109
109
  import { lscpuCommand, lsusbCommand, lspciCommand } from "./sysinfo";
110
110
  import { joinCommand, commCommand, splitCommand, csplitCommand } from "./textutils";
111
111
  import { topCommand } from "./top";
112
+ import { startxfce4Command } from "./startxfce4";
113
+ import { thunarCommand } from "./xfceDesktop";
114
+ import { mousepadCommand } from "./mousepad";
112
115
  const BASE_COMMANDS = [
113
116
  // Navigation
114
117
  pwdCommand,
@@ -258,6 +261,10 @@ const BASE_COMMANDS = [
258
261
  nodeCommand,
259
262
  python3Command,
260
263
  exprCommand,
264
+ // Desktop
265
+ startxfce4Command,
266
+ thunarCommand,
267
+ mousepadCommand,
261
268
  // System (extended)
262
269
  uptimeCommand,
263
270
  freeCommand,
@@ -0,0 +1,2 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const startxfce4Command: ShellModule;
@@ -0,0 +1,13 @@
1
+ export const startxfce4Command = {
2
+ name: "startxfce4",
3
+ aliases: ["xfce4-session"],
4
+ params: [],
5
+ async run(ctx) {
6
+ const dm = ctx.shell.desktopManager;
7
+ if (!dm) {
8
+ return { stderr: "startxfce4: desktop is only available in the browser", exitCode: 1 };
9
+ }
10
+ await dm.start();
11
+ return { exitCode: 0 };
12
+ },
13
+ };
@@ -27,7 +27,7 @@ export const lscpuCommand = {
27
27
  `Socket(s): 1`,
28
28
  `Vendor ID: GenuineIntel`,
29
29
  ];
30
- return { stdout: lines.join("\n") + "\n", exitCode: 0 };
30
+ return { stdout: `${lines.join("\n")}\n`, exitCode: 0 };
31
31
  },
32
32
  };
33
33
  /**
@@ -46,7 +46,7 @@ export const lsusbCommand = {
46
46
  "Bus 001 Device 002: ID 80ee:0021 VirtualBox USB Tablet",
47
47
  "Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub",
48
48
  ];
49
- return { stdout: devices.join("\n") + "\n", exitCode: 0 };
49
+ return { stdout: `${devices.join("\n")}\n`, exitCode: 0 };
50
50
  },
51
51
  };
52
52
  /**
@@ -68,6 +68,6 @@ export const lspciCommand = {
68
68
  "00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller",
69
69
  "00:04.0 SATA controller: Intel Corporation 82801IR/IO (ICH9R) SATA Controller",
70
70
  ];
71
- return { stdout: devices.join("\n") + "\n", exitCode: 0 };
71
+ return { stdout: `${devices.join("\n")}\n`, exitCode: 0 };
72
72
  },
73
73
  };
@@ -49,7 +49,7 @@ export const joinCommand = {
49
49
  results.push(`${match} ${line}`);
50
50
  }
51
51
  }
52
- return { stdout: results.join("\n") + "\n", exitCode: 0 };
52
+ return { stdout: `${results.join("\n")}\n`, exitCode: 0 };
53
53
  },
54
54
  };
55
55
  /**
@@ -105,7 +105,7 @@ export const commCommand = {
105
105
  const col3 = i < both.length ? both[i] : "";
106
106
  results.push(`${col1}\t${col2}\t${col3}`);
107
107
  }
108
- return { stdout: results.join("\n") + "\n", exitCode: 0 };
108
+ return { stdout: `${results.join("\n")}\n`, exitCode: 0 };
109
109
  },
110
110
  };
111
111
  /**
@@ -49,6 +49,6 @@ export const topCommand = {
49
49
  const status = p.status === "running" ? "R" : "S";
50
50
  lines.push(`${String(p.pid).padStart(5)} ${p.username.padEnd(8).slice(0, 8)} 20 0 ${String(virt).padStart(7)} ${String(res).padStart(6)} ${String(shr).padStart(6)} ${status} ${cpu.padStart(4)} ${mem.padStart(5)} 0:00.00 ${p.command}`);
51
51
  });
52
- return { stdout: lines.join("\n") + "\n", exitCode: 0 };
52
+ return { stdout: `${lines.join("\n")}\n`, exitCode: 0 };
53
53
  },
54
54
  };
@@ -12,7 +12,7 @@ export const unameCommand = {
12
12
  run: ({ shell, args }) => {
13
13
  const all = ifFlag(args, ["-a"]);
14
14
  const sysname = "Linux";
15
- const release = shell.properties?.kernel ?? "5.15.0";
15
+ const release = shell.properties?.kernel ?? "1.0.0+itsrealfortune+1-amd64";
16
16
  const machine = shell.properties?.arch ?? "x86_64";
17
17
  const hostname = shell.hostname;
18
18
  if (all)
@@ -0,0 +1,2 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const thunarCommand: ShellModule;
@@ -0,0 +1,13 @@
1
+ export const thunarCommand = {
2
+ name: "thunar",
3
+ params: [],
4
+ run(ctx) {
5
+ const dm = ctx.shell.desktopManager;
6
+ if (!dm?.isActive()) {
7
+ return { stderr: "thunar: desktop is not running (start it with startxfce4)", exitCode: 1 };
8
+ }
9
+ const path = ctx.args[0] || ctx.env.vars.HOME || "/root";
10
+ dm.createThunarWindow(path);
11
+ return { exitCode: 0 };
12
+ },
13
+ };
@@ -5,6 +5,10 @@
5
5
  * latency and packet loss. Used by the `ip`, `ping`, and `netstat` commands
6
6
  * to produce dynamic, deterministic output instead of hardcoded strings.
7
7
  */
8
+ /**
9
+ * A virtual network interface, either loopback or ethernet,
10
+ * with MAC address, MTU, IPv4/IPv6 addresses, and link state.
11
+ */
8
12
  export interface VirtualInterface {
9
13
  name: string;
10
14
  type: "loopback" | "ether";
@@ -15,6 +19,10 @@ export interface VirtualInterface {
15
19
  ipv4Mask: number;
16
20
  ipv6: string;
17
21
  }
22
+ /**
23
+ * A routing table entry mapping a destination subnet
24
+ * to a gateway and outbound device.
25
+ */
18
26
  export interface VirtualRoute {
19
27
  destination: string;
20
28
  gateway: string;
@@ -22,32 +30,93 @@ export interface VirtualRoute {
22
30
  device: string;
23
31
  flags: string;
24
32
  }
33
+ /**
34
+ * An ARP cache entry mapping an IP address to a MAC address
35
+ * on a specific device, with neighbour reachability state.
36
+ */
25
37
  export interface VirtualArpEntry {
26
38
  ip: string;
27
39
  mac: string;
28
40
  device: string;
29
41
  state: "REACHABLE" | "STALE" | "PERMANENT";
30
42
  }
43
+ /**
44
+ * Virtual network stack with routing table, ARP cache, and interface management.
45
+ * Provides dynamic data for `ip`, `ping`, and `/proc/net/*`.
46
+ */
31
47
  export declare class VirtualNetworkManager {
32
48
  private interfaces;
33
49
  private routes;
34
50
  private arpCache;
51
+ /**
52
+ * Returns a copy of all configured interfaces.
53
+ * @returns Array of VirtualInterface objects.
54
+ */
35
55
  getInterfaces(): VirtualInterface[];
56
+ /**
57
+ * Returns a copy of the routing table.
58
+ * @returns Array of VirtualRoute objects.
59
+ */
36
60
  getRoutes(): VirtualRoute[];
61
+ /**
62
+ * Returns a copy of the ARP cache.
63
+ * @returns Array of VirtualArpEntry objects.
64
+ */
37
65
  getArpCache(): VirtualArpEntry[];
66
+ /**
67
+ * Adds a new route to the routing table.
68
+ * @param dest Destination network or "default".
69
+ * @param gateway Gateway IP address.
70
+ * @param netmask Subnet mask (e.g. "255.255.255.0").
71
+ * @param device Outbound device name (e.g. "eth0").
72
+ */
38
73
  addRoute(dest: string, gateway: string, netmask: string, device: string): void;
74
+ /**
75
+ * Removes a route by destination network.
76
+ * @param dest Destination network to remove.
77
+ * @returns True if a route was removed, false if no match.
78
+ */
39
79
  delRoute(dest: string): boolean;
80
+ /**
81
+ * Sets the administrative state of an interface.
82
+ * @param name Interface name ("lo", "eth0", etc.).
83
+ * @param state Desired state: "UP" or "DOWN".
84
+ * @returns True if the interface was found and updated, false otherwise.
85
+ */
40
86
  setInterfaceState(name: string, state: "UP" | "DOWN"): boolean;
87
+ /**
88
+ * Sets the IPv4 address and prefix length on an interface.
89
+ * @param name Interface name.
90
+ * @param ipv4 New IPv4 address.
91
+ * @param mask New subnet mask prefix length (e.g. 24).
92
+ * @returns True if the interface was found and updated, false otherwise.
93
+ */
41
94
  setInterfaceIp(name: string, ipv4: string, mask: number): boolean;
42
- /** Ping simulation: returns latency in ms, or -1 if unreachable. */
95
+ /**
96
+ * Simulates an ICMP ping to the given host.
97
+ * @param host Target IP address or hostname.
98
+ * @returns Latency in milliseconds if reachable, -1 if unreachable.
99
+ */
43
100
  ping(host: string): number;
44
- /** Get formatted output for `ip addr`. */
101
+ /**
102
+ * Formats all interfaces as `ip addr` output.
103
+ * @returns Formatted string mimicking `ip addr` command.
104
+ */
45
105
  formatIpAddr(): string;
46
- /** Get formatted output for `ip route`. */
106
+ /**
107
+ * Formats the routing table as `ip route` output.
108
+ * @returns Formatted string mimicking `ip route` command.
109
+ */
47
110
  formatIpRoute(): string;
48
- /** Get formatted output for `ip link`. */
111
+ /**
112
+ * Formats all interfaces as `ip link` output.
113
+ * @returns Formatted string mimicking `ip link` command.
114
+ */
49
115
  formatIpLink(): string;
50
- /** Get formatted output for `ip neigh`. */
116
+ /**
117
+ * Formats the ARP cache as `ip neigh` output.
118
+ * @returns Formatted string mimicking `ip neigh` command.
119
+ */
51
120
  formatIpNeigh(): string;
52
121
  private _maskToCidr;
53
122
  private _ipForDevice;
@@ -5,10 +5,15 @@
5
5
  * latency and packet loss. Used by the `ip`, `ping`, and `netstat` commands
6
6
  * to produce dynamic, deterministic output instead of hardcoded strings.
7
7
  */
8
+ /** Generates a random MAC address in the 02:42:xx:xx:xx:xx range. */
8
9
  function randomMac() {
9
10
  const hex = () => Math.floor(Math.random() * 256).toString(16).padStart(2, "0");
10
11
  return `02:42:${hex()}:${hex()}:${hex()}:${hex()}`;
11
12
  }
13
+ /**
14
+ * Virtual network stack with routing table, ARP cache, and interface management.
15
+ * Provides dynamic data for `ip`, `ping`, and `/proc/net/*`.
16
+ */
12
17
  export class VirtualNetworkManager {
13
18
  interfaces = [
14
19
  {
@@ -40,18 +45,42 @@ export class VirtualNetworkManager {
40
45
  arpCache = [
41
46
  { ip: "10.0.0.1", mac: "02:42:0a:00:00:01", device: "eth0", state: "REACHABLE" },
42
47
  ];
48
+ /**
49
+ * Returns a copy of all configured interfaces.
50
+ * @returns Array of VirtualInterface objects.
51
+ */
43
52
  getInterfaces() {
44
53
  return [...this.interfaces];
45
54
  }
55
+ /**
56
+ * Returns a copy of the routing table.
57
+ * @returns Array of VirtualRoute objects.
58
+ */
46
59
  getRoutes() {
47
60
  return [...this.routes];
48
61
  }
62
+ /**
63
+ * Returns a copy of the ARP cache.
64
+ * @returns Array of VirtualArpEntry objects.
65
+ */
49
66
  getArpCache() {
50
67
  return [...this.arpCache];
51
68
  }
69
+ /**
70
+ * Adds a new route to the routing table.
71
+ * @param dest Destination network or "default".
72
+ * @param gateway Gateway IP address.
73
+ * @param netmask Subnet mask (e.g. "255.255.255.0").
74
+ * @param device Outbound device name (e.g. "eth0").
75
+ */
52
76
  addRoute(dest, gateway, netmask, device) {
53
77
  this.routes.push({ destination: dest, gateway, netmask, device, flags: "UG" });
54
78
  }
79
+ /**
80
+ * Removes a route by destination network.
81
+ * @param dest Destination network to remove.
82
+ * @returns True if a route was removed, false if no match.
83
+ */
55
84
  delRoute(dest) {
56
85
  const idx = this.routes.findIndex((r) => r.destination === dest);
57
86
  if (idx === -1)
@@ -59,6 +88,12 @@ export class VirtualNetworkManager {
59
88
  this.routes.splice(idx, 1);
60
89
  return true;
61
90
  }
91
+ /**
92
+ * Sets the administrative state of an interface.
93
+ * @param name Interface name ("lo", "eth0", etc.).
94
+ * @param state Desired state: "UP" or "DOWN".
95
+ * @returns True if the interface was found and updated, false otherwise.
96
+ */
62
97
  setInterfaceState(name, state) {
63
98
  const iface = this.interfaces.find((i) => i.name === name);
64
99
  if (!iface)
@@ -66,6 +101,13 @@ export class VirtualNetworkManager {
66
101
  iface.state = state;
67
102
  return true;
68
103
  }
104
+ /**
105
+ * Sets the IPv4 address and prefix length on an interface.
106
+ * @param name Interface name.
107
+ * @param ipv4 New IPv4 address.
108
+ * @param mask New subnet mask prefix length (e.g. 24).
109
+ * @returns True if the interface was found and updated, false otherwise.
110
+ */
69
111
  setInterfaceIp(name, ipv4, mask) {
70
112
  const iface = this.interfaces.find((i) => i.name === name);
71
113
  if (!iface)
@@ -74,7 +116,11 @@ export class VirtualNetworkManager {
74
116
  iface.ipv4Mask = mask;
75
117
  return true;
76
118
  }
77
- /** Ping simulation: returns latency in ms, or -1 if unreachable. */
119
+ /**
120
+ * Simulates an ICMP ping to the given host.
121
+ * @param host Target IP address or hostname.
122
+ * @returns Latency in milliseconds if reachable, -1 if unreachable.
123
+ */
78
124
  ping(host) {
79
125
  // Loopback always works
80
126
  if (host === "127.0.0.1" || host === "localhost" || host === "::1") {
@@ -90,7 +136,10 @@ export class VirtualNetworkManager {
90
136
  return -1;
91
137
  return 0.8 + Math.random() * 5;
92
138
  }
93
- /** Get formatted output for `ip addr`. */
139
+ /**
140
+ * Formats all interfaces as `ip addr` output.
141
+ * @returns Formatted string mimicking `ip addr` command.
142
+ */
94
143
  formatIpAddr() {
95
144
  const lines = [];
96
145
  let idx = 1;
@@ -108,7 +157,10 @@ export class VirtualNetworkManager {
108
157
  }
109
158
  return lines.join("\n");
110
159
  }
111
- /** Get formatted output for `ip route`. */
160
+ /**
161
+ * Formats the routing table as `ip route` output.
162
+ * @returns Formatted string mimicking `ip route` command.
163
+ */
112
164
  formatIpRoute() {
113
165
  return this.routes.map((r) => {
114
166
  if (r.destination === "default") {
@@ -117,7 +169,10 @@ export class VirtualNetworkManager {
117
169
  return `${r.destination}/${this._maskToCidr(r.netmask)} dev ${r.device} proto kernel scope link src ${this._ipForDevice(r.device)}`;
118
170
  }).join("\n");
119
171
  }
120
- /** Get formatted output for `ip link`. */
172
+ /**
173
+ * Formats all interfaces as `ip link` output.
174
+ * @returns Formatted string mimicking `ip link` command.
175
+ */
121
176
  formatIpLink() {
122
177
  const lines = [];
123
178
  let idx = 1;
@@ -131,7 +186,10 @@ export class VirtualNetworkManager {
131
186
  }
132
187
  return lines.join("\n");
133
188
  }
134
- /** Get formatted output for `ip neigh`. */
189
+ /**
190
+ * Formats the ARP cache as `ip neigh` output.
191
+ * @returns Formatted string mimicking `ip neigh` command.
192
+ */
135
193
  formatIpNeigh() {
136
194
  return this.arpCache.map((e) => `${e.ip} dev ${e.device} lladdr ${e.mac} ${e.state}`).join("\n");
137
195
  }
@@ -0,0 +1,104 @@
1
+ import type { VirtualShell } from "../VirtualShell";
2
+ import type { ShellStream } from "../types/streams";
3
+ import { WebTermRenderer } from "./webTermRenderer";
4
+ export interface TerminalContent {
5
+ type: "terminal";
6
+ termRenderer: WebTermRenderer;
7
+ dataListeners: Array<(chunk: Buffer) => void>;
8
+ preEl?: HTMLPreElement;
9
+ stream?: ShellStream;
10
+ }
11
+ export interface ThunarContent {
12
+ type: "thunar";
13
+ path: string;
14
+ }
15
+ export interface AboutContent {
16
+ type: "about";
17
+ }
18
+ export interface EditorContent {
19
+ type: "editor";
20
+ path: string;
21
+ dirty: boolean;
22
+ }
23
+ export type WindowContent = TerminalContent | ThunarContent | AboutContent | EditorContent;
24
+ export interface DesktopWindow {
25
+ id: string;
26
+ title: string;
27
+ x: number;
28
+ y: number;
29
+ width: number;
30
+ height: number;
31
+ minimized: boolean;
32
+ focused: boolean;
33
+ zIndex: number;
34
+ content: WindowContent;
35
+ }
36
+ export interface DesktopState {
37
+ active: boolean;
38
+ windows: DesktopWindow[];
39
+ menuOpen: boolean;
40
+ clock: string;
41
+ focusedWindowId: string | null;
42
+ }
43
+ export declare class DesktopManager {
44
+ private shell;
45
+ private container;
46
+ private active;
47
+ private windows;
48
+ private zCounter;
49
+ private menuOpen;
50
+ private nextWinId;
51
+ private clockInterval?;
52
+ private onExit;
53
+ private stopResolve;
54
+ private dragState;
55
+ private _renderGuard;
56
+ private readonly trashPath;
57
+ private docListeners;
58
+ private pendingTimeouts;
59
+ constructor(shell: VirtualShell, container: HTMLElement);
60
+ isActive(): boolean;
61
+ setOnExit(cb: () => void): void;
62
+ start(): Promise<void>;
63
+ stop(): void;
64
+ getFocusedTerminal(): {
65
+ stream: ShellStream;
66
+ dataListeners: Array<(chunk: Buffer) => void>;
67
+ preEl: HTMLPreElement;
68
+ } | null;
69
+ handleKeyDown(e: KeyboardEvent): void;
70
+ handlePaste(e: ClipboardEvent): void;
71
+ createTerminalWindow(): string;
72
+ createThunarWindow(path?: string): string;
73
+ createEditorWindow(path?: string): string;
74
+ createAboutWindow(): string;
75
+ closeWindow(id: string): void;
76
+ toggleMinimize(id: string): void;
77
+ focusWindow(id: string): void;
78
+ private createWindow;
79
+ private ensureWindowElement;
80
+ private renderWindowElement;
81
+ private addDocListener;
82
+ private removeAllDocListeners;
83
+ private setupEventDelegation;
84
+ private renderAll;
85
+ private renderPanel;
86
+ private renderDesktopIcons;
87
+ private renderWindows;
88
+ private renderWindowPositions;
89
+ private renderTerminalContentById;
90
+ private renderThunarContent;
91
+ private renderEditorContent;
92
+ private saveEditor;
93
+ private renderAboutContent;
94
+ private updateClock;
95
+ private showContextMenu;
96
+ private closeContextMenu;
97
+ private ensureTrashDir;
98
+ private refreshThunarWindow;
99
+ private moveToTrash;
100
+ private trashRestore;
101
+ private trashDelete;
102
+ private renamePrompt;
103
+ private escapeHtml;
104
+ }