mirror of
https://github.com/CyC2018/Interview-Notebook.git
synced 2026-11-02 20:33:42 +00:00
Merge pull request #1518 from CyC2018/site-load-a11y-v2
Update website loading and accessibility
This commit is contained in:
@@ -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\n')
|
||||
|
||||
@@ -13,17 +13,17 @@
|
||||
<body>
|
||||
<div id="app">正在载入 CS-Notes…</div>
|
||||
<noscript>请启用 JavaScript 阅读网站,或访问 <a href="https://github.com/CyC2018/CS-Notes">GitHub 仓库</a>。</noscript>
|
||||
<script src="/search-paths.js"></script>
|
||||
<script src="/site.js"></script>
|
||||
<script src="/search.js"></script>
|
||||
<script src="/vendor/docsify.min.js"></script>
|
||||
<script src="/vendor/docsify-copy-code.min.js"></script>
|
||||
<script src="/vendor/zoom-image.min.js"></script>
|
||||
<script src="/vendor/prism-bash.min.js"></script>
|
||||
<script src="/vendor/prism-c.min.js"></script>
|
||||
<script src="/vendor/prism-java.min.js"></script>
|
||||
<script src="/vendor/prism-sql.min.js"></script>
|
||||
<script src="/vendor/prism-python.min.js"></script>
|
||||
<script src="/vendor/prism-json.min.js"></script>
|
||||
<script src="/search-paths.js" defer></script>
|
||||
<script src="/site.js" defer></script>
|
||||
<script src="/search.js" defer></script>
|
||||
<script src="/vendor/docsify.min.js" defer></script>
|
||||
<script src="/vendor/docsify-copy-code.min.js" defer></script>
|
||||
<script src="/vendor/zoom-image.min.js" defer></script>
|
||||
<script src="/vendor/prism-bash.min.js" defer></script>
|
||||
<script src="/vendor/prism-c.min.js" defer></script>
|
||||
<script src="/vendor/prism-java.min.js" defer></script>
|
||||
<script src="/vendor/prism-sql.min.js" defer></script>
|
||||
<script src="/vendor/prism-python.min.js" defer></script>
|
||||
<script src="/vendor/prism-json.min.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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 + '<footer class="site-footer"><a href="https://github.com/CyC2018/CS-Notes" target="_blank" rel="noopener">CyC2018 · CS-Notes</a><span> · </span><a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener">粤ICP备19071404号-1</a></footer>';
|
||||
});
|
||||
hook.doneEach(function () {
|
||||
|
||||
Reference in New Issue
Block a user