Skip to content

Preguntas frecuentes ​

IDs duplicados al insertar una bandera más de una vez ​

Cada SVG define ids para su recorte, su degradado y su dibujo. Los ids llevan la bandera y la forma (pn-ar-clip para el banderín, pn-ar-circle-clip para el círculo), así que banderas distintas, o formas distintas de la misma bandera, nunca chocan. Insertar el mismo SVG dos veces sí genera ids repetidos. Los navegadores suelen dibujarlo igual, hasta que la primera copia se oculta con display: none: entonces las demás pierden el recorte y el degradado.

  • <Pennant> y <PennantSvg> reescriben los ids en cada instancia (pn<scope>-<código>[-<forma>]-, a partir de useId), así que varias copias, formas o raíces de React nunca comparten ids.
  • <pennant-flag> los mantiene dentro de su shadow root.
  • Si insertas el SVG a mano con innerHTML, pasa un prefijo único: renderFlag(ar, { idPrefix: 'hero' }) o loadFlag('ar', { shape: 'circle', idPrefix: 'fila-3' }). Un <img> (por ejemplo con toDataUri) también aísla los ids.

Content Security Policy ​

FormatoNecesita
<img>, PNG, clases CSSimg-src con tu dominio o https://cdn.jsdelivr.net
toDataUri(svg) en <img> o CSSimg-src data:
Chunks diferidosscript-src de tu propio origen (son parte de tu bundle)
Modo fetchconnect-src para el dominio de base (por defecto https://cdn.jsdelivr.net)
SVG inline, React, Web Component, personalizaciónnada extra: funciona con style-src 'self'

Ningún formato necesita 'unsafe-inline':

  • El SVG de la bandera no tiene atributos style: los colores de la barra son atributos de presentación y la personalización es una regla de pennants/css/theme.css.
  • En React, los modos inline y fetch y <PennantSvg> generan un <span role="img"> con un <svg width height viewBox> adentro, dimensionado con atributos, así que tampoco necesitan hoja de estilos.
  • <pennant-flag> aplica sus estilos con una hoja de estilos construible (adoptedStyleSheets), que la CSP no restringe. Solo los navegadores sin esa API recurren a un elemento <style>.

Dos casos todavía generan un atributo style, que una style-src estricta bloquea: <Pennant mode="img"> con un size en unidades CSS (usa un número) y cualquier prop style que pases tú.

SSR e hidratación ​

  • pennants/react se puede importar desde React Server Components. <PennantSvg> se renderiza en el servidor; <Pennant> vive en un módulo 'use client' y pasa a ser una referencia de cliente. pennants/react/static exporta solo <PennantSvg>, para bundlers que de otro modo emitirían igual los chunks diferidos.
  • <Pennant> (modo inline) renderiza en el servidor un <svg> vacío del tamaño correcto y carga la bandera después de hidratar. No hay error de hidratación ni salto de layout, pero la bandera no está en el HTML.
  • Para que la bandera esté en el HTML del servidor, usa mode="img" o <PennantSvg art={ar} /> con un import estático.
  • fetchPennant y el modo fetch funcionan solo en el navegador: necesitan DOMParser para sanear la respuesta, así que en el servidor fetchPennant rechaza la promesa. Allí usa renderFlag con un dibujo estático, loadFlag o <PennantSvg art>.
  • pennants/element se puede importar en el servidor: definePennantElement no hace nada donde no existe customElements. El elemento se dibuja cuando se define en el navegador.
  • getPennantName usa Intl.DisplayNames. El servidor y el navegador pueden traer versiones distintas de CLDR, así que algún nombre puede variar entre ambos. Si importa, pasa un title explícito.

Solo ESM y require ​

El paquete es solo ESM. Node.js 20.19+ y 22.12+ pueden hacer require() de módulos ES sin top-level await, y este paquete no lo usa:

js
const { getPennantName } = require('pennants'); // funciona en Node.js 20.19+

En entornos más antiguos usa import(). En TypeScript, usa moduleResolution: "bundler", "node16" o "nodenext"; el modo antiguo "node" (node10) no lee exports y no encuentra pennants/react ni pennants/art/*.

Imports de assets en el bundler ​

Importar un archivo de imagen devuelve lo que tu bundler tenga configurado:

js
import url from 'pennants/svg/pennant/ar.svg'; // Vite: la URL
import markup from 'pennants/svg/pennant/ar.svg?raw'; // Vite: el SVG como texto
  • webpack 5: agrega una regla con type: 'asset/resource' para los .svg de node_modules/pennants.
  • Next.js: el import estático de un .svg devuelve un objeto; usa .src, la carpeta /public o pennantUrl.
  • pennants/css con Vite, SvelteKit o Astro: lo más simple es import 'pennants/css/cdn': las mismas clases, apuntando a URLs de jsDelivr con la versión fijada, que los bundlers no tocan (2,0 kB de CSS con gzip; las banderas se cargan del CDN). Si prefieres servir las banderas tú mismo, usa la hoja de estilos normal y evita que se incrusten. El motivo: Vite incrusta como data URI los assets de menos de 4 KiB, así que la mayoría de las 271 banderas termina dentro de tu CSS: 376,2 kB min /53,0 kB con gzip, en lugar de15,7 kB / 3,8 kB. Para mantenerlas como archivos (enAstro, la opción va dentro de vite.build). Next.js y Angular no las incrustan.
js
// vite.config.js
export default {
  build: {
    assetsInlineLimit: (file) => (file.includes('/pennants/svg/') ? false : undefined),
  },
};

Una bandera se ve mal ​

Los diseños vienen de flag-icons. Revisa primero el repositorio de flag-icons; los problemas del banderín en sí (recorte, barra, tamaños) van en el gestor de issues de pennants.

Falta un código ​

isPennantCode y codes listan exactamente lo que incluye el paquete. Las banderas nuevas se piden en flag-icons; cuando estén allí, se agregan aquí con la siguiente actualización de flag-icons.

Licencia MIT. Banderas de flag-icons (MIT).