From bfd1f749f56808b696ad409c6a0e51dfa440c914 Mon Sep 17 00:00:00 2001 From: CyC2018 Date: Sun, 1 Nov 2026 11:33:43 +0800 Subject: [PATCH 1/4] Update site.css MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 载入提示占满一屏居中显示,预留滚动条位置;主色、代码高亮和学习入口说明文字的颜色调整到对比度 4.5:1 以上;首页头像链接按图片大小计算点击区域。 --- website/templates/site.css | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/website/templates/site.css b/website/templates/site.css index 03de5bee..49ea5866 100644 --- a/website/templates/site.css +++ b/website/templates/site.css @@ -1,5 +1,9 @@ -:root { --theme-color: #369b72; } +:root { --theme-color: #2a7a5a; } body, .sidebar, .sidebar-toggle { background: #f3f2ee; } +/* 载入提示:vue.css 的 div#app { margin: 40vh auto } 会穿透到 body,载入完成时整页从屏幕中间跳到顶部 */ +div#app { display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; color: #718078; font-size: 14px; letter-spacing: .04em; } +/* 载入完成前 body 不能滚动,出现滚动条时页面会左移;预留滚动条的位置 */ +html { scrollbar-gutter: stable; } body { color: #34495e; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; } .app-name { font-weight: 650 !important; letter-spacing: .02em; } .sidebar { padding-top: 24px; border-right: 1px solid #e2e3dc; } @@ -26,25 +30,25 @@ body { color: #34495e; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI .site-footer a { color: inherit; font-weight: 400; } .topic-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px; margin: 18px 0; } .topic-grid a { display: flex; align-items: center; justify-content: center; gap: 7px; padding: 13px 8px; border: 1px solid #dfe3da; border-radius: 7px; background: #fafbf8; text-decoration: none; font-size: 14px; white-space: nowrap; } -.topic-grid a:hover, .topic-grid a:focus-visible { background: #e8f1e9; border-color: #369b72; } +.topic-grid a:hover, .topic-grid a:focus-visible { background: #e8f1e9; border-color: #2a7a5a; } .site-search { padding: 8px 15px; } .site-search input { box-sizing: border-box; width: 100%; min-height: 42px; padding: 10px; border: 1px solid #dfe3da; color: #34495e; font-size: 15px; } -.site-search input:focus { outline: 2px solid #369b72; outline-offset: 1px; } +.site-search input:focus { outline: 2px solid #2a7a5a; outline-offset: 1px; } .search-status { color: #718078; font-size: 12px; margin: 7px 0; } .search-status:empty { display: none; } .site-search .matching-post { display: block; padding: 12px 0; border-bottom: 1px solid #dde3d8; text-decoration: none; } .matching-post strong, .matching-post small { display: block; } -.matching-post strong { color: #369b72; font-size: 14px; } +.matching-post strong { color: #2a7a5a; font-size: 14px; } .matching-post small { color: #718078; margin: 5px 0; font-size: 12px; } .matching-post p { color: #34495e; margin: 4px 0; font-size: 13px; line-height: 1.7; overflow-wrap: anywhere; } .article-toc { border: 1px solid #dfe3da; border-radius: 7px; padding: 12px 18px; margin: 20px 0 28px; background: #fafbf8; } -.article-toc summary { color: #369b72; font-weight: 600; cursor: pointer; min-height: 24px; } +.article-toc summary { color: #2a7a5a; font-weight: 600; cursor: pointer; min-height: 24px; } .article-toc > ul { margin-bottom: 0; } .learn-banner, .learn-callout { display: flex; align-items: center; gap: 16px; margin: 18px 0; padding: 16px 18px; border: 1px solid #e3e6e4; border-left: 4px solid var(--theme-color); border-radius: 10px; background: #fafbfa; color: inherit; text-decoration: none !important; } .learn-banner:hover, .learn-banner:focus-visible, .learn-callout:hover, .learn-callout:focus-visible { border-color: var(--theme-color); background: #eef7f2; } .learn-banner-text { flex: 1; min-width: 0; } .learn-banner b, .learn-callout b { display: block; color: var(--theme-color); font-size: 16px; } -.learn-banner-text span, .learn-callout span { display: block; margin-top: 2px; font-size: 14px; line-height: 1.6; opacity: .85; } +.learn-banner-text span, .learn-callout span { display: block; margin-top: 2px; font-size: 14px; line-height: 1.6; color: #34495e; } .learn-banner-go { flex: none; padding: 7px 18px; border-radius: 8px; background: var(--theme-color); color: #fff; font-weight: 600; font-size: 15px; } .learn-callout { display: block; } .learn-practice { margin-top: 36px; } @@ -90,5 +94,23 @@ body { color: #34495e; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI /* 步骤动图的播放器 */ .anim-bar { display: flex; justify-content: center; align-items: center; gap: 8px; margin: 6px 0 4px; } .anim-bar button { min-height: 30px; padding: 2px 12px; border: 1px solid #dfe3da; border-radius: 6px; background: #fafbf8; color: #34495e; font: inherit; font-size: 13px; cursor: pointer; } -.anim-bar button:hover, .anim-bar button:focus-visible { border-color: #369b72; color: #369b72; } +.anim-bar button:hover, .anim-bar button:focus-visible { border-color: #2a7a5a; color: #2a7a5a; } .anim-count { min-width: 44px; color: #718078; font-size: 12px; font-variant-numeric: tabular-nums; } + +/* 代码高亮:在 #f8f8f8 底上对比度不低于 4.5:1 */ +.markdown-section code { color: #9a3f2a; } +.token.comment, .token.prolog, .token.doctype, .token.cdata { color: #646e69; } +.token.keyword, .token.function { color: #a3501b; } +.token.string, .token.attr-value { color: #2a7a52; } +.token.number, .token.boolean { color: #9b5a14; } +.token.namespace { opacity: 1; color: #58635d; } +.token.tag, .token.attr-name, .token.variable, .token.placeholder { color: #2d6b9a; } +.token.important { color: #a8401c; } +.token.entity, .token.control, .token.directive, .token.unit { color: #17788a; } +.token.selector { color: #5a52a3; } +.token.property { color: #7f6212; } +.token.atrule, .token.regex, .token.statement, .token.url { color: #17788a; } +.learn-q-label { background: #e7f1eb; } +/* 首页贡献者头像:链接按图片大小计算点击区域 */ +.markdown-section > a:has(> img) { display: inline-block; margin: 2px; } +.markdown-section > a > img[src*="avatars"] { aspect-ratio: 1; } From 7b5a60f221b01412a0890b2ed052ae82af3e5eed Mon Sep 17 00:00:00 2001 From: CyC2018 Date: Sun, 1 Nov 2026 11:33:43 +0800 Subject: [PATCH 2/4] Update site.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 配图没有说明时用所在小节的标题作为替代文字;复制按钮的 aria-hidden 设为 true;文章第一张图直接加载;小节下的面试题在渲染时加入。 --- website/templates/site.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/website/templates/site.js b/website/templates/site.js index ddddfa16..53a01fb9 100644 --- a/website/templates/site.js +++ b/website/templates/site.js @@ -5,14 +5,29 @@ function encodedRoute(path) { return path.split('/').map(encodeURIComponent).join('/'); } function configureImages(root, homepage) { if (!root) return; + var first = root.querySelector('img'); root.querySelectorAll('img').forEach(function (img) { if (homepage && img.classList.contains('site-logo')) { img.loading = 'eager'; img.setAttribute('fetchpriority', 'high'); } else if (!img.hasAttribute('loading')) { - img.loading = 'lazy'; + // 文章的第一张图常在首屏内,延迟加载会推迟最大内容绘制,直接加载 + img.loading = !homepage && img === first ? 'eager' : 'lazy'; } img.decoding = 'async'; + // 笔记中的配图大多没写说明,读屏软件只能读出文件名;用所在小节的标题作为说明 + if (!img.hasAttribute('alt')) { + var heading = null; + for (var node = img; node && node !== root && !heading; node = node.previousElementSibling || node.parentElement) { + if (/^H[1-6]$/.test(node.tagName) && node !== img) heading = node; + } + var title = heading ? heading.textContent.replace(/[#¶]/g, '').trim() : ''; + img.alt = title ? title + (/[!-~]$/.test(title) ? ' ' : '') + '的配图' : '配图'; + } + }); + // 复制代码插件写的 aria-hidden="hidden" 不是有效值;插件的按钮在本插件之后才加上 + setTimeout(function () { + root.querySelectorAll('.docsify-copy-code-button [aria-hidden="hidden"]').forEach(function (node) { node.setAttribute('aria-hidden', 'true'); }); }); } function preserveLegacyLinks() { @@ -258,7 +273,7 @@ if (!section || !sections || section.querySelector('.learn-q')) return; var record = learnRecord(), today = localDay(); Object.keys(sections).forEach(function (anchor) { - var heading = document.getElementById(anchor), list = sections[anchor]; + var heading = (section.ownerDocument || document).getElementById(anchor), list = sections[anchor]; if (!heading || !section.contains(heading) || !/^H[2-6]$/.test(heading.tagName)) return; var tried = record ? list.filter(function (q) { return record.cards[q[0]]; }) : []; var due = tried.filter(function (q) { var c = record.cards[q[0]]; return c.due && c.due <= today; }).length; @@ -318,6 +333,7 @@ list.replaceWith(details); details.appendChild(list); } + sectionQuestions(vm, document.body); return document.body.innerHTML + ''; }); hook.doneEach(function () { From 8143eabbc5f43f42bcab2205300a63589c7aa5b9 Mon Sep 17 00:00:00 2001 From: CyC2018 Date: Sun, 1 Nov 2026 11:33:43 +0800 Subject: [PATCH 3/4] Update index.html MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 脚本改为 defer,先显示载入提示。 --- website/templates/index.html | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/website/templates/index.html b/website/templates/index.html index 6300c850..913dabcd 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -13,17 +13,17 @@
正在载入 CS-Notes…
- - - - - - - - - - - - + + + + + + + + + + + + From e139cabc4a08a6ea75c73d30611b59ac01873ed7 Mon Sep 17 00:00:00 2001 From: CyC2018 Date: Sun, 1 Nov 2026 11:33:43 +0800 Subject: [PATCH 4/4] Update verify_updates.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 没有可替换的 PNG 时用同类型的图片做替换测试。 --- website/builder/verify_updates.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/website/builder/verify_updates.py b/website/builder/verify_updates.py index 288137d4..c17143af 100644 --- a/website/builder/verify_updates.py +++ b/website/builder/verify_updates.py @@ -30,8 +30,10 @@ assert result.returncode == 0, result.stderr assert digest(OUTPUT / 'asset-manifest.json') == first_manifest, '相同输入的两次构建不一致' report = json.loads((BASE / 'dist-report.json').read_text()) -url, image = next((url, path) for url, path in report['imageReplacements'].items() - if path.startswith('/notes/pics/') and path.endswith('.png')) +# 优先选 PNG;笔记的旧外链图片都已重画为本地 PNG 时,剩下的多是 GIF,用同类型的图片替换 +candidates = [(url, path) for url, path in report['imageReplacements'].items() if path.startswith('/notes/pics/')] +url, image = next((item for item in candidates if item[1].endswith('.png')), candidates[0]) +suffix = Path(image).suffix image_name = unquote(image).lstrip('/') note = next(path for path in (SOURCE / 'notes').glob('*.md') if url in path.read_text()) note_name = note.relative_to(SOURCE) @@ -44,7 +46,7 @@ with tempfile.TemporaryDirectory(prefix='.update-check-', dir=BASE) as temp: shutil.copytree(SOURCE, source) with (source / note_name).open('a') as handle: handle.write('\n\n## 本地验证更新\n\n本地同步验证示例词:这是未上传的更新测试。\n') - replacement = next(path for path in (SOURCE / 'notes/pics').glob('*.png') if digest(path) != original_image) + replacement = next(path for path in (SOURCE / 'notes/pics').glob('*' + suffix) if digest(path) != original_image) shutil.copyfile(replacement, source / image_name) shutil.copyfile(replacement, source / 'notes/pics/local-validation-new.png') (source / 'notes/本地新增验证.md').write_text('# 本地新增验证\n\n仅在测试副本中生成。\n\n![新图片](pics/local-validation-new.png)\n')