diff --git a/Cargo.lock b/Cargo.lock index 512a4dd..bec4a72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4776,6 +4776,7 @@ dependencies = [ "barra-web", "fana-md-reader-web", "gioser-canvas-web", + "gioser-graph-web", "js-sys", "revista-web", "wasm-bindgen", diff --git a/crates/apps/gioser-web/Cargo.toml b/crates/apps/gioser-web/Cargo.toml index c9d0cf6..d537ae2 100644 --- a/crates/apps/gioser-web/Cargo.toml +++ b/crates/apps/gioser-web/Cargo.toml @@ -14,6 +14,7 @@ gioser-canvas-web = { path = "../../modules/gioser/gioser-canvas-web" } fana-md-reader-web = { path = "../../modules/fana/fana-md-reader-web" } revista-web = { path = "../../modules/revista/revista-web" } barra-web = { path = "../../modules/barra/barra-web" } +gioser-graph-web = { path = "../../modules/gioser/gioser-graph-web" } wasm-bindgen.workspace = true wasm-bindgen-futures.workspace = true js-sys.workspace = true diff --git a/crates/apps/gioser-web/cytoscape-graph.js b/crates/apps/gioser-web/cytoscape-graph.js deleted file mode 100644 index 9df419e..0000000 --- a/crates/apps/gioser-web/cytoscape-graph.js +++ /dev/null @@ -1,226 +0,0 @@ -/** - * gioser-graph.js — Grafo semántico con Cytoscape.js - * - * Detecta automáticamente elementos agregados al DOM - * incluso los creados dinámicamente por el WASM. - * - * Espera a que el contenedor tenga tamaño real (>0) antes de montar - * Cytoscape, porque el deck arranca oculto (transform:scale(0)). - * - * Efecto "wineandcheesemap": clic en nodo → centra + desvanece resto. - * Doble clic → callback de navegación (window.__gioserGraphNavigate). - */ - -(function () { - 'use strict'; - - var COLORS = { - logos: '#d0dbff', aire: '#d0dbff', - nomos: '#f59056', fuego: '#f59056', - kay: '#d49873', tierra: '#d49873', - uku: '#6cd0f3', agua: '#6cd0f3', - }; - function caminoColor(c) { return COLORS[c] || '#888'; } - - function initGraph(container) { - var apiUrl = container.getAttribute('data-api-url') || 'https://api.gioser.net'; - var onNavigate = window.__gioserGraphNavigate || null; - - if (typeof cytoscape === 'undefined') { - var chk = setInterval(function () { - if (typeof cytoscape !== 'undefined') { clearInterval(chk); initGraph(container); } - }, 100); - return; - } - - // Esperar a que el contenedor tenga ancho real (deck oculto → 0) - var wait = setInterval(function () { - if (container.offsetWidth > 0 || container.offsetHeight > 0) { - clearInterval(wait); - doInit(container, apiUrl, onNavigate); - } - }, 50); - - // Timeout: si después de 10s sigue en 0, forzar con tamaño mínimo - setTimeout(function () { - if (container.offsetWidth === 0 || container.offsetHeight === 0) { - clearInterval(wait); - container.style.minWidth = '200px'; - container.style.minHeight = '180px'; - doInit(container, apiUrl, onNavigate); - } - }, 10000); - } - - function doInit(container, apiUrl, onNavigate) { - fetch(apiUrl + '/graph?limit=500') - .then(function (r) { return r.json(); }) - .then(function (data) { - if (!data.nodes || data.nodes.length === 0) { - container.innerHTML = ''; - return; - } - - var elements = []; - for (var i = 0; i < data.nodes.length; i++) { - var d = data.nodes[i].data; - if (!d.doc_id) continue; - var color = caminoColor(d.camino); - elements.push({ group: 'nodes', data: { - id: d.id, doc_id: d.doc_id, - label: d.name.length > 24 ? d.name.slice(0, 22) + '\u2026' : d.name, - camino: d.camino.toUpperCase(), color: color, - }}); - } - - var nodeIds = {}; - for (var i = 0; i < elements.length; i++) nodeIds[elements[i].data.id] = true; - - for (var i = 0; i < data.edges.length; i++) { - var ed = data.edges[i].data; - if (!nodeIds[ed.source] || !nodeIds[ed.target]) continue; - elements.push({ group: 'edges', data: { - id: ed.id, source: ed.source, target: ed.target, - weight: ed.weight || 0.7, - }}); - } - - var tipMap = {}; - for (var i = 0; i < data.nodes.length; i++) { - var d = data.nodes[i].data; - if (d.doc_id) tipMap[d.id] = d; - } - - var cy = cytoscape({ - container: container, - elements: elements, - style: [ - { selector: 'edge', style: { - 'width': 'mapData(weight, 0.5, 1.0, 0.5, 4.5)', - 'line-color': 'rgba(255,255,255,0.16)', - 'curve-style': 'haystack', 'haystack-radius': 0, - 'opacity': 0.6, - }}, - { selector: 'node', style: { - 'shape': 'round-rectangle', - 'width': 130, 'height': 34, - 'background-color': 'data(color)', 'background-opacity': 0.18, - 'border-color': 'data(color)', 'border-width': 1.8, 'border-opacity': 0.55, - 'color': 'rgba(232,234,245,0.88)', - 'font-size': 11, 'font-family': 'Inter, system-ui, sans-serif', - 'font-weight': 500, - 'text-valign': 'center', 'text-halign': 'center', - 'label': 'data(label)', 'min-zoomed-font-size': 8, - 'transition-property': 'background-opacity, border-opacity, border-width', - 'transition-duration': 180, - }}, - ], - layout: { name: 'preset', fit: false }, - }); - - cy.layout({ - name: 'cose', - animate: 'end', - animationEasing: 'ease-out', - animationDuration: 600, - idealEdgeLength: 150, - nodeRepulsion: 7000, - gravity: 0.2, - numIter: 800, - fit: true, - padding: 25, - }).run(); - - // Tooltip - var tooltipEl = document.createElement('div'); - tooltipEl.className = 'cy-tooltip'; - tooltipEl.style.cssText = - 'position:absolute;z-index:10;pointer-events:none;' + - 'background:rgba(6,5,13,0.90);color:#e8eaf5;' + - 'padding:6px 10px;border-radius:8px;font-size:11px;' + - 'font-family:Inter,sans-serif;line-height:1.4;' + - 'border:1px solid rgba(255,255,255,0.10);' + - 'backdrop-filter:blur(8px);max-width:220px;' + - 'opacity:0;transition:opacity 180ms ease;'; - container.style.position = 'relative'; - container.appendChild(tooltipEl); - - cy.on('mouseover', 'node', function (ev) { - var n = ev.target; - n.style({ 'background-opacity': 0.45, 'border-opacity': 0.9, 'border-width': 2.2 }); - var t = tipMap[n.id()]; - if (t && t.preview) { - tooltipEl.textContent = t.preview.slice(0, 130); - tooltipEl.style.opacity = '1'; - } - }); - - cy.on('mouseout', 'node', function (ev) { - ev.target.style({ 'background-opacity': 0.18, 'border-opacity': 0.55, 'border-width': 1.8 }); - tooltipEl.style.opacity = '0'; - }); - - cy.on('mousemove', function (ev) { - if (tooltipEl.style.opacity === '1') { - var p = ev.renderedPosition || { x: 0, y: 0 }; - tooltipEl.style.left = (p.x + 14) + 'px'; - tooltipEl.style.top = (p.y - 10) + 'px'; - } - }); - - cy.on('click', 'node', function (ev) { - var node = ev.target; - cy.nodes().not(node).not(node.neighborhood()).forEach(function (n) { - n.style({ 'opacity': 0.12 }); - }); - cy.edges().forEach(function (e) { e.style({ 'opacity': 0.06 }); }); - node.neighborhood().nodes().forEach(function (n) { n.style({ 'opacity': 1 }); }); - node.style({ 'opacity': 1, 'background-opacity': 0.40, 'border-opacity': 1 }); - node.connectedEdges().forEach(function (e) { e.style({ 'opacity': 0.7 }); }); - cy.animate({ center: { eles: node }, zoom: 2.5, duration: 350 }); - }); - - cy.on('dblclick', 'node', function (ev) { - var docId = ev.target.data('doc_id'); - if (onNavigate && docId) onNavigate(docId); - }); - - cy.on('click', function (ev) { - if (ev.target === cy) { - cy.nodes().forEach(function (n) { - n.style({ 'opacity': 1, 'background-opacity': 0.18, 'border-opacity': 0.55, 'border-width': 1.8 }); - }); - cy.edges().forEach(function (e) { e.style({ 'opacity': 0.6 }); }); - cy.animate({ zoom: 1, pan: { x: 0, y: 0 }, duration: 300 }); - } - }); - - var ro = new ResizeObserver(function () { cy.resize().fit(25); }); - ro.observe(container); - }) - .catch(function (err) { - console.warn('gioser-graph: error:', err); - container.innerHTML = - '
' + - '· grafo no disponible ·
'; - }); - } - - // MutationObserver - var observer = new MutationObserver(function (mutations) { - for (var m = 0; m < mutations.length; m++) { - var added = mutations[m].addedNodes; - for (var i = 0; i < added.length; i++) { - var el = added[i]; - if (el.tagName && el.tagName.toLowerCase() === 'gioser-graph') { initGraph(el); } - var gs = el.querySelectorAll ? el.querySelectorAll('gioser-graph') : []; - for (var j = 0; j < gs.length; j++) { initGraph(gs[j]); } - } - } - }); - observer.observe(document.documentElement, { childList: true, subtree: true }); - - var existing = document.querySelectorAll('gioser-graph'); - for (var i = 0; i < existing.length; i++) { initGraph(existing[i]); } -})(); diff --git a/crates/apps/gioser-web/index.html b/crates/apps/gioser-web/index.html index f06dcff..9254583 100644 --- a/crates/apps/gioser-web/index.html +++ b/crates/apps/gioser-web/index.html @@ -99,9 +99,6 @@ - - - - - - diff --git a/crates/apps/gioser-web/pkg/gioser_web.d.ts b/crates/apps/gioser-web/pkg/gioser_web.d.ts index 7405bc0..d5a7121 100644 --- a/crates/apps/gioser-web/pkg/gioser_web.d.ts +++ b/crates/apps/gioser-web/pkg/gioser_web.d.ts @@ -8,13 +8,14 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl export interface InitOutput { readonly memory: WebAssembly.Memory; readonly boot: () => void; - readonly __wasm_bindgen_func_elem_175: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_1203: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_174: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_174_3: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_442: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_219: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_220: (a: number, b: number) => void; + readonly __wasm_bindgen_func_elem_218: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_1398: (a: number, b: number, c: number, d: number) => void; + readonly __wasm_bindgen_func_elem_217: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_217_3: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_494: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_593: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_289: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_288: (a: number, b: number) => void; readonly __wbindgen_export: (a: number, b: number) => number; readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number; readonly __wbindgen_export3: (a: number) => void; diff --git a/crates/apps/gioser-web/pkg/gioser_web.js b/crates/apps/gioser-web/pkg/gioser_web.js index a257310..5a39956 100644 --- a/crates/apps/gioser-web/pkg/gioser_web.js +++ b/crates/apps/gioser-web/pkg/gioser_web.js @@ -11,6 +11,13 @@ function __wbg_get_imports() { const ret = typeof(v) === 'boolean' ? v : undefined; return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0; }, + __wbg___wbindgen_debug_string_edece8177ad01481: function(arg0, arg1) { + const ret = debugString(getObject(arg1)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, __wbg___wbindgen_is_function_5cd60d5cf78b4eef: function(arg0) { const ret = typeof(getObject(arg0)) === 'function'; return ret; @@ -118,6 +125,10 @@ function __wbg_get_imports() { const ret = getObject(arg0).createBuffer(); return isLikeNone(ret) ? 0 : addHeapObject(ret); }, + __wbg_createElementNS_10d5e4db26ea11c7: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + const ret = getObject(arg0).createElementNS(arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + return addHeapObject(ret); + }, arguments); }, __wbg_createElement_d10771800cfb6e7e: function() { return handleError(function (arg0, arg1, arg2) { const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); return addHeapObject(ret); @@ -286,6 +297,56 @@ function __wbg_get_imports() { const ret = result; return ret; }, + __wbg_instanceof_SvgElement_46537942d3e1376d: function(arg0) { + let result; + try { + result = getObject(arg0) instanceof SVGElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_SvgLineElement_d8200164030c234d: function(arg0) { + let result; + try { + result = getObject(arg0) instanceof SVGLineElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_SvgRectElement_f5a06e74af743100: function(arg0) { + let result; + try { + result = getObject(arg0) instanceof SVGRectElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_SvgTextElement_06345cd3cc71c951: function(arg0) { + let result; + try { + result = getObject(arg0) instanceof SVGTextElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, + __wbg_instanceof_SvgsvgElement_767ee4029321b850: function(arg0) { + let result; + try { + result = getObject(arg0) instanceof SVGSVGElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, __wbg_instanceof_WebGl2RenderingContext_419098f7bf88e87e: function(arg0) { let result; try { @@ -400,6 +461,9 @@ function __wbg_get_imports() { __wbg_set_passive_2233318ae781e44d: function(arg0, arg1) { getObject(arg0).passive = arg1 !== 0; }, + __wbg_set_textContent_9c5d65d703443b6d: function(arg0, arg1, arg2) { + getObject(arg0).textContent = arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2); + }, __wbg_set_width_25112eb6bf1148df: function(arg0, arg1) { getObject(arg0).width = arg1 >>> 0; }, @@ -433,6 +497,10 @@ function __wbg_get_imports() { const ret = getObject(arg0).style; return addHeapObject(ret); }, + __wbg_style_e34c1197b6088769: function(arg0) { + const ret = getObject(arg0).style; + return addHeapObject(ret); + }, __wbg_target_84e05e84ffc12989: function(arg0) { const ret = getObject(arg0).target; return isLikeNone(ret) ? 0 : addHeapObject(ret); @@ -492,46 +560,51 @@ function __wbg_get_imports() { return ret; }, __wbindgen_cast_0000000000000001: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 128, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_1203); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 176, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_1398); return addHeapObject(ret); }, __wbindgen_cast_0000000000000002: function(arg0, arg1) { // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [F64], shim_idx: 2, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_175); + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_218); return addHeapObject(ret); }, __wbindgen_cast_0000000000000003: function(arg0, arg1) { // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 6, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_174); + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_217); return addHeapObject(ret); }, __wbindgen_cast_0000000000000004: function(arg0, arg1) { // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 6, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_174_3); + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_217_3); return addHeapObject(ret); }, __wbindgen_cast_0000000000000005: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MouseEvent")], shim_idx: 122, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_442); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MouseEvent")], shim_idx: 137, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_494); return addHeapObject(ret); }, __wbindgen_cast_0000000000000006: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PointerEvent")], shim_idx: 51, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_219); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MouseEvent")], shim_idx: 170, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_593); return addHeapObject(ret); }, __wbindgen_cast_0000000000000007: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 53, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_220); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PointerEvent")], shim_idx: 67, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_289); return addHeapObject(ret); }, __wbindgen_cast_0000000000000008: function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 69, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_288); + return addHeapObject(ret); + }, + __wbindgen_cast_0000000000000009: function(arg0, arg1) { // Cast intrinsic for `Ref(Slice(F32)) -> NamedExternref("Float32Array")`. const ret = getArrayF32FromWasm0(arg0, arg1); return addHeapObject(ret); }, - __wbindgen_cast_0000000000000009: function(arg0, arg1) { + __wbindgen_cast_000000000000000a: function(arg0, arg1) { // Cast intrinsic for `Ref(String) -> Externref`. const ret = getStringFromWasm0(arg0, arg1); return addHeapObject(ret); @@ -550,30 +623,34 @@ function __wbg_get_imports() { }; } -function __wasm_bindgen_func_elem_220(arg0, arg1) { - wasm.__wasm_bindgen_func_elem_220(arg0, arg1); +function __wasm_bindgen_func_elem_288(arg0, arg1) { + wasm.__wasm_bindgen_func_elem_288(arg0, arg1); } -function __wasm_bindgen_func_elem_174(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_174(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_217(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_217(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_174_3(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_174_3(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_217_3(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_217_3(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_442(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_442(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_494(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_494(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_219(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_219(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_593(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_593(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_1203(arg0, arg1, arg2) { +function __wasm_bindgen_func_elem_289(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_289(arg0, arg1, addHeapObject(arg2)); +} + +function __wasm_bindgen_func_elem_1398(arg0, arg1, arg2) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_1203(retptr, arg0, arg1, addHeapObject(arg2)); + wasm.__wasm_bindgen_func_elem_1398(retptr, arg0, arg1, addHeapObject(arg2)); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -584,8 +661,8 @@ function __wasm_bindgen_func_elem_1203(arg0, arg1, arg2) { } } -function __wasm_bindgen_func_elem_175(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_175(arg0, arg1, arg2); +function __wasm_bindgen_func_elem_218(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_218(arg0, arg1, arg2); } function addHeapObject(obj) { @@ -601,6 +678,71 @@ const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry(state => wasm.__wbindgen_export4(state.a, state.b)); +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches && builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + function dropObject(idx) { if (idx < 1028) return; heap[idx] = heap_next; diff --git a/crates/apps/gioser-web/pkg/gioser_web_bg.wasm b/crates/apps/gioser-web/pkg/gioser_web_bg.wasm index 2022d2c..49ad85b 100644 Binary files a/crates/apps/gioser-web/pkg/gioser_web_bg.wasm and b/crates/apps/gioser-web/pkg/gioser_web_bg.wasm differ diff --git a/crates/apps/gioser-web/pkg/gioser_web_bg.wasm.d.ts b/crates/apps/gioser-web/pkg/gioser_web_bg.wasm.d.ts index 6344d75..af910e6 100644 --- a/crates/apps/gioser-web/pkg/gioser_web_bg.wasm.d.ts +++ b/crates/apps/gioser-web/pkg/gioser_web_bg.wasm.d.ts @@ -2,13 +2,14 @@ /* eslint-disable */ export const memory: WebAssembly.Memory; export const boot: () => void; -export const __wasm_bindgen_func_elem_175: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_1203: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_174: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_174_3: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_442: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_219: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_220: (a: number, b: number) => void; +export const __wasm_bindgen_func_elem_218: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_1398: (a: number, b: number, c: number, d: number) => void; +export const __wasm_bindgen_func_elem_217: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_217_3: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_494: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_593: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_289: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_288: (a: number, b: number) => void; export const __wbindgen_export: (a: number, b: number) => number; export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number; export const __wbindgen_export3: (a: number) => void; diff --git a/crates/apps/gioser-web/src/lib.rs b/crates/apps/gioser-web/src/lib.rs index 678431a..e9651f2 100644 --- a/crates/apps/gioser-web/src/lib.rs +++ b/crates/apps/gioser-web/src/lib.rs @@ -21,6 +21,7 @@ use std::rc::Rc; use barra_web::{Task, TaskList}; use gioser_canvas_web::{tips, Renderer}; +use gioser_graph_web::GraphWidget; use fana_md_reader_web::Reader; use revista_web::Deck; use wasm_bindgen::prelude::*; @@ -281,34 +282,46 @@ impl AppState { if let Err(e) = reader.open_url(&url_owned, &element_owned).await { web_sys::console::warn_1(&e); } - // Montar contenedor del grafo (Cytoscape.js) debajo del md + // Después de cargar el md, montar el grafo debajo let graph_container_id = format!("graph-{}-container", element_owned); + // Si ya existe, no lo duplicamos if document_clone.get_element_by_id(&graph_container_id).is_some() { return; } + // Crear contenedor debajo del content let wrapper: HtmlElement = document_clone - .create_element("gioser-graph") + .create_element("div") .ok() .and_then(|e| e.dyn_into::().ok()) - .unwrap_or_else(|| { - // fallback: div normal - let d: HtmlElement = document_clone - .create_element("div") - .ok() - .and_then(|e| e.dyn_into().ok()) - .unwrap(); - d - }); + .unwrap(); wrapper.set_id(&graph_container_id); - wrapper.set_attribute("data-api-url", "https://api.gioser.net").ok(); - wrapper.style().set_property("margin-top", "1.5rem").ok(); + wrapper.style().set_property("margin-top", "1rem").ok(); wrapper.style().set_property("padding-top", "1rem").ok(); - wrapper.style().set_property("border-top", "1px solid rgba(255,255,255,0.06)").ok(); - wrapper.style().set_property("min-height", "220px").ok(); + wrapper.style().set_property("border-top", "1px solid rgba(255,255,255,0.08)").ok(); + // Label + let label: HtmlElement = document_clone + .create_element("div") + .ok() + .and_then(|e| e.dyn_into::().ok()) + .unwrap(); + label.set_inner_html( + " + · grafo semántico · + " + ); + wrapper.append_child(&label).ok(); content_clone.append_child(&wrapper).ok(); - // El script cytoscape-graph.js usa MutationObserver - // para detectar dinámicos. No hace falta - // disparar nada acá. + // Cargar el grafo + let mut graph = GraphWidget::new( + wrapper, + "https://api.gioser.net", + None, // callback simplificado por ahora + ); + if let Err(e) = graph.load().await { + web_sys::console::warn_1(&format!("grafo: error al cargar: {:?}", e).into()); + return; + } }); }