--- name: metabase_create_document kind: function lang: py domain: infra version: "1.1.0" purity: impure signature: "def metabase_create_document(client: MetabaseClient, name: str, document: dict, collection_id: int = 0, *, validate: bool = True) -> dict" description: "Crea un document con contenido ProseMirror. Valida el arbol contra la whitelist de nodos ANTES de enviar (evita documentos que la API acepta pero el frontend renderiza vacíos). Usar prosemirror_card_embed() para embeber cards." tags: [metabase, document, create, api, prosemirror, python] uses_functions: [metabase_validate_document_payload_py_infra] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [httpx, uuid] params: - name: client desc: "instancia autenticada de MetabaseClient" - name: name desc: "titulo del document (1-254 caracteres, no blank)" - name: document desc: "arbol ProseMirror JSON: {type: 'doc', content: [...]}, o '' para arrancar vacio" - name: collection_id desc: "ID de coleccion destino (0 = root)" - name: validate desc: "si True (default), valida el ProseMirror antes de enviar. Lanza ValueError si hay nodos no soportados" output: "dict: document recien creado con id, entity_id y metadata" tested: false tests: [] test_file_path: "" file_path: "python/functions/metabase/documents.py" --- ## Ejemplo ```python from metabase.documents import metabase_create_document, prosemirror_card_embed doc = metabase_create_document(client, "Reporte Q1", { "type": "doc", "content": [ {"type": "heading", "attrs": {"level": 1}, "content": [{"type": "text", "text": "KPIs"}]}, {"type": "paragraph", "content": [{"type": "text", "text": "Revenue por canal:"}]}, prosemirror_card_embed(42, height=450), ] }) ``` ## Nodos ProseMirror — whitelist **Renderizan correctamente** (TipTap v0.59): `doc, paragraph, text, heading, bulletList, orderedList, listItem, blockquote, codeBlock, horizontalRule, hardBreak, cardEmbed, flexContainer, smartLink, resizeNode, mention` **La API acepta pero el frontend IGNORA** (resultado: documento vacío): `callout, taskList, taskItem, details, table, tableRow, tableCell, image, iframe` **Marks que renderizan:** `bold, italic, strike, code, link` **Marks ignorados:** `underline, highlight, subscript, textStyle` ## cardEmbed — SIEMPRE envolver en resizeNode Un `cardEmbed` desnudo renderiza pero queda con ~50px de alto. Metabase espera que vaya dentro de un `resizeNode`: ```python # MAL — card diminuta {"type": "cardEmbed", "attrs": {"id": 42}} # BIEN — usar el helper from metabase.documents import prosemirror_card_embed prosemirror_card_embed(42, height=450) # Genera: {"type": "resizeNode", "attrs": {"height": 450, "minHeight": 280}, # "content": [{"type": "cardEmbed", "attrs": {"id": 42, ...}}]} ``` ## Notas - La validación (`validate=True`) llama internamente a `metabase_validate_document_payload`. Si detecta nodos no soportados, lanza `ValueError` ANTES de hacer el POST — evita documentos que se ven vacíos. - Pasar `validate=False` solo si se está experimentando con nodos nuevos. - Para destacar texto, usar `blockquote` (NO `callout`). - Cuando embebes un card via `cardEmbed`, Metabase crea una referencia al card — el card debe existir.