diff --git a/TODO.md b/TODO.md index f4140c6..9936447 100644 --- a/TODO.md +++ b/TODO.md @@ -7,26 +7,26 @@ ## π ΠΡΠ΅ΡΠ΅Π΄Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ (ΠΠΎΡΠ°Π³ΠΎΠ²ΡΠΉ ΠΏΠ»Π°Π½) ### 1. π ΠΠΎΠ»Π½ΠΎΡΠ΅Π½Π½ΡΠΉ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³ Markdown (.md) Π² ΡΠΈΡΠ°Π»ΠΊΠ΅ -- [ ] **ΠΠ»ΠΎΠΊΠΈ ΠΊΠΎΠ΄Π° (Fenced Code Blocks ```` ```language ````)**: +- [x] **ΠΠ»ΠΎΠΊΠΈ ΠΊΠΎΠ΄Π° (Fenced Code Blocks ```` ```language ````)**: - ΠΡΠ΄Π΅Π»Π΅Π½ΠΈΠ΅ Π±Π»ΠΎΠΊΠΎΠ² ΠΊΠΎΠ΄Π° Π² ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ `
`.
- ΠΠΎΠ½ΠΎΡΠΈΡΠΈΠ½Π½ΡΠΉ ΡΡΠΈΡΡ (`JetBrains Mono`, `Consolas`), ΡΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΠ΅ ΠΎΡΡΡΡΠΏΠΎΠ² ΠΈ ΡΠ°Π±ΡΠ»ΡΡΠΈΠΈ (`white-space: pre`).
- Π’ΡΠΌΠ½Π°Ρ ΠΏΠΎΠ΄Π»ΠΎΠΆΠΊΠ°, Π³ΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΡΠ½ΡΠΉ ΡΠΊΡΠΎΠ»Π» ΠΏΡΠΈ ΠΏΠ΅ΡΠ΅ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ, ΠΎΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΊΡΠ°ΡΠ½ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ (`text-indent: 0`).
- ΠΠ½ΠΎΠΏΠΊΠ° Β«ΠΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ ΠΊΠΎΠ΄Β» Π² ΡΠ°ΠΏΠΊΠ΅ Π±Π»ΠΎΠΊΠ°.
- ΠΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΈΠ½ΡΠ΅ΡΠ°ΠΊΡΠΈΠ²Π½ΡΡ
ΡΠ»ΠΎΠ²Π°ΡΠ½ΡΡ
ΡΠΏΠ°Π½ΠΎΠ² `` Π΄Π»Ρ ΠΊΠΎΠ΄Π°, ΡΡΠΎΠ±Ρ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ Π½Π΅ Π»ΠΎΠΌΠ°Π» ΡΠΎΡΠΌΠ°ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅.
-- [ ] **ΠΠ½Π»Π°ΠΉΠ½-ΠΊΠΎΠ΄ (`` `variable` ``)**:
+- [x] **ΠΠ½Π»Π°ΠΉΠ½-ΠΊΠΎΠ΄ (`` `variable` ``)**:
- ΠΠ±ΠΎΡΠ°ΡΠΈΠ²Π°Π½ΠΈΠ΅ Π² Π½Π°ΡΠΈΠ²Π½ΡΠΉ ΡΠ΅Π³ `` Ρ Π±Π΅ΠΉΠ΄ΠΆΠΈΠΊ-ΡΡΠΈΠ»Π΅ΠΌ.
-- [ ] **Π‘ΠΏΠΈΡΠΊΠΈ ΠΈ ΡΠΈΡΠ°ΡΡ**:
+- [x] **Π‘ΠΏΠΈΡΠΊΠΈ ΠΈ ΡΠΈΡΠ°ΡΡ**:
- ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΌΠ°ΡΠΊΠΈΡΠΎΠ²Π°Π½Π½ΡΡ
(`- `, `* `) ΠΈ Π½ΡΠΌΠ΅ΡΠΎΠ²Π°Π½Π½ΡΡ
(`1. `) ΡΠΏΠΈΡΠΊΠΎΠ² Π² `- ` / `
- `.
- ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠΈΡΠ°Ρ (`> `) Π² `
` Ρ Π°ΠΊΡΠ΅Π½ΡΠ½ΠΎΠΉ Π»Π΅Π²ΠΎΠΉ Π³ΡΠ°Π½ΠΈΡΠ΅ΠΉ.
- **Π‘Π»ΠΎΠ²Π° Π²Π½ΡΡΡΠΈ ΡΠΏΠΈΡΠΊΠΎΠ² ΠΈ ΡΠΈΡΠ°Ρ ΠΎΡΡΠ°ΡΡΡΡ ΠΊΠ»ΠΈΠΊΠ°Π±Π΅Π»ΡΠ½ΡΠΌΠΈ** (ΠΈΠ½ΡΠ΅ΡΠ°ΠΊΡΠΈΠ²Π½ΡΠΉ ΠΊΠ»ΠΈΠΊ-ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ!).
-- [ ] **ΠΠ°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ Markdown (`##`, `###`)**:
+- [x] **ΠΠ°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ Markdown (`##`, `###`)**:
- ΠΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΡ Π² ``, `` Ρ ΡΠ΄Π°Π»Π΅Π½ΠΈΠ΅ΠΌ ΡΡΡΡΡ
ΡΠ΅ΡΡΡΠΎΠΊ `#`.
-- [ ] **Π’ΠΎΡΠ½ΠΎΠ΅ ΠΏΠΎΠ·ΠΈΡΠΈΠΎΠ½ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΎΠΊΠ½Π° ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄Π° Ρ ΠΊΡΡΡΠΎΡΠ°/ΡΠ»ΠΎΠ²Π° (Popup Positioning)**:
- - ΠΡΠΏΡΠ°Π²ΠΈΡΡ Π±Π°Π³ Π΄Π²ΠΎΠΉΠ½ΠΎΠ³ΠΎ ΡΠΌΠ΅ΡΠ΅Π½ΠΈΡ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°Ρ: Ρ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ° `.reader-word-popup` Π² CSS Π·Π°Π΄Π°Π½ `position: fixed`, Π° Π² JS ΠΊ `rect.bottom` ΠΎΡΠΈΠ±ΠΎΡΠ½ΠΎ ΠΏΡΠΈΠ±Π°Π²Π»ΡΠ»ΡΡ `window.scrollY`, ΠΈΠ·-Π·Π° ΡΠ΅Π³ΠΎ ΠΎΠΊΠ½ΠΎ ΡΠ»Π΅ΡΠ°Π»ΠΎ Π΄Π°Π»Π΅ΠΊΠΎ Π²Π½ΠΈΠ· ΠΏΡΠΈ Π»ΡΠ±ΠΎΠΌ ΡΠΊΡΠΎΠ»Π»Π΅ ΡΡΡΠ°Π½ΠΈΡΡ.
- - ΠΠΎΠ·ΠΈΡΠΈΠΎΠ½ΠΈΡΠΎΠ²Π°ΡΡ ΠΎΠΊΠ½ΠΎ ΡΠΎΡΠ½ΠΎ ΠΏΠΎΠ΄ ΠΊΠ»ΠΈΠΊΠ½ΡΡΡΠΌ ΡΠ»ΠΎΠ²ΠΎΠΌ (`rect.bottom + 6`) Π»ΠΈΠ±ΠΎ Π½Π°Π΄ Π½ΠΈΠΌ (`rect.top - popupHeight - 6`), Π΅ΡΠ»ΠΈ ΡΠ½ΠΈΠ·Ρ Π½Π΅Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ ΠΌΠ΅ΡΡΠ° Π΄ΠΎ ΠΊΡΠ°Ρ ΡΠΊΡΠ°Π½Π°.
- - Π¦Π΅Π½ΡΡΠΈΡΠΎΠ²Π°ΡΡ ΠΎΠΊΠ½ΠΎ ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΡΠ»ΠΎΠ²Π° Ρ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎ Π³ΡΠ°Π½ΠΈΡΠ°ΠΌ Π²ΡΡΠΏΠΎΡΡΠ° (ΠΎΡΡΡΡΠΏΡ ΠΌΠΈΠ½ΠΈΠΌΡΠΌ 12px ΠΎΡ ΠΊΡΠ°ΡΠ² ΡΠΊΡΠ°Π½Π°).
-- [ ] **Π‘ΡΠΈΠ»ΠΈΠ·Π°ΡΠΈΡ Π² CSS ([`app/static/css/style.css`](file:///home/ai-projects/services/study.qpid.pro/app/static/css/style.css))**:
- - ΠΠΎΠ±Π°Π²ΠΈΡΡ ΡΡΠΈΠ»ΠΈ Π΄Π»Ρ `.reader-content-body pre`, `code`, `blockquote`, `ul`, `ol`.
+- [x] **Π’ΠΎΡΠ½ΠΎΠ΅ ΠΏΠΎΠ·ΠΈΡΠΈΠΎΠ½ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΎΠΊΠ½Π° ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄Π° Ρ ΠΊΡΡΡΠΎΡΠ°/ΡΠ»ΠΎΠ²Π° (Popup Positioning)**:
+ - ΠΡΠΏΡΠ°Π²Π»Π΅Π½ Π±Π°Π³ Π΄Π²ΠΎΠΉΠ½ΠΎΠ³ΠΎ ΡΠΌΠ΅ΡΠ΅Π½ΠΈΡ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°Ρ: ΡΠ±ΡΠ°Π½ `window.scrollY` ΠΏΡΠΈ `position: fixed`.
+ - ΠΠΊΠ½ΠΎ ΠΏΠΎΠ·ΠΈΡΠΈΠΎΠ½ΠΈΡΡΠ΅ΡΡΡ ΡΠΎΡΠ½ΠΎ ΠΏΠΎΠ΄ ΠΊΠ»ΠΈΠΊΠ½ΡΡΡΠΌ ΡΠ»ΠΎΠ²ΠΎΠΌ (`rect.bottom + 8`) Π»ΠΈΠ±ΠΎ Π½Π°Π΄ Π½ΠΈΠΌ (`rect.top - popupHeight - 8`), Π΅ΡΠ»ΠΈ ΡΠ½ΠΈΠ·Ρ Π½Π΅Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ ΠΌΠ΅ΡΡΠ°.
+ - ΠΠΊΠ½ΠΎ ΡΠ΅Π½ΡΡΠΈΡΡΠ΅ΡΡΡ ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΊΠ»ΠΈΠΊΠ½ΡΡΠΎΠ³ΠΎ ΡΠ»ΠΎΠ²Π° Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΎΠΉ Π³ΡΠ°Π½ΠΈΡ Π²ΡΡΠΏΠΎΡΡΠ° (ΠΎΡΡΡΡΠΏΡ ΠΌΠΈΠ½ΠΈΠΌΡΠΌ 12px ΠΎΡ ΠΊΡΠ°ΡΠ²).
+- [x] **Π‘ΡΠΈΠ»ΠΈΠ·Π°ΡΠΈΡ Π² CSS ([`app/static/css/style.css`](file:///home/ai-projects/services/study.qpid.pro/app/static/css/style.css))**:
+ - ΠΠΎΠ±Π°Π²Π»Π΅Π½Ρ ΡΡΠΈΠ»ΠΈ Π΄Π»Ρ `.reader-content-body pre`, `code`, `blockquote`, `ul`, `ol`, `.reader-code-block`, `.reader-inline-code`.
---
diff --git a/app/static/css/style.css b/app/static/css/style.css
index 562b45c..9788fab 100644
--- a/app/static/css/style.css
+++ b/app/static/css/style.css
@@ -2664,17 +2664,150 @@ body {
.reader-content-body h1,
.reader-content-body h2,
-.reader-content-body h3 {
+.reader-content-body h3,
+.reader-content-body h4,
+.reader-content-body h5,
+.reader-content-body h6 {
font-family: var(--font-family);
margin: 28px 0 16px;
color: var(--text-main);
+ text-indent: 0;
}
+.reader-content-body h4 { font-size: 1.15em; }
+.reader-content-body h5 { font-size: 1.05em; }
+
.reader-content-body p {
margin-bottom: 20px;
text-indent: 1.2em;
}
+/* Fenced Code Block */
+.reader-code-block {
+ margin: 24px 0;
+ border-radius: var(--radius-md);
+ background: #141820;
+ border: 1px solid var(--border-color);
+ overflow: hidden;
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
+}
+
+.reader-code-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 8px 14px;
+ background: rgba(255, 255, 255, 0.04);
+ border-bottom: 1px solid var(--border-color);
+ font-family: monospace;
+ font-size: 12px;
+ color: var(--text-muted);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.reader-code-lang {
+ font-weight: 600;
+}
+
+.reader-copy-code-btn {
+ background: transparent;
+ border: 1px solid var(--border-color);
+ color: var(--text-muted);
+ border-radius: 4px;
+ padding: 3px 8px;
+ font-size: 11px;
+ cursor: pointer;
+ transition: all 0.15s ease;
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+}
+
+.reader-copy-code-btn:hover {
+ background: rgba(255, 255, 255, 0.08);
+ color: var(--text-main);
+ border-color: var(--primary);
+}
+
+.reader-content-body pre {
+ margin: 0;
+ padding: 16px;
+ overflow-x: auto;
+ background: transparent;
+ border: none;
+ border-radius: 0;
+ font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
+ font-size: 14.5px;
+ line-height: 1.6;
+ text-indent: 0 !important;
+ white-space: pre;
+ tab-size: 4;
+}
+
+.reader-content-body pre code {
+ font-family: inherit;
+ font-size: inherit;
+ color: #e6edf3;
+ background: transparent;
+ padding: 0;
+ border: none;
+ white-space: pre;
+ display: block;
+ text-indent: 0;
+}
+
+/* Inline Code Badge */
+.reader-inline-code {
+ font-family: 'JetBrains Mono', 'Consolas', monospace;
+ font-size: 0.88em;
+ background: rgba(255, 255, 255, 0.08);
+ color: var(--primary);
+ padding: 2px 6px;
+ border-radius: 4px;
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+
+/* Blockquote */
+.reader-content-body blockquote {
+ margin: 20px 0;
+ padding: 12px 20px;
+ border-left: 4px solid var(--primary);
+ background: rgba(56, 189, 248, 0.06);
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
+ font-style: italic;
+ color: var(--text-main);
+ text-indent: 0;
+}
+
+.reader-content-body blockquote p {
+ margin: 0;
+ text-indent: 0;
+}
+
+/* Lists */
+.reader-content-body ul,
+.reader-content-body ol {
+ margin: 16px 0 20px 24px;
+ padding-left: 12px;
+ text-indent: 0;
+}
+
+.reader-content-body li {
+ margin-bottom: 8px;
+ line-height: 1.7;
+ text-indent: 0;
+}
+
+.reader-content-body hr {
+ border: 0;
+ height: 1px;
+ background: var(--border-color);
+ margin: 32px 0;
+}
+
/* Interactive Words */
.reader-word {
cursor: pointer;
diff --git a/app/static/index.html b/app/static/index.html
index f365d7c..b7a8fe4 100644
--- a/app/static/index.html
+++ b/app/static/index.html
@@ -5,7 +5,7 @@
Notes β ΠΠ΅ΡΡΠΎΠ½Π°Π»ΡΠ½ΡΠΉ ΡΡΠ΅Π½Π°ΠΆΠ΅Ρ ΠΈ ΡΠ»ΠΎΠ²Π°ΡΡ Π°Π½Π³Π»ΠΈΠΉΡΠΊΠΎΠ³ΠΎ ΡΠ·ΡΠΊΠ°
-
+
@@ -922,6 +922,6 @@
-
+