- settings: backgroundImage/backgroundImageOpacity (10..100, default 60) - main: otimg:// protocol serves only the configured background file (path-allowlisted, 403 otherwise); dev http origin cannot load file: - TerminalView: allowTransparency + transparent theme background while an image is set; .term-bg-image layer behind the xterm surface - terminal.css: .has-bg-image keeps .xterm-viewport transparent — the old chrome-bg pin covered the image layer (root cause of image not showing) - ThemeSettingsTab: image picker + opacity slider - ThemeEditor: duplicate-name hint now covers builtin names too; seed colors normalized to #rrggbb - settingsStore: sanitize theme colors, reject non-hex values
147 lines
5.7 KiB
TypeScript
147 lines
5.7 KiB
TypeScript
import type { TerminalTheme } from './theme'
|
|
import type { Language } from './i18n'
|
|
|
|
/** One terminal keyword-highlight rule (regex → ANSI color injection). */
|
|
export interface HighlightRule {
|
|
id: string
|
|
/** regex source; compiled with 'g' flag at use site */
|
|
pattern: string
|
|
enabled: boolean
|
|
/** 1..100, lower runs first and claims its spans first */
|
|
priority: number
|
|
/** truecolor hex (#rrggbb); fg required, bg optional */
|
|
color: { fg: string; bg?: string }
|
|
note?: string
|
|
/** part of the factory preset set (restored by 恢复默认) */
|
|
builtin?: boolean
|
|
}
|
|
|
|
export interface TerminalSettings {
|
|
fontFamily: string
|
|
fontSize: number
|
|
/** 100..900 */
|
|
fontWeight: number
|
|
/** 100..900 */
|
|
boldFontWeight: number
|
|
letterSpacing: number
|
|
lineHeight: number
|
|
scrollback: number
|
|
cursorBlink: boolean
|
|
cursorStyle: 'bar' | 'block' | 'underline'
|
|
cursorInactiveStyle: 'outline' | 'block' | 'bar' | 'underline' | 'none'
|
|
themeId: string
|
|
rendererMode: 'auto' | 'webgl' | 'dom'
|
|
autoWrap: boolean
|
|
copyOnSelect: boolean
|
|
/** confirm before pasting multi-line / suspicious text */
|
|
pasteRiskConfirm: boolean
|
|
/** inline command suggestion popup while typing (history + library) */
|
|
suggestEnabled: boolean
|
|
/** record executed commands into the history panel */
|
|
historyEnabled: boolean
|
|
/** max entries kept in command history */
|
|
historyLimit: number
|
|
/** terminal toolbar: session-log record button */
|
|
showRecButton: boolean
|
|
/** terminal toolbar: open logs folder button */
|
|
showOpenLogsButton: boolean
|
|
/** terminal toolbar: open working-directory button (local sessions only) */
|
|
showOpenCwdButton: boolean
|
|
/** accent color for the active tab outline, rail indicator and SSH badges */
|
|
tabAccentColor: string
|
|
/** absolute path to an image rendered behind the terminal; '' = none */
|
|
backgroundImage: string
|
|
/** background image layer opacity, 10..100 (%) */
|
|
backgroundImageOpacity: number
|
|
}
|
|
|
|
export interface SystemSettings {
|
|
/** register the app to launch at OS login */
|
|
launchAtLogin: boolean
|
|
/** hold a powerSaveBlocker so the OS never auto-suspends while running */
|
|
preventSleep: boolean
|
|
/** Electron accelerator that toggles window visibility; '' = disabled (M6) */
|
|
globalShowHide?: string
|
|
/** close-button behavior: prompt every time / hide to tray / quit directly */
|
|
closeAction?: 'ask' | 'tray' | 'exit'
|
|
/** check for updates shortly after startup (manual check always available) */
|
|
autoCheckUpdate?: boolean
|
|
/**
|
|
* Restore the previous layout and each pane's working directory on launch
|
|
* (see the session snapshot). On by default — that is the point of it.
|
|
*/
|
|
restoreSession?: boolean
|
|
/**
|
|
* Let the shell announce its cwd over OSC 7 (shell integration). Exact, but
|
|
* it wraps the user's prompt, so it is opt-in; without it the app falls back
|
|
* to parsing typed `cd` commands.
|
|
*/
|
|
shellIntegration?: boolean
|
|
/** interface language (see @shared/i18n); missing = 简体中文 */
|
|
language?: Language
|
|
}
|
|
|
|
export interface AppSettings {
|
|
terminal: TerminalSettings
|
|
/** user-created themes; builtin themes are immutable and live in shared/theme.ts */
|
|
customThemes: TerminalTheme[]
|
|
/** terminal keyword highlight rules, applied at write time in priority order */
|
|
highlightRules: HighlightRule[]
|
|
system: SystemSettings
|
|
}
|
|
|
|
const RULE = (
|
|
id: string,
|
|
pattern: string,
|
|
priority: number,
|
|
fg: string,
|
|
note: string,
|
|
bg?: string
|
|
): HighlightRule => ({ id, pattern, enabled: true, priority, color: { fg, bg }, note, builtin: true })
|
|
|
|
export const DEFAULT_HIGHLIGHT_RULES: HighlightRule[] = [
|
|
RULE('perm', '^[-dlbcps][rwxstST-]{9}', 1, '#3fb950', 'Linux 权限与用户'),
|
|
RULE('path', '(?:^|[\\s:=])(?:/[A-Za-z0-9_.\\-/@+]+|~[A-Za-z0-9_.\\-/]*)', 2, '#58a6ff', 'Linux 文件路径'),
|
|
RULE('shellkw', '\\b(if|then|else|elif|fi|for|while|do|done|case|esac|function|return|break|continue|export|source)\\b', 3, '#d2a8ff', 'Shell 关键字与流程'),
|
|
RULE('okstate', '\\b(SUCCESS|PASS|OK|DONE|PASSED)\\b', 5, '#3fb950', '成功状态'),
|
|
RULE('badstate', '\\b(FAILED|ERROR|FAIL|FATAL|WARN|WARNING|DENIED)\\b', 6, '#f85149', '错误/警告状态'),
|
|
RULE('quoted', '"[^"\\n]*"|\'[^\'\\n]*\'', 8, '#e3b341', '字符串与引号'),
|
|
RULE('envvar', '\\$\\{?[A-Za-z_][A-Za-z0-9_]*\\}?', 10, '#79c0ff', '环境变量与参数'),
|
|
RULE('ipv4', '\\b(?:\\d{1,3}\\.){3}\\d{1,3}(?::\\d{1,5})?\\b', 15, '#58a6ff', '网络与 IP 地址'),
|
|
RULE('datetime', '\\b\\d{4}[-/]\\d{1,2}[-/]\\d{1,2}(?:[ T]\\d{1,2}:\\d{2}(?::\\d{2})?)?\\b|\\b\\d{1,2}:\\d{2}(?::\\d{2})?\\b', 20, '#bc8cff', '时间与日期'),
|
|
RULE('numbers', '\\b\\d+(?:\\.\\d+)?(?:%)?\\b', 25, '#f2cc60', '数字与计数'),
|
|
RULE('url', 'https?://[^\\s]+|ftp://[^\\s]+|www\\.[A-Za-z0-9-]+\\.[A-Za-z]{2,}(?::\\d+)?(?:/[^\\s]*)?', 30, '#58a6ff', '网址链接')
|
|
]
|
|
|
|
export const DEFAULT_SETTINGS: AppSettings = {
|
|
terminal: {
|
|
fontFamily: "'Cascadia Mono', Consolas, 'JetBrains Mono', 'Courier New', monospace",
|
|
fontSize: 14,
|
|
fontWeight: 400,
|
|
boldFontWeight: 700,
|
|
letterSpacing: 0,
|
|
lineHeight: 1,
|
|
scrollback: 5000,
|
|
cursorBlink: true,
|
|
cursorStyle: 'block',
|
|
cursorInactiveStyle: 'outline',
|
|
themeId: 'material-dark',
|
|
rendererMode: 'auto',
|
|
autoWrap: true,
|
|
copyOnSelect: false,
|
|
pasteRiskConfirm: true,
|
|
suggestEnabled: false,
|
|
historyEnabled: false,
|
|
historyLimit: 100,
|
|
showRecButton: false,
|
|
showOpenLogsButton: false,
|
|
showOpenCwdButton: true,
|
|
tabAccentColor: '#3fb950',
|
|
backgroundImage: '',
|
|
backgroundImageOpacity: 60
|
|
},
|
|
customThemes: [],
|
|
highlightRules: DEFAULT_HIGHLIGHT_RULES,
|
|
system: { launchAtLogin: false, preventSleep: false, globalShowHide: '', closeAction: 'tray', autoCheckUpdate: true, restoreSession: true, shellIntegration: false, language: 'zh-CN' }
|
|
}
|