From 4e1bacdf819011447dca6c5b93e19fa1ae5b82f1 Mon Sep 17 00:00:00 2001 From: NikDizell Date: Mon, 9 Mar 2026 12:27:39 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC?= =?UTF-8?q?=D1=8B=20=D1=81=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC=20=D1=82=D0=B5=D0=BC=D1=8B?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D0=BE=D0=B4=D0=B0=201=D0=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blog/templates/blog/article_detail.html | 1 + programmer/static/blog/css/article.css | 50 +++++--- .../static/programmer/js/theme-switcher.js | 118 +++++++++--------- programmer/templates/programmer/base.html | 3 +- 4 files changed, 92 insertions(+), 80 deletions(-) diff --git a/blog/templates/blog/article_detail.html b/blog/templates/blog/article_detail.html index 030adea..37c8537 100644 --- a/blog/templates/blog/article_detail.html +++ b/blog/templates/blog/article_detail.html @@ -4,6 +4,7 @@ {% load seo_tags %} {% block extra_css %} + {% endblock %} diff --git a/programmer/static/blog/css/article.css b/programmer/static/blog/css/article.css index bf3fdac..4bd321f 100644 --- a/programmer/static/blog/css/article.css +++ b/programmer/static/blog/css/article.css @@ -173,9 +173,13 @@ margin-bottom: 0; } -/* --- Inline code --- */ +/* --- Inline code (not inside pre) --- */ +/* + * High specificity is fine here because this selector explicitly + * excludes pre > code, so it never touches hljs blocks. + */ -.content-card .card-content code { +.content-card .card-content :not(pre) > code { font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 0.875em; background: var(--bg-tertiary); @@ -186,28 +190,39 @@ word-break: break-all; } -/* --- Code blocks (CKEditor generates
) --- */
+/* --- Code blocks (CKEditor generates 
) --- */
+/*
+ * ALL pre and pre code rules use :where() — zero specificity.
+ * This guarantees hljs always wins on colors, background, and padding.
+ *
+ * Responsibility split:
+ *   article.css  → layout only: margin, border-radius, overflow, shadow
+ *   hljs CSS     → everything visual: background, color, padding, font-size
+ *
+ * font-size:0 on pre prevents inherited line-height:1.8 from inflating
+ * the spacing between lines (line-height is computed from font-size,
+ * so zeroing it on the wrapper element neutralises the inheritance).
+ * font-size is restored on pre code.
+ */
 
-.content-card .card-content pre {
+:where(.content-card .card-content) pre {
     margin: 1.5rem 0;
-    padding: 1.5rem;
-    background: #1A1F2E;
+    padding: 0;           /* hljs sets padding:1em on code.hljs — don't double it */
     border-radius: var(--radius-md);
     overflow-x: auto;
-    border: 1px solid var(--border-dark);
     box-shadow: var(--shadow-md);
+    font-size: 0;         /* neutralise inherited line-height */
+    line-height: 1;
+    background: none;     /* hljs controls background (#fff or #282c34) */
 }
 
-.content-card .card-content pre code {
+:where(.content-card .card-content) pre code {
     font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
-    font-size: 0.9rem;
-    background: transparent;
-    color: #E2E8F0;
-    padding: 0;
-    border: none;
-    border-radius: 0;
+    font-size: 0.9rem;    /* restore font-size for hljs to work from */
+    line-height: 1.5;
     word-break: normal;
     white-space: pre;
+    /* NO color, NO background, NO padding — hljs owns these */
 }
 
 /* --- Tables --- */
@@ -414,9 +429,10 @@
         margin: 1rem auto;
     }
 
-    .content-card .card-content pre {
-        padding: 1rem;
-        font-size: 0.8rem;
+    /* :where() keeps specificity at zero so hljs still wins on mobile */
+    :where(.content-card .card-content) pre {
+        box-shadow: none;
+        margin: 1rem 0;
     }
 
     .content-card .card-content th,
diff --git a/programmer/static/programmer/js/theme-switcher.js b/programmer/static/programmer/js/theme-switcher.js
index 6226fda..5386bbe 100644
--- a/programmer/static/programmer/js/theme-switcher.js
+++ b/programmer/static/programmer/js/theme-switcher.js
@@ -1,78 +1,72 @@
-// Theme Switcher Script
-document.addEventListener('DOMContentLoaded', function() {
-    const themeToggle = document.getElementById('theme-toggle');
+// theme-switcher.js
+document.addEventListener('DOMContentLoaded', function () {
+
+    const themeToggle       = document.getElementById('theme-toggle');
     const mobileThemeToggle = document.getElementById('mobile-theme-toggle');
-    const themeCSS1C = document.getElementById('theme-css-1c');
+    const themeCSS1C        = document.getElementById('theme-css-1c');
+
+    // FIX: Derive the base path once so we never rely on the current href value.
+    // href.replace() was silently failing when the filename didn't match exactly.
+    const hljsBasePath = themeCSS1C
+        ? themeCSS1C.href.replace(/1c-(light|dark)\.min\.css$/, '')
+        : null;
+
+    // console.log('Initial href:', themeCSS1C?.href);
+    // console.log('Computed basePath:', hljsBasePath);
+
+    // ── Theme application ────────────────────────────────────────────────────
+
+    function applyTheme(isDark) {
+        if (isDark) {
+            document.body.classList.add('theme-dark');
+            if (themeCSS1C && hljsBasePath) {
+                themeCSS1C.href = hljsBasePath + '1c-dark.min.css';
+            }
+        } else {
+            document.body.classList.remove('theme-dark');
+            if (themeCSS1C && hljsBasePath) {
+                themeCSS1C.href = hljsBasePath + '1c-light.min.css';
+            }
+        }
+
+        // FIX: CSS defines checked = dark (moon icon).
+        // Previously the handlers were calling the wrong function on check/uncheck.
+        if (themeToggle)       themeToggle.checked       = isDark;
+        if (mobileThemeToggle) mobileThemeToggle.checked = isDark;
+
+        localStorage.setItem('theme', isDark ? 'dark' : 'light');
+    }
+
+    // ── Initialise from saved preference ────────────────────────────────────
 
-    // Проверяем сохраненную тему в localStorage
     const savedTheme = localStorage.getItem('theme');
+    applyTheme(savedTheme === 'dark');
 
-    // Устанавливаем светлую тему по умолчанию
-    if (savedTheme === 'dark') {
-        switchToDarkTheme();
-    } else {
-        switchToLightTheme(); // Светлая тема по умолчанию
-    }
+    // ── Event listeners ──────────────────────────────────────────────────────
 
-    // Обработчик переключения темы для десктопного переключателя
+    // FIX: Both toggles now call the same applyTheme() — no duplicated logic,
+    // and both are always kept in sync with each other automatically.
     if (themeToggle) {
-        themeToggle.addEventListener('change', function() {
-            if (this.checked) {
-                switchToLightTheme();
-            } else {
-                switchToDarkTheme();
-            }
+        themeToggle.addEventListener('change', function () {
+            applyTheme(this.checked);
         });
     }
 
-    // Обработчик переключения темы для мобильного переключателя
     if (mobileThemeToggle) {
-        mobileThemeToggle.addEventListener('change', function() {
-            if (this.checked) {
-                switchToLightTheme();
-            } else {
-                switchToDarkTheme();
-            }
-            // Синхронизируем оба переключателя
-            if (themeToggle) {
-                themeToggle.checked = this.checked;
-            }
+        mobileThemeToggle.addEventListener('change', function () {
+            applyTheme(this.checked);
         });
     }
 
-    function switchToLightTheme() {
-        document.body.classList.remove('theme-dark');
-        if (themeCSS1C) {
-            themeCSS1C.href = themeCSS1C.href.replace('1c-dark.min.css', '1c-light.min.css');
-        }
-        if (themeToggle) themeToggle.checked = true;
-        if (mobileThemeToggle) mobileThemeToggle.checked = true;
-        localStorage.setItem('theme', 'light');
-        // 👇 Обновляем иконку ИКС
-        updateIKSTheme();
+    // ── CSS error handling ───────────────────────────────────────────────────
+
+    // FIX: was referencing undefined variable `themeCSS` instead of `themeCSS1C`
+    if (themeCSS1C) {
+        themeCSS1C.onerror = function () {
+            console.error('Ошибка загрузки CSS файла темы подсветки кода');
+            // Fall back to light theme
+            applyTheme(false);
+        };
     }
 
-    function switchToDarkTheme() {
-        document.body.classList.add('theme-dark');
-        if (themeCSS1C) {
-            themeCSS1C.href = themeCSS1C.href.replace('1c-light.min.css', '1c-dark.min.css');
-        }
-        if (themeToggle) themeToggle.checked = false;
-        if (mobileThemeToggle) mobileThemeToggle.checked = false;
-        localStorage.setItem('theme', 'dark');
-        // 👇 Обновляем иконку ИКС
-        updateIKSTheme();
-    }
-
-    // Синхронизация переключателей при загрузке
-    if (themeToggle && mobileThemeToggle) {
-        mobileThemeToggle.checked = themeToggle.checked;
-    }
-
-    // Обработка ошибок загрузки CSS
-    themeCSS.onerror = function() {
-        console.error('Ошибка загрузки CSS файла темы');
-        // Восстанавливаем светлую тему по умолчанию при ошибке
-        themeCSS1C.href = themeCSS1C.href.replace('1c-light.min.css', '1c-dark.min.css');
-    };
 });
\ No newline at end of file
diff --git a/programmer/templates/programmer/base.html b/programmer/templates/programmer/base.html
index 014fa39..b473f01 100644
--- a/programmer/templates/programmer/base.html
+++ b/programmer/templates/programmer/base.html
@@ -48,7 +48,8 @@
 
     
 
-    
+    
+