Skip to content

Commit 2b02609

Browse files
authored
Merge pull request #2 from calimania/feat/pages
Displaying pages, articles & products
2 parents 34ca4b1 + ad7877a commit 2b02609

25 files changed

+1753
-725
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ package-lock.json
99
.astro/
1010
*.local
1111
*.backup
12+
*.draft.*
Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
---
2+
import { type ContentBlock } from "../types.d";
3+
4+
export interface Props {
5+
content?: ContentBlock[];
6+
className?: string;
7+
}
8+
9+
const { content, className = "" } = Astro.props;
10+
---
11+
12+
{
13+
content && content.length > 0 && (
14+
<div class={`blocks-content ${className}`}>
15+
{content.map((block) => (
16+
<>
17+
{/* Paragraph blocks */}
18+
{block.type === "paragraph" && (
19+
<p class="mb-4 leading-relaxed">
20+
{block.children.map((child) => (
21+
<Fragment>
22+
{child.code && (
23+
<code class="bg-gray-100 text-gray-800 px-2 py-1 rounded text-sm font-mono">
24+
{child.text}
25+
</code>
26+
)}
27+
{child.type === "link" && !child.code && (
28+
<a
29+
href={child.url}
30+
target={child.url?.startsWith("/") ? "_self" : "_blank"}
31+
rel="noopener noreferrer"
32+
class="text-blue-600 hover:text-pink-600 transition-colors underline"
33+
>
34+
{child.children?.[0]?.text || child.text}
35+
</a>
36+
)}
37+
{!child.code &&
38+
child.type !== "link" &&
39+
(child.bold ? (
40+
<strong>{child.text}</strong>
41+
) : (
42+
<span>{child.text}</span>
43+
))}
44+
</Fragment>
45+
))}
46+
</p>
47+
)}
48+
49+
{/* Heading blocks */}
50+
{block.type === "heading" && block.level === 1 && (
51+
<h1 class="text-4xl font-bold my-6" style="color: var(--text);">
52+
{block.children.map((child) => (
53+
<Fragment>
54+
{child.code ? (
55+
<code class="bg-gray-100 text-gray-800 px-2 py-1 rounded text-sm font-mono">
56+
{child.text}
57+
</code>
58+
) : child.type === "link" ? (
59+
<a
60+
href={child.url}
61+
target={child.url?.startsWith("/") ? "_self" : "_blank"}
62+
rel="noopener noreferrer"
63+
class="text-blue-600 hover:text-pink-600 transition-colors underline"
64+
>
65+
{child.children?.[0]?.text || child.text}
66+
</a>
67+
) : (
68+
<span>{child.text}</span>
69+
)}
70+
</Fragment>
71+
))}
72+
</h1>
73+
)}
74+
75+
{block.type === "heading" && block.level === 2 && (
76+
<h2 class="text-3xl font-bold my-5" style="color: var(--text);">
77+
{block.children.map((child) => (
78+
<Fragment>
79+
{child.code ? (
80+
<code class="bg-gray-100 text-gray-800 px-2 py-1 rounded text-sm font-mono">
81+
{child.text}
82+
</code>
83+
) : child.type === "link" ? (
84+
<a
85+
href={child.url}
86+
target={child.url?.startsWith("/") ? "_self" : "_blank"}
87+
rel="noopener noreferrer"
88+
class="text-blue-600 hover:text-pink-600 transition-colors underline"
89+
>
90+
{child.children?.[0]?.text || child.text}
91+
</a>
92+
) : (
93+
<span>{child.text}</span>
94+
)}
95+
</Fragment>
96+
))}
97+
</h2>
98+
)}
99+
100+
{block.type === "heading" && block.level === 3 && (
101+
<h3 class="text-2xl font-bold my-4" style="color: var(--text);">
102+
{block.children.map((child) => (
103+
<Fragment>
104+
{child.code ? (
105+
<code class="bg-gray-100 text-gray-800 px-2 py-1 rounded text-sm font-mono">
106+
{child.text}
107+
</code>
108+
) : child.type === "link" ? (
109+
<a
110+
href={child.url}
111+
target={child.url?.startsWith("/") ? "_self" : "_blank"}
112+
rel="noopener noreferrer"
113+
class="text-blue-600 hover:text-pink-600 transition-colors underline"
114+
>
115+
{child.children?.[0]?.text || child.text}
116+
</a>
117+
) : (
118+
<span>{child.text}</span>
119+
)}
120+
</Fragment>
121+
))}
122+
</h3>
123+
)}
124+
125+
{block.type === "heading" && (block.level === 4 || !block.level) && (
126+
<h4 class="text-xl font-bold my-3 ">
127+
{block.children.map((child) => (
128+
<Fragment>
129+
{child.code ? (
130+
<code class="bg-gray-100 text-gray-800 px-2 py-1 rounded text-sm font-mono">
131+
{child.text}
132+
</code>
133+
) : child.type === "link" ? (
134+
<a
135+
href={child.url}
136+
target={child.url?.startsWith("/") ? "_self" : "_blank"}
137+
rel="noopener noreferrer"
138+
class="text-blue-600 hover:text-pink-600 transition-colors underline"
139+
>
140+
{child.children?.[0]?.text || child.text}
141+
</a>
142+
) : (
143+
<span>{child.text}</span>
144+
)}
145+
</Fragment>
146+
))}
147+
</h4>
148+
)}
149+
150+
{block.type === "heading" && block.level === 5 && (
151+
<h5 class="text-lg font-bold my-2" style="color: var(--text);">
152+
{block.children.map((child) => (
153+
<Fragment>
154+
{child.code ? (
155+
<code class="bg-gray-100 text-gray-800 px-2 py-1 rounded text-sm font-mono">
156+
{child.text}
157+
</code>
158+
) : child.type === "link" ? (
159+
<a
160+
href={child.url}
161+
target={child.url?.startsWith("/") ? "_self" : "_blank"}
162+
rel="noopener noreferrer"
163+
class="text-blue-600 hover:text-pink-600 transition-colors underline"
164+
>
165+
{child.children?.[0]?.text || child.text}
166+
</a>
167+
) : (
168+
<span>{child.text}</span>
169+
)}
170+
</Fragment>
171+
))}
172+
</h5>
173+
)}
174+
175+
{block.type === "heading" && block.level === 6 && (
176+
<h6 class="text-base font-bold my-2" style="color: var(--text);">
177+
{block.children.map((child) => (
178+
<Fragment>
179+
{child.code ? (
180+
<code class="bg-gray-100 text-gray-800 px-2 py-1 rounded text-sm font-mono">
181+
{child.text}
182+
</code>
183+
) : child.type === "link" ? (
184+
<a
185+
href={child.url}
186+
target={child.url?.startsWith("/") ? "_self" : "_blank"}
187+
rel="noopener noreferrer"
188+
class="text-blue-600 hover:text-pink-600 transition-colors underline"
189+
>
190+
{child.children?.[0]?.text || child.text}
191+
</a>
192+
) : (
193+
<span>{child.text}</span>
194+
)}
195+
</Fragment>
196+
))}
197+
</h6>
198+
)}
199+
200+
{/* Code blocks */}
201+
{block.type === "code" && (
202+
<div class="my-6">
203+
<pre class="bg-gray-900 text-green-400 p-4 rounded-lg overflow-x-auto">
204+
<code class="font-mono text-sm leading-relaxed">
205+
{block.children
206+
.map((child) => (child.code ? child.text : ""))
207+
.filter(Boolean)
208+
.join("\n")}
209+
</code>
210+
</pre>
211+
</div>
212+
)}
213+
214+
{/* List blocks */}
215+
{block.type === "list" && (
216+
<ul class="list-disc pl-6 my-4 space-y-2">
217+
{block.children
218+
.filter((child) => child.type === "list-item")
219+
.map((child) => (
220+
<li class="leading-relaxed">
221+
{child.children?.map((grandChild: any) => (
222+
<Fragment>
223+
{grandChild.type === "link" ? (
224+
<a
225+
href={grandChild.url}
226+
target={
227+
(grandChild.url || "").startsWith("/")
228+
? "_self"
229+
: "_blank"
230+
}
231+
rel="noopener noreferrer"
232+
class="text-blue-600 hover:text-pink-600 transition-colors underline"
233+
>
234+
{grandChild.text}
235+
</a>
236+
) : (
237+
<span>{grandChild.text}</span>
238+
)}
239+
</Fragment>
240+
))}
241+
</li>
242+
))}
243+
</ul>
244+
)}
245+
246+
{/* Quote blocks */}
247+
{block.type === "quote" && (
248+
<blockquote class="border-l-4 border-blue-500 pl-6 my-6 italic text-gray-700 bg-gray-50 py-4 rounded-r-lg">
249+
<div class="leading-relaxed">
250+
{block.children.map((child) => (
251+
<Fragment>
252+
{child.code ? (
253+
<code class="bg-gray-200 text-gray-800 px-2 py-1 rounded text-sm font-mono not-italic">
254+
{child.text}
255+
</code>
256+
) : child.type === "link" ? (
257+
<a
258+
href={child.url}
259+
target={child.url?.startsWith("/") ? "_self" : "_blank"}
260+
rel="noopener noreferrer"
261+
class="text-blue-600 hover:text-pink-600 transition-colors underline"
262+
>
263+
{child.children?.[0]?.text || child.text}
264+
</a>
265+
) : (
266+
<span>{child.text}</span>
267+
)}
268+
</Fragment>
269+
))}
270+
</div>
271+
</blockquote>
272+
)}
273+
274+
{/* Image blocks */}
275+
{block.type === "image" && block.image?.url && (
276+
<figure class="my-8">
277+
<div class="rounded-lg overflow-hidden shadow-lg">
278+
<img
279+
src={block.image.url}
280+
alt={
281+
(block.image as any).alternativeText ||
282+
(block.image as any).name ||
283+
""
284+
}
285+
class="w-full h-auto object-cover"
286+
width={block.image.width}
287+
height={block.image.height}
288+
loading="lazy"
289+
/>
290+
</div>
291+
{((block.image as any).caption ||
292+
(block.image as any).alternativeText ||
293+
(block.image as any).name) && (
294+
<figcaption class="text-center text-sm text-muted mt-3 italic">
295+
{(block.image as any).caption ||
296+
(block.image as any).alternativeText ||
297+
(block.image as any).name}
298+
</figcaption>
299+
)}
300+
</figure>
301+
)}
302+
</>
303+
))}
304+
</div>
305+
)
306+
}
307+
308+
<style>
309+
.blocks-content {
310+
max-width: none;
311+
line-height: 1.7;
312+
}
313+
314+
.blocks-content p {
315+
margin-bottom: 1rem;
316+
}
317+
318+
.blocks-content pre {
319+
font-size: 0.875rem;
320+
line-height: 1.6;
321+
}
322+
323+
.blocks-content code {
324+
font-family: "Fira Code", "Consolas", "Monaco", "Courier New", monospace;
325+
}
326+
327+
.blocks-content img {
328+
transition: transform 0.3s ease;
329+
}
330+
331+
.blocks-content img:hover {
332+
transform: scale(1.02);
333+
}
334+
335+
.blocks-content a {
336+
text-decoration-thickness: 2px;
337+
text-underline-offset: 2px;
338+
}
339+
340+
.blocks-content blockquote {
341+
position: relative;
342+
}
343+
344+
.blocks-content blockquote::before {
345+
content: '"';
346+
position: absolute;
347+
left: -0.5rem;
348+
top: -0.5rem;
349+
font-size: 3rem;
350+
color: #3b82f6;
351+
opacity: 0.3;
352+
}
353+
</style>

0 commit comments

Comments
 (0)