mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
feat(terminal): add Nerd Font support for Powerline themes (#29)
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
"@tanstack/react-query": "^5.90.12",
|
||||
"@tanstack/react-query-devtools": "^5.91.1",
|
||||
"@tanstack/react-router": "^1.143.6",
|
||||
"@xterm/addon-canvas": "^0.7.0",
|
||||
"@xterm/addon-fit": "^0.11.0",
|
||||
"@xterm/addon-web-links": "^0.12.0",
|
||||
"@xterm/xterm": "^6.0.0",
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Terminal } from '@xterm/xterm'
|
||||
import { FitAddon } from '@xterm/addon-fit'
|
||||
import { WebLinksAddon } from '@xterm/addon-web-links'
|
||||
import { CanvasAddon } from '@xterm/addon-canvas'
|
||||
import '@xterm/xterm/css/xterm.css'
|
||||
import { createFontProvider, type ITerminalFontProvider } from '@/lib/terminalFont'
|
||||
|
||||
function resolveThemeColors(): { background: string; foreground: string; selectionBackground: string } {
|
||||
const styles = getComputedStyle(document.documentElement)
|
||||
@@ -20,6 +22,12 @@ export function TerminalView(props: {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null)
|
||||
const onMountRef = useRef(props.onMount)
|
||||
const onResizeRef = useRef(props.onResize)
|
||||
const [fontProvider, setFontProvider] = useState<ITerminalFontProvider | null>(null)
|
||||
|
||||
// Initialize font provider
|
||||
useEffect(() => {
|
||||
createFontProvider('default').then(setFontProvider)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
onMountRef.current = props.onMount
|
||||
@@ -31,14 +39,14 @@ export function TerminalView(props: {
|
||||
|
||||
useEffect(() => {
|
||||
const container = containerRef.current
|
||||
if (!container) {
|
||||
if (!container || !fontProvider) {
|
||||
return
|
||||
}
|
||||
|
||||
const { background, foreground, selectionBackground } = resolveThemeColors()
|
||||
const terminal = new Terminal({
|
||||
cursorBlink: true,
|
||||
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
|
||||
fontFamily: fontProvider.getFontFamily(),
|
||||
fontSize: 13,
|
||||
theme: {
|
||||
background,
|
||||
@@ -46,13 +54,16 @@ export function TerminalView(props: {
|
||||
cursor: foreground,
|
||||
selectionBackground
|
||||
},
|
||||
convertEol: true
|
||||
convertEol: true,
|
||||
customGlyphs: true
|
||||
})
|
||||
|
||||
const fitAddon = new FitAddon()
|
||||
const webLinksAddon = new WebLinksAddon()
|
||||
const canvasAddon = new CanvasAddon()
|
||||
terminal.loadAddon(fitAddon)
|
||||
terminal.loadAddon(webLinksAddon)
|
||||
terminal.loadAddon(canvasAddon)
|
||||
terminal.open(container)
|
||||
|
||||
const resizeTerminal = () => {
|
||||
@@ -72,7 +83,7 @@ export function TerminalView(props: {
|
||||
observer.disconnect()
|
||||
terminal.dispose()
|
||||
}
|
||||
}, [])
|
||||
}, [fontProvider])
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Terminal Font Provider
|
||||
*
|
||||
* Provides font configuration for terminal rendering with Nerd Font support.
|
||||
* Follows SOLID principles for easy extensibility.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Terminal font provider interface
|
||||
*/
|
||||
export interface ITerminalFontProvider {
|
||||
/**
|
||||
* Get CSS fontFamily string for terminal
|
||||
*/
|
||||
getFontFamily(): string
|
||||
|
||||
/**
|
||||
* Optional async initialization (for future smart detection)
|
||||
*/
|
||||
initialize?(): Promise<void>
|
||||
}
|
||||
|
||||
/**
|
||||
* Default font provider with hardcoded Nerd Font fallback list
|
||||
*
|
||||
* Includes common Nerd Fonts and system fallbacks.
|
||||
* Zero runtime overhead - uses browser's native font fallback mechanism.
|
||||
*/
|
||||
export class DefaultFontProvider implements ITerminalFontProvider {
|
||||
private static readonly NERD_FONTS = [
|
||||
// Common Nerd Fonts (prioritized by popularity)
|
||||
'JetBrainsMono Nerd Font',
|
||||
'JetBrainsMonoNerdFont',
|
||||
'FiraCode Nerd Font',
|
||||
'FiraCodeNerdFont',
|
||||
'Hack Nerd Font',
|
||||
'HackNerdFont',
|
||||
'MapleMono NF',
|
||||
'Maple Mono NF',
|
||||
'Iosevka Nerd Font',
|
||||
'IosevkaNerdFont',
|
||||
'CaskaydiaCove Nerd Font',
|
||||
'MesloLGS Nerd Font',
|
||||
'SourceCodePro Nerd Font',
|
||||
'UbuntuMono Nerd Font'
|
||||
]
|
||||
|
||||
private static readonly SYSTEM_FALLBACKS = [
|
||||
'ui-monospace',
|
||||
'SFMono-Regular',
|
||||
'Menlo',
|
||||
'Monaco',
|
||||
'Consolas',
|
||||
'"Liberation Mono"',
|
||||
'"Courier New"',
|
||||
'monospace'
|
||||
]
|
||||
|
||||
getFontFamily(): string {
|
||||
return [
|
||||
...DefaultFontProvider.NERD_FONTS.map(f => `"${f}"`),
|
||||
...DefaultFontProvider.SYSTEM_FALLBACKS
|
||||
].join(', ')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory function to create font provider
|
||||
*
|
||||
* @param mode - Provider mode (currently only 'default', extensible for future)
|
||||
* @returns Font provider instance
|
||||
*/
|
||||
export async function createFontProvider(
|
||||
mode: 'default' = 'default'
|
||||
): Promise<ITerminalFontProvider> {
|
||||
switch (mode) {
|
||||
case 'default':
|
||||
default:
|
||||
return new DefaultFontProvider()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user