Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { FitAddon } from '@xterm/addon-fit';
import { xtermAppearanceAdapter } from '@/infrastructure/appearance/adapters/XtermAppearanceAdapter';
import { registerTerminalActions, unregisterTerminalActions } from '@/tools/terminal/services/TerminalActionManager';
import {
TERMINAL_OUTPUT_FONT_FAMILY, TERMINAL_OUTPUT_FONT_SIZE, TERMINAL_OUTPUT_FONT_WEIGHT,
readTerminalOutputFontFamily, TERMINAL_OUTPUT_FONT_SIZE, TERMINAL_OUTPUT_FONT_WEIGHT,
TERMINAL_OUTPUT_FONT_WEIGHT_BOLD, TERMINAL_OUTPUT_LINE_HEIGHT,
} from '@/tools/terminal/components/terminalOutputPresentation';
import type { TerminalProjection } from './backgroundTerminalReplay';
Expand All @@ -26,7 +26,7 @@ export default function BackgroundTerminalProjection({ projection }: {
const element = host.current!;
const terminal = new Terminal({
disableStdin: true, cursorBlink: false, cursorInactiveStyle: 'none',
fontFamily: TERMINAL_OUTPUT_FONT_FAMILY, fontSize: TERMINAL_OUTPUT_FONT_SIZE,
fontFamily: readTerminalOutputFontFamily(), fontSize: TERMINAL_OUTPUT_FONT_SIZE,
fontWeight: TERMINAL_OUTPUT_FONT_WEIGHT, fontWeightBold: TERMINAL_OUTPUT_FONT_WEIGHT_BOLD,
lineHeight: TERMINAL_OUTPUT_LINE_HEIGHT, scrollback: 5000, convertEol: true,
theme: xtermAppearanceAdapter.getColors('output'),
Expand Down
2 changes: 2 additions & 0 deletions src/web-ui/src/font-profiles/harmony-bundled.css
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
}

:where([data-openbitfun-design-system-root]):lang(zh-CN) {
/* Keep Latin code monospaced and use the same Chinese face as body text. */
--openbitfun-font-family-mono: "JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, "Cascadia Mono", "Cascadia Code", Consolas, "Liberation Mono", "Courier New", "OpenBitFun HarmonyOS Sans SC", "OpenBitFun HarmonyOS Sans", "Microsoft YaHei UI", monospace;
--openbitfun-font-family-sans: "OpenBitFun HarmonyOS Sans SC", "OpenBitFun HarmonyOS Sans", system-ui, "Microsoft YaHei UI", sans-serif;
--openbitfun-font-family-control: "OpenBitFun HarmonyOS Sans SC", "OpenBitFun HarmonyOS Sans", system-ui, "Microsoft YaHei UI", sans-serif;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@ import { createRoot, type Root } from 'react-dom/client';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';

import { TerminalOutputFallback } from './LazyTerminalOutputRenderer';
import { readTerminalOutputFontFamily } from './terminalOutputPresentation';
import { getTypographyTokenValue } from '@/infrastructure/design-system/typographyRuntime';

it('resolves the active output font at use time rather than module import time', () => {
const style = document.documentElement.style;
const property = '--openbitfun-font-family-mono';
const previous = style.getPropertyValue(property);
try {
const family = '"Fira Code", "OpenBitFun HarmonyOS Sans SC", monospace';
style.setProperty(property, family);
expect(readTerminalOutputFontFamily()).toBe(family);
style.removeProperty(property);
expect(readTerminalOutputFontFamily()).toBe(getTypographyTokenValue('font.family.mono'));
} finally {
if (previous) style.setProperty(property, previous);
else style.removeProperty(property);
}
});

describe('TerminalOutputFallback', () => {
let container: HTMLDivElement;
Expand Down
4 changes: 2 additions & 2 deletions src/web-ui/src/tools/terminal/components/Terminal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { sendDebugProbe } from '@/shared/utils/debugProbe';
import { nowMs } from '@/shared/utils/timing';
import {
getTypographyTokenNumber,
getTypographyTokenValue,
readActiveTypographyTokenValue,
readActiveTypographyTokenPx,
} from '@/infrastructure/design-system/typographyRuntime';
import { fontPreferenceService } from '@/infrastructure/font-preference';
Expand Down Expand Up @@ -188,7 +188,6 @@ function readTerminalFontSize(): number {
}

const DEFAULT_OPTIONS: TerminalOptions = {
fontFamily: getTypographyTokenValue('font.family.mono'),
lineHeight: getTypographyTokenNumber('lineHeight.tight'),
minimumContrastRatio: DEFAULT_XTERM_MINIMUM_CONTRAST_RATIO,
cursorStyle: 'block',
Expand Down Expand Up @@ -251,6 +250,7 @@ const Terminal = forwardRef<TerminalRef, TerminalProps>(({
// the black-background flash that occurs when a light theme is active.
const mergedOptions = {
...DEFAULT_OPTIONS,
fontFamily: readActiveTypographyTokenValue('font.family.mono'),
fontSize,
...options,
theme: getInitialXtermColors(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
calculateTerminalOutputHeight,
getEstimatedTerminalOutputRowHeight,
prepareReadOnlyTerminalOutput,
TERMINAL_OUTPUT_FONT_FAMILY,
readTerminalOutputFontFamily,
TERMINAL_OUTPUT_FONT_SIZE,
TERMINAL_OUTPUT_FONT_WEIGHT,
TERMINAL_OUTPUT_FONT_WEIGHT_BOLD,
Expand Down Expand Up @@ -122,7 +122,7 @@ const TerminalOutputRendererComponent = forwardRef<TerminalOutputRendererHandle,
cursorStyle: 'bar',
cursorInactiveStyle: 'none',
fontSize: TERMINAL_OUTPUT_FONT_SIZE,
fontFamily: TERMINAL_OUTPUT_FONT_FAMILY,
fontFamily: readTerminalOutputFontFamily(),
fontWeight: TERMINAL_OUTPUT_FONT_WEIGHT,
fontWeightBold: TERMINAL_OUTPUT_FONT_WEIGHT_BOLD,
lineHeight: TERMINAL_OUTPUT_LINE_HEIGHT,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {
getTypographyTokenNumber,
getTypographyTokenPx,
getTypographyTokenValue,
readActiveTypographyTokenValue,
} from '@/infrastructure/design-system/typographyRuntime';

export const TERMINAL_OUTPUT_FONT_SIZE = getTypographyTokenPx('font.size.xs');
export const TERMINAL_OUTPUT_LINE_HEIGHT = getTypographyTokenNumber('lineHeight.ui');
export const TERMINAL_OUTPUT_FONT_FAMILY = getTypographyTokenValue('font.family.mono');
export function readTerminalOutputFontFamily(): string {
return readActiveTypographyTokenValue('font.family.mono');
}
export const TERMINAL_OUTPUT_FONT_WEIGHT = getTypographyTokenNumber('font.weight.regular');
export const TERMINAL_OUTPUT_FONT_WEIGHT_BOLD = getTypographyTokenNumber('font.weight.bold');

Expand All @@ -16,14 +18,16 @@ const DEFAULT_OUTPUT_ROW_HEIGHT = Math.ceil(

let cachedDevicePixelRatio = 0;
let cachedRowHeight = 0;
let cachedFontFamily = '';

export function getEstimatedTerminalOutputRowHeight(): number {
if (typeof window === 'undefined') {
return DEFAULT_OUTPUT_ROW_HEIGHT;
}

const devicePixelRatio = window.devicePixelRatio || 1;
if (cachedRowHeight > 0 && cachedDevicePixelRatio === devicePixelRatio) {
const fontFamily = readTerminalOutputFontFamily();
if (cachedRowHeight > 0 && cachedDevicePixelRatio === devicePixelRatio && cachedFontFamily === fontFamily) {
return cachedRowHeight;
}

Expand All @@ -37,7 +41,7 @@ export function getEstimatedTerminalOutputRowHeight(): number {
return DEFAULT_OUTPUT_ROW_HEIGHT;
}

context.font = `${TERMINAL_OUTPUT_FONT_SIZE}px ${TERMINAL_OUTPUT_FONT_FAMILY}`;
context.font = `${TERMINAL_OUTPUT_FONT_SIZE}px ${fontFamily}`;
const metrics = context.measureText('W');
const fontHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
if (!Number.isFinite(fontHeight) || fontHeight <= 0) {
Expand All @@ -47,6 +51,7 @@ export function getEstimatedTerminalOutputRowHeight(): number {
const deviceCharHeight = Math.ceil(fontHeight * devicePixelRatio);
const deviceCellHeight = Math.floor(deviceCharHeight * TERMINAL_OUTPUT_LINE_HEIGHT);
cachedDevicePixelRatio = devicePixelRatio;
cachedFontFamily = fontFamily;
cachedRowHeight = deviceCellHeight / devicePixelRatio;
return cachedRowHeight;
} catch {
Expand Down
Loading