ProseImg
Uma imagem: consciente do tema, adaptável e ampliável.
Cada imagem de uma página Markdown.
Cada exemplo abaixo é um bloco de código. As imagens de teste são essa mesma marcação realmente desenhada — um gémeo escuro, um original mais estreito do que a coluna, um vetor, uma animação e uma imagem que se recusa a ampliar.
O que acrescenta
Duas variantes. Uma captura de um editor escuro sobre uma página branca — ou o contrário — é a coisa mais feia que acontece numa documentação, e o CSS não a resolve porque o que está errado são os pixels, não a moldura. Uma página pode nomear um segundo ficheiro:
{dark="/shots/sidebar-dark.png"}
Dois pedidos, não um ficheiro. A imagem na página e a imagem no diálogo de
ampliação pedem larguras diferentes, pelo que um telemóvel já não descarrega o
original de 2400 px para o desenhar numa coluna de 48rem. Ambas são srcset
gerados pelo @nuxt/image; nenhuma é um ficheiro que alguém tenha de preparar.
Clique para ampliar, salvo se a imagem pedir o contrário:
{zoom="false"}
Uma imagem ampliável tem um pequeno indicador de ampliação no seu canto, de forma
permanente e não ao passar o cursor — um cursor não existe num dispositivo tátil
e é invisível numa captura da página. A imagem é um botão: Tab alcança-o com um
anel visível, Enter e Espaço abrem o diálogo, Escape fecha-o e devolve o
foco. Com zoom="false" não há indicador, nem anel, nem nada para onde tabular.
Um fundo para uma imagem transparente. Um diagrama cujo traço foi pensado
para uma superfície clara desaparece numa página escura. Indique uma cor por
tema — qualquer cor CSS, var(--card) incluída:
{background="#fafafa" dark-background="#171717"}
Cores e não classes, de propósito: a folha de estilos da camada é construída a
partir dos seus próprios componentes, nunca do Markdown, pelo que uma classe
dark:bg-… escrita numa página não teria CSS por trás.
O visualizador ocupa o ecrã inteiro sobre a página desfocada. Os seus controlos —
diminuir o zoom, o nível de zoom (que o repõe), aumentar o zoom, abrir o original
num novo separador, fechar — flutuam numa linha acima da imagem e o texto
alternativo fica por baixo, pelo que nenhum a tapa. A roda amplia à volta do
cursor e o gesto de pinça à volta dos dedos; um clique na imagem amplia-a para
200 % nesse ponto e um segundo clique volta atrás; +, - e 0 fazem o mesmo
pelo teclado. Uma imagem ampliada arrasta-se para a deslocar e carrega o ficheiro
original para continuar nítida. Um clique no espaço à volta fecha o visualizador.
API
Props
| Prop | Tipo | Padrão | Notas |
|---|---|---|---|
src | string | — | Tal como escrito |
alt | string | — | Tal como escrito |
dark | string | — | Um segundo ficheiro, servido sob o tema escuro |
zoom | boolean | true | false deixa a imagem inerte |
width | number | — | Opcional; ver Dimensões abaixo |
height | number | — | Opcional; ver Dimensões abaixo |
sizes | string | — | Substitui a política da página; ver Tamanhos |
background | string | — | Uma cor CSS por trás de uma imagem transparente, na página e no visualizador |
dark-background | string | — | O mesmo no tema escuro; recorre a background |
Tamanhos
O tema sabe uma coisa que o @nuxt/image não pode saber: qual é a largura da
caixa onde desenha uma imagem. É só isso que configura.
- Na página —
sm:95vw md:768px. Abaixo demd, o artigo é a janela menos as suas margens; a partir demdfica limitado amax-w-3xlseja qual for o ecrã, pelo que a largura pedida deixa de crescer em vez de continuar a subir num ecrã 4K. - No diálogo —
sm:96vw md:96vw lg:96vw xl:1264px, acompanhando a janela até ao limite do próprio diálogo,min(96vw, 80rem).
Ambas nomeiam apenas os breakpoints que o @nuxt/image já traz, pelo que quem
redefinir image.screens mantém a sua definição. A camada não declara screens
próprios.
Uma imagem que não é tão larga como a coluna de texto — um logótipo, um distintivo, um diagrama à margem — diz-o:
{sizes="sm:50vw md:200px"}
sizes é a sintaxe do próprio @nuxt/image e alcança apenas a imagem da página.
O diálogo mantém a sua política: uma que descreve a coluna de texto não pode
descrever um diálogo.
Dimensões
width e height são opcionais e assim continuam — a maioria das páginas
omite-os, e exigi-los partiria todas as páginas já escritas.
Indique-os mesmo assim onde puder. São eles que permitem ao navegador reservar a caixa antes de o ficheiro chegar; sem eles a imagem não tem proporção intrínseca até carregar, e o texto por baixo mexe-se quando isso acontece. O componente preserva a proporção do par que recebe e não inventa nada quando não recebe nenhum: não há proporção por omissão nem recorte, porque uma proporção errada é pior do que um salto.
Uma imagem menor do que a coluna fica no seu próprio tamanho em vez de ser esticada.
Formatos
SVG e GIF animado passam sem ser tocados, na página e no diálogo, sem
qualquer srcset. Um vetor não tem pixels para reamostrar — pedir um com 608 px
de largura rasteriza um ficheiro que era nítido em qualquer tamanho — e um GIF
que passa por um encadeamento de rasterização volta reduzido ao seu primeiro
fotograma.
É isto que o componente faz, não uma afirmação sobre fornecedores: alguns deixam estes formatos passar, outros não, e uma camada de documentação não pode saber qual foi configurado pelo consumidor. As fontes adaptáveis servem os formatos de trama para os quais a ampliação existe — PNG, JPEG, WebP, AVIF.
Fornecedores
A camada não define qualquer chave image. Que serviço transforma uma imagem
pertence ao consumidor, tal como sources: um fornecedor escolhido pela camada é
um fornecedor que todo o consumidor tem de desfazer, e decide uma conta e uma
fatura tanto como um URL. Configure
@nuxt/image como em
qualquer aplicação Nuxt; o componente entrega-lhe apenas duas cadeias sizes.
Entregue a si mesmo, o @nuxt/image escolhe sozinho, e os três casos que um site
de documentação encontra são:
- Um servidor Node. O
ipxtransforma a pedido em/_ipx/…. Precisa dosharp, uma ligação nativa, que a saída Node já leva consigo. - Um site gerado (
nuxt generate). OipxStaticescreve cada variante no momento da construção. Depois disso nada corre, e a saída cresce com as variantes — o negócio que um site totalmente estático já está a fazer. - Um runtime na periferia — Cloudflare Workers e tudo o resto que não seja
Node nem estático. Nenhum transformador corre e as imagens são servidas tal
como foram versionadas. Um site pré-renderizado num runtime desses não deve
ser configurado com
ipx: é uma ligação nativa e não corre ali de todo. Recorra a um fornecedor de CDN se quiser as transformações.
As variantes do diálogo são geradas numa construção estática ainda que o diálogo esteja fechado quando a página é renderizada — o componente regista-as ele próprio junto do crawler de pré-renderização. Nada é descarregado até o diálogo abrir.
Uma imagem com zoom="false" não recebe nenhuma. Não há diálogo para abrir, por
isso cada ficheiro do tamanho do diálogo escrito para ela seria saída que
ninguém pode pedir.
Notas
A variante escura é nomeada explicitamente em vez de adivinhada por convenção.
Derivar -dark de um nome de ficheiro significa que um ficheiro em falta se
torna uma imagem partida, e o autor nunca fica a saber.
Uma imagem de uma fonte clonada de outro repositório não tem rota própria: o
Content descarrega a árvore para .data/content/, e nada copia os seus recursos
para public/. Os caminhos destes exemplos são absolutos para o public/ do
próprio site consumidor, que é onde uma imagem de documentação tem de viver hoje.