Al lado del cliente, la petición que el lector ha construido — escrita en el
lenguaje en el que trabaja, y reescrita en cada pulsación.

## Qué viene incluido

| Grupo        | Clientes                                 |
| :----------- | :--------------------------------------- |
| `curl`       | curl                                     |
| TypeScript   | `fetch`, `$fetch`, `useFetch`, axios     |
| Python       | requests, httpx, urllib                  |
| Go           | `net/http`                               |
| PHP          | Guzzle, Laravel `Http`, extensión curl   |

**Siete están activas por defecto:** curl, `fetch`, `$fetch`, Python requests, Go,
Guzzle y Laravel `Http`. Las otras cinco son el segundo cliente de un lenguaje que
ya tiene uno en pantalla, y un selector sirve para elegir, no para listar todo lo
que existe.

## Dos niveles

El lenguaje es la pestaña y el cliente un selector dentro de ella, así que PHP con
tres clientes cuesta una pestaña. Un sitio que añade tres propios para un lenguaje
sigue costando una. La elección del lector se recuerda entre páginas: quien trabaja
en curl trabaja en curl también en el siguiente endpoint.

## Configurar la lista

```ts
export default defineAppConfig({
  duxt: {
    requestSamples: ['curl', 'php-guzzle', 'php-laravel']
  }
})
```

Una cadena elige una de las incluidas; los ids son `curl`, `fetch`, `ofetch`,
`use-fetch`, `axios`, `python-requests`, `python-httpx`, `python-urllib`, `go`,
`php-guzzle`, `php-laravel`, `php-curl`.

La lista **reemplaza** en lugar de extender, como toda otra lista de la
configuración: de otro modo un sitio que documenta una API en PHP podría añadir
sus clientes pero nunca quitar los que no quiere. El orden es el orden en que
aparecen.

## Tu propio generador

Un objeto añade uno propio — o reemplaza uno incluido, reutilizando su id.

```ts
requestSamples: [
  'curl',
  {
    id: 'ruby',
    group: 'Ruby',
    label: 'Net::HTTP',
    language: 'ruby',
    generate: (request) => `
uri = URI('${request.url}')
Net::HTTP.get(uri)
`.trim()
  }
]
```

| Campo      | Tipo                  | Notas                                        |
| :--------- | :-------------------- | :------------------------------------------- |
| `id`       | `string`              | Estable: es también el valor recordado       |
| `group`    | `DuxtText`            | La pestaña                                   |
| `label`    | `DuxtText`            | La entrada dentro de la pestaña              |
| `language` | `string`              | Un id de Shiki — decide la gramática         |
| `generate` | `(request) => string` | Síncrono, puro, sin red, sin DOM             |

`generate` corre en el **navegador**, en cada pulsación, porque la muestra tiene
que seguir la petición que se está editando. `request` es
`{ method, url, headers, body?, responseType? }`, donde `body` es el texto del editor y no está
parseado — un generador que lo quiera como datos lo parsea él mismo, y decide qué
hacer cuando no es JSON.


### Por qué TypeScript y no JavaScript

`$fetch`, `useFetch` y axios toman la forma de la respuesta como parámetro de
tipo, y `responseType` es lo que lo rellena: `$fetch<Widget>(…)` es la línea que
alguien escribe de verdad. `fetch` no tiene ninguno — devuelve un `Response` sea
cual sea el cuerpo — así que su muestra es la misma en ambos lenguajes.

Por eso hay un grupo y no dos. Un grupo JavaScript al lado llevaría un `fetch`
que nunca difiere y tres clientes que difieren solo donde el documento nombró su
esquema de respuesta, al precio del doble de pestañas.

`responseType` es el nombre del componente que devuelve una respuesta correcta —
`Widget`, o `Widget[]` para una lista. Falta donde el esquema de respuesta está
en línea en lugar de tras un `$ref`, y la muestra entonces no lleva parámetro de
tipo: aquí no se inventa un nombre que el documento no dio.

## Qué muestra una muestra

**La petición, y nada después.** La respuesta ya está en pantalla, en el panel bajo
el editor, así que una muestra que la buscara una segunda vez estaría mostrando al
lector algo que puede ver — al precio de una rama de error en cada lenguaje que
tiene una.

Go es la excepción y conserva sus comprobaciones de `err`: sin ellas no es Go, y un
fragmento que no compila es peor que uno largo.

## Las gramáticas se pagan, no se suponen

Estas muestras se colorean en el navegador, así que cada lenguaje son bytes que un
lector descarga — a diferencia de un bloque Markdown, cuya gramática es un coste de
compilación y nunca llega a un navegador.

Por eso el conjunto de gramáticas se **genera desde la lista de arriba**: un sitio
envía exactamente los lenguajes que nombran sus muestras. Las siete por defecto
necesitan seis gramáticas. Cargar el mapa perezoso propio de Shiki costaría 3 KB y
haría que cada compilación emitiera 242 fragmentos de gramática.

## Muestras del documento

`x-codeSamples` — en cualquiera de sus dos formas, incluida la antigua
`x-code-samples` — se lee de una operación y **reemplaza las muestras generadas
para su lenguaje**. Quien es dueño de la API conoce sus modismos mejor que un
generador.

```yaml
paths:
  /pets:
    get:
      x-codeSamples:
        - lang: ruby
          label: Net::HTTP
          source: |
            Net::HTTP.get(URI('https://api.example.com/pets'))
```

Una muestra así es **estática** — no puede seguir las ediciones del lector — así
que el panel dice quién la escribió y que no sigue las ediciones de arriba. Un
lector que cambió el cuerpo y pasó a ella concluiría, si no, que el editor está
roto en lugar de que esta muestra es fija.

Su lenguaje no es visible donde se escribe el conjunto de gramáticas: una fuente
remota todavía no está clonada. Así que nómbralo:

```ts
duxt: {
  sampleLanguages: ['ruby']
}
```

Sin eso la muestra se renderiza como texto plano.