From 30f9daaec8584c796ddc0da0f9b2417cc93df146 Mon Sep 17 00:00:00 2001 From: Fovway Date: Wed, 5 Nov 2025 05:24:07 +0700 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=81=D1=82=D0=B8=D0=BB=D0=B8=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=20=D1=81=D0=BF=D0=BE=D0=B9=D0=BB=D0=B5=D1=80=D0=BE=D0=B2?= =?UTF-8?q?,=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B0=20=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BC=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B8=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D0=B5=20=D0=B2=D0=B8=D0=B7=D1=83=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D1=8D=D1=84=D1=84=D0=B5=D0=BA=D1=82=D1=8B?= =?UTF-8?q?.=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=84?= =?UTF-8?q?=D0=B0=D0=B9=D0=BB=20service=20worker=20=D1=81=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B5=D0=B9?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D1=8D=D1=88=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F.=20=D0=9E=D0=BF=D1=82=D0=B8?= =?UTF-8?q?=D0=BC=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D0=B0=20=D1=80=D0=B5=D0=BD=D0=B4?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D0=BD=D0=B3=D0=B0=20=D1=82=D0=BE=D0=BA=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=20=D0=B2=20markdown,=20=D1=83=D0=BB=D1=83?= =?UTF-8?q?=D1=87=D1=88=D0=B5=D0=BD=D0=B0=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D0=B0=20=D0=B2=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D1=85=20=D1=8D=D0=BB=D0=B5=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=B8=20=D1=81=D1=81=D1=8B=D0=BB=D0=BE=D0=BA.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dev-dist/sw.js | 2 +- src/styles/style.css | 36 +++++++++------- src/utils/markdown.ts | 97 +++++++++++++++++++++++-------------------- 3 files changed, 74 insertions(+), 61 deletions(-) diff --git a/dev-dist/sw.js b/dev-dist/sw.js index ec8c3ed..4f10989 100644 --- a/dev-dist/sw.js +++ b/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-9dc17825'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.nsn25edhihg" + "revision": "0.b1jpidvaji" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/src/styles/style.css b/src/styles/style.css index c368cbc..7670d89 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -671,7 +671,8 @@ header { /* Анимация пульсации для offline индикатора */ @keyframes pulse { - 0%, 100% { + 0%, + 100% { opacity: 1; transform: scale(1); } @@ -4409,7 +4410,7 @@ textarea:focus { /* Стили для скрытого текста (спойлеров) */ .spoiler { - background: linear-gradient(45deg, #f0f0f0, #e8e8e8); + background: linear-gradient(45deg, rgba(var(--accent-color-rgb), 0.15), rgba(var(--accent-color-rgb), 0.25)); color: transparent; cursor: pointer; border-radius: 4px; @@ -4417,11 +4418,15 @@ textarea:focus { user-select: none; transition: all 0.3s ease; position: relative; - border: 1px solid #ddd; + display: inline-block; + vertical-align: baseline; + border: 1px solid rgba(var(--accent-color-rgb), 0.3); font-weight: 500; backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); - text-shadow: 0 0 8px rgba(0, 0, 0, 0.3); + text-shadow: 0 0 8px rgba(var(--accent-color-rgb), 0.3); + isolation: isolate; + z-index: 0; } .spoiler::before { @@ -4431,27 +4436,30 @@ textarea:focus { left: 0; right: 0; bottom: 0; - background: rgba(255, 255, 255, 0.8); + background: rgba(var(--accent-color-rgb), 0.1); border-radius: 4px; filter: blur(1px); z-index: -1; + box-sizing: border-box; + pointer-events: none; } .spoiler:hover { - background: linear-gradient(45deg, #e8e8e8, #d8d8d8); + background: linear-gradient(45deg, rgba(var(--accent-color-rgb), 0.25), rgba(var(--accent-color-rgb), 0.35)); transform: scale(1.02); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + box-shadow: 0 2px 8px rgba(var(--accent-color-rgb), 0.25); + border-color: rgba(var(--accent-color-rgb), 0.4); } .spoiler:hover::before { - background: rgba(255, 255, 255, 0.9); + background: rgba(var(--accent-color-rgb), 0.15); } .spoiler.revealed { - background: linear-gradient(45deg, #e8f5e8, #d4edda); - color: #155724; - border-color: #c3e6cb; - box-shadow: 0 0 0 2px rgba(40, 167, 69, 0.25); + background: linear-gradient(45deg, rgba(var(--accent-color-rgb), 0.15), rgba(var(--accent-color-rgb), 0.2)); + color: var(--accent-color); + border-color: rgba(var(--accent-color-rgb), 0.4); + box-shadow: 0 0 0 2px rgba(var(--accent-color-rgb), 0.25); text-shadow: none; user-select: text; -webkit-user-select: text; @@ -4463,8 +4471,8 @@ textarea:focus { } .spoiler.revealed:hover { - background: linear-gradient(45deg, #d4edda, #c3e6cb); - box-shadow: 0 0 0 2px rgba(40, 167, 69, 0.35); + background: linear-gradient(45deg, rgba(var(--accent-color-rgb), 0.2), rgba(var(--accent-color-rgb), 0.25)); + box-shadow: 0 0 0 2px rgba(var(--accent-color-rgb), 0.35); } /* Стили для файлов */ diff --git a/src/utils/markdown.ts b/src/utils/markdown.ts index 6e89f04..c8ee080 100644 --- a/src/utils/markdown.ts +++ b/src/utils/markdown.ts @@ -25,49 +25,54 @@ const spoilerExtension = { // Функция для рендеринга вложенных токенов function renderTokens(tokens: any[], renderer: any): string { - return tokens.map((token) => { - // Используем кастомный renderer если он есть - if (renderer[token.type]) { - return renderer[token.type](token); - } - // Fallback для встроенных типов токенов - if (token.type === 'text') { - return token.text || ''; - } - if (token.type === 'strong') { - return `${renderTokens(token.tokens || [], renderer)}`; - } - if (token.type === 'em') { - return `${renderTokens(token.tokens || [], renderer)}`; - } - if (token.type === 'codespan') { - return `${token.text || ''}`; - } - if (token.type === 'del') { - return `${renderTokens(token.tokens || [], renderer)}`; - } - if (token.type === 'link') { - // Для ссылок используем кастомный renderer если доступен - if (renderer.link) { - return renderer.link(token); + return tokens + .map((token) => { + // Используем кастомный renderer если он есть + if (renderer[token.type]) { + return renderer[token.type](token); } - // Fallback для встроенных ссылок - const href = token.href || ''; - const title = token.title ? ` title="${token.title}"` : ''; - const text = token.tokens && token.tokens.length > 0 - ? renderTokens(token.tokens, renderer) - : (token.text || ''); - return `${text}`; - } - if (token.type === 'spoiler') { - // Для спойлеров используем кастомный renderer если доступен - if (renderer.spoiler) { - return renderer.spoiler(token); + // Fallback для встроенных типов токенов + if (token.type === "text") { + return token.text || ""; } - return `${token.text || ''}`; - } - return token.text || ''; - }).join(''); + if (token.type === "strong") { + return `${renderTokens(token.tokens || [], renderer)}`; + } + if (token.type === "em") { + return `${renderTokens(token.tokens || [], renderer)}`; + } + if (token.type === "codespan") { + return `${token.text || ""}`; + } + if (token.type === "del") { + return `${renderTokens(token.tokens || [], renderer)}`; + } + if (token.type === "link") { + // Для ссылок используем кастомный renderer если доступен + if (renderer.link) { + return renderer.link(token); + } + // Fallback для встроенных ссылок + const href = token.href || ""; + const title = token.title ? ` title="${token.title}"` : ""; + const text = + token.tokens && token.tokens.length > 0 + ? renderTokens(token.tokens, renderer) + : token.text || ""; + return `${text}`; + } + if (token.type === "spoiler") { + // Для спойлеров используем кастомный renderer если доступен + if (renderer.spoiler) { + return renderer.spoiler(token); + } + return `${ + token.text || "" + }`; + } + return token.text || ""; + }) + .join(""); } // Кастомный renderer для внешних ссылок и чекбоксов @@ -75,9 +80,9 @@ const renderer: any = { link(token: any) { const href = token.href; const title = token.title; - + // Правильно обрабатываем вложенные токены для форматирования внутри ссылок - let text = ''; + let text = ""; if (token.tokens && token.tokens.length > 0) { text = renderTokens(token.tokens, this); } else if (token.text) { @@ -101,9 +106,9 @@ const renderer: any = { listitem(token: any) { const task = token.task; const checked = token.checked; - + // Правильно обрабатываем вложенные токены для форматирования - let content = ''; + let content = ""; if (token.tokens && token.tokens.length > 0) { // Рендерим вложенные токены используя наш renderer content = renderTokens(token.tokens, this); @@ -174,7 +179,7 @@ export const extractTags = (content: string): string[] => { const tag = match[1]; // Проверяем, есть ли уже тег с таким же именем (регистронезависимо) - if (!tags.some(t => t.toLowerCase() === tag.toLowerCase())) { + if (!tags.some((t) => t.toLowerCase() === tag.toLowerCase())) { tags.push(tag); } }