@@ -38,7 +38,7 @@ export function getRows(contents: string, cols: number): number {
3838}
3939
4040// なぜか term.clear(); が効かない場合がある... これは効く
41- export function clearTerminal ( term : Terminal ) {
41+ export function clearTerminal ( term : Terminal ) {
4242 // term.clear();
4343 term . write ( "\x1b[3J\x1b[2J\x1b[1;1H" ) ;
4444}
@@ -50,6 +50,7 @@ interface TerminalProps {
5050export function useTerminal ( props : TerminalProps ) {
5151 const terminalRef = useRef < HTMLDivElement > ( null ! ) ;
5252 const terminalInstanceRef = useRef < Terminal | null > ( null ) ;
53+ const fitAddonRef = useRef < FitAddon | null > ( null ) ;
5354 const [ termReady , setTermReady ] = useState < boolean > ( false ) ;
5455
5556 const getRowsRef = useRef < ( cols : number ) => number > ( undefined ) ;
@@ -59,69 +60,94 @@ export function useTerminal(props: TerminalProps) {
5960
6061 // ターミナルの初期化処理
6162 useEffect ( ( ) => {
62- const fromCSS = ( varName : string ) =>
63- window . getComputedStyle ( document . body ) . getPropertyValue ( varName ) ;
64- // "--color-" + color_name のように文字列を分割するとTailwindCSSが認識せずCSSの値として出力されない場合があるので注意
65- const term = new Terminal ( {
66- cursorBlink : true ,
67- convertEol : true ,
68- cursorStyle : "bar" ,
69- cursorInactiveStyle : "none" ,
70- fontSize : 14 ,
71- lineHeight : 1.4 ,
72- letterSpacing : 0 ,
73- fontFamily : "Inconsolata Variable" ,
74- theme : {
75- // DaisyUIの変数を使用してテーマを設定している
76- // TODO: ダークテーマ/ライトテーマを切り替えたときに再設定する?
77- background : fromCSS ( "--color-base-300" ) ,
78- foreground : fromCSS ( "--color-base-content" ) ,
79- cursor : fromCSS ( "--color-base-content" ) ,
80- selectionBackground : fromCSS ( "--color-primary" ) ,
81- selectionForeground : fromCSS ( "--color-primary-content" ) ,
82- black : fromCSS ( "--color-black" ) ,
83- brightBlack : fromCSS ( "--color-neutral-500" ) ,
84- red : fromCSS ( "--color-red-600" ) ,
85- brightRed : fromCSS ( "--color-red-400" ) ,
86- green : fromCSS ( "--color-green-600" ) ,
87- brightGreen : fromCSS ( "--color-green-400" ) ,
88- yellow : fromCSS ( "--color-yellow-700" ) ,
89- brightYellow : fromCSS ( "--color-yellow-400" ) ,
90- blue : fromCSS ( "--color-indigo-600" ) ,
91- brightBlue : fromCSS ( "--color-indigo-400" ) ,
92- magenta : fromCSS ( "--color-fuchsia-600" ) ,
93- brightMagenta : fromCSS ( "--color-fuchsia-400" ) ,
94- cyan : fromCSS ( "--color-cyan-600" ) ,
95- brightCyan : fromCSS ( "--color-cyan-400" ) ,
96- white : fromCSS ( "--color-base-100" ) ,
97- brightWhite : fromCSS ( "--color-white" ) ,
98- } ,
99- } ) ;
100- terminalInstanceRef . current = term ;
63+ const abortController = new AbortController ( ) ;
64+
65+ ( async ( ) => {
66+ // globals.cssでフォントを指定し読み込んでいるが、
67+ // それが読み込まれる前にterminalを初期化してしまうとバグる。
68+ // なのでここでフォントをfetchし成功するまでterminalの初期化は待つ
69+ try {
70+ await fetch (
71+ "https://cdn.jsdelivr.net/fontsource/fonts/inconsolata:vf@latest/latin-wght-normal.woff2" ,
72+ { signal : abortController . signal }
73+ ) ;
74+ } catch {
75+ // ignore
76+ }
10177
102- const fitAddon = new FitAddon ( ) ;
103- term . loadAddon ( fitAddon ) ;
104- // fitAddon.fit();
78+ if ( ! abortController . signal . aborted ) {
79+ const fromCSS = ( varName : string ) =>
80+ window . getComputedStyle ( document . body ) . getPropertyValue ( varName ) ;
81+ // "--color-" + color_name のように文字列を分割するとTailwindCSSが認識せずCSSの値として出力されない場合があるので注意
82+ const term = new Terminal ( {
83+ cursorBlink : true ,
84+ convertEol : true ,
85+ cursorStyle : "bar" ,
86+ cursorInactiveStyle : "none" ,
87+ fontSize : 14 ,
88+ lineHeight : 1.4 ,
89+ letterSpacing : 0 ,
90+ fontFamily : "Inconsolata Variable" ,
91+ theme : {
92+ // DaisyUIの変数を使用してテーマを設定している
93+ // TODO: ダークテーマ/ライトテーマを切り替えたときに再設定する?
94+ background : fromCSS ( "--color-base-300" ) ,
95+ foreground : fromCSS ( "--color-base-content" ) ,
96+ cursor : fromCSS ( "--color-base-content" ) ,
97+ selectionBackground : fromCSS ( "--color-primary" ) ,
98+ selectionForeground : fromCSS ( "--color-primary-content" ) ,
99+ black : fromCSS ( "--color-black" ) ,
100+ brightBlack : fromCSS ( "--color-neutral-500" ) ,
101+ red : fromCSS ( "--color-red-600" ) ,
102+ brightRed : fromCSS ( "--color-red-400" ) ,
103+ green : fromCSS ( "--color-green-600" ) ,
104+ brightGreen : fromCSS ( "--color-green-400" ) ,
105+ yellow : fromCSS ( "--color-yellow-700" ) ,
106+ brightYellow : fromCSS ( "--color-yellow-400" ) ,
107+ blue : fromCSS ( "--color-indigo-600" ) ,
108+ brightBlue : fromCSS ( "--color-indigo-400" ) ,
109+ magenta : fromCSS ( "--color-fuchsia-600" ) ,
110+ brightMagenta : fromCSS ( "--color-fuchsia-400" ) ,
111+ cyan : fromCSS ( "--color-cyan-600" ) ,
112+ brightCyan : fromCSS ( "--color-cyan-400" ) ,
113+ white : fromCSS ( "--color-base-100" ) ,
114+ brightWhite : fromCSS ( "--color-white" ) ,
115+ } ,
116+ } ) ;
117+ terminalInstanceRef . current = term ;
105118
106- term . open ( terminalRef . current ) ;
119+ fitAddonRef . current = new FitAddon ( ) ;
120+ term . loadAddon ( fitAddonRef . current ) ;
121+ // fitAddon.fit();
107122
108- setTermReady ( true ) ;
109- onReadyRef . current ?.( ) ;
123+ term . open ( terminalRef . current ) ;
124+
125+ setTermReady ( true ) ;
126+ onReadyRef . current ?.( ) ;
127+ }
128+ } ) ( ) ;
110129
111130 const observer = new ResizeObserver ( ( ) => {
112131 // fitAddon.fit();
113- const dims = fitAddon . proposeDimensions ( ) ;
132+ const dims = fitAddonRef . current ? .proposeDimensions ( ) ;
114133 if ( dims ) {
115134 const rows = Math . max ( 5 , getRowsRef . current ?.( dims . cols ) ?? 0 ) ;
116- term . resize ( dims . cols , rows ) ;
135+ terminalInstanceRef . current ? .resize ( dims . cols , rows ) ;
117136 }
118137 } ) ;
119138 observer . observe ( terminalRef . current ) ;
120139
121140 return ( ) => {
141+ abortController . abort ( "terminal component dismount" ) ;
122142 observer . disconnect ( ) ;
123- term . dispose ( ) ;
124- terminalInstanceRef . current = null ;
143+ if ( fitAddonRef . current ) {
144+ fitAddonRef . current . dispose ( ) ;
145+ fitAddonRef . current = null ;
146+ }
147+ if ( terminalInstanceRef . current ) {
148+ terminalInstanceRef . current . dispose ( ) ;
149+ terminalInstanceRef . current = null ;
150+ }
125151 } ;
126152 } , [ ] ) ;
127153
0 commit comments