@luego/nunjucks-luego-image-extension
v2.2.1
Published
A extension for Nunjucks template engine
Readme
Luego Image {% img %}
Extensão Nunjucks para criar elementos <picture> responsivos e otimizados. A partir de uma imagem de origem, gera variantes em diferentes tamanhos (desktop/tablet/mobile), formatos, qualidades, densidades (1x/2x) e placeholders automáticos.
🚀 Versão 2.1.0 - Async Pipeline
- ✅ Extensão totalmente async: Usa
CallExtensionAsync— resolve corretamente imagens locais via{% img %} - ✅ Pipeline de exportação via sharp: Integração direta com
sharpno gulpfile (sem dependência degulp-sharp-responsive) - ✅ Comunicação module ↔ gulpfile:
imgsToExporteexportedImagescomo variáveis compartilhadas por referência - ✅ Flag
needsAlt: Marca imagens sem alt explícito para futura geração via IA - ✅ Getter
getItems(): Renomeado degetItens()(mantém backward compat) - ✅ Cache + mtime check: Evita re-exportação de imagens que não mudaram
- ✅ Exportação paralela:
Promise.allpara máximo throughput no build
Versão 2.0.0
- ✅ Dependências atualizadas: Sharp 0.33.5, Slugify 1.6.6
- ✅ Dependências removidas: image-size e spinnies (não utilizadas)
- ✅ Configuração flexível: Suporte a
LUEGO_CONFIG_PATHenv var - ✅ Tratamento de erros: Try/catch em operações assíncronas
- ✅ Cache de imagens: Evita reprocessamento desnecessário
- ✅ Validação de entrada: Valida parâmetros obrigatórios
Instalação
# NPM
npm i @luego/nunjucks-luego-image-extension
# Yarn
yarn add @luego/nunjucks-luego-image-extensionConfiguração (Opcional)
Por padrão, a extensão busca luego.config.js em ../../../luego.config.js. Para customizar:
export LUEGO_CONFIG_PATH=/path/to/your/luego.config.jsIntegração com o Gulpfile
A extensão funciona em duas fases:
- Build HTML (
build:html) — O{% img %}lê metadados da imagem (via sharp), monta o<picture>HTML responsivo e registra a imagem emimgsToExportpara exportação posterior. - Export Images (
build:exportImages) — LêimgsToExporte gera todas as variantes (tamanhos, placeholders, @2x) usando sharp diretamente.
// gulpfile.js — setup
const sharp = require('sharp');
// Variáveis compartilhadas por referência com o módulo
let exportedImages = {}; // { [slug]: { classSlug, component } } — imagens já processadas
let imgsToExport = []; // [{ imageSrc, imageName, config }] — fila de exportação
let imageItems = {}; // Referência para getItems() após build:html
const ImageExtensionHelper = new NunjucksImageExtension(nunjucks, nunjucksEnv, exportedImages, imgsToExport);
nunjucksEnv.addExtension('ImageExtension', ImageExtensionHelper);
// Após build:html concluir:
imageItems = ImageExtensionHelper.getItems();build:exportImages
Para cada imagem em imgsToExport, gera:
- Imagem principal por profile (desktop, tablet, mobile)
- Placeholder (6% do tamanho, webp, quality 25) — para efeito blur de carregamento
- Variante @2x quando
density === '2x'
Verifica mtime do source vs destino para evitar re-exportação desnecessária.
// Pipeline recomendado
gulp.task('build', gulp.series(
'clean',
'build:html',
gulp.parallel('build:scripts', 'build:styles', 'build:copy', 'build:exportImages')
));API
getItems() — Retorna exportedImages
const items = ImageExtensionHelper.getItems();
// { [slug]: { classSlug, component, needsAlt, ... } }getImgsToExport() — Retorna imgsToExport
const queue = ImageExtensionHelper.getImgsToExport();
// [{ imageSrc, imageName, config }]getItens() — Alias (deprecated, use getItems())
Como usar
A pasta root das imagens é /src/assets/images/ (sem .images)
# Versão abreviada
{% img 'imagem.jpg' %}
# Versão completa
{% img src='imagem.jpg' %}Resultado — <picture> com <source> por breakpoint + <img> com lazy loading:
<picture id="abc123" class="wrap-img wrap-imagem">
<source media="(max-width: 430px)" data-srcset="assets/images/exported/slug-mobile.webp" sizes="...">
<source media="(max-width: 1024px)" data-srcset="assets/images/exported/slug-tablet.webp" sizes="...">
<source media="(min-width: 1025px)" data-srcset="assets/images/exported/slug-desktop.webp" sizes="...">
<img
src="assets/images/exported/[email protected]"
alt="imagem"
class="imagem lazyload"
loading="lazy"
fetchpriority="auto"
height="1280"
width="1920"
data-image-type="exported"
style="--ratio: 1.5;">
<div class="blur"></div>
</picture>Observações importantes
- Imagens acima de 1920px de largura serão redimensionadas para 1920px (use width para forçar outro tamanho)
- Recomendamos sempre informar o atributo alt — imagens sem alt explícito recebem
needsAlt: truena config para futura geração automática via IA - A extensão padrão de exportação é webp
- Placeholders são gerados automaticamente (6% do tamanho, webp, quality 25)
- A extensão é async — requer
nunjucks.Environmentcom{ async: true }
Atributos
Atributo | Tipo | Default | Descrição
------ | ---- | ------- | -----------
src | string | — Obrigatório — | Caminho relativo à /src/assets/images/ ou URL externa
width | number | Tamanho original (max 1920px) | Somente width mantém o aspect ratio
height | number | Tamanho original | Somente height mantém o aspect ratio
fit | string | cover | cover / contain / fill / inside / outside
quality | number | 80 | De 1 a 100
format | string | webp | jpg / webp / png / gif / avif
loading | string | lazy | lazy / eager
fetchpriority | string | auto | auto / high / low
class | string | nome do arquivo | Classe CSS do <img> e <picture>
alt | string | imagem | Texto alternativo (imagens sem alt recebem needsAlt: true)
density | string | Auto por breakpoint | 1x / 2x
attr | string | '' | Atributos extras no <picture> (Emmet syntax)
breakpoints | object | Config padrão (desktop/tablet/mobile) | Breakpoints customizados
Width
{% img 'imagem.jpg', width=500 %}Height
{% img 'imagem.jpg', height=500 %}
# Com ambos, usa o atributo FIT (default: cover)
{% img 'imagem.jpg', height=500, width=500 %}Fit
{% img 'imagem.jpg', height=500, width=400, fit='contain' %}Quality
{% img 'imagem.jpg', quality=80 %}Format
{% img 'imagem.jpg', format='avif' %}Loading / Fetchpriority
# Imagem above-the-fold (LCP)
{% img 'hero.jpg', loading='eager', fetchpriority='high' %}Class
{% img 'imagem.jpg', class='hero-item' %}Breakpoints customizados
{% img 'imagem.jpg', breakpoints={
mobile: { breakpoint: '(max-width: 430px)', width: 400 },
tablet: { breakpoint: '(max-width: 1024px)', width: 800 },
desktop: { width: 1200 }
} %}Flag needsAlt
Quando o alt não é informado explicitamente (usa o default do config), a config da imagem recebe needsAlt: true. Isso permite, futuramente, integrar um pipeline de geração automática de alt-text via IA com leitura de imagem:
const items = ImageExtensionHelper.getItems();
for (const [slug, item] of Object.entries(items)) {
if (item.needsAlt) {
// Futuramente: enviar imagem para LLM com visão e obter alt-text
}
}