Diamo un'occhiata al progetto Astro installato nella lezione precedente. La cartella src
contiene cinque sottocartelle:
src/components
contiene i componenti che costituiscono le singole parti delle pagine del sito;src/content
contiene una serie di file.md
di esempio. Non utilizzeremo questi file in quanto importeremo i nostri contenuti da WordPress;src/layouts
contiene il layoutBlogPost.astro;
src/pages
contiene la cartellablog
e i due fileabout.astro
eindex.astro
;src/styles
contiene il foglio di stileglobal.css
.
Per creare un blog popolato con gli articoli di un sito WordPress, riscriveremo il codice dei seguenti file:
src/pages/blog/index.astro
;src/components/FormattedDate.astro
.
Creeremo, inoltre, un nuovo layout:
src/layouts/PostPreview.astro
;
Utilizzeremo ancora, ma senza modificarne il codice, i componenti BaseHead
, Header
e Footer
.
Il componente index.astro
La cartella /src/pages/blog
contiene i seguenti file:
[...slug].astro
;index.astro
;
Il file index.astro
è responsabile della generazione del blog, mentre il file [...slug].astro
rende a video i singoli post. Apriamo dunque il file index.astro
e sostituiamo il frontmatter presente con quello che segue:
---
import PostPreview from '../../layouts/PostPreview.astro';
import FormattedDate from '../../components/FormattedDate.astro';
let res = await fetch("https://developer.wordpress.org/news/wp-json/wp/v2/posts?per_page=21&_fields=id,slug,date,title,excerpt,content,link,_links&_embed=author,wp:featuredmedia,wp:term");
let posts = await res.json();
---
Abbiamo utilizzato la clausola import
per importare le risorse necessarie. Abbiamo, poi, utilizzato il metodo fetch()
con l'operatore await
per recuperare i dati.
Passiamo poi al template della pagina, che diventerà il seguente:
<PostPreview tytle="Blog">
<section>
<ul>
{
posts.map((post) => (
<li>
<a href={`/blog/${post.slug}/`}>
<!-- See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined#typeof_operator_and_undefined -->
<img src={typeof post._embedded['wp:featuredmedia'] !== "undefined" ? post._embedded['wp:featuredmedia']['0'].media_details.sizes.large.source_url : 'https://images.pexels.com/photos/270404/pexels-photo-270404.jpeg'} alt="" />
<h4 class="title">{post.title.rendered}</h4>
<FormattedDate date={post.date} />
</a>
</li>
))
}
</ul>
</section>
</PostPreview>
Grazie al metodo map
, abbiamo generato una lista di elementi utilizzando i dati recuperati dall'API:
post.slug
contiene lo slug del post;post._embedded['wp:featuredmedia'].media_details.sizes.medium.source_url
fornisce l'URL dell'immagine di anteprima del post;post.title.rendered
contiene il titolo del post;post.date
contiene la data del post.
L'operatore ternario ci permette di assegnare l'URL di un'immagine sostitutiva nel caso in cui non venga trovata l'immagine di anteprima del post.
Infine, utilizziamo il componente FormattedDate
assegnando alla proprietà date
il valore della data di pubblicazione del post corrente. Andiamo ora a riscrivere il codice di FormattedDate
.
La formattazione della data di pubblicazione dei post
Il file FormattedDate.astro
è nella cartella src/components
. Apriamolo e sostituiamo il codice presente con quello che segue:
---
const { date } = Astro.props;
let pubDate = new Date(date);
---
<time datetime={pubDate.toISOString()}>
{
pubDate.toLocaleDateString('it-IT', {
year: 'numeric',
month: 'long',
day: 'numeric',
})
}
</time>
La proprietà date
del componente FormattedDate
viene passata al costruttore Date
. La data così ottenuta viene assegnata alla variabile pubDate
.
La data viene convertita in una stringa in formato date time grazie al metodo toISOString
e assegnata all'attributo datetime
dell'elemento time
. Infine, il metodo toLocaleDateString
ci permette di convertire la data in formato locale 'it-IT'
.
L'anteprima dei post
Ora creiamo un nuovo file PostPreview.astro
nella cartella src/layouts
e scriviamo il codice del frontmatter:
---
import BaseHead from '../components/BaseHead.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
---
BaseHead
, Header
e Footer
sono tre componenti di cui disponiamo di default grazie al template scelto al momento dell'installazione. BaseHead
genera il contenuto della sezione di testa della pagina (prevalentemente elementi link
e meta
), Header
e Footer
generano rispettivamente la parte superiore e inferiore delle pagine.
SITE_TITLE
e SITE_DESCRIPTION
sono due costanti dichiarate nel file src/consts.ts
.
Passiamo al template del componente.
<!doctype html>
<html lang="en">
<head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
<style is:global>...</style>
</head>
<body>
<Header />
<main>
<slot />
</main>
<Footer />
</body>
</html>
Abbiamo assegnato i valori di SITE_TITLE
e SITE_DESCRIPTION
agli attributi title
e description
dell'elemento BaseHead
per la generazione dei meta tag title
e description
.
Per brevità non riportiamo gli stili, rinviando al codice dell'installazione. Ci limitiamo ad evidenziare la direttiva is:global
del tag style
. Questa stabilisce che gli stili qui definiti devono essere applicati su tutte le pagine del sito. Il resto del codice è autoesplicativo. Si noti solo il tag slot
, che durante il rendering viene sostituito dal template del file index.astro
.
Ora apriamo nel browser http://localhost:4321/
, facciamo clic sulla scheda "Blog" e diamo un'occhiata al blog del nostro sito.
Nel prossimo capitolo creeremo le pagine dei singoli articoli e una pagina di archivio con la relativa paginazione.