{"_id":"@agus01/node-red-contrib-monaco-editor","name":"@agus01/node-red-contrib-monaco-editor","dist-tags":{"latest":"1.1.0"},"versions":{"1.1.0":{"name":"@agus01/node-red-contrib-monaco-editor","version":"1.1.0","description":"Nodo Node-RED con editor Monaco que incluye validación inteligente de sintaxis para múltiples lenguajes de programación","main":"monaco.js","scripts":{"test":"echo \"No tests specified yet\" && exit 0"},"dependencies":{"express":"^4.19.2","monaco-editor":"0.34.1"},"keywords":["node-red","monaco-editor","code-editor","javascript","json","xml","html","css","web-editor","authentication","dynamic-content","mustache","handlebars","ejs","nunjucks","jinja2","jsonata","template-engine","syntax-highlighting"],"node-red":{"nodes":{"monaco-editor":"monaco.js"},"version":">=2.0.0"},"author":{"name":"Equipo-Scripting-IUA","email":"gragessi561@alumnos.iua.edu.ar"},"license":"MIT","_id":"@agus01/node-red-contrib-monaco-editor@1.1.0","_nodeVersion":"22.18.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-hI7N8yGz9p1UhdHlIve+oYqgsvhDvKwjMJRe6G2YYTVx6BtZFtLBNqbQFTLm7ErBxSmZEyKkFrcpwIuJGPTjFg==","shasum":"ddba80412bd4746a979d3166ba073c0a83e3237f","tarball":"https://registry.npmjs.org/@agus01/node-red-contrib-monaco-editor/-/node-red-contrib-monaco-editor-1.1.0.tgz","fileCount":5,"unpackedSize":74255,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIE0dbUDcLkYymK3Z97g6O7ryL4Kjj/qrVUX0VVE98hqJAiEA5Hs++tEsboq13RX/IOEwjcSY9WC7GqShrssuQjM/F/c="}]},"_npmUser":{"name":"agus01","email":"gragessi561@alumnos.iua.edu.ar"},"directories":{},"maintainers":[{"name":"agus01","email":"gragessi561@alumnos.iua.edu.ar"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/node-red-contrib-monaco-editor_1.1.0_1762745154948_0.6629374070141305"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-10T03:25:54.822Z","1.1.0":"2025-11-10T03:25:55.152Z","modified":"2025-11-10T03:25:55.522Z"},"maintainers":[{"name":"agus01","email":"gragessi561@alumnos.iua.edu.ar"}],"description":"Nodo Node-RED con editor Monaco que incluye validación inteligente de sintaxis para múltiples lenguajes de programación","keywords":["node-red","monaco-editor","code-editor","javascript","json","xml","html","css","web-editor","authentication","dynamic-content","mustache","handlebars","ejs","nunjucks","jinja2","jsonata","template-engine","syntax-highlighting"],"author":{"name":"Equipo-Scripting-IUA","email":"gragessi561@alumnos.iua.edu.ar"},"license":"MIT","readme":"# node-red-contrib-monaco-editor\r\n\r\nUn nodo Node-RED que integra el **Monaco Editor** (el mismo editor de VS Code) para edición de código con validación inteligente de sintaxis, soporte multi-lenguaje y autenticación flexible.\r\n\r\n## Descripción\r\n\r\nEste nodo permite crear interfaces de edición de código web completas directamente desde Node-RED, generando páginas HTML dinámicas con un editor Monaco totalmente funcional. Incluye soporte para múltiples lenguajes de programación, validación sintáctica en tiempo real, y diversas opciones de autenticación para interactuar con endpoints remotos o archivos locales.\r\n\r\n## Características Principales\r\n\r\n### Editor Monaco Integrado\r\n- **Editor de código profesional** basado en VS Code\r\n- **Tema oscuro** optimizado para sesiones largas de codificación\r\n- **IntelliSense** con autocompletado y sugerencias contextuales\r\n- **Minimapa** para navegación rápida en archivos grandes\r\n- **Ajuste de línea** automático para mejor legibilidad\r\n\r\n### Soporte Multi-Lenguaje\r\nValidación y resaltado de sintaxis para:\r\n- **JavaScript** (`.js`, `.mjs`, `.cjs`) - Validación completa con TypeScript compiler\r\n- **JSON** (`.json`) - Validación de estructura y sintaxis\r\n- **HTML** (`.html`, `.htm`) - Validación HTML5 completa\r\n- **CSS** (`.css`) - Validación de propiedades y sintaxis\r\n- **XML** (`.xml`) - Validación de estructura\r\n- **Markdown** (`.md`, `.markdown`) - Resaltado de sintaxis\r\n\r\n### Validación Inteligente de Sintaxis\r\n\r\n#### JavaScript/TypeScript\r\n- **Detección de variables no definidas** (errores semánticos)\r\n- **Validación de sintaxis ES2020+**\r\n- **Soporte para módulos ES6+**\r\n- **Ignorado inteligente** de errores de importación no resueltos\r\n- **Verificación de tipos** con JSDoc (opcional)\r\n\r\n#### HTML\r\n- **Validación HTML5** completa\r\n- **Detección de etiquetas no cerradas**\r\n- **Verificación de atributos válidos**\r\n- **Sugerencias de estructura** correcta\r\n\r\n#### JSON\r\n- **Validación de sintaxis JSON** estricta\r\n- **Detección de comas finales** o faltantes\r\n- **Verificación de estructura** de llaves/corchetes\r\n\r\n### Autenticación Flexible\r\nCuatro métodos de autenticación soportados:\r\n1. **Ninguna** - Sin autenticación\r\n2. **Basic Auth** - Usuario y contraseña\r\n3. **Bearer Token** - Token de autorización en headers\r\n4. **Query Token** - Token como parámetro en URL\r\n\r\n### Gestión de Archivos\r\n- **Selector de archivos** dinámico con carga desde endpoint\r\n- **Guardado automático** con detección de cambios\r\n- **Protección contra pérdida de datos** (confirmación antes de cerrar)\r\n- **Indicador visual** de cambios sin guardar\r\n- **Botón de recarga** para descartar cambios\r\n\r\n### Optimización de Rendimiento\r\n- **Workers sin CSP blob** para cumplir políticas de seguridad\r\n- **Carga optimizada** desde Node.js local o CDN (fallback)\r\n- **Caché de assets** con `immutable` y `maxAge: 1y`\r\n- **Debouncing** en detección de cambios (500ms)\r\n\r\n## Instalación\r\n\r\n### Desde la paleta de Node-RED\r\n```bash\r\ncd ~/.node-red\r\nnpm install node-red-contrib-monaco-editor\r\n```\r\n\r\n### Desde directorio de proyecto\r\n```bash\r\nnpm install node-red-contrib-monaco-editor\r\n```\r\n\r\n### Desarrollo/Local\r\n```bash\r\ncd ~/.node-red\r\nnpm install /ruta/a/node-red-contrib-monaco-editor\r\n```\r\n\r\nLuego reinicia Node-RED.\r\n\r\n## Uso Básico\r\n\r\n### Configuración del Nodo\r\n\r\n1. **Arrastra** el nodo `monaco-editor` desde la categoría \"function\" a tu flujo\r\n2. **Configura** las propiedades según tus necesidades:\r\n\r\n#### Propiedades Principales\r\n\r\n| Propiedad | Descripción | También vía msg |\r\n|-----------|-------------|-----------------|\r\n| **Nombre** | Nombre descriptivo del nodo | - |\r\n| **Tipo de contenido** | Lenguaje del editor (js, json, xml, html, css) | `msg.type` |\r\n| **Endpoint GET** | URL para obtener contenido desde servidor | `msg.endpointget` |\r\n| **Endpoint SET** | URL para guardar contenido en servidor | `msg.endpointset` |\r\n| **Archivo de contenido** | Ruta local al archivo a editar | `msg.pathtocontent` |\r\n\r\n#### Configuración de Autenticación\r\n\r\n| Tipo | Propiedades | También vía msg |\r\n|------|-------------|-----------------|\r\n| **Basic Auth** | Usuario y Contraseña | `msg.basicuser`, `msg.basicpass` |\r\n| **Bearer Token** | Token de autorización | `msg.authtoken` |\r\n| **Query Token** | Token y nombre del parámetro | `msg.authtoken`, `msg.tokenParam` |\r\n\r\n### Ejemplo de Flujo Simple\r\n\r\n```json\r\n[\r\n    {\r\n        \"id\": \"inject1\",\r\n        \"type\": \"inject\",\r\n        \"name\": \"Abrir Editor\",\r\n        \"topic\": \"\",\r\n        \"payload\": \"// Mi código inicial\\nconsole.log('Hola mundo');\",\r\n        \"wires\": [[\"monaco1\"]]\r\n    },\r\n    {\r\n        \"id\": \"monaco1\",\r\n        \"type\": \"monaco-editor\",\r\n        \"name\": \"Editor JavaScript\",\r\n        \"type\": \"js\",\r\n        \"endpointget\": \"http://localhost:1880/api/code/load\",\r\n        \"endpointset\": \"http://localhost:1880/api/code/save\",\r\n        \"authtype\": \"none\",\r\n        \"wires\": [[\"http1\"]]\r\n    },\r\n    {\r\n        \"id\": \"http1\",\r\n        \"type\": \"http response\",\r\n        \"name\": \"Respuesta HTTP\",\r\n        \"wires\": []\r\n    }\r\n]\r\n```\r\n\r\n## 📘 Ejemplos de Uso\r\n\r\n### Ejemplo 1: Editor Simple con Contenido Inicial\r\n\r\n```javascript\r\n// Inyectar contenido inicial\r\nmsg.payload = \"function suma(a, b) {\\n    return a + b;\\n}\";\r\nmsg.type = \"js\";\r\nreturn msg;\r\n```\r\n\r\n### Ejemplo 2: Editor con Archivo Local\r\n\r\n```javascript\r\nmsg.pathtocontent = \"/ruta/al/archivo/script.js\";\r\nmsg.type = \"js\";\r\nreturn msg;\r\n```\r\n\r\n### Ejemplo 3: Editor con API Remota y Basic Auth\r\n\r\n```javascript\r\nmsg.endpointget = \"https://api.ejemplo.com/code/load\";\r\nmsg.endpointset = \"https://api.ejemplo.com/code/save\";\r\nmsg.authtype = \"basic\";\r\nmsg.basicuser = \"usuario\";\r\nmsg.basicpass = \"contraseña\";\r\nmsg.type = \"json\";\r\nreturn msg;\r\n```\r\n\r\n### Ejemplo 4: Editor con Bearer Token\r\n\r\n```javascript\r\nmsg.endpointget = \"https://api.ejemplo.com/files/load\";\r\nmsg.endpointset = \"https://api.ejemplo.com/files/save\";\r\nmsg.authtype = \"bearer\";\r\nmsg.authtoken = \"mi-token-secreto-123\";\r\nmsg.type = \"html\";\r\nreturn msg;\r\n```\r\n\r\n### Ejemplo 5: Múltiples Archivos desde API\r\n\r\n```javascript\r\n// El editor automáticamente llamará a /api/code/files para listar archivos\r\nmsg.endpointget = \"http://localhost:1880/api/code/load\";\r\nmsg.endpointset = \"http://localhost:1880/api/code/save\";\r\nmsg.authtype = \"querytoken\";\r\nmsg.authtoken = \"abc123\";\r\nmsg.tokenParam = \"apikey\";\r\nmsg.type = \"js\";\r\nreturn msg;\r\n```\r\n\r\n## 🔌 API de Endpoints\r\n\r\n### GET - Cargar Contenido\r\n**URL:** `{endpointget}?filename={nombre_archivo}`\r\n\r\n**Headers:**\r\n```\r\nContent-Type: application/json\r\nAuthorization: Basic/Bearer (según configuración)\r\n```\r\n\r\n**Query Params (Query Token):**\r\n```\r\n?token=abc123 (o el nombre personalizado en tokenParam)\r\n```\r\n\r\n**Respuesta esperada:**\r\n```json\r\n{\r\n    \"content\": \"contenido del archivo...\",\r\n    \"filename\": \"script.js\"\r\n}\r\n```\r\n\r\n### POST - Guardar Contenido\r\n**URL:** `{endpointset}?filename={nombre_archivo}`\r\n\r\n**Headers:**\r\n```\r\nContent-Type: application/json\r\nAuthorization: Basic/Bearer (según configuración)\r\n```\r\n\r\n**Body:**\r\n```json\r\n{\r\n    \"content\": \"nuevo contenido...\",\r\n    \"code\": \"nuevo contenido...\",\r\n    \"filename\": \"script.js\"\r\n}\r\n```\r\n\r\n### GET - Listar Archivos\r\n**URL:** `{endpointget sin /load}/files`\r\n\r\n**Ejemplo:** Si `endpointget` es `/api/code/load`, el endpoint de archivos será `/api/code/files`\r\n\r\n**Respuesta esperada:**\r\n```json\r\n{\r\n    \"files\": [\r\n        { \"name\": \"script1.js\" },\r\n        { \"name\": \"config.json\" },\r\n        { \"name\": \"styles.css\" }\r\n    ]\r\n}\r\n```\r\n\r\nO formato simplificado:\r\n```json\r\n[\"script1.js\", \"config.json\", \"styles.css\"]\r\n```\r\n\r\n## Configuración Avanzada\r\n\r\n### Workers de Monaco\r\n\r\nEl nodo configura automáticamente los workers especializados para cada lenguaje:\r\n\r\n- **JavaScript/TypeScript**: `typescriptWorker.js`\r\n- **HTML**: `htmlWorker.js`\r\n- **CSS/SCSS/LESS**: `cssWorker.js`\r\n- **JSON**: `jsonWorker.js`\r\n- **Editor base**: `monaco-worker.js`\r\n\r\nLos workers se sirven desde:\r\n- **Local**: `/monaco-vs/vs/*` (cuando monaco-editor está instalado)\r\n- **CDN Fallback**: `https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/`\r\n\r\n### Opciones de Validación JavaScript\r\n\r\n```javascript\r\n// Configuración interna del nodo (no modificable sin editar código)\r\nmonaco.languages.typescript.javascriptDefaults.setCompilerOptions({\r\n    target: monaco.languages.typescript.ScriptTarget.ES2020,\r\n    allowNonTsExtensions: true,\r\n    moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,\r\n    module: monaco.languages.typescript.ModuleKind.ESNext,\r\n    allowJs: true,\r\n    checkJs: true, // Validación semántica activada\r\n    skipLibCheck: true\r\n});\r\n```\r\n\r\n### Detección Automática de Lenguaje\r\n\r\nEl editor detecta automáticamente el lenguaje basándose en la extensión del archivo:\r\n\r\n```javascript\r\n// Mapeo interno\r\n.js, .mjs, .cjs  → JavaScript\r\n.json            → JSON\r\n.html, .htm      → HTML\r\n.css             → CSS\r\n.xml             → XML\r\n.md, .markdown   → Markdown\r\n```\r\n\r\n## Arquitectura Técnica\r\n\r\n### Estructura del Proyecto\r\n\r\n```\r\nnode-red-contrib-monaco-editor/\r\n├── monaco.html          # Definición del nodo en Node-RED UI\r\n├── monaco.js            # Lógica del nodo en Node.js\r\n├── package.json         # Metadata y dependencias\r\n└── README.md           # Este archivo\r\n```\r\n\r\n### Flujo de Datos\r\n\r\n```\r\nUsuario → Inyecta msg → Nodo Monaco → Genera HTML → HTTP Response\r\n                            ↓\r\n                    Configura opciones\r\n                    (endpoints, auth, tipo)\r\n                            ↓\r\n                    Sirve Monaco assets\r\n                    (workers, VS loader)\r\n                            ↓\r\n                    Cliente web carga editor\r\n                            ↓\r\n                    Interactúa con endpoints\r\n                    (GET/POST archivos)\r\n```\r\n\r\n### Componentes Clave\r\n\r\n#### 1. **monaco.html** - Configuración UI\r\n- Define la interfaz de configuración del nodo\r\n- Campos dinámicos según tipo de autenticación\r\n- Validación de inputs\r\n- Tooltips y ayuda contextual\r\n\r\n#### 2. **monaco.js** - Lógica del Servidor\r\n- **Montaje de assets estáticos**: Sirve Monaco desde `node_modules`\r\n- **Generación HTML dinámica**: Crea el HTML del editor con configuración embebida\r\n- **Sistema de syntax providers**: Gestión de lenguajes soportados\r\n- **Detección de lenguaje**: Por extensión de archivo\r\n- **Gestión de workers**: Sin uso de `blob:` para compatibilidad CSP\r\n\r\n#### 3. **Editor HTML Generado** - Cliente Web\r\n- **Interfaz del editor**: Monaco embebido con toolbar\r\n- **Gestión de estado**: Detección de cambios, dirty flag\r\n- **Comunicación con endpoints**: Fetch API con autenticación\r\n- **Selector de archivos**: Listado y carga dinámica\r\n- **Prevención de pérdida**: Confirmación antes de cerrar\r\n\r\n## Opciones de Configuración del Editor\r\n\r\n### Opciones Monaco Predefinidas\r\n\r\n```javascript\r\n{\r\n    automaticLayout: true,        // Ajuste automático al contenedor\r\n    minimap: { enabled: true },   // Minimapa visible\r\n    theme: 'vs-dark',             // Tema oscuro\r\n    fontSize: 14,                 // Tamaño de fuente\r\n    lineNumbers: 'on',            // Números de línea\r\n    wordWrap: 'on',               // Ajuste de línea\r\n    suggestOnTriggerCharacters: true,\r\n    quickSuggestions: {\r\n        other: true,\r\n        comments: false,\r\n        strings: false\r\n    }\r\n}\r\n```\r\n\r\n### Atajos de Teclado\r\n\r\n| Atajo | Acción |\r\n|-------|--------|\r\n| `Ctrl/Cmd + S` | Guardar archivo |\r\n| `Ctrl/Cmd + Z` | Deshacer |\r\n| `Ctrl/Cmd + Y` | Rehacer |\r\n| `Ctrl/Cmd + F` | Buscar |\r\n| `Ctrl/Cmd + H` | Buscar y reemplazar |\r\n| `F1` | Paleta de comandos |\r\n\r\n## Depuración y Logs\r\n\r\n### Logs del Servidor (Node-RED)\r\n\r\nEl nodo emite logs en la consola de Node-RED:\r\n\r\n```\r\n[Monaco Worker] editor (local) baseUrl= /monaco-vs/\r\n[Monaco Worker] json (local) baseUrl= /monaco-vs/\r\n[DEBUG] after setModelLanguage(javascript) { langId: 'javascript', ... }\r\n```\r\n\r\n### Logs del Cliente (Navegador)\r\n\r\nAbre la consola del navegador (F12) para ver:\r\n\r\n```javascript\r\nMonaco Editor Config: { language: 'javascript', endpointGet: '...' }\r\nloadFileList() - Iniciando carga de archivos...\r\n[Markers update][current] { uri: '...', count: 2, markers: [...] }\r\n[HTML markers recargados] [...]\r\n```\r\n\r\n### Utilidad de Depuración\r\n\r\nEl editor expone una utilidad global en la consola del navegador:\r\n\r\n```javascript\r\n// Ver estado actual del editor\r\nwindow.monacoDebug.debugState('mi-tag');\r\n\r\n// Ver markers (errores/advertencias)\r\nwindow.monacoDebug.getCurrentMarkers();\r\n\r\n// Ver lenguajes disponibles\r\nwindow.monacoDebug.getLanguages();\r\n```\r\n\r\n## Seguridad\r\n\r\n### Content Security Policy (CSP)\r\n\r\nEl nodo **evita el uso de `blob:` URLs** para los workers, siendo compatible con políticas CSP estrictas:\r\n\r\n```\r\nContent-Security-Policy: script-src 'self' 'unsafe-eval'\r\n```\r\n\r\n### Recomendaciones de Seguridad\r\n\r\n1. **Usa HTTPS** para endpoints remotos\r\n2. **Almacena tokens** en variables de entorno, no en el flujo\r\n3. **Valida entrada** en tus endpoints antes de guardar archivos\r\n4. **Limita permisos** de escritura en el sistema de archivos\r\n5. **Implementa rate limiting** en tus APIs\r\n\r\n## 📊 Mensajes de Entrada y Salida\r\n\r\n### Mensaje de Entrada (`msg`)\r\n\r\n```javascript\r\n{\r\n    payload: \"código inicial\",     // Contenido inicial del editor\r\n    type: \"js\",                    // Tipo de contenido (js, json, html, css, xml)\r\n    endpointget: \"/api/load\",      // Endpoint GET\r\n    endpointset: \"/api/save\",      // Endpoint POST\r\n    pathtocontent: \"/ruta/file.js\", // Archivo local\r\n    authtype: \"bearer\",            // Tipo de autenticación\r\n    authtoken: \"token123\",         // Token de autenticación\r\n    basicuser: \"user\",             // Usuario (basic auth)\r\n    basicpass: \"pass\",             // Contraseña (basic auth)\r\n    tokenParam: \"apikey\"           // Nombre parámetro token (query)\r\n}\r\n```\r\n\r\n### Mensaje de Salida (`msg`)\r\n\r\n```javascript\r\n{\r\n    payload: \"<html>...</html>\",   // HTML completo del editor\r\n    editorConfig: {\r\n        language: \"javascript\",\r\n        endpoints: {\r\n            get: \"/api/load\",\r\n            set: \"/api/save\"\r\n        },\r\n        authentication: \"bearer\",\r\n        filePath: \"/ruta/file.js\"\r\n    }\r\n}\r\n```\r\n\r\n## 🧪 Testing\r\n\r\n### Prueba Básica\r\n\r\n1. Crea un flujo con:\r\n   - Nodo `inject` → `monaco-editor` → `http response`\r\n2. Configura un endpoint HTTP GET en el puerto que uses\r\n3. Inyecta el mensaje\r\n4. Abre el navegador en la URL configurada\r\n\r\n### Servidor de Prueba\r\n\r\n```javascript\r\n// Ejemplo de servidor Express simple para testing\r\nconst express = require('express');\r\nconst app = express();\r\napp.use(express.json());\r\n\r\nlet codeStorage = {\r\n    'test.js': 'console.log(\"Hola mundo\");',\r\n    'config.json': '{\\n  \"nombre\": \"prueba\"\\n}'\r\n};\r\n\r\n// Listar archivos\r\napp.get('/api/code/files', (req, res) => {\r\n    res.json({ \r\n        files: Object.keys(codeStorage).map(name => ({ name }))\r\n    });\r\n});\r\n\r\n// Cargar archivo\r\napp.get('/api/code/load', (req, res) => {\r\n    const filename = req.query.filename;\r\n    res.json({\r\n        content: codeStorage[filename] || '',\r\n        filename: filename\r\n    });\r\n});\r\n\r\n// Guardar archivo\r\napp.post('/api/code/save', (req, res) => {\r\n    const { filename, content } = req.body;\r\n    codeStorage[filename] = content;\r\n    res.json({ success: true });\r\n});\r\n\r\napp.listen(1880, () => console.log('Server on port 1880'));\r\n```\r\n\r\n## Changelog\r\n\r\n### v1.1.0\r\n- Validación completa de JavaScript con detección de variables no definidas\r\n- Validación HTML5 con detección de etiquetas y atributos\r\n- Sistema de syntax providers extensible\r\n- Soporte para múltiples archivos desde endpoint\r\n- Workers sin blob para compatibilidad CSP\r\n- Debouncing en detección de cambios\r\n- Protección contra pérdida de datos\r\n- Corrección de carga de workers HTML\r\n- Mejoras en detección de lenguaje por extensión\r\n\r\n### v1.0.0\r\n- Lanzamiento inicial\r\n- Integración de Monaco Editor\r\n- Soporte multi-lenguaje (JS, JSON, HTML, CSS, XML)\r\n- Autenticación flexible (none, basic, bearer, query token)\r\n- Carga/guardado desde endpoints\r\n- Lectura de archivos locales\r\n\r\n## Licencia\r\n\r\nMIT License - Ver archivo LICENSE para más detalles\r\n","readmeFilename":"README.md","_rev":"1-67011ea60234f111267f43bfba9fa6db"}