From 1cd2aabc6aa749b9f8b07b3ebd6ad27807bca907 Mon Sep 17 00:00:00 2001 From: MerfiDEV Date: Thu, 17 Sep 2026 22:18:01 +0300 Subject: [PATCH 1/5] custom ttf --- README.md | 63 ++- README.ru.md | 61 ++- src/main/index.js | 5 + src/main/ipc.js | 54 +++ src/main/settings-store.js | 5 + src/preload/api.js | 7 + src/preload/dom/fonts.js | 419 ++++++++++++++++++ src/preload/dom/settings-tab.js | 211 +++++++++ src/preload/i18n/i18n.js | 12 + src/preload/index.js | 4 + .../Anthropic Mono Web Regular Italic.otf | Bin 0 -> 98476 bytes src/ui/fonts/Anthropic Mono Web.otf | Bin 0 -> 100544 bytes test/preload/fonts.test.js | 118 +++++ 13 files changed, 914 insertions(+), 45 deletions(-) create mode 100644 src/preload/dom/fonts.js create mode 100644 src/ui/fonts/Anthropic Mono Web Regular Italic.otf create mode 100644 src/ui/fonts/Anthropic Mono Web.otf create mode 100644 test/preload/fonts.test.js diff --git a/README.md b/README.md index 3fb266d..7e72b41 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ It embeds the DeepSeek web chat into a native Electron window, injects a side ov ## Why it exists -Web chats are great at *thinking*, but they cannot *act* on your machine. Cookie Code closes that loop: +Web chats are great at _thinking_, but they cannot _act_ on your machine. Cookie Code closes that loop: - **Zero token cost** — everything goes through the DeepSeek web UI, no API calls. - **Real agent loop** — Think → Act → Observe → Repeat. File I/O, code search, shell commands, database queries, MCP tools. @@ -100,6 +100,18 @@ Under each AI reply you get an automatic badge: Change instantly, no reload required. +### Fonts + +Full control over the font of the Cookie Code UI **and** the DeepSeek page: + +- **System font** by default — nothing forced +- **Built-in Anthropic Mono** — one-click choice +- **Your own fonts** — drop files (`.ttf` / `.otf` / `.woff` / `.woff2`) into `/fonts` (button **"Open fonts folder"**) and click **"Refresh"** — the font appears in the preview grid +- **Weight slider** (100–900) — works for both the system font and any custom font +- Pick from a preview grid in **Settings → Cookie Code**; applies instantly to the whole UI and the page + +All settings persist in `cuckoo-settings.json` (`font`, `fontWeight`). + ### Blur & transparency Full control over the UI glass effect: @@ -159,15 +171,15 @@ Every `write` and `edit` runs the file through a language-specific formatter so Built-in formatters: -| Formatter | Trigger | What it needs | -|-----------|---------|---------------| -| `prettier` | `.js .jsx .ts .tsx .json .css .md .yaml` … | `prettier` in the nearest `package.json` + binary in `node_modules/.bin` or `PATH` | -| `biome` | same as prettier | `biome.json` / `biome.jsonc` in the project | -| `gofmt` | `.go` | `gofmt` in `PATH` | -| `ruff` | `.py .pyi` | `ruff` in `PATH` + `[tool.ruff]` in `pyproject.toml` (or `ruff.toml`) | -| `rustfmt` | `.rs` | `rustfmt` in `PATH` | -| `shfmt` | `.sh .bash` | `shfmt` in `PATH` | -| `clang-format` | `.c .cpp .h` … | `.clang-format` config + `clang-format` in `PATH` | +| Formatter | Trigger | What it needs | +| -------------- | ------------------------------------------ | ---------------------------------------------------------------------------------- | +| `prettier` | `.js .jsx .ts .tsx .json .css .md .yaml` … | `prettier` in the nearest `package.json` + binary in `node_modules/.bin` or `PATH` | +| `biome` | same as prettier | `biome.json` / `biome.jsonc` in the project | +| `gofmt` | `.go` | `gofmt` in `PATH` | +| `ruff` | `.py .pyi` | `ruff` in `PATH` + `[tool.ruff]` in `pyproject.toml` (or `ruff.toml`) | +| `rustfmt` | `.rs` | `rustfmt` in `PATH` | +| `shfmt` | `.sh .bash` | `shfmt` in `PATH` | +| `clang-format` | `.c .cpp .h` … | `.clang-format` config + `clang-format` in `PATH` | - Detection is **config-aware**: ruff won't run in a project without a `[tool.ruff]` section; prettier won't run without a `package.json` dependency. No unexpected reformatting of foreign code. - Formatter errors are swallowed — a failed formatter never blocks `write`/`edit`. @@ -246,19 +258,19 @@ Cookie Code intercepts it, executes it in a sandbox, and returns the result to t ## Available tools -| Tool | Description | -|------|-------------| -| `read`, `readLines` | Read files (with line numbers, offset/limit) | -| `write`, `edit` | Create / modify files (auto-formatted on save — see below) | -| `deleteFile` | Delete a file | -| `glob`, `grep` | File search (ripgrep-backed) | -| `bash`, `pwsh` | Execute shell commands | -| `todoWrite` | Structured task list | -| `webFetch` | Fetch HTTP(S) content as Markdown | -| `mysql` | Run SQL queries | -| `mcpCall`, `mcpListServers`, `mcpGetTools` | MCP tools | -| `skillList`, `skillLoad`, `skillExecute` | Custom skills | -| `openBrowserWindow`, `injectJS` | Electron browser window + JS injection | +| Tool | Description | +| ------------------------------------------ | ---------------------------------------------------------- | +| `read`, `readLines` | Read files (with line numbers, offset/limit) | +| `write`, `edit` | Create / modify files (auto-formatted on save — see below) | +| `deleteFile` | Delete a file | +| `glob`, `grep` | File search (ripgrep-backed) | +| `bash`, `pwsh` | Execute shell commands | +| `todoWrite` | Structured task list | +| `webFetch` | Fetch HTTP(S) content as Markdown | +| `mysql` | Run SQL queries | +| `mcpCall`, `mcpListServers`, `mcpGetTools` | MCP tools | +| `skillList`, `skillLoad`, `skillExecute` | Custom skills | +| `openBrowserWindow`, `injectJS` | Electron browser window + JS injection | Full TypeScript declarations are shipped at `tools/cuckoo-tools.d.ts`. @@ -282,6 +294,7 @@ Everything visual lives in **Settings → Cookie Code** and persists in `cuckoo- - **Backgrounds** — 27 built-in wallpapers, or drop your own image into `src/ui/backgrounds/` and register it in `registry.json`. - **Glass effect** — background / header / sidebar blur, opacity, and tool-block glass blur. +- **Fonts** — system by default, built-in Anthropic Mono, or your own fonts from a folder; weight slider (100–900). Applies to both the UI and the DeepSeek page. - **RGB username** — animated rainbow gradient in the sidebar, toggled under **Effects**. --- @@ -305,6 +318,8 @@ User settings live in `cuckoo-settings.json` under the app's userData directory: { "background": "miku", "backgroundBlur": 0, + "font": "system", + "fontWeight": 400, "headerBlur": 12, "sidebarBlur": 12, "headerOpacity": 45, @@ -357,6 +372,7 @@ src/ │ │ ├── response-meta.js ⏱ badge under replies │ │ ├── settings-tab.js Cookie Code tab in Settings │ │ ├── background.js Wallpaper & blur engine +│ │ ├── fonts.js UI & page font engine │ │ └── ... │ └── overlay/ Overlay panel UI │ ├── template.js buildOverlayHTML() + OVERLAY_CSS @@ -366,6 +382,7 @@ src/ │ └── deepseek.js Platform adapter ├── ui/ │ ├── backgrounds/ 27 wallpapers + registry.json +│ ├── fonts/ Built-in fonts (Anthropic Mono) │ └── logos/ tools/ Tool implementations (run in main process) └── cuckoo-tools.d.ts Type declarations for the AI diff --git a/README.ru.md b/README.ru.md index 19c7ff4..be935fe 100644 --- a/README.ru.md +++ b/README.ru.md @@ -66,6 +66,18 @@ - Выбор через сетку превью в **Настройки → Cookie Code** - Смена мгновенная, без перезагрузки +### Шрифт + +Полный контроль над шрифтом интерфейса Cookie Code **и** страницы DeepSeek: + +- **Системный шрифт** по умолчанию — ничего не навязывается +- **Встроенный Anthropic Mono** — на выбор одним кликом +- **Свои шрифты** — положите файлы (`.ttf` / `.otf` / `.woff` / `.woff2`) в папку `/fonts` (кнопка **«Открыть папку шрифтов»**) и нажмите **«Обновить»** — шрифт появится в сетке превью +- **Слайдер жирности** (100–900) — работает и для системного, и для любого кастомного шрифта +- Выбор через сетку превью в **Настройки → Cookie Code**, применяется мгновенно и ко всему интерфейсу, и к странице DeepSeek + +Все настройки сохраняются в `cuckoo-settings.json` (`font`, `fontWeight`). + ### Блюр и прозрачность Полный контроль над стеклянным эффектом интерфейса: @@ -124,15 +136,15 @@ Встроенные форматтеры: -| Форматтер | Для чего | Что нужно | -|-----------|----------|-----------| -| `prettier` | `.js .jsx .ts .tsx .json .css .md .yaml` … | `prettier` в ближайшем `package.json` + бинарь в `node_modules/.bin` или `PATH` | -| `biome` | то же, что prettier | `biome.json` / `biome.jsonc` в проекте | -| `gofmt` | `.go` | `gofmt` в `PATH` | -| `ruff` | `.py .pyi` | `ruff` в `PATH` + `[tool.ruff]` в `pyproject.toml` (или `ruff.toml`) | -| `rustfmt` | `.rs` | `rustfmt` в `PATH` | -| `shfmt` | `.sh .bash` | `shfmt` в `PATH` | -| `clang-format` | `.c .cpp .h` … | конфиг `.clang-format` + `clang-format` в `PATH` | +| Форматтер | Для чего | Что нужно | +| -------------- | ------------------------------------------ | ------------------------------------------------------------------------------- | +| `prettier` | `.js .jsx .ts .tsx .json .css .md .yaml` … | `prettier` в ближайшем `package.json` + бинарь в `node_modules/.bin` или `PATH` | +| `biome` | то же, что prettier | `biome.json` / `biome.jsonc` в проекте | +| `gofmt` | `.go` | `gofmt` в `PATH` | +| `ruff` | `.py .pyi` | `ruff` в `PATH` + `[tool.ruff]` в `pyproject.toml` (или `ruff.toml`) | +| `rustfmt` | `.rs` | `rustfmt` в `PATH` | +| `shfmt` | `.sh .bash` | `shfmt` в `PATH` | +| `clang-format` | `.c .cpp .h` … | конфиг `.clang-format` + `clang-format` в `PATH` | - Определение **учитывает конфиг проекта**: ruff не запустится без `[tool.ruff]`, prettier — без зависимости в `package.json`. Никакого неожиданного форматирования чужого кода. - Ошибки форматтера глушатся — падение форматтера никогда не блокирует `write`/`edit`. @@ -211,19 +223,19 @@ Cookie Code перехватывает его, выполняет в песоч ## Доступные инструменты -| Инструмент | Описание | -|-----------|----------| -| `read`, `readLines` | Чтение файлов (с номерами строк, offset/limit) | -| `write`, `edit` | Создание / изменение файлов (авто-форматирование при сохранении — см. ниже) | -| `deleteFile` | Удаление файла | -| `glob`, `grep` | Поиск по файлам (на базе ripgrep) | -| `bash`, `pwsh` | Выполнение команд | -| `todoWrite` | Структурированный список задач | -| `webFetch` | Загрузка HTTP(S) как Markdown | -| `mysql` | SQL-запросы | -| `mcpCall`, `mcpListServers`, `mcpGetTools` | MCP-инструменты | -| `skillList`, `skillLoad`, `skillExecute` | Пользовательские скиллы | -| `openBrowserWindow`, `injectJS` | Окно браузера Electron + инъекция JS | +| Инструмент | Описание | +| ------------------------------------------ | --------------------------------------------------------------------------- | +| `read`, `readLines` | Чтение файлов (с номерами строк, offset/limit) | +| `write`, `edit` | Создание / изменение файлов (авто-форматирование при сохранении — см. ниже) | +| `deleteFile` | Удаление файла | +| `glob`, `grep` | Поиск по файлам (на базе ripgrep) | +| `bash`, `pwsh` | Выполнение команд | +| `todoWrite` | Структурированный список задач | +| `webFetch` | Загрузка HTTP(S) как Markdown | +| `mysql` | SQL-запросы | +| `mcpCall`, `mcpListServers`, `mcpGetTools` | MCP-инструменты | +| `skillList`, `skillLoad`, `skillExecute` | Пользовательские скиллы | +| `openBrowserWindow`, `injectJS` | Окно браузера Electron + инъекция JS | Полные TypeScript-декларации — в `tools/cuckoo-tools.d.ts`. @@ -247,6 +259,7 @@ Cookie Code создан для того, чтобы его перестраив - **Фоны** — 27 встроенных обоев, либо положите своё изображение в `src/ui/backgrounds/` и зарегистрируйте его в `registry.json`. - **Стеклянный эффект** — размытие фона / шапки / сайдбара, прозрачность и размытие стекла tool-блоков. +- **Шрифт** — системный по умолчанию, встроенный Anthropic Mono или свои шрифты из папки; слайдер жирности (100–900). Применяется и к интерфейсу, и к странице DeepSeek. - **RGB-никнейм** — анимированный радужный градиент в сайдбаре, переключается в разделе **Effects**. ### Пользовательские скиллы @@ -290,6 +303,8 @@ AI получает к нему доступ через `skillList`, `skillLoad` { "background": "miku", "backgroundBlur": 0, + "font": "system", + "fontWeight": 400, "headerBlur": 12, "sidebarBlur": 12, "headerOpacity": 45, @@ -340,6 +355,7 @@ src/ │ │ ├── response-meta.js Бейдж ⏱ под ответом │ │ ├── settings-tab.js Вкладка Cookie Code в настройках │ │ ├── background.js Обои и блюр +│ │ ├── fonts.js Шрифт интерфейса и страницы │ │ └── ... │ └── overlay/ Оверлей-панель │ ├── template.js buildOverlayHTML() + OVERLAY_CSS @@ -349,6 +365,7 @@ src/ │ └── deepseek.js Адаптер платформы ├── ui/ │ ├── backgrounds/ 27 обоев + registry.json +│ ├── fonts/ Встроенные шрифты (Anthropic Mono) │ └── logos/ tools/ Реализация инструментов (в главном процессе) └── cuckoo-tools.d.ts TypeScript-декларации для AI diff --git a/src/main/index.js b/src/main/index.js index bbc1ef5..5fde39f 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -36,6 +36,11 @@ const CUSTOM_BACKGROUNDS_DIR = path.join( ); fs.mkdirSync(CUSTOM_BACKGROUNDS_DIR, { recursive: true }); +// Папка для пользовательских шрифтов: /fonts +// Пользователь кладёт туда .ttf/.otf — они появляются в выборе шрифта в настройках. +const CUSTOM_FONTS_DIR = path.join(app.getPath("userData"), "fonts"); +fs.mkdirSync(CUSTOM_FONTS_DIR, { recursive: true }); + // Папка для спрайтов петов: /pets // Пользователь кладёт туда PNG/GIF чубриков — они появляются в выборе пета. const CUSTOM_PETS_DIR = path.join(app.getPath("userData"), "pets"); diff --git a/src/main/ipc.js b/src/main/ipc.js index 309c94b..b7b3fd7 100644 --- a/src/main/ipc.js +++ b/src/main/ipc.js @@ -1190,6 +1190,60 @@ function registerIpcHandlers() { } }); + // ========== Пользовательские шрифты (userData/fonts) ========== + // Папка: /fonts — пользователь кладёт туда .ttf/.otf/.woff/.woff2, + // они автоматически появляются в выборе шрифта в настройках. + const CUSTOM_FONT_EXT = [".ttf", ".otf", ".woff", ".woff2"]; + const getCustomFontsDir = () => path.join(app.getPath("userData"), "fonts"); + + ipcMain.handle("cuckoo-fonts-list", async () => { + try { + const fs = require("fs"); + const dir = getCustomFontsDir(); + fs.mkdirSync(dir, { recursive: true }); + const files = fs.readdirSync(dir).filter((f) => { + return CUSTOM_FONT_EXT.includes(path.extname(f).toLowerCase()); + }); + const list = files.map((f) => { + const ext = path.extname(f); + const base = f.slice(0, -ext.length); + return { + id: "custom:" + base, + label: base, + file: path.join(dir, f), + custom: true, + }; + }); + return { success: true, dir, fonts: list }; + } catch (err) { + console.error( + "[Cookie Code] 读取 пользовательских шрифтов失败:", + err.message, + ); + return { + success: false, + error: err.message, + dir: getCustomFontsDir(), + fonts: [], + }; + } + }); + + // Открыть папку с пользовательскими шрифтами в системном проводнике. + ipcMain.handle("cuckoo-fonts-open-folder", async () => { + try { + const fs = require("fs"); + const dir = getCustomFontsDir(); + fs.mkdirSync(dir, { recursive: true }); + const errMsg = await shell.openPath(dir); + if (errMsg) return { success: false, error: errMsg }; + return { success: true, path: dir }; + } catch (err) { + console.error("[Cookie Code] 打开 папку шрифтов失败:", err.message); + return { success: false, error: err.message }; + } + }); + // ========== Спрайты петов (userData/pets) ========== // Папка: /pets — пользователь кладёт туда PNG/GIF чубриков. const PET_EXT = [".webp", ".jpg", ".jpeg", ".png", ".gif"]; diff --git a/src/main/settings-store.js b/src/main/settings-store.js index cf6b7ba..84207c4 100644 --- a/src/main/settings-store.js +++ b/src/main/settings-store.js @@ -25,6 +25,11 @@ const DEFAULT_DANGEROUS_PATTERNS = [ const DEFAULTS = { customizationEnabled: true, background: "miku", + // Шрифт интерфейса Cookie Code и страницы DeepSeek. + // "system" — системный по умолчанию; "" — встроенный или "custom:<имя>". + font: "system", + // Жирность шрифта (100–900). Применяется и к системному, и к кастомному. + fontWeight: 400, backgroundBlur: 0, // px — размытие самой картинки фона headerBlur: 12, // px — стекло верхней панели sidebarBlur: 12, // px — стекло левого сайдбара diff --git a/src/preload/api.js b/src/preload/api.js index 9b5ac13..c75651d 100644 --- a/src/preload/api.js +++ b/src/preload/api.js @@ -149,6 +149,13 @@ let electronAPI = { openCustomBackgroundsFolder: () => { return ipcRenderer.invoke("cuckoo-backgrounds-open-folder"); }, + // ========== Пользовательские шрифты (userData/fonts) ========== + listCustomFonts: () => { + return ipcRenderer.invoke("cuckoo-fonts-list"); + }, + openCustomFontsFolder: () => { + return ipcRenderer.invoke("cuckoo-fonts-open-folder"); + }, // ========== Спрайты петов (userData/pets) ========== listPets: () => { return ipcRenderer.invoke("cuckoo-pets-list"); diff --git a/src/preload/dom/fonts.js b/src/preload/dom/fonts.js new file mode 100644 index 0000000..ce1b1f5 --- /dev/null +++ b/src/preload/dom/fonts.js @@ -0,0 +1,419 @@ +/** + * Управление шрифтом интерфейса Cookie Code и страницы DeepSeek. + * + * Шрифты читаются из src/ui/fonts/ (встроенные) и /fonts (пользовательские) + * напрямую в preload через fs и кодируются в base64 data-URI. Это единственный + * надёжный способ: file:// заблокирован Chromium со страницы chat.deepseek.com, + * а кастомный cuckoo-asset:// не проходит через fetch API даже с bypassCSP. + * + * Инжектится один