Resumen: Este documento presenta una guía detallada para convertir documentos LaTeX
en páginas web interactivas utilizando herramientas como Make4ht y asistencia con IA. Se
abordan temas como la configuración de Make4ht, la conversión de entornos complejos a
imágenes SVG, la inclusión de actividades interactivas con JavaScript, y la integración de
elementos multimedia como applets de GeoGebra y videos de YouTube. El enfoque bimodal
permite generar tanto PDF como HTML, aprovechando las ventajas de cada formato: el PDF para
impresión y citación formal, y el HTML para accesibilidad e interactividad en dispositivos
digitales.
Palabras Clave: Palabras clave: Make4ht, LaTeX, HTML, interactividad, JavaScript, SVG, GeoGebra, IA,
conversión de documentos, diseño web.
Abstract: This paper provides a detailed guide for converting LaTeX documents into interactive web pages
using tools like Make4ht and AI assistance. It covers configuration of Make4ht, conversion of complex
environments into SVG images, incorporation of interactive JavaScript activities, and integration of
multimedia elements such as GeoGebra applets and YouTube videos. The bimodal approach
facilitates generating both PDF and HTML outputs, harnessing the advantages of each format: PDFs
for print and formal citation, and HTML for enhanced accessibility and interactivity on digital
devices.
Keywords: Make4ht, LaTeX, HTML, interactivity, JavaScript, SVG, GeoGebra, AI, document conversion,
web design.
Un documento .tex se puede compilar de varias maneras. En nuestro caso queremos algo bimodal:
Queremos como salida un documento pdf y un documento html (para agregar contenido interactivo).
Para obtener un documento pdf, compilamos con PDFLaTeX y para traducir el documento y obtener un
sitio web, con su archivo de estilo css, compilamos con Make4ht. El archivo css se modifica y/o se
amplia con un archivo personalizado config.cfg. En la Figura 1 se muestra el proceso de manera
simplificada.
La plantilla doc.tex (que que usa este documento) está implementado con código que ejecutan tanto PdfLaTeX como Make4ht. Pero hay partes en que solo nos interesa una salida html y otras en las que solo nos interesa la salida pdf, para esto usamos comandos que PDFLaTeX ignora y que Make4ht sí compila y viceversa.
Make4ht se enfoca en la estructura del contenido y, si no hay errores de compilación fatales, entrega un
archivo html correcto pero con un diseño simple. Este artículo es un ejemplo (y al mismo tiempo es una
plantilla) de cómo agregar diseño web moderno y responsivo, de manera manual, a través
de un archivo de configuración y también a través de un framework como Bootstrap, [1].
Este documento considera las tareas comunes en la implementación de material didáctico
en matemáticas y agrega un archivo de configuración para la salida moderna y correcta en
Html. La manera de configurar Make4ht para lograr este objetivo se describe en la sección
7.
¿Qué nivel necesitamos? Para usar la plantilla, se requiere ser un usuario normal de LaTeX y
posiblemente conocer cosas básicas de html y css (sino, podríamos empezar con [14] y [13]). La parte
interactiva requiere conocer JavaScript, en principio, en un nivel básico.
La IA puede generar código Latex, código de estilo (css) y scripts interactivos, con peticiones en
lenguaje natural. Pero en el estado actual de la IA, para tareas más complejas, hay un aumento
significativo en la productividad si hacemos peticiones con modelos de código y en lenguaje técnico
preciso. También debemos estar atentos a las repuestas de la IA, porque ocasionalmente nos
da resuestas basadas en información desactualizada (cosas raras, comandos que no existen,
etc.).
Si quiere conocer cómo se configuró la plantilla y eventualmente modificarla, entonces se debe leer la
sección 7. También conviene leer [2].
¿Por qué traducir un documento pdf a html? El formato html ofrece accesibilidad, interactividad y un
mayor alcance en el entorno digital actual. Generar el html desde un archivo Latex permite aplicar revisiones
y/o modificaciones al archivo .tex sin necesidad de tener que volver a editar manualmente la salida
html.
Mientras el formato pdf es ideal para impresión y citación formal, el html se adapta a cualquier dispositivo y permite integrar elementos dinámicos como visualizaciones, actividades interactivas y contenido multimedia. Este enfoque promueve la ciencia abierta y la educación digital al hacer el contenido más flexible y accesible.
Bien, tenemos una plantilla doc.zip con figuras y varios archivos .tex y un archivo de configración config.cdf
(entre otras cosas) que Make4ht traduce bien a html.
Podemos agregar paquetes y comandos personales, en el archivo ComandosdelUsuario.tex que está en la
carpeta "Paquetes". Pero hay que observar que hay paquetes incompatibles con Make4ht y posiblemente
también comandos. Siempre hay que estar compilando para ir probando como funcionann las
cosas.
Make4ht es altamente configurable, por lo que el diseño del sitio web final lo podemos automatizar a
través de un archivo de configuración que contiene código css, para aplicar ajustes específicos para el
formato de salida html.
Sentido común. Hay que pensar en "modo pdf" si visualizamos el pdf de salida, y en "modo html" si
visualizamos la página web de salida. Son mundos parecidos, pero hay cosas en pdf que no tiene equivalente en
html y viceversa. Así que hay que estar valorando qué cosas tienen sentido en uno y en el otro ambiente.
La buena noticia es que tenemos dos comandos para saltar de uno a otro modo en este documento doc.tex:
Las cosas sofisticadas en Latex , buenas para pdf pero que podrían no compilar bien con Make4ht, las
podemos simplicar y hacer una versión Latex más sencilla (pero equivalente) o inyectar código html de
manera directa.
Cosas demasiado complicadas se puede recortar e incluir como una imagen svg. Este formato esta bien
soportado por el html y permite renderizar texto, figuras y componente de scripts interactivos en alta calidad y
permite escalar sin pérdidas.
La estructura de la carpeta de trabajo se muestra en la Figura 2.
Algunas figuras generadas con código Latex las podemos convertir, de manera automática, con el paquete ltximg [8]. Lo vemos en la sección 3.
Make4ht ofrece varias opciones de compilación a través de un archivo de configuración y/o
con opciones entre comillas. En este documento mayormente compilamos en la terminal, con el
comando
make4ht -u -c config.cfg -u -f html5 -d SitioWeb doc.tex "mathml,svg,Gin-dim" % opción limpiar: agregar -m clean (y quitar después) % opción debug: agregar -a debug
En esta
plantilla, el archivo config.cfg puede cargar el script MathJax más personalizado, si se ocupan paquetes y comandos
adicionales. Ver sección 7.
Otras opciones. Se pueden agregar opciones de compilación (máximo 9) en el formato
make4ht filename.tex "op1,op2,..,optn"
En el capítulo de [2, Tex4ht (2024)] hay una lista de opciones que se pueden aplicar. Incluye: Partir el documento en varias páginas, agregar las "notas de pie de página" en una página final, usar imágenes para el texto, etc.
Make4ht compila el archivo .tex con htlatex. Esta compilación Usa "motores" como PDFtex o Luatex, pero
soporta solo paquetes básicos, en realidad, una cantidad suficiente de paquetes básicos. Así que la
primera fuente de errores de compilación están en el código .tex. Una vez superada esta etapa, podrían
haber errores en la traducción a html. Hay que evitar que el html se "rompa" (evitar que el DOM se rompa)
digamos por etiquetas que abren, pero no cierran como en <div><p>Contenido</div>
. También el DOM se
puede romper por paquetes incompatibles con Make4ht o entornos matemáticos complejos mal
interpretados.
En la compilación con Make4ht, una "advertencia" del tipo
[WARNING] domfilter: DOM parsing of test.html failed: [WARNING] domfilter: /home/.../ ... nbalanced Tag (/p) [char= ]
significa que la estructura del documento (DOM) se ha roto y la "advertencia" nos dice que una o varias cosas ya no van a salir bien. Lo normal es corregir el problema directamente o hacer modificaciones. Como en cualquier compilación normal, revisamos el .log para tratar de aislar el problema y corregirlo.
Como estamos en un ambiente bimodal, algunas cosas se pueden usar tanto para PDFLatex como para
Make4ht, pero hay otras cosas son exclusivas para PDFLaTex y hay algún equivalente para Make4ht y
viceversa.
Observe
que tanto PDFLatex como Make4ht, compilan todo el archivo .tex, solo que algunos bloques de código son exclusivos,
por razones especiales, para PDFLatex y otros para Make4ht.
En esta plantilla tenemos tres comandos personalizados (están en WebPreambuloyEntornos.tex):
\pdfomk{#1}{#2} : | PDFLatex ignora #2 y ejecuta #1 y Make4ht ignora #2 y ejecuta #1 | |
\insertarhtm{#1} : | Insertar código html puro con Make4ht , pero PDFLatex lo ignora | |
\pdfomk{#1}{} : | Solo PDFLatex ejecuta #1 | |
\pdfomk{}{#2} : | Solo Make4ht ejecuta #2 |
Comandos adicionales para generar código html desde Latex se muestran en la sección 5.
Adicionalmente vamos a usar programas externos que se ejectan en la terminal o consola (editores como Texstudio, TexMaker, Kile, etc. tienen la "consola" en la parte baja)
ltximg : | Extrae entornos LaTeX y los convierte en imágenes svg. | |
%<*ltximg> %</ltximg> | Identificar entornos que va a ser convertidos en imágenes svg | |
rsvg-convert | (Linux) Escalar imágenes svg (también tareas de conversión) | |
Inkscape | Varias tareas sobre imágenes (Windows, Linux, Mac) |
Ejemplo: Incluir una figura pdf con PDFLatex e incluir la misma figura en formato .¨svg en html
\pdfomk{% PDFLatex-> pdf \bc \includegraphics[scale=0.35]{images/sumaRiemann.pdf} \captionof{figure}{Figura \tt{.pdf}} \ec }{% Mkae4ht -> html \bc \includegraphics{images/sumaRiemann.svg} \captionof{figure}{Figura \tt{.svg}} \ec }
En html, los formatos mejor soportados son .png, .jpg y .svg.
\includegraphics[width=0.7\textwidth]{images/fig2.png}
Para escalar una figura png (o jpg) se puede usar la opción, [width=0.x\textwidth]
. Esta
opción, en términos de \textwidth
, es adecuada para pdf y html.
Estas figuras se inyectan en el html con algo como
<img alt=’PIC’ class=’includegraphics’ src=’images/fig2.png’ width=’310’ />
.
Es decir, también podemos insertar figras png desde latex . Por ejemplo,
\insertarhtml{% Make4ht -> html <img alt=’PIC’ class=’includegraphics’ src=’images/fig3.png’ width=’150’ />}
Se puede incluir incluir una figura svg con Make4ht, usando el código
\pdfomk{ % }{% Make4ht -> html \includegraphics{images/fig1.svg} }PDFLatex puede incluir figuras svg con el paquete svg, pero solo funciona para PDFLaTeX. Make4ht inyecta la figura .svg en el html con algo como
<object class=’graphics’ data=’images/fig1.svg’ type=’image/svg+xml’></object>
<object>...,/object>
es un elemento html que incrusta contenido externo (svg, pdf, html,
etc.) como un "documento embebido".[width=0.x\textwidth]
.Por ejemplo si queremos escalar fig1.svg a un ancho 150pt, ejecutamos la instrucción
cd images % sudo apt install librsvg2-bin rsvg-convert -f svg -w 150 fig1.svg -o sfig1.svgsfig1.svg es la figura escalada. Como el html toma las figuras de la carpeta images, podemos seguir ajustando al figura y recargando el html.
pdf. Los navegadores no renderizan los figuras pdf como imágenes (excepto con el elemento <object>). A
veces Make4ht puede convertir estas figuras automáticamente (en la compilación) a png o svg, mediante
herramientas externas (como ghostscript o pdf2svg). Esto depende de si en el sistema están instaladas estas
herramientas.
La práctica usual de colocar un minipage al lado de otro minpage está configurado en el archivo config.cfg
(porque necesitamos manejar de manera correcta las dimensiones de cada minipage).
Introducimos ambientes minipage en hmtl con el siguiente formato:
\linea \begin{minipage}{1.0\textwidth} \begin{minipage}{0.x\textwidth} % Contenido 1... \end{minipage}\hfill\begin{minipage}{0.y\textwidth} % Contenido 2... \end{minipage} \end{minipage} \linea
Un ejemplo. Introducimos texto a la izquierda y una figura a la derecha, con
\captionof{figure}
. Agregamos un par de líneas horizontales con \linea
(definida en el
preámbulo, correcta para PDFLatex y Make4ht).
\linea \begin{minipage}{1.0\textwidth} \begin{minipage}{0.6\textwidth} \vspace{-2\baselineskip} El espacio Euclidiano es $\R^2$, con la métrica \[ ds^2=dx^2+dy^2 \] En este modelo, la distancia más corta entre dos puntos es una línea recta \end{minipage}\hfill\begin{minipage}{0.35\textwidth} \bc \includegraphics{images/fig3.png}\captionof{figure}{Camino más corto} \ec \end{minipage} \end{minipage} \linea
El espacio Euclidiano es , con la métrica
En este modelo, la distancia más corta entre dos puntos es una línea recta
Make4ht traduce bien, en general, los ambientes tikzpicture. Con cosas muy complicadas todavía tenemos la
opción de recoratr la figura, como se indica en la subsección 3.
\begin{center} \begin{tikzpicture} \matrix (m) [matrix of math nodes, row sep=3.5em, column sep=3.5em, nodes={anchor=center}] {A & A[1] \\ A’ & A’[1] \\}; \path[-stealth] (m-1-1) edge node [above] {$x$} (m-1-2) (m-2-1) edge node [above] {$y$} (m-2-2) (m-1-1) edge node [right] {$z$} (m-2-1) (m-1-2) edge node [right] {$t$} (m-2-2); \end{tikzpicture} \end{center}
\begin{tikzpicture}[scale=0.7, x=(-15:1.2), y=(90:1.0), z=(-150:1.0), line cap=round, line join=round, axis/.style={black, thick,->}, vector/.style={>=stealth,->}] ... % El código lo puede ver en el archivo "ejemplos.tex" \end{tikzpicture}
Make4ht traduce estos entornos sin problema. Entornos demasiado complejos, posiblemente sea mejor,
insertarlos en el html como una imagen svg, como se indica en la subsección 3., o generar el equivalente html
con IA, si se pudiera.
El código completo de algunos ejemplos, se puede ver en el archivo ejemplos.tex
\begin{equation} \norm{f - L}_{\infty} = \overbrace{\abs{\frac{K_2}{2}}}^{\mathclap{\text{worst $f’’(x)$ }}}\underbrace{\left(\frac{h}{2}\right)^2}_{\mathclap{\text{worst (b - a)}}} \end{equation}
(1) |
\begin{equation}\label{eq:cases} S_{i,t}= \begin{cases} \begin{cases} [x_{i,t}=X^*, r_{i,t}=1] & \text{if $\max\{X_{i,t}\}=X^*$} \\ [x_{i,t}=\max\{X_{i,t}\}, r_{i,t}=0] & \text{if $\max\{X_{i,t}\} \neq X^*$} \end{cases} &\text{if $\sum_{i=1}^I u_{i,t-1}= \theta^{t-2} X^*$}\\ \begin{cases} [x_{i,t}=1, r_{i,t}=1] & \hspace{\maxmin} \text{if $\min\{X_{i,t}\}=1$} \\ [x_{i,t}=\min\{X_{i,t}\}, r_{i,t}=0] & \hspace{\maxmin} \text{if $\min\{X_{i,t}\} \neq 1$} \end{cases} &\text{otherwise} \end{cases} \end{equation}
(2) |
En la ecuación
\ref{eq:cases}
, o el formato \eqref{eq:cases}
, se tiene que ...
Usamos este paquete para colocar dos figuras, una al lado de la otra, con diferentes caption. El archivo de
configuración tiene el código para manejar esta situación en la traducción a html. En la Figura 1
usamos un código bimodal, porque usamos figuras .pdf para el pdf y el formato .svg para el
html.
\pdfomk{% subfiguras para pdflatex..., con formato .pdf % }{% subfiguras para que compile make4ht, en formato .svg \begin{figure}[h] \centering \begin{minipage}{1.0\textwidth} \centering \begin{subfigure}{0.4\textwidth} \centering \includegraphics{images/fig0a.svg} \caption{PDFLaTeX} \label{fig:fig0a} \end{subfigure}% ~ \begin{subfigure}{0.4\textwidth} \centering \includegraphics{images/fig0b.svg} \caption{Make4ht} \label{fig:fig0b} \end{subfigure}% % caption general \centering\caption{Compilar con PDFLaTeX o con Make4ht} \label{fig:fig0} \end{minipage} \end{figure} }
Make4ht traduce correctamente a html, tanto tablas simples como otras más elaboradas, que utilizan
paquetes como multirow, color o booktabs. Sin embargo, cuando se trata de estructuras más complejas
como
celdas combinadas de forma irregular, múltiples líneas horizontales o disposiciones no
estándar es
necesario recurrir a soluciones alternativas, como las que se ilustran en la sección 3. Además, una vez
generado el archivo html, es posible agregar interactividad directamente desde este mismo documento .tex.
(sección 5.)
A continuación mostramos algunos ejemplos de tablas que Make4ht traduce bien a html.
\multicolumn
(no usar \arrayrulecolor
)\begin{table}[h!!!] % Make4ht -> html. No lo soporta \arrayrulecolor{black} {\centering \begin{tabular}{ | l | c | c | c | c | c | c |}\hline\hline Tipo de Instrucción & opcode & & & & & \\\hline \multicolumn{1}{|r|}{\#bits} & 6 & 5 & 5 & 5 & 5 & 6\\\hline\hline Tipo-R & op & rs & rt & rd & shamt & funct\\\hline Tipo-I & op & rs & rt & \multicolumn{3}{c|}{dirección/inmediato}\\\hline Tipo-J & op & \multicolumn{5}{l|}{dirección objetivo} \\\hline \end{tabular} \caption{\label{tab:4.1}Tipos de instrucciones de código máquina MIPS} } \end{table}
Tipo de Instrucción | opcode | |||||
#bits | 6 | 5 | 5 | 5 | 5 | 6 |
Tipo-R | op | rs | rt | rd | shamt | funct |
Tipo-I | op | rs | rt | dirección/inmediato
| ||
Tipo-J | op | dirección objetivo
| ||||
\multirow
y \rowcolor
\begin{table}[h!!!] \centering \begin{tabular}{|l|l|l|l|} \hline \rowcolor{gray!30} \textbf{Categoría} & \textbf{Item} & \textbf{Cantidad} & \textbf{Precio} \\ \hline \multirow{2}{*}{Frutas} & Manzanas & 10 & \$5.00 \\ \cline{2-4} & Naranjas & 20 & \$8.00 \\ \hline \multirow{2}{*}{Vegetales} & Zanahorias & 15 & \$4.00 \\ \cline{2-4} & Papas& 25 & \$6.00 \\ \hline \end{tabular} \captionof{table}{Tabla sofisticada}\label{tab:4.2} \end{table}
Categoría | Item | Cantidad | Precio |
Frutas | Manzanas | 10 | $5.00 |
Naranjas | 20 | $8.00 | |
Vegetales | Zanahorias | 15 | $4.00 |
Papas | 25 | $6.00 | |
\setlength{\arrayrulewidth}{0.5pt} \arrayrulecolor{headerblue!80} \begin{tabular}{cc||ccc||ccc||ccc||ccc} \toprule \rowcolor{headerblue!90} ... \end{tabular}
Negación | Conjunción | Disyunción | Implicación | Equivalencia
| |||||||||
El documento doc.tex usa el paquete exsheets para listas de ejercicos. Definimos dos comandos en el
preámbulo
\hejersol{}{}
. Este comando lo ignora PDFLatex y Make4ht lo convierte en un enunciado con
un botón Ver/Ocultar, para ver la respuesta en el renglón que sigue.
\ejersol{}{}
.
Este comando funciona para PDFLatex y Make4ht. PDFLatex lo convierte en un ejercicio normal
y, para ver las soluciones, usualmente se pone al final del documento
\pdfomk{ \section*{Respuestas} \printsolutions }{}
Si compila Make4ht, \ejersol{}{}
se convierte en \hejersol{}{}
.
La idea es que a veces, un mismo ejercicio tiene un enunciado en el pdf, digamos con una figura fija por ejemplo, mientras que el enunciado en html no necesita la figura porque viene con un script.
Ejemplo: Lista de Ejercicos.
% Ejercicio 1: \ejersol{Resuelve para $x$: $2x + 5 = 13$}{$x = 4$}\\ % Ejercicio 2: \ejersol{Calcula el área de un cuadrado de lado 3 cm}{$9\ \text{cm}^2$}\\ % Ejercicio 3: \ejersol{Deriva $f(x) = 3x^2 + 2x - 1$}{$f’(x) = 6x + 2$}\\ % Ejercicio 4: \ejersol{Simplifica $\sin^2 \theta + \cos^2 \theta$}{$1$}\\ % Ejercicio 5: Solo PDFLatex \pdfomk{\ejersol{Calcula la velocidad final si $v_0=10\,m/s$, $a=2\,m/s^2$ y $t=3\,s$}{$16\,m/s$} }{}\\ % Ejercicio 6: Solo Make4ht \pdfomk{}{ \ejersol{Encuentra la energía cinética de un objeto de 5 kg moviéndose a 4 m/s}{$40\,J$} }\\ % Ejercicio 7: Solo Make4ht \hejersol{Halla la corriente si $V=12\,V$ y $R=4\,\Omega$}{$3\,A$}\\ % Al final: \pdfomk{ \section*{Respuestas} \printsolutions }{}
Ejercicio 2..1 Resuelve para :
Ejercicio 2..2 Calcula el área de un cuadrado de lado 3 cm
Ejercicio 2..3 Deriva
Ejercicio 2..4 Simplifica
Ejercicio 2..5 Encuentra la energía cinética de un objeto de 5 kg moviéndose a 4 m/s
Ejercicio 2..6 Halla la corriente si y
Para generar una tabla de contenidos en el pdf solo agregamos \tableofcontents
. Make4ht compila
\tableofcontents
y genera una tabla de contenidos adecuada para html.
Lo que queremos ahora es un botón minimalista que abre y cierra una ventanda con el contenido en
doc.html. Se requiere un script +toc-toggle.js+ y un archivo toc-toggle.css para hacer eso. Estso archivos ya
están incluidos en la plantilla. Para habilitarlos debemos agregar algunas cosas:
% Make4ht -> html % En el preámbulo se debe agregar la ruta del .css % \ifdefined\HCode\Configure{HEAD}{ % \HCode{<link rel="stylesheet" href="css/toc-toggle.css" />} % \HCode{<script src="js/toc-toggle.js"></script>} % } %\fi % \begin{document} % ... \pdfomk{%PDFLatex->pdf \tableofcontents }{ \ifdefined\HCode \ifvmode\IgnorePar\fi\EndP\par \HCode{<link rel="stylesheet" href="css/toc-togogle.css">} \HCode{<script src="js/toc-toogle.js"></script>} \HCode{<button class="toc-btn">Tabla de Contenidos</button>} \HCode{<div id="toc-container">} \ifvmode\IgnorePar\fi\EndP\par \fi \tableofcontents \ifdefined\HCode \ifvmode\IgnorePar\fi\EndP\par \HCode{</div>} \ifvmode\IgnorePar\fi\EndP\par \fi }
Make4ht no ofrece soporte para muchos paquetes que se usan para implementar tablas o arreglos complejos,
como las que se implementan con hhline, nicematrix, polynom etc. Podemos convertir estos entornos en
imágnes svg o también, si se presta, se podrían convertir en html interactivo (sección 5.)
\insertarhtml{}
. A veces el resultado es bueno.%<*ltximg> %</ltximg>
y los convierte en imágenes
.svg
El entorno %<*ltximg> %</ltximg>
es ingnorado por PDFLatex y por Make4ht. . Pero ltximg si lo
interpreta como un identificador.
%<*ltximg> Entorno... %</ltximg>Preparamos un archivo conv.tex con los entornos y los paquetes y comandos que necesitan
% conv.tex \documentclass{article} \usepackage[utf8]{inputenc} % Preámbulos para cada entorno \usepackage{polynom} \usepackage{nicematrix,tikz} \usetikzlibrary{fit} \newcommand{\ff}{\mathtt{f}} \begin{document} % conv-fig-1.svg %<*ltximg> %<- polynom NO requiere entorno matemático \polylongdiv[style=D]{6x^3-2x^2+x+3}{x^2-x+1} %</ltximg> % conv-fig-2.svg %<*ltximg> \begin{NiceTabular}[hvlines]{ccc} \CodeBefore [create-cell-nodes] \tikz \node [draw,fill=blue!15,rounded corners,fit = (2-1) (2-3)] {} ; \Body a & b & c \\ d & e & f \end{NiceTabular} %</ltximg> ... \end{document}Una vez que tenemos idenficados los entornos que vamos a convertir a imagen svg, tenemos que correr en terminal el comando que recorta y hace las conversiones.
% Ignoramos entornos tikzpicture, podría habilitarlos si se necesita ltximg --skipenv ’tikzpicture’ --runs 2 --subenv --svg --imgdir images -o conv-out conv.texFunciona así: Este comando recorre el documento conv.tex y localiza los entornos que están envueltos en el entorno
%<*ltximg> %</ltximg>
, luego genera y pega en la carpeta images, un archivo
conv.tex con solamente los entornos y el preámbulo del documento, luego genera la imagen .pdf de
cada entorno y las convierte a .svg.
Los nombres de las imágenes van numeradas por orden de aparición:
conv-fig-1.svg, conv-fig-2.svg, etc.
Para escalar las figuras svg usamos rsvg-convert o inkscape (o programas equivalentes), como se indicó
en la sección 2.3.
Vamos a recortar entornos con los paquetes nicematrix, polynomial y hhline. Recuerde que estos paquetes no
son soportados por Make4ht, pero sí por PDFLatex.
El orden de aparición es importante, porque eso define el nombre de la imagen .svg
\pdfomk{% PDFLatex -> pdf \bc \polylongdiv[style=D]{6x^3-2x^2+x+3}{x^2-x+1} % Genera conv-fig-1.svg \captionof{figure}{División con el paquete \tt{polynom}} \ec }{ % Make4ht -> html recoge la imagen generada por "ltximg" \bc \includegraphics[width=0.5\textwidth]{images/doc-fig-1.svg} \captionof{figure}{División con el paquete \tt{polynom}} \ec }
\pdfomk{% PDFLatex -> pdf %conv-fig-2.svg %\newcommand{\ff}{\mathtt{f}} \begin{equation*} \boldsymbol{\mathcal{F}}^{i} = \begin{bNiceMatrix}[margin,nullify-dots] ... \end{bNiceMatrix} \end{equation*} }{ % Make4ht -> html \includegraphics[width=0.5\textwidth]{images/conv-fig-2.svg} }
Para generar las imágenes svg ejecutamos en terminal
ltximg --skipenv ’tikzpicture’ --runs 2 --subenv --svg --imgdir images -o conv-out conv.tex
La plantilla tiene varios entornos ya configurados para que compilen bien con Make4ht.
Agregar nuevos entornos posiblemente requiera agregar nuevo código al archivo de configuración
config.cfg (ver sección 7.). Lo recomendable es usar los modelos que ya están en este archivo. Si usa IA, lo
mejor es indicarle primero que quiere el código siguiendo esos modelos.
Cosas de diseño de cada entorno, como bordes, color, color de fondo, etc. se puede modificar en
WebPreambuloyEntornos.tex.
Para modificar el diseño de cada entorno, para la salida html, requiere modificar el \Css{...}
del
entorno en el archivo config.cfg. Por ejemplo, para el entorno definción se tiene
\Css{% No dejar renglones en blanco .definicion { background-color: rgb(251, 251, 250); %/* gris magenta */ border-left: 4pt solid rgb(255, 20, 147); %/* magenta */ margin: 20pt 0; padding: 0pt 4pt 0 4pt; %/* padding-bottom reducido a 0 */ overflow: auto; %/* Contiene floats */ clear: both; %/* Evita solapamientos */ } %/* Título de la definición */ .definicion-title { color: rgb(255, 20, 147); font-weight: bold; margin-bottom: 0.5em; display: block; }
A continuación tenemos una lista de entornos con ejemplos.
\label{def:defi1} \begin{definicion}[nombre-opcional] Contenido... \end{definicion}Una definción con nombre.
Sea un conjunto de puntos. La envoltura convexa de , denotada por , es el conjunto convexo más pequeño que contiene a . Formalmente:
Es decir, está formado por todas las combinaciones convexas finitas de puntos de .
\ref
: En la Definición 1...Sean , , . El punto está dentro del triángulo pues:
Como , y , entonces se concluye que .
\label{teo:teo1} \begin{teorema}[nombre-opcional] Contenido... \end{teorema}Teorema con nombre.
\label{teo:teo2} \begin{teorema}[La recta es el camino más corto] ... \begin{caja}[Demostración.] ... \end{caja} \end{teorema}
En el plano euclidiano con la métrica usual, el camino más corto entre dos puntos y es el segmento de recta que los une.
Aplicamos la desigualdad de Cauchy–Schwarz:
con igualdad si y solo si es constante y paralelo al vector , es decir, si es una recta.
Por lo tanto, la longitud mínima se alcanza exactamente cuando es el segmento de recta entre y .
\label{ej:ejemplo1} \begin{ejemplo}[nombre-opcional] % Enunciado \end{ejemplo}Ejemplo: Vamos a usar un entorno minipage
\pdfomk{ % PDFLatex -> pdf \label{ej:ejemplo1} \begin{ejemplo}[Punto dentro del triángulo] \begin{minipage}{0.7\textwidth} Sean \( A = (1,1) \), \( B = (2,4) \), \( C = (4,0) \). ... \end{minipage}\hfill\begin{minipage}{0.2\textwidth} ... \includegraphics[scale=0.7]{images/fig2.pdf} \end{minipage} \end{ejemplo} }{ % Make4ht -> html \label{ej:ejemplo1} \begin{ejemplo}[Punto dentro del triángulo] \begin{minipage}{0.7\textwidth} Sean \( A = (1,1) \), \( B = (2,4) \), \( C = (4,0) \). ... \end{minipage}\hfill\begin{minipage}{0.2\textwidth} ... \includegraphics[scale=0.7]{images/fig2.svg} \end{minipage} \end{ejemplo} \end{ejemplo} }Ejemplo con solución
En esta plantilla se han definido más entornos. El disenño se puede modoficar tanto en el archivo WebPreambuloyEntornos.tex como en el archivo de configuración config.cfg. La lista de entornos es
\ObjetivoGeneral{...}
\ObjetivosEspecificos{...}
\resumen{...}
\palabrasclave{...}
\abstract{...}
\keywords{...}
\label{...}\begin{definicion}...\end{definicion}
\label{...}\begin{teorema}...\end{teorema}
\label{...}\begin{ejemplo}...\end{ejemplo}
\label{...}\begin{corolario}...\end{corolario}
\label{...}\begin{proposicion}...\end{proposicion}
\label{...}\begin{lema}...\end{lema}
\label{...}\begin{caja}...\end{caja}
\label{...}\begin{axioma}...\end{axioma}
\label{...}\begin{actividad}...\end{actividad}
\label{...}\begin{notahistorica}...\end{notahistorica}
\label{...}\begin{problema}...\end{problema}
\label{...}\begin{ejercicio}...\end{ejercicio}
\label{...}\begin{proyecto}...\end{proyecto}
\label{...}\begin{aplicacion}...\end{aplicacion}
Ahora que ya tenemos una manera fiable de traducir Latex a html para introducir contenido matemático,
pasamos a introducir interactividad. En esta parte, usamos \insertarhtml{}
para incrustar el bloque html
para nuestras actividades interactivas (en el caso de que no queramos que estén en páginas
independientes).
Las actividades interactivas en JavaScript requieren separación modular. Cada actividad puede tener su
propia lógica, estilo y comportamiento: Sus componentes de estilo css y el código js los separamos de las
otras actividades. Esto hace que el código se pueda mantener mejor, evita conflictos de estilo
entre módulos distintos y se puede reutilizar fácilmente un módulo en otra parte o en otro
proyecto.
Usualmente los scripts se comunican con el el sitio web porque el sitio web les provee de campos de texto,
botones, lienzos (canvas) para graficar, escribir, etc.
Cada actividad interactiva con JavaScript tiene una introducción teórica y/o práctica e instrucciones. Luego viene el bloque de código html de la página que se comunica con el script: Este código toma el estilo de una archivo .css en la carpeta css y el escript .js "vive" en la carpeta js , como se muestra en al Figura 13.
El código .js y el estilo .css lo implementamos nosotros mismos o, por supuesto, pedimos asistencia de la IA. Podríamos solicitar traducir un program ya implementado en otro lenguaje, a un equivalente .js o modificar un programa existente o, indicar todos los detalles del programa que queremos en lenguaje natural.
Para proyectos complejos necesitamos sin duda una especificación con modelos de código y lenguaje
técnico para pedir asistencia a la IA.
Si le pedimos a la IA (Copilot, chatGPT, DeepSeek, etc.) una aplicacion interactiva (no muy compleja),
entonces en general, seguimos estos pasos:
Primero pedimos un diseño básico de lo que queremos, con los detalles pertinentes.
Hay que tomar en cuenta que en JavaScript hay bibliotecas para graficar en 2D, 3D, derivar
en una o varias variables, simplificar expresiones algebraicas, etc.
Las bibliotecas 3D usuales son three.js y babylon.js, pero posiblemente queramos
quedarnos en algo práctico y sencillo como plotly.js, algo fácil de manejar con lenguaje
natural.
Si no tenemos el resultado esperado, a veces es necesario en los ajustes, especificar
fórmulas, algoritmos u otros detalles técnico.
<body> ...<\body>
es lo que insertamos. Adicionalmente hay que insertar en
el preámbulo de nuestro archivo .tex las líneas que deben ir en el <head> </head>
del
html.
Con más detalle:
Los <script>...
y/o <link>...
que tenemos que poner en <head>...<\head>
.
Para mantener el html de la actividad interactiva sin cambios, cuando modificamos el
contenido .tex, lo mejor es inyectar estos scripts del encabezado head al inicio del doc.tex.
Por ejemplo, podría ser algo como
\documentclass[fleqn,oneside]{article} \input{Paquetes/WebPreambuloyEntornos.tex} \input{Paquetes/ComandosdelUsuario.tex} %-- Actividades interactivas \ifdefined\HCode % Solo lo compila Make4ht -> html \Configure{HEAD} { \HCode{<link rel="stylesheet" href="css/tabla-hover-filas.css">} \HCode{<link rel="stylesheet" href="css/riemann.css">} %... } \fi
El bloque de código html de la actividad interactiva.
Introducimos este bloque en nuestro .tex para que Make4ht lo inyecte en el html de la página web
principal
Sería algo como,
% Make4ht -> html \insertarhtml{ <div id="nombre-actividad"> ... </div> ... <script src="js/nombre-del-script.js"></script> }
Si este bloque de código, por alguna razón lleva texto matemático, se debe incluir en código mathml
Ejemplo: Un script sencillo en lenguaje natural. Supongamos que queremos implementar un script para visualizar la intersección de dos intervalos. En general, lo mejor es tener una idea gráfica, algo como se muestra en la Figura 14
Luego debemos pensar en una petición. La IA "sabe" cómo calcular la intersección de dos intervalos, aún así siempre hay que revisar casos especiales y la lógica general, previniendo errores. Por ejemplo, la petición en lenguaje naural podría ser:
"Crea un script que muestre dos intervalos arrastrables (azul/verde) sobre una línea numérica, con discos rellenos/vacíos según sean cerrados/abiertos. Que calcule y muestre su intersección con un segmento (magenta) un poco más arribe, con líneas punteadas hacia abajo. Incluye doble click para cambiar apertura/cierre y redondeo cercano a enteros. Importante: El css debe estar encapsulado, oo debe haber ninguna variable ni estilo que afecte afuera de ese contenedor."
También está la opción de ser mucho más específicos:
Interfaz gráfica:
Discos en extremos:
Interacción:
Detalles visuales:
Encapsulamiento: Dame un widget encapsulado bajo .intintervalos-widget, con css y js encapsulados. No
debe haber ninguna variable ni estilo que afecte afuera de ese contenedor.
En este caso tuvimos éxito: El resultado, después de varios ajustes (peticiones adicionales) es como se muestra ya activo en la subsección 6.1
Luego, lo recomendable es revisar casos especiales y la lógica en el código del script.
En este caso la IA nos entregó los archivos .css, .js y .html, además de una petición espcial: que alistara
el código \insertarhtml{...}
para nuestro doc.tex.
En esta sección aparecen varios ejemplos, expuestos de manera suscinta, con aplicaciones interactivas. En
todos estas aplicaciones se usó IA (mayormente DeepSeek, también Copilot y chatGPT), para asistir en la
implementación de los scripts interactivos que aparecen más adelante.
Este documento es acerca de cosas de implementación, por eso no se expone
la parte complicada de diseñar la actividad interactiva.
Recordemos que
( intersección
) es el conjunto de elementos
comunes al conjunto
y al conjunto .
Dado que los intervalos representan conjuntos, es posible hallar sus intersecciones y uniones. Las
representaciones gráficas son útiles en este proceso.
¿Cómo hallar intersecciones y uniones de dos intervalos?
Actividad interactiva. En el siguiente script,
% Make4ht -> html % En el preámbulo se debe agregar la ruta del .css % \ifdefined\HCode\Configure{HEAD}{ % \HCode{<link rel="stylesheet" href="css/interseccionintervalos.css">} % %... % } %\fi % En la carpeta "css" agregar interseccionintervalos.css % En la carpeta "js" agregar interseccionintervalos.js \insertarhtml{ <div class="int-intervalos-container"> <div class="int-intervalos-contenedor"> <h2 style="color: \#d45500;">Intersección de Intervalos</h2> <div class="int-intervalos-resultado"> <input type="text" id="int-intervalos-input1" readonly /> <span class="intervalos-op"></span> <input type="text" id="int-intervalos-input2" readonly /> <span class="intervalos-op">=</span> <input type="text" id="int-intervalos-resultado" readonly /> </div> <canvas id="int-intervalos-canvas" width="600" height="250"></canvas> </div> </div> <script src="js/interseccionintervalos.js"></script> }
Script de ejercicios sobre intersección de intervalos.
En el script que sigue, el botón "Generar Intervalos", genera dos intervalos con extremos aleatorios. Su trabajo consiste en cálcular la intersección, si hubiera, y realizar la representación gráfica. Al final, puede ver la respuesta presionando el botón Respuesta.
Implementación: Esta basada en una petición detallada a la IA, especificando lo que contiene la primera fila y la zona gráfica.
% En el preámbulo agregar: %\ifdefined\HCode\Configure{HEAD}{%... % \HCode{<link rel="stylesheet" href="css/ejerinterseccionintervalos.css">} %} %\fi % En la carpeta "css" agregar ejerinterseccionintervalos.css % En la carpeta "js" agregar ejerinterseccionintervalos.js \insertarhtml{% Make4ht -> html <div class="interseccion-caja" style="margin: 0 auto; max-width: 600px;"> <div class="titulo" style="margin-bottom: 20px; color: \#d45500;">Script interactivo: Generar dos intervalos y ver su intersección.</div> <div class="controls"> <button id="btnGenerarIntersect" style="margin-right: 15px;">Generar Intervalos</button> <input type="text" id="int1Intersect" readonly style="width: 72px; margin-right: 10px; font-size: 16px; padding: 8px; text-align: center;"> <span style="margin-right: 10px;">\( \cap \)</span> <input type="text" id="int2Intersect" readonly style="width: 72px; margin-right: 15px; font-size: 16px; padding: 8px; text-align: center;"> <button id="btnCalcularIntersect">Respuesta</button> </div> <div id="resultadoInterseccionIntersect" style="text-align:center; margin-bottom:5px; font-size:18px;"></div> <canvas id="canvasIntersect" width="565" height="200"></canvas> </div> <script src="js/ejerinterseccionintervalos.js"></script> }
Una interpretación de la derivada de una función de una variable es que mide la tasa (instántanea) de cambio de la variable dependiente respecto a la variable independiente. La derivada de la función en es,
siempre y cuando este límite exista. Geométricamente, la derivada de en es la pendiente de la recta tangente a en el punto Y es el límite de las pendientes de las "cuerdas" que pasan por y cuando .
Ecuación de la recta tangente en un punto. Si
es derivable en
entonces la ecuación
de la recta tangente a
en es
.
Interpretación geómetrica de la derivada En el siguientes script puede arrastrar el punto rojo para cambiar
el punto de tangencia y el punto azul, para empezar el proceso de límite
% En el preámbulo agregar: %\ifdefined\HCode\Configure{HEAD}{ % \HCode{<link rel="stylesheet" href="css/intgeomderivada.css">} % \HCode{<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.8.0/math.js"></script>} %}\fi % En la carpeta css agregar intgeomderivada.css % En la carpeta "js" agregar intgeomderivada.js \insertarhtml{ % Make4ht -> html <div class="contenedor"> <svg id="grafico" width="600" height="400"></svg> <div class="tabla-valores"> <table> <thead><tr><th>x</th><th>x+h</th><th>(f(x+h) - f(x)) / h</th></tr></thead> <tbody id="tablaDatos"></tbody> </table> </div> </div> <script src="js/intgeomderivada.js"></script> }
x | x+h | (f(x+h) - f(x)) / h |
---|
Implementación: Esta es un traducción de un archivo .nb (Wofram Mathematica) a JavaScript, con DeepSeek. El archivo está disponible: Capx-DerivadaDefi.nb. La traducción requiere algunos ajustes que se pueden hacer a través de peticiones a DeepSeek o manualmente, directamente en el código.
El área del trapecio isósceles inscrito en la parte superior de una circunferencia de ecuación se puede escribir en funciónn de la base menor, de longitud :
Si , tendríamos un
triángulo de área . Pero
nos interesa el valor de
para que el trapecio tenga área máxima.
En el siguiente script podemos, con el deslizador, hacer que tome los valores permitidos, es decir, . En la tabal podemos ver como varía el área y en el gráfico de la derecha vemos que hay un valor de en que el área es máxima. Y queremos calculor el valor exacto de en el que el área del trapecio es máxima.
% En el preámbulo agregar: %\ifdefined\HCode\Configure{HEAD}{ % ... % \HCode{<script src="https://d3js.org/d3.v7.min.js"></script>} % \HCode{<link rel="stylesheet" href="css/optimizaciontrapecio.css">} %} %\fi % En la carpeta css agregar optimizaciontrapecio.css % En la carpeta "js" agregar optimizaciontrapecio.js \insertarhtml{% No dejar renglones en blanco <script src="js/optimizaciontrapecio.js" defer></script> <div class="trapecio-widget"> ... </div> </div> }
Ahora usamos el script para un ejercicio, con un botón Ver/Ocultar la respuesta. Recordemos, de la subsección ??, que
\hejersol{}{}
es solo para html y que \ejersol{}{}
lo compilan tanto PADFLatex
como Mak4ht (lo convierte en \hejersol{}{}
). Pero en este caso, el enunciado de los ejercicios no es igual en
ambos contextos, por eso los separamos.
\hejersol{ % Solo Make4ht -> html: Pregunta con botón ver/ocultar Hallar las dimensiones del trapecio isósceles de mayor área que puede inscribirse en un semicírculo de radio $4$. ... }{% respuesta La base mayor 8 unid, la menor 4 unid y la altura $2\sqrt{3}$ unid. }%-- \pdfomk{% PDFLatex -> pdf \ejersol{ Hallar las dimensiones del trapecio isósceles de mayor área que puede inscribirse en un semicírculo de radio $4$. \bc \includegraphics[width=0.45\linewidth]{images/fig8-appderivadas.pdf} \captionof{figure}{Trapecio isósceles inscrito}\label{trapecioisosceles} \ec }{ La base mayor 8 unid, la menor 4 unid y la altura $2\sqrt{3}$ unid. }%--ejersol }{} % \printsolutions % PDFLatex, soluciones final del documento.
Ejercicio 6..1 Hallar las dimensiones del trapecio isósceles de mayor área que puede inscribirse en un semicírculo de radio .
Implementación: Esta es un traducción de un archivo .nb (Wofram Mathematica) a JavaScript, con DeepSeek. El archivo está disponible: Capx-EjemplOptimizacion.nb. La traducción requiere algunos ajustes que se pueden hacer a través de peticiones a DeepSeek.
Históricamente, la integral de Riemann se define como un "límite" sobre todas las posibles particiones de
un intervalo, pero en realidad solo necesitamos definir la integral sobre particiones regulares [3].
Como consecuencia, si
es integrable, calculamos la integral con una escogencia de los
fijos,
sobre una familia de particiones regulares.
es integrable en porque es continua en este intervalo. Por tanto, según el Teorema 3
pues, tomando ,
% Make4ht -> html % En el preámbulo se debe agregar la ruta del riemann.css % \ifdefined\HCode\Configure{HEAD}{ % ... % \HCode{<link rel="stylesheet" href="css/riemann.css">} % } %\fi % En la carpeta css agregar riemann.css % En la carpeta "js" agregar riemann.js \insertarhtml{ <div class="riemann-widget"> <h1>Integral de Riemann</h1> ... </div> % <script src="js/riemann.js"></script> }
Implementación: Se hizo una petición detallada a DeepSeek. Se especificó que la evalución de la función se debía hacer con math.js (sino la IA trata de hacer un "parser" demasiado simple) y que no usara "charts" para los rectángulos. Finalmente, cuando el html funcionaba correctamente, se pidió a la IA que encapsulara y luego separara riemann.css, también riemann.js y el .html para extraer lo que debemos inyectar en el
<header>...<header>
y para extraer lo qu está en <body>...</body>
, e inyectarlo con
\insertarhtml{}
Es decir,
o, en términos de la derivada direccional,
En el siguiente script tenemos la superficie . Arrastrando el punto en la columna a la derecha podemos mover el punto en la superficie y el plano tangente. Vamos a observar...
% Make4ht -> html % En el preámbulo se debe agregar la ruta del planotangente.css y plotly % \ifdefined\HCode\Configure{HEAD}{%... % \HCode{<script src="https://cdn.plot.ly/plotly-2.32.0.min.js"></script>} % \HCode{<link rel="stylesheet" href="css/planotangente.css">}} % } %\fi % En la carpeta css agregar planotangente.css % En la carpeta "js" agregar planotangente.js \insertarhtml{ <div class="planotangente-widget"> <div id="plot3d"></div> <div id="plot2d-container"> <div id="controls"> <label><input type="checkbox" id="toggleTangents" checked> Mostrar rectas tangentes</label> </div> <div id="coords">Coordenadas: (1.05, 0.68, 0.00)</div> <div id="plot2d-wrapper"> <canvas id="plot2d"></canvas> </div></div></div> <script src="js/planotangente.js" defer></script> }
Implementación: Se hizo una petición detallada a DeepSeek (Copilot también fue muy eficiente y en menor mediada ChatGPT), en este caso hubo que hacer ajustes manuales en el .js para habilitar y deshabilitar cosas y corregir dimensiones. La IA "conoce" las ecuaciones del plano tangente y las ecuaciones de las rectas tangentes solicitadas. Pero debemos especificar que la gráfica de la superficie se implemente con plotly.js y que sea una "constante" (usar three.js o babylon.js requiere demasiados ajustes) y, como plotly.js no ofrece muchos eventos de ratón, solicitamos que el punto se actualice con las coordenadas que provee el punto de arrastre en la segunda columna, que debe ser en JavaScript normal. Es decir, las dos columnas se comunican. Solicitamos encapsulado con .planotangente-widget. Siempre hay que asegurarse que no use variables globales en el css, como name {...}, sino .planotangente-widget #name {...}. Finalmente pedimos el html, el .css y el .js separados. Observe que este script viene con un menú en la parte superior, para trasladar, imprimir, etc.
Queremos aplicar un efecto hover para resaltar o iluminar filas, columnas o elementos de una tabla, cuando el
ratón pasa por encima.
Estos efectos se aplican a la etiqueta <table class="...</table>
, pero Make4ht no siempre convierte un
entorno tabular en un entorno <table>...
(esto pasa cuando tabular está en entornos, center, table, minipage,
etc.). Además diseños especiales de tablas requieren un manejo especial.
En este caso, usamos el diseño de la Tabla 4. El estilo definido ya esta en la carpeta css
y se llama tabla-hover-filas.css. Además ya incluimos el código en el preámbulo de este
documento para cargar este estilo. Luego, usamos un entorno tablahoverfilas ya definido en el
preámbulo, y envolvemos las tablas con este entorno para envolver el tabular con la etiqueta
<div class=’tabla-hover-filas’>
. PDFLatex ignora este entorno, es solo para Make4ht.
\begin{tablahoverfilas} % Make4ht inyecta el efecto :hover en el html \begin{table}[h!!!] ... \begin{tabular}{cc||ccc||ccc||ccc||ccc} ... \end{tabular} \caption{Tabla modelo}\label{tabla-modelo} \end{table} \end{tablahoverfilas}
Negación | Conjunción | Disyunción | Implicación | Equivalencia
| |||||||||
Para cada tabla particular, si deseamos mantener su diseño, pedimos a la IA que traduzca el código
Latex a algo equivalente en html y que nos dé el archivo de estilo encapsulado .css de esta tabla. A este
estilo pedimos que le agregue el efecto :hover deseado.
Seleccionamos y copiamos el bloque de código de la tabla completo, para pegarlo en la petición que
vamos a hacer. \begin{table}\caption...\end{table}
y luego hacemos la solicitud a la IA de esta
manera:
Voy a proporcionar el código Latex de una tablay necesito lo siguiente:
\documentclass[fleqn,oneside]{article} \input{Paquetes/WebPreambuloyEntornos.tex} \input{Paquetes/ComandosdelUsuario.tex} % Make4ht-- -> html \ifdefined\HCode\Configure{HEAD}{ \HCode{<link rel="stylesheet" href="css/tabla-hover-filas.css">} \HCode{<link rel="stylesheet" href="css/tablahover1.css">} %... } \fi % \begin{document}
% html de la tabla (NO dejar filas en blanco!) \insertarhtml{% Make4ht -> html <div class="tablahover1"> % Agregamos manualmente id= para referencia <table id="tablahover1"> ... }Make4ht no incluye la referencia de la tabla, porque no la compiló en el archivo .tex, entonces hacemos referencia a esta tabla con
\insertarhtml{<a href="\#tabla-modelo">Ver Tabla modelo</a>}
GeoGebra [5] es un software interactivo para enseñar y aprender matemáticas mediante construcciones
visuales. Aunque su implemetación y/o uso requiere práctica, permite integrar recursos ya creados en
páginas web.
Incrustar un applet. Para incrustar applets de Geogebra en nuestra página html, seguimos las
instrucciones que se detallan en [6]. En la página de Recursos podría ser que haya algo que nos interese,
en ese caso abrimos el applet, y a la derecha del nombre del autor hacemos click en los tres puntos y, en el
menú que se abre, hacemos click en "Detalles"; en la ventana que se abre, hacemos click en "Compartir" y
damos click en "<\>
Incrustar". Copiamos el <iframe....></iframe>
con todo su contenido y eso es lo que
vamos incrustar.
Para incrustar el código html del <iframe...
, usamos un script toggleVentana.js (que ya está en la
carpeta js y que ya se carga con este este archivo doc.tex). Produce un botón que abre u oculta la ventana en la
que se despliega el applet de Geogebra. Pero debemos numerar bien la ventana en el data-tarjet="ventanak" y
en el identificador id="ventanak"
<button class="toggle-ventana-btn" data-target="ventanak"> Ver/Ocultar nombre </button> <div id="ventanak" class="ventana-container" style="display: none;">
Cambiamos ventanak por "ventana1", "ventana2", etc. porque cada applet ocupa un contenedor diferente.
Distribución Normal.
\insertarhtml{% ventana1 <button class="toggle-ventana-btn" data-target="ventana1">Ver/Ocultar Distribución Normal</button> <div id="ventana1" class="ventana-container" style="display: none;"> <div style="width:100\%; position:relative; padding-bottom:44.58\%;"> <iframe scrolling="no" title="Distribución Normal" src="https://www.geogebra.org/material/iframe/id/rZ7NHCsS/width/1366/height/609/border/888888/sfsb/true/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/false/rc/false/ld/false/sdz/false/ctl/false" width="900px" height="402px" style="border:0px;"></iframe> </div> </div> }
Las dimensiones que nos dan son de
width="1366px" height="609px"
. Pero para nuestro sitio parece
mejor (manteniendo las proporciones) width="900px" height="402px"
Tabla de Frecuencias. Este es otro ejemplo que tomamos de la página de Recursos
\insertarhtml{ % Numerar ventana!. Vamos por la "ventana2" <button class="toggle-ventana-btn" data-target="ventana2">Ver/Ocultar Tabla Frecuencias</button> <div id="ventana2" class="ventana-container" style="display: none;"> <iframe scrolling="no" title="Tabla de frecuencias" src="https://www.geogebra.org/material/iframe/id/sxG0ihm3/width/900/height/400/border/888888/sfsb/true/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/false/rc/true/ld/false/sdz/false/ctl/false" width="900px" height="400px" style="border:0px;"> </iframe> </div> }
De manera similar a como incrustamos applets de Geogebra, usamos un script toggleVentana.js y
actualizamos la numeración de la ventana.
En el video de YouTube que nos interesa, hacemos click en "Compartir" y hacemos click en "Incrustar" y
tomamos el código <iframe ...>...</iframe>
y lo insertamos en nuestro html.
El determinante | Esencia del álgebra lineal, capítulo 5.
% Numerar ventana!. Vamos por la "ventana3" \insertarhtml{ <button class="toggle-ventana-btn" data-target="ventana3">Ver/Ocultar Tabla Frecuencias</button> <div id="ventana3" class="ventana-container" style="display: none;"> <iframe width="560" height="315" src="https://www.youtube.com/embed/yt3eoYvGel0?si=sq7SgYaOXnHpZU5j" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div> }
Tex4ht (implementado por Eitan Gurari (1947–2009)) es un conjunto de scripts que, después de la
compilación con htlatex, "traduce" el archivo dvi. Este archivo dvi contiene toda la información sobre la
disposición del texto, gráficos y fórmulas matemáticas en un formato compacto. Esta información se
usa para generar documentos pdf, html, etc.
Make4ht es un sistema de compilación (implementado por Michal Hoftich) para Tex4ht. Make4ht es una
herramienta diseñada principalmente para convertir documentos LaTeX en HTML (y otros formatos),
enfocándose en la estructura del contenido (texto, tablas, imágenes, fórmulas matemáticas, etc.), pero no
se encarga del diseño web avanzado. Esto significa que, por defecto, Make4ht no genera estilos css complejos ni
diseños responsivos modernos.
Pero Make4ht permite controlar y configurar el diseño web. Usualmente lo que hacemos es que con un
archivo de configuración config.cfg controlamos la salida html de los entornos y otros componentes del
código Latex.
Esta sección es una aplicación de los elementos de configuración que se pueden leer en [2] y en
respuestas a preguntas relacionadas con Make4ht en TeX Stack Exchange. Creamos una plantilla doc.tex
configurada apropiadamente para que compile bien con Make4ht (parece que no tiene mucho sentido
compilar con Make4ht un documento .tex sin implementar la configuración adecuada, excepto que sea un
documento muy sencillo).
La IA puede ser útil para que nos ayude generando código tedioso y recomendaciones, pero en el
estado actual, no parece estar muy entrenada en Make4ht, por lo que la manera práctica de usar la IA, es
dándole modelos de código para que genere código Latex apropiado (sin supuestos raros, ni comandos
inexistentes).
Hay muchos comandos de configuración, pero vamos a describir y ver ejemplos de aplicación de algunos
comandos frecuentes en la configuración de nuestro documento doc.tex
\Configure{name}{arg 1}...{arg n}
Configura el comportamiento específico de un
elemento en el formato de salida.
Este comando declara el código que se inserta en los hooks ("ganchos") relacionados con la configuración del "name". Es posible definir hasta nueve hooks, por lo que el número de argumentos es variable.
\ConfigureEnv{<environmentname>}{before env}{after env}
. Personaliza cómo
se "renderiza" un entorno específico, definiendo elementos antes y después del entorno y la
lista. Este comando puede ser usado para insertar código pertinente en cualquier entorno.
\HCode{output format markup}
se usa para insertar, en este caso html "puro"
Este comando sólo permite la "expansión de macros", antes de enviar su contenido a la
salida. En él se puede introducir la instrucción \Hnewline
para solicitar saltos de línea, y el
comando \#
para el símbolo #.
\Css{...}
se usa para introducir estilo css desde el archivo de configuración.\ifdefined\HCode % Make4ht -> html \usepackage[spanish,english]{babel} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \else % PDFLatex -> pdf \usepackage[english, spanish, es-noquoting]{babel} \usepackage[autostyle, spanish = mexican]{csquotes} \MakeOuterQuote{"} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} % LaTeX clásico
:hover en tablas. El entorno tablahoverfilas
definido en el preámbulo, hace que
Make4ht genere el contenedor <div class="tabla-hover-filas">
. A este contenedor
se le aplica el comportameinto :hover: Iluminar filas cuando el cursor pasa. Esto se
implementó en la configuración css
\newenvironment{tablahoverfilas} {% \ifdefined\HCode \ifvmode\IgnorePar\fi\EndP \HCode{<div class="tabla-hover-filas">}% \par \fi } {% \ifdefined\HCode \ifvmode\IgnorePar\fi\EndP \HCode{</div>}% \par \fi } % \rowcolor{rowgray} tapa el hover, \rowgris para css y da \rowcolor{rowgray} para pdf \ifdefined\HCode \newcommand{\rowgris}{\HCode{<tr class="rowgray">}} \else \newcommand{\rowgris}{\rowcolor{rowgray}} \fi
Make4ht ignora \vspace \bigskip, \medskip, \smallskip
, así que lo configuramos para que
Make4ht lo interprete con elementos equivalentes en html. Las líneas horizontales no quedan
bien en html, por eso definimos el equivalente.
\newcommand{\linea}{\textcolor{lightgray}{\rule{\linewidth}{0.4pt}}\par} \ifdefined\HCode \def\bigskip{\HCode{<div style="margin-top:2em;"></div>}} \def\medskip{\HCode{<div style="margin-top:1.5em;"></div>}} \def\smallskip{\HCode{<div style="margin-top:1em;"></div>}} \def\linea{\HCode{<hr style="height:1px; border:none; background-color:\#ccc; margin:20px 0;">}} \fi % \ifdefined\HCode \newcommand{\vspacehtml}[1]{\HCode{<div style="margin-top:#1;"></div>}} \else \newcommand{\vspacehtml}[1]{\vspace*{#1}} \fi %% \vspacehtml{1em}
Comandos \pdfomk{#1}{#2}
para seperar código Latex exclusivo para pdf y código Latex
exclusivo para html. \insertarhtml{}
inserta html "puro", se usapara incrustar Javascript, iframe,
object etc.
%\pdfomk{#1}{#2} \ifdefined\HCode \long\def\pdfomk#1#2{% \protect#2%html } \else \long\def\pdfomk#1#2{% \protect#1%pdf } \fi % Insertarhtml{#1} %--\insertarhtml{#1} % Make4ht-> html \ifdefined\HCode \long\def\insertarhtml#1{% \HCode{#1}% } \else \long\def\insertarhtml#1{% PDFLaTeX->pdf % nada o si quiere %\textbf{[Contenido interactivo no disponible en PDF]} } \fi
Un entorno para un ejercicio con botón para ver/ocultar respuesta.
\ifdefined\HCode \newcommand{\hejersol}[2]{% \par\medskip \textbf{Ejercicio:} #1% \HCode{% <div class="ejercicio-solucion"> <div class="solucion-container"> <button>Mostrar/Ocultar solución</button> <div class="solucion"> <script src="js/ejerciciosolucion.js"></script> }% #2% \HCode{</div></div></div>}% \par\medskip } \else \newcommand{\hejersol}[2]{% Definir aquí el comportamiento pdf \par\medskip \textbf{Ejercicio:} #1% \par\smallskip \textcolor{lightgray}{ \textit{Solución:} #2}% \par\medskip } \fi
\begin{document}
\documentclass[fleqn,oneside]{article} \input{Paquetes/WebPreambuloyEntornos.tex} \input{Paquetes/ComandosdelUsuario.tex} %% Make4ht -> html: Inserta en <head>...</head> \ifdefined\HCode\Configure{HEAD}{ \HCode{<link rel="stylesheet" href="css/tabla-hover-filas.css">} \HCode{<link rel="stylesheet" href="css/riemann.css">} \HCode{<link rel="stylesheet" href="css/ejerinterseccionintervalos.css">} \HCode{<link rel="stylesheet" href="css/interseccionintervalos.css">} \HCode{<link href="css/intervalos.css" rel="stylesheet" type="text/css">} \HCode{<link rel="stylesheet" href="css/intgeomderivada.css">} \HCode{<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.8.0/math.js"></script>} \HCode{<link rel="stylesheet" href="css/ejerciciosolucion.css">} \HCode{<script src="https://d3js.org/d3.v7.min.js"></script>} \HCode{<link rel="stylesheet" href="css/optimizaciontrapecio.css">} \HCode{<script src="https://cdn.plot.ly/plotly-2.32.0.min.js"></script>} \HCode{<link rel="stylesheet" href="css/planotangente.css">} \HCode{<script src="js/toggleVentana.js" defer></script>} %\HCode{<link rel="preconnect" href="https://fonts.googleapis.com">} } \fi ... \begin{document}
El archivo de configuración tiene la forma
\Preamble{xhtml} %...Configure, ConfigureEnv, etc. \begin{document} %...insertar en header (posiblemente no cosas de uso ocasional) \EndPreamble
En este documento doc.tex configuramos el comportamiento de todos los entornos. El documento doc.tex usa el paquete mdframed (tcolorbox inserta las "label" internamente y complica las cosas). Make4ht traduce los entornos mdframe de manera simplificada, con solo cosas básicas. Pero el archivo de estilo doc.css gobierna todo, entonces tenemos que anular "ese poder" y modificarlo.
Siempre que configuramos algo, hay que evitar que el html se "rompa" (evitar que el DOM se rompa)
digamos por etiquetas que abren, pero no cierran como en <div><p>Contenido</div>
. También el DOM se
puede romper por paquetes incompatibles con Make4ht o entornos matemáticos complejos mal
interpretados.
En la compilación con Make4ht, una "advertencia" del tipo
[WARNING] domfilter: DOM parsing of test.html failed: [WARNING] domfilter: /home/.../ ... nbalanced Tag (/p) [char= ]
significa que la estructura del documento (DOM) se ha roto y la "advertencia" nos dice que una o varias cosas ya no van a salir bien. Lo normal es corregir el problema directamente o hacer modificaciones. El código que sigue es muy preciso, para no romper el DOM.
% Elimina la configuración automática de mdframed que inserta Make4ht \Configure{mdframed}{\IgnorePar\EndP}{\IgnorePar\EndP}{}{} % Eliminamos los márgenes que vienen por defecto \Css{.mdframed { margin-top: 0pt !important; padding-top: 0pt !important; }} % Preparar para la configuración personalizada usando \ConfigureEnv con \Css \ConfigureEnv{mdframed}{\ifvmode\IgnorePar\fi\EndP\HCode{<div class="mdframed">}\par} {\ifvmode\IgnorePar\fi\EndP\HCode{</div>}\par}{}{}En esta configuración de mdframed, se agregan etiquetas
<div>...</div>
alrededor del
contenido del cuerpo del documento. Los comandos \ifvmode\IgnorePar\fi
evitarán la
inserción de la etiqueta <p>
antes de <div>
si estamos en el modo vertical de TeX. \EndP
cierra el párrafo abierto, si está abierto. Los comandos \par\ShowPar
inician un nuevo
párrafo después de la etiqueta <div>
insertada. A veces es necesario iniciar los párrafos
explícitamente.\begin{definition}...\end{definition}
Podemos agregar diseño con css sin que el css original intervenga. La idea es que se parezca al
diseño del entorno en el doc.tex. Para empezar bebemos definir bordes, colores, etc. Más adelante
debemos definir otras cosas, como veremos. Recordar que estamos compilando con el motor Latex, por
lo tanto tenemos que "escapar" caracteres especiales o comentar.
\ConfigureEnv{definicion} {\ifvmode\IgnorePar\fi\EndP\HCode{<div class="definicion">}\par} {\ifvmode\IgnorePar\fi\EndP\HCode{</div>}\par} {}{} \Css{ %/* --- Estilo base para "definicion", bordes, etc. --- */ .definicion { background-color: rgb(251, 251, 250); %/* gris magenta */ border-left: 4pt solid rgb(255, 20, 147); %/* magenta */ % top right bottom left; margin: 20pt 0; padding: 0pt 4pt 0 4pt; %/* padding-bottom reducido a 0 */ overflow: auto; %/* Contiene floats */ clear: both; %/* Evita solapamientos */ } %/* Título de la definición */ .definicion-title { color: rgb(255, 20, 147); font-weight: bold; margin-bottom: 0.5em; display: block; }Este entorno se convierte en una "plantilla" para todos los otros entornos
%%--configura minipage y figuras---- \makeatletter % we must refer to minipage from the css file, because tags are beeing % written before we know dimensions \newcount\mini@count \ExplSyntaxOn % save original minipage \let\oldiimini\@iiiminipage % redefine minipage \def\@iiiminipage#1#2[#3]#4{% % calculate minipage dimensions and save it to the CSS file \Css{\#minipage\the\mini@count{width:\fp_eval:n{#4/\textwidth*100}\%;}}% \global\advance\mini@count by 1\relax% \oldiimini{#1}{#2}[#3]{#4}% } \ExplSyntaxOff \ConfigureEnv{minipage}{\ifvmode\IgnorePar\fi\EndP\HCode{<div class="minipage" align="center" id="minipage\the\mini@count"> }} {\ifvmode\IgnorePar\fi\EndP\HCode{</div>\Hnewline}% % we must write dimension here to the css file }{}{} \makeatother \Css{div.minipage { float: left; } } \Css{div.minipage:last-child { clear: none; float: right; }} \Css{ div.minipage + :not(.minipage) {clear:both;overflow:auto;width:100\%;}}Ahora esto va antes que nuestro entorno definción, por orden, y configuramos este entorno (y todos los otros) para que reciban minipage con dimensiones correctas
\Css{ %continuación de la configuración de definición. %/* --- Compatibilidad con minipages dinámicas --- */ %/* Contenedor padre de minipages (simula 1.0\textwidth) */ .definicion > .minipage { width: 100\% !important; %/* Ancho completo */ border: none !important; %/* Opcional: elimina borde si no lo quieres en el contenedor padre */ margin-bottom: 0.5em; padding-bottom: 0; } %/* Minipages internas (usan width dinámico via tu código \makeatletter) */ .definicion .minipage .minipage { float: left; %/* Tus reglas originales */ margin-right: 2\%; %/* Espacio entre columnas (ajustable) */ box-sizing: border-box; } %/* Última minipage (flotada a la derecha) */ .definicion .minipage .minipage:last-child { float: right !important; margin-right: 0 !important; } %/* Limpiar floats después de minipages anidadas */ .definicion .minipage::after { content: ""; display: table; clear: both; } %/* Ajuste para párrafos y contenido interno */ .definicion .minipage p { margin-top: 0.3em; margin-bottom: 0.3em; } %/* Captions centrados */ .definicion .caption { text-align: center; margin-top: 0.5em; } }
% Incrustar en el <head> del html \Configure{@HEAD}{ \HCode{<script> MathJax = { tex: { inlineMath: [[’\\(’, ’\\)’]], displayMath: [[’\\[’, ’\\]’]], packages: {’[+]’: [’textmacros’]}, // Permitir comandos de texto processEscapes: true }, options: { skipHtmlTags: [’script’, ’noscript’, ’style’, ’textarea’, ’pre’] } } }\HCode{</script>} \HCode{<script src="https://polyfill.io/v3/polyfill.min.js?features=es6">}\HCode{</script>} \HCode{<script id="MathJax-script" async="" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">}\HCode{</script>} }
En el archivo config.cfg aparecen más configuraciones figure, subfigure, etc. Pero ya después de estos ejemplos, el código es fácil de leer e interpretar.
Este artículo muestra cómo combinar LaTeX con herramientas modernas para crear contenido educativo y
científico interactivo, ampliando su alcance y utilidad en entornos digitales. La integración de IA facilita la
generación de código y la resolución de problemas técnicos, mientras que la modularidad y
configuración detallada aseguran resultados profesionales. Este enfoque no solo optimiza el flujo
de trabajo, sino que también promueve la ciencia abierta y la educación digital al hacer el
contenido más accesible y dinámico. La plantilla proporcionada sirve como punto de partida para
adaptaciones futuras, destacando la importancia de la flexibilidad y la innovación en la comunicación
académica.
[1] BootstrapMade. (2023). BootstrapMade: Free and premium Bootstrap templates. BootstrapMade. https://bootstrapmade.com/
[2] Hoftich, M. (2024). TeX4ht Documentation by TeX4ht Project. https://www.kodymirus.cz/tex4ht-doc/tex4ht-doc.html
[3] Denlinger, C. G. (2010). Elements of real analysis. Jones & Bartlett Publishers.
[4] Duckett, J. (2011). HTML and CSS: Design and Build Websites. Wiley.
[5] GeoGebra. (s. f.). GeoGebra: Plataforma interactiva de matemáticas. https://www.geogebra.org/
[6] GeoGebra Team. (n.d.). Incorporación de GeoGebra a páginas web. GeoGebra. https://www.geogebra.org/m/bs3cmu4a
[7] Inkscape Project. (2025). Inkscape: Professional vector graphics editor. https://inkscape.org/
[8] González, P. (2021). ltximg: LaTeX environments to image and standalone files (Version 2.1).
https://ftp.mpi-inf.mpg.de/pub/tex/mirror/ftp.dante.de/pub/tex/support/ltximg/ltximg-doc.pdf
[9] LuaTeX Developers. (s.f.). LuaTeX Reference Manual. http://www.luatex.org/documentation.html
[10] Hošovecký, M. (2023). make4ht: TeX4ht extension for build process automation. Comprehensive TeX Archive Network (CTAN). https://ctan.org/pkg/make4ht?lang=en
[11] The MathJax Consortium. (2023). MathJax documentation. MathJax. https://docs.mathjax.org/en/latest/
[12] Mittelbach, F., Goossens, M., Braams, J., Carlisle, D., & Rowley, C. (2004). The LaTeX Companion (2nd ed.). Addison-Wesley.
[13] W3Schools. (s.f.). CSS Tutorial. https://www.w3schools.com/css/
[14] W3Schools. (s.f.). HTML Tutorial. https://www.w3schools.com/html/