Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 63 additions & 87 deletions assets/highlight.css
Original file line number Diff line number Diff line change
@@ -1,103 +1,79 @@
:root {
--code-fg: #BD976A;
--keyword: #4D9375;
--variable: #BD976A;
--comment: #758575DD;
--operator: #666666;
--string: #C98A7D;
--number: #4C9A91;
--function: #CB7676;
--bracket: #93aa9e;
/* Light Mode Syntax Tokens (GitHub Light inspired) */
--hl-fg: #24292f;
--hl-keyword: #cf222e; /* Red */
--hl-variable: #953800; /* Orange */
--hl-comment: #6e7781; /* Gray */
--hl-operator: #24292f; /* Dark Gray */
--hl-string: #0a3069; /* Dark Blue */
--hl-number: #0550ae; /* Blue */
--hl-function: #8250df; /* Purple */
--hl-bracket: #24292f;
--hl-constant: #0550ae;
}

@media (prefers-color-scheme: dark) {
:root {
/* Dark Mode Syntax Tokens (GitHub Dark inspired) */
--hl-fg: #c9d1d9;
--hl-keyword: #ff7b72; /* Coral */
--hl-variable: #ffa657; /* Orange */
--hl-comment: #8b949e; /* Gray */
--hl-operator: #c9d1d9; /* Light Gray */
--hl-string: #a5d6ff; /* Light Blue */
--hl-number: #79c0ff; /* Blue */
--hl-function: #d2a8ff; /* Purple */
--hl-bracket: #c9d1d9;
--hl-constant: #79c0ff;
}
}

code {
color: var(--code-fg);
color: var(--hl-fg);
}

code.zig, code.javascript, code.c, code.cpp, code.zon, code.go{
color: var(--code-fg);
.keyword, .keyword_modifier, .type_builtin, .keyword_type, .keyword_return, .keyword_conditional, .keyword_repeat, .keyword_operator, .constant_builtin, .keyword_exception, .type{
color: var(--keyword);
}
.variable, .function_builtin{
color: var(--variable);
}
.comment{
color: var(--comment);
}
.operator, .punctuation{
color: var(--operator);
}
.string, .character{
color: var(--string);
}
.number{
color: var(--number);
}
.keyword_function, .punctuation_delimiter, .function{
color: var(--function);
}
.punctuation_bracket{
color: var(--bracket);
}
/* General Syntax Highlighting */
.keyword, .keyword_modifier, .type_builtin, .keyword_type, .keyword_return, .keyword_conditional, .keyword_repeat, .keyword_operator, .keyword_exception, .type, .storage, .tag {
color: var(--hl-keyword);
}

code.conf{
color: var(--code-fg);
.function{
color: var(--function);
}
.punctuation_bracket{
color: var(--bracket);
}
.variable, .function_builtin, .attr-name {
color: var(--hl-variable);
}

code.diff{
color: var(--code-fg);
.addition, .string{
color: #4D9375;
}
.deletion, .keyword{
color: #CB7676;
}
.comment, .prolog, .doctype, .cdata {
color: var(--hl-comment);
font-style: italic;
}

/* TODO 分词器太烂了 */
code.bash {
color: var(--code-fg);
.comment {
color: var(--comment);
font-style: italic;
}
span.operator {
color: var(--operator);
}
.constant {
color: var(--number);
}
.string {
color: var(--string);
}
.function {
color: var(--function);
}
.operator, .punctuation, .punctuation_delimiter {
color: var(--hl-operator);
}

code.json{
color: var(--code-fg);
.constant_builtin{
color: var(--keyword);
}
span.string_special_key{
color: var(--string)
}
.string{
color: var(--function)
}
.string, .character, .attr-value {
color: var(--hl-string);
}

@media (prefers-color-scheme: light) {
code{
filter: brightness(0.8) contrast(1.5);
}
}
.number, .constant_builtin, .constant, .boolean {
color: var(--hl-number);
}

.function, .keyword_function, .method {
color: var(--hl-function);
}

.punctuation_bracket, .bracket {
color: var(--hl-bracket);
}

/* Language Specific Overrides if needed */
code.diff .addition { color: #1a7f37; } /* Green */
code.diff .deletion { color: #cf222e; } /* Red */

@media (prefers-color-scheme: dark) {
code.diff .addition { color: #3fb950; }
code.diff .deletion { color: #ff7b72; }
}

/* Bash specific adjustments */
code.bash .constant { color: var(--hl-variable); }
4 changes: 4 additions & 0 deletions assets/icons/search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 1 addition & 5 deletions assets/index.css
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
.content{
font-size: 1.2rem;
display: flex;
flex-direction: column;
}
/* Deprecated: Styles moved to style.css */
45 changes: 45 additions & 0 deletions assets/js/code-block.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
document.addEventListener('DOMContentLoaded', () => {
const codeBlocks = document.querySelectorAll('pre code');

codeBlocks.forEach((code) => {
const preElement = code.parentNode;
if (preElement.tagName !== 'PRE') return;

const codeContainer = document.createElement('div');
codeContainer.className = 'code-block-container';
preElement.parentNode.insertBefore(codeContainer, preElement);
codeContainer.appendChild(preElement);

const copyButton = document.createElement('button');
copyButton.className = 'copy-code-btn';
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>';
codeContainer.appendChild(copyButton);

copyButton.addEventListener('click', () => {
const codeText = code.textContent;
navigator.clipboard.writeText(codeText).then(() => {
copyButton.classList.add('copied');
setTimeout(() => { copyButton.classList.remove('copied'); }, 2000);
}).catch(err => {
console.error('无法复制到剪贴板:', err);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message "无法复制到剪贴板:" is hardcoded in Chinese. For better internationalization and maintainability, consider externalizing this string for localization or providing it in English as a default.

});
});

const codeLines = code.textContent.split(/\r?\n/);
const hasTrailingEmptyLine = codeLines.length > 0 && codeLines[codeLines.length - 1].trim() === '';
if (hasTrailingEmptyLine) {
codeLines.pop();
}

if (codeLines.length > 0) {
const lineNumbersContainer = document.createElement('div');
lineNumbersContainer.className = 'line-numbers';
for (let i = 1; i <= codeLines.length; i++) {
const lineNumber = document.createElement('span');
lineNumber.innerText = i;
lineNumbersContainer.appendChild(lineNumber);
}
preElement.insertBefore(lineNumbersContainer, code);
}
});
});
60 changes: 60 additions & 0 deletions assets/js/toc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
document.addEventListener('DOMContentLoaded', () => {
const tocLinks = document.querySelectorAll('.toc-sticky a');

// Find all headings within main-content
// We query all headings first, then filter/map to find the actual anchor ID
const rawHeadings = document.querySelectorAll('.main-content h1, .main-content h2, .main-content h3, .main-content h4, .main-content h5, .main-content h6');

const headings = Array.from(rawHeadings)
.map(h => ({
element: h,
id: h.id || h.parentElement?.id || h.querySelector('[id]')?.id,
}))
.filter(h => h.id);

if (tocLinks.length === 0 || headings.length === 0) return;

const onScroll = () => {
let currentId = null;
const scrollPosition = window.scrollY + 120; // Offset for header + padding

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The offset value 120 is a magic number. It would be more maintainable and readable if this value were defined as a named constant or retrieved from a CSS variable, especially since it's described as an "Offset for header + padding".


// Find the last heading that is above the current scroll position
for (const h of headings) {
if (h.element.offsetTop <= scrollPosition) {
currentId = h.id;
} else {
break; // Since headings are in order, we can stop
}
}

if (currentId) {
tocLinks.forEach(link => {
link.classList.remove('active');
const href = link.getAttribute('href');
if (href === `#${currentId}`) {
link.classList.add('active');
}
});
} else {
// If no header is "current" (e.g. at very top), highlight the first one
if (window.scrollY < 100 && tocLinks.length > 0) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The scroll threshold 100 is a magic number. Similar to the 120 offset, it would improve maintainability and clarity if this value were defined as a named constant or derived from a CSS variable.

tocLinks.forEach(link => link.classList.remove('active'));
tocLinks[0].classList.add('active');
}
}
};

// Throttle scroll event slightly for performance
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
window.requestAnimationFrame(() => {
onScroll();
ticking = false;
});
ticking = true;
}
});

onScroll(); // Initial check
});
Loading