npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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 sharp no gulpfile (sem dependência de gulp-sharp-responsive)
  • Comunicação module ↔ gulpfile: imgsToExport e exportedImages como variáveis compartilhadas por referência
  • Flag needsAlt: Marca imagens sem alt explícito para futura geração via IA
  • Getter getItems(): Renomeado de getItens() (mantém backward compat)
  • Cache + mtime check: Evita re-exportação de imagens que não mudaram
  • Exportação paralela: Promise.all para 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_PATH env 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-extension

Configuraçã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.js

Integração com o Gulpfile

A extensão funciona em duas fases:

  1. Build HTML (build:html) — O {% img %} lê metadados da imagem (via sharp), monta o <picture> HTML responsivo e registra a imagem em imgsToExport para exportação posterior.
  2. Export Images (build:exportImages) — Lê imgsToExport e 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: true na 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.Environment com { 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
    }
}