TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Herramienta web (HTML/CSS/JS puro, sin build ni backend) para que la Federazione CAVA genere dos piezas oficiales y las descargue en PDF con un clic: 1. Comunicados A4 — una hoja membretada editable (tipo carta institucional). 2. Tarjetas Personales — una tarjeta de presentación (frente + dorso con QR) con datos que se completan en un formulario. No requiere instalación: se abre index.html directamente en el navegador (doble clic) y funciona tanto en file:// como servido desde cualquier hosting estático — con una excepción conocida hoy (Tarjetas Personales), ver "Pendientes" al final.README 전문 보기 ↗
Herramienta web (HTML/CSS/JS puro, sin build ni backend) para que la Federazione CAVA genere dos piezas oficiales y las descargue en PDF con un clic:
Además tiene un Mediakit: una galería con el logo oficial en varias versiones (completo o isotipo; color, blanco o negro) para descargar en SVG, PNG, JPG o PDF, eligiendo tamaño, fondo y forma (ajustado o cuadrado), o todo junto en un ZIP.
No requiere instalación: se abre index.html directamente en el navegador (doble clic) y funciona
tanto en file:// como servido desde cualquier hosting estático.
El botón "¿Cómo funciona esto?" del menú izquierdo abre un modal con la explicación completa para el usuario final, en español rioplatense. Si vas a tocar ese texto, mantené ese tono — es un pedido explícito de la Federazione, no un descuido.
index.html → estructura de la página (sidebar, hoja, tarjetas, panel derecho, modal)
vercel.json → hace que /logos sirva la misma index.html (link directo al Mediakit: el JS
detecta la ruta y abre esa vista; al cambiar de sección la URL pasa a /logos o /).
Bajo file:// no hay rutas, así que con doble clic se abre siempre en Comunicados.
css/
style.css → todo el CSS
js/
script.js → lógica de UI (sin frameworks, DOM API + execCommand) — NO incluye la
exportación del comunicado a PDF, ver pdf-comunicado.js
pdf-comunicado.js → arma el PDF del comunicado a mano con jsPDF, con texto real (no
rasteriza el DOM). Ver "La exportación a PDF" más abajo.
fonts-zt-nature.js → los 4 pesos de ZT Nature (Regular/Bold/Italic/BoldItalic) embebidos en
base64, para incrustarlos como fuente real dentro del PDF. Ver por qué
está embebido y no vía fetch() más abajo.
imagenes-comunicado.js → el logo y la franja de bandera del membrete, pre-rasterizados y
embebidos en base64, para incrustarlos en el PDF sin leerlos con
canvas.toDataURL() (mismo motivo que fonts-zt-nature.js, ver abajo).
imagenes-tarjeta.js → el QR del dorso de la tarjeta (img/qr.png) en base64, mismo motivo.
logo-vectores.js → el logo oficial vectorizado (paths SVG por capa de color: león,
letras, franja celeste, franja roja, leyenda). GENERADO, no editar a
mano: ver decisión de diseño #10.
mediakit.js → la vista Mediakit: arma cada versión del logo y la exporta.
herramientas/
vectorizar-logo.py → regenera js/logo-vectores.js a partir de logooficial.png (potrace).
logooficial.png → el logo oficial en alta (2058x2048), fuente de la vectorización.
img/ → todas las imágenes de la app:
- logo.png, bandera.svg → arte del membrete del comunicado (logo y franja de
bandera), usados también en el sidebar y las tarjetas
- iconoweb.png → favicon de la web (`<link rel="icon">` apunta a img/iconoweb.png).
Hubo una vuelta donde se probó `logo.png` como favicon y se volvió atrás — la
Federazione prefiere la banderita redonda para la pestaña del navegador.
- qr.png → QR fijo del dorso de la Tarjeta Personal
- loading.jpg (2400x1260px) → miniatura que usan las meta tags Open Graph/Twitter
Card del `<head>` para la vista previa al compartir el link por WhatsApp/redes.
No se referencia por ruta relativa sino por URL absoluta
(`https://generador-cava.vercel.app/img/loading.jpg`) — ver el comentario junto a
esas meta tags en `index.html` si cambia el dominio de despliegue.
fonts/ → ZTNature-{Regular,Bold,SemiBold,ExtraBold}.woff2, los únicos 4 pesos que carga
@font-face en css/style.css (tipografía única de toda la app — interfaz Y
documento). Los .ttf de Regular/Bold/Italic/BoldItalic que vivían acá se borraron:
no los carga nada en tiempo de ejecución (el PDF usa los que ya están embebidos en
base64 en js/fonts-zt-nature.js, no lee estos archivos).
El paquete completo de la tipografía (carpeta "ZT Nature/", 128 archivos) se SACÓ del repo a
propósito: el repo es público y no hay que redistribuir la familia completa (la Federazione tiene
autorización para usarla, no para regalarla). Lo guarda el responsable del proyecto fuera de
GitHub. NO volver a subirlo: si hace falta regenerar js/fonts-zt-nature.js, usar los .ttf locales
y subir solo el resultado.
No hay package.json, ni bundler, ni dependencias locales. Las únicas dependencias externas son
tres <script> por CDN (cdnjs), cargados en index.html antes de los scripts propios de js/:
html2canvas — todavía se usa para las Tarjetas Personales (descargarTarjetasPDF/PNG en
js/script.js), que son básicamente una imagen (logo + QR + datos), no un documento de texto.jspdf (UMD) — arma los PDF de comunicado y tarjetas.libphonenumber-js (bundle minificado, expone el global libphonenumber) — formatea en vivo el
campo Celular de la Tarjeta Personal a medida que se escribe (AsYouType, ver decisión de
diseño #7 más abajo).No se usa Google Fonts: toda la tipografía (interfaz y documento) es ZT Nature, self-hosted.
Si esto se despliega sin internet, hay que vendorizar estos tres scripts (jsPDF, html2canvas y libphonenumber-js).
Estas son las partes donde, si las "arreglás" sin saber por qué están así, vas a reintroducir bugs que ya se resolvieron a lo largo de varias iteraciones con el usuario:
pdf-comunicado.js arma el PDF del comunicado a mano con jsPDF, dibujando texto (seleccionable,
copiable, con links nativos) en vez de convertir el DOM en una imagen. Es la segunda vuelta de
esta función: la primera versión usaba html2canvas + jsPDF (rasterizaba #documento-a4 a una
imagen y pegaba rectángulos de pdf.link() encima para simular los links del footer) — se
reemplazó porque el texto no era seleccionable/copiable, algo que la Federazione pidió
explícitamente recuperar. Antes de esa, se probó window.print() (impresión nativa) y se volvió
atrás porque el logo y la franja de bandera no salían en impresión real y porque cambiaba la
descarga de un clic a tener que pasar por el diálogo de impresión.
Cómo funciona ahora (todo en pdf-comunicado.js):
.cuerpo (el contenteditable) y arma una lista de "bloques" (uno por <p>,
<div> o <li>), cada uno con una lista de "runs" de texto con su estilo. El estilo de cada
fragmento (negrita, cursiva, subrayado, tachado, color, resaltado, tamaño) se lee con
getComputedStyle() del nodo real en pantalla — NO se intenta detectar a mano combinaciones de
<b>/<font size>/<span style>, porque execCommand genera markup distinto según el
navegador para el mismo resultado visual, y getComputedStyle() ya resuelve esa variación.pdf.getTextWidth()), respetando alineación, viñetas/numeración y salto de página.medirAltura(), un layout "en seco"
que no dibuja nada) y ese espacio queda reservado —y nunca disponible para el cuerpo— en todas
las páginas por igual.<a href>) se detectan con el.closest('a[href]') en cada run de texto y
se agregan como pdf.link() real, en la posición exacta donde se dibujó ese texto — no hay
estimación por porcentaje del tamaño de la hoja como en la versión vieja.Extended_Pictographic): la fuente ZT
Nature no trae esos glifos y jsPDF no renderiza emoji a color. El footer (📍📞✉️🌐📱 originalmente)
ya no tiene emojis directamente en el HTML — se sacaron a propósito para que la previsualización
en pantalla se vea igual que el PDF final, ver decisión de diseño más abajo — así que esta regex
ahora solo importa como red de seguridad si alguien pega un emoji en el cuerpo del comunicado
(el contenteditable), donde sí puede aparecer texto arbitrario.pdf.addFileToVFS() + pdf.addFont(), usando los base64 de js/fonts-zt-nature.js. Están
embebidos como constante en vez de cargados con fetch() a unos .ttf en fonts/ porque la
app tiene que poder abrirse con doble clic vía file:// (ver el README más arriba), y fetch()
a archivos locales falla por CORS en Chrome bajo file:// (esos fuente ya no están en
— se usaron una sola vez para generar el base64 y se borraron; si hace falta
regenerarlo, pedirle los al responsable del proyecto, ver "Estructura de archivos"). Si en algún momento se agrega un
build/servidor y ya no hace falta soportar , se podría volver a + cache y
borrar , pero no lo hagas sin confirmar que dejó de ser un
requisito.Las Tarjetas Personales (descargarTarjetasPDF/descargarTarjetasPNG en js/script.js) siguen
usando html2canvas, pero con el mismo tratamiento: al cargar la página, js/script.js cambia
el src de las imágenes de las tarjetas por versiones embebidas (logo y bandera de
js/imagenes-comunicado.js, QR de js/imagenes-tarjeta.js). Antes leían img/ directo y la
descarga fallaba bajo file:// con el mismo SecurityError. Si cambia img/qr.png, hay que
regenerar js/imagenes-tarjeta.js.
.documento y .tarjeta tienen que quedar intactosEl CSS de .documento, .header-membrete, .cuerpo, .footer, .bandera-inferior, .tarjeta*
es el diseño "oficial" de la Federazione (logo y franja de bandera de img/logo.png/
img/bandera.svg, tipografía ZT Nature, medidas en mm reales para que impriman exacto en A4 /
90×50mm). Toda la demás interfaz (sidebar, panel derecho, modal, botones) usa esa misma tipografía
ZT Nature — antes había una separación deliberada donde la interfaz usaba Poppins de Google
Fonts, mientras que solo el documento usaba ZT Nature; se eliminó esa separación a pedido de la
Federazione para que toda la app use una sola tipografía.
@media print es un respaldo, no el camino principalEl botón verde "Descargar PDF" genera el archivo por JS (ver punto 1) y no dispara el diálogo de
impresión del navegador. El bloque @media print en css/style.css sigue existiendo por si
alguien hace Ctrl+P manualmente; tiene su propio arreglo para el bug de la doble hoja (fuerza
height: 297mm + overflow: hidden en .documento).
1fr iguales, no calc().app-shell es un grid: 1fr | sidebar | 1fr | (auto) | 1fr | panel-derecho | 1fr. Las cuatro
columnas 1fr son idénticas a propósito, para que el espacio entre pantalla↔sidebar,
sidebar↔hoja, hoja↔panel y panel↔pantalla sea siempre igual entre sí, sin importar el ancho
de ventana. La columna central es auto porque tiene que adaptarse tanto a la hoja A4 (794px)
como a la vista previa de tarjetas (mucho más angosta) sin que nadie tenga que recalcular nada.
Si volvés a esto con calc() a mano asumiendo un ancho fijo del centro, se rompe apenas cambie
el contenido (ya pasó dos veces). Esto es solo en compu: en tablet el grid se redefine (ver #6).
.main-panelbody tiene height: 100vh; overflow: hidden. El sidebar y el panel derecho quedan clavados en
pantalla (nunca se mueven) porque no hay scroll de página que se los lleve; el único que scrollea
es .main-panel (la hoja o las tarjetas), con su propio overflow-y: auto. Es un pedido explícito
del usuario ("que se mueva solo la hoja").
.main-panel alinea el contenido arriba por defecto (para que la hoja, más alta que la pantalla,
scrollee bien desde el principio) y solo se centra verticalmente cuando el JS agrega la clase
.centro-vertical (en el modo Tarjetas, que siempre entra entero en pantalla). No le pongas
justify-content: center fijo a .main-panel — reintroduce un bug de recorte de contenido con
overflow.
Hay tres layouts, todos en css/style.css:
--panel-w (ancho del sidebar y el
panel derecho) se achica en @media (max-width: 1400px) y @media (max-width: 1250px).<span class="nav-largo"> y se ocultan; "¿Cómo funciona esto?"
pasa a "Ayuda" con .nav-corto). Debajo: centro + panel derecho en 2 columnas, y si el panel
no entra de alto, los botones de descarga quedan sticky abajo. En tablet vertical
(601–900px) el panel derecho va arriba de la hoja como una cinta horizontal (herramientas en
fila; en Mediakit, 3 columnas con los .mk-col, que en los demás layouts son
display: contents y no existen para el layout).
transform: scale desde
ajustarEscalaCentro() en js/script.js (con un ResizeObserver). NO se usa zoom ni se
cambian las medidas en mm: así el PDF del comunicado (que lee getComputedStyle) y las marcas
de "Fin de hoja" no se enteran. La captura de tarjetas le saca el transform a la copia que
toma html2canvas (onclone en capturarTarjetas()), así la imagen sale siempre a tamaño real.formatoTexto() y
resaltarTexto() restauran el último rango seleccionado dentro de la hoja
(enfocarCuerpo()), y los botones hacen preventDefault en mousedown.(max-width: 600px), (max-width: 960px) and (max-height: 500px), mismo corte que
esCelular() / MEDIA_CELULAR en js/script.js): solo se puede usar el Mediakit (la gente
recibe el link por WhatsApp y quiere bajar el logo desde el teléfono; la hoja A4 no entra en un
teléfono). Todo se apila con scroll normal de página y se abre directo el Mediakit. Este bloque
va último en el CSS y pisa al de tablet. Para que se entienda que la herramienta "es para compu":
#modal-celular, abrirAvisoCelular()) que explica
que comunicados y tarjetas se arman en compu/tablet, con "Bajar el logo" y "Mandarme el link"
(navigator.share → portapapeles → WhatsApp). Una vez por sesión (). Por
no aparece: ya vinieron a buscar el logo.En el panel derecho del Mediakit en compu, el contenido está compactado para que entre sin scroll en una notebook de 1366x768: no le agregues cosas sin volver a chequear eso.
AsYouType en cada tecleoEl input #tj-celular ya NO tiene oninput="actualizarTarjeta()" en el HTML — ese listener se
movió a js/script.js con addEventListener('input', ...), a propósito, para que el orden de
ejecución quede garantizado: primero se reformatea el valor con
new libphonenumber.AsYouType('AR').input(valor) y recién después se llama a
actualizarTarjeta() para refrescar la vista previa. Si alguna vez se vuelve a poner
oninput="actualizarTarjeta()" en el HTML de ese input puntual, el handler inline se dispara
ANTES que el de addEventListener (se registra primero, al parsear el HTML) y la vista previa
queda un tecleo atrasada respecto del valor ya formateado.
Se crea una instancia de AsYouType nueva en cada tecleo (no una persistente reutilizada)
adrede: como siempre se le pasa el valor completo actual del input (no char por char), una
instancia nueva reformatea todo desde cero — así backspace, borrado en el medio y pegado de texto
funcionan bien sin arrastrar estado de tecleos anteriores. Si el usuario escribe un + seguido de
otro código de país (ej. +39 para Italia), AsYouType lo detecta solo a partir de los dígitos
y reformatea con ese país en vez de Argentina — no hay lógica propia de detección de país, es
built-in de la librería.
index.html tenía 📍📞✉️🌐📱 hardcodeados en .footer-texto (dirección, WhatsApp, email, web,
Instagram). Se sacaron directamente del HTML — no hay ningún script/listener limpiándolos en
tiempo de ejecución para esto puntual. El motivo: pdf-comunicado.js ya los descartaba al generar
el PDF (ver punto 1, la fuente ZT Nature no trae esos glifos), así que con los emojis todavía en
el HTML la previsualización en pantalla mostraba algo distinto de lo que salía en el PDF
descargado. Si en algún momento alguien quiere "decorar" el footer de nuevo, que sea con algo que
ZT Nature sepa dibujar (o con SVG inline, como los íconos de la toolbar), no con emoji — si no,
vuelve a haber esa diferencia entre pantalla y PDF.
body en css/style.css no es blanco puro: es un gris apenas más oscuro que el de la hoja A4 y
las tarjetas, con el único fin de que el área de trabajo (la hoja, las tarjetas) resalte por
contraste contra el fondo de la ventana. Si algún día "corregís" esto a blanco liso porque parece
un descuido, estás sacando ese contraste a propósito buscado.
Encima de ese gris hay un tricolor italiano muy suave (verde desde la izquierda, centro neutro,
rojo desde la derecha, con los colores de img/bandera.svg), para darle color sin que compita
con la hoja. Se probaron y descartaron: luces radiales en las esquinas, una franja de bandera
fija arriba, el león como marca de agua y un gris verdoso liso.
No hay un archivo por versión/formato en img/: js/mediakit.js toma los paths de
js/logo-vectores.js y, según lo que elija el usuario, arma el SVG como texto, rasteriza
PNG/JPG dibujando ese SVG (como data: URL) en un <canvas>, y dibuja el PDF vectorial
con el API de trazado de jsPDF (moveTo/lineTo/curveTo/fillEvenOdd) — por eso los paths
solo usan comandos M/L/C/Z absolutos. El ZIP se arma con JSZip (cdnjs).
data: URL (y no img/algo.svg) es lo que evita el canvas tainteado bajo
file:// (ver decisión #1): se probó y toDataURL() funciona con doble clic.canvas.toDataURL() + conversión a Blob en vez de canvas.toBlob(), porque toBlob
a veces nunca llama al callback (pasó en Chrome headless).fondos en TIPOS), y el panel solo ofrece
esos: no se puede bajar, por ejemplo, el logo blanco sobre fondo blanco. JPG no tiene
transparencia, así que cae solo al primer fondo sólido de la versión.img/logo.png (isotipo a color de la tarjeta, el comunicado y el menú) tenía el león en un
naranja más claro (#D58348) que logooficial.png. Se unificó al #D56F3C del Mediakit
(también en js/imagenes-comunicado.js) porque rinde mejor impreso: las líneas del león son
muy finas y el naranja claro se lavaba en papel. Si se reemplaza img/logo.png, mantener ese
naranja.logooficial.png y correr herramientas/vectorizar-logo.py
(instrucciones en el propio script); revisar el control.svg que genera contra el original..ttffonts/.ttffile://fetch()js/fonts-zt-nature.jsfile://js/imagenes-comunicado.js, igual que las fuentes. La primera versión de esto intentaba leerlos
en el momento con new Image() + <canvas> + toDataURL() (mismo mecanismo que usa
html2canvas puertas adentro) — funciona en file:// para MOSTRAR la imagen en pantalla, pero
Chrome tainea el canvas apenas tratás de leer sus píxeles de vuelta con toDataURL() sobre una
imagen cargada desde file://, aunque esté en la misma carpeta (SecurityError: Tainted canvases may not be exported). Por eso están precalculados: img/logo.png bajado a 1000px de
ancho (de sobra para imprimir a 32.2mm) y img/bandera.svg rasterizado una vez a ~300dpi
(2480×104px, porque jsPDF no soporta SVG vectorial sin un plugin aparte), los dos convertidos a
base64 a mano. Si algún día cambia el arte (img/logo.png o img/bandera.svg), hay que repetir
ese proceso y regenerar js/imagenes-comunicado.js — no alcanza con reemplazar el archivo de
imagen.sessionStorage/logosmostrarVista() no
los abre en celular y muestra el mismo aviso con un título según cuál se tocó.