|
| 1 | +--- |
| 2 | +title: Agregar una fuente RSS |
| 3 | +description: Agrega una fuente RSS a tu sitio Astro para que los usuarios puedan suscribirse a tu contenido. |
| 4 | +i18nReady: true |
| 5 | +type: recipe |
| 6 | +--- |
| 7 | + |
| 8 | +import Since from '~/components/Since.astro'; |
| 9 | +import { Steps } from '@astrojs/starlight/components'; |
| 10 | +import ReadMore from '~/components/ReadMore.astro'; |
| 11 | +import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro'; |
| 12 | + |
| 13 | +Astro permite generar de forma rápida y automática fuentes RSS para blogs y otras páginas web con contenido. Las fuentes RSS ofrecen a los usuarios una forma sencilla de suscribirse a tu contenido. |
| 14 | + |
| 15 | +## Configuración de `@astrojs/rss` |
| 16 | + |
| 17 | +El paquete [`@astrojs/rss`](https://github.com/withastro/astro/tree/main/packages/astro-rss) ofrece funciones de utilidad para generar fuentes RSS mediante [endpoints de la API](/es/guides/endpoints/#static-file-endpoints). Esto permite tanto las compilaciones estáticas como la generación bajo demanda al usar un [adaptador SSR](/es/guides/on-demand-rendering/). |
| 18 | + |
| 19 | +<Steps> |
| 20 | +1. Instala `@astrojs/rss` con tu gestor de paquetes preferido: |
| 21 | + |
| 22 | + <PackageManagerTabs> |
| 23 | + <Fragment slot="npm"> |
| 24 | + ```shell |
| 25 | + npm install @astrojs/rss |
| 26 | + ``` |
| 27 | + </Fragment> |
| 28 | + <Fragment slot="pnpm"> |
| 29 | + ```shell |
| 30 | + pnpm add @astrojs/rss |
| 31 | + ``` |
| 32 | + </Fragment> |
| 33 | + <Fragment slot="yarn"> |
| 34 | + ```shell |
| 35 | + yarn add @astrojs/rss |
| 36 | + ``` |
| 37 | + </Fragment> |
| 38 | + </PackageManagerTabs> |
| 39 | + |
| 40 | + :::tip |
| 41 | + Asegúrate de haber [configurado un `site`](/es/reference/configuration-reference/#site) en el archivo `astro.config` de tu proyecto. Se usará para generar enlaces a tus artículos RSS. |
| 42 | + ::: |
| 43 | + |
| 44 | +2. Crea un archivo en `src/pages/` con el nombre que prefieras y la extensión `.xml.js`, que se usará como URL de salida para tu fuente RSS. Algunos nombres habituales para las URL de fuentes RSS son `feed.xml` o `rss.xml`. |
| 45 | + |
| 46 | + El archivo de ejemplo que aparece a continuación, `src/pages/rss.xml.js`, creará una fuente RSS en `site/rss.xml`. |
| 47 | + |
| 48 | +3. Importa la función auxiliar `rss()` del paquete `@astrojs/rss` a tu archivo `.xml.js` y exporta una función que la devuelva usando los siguientes parámetros: |
| 49 | + |
| 50 | + ```js title="src/pages/rss.xml.js" |
| 51 | + import rss from '@astrojs/rss'; |
| 52 | + |
| 53 | + export function GET(context) { |
| 54 | + return rss({ |
| 55 | + // Campo `<title>` en el XML de salida |
| 56 | + title: 'Blog de Buzz', |
| 57 | + // Campo `<description>` en el XML de salida |
| 58 | + description: 'Una humilde guía de un astronauta para conocer las estrellas', |
| 59 | + // Obtén el "site" de tu proyecto a partir del contexto del endpoint |
| 60 | + // https://docs.astro.build/es/reference/api-reference/#site |
| 61 | + site: context.site, |
| 62 | + // Una lista de elementos `<item>` en el XML de salida |
| 63 | + // Consulta la sección "Generación de items" para ver ejemplos en los que se usan colecciones de contenido e importaciones globales. |
| 64 | + items: [], |
| 65 | + // (opcional) insertar XML personalizado |
| 66 | + customData: `<language>es-ES</language>`, |
| 67 | + }); |
| 68 | + } |
| 69 | + ``` |
| 70 | +</Steps> |
| 71 | + |
| 72 | +<ReadMore>See the [`@astrojs/rss` README](https://github.com/withastro/astro/tree/main/packages/astro-rss) for the full configuration reference.</ReadMore> |
| 73 | + |
| 74 | +## Generación de `items` |
| 75 | + |
| 76 | +El campo `items` acepta una lista de objetos de fuentes RSS, que pueden generarse a partir de entradas de colecciones de contenido mediante `getCollection()` o a partir de los archivos de tus páginas mediante `pagesGlobToRssItems()`. |
| 77 | + |
| 78 | +El formato estándar de las fuentes RSS incluye metadatos para cada elemento publicado, entre los que se encuentran valores como: |
| 79 | + |
| 80 | +- `title`: El título de la entrada. Es opcional solo si se ha establecido una `descripción`. En caso contrario, es obligatorio. |
| 81 | +- `description`: Un breve extracto de la entrada o una descripción de la misma. Opcional solo si se ha establecido un `título`. En caso contrario, es obligatorio. |
| 82 | +- `link`: Una URL que remita a la fuente original de la entrada. (opcional) |
| 83 | +- `pubDate`: La fecha de publicación de la entrada. (opcional) |
| 84 | +- `content`: El contenido completo de tu publicación. (opcional) |
| 85 | + |
| 86 | +<ReadMore>Consulta la [referencia de configuración de `items`](https://github.com/withastro/astro/tree/main/packages/astro-rss#items) para ver una lista completa de opciones.</ReadMore> |
| 87 | + |
| 88 | +### Uso de colecciones de contenidos |
| 89 | + |
| 90 | +Para crear un canal RSS de las páginas gestionadas en [colecciones de contenido](/es/guides/content-collections/), usa la función `getCollection()` para recuperar los datos necesarios para tu lista de `items`. Tendrás que especificar los valores de cada propiedad deseada (p. ej., `title`, `description`) a partir de los datos devueltos. |
| 91 | + |
| 92 | +```js title="src/pages/rss.xml.js" "items:" "const blog = await getCollection('blog');" |
| 93 | +import rss from '@astrojs/rss'; |
| 94 | +import { getCollection } from 'astro:content'; |
| 95 | + |
| 96 | +export async function GET(context) { |
| 97 | + const blog = await getCollection('blog'); |
| 98 | + return rss({ |
| 99 | + title: 'Blog de Buzz', |
| 100 | + description: 'Una humilde guía de un astronauta para conocer las estrellas', |
| 101 | + site: context.site, |
| 102 | + items: blog.map((post) => ({ |
| 103 | + title: post.data.title, |
| 104 | + pubDate: post.data.pubDate, |
| 105 | + description: post.data.description, |
| 106 | + // Computa el enlace RSS a partir del `id` de la entrada |
| 107 | + // En este ejemplo se da por hecho que todas las entradas se muestran mediante rutas del tipo `/blog/[id]` |
| 108 | + link: `/blog/${post.id}/`, |
| 109 | + })), |
| 110 | + }); |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +Opcional: sustituye el esquema de la colección de tu blog actual para garantizar que se cumplan las propiedades RSS esperadas. |
| 115 | + |
| 116 | +Para garantizar que cada entrada del blog genere un elemento válido en el canal RSS, puedes, si lo deseas, importar y aplicar `rssSchema` en lugar de definir cada propiedad del esquema por separado. |
| 117 | + |
| 118 | +```js title="src/content.config.ts" "rssSchema" |
| 119 | +import { defineCollection } from 'astro:content'; |
| 120 | +import { rssSchema } from '@astrojs/rss'; |
| 121 | + |
| 122 | +const blog = defineCollection({ |
| 123 | + schema: rssSchema, |
| 124 | +}); |
| 125 | + |
| 126 | +export const collections = { blog }; |
| 127 | +``` |
| 128 | + |
| 129 | +### Uso de importaciones glob |
| 130 | + |
| 131 | +<p><Since v="2.1.0" pkg="@astrojs/rss" /></p> |
| 132 | + |
| 133 | +Para crear un canal RSS a partir de los documentos de `src/pages/`, utiliza la función auxiliar `pagesGlobToRssItems()`. Esta función acepta un resultado de [`import.meta.glob`](https://es.vite.dev/guide/features#glob-import) y devuelve una lista de elementos válidos para el canal RSS (consulta [más información sobre cómo escribir patrones glob](/es/guides/imports/#glob-patterns) para especificar qué páginas incluir). |
| 134 | + |
| 135 | +:::caution |
| 136 | +Esta función da por hecho, aunque no verifica, que todas las propiedades de tu fuente RSS necesarias estén presentes en la información preliminar de cada documento. Si detectas algún error, comprueba manualmente la información preliminar de cada página. |
| 137 | +::: |
| 138 | + |
| 139 | +```js title="src/pages/rss.xml.js" "pagesGlobToRssItems" "await pagesGlobToRssItems(" |
| 140 | +import rss, { pagesGlobToRssItems } from '@astrojs/rss'; |
| 141 | + |
| 142 | +export async function GET(context) { |
| 143 | + return rss({ |
| 144 | + title: 'Blog de Buzz', |
| 145 | + description: 'Una humilde guía de un astronauta para conocer las estrellas', |
| 146 | + site: context.site, |
| 147 | + items: await pagesGlobToRssItems( |
| 148 | + import.meta.glob('./blog/*.{md,mdx}'), |
| 149 | + ), |
| 150 | + }); |
| 151 | +} |
| 152 | +``` |
| 153 | + |
| 154 | +:::note[¿Estás usando una versión anterior?] |
| 155 | +En las versiones de `@astrojs/rss` anteriores a la v2.1.0, pasa el resultado de glob directamente a `items` sin usar la función `pagesGlobToRssItems()`: |
| 156 | + |
| 157 | +```js |
| 158 | +items: import.meta.glob('./blog/*.{md,mdx}'), |
| 159 | +``` |
| 160 | + |
| 161 | +Este método ha quedado obsoleto en todas las versiones de Astro a partir de la v2.1.0 y no se puede usar en proyectos actuales. |
| 162 | +::: |
| 163 | + |
| 164 | +### Incluyendo el contenido completo de la entrada |
| 165 | + |
| 166 | +<p><Since v="1.6.14" /></p> |
| 167 | + |
| 168 | +Establece la clave `content` en `rss.items` para proporcionar el contenido completo de una entrada en formato HTML. Esto permite que `@astrojs/rss` ponga a disposición de los lectores de fuentes RSS el texto completo en Markdown de tu entrada. También se admiten imágenes y enlaces con rutas URL completas. Sin embargo, no se admiten las imágenes ni los enlaces internos a otras páginas que usen rutas relativas. |
| 169 | + |
| 170 | +Al renderizar el contenido completo de una entrada, deberás tener en cuenta las imágenes, los enlaces relativos, los estilos, los scripts y otros elementos que vayan más allá del texto estándar de Markdown y que puedas incluir en tus entradas. Es posible que tengas que añadir lógica adicional en tu endpoint `src/pages/rss.xml.js` para tener en cuenta estos elementos o para eliminar aquellos que no sean necesarios para una fuente RSS (p. ej., los que solo se usan para el estilo o la interacción en tu sitio web). |
| 171 | + |
| 172 | +Puedes consultar [una implementación concreta de la comunidad](https://github.com/delucis/astro-blog-full-text-rss/blob/latest/src/pages/rss.xml.ts) que aborda algunas de estas cuestiones, a modo de ejemplo de cómo proceder. |
| 173 | + |
| 174 | +:::tip |
| 175 | +Un paquete como [`sanitize-html`](https://www.npmjs.com/package/sanitize-html) se encargará de que tu contenido se depure, se escape y se codifique correctamente. Durante el proceso, es posible que dicho paquete también elimine algunos elementos y atributos inofensivos, así que asegúrate de comprobar el resultado y de configurar el paquete según tus necesidades. |
| 176 | +::: |
| 177 | + |
| 178 | +Al utilizar colecciones de contenido, procesa el `body` de la entrada con un procesador Markdown estándar, como [`markdown-it`](https://github.com/markdown-it/markdown-it), y depura el resultado, incluyendo cualquier etiqueta adicional (p. ej., `<img>`) necesaria para mostrar el contenido: |
| 179 | + |
| 180 | +```js title="src/pages/rss.xml.js" ins={3, 4, 5, 16} |
| 181 | +import rss from '@astrojs/rss'; |
| 182 | +import { getCollection } from 'astro:content'; |
| 183 | +import sanitizeHtml from 'sanitize-html'; |
| 184 | +import MarkdownIt from 'markdown-it'; |
| 185 | +const parser = new MarkdownIt(); |
| 186 | + |
| 187 | +export async function GET(context) { |
| 188 | + const blog = await getCollection('blog'); |
| 189 | + return rss({ |
| 190 | + title: 'Blog de Buzz', |
| 191 | + description: 'Una humilde guía de un astronauta para conocer las estrellas', |
| 192 | + site: context.site, |
| 193 | + items: blog.map((post) => ({ |
| 194 | + link: `/blog/${post.id}/`, |
| 195 | + // Nota: esto no procesará los componentes ni las expresiones JSX de los archivos MDX. |
| 196 | + content: sanitizeHtml(parser.render(post.body), { |
| 197 | + allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img']) |
| 198 | + }), |
| 199 | + ...post.data, |
| 200 | + })), |
| 201 | + }); |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +Al usar importaciones glob con Markdown, puedes usar la función auxiliar `compiledContent()` para recuperar el código HTML renderizado para su depuración. Nota: esta función **no** es compatible con archivos MDX. |
| 206 | + |
| 207 | +```js title="src/pages/rss.xml.js" ins={2, 13} |
| 208 | +import rss from '@astrojs/rss'; |
| 209 | +import sanitizeHtml from 'sanitize-html'; |
| 210 | + |
| 211 | +export async function GET(context) { |
| 212 | + const postImportResult = import.meta.glob('../posts/**/*.md', { eager: true }); |
| 213 | + const posts = Object.values(postImportResult); |
| 214 | + return rss({ |
| 215 | + title: 'Blog de Buzz', |
| 216 | + description: 'Una humilde guía de un astronauta para conocer las estrellas', |
| 217 | + site: context.site, |
| 218 | + items: await Promise.all(posts.map(async (post) => ({ |
| 219 | + link: post.url, |
| 220 | + content: sanitizeHtml((await post.compiledContent())), |
| 221 | + ...post.frontmatter, |
| 222 | + }))), |
| 223 | + }); |
| 224 | +} |
| 225 | +``` |
| 226 | + |
| 227 | +## Eliminar las barras finales |
| 228 | + |
| 229 | +Por defecto, el canal RSS de Astro genera enlaces con una barra al final, independientemente del valor que hayas configurado para `trailingSlash`. Esto significa que es posible que tus enlaces RSS no coincidan exactamente con las URL de tus entradas. |
| 230 | + |
| 231 | +Si has establecido `trailingSlash: "never"` en tu archivo `astro.config.mjs`, configura `trailingSlash: false` en la función auxiliar `rss()` para que tu fuente RSS se ajuste a la configuración de tu proyecto. |
| 232 | + |
| 233 | +```ts title="src/pages/rss.xml.js" ins={9} |
| 234 | +import rss from '@astrojs/rss'; |
| 235 | + |
| 236 | +export function GET(context) { |
| 237 | + const posts = Object.values(postImportResult); |
| 238 | + return rss({ |
| 239 | + title: 'Blog de Buzz', |
| 240 | + description: 'Una humilde guía de un astronauta para conocer las estrellas', |
| 241 | + site: context.site, |
| 242 | + trailingSlash: false, |
| 243 | + items: posts.map((post) => ({ |
| 244 | + link: post.url, |
| 245 | + ...post.frontmatter, |
| 246 | + })), |
| 247 | + }); |
| 248 | +} |
| 249 | +``` |
| 250 | + |
| 251 | +## Agregar una hoja de estilo |
| 252 | + |
| 253 | +Personaliza el aspecto de tu fuente RSS para ofrecer una experiencia de usuario más agradable al visualizar el archivo en el navegador. |
| 254 | + |
| 255 | +Usa la opción `stylesheet` de la función `rss` para especificar una ruta absoluta a tu hoja de estilos. |
| 256 | + |
| 257 | +```js |
| 258 | +rss({ |
| 259 | + // Por ejemplo, usa tu hoja de estilos ubicada en "public/rss/styles.xsl" |
| 260 | + stylesheet: '/rss/styles.xsl', |
| 261 | + // ... |
| 262 | +}); |
| 263 | +``` |
| 264 | + |
| 265 | +:::tip |
| 266 | +Si prefieres no crear tu propia hoja de estilos, puedes usar una hoja de estilos ya preparada, como la [hoja de estilos predeterminada de Pretty Feed v3](https://github.com/genmon/aboutfeeds/blob/main/tools/pretty-feed-v3.xsl). Descarga la hoja de estilos de GitHub y guárdala en el directorio `public/` de tu proyecto. |
| 267 | +::: |
| 268 | + |
| 269 | +## Habilitar la detección automática de fuentes RSS |
| 270 | + |
| 271 | +[Detección automática de RSS](https://www.rssboard.org/rss-autodiscovery) permite a los navegadores y a otros programas encontrar automáticamente el canal RSS de un sitio web a partir de la URL principal. |
| 272 | + |
| 273 | +Para habilitarlo, agrega una etiqueta `<link>` con los siguientes atributos al elemento `head` de tu sitio web: |
| 274 | + |
| 275 | +```jsx |
| 276 | +<link |
| 277 | + rel="alternate" |
| 278 | + type="application/rss+xml" |
| 279 | + title="El título de tu sitio" |
| 280 | + href={new URL("rss.xml", Astro.site)} |
| 281 | +/> |
| 282 | +``` |
| 283 | + |
| 284 | +Con esta etiqueta, los lectores de tu blog pueden introducir la URL base de tu sitio web en su lector RSS para suscribirse a tus entradas sin necesidad de conocer la URL específica de tu fuente RSS. |
| 285 | + |
| 286 | +## Próximos pasos |
| 287 | + |
| 288 | +Después de visitar tu fuente RSS en el navegador en `tu-dominio.com/rss.xml` y comprobar que puedes ver los datos de cada una de tus entradas, ya puedes [promocionar tu fuente RSS en tu página web] (https://medium.com/samsung-internet-dev/add-rss-feeds-to-your-website-to-keep-your-core-readers-engaged-3179dca9c91e#:~:text=com/~deno%2Drss-,Cómo%20promocionar%20tu%20feed%20RSS,-Ahora%20que%20ya%20tienes). Añadir el icono estándar de RSS a tu sitio web permite a tus lectores saber que pueden suscribirse a tus entradas en su propio lector de fuentes RSS. |
| 289 | + |
| 290 | +## Recursos |
| 291 | + |
| 292 | +- [Fuentes RSS](https://aboutfeeds.com/) |
0 commit comments