Terminal: Output-Batching (8 ms) + helle Themes, Projekt-Icons in der Liste, neues App-Icon inkl. Tray-Template, build.sh: Dev-Bundle nach .noindex
@@ -8,4 +8,18 @@ export RUSTUP_HOME="$HOME/tools/.rustup"
|
|||||||
export PATH="$CARGO_HOME/bin:$PATH"
|
export PATH="$CARGO_HOME/bin:$PATH"
|
||||||
|
|
||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
npm run tauri build -- "$@"
|
npm run tauri build -- --bundles app "$@"
|
||||||
|
|
||||||
|
# Dev-Bundle in ein .noindex-Verzeichnis schieben und aus Launch Services
|
||||||
|
# austragen — Spotlight indiziert .noindex-Ordner nicht, damit erscheint im
|
||||||
|
# Starter/Spotlight nur die installierte Kopie unter ~/Applications.
|
||||||
|
BUNDLE="$DIR/src-tauri/target/release/bundle/macos"
|
||||||
|
NOINDEX="$DIR/src-tauri/target/release/bundle/macos.noindex"
|
||||||
|
LSREGISTER=/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister
|
||||||
|
# lsregister -u meldet -10814, wenn das Bundle nicht registriert ist —
|
||||||
|
# erwartetes Ergebnis, kein Fehler.
|
||||||
|
"$LSREGISTER" -u "$BUNDLE/ai-control.app" || true
|
||||||
|
rm -rf "$NOINDEX/ai-control.app"
|
||||||
|
mkdir -p "$NOINDEX"
|
||||||
|
mv "$BUNDLE/ai-control.app" "$NOINDEX/"
|
||||||
|
"$LSREGISTER" -u "$NOINDEX/ai-control.app" || true
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 1012 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 956 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 867 B After Width: | Height: | Size: 747 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
@@ -123,17 +123,46 @@ pub fn term_start(
|
|||||||
|
|
||||||
let label = window.label().to_string();
|
let label = window.label().to_string();
|
||||||
let app = window.app_handle().clone();
|
let app = window.app_handle().clone();
|
||||||
|
|
||||||
|
// Output gebündelt emittieren statt pro read(): der Reader schiebt Chunks
|
||||||
|
// in einen Channel, der Emitter sammelt alles, was innerhalb von 8 ms
|
||||||
|
// ankommt, zu einem Event zusammen. Bei Output-Fluten (Scrollen, TUI-
|
||||||
|
// Redraws) sinkt die Zahl der IPC-Events um Größenordnungen; die 8 ms
|
||||||
|
// Zusatzlatenz beim Tasten-Echo liegen unter einem Frame.
|
||||||
|
let (tx, rx) = std::sync::mpsc::channel::<Vec<u8>>();
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let mut buf = [0u8; 8192];
|
let mut buf = [0u8; 8192];
|
||||||
loop {
|
loop {
|
||||||
match reader.read(&mut buf) {
|
match reader.read(&mut buf) {
|
||||||
Ok(0) | Err(_) => break,
|
Ok(0) | Err(_) => break,
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
let _ = app.emit_to(&label, "pty-output", STANDARD.encode(&buf[..n]));
|
if tx.send(buf[..n].to_vec()).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _ = child.wait();
|
let _ = child.wait();
|
||||||
|
// tx wird hier gedroppt — der Emitter sieht den geschlossenen Channel
|
||||||
|
// erst, nachdem er alle Rest-Chunks emittiert hat.
|
||||||
|
});
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
const FLUSH: std::time::Duration = std::time::Duration::from_millis(8);
|
||||||
|
while let Ok(first) = rx.recv() {
|
||||||
|
let mut chunk = first;
|
||||||
|
let deadline = std::time::Instant::now() + FLUSH;
|
||||||
|
loop {
|
||||||
|
let now = std::time::Instant::now();
|
||||||
|
if now >= deadline {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
match rx.recv_timeout(deadline - now) {
|
||||||
|
Ok(more) => chunk.extend_from_slice(&more),
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = app.emit_to(&label, "pty-output", STANDARD.encode(&chunk));
|
||||||
|
}
|
||||||
let _ = app.emit_to(&label, "pty-exit", ());
|
let _ = app.emit_to(&label, "pty-exit", ());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -387,6 +387,19 @@ tbody tr:hover {
|
|||||||
background: color-mix(in srgb, var(--mantle) 60%, transparent);
|
background: color-mix(in srgb, var(--mantle) 60%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.name-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proj-icon {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 4px;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
.cell-name strong {
|
.cell-name strong {
|
||||||
font-family: var(--mono);
|
font-family: var(--mono);
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { LigaturesAddon } from "@xterm/addon-ligatures";
|
|||||||
import "@xterm/xterm/css/xterm.css";
|
import "@xterm/xterm/css/xterm.css";
|
||||||
import "@fontsource/jetbrains-mono/400.css";
|
import "@fontsource/jetbrains-mono/400.css";
|
||||||
import "@fontsource/jetbrains-mono/500.css";
|
import "@fontsource/jetbrains-mono/500.css";
|
||||||
|
import "@fontsource/jetbrains-mono/600.css";
|
||||||
import "@fontsource/jetbrains-mono/700.css";
|
import "@fontsource/jetbrains-mono/700.css";
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||||
@@ -28,8 +29,9 @@ window.addEventListener("unhandledrejection", (e) =>
|
|||||||
const project = new URLSearchParams(location.search).get("project")!;
|
const project = new URLSearchParams(location.search).get("project")!;
|
||||||
const win = getCurrentWebviewWindow();
|
const win = getCurrentWebviewWindow();
|
||||||
|
|
||||||
// Fensterhintergründe je Theme stehen zusätzlich in terminal.rs
|
// Fensterhintergrund beim Öffnen kommt aus terminal.rs (theme_background);
|
||||||
// (theme_background) — beide Stellen müssen zusammenpassen.
|
// dort nicht gepflegte Themes fallen auf Mocha zurück (nur kurzer Moment
|
||||||
|
// bis die Webview lädt).
|
||||||
const THEMES: Record<
|
const THEMES: Record<
|
||||||
string,
|
string,
|
||||||
{ header: string; border: string; xterm: Record<string, string> }
|
{ header: string; border: string; xterm: Record<string, string> }
|
||||||
@@ -169,6 +171,222 @@ const THEMES: Record<
|
|||||||
brightWhite: "#ffffff",
|
brightWhite: "#ffffff",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"solarized-light": {
|
||||||
|
header: "#eee8d5",
|
||||||
|
border: "#93a1a1",
|
||||||
|
xterm: {
|
||||||
|
background: "#fdf6e3",
|
||||||
|
foreground: "#657b83",
|
||||||
|
cursor: "#657b83",
|
||||||
|
cursorAccent: "#fdf6e3",
|
||||||
|
selectionBackground: "#eee8d5b0",
|
||||||
|
black: "#073642",
|
||||||
|
red: "#dc322f",
|
||||||
|
green: "#859900",
|
||||||
|
yellow: "#b58900",
|
||||||
|
blue: "#268bd2",
|
||||||
|
magenta: "#d33682",
|
||||||
|
cyan: "#2aa198",
|
||||||
|
white: "#eee8d5",
|
||||||
|
brightBlack: "#002b36",
|
||||||
|
brightRed: "#cb4b16",
|
||||||
|
brightGreen: "#586e75",
|
||||||
|
brightYellow: "#657b83",
|
||||||
|
brightBlue: "#839496",
|
||||||
|
brightMagenta: "#6c71c4",
|
||||||
|
brightCyan: "#93a1a1",
|
||||||
|
brightWhite: "#fdf6e3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"catppuccin-latte": {
|
||||||
|
header: "#e6e9ef",
|
||||||
|
border: "#ccd0da",
|
||||||
|
xterm: {
|
||||||
|
background: "#eff1f5",
|
||||||
|
foreground: "#4c4f69",
|
||||||
|
cursor: "#dc8a78",
|
||||||
|
cursorAccent: "#eff1f5",
|
||||||
|
selectionBackground: "#acb0be80",
|
||||||
|
black: "#5c5f77",
|
||||||
|
red: "#d20f39",
|
||||||
|
green: "#40a02b",
|
||||||
|
yellow: "#df8e1d",
|
||||||
|
blue: "#1e66f5",
|
||||||
|
magenta: "#ea76cb",
|
||||||
|
cyan: "#179299",
|
||||||
|
white: "#acb0be",
|
||||||
|
brightBlack: "#6c6f85",
|
||||||
|
brightRed: "#d20f39",
|
||||||
|
brightGreen: "#40a02b",
|
||||||
|
brightYellow: "#df8e1d",
|
||||||
|
brightBlue: "#1e66f5",
|
||||||
|
brightMagenta: "#ea76cb",
|
||||||
|
brightCyan: "#179299",
|
||||||
|
brightWhite: "#bcc0cc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"one-light": {
|
||||||
|
header: "#eaeaeb",
|
||||||
|
border: "#d4d4d4",
|
||||||
|
xterm: {
|
||||||
|
background: "#fafafa",
|
||||||
|
foreground: "#383a42",
|
||||||
|
cursor: "#526eff",
|
||||||
|
cursorAccent: "#fafafa",
|
||||||
|
selectionBackground: "#e5e5e6b0",
|
||||||
|
black: "#383a42",
|
||||||
|
red: "#e45649",
|
||||||
|
green: "#50a14f",
|
||||||
|
yellow: "#c18401",
|
||||||
|
blue: "#4078f2",
|
||||||
|
magenta: "#a626a4",
|
||||||
|
cyan: "#0184bc",
|
||||||
|
white: "#a0a1a7",
|
||||||
|
brightBlack: "#696c77",
|
||||||
|
brightRed: "#e45649",
|
||||||
|
brightGreen: "#50a14f",
|
||||||
|
brightYellow: "#c18401",
|
||||||
|
brightBlue: "#4078f2",
|
||||||
|
brightMagenta: "#a626a4",
|
||||||
|
brightCyan: "#0184bc",
|
||||||
|
brightWhite: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nord: {
|
||||||
|
header: "#3b4252",
|
||||||
|
border: "#4c566a",
|
||||||
|
xterm: {
|
||||||
|
background: "#2e3440",
|
||||||
|
foreground: "#d8dee9",
|
||||||
|
cursor: "#d8dee9",
|
||||||
|
cursorAccent: "#2e3440",
|
||||||
|
selectionBackground: "#434c5e80",
|
||||||
|
black: "#3b4252",
|
||||||
|
red: "#bf616a",
|
||||||
|
green: "#a3be8c",
|
||||||
|
yellow: "#ebcb8b",
|
||||||
|
blue: "#81a1c1",
|
||||||
|
magenta: "#b48ead",
|
||||||
|
cyan: "#88c0d0",
|
||||||
|
white: "#e5e9f0",
|
||||||
|
brightBlack: "#4c566a",
|
||||||
|
brightRed: "#bf616a",
|
||||||
|
brightGreen: "#a3be8c",
|
||||||
|
brightYellow: "#ebcb8b",
|
||||||
|
brightBlue: "#81a1c1",
|
||||||
|
brightMagenta: "#b48ead",
|
||||||
|
brightCyan: "#8fbcbb",
|
||||||
|
brightWhite: "#eceff4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tokyo-night": {
|
||||||
|
header: "#16161e",
|
||||||
|
border: "#292e42",
|
||||||
|
xterm: {
|
||||||
|
background: "#1a1b26",
|
||||||
|
foreground: "#c0caf5",
|
||||||
|
cursor: "#c0caf5",
|
||||||
|
cursorAccent: "#1a1b26",
|
||||||
|
selectionBackground: "#28345780",
|
||||||
|
black: "#15161e",
|
||||||
|
red: "#f7768e",
|
||||||
|
green: "#9ece6a",
|
||||||
|
yellow: "#e0af68",
|
||||||
|
blue: "#7aa2f7",
|
||||||
|
magenta: "#bb9af7",
|
||||||
|
cyan: "#7dcfff",
|
||||||
|
white: "#a9b1d6",
|
||||||
|
brightBlack: "#414868",
|
||||||
|
brightRed: "#f7768e",
|
||||||
|
brightGreen: "#9ece6a",
|
||||||
|
brightYellow: "#e0af68",
|
||||||
|
brightBlue: "#7aa2f7",
|
||||||
|
brightMagenta: "#bb9af7",
|
||||||
|
brightCyan: "#7dcfff",
|
||||||
|
brightWhite: "#c0caf5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
monokai: {
|
||||||
|
header: "#1e1f1c",
|
||||||
|
border: "#49483e",
|
||||||
|
xterm: {
|
||||||
|
background: "#272822",
|
||||||
|
foreground: "#f8f8f2",
|
||||||
|
cursor: "#f8f8f2",
|
||||||
|
cursorAccent: "#272822",
|
||||||
|
selectionBackground: "#49483e80",
|
||||||
|
black: "#272822",
|
||||||
|
red: "#f92672",
|
||||||
|
green: "#a6e22e",
|
||||||
|
yellow: "#e6db74",
|
||||||
|
blue: "#66d9ef",
|
||||||
|
magenta: "#ae81ff",
|
||||||
|
cyan: "#a1efe4",
|
||||||
|
white: "#f8f8f2",
|
||||||
|
brightBlack: "#75715e",
|
||||||
|
brightRed: "#f92672",
|
||||||
|
brightGreen: "#a6e22e",
|
||||||
|
brightYellow: "#f4bf75",
|
||||||
|
brightBlue: "#66d9ef",
|
||||||
|
brightMagenta: "#ae81ff",
|
||||||
|
brightCyan: "#a1efe4",
|
||||||
|
brightWhite: "#f9f8f5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"rose-pine": {
|
||||||
|
header: "#1f1d2e",
|
||||||
|
border: "#26233a",
|
||||||
|
xterm: {
|
||||||
|
background: "#191724",
|
||||||
|
foreground: "#e0def4",
|
||||||
|
cursor: "#e0def4",
|
||||||
|
cursorAccent: "#191724",
|
||||||
|
selectionBackground: "#403d5280",
|
||||||
|
black: "#26233a",
|
||||||
|
red: "#eb6f92",
|
||||||
|
green: "#31748f",
|
||||||
|
yellow: "#f6c177",
|
||||||
|
blue: "#9ccfd8",
|
||||||
|
magenta: "#c4a7e7",
|
||||||
|
cyan: "#ebbcba",
|
||||||
|
white: "#e0def4",
|
||||||
|
brightBlack: "#6e6a86",
|
||||||
|
brightRed: "#eb6f92",
|
||||||
|
brightGreen: "#31748f",
|
||||||
|
brightYellow: "#f6c177",
|
||||||
|
brightBlue: "#9ccfd8",
|
||||||
|
brightMagenta: "#c4a7e7",
|
||||||
|
brightCyan: "#ebbcba",
|
||||||
|
brightWhite: "#e0def4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
everforest: {
|
||||||
|
header: "#232a2e",
|
||||||
|
border: "#475258",
|
||||||
|
xterm: {
|
||||||
|
background: "#2d353b",
|
||||||
|
foreground: "#d3c6aa",
|
||||||
|
cursor: "#d3c6aa",
|
||||||
|
cursorAccent: "#2d353b",
|
||||||
|
selectionBackground: "#47525880",
|
||||||
|
black: "#475258",
|
||||||
|
red: "#e67e80",
|
||||||
|
green: "#a7c080",
|
||||||
|
yellow: "#dbbc7f",
|
||||||
|
blue: "#7fbbb3",
|
||||||
|
magenta: "#d699b6",
|
||||||
|
cyan: "#83c092",
|
||||||
|
white: "#d3c6aa",
|
||||||
|
brightBlack: "#859289",
|
||||||
|
brightRed: "#e67e80",
|
||||||
|
brightGreen: "#a7c080",
|
||||||
|
brightYellow: "#dbbc7f",
|
||||||
|
brightBlue: "#7fbbb3",
|
||||||
|
brightMagenta: "#d699b6",
|
||||||
|
brightCyan: "#83c092",
|
||||||
|
brightWhite: "#d3c6aa",
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Project {
|
interface Project {
|
||||||
@@ -199,7 +417,7 @@ const term = new Terminal({
|
|||||||
fontFamily: '"JetBrains Mono", Menlo, monospace',
|
fontFamily: '"JetBrains Mono", Menlo, monospace',
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeightBold: "600",
|
fontWeightBold: "600",
|
||||||
lineHeight: 1.25,
|
lineHeight: 1.0,
|
||||||
letterSpacing: 0,
|
letterSpacing: 0,
|
||||||
cursorBlink: true,
|
cursorBlink: true,
|
||||||
cursorStyle: "bar",
|
cursorStyle: "bar",
|
||||||
@@ -220,8 +438,10 @@ term.attachCustomKeyEventHandler((e) => {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Font muss geladen sein, bevor WebGL den Glyphen-Atlas aufbaut.
|
// Font muss geladen sein, bevor WebGL den Glyphen-Atlas aufbaut —
|
||||||
|
// beide verwendeten Gewichte (400 normal, 600 bold).
|
||||||
await document.fonts.load('13px "JetBrains Mono"');
|
await document.fonts.load('13px "JetBrains Mono"');
|
||||||
|
await document.fonts.load('600 13px "JetBrains Mono"');
|
||||||
term.open(document.getElementById("term")!);
|
term.open(document.getElementById("term")!);
|
||||||
// Reihenfolge laut Addon-Doku: Ligaturen vor WebGL aktivieren.
|
// Reihenfolge laut Addon-Doku: Ligaturen vor WebGL aktivieren.
|
||||||
term.loadAddon(new LigaturesAddon());
|
term.loadAddon(new LigaturesAddon());
|
||||||
|
|||||||