import { createMemo, createSignal, onMount, Show, For } from "solid-js"; import { fetchFonts, fetchConfig, type FontInfo, type ServerConfig } from "./api"; import UploadSection from "./UploadSection"; const s = { wrap: { "max-width": "720px", margin: "0 auto", padding: "48px 24px", "font-family": "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif", color: "#1a1a1a", "line-height": "1.6", } as const, h1: { "font-size": "22px", "font-weight": 600, margin: "0 0 4px 0", } as const, desc: { "font-size": "14px", color: "#888", margin: "0 0 36px 0", } as const, label: { display: "block", "font-size": "13px", color: "#555", "margin-bottom": "6px", } as const, select: { width: "100%", padding: "8px 12px", "font-size": "15px", border: "1px solid #d9d9d9", "border-radius": "6px", outline: "none", "box-sizing": "border-box", } as const, textarea: { width: "100%", padding: "8px 12px", "font-size": "32px", border: "1px solid #d9d9d9", "border-radius": "6px", resize: "none", "box-sizing": "border-box", outline: "none", color: "#e74c3c", "line-height": "1.4", } as const, pre: { background: "#f7f7f8", padding: "16px", "border-radius": "6px", "font-size": "13px", "font-family": "'SF Mono', Menlo, Consolas, monospace", overflow: "auto", "white-space": "pre-wrap", "word-break": "break-all", "line-height": "1.5", margin: "0", } as const, section: { "margin-bottom": "28px", } as const, card: { padding: "16px", border: "1px solid #e8e8e8", "border-radius": "8px", "margin-bottom": "16px", } as const, btn: { padding: "6px 20px", "font-size": "14px", border: "1px solid #d9d9d9", "border-radius": "6px", cursor: "pointer", background: "#fff", color: "#333", } as const, input: { padding: "6px 12px", "font-size": "14px", border: "1px solid #d9d9d9", "border-radius": "6px", outline: "none", "box-sizing": "border-box", } as const, }; function App() { const [text, set_text] = createSignal("天地无极,乾坤借法"); const [fonts, set_fonts] = createSignal([]); const [selectedFont, set_selectedFont] = createSignal(""); const [serverConfig, set_serverConfig] = createSignal({ enableTempUpload: false, adminUploadEnabled: false, }); onMount(async () => { const [fontList, config] = await Promise.all([fetchFonts().catch(() => []), fetchConfig().catch(() => ({ enableTempUpload: false, adminUploadEnabled: false }))]); set_fonts(fontList); set_serverConfig(config); if (fontList.length > 0) { onFontChange(fontList[0].name); } }); const cssStyle = createMemo(() => { const font = selectedFont(); if (!font) return ""; return `@font-face { font-family: "CustomFont"; src: url("${location.origin}/api?font=${font}&text=${encodeURIComponent(text())}") format("truetype"); } .custom-font { color: red; font-family: "CustomFont"; }`; }); /** loadText loader 引用,字体或文本变化时增量加载 */ let textLoader: { update: (text: string) => void; dispose: () => void } | null = null; /** 文本变化时增量加载字体 */ const onTextChange = (value: string) => { set_text(value); if (!textLoader) return; textLoader.update(value); }; /** 根据文本行数动态计算 textarea 高度 */ const textareaRows = createMemo(() => { const lines = text().split("\n").length; return Math.max(2, Math.min(lines, 10)); }); /** 字体切换时为当前文本加载新字体 */ const onFontChange = (font: string) => { set_selectedFont(font); if (!font) return; if (textLoader) textLoader.dispose(); textLoader = (globalThis as any).WebFont?.loadText({ fontName: font, text: text(), family: "CustomFont", }) ?? null; const el = document.getElementById("webfont-preview"); if (el) el.style.fontFamily = '"CustomFont", sans-serif'; }; async function refreshFonts() { const fontList = await fetchFonts(); set_fonts(fontList); if (fontList.length > 0 && !selectedFont()) { onFontChange(fontList[0].name); } } return (

Web Font

如清风似闪电,超级快的字体子集化裁剪

Star on GitHub

输入文本,获取仅包含所需字符的子集字体 CSS