diff --git a/check_encoding.py b/check_encoding.py new file mode 100644 index 00000000..af14c4c5 --- /dev/null +++ b/check_encoding.py @@ -0,0 +1,52 @@ +path = 'e:/GitHub/blog/public/js/bundle.min.6c8518518bf5af8d666e1b391ef3cf4caaaca7537fd1961891ed292d86eb3fed.js' +with open(path, 'rb') as f: + content = f.read() + +# Find initCodeFold in the binary content +marker = 'window.initCodeFold=function'.encode('utf-8') +idx = content.find(marker) +if idx == -1: + # Try latin-1 or other encoding + marker = 'window.initCodeFold=function'.encode() + idx = content.find(marker) + +if idx == -1: + print("initCodeFold definition not found!") +else: + # Find the span innerHTML part + chunk = content[idx:idx+1200] + # Find '展开代码' or its bytes + # UTF-8 for 展开代码: e5 b1 95 e5 bc 80 e4 bb a3 e7 a0 81 + # UTF-8 for 收起代码: e6 94 b6 e8 b5 b7 e4 bb a3 e7 a0 81 + target1 = '展开代码'.encode('utf-8') + target2 = '收起代码'.encode('utf-8') + + t1_idx = chunk.find(target1) + t2_idx = chunk.find(target2) + + print(f"展开代码 found at offset {t1_idx}: {t1_idx != -1}") + print(f"收起代码 found at offset {t2_idx}: {t2_idx != -1}") + + # Also check the raw source file + print() + print("--- Checking source file ---") + with open('e:/GitHub/blog/themes/Ying/assets/js/modules/utils.js', 'rb') as f: + src = f.read() + t1 = src.find(target1) + t2 = src.find(target2) + print(f"展开代码 in source: {t1 != -1}") + print(f"收起代码 in source: {t2 != -1}") + + # Check file encoding + print() + print(f"Built JS file size: {len(content)} bytes") + + # Check if file starts with BOM or has other encoding markers + if content[:3] == b'\xef\xbb\xbf': + print("File has UTF-8 BOM") + elif content[:2] == b'\xff\xfe': + print("File has UTF-16 LE BOM") + elif content[:2] == b'\xfe\xff': + print("File has UTF-16 BE BOM") + else: + print("No BOM detected - likely UTF-8") diff --git a/check_fold.py b/check_fold.py new file mode 100644 index 00000000..33328035 --- /dev/null +++ b/check_fold.py @@ -0,0 +1,26 @@ +import re + +path = 'e:/GitHub/blog/public/js/bundle.min.6c8518518bf5af8d666e1b391ef3cf4caaaca7537fd1961891ed292d86eb3fed.js' +with open(path, 'r', encoding='utf-8') as f: + content = f.read() + +# Find all occurrences of initCodeFold +idx = 0 +matches = [] +while True: + idx = content.find('initCodeFold', idx) + if idx == -1: + break + start = max(0, idx - 200) + end = min(len(content), idx + 500) + matches.append((idx, content[start:end])) + idx += 1 + +print(f"Found {len(matches)} matches of 'initCodeFold'") +print(f"File length: {len(content)} chars") +print() + +for i, (pos, context) in enumerate(matches): + print(f'=== Match {i+1} at position {pos} ===') + print(context) + print() diff --git a/check_fold2.py b/check_fold2.py new file mode 100644 index 00000000..2f9f058d --- /dev/null +++ b/check_fold2.py @@ -0,0 +1,19 @@ +import re + +path = 'e:/GitHub/blog/public/js/bundle.min.6c8518518bf5af8d666e1b391ef3cf4caaaca7537fd1961891ed292d86eb3fed.js' +with open(path, 'r', encoding='utf-8') as f: + content = f.read() + +# Find initCodeFold definition +idx = content.find('window.initCodeFold=function') +if idx == -1: + print("initCodeFold definition not found!") +else: + # Extract a larger chunk + end_idx = content.find('window.initCodeCopy', idx) + if end_idx == -1: + end_idx = idx + 2000 + chunk = content[idx:end_idx] + print(f"Chunk length: {len(chunk)} chars") + print("=" * 60) + print(chunk) diff --git a/check_fold3.py b/check_fold3.py new file mode 100644 index 00000000..68779bc5 --- /dev/null +++ b/check_fold3.py @@ -0,0 +1,32 @@ +from pathlib import Path +import glob + +# Find latest bundle JS file +js_files = sorted(Path('e:/GitHub/blog/public/js').glob('bundle.min.*.js'), key=lambda p: p.stat().st_mtime, reverse=True) +if not js_files: + print("No JS bundle found!") + exit(1) + +path = str(js_files[0]) +print(f"Checking: {path}") + +with open(path, 'r', encoding='utf-8') as f: + content = f.read() + +idx = content.find('window.initCodeFold=function') +if idx == -1: + print("NOT FOUND") +else: + chunk = content[idx:idx+800] + print(chunk[:600]) + print() + # Check for the key changes + checks = [ + ('parentNode.classList.contains("code-fold-container")', 'early return check'), + ('pre.scrollHeight', 'pre scrollHeight'), + ('block.scrollHeight', 'block fallback'), + ('contentHeight', 'contentHeight var'), + ] + for pattern, desc in checks: + found = pattern in chunk + print(f" {desc}: {'YES' if found else 'MISSING!'}") diff --git a/themes/Ying/assets/css/main.css b/themes/Ying/assets/css/main.css index 054abb82..2e843b3d 100644 --- a/themes/Ying/assets/css/main.css +++ b/themes/Ying/assets/css/main.css @@ -175,6 +175,10 @@ hr { padding: 0; } +[data-theme="dark"] hr { + border-top-color: rgba(255, 255, 255, 0.2); +} + img { max-width: 100%; border-radius: 5px; diff --git a/themes/Ying/assets/js/modules/artalk.js b/themes/Ying/assets/js/modules/artalk.js index 4cf0d0f5..8486cb2e 100644 --- a/themes/Ying/assets/js/modules/artalk.js +++ b/themes/Ying/assets/js/modules/artalk.js @@ -181,26 +181,27 @@ var linkMap = null; var feedMap = null; // Comment rank table — Song dynasty 九品十八阶 +// Color scale: warm → cool gradient for visual hierarchy var RANK_TABLE = [ - { min: 2000, title: '正一品·太师', short: '太师', color: '#b8860b', bg: 'rgba(184,134,11,0.22)' }, - { min: 1400, title: '从一品·太尉', short: '太尉', color: '#b8860b', bg: 'rgba(184,134,11,0.18)' }, - { min: 1050, title: '正二品·参知政事', short: '参知政事', color: '#7c3aed', bg: 'rgba(124,58,237,0.18)' }, - { min: 800, title: '从二品·节度使', short: '节度使', color: '#7c3aed', bg: 'rgba(124,58,237,0.15)' }, - { min: 600, title: '正三品·御史中丞', short: '御史中丞', color: '#a855f7', bg: 'rgba(168,85,247,0.15)' }, - { min: 480, title: '从三品·秘书监', short: '秘书监', color: '#a855f7', bg: 'rgba(168,85,247,0.12)' }, - { min: 380, title: '正四品·谏议大夫', short: '谏议大夫', color: '#c084fc', bg: 'rgba(192,132,252,0.12)' }, - { min: 300, title: '从四品·侍读学士', short: '侍读学士', color: '#c084fc', bg: 'rgba(192,132,252,0.10)' }, - { min: 240, title: '正五品·给事中', short: '给事中', color: '#dc2626', bg: 'rgba(220,38,38,0.15)' }, - { min: 190, title: '从五品·知州', short: '知州', color: '#dc2626', bg: 'rgba(220,38,38,0.12)' }, - { min: 150, title: '正六品·侍御史', short: '侍御史', color: '#ef4444', bg: 'rgba(239,68,68,0.12)' }, - { min: 115, title: '从六品·通判', short: '通判', color: '#ef4444', bg: 'rgba(239,68,68,0.10)' }, - { min: 85, title: '正七品·知县', short: '知县', color: '#059669', bg: 'rgba(5,150,105,0.15)' }, - { min: 60, title: '从七品·殿中侍御史', short: '殿中侍御史', color: '#059669', bg: 'rgba(5,150,105,0.12)' }, - { min: 40, title: '正八品·大理评事', short: '大理评事', color: '#10b981', bg: 'rgba(16,185,129,0.12)' }, - { min: 25, title: '从八品·录事参军', short: '录事参军', color: '#10b981', bg: 'rgba(16,185,129,0.10)' }, - { min: 15, title: '正九品·主簿', short: '主簿', color: '#a16207', bg: 'rgba(161,98,7,0.15)' }, - { min: 5, title: '从九品·司户参军', short: '司户参军', color: '#a16207', bg: 'rgba(161,98,7,0.12)' }, - { min: 0, title: '庶民', short: '庶民', color: '#9ca3af', bg: 'rgba(156,163,175,0.12)' } + { min: 2000, title: '正一品·太师', short: '太师', color: '#c5881b', bg: 'rgba(197,136,27,0.16)' }, + { min: 1400, title: '从一品·太尉', short: '太尉', color: '#cc942a', bg: 'rgba(204,148,42,0.13)' }, + { min: 1050, title: '正二品·参知政事', short: '参知政事', color: '#d46d33', bg: 'rgba(212,109,51,0.16)' }, + { min: 800, title: '从二品·节度使', short: '节度使', color: '#d87940', bg: 'rgba(216,121,64,0.13)' }, + { min: 600, title: '正三品·御史中丞', short: '御史中丞', color: '#cf4a58', bg: 'rgba(207,74,88,0.16)' }, + { min: 480, title: '从三品·秘书监', short: '秘书监', color: '#d45d68', bg: 'rgba(212,93,104,0.13)' }, + { min: 380, title: '正四品·谏议大夫', short: '谏议大夫', color: '#b05385', bg: 'rgba(176,83,133,0.16)' }, + { min: 300, title: '从四品·侍读学士', short: '侍读学士', color: '#b8638f', bg: 'rgba(184,99,143,0.13)' }, + { min: 240, title: '正五品·给事中', short: '给事中', color: '#9570d6', bg: 'rgba(149,112,214,0.16)' }, + { min: 190, title: '从五品·知州', short: '知州', color: '#a07bda', bg: 'rgba(160,123,218,0.13)' }, + { min: 150, title: '正六品·侍御史', short: '侍御史', color: '#5f7ace', bg: 'rgba(95,122,206,0.16)' }, + { min: 115, title: '从六品·通判', short: '通判', color: '#6b85d0', bg: 'rgba(107,133,208,0.13)' }, + { min: 85, title: '正七品·知县', short: '知县', color: '#2a9a84', bg: 'rgba(42,154,132,0.16)' }, + { min: 60, title: '从七品·殿中侍御史', short: '殿中侍御史', color: '#34a390', bg: 'rgba(52,163,144,0.13)' }, + { min: 40, title: '正八品·大理评事', short: '大理评事', color: '#628530', bg: 'rgba(98,133,48,0.16)' }, + { min: 25, title: '从八品·录事参军', short: '录事参军', color: '#6e913d', bg: 'rgba(110,145,61,0.13)' }, + { min: 15, title: '正九品·主簿', short: '主簿', color: '#8a7050', bg: 'rgba(138,112,80,0.16)' }, + { min: 5, title: '从九品·司户参军', short: '司户参军', color: '#917a5c', bg: 'rgba(145,122,92,0.13)' }, + { min: 0, title: '庶民', short: '庶民', color: '#8a8e98', bg: 'rgba(138,142,152,0.10)' } ]; var getRank = function(count) { @@ -312,6 +313,12 @@ var processBadges = function() { rb.className = 'atk-rank-badge'; rb.textContent = rank.short; rb.title = rank.title + ' (' + count + '条评论)'; + rb.style.color = rank.color; + rb.style.backgroundColor = rank.bg; + rb.style.borderColor = rank.bg.replace(/[\d.]+\)$/, function(m) { + var v = parseFloat(m) + 0.06; + return Math.min(v, 0.26).toFixed(2) + ')'; + }); var idx = RANK_TABLE.indexOf(rank); if (idx > 0) { var next = RANK_TABLE[idx - 1]; diff --git a/themes/Ying/assets/js/modules/utils.js b/themes/Ying/assets/js/modules/utils.js index 850b37b3..9aaa66fa 100644 --- a/themes/Ying/assets/js/modules/utils.js +++ b/themes/Ying/assets/js/modules/utils.js @@ -83,23 +83,24 @@ window.initThemeToggle = function() { window.initCodeFold = function() { var codeBlocks = document.querySelectorAll('.highlight'); codeBlocks.forEach(function(block) { - var wrapper = block.parentNode && block.parentNode.classList.contains('code-fold-container') ? block.parentNode : null; - if (!wrapper && block.scrollHeight <= 360 && block.offsetHeight <= 360) return; + if (block.parentNode && block.parentNode.classList.contains('code-fold-container')) return; - if (!wrapper) { - wrapper = document.createElement('div'); - wrapper.className = 'code-fold-container collapsed'; - block.parentNode.insertBefore(wrapper, block); - wrapper.appendChild(block); - } + var pre = block.querySelector('pre'); + if (!pre) return; - var btn = wrapper.querySelector(':scope > .code-expand-btn'); - if (!btn) { - btn = document.createElement('button'); - btn.type = 'button'; - btn.className = 'code-expand-btn'; - wrapper.appendChild(btn); - } + // Use pre's content height; 0 means layout not ready, wrap conservatively + var contentHeight = pre.scrollHeight || block.scrollHeight; + if (contentHeight && contentHeight <= 360) return; + + var wrapper = document.createElement('div'); + wrapper.className = 'code-fold-container collapsed'; + block.parentNode.insertBefore(wrapper, block); + wrapper.appendChild(block); + + var btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'code-expand-btn'; + wrapper.appendChild(btn); var syncButton = function() { var collapsed = wrapper.classList.contains('collapsed'); diff --git a/themes/Ying/layouts/partials/artalk.html b/themes/Ying/layouts/partials/artalk.html index bda89eb6..13fd7e48 100644 --- a/themes/Ying/layouts/partials/artalk.html +++ b/themes/Ying/layouts/partials/artalk.html @@ -51,9 +51,9 @@ border: 1px solid rgba(217,119,6,0.15); } .atk-rank-badge { - color: #fff; - background: #3b82f6; - border: none; + color: #6b7280; + background: rgba(107,114,128,0.08); + border: 1px solid rgba(107,114,128,0.15); font-weight: 600; } [data-theme="dark"] .atk-link-badge { @@ -67,7 +67,9 @@ border-color: rgba(251,191,36,0.2); } [data-theme="dark"] .atk-rank-badge { - background: #2563eb; + color: rgb(148,163,184); + background: rgba(148,163,184,0.1); + border-color: rgba(148,163,184,0.18); } /* 覆盖 Artalk 原版 .atk-badge(博主)/ .atk-pinned-badge(置顶)尺寸 */