feat: version 2.9.0 -- ver documentos .md/.txt directo, sin descargar

Agrega un boton "Ver" en Documentos (adjuntos de proyectos/actividades) para archivos de
texto plano y Markdown: se leen via blob (mismo mecanismo ya usado para descargar, que ya
maneja el Bearer token) y se muestran en un popup -- el .md se renderiza con formato (marked)
y se sanitiza con DOMPurify antes de insertarse en el DOM, para no abrir una via de XSS con
HTML/JS embebido en un documento subido por otro usuario.

De paso corrige que subir un .md fallaba con "tipo de archivo no permitido": el navegador no
manda un mimetype confiable para esa extension (varia segun SO), asi que ahora se normaliza
por extension en el fileFilter de multer en vez de depender solo del mimetype del navegador.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Milton Gonzalez
2026-10-07 17:17:03 -05:00
parent 27cf2712fb
commit 3d220bcc20
11 changed files with 139 additions and 15 deletions
+21
View File
@@ -390,6 +390,27 @@ table.list-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
Chrome/Edge/Safari; en Firefox se ve el numero en texto plano, degradacion aceptable). */
.pin-input { -webkit-text-security: disc; letter-spacing: 4px; }
/* --- Visor de adjuntos de texto/markdown (ver AttachmentsPanel.jsx) --- */
.text-view {
white-space: pre-wrap; word-break: break-word; font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
font-size: .82rem; line-height: 1.5; color: rgb(var(--body)); margin: 0;
}
.markdown-view { font-size: .86rem; line-height: 1.55; color: rgb(var(--body)); }
.markdown-view h1, .markdown-view h2, .markdown-view h3, .markdown-view h4 { margin: 1.2em 0 .5em; line-height: 1.3; }
.markdown-view h1 { font-size: 1.4rem; }
.markdown-view h2 { font-size: 1.2rem; }
.markdown-view h3 { font-size: 1.05rem; }
.markdown-view p, .markdown-view ul, .markdown-view ol, .markdown-view blockquote { margin: 0 0 1em; }
.markdown-view ul, .markdown-view ol { padding-left: 1.4em; }
.markdown-view a { color: rgb(var(--accent)); }
.markdown-view code { background: rgb(var(--field)); border-radius: 4px; padding: .1em .35em; font-size: .85em; }
.markdown-view pre { background: rgb(var(--field)); border-radius: var(--r-sm); padding: 10px 12px; overflow-x: auto; }
.markdown-view pre code { background: none; padding: 0; }
.markdown-view blockquote { border-left: 3px solid rgb(var(--line)); padding-left: 12px; color: rgb(var(--muted)); }
.markdown-view img { max-width: 100%; }
.markdown-view table { border-collapse: collapse; margin-bottom: 1em; }
.markdown-view th, .markdown-view td { border: 1px solid rgb(var(--line)); padding: 4px 8px; font-size: .82rem; }
.vault-icon-picker { display: flex; flex-wrap: wrap; gap: 8px; }
.vault-icon-brands-header { display: flex; align-items: center; justify-content: space-between; padding-top: 8px; margin-top: 4px; border-top: 1px dashed rgb(var(--line)); }
.vault-icon-collapse-btn { color: rgb(var(--danger)); }