@anglefeint/astro-theme 0.1.0-alpha.0 → 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/package.json +1 -1
- package/public/scripts/about-effects.js +75 -75
- package/public/scripts/blogpost-effects.js +19 -19
- package/public/styles/about-page.css +125 -125
- package/public/styles/blog-post.css +16 -16
- package/src/cli-new-page.mjs +12 -6
- package/src/cli-new-post.mjs +0 -0
- package/src/components/Footer.astro +2 -71
- package/src/components/Header.astro +2 -325
- package/src/components/shared/CommonFooter.astro +74 -0
- package/src/components/shared/CommonHeader.astro +328 -0
- package/src/components/shared/ThemeFrame.astro +85 -0
- package/src/layouts/AiPageLayout.astro +16 -0
- package/src/layouts/BasePageLayout.astro +6 -57
- package/src/layouts/BlogPost.astro +76 -93
- package/src/layouts/CyberPageLayout.astro +16 -0
- package/src/layouts/HackerPageLayout.astro +16 -0
- package/src/layouts/HomePage.astro +29 -55
- package/src/layouts/MatrixPageLayout.astro +16 -0
- package/src/layouts/shells/AiShell.astro +58 -0
- package/src/layouts/shells/BaseShell.astro +16 -0
- package/src/layouts/shells/CyberShell.astro +30 -0
- package/src/layouts/shells/HackerShell.astro +21 -0
- package/src/layouts/shells/MatrixShell.astro +19 -0
- package/src/styles/global.css +236 -236
package/README.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
doc_id: package_readme
|
|
3
|
+
doc_role: package-guide
|
|
4
|
+
doc_scope: [package-install, package-upgrade, package-usage]
|
|
5
|
+
update_triggers: [package-change, command-change, export-change]
|
|
6
|
+
source_of_truth: true
|
|
7
|
+
depends_on: [docs/PACKAGING_WORKFLOW.md, docs/PACKAGE_RELEASE.md]
|
|
8
|
+
---
|
|
9
|
+
|
|
1
10
|
# @anglefeint/astro-theme
|
|
2
11
|
|
|
3
12
|
Core package for the Anglefeint Astro theme.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(function() {
|
|
2
2
|
function init() {
|
|
3
3
|
var runtimeConfig = {};
|
|
4
|
-
var runtimeConfigEl = document.getElementById('
|
|
4
|
+
var runtimeConfigEl = document.getElementById('hacker-runtime-config');
|
|
5
5
|
if (runtimeConfigEl && runtimeConfigEl.textContent) {
|
|
6
6
|
try {
|
|
7
7
|
runtimeConfig = JSON.parse(runtimeConfigEl.textContent);
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
// ── Terminal background: dir + 可输入 (点击背景聚焦,回车仅换行) ──
|
|
13
|
-
var bgCanvas = document.querySelector('.
|
|
13
|
+
var bgCanvas = document.querySelector('.hacker-bg-canvas');
|
|
14
14
|
if (bgCanvas) {
|
|
15
15
|
var bgCtx = bgCanvas.getContext('2d');
|
|
16
16
|
var fontSize = 13;
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
var dirLines = runtimeConfig.effects && Array.isArray(runtimeConfig.effects.backgroundLines) && runtimeConfig.effects.backgroundLines.length > 0
|
|
30
30
|
? runtimeConfig.effects.backgroundLines
|
|
31
31
|
: fallbackDirLines;
|
|
32
|
-
var
|
|
33
|
-
var
|
|
34
|
-
var
|
|
32
|
+
var hackerFocused = false;
|
|
33
|
+
var hackerInput = '';
|
|
34
|
+
var hackerHistory = [];
|
|
35
35
|
|
|
36
36
|
function sizeBackground() {
|
|
37
37
|
var dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
@@ -75,23 +75,23 @@
|
|
|
75
75
|
var promptY = baseY + dirLines.length * lineHeight + 10;
|
|
76
76
|
|
|
77
77
|
// 用户输入历史 (回车产生的行)
|
|
78
|
-
for (var i = 0; i <
|
|
78
|
+
for (var i = 0; i < hackerHistory.length; i++) {
|
|
79
79
|
bgCtx.fillStyle = 'rgba(255, 255, 255, 0.9)';
|
|
80
|
-
bgCtx.fillText('~ $ ' +
|
|
80
|
+
bgCtx.fillText('~ $ ' + hackerHistory[i], padX, promptY + i * lineHeight);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// 当前行: prompt + 输入 + 光标
|
|
84
|
-
var currentY = promptY +
|
|
84
|
+
var currentY = promptY + hackerHistory.length * lineHeight;
|
|
85
85
|
bgCtx.fillStyle = 'rgba(255, 255, 255, 0.9)';
|
|
86
86
|
bgCtx.fillText('~ $ ', padX, currentY);
|
|
87
87
|
var promptW = bgCtx.measureText('~ $ ').width;
|
|
88
|
-
bgCtx.fillText(
|
|
89
|
-
var inputW = bgCtx.measureText(
|
|
88
|
+
bgCtx.fillText(hackerInput, padX + promptW, currentY);
|
|
89
|
+
var inputW = bgCtx.measureText(hackerInput).width;
|
|
90
90
|
var blink = Math.floor(t / 530) % 2;
|
|
91
|
-
if (blink &&
|
|
91
|
+
if (blink && hackerFocused) {
|
|
92
92
|
bgCtx.fillStyle = 'rgba(0, 255, 100, 0.9)';
|
|
93
93
|
bgCtx.fillRect(padX + promptW + inputW, currentY - fontSize + 4, 8, fontSize - 2);
|
|
94
|
-
} else if (!
|
|
94
|
+
} else if (!hackerFocused && blink) {
|
|
95
95
|
bgCtx.fillStyle = 'rgba(0, 255, 100, 0.9)';
|
|
96
96
|
bgCtx.fillRect(padX + promptW + inputW, currentY - fontSize + 4, 8, fontSize - 2);
|
|
97
97
|
}
|
|
@@ -122,31 +122,31 @@
|
|
|
122
122
|
var header = document.querySelector('header');
|
|
123
123
|
var footer = document.querySelector('footer');
|
|
124
124
|
if (content && content.contains(e.target)) {
|
|
125
|
-
|
|
125
|
+
hackerFocused = false;
|
|
126
126
|
} else if (header && header.contains(e.target)) {
|
|
127
|
-
|
|
127
|
+
hackerFocused = false;
|
|
128
128
|
} else if (footer && footer.contains(e.target)) {
|
|
129
|
-
|
|
130
|
-
} else if (e.target.closest('.
|
|
131
|
-
|
|
129
|
+
hackerFocused = false;
|
|
130
|
+
} else if (e.target.closest('.hacker-back-to-top, .hacker-regenerate')) {
|
|
131
|
+
hackerFocused = false;
|
|
132
132
|
} else {
|
|
133
|
-
|
|
133
|
+
hackerFocused = true;
|
|
134
134
|
}
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
// 键盘输入 (仅当聚焦时)
|
|
138
138
|
document.addEventListener('keydown', function(e) {
|
|
139
|
-
if (!
|
|
139
|
+
if (!hackerFocused) return;
|
|
140
140
|
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
|
|
141
141
|
e.preventDefault();
|
|
142
142
|
if (e.key === 'Enter') {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (
|
|
143
|
+
hackerHistory.push(hackerInput);
|
|
144
|
+
hackerInput = '';
|
|
145
|
+
if (hackerHistory.length > 8) hackerHistory.shift();
|
|
146
146
|
} else if (e.key === 'Backspace') {
|
|
147
|
-
|
|
148
|
-
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey &&
|
|
149
|
-
|
|
147
|
+
hackerInput = hackerInput.slice(0, -1);
|
|
148
|
+
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && hackerInput.length < 80) {
|
|
149
|
+
hackerInput += e.key;
|
|
150
150
|
}
|
|
151
151
|
});
|
|
152
152
|
|
|
@@ -156,8 +156,8 @@
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// ── Progress bar + toasts + back-to-top ──
|
|
159
|
-
var progress = document.querySelector('.
|
|
160
|
-
var toast = document.querySelector('.
|
|
159
|
+
var progress = document.querySelector('.hacker-progress');
|
|
160
|
+
var toast = document.querySelector('.hacker-toast');
|
|
161
161
|
var fallbackToasts = {
|
|
162
162
|
p30: 'context parsed',
|
|
163
163
|
p60: 'inference stable',
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
var scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
185
185
|
var p = scrollHeight > 0 ? Math.min(1, scrollTop / scrollHeight) : 1;
|
|
186
186
|
progress.style.setProperty('--read-progress', String(p));
|
|
187
|
-
var btn = document.querySelector('.
|
|
187
|
+
var btn = document.querySelector('.hacker-back-to-top');
|
|
188
188
|
if (btn) btn.classList.toggle('visible', scrollTop > 400);
|
|
189
189
|
if (!hasScrolled && scrollTop > 6) hasScrolled = true;
|
|
190
190
|
if (!hasScrolled) return;
|
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
onScroll();
|
|
205
205
|
window.addEventListener('scroll', onScroll, { passive: true });
|
|
206
206
|
}
|
|
207
|
-
var backTop = document.querySelector('.
|
|
207
|
+
var backTop = document.querySelector('.hacker-back-to-top');
|
|
208
208
|
if (backTop) {
|
|
209
209
|
backTop.addEventListener('click', function() {
|
|
210
210
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
@@ -212,9 +212,9 @@
|
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
// ── 文件夹弹窗 ──
|
|
215
|
-
var modalOverlay = document.getElementById('
|
|
216
|
-
var modalBody = document.getElementById('
|
|
217
|
-
var modalTitle = document.querySelector('.
|
|
215
|
+
var modalOverlay = document.getElementById('hacker-modal');
|
|
216
|
+
var modalBody = document.getElementById('hacker-modal-body');
|
|
217
|
+
var modalTitle = document.querySelector('.hacker-modal-title');
|
|
218
218
|
var decryptorKeysLabel = runtimeConfig.decryptorKeysLabel || 'keys tested';
|
|
219
219
|
var decryptorInterval = null;
|
|
220
220
|
function randHex() {
|
|
@@ -277,13 +277,13 @@
|
|
|
277
277
|
['Ctrl','Alt','Space','AltRight','CtrlRight']
|
|
278
278
|
];
|
|
279
279
|
var codeMap = { '`':'Backquote','1':'Digit1','2':'Digit2','3':'Digit3','4':'Digit4','5':'Digit5','6':'Digit6','7':'Digit7','8':'Digit8','9':'Digit9','0':'Digit0','-':'Minus','=':'Equal','Backspace':'Backspace','Tab':'Tab','Q':'KeyQ','W':'KeyW','E':'KeyE','R':'KeyR','T':'KeyT','Y':'KeyY','U':'KeyU','I':'KeyI','O':'KeyO','P':'KeyP','[':'BracketLeft',']':'BracketRight','CapsLock':'CapsLock','A':'KeyA','S':'KeyS','D':'KeyD','F':'KeyF','G':'KeyG','H':'KeyH','J':'KeyJ','K':'KeyK','L':'KeyL',';':'Semicolon',"'":'Quote','Enter':'Enter','Shift':'ShiftLeft','ShiftRight':'ShiftRight','Z':'KeyZ','X':'KeyX','C':'KeyC','V':'KeyV','B':'KeyB','N':'KeyN','M':'KeyM',',':'Comma','.':'Period','/':'Slash','Ctrl':'ControlLeft','CtrlRight':'ControlRight','Alt':'AltLeft','AltRight':'AltRight','Space':'Space' };
|
|
280
|
-
var html = '<div class="
|
|
281
|
-
html += '<div class="
|
|
280
|
+
var html = '<div class="hacker-vkeyboard-wrap" id="help-keyboard">';
|
|
281
|
+
html += '<div class="hacker-vkeyboard hacker-vkeyboard-main">';
|
|
282
282
|
rows.forEach(function(row) {
|
|
283
|
-
html += '<div class="
|
|
283
|
+
html += '<div class="hacker-vkeyboard-row">';
|
|
284
284
|
row.forEach(function(k) {
|
|
285
285
|
var code = codeMap[k] || k;
|
|
286
|
-
var cls = '
|
|
286
|
+
var cls = 'hacker-vkey';
|
|
287
287
|
if (k === 'Tab' || k === 'CapsLock' || k === 'Enter') cls += ' wide';
|
|
288
288
|
if (k === 'Space') cls += ' space';
|
|
289
289
|
if (k === 'Backspace') cls += ' acc backspace';
|
|
@@ -293,30 +293,30 @@
|
|
|
293
293
|
html += '</div>';
|
|
294
294
|
});
|
|
295
295
|
html += '</div>';
|
|
296
|
-
html += '<div class="
|
|
297
|
-
html += '<div class="
|
|
298
|
-
html += '<div class="
|
|
299
|
-
html += '<div class="
|
|
296
|
+
html += '<div class="hacker-vkeyboard-side">';
|
|
297
|
+
html += '<div class="hacker-vkeyboard-side-block">';
|
|
298
|
+
html += '<div class="hacker-vkeyboard-side-row"><span class="hacker-vkey" data-code="Insert" data-key="Ins">Insert</span><span class="hacker-vkey nav-home" data-code="Home" data-key="Home">Home</span><span class="hacker-vkey" data-code="PageUp" data-key="PgUp">PgUp</span></div>';
|
|
299
|
+
html += '<div class="hacker-vkeyboard-side-row"><span class="hacker-vkey" data-code="Delete" data-key="Del">Delete</span><span class="hacker-vkey nav-end" data-code="End" data-key="End">End</span><span class="hacker-vkey" data-code="PageDown" data-key="PgDn">PgDn</span></div>';
|
|
300
300
|
html += '</div>';
|
|
301
|
-
html += '<div class="
|
|
302
|
-
html += '<div class="
|
|
303
|
-
html += '<div class="
|
|
304
|
-
html += '<span class="
|
|
305
|
-
html += '<span class="
|
|
306
|
-
html += '<span class="
|
|
307
|
-
html += '<span class="
|
|
301
|
+
html += '<div class="hacker-vkeyboard-side-row"><span class="hacker-vkey" data-code="Purge" data-key="Purge">Purge</span></div>';
|
|
302
|
+
html += '<div class="hacker-vkeyboard-arrows-wrap">';
|
|
303
|
+
html += '<div class="hacker-vkeyboard-arrows">';
|
|
304
|
+
html += '<span class="hacker-vkey arr-u" data-code="ArrowUp" data-key="↑">↑</span>';
|
|
305
|
+
html += '<span class="hacker-vkey arr-l" data-code="ArrowLeft" data-key="←">←</span>';
|
|
306
|
+
html += '<span class="hacker-vkey arr-r" data-code="ArrowRight" data-key="→">→</span>';
|
|
307
|
+
html += '<span class="hacker-vkey arr-d" data-code="ArrowDown" data-key="↓">↓</span>';
|
|
308
308
|
html += '</div>';
|
|
309
309
|
html += '</div></div></div>';
|
|
310
|
-
html += '<div class="
|
|
310
|
+
html += '<div class="hacker-vkeyboard-stats"><span class="hacker-vkeyboard-stats-label">' + statsLabel + '</span><br>' + typedPrefix + ' <span id="help-char-count">0</span> ' + typedSuffix + '</div>';
|
|
311
311
|
return html;
|
|
312
312
|
}
|
|
313
313
|
function highlightKey(code) {
|
|
314
314
|
if (code === 'Escape') code = 'Backspace';
|
|
315
|
-
var el = modalBody.querySelector('.
|
|
315
|
+
var el = modalBody.querySelector('.hacker-vkey[data-code="' + code + '"]');
|
|
316
316
|
if (!el) {
|
|
317
|
-
if (code === 'ShiftRight') el = modalBody.querySelector('.
|
|
318
|
-
else if (code === 'ControlRight') el = modalBody.querySelector('.
|
|
319
|
-
else if (code === 'AltRight') el = modalBody.querySelector('.
|
|
317
|
+
if (code === 'ShiftRight') el = modalBody.querySelector('.hacker-vkey[data-code="ShiftLeft"]');
|
|
318
|
+
else if (code === 'ControlRight') el = modalBody.querySelector('.hacker-vkey[data-code="ControlLeft"]');
|
|
319
|
+
else if (code === 'AltRight') el = modalBody.querySelector('.hacker-vkey[data-code="AltLeft"]');
|
|
320
320
|
}
|
|
321
321
|
if (el) {
|
|
322
322
|
el.classList.add('highlight');
|
|
@@ -327,7 +327,7 @@
|
|
|
327
327
|
helpCharCount = 0;
|
|
328
328
|
var charEl = document.getElementById('help-char-count');
|
|
329
329
|
if (charEl) charEl.textContent = '0';
|
|
330
|
-
modalBody.querySelectorAll('.
|
|
330
|
+
modalBody.querySelectorAll('.hacker-vkey').forEach(function(k) {
|
|
331
331
|
k.addEventListener('click', function() {
|
|
332
332
|
var code = k.getAttribute('data-code');
|
|
333
333
|
highlightKey(code);
|
|
@@ -346,7 +346,7 @@
|
|
|
346
346
|
});
|
|
347
347
|
}
|
|
348
348
|
function handleHelpKeydown(e) {
|
|
349
|
-
if (!modalOverlay.classList.contains('open') || !modalBody.classList.contains('
|
|
349
|
+
if (!modalOverlay.classList.contains('open') || !modalBody.classList.contains('hacker-modal-keyboard')) return;
|
|
350
350
|
if (e.key === 'Escape') return;
|
|
351
351
|
e.preventDefault();
|
|
352
352
|
highlightKey(e.code);
|
|
@@ -356,25 +356,25 @@
|
|
|
356
356
|
if (charEl) charEl.textContent = helpCharCount;
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
|
-
var scriptsTpl = document.getElementById('
|
|
359
|
+
var scriptsTpl = document.getElementById('hacker-scripts-folders-tpl');
|
|
360
360
|
var fallbackModalContent = {
|
|
361
|
-
'dl-data': { title: 'Downloading...', body: '<div class="
|
|
361
|
+
'dl-data': { title: 'Downloading...', body: '<div class="hacker-modal-download"><div class="modal-subtitle">Critical Data</div><div class="hacker-modal-progress" id="dl-progress"></div></div>', type: 'progress' },
|
|
362
362
|
'ai': { title: 'AI', body: '<pre>~ $ model --status\n\ninference: stable\ncontext: 8k tokens\nlatency: < 200ms\n\n>> system online</pre>' },
|
|
363
|
-
'decryptor': { title: 'Password Decryptor', body: '<pre class="
|
|
363
|
+
'decryptor': { title: 'Password Decryptor', body: '<pre class="hacker-decryptor-pre">Calculating Hashes\n\n<span id="dec-keys">[00:00:01] 0 keys tested</span>\n\nCurrent passphrase: <span id="dec-pass">********</span>\n\nMaster key\n<span id="dec-master1"></span>\n<span id="dec-master2"></span>\n\nTransient key\n<span id="dec-trans1"></span>\n<span id="dec-trans2"></span>\n<span id="dec-trans3"></span>\n<span id="dec-trans4"></span></pre>', type: 'decryptor' },
|
|
364
364
|
'help': { title: 'Help', body: '', type: 'keyboard' },
|
|
365
365
|
'all-scripts': { title: '/root/bash/scripts', body: '', type: 'scripts' }
|
|
366
366
|
};
|
|
367
367
|
var modalContent = runtimeConfig.modalContent || fallbackModalContent;
|
|
368
|
-
document.querySelectorAll('.
|
|
368
|
+
document.querySelectorAll('.hacker-folder[data-modal]').forEach(function(btn) {
|
|
369
369
|
btn.addEventListener('click', function() {
|
|
370
370
|
var id = btn.getAttribute('data-modal');
|
|
371
371
|
var data = modalContent[id];
|
|
372
372
|
if (data) {
|
|
373
|
-
var modalEl = modalOverlay.querySelector('.
|
|
374
|
-
if (modalEl) modalEl.classList.remove('
|
|
373
|
+
var modalEl = modalOverlay.querySelector('.hacker-modal');
|
|
374
|
+
if (modalEl) modalEl.classList.remove('hacker-modal-wide');
|
|
375
375
|
modalTitle.textContent = data.title;
|
|
376
376
|
modalBody.innerHTML = data.body;
|
|
377
|
-
modalBody.className = '
|
|
377
|
+
modalBody.className = 'hacker-modal-body' + (data.type === 'progress' ? ' hacker-modal-download' : '') + (data.type === 'keyboard' ? ' hacker-modal-keyboard' : '') + (data.type === 'scripts' ? ' hacker-modal-scripts-wrap' : '');
|
|
378
378
|
if (data.type === 'progress') {
|
|
379
379
|
var bar = document.getElementById('dl-progress');
|
|
380
380
|
if (bar) {
|
|
@@ -410,13 +410,13 @@
|
|
|
410
410
|
startDecryptorFlash();
|
|
411
411
|
} else if (data.type === 'keyboard') {
|
|
412
412
|
modalBody.innerHTML = buildHelpKeyboard();
|
|
413
|
-
if (modalEl) modalEl.classList.add('
|
|
413
|
+
if (modalEl) modalEl.classList.add('hacker-modal-wide');
|
|
414
414
|
initHelpKeyboard();
|
|
415
415
|
document.addEventListener('keydown', handleHelpKeydown);
|
|
416
416
|
} else if (data.type === 'scripts' && scriptsTpl && scriptsTpl.content) {
|
|
417
417
|
modalBody.innerHTML = '';
|
|
418
418
|
modalBody.appendChild(scriptsTpl.content.cloneNode(true));
|
|
419
|
-
if (modalEl) modalEl.classList.add('
|
|
419
|
+
if (modalEl) modalEl.classList.add('hacker-modal-wide');
|
|
420
420
|
}
|
|
421
421
|
modalOverlay.classList.add('open');
|
|
422
422
|
modalOverlay.setAttribute('aria-hidden', 'false');
|
|
@@ -429,12 +429,12 @@
|
|
|
429
429
|
decryptorInterval = null;
|
|
430
430
|
}
|
|
431
431
|
document.removeEventListener('keydown', handleHelpKeydown);
|
|
432
|
-
var modalEl = modalOverlay.querySelector('.
|
|
433
|
-
if (modalEl) modalEl.classList.remove('
|
|
432
|
+
var modalEl = modalOverlay.querySelector('.hacker-modal');
|
|
433
|
+
if (modalEl) modalEl.classList.remove('hacker-modal-wide');
|
|
434
434
|
modalOverlay.classList.remove('open');
|
|
435
435
|
modalOverlay.setAttribute('aria-hidden', 'true');
|
|
436
436
|
}
|
|
437
|
-
document.querySelector('.
|
|
437
|
+
document.querySelector('.hacker-modal-close').addEventListener('click', closeModal);
|
|
438
438
|
modalOverlay.addEventListener('click', function(e) {
|
|
439
439
|
if (e.target === modalOverlay) closeModal();
|
|
440
440
|
});
|
|
@@ -443,7 +443,7 @@
|
|
|
443
443
|
});
|
|
444
444
|
|
|
445
445
|
// ── Mouse glow ──
|
|
446
|
-
var glow = document.querySelector('.
|
|
446
|
+
var glow = document.querySelector('.hacker-mouse-glow');
|
|
447
447
|
if (glow) {
|
|
448
448
|
var glowRaf;
|
|
449
449
|
var mx = 0, my = 0;
|
|
@@ -459,19 +459,19 @@
|
|
|
459
459
|
}
|
|
460
460
|
|
|
461
461
|
// ── Paragraph scroll reveal ──
|
|
462
|
-
var paras = document.querySelectorAll('.
|
|
462
|
+
var paras = document.querySelectorAll('.hacker-body p, .hacker-body h2, .hacker-body blockquote, .about-manifest');
|
|
463
463
|
if (window.IntersectionObserver) {
|
|
464
464
|
var io = new IntersectionObserver(function(entries) {
|
|
465
465
|
entries.forEach(function(e) {
|
|
466
466
|
if (e.isIntersecting) {
|
|
467
|
-
e.target.classList.add('
|
|
467
|
+
e.target.classList.add('hacker-visible');
|
|
468
468
|
io.unobserve(e.target);
|
|
469
469
|
}
|
|
470
470
|
});
|
|
471
471
|
}, { rootMargin: '0px 0px -60px 0px', threshold: 0.1 });
|
|
472
472
|
paras.forEach(function(p) { io.observe(p); });
|
|
473
473
|
} else {
|
|
474
|
-
paras.forEach(function(p) { p.classList.add('
|
|
474
|
+
paras.forEach(function(p) { p.classList.add('hacker-visible'); });
|
|
475
475
|
}
|
|
476
476
|
|
|
477
477
|
// ── Typewriter section titles ──
|
|
@@ -505,22 +505,22 @@
|
|
|
505
505
|
}
|
|
506
506
|
|
|
507
507
|
// ── Regenerate button ──
|
|
508
|
-
var regen = document.querySelector('.
|
|
508
|
+
var regen = document.querySelector('.hacker-regenerate');
|
|
509
509
|
var article = document.querySelector('.about-shell');
|
|
510
|
-
var scan = document.querySelector('.
|
|
510
|
+
var scan = document.querySelector('.hacker-load-scan');
|
|
511
511
|
if (regen && article) {
|
|
512
512
|
regen.addEventListener('click', function() {
|
|
513
513
|
regen.disabled = true;
|
|
514
|
-
article.classList.add('
|
|
514
|
+
article.classList.add('hacker-flash');
|
|
515
515
|
if (scan) {
|
|
516
516
|
scan.style.animation = 'none';
|
|
517
517
|
scan.offsetHeight;
|
|
518
|
-
scan.style.animation = '
|
|
518
|
+
scan.style.animation = 'hacker-scan 0.8s ease-out forwards';
|
|
519
519
|
scan.style.top = '0';
|
|
520
520
|
scan.style.opacity = '1';
|
|
521
521
|
}
|
|
522
522
|
setTimeout(function() {
|
|
523
|
-
article.classList.remove('
|
|
523
|
+
article.classList.remove('hacker-flash');
|
|
524
524
|
regen.disabled = false;
|
|
525
525
|
}, 1200);
|
|
526
526
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
(function() {
|
|
2
2
|
function init() {
|
|
3
3
|
// 阅读进度条
|
|
4
|
-
var progress = document.querySelector('.
|
|
5
|
-
var article = document.querySelector('.
|
|
6
|
-
var toast = document.querySelector('.
|
|
4
|
+
var progress = document.querySelector('.ai-read-progress');
|
|
5
|
+
var article = document.querySelector('.ai-article');
|
|
6
|
+
var toast = document.querySelector('.ai-stage-toast');
|
|
7
7
|
var stageSeen = { p30: false, p60: false, p90: false };
|
|
8
8
|
var toastTimer = 0;
|
|
9
9
|
var hasScrolled = false;
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
var scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
23
23
|
var p = scrollHeight > 0 ? Math.min(1, scrollTop / scrollHeight) : 1;
|
|
24
24
|
progress.style.setProperty('--read-progress', String(p));
|
|
25
|
-
var btn = document.querySelector('.
|
|
25
|
+
var btn = document.querySelector('.ai-back-to-top');
|
|
26
26
|
if (btn) btn.classList.toggle('visible', scrollTop > 400);
|
|
27
27
|
if (!hasScrolled && scrollTop > 6) hasScrolled = true;
|
|
28
28
|
if (!hasScrolled) return;
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
onScroll();
|
|
43
43
|
window.addEventListener('scroll', onScroll, { passive: true });
|
|
44
44
|
}
|
|
45
|
-
var backTop = document.querySelector('.
|
|
45
|
+
var backTop = document.querySelector('.ai-back-to-top');
|
|
46
46
|
if (backTop) {
|
|
47
47
|
backTop.addEventListener('click', function() {
|
|
48
48
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
@@ -880,7 +880,7 @@
|
|
|
880
880
|
initRedQueenTv();
|
|
881
881
|
|
|
882
882
|
// 鼠标跟随光斑
|
|
883
|
-
var glow = document.querySelector('.
|
|
883
|
+
var glow = document.querySelector('.ai-mouse-glow');
|
|
884
884
|
if (glow) {
|
|
885
885
|
var raf;
|
|
886
886
|
var x = 0, y = 0;
|
|
@@ -896,10 +896,10 @@
|
|
|
896
896
|
}
|
|
897
897
|
|
|
898
898
|
// 悬浮预览卡:为链接添加 data-preview
|
|
899
|
-
document.querySelectorAll('.
|
|
899
|
+
document.querySelectorAll('.ai-prose-body a[href]').forEach(function(a) {
|
|
900
900
|
var href = a.getAttribute('href') || '';
|
|
901
901
|
if (!href || href.startsWith('#')) return;
|
|
902
|
-
a.classList.add('
|
|
902
|
+
a.classList.add('ai-link-preview');
|
|
903
903
|
try {
|
|
904
904
|
a.setAttribute('data-preview', href.startsWith('http') ? new URL(href, location.origin).hostname : href);
|
|
905
905
|
} catch (_) {
|
|
@@ -908,40 +908,40 @@
|
|
|
908
908
|
});
|
|
909
909
|
|
|
910
910
|
// 段落滚动浮现
|
|
911
|
-
var paras = document.querySelectorAll('.
|
|
911
|
+
var paras = document.querySelectorAll('.ai-prose-body p, .ai-prose-body h2, .ai-prose-body h3, .ai-prose-body pre, .ai-prose-body blockquote, .ai-prose-body ul, .ai-prose-body ol');
|
|
912
912
|
if (window.IntersectionObserver) {
|
|
913
913
|
var io = new IntersectionObserver(function(entries) {
|
|
914
914
|
entries.forEach(function(e) {
|
|
915
915
|
if (e.isIntersecting) {
|
|
916
|
-
e.target.classList.add('
|
|
916
|
+
e.target.classList.add('ai-para-visible');
|
|
917
917
|
io.unobserve(e.target);
|
|
918
918
|
}
|
|
919
919
|
});
|
|
920
920
|
}, { rootMargin: '0px 0px -60px 0px', threshold: 0.1 });
|
|
921
921
|
paras.forEach(function(p) { io.observe(p); });
|
|
922
922
|
} else {
|
|
923
|
-
paras.forEach(function(p) { p.classList.add('
|
|
923
|
+
paras.forEach(function(p) { p.classList.add('ai-para-visible'); });
|
|
924
924
|
}
|
|
925
925
|
|
|
926
926
|
// Regenerate 按钮
|
|
927
|
-
var regen = document.querySelector('.
|
|
928
|
-
var article = document.querySelector('.
|
|
929
|
-
var scan = document.querySelector('.
|
|
927
|
+
var regen = document.querySelector('.ai-regenerate');
|
|
928
|
+
var article = document.querySelector('.ai-article');
|
|
929
|
+
var scan = document.querySelector('.ai-load-scan');
|
|
930
930
|
if (regen && article) {
|
|
931
931
|
regen.addEventListener('click', function() {
|
|
932
932
|
regen.disabled = true;
|
|
933
|
-
regen.classList.add('
|
|
934
|
-
article.classList.add('
|
|
933
|
+
regen.classList.add('ai-regenerating');
|
|
934
|
+
article.classList.add('ai-regenerate-flash');
|
|
935
935
|
if (scan) {
|
|
936
936
|
scan.style.animation = 'none';
|
|
937
937
|
scan.offsetHeight;
|
|
938
|
-
scan.style.animation = '
|
|
938
|
+
scan.style.animation = 'ai-scan 0.8s ease-out forwards';
|
|
939
939
|
scan.style.top = '0';
|
|
940
940
|
scan.style.opacity = '1';
|
|
941
941
|
}
|
|
942
942
|
setTimeout(function() {
|
|
943
|
-
article.classList.remove('
|
|
944
|
-
regen.classList.remove('
|
|
943
|
+
article.classList.remove('ai-regenerate-flash');
|
|
944
|
+
regen.classList.remove('ai-regenerating');
|
|
945
945
|
regen.disabled = false;
|
|
946
946
|
}, 1200);
|
|
947
947
|
});
|