<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Kod |</title><link>https://clementgodbarge.com/sv/code/</link><atom:link href="https://clementgodbarge.com/sv/code/index.xml" rel="self" type="application/rss+xml"/><description>Kod</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>sv-se</language><image><url>https://clementgodbarge.com/media/icon_hu_64a6c3bec25b3d7b.png</url><title>Kod</title><link>https://clementgodbarge.com/sv/code/</link></image><item><title>tei-mcp</title><link>https://clementgodbarge.com/sv/code/tei-mcp/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/sv/code/tei-mcp/</guid><description>&lt;h2 id="tei-mcp-tei-p5-för-ai-agenter"&gt;tei-mcp: TEI P5 för AI-agenter&lt;/h2&gt;
&lt;p&gt;tei-mcp är en
-server med öppen källkod som ger AI-kodassistenter direkt tillgång till specifikationen
. I stället för att förlita sig på memorerade träningsdata – vilket ofta ger uppmärkning som ser rimlig ut men är fel – kan AI:n fråga specifikationen i realtid.&lt;/p&gt;
&lt;h2 id="funktioner"&gt;Funktioner&lt;/h2&gt;
&lt;p&gt;Servern tolkar ODD-filen för TEI P5 och exponerar 16 verktyg:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Slå upp&lt;/strong&gt; vilket element, vilken klass, vilket makro eller vilken modul som helst på namn, med skiftlägesokänslig matchning och förslag vid felstavning&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lös upp attribut&lt;/strong&gt; genom hela TEI:s klasshierarki (lokala + ärvda)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expandera innehållsmodeller&lt;/strong&gt; till strukturerade träd med upplösning av klasser och makron&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kontrollera nästling&lt;/strong&gt; – direkt förälder–barn eller rekursiv nåbarhet med spårad sökväg&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validera dokument&lt;/strong&gt; mot TEI P5: innehållsmodeller, attribut, slutna värdelistor, referensintegritet och utfasningsvarningar&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validera enskilda element&lt;/strong&gt; för stegvisa redigeringsflöden&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ladda ODD-anpassningar&lt;/strong&gt; för att begränsa schemat till en projektspecifik delmängd&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sök&lt;/strong&gt; bland alla entitetstyper med reguljära uttryck&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="installation"&gt;Installation&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;Eller kör direkt med:&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="användning"&gt;Användning&lt;/h2&gt;
&lt;p&gt;Lägg till i vilken MCP-kompatibel klient som helst (Claude, Cursor, Windsurf osv.):&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;Källkod och dokumentation finns i
.&lt;/p&gt;</description></item><item><title>Multi-Saxon</title><link>https://clementgodbarge.com/sv/code/multi-saxon/</link><pubDate>Fri, 28 Mar 2025 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/sv/code/multi-saxon/</guid><description>&lt;h2 id="multi-saxon-parallell-xslt-bearbetning-av-stora-tei-korpusar"&gt;Multi-Saxon: parallell XSLT-bearbetning av stora TEI-korpusar&lt;/h2&gt;
&lt;p&gt;Multi-Saxon fyller en kännbar lucka bland XML-verktygen genom att möjliggöra parallell körning av XSLT 2.0- och 3.0-transformationer som LXML (ett populärt XML-bibliotek för Python) inte klarar. Multi-Saxon är utformat särskilt för stora samlingar av XML-TEI-dokument och kortar bearbetningstiden avsevärt genom effektiv parallellkörning.&lt;/p&gt;
&lt;h2 id="huvudfunktioner"&gt;Huvudfunktioner&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Avancerat XSLT-stöd&lt;/strong&gt;: bearbetar XSLT 2.0- och 3.0-transformationer bortom LXML:s förmåga&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parallell bearbetning&lt;/strong&gt;: kortar transformationstiden dramatiskt för stora dokumentsamlingar genom parallellisering&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TEI-optimerat&lt;/strong&gt;: särskilt konstruerat för XML-dokument enligt Text Encoding Initiative (TEI)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skalbar prestanda&lt;/strong&gt;: hanterar effektivt korpusar från hundratals till tusentals dokument&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plattformsoberoende&lt;/strong&gt;: fungerar i olika operativsystem och miljöer&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="problemet-multi-saxon-löser"&gt;Problemet Multi-Saxon löser&lt;/h2&gt;
&lt;p&gt;Forskare inom digital humaniora som arbetar med TEI ställs ofta inför två stora svårigheter:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;LXML (ett vanligt XML-bibliotek för Python) stöder bara XSLT 1.0, vilket gör det omöjligt att använda de mer avancerade funktionerna i XSLT 2.0/3.0&lt;/li&gt;
&lt;li&gt;Att bearbeta stora TEI-korpusar sekventiellt kan ta oöverkomligt lång tid&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Multi-Saxon löser båda problemen genom att utnyttja Saxons avancerade XSLT-funktioner och samtidigt fördela bearbetningen över flera processorkärnor, med betydande prestandavinster som följd.&lt;/p&gt;
&lt;h2 id="implementering"&gt;Implementering&lt;/h2&gt;
&lt;p&gt;Multi-Saxon kombinerar Python med Javas Saxon-processor i en högpresterande transformationskedja:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;använder Javas Saxon-bibliotek för robust XSLT 2.0/3.0-bearbetning&lt;/li&gt;
&lt;li&gt;använder multiprocessing för att fördela transformationerna över tillgängliga processorkärnor&lt;/li&gt;
&lt;li&gt;hanterar processorpooler effektivt för maximal genomströmning&lt;/li&gt;
&lt;li&gt;erbjuder ett enkelt gränssnitt för batchbearbetning av TEI-dokument&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="användningsexempel"&gt;Användningsexempel&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="betydelse-för-digital-humaniora"&gt;Betydelse för digital humaniora&lt;/h2&gt;
&lt;p&gt;För projekt inom digital humaniora med stora TEI-samlingar möjliggör Multi-Saxon:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;komplexa transformationer av hela korpusar som vore omöjliga med LXML&lt;/li&gt;
&lt;li&gt;dramatiskt kortare bearbetningstider (ofta 5–10 gånger snabbare på flerkärniga system)&lt;/li&gt;
&lt;li&gt;mer avancerad analys tack vare funktionerna i XSLT 2.0/3.0&lt;/li&gt;
&lt;li&gt;ett enklare arbetsflöde för bearbetning av hela dokumentsamlingar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Källkod och dokumentation finns i
.&lt;/p&gt;</description></item><item><title>persNamer</title><link>https://clementgodbarge.com/sv/code/persnamer/</link><pubDate>Fri, 28 Mar 2025 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/sv/code/persnamer/</guid><description>&lt;h2 id="persnamer-tei-kopplat-till-virtual-international-authority-file"&gt;persNamer: TEI kopplat till Virtual International Authority File&lt;/h2&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;persNamer är ett specialiserat Python-verktyg som förenklar integrationen av auktoriserade persondata från VIAF (Virtual International Authority File) i TEI-XML-dokument. Genom att omvandla VIAF-identifierare till färdig TEI-uppmärkning minskar persNamer avsevärt det manuella arbetet med att skapa strukturerade personposter för digitala vetenskapliga utgåvor.&lt;/p&gt;
&lt;h2 id="auktoritetskontrollens-utmaning-i-tei"&gt;Auktoritetskontrollens utmaning i TEI&lt;/h2&gt;
&lt;p&gt;Digitala vetenskapliga utgåvor kräver ofta exakt identifiering av historiska personer, med standardiserade namnformer och levnadsår. Att upprätthålla en konsekvent auktoritetskontroll genom ett helt projekt kräver att man:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;identifierar personerna i de historiska texterna&lt;/li&gt;
&lt;li&gt;hittar auktoritetsdata om dem&lt;/li&gt;
&lt;li&gt;skapar korrekt formaterade TEI-poster&lt;/li&gt;
&lt;li&gt;ser till att hänvisningarna är konsekventa genom hela projektet&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Dessa steg är i regel manuella, tidskrävande och känsliga för inkonsekvenser.&lt;/p&gt;
&lt;h2 id="så-fungerar-persnamer"&gt;Så fungerar persNamer&lt;/h2&gt;
&lt;p&gt;persNamer automatiserar arbetsflödet genom att:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;hämta VIAF-data&lt;/strong&gt;: utifrån en VIAF-identifierare hämtar verktyget RDF-data via HTTP-innehållsförhandling&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;extrahera nyckeluppgifter&lt;/strong&gt;: tolkar RDF-data och plockar ut det föredragna namnet, födelsedatum och dödsdatum&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;generera TEI-uppmärkning&lt;/strong&gt;: skapar två centrala XML-utdrag:
&lt;ul&gt;
&lt;li&gt;en &lt;strong&gt;post för auktoritetsfilen&lt;/strong&gt; (ett &lt;code&gt;&amp;lt;person&amp;gt;&lt;/code&gt;-element med genererat &lt;code&gt;xml:id&lt;/code&gt;, &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; och &lt;code&gt;&amp;lt;idno type=&amp;quot;VIAF&amp;quot;&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;en separat &lt;strong&gt;annotationstagg&lt;/strong&gt; (&lt;code&gt;&amp;lt;persName&amp;gt;&lt;/code&gt; med ett &lt;code&gt;ref&lt;/code&gt;-attribut som pekar på auktoritetsposten)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Den dubbla utmatningen låter utgivaren underhålla en central auktoritetsfil och samtidigt enkelt infoga annotationstaggar i sina TEI-texter.&lt;/p&gt;
&lt;h2 id="huvudfunktioner"&gt;Huvudfunktioner&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Standardiserad ID-generering&lt;/strong&gt;: skapar konsekventa XML-ID:n i formatet &lt;code&gt;pers-[familyname]-[givenname initial]&lt;/code&gt; (t.ex. &lt;code&gt;pers-deteligny-c&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RDF-tolkning&lt;/strong&gt;: använder &lt;code&gt;rdflib&lt;/code&gt; för att hämta uppgifter ur olika RDF-egenskaper (t.ex. &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;Kommandoradsgränssnitt&lt;/strong&gt;: körs enkelt med ett VIAF-nummer som enda obligatoriska argument&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Utförlig utmatning&lt;/strong&gt;: ger detaljerad information om bearbetningen vid sidan av den färdiga XML-koden&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="exempel"&gt;Exempel&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;Kommandot ger:&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="användning-inom-digital-humaniora"&gt;Användning inom digital humaniora&lt;/h2&gt;
&lt;p&gt;persNamer är särskilt värdefullt för:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;digitala vetenskapliga utgåvor som kräver auktoritetskontroll&lt;/li&gt;
&lt;li&gt;TEI-kodningsprojekt som arbetar med historiska personer&lt;/li&gt;
&lt;li&gt;initiativ kring länkade data som kopplar dokument till auktoritetsposter&lt;/li&gt;
&lt;li&gt;att säkra konsekvens i stora TEI-korpusar&lt;/li&gt;
&lt;li&gt;undervisning i auktoritetskontroll på kurser i digital humaniora&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="implementering"&gt;Implementering&lt;/h2&gt;
&lt;p&gt;persNamer är skrivet i Python och bygger på:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;requests&lt;/code&gt; för HTTP-anrop&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rdflib&lt;/code&gt; för RDF-tolkning&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lxml&lt;/code&gt; för XML-hantering&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Källkod och dokumentation finns i
.&lt;/p&gt;</description></item><item><title>ITA2-telegrafemulator</title><link>https://clementgodbarge.com/sv/code/baudot-emulator/</link><pubDate>Thu, 13 Feb 2025 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/sv/code/baudot-emulator/</guid><description>&lt;p&gt;Den här ITA2-emulatorn är ett handfast hjälpmedel i undervisningen: den gör abstrakta kodningsbegrepp synliga och interaktiva. När studenterna skriver in text och genast ser den förvandlas till hålmönster lär de sig flera av datorteknikens och telekommunikationens nyckelbegrepp.&lt;/p&gt;
&lt;h2 id="pedagogisk-nytta"&gt;Pedagogisk nytta&lt;/h2&gt;
&lt;p&gt;För det första åskådliggör den binär representation – hur text blir mönster av ettor och nollor. Det brukar vi lära ut abstrakt, men när hålen faktiskt dyker upp blir det lättare att begripa hur fysiska system kan bära digital information.&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;Skiftmekanismen mellan BOKSTÄVER och SIFFROR (LETTERS/FIGURES) är en naturlig ingång till tillståndsmaskiner. Genom att pröva sig fram upptäcker studenterna att samma mönster kan stå för olika tecken beroende på vilket läge apparaten befinner sig i. Den praktiska erfarenheten av tillståndsberoende kodning förbereder dem för mer avancerade datavetenskapliga begrepp.&lt;/p&gt;
&lt;h2 id="teknisk-utformning"&gt;Teknisk utformning&lt;/h2&gt;
&lt;p&gt;Emulatorn är skriven i JavaScript och HTML/CSS och kan därför enkelt bäddas in på vilken webbsida som helst. Koden är modulär och kan anpassas till olika undervisningssammanhang.&lt;/p&gt;
&lt;p&gt;Källkoden finns i
, där du också kan pröva emulatorn själv.&lt;/p&gt;</description></item></channel></rss>