No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Markdown

13/25
Recursos

Aportes 10

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

En mi caso yo decidí aprovechar otra de las caracteristicas de Astro para hacer esto mismo, y es el uso de colecciones. Esto nos permite generar un esquema con todos los atributos necesarios que deben tener los contenidos que entren dentro de la colección. Para crear nuestras colecciones debemos definir un archivo config.ts con las colecciones que usaremos:

Ejemplo

import { z, defineCollection } from 'astro:content';

const postCollection = defineCollection({
  schema: z.object({
    title: z.string(),
    pubDate: z.string().datetime(),
    description: z.string(),
    image: z.string().optional(),
    tags: z.array(z.string()),
  }),
});

export const collections = {
  'posts': postCollection,
};

Astro viene con zod, una librería que nos permite generar una validación de esquemas con TypeScript, de está forma definimos las propiedades que debe cumplir nuestra colección, que crearemos con la función defineCollection. Por último exportamos un objeto collections con nuestras colecciones. Es importante saber que debe existir una carpeta con el mismo nombre por colección creada, y en dicha carpeta se encontrarán los ficheros pertenecientes a la colección.

Para consumir dicha colección en el index.astro hacemos lo siguiente:

---
import { getCollection } from "astro:content";
import Layout from "../layouts/Layout.astro"
import Card from "../components/Card.astro"
import Header from "../components/Header.astro";
import Hero from "../components/Hero.astro";

const postEntries = await getCollection('posts');
---

<Layout title="Astro Testing">
	<main>
		<Header title="Astro Testing"/>
		<Hero />
		<ul role="list" class="link-card-grid">
			{postEntries.map(post => (
				<Card title={post.data.title} time={post.data.pubDate} tags={post.data.tags}/>
			))}
		</ul>
	</main>
</Layout>

<style>
	main {
		margin: auto;
		padding: 1.5rem;
		max-width: 60ch;
	}
	.link-card-grid {
		display: grid;
		grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
		gap: 1rem;
		padding: 0;
	}
</style>

En este caso usamos la función getCollections para obtener todos los ficheros, y accedemos a los atributos del mismo a través de la propiedad data.

Otra forma de hacer esto es usando colecciones.
 
Una colección es cualquier directorio dentro de src/content
https://docs.astro.build/en/guides/content-collections
 

Creamos un subdirectorio dentro de content, en este subdirectorio incluimos nuestros archivos .md
https://docs.astro.build/en/guides/content-collections/#organizing-with-multiple-collections

📂content
		📂tips <- (este el el nuevo subdirectorio)
				-📄hello-astro.md
				-📄hello-js.md
				-📄hello-world.md

Luego modificamos nuestro archivo index.astro añadiendo getCollection (Esta función provista por Astro nos permite ejecutar una query la cual nos trae los elementos dentro de nuestro directorio content)
https://docs.astro.build/en/guides/content-collections/#querying-collections

// src/pages/index.astro
// ... other components
import { getCollection } from 'astro:content';
const allPosts = await getCollection('tips'); // Obtenemos la coleccion por el nombre de su directorio (tips)

//... layout
{
  allPosts.map(item=>(
    <Card
      title={item?.data?.title}
      time={item?.data?.pubDate}
      tags={item?.data?.tags}
    />
  ))
}

Usamos data envez de frontmatter.
 
Así quedaría nuestro archivo:

// src/pages/index.astro
---
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
import Header from '../components/Header.astro'
import Hero from '../components/Hero.astro';

import { getCollection } from 'astro:content';

const allPosts = await getCollection('tips');

---
<Layout title="Welcome to Astro.">
	<main>
		<Header title="Astro Tutorial"/>
		<Hero/>
		<ul role="list" class="link-card-grid">
      {
        allPosts.map(item=>(
          <Card
            title={item?.data?.title}
            time={item?.data?.pubDate}
            tags={item?.data?.tags}
          />
        ))
      }
		</ul>
	</main>
</Layout>
// ... styles

Hay algo que no se explicó en la clase, y es ¿Cómo renderizar el contenido del markdown en el componente Card?

En la clase, el profesor muestra que le pasa al componente Card por props el title, time y tags, los cuales obtiene de los archivos markdown en la propiedad frontmatter al realizar el map del array obtenido de Astro.glob().

Pero, el contenido como tal del markdown, ¿cómo los muestro en el componente?

  1. Debemos crear un <slot /> en el componente Card, donde ubicaremos el contenido a renderizar

Card.astro

//... contenido del componente

		<p class="mt-2 text-sm leading-relaxed text-gray-500 line-clamp-3">
			<slot /> <!-- su contenido es inyectado aquí -->
		</p>
		<div class="mt-4 flex flex-wrap gap-1">
			{
				tags.map((tag) => (
					<span class="whitespace-nowrap rounded-full bg-purple-100 px-2.5 py-0.5 text-xs text-purple-600">
						{tag}
					</span>
				))
			}
		</div>
  1. Astro nos proporciona en cada objeto del array devuelto por Astro.glob() un componente llamado Content que devuelve el contenido completo y renderizado del archivo.
    Debemos abrir y cerrar el componente Card, <Card></Card> para que podamos inyectar contenido en el slot, y adentro poder llamar el componente de esta forma:

Suponiendo que post es la variable que renderiza el objeto en el map, se llama a: <post.Content />

<Layout title="Welcome to Astro.">
	<main class="">
		<Header title="Astro Ameth" />
		<Hero />
		<ul role="list" class="link-card-grid">
      {
        allPost.map(post => {
          return <Card title={post.frontmatter.title} time={post.frontmatter.pubDate} tags={post.frontmatter.tags}><post.Content /></Card>
        })
      }
			
		</ul>
	</main>
</Layout>

Este componente renderizará el archivo en formato markdown que interprete el navegador.

Markdown

Markdown se usa comúnmente usado para crear contenido, como publicaciones de blog y documentación. Dicha lenguaje, en Astro se incluye el soporte para documentos en Markdown.
.
Al igual que otros contenidos, podemos generar rutas como vistas dentro del subdirectorio ./src/pages.
.
src/pages/page-1.md

---
title: Hello, World
---

# Hi there!

This Markdown file creates a page at `your-domain.com/page-1/`

It probably isn't styled much, but Markdown does support:
- **bold** and _italics._
- lists
- [links](https://astro.build)
- and more!

Como característica especial, con Markdown podemos generar contenido a partir de colecciones.
.

✨ Concepto clave
Las colecciones nos ayudan a organizar nuestro contenido en volumen, similar entre sí para generar catálogos o grupos taxonómicos de información (productos, autores, etc.).

.

Características de Markdown

Astro, provee de utilidades como características con los que potencian el uso de Markdown, inyectando y vinculando propiedades útiles como metadata, enrutamiento, etc.
.
Para el caso de metadata, podemos definir atributos de nuestro contenido para después ser presentado y organizado por algún layout mediante frontmatter
.
src/pages/posts/post-1.md

---
layout: ../../layouts/BlogPostLayout.astro
title: Astro in brief
author: Himanshu
description: Find out what makes Astro awesome!
--- 
This is a post written in Markdown.

.
src/layouts/BlogPostLayout.astro

---
const {frontmatter} = Astro.props;
---
<html>
  <!-- ... -->
  <h1>{frontmatter.title}</h1>
  <h2>Post author: {frontmatter.author}</h2>
  <p>{frontmatter.description}</p>
  <slot /> <!-- Markdown content is injected here -->
   <!-- ... -->
</html>

Importando contenido en Markdown

Pese a que podemos emplear una página escrita en Markdown para que, después sea dispuesta en el router. Podemos emplear el contenido de Markdown como un repositorio de contenido y disponerla en una página, escrita en .astro por ejemplo, para organizarla según alguna presentación.
.
/src/pages/posts/great-post.md

---
title: 'The greatest post of all time'
author: 'Ben'
---

Here is my _great_ post!

.
src/pages/my-posts.astro

---
interface Frontmatter {
  title: string;
  author: string;
	description?: string;
}

import * as greatPost from '../pages/post/great-post.md';

const posts = await Astro.glob<Frontmatter>('../pages/post/*.md');
---

<p>{greatPost.frontmatter.title}</p>
<p>Written by: {greatPost.frontmatter.author}</p>

<p>Post Archive:</p>
<ul>
  {posts.map(post => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}
</ul>

📌 Referencia
Para conocer las propiedades disponibles al importar contenido en Markdown o MDX:
Markdown & MDX

.

Content Collections

Las colecciones son una característica de Astro que ayudan a administrar, en documentos de Markdown o MDX, el contenido de algún proyecto. Las colecciones ayudan a organizar su contenido, validan su material de presentación y brindan seguridad automática de tipos de TypeScript para todo el contenido.
.

✨ Concepto clave
Las colecciones de contenido son la mejor forma de trabajar con Markdown y MDX en cualquier proyecto de Astro.

.
Las colecciones son recursos encontrados en el subdirectorio ./src/content.
.

Desarrollo de Collections

ⴵ Repositorio - Coffeeroasters

⬢ Commit - feat: ✨added content collection documents

⬢ Commit - feat: ✨added product components

.
Como se mencionó, las colecciones son parte fundamental de un contenido en sitios web. Su identificación se hace evidente por la dependencia e iteración visual que será servido durante la narrativa de nuestra vista o página.
.

✨ Concepto clave
Las colecciones será de gran utilidad cuando disponemos y consumimos recursos específicos agrupados (posts-post, authors-author, products-product, etc.).

.

.
Podemos analizar 2 componentes claro que distribuye nuestra colección de productos:

  • Products Gallery - Componente para distribuir en grid nuestros productos existentes
  • Product Item - Componente que representa a un producto

.
De aquí, se menciona la primera estructura visual de alguna colección, lo cual ganamos administración para aislar (similar a un modelo en la arquitectura MVC).
.
Siguiendo la 📚 documentación, se organiza nuestras colecciones en el subdirectorio ./src/content. El cual, al lanzar nuestro proyecto en dev o build, creará y sincronizará un directorio llamado .astro.
.

ℹ️ Definición
. astro es un directorio donde gestiona los tipos de las colecciones generadas por Astro, si fuera el caso sincronizarlas manualmente, por algún tipo de error, corremos el comando astro sync.
Se recomienda omitirlo en el archivo .gitignore

.
Al componentizar nuestra aplicación, podemos dividir en piezas nuestros diferentes componentes (diseño basado en composición), del cual tendríamos los siguientes componentes.
.
./src/componentes/Products/Item.astro

---
interface Props {
    title: string
    image: string
    content: string
}

const { title, image, content } = Astro.props
---

<div class='product-item'>
    <img src={image} alt={title} />
    <div class='product-item__body'>
        <h3>{title}</h3>
        <p>{content}</p>
    </div>
</div>

El cual será consultado y gestionado por un componente de tipo wrapper, el cual para su uso dependenerá de las colecciones, como modelos, y el producto como plantilla de representación.
.
./src/componentes/Products/Gallery.astro

---
import { getCollection } from 'astro:content'
import Product from './Item.astro'
const products = await getCollection('products')
---

<div class='products-gallery'>
    {products.map(product => (
        <Product title={product.data.title}
                 image={product.data.image}
                 content={product.body} />
    ))}
</div>

.

✨ Concepto clave
Las variantes visuales o de organización de nuestros componentes, pueden estar contenida en su generalización, como Products. Permitiendo utilizar sus diferentes presentaciones de manera selectiva, ProductsGallery y/o ProductsItem.

.
Como se observa, se consumirá de nuestro contenido la siguiente definición de colecciones:
.
./src/content/products/danche.md

---
title: Danche
image: /images/products/danche.png
---

Ethiopian hand-harvested blend densely packed with vibrant fruit notes.

.

✨ Concepto clave
Donde Astro nos recomienda delimiar y configurar nuestras colecciones para así, extender los diferentes arquetipos de nuestro producto web.

.
`./src/content/config.ts

import { z, defineCollection } from 'astro:content'

export const collections = {
    products: defineCollection({
        schema: z.object({
            title: z.string(),
            image: z.string(),
        }),
    }),
}

Finalmente, lo disponemos como contenido de nuestra página en una sección.
.
./src/pages/index.astro

---
import ProductsGallery from '@components/Products/Gallery.astro'
---

<Default>

        <section class='products'>
            <h2>Our premium collection</h2>
            <ProductsGallery />
        </section>

    </main>
</Default>

.

ⴵ Repositorio - Coffeeroasters

⬢ Commit - feat: ✨added content collection documents

⬢ Commit - feat: ✨added product components

En mi caso, yo agregue una nueva prop para añadir un pequeño resumen a la tarjeta:
El operador de **encadenamiento opcional** `?.` permite leer el valor de una propiedad ubicada dentro de una cadena de objetos conectados sin tener que validar expresamente que cada referencia en la cadena sea válida. El operador `?.` funciona de manera similar a el operador de encadenamiento `.`, excepto que en lugar de causar un error si una referencia es [casi-nula](https://developer.mozilla.org/en-US/docs/Glossary/Nullish "Esta página está disponible solo en inglés") ([`null`](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/null) o [`undefined`](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/undefined)), la expresión hace una evaluación de circuito corto con un valor de retorno de `undefined`. Cuando se usa con llamadas a funciones, devuelve `undefined` si la función dada no existe.
Hola, alguien sabe por que esta pasando esto: ![](https://static.platzi.com/media/user_upload/image-a26f0c9d-e441-4816-ad1f-70c5fdd52f46.jpg) Literlamente copie y pegue el codigo del profe y no funciona!
**Falto conectar los contenidos Markdown con Card.astro, en la parte superior de cada archivo que hicimos en markdown nómas hay que agregarle esta línea:** \--- title: "Hello-javascript" pubDate: 2024-05-07 tags: \["astro", "javascript"] **card: "../components/Card.astro"** \---

.