diff --git a/.data/history.txt b/.data/history.txt
index 349845b..dc6dece 100644
--- a/.data/history.txt
+++ b/.data/history.txt
@@ -1,11 +1,16 @@
salario=horas*tarifa
-salario=800
-tarifa=36
+#salario=8000
+#tarifa=36
horas=?
+plot(sin(x),(x,0,1))
+
+
+
+
diff --git a/.gitignore b/.gitignore
index 65045b3..9cdf267 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,8 @@ __pycache__/
*.json
+.mathjax/
+
# Distribution / packaging
.Python
build/
diff --git a/app/gui_evaluation.py b/app/gui_evaluation.py
index ce5ba3c..a4af69b 100644
--- a/app/gui_evaluation.py
+++ b/app/gui_evaluation.py
@@ -331,4 +331,11 @@ class EvaluationManager:
def schedule_evaluation(self):
"""Programa una evaluación con debounce"""
self._debounce_timer.stop()
- self._debounce_timer.start(300) # 300ms de debounce
\ No newline at end of file
+ self._debounce_timer.start(300) # 300ms de debounce
+
+ def handle_output_link_click(self, link_id: str, result_object):
+ """Maneja clicks en links del output delegando al interactive manager"""
+ if self.main_window.interactive_manager:
+ self.main_window.interactive_manager.handle_interactive_click(result_object)
+ else:
+ self.logger.warning("Interactive manager no disponible para manejar click")
\ No newline at end of file
diff --git a/app/gui_latex.py b/app/gui_latex.py
index 8802f4d..85c8390 100644
--- a/app/gui_latex.py
+++ b/app/gui_latex.py
@@ -10,6 +10,7 @@ from PySide6.QtWebEngineWidgets import QWebEngineView
import logging
from typing import List, Dict, Optional
from .evaluation import EvaluationResult
+from .mathjax_manager import MathJaxManager
import sympy
@@ -24,6 +25,12 @@ class LatexPanel(QWidget):
self._pending_equations = []
self._parent_calculator = parent
self._webview_initialized = False
+ self._mathjax_timeout_count = 0
+ self._max_mathjax_timeout = 20 # 10 segundos (20 * 500ms)
+
+ # Manager de MathJax local
+ self.mathjax_manager = MathJaxManager()
+
self._setup_ui()
# Timer para verificar si MathJax está listo (inicializado bajo demanda)
@@ -107,93 +114,131 @@ class LatexPanel(QWidget):
""")
def _generate_mathjax_html(self):
- """Genera HTML base con MathJax configurado para SVG"""
- return """
-
+ """Genera HTML base con MathJax configurado para SVG (local o CDN)"""
+ # Obtener URL de MathJax (local si está disponible, CDN como fallback)
+ mathjax_url = self.mathjax_manager.get_mathjax_url()
+
+ return f"""
-
@@ -204,53 +249,90 @@ class LatexPanel(QWidget):
"""
@@ -281,27 +363,67 @@ class LatexPanel(QWidget):
if not self._webview_available:
return
- # Verificar si MathJax está listo
- self.webview.page().runJavaScript(
- "window.mathJaxReady || false;",
- self._on_mathjax_ready_check
- )
+ # Verificar múltiples condiciones de MathJax
+ js_check = """
+ (function() {
+ try {
+ // Verificar si window.mathJaxReady está definido
+ if (window.mathJaxReady === true) return true;
+
+ // Verificar si MathJax está disponible y listo
+ if (window.MathJax && window.MathJax.startup && window.MathJax.startup.document && window.MathJax.startup.document.state() >= 8) {
+ window.mathJaxReady = true;
+ return true;
+ }
+
+ // Verificar si existen las funciones necesarias
+ if (typeof addEquation === 'function' && typeof clearEquations === 'function') {
+ window.mathJaxReady = true;
+ return true;
+ }
+
+ return false;
+ } catch(e) {
+ console.error('Error verificando MathJax:', e);
+ return false;
+ }
+ })();
+ """
+
+ self.webview.page().runJavaScript(js_check, self._on_mathjax_ready_check)
def _on_mathjax_ready_check(self, ready):
"""Callback cuando se verifica el estado de MathJax"""
+ logging.debug(f"🔍 MathJax ready check: {ready}")
+
if ready and not self._mathjax_ready:
self._mathjax_ready = True
self._mathjax_check_timer.stop()
- logging.debug("✅ MathJax listo, procesando ecuaciones pendientes")
+ logging.debug(f"✅ MathJax listo, procesando {len(self._pending_equations)} ecuaciones pendientes")
# Renderizar ecuaciones pendientes
for eq in self._pending_equations:
self._add_equation_to_webview(eq['type'], eq['content'])
+ logging.debug(f"📊 Ecuación agregada al WebView: {eq['type']}")
self._pending_equations.clear()
# Trigger initial render si hay un calculador padre
if self._parent_calculator and hasattr(self._parent_calculator, '_trigger_initial_latex_render'):
self._parent_calculator._trigger_initial_latex_render()
+ elif not ready:
+ self._mathjax_timeout_count += 1
+ if self._mathjax_timeout_count >= self._max_mathjax_timeout:
+ # Timeout alcanzado, forzar como listo para mostrar contenido en texto plano
+ logging.warning("⚠️ MathJax timeout - cambiando a modo fallback")
+ self._mathjax_ready = True
+ self._mathjax_check_timer.stop()
+
+ # Procesar ecuaciones pendientes como texto plano
+ for eq in self._pending_equations:
+ self._add_equation_as_text(eq['type'], eq['content'])
+ self._pending_equations.clear()
+ else:
+ logging.debug(f"⏳ MathJax aún no está listo ({self._mathjax_timeout_count}/{self._max_mathjax_timeout}), continuando verificación...")
def _add_equation_to_webview(self, eq_type: str, content: str):
"""Añade una ecuación directamente al webview"""
@@ -310,6 +432,22 @@ class LatexPanel(QWidget):
js_code = f"addEquation('{eq_type}', '{escaped_content}');"
self.webview.page().runJavaScript(js_code)
+ def _add_equation_as_text(self, eq_type: str, content: str):
+ """Añade una ecuación como texto plano cuando MathJax falla"""
+ if self._webview_available:
+ escaped_content = content.replace('\\', '\\\\').replace("'", "\\'").replace('"', '\\"')
+ # Agregar ecuación como texto plano sin MathJax
+ js_code = f"""
+ var container = document.getElementById('equations-container');
+ if (container) {{
+ var equation = document.createElement('div');
+ equation.className = 'equation-block {eq_type}';
+ equation.innerHTML = '{escaped_content}
';
+ container.appendChild(equation);
+ }}
+ """
+ self.webview.page().runJavaScript(js_code)
+
def add_equation(self, eq_type: str, content: str):
"""Añade una ecuación al panel"""
self.equations.append({'type': eq_type, 'content': content})
diff --git a/app/gui_main.py b/app/gui_main.py
index 13c51db..e868336 100644
--- a/app/gui_main.py
+++ b/app/gui_main.py
@@ -124,26 +124,40 @@ class HybridCalculatorPySide6(QMainWindow):
# Sincronizar scroll
self._setup_scroll_sync()
- # Añadir splitter al layout
- main_layout.addWidget(self.main_splitter)
+ # Crear splitter secundario para LaTeX
+ self.secondary_splitter = QSplitter(Qt.Horizontal)
+ self.secondary_splitter.addWidget(self.main_splitter)
# Botón expandible para LaTeX
self.latex_button = ExpandableLatexButton()
self.latex_button.clicked.connect(self._toggle_latex_panel)
- main_layout.addWidget(self.latex_button)
- # Panel LaTeX (inicialmente oculto)
+ # Panel LaTeX con splitter
self.latex_panel = LatexPanel(self)
- self.latex_panel.setMinimumWidth(300)
- self.latex_panel.setMaximumWidth(500)
+ self.latex_panel.setMinimumWidth(200)
if self.latex_panel_visible:
- main_layout.addWidget(self.latex_panel)
+ self.secondary_splitter.addWidget(self.latex_panel)
self.latex_button.setChecked(True)
+ # Configurar tamaños: 70% para main_splitter, 30% para latex_panel
+ latex_width = self.settings.get("latex_panel_width", 300)
+ total_width = 1000 # Ancho por defecto de la ventana
+ main_width = total_width - latex_width
+ self.secondary_splitter.setSizes([main_width, latex_width])
else:
# Asegurar que el panel está oculto por defecto
self.latex_panel.hide()
self.latex_button.setChecked(False)
+ self.secondary_splitter.setSizes([1000])
+
+ # Layout principal con splitter secundario y botón
+ splitter_layout = QHBoxLayout()
+ splitter_layout.setContentsMargins(0, 0, 0, 0)
+ splitter_layout.setSpacing(0)
+ splitter_layout.addWidget(self.secondary_splitter)
+ splitter_layout.addWidget(self.latex_button)
+
+ main_layout.addLayout(splitter_layout)
# Los formatos de salida se configuran automáticamente en EvaluationManager
@@ -154,6 +168,9 @@ class HybridCalculatorPySide6(QMainWindow):
# Aplicar tema oscuro
self._apply_dark_theme()
+
+ # Aplicar tamaño de fuente guardado
+ self._apply_saved_font_size()
def _setup_scroll_sync(self):
"""Sincroniza el scroll entre entrada y salida"""
@@ -242,6 +259,22 @@ class HybridCalculatorPySide6(QMainWindow):
"""
self.setStyleSheet(dark_style)
+ def _apply_saved_font_size(self):
+ """Aplica el tamaño de fuente guardado"""
+ is_large = self.settings_manager.get_setting("font_size_large", False)
+ font_size = 14 if is_large else 11
+
+ # Aplicar al estilo actual
+ current_style = self.styleSheet()
+ import re
+
+ # Reemplazar font-size en QPlainTextEdit y QTextEdit
+ pattern = r'(QPlainTextEdit, QTextEdit\s*\{[^}]*?)font-size:\s*\d+px;([^}]*\})'
+ replacement = rf'\1font-size: {font_size}px;\2'
+
+ new_style = re.sub(pattern, replacement, current_style)
+ self.setStyleSheet(new_style)
+
def _on_input_changed(self):
"""Maneja cambios en el texto de entrada"""
# Delegar al autocomplete manager
@@ -265,21 +298,28 @@ class HybridCalculatorPySide6(QMainWindow):
def _toggle_latex_panel(self):
"""Togglea la visibilidad del panel LaTeX"""
- main_layout = self.centralWidget().layout()
-
if self.latex_panel_visible:
# Ocultar panel
- main_layout.removeWidget(self.latex_panel)
+ self.secondary_splitter.widget(1).hide() if self.secondary_splitter.count() > 1 else None
self.latex_panel.hide()
self.latex_button.setChecked(False)
self.latex_panel_visible = False
+ self.secondary_splitter.setSizes([1000])
else:
# Mostrar panel
- main_layout.addWidget(self.latex_panel)
+ if self.secondary_splitter.count() == 1:
+ self.secondary_splitter.addWidget(self.latex_panel)
+
self.latex_panel.show()
self.latex_button.setChecked(True)
self.latex_panel_visible = True
+ # Configurar tamaños
+ latex_width = self.settings.get("latex_panel_width", 300)
+ total_width = self.width()
+ main_width = total_width - latex_width - 50 # 50 para el botón
+ self.secondary_splitter.setSizes([main_width, latex_width])
+
# Actualizar panel con ecuaciones pendientes
self._sync_latex_equations_on_show()
@@ -305,6 +345,13 @@ class HybridCalculatorPySide6(QMainWindow):
def closeEvent(self, event):
"""Maneja el cierre de la aplicación"""
+ # Guardar ancho del panel LaTeX si está visible
+ if self.latex_panel_visible and self.secondary_splitter.count() > 1:
+ sizes = self.secondary_splitter.sizes()
+ if len(sizes) > 1:
+ latex_width = sizes[1]
+ self.settings_manager.set_setting("latex_panel_width", latex_width)
+
# Delegar al settings manager
self.settings_manager.save_all()
event.accept()
diff --git a/app/gui_menus.py b/app/gui_menus.py
index 56f80e0..9d6b556 100644
--- a/app/gui_menus.py
+++ b/app/gui_menus.py
@@ -76,6 +76,31 @@ class MenuManager:
view_menu.addSeparator()
+ # Submenu de fuentes
+ font_menu = view_menu.addMenu("Tamaño de fuente")
+
+ font_small_action = QAction("Pequeña (11px)", self.main_window)
+ font_small_action.setCheckable(True)
+ font_small_action.triggered.connect(lambda: self.set_font_size(False))
+ font_menu.addAction(font_small_action)
+
+ font_large_action = QAction("Grande (14px)", self.main_window)
+ font_large_action.setCheckable(True)
+ font_large_action.triggered.connect(lambda: self.set_font_size(True))
+ font_menu.addAction(font_large_action)
+
+ # Marcar el tamaño actual
+ is_large = self.main_window.settings_manager.get_setting("font_size_large", False)
+ if is_large:
+ font_large_action.setChecked(True)
+ else:
+ font_small_action.setChecked(True)
+
+ self.font_small_action = font_small_action
+ self.font_large_action = font_large_action
+
+ view_menu.addSeparator()
+
system_info_action = QAction("Información del sistema", self.main_window)
system_info_action.triggered.connect(self.show_types_info)
view_menu.addAction(system_info_action)
@@ -100,6 +125,10 @@ class MenuManager:
latex_status_action.triggered.connect(self._show_latex_panel_status)
diag_menu.addAction(latex_status_action)
+ save_html_action = QAction("💾 Guardar HTML del Panel LaTeX", self.main_window)
+ save_html_action.triggered.connect(self._save_latex_html)
+ diag_menu.addAction(save_html_action)
+
diag_menu.addSeparator()
copy_debug_action = QAction("📋 Copiar Debug al Portapapeles", self.main_window)
@@ -212,6 +241,47 @@ class MenuManager:
except Exception as e:
QMessageBox.critical(self.main_window, "Error", f"No se pudo limpiar el historial:\n{e}")
+ def set_font_size(self, is_large: bool):
+ """Cambia el tamaño de fuente de los paneles"""
+ # Guardar configuración
+ self.main_window.settings_manager.set_setting("font_size_large", is_large)
+
+ # Actualizar checkboxes
+ self.font_small_action.setChecked(not is_large)
+ self.font_large_action.setChecked(is_large)
+
+ # Aplicar nuevo tamaño
+ font_size = 14 if is_large else 11
+ self._apply_font_size_to_panels(font_size)
+
+ status_text = f"🔤 Fuente cambiada a {'grande' if is_large else 'pequeña'} ({font_size}px)"
+ self.main_window._update_status(status_text)
+
+ def _apply_font_size_to_panels(self, font_size: int):
+ """Aplica el tamaño de fuente a los paneles de texto"""
+ style_update = f"""
+ QPlainTextEdit, QTextEdit {{
+ font-size: {font_size}px;
+ }}
+ """
+
+ # Actualizar estilo de los paneles principales
+ current_style = self.main_window.styleSheet()
+ # Reemplazar solo la parte de font-size en QPlainTextEdit y QTextEdit
+ import re
+
+ # Patrón para encontrar y reemplazar font-size en QPlainTextEdit y QTextEdit
+ pattern = r'(QPlainTextEdit, QTextEdit\s*\{[^}]*?)font-size:\s*\d+px;([^}]*\})'
+ replacement = rf'\1font-size: {font_size}px;\2'
+
+ new_style = re.sub(pattern, replacement, current_style)
+
+ # Si no se encontró el patrón, agregar el estilo
+ if new_style == current_style:
+ new_style += style_update
+
+ self.main_window.setStyleSheet(new_style)
+
# ========== FUNCIONES DE MENÚ HERRAMIENTAS ==========
def reload_types(self):
@@ -314,6 +384,70 @@ PARA SOLUCIONAR:
self._show_info_dialog("Estado Panel LaTeX", status_message)
+ def _save_latex_html(self):
+ """Guarda el HTML del panel LaTeX para diagnóstico"""
+ try:
+ # Obtener HTML del panel LaTeX
+ latex_panel = self.main_window.latex_panel
+
+ if hasattr(latex_panel, '_webview_available') and latex_panel._webview_available:
+ # Panel con WebEngine
+ if hasattr(latex_panel, 'webview') and latex_panel._webview_initialized:
+ # Obtener HTML actual del WebView
+ def on_html_received(html_content):
+ self._save_html_to_file(html_content, "webview_current")
+
+ latex_panel.webview.page().toHtml(on_html_received)
+
+ # También guardar el HTML base generado
+ base_html = latex_panel._generate_mathjax_html()
+ self._save_html_to_file(base_html, "webview_base")
+ else:
+ # WebEngine no inicializado, solo HTML base
+ base_html = latex_panel._generate_mathjax_html()
+ self._save_html_to_file(base_html, "webview_not_initialized")
+ else:
+ # Panel con fallback text browser
+ if hasattr(latex_panel, 'text_browser'):
+ fallback_html = latex_panel.text_browser.toHtml()
+ self._save_html_to_file(fallback_html, "fallback_textbrowser")
+ else:
+ self._save_html_to_file("No hay contenido HTML disponible", "no_content")
+
+ QMessageBox.information(
+ self.main_window,
+ "HTML Guardado",
+ "El HTML del panel LaTeX ha sido guardado en ./debug_html/ para diagnóstico."
+ )
+
+ except Exception as e:
+ self.logger.error(f"Error guardando HTML del panel LaTeX: {e}")
+ QMessageBox.critical(
+ self.main_window,
+ "Error",
+ f"Error guardando HTML: {e}"
+ )
+
+ def _save_html_to_file(self, html_content, file_suffix):
+ """Guarda contenido HTML a un archivo"""
+ # Crear directorio de debug si no existe
+ debug_dir = Path("./debug_html")
+ debug_dir.mkdir(exist_ok=True)
+
+ # Generar nombre de archivo con timestamp
+ timestamp = time.strftime("%Y%m%d_%H%M%S")
+ filename = f"latex_panel_{file_suffix}_{timestamp}.html"
+ filepath = debug_dir / filename
+
+ try:
+ with open(filepath, "w", encoding="utf-8") as f:
+ f.write(html_content)
+
+ self.logger.info(f"HTML guardado en: {filepath}")
+
+ except Exception as e:
+ self.logger.error(f"Error escribiendo archivo HTML: {e}")
+
def _copy_debug_to_clipboard(self):
"""Copia información de debug completa al portapapeles"""
try:
diff --git a/app/gui_settings.py b/app/gui_settings.py
index f6fe055..ca7781b 100644
--- a/app/gui_settings.py
+++ b/app/gui_settings.py
@@ -31,7 +31,9 @@ class SettingsManager:
"window_geometry": None,
"splitter_sizes": None,
"debug_mode": False,
- "latex_panel_visible": False
+ "latex_panel_visible": False,
+ "latex_panel_width": 300,
+ "font_size_large": False # False = pequeña (11px), True = grande (14px)
}
def _save_settings(self):
diff --git a/app/gui_widgets.py b/app/gui_widgets.py
index e94785a..c36eea8 100644
--- a/app/gui_widgets.py
+++ b/app/gui_widgets.py
@@ -48,9 +48,13 @@ class OutputTextEdit(QTextEdit):
cursor = self.cursorForPosition(event.pos())
pos = cursor.position()
+ logging.debug(f"🖱️ Click en posición {pos}, links disponibles: {len(self.clickable_links)}")
+
# Buscar si el click fue en un link
for (start, end), (link_id, obj) in self.clickable_links.items():
+ logging.debug(f"🔍 Verificando link {start}-{end}: {link_id}")
if start <= pos <= end:
+ logging.debug(f"✅ Click en link detectado: {link_id}")
self.link_clicked.emit(link_id, obj)
return
diff --git a/app/mathjax_manager.py b/app/mathjax_manager.py
new file mode 100644
index 0000000..5e1f238
--- /dev/null
+++ b/app/mathjax_manager.py
@@ -0,0 +1,120 @@
+"""
+Sistema de gestión de MathJax local con descarga automática
+"""
+import os
+import zipfile
+import logging
+from pathlib import Path
+from urllib.request import urlretrieve
+from urllib.error import URLError
+
+
+class MathJaxManager:
+ """Gestor de MathJax local con descarga automática"""
+
+ MATHJAX_VERSION = "3.2.2"
+ MATHJAX_URL = f"https://github.com/mathjax/MathJax/archive/{MATHJAX_VERSION}.zip"
+ LOCAL_DIR = Path(".mathjax")
+
+ def __init__(self):
+ self.logger = logging.getLogger(__name__)
+ self.mathjax_dir = self.LOCAL_DIR / f"MathJax-{self.MATHJAX_VERSION}"
+ self.es5_dir = self.mathjax_dir / "es5"
+
+ def get_mathjax_url(self) -> str:
+ """
+ Obtiene la URL de MathJax (local si está disponible, CDN si no)
+ """
+ if self.is_local_available():
+ # Construir URL local relativa para file://
+ local_url = f"file:///{self.es5_dir.absolute().as_posix()}/tex-svg.js"
+ self.logger.debug(f"Usando MathJax local: {local_url}")
+ return local_url
+ else:
+ # Descargar automáticamente si no existe
+ if self.download_mathjax():
+ local_url = f"file:///{self.es5_dir.absolute().as_posix()}/tex-svg.js"
+ self.logger.info(f"MathJax descargado y configurado localmente: {local_url}")
+ return local_url
+ else:
+ # Fallback a CDN
+ cdn_url = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"
+ self.logger.warning(f"Fallback a CDN: {cdn_url}")
+ return cdn_url
+
+ def is_local_available(self) -> bool:
+ """Verifica si MathJax está disponible localmente"""
+ tex_svg_file = self.es5_dir / "tex-svg.js"
+ return tex_svg_file.exists() and tex_svg_file.is_file()
+
+ def download_mathjax(self) -> bool:
+ """
+ Descarga MathJax automáticamente si no está disponible
+
+ Returns:
+ True si la descarga fue exitosa, False si falló
+ """
+ try:
+ self.logger.info(f"Descargando MathJax {self.MATHJAX_VERSION}...")
+
+ # Crear directorio si no existe
+ self.LOCAL_DIR.mkdir(exist_ok=True)
+
+ # Archivo temporal para la descarga
+ zip_path = self.LOCAL_DIR / f"mathjax-{self.MATHJAX_VERSION}.zip"
+
+ # Descargar archivo ZIP
+ self.logger.debug(f"Descargando desde: {self.MATHJAX_URL}")
+ urlretrieve(self.MATHJAX_URL, zip_path)
+
+ # Extraer archivo
+ self.logger.debug(f"Extrayendo en: {self.LOCAL_DIR}")
+ with zipfile.ZipFile(zip_path, 'r') as zip_ref:
+ zip_ref.extractall(self.LOCAL_DIR)
+
+ # Limpiar archivo ZIP
+ zip_path.unlink()
+
+ # Verificar que se extrajo correctamente
+ if self.is_local_available():
+ self.logger.info(f"✅ MathJax {self.MATHJAX_VERSION} descargado correctamente")
+ return True
+ else:
+ self.logger.error("❌ Error: MathJax no se extrajo correctamente")
+ return False
+
+ except URLError as e:
+ self.logger.error(f"❌ Error de red descargando MathJax: {e}")
+ return False
+ except zipfile.BadZipFile as e:
+ self.logger.error(f"❌ Error: archivo ZIP corrupto: {e}")
+ # Limpiar archivo corrupto
+ if zip_path.exists():
+ zip_path.unlink()
+ return False
+ except Exception as e:
+ self.logger.error(f"❌ Error inesperado descargando MathJax: {e}")
+ return False
+
+ def clean_local_mathjax(self):
+ """
+ Limpia la instalación local de MathJax
+ (Para forzar redownload en la siguiente inicialización)
+ """
+ try:
+ if self.LOCAL_DIR.exists():
+ import shutil
+ shutil.rmtree(self.LOCAL_DIR)
+ self.logger.info("🗑️ MathJax local limpiado")
+ except Exception as e:
+ self.logger.error(f"Error limpiando MathJax local: {e}")
+
+ def get_status_info(self) -> dict:
+ """Obtiene información del estado de MathJax"""
+ return {
+ "local_available": self.is_local_available(),
+ "local_dir": str(self.LOCAL_DIR.absolute()),
+ "mathjax_dir": str(self.mathjax_dir.absolute()) if self.mathjax_dir.exists() else None,
+ "version": self.MATHJAX_VERSION,
+ "tex_svg_file": str(self.es5_dir / "tex-svg.js") if self.is_local_available() else None
+ }
\ No newline at end of file
diff --git a/debug_html/latex_panel_webview_base_20250612_133012.html b/debug_html/latex_panel_webview_base_20250612_133012.html
new file mode 100644
index 0000000..39a1009
--- /dev/null
+++ b/debug_html/latex_panel_webview_base_20250612_133012.html
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+
+
+
+
+ Panel de Ecuaciones LaTeX (SVG)
+
+
+
+
+
+
\ No newline at end of file
diff --git a/debug_html/latex_panel_webview_current_20250612_133012.html b/debug_html/latex_panel_webview_current_20250612_133012.html
new file mode 100644
index 0000000..140da7a
--- /dev/null
+++ b/debug_html/latex_panel_webview_current_20250612_133012.html
@@ -0,0 +1,388 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file