Skip to content

Commit 8abfa1b

Browse files
committed
refactor: update mkdocs toolchain
1 parent 5db5f24 commit 8abfa1b

29 files changed

+1177
-724
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ docs/assets/images/writeups/AAA
99
docs/cs/pl/asm_int_list
1010

1111
# cached files of tikzautomata plugin
12-
cache/
12+
cache/
13+
14+
__pycache__/

docs/changelog.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
- "2025":
2+
- "2025-08-06":
3+
- refactor: 全面更新 mkdocs 工具链,采用规范化配置与 hooks
24
- "2025-07-12":
35
- pageupdate:
46
text: Web > 网络运维 > 内网穿透与反向代理(添加了 atrust 及正向代理)

docs/css/custom.css

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
--md-code-fg-color: var(--md-typeset-color);
6363
}
6464

65-
[data-md-color-scheme="slate"] {
65+
[data-md-color-scheme="slate"][data-md-color-primary="indigo"] {
6666
--md-default-bg-color: #161616;
6767
--md-default-bg-color--light: #161616;
6868
--md-default-bg-color--lighter: #161616;
@@ -267,4 +267,12 @@ input#mkdocs-content-password {
267267

268268
.toc-tag-reports::before {
269269
content: "实验报告"
270-
}
270+
}
271+
272+
.md-source-file__fact {
273+
font-size: 90%;
274+
}
275+
276+
.hr-before-source-file:not(:has(+ aside)) {
277+
display: none;
278+
}

docs/css/svg_extra.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
path[stroke="#000"], g[stroke="#000"] {
2+
stroke: var(--md-default-fg-color);
3+
}
4+
5+
path[stroke="#fff"], g[stroke="#fff"] {
6+
stroke: var(--md-default-bg-color);
7+
}
8+
9+
path[fill="#fff"] {
10+
fill: var(--md-default-bg-color);
11+
}
12+
13+
path:not([fill]) {
14+
fill: var(--md-default-fg-color);
15+
}

docs/css/toc_extra.css

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
:root {
2+
--toc-plugin-title-bg: rgba(255, 255, 255, 0.05);
3+
--toc-plugin-button-hover: rgba(255, 255, 255, 0.1);
4+
--toc-plugin-border: rgba(255, 255, 255, 0.15);
5+
}
6+
7+
[data-md-color-scheme="default"] {
8+
--toc-plugin-title-bg: rgba(0, 0, 0, 0.05);
9+
--toc-plugin-button-hover: rgba(0, 0, 0, 0.1);
10+
--toc-plugin-border: rgba(0, 0, 0, 0.15);
11+
}
12+
13+
.index-item-wrapper {
14+
border: 1px solid var(--toc-plugin-border);
15+
border-radius: 6px;
16+
}
17+
.title-wrapper {
18+
padding: 10px 14px;
19+
display: flex;
20+
justify-content: space-between;
21+
background-color: var(--toc-plugin-title-bg);
22+
}
23+
.title-wrapper:first-child {
24+
border-top: 0px;
25+
border-top-left-radius: 6px;
26+
border-top-right-radius: 6px;
27+
}
28+
.title-wrapper button {
29+
font-size: 1.12em;
30+
color: var(--md-typeset-color);
31+
display: flex;
32+
align-items: center;
33+
padding: 3px;
34+
padding-left: 8px;
35+
padding-right: 8px;
36+
border-radius: 6px;
37+
}
38+
.title-wrapper button:hover:not(:active) {
39+
background-color: var(--toc-plugin-button-hover);
40+
}
41+
.title-wrapper button:active {
42+
background-color: transparent;
43+
}
44+
.content-item-wrapper {
45+
margin: 0px !important;
46+
padding: 0px !important;
47+
}
48+
.content-item-wrapper li {
49+
display: grid;
50+
grid-template: "selection status primary metadata actions" auto "selection status main-content metadata actions" auto / min-content min-content minmax(7em, 1fr) minmax(0px, max-content) minmax(8em, max-content);
51+
gap: 4px;
52+
margin-left: 0 !important;
53+
margin-bottom: 0 !important;
54+
}
55+
.content-item-wrapper li:not(:last-child) {
56+
border-bottom: 1px solid var(--toc-plugin-border);
57+
border-top-color: var(--toc-plugin-border);
58+
border-right-color: var(--toc-plugin-border);
59+
border-left-color: var(--toc-plugin-border);
60+
}
61+
.item-primary {
62+
grid-area: primary;
63+
padding-top: 4px;
64+
}
65+
.item-primary a {
66+
color: var(--md-typeset-color);
67+
}
68+
.item-status {
69+
grid-area: status;
70+
padding-left: 13px;
71+
}
72+
.item-main-content {
73+
grid-area: main-content;
74+
font-size: 0.8em;
75+
margin-top: -3px;
76+
padding-bottom: 3px;
77+
opacity: 0.6;
78+
}
79+
.item-metadata {
80+
grid-area: metadata;
81+
display: flex;
82+
align-items: center;
83+
padding-right: 4px;
84+
}
85+
.note-tag {
86+
border: 1px solid #e6ad5b;
87+
color: #e6ad5b;
88+
border-radius: 0.9em;
89+
font-size: 0.9em;
90+
padding: 0px 8px;
91+
}
92+
.note-tag::before {
93+
content: "课程笔记";
94+
}
95+
.lab-tag {
96+
border: 1px solid #3f6ec6;
97+
color: #3f6ec6;
98+
border-radius: 0.9em;
99+
font-size: 0.9em;
100+
padding: 0px 8px;
101+
margin-left: 4px;
102+
}
103+
.lab-tag::before {
104+
content: "实验报告";
105+
}
106+
.item-actions, .item-lock {
107+
grid-area: actions;
108+
padding-right: 14px;
109+
display: flex;
110+
align-items: center;
111+
font-size: 0.9em;
112+
justify-content: flex-end;
113+
}
114+
@media screen and (max-width: 510px) {
115+
.note-tag {
116+
border: 5px solid #e6ad5b;
117+
color: #e6ad5b;
118+
border-radius: 0.9em;
119+
font-size: 0.9em;
120+
padding: 0px 0px;
121+
}
122+
.lab-tag {
123+
border: 5px solid #3f6ec6;
124+
color: #3f6ec6;
125+
border-radius: 0.9em;
126+
font-size: 0.9em;
127+
padding: 0px 0px;
128+
margin-left: 4px;
129+
}
130+
.note-tag::before {
131+
content: none;
132+
}
133+
.lab-tag::before {
134+
content: none;
135+
}
136+
}

docs/js/katex.js

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,38 @@
11
(function () {
2-
'use strict';
3-
4-
var katexMath = (function () {
5-
var maths = document.querySelectorAll('.arithmatex'),
6-
tex;
7-
8-
for (var i = 0; i < maths.length; i++) {
9-
tex = maths[i].textContent || maths[i].innerText;
10-
if (tex.startsWith('\\(') && tex.endsWith('\\)')) {
11-
katex.render(tex.slice(2, -2), maths[i], {'displayMode': false});
12-
} else if (tex.startsWith('\\[') && tex.endsWith('\\]')) {
13-
katex.render(tex.slice(2, -2), maths[i], {'displayMode': true});
2+
'use strict';
3+
4+
var katexMath = (function () {
5+
var maths = document.querySelectorAll('.arithmatex'),
6+
tex;
7+
8+
for (var i = 0; i < maths.length; i++) {
9+
tex = maths[i].textContent || maths[i].innerText;
10+
if (tex.startsWith('\\(') && tex.endsWith('\\)')) {
11+
katex.render(tex.slice(2, -2), maths[i], {'displayMode': false});
12+
} else if (tex.startsWith('\\[') && tex.endsWith('\\]')) {
13+
katex.render(tex.slice(2, -2), maths[i], {'displayMode': true});
14+
}
15+
}
16+
});
17+
18+
(function () {
19+
var onReady = function onReady(fn) {
20+
if (document.addEventListener) {
21+
document.addEventListener("DOMContentLoaded", fn);
22+
} else {
23+
document.attachEvent("onreadystatechange", function () {
24+
if (document.readyState === "interactive") {
25+
fn();
1426
}
15-
}
27+
});
28+
}
29+
};
30+
31+
onReady(function () {
32+
if (typeof katex !== "undefined") {
33+
katexMath();
34+
}
1635
});
17-
18-
(function () {
19-
var onReady = function onReady(fn) {
20-
if (document.addEventListener) {
21-
document.addEventListener("DOMContentLoaded", fn);
22-
} else {
23-
document.attachEvent("onreadystatechange", function () {
24-
if (document.readyState === "interactive") {
25-
fn();
26-
}
27-
});
28-
}
29-
};
30-
31-
onReady(function () {
32-
if (typeof katex !== "undefined") {
33-
katexMath();
34-
}
35-
});
36-
})();
37-
38-
}());
36+
})();
37+
}());
3938

docs/js/scheme.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
document.querySelector("body").setAttribute("data-md-color-scheme", (e.matches) ? "slate" : "default")
66
}
77
var frame = document.querySelector(".giscus-frame")
8-
var theme = document.querySelector("body").getAttribute("data-md-color-scheme") === "slate" ? "https://gcore.jsdelivr.net/gh/TonyCrane/note/docs/css/giscus.css" : "light"
8+
var theme = document.querySelector("body").getAttribute("data-md-color-scheme") === "slate" ? "transparent_dark" : "light"
99
frame.contentWindow.postMessage(
1010
{ giscus: { setConfig: { theme } } },
1111
"https://giscus.app"
@@ -90,7 +90,7 @@ window.toggleScheme = () => {
9090
body.setAttribute("data-md-color-scheme", scheme)
9191

9292
var frame = document.querySelector(".giscus-frame")
93-
var theme = scheme === "slate" ? "https://gcore.jsdelivr.net/gh/TonyCrane/note/docs/css/giscus.css" : "light"
93+
var theme = scheme === "slate" ? "transparent_dark" : "light"
9494
frame.contentWindow.postMessage(
9595
{ giscus: { setConfig: { theme } } },
9696
"https://giscus.app"

hooks/linkbackward.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import os
2+
import re
3+
import logging
4+
5+
from typing import Any, Dict
6+
7+
enabled = os.getenv("LINKBACKWARD", "0") == "1" or os.getenv("FULL", "0") == "true"
8+
logger = logging.getLogger("mkdocs.hooks.linkbackward")
9+
10+
if enabled:
11+
logger.info("hook - linkbackward is loaded and enabled")
12+
else:
13+
logger.info("hook - linkbackward is disabled")
14+
15+
WAIT_TIME = 0
16+
REDIRS = [
17+
("/ctf/steg/", "/ctf/misc/steg/"),
18+
("/ctf/steg/image/", "/ctf/misc/steg/image/"),
19+
("/ctf/steg/audio/", "/ctf/misc/steg/audio/"),
20+
("/ctf/escapes/", "/ctf/misc/escapes/"),
21+
("/ctf/escapes/pysandbox/", "/ctf/misc/escapes/pysandbox/"),
22+
("/ctf/forensics/", "/ctf/misc/forensics/"),
23+
("/ctf/forensics/mem/", "/ctf/misc/forensics/mem/"),
24+
("/ctf/coding/", "/ctf/misc/coding/"),
25+
("/ctf/qrcode/", "/ctf/misc/qrcode/"),
26+
("/ctf/esolang/", "/ctf/misc/esolang/"),
27+
("/cs/pl/c_cpp/", "/cs/pl/c_cpp/c/"),
28+
("/hpc/", "/cs/hpc/hpc101/"),
29+
("/hpc/hpc101/vectorized/", "/cs/hpc/hpc101/vectorized/"),
30+
("/hpc/hpc101/gpu/", "/cs/hpc/hpc101/gpu/"),
31+
("/hpc/hpc101/openmp/", "/cs/hpc/hpc101/openmp/"),
32+
("/hpc/hpc101/mpi/", "/cs/hpc/hpc101/mpi/"),
33+
("/hpc/hpc101/ml/", "/cs/hpc/hpc101/ml/"),
34+
]
35+
36+
37+
redirs = []
38+
for src, dst in REDIRS:
39+
if not src.startswith("/"):
40+
src = "/" + src[1:]
41+
if not dst.startswith("/"):
42+
dst = "/" + dst[1:]
43+
if src.endswith("/"):
44+
src += "index.html"
45+
if dst.endswith("/"):
46+
dst += "index.html"
47+
if not src.endswith(".htm") and not src.endswith(".html"):
48+
src += "/index.html"
49+
if not dst.endswith(".htm") and not dst.endswith(".html"):
50+
dst += "/index.html"
51+
redirs.append((src, dst))
52+
logger.debug(f"Redirect: `{src}` -> `{dst}`")
53+
54+
55+
def on_post_build(config: Dict[str, Any], **kwargs) -> None:
56+
if not enabled:
57+
return
58+
site_dir = config["site_dir"]
59+
template_file_path = os.path.join(site_dir, "redirection.html")
60+
with open(template_file_path, "r", encoding="utf-8") as f:
61+
template = f.read()
62+
for src, dst in redirs:
63+
if os.path.exists(os.path.join(site_dir, src[1:])):
64+
logger.warning(
65+
f"Skip creating redirection file `{src}` because it already exists"
66+
)
67+
continue
68+
if not os.path.exists(os.path.join(site_dir, dst[1:])):
69+
logger.warning(
70+
f"Skip creating redirection file `{src}` because the dest `{dst}` does not exist"
71+
)
72+
continue
73+
logger.debug(f"Creating redirection file `{src}` -> `{dst}`")
74+
src_file = re.sub(
75+
r"\./",
76+
"../" * src.count("/"),
77+
template,
78+
)
79+
src_file = re.sub(
80+
r"//old//",
81+
src.replace("index.html", ""),
82+
src_file,
83+
)
84+
src_file = re.sub(
85+
r"//new//",
86+
dst.replace("index.html", ""),
87+
src_file,
88+
)
89+
src_file = re.sub(
90+
r"//wait_time//",
91+
str(WAIT_TIME),
92+
src_file,
93+
)
94+
if WAIT_TIME == 0:
95+
src_file = re.sub(
96+
"<script>",
97+
f"<script>window.location='{dst.replace('index.html', '')}';",
98+
src_file,
99+
)
100+
os.makedirs(os.path.dirname(os.path.join(site_dir, src[1:])), exist_ok=True)
101+
with open(os.path.join(site_dir, src[1:]), "w", encoding="utf-8") as f:
102+
f.write(src_file)

0 commit comments

Comments
 (0)