Skip to content

Commit bc605ac

Browse files
authored
Reflector UI (#92)
* ui: implement site-wide redesign and layout restructuring * refactor: standardize SuperMD syntax and style updates * ui: refine TOC appearance and remove heading underlines * refactor: standardize monthly post structure and clean up titles * ui: implement TOC fallback for small screens and robust hiding logic * refactor: modernize UI and standardize content hierarchy - UI/UX Refinement: Removed 'TOC' titles, simplified active states, removed heading underlines. - Mobile Support: Added a robust TOC fallback for small screens with auto-hide logic. - Content Overhaul: Standardized monthly post hierarchy (##/###) and adopted $section.id. - Cleanup: Link normalization, title date stripping, and removal of build artifacts. - Bug Fixes: Addressed review feedback and fixed script comment conversion errors. * refactor(js): improve robustness of line numbering and TOC anchoring * feat(search): implement full-text search with Pagefind * refactor(layout): optimize pagefind indexing and metadata * refactor(content): migrate section ids and standardize frontmatter * refactor(search): optimize implementation - Restore missing CSS link in search layout - Use defer for script loading to improve performance - Refactor CSS to remove !important usage by increasing specificity - Improve Pagefind initialization logic * refactor(ui): unify date format and improve accessibility * refactor(ui): add security rel to external links and cleanup CSS
1 parent d995ea9 commit bc605ac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2152
-744
lines changed

assets/highlight.css

Lines changed: 63 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,79 @@
11
:root {
2-
--code-fg: #BD976A;
3-
--keyword: #4D9375;
4-
--variable: #BD976A;
5-
--comment: #758575DD;
6-
--operator: #666666;
7-
--string: #C98A7D;
8-
--number: #4C9A91;
9-
--function: #CB7676;
10-
--bracket: #93aa9e;
2+
/* Light Mode Syntax Tokens (GitHub Light inspired) */
3+
--hl-fg: #24292f;
4+
--hl-keyword: #cf222e; /* Red */
5+
--hl-variable: #953800; /* Orange */
6+
--hl-comment: #6e7781; /* Gray */
7+
--hl-operator: #24292f; /* Dark Gray */
8+
--hl-string: #0a3069; /* Dark Blue */
9+
--hl-number: #0550ae; /* Blue */
10+
--hl-function: #8250df; /* Purple */
11+
--hl-bracket: #24292f;
12+
--hl-constant: #0550ae;
13+
}
14+
15+
@media (prefers-color-scheme: dark) {
16+
:root {
17+
/* Dark Mode Syntax Tokens (GitHub Dark inspired) */
18+
--hl-fg: #c9d1d9;
19+
--hl-keyword: #ff7b72; /* Coral */
20+
--hl-variable: #ffa657; /* Orange */
21+
--hl-comment: #8b949e; /* Gray */
22+
--hl-operator: #c9d1d9; /* Light Gray */
23+
--hl-string: #a5d6ff; /* Light Blue */
24+
--hl-number: #79c0ff; /* Blue */
25+
--hl-function: #d2a8ff; /* Purple */
26+
--hl-bracket: #c9d1d9;
27+
--hl-constant: #79c0ff;
28+
}
1129
}
1230

1331
code {
14-
color: var(--code-fg);
32+
color: var(--hl-fg);
1533
}
1634

17-
code.zig, code.javascript, code.c, code.cpp, code.zon, code.go{
18-
color: var(--code-fg);
19-
.keyword, .keyword_modifier, .type_builtin, .keyword_type, .keyword_return, .keyword_conditional, .keyword_repeat, .keyword_operator, .constant_builtin, .keyword_exception, .type{
20-
color: var(--keyword);
21-
}
22-
.variable, .function_builtin{
23-
color: var(--variable);
24-
}
25-
.comment{
26-
color: var(--comment);
27-
}
28-
.operator, .punctuation{
29-
color: var(--operator);
30-
}
31-
.string, .character{
32-
color: var(--string);
33-
}
34-
.number{
35-
color: var(--number);
36-
}
37-
.keyword_function, .punctuation_delimiter, .function{
38-
color: var(--function);
39-
}
40-
.punctuation_bracket{
41-
color: var(--bracket);
42-
}
35+
/* General Syntax Highlighting */
36+
.keyword, .keyword_modifier, .type_builtin, .keyword_type, .keyword_return, .keyword_conditional, .keyword_repeat, .keyword_operator, .keyword_exception, .type, .storage, .tag {
37+
color: var(--hl-keyword);
4338
}
4439

45-
code.conf{
46-
color: var(--code-fg);
47-
.function{
48-
color: var(--function);
49-
}
50-
.punctuation_bracket{
51-
color: var(--bracket);
52-
}
40+
.variable, .function_builtin, .attr-name {
41+
color: var(--hl-variable);
5342
}
5443

55-
code.diff{
56-
color: var(--code-fg);
57-
.addition, .string{
58-
color: #4D9375;
59-
}
60-
.deletion, .keyword{
61-
color: #CB7676;
62-
}
44+
.comment, .prolog, .doctype, .cdata {
45+
color: var(--hl-comment);
46+
font-style: italic;
6347
}
6448

65-
/* TODO 分词器太烂了 */
66-
code.bash {
67-
color: var(--code-fg);
68-
.comment {
69-
color: var(--comment);
70-
font-style: italic;
71-
}
72-
span.operator {
73-
color: var(--operator);
74-
}
75-
.constant {
76-
color: var(--number);
77-
}
78-
.string {
79-
color: var(--string);
80-
}
81-
.function {
82-
color: var(--function);
83-
}
49+
.operator, .punctuation, .punctuation_delimiter {
50+
color: var(--hl-operator);
8451
}
8552

86-
code.json{
87-
color: var(--code-fg);
88-
.constant_builtin{
89-
color: var(--keyword);
90-
}
91-
span.string_special_key{
92-
color: var(--string)
93-
}
94-
.string{
95-
color: var(--function)
96-
}
53+
.string, .character, .attr-value {
54+
color: var(--hl-string);
9755
}
9856

99-
@media (prefers-color-scheme: light) {
100-
code{
101-
filter: brightness(0.8) contrast(1.5);
102-
}
103-
}
57+
.number, .constant_builtin, .constant, .boolean {
58+
color: var(--hl-number);
59+
}
60+
61+
.function, .keyword_function, .method {
62+
color: var(--hl-function);
63+
}
64+
65+
.punctuation_bracket, .bracket {
66+
color: var(--hl-bracket);
67+
}
68+
69+
/* Language Specific Overrides if needed */
70+
code.diff .addition { color: #1a7f37; } /* Green */
71+
code.diff .deletion { color: #cf222e; } /* Red */
72+
73+
@media (prefers-color-scheme: dark) {
74+
code.diff .addition { color: #3fb950; }
75+
code.diff .deletion { color: #ff7b72; }
76+
}
77+
78+
/* Bash specific adjustments */
79+
code.bash .constant { color: var(--hl-variable); }

assets/icons/search.svg

Lines changed: 4 additions & 0 deletions
Loading

assets/index.css

Lines changed: 0 additions & 5 deletions
This file was deleted.

assets/js/code-block.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
document.addEventListener('DOMContentLoaded', () => {
2+
const codeBlocks = document.querySelectorAll('pre code');
3+
4+
codeBlocks.forEach((code) => {
5+
const preElement = code.parentNode;
6+
if (preElement.tagName !== 'PRE') return;
7+
8+
const codeContainer = document.createElement('div');
9+
codeContainer.className = 'code-block-container';
10+
preElement.parentNode.insertBefore(codeContainer, preElement);
11+
codeContainer.appendChild(preElement);
12+
13+
const copyButton = document.createElement('button');
14+
copyButton.className = 'copy-code-btn';
15+
copyButton.setAttribute('aria-label', 'Copy code to clipboard');
16+
copyButton.setAttribute('title', 'Copy code');
17+
copyButton.innerHTML = '<svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>';
18+
codeContainer.appendChild(copyButton);
19+
20+
copyButton.addEventListener('click', () => {
21+
const codeText = code.textContent;
22+
navigator.clipboard.writeText(codeText).then(() => {
23+
copyButton.classList.add('copied');
24+
setTimeout(() => { copyButton.classList.remove('copied'); }, 2000);
25+
}).catch(err => {
26+
console.error('无法复制到剪贴板:', err);
27+
});
28+
});
29+
30+
const codeLines = code.textContent.split(/\r?\n/);
31+
const hasTrailingEmptyLine = codeLines.length > 0 && codeLines[codeLines.length - 1].trim() === '';
32+
if (hasTrailingEmptyLine) {
33+
codeLines.pop();
34+
}
35+
36+
if (codeLines.length > 0) {
37+
const lineNumbersContainer = document.createElement('div');
38+
lineNumbersContainer.className = 'line-numbers';
39+
for (let i = 1; i <= codeLines.length; i++) {
40+
const lineNumber = document.createElement('span');
41+
lineNumber.innerText = i;
42+
lineNumbersContainer.appendChild(lineNumber);
43+
}
44+
preElement.insertBefore(lineNumbersContainer, code);
45+
}
46+
});
47+
});

assets/js/toc.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
document.addEventListener('DOMContentLoaded', () => {
2+
const tocLinks = document.querySelectorAll('.toc-sticky a');
3+
4+
// Find all headings within main-content
5+
// We query all headings first, then filter/map to find the actual anchor ID
6+
const rawHeadings = document.querySelectorAll('.main-content h1, .main-content h2, .main-content h3, .main-content h4, .main-content h5, .main-content h6');
7+
8+
const headings = Array.from(rawHeadings)
9+
.map(h => ({
10+
element: h,
11+
id: h.id || h.parentElement?.id || h.querySelector('[id]')?.id,
12+
}))
13+
.filter(h => h.id);
14+
15+
if (tocLinks.length === 0 || headings.length === 0) return;
16+
17+
const onScroll = () => {
18+
let currentId = null;
19+
const scrollPosition = window.scrollY + 120; // Offset for header + padding
20+
21+
// Find the last heading that is above the current scroll position
22+
for (const h of headings) {
23+
if (h.element.offsetTop <= scrollPosition) {
24+
currentId = h.id;
25+
} else {
26+
break; // Since headings are in order, we can stop
27+
}
28+
}
29+
30+
if (currentId) {
31+
tocLinks.forEach(link => {
32+
link.classList.remove('active');
33+
const href = link.getAttribute('href');
34+
if (href === `#${currentId}`) {
35+
link.classList.add('active');
36+
}
37+
});
38+
} else {
39+
// If no header is "current" (e.g. at very top), highlight the first one
40+
if (window.scrollY < 100 && tocLinks.length > 0) {
41+
tocLinks.forEach(link => link.classList.remove('active'));
42+
tocLinks[0].classList.add('active');
43+
}
44+
}
45+
};
46+
47+
// Throttle scroll event slightly for performance
48+
let ticking = false;
49+
window.addEventListener('scroll', () => {
50+
if (!ticking) {
51+
window.requestAnimationFrame(() => {
52+
onScroll();
53+
ticking = false;
54+
});
55+
ticking = true;
56+
}
57+
}, { passive: true });
58+
59+
onScroll(); // Initial check
60+
});

0 commit comments

Comments
 (0)