astro-blog-kit 0.2.8 → 0.3.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/components/CommentForm.astro +20 -20
- package/components/Comments.astro +14 -14
- package/define-config.ts +97 -5
- package/integration.ts +93 -42
- package/package.json +1 -1
- package/templates/blog-config.ts.template +41 -24
- package/templates/blog-index.astro.template +42 -37
- package/types.ts +37 -5
|
@@ -170,14 +170,14 @@ const { postId, apiRoute = "/api/comments", replyToId } = Astro.props;
|
|
|
170
170
|
max-width: 720px;
|
|
171
171
|
margin: 3rem auto 0;
|
|
172
172
|
padding: 0 2rem 4rem;
|
|
173
|
-
font-family: var(--font-body);
|
|
173
|
+
font-family: var(--bk-font-body);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
.comment-form__title {
|
|
177
|
-
font-family: var(--font-display);
|
|
177
|
+
font-family: var(--bk-font-display);
|
|
178
178
|
font-size: 1.35rem;
|
|
179
179
|
font-weight: 700;
|
|
180
|
-
color: var(--
|
|
180
|
+
color: var(--bk-text);
|
|
181
181
|
margin: 0 0 1.5rem;
|
|
182
182
|
}
|
|
183
183
|
|
|
@@ -206,9 +206,9 @@ const { postId, apiRoute = "/api/comments", replyToId } = Astro.props;
|
|
|
206
206
|
align-items: center;
|
|
207
207
|
gap: 0.5rem;
|
|
208
208
|
font-size: 0.85rem;
|
|
209
|
-
color: var(--
|
|
210
|
-
background: var(--
|
|
211
|
-
border: 1px solid var(--
|
|
209
|
+
color: var(--bk-muted);
|
|
210
|
+
background: var(--bk-surface);
|
|
211
|
+
border: 1px solid var(--bk-border);
|
|
212
212
|
border-radius: 6px;
|
|
213
213
|
padding: 0.5rem 0.75rem;
|
|
214
214
|
margin-bottom: 1rem;
|
|
@@ -224,12 +224,12 @@ const { postId, apiRoute = "/api/comments", replyToId } = Astro.props;
|
|
|
224
224
|
border: none;
|
|
225
225
|
cursor: pointer;
|
|
226
226
|
font-size: 0.8rem;
|
|
227
|
-
color: var(--
|
|
227
|
+
color: var(--bk-muted);
|
|
228
228
|
padding: 0;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
.comment-form__reply-indicator button:hover {
|
|
232
|
-
color: var(--
|
|
232
|
+
color: var(--bk-accent);
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
.comment-form__row {
|
|
@@ -254,25 +254,25 @@ const { postId, apiRoute = "/api/comments", replyToId } = Astro.props;
|
|
|
254
254
|
.comment-form__label {
|
|
255
255
|
font-size: 0.8rem;
|
|
256
256
|
font-weight: 600;
|
|
257
|
-
color: var(--
|
|
258
|
-
font-family: var(--font-mono);
|
|
257
|
+
color: var(--bk-text);
|
|
258
|
+
font-family: var(--bk-font-mono);
|
|
259
259
|
letter-spacing: 0.5px;
|
|
260
260
|
text-transform: uppercase;
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
.comment-form__label span {
|
|
264
|
-
color: var(--
|
|
264
|
+
color: var(--bk-accent);
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
.comment-form__input,
|
|
268
268
|
.comment-form__textarea {
|
|
269
|
-
background: var(--
|
|
270
|
-
border: 1px solid var(--
|
|
269
|
+
background: var(--bk-surface);
|
|
270
|
+
border: 1px solid var(--bk-border);
|
|
271
271
|
border-radius: 6px;
|
|
272
272
|
padding: 0.65rem 0.9rem;
|
|
273
273
|
font-size: 0.95rem;
|
|
274
|
-
font-family: var(--font-body);
|
|
275
|
-
color: var(--
|
|
274
|
+
font-family: var(--bk-font-body);
|
|
275
|
+
color: var(--bk-text);
|
|
276
276
|
transition: border-color 0.15s;
|
|
277
277
|
width: 100%;
|
|
278
278
|
box-sizing: border-box;
|
|
@@ -281,7 +281,7 @@ const { postId, apiRoute = "/api/comments", replyToId } = Astro.props;
|
|
|
281
281
|
.comment-form__input:focus,
|
|
282
282
|
.comment-form__textarea:focus {
|
|
283
283
|
outline: none;
|
|
284
|
-
border-color: var(--
|
|
284
|
+
border-color: var(--bk-accent);
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
.comment-form__textarea {
|
|
@@ -291,20 +291,20 @@ const { postId, apiRoute = "/api/comments", replyToId } = Astro.props;
|
|
|
291
291
|
|
|
292
292
|
.comment-form__hint {
|
|
293
293
|
font-size: 0.75rem;
|
|
294
|
-
color: var(--
|
|
294
|
+
color: var(--bk-muted);
|
|
295
295
|
margin: 0;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
.comment-form__submit {
|
|
299
299
|
margin-top: 1.25rem;
|
|
300
300
|
padding: 0.7rem 1.75rem;
|
|
301
|
-
background: var(--
|
|
302
|
-
color: var(--
|
|
301
|
+
background: var(--bk-accent);
|
|
302
|
+
color: var(--bk-bg);
|
|
303
303
|
border: none;
|
|
304
304
|
border-radius: 6px;
|
|
305
305
|
font-size: 0.9rem;
|
|
306
306
|
font-weight: 700;
|
|
307
|
-
font-family: var(--font-mono);
|
|
307
|
+
font-family: var(--bk-font-mono);
|
|
308
308
|
letter-spacing: 0.5px;
|
|
309
309
|
cursor: pointer;
|
|
310
310
|
transition: opacity 0.15s;
|
|
@@ -121,21 +121,21 @@ const getReplies = (parentId: number) =>
|
|
|
121
121
|
max-width: 720px;
|
|
122
122
|
margin: 4rem auto 0;
|
|
123
123
|
padding: 0 2rem;
|
|
124
|
-
font-family: var(--font-body);
|
|
124
|
+
font-family: var(--bk-font-body);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
.comments__title {
|
|
128
|
-
font-family: var(--font-display);
|
|
128
|
+
font-family: var(--bk-font-display);
|
|
129
129
|
font-size: 1.5rem;
|
|
130
130
|
font-weight: 700;
|
|
131
|
-
color: var(--
|
|
131
|
+
color: var(--bk-text);
|
|
132
132
|
margin: 0 0 2rem;
|
|
133
133
|
padding-bottom: 1rem;
|
|
134
|
-
border-bottom: 1px solid var(--
|
|
134
|
+
border-bottom: 1px solid var(--bk-border);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
.comments__empty {
|
|
138
|
-
color: var(--
|
|
138
|
+
color: var(--bk-muted);
|
|
139
139
|
font-size: 0.95rem;
|
|
140
140
|
}
|
|
141
141
|
|
|
@@ -157,7 +157,7 @@ const getReplies = (parentId: number) =>
|
|
|
157
157
|
|
|
158
158
|
.comment--reply {
|
|
159
159
|
padding-left: 1.5rem;
|
|
160
|
-
border-left: 2px solid var(--
|
|
160
|
+
border-left: 2px solid var(--bk-border);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
.comment__header {
|
|
@@ -171,7 +171,7 @@ const getReplies = (parentId: number) =>
|
|
|
171
171
|
height: 48px;
|
|
172
172
|
border-radius: 50%;
|
|
173
173
|
object-fit: cover;
|
|
174
|
-
border: 2px solid var(--
|
|
174
|
+
border: 2px solid var(--bk-border);
|
|
175
175
|
flex-shrink: 0;
|
|
176
176
|
}
|
|
177
177
|
|
|
@@ -189,18 +189,18 @@ const getReplies = (parentId: number) =>
|
|
|
189
189
|
.comment__author {
|
|
190
190
|
font-size: 0.9rem;
|
|
191
191
|
font-weight: 700;
|
|
192
|
-
color: var(--
|
|
192
|
+
color: var(--bk-text);
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
.comment__date {
|
|
196
196
|
font-size: 0.75rem;
|
|
197
|
-
color: var(--
|
|
198
|
-
font-family: var(--font-mono);
|
|
197
|
+
color: var(--bk-muted);
|
|
198
|
+
font-family: var(--bk-font-mono);
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
.comment__body {
|
|
202
202
|
font-size: 0.95rem;
|
|
203
|
-
color: var(--
|
|
203
|
+
color: var(--bk-muted-light);
|
|
204
204
|
line-height: 1.75;
|
|
205
205
|
}
|
|
206
206
|
|
|
@@ -218,14 +218,14 @@ const getReplies = (parentId: number) =>
|
|
|
218
218
|
border: none;
|
|
219
219
|
cursor: pointer;
|
|
220
220
|
font-size: 0.8rem;
|
|
221
|
-
font-family: var(--font-mono);
|
|
222
|
-
color: var(--
|
|
221
|
+
font-family: var(--bk-font-mono);
|
|
222
|
+
color: var(--bk-muted);
|
|
223
223
|
padding: 0;
|
|
224
224
|
transition: color 0.15s;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
.comment__reply-btn:hover {
|
|
228
|
-
color: var(--
|
|
228
|
+
color: var(--bk-accent);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
.comment__replies {
|
package/define-config.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// ─────────────────────────────────────────────────────────────
|
|
2
2
|
// astro-blog-kit · define-config.ts
|
|
3
|
-
// Función helper para tipar la config del blog.
|
|
4
3
|
// ─────────────────────────────────────────────────────────────
|
|
5
4
|
|
|
6
|
-
import type { BlogKitConfig, BlogTheme } from "./types";
|
|
5
|
+
import type { BlogKitConfig, BlogTheme, BlogHero, BlogUI } from "./types";
|
|
7
6
|
|
|
8
7
|
export interface BlogConfig {
|
|
9
8
|
/** URL de tu WordPress. Ej: https://cms.tudominio.com */
|
|
@@ -14,8 +13,12 @@ export interface BlogConfig {
|
|
|
14
13
|
defaultLayout?: "grid" | "magazine" | "featured" | "cards";
|
|
15
14
|
/** Locale por defecto. @default "en" */
|
|
16
15
|
locale?: string;
|
|
17
|
-
/** Tema visual */
|
|
16
|
+
/** Tema visual (colores, fuentes, tamaños) */
|
|
18
17
|
theme?: BlogTheme;
|
|
18
|
+
/** Textos del hero/header del blog */
|
|
19
|
+
hero?: BlogHero;
|
|
20
|
+
/** Overrides de UI (botones, paginación, labels) */
|
|
21
|
+
ui?: BlogUI;
|
|
19
22
|
/** Configuración de i18n */
|
|
20
23
|
i18n?: {
|
|
21
24
|
locales: string[];
|
|
@@ -25,7 +28,6 @@ export interface BlogConfig {
|
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* Define la configuración del blog con tipado completo.
|
|
28
|
-
* Genera blog.config.ts en la raíz del proyecto.
|
|
29
31
|
*
|
|
30
32
|
* @example
|
|
31
33
|
* ```ts
|
|
@@ -35,10 +37,26 @@ export interface BlogConfig {
|
|
|
35
37
|
* export default defineBlogConfig({
|
|
36
38
|
* wpUrl: 'https://cms.tudominio.com',
|
|
37
39
|
* postsPerPage: 5,
|
|
38
|
-
* defaultLayout: '
|
|
40
|
+
* defaultLayout: 'featured',
|
|
39
41
|
* locale: 'en',
|
|
40
42
|
* theme: {
|
|
41
43
|
* accent: '#facc15',
|
|
44
|
+
* background: '#0a1a0a',
|
|
45
|
+
* text: '#ffffff',
|
|
46
|
+
* },
|
|
47
|
+
* hero: {
|
|
48
|
+
* tagline: 'Technical Resources',
|
|
49
|
+
* titleLine1: 'Building',
|
|
50
|
+
* titleLine2: 'Insights',
|
|
51
|
+
* description: 'Practical knowledge for architects and engineers.',
|
|
52
|
+
* },
|
|
53
|
+
* ui: {
|
|
54
|
+
* readMoreLabel: 'Read more →',
|
|
55
|
+
* btnPrev: 'Previous',
|
|
56
|
+
* btnNext: 'Next',
|
|
57
|
+
* commentButtonColor: '#facc15',
|
|
58
|
+
* commentButtonTextColor: '#0a0a0a',
|
|
59
|
+
* paginationStyle: 'minimal',
|
|
42
60
|
* },
|
|
43
61
|
* });
|
|
44
62
|
* ```
|
|
@@ -60,6 +78,80 @@ export function toBlogKitConfig(config: BlogConfig): BlogKitConfig {
|
|
|
60
78
|
postsPerPage: config.postsPerPage,
|
|
61
79
|
defaultLayout: config.defaultLayout,
|
|
62
80
|
theme: config.theme,
|
|
81
|
+
hero: config.hero,
|
|
82
|
+
ui: config.ui,
|
|
63
83
|
i18n: config.i18n,
|
|
64
84
|
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Resuelve los textos del hero con fallbacks según el locale.
|
|
89
|
+
* Usado internamente por BlogList.astro
|
|
90
|
+
*/
|
|
91
|
+
export function resolveHero(
|
|
92
|
+
hero: BlogHero | undefined,
|
|
93
|
+
locale: string
|
|
94
|
+
): Required<BlogHero> {
|
|
95
|
+
const defaults: Record<string, Required<BlogHero>> = {
|
|
96
|
+
en: {
|
|
97
|
+
tagline: "Our Blog",
|
|
98
|
+
titleLine1: "Latest",
|
|
99
|
+
titleLine2: "Articles",
|
|
100
|
+
description: "Welcome to our blog.",
|
|
101
|
+
},
|
|
102
|
+
es: {
|
|
103
|
+
tagline: "Nuestro Blog",
|
|
104
|
+
titleLine1: "Últimos",
|
|
105
|
+
titleLine2: "Artículos",
|
|
106
|
+
description: "Bienvenido a nuestro blog.",
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const d = defaults[locale] ?? defaults["en"];
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
tagline: hero?.tagline ?? d.tagline,
|
|
114
|
+
titleLine1: hero?.titleLine1 ?? d.titleLine1,
|
|
115
|
+
titleLine2: hero?.titleLine2 ?? d.titleLine2,
|
|
116
|
+
description: hero?.description ?? d.description,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Resuelve los labels de UI con fallbacks según el locale.
|
|
122
|
+
* Usado internamente por BlogList.astro y Pagination.astro
|
|
123
|
+
*/
|
|
124
|
+
export function resolveUI(
|
|
125
|
+
ui: BlogUI | undefined,
|
|
126
|
+
locale: string
|
|
127
|
+
): Required<BlogUI> {
|
|
128
|
+
const defaults: Record<string, Required<BlogUI>> = {
|
|
129
|
+
en: {
|
|
130
|
+
readMoreLabel: "Read more →",
|
|
131
|
+
btnPrev: "Previous",
|
|
132
|
+
btnNext: "Next",
|
|
133
|
+
commentButtonColor: "var(--bk-accent)",
|
|
134
|
+
commentButtonTextColor: "var(--bk-black)",
|
|
135
|
+
paginationStyle: "minimal",
|
|
136
|
+
},
|
|
137
|
+
es: {
|
|
138
|
+
readMoreLabel: "Leer más →",
|
|
139
|
+
btnPrev: "Anterior",
|
|
140
|
+
btnNext: "Siguiente",
|
|
141
|
+
commentButtonColor: "var(--bk-accent)",
|
|
142
|
+
commentButtonTextColor: "var(--bk-black)",
|
|
143
|
+
paginationStyle: "minimal",
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const d = defaults[locale] ?? defaults["en"];
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
readMoreLabel: ui?.readMoreLabel ?? d.readMoreLabel,
|
|
151
|
+
btnPrev: ui?.btnPrev ?? d.btnPrev,
|
|
152
|
+
btnNext: ui?.btnNext ?? d.btnNext,
|
|
153
|
+
commentButtonColor: ui?.commentButtonColor ?? d.commentButtonColor,
|
|
154
|
+
commentButtonTextColor: ui?.commentButtonTextColor ?? d.commentButtonTextColor,
|
|
155
|
+
paginationStyle: ui?.paginationStyle ?? d.paginationStyle,
|
|
156
|
+
};
|
|
65
157
|
}
|
package/integration.ts
CHANGED
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
// ─────────────────────────────────────────────────────────────
|
|
4
4
|
|
|
5
5
|
import type { AstroIntegration } from "astro";
|
|
6
|
+
import type { Plugin } from "vite";
|
|
6
7
|
import type { BlogKitConfig, BlogTheme } from "./types";
|
|
7
8
|
|
|
9
|
+
const VIRTUAL_MODULE_ID = "virtual:astro-blog-kit/theme";
|
|
10
|
+
const RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
|
|
11
|
+
|
|
8
12
|
/**
|
|
9
13
|
* Genera el bloque de CSS variables a partir del tema.
|
|
10
14
|
*/
|
|
@@ -27,36 +31,79 @@ function generateThemeCSS(theme: BlogTheme = {}): string {
|
|
|
27
31
|
};
|
|
28
32
|
|
|
29
33
|
return `
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
34
|
+
:root {
|
|
35
|
+
--bk-accent: ${t.accent};
|
|
36
|
+
--bk-background: ${t.background};
|
|
37
|
+
--bk-surface: ${t.surface};
|
|
38
|
+
--bk-text: ${t.text};
|
|
39
|
+
--bk-muted: ${t.muted};
|
|
40
|
+
--bk-muted-light: ${t.mutedLight};
|
|
41
|
+
--bk-border: ${t.border};
|
|
42
|
+
--bk-black: ${t.black};
|
|
43
|
+
--bk-white: ${t.white};
|
|
44
|
+
--bk-yellow: ${t.accent};
|
|
45
|
+
--bk-gray-100: #f3f4f6;
|
|
46
|
+
--bk-gray-200: #e5e7eb;
|
|
47
|
+
--bk-gray-300: #d1d5db;
|
|
48
|
+
--bk-gray-400: #9ca3af;
|
|
49
|
+
--bk-gray-600: #4b5563;
|
|
50
|
+
--bk-font-heading: ${t.fontHeading};
|
|
51
|
+
--bk-font-body: ${t.fontBody};
|
|
52
|
+
--bk-font-mono: ${t.fontMono};
|
|
53
|
+
--bk-font-display: ${t.fontDisplay};
|
|
54
|
+
--bk-container-max: ${t.containerMax};
|
|
55
|
+
--bk-transition: all 0.2s ease;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
*, *::before, *::after {
|
|
59
|
+
box-sizing: border-box;
|
|
60
|
+
margin: 0;
|
|
61
|
+
padding: 0;
|
|
62
|
+
}
|
|
63
|
+
`.trim();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Plugin de Vite que expone el tema como un virtual module CSS.
|
|
68
|
+
* Esto permite que Astro procese el CSS en SSR correctamente,
|
|
69
|
+
* sin depender de JavaScript en el cliente para inyectar variables.
|
|
70
|
+
*
|
|
71
|
+
* Uso en cualquier componente .astro del paquete:
|
|
72
|
+
* import 'virtual:astro-blog-kit/theme';
|
|
73
|
+
*/
|
|
74
|
+
function createThemePlugin(theme: BlogTheme): Plugin {
|
|
75
|
+
const css = generateThemeCSS(theme);
|
|
53
76
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
77
|
+
return {
|
|
78
|
+
name: "astro-blog-kit:theme",
|
|
79
|
+
resolveId(id) {
|
|
80
|
+
if (id === VIRTUAL_MODULE_ID) {
|
|
81
|
+
return RESOLVED_VIRTUAL_MODULE_ID;
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
load(id) {
|
|
85
|
+
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
86
|
+
// Retornamos CSS puro — Vite lo procesa como módulo CSS
|
|
87
|
+
return css;
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
// Fuerza el tipo del módulo como CSS para que Vite lo trate correctamente
|
|
91
|
+
transform(code, id) {
|
|
92
|
+
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
93
|
+
return {
|
|
94
|
+
code: `
|
|
95
|
+
const style = document.createElement('style');
|
|
96
|
+
style.id = 'astro-blog-kit-theme';
|
|
97
|
+
style.textContent = ${JSON.stringify(css)};
|
|
98
|
+
if (!document.getElementById('astro-blog-kit-theme')) {
|
|
99
|
+
document.head.appendChild(style);
|
|
100
|
+
}
|
|
101
|
+
`.trim(),
|
|
102
|
+
map: null,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
};
|
|
60
107
|
}
|
|
61
108
|
|
|
62
109
|
/**
|
|
@@ -72,7 +119,7 @@ function generateThemeCSS(theme: BlogTheme = {}): string {
|
|
|
72
119
|
* integrations: [
|
|
73
120
|
* blogKit({
|
|
74
121
|
* postsPerPage: 6,
|
|
75
|
-
* defaultLayout: '
|
|
122
|
+
* defaultLayout: 'featured',
|
|
76
123
|
* theme: {
|
|
77
124
|
* accent: '#facc15',
|
|
78
125
|
* fontHeading: 'Inter, sans-serif',
|
|
@@ -89,29 +136,33 @@ export function blogKit(config: BlogKitConfig = {}): AstroIntegration {
|
|
|
89
136
|
collectionName: config.collectionName ?? "blog",
|
|
90
137
|
i18n: config.i18n ?? { locales: [], defaultLocale: "en" },
|
|
91
138
|
theme: config.theme ?? {},
|
|
139
|
+
hero: config.hero ?? {}, // ← agregar
|
|
140
|
+
ui: config.ui ?? {},
|
|
92
141
|
};
|
|
93
142
|
|
|
94
143
|
return {
|
|
95
144
|
name: "astro-blog-kit",
|
|
96
145
|
|
|
97
146
|
hooks: {
|
|
98
|
-
"astro:config:setup": ({ injectScript, logger }) => {
|
|
147
|
+
"astro:config:setup": ({ updateConfig, injectScript, logger }) => {
|
|
99
148
|
logger.info(
|
|
100
149
|
`astro-blog-kit initialized — layout: ${resolvedConfig.defaultLayout}, postsPerPage: ${resolvedConfig.postsPerPage}`
|
|
101
150
|
);
|
|
102
151
|
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
152
|
+
// Registra el virtual module como plugin de Vite
|
|
153
|
+
// Esto garantiza que las CSS variables existen en SSR y en el build estático
|
|
154
|
+
updateConfig({
|
|
155
|
+
vite: {
|
|
156
|
+
plugins: [createThemePlugin(resolvedConfig.theme)],
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Inyecta el virtual module en cada página como CSS real
|
|
161
|
+
// "page-ssr" = se ejecuta en el servidor, garantiza que el style
|
|
162
|
+
// esté disponible antes del primer paint
|
|
163
|
+
injectScript("page-ssr", `import "${VIRTUAL_MODULE_ID}";`);
|
|
113
164
|
|
|
114
|
-
// Inyecta config global
|
|
165
|
+
// Inyecta config global accesible desde cualquier componente
|
|
115
166
|
injectScript(
|
|
116
167
|
"page-ssr",
|
|
117
168
|
`globalThis.__BLOG_KIT_CONFIG__ = ${JSON.stringify(resolvedConfig)};`
|
package/package.json
CHANGED
|
@@ -1,24 +1,41 @@
|
|
|
1
|
-
import { defineBlogConfig } from 'astro-blog-kit';
|
|
2
|
-
|
|
3
|
-
export default defineBlogConfig({
|
|
4
|
-
wpUrl: import.meta.env.WP_API_URL || '__WP_URL__',
|
|
5
|
-
postsPerPage: __POSTS_PER_PAGE__,
|
|
6
|
-
defaultLayout: '__DEFAULT_LAYOUT__',
|
|
7
|
-
locale: '__LOCALE__',
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
1
|
+
import { defineBlogConfig } from 'astro-blog-kit';
|
|
2
|
+
|
|
3
|
+
export default defineBlogConfig({
|
|
4
|
+
wpUrl: import.meta.env.WP_API_URL || '__WP_URL__',
|
|
5
|
+
postsPerPage: __POSTS_PER_PAGE__,
|
|
6
|
+
defaultLayout: '__DEFAULT_LAYOUT__',
|
|
7
|
+
locale: '__LOCALE__',
|
|
8
|
+
|
|
9
|
+
theme: {
|
|
10
|
+
accent: '#facc15',
|
|
11
|
+
background: '#ffffff',
|
|
12
|
+
surface: '#f8f8f8',
|
|
13
|
+
text: '#0a0a0a',
|
|
14
|
+
muted: '#6b7280',
|
|
15
|
+
mutedLight: '#4b5563',
|
|
16
|
+
border: '#e5e7eb',
|
|
17
|
+
black: '#0a0a0a',
|
|
18
|
+
white: '#ffffff',
|
|
19
|
+
fontHeading: 'Georgia, serif',
|
|
20
|
+
fontBody: 'system-ui, sans-serif',
|
|
21
|
+
fontMono: 'monospace',
|
|
22
|
+
fontDisplay: 'Georgia, serif',
|
|
23
|
+
containerMax:'1200px',
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
hero: {
|
|
27
|
+
tagline: '__T_TAGLINE__',
|
|
28
|
+
titleLine1: '__T_TITLE_LINE1__',
|
|
29
|
+
titleLine2: '__T_TITLE_LINE2__',
|
|
30
|
+
description: '__T_DESCRIPTION__',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
ui: {
|
|
34
|
+
readMoreLabel: '__T_BTNCTA__',
|
|
35
|
+
btnPrev: '__T_BTN_PREV__',
|
|
36
|
+
btnNext: '__T_BTN_NEXT__',
|
|
37
|
+
commentButtonColor: 'var(--bk-accent)',
|
|
38
|
+
commentButtonTextColor: 'var(--bk-black)',
|
|
39
|
+
paginationStyle: 'minimal',
|
|
40
|
+
},
|
|
41
|
+
});
|
|
@@ -1,37 +1,42 @@
|
|
|
1
|
-
---
|
|
2
|
-
import { BlogList } from
|
|
3
|
-
import { createWPClient } from
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
1
|
+
---
|
|
2
|
+
import { BlogList } from 'astro-blog-kit/components';
|
|
3
|
+
import { createWPClient } from 'astro-blog-kit/utils';
|
|
4
|
+
import { resolveHero, resolveUI } from 'astro-blog-kit';
|
|
5
|
+
import config from '../../../blog.config';
|
|
6
|
+
__LAYOUT_IMPORT__
|
|
7
|
+
|
|
8
|
+
const wp = createWPClient(config.wpUrl);
|
|
9
|
+
const { posts, totalPages } = await wp.getPosts({ perPage: config.postsPerPage ?? 5 });
|
|
10
|
+
|
|
11
|
+
const locale = config.locale ?? 'en';
|
|
12
|
+
const hero = resolveHero(config.hero, locale);
|
|
13
|
+
const ui = resolveUI(config.ui, locale);
|
|
14
|
+
|
|
15
|
+
const t = {
|
|
16
|
+
blog: {
|
|
17
|
+
tagline: hero.tagline,
|
|
18
|
+
title_line1: hero.titleLine1,
|
|
19
|
+
title_line2: hero.titleLine2,
|
|
20
|
+
description: hero.description,
|
|
21
|
+
btncta: ui.readMoreLabel,
|
|
22
|
+
btn_prev: ui.btnPrev,
|
|
23
|
+
btn_next: ui.btnNext,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const base = import.meta.env.BASE_URL;
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
__LAYOUT_OPEN__
|
|
31
|
+
<BlogList
|
|
32
|
+
posts={posts}
|
|
33
|
+
currentPage={1}
|
|
34
|
+
totalPages={totalPages}
|
|
35
|
+
basePath={`${base}blog/page/`}
|
|
36
|
+
blogBase={`${base}blog/`}
|
|
37
|
+
dateLocale={locale}
|
|
38
|
+
t={t}
|
|
39
|
+
locale={locale}
|
|
40
|
+
layout={config.defaultLayout ?? 'magazine'}
|
|
41
|
+
/>
|
|
42
|
+
__LAYOUT_CLOSE__
|
package/types.ts
CHANGED
|
@@ -4,10 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
// ── Post ──────────────────────────────────────────────────────
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* Forma normalizada de un post de blog.
|
|
9
|
-
* Compatible con WordPress REST API (_embedded).
|
|
10
|
-
*/
|
|
11
7
|
export interface BlogPost {
|
|
12
8
|
id?: number;
|
|
13
9
|
slug: string;
|
|
@@ -95,7 +91,7 @@ export interface BlogPostProps {
|
|
|
95
91
|
lang: string;
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
// ──
|
|
94
|
+
// ── Tema ──────────────────────────────────────────────────────
|
|
99
95
|
|
|
100
96
|
export interface BlogTheme {
|
|
101
97
|
/** Color de acento principal. @default "#facc15" */
|
|
@@ -128,6 +124,38 @@ export interface BlogTheme {
|
|
|
128
124
|
containerMax?: string;
|
|
129
125
|
}
|
|
130
126
|
|
|
127
|
+
// ── Hero del blog ─────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
export interface BlogHero {
|
|
130
|
+
/** Texto del badge superior. @default "Our Blog" */
|
|
131
|
+
tagline?: string;
|
|
132
|
+
/** Primera línea del título. @default "Latest" */
|
|
133
|
+
titleLine1?: string;
|
|
134
|
+
/** Segunda línea del título (resaltada). @default "Articles" */
|
|
135
|
+
titleLine2?: string;
|
|
136
|
+
/** Párrafo descriptivo debajo del título. @default "Welcome to our blog." */
|
|
137
|
+
description?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ── UI overrides ──────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
export interface BlogUI {
|
|
143
|
+
/** Texto del botón "leer más". @default "Read more →" */
|
|
144
|
+
readMoreLabel?: string;
|
|
145
|
+
/** Texto del botón de página anterior. @default "Previous" */
|
|
146
|
+
btnPrev?: string;
|
|
147
|
+
/** Texto del botón de página siguiente. @default "Next" */
|
|
148
|
+
btnNext?: string;
|
|
149
|
+
/** Color de fondo del botón de comentarios. @default var(--bk-accent) */
|
|
150
|
+
commentButtonColor?: string;
|
|
151
|
+
/** Color del texto del botón de comentarios. @default var(--bk-black) */
|
|
152
|
+
commentButtonTextColor?: string;
|
|
153
|
+
/** Estilo de paginación. @default "minimal" */
|
|
154
|
+
paginationStyle?: "minimal" | "numbered";
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ── Config del paquete ────────────────────────────────────────
|
|
158
|
+
|
|
131
159
|
export interface BlogKitConfig {
|
|
132
160
|
/** @default 5 */
|
|
133
161
|
postsPerPage?: number;
|
|
@@ -138,6 +166,10 @@ export interface BlogKitConfig {
|
|
|
138
166
|
collectionName?: string;
|
|
139
167
|
/** Tema visual del blog */
|
|
140
168
|
theme?: BlogTheme;
|
|
169
|
+
/** Textos del hero/header del blog */
|
|
170
|
+
hero?: BlogHero;
|
|
171
|
+
/** Overrides de UI (botones, paginación, labels) */
|
|
172
|
+
ui?: BlogUI;
|
|
141
173
|
}
|
|
142
174
|
|
|
143
175
|
// ── getStaticPaths ────────────────────────────────────────────
|