<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Código |</title><link>https://clementgodbarge.com/es/code/</link><atom:link href="https://clementgodbarge.com/es/code/index.xml" rel="self" type="application/rss+xml"/><description>Código</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>es-es</language><image><url>https://clementgodbarge.com/media/icon_hu_64a6c3bec25b3d7b.png</url><title>Código</title><link>https://clementgodbarge.com/es/code/</link></image><item><title>tei-mcp</title><link>https://clementgodbarge.com/es/code/tei-mcp/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/es/code/tei-mcp/</guid><description>&lt;h2 id="tei-mcp-tei-p5-para-agentes-de-ia"&gt;tei-mcp: TEI P5 para agentes de IA&lt;/h2&gt;
&lt;p&gt;tei-mcp es un servidor
de código abierto que da a los asistentes de programación con IA acceso directo a la especificación
. En lugar de fiarse de lo que memorizó durante el entrenamiento —fuente frecuente de marcado plausible pero incorrecto—, la IA puede consultar la especificación en tiempo real.&lt;/p&gt;
&lt;h2 id="funciones"&gt;Funciones&lt;/h2&gt;
&lt;p&gt;El servidor analiza el ODD de TEI P5 y expone 16 herramientas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consultar&lt;/strong&gt; cualquier elemento, clase, macro o módulo por su nombre, sin distinguir mayúsculas de minúsculas y con sugerencias en caso de errata&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resolver atributos&lt;/strong&gt; a lo largo de toda la jerarquía de clases de la TEI (locales y heredados)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expandir modelos de contenido&lt;/strong&gt; en árboles estructurados, con resolución de clases y macros&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validar el anidamiento&lt;/strong&gt;: relación directa padre-hijo o alcanzabilidad recursiva, con seguimiento de la ruta&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validar documentos&lt;/strong&gt; contra TEI P5: modelos de contenido, atributos, listas cerradas de valores, integridad de las referencias y avisos de obsolescencia&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validar elementos sueltos&lt;/strong&gt; para flujos de edición incremental&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cargar personalizaciones ODD&lt;/strong&gt; que restringen el esquema al subconjunto propio de un proyecto&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buscar&lt;/strong&gt; en todos los tipos de entidades con expresiones regulares&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="instalación"&gt;Instalación&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install tei-mcp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;O ejecútelo directamente con:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uvx tei-mcp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="uso"&gt;Uso&lt;/h2&gt;
&lt;p&gt;Añádalo a cualquier cliente compatible con MCP (Claude, Cursor, Windsurf, etc.):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tei&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;uvx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tei-mcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El código fuente y la documentación están en el
.&lt;/p&gt;</description></item><item><title>Multi-Saxon</title><link>https://clementgodbarge.com/es/code/multi-saxon/</link><pubDate>Fri, 28 Mar 2025 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/es/code/multi-saxon/</guid><description>&lt;h2 id="multi-saxon-xslt-en-paralelo-para-grandes-corpus-tei"&gt;Multi-Saxon: XSLT en paralelo para grandes corpus TEI&lt;/h2&gt;
&lt;p&gt;Multi-Saxon cubre una laguna importante de las herramientas de procesamiento XML: permite ejecutar en paralelo transformaciones XSLT 2.0 y 3.0 que LXML (una biblioteca XML muy usada en Python) no puede manejar. Pensado para grandes colecciones de documentos XML TEI, Multi-Saxon acorta considerablemente los tiempos de procesamiento gracias a una ejecución paralela eficiente.&lt;/p&gt;
&lt;h2 id="características-principales"&gt;Características principales&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compatibilidad avanzada con XSLT&lt;/strong&gt;: procesa transformaciones XSLT 2.0 y 3.0, fuera del alcance de LXML&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Procesamiento en paralelo&lt;/strong&gt;: la paralelización reduce drásticamente el tiempo de transformación de grandes colecciones de documentos&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimizado para TEI&lt;/strong&gt;: diseñado expresamente para documentos XML de la Text Encoding Initiative (TEI)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rendimiento escalable&lt;/strong&gt;: maneja con soltura corpus de cientos o miles de documentos&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multiplataforma&lt;/strong&gt;: funciona en sistemas operativos y entornos distintos&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="el-problema-que-resuelve-multi-saxon"&gt;El problema que resuelve Multi-Saxon&lt;/h2&gt;
&lt;p&gt;Quienes trabajan con TEI en humanidades digitales tropiezan a menudo con dos obstáculos:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;LXML (una biblioteca habitual de procesamiento XML en Python) solo admite XSLT 1.0, lo que deja fuera las funciones más avanzadas de XSLT 2.0/3.0&lt;/li&gt;
&lt;li&gt;Procesar grandes corpus de documentos TEI uno tras otro puede llevar un tiempo prohibitivo&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Multi-Saxon resuelve ambos aprovechando las capacidades XSLT avanzadas de Saxon y repartiendo el trabajo entre varios núcleos, con ganancias de rendimiento notables.&lt;/p&gt;
&lt;h2 id="implementación"&gt;Implementación&lt;/h2&gt;
&lt;p&gt;Multi-Saxon combina Python con el procesador Saxon de Java para formar una cadena de transformación de alto rendimiento:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Usa la biblioteca Saxon de Java para un procesamiento XSLT 2.0/3.0 robusto&lt;/li&gt;
&lt;li&gt;Recurre al multiprocesamiento para distribuir las transformaciones entre los núcleos de CPU disponibles&lt;/li&gt;
&lt;li&gt;Gestiona con eficiencia los grupos de procesos para maximizar el rendimiento&lt;/li&gt;
&lt;li&gt;Ofrece una interfaz sencilla para procesar documentos TEI por lotes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ejemplo-de-uso"&gt;Ejemplo de uso&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multi_saxon&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MultiSaxon&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Initialize with your XSLT stylesheet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;transformer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MultiSaxon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;transform.xsl&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Transform a single document&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;transformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;input.xml&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;output.xml&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Transform an entire directory in parallel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;transformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;input_dir&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;output_dir&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="qué-aporta-a-las-humanidades-digitales"&gt;Qué aporta a las humanidades digitales&lt;/h2&gt;
&lt;p&gt;A los proyectos de humanidades digitales que manejan grandes colecciones de documentos TEI, Multi-Saxon les permite:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Transformaciones complejas a escala de corpus, imposibles con LXML&lt;/li&gt;
&lt;li&gt;Tiempos de procesamiento drásticamente menores (a menudo entre 5 y 10 veces, en sistemas multinúcleo)&lt;/li&gt;
&lt;li&gt;Análisis más sofisticados gracias a las funciones avanzadas de XSLT 2.0/3.0&lt;/li&gt;
&lt;li&gt;Un flujo de trabajo más simple para procesar colecciones enteras de documentos&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;El código fuente y la documentación están en el
.&lt;/p&gt;</description></item><item><title>persNamer</title><link>https://clementgodbarge.com/es/code/persnamer/</link><pubDate>Fri, 28 Mar 2025 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/es/code/persnamer/</guid><description>&lt;h2 id="persnamer-conectar-la-tei-con-el-virtual-international-authority-file"&gt;persNamer: conectar la TEI con el Virtual International Authority File&lt;/h2&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;persNamer es una herramienta especializada en Python que agiliza la integración en documentos XML TEI de los datos de autoridad sobre personas de VIAF (Virtual International Authority File). Al convertir los identificadores VIAF en marcado TEI listo para usar, persNamer reduce en buena medida el trabajo manual que supone crear entradas de persona estructuradas para una edición crítica digital.&lt;/p&gt;
&lt;h2 id="el-reto-del-control-de-autoridades-en-tei"&gt;El reto del control de autoridades en TEI&lt;/h2&gt;
&lt;p&gt;Las ediciones críticas digitales suelen exigir una identificación precisa de los personajes históricos, con sus nombres normalizados y sus fechas de nacimiento y muerte. Mantener un control de autoridades coherente en todo un proyecto exige:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Identificar a las personas en los textos históricos&lt;/li&gt;
&lt;li&gt;Encontrar datos de autoridad sobre ellas&lt;/li&gt;
&lt;li&gt;Crear entradas TEI con el formato correcto&lt;/li&gt;
&lt;li&gt;Garantizar que las referencias sean coherentes en todo el proyecto&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Todo ello suele hacerse a mano, lleva tiempo y se presta a incoherencias.&lt;/p&gt;
&lt;h2 id="cómo-funciona-persnamer"&gt;Cómo funciona persNamer&lt;/h2&gt;
&lt;p&gt;persNamer automatiza este flujo de trabajo en tres pasos:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Obtiene los datos de VIAF&lt;/strong&gt;: a partir de un identificador VIAF, recupera los datos RDF mediante negociación de contenido HTTP&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extrae la información clave&lt;/strong&gt;: analiza el RDF para extraer el nombre preferente y las fechas de nacimiento y muerte&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Genera el marcado TEI&lt;/strong&gt;: crea dos fragmentos XML esenciales:
&lt;ul&gt;
&lt;li&gt;Una &lt;strong&gt;entrada del fichero de autoridades&lt;/strong&gt; (elemento &lt;code&gt;&amp;lt;person&amp;gt;&lt;/code&gt; con un &lt;code&gt;xml:id&lt;/code&gt; generado, &lt;code&gt;&amp;lt;persName&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;birth&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;death&amp;gt;&lt;/code&gt; e &lt;code&gt;&amp;lt;idno type=&amp;quot;VIAF&amp;quot;&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Una &lt;strong&gt;etiqueta de anotación&lt;/strong&gt; independiente (&lt;code&gt;&amp;lt;persName&amp;gt;&lt;/code&gt; con un atributo &lt;code&gt;ref&lt;/code&gt; que remite a la entrada de autoridad)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Esta doble salida permite al editor mantener un fichero de autoridades centralizado y, a la vez, insertar sin esfuerzo etiquetas de anotación en sus textos TEI.&lt;/p&gt;
&lt;h2 id="características-principales"&gt;Características principales&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Identificadores normalizados&lt;/strong&gt;: genera identificadores XML coherentes con el formato &lt;code&gt;pers-[apellido]-[inicial del nombre]&lt;/code&gt; (p. ej., &lt;code&gt;pers-deteligny-c&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Análisis de RDF&lt;/strong&gt;: usa &lt;code&gt;rdflib&lt;/code&gt; para extraer información de distintas propiedades RDF (p. ej., &lt;code&gt;rdfs:label&lt;/code&gt;, &lt;code&gt;schema:name&lt;/code&gt;, &lt;code&gt;viaf:mainHead&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interfaz de línea de comandos&lt;/strong&gt;: se ejecuta con un número VIAF como único argumento obligatorio&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Salida detallada&lt;/strong&gt;: informa con detalle del procesamiento junto a la salida XML final&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ejemplo-de-uso"&gt;Ejemplo de uso&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python persNamer.py &lt;span class="m"&gt;314802260&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Este comando produce:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;person&lt;/span&gt; &lt;span class="na"&gt;xml:id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pers-deteligny-c&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;persName&amp;gt;&lt;/span&gt;Charles deTéligny&lt;span class="nt"&gt;&amp;lt;/persName&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;birth&amp;gt;&lt;/span&gt;1535&lt;span class="nt"&gt;&amp;lt;/birth&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;death&amp;gt;&lt;/span&gt;1572-08-24&lt;span class="nt"&gt;&amp;lt;/death&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;idno&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;VIAF&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;314802260&lt;span class="nt"&gt;&amp;lt;/idno&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/person&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;persName&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#pers-deteligny-c&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Charles deTéligny&lt;span class="nt"&gt;&amp;lt;/persName&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="aplicaciones-en-humanidades-digitales"&gt;Aplicaciones en humanidades digitales&lt;/h2&gt;
&lt;p&gt;persNamer resulta especialmente útil para:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ediciones críticas digitales que necesitan control de autoridades&lt;/li&gt;
&lt;li&gt;Proyectos de codificación TEI que trabajan con personajes históricos&lt;/li&gt;
&lt;li&gt;Iniciativas de datos enlazados que conectan documentos con registros de autoridad&lt;/li&gt;
&lt;li&gt;Garantizar la coherencia en grandes corpus TEI&lt;/li&gt;
&lt;li&gt;Enseñar el control de autoridades en cursos de humanidades digitales&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="implementación"&gt;Implementación&lt;/h2&gt;
&lt;p&gt;persNamer está escrito en Python y depende de:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;requests&lt;/code&gt; para las peticiones HTTP&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rdflib&lt;/code&gt; para el análisis de RDF&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lxml&lt;/code&gt; para el manejo de XML&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;El código fuente y la documentación están en el
.&lt;/p&gt;</description></item><item><title>Emulador de telégrafo ITA2</title><link>https://clementgodbarge.com/es/code/baudot-emulator/</link><pubDate>Thu, 13 Feb 2025 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/es/code/baudot-emulator/</guid><description>&lt;p&gt;Este emulador de ITA2 es un recurso para el aula: vuelve visibles y manipulables las nociones abstractas de la codificación. Cuando los estudiantes escriben un texto y lo ven convertirse al instante en patrones de agujeros, están aprendiendo varias ideas clave de la informática y de las telecomunicaciones.&lt;/p&gt;
&lt;h2 id="ventajas-pedagógicas"&gt;Ventajas pedagógicas&lt;/h2&gt;
&lt;p&gt;En primer lugar, muestra la representación binaria: cómo un texto se convierte en una secuencia de unos y ceros. Solemos explicarlo en abstracto; ver cómo van apareciendo los agujeros ayuda, en cambio, a comprender que un sistema físico puede contener información digital.&lt;/p&gt;
&lt;div class="baudot-emulator"&gt;
&lt;h2&gt;ITA2 (Baudot-Murray) Telegraph Type Emulator&lt;/h2&gt;
&lt;p&gt;Type a word in the input below to see its representation on the ITA2 tape.&lt;/p&gt;
&lt;div class="baudot-controls"&gt;
&lt;label for="baudot-input"&gt;Type word:&lt;/label&gt;
&lt;input id="baudot-input" class="text-input" size="50" maxlength="50" /&gt;
&lt;button type="button" id="baudot-ltr-button" class="control-button active"&gt;LTR&lt;/button&gt;
&lt;button type="button" id="baudot-fig-button" class="control-button"&gt;FIG&lt;/button&gt;
&lt;/div&gt;
&lt;div class="tape-outer-container"&gt;
&lt;div class="tape-container"&gt;
&lt;table&gt;
&lt;tbody id="baudot-tape"&gt;&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;style&gt;
.baudot-emulator {
--light-color: #f3f4f6;
--dark-color: #1f2937;
--light-alt-color: #e5e7eb;
--dark-alt-color: #374151;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;
max-width: 100%;
margin: 2rem 0;
padding: 0;
box-sizing: border-box;
}
.baudot-emulator {
--tape-bg: var(--light-color);
--hole-bg: var(--light-color);
--hole-border: #d1d5db;
--punched-bg: var(--dark-color);
--punched-border: var(--dark-color);
--sprocket-bg: var(--light-color);
--sprocket-border: #9ca3af;
--button-bg: var(--light-color);
--button-bg-active: #d1d5db;
--button-text: var(--dark-color);
--button-border: #d1d5db;
--input-bg: white;
--input-border: #d1d5db;
--input-text: var(--dark-color);
--line-number: #6b7280;
}
html.dark .baudot-emulator,
html[data-theme='dark'] .baudot-emulator,
body.dark .baudot-emulator {
--tape-bg: var(--dark-alt-color);
--hole-bg: var(--dark-alt-color);
--hole-border: #4b5563;
--punched-bg: var(--light-color);
--punched-border: var(--light-color);
--sprocket-bg: var(--dark-alt-color);
--sprocket-border: #9ca3af;
--button-bg: var(--dark-alt-color);
--button-bg-active: #4b5563;
--button-text: var(--light-color);
--button-border: #4b5563;
--input-bg: var(--dark-alt-color);
--input-border: #4b5563;
--input-text: var(--light-color);
--line-number: #9ca3af;
}
.baudot-controls {
margin-bottom: 1.5rem;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem;
}
.baudot-emulator .text-input {
flex: 1;
min-width: 200px;
padding: 0.5rem;
font-size: 1rem;
border: 1px solid var(--input-border);
border-radius: 4px;
background: var(--input-bg);
color: var(--input-text);
}
.baudot-emulator .control-button {
padding: 0.5rem 1rem;
background: var(--button-bg);
color: var(--button-text);
border: 1px solid var(--button-border);
border-radius: 4px;
cursor: pointer;
font-size: 0.9rem;
}
.baudot-emulator .control-button.active {
background: var(--button-bg-active);
font-weight: bold;
}
.tape-outer-container {
padding: 0;
margin-bottom: 1.5rem;
border-radius: 4px;
overflow: hidden;
}
.tape-container {
width: 100%;
overflow-x: auto;
background: var(--tape-bg);
padding: 1rem 0.5rem;
}
.baudot-emulator table {
border-collapse: collapse;
width: 100%;
table-layout: fixed;
border: none;
}
.baudot-emulator tr {
height: 24px;
border: none;
}
.baudot-emulator td {
border: none;
padding: 0;
}
.baudot-emulator .line-number {
width: 20px;
text-align: center;
color: var(--line-number);
font-size: 0.8rem;
padding: 0 8px 0 0;
font-weight: bold;
}
.baudot-emulator .cell {
position: relative;
width: 20px;
height: 20px;
}
.baudot-emulator .cell-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--hole-bg);
border: 1px solid var(--hole-border);
}
.baudot-emulator .punched .cell-content {
background: var(--punched-bg);
border: 1px solid var(--punched-border);
}
.baudot-emulator .sprocket-hole {
position: absolute;
left: 50%;
top: 100%;
transform: translate(-50%, -50%);
width: 4px;
height: 4px;
border-radius: 50%;
background: var(--sprocket-bg);
border: 1px solid var(--sprocket-border);
z-index: 2;
}
&lt;/style&gt;
&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
initBaudotEmulator();
});
function initBaudotEmulator() {
if (!document.getElementById('baudot-input')) return;
const textInput = document.getElementById('baudot-input');
const tape = document.getElementById('baudot-tape');
const ltrButton = document.getElementById('baudot-ltr-button');
const figButton = document.getElementById('baudot-fig-button');
const ita2Code = {
'A': '00011', 'B': '11001', 'C': '01110', 'D': '01001', 'E': '00001',
'F': '01101', 'G': '11010', 'H': '10100', 'I': '00110', 'J': '01011',
'K': '01111', 'L': '10010', 'M': '11100', 'N': '01100', 'O': '11000',
'P': '10110', 'Q': '10111', 'R': '01010', 'S': '00101', 'T': '10000',
'U': '00111', 'V': '11110', 'W': '10011', 'X': '11101', 'Y': '10101',
'Z': '10001',
'1': '00011', '2': '11001', '3': '01110', '4': '01001', '5': '00001',
'6': '01101', '7': '11010', '8': '10100', '9': '01011', '0': '11000',
'-': '00011', '?': '00100', ':': '01010', '(': '11000', ')': '11101',
'.': '01000', ',': '00010', "'": '10001', '=': '01111', '/': '10011',
'+': '11011', ' ': '00100',
'FIG': '11011', 'LTR': '11111',
};
function generateTape() {
let rows = '';
for (let row = 0; row &lt; 5; row++) {
rows += '&lt;tr&gt;';
rows += `&lt;td class="line-number"&gt;${row + 1}&lt;/td&gt;`;
for (let col = 0; col &lt; 50; col++) {
rows += `&lt;td id="baudot_${row}_${col}" class="cell unpunched"&gt;
&lt;div class="cell-content"&gt;&lt;/div&gt;
${row === 2 ? '&lt;div class="sprocket-hole"&gt;&lt;/div&gt;' : ''}
&lt;/td&gt;`;
}
rows += '&lt;/tr&gt;';
}
tape.innerHTML = rows;
}
function updateITA2Code(word) {
clearTape();
word = word.toUpperCase();
let tapePosition = 0;
let currentCharType = 'LTR';
ltrButton.classList.add('active');
figButton.classList.remove('active');
for (let i = 0; i &lt; word.length; i++) {
const char = word[i];
let code = ita2Code[char] || ita2Code[' '];
let requiredCharType = /[A-Z ]/.test(char) ? 'LTR' : 'FIG';
if (requiredCharType !== currentCharType) {
const shiftCode = requiredCharType === 'LTR' ? ita2Code['LTR'] : ita2Code['FIG'];
punchTape(shiftCode, tapePosition++);
currentCharType = requiredCharType;
ltrButton.classList.toggle('active', currentCharType === 'LTR');
figButton.classList.toggle('active', currentCharType === 'FIG');
}
punchTape(code, tapePosition++);
}
}
function punchTape(code, tapePosition) {
if (tapePosition &gt;= 50) return;
for (let bit = 0; bit &lt; 5; bit++) {
const cell = document.getElementById(`baudot_${bit}_${tapePosition}`);
if (cell) {
cell.className = code[bit] === '1' ? 'cell punched' : 'cell unpunched';
}
}
}
function clearTape() {
for (let i = 0; i &lt; 50; i++) {
for (let bit = 0; bit &lt; 5; bit++) {
const cell = document.getElementById(`baudot_${bit}_${i}`);
if (cell) {
cell.className = 'cell unpunched';
}
}
}
}
generateTape();
textInput.addEventListener('input', function() {
updateITA2Code(this.value);
});
ltrButton.addEventListener('click', function() {
this.classList.add('active');
figButton.classList.remove('active');
if (textInput.value) {
updateITA2Code(textInput.value);
}
});
figButton.addEventListener('click', function() {
this.classList.add('active');
ltrButton.classList.remove('active');
if (textInput.value) {
updateITA2Code(textInput.value);
}
});
if (textInput.value) {
updateITA2Code(textInput.value);
}
}
&lt;/script&gt;
&lt;/div&gt;
&lt;p&gt;El mecanismo de cambio LETRAS/CIFRAS es la puerta natural a las máquinas de estados. A fuerza de probar, los estudiantes descubren que un mismo patrón puede representar caracteres distintos según el modo en que se encuentre la máquina; y esa experiencia directa de una codificación dependiente del estado los prepara para nociones informáticas más complejas.&lt;/p&gt;
&lt;h2 id="detalles-de-implementación"&gt;Detalles de implementación&lt;/h2&gt;
&lt;p&gt;El emulador está escrito en JavaScript y HTML/CSS, de modo que se incrusta sin dificultad en cualquier página web. El código es modular y puede adaptarse a distintos contextos docentes.&lt;/p&gt;
&lt;p&gt;El código fuente está disponible, y el emulador puede probarse, en el
.&lt;/p&gt;</description></item></channel></rss>