From 8c84eb41956beb0e0e6339299f763866595a44ff Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 12 Jun 2025 13:31:44 +0200 Subject: [PATCH] =?UTF-8?q?Actualizaci=C3=B3n=20del=20sistema=20de=20gesti?= =?UTF-8?q?=C3=B3n=20de=20ecuaciones=20en=20el=20panel=20LaTeX,=20implemen?= =?UTF-8?q?tando=20un=20nuevo=20manejador=20de=20MathJax=20para=20mejorar?= =?UTF-8?q?=20la=20carga=20de=20ecuaciones.=20Se=20a=C3=B1ade=20un=20men?= =?UTF-8?q?=C3=BA=20para=20seleccionar=20el=20tama=C3=B1o=20de=20fuente=20?= =?UTF-8?q?y=20se=20optimiza=20la=20visibilidad=20del=20panel=20LaTeX=20co?= =?UTF-8?q?n=20un=20nuevo=20dise=C3=B1o=20de=20splitter.=20Se=20mejora=20l?= =?UTF-8?q?a=20gesti=C3=B3n=20de=20la=20configuraci=C3=B3n=20de=20tama?= =?UTF-8?q?=C3=B1o=20de=20fuente=20y=20se=20implementa=20la=20funcionalida?= =?UTF-8?q?d=20para=20guardar=20el=20HTML=20del=20panel=20LaTeX=20para=20d?= =?UTF-8?q?iagn=C3=B3stico.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .data/history.txt | 9 +- .gitignore | 2 + app/gui_evaluation.py | 9 +- app/gui_latex.py | 320 +++++++++++---- app/gui_main.py | 69 +++- app/gui_menus.py | 134 ++++++ app/gui_settings.py | 4 +- app/gui_widgets.py | 4 + app/mathjax_manager.py | 120 ++++++ ...ex_panel_webview_base_20250612_133012.html | 218 ++++++++++ ...panel_webview_current_20250612_133012.html | 388 ++++++++++++++++++ 11 files changed, 1171 insertions(+), 106 deletions(-) create mode 100644 app/mathjax_manager.py create mode 100644 debug_html/latex_panel_webview_base_20250612_133012.html create mode 100644 debug_html/latex_panel_webview_current_20250612_133012.html 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 @@ + + + + + + + +
horastarifa
8000
36
horas=20009horas=222.222
+ + + + \ No newline at end of file