Skip to content

Commit 4a11cbc

Browse files
committed
refactor
1 parent 1c85232 commit 4a11cbc

File tree

4 files changed

+273
-334
lines changed

4 files changed

+273
-334
lines changed

.blogrc.example

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Blog configuration example
2+
# Copy this file to .blogrc and customize
3+
4+
# Blog title
5+
export BLOG_TITLE="My Awesome Blog"
6+
7+
# Author information
8+
export BLOG_AUTHOR="Your Name"
9+
export BLOG_EMAIL="your.email@example.com"
10+
11+
# Enable incremental builds (only rebuild changed files)
12+
# export INCREMENTAL_BUILD=true
13+
14+
# Additional Emacs load paths (if you have custom elisp packages)
15+
# export EMACS_LOAD_PATH="/path/to/custom/packages"

build.sh

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55

66
set -euo pipefail
77

8+
# Configuration
9+
BLOG_TITLE="${BLOG_TITLE:-Noob Notes}"
10+
BLOG_AUTHOR="${BLOG_AUTHOR:-bytenoob}"
11+
BLOG_EMAIL="${BLOG_EMAIL:-noreply@example.com}"
12+
INCREMENTAL_BUILD="${INCREMENTAL_BUILD:-false}"
13+
814
# Source configuration if available
915
if [ -f ".blogrc" ]; then
1016
# shellcheck source=/dev/null
@@ -18,6 +24,11 @@ NC='\033[0m'
1824

1925
echo -e "${GREEN}Building blog...${NC}"
2026

27+
# Show incremental build option if not enabled
28+
if [ "$INCREMENTAL_BUILD" != "true" ]; then
29+
echo -e "${YELLOW}Tip:${NC} Use INCREMENTAL_BUILD=true $0 to skip unchanged files"
30+
fi
31+
2132
# Get version numbers for cache busting based on file modification time
2233
CSS_VERSION=$(stat -c %Y static/css/blog.css 2> /dev/null || stat -f %m static/css/blog.css 2> /dev/null || echo "1")
2334
JS_VERSION=$(stat -c %Y static/js/blog.js 2> /dev/null || stat -f %m static/js/blog.js 2> /dev/null || echo "1")
@@ -40,6 +51,7 @@ if emacs --batch \
4051
;; Set user info (use environment variables for security)
4152
(setq user-full-name (or (getenv \"BLOG_AUTHOR\") \"bytenoob\"))
4253
(setq user-mail-address (or (getenv \"BLOG_EMAIL\") \"noreply@example.com\"))
54+
(setq blog-title (or (getenv \"BLOG_TITLE\") \"Noob Notes\"))
4355
4456
;; Load org and ox-publish
4557
(require 'org)
@@ -94,12 +106,21 @@ if emacs --batch \
94106
;; If htmlize fails to load, continue without syntax highlighting
95107
(message \"Warning: htmlize not available, syntax highlighting disabled\")))
96108
109+
;; Common HTML head content
110+
(defun blog/html-head ()
111+
(concat \"<link rel=\\\"icon\\\" type=\\\"image/svg+xml\\\" href=\\\"/static/favicon.svg\\\">
112+
<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">
113+
<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>
114+
<link href=\\\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\\\" rel=\\\"stylesheet\\\">
115+
<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" href=\\\"/static/css/blog.css?v=\" (or (getenv \"CSS_VERSION\") \"1\") \"\\\" />
116+
<script src=\\\"/static/js/blog.js?v=\" (or (getenv \"JS_VERSION\") \"1\") \"\\\" defer></script>\"))
117+
97118
;; Custom HTML preamble and postamble
98119
(defun blog/preamble (info)
99120
(concat
100121
\"<header class=\\\"site-header\\\">\"
101122
\"<div class=\\\"container\\\">\"
102-
\"<h1 class=\\\"site-title\\\"><a href=\\\"/\\\">Noob Notes</a></h1>\"
123+
\"<h1 class=\\\"site-title\\\"><a href=\\\"/\\\">\" blog-title \"</a></h1>\"
103124
\"<nav class=\\\"site-nav\\\">\"
104125
\"<a href=\\\"/\\\">Home</a>\"
105126
\"<a href=\\\"/about.html\\\">About</a>\"
@@ -130,16 +151,31 @@ if emacs --batch \
130151
(goto-char (point-min))
131152
(re-search-forward \"^#\\\\+DRAFT:\\\\s-*\\\\(true\\\\|t\\\\|yes\\\\)\" nil t)))
132153
133-
;; Custom publishing function that skips drafts
154+
;; Function to check if file needs rebuilding
155+
(defun blog/needs-rebuild-p (org-file html-file)
156+
\"Check if ORG-FILE needs to be rebuilt by comparing with HTML-FILE.\"
157+
(or (not (file-exists-p html-file))
158+
(file-newer-than-file-p org-file html-file)
159+
(not (string= (getenv \"INCREMENTAL_BUILD\") \"true\"))))
160+
161+
;; Custom publishing function that skips drafts and unchanged files
134162
(defun blog/publish-to-html (plist filename pub-dir)
135-
\"Publish an org file to HTML, but skip if it's a draft.\"
163+
\"Publish an org file to HTML, but skip if it's a draft or unchanged.\"
136164
(unless (blog/is-draft-p filename)
137-
(org-html-publish-to-html plist filename pub-dir)))
165+
(let* ((html-file (concat pub-dir
166+
(file-name-sans-extension
167+
(file-name-nondirectory filename))
168+
\".html\")))
169+
(if (blog/needs-rebuild-p filename html-file)
170+
(progn
171+
(message \"Building: %s\" filename)
172+
(org-html-publish-to-html plist filename pub-dir))
173+
(message \"Skipping unchanged: %s\" filename)))))
138174
139175
;; Custom sitemap function to exclude author and draft posts
140176
(defun blog/sitemap-function (title list)
141177
\"Generate sitemap as an Org file without author metadata and draft posts.\"
142-
(concat \"#+TITLE: Noob Notes\\n\"
178+
(concat \"#+TITLE: \" blog-title \"\\n\"
143179
\"#+AUTHOR:\\n\"
144180
\"#+OPTIONS: author:nil toc:nil num:nil h:0\\n\\n\"
145181
(org-list-to-org list)))
@@ -157,12 +193,7 @@ if emacs --batch \
157193
:with-toc t
158194
:with-author t
159195
:with-date t
160-
:html-head ,(concat \"<link rel=\\\"icon\\\" type=\\\"image/svg+xml\\\" href=\\\"/static/favicon.svg\\\">
161-
<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">
162-
<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>
163-
<link href=\\\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\\\" rel=\\\"stylesheet\\\">
164-
<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" href=\\\"/static/css/blog.css?v=\" (or (getenv \"CSS_VERSION\") \"$CSS_VERSION\") \"\\\" />
165-
<script src=\\\"/static/js/blog.js?v=\" (or (getenv \"JS_VERSION\") \"$JS_VERSION\") \"\\\" defer></script>\")
196+
:html-head ,(blog/html-head)
166197
:html-preamble blog/preamble
167198
:html-postamble blog/postamble
168199
:html-head-include-default-style nil
@@ -190,12 +221,7 @@ if emacs --batch \
190221
:with-toc t
191222
:with-author t
192223
:with-date t
193-
:html-head ,(concat \"<link rel=\\\"icon\\\" type=\\\"image/svg+xml\\\" href=\\\"/static/favicon.svg\\\">
194-
<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">
195-
<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>
196-
<link href=\\\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\\\" rel=\\\"stylesheet\\\">
197-
<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" href=\\\"/static/css/blog.css?v=\" (or (getenv \"CSS_VERSION\") \"$CSS_VERSION\") \"\\\" />
198-
<script src=\\\"/static/js/blog.js?v=\" (or (getenv \"JS_VERSION\") \"$JS_VERSION\") \"\\\" defer></script>\")
224+
:html-head ,(blog/html-head)
199225
:html-preamble blog/preamble
200226
:html-postamble blog/postamble
201227
:html-head-include-default-style nil
@@ -224,10 +250,14 @@ if emacs --batch \
224250

225251
# Show build statistics
226252
if [ -d "public" ]; then
227-
POST_COUNT=$(find public -name "*.html" -not -name "index.html" | wc -l)
253+
POST_COUNT=$(find public -name "*.html" -not -name "index.html" -not -name "index-cn.html" | wc -l)
228254
TOTAL_SIZE=$(du -sh public | cut -f1)
229255
echo -e "${GREEN}Generated:${NC} $POST_COUNT posts"
230256
echo -e "${GREEN}Total size:${NC} $TOTAL_SIZE"
257+
258+
if [ "$INCREMENTAL_BUILD" = "true" ]; then
259+
echo -e "${GREEN}Mode:${NC} Incremental build"
260+
fi
231261
fi
232262
else
233263
echo -e "${YELLOW}Build completed with warnings${NC}"

static/css/blog.css

Lines changed: 31 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,6 @@ body {
103103
}
104104

105105
/* Focus styles for accessibility */
106-
:focus {
107-
outline: 2px solid var(--accent-primary);
108-
outline-offset: 2px;
109-
}
110-
111106
/* Remove focus outline for mouse clicks, keep for keyboard */
112107
:focus:not(:focus-visible) {
113108
outline: none;
@@ -142,6 +137,11 @@ body {
142137
}
143138
}
144139

140+
/* Apply will-change to animated elements */
141+
.article-meta {
142+
will-change: opacity, transform;
143+
}
144+
145145
/* ===== Layout Components ===== */
146146

147147
/* Container */
@@ -205,11 +205,17 @@ body {
205205
position: relative;
206206
}
207207

208-
.site-nav a:hover,
209-
.site-nav a:focus {
208+
.site-nav a:hover {
210209
color: var(--text-primary);
211210
}
212211

212+
.site-nav a:focus-visible {
213+
color: var(--text-primary);
214+
outline: 2px solid var(--accent-primary);
215+
outline-offset: 2px;
216+
border-radius: 4px;
217+
}
218+
213219
/* Language Switcher */
214220
.lang-switcher {
215221
display: flex;
@@ -458,12 +464,18 @@ li strong {
458464
transition: all 0.15s ease;
459465
}
460466

461-
#table-of-contents a:hover,
462-
#table-of-contents a:focus {
467+
#table-of-contents a:hover {
463468
background-color: var(--bg-primary);
464469
color: var(--text-primary);
465470
}
466471

472+
#table-of-contents a:focus-visible {
473+
background-color: var(--bg-primary);
474+
color: var(--text-primary);
475+
outline: 2px solid var(--accent-primary);
476+
outline-offset: -2px;
477+
}
478+
467479
#table-of-contents a.active {
468480
background-color: var(--accent-primary);
469481
color: white;
@@ -559,6 +571,7 @@ pre {
559571
transition: all 0.2s ease;
560572
opacity: 0.8;
561573
z-index: 1;
574+
will-change: opacity, transform;
562575
}
563576

564577
.code-copy-button:hover {
@@ -659,6 +672,7 @@ img {
659672
text-decoration: none;
660673
cursor: pointer;
661674
transition: all 0.2s ease;
675+
will-change: transform;
662676
}
663677

664678
.btn:hover {
@@ -913,84 +927,42 @@ img {
913927
color: #9c6fcf;
914928
}
915929

916-
/* General purpose classes that might be used by various modes */
917-
.org-font-lock-keyword-face {
918-
color: #9c6fcf;
919-
font-weight: 600;
920-
}
921-
922-
.org-font-lock-type-face {
923-
color: #d4a27f;
924-
}
925-
926-
.org-font-lock-string-face {
927-
color: #86b85c;
928-
}
929-
930-
.org-font-lock-comment-face {
931-
color: #8a8a8a;
932-
font-style: italic;
933-
}
934-
935-
.org-font-lock-function-name-face {
936-
color: #5b9bc8;
937-
font-weight: 600;
938-
}
939-
940-
.org-font-lock-variable-name-face {
941-
color: #5b9bc8;
942-
}
943-
944-
.org-font-lock-constant-face {
945-
color: #d68b5b;
946-
}
947-
948-
.org-font-lock-builtin-face {
949-
color: #d4a27f;
950-
}
930+
/* General purpose classes that might be used by various modes - removed duplicates */
951931

952932
/* Dark mode adjustments */
953933
@media (prefers-color-scheme: dark) {
954-
.org-keyword,
955-
.org-font-lock-keyword-face {
934+
.org-keyword {
956935
color: #bb9af7;
957936
}
958937

959-
.org-builtin,
960-
.org-font-lock-builtin-face {
938+
.org-builtin {
961939
color: #e0af68;
962940
}
963941

964-
.org-string,
965-
.org-font-lock-string-face {
942+
.org-string {
966943
color: #9ece6a;
967944
}
968945

969946
.org-comment,
970947
.org-comment-delimiter,
971-
.org-font-lock-comment-face,
972948
.org-doc,
973949
.org-doc-keyword {
974950
color: #565f89;
975951
}
976952

977-
.org-function-name,
978-
.org-font-lock-function-name-face {
953+
.org-function-name {
979954
color: #7dcfff;
980955
}
981956

982-
.org-variable-name,
983-
.org-font-lock-variable-name-face {
957+
.org-variable-name {
984958
color: #7aa2f7;
985959
}
986960

987-
.org-constant,
988-
.org-font-lock-constant-face {
961+
.org-constant {
989962
color: #ff9e64;
990963
}
991964

992-
.org-type,
993-
.org-font-lock-type-face {
965+
.org-type {
994966
color: #e0af68;
995967
}
996968

0 commit comments

Comments
 (0)