Skip to content

2. Los ejemplos de este documento

Me gustaría escribir un artículo breve. Las interacciones entre una IA y un usuario se presentan en el artículo [Generar un script de Python con herramientas de IA], al que a partir de ahora me referiré como [ref1]. Las interacciones con Gemini y ChatGPT solo se presentarán de forma marginal. De todos modos, era imposible presentar todas las iteraciones.

Ahora voy a presentar ejemplos de las particularidades de mis documentos ODT / DOCX que el conversor Gemini / ChatGPT gestiona correctamente. Es este mismo documento el que propondremos para la conversión a HTML mediante el script de Gemini / ChatGPT. Veremos qué hace con él.

2.1. Las listas

El conversor Gemini / ChatGPT sabe gestionar las listas con viñetas y las listas numeradas, incluso si están anidadas:

2.1.1. Listas con viñetas s

  • Elemento 1;
  • Elemento 2:
  • Elemento 3;
    • Elemento 3.1;
      • Elemento 3.1.1
      • Elemento 3.1.2
        • Elemento 3.1.2.1
        • Elemento 3.1.2.2
    • Elemento 3.2;
  • Elemento 4;

2.1.2. Listas numeradas

  1. Elemento 1;
  1. Elemento 2;
    1. Elemento 2.1
      1. Elemento 2.1.1
        1. Elemento 2.1.1.1
        2. Elemento 2.1.1.2
      2. Elemento 2.1.2
    2. Elemento 2.2
  2. Elemento 3;

2.1.3. Listas mixtas 1

  • Elemento 1;
  • Elemento 2:
  • Elemento 3;
    • Elemento 3.1;
      1. Elemento 3.1.1
      2. Elemento 3.1.2
        • Elemento 3.1.2.1
        • Elemento 3.1.2.2
    • Elemento 3.2;
  • Elemento 4;

2.1.4. Listas mixtas 2

  1. Elemento 1;
  2. Elemento 2;
    1. Elemento 2.1
      1. Elemento 2.1.1
        • Elemento 2.1.1.1
        • Elemento 2.1.1.2
      2. Elemento 2.1.2
    2. Elemento 2.2
  3. Elemento 3;

2.1.5. Listas numeradas manualmente

Por numeración manual se entiende aquí que es el usuario quien establece el número de un párrafo numerado: [clic con el botón derecho del ratón sobre el párrafo numerado / párrafo / párrafo / reiniciar la numeración / comenzar con].

Empiezo una lista con un número distinto de 1.

  1. Elemento 6
  2. Elemento 7

Aquí interrumpo la lista para decir algo, pero luego quiero continuar con la numeración.

  1. Elemento 8
  2. elemento 9

A continuación, empiezo una nueva lista numerada:

  1. elemento 11
  2. elemento 12

2.2. Los bloques de código

Mis cursos contienen muchos bloques de código. A menudo se trata de códigos formateados (negrita, colores en las palabras clave) por los IDE (Eclipse, PyCharm, WebStorm, Netbeans). El conversor reproduce estos códigos formateados tal cual.

Cuando el código no está formateado (código procedente del Bloc de notas o Notepad o…), el conversor Gemini / ChatGPT lo reconoce (Java, C#, XML, HTML, …) mediante palabras clave del lenguaje incluidas en un archivo de configuración. Cuando reconoce un lenguaje, inserta un marcador (fence) para MkDocs, de modo que este adapte el resaltado sintáctico del código al lenguaje utilizado en el bloque de código.

2.2.1. Bloques de código enriquecido (Eclipse, Visual Studio, etc.)

A continuación se muestran bloques de código enriquecidos por diferentes IDE:

Java


package istia.st.spring.core;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

clase pública Demo01 {

    @SuppressWarnings({ "unchecked", "resource" })
    public static void main(String[] args) {
        // recuperación del contexto Spring
        ApplicationContext ctx = new ClassPathXmlApplicationContext("config-01.xml");
        // recuperamos los beans
        Persona p01 = ctx.getBean("persona_01", Persona.class);
        Persona p02 = ctx.getBean("persona_02", Persona.class);
        List<Persona> club = ctx.getBean("club", new ArrayList<Persona>().getClass());
        Piso piso01 = ctx.getBean(Piso.class);
...

C#


using System;

namespace Chap1 {
    class Impuestos {
        static void Main(string[] args) {
            // matrices de datos necesarias para el cálculo del impuesto
            decimal[] límites = { 4962M, 8382M, 14753M, 23888M, 38868M, 47932M, 0M };
            decimal[] coeffR = { 0M, 0.068M, 0.191M, 0.283M, 0.374M, 0.426M, 0.481M };
            decimal[] coeffN = { 0M, 291,09M, 1322,92M, 2668,39M, 4846,98M, 6883,66M, 9505,54M };

            // recuperamos el estado civil
            bool OK = false;
            string respuesta = null;
            while (!OK) {
                Console.Write("¿Está casado/a (S/N)? ");
                respuesta = Console.ReadLine().Trim().ToLower();
                if (respuesta != "s" && respuesta != "n")
                    Console.Error.WriteLine("Respuesta incorrecta. Vuelva a intentarlo");
                else OK = true;
            }//while
            bool marie = respuesta == "o";
...

Python


# ----------------------------------
def mostrar(cadena):
    # muestra cadena
    print("cadena=%s" % cadena)


# ----------------------------------
def mostrar_tipo(variable):
    # muestra el tipo de variable
    print("tipo[%s]=%s" % (variable, tipo(variable)))


# ----------------------------------
def f1(param):
    # suma 10 a param
    return param + 10


# ----------------------------------
def f2():
    # devuelve una tupla de 3 valores
    return "uno", 0, 100


# -------------------------------- programa principal ------------------------------------
...

PHP


<?php

// tipos estrictos para los parámetros de las funciones
declare(strict_types=1);

// constantes globales
define("LÍMITE_QF_MEDIA_PARTE", 1551);
define("LÍMITE_INGRESOS_SOLTERO_PARA_REDUCCIÓN", 21037);
define("LÍMITE_INGRESOS_PAREJA_PARA_REDUCCIÓN", 42074);
define("VALOR_REDUCCIÓN_MEDIA_PARTE", 3797);
define("LÍMITE_MÁXIMO_DE_DESCUENTO_SOLTERO", 1196);
define("LÍMITE_MÁXIMO_DE_DESCUENTO_PARA_PAREJAS", 1970);
define("LÍMITE_IMPUESTO_PAREJA_PARA_DESCUENTO", 2627);
define("LÍMITE_MÁXIMO_IMPUESTO_SOLTERO_PARA_DESCUENTO", 1595);
define("DESCUENTO_MÁXIMO_DEL_10_POR_CIENTO", 12502);
define("DESCUENTO_DIEZ_POR_CIENTO_MÍNIMO", 437);

// definición de las constantes locales
$DATA = "taxpayersdata.txt";
$RESULTADOS = "resultados.txt";
$límites = array(9964, 27519, 73779, 156244, 0);
$coeffR = array(0, 0.14, 0.3, 0.41, 0.45);
$coeffN = array(0, 1394.96, 5798, 13913.69, 20163.45);

// lectura de los datos
$data = fopen($DATA, "r");
if (!$data) {
  print "No se puede abrir el archivo de datos [$DATA] para lectura\n";
  exit;
}

...

ECMAScript


'use strict';
// esto es un comentario
// constante
const nombre = "dupont";
// una salida a pantalla
console.log("nombre: ", nombre);
// una matriz con elementos de diferentes tipos
const matriz = ["uno", "dos", 3, 4];
// su número de elementos
let n = array.length;
// un bucle
for (let i = 0; i < n; i++) {
  console.log("matriz[", i, "] = ", matriz[i]);
}
// inicialización de 2 variables con el contenido de un array
let [cadena1, cadena2] = ["cadena1", "cadena2"];
// concatenación de las 2 cadenas
const cadena3 = cadena1 + cadena2;
// visualización del resultado
console.log([cadena1, cadena2, cadena3]);
...

VBScript


' cálculo del impuesto de un contribuyente
' el programa debe ejecutarse con tres parámetros: casado, hijos, salario
' casado: carácter O si está casado, N si no lo está
' hijos: número de hijos
' salario: salario anual sin céntimos

' declaración obligatoria de las variables
  Option Explicit
  Dim error
  
' recuperamos los argumentos comprobando su validez
  Dim marie, enfants, salario
  error = getArguments(marie, enfants, salaire)
  ' ¿Error?
  If error(0)<>0 Then wscript.echo error(1) : wscript.quit error(0)

' se recuperan los datos necesarios para el cálculo del impuesto
  Dim límites, coeffR, coeffN
  error = getData(límites, coeffR, coeffN)
  ' ¿Hay error?
  Si error(0) ≠ 0 Entonces wscript.echo error(1) : wscript.quit 5

  ' se muestra el resultado
  wscript.echo "impuesto=" & calcularImpuesto(esposa,hijos,salario,límites,coefR,coefN)
  
  ' salimos sin error
  wscript.quit 0

XML


<?xml version="1.0" encoding="utf-8" ?>
<configuración>

  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </sectionGroup>
  </configSections>

  <spring>
    <context>
      <resource uri="config://spring/objects" />
    </context>
    <objects xmlns="http://www.springframework.net">
      <object name="dao" type="Dao.DataBaseImpot, ImpotsV7-dao">
        <constructor-arg index="0" value="MySql.Data.MySqlClient"/>
        <constructor-arg index="1" value="Server=localhost;Database=bdimpots;Uid=admimpots;Pwd=mdpimpots;"/>
        <constructor-arg index="2" value="select limite, coeffr, coeffn from tranches"/>
      </object>
      <object name="metier" type="Metier.ImpotMetier, ImpotsV7-metier">
        <constructor-arg index="0" ref="dao"/>
      </object>
    </objects>
  </spring>
</configuración>

2.2.2. Bloques de código sin formato (texto sin formato)

Estos son algunos ejemplos de código sin formato:

Resultados de la ejecución

Cabe señalar que el código no comienza en la línea n.º 1.

C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_01.py
nombre=dupont
lista[0] = uno
lista[1] = dos
lista[2]=3
lista[3]=4
[cadena1,cadena2,cadena1cadena2]
cadena = cadena1
tipo[4]=<class 'int'>
tipo[cadena1] = <class 'str'>
tipo[['uno', 'dos', 3, 4]] = <class 'list'>
tipo[ha cambiado] = <class 'str'>
res1 = 14s
(res1, res2, res3) = [uno, 0, 100]
lista[0] = uno
lista[1] = 0
lista[2] = 100
lista[0] = 8
lista[1] = 5
suma = 13

Proceso finalizado con código de salida 0

Este caso requirió decenas de iteraciones. El conversor nunca encontraba el número de la primera línea de código. Finalmente, le pregunté a Gemini cómo formatear el bloque de código para que lo reconociera. Esto es lo que me respondió:

Image

Seguí este procedimiento y funcionó. Yo utilizaba el método a través del icono de lista (Personalizar). Por lo tanto, es posible que haya que modificar ciertos elementos del documento ODT/DOCX para obtener lo que se desea.

El conversor sabe gestionar bloques de código sin numerar.

lista[0]=uno
lista[1]=0
lista[2]=100
lista[0]=8
lista[1]=5
suma = 13

Estos son los mismos ejemplos que en el apartado2.2.1 , pero sin enriquecer. En este caso, serán las palabras clave del archivo de configuración las que guiarán al convertidor hacia el lenguaje adecuado.

Java

package istia.st.spring.core;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

clase pública Demo01 {

@SuppressWarnings({ "unchecked", "resource" })
public static void main(String[] args) {
// recuperación del contexto Spring
ApplicationContext ctx = new ClassPathXmlApplicationContext("config-01.xml");
// recuperamos los beans
Persona p01 = ctx.getBean("persona_01", Persona.class);
Persona p02 = ctx.getBean("persona_02", Persona.class);
List<Persona> club = ctx.getBean("club", new ArrayList<Persona>().getClass());
Piso piso01 = ctx.getBean(Piso.class);
...

C#

using System;

namespace Chap1 {
    class Impuestos {
        static void Main(string[] args) {
            // Tablas de datos necesarias para el cálculo del impuesto
            decimal[] límites = { 4962M, 8382M, 14753M, 23888M, 38868M, 47932M, 0M };
            decimal[] coeffR = { 0M, 0,068M, 0,191M, 0,283M, 0,374M, 0,426M, 0,481M };
            decimal[] coeffN = { 0M, 291,09M, 1322,92M, 2668,39M, 4846,98M, 6883,66M, 9505,54M };

            // recuperamos el estado civil
            bool OK = false;
            string respuesta = null;
            while (!OK) {
                Console.Write("¿Está casado/a (S/N)? ");
                respuesta = Console.ReadLine().Trim().ToLower();
                if (respuesta != "s" && respuesta != "n")
                    Console.Error.WriteLine("Respuesta incorrecta. Vuelva a intentarlo");
                else OK = true;
            }//while
            bool marie = respuesta == "o";
...

Python

# ----------------------------------
def mostrar(cadena):
    # muestra cadena
    print("cadena=%s" % cadena)


# ----------------------------------
def mostrar_tipo(variable):
    # muestra el tipo de variable
    print("tipo[%s]=%s" % (variable, tipo(variable)))


# ----------------------------------
def f1(param):
    # suma 10 a param
    return param + 10


# ----------------------------------
def f2():
    # devuelve una tupla de 3 valores
    return "uno", 0, 100


# -------------------------------- programa principal ------------------------------------
...

PHP

<?php

// tipos estrictos para los parámetros de las funciones
declare(strict_types=1);

// constantes globales
define("LÍMITE_QF_MEDIA_PARTE", 1551);
define("LÍMITE_INGRESOS_SOLTERO_PARA_REDUCCIÓN", 21037);
define("LÍMITE_INGRESOS_PAREJA_PARA_REDUCCIÓN", 42074);
define("VALOR_REDUCCIÓN_MEDIA_PARTE", 3797);
define("LÍMITE_MÁXIMO_DE_DESCUENTO_SOLTERO", 1196);
define("LÍMITE_MÁXIMO_DE_DESCUENTO_PARA_PAREJAS", 1970);
define("LÍMITE_IMPUESTO_PAREJA_PARA_DESCUENTO", 2627);
define("LÍMITE_MÁXIMO_IMPUESTO_SOLTERO_PARA_DESCUENTO", 1595);
define("DESCUENTO_MÁXIMO_DEL_10_POR_CIENTO", 12502);
define("DESCUENTO_DIEZ_POR_CIENTO_MÍNIMO", 437);

// definición de las constantes locales
$DATA = "taxpayersdata.txt";
$RESULTADOS = "resultados.txt";
$límites = array(9964, 27519, 73779, 156244, 0);
$coeffR = array(0, 0.14, 0.3, 0.41, 0.45);
$coeffN = array(0, 1394.96, 5798, 13913.69, 20163.45);

// lectura de los datos
$data = fopen($DATA, "r");
if (!$data) {
  print "No se puede abrir el archivo de datos [$DATA] para lectura\n";
  exit;
}

...

ECMAScript

'use strict';
// esto es un comentario
// constante
const nombre = "dupont";
// una salida a pantalla
console.log("nombre: ", nombre);
// una matriz con elementos de diferentes tipos
const matriz = ["uno", "dos", 3, 4];
// su número de elementos
let n = array.length;
// un bucle
for (let i = 0; i < n; i++) {
  console.log("matriz[", i, "] = ", matriz[i]);
}
// inicialización de 2 variables con el contenido de un array
let [cadena1, cadena2] = ["cadena1", "cadena2"];
// concatenación de las 2 cadenas
const cadena3 = cadena1 + cadena2;
// visualización del resultado
console.log([cadena1, cadena2, cadena3]);
...

VBScript

' cálculo de los impuestos de un contribuyente
' el programa debe ejecutarse con tres parámetros: casado, hijos, salario
' casado: carácter O si está casado, N si no lo está
' hijos: número de hijos
' salario: salario anual sin céntimos

' declaración obligatoria de las variables
  Option Explicit
  Dim error

' recuperamos los argumentos comprobando su validez
  Dim marie, enfants, salario
  error = getArguments(marie, enfants, salaire)
  ' ¿Error?
  If error(0)<>0 Then wscript.echo error(1) : wscript.quit error(0)

' se recuperan los datos necesarios para el cálculo del impuesto
  Dim límites, coeffR, coeffN
  error = getData(límites, coeffR, coeffN)
  ' ¿Hay error?
  Si error(0) ≠ 0 Entonces wscript.echo error(1) : wscript.quit 5

  ' se muestra el resultado
  wscript.echo "impuesto=" & calcularImpuesto(esposa,hijos,salario,límites,coefR,coefN)

  ' salimos sin error
  wscript.quit 0

XML

<?xml version="1.0" encoding="utf-8" ?>
<configuración>

  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </grupoDeSecciones>
  </configSections>

  <spring>
    <context>
      <resource uri="config://spring/objects" />
    </context>
    <objects xmlns="http://www.springframework.net">
      <object name="dao" type="Dao.DataBaseImpot, ImpotsV7-dao">
        <constructor-arg index="0" value="MySql.Data.MySqlClient"/>
        <constructor-arg index="1" value="Server=localhost;Database=bdimpots;Uid=admimpots;Pwd=mdpimpots;"/>
        <constructor-arg index="2" value="select limite, coeffr, coeffn from tranches"/>
      </object>
      <objeto nombre="metier" tipo="Metier.ImpotMetier, ImpotsV7-metier">
        <argumento-constructor index="0" ref="dao"/>
      </object>
    </objects>
  </spring>
</configuración>

HTML

<!DOCTYPE HTML>
<HTML>
    <head>
        <title>Laragon</title>

        <link href="<a href="view-source:https://fonts.googleapis.com/css?family=Karla:400">https://fonts.googleapis.com/css?family=Karla:400</a> " rel="stylesheet" type="text/css">

        <style>
            HTML, body {
                height: 100%;
            }

            body {
                margin: 0;
                padding: 0;
                ancho: 100%;
                display: table;
                peso de fuente: 100;
                font-family: 'Karla';
            }

            .container {
                alineación del texto: centrada;
                display: table-cell;
                vertical-align: middle;
            }

            .content {
                alineación del texto: centrada;
                display: inline-block;
            }

            .title {
                tamaño de fuente: 96px;
            }

            .opt {
                margin-top: 30px;
            }

            .opt a {
              text-decoration: none;
              tamaño de fuente: 150%;
            }

            a:hover {
              color: red;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="content">
                <div class="title" title="Laragon">Laragon</div>

                <div class="info"><br />
                      Apache/2.4.35 (Win64) OpenSSL/1.1.0i PHP/7.2.11<br />
                      Versión de PHP: 7.2.11   <span><a title="phpinfo()" href="<a href="view-source:http://localhost/?q=info">/?q=info</a>">info</a></span><br />
                      Raíz del documento: C:/misprogramas/laragon-lite/www<br />

                </div>

2.3. Los enlaces

El conversor Gemini / ChatGPT conserva los enlaces externos del documento ODT / DOCX. Por ejemplo, Gemini 3 o [Generar un script de Python con herramientas de IA].

Sabe gestionar un enlace a un capítulo Enlace a un capítulo

Una referencia a un capítulo:2.1.1 .

Una referencia a una marca de texto anterior: Gemini 3

Una referencia a un marcador de texto posterior: GitHub

2.4. El enriquecimiento del texto

El conversor sabe gestionar la negrita, la cursiva, el subrayado y el resaltado. Respeta el color del resaltado.

Un texto con palabras en negrita, cursiva, subrayadas o resaltadas o resaltadas o resaltadas.

Lo mismo ocurre con los enlaces: [Generar un script de Python con herramientas de IA].

El conversor también gestiona el color de los caracteres.


También gestiona los bordes superior e inferior de los párrafos.



  • También gestiona los bordes superior e inferior de los párrafos.
  • También gestiona los bordes superior e inferior de los párrafos.
  • También gestiona los bordes superior e inferior de los párrafos.

  1. También gestiona los bordes superior e inferior de los párrafos.
  2. También gestiona los bordes superior e inferior de los párrafos.
  3. También gestiona los bordes superior e inferior de los párrafos.
  1. Un texto con palabras en negrita, cursiva, subrayadas o resaltadas.
  2. Lo mismo ocurre con los enlaces: [Generar un script de Python con herramientas de IA].
  3. El conversor también gestiona el color de los caracteres.
También gestiona el fondo del párrafo
  • También gestiona el fondo del párrafo
  1. También gestiona el fondo del párrafo

2.5. Un título también se puede enriquecer.

2.6. Las imágenes

El conversor Gemini / ChatGPT sabe gestionar imágenes y tablas de imágenes:

Image

En los documentos ODT es frecuente encontrar dibujos. A pesar de decenas de intentos, Gemini no ha logrado generar un script que genere la imagen (como una captura de pantalla) del dibujo. Así, arriba, la imagen 5 es la captura de pantalla de un dibujo de un documento ODT.

Todas las imágenes son clicables para ampliarlas. Si arriba hacemos clic en la imagen [1-3], obtenemos la siguiente ampliación:

2.7. Los caracteres que hay que proteger

Un sitio web de MkDocs1 tiene páginas cuyo contenido no es HTML, sino Markdown. Si el documento ODT/DOCX contiene caracteres que existen en Markdown, es posible que MkDocs los interprete y, por lo tanto, no se muestren como se esperaba. He aquí dos ejemplos:

El asterisco * tiene un significado en MarkDown. Por lo tanto, la siguiente línea puede interpretarse incorrectamente:

El impuesto I es entonces igual a 0,15*R – 2072,5*nbParts.

Otro ejemplo es cuando quieres insertar un bloque de código Markdown en tu documento como este:

# Convertidor de Word/ODT a sitio HTML (MkDocs)

🔗 **[Ver el sitio de demostración generado](https://stahe.github.io/word-odt-vers-html-janv-2026/)**

---

## 📝 Descripción

El objetivo de este proyecto es poner a disposición del lector un conversor en Python de documentos Word u ODT a un sitio web HTML estático.

Cuando el documento ODT/DOCX es adecuado, el conversor genera un sitio HTML mediante **MkDocs** que tiene el aspecto profesional de los sitios generados por Pandoc.

## 🤖 Contexto de creación

Este conversor ha sido creado íntegramente por la IA **Gemini 3** (con una suscripción pro). Es el resultado de sucesivas iteraciones para gestionar con precisión la estructura de los documentos ODT (OpenDocument Text).

## ✨ Funcionalidades

El script `convert.py` realiza las siguientes acciones:

* **Conversión de ODT a Markdown**: Analiza el archivo `.odt` (XML) para extraer su estructura.
* **Gestión de títulos**: Genera automáticamente la tabla de contenidos (TOC) y la navegación lateral.
* **Bloques de código**: Detección automática de lenguajes, coloración sintáctica y **gestión precisa de la numeración de líneas** (atributos `start-value`).
* **Listas**: Compatibilidad con listas con viñetas y numeradas con la sangría correcta.
* **Formato**: Compatibilidad con *negrita*, *cursiva*, *subrayado* y *resaltado* (respetando los colores originales).
* **Imágenes**: Extracción e integración automática de las imágenes contenidas en el documento.
* **Configuración**: Personalización mediante un archivo `config.py` (pie de página, Google Analytics, etc.).

## 🚀 Instalación

### Requisitos previos

* Python 3.x
* Las siguientes bibliotecas:

```bash
pip install odfpy unidecode mkdocs mkdocs-material

```

2.8. Las tablas

Una tabla puede contener diferentes contenidos:

1
2

package istia.st.spring.core;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

clase pública Demo01 {


    
3
4

# ----------------------------------
def mostrar(cadena):
    # muestra cadena
    print("cadena=%s" % cadena)


# ----------------------------------
def mostrar_tipo(variable):
    # muestra el tipo de variable
    print("tipo[%s]=%s" % (variable, tipo(variable)))


Una tabla que contiene enlaces:

El conversor Gemini / ChatGPT sabe conservar los
enlaces externos del documento ODT / DOCX. Por ejemplo
Sabe gestionar un enlace a un capítulo Enlace a un capítulo
Una referencia a un capítulo:2.1.1 .
Una referencia a un marcador de texto anterior: Gemini 3
Una referencia a un marcador de texto posterior: GitHub

Una tabla cuyas celdas contienen otra tabla:

html:form
sirve tanto para generar la etiqueta HTML <form> como para proporcionar información al controlador que tendrá que procesar este formulario:
action
url a la que se enviarán los valores del formulario
name
nombre del formulario HTML. También es el nombre del bean que almacenará los valores del mismo
type
nombre de la clase que deberá instanciarse para obtener el bean de almacenamiento del formulario
Cabe señalar que no se especifica el método de envío de los parámetros del formulario (GET/POST) al controlador. Se podría hacer con el atributo method. En ausencia de este, se utiliza el método POST por defecto.
html:text
sirve para generar la etiqueta <input type="text" value="...">:
property
nombre del campo del bean del formulario que se asociará al campo de entrada. Al enviar el formulario al servidor (cliente -> servidor), el campo del bean tomará el valor del campo de entrada. Al mostrar el formulario (servidor -> cliente), el valor contenido en el campo del bean se muestra en el campo de entrada de .
También gestiona el fondo del párrafo en una tabla
  • También gestiona el fondo del párrafo en una tabla
  1. También gestiona el fondo del párrafo en una tabla
 

2.9. Las notas al pie

El convertidor Gemini2 / ChatGPT gestiona las notas al pie de página. Aquí hay otra nota al pie de página3 .



  1. MkDocs 

  2. Google Gemini 

  3. La nota al pie