Ao lado do cliente, o pedido que o leitor construiu — escrito na linguagem em que
trabalha, e reescrito a cada tecla.

## O que vem incluído

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

**Sete estão ligadas por omissão:** curl, `fetch`, `$fetch`, Python requests, Go,
Guzzle e Laravel `Http`. As outras cinco são o segundo cliente de uma linguagem
que já tem um no ecrã, e um selector serve para escolher, não para listar tudo o
que existe.

## Dois níveis

A linguagem é o separador e o cliente um selector dentro dele, por isso PHP com
três clientes custa um separador. Um site que acrescenta três seus para uma
linguagem continua a custar um. A escolha do leitor é lembrada entre páginas: quem
trabalha em curl trabalha em curl também no endpoint seguinte.

## Configurar a lista

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

Uma string escolhe uma das incluídas; os ids são `curl`, `fetch`, `ofetch`,
`use-fetch`, `axios`, `python-requests`, `python-httpx`, `python-urllib`, `go`,
`php-guzzle`, `php-laravel`, `php-curl`.

A lista **substitui** em vez de estender, como toda a outra lista da configuração:
de outro modo um site que documenta uma API em PHP podia acrescentar os seus
clientes mas nunca largar os que não quer. A ordem é a ordem em que aparecem.

## O teu próprio gerador

Um objecto acrescenta um teu — ou substitui um incluído, reutilizando o seu 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`              | Estável: é também o valor lembrado           |
| `group`    | `DuxtText`            | O separador                                  |
| `label`    | `DuxtText`            | A entrada dentro do separador                |
| `language` | `string`              | Um id do Shiki — decide a gramática          |
| `generate` | `(request) => string` | Síncrono, puro, sem rede, sem DOM            |

O `generate` corre no **navegador**, a cada tecla, porque a amostra tem de seguir
o pedido que está a ser editado. `request` é `{ method, url, headers, body?, responseType? }`,
onde `body` é o texto do editor e não está parseado — um gerador que o queira como
dados parseia-o ele mesmo, e decide o que fazer quando não é JSON.


### Porque TypeScript e não JavaScript

O `$fetch`, o `useFetch` e o axios recebem a forma da resposta como parâmetro de
tipo, e o `responseType` é o que o preenche: `$fetch<Widget>(…)` é a linha que
alguém escreve de facto. O `fetch` não tem nenhum — devolve um `Response` seja
qual for o corpo — por isso a sua amostra é a mesma em ambas as linguagens.

É também por isso que há um grupo e não dois. Um grupo JavaScript ao lado
levaria um `fetch` que nunca difere e três clientes que diferem apenas onde o
documento nomeou o seu esquema de resposta, ao preço do dobro dos separadores.

O `responseType` é o nome do componente que uma resposta bem-sucedida devolve —
`Widget`, ou `Widget[]` para uma lista. Falta onde o esquema de resposta está em
linha em vez de atrás de um `$ref`, e a amostra então simplesmente não leva
parâmetro de tipo: nada aqui inventa um nome que o documento não deu.

## O que uma amostra mostra

**O pedido, e nada depois.** A resposta já está no ecrã, no painel sob o editor,
por isso uma amostra que a fosse buscar uma segunda vez estaria a mostrar ao
leitor algo que ele vê — ao preço de um ramo de erro em cada linguagem que tem um.

O Go é a excepção e mantém as verificações de `err`: sem elas não é Go, e um
excerto que não compila é pior do que um longo.

## As gramáticas pagam-se, não se presumem

Estas amostras são coloridas no navegador, por isso cada linguagem são bytes que
um leitor descarrega — ao contrário de um bloco Markdown, cuja gramática é um
custo de build e nunca chega a um navegador.

Por isso o conjunto de gramáticas é **gerado a partir da lista acima**: um site
entrega exactamente as linguagens que as suas amostras nomeiam. As sete por
omissão precisam de seis gramáticas. Carregar o mapa preguiçoso do próprio Shiki
custaria 3 KB e faria cada build emitir 242 pedaços de gramática.

## Amostras vindas do documento

O `x-codeSamples` — em qualquer das duas grafias, incluída a antiga
`x-code-samples` — é lido numa operação e **substitui as amostras geradas para a
sua linguagem**. Quem é dono da API conhece os seus idiomas melhor do que um
gerador.

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

Uma amostra assim é **estática** — não pode seguir as edições do leitor — por isso
o painel diz quem a escreveu e que não acompanha as edições acima. Um leitor que
mudou o corpo e passou para ela concluiria, de outro modo, que o editor está
avariado em vez de que esta amostra é fixa.

A sua linguagem não é visível onde o conjunto de gramáticas é escrito: uma fonte
remota ainda não está clonada. Portanto nomeia-a:

```ts
duxt: {
  sampleLanguages: ['ruby']
}
```
 
Sem isso a amostra é renderizada como texto simples.