<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hélio Marcondes</title>
    <description>The latest articles on DEV Community by Hélio Marcondes (@heliomsolivas).</description>
    <link>https://dev.to/heliomsolivas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F286144%2Fefcb08c2-f102-4154-a596-9b710706c30e.png</url>
      <title>DEV Community: Hélio Marcondes</title>
      <link>https://dev.to/heliomsolivas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/heliomsolivas"/>
    <language>en</language>
    <item>
      <title>API mocking with Mock Service Worker + Vue.js</title>
      <dc:creator>Hélio Marcondes</dc:creator>
      <pubDate>Mon, 06 May 2024 14:42:50 +0000</pubDate>
      <link>https://dev.to/heliomsolivas/api-mocking-with-mock-service-worker-vuejs-5d42</link>
      <guid>https://dev.to/heliomsolivas/api-mocking-with-mock-service-worker-vuejs-5d42</guid>
      <description>&lt;p&gt;Hi everyone.&lt;/p&gt;

&lt;p&gt;Last week I was working on a new project from scratch and encountered a common problem.&lt;/p&gt;

&lt;p&gt;I built a big part of the frontend and my backend teammates haven't finished their part. So, I was wondering how to improve my workflow defining some mock data on frontend.&lt;/p&gt;

&lt;p&gt;To be honest the quickly way that I usually do is to create some data in JSON format and have methods to load it, and after the API be functional I just remove the mock data to call the API.&lt;/p&gt;

&lt;p&gt;Something like this:&lt;/p&gt;

&lt;p&gt;./mocks/groupData.ts&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import type { GroupInterface } from '../interfaces/Group'

export function getGroupData(): { groups: GroupInterface[] } {
  const groups: GroupInterface[] = [
    {
      id: 1,
      group: 'Group 1',
    },
    {
      id: 2,
      group: 'Group 2',
    },
  ]

  return { groups }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;./screens/Groups/Groups.vue&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;script setup lang="ts"&amp;gt;
import { getGroupData } from '../../mocks/groupData'

const { groups } = getGroupData()


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But after a little research I found the &lt;a href="https://mswjs.io/" rel="noopener noreferrer"&gt;Mock Service Worker&lt;/a&gt; it's a mocking library that allows you to write client-agnostic mocks and reuse them across any frameworks, tools, and environments.&lt;/p&gt;

&lt;p&gt;I tested on my project and it fit very well for my case, here are the steps that I used to configure the library on a Vue.js 3 project.&lt;/p&gt;

&lt;p&gt;Step 1: Install the MSW library:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install msw@latest --save-dev


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Step 2: Create handlers to handle the "API" requests, it will be the methods and the return of the API request:&lt;/p&gt;

&lt;p&gt;./mocks/handlers.ts&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { http, HttpResponse } from "msw";

export const handlers = [
  http.get("/users", () =&amp;gt; {
    return HttpResponse.json([
      {
        id: "c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3d",
        firstName: "John",
        lastName: "Maverick",
      },
      {
        id: "c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3e",
        firstName: "Kar",
        lastName: "Marx",
      },
    ]);
  }),
];


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Step 3: Integrate MSW into a browser environment (other integrations are also available):&lt;/p&gt;

&lt;p&gt;./mocks/browser.ts&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// src/mocks/browser.js
import { setupWorker } from "msw/browser";
import { handlers } from "./handlers";

export const worker = setupWorker(...handlers);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Step 4: Copy the worker script to your public folder, MSW library provides a command to do this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx msw init &amp;lt;PUBLIC_DIR&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;On my example I use public as a "PUBLIC_DIR", after you execute the command it will generate a file named /mockServiceWorker.js inside the public directory&lt;/p&gt;

&lt;p&gt;Step 5: Enable mocking by calling it in main Vue.js file:&lt;/p&gt;

&lt;p&gt;main.ts&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { createApp } from "vue";
import App from "./App.vue";

import "./assets/main.css";

async function prepareApp() {
  const { worker } = await import("./mocks/browser");
  return worker.start();
}

const app = createApp(App);

prepareApp().then(() =&amp;gt; {
  app.mount("#app");
});


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After all this configuration you should be able to call the handler that you set before, like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;script setup lang="ts"&amp;gt;
import { onMounted, ref } from 'vue';

const users = ref&amp;lt;[]&amp;gt;([])

async function loadUserFromMsw() {
  const res = await fetch('/users')
    .then(response =&amp;gt; response.json())
    .then(json =&amp;gt; {
      return json
    })
    .catch(err =&amp;gt; console.log('Error', err));

  users.value = res
}

onMounted(async () =&amp;gt; {
  await loadUserFromMsw()
})


&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;main&amp;gt;
    &amp;lt;pre&amp;gt;
      {{ users }}
    &amp;lt;/pre&amp;gt;
  &amp;lt;/main&amp;gt;
&amp;lt;/template&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And here is the final result:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firlyryk87s28gfytwmza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firlyryk87s28gfytwmza.png" alt="Final result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My final thoughts are that I can mock various routes and methods using handlers of MSW easier than my usuall way to finish the frontend with mocking data.&lt;/p&gt;

&lt;p&gt;If you have any suggestions, please let me know. Thank you so much for reading!&lt;/p&gt;

</description>
      <category>vue</category>
      <category>mocking</category>
      <category>api</category>
    </item>
    <item>
      <title>A simple explanation of Adapter Pattern with Vue.js</title>
      <dc:creator>Hélio Marcondes</dc:creator>
      <pubDate>Fri, 26 Apr 2024 20:57:33 +0000</pubDate>
      <link>https://dev.to/heliomsolivas/a-simple-explanation-of-adapter-pattern-with-vuejs-add</link>
      <guid>https://dev.to/heliomsolivas/a-simple-explanation-of-adapter-pattern-with-vuejs-add</guid>
      <description>&lt;p&gt;Hi there.&lt;/p&gt;

&lt;p&gt;Today I will share how I understood the Adapter Pattern using Vue.js. In short, the Adapter Pattern in Vue.js is used to "adapt" the interface of a component, method, or service so that it can be used in a compatible way with other parts of the code that expect a different interface.&lt;/p&gt;

&lt;p&gt;This pattern is useful for integrating third-party components, APIs, or libraries that are not directly compatible with your Vue.js application, allowing for smoother, more flexible integration.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;

&lt;p&gt;1- I have a Home.vue file that will do a request to a random API (restcountries):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
async function getCountry(name: string) {
  const response = await useFetch(`https://restcountries.com/v3.1/name/${name}`)
  return response.data.value
}

let country: any = await getCountry('brasil')
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;pre&amp;gt;
        {{ country }}
    &amp;lt;/pre&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the return of the API request:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5idn75wdibw5q1b44fym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5idn75wdibw5q1b44fym.png" alt="Return of API" width="800" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, let's imagine that we only need three variables from this response, formatted in a specific way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Country {
  countryName: string
  countryCapital: string
  countryPopulation: number
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- I will create another file named adapters.ts and define a function to transform the current format into the one expected by the Country interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Country {
  countryName: string
  countryCapital: string
  countryPopulation: number
}

// Function that receives the API response and adapts it to an array of Country objects
export function getCountryAdapter(apiResponse: any): Country[] {
  // Check if is an array
  if (!Array.isArray(apiResponse)) {
    throw new Error('The API response is not a Array of countries.')
  }

  // Maps each country in the response to the Country object format
  const countries: Country[] = apiResponse.map((country: any) =&amp;gt; ({
    countryName: country.name.common,
    countryCapital: country.capital[0],
    countryPopulation: country.population,
  }))

  return countries
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- Now, let's call the adapter in the Home.vue file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
import { getCountryAdapter } from '../services/adapters'

async function getCountry(name: string) {
  const response = await useFetch(`https://restcountries.com/v3.1/name/${name}`)
  const country = getCountryAdapter(response.data.value)
  return country
}

let country: any = await getCountry('brasil')
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;pre&amp;gt;
        {{ country }}
    &amp;lt;/pre&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4- The final result is the response adapted to the interface 😊:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnno7xng7opzhmu9jftwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnno7xng7opzhmu9jftwr.png" alt="Adapted response" width="409" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any suggestions, please let me know. Thank you so much for reading!&lt;/p&gt;

</description>
      <category>vue</category>
      <category>designpatterns</category>
      <category>beginners</category>
      <category>vue3</category>
    </item>
    <item>
      <title>Global toast in Vue3</title>
      <dc:creator>Hélio Marcondes</dc:creator>
      <pubDate>Thu, 18 Apr 2024 19:53:51 +0000</pubDate>
      <link>https://dev.to/heliomsolivas/global-toast-in-vue3-1bmc</link>
      <guid>https://dev.to/heliomsolivas/global-toast-in-vue3-1bmc</guid>
      <description>&lt;p&gt;Hi there.&lt;/p&gt;

&lt;p&gt;Today I will share the way I built a simple Toast component using Vue3 composables.&lt;/p&gt;

&lt;p&gt;Recently, I had to create a project from scratch using Nuxt3 + TailwindCSS. In the middle of it, I needed a simple Toast component to handle some actions. So, after some research, I ended up with this component.&lt;/p&gt;

&lt;p&gt;1- Creating the Toast component involves a bit of styling with TailwindCSS classes and custom CSS to control how the Toast appears.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Toast.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
defineProps({
    message: {
        required: false,
        type: String,
    },
    visibility: {
        required: true,
        type: Boolean,
    },
})
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
    &amp;lt;div v-if="visibility"
        class="toast z-50 fixed top-4 right-4 flex items-center gap-4 mb-4 text-gray-200 transition-all duration-[3000ms] w-80 overflow-hidden"&amp;gt;
        &amp;lt;div class="p-3 w-full rounded-tl-none rounded-bl-none"&amp;gt;
            &amp;lt;div class="flex items-center w-full"&amp;gt;
                &amp;lt;div class="flex flex-col"&amp;gt;
                    &amp;lt;div class="toast__title text-sm text-green-800"&amp;gt;Success&amp;lt;/div&amp;gt;
                    &amp;lt;div class="toast__text text-sm text-green-500"&amp;gt;{{ message }}&amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;style scoped&amp;gt;
.toast {
    box-shadow: 0px 4px 14px 0px rgba(0, 0, 0, 0.18);
    border-radius: 5px 0px 0px 5px;
    border-left: 7px solid #1fac66;
    width: 429px;
}
&amp;lt;/style&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Creating the &lt;strong&gt;composable&lt;/strong&gt;&lt;br&gt;
I've created two functions to handle the logic of the Toast component: one to add the message inside the component and another to reset it. I'm also using the useState composable from Nuxt to keep the variables &lt;em&gt;visibility&lt;/em&gt; and &lt;em&gt;messages&lt;/em&gt; available.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useToast.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function useToast() {
    let visibility = useState('visibility', () =&amp;gt; false)
    let messages = useState&amp;lt;string[]&amp;gt;('messages', () =&amp;gt; [])

    function resetMessages() {
        messages.value = []
    }

    function addMessage(message: string) {
        if (message) {
            messages.value.push(message)
            visibility.value = true
            setTimeout(() =&amp;gt; {
                visibility.value = false
                resetMessages()
            }, 3000)
        }
    }

    return {
        messages,
        addMessage,
        visibility,
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- In the root component of the project (app.vue in my case), I import the component and the composable to work together. In this example, there are some extras that I added for layout purposes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
const { messages, visibility } = useToast()
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;NuxtLayout&amp;gt;
    &amp;lt;NuxtPage&amp;gt;&amp;lt;/NuxtPage&amp;gt;
  &amp;lt;/NuxtLayout&amp;gt;

  &amp;lt;TransitionGroup name="toast"&amp;gt;
    &amp;lt;Toast v-for="(message, index) in messages" :key="index" :message="message" :index="index"
      :visibility="visibility" /&amp;gt;
  &amp;lt;/TransitionGroup&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;style&amp;gt;
.toast-enter-from,
.toast-leave-to {
  opacity: 0;
  transform: translateY(-60px);
}

.toast-enter-to,
.toast-leave-from {
  opacity: 1;
  transform: translateY(0);
}

.toast-enter-active,
.toast-leave-active {
  transition: all 0.3s ease;
}
&amp;lt;/style&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4- To see it working, you can simply call it from any page or component that you need. Here are two examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To trigger the modal from a page, you can use the following code:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;index.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
const { addMessage } = useToast()

function triggerModal() {
    addMessage('My Amazing modal from Index.vue')
}
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;div&amp;gt;This is my &amp;lt;b&amp;gt;index.vue&amp;lt;/b&amp;gt; page&amp;lt;/div&amp;gt;
        &amp;lt;button @click="triggerModal()"&amp;gt;Trigger Modal&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vndnzjbl8x6po6yknwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vndnzjbl8x6po6yknwo.png" alt="Toast from page" width="499" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To trigger the modal from a random component, you can use the following code:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;myRandomComponent.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
const { addMessage } = useToast()

function triggerModal() {
    addMessage('My Amazing from component')
}
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;div&amp;gt;My test component&amp;lt;/div&amp;gt;
        &amp;lt;button @click="triggerModal()"&amp;gt;Trigger Modal from my Component&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmpgnx2r4i1mu2rorkep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmpgnx2r4i1mu2rorkep.png" alt="Toast from component" width="464" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any suggestions, please let me know. Thank you so much for reading!&lt;/p&gt;

</description>
      <category>vue</category>
      <category>vue3</category>
      <category>component</category>
      <category>composable</category>
    </item>
  </channel>
</rss>
