[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,190 @@
/**
* UI Fonts Configuration
* Includes general-purpose fonts suitable for application interface
*/
export interface UIFont {
id: string;
name: string;
family: string;
}
export type UiPlatform = 'darwin' | 'win32' | 'linux';
/**
* Bundled Noto Color Emoji subset (regional indicators U+1F1E61F1FF).
* Windows system fonts omit flag glyphs and show ISO country codes instead —
* see #1589, #1604.
*/
export const WINDOWS_FLAG_EMOJI_FONT = '"Noto Color Emoji Flags"';
/**
* Windows bundles UI fonts via @font-face. Their regional-indicator glyphs
* render as separate letters instead of composed flag emoji unless a color
* emoji font is consulted first — see #1589.
*/
export const WINDOWS_UI_EMOJI_FONTS = WINDOWS_FLAG_EMOJI_FONT;
/**
* Fallback fonts for CJK (Chinese, Japanese, Korean) support
*/
const CJK_FALLBACK_FONTS = [
'"PingFang SC"',
'"Hiragino Sans GB"',
'"Microsoft YaHei UI"',
'"Microsoft YaHei"',
'"Noto Sans CJK SC"',
'"Source Han Sans SC"',
'sans-serif',
];
const CJK_FALLBACK_STACK = CJK_FALLBACK_FONTS.join(', ');
export const withUiCjkFallback = (family: string) => {
const trimmed = family.trim();
// Avoid double-appending if a custom stack already includes one of these fonts.
if (CJK_FALLBACK_FONTS.some((f) => trimmed.includes(f.replace(/"/g, '')))) {
return trimmed;
}
return `${trimmed}, ${CJK_FALLBACK_STACK}`;
};
export function detectUiPlatform(userAgent: string): UiPlatform {
if (/Win/i.test(userAgent)) return 'win32';
if (/Mac|iPod|iPhone|iPad/i.test(userAgent)) return 'darwin';
return 'linux';
}
export function withWindowsEmojiFallback(
family: string,
platform: UiPlatform = typeof navigator !== 'undefined'
? detectUiPlatform(navigator.userAgent)
: 'linux',
): string {
if (platform !== 'win32') return family;
const trimmed = family.trim();
if (trimmed.includes('Noto Color Emoji Flags') || trimmed.includes('Segoe UI Emoji')) {
return trimmed;
}
return `${WINDOWS_UI_EMOJI_FONTS}, ${trimmed}, "Segoe UI Emoji", "Segoe UI Symbol"`;
}
const BASE_UI_FONTS: UIFont[] = [
{
id: 'mona-sans',
name: 'Mona Sans',
family: '"Mona Sans", system-ui',
},
{
id: 'space-grotesk',
name: 'Space Grotesk',
family: '"Space Grotesk", system-ui',
},
{
id: 'system-ui',
name: 'System UI',
family: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial',
},
{
id: 'inter',
name: 'Inter',
family: '"Inter", system-ui',
},
{
id: 'roboto',
name: 'Roboto',
family: '"Roboto", system-ui',
},
{
id: 'open-sans',
name: 'Open Sans',
family: '"Open Sans", system-ui',
},
{
id: 'lato',
name: 'Lato',
family: '"Lato", system-ui',
},
{
id: 'nunito',
name: 'Nunito',
family: '"Nunito", system-ui',
},
{
id: 'poppins',
name: 'Poppins',
family: '"Poppins", system-ui',
},
{
id: 'source-sans-pro',
name: 'Source Sans Pro',
family: '"Source Sans Pro", system-ui',
},
{
id: 'ubuntu',
name: 'Ubuntu',
family: '"Ubuntu", system-ui',
},
{
id: 'noto-sans',
name: 'Noto Sans',
family: '"Noto Sans", system-ui',
},
{
id: 'work-sans',
name: 'Work Sans',
family: '"Work Sans", system-ui',
},
{
id: 'dm-sans',
name: 'DM Sans',
family: '"DM Sans", system-ui',
},
{
id: 'montserrat',
name: 'Montserrat',
family: '"Montserrat", system-ui',
},
{
id: 'raleway',
name: 'Raleway',
family: '"Raleway", system-ui',
},
{
id: 'quicksand',
name: 'Quicksand',
family: '"Quicksand", system-ui',
},
{
id: 'ibm-plex-sans',
name: 'IBM Plex Sans',
family: '"IBM Plex Sans", system-ui',
},
{
id: 'outfit',
name: 'Outfit',
family: '"Outfit", system-ui',
},
{
id: 'plus-jakarta-sans',
name: 'Plus Jakarta Sans',
family: '"Plus Jakarta Sans", system-ui',
},
{
id: 'segoe-ui',
name: 'Segoe UI',
family: '"Segoe UI", system-ui',
},
{
id: 'sf-pro',
name: 'SF Pro',
family: '-apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui',
},
];
export const UI_FONTS: UIFont[] = BASE_UI_FONTS.map((font) => ({
...font,
family: withUiCjkFallback(font.family),
}));
export const DEFAULT_UI_FONT_ID = 'mona-sans';