--- id: KB-PLUGIN-038 title: "GLPI 11 — Assets de plugin: Monaco no lugar do CodeMirror, fim do jQuery UI, add_css/add_javascript e estáticos só em public/" domain: plugin-dev tags: - glpi11 - plugin - assets - monaco - codemirror - jquery-ui - add_css - add_javascript - public - gotcha status: active severity: high created_at: 2026-07-03 updated_at: 2026-07-03 applies_to: - plugins GLPI 11.x portados do GLPI 9/10 - qualquer plugin que injete CSS/JS ou sirva arquivos estáticos related_records: - KB-PLUGIN-004 - KB-PLUGIN-028 - KB-PLUGIN-036 --- # GLPI 11 — Assets de plugin: Monaco, fim do jQuery UI, add_css e public/ Aprendizados do porte do plugin `butterfly` (2.1.0, GLPI 10 → 11.0.8, 2026-07-03). Quatro armadilhas independentes que atingem qualquer plugin vindo do GLPI 9/10. ## 1. CodeMirror foi removido — o editor de código do core é o Monaco `public/lib/` do GLPI 11 não tem mais CodeMirror; tem `monaco-editor`/`monaco.js`. Qualquer `CodeMirror.fromTextArea(...)` de plugin quebra com `ReferenceError` silencioso no console (o form continua funcionando como textarea puro). ### Carregar a lib `monaco` é chave válida do mecanismo `$CFG_GLPI['javascript']` (testado em `Html.php` ~linha 1178, `in_array('monaco', $jslibs)`): ```php // setup.php, em plugin_init_() $CFG_GLPI['javascript']['config']['config'][] = 'monaco'; ``` ### Padrão de uso (o mesmo do core em templates/pages/admin/entity/custom_ui.html.twig) ```php echo '
'; echo Html::scriptBlock(' $(function() { window.GLPI.Monaco.createEditor("meu_editor", "scss", ' . json_encode($valor, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) . ', []).then(() => { $("#meu_editor").closest("form").on("formdata", (e) => { const editors = window.monaco.editor.getEditors().filter( (ed) => ed._domElement.id === "meu_editor" ); if (editors.length) { e.originalEvent.formData.delete("meu_campo"); e.originalEvent.formData.append("meu_campo", editors[0].getValue()); } }); }); }); '); ``` Pontos-chave: - O Monaco **não** usa textarea: é um `
` container + sync no submit via evento `formdata` (por isso o form precisa ser um `
` nativo). - Manter um `