Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ pnpm-debug.log*
package-lock.json
pnpm-lock.yaml

.astro
.astro
astro_tmp_pages_*
15 changes: 13 additions & 2 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { fileURLToPath } from 'url';
import { defineConfig } from 'astro/config';

import sitemap from '@astrojs/sitemap';
import { i18n, defaultLocaleSitemapFilter } from "astro-i18n-aut/integration";
import tailwind from '@astrojs/tailwind';
import mdx from '@astrojs/mdx';
import partytown from '@astrojs/partytown';
Expand All @@ -13,7 +14,7 @@ import tasks from "./src/utils/tasks";

import { readingTimeRemarkPlugin } from './src/utils/frontmatter.mjs';

import { ANALYTICS_CONFIG, SITE_CONFIG } from './src/utils/config.ts';
import { ANALYTICS_CONFIG, SITE_CONFIG, I18N_CONFIG } from './src/utils/config.ts';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

Expand All @@ -35,7 +36,17 @@ export default defineConfig({
tailwind({
applyBaseStyles: false,
}),
sitemap(),
i18n({
locales : I18N_CONFIG.locales,
defaultLocale : I18N_CONFIG.defaultLocale,
}),
sitemap({
i18n: {
locales : I18N_CONFIG.locales,
defaultLocale : I18N_CONFIG.defaultLocale,
},
filter: defaultLocaleSitemapFilter({ defaultLocale : I18N_CONFIG.defaultLocale }),
}),
mdx(),
icon({
include: {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"tailwind-merge": "^1.14.0",
"tailwindcss": "^3.3.3",
"typescript": "^5.1.6",
"unpic": "^3.10.0"
"unpic": "^3.10.0",
"astro-i18n-aut": "^0.3.2"
},
"engines": {
"node": ">=16.12.0"
Expand Down
20 changes: 18 additions & 2 deletions src/components/common/BasicScripts.astro
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
import { UI_CONFIG } from '~/utils/config';
import { UI_CONFIG, I18N_CONFIG, SITE_CONFIG } from '~/utils/config';
---

<script is:inline define:vars={{ defaultTheme: UI_CONFIG.theme }}>
<script is:inline define:vars={{ defaultTheme: UI_CONFIG.theme, locales:I18N_CONFIG.locales, trailingSlash:SITE_CONFIG.trailingSlash }}>
function applyTheme(theme) {
if (theme === 'dark') {
document.documentElement.classList.add('dark');
Expand Down Expand Up @@ -62,6 +62,22 @@ import { UI_CONFIG } from '~/utils/config';
localStorage.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
});


attachEvent('[data-aw-select-language]', 'click', function (_, elem) {
const newLang = elem.value;
const oldUrl = window.location.href;
const supportedLangs = Object.keys(locales);

const urlWithoutOrigin = oldUrl.replace(window.location.origin, '');
const urlWithoutOriginLang = supportedLangs.reduce((acc, lang) => {
return acc.replace(`/${lang}`, '');
}, urlWithoutOrigin)
const newUrlWithoutTrailingSlash = urlWithoutOriginLang.replace(/\/$/, '');

const newUrl = `/${newLang}${newUrlWithoutTrailingSlash}${trailingSlash ? '/' : ''}`;
window.location.pathname = newUrl;
});

attachEvent('[data-aw-social-share]', 'click', function (_, elem) {
const network = elem.getAttribute('data-aw-social-share');
const url = encodeURIComponent(elem.getAttribute('data-aw-url'));
Expand Down
19 changes: 19 additions & 0 deletions src/components/common/LanguagePicker.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
import { getLocale } from 'astro-i18n-aut';
import { I18N_CONFIG } from '~/utils/config';
const currentLocale = getLocale(Astro.url);
---

<select
id="languagePicker"
class="px-4 py-2 rounded-md text-sm font-medium bg-white dark:bg-dark text-gray-700 dark:text-gray-300 focus:ring-1 focus:ring-blue-500 focus:border-blue-500 hover:bg-gray-100 dark:hover:bg-gray-700 transition duration-150 ease-in-out"
data-aw-select-language
>
{
Object.keys(I18N_CONFIG.locales).map((locale) => (
<option value={locale} selected={locale === currentLocale} class="py-1">
{locale.replace(/^([a-z])/, (match) => match.toUpperCase())}
</option>
))
}
</select>
4 changes: 3 additions & 1 deletion src/components/widgets/BlogHighlightedPosts.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getBlogPermalink } from "~/utils/permalinks";
import { findPostsByIds } from "~/utils/blog";
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
import type { Widget } from "~/types";
import { getLocaleFromUrl } from "~/i18n/translator";

export interface Props extends Widget {
title?: string;
Expand All @@ -29,7 +30,8 @@ const {
bg = await Astro.slots.render("bg"),
} = Astro.props;

const posts = APP_BLOG_CONFIG.isEnabled ? await findPostsByIds(postIds) : [];
const locale = getLocaleFromUrl(Astro.url);
const posts = APP_BLOG_CONFIG.isEnabled ? await findPostsByIds(postIds, locale) : [];
---

{
Expand Down
4 changes: 3 additions & 1 deletion src/components/widgets/BlogLatestPosts.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getBlogPermalink } from "~/utils/permalinks";
import { findLatestPosts } from "~/utils/blog";
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
import type { Widget } from "~/types";
import { getLocaleFromUrl } from "~/i18n/translator";

export interface Props extends Widget {
title?: string;
Expand All @@ -29,7 +30,8 @@ const {
bg = await Astro.slots.render("bg"),
} = Astro.props;

const posts = APP_BLOG_CONFIG.isEnabled ? await findLatestPosts({ count }) : [];
const locale = getLocaleFromUrl(Astro.url);
const posts = APP_BLOG_CONFIG.isEnabled ? await findLatestPosts({ count }, locale) : [];
---

{
Expand Down
2 changes: 2 additions & 0 deletions src/components/widgets/Header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Icon } from "astro-icon/components";
import Logo from "~/components/Logo.astro";
import ToggleTheme from "~/components/common/ToggleTheme.astro";
import ToggleMenu from "~/components/common/ToggleMenu.astro";
import LanguagePicker from "../common/LanguagePicker.astro";

import { getHomePermalink } from "~/utils/permalinks";
import { trimSlash, getAsset } from "~/utils/permalinks";
Expand Down Expand Up @@ -142,6 +143,7 @@ const currentPath = `/${trimSlash(new URL(Astro.url).pathname)}`
</a>
)
}
<LanguagePicker />
</div>
{
actions?.length ? (
Expand Down
5 changes: 4 additions & 1 deletion src/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ metadata:
cardType: summary_large_image

i18n:
language: en
defaultLocale: en
locales:
en: en-US
it: it-IT
textDirection: ltr

apps:
Expand Down
209 changes: 209 additions & 0 deletions src/content/post/it/astrowind-template-in-depth.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
---
publishDate: 2023-07-17T00:00:00Z
title: Approfondimento sul template AstroWind
excerpt: Sebbene sia facile iniziare, AstroWind è abbastanza complesso internamente. Questa pagina fornisce la documentazione su alcune delle parti più intricate.
image: https://images.unsplash.com/photo-1534307671554-9a6d81f4d629?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1651&q=80
category: Documentation
tags:
- astro
- tailwind css
- front-end
metadata:
canonical: https://astrowind.vercel.app/it/astrowind-template-in-depth
---


import DListItem from '~/components/ui/DListItem.astro';
import ToggleTheme from '~/components/common/ToggleTheme.astro';

## Panoramica

Può essere un compito piuttosto imponente cercare di capire le componenti interne di _AstroWind_, e in particolare vari punti di utilizzo.

Questa pagina descrive e chiarisce alcune delle tecniche trovate in _AstroWind_. Utilizzala come guida per ulteriori modifiche o come istruzione per le tecniche da utilizzare nei tuoi progetti.

## Stile

Come suggerisce il nome, _AstroWind_ si basa su _TailWind_ per lo stile. Inoltre, _AstroWind_ definisce impostazioni di stile personalizzate a basso livello, che vengono incorporate in _TailWind_ in modo uniforme, fornendo coerenza per le costruzioni di stile di livello superiore e consentendo anche la modalità scura.

Il meccanismo di stile è composto dai seguenti file (tutti i percorsi sono preceduti da `/src/`):

<DListItem dt="assets/styles/tailwind.css">
Questo file è essenzialmente un'estensione di base.css di _TailWind_. Gli stili dei componenti di alto livello sono definiti qui. Nota
anche lo stile sugli elementi selezionati dai selettori 'attributo' alla fine dei file, in particolare quelli selezionati da
attributi 'data'.
</DListItem>
<DListItem dt="components/CustomStyles.astro">
Definisce colori e caratteri personalizzati. Per far sì che questi abbiano effetto nel file 'base.css', devono essere caricati nella sezione
dell'intestazione html. Vedi sotto.
</DListItem>
<DListItem dt="layouts/Layout.astro">
Questo layout è utilizzato per tutte le pagine renderizzate da _AstroWind_. I contenuti di _tailwind.css_ e del componente _CustomStyles.astro_,
descritti sopra, vengono iniettati nell'intestazione html.
</DListItem>

### Modalità scura

La _Modalità scura_ viene attivata dall'icona del 'sole': <ToggleTheme/>nell'intestazione della pagina. È definita in _components/common/ToggleTheme.astro_, ma l'evento è collegato e l'azione è definita in _components/common/BasicScripts.astro_ nel seguente snippet:

```javascript
attachEvent('[data-aw-toggle-color-scheme]', 'click', function () {
if (defaultTheme.endsWith(':only')) {
return;
}
document.documentElement.classList.toggle('dark');
localStorage.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
});
```

Nota che questo è un evento lato client. _BasicScripts.astro_ definisce anche diverse altre funzionalità lato client oltre a questa.

## Utilizzo avanzato degli slot

_Gli slot_ fanno parte dell'implementazione del componente, che è un concetto comune in molti framework, inclusi _Astrojs_. La tipica definizione di uno slot in un componente appare così:

```astro
---
// (file: MyComponent.astro)
const { title } = Astro.props;
export interface Props {
title: string;
}
---

<div>
<h2>{title}</h2>
<slot />
<!-- qui verranno iniettati i contenuti dello slot -->
<div></div>
</div>
```

E nell'uso altrove:

```astro
import MyComponent from "~/components/MyComponent"; ...
<MyComponent someArg="Un esempio di slot">
<p>Questo contenuto verrà visualizzato nello slot</p>
</MyComponent>
```

### Utilizzo alternativo

C'è un altro modo in cui possiamo utilizzare gli slot, particolarmente utile quando un componente può contenere del contenuto in markdown, come segue (studiare attentamente...):

```astro
---
// (file: MyComponent.astro)

const { title } = Astro.props;
export interface Props {
title: string;
}
const content: string = await Astro.props.render('default');
---

// renderizza l'HTML nella variabile 'content'
<div>
<h2>{title}</h2>
<div set:html={content} />
<!-- qui verranno iniettati i contenuti dello slot -->
<div></div>
</div>
```

Whoa!! Cosa sta succendendo qui?

Nota che non c'è una definizione di slot nella parte HTML del componente. Invece, quello che facciamo è far sì che _Astro_ renda il contenuto dello slot (qui, il contenuto 'default', ma è possibile anche rendere slot con nomi) in una variabile e quindi utilizzare quel contenuto in un _div_ (ad esempio).

Pertanto, se l'uso è in un file markdown, come segue:

```mdx
import MyComponent from '../../components/MyComponent';

# Utilizzando il componente sopra in un file .mdx (che può accettare componenti)

{' '}

<MyComponent title="Questo è un implementatore di slot">### Ecco un po' di contenuto in markdown - Con un elemento elenco.</MyComponent>
```

_MyComponent_ rende il markdown in HTML e poi lo inietta nel div.

Questo ha effettivamente un grande vantaggio: considera che con l'uso normale non hai accesso ai contenuti dello slot: _Astro_ semplicemente posiziona il contenuto nel tag _&lt;slot/&gt;_. Utilizzando questo metodo, tuttavia, puoi accedere al contenuto e manipolarlo ulteriormente prima che venga inserito nell'HTML.

Ciò permette una grande flessibilità nella progettazione dei componenti.

### Un Altro Passo Avanti

Ora, arriviamo alle tecniche utilizzate in _AstroWind_, useremo il file _pages/index.astro_ per illustrare.

Noterai che il file index importa molti componenti, ciascuno approssimativamente analogo a un pannello nella pagina index. Ciascuno di questi componenti, a sua volta, viene istanziato sequenzialmente in tutta la pagina. Ma noterai che alcuni di essi usano questa struttura (useremo l'ultima sezione, _CallToAction_, poiché è la più illustrativa della tecnica):

```astro
<CallToAction
callToAction={{
text: 'Ottieni il template',
href: 'https://github.com/onwidget/astrowind',
icon: 'tabler:download',
}}
>
<Fragment slot="title">
Astro + <br class="block sm:hidden" /><span class="sm:whitespace-nowrap">Tailwind CSS</span>
</Fragment>

<Fragment slot="subtitle">
Sorprenditi molto da questi enormi numeri falsi che stai vedendo in questa pagina. <br class="hidden md:inline" />Non perdere
altro tempo! :P
</Fragment>
</CallToAction>
```

Alcuni punti da notare qui:

<DListItem dt="L'argomento <em>callToAction</em>">
Questo argomento viene effettivamente passato come un oggetto JavaScript, non come una stringa. (Tuttavia, nella definizione in TS, potrebbe
essere una stringa...)
</DListItem>
<DListItem dt="Ci sono diversi elementi <em>Fragment</em> figli">
Inoltre, questi elementi &lt;Fragment/&gt; hanno ciascuno uno specificatore _slot="(valore)"_.
</DListItem>

Quest'ultimo sembra strano, perché &lt;Fragment/&gt; è un componente integrato su cui non hai controllo e non ha una disposizione per il rendering degli slot, <em>di per sé</em>.

La risposta si trova in un paragrafo nella sezione degli slot della documentazione di _Astro_, che afferma:

> Utilizza l'attributo `slot="my-slot"` sull'elemento figlio che vuoi far passare a uno slot corrispondente `name="my-slot" />` nel componente.

È abbastanza conciso e potrebbe sembrare un po' complicato da comprendere, ma fondamentalmente dice quanto segue:

1. Data una componente che definisce uno slot:
1. puoi fare riferimento a uno slot da un elemento figlio di quella componente e,
1. fornire contenuto allo slot del componente genitore dal figlio nominando lo slot nel figlio con l'assegnazione della proprietà `slot="<nome-slot>"`, dove il _nome-slot_ è lo slot del genitore.

Quindi, nell'esempio sopra, il componente _CallToAction_ definisce lo slot _subtitle_, e il seguente _&lt;Fragment slot="subtitle"&gt;_ popola lo slot con il seguente contenuto:

```astro
<Fragment slot="subtitle">
Sorprenditi molto da questi enormi numeri falsi che stai vedendo in questa pagina. <br class="hidden md:inline" />Non perdere
altro tempo! :P
</Fragment>
```

E, il componente _CallToAction_ lo definisce e lo renderizza in questo modo:


```astro
---
//...
const { subtitle = await Astro.slots.render('subtitle') } = Astro.props;
---

//...
{subtitle && <p class="text-xl text-muted dark:text-slate-400" set:html={subtitle} />}
//...
```

C'è molto da capire qui.

Nota innanzitutto che _subtitle_ è definito come un argomento prop/argomento, ma viene elaborato come uno slot. È interessante notare che gli argomenti prop/argomenti e gli slot sembrano essere in qualche modo interscambiabili: se _subtitle_ fosse semplicemente una stringa, prenderebbe semplicemente quell'assegnazione. La principale differenza è che se li renderizzi in modo indipendente, devi chiamare il render con un modificatore _await_.
Loading