@anglefeint/astro-theme 0.1.13 → 0.1.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anglefeint/astro-theme",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "type": "module",
5
5
  "description": "Anglefeint core theme package for Astro",
6
6
  "keywords": [
@@ -25,8 +25,7 @@
25
25
  "src/styles",
26
26
  "src/assets/theme",
27
27
  "src/cli-new-post.mjs",
28
- "src/cli-new-page.mjs",
29
- "public"
28
+ "src/cli-new-page.mjs"
30
29
  ],
31
30
  "bin": {
32
31
  "anglefeint-new-post": "src/cli-new-post.mjs",
@@ -40,7 +39,6 @@
40
39
  "./i18n/*": "./src/i18n/*",
41
40
  "./styles/*": "./src/styles/*",
42
41
  "./assets/*": "./src/assets/*",
43
- "./public/*": "./public/*",
44
42
  "./content-schema": "./src/content-schema.ts",
45
43
  "./consts": "./src/consts.ts"
46
44
  },
@@ -5,6 +5,7 @@ import themeRedqueen1 from '../assets/theme/red-queen/theme-redqueen1.webp';
5
5
  import themeRedqueen2 from '../assets/theme/red-queen/theme-redqueen2.gif';
6
6
  import FormattedDate from '../components/FormattedDate.astro';
7
7
  import AiShell from './shells/AiShell.astro';
8
+ import blogPostCssUrl from '../styles/blog-post.css?url';
8
9
  import { SITE_AUTHOR } from '@anglefeint/site-config/site';
9
10
  import { DEFAULT_LOCALE, type Locale, isLocale, localePath, blogIdToSlugAnyLocale } from '@anglefeint/site-i18n/config';
10
11
  import { getMessages } from '@anglefeint/site-i18n/messages';
@@ -62,7 +63,7 @@ const confidenceText = aiConfidence !== undefined ? aiConfidence.toFixed(2) : un
62
63
  tags={tags}
63
64
  localeHrefs={localeHrefs}
64
65
  >
65
- <link slot="head" rel="stylesheet" href="/styles/blog-post.css" />
66
+ <link slot="head" rel="stylesheet" href={blogPostCssUrl} />
66
67
  <Fragment slot="body-start">
67
68
  <div class="ai-bg" aria-hidden="true">
68
69
  <div class="ai-glow ai-glow-shift"></div>
@@ -2,6 +2,7 @@
2
2
  import type { Locale } from '@anglefeint/site-i18n/config';
3
3
  import ThemeFrame from '../../components/shared/ThemeFrame.astro';
4
4
  import type { ImageMetadata } from 'astro';
5
+ import themeAiCssUrl from '../../styles/theme-ai.css?url';
5
6
 
6
7
  interface Props {
7
8
  locale?: Locale;
@@ -51,7 +52,7 @@ const {
51
52
  scanlines
52
53
  localeHrefs={localeHrefs}
53
54
  >
54
- <link slot="head" rel="stylesheet" href="/styles/theme-ai.css" />
55
+ <link slot="head" rel="stylesheet" href={themeAiCssUrl} />
55
56
  <slot name="head" slot="head" />
56
57
  <slot name="body-start" slot="body-start" />
57
58
  <slot />
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  import type { Locale } from '@anglefeint/site-i18n/config';
3
3
  import ThemeFrame from '../../components/shared/ThemeFrame.astro';
4
+ import themeCyberCssUrl from '../../styles/theme-cyber.css?url';
5
+ import blogListCssUrl from '../../styles/blog-list.css?url';
4
6
 
5
7
  interface Props {
6
8
  locale?: Locale;
@@ -13,7 +15,8 @@ const { locale, title, description, localeHrefs } = Astro.props as Props;
13
15
  ---
14
16
 
15
17
  <ThemeFrame locale={locale} title={title} description={description} bodyClass="cyber-page" mainClass="page-main cyber-content" localeHrefs={localeHrefs}>
16
- <link slot="head" rel="stylesheet" href="/styles/theme-cyber.css" />
18
+ <link slot="head" rel="stylesheet" href={themeCyberCssUrl} />
19
+ <link slot="head" rel="stylesheet" href={blogListCssUrl} />
17
20
  <Fragment slot="body-start">
18
21
  <div class="cyber-load-glitch" aria-hidden="true"></div>
19
22
  <div class="cyber-spotlight" aria-hidden="true">
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  import type { Locale } from '@anglefeint/site-i18n/config';
3
3
  import ThemeFrame from '../../components/shared/ThemeFrame.astro';
4
+ import aboutPageCssUrl from '../../styles/about-page.css?url';
4
5
 
5
6
  interface Props {
6
7
  locale?: Locale;
@@ -13,7 +14,7 @@ const { locale, title, description, bodyClass = 'hacker-page' } = Astro.props as
13
14
  ---
14
15
 
15
16
  <ThemeFrame locale={locale} title={title} description={description} bodyClass={bodyClass} mainClass="page-main hacker-content">
16
- <link slot="head" rel="stylesheet" href="/styles/about-page.css" />
17
+ <link slot="head" rel="stylesheet" href={aboutPageCssUrl} />
17
18
  <slot name="head" slot="head" />
18
19
  <slot name="body-start" slot="body-start" />
19
20
  <slot />
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  import type { Locale } from '@anglefeint/site-i18n/config';
3
3
  import ThemeFrame from '../../components/shared/ThemeFrame.astro';
4
+ import homePageCssUrl from '../../styles/home-page.css?url';
4
5
 
5
6
  interface Props {
6
7
  locale?: Locale;
@@ -12,7 +13,7 @@ const { locale, title, description } = Astro.props as Props;
12
13
  ---
13
14
 
14
15
  <ThemeFrame locale={locale} title={title} description={description} bodyClass="page-home" mainClass="page-main home-content">
15
- <link slot="head" rel="stylesheet" href="/styles/home-page.css" />
16
+ <link slot="head" rel="stylesheet" href={homePageCssUrl} />
16
17
  <canvas slot="body-start" id="matrix-bg" aria-hidden="true"></canvas>
17
18
  <Fragment slot="body-end">
18
19
  <script>
@@ -0,0 +1,150 @@
1
+ export function initTerminalBackground(runtimeConfig, prefersReducedMotion) {
2
+ var bgCanvas = document.querySelector('.hacker-bg-canvas');
3
+ if (!bgCanvas) return;
4
+
5
+ var bgCtx = bgCanvas.getContext('2d');
6
+ var fontSize = 13;
7
+ var lineHeight = 18;
8
+ var bgAnimationId = 0;
9
+ var fallbackDirLines = [
10
+ '~ $ ls -la',
11
+ 'total 42',
12
+ 'drwxr-xr-x 12 void staff 384 Jan 12 about blog projects',
13
+ 'drwxr-xr-x 8 void staff 256 Jan 11 .config .ssh keys',
14
+ '-rw-r--r-- 1 void staff 2048 Jan 10 README.md .env.gpg',
15
+ '-rwxr-xr-x 1 void staff 512 Jan 9 deploy.sh hack',
16
+ '~ $ cat .motd',
17
+ '>> welcome to the void | access granted',
18
+ ];
19
+ var dirLines = runtimeConfig.effects && Array.isArray(runtimeConfig.effects.backgroundLines) && runtimeConfig.effects.backgroundLines.length > 0
20
+ ? runtimeConfig.effects.backgroundLines
21
+ : fallbackDirLines;
22
+ var hackerFocused = false;
23
+ var hackerInput = '';
24
+ var hackerHistory = [];
25
+
26
+ function sizeBackground() {
27
+ var dpr = Math.min(window.devicePixelRatio || 1, 2);
28
+ bgCanvas.width = window.innerWidth * dpr;
29
+ bgCanvas.height = window.innerHeight * dpr;
30
+ bgCanvas.style.width = window.innerWidth + 'px';
31
+ bgCanvas.style.height = window.innerHeight + 'px';
32
+ bgCtx.scale(dpr, dpr);
33
+ }
34
+
35
+ function renderBg(t) {
36
+ var w = window.innerWidth;
37
+ var h = window.innerHeight;
38
+ var dpr = Math.min(window.devicePixelRatio || 1, 2);
39
+
40
+ bgCtx.setTransform(dpr, 0, 0, dpr, 0, 0);
41
+ bgCtx.clearRect(0, 0, w, h);
42
+ bgCtx.fillStyle = '#0a0a0a';
43
+ bgCtx.fillRect(0, 0, w, h);
44
+
45
+ bgCtx.font = fontSize + 'px ui-monospace, SFMono-Regular, Menlo, monospace';
46
+ var padX = 24;
47
+ var baseY = 22;
48
+
49
+ for (var i = 0; i < dirLines.length; i++) {
50
+ var line = dirLines[i];
51
+ if (line.indexOf('~ $') === 0) {
52
+ bgCtx.fillStyle = 'rgba(255, 255, 255, 0.9)';
53
+ } else if (line.indexOf('>>') === 0) {
54
+ bgCtx.fillStyle = 'rgba(255, 255, 255, 0.75)';
55
+ } else if (line.indexOf('total') === 0 || line.indexOf('drwx') === 0 || line.indexOf('-rw') === 0) {
56
+ bgCtx.fillStyle = 'rgba(255, 255, 255, 0.55)';
57
+ } else {
58
+ bgCtx.fillStyle = 'rgba(255, 255, 255, 0.6)';
59
+ }
60
+ bgCtx.fillText(line, padX, baseY + i * lineHeight);
61
+ }
62
+
63
+ var promptY = baseY + dirLines.length * lineHeight + 10;
64
+
65
+ for (var j = 0; j < hackerHistory.length; j++) {
66
+ bgCtx.fillStyle = 'rgba(255, 255, 255, 0.9)';
67
+ bgCtx.fillText('~ $ ' + hackerHistory[j], padX, promptY + j * lineHeight);
68
+ }
69
+
70
+ var currentY = promptY + hackerHistory.length * lineHeight;
71
+ bgCtx.fillStyle = 'rgba(255, 255, 255, 0.9)';
72
+ bgCtx.fillText('~ $ ', padX, currentY);
73
+ var promptW = bgCtx.measureText('~ $ ').width;
74
+ bgCtx.fillText(hackerInput, padX + promptW, currentY);
75
+ var inputW = bgCtx.measureText(hackerInput).width;
76
+ var blink = Math.floor(t / 530) % 2;
77
+ if (blink && hackerFocused) {
78
+ bgCtx.fillStyle = 'rgba(0, 255, 100, 0.9)';
79
+ bgCtx.fillRect(padX + promptW + inputW, currentY - fontSize + 4, 8, fontSize - 2);
80
+ } else if (!hackerFocused && blink) {
81
+ bgCtx.fillStyle = 'rgba(0, 255, 100, 0.9)';
82
+ bgCtx.fillRect(padX + promptW + inputW, currentY - fontSize + 4, 8, fontSize - 2);
83
+ }
84
+
85
+ bgAnimationId = requestAnimationFrame(renderBg);
86
+ }
87
+
88
+ function startBackgroundLoop() {
89
+ if (bgAnimationId || document.hidden) return;
90
+ bgAnimationId = requestAnimationFrame(renderBg);
91
+ }
92
+
93
+ function stopBackgroundLoop() {
94
+ if (!bgAnimationId) return;
95
+ cancelAnimationFrame(bgAnimationId);
96
+ bgAnimationId = 0;
97
+ }
98
+
99
+ sizeBackground();
100
+
101
+ if (prefersReducedMotion) {
102
+ renderBg(performance.now());
103
+ stopBackgroundLoop();
104
+ } else {
105
+ startBackgroundLoop();
106
+ document.addEventListener('visibilitychange', function() {
107
+ if (document.hidden) {
108
+ stopBackgroundLoop();
109
+ return;
110
+ }
111
+ startBackgroundLoop();
112
+ });
113
+ }
114
+
115
+ document.addEventListener('click', function(e) {
116
+ var content = document.querySelector('.about-shell');
117
+ var header = document.querySelector('header');
118
+ var footer = document.querySelector('footer');
119
+ if (content && content.contains(e.target)) {
120
+ hackerFocused = false;
121
+ } else if (header && header.contains(e.target)) {
122
+ hackerFocused = false;
123
+ } else if (footer && footer.contains(e.target)) {
124
+ hackerFocused = false;
125
+ } else if (e.target.closest('.hacker-back-to-top, .hacker-regenerate')) {
126
+ hackerFocused = false;
127
+ } else {
128
+ hackerFocused = true;
129
+ }
130
+ });
131
+
132
+ document.addEventListener('keydown', function(e) {
133
+ if (!hackerFocused) return;
134
+ if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
135
+ e.preventDefault();
136
+ if (e.key === 'Enter') {
137
+ hackerHistory.push(hackerInput);
138
+ hackerInput = '';
139
+ if (hackerHistory.length > 8) hackerHistory.shift();
140
+ } else if (e.key === 'Backspace') {
141
+ hackerInput = hackerInput.slice(0, -1);
142
+ } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && hackerInput.length < 80) {
143
+ hackerInput += e.key;
144
+ }
145
+ });
146
+
147
+ window.addEventListener('resize', function() {
148
+ sizeBackground();
149
+ }, { passive: true });
150
+ }
@@ -0,0 +1,101 @@
1
+ export function initAboutInteractions(prefersReducedMotion) {
2
+ var glow = document.querySelector('.hacker-mouse-glow');
3
+ if (glow && !prefersReducedMotion) {
4
+ var glowRaf;
5
+ var mx = 0;
6
+ var my = 0;
7
+ document.addEventListener('mousemove', function(e) {
8
+ mx = e.clientX;
9
+ my = e.clientY;
10
+ if (!glowRaf) {
11
+ glowRaf = requestAnimationFrame(function() {
12
+ glow.style.setProperty('--mouse-x', mx + 'px');
13
+ glow.style.setProperty('--mouse-y', my + 'px');
14
+ glowRaf = 0;
15
+ });
16
+ }
17
+ });
18
+ }
19
+
20
+ var paras = document.querySelectorAll('.hacker-body p, .hacker-body h2, .hacker-body blockquote, .about-manifest');
21
+ if (window.IntersectionObserver) {
22
+ var io = new IntersectionObserver(function(entries) {
23
+ entries.forEach(function(entry) {
24
+ if (entry.isIntersecting) {
25
+ entry.target.classList.add('hacker-visible');
26
+ io.unobserve(entry.target);
27
+ }
28
+ });
29
+ }, { rootMargin: '0px 0px -60px 0px', threshold: 0.1 });
30
+ paras.forEach(function(p) { io.observe(p); });
31
+ } else {
32
+ paras.forEach(function(p) { p.classList.add('hacker-visible'); });
33
+ }
34
+
35
+ var titles = document.querySelectorAll('.about-section-title');
36
+ if (prefersReducedMotion && titles.length) {
37
+ titles.forEach(function(el) {
38
+ var fullText = el.textContent || '';
39
+ el.setAttribute('data-full-text', fullText);
40
+ el.textContent = fullText;
41
+ el.style.minHeight = '1.2em';
42
+ });
43
+ } else if (window.IntersectionObserver && titles.length) {
44
+ titles.forEach(function(el) {
45
+ var fullText = el.textContent || '';
46
+ el.setAttribute('data-full-text', fullText);
47
+ el.textContent = '';
48
+ el.style.minHeight = '1.2em';
49
+ });
50
+
51
+ var tio = new IntersectionObserver(function(entries) {
52
+ entries.forEach(function(entry) {
53
+ if (entry.isIntersecting) {
54
+ tio.unobserve(entry.target);
55
+ var text = entry.target.getAttribute('data-full-text') || '';
56
+ var i = 0;
57
+ entry.target.textContent = '';
58
+ function type() {
59
+ if (i <= text.length) {
60
+ entry.target.textContent = text.slice(0, i);
61
+ i++;
62
+ setTimeout(type, 32);
63
+ }
64
+ }
65
+ type();
66
+ }
67
+ });
68
+ }, { rootMargin: '0px 0px -40px 0px', threshold: 0.1 });
69
+
70
+ titles.forEach(function(el) { tio.observe(el); });
71
+ }
72
+
73
+ var regen = document.querySelector('.hacker-regenerate');
74
+ var article = document.querySelector('.about-shell');
75
+ var scan = document.querySelector('.hacker-load-scan');
76
+ if (regen && article) {
77
+ regen.addEventListener('click', function() {
78
+ if (prefersReducedMotion) {
79
+ article.classList.add('hacker-flash');
80
+ setTimeout(function() {
81
+ article.classList.remove('hacker-flash');
82
+ }, 120);
83
+ return;
84
+ }
85
+
86
+ regen.disabled = true;
87
+ article.classList.add('hacker-flash');
88
+ if (scan) {
89
+ scan.style.animation = 'none';
90
+ scan.offsetHeight;
91
+ scan.style.animation = 'hacker-scan 0.8s ease-out forwards';
92
+ scan.style.top = '0';
93
+ scan.style.opacity = '1';
94
+ }
95
+ setTimeout(function() {
96
+ article.classList.remove('hacker-flash');
97
+ regen.disabled = false;
98
+ }, 1200);
99
+ });
100
+ }
101
+ }